about summary refs log tree commit diff
path: root/src/comp
diff options
context:
space:
mode:
authorPatrick Walton <pcwalton@mimiga.net>2010-12-06 17:17:49 -0800
committerPatrick Walton <pcwalton@mimiga.net>2010-12-06 17:17:49 -0800
commit3f9d5dab5bd3e15eddbccbb97af30523cff17142 (patch)
treebed17beb0d5785517dd31fe97f979ca85b987b31 /src/comp
parenta1c7d1983670fb86f8ace78a255e15b0e753e791 (diff)
downloadrust-3f9d5dab5bd3e15eddbccbb97af30523cff17142.tar.gz
rust-3f9d5dab5bd3e15eddbccbb97af30523cff17142.zip
rustc: Run the verifier over LLVM modules before writing them out
Diffstat (limited to 'src/comp')
-rw-r--r--src/comp/lib/llvm.rs23
-rw-r--r--src/comp/middle/trans.rs13
2 files changed, 35 insertions, 1 deletions
diff --git a/src/comp/lib/llvm.rs b/src/comp/lib/llvm.rs
index 6063c3c653f..c5236725d6d 100644
--- a/src/comp/lib/llvm.rs
+++ b/src/comp/lib/llvm.rs
@@ -687,6 +687,16 @@ native mod llvm = llvm_lib {
     fn LLVMPreferredAlignmentOfType(TargetDataRef TD, TypeRef Ty) -> uint;
     /** Disposes target data. */
     fn LLVMDisposeTargetData(TargetDataRef TD);
+
+    /** Creates a pass manager. */
+    fn LLVMCreatePassManager() -> PassManagerRef;
+    /** Disposes a pass manager. */
+    fn LLVMDisposePassManager(PassManagerRef PM);
+    /** Runs a pass manager on a module. */
+    fn LLVMRunPassManager(PassManagerRef PM, ModuleRef M) -> Bool;
+
+    /** Adds a verification pass. */
+    fn LLVMAddVerifierPass(PassManagerRef PM);
 }
 
 /* Slightly more terse object-interface to LLVM's 'builder' functions. */
@@ -1209,6 +1219,19 @@ fn mk_target_data(str string_rep) -> target_data {
     ret rec(lltd=lltd, dtor=target_data_dtor(lltd));
 }
 
+/* Memory-managed interface to pass managers. */
+
+obj pass_manager_dtor(PassManagerRef PM) {
+    drop { llvm.LLVMDisposePassManager(PM); }
+}
+
+type pass_manager = rec(PassManagerRef llpm, pass_manager_dtor dtor);
+
+fn mk_pass_manager() -> pass_manager {
+    auto llpm = llvm.LLVMCreatePassManager();
+    ret rec(llpm=llpm, dtor=pass_manager_dtor(llpm));
+}
+
 
 //
 // Local Variables:
diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs
index 9b6450cb9b8..6f3705e86d0 100644
--- a/src/comp/middle/trans.rs
+++ b/src/comp/middle/trans.rs
@@ -23,8 +23,9 @@ import lib.llvm.llvm;
 import lib.llvm.builder;
 import lib.llvm.target_data;
 import lib.llvm.type_handle;
-import lib.llvm.mk_type_handle;
+import lib.llvm.mk_pass_manager;
 import lib.llvm.mk_target_data;
+import lib.llvm.mk_type_handle;
 import lib.llvm.llvm.ModuleRef;
 import lib.llvm.llvm.ValueRef;
 import lib.llvm.llvm.TypeRef;
@@ -2245,6 +2246,14 @@ fn declare_intrinsics(ModuleRef llmod) -> hashmap[str,ValueRef] {
     ret intrinsics;
 }
 
+fn check_module(ModuleRef llmod) {
+    auto pm = mk_pass_manager();
+    llvm.LLVMAddVerifierPass(pm.llpm);
+    llvm.LLVMRunPassManager(pm.llpm, llmod);
+
+    // TODO: run the linter here also, once there are llvm-c bindings for it.
+}
+
 fn trans_crate(session.session sess, @ast.crate crate, str output) {
     auto llmod =
         llvm.LLVMModuleCreateWithNameInContext(_str.buf("rust_out"),
@@ -2302,6 +2311,8 @@ fn trans_crate(session.session sess, @ast.crate crate, str output) {
     trans_exit_task_glue(cx);
     trans_main_fn(cx, crate_constant(cx));
 
+    check_module(llmod);
+
     llvm.LLVMWriteBitcodeToFile(llmod, _str.buf(output));
     llvm.LLVMDisposeModule(llmod);
 }