Auto merge of #56198 - bjorn3:cg_ssa_refactor, r=eddyb
Refactor rustc_codegen_ssa cc #56108 (not all things are done yet) This removes an unsafe method from cg_ssa. r? @eddyb cc @sunfishcode
This commit is contained in:
commit
21f2684950
38 changed files with 537 additions and 526 deletions
|
|
@ -192,7 +192,7 @@ pub fn unsized_info<'tcx, Cx: CodegenMethods<'tcx>>(
|
|||
(_, &ty::Dynamic(ref data, ..)) => {
|
||||
let vtable_ptr = cx.layout_of(cx.tcx().mk_mut_ptr(target))
|
||||
.field(cx, FAT_PTR_EXTRA);
|
||||
cx.static_ptrcast(meth::get_vtable(cx, source, data.principal()),
|
||||
cx.const_ptrcast(meth::get_vtable(cx, source, data.principal()),
|
||||
cx.backend_type(vtable_ptr))
|
||||
}
|
||||
_ => bug!("unsized_info: invalid unsizing {:?} -> {:?}",
|
||||
|
|
@ -366,14 +366,6 @@ pub fn wants_msvc_seh(sess: &Session) -> bool {
|
|||
sess.target.target.options.is_like_msvc
|
||||
}
|
||||
|
||||
pub fn call_assume<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
|
||||
bx: &mut Bx,
|
||||
val: Bx::Value
|
||||
) {
|
||||
let assume_intrinsic = bx.cx().get_intrinsic("llvm.assume");
|
||||
bx.call(assume_intrinsic, &[val], None);
|
||||
}
|
||||
|
||||
pub fn from_immediate<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
|
||||
bx: &mut Bx,
|
||||
val: Bx::Value
|
||||
|
|
|
|||
|
|
@ -194,7 +194,7 @@ fn shift_mask_rhs<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
|
|||
bx: &mut Bx,
|
||||
rhs: Bx::Value
|
||||
) -> Bx::Value {
|
||||
let rhs_llty = bx.cx().val_ty(rhs);
|
||||
let rhs_llty = bx.val_ty(rhs);
|
||||
let shift_val = shift_mask_val(bx, rhs_llty, rhs_llty, false);
|
||||
bx.and(rhs, shift_val)
|
||||
}
|
||||
|
|
@ -205,25 +205,25 @@ pub fn shift_mask_val<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
|
|||
mask_llty: Bx::Type,
|
||||
invert: bool
|
||||
) -> Bx::Value {
|
||||
let kind = bx.cx().type_kind(llty);
|
||||
let kind = bx.type_kind(llty);
|
||||
match kind {
|
||||
TypeKind::Integer => {
|
||||
// i8/u8 can shift by at most 7, i16/u16 by at most 15, etc.
|
||||
let val = bx.cx().int_width(llty) - 1;
|
||||
let val = bx.int_width(llty) - 1;
|
||||
if invert {
|
||||
bx.cx().const_int(mask_llty, !val as i64)
|
||||
bx.const_int(mask_llty, !val as i64)
|
||||
} else {
|
||||
bx.cx().const_uint(mask_llty, val)
|
||||
bx.const_uint(mask_llty, val)
|
||||
}
|
||||
},
|
||||
TypeKind::Vector => {
|
||||
let mask = shift_mask_val(
|
||||
bx,
|
||||
bx.cx().element_type(llty),
|
||||
bx.cx().element_type(mask_llty),
|
||||
bx.element_type(llty),
|
||||
bx.element_type(mask_llty),
|
||||
invert
|
||||
);
|
||||
bx.vector_splat(bx.cx().vector_length(mask_llty), mask)
|
||||
bx.vector_splat(bx.vector_length(mask_llty), mask)
|
||||
},
|
||||
_ => bug!("shift_mask_val: expected Integer or Vector, found {:?}", kind),
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,22 +23,21 @@ impl<D> FunctionDebugContext<D> {
|
|||
match *self {
|
||||
FunctionDebugContext::RegularContext(ref data) => data,
|
||||
FunctionDebugContext::DebugInfoDisabled => {
|
||||
span_bug!(span, "{}", FunctionDebugContext::<D>::debuginfo_disabled_message());
|
||||
span_bug!(
|
||||
span,
|
||||
"debuginfo: Error trying to access FunctionDebugContext \
|
||||
although debug info is disabled!",
|
||||
);
|
||||
}
|
||||
FunctionDebugContext::FunctionWithoutDebugInfo => {
|
||||
span_bug!(span, "{}", FunctionDebugContext::<D>::should_be_ignored_message());
|
||||
span_bug!(
|
||||
span,
|
||||
"debuginfo: Error trying to access FunctionDebugContext \
|
||||
for function that should be ignored by debug info!",
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn debuginfo_disabled_message() -> &'static str {
|
||||
"debuginfo: Error trying to access FunctionDebugContext although debug info is disabled!"
|
||||
}
|
||||
|
||||
fn should_be_ignored_message() -> &'static str {
|
||||
"debuginfo: Error trying to access FunctionDebugContext for function that should be \
|
||||
ignored by debug info!"
|
||||
}
|
||||
}
|
||||
|
||||
/// Enables emitting source locations for the given functions.
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@ use std;
|
|||
|
||||
use common::IntPredicate;
|
||||
use meth;
|
||||
use rustc::ty::layout::LayoutOf;
|
||||
use rustc::ty::{self, Ty};
|
||||
use traits::*;
|
||||
|
||||
|
|
@ -25,12 +24,12 @@ pub fn size_and_align_of_dst<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
|
|||
t: Ty<'tcx>,
|
||||
info: Option<Bx::Value>
|
||||
) -> (Bx::Value, Bx::Value) {
|
||||
let layout = bx.cx().layout_of(t);
|
||||
let layout = bx.layout_of(t);
|
||||
debug!("size_and_align_of_dst(ty={}, info={:?}): layout: {:?}",
|
||||
t, info, layout);
|
||||
if !layout.is_unsized() {
|
||||
let size = bx.cx().const_usize(layout.size.bytes());
|
||||
let align = bx.cx().const_usize(layout.align.abi.bytes());
|
||||
let size = bx.const_usize(layout.size.bytes());
|
||||
let align = bx.const_usize(layout.align.abi.bytes());
|
||||
return (size, align);
|
||||
}
|
||||
match t.sty {
|
||||
|
|
@ -40,11 +39,11 @@ pub fn size_and_align_of_dst<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
|
|||
(meth::SIZE.get_usize(bx, vtable), meth::ALIGN.get_usize(bx, vtable))
|
||||
}
|
||||
ty::Slice(_) | ty::Str => {
|
||||
let unit = layout.field(bx.cx(), 0);
|
||||
let unit = layout.field(bx, 0);
|
||||
// The info in this case is the length of the str, so the size is that
|
||||
// times the unit size.
|
||||
(bx.mul(info.unwrap(), bx.cx().const_usize(unit.size.bytes())),
|
||||
bx.cx().const_usize(unit.align.abi.bytes()))
|
||||
(bx.mul(info.unwrap(), bx.const_usize(unit.size.bytes())),
|
||||
bx.const_usize(unit.align.abi.bytes()))
|
||||
}
|
||||
_ => {
|
||||
// First get the size of all statically known fields.
|
||||
|
|
@ -58,12 +57,12 @@ pub fn size_and_align_of_dst<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
|
|||
let sized_align = layout.align.abi.bytes();
|
||||
debug!("DST {} statically sized prefix size: {} align: {}",
|
||||
t, sized_size, sized_align);
|
||||
let sized_size = bx.cx().const_usize(sized_size);
|
||||
let sized_align = bx.cx().const_usize(sized_align);
|
||||
let sized_size = bx.const_usize(sized_size);
|
||||
let sized_align = bx.const_usize(sized_align);
|
||||
|
||||
// Recurse to get the size of the dynamically sized field (must be
|
||||
// the last field).
|
||||
let field_ty = layout.field(bx.cx(), i).ty;
|
||||
let field_ty = layout.field(bx, i).ty;
|
||||
let (unsized_size, mut unsized_align) = size_and_align_of_dst(bx, field_ty, info);
|
||||
|
||||
// FIXME (#26403, #27023): We should be adding padding
|
||||
|
|
@ -85,12 +84,12 @@ pub fn size_and_align_of_dst<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
|
|||
|
||||
// Choose max of two known alignments (combined value must
|
||||
// be aligned according to more restrictive of the two).
|
||||
let align = match (bx.cx().const_to_opt_u128(sized_align, false),
|
||||
bx.cx().const_to_opt_u128(unsized_align, false)) {
|
||||
let align = match (bx.const_to_opt_u128(sized_align, false),
|
||||
bx.const_to_opt_u128(unsized_align, false)) {
|
||||
(Some(sized_align), Some(unsized_align)) => {
|
||||
// If both alignments are constant, (the sized_align should always be), then
|
||||
// pick the correct alignment statically.
|
||||
bx.cx().const_usize(std::cmp::max(sized_align, unsized_align) as u64)
|
||||
bx.const_usize(std::cmp::max(sized_align, unsized_align) as u64)
|
||||
}
|
||||
_ => {
|
||||
let cmp = bx.icmp(IntPredicate::IntUGT, sized_align, unsized_align);
|
||||
|
|
@ -108,7 +107,7 @@ pub fn size_and_align_of_dst<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
|
|||
// emulated via the semi-standard fast bit trick:
|
||||
//
|
||||
// `(size + (align-1)) & -align`
|
||||
let one = bx.cx().const_usize(1);
|
||||
let one = bx.const_usize(1);
|
||||
let addend = bx.sub(align, one);
|
||||
let add = bx.add(size, addend);
|
||||
let neg = bx.neg(align);
|
||||
|
|
|
|||
|
|
@ -39,10 +39,10 @@ impl<'a, 'tcx: 'a> VirtualIndex {
|
|||
|
||||
let llvtable = bx.pointercast(
|
||||
llvtable,
|
||||
bx.cx().type_ptr_to(bx.cx().fn_ptr_backend_type(fn_ty))
|
||||
bx.type_ptr_to(bx.fn_ptr_backend_type(fn_ty))
|
||||
);
|
||||
let ptr_align = bx.tcx().data_layout.pointer_align.abi;
|
||||
let gep = bx.inbounds_gep(llvtable, &[bx.cx().const_usize(self.0)]);
|
||||
let gep = bx.inbounds_gep(llvtable, &[bx.const_usize(self.0)]);
|
||||
let ptr = bx.load(gep, ptr_align);
|
||||
bx.nonnull_metadata(ptr);
|
||||
// Vtable loads are invariant
|
||||
|
|
@ -58,9 +58,9 @@ impl<'a, 'tcx: 'a> VirtualIndex {
|
|||
// Load the data pointer from the object.
|
||||
debug!("get_int({:?}, {:?})", llvtable, self);
|
||||
|
||||
let llvtable = bx.pointercast(llvtable, bx.cx().type_ptr_to(bx.cx().type_isize()));
|
||||
let llvtable = bx.pointercast(llvtable, bx.type_ptr_to(bx.type_isize()));
|
||||
let usize_align = bx.tcx().data_layout.pointer_align.abi;
|
||||
let gep = bx.inbounds_gep(llvtable, &[bx.cx().const_usize(self.0)]);
|
||||
let gep = bx.inbounds_gep(llvtable, &[bx.const_usize(self.0)]);
|
||||
let ptr = bx.load(gep, usize_align);
|
||||
// Vtable loads are invariant
|
||||
bx.set_invariant_load(ptr);
|
||||
|
|
|
|||
|
|
@ -182,22 +182,20 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
let lp1 = bx.load_operand(lp1).immediate();
|
||||
slot.storage_dead(&mut bx);
|
||||
|
||||
if !bx.cx().sess().target.target.options.custom_unwind_resume {
|
||||
let mut lp = bx.cx().const_undef(self.landing_pad_type());
|
||||
if !bx.sess().target.target.options.custom_unwind_resume {
|
||||
let mut lp = bx.const_undef(self.landing_pad_type());
|
||||
lp = bx.insert_value(lp, lp0, 0);
|
||||
lp = bx.insert_value(lp, lp1, 1);
|
||||
bx.resume(lp);
|
||||
} else {
|
||||
bx.call(bx.cx().eh_unwind_resume(), &[lp0], funclet(self));
|
||||
bx.call(bx.eh_unwind_resume(), &[lp0], funclet(self));
|
||||
bx.unreachable();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mir::TerminatorKind::Abort => {
|
||||
// Call core::intrinsics::abort()
|
||||
let fnname = bx.cx().get_intrinsic(&("llvm.trap"));
|
||||
bx.call(fnname, &[], None);
|
||||
bx.abort();
|
||||
bx.unreachable();
|
||||
}
|
||||
|
||||
|
|
@ -220,10 +218,10 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
bx.cond_br(discr.immediate(), lltrue, llfalse);
|
||||
}
|
||||
} else {
|
||||
let switch_llty = bx.cx().immediate_backend_type(
|
||||
bx.cx().layout_of(switch_ty)
|
||||
let switch_llty = bx.immediate_backend_type(
|
||||
bx.layout_of(switch_ty)
|
||||
);
|
||||
let llval = bx.cx().const_uint_big(switch_llty, values[0]);
|
||||
let llval = bx.const_uint_big(switch_llty, values[0]);
|
||||
let cmp = bx.icmp(IntPredicate::IntEQ, discr.immediate(), llval);
|
||||
bx.cond_br(cmp, lltrue, llfalse);
|
||||
}
|
||||
|
|
@ -232,11 +230,11 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
let switch = bx.switch(discr.immediate(),
|
||||
llblock(self, *otherwise),
|
||||
values.len());
|
||||
let switch_llty = bx.cx().immediate_backend_type(
|
||||
bx.cx().layout_of(switch_ty)
|
||||
let switch_llty = bx.immediate_backend_type(
|
||||
bx.layout_of(switch_ty)
|
||||
);
|
||||
for (&value, target) in values.iter().zip(targets) {
|
||||
let llval = bx.cx().const_uint_big(switch_llty, value);
|
||||
let llval = bx.const_uint_big(switch_llty, value);
|
||||
let llbb = llblock(self, *target);
|
||||
bx.add_case(switch, llval, llbb)
|
||||
}
|
||||
|
|
@ -285,8 +283,8 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
llval
|
||||
}
|
||||
};
|
||||
let addr = bx.pointercast(llslot, bx.cx().type_ptr_to(
|
||||
bx.cx().cast_backend_type(&cast_ty)
|
||||
let addr = bx.pointercast(llslot, bx.type_ptr_to(
|
||||
bx.cast_backend_type(&cast_ty)
|
||||
));
|
||||
bx.load(addr, self.fn_ty.ret.layout.align.abi)
|
||||
}
|
||||
|
|
@ -301,7 +299,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
mir::TerminatorKind::Drop { ref location, target, unwind } => {
|
||||
let ty = location.ty(self.mir, bx.tcx()).to_ty(bx.tcx());
|
||||
let ty = self.monomorphize(&ty);
|
||||
let drop_fn = monomorphize::resolve_drop_in_place(bx.cx().tcx(), ty);
|
||||
let drop_fn = monomorphize::resolve_drop_in_place(bx.tcx(), ty);
|
||||
|
||||
if let ty::InstanceDef::DropGlue(_, None) = drop_fn.def {
|
||||
// we don't actually need to drop anything.
|
||||
|
|
@ -325,14 +323,14 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
ty::ParamEnv::reveal_all(),
|
||||
&sig,
|
||||
);
|
||||
let fn_ty = bx.cx().new_vtable(sig, &[]);
|
||||
let fn_ty = bx.new_vtable(sig, &[]);
|
||||
let vtable = args[1];
|
||||
args = &args[..1];
|
||||
(meth::DESTRUCTOR.get_fn(&mut bx, vtable, &fn_ty), fn_ty)
|
||||
}
|
||||
_ => {
|
||||
(bx.cx().get_fn(drop_fn),
|
||||
bx.cx().fn_type_of_instance(&drop_fn))
|
||||
(bx.get_fn(drop_fn),
|
||||
bx.fn_type_of_instance(&drop_fn))
|
||||
}
|
||||
};
|
||||
do_call(self, &mut bx, fn_ty, drop_fn, args,
|
||||
|
|
@ -342,7 +340,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
|
||||
mir::TerminatorKind::Assert { ref cond, expected, ref msg, target, cleanup } => {
|
||||
let cond = self.codegen_operand(&mut bx, cond).immediate();
|
||||
let mut const_cond = bx.cx().const_to_opt_u128(cond, false).map(|c| c == 1);
|
||||
let mut const_cond = bx.const_to_opt_u128(cond, false).map(|c| c == 1);
|
||||
|
||||
// This case can currently arise only from functions marked
|
||||
// with #[rustc_inherit_overflow_checks] and inlined from
|
||||
|
|
@ -351,7 +349,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
// NOTE: Unlike binops, negation doesn't have its own
|
||||
// checked operation, just a comparison with the minimum
|
||||
// value, so we have to check for the assert message.
|
||||
if !bx.cx().check_overflow() {
|
||||
if !bx.check_overflow() {
|
||||
if let mir::interpret::EvalErrorKind::OverflowNeg = *msg {
|
||||
const_cond = Some(expected);
|
||||
}
|
||||
|
|
@ -364,8 +362,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
}
|
||||
|
||||
// Pass the condition through llvm.expect for branch hinting.
|
||||
let expect = bx.cx().get_intrinsic(&"llvm.expect.i1");
|
||||
let cond = bx.call(expect, &[cond, bx.cx().const_bool(expected)], None);
|
||||
let cond = bx.expect(cond, expected);
|
||||
|
||||
// Create the failure block and the conditional branch to it.
|
||||
let lltarget = llblock(self, target);
|
||||
|
|
@ -381,11 +378,11 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
self.set_debug_loc(&mut bx, terminator.source_info);
|
||||
|
||||
// Get the location information.
|
||||
let loc = bx.cx().sess().source_map().lookup_char_pos(span.lo());
|
||||
let loc = bx.sess().source_map().lookup_char_pos(span.lo());
|
||||
let filename = Symbol::intern(&loc.file.name.to_string()).as_str();
|
||||
let filename = bx.cx().const_str_slice(filename);
|
||||
let line = bx.cx().const_u32(loc.line as u32);
|
||||
let col = bx.cx().const_u32(loc.col.to_usize() as u32 + 1);
|
||||
let filename = bx.const_str_slice(filename);
|
||||
let line = bx.const_u32(loc.line as u32);
|
||||
let col = bx.const_u32(loc.col.to_usize() as u32 + 1);
|
||||
let align = tcx.data_layout.aggregate_align.abi
|
||||
.max(tcx.data_layout.i32_align.abi)
|
||||
.max(tcx.data_layout.pointer_align.abi);
|
||||
|
|
@ -396,8 +393,8 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
let len = self.codegen_operand(&mut bx, len).immediate();
|
||||
let index = self.codegen_operand(&mut bx, index).immediate();
|
||||
|
||||
let file_line_col = bx.cx().const_struct(&[filename, line, col], false);
|
||||
let file_line_col = bx.cx().static_addr_of(
|
||||
let file_line_col = bx.const_struct(&[filename, line, col], false);
|
||||
let file_line_col = bx.static_addr_of(
|
||||
file_line_col,
|
||||
align,
|
||||
Some("panic_bounds_check_loc")
|
||||
|
|
@ -408,12 +405,12 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
_ => {
|
||||
let str = msg.description();
|
||||
let msg_str = Symbol::intern(str).as_str();
|
||||
let msg_str = bx.cx().const_str_slice(msg_str);
|
||||
let msg_file_line_col = bx.cx().const_struct(
|
||||
let msg_str = bx.const_str_slice(msg_str);
|
||||
let msg_file_line_col = bx.const_struct(
|
||||
&[msg_str, filename, line, col],
|
||||
false
|
||||
);
|
||||
let msg_file_line_col = bx.cx().static_addr_of(
|
||||
let msg_file_line_col = bx.static_addr_of(
|
||||
msg_file_line_col,
|
||||
align,
|
||||
Some("panic_loc")
|
||||
|
|
@ -426,8 +423,8 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
// Obtain the panic entry point.
|
||||
let def_id = common::langcall(bx.tcx(), Some(span), "", lang_item);
|
||||
let instance = ty::Instance::mono(bx.tcx(), def_id);
|
||||
let fn_ty = bx.cx().fn_type_of_instance(&instance);
|
||||
let llfn = bx.cx().get_fn(instance);
|
||||
let fn_ty = bx.fn_type_of_instance(&instance);
|
||||
let llfn = bx.get_fn(instance);
|
||||
|
||||
// Codegen the actual panic invoke/call.
|
||||
do_call(self, &mut bx, fn_ty, llfn, &args, None, cleanup);
|
||||
|
|
@ -449,7 +446,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
|
||||
let (instance, mut llfn) = match callee.layout.ty.sty {
|
||||
ty::FnDef(def_id, substs) => {
|
||||
(Some(ty::Instance::resolve(bx.cx().tcx(),
|
||||
(Some(ty::Instance::resolve(bx.tcx(),
|
||||
ty::ParamEnv::reveal_all(),
|
||||
def_id,
|
||||
substs).unwrap()),
|
||||
|
|
@ -488,7 +485,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
// we can do what we like. Here, we declare that transmuting
|
||||
// into an uninhabited type is impossible, so anything following
|
||||
// it must be unreachable.
|
||||
assert_eq!(bx.cx().layout_of(sig.output()).abi, layout::Abi::Uninhabited);
|
||||
assert_eq!(bx.layout_of(sig.output()).abi, layout::Abi::Uninhabited);
|
||||
bx.unreachable();
|
||||
}
|
||||
return;
|
||||
|
|
@ -502,7 +499,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
|
||||
let fn_ty = match def {
|
||||
Some(ty::InstanceDef::Virtual(..)) => {
|
||||
bx.cx().new_vtable(sig, &extra_args)
|
||||
bx.new_vtable(sig, &extra_args)
|
||||
}
|
||||
Some(ty::InstanceDef::DropGlue(_, None)) => {
|
||||
// empty drop glue - a nop.
|
||||
|
|
@ -510,18 +507,18 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
funclet_br(self, &mut bx, target);
|
||||
return;
|
||||
}
|
||||
_ => bx.cx().new_fn_type(sig, &extra_args)
|
||||
_ => bx.new_fn_type(sig, &extra_args)
|
||||
};
|
||||
|
||||
// emit a panic instead of instantiating an uninhabited type
|
||||
if (intrinsic == Some("init") || intrinsic == Some("uninit")) &&
|
||||
fn_ty.ret.layout.abi.is_uninhabited()
|
||||
{
|
||||
let loc = bx.cx().sess().source_map().lookup_char_pos(span.lo());
|
||||
let loc = bx.sess().source_map().lookup_char_pos(span.lo());
|
||||
let filename = Symbol::intern(&loc.file.name.to_string()).as_str();
|
||||
let filename = bx.cx().const_str_slice(filename);
|
||||
let line = bx.cx().const_u32(loc.line as u32);
|
||||
let col = bx.cx().const_u32(loc.col.to_usize() as u32 + 1);
|
||||
let filename = bx.const_str_slice(filename);
|
||||
let line = bx.const_u32(loc.line as u32);
|
||||
let col = bx.const_u32(loc.col.to_usize() as u32 + 1);
|
||||
let align = tcx.data_layout.aggregate_align.abi
|
||||
.max(tcx.data_layout.i32_align.abi)
|
||||
.max(tcx.data_layout.pointer_align.abi);
|
||||
|
|
@ -532,12 +529,12 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
if intrinsic == Some("init") { "zeroed" } else { "uninitialized" }
|
||||
);
|
||||
let msg_str = Symbol::intern(&str).as_str();
|
||||
let msg_str = bx.cx().const_str_slice(msg_str);
|
||||
let msg_file_line_col = bx.cx().const_struct(
|
||||
let msg_str = bx.const_str_slice(msg_str);
|
||||
let msg_file_line_col = bx.const_struct(
|
||||
&[msg_str, filename, line, col],
|
||||
false,
|
||||
);
|
||||
let msg_file_line_col = bx.cx().static_addr_of(
|
||||
let msg_file_line_col = bx.static_addr_of(
|
||||
msg_file_line_col,
|
||||
align,
|
||||
Some("panic_loc"),
|
||||
|
|
@ -547,8 +544,8 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
let def_id =
|
||||
common::langcall(bx.tcx(), Some(span), "", lang_items::PanicFnLangItem);
|
||||
let instance = ty::Instance::mono(bx.tcx(), def_id);
|
||||
let fn_ty = bx.cx().fn_type_of_instance(&instance);
|
||||
let llfn = bx.cx().get_fn(instance);
|
||||
let fn_ty = bx.fn_type_of_instance(&instance);
|
||||
let llfn = bx.get_fn(instance);
|
||||
|
||||
// Codegen the actual panic invoke/call.
|
||||
do_call(
|
||||
|
|
@ -580,7 +577,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
let dest = match ret_dest {
|
||||
_ if fn_ty.ret.is_indirect() => llargs[0],
|
||||
ReturnDest::Nothing => {
|
||||
bx.cx().const_undef(bx.cx().type_ptr_to(bx.memory_ty(&fn_ty.ret)))
|
||||
bx.const_undef(bx.type_ptr_to(bx.memory_ty(&fn_ty.ret)))
|
||||
}
|
||||
ReturnDest::IndirectOperand(dst, _) |
|
||||
ReturnDest::Store(dst) => dst.llval,
|
||||
|
|
@ -614,7 +611,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
);
|
||||
return OperandRef {
|
||||
val: Immediate(llval),
|
||||
layout: bx.cx().layout_of(ty),
|
||||
layout: bx.layout_of(ty),
|
||||
};
|
||||
|
||||
},
|
||||
|
|
@ -632,7 +629,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
);
|
||||
return OperandRef {
|
||||
val: Immediate(llval),
|
||||
layout: bx.cx().layout_of(ty)
|
||||
layout: bx.layout_of(ty)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -642,7 +639,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
}).collect();
|
||||
|
||||
|
||||
let callee_ty = instance.as_ref().unwrap().ty(bx.cx().tcx());
|
||||
let callee_ty = instance.as_ref().unwrap().ty(bx.tcx());
|
||||
bx.codegen_intrinsic_call(callee_ty, &fn_ty, &args, dest,
|
||||
terminator.source_info.span);
|
||||
|
||||
|
|
@ -739,7 +736,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
|
||||
let fn_ptr = match (llfn, instance) {
|
||||
(Some(llfn), _) => llfn,
|
||||
(None, Some(instance)) => bx.cx().get_fn(instance),
|
||||
(None, Some(instance)) => bx.get_fn(instance),
|
||||
_ => span_bug!(span, "no llfn for call"),
|
||||
};
|
||||
|
||||
|
|
@ -763,7 +760,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
) {
|
||||
// Fill padding with undef value, where applicable.
|
||||
if let Some(ty) = arg.pad {
|
||||
llargs.push(bx.cx().const_undef(bx.cx().reg_backend_type(&ty)))
|
||||
llargs.push(bx.const_undef(bx.reg_backend_type(&ty)))
|
||||
}
|
||||
|
||||
if arg.is_ignore() {
|
||||
|
|
@ -823,8 +820,8 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
if by_ref && !arg.is_indirect() {
|
||||
// Have to load the argument, maybe while casting it.
|
||||
if let PassMode::Cast(ty) = arg.mode {
|
||||
let addr = bx.pointercast(llval, bx.cx().type_ptr_to(
|
||||
bx.cx().cast_backend_type(&ty))
|
||||
let addr = bx.pointercast(llval, bx.type_ptr_to(
|
||||
bx.cast_backend_type(&ty))
|
||||
);
|
||||
llval = bx.load(addr, align.min(arg.layout.align.abi));
|
||||
} else {
|
||||
|
|
@ -1033,7 +1030,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
LocalRef::Place(place) => self.codegen_transmute_into(bx, src, place),
|
||||
LocalRef::UnsizedPlace(_) => bug!("transmute must not involve unsized locals"),
|
||||
LocalRef::Operand(None) => {
|
||||
let dst_layout = bx.cx().layout_of(self.monomorphized_place_ty(dst));
|
||||
let dst_layout = bx.layout_of(self.monomorphized_place_ty(dst));
|
||||
assert!(!dst_layout.ty.has_erasable_regions());
|
||||
let place = PlaceRef::alloca(bx, dst_layout, "transmute_temp");
|
||||
place.storage_live(bx);
|
||||
|
|
@ -1060,8 +1057,8 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
dst: PlaceRef<'tcx, Bx::Value>
|
||||
) {
|
||||
let src = self.codegen_operand(bx, src);
|
||||
let llty = bx.cx().backend_type(src.layout);
|
||||
let cast_ptr = bx.pointercast(dst.llval, bx.cx().type_ptr_to(llty));
|
||||
let llty = bx.backend_type(src.layout);
|
||||
let cast_ptr = bx.pointercast(dst.llval, bx.type_ptr_to(llty));
|
||||
let align = src.layout.align.abi.min(dst.align);
|
||||
src.val.store(bx, PlaceRef::new_sized(cast_ptr, src.layout, align));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ use rustc::mir;
|
|||
use rustc_data_structures::indexed_vec::Idx;
|
||||
use rustc::mir::interpret::{GlobalId, ConstValue};
|
||||
use rustc::ty::{self, Ty};
|
||||
use rustc::ty::layout::{self, LayoutOf};
|
||||
use rustc::ty::layout;
|
||||
use syntax::source_map::Span;
|
||||
use traits::*;
|
||||
|
||||
|
|
@ -75,20 +75,20 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
c,
|
||||
)?;
|
||||
if let Some(prim) = field.val.try_to_scalar() {
|
||||
let layout = bx.cx().layout_of(field_ty);
|
||||
let layout = bx.layout_of(field_ty);
|
||||
let scalar = match layout.abi {
|
||||
layout::Abi::Scalar(ref x) => x,
|
||||
_ => bug!("from_const: invalid ByVal layout: {:#?}", layout)
|
||||
};
|
||||
Ok(bx.cx().scalar_to_backend(
|
||||
Ok(bx.scalar_to_backend(
|
||||
prim, scalar,
|
||||
bx.cx().immediate_backend_type(layout),
|
||||
bx.immediate_backend_type(layout),
|
||||
))
|
||||
} else {
|
||||
bug!("simd shuffle field {:?}", field)
|
||||
}
|
||||
}).collect();
|
||||
let llval = bx.cx().const_struct(&values?, false);
|
||||
let llval = bx.const_struct(&values?, false);
|
||||
Ok((llval, c.ty))
|
||||
})
|
||||
.unwrap_or_else(|_| {
|
||||
|
|
@ -98,8 +98,8 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
);
|
||||
// We've errored, so we don't have to produce working code.
|
||||
let ty = self.monomorphize(&ty);
|
||||
let llty = bx.cx().backend_type(bx.cx().layout_of(ty));
|
||||
(bx.cx().const_undef(llty), ty)
|
||||
let llty = bx.backend_type(bx.layout_of(ty));
|
||||
(bx.const_undef(llty), ty)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
use libc::c_uint;
|
||||
use rustc::ty::{self, Ty, TypeFoldable, UpvarSubsts};
|
||||
use rustc::ty::layout::{LayoutOf, TyLayout, HasTyCtxt};
|
||||
use rustc::ty::layout::{TyLayout, HasTyCtxt};
|
||||
use rustc::mir::{self, Mir};
|
||||
use rustc::ty::subst::Substs;
|
||||
use rustc::session::config::DebugInfo;
|
||||
|
|
@ -266,14 +266,14 @@ pub fn codegen_mir<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
|
|||
|
||||
let mut allocate_local = |local| {
|
||||
let decl = &mir.local_decls[local];
|
||||
let layout = bx.cx().layout_of(fx.monomorphize(&decl.ty));
|
||||
let layout = bx.layout_of(fx.monomorphize(&decl.ty));
|
||||
assert!(!layout.ty.has_erasable_regions());
|
||||
|
||||
if let Some(name) = decl.name {
|
||||
// User variable
|
||||
let debug_scope = fx.scopes[decl.visibility_scope];
|
||||
let dbg = debug_scope.is_valid() &&
|
||||
bx.cx().sess().opts.debuginfo == DebugInfo::Full;
|
||||
bx.sess().opts.debuginfo == DebugInfo::Full;
|
||||
|
||||
if !memory_locals.contains(local) && !dbg {
|
||||
debug!("alloc: {:?} ({}) -> operand", local, name);
|
||||
|
|
@ -376,7 +376,7 @@ fn create_funclets<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
|
|||
{
|
||||
block_bxs.iter_enumerated().zip(cleanup_kinds).map(|((bb, &llbb), cleanup_kind)| {
|
||||
match *cleanup_kind {
|
||||
CleanupKind::Funclet if base::wants_msvc_seh(bx.cx().sess()) => {}
|
||||
CleanupKind::Funclet if base::wants_msvc_seh(bx.sess()) => {}
|
||||
_ => return (None, None)
|
||||
}
|
||||
|
||||
|
|
@ -415,8 +415,8 @@ fn create_funclets<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
|
|||
// C++ personality function, but `catch (...)` has no type so
|
||||
// it's null. The 64 here is actually a bitfield which
|
||||
// represents that this is a catch-all block.
|
||||
let null = bx.cx().const_null(bx.cx().type_i8p());
|
||||
let sixty_four = bx.cx().const_i32(64);
|
||||
let null = bx.const_null(bx.type_i8p());
|
||||
let sixty_four = bx.const_i32(64);
|
||||
funclet = cp_bx.catch_pad(cs, &[null, sixty_four, null]);
|
||||
cp_bx.br(llbb);
|
||||
}
|
||||
|
|
@ -451,7 +451,7 @@ fn arg_local_refs<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
|
|||
|
||||
// Get the argument scope, if it exists and if we need it.
|
||||
let arg_scope = scopes[mir::OUTERMOST_SOURCE_SCOPE];
|
||||
let arg_scope = if bx.cx().sess().opts.debuginfo == DebugInfo::Full {
|
||||
let arg_scope = if bx.sess().opts.debuginfo == DebugInfo::Full {
|
||||
arg_scope.scope_metadata
|
||||
} else {
|
||||
None
|
||||
|
|
@ -478,7 +478,7 @@ fn arg_local_refs<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
|
|||
_ => bug!("spread argument isn't a tuple?!")
|
||||
};
|
||||
|
||||
let place = PlaceRef::alloca(bx, bx.cx().layout_of(arg_ty), &name);
|
||||
let place = PlaceRef::alloca(bx, bx.layout_of(arg_ty), &name);
|
||||
for i in 0..tupled_arg_tys.len() {
|
||||
let arg = &fx.fn_ty.args[idx];
|
||||
idx += 1;
|
||||
|
|
@ -524,18 +524,18 @@ fn arg_local_refs<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
|
|||
return local(OperandRef::new_zst(bx.cx(), arg.layout));
|
||||
}
|
||||
PassMode::Direct(_) => {
|
||||
let llarg = bx.cx().get_param(bx.llfn(), llarg_idx as c_uint);
|
||||
let llarg = bx.get_param(bx.llfn(), llarg_idx as c_uint);
|
||||
bx.set_value_name(llarg, &name);
|
||||
llarg_idx += 1;
|
||||
return local(
|
||||
OperandRef::from_immediate_or_packed_pair(bx, llarg, arg.layout));
|
||||
}
|
||||
PassMode::Pair(..) => {
|
||||
let a = bx.cx().get_param(bx.llfn(), llarg_idx as c_uint);
|
||||
let a = bx.get_param(bx.llfn(), llarg_idx as c_uint);
|
||||
bx.set_value_name(a, &(name.clone() + ".0"));
|
||||
llarg_idx += 1;
|
||||
|
||||
let b = bx.cx().get_param(bx.llfn(), llarg_idx as c_uint);
|
||||
let b = bx.get_param(bx.llfn(), llarg_idx as c_uint);
|
||||
bx.set_value_name(b, &(name + ".1"));
|
||||
llarg_idx += 1;
|
||||
|
||||
|
|
@ -552,16 +552,16 @@ fn arg_local_refs<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
|
|||
// Don't copy an indirect argument to an alloca, the caller
|
||||
// already put it in a temporary alloca and gave it up.
|
||||
// FIXME: lifetimes
|
||||
let llarg = bx.cx().get_param(bx.llfn(), llarg_idx as c_uint);
|
||||
let llarg = bx.get_param(bx.llfn(), llarg_idx as c_uint);
|
||||
bx.set_value_name(llarg, &name);
|
||||
llarg_idx += 1;
|
||||
PlaceRef::new_sized(llarg, arg.layout, arg.layout.align.abi)
|
||||
} else if arg.is_unsized_indirect() {
|
||||
// As the storage for the indirect argument lives during
|
||||
// the whole function call, we just copy the fat pointer.
|
||||
let llarg = bx.cx().get_param(bx.llfn(), llarg_idx as c_uint);
|
||||
let llarg = bx.get_param(bx.llfn(), llarg_idx as c_uint);
|
||||
llarg_idx += 1;
|
||||
let llextra = bx.cx().get_param(bx.llfn(), llarg_idx as c_uint);
|
||||
let llextra = bx.get_param(bx.llfn(), llarg_idx as c_uint);
|
||||
llarg_idx += 1;
|
||||
let indirect_operand = OperandValue::Pair(llarg, llextra);
|
||||
|
||||
|
|
@ -599,7 +599,7 @@ fn arg_local_refs<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
|
|||
// Or is it the closure environment?
|
||||
let (closure_layout, env_ref) = match arg.layout.ty.sty {
|
||||
ty::RawPtr(ty::TypeAndMut { ty, .. }) |
|
||||
ty::Ref(_, ty, _) => (bx.cx().layout_of(ty), true),
|
||||
ty::Ref(_, ty, _) => (bx.layout_of(ty), true),
|
||||
_ => (arg.layout, false)
|
||||
};
|
||||
|
||||
|
|
@ -618,10 +618,10 @@ fn arg_local_refs<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
|
|||
// doesn't actually strip the offset when splitting the closure
|
||||
// environment into its components so it ends up out of bounds.
|
||||
// (cuviper) It seems to be fine without the alloca on LLVM 6 and later.
|
||||
let env_alloca = !env_ref && bx.cx().closure_env_needs_indirect_debuginfo();
|
||||
let env_alloca = !env_ref && bx.closure_env_needs_indirect_debuginfo();
|
||||
let env_ptr = if env_alloca {
|
||||
let scratch = PlaceRef::alloca(bx,
|
||||
bx.cx().layout_of(tcx.mk_mut_ptr(arg.layout.ty)),
|
||||
bx.layout_of(tcx.mk_mut_ptr(arg.layout.ty)),
|
||||
"__debuginfo_env_ptr");
|
||||
bx.store(place.llval, scratch.llval, scratch.align);
|
||||
scratch.llval
|
||||
|
|
@ -632,7 +632,7 @@ fn arg_local_refs<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
|
|||
for (i, (decl, ty)) in mir.upvar_decls.iter().zip(upvar_tys).enumerate() {
|
||||
let byte_offset_of_var_in_env = closure_layout.fields.offset(i).bytes();
|
||||
|
||||
let ops = bx.cx().debuginfo_upvar_decls_ops_sequence(byte_offset_of_var_in_env);
|
||||
let ops = bx.debuginfo_upvar_decls_ops_sequence(byte_offset_of_var_in_env);
|
||||
|
||||
// The environment and the capture can each be indirect.
|
||||
|
||||
|
|
|
|||
|
|
@ -484,8 +484,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
}
|
||||
// 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);
|
||||
bx.abort();
|
||||
// We've errored, so we don't have to produce working code.
|
||||
let layout = bx.cx().layout_of(ty);
|
||||
bx.load_operand(PlaceRef::new_sized(
|
||||
|
|
|
|||
|
|
@ -413,8 +413,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
// 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);
|
||||
bx.abort();
|
||||
let llval = bx.cx().const_undef(
|
||||
bx.cx().type_ptr_to(bx.cx().backend_type(layout))
|
||||
);
|
||||
|
|
@ -424,7 +423,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
}
|
||||
mir::Place::Static(box mir::Static { def_id, ty }) => {
|
||||
let layout = cx.layout_of(self.monomorphize(&ty));
|
||||
PlaceRef::new_sized(cx.get_static(def_id), layout, layout.align.abi)
|
||||
PlaceRef::new_sized(bx.get_static(def_id), layout, layout.align.abi)
|
||||
},
|
||||
mir::Place::Projection(box mir::Projection {
|
||||
ref base,
|
||||
|
|
|
|||
|
|
@ -337,7 +337,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
llval,
|
||||
ll_t_in_const
|
||||
);
|
||||
base::call_assume(&mut bx, cmp);
|
||||
bx.assume(cmp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -693,11 +693,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
mir::BinOp::Mul => OverflowOp::Mul,
|
||||
_ => unreachable!()
|
||||
};
|
||||
let intrinsic = get_overflow_intrinsic(oop, bx, input_ty);
|
||||
let res = bx.call(intrinsic, &[lhs, rhs], None);
|
||||
|
||||
(bx.extract_value(res, 0),
|
||||
bx.extract_value(res, 1))
|
||||
bx.checked_binop(oop, input_ty, lhs, rhs)
|
||||
}
|
||||
mir::BinOp::Shl | mir::BinOp::Shr => {
|
||||
let lhs_llty = bx.cx().val_ty(lhs);
|
||||
|
|
@ -744,80 +740,6 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
enum OverflowOp {
|
||||
Add, Sub, Mul
|
||||
}
|
||||
|
||||
fn get_overflow_intrinsic<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
|
||||
oop: OverflowOp,
|
||||
bx: &mut Bx,
|
||||
ty: Ty
|
||||
) -> Bx::Value {
|
||||
use syntax::ast::IntTy::*;
|
||||
use syntax::ast::UintTy::*;
|
||||
use rustc::ty::{Int, Uint};
|
||||
|
||||
let tcx = bx.tcx();
|
||||
|
||||
let new_sty = match ty.sty {
|
||||
Int(Isize) => Int(tcx.sess.target.isize_ty),
|
||||
Uint(Usize) => Uint(tcx.sess.target.usize_ty),
|
||||
ref t @ Uint(_) | ref t @ Int(_) => t.clone(),
|
||||
_ => panic!("tried to get overflow intrinsic for op applied to non-int type")
|
||||
};
|
||||
|
||||
let name = match oop {
|
||||
OverflowOp::Add => match new_sty {
|
||||
Int(I8) => "llvm.sadd.with.overflow.i8",
|
||||
Int(I16) => "llvm.sadd.with.overflow.i16",
|
||||
Int(I32) => "llvm.sadd.with.overflow.i32",
|
||||
Int(I64) => "llvm.sadd.with.overflow.i64",
|
||||
Int(I128) => "llvm.sadd.with.overflow.i128",
|
||||
|
||||
Uint(U8) => "llvm.uadd.with.overflow.i8",
|
||||
Uint(U16) => "llvm.uadd.with.overflow.i16",
|
||||
Uint(U32) => "llvm.uadd.with.overflow.i32",
|
||||
Uint(U64) => "llvm.uadd.with.overflow.i64",
|
||||
Uint(U128) => "llvm.uadd.with.overflow.i128",
|
||||
|
||||
_ => unreachable!(),
|
||||
},
|
||||
OverflowOp::Sub => match new_sty {
|
||||
Int(I8) => "llvm.ssub.with.overflow.i8",
|
||||
Int(I16) => "llvm.ssub.with.overflow.i16",
|
||||
Int(I32) => "llvm.ssub.with.overflow.i32",
|
||||
Int(I64) => "llvm.ssub.with.overflow.i64",
|
||||
Int(I128) => "llvm.ssub.with.overflow.i128",
|
||||
|
||||
Uint(U8) => "llvm.usub.with.overflow.i8",
|
||||
Uint(U16) => "llvm.usub.with.overflow.i16",
|
||||
Uint(U32) => "llvm.usub.with.overflow.i32",
|
||||
Uint(U64) => "llvm.usub.with.overflow.i64",
|
||||
Uint(U128) => "llvm.usub.with.overflow.i128",
|
||||
|
||||
_ => unreachable!(),
|
||||
},
|
||||
OverflowOp::Mul => match new_sty {
|
||||
Int(I8) => "llvm.smul.with.overflow.i8",
|
||||
Int(I16) => "llvm.smul.with.overflow.i16",
|
||||
Int(I32) => "llvm.smul.with.overflow.i32",
|
||||
Int(I64) => "llvm.smul.with.overflow.i64",
|
||||
Int(I128) => "llvm.smul.with.overflow.i128",
|
||||
|
||||
Uint(U8) => "llvm.umul.with.overflow.i8",
|
||||
Uint(U16) => "llvm.umul.with.overflow.i16",
|
||||
Uint(U32) => "llvm.umul.with.overflow.i32",
|
||||
Uint(U64) => "llvm.umul.with.overflow.i64",
|
||||
Uint(U128) => "llvm.umul.with.overflow.i128",
|
||||
|
||||
_ => unreachable!(),
|
||||
},
|
||||
};
|
||||
|
||||
bx.cx().get_intrinsic(&name)
|
||||
}
|
||||
|
||||
fn cast_int_to_float<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
|
||||
bx: &mut Bx,
|
||||
signed: bool,
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
if let OperandValue::Immediate(_) = op.val {
|
||||
acc.push(op.immediate());
|
||||
} else {
|
||||
span_err!(bx.cx().sess(), span.to_owned(), E0669,
|
||||
span_err!(bx.sess(), span.to_owned(), E0669,
|
||||
"invalid value for constraint in inline assembly");
|
||||
}
|
||||
acc
|
||||
|
|
@ -98,7 +98,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
if input_vals.len() == inputs.len() {
|
||||
let res = bx.codegen_inline_asm(asm, outputs, input_vals);
|
||||
if !res {
|
||||
span_err!(bx.cx().sess(), statement.source_info.span, E0668,
|
||||
span_err!(bx.sess(), statement.source_info.span, E0668,
|
||||
"malformed inline assembly");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use super::HasCodegen;
|
||||
use super::BackendTypes;
|
||||
use rustc::ty::{FnSig, Instance, Ty};
|
||||
use rustc_target::abi::call::FnType;
|
||||
|
||||
|
|
@ -18,6 +18,6 @@ pub trait AbiMethods<'tcx> {
|
|||
fn fn_type_of_instance(&self, instance: &Instance<'tcx>) -> FnType<'tcx, Ty<'tcx>>;
|
||||
}
|
||||
|
||||
pub trait AbiBuilderMethods<'tcx>: HasCodegen<'tcx> {
|
||||
pub trait AbiBuilderMethods<'tcx>: BackendTypes {
|
||||
fn apply_attrs_callsite(&mut self, ty: &FnType<'tcx, Ty<'tcx>>, callsite: Self::Value);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,13 +8,12 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use super::Backend;
|
||||
use super::HasCodegen;
|
||||
use super::BackendTypes;
|
||||
use mir::place::PlaceRef;
|
||||
use rustc::hir::{GlobalAsm, InlineAsm};
|
||||
|
||||
pub trait AsmBuilderMethods<'tcx>: HasCodegen<'tcx> {
|
||||
// Take an inline assembly expression and splat it out via LLVM
|
||||
pub trait AsmBuilderMethods<'tcx>: BackendTypes {
|
||||
/// Take an inline assembly expression and splat it out via LLVM
|
||||
fn codegen_inline_asm(
|
||||
&mut self,
|
||||
ia: &InlineAsm,
|
||||
|
|
@ -23,6 +22,6 @@ pub trait AsmBuilderMethods<'tcx>: HasCodegen<'tcx> {
|
|||
) -> bool;
|
||||
}
|
||||
|
||||
pub trait AsmMethods<'tcx>: Backend<'tcx> {
|
||||
pub trait AsmMethods<'tcx> {
|
||||
fn codegen_global_asm(&self, ga: &GlobalAsm);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,7 +26,6 @@ pub trait BackendTypes {
|
|||
type Value: CodegenObject;
|
||||
type BasicBlock: Copy;
|
||||
type Type: CodegenObject;
|
||||
type Context;
|
||||
type Funclet;
|
||||
|
||||
type DIScope: Copy;
|
||||
|
|
@ -39,7 +38,8 @@ pub trait Backend<'tcx>:
|
|||
|
||||
impl<'tcx, T> Backend<'tcx> for T where
|
||||
Self: BackendTypes + HasTyCtxt<'tcx> + LayoutOf<Ty = Ty<'tcx>, TyLayout = TyLayout<'tcx>>
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
pub trait ExtraBackendMethods: CodegenBackend + WriteBackendMethods + Sized + Send {
|
||||
fn new_metadata(&self, sess: &Session, mod_name: &str) -> Self::Module;
|
||||
|
|
|
|||
|
|
@ -13,10 +13,11 @@ use super::asm::AsmBuilderMethods;
|
|||
use super::debuginfo::DebugInfoBuilderMethods;
|
||||
use super::intrinsic::IntrinsicCallMethods;
|
||||
use super::type_::ArgTypeMethods;
|
||||
use super::HasCodegen;
|
||||
use super::{HasCodegen, StaticBuilderMethods};
|
||||
use common::{AtomicOrdering, AtomicRmwBinOp, IntPredicate, RealPredicate, SynchronizationScope};
|
||||
use mir::operand::OperandRef;
|
||||
use mir::place::PlaceRef;
|
||||
use rustc::ty::Ty;
|
||||
use rustc::ty::layout::{Align, Size};
|
||||
use std::ffi::CStr;
|
||||
use MemFlags;
|
||||
|
|
@ -25,6 +26,13 @@ use std::borrow::Cow;
|
|||
use std::ops::Range;
|
||||
use syntax::ast::AsmDialect;
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub enum OverflowOp {
|
||||
Add,
|
||||
Sub,
|
||||
Mul,
|
||||
}
|
||||
|
||||
pub trait BuilderMethods<'a, 'tcx: 'a>:
|
||||
HasCodegen<'tcx>
|
||||
+ DebugInfoBuilderMethods<'tcx>
|
||||
|
|
@ -32,6 +40,7 @@ pub trait BuilderMethods<'a, 'tcx: 'a>:
|
|||
+ AbiBuilderMethods<'tcx>
|
||||
+ IntrinsicCallMethods<'tcx>
|
||||
+ AsmBuilderMethods<'tcx>
|
||||
+ StaticBuilderMethods<'tcx>
|
||||
{
|
||||
fn new_block<'b>(cx: &'a Self::CodegenCx, llfn: Self::Value, name: &'b str) -> Self;
|
||||
fn with_cx(cx: &'a Self::CodegenCx) -> Self;
|
||||
|
|
@ -97,6 +106,14 @@ pub trait BuilderMethods<'a, 'tcx: 'a>:
|
|||
fn fneg(&mut self, v: Self::Value) -> Self::Value;
|
||||
fn not(&mut self, v: Self::Value) -> Self::Value;
|
||||
|
||||
fn checked_binop(
|
||||
&mut self,
|
||||
oop: OverflowOp,
|
||||
ty: Ty,
|
||||
lhs: Self::Value,
|
||||
rhs: Self::Value,
|
||||
) -> (Self::Value, Self::Value);
|
||||
|
||||
fn alloca(&mut self, ty: Self::Type, name: &str, align: Align) -> Self::Value;
|
||||
fn dynamic_alloca(&mut self, ty: Self::Type, name: &str, align: Align) -> Self::Value;
|
||||
fn array_alloca(
|
||||
|
|
@ -297,18 +314,12 @@ pub trait BuilderMethods<'a, 'tcx: 'a>:
|
|||
) -> Cow<'b, [Self::Value]>
|
||||
where
|
||||
[Self::Value]: ToOwned;
|
||||
fn lifetime_start(&mut self, ptr: Self::Value, size: Size);
|
||||
fn lifetime_end(&mut self, ptr: Self::Value, size: Size);
|
||||
|
||||
/// If LLVM lifetime intrinsic support is enabled (i.e. optimizations
|
||||
/// on), and `ptr` is nonzero-sized, then extracts the size of `ptr`
|
||||
/// and the intrinsic for `lt` and passes them to `emit`, which is in
|
||||
/// charge of generating code to call the passed intrinsic on whatever
|
||||
/// block of generated code is targeted for the intrinsic.
|
||||
///
|
||||
/// If LLVM lifetime intrinsic support is disabled (i.e. optimizations
|
||||
/// off) or `ptr` is zero-sized, then no-op (does not call `emit`).
|
||||
fn call_lifetime_intrinsic(&mut self, intrinsic: &str, ptr: Self::Value, size: Size);
|
||||
/// Called for `StorageLive`
|
||||
fn lifetime_start(&mut self, ptr: Self::Value, size: Size);
|
||||
|
||||
/// Called for `StorageDead`
|
||||
fn lifetime_end(&mut self, ptr: Self::Value, size: Size);
|
||||
|
||||
fn call(
|
||||
&mut self,
|
||||
|
|
|
|||
|
|
@ -8,16 +8,15 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use super::Backend;
|
||||
use super::BackendTypes;
|
||||
use mir::place::PlaceRef;
|
||||
use rustc::mir::interpret::Allocation;
|
||||
use rustc::mir::interpret::Scalar;
|
||||
use rustc::ty::layout;
|
||||
use syntax::symbol::LocalInternedString;
|
||||
|
||||
pub trait ConstMethods<'tcx>: Backend<'tcx> {
|
||||
pub trait ConstMethods<'tcx>: BackendTypes {
|
||||
// Constant constructors
|
||||
|
||||
fn const_null(&self, t: Self::Type) -> Self::Value;
|
||||
fn const_undef(&self, t: Self::Type) -> Self::Value;
|
||||
fn const_int(&self, t: Self::Type, i: i64) -> Self::Value;
|
||||
|
|
@ -61,4 +60,6 @@ pub trait ConstMethods<'tcx>: Backend<'tcx> {
|
|||
alloc: &Allocation,
|
||||
offset: layout::Size,
|
||||
) -> PlaceRef<'tcx, Self::Value>;
|
||||
|
||||
fn const_ptrcast(&self, val: Self::Value, ty: Self::Type) -> Self::Value;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,8 +8,7 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use super::Backend;
|
||||
use super::HasCodegen;
|
||||
use super::BackendTypes;
|
||||
use debuginfo::{FunctionDebugContext, MirDebugScope, VariableAccess, VariableKind};
|
||||
use rustc::hir::def_id::CrateNum;
|
||||
use rustc::mir;
|
||||
|
|
@ -19,7 +18,7 @@ use rustc_mir::monomorphize::Instance;
|
|||
use syntax::ast::Name;
|
||||
use syntax_pos::{SourceFile, Span};
|
||||
|
||||
pub trait DebugInfoMethods<'tcx>: Backend<'tcx> {
|
||||
pub trait DebugInfoMethods<'tcx>: BackendTypes {
|
||||
fn create_vtable_metadata(&self, ty: Ty<'tcx>, vtable: Self::Value);
|
||||
|
||||
/// Creates the function-specific debug context.
|
||||
|
|
@ -51,7 +50,7 @@ pub trait DebugInfoMethods<'tcx>: Backend<'tcx> {
|
|||
fn debuginfo_upvar_decls_ops_sequence(&self, byte_offset_of_var_in_env: u64) -> [i64; 4];
|
||||
}
|
||||
|
||||
pub trait DebugInfoBuilderMethods<'tcx>: HasCodegen<'tcx> {
|
||||
pub trait DebugInfoBuilderMethods<'tcx>: BackendTypes {
|
||||
fn declare_local(
|
||||
&mut self,
|
||||
dbg_context: &FunctionDebugContext<Self::DIScope>,
|
||||
|
|
|
|||
|
|
@ -8,13 +8,13 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use super::Backend;
|
||||
use super::BackendTypes;
|
||||
use rustc::hir::def_id::DefId;
|
||||
use rustc::mir::mono::{Linkage, Visibility};
|
||||
use rustc::ty;
|
||||
use rustc_mir::monomorphize::Instance;
|
||||
|
||||
pub trait DeclareMethods<'tcx>: Backend<'tcx> {
|
||||
pub trait DeclareMethods<'tcx>: BackendTypes {
|
||||
/// Declare a global value.
|
||||
///
|
||||
/// If there’s a value with the same name already declared, the function will
|
||||
|
|
@ -71,7 +71,7 @@ pub trait DeclareMethods<'tcx>: Backend<'tcx> {
|
|||
fn get_defined_value(&self, name: &str) -> Option<Self::Value>;
|
||||
}
|
||||
|
||||
pub trait PreDefineMethods<'tcx>: Backend<'tcx> {
|
||||
pub trait PreDefineMethods<'tcx>: BackendTypes {
|
||||
fn predefine_static(
|
||||
&self,
|
||||
def_id: DefId,
|
||||
|
|
|
|||
|
|
@ -8,14 +8,13 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use super::Backend;
|
||||
use super::HasCodegen;
|
||||
use super::BackendTypes;
|
||||
use mir::operand::OperandRef;
|
||||
use rustc::ty::Ty;
|
||||
use rustc_target::abi::call::FnType;
|
||||
use syntax_pos::Span;
|
||||
|
||||
pub trait IntrinsicCallMethods<'tcx>: HasCodegen<'tcx> {
|
||||
pub trait IntrinsicCallMethods<'tcx>: BackendTypes {
|
||||
/// Remember to add all intrinsics here, in librustc_typeck/check/mod.rs,
|
||||
/// and in libcore/intrinsics.rs; if you need access to any llvm intrinsics,
|
||||
/// add them to librustc_codegen_llvm/context.rs
|
||||
|
|
@ -27,11 +26,8 @@ pub trait IntrinsicCallMethods<'tcx>: HasCodegen<'tcx> {
|
|||
llresult: Self::Value,
|
||||
span: Span,
|
||||
);
|
||||
}
|
||||
|
||||
pub trait IntrinsicDeclarationMethods<'tcx>: Backend<'tcx> {
|
||||
fn get_intrinsic(&self, key: &str) -> Self::Value;
|
||||
|
||||
/// Declare any llvm intrinsics that you might need
|
||||
fn declare_intrinsic(&self, key: &str) -> Option<Self::Value>;
|
||||
fn abort(&mut self);
|
||||
fn assume(&mut self, val: Self::Value);
|
||||
fn expect(&mut self, cond: Self::Value, expected: bool) -> Self::Value;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use super::Backend;
|
||||
use super::BackendTypes;
|
||||
use libc::c_uint;
|
||||
use rustc::mir::mono::Stats;
|
||||
use rustc::session::Session;
|
||||
|
|
@ -18,7 +18,7 @@ use rustc_mir::monomorphize::partitioning::CodegenUnit;
|
|||
use std::cell::RefCell;
|
||||
use std::sync::Arc;
|
||||
|
||||
pub trait MiscMethods<'tcx>: Backend<'tcx> {
|
||||
pub trait MiscMethods<'tcx>: BackendTypes {
|
||||
fn vtables(
|
||||
&self,
|
||||
) -> &RefCell<FxHashMap<(Ty<'tcx>, ty::PolyExistentialTraitRef<'tcx>), Self::Value>>;
|
||||
|
|
@ -32,7 +32,6 @@ pub trait MiscMethods<'tcx>: Backend<'tcx> {
|
|||
fn stats(&self) -> &RefCell<Stats>;
|
||||
fn consume_stats(self) -> RefCell<Stats>;
|
||||
fn codegen_unit(&self) -> &Arc<CodegenUnit<'tcx>>;
|
||||
fn statics_to_rauw(&self) -> &RefCell<Vec<(Self::Value, Self::Value)>>;
|
||||
fn closure_env_needs_indirect_debuginfo(&self) -> bool;
|
||||
fn used_statics(&self) -> &RefCell<Vec<Self::Value>>;
|
||||
fn set_frame_pointer_elimination(&self, llfn: Self::Value);
|
||||
|
|
|
|||
|
|
@ -40,13 +40,13 @@ mod write;
|
|||
pub use self::abi::{AbiBuilderMethods, AbiMethods};
|
||||
pub use self::asm::{AsmBuilderMethods, AsmMethods};
|
||||
pub use self::backend::{Backend, BackendTypes, ExtraBackendMethods};
|
||||
pub use self::builder::BuilderMethods;
|
||||
pub use self::builder::{BuilderMethods, OverflowOp};
|
||||
pub use self::consts::ConstMethods;
|
||||
pub use self::debuginfo::{DebugInfoBuilderMethods, DebugInfoMethods};
|
||||
pub use self::declare::{DeclareMethods, PreDefineMethods};
|
||||
pub use self::intrinsic::{IntrinsicCallMethods, IntrinsicDeclarationMethods};
|
||||
pub use self::intrinsic::IntrinsicCallMethods;
|
||||
pub use self::misc::MiscMethods;
|
||||
pub use self::statics::StaticMethods;
|
||||
pub use self::statics::{StaticMethods, StaticBuilderMethods};
|
||||
pub use self::type_::{
|
||||
ArgTypeMethods, BaseTypeMethods, DerivedTypeMethods, LayoutTypeMethods, TypeMethods,
|
||||
};
|
||||
|
|
@ -62,10 +62,9 @@ pub trait CodegenMethods<'tcx>:
|
|||
+ TypeMethods<'tcx>
|
||||
+ MiscMethods<'tcx>
|
||||
+ ConstMethods<'tcx>
|
||||
+ StaticMethods<'tcx>
|
||||
+ StaticMethods
|
||||
+ DebugInfoMethods<'tcx>
|
||||
+ AbiMethods<'tcx>
|
||||
+ IntrinsicDeclarationMethods<'tcx>
|
||||
+ DeclareMethods<'tcx>
|
||||
+ AsmMethods<'tcx>
|
||||
+ PreDefineMethods<'tcx>
|
||||
|
|
@ -77,22 +76,23 @@ impl<'tcx, T> CodegenMethods<'tcx> for T where
|
|||
+ TypeMethods<'tcx>
|
||||
+ MiscMethods<'tcx>
|
||||
+ ConstMethods<'tcx>
|
||||
+ StaticMethods<'tcx>
|
||||
+ StaticMethods
|
||||
+ DebugInfoMethods<'tcx>
|
||||
+ AbiMethods<'tcx>
|
||||
+ IntrinsicDeclarationMethods<'tcx>
|
||||
+ DeclareMethods<'tcx>
|
||||
+ AsmMethods<'tcx>
|
||||
+ PreDefineMethods<'tcx>
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
pub trait HasCodegen<'tcx>: Backend<'tcx> {
|
||||
pub trait HasCodegen<'tcx>:
|
||||
Backend<'tcx> + ::std::ops::Deref<Target = <Self as HasCodegen<'tcx>>::CodegenCx>
|
||||
{
|
||||
type CodegenCx: CodegenMethods<'tcx>
|
||||
+ BackendTypes<
|
||||
Value = Self::Value,
|
||||
BasicBlock = Self::BasicBlock,
|
||||
Type = Self::Type,
|
||||
Context = Self::Context,
|
||||
Funclet = Self::Funclet,
|
||||
DIScope = Self::DIScope,
|
||||
>;
|
||||
|
|
|
|||
|
|
@ -8,16 +8,15 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use super::Backend;
|
||||
use super::BackendTypes;
|
||||
use rustc::hir::def_id::DefId;
|
||||
use rustc::ty::layout::Align;
|
||||
|
||||
pub trait StaticMethods<'tcx>: Backend<'tcx> {
|
||||
fn static_ptrcast(&self, val: Self::Value, ty: Self::Type) -> Self::Value;
|
||||
fn static_bitcast(&self, val: Self::Value, ty: Self::Type) -> Self::Value;
|
||||
fn static_addr_of_mut(&self, cv: Self::Value, align: Align, kind: Option<&str>) -> Self::Value;
|
||||
pub trait StaticMethods: BackendTypes {
|
||||
fn static_addr_of(&self, cv: Self::Value, align: Align, kind: Option<&str>) -> Self::Value;
|
||||
fn get_static(&self, def_id: DefId) -> Self::Value;
|
||||
fn codegen_static(&self, def_id: DefId, is_mutable: bool);
|
||||
unsafe fn static_replace_all_uses(&self, old_g: Self::Value, new_g: Self::Value);
|
||||
}
|
||||
|
||||
pub trait StaticBuilderMethods<'tcx>: BackendTypes {
|
||||
fn get_static(&self, def_id: DefId) -> Self::Value;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,6 +20,8 @@ use rustc_target::abi::call::{ArgType, CastTarget, FnType, Reg};
|
|||
use std::cell::RefCell;
|
||||
use syntax::ast;
|
||||
|
||||
// This depends on `Backend` and not `BackendTypes`, because consumers will probably want to use
|
||||
// `LayoutOf` or `HasTyCtxt`. This way, they don't have to add a constraint on it themselves.
|
||||
pub trait BaseTypeMethods<'tcx>: Backend<'tcx> {
|
||||
fn type_void(&self) -> Self::Type;
|
||||
fn type_metadata(&self) -> Self::Type;
|
||||
|
|
@ -41,11 +43,9 @@ pub trait BaseTypeMethods<'tcx>: Backend<'tcx> {
|
|||
fn type_func(&self, args: &[Self::Type], ret: Self::Type) -> Self::Type;
|
||||
fn type_variadic_func(&self, args: &[Self::Type], ret: Self::Type) -> Self::Type;
|
||||
fn type_struct(&self, els: &[Self::Type], packed: bool) -> Self::Type;
|
||||
fn type_named_struct(&self, name: &str) -> Self::Type;
|
||||
fn type_array(&self, ty: Self::Type, len: u64) -> Self::Type;
|
||||
fn type_vector(&self, ty: Self::Type, len: u64) -> Self::Type;
|
||||
fn type_kind(&self, ty: Self::Type) -> TypeKind;
|
||||
fn set_struct_body(&self, ty: Self::Type, els: &[Self::Type], packed: bool);
|
||||
fn type_ptr_to(&self, ty: Self::Type) -> Self::Type;
|
||||
fn element_type(&self, ty: Self::Type) -> Self::Type;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue