Auto merge of #52597 - oli-obk:promotion_simplify, r=nagisa
Promoteds are statics and statics have a place, not just a value r? @eddyb This makes everything around promoteds a little simpler
This commit is contained in:
commit
6a3db033ad
57 changed files with 376 additions and 585 deletions
|
|
@ -242,9 +242,11 @@ pub fn get_static(cx: &CodegenCx, def_id: DefId) -> ValueRef {
|
|||
g
|
||||
}
|
||||
|
||||
pub fn codegen_static<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
|
||||
def_id: DefId,
|
||||
is_mutable: bool) {
|
||||
pub fn codegen_static<'a, 'tcx>(
|
||||
cx: &CodegenCx<'a, 'tcx>,
|
||||
def_id: DefId,
|
||||
is_mutable: bool,
|
||||
) {
|
||||
unsafe {
|
||||
let attrs = cx.tcx.codegen_fn_attrs(def_id);
|
||||
|
||||
|
|
|
|||
|
|
@ -507,14 +507,40 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
|
|||
// promotes any complex rvalues to constants.
|
||||
if i == 2 && intrinsic.unwrap().starts_with("simd_shuffle") {
|
||||
match *arg {
|
||||
// The shuffle array argument is usually not an explicit constant,
|
||||
// but specified directly in the code. This means it gets promoted
|
||||
// and we can then extract the value by evaluating the promoted.
|
||||
mir::Operand::Copy(mir::Place::Promoted(box(index, ty))) |
|
||||
mir::Operand::Move(mir::Place::Promoted(box(index, ty))) => {
|
||||
let param_env = ty::ParamEnv::reveal_all();
|
||||
let cid = mir::interpret::GlobalId {
|
||||
instance: self.instance,
|
||||
promoted: Some(index),
|
||||
};
|
||||
let c = bx.tcx().const_eval(param_env.and(cid));
|
||||
let (llval, ty) = self.simd_shuffle_indices(
|
||||
&bx,
|
||||
terminator.source_info.span,
|
||||
ty,
|
||||
c,
|
||||
);
|
||||
return OperandRef {
|
||||
val: Immediate(llval),
|
||||
layout: bx.cx.layout_of(ty),
|
||||
};
|
||||
|
||||
},
|
||||
mir::Operand::Copy(_) |
|
||||
mir::Operand::Move(_) => {
|
||||
span_bug!(span, "shuffle indices must be constant");
|
||||
}
|
||||
mir::Operand::Constant(ref constant) => {
|
||||
let c = self.eval_mir_constant(&bx, constant);
|
||||
let (llval, ty) = self.simd_shuffle_indices(
|
||||
&bx,
|
||||
constant,
|
||||
constant.span,
|
||||
constant.ty,
|
||||
c,
|
||||
);
|
||||
return OperandRef {
|
||||
val: Immediate(llval),
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ use consts;
|
|||
use type_of::LayoutLlvmExt;
|
||||
use type_::Type;
|
||||
use syntax::ast::Mutability;
|
||||
use syntax::codemap::Span;
|
||||
|
||||
use super::super::callee;
|
||||
use super::FunctionCx;
|
||||
|
|
@ -117,13 +118,12 @@ pub fn const_alloc_to_llvm(cx: &CodegenCx, alloc: &Allocation) -> ValueRef {
|
|||
|
||||
pub fn codegen_static_initializer<'a, 'tcx>(
|
||||
cx: &CodegenCx<'a, 'tcx>,
|
||||
def_id: DefId)
|
||||
-> Result<(ValueRef, &'tcx Allocation), Lrc<ConstEvalErr<'tcx>>>
|
||||
{
|
||||
def_id: DefId,
|
||||
) -> Result<(ValueRef, &'tcx Allocation), Lrc<ConstEvalErr<'tcx>>> {
|
||||
let instance = ty::Instance::mono(cx.tcx, def_id);
|
||||
let cid = GlobalId {
|
||||
instance,
|
||||
promoted: None
|
||||
promoted: None,
|
||||
};
|
||||
let param_env = ty::ParamEnv::reveal_all();
|
||||
let static_ = cx.tcx.const_eval(param_env.and(cid))?;
|
||||
|
|
@ -161,28 +161,19 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
|
|||
bx: &Builder<'a, 'tcx>,
|
||||
constant: &mir::Constant<'tcx>,
|
||||
) -> Result<&'tcx ty::Const<'tcx>, Lrc<ConstEvalErr<'tcx>>> {
|
||||
match constant.literal {
|
||||
mir::Literal::Promoted { index } => {
|
||||
let param_env = ty::ParamEnv::reveal_all();
|
||||
let cid = mir::interpret::GlobalId {
|
||||
instance: self.instance,
|
||||
promoted: Some(index),
|
||||
};
|
||||
bx.tcx().const_eval(param_env.and(cid))
|
||||
}
|
||||
mir::Literal::Value { value } => {
|
||||
Ok(self.monomorphize(&value))
|
||||
}
|
||||
}.and_then(|c| self.fully_evaluate(bx, c))
|
||||
let c = self.monomorphize(&constant.literal);
|
||||
self.fully_evaluate(bx, c)
|
||||
}
|
||||
|
||||
/// process constant containing SIMD shuffle indices
|
||||
pub fn simd_shuffle_indices(
|
||||
&mut self,
|
||||
bx: &Builder<'a, 'tcx>,
|
||||
constant: &mir::Constant<'tcx>,
|
||||
span: Span,
|
||||
ty: Ty<'tcx>,
|
||||
constant: Result<&'tcx ty::Const<'tcx>, Lrc<ConstEvalErr<'tcx>>>,
|
||||
) -> (ValueRef, Ty<'tcx>) {
|
||||
self.eval_mir_constant(bx, constant)
|
||||
constant
|
||||
.and_then(|c| {
|
||||
let field_ty = c.ty.builtin_index().unwrap();
|
||||
let fields = match c.ty.sty {
|
||||
|
|
@ -217,11 +208,11 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
|
|||
})
|
||||
.unwrap_or_else(|e| {
|
||||
e.report_as_error(
|
||||
bx.tcx().at(constant.span),
|
||||
bx.tcx().at(span),
|
||||
"could not evaluate shuffle_indices at compile time",
|
||||
);
|
||||
// We've errored, so we don't have to produce working code.
|
||||
let ty = self.monomorphize(&constant.ty);
|
||||
let ty = self.monomorphize(&ty);
|
||||
let llty = bx.cx.layout_of(ty).llvm_type(bx.cx);
|
||||
(C_undef(llty), ty)
|
||||
})
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use llvm::{ValueRef, LLVMConstInBoundsGEP};
|
||||
use llvm::ValueRef;
|
||||
use rustc::mir::interpret::ConstEvalErr;
|
||||
use rustc::mir;
|
||||
use rustc::mir::interpret::ConstValue;
|
||||
|
|
@ -22,14 +22,12 @@ use common::{CodegenCx, C_undef, C_usize};
|
|||
use builder::{Builder, MemFlags};
|
||||
use value::Value;
|
||||
use type_of::LayoutLlvmExt;
|
||||
use type_::Type;
|
||||
use consts;
|
||||
|
||||
use std::fmt;
|
||||
use std::ptr;
|
||||
|
||||
use super::{FunctionCx, LocalRef};
|
||||
use super::constant::{scalar_to_llvm, const_alloc_to_llvm};
|
||||
use super::constant::scalar_to_llvm;
|
||||
use super::place::PlaceRef;
|
||||
|
||||
/// The representation of a Rust value. The enum variant is in fact
|
||||
|
|
@ -139,16 +137,7 @@ impl<'a, 'tcx> OperandRef<'tcx> {
|
|||
OperandValue::Pair(a_llval, b_llval)
|
||||
},
|
||||
ConstValue::ByRef(alloc, offset) => {
|
||||
let init = const_alloc_to_llvm(bx.cx, alloc);
|
||||
let base_addr = consts::addr_of(bx.cx, init, layout.align, "byte_str");
|
||||
|
||||
let llval = unsafe { LLVMConstInBoundsGEP(
|
||||
consts::bitcast(base_addr, Type::i8p(bx.cx)),
|
||||
&C_usize(bx.cx, offset.bytes()),
|
||||
1,
|
||||
)};
|
||||
let llval = consts::bitcast(llval, layout.llvm_type(bx.cx).ptr_to());
|
||||
return Ok(PlaceRef::new_sized(llval, layout, alloc.align).load(bx));
|
||||
return Ok(PlaceRef::from_const_alloc(bx, layout, alloc, offset).load(bx));
|
||||
},
|
||||
};
|
||||
|
||||
|
|
@ -409,20 +398,12 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
|
|||
self.eval_mir_constant(bx, constant)
|
||||
.and_then(|c| OperandRef::from_const(bx, c))
|
||||
.unwrap_or_else(|err| {
|
||||
match constant.literal {
|
||||
mir::Literal::Promoted { .. } => {
|
||||
// this is unreachable as long as runtime
|
||||
// and compile-time agree on values
|
||||
// With floats that won't always be true
|
||||
// so we generate an abort below
|
||||
},
|
||||
mir::Literal::Value { .. } => {
|
||||
err.report_as_error(
|
||||
bx.tcx().at(constant.span),
|
||||
"could not evaluate constant operand",
|
||||
);
|
||||
},
|
||||
}
|
||||
err.report_as_error(
|
||||
bx.tcx().at(constant.span),
|
||||
"could not evaluate constant operand",
|
||||
);
|
||||
// Allow RalfJ to sleep soundly knowing that even refactorings that remove
|
||||
// the above error (or silence it under some conditions) will not cause UB
|
||||
let fnname = bx.cx.get_intrinsic(&("llvm.trap"));
|
||||
bx.call(fnname, &[], None);
|
||||
// We've errored, so we don't have to produce working code.
|
||||
|
|
|
|||
|
|
@ -8,9 +8,9 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use llvm::{self, ValueRef};
|
||||
use llvm::{self, ValueRef, LLVMConstInBoundsGEP};
|
||||
use rustc::ty::{self, Ty};
|
||||
use rustc::ty::layout::{self, Align, TyLayout, LayoutOf};
|
||||
use rustc::ty::layout::{self, Align, TyLayout, LayoutOf, Size};
|
||||
use rustc::mir;
|
||||
use rustc::mir::tcx::PlaceTy;
|
||||
use rustc_data_structures::indexed_vec::Idx;
|
||||
|
|
@ -22,6 +22,7 @@ use type_of::LayoutLlvmExt;
|
|||
use type_::Type;
|
||||
use value::Value;
|
||||
use glue;
|
||||
use mir::constant::const_alloc_to_llvm;
|
||||
|
||||
use std::ptr;
|
||||
|
||||
|
|
@ -56,6 +57,24 @@ impl<'a, 'tcx> PlaceRef<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn from_const_alloc(
|
||||
bx: &Builder<'a, 'tcx>,
|
||||
layout: TyLayout<'tcx>,
|
||||
alloc: &mir::interpret::Allocation,
|
||||
offset: Size,
|
||||
) -> PlaceRef<'tcx> {
|
||||
let init = const_alloc_to_llvm(bx.cx, alloc);
|
||||
let base_addr = consts::addr_of(bx.cx, init, layout.align, "byte_str");
|
||||
|
||||
let llval = unsafe { LLVMConstInBoundsGEP(
|
||||
consts::bitcast(base_addr, Type::i8p(bx.cx)),
|
||||
&C_usize(bx.cx, offset.bytes()),
|
||||
1,
|
||||
)};
|
||||
let llval = consts::bitcast(llval, layout.llvm_type(bx.cx).ptr_to());
|
||||
PlaceRef::new_sized(llval, layout, alloc.align)
|
||||
}
|
||||
|
||||
pub fn alloca(bx: &Builder<'a, 'tcx>, layout: TyLayout<'tcx>, name: &str)
|
||||
-> PlaceRef<'tcx> {
|
||||
debug!("alloca({:?}: {:?})", name, layout);
|
||||
|
|
@ -421,6 +440,32 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
|
|||
|
||||
let result = match *place {
|
||||
mir::Place::Local(_) => bug!(), // handled above
|
||||
mir::Place::Promoted(box (index, ty)) => {
|
||||
let param_env = ty::ParamEnv::reveal_all();
|
||||
let cid = mir::interpret::GlobalId {
|
||||
instance: self.instance,
|
||||
promoted: Some(index),
|
||||
};
|
||||
let layout = cx.layout_of(self.monomorphize(&ty));
|
||||
match bx.tcx().const_eval(param_env.and(cid)) {
|
||||
Ok(val) => match val.val {
|
||||
mir::interpret::ConstValue::ByRef(alloc, offset) => {
|
||||
PlaceRef::from_const_alloc(bx, layout, alloc, offset)
|
||||
}
|
||||
_ => bug!("promoteds should have an allocation: {:?}", val),
|
||||
},
|
||||
Err(_) => {
|
||||
// this is unreachable as long as runtime
|
||||
// and compile-time agree on values
|
||||
// With floats that won't always be true
|
||||
// so we generate an abort
|
||||
let fnname = bx.cx.get_intrinsic(&("llvm.trap"));
|
||||
bx.call(fnname, &[], None);
|
||||
let llval = C_undef(layout.llvm_type(bx.cx).ptr_to());
|
||||
PlaceRef::new_sized(llval, layout, layout.align)
|
||||
}
|
||||
}
|
||||
}
|
||||
mir::Place::Static(box mir::Static { def_id, ty }) => {
|
||||
let layout = cx.layout_of(self.monomorphize(&ty));
|
||||
PlaceRef::new_sized(consts::get_static(cx, def_id), layout, layout.align)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue