]> git.lizzy.rs Git - rust.git/commitdiff
Auto merge of #54993 - TimNN:pda-tdl, r=eddyb
authorbors <bors@rust-lang.org>
Sun, 11 Nov 2018 03:44:16 +0000 (03:44 +0000)
committerbors <bors@rust-lang.org>
Sun, 11 Nov 2018 03:44:16 +0000 (03:44 +0000)
Support for the program data address space option of LLVM's Target Datalayout

This was introduced recently (specifically, for AVR, cc @dylanmckay).

(I came up with this when attempting to run [avr-rust](https://github.com/avr-rust/rust) rebased on the latest [rust-lang](https://github.com/rust-lang/rust) commits. If this requires a different design, some additional discussions, or is not something to pursue right now, I'd be happy to close this PR).

Note that this somewhat overlaps with @DiamondLovesYou's #51576, I think, although the implementation here is significantly simpler: Since the address space applies to _all_ program data, we can just check the pointee's type whenever we create an LLVM pointer type. If it is a function we use the program data address space; if not we use the default address space.

cc @eddyb, who has been reviewing #51576

Ref: https://llvm.org/docs/LangRef.html#data-layout

src/librustc_codegen_llvm/abi.rs
src/librustc_codegen_llvm/meth.rs
src/librustc_codegen_llvm/type_.rs
src/librustc_codegen_llvm/type_of.rs
src/librustc_target/abi/mod.rs

index bd7a1c2c3293eb28194d3b8e4f2af54d56580d46..03b0b04d4014694f5571b97745f9cffd48504ef3 100644 (file)
@@ -19,7 +19,7 @@
 use type_of::{LayoutLlvmExt, PointerKind};
 use value::Value;
 
-use rustc_target::abi::{LayoutOf, Size, TyLayout, Abi as LayoutAbi};
+use rustc_target::abi::{HasDataLayout, LayoutOf, Size, TyLayout, Abi as LayoutAbi};
 use rustc::ty::{self, Ty};
 use rustc::ty::layout;
 
@@ -277,6 +277,7 @@ fn adjust_for_abi(&mut self,
                       cx: &CodegenCx<'ll, 'tcx>,
                       abi: Abi);
     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_callsite(&self, bx: &Builder<'a, 'll, 'tcx>, callsite: &'ll Value);
@@ -658,6 +659,13 @@ fn llvm_type(&self, cx: &CodegenCx<'ll, 'tcx>) -> &'ll Type {
         }
     }
 
+    fn ptr_to_llvm_type(&self, cx: &CodegenCx<'ll, 'tcx>) -> &'ll Type {
+        unsafe {
+            llvm::LLVMPointerType(self.llvm_type(cx),
+                                  cx.data_layout().instruction_address_space as c_uint)
+        }
+    }
+
     fn llvm_cconv(&self) -> llvm::CallConv {
         match self.conv {
             Conv::C => llvm::CCallConv,
index d38f343d01f34981b5088ff949df6494df9fd924..0dc5a4ddde82c538bc820518cff99dfb18b3f5cd 100644 (file)
@@ -39,7 +39,7 @@ pub fn get_fn(self, bx: &Builder<'a, 'll, 'tcx>,
         // Load the data pointer from the object.
         debug!("get_fn({:?}, {:?})", llvtable, self);
 
-        let llvtable = bx.pointercast(llvtable, fn_ty.llvm_type(bx.cx).ptr_to().ptr_to());
+        let llvtable = bx.pointercast(llvtable, fn_ty.ptr_to_llvm_type(bx.cx).ptr_to());
         let ptr_align = bx.tcx().data_layout.pointer_align;
         let ptr = bx.load(bx.inbounds_gep(llvtable, &[C_usize(bx.cx, self.0)]), ptr_align);
         bx.nonnull_metadata(ptr);
index 51a233d79162539d3e194db44f9db903eb38aa75..6fb78fe4aa5a4124c590b755153451f3a4fab0c0 100644 (file)
@@ -234,6 +234,8 @@ pub fn set_struct_body(&'ll self, els: &[&'ll Type], packed: bool) {
     }
 
     pub fn ptr_to(&self) -> &Type {
+        assert_ne!(self.kind(), TypeKind::Function,
+                   "don't call ptr_to on function types, use ptr_to_llvm_type on FnType instead");
         unsafe {
             llvm::LLVMPointerType(self, 0)
         }
index b01d7e3a776f7145b791bfe7670db6f55636f6f4..fea02edf7be01b70748d68f73f53285515b6e5d2 100644 (file)
@@ -265,7 +265,7 @@ fn llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> &'a Type {
                         ty::ParamEnv::reveal_all(),
                         &sig,
                     );
-                    FnType::new(cx, sig, &[]).llvm_type(cx).ptr_to()
+                    FnType::new(cx, sig, &[]).ptr_to_llvm_type(cx)
                 }
                 _ => self.scalar_llvm_type_at(cx, scalar, Size::ZERO)
             };
index c7d0469e556a75cf15127c71c153ff21d414d94a..15f61a033447fffacc782b2b4bc011f71a1d65ce 100644 (file)
@@ -35,7 +35,8 @@ pub struct TargetDataLayout {
     pub aggregate_align: Align,
 
     /// Alignments for vector types.
-    pub vector_align: Vec<(Size, Align)>
+    pub vector_align: Vec<(Size, Align)>,
+    pub instruction_address_space: u32,
 }
 
 impl Default for TargetDataLayout {
@@ -57,13 +58,22 @@ fn default() -> TargetDataLayout {
             vector_align: vec![
                 (Size::from_bits(64), Align::from_bits(64, 64).unwrap()),
                 (Size::from_bits(128), Align::from_bits(128, 128).unwrap())
-            ]
+            ],
+            instruction_address_space: 0,
         }
     }
 }
 
 impl TargetDataLayout {
     pub fn parse(target: &Target) -> Result<TargetDataLayout, String> {
+        // Parse an address space index from a string.
+        let parse_address_space = |s: &str, cause: &str| {
+            s.parse::<u32>().map_err(|err| {
+                format!("invalid address space `{}` for `{}` in \"data-layout\": {}",
+                        s, cause, err)
+            })
+        };
+
         // Parse a bit count from a string.
         let parse_bits = |s: &str, kind: &str, cause: &str| {
             s.parse::<u64>().map_err(|err| {
@@ -96,6 +106,9 @@ pub fn parse(target: &Target) -> Result<TargetDataLayout, String> {
             match spec.split(':').collect::<Vec<_>>()[..] {
                 ["e"] => dl.endian = Endian::Little,
                 ["E"] => dl.endian = Endian::Big,
+                [p] if p.starts_with("P") => {
+                    dl.instruction_address_space = parse_address_space(&p[1..], "P")?
+                }
                 ["a", ref a..] => dl.aggregate_align = align(a, "a")?,
                 ["f32", ref a..] => dl.f32_align = align(a, "f32")?,
                 ["f64", ref a..] => dl.f64_align = align(a, "f64")?,