import syntax::ast;
import syntax::print::pprust;
import lib::llvm::{ModuleRef, mk_pass_manager, mk_target_data, True, False,
- FileType};
+ PassManagerRef, FileType};
import metadata::filesearch;
import syntax::ast_map::{path, path_mod, path_name};
import io::{Writer, WriterUtil};
}
}
+#[cfg(stage0)]
+mod jit {
+ fn exec(_sess: session,
+ _pm: PassManagerRef,
+ _m: ModuleRef,
+ _opt: c_int,
+ _stacks: bool) {
+ fail
+ }
+}
+
+#[cfg(stage1)]
+#[cfg(stage2)]
+#[cfg(stage3)]
+mod jit {
+ #[nolink]
+ #[abi = "rust-intrinsic"]
+ extern mod rusti {
+ fn morestack_addr() -> *();
+ }
+
+ struct Closure {
+ code: *();
+ env: *();
+ }
+
+ fn exec(sess: session,
+ pm: PassManagerRef,
+ m: ModuleRef,
+ opt: c_int,
+ stacks: bool) unsafe {
+ let ptr = llvm::LLVMRustJIT(rusti::morestack_addr(), pm, m, opt, stacks);
+
+ if ptr::is_null(ptr) {
+ llvm_err(sess, ~"Could not JIT");
+ } else {
+ let bin = match os::self_exe_path() {
+ Some(path) => path.to_str(),
+ _ => ~"rustc"
+ };
+ let closure = Closure {
+ code: ptr,
+ env: ptr::null()
+ };
+ let func: fn(~[~str]) = unsafe::transmute(closure);
+
+ func(~[bin]);
+ }
+ }
+}
+
mod write {
fn is_object_or_assembly_or_exe(ot: output_type) -> bool {
if ot == output_type_assembly || ot == output_type_object ||
});
}*/
- if !llvm::LLVMRustJIT(pm.llpm,
- llmod,
- CodeGenOptLevel,
- true) {
- llvm_err(sess, ~"Could not JIT");
- }
+ jit::exec(sess, pm.llpm, llmod, CodeGenOptLevel, true);
if sess.time_llvm_passes() {
llvm::LLVMRustPrintPassTimings();
#include <unistd.h>
#endif
-// Does this need to be done, or can it be made to resolve from the main program?
-extern "C" void __morestack(void *args, void *fn_ptr, uintptr_t stack_ptr);
-
using namespace llvm;
static const char *LLVMRustError;
// that rustllvm doesn't actually link to and it's pointless to put target info
// into the registry that Rust can not generate machine code for.
-#define INITIALIZE_TARGETS() LLVMInitializeX86TargetInfo(); \
- LLVMInitializeX86Target(); \
- LLVMInitializeX86TargetMC(); \
- LLVMInitializeX86AsmPrinter(); \
- LLVMInitializeX86AsmParser();
+void LLVMRustInitializeTargets() {
+ LLVMInitializeX86TargetInfo();
+ LLVMInitializeX86Target();
+ LLVMInitializeX86TargetMC();
+ LLVMInitializeX86AsmPrinter();
+ LLVMInitializeX86AsmParser();
+}
extern "C" bool
LLVMRustLoadLibrary(const char* file) {
return true;
}
-ExecutionEngine* EE;
-
// Custom memory manager for MCJITting. It needs special features
// that the generic JIT memory manager doesn't entail. Based on
// code from LLI, change where needed for Rust.
SmallVector<sys::MemoryBlock, 16> AllocatedDataMem;
SmallVector<sys::MemoryBlock, 16> AllocatedCodeMem;
SmallVector<sys::MemoryBlock, 16> FreeCodeMem;
+ void* __morestack;
- RustMCJITMemoryManager() { }
+ RustMCJITMemoryManager(void* sym) : __morestack(sym) { }
~RustMCJITMemoryManager();
virtual uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment,
if (Name == "mknod") return (void*)(intptr_t)&mknod;
#endif
- if (Name == "__morestack") return (void*)(intptr_t)&__morestack;
+ if (Name == "__morestack") return &__morestack;
const char *NameStr = Name.c_str();
void *Ptr = sys::DynamicLibrary::SearchForAddressOfSymbol(NameStr);
free(AllocatedDataMem[i].base());
}
-extern "C" bool
-LLVMRustJIT(LLVMPassManagerRef PMR,
+extern "C" void*
+LLVMRustJIT(void* __morestack,
+ LLVMPassManagerRef PMR,
LLVMModuleRef M,
CodeGenOpt::Level OptLevel,
bool EnableSegmentedStacks) {
- INITIALIZE_TARGETS();
InitializeNativeTarget();
InitializeNativeTargetAsmPrinter();
PM->add(createInstructionCombiningPass());
PM->add(createReassociatePass());
PM->add(createGVNPass());
- PM->add(createPromoteMemoryToRegisterPass());
PM->add(createCFGSimplificationPass());
PM->add(createFunctionInliningPass());
+ PM->add(createPromoteMemoryToRegisterPass());
PM->run(*unwrap(M));
- RustMCJITMemoryManager* MM = new RustMCJITMemoryManager();
- EE = EngineBuilder(unwrap(M))
+ RustMCJITMemoryManager* MM = new RustMCJITMemoryManager(__morestack);
+ ExecutionEngine* EE = EngineBuilder(unwrap(M))
.setTargetOptions(Options)
.setJITMemoryManager(MM)
.setOptLevel(OptLevel)
.setUseMCJIT(true)
+ .setAllocateGVsWithCode(false)
.create();
if(!EE || Err != "") {
LLVMRustError = Err.c_str();
- return false;
+ return 0;
}
MM->invalidateInstructionCache();
- Function* func = EE->FindFunctionNamed("main");
+ Function* func = EE->FindFunctionNamed("_rust_main");
if(!func || Err != "") {
LLVMRustError = Err.c_str();
- return false;
+ return 0;
}
- typedef int (*Entry)(int, int);
- Entry entry = (Entry) EE->getPointerToFunction(func);
-
+ void* entry = EE->getPointerToFunction(func);
assert(entry);
- entry(0, 0);
- return true;
+ return entry;
}
extern "C" bool
CodeGenOpt::Level OptLevel,
bool EnableSegmentedStacks) {
- INITIALIZE_TARGETS();
+ LLVMRustInitializeTargets();
TargetOptions Options;
Options.NoFramePointerElim = true;