]> git.lizzy.rs Git - rust.git/blob - src/librustc_target/abi/call/mod.rs
489bb37fc26ff9ac8393a41262261a51c621cb9d
[rust.git] / src / librustc_target / abi / call / mod.rs
1 // Copyright 2017 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 use abi::{self, Abi, Align, FieldPlacement, Size};
12 use abi::{HasDataLayout, LayoutOf, TyLayout, TyLayoutMethods};
13 use spec::HasTargetSpec;
14
15 mod aarch64;
16 mod amdgpu;
17 mod arm;
18 mod asmjs;
19 mod hexagon;
20 mod mips;
21 mod mips64;
22 mod msp430;
23 mod nvptx;
24 mod nvptx64;
25 mod powerpc;
26 mod powerpc64;
27 mod riscv;
28 mod s390x;
29 mod sparc;
30 mod sparc64;
31 mod x86;
32 mod x86_64;
33 mod x86_win64;
34 mod wasm32;
35
36 #[derive(Clone, Copy, PartialEq, Eq, Debug)]
37 pub enum PassMode {
38     /// Ignore the argument (useful for empty struct).
39     Ignore,
40     /// Pass the argument directly.
41     Direct(ArgAttributes),
42     /// Pass a pair's elements directly in two arguments.
43     Pair(ArgAttributes, ArgAttributes),
44     /// Pass the argument after casting it, to either
45     /// a single uniform or a pair of registers.
46     Cast(CastTarget),
47     /// Pass the argument indirectly via a hidden pointer.
48     /// The second value, if any, is for the extra data (vtable or length)
49     /// which indicates that it refers to an unsized rvalue.
50     Indirect(ArgAttributes, Option<ArgAttributes>),
51 }
52
53 // Hack to disable non_upper_case_globals only for the bitflags! and not for the rest
54 // of this module
55 pub use self::attr_impl::ArgAttribute;
56
57 #[allow(non_upper_case_globals)]
58 #[allow(unused)]
59 mod attr_impl {
60     // The subset of llvm::Attribute needed for arguments, packed into a bitfield.
61     bitflags! {
62         #[derive(Default)]
63         pub struct ArgAttribute: u16 {
64             const ByVal     = 1 << 0;
65             const NoAlias   = 1 << 1;
66             const NoCapture = 1 << 2;
67             const NonNull   = 1 << 3;
68             const ReadOnly  = 1 << 4;
69             const SExt      = 1 << 5;
70             const StructRet = 1 << 6;
71             const ZExt      = 1 << 7;
72             const InReg     = 1 << 8;
73         }
74     }
75 }
76
77 /// A compact representation of LLVM attributes (at least those relevant for this module)
78 /// that can be manipulated without interacting with LLVM's Attribute machinery.
79 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
80 pub struct ArgAttributes {
81     pub regular: ArgAttribute,
82     pub pointee_size: Size,
83     pub pointee_align: Option<Align>
84 }
85
86 impl ArgAttributes {
87     pub fn new() -> Self {
88         ArgAttributes {
89             regular: ArgAttribute::default(),
90             pointee_size: Size::ZERO,
91             pointee_align: None,
92         }
93     }
94
95     pub fn set(&mut self, attr: ArgAttribute) -> &mut Self {
96         self.regular |= attr;
97         self
98     }
99
100     pub fn contains(&self, attr: ArgAttribute) -> bool {
101         self.regular.contains(attr)
102     }
103 }
104
105 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
106 pub enum RegKind {
107     Integer,
108     Float,
109     Vector
110 }
111
112 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
113 pub struct Reg {
114     pub kind: RegKind,
115     pub size: Size,
116 }
117
118 macro_rules! reg_ctor {
119     ($name:ident, $kind:ident, $bits:expr) => {
120         pub fn $name() -> Reg {
121             Reg {
122                 kind: RegKind::$kind,
123                 size: Size::from_bits($bits)
124             }
125         }
126     }
127 }
128
129 impl Reg {
130     reg_ctor!(i8, Integer, 8);
131     reg_ctor!(i16, Integer, 16);
132     reg_ctor!(i32, Integer, 32);
133     reg_ctor!(i64, Integer, 64);
134
135     reg_ctor!(f32, Float, 32);
136     reg_ctor!(f64, Float, 64);
137 }
138
139 impl Reg {
140     pub fn align<C: HasDataLayout>(&self, cx: &C) -> Align {
141         let dl = cx.data_layout();
142         match self.kind {
143             RegKind::Integer => {
144                 match self.size.bits() {
145                     1 => dl.i1_align.abi,
146                     2..=8 => dl.i8_align.abi,
147                     9..=16 => dl.i16_align.abi,
148                     17..=32 => dl.i32_align.abi,
149                     33..=64 => dl.i64_align.abi,
150                     65..=128 => dl.i128_align.abi,
151                     _ => panic!("unsupported integer: {:?}", self)
152                 }
153             }
154             RegKind::Float => {
155                 match self.size.bits() {
156                     32 => dl.f32_align.abi,
157                     64 => dl.f64_align.abi,
158                     _ => panic!("unsupported float: {:?}", self)
159                 }
160             }
161             RegKind::Vector => dl.vector_align(self.size).abi,
162         }
163     }
164 }
165
166 /// An argument passed entirely registers with the
167 /// same kind (e.g. HFA / HVA on PPC64 and AArch64).
168 #[derive(Clone, Copy, PartialEq, Eq, Debug)]
169 pub struct Uniform {
170     pub unit: Reg,
171
172     /// The total size of the argument, which can be:
173     /// * equal to `unit.size` (one scalar/vector)
174     /// * a multiple of `unit.size` (an array of scalar/vectors)
175     /// * if `unit.kind` is `Integer`, the last element
176     ///   can be shorter, i.e. `{ i64, i64, i32 }` for
177     ///   64-bit integers with a total size of 20 bytes
178     pub total: Size,
179 }
180
181 impl From<Reg> for Uniform {
182     fn from(unit: Reg) -> Uniform {
183         Uniform {
184             unit,
185             total: unit.size
186         }
187     }
188 }
189
190 impl Uniform {
191     pub fn align<C: HasDataLayout>(&self, cx: &C) -> Align {
192         self.unit.align(cx)
193     }
194 }
195
196 #[derive(Clone, Copy, PartialEq, Eq, Debug)]
197 pub struct CastTarget {
198     pub prefix: [Option<RegKind>; 8],
199     pub prefix_chunk: Size,
200     pub rest: Uniform,
201 }
202
203 impl From<Reg> for CastTarget {
204     fn from(unit: Reg) -> CastTarget {
205         CastTarget::from(Uniform::from(unit))
206     }
207 }
208
209 impl From<Uniform> for CastTarget {
210     fn from(uniform: Uniform) -> CastTarget {
211         CastTarget {
212             prefix: [None; 8],
213             prefix_chunk: Size::ZERO,
214             rest: uniform
215         }
216     }
217 }
218
219 impl CastTarget {
220     pub fn pair(a: Reg, b: Reg) -> CastTarget {
221         CastTarget {
222             prefix: [Some(a.kind), None, None, None, None, None, None, None],
223             prefix_chunk: a.size,
224             rest: Uniform::from(b)
225         }
226     }
227
228     pub fn size<C: HasDataLayout>(&self, cx: &C) -> Size {
229         (self.prefix_chunk * self.prefix.iter().filter(|x| x.is_some()).count() as u64)
230              .align_to(self.rest.align(cx)) + self.rest.total
231     }
232
233     pub fn align<C: HasDataLayout>(&self, cx: &C) -> Align {
234         self.prefix.iter()
235             .filter_map(|x| x.map(|kind| Reg { kind, size: self.prefix_chunk }.align(cx)))
236             .fold(cx.data_layout().aggregate_align.abi.max(self.rest.align(cx)),
237                 |acc, align| acc.max(align))
238     }
239 }
240
241 impl<'a, Ty> TyLayout<'a, Ty> {
242     fn is_aggregate(&self) -> bool {
243         match self.abi {
244             Abi::Uninhabited |
245             Abi::Scalar(_) |
246             Abi::Vector { .. } => false,
247             Abi::ScalarPair(..) |
248             Abi::Aggregate { .. } => true
249         }
250     }
251
252     fn homogeneous_aggregate<C>(&self, cx: &C) -> Option<Reg>
253         where Ty: TyLayoutMethods<'a, C> + Copy, C: LayoutOf<Ty = Ty, TyLayout = Self>
254     {
255         match self.abi {
256             Abi::Uninhabited => None,
257
258             // The primitive for this algorithm.
259             Abi::Scalar(ref scalar) => {
260                 let kind = match scalar.value {
261                     abi::Int(..) |
262                     abi::Pointer => RegKind::Integer,
263                     abi::Float(_) => RegKind::Float,
264                 };
265                 Some(Reg {
266                     kind,
267                     size: self.size
268                 })
269             }
270
271             Abi::Vector { .. } => {
272                 Some(Reg {
273                     kind: RegKind::Vector,
274                     size: self.size
275                 })
276             }
277
278             Abi::ScalarPair(..) |
279             Abi::Aggregate { .. } => {
280                 let mut total = Size::ZERO;
281                 let mut result = None;
282
283                 let is_union = match self.fields {
284                     FieldPlacement::Array { count, .. } => {
285                         if count > 0 {
286                             return self.field(cx, 0).homogeneous_aggregate(cx);
287                         } else {
288                             return None;
289                         }
290                     }
291                     FieldPlacement::Union(_) => true,
292                     FieldPlacement::Arbitrary { .. } => false
293                 };
294
295                 for i in 0..self.fields.count() {
296                     if !is_union && total != self.fields.offset(i) {
297                         return None;
298                     }
299
300                     let field = self.field(cx, i);
301                     match (result, field.homogeneous_aggregate(cx)) {
302                         // The field itself must be a homogeneous aggregate.
303                         (_, None) => return None,
304                         // If this is the first field, record the unit.
305                         (None, Some(unit)) => {
306                             result = Some(unit);
307                         }
308                         // For all following fields, the unit must be the same.
309                         (Some(prev_unit), Some(unit)) => {
310                             if prev_unit != unit {
311                                 return None;
312                             }
313                         }
314                     }
315
316                     // Keep track of the offset (without padding).
317                     let size = field.size;
318                     if is_union {
319                         total = total.max(size);
320                     } else {
321                         total += size;
322                     }
323                 }
324
325                 // There needs to be no padding.
326                 if total != self.size {
327                     None
328                 } else {
329                     result
330                 }
331             }
332         }
333     }
334 }
335
336 /// Information about how to pass an argument to,
337 /// or return a value from, a function, under some ABI.
338 #[derive(Debug)]
339 pub struct ArgType<'a, Ty> {
340     pub layout: TyLayout<'a, Ty>,
341
342     /// Dummy argument, which is emitted before the real argument.
343     pub pad: Option<Reg>,
344
345     pub mode: PassMode,
346 }
347
348 impl<'a, Ty> ArgType<'a, Ty> {
349     pub fn new(layout: TyLayout<'a, Ty>) -> Self {
350         ArgType {
351             layout,
352             pad: None,
353             mode: PassMode::Direct(ArgAttributes::new()),
354         }
355     }
356
357     pub fn make_indirect(&mut self) {
358         assert_eq!(self.mode, PassMode::Direct(ArgAttributes::new()));
359
360         // Start with fresh attributes for the pointer.
361         let mut attrs = ArgAttributes::new();
362
363         // For non-immediate arguments the callee gets its own copy of
364         // the value on the stack, so there are no aliases. It's also
365         // program-invisible so can't possibly capture
366         attrs.set(ArgAttribute::NoAlias)
367              .set(ArgAttribute::NoCapture)
368              .set(ArgAttribute::NonNull);
369         attrs.pointee_size = self.layout.size;
370         // FIXME(eddyb) We should be doing this, but at least on
371         // i686-pc-windows-msvc, it results in wrong stack offsets.
372         // attrs.pointee_align = Some(self.layout.align.abi);
373
374         let extra_attrs = if self.layout.is_unsized() {
375             Some(ArgAttributes::new())
376         } else {
377             None
378         };
379
380         self.mode = PassMode::Indirect(attrs, extra_attrs);
381     }
382
383     pub fn make_indirect_byval(&mut self) {
384         self.make_indirect();
385         match self.mode {
386             PassMode::Indirect(ref mut attrs, _) => {
387                 attrs.set(ArgAttribute::ByVal);
388             }
389             _ => unreachable!()
390         }
391     }
392
393     pub fn extend_integer_width_to(&mut self, bits: u64) {
394         // Only integers have signedness
395         if let Abi::Scalar(ref scalar) = self.layout.abi {
396             if let abi::Int(i, signed) = scalar.value {
397                 if i.size().bits() < bits {
398                     if let PassMode::Direct(ref mut attrs) = self.mode {
399                         attrs.set(if signed {
400                             ArgAttribute::SExt
401                         } else {
402                             ArgAttribute::ZExt
403                         });
404                     }
405                 }
406             }
407         }
408     }
409
410     pub fn cast_to<T: Into<CastTarget>>(&mut self, target: T) {
411         assert_eq!(self.mode, PassMode::Direct(ArgAttributes::new()));
412         self.mode = PassMode::Cast(target.into());
413     }
414
415     pub fn pad_with(&mut self, reg: Reg) {
416         self.pad = Some(reg);
417     }
418
419     pub fn is_indirect(&self) -> bool {
420         match self.mode {
421             PassMode::Indirect(..) => true,
422             _ => false
423         }
424     }
425
426     pub fn is_sized_indirect(&self) -> bool {
427         match self.mode {
428             PassMode::Indirect(_, None) => true,
429             _ => false
430         }
431     }
432
433     pub fn is_unsized_indirect(&self) -> bool {
434         match self.mode {
435             PassMode::Indirect(_, Some(_)) => true,
436             _ => false
437         }
438     }
439
440     pub fn is_ignore(&self) -> bool {
441         self.mode == PassMode::Ignore
442     }
443 }
444
445 #[derive(Copy, Clone, PartialEq, Debug)]
446 pub enum Conv {
447     C,
448
449     ArmAapcs,
450
451     Msp430Intr,
452
453     PtxKernel,
454
455     X86Fastcall,
456     X86Intr,
457     X86Stdcall,
458     X86ThisCall,
459     X86VectorCall,
460
461     X86_64SysV,
462     X86_64Win64,
463
464     AmdGpuKernel,
465 }
466
467 /// Metadata describing how the arguments to a native function
468 /// should be passed in order to respect the native ABI.
469 ///
470 /// I will do my best to describe this structure, but these
471 /// comments are reverse-engineered and may be inaccurate. -NDM
472 #[derive(Debug)]
473 pub struct FnType<'a, Ty> {
474     /// The LLVM types of each argument.
475     pub args: Vec<ArgType<'a, Ty>>,
476
477     /// LLVM return type.
478     pub ret: ArgType<'a, Ty>,
479
480     pub variadic: bool,
481
482     pub conv: Conv,
483 }
484
485 impl<'a, Ty> FnType<'a, Ty> {
486     pub fn adjust_for_cabi<C>(&mut self, cx: &C, abi: ::spec::abi::Abi) -> Result<(), String>
487         where Ty: TyLayoutMethods<'a, C> + Copy,
488               C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout + HasTargetSpec
489     {
490         match &cx.target_spec().arch[..] {
491             "x86" => {
492                 let flavor = if abi == ::spec::abi::Abi::Fastcall {
493                     x86::Flavor::Fastcall
494                 } else {
495                     x86::Flavor::General
496                 };
497                 x86::compute_abi_info(cx, self, flavor);
498             },
499             "x86_64" => if abi == ::spec::abi::Abi::SysV64 {
500                 x86_64::compute_abi_info(cx, self);
501             } else if abi == ::spec::abi::Abi::Win64 || cx.target_spec().options.is_like_windows {
502                 x86_win64::compute_abi_info(self);
503             } else {
504                 x86_64::compute_abi_info(cx, self);
505             },
506             "aarch64" => aarch64::compute_abi_info(cx, self),
507             "amdgpu" => amdgpu::compute_abi_info(cx, self),
508             "arm" => arm::compute_abi_info(cx, self),
509             "mips" => mips::compute_abi_info(cx, self),
510             "mips64" => mips64::compute_abi_info(cx, self),
511             "powerpc" => powerpc::compute_abi_info(cx, self),
512             "powerpc64" => powerpc64::compute_abi_info(cx, self),
513             "s390x" => s390x::compute_abi_info(cx, self),
514             "asmjs" => asmjs::compute_abi_info(cx, self),
515             "wasm32" => {
516                 if cx.target_spec().llvm_target.contains("emscripten") {
517                     asmjs::compute_abi_info(cx, self)
518                 } else {
519                     wasm32::compute_abi_info(self)
520                 }
521             }
522             "msp430" => msp430::compute_abi_info(self),
523             "sparc" => sparc::compute_abi_info(cx, self),
524             "sparc64" => sparc64::compute_abi_info(cx, self),
525             "nvptx" => nvptx::compute_abi_info(self),
526             "nvptx64" => nvptx64::compute_abi_info(self),
527             "hexagon" => hexagon::compute_abi_info(self),
528             "riscv32" => riscv::compute_abi_info(self, 32),
529             "riscv64" => riscv::compute_abi_info(self, 64),
530             a => return Err(format!("unrecognized arch \"{}\" in target specification", a))
531         }
532
533         if let PassMode::Indirect(ref mut attrs, _) = self.ret.mode {
534             attrs.set(ArgAttribute::StructRet);
535         }
536
537         Ok(())
538     }
539 }