1
Fork 0
This commit is contained in:
bjorn3 2019-02-21 15:06:09 +01:00
parent a87aa4f583
commit f02490d960
9 changed files with 341 additions and 220 deletions

View file

@ -2,7 +2,7 @@ use std::borrow::Cow;
use std::iter; use std::iter;
use rustc::hir; use rustc::hir;
use rustc::ty::layout::{Scalar, Primitive, Integer, FloatTy}; use rustc::ty::layout::{FloatTy, Integer, Primitive, Scalar};
use rustc_target::spec::abi::Abi; use rustc_target::spec::abi::Abi;
use crate::prelude::*; use crate::prelude::*;
@ -32,11 +32,11 @@ pub fn scalar_to_clif_type(tcx: TyCtxt, scalar: Scalar) -> Type {
Integer::I32 => types::I32, Integer::I32 => types::I32,
Integer::I64 => types::I64, Integer::I64 => types::I64,
Integer::I128 => unimpl!("u/i128"), Integer::I128 => unimpl!("u/i128"),
} },
Primitive::Float(flt) => match flt { Primitive::Float(flt) => match flt {
FloatTy::F32 => types::F32, FloatTy::F32 => types::F32,
FloatTy::F64 => types::F64, FloatTy::F64 => types::F64,
} },
Primitive::Pointer => pointer_ty(tcx), Primitive::Pointer => pointer_ty(tcx),
} }
} }
@ -46,9 +46,7 @@ fn get_pass_mode<'a, 'tcx: 'a>(
ty: Ty<'tcx>, ty: Ty<'tcx>,
is_return: bool, is_return: bool,
) -> PassMode { ) -> PassMode {
let layout = tcx let layout = tcx.layout_of(ParamEnv::reveal_all().and(ty)).unwrap();
.layout_of(ParamEnv::reveal_all().and(ty))
.unwrap();
assert!(!layout.is_unsized()); assert!(!layout.is_unsized());
if layout.size.bytes() == 0 { if layout.size.bytes() == 0 {
@ -66,7 +64,9 @@ fn get_pass_mode<'a, 'tcx: 'a>(
PassMode::ByRef PassMode::ByRef
} }
} }
layout::Abi::Scalar(scalar) => PassMode::ByVal(scalar_to_clif_type(tcx, scalar.clone())), layout::Abi::Scalar(scalar) => {
PassMode::ByVal(scalar_to_clif_type(tcx, scalar.clone()))
}
// FIXME implement ScalarPair and Vector Abi in a cg_llvm compatible way // FIXME implement ScalarPair and Vector Abi in a cg_llvm compatible way
layout::Abi::ScalarPair(_, _) => PassMode::ByRef, layout::Abi::ScalarPair(_, _) => PassMode::ByRef,
@ -88,10 +88,7 @@ fn adjust_arg_for_abi<'a, 'tcx: 'a>(
} }
} }
fn clif_sig_from_fn_sig<'a, 'tcx: 'a>( fn clif_sig_from_fn_sig<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>, sig: FnSig<'tcx>) -> Signature {
tcx: TyCtxt<'a, 'tcx, 'tcx>,
sig: FnSig<'tcx>,
) -> Signature {
let (call_conv, inputs, output): (CallConv, Vec<Ty>, Ty) = match sig.abi { let (call_conv, inputs, output): (CallConv, Vec<Ty>, Ty) = match sig.abi {
Abi::Rust => (CallConv::SystemV, sig.inputs().to_vec(), sig.output()), Abi::Rust => (CallConv::SystemV, sig.inputs().to_vec(), sig.output()),
Abi::C => (CallConv::SystemV, sig.inputs().to_vec(), sig.output()), Abi::C => (CallConv::SystemV, sig.inputs().to_vec(), sig.output()),
@ -191,7 +188,7 @@ pub fn ty_fn_sig<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ty: Ty<'tcx>) -> ty::FnS
pub fn get_function_name_and_sig<'a, 'tcx>( pub fn get_function_name_and_sig<'a, 'tcx>(
tcx: TyCtxt<'a, 'tcx, 'tcx>, tcx: TyCtxt<'a, 'tcx, 'tcx>,
inst: Instance<'tcx>, inst: Instance<'tcx>,
support_vararg: bool support_vararg: bool,
) -> (String, Signature) { ) -> (String, Signature) {
assert!(!inst.substs.needs_infer() && !inst.substs.has_param_types()); assert!(!inst.substs.needs_infer() && !inst.substs.has_param_types());
let fn_ty = inst.ty(tcx); let fn_ty = inst.ty(tcx);
@ -219,7 +216,8 @@ impl<'a, 'tcx: 'a, B: Backend + 'a> FunctionCx<'a, 'tcx, B> {
/// Instance must be monomorphized /// Instance must be monomorphized
pub fn get_function_ref(&mut self, inst: Instance<'tcx>) -> FuncRef { pub fn get_function_ref(&mut self, inst: Instance<'tcx>) -> FuncRef {
let func_id = import_function(self.tcx, self.module, inst); let func_id = import_function(self.tcx, self.module, inst);
let func_ref = self.module let func_ref = self
.module
.declare_func_in_func(func_id, &mut self.bcx.func); .declare_func_in_func(func_id, &mut self.bcx.func);
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
@ -285,7 +283,12 @@ impl<'a, 'tcx: 'a, B: Backend + 'a> FunctionCx<'a, 'tcx, B> {
if let Some(val) = self.lib_call(name, input_tys, return_ty, &args) { if let Some(val) = self.lib_call(name, input_tys, return_ty, &args) {
CValue::ByVal(val, return_layout) CValue::ByVal(val, return_layout)
} else { } else {
CValue::ByRef(self.bcx.ins().iconst(self.pointer_type, self.pointer_type.bytes() as i64), return_layout) CValue::ByRef(
self.bcx
.ins()
.iconst(self.pointer_type, self.pointer_type.bytes() as i64),
return_layout,
)
} }
} }
@ -322,13 +325,21 @@ fn add_arg_comment<'a, 'tcx: 'a>(
let pass_mode = format!("{:?}", pass_mode); let pass_mode = format!("{:?}", pass_mode);
fx.add_global_comment(format!( fx.add_global_comment(format!(
"{msg:5} {local:>3}{local_field:<5} {param:10} {pass_mode:20} {ssa:10} {ty:?}", "{msg:5} {local:>3}{local_field:<5} {param:10} {pass_mode:20} {ssa:10} {ty:?}",
msg=msg, local=format!("{:?}", local), local_field=local_field, param=param, pass_mode=pass_mode, ssa=format!("{:?}", ssa), ty=ty, msg = msg,
local = format!("{:?}", local),
local_field = local_field,
param = param,
pass_mode = pass_mode,
ssa = format!("{:?}", ssa),
ty = ty,
)); ));
} }
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
fn add_local_header_comment(fx: &mut FunctionCx<impl Backend>) { fn add_local_header_comment(fx: &mut FunctionCx<impl Backend>) {
fx.add_global_comment(format!("msg loc.idx param pass mode ssa flags ty")); fx.add_global_comment(format!(
"msg loc.idx param pass mode ssa flags ty"
));
} }
fn local_place<'a, 'tcx: 'a>( fn local_place<'a, 'tcx: 'a>(
@ -338,7 +349,8 @@ fn local_place<'a, 'tcx: 'a>(
is_ssa: bool, is_ssa: bool,
) -> CPlace<'tcx> { ) -> CPlace<'tcx> {
let place = if is_ssa { let place = if is_ssa {
fx.bcx.declare_var(mir_var(local), fx.clif_type(layout.ty).unwrap()); fx.bcx
.declare_var(mir_var(local), fx.clif_type(layout.ty).unwrap());
CPlace::Var(local, layout) CPlace::Var(local, layout)
} else { } else {
let place = CPlace::new_stack_slot(fx, layout.ty); let place = CPlace::new_stack_slot(fx, layout.ty);
@ -346,15 +358,32 @@ fn local_place<'a, 'tcx: 'a>(
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
{ {
let TyLayout { ty, details } = layout; let TyLayout { ty, details } = layout;
let ty::layout::LayoutDetails { size, align, abi: _, variants: _, fields: _ } = details; let ty::layout::LayoutDetails {
size,
align,
abi: _,
variants: _,
fields: _,
} = details;
match place { match place {
CPlace::Stack(stack_slot, _) => fx.add_entity_comment(stack_slot, format!( CPlace::Stack(stack_slot, _) => fx.add_entity_comment(
"{:?}: {:?} size={} align={},{}", stack_slot,
local, ty, size.bytes(), align.abi.bytes(), align.pref.bytes(), format!(
)), "{:?}: {:?} size={} align={},{}",
local,
ty,
size.bytes(),
align.abi.bytes(),
align.pref.bytes(),
),
),
CPlace::NoPlace(_) => fx.add_global_comment(format!( CPlace::NoPlace(_) => fx.add_global_comment(format!(
"zst {:?}: {:?} size={} align={}, {}", "zst {:?}: {:?} size={} align={}, {}",
local, ty, size.bytes(), align.abi.bytes(), align.pref.bytes(), local,
ty,
size.bytes(),
align.abi.bytes(),
align.pref.bytes(),
)), )),
_ => unreachable!(), _ => unreachable!(),
} }
@ -383,7 +412,16 @@ fn cvalue_for_param<'a, 'tcx: 'a>(
let ebb_param = fx.bcx.append_ebb_param(start_ebb, clif_type); let ebb_param = fx.bcx.append_ebb_param(start_ebb, clif_type);
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
add_arg_comment(fx, "arg", local, local_field, Some(ebb_param), pass_mode, ssa_flags, arg_ty); add_arg_comment(
fx,
"arg",
local,
local_field,
Some(ebb_param),
pass_mode,
ssa_flags,
arg_ty,
);
match pass_mode { match pass_mode {
PassMode::NoPass => unimplemented!("pass mode nopass"), PassMode::NoPass => unimplemented!("pass mode nopass"),
@ -412,7 +450,16 @@ pub fn codegen_fn_prelude<'a, 'tcx: 'a>(
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
{ {
add_local_header_comment(fx); add_local_header_comment(fx);
add_arg_comment(fx, "ret", RETURN_PLACE, None, ret_param, output_pass_mode, ssa_analyzed[&RETURN_PLACE], ret_layout.ty); add_arg_comment(
fx,
"ret",
RETURN_PLACE,
None,
ret_param,
output_pass_mode,
ssa_analyzed[&RETURN_PLACE],
ret_layout.ty,
);
} }
enum ArgKind<'tcx> { enum ArgKind<'tcx> {
@ -440,18 +487,22 @@ pub fn codegen_fn_prelude<'a, 'tcx: 'a>(
let mut params = Vec::new(); let mut params = Vec::new();
for (i, arg_ty) in tupled_arg_tys.iter().enumerate() { for (i, arg_ty) in tupled_arg_tys.iter().enumerate() {
let param = cvalue_for_param(fx, start_ebb, local, Some(i), arg_ty, ssa_analyzed[&local]); let param = cvalue_for_param(
fx,
start_ebb,
local,
Some(i),
arg_ty,
ssa_analyzed[&local],
);
params.push(param); params.push(param);
} }
(local, ArgKind::Spread(params), arg_ty) (local, ArgKind::Spread(params), arg_ty)
} else { } else {
let param = cvalue_for_param(fx, start_ebb, local, None, arg_ty, ssa_analyzed[&local]); let param =
( cvalue_for_param(fx, start_ebb, local, None, arg_ty, ssa_analyzed[&local]);
local, (local, ArgKind::Normal(param), arg_ty)
ArgKind::Normal(param),
arg_ty,
)
} }
}) })
.collect::<Vec<(Local, ArgKind, Ty)>>(); .collect::<Vec<(Local, ArgKind, Ty)>>();
@ -460,7 +511,8 @@ pub fn codegen_fn_prelude<'a, 'tcx: 'a>(
match output_pass_mode { match output_pass_mode {
PassMode::NoPass => { PassMode::NoPass => {
fx.local_map.insert(RETURN_PLACE, CPlace::NoPlace(ret_layout)); fx.local_map
.insert(RETURN_PLACE, CPlace::NoPlace(ret_layout));
} }
PassMode::ByVal(_) => { PassMode::ByVal(_) => {
let is_ssa = !ssa_analyzed let is_ssa = !ssa_analyzed
@ -494,7 +546,9 @@ pub fn codegen_fn_prelude<'a, 'tcx: 'a>(
} }
ArgKind::Spread(params) => { ArgKind::Spread(params) => {
for (i, param) in params.into_iter().enumerate() { for (i, param) in params.into_iter().enumerate() {
place.place_field(fx, mir::Field::new(i)).write_cvalue(fx, param); place
.place_field(fx, mir::Field::new(i))
.write_cvalue(fx, param);
} }
} }
} }
@ -553,12 +607,8 @@ pub fn codegen_terminator_call<'a, 'tcx: 'a>(
.map(|&(ref place, bb)| (trans_place(fx, place), bb)); .map(|&(ref place, bb)| (trans_place(fx, place), bb));
if let ty::FnDef(def_id, substs) = fn_ty.sty { if let ty::FnDef(def_id, substs) = fn_ty.sty {
let instance = ty::Instance::resolve( let instance =
fx.tcx, ty::Instance::resolve(fx.tcx, ty::ParamEnv::reveal_all(), def_id, substs).unwrap();
ty::ParamEnv::reveal_all(),
def_id,
substs,
).unwrap();
match instance.def { match instance.def {
InstanceDef::Intrinsic(_) => { InstanceDef::Intrinsic(_) => {
@ -637,8 +687,12 @@ pub fn codegen_call_inner<'a, 'tcx: 'a>(
// Indirect call // Indirect call
None => { None => {
let func = trans_operand(fx, func.expect("indirect call without func Operand")).load_scalar(fx); let func = trans_operand(fx, func.expect("indirect call without func Operand"))
(Some(func), args.get(0).map(|arg| adjust_arg_for_abi(fx, *arg))) .load_scalar(fx);
(
Some(func),
args.get(0).map(|arg| adjust_arg_for_abi(fx, *arg)),
)
} }
}; };
@ -653,7 +707,9 @@ pub fn codegen_call_inner<'a, 'tcx: 'a>(
.collect::<Vec<_>>(); .collect::<Vec<_>>();
let call_inst = if let Some(func_ref) = func_ref { let call_inst = if let Some(func_ref) = func_ref {
let sig = fx.bcx.import_signature(clif_sig_from_fn_sig(fx.tcx, fn_sig)); let sig = fx
.bcx
.import_signature(clif_sig_from_fn_sig(fx.tcx, fn_sig));
fx.bcx.ins().call_indirect(sig, func_ref, &call_args) fx.bcx.ins().call_indirect(sig, func_ref, &call_args)
} else { } else {
let func_ref = fx.get_function_ref(instance.expect("non-indirect call on non-FnDef type")); let func_ref = fx.get_function_ref(instance.expect("non-indirect call on non-FnDef type"));
@ -666,14 +722,17 @@ pub fn codegen_call_inner<'a, 'tcx: 'a>(
unimpl!("Variadic call for non-C abi {:?}", fn_sig.abi); unimpl!("Variadic call for non-C abi {:?}", fn_sig.abi);
} }
let sig_ref = fx.bcx.func.dfg.call_signature(call_inst).unwrap(); let sig_ref = fx.bcx.func.dfg.call_signature(call_inst).unwrap();
let abi_params = call_args.into_iter().map(|arg| { let abi_params = call_args
let ty = fx.bcx.func.dfg.value_type(arg); .into_iter()
if !ty.is_int() { .map(|arg| {
// FIXME set %al to upperbound on float args once floats are supported let ty = fx.bcx.func.dfg.value_type(arg);
unimpl!("Non int ty {:?} for variadic call", ty); if !ty.is_int() {
} // FIXME set %al to upperbound on float args once floats are supported
AbiParam::new(ty) unimpl!("Non int ty {:?} for variadic call", ty);
}).collect::<Vec<AbiParam>>(); }
AbiParam::new(ty)
})
.collect::<Vec<AbiParam>>();
fx.bcx.func.dfg.signatures[sig_ref].params = abi_params; fx.bcx.func.dfg.signatures[sig_ref].params = abi_params;
} }
@ -700,11 +759,13 @@ pub fn codegen_drop<'a, 'tcx: 'a>(
let fn_sig = ty_fn_sig(fx.tcx, drop_fn_ty); let fn_sig = ty_fn_sig(fx.tcx, drop_fn_ty);
match get_pass_mode(fx.tcx, fn_sig.output(), true) { match get_pass_mode(fx.tcx, fn_sig.output(), true) {
PassMode::NoPass => {}, PassMode::NoPass => {}
_ => unreachable!(), _ => unreachable!(),
}; };
let sig = fx.bcx.import_signature(clif_sig_from_fn_sig(fx.tcx, fn_sig)); let sig = fx
.bcx
.import_signature(clif_sig_from_fn_sig(fx.tcx, fn_sig));
fx.bcx.ins().call_indirect(sig, drop_fn, &[ptr]); fx.bcx.ins().call_indirect(sig, drop_fn, &[ptr]);
} }

View file

@ -15,14 +15,10 @@ use rustc_allocator::{AllocatorTy, ALLOCATOR_METHODS};
/// Returns whether an allocator shim was created /// Returns whether an allocator shim was created
pub fn codegen(sess: &Session, module: &mut Module<impl Backend + 'static>) -> bool { pub fn codegen(sess: &Session, module: &mut Module<impl Backend + 'static>) -> bool {
let any_dynamic_crate = sess let any_dynamic_crate = sess.dependency_formats.borrow().iter().any(|(_, list)| {
.dependency_formats use rustc::middle::dependency_format::Linkage;
.borrow() list.iter().any(|&linkage| linkage == Linkage::Dynamic)
.iter() });
.any(|(_, list)| {
use rustc::middle::dependency_format::Linkage;
list.iter().any(|&linkage| linkage == Linkage::Dynamic)
});
if any_dynamic_crate { if any_dynamic_crate {
false false
} else if let Some(kind) = *sess.allocator_kind.get() { } else if let Some(kind) = *sess.allocator_kind.get() {

View file

@ -66,16 +66,11 @@ fn trans_fn<'a, 'clif, 'tcx: 'a, B: Backend + 'static>(
// Step 2. Declare function // Step 2. Declare function
let (name, sig) = get_function_name_and_sig(tcx, instance, false); let (name, sig) = get_function_name_and_sig(tcx, instance, false);
let func_id = cx.module let func_id = cx.module.declare_function(&name, linkage, &sig).unwrap();
.declare_function(&name, linkage, &sig) let mut debug_context = cx
.unwrap(); .debug_context
let mut debug_context = cx.debug_context.as_mut().map(|debug_context| FunctionDebugContext::new( .as_mut()
tcx, .map(|debug_context| FunctionDebugContext::new(tcx, debug_context, mir, &name, &sig));
debug_context,
mir,
&name,
&sig,
));
// Step 3. Make FunctionBuilder // Step 3. Make FunctionBuilder
let mut func = Function::with_name_signature(ExternalName::user(0, 0), sig); let mut func = Function::with_name_signature(ExternalName::user(0, 0), sig);
@ -127,12 +122,16 @@ fn trans_fn<'a, 'clif, 'tcx: 'a, B: Backend + 'static>(
// Step 9. Define function // Step 9. Define function
cx.caches.context.func = func; cx.caches.context.func = func;
cx.module.define_function(func_id, &mut cx.caches.context).unwrap(); cx.module
.define_function(func_id, &mut cx.caches.context)
.unwrap();
// Step 10. Define debuginfo for function // Step 10. Define debuginfo for function
let context = &cx.caches.context; let context = &cx.caches.context;
let isa = cx.module.isa(); let isa = cx.module.isa();
debug_context.as_mut().map(|x| x.define(tcx, context, isa, &source_info_set)); debug_context
.as_mut()
.map(|x| x.define(tcx, context, isa, &source_info_set));
// Step 11. Clear context to make it usable for the next function // Step 11. Clear context to make it usable for the next function
cx.caches.context.clear(); cx.caches.context.clear();
@ -444,10 +443,14 @@ fn trans_stmt<'a, 'tcx: 'a>(
} }
Rvalue::Cast(CastKind::ReifyFnPointer, operand, ty) => { Rvalue::Cast(CastKind::ReifyFnPointer, operand, ty) => {
let layout = fx.layout_of(ty); let layout = fx.layout_of(ty);
match fx.monomorphize(&operand.ty(&fx.mir.local_decls, fx.tcx)).sty { match fx
.monomorphize(&operand.ty(&fx.mir.local_decls, fx.tcx))
.sty
{
ty::FnDef(def_id, substs) => { ty::FnDef(def_id, substs) => {
let func_ref = fx.get_function_ref( let func_ref = fx.get_function_ref(
Instance::resolve(fx.tcx, ParamEnv::reveal_all(), def_id, substs).unwrap(), Instance::resolve(fx.tcx, ParamEnv::reveal_all(), def_id, substs)
.unwrap(),
); );
let func_addr = fx.bcx.ins().func_addr(fx.pointer_type, func_ref); let func_addr = fx.bcx.ins().func_addr(fx.pointer_type, func_ref);
lval.write_cvalue(fx, CValue::ByVal(func_addr, layout)); lval.write_cvalue(fx, CValue::ByVal(func_addr, layout));
@ -570,9 +573,13 @@ fn trans_stmt<'a, 'tcx: 'a>(
}; };
lval.write_cvalue(fx, CValue::ByVal(res, dest_layout)); lval.write_cvalue(fx, CValue::ByVal(res, dest_layout));
} }
(ty::Adt(adt_def, _substs), ty::Uint(_)) | (ty::Adt(adt_def, _substs), ty::Int(_)) if adt_def.is_enum() => { (ty::Adt(adt_def, _substs), ty::Uint(_))
| (ty::Adt(adt_def, _substs), ty::Int(_))
if adt_def.is_enum() =>
{
// FIXME avoid forcing to stack // FIXME avoid forcing to stack
let place = CPlace::Addr(operand.force_stack(fx), None, operand.layout()); let place =
CPlace::Addr(operand.force_stack(fx), None, operand.layout());
let discr = trans_get_discriminant(fx, place, fx.layout_of(to_ty)); let discr = trans_get_discriminant(fx, place, fx.layout_of(to_ty));
lval.write_cvalue(fx, discr); lval.write_cvalue(fx, discr);
} }
@ -674,9 +681,10 @@ fn codegen_array_len<'a, 'tcx: 'a>(
let len = crate::constant::force_eval_const(fx, len).unwrap_usize(fx.tcx) as i64; let len = crate::constant::force_eval_const(fx, len).unwrap_usize(fx.tcx) as i64;
fx.bcx.ins().iconst(fx.pointer_type, len) fx.bcx.ins().iconst(fx.pointer_type, len)
} }
ty::Slice(_elem_ty) => { ty::Slice(_elem_ty) => place
place.to_addr_maybe_unsized(fx).1.expect("Length metadata for slice place") .to_addr_maybe_unsized(fx)
} .1
.expect("Length metadata for slice place"),
_ => bug!("Rvalue::Len({:?})", place), _ => bug!("Rvalue::Len({:?})", place),
} }
} }
@ -1012,7 +1020,9 @@ fn trans_ptr_binop<'a, 'tcx: 'a>(
ret_ty: Ty<'tcx>, ret_ty: Ty<'tcx>,
) -> CValue<'tcx> { ) -> CValue<'tcx> {
let not_fat = match lhs.layout().ty.sty { let not_fat = match lhs.layout().ty.sty {
ty::RawPtr(TypeAndMut { ty, mutbl: _ }) => ty.is_sized(fx.tcx.at(DUMMY_SP), ParamEnv::reveal_all()), ty::RawPtr(TypeAndMut { ty, mutbl: _ }) => {
ty.is_sized(fx.tcx.at(DUMMY_SP), ParamEnv::reveal_all())
}
ty::FnPtr(..) => true, ty::FnPtr(..) => true,
_ => bug!("trans_ptr_binop on non ptr"), _ => bug!("trans_ptr_binop on non ptr"),
}; };

View file

@ -246,7 +246,7 @@ pub enum CPlace<'tcx> {
Var(Local, TyLayout<'tcx>), Var(Local, TyLayout<'tcx>),
Addr(Value, Option<Value>, TyLayout<'tcx>), Addr(Value, Option<Value>, TyLayout<'tcx>),
Stack(StackSlot, TyLayout<'tcx>), Stack(StackSlot, TyLayout<'tcx>),
NoPlace(TyLayout<'tcx>) NoPlace(TyLayout<'tcx>),
} }
impl<'a, 'tcx: 'a> CPlace<'tcx> { impl<'a, 'tcx: 'a> CPlace<'tcx> {
@ -255,11 +255,14 @@ impl<'a, 'tcx: 'a> CPlace<'tcx> {
CPlace::Var(_, layout) CPlace::Var(_, layout)
| CPlace::Addr(_, _, layout) | CPlace::Addr(_, _, layout)
| CPlace::Stack(_, layout) | CPlace::Stack(_, layout)
| CPlace::NoPlace(layout) => layout, | CPlace::NoPlace(layout) => layout,
} }
} }
pub fn new_stack_slot(fx: &mut FunctionCx<'a, 'tcx, impl Backend>, ty: Ty<'tcx>) -> CPlace<'tcx> { pub fn new_stack_slot(
fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
ty: Ty<'tcx>,
) -> CPlace<'tcx> {
let layout = fx.layout_of(ty); let layout = fx.layout_of(ty);
assert!(!layout.is_unsized()); assert!(!layout.is_unsized());
if layout.size.bytes() == 0 { if layout.size.bytes() == 0 {
@ -281,12 +284,16 @@ impl<'a, 'tcx: 'a> CPlace<'tcx> {
assert!(extra.is_none(), "unsized values are not yet supported"); assert!(extra.is_none(), "unsized values are not yet supported");
CValue::ByRef(addr, layout) CValue::ByRef(addr, layout)
} }
CPlace::Stack(stack_slot, layout) => { CPlace::Stack(stack_slot, layout) => CValue::ByRef(
CValue::ByRef(fx.bcx.ins().stack_addr(fx.pointer_type, stack_slot, 0), layout) fx.bcx.ins().stack_addr(fx.pointer_type, stack_slot, 0),
} layout,
CPlace::NoPlace(layout) => { ),
CValue::ByRef(fx.bcx.ins().iconst(fx.pointer_type, fx.pointer_type.bytes() as i64), layout) CPlace::NoPlace(layout) => CValue::ByRef(
} fx.bcx
.ins()
.iconst(fx.pointer_type, fx.pointer_type.bytes() as i64),
layout,
),
} }
} }
@ -303,9 +310,10 @@ impl<'a, 'tcx: 'a> CPlace<'tcx> {
) -> (Value, Option<Value>) { ) -> (Value, Option<Value>) {
match self { match self {
CPlace::Addr(addr, extra, _layout) => (addr, extra), CPlace::Addr(addr, extra, _layout) => (addr, extra),
CPlace::Stack(stack_slot, _layout) => { CPlace::Stack(stack_slot, _layout) => (
(fx.bcx.ins().stack_addr(fx.pointer_type, stack_slot, 0), None) fx.bcx.ins().stack_addr(fx.pointer_type, stack_slot, 0),
} None,
),
CPlace::NoPlace(_) => (fx.bcx.ins().iconst(fx.pointer_type, 45), None), CPlace::NoPlace(_) => (fx.bcx.ins().iconst(fx.pointer_type, 45), None),
CPlace::Var(_, _) => bug!("Expected CPlace::Addr, found CPlace::Var"), CPlace::Var(_, _) => bug!("Expected CPlace::Addr, found CPlace::Var"),
} }
@ -364,9 +372,10 @@ impl<'a, 'tcx: 'a> CPlace<'tcx> {
return; return;
} }
CPlace::Addr(addr, None, dst_layout) => (addr, dst_layout), CPlace::Addr(addr, None, dst_layout) => (addr, dst_layout),
CPlace::Stack(stack_slot, dst_layout) => { CPlace::Stack(stack_slot, dst_layout) => (
(fx.bcx.ins().stack_addr(fx.pointer_type, stack_slot, 0), dst_layout) fx.bcx.ins().stack_addr(fx.pointer_type, stack_slot, 0),
} dst_layout,
),
CPlace::NoPlace(layout) => { CPlace::NoPlace(layout) => {
assert!(layout.size.bytes() == 0); assert!(layout.size.bytes() == 0);
assert!(from.layout().size.bytes() == 0); assert!(from.layout().size.bytes() == 0);
@ -389,7 +398,14 @@ impl<'a, 'tcx: 'a> CPlace<'tcx> {
let size = dst_layout.size.bytes(); let size = dst_layout.size.bytes();
let src_align = src_layout.align.abi.bytes() as u8; let src_align = src_layout.align.abi.bytes() as u8;
let dst_align = dst_layout.align.abi.bytes() as u8; let dst_align = dst_layout.align.abi.bytes() as u8;
fx.bcx.emit_small_memcpy(fx.module.target_config(), addr, from, size, dst_align, src_align); fx.bcx.emit_small_memcpy(
fx.module.target_config(),
addr,
from,
size,
dst_align,
src_align,
);
} }
} }
} }
@ -419,10 +435,7 @@ impl<'a, 'tcx: 'a> CPlace<'tcx> {
) -> CPlace<'tcx> { ) -> CPlace<'tcx> {
let (elem_layout, addr) = match self.layout().ty.sty { let (elem_layout, addr) = match self.layout().ty.sty {
ty::Array(elem_ty, _) => (fx.layout_of(elem_ty), self.to_addr(fx)), ty::Array(elem_ty, _) => (fx.layout_of(elem_ty), self.to_addr(fx)),
ty::Slice(elem_ty) => ( ty::Slice(elem_ty) => (fx.layout_of(elem_ty), self.to_addr_maybe_unsized(fx).0),
fx.layout_of(elem_ty),
self.to_addr_maybe_unsized(fx).0,
),
_ => bug!("place_index({:?})", self.layout().ty), _ => bug!("place_index({:?})", self.layout().ty),
}; };
@ -472,9 +485,7 @@ impl<'a, 'tcx: 'a> CPlace<'tcx> {
match dest.layout().abi { match dest.layout().abi {
Abi::ScalarPair(ref a, _) => { Abi::ScalarPair(ref a, _) => {
let dest_addr = dest.to_addr(fx); let dest_addr = dest.to_addr(fx);
fx.bcx fx.bcx.ins().store(MemFlags::new(), value, dest_addr, 0);
.ins()
.store(MemFlags::new(), value, dest_addr, 0);
fx.bcx.ins().store( fx.bcx.ins().store(
MemFlags::new(), MemFlags::new(),
extra.expect("unsized type without metadata"), extra.expect("unsized type without metadata"),
@ -494,12 +505,8 @@ impl<'a, 'tcx: 'a> CPlace<'tcx> {
assert!(!self.layout().is_unsized()); assert!(!self.layout().is_unsized());
match self { match self {
CPlace::Var(var, _) => CPlace::Var(var, layout), CPlace::Var(var, _) => CPlace::Var(var, layout),
CPlace::Addr(addr, extra, _) => { CPlace::Addr(addr, extra, _) => CPlace::Addr(addr, extra, layout),
CPlace::Addr(addr, extra, layout) CPlace::Stack(stack_slot, _) => CPlace::Stack(stack_slot, layout),
}
CPlace::Stack(stack_slot, _) => {
CPlace::Stack(stack_slot, layout)
}
CPlace::NoPlace(_) => { CPlace::NoPlace(_) => {
assert!(layout.size.bytes() == 0); assert!(layout.size.bytes() == 0);
CPlace::NoPlace(layout) CPlace::NoPlace(layout)

View file

@ -5,7 +5,8 @@ use rustc::mir::interpret::{
}; };
use rustc::ty::{Const, LazyConst}; use rustc::ty::{Const, LazyConst};
use rustc_mir::interpret::{ use rustc_mir::interpret::{
EvalContext, MPlaceTy, Machine, Memory, MemoryKind, OpTy, PlaceTy, Pointer, StackPopCleanup, ImmTy, EvalContext, ImmTy, MPlaceTy, Machine, Memory, MemoryKind, OpTy, PlaceTy, Pointer,
StackPopCleanup,
}; };
use cranelift_module::*; use cranelift_module::*;
@ -110,12 +111,12 @@ fn trans_const_value<'a, 'tcx: 'a>(
let bits = const_.val.try_to_bits(layout.size).unwrap(); let bits = const_.val.try_to_bits(layout.size).unwrap();
CValue::const_val(fx, ty, bits as i128 as i64) CValue::const_val(fx, ty, bits as i128 as i64)
} }
ty::FnDef(_def_id, _substs) => { ty::FnDef(_def_id, _substs) => CValue::ByRef(
CValue::ByRef( fx.bcx
fx.bcx.ins().iconst(fx.pointer_type, fx.pointer_type.bytes() as i64), .ins()
layout .iconst(fx.pointer_type, fx.pointer_type.bytes() as i64),
) layout,
} ),
_ => trans_const_place(fx, const_).to_cvalue(fx), _ => trans_const_place(fx, const_).to_cvalue(fx),
} }
} }
@ -370,7 +371,7 @@ impl<'a, 'mir, 'tcx> Machine<'a, 'mir, 'tcx> for TransPlaceInterpreter {
ptr ptr
} }
fn stack_push(_: &mut EvalContext<'a, 'mir, 'tcx, Self>) -> EvalResult<'tcx>{ fn stack_push(_: &mut EvalContext<'a, 'mir, 'tcx, Self>) -> EvalResult<'tcx> {
Ok(()) Ok(())
} }

View file

@ -5,11 +5,10 @@ use std::marker::PhantomData;
use syntax::source_map::FileName; use syntax::source_map::FileName;
use gimli::write::{ use gimli::write::{
Address, AttributeValue, DwarfUnit, EndianVec, LineProgram, Range, Address, AttributeValue, DwarfUnit, EndianVec, FileId, LineProgram, LineString,
RangeList, Result, SectionId, UnitEntryId, LineStringTable, Range, RangeList, Result, SectionId, Sections, UnitEntryId, Writer,
Writer, FileId, LineStringTable, LineString, Sections,
}; };
use gimli::{Encoding, Format, RunTimeEndian, LineEncoding}; use gimli::{Encoding, Format, LineEncoding, RunTimeEndian};
use faerie::*; use faerie::*;
@ -22,28 +21,35 @@ fn target_endian(tcx: TyCtxt) -> RunTimeEndian {
} }
} }
fn line_program_add_file(line_program: &mut LineProgram, line_strings: &mut LineStringTable, file: &FileName) -> FileId { fn line_program_add_file(
line_program: &mut LineProgram,
line_strings: &mut LineStringTable,
file: &FileName,
) -> FileId {
match file { match file {
FileName::Real(path) => { FileName::Real(path) => {
let dir_name = LineString::new(path.parent().unwrap().to_str().unwrap().as_bytes(), line_program.encoding(), line_strings); let dir_name = LineString::new(
let dir_id = path.parent().unwrap().to_str().unwrap().as_bytes(),
line_program.add_directory(dir_name); line_program.encoding(),
let file_name = LineString::new(path.file_name().unwrap().to_str().unwrap().as_bytes(), line_program.encoding(), line_strings); line_strings,
line_program.add_file( );
file_name, let dir_id = line_program.add_directory(dir_name);
dir_id, let file_name = LineString::new(
None, path.file_name().unwrap().to_str().unwrap().as_bytes(),
) line_program.encoding(),
line_strings,
);
line_program.add_file(file_name, dir_id, None)
} }
// FIXME give more appropriate file names // FIXME give more appropriate file names
_ => { _ => {
let dir_id = line_program.default_directory(); let dir_id = line_program.default_directory();
let dummy_file_name = LineString::new(file.to_string().into_bytes(), line_program.encoding(), line_strings); let dummy_file_name = LineString::new(
line_program.add_file( file.to_string().into_bytes(),
dummy_file_name, line_program.encoding(),
dir_id, line_strings,
None, );
) line_program.add_file(dummy_file_name, dir_id, None)
} }
} }
} }
@ -133,7 +139,7 @@ impl<'a, 'tcx: 'a> DebugContext<'tcx> {
); );
} }
DebugContext { DebugContext {
endian: target_endian(tcx), endian: target_endian(tcx),
symbols: indexmap::IndexSet::new(), symbols: indexmap::IndexSet::new(),
@ -155,7 +161,10 @@ impl<'a, 'tcx: 'a> DebugContext<'tcx> {
let entry = self.dwarf.unit.get_mut(entry_id); let entry = self.dwarf.unit.get_mut(entry_id);
entry.set(gimli::DW_AT_decl_file, AttributeValue::FileIndex(Some(file_id))); entry.set(
gimli::DW_AT_decl_file,
AttributeValue::FileIndex(Some(file_id)),
);
entry.set( entry.set(
gimli::DW_AT_decl_line, gimli::DW_AT_decl_line,
AttributeValue::Udata(loc.line as u64), AttributeValue::Udata(loc.line as u64),
@ -182,11 +191,7 @@ impl<'a, 'tcx: 'a> DebugContext<'tcx> {
let _: Result<()> = sections.for_each_mut(|id, section| { let _: Result<()> = sections.for_each_mut(|id, section| {
if !section.writer.slice().is_empty() { if !section.writer.slice().is_empty() {
artifact artifact
.declare_with( .declare_with(id.name(), Decl::DebugSection, section.writer.take())
id.name(),
Decl::DebugSection,
section.writer.take(),
)
.unwrap(); .unwrap();
} }
Ok(()) Ok(())
@ -233,7 +238,10 @@ impl<'a, 'b, 'tcx: 'b> FunctionDebugContext<'a, 'tcx> {
// FIXME: add to appropriate scope intead of root // FIXME: add to appropriate scope intead of root
let scope = debug_context.dwarf.unit.root(); let scope = debug_context.dwarf.unit.root();
let entry_id = debug_context.dwarf.unit.add(scope, gimli::DW_TAG_subprogram); let entry_id = debug_context
.dwarf
.unit
.add(scope, gimli::DW_TAG_subprogram);
let entry = debug_context.dwarf.unit.get_mut(entry_id); let entry = debug_context.dwarf.unit.get_mut(entry_id);
let name_id = debug_context.dwarf.strings.add(name); let name_id = debug_context.dwarf.strings.add(name);
entry.set( entry.set(
@ -314,13 +322,16 @@ impl<'a, 'b, 'tcx: 'b> FunctionDebugContext<'a, 'tcx> {
let entry = self.debug_context.dwarf.unit.get_mut(self.entry_id); let entry = self.debug_context.dwarf.unit.get_mut(self.entry_id);
entry.set(gimli::DW_AT_high_pc, AttributeValue::Udata(end as u64)); entry.set(gimli::DW_AT_high_pc, AttributeValue::Udata(end as u64));
self.debug_context.unit_range_list.0.push(Range::StartLength { self.debug_context
begin: Address::Relative { .unit_range_list
symbol: self.symbol, .0
addend: 0, .push(Range::StartLength {
}, begin: Address::Relative {
length: end as u64, symbol: self.symbol,
}); addend: 0,
},
length: end as u64,
});
} }
} }
@ -331,7 +342,7 @@ struct WriterRelocate {
} }
impl WriterRelocate { impl WriterRelocate {
fn new(ctx: & DebugContext) -> Self { fn new(ctx: &DebugContext) -> Self {
WriterRelocate { WriterRelocate {
relocs: Vec::new(), relocs: Vec::new(),
writer: EndianVec::new(ctx.endian), writer: EndianVec::new(ctx.endian),

View file

@ -14,19 +14,19 @@ extern crate rustc_target;
extern crate syntax; extern crate syntax;
use std::any::Any; use std::any::Any;
use std::fs::File;
use std::sync::mpsc;
use std::os::raw::{c_char, c_int};
use std::ffi::CString; use std::ffi::CString;
use std::fs::File;
use std::os::raw::{c_char, c_int};
use std::sync::mpsc;
use rustc::dep_graph::DepGraph; use rustc::dep_graph::DepGraph;
use rustc::middle::cstore::MetadataLoader; use rustc::middle::cstore::MetadataLoader;
use rustc::mir::mono::{Linkage as RLinkage, Visibility};
use rustc::session::{ use rustc::session::{
config::{DebugInfo, OutputFilenames, OutputType}, config::{DebugInfo, OutputFilenames, OutputType},
CompileIncomplete, CompileIncomplete,
}; };
use rustc::ty::query::Providers; use rustc::ty::query::Providers;
use rustc::mir::mono::{Linkage as RLinkage, Visibility};
use rustc_codegen_ssa::back::linker::LinkerInfo; use rustc_codegen_ssa::back::linker::LinkerInfo;
use rustc_codegen_ssa::CrateInfo; use rustc_codegen_ssa::CrateInfo;
use rustc_codegen_utils::codegen_backend::CodegenBackend; use rustc_codegen_utils::codegen_backend::CodegenBackend;
@ -62,7 +62,7 @@ mod prelude {
pub use std::collections::{HashMap, HashSet}; pub use std::collections::{HashMap, HashSet};
pub use syntax::ast::{FloatTy, IntTy, UintTy}; pub use syntax::ast::{FloatTy, IntTy, UintTy};
pub use syntax::source_map::{DUMMY_SP, Span, Pos}; pub use syntax::source_map::{Pos, Span, DUMMY_SP};
pub use rustc::bug; pub use rustc::bug;
pub use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE}; pub use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
@ -84,18 +84,17 @@ mod prelude {
pub use rustc_mir::monomorphize::{collector, MonoItem}; pub use rustc_mir::monomorphize::{collector, MonoItem};
pub use rustc_codegen_ssa::mir::operand::{OperandRef, OperandValue}; pub use rustc_codegen_ssa::mir::operand::{OperandRef, OperandValue};
pub use rustc_codegen_ssa::{CodegenResults, CompiledModule, ModuleKind};
pub use rustc_codegen_ssa::traits::*; pub use rustc_codegen_ssa::traits::*;
pub use rustc_codegen_ssa::{CodegenResults, CompiledModule, ModuleKind};
pub use cranelift::codegen::ir::{ pub use cranelift::codegen::ir::{
condcodes::IntCC, function::Function, ExternalName, FuncRef, Inst, StackSlot, SourceLoc, condcodes::IntCC, function::Function, ExternalName, FuncRef, Inst, SourceLoc, StackSlot,
}; };
pub use cranelift::codegen::isa::CallConv; pub use cranelift::codegen::isa::CallConv;
pub use cranelift::codegen::Context; pub use cranelift::codegen::Context;
pub use cranelift::prelude::*; pub use cranelift::prelude::*;
pub use cranelift_module::{ pub use cranelift_module::{
self, Backend, DataContext, DataId, FuncId, FuncOrDataId, Linkage, self, Backend, DataContext, DataId, FuncId, FuncOrDataId, Linkage, Module,
Module,
}; };
pub use cranelift_simplejit::{SimpleJITBackend, SimpleJITBuilder}; pub use cranelift_simplejit::{SimpleJITBackend, SimpleJITBuilder};
@ -251,11 +250,12 @@ impl CodegenBackend for CraneliftCodegenBackend {
let f: extern "C" fn(c_int, *const *const c_char) -> c_int = let f: extern "C" fn(c_int, *const *const c_char) -> c_int =
unsafe { ::std::mem::transmute(finalized_main) }; unsafe { ::std::mem::transmute(finalized_main) };
let args = ::std::env::var("JIT_ARGS").unwrap_or_else(|_|String::new()); let args = ::std::env::var("JIT_ARGS").unwrap_or_else(|_| String::new());
let args = args let args = args
.split(" ") .split(" ")
.chain(Some(&*tcx.crate_name(LOCAL_CRATE).as_str().to_string())) .chain(Some(&*tcx.crate_name(LOCAL_CRATE).as_str().to_string()))
.map(|arg| CString::new(arg).unwrap()).collect::<Vec<_>>(); .map(|arg| CString::new(arg).unwrap())
.collect::<Vec<_>>();
let argv = args.iter().map(|arg| arg.as_ptr()).collect::<Vec<_>>(); let argv = args.iter().map(|arg| arg.as_ptr()).collect::<Vec<_>>();
// TODO: Rust doesn't care, but POSIX argv has a NULL sentinel at the end // TODO: Rust doesn't care, but POSIX argv has a NULL sentinel at the end
@ -274,14 +274,14 @@ impl CodegenBackend for CraneliftCodegenBackend {
) )
.unwrap(), .unwrap(),
); );
assert_eq!( assert_eq!(pointer_ty(tcx), module.target_config().pointer_type());
pointer_ty(tcx),
module.target_config().pointer_type()
);
module module
}; };
let emit_module = |name: &str, kind: ModuleKind, mut module: Module<FaerieBackend>, debug: Option<DebugContext>| { let emit_module = |name: &str,
kind: ModuleKind,
mut module: Module<FaerieBackend>,
debug: Option<DebugContext>| {
module.finalize_definitions(); module.finalize_definitions();
let mut artifact = module.finish().artifact; let mut artifact = module.finish().artifact;
@ -306,9 +306,13 @@ impl CodegenBackend for CraneliftCodegenBackend {
let mut faerie_module = new_module("some_file".to_string()); let mut faerie_module = new_module("some_file".to_string());
let mut debug = if tcx.sess.opts.debuginfo != DebugInfo::None let mut debug = if tcx.sess.opts.debuginfo != DebugInfo::None
&& !tcx.sess.target.target.options.is_like_osx // macOS debuginfo doesn't work yet (see #303) // macOS debuginfo doesn't work yet (see #303)
&& !tcx.sess.target.target.options.is_like_osx
{ {
let debug = DebugContext::new(tcx, faerie_module.target_config().pointer_type().bytes() as u8); let debug = DebugContext::new(
tcx,
faerie_module.target_config().pointer_type().bytes() as u8,
);
Some(debug) Some(debug)
} else { } else {
None None
@ -319,14 +323,23 @@ impl CodegenBackend for CraneliftCodegenBackend {
tcx.sess.abort_if_errors(); tcx.sess.abort_if_errors();
let mut allocator_module = new_module("allocator_shim.o".to_string()); let mut allocator_module = new_module("allocator_shim.o".to_string());
let created_alloc_shim = let created_alloc_shim = crate::allocator::codegen(tcx.sess, &mut allocator_module);
crate::allocator::codegen(tcx.sess, &mut allocator_module);
return Box::new(CodegenResults { return Box::new(CodegenResults {
crate_name: tcx.crate_name(LOCAL_CRATE), crate_name: tcx.crate_name(LOCAL_CRATE),
modules: vec![emit_module("dummy_name", ModuleKind::Regular, faerie_module, debug)], modules: vec![emit_module(
"dummy_name",
ModuleKind::Regular,
faerie_module,
debug,
)],
allocator_module: if created_alloc_shim { allocator_module: if created_alloc_shim {
Some(emit_module("allocator_shim", ModuleKind::Allocator, allocator_module, None)) Some(emit_module(
"allocator_shim",
ModuleKind::Allocator,
allocator_module,
None,
))
} else { } else {
None None
}, },
@ -377,7 +390,7 @@ fn build_isa(sess: &Session) -> Box<isa::TargetIsa + 'static> {
let mut flags_builder = settings::builder(); let mut flags_builder = settings::builder();
flags_builder.enable("is_pic").unwrap(); flags_builder.enable("is_pic").unwrap();
flags_builder.set("probestack_enabled", "false").unwrap(); // ___cranelift_probestack is not provided flags_builder.set("probestack_enabled", "false").unwrap(); // ___cranelift_probestack is not provided
flags_builder.set("enable_verifier", if cfg!(debug_assertions) { flags_builder.set("enable_verifier", if cfg!(debug_assertions) {
"true" "true"
} else { } else {
"false" "false"
@ -438,7 +451,7 @@ fn codegen_mono_items<'a, 'tcx: 'a>(
(RLinkage::Internal, Visibility::Default) => Linkage::Local, (RLinkage::Internal, Visibility::Default) => Linkage::Local,
// FIXME this should get external linkage, but hidden visibility, // FIXME this should get external linkage, but hidden visibility,
// not internal linkage and default visibility // not internal linkage and default visibility
| (RLinkage::External, Visibility::Hidden) => Linkage::Export, (RLinkage::External, Visibility::Hidden) => Linkage::Export,
_ => panic!("{:?} = {:?} {:?}", mono_item, linkage, vis), _ => panic!("{:?} = {:?} {:?}", mono_item, linkage, vis),
}; };
base::trans_mono_item(&mut cx, mono_item, linkage); base::trans_mono_item(&mut cx, mono_item, linkage);

View file

@ -70,10 +70,7 @@ pub struct CommentWriter {
} }
impl CommentWriter { impl CommentWriter {
pub fn new<'a, 'tcx: 'a>( pub fn new<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>, instance: Instance<'tcx>) -> Self {
tcx: TyCtxt<'a, 'tcx, 'tcx>,
instance: Instance<'tcx>,
) -> Self {
CommentWriter { CommentWriter {
global_comments: vec![ global_comments: vec![
format!("symbol {}", tcx.symbol_name(instance).as_str()), format!("symbol {}", tcx.symbol_name(instance).as_str()),
@ -158,7 +155,11 @@ impl<'a, 'tcx: 'a, B: Backend + 'a> FunctionCx<'a, 'tcx, B> {
self.clif_comments.global_comments.push(comment.into()); self.clif_comments.global_comments.push(comment.into());
} }
pub fn add_entity_comment<'s, S: Into<Cow<'s, str>>, E: Into<AnyEntity>>(&mut self, entity: E, comment: S) { pub fn add_entity_comment<'s, S: Into<Cow<'s, str>>, E: Into<AnyEntity>>(
&mut self,
entity: E,
comment: S,
) {
use std::collections::hash_map::Entry; use std::collections::hash_map::Entry;
match self.clif_comments.entity_comments.entry(entity.into()) { match self.clif_comments.entity_comments.entry(entity.into()) {
Entry::Occupied(mut occ) => { Entry::Occupied(mut occ) => {
@ -196,12 +197,18 @@ impl<'a, 'tcx: 'a, B: Backend + 'a> FunctionCx<'a, 'tcx, B> {
); );
let mut clif = String::new(); let mut clif = String::new();
::cranelift::codegen::write::decorate_function(&mut &self.clif_comments, &mut clif, &self.bcx.func, None) ::cranelift::codegen::write::decorate_function(
.unwrap(); &mut &self.clif_comments,
&mut clif,
&self.bcx.func,
None,
)
.unwrap();
match ::std::fs::File::create(clif_file_name) { match ::std::fs::File::create(clif_file_name) {
Ok(mut file) => { Ok(mut file) => {
let target_triple: ::target_lexicon::Triple = self.tcx.sess.target.target.llvm_target.parse().unwrap(); let target_triple: ::target_lexicon::Triple =
self.tcx.sess.target.target.llvm_target.parse().unwrap();
writeln!(file, "test compile").unwrap(); writeln!(file, "test compile").unwrap();
writeln!(file, "set is_pic").unwrap(); writeln!(file, "set is_pic").unwrap();
writeln!(file, "target {}", target_triple).unwrap(); writeln!(file, "target {}", target_triple).unwrap();
@ -209,7 +216,9 @@ impl<'a, 'tcx: 'a, B: Backend + 'a> FunctionCx<'a, 'tcx, B> {
file.write(clif.as_bytes()).unwrap(); file.write(clif.as_bytes()).unwrap();
} }
Err(e) => { Err(e) => {
self.tcx.sess.warn(&format!("err opening clif file: {:?}", e)); self.tcx
.sess
.warn(&format!("err opening clif file: {:?}", e));
} }
} }
} }

View file

@ -16,21 +16,22 @@ pub fn unsized_info<'a, 'tcx: 'a>(
) -> Value { ) -> Value {
let (source, target) = fx.tcx.struct_lockstep_tails(source, target); let (source, target) = fx.tcx.struct_lockstep_tails(source, target);
match (&source.sty, &target.sty) { match (&source.sty, &target.sty) {
(&ty::Array(_, len), &ty::Slice(_)) => { (&ty::Array(_, len), &ty::Slice(_)) => fx
fx.bcx.ins().iconst(fx.pointer_type, len.unwrap_usize(fx.tcx) as i64) .bcx
} .ins()
.iconst(fx.pointer_type, len.unwrap_usize(fx.tcx) as i64),
(&ty::Dynamic(..), &ty::Dynamic(..)) => { (&ty::Dynamic(..), &ty::Dynamic(..)) => {
// For now, upcasts are limited to changes in marker // For now, upcasts are limited to changes in marker
// traits, and hence never actually require an actual // traits, and hence never actually require an actual
// change to the vtable. // change to the vtable.
old_info.expect("unsized_info: missing old info for trait upcast") old_info.expect("unsized_info: missing old info for trait upcast")
} }
(_, &ty::Dynamic(ref data, ..)) => { (_, &ty::Dynamic(ref data, ..)) => crate::vtable::get_vtable(fx, source, data.principal()),
crate::vtable::get_vtable(fx, source, data.principal()) _ => bug!(
} "unsized_info: invalid unsizing {:?} -> {:?}",
_ => bug!("unsized_info: invalid unsizing {:?} -> {:?}", source,
source, target
target), ),
} }
} }
@ -39,15 +40,12 @@ pub fn unsize_thin_ptr<'a, 'tcx: 'a>(
fx: &mut FunctionCx<'a, 'tcx, impl Backend>, fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
src: Value, src: Value,
src_ty: Ty<'tcx>, src_ty: Ty<'tcx>,
dst_ty: Ty<'tcx> dst_ty: Ty<'tcx>,
) -> (Value, Value) { ) -> (Value, Value) {
match (&src_ty.sty, &dst_ty.sty) { match (&src_ty.sty, &dst_ty.sty) {
(&ty::Ref(_, a, _), (&ty::Ref(_, a, _), &ty::Ref(_, b, _))
&ty::Ref(_, b, _)) | | (&ty::Ref(_, a, _), &ty::RawPtr(ty::TypeAndMut { ty: b, .. }))
(&ty::Ref(_, a, _), | (&ty::RawPtr(ty::TypeAndMut { ty: a, .. }), &ty::RawPtr(ty::TypeAndMut { ty: b, .. })) => {
&ty::RawPtr(ty::TypeAndMut { ty: b, .. })) |
(&ty::RawPtr(ty::TypeAndMut { ty: a, .. }),
&ty::RawPtr(ty::TypeAndMut { ty: b, .. })) => {
assert!(!fx.layout_of(a).is_unsized()); assert!(!fx.layout_of(a).is_unsized());
(src, unsized_info(fx, a, b, None)) (src, unsized_info(fx, a, b, None))
} }
@ -88,11 +86,14 @@ pub fn coerce_unsized_into<'a, 'tcx: 'a>(
fx: &mut FunctionCx<'a, 'tcx, impl Backend>, fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
src: CValue<'tcx>, src: CValue<'tcx>,
dst: CPlace<'tcx>, dst: CPlace<'tcx>,
) { ) {
let src_ty = src.layout().ty; let src_ty = src.layout().ty;
let dst_ty = dst.layout().ty; let dst_ty = dst.layout().ty;
let mut coerce_ptr = || { let mut coerce_ptr = || {
let (base, info) = if fx.layout_of(src.layout().ty.builtin_deref(true).unwrap().ty).is_unsized() { let (base, info) = if fx
.layout_of(src.layout().ty.builtin_deref(true).unwrap().ty)
.is_unsized()
{
// fat-ptr to fat-ptr unsize preserves the vtable // fat-ptr to fat-ptr unsize preserves the vtable
// i.e., &'a fmt::Debug+Send => &'a fmt::Debug // i.e., &'a fmt::Debug+Send => &'a fmt::Debug
src.load_value_pair(fx) src.load_value_pair(fx)
@ -103,11 +104,9 @@ pub fn coerce_unsized_into<'a, 'tcx: 'a>(
dst.write_cvalue(fx, CValue::ByValPair(base, info, dst.layout())); dst.write_cvalue(fx, CValue::ByValPair(base, info, dst.layout()));
}; };
match (&src_ty.sty, &dst_ty.sty) { match (&src_ty.sty, &dst_ty.sty) {
(&ty::Ref(..), &ty::Ref(..)) | (&ty::Ref(..), &ty::Ref(..))
(&ty::Ref(..), &ty::RawPtr(..)) | | (&ty::Ref(..), &ty::RawPtr(..))
(&ty::RawPtr(..), &ty::RawPtr(..)) => { | (&ty::RawPtr(..), &ty::RawPtr(..)) => coerce_ptr(),
coerce_ptr()
}
(&ty::Adt(def_a, _), &ty::Adt(def_b, _)) => { (&ty::Adt(def_a, _), &ty::Adt(def_b, _)) => {
assert_eq!(def_a, def_b); assert_eq!(def_a, def_b);
@ -126,13 +125,14 @@ pub fn coerce_unsized_into<'a, 'tcx: 'a>(
} }
} }
} }
_ => bug!("coerce_unsized_into: invalid coercion {:?} -> {:?}", _ => bug!(
src_ty, "coerce_unsized_into: invalid coercion {:?} -> {:?}",
dst_ty), src_ty,
dst_ty
),
} }
} }
// Adapted from https://github.com/rust-lang/rust/blob/2a663555ddf36f6b041445894a8c175cd1bc718c/src/librustc_codegen_ssa/glue.rs // Adapted from https://github.com/rust-lang/rust/blob/2a663555ddf36f6b041445894a8c175cd1bc718c/src/librustc_codegen_ssa/glue.rs
pub fn size_and_align_of_dst<'a, 'tcx: 'a>( pub fn size_and_align_of_dst<'a, 'tcx: 'a>(
@ -142,8 +142,14 @@ pub fn size_and_align_of_dst<'a, 'tcx: 'a>(
) -> (Value, Value) { ) -> (Value, Value) {
let layout = fx.layout_of(ty); let layout = fx.layout_of(ty);
if !layout.is_unsized() { if !layout.is_unsized() {
let size = fx.bcx.ins().iconst(fx.pointer_type, layout.size.bytes() as i64); let size = fx
let align = fx.bcx.ins().iconst(fx.pointer_type, layout.align.abi.bytes() as i64); .bcx
.ins()
.iconst(fx.pointer_type, layout.size.bytes() as i64);
let align = fx
.bcx
.ins()
.iconst(fx.pointer_type, layout.align.abi.bytes() as i64);
return (size, align); return (size, align);
} }
match ty.sty { match ty.sty {
@ -158,8 +164,12 @@ pub fn size_and_align_of_dst<'a, 'tcx: 'a>(
let unit = layout.field(fx, 0); let unit = layout.field(fx, 0);
// The info in this case is the length of the str, so the size is that // The info in this case is the length of the str, so the size is that
// times the unit size. // times the unit size.
(fx.bcx.ins().imul_imm(info, unit.size.bytes() as i64), (
fx.bcx.ins().iconst(fx.pointer_type, unit.align.abi.bytes() as i64)) fx.bcx.ins().imul_imm(info, unit.size.bytes() as i64),
fx.bcx
.ins()
.iconst(fx.pointer_type, unit.align.abi.bytes() as i64),
)
} }
_ => { _ => {
// First get the size of all statically known fields. // First get the size of all statically known fields.
@ -196,7 +206,10 @@ pub fn size_and_align_of_dst<'a, 'tcx: 'a>(
// Choose max of two known alignments (combined value must // Choose max of two known alignments (combined value must
// be aligned according to more restrictive of the two). // be aligned according to more restrictive of the two).
let cmp = fx.bcx.ins().icmp(IntCC::UnsignedGreaterThan, sized_align, unsized_align); let cmp = fx
.bcx
.ins()
.icmp(IntCC::UnsignedGreaterThan, sized_align, unsized_align);
let align = fx.bcx.ins().select(cmp, sized_align, unsized_align); let align = fx.bcx.ins().select(cmp, sized_align, unsized_align);
// Issue #27023: must add any necessary padding to `size` // Issue #27023: must add any necessary padding to `size`
@ -212,7 +225,7 @@ pub fn size_and_align_of_dst<'a, 'tcx: 'a>(
let addend = fx.bcx.ins().iadd_imm(align, -1); let addend = fx.bcx.ins().iadd_imm(align, -1);
let add = fx.bcx.ins().iadd(size, addend); let add = fx.bcx.ins().iadd(size, addend);
let zero = fx.bcx.ins().iconst(fx.pointer_type, 0); let zero = fx.bcx.ins().iconst(fx.pointer_type, 0);
let neg = fx.bcx.ins().isub(zero, align); let neg = fx.bcx.ins().isub(zero, align);
let size = fx.bcx.ins().band(add, neg); let size = fx.bcx.ins().band(add, neg);
(size, align) (size, align)