Index: include/llvm/CodeGen/AsmPrinter.h =================================================================== --- include/llvm/CodeGen/AsmPrinter.h +++ include/llvm/CodeGen/AsmPrinter.h @@ -22,6 +22,7 @@ #include "llvm/Support/ErrorHandling.h" namespace llvm { + class AsmPrinterObserver; class BlockAddress; class GCStrategy; class Constant; @@ -110,12 +111,21 @@ /// function. MachineLoopInfo *LI; - /// DD - If the target supports dwarf debug info, this pointer is non-null. - DwarfDebug *DD; - - /// DE - If the target supports dwarf exception info, this pointer is - /// non-null. - DwarfException *DE; + struct ObserverInfo { + AsmPrinterObserver *Observer; + const char *TimerName, *TimerGroupName; + ObserverInfo(AsmPrinterObserver *Observer, const char *TimerName, + const char *TimerGroupName) + : Observer(Observer), TimerName(TimerName), + TimerGroupName(TimerGroupName) {} + }; + /// Observers - a vector of all debug/EH info emitters we should use. + /// This vector maintains ownership of the emitters. + SmallVector Observers; + + /// DwarfVersion - If the target supports dwarf debug info, holds the Dwarf + /// Version. Otherwise, zero. + unsigned DwarfVersion; protected: explicit AsmPrinter(TargetMachine &TM, MCStreamer &Streamer); @@ -123,7 +133,8 @@ public: virtual ~AsmPrinter(); - const DwarfDebug *getDwarfDebug() const { return DD; } + /// Returns the Dwarf Version or zero. + unsigned getDwarfVersion() const { return DwarfVersion; } /// isVerbose - Return true if assembly output should contain comments. /// Index: lib/CodeGen/AsmPrinter/AsmPrinter.cpp =================================================================== --- lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -99,14 +99,15 @@ OutContext(Streamer.getContext()), OutStreamer(Streamer), LastMI(0), LastFn(0), Counter(~0U), SetCounter(0) { - DD = 0; DE = 0; MMI = 0; LI = 0; MF = 0; + MMI = 0; LI = 0; MF = 0; + DwarfVersion = 0; CurrentFnSym = CurrentFnSymForSize = 0; GCMetadataPrinters = 0; VerboseAsm = Streamer.isVerboseAsm(); } AsmPrinter::~AsmPrinter() { - assert(DD == 0 && DE == 0 && "Debug/EH info didn't get finalized"); + assert(Observers.empty() && "Debug/EH info didn't get finalized"); if (GCMetadataPrinters != 0) { gcp_map_type &GCMap = getGCMap(GCMetadataPrinters); @@ -192,25 +193,30 @@ OutStreamer.AddBlankLine(); } - if (MAI->doesSupportDebugInformation()) - DD = new DwarfDebug(this, &M); + if (MAI->doesSupportDebugInformation()) { + DwarfDebug *DD = new DwarfDebug(this, &M); + DwarfVersion = DD->getDwarfVersion(); + Observers.push_back(ObserverInfo(DD, DbgTimerName, DWARFGroupName)); + } + DwarfException *DE = 0; switch (MAI->getExceptionHandlingType()) { case ExceptionHandling::None: - return false; + break; case ExceptionHandling::SjLj: case ExceptionHandling::DwarfCFI: DE = new DwarfCFIException(this); - return false; + break; case ExceptionHandling::ARM: DE = new ARMException(this); - return false; + break; case ExceptionHandling::Win64: DE = new Win64Exception(this); - return false; + break; } - - llvm_unreachable("Unknown exception type."); + if (DE) + Observers.push_back(ObserverInfo(DE, EHTimerName, DWARFGroupName)); + return false; } void AsmPrinter::EmitLinkage(const GlobalValue *GV, MCSymbol *GVSym) const { @@ -311,8 +317,11 @@ // sections and expected to be contiguous (e.g. ObjC metadata). unsigned AlignLog = getGVAlignmentLog2(GV, *DL); - if (DD) - DD->setSymbolSize(GVSym, Size); + for (unsigned I = 0, E = Observers.size(); I != E; ++I) { + const ObserverInfo &OI = Observers[I]; + NamedRegionTimer T(OI.TimerName, OI.TimerGroupName, TimePassesIsEnabled); + OI.Observer->setSymbolSize(GVSym, Size); + } // Handle common and BSS local symbols (.lcomm). if (GVKind.isCommon() || GVKind.isBSSLocal()) { @@ -482,13 +491,10 @@ } // Emit pre-function debug and/or EH information. - if (DE) { - NamedRegionTimer T(EHTimerName, DWARFGroupName, TimePassesIsEnabled); - DE->beginFunction(MF); - } - if (DD) { - NamedRegionTimer T(DbgTimerName, DWARFGroupName, TimePassesIsEnabled); - DD->beginFunction(MF); + for (unsigned I = 0, E = Observers.size(); I != E; ++I) { + const ObserverInfo &OI = Observers[I]; + NamedRegionTimer T(OI.TimerName, OI.TimerGroupName, TimePassesIsEnabled); + OI.Observer->beginFunction(MF); } // Emit the prefix data. @@ -693,7 +699,7 @@ // Emit target-specific gunk before the function body. EmitFunctionBodyStart(); - bool ShouldPrintDebugScopes = DD && MMI->hasDebugInfo(); + bool ShouldPrintDebugScopes = MMI->hasDebugInfo(); // Print out code for the function. bool HasAnyRealCode = false; @@ -714,8 +720,12 @@ } if (ShouldPrintDebugScopes) { - NamedRegionTimer T(DbgTimerName, DWARFGroupName, TimePassesIsEnabled); - DD->beginInstruction(II); + for (unsigned III = 0, EEE = Observers.size(); III != EEE; ++III) { + const ObserverInfo &OI = Observers[III]; + NamedRegionTimer T(OI.TimerName, OI.TimerGroupName, + TimePassesIsEnabled); + OI.Observer->beginInstruction(II); + } } if (isVerbose()) @@ -754,8 +764,12 @@ } if (ShouldPrintDebugScopes) { - NamedRegionTimer T(DbgTimerName, DWARFGroupName, TimePassesIsEnabled); - DD->endInstruction(II); + for (unsigned III = 0, EEE = Observers.size(); III != EEE; ++III) { + const ObserverInfo &OI = Observers[III]; + NamedRegionTimer T(OI.TimerName, OI.TimerGroupName, + TimePassesIsEnabled); + OI.Observer->endInstruction(II); + } } } } @@ -811,14 +825,12 @@ OutStreamer.EmitELFSize(CurrentFnSym, SizeExp); } - // Emit post-function debug information. - if (DD) { - NamedRegionTimer T(DbgTimerName, DWARFGroupName, TimePassesIsEnabled); - DD->endFunction(MF); - } - if (DE) { - NamedRegionTimer T(EHTimerName, DWARFGroupName, TimePassesIsEnabled); - DE->endFunction(); + // Emit post-function debug and/or EH information. + for (unsigned I = 0, E = Observers.size(); I != E; ++I) { + const ObserverInfo &OI = Observers[I]; + NamedRegionTimer T(OI.TimerName, OI.TimerGroupName, + TimePassesIsEnabled); + OI.Observer->endFunction(); } MMI->EndFunction(); @@ -907,20 +919,14 @@ OutStreamer.Flush(); // Finalize debug and EH information. - if (DE) { - { - NamedRegionTimer T(EHTimerName, DWARFGroupName, TimePassesIsEnabled); - DE->endModule(); - } - delete DE; DE = 0; - } - if (DD) { - { - NamedRegionTimer T(DbgTimerName, DWARFGroupName, TimePassesIsEnabled); - DD->endModule(); - } - delete DD; DD = 0; + for (unsigned I = 0, E = Observers.size(); I != E; ++I) { + const ObserverInfo &OI = Observers[I]; + NamedRegionTimer T(OI.TimerName, OI.TimerGroupName, + TimePassesIsEnabled); + OI.Observer->endModule(); + delete OI.Observer; } + Observers.clear(); // If the target wants to know about weak references, print them all. if (MAI->getWeakRefDirective()) { Index: lib/CodeGen/AsmPrinter/AsmPrinterObserver.h =================================================================== --- lib/CodeGen/AsmPrinter/AsmPrinterObserver.h +++ lib/CodeGen/AsmPrinter/AsmPrinterObserver.h @@ -0,0 +1,53 @@ +//===-- lib/CodeGen/AsmPrinter/AsmPrinterObserver.h ------------*- C++ -*--===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains a generic interface for AsmPrinter observers, +// like debug and EH info emitters. +// +//===----------------------------------------------------------------------===// + +#ifndef CODEGEN_ASMPRINTER_ASMPRINTEROBSERVER_H__ +#define CODEGEN_ASMPRINTER_ASMPRINTEROBSERVER_H__ + +#include + +namespace llvm { + +class MachineFunction; +class MachineInstr; +class MCSymbol; + +/// \brief Collects and handles AsmPrinter objects required to build debug +/// or EH information. +class AsmPrinterObserver { +public: + virtual ~AsmPrinterObserver() {} + + /// \brief For symbols that have a size designated (e.g. common symbols), + /// this tracks that size. + virtual void setSymbolSize(const MCSymbol *Sym, uint64_t Size) = 0; + + /// \brief Emit all sections that should come after the content. + virtual void endModule() = 0; + + /// \brief Gather pre-function debug information. + virtual void beginFunction(const MachineFunction *MF) = 0; + + /// \brief Gather post-function debug information. + virtual void endFunction() = 0; + + /// \brief Process beginning of an instruction. + virtual void beginInstruction(const MachineInstr *MI) = 0; + + /// \brief Process end of an instruction. + virtual void endInstruction(const MachineInstr *MI) = 0; +}; +} // End of namespace llvm + +#endif Index: lib/CodeGen/AsmPrinter/DIE.cpp =================================================================== --- lib/CodeGen/AsmPrinter/DIE.cpp +++ lib/CodeGen/AsmPrinter/DIE.cpp @@ -390,7 +390,9 @@ // specified to be four bytes in the DWARF 32-bit format and eight bytes // in the DWARF 64-bit format, while DWARF Version 2 specifies that such // references have the same size as an address on the target system. - if (AP->getDwarfDebug()->getDwarfVersion() == 2) + unsigned DwarfVersion = AP->getDwarfVersion(); + assert(DwarfVersion && "Expected Dwarf Debug info to be available"); + if (DwarfVersion == 2) return AP->getDataLayout().getPointerSize(); return sizeof(int32_t); } Index: lib/CodeGen/AsmPrinter/DwarfDebug.h =================================================================== --- lib/CodeGen/AsmPrinter/DwarfDebug.h +++ lib/CodeGen/AsmPrinter/DwarfDebug.h @@ -14,6 +14,7 @@ #ifndef CODEGEN_ASMPRINTER_DWARFDEBUG_H__ #define CODEGEN_ASMPRINTER_DWARFDEBUG_H__ +#include "AsmPrinterObserver.h" #include "DIE.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/FoldingSet.h" @@ -313,7 +314,7 @@ }; /// \brief Collects and handles dwarf debug information. -class DwarfDebug { +class DwarfDebug : public AsmPrinterObserver { // Target of Dwarf emission. AsmPrinter *Asm; @@ -417,6 +418,9 @@ // body. DebugLoc PrologEndLoc; + // If nonnull, stores the current machine function we're processing. + const MachineFunction *CurFn; + // Section Symbols: these are assembler temporary labels that are emitted at // the beginning of each supported dwarf section. These are used to form // section offsets and are created by EmitSectionLabels. @@ -637,17 +641,14 @@ /// \brief If Var is an current function argument that add it in /// CurrentFnArguments list. - bool addCurrentFnArgument(const MachineFunction *MF, - DbgVariable *Var, LexicalScope *Scope); + bool addCurrentFnArgument(DbgVariable *Var, LexicalScope *Scope); /// \brief Populate LexicalScope entries with variables' info. - void collectVariableInfo(const MachineFunction *, - SmallPtrSet &ProcessedVars); + void collectVariableInfo(SmallPtrSet &ProcessedVars); /// \brief Collect variable information from the side table maintained /// by MMI. - void collectVariableInfoFromMMITable(const MachineFunction * MF, - SmallPtrSet &P); + void collectVariableInfoFromMMITable(SmallPtrSet &P); /// \brief Ensure that a label will be emitted before MI. void requestLabelBeforeInsn(const MachineInstr *MI) { @@ -689,7 +690,7 @@ void beginFunction(const MachineFunction *MF); /// \brief Gather and emit post-function debug information. - void endFunction(const MachineFunction *MF); + void endFunction(); /// \brief Process beginning of an instruction. void beginInstruction(const MachineInstr *MI); Index: lib/CodeGen/AsmPrinter/DwarfDebug.cpp =================================================================== --- lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -197,6 +197,7 @@ DwarfAddrSectionSym = 0; DwarfAbbrevDWOSectionSym = DwarfStrDWOSectionSym = 0; FunctionBeginSym = FunctionEndSym = 0; + CurFn = 0; // Turn on accelerator tables for Darwin by default, pubnames by // default for non-Darwin, and handle split dwarf. @@ -1149,6 +1150,7 @@ // Emit all Dwarf sections that should come after the content. void DwarfDebug::endModule() { + assert(CurFn == 0); if (!FirstCU) return; @@ -1230,8 +1232,7 @@ } // If Var is a current function argument then add it to CurrentFnArguments list. -bool DwarfDebug::addCurrentFnArgument(const MachineFunction *MF, - DbgVariable *Var, LexicalScope *Scope) { +bool DwarfDebug::addCurrentFnArgument(DbgVariable *Var, LexicalScope *Scope) { if (!LScopes.isCurrentFunctionScope(Scope)) return false; DIVariable DV = Var->getVariable(); @@ -1243,7 +1244,7 @@ size_t Size = CurrentFnArguments.size(); if (Size == 0) - CurrentFnArguments.resize(MF->getFunction()->arg_size()); + CurrentFnArguments.resize(CurFn->getFunction()->arg_size()); // llvm::Function argument size is not good indicator of how many // arguments does the function have at source level. if (ArgNo > Size) @@ -1254,7 +1255,7 @@ // Collect variable information from side table maintained by MMI. void DwarfDebug::collectVariableInfoFromMMITable( - const MachineFunction *MF, SmallPtrSet &Processed) { + SmallPtrSet &Processed) { MachineModuleInfo::VariableDbgInfoMapTy &VMap = MMI->getVariableDbgInfo(); for (MachineModuleInfo::VariableDbgInfoMapTy::iterator VI = VMap.begin(), VE = VMap.end(); @@ -1275,7 +1276,7 @@ DbgVariable *AbsDbgVariable = findAbstractVariable(DV, VP.second); DbgVariable *RegVar = new DbgVariable(DV, AbsDbgVariable, this); RegVar->setFrameIndex(VP.first); - if (!addCurrentFnArgument(MF, RegVar, Scope)) + if (!addCurrentFnArgument(RegVar, Scope)) addScopeVariable(Scope, RegVar); if (AbsDbgVariable) AbsDbgVariable->setFrameIndex(VP.first); @@ -1322,11 +1323,10 @@ // Find variables for each lexical scope. void -DwarfDebug::collectVariableInfo(const MachineFunction *MF, - SmallPtrSet &Processed) { +DwarfDebug::collectVariableInfo(SmallPtrSet &Processed) { // Grab the variable info that was squirreled away in the MMI side-table. - collectVariableInfoFromMMITable(MF, Processed); + collectVariableInfoFromMMITable(Processed); for (SmallVectorImpl::const_iterator UVI = UserVariables.begin(), @@ -1346,7 +1346,7 @@ DIVariable DV(Var); LexicalScope *Scope = NULL; if (DV.getTag() == dwarf::DW_TAG_arg_variable && - DISubprogram(DV.getContext()).describes(MF->getFunction())) + DISubprogram(DV.getContext()).describes(CurFn->getFunction())) Scope = LScopes.getCurrentFunctionScope(); else if (MDNode *IA = DV.getInlinedAt()) Scope = LScopes.findInlinedScope(DebugLoc::getFromDILocation(IA)); @@ -1360,7 +1360,7 @@ assert(MInsn->isDebugValue() && "History must begin with debug value"); DbgVariable *AbsVar = findAbstractVariable(DV, MInsn->getDebugLoc()); DbgVariable *RegVar = new DbgVariable(DV, AbsVar, this); - if (!addCurrentFnArgument(MF, RegVar, Scope)) + if (!addCurrentFnArgument(RegVar, Scope)) addScopeVariable(Scope, RegVar); if (AbsVar) AbsVar->setMInsn(MInsn); @@ -1570,6 +1570,7 @@ // Gather pre-function debug information. Assumes being called immediately // after the function entry point has been emitted. void DwarfDebug::beginFunction(const MachineFunction *MF) { + CurFn = MF; // If there's no debug info for the function we're not going to do anything. if (!MMI->hasDebugInfo()) @@ -1796,9 +1797,13 @@ } // Gather and emit post-function debug information. -void DwarfDebug::endFunction(const MachineFunction *MF) { - if (!MMI->hasDebugInfo() || LScopes.empty()) +void DwarfDebug::endFunction() { + assert(CurFn != 0); + + if (!MMI->hasDebugInfo() || LScopes.empty()) { + CurFn = 0; return; + } // Define end label for subprogram. FunctionEndSym = Asm->GetTempSymbol("func_end", Asm->getFunctionNumber()); @@ -1808,7 +1813,7 @@ Asm->OutStreamer.getContext().setDwarfCompileUnitID(0); SmallPtrSet ProcessedVars; - collectVariableInfo(MF, ProcessedVars); + collectVariableInfo(ProcessedVars); LexicalScope *FnScope = LScopes.getCurrentFunctionScope(); CompileUnit *TheCU = SPMap.lookup(FnScope->getScopeNode()); @@ -1842,7 +1847,7 @@ DIE *CurFnDIE = constructScopeDIE(TheCU, FnScope); - if (!MF->getTarget().Options.DisableFramePointerElim(*MF)) + if (!CurFn->getTarget().Options.DisableFramePointerElim(*CurFn)) TheCU->addFlag(CurFnDIE, dwarf::DW_AT_APPLE_omit_frame_ptr); // Clear debug info @@ -1858,6 +1863,7 @@ LabelsBeforeInsn.clear(); LabelsAfterInsn.clear(); PrevLabel = NULL; + CurFn = 0; } // Register a source line with debug info. Returns the unique label that was Index: lib/CodeGen/AsmPrinter/DwarfException.h =================================================================== --- lib/CodeGen/AsmPrinter/DwarfException.h +++ lib/CodeGen/AsmPrinter/DwarfException.h @@ -14,6 +14,7 @@ #ifndef LLVM_CODEGEN_ASMPRINTER_DWARFEXCEPTION_H #define LLVM_CODEGEN_ASMPRINTER_DWARFEXCEPTION_H +#include "AsmPrinterObserver.h" #include "llvm/ADT/DenseMap.h" #include "llvm/CodeGen/AsmPrinter.h" #include @@ -35,7 +36,7 @@ //===----------------------------------------------------------------------===// /// DwarfException - Emits Dwarf exception handling directives. /// -class DwarfException { +class DwarfException : public AsmPrinterObserver { protected: /// Asm - Target of Dwarf emission. AsmPrinter *Asm; @@ -140,6 +141,11 @@ /// endFunction - Gather and emit post-function exception information. virtual void endFunction(); + + // We don't need these. + virtual void setSymbolSize(const MCSymbol *Sym, uint64_t Size) {} + virtual void beginInstruction(const MachineInstr *MI) {} + virtual void endInstruction(const MachineInstr *MI) {} }; class DwarfCFIException : public DwarfException {