]> git.lizzy.rs Git - rust.git/commitdiff
[WIP] Add arbitrary constant support
authorbjorn3 <bjorn3@users.noreply.github.com>
Mon, 16 Jul 2018 13:13:37 +0000 (15:13 +0200)
committerbjorn3 <bjorn3@users.noreply.github.com>
Mon, 16 Jul 2018 13:13:37 +0000 (15:13 +0200)
src/base.rs
src/common.rs
src/constant.rs
src/lib.rs

index c7f07542b0e84c3c551275426a53b701bcb0e35a..5301656cf2418a63d81c8b0cc027822495127d6a 100644 (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
index 83f992380c0c51036ab3e2f175266734d1aba8c0..5e3433410ee2dcdf17169cba656baf63cfa80d2b 100644 (file)
@@ -6,7 +6,7 @@
 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> {
index ab3e4376a820fee8c4afa10231621b9cc140d52f..a4f5032fb322fe439fad33d1f30e06197aa8e750 100644 (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);
     }
-}
\ No newline at end of file
+    *fx.constants.get(&alloc_id).unwrap()
+}
index e8cab41d81074e38ad5797c21d00c567f94b20c9..dc640838b6b846d58066e55efb87d18b5b534428 100644 (file)
 
 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 @@ fn codegen_crate<'a, 'tcx>(
                 tcx,
                 module: &mut module,
                 def_id_fn_id_map: &mut def_id_fn_id_map,
+                constants: HashMap::new(),
             };
 
             for mono_item in