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.
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.
11 use abi
::{self, Abi, Align, FieldPlacement, Size}
;
12 use abi
::{HasDataLayout, LayoutOf, TyLayout, TyLayoutMethods}
;
13 use spec
::HasTargetSpec
;
34 #[derive(Clone, Copy, PartialEq, Eq, Debug)]
36 /// Ignore the argument (useful for empty struct).
38 /// Pass the argument directly.
39 Direct(ArgAttributes
),
40 /// Pass a pair's elements directly in two arguments.
41 Pair(ArgAttributes
, ArgAttributes
),
42 /// Pass the argument after casting it, to either
43 /// a single uniform or a pair of registers.
45 /// Pass the argument indirectly via a hidden pointer.
46 Indirect(ArgAttributes
),
49 // Hack to disable non_upper_case_globals only for the bitflags! and not for the rest
51 pub use self::attr_impl
::ArgAttribute
;
53 #[allow(non_upper_case_globals)]
56 // The subset of llvm::Attribute needed for arguments, packed into a bitfield.
59 pub struct ArgAttribute
: u16 {
61 const NoAlias
= 1 << 1;
62 const NoCapture
= 1 << 2;
63 const NonNull
= 1 << 3;
64 const ReadOnly
= 1 << 4;
66 const StructRet
= 1 << 6;
73 /// A compact representation of LLVM attributes (at least those relevant for this module)
74 /// that can be manipulated without interacting with LLVM's Attribute machinery.
75 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
76 pub struct ArgAttributes
{
77 pub regular
: ArgAttribute
,
78 pub pointee_size
: Size
,
79 pub pointee_align
: Option
<Align
>
83 pub fn new() -> Self {
85 regular
: ArgAttribute
::default(),
86 pointee_size
: Size
::ZERO
,
91 pub fn set(&mut self, attr
: ArgAttribute
) -> &mut Self {
92 self.regular
= self.regular
| attr
;
96 pub fn contains(&self, attr
: ArgAttribute
) -> bool
{
97 self.regular
.contains(attr
)
101 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
108 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
114 macro_rules
! reg_ctor
{
115 ($name
:ident
, $kind
:ident
, $bits
:expr
) => {
116 pub fn $
name() -> Reg
{
118 kind
: RegKind
::$kind
,
119 size
: Size
::from_bits($bits
)
126 reg_ctor
!(i8, Integer
, 8);
127 reg_ctor
!(i16, Integer
, 16);
128 reg_ctor
!(i32, Integer
, 32);
129 reg_ctor
!(i64, Integer
, 64);
131 reg_ctor
!(f32, Float
, 32);
132 reg_ctor
!(f64, Float
, 64);
136 pub fn align
<C
: HasDataLayout
>(&self, cx
: C
) -> Align
{
137 let dl
= cx
.data_layout();
139 RegKind
::Integer
=> {
140 match self.size
.bits() {
142 2...8 => dl
.i8_align
,
143 9...16 => dl
.i16_align
,
144 17...32 => dl
.i32_align
,
145 33...64 => dl
.i64_align
,
146 65...128 => dl
.i128_align
,
147 _
=> panic
!("unsupported integer: {:?}", self)
151 match self.size
.bits() {
154 _
=> panic
!("unsupported float: {:?}", self)
157 RegKind
::Vector
=> dl
.vector_align(self.size
)
162 /// An argument passed entirely registers with the
163 /// same kind (e.g. HFA / HVA on PPC64 and AArch64).
164 #[derive(Clone, Copy, PartialEq, Eq, Debug)]
168 /// The total size of the argument, which can be:
169 /// * equal to `unit.size` (one scalar/vector)
170 /// * a multiple of `unit.size` (an array of scalar/vectors)
171 /// * if `unit.kind` is `Integer`, the last element
172 /// can be shorter, i.e. `{ i64, i64, i32 }` for
173 /// 64-bit integers with a total size of 20 bytes
177 impl From
<Reg
> for Uniform
{
178 fn from(unit
: Reg
) -> Uniform
{
187 pub fn align
<C
: HasDataLayout
>(&self, cx
: C
) -> Align
{
192 #[derive(Clone, Copy, PartialEq, Eq, Debug)]
193 pub struct CastTarget
{
194 pub prefix
: [Option
<RegKind
>; 8],
195 pub prefix_chunk
: Size
,
199 impl From
<Reg
> for CastTarget
{
200 fn from(unit
: Reg
) -> CastTarget
{
201 CastTarget
::from(Uniform
::from(unit
))
205 impl From
<Uniform
> for CastTarget
{
206 fn from(uniform
: Uniform
) -> CastTarget
{
209 prefix_chunk
: Size
::ZERO
,
216 pub fn pair(a
: Reg
, b
: Reg
) -> CastTarget
{
218 prefix
: [Some(a
.kind
), None
, None
, None
, None
, None
, None
, None
],
219 prefix_chunk
: a
.size
,
220 rest
: Uniform
::from(b
)
224 pub fn size
<C
: HasDataLayout
>(&self, cx
: C
) -> Size
{
225 (self.prefix_chunk
* self.prefix
.iter().filter(|x
| x
.is_some()).count() as u64)
226 .abi_align(self.rest
.align(cx
)) + self.rest
.total
229 pub fn align
<C
: HasDataLayout
>(&self, cx
: C
) -> Align
{
231 .filter_map(|x
| x
.map(|kind
| Reg { kind: kind, size: self.prefix_chunk }
.align(cx
)))
232 .fold(cx
.data_layout().aggregate_align
.max(self.rest
.align(cx
)),
233 |acc
, align
| acc
.max(align
))
237 impl<'a
, Ty
> TyLayout
<'a
, Ty
> {
238 fn is_aggregate(&self) -> bool
{
242 Abi
::Vector { .. }
=> false,
243 Abi
::ScalarPair(..) |
244 Abi
::Aggregate { .. }
=> true
248 fn homogeneous_aggregate
<C
>(&self, cx
: C
) -> Option
<Reg
>
249 where Ty
: TyLayoutMethods
<'a
, C
> + Copy
, C
: LayoutOf
<Ty
= Ty
, TyLayout
= Self> + Copy
252 Abi
::Uninhabited
=> None
,
254 // The primitive for this algorithm.
255 Abi
::Scalar(ref scalar
) => {
256 let kind
= match scalar
.value
{
258 abi
::Pointer
=> RegKind
::Integer
,
259 abi
::Float(_
) => RegKind
::Float
,
267 Abi
::Vector { .. }
=> {
269 kind
: RegKind
::Vector
,
274 Abi
::ScalarPair(..) |
275 Abi
::Aggregate { .. }
=> {
276 let mut total
= Size
::ZERO
;
277 let mut result
= None
;
279 let is_union
= match self.fields
{
280 FieldPlacement
::Array { count, .. }
=> {
282 return self.field(cx
, 0).homogeneous_aggregate(cx
);
287 FieldPlacement
::Union(_
) => true,
288 FieldPlacement
::Arbitrary { .. }
=> false
291 for i
in 0..self.fields
.count() {
292 if !is_union
&& total
!= self.fields
.offset(i
) {
296 let field
= self.field(cx
, i
);
297 match (result
, field
.homogeneous_aggregate(cx
)) {
298 // The field itself must be a homogeneous aggregate.
299 (_
, None
) => return None
,
300 // If this is the first field, record the unit.
301 (None
, Some(unit
)) => {
304 // For all following fields, the unit must be the same.
305 (Some(prev_unit
), Some(unit
)) => {
306 if prev_unit
!= unit
{
312 // Keep track of the offset (without padding).
313 let size
= field
.size
;
315 total
= total
.max(size
);
321 // There needs to be no padding.
322 if total
!= self.size
{
332 /// Information about how to pass an argument to,
333 /// or return a value from, a function, under some ABI.
335 pub struct ArgType
<'a
, Ty
> {
336 pub layout
: TyLayout
<'a
, Ty
>,
338 /// Dummy argument, which is emitted before the real argument.
339 pub pad
: Option
<Reg
>,
344 impl<'a
, Ty
> ArgType
<'a
, Ty
> {
345 pub fn new(layout
: TyLayout
<'a
, Ty
>) -> Self {
349 mode
: PassMode
::Direct(ArgAttributes
::new()),
353 pub fn make_indirect(&mut self) {
354 assert_eq
!(self.mode
, PassMode
::Direct(ArgAttributes
::new()));
356 // Start with fresh attributes for the pointer.
357 let mut attrs
= ArgAttributes
::new();
359 // For non-immediate arguments the callee gets its own copy of
360 // the value on the stack, so there are no aliases. It's also
361 // program-invisible so can't possibly capture
362 attrs
.set(ArgAttribute
::NoAlias
)
363 .set(ArgAttribute
::NoCapture
)
364 .set(ArgAttribute
::NonNull
);
365 attrs
.pointee_size
= self.layout
.size
;
366 // FIXME(eddyb) We should be doing this, but at least on
367 // i686-pc-windows-msvc, it results in wrong stack offsets.
368 // attrs.pointee_align = Some(self.layout.align);
370 self.mode
= PassMode
::Indirect(attrs
);
373 pub fn make_indirect_byval(&mut self) {
374 self.make_indirect();
376 PassMode
::Indirect(ref mut attrs
) => {
377 attrs
.set(ArgAttribute
::ByVal
);
383 pub fn extend_integer_width_to(&mut self, bits
: u64) {
384 // Only integers have signedness
385 if let Abi
::Scalar(ref scalar
) = self.layout
.abi
{
386 if let abi
::Int(i
, signed
) = scalar
.value
{
387 if i
.size().bits() < bits
{
388 if let PassMode
::Direct(ref mut attrs
) = self.mode
{
389 attrs
.set(if signed
{
400 pub fn cast_to
<T
: Into
<CastTarget
>>(&mut self, target
: T
) {
401 assert_eq
!(self.mode
, PassMode
::Direct(ArgAttributes
::new()));
402 self.mode
= PassMode
::Cast(target
.into());
405 pub fn pad_with(&mut self, reg
: Reg
) {
406 self.pad
= Some(reg
);
409 pub fn is_indirect(&self) -> bool
{
411 PassMode
::Indirect(_
) => true,
416 pub fn is_ignore(&self) -> bool
{
417 self.mode
== PassMode
::Ignore
421 #[derive(Copy, Clone, PartialEq, Debug)]
441 /// Metadata describing how the arguments to a native function
442 /// should be passed in order to respect the native ABI.
444 /// I will do my best to describe this structure, but these
445 /// comments are reverse-engineered and may be inaccurate. -NDM
447 pub struct FnType
<'a
, Ty
> {
448 /// The LLVM types of each argument.
449 pub args
: Vec
<ArgType
<'a
, Ty
>>,
451 /// LLVM return type.
452 pub ret
: ArgType
<'a
, Ty
>,
459 impl<'a
, Ty
> FnType
<'a
, Ty
> {
460 pub fn adjust_for_cabi
<C
>(&mut self, cx
: C
, abi
: ::spec
::abi
::Abi
) -> Result
<(), String
>
461 where Ty
: TyLayoutMethods
<'a
, C
> + Copy
,
462 C
: LayoutOf
<Ty
= Ty
, TyLayout
= TyLayout
<'a
, Ty
>> + HasDataLayout
+ HasTargetSpec
464 match &cx
.target_spec().arch
[..] {
466 let flavor
= if abi
== ::spec
::abi
::Abi
::Fastcall
{
467 x86
::Flavor
::Fastcall
471 x86
::compute_abi_info(cx
, self, flavor
);
473 "x86_64" => if abi
== ::spec
::abi
::Abi
::SysV64
{
474 x86_64
::compute_abi_info(cx
, self);
475 } else if abi
== ::spec
::abi
::Abi
::Win64
|| cx
.target_spec().options
.is_like_windows
{
476 x86_win64
::compute_abi_info(self);
478 x86_64
::compute_abi_info(cx
, self);
480 "aarch64" => aarch64
::compute_abi_info(cx
, self),
481 "arm" => arm
::compute_abi_info(cx
, self),
482 "mips" => mips
::compute_abi_info(cx
, self),
483 "mips64" => mips64
::compute_abi_info(cx
, self),
484 "powerpc" => powerpc
::compute_abi_info(cx
, self),
485 "powerpc64" => powerpc64
::compute_abi_info(cx
, self),
486 "s390x" => s390x
::compute_abi_info(cx
, self),
487 "asmjs" => asmjs
::compute_abi_info(cx
, self),
489 if cx
.target_spec().llvm_target
.contains("emscripten") {
490 asmjs
::compute_abi_info(cx
, self)
492 wasm32
::compute_abi_info(self)
495 "msp430" => msp430
::compute_abi_info(self),
496 "sparc" => sparc
::compute_abi_info(cx
, self),
497 "sparc64" => sparc64
::compute_abi_info(cx
, self),
498 "nvptx" => nvptx
::compute_abi_info(self),
499 "nvptx64" => nvptx64
::compute_abi_info(self),
500 "hexagon" => hexagon
::compute_abi_info(self),
501 a
=> return Err(format
!("unrecognized arch \"{}\" in target specification", a
))
504 if let PassMode
::Indirect(ref mut attrs
) = self.ret
.mode
{
505 attrs
.set(ArgAttribute
::StructRet
);