Akos Kiss | 6e5fb8b | 2014-12-12 23:39:27 | [diff] [blame] | 1 | // Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT |
Tim Chevalier | 41adf9d | 2013-01-25 22:56:56 | [diff] [blame] | 2 | // file at the top-level directory of this distribution and at |
| 3 | // http://rust-lang.org/COPYRIGHT. |
| 4 | // |
| 5 | // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or |
| 6 | // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license |
| 7 | // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your |
| 8 | // option. This file may not be copied, modified, or distributed |
| 9 | // except according to those terms. |
| 10 | |
Steven Fackler | 3dcd215 | 2014-11-06 08:05:53 | [diff] [blame] | 11 | pub use self::ArgKind::*; |
| 12 | |
Brian Anderson | 3096d9b | 2014-07-08 00:58:01 | [diff] [blame] | 13 | use llvm::Attribute; |
Corey Richardson | 1662bd3 | 2013-06-28 22:32:26 | [diff] [blame] | 14 | use std::option; |
Niko Matsakis | dc6e414 | 2014-11-16 01:30:33 | [diff] [blame] | 15 | use trans::context::CrateContext; |
| 16 | use trans::cabi_x86; |
| 17 | use trans::cabi_x86_64; |
| 18 | use trans::cabi_x86_win64; |
| 19 | use trans::cabi_arm; |
Akos Kiss | 6e5fb8b | 2014-12-12 23:39:27 | [diff] [blame] | 20 | use trans::cabi_aarch64; |
Niko Matsakis | dc6e414 | 2014-11-16 01:30:33 | [diff] [blame] | 21 | use trans::cabi_mips; |
| 22 | use trans::type_::Type; |
Tim Chevalier | 41adf9d | 2013-01-25 22:56:56 | [diff] [blame] | 23 | |
Jorge Aparicio | 351409a | 2015-01-04 03:54:18 | [diff] [blame] | 24 | #[derive(Clone, Copy, PartialEq)] |
Jyun-Yan You | 95fc31a | 2013-09-25 10:30:44 | [diff] [blame] | 25 | pub enum ArgKind { |
| 26 | /// Pass the argument directly using the normal converted |
| 27 | /// LLVM type or by coercing to another specified type |
| 28 | Direct, |
| 29 | /// Pass the argument indirectly via a hidden pointer |
klutzy | 2d31bca | 2014-03-09 06:42:22 | [diff] [blame] | 30 | Indirect, |
| 31 | /// Ignore the argument (useful for empty struct) |
| 32 | Ignore, |
Jyun-Yan You | 95fc31a | 2013-09-25 10:30:44 | [diff] [blame] | 33 | } |
| 34 | |
| 35 | /// Information about how a specific C type |
| 36 | /// should be passed to or returned from a function |
| 37 | /// |
| 38 | /// This is borrowed from clang's ABIInfo.h |
Jorge Aparicio | 351409a | 2015-01-04 03:54:18 | [diff] [blame] | 39 | #[derive(Clone, Copy)] |
Jyun-Yan You | 95fc31a | 2013-09-25 10:30:44 | [diff] [blame] | 40 | pub struct ArgType { |
Alex Crichton | 89fa141 | 2014-03-28 17:05:27 | [diff] [blame] | 41 | pub kind: ArgKind, |
Jyun-Yan You | 95fc31a | 2013-09-25 10:30:44 | [diff] [blame] | 42 | /// Original LLVM type |
Alex Crichton | 89fa141 | 2014-03-28 17:05:27 | [diff] [blame] | 43 | pub ty: Type, |
Jyun-Yan You | 95fc31a | 2013-09-25 10:30:44 | [diff] [blame] | 44 | /// Coerced LLVM Type |
Alex Crichton | 89fa141 | 2014-03-28 17:05:27 | [diff] [blame] | 45 | pub cast: option::Option<Type>, |
Jyun-Yan You | 95fc31a | 2013-09-25 10:30:44 | [diff] [blame] | 46 | /// Dummy argument, which is emitted before the real argument |
Alex Crichton | 89fa141 | 2014-03-28 17:05:27 | [diff] [blame] | 47 | pub pad: option::Option<Type>, |
Jyun-Yan You | 95fc31a | 2013-09-25 10:30:44 | [diff] [blame] | 48 | /// LLVM attribute of argument |
Alex Crichton | 89fa141 | 2014-03-28 17:05:27 | [diff] [blame] | 49 | pub attr: option::Option<Attribute> |
Jyun-Yan You | 95fc31a | 2013-09-25 10:30:44 | [diff] [blame] | 50 | } |
| 51 | |
| 52 | impl ArgType { |
| 53 | pub fn direct(ty: Type, cast: option::Option<Type>, |
| 54 | pad: option::Option<Type>, |
| 55 | attr: option::Option<Attribute>) -> ArgType { |
| 56 | ArgType { |
| 57 | kind: Direct, |
| 58 | ty: ty, |
| 59 | cast: cast, |
| 60 | pad: pad, |
| 61 | attr: attr |
| 62 | } |
| 63 | } |
| 64 | |
| 65 | pub fn indirect(ty: Type, attr: option::Option<Attribute>) -> ArgType { |
| 66 | ArgType { |
| 67 | kind: Indirect, |
| 68 | ty: ty, |
Corey Farwell | 4ef1674 | 2014-11-28 16:57:41 | [diff] [blame] | 69 | cast: option::Option::None, |
| 70 | pad: option::Option::None, |
Jyun-Yan You | 95fc31a | 2013-09-25 10:30:44 | [diff] [blame] | 71 | attr: attr |
| 72 | } |
| 73 | } |
| 74 | |
klutzy | 2d31bca | 2014-03-09 06:42:22 | [diff] [blame] | 75 | pub fn ignore(ty: Type) -> ArgType { |
| 76 | ArgType { |
| 77 | kind: Ignore, |
| 78 | ty: ty, |
| 79 | cast: None, |
| 80 | pad: None, |
| 81 | attr: None, |
| 82 | } |
| 83 | } |
| 84 | |
Jyun-Yan You | 95fc31a | 2013-09-25 10:30:44 | [diff] [blame] | 85 | pub fn is_indirect(&self) -> bool { |
| 86 | return self.kind == Indirect; |
| 87 | } |
klutzy | 2d31bca | 2014-03-09 06:42:22 | [diff] [blame] | 88 | |
| 89 | pub fn is_ignore(&self) -> bool { |
| 90 | return self.kind == Ignore; |
| 91 | } |
Tim Chevalier | 41adf9d | 2013-01-25 22:56:56 | [diff] [blame] | 92 | } |
| 93 | |
Niko Matsakis | 303f650 | 2013-05-21 19:25:44 | [diff] [blame] | 94 | /// Metadata describing how the arguments to a native function |
| 95 | /// should be passed in order to respect the native ABI. |
| 96 | /// |
| 97 | /// I will do my best to describe this structure, but these |
| 98 | /// comments are reverse-engineered and may be inaccurate. -NDM |
Patrick Walton | ba11e96 | 2013-01-30 19:46:19 | [diff] [blame] | 99 | pub struct FnType { |
Jyun-Yan You | 95fc31a | 2013-09-25 10:30:44 | [diff] [blame] | 100 | /// The LLVM types of each argument. |
Alex Crichton | 89fa141 | 2014-03-28 17:05:27 | [diff] [blame] | 101 | pub arg_tys: Vec<ArgType> , |
Niko Matsakis | 303f650 | 2013-05-21 19:25:44 | [diff] [blame] | 102 | |
| 103 | /// LLVM return type. |
Alex Crichton | 89fa141 | 2014-03-28 17:05:27 | [diff] [blame] | 104 | pub ret_ty: ArgType, |
Tim Chevalier | 41adf9d | 2013-01-25 22:56:56 | [diff] [blame] | 105 | } |
| 106 | |
Patrick Walton | b941677 | 2013-12-20 00:47:15 | [diff] [blame] | 107 | pub fn compute_abi_info(ccx: &CrateContext, |
Niko Matsakis | 303f650 | 2013-05-21 19:25:44 | [diff] [blame] | 108 | atys: &[Type], |
| 109 | rty: Type, |
| 110 | ret_def: bool) -> FnType { |
Jorge Aparicio | 517f1cc | 2015-01-07 16:58:31 | [diff] [blame^] | 111 | match &ccx.sess().target.target.arch[] { |
Corey Richardson | 6b130e3 | 2014-07-23 18:56:36 | [diff] [blame] | 112 | "x86" => cabi_x86::compute_abi_info(ccx, atys, rty, ret_def), |
| 113 | "x86_64" => if ccx.sess().target.target.options.is_like_windows { |
| 114 | cabi_x86_win64::compute_abi_info(ccx, atys, rty, ret_def) |
| 115 | } else { |
| 116 | cabi_x86_64::compute_abi_info(ccx, atys, rty, ret_def) |
| 117 | }, |
| 118 | "arm" => cabi_arm::compute_abi_info(ccx, atys, rty, ret_def), |
Akos Kiss | 6e5fb8b | 2014-12-12 23:39:27 | [diff] [blame] | 119 | "aarch64" => cabi_aarch64::compute_abi_info(ccx, atys, rty, ret_def), |
Corey Richardson | 6b130e3 | 2014-07-23 18:56:36 | [diff] [blame] | 120 | "mips" => cabi_mips::compute_abi_info(ccx, atys, rty, ret_def), |
Jorge Aparicio | 517f1cc | 2015-01-07 16:58:31 | [diff] [blame^] | 121 | a => ccx.sess().fatal(&format!("unrecognized arch \"{}\" in target specification", a) |
| 122 | []), |
Tim Chevalier | 41adf9d | 2013-01-25 22:56:56 | [diff] [blame] | 123 | } |
| 124 | } |