From 6b34ba242d7372b779bf50682b9401b61183828e Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Sun, 1 Dec 2013 14:37:15 -0800 Subject: [PATCH 1/2] Update LLVM and jettison jit support LLVM's JIT has been updated numerous times, and we haven't been tracking it at all. The existing LLVM glue code no longer compiles, and the JIT isn't used for anything currently. This also rebases out the FixedStackSegment support which we have added to LLVM. None of this is still in use by the compiler, and there's no need to keep this functionality around inside of LLVM. This is needed to unblock #10708 (where we're tripping an LLVM assertion). --- src/librustc/back/link.rs | 169 +++------------- src/librustc/driver/driver.rs | 7 - src/librustc/driver/session.rs | 28 ++- src/librustc/lib.rs | 4 - src/librustc/lib/llvm.rs | 12 -- src/llvm | 2 +- src/rustllvm/PassWrapper.cpp | 1 - src/rustllvm/RustWrapper.cpp | 278 +-------------------------- src/rustllvm/llvm-auto-clean-trigger | 2 +- src/rustllvm/rustllvm.def.in | 3 - 10 files changed, 43 insertions(+), 463 deletions(-) diff --git a/src/librustc/back/link.rs b/src/librustc/back/link.rs index 1c4b15f42e986..2bebadc2ef2bc 100644 --- a/src/librustc/back/link.rs +++ b/src/librustc/back/link.rs @@ -82,111 +82,8 @@ pub fn WriteOutputFile( } } -pub mod jit { - - use back::link::llvm_err; - use driver::session::Session; - use lib::llvm::llvm; - use lib::llvm::{ModuleRef, ContextRef, ExecutionEngineRef}; - - use std::c_str::ToCStr; - use std::cast; - use std::local_data; - use std::unstable::intrinsics; - - struct LLVMJITData { - ee: ExecutionEngineRef, - llcx: ContextRef - } - - pub trait Engine {} - impl Engine for LLVMJITData {} - - impl Drop for LLVMJITData { - fn drop(&mut self) { - unsafe { - llvm::LLVMDisposeExecutionEngine(self.ee); - llvm::LLVMContextDispose(self.llcx); - } - } - } - - pub fn exec(sess: Session, - c: ContextRef, - m: ModuleRef, - stacks: bool) { - unsafe { - let manager = llvm::LLVMRustPrepareJIT(intrinsics::morestack_addr()); - - // We need to tell JIT where to resolve all linked - // symbols from. The equivalent of -lstd, -lcore, etc. - // By default the JIT will resolve symbols from the extra and - // core linked into rustc. We don't want that, - // incase the user wants to use an older extra library. - - // We custom-build a JIT execution engine via some rust wrappers - // first. This wrappers takes ownership of the module passed in. - let ee = llvm::LLVMRustBuildJIT(manager, m, stacks); - if ee.is_null() { - llvm::LLVMContextDispose(c); - llvm_err(sess, ~"Could not create the JIT"); - } - - // Next, we need to get a handle on the _rust_main function by - // looking up it's corresponding ValueRef and then requesting that - // the execution engine compiles the function. - let fun = "_rust_main".with_c_str(|entry| { - llvm::LLVMGetNamedFunction(m, entry) - }); - if fun.is_null() { - llvm::LLVMDisposeExecutionEngine(ee); - llvm::LLVMContextDispose(c); - llvm_err(sess, ~"Could not find _rust_main in the JIT"); - } - - // Finally, once we have the pointer to the code, we can do some - // closure magic here to turn it straight into a callable rust - // closure - let code = llvm::LLVMGetPointerToGlobal(ee, fun); - assert!(!code.is_null()); - let func: extern "Rust" fn() = cast::transmute(code); - func(); - - // Currently there is no method of re-using the executing engine - // from LLVM in another call to the JIT. While this kinda defeats - // the purpose of having a JIT in the first place, there isn't - // actually much code currently which would re-use data between - // different invocations of this. Additionally, the compilation - // model currently isn't designed to support this scenario. - // - // We can't destroy the engine/context immediately here, however, - // because of annihilation. The JIT code contains drop glue for any - // types defined in the crate we just ran, and if any of those boxes - // are going to be dropped during annihilation, the drop glue must - // be run. Hence, we need to transfer ownership of this jit engine - // to the caller of this function. To be convenient for now, we - // shove it into TLS and have someone else remove it later on. - let data = ~LLVMJITData { ee: ee, llcx: c }; - set_engine(data as ~Engine); - } - } - - // The stage1 compiler won't work, but that doesn't really matter. TLS - // changed only very recently to allow storage of owned values. - local_data_key!(engine_key: ~Engine) - - fn set_engine(engine: ~Engine) { - local_data::set(engine_key, engine) - } - - pub fn consume_engine() -> Option<~Engine> { - local_data::pop(engine_key) - } -} - pub mod write { - use back::link::jit; use back::link::{WriteOutputFile, output_type}; use back::link::{output_type_assembly, output_type_bitcode}; use back::link::{output_type_exe, output_type_llvm_assembly}; @@ -307,48 +204,38 @@ pub mod write { }) } - if sess.opts.jit { - // If we are using JIT, go ahead and create and execute the - // engine now. JIT execution takes ownership of the module and - // context, so don't dispose - jit::exec(sess, llcx, llmod, true); - } else { - // Create a codegen-specific pass manager to emit the actual - // assembly or object files. This may not end up getting used, - // but we make it anyway for good measure. - let cpm = llvm::LLVMCreatePassManager(); - llvm::LLVMRustAddAnalysisPasses(tm, cpm, llmod); - llvm::LLVMRustAddLibraryInfo(cpm, llmod); - - match output_type { - output_type_none => {} - output_type_bitcode => { - output.with_c_str(|buf| { - llvm::LLVMWriteBitcodeToFile(llmod, buf); - }) - } - output_type_llvm_assembly => { - output.with_c_str(|output| { - llvm::LLVMRustPrintModule(cpm, llmod, output) - }) - } - output_type_assembly => { - WriteOutputFile(sess, tm, cpm, llmod, output, lib::llvm::AssemblyFile); - } - output_type_exe | output_type_object => { - WriteOutputFile(sess, tm, cpm, llmod, output, lib::llvm::ObjectFile); - } + // Create a codegen-specific pass manager to emit the actual + // assembly or object files. This may not end up getting used, + // but we make it anyway for good measure. + let cpm = llvm::LLVMCreatePassManager(); + llvm::LLVMRustAddAnalysisPasses(tm, cpm, llmod); + llvm::LLVMRustAddLibraryInfo(cpm, llmod); + + match output_type { + output_type_none => {} + output_type_bitcode => { + output.with_c_str(|buf| { + llvm::LLVMWriteBitcodeToFile(llmod, buf); + }) + } + output_type_llvm_assembly => { + output.with_c_str(|output| { + llvm::LLVMRustPrintModule(cpm, llmod, output) + }) + } + output_type_assembly => { + WriteOutputFile(sess, tm, cpm, llmod, output, lib::llvm::AssemblyFile); + } + output_type_exe | output_type_object => { + WriteOutputFile(sess, tm, cpm, llmod, output, lib::llvm::ObjectFile); } - - llvm::LLVMDisposePassManager(cpm); } + llvm::LLVMDisposePassManager(cpm); + llvm::LLVMRustDisposeTargetMachine(tm); - // the jit takes ownership of these two items - if !sess.opts.jit { - llvm::LLVMDisposeModule(llmod); - llvm::LLVMContextDispose(llcx); - } + llvm::LLVMDisposeModule(llmod); + llvm::LLVMContextDispose(llcx); if sess.time_llvm_passes() { llvm::LLVMRustPrintPassTimings(); } } } diff --git a/src/librustc/driver/driver.rs b/src/librustc/driver/driver.rs index 4559a1230bd14..63d6c60d2698d 100644 --- a/src/librustc/driver/driver.rs +++ b/src/librustc/driver/driver.rs @@ -419,11 +419,6 @@ pub fn stop_after_phase_5(sess: Session) -> bool { debug!("not building executable, returning early from compile_input"); return true; } - - if sess.opts.jit { - debug!("running JIT, returning early from compile_input"); - return true; - } return false; } @@ -751,7 +746,6 @@ pub fn build_session_options(binary: @str, } else { No } }; let gc = debugging_opts & session::gc != 0; - let jit = debugging_opts & session::jit != 0; let extra_debuginfo = debugging_opts & session::extra_debug_info != 0; let debuginfo = debugging_opts & session::debug_info != 0 || extra_debuginfo; @@ -802,7 +796,6 @@ pub fn build_session_options(binary: @str, extra_debuginfo: extra_debuginfo, lint_opts: lint_opts, save_temps: save_temps, - jit: jit, output_type: output_type, addl_lib_search_paths: @mut addl_lib_search_paths, ar: ar, diff --git a/src/librustc/driver/session.rs b/src/librustc/driver/session.rs index e45ea533f7937..2c41cf00e6b82 100644 --- a/src/librustc/driver/session.rs +++ b/src/librustc/driver/session.rs @@ -55,19 +55,18 @@ pub static count_type_sizes: uint = 1 << 14; pub static meta_stats: uint = 1 << 15; pub static no_opt: uint = 1 << 16; pub static gc: uint = 1 << 17; -pub static jit: uint = 1 << 18; -pub static debug_info: uint = 1 << 19; -pub static extra_debug_info: uint = 1 << 20; -pub static print_link_args: uint = 1 << 21; -pub static no_debug_borrows: uint = 1 << 22; -pub static lint_llvm: uint = 1 << 23; -pub static print_llvm_passes: uint = 1 << 24; -pub static no_vectorize_loops: uint = 1 << 25; -pub static no_vectorize_slp: uint = 1 << 26; -pub static no_prepopulate_passes: uint = 1 << 27; -pub static use_softfp: uint = 1 << 28; -pub static gen_crate_map: uint = 1 << 29; -pub static prefer_dynamic: uint = 1 << 30; +pub static debug_info: uint = 1 << 18; +pub static extra_debug_info: uint = 1 << 19; +pub static print_link_args: uint = 1 << 20; +pub static no_debug_borrows: uint = 1 << 21; +pub static lint_llvm: uint = 1 << 22; +pub static print_llvm_passes: uint = 1 << 23; +pub static no_vectorize_loops: uint = 1 << 24; +pub static no_vectorize_slp: uint = 1 << 25; +pub static no_prepopulate_passes: uint = 1 << 26; +pub static use_softfp: uint = 1 << 27; +pub static gen_crate_map: uint = 1 << 28; +pub static prefer_dynamic: uint = 1 << 29; pub fn debugging_opts_map() -> ~[(&'static str, &'static str, uint)] { ~[("verbose", "in general, enable more debug printouts", verbose), @@ -95,7 +94,6 @@ pub fn debugging_opts_map() -> ~[(&'static str, &'static str, uint)] { ("no-opt", "do not optimize, even if -O is passed", no_opt), ("print-link-args", "Print the arguments passed to the linker", print_link_args), ("gc", "Garbage collect shared data (experimental)", gc), - ("jit", "Execute using JIT (experimental)", jit), ("extra-debug-info", "Extra debugging info (experimental)", extra_debug_info), ("debug-info", "Produce debug info (experimental)", debug_info), @@ -146,7 +144,6 @@ pub struct options { extra_debuginfo: bool, lint_opts: ~[(lint::lint, lint::level)], save_temps: bool, - jit: bool, output_type: back::link::output_type, addl_lib_search_paths: @mut HashSet, // This is mutable for rustpkg, which // updates search paths based on the @@ -370,7 +367,6 @@ pub fn basic_options() -> @options { extra_debuginfo: false, lint_opts: ~[], save_temps: false, - jit: false, output_type: link::output_type_exe, addl_lib_search_paths: @mut HashSet::new(), ar: None, diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index 438dc03b76621..166e1414f6ea2 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -363,10 +363,6 @@ pub fn monitor(f: proc(@diagnostic::Emitter)) { let _finally = finally { ch: ch }; f(demitter); - - // Due reasons explain in #7732, if there was a jit execution context it - // must be consumed and passed along to our parent task. - back::link::jit::consume_engine() }) { result::Ok(_) => { /* fallthrough */ } result::Err(_) => { diff --git a/src/librustc/lib/llvm.rs b/src/librustc/lib/llvm.rs index a856c06997169..1e1444babf232 100644 --- a/src/librustc/lib/llvm.rs +++ b/src/librustc/lib/llvm.rs @@ -1441,18 +1441,6 @@ pub mod llvm { call. */ pub fn LLVMRustGetLastError() -> *c_char; - /** Prepare the JIT. Returns a memory manager that can load crates. */ - pub fn LLVMRustPrepareJIT(__morestack: *()) -> *(); - - /** Load a crate into the memory manager. */ - pub fn LLVMRustLoadCrate(MM: *(), Filename: *c_char) -> bool; - - /** Execute the JIT engine. */ - pub fn LLVMRustBuildJIT(MM: *(), - M: ModuleRef, - EnableSegmentedStacks: bool) - -> ExecutionEngineRef; - /// Print the pass timings since static dtors aren't picking them up. pub fn LLVMRustPrintPassTimings(); diff --git a/src/llvm b/src/llvm index c9ffab392a39e..9e85884132d27 160000 --- a/src/llvm +++ b/src/llvm @@ -1 +1 @@ -Subproject commit c9ffab392a39eb85f2f15ffc8d41e8c4f4397b8e +Subproject commit 9e85884132d277efeb507d0aeaa160ba201d054f diff --git a/src/rustllvm/PassWrapper.cpp b/src/rustllvm/PassWrapper.cpp index 8d0b447fa4a1e..0ae8991b2e740 100644 --- a/src/rustllvm/PassWrapper.cpp +++ b/src/rustllvm/PassWrapper.cpp @@ -81,7 +81,6 @@ LLVMRustCreateTargetMachine(const char *triple, TargetOptions Options; Options.NoFramePointerElim = true; Options.EnableSegmentedStacks = EnableSegmentedStacks; - Options.FixedStackSegmentSize = 2 * 1024 * 1024; // XXX: This is too big. Options.FloatABIType = (Trip.getEnvironment() == Triple::GNUEABIHF) ? FloatABI::Hard : FloatABI::Default; diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp index 0a148d334ab61..484cded314710 100644 --- a/src/rustllvm/RustWrapper.cpp +++ b/src/rustllvm/RustWrapper.cpp @@ -34,282 +34,6 @@ extern "C" const char *LLVMRustGetLastError(void) { return LLVMRustError; } -// 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. -class RustMCJITMemoryManager : public JITMemoryManager { -public: - SmallVector AllocatedDataMem; - SmallVector AllocatedCodeMem; - SmallVector FreeCodeMem; - void* __morestack; - DenseSet crates; - - RustMCJITMemoryManager(void* sym) : __morestack(sym) { } - ~RustMCJITMemoryManager(); - - bool loadCrate(const char*, std::string*); - - virtual uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment, - unsigned SectionID); - - virtual uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment, - unsigned SectionID, bool isReadOnly); - bool finalizeMemory(std::string *ErrMsg) { return false; } - - virtual bool applyPermissions(std::string *Str); - - virtual void *getPointerToNamedFunction(const std::string &Name, - bool AbortOnFailure = true); - - // Invalidate instruction cache for code sections. Some platforms with - // separate data cache and instruction cache require explicit cache flush, - // otherwise JIT code manipulations (like resolved relocations) will get to - // the data cache but not to the instruction cache. - virtual void invalidateInstructionCache(); - - // The MCJITMemoryManager doesn't use the following functions, so we don't - // need implement them. - virtual void setMemoryWritable() { - llvm_unreachable("Unimplemented call"); - } - virtual void setMemoryExecutable() { - llvm_unreachable("Unimplemented call"); - } - virtual void setPoisonMemory(bool poison) { - llvm_unreachable("Unimplemented call"); - } - virtual void AllocateGOT() { - llvm_unreachable("Unimplemented call"); - } - virtual uint8_t *getGOTBase() const { - llvm_unreachable("Unimplemented call"); - return 0; - } - virtual uint8_t *startFunctionBody(const Function *F, - uintptr_t &ActualSize){ - llvm_unreachable("Unimplemented call"); - return 0; - } - virtual uint8_t *allocateStub(const GlobalValue* F, unsigned StubSize, - unsigned Alignment) { - llvm_unreachable("Unimplemented call"); - return 0; - } - virtual void endFunctionBody(const Function *F, uint8_t *FunctionStart, - uint8_t *FunctionEnd) { - llvm_unreachable("Unimplemented call"); - } - virtual uint8_t *allocateSpace(intptr_t Size, unsigned Alignment) { - llvm_unreachable("Unimplemented call"); - return 0; - } - virtual uint8_t *allocateGlobal(uintptr_t Size, unsigned Alignment) { - llvm_unreachable("Unimplemented call"); - return 0; - } - virtual void deallocateFunctionBody(void *Body) { - llvm_unreachable("Unimplemented call"); - } - virtual uint8_t* startExceptionTable(const Function* F, - uintptr_t &ActualSize) { - llvm_unreachable("Unimplemented call"); - return 0; - } - virtual void endExceptionTable(const Function *F, uint8_t *TableStart, - uint8_t *TableEnd, uint8_t* FrameRegister) { - llvm_unreachable("Unimplemented call"); - } - virtual void deallocateExceptionTable(void *ET) { - llvm_unreachable("Unimplemented call"); - } -}; - -bool RustMCJITMemoryManager::loadCrate(const char* file, std::string* err) { - DynamicLibrary crate = DynamicLibrary::getPermanentLibrary(file, - err); - - if(crate.isValid()) { - crates.insert(&crate); - - return true; - } - - return false; -} - -uint8_t *RustMCJITMemoryManager::allocateDataSection(uintptr_t Size, - unsigned Alignment, - unsigned SectionID, - bool isReadOnly) { - if (!Alignment) - Alignment = 16; - uint8_t *Addr = (uint8_t*)calloc((Size + Alignment - 1)/Alignment, Alignment); - AllocatedDataMem.push_back(sys::MemoryBlock(Addr, Size)); - return Addr; -} - -bool RustMCJITMemoryManager::applyPermissions(std::string *Str) { - // Empty. - return true; -} - -uint8_t *RustMCJITMemoryManager::allocateCodeSection(uintptr_t Size, - unsigned Alignment, - unsigned SectionID) { - if (!Alignment) - Alignment = 16; - unsigned NeedAllocate = Alignment * ((Size + Alignment - 1)/Alignment + 1); - uintptr_t Addr = 0; - // Look in the list of free code memory regions and use a block there if one - // is available. - for (int i = 0, e = FreeCodeMem.size(); i != e; ++i) { - sys::MemoryBlock &MB = FreeCodeMem[i]; - if (MB.size() >= NeedAllocate) { - Addr = (uintptr_t)MB.base(); - uintptr_t EndOfBlock = Addr + MB.size(); - // Align the address. - Addr = (Addr + Alignment - 1) & ~(uintptr_t)(Alignment - 1); - // Store cutted free memory block. - FreeCodeMem[i] = sys::MemoryBlock((void*)(Addr + Size), - EndOfBlock - Addr - Size); - return (uint8_t*)Addr; - } - } - - // No pre-allocated free block was large enough. Allocate a new memory region. - sys::MemoryBlock MB = sys::Memory::AllocateRWX(NeedAllocate, 0, 0); - - AllocatedCodeMem.push_back(MB); - Addr = (uintptr_t)MB.base(); - uintptr_t EndOfBlock = Addr + MB.size(); - // Align the address. - Addr = (Addr + Alignment - 1) & ~(uintptr_t)(Alignment - 1); - // The AllocateRWX may allocate much more memory than we need. In this case, - // we store the unused memory as a free memory block. - unsigned FreeSize = EndOfBlock-Addr-Size; - if (FreeSize > 16) - FreeCodeMem.push_back(sys::MemoryBlock((void*)(Addr + Size), FreeSize)); - - // Return aligned address - return (uint8_t*)Addr; -} - -void RustMCJITMemoryManager::invalidateInstructionCache() { - for (int i = 0, e = AllocatedCodeMem.size(); i != e; ++i) - sys::Memory::InvalidateInstructionCache(AllocatedCodeMem[i].base(), - AllocatedCodeMem[i].size()); -} - -void *RustMCJITMemoryManager::getPointerToNamedFunction(const std::string &Name, - bool AbortOnFailure) { -#ifdef __linux__ - // Force the following functions to be linked in to anything that uses the - // JIT. This is a hack designed to work around the all-too-clever Glibc - // strategy of making these functions work differently when inlined vs. when - // not inlined, and hiding their real definitions in a separate archive file - // that the dynamic linker can't see. For more info, search for - // 'libc_nonshared.a' on Google, or read http://llvm.org/PR274. - if (Name == "stat") return (void*)(intptr_t)&stat; - if (Name == "fstat") return (void*)(intptr_t)&fstat; - if (Name == "lstat") return (void*)(intptr_t)&lstat; - if (Name == "stat64") return (void*)(intptr_t)&stat64; - if (Name == "fstat64") return (void*)(intptr_t)&fstat64; - if (Name == "lstat64") return (void*)(intptr_t)&lstat64; - if (Name == "atexit") return (void*)(intptr_t)&atexit; - if (Name == "mknod") return (void*)(intptr_t)&mknod; -#endif - - if (Name == "__morestack" || Name == "___morestack") return &__morestack; - - const char *NameStr = Name.c_str(); - - // Look through loaded crates and main for symbols. - - void *Ptr = sys::DynamicLibrary::SearchForAddressOfSymbol(NameStr); - if (Ptr) return Ptr; - - // If it wasn't found and if it starts with an underscore ('_') character, - // try again without the underscore. - if (NameStr[0] == '_') { - Ptr = sys::DynamicLibrary::SearchForAddressOfSymbol(NameStr+1); - if (Ptr) return Ptr; - } - - if (AbortOnFailure) - report_fatal_error("Program used external function '" + Name + - "' which could not be resolved!"); - return 0; -} - -RustMCJITMemoryManager::~RustMCJITMemoryManager() { - for (unsigned i = 0, e = AllocatedCodeMem.size(); i != e; ++i) - sys::Memory::ReleaseRWX(AllocatedCodeMem[i]); - for (unsigned i = 0, e = AllocatedDataMem.size(); i != e; ++i) - free(AllocatedDataMem[i].base()); -} - -extern "C" void* -LLVMRustPrepareJIT(void* __morestack) { - // An execution engine will take ownership of this later - // and clean it up for us. - - return (void*) new RustMCJITMemoryManager(__morestack); -} - -extern "C" bool -LLVMRustLoadCrate(void* mem, const char* crate) { - RustMCJITMemoryManager* manager = (RustMCJITMemoryManager*) mem; - std::string Err; - - assert(manager); - - if(!manager->loadCrate(crate, &Err)) { - LLVMRustError = Err.c_str(); - return false; - } - - return true; -} - -extern "C" LLVMExecutionEngineRef -LLVMRustBuildJIT(void* mem, - LLVMModuleRef M, - bool EnableSegmentedStacks) { - - InitializeNativeTarget(); - InitializeNativeTargetAsmPrinter(); - InitializeNativeTargetAsmParser(); - - std::string Err; - TargetOptions Options; - Options.JITEmitDebugInfo = true; - Options.NoFramePointerElim = true; - Options.EnableSegmentedStacks = EnableSegmentedStacks; - RustMCJITMemoryManager* MM = (RustMCJITMemoryManager*) mem; - assert(MM); - - ExecutionEngine* EE = EngineBuilder(unwrap(M)) - .setErrorStr(&Err) - .setTargetOptions(Options) - .setJITMemoryManager(MM) - .setUseMCJIT(true) - .setAllocateGVsWithCode(false) - .create(); - - if(!EE || Err != "") { - LLVMRustError = Err.c_str(); - // The EngineBuilder only takes ownership of these two structures if the - // create() call is successful, but here it wasn't successful. - LLVMDisposeModule(M); - delete MM; - return NULL; - } - - MM->invalidateInstructionCache(); - return wrap(EE); -} - extern "C" void LLVMRustSetNormalizedTarget(LLVMModuleRef M, const char *triple) { unwrap(M)->setTargetTriple(Triple::normalize(triple)); @@ -566,7 +290,7 @@ extern "C" LLVMValueRef LLVMDIBuilderCreateStructType( unwrapDI(DerivedFrom), unwrapDI(Elements), RunTimeLang, - unwrapDI(VTableHolder), + unwrapDI(VTableHolder), UniqueId)); } diff --git a/src/rustllvm/llvm-auto-clean-trigger b/src/rustllvm/llvm-auto-clean-trigger index 01a5eaefa89b5..a72e585355480 100644 --- a/src/rustllvm/llvm-auto-clean-trigger +++ b/src/rustllvm/llvm-auto-clean-trigger @@ -1,4 +1,4 @@ # If this file is modified, then llvm will be forcibly cleaned and then rebuilt. # The actual contents of this file do not matter, but to trigger a change on the # build bots then the contents should be changed so git updates the mtime. -2013-09-23 +2013-11-19 diff --git a/src/rustllvm/rustllvm.def.in b/src/rustllvm/rustllvm.def.in index 069f29e909d4b..d8ec1c868408d 100644 --- a/src/rustllvm/rustllvm.def.in +++ b/src/rustllvm/rustllvm.def.in @@ -3,9 +3,6 @@ LLVMRustWriteOutputFile LLVMRustGetLastError LLVMRustConstSmallInt LLVMRustConstInt -LLVMRustLoadCrate -LLVMRustPrepareJIT -LLVMRustBuildJIT LLVMRustPrintPassTimings LLVMRustStartMultithreading LLVMCreateObjectFile From 17a951c7bf8c302a964a611c6ee1d46c461c50a3 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 28 Nov 2013 14:16:17 -0800 Subject: [PATCH 2/2] Remove unused upcalls The main one removed is rust_upcall_reset_stack_limit (continuation of #10156), and this also removes the upcall_trace function. The was hidden behind a `-Z trace` flag, but if you attempt to use this now you'll get a linker error because there is no implementation of the 'upcall_trace' function. Due to this no longer working, I decided to remove it entirely from the compiler (I'm also a little unsure on what it did in the first place). --- mk/llvm.mk | 2 + src/librustc/back/link.rs | 4 +- src/librustc/back/upcall.rs | 20 +------- src/librustc/driver/session.rs | 47 +++++++++--------- src/librustc/middle/trans/base.rs | 62 ++++++------------------ src/librustc/middle/trans/expr.rs | 8 --- src/librustc/middle/trans/macros.rs | 22 --------- src/librustc/middle/trans/write_guard.rs | 7 --- src/llvm | 2 +- src/rt/rust_upcall.c | 3 +- src/rustllvm/llvm-auto-clean-trigger | 2 +- 11 files changed, 46 insertions(+), 133 deletions(-) diff --git a/mk/llvm.mk b/mk/llvm.mk index efaa109c29e91..42b1a551805af 100644 --- a/mk/llvm.mk +++ b/mk/llvm.mk @@ -37,7 +37,9 @@ endif # dependencies. In these cases, commit a change that touches # the stamp in the source dir. $$(LLVM_STAMP_$(1)): $(S)src/rustllvm/llvm-auto-clean-trigger + @$$(call E, make: cleaning llvm) $(Q)$(MAKE) clean-llvm + @$$(call E, make: done cleaning llvm) touch $$@ endef diff --git a/src/librustc/back/link.rs b/src/librustc/back/link.rs index 2bebadc2ef2bc..1cb10d59e59c9 100644 --- a/src/librustc/back/link.rs +++ b/src/librustc/back/link.rs @@ -598,8 +598,8 @@ pub fn sanitize(s: &str) -> ~str { ',' => result.push_str("$C$"), // '.' doesn't occur in types and functions, so reuse it - // for ':' - ':' => result.push_char('.'), + // for ':' and '-' + '-' | ':' => result.push_char('.'), // These are legal symbols 'a' .. 'z' diff --git a/src/librustc/back/upcall.rs b/src/librustc/back/upcall.rs index 0ad53c4d49c1a..730ceba12c786 100644 --- a/src/librustc/back/upcall.rs +++ b/src/librustc/back/upcall.rs @@ -15,22 +15,10 @@ use middle::trans::type_::Type; use lib::llvm::{ModuleRef, ValueRef}; pub struct Upcalls { - trace: ValueRef, rust_personality: ValueRef, - reset_stack_limit: ValueRef } macro_rules! upcall ( - (fn $name:ident($($arg:expr),+) -> $ret:expr) => ({ - let fn_ty = Type::func([ $($arg),* ], &$ret); - base::decl_cdecl_fn(llmod, ~"upcall_" + stringify!($name), fn_ty) - }); - (nothrow fn $name:ident($($arg:expr),+) -> $ret:expr) => ({ - let fn_ty = Type::func([ $($arg),* ], &$ret); - let decl = base::decl_cdecl_fn(llmod, ~"upcall_" + stringify!($name), fn_ty); - base::set_no_unwind(decl); - decl - }); (nothrow fn $name:ident -> $ret:expr) => ({ let fn_ty = Type::func([], &$ret); let decl = base::decl_cdecl_fn(llmod, ~"upcall_" + stringify!($name), fn_ty); @@ -39,13 +27,9 @@ macro_rules! upcall ( }) ) -pub fn declare_upcalls(targ_cfg: @session::config, llmod: ModuleRef) -> @Upcalls { - let opaque_ptr = Type::i8().ptr_to(); - let int_ty = Type::int(targ_cfg.arch); - +pub fn declare_upcalls(_targ_cfg: @session::config, + llmod: ModuleRef) -> @Upcalls { @Upcalls { - trace: upcall!(fn trace(opaque_ptr, opaque_ptr, int_ty) -> Type::void()), rust_personality: upcall!(nothrow fn rust_personality -> Type::i32()), - reset_stack_limit: upcall!(nothrow fn reset_stack_limit -> Type::void()) } } diff --git a/src/librustc/driver/session.rs b/src/librustc/driver/session.rs index 2c41cf00e6b82..6a4755344eff4 100644 --- a/src/librustc/driver/session.rs +++ b/src/librustc/driver/session.rs @@ -44,29 +44,28 @@ pub static time_llvm_passes: uint = 1 << 3; pub static trans_stats: uint = 1 << 4; pub static asm_comments: uint = 1 << 5; pub static no_verify: uint = 1 << 6; -pub static trace: uint = 1 << 7; -pub static coherence: uint = 1 << 8; -pub static borrowck_stats: uint = 1 << 9; -pub static borrowck_note_pure: uint = 1 << 10; -pub static borrowck_note_loan: uint = 1 << 11; -pub static no_landing_pads: uint = 1 << 12; -pub static debug_llvm: uint = 1 << 13; -pub static count_type_sizes: uint = 1 << 14; -pub static meta_stats: uint = 1 << 15; -pub static no_opt: uint = 1 << 16; -pub static gc: uint = 1 << 17; -pub static debug_info: uint = 1 << 18; -pub static extra_debug_info: uint = 1 << 19; -pub static print_link_args: uint = 1 << 20; -pub static no_debug_borrows: uint = 1 << 21; -pub static lint_llvm: uint = 1 << 22; -pub static print_llvm_passes: uint = 1 << 23; -pub static no_vectorize_loops: uint = 1 << 24; -pub static no_vectorize_slp: uint = 1 << 25; -pub static no_prepopulate_passes: uint = 1 << 26; -pub static use_softfp: uint = 1 << 27; -pub static gen_crate_map: uint = 1 << 28; -pub static prefer_dynamic: uint = 1 << 29; +pub static coherence: uint = 1 << 7; +pub static borrowck_stats: uint = 1 << 8; +pub static borrowck_note_pure: uint = 1 << 9; +pub static borrowck_note_loan: uint = 1 << 10; +pub static no_landing_pads: uint = 1 << 11; +pub static debug_llvm: uint = 1 << 12; +pub static count_type_sizes: uint = 1 << 13; +pub static meta_stats: uint = 1 << 14; +pub static no_opt: uint = 1 << 15; +pub static gc: uint = 1 << 16; +pub static debug_info: uint = 1 << 17; +pub static extra_debug_info: uint = 1 << 18; +pub static print_link_args: uint = 1 << 19; +pub static no_debug_borrows: uint = 1 << 20; +pub static lint_llvm: uint = 1 << 21; +pub static print_llvm_passes: uint = 1 << 22; +pub static no_vectorize_loops: uint = 1 << 23; +pub static no_vectorize_slp: uint = 1 << 24; +pub static no_prepopulate_passes: uint = 1 << 25; +pub static use_softfp: uint = 1 << 26; +pub static gen_crate_map: uint = 1 << 27; +pub static prefer_dynamic: uint = 1 << 28; pub fn debugging_opts_map() -> ~[(&'static str, &'static str, uint)] { ~[("verbose", "in general, enable more debug printouts", verbose), @@ -78,7 +77,6 @@ pub fn debugging_opts_map() -> ~[(&'static str, &'static str, uint)] { ("trans-stats", "gather trans statistics", trans_stats), ("asm-comments", "generate comments into the assembly (may change behavior)", asm_comments), ("no-verify", "skip LLVM verification", no_verify), - ("trace", "emit trace logs", trace), ("coherence", "perform coherence checking", coherence), ("borrowck-stats", "gather borrowck statistics", borrowck_stats), ("borrowck-note-pure", "note where purity is req'd", @@ -308,7 +306,6 @@ impl Session_ { pub fn asm_comments(&self) -> bool { self.debugging_opt(asm_comments) } pub fn no_verify(&self) -> bool { self.debugging_opt(no_verify) } pub fn lint_llvm(&self) -> bool { self.debugging_opt(lint_llvm) } - pub fn trace(&self) -> bool { self.debugging_opt(trace) } pub fn coherence(&self) -> bool { self.debugging_opt(coherence) } pub fn borrowck_stats(&self) -> bool { self.debugging_opt(borrowck_stats) } pub fn borrowck_note_pure(&self) -> bool { diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index d4586fc59905b..72b9fc83c4ab8 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -1018,11 +1018,6 @@ pub fn get_landing_pad(bcx: @mut Block) -> BasicBlockRef { // The landing pad block is a cleanup SetCleanup(pad_bcx, llretval); - // Because we may have unwound across a stack boundary, we must call into - // the runtime to figure out which stack segment we are on and place the - // stack limit back into the TLS. - Call(pad_bcx, bcx.ccx().upcalls.reset_stack_limit, [], []); - // We store the retval in a function-central alloca, so that calls to // Resume can find it. match bcx.fcx.personality { @@ -1097,28 +1092,6 @@ pub fn load_if_immediate(cx: @mut Block, v: ValueRef, t: ty::t) -> ValueRef { return v; } -pub fn trans_trace(bcx: @mut Block, sp_opt: Option, trace_str: @str) { - if !bcx.sess().trace() { return; } - let _icx = push_ctxt("trans_trace"); - add_comment(bcx, trace_str); - let V_trace_str = C_cstr(bcx.ccx(), trace_str); - let (V_filename, V_line) = match sp_opt { - Some(sp) => { - let sess = bcx.sess(); - let loc = sess.parse_sess.cm.lookup_char_pos(sp.lo); - (C_cstr(bcx.ccx(), loc.file.name), loc.line as int) - } - None => { - (C_cstr(bcx.ccx(), @""), 0) - } - }; - let ccx = bcx.ccx(); - let V_trace_str = PointerCast(bcx, V_trace_str, Type::i8p()); - let V_filename = PointerCast(bcx, V_filename, Type::i8p()); - let args = ~[V_trace_str, V_filename, C_int(ccx, V_line)]; - Call(bcx, ccx.upcalls.trace, args, []); -} - pub fn ignore_lhs(_bcx: @mut Block, local: &ast::Local) -> bool { match local.pat.node { ast::PatWild => true, _ => false @@ -1313,12 +1286,6 @@ pub fn cleanup_and_leave(bcx: @mut Block, loop { debug!("cleanup_and_leave: leaving {}", cur.to_str()); - if bcx.sess().trace() { - trans_trace( - bcx, None, - (format!("cleanup_and_leave({})", cur.to_str())).to_managed()); - } - let mut cur_scope = cur.scope; loop { cur_scope = match cur_scope { @@ -1387,12 +1354,6 @@ pub fn cleanup_block(bcx: @mut Block, upto: Option) -> @mut Block loop { debug!("cleanup_block: {}", cur.to_str()); - if bcx.sess().trace() { - trans_trace( - bcx, None, - (format!("cleanup_block({})", cur.to_str())).to_managed()); - } - let mut cur_scope = cur.scope; loop { cur_scope = match cur_scope { @@ -2961,6 +2922,11 @@ pub fn create_module_map(ccx: &mut CrateContext) -> (ValueRef, uint) { return (map, keys.len()) } +pub fn symname(sess: session::Session, name: &str, + hash: &str, vers: &str) -> ~str { + let elt = path_name(sess.ident_of(name)); + link::exported_name(sess, ~[elt], hash, vers) +} pub fn decl_crate_map(sess: session::Session, mapmeta: LinkMeta, llmod: ModuleRef) -> ValueRef { @@ -2969,13 +2935,14 @@ pub fn decl_crate_map(sess: session::Session, mapmeta: LinkMeta, let mut n_subcrates = 1; let cstore = sess.cstore; while cstore::have_crate_data(cstore, n_subcrates) { n_subcrates += 1; } - let mapname = if *sess.building_library && !sess.gen_crate_map() { - format!("{}_{}_{}", mapmeta.name, mapmeta.vers, mapmeta.extras_hash) + let is_top = !*sess.building_library || sess.gen_crate_map(); + let sym_name = if is_top { + ~"_rust_crate_map_toplevel" } else { - ~"toplevel" + symname(sess, "_rust_crate_map_" + mapmeta.name, mapmeta.extras_hash, + mapmeta.vers) }; - let sym_name = ~"_rust_crate_map_" + mapname; let slicetype = Type::struct_([int_type, int_type], false); let maptype = Type::struct_([ Type::i32(), // version @@ -2990,7 +2957,7 @@ pub fn decl_crate_map(sess: session::Session, mapmeta: LinkMeta, }); // On windows we'd like to export the toplevel cratemap // such that we can find it from libstd. - if targ_cfg.os == OsWin32 && "toplevel" == mapname { + if targ_cfg.os == OsWin32 && is_top { lib::llvm::SetLinkage(map, lib::llvm::DLLExportLinkage); } else { lib::llvm::SetLinkage(map, lib::llvm::ExternalLinkage); @@ -3005,10 +2972,9 @@ pub fn fill_crate_map(ccx: @mut CrateContext, map: ValueRef) { let cstore = ccx.sess.cstore; while cstore::have_crate_data(cstore, i) { let cdata = cstore::get_crate_data(cstore, i); - let nm = format!("_rust_crate_map_{}_{}_{}", - cdata.name, - cstore::get_crate_vers(cstore, i), - cstore::get_crate_hash(cstore, i)); + let nm = symname(ccx.sess, format!("_rust_crate_map_{}", cdata.name), + cstore::get_crate_hash(cstore, i), + cstore::get_crate_vers(cstore, i)); let cr = nm.with_c_str(|buf| { unsafe { llvm::LLVMAddGlobal(ccx.llmod, ccx.int_type.to_ref(), buf) diff --git a/src/librustc/middle/trans/expr.rs b/src/librustc/middle/trans/expr.rs index 09218b5342493..2c3a9e040c959 100644 --- a/src/librustc/middle/trans/expr.rs +++ b/src/librustc/middle/trans/expr.rs @@ -567,8 +567,6 @@ fn trans_to_datum_unadjusted(bcx: @mut Block, expr: &ast::Expr) -> DatumBlock { fn trans_rvalue_datum_unadjusted(bcx: @mut Block, expr: &ast::Expr) -> DatumBlock { let _icx = push_ctxt("trans_rvalue_datum_unadjusted"); - trace_span!(bcx, expr.span, shorten(bcx.expr_to_str(expr))); - match expr.node { ast::ExprPath(_) | ast::ExprSelf => { return trans_def_datum_unadjusted(bcx, expr, bcx.def(expr.id)); @@ -625,8 +623,6 @@ fn trans_rvalue_stmt_unadjusted(bcx: @mut Block, expr: &ast::Expr) -> @mut Block return bcx; } - trace_span!(bcx, expr.span, shorten(bcx.expr_to_str(expr))); - match expr.node { ast::ExprBreak(label_opt) => { return controlflow::trans_break(bcx, label_opt); @@ -676,8 +672,6 @@ fn trans_rvalue_dps_unadjusted(bcx: @mut Block, expr: &ast::Expr, let _icx = push_ctxt("trans_rvalue_dps_unadjusted"); let tcx = bcx.tcx(); - trace_span!(bcx, expr.span, shorten(bcx.expr_to_str(expr))); - match expr.node { ast::ExprParen(e) => { return trans_rvalue_dps_unadjusted(bcx, e, dest); @@ -895,8 +889,6 @@ fn trans_lvalue_unadjusted(bcx: @mut Block, expr: &ast::Expr) -> DatumBlock { debug!("trans_lvalue(expr={})", bcx.expr_to_str(expr)); let _indenter = indenter(); - trace_span!(bcx, expr.span, shorten(bcx.expr_to_str(expr))); - return match expr.node { ast::ExprParen(e) => { trans_lvalue_unadjusted(bcx, e) diff --git a/src/librustc/middle/trans/macros.rs b/src/librustc/middle/trans/macros.rs index 43cc66c556867..938484fd44ceb 100644 --- a/src/librustc/middle/trans/macros.rs +++ b/src/librustc/middle/trans/macros.rs @@ -29,25 +29,3 @@ macro_rules! unpack_result( } ) ) - -macro_rules! trace_span( - ($bcx: ident, $sp: expr, $str: expr) => ( - { - let bcx = $bcx; - if bcx.sess().trace() { - trans_trace(bcx, Some($sp), $str); - } - } - ) -) - -macro_rules! trace( - ($bcx: ident, $str: expr) => ( - { - let bcx = $bcx; - if bcx.sess().trace() { - trans_trace(bcx, None, $str); - } - } - ) -) diff --git a/src/librustc/middle/trans/write_guard.rs b/src/librustc/middle/trans/write_guard.rs index 577e0a28105f2..2da2da80fdd6a 100644 --- a/src/librustc/middle/trans/write_guard.rs +++ b/src/librustc/middle/trans/write_guard.rs @@ -114,13 +114,6 @@ fn root(datum: &Datum, debug!("write_guard::root(root_key={:?}, root_info={:?}, datum={:?})", root_key, root_info, datum.to_str(bcx.ccx())); - if bcx.sess().trace() { - trans_trace( - bcx, None, - (format!("preserving until end of scope {}", - root_info.scope)).to_managed()); - } - // First, root the datum. Note that we must zero this value, // because sometimes we root on one path but not another. // See e.g. #4904. diff --git a/src/llvm b/src/llvm index 9e85884132d27..eac6ff795c407 160000 --- a/src/llvm +++ b/src/llvm @@ -1 +1 @@ -Subproject commit 9e85884132d277efeb507d0aeaa160ba201d054f +Subproject commit eac6ff795c40778683e42b0c6ab6f6adaceb391d diff --git a/src/rt/rust_upcall.c b/src/rt/rust_upcall.c index 9740fdea82c96..18b71fbb17908 100644 --- a/src/rt/rust_upcall.c +++ b/src/rt/rust_upcall.c @@ -51,7 +51,7 @@ struct s_rust_personality_args { struct _Unwind_Context *context; }; -void +static void upcall_s_rust_personality(struct s_rust_personality_args *args) { args->retval = PERSONALITY_FUNC(args->version, args->actions, @@ -78,6 +78,7 @@ upcall_rust_personality(int version, return args.retval; } +// NOTE: remove after stage0 // Landing pads need to call this to insert the // correct limit into TLS. // NB: This must run on the Rust stack because it diff --git a/src/rustllvm/llvm-auto-clean-trigger b/src/rustllvm/llvm-auto-clean-trigger index a72e585355480..bae0ad8fbc6c1 100644 --- a/src/rustllvm/llvm-auto-clean-trigger +++ b/src/rustllvm/llvm-auto-clean-trigger @@ -1,4 +1,4 @@ # If this file is modified, then llvm will be forcibly cleaned and then rebuilt. # The actual contents of this file do not matter, but to trigger a change on the # build bots then the contents should be changed so git updates the mtime. -2013-11-19 +2013-12-05