LCOV - code coverage report
Current view: top level - src - ccall.cpp (source / functions) Hit Total Coverage
Test: [build process] commit ef510b1f346f4c9f9d86eaceace5ca54961a1dbc Lines: 946 1209 78.2 %
Date: 2022-07-17 01:01:28 Functions: 29 31 93.5 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 570 952 59.9 %

           Branch data     Line data    Source code
       1                 :            : // This file is a part of Julia. License is MIT: https://julialang.org/license
       2                 :            : 
       3                 :            : // --- the ccall, cglobal, and llvm intrinsics ---
       4                 :            : 
       5                 :            : // Mark our stats as being from ccall
       6                 :            : #undef DEBUG_TYPE
       7                 :            : #define DEBUG_TYPE "julia_irgen_ccall"
       8                 :            : 
       9                 :            : STATISTIC(RuntimeSymLookups, "Number of runtime symbol lookups emitted");
      10                 :            : STATISTIC(PLTThunks, "Number of PLT Thunks emitted");
      11                 :            : STATISTIC(PLT, "Number of direct PLT entries emitted");
      12                 :            : STATISTIC(EmittedCGlobals, "Number of C globals emitted");
      13                 :            : STATISTIC(EmittedLLVMCalls, "Number of llvmcall intrinsics emitted");
      14                 :            : 
      15                 :            : #define _CCALL_STAT(name) jl_transformed_ccall__##name
      16                 :            : #define CCALL_STAT(name) _CCALL_STAT(name)
      17                 :            : #define TRANSFORMED_CCALL_STAT(name) STATISTIC(_CCALL_STAT(name), "Number of " #name " ccalls intercepted")
      18                 :            : TRANSFORMED_CCALL_STAT(jl_array_ptr);
      19                 :            : TRANSFORMED_CCALL_STAT(jl_value_ptr);
      20                 :            : TRANSFORMED_CCALL_STAT(jl_cpu_pause);
      21                 :            : TRANSFORMED_CCALL_STAT(jl_cpu_wake);
      22                 :            : TRANSFORMED_CCALL_STAT(jl_gc_safepoint);
      23                 :            : TRANSFORMED_CCALL_STAT(jl_get_ptls_states);
      24                 :            : TRANSFORMED_CCALL_STAT(jl_threadid);
      25                 :            : TRANSFORMED_CCALL_STAT(jl_gc_enable_disable_finalizers_internal);
      26                 :            : TRANSFORMED_CCALL_STAT(jl_get_current_task);
      27                 :            : TRANSFORMED_CCALL_STAT(jl_set_next_task);
      28                 :            : TRANSFORMED_CCALL_STAT(jl_sigatomic_begin);
      29                 :            : TRANSFORMED_CCALL_STAT(jl_sigatomic_end);
      30                 :            : TRANSFORMED_CCALL_STAT(jl_svec_len);
      31                 :            : TRANSFORMED_CCALL_STAT(jl_svec_isassigned);
      32                 :            : TRANSFORMED_CCALL_STAT(jl_svec_ref);
      33                 :            : TRANSFORMED_CCALL_STAT(jl_array_isassigned);
      34                 :            : TRANSFORMED_CCALL_STAT(jl_string_ptr);
      35                 :            : TRANSFORMED_CCALL_STAT(jl_symbol_name);
      36                 :            : TRANSFORMED_CCALL_STAT(memcpy);
      37                 :            : TRANSFORMED_CCALL_STAT(memset);
      38                 :            : TRANSFORMED_CCALL_STAT(memmove);
      39                 :            : TRANSFORMED_CCALL_STAT(jl_object_id);
      40                 :            : #undef TRANSFORMED_CCALL_STAT
      41                 :            : 
      42                 :            : STATISTIC(EmittedCCalls, "Number of ccalls emitted");
      43                 :            : STATISTIC(DeferredCCallLookups, "Number of ccalls looked up at runtime");
      44                 :            : STATISTIC(LiteralCCalls, "Number of ccalls directly emitted through a pointer");
      45                 :            : STATISTIC(RetBoxedCCalls, "Number of ccalls that were retboxed");
      46                 :            : STATISTIC(SRetCCalls, "Number of ccalls that were marked sret");
      47                 :            : 
      48                 :            : // somewhat unusual variable, in that aotcompile wants to get the address of this for a sanity check
      49                 :      62107 : GlobalVariable *jl_emit_RTLD_DEFAULT_var(Module *M)
      50                 :            : {
      51                 :      62107 :     return prepare_global_in(M, jlRTLD_DEFAULT_var);
      52                 :            : }
      53                 :            : 
      54                 :            : 
      55                 :            : // Find or create the GVs for the library and symbol lookup.
      56                 :            : // Return `runtime_lib` (whether the library name is a string)
      57                 :            : // The `lib` and `sym` GV returned may not be in the current module.
      58                 :      63743 : static bool runtime_sym_gvs(jl_codectx_t &ctx, const char *f_lib, const char *f_name,
      59                 :            :                             GlobalVariable *&lib, GlobalVariable *&sym)
      60                 :            : {
      61                 :      63743 :     auto &TSM = ctx.emission_context.shared_module(*jl_Module);
      62                 :            :     //Safe b/c emission context holds context lock
      63                 :      63743 :     auto M = TSM.getModuleUnlocked();
      64                 :      63743 :     bool runtime_lib = false;
      65                 :            :     GlobalVariable *libptrgv;
      66                 :            :     jl_codegen_params_t::SymMapGV *symMap;
      67                 :            : #ifdef _OS_WINDOWS_
      68                 :            :     if ((intptr_t)f_lib == (intptr_t)JL_EXE_LIBNAME) {
      69                 :            :         libptrgv = prepare_global_in(M, jlexe_var);
      70                 :            :         symMap = &ctx.emission_context.symMapExe;
      71                 :            :     }
      72                 :            :     else if ((intptr_t)f_lib == (intptr_t)JL_LIBJULIA_INTERNAL_DL_LIBNAME) {
      73                 :            :         libptrgv = prepare_global_in(M, jldlli_var);
      74                 :            :         symMap = &ctx.emission_context.symMapDlli;
      75                 :            :     }
      76                 :            :     else if ((intptr_t)f_lib == (intptr_t)JL_LIBJULIA_DL_LIBNAME) {
      77                 :            :         libptrgv = prepare_global_in(M, jldll_var);
      78                 :            :         symMap = &ctx.emission_context.symMapDll;
      79                 :            :     }
      80                 :            :     else
      81                 :            : #endif
      82         [ +  + ]:      63743 :     if (f_lib == NULL) {
      83                 :      62105 :         libptrgv = jl_emit_RTLD_DEFAULT_var(M);
      84                 :      62105 :         symMap = &ctx.emission_context.symMapDefault;
      85                 :            :     }
      86                 :            :     else {
      87                 :       1638 :         std::string name = "ccalllib_";
      88                 :       1638 :         name += llvm::sys::path::filename(f_lib);
      89                 :       1638 :         name += std::to_string(globalUniqueGeneratedNames++);
      90                 :       1638 :         runtime_lib = true;
      91                 :       1638 :         auto &libgv = ctx.emission_context.libMapGV[f_lib];
      92         [ +  + ]:       1638 :         if (libgv.first == NULL) {
      93                 :        220 :             libptrgv = new GlobalVariable(*M, getInt8PtrTy(M->getContext()), false,
      94                 :            :                                           GlobalVariable::ExternalLinkage,
      95                 :        220 :                                           Constant::getNullValue(getInt8PtrTy(M->getContext())), name);
      96                 :        110 :             libgv.first = libptrgv;
      97                 :            :         }
      98                 :            :         else {
      99                 :       1528 :             libptrgv = libgv.first;
     100                 :            :         }
     101                 :       1638 :         symMap = &libgv.second;
     102                 :            :     }
     103                 :            : 
     104                 :      63743 :     GlobalVariable *&llvmgv = (*symMap)[f_name];
     105         [ +  + ]:      63743 :     if (llvmgv == NULL) {
     106                 :       7613 :         std::string name = "ccall_";
     107                 :       7613 :         name += f_name;
     108                 :       7613 :         name += "_";
     109                 :       7613 :         name += std::to_string(globalUniqueGeneratedNames++);
     110                 :       7613 :         auto T_pvoidfunc = JuliaType::get_pvoidfunc_ty(M->getContext());
     111                 :      15226 :         llvmgv = new GlobalVariable(*M, T_pvoidfunc, false,
     112                 :            :                                     GlobalVariable::ExternalLinkage,
     113                 :      15226 :                                     Constant::getNullValue(T_pvoidfunc), name);
     114                 :            :     }
     115                 :            : 
     116                 :      63743 :     lib = libptrgv;
     117                 :      63743 :     sym = llvmgv;
     118                 :      63743 :     return runtime_lib;
     119                 :            : }
     120                 :            : 
     121                 :      10525 : static Value *runtime_sym_lookup(
     122                 :            :         jl_codegen_params_t &emission_context,
     123                 :            :         IRBuilder<> &irbuilder,
     124                 :            :         jl_codectx_t *ctx,
     125                 :            :         PointerType *funcptype, const char *f_lib, jl_value_t *lib_expr,
     126                 :            :         const char *f_name, Function *f,
     127                 :            :         GlobalVariable *libptrgv,
     128                 :            :         GlobalVariable *llvmgv, bool runtime_lib)
     129                 :            : {
     130                 :      10525 :     ++RuntimeSymLookups;
     131                 :            :     // in pseudo-code, this function emits the following:
     132                 :            :     //   global HMODULE *libptrgv
     133                 :            :     //   global void **llvmgv
     134                 :            :     //   if (*llvmgv == NULL) {
     135                 :            :     //       *llvmgv = jl_load_and_lookup(f_lib, f_name, libptrgv);
     136                 :            :     //   }
     137                 :            :     //   return (*llvmgv)
     138                 :      10525 :     auto T_pvoidfunc = JuliaType::get_pvoidfunc_ty(irbuilder.getContext());
     139                 :      10525 :     BasicBlock *enter_bb = irbuilder.GetInsertBlock();
     140                 :      10525 :     BasicBlock *dlsym_lookup = BasicBlock::Create(irbuilder.getContext(), "dlsym");
     141                 :      10525 :     BasicBlock *ccall_bb = BasicBlock::Create(irbuilder.getContext(), "ccall");
     142                 :      10525 :     Constant *initnul = ConstantPointerNull::get(T_pvoidfunc);
     143                 :      10525 :     LoadInst *llvmf_orig = irbuilder.CreateAlignedLoad(T_pvoidfunc, llvmgv, Align(sizeof(void*)));
     144                 :            :     // This in principle needs a consume ordering so that load from
     145                 :            :     // this pointer sees a valid value. However, this is not supported by
     146                 :            :     // LLVM (or agreed on in the C/C++ standard FWIW) and should be
     147                 :            :     // almost impossible to happen on every platform we support since this
     148                 :            :     // ordering is enforced by the hardware and LLVM has to speculate an
     149                 :            :     // invalid load from the `cglobal` but doesn't depend on the `cglobal`
     150                 :            :     // value for this to happen.
     151                 :      10525 :     llvmf_orig->setAtomic(AtomicOrdering::Unordered);
     152                 :      10525 :     irbuilder.CreateCondBr(
     153                 :            :             irbuilder.CreateICmpNE(llvmf_orig, initnul),
     154                 :            :             ccall_bb,
     155                 :            :             dlsym_lookup);
     156                 :            : 
     157         [ -  + ]:      10525 :     assert(f->getParent() != NULL);
     158                 :      10525 :     f->getBasicBlockList().push_back(dlsym_lookup);
     159                 :      10525 :     irbuilder.SetInsertPoint(dlsym_lookup);
     160                 :            :     Instruction *llvmf;
     161                 :      10525 :     Value *nameval = stringConstPtr(emission_context, irbuilder, f_name);
     162         [ -  + ]:      10525 :     if (lib_expr) {
     163                 :          0 :         jl_cgval_t libval = emit_expr(*ctx, lib_expr);
     164                 :          0 :         llvmf = irbuilder.CreateCall(prepare_call_in(jl_builderModule(irbuilder), jllazydlsym_func),
     165                 :          0 :                     { boxed(*ctx, libval), nameval });
     166                 :            :     }
     167                 :            :     else {
     168                 :            :         Value *libname;
     169         [ +  + ]:      10525 :         if (runtime_lib) {
     170                 :        814 :             libname = stringConstPtr(emission_context, irbuilder, f_lib);
     171                 :            :         }
     172                 :            :         else {
     173                 :            :             // f_lib is actually one of the special sentinel values
     174                 :       9711 :             libname = ConstantExpr::getIntToPtr(ConstantInt::get(getSizeTy(irbuilder.getContext()), (uintptr_t)f_lib), getInt8PtrTy(irbuilder.getContext()));
     175                 :            :         }
     176                 :      10525 :         llvmf = irbuilder.CreateCall(prepare_call_in(jl_builderModule(irbuilder), jldlsym_func),
     177                 :            :                     { libname, nameval, libptrgv });
     178                 :            :     }
     179                 :      10525 :     StoreInst *store = irbuilder.CreateAlignedStore(llvmf, llvmgv, Align(sizeof(void*)));
     180                 :      10525 :     store->setAtomic(AtomicOrdering::Release);
     181                 :      10525 :     irbuilder.CreateBr(ccall_bb);
     182                 :            : 
     183                 :      10525 :     f->getBasicBlockList().push_back(ccall_bb);
     184                 :      10525 :     irbuilder.SetInsertPoint(ccall_bb);
     185                 :      10525 :     PHINode *p = irbuilder.CreatePHI(T_pvoidfunc, 2);
     186                 :      10525 :     p->addIncoming(llvmf_orig, enter_bb);
     187                 :      10525 :     p->addIncoming(llvmf, llvmf->getParent());
     188                 :      10525 :     return irbuilder.CreateBitCast(p, funcptype);
     189                 :            : }
     190                 :            : 
     191                 :       3245 : static Value *runtime_sym_lookup(
     192                 :            :         jl_codectx_t &ctx,
     193                 :            :         PointerType *funcptype, const char *f_lib, jl_value_t *lib_expr,
     194                 :            :         const char *f_name, Function *f,
     195                 :            :         GlobalVariable *libptrgv,
     196                 :            :         GlobalVariable *llvmgv, bool runtime_lib)
     197                 :            : {
     198                 :       3245 :     return runtime_sym_lookup(ctx.emission_context, ctx.builder, &ctx, funcptype, f_lib, lib_expr,
     199                 :       3245 :                               f_name, f, libptrgv, llvmgv, runtime_lib);
     200                 :            : }
     201                 :            : 
     202                 :       3245 : static Value *runtime_sym_lookup(
     203                 :            :         jl_codectx_t &ctx,
     204                 :            :         PointerType *funcptype, const char *f_lib, jl_value_t *lib_expr,
     205                 :            :         const char *f_name, Function *f)
     206                 :            : {
     207                 :       3245 :     auto T_pvoidfunc = JuliaType::get_pvoidfunc_ty(ctx.builder.getContext());
     208                 :            :     GlobalVariable *libptrgv;
     209                 :            :     GlobalVariable *llvmgv;
     210                 :            :     bool runtime_lib;
     211         [ -  + ]:       3245 :     if (lib_expr) {
     212                 :            :         // for computed library names, generate a global variable to cache the function
     213                 :            :         // pointer just for this call site.
     214                 :          0 :         runtime_lib = true;
     215                 :          0 :         libptrgv = NULL;
     216                 :          0 :         std::string gvname = "libname_";
     217                 :          0 :         gvname += f_name;
     218                 :          0 :         gvname += "_";
     219                 :          0 :         gvname += std::to_string(globalUniqueGeneratedNames++);
     220                 :          0 :         llvmgv = new GlobalVariable(*jl_Module, T_pvoidfunc, false,
     221                 :            :                                     GlobalVariable::ExternalLinkage,
     222                 :          0 :                                     Constant::getNullValue(T_pvoidfunc), gvname);
     223                 :            :     }
     224                 :            :     else {
     225                 :       3245 :         runtime_lib = runtime_sym_gvs(ctx, f_lib, f_name, libptrgv, llvmgv);
     226                 :       3245 :         libptrgv = prepare_global_in(jl_Module, libptrgv);
     227                 :            :     }
     228                 :       3245 :     llvmgv = prepare_global_in(jl_Module, llvmgv);
     229                 :       3245 :     return runtime_sym_lookup(ctx, funcptype, f_lib, lib_expr, f_name, f, libptrgv, llvmgv, runtime_lib);
     230                 :            : }
     231                 :            : 
     232                 :            : // Emit a "PLT" entry that will be lazily initialized
     233                 :            : // when being called the first time.
     234                 :       7280 : static GlobalVariable *emit_plt_thunk(
     235                 :            :         jl_codectx_t &ctx,
     236                 :            :         FunctionType *functype, const AttributeList &attrs,
     237                 :            :         CallingConv::ID cc, const char *f_lib, const char *f_name,
     238                 :            :         GlobalVariable *libptrgv, GlobalVariable *llvmgv,
     239                 :            :         bool runtime_lib)
     240                 :            : {
     241                 :       7280 :     ++PLTThunks;
     242                 :       7280 :     auto &TSM = ctx.emission_context.shared_module(*jl_Module);
     243                 :       7280 :     Module *M = TSM.getModuleUnlocked();
     244                 :       7280 :     PointerType *funcptype = PointerType::get(functype, 0);
     245                 :       7280 :     libptrgv = prepare_global_in(M, libptrgv);
     246                 :       7280 :     llvmgv = prepare_global_in(M, llvmgv);
     247                 :      14560 :     std::string fname;
     248                 :       7280 :     raw_string_ostream(fname) << "jlplt_" << f_name << "_" << globalUniqueGeneratedNames++;
     249                 :       7280 :     Function *plt = Function::Create(functype,
     250                 :            :                                      GlobalVariable::ExternalLinkage,
     251                 :            :                                      fname, M);
     252                 :       7280 :     plt->setAttributes(attrs);
     253         [ -  + ]:       7280 :     if (cc != CallingConv::C)
     254                 :          0 :         plt->setCallingConv(cc);
     255                 :       7280 :     fname += "_got";
     256                 :       7280 :     auto T_pvoidfunc = JuliaType::get_pvoidfunc_ty(M->getContext());
     257                 :            :     GlobalVariable *got = new GlobalVariable(*M, T_pvoidfunc, false,
     258                 :            :                                              GlobalVariable::ExternalLinkage,
     259                 :       7280 :                                              ConstantExpr::getBitCast(plt, T_pvoidfunc),
     260                 :       7280 :                                              fname);
     261                 :       7280 :     BasicBlock *b0 = BasicBlock::Create(M->getContext(), "top", plt);
     262                 :      14560 :     IRBuilder<> irbuilder(b0);
     263                 :       7280 :     Value *ptr = runtime_sym_lookup(ctx.emission_context, irbuilder, NULL, funcptype, f_lib, NULL, f_name, plt, libptrgv,
     264                 :            :                                     llvmgv, runtime_lib);
     265                 :       7280 :     StoreInst *store = irbuilder.CreateAlignedStore(irbuilder.CreateBitCast(ptr, T_pvoidfunc), got, Align(sizeof(void*)));
     266                 :       7280 :     store->setAtomic(AtomicOrdering::Release);
     267                 :       7280 :     SmallVector<Value*, 16> args;
     268         [ +  + ]:      21328 :     for (Function::arg_iterator arg = plt->arg_begin(), arg_e = plt->arg_end(); arg != arg_e; ++arg)
     269                 :      14048 :         args.push_back(&*arg);
     270         [ -  + ]:       7280 :     assert(cast<PointerType>(ptr->getType())->isOpaqueOrPointeeTypeMatches(functype));
     271                 :       7280 :     CallInst *ret = irbuilder.CreateCall(
     272                 :            :         functype,
     273                 :            :         ptr, ArrayRef<Value*>(args));
     274                 :       7280 :     ret->setAttributes(attrs);
     275         [ -  + ]:       7280 :     if (cc != CallingConv::C)
     276                 :          0 :         ret->setCallingConv(cc);
     277                 :            :     // NoReturn function can trigger LLVM verifier error when declared as
     278                 :            :     // MustTail since other passes might replace the `ret` with
     279                 :            :     // `unreachable` (LLVM should probably accept `unreachable`).
     280         [ +  + ]:       7280 :     if (hasFnAttr(attrs, Attribute::NoReturn)) {
     281                 :         22 :         irbuilder.CreateUnreachable();
     282                 :            :     }
     283                 :            :     else {
     284                 :            :         // musttail support is very bad on ARM, PPC, PPC64 (as of LLVM 3.9)
     285                 :            :         // Known failures includes vararg (not needed here) and sret.
     286                 :            : 
     287                 :            : #if (defined(_CPU_X86_) || defined(_CPU_X86_64_) || (defined(_CPU_AARCH64_) && !defined(_OS_DARWIN_)))
     288                 :            :         // Ref https://bugs.llvm.org/show_bug.cgi?id=47058
     289                 :            :         // LLVM, as of 10.0.1 emits wrong/worse code when musttail is set
     290                 :            :         // Apple silicon macs give an LLVM ERROR if musttail is set here #44107.
     291         [ +  - ]:       7258 :         if (!attrs.hasAttrSomewhere(Attribute::ByVal))
     292                 :       7258 :             ret->setTailCallKind(CallInst::TCK_MustTail);
     293                 :            : #endif
     294         [ +  + ]:       7258 :         if (functype->getReturnType() == getVoidTy(irbuilder.getContext())) {
     295                 :       1904 :             irbuilder.CreateRetVoid();
     296                 :            :         }
     297                 :            :         else {
     298                 :       5354 :             irbuilder.CreateRet(ret);
     299                 :            :         }
     300                 :            :     }
     301                 :       7280 :     irbuilder.ClearInsertionPoint();
     302                 :            : 
     303                 :       7280 :     return got;
     304                 :            : }
     305                 :            : 
     306                 :      60498 : static Value *emit_plt(
     307                 :            :         jl_codectx_t &ctx,
     308                 :            :         FunctionType *functype,
     309                 :            :         const AttributeList &attrs,
     310                 :            :         CallingConv::ID cc, const char *f_lib, const char *f_name)
     311                 :            : {
     312                 :      60498 :     ++PLT;
     313         [ -  + ]:      60498 :     assert(ctx.emission_context.imaging);
     314                 :            :     // Don't do this for vararg functions so that the `musttail` is only
     315                 :            :     // an optimization and is not required to function correctly.
     316         [ -  + ]:      60498 :     assert(!functype->isVarArg());
     317                 :            :     GlobalVariable *libptrgv;
     318                 :            :     GlobalVariable *llvmgv;
     319                 :      60498 :     bool runtime_lib = runtime_sym_gvs(ctx, f_lib, f_name, libptrgv, llvmgv);
     320                 :      60498 :     PointerType *funcptype = PointerType::get(functype, 0);
     321                 :            : 
     322                 :      60498 :     auto &pltMap = ctx.emission_context.allPltMap[attrs];
     323                 :      60498 :     auto key = std::make_tuple(llvmgv, functype, cc);
     324                 :      60498 :     GlobalVariable *&sharedgot = pltMap[key];
     325         [ +  + ]:      60498 :     if (!sharedgot) {
     326                 :       7280 :         sharedgot = emit_plt_thunk(ctx,
     327                 :            :                 functype, attrs, cc, f_lib, f_name, libptrgv, llvmgv, runtime_lib);
     328                 :            :     }
     329                 :      60498 :     GlobalVariable *got = prepare_global_in(jl_Module, sharedgot);
     330                 :      60498 :     LoadInst *got_val = ctx.builder.CreateAlignedLoad(got->getValueType(), got, Align(sizeof(void*)));
     331                 :            :     // See comment in `runtime_sym_lookup` above. This in principle needs a
     332                 :            :     // consume ordering too. This is even less likely to cause issues though
     333                 :            :     // since the only thing we do to this loaded pointer is to call it
     334                 :            :     // immediately.
     335                 :      60498 :     got_val->setAtomic(AtomicOrdering::Unordered);
     336                 :      60498 :     return ctx.builder.CreateBitCast(got_val, funcptype);
     337                 :            : }
     338                 :            : 
     339                 :            : // --- ABI Implementations ---
     340                 :            : // Partially based on the LDC ABI implementations licensed under the BSD 3-clause license
     341                 :            : 
     342                 :            : class AbiLayout {
     343                 :            : public:
     344                 :     424161 :     virtual ~AbiLayout() {}
     345                 :            :     virtual bool use_sret(jl_datatype_t *ty, LLVMContext &ctx) = 0;
     346                 :            :     virtual bool needPassByRef(jl_datatype_t *ty, AttrBuilder&, LLVMContext &ctx, Type* llvm_t) = 0;
     347                 :            :     virtual Type *preferred_llvm_type(jl_datatype_t *ty, bool isret, LLVMContext &ctx) const = 0;
     348                 :            : };
     349                 :            : 
     350                 :            : // Determine if object of bitstype ty maps to a native x86 SIMD type (__m128, __m256, or __m512) in C
     351                 :     113431 : static bool is_native_simd_type(jl_datatype_t *dt) {
     352                 :     113431 :     size_t size = jl_datatype_size(dt);
     353   [ +  +  +  -  :     113431 :     if (size != 16 && size != 32 && size != 64)
                   +  - ]
     354                 :            :         // Wrong size for xmm, ymm, or zmm register.
     355                 :     112975 :         return false;
     356                 :        456 :     uint32_t n = jl_datatype_nfields(dt);
     357         [ -  + ]:        456 :     if (n<2)
     358                 :            :         // Not mapped to SIMD register.
     359                 :          0 :         return false;
     360                 :        456 :     jl_value_t *ft0 = jl_field_type(dt, 0);
     361         [ +  + ]:        846 :     for (uint32_t i = 1; i < n; ++i)
     362         [ +  + ]:        456 :         if (jl_field_type(dt, i) != ft0)
     363                 :            :             // Not homogeneous
     364                 :         66 :             return false;
     365                 :            :     // Type is homogeneous.  Check if it maps to LLVM vector.
     366                 :        390 :     return jl_special_vector_alignment(n, ft0) != 0;
     367                 :            : }
     368                 :            : 
     369                 :            : #include "abi_llvm.cpp"
     370                 :            : 
     371                 :            : #include "abi_arm.cpp"
     372                 :            : #include "abi_aarch64.cpp"
     373                 :            : #include "abi_ppc64le.cpp"
     374                 :            : #include "abi_win32.cpp"
     375                 :            : #include "abi_win64.cpp"
     376                 :            : #include "abi_x86_64.cpp"
     377                 :            : #include "abi_x86.cpp"
     378                 :            : 
     379                 :            : #if defined ABI_LLVM
     380                 :            :   typedef ABI_LLVMLayout DefaultAbiState;
     381                 :            : #elif defined _CPU_X86_64_
     382                 :            : #  if defined _OS_WINDOWS_
     383                 :            :      typedef ABI_Win64Layout DefaultAbiState;
     384                 :            : #  else
     385                 :            :      typedef ABI_x86_64Layout DefaultAbiState;
     386                 :            : #  endif
     387                 :            : #elif defined _CPU_X86_
     388                 :            : #  if defined _OS_WINDOWS_
     389                 :            :      typedef ABI_Win32Layout DefaultAbiState;
     390                 :            : #  else
     391                 :            :      typedef ABI_x86Layout DefaultAbiState;
     392                 :            : #  endif
     393                 :            : #elif defined _CPU_ARM_
     394                 :            :   typedef ABI_ARMLayout DefaultAbiState;
     395                 :            : #elif defined _CPU_AARCH64_
     396                 :            :   typedef ABI_AArch64Layout DefaultAbiState;
     397                 :            : #elif defined _CPU_PPC64_
     398                 :            :   typedef ABI_PPC64leLayout DefaultAbiState;
     399                 :            : #else
     400                 :            : #  pragma message("ccall is defaulting to llvm ABI, since no platform ABI has been defined for this CPU/OS combination")
     401                 :            :   typedef ABI_LLVMLayout DefaultAbiState;
     402                 :            : #endif
     403                 :            : 
     404                 :            : // basic type widening and cast conversions
     405                 :     184001 : static Value *llvm_type_rewrite(
     406                 :            :         jl_codectx_t &ctx,
     407                 :            :         Value *v, Type *target_type,
     408                 :            :         bool issigned) /* determines whether an integer value should be zero or sign extended */
     409                 :            : {
     410                 :     184001 :     Type *from_type = v->getType();
     411         [ +  + ]:     184001 :     if (target_type == from_type)
     412                 :     183849 :         return v;
     413                 :            : 
     414   [ +  -  -  +  :        152 :     if (from_type == getVoidTy(ctx.builder.getContext()) || isa<UndefValue>(v))
                   -  + ]
     415                 :          0 :         return UndefValue::get(target_type); // convert undef (unreachable) -> undef (target_type)
     416                 :            : 
     417         [ -  + ]:        152 :     assert(from_type->isPointerTy() == target_type->isPointerTy()); // expect that all ABIs consider all pointers to be equivalent
     418         [ -  + ]:        152 :     if (target_type->isPointerTy())
     419                 :          0 :         return emit_bitcast(ctx, v, target_type);
     420                 :            : 
     421                 :            :     // simple integer and float widening & conversion cases
     422   [ -  +  -  - ]:        152 :     if (from_type->getPrimitiveSizeInBits() > 0 &&
     423         [ -  + ]:        152 :             target_type->getPrimitiveSizeInBits() == from_type->getPrimitiveSizeInBits())
     424                 :          0 :         return emit_bitcast(ctx, v, target_type);
     425                 :            : 
     426   [ -  +  -  -  :        152 :     if (target_type->isFloatingPointTy() && from_type->isFloatingPointTy()) {
                   -  + ]
     427         [ #  # ]:          0 :         if (target_type->getPrimitiveSizeInBits() > from_type->getPrimitiveSizeInBits())
     428                 :          0 :             return ctx.builder.CreateFPExt(v, target_type);
     429         [ #  # ]:          0 :         else if (target_type->getPrimitiveSizeInBits() < from_type->getPrimitiveSizeInBits())
     430                 :          0 :             return ctx.builder.CreateFPTrunc(v, target_type);
     431                 :            :         else
     432                 :          0 :             return v;
     433                 :            :     }
     434                 :            : 
     435   [ -  +  -  -  :        152 :     if (target_type->isIntegerTy() && from_type->isIntegerTy()) {
                   -  + ]
     436         [ #  # ]:          0 :         if (issigned)
     437                 :          0 :             return ctx.builder.CreateSExtOrTrunc(v, target_type);
     438                 :            :         else
     439                 :          0 :             return ctx.builder.CreateZExtOrTrunc(v, target_type);
     440                 :            :     }
     441                 :            : 
     442                 :            :     // one or both of from_type and target_type is a VectorType or AggregateType
     443                 :            :     // LLVM doesn't allow us to cast these values directly, so
     444                 :            :     // we need to use this alloca copy trick instead
     445                 :            :     // On ARM and AArch64, the ABI requires casting through memory to different
     446                 :            :     // sizes.
     447                 :            :     Value *from;
     448                 :            :     Value *to;
     449                 :        152 :     const DataLayout &DL = ctx.builder.GetInsertBlock()->getModule()->getDataLayout();
     450                 :        152 :     unsigned align = std::max(DL.getPrefTypeAlignment(target_type), DL.getPrefTypeAlignment(from_type));
     451         [ +  - ]:        152 :     if (DL.getTypeAllocSize(target_type) >= DL.getTypeAllocSize(from_type)) {
     452                 :        152 :         to = emit_static_alloca(ctx, target_type);
     453                 :        152 :         cast<AllocaInst>(to)->setAlignment(Align(align));
     454                 :        152 :         from = emit_bitcast(ctx, to, from_type->getPointerTo());
     455                 :            :     }
     456                 :            :     else {
     457                 :          0 :         from = emit_static_alloca(ctx, from_type);
     458                 :          0 :         cast<AllocaInst>(from)->setAlignment(Align(align));
     459                 :          0 :         to = emit_bitcast(ctx, from, target_type->getPointerTo());
     460                 :            :     }
     461                 :        152 :     ctx.builder.CreateAlignedStore(v, from, Align(align));
     462                 :        152 :     return ctx.builder.CreateAlignedLoad(target_type, to, Align(align));
     463                 :            : }
     464                 :            : 
     465                 :            : // --- argument passing and scratch space utilities ---
     466                 :            : 
     467                 :            : // Returns ctx.types().T_prjlvalue
     468                 :          1 : static Value *runtime_apply_type_env(jl_codectx_t &ctx, jl_value_t *ty)
     469                 :            : {
     470                 :            :     // box if concrete type was not statically known
     471                 :            :     Value *args[] = {
     472                 :          1 :         literal_pointer_val(ctx, ty),
     473                 :          1 :         literal_pointer_val(ctx, (jl_value_t*)ctx.linfo->def.method->sig),
     474                 :          1 :         ctx.builder.CreateInBoundsGEP(
     475                 :          1 :                 ctx.types().T_prjlvalue,
     476                 :            :                 ctx.spvals_ptr,
     477                 :          1 :                 ConstantInt::get(getSizeTy(ctx.builder.getContext()), sizeof(jl_svec_t) / sizeof(jl_value_t*)))
     478                 :          1 :     };
     479                 :          1 :     auto call = ctx.builder.CreateCall(prepare_call(jlapplytype_func), makeArrayRef(args));
     480                 :          1 :     addRetAttr(call, Attribute::getWithAlignment(ctx.builder.getContext(), Align(16)));
     481                 :          1 :     return call;
     482                 :            : }
     483                 :            : 
     484                 :         72 : static const std::string make_errmsg(const char *fname, int n, const char *err)
     485                 :            : {
     486                 :        144 :     std::string _msg;
     487                 :        144 :     raw_string_ostream msg(_msg);
     488                 :         72 :     msg << fname;
     489         [ +  + ]:         72 :     if (n > 0)
     490                 :         71 :         msg << " argument " << n;
     491                 :            :     else
     492                 :          1 :         msg << " return";
     493                 :         72 :     msg << err;
     494                 :         72 :     return msg.str();
     495                 :            : }
     496                 :            : 
     497                 :      94301 : static void typeassert_input(jl_codectx_t &ctx, const jl_cgval_t &jvinfo, jl_value_t *jlto, jl_unionall_t *jlto_env, int argn)
     498                 :            : {
     499   [ +  -  +  +  :      94301 :     if (jlto != (jl_value_t*)jl_any_type && !jl_subtype(jvinfo.typ, jlto)) {
                   +  + ]
     500         [ +  + ]:        775 :         if (jlto == (jl_value_t*)jl_voidpointer_type) {
     501                 :            :             // allow a bit more flexibility for what can be passed to (void*) due to Ref{T} conversion behavior in input
     502         [ +  + ]:        712 :             if (!jl_is_cpointer_type(jvinfo.typ)) {
     503                 :            :                 // emit a typecheck, if not statically known to be correct
     504                 :          8 :                 emit_cpointercheck(ctx, jvinfo, make_errmsg("ccall", argn + 1, ""));
     505                 :            :             }
     506                 :            :         }
     507                 :            :         else {
     508                 :            :             // emit a typecheck, if not statically known to be correct
     509                 :        126 :             std::string msg = make_errmsg("ccall", argn + 1, "");
     510   [ +  +  +  -  :         63 :             if (!jlto_env || !jl_has_typevar_from_unionall(jlto, jlto_env)) {
                   +  - ]
     511                 :         63 :                 emit_typecheck(ctx, jvinfo, jlto, msg);
     512                 :            :             }
     513                 :            :             else {
     514                 :          0 :                 jl_cgval_t jlto_runtime = mark_julia_type(ctx, runtime_apply_type_env(ctx, jlto), true, jl_any_type);
     515                 :          0 :                 Value *vx = boxed(ctx, jvinfo);
     516                 :          0 :                 Value *istype = ctx.builder.CreateICmpNE(
     517                 :          0 :                         ctx.builder.CreateCall(prepare_call(jlisa_func), { vx, boxed(ctx, jlto_runtime) }),
     518                 :          0 :                         ConstantInt::get(getInt32Ty(ctx.builder.getContext()), 0));
     519                 :          0 :                 BasicBlock *failBB = BasicBlock::Create(ctx.builder.getContext(), "fail", ctx.f);
     520                 :          0 :                 BasicBlock *passBB = BasicBlock::Create(ctx.builder.getContext(), "pass", ctx.f);
     521                 :          0 :                 ctx.builder.CreateCondBr(istype, passBB, failBB);
     522                 :            : 
     523                 :          0 :                 ctx.builder.SetInsertPoint(failBB);
     524                 :          0 :                 emit_type_error(ctx, mark_julia_type(ctx, vx, true, jl_any_type), boxed(ctx, jlto_runtime), msg);
     525                 :          0 :                 ctx.builder.CreateUnreachable();
     526                 :          0 :                 ctx.builder.SetInsertPoint(passBB);
     527                 :            :             }
     528                 :            :         }
     529                 :            :     }
     530                 :      94301 : }
     531                 :            : 
     532                 :            : // Emit code to convert argument to form expected by C ABI
     533                 :            : // to = desired LLVM type
     534                 :            : // jlto = Julia type of formal argument
     535                 :            : // jvinfo = value of actual argument
     536                 :     183207 : static Value *julia_to_native(
     537                 :            :         jl_codectx_t &ctx,
     538                 :            :         Type *to, bool toboxed, jl_value_t *jlto, jl_unionall_t *jlto_env,
     539                 :            :         const jl_cgval_t &jvinfo,
     540                 :            :         bool byRef, int argn)
     541                 :            : {
     542                 :            :     // We're passing Any
     543         [ +  + ]:     183207 :     if (toboxed) {
     544         [ -  + ]:      88906 :         assert(!byRef); // don't expect any ABI to pass pointers by pointer
     545                 :      88906 :         return boxed(ctx, jvinfo);
     546                 :            :     }
     547   [ +  -  +  - ]:      94301 :     assert(jl_is_datatype(jlto) && jl_struct_try_layout((jl_datatype_t*)jlto));
     548                 :            : 
     549                 :      94301 :     typeassert_input(ctx, jvinfo, jlto, jlto_env, argn);
     550         [ +  - ]:      94301 :     if (!byRef)
     551                 :      94301 :         return emit_unbox(ctx, to, jvinfo, jlto);
     552                 :            : 
     553                 :            :     // pass the address of an alloca'd thing, not a box
     554                 :            :     // since those are immutable.
     555                 :          0 :     Value *slot = emit_static_alloca(ctx, to);
     556         [ #  # ]:          0 :     if (!jvinfo.ispointer()) {
     557                 :          0 :         tbaa_decorate(jvinfo.tbaa, ctx.builder.CreateStore(emit_unbox(ctx, to, jvinfo, jlto), slot));
     558                 :            :     }
     559                 :            :     else {
     560                 :          0 :         emit_memcpy(ctx, slot, jvinfo.tbaa, jvinfo, jl_datatype_size(jlto), julia_alignment(jlto));
     561                 :            :     }
     562                 :          0 :     return slot;
     563                 :            : }
     564                 :            : 
     565                 :            : typedef struct {
     566                 :            :     Value *jl_ptr;  // if the argument is a run-time computed pointer
     567                 :            :     void (*fptr)(void);     // if the argument is a constant pointer
     568                 :            :     const char *f_name;   // if the symbol name is known
     569                 :            :     const char *f_lib;    // if a library name is specified
     570                 :            :     jl_value_t *lib_expr; // expression to compute library path lazily
     571                 :            :     jl_value_t *gcroot;
     572                 :            : } native_sym_arg_t;
     573                 :            : 
     574                 :            : // --- parse :sym or (:sym, :lib) argument into address info ---
     575                 :     165962 : static void interpret_symbol_arg(jl_codectx_t &ctx, native_sym_arg_t &out, jl_value_t *arg, const char *fname, bool llvmcall)
     576                 :            : {
     577                 :     165962 :     Value *&jl_ptr = out.jl_ptr;
     578                 :     165962 :     void (*&fptr)(void) = out.fptr;
     579                 :     165962 :     const char *&f_name = out.f_name;
     580                 :     165962 :     const char *&f_lib = out.f_lib;
     581                 :            : 
     582                 :     165962 :     jl_value_t *ptr = static_eval(ctx, arg);
     583         [ -  + ]:     165962 :     if (ptr == NULL) {
     584   [ #  #  #  # ]:          0 :         if (jl_is_expr(arg) && ((jl_expr_t*)arg)->head == jl_call_sym && jl_expr_nargs(arg) == 3 &&
     585   [ #  #  #  #  :          0 :             jl_is_globalref(jl_exprarg(arg,0)) && jl_globalref_mod(jl_exprarg(arg,0)) == jl_core_module &&
          #  #  #  #  #  
                      # ]
     586                 :          0 :             jl_globalref_name(jl_exprarg(arg,0)) == jl_symbol("tuple")) {
     587                 :            :             // attempt to interpret a non-constant 2-tuple expression as (func_name, lib_name()), where
     588                 :            :             // `lib_name()` will be executed when first used.
     589                 :          0 :             jl_value_t *name_val = static_eval(ctx, jl_exprarg(arg,1));
     590   [ #  #  #  # ]:          0 :             if (name_val && jl_is_symbol(name_val)) {
     591                 :          0 :                 f_name = jl_symbol_name((jl_sym_t*)name_val);
     592                 :          0 :                 out.lib_expr = jl_exprarg(arg, 2);
     593                 :          0 :                 return;
     594                 :            :             }
     595   [ #  #  #  # ]:          0 :             else if (name_val && jl_is_string(name_val)) {
     596                 :          0 :                 f_name = jl_string_data(name_val);
     597                 :          0 :                 out.gcroot = name_val;
     598                 :          0 :                 out.lib_expr = jl_exprarg(arg, 2);
     599                 :          0 :                 return;
     600                 :            :             }
     601                 :            :         }
     602                 :          0 :         jl_cgval_t arg1 = emit_expr(ctx, arg);
     603                 :          0 :         jl_value_t *ptr_ty = arg1.typ;
     604         [ #  # ]:          0 :         if (!jl_is_cpointer_type(ptr_ty)) {
     605         [ #  # ]:          0 :             const char *errmsg = !strcmp(fname, "ccall") ?
     606                 :            :                 "ccall: first argument not a pointer or valid constant expression" :
     607                 :            :                 "cglobal: first argument not a pointer or valid constant expression";
     608                 :          0 :             emit_cpointercheck(ctx, arg1, errmsg);
     609                 :            :         }
     610                 :          0 :         arg1 = update_julia_type(ctx, arg1, (jl_value_t*)jl_voidpointer_type);
     611                 :          0 :         jl_ptr = emit_unbox(ctx, getSizeTy(ctx.builder.getContext()), arg1, (jl_value_t*)jl_voidpointer_type);
     612                 :            :     }
     613                 :            :     else {
     614                 :     165962 :         out.gcroot = ptr;
     615   [ +  +  -  + ]:     165962 :         if (jl_is_tuple(ptr) && jl_nfields(ptr) == 1) {
     616                 :          0 :             ptr = jl_fieldref(ptr, 0);
     617                 :            :         }
     618                 :            : 
     619         [ +  + ]:     165962 :         if (jl_is_symbol(ptr))
     620                 :     163438 :             f_name = jl_symbol_name((jl_sym_t*)ptr);
     621         [ +  + ]:       2524 :         else if (jl_is_string(ptr))
     622                 :          4 :             f_name = jl_string_data(ptr);
     623                 :            : 
     624         [ +  + ]:     165962 :         if (f_name != NULL) {
     625                 :            :             // just symbol, default to JuliaDLHandle
     626                 :            :             // will look in process symbol table
     627         [ +  + ]:     163442 :             if (!llvmcall) {
     628                 :            :                 void *symaddr;
     629                 :     326876 :                 std::string iname("i");
     630                 :     163438 :                 iname += f_name;
     631         [ +  + ]:     163438 :                 if (jl_dlsym(jl_libjulia_internal_handle, iname.c_str(), &symaddr, 0)) {
     632                 :            : #ifdef _OS_WINDOWS_
     633                 :            :                     f_lib = JL_LIBJULIA_INTERNAL_DL_LIBNAME;
     634                 :            : #endif
     635                 :     130880 :                     f_name = jl_symbol_name(jl_symbol(iname.c_str()));
     636                 :            :                 }
     637                 :            : #ifdef _OS_WINDOWS_
     638                 :            :                 else {
     639                 :            :                     f_lib = jl_dlfind_win32(f_name);
     640                 :            :                 }
     641                 :            : #endif
     642                 :            :             }
     643                 :            :         }
     644         [ -  + ]:       2520 :         else if (jl_is_cpointer_type(jl_typeof(ptr))) {
     645                 :          0 :             fptr = *(void(**)(void))jl_data_ptr(ptr);
     646                 :            :         }
     647   [ +  -  +  - ]:       2520 :         else if (jl_is_tuple(ptr) && jl_nfields(ptr) > 1) {
     648                 :       2520 :             jl_value_t *t0 = jl_fieldref(ptr, 0);
     649         [ +  + ]:       2520 :             if (jl_is_symbol(t0))
     650                 :       2344 :                 f_name = jl_symbol_name((jl_sym_t*)t0);
     651         [ +  - ]:        176 :             else if (jl_is_string(t0))
     652                 :        176 :                 f_name = jl_string_data(t0);
     653                 :            :             else
     654         [ #  # ]:          0 :                 JL_TYPECHKS(fname, symbol, t0);
     655                 :            : 
     656                 :       2520 :             jl_value_t *t1 = jl_fieldref(ptr, 1);
     657         [ +  + ]:       2520 :             if (jl_is_symbol(t1))
     658                 :       1208 :                 f_lib = jl_symbol_name((jl_sym_t*)t1);
     659         [ +  - ]:       1312 :             else if (jl_is_string(t1))
     660                 :       1312 :                 f_lib = jl_string_data(t1);
     661                 :            :             else
     662         [ -  - ]:       2520 :                 JL_TYPECHKS(fname, symbol, t1);
     663                 :            :         }
     664                 :            :         else {
     665         [ #  # ]:          0 :             JL_TYPECHKS(fname, pointer, ptr);
     666                 :            :         }
     667                 :            :     }
     668                 :            : }
     669                 :            : 
     670                 :            : // --- code generator for cglobal ---
     671                 :            : 
     672                 :            : static jl_cgval_t emit_runtime_call(jl_codectx_t &ctx, JL_I::intrinsic f, const jl_cgval_t *argv, size_t nargs);
     673                 :            : 
     674                 :       3299 : static jl_cgval_t emit_cglobal(jl_codectx_t &ctx, jl_value_t **args, size_t nargs)
     675                 :            : {
     676                 :       3299 :     ++EmittedCGlobals;
     677   [ -  +  -  + ]:       3299 :     JL_NARGS(cglobal, 1, 2);
     678                 :       3299 :     jl_value_t *rt = NULL;
     679                 :            :     Value *res;
     680                 :       3299 :     native_sym_arg_t sym = {};
     681                 :       3299 :     JL_GC_PUSH2(&rt, &sym.gcroot);
     682                 :            : 
     683         [ +  + ]:       3299 :     if (nargs == 2) {
     684                 :       3167 :         rt = static_eval(ctx, args[2]);
     685         [ -  + ]:       3167 :         if (rt == NULL) {
     686                 :          0 :             JL_GC_POP();
     687                 :          0 :             jl_cgval_t argv[2] = {jl_cgval_t(), jl_cgval_t()};
     688                 :          0 :             argv[0] = emit_expr(ctx, args[1]);
     689                 :          0 :             argv[1] = emit_expr(ctx, args[2]);
     690                 :          0 :             return emit_runtime_call(ctx, JL_I::cglobal, argv, nargs);
     691                 :            :         }
     692                 :            : 
     693         [ -  + ]:       3167 :         JL_TYPECHK(cglobal, type, rt);
     694                 :       3167 :         rt = (jl_value_t*)jl_apply_type1((jl_value_t*)jl_pointer_type, rt);
     695                 :            :     }
     696                 :            :     else {
     697                 :        132 :         rt = (jl_value_t*)jl_voidpointer_type;
     698                 :            :     }
     699                 :       3299 :     Type *lrt = getSizeTy(ctx.builder.getContext());
     700         [ -  + ]:       3299 :     assert(lrt == julia_type_to_llvm(ctx, rt));
     701                 :            : 
     702                 :       3299 :     interpret_symbol_arg(ctx, sym, args[1], "cglobal", false);
     703                 :            : 
     704         [ -  + ]:       3299 :     if (sym.jl_ptr != NULL) {
     705                 :          0 :         res = ctx.builder.CreateBitCast(sym.jl_ptr, lrt);
     706                 :            :     }
     707         [ -  + ]:       3299 :     else if (sym.fptr != NULL) {
     708                 :          0 :         res = ConstantInt::get(lrt, (uint64_t)sym.fptr);
     709         [ #  # ]:          0 :         if (ctx.emission_context.imaging)
     710                 :          0 :             jl_printf(JL_STDERR,"WARNING: literal address used in cglobal for %s; code cannot be statically compiled\n", sym.f_name);
     711                 :            :     }
     712                 :            :     else {
     713         [ -  + ]:       3299 :         if (sym.lib_expr) {
     714                 :          0 :             res = runtime_sym_lookup(ctx, cast<PointerType>(getInt8PtrTy(ctx.builder.getContext())), NULL, sym.lib_expr, sym.f_name, ctx.f);
     715                 :            :         }
     716         [ +  + ]:       3299 :         else if (ctx.emission_context.imaging) {
     717                 :       1791 :             res = runtime_sym_lookup(ctx, cast<PointerType>(getInt8PtrTy(ctx.builder.getContext())), sym.f_lib, NULL, sym.f_name, ctx.f);
     718                 :       1791 :             res = ctx.builder.CreatePtrToInt(res, lrt);
     719                 :            :         }
     720                 :            :         else {
     721                 :            :             void *symaddr;
     722                 :            : 
     723                 :       1508 :             void* libsym = jl_get_library_(sym.f_lib, 0);
     724   [ +  -  -  +  :       1508 :             if (!libsym || !jl_dlsym(libsym, sym.f_name, &symaddr, 0)) {
                   -  + ]
     725                 :            :                 // Error mode, either the library or the symbol couldn't be find during compiletime.
     726                 :            :                 // Fallback to a runtime symbol lookup.
     727                 :          0 :                 res = runtime_sym_lookup(ctx, cast<PointerType>(getInt8PtrTy(ctx.builder.getContext())), sym.f_lib, NULL, sym.f_name, ctx.f);
     728                 :          0 :                 res = ctx.builder.CreatePtrToInt(res, lrt);
     729                 :            :             } else {
     730                 :            :                 // since we aren't saving this code, there's no sense in
     731                 :            :                 // putting anything complicated here: just JIT the address of the cglobal
     732                 :       1508 :                 res = ConstantInt::get(lrt, (uint64_t)symaddr);
     733                 :            :             }
     734                 :            :         }
     735                 :            :     }
     736                 :            : 
     737                 :       3299 :     JL_GC_POP();
     738                 :       3299 :     return mark_julia_type(ctx, res, false, rt);
     739                 :            : }
     740                 :            : 
     741                 :            : // --- code generator for llvmcall ---
     742                 :            : 
     743                 :        410 : static jl_cgval_t emit_llvmcall(jl_codectx_t &ctx, jl_value_t **args, size_t nargs)
     744                 :            : {
     745                 :        410 :     ++EmittedLLVMCalls;
     746                 :            :     // parse and validate arguments
     747                 :            :     //
     748                 :            :     // two forms of llvmcall are supported:
     749                 :            :     // - llvmcall(ir, (rettypes...), (argtypes...), args...)
     750                 :            :     //   where `ir` represents IR that should be pasted in a function body
     751                 :            :     // - llvmcall((mod, fn), (rettypes...), (argtypes...), args...)
     752                 :            :     //   where `mod` represents the assembly of an entire LLVM module,
     753                 :            :     //   and `fn` the name of the function to call
     754         [ -  + ]:        410 :     JL_NARGSV(llvmcall, 3);
     755                 :        410 :     jl_value_t *rt = NULL, *at = NULL, *ir = NULL, *entry = NULL;
     756                 :        410 :     jl_value_t *ir_arg = args[1];
     757                 :        410 :     JL_GC_PUSH4(&ir, &rt, &at, &entry);
     758         [ -  + ]:        410 :     if (jl_is_ssavalue(ir_arg))
     759                 :          0 :         ir_arg = jl_arrayref((jl_array_t*)ctx.source->code, ((jl_ssavalue_t*)ir_arg)->id - 1);
     760                 :        410 :     ir = static_eval(ctx, ir_arg);
     761         [ -  + ]:        410 :     if (!ir) {
     762                 :          0 :         emit_error(ctx, "error statically evaluating llvm IR argument");
     763                 :          0 :         return jl_cgval_t();
     764                 :            :     }
     765   [ -  +  -  - ]:        410 :     if (jl_is_ssavalue(args[2]) && !jl_is_long(ctx.source->ssavaluetypes)) {
     766                 :          0 :         jl_value_t *rtt = jl_arrayref((jl_array_t*)ctx.source->ssavaluetypes, ((jl_ssavalue_t*)args[2])->id - 1);
     767         [ #  # ]:          0 :         if (jl_is_type_type(rtt))
     768                 :          0 :             rt = jl_tparam0(rtt);
     769                 :            :     }
     770         [ +  - ]:        410 :     if (!rt) {
     771                 :        410 :         rt = static_eval(ctx, args[2]);
     772         [ -  + ]:        410 :         if (!rt) {
     773                 :          0 :             emit_error(ctx, "error statically evaluating llvmcall return type");
     774                 :          0 :             return jl_cgval_t();
     775                 :            :         }
     776                 :            :     }
     777   [ -  +  -  - ]:        410 :     if (jl_is_ssavalue(args[3]) && !jl_is_long(ctx.source->ssavaluetypes)) {
     778                 :          0 :         jl_value_t *att = jl_arrayref((jl_array_t*)ctx.source->ssavaluetypes, ((jl_ssavalue_t*)args[3])->id - 1);
     779         [ #  # ]:          0 :         if (jl_is_type_type(att))
     780                 :          0 :             at = jl_tparam0(att);
     781                 :            :     }
     782         [ +  - ]:        410 :     if (!at) {
     783                 :        410 :         at = static_eval(ctx, args[3]);
     784         [ -  + ]:        410 :         if (!at) {
     785                 :          0 :             emit_error(ctx, "error statically evaluating llvmcall argument tuple");
     786                 :          0 :             return jl_cgval_t();
     787                 :            :         }
     788                 :            :     }
     789         [ -  + ]:        410 :     if (jl_is_tuple(ir)) {
     790                 :            :         // if the IR is a tuple, we expect (mod, fn)
     791         [ #  # ]:          0 :         if (jl_nfields(ir) != 2) {
     792                 :          0 :             emit_error(ctx, "Tuple as first argument to llvmcall must have exactly two children");
     793                 :          0 :             return jl_cgval_t();
     794                 :            :         }
     795                 :          0 :         entry = jl_fieldref(ir, 1);
     796         [ #  # ]:          0 :         if (!jl_is_string(entry)) {
     797                 :          0 :             emit_error(ctx, "Function name passed to llvmcall must be a string");
     798                 :          0 :             return jl_cgval_t();
     799                 :            :         }
     800                 :          0 :         ir = jl_fieldref(ir, 0);
     801                 :            : 
     802   [ #  #  #  # ]:          0 :         if (!jl_is_string(ir) && !jl_typeis(ir, jl_array_uint8_type)) {
     803                 :          0 :             emit_error(ctx, "Module IR passed to llvmcall must be a string or an array of bytes");
     804                 :          0 :             return jl_cgval_t();
     805                 :            :         }
     806                 :            :     }
     807                 :            :     else {
     808         [ -  + ]:        410 :         if (!jl_is_string(ir)) {
     809                 :          0 :             emit_error(ctx, "Function IR passed to llvmcall must be a string");
     810                 :          0 :             return jl_cgval_t();
     811                 :            :         }
     812                 :            :     }
     813                 :            : 
     814         [ -  + ]:        410 :     JL_TYPECHK(llvmcall, type, rt);
     815         [ -  + ]:        410 :     JL_TYPECHK(llvmcall, type, at);
     816                 :            : 
     817                 :            :     // Generate arguments
     818                 :        820 :     std::string arguments;
     819                 :        820 :     raw_string_ostream argstream(arguments);
     820                 :        410 :     jl_svec_t *tt = ((jl_datatype_t*)at)->parameters;
     821                 :        410 :     jl_value_t *rtt = rt;
     822                 :        410 :     size_t nargt = jl_svec_len(tt);
     823                 :            : 
     824                 :            :     /*
     825                 :            :      * Semantics for arguments are as follows:
     826                 :            :      * If the argument type is immutable (including bitstype), we pass the loaded llvm value
     827                 :            :      * type. Otherwise we pass a pointer to a jl_value_t.
     828                 :            :      */
     829                 :        820 :     std::vector<llvm::Type*> argtypes;
     830                 :        410 :     Value **argvals = (Value**)alloca(nargt * sizeof(Value*));
     831         [ +  + ]:       1096 :     for (size_t i = 0; i < nargt; ++i) {
     832                 :        686 :         jl_value_t *tti = jl_svecref(tt,i);
     833                 :            :         bool toboxed;
     834                 :        686 :         Type *t = julia_type_to_llvm(ctx, tti, &toboxed);
     835                 :        686 :         argtypes.push_back(t);
     836         [ -  + ]:        686 :         if (4 + i > nargs) {
     837                 :          0 :             emit_error(ctx, "Missing arguments to llvmcall!");
     838                 :          0 :             return jl_cgval_t();
     839                 :            :         }
     840                 :        686 :         jl_value_t *argi = args[4 + i];
     841                 :        686 :         jl_cgval_t arg = emit_expr(ctx, argi);
     842                 :            : 
     843                 :        686 :         Value *v = julia_to_native(ctx, t, toboxed, tti, NULL, arg, false, i);
     844   [ +  -  +  + ]:        686 :         bool issigned = jl_signed_type && jl_subtype(tti, (jl_value_t*)jl_signed_type);
     845                 :        686 :         argvals[i] = llvm_type_rewrite(ctx, v, t, issigned);
     846                 :            :     }
     847                 :            : 
     848                 :            :     bool retboxed;
     849                 :        410 :     Type *rettype = julia_type_to_llvm(ctx, rtt, &retboxed);
     850                 :            : 
     851                 :            :     // Make sure to find a unique name
     852                 :        820 :     std::string ir_name;
     853                 :            :     while (true) {
     854                 :        410 :         raw_string_ostream(ir_name) << (ctx.f->getName().str()) << "u" << globalUniqueGeneratedNames++;
     855         [ +  - ]:        410 :         if (jl_Module->getFunction(ir_name) == NULL)
     856                 :        410 :             break;
     857                 :            :     }
     858                 :            : 
     859                 :            :     // generate a temporary module that contains our IR
     860                 :        410 :     std::unique_ptr<Module> Mod;
     861         [ +  - ]:        410 :     if (entry == NULL) {
     862                 :            :         // we only have function IR, which we should put in a function
     863                 :            : 
     864                 :        410 :         bool first = true;
     865         [ +  + ]:       1096 :         for (std::vector<Type *>::iterator it = argtypes.begin(); it != argtypes.end(); ++it) {
     866         [ +  + ]:        686 :             if (!first)
     867                 :        276 :                 argstream << ",";
     868                 :            :             else
     869                 :        410 :                 first = false;
     870                 :        686 :             (*it)->print(argstream);
     871                 :        686 :             argstream << " ";
     872                 :            :         }
     873                 :            : 
     874                 :        410 :         std::string rstring;
     875                 :        410 :         raw_string_ostream rtypename(rstring);
     876                 :        410 :         rettype->print(rtypename);
     877                 :        410 :         std::map<uint64_t,std::string> localDecls;
     878                 :            : 
     879                 :        410 :         std::string ir_string;
     880                 :        410 :         raw_string_ostream ir_stream(ir_string);
     881                 :        410 :         ir_stream << "; Number of arguments: " << nargt << "\n"
     882                 :        410 :         << "define "<<rtypename.str()<<" @\"" << ir_name << "\"("<<argstream.str()<<") {\n"
     883                 :        410 :         << jl_string_data(ir) << "\n}";
     884                 :            : 
     885                 :        410 :         SMDiagnostic Err = SMDiagnostic();
     886                 :        410 :         Mod = parseAssemblyString(ir_stream.str(), Err, ctx.builder.getContext());
     887         [ -  + ]:        410 :         if (!Mod) {
     888                 :          0 :             std::string message = "Failed to parse LLVM assembly: \n";
     889                 :          0 :             raw_string_ostream stream(message);
     890                 :          0 :             Err.print("", stream, true);
     891                 :          0 :             emit_error(ctx, stream.str());
     892                 :          0 :             return jl_cgval_t();
     893                 :            :         }
     894                 :            : 
     895                 :        410 :         Function *f = Mod->getFunction(ir_name);
     896                 :        410 :         f->addFnAttr(Attribute::AlwaysInline);
     897                 :            :     }
     898                 :            :     else {
     899                 :            :         // we have the IR or bitcode of an entire module, which we can parse directly
     900                 :            : 
     901         [ #  # ]:          0 :         if (jl_is_string(ir)) {
     902                 :          0 :             SMDiagnostic Err = SMDiagnostic();
     903                 :          0 :             Mod = parseAssemblyString(jl_string_data(ir), Err, ctx.builder.getContext());
     904         [ #  # ]:          0 :             if (!Mod) {
     905                 :          0 :                 std::string message = "Failed to parse LLVM assembly: \n";
     906                 :          0 :                 raw_string_ostream stream(message);
     907                 :          0 :                 Err.print("", stream, true);
     908                 :          0 :                 emit_error(ctx, stream.str());
     909                 :          0 :                 return jl_cgval_t();
     910                 :            :             }
     911                 :            :         }
     912                 :            :         else {
     913                 :            :             auto Buf = MemoryBuffer::getMemBuffer(
     914                 :          0 :                 StringRef((char *)jl_array_data(ir), jl_array_len(ir)), "llvmcall",
     915                 :          0 :                 /*RequiresNullTerminator*/ false);
     916                 :            :             Expected<std::unique_ptr<Module>> ModuleOrErr =
     917                 :          0 :                 parseBitcodeFile(*Buf, ctx.builder.getContext());
     918         [ #  # ]:          0 :             if (Error Err = ModuleOrErr.takeError()) {
     919                 :          0 :                 std::string Message;
     920                 :          0 :                 handleAllErrors(std::move(Err),
     921                 :          0 :                                 [&](ErrorInfoBase &EIB) { Message = EIB.message(); });
     922                 :          0 :                 std::string message = "Failed to parse LLVM bitcode: \n";
     923                 :          0 :                 raw_string_ostream stream(message);
     924                 :          0 :                 stream << Message;
     925                 :          0 :                 emit_error(ctx, stream.str());
     926                 :          0 :                 return jl_cgval_t();
     927                 :            :             }
     928                 :          0 :             Mod = std::move(ModuleOrErr.get());
     929                 :            :         }
     930                 :            : 
     931                 :          0 :         Function *f = Mod->getFunction(jl_string_data(entry));
     932         [ #  # ]:          0 :         if (!f) {
     933                 :          0 :             emit_error(ctx, "Module IR does not contain specified entry function");
     934                 :          0 :             return jl_cgval_t();
     935                 :            :         }
     936                 :          0 :         f->setName(ir_name);
     937                 :            : 
     938                 :            :         // verify the function type
     939         [ #  # ]:          0 :         assert(!f->isDeclaration());
     940         [ #  # ]:          0 :         assert(f->getReturnType() == rettype);
     941                 :          0 :         int i = 0;
     942                 :          0 :         for (std::vector<Type *>::iterator it = argtypes.begin();
     943         [ #  # ]:          0 :             it != argtypes.end(); ++it, ++i)
     944         [ #  # ]:          0 :             assert(*it == f->getFunctionType()->getParamType(i));
     945                 :            :     }
     946                 :            : 
     947                 :            :     // copy module properties that should always match
     948                 :        410 :     Mod->setTargetTriple(jl_Module->getTargetTriple());
     949                 :        410 :     Mod->setDataLayout(jl_Module->getDataLayout());
     950                 :            : #if JL_LLVM_VERSION >= 130000
     951                 :        410 :     Mod->setStackProtectorGuard(jl_Module->getStackProtectorGuard());
     952                 :        410 :     Mod->setOverrideStackAlignment(jl_Module->getOverrideStackAlignment());
     953                 :            : #endif
     954                 :            : 
     955                 :            :     // verify the definition
     956                 :        410 :     Function *def = Mod->getFunction(ir_name);
     957         [ -  + ]:        410 :     assert(def);
     958                 :        820 :     std::string message = "Malformed LLVM function: \n";
     959                 :        820 :     raw_string_ostream stream(message);
     960         [ -  + ]:        410 :     if (verifyFunction(*def, &stream)) {
     961                 :          0 :         emit_error(ctx, stream.str());
     962                 :          0 :         return jl_cgval_t();
     963                 :            :     }
     964                 :        410 :     def->setLinkage(GlobalVariable::LinkOnceODRLinkage);
     965                 :            : 
     966                 :            :     // generate a call
     967                 :        410 :     FunctionType *decl_typ = FunctionType::get(rettype, argtypes, def->isVarArg());
     968                 :        410 :     Function *decl = Function::Create(decl_typ, def->getLinkage(), def->getAddressSpace(),
     969                 :        410 :                                       def->getName(), jl_Module);
     970                 :        410 :     decl->setAttributes(def->getAttributes());
     971                 :        410 :     CallInst *inst = ctx.builder.CreateCall(decl, ArrayRef<Value *>(&argvals[0], nargt));
     972                 :            : 
     973                 :            :     // save the module to be linked later.
     974                 :            :     // we cannot do this right now, because linking mutates the destination module,
     975                 :            :     // which might invalidate LLVM values cached in cgval_t's (specifically constant arrays)
     976                 :        410 :     ctx.llvmcall_modules.push_back(orc::ThreadSafeModule(std::move(Mod), ctx.emission_context.tsctx));
     977                 :            : 
     978                 :        410 :     JL_GC_POP();
     979                 :            : 
     980         [ -  + ]:        410 :     if (inst->getType() != rettype) {
     981                 :          0 :         std::string message;
     982                 :          0 :         raw_string_ostream stream(message);
     983                 :          0 :         stream << "llvmcall return type " << *inst->getType()
     984                 :          0 :                << " does not match declared return type" << *rettype;
     985                 :          0 :         emit_error(ctx, stream.str());
     986                 :          0 :         return jl_cgval_t();
     987                 :            :     }
     988                 :            : 
     989                 :        410 :     return mark_julia_type(ctx, inst, retboxed, rtt);
     990                 :            : }
     991                 :            : 
     992                 :            : // --- code generator for ccall itself ---
     993                 :            : 
     994                 :            : // Returns ctx.types().T_prjlvalue
     995                 :          1 : static Value *box_ccall_result(jl_codectx_t &ctx, Value *result, Value *runtime_dt, jl_value_t *rt)
     996                 :            : {
     997                 :            :     // XXX: need to handle parameterized zero-byte types (singleton)
     998                 :          1 :     const DataLayout &DL = ctx.builder.GetInsertBlock()->getModule()->getDataLayout();
     999                 :          1 :     unsigned nb = DL.getTypeStoreSize(result->getType());
    1000         [ -  + ]:          1 :     MDNode *tbaa = jl_is_mutable(rt) ? ctx.tbaa().tbaa_mutab : ctx.tbaa().tbaa_immut;
    1001                 :          1 :     Value *strct = emit_allocobj(ctx, nb, runtime_dt);
    1002                 :          1 :     init_bits_value(ctx, strct, result, tbaa);
    1003                 :          1 :     return strct;
    1004                 :            : }
    1005                 :            : 
    1006                 :     124487 : static jl_cgval_t mark_or_box_ccall_result(jl_codectx_t &ctx, Value *result, bool isboxed, jl_value_t *rt, jl_unionall_t *unionall, bool static_rt)
    1007                 :            : {
    1008         [ +  + ]:     124487 :     if (!static_rt) {
    1009   [ +  -  +  -  :          1 :         assert(!isboxed && jl_is_datatype(rt) && ctx.spvals_ptr && unionall);
             +  -  +  - ]
    1010                 :          1 :         Value *runtime_dt = runtime_apply_type_env(ctx, rt);
    1011                 :            :         // TODO: skip this check if rt is not a Tuple
    1012                 :          1 :         emit_concretecheck(ctx, runtime_dt, "ccall: return type must be a concrete DataType");
    1013                 :          1 :         Value *strct = box_ccall_result(ctx, result, runtime_dt, rt);
    1014                 :          1 :         return mark_julia_type(ctx, strct, true, rt); // TODO: jl_rewrap_unionall(rt, unionall)
    1015                 :            :     }
    1016                 :     124486 :     return mark_julia_type(ctx, result, isboxed, rt);
    1017                 :            : }
    1018                 :            : 
    1019                 :            : class function_sig_t {
    1020                 :            : public:
    1021                 :            :     std::vector<Type*> fargt; // vector of llvm output types (julia_struct_to_llvm) for arguments
    1022                 :            :     std::vector<Type*> fargt_sig; // vector of ABI coercion types for call signature
    1023                 :            :     std::vector<bool> fargt_isboxed; // vector of whether the llvm output type is a Julia-box for each argument
    1024                 :            :     std::vector<bool> byRefList; // vector of "byref" parameters
    1025                 :            :     AttributeList attributes; // vector of function call site attributes
    1026                 :            :     Type *lrt; // input parameter of the llvm return type (from julia_struct_to_llvm)
    1027                 :            :     bool retboxed; // input parameter indicating whether lrt is jl_value_t*
    1028                 :            :     Type *prt; // out parameter of the llvm return type for the function signature
    1029                 :            :     int sret; // out parameter for indicating whether return value has been moved to the first argument position
    1030                 :            :     std::string err_msg;
    1031                 :            :     CallingConv::ID cc; // calling convention ABI
    1032                 :            :     bool llvmcall;
    1033                 :            :     jl_svec_t *at; // svec of julia argument types
    1034                 :            :     jl_value_t *rt; // julia return type
    1035                 :            :     jl_unionall_t *unionall_env; // UnionAll environment for `at` and `rt`
    1036                 :            :     size_t nccallargs; // number of actual arguments
    1037                 :            :     size_t nreqargs; // number of required arguments in ccall function definition
    1038                 :            :     jl_codegen_params_t *ctx;
    1039                 :            : 
    1040                 :     162869 :     function_sig_t(const char *fname, Type *lrt, jl_value_t *rt, bool retboxed, jl_svec_t *at, jl_unionall_t *unionall_env, size_t nreqargs, CallingConv::ID cc, bool llvmcall, jl_codegen_params_t *ctx)
    1041                 :     162869 :       : lrt(lrt), retboxed(retboxed),
    1042                 :            :         prt(NULL), sret(0), cc(cc), llvmcall(llvmcall),
    1043                 :            :         at(at), rt(rt), unionall_env(unionall_env),
    1044                 :     162869 :         nccallargs(jl_svec_len(at)), nreqargs(nreqargs),
    1045                 :     162869 :         ctx(ctx)
    1046                 :            :     {
    1047                 :     162869 :         err_msg = generate_func_sig(fname);
    1048                 :     162869 :     }
    1049                 :            : 
    1050                 :      96486 :     FunctionType *functype(LLVMContext &ctxt) const {
    1051         [ -  + ]:      96486 :         assert(err_msg.empty());
    1052         [ +  + ]:      96486 :         if (nreqargs > 0)
    1053         [ -  + ]:       2366 :             return FunctionType::get(sret ? getVoidTy(ctxt) : prt, makeArrayRef(fargt_sig).slice(0, nreqargs), true);
    1054                 :            :         else
    1055         [ +  + ]:      94120 :             return FunctionType::get(sret ? getVoidTy(ctxt) : prt, fargt_sig, false);
    1056                 :            :     }
    1057                 :            : 
    1058                 :            :     jl_cgval_t emit_a_ccall(
    1059                 :            :             jl_codectx_t &ctx,
    1060                 :            :             const native_sym_arg_t &symarg,
    1061                 :            :             jl_cgval_t *argv,
    1062                 :            :             SmallVector<Value*, 16> &gc_uses,
    1063                 :            :             bool static_rt) const;
    1064                 :            : 
    1065                 :            : private:
    1066                 :     162869 : std::string generate_func_sig(const char *fname)
    1067                 :            : {
    1068   [ +  -  +  - ]:     162869 :     assert(rt && !jl_is_abstract_ref_type(rt));
    1069                 :            : 
    1070                 :     325738 :     std::vector<AttributeSet> paramattrs;
    1071                 :     162869 :     std::unique_ptr<AbiLayout> abi;
    1072         [ +  + ]:     162869 :     if (llvmcall)
    1073                 :          4 :         abi.reset(new ABI_LLVMLayout());
    1074                 :            :     else
    1075                 :     162865 :         abi.reset(new DefaultAbiState());
    1076                 :     162869 :     sret = 0;
    1077                 :     162869 :     LLVMContext &LLVMCtx = lrt->getContext();
    1078         [ +  + ]:     162869 :     if (type_is_ghost(lrt)) {
    1079                 :      38292 :         prt = lrt = getVoidTy(LLVMCtx);
    1080                 :      38292 :         abi->use_sret(jl_nothing_type, LLVMCtx);
    1081                 :            :     }
    1082                 :            :     else {
    1083   [ +  +  +  +  :     124577 :         if (retboxed || jl_is_cpointer_type(rt) || lrt->isPointerTy()) {
             -  +  +  + ]
    1084                 :     100293 :             prt = lrt; // passed as pointer
    1085                 :     100293 :             abi->use_sret(jl_voidpointer_type, LLVMCtx);
    1086                 :            :         }
    1087         [ +  + ]:      24284 :         else if (abi->use_sret((jl_datatype_t*)rt, LLVMCtx)) {
    1088                 :            : #if JL_LLVM_VERSION >= 140000
    1089                 :          4 :             AttrBuilder retattrs(LLVMCtx);
    1090                 :            : #else
    1091                 :            :             AttrBuilder retattrs;
    1092                 :            : #endif
    1093                 :            : #if !defined(_OS_WINDOWS_) // llvm used to use the old mingw ABI, skipping this marking works around that difference
    1094                 :          4 :             retattrs.addStructRetAttr(lrt);
    1095                 :            : #endif
    1096                 :          4 :             retattrs.addAttribute(Attribute::NoAlias);
    1097                 :          4 :             paramattrs.push_back(AttributeSet::get(LLVMCtx, retattrs));
    1098                 :          4 :             fargt_sig.push_back(PointerType::get(lrt, 0));
    1099                 :          4 :             sret = 1;
    1100                 :          4 :             prt = lrt;
    1101                 :            :         }
    1102                 :            :         else {
    1103                 :      24280 :             prt = abi->preferred_llvm_type((jl_datatype_t*)rt, true, LLVMCtx);
    1104         [ +  + ]:      24280 :             if (prt == NULL)
    1105                 :          4 :                 prt = lrt;
    1106                 :            :         }
    1107                 :            :     }
    1108                 :            : 
    1109         [ +  + ]:     424173 :     for (size_t i = 0; i < nccallargs; ++i) {
    1110                 :            : #if JL_LLVM_VERSION >= 140000
    1111                 :     261304 :         AttrBuilder ab(LLVMCtx);
    1112                 :            : #else
    1113                 :            :         AttrBuilder ab;
    1114                 :            : #endif
    1115                 :     261304 :         jl_value_t *tti = jl_svecref(at, i);
    1116                 :     261304 :         Type *t = NULL;
    1117                 :            :         bool isboxed;
    1118         [ +  + ]:     261304 :         if (jl_is_abstract_ref_type(tti)) {
    1119                 :        724 :             tti = (jl_value_t*)jl_voidpointer_type;
    1120                 :        724 :             t = getInt8PtrTy(LLVMCtx);
    1121                 :        724 :             isboxed = false;
    1122                 :            :         }
    1123   [ +  +  -  +  :     260580 :         else if (llvmcall && jl_is_llvmpointer_type(tti)) {
                   -  + ]
    1124                 :          0 :             t = bitstype_to_llvm(tti, LLVMCtx, true);
    1125                 :          0 :             tti = (jl_value_t*)jl_voidpointer_type;
    1126                 :          0 :             isboxed = false;
    1127                 :            :         }
    1128                 :            :         else {
    1129         [ +  + ]:     260580 :             if (jl_is_primitivetype(tti)) {
    1130                 :            :                 // see pull req #978. need to annotate signext/zeroext for
    1131                 :            :                 // small integer arguments.
    1132                 :     116734 :                 jl_datatype_t *bt = (jl_datatype_t*)tti;
    1133   [ +  +  +  - ]:     116734 :                 if (jl_datatype_size(bt) < 4 && bt != jl_float16_type) {
    1134   [ +  +  +  +  :        453 :                     if (jl_signed_type && jl_subtype(tti, (jl_value_t*)jl_signed_type))
                   +  + ]
    1135                 :         62 :                         ab.addAttribute(Attribute::SExt);
    1136                 :            :                     else
    1137                 :        391 :                         ab.addAttribute(Attribute::ZExt);
    1138                 :            :                 }
    1139                 :            :             }
    1140                 :            : 
    1141                 :     260580 :             t = _julia_struct_to_llvm(ctx, LLVMCtx, tti, &isboxed, llvmcall);
    1142         [ -  + ]:     260580 :             if (t == getVoidTy(LLVMCtx)) {
    1143                 :          0 :                 return make_errmsg(fname, i + 1, " type doesn't correspond to a C type");
    1144                 :            :             }
    1145                 :            :         }
    1146                 :            : 
    1147                 :            :         Type *pat;
    1148   [ +  -  +  +  :     261304 :         if (!jl_is_datatype(tti) || ((jl_datatype_t*)tti)->layout == NULL || jl_is_layout_opaque(((jl_datatype_t*)tti)->layout)) {
             -  +  +  + ]
    1149                 :     143778 :             tti = (jl_value_t*)jl_voidpointer_type; // passed as pointer
    1150                 :            :         }
    1151                 :            : 
    1152                 :            :         // Whether or not LLVM wants us to emit a pointer to the data
    1153         [ -  + ]:     261304 :         assert(t && "LLVM type should not be null");
    1154                 :     261304 :         bool byRef = abi->needPassByRef((jl_datatype_t*)tti, ab, LLVMCtx, t);
    1155                 :            : 
    1156         [ +  + ]:     261304 :         if (jl_is_cpointer_type(tti)) {
    1157                 :     172445 :             pat = t;
    1158                 :            :         }
    1159         [ -  + ]:      88859 :         else if (byRef) {
    1160                 :          0 :             pat = PointerType::get(t, AddressSpace::Derived);
    1161                 :            :         }
    1162                 :            :         else {
    1163                 :      88859 :             pat = abi->preferred_llvm_type((jl_datatype_t*)tti, false, LLVMCtx);
    1164         [ +  + ]:      88859 :             if (pat == NULL)
    1165                 :         12 :                 pat = t;
    1166                 :            :         }
    1167                 :            : 
    1168   [ +  -  +  +  :     261304 :         if (!byRef && nreqargs > 0 && i >= nreqargs) { // TODO: handle byRef case too?
                   +  + ]
    1169                 :            :             // The C vararg ABI says that small types must get widened,
    1170                 :            :             // but we don't really want to expect the user to know that,
    1171                 :            :             // so attempt to do that coercion here
    1172   [ +  -  +  - ]:         58 :             if (!llvmcall && cc == CallingConv::C) {
    1173   [ +  +  -  +  :         58 :                 if (pat->isIntegerTy() && pat->getPrimitiveSizeInBits() < sizeof(int) * 8)
                   -  + ]
    1174                 :          0 :                     pat = getInt32Ty(lrt->getContext());
    1175   [ -  +  -  -  :         58 :                 if (pat->isFloatingPointTy() && pat->getPrimitiveSizeInBits() < sizeof(double) * 8)
                   -  + ]
    1176                 :          0 :                     pat = getDoubleTy(lrt->getContext());
    1177                 :         58 :                 ab.removeAttribute(Attribute::SExt);
    1178                 :         58 :                 ab.removeAttribute(Attribute::ZExt);
    1179                 :            :             }
    1180                 :            :         }
    1181                 :            : 
    1182                 :     261304 :         byRefList.push_back(byRef);
    1183                 :     261304 :         fargt.push_back(t);
    1184                 :     261304 :         fargt_isboxed.push_back(isboxed);
    1185                 :     261304 :         fargt_sig.push_back(pat);
    1186                 :     261304 :         paramattrs.push_back(AttributeSet::get(LLVMCtx, ab));
    1187                 :            :     }
    1188                 :            : 
    1189                 :     162869 :     AttributeSet FnAttrs;
    1190                 :     162869 :     AttributeSet RetAttrs;
    1191                 :            :     // If return value is boxed it must be non-null.
    1192         [ +  + ]:     162869 :     if (retboxed)
    1193                 :      54145 :         RetAttrs = RetAttrs.addAttribute(LLVMCtx, Attribute::NonNull);
    1194         [ +  + ]:     162869 :     if (rt == jl_bottom_type)
    1195                 :         50 :         FnAttrs = FnAttrs.addAttribute(LLVMCtx, Attribute::NoReturn);
    1196         [ -  + ]:     162869 :     assert(attributes.isEmpty());
    1197                 :     162869 :     attributes = AttributeList::get(LLVMCtx, FnAttrs, RetAttrs, paramattrs);
    1198                 :     162869 :     return "";
    1199                 :            : }
    1200                 :            : };
    1201                 :            : 
    1202                 :     162663 : static std::pair<CallingConv::ID, bool> convert_cconv(jl_sym_t *lhd)
    1203                 :            : {
    1204                 :            :     // check for calling convention specifier
    1205         [ -  + ]:     162663 :     if (lhd == jl_symbol("stdcall")) {
    1206                 :          0 :         return std::make_pair(CallingConv::X86_StdCall, false);
    1207                 :            :     }
    1208   [ +  -  +  +  :     162663 :     else if (lhd == jl_symbol("cdecl") || lhd == jl_symbol("ccall")) {
                   +  + ]
    1209                 :            :         // `ccall` calling convention is a placeholder for when there isn't one provided
    1210                 :            :         // it is not by itself a valid calling convention name to be specified in the surface
    1211                 :            :         // syntax.
    1212                 :     162659 :         return std::make_pair(CallingConv::C, false);
    1213                 :            :     }
    1214         [ -  + ]:          4 :     else if (lhd == jl_symbol("fastcall")) {
    1215                 :          0 :         return std::make_pair(CallingConv::X86_FastCall, false);
    1216                 :            :     }
    1217         [ -  + ]:          4 :     else if (lhd == jl_symbol("thiscall")) {
    1218                 :          0 :         return std::make_pair(CallingConv::X86_ThisCall, false);
    1219                 :            :     }
    1220         [ +  - ]:          4 :     else if (lhd == jl_symbol("llvmcall")) {
    1221                 :          4 :         return std::make_pair(CallingConv::C, true);
    1222                 :            :     }
    1223                 :          0 :     jl_errorf("ccall: invalid calling convention %s", jl_symbol_name(lhd));
    1224                 :            : }
    1225                 :            : 
    1226                 :      16320 : static bool verify_ref_type(jl_codectx_t &ctx, jl_value_t* ref, jl_unionall_t *unionall_env, int n, const char *fname)
    1227                 :            : {
    1228                 :            :     // emit verification that the tparam for Ref isn't Any or a TypeVar
    1229                 :      16320 :     const char rt_err_msg_notany[] = " type Ref{Any} is invalid. Use Any or Ptr{Any} instead.";
    1230   [ -  +  -  - ]:      16320 :     if (ref == (jl_value_t*)jl_any_type && n == 0) {
    1231                 :          0 :         emit_error(ctx, make_errmsg(fname, n, rt_err_msg_notany));
    1232                 :          0 :         return false;
    1233                 :            :     }
    1234         [ +  + ]:      16320 :     else if (jl_is_typevar(ref)) {
    1235                 :         47 :         bool always_error = true;
    1236         [ +  - ]:         47 :         if (unionall_env) {
    1237                 :            :             int i;
    1238                 :         47 :             jl_unionall_t *ua = unionall_env;
    1239         [ +  - ]:         47 :             for (i = 0; jl_is_unionall(ua); i++) {
    1240         [ +  - ]:         47 :                 if (ua->var == (jl_tvar_t*)ref) {
    1241                 :         47 :                     jl_cgval_t runtime_sp = emit_sparam(ctx, i);
    1242         [ -  + ]:         47 :                     if (n > 0) {
    1243                 :          0 :                         always_error = false;
    1244                 :            :                     }
    1245         [ +  + ]:         47 :                     else if (runtime_sp.constant) {
    1246         [ +  - ]:         46 :                         if (runtime_sp.constant != (jl_value_t*)jl_any_type)
    1247                 :         46 :                             always_error = false;
    1248                 :            :                     }
    1249                 :            :                     else {
    1250                 :          1 :                         Value *notany = ctx.builder.CreateICmpNE(
    1251                 :            :                                 boxed(ctx, runtime_sp),
    1252                 :            :                                 track_pjlvalue(ctx, literal_pointer_val(ctx, (jl_value_t*)jl_any_type)));
    1253                 :          1 :                         error_unless(ctx, notany, make_errmsg(fname, n, rt_err_msg_notany));
    1254                 :          1 :                         always_error = false;
    1255                 :            :                     }
    1256                 :         47 :                     break;
    1257                 :            :                 }
    1258                 :          0 :                 ua = (jl_unionall_t*)ua->body;
    1259                 :            :             }
    1260                 :            :         }
    1261         [ -  + ]:         47 :         if (always_error) {
    1262                 :          0 :             emit_error(ctx, make_errmsg(fname, n, " type Ref should have an element type, not Ref{<:T}."));
    1263                 :          0 :             return false;
    1264                 :            :         }
    1265                 :            :     }
    1266                 :      16320 :     return true;
    1267                 :            : }
    1268                 :            : 
    1269                 :     162869 : static const std::string verify_ccall_sig(jl_value_t *&rt, jl_value_t *at,
    1270                 :            :                                           jl_unionall_t *unionall_env, jl_svec_t *sparam_vals,
    1271                 :            :                                           jl_codegen_params_t *ctx,
    1272                 :            :                                           Type *&lrt, LLVMContext &ctxt,
    1273                 :            :                                           bool &retboxed, bool &static_rt, bool llvmcall=false)
    1274                 :            : {
    1275         [ -  + ]:     162869 :     JL_TYPECHK(ccall, type, rt);
    1276         [ -  + ]:     162869 :     JL_TYPECHK(ccall, simplevector, at);
    1277                 :            : 
    1278   [ +  +  +  +  :     271654 :     if (rt == (jl_value_t*)jl_any_type || jl_is_array_type(rt) ||
                   +  + ]
    1279   [ +  +  +  -  :     217520 :             (jl_is_datatype(rt) && ((jl_datatype_t*)rt)->layout != NULL &&
                   +  + ]
    1280                 :     108735 :              jl_is_layout_opaque(((jl_datatype_t*)rt)->layout))) {
    1281                 :            :         // n.b. `Array` used as return type just returns a julia object reference
    1282                 :      54145 :         lrt = JuliaType::get_prjlvalue_ty(ctxt);
    1283                 :      54145 :         retboxed = true;
    1284                 :            :     }
    1285                 :            :     else {
    1286                 :            :         // jl_type_mappable_to_c should have already ensured that these are valid
    1287   [ +  +  +  +  :     108724 :         assert(jl_is_structtype(rt) || jl_is_primitivetype(rt) || rt == (jl_value_t*)jl_bottom_type);
                   -  + ]
    1288                 :     108724 :         lrt = _julia_struct_to_llvm(ctx, ctxt, rt, &retboxed, llvmcall);
    1289         [ -  + ]:     108724 :         assert(!retboxed);
    1290         [ -  + ]:     108724 :         if (CountTrackedPointers(lrt).count != 0)
    1291                 :          0 :             return "return type struct fields cannot contain a reference";
    1292                 :            :     }
    1293                 :            : 
    1294                 :            :     // is return type fully statically known?
    1295         [ +  + ]:     162869 :     if (unionall_env == NULL) {
    1296                 :     132395 :         static_rt = true;
    1297                 :            :     }
    1298                 :            :     else {
    1299   [ +  +  +  + ]:      30474 :         static_rt = retboxed || !jl_has_typevar_from_unionall(rt, unionall_env);
    1300   [ +  +  +  +  :      30474 :         if (!static_rt && sparam_vals != NULL && jl_svec_len(sparam_vals) > 0) {
                   +  - ]
    1301                 :         46 :             rt = jl_instantiate_type_in_env(rt, unionall_env, jl_svec_data(sparam_vals));
    1302                 :            :             // `rt` is gc-rooted by the caller
    1303                 :         46 :             static_rt = true;
    1304                 :            :         }
    1305                 :            :     }
    1306                 :            : 
    1307                 :     162869 :     return "";
    1308                 :            : }
    1309                 :            : 
    1310                 :            : const int fc_args_start = 6;
    1311                 :            : 
    1312                 :            : // Expr(:foreigncall, pointer, rettype, (argtypes...), nreq, [cconv | (cconv, effects)], args..., roots...)
    1313                 :     162663 : static jl_cgval_t emit_ccall(jl_codectx_t &ctx, jl_value_t **args, size_t nargs)
    1314                 :            : {
    1315         [ -  + ]:     162663 :     JL_NARGSV(ccall, 5);
    1316                 :     162663 :     args -= 1;
    1317                 :     162663 :     jl_value_t *rt = args[2];
    1318                 :     162663 :     jl_value_t *at = args[3];
    1319                 :     162663 :     size_t nccallargs = jl_svec_len(at);
    1320                 :     162663 :     size_t nreqargs = jl_unbox_long(args[4]); // if vararg
    1321         [ -  + ]:     162663 :     assert(jl_is_quotenode(args[5]));
    1322                 :     162663 :     jl_value_t *jlcc = jl_quotenode_value(args[5]);
    1323                 :     162663 :     jl_sym_t *cc_sym = NULL;
    1324         [ +  + ]:     162663 :     if (jl_is_symbol(jlcc)) {
    1325                 :     160367 :         cc_sym = (jl_sym_t*)jlcc;
    1326                 :            :     }
    1327         [ +  - ]:       2296 :     else if (jl_is_tuple(jlcc)) {
    1328                 :       2296 :         cc_sym = (jl_sym_t*)jl_get_nth_field_noalloc(jlcc, 0);
    1329                 :            :     }
    1330         [ -  + ]:     162663 :     assert(jl_is_symbol(cc_sym));
    1331                 :     162663 :     native_sym_arg_t symarg = {};
    1332                 :     162663 :     JL_GC_PUSH3(&rt, &at, &symarg.gcroot);
    1333                 :            : 
    1334                 :     162663 :     CallingConv::ID cc = CallingConv::C;
    1335                 :     162663 :     bool llvmcall = false;
    1336                 :     162663 :     std::tie(cc, llvmcall) = convert_cconv(cc_sym);
    1337                 :            : 
    1338                 :     162663 :     interpret_symbol_arg(ctx, symarg, args[1], "ccall", llvmcall);
    1339                 :     162663 :     Value *&jl_ptr = symarg.jl_ptr;
    1340                 :     162663 :     void (*&fptr)(void) = symarg.fptr;
    1341                 :     162663 :     const char *&f_name = symarg.f_name;
    1342                 :     162663 :     const char *&f_lib = symarg.f_lib;
    1343                 :            : 
    1344   [ -  +  -  -  :     162663 :     if (f_name == NULL && fptr == NULL && jl_ptr == NULL) {
                   -  - ]
    1345                 :          0 :         emit_error(ctx, "ccall: null function pointer");
    1346                 :          0 :         JL_GC_POP();
    1347                 :          0 :         return jl_cgval_t();
    1348                 :            :     }
    1349                 :            : 
    1350                 :     262106 :     auto ccallarg = [=] (size_t i) {
    1351   [ +  -  +  - ]:     262106 :         assert(i < nccallargs && i + fc_args_start <= nargs);
    1352                 :     262106 :         return args[fc_args_start + i];
    1353                 :     162663 :     };
    1354                 :            : 
    1355                 :    3093960 :     auto _is_libjulia_func = [&] (uintptr_t ptr, StringRef name) {
    1356         [ -  + ]:    3093960 :         if ((uintptr_t)fptr == ptr)
    1357                 :          0 :             return true;
    1358         [ +  + ]:    3093960 :         if (f_lib) {
    1359                 :            : #ifdef _OS_WINDOWS_
    1360                 :            :             if ((f_lib == JL_EXE_LIBNAME) || // preventing invalid pointer access
    1361                 :            :                 (f_lib == JL_LIBJULIA_INTERNAL_DL_LIBNAME) ||
    1362                 :            :                 (f_lib == JL_LIBJULIA_DL_LIBNAME) ||
    1363                 :            :                 (!strcmp(f_lib, jl_crtdll_basename))) {
    1364                 :            :                 // libjulia-like
    1365                 :            :             }
    1366                 :            :             else
    1367                 :            :                 return false;
    1368                 :            : #else
    1369                 :      54372 :             return false;
    1370                 :            : #endif
    1371                 :            :         }
    1372   [ +  -  +  + ]:    3039590 :         return f_name && f_name == name;
    1373                 :     162663 :     };
    1374                 :            : #define is_libjulia_func(name) _is_libjulia_func((uintptr_t)&(name), StringRef(XSTR(name)))
    1375                 :            : 
    1376                 :            :     // emit arguments
    1377                 :     162663 :     jl_cgval_t *argv = (jl_cgval_t*)alloca(sizeof(jl_cgval_t) * nccallargs);
    1378         [ +  + ]:     423305 :     for (size_t i = 0; i < nccallargs; i++) {
    1379                 :            :         // Julia (expression) value of current parameter
    1380                 :     260642 :         jl_value_t *argi = ccallarg(i);
    1381                 :     260642 :         argv[i] = emit_expr(ctx, argi);
    1382                 :            :     }
    1383                 :            : 
    1384                 :            :     // emit roots
    1385                 :     325326 :     SmallVector<Value*, 16> gc_uses;
    1386         [ +  + ]:     277297 :     for (size_t i = nccallargs + fc_args_start; i <= nargs; i++) {
    1387                 :            :         // Julia (expression) value of current parameter gcroot
    1388                 :     114634 :         jl_value_t *argi_root = args[i];
    1389         [ +  + ]:     114634 :         if (jl_is_long(argi_root))
    1390                 :      16218 :             continue;
    1391                 :      98416 :         jl_cgval_t arg_root = emit_expr(ctx, argi_root);
    1392                 :      98416 :         Value *gc_root = get_gc_root_for(arg_root);
    1393         [ +  + ]:      98416 :         if (gc_root)
    1394                 :      12764 :             gc_uses.push_back(gc_root);
    1395                 :            :     }
    1396                 :            : 
    1397         [ +  + ]:     162477 :     jl_unionall_t *unionall = (jl_is_method(ctx.linfo->def.method) && jl_is_unionall(ctx.linfo->def.method->sig))
    1398         [ +  + ]:     325140 :         ? (jl_unionall_t*)ctx.linfo->def.method->sig
    1399                 :            :         : NULL;
    1400                 :            : 
    1401         [ +  + ]:     162663 :     if (jl_is_abstract_ref_type(rt)) {
    1402         [ -  + ]:      15596 :         if (!verify_ref_type(ctx, jl_tparam0(rt), unionall, 0, "ccall")) {
    1403                 :          0 :             JL_GC_POP();
    1404                 :          0 :             return jl_cgval_t();
    1405                 :            :         }
    1406                 :      15596 :         rt = (jl_value_t*)jl_any_type; // convert return type to jl_value_t*
    1407                 :            :     }
    1408                 :            : 
    1409                 :            :     // some sanity checking and check whether there's a vararg
    1410                 :            :     Type *lrt;
    1411                 :            :     bool retboxed;
    1412                 :            :     bool static_rt;
    1413                 :            :     std::string err = verify_ccall_sig(
    1414                 :            :       /* inputs:  */
    1415                 :            :       rt, at, unionall,
    1416                 :     325311 :       ctx.spvals_ptr == NULL ? ctx.linfo->sparam_vals : NULL,
    1417                 :     162663 :       &ctx.emission_context,
    1418                 :            :       /* outputs: */
    1419                 :            :       lrt, ctx.builder.getContext(),
    1420                 :            :       retboxed, static_rt,
    1421                 :            :       /* optional arguments */
    1422         [ +  + ]:     325326 :       llvmcall);
    1423         [ +  - ]:     162663 :     if (err.empty()) {
    1424                 :            :         // some extra checks for ccall
    1425   [ +  +  +  + ]:     162663 :         if (!retboxed && static_rt) {
    1426         [ +  + ]:     108517 :             if (!jl_is_concrete_type(rt)) {
    1427         [ -  + ]:         50 :                 if (jl_is_cpointer_type(rt))
    1428                 :          0 :                     err = "return type Ptr should have an element type (not Ptr{<:T})";
    1429         [ -  + ]:         50 :                 else if (rt != jl_bottom_type)
    1430                 :          0 :                     err = "return type must be a concrete DataType";
    1431                 :            :             }
    1432                 :            :         }
    1433         [ -  + ]:     162663 :         assert(jl_svec_len(at) >= nreqargs);
    1434                 :            :     }
    1435         [ -  + ]:     162663 :     if (!err.empty()) {
    1436                 :          0 :         emit_error(ctx, "ccall " + err);
    1437                 :          0 :         JL_GC_POP();
    1438                 :          0 :         return jl_cgval_t();
    1439                 :            :     }
    1440   [ +  +  +  + ]:     162663 :     if (rt != args[2] && rt != (jl_value_t*)jl_any_type)
    1441                 :         46 :         jl_add_method_root(ctx, rt);
    1442                 :            :     function_sig_t sig("ccall", lrt, rt, retboxed,
    1443                 :            :                        (jl_svec_t*)at, unionall, nreqargs,
    1444                 :     325326 :                        cc, llvmcall, &ctx.emission_context);
    1445         [ +  + ]:     423305 :     for (size_t i = 0; i < nccallargs; i++) {
    1446                 :     260642 :         jl_value_t *tti = jl_svecref(at, i);
    1447         [ +  + ]:     260642 :         if (jl_is_abstract_ref_type(tti)) {
    1448         [ -  + ]:        704 :             if (!verify_ref_type(ctx, jl_tparam0(tti), unionall, i + 1, "ccall")) {
    1449                 :          0 :                 JL_GC_POP();
    1450                 :          0 :                 return jl_cgval_t();
    1451                 :            :             }
    1452                 :            :         }
    1453                 :            :     }
    1454                 :            : 
    1455                 :            :     // some special functions
    1456                 :     162663 :     bool isVa = nreqargs > 0;
    1457                 :            :     (void)isVa; // prevent compiler warning
    1458         [ +  + ]:     162663 :     if (is_libjulia_func(jl_array_ptr)) {
    1459                 :      11748 :         ++CCALL_STAT(jl_array_ptr);
    1460         [ -  + ]:      11748 :         assert(lrt == getSizeTy(ctx.builder.getContext()));
    1461   [ +  -  +  -  :      11748 :         assert(!isVa && !llvmcall && nccallargs == 1);
                   +  - ]
    1462                 :      11748 :         const jl_cgval_t &ary = argv[0];
    1463                 :      11748 :         JL_GC_POP();
    1464                 :            :         return mark_or_box_ccall_result(ctx, ctx.builder.CreatePtrToInt(emit_unsafe_arrayptr(ctx, ary), lrt),
    1465                 :      11748 :                                         retboxed, rt, unionall, static_rt);
    1466                 :            :     }
    1467         [ +  + ]:     150915 :     else if (is_libjulia_func(jl_value_ptr)) {
    1468                 :       2934 :         ++CCALL_STAT(jl_value_ptr);
    1469   [ +  +  -  + ]:       2934 :         assert(retboxed ? lrt == ctx.types().T_prjlvalue : lrt == getSizeTy(ctx.builder.getContext()));
    1470   [ +  -  +  -  :       2934 :         assert(!isVa && !llvmcall && nccallargs == 1);
                   +  - ]
    1471                 :       2934 :         jl_value_t *tti = jl_svecref(at, 0);
    1472                 :            :         Type *largty;
    1473                 :            :         bool isboxed;
    1474         [ -  + ]:       2934 :         if (jl_is_abstract_ref_type(tti)) {
    1475                 :          0 :             tti = (jl_value_t*)jl_voidpointer_type;
    1476                 :          0 :             largty = getSizeTy(ctx.builder.getContext());
    1477                 :          0 :             isboxed = false;
    1478                 :            :         }
    1479                 :            :         else {
    1480                 :       2934 :             largty = _julia_struct_to_llvm(&ctx.emission_context, ctx.builder.getContext(), tti, &isboxed, llvmcall);
    1481                 :            :         }
    1482                 :            :         Value *retval;
    1483         [ +  + ]:       2934 :         if (isboxed) {
    1484                 :       2780 :             retval = boxed(ctx, argv[0]);
    1485                 :       2780 :             retval = emit_pointer_from_objref(ctx, emit_bitcast(ctx, retval, ctx.types().T_prjlvalue));
    1486                 :            :         }
    1487                 :            :         else {
    1488                 :        154 :             retval = emit_unbox(ctx, largty, argv[0], tti);
    1489                 :        154 :             retval = emit_inttoptr(ctx, retval, ctx.types().T_pjlvalue);
    1490                 :            :         }
    1491                 :            :         // retval is now an untracked jl_value_t*
    1492         [ +  + ]:       2934 :         if (retboxed)
    1493                 :            :             // WARNING: this addrspace cast necessarily implies that the value is rooted elsewhere!
    1494                 :        154 :             retval = ctx.builder.CreateAddrSpaceCast(retval, ctx.types().T_prjlvalue);
    1495                 :       2934 :         JL_GC_POP();
    1496                 :       2934 :         return mark_or_box_ccall_result(ctx, retval, retboxed, rt, unionall, static_rt);
    1497                 :            :     }
    1498         [ +  + ]:     147981 :     else if (is_libjulia_func(jl_cpu_pause)) {
    1499                 :         16 :         ++CCALL_STAT(jl_cpu_pause);
    1500                 :            :         // Keep in sync with the julia_threads.h version
    1501         [ -  + ]:         16 :         assert(lrt == getVoidTy(ctx.builder.getContext()));
    1502   [ +  -  +  -  :         16 :         assert(!isVa && !llvmcall && nccallargs == 0);
                   +  - ]
    1503                 :            : #ifdef __MIC__
    1504                 :            :         // TODO
    1505                 :            : #elif defined(_CPU_X86_64_) || defined(_CPU_X86_)  /* !__MIC__ */
    1506                 :         16 :         auto pauseinst = InlineAsm::get(FunctionType::get(getVoidTy(ctx.builder.getContext()), false), "pause",
    1507                 :            :                                                "~{memory}", true);
    1508                 :         16 :         ctx.builder.CreateCall(pauseinst);
    1509                 :         16 :         JL_GC_POP();
    1510                 :         16 :         return ghostValue(ctx, jl_nothing_type);
    1511                 :            : #elif defined(_CPU_AARCH64_) || (defined(_CPU_ARM_) && __ARM_ARCH >= 7)
    1512                 :            :         auto wfeinst = InlineAsm::get(FunctionType::get(getVoidTy(ctx.builder.getContext()), false), "wfe",
    1513                 :            :                                              "~{memory}", true);
    1514                 :            :         ctx.builder.CreateCall(wfeinst);
    1515                 :            :         JL_GC_POP();
    1516                 :            :         return ghostValue(ctx, jl_nothing_type);
    1517                 :            : #else
    1518                 :            :         JL_GC_POP();
    1519                 :            :         return ghostValue(ctx, jl_nothing_type);
    1520                 :            : #endif
    1521                 :            :     }
    1522         [ +  + ]:     147965 :     else if (is_libjulia_func(jl_cpu_wake)) {
    1523                 :        700 :         ++CCALL_STAT(jl_cpu_wake);
    1524                 :            :         // Keep in sync with the julia_threads.h version
    1525         [ -  + ]:        700 :         assert(lrt == getVoidTy(ctx.builder.getContext()));
    1526   [ +  -  +  -  :        700 :         assert(!isVa && !llvmcall && nccallargs == 0);
                   +  - ]
    1527                 :            : #if JL_CPU_WAKE_NOOP == 1
    1528                 :        700 :         JL_GC_POP();
    1529                 :        700 :         return ghostValue(ctx, jl_nothing_type);
    1530                 :            : #elif defined(_CPU_AARCH64_) || (defined(_CPU_ARM_) && __ARM_ARCH >= 7)
    1531                 :            :         auto sevinst = InlineAsm::get(FunctionType::get(getVoidTy(ctx.builder.getContext()), false), "sev",
    1532                 :            :                                              "~{memory}", true);
    1533                 :            :         ctx.builder.CreateCall(sevinst);
    1534                 :            :         JL_GC_POP();
    1535                 :            :         return ghostValue(ctx, jl_nothing_type);
    1536                 :            : #endif
    1537                 :            :     }
    1538         [ +  + ]:     147265 :     else if (is_libjulia_func(jl_gc_safepoint)) {
    1539                 :         48 :         ++CCALL_STAT(jl_gc_safepoint);
    1540         [ -  + ]:         48 :         assert(lrt == getVoidTy(ctx.builder.getContext()));
    1541   [ +  -  +  -  :         48 :         assert(!isVa && !llvmcall && nccallargs == 0);
                   +  - ]
    1542                 :         48 :         JL_GC_POP();
    1543                 :         48 :         emit_gc_safepoint(ctx);
    1544                 :         48 :         return ghostValue(ctx, jl_nothing_type);
    1545                 :            :     }
    1546         [ -  + ]:     147217 :     else if (is_libjulia_func("jl_get_ptls_states")) {
    1547                 :          0 :         ++CCALL_STAT(jl_get_ptls_states);
    1548         [ #  # ]:          0 :         assert(lrt == getSizeTy(ctx.builder.getContext()));
    1549   [ #  #  #  #  :          0 :         assert(!isVa && !llvmcall && nccallargs == 0);
                   #  # ]
    1550                 :          0 :         JL_GC_POP();
    1551                 :            :         return mark_or_box_ccall_result(ctx,
    1552                 :            :             ctx.builder.CreatePtrToInt(get_current_ptls(ctx), lrt),
    1553                 :          0 :             retboxed, rt, unionall, static_rt);
    1554                 :            :     }
    1555         [ +  + ]:     147217 :     else if (is_libjulia_func(jl_threadid)) {
    1556                 :        152 :         ++CCALL_STAT(jl_threadid);
    1557         [ -  + ]:        152 :         assert(lrt == getInt16Ty(ctx.builder.getContext()));
    1558   [ +  -  +  -  :        152 :         assert(!isVa && !llvmcall && nccallargs == 0);
                   +  - ]
    1559                 :        152 :         JL_GC_POP();
    1560                 :        152 :         Value *ptask_i16 = emit_bitcast(ctx, get_current_task(ctx), getInt16PtrTy(ctx.builder.getContext()));
    1561                 :        152 :         const int tid_offset = offsetof(jl_task_t, tid);
    1562                 :        152 :         Value *ptid = ctx.builder.CreateInBoundsGEP(getInt16Ty(ctx.builder.getContext()), ptask_i16, ConstantInt::get(getSizeTy(ctx.builder.getContext()), tid_offset / sizeof(int16_t)));
    1563                 :        152 :         LoadInst *tid = ctx.builder.CreateAlignedLoad(getInt16Ty(ctx.builder.getContext()), ptid, Align(sizeof(int16_t)));
    1564                 :        152 :         tbaa_decorate(ctx.tbaa().tbaa_gcframe, tid);
    1565                 :        152 :         return mark_or_box_ccall_result(ctx, tid, retboxed, rt, unionall, static_rt);
    1566                 :            :     }
    1567                 :     147065 :     else if (is_libjulia_func(jl_gc_disable_finalizers_internal)
    1568                 :            : #ifdef NDEBUG
    1569   [ +  +  +  +  :     147065 :              || is_libjulia_func(jl_gc_enable_finalizers_internal)
                   +  + ]
    1570                 :            : #endif
    1571                 :            :              ) {
    1572                 :       1950 :         JL_GC_POP();
    1573                 :       1950 :         Value *ptls_i32 = emit_bitcast(ctx, get_current_ptls(ctx), getInt32PtrTy(ctx.builder.getContext()));
    1574                 :       1950 :         const int finh_offset = offsetof(jl_tls_states_t, finalizers_inhibited);
    1575                 :       1950 :         Value *pfinh = ctx.builder.CreateInBoundsGEP(getInt32Ty(ctx.builder.getContext()), ptls_i32, ConstantInt::get(getSizeTy(ctx.builder.getContext()), finh_offset / 4));
    1576                 :       1950 :         LoadInst *finh = ctx.builder.CreateAlignedLoad(getInt32Ty(ctx.builder.getContext()), pfinh, Align(sizeof(int32_t)));
    1577                 :            :         Value *newval;
    1578         [ +  + ]:       1950 :         if (is_libjulia_func(jl_gc_disable_finalizers_internal)) {
    1579                 :         72 :             newval = ctx.builder.CreateAdd(finh, ConstantInt::get(getInt32Ty(ctx.builder.getContext()), 1));
    1580                 :            :         }
    1581                 :            :         else {
    1582                 :       5634 :             newval = ctx.builder.CreateSelect(ctx.builder.CreateICmpEQ(finh, ConstantInt::get(getInt32Ty(ctx.builder.getContext()), 0)),
    1583                 :       1878 :                                               ConstantInt::get(getInt32Ty(ctx.builder.getContext()), 0),
    1584                 :       1878 :                                               ctx.builder.CreateSub(finh, ConstantInt::get(getInt32Ty(ctx.builder.getContext()), 1)));
    1585                 :            :         }
    1586                 :       1950 :         ctx.builder.CreateStore(newval, pfinh);
    1587                 :       1950 :         return ghostValue(ctx, jl_nothing_type);
    1588                 :            :     }
    1589         [ +  + ]:     145115 :     else if (is_libjulia_func(jl_get_current_task)) {
    1590                 :       2866 :         ++CCALL_STAT(jl_get_current_task);
    1591         [ -  + ]:       2866 :         assert(lrt == ctx.types().T_prjlvalue);
    1592   [ +  -  +  -  :       2866 :         assert(!isVa && !llvmcall && nccallargs == 0);
                   +  - ]
    1593                 :       2866 :         JL_GC_POP();
    1594                 :       2866 :         auto ct = track_pjlvalue(ctx, emit_bitcast(ctx, get_current_task(ctx), ctx.types().T_pjlvalue));
    1595                 :       2866 :         return mark_or_box_ccall_result(ctx, ct, retboxed, rt, unionall, static_rt);
    1596                 :            :     }
    1597         [ +  + ]:     142249 :     else if (is_libjulia_func(jl_set_next_task)) {
    1598                 :         44 :         ++CCALL_STAT(jl_set_next_task);
    1599         [ -  + ]:         44 :         assert(lrt == getVoidTy(ctx.builder.getContext()));
    1600   [ +  -  +  -  :         44 :         assert(!isVa && !llvmcall && nccallargs == 1);
                   +  - ]
    1601                 :         44 :         JL_GC_POP();
    1602                 :         44 :         Value *ptls_pv = emit_bitcast(ctx, get_current_ptls(ctx), ctx.types().T_ppjlvalue);
    1603                 :         44 :         const int nt_offset = offsetof(jl_tls_states_t, next_task);
    1604                 :         44 :         Value *pnt = ctx.builder.CreateInBoundsGEP(ctx.types().T_pjlvalue, ptls_pv, ConstantInt::get(getSizeTy(ctx.builder.getContext()), nt_offset / sizeof(void*)));
    1605                 :         44 :         ctx.builder.CreateStore(emit_pointer_from_objref(ctx, boxed(ctx, argv[0])), pnt);
    1606                 :         44 :         return ghostValue(ctx, jl_nothing_type);
    1607                 :            :     }
    1608         [ +  + ]:     142205 :     else if (is_libjulia_func(jl_sigatomic_begin)) {
    1609                 :         24 :         ++CCALL_STAT(jl_sigatomic_begin);
    1610         [ -  + ]:         24 :         assert(lrt == getVoidTy(ctx.builder.getContext()));
    1611   [ +  -  +  -  :         24 :         assert(!isVa && !llvmcall && nccallargs == 0);
                   +  - ]
    1612                 :         24 :         JL_GC_POP();
    1613                 :         24 :         ctx.builder.CreateCall(prepare_call(gcroot_flush_func));
    1614                 :         24 :         Value *pdefer_sig = emit_defer_signal(ctx);
    1615                 :         24 :         Value *defer_sig = ctx.builder.CreateLoad(ctx.types().T_sigatomic, pdefer_sig);
    1616                 :         24 :         defer_sig = ctx.builder.CreateAdd(defer_sig, ConstantInt::get(ctx.types().T_sigatomic, 1));
    1617                 :         24 :         ctx.builder.CreateStore(defer_sig, pdefer_sig);
    1618                 :         24 :         emit_signal_fence(ctx);
    1619                 :         24 :         return ghostValue(ctx, jl_nothing_type);
    1620                 :            :     }
    1621         [ +  + ]:     142181 :     else if (is_libjulia_func(jl_sigatomic_end)) {
    1622                 :         50 :         ++CCALL_STAT(jl_sigatomic_end);
    1623         [ -  + ]:         50 :         assert(lrt == getVoidTy(ctx.builder.getContext()));
    1624   [ +  -  +  -  :         50 :         assert(!isVa && !llvmcall && nccallargs == 0);
                   +  - ]
    1625                 :         50 :         JL_GC_POP();
    1626                 :         50 :         ctx.builder.CreateCall(prepare_call(gcroot_flush_func));
    1627                 :         50 :         Value *pdefer_sig = emit_defer_signal(ctx);
    1628                 :         50 :         Value *defer_sig = ctx.builder.CreateLoad(ctx.types().T_sigatomic, pdefer_sig);
    1629                 :         50 :         emit_signal_fence(ctx);
    1630                 :        100 :         error_unless(ctx,
    1631                 :         50 :                 ctx.builder.CreateICmpNE(defer_sig, ConstantInt::get(ctx.types().T_sigatomic, 0)),
    1632                 :            :                 "sigatomic_end called in non-sigatomic region");
    1633                 :        100 :         defer_sig = ctx.builder.CreateSub(
    1634                 :            :                 defer_sig,
    1635                 :         50 :                 ConstantInt::get(ctx.types().T_sigatomic, 1));
    1636                 :         50 :         ctx.builder.CreateStore(defer_sig, pdefer_sig);
    1637                 :         50 :         BasicBlock *checkBB = BasicBlock::Create(ctx.builder.getContext(), "check",
    1638                 :            :                                                  ctx.f);
    1639                 :         50 :         BasicBlock *contBB = BasicBlock::Create(ctx.builder.getContext(), "cont");
    1640                 :        100 :         ctx.builder.CreateCondBr(
    1641                 :         50 :                 ctx.builder.CreateICmpEQ(defer_sig, ConstantInt::get(ctx.types().T_sigatomic, 0)),
    1642                 :            :                 checkBB, contBB);
    1643                 :         50 :         ctx.builder.SetInsertPoint(checkBB);
    1644                 :        150 :         ctx.builder.CreateLoad(
    1645                 :         50 :                 getSizeTy(ctx.builder.getContext()),
    1646                 :         50 :                 ctx.builder.CreateConstInBoundsGEP1_32(getSizeTy(ctx.builder.getContext()), get_current_signal_page(ctx), -1),
    1647                 :            :                 true);
    1648                 :         50 :         ctx.builder.CreateBr(contBB);
    1649                 :         50 :         ctx.f->getBasicBlockList().push_back(contBB);
    1650                 :         50 :         ctx.builder.SetInsertPoint(contBB);
    1651                 :         50 :         return ghostValue(ctx, jl_nothing_type);
    1652                 :            :     }
    1653         [ +  + ]:     142131 :     else if (is_libjulia_func(jl_svec_len)) {
    1654                 :       8481 :         ++CCALL_STAT(jl_svec_len);
    1655   [ +  -  +  -  :       8481 :         assert(!isVa && !llvmcall && nccallargs == 1);
                   +  - ]
    1656                 :       8481 :         const jl_cgval_t &svecv = argv[0];
    1657                 :            :         Value *len;
    1658   [ -  +  -  - ]:       8481 :         if (svecv.constant && svecv.typ == (jl_value_t*)jl_simplevector_type) {
    1659                 :            :             // Check the type as well before we call
    1660                 :          0 :             len = ConstantInt::get(getSizeTy(ctx.builder.getContext()), jl_svec_len(svecv.constant));
    1661                 :            :         }
    1662                 :            :         else {
    1663                 :       8481 :             auto ptr = emit_bitcast(ctx, boxed(ctx, svecv), getSizePtrTy(ctx.builder.getContext()));
    1664                 :       8481 :             len = ctx.builder.CreateAlignedLoad(getSizeTy(ctx.builder.getContext()), ptr, Align(sizeof(size_t)));
    1665                 :            :             // Only mark with TBAA if we are sure about the type.
    1666                 :            :             // This could otherwise be in a dead branch
    1667         [ +  - ]:       8481 :             if (svecv.typ == (jl_value_t*)jl_simplevector_type)
    1668                 :       8481 :                 tbaa_decorate(ctx.tbaa().tbaa_const, cast<Instruction>(len));
    1669                 :       8481 :             MDBuilder MDB(ctx.builder.getContext());
    1670                 :       8481 :             auto rng = MDB.createRange(
    1671                 :       8481 :                 Constant::getNullValue(getSizeTy(ctx.builder.getContext())), ConstantInt::get(getSizeTy(ctx.builder.getContext()), INTPTR_MAX / sizeof(void*) - 1));
    1672                 :       8481 :             cast<LoadInst>(len)->setMetadata(LLVMContext::MD_range, rng);
    1673                 :            :         }
    1674                 :       8481 :         JL_GC_POP();
    1675                 :       8481 :         return mark_or_box_ccall_result(ctx, len, retboxed, rt, unionall, static_rt);
    1676                 :            :     }
    1677   [ +  +  +  + ]:     133670 :     else if (is_libjulia_func(jl_svec_isassigned) &&
    1678         [ +  - ]:         20 :              argv[1].typ == (jl_value_t*)jl_long_type) {
    1679                 :         20 :         ++CCALL_STAT(jl_svec_isassigned);
    1680   [ +  -  +  -  :         20 :         assert(!isVa && !llvmcall && nccallargs == 2);
                   +  - ]
    1681                 :         20 :         const jl_cgval_t &svecv = argv[0];
    1682                 :         20 :         const jl_cgval_t &idxv = argv[1];
    1683                 :         20 :         Value *idx = emit_unbox(ctx, getSizeTy(ctx.builder.getContext()), idxv, (jl_value_t*)jl_long_type);
    1684                 :         20 :         idx = ctx.builder.CreateAdd(idx, ConstantInt::get(getSizeTy(ctx.builder.getContext()), 1));
    1685                 :         20 :         auto ptr = emit_bitcast(ctx, boxed(ctx, svecv), ctx.types().T_pprjlvalue);
    1686                 :         20 :         Value *slot_addr = ctx.builder.CreateInBoundsGEP(ctx.types().T_prjlvalue,
    1687                 :            :                                                          decay_derived(ctx, ptr), idx);
    1688                 :         40 :         LoadInst *load = ctx.builder.CreateAlignedLoad(ctx.types().T_prjlvalue, slot_addr,
    1689                 :         20 :                                                        Align(sizeof(void*)));
    1690                 :         20 :         load->setAtomic(AtomicOrdering::Unordered);
    1691                 :            :         // Only mark with TBAA if we are sure about the type.
    1692                 :            :         // This could otherwise be in a dead branch
    1693         [ +  - ]:         20 :         if (svecv.typ == (jl_value_t*)jl_simplevector_type)
    1694                 :         20 :             tbaa_decorate(ctx.tbaa().tbaa_const, load);
    1695                 :         20 :         Value *res = ctx.builder.CreateZExt(ctx.builder.CreateICmpNE(load, Constant::getNullValue(ctx.types().T_prjlvalue)), getInt8Ty(ctx.builder.getContext()));
    1696                 :         20 :         JL_GC_POP();
    1697                 :         20 :         return mark_or_box_ccall_result(ctx, res, retboxed, rt, unionall, static_rt);
    1698                 :            :     }
    1699   [ +  +  +  +  :     133630 :     else if (is_libjulia_func(jl_svec_ref) && argv[1].typ == (jl_value_t*)jl_long_type) {
                   +  + ]
    1700                 :       4902 :         ++CCALL_STAT(jl_svec_ref);
    1701         [ -  + ]:       4902 :         assert(lrt == ctx.types().T_prjlvalue);
    1702   [ +  -  +  -  :       4902 :         assert(!isVa && !llvmcall && nccallargs == 2);
                   +  - ]
    1703                 :       4902 :         const jl_cgval_t &svecv = argv[0];
    1704                 :       4902 :         const jl_cgval_t &idxv = argv[1];
    1705                 :       4902 :         Value *idx = emit_unbox(ctx, getSizeTy(ctx.builder.getContext()), idxv, (jl_value_t*)jl_long_type);
    1706                 :       4902 :         idx = ctx.builder.CreateAdd(idx, ConstantInt::get(getSizeTy(ctx.builder.getContext()), 1));
    1707                 :       4902 :         auto ptr = emit_bitcast(ctx, boxed(ctx, svecv), ctx.types().T_pprjlvalue);
    1708                 :       4902 :         Value *slot_addr = ctx.builder.CreateInBoundsGEP(ctx.types().T_prjlvalue,
    1709                 :            :                                                          decay_derived(ctx, ptr), idx);
    1710                 :       9804 :         LoadInst *load = ctx.builder.CreateAlignedLoad(ctx.types().T_prjlvalue, slot_addr,
    1711                 :       4902 :                                                        Align(sizeof(void*)));
    1712                 :       4902 :         load->setAtomic(AtomicOrdering::Unordered);
    1713                 :            :         // Only mark with TBAA if we are sure about the type.
    1714                 :            :         // This could otherwise be in a dead branch
    1715         [ +  - ]:       4902 :         if (svecv.typ == (jl_value_t*)jl_simplevector_type)
    1716                 :       4902 :             tbaa_decorate(ctx.tbaa().tbaa_const, load);
    1717                 :       4902 :         null_pointer_check(ctx, load);
    1718                 :       4902 :         JL_GC_POP();
    1719                 :       4902 :         return mark_or_box_ccall_result(ctx, load, retboxed, rt, unionall, static_rt);
    1720                 :            :     }
    1721   [ +  +  +  + ]:     130193 :     else if (is_libjulia_func(jl_array_isassigned) &&
    1722         [ +  + ]:       1465 :              argv[1].typ == (jl_value_t*)jl_ulong_type) {
    1723                 :       1464 :         ++CCALL_STAT(jl_array_isassigned);
    1724   [ +  -  +  -  :       1464 :         assert(!isVa && !llvmcall && nccallargs == 2);
                   +  - ]
    1725                 :       1464 :         jl_value_t *aryex = ccallarg(0);
    1726                 :       1464 :         const jl_cgval_t &aryv = argv[0];
    1727                 :       1464 :         const jl_cgval_t &idxv = argv[1];
    1728                 :       1464 :         jl_datatype_t *arydt = (jl_datatype_t*)jl_unwrap_unionall(aryv.typ);
    1729         [ +  - ]:       1464 :         if (jl_is_array_type(arydt)) {
    1730                 :       1464 :             jl_value_t *ety = jl_tparam0(arydt);
    1731                 :       1464 :             bool ptrarray = !jl_stored_inline(ety);
    1732   [ +  +  +  +  :       1464 :             if (!ptrarray && !jl_type_hasptr(ety)) {
                   +  + ]
    1733                 :        310 :                 JL_GC_POP();
    1734                 :        310 :                 return mark_or_box_ccall_result(ctx, ConstantInt::get(getInt32Ty(ctx.builder.getContext()), 1),
    1735                 :        620 :                                                 false, rt, unionall, static_rt);
    1736                 :            :             }
    1737         [ +  + ]:       1154 :             else if (!jl_has_free_typevars(ety)) {
    1738                 :       1150 :                 Value *idx = emit_unbox(ctx, getSizeTy(ctx.builder.getContext()), idxv, (jl_value_t*)jl_ulong_type);
    1739                 :       1150 :                 Value *arrayptr = emit_bitcast(ctx, emit_arrayptr(ctx, aryv, aryex), ctx.types().T_pprjlvalue);
    1740         [ +  + ]:       1150 :                 if (!ptrarray) {
    1741                 :        244 :                     size_t elsz = jl_datatype_size(ety);
    1742                 :        244 :                     unsigned align = jl_datatype_align(ety);
    1743                 :        244 :                     size_t stride = LLT_ALIGN(elsz, align) / sizeof(jl_value_t*);
    1744         [ +  + ]:        244 :                     if (stride != 1)
    1745                 :        220 :                         idx = ctx.builder.CreateMul(idx, ConstantInt::get(getSizeTy(ctx.builder.getContext()), stride));
    1746                 :        244 :                     idx = ctx.builder.CreateAdd(idx, ConstantInt::get(getSizeTy(ctx.builder.getContext()), ((jl_datatype_t*)ety)->layout->first_ptr));
    1747                 :            :                 }
    1748                 :       1150 :                 Value *slot_addr = ctx.builder.CreateInBoundsGEP(ctx.types().T_prjlvalue, arrayptr, idx);
    1749                 :       1150 :                 LoadInst *load = ctx.builder.CreateAlignedLoad(ctx.types().T_prjlvalue, slot_addr, Align(sizeof(void*)));
    1750                 :       1150 :                 load->setAtomic(AtomicOrdering::Unordered);
    1751                 :       1150 :                 tbaa_decorate(ctx.tbaa().tbaa_ptrarraybuf, load);
    1752                 :       1150 :                 Value *res = ctx.builder.CreateZExt(ctx.builder.CreateICmpNE(load, Constant::getNullValue(ctx.types().T_prjlvalue)), getInt32Ty(ctx.builder.getContext()));
    1753                 :       1150 :                 JL_GC_POP();
    1754                 :       1150 :                 return mark_or_box_ccall_result(ctx, res, retboxed, rt, unionall, static_rt);
    1755                 :            :             }
    1756                 :            :         }
    1757                 :            :     }
    1758         [ +  + ]:     127264 :     else if (is_libjulia_func(jl_string_ptr)) {
    1759                 :      21391 :         ++CCALL_STAT(jl_string_ptr);
    1760         [ -  + ]:      21391 :         assert(lrt == getSizeTy(ctx.builder.getContext()));
    1761   [ +  -  +  -  :      21391 :         assert(!isVa && !llvmcall && nccallargs == 1);
                   +  - ]
    1762                 :      21391 :         auto obj = emit_bitcast(ctx, emit_pointer_from_objref(ctx, boxed(ctx, argv[0])),
    1763                 :      21391 :                                 ctx.types().T_pprjlvalue);
    1764                 :            :         // The inbounds gep makes it more clear to LLVM that the resulting value is not
    1765                 :            :         // a null pointer.
    1766                 :      21391 :         auto strp = ctx.builder.CreateConstInBoundsGEP1_32(ctx.types().T_prjlvalue, obj, 1);
    1767                 :      21391 :         strp = ctx.builder.CreatePtrToInt(strp, getSizeTy(ctx.builder.getContext()));
    1768                 :      21391 :         JL_GC_POP();
    1769                 :      21391 :         return mark_or_box_ccall_result(ctx, strp, retboxed, rt, unionall, static_rt);
    1770                 :            :     }
    1771         [ +  + ]:     105873 :     else if (is_libjulia_func(jl_symbol_name)) {
    1772                 :       2508 :         ++CCALL_STAT(jl_symbol_name);
    1773         [ -  + ]:       2508 :         assert(lrt == getSizeTy(ctx.builder.getContext()));
    1774   [ +  -  +  -  :       2508 :         assert(!isVa && !llvmcall && nccallargs == 1);
                   +  - ]
    1775                 :       2508 :         auto obj = emit_bitcast(ctx, emit_pointer_from_objref(ctx, boxed(ctx, argv[0])),
    1776                 :       2508 :                                 ctx.types().T_pprjlvalue);
    1777                 :            :         // The inbounds gep makes it more clear to LLVM that the resulting value is not
    1778                 :            :         // a null pointer.
    1779                 :       5016 :         auto strp = ctx.builder.CreateConstInBoundsGEP1_32(
    1780                 :       2508 :             ctx.types().T_prjlvalue, obj, (sizeof(jl_sym_t) + sizeof(void*) - 1) / sizeof(void*));
    1781                 :       2508 :         strp = ctx.builder.CreatePtrToInt(strp, getSizeTy(ctx.builder.getContext()));
    1782                 :       2508 :         JL_GC_POP();
    1783                 :       2508 :         return mark_or_box_ccall_result(ctx, strp, retboxed, rt, unionall, static_rt);
    1784                 :            :     }
    1785   [ +  +  +  -  :     103365 :     else if (is_libjulia_func(memcpy) && (rt == (jl_value_t*)jl_nothing_type || jl_is_cpointer_type(rt))) {
             +  -  +  + ]
    1786                 :        190 :         ++CCALL_STAT(memcpy);
    1787                 :        190 :         const jl_cgval_t &dst = argv[0];
    1788                 :        190 :         const jl_cgval_t &src = argv[1];
    1789                 :        190 :         const jl_cgval_t &n = argv[2];
    1790                 :        190 :         Value *destp = emit_unbox(ctx, getSizeTy(ctx.builder.getContext()), dst, (jl_value_t*)jl_voidpointer_type);
    1791                 :            : 
    1792                 :        570 :         ctx.builder.CreateMemCpy(
    1793                 :        190 :                 emit_inttoptr(ctx, destp, getInt8PtrTy(ctx.builder.getContext())),
    1794                 :            :                 MaybeAlign(1),
    1795                 :            :                 emit_inttoptr(ctx,
    1796                 :        190 :                     emit_unbox(ctx, getSizeTy(ctx.builder.getContext()), src, (jl_value_t*)jl_voidpointer_type),
    1797                 :        190 :                     getInt8PtrTy(ctx.builder.getContext())),
    1798                 :            :                 MaybeAlign(0),
    1799                 :        190 :                 emit_unbox(ctx, getSizeTy(ctx.builder.getContext()), n, (jl_value_t*)jl_ulong_type),
    1800                 :            :                 false);
    1801                 :        190 :         JL_GC_POP();
    1802                 :          0 :         return rt == (jl_value_t*)jl_nothing_type ? ghostValue(ctx, jl_nothing_type) :
    1803         [ -  + ]:        190 :             mark_or_box_ccall_result(ctx, destp, retboxed, rt, unionall, static_rt);
    1804                 :            :     }
    1805   [ +  +  +  -  :     103175 :     else if (is_libjulia_func(memset) && (rt == (jl_value_t*)jl_nothing_type || jl_is_cpointer_type(rt))) {
             +  -  +  + ]
    1806                 :       3791 :         ++CCALL_STAT(memset);
    1807                 :       3791 :         const jl_cgval_t &dst = argv[0];
    1808                 :       3791 :         const jl_cgval_t &val = argv[1];
    1809                 :       3791 :         const jl_cgval_t &n = argv[2];
    1810                 :       3791 :         Value *destp = emit_unbox(ctx, getSizeTy(ctx.builder.getContext()), dst, (jl_value_t*)jl_voidpointer_type);
    1811                 :       3791 :         Value *val32 = emit_unbox(ctx, getInt32Ty(ctx.builder.getContext()), val, (jl_value_t*)jl_uint32_type);
    1812                 :       3791 :         Value *val8 = ctx.builder.CreateTrunc(val32, getInt8Ty(ctx.builder.getContext()), "memset_val");
    1813                 :      11373 :         ctx.builder.CreateMemSet(
    1814                 :       3791 :             emit_inttoptr(ctx, destp, getInt8PtrTy(ctx.builder.getContext())),
    1815                 :            :             val8,
    1816                 :       3791 :             emit_unbox(ctx, getSizeTy(ctx.builder.getContext()), n, (jl_value_t*)jl_ulong_type),
    1817                 :            :             MaybeAlign(1)
    1818                 :            :         );
    1819                 :       3791 :         JL_GC_POP();
    1820                 :          0 :         return rt == (jl_value_t*)jl_nothing_type ? ghostValue(ctx, jl_nothing_type) :
    1821         [ -  + ]:       3791 :             mark_or_box_ccall_result(ctx, destp, retboxed, rt, unionall, static_rt);
    1822                 :            :     }
    1823   [ +  +  +  -  :      99384 :     else if (is_libjulia_func(memmove) && (rt == (jl_value_t*)jl_nothing_type || jl_is_cpointer_type(rt))) {
             +  -  +  + ]
    1824                 :       1600 :         ++CCALL_STAT(memmove);
    1825                 :       1600 :         const jl_cgval_t &dst = argv[0];
    1826                 :       1600 :         const jl_cgval_t &src = argv[1];
    1827                 :       1600 :         const jl_cgval_t &n = argv[2];
    1828                 :       1600 :         Value *destp = emit_unbox(ctx, getSizeTy(ctx.builder.getContext()), dst, (jl_value_t*)jl_voidpointer_type);
    1829                 :            : 
    1830                 :       4800 :         ctx.builder.CreateMemMove(
    1831                 :       1600 :                 emit_inttoptr(ctx, destp, getInt8PtrTy(ctx.builder.getContext())),
    1832                 :            :                 MaybeAlign(0),
    1833                 :            :                 emit_inttoptr(ctx,
    1834                 :       1600 :                     emit_unbox(ctx, getSizeTy(ctx.builder.getContext()), src, (jl_value_t*)jl_voidpointer_type),
    1835                 :       1600 :                     getInt8PtrTy(ctx.builder.getContext())),
    1836                 :            :                 MaybeAlign(0),
    1837                 :       1600 :                 emit_unbox(ctx, getSizeTy(ctx.builder.getContext()), n, (jl_value_t*)jl_ulong_type),
    1838                 :            :                 false);
    1839                 :       1600 :         JL_GC_POP();
    1840                 :          0 :         return rt == (jl_value_t*)jl_nothing_type ? ghostValue(ctx, jl_nothing_type) :
    1841         [ -  + ]:       1600 :             mark_or_box_ccall_result(ctx, destp, retboxed, rt, unionall, static_rt);
    1842                 :            :     }
    1843   [ +  +  +  -  :      99792 :     else if (is_libjulia_func(jl_object_id) && nccallargs == 1 &&
                   +  + ]
    1844         [ +  - ]:       2008 :             rt == (jl_value_t*)jl_ulong_type) {
    1845                 :       2008 :         ++CCALL_STAT(jl_object_id);
    1846                 :       2008 :         jl_cgval_t val = argv[0];
    1847         [ +  + ]:       2008 :         if (val.typ == (jl_value_t*)jl_symbol_type) {
    1848                 :       1310 :             JL_GC_POP();
    1849                 :       1310 :             const int hash_offset = offsetof(jl_sym_t, hash);
    1850                 :       1310 :             Value *ph1 = emit_bitcast(ctx, decay_derived(ctx, boxed(ctx, val)), getSizePtrTy(ctx.builder.getContext()));
    1851                 :       1310 :             Value *ph2 = ctx.builder.CreateInBoundsGEP(getSizeTy(ctx.builder.getContext()), ph1, ConstantInt::get(getSizeTy(ctx.builder.getContext()), hash_offset / sizeof(size_t)));
    1852                 :       1310 :             LoadInst *hashval = ctx.builder.CreateAlignedLoad(getSizeTy(ctx.builder.getContext()), ph2, Align(sizeof(size_t)));
    1853                 :       1310 :             tbaa_decorate(ctx.tbaa().tbaa_const, hashval);
    1854                 :       1508 :             return mark_or_box_ccall_result(ctx, hashval, retboxed, rt, unionall, static_rt);
    1855                 :            :         }
    1856         [ +  + ]:        698 :         else if (!val.isboxed) {
    1857                 :            :             // If the value is not boxed, try to compute the object id without
    1858                 :            :             // reboxing it.
    1859                 :        198 :             auto T_pint8_derived = PointerType::get(getInt8Ty(ctx.builder.getContext()), AddressSpace::Derived);
    1860   [ +  +  +  +  :        198 :             if (!val.isghost && !val.ispointer())
                   +  + ]
    1861                 :          6 :                 val = value_to_pointer(ctx, val);
    1862                 :            :             Value *args[] = {
    1863                 :        198 :                 emit_typeof_boxed(ctx, val),
    1864                 :        136 :                 val.isghost ? ConstantPointerNull::get(T_pint8_derived) :
    1865                 :         62 :                     ctx.builder.CreateBitCast(
    1866                 :            :                         decay_derived(ctx, data_pointer(ctx, val)),
    1867                 :            :                         T_pint8_derived)
    1868         [ +  + ]:        198 :             };
    1869                 :        198 :             Value *ret = ctx.builder.CreateCall(prepare_call(jl_object_id__func), makeArrayRef(args));
    1870                 :        198 :             JL_GC_POP();
    1871                 :        198 :             return mark_or_box_ccall_result(ctx, ret, retboxed, rt, unionall, static_rt);
    1872                 :            :         }
    1873                 :            :     }
    1874                 :            : 
    1875                 :            :     jl_cgval_t retval = sig.emit_a_ccall(
    1876                 :            :             ctx,
    1877                 :            :             symarg,
    1878                 :            :             argv,
    1879                 :            :             gc_uses,
    1880                 :      96280 :             static_rt);
    1881                 :      96280 :     JL_GC_POP();
    1882                 :      96280 :     return retval;
    1883                 :            : }
    1884                 :            : 
    1885                 :      96280 : jl_cgval_t function_sig_t::emit_a_ccall(
    1886                 :            :         jl_codectx_t &ctx,
    1887                 :            :         const native_sym_arg_t &symarg,
    1888                 :            :         jl_cgval_t *argv,
    1889                 :            :         SmallVector<Value*, 16> &gc_uses,
    1890                 :            :         bool static_rt) const
    1891                 :            : {
    1892                 :      96280 :     ++EmittedCCalls;
    1893         [ -  + ]:      96280 :     if (!err_msg.empty()) {
    1894                 :          0 :         emit_error(ctx, err_msg);
    1895                 :          0 :         return jl_cgval_t();
    1896                 :            :     }
    1897                 :            : 
    1898                 :      96280 :     FunctionType *functype = this->functype(ctx.builder.getContext());
    1899                 :            : 
    1900                 :      96280 :     Value **argvals = (Value**) alloca((nccallargs + sret) * sizeof(Value*));
    1901         [ +  + ]:     278801 :     for (size_t ai = 0; ai < nccallargs; ai++) {
    1902                 :            :         // Current C function parameter
    1903                 :     182521 :         jl_cgval_t &arg = argv[ai];
    1904                 :     182521 :         jl_value_t *jargty = jl_svecref(at, ai); // Julia type of the current parameter
    1905                 :     182521 :         Type *largty = fargt.at(ai); // LLVM type of the current parameter
    1906                 :     182521 :         bool toboxed = fargt_isboxed.at(ai);
    1907                 :     182521 :         Type *pargty = fargt_sig.at(ai + sret); // LLVM coercion type
    1908                 :     182521 :         bool byRef = byRefList.at(ai); // Argument attributes
    1909                 :            : 
    1910                 :            :         // if we know the function sparams, try to fill those in now
    1911                 :            :         // so that the julia_to_native type checks are more likely to be doable (e.g. concrete types) at compile-time
    1912                 :     182521 :         jl_value_t *jargty_in_env = jargty;
    1913   [ +  +  +  +  :     182521 :         if (ctx.spvals_ptr == NULL && !toboxed && unionall_env && jl_has_typevar_from_unionall(jargty, unionall_env) &&
          +  +  -  +  -  
                      + ]
    1914         [ #  # ]:          0 :                 jl_svec_len(ctx.linfo->sparam_vals) > 0) {
    1915                 :          0 :             jargty_in_env = jl_instantiate_type_in_env(jargty_in_env, unionall_env, jl_svec_data(ctx.linfo->sparam_vals));
    1916         [ #  # ]:          0 :             if (jargty_in_env != jargty)
    1917                 :          0 :                 jl_add_method_root(ctx, jargty_in_env);
    1918                 :            :         }
    1919                 :            : 
    1920                 :            :         Value *v;
    1921         [ +  + ]:     182521 :         if (jl_is_abstract_ref_type(jargty)) {
    1922         [ -  + ]:        704 :             if (!jl_is_cpointer_type(arg.typ)) {
    1923                 :          0 :                 emit_cpointercheck(ctx, arg, "ccall: argument to Ref{T} is not a pointer");
    1924                 :          0 :                 arg.typ = (jl_value_t*)jl_voidpointer_type;
    1925                 :          0 :                 arg.isboxed = false;
    1926                 :            :             }
    1927                 :        704 :             jargty_in_env = (jl_value_t*)jl_voidpointer_type;
    1928                 :            :         }
    1929                 :            : 
    1930                 :     182521 :         v = julia_to_native(ctx, largty, toboxed, jargty_in_env, unionall_env, arg, byRef, ai);
    1931   [ +  +  +  + ]:     182521 :         bool issigned = jl_signed_type && jl_subtype(jargty, (jl_value_t*)jl_signed_type);
    1932         [ -  + ]:     182521 :         if (byRef) {
    1933                 :          0 :             v = decay_derived(ctx, v);
    1934                 :            :             // julia_to_native should already have done the alloca and store
    1935         [ #  # ]:          0 :             assert(v->getType() == pargty);
    1936                 :            :         }
    1937                 :            :         else {
    1938                 :     182521 :             v = llvm_type_rewrite(ctx, v, pargty, issigned);
    1939                 :            :         }
    1940                 :            : 
    1941         [ -  + ]:     182521 :         if (isa<UndefValue>(v)) {
    1942                 :          0 :             return jl_cgval_t();
    1943                 :            :         }
    1944         [ -  + ]:     182521 :         assert(v->getType() == pargty);
    1945                 :     182521 :         argvals[ai + sret] = v;
    1946                 :            :     }
    1947                 :            : 
    1948                 :      96280 :     Value *result = NULL;
    1949                 :            :     //This is only needed if !retboxed && srt && !jlretboxed
    1950                 :      96280 :     Type *sretty = nullptr;
    1951                 :            :     // First, if the ABI requires us to provide the space for the return
    1952                 :            :     // argument, allocate the box and store that as the first argument type
    1953                 :      96280 :     bool sretboxed = false;
    1954         [ +  + ]:      96280 :     if (sret) {
    1955   [ +  -  +  - ]:          4 :         assert(!retboxed && jl_is_datatype(rt) && "sret return type invalid");
    1956         [ +  - ]:          4 :         if (jl_is_pointerfree(rt)) {
    1957                 :          4 :             result = emit_static_alloca(ctx, lrt);
    1958                 :          4 :             sretty = lrt;
    1959                 :          4 :             argvals[0] = ctx.builder.CreateBitCast(result, fargt_sig.at(0));
    1960                 :            :         }
    1961                 :            :         else {
    1962                 :            :             // XXX: result needs to be zero'd and given a GC root here
    1963                 :            :             // and has incorrect write barriers.
    1964                 :            :             // instead this code path should behave like `unsafe_load`
    1965         [ #  # ]:          0 :             assert(jl_datatype_size(rt) > 0 && "sret shouldn't be a singleton instance");
    1966                 :          0 :             result = emit_allocobj(ctx, jl_datatype_size(rt),
    1967                 :          0 :                                    literal_pointer_val(ctx, (jl_value_t*)rt));
    1968                 :          0 :             sretty = ctx.types().T_jlvalue;
    1969                 :          0 :             sretboxed = true;
    1970                 :          0 :             gc_uses.push_back(result);
    1971                 :          0 :             argvals[0] = ctx.builder.CreateBitCast(emit_pointer_from_objref(ctx, result), fargt_sig.at(0));
    1972                 :            :         }
    1973                 :            :     }
    1974                 :            : 
    1975                 :            :     // make LLVM function object for the target
    1976                 :            :     // keep this close to the function call, so that the compiler can
    1977                 :            :     // optimize the global pointer load in the common case
    1978                 :            :     Value *llvmf;
    1979         [ +  + ]:      96280 :     if (llvmcall) {
    1980                 :          4 :         ++EmittedLLVMCalls;
    1981         [ -  + ]:          4 :         if (symarg.jl_ptr != NULL) {
    1982                 :          0 :             emit_error(ctx, "llvmcall doesn't support dynamic pointers");
    1983                 :          0 :             return jl_cgval_t();
    1984                 :            :         }
    1985         [ -  + ]:          4 :         else if (symarg.fptr != NULL) {
    1986                 :          0 :             emit_error(ctx, "llvmcall doesn't support static pointers");
    1987                 :          0 :             return jl_cgval_t();
    1988                 :            :         }
    1989         [ -  + ]:          4 :         else if (symarg.f_lib != NULL) {
    1990                 :          0 :             emit_error(ctx, "llvmcall doesn't support dynamic libraries");
    1991                 :          0 :             return jl_cgval_t();
    1992                 :            :         }
    1993                 :            :         else {
    1994         [ -  + ]:          4 :             assert(symarg.f_name != NULL);
    1995                 :          4 :             StringRef f_name(symarg.f_name);
    1996                 :          4 :             bool f_extern = f_name.consume_front("extern ");
    1997                 :          4 :             llvmf = NULL;
    1998         [ -  + ]:          4 :             if (f_extern) {
    1999                 :          0 :                 llvmf = jl_Module->getOrInsertFunction(f_name, functype).getCallee();
    2000   [ #  #  #  #  :          0 :                 if (!isa<Function>(llvmf) || cast<Function>(llvmf)->isIntrinsic() || cast<Function>(llvmf)->getFunctionType() != functype)
             #  #  #  # ]
    2001                 :          0 :                     llvmf = NULL;
    2002                 :            :             }
    2003         [ +  - ]:          4 :             else if (f_name.startswith("llvm.")) {
    2004                 :            :                 // compute and verify auto-mangling for intrinsic name
    2005                 :          4 :                 auto ID = Function::lookupIntrinsicID(f_name);
    2006         [ +  - ]:          4 :                 if (ID != Intrinsic::not_intrinsic) {
    2007                 :            :                     // Accumulate an array of overloaded types for the given intrinsic
    2008                 :            :                     // and compute the new name mangling schema
    2009                 :          8 :                     SmallVector<Type*, 4> overloadTys;
    2010                 :          8 :                     SmallVector<Intrinsic::IITDescriptor, 8> Table;
    2011                 :          4 :                     getIntrinsicInfoTableEntries(ID, Table);
    2012                 :          4 :                     ArrayRef<Intrinsic::IITDescriptor> TableRef = Table;
    2013                 :          4 :                     auto res = Intrinsic::matchIntrinsicSignature(functype, TableRef, overloadTys);
    2014         [ +  - ]:          4 :                     if (res == Intrinsic::MatchIntrinsicTypes_Match) {
    2015                 :          4 :                         bool matchvararg = !Intrinsic::matchIntrinsicVarArg(functype->isVarArg(), TableRef);
    2016         [ +  - ]:          4 :                         if (matchvararg) {
    2017                 :          4 :                             Function *intrinsic = Intrinsic::getDeclaration(jl_Module, ID, overloadTys);
    2018         [ -  + ]:          4 :                             assert(intrinsic->getFunctionType() == functype);
    2019   [ -  +  -  -  :          4 :                             if (intrinsic->getName() == f_name || Intrinsic::getBaseName(ID) == f_name)
                   +  - ]
    2020                 :          4 :                                 llvmf = intrinsic;
    2021                 :            :                         }
    2022                 :            :                     }
    2023                 :            :                 }
    2024                 :            :             }
    2025         [ -  + ]:          4 :             if (llvmf == NULL) {
    2026                 :          0 :                 emit_error(ctx, "llvmcall only supports intrinsic calls");
    2027                 :          0 :                 return jl_cgval_t();
    2028                 :            :             }
    2029                 :            :         }
    2030                 :            :     }
    2031         [ -  + ]:      96276 :     else if (symarg.jl_ptr != NULL) {
    2032                 :          0 :         ++LiteralCCalls;
    2033                 :          0 :         null_pointer_check(ctx, symarg.jl_ptr);
    2034                 :          0 :         Type *funcptype = PointerType::get(functype, 0);
    2035                 :          0 :         llvmf = emit_inttoptr(ctx, symarg.jl_ptr, funcptype);
    2036                 :            :     }
    2037         [ -  + ]:      96276 :     else if (symarg.fptr != NULL) {
    2038                 :          0 :         ++LiteralCCalls;
    2039                 :          0 :         Type *funcptype = PointerType::get(functype, 0);
    2040                 :          0 :         llvmf = literal_static_pointer_val((void*)(uintptr_t)symarg.fptr, funcptype);
    2041         [ #  # ]:          0 :         if (ctx.emission_context.imaging)
    2042                 :          0 :             jl_printf(JL_STDERR,"WARNING: literal address used in ccall for %s; code cannot be statically compiled\n", symarg.f_name);
    2043                 :            :     }
    2044                 :            :     else {
    2045         [ -  + ]:      96276 :         assert(symarg.f_name != NULL);
    2046                 :      96276 :         PointerType *funcptype = PointerType::get(functype, 0);
    2047         [ -  + ]:      96276 :         if (symarg.lib_expr) {
    2048                 :          0 :             ++DeferredCCallLookups;
    2049                 :          0 :             llvmf = runtime_sym_lookup(ctx, funcptype, NULL, symarg.lib_expr, symarg.f_name, ctx.f);
    2050                 :            :         }
    2051         [ +  + ]:      96276 :         else if (ctx.emission_context.imaging) {
    2052                 :      61952 :             ++DeferredCCallLookups;
    2053                 :            :             // vararg requires musttail,
    2054                 :            :             // but musttail is incompatible with noreturn.
    2055         [ +  + ]:      61952 :             if (functype->isVarArg())
    2056                 :       1454 :                 llvmf = runtime_sym_lookup(ctx, funcptype, symarg.f_lib, NULL, symarg.f_name, ctx.f);
    2057                 :            :             else
    2058                 :      60498 :                 llvmf = emit_plt(ctx, functype, attributes, cc, symarg.f_lib, symarg.f_name);
    2059                 :            :         }
    2060                 :            :         else {
    2061                 :            :             void *symaddr;
    2062                 :      34324 :             void *libsym = jl_get_library_(symarg.f_lib, 0);
    2063   [ +  -  -  +  :      34324 :             if (!libsym || !jl_dlsym(libsym, symarg.f_name, &symaddr, 0)) {
                   -  + ]
    2064                 :          0 :                 ++DeferredCCallLookups;
    2065                 :            :                 // either the library or the symbol could not be found, place a runtime
    2066                 :            :                 // lookup here instead.
    2067                 :          0 :                 llvmf = runtime_sym_lookup(ctx, funcptype, symarg.f_lib, NULL, symarg.f_name, ctx.f);
    2068                 :            :             } else {
    2069                 :      34324 :                 ++LiteralCCalls;
    2070                 :            :                 // since we aren't saving this code, there's no sense in
    2071                 :            :                 // putting anything complicated here: just JIT the function address
    2072                 :      34324 :                 llvmf = literal_static_pointer_val(symaddr, funcptype);
    2073                 :            :             }
    2074                 :            :         }
    2075                 :            :     }
    2076                 :            : 
    2077                 :     288840 :     OperandBundleDef OpBundle("jl_roots", gc_uses);
    2078                 :            :     // the actual call
    2079         [ +  + ]:     288840 :     CallInst *ret = ctx.builder.CreateCall(functype, llvmf,
    2080                 :      96280 :             ArrayRef<Value*>(&argvals[0], nccallargs + sret),
    2081                 :      96280 :             ArrayRef<OperandBundleDef>(&OpBundle, gc_uses.empty() ? 0 : 1));
    2082                 :      96280 :     ((CallInst*)ret)->setAttributes(attributes);
    2083                 :            : 
    2084         [ -  + ]:      96280 :     if (cc != CallingConv::C)
    2085                 :          0 :         ((CallInst*)ret)->setCallingConv(cc);
    2086         [ +  + ]:      96280 :     if (!sret)
    2087                 :      96276 :         result = ret; // no need to update sretty here because we know !sret
    2088                 :            :     if (0) { // Enable this to turn on SSPREQ (-fstack-protector) on the function containing this ccall
    2089                 :            :         ctx.f->addFnAttr(Attribute::StackProtectReq);
    2090                 :            :     }
    2091                 :            : 
    2092         [ +  + ]:      96280 :     if (rt == jl_bottom_type) {
    2093                 :         50 :         CreateTrap(ctx.builder);
    2094                 :         50 :         return jl_cgval_t();
    2095                 :            :     }
    2096                 :            : 
    2097                 :            :     // Finally we need to box the result into julia type
    2098                 :            :     // However, if we have already created a box for the return
    2099                 :            :     // type because the ABI required us to pass a pointer (sret),
    2100                 :            :     // then we do not need to do this.
    2101                 :            :     bool jlretboxed;
    2102         [ +  + ]:      96230 :     if (retboxed) {
    2103         [ -  + ]:      46223 :         assert(!sret);
    2104                 :      46223 :         jlretboxed = true;
    2105                 :      46223 :         ++RetBoxedCCalls;
    2106                 :            :     }
    2107         [ +  + ]:      50007 :     else if (sret) {
    2108                 :          4 :         jlretboxed = sretboxed;
    2109         [ +  - ]:          4 :         if (!jlretboxed) {
    2110                 :            :             // something alloca'd above is SSA
    2111         [ +  - ]:          4 :             if (static_rt)
    2112                 :          4 :                 return mark_julia_slot(result, rt, NULL, ctx.tbaa().tbaa_stack);
    2113                 :          0 :             ++SRetCCalls;
    2114                 :          0 :             result = ctx.builder.CreateLoad(sretty, result);
    2115                 :            :         }
    2116                 :            :     }
    2117                 :            :     else {
    2118                 :      50003 :         Type *jlrt = julia_type_to_llvm(ctx, rt, &jlretboxed); // compute the real "julian" return type and compute whether it is boxed
    2119         [ +  + ]:      50003 :         if (type_is_ghost(jlrt)) {
    2120                 :      35290 :             return ghostValue(ctx, rt);
    2121                 :            :         }
    2122   [ +  -  -  +  :      14713 :         else if (jl_is_datatype(rt) && jl_is_datatype_singleton((jl_datatype_t*)rt)) {
                   -  + ]
    2123                 :          0 :             return mark_julia_const(ctx, ((jl_datatype_t*)rt)->instance);
    2124                 :            :         }
    2125   [ -  +  -  - ]:      14713 :         else if (jlretboxed && !retboxed) {
    2126         [ #  # ]:          0 :             assert(jl_is_datatype(rt));
    2127         [ #  # ]:          0 :             if (static_rt) {
    2128                 :          0 :                 Value *runtime_bt = literal_pointer_val(ctx, rt);
    2129                 :          0 :                 size_t rtsz = jl_datatype_size(rt);
    2130         [ #  # ]:          0 :                 assert(rtsz > 0);
    2131                 :          0 :                 Value *strct = emit_allocobj(ctx, rtsz, runtime_bt);
    2132         [ #  # ]:          0 :                 MDNode *tbaa = jl_is_mutable(rt) ? ctx.tbaa().tbaa_mutab : ctx.tbaa().tbaa_immut;
    2133                 :          0 :                 int boxalign = julia_alignment(rt);
    2134                 :            :                 // copy the data from the return value to the new struct
    2135                 :          0 :                 const DataLayout &DL = ctx.builder.GetInsertBlock()->getModule()->getDataLayout();
    2136                 :          0 :                 auto resultTy = result->getType();
    2137         [ #  # ]:          0 :                 if (DL.getTypeStoreSize(resultTy) > rtsz) {
    2138                 :            :                     // ARM and AArch64 can use a LLVM type larger than the julia type.
    2139                 :            :                     // When this happens, cast through memory.
    2140                 :          0 :                     auto slot = emit_static_alloca(ctx, resultTy);
    2141                 :          0 :                     slot->setAlignment(Align(boxalign));
    2142                 :          0 :                     ctx.builder.CreateAlignedStore(result, slot, Align(boxalign));
    2143                 :          0 :                     emit_memcpy(ctx, strct, tbaa, slot, tbaa, rtsz, boxalign);
    2144                 :            :                 }
    2145                 :            :                 else {
    2146                 :          0 :                     init_bits_value(ctx, strct, result, tbaa, boxalign);
    2147                 :            :                 }
    2148                 :          0 :                 return mark_julia_type(ctx, strct, true, rt);
    2149                 :            :             }
    2150                 :          0 :             jlretboxed = false; // trigger mark_or_box_ccall_result to build the runtime box
    2151                 :            :         }
    2152         [ +  + ]:      14713 :         else if (lrt != prt) {
    2153   [ -  +  -  - ]:         96 :             assert(jlrt == lrt || !lrt->isStructTy()); // julia_type_to_llvm and julia_struct_to_llvm should be returning the same StructType
    2154                 :         96 :             result = llvm_type_rewrite(ctx, result, lrt, false);
    2155                 :            :         }
    2156                 :            :     }
    2157                 :            : 
    2158                 :      60936 :     return mark_or_box_ccall_result(ctx, result, jlretboxed, rt, unionall_env, static_rt);
    2159                 :            : }
    2160                 :            : 
    2161                 :            : // Reset us back to codegen debug type
    2162                 :            : #undef DEBUG_TYPE
    2163                 :            : #define DEBUG_TYPE "julia_irgen_codegen"

Generated by: LCOV version 1.14