Run rustfmt 0.9.0-nightly (69ad879 2018-07-27)

This commit is contained in:
bjorn3
2018-07-31 12:25:16 +02:00
parent 82dbd07806
commit f001808249
7 changed files with 603 additions and 318 deletions

View File

@@ -62,16 +62,8 @@ fn cmp_raw_ptr(a: *const u8, b: *const u8) -> bool {
fn int_cast(a: u16, b: i16) -> (u8, u16, u32, usize, i8, i16, i32, isize, u8, u32) { fn int_cast(a: u16, b: i16) -> (u8, u16, u32, usize, i8, i16, i32, isize, u8, u32) {
( (
a as u8, a as u8, a as u16, a as u32, a as usize, a as i8, a as i16, a as i32, a as isize, b as u8,
a as u16, b as u32,
a as u32,
a as usize,
a as i8,
a as i16,
a as i32,
a as isize,
b as u8,
b as u32
) )
} }
@@ -86,9 +78,7 @@ fn debug_tuple() -> DebugTuple {
} }
fn size_of<T>() -> usize { fn size_of<T>() -> usize {
unsafe { unsafe { intrinsics::size_of::<T>() }
intrinsics::size_of::<T>()
}
} }
fn use_size_of() -> usize { fn use_size_of() -> usize {
@@ -111,31 +101,27 @@ fn use_const() -> u8 {
} }
fn call_closure_3arg() { fn call_closure_3arg() {
(|_, _, _| { (|_, _, _| {})(0u8, 42u16, 0u8)
})(0u8, 42u16, 0u8)
} }
fn call_closure_2arg() { fn call_closure_2arg() {
(|_, _| { (|_, _| {})(0u8, 42u16)
})(0u8, 42u16)
} }
struct IsNotEmpty; struct IsNotEmpty;
impl<'a, 'b> FnOnce<(&'a &'b [u16], )> for IsNotEmpty { impl<'a, 'b> FnOnce<(&'a &'b [u16],)> for IsNotEmpty {
type Output = bool; type Output = bool;
#[inline] #[inline]
extern "rust-call" fn call_once(mut self, arg: (&'a &'b [u16], )) -> bool { extern "rust-call" fn call_once(mut self, arg: (&'a &'b [u16],)) -> bool {
self.call_mut(arg) self.call_mut(arg)
} }
} }
impl<'a, 'b> FnMut<(&'a &'b [u16], )> for IsNotEmpty { impl<'a, 'b> FnMut<(&'a &'b [u16],)> for IsNotEmpty {
#[inline] #[inline]
extern "rust-call" fn call_mut(&mut self, arg: (&'a &'b [u16], )) -> bool { extern "rust-call" fn call_mut(&mut self, arg: (&'a &'b [u16],)) -> bool {
true true
} }
} }

View File

@@ -2,7 +2,7 @@
#![no_core] #![no_core]
#![allow(dead_code)] #![allow(dead_code)]
#[lang="sized"] #[lang = "sized"]
pub trait Sized {} pub trait Sized {}
#[lang = "unsize"] #[lang = "unsize"]
@@ -11,9 +11,9 @@ pub trait Unsize<T: ?Sized> {}
#[lang = "coerce_unsized"] #[lang = "coerce_unsized"]
pub trait CoerceUnsized<T> {} pub trait CoerceUnsized<T> {}
impl<'a, 'b: 'a, T: ?Sized+Unsize<U>, U: ?Sized> CoerceUnsized<&'a U> for &'b T {} impl<'a, 'b: 'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<&'a U> for &'b T {}
#[lang="copy"] #[lang = "copy"]
pub unsafe trait Copy {} pub unsafe trait Copy {}
unsafe impl Copy for bool {} unsafe impl Copy for bool {}
@@ -30,10 +30,10 @@ unsafe impl Copy for char {}
unsafe impl<'a, T: ?Sized> Copy for &'a T {} unsafe impl<'a, T: ?Sized> Copy for &'a T {}
unsafe impl<T: ?Sized> Copy for *const T {} unsafe impl<T: ?Sized> Copy for *const T {}
#[lang="freeze"] #[lang = "freeze"]
trait Freeze {} trait Freeze {}
#[lang="mul"] #[lang = "mul"]
pub trait Mul<RHS = Self> { pub trait Mul<RHS = Self> {
type Output; type Output;
@@ -49,7 +49,7 @@ impl Mul for u8 {
} }
} }
#[lang="bitor"] #[lang = "bitor"]
pub trait BitOr<RHS = Self> { pub trait BitOr<RHS = Self> {
type Output; type Output;
@@ -80,18 +80,30 @@ pub trait PartialEq<Rhs: ?Sized = Self> {
} }
impl PartialEq for u8 { impl PartialEq for u8 {
fn eq(&self, other: &u8) -> bool { (*self) == (*other) } fn eq(&self, other: &u8) -> bool {
fn ne(&self, other: &u8) -> bool { (*self) != (*other) } (*self) == (*other)
}
fn ne(&self, other: &u8) -> bool {
(*self) != (*other)
}
} }
impl PartialEq for char { impl PartialEq for char {
fn eq(&self, other: &char) -> bool { (*self) == (*other) } fn eq(&self, other: &char) -> bool {
fn ne(&self, other: &char) -> bool { (*self) != (*other) } (*self) == (*other)
}
fn ne(&self, other: &char) -> bool {
(*self) != (*other)
}
} }
impl<T: ?Sized> PartialEq for *const T { impl<T: ?Sized> PartialEq for *const T {
fn eq(&self, other: &*const T) -> bool { *self == *other } fn eq(&self, other: &*const T) -> bool {
fn ne(&self, other: &*const T) -> bool { *self != *other } *self == *other
}
fn ne(&self, other: &*const T) -> bool {
*self != *other
}
} }
#[lang = "fn_once"] #[lang = "fn_once"]
@@ -104,11 +116,11 @@ pub trait FnOnce<Args> {
#[lang = "fn_mut"] #[lang = "fn_mut"]
#[rustc_paren_sugar] #[rustc_paren_sugar]
pub trait FnMut<Args> : FnOnce<Args> { pub trait FnMut<Args>: FnOnce<Args> {
extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output; extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output;
} }
#[lang="panic"] #[lang = "panic"]
pub fn panic(_expr_file_line_col: &(&'static str, &'static str, u32, u32)) -> ! { pub fn panic(_expr_file_line_col: &(&'static str, &'static str, u32, u32)) -> ! {
loop {} loop {}
} }

View File

@@ -5,14 +5,22 @@ use rustc_target::spec::abi::Abi;
use crate::prelude::*; use crate::prelude::*;
pub fn cton_sig_from_fn_ty<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>, fn_ty: Ty<'tcx>) -> Signature { pub fn cton_sig_from_fn_ty<'a, 'tcx: 'a>(
tcx: TyCtxt<'a, 'tcx, 'tcx>,
fn_ty: Ty<'tcx>,
) -> Signature {
let sig = ty_fn_sig(tcx, fn_ty); let sig = ty_fn_sig(tcx, fn_ty);
assert!(!sig.variadic, "Variadic function are not yet supported"); assert!(!sig.variadic, "Variadic function are not yet supported");
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::Fast, sig.inputs().to_vec(), sig.output()), Abi::Rust => (CallConv::Fast, 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()),
Abi::RustCall => { Abi::RustCall => {
println!("rust-call sig: {:?} inputs: {:?} output: {:?}", sig, sig.inputs(), sig.output()); println!(
"rust-call sig: {:?} inputs: {:?} output: {:?}",
sig,
sig.inputs(),
sig.output()
);
assert_eq!(sig.inputs().len(), 2); assert_eq!(sig.inputs().len(), 2);
let extra_args = match sig.inputs().last().unwrap().sty { let extra_args = match sig.inputs().last().unwrap().sty {
ty::TyTuple(ref tupled_arguments) => tupled_arguments, ty::TyTuple(ref tupled_arguments) => tupled_arguments,
@@ -20,11 +28,7 @@ pub fn cton_sig_from_fn_ty<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>, fn_ty: Ty<
}; };
let mut inputs: Vec<Ty> = vec![sig.inputs()[0]]; let mut inputs: Vec<Ty> = vec![sig.inputs()[0]];
inputs.extend(extra_args.into_iter()); inputs.extend(extra_args.into_iter());
( (CallConv::Fast, inputs, sig.output())
CallConv::Fast,
inputs,
sig.output(),
)
} }
Abi::System => bug!("system abi should be selected elsewhere"), Abi::System => bug!("system abi should be selected elsewhere"),
Abi::RustIntrinsic => (CallConv::SystemV, sig.inputs().to_vec(), sig.output()), Abi::RustIntrinsic => (CallConv::SystemV, sig.inputs().to_vec(), sig.output()),
@@ -50,10 +54,7 @@ pub fn cton_sig_from_fn_ty<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>, fn_ty: Ty<
} }
} }
fn ty_fn_sig<'a, 'tcx>( fn ty_fn_sig<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ty: Ty<'tcx>) -> ty::FnSig<'tcx> {
tcx: TyCtxt<'a, 'tcx, 'tcx>,
ty: Ty<'tcx>
) -> ty::FnSig<'tcx> {
let sig = match ty.sty { let sig = match ty.sty {
ty::TyFnDef(..) | ty::TyFnDef(..) |
// Shims currently have type TyFnPtr. Not sure this should remain. // Shims currently have type TyFnPtr. Not sure this should remain.
@@ -104,11 +105,16 @@ impl<'a, 'tcx: 'a> FunctionCx<'a, 'tcx> {
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(self.tcx); let fn_ty = inst.ty(self.tcx);
let sig = cton_sig_from_fn_ty(self.tcx, fn_ty); let sig = cton_sig_from_fn_ty(self.tcx, fn_ty);
let def_path_based_names = ::rustc_mir::monomorphize::item::DefPathBasedNames::new(self.tcx, false, false); let def_path_based_names =
::rustc_mir::monomorphize::item::DefPathBasedNames::new(self.tcx, false, false);
let mut name = String::new(); let mut name = String::new();
def_path_based_names.push_instance_as_string(inst, &mut name); def_path_based_names.push_instance_as_string(inst, &mut name);
let func_id = self.module.declare_function(&name, Linkage::Import, &sig).unwrap(); let func_id = self
self.module.declare_func_in_func(func_id, &mut self.bcx.func) .module
.declare_function(&name, Linkage::Import, &sig)
.unwrap();
self.module
.declare_func_in_func(func_id, &mut self.bcx.func)
} }
fn lib_call( fn lib_call(
@@ -124,8 +130,13 @@ impl<'a, 'tcx: 'a> FunctionCx<'a, 'tcx> {
call_conv: CallConv::SystemV, call_conv: CallConv::SystemV,
argument_bytes: None, argument_bytes: None,
}; };
let func_id = self.module.declare_function(&name, Linkage::Import, &sig).unwrap(); let func_id = self
let func_ref = self.module.declare_func_in_func(func_id, &mut self.bcx.func); .module
.declare_function(&name, Linkage::Import, &sig)
.unwrap();
let func_ref = self
.module
.declare_func_in_func(func_id, &mut self.bcx.func);
let call_inst = self.bcx.ins().call(func_ref, args); let call_inst = self.bcx.ins().call(func_ref, args);
if output_ty.is_none() { if output_ty.is_none() {
return None; return None;
@@ -135,8 +146,20 @@ impl<'a, 'tcx: 'a> FunctionCx<'a, 'tcx> {
Some(results[0]) Some(results[0])
} }
pub fn easy_call(&mut self, name: &str, args: &[CValue<'tcx>], return_ty: Ty<'tcx>) -> CValue<'tcx> { pub fn easy_call(
let (input_tys, args): (Vec<_>, Vec<_>) = args.into_iter().map(|arg| (self.cton_type(arg.layout().ty).unwrap(), arg.load_value(self))).unzip(); &mut self,
name: &str,
args: &[CValue<'tcx>],
return_ty: Ty<'tcx>,
) -> CValue<'tcx> {
let (input_tys, args): (Vec<_>, Vec<_>) = args
.into_iter()
.map(|arg| {
(
self.cton_type(arg.layout().ty).unwrap(),
arg.load_value(self),
)
}).unzip();
let return_layout = self.layout_of(return_ty); let return_layout = self.layout_of(return_ty);
let return_ty = if let TypeVariants::TyTuple(tup) = return_ty.sty { let return_ty = if let TypeVariants::TyTuple(tup) = return_ty.sty {
if !tup.is_empty() { if !tup.is_empty() {
@@ -209,7 +232,8 @@ pub fn codegen_fn_prelude<'a, 'tcx: 'a>(fx: &mut FunctionCx<'a, 'tcx>, start_ebb
}).collect::<Vec<(Local, ArgKind, Ty)>>(); }).collect::<Vec<(Local, ArgKind, Ty)>>();
let ret_layout = fx.layout_of(fx.return_type()); let ret_layout = fx.layout_of(fx.return_type());
fx.local_map.insert(RETURN_PLACE, CPlace::Addr(ret_param, ret_layout)); fx.local_map
.insert(RETURN_PLACE, CPlace::Addr(ret_param, ret_layout));
for (local, arg_kind, ty) in func_params { for (local, arg_kind, ty) in func_params {
let layout = fx.layout_of(ty); let layout = fx.layout_of(ty);
@@ -284,17 +308,18 @@ pub fn codegen_call<'a, 'tcx: 'a>(
for (i, _) in tupled_arguments.iter().enumerate() { for (i, _) in tupled_arguments.iter().enumerate() {
args.push(pack_arg.value_field(fx, mir::Field::new(i))); args.push(pack_arg.value_field(fx, mir::Field::new(i)));
} }
}, }
_ => bug!("argument to function with \"rust-call\" ABI is not a tuple"), _ => 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<_>>()); println!(
"{:?} {:?}",
pack_arg.layout().ty,
args.iter().map(|a| a.layout().ty).collect::<Vec<_>>()
);
args args
} else { } else {
args args.into_iter()
.into_iter() .map(|arg| trans_operand(fx, arg))
.map(|arg| {
trans_operand(fx, arg)
})
.collect::<Vec<_>>() .collect::<Vec<_>>()
}; };
@@ -326,7 +351,11 @@ pub fn codegen_call<'a, 'tcx: 'a>(
let dst = args[1]; let dst = args[1];
let count = args[2].load_value(fx); let count = args[2].load_value(fx);
let byte_amount = fx.bcx.ins().imul(count, elem_size); let byte_amount = fx.bcx.ins().imul(count, elem_size);
fx.easy_call("memmove", &[dst, src, CValue::ByVal(byte_amount, usize_layout)], nil_ty); fx.easy_call(
"memmove",
&[dst, src, CValue::ByVal(byte_amount, usize_layout)],
nil_ty,
);
unimplemented!("copy"); unimplemented!("copy");
} }
"discriminant_value" => { "discriminant_value" => {
@@ -362,12 +391,24 @@ pub fn codegen_call<'a, 'tcx: 'a>(
_ => unimplemented!("intrinsic {}", intrinsic), _ => unimplemented!("intrinsic {}", intrinsic),
}; };
let res = match ret.layout().ty.sty { let res = match ret.layout().ty.sty {
TypeVariants::TyUint(_) => { TypeVariants::TyUint(_) => crate::base::trans_int_binop(
crate::base::trans_int_binop(fx, bin_op, args[0], args[1], ret.layout().ty, false, false) fx,
} bin_op,
TypeVariants::TyInt(_) => { args[0],
crate::base::trans_int_binop(fx, bin_op, args[0], args[1], ret.layout().ty, true, false) args[1],
} ret.layout().ty,
false,
false,
),
TypeVariants::TyInt(_) => crate::base::trans_int_binop(
fx,
bin_op,
args[0],
args[1],
ret.layout().ty,
true,
false,
),
_ => panic!(), _ => panic!(),
}; };
ret.write_cvalue(fx, res); ret.write_cvalue(fx, res);
@@ -402,7 +443,10 @@ pub fn codegen_call<'a, 'tcx: 'a>(
let uninit_val = uninit_place.to_cvalue(fx); let uninit_val = uninit_place.to_cvalue(fx);
ret.write_cvalue(fx, uninit_val); ret.write_cvalue(fx, uninit_val);
} }
_ => fx.tcx.sess.fatal(&format!("unsupported intrinsic {}", intrinsic)), _ => fx
.tcx
.sess
.fatal(&format!("unsupported intrinsic {}", intrinsic)),
} }
if let Some((_, dest)) = *destination { if let Some((_, dest)) = *destination {
let ret_ebb = fx.get_ebb(dest); let ret_ebb = fx.get_ebb(dest);
@@ -419,7 +463,9 @@ pub fn codegen_call<'a, 'tcx: 'a>(
None => fx.bcx.ins().iconst(types::I64, 0), None => fx.bcx.ins().iconst(types::I64, 0),
}; };
let call_args = Some(return_ptr).into_iter().chain(args.into_iter().map(|arg| { let call_args = Some(return_ptr)
.into_iter()
.chain(args.into_iter().map(|arg| {
if fx.cton_type(arg.layout().ty).is_some() { if fx.cton_type(arg.layout().ty).is_some() {
arg.load_value(fx) arg.load_value(fx)
} else { } else {
@@ -434,7 +480,9 @@ pub fn codegen_call<'a, 'tcx: 'a>(
func => { func => {
let func_ty = func.layout().ty; let func_ty = func.layout().ty;
let func = func.load_value(fx); let func = func.load_value(fx);
let sig = fx.bcx.import_signature(cton_sig_from_fn_ty(fx.tcx, func_ty)); let sig = fx
.bcx
.import_signature(cton_sig_from_fn_ty(fx.tcx, func_ty));
fx.bcx.ins().call_indirect(sig, func, &call_args); fx.bcx.ins().call_indirect(sig, func, &call_args);
} }
} }

View File

@@ -1,6 +1,10 @@
use crate::prelude::*; use crate::prelude::*;
pub fn trans_mono_item<'a, 'tcx: 'a>(cx: &mut CodegenCx<'a, 'tcx, CurrentBackend>, context: &mut Context, mono_item: MonoItem<'tcx>) { pub fn trans_mono_item<'a, 'tcx: 'a>(
cx: &mut CodegenCx<'a, 'tcx, CurrentBackend>,
context: &mut Context,
mono_item: MonoItem<'tcx>,
) {
let tcx = cx.tcx; let tcx = cx.tcx;
match mono_item { match mono_item {
@@ -11,7 +15,11 @@ pub fn trans_mono_item<'a, 'tcx: 'a>(cx: &mut CodegenCx<'a, 'tcx, CurrentBackend
} => { } => {
let mut mir = ::std::io::Cursor::new(Vec::new()); let mut mir = ::std::io::Cursor::new(Vec::new());
::rustc_mir::util::write_mir_pretty(tcx, Some(def_id), &mut mir).unwrap(); ::rustc_mir::util::write_mir_pretty(tcx, Some(def_id), &mut mir).unwrap();
tcx.sess.warn(&format!("{:?}:\n\n{}", inst, String::from_utf8_lossy(&mir.into_inner()))); tcx.sess.warn(&format!(
"{:?}:\n\n{}",
inst,
String::from_utf8_lossy(&mir.into_inner())
));
let fn_ty = inst.ty(tcx); let fn_ty = inst.ty(tcx);
let fn_ty = tcx.subst_and_normalize_erasing_regions( let fn_ty = tcx.subst_and_normalize_erasing_regions(
@@ -23,15 +31,23 @@ pub fn trans_mono_item<'a, 'tcx: 'a>(cx: &mut CodegenCx<'a, 'tcx, CurrentBackend
let func_id = { let func_id = {
// WARNING: keep in sync with FunctionCx::get_function_ref // WARNING: keep in sync with FunctionCx::get_function_ref
let def_path_based_names = ::rustc_mir::monomorphize::item::DefPathBasedNames::new(cx.tcx, false, false); let def_path_based_names =
::rustc_mir::monomorphize::item::DefPathBasedNames::new(
cx.tcx, false, false,
);
let mut name = String::new(); let mut name = String::new();
def_path_based_names.push_instance_as_string(inst, &mut name); def_path_based_names.push_instance_as_string(inst, &mut name);
cx.module.declare_function(&name, Linkage::Export, &sig).unwrap() cx.module
.declare_function(&name, Linkage::Export, &sig)
.unwrap()
}; };
let mut f = Function::with_name_signature(ExternalName::user(0, func_id.index() as u32), sig); let mut f = Function::with_name_signature(
ExternalName::user(0, func_id.index() as u32),
sig,
);
let comments = match trans_fn(cx, &mut f, inst){ let comments = match trans_fn(cx, &mut f, inst) {
Ok(comments) => comments, Ok(comments) => comments,
Err(err) => { Err(err) => {
tcx.sess.err(&err); tcx.sess.err(&err);
@@ -41,7 +57,8 @@ pub fn trans_mono_item<'a, 'tcx: 'a>(cx: &mut CodegenCx<'a, 'tcx, CurrentBackend
let mut writer = crate::pretty_clif::CommentWriter(comments); let mut writer = crate::pretty_clif::CommentWriter(comments);
let mut cton = String::new(); let mut cton = String::new();
::cranelift::codegen::write::decorate_function(&mut writer, &mut cton, &f, None).unwrap(); ::cranelift::codegen::write::decorate_function(&mut writer, &mut cton, &f, None)
.unwrap();
tcx.sess.warn(&cton); tcx.sess.warn(&cton);
let flags = settings::Flags::new(settings::builder()); let flags = settings::Flags::new(settings::builder());
@@ -49,8 +66,15 @@ pub fn trans_mono_item<'a, 'tcx: 'a>(cx: &mut CodegenCx<'a, 'tcx, CurrentBackend
Ok(_) => {} Ok(_) => {}
Err(err) => { Err(err) => {
tcx.sess.err(&format!("{:?}", err)); tcx.sess.err(&format!("{:?}", err));
let pretty_error = ::cranelift::codegen::print_errors::pretty_verifier_error(&f, None, Some(Box::new(writer)), &err); let pretty_error =
tcx.sess.fatal(&format!("cretonne verify error:\n{}", pretty_error)); ::cranelift::codegen::print_errors::pretty_verifier_error(
&f,
None,
Some(Box::new(writer)),
&err,
);
tcx.sess
.fatal(&format!("cretonne verify error:\n{}", pretty_error));
} }
} }
@@ -60,14 +84,27 @@ pub fn trans_mono_item<'a, 'tcx: 'a>(cx: &mut CodegenCx<'a, 'tcx, CurrentBackend
context.clear(); context.clear();
} }
inst => cx.tcx.sess.warn(&format!("Unimplemented instance {:?}", inst)), inst => cx
} .tcx
MonoItem::Static(def_id) => cx.tcx.sess.err(&format!("Unimplemented static mono item {:?}", def_id)), .sess
MonoItem::GlobalAsm(node_id) => cx.tcx.sess.err(&format!("Unimplemented global asm mono item {:?}", node_id)), .warn(&format!("Unimplemented instance {:?}", inst)),
},
MonoItem::Static(def_id) => cx
.tcx
.sess
.err(&format!("Unimplemented static mono item {:?}", def_id)),
MonoItem::GlobalAsm(node_id) => cx
.tcx
.sess
.err(&format!("Unimplemented global asm mono item {:?}", node_id)),
} }
} }
pub fn trans_fn<'a, 'tcx: 'a>(cx: &mut CodegenCx<'a, 'tcx, CurrentBackend>, f: &mut Function, instance: Instance<'tcx>) -> Result<HashMap<Inst, String>, String> { pub fn trans_fn<'a, 'tcx: 'a>(
cx: &mut CodegenCx<'a, 'tcx, CurrentBackend>,
f: &mut Function,
instance: Instance<'tcx>,
) -> Result<HashMap<Inst, String>, String> {
let mir = cx.tcx.optimized_mir(instance.def_id()); let mir = cx.tcx.optimized_mir(instance.def_id());
let mut func_ctx = FunctionBuilderContext::new(); let mut func_ctx = FunctionBuilderContext::new();
let mut bcx: FunctionBuilder<Variable> = FunctionBuilder::new(f, &mut func_ctx); let mut bcx: FunctionBuilder<Variable> = FunctionBuilder::new(f, &mut func_ctx);
@@ -98,7 +135,9 @@ pub fn trans_fn<'a, 'tcx: 'a>(cx: &mut CodegenCx<'a, 'tcx, CurrentBackend>, f: &
crate::abi::codegen_fn_prelude(fx, start_ebb); crate::abi::codegen_fn_prelude(fx, start_ebb);
fx.bcx.ins().jump(*fx.ebb_map.get(&START_BLOCK).unwrap(), &[]); fx.bcx
.ins()
.jump(*fx.ebb_map.get(&START_BLOCK).unwrap(), &[]);
for (bb, bb_data) in mir.basic_blocks().iter_enumerated() { for (bb, bb_data) in mir.basic_blocks().iter_enumerated() {
let ebb = fx.get_ebb(bb); let ebb = fx.get_ebb(bb);
@@ -110,7 +149,11 @@ pub fn trans_fn<'a, 'tcx: 'a>(cx: &mut CodegenCx<'a, 'tcx, CurrentBackend>, f: &
} }
let mut terminator_head = "\n".to_string(); let mut terminator_head = "\n".to_string();
bb_data.terminator().kind.fmt_head(&mut terminator_head).unwrap(); bb_data
.terminator()
.kind
.fmt_head(&mut terminator_head)
.unwrap();
let inst = fx.bcx.func.layout.last_inst(ebb).unwrap(); let inst = fx.bcx.func.layout.last_inst(ebb).unwrap();
fx.add_comment(inst, terminator_head); fx.add_comment(inst, terminator_head);
@@ -122,7 +165,13 @@ pub fn trans_fn<'a, 'tcx: 'a>(cx: &mut CodegenCx<'a, 'tcx, CurrentBackend>, f: &
TerminatorKind::Return => { TerminatorKind::Return => {
fx.bcx.ins().return_(&[]); fx.bcx.ins().return_(&[]);
} }
TerminatorKind::Assert { cond, expected, msg: _, target, cleanup: _ } => { TerminatorKind::Assert {
cond,
expected,
msg: _,
target,
cleanup: _,
} => {
let cond = trans_operand(fx, cond).load_value(fx); let cond = trans_operand(fx, cond).load_value(fx);
let target = fx.get_ebb(*target); let target = fx.get_ebb(*target);
if *expected { if *expected {
@@ -133,7 +182,12 @@ pub fn trans_fn<'a, 'tcx: 'a>(cx: &mut CodegenCx<'a, 'tcx, CurrentBackend>, f: &
fx.bcx.ins().trap(TrapCode::User(!0)); fx.bcx.ins().trap(TrapCode::User(!0));
} }
TerminatorKind::SwitchInt { discr, switch_ty: _, values, targets } => { TerminatorKind::SwitchInt {
discr,
switch_ty: _,
values,
targets,
} => {
let discr = trans_operand(fx, discr).load_value(fx); let discr = trans_operand(fx, discr).load_value(fx);
let mut jt_data = JumpTableData::new(); let mut jt_data = JumpTableData::new();
for (i, value) in values.iter().enumerate() { for (i, value) in values.iter().enumerate() {
@@ -145,15 +199,20 @@ pub fn trans_fn<'a, 'tcx: 'a>(cx: &mut CodegenCx<'a, 'tcx, CurrentBackend>, f: &
let otherwise_ebb = fx.get_ebb(targets[targets.len() - 1]); let otherwise_ebb = fx.get_ebb(targets[targets.len() - 1]);
fx.bcx.ins().jump(otherwise_ebb, &[]); fx.bcx.ins().jump(otherwise_ebb, &[]);
} }
TerminatorKind::Call { func, args, destination, cleanup: _ } => { TerminatorKind::Call {
func,
args,
destination,
cleanup: _,
} => {
crate::abi::codegen_call(fx, func, args, destination); crate::abi::codegen_call(fx, func, args, destination);
} }
TerminatorKind::Resume | TerminatorKind::Abort | TerminatorKind::Unreachable => { TerminatorKind::Resume | TerminatorKind::Abort | TerminatorKind::Unreachable => {
fx.bcx.ins().trap(TrapCode::User(!0)); fx.bcx.ins().trap(TrapCode::User(!0));
} }
TerminatorKind::Yield { .. } | TerminatorKind::Yield { .. }
TerminatorKind::FalseEdges { .. } | | TerminatorKind::FalseEdges { .. }
TerminatorKind::FalseUnwind { .. } => { | TerminatorKind::FalseUnwind { .. } => {
bug!("shouldn't exist at trans {:?}", bb_data.terminator()); bug!("shouldn't exist at trans {:?}", bb_data.terminator());
} }
TerminatorKind::Drop { target, .. } | TerminatorKind::DropAndReplace { target, .. } => { TerminatorKind::Drop { target, .. } | TerminatorKind::DropAndReplace { target, .. } => {
@@ -174,14 +233,21 @@ pub fn trans_fn<'a, 'tcx: 'a>(cx: &mut CodegenCx<'a, 'tcx, CurrentBackend>, f: &
Ok(fx.comments.clone()) Ok(fx.comments.clone())
} }
fn trans_stmt<'a, 'tcx: 'a>(fx: &mut FunctionCx<'a, 'tcx>, cur_ebb: Ebb, stmt: &Statement<'tcx>) -> Result<(), String> { fn trans_stmt<'a, 'tcx: 'a>(
fx: &mut FunctionCx<'a, 'tcx>,
cur_ebb: Ebb,
stmt: &Statement<'tcx>,
) -> Result<(), String> {
fx.tcx.sess.warn(&format!("stmt {:?}", stmt)); fx.tcx.sess.warn(&format!("stmt {:?}", stmt));
let inst = fx.bcx.func.layout.last_inst(cur_ebb).unwrap(); let inst = fx.bcx.func.layout.last_inst(cur_ebb).unwrap();
fx.add_comment(inst, format!("{:?}", stmt)); fx.add_comment(inst, format!("{:?}", stmt));
match &stmt.kind { match &stmt.kind {
StatementKind::SetDiscriminant { place, variant_index } => { StatementKind::SetDiscriminant {
place,
variant_index,
} => {
let place = trans_place(fx, place); let place = trans_place(fx, place);
let layout = place.layout(); let layout = place.layout();
if layout.for_variant(&*fx, *variant_index).abi == layout::Abi::Uninhabited { if layout.for_variant(&*fx, *variant_index).abi == layout::Abi::Uninhabited {
@@ -193,7 +259,10 @@ fn trans_stmt<'a, 'tcx: 'a>(fx: &mut FunctionCx<'a, 'tcx>, cur_ebb: Ebb, stmt: &
} }
layout::Variants::Tagged { .. } => { layout::Variants::Tagged { .. } => {
let ptr = place.place_field(fx, mir::Field::new(0)); let ptr = place.place_field(fx, mir::Field::new(0));
let to = layout.ty.ty_adt_def().unwrap() let to = layout
.ty
.ty_adt_def()
.unwrap()
.discriminant_for_variant(fx.tcx, *variant_index) .discriminant_for_variant(fx.tcx, *variant_index)
.val; .val;
let discr = CValue::const_val(fx, ptr.layout().ty, to as u64 as i64); let discr = CValue::const_val(fx, ptr.layout().ty, to as u64 as i64);
@@ -288,7 +357,7 @@ fn trans_stmt<'a, 'tcx: 'a>(fx: &mut FunctionCx<'a, 'tcx>, cur_ebb: Ebb, stmt: &
UnOp::Neg => match ty.sty { UnOp::Neg => match ty.sty {
TypeVariants::TyFloat(_) => fx.bcx.ins().fneg(val), TypeVariants::TyFloat(_) => fx.bcx.ins().fneg(val),
_ => unimplemented!("un op Neg for {:?}", ty), _ => unimplemented!("un op Neg for {:?}", ty),
} },
}; };
lval.write_cvalue(fx, CValue::ByVal(res, layout)); lval.write_cvalue(fx, CValue::ByVal(res, layout));
} }
@@ -306,50 +375,66 @@ fn trans_stmt<'a, 'tcx: 'a>(fx: &mut FunctionCx<'a, 'tcx>, cur_ebb: Ebb, stmt: &
let operand = trans_operand(fx, operand); let operand = trans_operand(fx, operand);
let from_ty = operand.layout().ty; let from_ty = operand.layout().ty;
match (&from_ty.sty, &to_ty.sty) { match (&from_ty.sty, &to_ty.sty) {
(TypeVariants::TyRef(..), TypeVariants::TyRef(..)) | (TypeVariants::TyRef(..), TypeVariants::TyRef(..))
(TypeVariants::TyRef(..), TypeVariants::TyRawPtr(..)) | | (TypeVariants::TyRef(..), TypeVariants::TyRawPtr(..))
(TypeVariants::TyRawPtr(..), TypeVariants::TyRef(..)) | | (TypeVariants::TyRawPtr(..), TypeVariants::TyRef(..))
(TypeVariants::TyRawPtr(..), TypeVariants::TyRawPtr(..)) => { | (TypeVariants::TyRawPtr(..), TypeVariants::TyRawPtr(..)) => {
lval.write_cvalue(fx, operand.unchecked_cast_to(dest_layout)); lval.write_cvalue(fx, operand.unchecked_cast_to(dest_layout));
} }
(TypeVariants::TyChar, TypeVariants::TyUint(_)) | (TypeVariants::TyChar, TypeVariants::TyUint(_))
(TypeVariants::TyUint(_), TypeVariants::TyInt(_)) | | (TypeVariants::TyUint(_), TypeVariants::TyInt(_))
(TypeVariants::TyUint(_), TypeVariants::TyUint(_)) => { | (TypeVariants::TyUint(_), TypeVariants::TyUint(_)) => {
let from = operand.load_value(fx); let from = operand.load_value(fx);
let res = crate::common::cton_intcast(fx, from, from_ty, to_ty, false); let res = crate::common::cton_intcast(fx, from, from_ty, to_ty, false);
lval.write_cvalue(fx, CValue::ByVal(res, dest_layout)); lval.write_cvalue(fx, CValue::ByVal(res, dest_layout));
} }
(TypeVariants::TyInt(_), TypeVariants::TyInt(_)) | (TypeVariants::TyInt(_), TypeVariants::TyInt(_))
(TypeVariants::TyInt(_), TypeVariants::TyUint(_)) => { | (TypeVariants::TyInt(_), TypeVariants::TyUint(_)) => {
let from = operand.load_value(fx); let from = operand.load_value(fx);
let res = crate::common::cton_intcast(fx, from, from_ty, to_ty, true); let res = crate::common::cton_intcast(fx, from, from_ty, to_ty, true);
lval.write_cvalue(fx, CValue::ByVal(res, dest_layout)); lval.write_cvalue(fx, CValue::ByVal(res, dest_layout));
} }
_ => return Err(format!("rval misc {:?} {:?}", operand, to_ty)), _ => return Err(format!("rval misc {:?} {:?}", operand, to_ty)),
} }
}, }
Rvalue::Cast(CastKind::ClosureFnPointer, operand, ty) => unimplemented!("rval closure_fn_ptr {:?} {:?}", operand, ty), Rvalue::Cast(CastKind::ClosureFnPointer, operand, ty) => {
Rvalue::Cast(CastKind::Unsize, operand, ty) => return Err(format!("rval unsize {:?} {:?}", operand, ty)), unimplemented!("rval closure_fn_ptr {:?} {:?}", operand, ty)
}
Rvalue::Cast(CastKind::Unsize, operand, ty) => {
return Err(format!("rval unsize {:?} {:?}", operand, ty))
}
Rvalue::Discriminant(place) => { Rvalue::Discriminant(place) => {
let place = trans_place(fx, place).to_cvalue(fx); let place = trans_place(fx, place).to_cvalue(fx);
let discr = trans_get_discriminant(fx, place, dest_layout); let discr = trans_get_discriminant(fx, place, dest_layout);
lval.write_cvalue(fx, discr); lval.write_cvalue(fx, discr);
} }
Rvalue::Repeat(operand, times) => unimplemented!("rval repeat {:?} {:?}", operand, times), Rvalue::Repeat(operand, times) => {
unimplemented!("rval repeat {:?} {:?}", operand, times)
}
Rvalue::Len(lval) => return Err(format!("rval len {:?}", lval)), Rvalue::Len(lval) => return Err(format!("rval len {:?}", lval)),
Rvalue::NullaryOp(NullOp::Box, ty) => unimplemented!("rval box {:?}", ty), Rvalue::NullaryOp(NullOp::Box, ty) => unimplemented!("rval box {:?}", ty),
Rvalue::NullaryOp(NullOp::SizeOf, ty) => unimplemented!("rval size_of {:?}", ty), Rvalue::NullaryOp(NullOp::SizeOf, ty) => unimplemented!("rval size_of {:?}", ty),
Rvalue::Aggregate(_, _) => bug!("shouldn't exist at trans {:?}", rval), Rvalue::Aggregate(_, _) => bug!("shouldn't exist at trans {:?}", rval),
} }
} }
StatementKind::StorageLive(_) | StatementKind::StorageDead(_) | StatementKind::Nop | StatementKind::ReadForMatch(_) | StatementKind::Validate(_, _) | StatementKind::EndRegion(_) | StatementKind::UserAssertTy(_, _) => {} StatementKind::StorageLive(_)
| StatementKind::StorageDead(_)
| StatementKind::Nop
| StatementKind::ReadForMatch(_)
| StatementKind::Validate(_, _)
| StatementKind::EndRegion(_)
| StatementKind::UserAssertTy(_, _) => {}
StatementKind::InlineAsm { .. } => fx.tcx.sess.fatal("Inline assembly is not supported"), StatementKind::InlineAsm { .. } => fx.tcx.sess.fatal("Inline assembly is not supported"),
} }
Ok(()) Ok(())
} }
pub fn trans_get_discriminant<'a, 'tcx: 'a>(fx: &mut FunctionCx<'a, 'tcx>, value: CValue<'tcx>, dest_layout: TyLayout<'tcx>) -> CValue<'tcx> { pub fn trans_get_discriminant<'a, 'tcx: 'a>(
fx: &mut FunctionCx<'a, 'tcx>,
value: CValue<'tcx>,
dest_layout: TyLayout<'tcx>,
) -> CValue<'tcx> {
let layout = value.layout(); let layout = value.layout();
if layout.abi == layout::Abi::Uninhabited { if layout.abi == layout::Abi::Uninhabited {
@@ -357,13 +442,12 @@ pub fn trans_get_discriminant<'a, 'tcx: 'a>(fx: &mut FunctionCx<'a, 'tcx>, value
} }
match layout.variants { match layout.variants {
layout::Variants::Single { index } => { layout::Variants::Single { index } => {
let discr_val = layout.ty.ty_adt_def().map_or( let discr_val = layout.ty.ty_adt_def().map_or(index as u128, |def| {
index as u128, def.discriminant_for_variant(fx.tcx, index).val
|def| def.discriminant_for_variant(fx.tcx, index).val); });
return CValue::const_val(fx, dest_layout.ty, discr_val as u64 as i64); return CValue::const_val(fx, dest_layout.ty, discr_val as u64 as i64);
} }
layout::Variants::Tagged { .. } | layout::Variants::Tagged { .. } | layout::Variants::NicheFilling { .. } => {}
layout::Variants::NicheFilling { .. } => {},
} }
let discr = value.value_field(fx, mir::Field::new(0)); let discr = value.value_field(fx, mir::Field::new(0));
@@ -374,7 +458,7 @@ pub fn trans_get_discriminant<'a, 'tcx: 'a>(fx: &mut FunctionCx<'a, 'tcx>, value
layout::Variants::Tagged { ref tag, .. } => { layout::Variants::Tagged { ref tag, .. } => {
let signed = match tag.value { let signed = match tag.value {
layout::Int(_, signed) => signed, layout::Int(_, signed) => signed,
_ => false _ => false,
}; };
let val = cton_intcast(fx, lldiscr, discr_ty, dest_layout.ty, signed); let val = cton_intcast(fx, lldiscr, discr_ty, dest_layout.ty, signed);
return CValue::ByVal(val, dest_layout); return CValue::ByVal(val, dest_layout);
@@ -388,9 +472,18 @@ pub fn trans_get_discriminant<'a, 'tcx: 'a>(fx: &mut FunctionCx<'a, 'tcx>, value
let niche_llty = fx.cton_type(discr_ty).unwrap(); let niche_llty = fx.cton_type(discr_ty).unwrap();
if niche_variants.start() == niche_variants.end() { if niche_variants.start() == niche_variants.end() {
let dest_cton_ty = fx.cton_type(dest_layout.ty).unwrap(); let dest_cton_ty = fx.cton_type(dest_layout.ty).unwrap();
let b = fx.bcx.ins().icmp_imm(IntCC::Equal, lldiscr, niche_start as u64 as i64); let b = fx
let if_true = fx.bcx.ins().iconst(dest_cton_ty, *niche_variants.start() as u64 as i64); .bcx
let if_false = fx.bcx.ins().iconst(dest_cton_ty, dataful_variant as u64 as i64); .ins()
.icmp_imm(IntCC::Equal, lldiscr, niche_start as u64 as i64);
let if_true = fx
.bcx
.ins()
.iconst(dest_cton_ty, *niche_variants.start() as u64 as i64);
let if_false = fx
.bcx
.ins()
.iconst(dest_cton_ty, dataful_variant as u64 as i64);
let val = fx.bcx.ins().select(b, if_true, if_false); let val = fx.bcx.ins().select(b, if_true, if_false);
return CValue::ByVal(val, dest_layout); return CValue::ByVal(val, dest_layout);
} else { } else {
@@ -398,9 +491,16 @@ pub fn trans_get_discriminant<'a, 'tcx: 'a>(fx: &mut FunctionCx<'a, 'tcx>, value
let delta = niche_start.wrapping_sub(*niche_variants.start() as u128); let delta = niche_start.wrapping_sub(*niche_variants.start() as u128);
let delta = fx.bcx.ins().iconst(niche_llty, delta as u64 as i64); let delta = fx.bcx.ins().iconst(niche_llty, delta as u64 as i64);
let lldiscr = fx.bcx.ins().isub(lldiscr, delta); let lldiscr = fx.bcx.ins().isub(lldiscr, delta);
let b = fx.bcx.ins().icmp_imm(IntCC::UnsignedLessThanOrEqual, lldiscr, *niche_variants.end() as u64 as i64); let b = fx.bcx.ins().icmp_imm(
IntCC::UnsignedLessThanOrEqual,
lldiscr,
*niche_variants.end() as u64 as i64,
);
let if_true = cton_intcast(fx, lldiscr, discr_ty, dest_layout.ty, false); let if_true = cton_intcast(fx, lldiscr, discr_ty, dest_layout.ty, false);
let if_false = fx.bcx.ins().iconst(niche_llty, dataful_variant as u64 as i64); let if_false = fx
.bcx
.ins()
.iconst(niche_llty, dataful_variant as u64 as i64);
let val = fx.bcx.ins().select(b, if_true, if_false); let val = fx.bcx.ins().select(b, if_true, if_false);
return CValue::ByVal(val, dest_layout); return CValue::ByVal(val, dest_layout);
} }
@@ -447,7 +547,13 @@ macro_rules! binop_match {
}} }}
} }
fn trans_bool_binop<'a, 'tcx: 'a>(fx: &mut FunctionCx<'a, 'tcx>, bin_op: BinOp, lhs: CValue<'tcx>, rhs: CValue<'tcx>, ty: Ty<'tcx>) -> CValue<'tcx> { fn trans_bool_binop<'a, 'tcx: 'a>(
fx: &mut FunctionCx<'a, 'tcx>,
bin_op: BinOp,
lhs: CValue<'tcx>,
rhs: CValue<'tcx>,
ty: Ty<'tcx>,
) -> CValue<'tcx> {
let res = binop_match! { let res = binop_match! {
fx, bin_op, false, lhs, rhs, ty, "bool"; fx, bin_op, false, lhs, rhs, ty, "bool";
Add (_) bug; Add (_) bug;
@@ -474,7 +580,15 @@ fn trans_bool_binop<'a, 'tcx: 'a>(fx: &mut FunctionCx<'a, 'tcx>, bin_op: BinOp,
res res
} }
pub fn trans_int_binop<'a, 'tcx: 'a>(fx: &mut FunctionCx<'a, 'tcx>, bin_op: BinOp, lhs: CValue<'tcx>, rhs: CValue<'tcx>, ty: Ty<'tcx>, signed: bool, _checked: bool) -> CValue<'tcx> { pub fn trans_int_binop<'a, 'tcx: 'a>(
fx: &mut FunctionCx<'a, 'tcx>,
bin_op: BinOp,
lhs: CValue<'tcx>,
rhs: CValue<'tcx>,
ty: Ty<'tcx>,
signed: bool,
_checked: bool,
) -> CValue<'tcx> {
let res = binop_match! { let res = binop_match! {
fx, bin_op, signed, lhs, rhs, ty, "int/uint"; fx, bin_op, signed, lhs, rhs, ty, "int/uint";
Add (_) iadd; Add (_) iadd;
@@ -509,7 +623,13 @@ pub fn trans_int_binop<'a, 'tcx: 'a>(fx: &mut FunctionCx<'a, 'tcx>, bin_op: BinO
res res
} }
fn trans_float_binop<'a, 'tcx: 'a>(fx: &mut FunctionCx<'a, 'tcx>, bin_op: BinOp, lhs: CValue<'tcx>, rhs: CValue<'tcx>, ty: Ty<'tcx>) -> CValue<'tcx> { fn trans_float_binop<'a, 'tcx: 'a>(
fx: &mut FunctionCx<'a, 'tcx>,
bin_op: BinOp,
lhs: CValue<'tcx>,
rhs: CValue<'tcx>,
ty: Ty<'tcx>,
) -> CValue<'tcx> {
let res = binop_match! { let res = binop_match! {
fx, bin_op, false, lhs, rhs, ty, "float"; fx, bin_op, false, lhs, rhs, ty, "float";
Add (_) fadd; Add (_) fadd;
@@ -544,7 +664,13 @@ fn trans_float_binop<'a, 'tcx: 'a>(fx: &mut FunctionCx<'a, 'tcx>, bin_op: BinOp,
res res
} }
fn trans_char_binop<'a, 'tcx: 'a>(fx: &mut FunctionCx<'a, 'tcx>, bin_op: BinOp, lhs: CValue<'tcx>, rhs: CValue<'tcx>, ty: Ty<'tcx>) -> CValue<'tcx> { fn trans_char_binop<'a, 'tcx: 'a>(
fx: &mut FunctionCx<'a, 'tcx>,
bin_op: BinOp,
lhs: CValue<'tcx>,
rhs: CValue<'tcx>,
ty: Ty<'tcx>,
) -> CValue<'tcx> {
let res = binop_match! { let res = binop_match! {
fx, bin_op, false, lhs, rhs, ty, "char"; fx, bin_op, false, lhs, rhs, ty, "char";
Add (_) bug; Add (_) bug;
@@ -571,7 +697,14 @@ fn trans_char_binop<'a, 'tcx: 'a>(fx: &mut FunctionCx<'a, 'tcx>, bin_op: BinOp,
res res
} }
fn trans_ptr_binop<'a, 'tcx: 'a>(fx: &mut FunctionCx<'a, 'tcx>, bin_op: BinOp, lhs: CValue<'tcx>, rhs: CValue<'tcx>, ty: Ty<'tcx>, _checked: bool) -> CValue<'tcx> { fn trans_ptr_binop<'a, 'tcx: 'a>(
fx: &mut FunctionCx<'a, 'tcx>,
bin_op: BinOp,
lhs: CValue<'tcx>,
rhs: CValue<'tcx>,
ty: Ty<'tcx>,
_checked: bool,
) -> CValue<'tcx> {
binop_match! { binop_match! {
fx, bin_op, false, lhs, rhs, ty, "ptr"; fx, bin_op, false, lhs, rhs, ty, "ptr";
Add (_) bug; Add (_) bug;
@@ -596,41 +729,66 @@ fn trans_ptr_binop<'a, 'tcx: 'a>(fx: &mut FunctionCx<'a, 'tcx>, bin_op: BinOp, l
} }
} }
pub fn trans_place<'a, 'tcx: 'a>(fx: &mut FunctionCx<'a, 'tcx>, place: &Place<'tcx>) -> CPlace<'tcx> { pub fn trans_place<'a, 'tcx: 'a>(
fx: &mut FunctionCx<'a, 'tcx>,
place: &Place<'tcx>,
) -> CPlace<'tcx> {
match place { match place {
Place::Local(local) => fx.get_local_place(*local), Place::Local(local) => fx.get_local_place(*local),
Place::Promoted(promoted) => crate::constant::trans_promoted(fx, promoted.0), Place::Promoted(promoted) => crate::constant::trans_promoted(fx, promoted.0),
Place::Static(static_) => unimplemented!("static place {:?} ty {:?}", static_.def_id, static_.ty), Place::Static(static_) => {
unimplemented!("static place {:?} ty {:?}", static_.def_id, static_.ty)
}
Place::Projection(projection) => { Place::Projection(projection) => {
let base = trans_place(fx, &projection.base); let base = trans_place(fx, &projection.base);
match projection.elem { match projection.elem {
ProjectionElem::Deref => { ProjectionElem::Deref => CPlace::Addr(
CPlace::Addr(base.to_cvalue(fx).load_value(fx), fx.layout_of(place.ty(&*fx.mir, fx.tcx).to_ty(fx.tcx))) base.to_cvalue(fx).load_value(fx),
} fx.layout_of(place.ty(&*fx.mir, fx.tcx).to_ty(fx.tcx)),
ProjectionElem::Field(field, _ty) => { ),
base.place_field(fx, field) ProjectionElem::Field(field, _ty) => base.place_field(fx, field),
} ProjectionElem::Index(local) => {
ProjectionElem::Index(local) => unimplemented!("projection index {:?} {:?}", projection.base, local), unimplemented!("projection index {:?} {:?}", projection.base, local)
ProjectionElem::ConstantIndex { offset, min_length: _, from_end: false } => unimplemented!("projection const index {:?} offset {:?} not from end", projection.base, offset),
ProjectionElem::ConstantIndex { offset, min_length: _, from_end: true } => unimplemented!("projection const index {:?} offset {:?} from end", projection.base, offset),
ProjectionElem::Subslice { from, to } => unimplemented!("projection subslice {:?} from {} to {}", projection.base, from, to),
ProjectionElem::Downcast(_adt_def, variant) => {
base.downcast_variant(fx, variant)
} }
ProjectionElem::ConstantIndex {
offset,
min_length: _,
from_end: false,
} => unimplemented!(
"projection const index {:?} offset {:?} not from end",
projection.base,
offset
),
ProjectionElem::ConstantIndex {
offset,
min_length: _,
from_end: true,
} => unimplemented!(
"projection const index {:?} offset {:?} from end",
projection.base,
offset
),
ProjectionElem::Subslice { from, to } => unimplemented!(
"projection subslice {:?} from {} to {}",
projection.base,
from,
to
),
ProjectionElem::Downcast(_adt_def, variant) => base.downcast_variant(fx, variant),
} }
} }
} }
} }
pub fn trans_operand<'a, 'tcx>(fx: &mut FunctionCx<'a, 'tcx>, operand: &Operand<'tcx>) -> CValue<'tcx> { pub fn trans_operand<'a, 'tcx>(
fx: &mut FunctionCx<'a, 'tcx>,
operand: &Operand<'tcx>,
) -> CValue<'tcx> {
match operand { match operand {
Operand::Move(place) | Operand::Move(place) | Operand::Copy(place) => {
Operand::Copy(place) => {
let cplace = trans_place(fx, place); let cplace = trans_place(fx, place);
cplace.to_cvalue(fx) cplace.to_cvalue(fx)
},
Operand::Constant(const_) => {
crate::constant::trans_constant(fx, const_)
} }
Operand::Constant(const_) => crate::constant::trans_constant(fx, const_),
} }
} }

View File

@@ -2,7 +2,7 @@ use std::fmt;
use rustc_target::spec::{HasTargetSpec, Target}; use rustc_target::spec::{HasTargetSpec, Target};
use cranelift_module::{Module, DataId}; use cranelift_module::{DataId, Module};
use crate::prelude::*; use crate::prelude::*;
@@ -21,36 +21,33 @@ impl EntityRef for Variable {
} }
} }
pub fn cton_type_from_ty<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ty: Ty<'tcx>) -> Option<types::Type> { pub fn cton_type_from_ty<'a, 'tcx: 'a>(
tcx: TyCtxt<'a, 'tcx, 'tcx>,
ty: Ty<'tcx>,
) -> Option<types::Type> {
Some(match ty.sty { Some(match ty.sty {
TypeVariants::TyBool => types::I8, TypeVariants::TyBool => types::I8,
TypeVariants::TyUint(size) => { TypeVariants::TyUint(size) => match size {
match size {
UintTy::U8 => types::I8, UintTy::U8 => types::I8,
UintTy::U16 => types::I16, UintTy::U16 => types::I16,
UintTy::U32 => types::I32, UintTy::U32 => types::I32,
UintTy::U64 => types::I64, UintTy::U64 => types::I64,
UintTy::U128 => unimplemented!("u128"), UintTy::U128 => unimplemented!("u128"),
UintTy::Usize => types::I64, UintTy::Usize => types::I64,
} },
} TypeVariants::TyInt(size) => match size {
TypeVariants::TyInt(size) => {
match size {
IntTy::I8 => types::I8, IntTy::I8 => types::I8,
IntTy::I16 => types::I16, IntTy::I16 => types::I16,
IntTy::I32 => types::I32, IntTy::I32 => types::I32,
IntTy::I64 => types::I64, IntTy::I64 => types::I64,
IntTy::I128 => unimplemented!("i128"), IntTy::I128 => unimplemented!("i128"),
IntTy::Isize => types::I64, IntTy::Isize => types::I64,
} },
}
TypeVariants::TyChar => types::I32, TypeVariants::TyChar => types::I32,
TypeVariants::TyFloat(size) => { TypeVariants::TyFloat(size) => match size {
match size {
FloatTy::F32 => types::I32, FloatTy::F32 => types::I32,
FloatTy::F64 => types::I64, FloatTy::F64 => types::I64,
} },
}
TypeVariants::TyFnPtr(_) => types::I64, TypeVariants::TyFnPtr(_) => types::I64,
TypeVariants::TyRawPtr(TypeAndMut { ty, mutbl: _ }) | TypeVariants::TyRef(_, ty, _) => { TypeVariants::TyRawPtr(TypeAndMut { ty, mutbl: _ }) | TypeVariants::TyRef(_, ty, _) => {
if ty.is_sized(tcx.at(DUMMY_SP), ParamEnv::reveal_all()) { if ty.is_sized(tcx.at(DUMMY_SP), ParamEnv::reveal_all()) {
@@ -68,7 +65,7 @@ fn codegen_field<'a, 'tcx: 'a>(
fx: &mut FunctionCx<'a, 'tcx>, fx: &mut FunctionCx<'a, 'tcx>,
base: Value, base: Value,
layout: TyLayout<'tcx>, layout: TyLayout<'tcx>,
field: mir::Field field: mir::Field,
) -> (Value, TyLayout<'tcx>) { ) -> (Value, TyLayout<'tcx>) {
let field_offset = layout.fields.offset(field.index()); let field_offset = layout.fields.offset(field.index());
let field_ty = layout.field(&*fx, field.index()); let field_ty = layout.field(&*fx, field.index());
@@ -91,13 +88,14 @@ pub enum CValue<'tcx> {
impl<'tcx> CValue<'tcx> { impl<'tcx> CValue<'tcx> {
pub fn layout(&self) -> TyLayout<'tcx> { pub fn layout(&self) -> TyLayout<'tcx> {
match *self { match *self {
CValue::ByRef(_, layout) | CValue::ByRef(_, layout) | CValue::ByVal(_, layout) | CValue::Func(_, layout) => layout,
CValue::ByVal(_, layout) |
CValue::Func(_, layout) => layout
} }
} }
pub fn force_stack<'a>(self, fx: &mut FunctionCx<'a, 'tcx>) -> Value where 'tcx: 'a { pub fn force_stack<'a>(self, fx: &mut FunctionCx<'a, 'tcx>) -> Value
where
'tcx: 'a,
{
match self { match self {
CValue::ByRef(value, _layout) => value, CValue::ByRef(value, _layout) => value,
CValue::ByVal(value, layout) => { CValue::ByVal(value, layout) => {
@@ -116,16 +114,19 @@ impl<'tcx> CValue<'tcx> {
} }
} }
pub fn load_value<'a>(self, fx: &mut FunctionCx<'a, 'tcx>) -> Value where 'tcx: 'a{ pub fn load_value<'a>(self, fx: &mut FunctionCx<'a, 'tcx>) -> Value
where
'tcx: 'a,
{
match self { match self {
CValue::ByRef(addr, layout) => { CValue::ByRef(addr, layout) => {
let cton_ty = fx.cton_type(layout.ty).expect(&format!("load_value of type {:?}", layout.ty)); let cton_ty = fx
.cton_type(layout.ty)
.expect(&format!("load_value of type {:?}", layout.ty));
fx.bcx.ins().load(cton_ty, MemFlags::new(), addr, 0) fx.bcx.ins().load(cton_ty, MemFlags::new(), addr, 0)
} }
CValue::ByVal(value, _layout) => value, CValue::ByVal(value, _layout) => value,
CValue::Func(func, _layout) => { CValue::Func(func, _layout) => fx.bcx.ins().func_addr(types::I64, func),
fx.bcx.ins().func_addr(types::I64, func)
}
} }
} }
@@ -137,7 +138,10 @@ impl<'tcx> CValue<'tcx> {
} }
} }
pub fn value_field<'a>(self, fx: &mut FunctionCx<'a, 'tcx>, field: mir::Field) -> CValue<'tcx> where 'tcx: 'a { pub fn value_field<'a>(self, fx: &mut FunctionCx<'a, 'tcx>, field: mir::Field) -> CValue<'tcx>
where
'tcx: 'a,
{
let (base, layout) = match self { let (base, layout) = match self {
CValue::ByRef(addr, layout) => (addr, layout), CValue::ByRef(addr, layout) => (addr, layout),
_ => bug!("place_field for {:?}", self), _ => bug!("place_field for {:?}", self),
@@ -147,7 +151,14 @@ impl<'tcx> CValue<'tcx> {
CValue::ByRef(field_ptr, field_layout) 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 { pub fn const_val<'a>(
fx: &mut FunctionCx<'a, 'tcx>,
ty: Ty<'tcx>,
const_val: i64,
) -> CValue<'tcx>
where
'tcx: 'a,
{
let cton_ty = fx.cton_type(ty).unwrap(); let cton_ty = fx.cton_type(ty).unwrap();
let layout = fx.layout_of(ty); let layout = fx.layout_of(ty);
CValue::ByVal(fx.bcx.ins().iconst(cton_ty, const_val), layout) CValue::ByVal(fx.bcx.ins().iconst(cton_ty, const_val), layout)
@@ -172,12 +183,15 @@ pub enum CPlace<'tcx> {
impl<'a, 'tcx: 'a> CPlace<'tcx> { impl<'a, 'tcx: 'a> CPlace<'tcx> {
pub fn layout(&self) -> TyLayout<'tcx> { pub fn layout(&self) -> TyLayout<'tcx> {
match *self { match *self {
CPlace::Var(_, layout) | CPlace::Var(_, layout) | CPlace::Addr(_, layout) => layout,
CPlace::Addr(_, layout) => layout,
} }
} }
pub fn from_stack_slot(fx: &mut FunctionCx<'a, 'tcx>, stack_slot: StackSlot, ty: Ty<'tcx>) -> CPlace<'tcx> { pub fn from_stack_slot(
fx: &mut FunctionCx<'a, 'tcx>,
stack_slot: StackSlot,
ty: Ty<'tcx>,
) -> CPlace<'tcx> {
let layout = fx.layout_of(ty); let layout = fx.layout_of(ty);
CPlace::Addr(fx.bcx.ins().stack_addr(types::I64, stack_slot, 0), layout) CPlace::Addr(fx.bcx.ins().stack_addr(types::I64, stack_slot, 0), layout)
} }
@@ -198,23 +212,25 @@ impl<'a, 'tcx: 'a> CPlace<'tcx> {
pub fn write_cvalue(self, fx: &mut FunctionCx<'a, 'tcx>, from: CValue<'tcx>) { pub fn write_cvalue(self, fx: &mut FunctionCx<'a, 'tcx>, from: CValue<'tcx>) {
match (&self.layout().ty.sty, &from.layout().ty.sty) { match (&self.layout().ty.sty, &from.layout().ty.sty) {
(TypeVariants::TyRef(_, t, dest_mut), TypeVariants::TyRef(_, u, src_mut)) if ( (TypeVariants::TyRef(_, t, dest_mut), TypeVariants::TyRef(_, u, src_mut))
if *dest_mut != ::rustc::hir::Mutability::MutImmutable && src_mut != dest_mut { if (if *dest_mut != ::rustc::hir::Mutability::MutImmutable && src_mut != dest_mut {
false false
} else if t != u { } else if t != u {
false false
} else { } else {
true true
} }) =>
) => { {
// &mut T -> &T is allowed // &mut T -> &T is allowed
// &'a T -> &'b T is allowed // &'a T -> &'b T is allowed
} }
_ => { _ => {
assert_eq!( assert_eq!(
self.layout().ty, from.layout().ty, self.layout().ty,
from.layout().ty,
"Can't write value of incompatible type to place {:?} {:?}\n\n{:#?}", "Can't write value of incompatible type to place {:?} {:?}\n\n{:#?}",
self.layout().ty.sty, from.layout().ty.sty, self.layout().ty.sty,
from.layout().ty.sty,
fx, fx,
); );
} }
@@ -224,7 +240,7 @@ impl<'a, 'tcx: 'a> CPlace<'tcx> {
CPlace::Var(var, _) => { CPlace::Var(var, _) => {
let data = from.load_value(fx); let data = from.load_value(fx);
fx.bcx.def_var(var, data) fx.bcx.def_var(var, data)
}, }
CPlace::Addr(addr, layout) => { CPlace::Addr(addr, layout) => {
let size = layout.size.bytes() as i32; let size = layout.size.bytes() as i32;
@@ -235,17 +251,26 @@ impl<'a, 'tcx: 'a> CPlace<'tcx> {
let from = from.expect_byref(); let from = from.expect_byref();
let mut offset = 0; let mut offset = 0;
while size - offset >= 8 { while size - offset >= 8 {
let byte = fx.bcx.ins().load(types::I64, MemFlags::new(), from.0, offset); let byte = fx
.bcx
.ins()
.load(types::I64, MemFlags::new(), from.0, offset);
fx.bcx.ins().store(MemFlags::new(), byte, addr, offset); fx.bcx.ins().store(MemFlags::new(), byte, addr, offset);
offset += 8; offset += 8;
} }
while size - offset >= 4 { while size - offset >= 4 {
let byte = fx.bcx.ins().load(types::I32, MemFlags::new(), from.0, offset); let byte = fx
.bcx
.ins()
.load(types::I32, MemFlags::new(), from.0, offset);
fx.bcx.ins().store(MemFlags::new(), byte, addr, offset); fx.bcx.ins().store(MemFlags::new(), byte, addr, offset);
offset += 4; offset += 4;
} }
while offset < size { while offset < size {
let byte = fx.bcx.ins().load(types::I8, MemFlags::new(), from.0, offset); let byte = fx
.bcx
.ins()
.load(types::I8, MemFlags::new(), from.0, offset);
fx.bcx.ins().store(MemFlags::new(), byte, addr, offset); fx.bcx.ins().store(MemFlags::new(), byte, addr, offset);
offset += 1; offset += 1;
} }
@@ -275,7 +300,13 @@ impl<'a, 'tcx: 'a> CPlace<'tcx> {
} }
} }
pub fn cton_intcast<'a, 'tcx: 'a>(fx: &mut FunctionCx<'a, 'tcx>, val: Value, from: Ty<'tcx>, to: Ty<'tcx>, signed: bool) -> Value { pub fn cton_intcast<'a, 'tcx: 'a>(
fx: &mut FunctionCx<'a, 'tcx>,
val: Value,
from: Ty<'tcx>,
to: Ty<'tcx>,
signed: bool,
) -> Value {
let from = fx.cton_type(from).unwrap(); let from = fx.cton_type(from).unwrap();
let to = fx.cton_type(to).unwrap(); let to = fx.cton_type(to).unwrap();
if from == to { if from == to {
@@ -352,7 +383,8 @@ impl<'a, 'tcx> HasTargetSpec for &'a FunctionCx<'a, 'tcx> {
impl<'a, 'tcx: 'a> FunctionCx<'a, 'tcx> { impl<'a, 'tcx: 'a> FunctionCx<'a, 'tcx> {
pub fn monomorphize<T>(&self, value: &T) -> T pub fn monomorphize<T>(&self, value: &T) -> T
where T: TypeFoldable<'tcx> where
T: TypeFoldable<'tcx>,
{ {
self.tcx.subst_and_normalize_erasing_regions( self.tcx.subst_and_normalize_erasing_regions(
self.param_substs, self.param_substs,

View File

@@ -1,29 +1,37 @@
use crate::prelude::*;
use rustc::ty::Const;
use rustc::mir::interpret::{ConstValue, GlobalId, AllocId, read_target_uint};
use rustc_mir::interpret::{CompileTimeEvaluator, Memory, MemoryKind};
use cranelift_module::*; use cranelift_module::*;
use crate::prelude::*;
use rustc::mir::interpret::{read_target_uint, AllocId, ConstValue, GlobalId};
use rustc::ty::Const;
use rustc_mir::interpret::{CompileTimeEvaluator, Memory, MemoryKind};
pub fn trans_promoted<'a, 'tcx: 'a>(fx: &mut FunctionCx<'a, 'tcx>, promoted: Promoted) -> CPlace<'tcx> { pub fn trans_promoted<'a, 'tcx: 'a>(
fx: &mut FunctionCx<'a, 'tcx>,
promoted: Promoted,
) -> CPlace<'tcx> {
let const_ = fx let const_ = fx
.tcx .tcx
.const_eval(ParamEnv::reveal_all().and(GlobalId { .const_eval(ParamEnv::reveal_all().and(GlobalId {
instance: fx.instance, instance: fx.instance,
promoted: Some(promoted), promoted: Some(promoted),
})) })).unwrap();
.unwrap();
let const_ = force_eval_const(fx, const_); let const_ = force_eval_const(fx, const_);
trans_const_place(fx, const_) trans_const_place(fx, const_)
} }
pub fn trans_constant<'a, 'tcx: 'a>(fx: &mut FunctionCx<'a, 'tcx>, constant: &Constant<'tcx>) -> CValue<'tcx> { pub fn trans_constant<'a, 'tcx: 'a>(
fx: &mut FunctionCx<'a, 'tcx>,
constant: &Constant<'tcx>,
) -> CValue<'tcx> {
let const_ = fx.monomorphize(&constant.literal); let const_ = fx.monomorphize(&constant.literal);
let const_ = force_eval_const(fx, const_); let const_ = force_eval_const(fx, const_);
trans_const_value(fx, const_) trans_const_value(fx, const_)
} }
fn force_eval_const<'a, 'tcx: 'a>(fx: &FunctionCx<'a, 'tcx>, const_: &'tcx Const<'tcx>) -> &'tcx Const<'tcx> { fn force_eval_const<'a, 'tcx: 'a>(
fx: &FunctionCx<'a, 'tcx>,
const_: &'tcx Const<'tcx>,
) -> &'tcx Const<'tcx> {
match const_.val { match const_.val {
ConstValue::Unevaluated(def_id, ref substs) => { ConstValue::Unevaluated(def_id, ref substs) => {
let param_env = ParamEnv::reveal_all(); let param_env = ParamEnv::reveal_all();
@@ -33,12 +41,15 @@ fn force_eval_const<'a, 'tcx: 'a>(fx: &FunctionCx<'a, 'tcx>, const_: &'tcx Const
promoted: None, promoted: None,
}; };
fx.tcx.const_eval(param_env.and(cid)).unwrap() fx.tcx.const_eval(param_env.and(cid)).unwrap()
}, }
_ => const_, _ => const_,
} }
} }
fn trans_const_value<'a, 'tcx: 'a>(fx: &mut FunctionCx<'a, 'tcx>, const_: &'tcx Const<'tcx>) -> CValue<'tcx> { fn trans_const_value<'a, 'tcx: 'a>(
fx: &mut FunctionCx<'a, 'tcx>,
const_: &'tcx Const<'tcx>,
) -> CValue<'tcx> {
let ty = fx.monomorphize(&const_.ty); let ty = fx.monomorphize(&const_.ty);
let layout = fx.layout_of(ty); let layout = fx.layout_of(ty);
match ty.sty { match ty.sty {
@@ -58,13 +69,14 @@ fn trans_const_value<'a, 'tcx: 'a>(fx: &mut FunctionCx<'a, 'tcx>, const_: &'tcx
let func_ref = fx.get_function_ref(Instance::new(def_id, substs)); let func_ref = fx.get_function_ref(Instance::new(def_id, substs));
CValue::Func(func_ref, layout) CValue::Func(func_ref, layout)
} }
_ => { _ => trans_const_place(fx, const_).to_cvalue(fx),
trans_const_place(fx, const_).to_cvalue(fx)
}
} }
} }
fn trans_const_place<'a, 'tcx: 'a>(fx: &mut FunctionCx<'a, 'tcx>, const_: &'tcx Const<'tcx>) -> CPlace<'tcx> { fn trans_const_place<'a, 'tcx: 'a>(
fx: &mut FunctionCx<'a, 'tcx>,
const_: &'tcx Const<'tcx>,
) -> CPlace<'tcx> {
let ty = fx.monomorphize(&const_.ty); let ty = fx.monomorphize(&const_.ty);
let layout = fx.layout_of(ty); let layout = fx.layout_of(ty);
if true { if true {
@@ -75,7 +87,9 @@ fn trans_const_place<'a, 'tcx: 'a>(fx: &mut FunctionCx<'a, 'tcx>, const_: &'tcx
let mut memory = Memory::<CompileTimeEvaluator>::new(fx.tcx.at(DUMMY_SP), ()); let mut memory = Memory::<CompileTimeEvaluator>::new(fx.tcx.at(DUMMY_SP), ());
let alloc = fx.tcx.const_value_to_allocation(const_); let alloc = fx.tcx.const_value_to_allocation(const_);
//println!("const value: {:?} allocation: {:?}", value, alloc); //println!("const value: {:?} allocation: {:?}", value, alloc);
let alloc_id = memory.allocate_value(alloc.clone(), MemoryKind::Stack).unwrap(); let alloc_id = memory
.allocate_value(alloc.clone(), MemoryKind::Stack)
.unwrap();
let data_id = get_global_for_alloc_id(fx, &memory, alloc_id); let data_id = get_global_for_alloc_id(fx, &memory, alloc_id);
let local_data_id = fx.module.declare_data_in_func(data_id, &mut fx.bcx.func); let local_data_id = fx.module.declare_data_in_func(data_id, &mut fx.bcx.func);
// TODO: does global_value return a ptr of a val? // TODO: does global_value return a ptr of a val?
@@ -84,14 +98,19 @@ fn trans_const_place<'a, 'tcx: 'a>(fx: &mut FunctionCx<'a, 'tcx>, const_: &'tcx
} }
// If ret.1 is true, then the global didn't exist before // If ret.1 is true, then the global didn't exist before
fn define_global_for_alloc_id(fx: &mut FunctionCx, alloc_id: AllocId, todo: &mut HashMap<AllocId, DataId>) -> (DataId, bool) { fn define_global_for_alloc_id(
fx: &mut FunctionCx,
alloc_id: AllocId,
todo: &mut HashMap<AllocId, DataId>,
) -> (DataId, bool) {
use std::collections::hash_map::Entry; use std::collections::hash_map::Entry;
match fx.constants.entry(alloc_id) { match fx.constants.entry(alloc_id) {
Entry::Occupied(mut occ) => { Entry::Occupied(mut occ) => (*occ.get_mut(), false),
(*occ.get_mut(), false)
}
Entry::Vacant(vac) => { Entry::Vacant(vac) => {
let data_id = fx.module.declare_data(&alloc_id.0.to_string(), Linkage::Local, false).unwrap(); let data_id = fx
.module
.declare_data(&alloc_id.0.to_string(), Linkage::Local, false)
.unwrap();
todo.insert(alloc_id, data_id); todo.insert(alloc_id, data_id);
vac.insert(data_id); vac.insert(data_id);
(data_id, true) (data_id, true)
@@ -99,7 +118,11 @@ fn define_global_for_alloc_id(fx: &mut FunctionCx, alloc_id: AllocId, todo: &mut
} }
} }
fn get_global_for_alloc_id(fx: &mut FunctionCx, memory: &Memory<CompileTimeEvaluator>, alloc_id: AllocId) -> DataId { fn get_global_for_alloc_id(
fx: &mut FunctionCx,
memory: &Memory<CompileTimeEvaluator>,
alloc_id: AllocId,
) -> DataId {
if let Some(data_id) = fx.constants.get(&alloc_id) { if let Some(data_id) = fx.constants.get(&alloc_id) {
return *data_id; return *data_id;
} }
@@ -108,13 +131,22 @@ fn get_global_for_alloc_id(fx: &mut FunctionCx, memory: &Memory<CompileTimeEvalu
let mut done = HashSet::new(); let mut done = HashSet::new();
define_global_for_alloc_id(fx, alloc_id, &mut todo); define_global_for_alloc_id(fx, alloc_id, &mut todo);
while let Some((alloc_id, data_id)) = { let next = todo.drain().next(); next } { while let Some((alloc_id, data_id)) = {
println!("cur: {:?}:{:?} todo: {:?} done: {:?}", alloc_id, data_id, todo, done); let next = todo.drain().next();
next
} {
println!(
"cur: {:?}:{:?} todo: {:?} done: {:?}",
alloc_id, data_id, todo, done
);
let alloc = memory.get(alloc_id).unwrap(); let alloc = memory.get(alloc_id).unwrap();
let mut data_ctx = DataContext::new(); let mut data_ctx = DataContext::new();
data_ctx.define(alloc.bytes.to_vec().into_boxed_slice(), Writability::Readonly); data_ctx.define(
alloc.bytes.to_vec().into_boxed_slice(),
Writability::Readonly,
);
for &(offset, reloc) in alloc.relocations.iter() { for &(offset, reloc) in alloc.relocations.iter() {
let data_id = define_global_for_alloc_id(fx, reloc, &mut todo).0; let data_id = define_global_for_alloc_id(fx, reloc, &mut todo).0;

View File

@@ -4,82 +4,81 @@
extern crate syntax; extern crate syntax;
#[macro_use] #[macro_use]
extern crate rustc; extern crate rustc;
extern crate rustc_mir;
extern crate rustc_codegen_utils; extern crate rustc_codegen_utils;
extern crate rustc_target;
extern crate rustc_incremental; extern crate rustc_incremental;
extern crate rustc_mir;
extern crate rustc_target;
#[macro_use] #[macro_use]
extern crate rustc_data_structures; extern crate rustc_data_structures;
extern crate ar; extern crate ar;
extern crate faerie; extern crate faerie;
//extern crate goblin; //extern crate goblin;
extern crate target_lexicon;
extern crate cranelift; extern crate cranelift;
extern crate cranelift_faerie;
extern crate cranelift_module; extern crate cranelift_module;
extern crate cranelift_simplejit; extern crate cranelift_simplejit;
extern crate cranelift_faerie; extern crate target_lexicon;
use std::any::Any; use std::any::Any;
use std::sync::{mpsc, Arc};
use std::path::Path;
use std::fs::File; use std::fs::File;
use std::path::Path;
use std::sync::{mpsc, Arc};
use syntax::symbol::Symbol;
use rustc::session::{
CompileIncomplete,
config::{
CrateType,
OutputFilenames,
},
};
use rustc::middle::cstore::MetadataLoader;
use rustc::dep_graph::DepGraph; use rustc::dep_graph::DepGraph;
use rustc::middle::cstore::MetadataLoader;
use rustc::session::{
config::{CrateType, OutputFilenames},
CompileIncomplete,
};
use rustc::ty::query::Providers; use rustc::ty::query::Providers;
use rustc_codegen_utils::codegen_backend::CodegenBackend; use rustc_codegen_utils::codegen_backend::CodegenBackend;
use rustc_codegen_utils::link::{out_filename, build_link_meta}; use rustc_codegen_utils::link::{build_link_meta, out_filename};
use rustc_data_structures::owning_ref::{self, OwningRef}; use rustc_data_structures::owning_ref::{self, OwningRef};
use syntax::symbol::Symbol;
use cranelift::codegen::settings; use cranelift::codegen::settings;
use cranelift_faerie::*; use cranelift_faerie::*;
mod abi; mod abi;
mod base; mod base;
mod constant;
mod common; mod common;
mod constant;
mod pretty_clif; mod pretty_clif;
mod prelude { mod prelude {
pub use std::any::Any; pub use std::any::Any;
pub use std::collections::{HashMap, HashSet}; pub use std::collections::{HashMap, HashSet};
pub use syntax::codemap::DUMMY_SP;
pub use syntax::ast::{IntTy, UintTy, FloatTy};
pub use rustc::hir::def_id::{DefId, LOCAL_CRATE}; pub use rustc::hir::def_id::{DefId, LOCAL_CRATE};
pub use rustc::mir; pub use rustc::mir;
pub use rustc::mir::*;
pub use rustc::mir::interpret::AllocId; pub use rustc::mir::interpret::AllocId;
pub use rustc::mir::*;
pub use rustc::session::Session; pub use rustc::session::Session;
pub use rustc::ty::layout::{self, LayoutOf, TyLayout, Size}; pub use rustc::ty::layout::{self, LayoutOf, Size, TyLayout};
pub use rustc::ty::{ pub use rustc::ty::{
self, subst::Substs, FnSig, Instance, InstanceDef, ParamEnv, PolyFnSig, Ty, TyCtxt, self, subst::Substs, FnSig, Instance, InstanceDef, ParamEnv, PolyFnSig, Ty, TyCtxt,
TypeFoldable, TypeVariants, TypeAndMut, TypeAndMut, TypeFoldable, TypeVariants,
}; };
pub use rustc_data_structures::{indexed_vec::Idx, sync::Lrc}; pub use rustc_data_structures::{indexed_vec::Idx, sync::Lrc};
pub use rustc_mir::monomorphize::{MonoItem, collector}; pub use rustc_mir::monomorphize::{collector, MonoItem};
pub use syntax::ast::{FloatTy, IntTy, UintTy};
pub use syntax::codemap::DUMMY_SP;
pub use cranelift::codegen::ir::{ pub use cranelift::codegen::ir::{
condcodes::IntCC, function::Function, ExternalName, FuncRef, StackSlot, Inst condcodes::IntCC, function::Function, ExternalName, FuncRef, Inst, StackSlot,
}; };
pub use cranelift::codegen::Context; pub use cranelift::codegen::Context;
pub use cranelift::prelude::*; pub use cranelift::prelude::*;
pub use cranelift_module::{Module, Backend, DataContext, FuncId, DataId, Linkage, Writability}; pub use cranelift_module::{
pub use cranelift_simplejit::{SimpleJITBuilder, SimpleJITBackend}; Backend, DataContext, DataId, FuncId, Linkage, Module, Writability,
};
pub use cranelift_simplejit::{SimpleJITBackend, SimpleJITBuilder};
pub use crate::abi::*; pub use crate::abi::*;
pub use crate::base::{trans_operand, trans_place};
pub use crate::common::Variable; pub use crate::common::Variable;
pub use crate::common::*; pub use crate::common::*;
pub use crate::base::{trans_operand, trans_place};
pub use crate::CodegenCx; pub use crate::CodegenCx;
} }
@@ -95,14 +94,18 @@ pub struct CodegenCx<'a, 'tcx: 'a, B: Backend + 'a> {
struct CraneliftMetadataLoader; struct CraneliftMetadataLoader;
impl MetadataLoader for CraneliftMetadataLoader { impl MetadataLoader for CraneliftMetadataLoader {
fn get_rlib_metadata(&self, _target: &rustc_target::spec::Target, path: &Path) -> Result<owning_ref::ErasedBoxRef<[u8]>, String> { fn get_rlib_metadata(
let mut archive = ar::Archive::new(File::open(path).map_err(|e|format!("{:?}", e))?); &self,
_target: &rustc_target::spec::Target,
path: &Path,
) -> Result<owning_ref::ErasedBoxRef<[u8]>, String> {
let mut archive = ar::Archive::new(File::open(path).map_err(|e| format!("{:?}", e))?);
// Iterate over all entries in the archive: // Iterate over all entries in the archive:
while let Some(entry_result) = archive.next_entry() { while let Some(entry_result) = archive.next_entry() {
let mut entry = entry_result.map_err(|e|format!("{:?}", e))?; let mut entry = entry_result.map_err(|e| format!("{:?}", e))?;
if entry.header().identifier() == b".rustc.clif_metadata" { if entry.header().identifier() == b".rustc.clif_metadata" {
let mut buf = Vec::new(); let mut buf = Vec::new();
::std::io::copy(&mut entry, &mut buf).map_err(|e|format!("{:?}", e))?; ::std::io::copy(&mut entry, &mut buf).map_err(|e| format!("{:?}", e))?;
let buf: OwningRef<Vec<u8>, [u8]> = OwningRef::new(buf).into(); let buf: OwningRef<Vec<u8>, [u8]> = OwningRef::new(buf).into();
return Ok(rustc_erase_owner!(buf.map_owner_box())); return Ok(rustc_erase_owner!(buf.map_owner_box()));
} }
@@ -112,7 +115,11 @@ impl MetadataLoader for CraneliftMetadataLoader {
//self.get_dylib_metadata(target, path) //self.get_dylib_metadata(target, path)
} }
fn get_dylib_metadata(&self, _target: &rustc_target::spec::Target, _path: &Path) -> Result<owning_ref::ErasedBoxRef<[u8]>, String> { fn get_dylib_metadata(
&self,
_target: &rustc_target::spec::Target,
_path: &Path,
) -> Result<owning_ref::ErasedBoxRef<[u8]>, String> {
//use goblin::Object; //use goblin::Object;
//let buffer = ::std::fs::read(path).map_err(|e|format!("{:?}", e))?; //let buffer = ::std::fs::read(path).map_err(|e|format!("{:?}", e))?;
@@ -149,13 +156,15 @@ impl CodegenBackend for CraneliftCodegenBackend {
fn init(&self, sess: &Session) { fn init(&self, sess: &Session) {
for cty in sess.opts.crate_types.iter() { for cty in sess.opts.crate_types.iter() {
match *cty { match *cty {
CrateType::CrateTypeRlib | CrateType::CrateTypeDylib | CrateType::CrateTypeRlib
CrateType::CrateTypeExecutable => {}, | CrateType::CrateTypeDylib
| CrateType::CrateTypeExecutable => {}
_ => { _ => {
sess.parse_sess.span_diagnostic.warn( sess.parse_sess.span_diagnostic.warn(&format!(
&format!("LLVM unsupported, so output type {} is not supported", cty) "LLVM unsupported, so output type {} is not supported",
); cty
}, ));
}
} }
} }
} }
@@ -167,9 +176,7 @@ impl CodegenBackend for CraneliftCodegenBackend {
fn provide(&self, providers: &mut Providers) { fn provide(&self, providers: &mut Providers) {
rustc_codegen_utils::symbol_names::provide(providers); rustc_codegen_utils::symbol_names::provide(providers);
providers.target_features_whitelist = |_tcx, _cnum| { providers.target_features_whitelist = |_tcx, _cnum| Lrc::new(Default::default());
Lrc::new(Default::default())
};
providers.is_reachable_non_generic = |_tcx, _defid| true; providers.is_reachable_non_generic = |_tcx, _defid| true;
providers.exported_symbols = |_tcx, _crate| Arc::new(Vec::new()); providers.exported_symbols = |_tcx, _crate| Arc::new(Vec::new());
} }
@@ -180,7 +187,7 @@ impl CodegenBackend for CraneliftCodegenBackend {
fn codegen_crate<'a, 'tcx>( fn codegen_crate<'a, 'tcx>(
&self, &self,
tcx: TyCtxt<'a, 'tcx, 'tcx>, tcx: TyCtxt<'a, 'tcx, 'tcx>,
_rx: mpsc::Receiver<Box<Any + Send>> _rx: mpsc::Receiver<Box<Any + Send>>,
) -> Box<Any> { ) -> Box<Any> {
use rustc_mir::monomorphize::item::MonoItem; use rustc_mir::monomorphize::item::MonoItem;
@@ -188,20 +195,18 @@ impl CodegenBackend for CraneliftCodegenBackend {
rustc_codegen_utils::symbol_names_test::report_symbol_names(tcx); rustc_codegen_utils::symbol_names_test::report_symbol_names(tcx);
rustc_incremental::assert_dep_graph(tcx); rustc_incremental::assert_dep_graph(tcx);
rustc_incremental::assert_module_sources::assert_module_sources(tcx); rustc_incremental::assert_module_sources::assert_module_sources(tcx);
rustc_mir::monomorphize::assert_symbols_are_distinct(tcx, rustc_mir::monomorphize::assert_symbols_are_distinct(
collector::collect_crate_mono_items(
tcx, tcx,
collector::MonoItemCollectionMode::Eager collector::collect_crate_mono_items(tcx, collector::MonoItemCollectionMode::Eager)
).0.iter() .0
.iter(),
); );
//::rustc::middle::dependency_format::calculate(tcx); //::rustc::middle::dependency_format::calculate(tcx);
let _ = tcx.link_args(LOCAL_CRATE); let _ = tcx.link_args(LOCAL_CRATE);
let _ = tcx.native_libraries(LOCAL_CRATE); let _ = tcx.native_libraries(LOCAL_CRATE);
for mono_item in for mono_item in
collector::collect_crate_mono_items( collector::collect_crate_mono_items(tcx, collector::MonoItemCollectionMode::Eager).0
tcx, {
collector::MonoItemCollectionMode::Eager
).0 {
match mono_item { match mono_item {
MonoItem::Fn(inst) => { MonoItem::Fn(inst) => {
let def_id = inst.def_id(); let def_id = inst.def_id();
@@ -221,7 +226,9 @@ impl CodegenBackend for CraneliftCodegenBackend {
let mut flags_builder = settings::builder(); let mut flags_builder = settings::builder();
flags_builder.enable("is_pic").unwrap(); flags_builder.enable("is_pic").unwrap();
let flags = settings::Flags::new(flags_builder); let flags = settings::Flags::new(flags_builder);
let isa = cranelift::codegen::isa::lookup(target_lexicon::Triple::host()).unwrap().finish(flags); let isa = cranelift::codegen::isa::lookup(target_lexicon::Triple::host())
.unwrap()
.finish(flags);
let mut module: Module<SimpleJITBackend> = Module::new(SimpleJITBuilder::new()); let mut module: Module<SimpleJITBackend> = Module::new(SimpleJITBuilder::new());
let mut context = Context::new(); let mut context = Context::new();
@@ -233,10 +240,8 @@ impl CodegenBackend for CraneliftCodegenBackend {
}; };
for mono_item in for mono_item in
collector::collect_crate_mono_items( collector::collect_crate_mono_items(tcx, collector::MonoItemCollectionMode::Eager).0
tcx, {
collector::MonoItemCollectionMode::Eager
).0 {
base::trans_mono_item(&mut cx, &mut context, mono_item) base::trans_mono_item(&mut cx, &mut context, mono_item)
} }
} }
@@ -249,11 +254,8 @@ impl CodegenBackend for CraneliftCodegenBackend {
tcx.sess.warn("Finalized everything"); tcx.sess.warn("Finalized everything");
for mono_item in for mono_item in
collector::collect_crate_mono_items( collector::collect_crate_mono_items(tcx, collector::MonoItemCollectionMode::Eager).0
tcx, {
collector::MonoItemCollectionMode::Eager
).0 {
let inst = match mono_item { let inst = match mono_item {
MonoItem::Fn(inst) => inst, MonoItem::Fn(inst) => inst,
_ => continue, _ => continue,
@@ -266,17 +268,21 @@ impl CodegenBackend for CraneliftCodegenBackend {
let fn_ty = inst.ty(tcx); let fn_ty = inst.ty(tcx);
let sig = cton_sig_from_fn_ty(tcx, fn_ty); let sig = cton_sig_from_fn_ty(tcx, fn_ty);
let def_path_based_names = ::rustc_mir::monomorphize::item::DefPathBasedNames::new(tcx, false, false); let def_path_based_names =
::rustc_mir::monomorphize::item::DefPathBasedNames::new(tcx, false, false);
let mut name = String::new(); let mut name = String::new();
def_path_based_names.push_instance_as_string(inst, &mut name); def_path_based_names.push_instance_as_string(inst, &mut name);
let func_id = module.declare_function(&name, Linkage::Import, &sig).unwrap(); let func_id = module
.declare_function(&name, Linkage::Import, &sig)
.unwrap();
let finalized_function: *const u8 = module.finalize_function(func_id); let finalized_function: *const u8 = module.finalize_function(func_id);
/*let f: extern "C" fn(&mut u32) = unsafe { ::std::mem::transmute(finalized_function) }; /*let f: extern "C" fn(&mut u32) = unsafe { ::std::mem::transmute(finalized_function) };
let mut res = 0u32; let mut res = 0u32;
f(&mut res); f(&mut res);
tcx.sess.warn(&format!("ret_42 returned {}", res));*/ tcx.sess.warn(&format!("ret_42 returned {}", res));*/
let f: extern "C" fn(&mut bool, &u8, bool) = unsafe { ::std::mem::transmute(finalized_function) }; let f: extern "C" fn(&mut bool, &u8, bool) =
unsafe { ::std::mem::transmute(finalized_function) };
let mut res = false; let mut res = false;
f(&mut res, &3, false); f(&mut res, &3, false);
tcx.sess.warn(&format!("option_unwrap_or returned {}", res)); tcx.sess.warn(&format!("option_unwrap_or returned {}", res));
@@ -290,9 +296,8 @@ impl CodegenBackend for CraneliftCodegenBackend {
isa, isa,
"some_file.o".to_string(), "some_file.o".to_string(),
FaerieTrapCollection::Disabled, FaerieTrapCollection::Disabled,
FaerieBuilder::default_libcall_names() FaerieBuilder::default_libcall_names(),
) ).unwrap(),
.unwrap()
); );
Box::new(OngoingCodegen { Box::new(OngoingCodegen {
@@ -309,30 +314,42 @@ impl CodegenBackend for CraneliftCodegenBackend {
_dep_graph: &DepGraph, _dep_graph: &DepGraph,
outputs: &OutputFilenames, outputs: &OutputFilenames,
) -> Result<(), CompileIncomplete> { ) -> Result<(), CompileIncomplete> {
let ongoing_codegen = *ongoing_codegen.downcast::<OngoingCodegen>() let ongoing_codegen = *ongoing_codegen
.downcast::<OngoingCodegen>()
.expect("Expected CraneliftCodegenBackend's OngoingCodegen, found Box<Any>"); .expect("Expected CraneliftCodegenBackend's OngoingCodegen, found Box<Any>");
let mut artifact = ongoing_codegen.product.artifact; let mut artifact = ongoing_codegen.product.artifact;
let metadata = ongoing_codegen.metadata; let metadata = ongoing_codegen.metadata;
artifact.declare_with( artifact
.declare_with(
".rustc.clif_metadata", ".rustc.clif_metadata",
faerie::artifact::Decl::Data { faerie::artifact::Decl::Data {
global: true, global: true,
writeable: false writeable: false,
}, },
metadata.clone(), metadata.clone(),
).unwrap(); ).unwrap();
for &crate_type in sess.opts.crate_types.iter() { for &crate_type in sess.opts.crate_types.iter() {
if crate_type != CrateType::CrateTypeRlib /*&& crate_type != CrateType::CrateTypeDylib*/ { if crate_type != CrateType::CrateTypeRlib
/*&& crate_type != CrateType::CrateTypeDylib*/
{
sess.fatal(&format!("Unsupported crate type: {:?}", crate_type)); sess.fatal(&format!("Unsupported crate type: {:?}", crate_type));
} }
let output_name = let output_name = out_filename(
out_filename(sess, crate_type, &outputs, &ongoing_codegen.crate_name.as_str()); sess,
crate_type,
&outputs,
&ongoing_codegen.crate_name.as_str(),
);
let file = File::create(&output_name).unwrap(); let file = File::create(&output_name).unwrap();
let mut builder = ar::Builder::new(file); let mut builder = ar::Builder::new(file);
builder.append(&ar::Header::new(b".rustc.clif_metadata".to_vec(), metadata.len() as u64), ::std::io::Cursor::new(metadata.clone())).unwrap(); builder
.append(
&ar::Header::new(b".rustc.clif_metadata".to_vec(), metadata.len() as u64),
::std::io::Cursor::new(metadata.clone()),
).unwrap();
//artifact.write(file).unwrap(); //artifact.write(file).unwrap();
} }