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::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]);
}

View File

@ -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() {

View File

@ -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"),
};

View File

@ -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)

View File

@ -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(())
}

View File

@ -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),

View File

@ -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);

View File

@ -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));
}
}
}

View File

@ -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)