Skip to content
DwarfDebug.cpp 132 KiB
Newer Older
  if (!CI || !CI->isZero())
    return NULL;

  // Third operand is offset.
  if (!isa<ConstantInt>(CE->getOperand(2)))
    return NULL;

  return CE;
}

/// constructGlobalVariableDIE - Construct global variable DIE.
void DwarfDebug::constructGlobalVariableDIE(const MDNode *N) {
  DIGlobalVariable GV(N);
  // If debug information is malformed then ignore it.
  if (GV.Verify() == false)
  // Check for pre-existence.
  CompileUnit *TheCU = getCompileUnit(N);
  if (TheCU->getDIE(GV))
Devang Patel's avatar
 
Devang Patel committed
    return;
  DIType GTy = GV.getType();
  DIE *VariableDIE = new DIE(GV.getTag());

  bool isGlobalVariable = GV.getGlobal() != NULL;
  // Add name.
  addString(VariableDIE, dwarf::DW_AT_name, dwarf::DW_FORM_string,
            GV.getDisplayName());
  StringRef LinkageName = GV.getLinkageName();
  if (!LinkageName.empty() && isGlobalVariable)
    addString(VariableDIE, dwarf::DW_AT_MIPS_linkage_name, dwarf::DW_FORM_string,
              getRealLinkageName(LinkageName));
  // Add type.
  addType(VariableDIE, GTy);
  if (GTy.isCompositeType() && !GTy.getName().empty()
      && !GTy.isForwardDecl()) {
    DIEEntry *Entry = TheCU->getDIEEntry(GTy);
    assert(Entry && "Missing global type!");
    TheCU->addGlobalType(GTy.getName(), Entry->getEntry());
  }
  // Add scoping info.
  if (!GV.isLocalToUnit()) {
    addUInt(VariableDIE, dwarf::DW_AT_external, dwarf::DW_FORM_flag, 1);
    // Expose as global. 
    TheCU->addGlobal(GV.getName(), VariableDIE);
  }
  // Add line number info.
  addSourceLine(VariableDIE, GV);
  TheCU->insertDIE(N, VariableDIE);
  // Add to context owner.
  DIDescriptor GVContext = GV.getContext();
  addToContextOwner(VariableDIE, GVContext);
  // Add location.
  if (isGlobalVariable) {
    DIEBlock *Block = new (DIEValueAllocator) DIEBlock();
    addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_addr);
    addLabel(Block, 0, dwarf::DW_FORM_udata,
             Asm->Mang->getSymbol(GV.getGlobal()));
    // Do not create specification DIE if context is either compile unit
    // or a subprogram.
    if (GV.isDefinition() && !GVContext.isCompileUnit() &&
        !GVContext.isFile() && !isSubprogramContext(GVContext)) {
      // Create specification DIE.
      DIE *VariableSpecDIE = new DIE(dwarf::DW_TAG_variable);
      addDIEEntry(VariableSpecDIE, dwarf::DW_AT_specification,
                  dwarf::DW_FORM_ref4, VariableDIE);
      addBlock(VariableSpecDIE, dwarf::DW_AT_location, 0, Block);
      addUInt(VariableDIE, dwarf::DW_AT_declaration, dwarf::DW_FORM_flag, 1);
      TheCU->addDie(VariableSpecDIE);
    } else {
      addBlock(VariableDIE, dwarf::DW_AT_location, 0, Block);
    } 
Devang Patel's avatar
Devang Patel committed
  } else if (ConstantInt *CI = 
             dyn_cast_or_null<ConstantInt>(GV.getConstant()))
    addConstantValue(VariableDIE, CI, isUnsignedDIType(GTy));
  else if (const ConstantExpr *CE = getMergedGlobalExpr(N->getOperand(11))) {
    // GV is a merged global.
    DIEBlock *Block = new (DIEValueAllocator) DIEBlock();
    addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_addr);
    addLabel(Block, 0, dwarf::DW_FORM_udata,
             Asm->Mang->getSymbol(cast<GlobalValue>(CE->getOperand(0))));
    ConstantInt *CII = cast<ConstantInt>(CE->getOperand(2));
    addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_constu);
    addUInt(Block, 0, dwarf::DW_FORM_udata, CII->getZExtValue());
    addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_plus);
    addBlock(VariableDIE, dwarf::DW_AT_location, 0, Block);
  }
Devang Patel's avatar
 
Devang Patel committed
  return;
/// construct SubprogramDIE - Construct subprogram DIE.
void DwarfDebug::constructSubprogramDIE(const MDNode *N) {
Devang Patel's avatar
Devang Patel committed
  DISubprogram SP(N);
  CompileUnit *TheCU = getCompileUnit(N);
  if (TheCU->getDIE(N))
  if (!SP.isDefinition())
    // This is a method declaration which will be handled while constructing
    // class type.
Devang Patel's avatar
 
Devang Patel committed
    return;
  DIE *SubprogramDie = createSubprogramDIE(SP);

  // Add to map.
  TheCU->insertDIE(N, SubprogramDie);
  // Add to context owner.
  addToContextOwner(SubprogramDie, SP.getContext());
  // Expose as global.
  TheCU->addGlobal(SP.getName(), SubprogramDie);
Devang Patel's avatar
Devang Patel committed

Devang Patel's avatar
 
Devang Patel committed
  return;
/// beginModule - Emit all Dwarf sections that should come prior to the
Daniel Dunbar's avatar
Daniel Dunbar committed
/// content. Create global DIEs and emit initial debug info sections.
/// This is inovked by the target AsmPrinter.
void DwarfDebug::beginModule(Module *M) {
Devang Patel's avatar
 
Devang Patel committed
  DebugInfoFinder DbgFinder;
  DbgFinder.processModule(*M);
Devang Patel's avatar
 
Devang Patel committed

  bool HasDebugInfo = false;
  // Scan all the compile-units to see if there are any marked as the main unit.
  // if not, we do not generate debug info.
  for (DebugInfoFinder::iterator I = DbgFinder.compile_unit_begin(),
       E = DbgFinder.compile_unit_end(); I != E; ++I) {
    if (DICompileUnit(*I).isMain()) {
      HasDebugInfo = true;
      break;
    }
  }
  if (!HasDebugInfo) return;

  // Tell MMI that we have debug info.
  MMI->setDebugInfoAvailability(true);
  // Create all the compile unit DIEs.
Devang Patel's avatar
 
Devang Patel committed
  for (DebugInfoFinder::iterator I = DbgFinder.compile_unit_begin(),
         E = DbgFinder.compile_unit_end(); I != E; ++I)
  // Create DIEs for each subprogram.
Devang Patel's avatar
 
Devang Patel committed
  for (DebugInfoFinder::iterator I = DbgFinder.subprogram_begin(),
         E = DbgFinder.subprogram_end(); I != E; ++I)
    constructSubprogramDIE(*I);
Devang Patel's avatar
 
Devang Patel committed

  // Create DIEs for each global variable.
  for (DebugInfoFinder::iterator I = DbgFinder.global_variable_begin(),
         E = DbgFinder.global_variable_end(); I != E; ++I)
    constructGlobalVariableDIE(*I);

  //getOrCreateTypeDIE
  if (NamedMDNode *NMD = M->getNamedMetadata("llvm.dbg.enum"))
    for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i)
      getOrCreateTypeDIE(DIType(NMD->getOperand(i)));

  if (NamedMDNode *NMD = M->getNamedMetadata("llvm.dbg.ty"))
    for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i)
      getOrCreateTypeDIE(DIType(NMD->getOperand(i)));

  // Prime section data.
  SectionMap.insert(Asm->getObjFileLowering().getTextSection());
/// endModule - Emit all Dwarf sections that should come after the content.
void DwarfDebug::endModule() {
  if (!FirstCU) return;
  const Module *M = MMI->getModule();
  DenseMap<const MDNode *, DbgScope *> DeadFnScopeMap;
  if (NamedMDNode *AllSPs = M->getNamedMetadata("llvm.dbg.sp")) {
    for (unsigned SI = 0, SE = AllSPs->getNumOperands(); SI != SE; ++SI) {
      if (ProcessedSPNodes.count(AllSPs->getOperand(SI)) != 0) continue;
      DISubprogram SP(AllSPs->getOperand(SI));
      if (!SP.Verify()) continue;

      // Collect info for variables that were optimized out.
Devang Patel's avatar
Devang Patel committed
      if (!SP.isDefinition()) continue;
      StringRef FName = SP.getLinkageName();
      if (FName.empty())
        FName = SP.getName();
      NamedMDNode *NMD = getFnSpecificMDNode(*(MMI->getModule()), FName);
      if (!NMD) continue;
      unsigned E = NMD->getNumOperands();
      if (!E) continue;
      DbgScope *Scope = new DbgScope(NULL, DIDescriptor(SP), NULL);
      DeadFnScopeMap[SP] = Scope;
      for (unsigned I = 0; I != E; ++I) {
        DIVariable DV(NMD->getOperand(I));
        if (!DV.Verify()) continue;
        Scope->addVariable(new DbgVariable(DV));
      }
      // Construct subprogram DIE and add variables DIEs.
      constructSubprogramDIE(SP);
      DIE *ScopeDIE = getCompileUnit(SP)->getDIE(SP);
Devang Patel's avatar
Devang Patel committed
      const SmallVector<DbgVariable *, 8> &Variables = Scope->getDbgVariables();
      for (unsigned i = 0, N = Variables.size(); i < N; ++i) {
        DIE *VariableDIE = constructVariableDIE(Variables[i], Scope);
        if (VariableDIE)
          ScopeDIE->addChild(VariableDIE);
      }
    }
  }
  // Attach DW_AT_inline attribute with inlined subprogram DIEs.
  for (SmallPtrSet<DIE *, 4>::iterator AI = InlinedSubprogramDIEs.begin(),
         AE = InlinedSubprogramDIEs.end(); AI != AE; ++AI) {
    DIE *ISP = *AI;
    addUInt(ISP, dwarf::DW_AT_inline, 0, dwarf::DW_INL_inlined);
  for (DenseMap<DIE *, const MDNode *>::iterator CI = ContainingTypeMap.begin(),
         CE = ContainingTypeMap.end(); CI != CE; ++CI) {
    DIE *SPDie = CI->first;
    const MDNode *N = dyn_cast_or_null<MDNode>(CI->second);
    DIE *NDie = getCompileUnit(N)->getDIE(N);
    if (!NDie) continue;
    addDIEEntry(SPDie, dwarf::DW_AT_containing_type, dwarf::DW_FORM_ref4, NDie);
  }

  // Standard sections final addresses.
  Asm->OutStreamer.SwitchSection(Asm->getObjFileLowering().getTextSection());
  Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("text_end"));
  Asm->OutStreamer.SwitchSection(Asm->getObjFileLowering().getDataSection());
  Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("data_end"));
  // End text sections.
  for (unsigned i = 1, N = SectionMap.size(); i <= N; ++i) {
    Asm->OutStreamer.SwitchSection(SectionMap[i]);
    Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("section_end", i));
  // Emit common frame information.
  // Emit function debug frame information
  for (std::vector<FunctionDebugFrameInfo>::iterator I = DebugFrames.begin(),
         E = DebugFrames.end(); I != E; ++I)
    emitFunctionDebugFrame(*I);
  // Compute DIE offsets and sizes.
  // Emit all the DIEs into a debug info section
  // Corresponding abbreviations into a abbrev section.
  // Emit info into a debug pubnames section.
Devang Patel's avatar
Devang Patel committed
  // Emit info into a debug pubtypes section.
  emitDebugPubTypes();

  // Emit info into a debug loc section.
  // Emit info into a debug aranges section.
  EmitDebugARanges();
  // Emit info into a debug ranges section.
  // Emit info into a debug macinfo section.
  // Emit inline info.
  // Emit info into a debug str section.
  emitDebugStr();
  // clean up.
  DeleteContainerSeconds(DeadFnScopeMap);
  for (DenseMap<const MDNode *, CompileUnit *>::iterator I = CUMap.begin(),
         E = CUMap.end(); I != E; ++I)
    delete I->second;
  FirstCU = NULL;  // Reset for the next Module, if any.
/// findAbstractVariable - Find abstract variable, if any, associated with Var.
DbgVariable *DwarfDebug::findAbstractVariable(DIVariable &Var,
  DbgVariable *AbsDbgVariable = AbstractVariables.lookup(Var);
  LLVMContext &Ctx = Var->getContext();
  DbgScope *Scope = AbstractScopes.lookup(ScopeLoc.getScope(Ctx));
  AbsDbgVariable = new DbgVariable(Var);
  AbstractVariables[Var] = AbsDbgVariable;
/// addCurrentFnArgument - If Var is an current function argument that add
/// it in CurrentFnArguments list.
bool DwarfDebug::addCurrentFnArgument(const MachineFunction *MF,
                                      DbgVariable *Var, DbgScope *Scope) {
  if (Scope != CurrentFnDbgScope) 
    return false;
  DIVariable DV = Var->getVariable();
  if (DV.getTag() != dwarf::DW_TAG_arg_variable)
    return false;
  unsigned ArgNo = DV.getArgNumber();
  if (ArgNo == 0) 
    return false;

  size_t Size = CurrentFnArguments.size();
  if (Size == 0)
    CurrentFnArguments.resize(MF->getFunction()->arg_size());
  else if (ArgNo > Size)
    CurrentFnArguments.resize(ArgNo * 2);
Devang Patel's avatar
Devang Patel committed
/// collectVariableInfoFromMMITable - Collect variable information from
/// side table maintained by MMI.
Devang Patel's avatar
Devang Patel committed
DwarfDebug::collectVariableInfoFromMMITable(const MachineFunction * MF,
                                   SmallPtrSet<const MDNode *, 16> &Processed) {
  const LLVMContext &Ctx = Asm->MF->getFunction()->getContext();
  MachineModuleInfo::VariableDbgInfoMapTy &VMap = MMI->getVariableDbgInfo();
  for (MachineModuleInfo::VariableDbgInfoMapTy::iterator VI = VMap.begin(),
         VE = VMap.end(); VI != VE; ++VI) {
    const MDNode *Var = VI->first;
    if (!Var) continue;
    DIVariable DV(Var);
    const std::pair<unsigned, DebugLoc> &VP = VI->second;

    DbgScope *Scope = 0;
    if (const MDNode *IA = VP.second.getInlinedAt(Ctx))
      Scope = ConcreteScopes.lookup(IA);
    if (Scope == 0)
      Scope = DbgScopeMap.lookup(VP.second.getScope(Ctx));
    // If variable scope is not found then skip this variable.
    DbgVariable *AbsDbgVariable = findAbstractVariable(DV, VP.second);
    DbgVariable *RegVar = new DbgVariable(DV);
    recordVariableFrameIndex(RegVar, VP.first);
    if (!addCurrentFnArgument(MF, RegVar, Scope))
      Scope->addVariable(RegVar);
    if (AbsDbgVariable) {
      recordVariableFrameIndex(AbsDbgVariable, VP.first);
      VarToAbstractVarMap[RegVar] = AbsDbgVariable;
    }
Devang Patel's avatar
Devang Patel committed
}

/// isDbgValueInDefinedReg - Return true if debug value, encoded by
/// DBG_VALUE instruction, is in a defined reg.
static bool isDbgValueInDefinedReg(const MachineInstr *MI) {
  assert (MI->isDebugValue() && "Invalid DBG_VALUE machine instruction!");
  if (MI->getOperand(0).isReg() && MI->getOperand(0).getReg())
    return true;
  return false;
}

Devang Patel's avatar
Devang Patel committed
/// collectVariableInfo - Populate DbgScope entries with variables' info.
DwarfDebug::collectVariableInfo(const MachineFunction *MF,
                                SmallPtrSet<const MDNode *, 16> &Processed) {
Devang Patel's avatar
Devang Patel committed
  /// collection info from MMI table.
  collectVariableInfoFromMMITable(MF, Processed);
Devang Patel's avatar
Devang Patel committed
  SmallVector<const MachineInstr *, 8> DbgValues;
  // Collect variable information from DBG_VALUE machine instructions;
  for (MachineFunction::const_iterator I = Asm->MF->begin(), E = Asm->MF->end();
Devang Patel's avatar
Devang Patel committed
       I != E; ++I)
    for (MachineBasicBlock::const_iterator II = I->begin(), IE = I->end();
         II != IE; ++II) {
      const MachineInstr *MInsn = II;
      if (!MInsn->isDebugValue())
Devang Patel's avatar
Devang Patel committed
      DbgValues.push_back(MInsn);
    }
  // This is a collection of DBV_VALUE instructions describing same variable.
  SmallVector<const MachineInstr *, 4> MultipleValues;
Devang Patel's avatar
Devang Patel committed
  for(SmallVector<const MachineInstr *, 8>::iterator I = DbgValues.begin(),
        E = DbgValues.end(); I != E; ++I) {
    const MachineInstr *MInsn = *I;
    MultipleValues.clear();
    if (isDbgValueInDefinedReg(MInsn))
      MultipleValues.push_back(MInsn);
Devang Patel's avatar
Devang Patel committed
    DIVariable DV(MInsn->getOperand(MInsn->getNumOperands() - 1).getMetadata());
    if (Processed.count(DV) != 0)
      continue;
    const MachineInstr *PrevMI = MInsn;
    for (SmallVector<const MachineInstr *, 8>::iterator MI = I+1,
           ME = DbgValues.end(); MI != ME; ++MI) {
      const MDNode *Var =
        (*MI)->getOperand((*MI)->getNumOperands()-1).getMetadata();
          !PrevMI->isIdenticalTo(*MI))
        MultipleValues.push_back(*MI);
    if (DV.getTag() == dwarf::DW_TAG_arg_variable &&
        DISubprogram(DV.getContext()).describes(MF->getFunction()))
Devang Patel's avatar
Devang Patel committed
      Scope = CurrentFnDbgScope;
    else
      Scope = findDbgScope(MInsn);
Devang Patel's avatar
Devang Patel committed
    // If variable scope is not found then skip this variable.
Devang Patel's avatar
Devang Patel committed
    if (!Scope)
Devang Patel's avatar
Devang Patel committed
      continue;

    Processed.insert(DV);
    DbgVariable *RegVar = new DbgVariable(DV);
    if (!addCurrentFnArgument(MF, RegVar, Scope))
      Scope->addVariable(RegVar);
Devang Patel's avatar
Devang Patel committed
    if (DbgVariable *AbsVar = findAbstractVariable(DV, MInsn->getDebugLoc())) {
      DbgVariableToDbgInstMap[AbsVar] = MInsn;
      VarToAbstractVarMap[RegVar] = AbsVar;
    if (MultipleValues.size() <= 1) {
      DbgVariableToDbgInstMap[RegVar] = MInsn;
      continue;
    }

    // handle multiple DBG_VALUE instructions describing one variable.
    if (DotDebugLocEntries.empty())
      RegVar->setDotDebugLocOffset(0);
    else
      RegVar->setDotDebugLocOffset(DotDebugLocEntries.size());
    const MachineInstr *Begin = NULL;
    const MachineInstr *End = NULL;
    for (SmallVector<const MachineInstr *, 4>::iterator
           MVI = MultipleValues.begin(), MVE = MultipleValues.end();
Devang Patel's avatar
Devang Patel committed
         MVI != MVE; ++MVI) {
      if (!Begin) {
        Begin = *MVI;
        continue;
      MachineLocation MLoc;
      if (Begin->getNumOperands() == 3) {
        if (Begin->getOperand(0).isReg() && Begin->getOperand(1).isImm())
          MLoc.set(Begin->getOperand(0).getReg(), Begin->getOperand(1).getImm());
      } else
        MLoc = Asm->getDebugValueLocation(Begin);

      const MCSymbol *FLabel = getLabelBeforeInsn(Begin);
      const MCSymbol *SLabel = getLabelBeforeInsn(End);
      if (MLoc.getReg())
        DotDebugLocEntries.push_back(DotDebugLocEntry(FLabel, SLabel, MLoc));

      Begin = End;
      if (MVI + 1 == MVE) {
        // If End is the last instruction then its value is valid
        // until the end of the funtion.
        MachineLocation EMLoc;
        if (End->getNumOperands() == 3) {
          if (End->getOperand(0).isReg() && Begin->getOperand(1).isImm())
          EMLoc.set(Begin->getOperand(0).getReg(), Begin->getOperand(1).getImm());
        } else
          EMLoc = Asm->getDebugValueLocation(End);
        if (EMLoc.getReg()) 
          DotDebugLocEntries.
            push_back(DotDebugLocEntry(SLabel, FunctionEndSym, EMLoc));
      }
    }
    DotDebugLocEntries.push_back(DotDebugLocEntry());

  // Collect info for variables that were optimized out.
  const Function *F = MF->getFunction();
  if (NamedMDNode *NMD = getFnSpecificMDNode(*(F->getParent()), F->getName())) {
    for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) {
      DIVariable DV(cast<MDNode>(NMD->getOperand(i)));
Devang Patel's avatar
Devang Patel committed
      if (!DV || !Processed.insert(DV))
        continue;
      DbgScope *Scope = DbgScopeMap.lookup(DV.getContext());
      if (Scope)
        Scope->addVariable(new DbgVariable(DV));
}

/// getLabelBeforeInsn - Return Label preceding the instruction.
const MCSymbol *DwarfDebug::getLabelBeforeInsn(const MachineInstr *MI) {
  DenseMap<const MachineInstr *, MCSymbol *>::iterator I =
    LabelsBeforeInsn.find(MI);
  if (I == LabelsBeforeInsn.end())
    // FunctionBeginSym always preceeds all the instruction in current function.
    return FunctionBeginSym;
  return I->second;
}
/// getLabelAfterInsn - Return Label immediately following the instruction.
const MCSymbol *DwarfDebug::getLabelAfterInsn(const MachineInstr *MI) {
  DenseMap<const MachineInstr *, MCSymbol *>::iterator I =
    LabelsAfterInsn.find(MI);
  if (I == LabelsAfterInsn.end())
    return NULL;
  return I->second;
/// beginInstruction - Process beginning of an instruction.
void DwarfDebug::beginInstruction(const MachineInstr *MI) {
  if (InsnNeedsLabel.count(MI) == 0) {
    LabelsBeforeInsn[MI] = PrevLabel;
    return;
  }

  // Check location.
  DebugLoc DL = MI->getDebugLoc();
  if (!DL.isUnknown()) {
    const MDNode *Scope = DL.getScope(Asm->MF->getFunction()->getContext());
    PrevLabel = recordSourceLine(DL.getLine(), DL.getCol(), Scope);
    PrevInstLoc = DL;
    LabelsBeforeInsn[MI] = PrevLabel;
  // If location is unknown then use temp label for this DBG_VALUE
  if (MI->isDebugValue()) {
    PrevLabel = MMI->getContext().CreateTempSymbol();
    Asm->OutStreamer.EmitLabel(PrevLabel);
    LabelsBeforeInsn[MI] = PrevLabel;
    return;
  if (UnknownLocations) {
    PrevLabel = recordSourceLine(0, 0, 0);
    LabelsBeforeInsn[MI] = PrevLabel;
    return;
  }

  assert (0 && "Instruction is not processed!");
/// endInstruction - Process end of an instruction.
void DwarfDebug::endInstruction(const MachineInstr *MI) {
  if (InsnsEndScopeSet.count(MI) != 0) {
    // Emit a label if this instruction ends a scope.
    MCSymbol *Label = MMI->getContext().CreateTempSymbol();
    Asm->OutStreamer.EmitLabel(Label);
/// getOrCreateDbgScope - Create DbgScope for the scope.
DbgScope *DwarfDebug::getOrCreateDbgScope(const MDNode *Scope,
Devang Patel's avatar
Devang Patel committed
                                          const MDNode *InlinedAt) {
  if (!InlinedAt) {
    DbgScope *WScope = DbgScopeMap.lookup(Scope);
    if (WScope)
    WScope = new DbgScope(NULL, DIDescriptor(Scope), NULL);
    DbgScopeMap.insert(std::make_pair(Scope, WScope));
    if (DIDescriptor(Scope).isLexicalBlock()) {
      DbgScope *Parent =
        getOrCreateDbgScope(DILexicalBlock(Scope).getContext(), NULL);
      WScope->setParent(Parent);
      Parent->addScope(WScope);
    }

    if (!WScope->getParent()) {
      StringRef SPName = DISubprogram(Scope).getLinkageName();
Stuart Hastings's avatar
Stuart Hastings committed
      // We used to check only for a linkage name, but that fails
      // since we began omitting the linkage name for private
      // functions.  The new way is to check for the name in metadata,
      // but that's not supported in old .ll test cases.  Ergo, we
      // check both.
      if (SPName == Asm->MF->getFunction()->getName() ||
          DISubprogram(Scope).getFunction() == Asm->MF->getFunction())
  getOrCreateAbstractScope(Scope);
  DbgScope *WScope = DbgScopeMap.lookup(InlinedAt);
  if (WScope)

  WScope = new DbgScope(NULL, DIDescriptor(Scope), InlinedAt);
  DbgScopeMap.insert(std::make_pair(InlinedAt, WScope));
  DILocation DL(InlinedAt);
    getOrCreateDbgScope(DL.getScope(), DL.getOrigLocation());
  WScope->setParent(Parent);
  Parent->addScope(WScope);

  ConcreteScopes[InlinedAt] = WScope;

  return WScope;
}

/// hasValidLocation - Return true if debug location entry attached with
/// machine instruction encodes valid location info.
static bool hasValidLocation(LLVMContext &Ctx,
                             const MachineInstr *MInsn,
                             const MDNode *&Scope, const MDNode *&InlinedAt) {
  DebugLoc DL = MInsn->getDebugLoc();
  if (DL.isUnknown()) return false;
  const MDNode *S = DL.getScope(Ctx);
  // There is no need to create another DIE for compile unit. For all
  // other scopes, create one DbgScope now. This will be translated
  // into a scope DIE at the end.
  if (DIScope(S).isCompileUnit()) return false;
  Scope = S;
  InlinedAt = DL.getInlinedAt(Ctx);
  return true;
}

/// calculateDominanceGraph - Calculate dominance graph for DbgScope
/// hierarchy.
static void calculateDominanceGraph(DbgScope *Scope) {
  assert (Scope && "Unable to calculate scop edominance graph!");
  SmallVector<DbgScope *, 4> WorkStack;
  WorkStack.push_back(Scope);
  unsigned Counter = 0;
  while (!WorkStack.empty()) {
    DbgScope *WS = WorkStack.back();
    const SmallVector<DbgScope *, 4> &Children = WS->getScopes();
    bool visitedChildren = false;
    for (SmallVector<DbgScope *, 4>::const_iterator SI = Children.begin(),
           SE = Children.end(); SI != SE; ++SI) {
      DbgScope *ChildScope = *SI;
      if (!ChildScope->getDFSOut()) {
        WorkStack.push_back(ChildScope);
        visitedChildren = true;
        ChildScope->setDFSIn(++Counter);
        break;
      }
    }
    if (!visitedChildren) {
      WorkStack.pop_back();
      WS->setDFSOut(++Counter);
    }
  }
/// printDbgScopeInfo - Print DbgScope info for each machine instruction.
void printDbgScopeInfo(LLVMContext &Ctx, const MachineFunction *MF,
                       DenseMap<const MachineInstr *, DbgScope *> &MI2ScopeMap)
{
#ifndef NDEBUG
  unsigned PrevDFSIn = 0;
  for (MachineFunction::const_iterator I = MF->begin(), E = MF->end();
       I != E; ++I) {
    for (MachineBasicBlock::const_iterator II = I->begin(), IE = I->end();
         II != IE; ++II) {
      const MachineInstr *MInsn = II;
      const MDNode *Scope = NULL;
      const MDNode *InlinedAt = NULL;

      // Check if instruction has valid location information.
      if (hasValidLocation(Ctx, MInsn, Scope, InlinedAt)) {
        dbgs() << " [ ";
        if (InlinedAt)
        DenseMap<const MachineInstr *, DbgScope *>::iterator DI =
          MI2ScopeMap.find(MInsn);
        if (DI != MI2ScopeMap.end()) {
          DbgScope *S = DI->second;
          dbgs() << S->getDFSIn();
          PrevDFSIn = S->getDFSIn();
        } else
          dbgs() << PrevDFSIn;
        dbgs() << " [ x" << PrevDFSIn;
      dbgs() << " ]";
      MInsn->dump();
    }
    dbgs() << "\n";
  }
#endif
}
/// extractScopeInformation - Scan machine instructions in this function
/// and collect DbgScopes. Return true, if at least one scope was found.
bool DwarfDebug::extractScopeInformation() {
  // If scope information was extracted using .dbg intrinsics then there is not
  // any need to extract these information by scanning each instruction.
  if (!DbgScopeMap.empty())
    return false;

  // Scan each instruction and create scopes. First build working set of scopes.
  LLVMContext &Ctx = Asm->MF->getFunction()->getContext();
  SmallVector<DbgRange, 4> MIRanges;
  DenseMap<const MachineInstr *, DbgScope *> MI2ScopeMap;
  const MDNode *PrevScope = NULL;
  const MDNode *PrevInlinedAt = NULL;
  const MachineInstr *RangeBeginMI = NULL;
  const MachineInstr *PrevMI = NULL;
  for (MachineFunction::const_iterator I = Asm->MF->begin(), E = Asm->MF->end();
       I != E; ++I) {
    for (MachineBasicBlock::const_iterator II = I->begin(), IE = I->end();
         II != IE; ++II) {
      const MachineInstr *MInsn = II;
      const MDNode *Scope = NULL;
      const MDNode *InlinedAt = NULL;
Devang Patel's avatar
Devang Patel committed

      // Check if instruction has valid location information.
      if (!hasValidLocation(Ctx, MInsn, Scope, InlinedAt)) {
        PrevMI = MInsn;
        continue;
      }
      // If scope has not changed then skip this instruction.
      if (Scope == PrevScope && PrevInlinedAt == InlinedAt) {
        PrevMI = MInsn;
        continue;
      }
      // Ignore DBG_VALUE. It does not contribute any instruction in output.
      if (MInsn->isDebugValue())
        continue;

      if (RangeBeginMI) {
        // If we have alread seen a beginning of a instruction range and
        // current instruction scope does not match scope of first instruction
        // in this range then create a new instruction range.
        DbgRange R(RangeBeginMI, PrevMI);
        MI2ScopeMap[RangeBeginMI] = getOrCreateDbgScope(PrevScope,
Devang Patel's avatar
Devang Patel committed
                                                        PrevInlinedAt);
      // This is a beginning of a new instruction range.
      RangeBeginMI = MInsn;
      // Reset previous markers.
      PrevMI = MInsn;
      PrevScope = Scope;
      PrevInlinedAt = InlinedAt;
  // Create last instruction range.
  if (RangeBeginMI && PrevMI && PrevScope) {
    DbgRange R(RangeBeginMI, PrevMI);
    MIRanges.push_back(R);
    MI2ScopeMap[RangeBeginMI] = getOrCreateDbgScope(PrevScope, PrevInlinedAt);
  }
  if (!CurrentFnDbgScope)
    return false;

  calculateDominanceGraph(CurrentFnDbgScope);
  if (PrintDbgScope)
    printDbgScopeInfo(Ctx, Asm->MF, MI2ScopeMap);

  // Find ranges of instructions covered by each DbgScope;
  DbgScope *PrevDbgScope = NULL;
  for (SmallVector<DbgRange, 4>::const_iterator RI = MIRanges.begin(),
         RE = MIRanges.end(); RI != RE; ++RI) {
    const DbgRange &R = *RI;
    DbgScope *S = MI2ScopeMap.lookup(R.first);
    assert (S && "Lost DbgScope for a machine instruction!");
    if (PrevDbgScope && !PrevDbgScope->dominates(S))
      PrevDbgScope->closeInsnRange(S);
    S->openInsnRange(R.first);
    S->extendInsnRange(R.second);
    PrevDbgScope = S;
  }

  if (PrevDbgScope)
    PrevDbgScope->closeInsnRange();
Devang Patel's avatar
Devang Patel committed
  identifyScopeMarkers();
Devang Patel's avatar
Devang Patel committed

  return !DbgScopeMap.empty();
}

/// identifyScopeMarkers() -
/// Each DbgScope has first instruction and last instruction to mark beginning
/// and end of a scope respectively. Create an inverse map that list scopes
/// starts (and ends) with an instruction. One instruction may start (or end)
/// multiple scopes. Ignore scopes that are not reachable.
Devang Patel's avatar
Devang Patel committed
void DwarfDebug::identifyScopeMarkers() {
  SmallVector<DbgScope *, 4> WorkList;
  WorkList.push_back(CurrentFnDbgScope);
  while (!WorkList.empty()) {
    DbgScope *S = WorkList.pop_back_val();
    const SmallVector<DbgScope *, 4> &Children = S->getScopes();
    if (!Children.empty())
      for (SmallVector<DbgScope *, 4>::const_iterator SI = Children.begin(),
             SE = Children.end(); SI != SE; ++SI)
        WorkList.push_back(*SI);

    if (S->isAbstractScope())
      continue;
    const SmallVector<DbgRange, 4> &Ranges = S->getRanges();
    if (Ranges.empty())
      continue;
    for (SmallVector<DbgRange, 4>::const_iterator RI = Ranges.begin(),
           RE = Ranges.end(); RI != RE; ++RI) {
      assert(RI->first && "DbgRange does not have first instruction!");
      assert(RI->second && "DbgRange does not have second instruction!");
/// FindFirstDebugLoc - Find the first debug location in the function. This
/// is intended to be an approximation for the source position of the
/// beginning of the function.
static DebugLoc FindFirstDebugLoc(const MachineFunction *MF) {
  for (MachineFunction::const_iterator I = MF->begin(), E = MF->end();
       I != E; ++I)
    for (MachineBasicBlock::const_iterator MBBI = I->begin(), MBBE = I->end();
         MBBI != MBBE; ++MBBI) {
      DebugLoc DL = MBBI->getDebugLoc();
      if (!DL.isUnknown())
        return DL;
    }
  return DebugLoc();
}

#ifndef NDEBUG
/// CheckLineNumbers - Count basicblocks whose instructions do not have any
/// line number information.
static void CheckLineNumbers(const MachineFunction *MF) {
  for (MachineFunction::const_iterator I = MF->begin(), E = MF->end();
       I != E; ++I) {
    bool FoundLineNo = false;
    for (MachineBasicBlock::const_iterator II = I->begin(), IE = I->end();
         II != IE; ++II) {
      const MachineInstr *MI = II;
      if (!MI->getDebugLoc().isUnknown()) {
        FoundLineNo = true;
        break;
      }
    }
Devang Patel's avatar
Devang Patel committed
    if (!FoundLineNo && I->size())
/// beginFunction - Gather pre-function debug information.  Assumes being
/// emitted immediately after the function entry point.
void DwarfDebug::beginFunction(const MachineFunction *MF) {
  if (!extractScopeInformation()) return;
  FunctionBeginSym = Asm->GetTempSymbol("func_begin",
                                        Asm->getFunctionNumber());
  // Assumes in correct section after the entry point.
  Asm->OutStreamer.EmitLabel(FunctionBeginSym);

  // Emit label for the implicitly defined dbg.stoppoint at the start of the
  // function.
  DebugLoc FDL = FindFirstDebugLoc(MF);
  const MDNode *Scope = FDL.getScope(MF->getFunction()->getContext());
  DISubprogram SP = getDISubprogram(Scope);
  unsigned Line, Col;
  if (SP.Verify()) {
    Line = SP.getLineNumber();
    Col = 0;
  } else {
    Line = FDL.getLine();
    Col = FDL.getCol();
  recordSourceLine(Line, Col, TheScope);
Devang Patel's avatar
 
Devang Patel committed
  /// ProcessedArgs - Collection of arguments already processed.
  SmallPtrSet<const MDNode *, 8> ProcessedArgs;

  DebugLoc PrevLoc;
  for (MachineFunction::const_iterator I = MF->begin(), E = MF->end();
       I != E; ++I)
    for (MachineBasicBlock::const_iterator II = I->begin(), IE = I->end();
         II != IE; ++II) {
      const MachineInstr *MI = II;
      DebugLoc DL = MI->getDebugLoc();
      if (MI->isDebugValue()) {
        assert (MI->getNumOperands() > 1 && "Invalid machine instruction!");
        DIVariable DV(MI->getOperand(MI->getNumOperands() - 1).getMetadata());
        if (!DV.Verify()) continue;
        // If DBG_VALUE is for a local variable then it needs a label.
        if (DV.getTag() != dwarf::DW_TAG_arg_variable)
        // DBG_VALUE for inlined functions argument needs a label.
        else if (!DISubprogram(getDISubprogram(DV.getContext())).
                 describes(MF->getFunction()))
          InsnNeedsLabel.insert(MI);
        // DBG_VALUE indicating argument location change needs a label.
        // If location is unknown then instruction needs a location only if
        // UnknownLocations flag is set.
        if (DL.isUnknown()) {
          if (UnknownLocations && !PrevLoc.isUnknown())
            InsnNeedsLabel.insert(MI);
        } else if (DL != PrevLoc)
          // Otherwise, instruction needs a location only if it is new location.
          InsnNeedsLabel.insert(MI);
      }
      if (!DL.isUnknown() || UnknownLocations)
        PrevLoc = DL;
    }

  PrevLabel = FunctionBeginSym;
/// endFunction - Gather and emit post-function debug information.
void DwarfDebug::endFunction(const MachineFunction *MF) {
  if (!MMI->hasDebugInfo() || DbgScopeMap.empty()) return;
  if (CurrentFnDbgScope) {
    // Define end label for subprogram.
    FunctionEndSym = Asm->GetTempSymbol("func_end",
                                        Asm->getFunctionNumber());
    // Assumes in correct section after the entry point.
    Asm->OutStreamer.EmitLabel(FunctionEndSym);
    SmallPtrSet<const MDNode *, 16> ProcessedVars;
    collectVariableInfo(MF, ProcessedVars);
    // Construct abstract scopes.
    for (SmallVector<DbgScope *, 4>::iterator AI = AbstractScopesList.begin(),
           AE = AbstractScopesList.end(); AI != AE; ++AI) {
      DISubprogram SP((*AI)->getScopeNode());
      if (SP.Verify()) {
        // Collect info for variables that were optimized out.
        StringRef FName = SP.getLinkageName();
        if (FName.empty())
          FName = SP.getName();
        if (NamedMDNode *NMD = 
            getFnSpecificMDNode(*(MF->getFunction()->getParent()), FName)) {
          for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) {
          DIVariable DV(cast<MDNode>(NMD->getOperand(i)));
          if (!DV || !ProcessedVars.insert(DV))
            continue;
          DbgScope *Scope = AbstractScopes.lookup(DV.getContext());
          if (Scope)
            Scope->addVariable(new DbgVariable(DV));
          }
        }
      }
      if (ProcessedSPNodes.count((*AI)->getScopeNode()) == 0)
        constructScopeDIE(*AI);
Devang Patel's avatar
Devang Patel committed

    DIE *CurFnDIE = constructScopeDIE(CurrentFnDbgScope);
      addUInt(CurFnDIE, dwarf::DW_AT_APPLE_omit_frame_ptr,