Example #1
0
// Clone the module-level debug info associated with OldFunc. The cloned data
// will point to NewFunc instead.
static void CloneDebugInfoMetadata(Function *NewFunc, const Function *OldFunc,
                            ValueToValueMapTy &VMap) {
  DebugInfoFinder Finder;
  Finder.processModule(*OldFunc->getParent());

  const MDNode *OldSubprogramMDNode = FindSubprogram(OldFunc, Finder);
  if (!OldSubprogramMDNode) return;

  // Ensure that OldFunc appears in the map.
  // (if it's already there it must point to NewFunc anyway)
  VMap[OldFunc] = NewFunc;
  DISubprogram NewSubprogram(MapMetadata(OldSubprogramMDNode, VMap));

  for (DICompileUnit CU : Finder.compile_units()) {
    DIArray Subprograms(CU.getSubprograms());

    // If the compile unit's function list contains the old function, it should
    // also contain the new one.
    for (unsigned i = 0; i < Subprograms.getNumElements(); i++) {
      if ((MDNode*)Subprograms.getElement(i) == OldSubprogramMDNode) {
        AddOperand(CU, Subprograms, NewSubprogram);
        break;
      }
    }
  }
}
void PTXAsmPrinter::EmitStartOfAsmFile(Module &M)
{
  const PTXSubtarget& ST = TM.getSubtarget<PTXSubtarget>();

  // Emit the PTX .version and .target attributes
  OutStreamer.EmitRawText(Twine("\t.version ") + ST.getPTXVersionString());
  OutStreamer.EmitRawText(Twine("\t.target ") + ST.getTargetString() +
                                (ST.supportsDouble() ? ""
                                                     : ", map_f64_to_f32"));
  // .address_size directive is optional, but it must immediately follow
  // the .target directive if present within a module
  if (ST.supportsPTX23()) {
    const char *addrSize = ST.is64Bit() ? "64" : "32";
    OutStreamer.EmitRawText(Twine("\t.address_size ") + addrSize);
  }

  OutStreamer.AddBlankLine();

  // Define any .file directives
  DebugInfoFinder DbgFinder;
  DbgFinder.processModule(M);

  for (DebugInfoFinder::iterator I = DbgFinder.compile_unit_begin(),
       E = DbgFinder.compile_unit_end(); I != E; ++I) {
    DICompileUnit DIUnit(*I);
    StringRef FN = DIUnit.getFilename();
    StringRef Dir = DIUnit.getDirectory();
    GetOrCreateSourceID(FN, Dir);
  }

  OutStreamer.AddBlankLine();

  // declare external functions
  for (Module::const_iterator i = M.begin(), e = M.end();
       i != e; ++i)
    EmitFunctionDeclaration(i);
  
  // declare global variables
  for (Module::const_global_iterator i = M.global_begin(), e = M.global_end();
       i != e; ++i)
    EmitVariableDeclaration(i);
}
Example #3
0
// Clone the module-level debug info associated with OldFunc. The cloned data
// will point to NewFunc instead.
static void CloneDebugInfoMetadata(Function *NewFunc, const Function *OldFunc,
                            ValueToValueMapTy &VMap) {
  DebugInfoFinder Finder;
  Finder.processModule(*OldFunc->getParent());

  const DISubprogram *OldSubprogramMDNode = FindSubprogram(OldFunc, Finder);
  if (!OldSubprogramMDNode) return;

  auto *NewSubprogram =
      cast<DISubprogram>(MapMetadata(OldSubprogramMDNode, VMap));
  NewFunc->setSubprogram(NewSubprogram);

  for (auto *CU : Finder.compile_units()) {
    auto Subprograms = CU->getSubprograms();
    // If the compile unit's function list contains the old function, it should
    // also contain the new one.
    for (auto *SP : Subprograms) {
      if (SP == OldSubprogramMDNode) {
        AddOperand(CU, Subprograms, NewSubprogram);
        break;
      }
    }
  }
}
Example #4
0
// Rewrite all `DICompileUnit` pointers to the `DICompileUnit` specified. See
// the comment in `back/lto.rs` for why this exists.
extern "C" void
LLVMRustThinLTOPatchDICompileUnit(LLVMModuleRef Mod, DICompileUnit *Unit) {
  Module *M = unwrap(Mod);

  // If the original source module didn't have a `DICompileUnit` then try to
  // merge all the existing compile units. If there aren't actually any though
  // then there's not much for us to do so return.
  if (Unit == nullptr) {
    for (DICompileUnit *CU : M->debug_compile_units()) {
      Unit = CU;
      break;
    }
    if (Unit == nullptr)
      return;
  }

  // Use LLVM's built-in `DebugInfoFinder` to find a bunch of debuginfo and
  // process it recursively. Note that we specifically iterate over instructions
  // to ensure we feed everything into it.
  DebugInfoFinder Finder;
  Finder.processModule(*M);
  for (Function &F : M->functions()) {
    for (auto &FI : F) {
      for (Instruction &BI : FI) {
        if (auto Loc = BI.getDebugLoc())
          Finder.processLocation(*M, Loc);
        if (auto DVI = dyn_cast<DbgValueInst>(&BI))
          Finder.processValue(*M, DVI);
        if (auto DDI = dyn_cast<DbgDeclareInst>(&BI))
          Finder.processDeclare(*M, DDI);
      }
    }
  }

  // After we've found all our debuginfo, rewrite all subprograms to point to
  // the same `DICompileUnit`.
  for (auto &F : Finder.subprograms()) {
    F->replaceUnit(Unit);
  }

  // Erase any other references to other `DICompileUnit` instances, the verifier
  // will later ensure that we don't actually have any other stale references to
  // worry about.
  auto *MD = M->getNamedMetadata("llvm.dbg.cu");
  MD->clearOperands();
  MD->addOperand(Unit);
}
Example #5
0
/// Remove any debug info for global variables/functions in the given module for
/// which said global variable/function no longer exists (i.e. is null).
///
/// Debugging information is encoded in llvm IR using metadata. This is designed
/// such a way that debug info for symbols preserved even if symbols are
/// optimized away by the optimizer. This special pass removes debug info for
/// such symbols.
bool StripDeadDebugInfo::runOnModule(Module &M) {
  bool Changed = false;

  LLVMContext &C = M.getContext();

  // Find all debug info in F. This is actually overkill in terms of what we
  // want to do, but we want to try and be as resilient as possible in the face
  // of potential debug info changes by using the formal interfaces given to us
  // as much as possible.
  DebugInfoFinder F;
  F.processModule(M);

  // For each compile unit, find the live set of global variables/functions and
  // replace the current list of potentially dead global variables/functions
  // with the live list.
  SmallVector<Value *, 64> LiveGlobalVariables;
  SmallVector<Value *, 64> LiveSubprograms;
  DenseSet<const MDNode *> VisitedSet;

  for (DebugInfoFinder::iterator CI = F.compile_unit_begin(),
         CE = F.compile_unit_end(); CI != CE; ++CI) {
    // Create our compile unit.
    DICompileUnit DIC(*CI);
    assert(DIC.Verify() && "DIC must verify as a DICompileUnit.");

    // Create our live subprogram list.
    DIArray SPs = DIC.getSubprograms();
    bool SubprogramChange = false;
    for (unsigned i = 0, e = SPs.getNumElements(); i != e; ++i) {
      DISubprogram DISP(SPs.getElement(i));
      assert(DISP.Verify() && "DISP must verify as a DISubprogram.");

      // Make sure we visit each subprogram only once.
      if (!VisitedSet.insert(DISP).second)
        continue;

      // If the function referenced by DISP is not null, the function is live.
      if (DISP.getFunction())
        LiveSubprograms.push_back(DISP);
      else
        SubprogramChange = true;
    }

    // Create our live global variable list.
    DIArray GVs = DIC.getGlobalVariables();
    bool GlobalVariableChange = false;
    for (unsigned i = 0, e = GVs.getNumElements(); i != e; ++i) {
      DIGlobalVariable DIG(GVs.getElement(i));
      assert(DIG.Verify() && "DIG must verify as DIGlobalVariable.");

      // Make sure we only visit each global variable only once.
      if (!VisitedSet.insert(DIG).second)
        continue;

      // If the global variable referenced by DIG is not null, the global
      // variable is live.
      if (DIG.getGlobal())
        LiveGlobalVariables.push_back(DIG);
      else
        GlobalVariableChange = true;
    }

    // If we found dead subprograms or global variables, replace the current
    // subprogram list/global variable list with our new live subprogram/global
    // variable list.
    if (SubprogramChange) {
      // Make sure that 9 is still the index of the subprograms. This is to make
      // sure that an assert is hit if the location of the subprogram array
      // changes. This is just to make sure that this is updated if such an
      // event occurs.
      assert(DIC->getNumOperands() >= 10 &&
             SPs == DIC->getOperand(9) &&
             "DICompileUnits is expected to store Subprograms in operand "
             "9.");
      DIC->replaceOperandWith(9, MDNode::get(C, LiveSubprograms));
      Changed = true;
    }

    if (GlobalVariableChange) {
      // Make sure that 10 is still the index of global variables. This is to
      // make sure that an assert is hit if the location of the subprogram array
      // changes. This is just to make sure that this index is updated if such
      // an event occurs.
      assert(DIC->getNumOperands() >= 11 &&
             GVs == DIC->getOperand(10) &&
             "DICompileUnits is expected to store Global Variables in operand "
             "10.");
      DIC->replaceOperandWith(10, MDNode::get(C, LiveGlobalVariables));
      Changed = true;
    }

    // Reset lists for the next iteration.
    LiveSubprograms.clear();
    LiveGlobalVariables.clear();
  }

  return Changed;
}
Example #6
0
void DIEItem::CreateCompileUnitChildren(wxTreeCtrl *tree,
    const wxTreeItemId& id) {
  // It's expensive to rescan the entire module, but it's only done lazily.
  DebugInfoFinder diFinder;
  diFinder.processModule(*const_cast<Module *>(module_));

  // CU-specific Types
  if (diFinder.type_count() > 0) {
    llvm::SmallVector<llvm::MDNode*, 32> cuTypes;
    for (DebugInfoFinder::iterator it = diFinder.type_begin(),
        itEnd = diFinder.type_end(); it != itEnd; ++it) {
      DIType diType(*it);
      if (diType.getCompileUnit() == node_) {
        cuTypes.push_back(*it);
      }
    }
    if (!cuTypes.empty()) {
      CreateChild(tree, id, new DIETypeListItem(
          module_, _("Types"), cuTypes.begin(), cuTypes.end()));
    }
  }

  // CU-specific Global variables
  if (diFinder.global_variable_count() > 0) {
    llvm::SmallVector<llvm::MDNode*, 32> cuVariables;
    for (DebugInfoFinder::iterator it = diFinder.global_variable_begin(),
        itEnd = diFinder.global_variable_end(); it != itEnd; ++it) {
      DIGlobalVariable diVar(*it);
      if (diVar.getCompileUnit() == node_) {
        cuVariables.push_back(*it);
      }
    }
    if (!cuVariables.empty()) {
      CreateChild(tree, id, new DIEListItem(
          module_, _("Global Variables"),
          cuVariables.begin(), cuVariables.end()));
    }
  }

  // CU-specific Subprograms
  if (diFinder.subprogram_count() > 0) {
    llvm::SmallVector<llvm::MDNode*, 32> cuSubprograms;
    for (DebugInfoFinder::iterator it = diFinder.subprogram_begin(),
        itEnd = diFinder.subprogram_end(); it != itEnd; ++it) {
      DISubprogram diSubprogram(*it);
      if (diSubprogram.getCompileUnit() == node_) {
        cuSubprograms.push_back(*it);
      }
    }
    if (!cuSubprograms.empty()) {
      CreateChild(tree, id, new DIEListItem(
          module_, _("Subprograms"),
          cuSubprograms.begin(), cuSubprograms.end()));
    }
  }
}
Example #7
0
// Clone OldFunc into NewFunc, transforming the old arguments into references to
// VMap values.
//
void llvm::CloneFunctionInto(Function *NewFunc, const Function *OldFunc,
                             ValueToValueMapTy &VMap,
                             bool ModuleLevelChanges,
                             SmallVectorImpl<ReturnInst*> &Returns,
                             const char *NameSuffix, ClonedCodeInfo *CodeInfo,
                             ValueMapTypeRemapper *TypeMapper,
                             ValueMaterializer *Materializer) {
  assert(NameSuffix && "NameSuffix cannot be null!");

#ifndef NDEBUG
  for (const Argument &I : OldFunc->args())
    assert(VMap.count(&I) && "No mapping from source argument specified!");
#endif

  // Copy all attributes other than those stored in the AttributeList.  We need
  // to remap the parameter indices of the AttributeList.
  AttributeList NewAttrs = NewFunc->getAttributes();
  NewFunc->copyAttributesFrom(OldFunc);
  NewFunc->setAttributes(NewAttrs);

  // Fix up the personality function that got copied over.
  if (OldFunc->hasPersonalityFn())
    NewFunc->setPersonalityFn(
        MapValue(OldFunc->getPersonalityFn(), VMap,
                 ModuleLevelChanges ? RF_None : RF_NoModuleLevelChanges,
                 TypeMapper, Materializer));

  SmallVector<AttributeSet, 4> NewArgAttrs(NewFunc->arg_size());
  AttributeList OldAttrs = OldFunc->getAttributes();

  // Clone any argument attributes that are present in the VMap.
  for (const Argument &OldArg : OldFunc->args()) {
    if (Argument *NewArg = dyn_cast<Argument>(VMap[&OldArg])) {
      NewArgAttrs[NewArg->getArgNo()] =
          OldAttrs.getParamAttributes(OldArg.getArgNo());
    }
  }

  NewFunc->setAttributes(
      AttributeList::get(NewFunc->getContext(), OldAttrs.getFnAttributes(),
                         OldAttrs.getRetAttributes(), NewArgAttrs));

  bool MustCloneSP =
      OldFunc->getParent() && OldFunc->getParent() == NewFunc->getParent();
  DISubprogram *SP = OldFunc->getSubprogram();
  if (SP) {
    assert(!MustCloneSP || ModuleLevelChanges);
    // Add mappings for some DebugInfo nodes that we don't want duplicated
    // even if they're distinct.
    auto &MD = VMap.MD();
    MD[SP->getUnit()].reset(SP->getUnit());
    MD[SP->getType()].reset(SP->getType());
    MD[SP->getFile()].reset(SP->getFile());
    // If we're not cloning into the same module, no need to clone the
    // subprogram
    if (!MustCloneSP)
      MD[SP].reset(SP);
  }

  SmallVector<std::pair<unsigned, MDNode *>, 1> MDs;
  OldFunc->getAllMetadata(MDs);
  for (auto MD : MDs) {
    NewFunc->addMetadata(
        MD.first,
        *MapMetadata(MD.second, VMap,
                     ModuleLevelChanges ? RF_None : RF_NoModuleLevelChanges,
                     TypeMapper, Materializer));
  }

  // When we remap instructions, we want to avoid duplicating inlined
  // DISubprograms, so record all subprograms we find as we duplicate
  // instructions and then freeze them in the MD map.
  DebugInfoFinder DIFinder;

  // Loop over all of the basic blocks in the function, cloning them as
  // appropriate.  Note that we save BE this way in order to handle cloning of
  // recursive functions into themselves.
  //
  for (Function::const_iterator BI = OldFunc->begin(), BE = OldFunc->end();
       BI != BE; ++BI) {
    const BasicBlock &BB = *BI;

    // Create a new basic block and copy instructions into it!
    BasicBlock *CBB = CloneBasicBlock(&BB, VMap, NameSuffix, NewFunc, CodeInfo,
                                      SP ? &DIFinder : nullptr);

    // Add basic block mapping.
    VMap[&BB] = CBB;

    // It is only legal to clone a function if a block address within that
    // function is never referenced outside of the function.  Given that, we
    // want to map block addresses from the old function to block addresses in
    // the clone. (This is different from the generic ValueMapper
    // implementation, which generates an invalid blockaddress when
    // cloning a function.)
    if (BB.hasAddressTaken()) {
      Constant *OldBBAddr = BlockAddress::get(const_cast<Function*>(OldFunc),
                                              const_cast<BasicBlock*>(&BB));
      VMap[OldBBAddr] = BlockAddress::get(NewFunc, CBB);
    }

    // Note return instructions for the caller.
    if (ReturnInst *RI = dyn_cast<ReturnInst>(CBB->getTerminator()))
      Returns.push_back(RI);
  }

  for (DISubprogram *ISP : DIFinder.subprograms()) {
    if (ISP != SP) {
      VMap.MD()[ISP].reset(ISP);
    }
  }

  // Loop over all of the instructions in the function, fixing up operand
  // references as we go.  This uses VMap to do all the hard work.
  for (Function::iterator BB =
           cast<BasicBlock>(VMap[&OldFunc->front()])->getIterator(),
                          BE = NewFunc->end();
       BB != BE; ++BB)
    // Loop over all instructions, fixing each one as we find it...
    for (Instruction &II : *BB)
      RemapInstruction(&II, VMap,
                       ModuleLevelChanges ? RF_None : RF_NoModuleLevelChanges,
                       TypeMapper, Materializer);
}
Example #8
0
/// Remove any debug info for global variables/functions in the given module for
/// which said global variable/function no longer exists (i.e. is null).
///
/// Debugging information is encoded in llvm IR using metadata. This is designed
/// such a way that debug info for symbols preserved even if symbols are
/// optimized away by the optimizer. This special pass removes debug info for
/// such symbols.
bool StripDeadDebugInfo::runOnModule(Module &M) {
  if (skipModule(M))
    return false;

  bool Changed = false;

  LLVMContext &C = M.getContext();

  // Find all debug info in F. This is actually overkill in terms of what we
  // want to do, but we want to try and be as resilient as possible in the face
  // of potential debug info changes by using the formal interfaces given to us
  // as much as possible.
  DebugInfoFinder F;
  F.processModule(M);

  // For each compile unit, find the live set of global variables/functions and
  // replace the current list of potentially dead global variables/functions
  // with the live list.
  SmallVector<Metadata *, 64> LiveGlobalVariables;
  DenseSet<DIGlobalVariableExpression *> VisitedSet;

  std::set<DIGlobalVariableExpression *> LiveGVs;
  for (GlobalVariable &GV : M.globals()) {
    SmallVector<DIGlobalVariableExpression *, 1> GVEs;
    GV.getDebugInfo(GVEs);
    for (auto *GVE : GVEs)
      LiveGVs.insert(GVE);
  }

  std::set<DICompileUnit *> LiveCUs;
  // Any CU referenced from a subprogram is live.
  for (DISubprogram *SP : F.subprograms()) {
    if (SP->getUnit())
      LiveCUs.insert(SP->getUnit());
  }

  bool HasDeadCUs = false;
  for (DICompileUnit *DIC : F.compile_units()) {
    // Create our live global variable list.
    bool GlobalVariableChange = false;
    for (auto *DIG : DIC->getGlobalVariables()) {
      if (DIG->getExpression() && DIG->getExpression()->isConstant())
        LiveGVs.insert(DIG);

      // Make sure we only visit each global variable only once.
      if (!VisitedSet.insert(DIG).second)
        continue;

      // If a global variable references DIG, the global variable is live.
      if (LiveGVs.count(DIG))
        LiveGlobalVariables.push_back(DIG);
      else
        GlobalVariableChange = true;
    }

    if (!LiveGlobalVariables.empty())
      LiveCUs.insert(DIC);
    else if (!LiveCUs.count(DIC))
      HasDeadCUs = true;

    // If we found dead global variables, replace the current global
    // variable list with our new live global variable list.
    if (GlobalVariableChange) {
      DIC->replaceGlobalVariables(MDTuple::get(C, LiveGlobalVariables));
      Changed = true;
    }

    // Reset lists for the next iteration.
    LiveGlobalVariables.clear();
  }

  if (HasDeadCUs) {
    // Delete the old node and replace it with a new one
    NamedMDNode *NMD = M.getOrInsertNamedMetadata("llvm.dbg.cu");
    NMD->clearOperands();
    if (!LiveCUs.empty()) {
      for (DICompileUnit *CU : LiveCUs)
        NMD->addOperand(CU);
    }
    Changed = true;
  }

  return Changed;
}