Skip to content

Commit 8b99c61

Browse files
committed
Ensure that statics are always ByRef
1 parent c95e1cc commit 8b99c61

File tree

3 files changed

+69
-133
lines changed

3 files changed

+69
-133
lines changed

src/librustc_codegen_llvm/mir/constant.rs

Lines changed: 3 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -81,49 +81,6 @@ pub fn primval_to_llvm(cx: &CodegenCx,
8181
}
8282
}
8383

84-
fn const_value_to_llvm<'tcx>(cx: &CodegenCx<'_, 'tcx>, val: ConstValue, ty: Ty<'tcx>) -> ValueRef {
85-
let layout = cx.layout_of(ty);
86-
87-
if layout.is_zst() {
88-
return C_undef(layout.immediate_llvm_type(cx));
89-
}
90-
91-
match val {
92-
ConstValue::ByVal(x) => {
93-
let scalar = match layout.abi {
94-
layout::Abi::Scalar(ref x) => x,
95-
_ => bug!("const_value_to_llvm: invalid ByVal layout: {:#?}", layout)
96-
};
97-
primval_to_llvm(
98-
cx,
99-
x,
100-
scalar,
101-
layout.immediate_llvm_type(cx),
102-
)
103-
},
104-
ConstValue::ByValPair(a, b) => {
105-
let (a_scalar, b_scalar) = match layout.abi {
106-
layout::Abi::ScalarPair(ref a, ref b) => (a, b),
107-
_ => bug!("const_value_to_llvm: invalid ByValPair layout: {:#?}", layout)
108-
};
109-
let a_llval = primval_to_llvm(
110-
cx,
111-
a,
112-
a_scalar,
113-
layout.scalar_pair_element_llvm_type(cx, 0),
114-
);
115-
let b_llval = primval_to_llvm(
116-
cx,
117-
b,
118-
b_scalar,
119-
layout.scalar_pair_element_llvm_type(cx, 1),
120-
);
121-
C_struct(cx, &[a_llval, b_llval], false)
122-
},
123-
ConstValue::ByRef(alloc) => const_alloc_to_llvm(cx, alloc),
124-
}
125-
}
126-
12784
pub fn const_alloc_to_llvm(cx: &CodegenCx, alloc: &Allocation) -> ValueRef {
12885
let mut llvals = Vec::with_capacity(alloc.relocations.len() + 1);
12986
let layout = cx.data_layout();
@@ -171,11 +128,11 @@ pub fn codegen_static_initializer<'a, 'tcx>(
171128
let param_env = ty::ParamEnv::reveal_all();
172129
let static_ = cx.tcx.const_eval(param_env.and(cid))?;
173130

174-
let val = match static_.val {
175-
ConstVal::Value(val) => val,
131+
let alloc = match static_.val {
132+
ConstVal::Value(ConstValue::ByRef(alloc)) => alloc,
176133
_ => bug!("static const eval returned {:#?}", static_),
177134
};
178-
Ok(const_value_to_llvm(cx, val, static_.ty))
135+
Ok(const_alloc_to_llvm(cx, alloc))
179136
}
180137

181138
impl<'a, 'tcx> FunctionCx<'a, 'tcx> {

src/librustc_mir/interpret/const_eval.rs

Lines changed: 59 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -98,59 +98,32 @@ pub fn value_to_const_value<'tcx>(
9898
mut val: Value,
9999
ty: Ty<'tcx>,
100100
) -> &'tcx ty::Const<'tcx> {
101-
let result = (|| {
101+
let val = (|| {
102102
// Convert to ByVal or ByValPair if possible
103103
if let Value::ByRef(ptr, align) = val {
104104
if let Some(read_val) = ecx.try_read_value(ptr, align, ty)? {
105105
val = read_val;
106106
}
107107
}
108-
109-
let layout = ecx.tcx.layout_of(ty::ParamEnv::reveal_all().and(ty)).unwrap();
110-
111-
if layout.is_zst() {
112-
return Ok(ty::Const::from_const_value(
113-
ecx.tcx.tcx,
114-
ConstValue::ByVal(PrimVal::Undef),
115-
ty));
116-
}
117-
118-
let val = match layout.abi {
119-
layout::Abi::Scalar(..) => {
120-
if let Value::ByVal(val) = val {
121-
ConstValue::ByVal(val)
122-
} else {
123-
bug!("expected ByVal value, got {:?}", val);
124-
}
125-
}
126-
layout::Abi::ScalarPair(..) => {
127-
if let Value::ByValPair(a, b) = val {
128-
ConstValue::ByValPair(a, b)
129-
} else {
130-
bug!("expected ByValPair value, got {:?}", val);
131-
}
108+
match val {
109+
Value::ByVal(val) => Ok(ConstValue::ByVal(val)),
110+
Value::ByValPair(a, b) => Ok(ConstValue::ByValPair(a, b)),
111+
Value::ByRef(ptr, align) => {
112+
let ptr = ptr.primval.to_ptr().unwrap();
113+
assert_eq!(ptr.offset, 0);
114+
let alloc = ecx.memory.get(ptr.alloc_id)?;
115+
assert!(alloc.align.abi() >= layout.align.abi());
116+
assert!(alloc.bytes.len() as u64 == layout.size.bytes());
117+
let mut alloc = alloc.clone();
118+
// The align field is meaningless for values, so just use the layout's align
119+
alloc.align = layout.align;
120+
let alloc = ecx.tcx.intern_const_alloc(alloc);
121+
Ok(ConstValue::ByRef(alloc))
132122
}
133-
_ => {
134-
if let Value::ByRef(ptr, _) = val {
135-
let ptr = ptr.primval.to_ptr().unwrap();
136-
assert_eq!(ptr.offset, 0);
137-
let alloc = ecx.memory.get(ptr.alloc_id)?;
138-
assert!(alloc.align.abi() >= layout.align.abi());
139-
assert!(alloc.bytes.len() as u64 == layout.size.bytes());
140-
let mut alloc = alloc.clone();
141-
// The align field is meaningless for values, so just use the layout's align
142-
alloc.align = layout.align;
143-
let alloc = ecx.tcx.intern_const_alloc(alloc);
144-
ConstValue::ByRef(alloc)
145-
} else {
146-
bug!("expected ByRef value, got {:?}", val);
147-
}
148-
},
149-
};
150-
Ok(ty::Const::from_const_value(ecx.tcx.tcx, val, ty))
123+
}
151124
})();
152125
match result {
153-
Ok(v) => v,
126+
Ok(v) => ty::Const::from_const_value(tcx, val, ty),
154127
Err(mut err) => {
155128
ecx.report(&mut err, true, None);
156129
bug!("miri error occured when converting Value to ConstValue")
@@ -182,49 +155,49 @@ fn eval_body_using_ecx<'a, 'mir, 'tcx>(
182155
) -> EvalResult<'tcx, (Value, Pointer, Ty<'tcx>)> {
183156
debug!("eval_body: {:?}, {:?}", cid, param_env);
184157
let tcx = ecx.tcx.tcx;
185-
let mut mir = match mir {
186-
Some(mir) => mir,
187-
None => ecx.load_mir(cid.instance.def)?,
188-
};
189-
if let Some(index) = cid.promoted {
190-
mir = &mir.promoted[index];
191-
}
192-
let layout = ecx.layout_of(mir.return_ty().subst(tcx, cid.instance.substs))?;
193-
assert!(!layout.is_unsized());
194-
let ptr = ecx.memory.allocate(
195-
layout.size.bytes(),
196-
layout.align,
197-
None,
198-
)?;
199-
let internally_mutable = !layout.ty.is_freeze(tcx, param_env, mir.span);
200-
let mutability = tcx.is_static(cid.instance.def_id());
201-
let mutability = if mutability == Some(hir::Mutability::MutMutable) || internally_mutable {
202-
Mutability::Mutable
203-
} else {
204-
Mutability::Immutable
205-
};
206-
let cleanup = StackPopCleanup::MarkStatic(mutability);
207-
let name = ty::tls::with(|tcx| tcx.item_path_str(cid.instance.def_id()));
208-
let prom = cid.promoted.map_or(String::new(), |p| format!("::promoted[{:?}]", p));
209-
trace!("const_eval: pushing stack frame for global: {}{}", name, prom);
210-
assert!(mir.arg_count == 0);
211-
ecx.push_stack_frame(
212-
cid.instance,
213-
mir.span,
214-
mir,
215-
Place::from_ptr(ptr, layout.align),
216-
cleanup,
217-
)?;
158+
let mut mir = match mir {
159+
Some(mir) => mir,
160+
None => ecx.load_mir(cid.instance.def)?,
161+
};
162+
if let Some(index) = cid.promoted {
163+
mir = &mir.promoted[index];
164+
}
165+
let layout = ecx.layout_of(mir.return_ty().subst(tcx, cid.instance.substs))?;
166+
assert!(!layout.is_unsized());
167+
let ptr = ecx.memory.allocate(
168+
layout.size.bytes(),
169+
layout.align,
170+
None,
171+
)?;
172+
let internally_mutable = !layout.ty.is_freeze(tcx, param_env, mir.span);
173+
let is_static = tcx.is_static(cid.instance.def_id());
174+
let mutability = if is_static == Some(hir::Mutability::MutMutable) || internally_mutable {
175+
Mutability::Mutable
176+
} else {
177+
Mutability::Immutable
178+
};
179+
let cleanup = StackPopCleanup::MarkStatic(mutability);
180+
let name = ty::tls::with(|tcx| tcx.item_path_str(cid.instance.def_id()));
181+
let prom = cid.promoted.map_or(String::new(), |p| format!("::promoted[{:?}]", p));
182+
trace!("const_eval: pushing stack frame for global: {}{}", name, prom);
183+
assert!(mir.arg_count == 0);
184+
ecx.push_stack_frame(
185+
cid.instance,
186+
mir.span,
187+
mir,
188+
Place::from_ptr(ptr, layout.align),
189+
cleanup,
190+
)?;
218191

219-
while ecx.step()? {}
220-
let ptr = ptr.into();
221-
// always try to read the value and report errors
222-
let value = match ecx.try_read_value(ptr, layout.align, layout.ty)? {
223-
Some(val) => val,
224-
// point at the allocation
225-
_ => Value::ByRef(ptr, layout.align),
226-
};
227-
Ok((value, ptr, layout.ty))
192+
while ecx.step()? {}
193+
let ptr = ptr.into();
194+
// always try to read the value and report errors
195+
let value = match ecx.try_read_value(ptr, layout.align, layout.ty)? {
196+
Some(val) if is_static.is_none() => val,
197+
// point at the allocation
198+
_ => Value::ByRef(ptr, layout.align),
199+
};
200+
Ok((value, ptr, layout.ty))
228201
}
229202

230203
pub struct CompileTimeEvaluator;

src/test/codegen/link_section.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,17 @@
1212

1313
#![crate_type = "lib"]
1414

15-
// CHECK: @VAR1 = constant i32 1, section ".test_one"
15+
// CHECK: @VAR1 = constant <{ [4 x i8] }> <{ [4 x i8] c"\01\00\00\00" }>, section ".test_one"
1616
#[no_mangle]
1717
#[link_section = ".test_one"]
18+
#[cfg(target_endian = "little")]
1819
pub static VAR1: u32 = 1;
1920

21+
#[no_mangle]
22+
#[link_section = ".test_one"]
23+
#[cfg(target_endian = "big")]
24+
pub static VAR1: u32 = 0x01000000;
25+
2026
pub enum E {
2127
A(u32),
2228
B(f32)

0 commit comments

Comments
 (0)