instance: Instance<'tcx>,
linkage: Linkage,
) {
- let tcx = cx.tcx;
+ let tcx = cx.codegen_cx.tcx;
let mir = tcx.instance_mir(instance.def);
// Declare function
- let (name, sig) = get_function_name_and_sig(tcx, cx.module.isa().triple(), instance, false);
- let func_id = cx.module.declare_function(&name, linkage, &sig).unwrap();
+ let (name, sig) = get_function_name_and_sig(tcx, cx.codegen_cx.module.isa().triple(), instance, false);
+ let func_id = cx.codegen_cx.module.declare_function(&name, linkage, &sig).unwrap();
// Make FunctionBuilder
let context = &mut cx.cached_context;
let block_map: IndexVec<BasicBlock, Block> = (0..mir.basic_blocks().len()).map(|_| bcx.create_block()).collect();
// Make FunctionCx
- let pointer_type = cx.module.target_config().pointer_type();
+ let pointer_type = cx.codegen_cx.module.target_config().pointer_type();
let clif_comments = crate::pretty_clif::CommentWriter::new(tcx, instance);
let mut fx = FunctionCx {
tcx,
- module: &mut cx.module,
+ module: &mut cx.codegen_cx.module,
+ global_asm: &mut cx.global_asm,
pointer_type,
instance,
vtables: &mut cx.vtables,
source_info_set: indexmap::IndexSet::new(),
next_ssa_var: 0,
+
+ inline_asm_index: 0,
};
let arg_uninhabited = fx.mir.args_iter().any(|arg| fx.layout_of(fx.monomorphize(&fx.mir.local_decls[arg].ty)).abi.is_uninhabited());
let cold_blocks = fx.cold_blocks;
crate::pretty_clif::write_clif_file(
- cx.tcx,
+ cx.codegen_cx.tcx,
"unopt",
None,
instance,
// instruction, which doesn't have an encoding.
context.compute_cfg();
context.compute_domtree();
- context.eliminate_unreachable_code(cx.module.isa()).unwrap();
+ context.eliminate_unreachable_code(cx.codegen_cx.module.isa()).unwrap();
// Define function
- let module = &mut cx.module;
+ let module = &mut cx.codegen_cx.module;
tcx.sess.time(
"define function",
|| module.define_function(
// Write optimized function to file for debugging
crate::pretty_clif::write_clif_file(
- cx.tcx,
+ cx.codegen_cx.tcx,
"opt",
- Some(cx.module.isa()),
+ Some(cx.codegen_cx.module.isa()),
instance,
&context,
&clif_comments,
);
// Define debuginfo for function
- let isa = cx.module.isa();
+ let isa = cx.codegen_cx.module.isa();
let debug_context = &mut cx.debug_context;
let unwind_context = &mut cx.unwind_context;
tcx.sess.time("generate debug info", || {
}
fn codegen_fn_content(fx: &mut FunctionCx<'_, '_, impl Backend>) {
+ crate::constant::check_constants(fx);
+
for (bb, bb_data) in fx.mir.basic_blocks().iter_enumerated() {
let block = fx.get_block(bb);
fx.bcx.switch_to_block(block);
target,
cleanup: _,
} => {
- if !fx.tcx.sess.overflow_checks() {
+ if !fx.codegen_cx.tcx.sess.overflow_checks() {
if let mir::AssertKind::OverflowNeg(_) = *msg {
let target = fx.get_block(*target);
fx.bcx.ins().jump(target, &[]);
}
};
- let def_id = fx.tcx.lang_items().require(lang_item).unwrap_or_else(|s| {
- fx.tcx.sess.span_fatal(bb_data.terminator().source_info.span, &s)
+ let def_id = fx.codegen_cx.tcx.lang_items().require(lang_item).unwrap_or_else(|s| {
+ fx.codegen_cx.tcx.sess.span_fatal(bb_data.terminator().source_info.span, &s)
});
- let instance = Instance::mono(fx.tcx, def_id);
- let symbol_name = fx.tcx.symbol_name(instance).name.as_str();
+ let instance = Instance::mono(fx.codegen_cx.tcx, def_id).polymorphize(fx.codegen_cx.tcx);
+ let symbol_name = fx.codegen_cx.tcx.symbol_name(instance).name;
fx.lib_call(&*symbol_name, vec![fx.pointer_type, fx.pointer_type, fx.pointer_type], vec![], &args);
let mut switch = ::cranelift_frontend::Switch::new();
for (i, value) in values.iter().enumerate() {
let block = fx.get_block(targets[i]);
- switch.set_entry(*value as u64, block);
+ switch.set_entry(*value, block);
}
let otherwise_block = fx.get_block(targets[targets.len() - 1]);
switch.emit(&mut fx.bcx, discr, otherwise_block);
cleanup: _,
from_hir_call: _,
} => {
- fx.tcx.sess.time("codegen call", || crate::abi::codegen_terminator_call(
+ fx.codegen_cx.tcx.sess.time("codegen call", || crate::abi::codegen_terminator_call(
fx,
*fn_span,
block,
TerminatorKind::InlineAsm {
template,
operands,
- options: _,
+ options,
destination,
line_spans: _,
} => {
- match template {
- &[] => {
- assert_eq!(operands, &[]);
- match *destination {
- Some(destination) => {
- let destination_block = fx.get_block(destination);
- fx.bcx.ins().jump(destination_block, &[]);
- }
- None => bug!(),
- }
+ crate::inline_asm::codegen_inline_asm(
+ fx,
+ bb_data.terminator().source_info.span,
+ template,
+ operands,
+ *options,
+ );
- // Black box
+ match *destination {
+ Some(destination) => {
+ let destination_block = fx.get_block(destination);
+ fx.bcx.ins().jump(destination_block, &[]);
+ }
+ None => {
+ crate::trap::trap_unreachable(fx, "[corruption] Returned from noreturn inline asm");
}
- _ => fx.tcx.sess.span_fatal(bb_data.terminator().source_info.span, "Inline assembly is not supported"),
}
}
TerminatorKind::Resume | TerminatorKind::Abort => {
let lhs = trans_operand(fx, lhs);
let rhs = trans_operand(fx, rhs);
- let res = if !fx.tcx.sess.overflow_checks() {
+ let res = if !fx.codegen_cx.tcx.sess.overflow_checks() {
let val =
crate::num::trans_int_binop(fx, *bin_op, lhs, rhs).load_scalar(fx);
let is_overflow = fx.bcx.ins().iconst(types::I8, 0);
lval.write_cvalue(fx, res);
}
Rvalue::Cast(CastKind::Pointer(PointerCast::ReifyFnPointer), operand, to_ty) => {
- let from_ty = fx.monomorphize(&operand.ty(&fx.mir.local_decls, fx.tcx));
+ let from_ty = fx.monomorphize(&operand.ty(&fx.mir.local_decls, fx.codegen_cx.tcx));
let to_layout = fx.layout_of(fx.monomorphize(to_ty));
match from_ty.kind {
ty::FnDef(def_id, substs) => {
let func_ref = fx.get_function_ref(
- Instance::resolve_for_fn_ptr(fx.tcx, ParamEnv::reveal_all(), def_id, substs)
- .unwrap(),
+ Instance::resolve_for_fn_ptr(fx.codegen_cx.tcx, ParamEnv::reveal_all(), def_id, substs)
+ .unwrap()
+ .polymorphize(fx.codegen_cx.tcx),
);
let func_addr = fx.bcx.ins().func_addr(fx.pointer_type, func_ref);
lval.write_cvalue(fx, CValue::by_val(func_addr, to_layout));
|ty::TypeAndMut {
ty: pointee_ty,
mutbl: _,
- }| has_ptr_meta(fx.tcx, pointee_ty),
+ }| has_ptr_meta(fx.codegen_cx.tcx, pointee_ty),
)
.unwrap_or(false)
}
_ => unreachable!("cast adt {} -> {}", from_ty, to_ty),
}
- let discr = crate::discriminant::codegen_get_discriminant(
- fx,
- operand,
- fx.layout_of(to_ty),
- );
- lval.write_cvalue(fx, discr);
+ use rustc_target::abi::{TagEncoding, Int, Variants};
+
+ match &operand.layout().variants {
+ Variants::Single { index } => {
+ let discr = operand.layout().ty.discriminant_for_variant(fx.codegen_cx.tcx, *index).unwrap();
+ let discr = if discr.ty.is_signed() {
+ rustc_middle::mir::interpret::sign_extend(discr.val, fx.layout_of(discr.ty).size)
+ } else {
+ discr.val
+ };
+
+ let discr = CValue::const_val(fx, fx.layout_of(to_ty), discr);
+ lval.write_cvalue(fx, discr);
+ }
+ Variants::Multiple {
+ tag,
+ tag_field,
+ tag_encoding: TagEncoding::Direct,
+ variants: _,
+ } => {
+ let cast_to = fx.clif_type(dest_layout.ty).unwrap();
+
+ // Read the tag/niche-encoded discriminant from memory.
+ let encoded_discr = operand.value_field(fx, mir::Field::new(*tag_field));
+ let encoded_discr = encoded_discr.load_scalar(fx);
+
+ // Decode the discriminant (specifically if it's niche-encoded).
+ let signed = match tag.value {
+ Int(_, signed) => signed,
+ _ => false,
+ };
+ let val = clif_intcast(fx, encoded_discr, cast_to, signed);
+ let val = CValue::by_val(val, dest_layout);
+ lval.write_cvalue(fx, val);
+ }
+ Variants::Multiple { ..} => unreachable!(),
+ }
} else {
let to_clif_ty = fx.clif_type(to_ty).unwrap();
let from = operand.load_scalar(fx);
match operand.layout().ty.kind {
ty::Closure(def_id, substs) => {
let instance = Instance::resolve_closure(
- fx.tcx,
+ fx.codegen_cx.tcx,
def_id,
substs,
ty::ClosureKind::FnOnce,
- );
+ ).polymorphize(fx.codegen_cx.tcx);
let func_ref = fx.get_function_ref(instance);
let func_addr = fx.bcx.ins().func_addr(fx.pointer_type, func_ref);
lval.write_cvalue(fx, CValue::by_val(func_addr, lval.layout()));
let operand = trans_operand(fx, operand);
let times = fx
.monomorphize(times)
- .eval(fx.tcx, ParamEnv::reveal_all())
+ .eval(fx.codegen_cx.tcx, ParamEnv::reveal_all())
.val
- .try_to_bits(fx.tcx.data_layout.pointer_size)
+ .try_to_bits(fx.codegen_cx.tcx.data_layout.pointer_size)
.unwrap();
for i in 0..times {
let index = fx.bcx.ins().iconst(fx.pointer_type, i as i64);
}
Rvalue::Len(place) => {
let place = trans_place(fx, *place);
- let usize_layout = fx.layout_of(fx.tcx.types.usize);
+ let usize_layout = fx.layout_of(fx.codegen_cx.tcx.types.usize);
let len = codegen_array_len(fx, place);
lval.write_cvalue(fx, CValue::by_val(len, usize_layout));
}
Rvalue::NullaryOp(NullOp::Box, content_ty) => {
use rustc_hir::lang_items::ExchangeMallocFnLangItem;
- let usize_type = fx.clif_type(fx.tcx.types.usize).unwrap();
+ let usize_type = fx.clif_type(fx.codegen_cx.tcx.types.usize).unwrap();
let content_ty = fx.monomorphize(content_ty);
let layout = fx.layout_of(content_ty);
let llsize = fx.bcx.ins().iconst(usize_type, layout.size.bytes() as i64);
.bcx
.ins()
.iconst(usize_type, layout.align.abi.bytes() as i64);
- let box_layout = fx.layout_of(fx.tcx.mk_box(content_ty));
+ let box_layout = fx.layout_of(fx.codegen_cx.tcx.mk_box(content_ty));
// Allocate space:
- let def_id = match fx.tcx.lang_items().require(ExchangeMallocFnLangItem) {
+ let def_id = match fx.codegen_cx.tcx.lang_items().require(ExchangeMallocFnLangItem) {
Ok(id) => id,
Err(s) => {
- fx.tcx
+ fx.codegen_cx.tcx
.sess
.fatal(&format!("allocation of `{}` {}", box_layout.ty, s));
}
};
- let instance = ty::Instance::mono(fx.tcx, def_id);
+ let instance = ty::Instance::mono(fx.codegen_cx.tcx, def_id).polymorphize(fx.codegen_cx.tcx);
let func_ref = fx.get_function_ref(instance);
let call = fx.bcx.ins().call(func_ref, &[llsize, llalign]);
let ptr = fx.bcx.inst_results(call)[0];
assert!(lval
.layout()
.ty
- .is_sized(fx.tcx.at(stmt.source_info.span), ParamEnv::reveal_all()));
+ .is_sized(fx.codegen_cx.tcx.at(stmt.source_info.span), ParamEnv::reveal_all()));
let ty_size = fx.layout_of(fx.monomorphize(ty)).size.bytes();
- let val = CValue::const_val(fx, fx.layout_of(fx.tcx.types.usize), ty_size.into());
+ let val = CValue::const_val(fx, fx.layout_of(fx.codegen_cx.tcx.types.usize), ty_size.into());
lval.write_cvalue(fx, val);
}
Rvalue::Aggregate(kind, operands) => match **kind {
use rustc_span::symbol::Symbol;
let LlvmInlineAsm {
asm,
- outputs: _,
- inputs: _,
+ outputs,
+ inputs,
} = &**asm;
let rustc_hir::LlvmInlineAsmInner {
asm: asm_code, // Name
- outputs, // Vec<Name>
- inputs, // Vec<Name>
+ outputs: output_names, // Vec<LlvmInlineAsmOutput>
+ inputs: input_names, // Vec<Name>
clobbers, // Vec<Name>
volatile, // bool
alignstack, // bool
- dialect: _, // rustc_ast::ast::AsmDialect
+ dialect: _,
asm_str_style: _,
} = asm;
- match &*asm_code.as_str() {
- cpuid if cpuid.contains("cpuid") => {
- crate::trap::trap_unimplemented(
- fx,
- "__cpuid_count arch intrinsic is not supported",
- );
+ match asm_code.as_str().trim() {
+ "" => {
+ // Black box
+ }
+ "mov %rbx, %rsi\n cpuid\n xchg %rbx, %rsi" => {
+ assert_eq!(input_names, &[Symbol::intern("{eax}"), Symbol::intern("{ecx}")]);
+ assert_eq!(output_names.len(), 4);
+ for (i, c) in (&["={eax}", "={esi}", "={ecx}", "={edx}"]).iter().enumerate() {
+ assert_eq!(&output_names[i].constraint.as_str(), c);
+ assert!(!output_names[i].is_rw);
+ assert!(!output_names[i].is_indirect);
+ }
+
+ assert_eq!(clobbers, &[]);
+
+ assert!(!volatile);
+ assert!(!alignstack);
+
+ assert_eq!(inputs.len(), 2);
+ let leaf = trans_operand(fx, &inputs[0].1).load_scalar(fx); // %eax
+ let subleaf = trans_operand(fx, &inputs[1].1).load_scalar(fx); // %ecx
+
+ let (eax, ebx, ecx, edx) = crate::intrinsics::codegen_cpuid_call(fx, leaf, subleaf);
+
+ assert_eq!(outputs.len(), 4);
+ trans_place(fx, outputs[0]).write_cvalue(fx, CValue::by_val(eax, fx.layout_of(fx.codegen_cx.tcx.types.u32)));
+ trans_place(fx, outputs[1]).write_cvalue(fx, CValue::by_val(ebx, fx.layout_of(fx.codegen_cx.tcx.types.u32)));
+ trans_place(fx, outputs[2]).write_cvalue(fx, CValue::by_val(ecx, fx.layout_of(fx.codegen_cx.tcx.types.u32)));
+ trans_place(fx, outputs[3]).write_cvalue(fx, CValue::by_val(edx, fx.layout_of(fx.codegen_cx.tcx.types.u32)));
}
"xgetbv" => {
- assert_eq!(inputs, &[Symbol::intern("{ecx}")]);
+ assert_eq!(input_names, &[Symbol::intern("{ecx}")]);
- assert_eq!(outputs.len(), 2);
+ assert_eq!(output_names.len(), 2);
for (i, c) in (&["={eax}", "={edx}"]).iter().enumerate() {
- assert_eq!(&outputs[i].constraint.as_str(), c);
- assert!(!outputs[i].is_rw);
- assert!(!outputs[i].is_indirect);
+ assert_eq!(&output_names[i].constraint.as_str(), c);
+ assert!(!output_names[i].is_rw);
+ assert!(!output_names[i].is_indirect);
}
assert_eq!(clobbers, &[]);
crate::trap::trap_unimplemented(fx, "_xgetbv arch intrinsic is not supported");
}
// ___chkstk, ___chkstk_ms and __alloca are only used on Windows
- _ if fx.tcx.symbol_name(fx.instance).name.as_str().starts_with("___chkstk") => {
+ _ if fx.codegen_cx.tcx.symbol_name(fx.instance).name.starts_with("___chkstk") => {
crate::trap::trap_unimplemented(fx, "Stack probes are not supported");
}
- _ if fx.tcx.symbol_name(fx.instance).name.as_str() == "__alloca" => {
+ _ if fx.codegen_cx.tcx.symbol_name(fx.instance).name == "__alloca" => {
crate::trap::trap_unimplemented(fx, "Alloca is not supported");
}
// Used in sys::windows::abort_internal
"int $$0x29" => {
crate::trap::trap_unimplemented(fx, "Windows abort");
}
- _ => fx.tcx.sess.span_fatal(stmt.source_info.span, "Inline assembly is not supported"),
+ _ => fx.codegen_cx.tcx.sess.span_fatal(stmt.source_info.span, "Inline assembly is not supported"),
}
}
}
match place.layout().ty.kind {
ty::Array(_elem_ty, len) => {
let len = fx.monomorphize(&len)
- .eval(fx.tcx, ParamEnv::reveal_all())
- .eval_usize(fx.tcx, ParamEnv::reveal_all()) as i64;
+ .eval(fx.codegen_cx.tcx, ParamEnv::reveal_all())
+ .eval_usize(fx.codegen_cx.tcx, ParamEnv::reveal_all()) as i64;
fx.bcx.ins().iconst(fx.pointer_type, len)
}
ty::Slice(_elem_ty) => place
from_end,
} => {
let index = if !from_end {
- fx.bcx.ins().iconst(fx.pointer_type, offset as i64)
+ fx.bcx.ins().iconst(fx.pointer_type, i64::from(offset))
} else {
let len = codegen_array_len(fx, cplace);
- fx.bcx.ins().iadd_imm(len, -(offset as i64))
+ fx.bcx.ins().iadd_imm(len, -i64::from(offset))
};
cplace = cplace.place_index(fx, index);
}
let elem_layout = fx.layout_of(elem_ty);
let ptr = cplace.to_ptr();
cplace = CPlace::for_ptr(
- ptr.offset_i64(fx, elem_layout.size.bytes() as i64 * from as i64),
- fx.layout_of(fx.tcx.mk_array(elem_ty, to as u64 - from as u64)),
+ ptr.offset_i64(fx, elem_layout.size.bytes() as i64 * i64::from(from)),
+ fx.layout_of(fx.codegen_cx.tcx.mk_array(elem_ty, u64::from(to) - u64::from(from))),
);
}
ty::Slice(elem_ty) => {
let (ptr, len) = cplace.to_ptr_maybe_unsized();
let len = len.unwrap();
cplace = CPlace::for_ptr_with_extra(
- ptr.offset_i64(fx, elem_layout.size.bytes() as i64 * from as i64),
- fx.bcx.ins().iadd_imm(len, -(from as i64 + to as i64)),
+ ptr.offset_i64(fx, elem_layout.size.bytes() as i64 * i64::from(from)),
+ fx.bcx.ins().iadd_imm(len, -(i64::from(from) + i64::from(to))),
cplace.layout(),
);
}