From c7e7e1fe0fa8468b3cd8bc7db7d0332d7257b74e Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Fri, 22 Jun 2018 19:18:53 +0200 Subject: [PATCH] Split common utils out of base.rs --- src/base.rs | 237 -------------------------------------------------- src/common.rs | 232 ++++++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 16 ++++ 3 files changed, 248 insertions(+), 237 deletions(-) create mode 100644 src/common.rs diff --git a/src/base.rs b/src/base.rs index 7d18ad98572..0b9f1253c91 100644 --- a/src/base.rs +++ b/src/base.rs @@ -1,15 +1,5 @@ -use syntax::ast::{IntTy, UintTy}; use rustc_mir::monomorphize::MonoItem; -use cretonne::prelude::*; -use cretonne::codegen::Context; -use cretonne::codegen::ir::{ - ExternalName, - FuncRef, - StackSlot, - function::Function, -}; - use cretonne_module::{Module, Backend, FuncId, Linkage}; use cretonne_simplejit::{SimpleJITBuilder, SimpleJITBackend}; @@ -18,142 +8,6 @@ use std::collections::HashMap; use prelude::*; -#[derive(Debug, Copy, Clone, Eq, PartialEq)] -struct Variable(Local); - -type CurrentBackend = SimpleJITBackend; - -impl EntityRef for Variable { - fn new(u: usize) -> Self { - Variable(Local::new(u)) - } - - fn index(self) -> usize { - self.0.index() - } -} - -// FIXME(cretonne) fix load.i8 -fn load_workaround(fx: &mut FunctionCx, ty: Type, addr: Value, offset: i32) -> Value { - use cretonne::codegen::ir::types::*; - match ty { - I8 => fx.bcx.ins().uload8(I32, MemFlags::new(), addr, offset), - I16 => fx.bcx.ins().uload16(I32, MemFlags::new(), addr, offset), - // I32 and I64 work - _ => fx.bcx.ins().load(ty, MemFlags::new(), addr, offset), - } -} - -// FIXME(cretonne) fix store.i8 -fn store_workaround(fx: &mut FunctionCx, ty: Type, addr: Value, val: Value, offset: i32) { - use cretonne::codegen::ir::types::*; - match ty { - I8 => fx.bcx.ins().istore8(MemFlags::new(), val, addr, offset), - I16 => fx.bcx.ins().istore16(MemFlags::new(), val, addr, offset), - // I32 and I64 work - _ => fx.bcx.ins().store(MemFlags::new(), val, addr, offset), - }; -} - -#[derive(Copy, Clone)] -enum CValue { - ByRef(Value), - ByVal(Value), - Func(FuncRef), -} - -impl CValue { - fn force_stack<'a, 'tcx: 'a>(self, fx: &mut FunctionCx<'a, 'tcx>, ty: Ty<'tcx>) -> Value { - match self { - CValue::ByRef(value) => value, - CValue::ByVal(value) => { - let layout = fx.tcx.layout_of(ParamEnv::empty().and(ty)).unwrap(); - let stack_slot = fx.bcx.create_stack_slot(StackSlotData { - kind: StackSlotKind::ExplicitSlot, - size: layout.size.bytes() as u32, - offset: None, - }); - fx.bcx.ins().stack_store(value, stack_slot, 0); - fx.bcx.ins().stack_addr(types::I64, stack_slot, 0) - } - CValue::Func(func) => { - let func = fx.bcx.ins().func_addr(types::I64, func); - CValue::ByVal(func).force_stack(fx, ty) - } - } - } - - fn load_value<'a, 'tcx: 'a>(self, fx: &mut FunctionCx<'a, 'tcx>, ty: Ty<'tcx>) -> Value { - match self { - CValue::ByRef(value) => { - let cton_ty = cton_type_from_ty(ty).unwrap(); - load_workaround(fx, cton_ty, value, 0) - } - CValue::ByVal(value) => value, - CValue::Func(func) => { - fx.bcx.ins().func_addr(types::I64, func) - } - } - } - - fn expect_byref(self) -> Value { - match self { - CValue::ByRef(value) => value, - CValue::ByVal(_) => bug!("Expected CValue::ByRef, found CValue::ByVal"), - CValue::Func(_) => bug!("Expected CValue::ByRef, found CValue::Func"), - } - } -} - -#[derive(Copy, Clone)] -enum CPlace { - Var(Variable), - Addr(Value), -} - -impl<'a, 'tcx: 'a> CPlace { - fn from_stack_slot(fx: &mut FunctionCx<'a, 'tcx>, stack_slot: StackSlot) -> CPlace { - CPlace::Addr(fx.bcx.ins().stack_addr(types::I64, stack_slot, 0)) - } - - fn to_cvalue(self, fx: &mut FunctionCx<'a, 'tcx>) -> CValue { - match self { - CPlace::Var(var) => CValue::ByVal(fx.bcx.use_var(var)), - CPlace::Addr(addr) => CValue::ByRef(addr), - } - } - - fn expect_addr(self) -> Value { - match self { - CPlace::Addr(addr) => addr, - CPlace::Var(_) => bug!("Expected CPlace::Addr, found CPlace::Var"), - } - } - - fn write_cvalue(self, fx: &mut FunctionCx<'a, 'tcx>, from: CValue, ty: Ty<'tcx>) { - let layout = fx.tcx.layout_of(ParamEnv::reveal_all().and(ty)).unwrap(); - let size = layout.size.bytes() as i32; - match self { - CPlace::Var(var) => { - let data = from.load_value(fx, ty); - fx.bcx.def_var(var, data) - }, - CPlace::Addr(addr) => { - if let Some(cton_ty) = cton_type_from_ty(ty) { - let data = from.load_value(fx, ty); - store_workaround(fx, cton_ty, addr, data, 0); - } else { - for i in 0..size { - let from = from.expect_byref(); - let byte = load_workaround(fx, types::I8, from, i); - store_workaround(fx, types::I8, addr, byte, i); - } - } - } - } - } -} - pub fn trans_crate<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Box { let link_meta = ::build_link_meta(tcx.crate_hash(LOCAL_CRATE)); let metadata = tcx.encode_metadata(&link_meta); @@ -249,36 +103,6 @@ struct CodegenCx<'a, 'tcx: 'a, B: Backend + 'a> { def_id_fn_id_map: &'a mut HashMap, FuncId>, } -struct FunctionCx<'a, 'tcx: 'a> { - tcx: TyCtxt<'a, 'tcx, 'tcx>, - module: &'a mut Module, - def_id_fn_id_map: &'a mut HashMap, FuncId>, - bcx: FunctionBuilder<'a, Variable>, - mir: &'tcx Mir<'tcx>, - ebb_map: HashMap, - local_map: HashMap, -} - -impl<'f, 'tcx> FunctionCx<'f, 'tcx> { - fn get_ebb(&self, bb: BasicBlock) -> Ebb { - *self.ebb_map.get(&bb).unwrap() - } - - fn get_local_place(&mut self, local: Local) -> CPlace { - *self.local_map.get(&local).unwrap() - } - - fn get_function_ref(&mut self, inst: Instance<'tcx>) -> FuncRef { - let tcx = self.tcx; - let module = &mut self.module; - let func_id = *self.def_id_fn_id_map.entry(inst).or_insert_with(|| { - let sig = cton_sig_from_instance(tcx, inst); - module.declare_function(&tcx.absolute_item_path_str(inst.def_id()), Linkage::Local, &sig).unwrap() - }); - module.declare_func_in_func(func_id, &mut self.bcx.func) - } -} - fn trans_fn<'a, 'tcx: 'a>(cx: &mut CodegenCx<'a, 'tcx, CurrentBackend>, f: &mut Function, def_id: DefId, substs: &Substs<'tcx>) { let mir = cx.tcx.optimized_mir(def_id); let mut func_ctx = FunctionBuilderContext::new(); @@ -553,64 +377,3 @@ fn trans_operand<'a, 'tcx>(fx: &mut FunctionCx<'a, 'tcx>, operand: &Operand<'tcx } } } - -fn ext_name_from_did(def_id: DefId) -> ExternalName { - ExternalName::user(def_id.krate.as_u32(), def_id.index.as_raw_u32()) -} - -fn cton_sig_from_fn_sig<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>, sig: PolyFnSig<'tcx>, substs: &Substs<'tcx>) -> Signature { - let sig = tcx.subst_and_normalize_erasing_regions(substs, ParamEnv::reveal_all(), &sig); - cton_sig_from_mono_fn_sig(sig) -} - -fn cton_sig_from_instance<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>, inst: Instance<'tcx>) -> Signature { - let fn_ty = inst.ty(tcx); - let sig = fn_ty.fn_sig(tcx); - cton_sig_from_mono_fn_sig(sig) -} - -fn cton_sig_from_mono_fn_sig<'a ,'tcx: 'a>(sig: PolyFnSig<'tcx>) -> Signature { - let sig = sig.skip_binder(); - let inputs = sig.inputs(); - let _output = sig.output(); - assert!(!sig.variadic, "Variadic function are not yet supported"); - let call_conv = match sig.abi { - _ => CallConv::SystemV, - }; - Signature { - params: Some(types::I64).into_iter() // First param is place to put return val - .chain(inputs.into_iter().map(|ty| cton_type_from_ty(ty).unwrap_or(types::I64))) - .map(AbiParam::new).collect(), - returns: vec![], - call_conv, - argument_bytes: None, - } -} - -fn cton_type_from_ty(ty: Ty) -> Option { - Some(match ty.sty { - TypeVariants::TyBool => types::I8, - TypeVariants::TyUint(size) => { - match size { - UintTy::U8 => types::I8, - UintTy::U16 => types::I16, - UintTy::U32 => types::I32, - UintTy::U64 => types::I64, - UintTy::U128 => unimplemented!(), - UintTy::Usize => unimplemented!(), - } - } - TypeVariants::TyInt(size) => { - match size { - IntTy::I8 => types::I8, - IntTy::I16 => types::I16, - IntTy::I32 => types::I32, - IntTy::I64 => types::I64, - IntTy::I128 => unimplemented!(), - IntTy::Isize => unimplemented!(), - } - } - TypeVariants::TyFnPtr(_) => types::I64, - _ => return None, - }) -} diff --git a/src/common.rs b/src/common.rs new file mode 100644 index 00000000000..34196c6fc59 --- /dev/null +++ b/src/common.rs @@ -0,0 +1,232 @@ +use syntax::ast::{IntTy, UintTy}; + +use cretonne_module::{Module, Linkage, FuncId}; + +use prelude::*; + +pub type CurrentBackend = ::cretonne_simplejit::SimpleJITBackend; + +#[derive(Debug, Copy, Clone, Eq, PartialEq)] +pub struct Variable(Local); + +impl EntityRef for Variable { + fn new(u: usize) -> Self { + Variable(Local::new(u)) + } + + fn index(self) -> usize { + self.0.index() + } +} + +pub fn cton_type_from_ty(ty: Ty) -> Option { + Some(match ty.sty { + TypeVariants::TyBool => types::I8, + TypeVariants::TyUint(size) => { + match size { + UintTy::U8 => types::I8, + UintTy::U16 => types::I16, + UintTy::U32 => types::I32, + UintTy::U64 => types::I64, + UintTy::U128 => unimplemented!(), + UintTy::Usize => unimplemented!(), + } + } + TypeVariants::TyInt(size) => { + match size { + IntTy::I8 => types::I8, + IntTy::I16 => types::I16, + IntTy::I32 => types::I32, + IntTy::I64 => types::I64, + IntTy::I128 => unimplemented!(), + IntTy::Isize => unimplemented!(), + } + } + TypeVariants::TyFnPtr(_) => types::I64, + _ => return None, + }) +} + +// FIXME(cretonne) fix load.i8 +fn load_workaround(fx: &mut FunctionCx, ty: Type, addr: Value, offset: i32) -> Value { + use cretonne::codegen::ir::types::*; + match ty { + I8 => fx.bcx.ins().uload8(I32, MemFlags::new(), addr, offset), + I16 => fx.bcx.ins().uload16(I32, MemFlags::new(), addr, offset), + // I32 and I64 work + _ => fx.bcx.ins().load(ty, MemFlags::new(), addr, offset), + } +} + +// FIXME(cretonne) fix store.i8 +fn store_workaround(fx: &mut FunctionCx, ty: Type, addr: Value, val: Value, offset: i32) { + use cretonne::codegen::ir::types::*; + match ty { + I8 => fx.bcx.ins().istore8(MemFlags::new(), val, addr, offset), + I16 => fx.bcx.ins().istore16(MemFlags::new(), val, addr, offset), + // I32 and I64 work + _ => fx.bcx.ins().store(MemFlags::new(), val, addr, offset), + }; +} + +#[derive(Copy, Clone)] +pub enum CValue { + ByRef(Value), + ByVal(Value), + Func(FuncRef), +} + +impl CValue { + pub fn force_stack<'a, 'tcx: 'a>(self, fx: &mut FunctionCx<'a, 'tcx>, ty: Ty<'tcx>) -> Value { + match self { + CValue::ByRef(value) => value, + CValue::ByVal(value) => { + let layout = fx.tcx.layout_of(ParamEnv::empty().and(ty)).unwrap(); + let stack_slot = fx.bcx.create_stack_slot(StackSlotData { + kind: StackSlotKind::ExplicitSlot, + size: layout.size.bytes() as u32, + offset: None, + }); + fx.bcx.ins().stack_store(value, stack_slot, 0); + fx.bcx.ins().stack_addr(types::I64, stack_slot, 0) + } + CValue::Func(func) => { + let func = fx.bcx.ins().func_addr(types::I64, func); + CValue::ByVal(func).force_stack(fx, ty) + } + } + } + + pub fn load_value<'a, 'tcx: 'a>(self, fx: &mut FunctionCx<'a, 'tcx>, ty: Ty<'tcx>) -> Value { + match self { + CValue::ByRef(value) => { + let cton_ty = cton_type_from_ty(ty).unwrap(); + load_workaround(fx, cton_ty, value, 0) + } + CValue::ByVal(value) => value, + CValue::Func(func) => { + fx.bcx.ins().func_addr(types::I64, func) + } + } + } + + pub fn expect_byref(self) -> Value { + match self { + CValue::ByRef(value) => value, + CValue::ByVal(_) => bug!("Expected CValue::ByRef, found CValue::ByVal"), + CValue::Func(_) => bug!("Expected CValue::ByRef, found CValue::Func"), + } + } +} + +#[derive(Copy, Clone)] +pub enum CPlace { + Var(Variable), + Addr(Value), +} + +impl<'a, 'tcx: 'a> CPlace { + pub fn from_stack_slot(fx: &mut FunctionCx<'a, 'tcx>, stack_slot: StackSlot) -> CPlace { + CPlace::Addr(fx.bcx.ins().stack_addr(types::I64, stack_slot, 0)) + } + + pub fn to_cvalue(self, fx: &mut FunctionCx<'a, 'tcx>) -> CValue { + match self { + CPlace::Var(var) => CValue::ByVal(fx.bcx.use_var(var)), + CPlace::Addr(addr) => CValue::ByRef(addr), + } + } + + pub fn expect_addr(self) -> Value { + match self { + CPlace::Addr(addr) => addr, + CPlace::Var(_) => bug!("Expected CPlace::Addr, found CPlace::Var"), + } + } + + pub fn write_cvalue(self, fx: &mut FunctionCx<'a, 'tcx>, from: CValue, ty: Ty<'tcx>) { + let layout = fx.tcx.layout_of(ParamEnv::reveal_all().and(ty)).unwrap(); + let size = layout.size.bytes() as i32; + match self { + CPlace::Var(var) => { + let data = from.load_value(fx, ty); + fx.bcx.def_var(var, data) + }, + CPlace::Addr(addr) => { + if let Some(cton_ty) = cton_type_from_ty(ty) { + let data = from.load_value(fx, ty); + store_workaround(fx, cton_ty, addr, data, 0); + } else { + for i in 0..size { + let from = from.expect_byref(); + let byte = load_workaround(fx, types::I8, from, i); + store_workaround(fx, types::I8, addr, byte, i); + } + } + } + } + } +} + +pub fn ext_name_from_did(def_id: DefId) -> ExternalName { + ExternalName::user(def_id.krate.as_u32(), def_id.index.as_raw_u32()) +} + +pub fn cton_sig_from_fn_sig<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>, sig: PolyFnSig<'tcx>, substs: &Substs<'tcx>) -> Signature { + let sig = tcx.subst_and_normalize_erasing_regions(substs, ParamEnv::reveal_all(), &sig); + cton_sig_from_mono_fn_sig(sig) +} + +pub fn cton_sig_from_instance<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>, inst: Instance<'tcx>) -> Signature { + let fn_ty = inst.ty(tcx); + let sig = fn_ty.fn_sig(tcx); + cton_sig_from_mono_fn_sig(sig) +} + +pub fn cton_sig_from_mono_fn_sig<'a ,'tcx: 'a>(sig: PolyFnSig<'tcx>) -> Signature { + let sig = sig.skip_binder(); + let inputs = sig.inputs(); + let _output = sig.output(); + assert!(!sig.variadic, "Variadic function are not yet supported"); + let call_conv = match sig.abi { + _ => CallConv::SystemV, + }; + Signature { + params: Some(types::I64).into_iter() // First param is place to put return val + .chain(inputs.into_iter().map(|ty| cton_type_from_ty(ty).unwrap_or(types::I64))) + .map(AbiParam::new).collect(), + returns: vec![], + call_conv, + argument_bytes: None, + } +} + +pub struct FunctionCx<'a, 'tcx: 'a> { + pub tcx: TyCtxt<'a, 'tcx, 'tcx>, + pub module: &'a mut Module, + pub def_id_fn_id_map: &'a mut HashMap, FuncId>, + pub bcx: FunctionBuilder<'a, Variable>, + pub mir: &'tcx Mir<'tcx>, + pub ebb_map: HashMap, + pub local_map: HashMap, +} + +impl<'f, 'tcx> FunctionCx<'f, 'tcx> { + pub fn get_ebb(&self, bb: BasicBlock) -> Ebb { + *self.ebb_map.get(&bb).unwrap() + } + + pub fn get_local_place(&mut self, local: Local) -> CPlace { + *self.local_map.get(&local).unwrap() + } + + pub fn get_function_ref(&mut self, inst: Instance<'tcx>) -> FuncRef { + let tcx = self.tcx; + let module = &mut self.module; + let func_id = *self.def_id_fn_id_map.entry(inst).or_insert_with(|| { + let sig = cton_sig_from_instance(tcx, inst); + module.declare_function(&tcx.absolute_item_path_str(inst.def_id()), Linkage::Local, &sig).unwrap() + }); + module.declare_func_in_func(func_id, &mut self.bcx.func) + } +} diff --git a/src/lib.rs b/src/lib.rs index a0aec6c3116..039fdbd8e61 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -33,8 +33,11 @@ use std::fs::File; use std::io::Write; mod base; +mod common; mod prelude { + pub use std::collections::HashMap; + pub use rustc::session::Session; pub use rustc::hir::def_id::{DefId, LOCAL_CRATE}; pub use rustc::ty::{TyCtxt, Ty, TypeVariants, Instance, InstanceDef, ParamEnv, FnSig, PolyFnSig, subst::Substs}; @@ -44,6 +47,19 @@ mod prelude { sync::Lrc, indexed_vec::Idx, }; + + pub use cretonne::prelude::*; + pub use cretonne::codegen::Context; + pub use cretonne::codegen::ir::{ + ExternalName, + FuncRef, + StackSlot, + function::Function, + }; + + + pub use common::*; + pub use common::Variable; } use prelude::*;