LCOV - code coverage report
Current view: top level - src - jitlayers.cpp (source / functions) Hit Total Coverage
Test: [test only] commit 0f242327d2cc9bd130497f44b6350c924185606a Lines: 637 705 90.4 %
Date: 2022-07-16 23:42:53 Functions: 73 79 92.4 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 320 440 72.7 %

           Branch data     Line data    Source code
       1                 :            : // This file is a part of Julia. License is MIT: https://julialang.org/license
       2                 :            : 
       3                 :            : #include "llvm-version.h"
       4                 :            : #include "platform.h"
       5                 :            : #include <stdint.h>
       6                 :            : 
       7                 :            : #include "llvm/IR/Mangler.h"
       8                 :            : #include <llvm/ADT/StringMap.h>
       9                 :            : #include <llvm/Analysis/TargetLibraryInfo.h>
      10                 :            : #include <llvm/Analysis/TargetTransformInfo.h>
      11                 :            : #include <llvm/ExecutionEngine/Orc/CompileUtils.h>
      12                 :            : #include <llvm/ExecutionEngine/Orc/ExecutionUtils.h>
      13                 :            : #if JL_LLVM_VERSION >= 130000
      14                 :            : #include <llvm/ExecutionEngine/Orc/ExecutorProcessControl.h>
      15                 :            : #endif
      16                 :            : #include <llvm/Support/DynamicLibrary.h>
      17                 :            : #include <llvm/Support/FormattedStream.h>
      18                 :            : #include <llvm/Support/SmallVectorMemoryBuffer.h>
      19                 :            : #include <llvm/Support/raw_ostream.h>
      20                 :            : #include <llvm/Transforms/Utils/Cloning.h>
      21                 :            : #include <llvm/Transforms/Utils/ModuleUtils.h>
      22                 :            : #include <llvm/Bitcode/BitcodeWriter.h>
      23                 :            : 
      24                 :            : // target machine computation
      25                 :            : #include <llvm/CodeGen/TargetSubtargetInfo.h>
      26                 :            : #if JL_LLVM_VERSION >= 140000
      27                 :            : #include <llvm/MC/TargetRegistry.h>
      28                 :            : #else
      29                 :            : #include <llvm/Support/TargetRegistry.h>
      30                 :            : #endif
      31                 :            : #include <llvm/Target/TargetOptions.h>
      32                 :            : #include <llvm/Support/Host.h>
      33                 :            : #include <llvm/Support/TargetSelect.h>
      34                 :            : #include <llvm/Object/SymbolSize.h>
      35                 :            : 
      36                 :            : using namespace llvm;
      37                 :            : 
      38                 :            : #include "julia.h"
      39                 :            : #include "julia_internal.h"
      40                 :            : #include "codegen_shared.h"
      41                 :            : #include "jitlayers.h"
      42                 :            : #include "julia_assert.h"
      43                 :            : #include "processor.h"
      44                 :            : 
      45                 :            : #ifdef JL_USE_JITLINK
      46                 :            : # if JL_LLVM_VERSION >= 140000
      47                 :            : #  include <llvm/ExecutionEngine/Orc/DebuggerSupportPlugin.h>
      48                 :            : # endif
      49                 :            : # include <llvm/ExecutionEngine/JITLink/EHFrameSupport.h>
      50                 :            : # include <llvm/ExecutionEngine/JITLink/JITLinkMemoryManager.h>
      51                 :            : #else
      52                 :            : # include <llvm/ExecutionEngine/SectionMemoryManager.h>
      53                 :            : #endif
      54                 :            : 
      55                 :            : #define DEBUG_TYPE "jitlayers"
      56                 :            : 
      57                 :            : // Snooping on which functions are being compiled, and how long it takes
      58                 :            : extern "C" JL_DLLEXPORT
      59                 :          4 : void jl_dump_compiles_impl(void *s)
      60                 :            : {
      61                 :          4 :     **jl_ExecutionEngine->get_dump_compiles_stream() = (JL_STREAM*)s;
      62                 :          4 : }
      63                 :            : extern "C" JL_DLLEXPORT
      64                 :          2 : void jl_dump_llvm_opt_impl(void *s)
      65                 :            : {
      66                 :          2 :     **jl_ExecutionEngine->get_dump_llvm_opt_stream() = (JL_STREAM*)s;
      67                 :          2 : }
      68                 :            : 
      69                 :            : static void jl_add_to_ee(orc::ThreadSafeModule &M, StringMap<orc::ThreadSafeModule*> &NewExports);
      70                 :            : static void jl_decorate_module(Module &M);
      71                 :            : static uint64_t getAddressForFunction(StringRef fname);
      72                 :            : 
      73                 :     179327 : void jl_link_global(GlobalVariable *GV, void *addr)
      74                 :            : {
      75                 :     179327 :     Constant *P = literal_static_pointer_val(addr, GV->getValueType());
      76                 :     179327 :     GV->setInitializer(P);
      77         [ -  + ]:     179327 :     if (jl_options.image_codegen) {
      78                 :            :         // If we are forcing imaging mode codegen for debugging,
      79                 :            :         // emit external non-const symbol to avoid LLVM optimizing the code
      80                 :            :         // similar to non-imaging mode.
      81                 :          0 :         GV->setLinkage(GlobalValue::ExternalLinkage);
      82                 :            :     }
      83                 :            :     else {
      84                 :     179327 :         GV->setConstant(true);
      85                 :     179327 :         GV->setLinkage(GlobalValue::PrivateLinkage);
      86                 :     179327 :         GV->setUnnamedAddr(GlobalValue::UnnamedAddr::Global);
      87                 :            :     }
      88                 :     179327 : }
      89                 :            : 
      90                 :          4 : void jl_jit_globals(std::map<void *, GlobalVariable*> &globals)
      91                 :            : {
      92         [ -  + ]:          4 :     for (auto &global : globals) {
      93                 :          0 :         jl_link_global(global.second, global.first);
      94                 :            :     }
      95                 :          4 : }
      96                 :            : 
      97                 :            : // this generates llvm code for the lambda info
      98                 :            : // and adds the result to the jitlayers
      99                 :            : // (and the shadow module),
     100                 :            : // and generates code for it
     101                 :     188320 : static jl_callptr_t _jl_compile_codeinst(
     102                 :            :         jl_code_instance_t *codeinst,
     103                 :            :         jl_code_info_t *src,
     104                 :            :         size_t world,
     105                 :            :         orc::ThreadSafeContext context)
     106                 :            : {
     107                 :            :     // caller must hold codegen_lock
     108                 :            :     // and have disabled finalizers
     109                 :     188320 :     uint64_t start_time = 0;
     110                 :     188320 :     bool timed = !!*jl_ExecutionEngine->get_dump_compiles_stream();
     111         [ +  + ]:     188320 :     if (timed)
     112                 :          1 :         start_time = jl_hrtime();
     113                 :            : 
     114         [ -  + ]:     188320 :     assert(jl_is_code_instance(codeinst));
     115   [ +  -  -  +  :     188320 :     assert(codeinst->min_world <= world && (codeinst->max_world >= world || codeinst->max_world == 0) &&
                   -  - ]
     116                 :            :         "invalid world for method-instance");
     117   [ +  -  +  - ]:     188320 :     assert(src && jl_is_code_info(src));
     118                 :            : 
     119                 :     188320 :     jl_callptr_t fptr = NULL;
     120                 :            :     // emit the code in LLVM IR form
     121                 :     376629 :     jl_codegen_params_t params(std::move(context)); // Locks the context
     122                 :     188320 :     params.cache = true;
     123                 :     188320 :     params.world = world;
     124                 :     188320 :     jl_workqueue_t emitted;
     125                 :            :     {
     126                 :            :         orc::ThreadSafeModule result_m =
     127                 :     376629 :             jl_create_llvm_module(name_from_method_instance(codeinst->def), params.tsctx, params.imaging);
     128                 :     376629 :         jl_llvm_functions_t decls = jl_emit_codeinst(result_m, codeinst, src, params);
     129         [ +  - ]:     188310 :         if (result_m)
     130                 :     188310 :             emitted[codeinst] = {std::move(result_m), std::move(decls)};
     131                 :            :         {
     132                 :     376620 :             auto temp_module = jl_create_llvm_module(name_from_method_instance(codeinst->def), params.tsctx, params.imaging);
     133                 :     188310 :             jl_compile_workqueue(emitted, *temp_module.getModuleUnlocked(), params, CompilationPolicy::Default);
     134                 :            :         }
     135                 :            : 
     136         [ +  + ]:     188310 :         if (params._shared_module)
     137                 :       1292 :             jl_ExecutionEngine->addModule(std::move(params._shared_module));
     138                 :     376619 :         StringMap<orc::ThreadSafeModule*> NewExports;
     139                 :     376619 :         StringMap<void*> NewGlobals;
     140         [ +  + ]:     291852 :         for (auto &global : params.globals) {
     141                 :     103542 :             NewGlobals[global.second->getName()] = global.first;
     142                 :            :         }
     143         [ +  + ]:     525526 :         for (auto &def : emitted) {
     144                 :     337216 :             orc::ThreadSafeModule &TSM = std::get<0>(def.second);
     145                 :            :             //The underlying context object is still locked because params is not destroyed yet
     146                 :     337216 :             auto M = TSM.getModuleUnlocked();
     147         [ +  + ]:    4353980 :             for (auto &F : M->global_objects()) {
     148   [ +  +  +  +  :    4016760 :                 if (!F.isDeclaration() && F.getLinkage() == GlobalValue::ExternalLinkage) {
                   +  + ]
     149                 :     656019 :                     NewExports[F.getName()] = &TSM;
     150                 :            :                 }
     151                 :            :             }
     152                 :            :             // Let's link all globals here also (for now)
     153         [ +  + ]:     664924 :             for (auto &GV : M->globals()) {
     154                 :     327708 :                 auto InitValue = NewGlobals.find(GV.getName());
     155         [ +  + ]:     327708 :                 if (InitValue != NewGlobals.end()) {
     156                 :     179327 :                     jl_link_global(&GV, InitValue->second);
     157                 :            :                 }
     158                 :            :             }
     159                 :            :         }
     160         [ +  + ]:     525525 :         for (auto &def : emitted) {
     161                 :            :             // Add the results to the execution engine now
     162                 :     337216 :             orc::ThreadSafeModule &M = std::get<0>(def.second);
     163                 :     337216 :             jl_add_to_ee(M, NewExports);
     164                 :            :         }
     165                 :            :     }
     166                 :            :     JL_TIMING(LLVM_MODULE_FINISH);
     167                 :            : 
     168         [ +  + ]:     525524 :     for (auto &def : emitted) {
     169                 :     337215 :         jl_code_instance_t *this_code = def.first;
     170                 :     674430 :         jl_llvm_functions_t decls = std::get<1>(def.second);
     171                 :            :         jl_callptr_t addr;
     172                 :     337215 :         bool isspecsig = false;
     173         [ +  + ]:     337215 :         if (decls.functionObject == "jl_fptr_args") {
     174                 :      19041 :             addr = jl_fptr_args_addr;
     175                 :            :         }
     176         [ +  + ]:     318174 :         else if (decls.functionObject == "jl_fptr_sparam") {
     177                 :        200 :             addr = jl_fptr_sparam_addr;
     178                 :            :         }
     179                 :            :         else {
     180                 :     317974 :             addr = (jl_callptr_t)getAddressForFunction(decls.functionObject);
     181                 :     317974 :             isspecsig = true;
     182                 :            :         }
     183         [ +  + ]:     337215 :         if (jl_atomic_load_relaxed(&this_code->invoke) == NULL) {
     184                 :            :             // once set, don't change invoke-ptr, as that leads to race conditions
     185                 :            :             // with the (not) simultaneous updates to invoke and specptr
     186         [ +  - ]:     337214 :             if (!decls.specFunctionObject.empty()) {
     187                 :     337214 :                 jl_atomic_store_release(&this_code->specptr.fptr, (void*)getAddressForFunction(decls.specFunctionObject));
     188                 :     337214 :                 this_code->isspecsig = isspecsig;
     189                 :            :             }
     190                 :     337214 :             jl_atomic_store_release(&this_code->invoke, addr);
     191                 :            :         }
     192   [ +  -  +  -  :          1 :         else if (jl_atomic_load_relaxed(&this_code->invoke) == jl_fptr_const_return_addr && !decls.specFunctionObject.empty()) {
                   +  - ]
     193                 :            :             // hack to export this pointer value to jl_dump_method_disasm
     194                 :          1 :             jl_atomic_store_release(&this_code->specptr.fptr, (void*)getAddressForFunction(decls.specFunctionObject));
     195                 :            :         }
     196         [ +  + ]:     337215 :         if (this_code== codeinst)
     197                 :     188309 :             fptr = addr;
     198                 :            :     }
     199                 :            : 
     200                 :     188309 :     uint64_t end_time = 0;
     201         [ +  + ]:     188309 :     if (timed)
     202                 :          1 :         end_time = jl_hrtime();
     203                 :            : 
     204                 :            :     // If logging of the compilation stream is enabled,
     205                 :            :     // then dump the method-instance specialization type to the stream
     206                 :     188309 :     jl_method_instance_t *mi = codeinst->def;
     207         [ +  + ]:     188309 :     if (jl_is_method(mi->def.method)) {
     208                 :     374396 :         auto stream = *jl_ExecutionEngine->get_dump_compiles_stream();
     209         [ +  + ]:     187198 :         if (stream) {
     210                 :          1 :             jl_printf(stream, "%" PRIu64 "\t\"", end_time - start_time);
     211                 :          1 :             jl_static_show(stream, mi->specTypes);
     212                 :          1 :             jl_printf(stream, "\"\n");
     213                 :            :         }
     214                 :            :     }
     215                 :     188309 :     return fptr;
     216                 :            : }
     217                 :            : 
     218                 :            : const char *jl_generate_ccallable(LLVMOrcThreadSafeModuleRef llvmmod, void *sysimg_handle, jl_value_t *declrt, jl_value_t *sigt, jl_codegen_params_t &params);
     219                 :            : 
     220                 :            : // compile a C-callable alias
     221                 :            : extern "C" JL_DLLEXPORT
     222                 :          6 : int jl_compile_extern_c_impl(LLVMOrcThreadSafeModuleRef llvmmod, void *p, void *sysimg, jl_value_t *declrt, jl_value_t *sigt)
     223                 :            : {
     224                 :          6 :     JL_LOCK(&jl_codegen_lock);
     225                 :          6 :     uint64_t compiler_start_time = 0;
     226                 :          6 :     uint8_t measure_compile_time_enabled = jl_atomic_load_relaxed(&jl_measure_compile_time_enabled);
     227         [ -  + ]:          6 :     if (measure_compile_time_enabled)
     228                 :          0 :         compiler_start_time = jl_hrtime();
     229                 :          6 :     orc::ThreadSafeContext ctx;
     230                 :          6 :     auto into = unwrap(llvmmod);
     231                 :          6 :     jl_codegen_params_t *pparams = (jl_codegen_params_t*)p;
     232                 :          6 :     orc::ThreadSafeModule backing;
     233         [ +  - ]:          6 :     if (into == NULL) {
     234         [ +  - ]:          6 :         if (!pparams) {
     235                 :          6 :             ctx = jl_ExecutionEngine->acquireContext();
     236                 :            :         }
     237   [ -  +  -  + ]:         12 :         backing = jl_create_llvm_module("cextern", pparams ? pparams->tsctx : ctx, pparams ? pparams->imaging : imaging_default());
     238                 :          6 :         into = &backing;
     239                 :            :     }
     240                 :          6 :     jl_codegen_params_t params(into->getContext());
     241         [ +  - ]:          6 :     if (pparams == NULL)
     242                 :          6 :         pparams = &params;
     243         [ -  + ]:          6 :     assert(pparams->tsctx.getContext() == into->getContext().getContext());
     244                 :          6 :     const char *name = jl_generate_ccallable(wrap(into), sysimg, declrt, sigt, *pparams);
     245                 :          6 :     bool success = true;
     246         [ +  - ]:          6 :     if (!sysimg) {
     247         [ +  + ]:          6 :         if (jl_ExecutionEngine->getGlobalValueAddress(name)) {
     248                 :          2 :             success = false;
     249                 :            :         }
     250   [ +  +  +  - ]:          6 :         if (success && p == NULL) {
     251                 :          4 :             jl_jit_globals(params.globals);
     252         [ -  + ]:          4 :             assert(params.workqueue.empty());
     253         [ -  + ]:          4 :             if (params._shared_module)
     254                 :          0 :                 jl_ExecutionEngine->addModule(std::move(params._shared_module));
     255                 :            :         }
     256   [ +  +  +  - ]:          6 :         if (success && llvmmod == NULL)
     257                 :          4 :             jl_ExecutionEngine->addModule(std::move(*into));
     258                 :            :     }
     259   [ +  -  -  + ]:          6 :     if (jl_codegen_lock.count == 1 && measure_compile_time_enabled)
     260                 :          0 :         jl_atomic_fetch_add_relaxed(&jl_cumulative_compile_time, (jl_hrtime() - compiler_start_time));
     261         [ +  - ]:          6 :     if (ctx.getContext()) {
     262                 :          6 :         jl_ExecutionEngine->releaseContext(std::move(ctx));
     263                 :            :     }
     264                 :          6 :     JL_UNLOCK(&jl_codegen_lock);
     265                 :          6 :     return success;
     266                 :          6 : }
     267                 :            : 
     268                 :            : // declare a C-callable entry point; called during code loading from the toplevel
     269                 :            : extern "C" JL_DLLEXPORT
     270                 :          4 : void jl_extern_c_impl(jl_value_t *declrt, jl_tupletype_t *sigt)
     271                 :            : {
     272                 :            :     // validate arguments. try to do as many checks as possible here to avoid
     273                 :            :     // throwing errors later during codegen.
     274         [ -  + ]:          4 :     JL_TYPECHK(@ccallable, type, declrt);
     275         [ -  + ]:          4 :     if (!jl_is_tuple_type(sigt))
     276                 :          0 :         jl_type_error("@ccallable", (jl_value_t*)jl_anytuple_type_type, (jl_value_t*)sigt);
     277                 :            :     // check that f is a guaranteed singleton type
     278                 :          4 :     jl_datatype_t *ft = (jl_datatype_t*)jl_tparam0(sigt);
     279   [ +  -  -  + ]:          4 :     if (!jl_is_datatype(ft) || ft->instance == NULL)
     280                 :          0 :         jl_error("@ccallable: function object must be a singleton");
     281                 :            : 
     282                 :            :     // compute / validate return type
     283   [ +  -  -  +  :          4 :     if (!jl_is_concrete_type(declrt) || jl_is_kind(declrt))
                   -  + ]
     284                 :          0 :         jl_error("@ccallable: return type must be concrete and correspond to a C type");
     285         [ -  + ]:          4 :     if (!jl_type_mappable_to_c(declrt))
     286                 :          0 :         jl_error("@ccallable: return type doesn't correspond to a C type");
     287                 :            : 
     288                 :            :     // validate method signature
     289                 :          4 :     size_t i, nargs = jl_nparams(sigt);
     290         [ +  + ]:          6 :     for (i = 1; i < nargs; i++) {
     291                 :          2 :         jl_value_t *ati = jl_tparam(sigt, i);
     292   [ +  -  +  -  :          2 :         if (!jl_is_concrete_type(ati) || jl_is_kind(ati) || !jl_type_mappable_to_c(ati))
             -  +  -  + ]
     293                 :          0 :             jl_error("@ccallable: argument types must be concrete");
     294                 :            :     }
     295                 :            : 
     296                 :            :     // save a record of this so that the alias is generated when we write an object file
     297                 :          4 :     jl_method_t *meth = (jl_method_t*)jl_methtable_lookup(ft->name->mt, (jl_value_t*)sigt, jl_atomic_load_acquire(&jl_world_counter));
     298         [ -  + ]:          4 :     if (!jl_is_method(meth))
     299                 :          0 :         jl_error("@ccallable: could not find requested method");
     300                 :          4 :     JL_GC_PUSH1(&meth);
     301                 :          4 :     meth->ccallable = jl_svec2(declrt, (jl_value_t*)sigt);
     302                 :          4 :     jl_gc_wb(meth, meth->ccallable);
     303                 :          4 :     JL_GC_POP();
     304                 :            : 
     305                 :            :     // create the alias in the current runtime environment
     306                 :          4 :     int success = jl_compile_extern_c(NULL, NULL, NULL, declrt, (jl_value_t*)sigt);
     307         [ +  + ]:          4 :     if (!success)
     308                 :          1 :         jl_error("@ccallable was already defined for this method name");
     309                 :          3 : }
     310                 :            : 
     311                 :            : // this compiles li and emits fptr
     312                 :            : extern "C" JL_DLLEXPORT
     313                 :   81403900 : jl_code_instance_t *jl_generate_fptr_impl(jl_method_instance_t *mi JL_PROPAGATES_ROOT, size_t world)
     314                 :            : {
     315                 :   81403900 :     JL_LOCK(&jl_codegen_lock); // also disables finalizers, to prevent any unexpected recursion
     316                 :   81403900 :     auto ctx = jl_ExecutionEngine->getContext();
     317                 :   81403900 :     auto &context = *ctx;
     318                 :   81403900 :     uint64_t compiler_start_time = 0;
     319                 :   81403900 :     uint8_t measure_compile_time_enabled = jl_atomic_load_relaxed(&jl_measure_compile_time_enabled);
     320                 :   81403900 :     bool is_recompile = false;
     321         [ +  + ]:   81403900 :     if (measure_compile_time_enabled)
     322                 :          7 :         compiler_start_time = jl_hrtime();
     323                 :            :     // if we don't have any decls already, try to generate it now
     324                 :   81403900 :     jl_code_info_t *src = NULL;
     325                 :   81403900 :     JL_GC_PUSH1(&src);
     326                 :   81403900 :     jl_value_t *ci = jl_rettype_inferred(mi, world, world);
     327         [ +  + ]:   81403900 :     jl_code_instance_t *codeinst = (ci == jl_nothing ? NULL : (jl_code_instance_t*)ci);
     328         [ +  + ]:   81403900 :     if (codeinst) {
     329                 :      58281 :         src = (jl_code_info_t*)codeinst->inferred;
     330         [ +  + ]:      58281 :         if ((jl_value_t*)src == jl_nothing)
     331                 :       4443 :             src = NULL;
     332         [ +  + ]:      53838 :         else if (jl_is_method(mi->def.method))
     333                 :      52828 :             src = jl_uncompress_ir(mi->def.method, codeinst, (jl_array_t*)src);
     334                 :            :     }
     335                 :            :     else {
     336                 :            :         // identify whether this is an invalidated method that is being recompiled
     337                 :   81345700 :         is_recompile = jl_atomic_load_relaxed(&mi->cache) != NULL;
     338                 :            :     }
     339   [ +  +  +  +  :  162754000 :     if (src == NULL && jl_is_method(mi->def.method) &&
                   +  + ]
     340         [ +  + ]:   81350000 :              jl_symbol_name(mi->def.method->name)[0] != '@') {
     341         [ +  - ]:   81265200 :         if (mi->def.method->source != jl_nothing) {
     342                 :            :             // If the caller didn't provide the source and IR is available,
     343                 :            :             // see if it is inferred, or try to infer it for ourself.
     344                 :            :             // (but don't bother with typeinf on macros or toplevel thunks)
     345                 :   81265200 :             src = jl_type_infer(mi, world, 0);
     346                 :            :         }
     347                 :            :     }
     348                 :   81403900 :     jl_code_instance_t *compiled = jl_method_compiled(mi, world);
     349         [ +  + ]:   81403900 :     if (compiled) {
     350                 :       8929 :         codeinst = compiled;
     351                 :            :     }
     352   [ +  +  +  - ]:   81395000 :     else if (src && jl_is_code_info(src)) {
     353         [ +  + ]:     185181 :         if (!codeinst) {
     354                 :     131339 :             codeinst = jl_get_method_inferred(mi, src->rettype, src->min_world, src->max_world);
     355   [ +  -  -  + ]:     131339 :             if (src->inferred && !codeinst->inferred)
     356                 :          0 :                 codeinst->inferred = jl_nothing;
     357                 :            :         }
     358                 :     185181 :         _jl_compile_codeinst(codeinst, src, world, context);
     359         [ -  + ]:     185170 :         if (jl_atomic_load_relaxed(&codeinst->invoke) == NULL)
     360                 :          0 :             codeinst = NULL;
     361                 :            :     }
     362                 :            :     else {
     363                 :   81209800 :         codeinst = NULL;
     364                 :            :     }
     365   [ +  +  +  + ]:   81403900 :     if (jl_codegen_lock.count == 1 && measure_compile_time_enabled) {
     366                 :          7 :         uint64_t t_comp = jl_hrtime() - compiler_start_time;
     367         [ +  + ]:          7 :         if (is_recompile)
     368                 :          1 :             jl_atomic_fetch_add_relaxed(&jl_cumulative_recompile_time, t_comp);
     369                 :          7 :         jl_atomic_fetch_add_relaxed(&jl_cumulative_compile_time, t_comp);
     370                 :            :     }
     371                 :   81403900 :     JL_UNLOCK(&jl_codegen_lock);
     372                 :   81403900 :     JL_GC_POP();
     373                 :   81403900 :     return codeinst;
     374                 :            : }
     375                 :            : 
     376                 :            : extern "C" JL_DLLEXPORT
     377                 :       3146 : void jl_generate_fptr_for_unspecialized_impl(jl_code_instance_t *unspec)
     378                 :            : {
     379         [ -  + ]:       3146 :     if (jl_atomic_load_relaxed(&unspec->invoke) != NULL) {
     380                 :          0 :         return;
     381                 :            :     }
     382                 :       3146 :     JL_LOCK(&jl_codegen_lock);
     383                 :       6284 :     auto ctx = jl_ExecutionEngine->getContext();
     384                 :       3146 :     auto &context = *ctx;
     385                 :       3146 :     uint64_t compiler_start_time = 0;
     386                 :       3146 :     uint8_t measure_compile_time_enabled = jl_atomic_load_relaxed(&jl_measure_compile_time_enabled);
     387         [ -  + ]:       3146 :     if (measure_compile_time_enabled)
     388                 :          0 :         compiler_start_time = jl_hrtime();
     389         [ +  - ]:       3146 :     if (jl_atomic_load_relaxed(&unspec->invoke) == NULL) {
     390                 :       3146 :         jl_code_info_t *src = NULL;
     391                 :       3146 :         JL_GC_PUSH1(&src);
     392                 :       3146 :         jl_method_t *def = unspec->def->def.method;
     393         [ +  + ]:       3146 :         if (jl_is_method(def)) {
     394                 :       3045 :             src = (jl_code_info_t*)def->source;
     395         [ +  + ]:       3045 :             if (src == NULL) {
     396                 :            :                 // TODO: this is wrong
     397         [ -  + ]:          8 :                 assert(def->generator);
     398                 :            :                 // TODO: jl_code_for_staged can throw
     399                 :          8 :                 src = jl_code_for_staged(unspec->def);
     400                 :            :             }
     401   [ +  -  +  - ]:       3037 :             if (src && (jl_value_t*)src != jl_nothing)
     402                 :       3037 :                 src = jl_uncompress_ir(def, NULL, (jl_array_t*)src);
     403                 :            :         }
     404                 :            :         else {
     405                 :        101 :             src = (jl_code_info_t*)unspec->def->uninferred;
     406                 :            :         }
     407   [ +  -  +  - ]:       3138 :         assert(src && jl_is_code_info(src));
     408                 :       3138 :         _jl_compile_codeinst(unspec, src, unspec->min_world, context);
     409         [ -  + ]:       3138 :         if (jl_atomic_load_relaxed(&unspec->invoke) == NULL) {
     410                 :            :             // if we hit a codegen bug (or ran into a broken generated function or llvmcall), fall back to the interpreter as a last resort
     411                 :          0 :             jl_atomic_store_release(&unspec->invoke, jl_fptr_interpret_call_addr);
     412                 :            :         }
     413                 :       3138 :         JL_GC_POP();
     414                 :            :     }
     415   [ +  +  -  + ]:       3138 :     if (jl_codegen_lock.count == 1 && measure_compile_time_enabled)
     416                 :          0 :         jl_atomic_fetch_add_relaxed(&jl_cumulative_compile_time, (jl_hrtime() - compiler_start_time));
     417                 :       3138 :     JL_UNLOCK(&jl_codegen_lock); // Might GC
     418                 :            : }
     419                 :            : 
     420                 :            : 
     421                 :            : // get a native disassembly for a compiled method
     422                 :            : extern "C" JL_DLLEXPORT
     423                 :          3 : jl_value_t *jl_dump_method_asm_impl(jl_method_instance_t *mi, size_t world,
     424                 :            :         char raw_mc, char getwrapper, const char* asm_variant, const char *debuginfo, char binary)
     425                 :            : {
     426                 :            :     // printing via disassembly
     427                 :          3 :     jl_code_instance_t *codeinst = jl_generate_fptr(mi, world);
     428         [ +  - ]:          3 :     if (codeinst) {
     429                 :          3 :         uintptr_t fptr = (uintptr_t)jl_atomic_load_relaxed(&codeinst->invoke);
     430         [ -  + ]:          3 :         if (getwrapper)
     431                 :          0 :             return jl_dump_fptr_asm(fptr, raw_mc, asm_variant, debuginfo, binary);
     432                 :          3 :         uintptr_t specfptr = (uintptr_t)jl_atomic_load_relaxed(&codeinst->specptr.fptr);
     433   [ +  -  +  + ]:          3 :         if (fptr == (uintptr_t)jl_fptr_const_return_addr && specfptr == 0) {
     434                 :            :             // normally we prevent native code from being generated for these functions,
     435                 :            :             // (using sentinel value `1` instead)
     436                 :            :             // so create an exception here so we can print pretty our lies
     437                 :          1 :             JL_LOCK(&jl_codegen_lock); // also disables finalizers, to prevent any unexpected recursion
     438                 :          2 :             auto ctx = jl_ExecutionEngine->getContext();
     439                 :          1 :             auto &context = *ctx;
     440                 :          1 :             uint64_t compiler_start_time = 0;
     441                 :          1 :             uint8_t measure_compile_time_enabled = jl_atomic_load_relaxed(&jl_measure_compile_time_enabled);
     442         [ -  + ]:          1 :             if (measure_compile_time_enabled)
     443                 :          0 :                 compiler_start_time = jl_hrtime();
     444                 :          1 :             specfptr = (uintptr_t)jl_atomic_load_relaxed(&codeinst->specptr.fptr);
     445         [ +  - ]:          1 :             if (specfptr == 0) {
     446                 :          1 :                 jl_code_info_t *src = jl_type_infer(mi, world, 0);
     447                 :          1 :                 JL_GC_PUSH1(&src);
     448                 :          1 :                 jl_method_t *def = mi->def.method;
     449         [ +  - ]:          1 :                 if (jl_is_method(def)) {
     450         [ -  + ]:          1 :                     if (!src) {
     451                 :            :                         // TODO: jl_code_for_staged can throw
     452         [ #  # ]:          0 :                         src = def->generator ? jl_code_for_staged(mi) : (jl_code_info_t*)def->source;
     453                 :            :                     }
     454   [ +  -  +  - ]:          1 :                     if (src && (jl_value_t*)src != jl_nothing)
     455                 :          1 :                         src = jl_uncompress_ir(mi->def.method, codeinst, (jl_array_t*)src);
     456                 :            :                 }
     457                 :          1 :                 fptr = (uintptr_t)jl_atomic_load_relaxed(&codeinst->invoke);
     458                 :          1 :                 specfptr = (uintptr_t)jl_atomic_load_relaxed(&codeinst->specptr.fptr);
     459   [ +  -  +  - ]:          1 :                 if (src && jl_is_code_info(src)) {
     460   [ +  -  +  - ]:          1 :                     if (fptr == (uintptr_t)jl_fptr_const_return_addr && specfptr == 0) {
     461                 :          1 :                         fptr = (uintptr_t)_jl_compile_codeinst(codeinst, src, world, context);
     462                 :          1 :                         specfptr = (uintptr_t)jl_atomic_load_relaxed(&codeinst->specptr.fptr);
     463                 :            :                     }
     464                 :            :                 }
     465                 :          1 :                 JL_GC_POP();
     466                 :            :             }
     467         [ -  + ]:          1 :             if (measure_compile_time_enabled)
     468                 :          0 :                 jl_atomic_fetch_add_relaxed(&jl_cumulative_compile_time, (jl_hrtime() - compiler_start_time));
     469                 :          1 :             JL_UNLOCK(&jl_codegen_lock);
     470                 :            :         }
     471         [ +  - ]:          3 :         if (specfptr != 0)
     472                 :          3 :             return jl_dump_fptr_asm(specfptr, raw_mc, asm_variant, debuginfo, binary);
     473                 :            :     }
     474                 :            : 
     475                 :            :     // whatever, that didn't work - use the assembler output instead
     476                 :            :     jl_llvmf_dump_t llvmf_dump;
     477                 :          0 :     jl_get_llvmf_defn(&llvmf_dump, mi, world, getwrapper, true, jl_default_cgparams);
     478         [ #  # ]:          0 :     if (!llvmf_dump.F)
     479                 :          0 :         return jl_an_empty_string;
     480                 :          0 :     return jl_dump_function_asm(&llvmf_dump, raw_mc, asm_variant, debuginfo, binary);
     481                 :            : }
     482                 :            : 
     483                 :       5103 : CodeGenOpt::Level CodeGenOptLevelFor(int optlevel)
     484                 :            : {
     485                 :            : #ifdef DISABLE_OPT
     486                 :            :     return CodeGenOpt::None;
     487                 :            : #else
     488         [ +  + ]:       7846 :     return optlevel < 2 ? CodeGenOpt::None :
     489         [ +  + ]:       2743 :         optlevel == 2 ? CodeGenOpt::Default :
     490                 :       5103 :         CodeGenOpt::Aggressive;
     491                 :            : #endif
     492                 :            : }
     493                 :            : 
     494                 :          2 : static auto countBasicBlocks(const Function &F)
     495                 :            : {
     496                 :          2 :     return std::distance(F.begin(), F.end());
     497                 :            : }
     498                 :            : 
     499                 :     334404 : void JuliaOJIT::OptSelLayerT::emit(std::unique_ptr<orc::MaterializationResponsibility> R, orc::ThreadSafeModule TSM) {
     500                 :     334404 :     size_t optlevel = SIZE_MAX;
     501                 :     334404 :     TSM.withModuleDo([&](Module &M) {
     502         [ +  + ]:     334404 :         if (jl_generating_output()) {
     503                 :      15065 :             optlevel = 0;
     504                 :            :         }
     505                 :            :         else {
     506                 :     319339 :             optlevel = std::max(static_cast<int>(jl_options.opt_level), 0);
     507                 :     319339 :             size_t optlevel_min = std::max(static_cast<int>(jl_options.opt_level_min), 0);
     508         [ +  + ]:    3835040 :             for (auto &F : M.functions()) {
     509         [ +  + ]:    3515700 :                 if (!F.getBasicBlockList().empty()) {
     510                 :     633657 :                     Attribute attr = F.getFnAttribute("julia-optimization-level");
     511                 :     633657 :                     StringRef val = attr.getValueAsString();
     512         [ +  + ]:     633657 :                     if (val != "") {
     513                 :       2227 :                         size_t ol = (size_t)val[0] - '0';
     514         [ +  + ]:       2227 :                         if (ol < optlevel)
     515                 :       1933 :                             optlevel = ol;
     516                 :            :                     }
     517                 :            :                 }
     518                 :            :             }
     519                 :     319339 :             optlevel = std::min(std::max(optlevel, optlevel_min), this->count);
     520                 :            :         }
     521                 :     334404 :     });
     522         [ -  + ]:     334404 :     assert(optlevel != SIZE_MAX && "Failed to select a valid optimization level!");
     523                 :     334404 :     this->optimizers[optlevel]->OptimizeLayer.emit(std::move(R), std::move(TSM));
     524                 :     334403 : }
     525                 :            : 
     526                 :            : void jl_register_jit_object(const object::ObjectFile &debugObj,
     527                 :            :                             std::function<uint64_t(const StringRef &)> getLoadAddress,
     528                 :            :                             std::function<void *(void *)> lookupWriteAddress);
     529                 :            : 
     530                 :            : #ifdef JL_USE_JITLINK
     531                 :            : 
     532                 :            : namespace {
     533                 :            : 
     534                 :            : using namespace llvm::orc;
     535                 :            : 
     536                 :            : struct JITObjectInfo {
     537                 :            :     std::unique_ptr<MemoryBuffer> BackingBuffer;
     538                 :            :     std::unique_ptr<object::ObjectFile> Object;
     539                 :            :     StringMap<uint64_t> SectionLoadAddresses;
     540                 :            : };
     541                 :            : 
     542                 :            : class JLDebuginfoPlugin : public ObjectLinkingLayer::Plugin {
     543                 :            :     std::map<MaterializationResponsibility *, std::unique_ptr<JITObjectInfo>> PendingObjs;
     544                 :            :     // Resources from distinct MaterializationResponsibilitys can get merged
     545                 :            :     // after emission, so we can have multiple debug objects per resource key.
     546                 :            :     std::map<ResourceKey, std::vector<std::unique_ptr<JITObjectInfo>>> RegisteredObjs;
     547                 :            : 
     548                 :            : public:
     549                 :            :     void notifyMaterializing(MaterializationResponsibility &MR, jitlink::LinkGraph &G,
     550                 :            :                              jitlink::JITLinkContext &Ctx,
     551                 :            :                              MemoryBufferRef InputObject) override
     552                 :            :     {
     553                 :            :         // Keeping around a full copy of the input object file (and re-parsing it) is
     554                 :            :         // wasteful, but for now, this lets us reuse the existing debuginfo.cpp code.
     555                 :            :         // Should look into just directly pulling out all the information required in
     556                 :            :         // a JITLink pass and just keeping the required tables/DWARF sections around
     557                 :            :         // (perhaps using the LLVM DebuggerSupportPlugin as a reference).
     558                 :            :         auto NewBuffer =
     559                 :            :             MemoryBuffer::getMemBufferCopy(InputObject.getBuffer(), G.getName());
     560                 :            :         auto NewObj =
     561                 :            :             cantFail(object::ObjectFile::createObjectFile(NewBuffer->getMemBufferRef()));
     562                 :            : 
     563                 :            :         assert(PendingObjs.count(&MR) == 0);
     564                 :            :         PendingObjs[&MR] = std::unique_ptr<JITObjectInfo>(
     565                 :            :             new JITObjectInfo{std::move(NewBuffer), std::move(NewObj), {}});
     566                 :            :     }
     567                 :            : 
     568                 :            :     Error notifyEmitted(MaterializationResponsibility &MR) override
     569                 :            :     {
     570                 :            :         auto It = PendingObjs.find(&MR);
     571                 :            :         if (It == PendingObjs.end())
     572                 :            :             return Error::success();
     573                 :            : 
     574                 :            :         auto NewInfo = PendingObjs[&MR].get();
     575                 :            :         auto getLoadAddress = [NewInfo](const StringRef &Name) -> uint64_t {
     576                 :            :             auto result = NewInfo->SectionLoadAddresses.find(Name);
     577                 :            :             if (result == NewInfo->SectionLoadAddresses.end()) {
     578                 :            :                 LLVM_DEBUG({
     579                 :            :                     dbgs() << "JLDebuginfoPlugin: No load address found for section '"
     580                 :            :                            << Name << "'\n";
     581                 :            :                 });
     582                 :            :                 return 0;
     583                 :            :             }
     584                 :            :             return result->second;
     585                 :            :         };
     586                 :            : 
     587                 :            :         jl_register_jit_object(*NewInfo->Object, getLoadAddress, nullptr);
     588                 :            : 
     589                 :            :         cantFail(MR.withResourceKeyDo([&](ResourceKey K) {
     590                 :            :             RegisteredObjs[K].push_back(std::move(PendingObjs[&MR]));
     591                 :            :             PendingObjs.erase(&MR);
     592                 :            :         }));
     593                 :            : 
     594                 :            :         return Error::success();
     595                 :            :     }
     596                 :            : 
     597                 :            :     Error notifyFailed(MaterializationResponsibility &MR) override
     598                 :            :     {
     599                 :            :         PendingObjs.erase(&MR);
     600                 :            :         return Error::success();
     601                 :            :     }
     602                 :            : 
     603                 :            :     Error notifyRemovingResources(ResourceKey K) override
     604                 :            :     {
     605                 :            :         RegisteredObjs.erase(K);
     606                 :            :         // TODO: If we ever unload code, need to notify debuginfo registry.
     607                 :            :         return Error::success();
     608                 :            :     }
     609                 :            : 
     610                 :            :     void notifyTransferringResources(ResourceKey DstKey, ResourceKey SrcKey) override
     611                 :            :     {
     612                 :            :         auto SrcIt = RegisteredObjs.find(SrcKey);
     613                 :            :         if (SrcIt != RegisteredObjs.end()) {
     614                 :            :             for (std::unique_ptr<JITObjectInfo> &Info : SrcIt->second)
     615                 :            :                 RegisteredObjs[DstKey].push_back(std::move(Info));
     616                 :            :             RegisteredObjs.erase(SrcIt);
     617                 :            :         }
     618                 :            :     }
     619                 :            : 
     620                 :            :     void modifyPassConfig(MaterializationResponsibility &MR, jitlink::LinkGraph &,
     621                 :            :                           jitlink::PassConfiguration &PassConfig) override
     622                 :            :     {
     623                 :            :         auto It = PendingObjs.find(&MR);
     624                 :            :         if (It == PendingObjs.end())
     625                 :            :             return;
     626                 :            : 
     627                 :            :         JITObjectInfo &Info = *It->second;
     628                 :            :         PassConfig.PostAllocationPasses.push_back([&Info](jitlink::LinkGraph &G) -> Error {
     629                 :            :             for (const jitlink::Section &Sec : G.sections()) {
     630                 :            :                 // Canonical JITLink section names have the segment name included, e.g.
     631                 :            :                 // "__TEXT,__text" or "__DWARF,__debug_str". There are some special internal
     632                 :            :                 // sections without a comma separator, which we can just ignore.
     633                 :            :                 size_t SepPos = Sec.getName().find(',');
     634                 :            :                 if (SepPos >= 16 || (Sec.getName().size() - (SepPos + 1) > 16)) {
     635                 :            :                     LLVM_DEBUG({
     636                 :            :                         dbgs() << "JLDebuginfoPlugin: Ignoring section '" << Sec.getName()
     637                 :            :                                << "'\n";
     638                 :            :                     });
     639                 :            :                     continue;
     640                 :            :                 }
     641                 :            :                 auto SecName = Sec.getName().substr(SepPos + 1);
     642                 :            :                 // https://github.com/llvm/llvm-project/commit/118e953b18ff07d00b8f822dfbf2991e41d6d791
     643                 :            : #if JL_LLVM_VERSION >= 140000
     644                 :            :                Info.SectionLoadAddresses[SecName] = jitlink::SectionRange(Sec).getStart().getValue();
     645                 :            : #else
     646                 :            :                Info.SectionLoadAddresses[SecName] = jitlink::SectionRange(Sec).getStart();
     647                 :            : #endif
     648                 :            :             }
     649                 :            :             return Error::success();
     650                 :            :         });
     651                 :            :     }
     652                 :            : };
     653                 :            : }
     654                 :            : 
     655                 :            : # ifdef LLVM_SHLIB
     656                 :            : 
     657                 :            : #  if JL_LLVM_VERSION >= 140000
     658                 :            : #   define EHFRAME_RANGE(name) orc::ExecutorAddrRange name
     659                 :            : #   define UNPACK_EHFRAME_RANGE(name) \
     660                 :            :         name.Start.toPtr<uint8_t *>(), \
     661                 :            :         static_cast<size_t>(name.size())
     662                 :            : #  else
     663                 :            : #   define EHFRAME_RANGE(name) JITTargetAddress name##Addr, size_t name##Size
     664                 :            : #   define UNPACK_EHFRAME_RANGE(name) \
     665                 :            :         jitTargetAddressToPointer<uint8_t *>(name##Addr), \
     666                 :            :         name##Size
     667                 :            : #  endif
     668                 :            : 
     669                 :            : class JLEHFrameRegistrar final : public jitlink::EHFrameRegistrar {
     670                 :            : public:
     671                 :            :     Error registerEHFrames(EHFRAME_RANGE(EHFrameSection)) override {
     672                 :            :         register_eh_frames(
     673                 :            :             UNPACK_EHFRAME_RANGE(EHFrameSection));
     674                 :            :         return Error::success();
     675                 :            :     }
     676                 :            : 
     677                 :            :     Error deregisterEHFrames(EHFRAME_RANGE(EHFrameSection)) override {
     678                 :            :         deregister_eh_frames(
     679                 :            :             UNPACK_EHFRAME_RANGE(EHFrameSection));
     680                 :            :         return Error::success();
     681                 :            :     }
     682                 :            : };
     683                 :            : # endif
     684                 :            : 
     685                 :            : #else // !JL_USE_JITLINK
     686                 :            : 
     687                 :            : RTDyldMemoryManager* createRTDyldMemoryManager(void);
     688                 :            : 
     689                 :            : // A simple forwarding class, since OrcJIT v2 needs a unique_ptr, while we have a shared_ptr
     690                 :            : class ForwardingMemoryManager : public RuntimeDyld::MemoryManager {
     691                 :            : private:
     692                 :            :     std::shared_ptr<RuntimeDyld::MemoryManager> MemMgr;
     693                 :            : 
     694                 :            : public:
     695                 :     334403 :     ForwardingMemoryManager(std::shared_ptr<RuntimeDyld::MemoryManager> MemMgr) : MemMgr(MemMgr) {}
     696                 :          0 :     virtual ~ForwardingMemoryManager() = default;
     697                 :     334380 :     virtual uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment,
     698                 :            :                                      unsigned SectionID,
     699                 :            :                                      StringRef SectionName) override {
     700                 :     334380 :         return MemMgr->allocateCodeSection(Size, Alignment, SectionID, SectionName);
     701                 :            :     }
     702                 :     454179 :     virtual uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment,
     703                 :            :                                      unsigned SectionID,
     704                 :            :                                      StringRef SectionName,
     705                 :            :                                      bool IsReadOnly) override {
     706                 :     454179 :         return MemMgr->allocateDataSection(Size, Alignment, SectionID, SectionName, IsReadOnly);
     707                 :            :     }
     708                 :          0 :     virtual void reserveAllocationSpace(uintptr_t CodeSize, uint32_t CodeAlign,
     709                 :            :                                         uintptr_t RODataSize,
     710                 :            :                                         uint32_t RODataAlign,
     711                 :            :                                         uintptr_t RWDataSize,
     712                 :            :                                         uint32_t RWDataAlign) override {
     713                 :          0 :         return MemMgr->reserveAllocationSpace(CodeSize, CodeAlign, RODataSize, RODataAlign, RWDataSize, RWDataAlign);
     714                 :            :     }
     715                 :     334403 :     virtual bool needsToReserveAllocationSpace() override {
     716                 :     334403 :         return MemMgr->needsToReserveAllocationSpace();
     717                 :            :     }
     718                 :     334380 :     virtual void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr,
     719                 :            :                                   size_t Size) override {
     720                 :     334380 :         return MemMgr->registerEHFrames(Addr, LoadAddr, Size);
     721                 :            :     }
     722                 :          0 :     virtual void deregisterEHFrames() override {
     723                 :          0 :         return MemMgr->deregisterEHFrames();
     724                 :            :     }
     725                 :     334403 :     virtual bool finalizeMemory(std::string *ErrMsg = nullptr) override {
     726                 :     334403 :         return MemMgr->finalizeMemory(ErrMsg);
     727                 :            :     }
     728                 :     334403 :     virtual void notifyObjectLoaded(RuntimeDyld &RTDyld,
     729                 :            :                                     const object::ObjectFile &Obj) override {
     730                 :     334403 :         return MemMgr->notifyObjectLoaded(RTDyld, Obj);
     731                 :            :     }
     732                 :            : };
     733                 :            : 
     734                 :            : 
     735                 :            : #if defined(_OS_WINDOWS_) && defined(_CPU_X86_64_)
     736                 :            : void *lookupWriteAddressFor(RTDyldMemoryManager *MemMgr, void *rt_addr);
     737                 :            : #endif
     738                 :            : 
     739                 :     334403 : void registerRTDyldJITObject(const object::ObjectFile &Object,
     740                 :            :                              const RuntimeDyld::LoadedObjectInfo &L,
     741                 :            :                              const std::shared_ptr<RTDyldMemoryManager> &MemMgr)
     742                 :            : {
     743                 :     668806 :     auto SavedObject = L.getObjectForDebug(Object).takeBinary();
     744                 :            :     // If the debug object is unavailable, save (a copy of) the original object
     745                 :            :     // for our backtraces.
     746                 :            :     // This copy seems unfortunate, but there doesn't seem to be a way to take
     747                 :            :     // ownership of the original buffer.
     748         [ -  + ]:     334403 :     if (!SavedObject.first) {
     749                 :            :         auto NewBuffer =
     750                 :          0 :             MemoryBuffer::getMemBufferCopy(Object.getData(), Object.getFileName());
     751                 :            :         auto NewObj =
     752                 :          0 :             cantFail(object::ObjectFile::createObjectFile(NewBuffer->getMemBufferRef()));
     753                 :          0 :         SavedObject = std::make_pair(std::move(NewObj), std::move(NewBuffer));
     754                 :            :     }
     755                 :     334403 :     const object::ObjectFile *DebugObj = SavedObject.first.release();
     756                 :     334403 :     SavedObject.second.release();
     757                 :            : 
     758                 :     668806 :     StringMap<object::SectionRef> loadedSections;
     759                 :            :     // Use the original Object, not the DebugObject, as this is used for the
     760                 :            :     // RuntimeDyld::LoadedObjectInfo lookup.
     761         [ +  + ]:    6912650 :     for (const object::SectionRef &lSection : Object.sections()) {
     762                 :   13156500 :         auto sName = lSection.getName();
     763         [ +  - ]:    6578250 :         if (sName) {
     764                 :    6578250 :             bool inserted = loadedSections.insert(std::make_pair(*sName, lSection)).second;
     765         [ -  + ]:    6578250 :             assert(inserted);
     766                 :            :             (void)inserted;
     767                 :            :         }
     768                 :            :     }
     769                 :     334403 :     auto getLoadAddress = [loadedSections = std::move(loadedSections),
     770                 :     660334 :                            &L](const StringRef &sName) -> uint64_t {
     771                 :     660334 :         auto search = loadedSections.find(sName);
     772         [ -  + ]:     660334 :         if (search == loadedSections.end())
     773                 :          0 :             return 0;
     774                 :     660334 :         return L.getSectionLoadAddress(search->second);
     775                 :     334403 :     };
     776                 :            : 
     777                 :     334403 :     jl_register_jit_object(*DebugObj, getLoadAddress,
     778                 :            : #if defined(_OS_WINDOWS_) && defined(_CPU_X86_64_)
     779                 :            :         [MemMgr](void *p) { return lookupWriteAddressFor(MemMgr.get(), p); }
     780                 :            : #else
     781                 :            :         nullptr
     782                 :            : #endif
     783                 :            :     );
     784                 :     334403 : }
     785                 :            : #endif
     786                 :            : namespace {
     787                 :        567 :     std::unique_ptr<TargetMachine> createTargetMachine() {
     788                 :            : 
     789                 :       1134 :         TargetOptions options = TargetOptions();
     790                 :            : #if defined(_OS_WINDOWS_)
     791                 :            :         // use ELF because RuntimeDyld COFF i686 support didn't exist
     792                 :            :         // use ELF because RuntimeDyld COFF X86_64 doesn't seem to work (fails to generate function pointers)?
     793                 :            : #define FORCE_ELF
     794                 :            : #endif
     795                 :            :         //options.PrintMachineCode = true; //Print machine code produced during JIT compiling
     796                 :            : #if defined(_OS_WINDOWS_) && !defined(_CPU_X86_64_) && JL_LLVM_VERSION < 130000
     797                 :            :         // tell Win32 to assume the stack is always 16-byte aligned,
     798                 :            :         // and to ensure that it is 16-byte aligned for out-going calls,
     799                 :            :         // to ensure compatibility with GCC codes
     800                 :            :         // In LLVM 13 and onwards this has turned into a module option
     801                 :            :         options.StackAlignmentOverride = 16;
     802                 :            : #endif
     803                 :            : #if defined(JL_DEBUG_BUILD) && JL_LLVM_VERSION < 130000
     804                 :            :         // LLVM defaults to tls stack guard, which causes issues with Julia's tls implementation
     805                 :            :         options.StackProtectorGuard = StackProtectorGuards::Global;
     806                 :            : #endif
     807                 :       1134 :         Triple TheTriple(sys::getProcessTriple());
     808                 :            : #if defined(FORCE_ELF)
     809                 :            :         TheTriple.setObjectFormat(Triple::ELF);
     810                 :            : #endif
     811                 :        567 :         uint32_t target_flags = 0;
     812                 :       1134 :         auto target = jl_get_llvm_target(imaging_default(), target_flags);
     813                 :        567 :         auto &TheCPU = target.first;
     814                 :       1134 :         SmallVector<std::string, 10> targetFeatures(target.second.begin(), target.second.end());
     815                 :       1134 :         std::string errorstr;
     816                 :        567 :         const Target *TheTarget = TargetRegistry::lookupTarget("", TheTriple, errorstr);
     817         [ -  + ]:        567 :         if (!TheTarget) {
     818                 :            :             // Note we are explicitly not using `jl_errorf()` here, as it will attempt to
     819                 :            :             // collect a backtrace, but we're too early in LLVM initialization for that.
     820                 :          0 :             jl_printf(JL_STDERR, "ERROR: %s", errorstr.c_str());
     821                 :          0 :             exit(1);
     822                 :            :         }
     823   [ +  -  -  + ]:        567 :         if (jl_processor_print_help || (target_flags & JL_TARGET_UNKNOWN_NAME)) {
     824                 :            :             std::unique_ptr<MCSubtargetInfo> MSTI(
     825                 :          0 :                 TheTarget->createMCSubtargetInfo(TheTriple.str(), "", ""));
     826         [ #  # ]:          0 :             if (!MSTI->isCPUStringValid(TheCPU)) {
     827                 :            :                 // Same as above, we are too early to use `jl_errorf()` here.
     828                 :          0 :                 jl_printf(JL_STDERR, "ERROR: Invalid CPU name \"%s\".", TheCPU.c_str());
     829                 :          0 :                 exit(1);
     830                 :            :             }
     831         [ #  # ]:          0 :             if (jl_processor_print_help) {
     832                 :            :                 // This is the only way I can find to print the help message once.
     833                 :            :                 // It'll be nice if we can iterate through the features and print our own help
     834                 :            :                 // message...
     835                 :          0 :                 MSTI->setDefaultFeatures("help", "", "");
     836                 :            :             }
     837                 :            :         }
     838                 :            :         // Package up features to be passed to target/subtarget
     839                 :       1134 :         std::string FeaturesStr;
     840         [ +  - ]:        567 :         if (!targetFeatures.empty()) {
     841                 :        567 :             SubtargetFeatures Features;
     842         [ +  + ]:      44793 :             for (unsigned i = 0; i != targetFeatures.size(); ++i)
     843                 :      44226 :                 Features.AddFeature(targetFeatures[i]);
     844                 :        567 :             FeaturesStr = Features.getString();
     845                 :            :         }
     846                 :            :         // Allocate a target...
     847                 :        567 :         Optional<CodeModel::Model> codemodel =
     848                 :            : #ifdef _P64
     849                 :            :             // Make sure we are using the large code model on 64bit
     850                 :            :             // Let LLVM pick a default suitable for jitting on 32bit
     851                 :            :             CodeModel::Large;
     852                 :            : #else
     853                 :            :             None;
     854                 :            : #endif
     855                 :        567 :         auto optlevel = CodeGenOptLevelFor(jl_options.opt_level);
     856                 :        567 :         auto TM = TheTarget->createTargetMachine(
     857                 :            :                 TheTriple.getTriple(), TheCPU, FeaturesStr,
     858                 :            :                 options,
     859                 :        567 :                 Reloc::Static, // Generate simpler code for JIT
     860                 :            :                 codemodel,
     861                 :            :                 optlevel,
     862                 :            :                 true // JIT
     863                 :            :                 );
     864         [ -  + ]:        567 :         assert(TM && "Failed to select target machine -"
     865                 :            :                                 " Is the LLVM backend for this CPU enabled?");
     866                 :            :         #if (!defined(_CPU_ARM_) && !defined(_CPU_PPC64_))
     867                 :            :         // FastISel seems to be buggy for ARM. Ref #13321
     868         [ +  + ]:        567 :         if (jl_options.opt_level < 2)
     869                 :         92 :             TM->setFastISel(true);
     870                 :            :         #endif
     871                 :        567 :         return std::unique_ptr<TargetMachine>(TM);
     872                 :            :     }
     873                 :            : } // namespace
     874                 :            : 
     875                 :            : namespace {
     876                 :            : 
     877                 :            :     typedef legacy::PassManager PassManager;
     878                 :            : 
     879                 :       4536 :     orc::JITTargetMachineBuilder createJTMBFromTM(TargetMachine &TM, int optlevel) {
     880                 :       9072 :         return orc::JITTargetMachineBuilder(TM.getTargetTriple())
     881                 :       9072 :         .setCPU(TM.getTargetCPU().str())
     882                 :       4536 :         .setFeatures(TM.getTargetFeatureString())
     883                 :       9072 :         .setOptions(TM.Options)
     884                 :       4536 :         .setRelocationModel(Reloc::Static)
     885                 :       9072 :         .setCodeModel(TM.getCodeModel())
     886                 :       4536 :         .setCodeGenOptLevel(CodeGenOptLevelFor(optlevel));
     887                 :            :     }
     888                 :            : 
     889                 :            :     struct TMCreator {
     890                 :            :         orc::JITTargetMachineBuilder JTMB;
     891                 :            : 
     892                 :       2268 :         TMCreator(TargetMachine &TM, int optlevel) : JTMB(createJTMBFromTM(TM, optlevel)) {}
     893                 :            : 
     894                 :        952 :         std::unique_ptr<TargetMachine> operator()() {
     895                 :        952 :             return cantFail(JTMB.createTargetMachine());
     896                 :            :         }
     897                 :            :     };
     898                 :            : 
     899                 :            :     struct PMCreator {
     900                 :            :         std::unique_ptr<TargetMachine> TM;
     901                 :            :         int optlevel;
     902                 :       2268 :         PMCreator(TargetMachine &TM, int optlevel) : TM(cantFail(createJTMBFromTM(TM, optlevel).createTargetMachine())), optlevel(optlevel) {}
     903                 :          0 :         PMCreator(const PMCreator &other) : PMCreator(*other.TM, other.optlevel) {}
     904                 :       2268 :         PMCreator(PMCreator &&other) : TM(std::move(other.TM)), optlevel(other.optlevel) {}
     905                 :            :         friend void swap(PMCreator &self, PMCreator &other) {
     906                 :            :             using std::swap;
     907                 :            :             swap(self.TM, other.TM);
     908                 :            :             swap(self.optlevel, other.optlevel);
     909                 :            :         }
     910                 :            :         PMCreator &operator=(PMCreator other) {
     911                 :            :             swap(*this, other);
     912                 :            :             return *this;
     913                 :            :         }
     914                 :        952 :         std::unique_ptr<PassManager> operator()() {
     915                 :        952 :             auto PM = std::make_unique<legacy::PassManager>();
     916                 :        952 :             addTargetPasses(PM.get(), TM->getTargetTriple(), TM->getTargetIRAnalysis());
     917                 :        952 :             addOptimizationPasses(PM.get(), optlevel);
     918                 :        952 :             addMachinePasses(PM.get(), optlevel);
     919                 :        952 :             return PM;
     920                 :            :         }
     921                 :            :     };
     922                 :            : 
     923                 :            :     struct OptimizerT {
     924                 :       2268 :         OptimizerT(TargetMachine &TM, int optlevel) : optlevel(optlevel), PMs(PMCreator(TM, optlevel)) {}
     925                 :            : 
     926                 :     334404 :         OptimizerResultT operator()(orc::ThreadSafeModule TSM, orc::MaterializationResponsibility &R) {
     927                 :     334404 :             TSM.withModuleDo([&](Module &M) {
     928                 :     334404 :                 uint64_t start_time = 0;
     929                 :            :                 {
     930                 :     668808 :                     auto stream = *jl_ExecutionEngine->get_dump_llvm_opt_stream();
     931         [ +  + ]:     334404 :                     if (stream) {
     932                 :            :                         // Print LLVM function statistics _before_ optimization
     933                 :            :                         // Print all the information about this invocation as a YAML object
     934                 :          1 :                         jl_printf(stream, "- \n");
     935                 :            :                         // We print the name and some statistics for each function in the module, both
     936                 :            :                         // before optimization and again afterwards.
     937                 :          1 :                         jl_printf(stream, "  before: \n");
     938         [ +  + ]:          5 :                         for (auto &F : M.functions()) {
     939   [ +  +  +  +  :          4 :                             if (F.isDeclaration() || F.getName().startswith("jfptr_")) {
                   +  + ]
     940                 :          3 :                                 continue;
     941                 :            :                             }
     942                 :            :                             // Each function is printed as a YAML object with several attributes
     943                 :          1 :                             jl_printf(stream, "    \"%s\":\n", F.getName().str().c_str());
     944                 :          1 :                             jl_printf(stream, "        instructions: %u\n", F.getInstructionCount());
     945                 :          1 :                             jl_printf(stream, "        basicblocks: %zd\n", countBasicBlocks(F));
     946                 :            :                         }
     947                 :            : 
     948                 :          1 :                         start_time = jl_hrtime();
     949                 :            :                     }
     950                 :            :                 }
     951                 :            : 
     952                 :            :                 JL_TIMING(LLVM_OPT);
     953                 :            : 
     954                 :            :                 //Run the optimization
     955                 :     334404 :                 (***PMs).run(M);
     956                 :            : 
     957                 :     334404 :                 uint64_t end_time = 0;
     958                 :            :                 {
     959                 :     668808 :                     auto stream = *jl_ExecutionEngine->get_dump_llvm_opt_stream();
     960         [ +  + ]:     334404 :                     if (stream) {
     961                 :          1 :                         end_time = jl_hrtime();
     962                 :          1 :                         jl_printf(stream, "  time_ns: %" PRIu64 "\n", end_time - start_time);
     963                 :          1 :                         jl_printf(stream, "  optlevel: %d\n", optlevel);
     964                 :            : 
     965                 :            :                         // Print LLVM function statistics _after_ optimization
     966                 :          1 :                         jl_printf(stream, "  after: \n");
     967         [ +  + ]:          9 :                         for (auto &F : M.functions()) {
     968   [ +  +  +  +  :          8 :                             if (F.isDeclaration() || F.getName().startswith("jfptr_")) {
                   +  + ]
     969                 :          7 :                                 continue;
     970                 :            :                             }
     971                 :          1 :                             jl_printf(stream, "    \"%s\":\n", F.getName().str().c_str());
     972                 :          1 :                             jl_printf(stream, "        instructions: %u\n", F.getInstructionCount());
     973                 :          1 :                             jl_printf(stream, "        basicblocks: %zd\n", countBasicBlocks(F));
     974                 :            :                         }
     975                 :            :                     }
     976                 :            :                 }
     977                 :     334404 :             });
     978                 :     334404 :             return Expected<orc::ThreadSafeModule>{std::move(TSM)};
     979                 :            :         }
     980                 :            :     private:
     981                 :            :         int optlevel;
     982                 :            :         JuliaOJIT::ResourcePool<std::unique_ptr<PassManager>> PMs;
     983                 :            :     };
     984                 :            : 
     985                 :            :     struct CompilerT : orc::IRCompileLayer::IRCompiler {
     986                 :            : 
     987                 :       2268 :         CompilerT(orc::IRSymbolMapper::ManglingOptions MO, TargetMachine &TM, int optlevel)
     988                 :       2268 :         : orc::IRCompileLayer::IRCompiler(MO), TMs(TMCreator(TM, optlevel)) {}
     989                 :            : 
     990                 :     334404 :         Expected<std::unique_ptr<MemoryBuffer>> operator()(Module &M) override {
     991                 :     334404 :             return orc::SimpleCompiler(***TMs)(M);
     992                 :            :         }
     993                 :            : 
     994                 :            :         JuliaOJIT::ResourcePool<std::unique_ptr<TargetMachine>> TMs;
     995                 :            :     };
     996                 :            : }
     997                 :            : 
     998                 :        568 : llvm::DataLayout jl_create_datalayout(TargetMachine &TM) {
     999                 :            :     // Mark our address spaces as non-integral
    1000                 :        568 :     auto jl_data_layout = TM.createDataLayout();
    1001                 :        568 :     jl_data_layout.reset(jl_data_layout.getStringRepresentation() + "-ni:10:11:12:13");
    1002                 :        568 :     return jl_data_layout;
    1003                 :            : }
    1004                 :            : 
    1005                 :       2268 : JuliaOJIT::PipelineT::PipelineT(orc::ObjectLayer &BaseLayer, TargetMachine &TM, int optlevel)
    1006                 :            : : CompileLayer(BaseLayer.getExecutionSession(), BaseLayer,
    1007                 :       2268 :     std::make_unique<CompilerT>(orc::irManglingOptionsFromTargetOptions(TM.Options), TM, optlevel)),
    1008                 :       4536 :   OptimizeLayer(CompileLayer.getExecutionSession(), CompileLayer, OptimizerT(TM, optlevel)) {}
    1009                 :            : 
    1010                 :        567 : JuliaOJIT::JuliaOJIT()
    1011                 :            :   : TM(createTargetMachine()),
    1012                 :        567 :     DL(jl_create_datalayout(*TM)),
    1013                 :            : #if JL_LLVM_VERSION >= 130000
    1014                 :       1134 :     ES(cantFail(orc::SelfExecutorProcessControl::Create())),
    1015                 :            : #else
    1016                 :            :     ES(),
    1017                 :            : #endif
    1018                 :       1134 :     GlobalJD(ES.createBareJITDylib("JuliaGlobals")),
    1019                 :       1134 :     JD(ES.createBareJITDylib("JuliaOJIT")),
    1020                 :        812 :     ContextPool([](){
    1021                 :        812 :         auto ctx = std::make_unique<LLVMContext>();
    1022                 :            : #ifdef JL_LLVM_OPAQUE_POINTERS
    1023                 :            :         ctx->enableOpaquePointers();
    1024                 :            : #endif
    1025                 :        812 :         return orc::ThreadSafeContext(std::move(ctx));
    1026                 :            :     }),
    1027                 :            : #ifdef JL_USE_JITLINK
    1028                 :            :     // TODO: Port our memory management optimisations to JITLink instead of using the
    1029                 :            :     // default InProcessMemoryManager.
    1030                 :            : # if JL_LLVM_VERSION < 140000
    1031                 :            :     ObjectLayer(ES, std::make_unique<jitlink::InProcessMemoryManager>()),
    1032                 :            : # else
    1033                 :            :     ObjectLayer(ES, cantFail(jitlink::InProcessMemoryManager::Create())),
    1034                 :            : # endif
    1035                 :            : #else
    1036                 :            :     MemMgr(createRTDyldMemoryManager()),
    1037                 :            :     ObjectLayer(
    1038                 :        567 :             ES,
    1039                 :     334403 :             [this]() {
    1040                 :     334403 :                 std::unique_ptr<RuntimeDyld::MemoryManager> result(new ForwardingMemoryManager(MemMgr));
    1041                 :     334403 :                 return result;
    1042                 :            :             }
    1043                 :            :         ),
    1044                 :            : #endif
    1045                 :            :     Pipelines{
    1046                 :       1701 :         std::make_unique<PipelineT>(ObjectLayer, *TM, 0),
    1047                 :        567 :         std::make_unique<PipelineT>(ObjectLayer, *TM, 1),
    1048                 :        567 :         std::make_unique<PipelineT>(ObjectLayer, *TM, 2),
    1049                 :        567 :         std::make_unique<PipelineT>(ObjectLayer, *TM, 3),
    1050                 :            :     },
    1051                 :       5103 :     OptSelLayer(Pipelines)
    1052                 :            : {
    1053                 :            : #ifdef JL_USE_JITLINK
    1054                 :            : # if defined(_OS_DARWIN_) && defined(LLVM_SHLIB)
    1055                 :            :     // When dynamically linking against LLVM, use our custom EH frame registration code
    1056                 :            :     // also used with RTDyld to inform both our and the libc copy of libunwind.
    1057                 :            :     auto ehRegistrar = std::make_unique<JLEHFrameRegistrar>();
    1058                 :            : # else
    1059                 :            :     auto ehRegistrar = std::make_unique<jitlink::InProcessEHFrameRegistrar>();
    1060                 :            : # endif
    1061                 :            :     ObjectLayer.addPlugin(std::make_unique<EHFrameRegistrationPlugin>(
    1062                 :            :         ES, std::move(ehRegistrar)));
    1063                 :            : 
    1064                 :            :     ObjectLayer.addPlugin(std::make_unique<JLDebuginfoPlugin>());
    1065                 :            : #else
    1066                 :            :     ObjectLayer.setNotifyLoaded(
    1067                 :     334403 :         [this](orc::MaterializationResponsibility &MR,
    1068                 :            :                const object::ObjectFile &Object,
    1069                 :     334403 :                const RuntimeDyld::LoadedObjectInfo &LO) {
    1070                 :     334403 :             registerRTDyldJITObject(Object, LO, MemMgr);
    1071                 :        567 :         });
    1072                 :            : #endif
    1073                 :            : 
    1074                 :            :     // Make sure SectionMemoryManager::getSymbolAddressInProcess can resolve
    1075                 :            :     // symbols in the program as well. The nullptr argument to the function
    1076                 :            :     // tells DynamicLibrary to load the program, not a library.
    1077                 :       1134 :     std::string ErrorStr;
    1078         [ -  + ]:        567 :     if (sys::DynamicLibrary::LoadLibraryPermanently(nullptr, &ErrorStr))
    1079                 :          0 :         report_fatal_error(llvm::Twine("FATAL: unable to dlopen self\n") + ErrorStr);
    1080                 :            : 
    1081                 :        567 :     GlobalJD.addGenerator(
    1082                 :       1701 :       cantFail(orc::DynamicLibrarySearchGenerator::GetForCurrentProcess(
    1083                 :       1134 :         DL.getGlobalPrefix())));
    1084                 :            : 
    1085                 :            :     // Resolve non-lock free atomic functions in the libatomic1 library.
    1086                 :            :     // This is the library that provides support for c11/c++11 atomic operations.
    1087                 :        567 :     const char *const libatomic =
    1088                 :            : #if defined(_OS_LINUX_) || defined(_OS_FREEBSD_)
    1089                 :            :         "libatomic.so.1";
    1090                 :            : #elif defined(_OS_WINDOWS_)
    1091                 :            :         "libatomic-1.dll";
    1092                 :            : #else
    1093                 :            :         NULL;
    1094                 :            : #endif
    1095                 :            :     if (libatomic) {
    1096   [ +  -  +  - ]:        567 :         static void *atomic_hdl = jl_load_dynamic_library(libatomic, JL_RTLD_LOCAL, 0);
    1097         [ +  - ]:        567 :         if (atomic_hdl != NULL) {
    1098                 :        567 :             GlobalJD.addGenerator(
    1099                 :       1701 :               cantFail(orc::DynamicLibrarySearchGenerator::Load(
    1100                 :            :                   libatomic,
    1101                 :        567 :                   DL.getGlobalPrefix(),
    1102                 :     809546 :                   [&](const orc::SymbolStringPtr &S) {
    1103                 :     809546 :                         const char *const atomic_prefix = "__atomic_";
    1104                 :     809546 :                         return (*S).startswith(atomic_prefix);
    1105                 :        567 :                   })));
    1106                 :            :         }
    1107                 :            :     }
    1108                 :            : 
    1109                 :        567 :     JD.addToLinkOrder(GlobalJD, orc::JITDylibLookupFlags::MatchExportedSymbolsOnly);
    1110                 :        567 : }
    1111                 :            : 
    1112                 :     130346 : void JuliaOJIT::addGlobalMapping(StringRef Name, uint64_t Addr)
    1113                 :            : {
    1114                 :     130346 :     std::string MangleName = getMangledName(Name);
    1115         [ +  + ]:     260692 :     cantFail(JD.define(orc::absoluteSymbols({{ES.intern(MangleName), JITEvaluatedSymbol::fromPointer((void*)Addr)}})));
    1116                 :     130346 : }
    1117                 :            : 
    1118                 :     334404 : void JuliaOJIT::addModule(orc::ThreadSafeModule TSM)
    1119                 :            : {
    1120                 :            :     JL_TIMING(LLVM_MODULE_FINISH);
    1121                 :     668807 :     std::vector<std::string> NewExports;
    1122                 :     334404 :     TSM.withModuleDo([&](Module &M) {
    1123                 :     334404 :         jl_decorate_module(M);
    1124                 :     334404 :         shareStrings(M);
    1125         [ +  + ]:    4315620 :         for (auto &F : M.global_values()) {
    1126   [ +  +  +  +  :    3981220 :             if (!F.isDeclaration() && F.getLinkage() == GlobalValue::ExternalLinkage) {
                   +  + ]
    1127                 :     665980 :                 NewExports.push_back(getMangledName(F.getName()));
    1128                 :            :             }
    1129                 :            :         }
    1130                 :            : #if !defined(JL_NDEBUG) && !defined(JL_USE_JITLINK)
    1131                 :            :         // validate the relocations for M (not implemented for the JITLink memory manager yet)
    1132         [ +  + ]:    4315620 :         for (Module::global_object_iterator I = M.global_objects().begin(), E = M.global_objects().end(); I != E; ) {
    1133                 :    3981210 :             GlobalObject *F = &*I;
    1134                 :    3981210 :             ++I;
    1135         [ +  + ]:    3981210 :             if (F->isDeclaration()) {
    1136         [ +  + ]:    3012550 :                 if (F->use_empty())
    1137                 :       4586 :                     F->eraseFromParent();
    1138   [ +  +  +  +  :    4401960 :                 else if (!((isa<Function>(F) && isIntrinsicFunction(cast<Function>(F))) ||
                   -  - ]
    1139   [ -  +  -  + ]:    4401960 :                         findUnmangledSymbol(F->getName()) ||
    1140                 :          0 :                         SectionMemoryManager::getSymbolAddressInProcess(
    1141   [ -  +  +  + ]:    3007960 :                             getMangledName(F->getName())))) {
    1142                 :          0 :                     llvm::errs() << "FATAL ERROR: "
    1143                 :          0 :                                 << "Symbol \"" << F->getName().str() << "\""
    1144                 :          0 :                                 << "not found";
    1145                 :          0 :                     abort();
    1146                 :            :                 }
    1147                 :            :             }
    1148                 :            :         }
    1149                 :            : #endif
    1150                 :     334404 :     });
    1151                 :            :     // TODO: what is the performance characteristics of this?
    1152                 :     334404 :     cantFail(OptSelLayer.add(JD, std::move(TSM)));
    1153                 :            :     // force eager compilation (for now), due to memory management specifics
    1154                 :            :     // (can't handle compilation recursion)
    1155         [ +  + ]:    1000380 :     for (auto Name : NewExports)
    1156                 :     665979 :         cantFail(ES.lookup({&JD}, Name));
    1157                 :            : 
    1158                 :     334403 : }
    1159                 :            : 
    1160                 :    2049200 : JL_JITSymbol JuliaOJIT::findSymbol(StringRef Name, bool ExportedSymbolsOnly)
    1161                 :            : {
    1162                 :    2049200 :     orc::JITDylib* SearchOrders[2] = {&GlobalJD, &JD};
    1163   [ +  +  +  + ]:    2049200 :     ArrayRef<orc::JITDylib*> SearchOrder = makeArrayRef(&SearchOrders[ExportedSymbolsOnly ? 0 : 1], ExportedSymbolsOnly ? 2 : 1);
    1164                 :    4098390 :     auto Sym = ES.lookup(SearchOrder, Name);
    1165         [ +  + ]:    2049200 :     if (Sym)
    1166                 :    2049190 :         return *Sym;
    1167                 :          4 :     return Sym.takeError();
    1168                 :            : }
    1169                 :            : 
    1170                 :    1394000 : JL_JITSymbol JuliaOJIT::findUnmangledSymbol(StringRef Name)
    1171                 :            : {
    1172                 :    1394000 :     return findSymbol(getMangledName(Name), true);
    1173                 :            : }
    1174                 :            : 
    1175                 :          6 : uint64_t JuliaOJIT::getGlobalValueAddress(StringRef Name)
    1176                 :            : {
    1177                 :         12 :     auto addr = findSymbol(getMangledName(Name), false);
    1178         [ +  + ]:          6 :     if (!addr) {
    1179                 :          4 :         consumeError(addr.takeError());
    1180                 :          4 :         return 0;
    1181                 :            :     }
    1182                 :          2 :     return cantFail(addr.getAddress());
    1183                 :            : }
    1184                 :            : 
    1185                 :     655189 : uint64_t JuliaOJIT::getFunctionAddress(StringRef Name)
    1186                 :            : {
    1187                 :    1310380 :     auto addr = findSymbol(getMangledName(Name), false);
    1188         [ -  + ]:     655189 :     if (!addr) {
    1189                 :          0 :         consumeError(addr.takeError());
    1190                 :          0 :         return 0;
    1191                 :            :     }
    1192                 :     655189 :     return cantFail(addr.getAddress());
    1193                 :            : }
    1194                 :            : 
    1195                 :    1286480 : StringRef JuliaOJIT::getFunctionAtAddress(uint64_t Addr, jl_code_instance_t *codeinst)
    1196                 :            : {
    1197                 :    1286480 :     std::lock_guard<std::mutex> lock(RLST_mutex);
    1198                 :    1286480 :     std::string *fname = &ReverseLocalSymbolTable[(void*)(uintptr_t)Addr];
    1199         [ +  + ]:    1286480 :     if (fname->empty()) {
    1200                 :     141622 :         std::string string_fname;
    1201                 :      70811 :         raw_string_ostream stream_fname(string_fname);
    1202                 :            :         // try to pick an appropriate name that describes it
    1203                 :      70811 :         jl_callptr_t invoke = jl_atomic_load_relaxed(&codeinst->invoke);
    1204         [ -  + ]:      70811 :         if (Addr == (uintptr_t)invoke) {
    1205                 :          0 :             stream_fname << "jsysw_";
    1206                 :            :         }
    1207         [ +  + ]:      70811 :         else if (invoke == jl_fptr_args_addr) {
    1208                 :       3995 :             stream_fname << "jsys1_";
    1209                 :            :         }
    1210         [ -  + ]:      66816 :         else if (invoke == jl_fptr_sparam_addr) {
    1211                 :          0 :             stream_fname << "jsys3_";
    1212                 :            :         }
    1213                 :            :         else {
    1214                 :      66816 :             stream_fname << "jlsys_";
    1215                 :            :         }
    1216                 :      70811 :         const char* unadorned_name = jl_symbol_name(codeinst->def->def.method->name);
    1217                 :      70811 :         stream_fname << unadorned_name << "_" << RLST_inc++;
    1218                 :      70811 :         *fname = std::move(stream_fname.str()); // store to ReverseLocalSymbolTable
    1219                 :      70811 :         addGlobalMapping(*fname, Addr);
    1220                 :            :     }
    1221                 :    1286480 :     return *fname;
    1222                 :            : }
    1223                 :            : 
    1224                 :            : 
    1225                 :            : #ifdef JL_USE_JITLINK
    1226                 :            : # if JL_LLVM_VERSION < 140000
    1227                 :            : #  pragma message("JIT debugging (GDB integration) not available on LLVM < 14.0 (for JITLink)")
    1228                 :            : void JuliaOJIT::enableJITDebuggingSupport() {}
    1229                 :            : # else
    1230                 :            : extern "C" orc::shared::CWrapperFunctionResult
    1231                 :            : llvm_orc_registerJITLoaderGDBAllocAction(const char *Data, size_t Size);
    1232                 :            : 
    1233                 :            : void JuliaOJIT::enableJITDebuggingSupport()
    1234                 :            : {
    1235                 :            :     // We do not use GDBJITDebugInfoRegistrationPlugin::Create, as the runtime name
    1236                 :            :     // lookup is unnecessarily involved/fragile for our in-process JIT use case
    1237                 :            :     // (with the llvm_orc_registerJITLoaderGDBAllocAction symbol being in either
    1238                 :            :     // libjulia-codegen or yet another shared library for LLVM depending on the build
    1239                 :            :     // flags, etc.).
    1240                 :            :     const auto Addr = ExecutorAddr::fromPtr(&llvm_orc_registerJITLoaderGDBAllocAction);
    1241                 :            :     ObjectLayer.addPlugin(std::make_unique<orc::GDBJITDebugInfoRegistrationPlugin>(Addr));
    1242                 :            : }
    1243                 :            : # endif
    1244                 :            : #else
    1245                 :        567 : void JuliaOJIT::enableJITDebuggingSupport()
    1246                 :            : {
    1247                 :        567 :     RegisterJITEventListener(JITEventListener::createGDBRegistrationListener());
    1248                 :        567 : }
    1249                 :            : 
    1250                 :        567 : void JuliaOJIT::RegisterJITEventListener(JITEventListener *L)
    1251                 :            : {
    1252         [ -  + ]:        567 :     if (!L)
    1253                 :          0 :         return;
    1254                 :        567 :     this->ObjectLayer.registerJITEventListener(*L);
    1255                 :            : }
    1256                 :            : #endif
    1257                 :            : 
    1258                 :     376745 : const DataLayout& JuliaOJIT::getDataLayout() const
    1259                 :            : {
    1260                 :     376745 :     return DL;
    1261                 :            : }
    1262                 :            : 
    1263                 :    2845520 : std::string JuliaOJIT::getMangledName(StringRef Name)
    1264                 :            : {
    1265                 :    2845520 :     SmallString<128> FullName;
    1266                 :    2845520 :     Mangler::getNameWithPrefix(FullName, Name, DL);
    1267                 :    2845520 :     return FullName.str().str();
    1268                 :            : }
    1269                 :            : 
    1270                 :          0 : std::string JuliaOJIT::getMangledName(const GlobalValue *GV)
    1271                 :            : {
    1272                 :          0 :     return getMangledName(GV->getName());
    1273                 :            : }
    1274                 :            : 
    1275                 :            : #ifdef JL_USE_JITLINK
    1276                 :            : size_t JuliaOJIT::getTotalBytes() const
    1277                 :            : {
    1278                 :            :     // TODO: Implement in future custom JITLink memory manager.
    1279                 :            :     return 0;
    1280                 :            : }
    1281                 :            : #else
    1282                 :            : size_t getRTDyldMemoryManagerTotalBytes(RTDyldMemoryManager *mm);
    1283                 :            : 
    1284                 :          1 : size_t JuliaOJIT::getTotalBytes() const
    1285                 :            : {
    1286                 :          1 :     return getRTDyldMemoryManagerTotalBytes(MemMgr.get());
    1287                 :            : }
    1288                 :            : #endif
    1289                 :            : 
    1290                 :            : JuliaOJIT *jl_ExecutionEngine;
    1291                 :            : 
    1292                 :            : // destructively move the contents of src into dest
    1293                 :            : // this assumes that the targets of the two modules are the same
    1294                 :            : // including the DataLayout and ModuleFlags (for example)
    1295                 :            : // and that there is no module-level assembly
    1296                 :            : // Comdat is also removed, since the JIT doesn't need it
    1297                 :      33720 : void jl_merge_module(orc::ThreadSafeModule &destTSM, orc::ThreadSafeModule srcTSM)
    1298                 :            : {
    1299                 :      33720 :     destTSM.withModuleDo([&](Module &dest) {
    1300                 :      33720 :         srcTSM.withModuleDo([&](Module &src) {
    1301         [ -  + ]:      33720 :             assert(&dest != &src && "Cannot merge module with itself!");
    1302         [ +  - ]:      33720 :             assert(&dest.getContext() == &src.getContext() && "Cannot merge modules with different contexts!");
    1303         [ +  - ]:      33720 :             assert(dest.getDataLayout() == src.getDataLayout() && "Cannot merge modules with different data layouts!");
    1304         [ +  - ]:      33720 :             assert(dest.getTargetTriple() == src.getTargetTriple() && "Cannot merge modules with different target triples!");
    1305                 :            : 
    1306         [ +  + ]:     425418 :             for (Module::global_iterator I = src.global_begin(), E = src.global_end(); I != E;) {
    1307                 :     391698 :                 GlobalVariable *sG = &*I;
    1308                 :     391698 :                 GlobalVariable *dG = cast_or_null<GlobalVariable>(dest.getNamedValue(sG->getName()));
    1309                 :     391698 :                 ++I;
    1310                 :            :                 // Replace a declaration with the definition:
    1311         [ +  + ]:     391698 :                 if (dG) {
    1312         [ +  + ]:     357081 :                     if (sG->isDeclaration()) {
    1313                 :     340807 :                         sG->replaceAllUsesWith(dG);
    1314                 :     340807 :                         sG->eraseFromParent();
    1315                 :     340807 :                         continue;
    1316                 :            :                     }
    1317                 :            :                     //// If we start using llvm.used, we need to enable and test this
    1318                 :            :                     //else if (!dG->isDeclaration() && dG->hasAppendingLinkage() && sG->hasAppendingLinkage()) {
    1319                 :            :                     //    auto *dCA = cast<ConstantArray>(dG->getInitializer());
    1320                 :            :                     //    auto *sCA = cast<ConstantArray>(sG->getInitializer());
    1321                 :            :                     //    SmallVector<Constant *, 16> Init;
    1322                 :            :                     //    for (auto &Op : dCA->operands())
    1323                 :            :                     //        Init.push_back(cast_or_null<Constant>(Op));
    1324                 :            :                     //    for (auto &Op : sCA->operands())
    1325                 :            :                     //        Init.push_back(cast_or_null<Constant>(Op));
    1326                 :            :                     //    Type *Int8PtrTy = Type::getInt8PtrTy(dest.getContext());
    1327                 :            :                     //    ArrayType *ATy = ArrayType::get(Int8PtrTy, Init.size());
    1328                 :            :                     //    GlobalVariable *GV = new GlobalVariable(dest, ATy, dG->isConstant(),
    1329                 :            :                     //            GlobalValue::AppendingLinkage, ConstantArray::get(ATy, Init), "",
    1330                 :            :                     //            dG->getThreadLocalMode(), dG->getType()->getAddressSpace());
    1331                 :            :                     //    GV->copyAttributesFrom(dG);
    1332                 :            :                     //    sG->replaceAllUsesWith(GV);
    1333                 :            :                     //    dG->replaceAllUsesWith(GV);
    1334                 :            :                     //    GV->takeName(sG);
    1335                 :            :                     //    sG->eraseFromParent();
    1336                 :            :                     //    dG->eraseFromParent();
    1337                 :            :                     //    continue;
    1338                 :            :                     //}
    1339                 :            :                     else {
    1340   [ +  +  -  + ]:      16274 :                         assert(dG->isDeclaration() || dG->getInitializer() == sG->getInitializer());
    1341                 :      16274 :                         dG->replaceAllUsesWith(sG);
    1342                 :      16274 :                         dG->eraseFromParent();
    1343                 :            :                     }
    1344                 :            :                 }
    1345                 :            :                 // Reparent the global variable:
    1346                 :      50891 :                 sG->removeFromParent();
    1347                 :      50891 :                 dest.getGlobalList().push_back(sG);
    1348                 :            :                 // Comdat is owned by the Module
    1349                 :      50891 :                 sG->setComdat(nullptr);
    1350                 :            :             }
    1351                 :            : 
    1352         [ +  + ]:     331716 :             for (Module::iterator I = src.begin(), E = src.end(); I != E;) {
    1353                 :     297996 :                 Function *sG = &*I;
    1354                 :     297996 :                 Function *dG = cast_or_null<Function>(dest.getNamedValue(sG->getName()));
    1355                 :     297996 :                 ++I;
    1356                 :            :                 // Replace a declaration with the definition:
    1357         [ +  + ]:     297996 :                 if (dG) {
    1358         [ +  + ]:     223459 :                     if (sG->isDeclaration()) {
    1359                 :     215234 :                         sG->replaceAllUsesWith(dG);
    1360                 :     215234 :                         sG->eraseFromParent();
    1361                 :     215234 :                         continue;
    1362                 :            :                     }
    1363                 :            :                     else {
    1364         [ -  + ]:       8225 :                         assert(dG->isDeclaration());
    1365                 :       8225 :                         dG->replaceAllUsesWith(sG);
    1366                 :       8225 :                         dG->eraseFromParent();
    1367                 :            :                     }
    1368                 :            :                 }
    1369                 :            :                 // Reparent the global variable:
    1370                 :      82762 :                 sG->removeFromParent();
    1371                 :      82762 :                 dest.getFunctionList().push_back(sG);
    1372                 :            :                 // Comdat is owned by the Module
    1373                 :      82762 :                 sG->setComdat(nullptr);
    1374                 :            :             }
    1375                 :            : 
    1376         [ -  + ]:      33720 :             for (Module::alias_iterator I = src.alias_begin(), E = src.alias_end(); I != E;) {
    1377                 :          0 :                 GlobalAlias *sG = &*I;
    1378                 :          0 :                 GlobalAlias *dG = cast_or_null<GlobalAlias>(dest.getNamedValue(sG->getName()));
    1379                 :          0 :                 ++I;
    1380         [ #  # ]:          0 :                 if (dG) {
    1381         [ #  # ]:          0 :                     if (!dG->isDeclaration()) { // aliases are always definitions, so this test is reversed from the above two
    1382                 :          0 :                         sG->replaceAllUsesWith(dG);
    1383                 :          0 :                         sG->eraseFromParent();
    1384                 :          0 :                         continue;
    1385                 :            :                     }
    1386                 :            :                     else {
    1387                 :          0 :                         dG->replaceAllUsesWith(sG);
    1388                 :          0 :                         dG->eraseFromParent();
    1389                 :            :                     }
    1390                 :            :                 }
    1391                 :          0 :                 sG->removeFromParent();
    1392                 :          0 :                 dest.getAliasList().push_back(sG);
    1393                 :            :             }
    1394                 :            : 
    1395                 :            :             // metadata nodes need to be explicitly merged not just copied
    1396                 :            :             // so there are special passes here for each known type of metadata
    1397                 :      33720 :             NamedMDNode *sNMD = src.getNamedMetadata("llvm.dbg.cu");
    1398         [ +  + ]:      33720 :             if (sNMD) {
    1399                 :      27874 :                 NamedMDNode *dNMD = dest.getOrInsertNamedMetadata("llvm.dbg.cu");
    1400         [ +  + ]:      55748 :                 for (NamedMDNode::op_iterator I = sNMD->op_begin(), E = sNMD->op_end(); I != E; ++I) {
    1401                 :      27874 :                     dNMD->addOperand(*I);
    1402                 :            :                 }
    1403                 :            :             }
    1404                 :      33720 :         });
    1405                 :      33720 :     });
    1406                 :      33720 : }
    1407                 :            : 
    1408                 :            : // optimize memory by turning long strings into memoized copies, instead of
    1409                 :            : // making a copy per object file of output.
    1410                 :     334404 : void JuliaOJIT::shareStrings(Module &M)
    1411                 :            : {
    1412                 :     668808 :     std::vector<GlobalVariable*> erase;
    1413         [ +  + ]:     665489 :     for (auto &GV : M.globals()) {
    1414   [ +  +  +  +  :     331085 :         if (!GV.hasInitializer() || !GV.isConstant())
                   +  + ]
    1415                 :     280564 :             continue;
    1416                 :     305413 :         ConstantDataSequential *CDS = dyn_cast<ConstantDataSequential>(GV.getInitializer());
    1417         [ +  + ]:     305413 :         if (CDS == nullptr)
    1418                 :     254892 :             continue;
    1419                 :      50521 :         StringRef data = CDS->getRawDataValues();
    1420         [ +  + ]:      50521 :         if (data.size() > 16) { // only for long strings: keep short ones as values
    1421                 :       7688 :             Type *T_size = Type::getIntNTy(GV.getContext(), sizeof(void*) * 8);
    1422                 :       7688 :             Constant *v = ConstantExpr::getIntToPtr(
    1423                 :      15376 :                 ConstantInt::get(T_size, (uintptr_t)(*ES.intern(data)).data()),
    1424                 :       7688 :                 GV.getType());
    1425                 :       7688 :             GV.replaceAllUsesWith(v);
    1426                 :       7688 :             erase.push_back(&GV);
    1427                 :            :         }
    1428                 :            :     }
    1429         [ +  + ]:     342092 :     for (auto GV : erase)
    1430                 :       7688 :         GV->eraseFromParent();
    1431                 :     334404 : }
    1432                 :            : 
    1433                 :            : //TargetMachine pass-through methods
    1434                 :            : 
    1435                 :         24 : std::unique_ptr<TargetMachine> JuliaOJIT::cloneTargetMachine() const
    1436                 :            : {
    1437                 :         24 :     return std::unique_ptr<TargetMachine>(getTarget()
    1438                 :            :         .createTargetMachine(
    1439                 :         24 :             getTargetTriple().str(),
    1440                 :            :             getTargetCPU(),
    1441                 :            :             getTargetFeatureString(),
    1442                 :            :             getTargetOptions(),
    1443                 :         24 :             TM->getRelocationModel(),
    1444                 :         24 :             TM->getCodeModel(),
    1445                 :         96 :             TM->getOptLevel()));
    1446                 :            : }
    1447                 :            : 
    1448                 :     376893 : const Triple& JuliaOJIT::getTargetTriple() const {
    1449                 :     376893 :     return TM->getTargetTriple();
    1450                 :            : }
    1451                 :        476 : StringRef JuliaOJIT::getTargetFeatureString() const {
    1452                 :        476 :     return TM->getTargetFeatureString();
    1453                 :            : }
    1454                 :         25 : StringRef JuliaOJIT::getTargetCPU() const {
    1455                 :         25 :     return TM->getTargetCPU();
    1456                 :            : }
    1457                 :         25 : const TargetOptions &JuliaOJIT::getTargetOptions() const {
    1458                 :         25 :     return TM->Options;
    1459                 :            : }
    1460                 :         25 : const Target &JuliaOJIT::getTarget() const {
    1461                 :         25 :     return TM->getTarget();
    1462                 :            : }
    1463                 :         99 : TargetIRAnalysis JuliaOJIT::getTargetIRAnalysis() const {
    1464                 :         99 :     return TM->getTargetIRAnalysis();
    1465                 :            : }
    1466                 :            : 
    1467                 :     334404 : static void jl_decorate_module(Module &M) {
    1468                 :            : #if defined(_CPU_X86_64_) && defined(_OS_WINDOWS_)
    1469                 :            :     // Add special values used by debuginfo to build the UnwindData table registration for Win64
    1470                 :            :     // This used to be GV, but with https://reviews.llvm.org/D100944 we no longer can emit GV into `.text`
    1471                 :            :     // TODO: The data is set in debuginfo.cpp but it should be okay to actually emit it here.
    1472                 :            :     M.appendModuleInlineAsm("\
    1473                 :            :     .section .text                  \n\
    1474                 :            :     .type   __UnwindData,@object    \n\
    1475                 :            :     .p2align        2, 0x90         \n\
    1476                 :            :     __UnwindData:                   \n\
    1477                 :            :         .zero   12                  \n\
    1478                 :            :         .size   __UnwindData, 12    \n\
    1479                 :            :                                     \n\
    1480                 :            :         .type   __catchjmp,@object  \n\
    1481                 :            :         .p2align        2, 0x90     \n\
    1482                 :            :     __catchjmp:                     \n\
    1483                 :            :         .zero   12                  \n\
    1484                 :            :         .size   __catchjmp, 12");
    1485                 :            : #endif
    1486                 :     334404 : }
    1487                 :            : 
    1488                 :     519813 : static int jl_add_to_ee(
    1489                 :            :         orc::ThreadSafeModule &M,
    1490                 :            :         StringMap<orc::ThreadSafeModule*> &NewExports,
    1491                 :            :         DenseMap<orc::ThreadSafeModule*, int> &Queued,
    1492                 :            :         std::vector<std::vector<orc::ThreadSafeModule*>> &ToMerge,
    1493                 :            :         int depth)
    1494                 :            : {
    1495                 :            :     // DAG-sort (post-dominator) the compile to compute the minimum
    1496                 :            :     // merge-module sets for linkage
    1497         [ +  + ]:     519813 :     if (!M)
    1498                 :     180007 :         return 0;
    1499                 :            :     // First check and record if it's on the stack somewhere
    1500                 :            :     {
    1501                 :     339806 :         auto &Cycle = Queued[&M];
    1502         [ +  + ]:     339806 :         if (Cycle)
    1503                 :       2590 :             return Cycle;
    1504                 :     337216 :         ToMerge.push_back({});
    1505                 :     337216 :         Cycle = depth;
    1506                 :            :     }
    1507                 :     337216 :     int MergeUp = depth;
    1508                 :            :     // Compute the cycle-id
    1509                 :     337216 :     M.withModuleDo([&](Module &m) {
    1510         [ +  + ]:    4353980 :         for (auto &F : m.global_objects()) {
    1511   [ +  +  +  -  :    4016760 :             if (F.isDeclaration() && F.getLinkage() == GlobalValue::ExternalLinkage) {
                   +  + ]
    1512                 :    3046220 :                 auto Callee = NewExports.find(F.getName());
    1513         [ +  + ]:    3046220 :                 if (Callee != NewExports.end()) {
    1514                 :     182597 :                     auto &CM = Callee->second;
    1515                 :     182597 :                     int Down = jl_add_to_ee(*CM, NewExports, Queued, ToMerge, depth + 1);
    1516         [ -  + ]:     182597 :                     assert(Down <= depth);
    1517   [ +  +  +  + ]:     182597 :                     if (Down && Down < MergeUp)
    1518                 :       4224 :                         MergeUp = Down;
    1519                 :            :                 }
    1520                 :            :             }
    1521                 :            :         }
    1522                 :     337216 :     });
    1523         [ +  + ]:     337216 :     if (MergeUp == depth) {
    1524                 :            :         // Not in a cycle (or at the top of it)
    1525                 :     333108 :         Queued.erase(&M);
    1526         [ +  + ]:     337216 :         for (auto &CM : ToMerge.at(depth - 1)) {
    1527         [ -  + ]:       4108 :             assert(Queued.find(CM)->second == depth);
    1528                 :       4108 :             Queued.erase(CM);
    1529                 :       4108 :             jl_merge_module(M, std::move(*CM));
    1530                 :            :         }
    1531                 :     333108 :         jl_ExecutionEngine->addModule(std::move(M));
    1532                 :     333107 :         MergeUp = 0;
    1533                 :            :     }
    1534                 :            :     else {
    1535                 :            :         // Add our frame(s) to the top of the cycle
    1536                 :       4108 :         Queued[&M] = MergeUp;
    1537                 :       4108 :         auto &Top = ToMerge.at(MergeUp - 1);
    1538                 :       4108 :         Top.push_back(&M);
    1539         [ +  + ]:       4464 :         for (auto &CM : ToMerge.at(depth - 1)) {
    1540         [ -  + ]:        356 :             assert(Queued.find(CM)->second == depth);
    1541                 :        356 :             Queued[CM] = MergeUp;
    1542                 :        356 :             Top.push_back(CM);
    1543                 :            :         }
    1544                 :            :     }
    1545                 :     337215 :     ToMerge.pop_back();
    1546                 :     337215 :     return MergeUp;
    1547                 :            : }
    1548                 :            : 
    1549                 :     337216 : static void jl_add_to_ee(orc::ThreadSafeModule &M, StringMap<orc::ThreadSafeModule*> &NewExports)
    1550                 :            : {
    1551                 :     674431 :     DenseMap<orc::ThreadSafeModule*, int> Queued;
    1552                 :     674431 :     std::vector<std::vector<orc::ThreadSafeModule*>> ToMerge;
    1553                 :     337216 :     jl_add_to_ee(M, NewExports, Queued, ToMerge, 1);
    1554         [ -  + ]:     337215 :     assert(!M);
    1555                 :     337215 : }
    1556                 :            : 
    1557                 :            : 
    1558                 :     655189 : static uint64_t getAddressForFunction(StringRef fname)
    1559                 :            : {
    1560                 :     655189 :     auto addr = jl_ExecutionEngine->getFunctionAddress(fname);
    1561         [ -  + ]:     655189 :     assert(addr);
    1562                 :     655189 :     return addr;
    1563                 :            : }
    1564                 :            : 
    1565                 :            : // helper function for adding a DLLImport (dlsym) address to the execution engine
    1566                 :      59535 : void add_named_global(StringRef name, void *addr)
    1567                 :            : {
    1568                 :      59535 :     jl_ExecutionEngine->addGlobalMapping(name, (uint64_t)(uintptr_t)addr);
    1569                 :      59535 : }
    1570                 :            : 
    1571                 :            : extern "C" JL_DLLEXPORT
    1572                 :          1 : size_t jl_jit_total_bytes_impl(void)
    1573                 :            : {
    1574                 :          1 :     return jl_ExecutionEngine->getTotalBytes();
    1575                 :            : }

Generated by: LCOV version 1.14