Rustfmt
This commit is contained in:
parent
a87aa4f583
commit
f02490d960
167
src/abi.rs
167
src/abi.rs
@ -2,7 +2,7 @@
|
||||
use std::iter;
|
||||
|
||||
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 crate::prelude::*;
|
||||
@ -32,11 +32,11 @@ pub fn scalar_to_clif_type(tcx: TyCtxt, scalar: Scalar) -> Type {
|
||||
Integer::I32 => types::I32,
|
||||
Integer::I64 => types::I64,
|
||||
Integer::I128 => unimpl!("u/i128"),
|
||||
}
|
||||
},
|
||||
Primitive::Float(flt) => match flt {
|
||||
FloatTy::F32 => types::F32,
|
||||
FloatTy::F64 => types::F64,
|
||||
}
|
||||
},
|
||||
Primitive::Pointer => pointer_ty(tcx),
|
||||
}
|
||||
}
|
||||
@ -46,9 +46,7 @@ fn get_pass_mode<'a, 'tcx: 'a>(
|
||||
ty: Ty<'tcx>,
|
||||
is_return: bool,
|
||||
) -> PassMode {
|
||||
let layout = tcx
|
||||
.layout_of(ParamEnv::reveal_all().and(ty))
|
||||
.unwrap();
|
||||
let layout = tcx.layout_of(ParamEnv::reveal_all().and(ty)).unwrap();
|
||||
assert!(!layout.is_unsized());
|
||||
|
||||
if layout.size.bytes() == 0 {
|
||||
@ -66,7 +64,9 @@ fn get_pass_mode<'a, 'tcx: 'a>(
|
||||
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
|
||||
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>(
|
||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
sig: FnSig<'tcx>,
|
||||
) -> Signature {
|
||||
fn clif_sig_from_fn_sig<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>, sig: FnSig<'tcx>) -> Signature {
|
||||
let (call_conv, inputs, output): (CallConv, Vec<Ty>, Ty) = match sig.abi {
|
||||
Abi::Rust => (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>(
|
||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
inst: Instance<'tcx>,
|
||||
support_vararg: bool
|
||||
support_vararg: bool,
|
||||
) -> (String, Signature) {
|
||||
assert!(!inst.substs.needs_infer() && !inst.substs.has_param_types());
|
||||
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
|
||||
pub fn get_function_ref(&mut self, inst: Instance<'tcx>) -> FuncRef {
|
||||
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);
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
@ -285,7 +283,12 @@ pub fn easy_call(
|
||||
if let Some(val) = self.lib_call(name, input_tys, return_ty, &args) {
|
||||
CValue::ByVal(val, return_layout)
|
||||
} 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);
|
||||
fx.add_global_comment(format!(
|
||||
"{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)]
|
||||
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>(
|
||||
@ -338,7 +349,8 @@ fn local_place<'a, 'tcx: 'a>(
|
||||
is_ssa: bool,
|
||||
) -> CPlace<'tcx> {
|
||||
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)
|
||||
} else {
|
||||
let place = CPlace::new_stack_slot(fx, layout.ty);
|
||||
@ -346,15 +358,32 @@ fn local_place<'a, 'tcx: 'a>(
|
||||
#[cfg(debug_assertions)]
|
||||
{
|
||||
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 {
|
||||
CPlace::Stack(stack_slot, _) => fx.add_entity_comment(stack_slot, format!(
|
||||
"{:?}: {:?} size={} align={},{}",
|
||||
local, ty, size.bytes(), align.abi.bytes(), align.pref.bytes(),
|
||||
)),
|
||||
CPlace::Stack(stack_slot, _) => fx.add_entity_comment(
|
||||
stack_slot,
|
||||
format!(
|
||||
"{:?}: {:?} size={} align={},{}",
|
||||
local,
|
||||
ty,
|
||||
size.bytes(),
|
||||
align.abi.bytes(),
|
||||
align.pref.bytes(),
|
||||
),
|
||||
),
|
||||
CPlace::NoPlace(_) => fx.add_global_comment(format!(
|
||||
"zst {:?}: {:?} size={} align={}, {}",
|
||||
local, ty, size.bytes(), align.abi.bytes(), align.pref.bytes(),
|
||||
local,
|
||||
ty,
|
||||
size.bytes(),
|
||||
align.abi.bytes(),
|
||||
align.pref.bytes(),
|
||||
)),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
@ -383,7 +412,16 @@ fn cvalue_for_param<'a, 'tcx: 'a>(
|
||||
let ebb_param = fx.bcx.append_ebb_param(start_ebb, clif_type);
|
||||
|
||||
#[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 {
|
||||
PassMode::NoPass => unimplemented!("pass mode nopass"),
|
||||
@ -412,7 +450,16 @@ pub fn codegen_fn_prelude<'a, 'tcx: 'a>(
|
||||
#[cfg(debug_assertions)]
|
||||
{
|
||||
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> {
|
||||
@ -440,18 +487,22 @@ enum ArgKind<'tcx> {
|
||||
|
||||
let mut params = Vec::new();
|
||||
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);
|
||||
}
|
||||
|
||||
(local, ArgKind::Spread(params), arg_ty)
|
||||
} else {
|
||||
let param = cvalue_for_param(fx, start_ebb, local, None, arg_ty, ssa_analyzed[&local]);
|
||||
(
|
||||
local,
|
||||
ArgKind::Normal(param),
|
||||
arg_ty,
|
||||
)
|
||||
let param =
|
||||
cvalue_for_param(fx, start_ebb, local, None, arg_ty, ssa_analyzed[&local]);
|
||||
(local, ArgKind::Normal(param), arg_ty)
|
||||
}
|
||||
})
|
||||
.collect::<Vec<(Local, ArgKind, Ty)>>();
|
||||
@ -460,7 +511,8 @@ enum ArgKind<'tcx> {
|
||||
|
||||
match output_pass_mode {
|
||||
PassMode::NoPass => {
|
||||
fx.local_map.insert(RETURN_PLACE, CPlace::NoPlace(ret_layout));
|
||||
fx.local_map
|
||||
.insert(RETURN_PLACE, CPlace::NoPlace(ret_layout));
|
||||
}
|
||||
PassMode::ByVal(_) => {
|
||||
let is_ssa = !ssa_analyzed
|
||||
@ -494,7 +546,9 @@ enum ArgKind<'tcx> {
|
||||
}
|
||||
ArgKind::Spread(params) => {
|
||||
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));
|
||||
|
||||
if let ty::FnDef(def_id, substs) = fn_ty.sty {
|
||||
let instance = ty::Instance::resolve(
|
||||
fx.tcx,
|
||||
ty::ParamEnv::reveal_all(),
|
||||
def_id,
|
||||
substs,
|
||||
).unwrap();
|
||||
let instance =
|
||||
ty::Instance::resolve(fx.tcx, ty::ParamEnv::reveal_all(), def_id, substs).unwrap();
|
||||
|
||||
match instance.def {
|
||||
InstanceDef::Intrinsic(_) => {
|
||||
@ -637,8 +687,12 @@ pub fn codegen_call_inner<'a, 'tcx: 'a>(
|
||||
|
||||
// Indirect call
|
||||
None => {
|
||||
let func = trans_operand(fx, func.expect("indirect call without func Operand")).load_scalar(fx);
|
||||
(Some(func), args.get(0).map(|arg| adjust_arg_for_abi(fx, *arg)))
|
||||
let func = trans_operand(fx, func.expect("indirect call without func Operand"))
|
||||
.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<_>>();
|
||||
|
||||
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)
|
||||
} else {
|
||||
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);
|
||||
}
|
||||
let sig_ref = fx.bcx.func.dfg.call_signature(call_inst).unwrap();
|
||||
let abi_params = call_args.into_iter().map(|arg| {
|
||||
let ty = fx.bcx.func.dfg.value_type(arg);
|
||||
if !ty.is_int() {
|
||||
// FIXME set %al to upperbound on float args once floats are supported
|
||||
unimpl!("Non int ty {:?} for variadic call", ty);
|
||||
}
|
||||
AbiParam::new(ty)
|
||||
}).collect::<Vec<AbiParam>>();
|
||||
let abi_params = call_args
|
||||
.into_iter()
|
||||
.map(|arg| {
|
||||
let ty = fx.bcx.func.dfg.value_type(arg);
|
||||
if !ty.is_int() {
|
||||
// FIXME set %al to upperbound on float args once floats are supported
|
||||
unimpl!("Non int ty {:?} for variadic call", ty);
|
||||
}
|
||||
AbiParam::new(ty)
|
||||
})
|
||||
.collect::<Vec<AbiParam>>();
|
||||
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);
|
||||
|
||||
match get_pass_mode(fx.tcx, fn_sig.output(), true) {
|
||||
PassMode::NoPass => {},
|
||||
PassMode::NoPass => {}
|
||||
_ => 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]);
|
||||
}
|
||||
|
||||
|
@ -15,14 +15,10 @@
|
||||
|
||||
/// Returns whether an allocator shim was created
|
||||
pub fn codegen(sess: &Session, module: &mut Module<impl Backend + 'static>) -> bool {
|
||||
let any_dynamic_crate = sess
|
||||
.dependency_formats
|
||||
.borrow()
|
||||
.iter()
|
||||
.any(|(_, list)| {
|
||||
use rustc::middle::dependency_format::Linkage;
|
||||
list.iter().any(|&linkage| linkage == Linkage::Dynamic)
|
||||
});
|
||||
let any_dynamic_crate = sess.dependency_formats.borrow().iter().any(|(_, list)| {
|
||||
use rustc::middle::dependency_format::Linkage;
|
||||
list.iter().any(|&linkage| linkage == Linkage::Dynamic)
|
||||
});
|
||||
if any_dynamic_crate {
|
||||
false
|
||||
} else if let Some(kind) = *sess.allocator_kind.get() {
|
||||
|
50
src/base.rs
50
src/base.rs
@ -66,16 +66,11 @@ fn trans_fn<'a, 'clif, 'tcx: 'a, B: Backend + 'static>(
|
||||
|
||||
// Step 2. Declare function
|
||||
let (name, sig) = get_function_name_and_sig(tcx, instance, false);
|
||||
let func_id = cx.module
|
||||
.declare_function(&name, linkage, &sig)
|
||||
.unwrap();
|
||||
let mut debug_context = cx.debug_context.as_mut().map(|debug_context| FunctionDebugContext::new(
|
||||
tcx,
|
||||
debug_context,
|
||||
mir,
|
||||
&name,
|
||||
&sig,
|
||||
));
|
||||
let func_id = cx.module.declare_function(&name, linkage, &sig).unwrap();
|
||||
let mut debug_context = cx
|
||||
.debug_context
|
||||
.as_mut()
|
||||
.map(|debug_context| FunctionDebugContext::new(tcx, debug_context, mir, &name, &sig));
|
||||
|
||||
// Step 3. Make FunctionBuilder
|
||||
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
|
||||
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
|
||||
let context = &cx.caches.context;
|
||||
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
|
||||
cx.caches.context.clear();
|
||||
@ -444,10 +443,14 @@ fn trans_stmt<'a, 'tcx: 'a>(
|
||||
}
|
||||
Rvalue::Cast(CastKind::ReifyFnPointer, operand, 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) => {
|
||||
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);
|
||||
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));
|
||||
}
|
||||
(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
|
||||
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));
|
||||
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;
|
||||
fx.bcx.ins().iconst(fx.pointer_type, len)
|
||||
}
|
||||
ty::Slice(_elem_ty) => {
|
||||
place.to_addr_maybe_unsized(fx).1.expect("Length metadata for slice place")
|
||||
}
|
||||
ty::Slice(_elem_ty) => place
|
||||
.to_addr_maybe_unsized(fx)
|
||||
.1
|
||||
.expect("Length metadata for slice place"),
|
||||
_ => bug!("Rvalue::Len({:?})", place),
|
||||
}
|
||||
}
|
||||
@ -1012,7 +1020,9 @@ fn trans_ptr_binop<'a, 'tcx: 'a>(
|
||||
ret_ty: Ty<'tcx>,
|
||||
) -> CValue<'tcx> {
|
||||
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,
|
||||
_ => bug!("trans_ptr_binop on non ptr"),
|
||||
};
|
||||
|
@ -246,7 +246,7 @@ pub enum CPlace<'tcx> {
|
||||
Var(Local, TyLayout<'tcx>),
|
||||
Addr(Value, Option<Value>, TyLayout<'tcx>),
|
||||
Stack(StackSlot, TyLayout<'tcx>),
|
||||
NoPlace(TyLayout<'tcx>)
|
||||
NoPlace(TyLayout<'tcx>),
|
||||
}
|
||||
|
||||
impl<'a, 'tcx: 'a> CPlace<'tcx> {
|
||||
@ -255,11 +255,14 @@ pub fn layout(&self) -> TyLayout<'tcx> {
|
||||
CPlace::Var(_, layout)
|
||||
| CPlace::Addr(_, _, 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);
|
||||
assert!(!layout.is_unsized());
|
||||
if layout.size.bytes() == 0 {
|
||||
@ -281,12 +284,16 @@ pub fn to_cvalue(self, fx: &mut FunctionCx<'a, 'tcx, impl Backend>) -> CValue<'t
|
||||
assert!(extra.is_none(), "unsized values are not yet supported");
|
||||
CValue::ByRef(addr, layout)
|
||||
}
|
||||
CPlace::Stack(stack_slot, layout) => {
|
||||
CValue::ByRef(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::Stack(stack_slot, layout) => CValue::ByRef(
|
||||
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,
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
@ -303,9 +310,10 @@ pub fn to_addr_maybe_unsized(
|
||||
) -> (Value, Option<Value>) {
|
||||
match self {
|
||||
CPlace::Addr(addr, extra, _layout) => (addr, extra),
|
||||
CPlace::Stack(stack_slot, _layout) => {
|
||||
(fx.bcx.ins().stack_addr(fx.pointer_type, stack_slot, 0), None)
|
||||
}
|
||||
CPlace::Stack(stack_slot, _layout) => (
|
||||
fx.bcx.ins().stack_addr(fx.pointer_type, stack_slot, 0),
|
||||
None,
|
||||
),
|
||||
CPlace::NoPlace(_) => (fx.bcx.ins().iconst(fx.pointer_type, 45), None),
|
||||
CPlace::Var(_, _) => bug!("Expected CPlace::Addr, found CPlace::Var"),
|
||||
}
|
||||
@ -364,9 +372,10 @@ pub fn write_cvalue(self, fx: &mut FunctionCx<'a, 'tcx, impl Backend>, from: CVa
|
||||
return;
|
||||
}
|
||||
CPlace::Addr(addr, None, dst_layout) => (addr, dst_layout),
|
||||
CPlace::Stack(stack_slot, dst_layout) => {
|
||||
(fx.bcx.ins().stack_addr(fx.pointer_type, stack_slot, 0), dst_layout)
|
||||
}
|
||||
CPlace::Stack(stack_slot, dst_layout) => (
|
||||
fx.bcx.ins().stack_addr(fx.pointer_type, stack_slot, 0),
|
||||
dst_layout,
|
||||
),
|
||||
CPlace::NoPlace(layout) => {
|
||||
assert!(layout.size.bytes() == 0);
|
||||
assert!(from.layout().size.bytes() == 0);
|
||||
@ -389,7 +398,14 @@ pub fn write_cvalue(self, fx: &mut FunctionCx<'a, 'tcx, impl Backend>, from: CVa
|
||||
let size = dst_layout.size.bytes();
|
||||
let src_align = src_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 @@ pub fn place_index(
|
||||
) -> CPlace<'tcx> {
|
||||
let (elem_layout, addr) = match self.layout().ty.sty {
|
||||
ty::Array(elem_ty, _) => (fx.layout_of(elem_ty), self.to_addr(fx)),
|
||||
ty::Slice(elem_ty) => (
|
||||
fx.layout_of(elem_ty),
|
||||
self.to_addr_maybe_unsized(fx).0,
|
||||
),
|
||||
ty::Slice(elem_ty) => (fx.layout_of(elem_ty), self.to_addr_maybe_unsized(fx).0),
|
||||
_ => bug!("place_index({:?})", self.layout().ty),
|
||||
};
|
||||
|
||||
@ -472,9 +485,7 @@ pub fn write_place_ref(self, fx: &mut FunctionCx<'a, 'tcx, impl Backend>, dest:
|
||||
match dest.layout().abi {
|
||||
Abi::ScalarPair(ref a, _) => {
|
||||
let dest_addr = dest.to_addr(fx);
|
||||
fx.bcx
|
||||
.ins()
|
||||
.store(MemFlags::new(), value, dest_addr, 0);
|
||||
fx.bcx.ins().store(MemFlags::new(), value, dest_addr, 0);
|
||||
fx.bcx.ins().store(
|
||||
MemFlags::new(),
|
||||
extra.expect("unsized type without metadata"),
|
||||
@ -494,12 +505,8 @@ pub fn unchecked_cast_to(self, layout: TyLayout<'tcx>) -> Self {
|
||||
assert!(!self.layout().is_unsized());
|
||||
match self {
|
||||
CPlace::Var(var, _) => CPlace::Var(var, layout),
|
||||
CPlace::Addr(addr, extra, _) => {
|
||||
CPlace::Addr(addr, extra, layout)
|
||||
}
|
||||
CPlace::Stack(stack_slot, _) => {
|
||||
CPlace::Stack(stack_slot, layout)
|
||||
}
|
||||
CPlace::Addr(addr, extra, _) => CPlace::Addr(addr, extra, layout),
|
||||
CPlace::Stack(stack_slot, _) => CPlace::Stack(stack_slot, layout),
|
||||
CPlace::NoPlace(_) => {
|
||||
assert!(layout.size.bytes() == 0);
|
||||
CPlace::NoPlace(layout)
|
||||
|
@ -5,7 +5,8 @@
|
||||
};
|
||||
use rustc::ty::{Const, LazyConst};
|
||||
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::*;
|
||||
@ -110,12 +111,12 @@ fn trans_const_value<'a, 'tcx: 'a>(
|
||||
let bits = const_.val.try_to_bits(layout.size).unwrap();
|
||||
CValue::const_val(fx, ty, bits as i128 as i64)
|
||||
}
|
||||
ty::FnDef(_def_id, _substs) => {
|
||||
CValue::ByRef(
|
||||
fx.bcx.ins().iconst(fx.pointer_type, fx.pointer_type.bytes() as i64),
|
||||
layout
|
||||
)
|
||||
}
|
||||
ty::FnDef(_def_id, _substs) => CValue::ByRef(
|
||||
fx.bcx
|
||||
.ins()
|
||||
.iconst(fx.pointer_type, fx.pointer_type.bytes() as i64),
|
||||
layout,
|
||||
),
|
||||
_ => trans_const_place(fx, const_).to_cvalue(fx),
|
||||
}
|
||||
}
|
||||
@ -370,7 +371,7 @@ fn tag_new_allocation(
|
||||
ptr
|
||||
}
|
||||
|
||||
fn stack_push(_: &mut EvalContext<'a, 'mir, 'tcx, Self>) -> EvalResult<'tcx>{
|
||||
fn stack_push(_: &mut EvalContext<'a, 'mir, 'tcx, Self>) -> EvalResult<'tcx> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -5,11 +5,10 @@
|
||||
use syntax::source_map::FileName;
|
||||
|
||||
use gimli::write::{
|
||||
Address, AttributeValue, DwarfUnit, EndianVec, LineProgram, Range,
|
||||
RangeList, Result, SectionId, UnitEntryId,
|
||||
Writer, FileId, LineStringTable, LineString, Sections,
|
||||
Address, AttributeValue, DwarfUnit, EndianVec, FileId, LineProgram, LineString,
|
||||
LineStringTable, Range, RangeList, Result, SectionId, Sections, UnitEntryId, Writer,
|
||||
};
|
||||
use gimli::{Encoding, Format, RunTimeEndian, LineEncoding};
|
||||
use gimli::{Encoding, Format, LineEncoding, RunTimeEndian};
|
||||
|
||||
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 {
|
||||
FileName::Real(path) => {
|
||||
let dir_name = LineString::new(path.parent().unwrap().to_str().unwrap().as_bytes(), line_program.encoding(), line_strings);
|
||||
let dir_id =
|
||||
line_program.add_directory(dir_name);
|
||||
let file_name = LineString::new(path.file_name().unwrap().to_str().unwrap().as_bytes(), line_program.encoding(), line_strings);
|
||||
line_program.add_file(
|
||||
file_name,
|
||||
dir_id,
|
||||
None,
|
||||
)
|
||||
let dir_name = LineString::new(
|
||||
path.parent().unwrap().to_str().unwrap().as_bytes(),
|
||||
line_program.encoding(),
|
||||
line_strings,
|
||||
);
|
||||
let dir_id = line_program.add_directory(dir_name);
|
||||
let file_name = LineString::new(
|
||||
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
|
||||
_ => {
|
||||
let dir_id = line_program.default_directory();
|
||||
let dummy_file_name = LineString::new(file.to_string().into_bytes(), line_program.encoding(), line_strings);
|
||||
line_program.add_file(
|
||||
dummy_file_name,
|
||||
dir_id,
|
||||
None,
|
||||
)
|
||||
let dummy_file_name = LineString::new(
|
||||
file.to_string().into_bytes(),
|
||||
line_program.encoding(),
|
||||
line_strings,
|
||||
);
|
||||
line_program.add_file(dummy_file_name, dir_id, None)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -133,7 +139,7 @@ pub fn new(tcx: TyCtxt, address_size: u8) -> Self {
|
||||
);
|
||||
}
|
||||
|
||||
DebugContext {
|
||||
DebugContext {
|
||||
endian: target_endian(tcx),
|
||||
symbols: indexmap::IndexSet::new(),
|
||||
|
||||
@ -155,7 +161,10 @@ fn emit_location(&mut self, tcx: TyCtxt<'a, 'tcx, 'tcx>, entry_id: UnitEntryId,
|
||||
|
||||
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(
|
||||
gimli::DW_AT_decl_line,
|
||||
AttributeValue::Udata(loc.line as u64),
|
||||
@ -182,11 +191,7 @@ pub fn emit(&mut self, artifact: &mut Artifact) {
|
||||
let _: Result<()> = sections.for_each_mut(|id, section| {
|
||||
if !section.writer.slice().is_empty() {
|
||||
artifact
|
||||
.declare_with(
|
||||
id.name(),
|
||||
Decl::DebugSection,
|
||||
section.writer.take(),
|
||||
)
|
||||
.declare_with(id.name(), Decl::DebugSection, section.writer.take())
|
||||
.unwrap();
|
||||
}
|
||||
Ok(())
|
||||
@ -233,7 +238,10 @@ pub fn new(
|
||||
// FIXME: add to appropriate scope intead of 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 name_id = debug_context.dwarf.strings.add(name);
|
||||
entry.set(
|
||||
@ -314,13 +322,16 @@ pub fn define(
|
||||
let entry = self.debug_context.dwarf.unit.get_mut(self.entry_id);
|
||||
entry.set(gimli::DW_AT_high_pc, AttributeValue::Udata(end as u64));
|
||||
|
||||
self.debug_context.unit_range_list.0.push(Range::StartLength {
|
||||
begin: Address::Relative {
|
||||
symbol: self.symbol,
|
||||
addend: 0,
|
||||
},
|
||||
length: end as u64,
|
||||
});
|
||||
self.debug_context
|
||||
.unit_range_list
|
||||
.0
|
||||
.push(Range::StartLength {
|
||||
begin: Address::Relative {
|
||||
symbol: self.symbol,
|
||||
addend: 0,
|
||||
},
|
||||
length: end as u64,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -331,7 +342,7 @@ struct WriterRelocate {
|
||||
}
|
||||
|
||||
impl WriterRelocate {
|
||||
fn new(ctx: & DebugContext) -> Self {
|
||||
fn new(ctx: &DebugContext) -> Self {
|
||||
WriterRelocate {
|
||||
relocs: Vec::new(),
|
||||
writer: EndianVec::new(ctx.endian),
|
||||
|
61
src/lib.rs
61
src/lib.rs
@ -14,19 +14,19 @@
|
||||
extern crate syntax;
|
||||
|
||||
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::fs::File;
|
||||
use std::os::raw::{c_char, c_int};
|
||||
use std::sync::mpsc;
|
||||
|
||||
use rustc::dep_graph::DepGraph;
|
||||
use rustc::middle::cstore::MetadataLoader;
|
||||
use rustc::mir::mono::{Linkage as RLinkage, Visibility};
|
||||
use rustc::session::{
|
||||
config::{DebugInfo, OutputFilenames, OutputType},
|
||||
CompileIncomplete,
|
||||
};
|
||||
use rustc::ty::query::Providers;
|
||||
use rustc::mir::mono::{Linkage as RLinkage, Visibility};
|
||||
use rustc_codegen_ssa::back::linker::LinkerInfo;
|
||||
use rustc_codegen_ssa::CrateInfo;
|
||||
use rustc_codegen_utils::codegen_backend::CodegenBackend;
|
||||
@ -62,7 +62,7 @@ mod prelude {
|
||||
pub use std::collections::{HashMap, HashSet};
|
||||
|
||||
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::hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
|
||||
@ -84,18 +84,17 @@ mod prelude {
|
||||
pub use rustc_mir::monomorphize::{collector, MonoItem};
|
||||
|
||||
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::{CodegenResults, CompiledModule, ModuleKind};
|
||||
|
||||
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::Context;
|
||||
pub use cranelift::prelude::*;
|
||||
pub use cranelift_module::{
|
||||
self, Backend, DataContext, DataId, FuncId, FuncOrDataId, Linkage,
|
||||
Module,
|
||||
self, Backend, DataContext, DataId, FuncId, FuncOrDataId, Linkage, Module,
|
||||
};
|
||||
pub use cranelift_simplejit::{SimpleJITBackend, SimpleJITBuilder};
|
||||
|
||||
@ -251,11 +250,12 @@ fn codegen_crate<'a, 'tcx>(
|
||||
let f: extern "C" fn(c_int, *const *const c_char) -> c_int =
|
||||
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
|
||||
.split(" ")
|
||||
.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<_>>();
|
||||
// TODO: Rust doesn't care, but POSIX argv has a NULL sentinel at the end
|
||||
|
||||
@ -274,14 +274,14 @@ fn codegen_crate<'a, 'tcx>(
|
||||
)
|
||||
.unwrap(),
|
||||
);
|
||||
assert_eq!(
|
||||
pointer_ty(tcx),
|
||||
module.target_config().pointer_type()
|
||||
);
|
||||
assert_eq!(pointer_ty(tcx), module.target_config().pointer_type());
|
||||
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();
|
||||
let mut artifact = module.finish().artifact;
|
||||
|
||||
@ -306,9 +306,13 @@ fn codegen_crate<'a, 'tcx>(
|
||||
let mut faerie_module = new_module("some_file".to_string());
|
||||
|
||||
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)
|
||||
} else {
|
||||
None
|
||||
@ -319,14 +323,23 @@ fn codegen_crate<'a, 'tcx>(
|
||||
tcx.sess.abort_if_errors();
|
||||
|
||||
let mut allocator_module = new_module("allocator_shim.o".to_string());
|
||||
let created_alloc_shim =
|
||||
crate::allocator::codegen(tcx.sess, &mut allocator_module);
|
||||
let created_alloc_shim = crate::allocator::codegen(tcx.sess, &mut allocator_module);
|
||||
|
||||
return Box::new(CodegenResults {
|
||||
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 {
|
||||
Some(emit_module("allocator_shim", ModuleKind::Allocator, allocator_module, None))
|
||||
Some(emit_module(
|
||||
"allocator_shim",
|
||||
ModuleKind::Allocator,
|
||||
allocator_module,
|
||||
None,
|
||||
))
|
||||
} else {
|
||||
None
|
||||
},
|
||||
@ -377,7 +390,7 @@ fn build_isa(sess: &Session) -> Box<isa::TargetIsa + 'static> {
|
||||
let mut flags_builder = settings::builder();
|
||||
flags_builder.enable("is_pic").unwrap();
|
||||
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"
|
||||
} else {
|
||||
"false"
|
||||
@ -438,7 +451,7 @@ fn codegen_mono_items<'a, 'tcx: 'a>(
|
||||
(RLinkage::Internal, Visibility::Default) => Linkage::Local,
|
||||
// FIXME this should get external linkage, but hidden visibility,
|
||||
// not internal linkage and default visibility
|
||||
| (RLinkage::External, Visibility::Hidden) => Linkage::Export,
|
||||
(RLinkage::External, Visibility::Hidden) => Linkage::Export,
|
||||
_ => panic!("{:?} = {:?} {:?}", mono_item, linkage, vis),
|
||||
};
|
||||
base::trans_mono_item(&mut cx, mono_item, linkage);
|
||||
|
@ -70,10 +70,7 @@ pub struct CommentWriter {
|
||||
}
|
||||
|
||||
impl CommentWriter {
|
||||
pub fn new<'a, 'tcx: 'a>(
|
||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
instance: Instance<'tcx>,
|
||||
) -> Self {
|
||||
pub fn new<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>, instance: Instance<'tcx>) -> Self {
|
||||
CommentWriter {
|
||||
global_comments: vec![
|
||||
format!("symbol {}", tcx.symbol_name(instance).as_str()),
|
||||
@ -158,7 +155,11 @@ pub fn add_global_comment<S: Into<String>>(&mut self, comment: S) {
|
||||
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;
|
||||
match self.clif_comments.entity_comments.entry(entity.into()) {
|
||||
Entry::Occupied(mut occ) => {
|
||||
@ -196,12 +197,18 @@ pub fn write_clif_file(&mut self) {
|
||||
);
|
||||
|
||||
let mut clif = String::new();
|
||||
::cranelift::codegen::write::decorate_function(&mut &self.clif_comments, &mut clif, &self.bcx.func, None)
|
||||
.unwrap();
|
||||
::cranelift::codegen::write::decorate_function(
|
||||
&mut &self.clif_comments,
|
||||
&mut clif,
|
||||
&self.bcx.func,
|
||||
None,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
match ::std::fs::File::create(clif_file_name) {
|
||||
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, "set is_pic").unwrap();
|
||||
writeln!(file, "target {}", target_triple).unwrap();
|
||||
@ -209,7 +216,9 @@ pub fn write_clif_file(&mut self) {
|
||||
file.write(clif.as_bytes()).unwrap();
|
||||
}
|
||||
Err(e) => {
|
||||
self.tcx.sess.warn(&format!("err opening clif file: {:?}", e));
|
||||
self.tcx
|
||||
.sess
|
||||
.warn(&format!("err opening clif file: {:?}", e));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -16,21 +16,22 @@ pub fn unsized_info<'a, 'tcx: 'a>(
|
||||
) -> Value {
|
||||
let (source, target) = fx.tcx.struct_lockstep_tails(source, target);
|
||||
match (&source.sty, &target.sty) {
|
||||
(&ty::Array(_, len), &ty::Slice(_)) => {
|
||||
fx.bcx.ins().iconst(fx.pointer_type, len.unwrap_usize(fx.tcx) as i64)
|
||||
}
|
||||
(&ty::Array(_, len), &ty::Slice(_)) => fx
|
||||
.bcx
|
||||
.ins()
|
||||
.iconst(fx.pointer_type, len.unwrap_usize(fx.tcx) as i64),
|
||||
(&ty::Dynamic(..), &ty::Dynamic(..)) => {
|
||||
// For now, upcasts are limited to changes in marker
|
||||
// traits, and hence never actually require an actual
|
||||
// change to the vtable.
|
||||
old_info.expect("unsized_info: missing old info for trait upcast")
|
||||
}
|
||||
(_, &ty::Dynamic(ref data, ..)) => {
|
||||
crate::vtable::get_vtable(fx, source, data.principal())
|
||||
}
|
||||
_ => bug!("unsized_info: invalid unsizing {:?} -> {:?}",
|
||||
source,
|
||||
target),
|
||||
(_, &ty::Dynamic(ref data, ..)) => crate::vtable::get_vtable(fx, source, data.principal()),
|
||||
_ => bug!(
|
||||
"unsized_info: invalid unsizing {:?} -> {:?}",
|
||||
source,
|
||||
target
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
@ -39,15 +40,12 @@ pub fn unsize_thin_ptr<'a, 'tcx: 'a>(
|
||||
fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
|
||||
src: Value,
|
||||
src_ty: Ty<'tcx>,
|
||||
dst_ty: Ty<'tcx>
|
||||
dst_ty: Ty<'tcx>,
|
||||
) -> (Value, Value) {
|
||||
match (&src_ty.sty, &dst_ty.sty) {
|
||||
(&ty::Ref(_, a, _),
|
||||
&ty::Ref(_, b, _)) |
|
||||
(&ty::Ref(_, a, _),
|
||||
&ty::RawPtr(ty::TypeAndMut { ty: b, .. })) |
|
||||
(&ty::RawPtr(ty::TypeAndMut { ty: a, .. }),
|
||||
&ty::RawPtr(ty::TypeAndMut { ty: b, .. })) => {
|
||||
(&ty::Ref(_, a, _), &ty::Ref(_, b, _))
|
||||
| (&ty::Ref(_, a, _), &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());
|
||||
(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>,
|
||||
src: CValue<'tcx>,
|
||||
dst: CPlace<'tcx>,
|
||||
) {
|
||||
) {
|
||||
let src_ty = src.layout().ty;
|
||||
let dst_ty = dst.layout().ty;
|
||||
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
|
||||
// i.e., &'a fmt::Debug+Send => &'a fmt::Debug
|
||||
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()));
|
||||
};
|
||||
match (&src_ty.sty, &dst_ty.sty) {
|
||||
(&ty::Ref(..), &ty::Ref(..)) |
|
||||
(&ty::Ref(..), &ty::RawPtr(..)) |
|
||||
(&ty::RawPtr(..), &ty::RawPtr(..)) => {
|
||||
coerce_ptr()
|
||||
}
|
||||
(&ty::Ref(..), &ty::Ref(..))
|
||||
| (&ty::Ref(..), &ty::RawPtr(..))
|
||||
| (&ty::RawPtr(..), &ty::RawPtr(..)) => coerce_ptr(),
|
||||
(&ty::Adt(def_a, _), &ty::Adt(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 {:?} -> {:?}",
|
||||
src_ty,
|
||||
dst_ty),
|
||||
_ => bug!(
|
||||
"coerce_unsized_into: invalid coercion {:?} -> {:?}",
|
||||
src_ty,
|
||||
dst_ty
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 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>(
|
||||
@ -142,8 +142,14 @@ pub fn size_and_align_of_dst<'a, 'tcx: 'a>(
|
||||
) -> (Value, Value) {
|
||||
let layout = fx.layout_of(ty);
|
||||
if !layout.is_unsized() {
|
||||
let size = fx.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);
|
||||
let size = fx
|
||||
.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);
|
||||
}
|
||||
match ty.sty {
|
||||
@ -158,8 +164,12 @@ pub fn size_and_align_of_dst<'a, 'tcx: 'a>(
|
||||
let unit = layout.field(fx, 0);
|
||||
// The info in this case is the length of the str, so the size is that
|
||||
// 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.
|
||||
@ -196,7 +206,10 @@ pub fn size_and_align_of_dst<'a, 'tcx: 'a>(
|
||||
|
||||
// Choose max of two known alignments (combined value must
|
||||
// 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);
|
||||
|
||||
// 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 add = fx.bcx.ins().iadd(size, addend);
|
||||
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);
|
||||
|
||||
(size, align)
|
||||
|
Loading…
Reference in New Issue
Block a user