]> git.lizzy.rs Git - rust.git/commitdiff
Merge pull request #24 from oli-obk/typesafe_fn_calls
authorScott Olson <scott@solson.me>
Wed, 15 Jun 2016 11:05:50 +0000 (05:05 -0600)
committerGitHub <noreply@github.com>
Wed, 15 Jun 2016 11:05:50 +0000 (05:05 -0600)
Typesafe fn calls

src/bin/miri.rs
src/interpreter/mod.rs
tests/compiletest.rs
tests/run-pass/main_fn.rs [new file with mode: 0644]
tests/run-pass/start_fn.rs [new file with mode: 0644]

index f1e9714ff39d13017c3283ee86f3bd12fb3850c7..8ec691dbbbc2777d84e633e8def353702e8195a5 100644 (file)
 use rustc::session::Session;
 use rustc_driver::{driver, CompilerCalls};
 use rustc::ty::{TyCtxt, subst};
-use rustc::mir::mir_map::MirMap;
-use rustc::mir::repr::Mir;
 use rustc::hir::def_id::DefId;
-use rustc::hir::{map, ItemFn, Item};
-use syntax::codemap::Span;
 
 struct MiriCompilerCalls;
 
@@ -40,15 +36,29 @@ fn build_controller(
 
             let tcx = state.tcx.unwrap();
             let mir_map = state.mir_map.unwrap();
-            let (span, mir, def_id) = get_main(tcx, mir_map);
-            println!("found `main` function at: {:?}", span);
 
+            let (node_id, span) = state.session.entry_fn.borrow().expect("no main or start function found");
+            debug!("found `main` function at: {:?}", span);
+
+            let mir = mir_map.map.get(&node_id).expect("no mir for main function");
+            let def_id = tcx.map.local_def_id(node_id);
             let mut ecx = EvalContext::new(tcx, mir_map);
             let substs = tcx.mk_substs(subst::Substs::empty());
             let return_ptr = ecx.alloc_ret_ptr(mir.return_ty, substs).expect("main function should not be diverging");
 
             ecx.push_stack_frame(def_id, mir.span, CachedMir::Ref(mir), substs, Some(return_ptr));
 
+            if mir.arg_decls.len() == 2 {
+                // start function
+                let ptr_size = ecx.memory().pointer_size;
+                let nargs = ecx.memory_mut().allocate(ptr_size);
+                ecx.memory_mut().write_usize(nargs, 0).unwrap();
+                let args = ecx.memory_mut().allocate(ptr_size);
+                ecx.memory_mut().write_usize(args, 0).unwrap();
+                ecx.frame_mut().locals[0] = nargs;
+                ecx.frame_mut().locals[1] = args;
+            }
+
             loop {
                 match step(&mut ecx) {
                     Ok(true) => {}
@@ -66,19 +76,6 @@ fn build_controller(
     }
 }
 
-fn get_main<'a, 'b, 'tcx: 'b>(tcx: TyCtxt<'a, 'tcx, 'tcx>, mir_map: &'b MirMap<'tcx>) -> (Span, &'b Mir<'tcx>, DefId) {
-    for (&id, mir) in &mir_map.map {
-        if let map::Node::NodeItem(&Item { name, span, ref node, .. }) = tcx.map.get(id) {
-            if let ItemFn(..) = *node {
-                if name.as_str() == "main" {
-                    return (span, mir, tcx.map.local_def_id(id));
-                }
-            }
-        }
-    }
-    panic!("no main function found");
-}
-
 fn report(tcx: TyCtxt, ecx: &EvalContext, e: EvalError) {
     let frame = ecx.stack().last().expect("stackframe was empty");
     let block = &frame.mir.basic_blocks()[frame.next_block];
index 4acefb91130a44ac4f2b1e3bed03b3b44de60e50..5b2428d20c8c87bf5c21c50e7aa10486b6aae4d1 100644 (file)
@@ -154,6 +154,10 @@ pub fn memory(&self) -> &Memory {
         &self.memory
     }
 
+    pub fn memory_mut(&mut self) -> &mut Memory<'tcx> {
+        &mut self.memory
+    }
+
     pub fn stack(&self) -> &[Frame] {
         &self.stack
     }
@@ -1376,7 +1380,7 @@ fn frame(&self) -> &Frame<'a, 'tcx> {
         self.stack.last().expect("no call frames exist")
     }
 
-    fn frame_mut(&mut self) -> &mut Frame<'a, 'tcx> {
+    pub fn frame_mut(&mut self) -> &mut Frame<'a, 'tcx> {
         self.stack.last_mut().expect("no call frames exist")
     }
 
index 0619c5a76561754d10e141bba37d3c6f029a486f..7ce9636fc05f07037bf28cb353dcc19fd3621136 100644 (file)
@@ -15,20 +15,23 @@ fn run_mode(mode: &'static str) {
             .expect("need to specify RUST_SYSROOT env var or use rustup or multirust")
             .to_owned(),
     };
-    let sysroot_flag = format!("--sysroot {} -Dwarnings", sysroot);
+    let flags = format!("--sysroot {} -Dwarnings", sysroot);
 
     // FIXME: read directories in sysroot/lib/rustlib and generate the test targets from that
     let targets = &["x86_64-unknown-linux-gnu", "i686-unknown-linux-gnu"];
 
     for &target in targets {
+        use std::io::Write;
+        let stderr = std::io::stderr();
+        write!(stderr.lock(), "running tests for target {}", target).unwrap();
         let mut config = compiletest::default_config();
-        config.host_rustcflags = Some(sysroot_flag.clone());
+        config.host_rustcflags = Some(flags.clone());
         config.mode = mode.parse().expect("Invalid mode");
         config.run_lib_path = format!("{}/lib/rustlib/{}/lib", sysroot, target);
         config.rustc_path = "target/debug/miri".into();
         config.src_base = PathBuf::from(format!("tests/{}", mode));
         config.target = target.to_owned();
-        config.target_rustcflags = Some(sysroot_flag.clone());
+        config.target_rustcflags = Some(flags.clone());
         compiletest::run_tests(&config);
     }
 }
diff --git a/tests/run-pass/main_fn.rs b/tests/run-pass/main_fn.rs
new file mode 100644 (file)
index 0000000..91d183e
--- /dev/null
@@ -0,0 +1,5 @@
+#![feature(main)]
+
+#[main]
+fn foo() {
+}
diff --git a/tests/run-pass/start_fn.rs b/tests/run-pass/start_fn.rs
new file mode 100644 (file)
index 0000000..8b884e2
--- /dev/null
@@ -0,0 +1,9 @@
+#![feature(start)]
+
+#[start]
+fn foo(nargs: isize, args: *const *const u8) -> isize {
+    if nargs > 0 {
+        assert!(unsafe{*args} as usize != 0);
+    }
+    0
+}