Ensure that statics are always ByRef
This commit is contained in:
parent
c95e1cccc9
commit
8b99c61701
@ -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 {
|
pub fn const_alloc_to_llvm(cx: &CodegenCx, alloc: &Allocation) -> ValueRef {
|
||||||
let mut llvals = Vec::with_capacity(alloc.relocations.len() + 1);
|
let mut llvals = Vec::with_capacity(alloc.relocations.len() + 1);
|
||||||
let layout = cx.data_layout();
|
let layout = cx.data_layout();
|
||||||
@ -171,11 +128,11 @@ pub fn codegen_static_initializer<'a, 'tcx>(
|
|||||||
let param_env = ty::ParamEnv::reveal_all();
|
let param_env = ty::ParamEnv::reveal_all();
|
||||||
let static_ = cx.tcx.const_eval(param_env.and(cid))?;
|
let static_ = cx.tcx.const_eval(param_env.and(cid))?;
|
||||||
|
|
||||||
let val = match static_.val {
|
let alloc = match static_.val {
|
||||||
ConstVal::Value(val) => val,
|
ConstVal::Value(ConstValue::ByRef(alloc)) => alloc,
|
||||||
_ => bug!("static const eval returned {:#?}", static_),
|
_ => 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> {
|
impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
|
||||||
|
@ -98,59 +98,32 @@ pub fn value_to_const_value<'tcx>(
|
|||||||
mut val: Value,
|
mut val: Value,
|
||||||
ty: Ty<'tcx>,
|
ty: Ty<'tcx>,
|
||||||
) -> &'tcx ty::Const<'tcx> {
|
) -> &'tcx ty::Const<'tcx> {
|
||||||
let result = (|| {
|
let val = (|| {
|
||||||
// Convert to ByVal or ByValPair if possible
|
// Convert to ByVal or ByValPair if possible
|
||||||
if let Value::ByRef(ptr, align) = val {
|
if let Value::ByRef(ptr, align) = val {
|
||||||
if let Some(read_val) = ecx.try_read_value(ptr, align, ty)? {
|
if let Some(read_val) = ecx.try_read_value(ptr, align, ty)? {
|
||||||
val = read_val;
|
val = read_val;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
match val {
|
||||||
let layout = ecx.tcx.layout_of(ty::ParamEnv::reveal_all().and(ty)).unwrap();
|
Value::ByVal(val) => Ok(ConstValue::ByVal(val)),
|
||||||
|
Value::ByValPair(a, b) => Ok(ConstValue::ByValPair(a, b)),
|
||||||
if layout.is_zst() {
|
Value::ByRef(ptr, align) => {
|
||||||
return Ok(ty::Const::from_const_value(
|
let ptr = ptr.primval.to_ptr().unwrap();
|
||||||
ecx.tcx.tcx,
|
assert_eq!(ptr.offset, 0);
|
||||||
ConstValue::ByVal(PrimVal::Undef),
|
let alloc = ecx.memory.get(ptr.alloc_id)?;
|
||||||
ty));
|
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))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
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 {
|
match result {
|
||||||
Ok(v) => v,
|
Ok(v) => ty::Const::from_const_value(tcx, val, ty),
|
||||||
Err(mut err) => {
|
Err(mut err) => {
|
||||||
ecx.report(&mut err, true, None);
|
ecx.report(&mut err, true, None);
|
||||||
bug!("miri error occured when converting Value to ConstValue")
|
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>)> {
|
) -> EvalResult<'tcx, (Value, Pointer, Ty<'tcx>)> {
|
||||||
debug!("eval_body: {:?}, {:?}", cid, param_env);
|
debug!("eval_body: {:?}, {:?}", cid, param_env);
|
||||||
let tcx = ecx.tcx.tcx;
|
let tcx = ecx.tcx.tcx;
|
||||||
let mut mir = match mir {
|
let mut mir = match mir {
|
||||||
Some(mir) => mir,
|
Some(mir) => mir,
|
||||||
None => ecx.load_mir(cid.instance.def)?,
|
None => ecx.load_mir(cid.instance.def)?,
|
||||||
};
|
};
|
||||||
if let Some(index) = cid.promoted {
|
if let Some(index) = cid.promoted {
|
||||||
mir = &mir.promoted[index];
|
mir = &mir.promoted[index];
|
||||||
}
|
}
|
||||||
let layout = ecx.layout_of(mir.return_ty().subst(tcx, cid.instance.substs))?;
|
let layout = ecx.layout_of(mir.return_ty().subst(tcx, cid.instance.substs))?;
|
||||||
assert!(!layout.is_unsized());
|
assert!(!layout.is_unsized());
|
||||||
let ptr = ecx.memory.allocate(
|
let ptr = ecx.memory.allocate(
|
||||||
layout.size.bytes(),
|
layout.size.bytes(),
|
||||||
layout.align,
|
layout.align,
|
||||||
None,
|
None,
|
||||||
)?;
|
)?;
|
||||||
let internally_mutable = !layout.ty.is_freeze(tcx, param_env, mir.span);
|
let internally_mutable = !layout.ty.is_freeze(tcx, param_env, mir.span);
|
||||||
let mutability = tcx.is_static(cid.instance.def_id());
|
let is_static = tcx.is_static(cid.instance.def_id());
|
||||||
let mutability = if mutability == Some(hir::Mutability::MutMutable) || internally_mutable {
|
let mutability = if is_static == Some(hir::Mutability::MutMutable) || internally_mutable {
|
||||||
Mutability::Mutable
|
Mutability::Mutable
|
||||||
} else {
|
} else {
|
||||||
Mutability::Immutable
|
Mutability::Immutable
|
||||||
};
|
};
|
||||||
let cleanup = StackPopCleanup::MarkStatic(mutability);
|
let cleanup = StackPopCleanup::MarkStatic(mutability);
|
||||||
let name = ty::tls::with(|tcx| tcx.item_path_str(cid.instance.def_id()));
|
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));
|
let prom = cid.promoted.map_or(String::new(), |p| format!("::promoted[{:?}]", p));
|
||||||
trace!("const_eval: pushing stack frame for global: {}{}", name, prom);
|
trace!("const_eval: pushing stack frame for global: {}{}", name, prom);
|
||||||
assert!(mir.arg_count == 0);
|
assert!(mir.arg_count == 0);
|
||||||
ecx.push_stack_frame(
|
ecx.push_stack_frame(
|
||||||
cid.instance,
|
cid.instance,
|
||||||
mir.span,
|
mir.span,
|
||||||
mir,
|
mir,
|
||||||
Place::from_ptr(ptr, layout.align),
|
Place::from_ptr(ptr, layout.align),
|
||||||
cleanup,
|
cleanup,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
while ecx.step()? {}
|
while ecx.step()? {}
|
||||||
let ptr = ptr.into();
|
let ptr = ptr.into();
|
||||||
// always try to read the value and report errors
|
// always try to read the value and report errors
|
||||||
let value = match ecx.try_read_value(ptr, layout.align, layout.ty)? {
|
let value = match ecx.try_read_value(ptr, layout.align, layout.ty)? {
|
||||||
Some(val) => val,
|
Some(val) if is_static.is_none() => val,
|
||||||
// point at the allocation
|
// point at the allocation
|
||||||
_ => Value::ByRef(ptr, layout.align),
|
_ => Value::ByRef(ptr, layout.align),
|
||||||
};
|
};
|
||||||
Ok((value, ptr, layout.ty))
|
Ok((value, ptr, layout.ty))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct CompileTimeEvaluator;
|
pub struct CompileTimeEvaluator;
|
||||||
|
@ -12,11 +12,17 @@
|
|||||||
|
|
||||||
#![crate_type = "lib"]
|
#![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]
|
#[no_mangle]
|
||||||
#[link_section = ".test_one"]
|
#[link_section = ".test_one"]
|
||||||
|
#[cfg(target_endian = "little")]
|
||||||
pub static VAR1: u32 = 1;
|
pub static VAR1: u32 = 1;
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
#[link_section = ".test_one"]
|
||||||
|
#[cfg(target_endian = "big")]
|
||||||
|
pub static VAR1: u32 = 0x01000000;
|
||||||
|
|
||||||
pub enum E {
|
pub enum E {
|
||||||
A(u32),
|
A(u32),
|
||||||
B(f32)
|
B(f32)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user