]> git.lizzy.rs Git - rust.git/commitdiff
Pass type to byval attributes
authorNikita Popov <nikita.ppv@gmail.com>
Sat, 6 Jul 2019 19:52:25 +0000 (21:52 +0200)
committerNikita Popov <nikita.ppv@gmail.com>
Tue, 9 Jul 2019 19:55:29 +0000 (21:55 +0200)
src/librustc_codegen_llvm/abi.rs
src/librustc_codegen_llvm/declare.rs
src/librustc_codegen_llvm/llvm/ffi.rs
src/rustllvm/RustWrapper.cpp

index 38d4b7e3f9d85504db9548447f19f8e294fec49f..ff87afe0c444b7556739c73517056a6c7e919f20 100644 (file)
@@ -34,17 +34,17 @@ trait ArgAttributeExt {
 impl ArgAttributeExt for ArgAttribute {
     fn for_each_kind<F>(&self, mut f: F) where F: FnMut(llvm::Attribute) {
         for_each_kind!(self, f,
-                       ByVal, NoAlias, NoCapture, NonNull, ReadOnly, SExt, StructRet, ZExt, InReg)
+                       NoAlias, NoCapture, NonNull, ReadOnly, SExt, StructRet, ZExt, InReg)
     }
 }
 
 pub trait ArgAttributesExt {
-    fn apply_llfn(&self, idx: AttributePlace, llfn: &Value);
-    fn apply_callsite(&self, idx: AttributePlace, callsite: &Value);
+    fn apply_llfn(&self, idx: AttributePlace, llfn: &Value, ty: Option<&Type>);
+    fn apply_callsite(&self, idx: AttributePlace, callsite: &Value, ty: Option<&Type>);
 }
 
 impl ArgAttributesExt for ArgAttributes {
-    fn apply_llfn(&self, idx: AttributePlace, llfn: &Value) {
+    fn apply_llfn(&self, idx: AttributePlace, llfn: &Value, ty: Option<&Type>) {
         let mut regular = self.regular;
         unsafe {
             let deref = self.pointee_size.bytes();
@@ -65,11 +65,14 @@ fn apply_llfn(&self, idx: AttributePlace, llfn: &Value) {
                                                idx.as_uint(),
                                                align.bytes() as u32);
             }
+            if regular.contains(ArgAttribute::ByVal) {
+                llvm::LLVMRustAddByValAttr(llfn, idx.as_uint(), ty.unwrap());
+            }
             regular.for_each_kind(|attr| attr.apply_llfn(idx, llfn));
         }
     }
 
-    fn apply_callsite(&self, idx: AttributePlace, callsite: &Value) {
+    fn apply_callsite(&self, idx: AttributePlace, callsite: &Value, ty: Option<&Type>) {
         let mut regular = self.regular;
         unsafe {
             let deref = self.pointee_size.bytes();
@@ -90,6 +93,9 @@ fn apply_callsite(&self, idx: AttributePlace, callsite: &Value) {
                                                        idx.as_uint(),
                                                        align.bytes() as u32);
             }
+            if regular.contains(ArgAttribute::ByVal) {
+                llvm::LLVMRustAddByValCallSiteAttr(callsite, idx.as_uint(), ty.unwrap());
+            }
             regular.for_each_kind(|attr| attr.apply_callsite(idx, callsite));
         }
     }
@@ -298,7 +304,7 @@ pub trait FnTypeLlvmExt<'tcx> {
     fn llvm_type(&self, cx: &CodegenCx<'ll, 'tcx>) -> &'ll Type;
     fn ptr_to_llvm_type(&self, cx: &CodegenCx<'ll, 'tcx>) -> &'ll Type;
     fn llvm_cconv(&self) -> llvm::CallConv;
-    fn apply_attrs_llfn(&self, llfn: &'ll Value);
+    fn apply_attrs_llfn(&self, cx: &CodegenCx<'ll, 'tcx>, llfn: &'ll Value);
     fn apply_attrs_callsite(&self, bx: &mut Builder<'a, 'll, 'tcx>, callsite: &'ll Value);
 }
 
@@ -384,51 +390,51 @@ fn llvm_cconv(&self) -> llvm::CallConv {
         }
     }
 
-    fn apply_attrs_llfn(&self, llfn: &'ll Value) {
+    fn apply_attrs_llfn(&self, cx: &CodegenCx<'ll, 'tcx>, llfn: &'ll Value) {
         let mut i = 0;
-        let mut apply = |attrs: &ArgAttributes| {
-            attrs.apply_llfn(llvm::AttributePlace::Argument(i), llfn);
+        let mut apply = |attrs: &ArgAttributes, ty: Option<&Type>| {
+            attrs.apply_llfn(llvm::AttributePlace::Argument(i), llfn, ty);
             i += 1;
         };
         match self.ret.mode {
             PassMode::Direct(ref attrs) => {
-                attrs.apply_llfn(llvm::AttributePlace::ReturnValue, llfn);
+                attrs.apply_llfn(llvm::AttributePlace::ReturnValue, llfn, None);
             }
-            PassMode::Indirect(ref attrs, _) => apply(attrs),
+            PassMode::Indirect(ref attrs, _) => apply(attrs, Some(self.ret.layout.llvm_type(cx))),
             _ => {}
         }
         for arg in &self.args {
             if arg.pad.is_some() {
-                apply(&ArgAttributes::new());
+                apply(&ArgAttributes::new(), None);
             }
             match arg.mode {
                 PassMode::Ignore(_) => {}
                 PassMode::Direct(ref attrs) |
-                PassMode::Indirect(ref attrs, None) => apply(attrs),
+                PassMode::Indirect(ref attrs, None) => apply(attrs, Some(arg.layout.llvm_type(cx))),
                 PassMode::Indirect(ref attrs, Some(ref extra_attrs)) => {
-                    apply(attrs);
-                    apply(extra_attrs);
+                    apply(attrs, None);
+                    apply(extra_attrs, None);
                 }
                 PassMode::Pair(ref a, ref b) => {
-                    apply(a);
-                    apply(b);
+                    apply(a, None);
+                    apply(b, None);
                 }
-                PassMode::Cast(_) => apply(&ArgAttributes::new()),
+                PassMode::Cast(_) => apply(&ArgAttributes::new(), None),
             }
         }
     }
 
     fn apply_attrs_callsite(&self, bx: &mut Builder<'a, 'll, 'tcx>, callsite: &'ll Value) {
         let mut i = 0;
-        let mut apply = |attrs: &ArgAttributes| {
-            attrs.apply_callsite(llvm::AttributePlace::Argument(i), callsite);
+        let mut apply = |attrs: &ArgAttributes, ty: Option<&Type>| {
+            attrs.apply_callsite(llvm::AttributePlace::Argument(i), callsite, ty);
             i += 1;
         };
         match self.ret.mode {
             PassMode::Direct(ref attrs) => {
-                attrs.apply_callsite(llvm::AttributePlace::ReturnValue, callsite);
+                attrs.apply_callsite(llvm::AttributePlace::ReturnValue, callsite, None);
             }
-            PassMode::Indirect(ref attrs, _) => apply(attrs),
+            PassMode::Indirect(ref attrs, _) => apply(attrs, Some(self.ret.layout.llvm_type(bx))),
             _ => {}
         }
         if let layout::Abi::Scalar(ref scalar) = self.ret.layout.abi {
@@ -446,21 +452,21 @@ fn apply_attrs_callsite(&self, bx: &mut Builder<'a, 'll, 'tcx>, callsite: &'ll V
         }
         for arg in &self.args {
             if arg.pad.is_some() {
-                apply(&ArgAttributes::new());
+                apply(&ArgAttributes::new(), None);
             }
             match arg.mode {
                 PassMode::Ignore(_) => {}
                 PassMode::Direct(ref attrs) |
-                PassMode::Indirect(ref attrs, None) => apply(attrs),
+                PassMode::Indirect(ref attrs, None) => apply(attrs, Some(arg.layout.llvm_type(bx))),
                 PassMode::Indirect(ref attrs, Some(ref extra_attrs)) => {
-                    apply(attrs);
-                    apply(extra_attrs);
+                    apply(attrs, None);
+                    apply(extra_attrs, None);
                 }
                 PassMode::Pair(ref a, ref b) => {
-                    apply(a);
-                    apply(b);
+                    apply(a, None);
+                    apply(b, None);
                 }
-                PassMode::Cast(_) => apply(&ArgAttributes::new()),
+                PassMode::Cast(_) => apply(&ArgAttributes::new(), None),
             }
         }
 
index bcb14b8899ec245bb728af3535bc91e0557bf1f8..62eab0f3d4e69b8f047d2f749fe65b13b672c8fb 100644 (file)
@@ -107,7 +107,7 @@ fn declare_fn(
             llvm::Attribute::NoReturn.apply_llfn(Function, llfn);
         }
 
-        fty.apply_attrs_llfn(llfn);
+        fty.apply_attrs_llfn(self, llfn);
 
         llfn
     }
index a5c295cd4525c25304aecf06828faa3f18108222..75f639ec3eca07715b02aec9990ece3373e1bbf8 100644 (file)
@@ -794,6 +794,7 @@ pub fn LLVMRustGetOrInsertFunction(M: &'a Module,
     pub fn LLVMRustAddAlignmentAttr(Fn: &Value, index: c_uint, bytes: u32);
     pub fn LLVMRustAddDereferenceableAttr(Fn: &Value, index: c_uint, bytes: u64);
     pub fn LLVMRustAddDereferenceableOrNullAttr(Fn: &Value, index: c_uint, bytes: u64);
+    pub fn LLVMRustAddByValAttr(Fn: &Value, index: c_uint, ty: &Type);
     pub fn LLVMRustAddFunctionAttribute(Fn: &Value, index: c_uint, attr: Attribute);
     pub fn LLVMRustAddFunctionAttrStringValue(Fn: &Value,
                                               index: c_uint,
@@ -824,6 +825,7 @@ pub fn LLVMAppendBasicBlockInContext(C: &'a Context,
     pub fn LLVMRustAddDereferenceableOrNullCallSiteAttr(Instr: &Value,
                                                         index: c_uint,
                                                         bytes: u64);
+    pub fn LLVMRustAddByValCallSiteAttr(Instr: &Value, index: c_uint, ty: &Type);
 
     // Operations on load/store instructions (only)
     pub fn LLVMSetVolatile(MemoryAccessInst: &Value, volatile: Bool);
index 66453c08a66ef2b6ee7a0444b56b9b25978d479c..16d08ee534edc413f6b1a9f88ba11e151b35f1de 100644 (file)
@@ -237,6 +237,17 @@ extern "C" void LLVMRustAddDereferenceableOrNullCallSiteAttr(LLVMValueRef Instr,
       Call->getContext(), Index, B));
 }
 
+extern "C" void LLVMRustAddByValCallSiteAttr(LLVMValueRef Instr, unsigned Index,
+                                             LLVMTypeRef Ty) {
+  CallSite Call = CallSite(unwrap<Instruction>(Instr));
+#if LLVM_VERSION_GE(9, 0)
+  Attribute Attr = Attribute::getWithByValType(Call->getContext(), unwrap(Ty));
+#else
+  Attribute Attr = Attribute::get(Call->getContext(), Attribute::ByVal);
+#endif
+  Call.addAttribute(Index, Attr);
+}
+
 extern "C" void LLVMRustAddFunctionAttribute(LLVMValueRef Fn, unsigned Index,
                                              LLVMRustAttribute RustAttr) {
   Function *A = unwrap<Function>(Fn);
@@ -271,6 +282,17 @@ extern "C" void LLVMRustAddDereferenceableOrNullAttr(LLVMValueRef Fn,
   A->addAttributes(Index, B);
 }
 
+extern "C" void LLVMRustAddByValAttr(LLVMValueRef Fn, unsigned Index,
+                                     LLVMTypeRef Ty) {
+  Function *F = unwrap<Function>(Fn);
+#if LLVM_VERSION_GE(9, 0)
+  Attribute Attr = Attribute::getWithByValType(F->getContext(), unwrap(Ty));
+#else
+  Attribute Attr = Attribute::get(F->getContext(), Attribute::ByVal);
+#endif
+  F->addAttribute(Index, Attr);
+}
+
 extern "C" void LLVMRustAddFunctionAttrStringValue(LLVMValueRef Fn,
                                                    unsigned Index,
                                                    const char *Name,