mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-24 15:54:15 +00:00
Fix non-closure rust-call functions and fix a field projection bug
This commit is contained in:
parent
d470a61d0b
commit
ebaa122d34
20
example.rs
20
example.rs
@ -1,4 +1,4 @@
|
||||
#![feature(no_core)]
|
||||
#![feature(no_core, unboxed_closures)]
|
||||
#![no_core]
|
||||
#![allow(dead_code)]
|
||||
|
||||
@ -122,6 +122,24 @@ fn call_closure_2arg() {
|
||||
})(0u8, 42u16)
|
||||
}
|
||||
|
||||
struct IsNotEmpty;
|
||||
|
||||
impl<'a, 'b> FnOnce<(&'a &'b [u16], )> for IsNotEmpty {
|
||||
type Output = bool;
|
||||
|
||||
#[inline]
|
||||
extern "rust-call" fn call_once(mut self, arg: (&'a &'b [u16], )) -> bool {
|
||||
self.call_mut(arg)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'b> FnMut<(&'a &'b [u16], )> for IsNotEmpty {
|
||||
#[inline]
|
||||
extern "rust-call" fn call_mut(&mut self, arg: (&'a &'b [u16], )) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
fn eq_char(a: char, b: char) -> bool {
|
||||
a == b
|
||||
}
|
||||
|
@ -88,7 +88,7 @@ impl<T: ?Sized> PartialEq for *const T {
|
||||
|
||||
#[lang = "fn_once"]
|
||||
#[rustc_paren_sugar]
|
||||
trait FnOnce<Args> {
|
||||
pub trait FnOnce<Args> {
|
||||
type Output;
|
||||
|
||||
extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
|
||||
@ -96,7 +96,7 @@ trait FnOnce<Args> {
|
||||
|
||||
#[lang = "fn_mut"]
|
||||
#[rustc_paren_sugar]
|
||||
trait FnMut<Args> : FnOnce<Args> {
|
||||
pub trait FnMut<Args> : FnOnce<Args> {
|
||||
extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output;
|
||||
}
|
||||
|
||||
|
73
src/abi.rs
73
src/abi.rs
@ -26,7 +26,6 @@ pub fn cton_sig_from_fn_ty<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>, fn_ty: Ty<
|
||||
)
|
||||
}
|
||||
Abi::System => bug!("system abi should be selected elsewhere"),
|
||||
// TODO: properly implement intrinsics
|
||||
Abi::RustIntrinsic => (CallConv::SystemV, sig.inputs().to_vec(), sig.output()),
|
||||
_ => unimplemented!("unsupported abi {:?}", sig.abi),
|
||||
};
|
||||
@ -122,27 +121,70 @@ pub fn codegen_fn_prelude<'a, 'tcx: 'a>(fx: &mut FunctionCx<'a, 'tcx>, start_ebb
|
||||
offset: None,
|
||||
}); // Dummy stack slot for debugging
|
||||
|
||||
enum ArgKind {
|
||||
Normal(Value),
|
||||
Spread(Vec<Value>),
|
||||
}
|
||||
|
||||
let func_params = fx.mir.args_iter().map(|local| {
|
||||
let layout = fx.layout_of(fx.mir.local_decls[local].ty);
|
||||
let arg_ty = fx.mir.local_decls[local].ty;
|
||||
|
||||
// Adapted from https://github.com/rust-lang/rust/blob/145155dc96757002c7b2e9de8489416e2fdbbd57/src/librustc_codegen_llvm/mir/mod.rs#L442-L482
|
||||
if Some(local) == fx.mir.spread_arg {
|
||||
// This argument (e.g. the last argument in the "rust-call" ABI)
|
||||
// is a tuple that was spread at the ABI level and now we have
|
||||
// to reconstruct it into a tuple local variable, from multiple
|
||||
// individual function arguments.
|
||||
|
||||
let tupled_arg_tys = match arg_ty.sty {
|
||||
ty::TyTuple(ref tys) => tys,
|
||||
_ => bug!("spread argument isn't a tuple?!")
|
||||
};
|
||||
|
||||
let mut ebb_params = Vec::new();
|
||||
for arg_ty in tupled_arg_tys.iter() {
|
||||
let cton_type = fx.cton_type(arg_ty).unwrap_or(types::I64);
|
||||
ebb_params.push(fx.bcx.append_ebb_param(start_ebb, cton_type));
|
||||
}
|
||||
|
||||
(local, ArgKind::Spread(ebb_params), arg_ty)
|
||||
} else {
|
||||
let cton_type = fx.cton_type(arg_ty).unwrap_or(types::I64);
|
||||
(local, ArgKind::Normal(fx.bcx.append_ebb_param(start_ebb, cton_type)), arg_ty)
|
||||
}
|
||||
}).collect::<Vec<(Local, ArgKind, Ty)>>();
|
||||
|
||||
let ret_layout = fx.layout_of(fx.return_type());
|
||||
fx.local_map.insert(RETURN_PLACE, CPlace::Addr(ret_param, ret_layout));
|
||||
|
||||
for (local, arg_kind, ty) in func_params {
|
||||
let layout = fx.layout_of(ty);
|
||||
let stack_slot = fx.bcx.create_stack_slot(StackSlotData {
|
||||
kind: StackSlotKind::ExplicitSlot,
|
||||
size: layout.size.bytes() as u32,
|
||||
offset: None,
|
||||
});
|
||||
let ty = fx.mir.local_decls[local].ty;
|
||||
let cton_type = fx.cton_type(ty).unwrap_or(types::I64);
|
||||
(local, fx.bcx.append_ebb_param(start_ebb, cton_type), ty, stack_slot)
|
||||
}).collect::<Vec<(Local, Value, Ty, StackSlot)>>();
|
||||
|
||||
let ret_layout = fx.layout_of(fx.return_type());
|
||||
fx.local_map.insert(RETURN_PLACE, CPlace::Addr(ret_param, ret_layout));
|
||||
|
||||
for (local, ebb_param, ty, stack_slot) in func_params {
|
||||
let place = CPlace::from_stack_slot(fx, stack_slot, ty);
|
||||
if fx.cton_type(ty).is_some() {
|
||||
place.write_cvalue(fx, CValue::ByVal(ebb_param, place.layout()));
|
||||
} else {
|
||||
place.write_cvalue(fx, CValue::ByRef(ebb_param, place.layout()));
|
||||
|
||||
match arg_kind {
|
||||
ArgKind::Normal(ebb_param) => {
|
||||
if fx.cton_type(ty).is_some() {
|
||||
place.write_cvalue(fx, CValue::ByVal(ebb_param, place.layout()));
|
||||
} else {
|
||||
place.write_cvalue(fx, CValue::ByRef(ebb_param, place.layout()));
|
||||
}
|
||||
}
|
||||
ArgKind::Spread(ebb_params) => {
|
||||
for (i, ebb_param) in ebb_params.into_iter().enumerate() {
|
||||
let sub_place = place.place_field(fx, mir::Field::new(i));
|
||||
if fx.cton_type(sub_place.layout().ty).is_some() {
|
||||
sub_place.write_cvalue(fx, CValue::ByVal(ebb_param, sub_place.layout()));
|
||||
} else {
|
||||
sub_place.write_cvalue(fx, CValue::ByRef(ebb_param, sub_place.layout()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
fx.local_map.insert(local, place);
|
||||
}
|
||||
@ -191,6 +233,7 @@ pub fn codegen_call<'a, 'tcx: 'a>(
|
||||
},
|
||||
_ => bug!("argument to function with \"rust-call\" ABI is not a tuple"),
|
||||
}
|
||||
println!("{:?} {:?}", pack_arg.layout().ty, args.iter().map(|a|a.layout().ty).collect::<Vec<_>>());
|
||||
args
|
||||
} else {
|
||||
args
|
||||
@ -209,7 +252,7 @@ pub fn codegen_call<'a, 'tcx: 'a>(
|
||||
let usize_layout = fx.layout_of(fx.tcx.types.usize);
|
||||
let ret = return_place.unwrap();
|
||||
match intrinsic {
|
||||
"copy" => {
|
||||
"copy" | "copy_nonoverlapping" => {
|
||||
/*let elem_ty = substs.type_at(0);
|
||||
assert_eq!(args.len(), 3);
|
||||
let src = args[0];
|
||||
|
@ -1,6 +1,6 @@
|
||||
use std::fmt;
|
||||
|
||||
use syntax::ast::{IntTy, UintTy};
|
||||
use syntax::ast::{IntTy, UintTy, FloatTy};
|
||||
use rustc_target::spec::{HasTargetSpec, Target};
|
||||
|
||||
use cranelift_module::{Module, FuncId, DataId};
|
||||
@ -46,6 +46,12 @@ pub fn cton_type_from_ty<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ty: Ty<'tcx>
|
||||
}
|
||||
}
|
||||
TypeVariants::TyChar => types::I32,
|
||||
TypeVariants::TyFloat(size) => {
|
||||
match size {
|
||||
FloatTy::F32 => types::I32,
|
||||
FloatTy::F64 => types::I64,
|
||||
}
|
||||
}
|
||||
TypeVariants::TyFnPtr(_) => types::I64,
|
||||
TypeVariants::TyRawPtr(TypeAndMut { ty, mutbl: _ }) | TypeVariants::TyRef(_, ty, _) => {
|
||||
if ty.is_sized(tcx.at(DUMMY_SP), ParamEnv::reveal_all()) {
|
||||
@ -59,6 +65,22 @@ pub fn cton_type_from_ty<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ty: Ty<'tcx>
|
||||
})
|
||||
}
|
||||
|
||||
fn codegen_field<'a, 'tcx: 'a>(
|
||||
fx: &mut FunctionCx<'a, 'tcx>,
|
||||
base: Value,
|
||||
layout: TyLayout<'tcx>,
|
||||
field: mir::Field
|
||||
) -> (Value, TyLayout<'tcx>) {
|
||||
let field_offset = layout.fields.offset(field.index());
|
||||
let field_ty = layout.field(&*fx, field.index());
|
||||
if field_offset.bytes() > 0 {
|
||||
let field_offset = fx.bcx.ins().iconst(types::I64, field_offset.bytes() as i64);
|
||||
(fx.bcx.ins().iadd(base, field_offset), field_ty)
|
||||
} else {
|
||||
(base, field_ty)
|
||||
}
|
||||
}
|
||||
|
||||
/// A read-only value
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub enum CValue<'tcx> {
|
||||
@ -117,29 +139,13 @@ impl<'tcx> CValue<'tcx> {
|
||||
}
|
||||
|
||||
pub fn value_field<'a>(self, fx: &mut FunctionCx<'a, 'tcx>, field: mir::Field) -> CValue<'tcx> where 'tcx: 'a {
|
||||
use rustc::ty::util::IntTypeExt;
|
||||
|
||||
let (base, layout) = match self {
|
||||
CValue::ByRef(addr, layout) => (addr, layout),
|
||||
_ => bug!("place_field for {:?}", self),
|
||||
};
|
||||
let field_offset = layout.fields.offset(field.index());
|
||||
let field_layout = if field.index() == 0 {
|
||||
fx.layout_of(if let ty::TyAdt(adt_def, _) = layout.ty.sty {
|
||||
adt_def.repr.discr_type().to_ty(fx.tcx)
|
||||
} else {
|
||||
// This can only be `0`, for now, so `u8` will suffice.
|
||||
fx.tcx.types.u8
|
||||
})
|
||||
} else {
|
||||
layout.field(&*fx, field.index())
|
||||
};
|
||||
if field_offset.bytes() > 0 {
|
||||
let field_offset = fx.bcx.ins().iconst(types::I64, field_offset.bytes() as i64);
|
||||
CValue::ByRef(fx.bcx.ins().iadd(base, field_offset), field_layout)
|
||||
} else {
|
||||
CValue::ByRef(base, field_layout)
|
||||
}
|
||||
|
||||
let (field_ptr, field_layout) = codegen_field(fx, base, layout, field);
|
||||
CValue::ByRef(field_ptr, field_layout)
|
||||
}
|
||||
|
||||
pub fn const_val<'a>(fx: &mut FunctionCx<'a, 'tcx>, ty: Ty<'tcx>, const_val: i64) -> CValue<'tcx> where 'tcx: 'a {
|
||||
@ -252,14 +258,9 @@ impl<'a, 'tcx: 'a> CPlace<'tcx> {
|
||||
pub fn place_field(self, fx: &mut FunctionCx<'a, 'tcx>, field: mir::Field) -> CPlace<'tcx> {
|
||||
let base = self.expect_addr();
|
||||
let layout = self.layout();
|
||||
let field_offset = layout.fields.offset(field.index());
|
||||
let field_ty = layout.field(&*fx, field.index());
|
||||
if field_offset.bytes() > 0 {
|
||||
let field_offset = fx.bcx.ins().iconst(types::I64, field_offset.bytes() as i64);
|
||||
CPlace::Addr(fx.bcx.ins().iadd(base, field_offset), field_ty)
|
||||
} else {
|
||||
CPlace::Addr(base, field_ty)
|
||||
}
|
||||
|
||||
let (field_ptr, field_layout) = codegen_field(fx, base, layout, field);
|
||||
CPlace::Addr(field_ptr, field_layout)
|
||||
}
|
||||
|
||||
pub fn unchecked_cast_to(self, layout: TyLayout<'tcx>) -> Self {
|
||||
|
Loading…
Reference in New Issue
Block a user