about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEduard Burtescu <edy.burt@gmail.com>2016-02-25 19:35:40 +0200
committerEduard Burtescu <edy.burt@gmail.com>2016-03-17 21:51:51 +0200
commitde5f8244f20e434d2e0d351c7f4b55e604b4f3b3 (patch)
treed128ccce17da925c734aa525bd011170c80d75a3
parentc7172a9935771601a67cdcbedcd2a8cda87367e9 (diff)
trans: Use llvm::Attributes directly in ArgTy.
-rw-r--r--src/librustc_llvm/lib.rs2
-rw-r--r--src/librustc_trans/trans/abi.rs86
-rw-r--r--src/librustc_trans/trans/cabi_aarch64.rs6
-rw-r--r--src/librustc_trans/trans/cabi_arm.rs4
-rw-r--r--src/librustc_trans/trans/cabi_asmjs.rs18
-rw-r--r--src/librustc_trans/trans/cabi_mips.rs4
-rw-r--r--src/librustc_trans/trans/cabi_powerpc.rs4
-rw-r--r--src/librustc_trans/trans/cabi_powerpc64.rs6
-rw-r--r--src/librustc_trans/trans/cabi_x86.rs12
-rw-r--r--src/librustc_trans/trans/cabi_x86_64.rs8
-rw-r--r--src/librustc_trans/trans/cabi_x86_win64.rs4
-rw-r--r--src/librustc_trans/trans/declare.rs2
-rw-r--r--src/librustc_trans/trans/foreign.rs2
13 files changed, 80 insertions, 78 deletions
diff --git a/src/librustc_llvm/lib.rs b/src/librustc_llvm/lib.rs
index 10865df3a4d..b8377916efe 100644
--- a/src/librustc_llvm/lib.rs
+++ b/src/librustc_llvm/lib.rs
@@ -185,7 +185,7 @@ bitflags! {
     }
 }
 
-#[derive(Copy, Clone, Default)]
+#[derive(Copy, Clone, Default, Debug)]
 pub struct Attributes {
     regular: Attribute,
     dereferenceable_bytes: u64
diff --git a/src/librustc_trans/trans/abi.rs b/src/librustc_trans/trans/abi.rs
index 7a639d5c89e..ccd276457ce 100644
--- a/src/librustc_trans/trans/abi.rs
+++ b/src/librustc_trans/trans/abi.rs
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-pub use self::ArgKind::*;
-
 use llvm;
 use trans::common::{return_type_is_void, type_is_fat_ptr};
 use trans::context::CrateContext;
@@ -43,7 +41,7 @@ pub const FAT_PTR_ADDR: usize = 0;
 pub const FAT_PTR_EXTRA: usize = 1;
 
 #[derive(Clone, Copy, PartialEq, Debug)]
-pub enum ArgKind {
+enum ArgKind {
     /// Pass the argument directly using the normal converted
     /// LLVM type or by coercing to another specified type
     Direct,
@@ -59,7 +57,7 @@ pub enum ArgKind {
 /// This is borrowed from clang's ABIInfo.h
 #[derive(Clone, Copy, Debug)]
 pub struct ArgType {
-    pub kind: ArgKind,
+    kind: ArgKind,
     /// Original LLVM type
     pub original_ty: Type,
     /// Sizing LLVM type (pointers are opaque).
@@ -81,28 +79,48 @@ pub struct ArgType {
     pub cast: Option<Type>,
     /// Dummy argument, which is emitted before the real argument
     pub pad: Option<Type>,
-    /// LLVM attribute of argument
-    pub attr: Option<llvm::Attribute>
+    /// LLVM attributes of argument
+    pub attrs: llvm::Attributes
 }
 
 impl ArgType {
     fn new(original_ty: Type, ty: Type) -> ArgType {
         ArgType {
-            kind: Direct,
+            kind: ArgKind::Direct,
             original_ty: original_ty,
             ty: ty,
             cast: None,
             pad: None,
-            attr: None
+            attrs: llvm::Attributes::default()
         }
     }
 
+    pub fn make_indirect(&mut self, ccx: &CrateContext) {
+        // Wipe old attributes, likely not valid through indirection.
+        self.attrs = llvm::Attributes::default();
+
+        let llarg_sz = llsize_of_real(ccx, self.ty);
+
+        // For non-immediate arguments the callee gets its own copy of
+        // the value on the stack, so there are no aliases. It's also
+        // program-invisible so can't possibly capture
+        self.attrs.set(llvm::Attribute::NoAlias)
+                  .set(llvm::Attribute::NoCapture)
+                  .set_dereferenceable(llarg_sz);
+
+        self.kind = ArgKind::Indirect;
+    }
+
+    pub fn ignore(&mut self) {
+        self.kind = ArgKind::Ignore;
+    }
+
     pub fn is_indirect(&self) -> bool {
-        self.kind == Indirect
+        self.kind == ArgKind::Indirect
     }
 
     pub fn is_ignore(&self) -> bool {
-        self.kind == Ignore
+        self.kind == ArgKind::Ignore
     }
 }
 
@@ -178,7 +196,7 @@ impl FnType {
             if ty.is_bool() {
                 let llty = Type::i1(ccx);
                 let mut arg = ArgType::new(llty, llty);
-                arg.attr = Some(llvm::Attribute::ZExt);
+                arg.attrs.set(llvm::Attribute::ZExt);
                 arg
             } else {
                 ArgType::new(type_of::type_of(ccx, ty),
@@ -221,7 +239,7 @@ impl FnType {
                 }
                 let size = llsize_of_alloc(ccx, arg.ty);
                 if size > llsize_of_alloc(ccx, ccx.int_type()) {
-                    arg.kind = Indirect;
+                    arg.make_indirect(ccx);
                 } else if size > 0 {
                     // We want to pass small aggregates as immediates, but using
                     // a LLVM aggregate type for this leads to bad optimizations,
@@ -238,6 +256,9 @@ impl FnType {
             for arg in &mut fty.args {
                 fixup(arg);
             }
+            if fty.ret.is_indirect() {
+                fty.ret.attrs.set(llvm::Attribute::StructRet);
+            }
             return fty;
         }
 
@@ -264,6 +285,10 @@ impl FnType {
             a => ccx.sess().fatal(&format!("unrecognized arch \"{}\" in target specification", a))
         }
 
+        if fty.ret.is_indirect() {
+            fty.ret.attrs.set(llvm::Attribute::StructRet);
+        }
+
         fty
     }
 
@@ -302,43 +327,18 @@ impl FnType {
         }
     }
 
-    pub fn llvm_attrs(&self, ccx: &CrateContext) -> llvm::AttrBuilder {
+    pub fn llvm_attrs(&self) -> llvm::AttrBuilder {
         let mut attrs = llvm::AttrBuilder::new();
         let mut i = if self.ret.is_indirect() { 1 } else { 0 };
-
-        // Add attributes that are always applicable, independent of the concrete foreign ABI
-        if self.ret.is_indirect() {
-            let llret_sz = llsize_of_real(ccx, self.ret.ty);
-
-            // The outptr can be noalias and nocapture because it's entirely
-            // invisible to the program. We also know it's nonnull as well
-            // as how many bytes we can dereference
-            attrs.arg(i).set(llvm::Attribute::StructRet)
-                        .set(llvm::Attribute::NoAlias)
-                        .set(llvm::Attribute::NoCapture)
-                        .set_dereferenceable(llret_sz);
-        };
-
-        // Add attributes that depend on the concrete foreign ABI
-        if let Some(attr) = self.ret.attr {
-            attrs.arg(i).set(attr);
-        }
-
+        *attrs.arg(i) = self.ret.attrs;
         i += 1;
         for arg in &self.args {
-            if arg.is_ignore() {
-                continue;
-            }
-            // skip padding
-            if arg.pad.is_some() { i += 1; }
-
-            if let Some(attr) = arg.attr {
-                attrs.arg(i).set(attr);
+            if !arg.is_ignore() {
+                if arg.pad.is_some() { i += 1; }
+                *attrs.arg(i) = arg.attrs;
+                i += 1;
             }
-
-            i += 1;
         }
-
         attrs
     }
 }
diff --git a/src/librustc_trans/trans/cabi_aarch64.rs b/src/librustc_trans/trans/cabi_aarch64.rs
index 65d2ad9c4fa..4398e14fdcc 100644
--- a/src/librustc_trans/trans/cabi_aarch64.rs
+++ b/src/librustc_trans/trans/cabi_aarch64.rs
@@ -11,7 +11,7 @@
 #![allow(non_upper_case_globals)]
 
 use llvm::{Integer, Pointer, Float, Double, Struct, Array, Vector};
-use trans::abi::{FnType, ArgType, Indirect};
+use trans::abi::{FnType, ArgType};
 use trans::context::CrateContext;
 use trans::type_::Type;
 
@@ -185,7 +185,7 @@ fn classify_ret_ty(ccx: &CrateContext, ret: &mut ArgType) {
         ret.cast = Some(llty);
         return;
     }
-    ret.kind = Indirect;
+    ret.make_indirect(ccx);
 }
 
 fn classify_arg_ty(ccx: &CrateContext, arg: &mut ArgType) {
@@ -214,7 +214,7 @@ fn classify_arg_ty(ccx: &CrateContext, arg: &mut ArgType) {
         arg.cast = Some(llty);
         return;
     }
-    arg.kind = Indirect;
+    arg.make_indirect(ccx);
 }
 
 fn is_reg_ty(ty: Type) -> bool {
diff --git a/src/librustc_trans/trans/cabi_arm.rs b/src/librustc_trans/trans/cabi_arm.rs
index 77941a853e6..2146a9c5e21 100644
--- a/src/librustc_trans/trans/cabi_arm.rs
+++ b/src/librustc_trans/trans/cabi_arm.rs
@@ -11,7 +11,7 @@
 #![allow(non_upper_case_globals)]
 
 use llvm::{Integer, Pointer, Float, Double, Struct, Array, Vector};
-use trans::abi::{FnType, ArgType, Indirect};
+use trans::abi::{FnType, ArgType};
 use trans::context::CrateContext;
 use trans::type_::Type;
 
@@ -145,7 +145,7 @@ fn classify_ret_ty(ccx: &CrateContext, ret: &mut ArgType, align_fn: TyAlignFn) {
         ret.cast = Some(llty);
         return;
     }
-    ret.kind = Indirect;
+    ret.make_indirect(ccx);
 }
 
 fn classify_arg_ty(ccx: &CrateContext, arg: &mut ArgType, align_fn: TyAlignFn) {
diff --git a/src/librustc_trans/trans/cabi_asmjs.rs b/src/librustc_trans/trans/cabi_asmjs.rs
index 5c9bf28e4e0..4ec547c3640 100644
--- a/src/librustc_trans/trans/cabi_asmjs.rs
+++ b/src/librustc_trans/trans/cabi_asmjs.rs
@@ -11,7 +11,7 @@
 #![allow(non_upper_case_globals)]
 
 use llvm::{Struct, Array, Attribute};
-use trans::abi::{FnType, ArgType, Indirect};
+use trans::abi::{FnType, ArgType};
 use trans::context::CrateContext;
 use trans::type_::Type;
 
@@ -20,36 +20,36 @@ use trans::type_::Type;
 // See the https://github.com/kripken/emscripten-fastcomp-clang repository.
 // The class `EmscriptenABIInfo` in `/lib/CodeGen/TargetInfo.cpp` contains the ABI definitions.
 
-fn classify_ret_ty(ret: &mut ArgType) {
+fn classify_ret_ty(ccx: &CrateContext, ret: &mut ArgType) {
     match ret.ty.kind() {
         Struct => {
             let field_types = ret.ty.field_types();
             if field_types.len() == 1 {
                 ret.cast = Some(field_types[0]);
             } else {
-                ret.kind = Indirect;
+                ret.make_indirect(ccx);
             }
         }
         Array => {
-            ret.kind = Indirect;
+            ret.make_indirect(ccx);
         }
         _ => {}
     }
 }
 
-fn classify_arg_ty(arg: &mut ArgType) {
+fn classify_arg_ty(ccx: &CrateContext, arg: &mut ArgType) {
     if arg.ty.is_aggregate() {
-        arg.kind = Indirect;
-        arg.attr = Some(Attribute::ByVal);
+        arg.make_indirect(ccx);
+        arg.attrs.set(Attribute::ByVal);
     }
 }
 
 pub fn compute_abi_info(ccx: &CrateContext, fty: &mut FnType) {
     if fty.ret.ty != Type::void(ccx) {
-        classify_ret_ty(&mut fty.ret);
+        classify_ret_ty(ccx, &mut fty.ret);
     }
 
     for arg in &mut fty.args {
-        classify_arg_ty(arg);
+        classify_arg_ty(ccx, arg);
     }
 }
diff --git a/src/librustc_trans/trans/cabi_mips.rs b/src/librustc_trans/trans/cabi_mips.rs
index 419c56072b4..b4fe00f8d69 100644
--- a/src/librustc_trans/trans/cabi_mips.rs
+++ b/src/librustc_trans/trans/cabi_mips.rs
@@ -14,7 +14,7 @@ use libc::c_uint;
 use std::cmp;
 use llvm;
 use llvm::{Integer, Pointer, Float, Double, Struct, Array, Vector};
-use trans::abi::{ArgType, FnType, Indirect};
+use trans::abi::{ArgType, FnType};
 use trans::context::CrateContext;
 use trans::type_::Type;
 
@@ -148,7 +148,7 @@ fn struct_ty(ccx: &CrateContext, ty: Type) -> Type {
 pub fn compute_abi_info(ccx: &CrateContext, fty: &mut FnType) {
     if fty.ret.ty != Type::void(ccx) {
         if !is_reg_ty(fty.ret.ty) {
-            fty.ret.kind = Indirect;
+            fty.ret.make_indirect(ccx);
         }
     }
 
diff --git a/src/librustc_trans/trans/cabi_powerpc.rs b/src/librustc_trans/trans/cabi_powerpc.rs
index ecd5b71ada9..8d9c6e8e1f8 100644
--- a/src/librustc_trans/trans/cabi_powerpc.rs
+++ b/src/librustc_trans/trans/cabi_powerpc.rs
@@ -11,7 +11,7 @@
 use libc::c_uint;
 use llvm;
 use llvm::{Integer, Pointer, Float, Double, Struct, Array};
-use trans::abi::{FnType, ArgType, Indirect};
+use trans::abi::{FnType, ArgType};
 use trans::context::CrateContext;
 use trans::type_::Type;
 
@@ -143,7 +143,7 @@ fn struct_ty(ccx: &CrateContext, ty: Type) -> Type {
 pub fn compute_abi_info(ccx: &CrateContext, fty: &mut FnType) {
     if fty.ret.ty != Type::void(ccx) {
         if !is_reg_ty(fty.ret.ty) {
-            fty.ret.kind = Indirect;
+            fty.ret.make_indirect(ccx);
         }
     }
 
diff --git a/src/librustc_trans/trans/cabi_powerpc64.rs b/src/librustc_trans/trans/cabi_powerpc64.rs
index b28ec618650..77858398f37 100644
--- a/src/librustc_trans/trans/cabi_powerpc64.rs
+++ b/src/librustc_trans/trans/cabi_powerpc64.rs
@@ -16,7 +16,7 @@
 // need to be fixed when PowerPC vector support is added.
 
 use llvm::{Integer, Pointer, Float, Double, Struct, Array};
-use trans::abi::{FnType, ArgType, Indirect};
+use trans::abi::{FnType, ArgType};
 use trans::context::CrateContext;
 use trans::type_::Type;
 
@@ -158,7 +158,7 @@ fn classify_ret_ty(ccx: &CrateContext, ret: &mut ArgType) {
 
     // The PowerPC64 big endian ABI doesn't return aggregates in registers
     if ccx.sess().target.target.target_endian == "big" {
-        ret.kind = Indirect;
+        ret.make_indirect(ccx);
     }
 
     if let Some((base_ty, members)) = is_homogenous_aggregate_ty(ret.ty) {
@@ -182,7 +182,7 @@ fn classify_ret_ty(ccx: &CrateContext, ret: &mut ArgType) {
         return;
     }
 
-    ret.kind = Indirect;
+    ret.make_indirect(ccx);
 }
 
 fn classify_arg_ty(ccx: &CrateContext, arg: &mut ArgType) {
diff --git a/src/librustc_trans/trans/cabi_x86.rs b/src/librustc_trans/trans/cabi_x86.rs
index fd1b8b21401..af194e8e5d7 100644
--- a/src/librustc_trans/trans/cabi_x86.rs
+++ b/src/librustc_trans/trans/cabi_x86.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 use llvm::*;
-use trans::abi::{FnType, Indirect, Ignore};
+use trans::abi::FnType;
 use trans::type_::Type;
 use super::common::*;
 use super::machine::*;
@@ -30,20 +30,20 @@ pub fn compute_abi_info(ccx: &CrateContext, fty: &mut FnType) {
                 2 => fty.ret.cast = Some(Type::i16(ccx)),
                 4 => fty.ret.cast = Some(Type::i32(ccx)),
                 8 => fty.ret.cast = Some(Type::i64(ccx)),
-                _ => fty.ret.kind = Indirect
+                _ => fty.ret.make_indirect(ccx)
             }
         } else {
-            fty.ret.kind = Indirect;
+            fty.ret.make_indirect(ccx);
         }
     }
 
     for arg in &mut fty.args {
         if arg.ty.kind() == Struct {
             if llsize_of_alloc(ccx, arg.ty) == 0 {
-                arg.kind = Ignore;
+                arg.ignore();
             } else {
-                arg.kind = Indirect;
-                arg.attr = Some(Attribute::ByVal);
+                arg.make_indirect(ccx);
+                arg.attrs.set(Attribute::ByVal);
             }
         }
     }
diff --git a/src/librustc_trans/trans/cabi_x86_64.rs b/src/librustc_trans/trans/cabi_x86_64.rs
index ab32ca206fc..c6f1dc9e671 100644
--- a/src/librustc_trans/trans/cabi_x86_64.rs
+++ b/src/librustc_trans/trans/cabi_x86_64.rs
@@ -16,7 +16,7 @@ use self::RegClass::*;
 
 use llvm::{Integer, Pointer, Float, Double};
 use llvm::{Struct, Array, Attribute, Vector};
-use trans::abi::{ArgType, FnType, Indirect};
+use trans::abi::{ArgType, FnType};
 use trans::context::CrateContext;
 use trans::type_::Type;
 
@@ -393,8 +393,10 @@ pub fn compute_abi_info(ccx: &CrateContext, fty: &mut FnType) {
         if !arg.ty.is_reg_ty() {
             let cls = classify_ty(arg.ty);
             if is_mem_cls(&cls) {
-                arg.kind = Indirect;
-                arg.attr = ind_attr;
+                arg.make_indirect(ccx);
+                if let Some(attr) = ind_attr {
+                    arg.attrs.set(attr);
+                }
             } else {
                 arg.cast = Some(llreg_ty(ccx, &cls));
             }
diff --git a/src/librustc_trans/trans/cabi_x86_win64.rs b/src/librustc_trans/trans/cabi_x86_win64.rs
index e9a06fd8d6b..448789530a5 100644
--- a/src/librustc_trans/trans/cabi_x86_win64.rs
+++ b/src/librustc_trans/trans/cabi_x86_win64.rs
@@ -11,7 +11,7 @@
 use llvm::*;
 use super::common::*;
 use super::machine::*;
-use trans::abi::{ArgType, FnType, Indirect};
+use trans::abi::{ArgType, FnType};
 use trans::type_::Type;
 
 // Win64 ABI: http://msdn.microsoft.com/en-us/library/zthk2dkh.aspx
@@ -24,7 +24,7 @@ pub fn compute_abi_info(ccx: &CrateContext, fty: &mut FnType) {
                 2 => a.cast = Some(Type::i16(ccx)),
                 4 => a.cast = Some(Type::i32(ccx)),
                 8 => a.cast = Some(Type::i64(ccx)),
-                _ => a.kind = Indirect
+                _ => a.make_indirect(ccx)
             }
         }
     };
diff --git a/src/librustc_trans/trans/declare.rs b/src/librustc_trans/trans/declare.rs
index f7bc22a4482..6d21a90bb0d 100644
--- a/src/librustc_trans/trans/declare.rs
+++ b/src/librustc_trans/trans/declare.rs
@@ -113,7 +113,7 @@ pub fn declare_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, name: &str,
         attributes::from_fn_type(ccx, fn_type)
     } else {
         attributes::unwind(llfn, false);
-        fty.llvm_attrs(ccx)
+        fty.llvm_attrs()
     };
 
     attrs.apply_llfn(llfn);
diff --git a/src/librustc_trans/trans/foreign.rs b/src/librustc_trans/trans/foreign.rs
index ed96871002a..ac316d18940 100644
--- a/src/librustc_trans/trans/foreign.rs
+++ b/src/librustc_trans/trans/foreign.rs
@@ -253,7 +253,7 @@ pub fn trans_native_call<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                                         llfn,
                                         &llargs_foreign[..],
                                         fn_type.cconv,
-                                        Some(fn_type.llvm_attrs(ccx)),
+                                        Some(fn_type.llvm_attrs()),
                                         call_debug_loc);
 
     // If the function we just called does not use an outpointer,