diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2017-06-26 20:32:52 +0000 | 
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2017-06-26 20:32:52 +0000 | 
| commit | 08bbd35a80bf7765fe0d3043f9eb5a2f2786b649 (patch) | |
| tree | 80108f0f128657f8623f8f66ad9735b4d88e7b47 /lib/CodeGen/AsmPrinter | |
| parent | 7c7aba6e5fef47a01a136be655b0a92cfd7090f6 (diff) | |
Notes
Diffstat (limited to 'lib/CodeGen/AsmPrinter')
| -rw-r--r-- | lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 14 | ||||
| -rw-r--r-- | lib/CodeGen/AsmPrinter/DIE.cpp | 6 | ||||
| -rw-r--r-- | lib/CodeGen/AsmPrinter/DwarfDebug.cpp | 68 | 
3 files changed, 65 insertions, 23 deletions
| diff --git a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index ad348d723bae..c48fcaa7b0d1 100644 --- a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -2801,26 +2801,24 @@ void AsmPrinter::emitXRayTable() {    }    // Before we switch over, we force a reference to a label inside the -  // xray_instr_map and xray_fn_idx sections. Since this function is always -  // called just before the function's end, we assume that this is happening -  // after the last return instruction. We also use the synthetic label in the -  // xray_inster_map as a delimeter for the range of sleds for this function in -  // the index. +  // xray_fn_idx sections. This makes sure that the xray_fn_idx section is kept +  // live by the linker if the function is not garbage-collected. Since this +  // function is always called just before the function's end, we assume that +  // this is happening after the last return instruction.    auto WordSizeBytes = MAI->getCodePointerSize(); -  MCSymbol *SledsStart = OutContext.createTempSymbol("xray_synthetic_", true);    MCSymbol *IdxRef = OutContext.createTempSymbol("xray_fn_idx_synth_", true);    OutStreamer->EmitCodeAlignment(16); -  OutStreamer->EmitSymbolValue(SledsStart, WordSizeBytes, false);    OutStreamer->EmitSymbolValue(IdxRef, WordSizeBytes, false);    // Now we switch to the instrumentation map section. Because this is done    // per-function, we are able to create an index entry that will represent the    // range of sleds associated with a function. +  MCSymbol *SledsStart = OutContext.createTempSymbol("xray_sleds_start", true);    OutStreamer->SwitchSection(InstMap);    OutStreamer->EmitLabel(SledsStart);    for (const auto &Sled : Sleds)      Sled.emit(WordSizeBytes, OutStreamer.get(), CurrentFnSym); -  MCSymbol *SledsEnd = OutContext.createTempSymbol("xray_synthetic_end", true); +  MCSymbol *SledsEnd = OutContext.createTempSymbol("xray_sleds_end", true);    OutStreamer->EmitLabel(SledsEnd);    // We then emit a single entry in the index per function. We use the symbols diff --git a/lib/CodeGen/AsmPrinter/DIE.cpp b/lib/CodeGen/AsmPrinter/DIE.cpp index 30bfd7c94e68..886e6e264b3e 100644 --- a/lib/CodeGen/AsmPrinter/DIE.cpp +++ b/lib/CodeGen/AsmPrinter/DIE.cpp @@ -105,7 +105,7 @@ void DIEAbbrev::Emit(const AsmPrinter *AP) const {  }  LLVM_DUMP_METHOD -void DIEAbbrev::print(raw_ostream &O) { +void DIEAbbrev::print(raw_ostream &O) const {    O << "Abbreviation @"      << format("0x%lx", (long)(intptr_t)this)      << "  " @@ -128,7 +128,7 @@ void DIEAbbrev::print(raw_ostream &O) {  }  #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) -LLVM_DUMP_METHOD void DIEAbbrev::dump() { +LLVM_DUMP_METHOD void DIEAbbrev::dump() const {    print(dbgs());  }  #endif @@ -268,7 +268,7 @@ void DIE::print(raw_ostream &O, unsigned IndentCount) const {  }  #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) -LLVM_DUMP_METHOD void DIE::dump() { +LLVM_DUMP_METHOD void DIE::dump() const {    print(dbgs());  }  #endif diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp index 75eb355bfb54..f1b4d9f20ca9 100644 --- a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -972,16 +972,62 @@ DbgVariable *DwarfDebug::createConcreteVariable(DwarfCompileUnit &TheCU,    return ConcreteVariables.back().get();  } -// Determine whether this DBG_VALUE is valid at the beginning of the function. -static bool validAtEntry(const MachineInstr *MInsn) { -  auto MBB = MInsn->getParent(); -  // Is it in the entry basic block? -  if (!MBB->pred_empty()) +/// Determine whether a *singular* DBG_VALUE is valid for the entirety of its +/// enclosing lexical scope. The check ensures there are no other instructions +/// in the same lexical scope preceding the DBG_VALUE and that its range is +/// either open or otherwise rolls off the end of the scope. +static bool validThroughout(LexicalScopes &LScopes, +                            const MachineInstr *DbgValue, +                            const MachineInstr *RangeEnd) { +  assert(DbgValue->getDebugLoc() && "DBG_VALUE without a debug location"); +  auto MBB = DbgValue->getParent(); +  auto DL = DbgValue->getDebugLoc(); +  auto *LScope = LScopes.findLexicalScope(DL); +  // Scope doesn't exist; this is a dead DBG_VALUE. +  if (!LScope)      return false; -  for (MachineBasicBlock::const_reverse_iterator I(MInsn); I != MBB->rend(); ++I) -    if (!(I->isDebugValue() || I->getFlag(MachineInstr::FrameSetup))) +  auto &LSRange = LScope->getRanges(); +  if (LSRange.size() == 0) +    return false; + +  // Determine if the DBG_VALUE is valid at the beginning of its lexical block. +  const MachineInstr *LScopeBegin = LSRange.front().first; +  // Early exit if the lexical scope begins outside of the current block. +  if (LScopeBegin->getParent() != MBB) +    return false; +  MachineBasicBlock::const_reverse_iterator Pred(DbgValue); +  for (++Pred; Pred != MBB->rend(); ++Pred) { +    if (Pred->getFlag(MachineInstr::FrameSetup)) +      break; +    auto PredDL = Pred->getDebugLoc(); +    if (!PredDL || Pred->isMetaInstruction()) +      continue; +    // Check whether the instruction preceding the DBG_VALUE is in the same +    // (sub)scope as the DBG_VALUE. +    if (DL->getScope() == PredDL->getScope())        return false; -  return true; +    auto *PredScope = LScopes.findLexicalScope(PredDL); +    if (!PredScope || LScope->dominates(PredScope)) +      return false; +  } + +  // If the range of the DBG_VALUE is open-ended, report success. +  if (!RangeEnd) +    return true; + +  // Fail if there are instructions belonging to our scope in another block. +  const MachineInstr *LScopeEnd = LSRange.back().second; +  if (LScopeEnd->getParent() != MBB) +    return false; + +  // Single, constant DBG_VALUEs in the prologue are promoted to be live +  // throughout the function. This is a hack, presumably for DWARF v2 and not +  // necessarily correct. It would be much better to use a dbg.declare instead +  // if we know the constant is live throughout the scope. +  if (DbgValue->getOperand(0).isImm() && MBB->pred_empty()) +    return true; + +  return false;  }  // Find variables for each lexical scope. @@ -1016,11 +1062,9 @@ void DwarfDebug::collectVariableInfo(DwarfCompileUnit &TheCU,      const MachineInstr *MInsn = Ranges.front().first;      assert(MInsn->isDebugValue() && "History must begin with debug value"); -    // Check if there is a single DBG_VALUE, valid throughout the function. -    // A single constant is also considered valid for the entire function. +    // Check if there is a single DBG_VALUE, valid throughout the var's scope.      if (Ranges.size() == 1 && -        (MInsn->getOperand(0).isImm() || -         (validAtEntry(MInsn) && Ranges.front().second == nullptr))) { +        validThroughout(LScopes, MInsn, Ranges.front().second)) {        RegVar->initializeDbgValue(MInsn);        continue;      } | 
