diff options
Diffstat (limited to 'lib/CodeGen/AsmPrinter')
| -rw-r--r-- | lib/CodeGen/AsmPrinter/ARMException.cpp | 85 | ||||
| -rw-r--r-- | lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 156 | ||||
| -rw-r--r-- | lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp | 50 | ||||
| -rw-r--r-- | lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp | 255 | ||||
| -rw-r--r-- | lib/CodeGen/AsmPrinter/DIE.cpp | 15 | ||||
| -rw-r--r-- | lib/CodeGen/AsmPrinter/DIE.h | 14 | ||||
| -rw-r--r-- | lib/CodeGen/AsmPrinter/DwarfAccelTable.cpp | 20 | ||||
| -rw-r--r-- | lib/CodeGen/AsmPrinter/DwarfAccelTable.h | 36 | ||||
| -rw-r--r-- | lib/CodeGen/AsmPrinter/DwarfCFIException.cpp | 25 | ||||
| -rw-r--r-- | lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp | 217 | ||||
| -rw-r--r-- | lib/CodeGen/AsmPrinter/DwarfCompileUnit.h | 45 | ||||
| -rw-r--r-- | lib/CodeGen/AsmPrinter/DwarfDebug.cpp | 1019 | ||||
| -rw-r--r-- | lib/CodeGen/AsmPrinter/DwarfDebug.h | 489 | ||||
| -rw-r--r-- | lib/CodeGen/AsmPrinter/DwarfException.cpp | 40 | ||||
| -rw-r--r-- | lib/CodeGen/AsmPrinter/DwarfException.h | 3 | ||||
| -rw-r--r-- | lib/CodeGen/AsmPrinter/OcamlGCPrinter.cpp | 14 | ||||
| -rw-r--r-- | lib/CodeGen/AsmPrinter/Win64Exception.cpp | 18 |
17 files changed, 1549 insertions, 952 deletions
diff --git a/lib/CodeGen/AsmPrinter/ARMException.cpp b/lib/CodeGen/AsmPrinter/ARMException.cpp index bf5d8c4..1728331 100644 --- a/lib/CodeGen/AsmPrinter/ARMException.cpp +++ b/lib/CodeGen/AsmPrinter/ARMException.cpp @@ -12,29 +12,29 @@ //===----------------------------------------------------------------------===// #include "DwarfException.h" -#include "llvm/Module.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/Twine.h" #include "llvm/CodeGen/AsmPrinter.h" -#include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/IR/Module.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCSection.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSymbol.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Dwarf.h" +#include "llvm/Support/FormattedStream.h" #include "llvm/Target/Mangler.h" -#include "llvm/Target/TargetData.h" #include "llvm/Target/TargetFrameLowering.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetOptions.h" #include "llvm/Target/TargetRegisterInfo.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/Dwarf.h" -#include "llvm/Support/FormattedStream.h" -#include "llvm/ADT/SmallString.h" -#include "llvm/ADT/StringExtras.h" -#include "llvm/ADT/Twine.h" using namespace llvm; cl::opt<bool> @@ -69,24 +69,69 @@ void ARMException::EndFunction() { Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("eh_func_end", Asm->getFunctionNumber())); - // Emit references to personality. - if (const Function * Personality = - MMI->getPersonalities()[MMI->getPersonalityIndex()]) { - MCSymbol *PerSym = Asm->Mang->getSymbol(Personality); - Asm->OutStreamer.EmitSymbolAttribute(PerSym, MCSA_Global); - Asm->OutStreamer.EmitPersonality(PerSym); - } - if (EnableARMEHABIDescriptors) { // Map all labels and get rid of any dead landing pads. MMI->TidyLandingPads(); - Asm->OutStreamer.EmitHandlerData(); + if (!MMI->getLandingPads().empty()) { + // Emit references to personality. + if (const Function * Personality = + MMI->getPersonalities()[MMI->getPersonalityIndex()]) { + MCSymbol *PerSym = Asm->Mang->getSymbol(Personality); + Asm->OutStreamer.EmitSymbolAttribute(PerSym, MCSA_Global); + Asm->OutStreamer.EmitPersonality(PerSym); + } + + // Emit .handlerdata directive. + Asm->OutStreamer.EmitHandlerData(); - // Emit actual exception table - EmitExceptionTable(); + // Emit actual exception table + EmitExceptionTable(); + } } } Asm->OutStreamer.EmitFnEnd(); } + +void ARMException::EmitTypeInfos(unsigned TTypeEncoding) { + const std::vector<const GlobalVariable *> &TypeInfos = MMI->getTypeInfos(); + const std::vector<unsigned> &FilterIds = MMI->getFilterIds(); + + bool VerboseAsm = Asm->OutStreamer.isVerboseAsm(); + + int Entry = 0; + // Emit the Catch TypeInfos. + if (VerboseAsm && !TypeInfos.empty()) { + Asm->OutStreamer.AddComment(">> Catch TypeInfos <<"); + Asm->OutStreamer.AddBlankLine(); + Entry = TypeInfos.size(); + } + + for (std::vector<const GlobalVariable *>::const_reverse_iterator + I = TypeInfos.rbegin(), E = TypeInfos.rend(); I != E; ++I) { + const GlobalVariable *GV = *I; + if (VerboseAsm) + Asm->OutStreamer.AddComment("TypeInfo " + Twine(Entry--)); + Asm->EmitTTypeReference(GV, TTypeEncoding); + } + + // Emit the Exception Specifications. + if (VerboseAsm && !FilterIds.empty()) { + Asm->OutStreamer.AddComment(">> Filter TypeInfos <<"); + Asm->OutStreamer.AddBlankLine(); + Entry = 0; + } + for (std::vector<unsigned>::const_iterator + I = FilterIds.begin(), E = FilterIds.end(); I < E; ++I) { + unsigned TypeID = *I; + if (VerboseAsm) { + --Entry; + if (TypeID != 0) + Asm->OutStreamer.AddComment("FilterInfo " + Twine(Entry)); + } + + Asm->EmitTTypeReference((TypeID == 0 ? 0 : TypeInfos[TypeID - 1]), + TTypeEncoding); + } +} diff --git a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index b30b427..cbcc290 100644 --- a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -15,8 +15,10 @@ #include "llvm/CodeGen/AsmPrinter.h" #include "DwarfDebug.h" #include "DwarfException.h" -#include "llvm/DebugInfo.h" -#include "llvm/Module.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/Analysis/ConstantFolding.h" +#include "llvm/Assembly/Writer.h" #include "llvm/CodeGen/GCMetadataPrinter.h" #include "llvm/CodeGen/MachineConstantPool.h" #include "llvm/CodeGen/MachineFrameInfo.h" @@ -24,7 +26,10 @@ #include "llvm/CodeGen/MachineJumpTableInfo.h" #include "llvm/CodeGen/MachineLoopInfo.h" #include "llvm/CodeGen/MachineModuleInfo.h" -#include "llvm/Analysis/ConstantFolding.h" +#include "llvm/DebugInfo.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/Operator.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCExpr.h" @@ -32,21 +37,16 @@ #include "llvm/MC/MCSection.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSymbol.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/Format.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Support/Timer.h" #include "llvm/Target/Mangler.h" -#include "llvm/Target/TargetData.h" #include "llvm/Target/TargetInstrInfo.h" #include "llvm/Target/TargetLowering.h" #include "llvm/Target/TargetLoweringObjectFile.h" #include "llvm/Target/TargetOptions.h" #include "llvm/Target/TargetRegisterInfo.h" -#include "llvm/Assembly/Writer.h" -#include "llvm/ADT/SmallString.h" -#include "llvm/ADT/Statistic.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/Format.h" -#include "llvm/Support/MathExtras.h" -#include "llvm/Support/Timer.h" -#include <ctype.h> using namespace llvm; static const char *DWARFGroupName = "DWARF Emission"; @@ -68,7 +68,7 @@ static gcp_map_type &getGCMap(void *&P) { /// getGVAlignmentLog2 - Return the alignment to use for the specified global /// value in log2 form. This rounds up to the preferred alignment if possible /// and legal. -static unsigned getGVAlignmentLog2(const GlobalValue *GV, const TargetData &TD, +static unsigned getGVAlignmentLog2(const GlobalValue *GV, const DataLayout &TD, unsigned InBits = 0) { unsigned NumBits = 0; if (const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV)) @@ -91,9 +91,6 @@ static unsigned getGVAlignmentLog2(const GlobalValue *GV, const TargetData &TD, return NumBits; } - - - AsmPrinter::AsmPrinter(TargetMachine &tm, MCStreamer &Streamer) : MachineFunctionPass(ID), TM(tm), MAI(tm.getMCAsmInfo()), @@ -131,10 +128,9 @@ const TargetLoweringObjectFile &AsmPrinter::getObjFileLowering() const { return TM.getTargetLowering()->getObjFileLowering(); } - -/// getTargetData - Return information about data layout. -const TargetData &AsmPrinter::getTargetData() const { - return *TM.getTargetData(); +/// getDataLayout - Return information about data layout. +const DataLayout &AsmPrinter::getDataLayout() const { + return *TM.getDataLayout(); } /// getCurrentSection() - Return the current section we are emitting to. @@ -154,6 +150,8 @@ void AsmPrinter::getAnalysisUsage(AnalysisUsage &AU) const { } bool AsmPrinter::doInitialization(Module &M) { + OutStreamer.InitStreamer(); + MMI = getAnalysisIfAvailable<MachineModuleInfo>(); MMI->AnalyzeModule(M); @@ -161,7 +159,7 @@ bool AsmPrinter::doInitialization(Module &M) { const_cast<TargetLoweringObjectFile&>(getObjFileLowering()) .Initialize(OutContext, TM); - Mang = new Mangler(OutContext, *TM.getTargetData()); + Mang = new Mangler(OutContext, *TM.getDataLayout()); // Allow the target to emit any magic that it wants at the start of the file. EmitStartOfAsmFile(M); @@ -281,7 +279,7 @@ void AsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) { SectionKind GVKind = TargetLoweringObjectFile::getKindForGlobal(GV, TM); - const TargetData *TD = TM.getTargetData(); + const DataLayout *TD = TM.getDataLayout(); uint64_t Size = TD->getTypeAllocSize(GV->getType()->getElementType()); // If the alignment is specified, we *must* obey it. Overaligning a global @@ -313,8 +311,13 @@ void AsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) { return; } - if (Align == 1 || - MAI->getLCOMMDirectiveAlignmentType() != LCOMM::NoAlignment) { + // Use .lcomm only if it supports user-specified alignment. + // Otherwise, while it would still be correct to use .lcomm in some + // cases (e.g. when Align == 1), the external assembler might enfore + // some -unknown- default alignment behavior, which could cause + // spurious differences between external and integrated assembler. + // Prefer to simply fall back to .local / .comm in this case. + if (MAI->getLCOMMDirectiveAlignmentType() != LCOMM::NoAlignment) { // .lcomm _foo, 42 OutStreamer.EmitLocalCommonSymbol(GVSym, Size, Align); return; @@ -944,6 +947,8 @@ bool AsmPrinter::doFinalization(Module &M) { MMI = 0; OutStreamer.Finish(); + OutStreamer.reset(); + return false; } @@ -992,7 +997,7 @@ void AsmPrinter::EmitConstantPool() { Kind = SectionKind::getReadOnlyWithRelLocal(); break; case 0: - switch (TM.getTargetData()->getTypeAllocSize(CPE.getType())) { + switch (TM.getDataLayout()->getTypeAllocSize(CPE.getType())) { case 4: Kind = SectionKind::getMergeableConst4(); break; case 8: Kind = SectionKind::getMergeableConst8(); break; case 16: Kind = SectionKind::getMergeableConst16();break; @@ -1038,7 +1043,7 @@ void AsmPrinter::EmitConstantPool() { OutStreamer.EmitFill(NewOffset - Offset, 0/*fillval*/, 0/*addrspace*/); Type *Ty = CPE.getType(); - Offset = NewOffset + TM.getTargetData()->getTypeAllocSize(Ty); + Offset = NewOffset + TM.getDataLayout()->getTypeAllocSize(Ty); OutStreamer.EmitLabel(GetCPISymbol(CPI)); if (CPE.isMachineConstantPoolEntry()) @@ -1081,7 +1086,12 @@ void AsmPrinter::EmitJumpTableInfo() { JTInDiffSection = true; } - EmitAlignment(Log2_32(MJTI->getEntryAlignment(*TM.getTargetData()))); + EmitAlignment(Log2_32(MJTI->getEntryAlignment(*TM.getDataLayout()))); + + // Jump tables in code sections are marked with a data_region directive + // where that's supported. + if (!JTInDiffSection) + OutStreamer.EmitDataRegion(MCDR_DataRegionJT32); for (unsigned JTI = 0, e = JT.size(); JTI != e; ++JTI) { const std::vector<MachineBasicBlock*> &JTBBs = JT[JTI].MBBs; @@ -1123,6 +1133,8 @@ void AsmPrinter::EmitJumpTableInfo() { for (unsigned ii = 0, ee = JTBBs.size(); ii != ee; ++ii) EmitJumpTableEntry(MJTI, JTBBs[ii], JTI); } + if (!JTInDiffSection) + OutStreamer.EmitDataRegion(MCDR_DataRegionEnd); } /// EmitJumpTableEntry - Emit a jump table entry for the specified MBB to the @@ -1190,7 +1202,7 @@ void AsmPrinter::EmitJumpTableEntry(const MachineJumpTableInfo *MJTI, assert(Value && "Unknown entry kind!"); - unsigned EntrySize = MJTI->getEntrySize(*TM.getTargetData()); + unsigned EntrySize = MJTI->getEntrySize(*TM.getDataLayout()); OutStreamer.EmitValue(Value, EntrySize, /*addrspace*/0); } @@ -1292,7 +1304,7 @@ void AsmPrinter::EmitXXStructorList(const Constant *List, bool isCtor) { } // Emit the function pointers in the target-specific order - const TargetData *TD = TM.getTargetData(); + const DataLayout *TD = TM.getDataLayout(); unsigned Align = Log2_32(TD->getPointerPrefAlignment()); std::stable_sort(Structors.begin(), Structors.end(), priority_order); for (unsigned i = 0, e = Structors.size(); i != e; ++i) { @@ -1408,7 +1420,7 @@ void AsmPrinter::EmitLabelPlusOffset(const MCSymbol *Label, uint64_t Offset, // if required for correctness. // void AsmPrinter::EmitAlignment(unsigned NumBits, const GlobalValue *GV) const { - if (GV) NumBits = getGVAlignmentLog2(GV, *TM.getTargetData(), NumBits); + if (GV) NumBits = getGVAlignmentLog2(GV, *TM.getDataLayout(), NumBits); if (NumBits == 0) return; // 1-byte aligned: no need to emit alignment. @@ -1447,10 +1459,10 @@ static const MCExpr *lowerConstant(const Constant *CV, AsmPrinter &AP) { switch (CE->getOpcode()) { default: // If the code isn't optimized, there may be outstanding folding - // opportunities. Attempt to fold the expression using TargetData as a + // opportunities. Attempt to fold the expression using DataLayout as a // last resort before giving up. if (Constant *C = - ConstantFoldConstantExpression(CE, AP.TM.getTargetData())) + ConstantFoldConstantExpression(CE, AP.TM.getDataLayout())) if (C != CE) return lowerConstant(C, AP); @@ -1464,21 +1476,16 @@ static const MCExpr *lowerConstant(const Constant *CV, AsmPrinter &AP) { report_fatal_error(OS.str()); } case Instruction::GetElementPtr: { - const TargetData &TD = *AP.TM.getTargetData(); + const DataLayout &TD = *AP.TM.getDataLayout(); // Generate a symbolic expression for the byte address - const Constant *PtrVal = CE->getOperand(0); - SmallVector<Value*, 8> IdxVec(CE->op_begin()+1, CE->op_end()); - int64_t Offset = TD.getIndexedOffset(PtrVal->getType(), IdxVec); + APInt OffsetAI(TD.getPointerSizeInBits(), 0); + cast<GEPOperator>(CE)->accumulateConstantOffset(TD, OffsetAI); const MCExpr *Base = lowerConstant(CE->getOperand(0), AP); - if (Offset == 0) + if (!OffsetAI) return Base; - // Truncate/sext the offset to the pointer size. - unsigned Width = TD.getPointerSizeInBits(); - if (Width < 64) - Offset = SignExtend64(Offset, Width); - + int64_t Offset = OffsetAI.getSExtValue(); return MCBinaryExpr::CreateAdd(Base, MCConstantExpr::Create(Offset, Ctx), Ctx); } @@ -1493,7 +1500,7 @@ static const MCExpr *lowerConstant(const Constant *CV, AsmPrinter &AP) { return lowerConstant(CE->getOperand(0), AP); case Instruction::IntToPtr: { - const TargetData &TD = *AP.TM.getTargetData(); + const DataLayout &TD = *AP.TM.getDataLayout(); // Handle casts to pointers by changing them into casts to the appropriate // integer type. This promotes constant folding and simplifies this code. Constant *Op = CE->getOperand(0); @@ -1503,7 +1510,7 @@ static const MCExpr *lowerConstant(const Constant *CV, AsmPrinter &AP) { } case Instruction::PtrToInt: { - const TargetData &TD = *AP.TM.getTargetData(); + const DataLayout &TD = *AP.TM.getDataLayout(); // Support only foldable casts to/from pointers that can be eliminated by // changing the pointer to the appropriately sized integer type. Constant *Op = CE->getOperand(0); @@ -1577,7 +1584,7 @@ static int isRepeatedByteSequence(const Value *V, TargetMachine &TM) { if (const ConstantInt *CI = dyn_cast<ConstantInt>(V)) { if (CI->getBitWidth() > 64) return -1; - uint64_t Size = TM.getTargetData()->getTypeAllocSize(V->getType()); + uint64_t Size = TM.getDataLayout()->getTypeAllocSize(V->getType()); uint64_t Value = CI->getZExtValue(); // Make sure the constant is at least 8 bits long and has a power @@ -1608,7 +1615,7 @@ static int isRepeatedByteSequence(const Value *V, TargetMachine &TM) { } return Byte; } - + if (const ConstantDataSequential *CDS = dyn_cast<ConstantDataSequential>(V)) return isRepeatedByteSequence(CDS); @@ -1617,16 +1624,16 @@ static int isRepeatedByteSequence(const Value *V, TargetMachine &TM) { static void emitGlobalConstantDataSequential(const ConstantDataSequential *CDS, unsigned AddrSpace,AsmPrinter &AP){ - + // See if we can aggregate this into a .fill, if so, emit it as such. int Value = isRepeatedByteSequence(CDS, AP.TM); if (Value != -1) { - uint64_t Bytes = AP.TM.getTargetData()->getTypeAllocSize(CDS->getType()); + uint64_t Bytes = AP.TM.getDataLayout()->getTypeAllocSize(CDS->getType()); // Don't emit a 1-byte object as a .fill. if (Bytes > 1) return AP.OutStreamer.EmitFill(Bytes, Value, AddrSpace); } - + // If this can be emitted with .ascii/.asciz, emit it as such. if (CDS->isString()) return AP.OutStreamer.EmitBytes(CDS->getAsString(), AddrSpace); @@ -1650,7 +1657,7 @@ static void emitGlobalConstantDataSequential(const ConstantDataSequential *CDS, float F; uint32_t I; }; - + F = CDS->getElementAsFloat(i); if (AP.isVerbose()) AP.OutStreamer.GetCommentOS() << "float " << F << '\n'; @@ -1663,7 +1670,7 @@ static void emitGlobalConstantDataSequential(const ConstantDataSequential *CDS, double F; uint64_t I; }; - + F = CDS->getElementAsDouble(i); if (AP.isVerbose()) AP.OutStreamer.GetCommentOS() << "double " << F << '\n'; @@ -1671,7 +1678,7 @@ static void emitGlobalConstantDataSequential(const ConstantDataSequential *CDS, } } - const TargetData &TD = *AP.TM.getTargetData(); + const DataLayout &TD = *AP.TM.getDataLayout(); unsigned Size = TD.getTypeAllocSize(CDS->getType()); unsigned EmittedSize = TD.getTypeAllocSize(CDS->getType()->getElementType()) * CDS->getNumElements(); @@ -1687,7 +1694,7 @@ static void emitGlobalConstantArray(const ConstantArray *CA, unsigned AddrSpace, int Value = isRepeatedByteSequence(CA, AP.TM); if (Value != -1) { - uint64_t Bytes = AP.TM.getTargetData()->getTypeAllocSize(CA->getType()); + uint64_t Bytes = AP.TM.getDataLayout()->getTypeAllocSize(CA->getType()); AP.OutStreamer.EmitFill(Bytes, Value, AddrSpace); } else { @@ -1701,7 +1708,7 @@ static void emitGlobalConstantVector(const ConstantVector *CV, for (unsigned i = 0, e = CV->getType()->getNumElements(); i != e; ++i) emitGlobalConstantImpl(CV->getOperand(i), AddrSpace, AP); - const TargetData &TD = *AP.TM.getTargetData(); + const DataLayout &TD = *AP.TM.getDataLayout(); unsigned Size = TD.getTypeAllocSize(CV->getType()); unsigned EmittedSize = TD.getTypeAllocSize(CV->getType()->getElementType()) * CV->getType()->getNumElements(); @@ -1712,7 +1719,7 @@ static void emitGlobalConstantVector(const ConstantVector *CV, static void emitGlobalConstantStruct(const ConstantStruct *CS, unsigned AddrSpace, AsmPrinter &AP) { // Print the fields in successive locations. Pad to align if needed! - const TargetData *TD = AP.TM.getTargetData(); + const DataLayout *TD = AP.TM.getDataLayout(); unsigned Size = TD->getTypeAllocSize(CS->getType()); const StructLayout *Layout = TD->getStructLayout(CS->getType()); uint64_t SizeSoFar = 0; @@ -1777,31 +1784,34 @@ static void emitGlobalConstantFP(const ConstantFP *CFP, unsigned AddrSpace, return; } - if (CFP->getType()->isX86_FP80Ty()) { + if (CFP->getType()->isX86_FP80Ty() || CFP->getType()->isFP128Ty()) { // all long double variants are printed as hex // API needed to prevent premature destruction APInt API = CFP->getValueAPF().bitcastToAPInt(); const uint64_t *p = API.getRawData(); if (AP.isVerbose()) { // Convert to double so we can print the approximate val as a comment. - APFloat DoubleVal = CFP->getValueAPF(); - bool ignored; - DoubleVal.convert(APFloat::IEEEdouble, APFloat::rmNearestTiesToEven, - &ignored); - AP.OutStreamer.GetCommentOS() << "x86_fp80 ~= " - << DoubleVal.convertToDouble() << '\n'; + SmallString<8> StrVal; + CFP->getValueAPF().toString(StrVal); + + const char *TyNote = CFP->getType()->isFP128Ty() ? "fp128 " : "x86_fp80 "; + AP.OutStreamer.GetCommentOS() << TyNote << StrVal << '\n'; } - if (AP.TM.getTargetData()->isBigEndian()) { - AP.OutStreamer.EmitIntValue(p[1], 2, AddrSpace); + // The 80-bit type is made of a 64-bit and 16-bit value, the 128-bit has 2 + // 64-bit words. + uint32_t TrailingSize = CFP->getType()->isFP128Ty() ? 8 : 2; + + if (AP.TM.getDataLayout()->isBigEndian()) { + AP.OutStreamer.EmitIntValue(p[1], TrailingSize, AddrSpace); AP.OutStreamer.EmitIntValue(p[0], 8, AddrSpace); } else { AP.OutStreamer.EmitIntValue(p[0], 8, AddrSpace); - AP.OutStreamer.EmitIntValue(p[1], 2, AddrSpace); + AP.OutStreamer.EmitIntValue(p[1], TrailingSize, AddrSpace); } // Emit the tail padding for the long double. - const TargetData &TD = *AP.TM.getTargetData(); + const DataLayout &TD = *AP.TM.getDataLayout(); AP.OutStreamer.EmitZeros(TD.getTypeAllocSize(CFP->getType()) - TD.getTypeStoreSize(CFP->getType()), AddrSpace); return; @@ -1813,7 +1823,7 @@ static void emitGlobalConstantFP(const ConstantFP *CFP, unsigned AddrSpace, // API needed to prevent premature destruction. APInt API = CFP->getValueAPF().bitcastToAPInt(); const uint64_t *p = API.getRawData(); - if (AP.TM.getTargetData()->isBigEndian()) { + if (AP.TM.getDataLayout()->isBigEndian()) { AP.OutStreamer.EmitIntValue(p[0], 8, AddrSpace); AP.OutStreamer.EmitIntValue(p[1], 8, AddrSpace); } else { @@ -1824,7 +1834,7 @@ static void emitGlobalConstantFP(const ConstantFP *CFP, unsigned AddrSpace, static void emitGlobalConstantLargeInt(const ConstantInt *CI, unsigned AddrSpace, AsmPrinter &AP) { - const TargetData *TD = AP.TM.getTargetData(); + const DataLayout *TD = AP.TM.getDataLayout(); unsigned BitWidth = CI->getBitWidth(); assert((BitWidth & 63) == 0 && "only support multiples of 64-bits"); @@ -1840,7 +1850,7 @@ static void emitGlobalConstantLargeInt(const ConstantInt *CI, static void emitGlobalConstantImpl(const Constant *CV, unsigned AddrSpace, AsmPrinter &AP) { - const TargetData *TD = AP.TM.getTargetData(); + const DataLayout *TD = AP.TM.getDataLayout(); uint64_t Size = TD->getTypeAllocSize(CV->getType()); if (isa<ConstantAggregateZero>(CV) || isa<UndefValue>(CV)) return AP.OutStreamer.EmitZeros(Size, AddrSpace); @@ -1872,7 +1882,7 @@ static void emitGlobalConstantImpl(const Constant *CV, unsigned AddrSpace, if (const ConstantDataSequential *CDS = dyn_cast<ConstantDataSequential>(CV)) return emitGlobalConstantDataSequential(CDS, AddrSpace, AP); - + if (const ConstantArray *CVA = dyn_cast<ConstantArray>(CV)) return emitGlobalConstantArray(CVA, AddrSpace, AP); @@ -1894,10 +1904,10 @@ static void emitGlobalConstantImpl(const Constant *CV, unsigned AddrSpace, return emitGlobalConstantImpl(New, AddrSpace, AP); } } - + if (const ConstantVector *V = dyn_cast<ConstantVector>(CV)) return emitGlobalConstantVector(V, AddrSpace, AP); - + // Otherwise, it must be a ConstantExpr. Lower it to an MCExpr, then emit it // thread the streamer with EmitValue. AP.OutStreamer.EmitValue(lowerConstant(CV, AP), Size, AddrSpace); @@ -1905,7 +1915,7 @@ static void emitGlobalConstantImpl(const Constant *CV, unsigned AddrSpace, /// EmitGlobalConstant - Print a general LLVM constant to the .s file. void AsmPrinter::EmitGlobalConstant(const Constant *CV, unsigned AddrSpace) { - uint64_t Size = TM.getTargetData()->getTypeAllocSize(CV->getType()); + uint64_t Size = TM.getDataLayout()->getTypeAllocSize(CV->getType()); if (Size) emitGlobalConstantImpl(CV, AddrSpace, *this); else if (MAI->hasSubsectionsViaSymbols()) { diff --git a/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp b/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp index 90d511c..ece92d8 100644 --- a/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp +++ b/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp @@ -13,19 +13,19 @@ #define DEBUG_TYPE "asm-printer" #include "llvm/CodeGen/AsmPrinter.h" -#include "llvm/MC/MachineLocation.h" +#include "llvm/ADT/Twine.h" +#include "llvm/IR/DataLayout.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCSection.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSymbol.h" -#include "llvm/Target/TargetData.h" +#include "llvm/MC/MachineLocation.h" +#include "llvm/Support/Dwarf.h" +#include "llvm/Support/ErrorHandling.h" #include "llvm/Target/TargetFrameLowering.h" #include "llvm/Target/TargetLoweringObjectFile.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetRegisterInfo.h" -#include "llvm/ADT/Twine.h" -#include "llvm/Support/Dwarf.h" -#include "llvm/Support/ErrorHandling.h" using namespace llvm; //===----------------------------------------------------------------------===// @@ -53,7 +53,7 @@ void AsmPrinter::EmitULEB128(unsigned Value, const char *Desc, void AsmPrinter::EmitCFAByte(unsigned Val) const { if (isVerbose()) { if (Val >= dwarf::DW_CFA_offset && Val < dwarf::DW_CFA_offset+64) - OutStreamer.AddComment("DW_CFA_offset + Reg (" + + OutStreamer.AddComment("DW_CFA_offset + Reg (" + Twine(Val-dwarf::DW_CFA_offset) + ")"); else OutStreamer.AddComment(dwarf::CallFrameString(Val)); @@ -83,7 +83,7 @@ static const char *DecodeDWARFEncoding(unsigned Encoding) { case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |dwarf::DW_EH_PE_sdata8: return "indirect pcrel sdata8"; } - + return "<unknown encoding>"; } @@ -101,7 +101,7 @@ void AsmPrinter::EmitEncodingByte(unsigned Val, const char *Desc) const { OutStreamer.AddComment(Twine("Encoding = ") + DecodeDWARFEncoding(Val)); } - + OutStreamer.EmitIntValue(Val, 1, 0/*addrspace*/); } @@ -109,30 +109,26 @@ void AsmPrinter::EmitEncodingByte(unsigned Val, const char *Desc) const { unsigned AsmPrinter::GetSizeOfEncodedValue(unsigned Encoding) const { if (Encoding == dwarf::DW_EH_PE_omit) return 0; - + switch (Encoding & 0x07) { default: llvm_unreachable("Invalid encoded value."); - case dwarf::DW_EH_PE_absptr: return TM.getTargetData()->getPointerSize(); + case dwarf::DW_EH_PE_absptr: return TM.getDataLayout()->getPointerSize(); case dwarf::DW_EH_PE_udata2: return 2; case dwarf::DW_EH_PE_udata4: return 4; case dwarf::DW_EH_PE_udata8: return 8; } } -void AsmPrinter::EmitReference(const MCSymbol *Sym, unsigned Encoding) const { - const TargetLoweringObjectFile &TLOF = getObjFileLowering(); - - const MCExpr *Exp = - TLOF.getExprForDwarfReference(Sym, Encoding, OutStreamer); - OutStreamer.EmitAbsValue(Exp, GetSizeOfEncodedValue(Encoding)); -} +void AsmPrinter::EmitTTypeReference(const GlobalValue *GV, + unsigned Encoding) const { + if (GV) { + const TargetLoweringObjectFile &TLOF = getObjFileLowering(); -void AsmPrinter::EmitReference(const GlobalValue *GV, unsigned Encoding)const{ - const TargetLoweringObjectFile &TLOF = getObjFileLowering(); - - const MCExpr *Exp = - TLOF.getExprForDwarfGlobalReference(GV, Mang, MMI, Encoding, OutStreamer); - OutStreamer.EmitValue(Exp, GetSizeOfEncodedValue(Encoding), /*addrspace*/0); + const MCExpr *Exp = + TLOF.getTTypeGlobalReference(GV, Mang, MMI, Encoding, OutStreamer); + OutStreamer.EmitValue(Exp, GetSizeOfEncodedValue(Encoding), /*addrspace*/0); + } else + OutStreamer.EmitIntValue(0, GetSizeOfEncodedValue(Encoding), 0); } /// EmitSectionOffset - Emit the 4-byte offset of Label from the start of its @@ -149,22 +145,22 @@ void AsmPrinter::EmitSectionOffset(const MCSymbol *Label, OutStreamer.EmitCOFFSecRel32(Label); return; } - + // Get the section that we're referring to, based on SectionLabel. const MCSection &Section = SectionLabel->getSection(); - + // If Label has already been emitted, verify that it is in the same section as // section label for sanity. assert((!Label->isInSection() || &Label->getSection() == &Section) && "Section offset using wrong section base for label"); - + // If the section in question will end up with an address of 0 anyway, we can // just emit an absolute reference to save a relocation. if (Section.isBaseAddressKnownZero()) { OutStreamer.EmitSymbolValue(Label, 4, 0/*AddrSpace*/); return; } - + // Otherwise, emit it as a label difference from the start of the section. EmitLabelDifference(Label, SectionLabel, 4); } diff --git a/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp b/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp index b26ffeb..4890627 100644 --- a/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp +++ b/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp @@ -13,32 +13,32 @@ #define DEBUG_TYPE "asm-printer" #include "llvm/CodeGen/AsmPrinter.h" -#include "llvm/Constants.h" -#include "llvm/InlineAsm.h" -#include "llvm/LLVMContext.h" -#include "llvm/Module.h" +#include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/Twine.h" #include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/InlineAsm.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Module.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSubtargetInfo.h" #include "llvm/MC/MCSymbol.h" #include "llvm/MC/MCTargetAsmParser.h" -#include "llvm/Target/TargetMachine.h" -#include "llvm/ADT/OwningPtr.h" -#include "llvm/ADT/SmallString.h" -#include "llvm/ADT/Twine.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/SourceMgr.h" #include "llvm/Support/TargetRegistry.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/Target/TargetMachine.h" using namespace llvm; namespace { struct SrcMgrDiagInfo { const MDNode *LocInfo; - LLVMContext::InlineAsmDiagHandlerTy DiagHandler; + LLVMContext::DiagHandlerTy DiagHandler; void *DiagContext; }; } @@ -89,15 +89,15 @@ void AsmPrinter::EmitInlineAsm(StringRef Str, const MDNode *LocMDNode, SourceMgr SrcMgr; SrcMgrDiagInfo DiagInfo; - // If the current LLVMContext has an inline asm handler, set it in SourceMgr. + // If the current LLVMContext has a diagnostic handler, set it in SourceMgr. LLVMContext &LLVMCtx = MMI->getModule()->getContext(); bool HasDiagHandler = false; - if (LLVMCtx.getInlineAsmDiagnosticHandler() != 0) { + if (LLVMCtx.getDiagnosticHandler() != 0) { // If the source manager has an issue, we arrange for srcMgrDiagHandler // to be invoked, getting DiagInfo passed into it. DiagInfo.LocInfo = LocMDNode; - DiagInfo.DiagHandler = LLVMCtx.getInlineAsmDiagnosticHandler(); - DiagInfo.DiagContext = LLVMCtx.getInlineAsmDiagnosticContext(); + DiagInfo.DiagHandler = LLVMCtx.getDiagnosticHandler(); + DiagInfo.DiagContext = LLVMCtx.getDiagnosticContext(); SrcMgr.setDiagHandler(srcMgrDiagHandler, &DiagInfo); HasDiagHandler = true; } @@ -139,81 +139,116 @@ void AsmPrinter::EmitInlineAsm(StringRef Str, const MDNode *LocMDNode, #endif // ANDROID_TARGET_BUILD } - -/// EmitInlineAsm - This method formats and emits the specified machine -/// instruction that is an inline asm. -void AsmPrinter::EmitInlineAsm(const MachineInstr *MI) const { +static void EmitMSInlineAsmStr(const char *AsmStr, const MachineInstr *MI, + MachineModuleInfo *MMI, int InlineAsmVariant, + AsmPrinter *AP, unsigned LocCookie, + raw_ostream &OS) { #ifndef ANDROID_TARGET_BUILD - assert(MI->isInlineAsm() && "printInlineAsm only works on inline asms"); + // Switch to the inline assembly variant. + OS << "\t.intel_syntax\n\t"; + const char *LastEmitted = AsmStr; // One past the last character emitted. unsigned NumOperands = MI->getNumOperands(); - // Count the number of register definitions to find the asm string. - unsigned NumDefs = 0; - for (; MI->getOperand(NumDefs).isReg() && MI->getOperand(NumDefs).isDef(); - ++NumDefs) - assert(NumDefs != NumOperands-2 && "No asm string?"); - - assert(MI->getOperand(NumDefs).isSymbol() && "No asm string?"); + while (*LastEmitted) { + switch (*LastEmitted) { + default: { + // Not a special case, emit the string section literally. + const char *LiteralEnd = LastEmitted+1; + while (*LiteralEnd && *LiteralEnd != '{' && *LiteralEnd != '|' && + *LiteralEnd != '}' && *LiteralEnd != '$' && *LiteralEnd != '\n') + ++LiteralEnd; - // Disassemble the AsmStr, printing out the literal pieces, the operands, etc. - const char *AsmStr = MI->getOperand(NumDefs).getSymbolName(); + OS.write(LastEmitted, LiteralEnd-LastEmitted); + LastEmitted = LiteralEnd; + break; + } + case '\n': + ++LastEmitted; // Consume newline character. + OS << '\n'; // Indent code with newline. + break; + case '$': { + ++LastEmitted; // Consume '$' character. + bool Done = true; - // If this asmstr is empty, just print the #APP/#NOAPP markers. - // These are useful to see where empty asm's wound up. - if (AsmStr[0] == 0) { - // Don't emit the comments if writing to a .o file. - if (!OutStreamer.hasRawTextSupport()) return; + // Handle escapes. + switch (*LastEmitted) { + default: Done = false; break; + case '$': + ++LastEmitted; // Consume second '$' character. + break; + } + if (Done) break; - OutStreamer.EmitRawText(Twine("\t")+MAI->getCommentString()+ - MAI->getInlineAsmStart()); - OutStreamer.EmitRawText(Twine("\t")+MAI->getCommentString()+ - MAI->getInlineAsmEnd()); - return; - } + const char *IDStart = LastEmitted; + const char *IDEnd = IDStart; + while (*IDEnd >= '0' && *IDEnd <= '9') ++IDEnd; - // Emit the #APP start marker. This has to happen even if verbose-asm isn't - // enabled, so we use EmitRawText. - if (OutStreamer.hasRawTextSupport()) - OutStreamer.EmitRawText(Twine("\t")+MAI->getCommentString()+ - MAI->getInlineAsmStart()); + unsigned Val; + if (StringRef(IDStart, IDEnd-IDStart).getAsInteger(10, Val)) + report_fatal_error("Bad $ operand number in inline asm string: '" + + Twine(AsmStr) + "'"); + LastEmitted = IDEnd; - // Get the !srcloc metadata node if we have it, and decode the loc cookie from - // it. - unsigned LocCookie = 0; - const MDNode *LocMD = 0; - for (unsigned i = MI->getNumOperands(); i != 0; --i) { - if (MI->getOperand(i-1).isMetadata() && - (LocMD = MI->getOperand(i-1).getMetadata()) && - LocMD->getNumOperands() != 0) { - if (const ConstantInt *CI = dyn_cast<ConstantInt>(LocMD->getOperand(0))) { - LocCookie = CI->getZExtValue(); - break; - } - } - } + if (Val >= NumOperands-1) + report_fatal_error("Invalid $ operand number in inline asm string: '" + + Twine(AsmStr) + "'"); - // Emit the inline asm to a temporary string so we can emit it through - // EmitInlineAsm. - SmallString<256> StringData; - raw_svector_ostream OS(StringData); + // Okay, we finally have a value number. Ask the target to print this + // operand! + unsigned OpNo = InlineAsm::MIOp_FirstOperand; - OS << '\t'; + bool Error = false; - // The variant of the current asmprinter. - int AsmPrinterVariant = MAI->getAssemblerDialect(); - int InlineAsmVariant = MI->getInlineAsmDialect(); + // Scan to find the machine operand number for the operand. + for (; Val; --Val) { + if (OpNo >= MI->getNumOperands()) break; + unsigned OpFlags = MI->getOperand(OpNo).getImm(); + OpNo += InlineAsm::getNumOperandRegisters(OpFlags) + 1; + } - // Switch to the inline assembly variant. - if (AsmPrinterVariant != InlineAsmVariant) { - if (InlineAsmVariant == 0) - OS << ".att_syntax\n\t"; - else - OS << ".intel_syntax\n\t"; + // We may have a location metadata attached to the end of the + // instruction, and at no point should see metadata at any + // other point while processing. It's an error if so. + if (OpNo >= MI->getNumOperands() || + MI->getOperand(OpNo).isMetadata()) { + Error = true; + } else { + unsigned OpFlags = MI->getOperand(OpNo).getImm(); + ++OpNo; // Skip over the ID number. + + if (InlineAsm::isMemKind(OpFlags)) { + Error = AP->PrintAsmMemoryOperand(MI, OpNo, InlineAsmVariant, + /*Modifier*/ 0, OS); + } else { + Error = AP->PrintAsmOperand(MI, OpNo, InlineAsmVariant, + /*Modifier*/ 0, OS); + } + } + if (Error) { + std::string msg; + raw_string_ostream Msg(msg); + Msg << "invalid operand in inline asm: '" << AsmStr << "'"; + MMI->getModule()->getContext().emitError(LocCookie, Msg.str()); + } + break; + } + } } + OS << "\n\t.att_syntax\n" << (char)0; // null terminate string. +#endif // ANDROID_TARGET_BUILD +} +static void EmitGCCInlineAsmStr(const char *AsmStr, const MachineInstr *MI, + MachineModuleInfo *MMI, int InlineAsmVariant, + int AsmPrinterVariant, AsmPrinter *AP, + unsigned LocCookie, raw_ostream &OS) { +#ifndef ANDROID_TARGET_BUILD int CurVariant = -1; // The number of the {.|.|.} region we are in. const char *LastEmitted = AsmStr; // One past the last character emitted. + unsigned NumOperands = MI->getNumOperands(); + + OS << '\t'; while (*LastEmitted) { switch (*LastEmitted) { @@ -286,7 +321,7 @@ void AsmPrinter::EmitInlineAsm(const MachineInstr *MI) const { " string: '" + Twine(AsmStr) + "'"); std::string Val(StrStart, StrEnd); - PrintSpecial(MI, OS, Val.c_str()); + AP->PrintSpecial(MI, OS, Val.c_str()); LastEmitted = StrEnd+1; break; } @@ -354,7 +389,6 @@ void AsmPrinter::EmitInlineAsm(const MachineInstr *MI) const { // FIXME: What if the operand isn't an MBB, report error? OS << *MI->getOperand(OpNo).getMBB()->getSymbol(); else { - AsmPrinter *AP = const_cast<AsmPrinter*>(this); if (InlineAsm::isMemKind(OpFlags)) { Error = AP->PrintAsmMemoryOperand(MI, OpNo, InlineAsmVariant, Modifier[0] ? Modifier : 0, @@ -376,15 +410,76 @@ void AsmPrinter::EmitInlineAsm(const MachineInstr *MI) const { } } } - // Switch to the AsmPrinter variant. - if (AsmPrinterVariant != InlineAsmVariant) { - if (AsmPrinterVariant == 0) - OS << "\n\t.att_syntax"; - else - OS << "\n\t.intel_syntax"; + OS << '\n' << (char)0; // null terminate string. +#endif // ANDROID_TARGET_BUILD +} + +/// EmitInlineAsm - This method formats and emits the specified machine +/// instruction that is an inline asm. +void AsmPrinter::EmitInlineAsm(const MachineInstr *MI) const { +#ifndef ANDROID_TARGET_BUILD + assert(MI->isInlineAsm() && "printInlineAsm only works on inline asms"); + + // Count the number of register definitions to find the asm string. + unsigned NumDefs = 0; + for (; MI->getOperand(NumDefs).isReg() && MI->getOperand(NumDefs).isDef(); + ++NumDefs) + assert(NumDefs != MI->getNumOperands()-2 && "No asm string?"); + + assert(MI->getOperand(NumDefs).isSymbol() && "No asm string?"); + + // Disassemble the AsmStr, printing out the literal pieces, the operands, etc. + const char *AsmStr = MI->getOperand(NumDefs).getSymbolName(); + + // If this asmstr is empty, just print the #APP/#NOAPP markers. + // These are useful to see where empty asm's wound up. + if (AsmStr[0] == 0) { + // Don't emit the comments if writing to a .o file. + if (!OutStreamer.hasRawTextSupport()) return; + + OutStreamer.EmitRawText(Twine("\t")+MAI->getCommentString()+ + MAI->getInlineAsmStart()); + OutStreamer.EmitRawText(Twine("\t")+MAI->getCommentString()+ + MAI->getInlineAsmEnd()); + return; } - OS << '\n' << (char)0; // null terminate string. + // Emit the #APP start marker. This has to happen even if verbose-asm isn't + // enabled, so we use EmitRawText. + if (OutStreamer.hasRawTextSupport()) + OutStreamer.EmitRawText(Twine("\t")+MAI->getCommentString()+ + MAI->getInlineAsmStart()); + + // Get the !srcloc metadata node if we have it, and decode the loc cookie from + // it. + unsigned LocCookie = 0; + const MDNode *LocMD = 0; + for (unsigned i = MI->getNumOperands(); i != 0; --i) { + if (MI->getOperand(i-1).isMetadata() && + (LocMD = MI->getOperand(i-1).getMetadata()) && + LocMD->getNumOperands() != 0) { + if (const ConstantInt *CI = dyn_cast<ConstantInt>(LocMD->getOperand(0))) { + LocCookie = CI->getZExtValue(); + break; + } + } + } + + // Emit the inline asm to a temporary string so we can emit it through + // EmitInlineAsm. + SmallString<256> StringData; + raw_svector_ostream OS(StringData); + + // The variant of the current asmprinter. + int AsmPrinterVariant = MAI->getAssemblerDialect(); + InlineAsm::AsmDialect InlineAsmVariant = MI->getInlineAsmDialect(); + AsmPrinter *AP = const_cast<AsmPrinter*>(this); + if (InlineAsmVariant == InlineAsm::AD_ATT) + EmitGCCInlineAsmStr(AsmStr, MI, MMI, InlineAsmVariant, AsmPrinterVariant, + AP, LocCookie, OS); + else + EmitMSInlineAsmStr(AsmStr, MI, MMI, InlineAsmVariant, AP, LocCookie, OS); + EmitInlineAsm(OS.str(), LocMD, MI->getInlineAsmDialect()); // Emit the #NOAPP end marker. This has to happen even if verbose-asm isn't diff --git a/lib/CodeGen/AsmPrinter/DIE.cpp b/lib/CodeGen/AsmPrinter/DIE.cpp index 0885285..a913ca4 100644 --- a/lib/CodeGen/AsmPrinter/DIE.cpp +++ b/lib/CodeGen/AsmPrinter/DIE.cpp @@ -8,16 +8,16 @@ //===----------------------------------------------------------------------===// // // Data structures for DWARF info entries. -// +// //===----------------------------------------------------------------------===// #include "DIE.h" #include "llvm/ADT/Twine.h" #include "llvm/CodeGen/AsmPrinter.h" +#include "llvm/IR/DataLayout.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSymbol.h" -#include "llvm/Target/TargetData.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" @@ -197,9 +197,11 @@ void DIEInteger::EmitValue(AsmPrinter *Asm, unsigned Form) const { case dwarf::DW_FORM_data4: Size = 4; break; case dwarf::DW_FORM_ref8: // Fall thru case dwarf::DW_FORM_data8: Size = 8; break; + case dwarf::DW_FORM_GNU_str_index: Asm->EmitULEB128(Integer); return; case dwarf::DW_FORM_udata: Asm->EmitULEB128(Integer); return; case dwarf::DW_FORM_sdata: Asm->EmitSLEB128(Integer); return; - case dwarf::DW_FORM_addr: Size = Asm->getTargetData().getPointerSize(); break; + case dwarf::DW_FORM_addr: + Size = Asm->getDataLayout().getPointerSize(); break; default: llvm_unreachable("DIE Value form not supported yet"); } Asm->OutStreamer.EmitIntValue(Integer, Size, 0/*addrspace*/); @@ -219,9 +221,10 @@ unsigned DIEInteger::SizeOf(AsmPrinter *AP, unsigned Form) const { case dwarf::DW_FORM_data4: return sizeof(int32_t); case dwarf::DW_FORM_ref8: // Fall thru case dwarf::DW_FORM_data8: return sizeof(int64_t); + case dwarf::DW_FORM_GNU_str_index: return MCAsmInfo::getULEB128Size(Integer); case dwarf::DW_FORM_udata: return MCAsmInfo::getULEB128Size(Integer); case dwarf::DW_FORM_sdata: return MCAsmInfo::getSLEB128Size(Integer); - case dwarf::DW_FORM_addr: return AP->getTargetData().getPointerSize(); + case dwarf::DW_FORM_addr: return AP->getDataLayout().getPointerSize(); default: llvm_unreachable("DIE Value form not supported yet"); } } @@ -248,7 +251,7 @@ void DIELabel::EmitValue(AsmPrinter *AP, unsigned Form) const { unsigned DIELabel::SizeOf(AsmPrinter *AP, unsigned Form) const { if (Form == dwarf::DW_FORM_data4) return 4; if (Form == dwarf::DW_FORM_strp) return 4; - return AP->getTargetData().getPointerSize(); + return AP->getDataLayout().getPointerSize(); } #ifndef NDEBUG @@ -272,7 +275,7 @@ void DIEDelta::EmitValue(AsmPrinter *AP, unsigned Form) const { unsigned DIEDelta::SizeOf(AsmPrinter *AP, unsigned Form) const { if (Form == dwarf::DW_FORM_data4) return 4; if (Form == dwarf::DW_FORM_strp) return 4; - return AP->getTargetData().getPointerSize(); + return AP->getDataLayout().getPointerSize(); } #ifndef NDEBUG diff --git a/lib/CodeGen/AsmPrinter/DIE.h b/lib/CodeGen/AsmPrinter/DIE.h index f93ea1b..35d7959 100644 --- a/lib/CodeGen/AsmPrinter/DIE.h +++ b/lib/CodeGen/AsmPrinter/DIE.h @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// // // Data structures for DWARF info entries. -// +// //===----------------------------------------------------------------------===// #ifndef CODEGEN_ASMPRINTER_DIE_H__ @@ -131,7 +131,7 @@ namespace llvm { DIE *Parent; - /// Attributes values. + /// Attribute values. /// SmallVector<DIEValue*, 32> Values; @@ -155,7 +155,7 @@ namespace llvm { void setTag(unsigned Tag) { Abbrev.setTag(Tag); } void setOffset(unsigned O) { Offset = O; } void setSize(unsigned S) { Size = S; } - + /// addValue - Add a value and attributes to a DIE. /// void addValue(unsigned Attribute, unsigned Form, DIEValue *Value) { @@ -214,9 +214,6 @@ namespace llvm { /// virtual unsigned SizeOf(AsmPrinter *AP, unsigned Form) const = 0; - // Implement isa/cast/dyncast. - static bool classof(const DIEValue *) { return true; } - #ifndef NDEBUG virtual void print(raw_ostream &O) = 0; void dump(); @@ -257,7 +254,6 @@ namespace llvm { virtual unsigned SizeOf(AsmPrinter *AP, unsigned Form) const; // Implement isa/cast/dyncast. - static bool classof(const DIEInteger *) { return true; } static bool classof(const DIEValue *I) { return I->getType() == isInteger; } #ifndef NDEBUG @@ -286,7 +282,6 @@ namespace llvm { virtual unsigned SizeOf(AsmPrinter *AP, unsigned Form) const; // Implement isa/cast/dyncast. - static bool classof(const DIELabel *) { return true; } static bool classof(const DIEValue *L) { return L->getType() == isLabel; } #ifndef NDEBUG @@ -313,7 +308,6 @@ namespace llvm { virtual unsigned SizeOf(AsmPrinter *AP, unsigned Form) const; // Implement isa/cast/dyncast. - static bool classof(const DIEDelta *) { return true; } static bool classof(const DIEValue *D) { return D->getType() == isDelta; } #ifndef NDEBUG @@ -343,7 +337,6 @@ namespace llvm { } // Implement isa/cast/dyncast. - static bool classof(const DIEEntry *) { return true; } static bool classof(const DIEValue *E) { return E->getType() == isEntry; } #ifndef NDEBUG @@ -383,7 +376,6 @@ namespace llvm { virtual unsigned SizeOf(AsmPrinter *AP, unsigned Form) const; // Implement isa/cast/dyncast. - static bool classof(const DIEBlock *) { return true; } static bool classof(const DIEValue *E) { return E->getType() == isBlock; } #ifndef NDEBUG diff --git a/lib/CodeGen/AsmPrinter/DwarfAccelTable.cpp b/lib/CodeGen/AsmPrinter/DwarfAccelTable.cpp index 454a923..c193999 100644 --- a/lib/CodeGen/AsmPrinter/DwarfAccelTable.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfAccelTable.cpp @@ -12,10 +12,10 @@ //===----------------------------------------------------------------------===// #include "DwarfAccelTable.h" -#include "DwarfDebug.h" #include "DIE.h" -#include "llvm/ADT/Twine.h" +#include "DwarfDebug.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/Twine.h" #include "llvm/CodeGen/AsmPrinter.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCStreamer.h" @@ -32,7 +32,7 @@ const char *DwarfAccelTable::Atom::AtomTypeString(enum AtomType AT) { case eAtomTypeTag: return "eAtomTypeTag"; case eAtomTypeNameFlags: return "eAtomTypeNameFlags"; case eAtomTypeTypeFlags: return "eAtomTypeTypeFlags"; - } + } llvm_unreachable("invalid AtomType!"); } @@ -133,8 +133,8 @@ void DwarfAccelTable::EmitHeader(AsmPrinter *Asm) { } } -// Walk through and emit the buckets for the table. This will look -// like a list of numbers of how many elements are in each bucket. +// Walk through and emit the buckets for the table. Each index is +// an offset into the list of hashes. void DwarfAccelTable::EmitBuckets(AsmPrinter *Asm) { unsigned index = 0; for (size_t i = 0, e = Buckets.size(); i < e; ++i) { @@ -155,7 +155,7 @@ void DwarfAccelTable::EmitHashes(AsmPrinter *Asm) { HE = Buckets[i].end(); HI != HE; ++HI) { Asm->OutStreamer.AddComment("Hash in Bucket " + Twine(i)); Asm->EmitInt32((*HI)->HashValue); - } + } } } @@ -181,7 +181,7 @@ void DwarfAccelTable::EmitOffsets(AsmPrinter *Asm, MCSymbol *SecBegin) { // Walk through the buckets and emit the full data for each element in // the bucket. For the string case emit the dies and the various offsets. // Terminate each HashData bucket with 0. -void DwarfAccelTable::EmitData(AsmPrinter *Asm, DwarfDebug *D) { +void DwarfAccelTable::EmitData(AsmPrinter *Asm, DwarfUnits *D) { uint64_t PrevHash = UINT64_MAX; for (size_t i = 0, e = Buckets.size(); i < e; ++i) { for (HashList::const_iterator HI = Buckets[i].begin(), @@ -190,7 +190,7 @@ void DwarfAccelTable::EmitData(AsmPrinter *Asm, DwarfDebug *D) { Asm->OutStreamer.EmitLabel((*HI)->Sym); Asm->OutStreamer.AddComment((*HI)->Str); Asm->EmitSectionOffset(D->getStringPoolEntry((*HI)->Str), - D->getStringPool()); + D->getStringPoolSym()); Asm->OutStreamer.AddComment("Num DIEs"); Asm->EmitInt32((*HI)->Data.size()); for (ArrayRef<HashDataContents*>::const_iterator @@ -215,7 +215,7 @@ void DwarfAccelTable::EmitData(AsmPrinter *Asm, DwarfDebug *D) { // Emit the entire data structure to the output file. void DwarfAccelTable::Emit(AsmPrinter *Asm, MCSymbol *SecBegin, - DwarfDebug *D) { + DwarfUnits *D) { // Emit the header. EmitHeader(Asm); @@ -258,7 +258,7 @@ void DwarfAccelTable::print(raw_ostream &O) { for (std::vector<HashData*>::const_iterator DI = Data.begin(), DE = Data.end(); DI != DE; ++DI) (*DI)->print(O); - + } #endif diff --git a/lib/CodeGen/AsmPrinter/DwarfAccelTable.h b/lib/CodeGen/AsmPrinter/DwarfAccelTable.h index 963b8cd..9915bca 100644 --- a/lib/CodeGen/AsmPrinter/DwarfAccelTable.h +++ b/lib/CodeGen/AsmPrinter/DwarfAccelTable.h @@ -14,18 +14,18 @@ #ifndef CODEGEN_ASMPRINTER_DWARFACCELTABLE_H__ #define CODEGEN_ASMPRINTER_DWARFACCELTABLE_H__ -#include "llvm/ADT/StringMap.h" +#include "DIE.h" #include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/StringMap.h" #include "llvm/MC/MCSymbol.h" -#include "llvm/Support/Dwarf.h" #include "llvm/Support/DataTypes.h" #include "llvm/Support/Debug.h" +#include "llvm/Support/Dwarf.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/Format.h" #include "llvm/Support/FormattedStream.h" -#include "DIE.h" -#include <vector> #include <map> +#include <vector> // The dwarf accelerator tables are an indirect hash table optimized // for null lookup rather than access to known data. They are output into @@ -51,7 +51,7 @@ // section contains all of the 32-bit hash values in contiguous memory, and // the offsets contain the offset into the data area for the particular // hash. -// +// // For a lookup example, we could hash a function name and take it modulo the // number of buckets giving us our bucket. From there we take the bucket value // as an index into the hashes table and look at each successive hash as long @@ -63,8 +63,8 @@ namespace llvm { class AsmPrinter; class DIE; -class DwarfDebug; - +class DwarfUnits; + class DwarfAccelTable { enum HashFunctionType { @@ -81,7 +81,7 @@ class DwarfAccelTable { // Helper function to compute the number of buckets needed based on // the number of unique hashes. void ComputeBucketCount (void); - + struct TableHeader { uint32_t magic; // 'HASH' magic value to allow endian detection uint16_t version; // Version number. @@ -94,7 +94,7 @@ class DwarfAccelTable { // Also written to disk is the implementation specific header data. static const uint32_t MagicHash = 0x48415348; - + TableHeader (uint32_t data_len) : magic (MagicHash), version (1), hash_function (eHashFunctionDJB), bucket_count (0), hashes_count (0), header_data_len (data_len) @@ -123,7 +123,7 @@ public: // // uint32_t die_offset_base // uint32_t atom_count - // atom_count Atoms + // atom_count Atoms enum AtomType { eAtomTypeNULL = 0u, eAtomTypeDIEOffset = 1u, // DIE offset, check form for encoding @@ -138,12 +138,12 @@ public: enum TypeFlags { eTypeFlagClassMask = 0x0000000fu, - + // Always set for C++, only set for ObjC if this is the // @implementation for a class. eTypeFlagClassIsImplementation = ( 1u << 1 ) - }; - + }; + // Make these public so that they can be used as a general interface to // the class. struct Atom { @@ -237,15 +237,15 @@ private: #endif }; - DwarfAccelTable(const DwarfAccelTable&); // DO NOT IMPLEMENT - void operator=(const DwarfAccelTable&); // DO NOT IMPLEMENT + DwarfAccelTable(const DwarfAccelTable&) LLVM_DELETED_FUNCTION; + void operator=(const DwarfAccelTable&) LLVM_DELETED_FUNCTION; // Internal Functions void EmitHeader(AsmPrinter *); void EmitBuckets(AsmPrinter *); void EmitHashes(AsmPrinter *); void EmitOffsets(AsmPrinter *, MCSymbol *); - void EmitData(AsmPrinter *, DwarfDebug *D); + void EmitData(AsmPrinter *, DwarfUnits *D); // Allocator for HashData and HashDataContents. BumpPtrAllocator Allocator; @@ -265,14 +265,14 @@ private: typedef std::vector<HashList> BucketList; BucketList Buckets; HashList Hashes; - + // Public Implementation public: DwarfAccelTable(ArrayRef<DwarfAccelTable::Atom>); ~DwarfAccelTable(); void AddName(StringRef, DIE*, char = 0); void FinalizeTable(AsmPrinter *, const char *); - void Emit(AsmPrinter *, MCSymbol *, DwarfDebug *); + void Emit(AsmPrinter *, MCSymbol *, DwarfUnits *); #ifndef NDEBUG void print(raw_ostream &O); void dump() { print(dbgs()); } diff --git a/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp b/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp index d975f1f..fec5ced 100644 --- a/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp @@ -12,31 +12,31 @@ //===----------------------------------------------------------------------===// #include "DwarfException.h" -#include "llvm/Module.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/Twine.h" #include "llvm/CodeGen/AsmPrinter.h" -#include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineFunction.h" -#include "llvm/MC/MachineLocation.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/IR/Module.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCSection.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSymbol.h" +#include "llvm/MC/MachineLocation.h" +#include "llvm/Support/Dwarf.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/FormattedStream.h" #include "llvm/Target/Mangler.h" -#include "llvm/Target/TargetData.h" #include "llvm/Target/TargetFrameLowering.h" #include "llvm/Target/TargetLoweringObjectFile.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetOptions.h" #include "llvm/Target/TargetRegisterInfo.h" -#include "llvm/Support/Dwarf.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/FormattedStream.h" -#include "llvm/ADT/SmallString.h" -#include "llvm/ADT/StringExtras.h" -#include "llvm/ADT/Twine.h" using namespace llvm; DwarfCFIException::DwarfCFIException(AsmPrinter *A) @@ -122,8 +122,9 @@ void DwarfCFIException::BeginFunction(const MachineFunction *MF) { const MCSymbol *Sym = TLOF.getCFIPersonalitySymbol(Per, Asm->Mang, MMI); Asm->OutStreamer.EmitCFIPersonality(Sym, PerEncoding); - Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("eh_func_begin", - Asm->getFunctionNumber())); + Asm->OutStreamer.EmitDebugLabel + (Asm->GetTempSymbol("eh_func_begin", + Asm->getFunctionNumber())); // Provide LSDA information. if (!shouldEmitLSDA) diff --git a/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp b/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp index e585897..21cceaf 100644 --- a/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp @@ -13,28 +13,29 @@ #define DEBUG_TYPE "dwarfdebug" -#include "DwarfAccelTable.h" #include "DwarfCompileUnit.h" +#include "DwarfAccelTable.h" #include "DwarfDebug.h" -#include "llvm/Constants.h" +#include "llvm/ADT/APFloat.h" #include "llvm/DIBuilder.h" -#include "llvm/GlobalVariable.h" -#include "llvm/Instructions.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/IR/GlobalVariable.h" +#include "llvm/IR/Instructions.h" #include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" #include "llvm/Target/Mangler.h" -#include "llvm/Target/TargetData.h" #include "llvm/Target/TargetFrameLowering.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetRegisterInfo.h" -#include "llvm/ADT/APFloat.h" -#include "llvm/Support/ErrorHandling.h" using namespace llvm; /// CompileUnit - Compile unit constructor. -CompileUnit::CompileUnit(unsigned I, unsigned L, DIE *D, AsmPrinter *A, - DwarfDebug *DW) - : ID(I), Language(L), CUDie(D), Asm(A), DD(DW), IndexTyDie(0) { +CompileUnit::CompileUnit(unsigned UID, unsigned L, DIE *D, AsmPrinter *A, + DwarfDebug *DW, DwarfUnits *DWU) + : UniqueID(UID), Language(L), CUDie(D), Asm(A), DD(DW), DU(DWU), + IndexTyDie(0) { DIEIntegerOne = new (DIEValueAllocator) DIEInteger(1); } @@ -51,6 +52,50 @@ DIEEntry *CompileUnit::createDIEEntry(DIE *Entry) { return Value; } +/// getDefaultLowerBound - Return the default lower bound for an array. If the +/// DWARF version doesn't handle the language, return -1. +int64_t CompileUnit::getDefaultLowerBound() const { + switch (Language) { + default: + break; + + case dwarf::DW_LANG_C89: + case dwarf::DW_LANG_C99: + case dwarf::DW_LANG_C: + case dwarf::DW_LANG_C_plus_plus: + case dwarf::DW_LANG_ObjC: + case dwarf::DW_LANG_ObjC_plus_plus: + return 0; + + case dwarf::DW_LANG_Fortran77: + case dwarf::DW_LANG_Fortran90: + case dwarf::DW_LANG_Fortran95: + return 1; + + // The languages below have valid values only if the DWARF version >= 4. + case dwarf::DW_LANG_Java: + case dwarf::DW_LANG_Python: + case dwarf::DW_LANG_UPC: + case dwarf::DW_LANG_D: + if (dwarf::DWARF_VERSION >= 4) + return 0; + break; + + case dwarf::DW_LANG_Ada83: + case dwarf::DW_LANG_Ada95: + case dwarf::DW_LANG_Cobol74: + case dwarf::DW_LANG_Cobol85: + case dwarf::DW_LANG_Modula2: + case dwarf::DW_LANG_Pascal83: + case dwarf::DW_LANG_PLI: + if (dwarf::DWARF_VERSION >= 4) + return 1; + break; + } + + return -1; +} + /// addFlag - Add a flag that is true. void CompileUnit::addFlag(DIE *Die, unsigned Attribute) { if (!DD->useDarwinGDBCompat()) @@ -81,14 +126,37 @@ void CompileUnit::addSInt(DIE *Die, unsigned Attribute, /// addString - Add a string attribute data and value. We always emit a /// reference to the string pool instead of immediate strings so that DIEs have -/// more predictable sizes. +/// more predictable sizes. In the case of split dwarf we emit an index +/// into another table which gets us the static offset into the string +/// table. void CompileUnit::addString(DIE *Die, unsigned Attribute, StringRef String) { - MCSymbol *Symb = DD->getStringPoolEntry(String); + if (!DD->useSplitDwarf()) { + MCSymbol *Symb = DU->getStringPoolEntry(String); + DIEValue *Value; + if (Asm->needsRelocationsForDwarfStringPool()) + Value = new (DIEValueAllocator) DIELabel(Symb); + else { + MCSymbol *StringPool = DU->getStringPoolSym(); + Value = new (DIEValueAllocator) DIEDelta(Symb, StringPool); + } + Die->addValue(Attribute, dwarf::DW_FORM_strp, Value); + } else { + unsigned idx = DU->getStringPoolIndex(String); + DIEValue *Value = new (DIEValueAllocator) DIEInteger(idx); + Die->addValue(Attribute, dwarf::DW_FORM_GNU_str_index, Value); + } +} + +/// addLocalString - Add a string attribute data and value. This is guaranteed +/// to be in the local string pool instead of indirected. +void CompileUnit::addLocalString(DIE *Die, unsigned Attribute, + StringRef String) { + MCSymbol *Symb = DU->getStringPoolEntry(String); DIEValue *Value; if (Asm->needsRelocationsForDwarfStringPool()) Value = new (DIEValueAllocator) DIELabel(Symb); else { - MCSymbol *StringPool = DD->getStringPool(); + MCSymbol *StringPool = DU->getStringPoolSym(); Value = new (DIEValueAllocator) DIEDelta(Symb, StringPool); } Die->addValue(Attribute, dwarf::DW_FORM_strp, Value); @@ -132,11 +200,11 @@ void CompileUnit::addSourceLine(DIE *Die, DIVariable V) { // Verify variable. if (!V.Verify()) return; - + unsigned Line = V.getLineNumber(); if (Line == 0) return; - unsigned FileID = DD->GetOrCreateSourceID(V.getContext().getFilename(), + unsigned FileID = DD->getOrCreateSourceID(V.getContext().getFilename(), V.getContext().getDirectory()); assert(FileID && "Invalid file id"); addUInt(Die, dwarf::DW_AT_decl_file, 0, FileID); @@ -153,7 +221,7 @@ void CompileUnit::addSourceLine(DIE *Die, DIGlobalVariable G) { unsigned Line = G.getLineNumber(); if (Line == 0) return; - unsigned FileID = DD->GetOrCreateSourceID(G.getFilename(), G.getDirectory()); + unsigned FileID = DD->getOrCreateSourceID(G.getFilename(), G.getDirectory()); assert(FileID && "Invalid file id"); addUInt(Die, dwarf::DW_AT_decl_file, 0, FileID); addUInt(Die, dwarf::DW_AT_decl_line, 0, Line); @@ -171,7 +239,7 @@ void CompileUnit::addSourceLine(DIE *Die, DISubprogram SP) { if (Line == 0) return; - unsigned FileID = DD->GetOrCreateSourceID(SP.getFilename(), + unsigned FileID = DD->getOrCreateSourceID(SP.getFilename(), SP.getDirectory()); assert(FileID && "Invalid file id"); addUInt(Die, dwarf::DW_AT_decl_file, 0, FileID); @@ -188,7 +256,7 @@ void CompileUnit::addSourceLine(DIE *Die, DIType Ty) { unsigned Line = Ty.getLineNumber(); if (Line == 0) return; - unsigned FileID = DD->GetOrCreateSourceID(Ty.getFilename(), + unsigned FileID = DD->getOrCreateSourceID(Ty.getFilename(), Ty.getDirectory()); assert(FileID && "Invalid file id"); addUInt(Die, dwarf::DW_AT_decl_file, 0, FileID); @@ -206,7 +274,7 @@ void CompileUnit::addSourceLine(DIE *Die, DIObjCProperty Ty) { if (Line == 0) return; DIFile File = Ty.getFile(); - unsigned FileID = DD->GetOrCreateSourceID(File.getFilename(), + unsigned FileID = DD->getOrCreateSourceID(File.getFilename(), File.getDirectory()); assert(FileID && "Invalid file id"); addUInt(Die, dwarf::DW_AT_decl_file, 0, FileID); @@ -225,15 +293,15 @@ void CompileUnit::addSourceLine(DIE *Die, DINameSpace NS) { return; StringRef FN = NS.getFilename(); - unsigned FileID = DD->GetOrCreateSourceID(FN, NS.getDirectory()); + unsigned FileID = DD->getOrCreateSourceID(FN, NS.getDirectory()); assert(FileID && "Invalid file id"); addUInt(Die, dwarf::DW_AT_decl_file, 0, FileID); addUInt(Die, dwarf::DW_AT_decl_line, 0, Line); } -/// addVariableAddress - Add DW_AT_location attribute for a +/// addVariableAddress - Add DW_AT_location attribute for a /// DbgVariable based on provided MachineLocation. -void CompileUnit::addVariableAddress(DbgVariable *&DV, DIE *Die, +void CompileUnit::addVariableAddress(DbgVariable *&DV, DIE *Die, MachineLocation Location) { if (DV->variableHasComplexAddress()) addComplexAddress(DV, Die, dwarf::DW_AT_location, Location); @@ -492,7 +560,7 @@ bool CompileUnit::addConstantValue(DIE *Die, const MachineOperand &MO, case 64: Form = dwarf::DW_FORM_data8; break; default: break; } - SignedConstant ? addSInt(Block, 0, Form, MO.getImm()) + SignedConstant ? addSInt(Block, 0, Form, MO.getImm()) : addUInt(Block, 0, Form, MO.getImm()); addBlock(Die, dwarf::DW_AT_const_value, 0, Block); @@ -510,7 +578,7 @@ bool CompileUnit::addConstantFPValue(DIE *Die, const MachineOperand &MO) { const char *FltPtr = (const char*)FltVal.getRawData(); int NumBytes = FltVal.getBitWidth() / 8; // 8 bits per byte. - bool LittleEndian = Asm->getTargetData().isLittleEndian(); + bool LittleEndian = Asm->getDataLayout().isLittleEndian(); int Incr = (LittleEndian ? 1 : -1); int Start = (LittleEndian ? 0 : NumBytes - 1); int Stop = (LittleEndian ? NumBytes : -1); @@ -535,7 +603,7 @@ bool CompileUnit::addConstantValue(DIE *Die, const ConstantInt *CI, case 16: form = dwarf::DW_FORM_data2; break; case 32: form = dwarf::DW_FORM_data4; break; case 64: form = dwarf::DW_FORM_data8; break; - default: + default: form = Unsigned ? dwarf::DW_FORM_udata : dwarf::DW_FORM_sdata; } if (Unsigned) @@ -552,7 +620,7 @@ bool CompileUnit::addConstantValue(DIE *Die, const ConstantInt *CI, const uint64_t *Ptr64 = Val.getRawData(); int NumBytes = Val.getBitWidth() / 8; // 8 bits per byte. - bool LittleEndian = Asm->getTargetData().isLittleEndian(); + bool LittleEndian = Asm->getDataLayout().isLittleEndian(); // Output the constant to DWARF one byte at a time. for (int i = 0; i < NumBytes; i++) { @@ -635,7 +703,7 @@ DIE *CompileUnit::getOrCreateTypeDIE(const MDNode *TyNode) { DwarfAccelTable::eTypeFlagClassIsImplementation : 0; addAccelType(Ty.getName(), std::make_pair(TyDIE, Flags)); } - + addToContextOwner(TyDIE, Ty.getContext()); return TyDIE; } @@ -670,8 +738,8 @@ void CompileUnit::addType(DIE *Entity, DIType Ty, unsigned Attribute) { /// void CompileUnit::addGlobalType(DIType Ty) { DIDescriptor Context = Ty.getContext(); - if (Ty.isCompositeType() && !Ty.getName().empty() && !Ty.isForwardDecl() - && (!Context || Context.isCompileUnit() || Context.isFile() + if (Ty.isCompositeType() && !Ty.getName().empty() && !Ty.isForwardDecl() + && (!Context || Context.isCompileUnit() || Context.isFile() || Context.isNameSpace())) if (DIEEntry *Entry = getDIEEntry(Ty)) GlobalTypes[Ty.getName()] = Entry->getEntry(); @@ -739,6 +807,9 @@ void CompileUnit::constructTypeDIE(DIE &Buffer, DIDerivedType DTy) { if (Size && Tag != dwarf::DW_TAG_pointer_type) addUInt(&Buffer, dwarf::DW_AT_byte_size, 0, Size); + if (Tag == dwarf::DW_TAG_ptr_to_member_type) + addDIEEntry(&Buffer, dwarf::DW_AT_containing_type, dwarf::DW_FORM_ref4, + getOrCreateTypeDIE(DTy.getClassType())); // Add source line info if available and TyDesc is not a forward declaration. if (!DTy.isForwardDecl()) addSourceLine(&Buffer, DTy); @@ -754,7 +825,6 @@ void CompileUnit::constructTypeDIE(DIE &Buffer, DICompositeType CTy) { Buffer.setTag(Tag); switch (Tag) { - case dwarf::DW_TAG_vector_type: case dwarf::DW_TAG_array_type: constructArrayTypeDIE(Buffer, &CTy); break; @@ -830,7 +900,7 @@ void CompileUnit::constructTypeDIE(DIE &Buffer, DICompositeType CTy) { else if (SP.isPrivate()) addUInt(ElemDie, dwarf::DW_AT_accessibility, dwarf::DW_FORM_data1, dwarf::DW_ACCESS_private); - else + else addUInt(ElemDie, dwarf::DW_AT_accessibility, dwarf::DW_FORM_data1, dwarf::DW_ACCESS_public); if (SP.isExplicit()) @@ -878,7 +948,7 @@ void CompileUnit::constructTypeDIE(DIE &Buffer, DICompositeType CTy) { if (Property.isNonAtomicObjCProperty()) PropertyAttributes |= dwarf::DW_APPLE_PROPERTY_nonatomic; if (PropertyAttributes) - addUInt(ElemDie, dwarf::DW_AT_APPLE_property_attribute, 0, + addUInt(ElemDie, dwarf::DW_AT_APPLE_property_attribute, 0, PropertyAttributes); DIEEntry *Entry = getDIEEntry(Element); @@ -951,7 +1021,7 @@ void CompileUnit::constructTypeDIE(DIE &Buffer, DICompositeType CTy) { } } -/// getOrCreateTemplateTypeParameterDIE - Find existing DIE or create new DIE +/// getOrCreateTemplateTypeParameterDIE - Find existing DIE or create new DIE /// for the given DITemplateTypeParameter. DIE * CompileUnit::getOrCreateTemplateTypeParameterDIE(DITemplateTypeParameter TP) { @@ -965,7 +1035,7 @@ CompileUnit::getOrCreateTemplateTypeParameterDIE(DITemplateTypeParameter TP) { return ParamDIE; } -/// getOrCreateTemplateValueParameterDIE - Find existing DIE or create new DIE +/// getOrCreateTemplateValueParameterDIE - Find existing DIE or create new DIE /// for the given DITemplateValueParameter. DIE * CompileUnit::getOrCreateTemplateValueParameterDIE(DITemplateValueParameter TPV){ @@ -977,7 +1047,7 @@ CompileUnit::getOrCreateTemplateValueParameterDIE(DITemplateValueParameter TPV){ addType(ParamDIE, TPV.getType()); if (!TPV.getName().empty()) addString(ParamDIE, dwarf::DW_AT_name, TPV.getName()); - addUInt(ParamDIE, dwarf::DW_AT_const_value, dwarf::DW_FORM_udata, + addUInt(ParamDIE, dwarf::DW_AT_const_value, dwarf::DW_FORM_udata, TPV.getValue()); return ParamDIE; } @@ -1095,7 +1165,7 @@ DIE *CompileUnit::getOrCreateSubprogramDIE(DISubprogram SP) { if (!SP.isDefinition()) { addFlag(SPDie, dwarf::DW_AT_declaration); - + // Add arguments. Do not add arguments for subprogram definition. They will // be handled while processing variables. DICompositeType SPTy = SP.getType(); @@ -1105,7 +1175,7 @@ DIE *CompileUnit::getOrCreateSubprogramDIE(DISubprogram SP) { if (SPTag == dwarf::DW_TAG_subroutine_type) for (unsigned i = 1, N = Args.getNumElements(); i < N; ++i) { DIE *Arg = new DIE(dwarf::DW_TAG_formal_parameter); - DIType ATy = DIType(DIType(Args.getElement(i))); + DIType ATy = DIType(Args.getElement(i)); addType(Arg, ATy); if (ATy.isArtificial()) addFlag(Arg, dwarf::DW_AT_artificial); @@ -1213,7 +1283,7 @@ void CompileUnit::createGlobalVariableDIE(const MDNode *N) { } else { addBlock(VariableDIE, dwarf::DW_AT_location, 0, Block); } - } else if (const ConstantInt *CI = + } else if (const ConstantInt *CI = dyn_cast_or_null<ConstantInt>(GV.getConstant())) addConstantValue(VariableDIE, CI, GTy.isUnsignedDIType()); else if (const ConstantExpr *CE = getMergedGlobalExpr(N->getOperand(11))) { @@ -1226,8 +1296,8 @@ void CompileUnit::createGlobalVariableDIE(const MDNode *N) { Asm->Mang->getSymbol(cast<GlobalValue>(Ptr))); addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_constu); SmallVector<Value*, 3> Idx(CE->op_begin()+1, CE->op_end()); - addUInt(Block, 0, dwarf::DW_FORM_udata, - Asm->getTargetData().getIndexedOffset(Ptr->getType(), Idx)); + addUInt(Block, 0, dwarf::DW_FORM_udata, + Asm->getDataLayout().getIndexedOffset(Ptr->getType(), Idx)); addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_plus); addBlock(VariableDIE, dwarf::DW_AT_location, 0, Block); } @@ -1250,22 +1320,25 @@ void CompileUnit::constructSubrangeDIE(DIE &Buffer, DISubrange SR, DIE *IndexTy) { DIE *DW_Subrange = new DIE(dwarf::DW_TAG_subrange_type); addDIEEntry(DW_Subrange, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, IndexTy); - uint64_t L = SR.getLo(); - uint64_t H = SR.getHi(); - // The L value defines the lower bounds which is typically zero for C/C++. The - // H value is the upper bounds. Values are 64 bit. H - L + 1 is the size - // of the array. If L > H then do not emit DW_AT_lower_bound and - // DW_AT_upper_bound attributes. If L is zero and H is also zero then the - // array has one element and in such case do not emit lower bound. + // The LowerBound value defines the lower bounds which is typically zero for + // C/C++. The Count value is the number of elements. Values are 64 bit. If + // Count == -1 then the array is unbounded and we do not emit + // DW_AT_lower_bound and DW_AT_upper_bound attributes. If LowerBound == 0 and + // Count == 0, then the array has zero elements in which case we do not emit + // an upper bound. + int64_t LowerBound = SR.getLo(); + int64_t DefaultLowerBound = getDefaultLowerBound(); + int64_t Count = SR.getCount(); + + if (DefaultLowerBound == -1 || LowerBound != DefaultLowerBound) + addUInt(DW_Subrange, dwarf::DW_AT_lower_bound, 0, LowerBound); + + if (Count != -1 && Count != 0) + // FIXME: An unbounded array should reference the expression that defines + // the array. + addUInt(DW_Subrange, dwarf::DW_AT_upper_bound, 0, LowerBound + Count - 1); - if (L > H) { - Buffer.addChild(DW_Subrange); - return; - } - if (L) - addUInt(DW_Subrange, dwarf::DW_AT_lower_bound, 0, L); - addUInt(DW_Subrange, dwarf::DW_AT_upper_bound, 0, H); Buffer.addChild(DW_Subrange); } @@ -1273,7 +1346,7 @@ void CompileUnit::constructSubrangeDIE(DIE &Buffer, DISubrange SR, void CompileUnit::constructArrayTypeDIE(DIE &Buffer, DICompositeType *CTy) { Buffer.setTag(dwarf::DW_TAG_array_type); - if (CTy->getTag() == dwarf::DW_TAG_vector_type) + if (CTy->isVector()) addFlag(&Buffer, dwarf::DW_AT_GNU_vector); // Emit derived type. @@ -1281,10 +1354,13 @@ void CompileUnit::constructArrayTypeDIE(DIE &Buffer, DIArray Elements = CTy->getTypeArray(); // Get an anonymous type for index type. + // FIXME: This type should be passed down from the front end + // as different languages may have different sizes for indexes. DIE *IdxTy = getIndexTyDie(); if (!IdxTy) { // Construct an anonymous type for index type. IdxTy = new DIE(dwarf::DW_TAG_base_type); + addString(IdxTy, dwarf::DW_AT_name, "int"); addUInt(IdxTy, dwarf::DW_AT_byte_size, 0, sizeof(int32_t)); addUInt(IdxTy, dwarf::DW_AT_encoding, dwarf::DW_FORM_data1, dwarf::DW_ATE_signed); @@ -1327,8 +1403,6 @@ void CompileUnit::constructContainingTypeDIEs() { /// constructVariableDIE - Construct a DIE for the given DbgVariable. DIE *CompileUnit::constructVariableDIE(DbgVariable *DV, bool isScopeAbstract) { StringRef Name = DV->getName(); - if (Name.empty()) - return NULL; // Translate tag to proper Dwarf tag. unsigned Tag = DV->getTag(); @@ -1376,20 +1450,20 @@ DIE *CompileUnit::constructVariableDIE(DbgVariable *DV, bool isScopeAbstract) { TRI->getFrameRegister(*Asm->MF) == RegOp.getReg()) { unsigned FrameReg = 0; const TargetFrameLowering *TFI = Asm->TM.getFrameLowering(); - int Offset = - TFI->getFrameIndexReference(*Asm->MF, - DVInsn->getOperand(1).getImm(), + int Offset = + TFI->getFrameIndexReference(*Asm->MF, + DVInsn->getOperand(1).getImm(), FrameReg); MachineLocation Location(FrameReg, Offset); addVariableAddress(DV, VariableDie, Location); - + } else if (RegOp.getReg()) - addVariableAddress(DV, VariableDie, + addVariableAddress(DV, VariableDie, MachineLocation(RegOp.getReg())); updated = true; } else if (DVInsn->getOperand(0).isImm()) - updated = + updated = addConstantValue(VariableDie, DVInsn->getOperand(0), DV->getType()); else if (DVInsn->getOperand(0).isFPImm()) @@ -1397,11 +1471,11 @@ DIE *CompileUnit::constructVariableDIE(DbgVariable *DV, bool isScopeAbstract) { addConstantFPValue(VariableDie, DVInsn->getOperand(0)); else if (DVInsn->getOperand(0).isCImm()) updated = - addConstantValue(VariableDie, + addConstantValue(VariableDie, DVInsn->getOperand(0).getCImm(), DV->getType().isUnsignedDIType()); } else { - addVariableAddress(DV, VariableDie, + addVariableAddress(DV, VariableDie, Asm->getDebugValueLocation(DVInsn)); updated = true; } @@ -1419,7 +1493,7 @@ DIE *CompileUnit::constructVariableDIE(DbgVariable *DV, bool isScopeAbstract) { if (FI != ~0) { unsigned FrameReg = 0; const TargetFrameLowering *TFI = Asm->TM.getFrameLowering(); - int Offset = + int Offset = TFI->getFrameIndexReference(*Asm->MF, FI, FrameReg); MachineLocation Location(FrameReg, Offset); addVariableAddress(DV, VariableDie, Location); @@ -1459,7 +1533,7 @@ DIE *CompileUnit::createMemberDIE(DIDerivedType DT) { Offset -= FieldOffset; // Maybe we need to work from the other end. - if (Asm->getTargetData().isLittleEndian()) + if (Asm->getDataLayout().isLittleEndian()) Offset = FieldSize - (Offset + Size); addUInt(MemberDie, dwarf::DW_AT_bit_offset, 0, Offset); @@ -1499,7 +1573,7 @@ DIE *CompileUnit::createMemberDIE(DIDerivedType DT) { addUInt(MemberDie, dwarf::DW_AT_accessibility, dwarf::DW_FORM_data1, dwarf::DW_ACCESS_private); // Otherwise C++ member and base classes are considered public. - else + else addUInt(MemberDie, dwarf::DW_AT_accessibility, dwarf::DW_FORM_data1, dwarf::DW_ACCESS_public); if (DT.isVirtual()) @@ -1509,9 +1583,12 @@ DIE *CompileUnit::createMemberDIE(DIDerivedType DT) { // Objective-C properties. if (MDNode *PNode = DT.getObjCProperty()) if (DIEEntry *PropertyDie = getDIEEntry(PNode)) - MemberDie->addValue(dwarf::DW_AT_APPLE_property, dwarf::DW_FORM_ref4, + MemberDie->addValue(dwarf::DW_AT_APPLE_property, dwarf::DW_FORM_ref4, PropertyDie); + if (DT.isArtificial()) + addFlag(MemberDie, dwarf::DW_AT_artificial); + // This is only for backward compatibility. StringRef PropertyName = DT.getObjCPropertyName(); if (!PropertyName.empty()) { @@ -1536,7 +1613,7 @@ DIE *CompileUnit::createMemberDIE(DIDerivedType DT) { if (DT.isNonAtomicObjCProperty()) PropertyAttributes |= dwarf::DW_APPLE_PROPERTY_nonatomic; if (PropertyAttributes) - addUInt(MemberDie, dwarf::DW_AT_APPLE_property_attribute, 0, + addUInt(MemberDie, dwarf::DW_AT_APPLE_property_attribute, 0, PropertyAttributes); } return MemberDie; diff --git a/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h b/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h index 22401fe..f210dcc 100644 --- a/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h +++ b/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h @@ -15,14 +15,15 @@ #define CODEGEN_ASMPRINTER_DWARFCOMPILEUNIT_H #include "DIE.h" -#include "llvm/DebugInfo.h" #include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/StringMap.h" #include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/DebugInfo.h" namespace llvm { class DwarfDebug; +class DwarfUnits; class MachineLocation; class MachineOperand; class ConstantInt; @@ -32,9 +33,9 @@ class DbgVariable; /// CompileUnit - This dwarf writer support class manages information associated /// with a source file. class CompileUnit { - /// ID - File identifier for source. + /// UniqueID - a numeric ID unique among all CUs in the module /// - unsigned ID; + unsigned UniqueID; /// Language - The DW_AT_language of the compile unit /// @@ -47,7 +48,9 @@ class CompileUnit { /// Asm - Target of Dwarf emission. AsmPrinter *Asm; + // Holders for some common dwarf information. DwarfDebug *DD; + DwarfUnits *DU; /// IndexTyDie - An anonymous type for index type. Owned by CUDie. DIE *IndexTyDie; @@ -79,12 +82,17 @@ class CompileUnit { /// corresponds to the MDNode mapped with the subprogram DIE. DenseMap<DIE *, const MDNode *> ContainingTypeMap; + /// getLowerBoundDefault - Return the default lower bound for an array. If the + /// DWARF version doesn't handle the language, return -1. + int64_t getDefaultLowerBound() const; + public: - CompileUnit(unsigned I, unsigned L, DIE *D, AsmPrinter *A, DwarfDebug *DW); + CompileUnit(unsigned UID, unsigned L, DIE *D, AsmPrinter *A, DwarfDebug *DW, + DwarfUnits *); ~CompileUnit(); // Accessors. - unsigned getID() const { return ID; } + unsigned getUniqueID() const { return UniqueID; } unsigned getLanguage() const { return Language; } DIE* getCUDie() const { return CUDie.get(); } const StringMap<DIE*> &getGlobalTypes() const { return GlobalTypes; } @@ -102,7 +110,7 @@ public: &getAccelTypes() const { return AccelTypes; } - + /// hasContent - Return true if this compile unit has something to write out. /// bool hasContent() const { return !CUDie->getChildren().empty(); } @@ -129,12 +137,12 @@ public: std::vector<std::pair<DIE*, unsigned > > &DIEs = AccelTypes[Name]; DIEs.push_back(Die); } - + /// getDIE - Returns the debug information entry map slot for the /// specified debug variable. DIE *getDIE(const MDNode *N) { return MDNodeToDieMap.lookup(N); } - DIEBlock *getDIEBlock() { + DIEBlock *getDIEBlock() { return new (DIEValueAllocator) DIEBlock(); } @@ -174,11 +182,10 @@ public: void setIndexTyDie(DIE *D) { IndexTyDie = D; } -public: /// addFlag - Add a flag that is true to the DIE. void addFlag(DIE *Die, unsigned Attribute); - + /// addUInt - Add an unsigned integer attribute data and value. /// void addUInt(DIE *Die, unsigned Attribute, unsigned Form, uint64_t Integer); @@ -191,6 +198,10 @@ public: /// void addString(DIE *Die, unsigned Attribute, const StringRef Str); + /// addLocalString - Add a string attribute data and value. + /// + void addLocalString(DIE *Die, unsigned Attribute, const StringRef Str); + /// addLabel - Add a Dwarf label attribute data and value. /// void addLabel(DIE *Die, unsigned Attribute, unsigned Form, @@ -204,7 +215,7 @@ public: /// addDIEEntry - Add a DIE attribute data and value. /// void addDIEEntry(DIE *Die, unsigned Attribute, unsigned Form, DIE *Entry); - + /// addBlock - Add block data. /// void addBlock(DIE *Die, unsigned Attribute, unsigned Form, DIEBlock *Block); @@ -257,7 +268,7 @@ public: void addBlockByrefAddress(DbgVariable *&DV, DIE *Die, unsigned Attribute, const MachineLocation &Location); - /// addVariableAddress - Add DW_AT_location attribute for a + /// addVariableAddress - Add DW_AT_location attribute for a /// DbgVariable based on provided MachineLocation. void addVariableAddress(DbgVariable *&DV, DIE *Die, MachineLocation Location); @@ -279,12 +290,12 @@ public: /// given DIType. DIE *getOrCreateTypeDIE(const MDNode *N); - /// getOrCreateTemplateTypeParameterDIE - Find existing DIE or create new DIE + /// getOrCreateTemplateTypeParameterDIE - Find existing DIE or create new DIE /// for the given DITemplateTypeParameter. DIE *getOrCreateTemplateTypeParameterDIE(DITemplateTypeParameter TP); - /// getOrCreateTemplateValueParameterDIE - Find existing DIE or create new DIE - /// for the given DITemplateValueParameter. + /// getOrCreateTemplateValueParameterDIE - Find existing DIE or create + /// new DIE for the given DITemplateValueParameter. DIE *getOrCreateTemplateValueParameterDIE(DITemplateValueParameter TVP); /// createDIEEntry - Creates a new DIEEntry to be a proxy for a debug @@ -312,7 +323,7 @@ public: void constructSubrangeDIE(DIE &Buffer, DISubrange SR, DIE *IndexTy); /// constructArrayTypeDIE - Construct array type DIE from DICompositeType. - void constructArrayTypeDIE(DIE &Buffer, + void constructArrayTypeDIE(DIE &Buffer, DICompositeType *CTy); /// constructEnumTypeDIE - Construct enum type DIE from DIEnumerator. diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp index 946ac35..66a5a6d 100644 --- a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -16,34 +16,34 @@ #include "DIE.h" #include "DwarfAccelTable.h" #include "DwarfCompileUnit.h" -#include "llvm/Constants.h" -#include "llvm/DebugInfo.h" -#include "llvm/DIBuilder.h" -#include "llvm/Module.h" -#include "llvm/Instructions.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/Triple.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/DIBuilder.h" +#include "llvm/DebugInfo.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/Module.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCSection.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSymbol.h" -#include "llvm/Target/TargetData.h" -#include "llvm/Target/TargetFrameLowering.h" -#include "llvm/Target/TargetLoweringObjectFile.h" -#include "llvm/Target/TargetMachine.h" -#include "llvm/Target/TargetRegisterInfo.h" -#include "llvm/Target/TargetOptions.h" -#include "llvm/ADT/Statistic.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/StringExtras.h" -#include "llvm/ADT/Triple.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/ValueHandle.h" #include "llvm/Support/FormattedStream.h" -#include "llvm/Support/Timer.h" #include "llvm/Support/Path.h" +#include "llvm/Support/Timer.h" +#include "llvm/Support/ValueHandle.h" +#include "llvm/Target/TargetFrameLowering.h" +#include "llvm/Target/TargetLoweringObjectFile.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetOptions.h" +#include "llvm/Target/TargetRegisterInfo.h" using namespace llvm; static cl::opt<bool> DisableDebugInfoPrinting("disable-debug-info-print", @@ -78,6 +78,15 @@ static cl::opt<DefaultOnOff> DarwinGDBCompat("darwin-gdb-compat", cl::Hidden, clEnumValEnd), cl::init(Default)); +static cl::opt<DefaultOnOff> SplitDwarf("split-dwarf", cl::Hidden, + cl::desc("Output prototype dwarf split debug info."), + cl::values( + clEnumVal(Default, "Default for platform"), + clEnumVal(Enable, "Enabled"), + clEnumVal(Disable, "Disabled"), + clEnumValEnd), + cl::init(Default)); + namespace { const char *DWARFGroupName = "DWARF Emission"; const char *DbgTimerName = "DWARF Debug Writer"; @@ -85,8 +94,8 @@ namespace { //===----------------------------------------------------------------------===// -/// Configuration values for initial hash set sizes (log2). -/// +// Configuration values for initial hash set sizes (log2). +// static const unsigned InitAbbreviationsSetSize = 9; // log2(512) namespace llvm { @@ -102,19 +111,19 @@ DIType DbgVariable::getType() const { either the struct, or a pointer to the struct, as its type. This is necessary for various behind-the-scenes things the compiler needs to do with by-reference variables in blocks. - + However, as far as the original *programmer* is concerned, the variable should still have type 'SomeType', as originally declared. - + The following function dives into the __Block_byref_x_VarName struct to find the original type of the variable. This will be passed back to the code generating the type for the Debug Information Entry for the variable 'VarName'. 'VarName' will then have the original type 'SomeType' in its debug information. - + The original type 'SomeType' will be the type of the field named 'VarName' inside the __Block_byref_x_VarName struct. - + NOTE: In order for this to not completely fail on the debugger side, the Debug Information Entry for the variable VarName needs to have a DW_AT_location that tells the debugger how to unwind through @@ -122,15 +131,15 @@ DIType DbgVariable::getType() const { value of the variable. The function addBlockByrefType does this. */ DIType subType = Ty; unsigned tag = Ty.getTag(); - + if (tag == dwarf::DW_TAG_pointer_type) { DIDerivedType DTy = DIDerivedType(Ty); subType = DTy.getTypeDerivedFrom(); } - + DICompositeType blockStruct = DICompositeType(subType); DIArray Elements = blockStruct.getTypeArray(); - + for (unsigned i = 0, N = Elements.getNumElements(); i < N; ++i) { DIDescriptor Element = Elements.getElement(i); DIDerivedType DT = DIDerivedType(Element); @@ -146,45 +155,56 @@ DIType DbgVariable::getType() const { DwarfDebug::DwarfDebug(AsmPrinter *A, Module *M) : Asm(A), MMI(Asm->MMI), FirstCU(0), AbbreviationsSet(InitAbbreviationsSetSize), - SourceIdMap(DIEValueAllocator), StringPool(DIEValueAllocator), - PrevLabel(NULL) { - NextStringPoolNumber = 0; + SourceIdMap(DIEValueAllocator), + PrevLabel(NULL), GlobalCUIndexCount(0), + InfoHolder(A, &AbbreviationsSet, &Abbreviations, "info_string", + DIEValueAllocator), + SkeletonCU(0), + SkeletonAbbrevSet(InitAbbreviationsSetSize), + SkeletonHolder(A, &SkeletonAbbrevSet, &SkeletonAbbrevs, "skel_string", + DIEValueAllocator) { DwarfInfoSectionSym = DwarfAbbrevSectionSym = 0; DwarfStrSectionSym = TextSectionSym = 0; DwarfDebugRangeSectionSym = DwarfDebugLocSectionSym = 0; + DwarfAbbrevDWOSectionSym = DwarfStrDWOSectionSym = 0; FunctionBeginSym = FunctionEndSym = 0; // Turn on accelerator tables and older gdb compatibility // for Darwin. - bool isDarwin = Triple(M->getTargetTriple()).isOSDarwin(); + bool IsDarwin = Triple(M->getTargetTriple()).isOSDarwin(); if (DarwinGDBCompat == Default) { - if (isDarwin) - isDarwinGDBCompat = true; + if (IsDarwin) + IsDarwinGDBCompat = true; else - isDarwinGDBCompat = false; + IsDarwinGDBCompat = false; } else - isDarwinGDBCompat = DarwinGDBCompat == Enable ? true : false; + IsDarwinGDBCompat = DarwinGDBCompat == Enable ? true : false; if (DwarfAccelTables == Default) { - if (isDarwin) - hasDwarfAccelTables = true; + if (IsDarwin) + HasDwarfAccelTables = true; else - hasDwarfAccelTables = false; + HasDwarfAccelTables = false; } else - hasDwarfAccelTables = DwarfAccelTables == Enable ? true : false; + HasDwarfAccelTables = DwarfAccelTables == Enable ? true : false; + + if (SplitDwarf == Default) + HasSplitDwarf = false; + else + HasSplitDwarf = SplitDwarf == Enable ? true : false; { NamedRegionTimer T(DbgTimerName, DWARFGroupName, TimePassesIsEnabled); - beginModule(M); + beginModule(); } } DwarfDebug::~DwarfDebug() { } -/// EmitSectionSym - Switch to the specified MCSection and emit an assembler -/// temporary label to it if SymbolStem is specified. -static MCSymbol *EmitSectionSym(AsmPrinter *Asm, const MCSection *Section, +// Switch to the specified MCSection and emit an assembler +// temporary label to it if SymbolStem is specified. +static MCSymbol *emitSectionSym(AsmPrinter *Asm, const MCSection *Section, const char *SymbolStem = 0) { Asm->OutStreamer.SwitchSection(Section); if (!SymbolStem) return 0; @@ -194,44 +214,55 @@ static MCSymbol *EmitSectionSym(AsmPrinter *Asm, const MCSection *Section, return TmpSym; } -MCSymbol *DwarfDebug::getStringPool() { - return Asm->GetTempSymbol("section_str"); +MCSymbol *DwarfUnits::getStringPoolSym() { + return Asm->GetTempSymbol(StringPref); } -MCSymbol *DwarfDebug::getStringPoolEntry(StringRef Str) { - std::pair<MCSymbol*, unsigned> &Entry = StringPool[Str]; +MCSymbol *DwarfUnits::getStringPoolEntry(StringRef Str) { + std::pair<MCSymbol*, unsigned> &Entry = + StringPool.GetOrCreateValue(Str).getValue(); if (Entry.first) return Entry.first; Entry.second = NextStringPoolNumber++; - return Entry.first = Asm->GetTempSymbol("string", Entry.second); + return Entry.first = Asm->GetTempSymbol(StringPref, Entry.second); } -/// assignAbbrevNumber - Define a unique number for the abbreviation. -/// -void DwarfDebug::assignAbbrevNumber(DIEAbbrev &Abbrev) { +unsigned DwarfUnits::getStringPoolIndex(StringRef Str) { + std::pair<MCSymbol*, unsigned> &Entry = + StringPool.GetOrCreateValue(Str).getValue(); + if (Entry.first) return Entry.second; + + Entry.second = NextStringPoolNumber++; + Entry.first = Asm->GetTempSymbol(StringPref, Entry.second); + return Entry.second; +} + +// Define a unique number for the abbreviation. +// +void DwarfUnits::assignAbbrevNumber(DIEAbbrev &Abbrev) { // Profile the node so that we can make it unique. FoldingSetNodeID ID; Abbrev.Profile(ID); // Check the set for priors. - DIEAbbrev *InSet = AbbreviationsSet.GetOrInsertNode(&Abbrev); + DIEAbbrev *InSet = AbbreviationsSet->GetOrInsertNode(&Abbrev); // If it's newly added. if (InSet == &Abbrev) { // Add to abbreviation list. - Abbreviations.push_back(&Abbrev); + Abbreviations->push_back(&Abbrev); // Assign the vector position + 1 as its number. - Abbrev.setNumber(Abbreviations.size()); + Abbrev.setNumber(Abbreviations->size()); } else { // Assign existing abbreviation number. Abbrev.setNumber(InSet->getNumber()); } } -/// getRealLinkageName - If special LLVM prefix that is used to inform the asm -/// printer to not emit usual symbol prefix before the symbol name is used then -/// return linkage name after skipping this special LLVM prefix. +// If special LLVM prefix that is used to inform the asm +// printer to not emit usual symbol prefix before the symbol name is used then +// return linkage name after skipping this special LLVM prefix. static StringRef getRealLinkageName(StringRef LinkageName) { char One = '\1'; if (LinkageName.startswith(StringRef(&One, 1))) @@ -275,7 +306,7 @@ static StringRef getObjCMethodName(StringRef In) { static void addSubprogramNames(CompileUnit *TheCU, DISubprogram SP, DIE* Die) { if (!SP.isDefinition()) return; - + TheCU->addAccelName(SP.getName(), Die); // If the linkage name is different than the name, go ahead and output @@ -296,10 +327,9 @@ static void addSubprogramNames(CompileUnit *TheCU, DISubprogram SP, } } -/// updateSubprogramScopeDIE - Find DIE for the given subprogram and -/// attach appropriate DW_AT_low_pc and DW_AT_high_pc attributes. -/// If there are global variables in this scope then create and insert -/// DIEs for these variables. +// Find DIE for the given subprogram and attach appropriate DW_AT_low_pc +// and DW_AT_high_pc attributes. If there are global variables in this +// scope then create and insert DIEs for these variables. DIE *DwarfDebug::updateSubprogramScopeDIE(CompileUnit *SPCU, const MDNode *SPNode) { DIE *SPDie = SPCU->getDIE(SPNode); @@ -307,44 +337,51 @@ DIE *DwarfDebug::updateSubprogramScopeDIE(CompileUnit *SPCU, assert(SPDie && "Unable to find subprogram DIE!"); DISubprogram SP(SPNode); - DISubprogram SPDecl = SP.getFunctionDeclaration(); - if (!SPDecl.isSubprogram()) { - // There is not any need to generate specification DIE for a function - // defined at compile unit level. If a function is defined inside another - // function then gdb prefers the definition at top level and but does not - // expect specification DIE in parent function. So avoid creating - // specification DIE for a function defined inside a function. - if (SP.isDefinition() && !SP.getContext().isCompileUnit() && - !SP.getContext().isFile() && - !isSubprogramContext(SP.getContext())) { - SPCU->addFlag(SPDie, dwarf::DW_AT_declaration); - - // Add arguments. - DICompositeType SPTy = SP.getType(); - DIArray Args = SPTy.getTypeArray(); - unsigned SPTag = SPTy.getTag(); - if (SPTag == dwarf::DW_TAG_subroutine_type) - for (unsigned i = 1, N = Args.getNumElements(); i < N; ++i) { - DIE *Arg = new DIE(dwarf::DW_TAG_formal_parameter); - DIType ATy = DIType(DIType(Args.getElement(i))); - SPCU->addType(Arg, ATy); - if (ATy.isArtificial()) - SPCU->addFlag(Arg, dwarf::DW_AT_artificial); - SPDie->addChild(Arg); - } - DIE *SPDeclDie = SPDie; - SPDie = new DIE(dwarf::DW_TAG_subprogram); - SPCU->addDIEEntry(SPDie, dwarf::DW_AT_specification, dwarf::DW_FORM_ref4, - SPDeclDie); - SPCU->addDie(SPDie); - } - } - // Pick up abstract subprogram DIE. + // If we're updating an abstract DIE, then we will be adding the children and + // object pointer later on. But what we don't want to do is process the + // concrete DIE twice. if (DIE *AbsSPDIE = AbstractSPDies.lookup(SPNode)) { + // Pick up abstract subprogram DIE. SPDie = new DIE(dwarf::DW_TAG_subprogram); SPCU->addDIEEntry(SPDie, dwarf::DW_AT_abstract_origin, dwarf::DW_FORM_ref4, AbsSPDIE); SPCU->addDie(SPDie); + } else { + DISubprogram SPDecl = SP.getFunctionDeclaration(); + if (!SPDecl.isSubprogram()) { + // There is not any need to generate specification DIE for a function + // defined at compile unit level. If a function is defined inside another + // function then gdb prefers the definition at top level and but does not + // expect specification DIE in parent function. So avoid creating + // specification DIE for a function defined inside a function. + if (SP.isDefinition() && !SP.getContext().isCompileUnit() && + !SP.getContext().isFile() && + !isSubprogramContext(SP.getContext())) { + SPCU->addFlag(SPDie, dwarf::DW_AT_declaration); + + // Add arguments. + DICompositeType SPTy = SP.getType(); + DIArray Args = SPTy.getTypeArray(); + unsigned SPTag = SPTy.getTag(); + if (SPTag == dwarf::DW_TAG_subroutine_type) + for (unsigned i = 1, N = Args.getNumElements(); i < N; ++i) { + DIE *Arg = new DIE(dwarf::DW_TAG_formal_parameter); + DIType ATy = DIType(Args.getElement(i)); + SPCU->addType(Arg, ATy); + if (ATy.isArtificial()) + SPCU->addFlag(Arg, dwarf::DW_AT_artificial); + if (ATy.isObjectPointer()) + SPCU->addDIEEntry(SPDie, dwarf::DW_AT_object_pointer, + dwarf::DW_FORM_ref4, Arg); + SPDie->addChild(Arg); + } + DIE *SPDeclDie = SPDie; + SPDie = new DIE(dwarf::DW_TAG_subprogram); + SPCU->addDIEEntry(SPDie, dwarf::DW_AT_specification, + dwarf::DW_FORM_ref4, SPDeclDie); + SPCU->addDie(SPDie); + } + } } SPCU->addLabel(SPDie, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr, @@ -358,13 +395,13 @@ DIE *DwarfDebug::updateSubprogramScopeDIE(CompileUnit *SPCU, // Add name to the name table, we do this here because we're guaranteed // to have concrete versions of our DW_TAG_subprogram nodes. addSubprogramNames(SPCU, SP, SPDie); - + return SPDie; } -/// constructLexicalScope - Construct new DW_TAG_lexical_block -/// for this scope and attach DW_AT_low_pc/DW_AT_high_pc labels. -DIE *DwarfDebug::constructLexicalScopeDIE(CompileUnit *TheCU, +// Construct new DW_TAG_lexical_block for this scope and attach +// DW_AT_low_pc/DW_AT_high_pc labels. +DIE *DwarfDebug::constructLexicalScopeDIE(CompileUnit *TheCU, LexicalScope *Scope) { DIE *ScopeDIE = new DIE(dwarf::DW_TAG_lexical_block); if (Scope->isAbstractScope()) @@ -380,8 +417,8 @@ DIE *DwarfDebug::constructLexicalScopeDIE(CompileUnit *TheCU, // .debug_range as a uint, size 4, for now. emitDIE will handle // DW_AT_ranges appropriately. TheCU->addUInt(ScopeDIE, dwarf::DW_AT_ranges, dwarf::DW_FORM_data4, - DebugRangeSymbols.size() - * Asm->getTargetData().getPointerSize()); + DebugRangeSymbols.size() + * Asm->getDataLayout().getPointerSize()); for (SmallVector<InsnRange, 4>::const_iterator RI = Ranges.begin(), RE = Ranges.end(); RI != RE; ++RI) { DebugRangeSymbols.push_back(getLabelBeforeInsn(RI->first)); @@ -406,9 +443,8 @@ DIE *DwarfDebug::constructLexicalScopeDIE(CompileUnit *TheCU, return ScopeDIE; } -/// constructInlinedScopeDIE - This scope represents inlined body of -/// a function. Construct DIE to represent this concrete inlined copy -/// of the function. +// This scope represents inlined body of a function. Construct DIE to +// represent this concrete inlined copy of the function. DIE *DwarfDebug::constructInlinedScopeDIE(CompileUnit *TheCU, LexicalScope *Scope) { const SmallVector<InsnRange, 4> &Ranges = Scope->getRanges(); @@ -421,7 +457,7 @@ DIE *DwarfDebug::constructInlinedScopeDIE(CompileUnit *TheCU, DISubprogram InlinedSP = getDISubprogram(DS); DIE *OriginDIE = TheCU->getDIE(InlinedSP); if (!OriginDIE) { - DEBUG(dbgs() << "Unable to find original DIE for inlined subprogram."); + DEBUG(dbgs() << "Unable to find original DIE for an inlined subprogram."); return NULL; } @@ -430,7 +466,7 @@ DIE *DwarfDebug::constructInlinedScopeDIE(CompileUnit *TheCU, const MCSymbol *EndLabel = getLabelAfterInsn(RI->second); if (StartLabel == 0 || EndLabel == 0) { - llvm_unreachable("Unexpected Start and End labels for a inlined scope!"); + llvm_unreachable("Unexpected Start and End labels for an inlined scope!"); } assert(StartLabel->isDefined() && "Invalid starting label for an inlined scope!"); @@ -446,8 +482,8 @@ DIE *DwarfDebug::constructInlinedScopeDIE(CompileUnit *TheCU, // .debug_range as a uint, size 4, for now. emitDIE will handle // DW_AT_ranges appropriately. TheCU->addUInt(ScopeDIE, dwarf::DW_AT_ranges, dwarf::DW_FORM_data4, - DebugRangeSymbols.size() - * Asm->getTargetData().getPointerSize()); + DebugRangeSymbols.size() + * Asm->getDataLayout().getPointerSize()); for (SmallVector<InsnRange, 4>::const_iterator RI = Ranges.begin(), RE = Ranges.end(); RI != RE; ++RI) { DebugRangeSymbols.push_back(getLabelBeforeInsn(RI->first)); @@ -456,9 +492,9 @@ DIE *DwarfDebug::constructInlinedScopeDIE(CompileUnit *TheCU, DebugRangeSymbols.push_back(NULL); DebugRangeSymbols.push_back(NULL); } else { - TheCU->addLabel(ScopeDIE, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr, + TheCU->addLabel(ScopeDIE, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr, StartLabel); - TheCU->addLabel(ScopeDIE, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr, + TheCU->addLabel(ScopeDIE, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr, EndLabel); } @@ -480,37 +516,42 @@ DIE *DwarfDebug::constructInlinedScopeDIE(CompileUnit *TheCU, DILocation DL(Scope->getInlinedAt()); TheCU->addUInt(ScopeDIE, dwarf::DW_AT_call_file, 0, - GetOrCreateSourceID(DL.getFilename(), DL.getDirectory())); + getOrCreateSourceID(DL.getFilename(), DL.getDirectory())); TheCU->addUInt(ScopeDIE, dwarf::DW_AT_call_line, 0, DL.getLineNumber()); // Add name to the name table, we do this here because we're guaranteed // to have concrete versions of our DW_TAG_inlined_subprogram nodes. addSubprogramNames(TheCU, InlinedSP, ScopeDIE); - + return ScopeDIE; } -/// constructScopeDIE - Construct a DIE for this scope. +// Construct a DIE for this scope. DIE *DwarfDebug::constructScopeDIE(CompileUnit *TheCU, LexicalScope *Scope) { if (!Scope || !Scope->getScopeNode()) return NULL; SmallVector<DIE *, 8> Children; + DIE *ObjectPointer = NULL; // Collect arguments for current function. if (LScopes.isCurrentFunctionScope(Scope)) for (unsigned i = 0, N = CurrentFnArguments.size(); i < N; ++i) if (DbgVariable *ArgDV = CurrentFnArguments[i]) - if (DIE *Arg = - TheCU->constructVariableDIE(ArgDV, Scope->isAbstractScope())) + if (DIE *Arg = + TheCU->constructVariableDIE(ArgDV, Scope->isAbstractScope())) { Children.push_back(Arg); + if (ArgDV->isObjectPointer()) ObjectPointer = Arg; + } // Collect lexical scope children first. const SmallVector<DbgVariable *, 8> &Variables = ScopeVariables.lookup(Scope); for (unsigned i = 0, N = Variables.size(); i < N; ++i) - if (DIE *Variable = - TheCU->constructVariableDIE(Variables[i], Scope->isAbstractScope())) + if (DIE *Variable = + TheCU->constructVariableDIE(Variables[i], Scope->isAbstractScope())) { Children.push_back(Variable); + if (Variables[i]->isObjectPointer()) ObjectPointer = Variable; + } const SmallVector<LexicalScope *, 4> &Scopes = Scope->getChildren(); for (unsigned j = 0, M = Scopes.size(); j < M; ++j) if (DIE *Nested = constructScopeDIE(TheCU, Scopes[j])) @@ -536,7 +577,7 @@ DIE *DwarfDebug::constructScopeDIE(CompileUnit *TheCU, LexicalScope *Scope) { return NULL; ScopeDIE = constructLexicalScopeDIE(TheCU, Scope); } - + if (!ScopeDIE) return NULL; // Add children @@ -544,21 +585,25 @@ DIE *DwarfDebug::constructScopeDIE(CompileUnit *TheCU, LexicalScope *Scope) { E = Children.end(); I != E; ++I) ScopeDIE->addChild(*I); + if (DS.isSubprogram() && ObjectPointer != NULL) + TheCU->addDIEEntry(ScopeDIE, dwarf::DW_AT_object_pointer, + dwarf::DW_FORM_ref4, ObjectPointer); + if (DS.isSubprogram()) TheCU->addPubTypes(DISubprogram(DS)); return ScopeDIE; } -/// GetOrCreateSourceID - Look up the source id with the given directory and -/// source file names. If none currently exists, create a new id and insert it -/// in the SourceIds map. This can update DirectoryNames and SourceFileNames -/// maps as well. -unsigned DwarfDebug::GetOrCreateSourceID(StringRef FileName, +// Look up the source id with the given directory and source file names. +// If none currently exists, create a new id and insert it in the +// SourceIds map. This can update DirectoryNames and SourceFileNames maps +// as well. +unsigned DwarfDebug::getOrCreateSourceID(StringRef FileName, StringRef DirName) { // If FE did not provide a file name, then assume stdin. if (FileName.empty()) - return GetOrCreateSourceID("<stdin>", StringRef()); + return getOrCreateSourceID("<stdin>", StringRef()); // TODO: this might not belong here. See if we can factor this better. if (DirName == CompilationDir) @@ -582,16 +627,20 @@ unsigned DwarfDebug::GetOrCreateSourceID(StringRef FileName, return SrcId; } -/// constructCompileUnit - Create new CompileUnit for the given -/// metadata node with tag DW_TAG_compile_unit. +// Create new CompileUnit for the given metadata node with tag +// DW_TAG_compile_unit. CompileUnit *DwarfDebug::constructCompileUnit(const MDNode *N) { DICompileUnit DIUnit(N); StringRef FN = DIUnit.getFilename(); CompilationDir = DIUnit.getDirectory(); - unsigned ID = GetOrCreateSourceID(FN, CompilationDir); + // Call this to emit a .file directive if it wasn't emitted for the source + // file this CU comes from yet. + getOrCreateSourceID(FN, CompilationDir); DIE *Die = new DIE(dwarf::DW_TAG_compile_unit); - CompileUnit *NewCU = new CompileUnit(ID, DIUnit.getLanguage(), Die, Asm, this); + CompileUnit *NewCU = new CompileUnit(GlobalCUIndexCount++, + DIUnit.getLanguage(), Die, Asm, + this, &InfoHolder); NewCU->addString(Die, dwarf::DW_AT_producer, DIUnit.getProducer()); NewCU->addUInt(Die, dwarf::DW_AT_language, dwarf::DW_FORM_data2, DIUnit.getLanguage()); @@ -615,19 +664,24 @@ CompileUnit *DwarfDebug::constructCompileUnit(const MDNode *N) { StringRef Flags = DIUnit.getFlags(); if (!Flags.empty()) NewCU->addString(Die, dwarf::DW_AT_APPLE_flags, Flags); - + if (unsigned RVer = DIUnit.getRunTimeVersion()) NewCU->addUInt(Die, dwarf::DW_AT_APPLE_major_runtime_vers, dwarf::DW_FORM_data1, RVer); if (!FirstCU) FirstCU = NewCU; + if (useSplitDwarf() && !SkeletonCU) + SkeletonCU = constructSkeletonCU(N); + + InfoHolder.addUnit(NewCU); + CUMap.insert(std::make_pair(N, NewCU)); return NewCU; } -/// construct SubprogramDIE - Construct subprogram DIE. -void DwarfDebug::constructSubprogramDIE(CompileUnit *TheCU, +// Construct subprogram DIE. +void DwarfDebug::constructSubprogramDIE(CompileUnit *TheCU, const MDNode *N) { CompileUnit *&CURef = SPMap[N]; if (CURef) @@ -651,30 +705,29 @@ void DwarfDebug::constructSubprogramDIE(CompileUnit *TheCU, return; } -/// collectInfoFromNamedMDNodes - Collect debug info from named mdnodes such -/// as llvm.dbg.enum and llvm.dbg.ty -void DwarfDebug::collectInfoFromNamedMDNodes(Module *M) { +// Collect debug info from named mdnodes such as llvm.dbg.enum and llvm.dbg.ty. +void DwarfDebug::collectInfoFromNamedMDNodes(const Module *M) { if (NamedMDNode *NMD = M->getNamedMetadata("llvm.dbg.sp")) for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) { const MDNode *N = NMD->getOperand(i); if (CompileUnit *CU = CUMap.lookup(DISubprogram(N).getCompileUnit())) constructSubprogramDIE(CU, N); } - + if (NamedMDNode *NMD = M->getNamedMetadata("llvm.dbg.gv")) for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) { const MDNode *N = NMD->getOperand(i); if (CompileUnit *CU = CUMap.lookup(DIGlobalVariable(N).getCompileUnit())) CU->createGlobalVariableDIE(N); } - + if (NamedMDNode *NMD = M->getNamedMetadata("llvm.dbg.enum")) for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) { DIType Ty(NMD->getOperand(i)); if (CompileUnit *CU = CUMap.lookup(Ty.getCompileUnit())) CU->getOrCreateTypeDIE(Ty); } - + if (NamedMDNode *NMD = M->getNamedMetadata("llvm.dbg.ty")) for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) { DIType Ty(NMD->getOperand(i)); @@ -683,12 +736,12 @@ void DwarfDebug::collectInfoFromNamedMDNodes(Module *M) { } } -/// collectLegacyDebugInfo - Collect debug info using DebugInfoFinder. -/// FIXME - Remove this when dragon-egg and llvm-gcc switch to DIBuilder. -bool DwarfDebug::collectLegacyDebugInfo(Module *M) { +// Collect debug info using DebugInfoFinder. +// FIXME - Remove this when dragonegg switches to DIBuilder. +bool DwarfDebug::collectLegacyDebugInfo(const Module *M) { DebugInfoFinder DbgFinder; DbgFinder.processModule(*M); - + 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. @@ -700,12 +753,12 @@ bool DwarfDebug::collectLegacyDebugInfo(Module *M) { } } if (!HasDebugInfo) return false; - + // Create all the compile unit DIEs. for (DebugInfoFinder::iterator I = DbgFinder.compile_unit_begin(), E = DbgFinder.compile_unit_end(); I != E; ++I) constructCompileUnit(*I); - + // Create DIEs for each global variable. for (DebugInfoFinder::iterator I = DbgFinder.global_variable_begin(), E = DbgFinder.global_variable_end(); I != E; ++I) { @@ -713,7 +766,7 @@ bool DwarfDebug::collectLegacyDebugInfo(Module *M) { if (CompileUnit *CU = CUMap.lookup(DIGlobalVariable(N).getCompileUnit())) CU->createGlobalVariableDIE(N); } - + // Create DIEs for each subprogram. for (DebugInfoFinder::iterator I = DbgFinder.subprogram_begin(), E = DbgFinder.subprogram_end(); I != E; ++I) { @@ -725,13 +778,15 @@ bool DwarfDebug::collectLegacyDebugInfo(Module *M) { return HasDebugInfo; } -/// beginModule - Emit all Dwarf sections that should come prior to the -/// content. Create global DIEs and emit initial debug info sections. -/// This is invoked by the target AsmPrinter. -void DwarfDebug::beginModule(Module *M) { +// Emit all Dwarf sections that should come prior to the content. Create +// global DIEs and emit initial debug info sections. This is invoked by +// the target AsmPrinter. +void DwarfDebug::beginModule() { if (DisableDebugInfoPrinting) return; + const Module *M = MMI->getModule(); + // If module has named metadata anchors then use them, otherwise scan the // module using debug info finder to collect debug info. NamedMDNode *CU_Nodes = M->getNamedMetadata("llvm.dbg.cu"); @@ -756,25 +811,36 @@ void DwarfDebug::beginModule(Module *M) { return; collectInfoFromNamedMDNodes(M); - + // Tell MMI that we have debug info. MMI->setDebugInfoAvailability(true); - - // Emit initial sections. - EmitSectionLabels(); // 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; +// Attach DW_AT_inline attribute with inlined subprogram DIEs. +void DwarfDebug::computeInlinedDIEs() { + // 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; + FirstCU->addUInt(ISP, dwarf::DW_AT_inline, 0, dwarf::DW_INL_inlined); + } + for (DenseMap<const MDNode *, DIE *>::iterator AI = AbstractSPDies.begin(), + AE = AbstractSPDies.end(); AI != AE; ++AI) { + DIE *ISP = AI->second; + if (InlinedSubprogramDIEs.count(ISP)) + continue; + FirstCU->addUInt(ISP, dwarf::DW_AT_inline, 0, dwarf::DW_INL_inlined); + } +} + +// Collect info for variables that were optimized out. +void DwarfDebug::collectDeadVariables() { const Module *M = MMI->getModule(); DenseMap<const MDNode *, LexicalScope *> DeadFnScopeMap; - // Collect info for variables that were optimized out. if (NamedMDNode *CU_Nodes = M->getNamedMetadata("llvm.dbg.cu")) { for (unsigned i = 0, e = CU_Nodes->getNumOperands(); i != e; ++i) { DICompileUnit TheCU(CU_Nodes->getOperand(i)); @@ -787,10 +853,10 @@ void DwarfDebug::endModule() { DIArray Variables = SP.getVariables(); if (Variables.getNumElements() == 0) continue; - LexicalScope *Scope = + LexicalScope *Scope = new LexicalScope(NULL, DIDescriptor(SP), NULL, false); DeadFnScopeMap[SP] = Scope; - + // Construct subprogram DIE and add variables DIEs. CompileUnit *SPCU = CUMap.lookup(TheCU); assert(SPCU && "Unable to find Compile Unit!"); @@ -800,27 +866,22 @@ void DwarfDebug::endModule() { DIVariable DV(Variables.getElement(vi)); if (!DV.Verify()) continue; DbgVariable *NewVar = new DbgVariable(DV, NULL); - if (DIE *VariableDIE = + if (DIE *VariableDIE = SPCU->constructVariableDIE(NewVar, Scope->isAbstractScope())) ScopeDIE->addChild(VariableDIE); } } } } + DeleteContainerSeconds(DeadFnScopeMap); +} + +void DwarfDebug::finalizeModuleInfo() { + // Collect info for variables that were optimized out. + collectDeadVariables(); // 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; - FirstCU->addUInt(ISP, dwarf::DW_AT_inline, 0, dwarf::DW_INL_inlined); - } - for (DenseMap<const MDNode *, DIE *>::iterator AI = AbstractSPDies.begin(), - AE = AbstractSPDies.end(); AI != AE; ++AI) { - DIE *ISP = AI->second; - if (InlinedSubprogramDIEs.count(ISP)) - continue; - FirstCU->addUInt(ISP, dwarf::DW_AT_inline, 0, dwarf::DW_INL_inlined); - } + computeInlinedDIEs(); // Emit DW_AT_containing_type attribute to connect types with their // vtable holding type. @@ -830,6 +891,13 @@ void DwarfDebug::endModule() { TheCU->constructContainingTypeDIEs(); } + // Compute DIE offsets and sizes. + InfoHolder.computeSizeAndOffsets(); + if (useSplitDwarf()) + SkeletonHolder.computeSizeAndOffsets(); +} + +void DwarfDebug::endSections() { // Standard sections final addresses. Asm->OutStreamer.SwitchSection(Asm->getObjFileLowering().getTextSection()); Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("text_end")); @@ -837,19 +905,83 @@ void DwarfDebug::endModule() { 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)); + for (unsigned I = 0, E = SectionMap.size(); I != E; ++I) { + Asm->OutStreamer.SwitchSection(SectionMap[I]); + Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("section_end", I+1)); } +} + +// Emit all Dwarf sections that should come after the content. +void DwarfDebug::endModule() { + + if (!FirstCU) return; + + // End any existing sections. + // TODO: Does this need to happen? + endSections(); + + // Finalize the debug info for the module. + finalizeModuleInfo(); + + // Emit initial sections. + emitSectionLabels(); + + if (!useSplitDwarf()) { + // Emit all the DIEs into a debug info section. + emitDebugInfo(); + + // Corresponding abbreviations into a abbrev section. + emitAbbreviations(); + + // Emit info into a debug loc section. + emitDebugLoc(); + + // Emit info into a debug aranges section. + emitDebugARanges(); - // Compute DIE offsets and sizes. - computeSizeAndOffsets(); + // Emit info into a debug ranges section. + emitDebugRanges(); - // Emit all the DIEs into a debug info section - emitDebugInfo(); + // Emit info into a debug macinfo section. + emitDebugMacInfo(); - // Corresponding abbreviations into a abbrev section. - emitAbbreviations(); + // Emit inline info. + // TODO: When we don't need the option anymore we + // can remove all of the code that this section + // depends upon. + if (useDarwinGDBCompat()) + emitDebugInlineInfo(); + } else { + // TODO: Fill this in for separated debug sections and separate + // out information into new sections. + + // Emit the debug info section and compile units. + emitDebugInfo(); + emitDebugInfoDWO(); + + // Corresponding abbreviations into a abbrev section. + emitAbbreviations(); + emitDebugAbbrevDWO(); + + // Emit info into a debug loc section. + emitDebugLoc(); + + // Emit info into a debug aranges section. + emitDebugARanges(); + + // Emit info into a debug ranges section. + emitDebugRanges(); + + // Emit info into a debug macinfo section. + emitDebugMacInfo(); + + // Emit inline info. + // TODO: When we don't need the option anymore we + // can remove all of the code that this section + // depends upon. + if (useDarwinGDBCompat()) + emitDebugInlineInfo(); + } // Emit info into the dwarf accelerator table sections. if (useDwarfAccelTables()) { @@ -858,45 +990,32 @@ void DwarfDebug::endModule() { emitAccelNamespaces(); emitAccelTypes(); } - + // Emit info into a debug pubtypes section. // TODO: When we don't need the option anymore we can // remove all of the code that adds to the table. if (useDarwinGDBCompat()) emitDebugPubTypes(); - // Emit info into a debug loc section. - emitDebugLoc(); - - // Emit info into a debug aranges section. - EmitDebugARanges(); - - // Emit info into a debug ranges section. - emitDebugRanges(); - - // Emit info into a debug macinfo section. - emitDebugMacInfo(); - - // Emit inline info. - // TODO: When we don't need the option anymore we - // can remove all of the code that this section - // depends upon. - if (useDarwinGDBCompat()) - emitDebugInlineInfo(); - - // Emit info into a debug str section. + // Finally emit string information into a string table. emitDebugStr(); + if (useSplitDwarf()) + emitDebugStrDWO(); // clean up. - DeleteContainerSeconds(DeadFnScopeMap); SPMap.clear(); 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. + + delete SkeletonCU; + + // Reset these for the next Module if we have one. + FirstCU = NULL; + SkeletonCU = NULL; } -/// findAbstractVariable - Find abstract variable, if any, associated with Var. +// Find abstract variable, if any, associated with Var. DbgVariable *DwarfDebug::findAbstractVariable(DIVariable &DV, DebugLoc ScopeLoc) { LLVMContext &Ctx = DV->getContext(); @@ -916,8 +1035,7 @@ DbgVariable *DwarfDebug::findAbstractVariable(DIVariable &DV, return AbsDbgVariable; } -/// addCurrentFnArgument - If Var is a current function argument then add -/// it to CurrentFnArguments list. +// If Var is a current function argument then add it to CurrentFnArguments list. bool DwarfDebug::addCurrentFnArgument(const MachineFunction *MF, DbgVariable *Var, LexicalScope *Scope) { if (!LScopes.isCurrentFunctionScope(Scope)) @@ -926,7 +1044,7 @@ bool DwarfDebug::addCurrentFnArgument(const MachineFunction *MF, if (DV.getTag() != dwarf::DW_TAG_arg_variable) return false; unsigned ArgNo = DV.getArgNumber(); - if (ArgNo == 0) + if (ArgNo == 0) return false; size_t Size = CurrentFnArguments.size(); @@ -940,8 +1058,7 @@ bool DwarfDebug::addCurrentFnArgument(const MachineFunction *MF, return true; } -/// collectVariableInfoFromMMITable - Collect variable information from -/// side table maintained by MMI. +// Collect variable information from side table maintained by MMI. void DwarfDebug::collectVariableInfoFromMMITable(const MachineFunction *MF, SmallPtrSet<const MDNode *, 16> &Processed) { @@ -970,8 +1087,8 @@ DwarfDebug::collectVariableInfoFromMMITable(const MachineFunction *MF, } } -/// isDbgValueInDefinedReg - Return true if debug value, encoded by -/// DBG_VALUE instruction, is in a defined reg. +// 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!"); return MI->getNumOperands() == 3 && @@ -979,10 +1096,9 @@ static bool isDbgValueInDefinedReg(const MachineInstr *MI) { MI->getOperand(1).isImm() && MI->getOperand(1).getImm() == 0; } -/// getDebugLocEntry - Get .debug_loc entry for the instruction range starting -/// at MI. -static DotDebugLocEntry getDebugLocEntry(AsmPrinter *Asm, - const MCSymbol *FLabel, +// Get .debug_loc entry for the instruction range starting at MI. +static DotDebugLocEntry getDebugLocEntry(AsmPrinter *Asm, + const MCSymbol *FLabel, const MCSymbol *SLabel, const MachineInstr *MI) { const MDNode *Var = MI->getOperand(MI->getNumOperands() - 1).getMetadata(); @@ -1006,12 +1122,12 @@ static DotDebugLocEntry getDebugLocEntry(AsmPrinter *Asm, llvm_unreachable("Unexpected 3 operand DBG_VALUE instruction!"); } -/// collectVariableInfo - Find variables for each lexical scope. +// Find variables for each lexical scope. void DwarfDebug::collectVariableInfo(const MachineFunction *MF, SmallPtrSet<const MDNode *, 16> &Processed) { - /// collection info from MMI table. + // collection info from MMI table. collectVariableInfoFromMMITable(MF, Processed); for (SmallVectorImpl<const MDNode*>::const_iterator @@ -1056,7 +1172,7 @@ DwarfDebug::collectVariableInfo(const MachineFunction *MF, if (AbsVar) AbsVar->setMInsn(MInsn); - // Simple ranges that are fully coalesced. + // Simplify ranges that are fully coalesced. if (History.size() <= 1 || (History.size() == 2 && MInsn->isIdenticalTo(History.back()))) { RegVar->setMInsn(MInsn); @@ -1086,7 +1202,7 @@ DwarfDebug::collectVariableInfo(const MachineFunction *MF, SLabel = FunctionEndSym; else { const MachineInstr *End = HI[1]; - DEBUG(dbgs() << "DotDebugLoc Pair:\n" + DEBUG(dbgs() << "DotDebugLoc Pair:\n" << "\t" << *Begin << "\t" << *End << "\n"); if (End->isDebugValue()) SLabel = getLabelBeforeInsn(End); @@ -1117,19 +1233,19 @@ DwarfDebug::collectVariableInfo(const MachineFunction *MF, } } -/// getLabelBeforeInsn - Return Label preceding the instruction. +// Return Label preceding the instruction. const MCSymbol *DwarfDebug::getLabelBeforeInsn(const MachineInstr *MI) { MCSymbol *Label = LabelsBeforeInsn.lookup(MI); assert(Label && "Didn't insert label before instruction"); return Label; } -/// getLabelAfterInsn - Return Label immediately following the instruction. +// Return Label immediately following the instruction. const MCSymbol *DwarfDebug::getLabelAfterInsn(const MachineInstr *MI) { return LabelsAfterInsn.lookup(MI); } -/// beginInstruction - Process beginning of an instruction. +// Process beginning of an instruction. void DwarfDebug::beginInstruction(const MachineInstr *MI) { // Check if source location changes, but ignore DBG_VALUE locations. if (!MI->isDebugValue()) { @@ -1171,7 +1287,7 @@ void DwarfDebug::beginInstruction(const MachineInstr *MI) { I->second = PrevLabel; } -/// endInstruction - Process end of an instruction. +// Process end of an instruction. void DwarfDebug::endInstruction(const MachineInstr *MI) { // Don't create a new label after DBG_VALUE instructions. // They don't generate code. @@ -1197,11 +1313,10 @@ void DwarfDebug::endInstruction(const MachineInstr *MI) { I->second = PrevLabel; } -/// identifyScopeMarkers() - -/// Each LexicalScope 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. +// Each LexicalScope 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. void DwarfDebug::identifyScopeMarkers() { SmallVector<LexicalScope *, 4> WorkList; WorkList.push_back(LScopes.getCurrentFunctionScope()); @@ -1230,15 +1345,15 @@ void DwarfDebug::identifyScopeMarkers() { } } -/// getScopeNode - Get MDNode for DebugLoc's scope. +// Get MDNode for DebugLoc's scope. static MDNode *getScopeNode(DebugLoc DL, const LLVMContext &Ctx) { if (MDNode *InlinedAt = DL.getInlinedAt(Ctx)) return getScopeNode(DebugLoc::getFromDILocation(InlinedAt), Ctx); return DL.getScope(Ctx); } -/// getFnDebugLoc - Walk up the scope chain of given debug loc and find -/// line number info for the function. +// Walk up the scope chain of given debug loc and find line number info +// for the function. static DebugLoc getFnDebugLoc(DebugLoc DL, const LLVMContext &Ctx) { const MDNode *Scope = getScopeNode(DL, Ctx); DISubprogram SP = getDISubprogram(Scope); @@ -1254,8 +1369,8 @@ static DebugLoc getFnDebugLoc(DebugLoc DL, const LLVMContext &Ctx) { return DebugLoc(); } -/// beginFunction - Gather pre-function debug information. Assumes being -/// emitted immediately after the function entry point. +// Gather pre-function debug information. Assumes being called immediately +// after the function entry point has been emitted. void DwarfDebug::beginFunction(const MachineFunction *MF) { if (!MMI->hasDebugInfo()) return; LScopes.initialize(*MF); @@ -1270,7 +1385,7 @@ void DwarfDebug::beginFunction(const MachineFunction *MF) { assert(UserVariables.empty() && DbgValues.empty() && "Maps weren't cleaned"); const TargetRegisterInfo *TRI = Asm->TM.getRegisterInfo(); - /// LiveUserVar - Map physreg numbers to the MDNode they contain. + // LiveUserVar - Map physreg numbers to the MDNode they contain. std::vector<const MDNode*> LiveUserVar(TRI->getNumRegs()); for (MachineFunction::const_iterator I = MF->begin(), E = MF->end(); @@ -1309,8 +1424,8 @@ void DwarfDebug::beginFunction(const MachineFunction *MF) { // Coalesce identical entries at the end of History. if (History.size() >= 2 && Prev->isIdenticalTo(History[History.size() - 2])) { - DEBUG(dbgs() << "Coalesce identical DBG_VALUE entries:\n" - << "\t" << *Prev + DEBUG(dbgs() << "Coalescing identical DBG_VALUE entries:\n" + << "\t" << *Prev << "\t" << *History[History.size() - 2] << "\n"); History.pop_back(); } @@ -1325,7 +1440,7 @@ void DwarfDebug::beginFunction(const MachineFunction *MF) { PrevMBB->getLastNonDebugInstr(); if (LastMI == PrevMBB->end()) { // Drop DBG_VALUE for empty range. - DEBUG(dbgs() << "Drop DBG_VALUE for empty range:\n" + DEBUG(dbgs() << "Dropping DBG_VALUE for empty range:\n" << "\t" << *Prev << "\n"); History.pop_back(); } @@ -1342,9 +1457,10 @@ void DwarfDebug::beginFunction(const MachineFunction *MF) { if (!MI->isLabel()) AtBlockEntry = false; - // First known non DBG_VALUE location marks beginning of function - // body. - if (PrologEndLoc.isUnknown() && !MI->getDebugLoc().isUnknown()) + // First known non-DBG_VALUE and non-frame setup location marks + // the beginning of the function body. + if (!MI->getFlag(MachineInstr::FrameSetup) && + (PrologEndLoc.isUnknown() && !MI->getDebugLoc().isUnknown())) PrologEndLoc = MI->getDebugLoc(); // Check if the instruction clobbers any registers with debug vars. @@ -1395,7 +1511,7 @@ void DwarfDebug::beginFunction(const MachineFunction *MF) { const MachineInstr *Prev = History.back(); if (Prev->isDebugValue() && isDbgValueInDefinedReg(Prev)) { const MachineBasicBlock *PrevMBB = Prev->getParent(); - MachineBasicBlock::const_iterator LastMI = + MachineBasicBlock::const_iterator LastMI = PrevMBB->getLastNonDebugInstr(); if (LastMI == PrevMBB->end()) // Drop DBG_VALUE for empty range. @@ -1424,7 +1540,9 @@ void DwarfDebug::beginFunction(const MachineFunction *MF) { MF->getFunction()->getContext()); recordSourceLine(FnStartDL.getLine(), FnStartDL.getCol(), FnStartDL.getScope(MF->getFunction()->getContext()), - DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0); + // We'd like to list the prologue as "not statements" but GDB behaves + // poorly if we do that. Revisit this with caution/GDB (7.5+) testing. + DWARF2_FLAG_IS_STMT); } } @@ -1434,8 +1552,7 @@ void DwarfDebug::addScopeVariable(LexicalScope *LS, DbgVariable *Var) { // Vars.push_back(Var); } -/// endFunction - Gather and emit post-function debug information. -/// +// Gather and emit post-function debug information. void DwarfDebug::endFunction(const MachineFunction *MF) { if (!MMI->hasDebugInfo() || LScopes.empty()) return; @@ -1444,10 +1561,10 @@ void DwarfDebug::endFunction(const MachineFunction *MF) { Asm->getFunctionNumber()); // Assumes in correct section after the entry point. Asm->OutStreamer.EmitLabel(FunctionEndSym); - + SmallPtrSet<const MDNode *, 16> ProcessedVars; collectVariableInfo(MF, ProcessedVars); - + LexicalScope *FnScope = LScopes.getCurrentFunctionScope(); CompileUnit *TheCU = SPMap.lookup(FnScope->getScopeNode()); assert(TheCU && "Unable to find compile unit!"); @@ -1477,9 +1594,9 @@ void DwarfDebug::endFunction(const MachineFunction *MF) { if (ProcessedSPNodes.count(AScope->getScopeNode()) == 0) constructScopeDIE(TheCU, AScope); } - + DIE *CurFnDIE = constructScopeDIE(TheCU, FnScope); - + if (!MF->getTarget().Options.DisableFramePointerElim(*MF)) TheCU->addFlag(CurFnDIE, dwarf::DW_AT_APPLE_omit_frame_ptr); @@ -1500,9 +1617,8 @@ void DwarfDebug::endFunction(const MachineFunction *MF) { PrevLabel = NULL; } -/// recordSourceLine - Register a source line with debug info. Returns the -/// unique label that was emitted and which provides correspondence to -/// the source line list. +// Register a source line with debug info. Returns the unique label that was +// emitted and which provides correspondence to the source line list. void DwarfDebug::recordSourceLine(unsigned Line, unsigned Col, const MDNode *S, unsigned Flags) { StringRef Fn; @@ -1534,7 +1650,7 @@ void DwarfDebug::recordSourceLine(unsigned Line, unsigned Col, const MDNode *S, } else llvm_unreachable("Unexpected scope info"); - Src = GetOrCreateSourceID(Fn, Dir); + Src = getOrCreateSourceID(Fn, Dir); } Asm->OutStreamer.EmitDwarfLocDirective(Src, Line, Col, Flags, 0, 0, Fn); } @@ -1543,10 +1659,9 @@ void DwarfDebug::recordSourceLine(unsigned Line, unsigned Col, const MDNode *S, // Emit Methods //===----------------------------------------------------------------------===// -/// computeSizeAndOffset - Compute the size and offset of a DIE. -/// +// Compute the size and offset of a DIE. unsigned -DwarfDebug::computeSizeAndOffset(DIE *Die, unsigned Offset, bool Last) { +DwarfUnits::computeSizeAndOffset(DIE *Die, unsigned Offset) { // Get the children. const std::vector<DIE *> &Children = Die->getChildren(); @@ -1555,7 +1670,7 @@ DwarfDebug::computeSizeAndOffset(DIE *Die, unsigned Offset, bool Last) { // Get the abbreviation for this DIE. unsigned AbbrevNumber = Die->getAbbrevNumber(); - const DIEAbbrev *Abbrev = Abbreviations[AbbrevNumber - 1]; + const DIEAbbrev *Abbrev = Abbreviations->at(AbbrevNumber - 1); // Set DIE offset Die->setOffset(Offset); @@ -1577,7 +1692,7 @@ DwarfDebug::computeSizeAndOffset(DIE *Die, unsigned Offset, bool Last) { "Children flag not set"); for (unsigned j = 0, M = Children.size(); j < M; ++j) - Offset = computeSizeAndOffset(Children[j], Offset, (j + 1) == M); + Offset = computeSizeAndOffset(Children[j], Offset); // End of children marker. Offset += sizeof(int8_t); @@ -1587,57 +1702,61 @@ DwarfDebug::computeSizeAndOffset(DIE *Die, unsigned Offset, bool Last) { return Offset; } -/// computeSizeAndOffsets - Compute the size and offset of all the DIEs. -/// -void DwarfDebug::computeSizeAndOffsets() { - for (DenseMap<const MDNode *, CompileUnit *>::iterator I = CUMap.begin(), - E = CUMap.end(); I != E; ++I) { - // Compute size of compile unit header. - unsigned Offset = +// Compute the size and offset of all the DIEs. +void DwarfUnits::computeSizeAndOffsets() { + for (SmallVector<CompileUnit *, 1>::iterator I = CUs.begin(), + E = CUs.end(); I != E; ++I) { + unsigned Offset = sizeof(int32_t) + // Length of Compilation Unit Info sizeof(int16_t) + // DWARF version number sizeof(int32_t) + // Offset Into Abbrev. Section sizeof(int8_t); // Pointer Size (in bytes) - computeSizeAndOffset(I->second->getCUDie(), Offset, true); + + computeSizeAndOffset((*I)->getCUDie(), Offset); } } -/// EmitSectionLabels - Emit initial Dwarf sections with a label at -/// the start of each one. -void DwarfDebug::EmitSectionLabels() { +// Emit initial Dwarf sections with a label at the start of each one. +void DwarfDebug::emitSectionLabels() { const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering(); // Dwarf sections base addresses. DwarfInfoSectionSym = - EmitSectionSym(Asm, TLOF.getDwarfInfoSection(), "section_info"); + emitSectionSym(Asm, TLOF.getDwarfInfoSection(), "section_info"); DwarfAbbrevSectionSym = - EmitSectionSym(Asm, TLOF.getDwarfAbbrevSection(), "section_abbrev"); - EmitSectionSym(Asm, TLOF.getDwarfARangesSection()); + emitSectionSym(Asm, TLOF.getDwarfAbbrevSection(), "section_abbrev"); + if (useSplitDwarf()) + DwarfAbbrevDWOSectionSym = + emitSectionSym(Asm, TLOF.getDwarfAbbrevDWOSection(), + "section_abbrev_dwo"); + emitSectionSym(Asm, TLOF.getDwarfARangesSection()); if (const MCSection *MacroInfo = TLOF.getDwarfMacroInfoSection()) - EmitSectionSym(Asm, MacroInfo); + emitSectionSym(Asm, MacroInfo); - EmitSectionSym(Asm, TLOF.getDwarfLineSection(), "section_line"); - EmitSectionSym(Asm, TLOF.getDwarfLocSection()); - EmitSectionSym(Asm, TLOF.getDwarfPubTypesSection()); + emitSectionSym(Asm, TLOF.getDwarfLineSection(), "section_line"); + emitSectionSym(Asm, TLOF.getDwarfLocSection()); + emitSectionSym(Asm, TLOF.getDwarfPubTypesSection()); DwarfStrSectionSym = - EmitSectionSym(Asm, TLOF.getDwarfStrSection(), "section_str"); - DwarfDebugRangeSectionSym = EmitSectionSym(Asm, TLOF.getDwarfRangesSection(), + emitSectionSym(Asm, TLOF.getDwarfStrSection(), "info_string"); + if (useSplitDwarf()) + DwarfStrDWOSectionSym = + emitSectionSym(Asm, TLOF.getDwarfStrDWOSection(), "skel_string"); + DwarfDebugRangeSectionSym = emitSectionSym(Asm, TLOF.getDwarfRangesSection(), "debug_range"); - DwarfDebugLocSectionSym = EmitSectionSym(Asm, TLOF.getDwarfLocSection(), + DwarfDebugLocSectionSym = emitSectionSym(Asm, TLOF.getDwarfLocSection(), "section_debug_loc"); - TextSectionSym = EmitSectionSym(Asm, TLOF.getTextSection(), "text_begin"); - EmitSectionSym(Asm, TLOF.getDataSection()); + TextSectionSym = emitSectionSym(Asm, TLOF.getTextSection(), "text_begin"); + emitSectionSym(Asm, TLOF.getDataSection()); } -/// emitDIE - Recursively emits a debug information entry. -/// -void DwarfDebug::emitDIE(DIE *Die) { +// Recursively emits a debug information entry. +void DwarfDebug::emitDIE(DIE *Die, std::vector<DIEAbbrev *> *Abbrevs) { // Get the abbreviation for this DIE. unsigned AbbrevNumber = Die->getAbbrevNumber(); - const DIEAbbrev *Abbrev = Abbreviations[AbbrevNumber - 1]; + const DIEAbbrev *Abbrev = Abbrevs->at(AbbrevNumber - 1); // Emit the code (index) for the abbreviation. if (Asm->isVerbose()) @@ -1714,7 +1833,7 @@ void DwarfDebug::emitDIE(DIE *Die) { const std::vector<DIE *> &Children = Die->getChildren(); for (unsigned j = 0, M = Children.size(); j < M; ++j) - emitDIE(Children[j]); + emitDIE(Children[j], Abbrevs); if (Asm->isVerbose()) Asm->OutStreamer.AddComment("End Of Children Mark"); @@ -1722,20 +1841,22 @@ void DwarfDebug::emitDIE(DIE *Die) { } } -/// emitDebugInfo - Emit the debug info section. -/// -void DwarfDebug::emitDebugInfo() { - // Start debug info section. - Asm->OutStreamer.SwitchSection( - Asm->getObjFileLowering().getDwarfInfoSection()); - for (DenseMap<const MDNode *, CompileUnit *>::iterator I = CUMap.begin(), - E = CUMap.end(); I != E; ++I) { - CompileUnit *TheCU = I->second; +// Emit the various dwarf units to the unit section USection with +// the abbreviations going into ASection. +void DwarfUnits::emitUnits(DwarfDebug *DD, + const MCSection *USection, + const MCSection *ASection, + const MCSymbol *ASectionSym) { + Asm->OutStreamer.SwitchSection(USection); + for (SmallVector<CompileUnit *, 1>::iterator I = CUs.begin(), + E = CUs.end(); I != E; ++I) { + CompileUnit *TheCU = *I; DIE *Die = TheCU->getCUDie(); // Emit the compile units header. - Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("info_begin", - TheCU->getID())); + Asm->OutStreamer + .EmitLabel(Asm->GetTempSymbol(USection->getLabelBeginName(), + TheCU->getUniqueID())); // Emit size of content not including length itself unsigned ContentSize = Die->getSize() + @@ -1748,31 +1869,49 @@ void DwarfDebug::emitDebugInfo() { Asm->OutStreamer.AddComment("DWARF version number"); Asm->EmitInt16(dwarf::DWARF_VERSION); Asm->OutStreamer.AddComment("Offset Into Abbrev. Section"); - Asm->EmitSectionOffset(Asm->GetTempSymbol("abbrev_begin"), - DwarfAbbrevSectionSym); + Asm->EmitSectionOffset(Asm->GetTempSymbol(ASection->getLabelBeginName()), + ASectionSym); Asm->OutStreamer.AddComment("Address Size (in bytes)"); - Asm->EmitInt8(Asm->getTargetData().getPointerSize()); + Asm->EmitInt8(Asm->getDataLayout().getPointerSize()); - emitDIE(Die); - Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("info_end", TheCU->getID())); + DD->emitDIE(Die, Abbreviations); + Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol(USection->getLabelEndName(), + TheCU->getUniqueID())); } } -/// emitAbbreviations - Emit the abbreviation section. -/// -void DwarfDebug::emitAbbreviations() const { +// Emit the debug info section. +void DwarfDebug::emitDebugInfo() { + DwarfUnits &Holder = useSplitDwarf() ? SkeletonHolder : InfoHolder; + + Holder.emitUnits(this, Asm->getObjFileLowering().getDwarfInfoSection(), + Asm->getObjFileLowering().getDwarfAbbrevSection(), + DwarfAbbrevSectionSym); +} + +// Emit the abbreviation section. +void DwarfDebug::emitAbbreviations() { + if (!useSplitDwarf()) + emitAbbrevs(Asm->getObjFileLowering().getDwarfAbbrevSection(), + &Abbreviations); + else + emitSkeletonAbbrevs(Asm->getObjFileLowering().getDwarfAbbrevSection()); +} + +void DwarfDebug::emitAbbrevs(const MCSection *Section, + std::vector<DIEAbbrev *> *Abbrevs) { // Check to see if it is worth the effort. - if (!Abbreviations.empty()) { + if (!Abbrevs->empty()) { // Start the debug abbrev section. - Asm->OutStreamer.SwitchSection( - Asm->getObjFileLowering().getDwarfAbbrevSection()); + Asm->OutStreamer.SwitchSection(Section); - Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("abbrev_begin")); + MCSymbol *Begin = Asm->GetTempSymbol(Section->getLabelBeginName()); + Asm->OutStreamer.EmitLabel(Begin); // For each abbrevation. - for (unsigned i = 0, N = Abbreviations.size(); i < N; ++i) { + for (unsigned i = 0, N = Abbrevs->size(); i < N; ++i) { // Get abbreviation data - const DIEAbbrev *Abbrev = Abbreviations[i]; + const DIEAbbrev *Abbrev = Abbrevs->at(i); // Emit the abbrevations code (base 1 index.) Asm->EmitULEB128(Abbrev->getNumber(), "Abbreviation Code"); @@ -1784,27 +1923,26 @@ void DwarfDebug::emitAbbreviations() const { // Mark end of abbreviations. Asm->EmitULEB128(0, "EOM(3)"); - Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("abbrev_end")); + MCSymbol *End = Asm->GetTempSymbol(Section->getLabelEndName()); + Asm->OutStreamer.EmitLabel(End); } } -/// emitEndOfLineMatrix - Emit the last address of the section and the end of -/// the line matrix. -/// +// Emit the last address of the section and the end of the line matrix. void DwarfDebug::emitEndOfLineMatrix(unsigned SectionEnd) { // Define last address of section. Asm->OutStreamer.AddComment("Extended Op"); Asm->EmitInt8(0); Asm->OutStreamer.AddComment("Op size"); - Asm->EmitInt8(Asm->getTargetData().getPointerSize() + 1); + Asm->EmitInt8(Asm->getDataLayout().getPointerSize() + 1); Asm->OutStreamer.AddComment("DW_LNE_set_address"); Asm->EmitInt8(dwarf::DW_LNE_set_address); Asm->OutStreamer.AddComment("Section end label"); Asm->OutStreamer.EmitSymbolValue(Asm->GetTempSymbol("section_end",SectionEnd), - Asm->getTargetData().getPointerSize(), + Asm->getDataLayout().getPointerSize(), 0/*AddrSpace*/); // Mark end of matrix. @@ -1814,8 +1952,7 @@ void DwarfDebug::emitEndOfLineMatrix(unsigned SectionEnd) { Asm->EmitInt8(1); } -/// emitAccelNames - Emit visible names into a hashed accelerator table -/// section. +// Emit visible names into a hashed accelerator table section. void DwarfDebug::emitAccelNames() { DwarfAccelTable AT(DwarfAccelTable::Atom(DwarfAccelTable::eAtomTypeDIEOffset, dwarf::DW_FORM_data4)); @@ -1840,11 +1977,11 @@ void DwarfDebug::emitAccelNames() { Asm->OutStreamer.EmitLabel(SectionBegin); // Emit the full data. - AT.Emit(Asm, SectionBegin, this); + AT.Emit(Asm, SectionBegin, &InfoHolder); } -/// emitAccelObjC - Emit objective C classes and categories into a hashed -/// accelerator table section. +// Emit objective C classes and categories into a hashed accelerator table +// section. void DwarfDebug::emitAccelObjC() { DwarfAccelTable AT(DwarfAccelTable::Atom(DwarfAccelTable::eAtomTypeDIEOffset, dwarf::DW_FORM_data4)); @@ -1869,11 +2006,10 @@ void DwarfDebug::emitAccelObjC() { Asm->OutStreamer.EmitLabel(SectionBegin); // Emit the full data. - AT.Emit(Asm, SectionBegin, this); + AT.Emit(Asm, SectionBegin, &InfoHolder); } -/// emitAccelNamespace - Emit namespace dies into a hashed accelerator -/// table. +// Emit namespace dies into a hashed accelerator table. void DwarfDebug::emitAccelNamespaces() { DwarfAccelTable AT(DwarfAccelTable::Atom(DwarfAccelTable::eAtomTypeDIEOffset, dwarf::DW_FORM_data4)); @@ -1898,10 +2034,10 @@ void DwarfDebug::emitAccelNamespaces() { Asm->OutStreamer.EmitLabel(SectionBegin); // Emit the full data. - AT.Emit(Asm, SectionBegin, this); + AT.Emit(Asm, SectionBegin, &InfoHolder); } -/// emitAccelTypes() - Emit type dies into a hashed accelerator table. +// Emit type dies into a hashed accelerator table. void DwarfDebug::emitAccelTypes() { std::vector<DwarfAccelTable::Atom> Atoms; Atoms.push_back(DwarfAccelTable::Atom(DwarfAccelTable::eAtomTypeDIEOffset, @@ -1933,7 +2069,7 @@ void DwarfDebug::emitAccelTypes() { Asm->OutStreamer.EmitLabel(SectionBegin); // Emit the full data. - AT.Emit(Asm, SectionBegin, this); + AT.Emit(Asm, SectionBegin, &InfoHolder); } void DwarfDebug::emitDebugPubTypes() { @@ -1945,22 +2081,26 @@ void DwarfDebug::emitDebugPubTypes() { Asm->getObjFileLowering().getDwarfPubTypesSection()); Asm->OutStreamer.AddComment("Length of Public Types Info"); Asm->EmitLabelDifference( - Asm->GetTempSymbol("pubtypes_end", TheCU->getID()), - Asm->GetTempSymbol("pubtypes_begin", TheCU->getID()), 4); + Asm->GetTempSymbol("pubtypes_end", TheCU->getUniqueID()), + Asm->GetTempSymbol("pubtypes_begin", TheCU->getUniqueID()), 4); Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("pubtypes_begin", - TheCU->getID())); + TheCU->getUniqueID())); if (Asm->isVerbose()) Asm->OutStreamer.AddComment("DWARF Version"); Asm->EmitInt16(dwarf::DWARF_VERSION); Asm->OutStreamer.AddComment("Offset of Compilation Unit Info"); - Asm->EmitSectionOffset(Asm->GetTempSymbol("info_begin", TheCU->getID()), + const MCSection *ISec = Asm->getObjFileLowering().getDwarfInfoSection(); + Asm->EmitSectionOffset(Asm->GetTempSymbol(ISec->getLabelBeginName(), + TheCU->getUniqueID()), DwarfInfoSectionSym); Asm->OutStreamer.AddComment("Compilation Unit Length"); - Asm->EmitLabelDifference(Asm->GetTempSymbol("info_end", TheCU->getID()), - Asm->GetTempSymbol("info_begin", TheCU->getID()), + Asm->EmitLabelDifference(Asm->GetTempSymbol(ISec->getLabelEndName(), + TheCU->getUniqueID()), + Asm->GetTempSymbol(ISec->getLabelBeginName(), + TheCU->getUniqueID()), 4); const StringMap<DIE*> &Globals = TheCU->getGlobalTypes(); @@ -1980,27 +2120,28 @@ void DwarfDebug::emitDebugPubTypes() { Asm->OutStreamer.AddComment("End Mark"); Asm->EmitInt32(0); Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("pubtypes_end", - TheCU->getID())); + TheCU->getUniqueID())); } } -/// emitDebugStr - Emit visible names into a debug str section. -/// -void DwarfDebug::emitDebugStr() { - // Check to see if it is worth the effort. +// Emit strings into a string section. +void DwarfUnits::emitStrings(const MCSection *StrSection, + const MCSection *OffsetSection = NULL, + const MCSymbol *StrSecSym = NULL) { + if (StringPool.empty()) return; // Start the dwarf str section. - Asm->OutStreamer.SwitchSection( - Asm->getObjFileLowering().getDwarfStrSection()); + Asm->OutStreamer.SwitchSection(StrSection); // Get all of the string pool entries and put them in an array by their ID so // we can sort them. SmallVector<std::pair<unsigned, - StringMapEntry<std::pair<MCSymbol*, unsigned> >*>, 64> Entries; + StringMapEntry<std::pair<MCSymbol*, unsigned> >*>, 64> Entries; for (StringMap<std::pair<MCSymbol*, unsigned> >::iterator - I = StringPool.begin(), E = StringPool.end(); I != E; ++I) + I = StringPool.begin(), E = StringPool.end(); + I != E; ++I) Entries.push_back(std::make_pair(I->second.second, &*I)); array_pod_sort(Entries.begin(), Entries.end()); @@ -2014,10 +2155,26 @@ void DwarfDebug::emitDebugStr() { Entries[i].second->getKeyLength()+1), 0/*addrspace*/); } + + // If we've got an offset section go ahead and emit that now as well. + if (OffsetSection) { + Asm->OutStreamer.SwitchSection(OffsetSection); + unsigned offset = 0; + unsigned size = 4; + for (unsigned i = 0, e = Entries.size(); i != e; ++i) { + Asm->OutStreamer.EmitIntValue(offset, size, 0); + offset += Entries[i].second->getKeyLength() + 1; + } + } +} + +// Emit visible names into a debug str section. +void DwarfDebug::emitDebugStr() { + DwarfUnits &Holder = useSplitDwarf() ? SkeletonHolder : InfoHolder; + Holder.emitStrings(Asm->getObjFileLowering().getDwarfStrSection()); } -/// emitDebugLoc - Emit visible names into a debug loc section. -/// +// Emit visible names into a debug loc section. void DwarfDebug::emitDebugLoc() { if (DotDebugLocEntries.empty()) return; @@ -2033,7 +2190,7 @@ void DwarfDebug::emitDebugLoc() { // Start the dwarf loc section. Asm->OutStreamer.SwitchSection( Asm->getObjFileLowering().getDwarfLocSection()); - unsigned char Size = Asm->getTargetData().getPointerSize(); + unsigned char Size = Asm->getDataLayout().getPointerSize(); Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("debug_loc", 0)); unsigned index = 1; for (SmallVector<DotDebugLocEntry, 4>::iterator @@ -2057,7 +2214,7 @@ void DwarfDebug::emitDebugLoc() { if (Entry.isInt()) { DIBasicType BTy(DV.getType()); if (BTy.Verify() && - (BTy.getEncoding() == dwarf::DW_ATE_signed + (BTy.getEncoding() == dwarf::DW_ATE_signed || BTy.getEncoding() == dwarf::DW_ATE_signed_char)) { Asm->OutStreamer.AddComment("DW_OP_consts"); Asm->EmitInt8(dwarf::DW_OP_consts); @@ -2068,7 +2225,7 @@ void DwarfDebug::emitDebugLoc() { Asm->EmitULEB128(Entry.getInt()); } } else if (Entry.isLocation()) { - if (!DV.hasComplexAddress()) + if (!DV.hasComplexAddress()) // Regular entry. Asm->EmitDwarfRegOp(Entry.Loc); else { @@ -2094,7 +2251,7 @@ void DwarfDebug::emitDebugLoc() { } else { Asm->EmitDwarfRegOp(Entry.Loc); } - + // Emit remaining complex address elements. for (; i < N; ++i) { uint64_t Element = DV.getAddrElement(i); @@ -2116,21 +2273,19 @@ void DwarfDebug::emitDebugLoc() { } } -/// EmitDebugARanges - Emit visible names into a debug aranges section. -/// -void DwarfDebug::EmitDebugARanges() { +// Emit visible names into a debug aranges section. +void DwarfDebug::emitDebugARanges() { // Start the dwarf aranges section. Asm->OutStreamer.SwitchSection( Asm->getObjFileLowering().getDwarfARangesSection()); } -/// emitDebugRanges - Emit visible names into a debug ranges section. -/// +// Emit visible names into a debug ranges section. void DwarfDebug::emitDebugRanges() { // Start the dwarf ranges section. Asm->OutStreamer.SwitchSection( Asm->getObjFileLowering().getDwarfRangesSection()); - unsigned char Size = Asm->getTargetData().getPointerSize(); + unsigned char Size = Asm->getDataLayout().getPointerSize(); for (SmallVector<const MCSymbol *, 8>::iterator I = DebugRangeSymbols.begin(), E = DebugRangeSymbols.end(); I != E; ++I) { @@ -2141,8 +2296,7 @@ void DwarfDebug::emitDebugRanges() { } } -/// emitDebugMacInfo - Emit visible names into a debug macinfo section. -/// +// Emit visible names into a debug macinfo section. void DwarfDebug::emitDebugMacInfo() { if (const MCSection *LineInfo = Asm->getObjFileLowering().getDwarfMacroInfoSection()) { @@ -2151,24 +2305,24 @@ void DwarfDebug::emitDebugMacInfo() { } } -/// emitDebugInlineInfo - Emit inline info using following format. -/// Section Header: -/// 1. length of section -/// 2. Dwarf version number -/// 3. address size. -/// -/// Entries (one "entry" for each function that was inlined): -/// -/// 1. offset into __debug_str section for MIPS linkage name, if exists; -/// otherwise offset into __debug_str for regular function name. -/// 2. offset into __debug_str section for regular function name. -/// 3. an unsigned LEB128 number indicating the number of distinct inlining -/// instances for the function. -/// -/// The rest of the entry consists of a {die_offset, low_pc} pair for each -/// inlined instance; the die_offset points to the inlined_subroutine die in the -/// __debug_info section, and the low_pc is the starting address for the -/// inlining instance. +// Emit inline info using following format. +// Section Header: +// 1. length of section +// 2. Dwarf version number +// 3. address size. +// +// Entries (one "entry" for each function that was inlined): +// +// 1. offset into __debug_str section for MIPS linkage name, if exists; +// otherwise offset into __debug_str for regular function name. +// 2. offset into __debug_str section for regular function name. +// 3. an unsigned LEB128 number indicating the number of distinct inlining +// instances for the function. +// +// The rest of the entry consists of a {die_offset, low_pc} pair for each +// inlined instance; the die_offset points to the inlined_subroutine die in the +// __debug_info section, and the low_pc is the starting address for the +// inlining instance. void DwarfDebug::emitDebugInlineInfo() { if (!Asm->MAI->doesDwarfUseInlineInfoSection()) return; @@ -2188,7 +2342,7 @@ void DwarfDebug::emitDebugInlineInfo() { Asm->OutStreamer.AddComment("Dwarf Version"); Asm->EmitInt16(dwarf::DWARF_VERSION); Asm->OutStreamer.AddComment("Address Size (in bytes)"); - Asm->EmitInt8(Asm->getTargetData().getPointerSize()); + Asm->EmitInt8(Asm->getDataLayout().getPointerSize()); for (SmallVector<const MDNode *, 4>::iterator I = InlinedSPNodes.begin(), E = InlinedSPNodes.end(); I != E; ++I) { @@ -2203,13 +2357,16 @@ void DwarfDebug::emitDebugInlineInfo() { Asm->OutStreamer.AddComment("MIPS linkage name"); if (LName.empty()) - Asm->EmitSectionOffset(getStringPoolEntry(Name), DwarfStrSectionSym); + Asm->EmitSectionOffset(InfoHolder.getStringPoolEntry(Name), + DwarfStrSectionSym); else - Asm->EmitSectionOffset(getStringPoolEntry(getRealLinkageName(LName)), + Asm->EmitSectionOffset(InfoHolder + .getStringPoolEntry(getRealLinkageName(LName)), DwarfStrSectionSym); Asm->OutStreamer.AddComment("Function name"); - Asm->EmitSectionOffset(getStringPoolEntry(Name), DwarfStrSectionSym); + Asm->EmitSectionOffset(InfoHolder.getStringPoolEntry(Name), + DwarfStrSectionSym); Asm->EmitULEB128(Labels.size(), "Inline count"); for (SmallVector<InlineInfoLabels, 4>::iterator LI = Labels.begin(), @@ -2219,9 +2376,113 @@ void DwarfDebug::emitDebugInlineInfo() { if (Asm->isVerbose()) Asm->OutStreamer.AddComment("low_pc"); Asm->OutStreamer.EmitSymbolValue(LI->first, - Asm->getTargetData().getPointerSize(),0); + Asm->getDataLayout().getPointerSize(),0); } } Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("debug_inlined_end", 1)); } + +// DWARF5 Experimental Separate Dwarf emitters. + +// This DIE has the following attributes: DW_AT_comp_dir, DW_AT_stmt_list, +// DW_AT_low_pc, DW_AT_high_pc, DW_AT_ranges, DW_AT_dwo_name, DW_AT_dwo_id, +// DW_AT_ranges_base, DW_AT_addr_base. If DW_AT_ranges is present, +// DW_AT_low_pc and DW_AT_high_pc are not used, and vice versa. +CompileUnit *DwarfDebug::constructSkeletonCU(const MDNode *N) { + DICompileUnit DIUnit(N); + StringRef FN = DIUnit.getFilename(); + CompilationDir = DIUnit.getDirectory(); + + DIE *Die = new DIE(dwarf::DW_TAG_compile_unit); + CompileUnit *NewCU = new CompileUnit(GlobalCUIndexCount++, + DIUnit.getLanguage(), Die, Asm, + this, &SkeletonHolder); + // FIXME: This should be the .dwo file. + NewCU->addLocalString(Die, dwarf::DW_AT_GNU_dwo_name, FN); + + // FIXME: We also need DW_AT_addr_base and DW_AT_dwo_id. + + // 2.17.1 requires that we use DW_AT_low_pc for a single entry point + // into an entity. + NewCU->addUInt(Die, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr, 0); + // DW_AT_stmt_list is a offset of line number information for this + // compile unit in debug_line section. + if (Asm->MAI->doesDwarfUseRelocationsAcrossSections()) + NewCU->addLabel(Die, dwarf::DW_AT_stmt_list, dwarf::DW_FORM_data4, + Asm->GetTempSymbol("section_line")); + else + NewCU->addUInt(Die, dwarf::DW_AT_stmt_list, dwarf::DW_FORM_data4, 0); + + if (!CompilationDir.empty()) + NewCU->addLocalString(Die, dwarf::DW_AT_comp_dir, CompilationDir); + + SkeletonHolder.addUnit(NewCU); + + return NewCU; +} + +void DwarfDebug::emitSkeletonCU(const MCSection *Section) { + Asm->OutStreamer.SwitchSection(Section); + DIE *Die = SkeletonCU->getCUDie(); + + // Emit the compile units header. + Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol(Section->getLabelBeginName(), + SkeletonCU->getUniqueID())); + + // Emit size of content not including length itself + unsigned ContentSize = Die->getSize() + + sizeof(int16_t) + // DWARF version number + sizeof(int32_t) + // Offset Into Abbrev. Section + sizeof(int8_t); // Pointer Size (in bytes) + + Asm->OutStreamer.AddComment("Length of Compilation Unit Info"); + Asm->EmitInt32(ContentSize); + Asm->OutStreamer.AddComment("DWARF version number"); + Asm->EmitInt16(dwarf::DWARF_VERSION); + Asm->OutStreamer.AddComment("Offset Into Abbrev. Section"); + + const MCSection *ASec = Asm->getObjFileLowering().getDwarfAbbrevSection(); + Asm->EmitSectionOffset(Asm->GetTempSymbol(ASec->getLabelBeginName()), + DwarfAbbrevSectionSym); + Asm->OutStreamer.AddComment("Address Size (in bytes)"); + Asm->EmitInt8(Asm->getDataLayout().getPointerSize()); + + emitDIE(Die, &SkeletonAbbrevs); + Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol(Section->getLabelEndName(), + SkeletonCU->getUniqueID())); +} + +void DwarfDebug::emitSkeletonAbbrevs(const MCSection *Section) { + assert(useSplitDwarf() && "No split dwarf debug info?"); + emitAbbrevs(Section, &SkeletonAbbrevs); +} + +// Emit the .debug_info.dwo section for separated dwarf. This contains the +// compile units that would normally be in debug_info. +void DwarfDebug::emitDebugInfoDWO() { + assert(useSplitDwarf() && "No split dwarf debug info?"); + InfoHolder.emitUnits(this, Asm->getObjFileLowering().getDwarfInfoDWOSection(), + Asm->getObjFileLowering().getDwarfAbbrevDWOSection(), + DwarfAbbrevDWOSectionSym); +} + +// Emit the .debug_abbrev.dwo section for separated dwarf. This contains the +// abbreviations for the .debug_info.dwo section. +void DwarfDebug::emitDebugAbbrevDWO() { + assert(useSplitDwarf() && "No split dwarf?"); + emitAbbrevs(Asm->getObjFileLowering().getDwarfAbbrevDWOSection(), + &Abbreviations); +} + +// Emit the .debug_str.dwo section for separated dwarf. This contains the +// string section and is identical in format to traditional .debug_str +// sections. +void DwarfDebug::emitDebugStrDWO() { + assert(useSplitDwarf() && "No split dwarf?"); + const MCSection *OffSec = Asm->getObjFileLowering() + .getDwarfStrOffDWOSection(); + const MCSymbol *StrSym = DwarfStrSectionSym; + InfoHolder.emitStrings(Asm->getObjFileLowering().getDwarfStrDWOSection(), + OffSec, StrSym); +} diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.h b/lib/CodeGen/AsmPrinter/DwarfDebug.h index f94c9d0..1e471f7 100644 --- a/lib/CodeGen/AsmPrinter/DwarfDebug.h +++ b/lib/CodeGen/AsmPrinter/DwarfDebug.h @@ -15,15 +15,15 @@ #define CODEGEN_ASMPRINTER_DWARFDEBUG_H__ #include "DIE.h" -#include "llvm/DebugInfo.h" -#include "llvm/CodeGen/AsmPrinter.h" -#include "llvm/CodeGen/LexicalScopes.h" -#include "llvm/MC/MachineLocation.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/FoldingSet.h" +#include "llvm/ADT/SetVector.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/StringMap.h" -#include "llvm/ADT/UniqueVector.h" +#include "llvm/CodeGen/AsmPrinter.h" +#include "llvm/CodeGen/LexicalScopes.h" +#include "llvm/DebugInfo.h" +#include "llvm/MC/MachineLocation.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/DebugLoc.h" @@ -41,10 +41,10 @@ class DIEAbbrev; class DIE; class DIEBlock; class DIEEntry; +class DwarfDebug; //===----------------------------------------------------------------------===// -/// SrcLineInfo - This class is used to record source line correspondence. -/// +/// \brief This class is used to record source line correspondence. class SrcLineInfo { unsigned Line; // Source line number. unsigned Column; // Source column. @@ -61,8 +61,8 @@ public: MCSymbol *getLabel() const { return Label; } }; -/// DotDebugLocEntry - This struct describes location entries emitted in -/// .debug_loc section. +/// \brief This struct describes location entries emitted in the .debug_loc +/// section. typedef struct DotDebugLocEntry { const MCSymbol *Begin; const MCSymbol *End; @@ -83,24 +83,25 @@ typedef struct DotDebugLocEntry { const ConstantFP *CFP; const ConstantInt *CIP; } Constants; - DotDebugLocEntry() - : Begin(0), End(0), Variable(0), Merged(false), + DotDebugLocEntry() + : Begin(0), End(0), Variable(0), Merged(false), Constant(false) { Constants.Int = 0;} DotDebugLocEntry(const MCSymbol *B, const MCSymbol *E, MachineLocation &L, - const MDNode *V) - : Begin(B), End(E), Loc(L), Variable(V), Merged(false), + const MDNode *V) + : Begin(B), End(E), Loc(L), Variable(V), Merged(false), Constant(false) { Constants.Int = 0; EntryKind = E_Location; } DotDebugLocEntry(const MCSymbol *B, const MCSymbol *E, int64_t i) - : Begin(B), End(E), Variable(0), Merged(false), + : Begin(B), End(E), Variable(0), Merged(false), Constant(true) { Constants.Int = i; EntryKind = E_Integer; } DotDebugLocEntry(const MCSymbol *B, const MCSymbol *E, const ConstantFP *FPtr) - : Begin(B), End(E), Variable(0), Merged(false), + : Begin(B), End(E), Variable(0), Merged(false), Constant(true) { Constants.CFP = FPtr; EntryKind = E_ConstantFP; } - DotDebugLocEntry(const MCSymbol *B, const MCSymbol *E, const ConstantInt *IPtr) - : Begin(B), End(E), Variable(0), Merged(false), + DotDebugLocEntry(const MCSymbol *B, const MCSymbol *E, + const ConstantInt *IPtr) + : Begin(B), End(E), Variable(0), Merged(false), Constant(true) { Constants.CIP = IPtr; EntryKind = E_ConstantInt; } - /// Empty entries are also used as a trigger to emit temp label. Such + /// \brief Empty entries are also used as a trigger to emit temp label. Such /// labels are referenced is used to find debug_loc offset for a given DIE. bool isEmpty() { return Begin == 0 && End == 0; } bool isMerged() { return Merged; } @@ -120,8 +121,7 @@ typedef struct DotDebugLocEntry { } DotDebugLocEntry; //===----------------------------------------------------------------------===// -/// DbgVariable - This class is used to track local variable information. -/// +/// \brief This class is used to track local variable information. class DbgVariable { DIVariable Var; // Variable Descriptor. DIE *TheDIE; // Variable DIE. @@ -131,7 +131,7 @@ class DbgVariable { int FrameIndex; public: // AbsVar may be NULL. - DbgVariable(DIVariable V, DbgVariable *AV) + DbgVariable(DIVariable V, DbgVariable *AV) : Var(V), TheDIE(0), DotDebugLocOffset(~0U), AbsVar(AV), MInsn(0), FrameIndex(~0) {} @@ -147,22 +147,30 @@ public: void setMInsn(const MachineInstr *M) { MInsn = M; } int getFrameIndex() const { return FrameIndex; } void setFrameIndex(int FI) { FrameIndex = FI; } - // Translate tag to proper Dwarf tag. - unsigned getTag() const { + // Translate tag to proper Dwarf tag. + unsigned getTag() const { if (Var.getTag() == dwarf::DW_TAG_arg_variable) return dwarf::DW_TAG_formal_parameter; - + return dwarf::DW_TAG_variable; } - /// isArtificial - Return true if DbgVariable is artificial. + /// \brief Return true if DbgVariable is artificial. bool isArtificial() const { if (Var.isArtificial()) return true; - if (Var.getTag() == dwarf::DW_TAG_arg_variable - && getType().isArtificial()) + if (getType().isArtificial()) + return true; + return false; + } + + bool isObjectPointer() const { + if (Var.isObjectPointer()) + return true; + if (getType().isObjectPointer()) return true; return false; } + bool variableHasComplexAddress() const { assert(Var.Verify() && "Invalid complex DbgVariable!"); return Var.hasComplexAddress(); @@ -171,7 +179,7 @@ public: assert(Var.Verify() && "Invalid complex DbgVariable!"); return Var.isBlockByrefVariable(); } - unsigned getNumAddrElements() const { + unsigned getNumAddrElements() const { assert(Var.Verify() && "Invalid complex DbgVariable!"); return Var.getNumAddrElements(); } @@ -181,108 +189,167 @@ public: DIType getType() const; }; + +// A String->Symbol mapping of strings used by indirect +// references. +typedef StringMap<std::pair<MCSymbol*, unsigned>, + BumpPtrAllocator&> StrPool; + +/// \brief Collects and handles information specific to a particular +/// collection of units. +class DwarfUnits { + // Target of Dwarf emission, used for sizing of abbreviations. + AsmPrinter *Asm; + + // Used to uniquely define abbreviations. + FoldingSet<DIEAbbrev> *AbbreviationsSet; + + // A list of all the unique abbreviations in use. + std::vector<DIEAbbrev *> *Abbreviations; + + // A pointer to all units in the section. + SmallVector<CompileUnit *, 1> CUs; + + // Collection of strings for this unit and assorted symbols. + StrPool StringPool; + unsigned NextStringPoolNumber; + std::string StringPref; + +public: + DwarfUnits(AsmPrinter *AP, FoldingSet<DIEAbbrev> *AS, + std::vector<DIEAbbrev *> *A, const char *Pref, + BumpPtrAllocator &DA) : + Asm(AP), AbbreviationsSet(AS), Abbreviations(A), + StringPool(DA), NextStringPoolNumber(0), StringPref(Pref) {} + + /// \brief Compute the size and offset of a DIE given an incoming Offset. + unsigned computeSizeAndOffset(DIE *Die, unsigned Offset); + + /// \brief Compute the size and offset of all the DIEs. + void computeSizeAndOffsets(); + + /// \brief Define a unique number for the abbreviation. + void assignAbbrevNumber(DIEAbbrev &Abbrev); + + /// \brief Add a unit to the list of CUs. + void addUnit(CompileUnit *CU) { CUs.push_back(CU); } + + /// \brief Emit all of the units to the section listed with the given + /// abbreviation section. + void emitUnits(DwarfDebug *, const MCSection *, const MCSection *, + const MCSymbol *); + + /// \brief Emit all of the strings to the section given. + void emitStrings(const MCSection *, const MCSection *, const MCSymbol *); + + /// \brief Returns the entry into the start of the pool. + MCSymbol *getStringPoolSym(); + + /// \brief Returns an entry into the string pool with the given + /// string text. + MCSymbol *getStringPoolEntry(StringRef Str); + + /// \brief Returns the index into the string pool with the given + /// string text. + unsigned getStringPoolIndex(StringRef Str); + + /// \brief Returns the string pool. + StrPool *getStringPool() { return &StringPool; } +}; + +/// \brief Collects and handles dwarf debug information. class DwarfDebug { - /// Asm - Target of Dwarf emission. + // Target of Dwarf emission. AsmPrinter *Asm; - /// MMI - Collected machine module information. + // Collected machine module information. MachineModuleInfo *MMI; - /// DIEValueAllocator - All DIEValues are allocated through this allocator. + // All DIEValues are allocated through this allocator. BumpPtrAllocator DIEValueAllocator; //===--------------------------------------------------------------------===// - // Attributes used to construct specific Dwarf sections. + // Attribute used to construct specific Dwarf sections. // CompileUnit *FirstCU; - /// Maps MDNode with its corresponding CompileUnit. + // Maps MDNode with its corresponding CompileUnit. DenseMap <const MDNode *, CompileUnit *> CUMap; - /// Maps subprogram MDNode with its corresponding CompileUnit. + // Maps subprogram MDNode with its corresponding CompileUnit. DenseMap <const MDNode *, CompileUnit *> SPMap; - /// AbbreviationsSet - Used to uniquely define abbreviations. - /// + // Used to uniquely define abbreviations. FoldingSet<DIEAbbrev> AbbreviationsSet; - /// Abbreviations - A list of all the unique abbreviations in use. - /// + // A list of all the unique abbreviations in use. std::vector<DIEAbbrev *> Abbreviations; - /// SourceIdMap - Source id map, i.e. pair of source filename and directory, - /// separated by a zero byte, mapped to a unique id. + // Source id map, i.e. pair of source filename and directory, + // separated by a zero byte, mapped to a unique id. StringMap<unsigned, BumpPtrAllocator&> SourceIdMap; - /// StringPool - A String->Symbol mapping of strings used by indirect - /// references. - StringMap<std::pair<MCSymbol*, unsigned>, BumpPtrAllocator&> StringPool; - unsigned NextStringPoolNumber; - - /// SectionMap - Provides a unique id per text section. - /// - UniqueVector<const MCSection*> SectionMap; + // Provides a unique id per text section. + SetVector<const MCSection*> SectionMap; - /// CurrentFnArguments - List of Arguments (DbgValues) for current function. + // List of Arguments (DbgValues) for current function. SmallVector<DbgVariable *, 8> CurrentFnArguments; LexicalScopes LScopes; - /// AbstractSPDies - Collection of abstract subprogram DIEs. + // Collection of abstract subprogram DIEs. DenseMap<const MDNode *, DIE *> AbstractSPDies; - /// ScopeVariables - Collection of dbg variables of a scope. + // Collection of dbg variables of a scope. DenseMap<LexicalScope *, SmallVector<DbgVariable *, 8> > ScopeVariables; - /// AbstractVariables - Collection of abstract variables. + // Collection of abstract variables. DenseMap<const MDNode *, DbgVariable *> AbstractVariables; - /// DotDebugLocEntries - Collection of DotDebugLocEntry. + // Collection of DotDebugLocEntry. SmallVector<DotDebugLocEntry, 4> DotDebugLocEntries; - /// InlinedSubprogramDIEs - Collection of subprogram DIEs that are marked - /// (at the end of the module) as DW_AT_inline. + // Collection of subprogram DIEs that are marked (at the end of the module) + // as DW_AT_inline. SmallPtrSet<DIE *, 4> InlinedSubprogramDIEs; - /// InlineInfo - Keep track of inlined functions and their location. This - /// information is used to populate the debug_inlined section. + // Keep track of inlined functions and their location. This + // information is used to populate the debug_inlined section. typedef std::pair<const MCSymbol *, DIE *> InlineInfoLabels; DenseMap<const MDNode *, SmallVector<InlineInfoLabels, 4> > InlineInfo; SmallVector<const MDNode *, 4> InlinedSPNodes; - // ProcessedSPNodes - This is a collection of subprogram MDNodes that - // are processed to create DIEs. + // This is a collection of subprogram MDNodes that are processed to + // create DIEs. SmallPtrSet<const MDNode *, 16> ProcessedSPNodes; - /// LabelsBeforeInsn - Maps instruction with label emitted before - /// instruction. + // Maps instruction with label emitted before instruction. DenseMap<const MachineInstr *, MCSymbol *> LabelsBeforeInsn; - /// LabelsAfterInsn - Maps instruction with label emitted after - /// instruction. + // Maps instruction with label emitted after instruction. DenseMap<const MachineInstr *, MCSymbol *> LabelsAfterInsn; - /// UserVariables - Every user variable mentioned by a DBG_VALUE instruction - /// in order of appearance. + // Every user variable mentioned by a DBG_VALUE instruction in order of + // appearance. SmallVector<const MDNode*, 8> UserVariables; - /// DbgValues - For each user variable, keep a list of DBG_VALUE - /// instructions in order. The list can also contain normal instructions that - /// clobber the previous DBG_VALUE. + // For each user variable, keep a list of DBG_VALUE instructions in order. + // The list can also contain normal instructions that clobber the previous + // DBG_VALUE. typedef DenseMap<const MDNode*, SmallVector<const MachineInstr*, 4> > DbgValueHistoryMap; DbgValueHistoryMap DbgValues; SmallVector<const MCSymbol *, 8> DebugRangeSymbols; - /// Previous instruction's location information. This is used to determine - /// label location to indicate scope boundries in dwarf debug info. + // Previous instruction's location information. This is used to determine + // label location to indicate scope boundries in dwarf debug info. DebugLoc PrevInstLoc; MCSymbol *PrevLabel; - /// PrologEndLoc - This location indicates end of function prologue and - /// beginning of function body. + // This location indicates end of function prologue and beginning of function + // body. DebugLoc PrologEndLoc; struct FunctionDebugFrameInfo { @@ -302,177 +369,205 @@ class DwarfDebug { MCSymbol *DwarfStrSectionSym, *TextSectionSym, *DwarfDebugRangeSectionSym; MCSymbol *DwarfDebugLocSectionSym; MCSymbol *FunctionBeginSym, *FunctionEndSym; + MCSymbol *DwarfAbbrevDWOSectionSym, *DwarfStrDWOSectionSym; // As an optimization, there is no need to emit an entry in the directory // table for the same directory as DW_at_comp_dir. StringRef CompilationDir; - // A holder for the DarwinGDBCompat flag so that the compile unit can use it. - bool isDarwinGDBCompat; - bool hasDwarfAccelTables; -private: + // Counter for assigning globally unique IDs for CUs. + unsigned GlobalCUIndexCount; - /// assignAbbrevNumber - Define a unique number for the abbreviation. - /// - void assignAbbrevNumber(DIEAbbrev &Abbrev); + // Holder for the file specific debug information. + DwarfUnits InfoHolder; + + // Holders for the various debug information flags that we might need to + // have exposed. See accessor functions below for description. + + // Whether or not we're emitting info for older versions of gdb on darwin. + bool IsDarwinGDBCompat; + + // DWARF5 Experimental Options + bool HasDwarfAccelTables; + bool HasSplitDwarf; + + // Separated Dwarf Variables + // In general these will all be for bits that are left in the + // original object file, rather than things that are meant + // to be in the .dwo sections. + + // The CU left in the original object file for separated debug info. + CompileUnit *SkeletonCU; + + // Used to uniquely define abbreviations for the skeleton emission. + FoldingSet<DIEAbbrev> SkeletonAbbrevSet; + + // A list of all the unique abbreviations in use. + std::vector<DIEAbbrev *> SkeletonAbbrevs; + + // Holder for the skeleton information. + DwarfUnits SkeletonHolder; + +private: void addScopeVariable(LexicalScope *LS, DbgVariable *Var); - /// findAbstractVariable - Find abstract variable associated with Var. + /// \brief Find abstract variable associated with Var. DbgVariable *findAbstractVariable(DIVariable &Var, DebugLoc Loc); - /// updateSubprogramScopeDIE - Find DIE for the given subprogram and - /// attach appropriate DW_AT_low_pc and DW_AT_high_pc attributes. - /// If there are global variables in this scope then create and insert - /// DIEs for these variables. + /// \brief Find DIE for the given subprogram and attach appropriate + /// DW_AT_low_pc and DW_AT_high_pc attributes. If there are global + /// variables in this scope then create and insert DIEs for these + /// variables. DIE *updateSubprogramScopeDIE(CompileUnit *SPCU, const MDNode *SPNode); - /// constructLexicalScope - Construct new DW_TAG_lexical_block - /// for this scope and attach DW_AT_low_pc/DW_AT_high_pc labels. + /// \brief Construct new DW_TAG_lexical_block for this scope and + /// attach DW_AT_low_pc/DW_AT_high_pc labels. DIE *constructLexicalScopeDIE(CompileUnit *TheCU, LexicalScope *Scope); - /// constructInlinedScopeDIE - This scope represents inlined body of - /// a function. Construct DIE to represent this concrete inlined copy - /// of the function. + /// \brief This scope represents inlined body of a function. Construct + /// DIE to represent this concrete inlined copy of the function. DIE *constructInlinedScopeDIE(CompileUnit *TheCU, LexicalScope *Scope); - /// constructScopeDIE - Construct a DIE for this scope. + /// \brief Construct a DIE for this scope. DIE *constructScopeDIE(CompileUnit *TheCU, LexicalScope *Scope); - /// EmitSectionLabels - Emit initial Dwarf sections with a label at - /// the start of each one. - void EmitSectionLabels(); + /// \brief Emit initial Dwarf sections with a label at the start of each one. + void emitSectionLabels(); - /// emitDIE - Recursively Emits a debug information entry. - /// - void emitDIE(DIE *Die); + /// \brief Compute the size and offset of a DIE given an incoming Offset. + unsigned computeSizeAndOffset(DIE *Die, unsigned Offset); - /// computeSizeAndOffset - Compute the size and offset of a DIE. - /// - unsigned computeSizeAndOffset(DIE *Die, unsigned Offset, bool Last); - - /// computeSizeAndOffsets - Compute the size and offset of all the DIEs. - /// + /// \brief Compute the size and offset of all the DIEs. void computeSizeAndOffsets(); - /// EmitDebugInfo - Emit the debug info section. - /// + /// \brief Attach DW_AT_inline attribute with inlined subprogram DIEs. + void computeInlinedDIEs(); + + /// \brief Collect info for variables that were optimized out. + void collectDeadVariables(); + + /// \brief Finish off debug information after all functions have been + /// processed. + void finalizeModuleInfo(); + + /// \brief Emit labels to close any remaining sections that have been left + /// open. + void endSections(); + + /// \brief Emit a set of abbreviations to the specific section. + void emitAbbrevs(const MCSection *, std::vector<DIEAbbrev*> *); + + /// \brief Emit the debug info section. void emitDebugInfo(); - /// emitAbbreviations - Emit the abbreviation section. - /// - void emitAbbreviations() const; + /// \brief Emit the abbreviation section. + void emitAbbreviations(); - /// emitEndOfLineMatrix - Emit the last address of the section and the end of + /// \brief Emit the last address of the section and the end of /// the line matrix. - /// void emitEndOfLineMatrix(unsigned SectionEnd); - /// emitAccelNames - Emit visible names into a hashed accelerator table - /// section. + /// \brief Emit visible names into a hashed accelerator table section. void emitAccelNames(); - - /// emitAccelObjC - Emit objective C classes and categories into a hashed + + /// \brief Emit objective C classes and categories into a hashed /// accelerator table section. void emitAccelObjC(); - /// emitAccelNamespace - Emit namespace dies into a hashed accelerator - /// table. + /// \brief Emit namespace dies into a hashed accelerator table. void emitAccelNamespaces(); - /// emitAccelTypes() - Emit type dies into a hashed accelerator table. - /// + /// \brief Emit type dies into a hashed accelerator table. void emitAccelTypes(); - - /// emitDebugPubTypes - Emit visible types into a debug pubtypes section. - /// + + /// \brief Emit visible types into a debug pubtypes section. void emitDebugPubTypes(); - /// emitDebugStr - Emit visible names into a debug str section. - /// + /// \brief Emit visible names into a debug str section. void emitDebugStr(); - /// emitDebugLoc - Emit visible names into a debug loc section. - /// + /// \brief Emit visible names into a debug loc section. void emitDebugLoc(); - /// EmitDebugARanges - Emit visible names into a debug aranges section. - /// - void EmitDebugARanges(); + /// \brief Emit visible names into a debug aranges section. + void emitDebugARanges(); - /// emitDebugRanges - Emit visible names into a debug ranges section. - /// + /// \brief Emit visible names into a debug ranges section. void emitDebugRanges(); - /// emitDebugMacInfo - Emit visible names into a debug macinfo section. - /// + /// \brief Emit visible names into a debug macinfo section. void emitDebugMacInfo(); - /// emitDebugInlineInfo - Emit inline info using following format. - /// Section Header: - /// 1. length of section - /// 2. Dwarf version number - /// 3. address size. - /// - /// Entries (one "entry" for each function that was inlined): - /// - /// 1. offset into __debug_str section for MIPS linkage name, if exists; - /// otherwise offset into __debug_str for regular function name. - /// 2. offset into __debug_str section for regular function name. - /// 3. an unsigned LEB128 number indicating the number of distinct inlining - /// instances for the function. - /// - /// The rest of the entry consists of a {die_offset, low_pc} pair for each - /// inlined instance; the die_offset points to the inlined_subroutine die in - /// the __debug_info section, and the low_pc is the starting address for the - /// inlining instance. + /// \brief Emit inline info using custom format. void emitDebugInlineInfo(); - /// constructCompileUnit - Create new CompileUnit for the given - /// metadata node with tag DW_TAG_compile_unit. + /// DWARF 5 Experimental Split Dwarf Emitters + + /// \brief Construct the split debug info compile unit for the debug info + /// section. + CompileUnit *constructSkeletonCU(const MDNode *); + + /// \brief Emit the local split debug info section. + void emitSkeletonCU(const MCSection *); + + /// \brief Emit the local split abbreviations. + void emitSkeletonAbbrevs(const MCSection *); + + /// \brief Emit the debug info dwo section. + void emitDebugInfoDWO(); + + /// \brief Emit the debug abbrev dwo section. + void emitDebugAbbrevDWO(); + + /// \brief Emit the debug str dwo section. + void emitDebugStrDWO(); + + /// \brief Create new CompileUnit for the given metadata node with tag + /// DW_TAG_compile_unit. CompileUnit *constructCompileUnit(const MDNode *N); - /// construct SubprogramDIE - Construct subprogram DIE. + /// \brief Construct subprogram DIE. void constructSubprogramDIE(CompileUnit *TheCU, const MDNode *N); - /// recordSourceLine - Register a source line with debug info. Returns the - /// unique label that was emitted and which provides correspondence to - /// the source line list. + /// \brief Register a source line with debug info. Returns the unique + /// label that was emitted and which provides correspondence to the + /// source line list. void recordSourceLine(unsigned Line, unsigned Col, const MDNode *Scope, unsigned Flags); - - /// identifyScopeMarkers() - Indentify instructions that are marking the - /// beginning of or ending of a scope. + + /// \brief Indentify instructions that are marking the beginning of or + /// ending of a scope. void identifyScopeMarkers(); - /// addCurrentFnArgument - If Var is an current function argument that add - /// it in CurrentFnArguments list. + /// \brief If Var is an current function argument that add it in + /// CurrentFnArguments list. bool addCurrentFnArgument(const MachineFunction *MF, DbgVariable *Var, LexicalScope *Scope); - /// collectVariableInfo - Populate LexicalScope entries with variables' info. + /// \brief Populate LexicalScope entries with variables' info. void collectVariableInfo(const MachineFunction *, SmallPtrSet<const MDNode *, 16> &ProcessedVars); - - /// collectVariableInfoFromMMITable - Collect variable information from - /// side table maintained by MMI. + + /// \brief Collect variable information from the side table maintained + /// by MMI. void collectVariableInfoFromMMITable(const MachineFunction * MF, SmallPtrSet<const MDNode *, 16> &P); - /// requestLabelBeforeInsn - Ensure that a label will be emitted before MI. + /// \brief Ensure that a label will be emitted before MI. void requestLabelBeforeInsn(const MachineInstr *MI) { LabelsBeforeInsn.insert(std::make_pair(MI, (MCSymbol*)0)); } - /// getLabelBeforeInsn - Return Label preceding the instruction. + /// \brief Return Label preceding the instruction. const MCSymbol *getLabelBeforeInsn(const MachineInstr *MI); - /// requestLabelAfterInsn - Ensure that a label will be emitted after MI. + /// \brief Ensure that a label will be emitted after MI. void requestLabelAfterInsn(const MachineInstr *MI) { LabelsAfterInsn.insert(std::make_pair(MI, (MCSymbol*)0)); } - /// getLabelAfterInsn - Return Label immediately following the instruction. + /// \brief Return Label immediately following the instruction. const MCSymbol *getLabelAfterInsn(const MachineInstr *MI); public: @@ -482,52 +577,54 @@ public: DwarfDebug(AsmPrinter *A, Module *M); ~DwarfDebug(); - /// collectInfoFromNamedMDNodes - Collect debug info from named mdnodes such - /// as llvm.dbg.enum and llvm.dbg.ty - void collectInfoFromNamedMDNodes(Module *M); + /// \brief Collect debug info from named mdnodes such as llvm.dbg.enum + /// and llvm.dbg.ty + void collectInfoFromNamedMDNodes(const Module *M); - /// collectLegacyDebugInfo - Collect debug info using DebugInfoFinder. + /// \brief Collect debug info using DebugInfoFinder. /// FIXME - Remove this when DragonEgg switches to DIBuilder. - bool collectLegacyDebugInfo(Module *M); + bool collectLegacyDebugInfo(const Module *M); - /// beginModule - Emit all Dwarf sections that should come prior to the + /// \brief Emit all Dwarf sections that should come prior to the /// content. - void beginModule(Module *M); + void beginModule(); - /// endModule - Emit all Dwarf sections that should come after the content. - /// + /// \brief Emit all Dwarf sections that should come after the content. void endModule(); - /// beginFunction - Gather pre-function debug information. Assumes being - /// emitted immediately after the function entry point. + /// \brief Gather pre-function debug information. void beginFunction(const MachineFunction *MF); - /// endFunction - Gather and emit post-function debug information. - /// + /// \brief Gather and emit post-function debug information. void endFunction(const MachineFunction *MF); - /// beginInstruction - Process beginning of an instruction. + /// \brief Process beginning of an instruction. void beginInstruction(const MachineInstr *MI); - /// endInstruction - Prcess end of an instruction. + /// \brief Process end of an instruction. void endInstruction(const MachineInstr *MI); - /// GetOrCreateSourceID - Look up the source id with the given directory and - /// source file names. If none currently exists, create a new id and insert it - /// in the SourceIds map. - unsigned GetOrCreateSourceID(StringRef DirName, StringRef FullName); - - /// getStringPool - returns the entry into the start of the pool. - MCSymbol *getStringPool(); + /// \brief Look up the source id with the given directory and source file + /// names. If none currently exists, create a new id and insert it in the + /// SourceIds map. + unsigned getOrCreateSourceID(StringRef DirName, StringRef FullName); - /// getStringPoolEntry - returns an entry into the string pool with the given - /// string text. - MCSymbol *getStringPoolEntry(StringRef Str); + /// \brief Recursively Emits a debug information entry. + void emitDIE(DIE *Die, std::vector<DIEAbbrev *> *Abbrevs); - /// useDarwinGDBCompat - returns whether or not to limit some of our debug + /// \brief Returns whether or not to limit some of our debug /// output to the limitations of darwin gdb. - bool useDarwinGDBCompat() { return isDarwinGDBCompat; } - bool useDwarfAccelTables() { return hasDwarfAccelTables; } + bool useDarwinGDBCompat() { return IsDarwinGDBCompat; } + + // Experimental DWARF5 features. + + /// \brief Returns whether or not to emit tables that dwarf consumers can + /// use to accelerate lookup. + bool useDwarfAccelTables() { return HasDwarfAccelTables; } + + /// \brief Returns whether or not to change the current debug info for the + /// split dwarf proposal support. + bool useSplitDwarf() { return HasSplitDwarf; } }; } // End of namespace llvm diff --git a/lib/CodeGen/AsmPrinter/DwarfException.cpp b/lib/CodeGen/AsmPrinter/DwarfException.cpp index 70cc2e5..975bb94 100644 --- a/lib/CodeGen/AsmPrinter/DwarfException.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfException.cpp @@ -12,30 +12,30 @@ //===----------------------------------------------------------------------===// #include "DwarfException.h" -#include "llvm/Module.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/Twine.h" #include "llvm/CodeGen/AsmPrinter.h" -#include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/IR/Module.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCSection.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSymbol.h" +#include "llvm/Support/Dwarf.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/FormattedStream.h" #include "llvm/Target/Mangler.h" -#include "llvm/Target/TargetData.h" #include "llvm/Target/TargetFrameLowering.h" #include "llvm/Target/TargetLoweringObjectFile.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetOptions.h" #include "llvm/Target/TargetRegisterInfo.h" -#include "llvm/Support/Dwarf.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/FormattedStream.h" -#include "llvm/ADT/SmallString.h" -#include "llvm/ADT/StringExtras.h" -#include "llvm/ADT/Twine.h" using namespace llvm; DwarfException::DwarfException(AsmPrinter *A) @@ -417,7 +417,7 @@ void DwarfException::EmitExceptionTable() { // that we're omitting that bit. TTypeEncoding = dwarf::DW_EH_PE_omit; // dwarf::DW_EH_PE_absptr - TypeFormatSize = Asm->getTargetData().getPointerSize(); + TypeFormatSize = Asm->getDataLayout().getPointerSize(); } else { // Okay, we have actual filters or typeinfos to emit. As such, we need to // pick a type encoding for them. We're about to emit a list of pointers to @@ -672,6 +672,18 @@ void DwarfException::EmitExceptionTable() { Asm->EmitSLEB128(Action.NextAction); } + EmitTypeInfos(TTypeEncoding); + + Asm->EmitAlignment(2); +} + +void DwarfException::EmitTypeInfos(unsigned TTypeEncoding) { + const std::vector<const GlobalVariable *> &TypeInfos = MMI->getTypeInfos(); + const std::vector<unsigned> &FilterIds = MMI->getFilterIds(); + + bool VerboseAsm = Asm->OutStreamer.isVerboseAsm(); + + int Entry = 0; // Emit the Catch TypeInfos. if (VerboseAsm && !TypeInfos.empty()) { Asm->OutStreamer.AddComment(">> Catch TypeInfos <<"); @@ -684,11 +696,7 @@ void DwarfException::EmitExceptionTable() { const GlobalVariable *GV = *I; if (VerboseAsm) Asm->OutStreamer.AddComment("TypeInfo " + Twine(Entry--)); - if (GV) - Asm->EmitReference(GV, TTypeEncoding); - else - Asm->OutStreamer.EmitIntValue(0,Asm->GetSizeOfEncodedValue(TTypeEncoding), - 0); + Asm->EmitTTypeReference(GV, TTypeEncoding); } // Emit the Exception Specifications. @@ -708,8 +716,6 @@ void DwarfException::EmitExceptionTable() { Asm->EmitULEB128(TypeID); } - - Asm->EmitAlignment(2); } /// EndModule - Emit all exception information that should come after the diff --git a/lib/CodeGen/AsmPrinter/DwarfException.h b/lib/CodeGen/AsmPrinter/DwarfException.h index fe9e493..74b1b13 100644 --- a/lib/CodeGen/AsmPrinter/DwarfException.h +++ b/lib/CodeGen/AsmPrinter/DwarfException.h @@ -121,6 +121,8 @@ protected: /// catches in the function. This tables is reversed indexed base 1. void EmitExceptionTable(); + virtual void EmitTypeInfos(unsigned TTypeEncoding); + public: //===--------------------------------------------------------------------===// // Main entry points. @@ -175,6 +177,7 @@ public: }; class ARMException : public DwarfException { + void EmitTypeInfos(unsigned TTypeEncoding); public: //===--------------------------------------------------------------------===// // Main entry points. diff --git a/lib/CodeGen/AsmPrinter/OcamlGCPrinter.cpp b/lib/CodeGen/AsmPrinter/OcamlGCPrinter.cpp index 1153817..b802853 100644 --- a/lib/CodeGen/AsmPrinter/OcamlGCPrinter.cpp +++ b/lib/CodeGen/AsmPrinter/OcamlGCPrinter.cpp @@ -12,20 +12,20 @@ //===----------------------------------------------------------------------===// #include "llvm/CodeGen/GCs.h" +#include "llvm/ADT/SmallString.h" #include "llvm/CodeGen/AsmPrinter.h" #include "llvm/CodeGen/GCMetadataPrinter.h" -#include "llvm/Module.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/IR/Module.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCContext.h" -#include "llvm/MC/MCSymbol.h" #include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/FormattedStream.h" #include "llvm/Target/Mangler.h" -#include "llvm/Target/TargetData.h" #include "llvm/Target/TargetLoweringObjectFile.h" #include "llvm/Target/TargetMachine.h" -#include "llvm/ADT/SmallString.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/FormattedStream.h" #include <cctype> using namespace llvm; @@ -91,7 +91,7 @@ void OcamlGCMetadataPrinter::beginAssembly(AsmPrinter &AP) { /// either condition is detected in a function which uses the GC. /// void OcamlGCMetadataPrinter::finishAssembly(AsmPrinter &AP) { - unsigned IntPtrSize = AP.TM.getTargetData()->getPointerSize(); + unsigned IntPtrSize = AP.TM.getDataLayout()->getPointerSize(); AP.OutStreamer.SwitchSection(AP.getObjFileLowering().getTextSection()); EmitCamlGlobal(getModule(), AP, "code_end"); diff --git a/lib/CodeGen/AsmPrinter/Win64Exception.cpp b/lib/CodeGen/AsmPrinter/Win64Exception.cpp index b83aa5a..cb25674 100644 --- a/lib/CodeGen/AsmPrinter/Win64Exception.cpp +++ b/lib/CodeGen/AsmPrinter/Win64Exception.cpp @@ -12,30 +12,30 @@ //===----------------------------------------------------------------------===// #include "DwarfException.h" -#include "llvm/Module.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/Twine.h" #include "llvm/CodeGen/AsmPrinter.h" -#include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/IR/Module.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCSection.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSymbol.h" +#include "llvm/Support/Dwarf.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/FormattedStream.h" #include "llvm/Target/Mangler.h" -#include "llvm/Target/TargetData.h" #include "llvm/Target/TargetFrameLowering.h" #include "llvm/Target/TargetLoweringObjectFile.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetOptions.h" #include "llvm/Target/TargetRegisterInfo.h" -#include "llvm/Support/Dwarf.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/FormattedStream.h" -#include "llvm/ADT/SmallString.h" -#include "llvm/ADT/StringExtras.h" -#include "llvm/ADT/Twine.h" using namespace llvm; Win64Exception::Win64Exception(AsmPrinter *A) |
