LCOV - code coverage report
Current view: top level - src - llvm-pass-helpers.cpp (source / functions) Hit Total Coverage
Test: [test only] commit 0f242327d2cc9bd130497f44b6350c924185606a Lines: 103 103 100.0 %
Date: 2022-07-16 23:42:53 Functions: 18 18 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 11 12 91.7 %

           Branch data     Line data    Source code
       1                 :            : // This file is a part of Julia. License is MIT: https://julialang.org/license
       2                 :            : 
       3                 :            : //
       4                 :            : // This file implements common functionality that is useful for the late GC frame
       5                 :            : // lowering and final GC intrinsic lowering passes. See the corresponding header
       6                 :            : // for docs.
       7                 :            : 
       8                 :            : #include "llvm-version.h"
       9                 :            : 
      10                 :            : #include <llvm/IR/Function.h>
      11                 :            : #include <llvm/IR/Metadata.h>
      12                 :            : #include <llvm/IR/Module.h>
      13                 :            : #include <llvm/IR/Type.h>
      14                 :            : 
      15                 :            : #include "codegen_shared.h"
      16                 :            : #include "julia_assert.h"
      17                 :            : #include "llvm-pass-helpers.h"
      18                 :            : 
      19                 :            : using namespace llvm;
      20                 :            : 
      21                 :    1207150 : JuliaPassContext::JuliaPassContext()
      22                 :            :     : T_prjlvalue(nullptr),
      23                 :            : 
      24                 :            :         tbaa_gcframe(nullptr), tbaa_tag(nullptr),
      25                 :            : 
      26                 :            :         pgcstack_getter(nullptr), gc_flush_func(nullptr),
      27                 :            :         gc_preserve_begin_func(nullptr), gc_preserve_end_func(nullptr),
      28                 :            :         pointer_from_objref_func(nullptr), alloc_obj_func(nullptr),
      29                 :            :         typeof_func(nullptr), write_barrier_func(nullptr),
      30                 :            :         write_barrier_binding_func(nullptr), call_func(nullptr),
      31                 :    1207150 :         call2_func(nullptr), module(nullptr)
      32                 :            : {
      33                 :    1207150 : }
      34                 :            : 
      35                 :    3467060 : void JuliaPassContext::initFunctions(Module &M)
      36                 :            : {
      37                 :    3467060 :     module = &M;
      38                 :    3467060 :     LLVMContext &llvmctx = M.getContext();
      39                 :            : 
      40                 :    3467060 :     tbaa_gcframe = tbaa_make_child_with_context(llvmctx, "jtbaa_gcframe").first;
      41                 :            :     MDNode *tbaa_data;
      42                 :            :     MDNode *tbaa_data_scalar;
      43                 :    3467060 :     std::tie(tbaa_data, tbaa_data_scalar) = tbaa_make_child_with_context(llvmctx, "jtbaa_data");
      44                 :    3467060 :     tbaa_tag = tbaa_make_child_with_context(llvmctx, "jtbaa_tag", tbaa_data_scalar).first;
      45                 :            : 
      46                 :    3467060 :     pgcstack_getter = M.getFunction("julia.get_pgcstack");
      47                 :    3467060 :     gc_flush_func = M.getFunction("julia.gcroot_flush");
      48                 :    3467060 :     gc_preserve_begin_func = M.getFunction("llvm.julia.gc_preserve_begin");
      49                 :    3467060 :     gc_preserve_end_func = M.getFunction("llvm.julia.gc_preserve_end");
      50                 :    3467060 :     pointer_from_objref_func = M.getFunction("julia.pointer_from_objref");
      51                 :    3467060 :     typeof_func = M.getFunction("julia.typeof");
      52                 :    3467060 :     write_barrier_func = M.getFunction("julia.write_barrier");
      53                 :    3467060 :     write_barrier_binding_func = M.getFunction("julia.write_barrier_binding");
      54                 :    3467060 :     alloc_obj_func = M.getFunction("julia.gc_alloc_obj");
      55                 :    3467060 :     call_func = M.getFunction("julia.call");
      56                 :    3467060 :     call2_func = M.getFunction("julia.call2");
      57                 :    3467060 : }
      58                 :            : 
      59                 :    2263260 : void JuliaPassContext::initAll(Module &M)
      60                 :            : {
      61                 :            :     // First initialize the functions.
      62                 :    2263260 :     initFunctions(M);
      63                 :            : 
      64                 :            :     // Then initialize types and metadata nodes.
      65                 :    2263260 :     auto &ctx = M.getContext();
      66                 :            : 
      67                 :            :     // Construct derived types.
      68                 :    2263260 :     T_prjlvalue = JuliaType::get_prjlvalue_ty(ctx);
      69                 :    2263260 : }
      70                 :            : 
      71                 :    1372710 : llvm::CallInst *JuliaPassContext::getPGCstack(llvm::Function &F) const
      72                 :            : {
      73                 :    3963750 :     for (auto I = F.getEntryBlock().begin(), E = F.getEntryBlock().end();
      74   [ +  -  +  +  :    6554800 :          pgcstack_getter && I != E; ++I) {
                   +  + ]
      75         [ +  + ]:    3962300 :         if (CallInst *callInst = dyn_cast<CallInst>(&*I)) {
      76         [ +  + ]:    2106050 :             if (callInst->getCalledOperand() == pgcstack_getter) {
      77                 :    1371260 :                 return callInst;
      78                 :            :             }
      79                 :            :         }
      80                 :            :     }
      81                 :       1450 :     return nullptr;
      82                 :            : }
      83                 :            : 
      84                 :    9765820 : llvm::Function *JuliaPassContext::getOrNull(
      85                 :            :     const jl_intrinsics::IntrinsicDescription &desc) const
      86                 :            : {
      87                 :    9765820 :     return module->getFunction(desc.name);
      88                 :            : }
      89                 :            : 
      90                 :    4966410 : llvm::Function *JuliaPassContext::getOrDeclare(
      91                 :            :     const jl_intrinsics::IntrinsicDescription &desc)
      92                 :            : {
      93                 :    4966410 :     auto local = getOrNull(desc);
      94         [ +  + ]:    4966410 :     if (local) {
      95                 :            :         // If the function exists already, then we'll
      96                 :            :         // just return it.
      97                 :    2546790 :         return local;
      98                 :            :     }
      99                 :            :     else {
     100                 :            :         // Otherwise, we'll declare it and add it to the module.
     101                 :            :         // Declare the function.
     102                 :    2419620 :         auto func = desc.declare(*this);
     103                 :            :         // Add it to the function list.
     104                 :    2419620 :         module->getFunctionList().push_back(func);
     105                 :            :         // Return the newly created function.
     106                 :    2419620 :         return func;
     107                 :            :     }
     108                 :            : }
     109                 :            : 
     110                 :            : namespace jl_intrinsics {
     111                 :            :     static const char *GET_GC_FRAME_SLOT_NAME = "julia.get_gc_frame_slot";
     112                 :            :     static const char *GC_ALLOC_BYTES_NAME = "julia.gc_alloc_bytes";
     113                 :            :     static const char *NEW_GC_FRAME_NAME = "julia.new_gc_frame";
     114                 :            :     static const char *PUSH_GC_FRAME_NAME = "julia.push_gc_frame";
     115                 :            :     static const char *POP_GC_FRAME_NAME = "julia.pop_gc_frame";
     116                 :            :     static const char *QUEUE_GC_ROOT_NAME = "julia.queue_gc_root";
     117                 :            :     static const char *QUEUE_GC_BINDING_NAME = "julia.queue_gc_binding";
     118                 :            : 
     119                 :            :     // Annotates a function with attributes suitable for GC allocation
     120                 :            :     // functions. Specifically, the return value is marked noalias and nonnull.
     121                 :            :     // The allocation size is set to the first argument.
     122                 :     835250 :     static Function *addGCAllocAttributes(Function *target, LLVMContext &context)
     123                 :            :     {
     124                 :     835250 :         addRetAttr(target, Attribute::NoAlias);
     125                 :     835250 :         addRetAttr(target, Attribute::NonNull);
     126                 :     835250 :         target->addFnAttr(Attribute::getWithAllocSizeArgs(context, 1, None)); // returns %1 bytes
     127                 :     835250 :         return target;
     128                 :            :     }
     129                 :            : 
     130                 :            :     const IntrinsicDescription getGCFrameSlot(
     131                 :            :         GET_GC_FRAME_SLOT_NAME,
     132                 :     226357 :         [](const JuliaPassContext &context) {
     133                 :     905428 :             return Function::Create(
     134                 :            :                 FunctionType::get(
     135                 :     226357 :                     PointerType::get(context.T_prjlvalue, 0),
     136                 :     226357 :                     {PointerType::get(context.T_prjlvalue, 0), Type::getInt32Ty(context.getLLVMContext())},
     137                 :            :                     false),
     138                 :            :                 Function::ExternalLinkage,
     139                 :     226357 :                 GET_GC_FRAME_SLOT_NAME);
     140                 :            :         });
     141                 :            : 
     142                 :            :     const IntrinsicDescription GCAllocBytes(
     143                 :            :         GC_ALLOC_BYTES_NAME,
     144                 :     166240 :         [](const JuliaPassContext &context) {
     145                 :     498720 :             auto intrinsic = Function::Create(
     146                 :            :                 FunctionType::get(
     147                 :     166240 :                     context.T_prjlvalue,
     148                 :     166240 :                     { Type::getInt8PtrTy(context.getLLVMContext()),
     149                 :     166240 :                         sizeof(size_t) == sizeof(uint32_t) ?
     150                 :            :                         Type::getInt32Ty(context.getLLVMContext()) :
     151                 :            :                         Type::getInt64Ty(context.getLLVMContext()) },
     152                 :            :                     false),
     153                 :            :                 Function::ExternalLinkage,
     154                 :            :                 GC_ALLOC_BYTES_NAME);
     155                 :            : 
     156                 :     166240 :             return addGCAllocAttributes(intrinsic, context.getLLVMContext());
     157                 :            :         });
     158                 :            : 
     159                 :            :     const IntrinsicDescription newGCFrame(
     160                 :            :         NEW_GC_FRAME_NAME,
     161                 :     226357 :         [](const JuliaPassContext &context) {
     162                 :     679071 :             auto intrinsic = Function::Create(
     163                 :     452714 :                 FunctionType::get(PointerType::get(context.T_prjlvalue, 0), {Type::getInt32Ty(context.getLLVMContext())}, false),
     164                 :            :                 Function::ExternalLinkage,
     165                 :            :                 NEW_GC_FRAME_NAME);
     166                 :     226357 :             addRetAttr(intrinsic, Attribute::NoAlias);
     167                 :     226357 :             addRetAttr(intrinsic, Attribute::NonNull);
     168                 :            : 
     169                 :     226357 :             return intrinsic;
     170                 :            :         });
     171                 :            : 
     172                 :            :     const IntrinsicDescription pushGCFrame(
     173                 :            :         PUSH_GC_FRAME_NAME,
     174                 :     226357 :         [](const JuliaPassContext &context) {
     175                 :     679071 :             return Function::Create(
     176                 :            :                 FunctionType::get(
     177                 :            :                     Type::getVoidTy(context.getLLVMContext()),
     178                 :     226357 :                     {PointerType::get(context.T_prjlvalue, 0), Type::getInt32Ty(context.getLLVMContext())},
     179                 :            :                     false),
     180                 :            :                 Function::ExternalLinkage,
     181                 :     226357 :                 PUSH_GC_FRAME_NAME);
     182                 :            :         });
     183                 :            : 
     184                 :            :     const IntrinsicDescription popGCFrame(
     185                 :            :         POP_GC_FRAME_NAME,
     186                 :     206719 :         [](const JuliaPassContext &context) {
     187                 :     620157 :             return Function::Create(
     188                 :            :                 FunctionType::get(
     189                 :            :                     Type::getVoidTy(context.getLLVMContext()),
     190                 :     206719 :                     {PointerType::get(context.T_prjlvalue, 0)},
     191                 :            :                     false),
     192                 :            :                 Function::ExternalLinkage,
     193                 :     206719 :                 POP_GC_FRAME_NAME);
     194                 :            :         });
     195                 :            : 
     196                 :            :     const IntrinsicDescription queueGCRoot(
     197                 :            :         QUEUE_GC_ROOT_NAME,
     198                 :      28654 :         [](const JuliaPassContext &context) {
     199                 :      57308 :             auto intrinsic = Function::Create(
     200                 :            :                 FunctionType::get(
     201                 :            :                     Type::getVoidTy(context.getLLVMContext()),
     202                 :      28654 :                     { context.T_prjlvalue },
     203                 :            :                     false),
     204                 :            :                 Function::ExternalLinkage,
     205                 :            :                 QUEUE_GC_ROOT_NAME);
     206                 :      28654 :             intrinsic->addFnAttr(Attribute::InaccessibleMemOrArgMemOnly);
     207                 :      28654 :             return intrinsic;
     208                 :            :         });
     209                 :            : 
     210                 :            :     const IntrinsicDescription queueGCBinding(
     211                 :            :         QUEUE_GC_BINDING_NAME,
     212                 :        919 :         [](const JuliaPassContext &context) {
     213                 :       1838 :             auto intrinsic = Function::Create(
     214                 :            :                 FunctionType::get(
     215                 :            :                     Type::getVoidTy(context.getLLVMContext()),
     216                 :        919 :                     { context.T_prjlvalue },
     217                 :            :                     false),
     218                 :            :                 Function::ExternalLinkage,
     219                 :            :                 QUEUE_GC_BINDING_NAME);
     220                 :        919 :             intrinsic->addFnAttr(Attribute::InaccessibleMemOrArgMemOnly);
     221                 :        919 :             return intrinsic;
     222                 :            :         });
     223                 :            : }
     224                 :            : 
     225                 :            : namespace jl_well_known {
     226                 :            :     static const char *GC_BIG_ALLOC_NAME = XSTR(jl_gc_big_alloc);
     227                 :            :     static const char *GC_POOL_ALLOC_NAME = XSTR(jl_gc_pool_alloc);
     228                 :            :     static const char *GC_QUEUE_ROOT_NAME = XSTR(jl_gc_queue_root);
     229                 :            :     static const char *GC_QUEUE_BINDING_NAME = XSTR(jl_gc_queue_binding);
     230                 :            : 
     231                 :            :     using jl_intrinsics::addGCAllocAttributes;
     232                 :            : 
     233                 :            :     const WellKnownFunctionDescription GCBigAlloc(
     234                 :            :         GC_BIG_ALLOC_NAME,
     235                 :     334505 :         [](const JuliaPassContext &context) {
     236                 :    1003520 :             auto bigAllocFunc = Function::Create(
     237                 :            :                 FunctionType::get(
     238                 :     334505 :                     context.T_prjlvalue,
     239                 :     334505 :                     { Type::getInt8PtrTy(context.getLLVMContext()),
     240                 :     334505 :                         sizeof(size_t) == sizeof(uint32_t) ?
     241                 :            :                         Type::getInt32Ty(context.getLLVMContext()) :
     242                 :            :                         Type::getInt64Ty(context.getLLVMContext()) },
     243                 :            :                     false),
     244                 :            :                 Function::ExternalLinkage,
     245                 :            :                 GC_BIG_ALLOC_NAME);
     246                 :            : 
     247                 :     334505 :             return addGCAllocAttributes(bigAllocFunc, context.getLLVMContext());
     248                 :            :         });
     249                 :            : 
     250                 :            :     const WellKnownFunctionDescription GCPoolAlloc(
     251                 :            :         GC_POOL_ALLOC_NAME,
     252                 :     334505 :         [](const JuliaPassContext &context) {
     253                 :    1003520 :             auto poolAllocFunc = Function::Create(
     254                 :            :                 FunctionType::get(
     255                 :     334505 :                     context.T_prjlvalue,
     256                 :     334505 :                     { Type::getInt8PtrTy(context.getLLVMContext()), Type::getInt32Ty(context.getLLVMContext()), Type::getInt32Ty(context.getLLVMContext()) },
     257                 :            :                     false),
     258                 :            :                 Function::ExternalLinkage,
     259                 :            :                 GC_POOL_ALLOC_NAME);
     260                 :            : 
     261                 :     334505 :             return addGCAllocAttributes(poolAllocFunc, context.getLLVMContext());
     262                 :            :         });
     263                 :            : 
     264                 :            :     const WellKnownFunctionDescription GCQueueBinding(
     265                 :            :         GC_QUEUE_BINDING_NAME,
     266                 :     334505 :         [](const JuliaPassContext &context) {
     267                 :     669010 :             auto func = Function::Create(
     268                 :            :                 FunctionType::get(
     269                 :            :                     Type::getVoidTy(context.getLLVMContext()),
     270                 :     334505 :                     { context.T_prjlvalue },
     271                 :            :                     false),
     272                 :            :                 Function::ExternalLinkage,
     273                 :            :                 GC_QUEUE_BINDING_NAME);
     274                 :     334505 :             func->addFnAttr(Attribute::InaccessibleMemOrArgMemOnly);
     275                 :     334505 :             return func;
     276                 :            :         });
     277                 :            : 
     278                 :            :     const WellKnownFunctionDescription GCQueueRoot(
     279                 :            :         GC_QUEUE_ROOT_NAME,
     280                 :     334505 :         [](const JuliaPassContext &context) {
     281                 :     669010 :             auto func = Function::Create(
     282                 :            :                 FunctionType::get(
     283                 :            :                     Type::getVoidTy(context.getLLVMContext()),
     284                 :     334505 :                     { context.T_prjlvalue },
     285                 :            :                     false),
     286                 :            :                 Function::ExternalLinkage,
     287                 :            :                 GC_QUEUE_ROOT_NAME);
     288                 :     334505 :             func->addFnAttr(Attribute::InaccessibleMemOrArgMemOnly);
     289                 :     334505 :             return func;
     290                 :            :         });
     291                 :            : }

Generated by: LCOV version 1.14