[WIP] Add arbitrary constant support

This commit is contained in:
bjorn3 2018-07-16 15:13:37 +02:00
parent ee45f7d6bc
commit af3234cfd7
4 changed files with 86 additions and 8 deletions

View File

@ -85,6 +85,7 @@ pub fn trans_fn<'a, 'tcx: 'a>(cx: &mut CodegenCx<'a, 'tcx, CurrentBackend>, f: &
ebb_map,
local_map: HashMap::new(),
comments: HashMap::new(),
constants: &mut cx.constants,
};
let fx = &mut fx;
@ -458,6 +459,8 @@ fn trans_int_binop<'a, 'tcx: 'a>(fx: &mut FunctionCx<'a, 'tcx>, bin_op: BinOp, l
(BinOp::Shl, _) => fx.bcx.ins().ishl(lhs, rhs),
(BinOp::Shr, false) => fx.bcx.ins().ushr(lhs, rhs),
(BinOp::Shr, true) => fx.bcx.ins().sshr(lhs, rhs),
// TODO: cast b1 to u8
(BinOp::Eq, _) => fx.bcx.ins().icmp(IntCC::Equal , lhs, rhs),
(BinOp::Lt, false) => fx.bcx.ins().icmp(IntCC::UnsignedLessThan , lhs, rhs),
(BinOp::Lt, true) => fx.bcx.ins().icmp(IntCC::SignedLessThan , lhs, rhs),
@ -468,6 +471,7 @@ fn trans_int_binop<'a, 'tcx: 'a>(fx: &mut FunctionCx<'a, 'tcx>, bin_op: BinOp, l
(BinOp::Ge, true) => fx.bcx.ins().icmp(IntCC::SignedGreaterThanOrEqual , lhs, rhs),
(BinOp::Gt, false) => fx.bcx.ins().icmp(IntCC::UnsignedGreaterThan , lhs, rhs),
(BinOp::Gt, true) => fx.bcx.ins().icmp(IntCC::SignedGreaterThan , lhs, rhs),
(BinOp::Offset, _) => bug!("bin op Offset on non ptr lhs: {:?} rhs: {:?}", lhs, rhs),
};
// TODO: return correct value for checked binops

View File

@ -6,7 +6,7 @@ use std::fmt;
use syntax::ast::{IntTy, UintTy};
use self::rustc_target::spec::{HasTargetSpec, Target};
use cranelift_module::{Module, Linkage, FuncId};
use cranelift_module::{Module, Linkage, FuncId, DataId};
use prelude::*;
@ -56,7 +56,7 @@ fn cton_type_from_ty<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ty: Ty<'tcx>) ->
return None;
}
}
TypeVariants::TyParam(_) => bug!("{:?}", ty),
TypeVariants::TyParam(_) => bug!("{:?}: {:?}", ty, ty.sty),
_ => return None,
})
}
@ -288,6 +288,7 @@ pub fn cton_sig_from_instance<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>, inst: I
pub fn cton_sig_from_mono_fn_sig<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>, sig: PolyFnSig<'tcx>) -> Signature {
// TODO: monomorphize signature
// TODO: this should likely not use skip_binder()
let sig = sig.skip_binder();
let inputs = sig.inputs();
@ -334,6 +335,7 @@ pub struct FunctionCx<'a, 'tcx: 'a> {
pub ebb_map: HashMap<BasicBlock, Ebb>,
pub local_map: HashMap<Local, CPlace<'tcx>>,
pub comments: HashMap<Inst, String>,
pub constants: &'a mut HashMap<AllocId, DataId>,
}
impl<'a, 'tcx: 'a> fmt::Debug for FunctionCx<'a, 'tcx> {

View File

@ -1,8 +1,9 @@
use prelude::*;
use rustc::mir::interpret::{GlobalId, AllocId, read_target_uint};
use rustc_mir::interpret::{CompileTimeEvaluator, Memory, MemoryKind};
use cranelift_module::*;
pub fn trans_constant<'a, 'tcx: 'a>(fx: &mut FunctionCx<'a, 'tcx>, const_: &Constant<'tcx>) -> CValue<'tcx> {
use rustc::mir::interpret::{Scalar, ConstValue, GlobalId};
let value = match const_.literal {
Literal::Value { value } => value,
Literal::Promoted { index } => fx
@ -32,6 +33,74 @@ pub fn trans_constant<'a, 'tcx: 'a>(fx: &mut FunctionCx<'a, 'tcx>, const_: &Cons
let func_ref = fx.get_function_ref(Instance::new(def_id, substs));
CValue::Func(func_ref, fx.layout_of(const_.ty))
}
_ => unimplemented!("value {:?} ty {:?}", value, const_.ty),
_ => {
let mut memory = Memory::<CompileTimeEvaluator>::new(fx.tcx.at(DUMMY_SP), ());
let alloc = fx.tcx.const_value_to_allocation(value);
//println!("const value: {:?} allocation: {:?}", value, alloc);
let alloc_id = memory.allocate_value(alloc.clone(), MemoryKind::Stack).unwrap();
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);
// TODO: does global_value return a ptr of a val?
let global_ptr = fx.bcx.ins().global_value(types::I64, local_data_id);
CValue::ByRef(global_ptr, layout)
}
}
}
}
// 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) {
use std::collections::hash_map::Entry;
match fx.constants.entry(alloc_id) {
Entry::Occupied(mut occ) => {
(*occ.get_mut(), false)
}
Entry::Vacant(vac) => {
let data_id = fx.module.declare_data(&alloc_id.0.to_string(), Linkage::Local, false).unwrap();
todo.insert(alloc_id, data_id);
vac.insert(data_id);
(data_id, true)
}
}
}
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) {
return *data_id;
}
let mut todo = HashMap::new();
let mut done = HashSet::new();
define_global_for_alloc_id(fx, alloc_id, &mut todo);
while let Some((alloc_id, data_id)) = { let next = todo.drain().next(); next } {
println!("cur: {:?}:{:?} todo: {:?} done: {:?}", alloc_id, data_id, todo, done);
let alloc = memory.get(alloc_id).unwrap();
let mut data_ctx = DataContext::new();
data_ctx.define(alloc.bytes.to_vec().into_boxed_slice(), Writability::Readonly);
for &(offset, reloc) in alloc.relocations.iter() {
let data_id = define_global_for_alloc_id(fx, reloc, &mut todo).0;
let reloc_offset = {
let endianness = memory.endianness();
let offset = offset.bytes() as usize;
let ptr_size = fx.tcx.data_layout.pointer_size;
let bytes = &alloc.bytes[offset..offset + ptr_size.bytes() as usize];
read_target_uint(endianness, bytes).unwrap()
};
// TODO: is this a correct usage of the api
let global_value = fx.module.declare_data_in_data(data_id, &mut data_ctx);
data_ctx.write_data_addr(reloc_offset as u32, global_value, 0);
}
fx.module.define_data(data_id, &data_ctx).unwrap();
done.insert(data_id);
}
for data_id in done.drain() {
fx.module.finalize_data(data_id);
}
*fx.constants.get(&alloc_id).unwrap()
}

View File

@ -40,12 +40,13 @@ mod pretty_clif;
mod prelude {
pub use std::any::Any;
pub use std::collections::HashMap;
pub use std::collections::{HashMap, HashSet};
pub use syntax::codemap::DUMMY_SP;
pub use rustc::hir::def_id::{DefId, LOCAL_CRATE};
pub use rustc::mir;
pub use rustc::mir::*;
pub use rustc::mir::interpret::AllocId;
pub use rustc::session::Session;
pub use rustc::ty::layout::{self, LayoutOf, TyLayout, Size};
pub use rustc::ty::{
@ -60,7 +61,7 @@ mod prelude {
};
pub use cranelift::codegen::Context;
pub use cranelift::prelude::*;
pub use cranelift_module::{Module, Backend, FuncId, Linkage};
pub use cranelift_module::{Module, Backend, FuncId, DataId, Linkage};
pub use cranelift_simplejit::{SimpleJITBuilder, SimpleJITBackend};
pub use common::Variable;
@ -75,6 +76,7 @@ pub struct CodegenCx<'a, 'tcx: 'a, B: Backend + 'a> {
pub tcx: TyCtxt<'a, 'tcx, 'tcx>,
pub module: &'a mut Module<B>,
pub def_id_fn_id_map: &'a mut HashMap<Instance<'tcx>, FuncId>,
pub constants: HashMap<AllocId, DataId>,
}
struct CraneliftCodegenBackend(());
@ -176,6 +178,7 @@ impl CodegenBackend for CraneliftCodegenBackend {
tcx,
module: &mut module,
def_id_fn_id_map: &mut def_id_fn_id_map,
constants: HashMap::new(),
};
for mono_item in