ebb_map,
local_map: HashMap::new(),
comments: HashMap::new(),
+ constants: &mut cx.constants,
};
let fx = &mut fx;
(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),
(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
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::*;
return None;
}
}
- TypeVariants::TyParam(_) => bug!("{:?}", ty),
+ TypeVariants::TyParam(_) => bug!("{:?}: {:?}", ty, ty.sty),
_ => return None,
})
}
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();
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> {
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
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);
}
-}
\ No newline at end of file
+ *fx.constants.get(&alloc_id).unwrap()
+}
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::{
};
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;
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(());
tcx,
module: &mut module,
def_id_fn_id_map: &mut def_id_fn_id_map,
+ constants: HashMap::new(),
};
for mono_item in