diff --git a/[refs] b/[refs] index b9be7f87bc2b7..ddee6a42b8e7a 100644 --- a/[refs] +++ b/[refs] @@ -35,7 +35,7 @@ refs/heads/kf/uvint32: eaeee720ed1d4109801549813c7bdbe5d16c75e4 "refs/heads/sjk/return_type": bea6a57566034aaf880b7f380e9e4e7cea9733a3 refs/heads/tan/sparse: 27e4b6914cdc5ef685cb832dd194348164caec10 refs/heads/kf/mmap: 64facb8fd791faf0a5f0768be2e2e2f320e1f2eb -refs/heads/anj/transpose: d594954e299617fdf72af6a896a5ff89c5d831f1 +refs/heads/anj/transpose: d61a09ad8ae6c5d3f9f2a9902f638f3eafdae938 "refs/heads/jn/cond_module": 687ae19896c164292399bb73c19154bf68976ee5 refs/heads/teh/multiprocloading: eabdd0f2c48ad31007266c46fe3aad7f987c6d41 refs/heads/kf/replfixes: 1c345c7d9598b0ae5d4818ecdba1eb25a170bd77 diff --git a/branches/anj/transpose/base/complex.jl b/branches/anj/transpose/base/complex.jl index b005d728ef87c..f1cc868cf468a 100644 --- a/branches/anj/transpose/base/complex.jl +++ b/branches/anj/transpose/base/complex.jl @@ -37,9 +37,6 @@ reim(z) = (real(z), imag(z)) real{T<:Real}(::Type{T}) = T real{T<:Real}(::Type{Complex{T}}) = T -complex{T<:Real}(::Type{T}) = Complex{T} -complex{T<:Real}(::Type{Complex{T}}) = Complex{T} - isreal(x::Real) = true isreal(z::Complex) = imag(z) == 0 isimag(z::Number) = real(z) == 0 diff --git a/branches/anj/transpose/base/inference.jl b/branches/anj/transpose/base/inference.jl index b28f36de6223b..e3161c389c51f 100644 --- a/branches/anj/transpose/base/inference.jl +++ b/branches/anj/transpose/base/inference.jl @@ -2721,14 +2721,6 @@ function inlineable(f::ANY, e::Expr, atype::ANY, sv::StaticVarInfo, enclosing_as expr = lastexpr.args[1] end - if length(stmts) == 1 - # remove line number when inlining a single expression. see issue #13725 - s = stmts[1] - if isa(s,Expr)&&is(s.head,:line) || isa(s,LineNumberNode) - pop!(stmts) - end - end - if isa(expr,Expr) old_t = e.typ if old_t <: expr.typ diff --git a/branches/anj/transpose/base/loading.jl b/branches/anj/transpose/base/loading.jl index d6d113cd6a794..f2a90cb224acb 100644 --- a/branches/anj/transpose/base/loading.jl +++ b/branches/anj/transpose/base/loading.jl @@ -138,9 +138,6 @@ end # returns an array of modules loaded, or nothing if failed function _require_from_serialized(node::Int, mod::Symbol, path_to_try::ByteString, toplevel_load::Bool) - if JLOptions().use_compilecache == 0 - return nothing - end restored = nothing if toplevel_load && myid() == 1 && nprocs() > 1 recompile_stale(mod, path_to_try) @@ -180,9 +177,6 @@ function _require_from_serialized(node::Int, mod::Symbol, path_to_try::ByteStrin end function _require_from_serialized(node::Int, mod::Symbol, toplevel_load::Bool) - if JLOptions().use_compilecache == 0 - return nothing - end if node == myid() paths = find_all_in_cache_path(mod) else @@ -240,10 +234,8 @@ precompilableerror(ex, c) = false # to be prevent it from being precompiled (false). __precompile__(true) is # ignored except within "require" call. function __precompile__(isprecompilable::Bool=true) - if (myid() == 1 && - JLOptions().use_compilecache != 0 && - isprecompilable != (0 != ccall(:jl_generating_output, Cint, ())) && - !(isprecompilable && toplevel_load::Bool)) + if myid() == 1 && isprecompilable != (0 != ccall(:jl_generating_output, Cint, ())) && + !(isprecompilable && toplevel_load::Bool) throw(PrecompilableError(isprecompilable)) end end @@ -254,21 +246,19 @@ function require_modname(name::AbstractString) # While we could also strip off the absolute path, the user may be # deliberately directing to a different file than what got # cached. So this takes a conservative approach. - if Bool(JLOptions().use_compilecache) - if endswith(name, ".jl") - tmp = name[1:end-3] - for prefix in LOAD_CACHE_PATH - path = joinpath(prefix, tmp*".ji") - if isfile(path) - return tmp - end + if endswith(name, ".jl") + tmp = name[1:end-3] + for prefix in LOAD_CACHE_PATH + path = joinpath(prefix, tmp*".ji") + if isfile(path) + return tmp end end end - return name + name end -""" +doc""" reload(name::AbstractString) Force reloading of a package, even if it has been loaded before. This is intended for use @@ -315,6 +305,7 @@ function require(mod::Symbol) end return end + name = string(mod) path = find_in_node_path(name, nothing, 1) if path === nothing @@ -356,8 +347,9 @@ include_string(txt::ByteString, fname::ByteString) = ccall(:jl_load_file_string, Any, (Ptr{UInt8},Csize_t,Ptr{UInt8},Csize_t), txt, sizeof(txt), fname, sizeof(fname)) -include_string(txt::AbstractString, fname::AbstractString="string") = - include_string(bytestring(txt), bytestring(fname)) +include_string(txt::AbstractString, fname::AbstractString) = include_string(bytestring(txt), bytestring(fname)) + +include_string(txt::AbstractString) = include_string(txt, "string") function source_path(default::Union{AbstractString,Void}="") t = current_task() @@ -444,7 +436,9 @@ function create_expr_cache(input::AbstractString, output::AbstractString) serialize(io, :(Base._track_dependencies[1] = true)) serialize(io, :(Base.include($(abspath(input))))) if source !== nothing - serialize(io, :(delete!(task_local_storage(), :SOURCE_PATH))) + serialize(io, quote + delete!(task_local_storage(), :SOURCE_PATH) + end) end close(io) wait(pobj) diff --git a/branches/anj/transpose/base/options.jl b/branches/anj/transpose/base/options.jl index f48abdb314210..fd4f7c3211b38 100644 --- a/branches/anj/transpose/base/options.jl +++ b/branches/anj/transpose/base/options.jl @@ -28,7 +28,6 @@ immutable JLOptions worker::Int8 handle_signals::Int8 use_precompiled::Int8 - use_compilecache::Int8 bindto::Ptr{UInt8} outputbc::Ptr{UInt8} outputo::Ptr{UInt8} @@ -37,17 +36,3 @@ immutable JLOptions end JLOptions() = unsafe_load(cglobal(:jl_options, JLOptions)) - -function show(io::IO, opt::JLOptions) - println(io, "JLOptions(") - fields = fieldnames(opt) - nfields = length(fields) - for (i,f) in enumerate(fieldnames(opt)) - v = getfield(opt,f) - if isa(v, Ptr{UInt8}) - v = v != C_NULL ? bytestring(v) : "" - end - println(io, " ", f, " = ", repr(v), i < nfields ? "," : "") - end - print(io,")") -end diff --git a/branches/anj/transpose/base/pkg/entry.jl b/branches/anj/transpose/base/pkg/entry.jl index 037b609341af6..195441d2d3021 100644 --- a/branches/anj/transpose/base/pkg/entry.jl +++ b/branches/anj/transpose/base/pkg/entry.jl @@ -543,7 +543,6 @@ function build!(pkgs::Vector, errs::Dict, seen::Set=Set()) end """ io, pobj = open(detach(`$(Base.julia_cmd()) - --compilecache=$(Bool(Base.JLOptions().use_compilecache) ? "yes" : "no") --history-file=no --color=$(Base.have_color ? "yes" : "no") --eval $code`), "w", STDOUT) diff --git a/branches/anj/transpose/deps/Makefile b/branches/anj/transpose/deps/Makefile index 5d47f760981fe..5ea57f3c16c71 100644 --- a/branches/anj/transpose/deps/Makefile +++ b/branches/anj/transpose/deps/Makefile @@ -645,7 +645,7 @@ ifeq ($(BUILD_LLDB),1) (cd $(LLVM_SRC_DIR)/tools/lldb && \ git pull --ff-only) ifneq ($(LLVM_GIT_VER_LLDB),) - (cd $(LLVM_SRC_DIR)/tools/lldb && \ + (cd $(LLVM_SRC_DIR)/tools/LLDB && \ git checkout $(LLVM_GIT_VER_LLDB)) endif # LLVM_GIT_VER_CLANG endif # BUILD_LLDB diff --git a/branches/anj/transpose/doc/man/julia.1 b/branches/anj/transpose/doc/man/julia.1 index 65772848c802f..abca45488014e 100644 --- a/branches/anj/transpose/doc/man/julia.1 +++ b/branches/anj/transpose/doc/man/julia.1 @@ -54,6 +54,7 @@ If a Julia source file is given as a \fIprogram\fP (optionally followed by .\" This section was taken nearly verbatim from the output of `julia --help` .SH "COMMAND-LINE OPTIONS" +.TP 25 .TP -v, --version @@ -64,25 +65,13 @@ Display version information Print help message .TP --J, --sysimage -Start up with the given system image file - -.TP --precompiled={yes|no} -Use precompiled code from system image if available +-q, --quiet +Quiet startup without banner .TP -H, --home Set location of julia executable -.TP ---startup-file={yes|no} -Load ~/.juliarc.jl - -.TP ---handle-signals={yes|no} -Enable or disable Julia's default signal handlers - .TP -e, --eval Evaluate @@ -99,6 +88,14 @@ Evaluate , but don't disable interactive mode -L, --load Load immediately on all processors +.TP +-J, --sysimage +Start up with the given system image file + +.TP +-C, --cpu-target +Limit usage of cpu features up to + .TP -p, --procs Run n local processes @@ -111,10 +108,6 @@ Run processes on hosts listed in -i Force isinteractive() to be true -.TP --q, --quiet -Quiet startup without banner - .TP --color={yes|no} Enable or disable color text @@ -124,57 +117,45 @@ Enable or disable color text Load or save history .TP - --compile={yes|no|all} +--startup-file={yes|no} +Load ~/.juliarc.jl + +.TP +--compile={yes|no|all} Enable or disable compiler, or request exhaustive compilation .TP --C, --cpu-target -Limit usage of cpu features up to +--code-coverage={none|user|all}, --code-coverage +Count executions of source lines (omitting setting is equivalent to 'user') .TP --O, --optimize -Run time-intensive code optimizations +--track-allocation={none|user|all}, --track-allocation +Count bytes allocated by each source line .TP ---inline={yes|no} -Control whether inlining is permitted (overrides functions declared as @inline) +-O, --optimize +Run time-intensive code optimizations .TP --check-bounds={yes|no} Emit bounds checks always or never (ignoring declarations) .TP ---math-mode={ieee|user} -Always use IEEE semantics for math (ignoring declarations), -or adhere to declarations in source code +--dump-bitcode={yes|no} +Dump bitcode for the system image (used with --build) .TP --depwarn={yes|no|error} Enable or disable syntax and method deprecation warnings ('error' turns warnings into errors) .TP - --output-o name -Generate an object file (including system image data) - -.TP ---output-ji name -Generate a system image data file (.ji) - -.TP ---output-bc name -Generate LLVM bitcode (.bc) - -.TP - --output-incremental=no -Generate an incremental output file (rather than complete) - -.TP ---code-coverage={none|user|all}, --code-coverage -Count executions of source lines (omitting setting is equivalent to 'user') +--inline={yes|no} +Control whether inlining is permitted (overrides functions declared as @inline) .TP ---track-allocation={none|user|all}, --track-allocation -Count bytes allocated by each source line +--math-mode={ieee|user} +Always use IEEE semantics for math (ignoring declarations), +or adhere to declarations in source code .SH FILES .I ~/.juliarc.jl diff --git a/branches/anj/transpose/doc/manual/getting-started.rst b/branches/anj/transpose/doc/manual/getting-started.rst index 14c42585bd075..5b31ed3079383 100644 --- a/branches/anj/transpose/doc/manual/getting-started.rst +++ b/branches/anj/transpose/doc/manual/getting-started.rst @@ -112,7 +112,6 @@ those available for the ``perl`` and ``ruby`` programs:: -J, --sysimage Start up with the given system image file --precompiled={yes|no} Use precompiled code from system image if available - --compilecache={yes|no} Enable/disable incremental precompilation of modules\n" -H, --home Set location of julia executable --startup-file={yes|no} Load ~/.juliarc.jl -f, --no-startup Don't load ~/.juliarc (deprecated, use --startup-file=no) diff --git a/branches/anj/transpose/doc/manual/modules.rst b/branches/anj/transpose/doc/manual/modules.rst index a797d213a0c7e..6b988f50d80ad 100644 --- a/branches/anj/transpose/doc/manual/modules.rst +++ b/branches/anj/transpose/doc/manual/modules.rst @@ -419,9 +419,3 @@ A few other points to be aware of: 4. WeakRef objects and finalizers are not currently handled properly by the serializer (this will be fixed in an upcoming release). - -It is sometimes helpful during module development to turn off incremental precompilation. -The command line flag ``--compilecache={yes|no}`` enables you to toggle module precompilation on and off. -When Julia is started with ``--compilecache=no`` the serialized modules in the compile cache are ignored when loading modules and module dependencies. -``Base.compilecache()`` can still be called manually and it will respect ``__precompile__()`` directives for the module. -The state of this command line flag is passed to ``Pkg.build()`` to disable automatic precompilation triggering when installing, updating, and explicitly building packages. diff --git a/branches/anj/transpose/src/cgutils.cpp b/branches/anj/transpose/src/cgutils.cpp index eb25d12954a62..0d689285da54b 100644 --- a/branches/anj/transpose/src/cgutils.cpp +++ b/branches/anj/transpose/src/cgutils.cpp @@ -69,10 +69,12 @@ static inline void add_named_global(GlobalObject *gv, void *addr) static inline void add_named_global(GlobalValue *gv, void *addr) #endif { -#ifdef USE_MCJIT - +#ifdef LLVM34 StringRef name = gv->getName(); +#endif + #ifdef _OS_WINDOWS_ +#ifdef LLVM35 std::string imp_name; // setting DLLEXPORT correctly only matters when building a binary if (jl_generating_output()) { @@ -89,13 +91,7 @@ static inline void add_named_global(GlobalValue *gv, void *addr) addr = (void*)imp_addr; } } -#endif - addComdat(gv); - sys::DynamicLibrary::AddSymbol(name, addr); - -#else // USE_MCJIT - -#ifdef _OS_WINDOWS_ +#else // setting DLLEXPORT correctly only matters when building a binary if (jl_generating_output()) { if (gv->getLinkage() == GlobalValue::ExternalLinkage) @@ -108,7 +104,16 @@ static inline void add_named_global(GlobalValue *gv, void *addr) addr = (void*)imp_addr; #endif } +#endif #endif // _OS_WINDOWS_ + +#ifdef USE_ORCJIT + addComdat(gv); + jl_ExecutionEngine->addGlobalMapping(name, addr); +#elif defined(USE_MCJIT) + addComdat(gv); + sys::DynamicLibrary::AddSymbol(name, addr); +#else // USE_MCJIT jl_ExecutionEngine->addGlobalMapping(gv, addr); #endif // USE_MCJIT } diff --git a/branches/anj/transpose/src/codegen.cpp b/branches/anj/transpose/src/codegen.cpp index 00980f25d9eb8..cbe8fda559292 100644 --- a/branches/anj/transpose/src/codegen.cpp +++ b/branches/anj/transpose/src/codegen.cpp @@ -51,16 +51,6 @@ #include #endif #include -#ifdef USE_MCJIT -#include -#include -#include -#include -#else -#include -#include -#include -#endif #include #include #include @@ -88,6 +78,24 @@ #include #include +#if defined(USE_ORCJIT) +#include "llvm/ExecutionEngine/Orc/CompileUtils.h" +#include "llvm/ExecutionEngine/Orc/IRCompileLayer.h" +#include "llvm/ExecutionEngine/Orc/LambdaResolver.h" +#include "llvm/ExecutionEngine/Orc/LazyEmittingLayer.h" +#include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h" +#include "llvm/ExecutionEngine/ObjectMemoryBuffer.h" +#elif defined(USE_MCJIT) +#include +#include +#include +#include +#else +#include +#include +#include +#endif + #if defined(_OS_WINDOWS_) && !defined(NOMINMAX) #define NOMINMAX #endif @@ -166,12 +174,162 @@ extern void _chkstk(void); // llvm state DLLEXPORT LLVMContext &jl_LLVMContext = getGlobalContext(); static IRBuilder<> builder(getGlobalContext()); -static bool nested_compile=false; -DLLEXPORT ExecutionEngine *jl_ExecutionEngine; -DLLEXPORT TargetMachine *jl_TargetMachine; +static bool nested_compile = false; +static TargetMachine *jl_TargetMachine; + +#ifdef USE_ORCJIT +template +static std::vector singletonSet(T t) { + std::vector Vec; + Vec.push_back(std::move(t)); + return Vec; +} + +class JuliaOJIT { +public: + typedef orc::ObjectLinkingLayer<> ObjLayerT; + typedef orc::IRCompileLayer CompileLayerT; + typedef CompileLayerT::ModuleSetHandleT ModuleHandleT; + typedef StringMap GlobalSymbolTableT; + + JuliaOJIT(TargetMachine &TM) + : TM(TM), + DL(TM.createDataLayout()), + CompileLayer(ObjectLayer, JITCompiler(*this)) { + // Make sure SectionMemoryManager::getSymbolAddressInProcess can resolve + // symbols in the program as well. The nullptr argument to the function + // tells DynamicLibrary to load the program, not a library. + std::string *ErrorStr = nullptr; + if (sys::DynamicLibrary::LoadLibraryPermanently(nullptr, ErrorStr)) + report_fatal_error("FATAL: unable to dlopen self\n" + *ErrorStr); + } + + std::string mangle(const std::string &Name) { + std::string MangledName; + { + raw_string_ostream MangledNameStream(MangledName); + Mangler::getNameWithPrefix(MangledNameStream, Name, DL); + } + return MangledName; + } + + void addGlobalMapping(StringRef Name, void *Addr) { + GlobalSymbolTable[mangle(Name)] = Addr; + } + + ModuleHandleT addModule(Module *M) { + // We need a memory manager to allocate memory and resolve symbols for this + // new module. Create one that resolves symbols by looking back into the + // JIT. + auto Resolver = orc::createLambdaResolver( + [&](const std::string &Name) { + // TODO: consider moving the FunctionMover resolver here + // Step 0: ObjectLinkingLayer has checked whether it is in the current module + // Step 1: Check against list of known external globals + GlobalSymbolTableT::const_iterator pos = GlobalSymbolTable.find(Name); + if (pos != GlobalSymbolTable.end()) + return RuntimeDyld::SymbolInfo((intptr_t)pos->second, JITSymbolFlags::Exported); + // Step 2: Search all previously emitted symbols + if (auto Sym = findSymbol(Name)) + return RuntimeDyld::SymbolInfo(Sym.getAddress(), + Sym.getFlags()); + // Step 2: Search the program symbols + if (uint64_t addr = SectionMemoryManager::getSymbolAddressInProcess(Name)) + return RuntimeDyld::SymbolInfo(addr, JITSymbolFlags::Exported); + // Return failure code + return RuntimeDyld::SymbolInfo(nullptr); + }, + [](const std::string &S) { return nullptr; } + ); + return CompileLayer.addModuleSet(singletonSet(std::move(M)), + &MemMgr, + std::move(Resolver)); + } + + void removeModule(ModuleHandleT H) { CompileLayer.removeModuleSet(H); } + + orc::JITSymbol findSymbol(const std::string &Name) { + return CompileLayer.findSymbol(Name, true); + } + + orc::JITSymbol findUnmangledSymbol(const std::string Name) { + return findSymbol(mangle(Name)); + } + + uint64_t getGlobalValueAddress(const std::string &Name) { + return CompileLayer.findSymbol(mangle(Name), false).getAddress(); + } + + uint64_t getFunctionAddress(const std::string &Name) { + return CompileLayer.findSymbol(mangle(Name), false).getAddress(); + } + + uint64_t FindFunctionNamed(const std::string &Name) { + return 0; // Functions are not kept around + } + + void RegisterJITEventListener(JITEventListener *L) { + // TODO + } + + const DataLayout& getDataLayout() const { + return DL; + } + + const Triple& getTargetTriple() const { + return TM.getTargetTriple(); + } + +private: + TargetMachine &TM; + const DataLayout DL; + SectionMemoryManager MemMgr; + ObjLayerT ObjectLayer; + CompileLayerT CompileLayer; + GlobalSymbolTableT GlobalSymbolTable; + + /// Simple compile functor: Takes a single IR module and returns an ObjectFile. + class JITCompiler { + public: + /// Construct a simple compile functor with the given target. + JITCompiler(JuliaOJIT &JIT) : JIT(JIT) { } + + /// Compile a Module to an ObjectFile. + object::OwningBinary operator()(Module &M) const { + MCContext *Ctx; + SmallVector ObjBufferSV; + raw_svector_ostream ObjStream(ObjBufferSV); + legacy::PassManager PM; + if (JIT.TM.addPassesToEmitMC(PM, Ctx, ObjStream)) + llvm_unreachable("Target does not support MC emission."); + PM.run(M); + ObjStream.flush(); + std::unique_ptr ObjBuffer( + new ObjectMemoryBuffer(std::move(ObjBufferSV))); + ErrorOr> Obj = + object::ObjectFile::createObjectFile(ObjBuffer->getMemBufferRef()); + // TODO: Actually report errors helpfully. + typedef object::OwningBinary OwningObj; + if (Obj) + return OwningObj(std::move(*Obj), std::move(ObjBuffer)); + return OwningObj(nullptr, nullptr); + } + + private: + JuliaOJIT &JIT; + }; +}; +static JuliaOJIT *jl_ExecutionEngine; +#else +#if !defined(LLVM35) || defined(LLVM36) +static +#endif + ExecutionEngine *jl_ExecutionEngine; +#endif + #ifdef USE_MCJIT static Module *shadow_module; -DLLEXPORT RTDyldMemoryManager *jl_mcjmm; +static RTDyldMemoryManager *jl_mcjmm; #define jl_Module (builder.GetInsertBlock()->getParent()->getParent()) #else static Module *jl_Module; @@ -367,6 +525,11 @@ static Function *queuerootfun; static Function *expect_func; static Function *jldlsym_func; static Function *jlnewbits_func; +static Function *jltypeassert_func; +#ifndef LLVM36 +static Function *jlpow_func; +static Function *jlpowf_func; +#endif //static Function *jlgetnthfield_func; static Function *jlgetnthfieldchecked_func; //static Function *jlsetnthfield_func; @@ -842,7 +1005,7 @@ static Function *to_function(jl_lambda_info_t *li) return f; } -static void jl_setup_module(Module *m, bool add) +static void jl_setup_module(Module *m) { m->addModuleFlag(llvm::Module::Warning, "Dwarf Version",2); #ifdef LLVM34 @@ -851,7 +1014,9 @@ static void jl_setup_module(Module *m, bool add) #endif #ifdef LLVM37 if (jl_ExecutionEngine) { -#ifdef LLVM38 +#ifdef USE_ORCJIT + m->setDataLayout(jl_ExecutionEngine->getDataLayout()); +#elif defined(LLVM38) m->setDataLayout(jl_ExecutionEngine->getDataLayout().getStringRepresentation()); #else m->setDataLayout(jl_ExecutionEngine->getDataLayout()->getStringRepresentation()); @@ -862,23 +1027,25 @@ static void jl_setup_module(Module *m, bool add) if (jl_ExecutionEngine) m->setDataLayout(jl_ExecutionEngine->getDataLayout()); #endif - if (add) { - assert(jl_ExecutionEngine); -#ifdef LLVM36 - jl_ExecutionEngine->addModule(std::unique_ptr(m)); -#else - jl_ExecutionEngine->addModule(m); -#endif +} + +static void jl_finalize_module(Module *m) +{ #if defined(_CPU_X86_64_) && defined(_OS_WINDOWS_) && defined(USE_MCJIT) - ArrayType *atype = ArrayType::get(T_uint32,3); // want 4-byte alignment of 12-bytes of data - (new GlobalVariable(*m, atype, - false, GlobalVariable::InternalLinkage, - ConstantAggregateZero::get(atype), "__UnwindData"))->setSection(".text"); - (new GlobalVariable(*m, atype, - false, GlobalVariable::InternalLinkage, - ConstantAggregateZero::get(atype), "__catchjmp"))->setSection(".text"); + ArrayType *atype = ArrayType::get(T_uint32,3); // want 4-byte alignment of 12-bytes of data + (new GlobalVariable(*m, atype, + false, GlobalVariable::InternalLinkage, + ConstantAggregateZero::get(atype), "__UnwindData"))->setSection(".text"); + (new GlobalVariable(*m, atype, + false, GlobalVariable::InternalLinkage, + ConstantAggregateZero::get(atype), "__catchjmp"))->setSection(".text"); +#endif + assert(jl_ExecutionEngine); +#if defined(LLVM36) && !defined(USE_ORCJIT) + jl_ExecutionEngine->addModule(std::unique_ptr(m)); +#else + jl_ExecutionEngine->addModule(m); #endif - } } extern "C" void jl_generate_fptr(jl_function_t *f) @@ -892,7 +1059,7 @@ extern "C" void jl_generate_fptr(jl_function_t *f) if (imaging_mode) { // Copy the function out of the shadow module Module *m = new Module("julia", jl_LLVMContext); - jl_setup_module(m, true); + jl_setup_module(m); FunctionMover mover(m, shadow_module); li->functionObject = mover.CloneFunction((Function*)li->functionObject); if (li->specFunctionObject != NULL) @@ -908,6 +1075,7 @@ extern "C" void jl_generate_fptr(jl_function_t *f) #endif Function *llvmf = (Function*)li->functionObject; + jl_finalize_module(llvmf->getParent()); #ifdef USE_MCJIT li->fptr = (jl_fptr_t)(intptr_t)jl_ExecutionEngine->getFunctionAddress(llvmf->getName()); #else @@ -1053,6 +1221,19 @@ void *jl_function_ptr(jl_function_t *f, jl_value_t *rt, jl_value_t *argt) Function *llvmf = jl_cfunction_object(f, rt, (jl_tupletype_t*)argt); assert(llvmf); JL_GC_POP(); + +#ifdef USE_MCJIT + if (uint64_t addr = jl_ExecutionEngine->getFunctionAddress(llvmf->getName())) + return (void*)(intptr_t)addr; + if (llvmf->getParent() == shadow_module) { + // Copy the function out of the shadow module + Module *m = new Module("julia", jl_LLVMContext); + jl_setup_module(m); + FunctionMover mover(m, shadow_module); + (void)mover.CloneFunction(llvmf); + jl_finalize_module(m); + } +#endif #ifdef USE_MCJIT return (void*)(intptr_t)jl_ExecutionEngine->getFunctionAddress(llvmf->getName()); #else @@ -1091,7 +1272,7 @@ void jl_extern_c(jl_function_t *f, jl_value_t *rt, jl_value_t *argt, char *name) } // --- native code info, and dump function to IR and ASM --- -extern void RegisterJuliaJITEventListener(); +extern JITEventListener* CreateJuliaJITEventListener(); extern int jl_get_llvmf_info(uint64_t fptr, uint64_t *symsize, uint64_t *slide, #ifdef USE_MCJIT @@ -1183,7 +1364,7 @@ const jl_value_t *jl_dump_function_ir(void *f, bool strip_ir_metadata, bool dump else { // make a copy of the function with all module metadata Module *m = new Module(llvmf->getName(), jl_LLVMContext); - jl_setup_module(m, false); + jl_setup_module(m); Function *f2 = CloneFunctionToModule(llvmf, m); if (strip_ir_metadata) { // strip metadata from the copy @@ -2253,16 +2434,14 @@ static bool emit_known_call(jl_cgval_t *ret, jl_value_t *ff, } } if (jl_subtype(ty, (jl_value_t*)jl_type_type, 0)) { - FunctionType *ft = FunctionType::get(T_void, two_pvalue_llvmt, false); // TODO: move this to the codegen init section - Value *typeassert = jl_Module->getOrInsertFunction("jl_typeassert", ft); int ldepth = ctx->gc.argDepth; *ret = emit_expr(args[1], ctx); Value *V = boxed(*ret, ctx); make_gcroot(V, ctx); #ifdef LLVM37 - builder.CreateCall(prepare_call(typeassert), {V, boxed(emit_expr(args[2], ctx),ctx)}); + builder.CreateCall(prepare_call(jltypeassert_func), {V, boxed(emit_expr(args[2], ctx),ctx)}); #else - builder.CreateCall2(prepare_call(typeassert), V, boxed(emit_expr(args[2], ctx),ctx)); + builder.CreateCall2(prepare_call(jltypeassert_func), V, boxed(emit_expr(args[2], ctx),ctx)); #endif ctx->gc.argDepth = ldepth; JL_GC_POP(); @@ -3828,12 +4007,12 @@ static Function *gen_cfun_wrapper(jl_function_t *ff, jl_value_t *jlrettype, jl_t // Create the Function stub Module *m; #ifdef USE_MCJIT - if (!imaging_mode) { - m = new Module(funcName.str(), jl_LLVMContext); - jl_setup_module(m,true); + if (imaging_mode) { + m = shadow_module; } else { - m = shadow_module; + m = new Module(funcName.str(), jl_LLVMContext); + jl_setup_module(m); } #else m = jl_Module; @@ -4042,16 +4221,9 @@ static Function *gen_cfun_wrapper(jl_function_t *ff, jl_value_t *jlrettype, jl_t #endif #ifdef USE_MCJIT - if (imaging_mode) { - // Copy the function out of the shadow module - Module *m = new Module("julia", jl_LLVMContext); - jl_setup_module(m, true); - FunctionMover mover(m, shadow_module); - Function *clone = mover.CloneFunction(cw); - FPM->run(*clone); - } - else { - FPM->run(*cw); + FPM->run(*cw); + if (!imaging_mode) { + jl_finalize_module(m); } #endif @@ -4285,12 +4457,12 @@ static Function *emit_function(jl_lambda_info_t *lam) Module *m; #ifdef USE_MCJIT - if (!imaging_mode) { - m = new Module(funcName.str(), jl_LLVMContext); - jl_setup_module(m,true); + if (imaging_mode) { + m = shadow_module; } else { - m = shadow_module; + m = new Module(funcName.str(), jl_LLVMContext); + jl_setup_module(m); } #else m = jl_Module; @@ -5540,6 +5712,11 @@ static void init_julia_llvm_env(Module *m) jlgetfield_func = builtin_func_map[jl_f_get_field]; jlapplygeneric_func = jlcall_func_to_llvm("jl_apply_generic", (void*)&jl_apply_generic, m); + jltypeassert_func = Function::Create(FunctionType::get(T_void, two_pvalue_llvmt, false), + Function::ExternalLinkage, + "jl_typeassert", m); + add_named_global(jltypeassert_func, (void*)&jl_typeassert); + queuerootfun = Function::Create(FunctionType::get(T_void, args_1ptr, false), Function::ExternalLinkage, "jl_gc_queue_root", m); @@ -5753,6 +5930,20 @@ static void init_julia_llvm_env(Module *m) "jl_gc_diff_total_bytes", m); add_named_global(diff_gc_total_bytes_func, (void*)*jl_gc_diff_total_bytes); +#ifndef LLVM36 + Type *powf_type[2] = { T_float32, T_float32 }; + jlpowf_func = Function::Create(FunctionType::get(T_float32, powf_type, false), + Function::ExternalLinkage, + "powf", m); + add_named_global(jlpowf_func, (void*)&powf); + + Type *pow_type[2] = { T_float64, T_float64 }; + jlpow_func = Function::Create(FunctionType::get(T_float64, pow_type, false), + Function::ExternalLinkage, + "pow", m); + add_named_global(jlpow_func, (void*)&pow); +#endif + // set up optimization passes #ifdef LLVM38 FPM = new legacy::FunctionPassManager(m); @@ -5958,17 +6149,17 @@ extern "C" void jl_init_codegen(void) #ifdef USE_MCJIT m = shadow_module = new Module("shadow", jl_LLVMContext); - jl_setup_module(shadow_module,false); + jl_setup_module(shadow_module); if (imaging_mode) { engine_module = new Module("engine_module", jl_LLVMContext); - jl_setup_module(engine_module,false); + jl_setup_module(engine_module); } else { engine_module = m; } #else engine_module = m = jl_Module = new Module("julia", jl_LLVMContext); - jl_setup_module(engine_module,false); + jl_setup_module(engine_module); #endif TargetOptions options = TargetOptions(); @@ -6007,7 +6198,7 @@ extern "C" void jl_init_codegen(void) .setJITMemoryManager(createJITMemoryManagerWin()) #elif defined(CUSTOM_MEMORY_MANAGER) .setMCJITMemoryManager(std::move(std::unique_ptr{createRTDyldMemoryManagerOSX()})) -#elif defined(USE_ORCJIT) // ORCJIT forgets to create one if one isn't created for it +#elif defined(USE_ORCMCJIT) // ORCJIT forgets to create one if one isn't created for it .setMCJITMemoryManager(std::move(std::unique_ptr{new SectionMemoryManager()})) #endif .setTargetOptions(options) @@ -6021,7 +6212,7 @@ extern "C" void jl_init_codegen(void) #if defined(USE_MCJIT) && !defined(LLVM36) .setUseMCJIT(true) #endif -#ifdef USE_ORCJIT +#ifdef USE_ORCMCJIT .setUseOrcMCJITReplacement(true) #endif ; @@ -6055,6 +6246,10 @@ extern "C" void jl_init_codegen(void) #else engine_module->setDataLayout(jl_TargetMachine->getDataLayout()->getStringRepresentation()); #endif + +#ifdef USE_ORCJIT + jl_ExecutionEngine = new JuliaOJIT(*jl_TargetMachine); +#else jl_ExecutionEngine = eb.create(jl_TargetMachine); //jl_printf(JL_STDERR,"%s\n",jl_ExecutionEngine->getDataLayout()->getStringRepresentation().c_str()); if (!jl_ExecutionEngine) { @@ -6062,12 +6257,20 @@ extern "C" void jl_init_codegen(void) ErrorStr.c_str()); exit(1); } -#if defined(LLVM35) && !defined(USE_ORCJIT) +#if defined(LLVM35) && !defined(USE_ORCMCJIT) jl_ExecutionEngine->setProcessAllSections(true); #endif jl_ExecutionEngine->DisableLazyCompilation(); +#endif + mbuilder = new MDBuilder(getGlobalContext()); +#ifdef USE_ORCJIT + m->setDataLayout(jl_ExecutionEngine->getDataLayout()); + engine_module->setDataLayout(jl_ExecutionEngine->getDataLayout()); + m->setTargetTriple(jl_TargetMachine->getTargetTriple().str()); + engine_module->setTargetTriple(jl_TargetMachine->getTargetTriple().str()); +#else #ifdef LLVM37 #ifdef LLVM38 m->setDataLayout(jl_ExecutionEngine->getDataLayout().getStringRepresentation()); @@ -6082,9 +6285,11 @@ extern "C" void jl_init_codegen(void) m->setDataLayout(jl_ExecutionEngine->getDataLayout()); engine_module->setDataLayout(jl_ExecutionEngine->getDataLayout()); #endif +#endif + init_julia_llvm_env(m); - RegisterJuliaJITEventListener(); + jl_ExecutionEngine->RegisterJITEventListener(CreateJuliaJITEventListener()); #ifdef JL_USE_INTEL_JITEVENTS if (jl_using_intel_jitevents) jl_ExecutionEngine->RegisterJITEventListener( diff --git a/branches/anj/transpose/src/debuginfo.cpp b/branches/anj/transpose/src/debuginfo.cpp index 07142b08e120d..cfbdedc2fed9a 100644 --- a/branches/anj/transpose/src/debuginfo.cpp +++ b/branches/anj/transpose/src/debuginfo.cpp @@ -52,7 +52,9 @@ #include using namespace llvm; -extern DLLEXPORT ExecutionEngine *jl_ExecutionEngine; +#if defined(LLVM35) && !defined(LLVM36) +extern ExecutionEngine *jl_ExecutionEngine; +#endif #ifdef USE_MCJIT typedef object::SymbolRef SymRef; @@ -454,11 +456,11 @@ char *jl_demangle(const char *name) return strdup(name); } -JuliaJITEventListener *jl_jit_events; -void RegisterJuliaJITEventListener() +static JuliaJITEventListener *jl_jit_events; +JITEventListener* CreateJuliaJITEventListener() { jl_jit_events = new JuliaJITEventListener(); - jl_ExecutionEngine->RegisterJITEventListener(jl_jit_events); + return jl_jit_events; } // *name and *filename are either NULL or malloc'd pointers diff --git a/branches/anj/transpose/src/init.c b/branches/anj/transpose/src/init.c index caf52c6a49d6b..0ebcb048c5a80 100644 --- a/branches/anj/transpose/src/init.c +++ b/branches/anj/transpose/src/init.c @@ -76,7 +76,6 @@ jl_options_t jl_options = { 0, // quiet #else JL_OPTIONS_USE_PRECOMPILED_YES, #endif - JL_OPTIONS_USE_COMPILECACHE_YES, NULL, // bindto NULL, // outputbc NULL, // outputo diff --git a/branches/anj/transpose/src/intrinsics.cpp b/branches/anj/transpose/src/intrinsics.cpp index 3864d2ac6da43..29d32af125d18 100644 --- a/branches/anj/transpose/src/intrinsics.cpp +++ b/branches/anj/transpose/src/intrinsics.cpp @@ -1518,10 +1518,8 @@ static Value *emit_untyped_intrinsic(intrinsic f, Value *x, Value *y, Value *z, #endif #else // issue #6506 - Type *ts[2] = { tx, tx }; - Value *pow = jl_Module->getOrInsertFunction( - tx==T_float64 ? "pow" : "powf", FunctionType::get(tx, ts, false)); - return builder.CreateCall2(pow, x, builder.CreateSIToFP(y, tx)); + return builder.CreateCall2(prepare_call(tx == T_float64 ? jlpow_func : jlpowf_func), + x, builder.CreateSIToFP(y, tx)); #endif } case sqrt_llvm_fast: { diff --git a/branches/anj/transpose/src/julia.h b/branches/anj/transpose/src/julia.h index 28bbd4a6236b5..b5efdd8af06a4 100644 --- a/branches/anj/transpose/src/julia.h +++ b/branches/anj/transpose/src/julia.h @@ -1572,7 +1572,6 @@ typedef struct { int8_t worker; int8_t handle_signals; int8_t use_precompiled; - int8_t use_compilecache; const char *bindto; const char *outputbc; const char *outputo; @@ -1622,9 +1621,6 @@ DLLEXPORT int jl_generating_output(void); #define JL_OPTIONS_USE_PRECOMPILED_YES 1 #define JL_OPTIONS_USE_PRECOMPILED_NO 0 -#define JL_OPTIONS_USE_COMPILECACHE_YES 1 -#define JL_OPTIONS_USE_COMPILECACHE_NO 0 - // Version information #include diff --git a/branches/anj/transpose/src/julia_internal.h b/branches/anj/transpose/src/julia_internal.h index 0ab602496eaaa..72526822c7300 100644 --- a/branches/anj/transpose/src/julia_internal.h +++ b/branches/anj/transpose/src/julia_internal.h @@ -66,6 +66,7 @@ void jl_set_gs_ctr(uint32_t ctr); void NORETURN jl_no_method_error_bare(jl_function_t *f, jl_value_t *args); void NORETURN jl_no_method_error(jl_function_t *f, jl_value_t **args, size_t na); +DLLEXPORT void jl_typeassert(jl_value_t *x, jl_value_t *t); #define JL_CALLABLE(name) \ DLLEXPORT jl_value_t *name(jl_value_t *F, jl_value_t **args, uint32_t nargs) diff --git a/branches/anj/transpose/src/llvm-version.h b/branches/anj/transpose/src/llvm-version.h index 7d11b2013dba8..e9c058993acc7 100644 --- a/branches/anj/transpose/src/llvm-version.h +++ b/branches/anj/transpose/src/llvm-version.h @@ -9,6 +9,7 @@ #if defined(LLVM_VERSION_MAJOR) && LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR >= 7 #define LLVM37 1 // Experimental: +//#define USE_ORCMCJIT //#define USE_ORCJIT #endif @@ -34,3 +35,6 @@ #ifdef USE_ORCJIT //temporary, since in some places USE_MCJIT may be used instead of the correct LLVM version test #define USE_MCJIT #endif +#ifdef USE_ORCMCJIT //temporary, since in some places USE_MCJIT may be used instead of the correct LLVM version test +#define USE_MCJIT +#endif diff --git a/branches/anj/transpose/test/cmdlineargs.jl b/branches/anj/transpose/test/cmdlineargs.jl index 175e8bc6f735d..9a8e9396aed1a 100644 --- a/branches/anj/transpose/test/cmdlineargs.jl +++ b/branches/anj/transpose/test/cmdlineargs.jl @@ -232,10 +232,4 @@ let exename = `$(joinpath(JULIA_HOME, Base.julia_exename())) --precompiled=yes` @test readchomp(pipeline(ignorestatus(`$exename -f -p`),stderr=`cat`)) == "ERROR: option `-p/--procs` is missing an argument" @test readchomp(pipeline(ignorestatus(`$exename -f --inline`),stderr=`cat`)) == "ERROR: option `--inline` is missing an argument" @test readchomp(pipeline(ignorestatus(`$exename -f -e "@show ARGS" -now -- julia RUN.jl`),stderr=`cat`)) == "ERROR: unknown option `-n`" - - # --compilecache={yes|no} - @test readchomp(`$exename -E "Bool(Base.JLOptions().use_compilecache)"`) == "true" - @test readchomp(`$exename --compilecache=yes -E "Bool(Base.JLOptions().use_compilecache)"`) == "true" - @test readchomp(`$exename --compilecache=no -E "Bool(Base.JLOptions().use_compilecache)"`) == "false" - @test !success(`$exename --compilecache=foo -e "exit(0)"`) end diff --git a/branches/anj/transpose/test/compile.jl b/branches/anj/transpose/test/compile.jl index 4e4da3dcb733a..49b6c5cfdc57b 100644 --- a/branches/anj/transpose/test/compile.jl +++ b/branches/anj/transpose/test/compile.jl @@ -81,55 +81,8 @@ try end println(STDERR, "\nNOTE: The following 'LoadError: break me' indicates normal operation") @test_throws ErrorException Base.require(:FooBar) - finally splice!(Base.LOAD_CACHE_PATH, 1) splice!(LOAD_PATH, 1) rm(dir, recursive=true) end - -# test --compilecache=no command line option -dir = mktempdir() -let dir = mktempdir(), - Time_module = :Time4b3a94a1a081a8cb - - try - open(joinpath(dir, "$Time_module.jl"), "w") do io - write(io, """ - module $Time_module - __precompile__(true) - time = Base.time() - end - """) - end - - eval(quote - insert!(LOAD_PATH, 1, $(dir)) - insert!(Base.LOAD_CACHE_PATH, 1, $(dir)) - Base.compilecache(:Time4b3a94a1a081a8cb) - end) - - exename = `$(joinpath(JULIA_HOME, Base.julia_exename())) --precompiled=yes` - - testcode = """ - insert!(LOAD_PATH, 1, $(repr(dir))) - insert!(Base.LOAD_CACHE_PATH, 1, $(repr(dir))) - using $Time_module - getfield($Time_module, :time) - """ - - t1_yes = readchomp(`$exename --compilecache=yes -E $(testcode)`) - t2_yes = readchomp(`$exename --compilecache=yes -E $(testcode)`) - @test t1_yes == t2_yes - - t1_no = readchomp(`$exename --compilecache=no -E $(testcode)`) - t2_no = readchomp(`$exename --compilecache=no -E $(testcode)`) - @test t1_no != t2_no - @test parse(Float64, t1_no) < parse(Float64, t2_no) - - finally - splice!(Base.LOAD_CACHE_PATH, 1) - splice!(LOAD_PATH, 1) - rm(dir, recursive=true) - end -end diff --git a/branches/anj/transpose/test/complex.jl b/branches/anj/transpose/test/complex.jl index d9fe38d12ae22..de1aaeb506c80 100644 --- a/branches/anj/transpose/test/complex.jl +++ b/branches/anj/transpose/test/complex.jl @@ -2,13 +2,6 @@ @test reim(2 + 3im) == (2, 3) -for T in (Int64, Float64) - @test real(T) == T - @test real(Complex{T}) == T - @test complex(T) == Complex{T} - @test complex(Complex{T}) == Complex{T} -end - # Basic arithmetic for T in (Float16, Float32, Float64, BigFloat) t = true diff --git a/branches/anj/transpose/ui/repl.c b/branches/anj/transpose/ui/repl.c index 30cd1dfab149f..ea9cab2f85440 100644 --- a/branches/anj/transpose/ui/repl.c +++ b/branches/anj/transpose/ui/repl.c @@ -47,7 +47,6 @@ static const char opts[] = // startup options " -J, --sysimage Start up with the given system image file\n" " --precompiled={yes|no} Use precompiled code from system image if available\n" - " --compilecache={yes|no} Enable/disable incremental precompilation of modules\n" " -H, --home Set location of julia executable\n" " --startup-file={yes|no} Load ~/.juliarc.jl\n" " -f, --no-startup Don't load ~/.juliarc (deprecated, use --startup-file=no)\n" @@ -116,7 +115,6 @@ void parse_opts(int *argcp, char ***argvp) opt_output_o, opt_output_ji, opt_use_precompiled, - opt_use_compilecache, opt_incremental }; static char* shortopts = "+vhqFfH:e:E:P:L:J:C:ip:O"; @@ -134,7 +132,6 @@ void parse_opts(int *argcp, char ***argvp) { "load", required_argument, 0, 'L' }, { "sysimage", required_argument, 0, 'J' }, { "precompiled", required_argument, 0, opt_use_precompiled }, - { "compilecache", required_argument, 0, opt_use_compilecache }, { "cpu-target", required_argument, 0, 'C' }, { "procs", required_argument, 0, 'p' }, { "machinefile", required_argument, 0, opt_machinefile }, @@ -234,14 +231,6 @@ void parse_opts(int *argcp, char ***argvp) else jl_errorf("julia: invalid argument to --precompiled={yes|no} (%s)", optarg); break; - case opt_use_compilecache: - if (!strcmp(optarg,"yes")) - jl_options.use_compilecache = JL_OPTIONS_USE_COMPILECACHE_YES; - else if (!strcmp(optarg,"no")) - jl_options.use_compilecache = JL_OPTIONS_USE_COMPILECACHE_NO; - else - jl_errorf("julia: invalid argument to --compilecache={yes|no} (%s)", optarg); - break; case 'C': // cpu-target jl_options.cpu_target = strdup(optarg); break;