Home | History | Annotate | Line # | Download | only in CodeGen
      1 //===-- GCRootLowering.cpp - Garbage collection infrastructure ------------===//
      2 //
      3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
      4 // See https://llvm.org/LICENSE.txt for license information.
      5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
      6 //
      7 //===----------------------------------------------------------------------===//
      8 //
      9 // This file implements the lowering for the gc.root mechanism.
     10 //
     11 //===----------------------------------------------------------------------===//
     12 
     13 #include "llvm/CodeGen/GCMetadata.h"
     14 #include "llvm/CodeGen/MachineFrameInfo.h"
     15 #include "llvm/CodeGen/MachineFunctionPass.h"
     16 #include "llvm/CodeGen/MachineInstrBuilder.h"
     17 #include "llvm/CodeGen/MachineModuleInfo.h"
     18 #include "llvm/CodeGen/Passes.h"
     19 #include "llvm/CodeGen/TargetFrameLowering.h"
     20 #include "llvm/CodeGen/TargetInstrInfo.h"
     21 #include "llvm/CodeGen/TargetRegisterInfo.h"
     22 #include "llvm/CodeGen/TargetSubtargetInfo.h"
     23 #include "llvm/IR/Dominators.h"
     24 #include "llvm/IR/IntrinsicInst.h"
     25 #include "llvm/IR/Module.h"
     26 #include "llvm/InitializePasses.h"
     27 #include "llvm/Support/Debug.h"
     28 #include "llvm/Support/ErrorHandling.h"
     29 #include "llvm/Support/raw_ostream.h"
     30 
     31 using namespace llvm;
     32 
     33 namespace {
     34 
     35 /// LowerIntrinsics - This pass rewrites calls to the llvm.gcread or
     36 /// llvm.gcwrite intrinsics, replacing them with simple loads and stores as
     37 /// directed by the GCStrategy. It also performs automatic root initialization
     38 /// and custom intrinsic lowering.
     39 class LowerIntrinsics : public FunctionPass {
     40   bool DoLowering(Function &F, GCStrategy &S);
     41 
     42 public:
     43   static char ID;
     44 
     45   LowerIntrinsics();
     46   StringRef getPassName() const override;
     47   void getAnalysisUsage(AnalysisUsage &AU) const override;
     48 
     49   bool doInitialization(Module &M) override;
     50   bool runOnFunction(Function &F) override;
     51 };
     52 
     53 /// GCMachineCodeAnalysis - This is a target-independent pass over the machine
     54 /// function representation to identify safe points for the garbage collector
     55 /// in the machine code. It inserts labels at safe points and populates a
     56 /// GCMetadata record for each function.
     57 class GCMachineCodeAnalysis : public MachineFunctionPass {
     58   GCFunctionInfo *FI;
     59   const TargetInstrInfo *TII;
     60 
     61   void FindSafePoints(MachineFunction &MF);
     62   void VisitCallPoint(MachineBasicBlock::iterator CI);
     63   MCSymbol *InsertLabel(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
     64                         const DebugLoc &DL) const;
     65 
     66   void FindStackOffsets(MachineFunction &MF);
     67 
     68 public:
     69   static char ID;
     70 
     71   GCMachineCodeAnalysis();
     72   void getAnalysisUsage(AnalysisUsage &AU) const override;
     73 
     74   bool runOnMachineFunction(MachineFunction &MF) override;
     75 };
     76 }
     77 
     78 // -----------------------------------------------------------------------------
     79 
     80 INITIALIZE_PASS_BEGIN(LowerIntrinsics, "gc-lowering", "GC Lowering", false,
     81                       false)
     82 INITIALIZE_PASS_DEPENDENCY(GCModuleInfo)
     83 INITIALIZE_PASS_END(LowerIntrinsics, "gc-lowering", "GC Lowering", false, false)
     84 
     85 FunctionPass *llvm::createGCLoweringPass() { return new LowerIntrinsics(); }
     86 
     87 char LowerIntrinsics::ID = 0;
     88 
     89 LowerIntrinsics::LowerIntrinsics() : FunctionPass(ID) {
     90   initializeLowerIntrinsicsPass(*PassRegistry::getPassRegistry());
     91 }
     92 
     93 StringRef LowerIntrinsics::getPassName() const {
     94   return "Lower Garbage Collection Instructions";
     95 }
     96 
     97 void LowerIntrinsics::getAnalysisUsage(AnalysisUsage &AU) const {
     98   FunctionPass::getAnalysisUsage(AU);
     99   AU.addRequired<GCModuleInfo>();
    100   AU.addPreserved<DominatorTreeWrapperPass>();
    101 }
    102 
    103 /// doInitialization - If this module uses the GC intrinsics, find them now.
    104 bool LowerIntrinsics::doInitialization(Module &M) {
    105   GCModuleInfo *MI = getAnalysisIfAvailable<GCModuleInfo>();
    106   assert(MI && "LowerIntrinsics didn't require GCModuleInfo!?");
    107   for (Function &F : M)
    108     if (!F.isDeclaration() && F.hasGC())
    109       MI->getFunctionInfo(F); // Instantiate the GC strategy.
    110 
    111   return false;
    112 }
    113 
    114 /// CouldBecomeSafePoint - Predicate to conservatively determine whether the
    115 /// instruction could introduce a safe point.
    116 static bool CouldBecomeSafePoint(Instruction *I) {
    117   // The natural definition of instructions which could introduce safe points
    118   // are:
    119   //
    120   //   - call, invoke (AfterCall, BeforeCall)
    121   //   - phis (Loops)
    122   //   - invoke, ret, unwind (Exit)
    123   //
    124   // However, instructions as seemingly inoccuous as arithmetic can become
    125   // libcalls upon lowering (e.g., div i64 on a 32-bit platform), so instead
    126   // it is necessary to take a conservative approach.
    127 
    128   if (isa<AllocaInst>(I) || isa<GetElementPtrInst>(I) || isa<StoreInst>(I) ||
    129       isa<LoadInst>(I))
    130     return false;
    131 
    132   // llvm.gcroot is safe because it doesn't do anything at runtime.
    133   if (CallInst *CI = dyn_cast<CallInst>(I))
    134     if (Function *F = CI->getCalledFunction())
    135       if (Intrinsic::ID IID = F->getIntrinsicID())
    136         if (IID == Intrinsic::gcroot)
    137           return false;
    138 
    139   return true;
    140 }
    141 
    142 static bool InsertRootInitializers(Function &F, ArrayRef<AllocaInst *> Roots) {
    143   // Scroll past alloca instructions.
    144   BasicBlock::iterator IP = F.getEntryBlock().begin();
    145   while (isa<AllocaInst>(IP))
    146     ++IP;
    147 
    148   // Search for initializers in the initial BB.
    149   SmallPtrSet<AllocaInst *, 16> InitedRoots;
    150   for (; !CouldBecomeSafePoint(&*IP); ++IP)
    151     if (StoreInst *SI = dyn_cast<StoreInst>(IP))
    152       if (AllocaInst *AI =
    153               dyn_cast<AllocaInst>(SI->getOperand(1)->stripPointerCasts()))
    154         InitedRoots.insert(AI);
    155 
    156   // Add root initializers.
    157   bool MadeChange = false;
    158 
    159   for (AllocaInst *Root : Roots)
    160     if (!InitedRoots.count(Root)) {
    161       new StoreInst(
    162           ConstantPointerNull::get(cast<PointerType>(Root->getAllocatedType())),
    163           Root, Root->getNextNode());
    164       MadeChange = true;
    165     }
    166 
    167   return MadeChange;
    168 }
    169 
    170 /// runOnFunction - Replace gcread/gcwrite intrinsics with loads and stores.
    171 /// Leave gcroot intrinsics; the code generator needs to see those.
    172 bool LowerIntrinsics::runOnFunction(Function &F) {
    173   // Quick exit for functions that do not use GC.
    174   if (!F.hasGC())
    175     return false;
    176 
    177   GCFunctionInfo &FI = getAnalysis<GCModuleInfo>().getFunctionInfo(F);
    178   GCStrategy &S = FI.getStrategy();
    179 
    180   return DoLowering(F, S);
    181 }
    182 
    183 /// Lower barriers out of existance (if the associated GCStrategy hasn't
    184 /// already done so...), and insert initializing stores to roots as a defensive
    185 /// measure.  Given we're going to report all roots live at all safepoints, we
    186 /// need to be able to ensure each root has been initialized by the point the
    187 /// first safepoint is reached.  This really should have been done by the
    188 /// frontend, but the old API made this non-obvious, so we do a potentially
    189 /// redundant store just in case.
    190 bool LowerIntrinsics::DoLowering(Function &F, GCStrategy &S) {
    191   SmallVector<AllocaInst *, 32> Roots;
    192 
    193   bool MadeChange = false;
    194   for (BasicBlock &BB : F)
    195     for (BasicBlock::iterator II = BB.begin(), E = BB.end(); II != E;) {
    196       IntrinsicInst *CI = dyn_cast<IntrinsicInst>(II++);
    197       if (!CI)
    198         continue;
    199 
    200       Function *F = CI->getCalledFunction();
    201       switch (F->getIntrinsicID()) {
    202       default: break;
    203       case Intrinsic::gcwrite: {
    204         // Replace a write barrier with a simple store.
    205         Value *St = new StoreInst(CI->getArgOperand(0),
    206                                   CI->getArgOperand(2), CI);
    207         CI->replaceAllUsesWith(St);
    208         CI->eraseFromParent();
    209         MadeChange = true;
    210         break;
    211       }
    212       case Intrinsic::gcread: {
    213         // Replace a read barrier with a simple load.
    214         Value *Ld = new LoadInst(CI->getType(), CI->getArgOperand(1), "", CI);
    215         Ld->takeName(CI);
    216         CI->replaceAllUsesWith(Ld);
    217         CI->eraseFromParent();
    218         MadeChange = true;
    219         break;
    220       }
    221       case Intrinsic::gcroot: {
    222         // Initialize the GC root, but do not delete the intrinsic. The
    223         // backend needs the intrinsic to flag the stack slot.
    224         Roots.push_back(
    225             cast<AllocaInst>(CI->getArgOperand(0)->stripPointerCasts()));
    226         break;
    227       }
    228       }
    229     }
    230 
    231   if (Roots.size())
    232     MadeChange |= InsertRootInitializers(F, Roots);
    233 
    234   return MadeChange;
    235 }
    236 
    237 // -----------------------------------------------------------------------------
    238 
    239 char GCMachineCodeAnalysis::ID = 0;
    240 char &llvm::GCMachineCodeAnalysisID = GCMachineCodeAnalysis::ID;
    241 
    242 INITIALIZE_PASS(GCMachineCodeAnalysis, "gc-analysis",
    243                 "Analyze Machine Code For Garbage Collection", false, false)
    244 
    245 GCMachineCodeAnalysis::GCMachineCodeAnalysis() : MachineFunctionPass(ID) {}
    246 
    247 void GCMachineCodeAnalysis::getAnalysisUsage(AnalysisUsage &AU) const {
    248   MachineFunctionPass::getAnalysisUsage(AU);
    249   AU.setPreservesAll();
    250   AU.addRequired<GCModuleInfo>();
    251 }
    252 
    253 MCSymbol *GCMachineCodeAnalysis::InsertLabel(MachineBasicBlock &MBB,
    254                                              MachineBasicBlock::iterator MI,
    255                                              const DebugLoc &DL) const {
    256   MCSymbol *Label = MBB.getParent()->getContext().createTempSymbol();
    257   BuildMI(MBB, MI, DL, TII->get(TargetOpcode::GC_LABEL)).addSym(Label);
    258   return Label;
    259 }
    260 
    261 void GCMachineCodeAnalysis::VisitCallPoint(MachineBasicBlock::iterator CI) {
    262   // Find the return address (next instruction), since that's what will be on
    263   // the stack when the call is suspended and we need to inspect the stack.
    264   MachineBasicBlock::iterator RAI = CI;
    265   ++RAI;
    266 
    267   MCSymbol *Label = InsertLabel(*CI->getParent(), RAI, CI->getDebugLoc());
    268   FI->addSafePoint(Label, CI->getDebugLoc());
    269 }
    270 
    271 void GCMachineCodeAnalysis::FindSafePoints(MachineFunction &MF) {
    272   for (MachineBasicBlock &MBB : MF)
    273     for (MachineBasicBlock::iterator MI = MBB.begin(), ME = MBB.end();
    274          MI != ME; ++MI)
    275       if (MI->isCall()) {
    276         // Do not treat tail or sibling call sites as safe points.  This is
    277         // legal since any arguments passed to the callee which live in the
    278         // remnants of the callers frame will be owned and updated by the
    279         // callee if required.
    280         if (MI->isTerminator())
    281           continue;
    282         VisitCallPoint(MI);
    283       }
    284 }
    285 
    286 void GCMachineCodeAnalysis::FindStackOffsets(MachineFunction &MF) {
    287   const TargetFrameLowering *TFI = MF.getSubtarget().getFrameLowering();
    288   assert(TFI && "TargetRegisterInfo not available!");
    289 
    290   for (GCFunctionInfo::roots_iterator RI = FI->roots_begin();
    291        RI != FI->roots_end();) {
    292     // If the root references a dead object, no need to keep it.
    293     if (MF.getFrameInfo().isDeadObjectIndex(RI->Num)) {
    294       RI = FI->removeStackRoot(RI);
    295     } else {
    296       Register FrameReg; // FIXME: surely GCRoot ought to store the
    297                          // register that the offset is from?
    298       auto FrameOffset = TFI->getFrameIndexReference(MF, RI->Num, FrameReg);
    299       assert(!FrameOffset.getScalable() &&
    300              "Frame offsets with a scalable component are not supported");
    301       RI->StackOffset = FrameOffset.getFixed();
    302       ++RI;
    303     }
    304   }
    305 }
    306 
    307 bool GCMachineCodeAnalysis::runOnMachineFunction(MachineFunction &MF) {
    308   // Quick exit for functions that do not use GC.
    309   if (!MF.getFunction().hasGC())
    310     return false;
    311 
    312   FI = &getAnalysis<GCModuleInfo>().getFunctionInfo(MF.getFunction());
    313   TII = MF.getSubtarget().getInstrInfo();
    314 
    315   // Find the size of the stack frame.  There may be no correct static frame
    316   // size, we use UINT64_MAX to represent this.
    317   const MachineFrameInfo &MFI = MF.getFrameInfo();
    318   const TargetRegisterInfo *RegInfo = MF.getSubtarget().getRegisterInfo();
    319   const bool DynamicFrameSize =
    320       MFI.hasVarSizedObjects() || RegInfo->hasStackRealignment(MF);
    321   FI->setFrameSize(DynamicFrameSize ? UINT64_MAX : MFI.getStackSize());
    322 
    323   // Find all safe points.
    324   if (FI->getStrategy().needsSafePoints())
    325     FindSafePoints(MF);
    326 
    327   // Find the concrete stack offsets for all roots (stack slots)
    328   FindStackOffsets(MF);
    329 
    330   return false;
    331 }
    332