about summary refs log tree commit diff
diff options
context:
space:
mode:
authorOliver Schneider <git-no-reply-9879165716479413131@oli-obk.de>2018-05-12 18:47:20 +0200
committerOliver Schneider <github35764891676564198441@oli-obk.de>2018-05-19 14:24:24 +0200
commit8b99c61701cd3230bb24fba970d2f400e6e09fa1 (patch)
tree8fbb33beb424a2aef89841af69dd3df7f3e3249f
parentc95e1cccc9c248789230a54ecfd87971a04d5c0c (diff)
downloadrust-8b99c61701cd3230bb24fba970d2f400e6e09fa1.tar.gz
rust-8b99c61701cd3230bb24fba970d2f400e6e09fa1.zip
Ensure that statics are always ByRef
-rw-r--r--src/librustc_codegen_llvm/mir/constant.rs49
-rw-r--r--src/librustc_mir/interpret/const_eval.rs145
-rw-r--r--src/test/codegen/link_section.rs8
3 files changed, 69 insertions, 133 deletions
diff --git a/src/librustc_codegen_llvm/mir/constant.rs b/src/librustc_codegen_llvm/mir/constant.rs
index c2638d2d410..66a8b3ca36f 100644
--- a/src/librustc_codegen_llvm/mir/constant.rs
+++ b/src/librustc_codegen_llvm/mir/constant.rs
@@ -81,49 +81,6 @@ pub fn primval_to_llvm(cx: &CodegenCx,
     }
 }
 
-fn const_value_to_llvm<'tcx>(cx: &CodegenCx<'_, 'tcx>, val: ConstValue, ty: Ty<'tcx>) -> ValueRef {
-    let layout = cx.layout_of(ty);
-
-    if layout.is_zst() {
-        return C_undef(layout.immediate_llvm_type(cx));
-    }
-
-    match val {
-        ConstValue::ByVal(x) => {
-            let scalar = match layout.abi {
-                layout::Abi::Scalar(ref x) => x,
-                _ => bug!("const_value_to_llvm: invalid ByVal layout: {:#?}", layout)
-            };
-            primval_to_llvm(
-                cx,
-                x,
-                scalar,
-                layout.immediate_llvm_type(cx),
-            )
-        },
-        ConstValue::ByValPair(a, b) => {
-            let (a_scalar, b_scalar) = match layout.abi {
-                layout::Abi::ScalarPair(ref a, ref b) => (a, b),
-                _ => bug!("const_value_to_llvm: invalid ByValPair layout: {:#?}", layout)
-            };
-            let a_llval = primval_to_llvm(
-                cx,
-                a,
-                a_scalar,
-                layout.scalar_pair_element_llvm_type(cx, 0),
-            );
-            let b_llval = primval_to_llvm(
-                cx,
-                b,
-                b_scalar,
-                layout.scalar_pair_element_llvm_type(cx, 1),
-            );
-            C_struct(cx, &[a_llval, b_llval], false)
-        },
-        ConstValue::ByRef(alloc) => const_alloc_to_llvm(cx, alloc),
-    }
-}
-
 pub fn const_alloc_to_llvm(cx: &CodegenCx, alloc: &Allocation) -> ValueRef {
     let mut llvals = Vec::with_capacity(alloc.relocations.len() + 1);
     let layout = cx.data_layout();
@@ -171,11 +128,11 @@ pub fn codegen_static_initializer<'a, 'tcx>(
     let param_env = ty::ParamEnv::reveal_all();
     let static_ = cx.tcx.const_eval(param_env.and(cid))?;
 
-    let val = match static_.val {
-        ConstVal::Value(val) => val,
+    let alloc = match static_.val {
+        ConstVal::Value(ConstValue::ByRef(alloc)) => alloc,
         _ => bug!("static const eval returned {:#?}", static_),
     };
-    Ok(const_value_to_llvm(cx, val, static_.ty))
+    Ok(const_alloc_to_llvm(cx, alloc))
 }
 
 impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
diff --git a/src/librustc_mir/interpret/const_eval.rs b/src/librustc_mir/interpret/const_eval.rs
index 7d0c16de0a4..1f368cd3dfc 100644
--- a/src/librustc_mir/interpret/const_eval.rs
+++ b/src/librustc_mir/interpret/const_eval.rs
@@ -98,59 +98,32 @@ pub fn value_to_const_value<'tcx>(
     mut val: Value,
     ty: Ty<'tcx>,
 ) -> &'tcx ty::Const<'tcx> {
-    let result = (|| {
+    let val = (|| {
         // Convert to ByVal or ByValPair if possible
         if let Value::ByRef(ptr, align) = val {
             if let Some(read_val) = ecx.try_read_value(ptr, align, ty)? {
                 val = read_val;
             }
         }
-
-        let layout = ecx.tcx.layout_of(ty::ParamEnv::reveal_all().and(ty)).unwrap();
-
-        if layout.is_zst() {
-            return Ok(ty::Const::from_const_value(
-                ecx.tcx.tcx,
-                ConstValue::ByVal(PrimVal::Undef),
-                ty));
-        }
-
-        let val = match layout.abi {
-            layout::Abi::Scalar(..) => {
-                if let Value::ByVal(val) = val {
-                    ConstValue::ByVal(val)
-                } else {
-                    bug!("expected ByVal value, got {:?}", val);
-                }
-            }
-            layout::Abi::ScalarPair(..) => {
-                if let Value::ByValPair(a, b) = val {
-                    ConstValue::ByValPair(a, b)
-                } else {
-                    bug!("expected ByValPair value, got {:?}", val);
-                }
+        match val {
+            Value::ByVal(val) => Ok(ConstValue::ByVal(val)),
+            Value::ByValPair(a, b) => Ok(ConstValue::ByValPair(a, b)),
+            Value::ByRef(ptr, align) => {
+                let ptr = ptr.primval.to_ptr().unwrap();
+                assert_eq!(ptr.offset, 0);
+                let alloc = ecx.memory.get(ptr.alloc_id)?;
+                assert!(alloc.align.abi() >= layout.align.abi());
+                assert!(alloc.bytes.len() as u64 == layout.size.bytes());
+                let mut alloc = alloc.clone();
+                // The align field is meaningless for values, so just use the layout's align
+                alloc.align = layout.align;
+                let alloc = ecx.tcx.intern_const_alloc(alloc);
+                Ok(ConstValue::ByRef(alloc))
             }
-            _ => {
-                if let Value::ByRef(ptr, _) = val {
-                    let ptr = ptr.primval.to_ptr().unwrap();
-                    assert_eq!(ptr.offset, 0);
-                    let alloc = ecx.memory.get(ptr.alloc_id)?;
-                    assert!(alloc.align.abi() >= layout.align.abi());
-                    assert!(alloc.bytes.len() as u64 == layout.size.bytes());
-                    let mut alloc = alloc.clone();
-                    // The align field is meaningless for values, so just use the layout's align
-                    alloc.align = layout.align;
-                    let alloc = ecx.tcx.intern_const_alloc(alloc);
-                    ConstValue::ByRef(alloc)
-                } else {
-                    bug!("expected ByRef value, got {:?}", val);
-                }
-            },
-        };
-        Ok(ty::Const::from_const_value(ecx.tcx.tcx, val, ty))
+        }
     })();
     match result {
-        Ok(v) => v,
+        Ok(v) => ty::Const::from_const_value(tcx, val, ty),
         Err(mut err) => {
             ecx.report(&mut err, true, None);
             bug!("miri error occured when converting Value to ConstValue")
@@ -182,49 +155,49 @@ fn eval_body_using_ecx<'a, 'mir, 'tcx>(
 ) -> EvalResult<'tcx, (Value, Pointer, Ty<'tcx>)> {
     debug!("eval_body: {:?}, {:?}", cid, param_env);
     let tcx = ecx.tcx.tcx;
-        let mut mir = match mir {
-            Some(mir) => mir,
-            None => ecx.load_mir(cid.instance.def)?,
-        };
-        if let Some(index) = cid.promoted {
-            mir = &mir.promoted[index];
-        }
-        let layout = ecx.layout_of(mir.return_ty().subst(tcx, cid.instance.substs))?;
-        assert!(!layout.is_unsized());
-        let ptr = ecx.memory.allocate(
-            layout.size.bytes(),
-            layout.align,
-            None,
-        )?;
-        let internally_mutable = !layout.ty.is_freeze(tcx, param_env, mir.span);
-        let mutability = tcx.is_static(cid.instance.def_id());
-        let mutability = if mutability == Some(hir::Mutability::MutMutable) || internally_mutable {
-            Mutability::Mutable
-        } else {
-            Mutability::Immutable
-        };
-        let cleanup = StackPopCleanup::MarkStatic(mutability);
-        let name = ty::tls::with(|tcx| tcx.item_path_str(cid.instance.def_id()));
-        let prom = cid.promoted.map_or(String::new(), |p| format!("::promoted[{:?}]", p));
-        trace!("const_eval: pushing stack frame for global: {}{}", name, prom);
-        assert!(mir.arg_count == 0);
-        ecx.push_stack_frame(
-            cid.instance,
-            mir.span,
-            mir,
-            Place::from_ptr(ptr, layout.align),
-            cleanup,
-        )?;
+    let mut mir = match mir {
+        Some(mir) => mir,
+        None => ecx.load_mir(cid.instance.def)?,
+    };
+    if let Some(index) = cid.promoted {
+        mir = &mir.promoted[index];
+    }
+    let layout = ecx.layout_of(mir.return_ty().subst(tcx, cid.instance.substs))?;
+    assert!(!layout.is_unsized());
+    let ptr = ecx.memory.allocate(
+        layout.size.bytes(),
+        layout.align,
+        None,
+    )?;
+    let internally_mutable = !layout.ty.is_freeze(tcx, param_env, mir.span);
+    let is_static = tcx.is_static(cid.instance.def_id());
+    let mutability = if is_static == Some(hir::Mutability::MutMutable) || internally_mutable {
+        Mutability::Mutable
+    } else {
+        Mutability::Immutable
+    };
+    let cleanup = StackPopCleanup::MarkStatic(mutability);
+    let name = ty::tls::with(|tcx| tcx.item_path_str(cid.instance.def_id()));
+    let prom = cid.promoted.map_or(String::new(), |p| format!("::promoted[{:?}]", p));
+    trace!("const_eval: pushing stack frame for global: {}{}", name, prom);
+    assert!(mir.arg_count == 0);
+    ecx.push_stack_frame(
+        cid.instance,
+        mir.span,
+        mir,
+        Place::from_ptr(ptr, layout.align),
+        cleanup,
+    )?;
 
-        while ecx.step()? {}
-        let ptr = ptr.into();
-        // always try to read the value and report errors
-        let value = match ecx.try_read_value(ptr, layout.align, layout.ty)? {
-            Some(val) => val,
-            // point at the allocation
-            _ => Value::ByRef(ptr, layout.align),
-        };
-        Ok((value, ptr, layout.ty))
+    while ecx.step()? {}
+    let ptr = ptr.into();
+    // always try to read the value and report errors
+    let value = match ecx.try_read_value(ptr, layout.align, layout.ty)? {
+        Some(val) if is_static.is_none() => val,
+        // point at the allocation
+        _ => Value::ByRef(ptr, layout.align),
+    };
+    Ok((value, ptr, layout.ty))
 }
 
 pub struct CompileTimeEvaluator;
diff --git a/src/test/codegen/link_section.rs b/src/test/codegen/link_section.rs
index 1879002e7f3..415ee6eb7ea 100644
--- a/src/test/codegen/link_section.rs
+++ b/src/test/codegen/link_section.rs
@@ -12,11 +12,17 @@
 
 #![crate_type = "lib"]
 
-// CHECK: @VAR1 = constant i32 1, section ".test_one"
+// CHECK: @VAR1 = constant <{ [4 x i8] }> <{ [4 x i8] c"\01\00\00\00" }>, section ".test_one"
 #[no_mangle]
 #[link_section = ".test_one"]
+#[cfg(target_endian = "little")]
 pub static VAR1: u32 = 1;
 
+#[no_mangle]
+#[link_section = ".test_one"]
+#[cfg(target_endian = "big")]
+pub static VAR1: u32 = 0x01000000;
+
 pub enum E {
     A(u32),
     B(f32)