]>
Commit | Line | Data |
---|---|---|
1a4d82fc JJ |
1 | // Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT |
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 | ||
11 | pub use self::ArgKind::*; | |
12 | ||
13 | use llvm::Attribute; | |
14 | use std::option; | |
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; | |
20 | use trans::cabi_aarch64; | |
85aaf69f | 21 | use trans::cabi_powerpc; |
9cc50fc6 | 22 | use trans::cabi_powerpc64; |
1a4d82fc | 23 | use trans::cabi_mips; |
7453a54e | 24 | use trans::cabi_asmjs; |
1a4d82fc JJ |
25 | use trans::type_::Type; |
26 | ||
27 | #[derive(Clone, Copy, PartialEq)] | |
28 | pub enum ArgKind { | |
29 | /// Pass the argument directly using the normal converted | |
30 | /// LLVM type or by coercing to another specified type | |
31 | Direct, | |
32 | /// Pass the argument indirectly via a hidden pointer | |
33 | Indirect, | |
34 | /// Ignore the argument (useful for empty struct) | |
35 | Ignore, | |
36 | } | |
37 | ||
38 | /// Information about how a specific C type | |
39 | /// should be passed to or returned from a function | |
40 | /// | |
41 | /// This is borrowed from clang's ABIInfo.h | |
42 | #[derive(Clone, Copy)] | |
43 | pub struct ArgType { | |
44 | pub kind: ArgKind, | |
45 | /// Original LLVM type | |
46 | pub ty: Type, | |
47 | /// Coerced LLVM Type | |
48 | pub cast: option::Option<Type>, | |
49 | /// Dummy argument, which is emitted before the real argument | |
50 | pub pad: option::Option<Type>, | |
51 | /// LLVM attribute of argument | |
52 | pub attr: option::Option<Attribute> | |
53 | } | |
54 | ||
55 | impl ArgType { | |
56 | pub fn direct(ty: Type, cast: option::Option<Type>, | |
57 | pad: option::Option<Type>, | |
58 | attr: option::Option<Attribute>) -> ArgType { | |
59 | ArgType { | |
60 | kind: Direct, | |
61 | ty: ty, | |
62 | cast: cast, | |
63 | pad: pad, | |
64 | attr: attr | |
65 | } | |
66 | } | |
67 | ||
68 | pub fn indirect(ty: Type, attr: option::Option<Attribute>) -> ArgType { | |
69 | ArgType { | |
70 | kind: Indirect, | |
71 | ty: ty, | |
72 | cast: option::Option::None, | |
73 | pad: option::Option::None, | |
74 | attr: attr | |
75 | } | |
76 | } | |
77 | ||
78 | pub fn ignore(ty: Type) -> ArgType { | |
79 | ArgType { | |
80 | kind: Ignore, | |
81 | ty: ty, | |
82 | cast: None, | |
83 | pad: None, | |
84 | attr: None, | |
85 | } | |
86 | } | |
87 | ||
88 | pub fn is_indirect(&self) -> bool { | |
89 | return self.kind == Indirect; | |
90 | } | |
91 | ||
92 | pub fn is_ignore(&self) -> bool { | |
93 | return self.kind == Ignore; | |
94 | } | |
95 | } | |
96 | ||
97 | /// Metadata describing how the arguments to a native function | |
98 | /// should be passed in order to respect the native ABI. | |
99 | /// | |
100 | /// I will do my best to describe this structure, but these | |
101 | /// comments are reverse-engineered and may be inaccurate. -NDM | |
102 | pub struct FnType { | |
103 | /// The LLVM types of each argument. | |
104 | pub arg_tys: Vec<ArgType> , | |
105 | ||
106 | /// LLVM return type. | |
107 | pub ret_ty: ArgType, | |
108 | } | |
109 | ||
110 | pub fn compute_abi_info(ccx: &CrateContext, | |
111 | atys: &[Type], | |
112 | rty: Type, | |
113 | ret_def: bool) -> FnType { | |
c34b1796 | 114 | match &ccx.sess().target.target.arch[..] { |
1a4d82fc JJ |
115 | "x86" => cabi_x86::compute_abi_info(ccx, atys, rty, ret_def), |
116 | "x86_64" => if ccx.sess().target.target.options.is_like_windows { | |
117 | cabi_x86_win64::compute_abi_info(ccx, atys, rty, ret_def) | |
118 | } else { | |
119 | cabi_x86_64::compute_abi_info(ccx, atys, rty, ret_def) | |
120 | }, | |
1a4d82fc | 121 | "aarch64" => cabi_aarch64::compute_abi_info(ccx, atys, rty, ret_def), |
85aaf69f SL |
122 | "arm" => { |
123 | let flavor = if ccx.sess().target.target.target_os == "ios" { | |
124 | cabi_arm::Flavor::Ios | |
125 | } else { | |
126 | cabi_arm::Flavor::General | |
127 | }; | |
128 | cabi_arm::compute_abi_info(ccx, atys, rty, ret_def, flavor) | |
129 | }, | |
1a4d82fc | 130 | "mips" => cabi_mips::compute_abi_info(ccx, atys, rty, ret_def), |
85aaf69f | 131 | "powerpc" => cabi_powerpc::compute_abi_info(ccx, atys, rty, ret_def), |
7453a54e SL |
132 | "powerpc64" => cabi_powerpc64::compute_abi_info(ccx, atys, rty, ret_def), |
133 | "asmjs" => cabi_asmjs::compute_abi_info(ccx, atys, rty, ret_def), | |
1a4d82fc | 134 | a => ccx.sess().fatal(&format!("unrecognized arch \"{}\" in target specification", a) |
c34b1796 | 135 | ), |
1a4d82fc JJ |
136 | } |
137 | } |