diff options
Diffstat (limited to 'lib/CodeGen/AsmPrinter')
-rw-r--r-- | lib/CodeGen/AsmPrinter/ARMException.cpp | 19 | ||||
-rw-r--r-- | lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 253 | ||||
-rw-r--r-- | lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp | 8 | ||||
-rw-r--r-- | lib/CodeGen/AsmPrinter/DIE.cpp | 18 | ||||
-rw-r--r-- | lib/CodeGen/AsmPrinter/DIE.h | 57 | ||||
-rw-r--r-- | lib/CodeGen/AsmPrinter/DwarfAccelTable.cpp | 63 | ||||
-rw-r--r-- | lib/CodeGen/AsmPrinter/DwarfAccelTable.h | 55 | ||||
-rw-r--r-- | lib/CodeGen/AsmPrinter/DwarfCFIException.cpp | 6 | ||||
-rw-r--r-- | lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp | 87 | ||||
-rw-r--r-- | lib/CodeGen/AsmPrinter/DwarfCompileUnit.h | 16 | ||||
-rw-r--r-- | lib/CodeGen/AsmPrinter/DwarfDebug.cpp | 66 | ||||
-rw-r--r-- | lib/CodeGen/AsmPrinter/DwarfDebug.h | 4 | ||||
-rw-r--r-- | lib/CodeGen/AsmPrinter/DwarfException.cpp | 7 |
13 files changed, 426 insertions, 233 deletions
diff --git a/lib/CodeGen/AsmPrinter/ARMException.cpp b/lib/CodeGen/AsmPrinter/ARMException.cpp index 3f23873..b60fda8 100644 --- a/lib/CodeGen/AsmPrinter/ARMException.cpp +++ b/lib/CodeGen/AsmPrinter/ARMException.cpp @@ -29,6 +29,7 @@ #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" @@ -36,6 +37,12 @@ #include "llvm/ADT/Twine.h" using namespace llvm; +cl::opt<bool> +EnableARMEHABIDescriptors("arm-enable-ehabi-descriptors", cl::Hidden, + cl::desc("Generate ARM EHABI tables with unwinding descriptors"), + cl::init(false)); + + ARMException::ARMException(AsmPrinter *A) : DwarfException(A), shouldEmitTable(false), shouldEmitMoves(false), shouldEmitTableModule(false) @@ -72,13 +79,15 @@ void ARMException::EndFunction() { Asm->OutStreamer.EmitPersonality(PerSym); } - // Map all labels and get rid of any dead landing pads. - MMI->TidyLandingPads(); + if (EnableARMEHABIDescriptors) { + // Map all labels and get rid of any dead landing pads. + MMI->TidyLandingPads(); - Asm->OutStreamer.EmitHandlerData(); + Asm->OutStreamer.EmitHandlerData(); - // Emit actual exception table - EmitExceptionTable(); + // Emit actual exception table + EmitExceptionTable(); + } } Asm->OutStreamer.EmitFnEnd(); diff --git a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index f0e1fe4..d5926f9 100644 --- a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -103,6 +103,7 @@ AsmPrinter::AsmPrinter(TargetMachine &tm, MCStreamer &Streamer) OutStreamer(Streamer), LastMI(0), LastFn(0), Counter(~0U), SetCounter(0) { DD = 0; DE = 0; MMI = 0; LI = 0; + CurrentFnSym = CurrentFnSymForSize = 0; GCMetadataPrinters = 0; VerboseAsm = Streamer.isVerboseAsm(); } @@ -774,7 +775,8 @@ void AsmPrinter::EmitFunctionBody() { const MCExpr *SizeExp = MCBinaryExpr::CreateSub(MCSymbolRefExpr::Create(FnEndLabel, OutContext), - MCSymbolRefExpr::Create(CurrentFnSym, OutContext), + MCSymbolRefExpr::Create(CurrentFnSymForSize, + OutContext), OutContext); OutStreamer.EmitELFSize(CurrentFnSym, SizeExp); } @@ -811,7 +813,7 @@ void AsmPrinter::EmitDwarfRegOp(const MachineLocation &MLoc) const { const TargetRegisterInfo *TRI = TM.getRegisterInfo(); int Reg = TRI->getDwarfRegNum(MLoc.getReg(), false); - for (const unsigned *SR = TRI->getSuperRegisters(MLoc.getReg()); + for (const uint16_t *SR = TRI->getSuperRegisters(MLoc.getReg()); *SR && Reg < 0; ++SR) { Reg = TRI->getDwarfRegNum(*SR, false); // FIXME: Get the bit range this register uses of the superregister @@ -872,6 +874,12 @@ bool AsmPrinter::doFinalization(Module &M) { EmitVisibility(Name, V, false); } + // Emit module flags. + SmallVector<Module::ModuleFlagEntry, 8> ModuleFlags; + M.getModuleFlagsMetadata(ModuleFlags); + if (!ModuleFlags.empty()) + getObjFileLowering().emitModuleFlags(OutStreamer, ModuleFlags, Mang, TM); + // Finalize debug and EH information. #if !defined(ANDROID_TARGET_BUILD) || defined(ANDROID_ENGINEERING_BUILD) if (DE) { @@ -962,6 +970,7 @@ void AsmPrinter::SetupMachineFunction(MachineFunction &MF) { this->MF = &MF; // Get the function symbol. CurrentFnSym = Mang->getSymbol(MF.getFunction()); + CurrentFnSymForSize = CurrentFnSym; if (isVerbose()) LI = &getAnalysis<MachineLoopInfo>(); @@ -1153,7 +1162,7 @@ void AsmPrinter::EmitJumpTableEntry(const MachineJumpTableInfo *MJTI, const MCExpr *Value = 0; switch (MJTI->getEntryKind()) { case MachineJumpTableInfo::EK_Inline: - llvm_unreachable("Cannot emit EK_Inline jump table entry"); break; + llvm_unreachable("Cannot emit EK_Inline jump table entry"); case MachineJumpTableInfo::EK_Custom32: Value = TM.getTargetLowering()->LowerCustomJumpTableEntry(MJTI, MBB, UID, OutContext); @@ -1172,6 +1181,15 @@ void AsmPrinter::EmitJumpTableEntry(const MachineJumpTableInfo *MJTI, return; } + case MachineJumpTableInfo::EK_GPRel64BlockAddress: { + // EK_GPRel64BlockAddress - Each entry is an address of block, encoded + // with a relocation as gp-relative, e.g.: + // .gpdword LBB123 + MCSymbol *MBBSym = MBB->getSymbol(); + OutStreamer.EmitGPRel64Value(MCSymbolRefExpr::Create(MBBSym, OutContext)); + return; + } + case MachineJumpTableInfo::EK_LabelDifference32: { // EK_LabelDifference32 - Each entry is the address of the block minus // the address of the jump table. This is used for PIC jump tables where @@ -1224,12 +1242,8 @@ bool AsmPrinter::EmitSpecialLLVMGlobal(const GlobalVariable *GV) { assert(GV->hasInitializer() && "Not a special LLVM global!"); - const TargetData *TD = TM.getTargetData(); - unsigned Align = Log2_32(TD->getPointerPrefAlignment()); if (GV->getName() == "llvm.global_ctors") { - OutStreamer.SwitchSection(getObjFileLowering().getStaticCtorSection()); - EmitAlignment(Align); - EmitXXStructorList(GV->getInitializer()); + EmitXXStructorList(GV->getInitializer(), /* isCtor */ true); if (TM.getRelocationModel() == Reloc::Static && MAI->hasStaticCtorDtorReferenceInStaticMode()) { @@ -1241,9 +1255,7 @@ bool AsmPrinter::EmitSpecialLLVMGlobal(const GlobalVariable *GV) { } if (GV->getName() == "llvm.global_dtors") { - OutStreamer.SwitchSection(getObjFileLowering().getStaticDtorSection()); - EmitAlignment(Align); - EmitXXStructorList(GV->getInitializer()); + EmitXXStructorList(GV->getInitializer(), /* isCtor */ false); if (TM.getRelocationModel() == Reloc::Static && MAI->hasStaticCtorDtorReferenceInStaticMode()) { @@ -1273,7 +1285,7 @@ void AsmPrinter::EmitLLVMUsedList(const Constant *List) { } } -typedef std::pair<int, Constant*> Structor; +typedef std::pair<unsigned, Constant*> Structor; static bool priority_order(const Structor& lhs, const Structor& rhs) { return lhs.first < rhs.first; @@ -1281,7 +1293,7 @@ static bool priority_order(const Structor& lhs, const Structor& rhs) { /// EmitXXStructorList - Emit the ctor or dtor list taking into account the init /// priority. -void AsmPrinter::EmitXXStructorList(const Constant *List) { +void AsmPrinter::EmitXXStructorList(const Constant *List, bool isCtor) { // Should be an array of '{ int, void ()* }' structs. The first value is the // init priority. if (!isa<ConstantArray>(List)) return; @@ -1307,19 +1319,20 @@ void AsmPrinter::EmitXXStructorList(const Constant *List) { CS->getOperand(1))); } - // Emit the function pointers in reverse priority order. - switch (getObjFileLowering().getStructorOutputOrder()) { - case Structors::None: - break; - case Structors::PriorityOrder: - std::sort(Structors.begin(), Structors.end(), priority_order); - break; - case Structors::ReversePriorityOrder: - std::sort(Structors.rbegin(), Structors.rend(), priority_order); - break; + // Emit the function pointers in the target-specific order + const TargetData *TD = TM.getTargetData(); + 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) { + const MCSection *OutputSection = + (isCtor ? + getObjFileLowering().getStaticCtorSection(Structors[i].first) : + getObjFileLowering().getStaticDtorSection(Structors[i].first)); + OutStreamer.SwitchSection(OutputSection); + if (OutStreamer.getCurrentSection() != OutStreamer.getPreviousSection()) + EmitAlignment(Align); + EmitXXStructor(Structors[i].second); } - for (unsigned i = 0, e = Structors.size(); i != e; ++i) - EmitGlobalConstant(Structors[i].second); } //===--------------------------------------------------------------------===// @@ -1456,7 +1469,6 @@ static const MCExpr *LowerConstant(const Constant *CV, AsmPrinter &AP) { const ConstantExpr *CE = dyn_cast<ConstantExpr>(CV); if (CE == 0) { llvm_unreachable("Unknown constant value to lower!"); - return MCConstantExpr::Create(0, Ctx); } switch (CE->getOpcode()) { @@ -1478,7 +1490,6 @@ static const MCExpr *LowerConstant(const Constant *CV, AsmPrinter &AP) { !AP.MF ? 0 : AP.MF->getFunction()->getParent()); report_fatal_error(OS.str()); } - return MCConstantExpr::Create(0, Ctx); case Instruction::GetElementPtr: { const TargetData &TD = *AP.TM.getTargetData(); // Generate a symbolic expression for the byte address @@ -1576,6 +1587,19 @@ static void EmitGlobalConstantImpl(const Constant *C, unsigned AddrSpace, /// isRepeatedByteSequence - Determine whether the given value is /// composed of a repeated sequence of identical bytes and return the /// byte value. If it is not a repeated sequence, return -1. +static int isRepeatedByteSequence(const ConstantDataSequential *V) { + StringRef Data = V->getRawDataValues(); + assert(!Data.empty() && "Empty aggregates should be CAZ node"); + char C = Data[0]; + for (unsigned i = 1, e = Data.size(); i != e; ++i) + if (Data[i] != C) return -1; + return static_cast<uint8_t>(C); // Ensure 255 is not returned as -1. +} + + +/// isRepeatedByteSequence - Determine whether the given value is +/// composed of a repeated sequence of identical bytes and return the +/// byte value. If it is not a repeated sequence, return -1. static int isRepeatedByteSequence(const Value *V, TargetMachine &TM) { if (const ConstantInt *CI = dyn_cast<ConstantInt>(V)) { @@ -1601,8 +1625,7 @@ static int isRepeatedByteSequence(const Value *V, TargetMachine &TM) { if (const ConstantArray *CA = dyn_cast<ConstantArray>(V)) { // Make sure all array elements are sequences of the same repeated // byte. - if (CA->getNumOperands() == 0) return -1; - + assert(CA->getNumOperands() != 0 && "Should be a CAZ"); int Byte = isRepeatedByteSequence(CA->getOperand(0), TM); if (Byte == -1) return -1; @@ -1613,37 +1636,92 @@ static int isRepeatedByteSequence(const Value *V, TargetMachine &TM) { } return Byte; } + + if (const ConstantDataSequential *CDS = dyn_cast<ConstantDataSequential>(V)) + return isRepeatedByteSequence(CDS); return -1; } -static void EmitGlobalConstantArray(const ConstantArray *CA, unsigned AddrSpace, - AsmPrinter &AP) { - if (AddrSpace != 0 || !CA->isString()) { - // Not a string. Print the values in successive locations. - - // See if we can aggregate some values. Make sure it can be - // represented as a series of bytes of the constant value. - int Value = isRepeatedByteSequence(CA, AP.TM); - - if (Value != -1) { - uint64_t Bytes = AP.TM.getTargetData()->getTypeAllocSize(CA->getType()); - AP.OutStreamer.EmitFill(Bytes, Value, AddrSpace); +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()); + // 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); + + // Otherwise, emit the values in successive locations. + unsigned ElementByteSize = CDS->getElementByteSize(); + if (isa<IntegerType>(CDS->getElementType())) { + for (unsigned i = 0, e = CDS->getNumElements(); i != e; ++i) { + if (AP.isVerbose()) + AP.OutStreamer.GetCommentOS() << format("0x%" PRIx64 "\n", + CDS->getElementAsInteger(i)); + AP.OutStreamer.EmitIntValue(CDS->getElementAsInteger(i), + ElementByteSize, AddrSpace); } - else { - for (unsigned i = 0, e = CA->getNumOperands(); i != e; ++i) - EmitGlobalConstantImpl(CA->getOperand(i), AddrSpace, AP); + } else if (ElementByteSize == 4) { + // FP Constants are printed as integer constants to avoid losing + // precision. + assert(CDS->getElementType()->isFloatTy()); + for (unsigned i = 0, e = CDS->getNumElements(); i != e; ++i) { + union { + float F; + uint32_t I; + }; + + F = CDS->getElementAsFloat(i); + if (AP.isVerbose()) + AP.OutStreamer.GetCommentOS() << "float " << F << '\n'; + AP.OutStreamer.EmitIntValue(I, 4, AddrSpace); + } + } else { + assert(CDS->getElementType()->isDoubleTy()); + for (unsigned i = 0, e = CDS->getNumElements(); i != e; ++i) { + union { + double F; + uint64_t I; + }; + + F = CDS->getElementAsDouble(i); + if (AP.isVerbose()) + AP.OutStreamer.GetCommentOS() << "double " << F << '\n'; + AP.OutStreamer.EmitIntValue(I, 8, AddrSpace); } - return; } - // Otherwise, it can be emitted as .ascii. - SmallVector<char, 128> TmpVec; - TmpVec.reserve(CA->getNumOperands()); - for (unsigned i = 0, e = CA->getNumOperands(); i != e; ++i) - TmpVec.push_back(cast<ConstantInt>(CA->getOperand(i))->getZExtValue()); + const TargetData &TD = *AP.TM.getTargetData(); + unsigned Size = TD.getTypeAllocSize(CDS->getType()); + unsigned EmittedSize = TD.getTypeAllocSize(CDS->getType()->getElementType()) * + CDS->getNumElements(); + if (unsigned Padding = Size - EmittedSize) + AP.OutStreamer.EmitZeros(Padding, AddrSpace); + +} - AP.OutStreamer.EmitBytes(StringRef(TmpVec.data(), TmpVec.size()), AddrSpace); +static void EmitGlobalConstantArray(const ConstantArray *CA, unsigned AddrSpace, + AsmPrinter &AP) { + // See if we can aggregate some values. Make sure it can be + // represented as a series of bytes of the constant value. + int Value = isRepeatedByteSequence(CA, AP.TM); + + if (Value != -1) { + uint64_t Bytes = AP.TM.getTargetData()->getTypeAllocSize(CA->getType()); + AP.OutStreamer.EmitFill(Bytes, Value, AddrSpace); + } + else { + for (unsigned i = 0, e = CA->getNumOperands(); i != e; ++i) + EmitGlobalConstantImpl(CA->getOperand(i), AddrSpace, AP); + } } static void EmitGlobalConstantVector(const ConstantVector *CV, @@ -1659,28 +1737,6 @@ static void EmitGlobalConstantVector(const ConstantVector *CV, AP.OutStreamer.EmitZeros(Padding, AddrSpace); } -static void LowerVectorConstant(const Constant *CV, unsigned AddrSpace, - AsmPrinter &AP) { - // Look through bitcasts - if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(CV)) - if (CE->getOpcode() == Instruction::BitCast) - CV = CE->getOperand(0); - - if (const ConstantVector *V = dyn_cast<ConstantVector>(CV)) - return EmitGlobalConstantVector(V, AddrSpace, AP); - - // If we get here, we're stuck; report the problem to the user. - // FIXME: Are there any other useful tricks for vectors? - { - std::string S; - raw_string_ostream OS(S); - OS << "Unsupported vector expression in static initializer: "; - WriteAsOperand(OS, CV, /*PrintType=*/false, - !AP.MF ? 0 : AP.MF->getFunction()->getParent()); - report_fatal_error(OS.str()); - } -} - static void EmitGlobalConstantStruct(const ConstantStruct *CS, unsigned AddrSpace, AsmPrinter &AP) { // Print the fields in successive locations. Pad to align if needed! @@ -1711,16 +1767,14 @@ static void EmitGlobalConstantStruct(const ConstantStruct *CS, static void EmitGlobalConstantFP(const ConstantFP *CFP, unsigned AddrSpace, AsmPrinter &AP) { - // FP Constants are printed as integer constants to avoid losing - // precision. - if (CFP->getType()->isDoubleTy()) { + if (CFP->getType()->isHalfTy()) { if (AP.isVerbose()) { - double Val = CFP->getValueAPF().convertToDouble(); - AP.OutStreamer.GetCommentOS() << "double " << Val << '\n'; + SmallString<10> Str; + CFP->getValueAPF().toString(Str); + AP.OutStreamer.GetCommentOS() << "half " << Str << '\n'; } - uint64_t Val = CFP->getValueAPF().bitcastToAPInt().getZExtValue(); - AP.OutStreamer.EmitIntValue(Val, 8, AddrSpace); + AP.OutStreamer.EmitIntValue(Val, 2, AddrSpace); return; } @@ -1734,6 +1788,19 @@ static void EmitGlobalConstantFP(const ConstantFP *CFP, unsigned AddrSpace, return; } + // FP Constants are printed as integer constants to avoid losing + // precision. + if (CFP->getType()->isDoubleTy()) { + if (AP.isVerbose()) { + double Val = CFP->getValueAPF().convertToDouble(); + AP.OutStreamer.GetCommentOS() << "double " << Val << '\n'; + } + + uint64_t Val = CFP->getValueAPF().bitcastToAPInt().getZExtValue(); + AP.OutStreamer.EmitIntValue(Val, 8, AddrSpace); + return; + } + if (CFP->getType()->isX86_FP80Ty()) { // all long double variants are printed as hex // API needed to prevent premature destruction @@ -1820,12 +1887,6 @@ static void EmitGlobalConstantImpl(const Constant *CV, unsigned AddrSpace, } } - if (const ConstantArray *CVA = dyn_cast<ConstantArray>(CV)) - return EmitGlobalConstantArray(CVA, AddrSpace, AP); - - if (const ConstantStruct *CVS = dyn_cast<ConstantStruct>(CV)) - return EmitGlobalConstantStruct(CVS, AddrSpace, AP); - if (const ConstantFP *CFP = dyn_cast<ConstantFP>(CV)) return EmitGlobalConstantFP(CFP, AddrSpace, AP); @@ -1835,9 +1896,24 @@ static void EmitGlobalConstantImpl(const Constant *CV, unsigned AddrSpace, return; } - if (CV->getType()->isVectorTy()) - return LowerVectorConstant(CV, AddrSpace, AP); + 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); + if (const ConstantStruct *CVS = dyn_cast<ConstantStruct>(CV)) + return EmitGlobalConstantStruct(CVS, AddrSpace, AP); + + // Look through bitcasts, which might not be able to be MCExpr'ized (e.g. of + // vectors). + if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(CV)) + if (CE->getOpcode() == Instruction::BitCast) + return EmitGlobalConstantImpl(CE->getOperand(0), 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), @@ -2146,5 +2222,4 @@ GCMetadataPrinter *AsmPrinter::GetOrCreateGCPrinter(GCStrategy *S) { } report_fatal_error("no GCMetadataPrinter registered for GC: " + Twine(Name)); - return 0; } diff --git a/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp b/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp index 605b775..90d511c 100644 --- a/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp +++ b/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp @@ -25,6 +25,7 @@ #include "llvm/Target/TargetRegisterInfo.h" #include "llvm/ADT/Twine.h" #include "llvm/Support/Dwarf.h" +#include "llvm/Support/ErrorHandling.h" using namespace llvm; //===----------------------------------------------------------------------===// @@ -110,7 +111,7 @@ unsigned AsmPrinter::GetSizeOfEncodedValue(unsigned Encoding) const { return 0; switch (Encoding & 0x07) { - default: assert(0 && "Invalid encoded value."); + default: llvm_unreachable("Invalid encoded value."); case dwarf::DW_EH_PE_absptr: return TM.getTargetData()->getPointerSize(); case dwarf::DW_EH_PE_udata2: return 2; case dwarf::DW_EH_PE_udata4: return 4; @@ -144,9 +145,8 @@ void AsmPrinter::EmitReference(const GlobalValue *GV, unsigned Encoding)const{ void AsmPrinter::EmitSectionOffset(const MCSymbol *Label, const MCSymbol *SectionLabel) const { // On COFF targets, we have to emit the special .secrel32 directive. - if (const char *SecOffDir = MAI->getDwarfSectionOffsetDirective()) { - // FIXME: MCize. - OutStreamer.EmitRawText(SecOffDir + Twine(Label->getName())); + if (MAI->getDwarfSectionOffsetDirective()) { + OutStreamer.EmitCOFFSecRel32(Label); return; } diff --git a/lib/CodeGen/AsmPrinter/DIE.cpp b/lib/CodeGen/AsmPrinter/DIE.cpp index 4f2d3e5..3776848 100644 --- a/lib/CodeGen/AsmPrinter/DIE.cpp +++ b/lib/CodeGen/AsmPrinter/DIE.cpp @@ -112,15 +112,6 @@ DIE::~DIE() { delete Children[i]; } -/// addSiblingOffset - Add a sibling offset field to the front of the DIE. -/// -DIEValue *DIE::addSiblingOffset(BumpPtrAllocator &A) { - DIEInteger *DI = new (A) DIEInteger(0); - Values.insert(Values.begin(), DI); - Abbrev.AddFirstAttribute(dwarf::DW_AT_sibling, dwarf::DW_FORM_ref4); - return DI; -} - #ifndef NDEBUG void DIE::print(raw_ostream &O, unsigned IncIndent) { IndentCount += IncIndent; @@ -174,6 +165,7 @@ void DIE::dump() { } #endif +void DIEValue::anchor() { } #ifndef NDEBUG void DIEValue::dump() { @@ -223,9 +215,8 @@ unsigned DIEInteger::SizeOf(AsmPrinter *AP, unsigned Form) const { 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(); - default: llvm_unreachable("DIE Value form not supported yet"); break; + default: llvm_unreachable("DIE Value form not supported yet"); } - return 0; } #ifndef NDEBUG @@ -319,7 +310,7 @@ unsigned DIEBlock::ComputeSize(AsmPrinter *AP) { /// void DIEBlock::EmitValue(AsmPrinter *Asm, unsigned Form) const { switch (Form) { - default: assert(0 && "Improper form for block"); break; + default: llvm_unreachable("Improper form for block"); case dwarf::DW_FORM_block1: Asm->EmitInt8(Size); break; case dwarf::DW_FORM_block2: Asm->EmitInt16(Size); break; case dwarf::DW_FORM_block4: Asm->EmitInt32(Size); break; @@ -339,9 +330,8 @@ unsigned DIEBlock::SizeOf(AsmPrinter *AP, unsigned Form) const { case dwarf::DW_FORM_block2: return Size + sizeof(int16_t); case dwarf::DW_FORM_block4: return Size + sizeof(int32_t); case dwarf::DW_FORM_block: return Size + MCAsmInfo::getULEB128Size(Size); - default: llvm_unreachable("Improper form for block"); break; + default: llvm_unreachable("Improper form for block"); } - return 0; } #ifndef NDEBUG diff --git a/lib/CodeGen/AsmPrinter/DIE.h b/lib/CodeGen/AsmPrinter/DIE.h index 265446c..f93ea1b 100644 --- a/lib/CodeGen/AsmPrinter/DIE.h +++ b/lib/CodeGen/AsmPrinter/DIE.h @@ -31,17 +31,17 @@ namespace llvm { class DIEAbbrevData { /// Attribute - Dwarf attribute code. /// - unsigned Attribute; + uint16_t Attribute; /// Form - Dwarf form code. /// - unsigned Form; + uint16_t Form; public: - DIEAbbrevData(unsigned A, unsigned F) : Attribute(A), Form(F) {} + DIEAbbrevData(uint16_t A, uint16_t F) : Attribute(A), Form(F) {} // Accessors. - unsigned getAttribute() const { return Attribute; } - unsigned getForm() const { return Form; } + uint16_t getAttribute() const { return Attribute; } + uint16_t getForm() const { return Form; } /// Profile - Used to gather unique data for the abbreviation folding set. /// @@ -54,41 +54,41 @@ namespace llvm { class DIEAbbrev : public FoldingSetNode { /// Tag - Dwarf tag code. /// - unsigned Tag; + uint16_t Tag; - /// Unique number for node. + /// ChildrenFlag - Dwarf children flag. /// - unsigned Number; + uint16_t ChildrenFlag; - /// ChildrenFlag - Dwarf children flag. + /// Unique number for node. /// - unsigned ChildrenFlag; + unsigned Number; /// Data - Raw data bytes for abbreviation. /// SmallVector<DIEAbbrevData, 8> Data; public: - DIEAbbrev(unsigned T, unsigned C) : Tag(T), ChildrenFlag(C), Data() {} + DIEAbbrev(uint16_t T, uint16_t C) : Tag(T), ChildrenFlag(C), Data() {} // Accessors. - unsigned getTag() const { return Tag; } + uint16_t getTag() const { return Tag; } unsigned getNumber() const { return Number; } - unsigned getChildrenFlag() const { return ChildrenFlag; } + uint16_t getChildrenFlag() const { return ChildrenFlag; } const SmallVector<DIEAbbrevData, 8> &getData() const { return Data; } - void setTag(unsigned T) { Tag = T; } - void setChildrenFlag(unsigned CF) { ChildrenFlag = CF; } + void setTag(uint16_t T) { Tag = T; } + void setChildrenFlag(uint16_t CF) { ChildrenFlag = CF; } void setNumber(unsigned N) { Number = N; } /// AddAttribute - Adds another set of attribute information to the /// abbreviation. - void AddAttribute(unsigned Attribute, unsigned Form) { + void AddAttribute(uint16_t Attribute, uint16_t Form) { Data.push_back(DIEAbbrevData(Attribute, Form)); } /// AddFirstAttribute - Adds a set of attribute information to the front /// of the abbreviation. - void AddFirstAttribute(unsigned Attribute, unsigned Form) { + void AddFirstAttribute(uint16_t Attribute, uint16_t Form) { Data.insert(Data.begin(), DIEAbbrevData(Attribute, Form)); } @@ -113,10 +113,6 @@ namespace llvm { class DIE { protected: - /// Abbrev - Buffer for constructing abbreviation. - /// - DIEAbbrev Abbrev; - /// Offset - Offset in debug info section. /// unsigned Offset; @@ -125,6 +121,10 @@ namespace llvm { /// unsigned Size; + /// Abbrev - Buffer for constructing abbreviation. + /// + DIEAbbrev Abbrev; + /// Children DIEs. /// std::vector<DIE *> Children; @@ -139,8 +139,8 @@ namespace llvm { mutable unsigned IndentCount; public: explicit DIE(unsigned Tag) - : Abbrev(Tag, dwarf::DW_CHILDREN_no), Offset(0), - Size(0), Parent(0), IndentCount(0) {} + : Offset(0), Size(0), Abbrev(Tag, dwarf::DW_CHILDREN_no), Parent(0), + IndentCount(0) {} virtual ~DIE(); // Accessors. @@ -163,16 +163,6 @@ namespace llvm { Values.push_back(Value); } - /// SiblingOffset - Return the offset of the debug information entry's - /// sibling. - unsigned getSiblingOffset() const { return Offset + Size; } - - /// addSiblingOffset - Add a sibling offset field to the front of the DIE. - /// The caller is responsible for deleting the return value at or after the - /// same time it destroys this DIE. - /// - DIEValue *addSiblingOffset(BumpPtrAllocator &A); - /// addChild - Add a child to the DIE. /// void addChild(DIE *Child) { @@ -195,6 +185,7 @@ namespace llvm { /// DIEValue - A debug information entry value. /// class DIEValue { + virtual void anchor(); public: enum { isInteger, diff --git a/lib/CodeGen/AsmPrinter/DwarfAccelTable.cpp b/lib/CodeGen/AsmPrinter/DwarfAccelTable.cpp index 6c77a63..644eaad 100644 --- a/lib/CodeGen/AsmPrinter/DwarfAccelTable.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfAccelTable.cpp @@ -24,7 +24,6 @@ using namespace llvm; const char *DwarfAccelTable::Atom::AtomTypeString(enum AtomType AT) { switch (AT) { - default: llvm_unreachable("invalid AtomType!"); case eAtomTypeNULL: return "eAtomTypeNULL"; case eAtomTypeDIEOffset: return "eAtomTypeDIEOffset"; case eAtomTypeCUOffset: return "eAtomTypeCUOffset"; @@ -32,6 +31,7 @@ const char *DwarfAccelTable::Atom::AtomTypeString(enum AtomType AT) { case eAtomTypeNameFlags: return "eAtomTypeNameFlags"; case eAtomTypeTypeFlags: return "eAtomTypeTypeFlags"; } + llvm_unreachable("invalid AtomType!"); } // The general case would need to have a less hard coded size for the @@ -42,16 +42,27 @@ DwarfAccelTable::DwarfAccelTable(DwarfAccelTable::Atom atom) : HeaderData(atom) { } +// The length of the header data is always going to be 4 + 4 + 4*NumAtoms. +DwarfAccelTable::DwarfAccelTable(std::vector<DwarfAccelTable::Atom> &atomList) : + Header(8 + (atomList.size() * 4)), + HeaderData(atomList) { +} + DwarfAccelTable::~DwarfAccelTable() { - for (size_t i = 0, e = Data.size() ; i < e; ++i) + for (size_t i = 0, e = Data.size(); i < e; ++i) delete Data[i]; + for (StringMap<DataArray>::iterator + EI = Entries.begin(), EE = Entries.end(); EI != EE; ++EI) + for (DataArray::iterator DI = EI->second.begin(), + DE = EI->second.end(); DI != DE; ++DI) + delete (*DI); } -void DwarfAccelTable::AddName(StringRef Name, DIE* die) { +void DwarfAccelTable::AddName(StringRef Name, DIE* die, char Flags) { // If the string is in the list already then add this die to the list // otherwise add a new one. - DIEArray &DIEs = Entries[Name]; - DIEs.push_back(die); + DataArray &DIEs = Entries[Name]; + DIEs.push_back(new HashDataContents(die, Flags)); } void DwarfAccelTable::ComputeBucketCount(void) { @@ -76,27 +87,28 @@ void DwarfAccelTable::ComputeBucketCount(void) { namespace { // DIESorter - comparison predicate that sorts DIEs by their offset. struct DIESorter { - bool operator()(DIE *A, DIE *B) const { - return A->getOffset() < B->getOffset(); + bool operator()(const struct DwarfAccelTable::HashDataContents *A, + const struct DwarfAccelTable::HashDataContents *B) const { + return A->Die->getOffset() < B->Die->getOffset(); } }; } void DwarfAccelTable::FinalizeTable(AsmPrinter *Asm, const char *Prefix) { // Create the individual hash data outputs. - for (StringMap<DIEArray>::iterator + for (StringMap<DataArray>::iterator EI = Entries.begin(), EE = Entries.end(); EI != EE; ++EI) { struct HashData *Entry = new HashData((*EI).getKeyData()); // Unique the entries. - std::stable_sort((*EI).second.begin(), (*EI).second.end(), DIESorter()); - (*EI).second.erase(std::unique((*EI).second.begin(), (*EI).second.end()), - (*EI).second.end()); + std::stable_sort(EI->second.begin(), EI->second.end(), DIESorter()); + EI->second.erase(std::unique(EI->second.begin(), EI->second.end()), + EI->second.end()); - for (DIEArray::const_iterator DI = (*EI).second.begin(), - DE = (*EI).second.end(); + for (DataArray::const_iterator DI = EI->second.begin(), + DE = EI->second.end(); DI != DE; ++DI) - Entry->addOffset((*DI)->getOffset()); + Entry->addData((*DI)); Data.push_back(Entry); } @@ -202,11 +214,18 @@ void DwarfAccelTable::EmitData(AsmPrinter *Asm, DwarfDebug *D) { Asm->EmitSectionOffset(D->getStringPoolEntry((*HI)->Str), D->getStringPool()); Asm->OutStreamer.AddComment("Num DIEs"); - Asm->EmitInt32((*HI)->DIEOffsets.size()); - for (std::vector<uint32_t>::const_iterator - DI = (*HI)->DIEOffsets.begin(), DE = (*HI)->DIEOffsets.end(); + Asm->EmitInt32((*HI)->Data.size()); + for (std::vector<struct HashDataContents*>::const_iterator + DI = (*HI)->Data.begin(), DE = (*HI)->Data.end(); DI != DE; ++DI) { - Asm->EmitInt32((*DI)); + // Emit the DIE offset + Asm->EmitInt32((*DI)->Die->getOffset()); + // If we have multiple Atoms emit that info too. + // FIXME: A bit of a hack, we either emit only one atom or all info. + if (HeaderData.Atoms.size() > 1) { + Asm->EmitInt16((*DI)->Die->getTag()); + Asm->EmitInt8((*DI)->Flags); + } } // Emit a 0 to terminate the data unless we have a hash collision. if (PrevHash != (*HI)->HashValue) @@ -242,11 +261,11 @@ void DwarfAccelTable::print(raw_ostream &O) { HeaderData.print(O); O << "Entries: \n"; - for (StringMap<DIEArray>::const_iterator + for (StringMap<DataArray>::const_iterator EI = Entries.begin(), EE = Entries.end(); EI != EE; ++EI) { - O << "Name: " << (*EI).getKeyData() << "\n"; - for (DIEArray::const_iterator DI = (*EI).second.begin(), - DE = (*EI).second.end(); + O << "Name: " << EI->getKeyData() << "\n"; + for (DataArray::const_iterator DI = EI->second.begin(), + DE = EI->second.end(); DI != DE; ++DI) (*DI)->print(O); } diff --git a/lib/CodeGen/AsmPrinter/DwarfAccelTable.h b/lib/CodeGen/AsmPrinter/DwarfAccelTable.h index 0c1e949..2278d4c 100644 --- a/lib/CodeGen/AsmPrinter/DwarfAccelTable.h +++ b/lib/CodeGen/AsmPrinter/DwarfAccelTable.h @@ -22,6 +22,7 @@ #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/Format.h" #include "llvm/Support/FormattedStream.h" +#include "DIE.h" #include <vector> #include <map> @@ -134,6 +135,14 @@ public: eAtomTypeTypeFlags = 5u // Flags from enum TypeFlags }; + 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 { @@ -144,7 +153,7 @@ public: static const char * AtomTypeString(enum AtomType); #ifndef NDEBUG void print(raw_ostream &O) { - O << "Type: " << dwarf::TagString(type) << "\n" + O << "Type: " << AtomTypeString(type) << "\n" << "Form: " << dwarf::FormEncodingString(form) << "\n"; } void dump() { @@ -159,6 +168,13 @@ public: uint32_t die_offset_base; std::vector<Atom> Atoms; + TableHeaderData(std::vector<DwarfAccelTable::Atom> &AtomList, + uint32_t offset = 0) : + die_offset_base(offset) { + for (size_t i = 0, e = AtomList.size(); i != e; ++i) + Atoms.push_back(AtomList[i]); + } + TableHeaderData(DwarfAccelTable::Atom Atom, uint32_t offset = 0) : die_offset_base(offset) { Atoms.push_back(Atom); @@ -184,15 +200,32 @@ public: // uint32_t str_offset // uint32_t hash_data_count // HashData[hash_data_count] +public: + struct HashDataContents { + DIE *Die; // Offsets + char Flags; // Specific flags to output + + HashDataContents(DIE *D, char Flags) : + Die(D), + Flags(Flags) { } + #ifndef NDEBUG + void print(raw_ostream &O) const { + O << " Offset: " << Die->getOffset() << "\n"; + O << " Tag: " << dwarf::TagString(Die->getTag()) << "\n"; + O << " Flags: " << Flags << "\n"; + } + #endif + }; +private: struct HashData { StringRef Str; uint32_t HashValue; MCSymbol *Sym; - std::vector<uint32_t> DIEOffsets; // offsets + std::vector<struct HashDataContents*> Data; // offsets HashData(StringRef S) : Str(S) { HashValue = DwarfAccelTable::HashDJB(S); } - void addOffset(uint32_t off) { DIEOffsets.push_back(off); } + void addData(struct HashDataContents *Datum) { Data.push_back(Datum); } #ifndef NDEBUG void print(raw_ostream &O) { O << "Name: " << Str << "\n"; @@ -201,8 +234,11 @@ public: if (Sym) Sym->print(O); else O << "<none>"; O << "\n"; - for (size_t i = 0; i < DIEOffsets.size(); i++) - O << " Offset: " << DIEOffsets[i] << "\n"; + for (size_t i = 0; i < Data.size(); i++) { + O << " Offset: " << Data[i]->Die->getOffset() << "\n"; + O << " Tag: " << dwarf::TagString(Data[i]->Die->getTag()) << "\n"; + O << " Flags: " << Data[i]->Flags << "\n"; + } } void dump() { print(dbgs()); @@ -226,8 +262,8 @@ public: std::vector<HashData*> Data; // String Data - typedef std::vector<DIE*> DIEArray; - typedef StringMap<DIEArray> StringEntries; + typedef std::vector<struct HashDataContents*> DataArray; + typedef StringMap<DataArray> StringEntries; StringEntries Entries; // Buckets/Hashes/Offsets @@ -238,9 +274,10 @@ public: // Public Implementation public: - DwarfAccelTable(DwarfAccelTable::Atom Atom); + DwarfAccelTable(DwarfAccelTable::Atom); + DwarfAccelTable(std::vector<DwarfAccelTable::Atom> &); ~DwarfAccelTable(); - void AddName(StringRef, DIE*); + void AddName(StringRef, DIE*, char = 0); void FinalizeTable(AsmPrinter *, const char *); void Emit(AsmPrinter *, MCSymbol *, DwarfDebug *); #ifndef NDEBUG diff --git a/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp b/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp index 8ed4f4c..d975f1f 100644 --- a/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp @@ -142,12 +142,14 @@ void DwarfCFIException::EndFunction() { Asm->OutStreamer.EmitCFIEndProc(); + if (!shouldEmitPersonality) + return; + Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("eh_func_end", Asm->getFunctionNumber())); // Map all labels and get rid of any dead landing pads. MMI->TidyLandingPads(); - if (shouldEmitPersonality) - EmitExceptionTable(); + EmitExceptionTable(); } diff --git a/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp b/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp index 8cb5156..51c635e 100644 --- a/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp @@ -13,6 +13,7 @@ #define DEBUG_TYPE "dwarfdebug" +#include "DwarfAccelTable.h" #include "DwarfCompileUnit.h" #include "DwarfDebug.h" #include "llvm/Constants.h" @@ -31,8 +32,9 @@ using namespace llvm; /// CompileUnit - Compile unit constructor. -CompileUnit::CompileUnit(unsigned I, DIE *D, AsmPrinter *A, DwarfDebug *DW) - : ID(I), CUDie(D), Asm(A), DD(DW), IndexTyDie(0) { +CompileUnit::CompileUnit(unsigned I, unsigned L, DIE *D, AsmPrinter *A, + DwarfDebug *DW) + : ID(I), Language(L), CUDie(D), Asm(A), DD(DW), IndexTyDie(0) { DIEIntegerOne = new (DIEValueAllocator) DIEInteger(1); } @@ -608,8 +610,19 @@ DIE *CompileUnit::getOrCreateTypeDIE(const MDNode *TyNode) { } // If this is a named finished type then include it in the list of types // for the accelerator tables. - if (!Ty.getName().empty() && !Ty.isForwardDecl()) - addAccelType(Ty.getName(), TyDIE); + if (!Ty.getName().empty() && !Ty.isForwardDecl()) { + bool IsImplementation = 0; + if (Ty.isCompositeType()) { + DICompositeType CT(Ty); + // A runtime language of 0 actually means C/C++ and that any + // non-negative value is some version of Objective-C/C++. + IsImplementation = (CT.getRunTimeLang() == 0) || + CT.isObjcClassComplete(); + } + unsigned Flags = IsImplementation ? + DwarfAccelTable::eTypeFlagClassIsImplementation : 0; + addAccelType(Ty.getName(), std::make_pair(TyDIE, Flags)); + } addToContextOwner(TyDIE, Ty.getContext()); return TyDIE; @@ -684,7 +697,7 @@ void CompileUnit::constructTypeDIE(DIE &Buffer, DIBasicType BTy) { Buffer.setTag(dwarf::DW_TAG_base_type); addUInt(&Buffer, dwarf::DW_AT_encoding, dwarf::DW_FORM_data1, - BTy.getEncoding()); + BTy.getEncoding()); uint64_t Size = BTy.getSizeInBits() >> 3; addUInt(&Buffer, dwarf::DW_AT_byte_size, 0, Size); @@ -711,7 +724,7 @@ void CompileUnit::constructTypeDIE(DIE &Buffer, DIDerivedType DTy) { addString(&Buffer, dwarf::DW_AT_name, Name); // Add size if non-zero (derived types might be zero-sized.) - if (Size) + if (Size && Tag != dwarf::DW_TAG_pointer_type) addUInt(&Buffer, dwarf::DW_AT_byte_size, 0, Size); // Add source line info if available and TyDesc is not a forward declaration. @@ -767,8 +780,12 @@ void CompileUnit::constructTypeDIE(DIE &Buffer, DICompositeType CTy) { Buffer.addChild(Arg); } } - // Add prototype flag. - if (isPrototyped) + // Add prototype flag if we're dealing with a C language and the + // function has been prototyped. + if (isPrototyped && + (Language == dwarf::DW_LANG_C89 || + Language == dwarf::DW_LANG_C99 || + Language == dwarf::DW_LANG_ObjC)) addUInt(&Buffer, dwarf::DW_AT_prototyped, dwarf::DW_FORM_flag, 1); } break; @@ -812,7 +829,40 @@ void CompileUnit::constructTypeDIE(DIE &Buffer, DICompositeType CTy) { addSourceLine(ElemDie, DV); } else if (Element.isDerivedType()) ElemDie = createMemberDIE(DIDerivedType(Element)); - else + else if (Element.isObjCProperty()) { + DIObjCProperty Property(Element); + ElemDie = new DIE(Property.getTag()); + StringRef PropertyName = Property.getObjCPropertyName(); + addString(ElemDie, dwarf::DW_AT_APPLE_property_name, PropertyName); + StringRef GetterName = Property.getObjCPropertyGetterName(); + if (!GetterName.empty()) + addString(ElemDie, dwarf::DW_AT_APPLE_property_getter, GetterName); + StringRef SetterName = Property.getObjCPropertySetterName(); + if (!SetterName.empty()) + addString(ElemDie, dwarf::DW_AT_APPLE_property_setter, SetterName); + unsigned PropertyAttributes = 0; + if (Property.isReadOnlyObjCProperty()) + PropertyAttributes |= dwarf::DW_APPLE_PROPERTY_readonly; + if (Property.isReadWriteObjCProperty()) + PropertyAttributes |= dwarf::DW_APPLE_PROPERTY_readwrite; + if (Property.isAssignObjCProperty()) + PropertyAttributes |= dwarf::DW_APPLE_PROPERTY_assign; + if (Property.isRetainObjCProperty()) + PropertyAttributes |= dwarf::DW_APPLE_PROPERTY_retain; + if (Property.isCopyObjCProperty()) + PropertyAttributes |= dwarf::DW_APPLE_PROPERTY_copy; + if (Property.isNonAtomicObjCProperty()) + PropertyAttributes |= dwarf::DW_APPLE_PROPERTY_nonatomic; + if (PropertyAttributes) + addUInt(ElemDie, dwarf::DW_AT_APPLE_property_attribute, 0, + PropertyAttributes); + + DIEEntry *Entry = getDIEEntry(Element); + if (!Entry) { + Entry = createDIEEntry(ElemDie); + insertDIEEntry(Element, Entry); + } + } else continue; Buffer.addChild(ElemDie); } @@ -838,7 +888,11 @@ void CompileUnit::constructTypeDIE(DIE &Buffer, DICompositeType CTy) { addUInt(&Buffer, dwarf::DW_AT_APPLE_objc_complete_type, dwarf::DW_FORM_flag, 1); - if (Tag == dwarf::DW_TAG_class_type) + // Add template parameters to a class, structure or union types. + // FIXME: The support isn't in the metadata for this yet. + if (Tag == dwarf::DW_TAG_class_type || + Tag == dwarf::DW_TAG_structure_type || + Tag == dwarf::DW_TAG_union_type) addTemplateParams(Buffer, CTy.getTemplateParams()); break; @@ -973,7 +1027,12 @@ DIE *CompileUnit::getOrCreateSubprogramDIE(DISubprogram SP) { addSourceLine(SPDie, SP); - if (SP.isPrototyped()) + // Add the prototype if we have a prototype and we have a C like + // language. + if (SP.isPrototyped() && + (Language == dwarf::DW_LANG_C89 || + Language == dwarf::DW_LANG_C99 || + Language == dwarf::DW_LANG_ObjC)) addUInt(SPDie, dwarf::DW_AT_prototyped, dwarf::DW_FORM_flag, 1); // Add Return Type. @@ -1412,6 +1471,12 @@ DIE *CompileUnit::createMemberDIE(DIDerivedType DT) { dwarf::DW_VIRTUALITY_virtual); // Objective-C properties. + if (MDNode *PNode = DT.getObjCProperty()) + if (DIEEntry *PropertyDie = getDIEEntry(PNode)) + MemberDie->addValue(dwarf::DW_AT_APPLE_property, dwarf::DW_FORM_ref4, + PropertyDie); + + // This is only for backward compatibility. StringRef PropertyName = DT.getObjCPropertyName(); if (!PropertyName.empty()) { addString(MemberDie, dwarf::DW_AT_APPLE_property_name, PropertyName); diff --git a/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h b/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h index 07a7723..4e63c3f 100644 --- a/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h +++ b/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h @@ -36,6 +36,10 @@ class CompileUnit { /// unsigned ID; + /// Language - The DW_AT_language of the compile unit + /// + unsigned Language; + /// Die - Compile unit debug information entry. /// const OwningPtr<DIE> CUDie; @@ -65,7 +69,7 @@ class CompileUnit { StringMap<std::vector<DIE*> > AccelNames; StringMap<std::vector<DIE*> > AccelObjC; StringMap<std::vector<DIE*> > AccelNamespace; - StringMap<std::vector<DIE*> > AccelTypes; + StringMap<std::vector<std::pair<DIE*, unsigned> > > AccelTypes; /// DIEBlocks - A list of all the DIEBlocks in use. std::vector<DIEBlock *> DIEBlocks; @@ -76,11 +80,12 @@ class CompileUnit { DenseMap<DIE *, const MDNode *> ContainingTypeMap; public: - CompileUnit(unsigned I, DIE *D, AsmPrinter *A, DwarfDebug *DW); + CompileUnit(unsigned I, unsigned L, DIE *D, AsmPrinter *A, DwarfDebug *DW); ~CompileUnit(); // Accessors. unsigned getID() const { return ID; } + unsigned getLanguage() const { return Language; } DIE* getCUDie() const { return CUDie.get(); } const StringMap<DIE*> &getGlobalTypes() const { return GlobalTypes; } @@ -93,7 +98,8 @@ public: const StringMap<std::vector<DIE*> > &getAccelNamespace() const { return AccelNamespace; } - const StringMap<std::vector<DIE*> > &getAccelTypes() const { + const StringMap<std::vector<std::pair<DIE*, unsigned > > > + &getAccelTypes() const { return AccelTypes; } @@ -119,8 +125,8 @@ public: std::vector<DIE*> &DIEs = AccelNamespace[Name]; DIEs.push_back(Die); } - void addAccelType(StringRef Name, DIE *Die) { - std::vector<DIE*> &DIEs = AccelTypes[Name]; + void addAccelType(StringRef Name, std::pair<DIE *, unsigned> Die) { + std::vector<std::pair<DIE*, unsigned > > &DIEs = AccelTypes[Name]; DIEs.push_back(Die); } diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp index a3db96a..fa62169 100644 --- a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -389,8 +389,7 @@ DIE *DwarfDebug::constructInlinedScopeDIE(CompileUnit *TheCU, const MCSymbol *EndLabel = getLabelAfterInsn(RI->second); if (StartLabel == 0 || EndLabel == 0) { - assert(0 && "Unexpected Start and End labels for a inlined scope!"); - return 0; + llvm_unreachable("Unexpected Start and End labels for a inlined scope!"); } assert(StartLabel->isDefined() && "Invalid starting label for an inlined scope!"); @@ -449,8 +448,6 @@ DIE *DwarfDebug::constructInlinedScopeDIE(CompileUnit *TheCU, return ScopeDIE; } - - /// constructScopeDIE - Construct a DIE for this scope. DIE *DwarfDebug::constructScopeDIE(CompileUnit *TheCU, LexicalScope *Scope) { if (!Scope || !Scope->getScopeNode()) @@ -533,7 +530,7 @@ unsigned DwarfDebug::GetOrCreateSourceID(StringRef FileName, std::map<std::pair<std::string, std::string>, unsigned>::iterator I; bool NewlyInserted; - tie(I, NewlyInserted) = SourceIdMap.insert(Entry); + llvm::tie(I, NewlyInserted) = SourceIdMap.insert(Entry); if (!NewlyInserted) return I->second; @@ -553,7 +550,7 @@ CompileUnit *DwarfDebug::constructCompileUnit(const MDNode *N) { unsigned ID = GetOrCreateSourceID(FN, CompilationDir); DIE *Die = new DIE(dwarf::DW_TAG_compile_unit); - CompileUnit *NewCU = new CompileUnit(ID, Die, Asm, this); + CompileUnit *NewCU = new CompileUnit(ID, DIUnit.getLanguage(), Die, Asm, this); NewCU->addString(Die, dwarf::DW_AT_producer, DIUnit.getProducer()); NewCU->addUInt(Die, dwarf::DW_AT_language, dwarf::DW_FORM_data2, DIUnit.getLanguage()); @@ -958,8 +955,7 @@ static DotDebugLocEntry getDebugLocEntry(AsmPrinter *Asm, if (MI->getOperand(0).isCImm()) return DotDebugLocEntry(FLabel, SLabel, MI->getOperand(0).getCImm()); - assert(0 && "Unexpected 3 operand DBG_VALUE instruction!"); - return DotDebugLocEntry(); + llvm_unreachable("Unexpected 3 operand DBG_VALUE instruction!"); } /// collectVariableInfo - Find variables for each lexical scope. @@ -1055,7 +1051,8 @@ DwarfDebug::collectVariableInfo(const MachineFunction *MF, } // The value is valid until the next DBG_VALUE or clobber. - DotDebugLocEntries.push_back(getDebugLocEntry(Asm, FLabel, SLabel, Begin)); + DotDebugLocEntries.push_back(getDebugLocEntry(Asm, FLabel, SLabel, + Begin)); } DotDebugLocEntries.push_back(DotDebugLocEntry()); } @@ -1297,7 +1294,7 @@ void DwarfDebug::beginFunction(const MachineFunction *MF) { MOE = MI->operands_end(); MOI != MOE; ++MOI) { if (!MOI->isReg() || !MOI->isDef() || !MOI->getReg()) continue; - for (const unsigned *AI = TRI->getOverlaps(MOI->getReg()); + for (const uint16_t *AI = TRI->getOverlaps(MOI->getReg()); unsigned Reg = *AI; ++AI) { const MDNode *Var = LiveUserVar[Reg]; if (!Var) @@ -1471,7 +1468,7 @@ void DwarfDebug::recordSourceLine(unsigned Line, unsigned Col, const MDNode *S, Fn = DB.getFilename(); Dir = DB.getDirectory(); } else - assert(0 && "Unexpected scope info"); + llvm_unreachable("Unexpected scope info"); Src = GetOrCreateSourceID(Fn, Dir); } @@ -1489,10 +1486,6 @@ DwarfDebug::computeSizeAndOffset(DIE *Die, unsigned Offset, bool Last) { // Get the children. const std::vector<DIE *> &Children = Die->getChildren(); - // If not last sibling and has children then add sibling offset attribute. - if (!Last && !Children.empty()) - Die->addSiblingOffset(DIEValueAllocator); - // Record the abbreviation. assignAbbrevNumber(Die->getAbbrev()); @@ -1603,9 +1596,6 @@ void DwarfDebug::emitDIE(DIE *Die) { Asm->OutStreamer.AddComment(dwarf::AttributeString(Attr)); switch (Attr) { - case dwarf::DW_AT_sibling: - Asm->EmitInt32(Die->getSiblingOffset()); - break; case dwarf::DW_AT_abstract_origin: { DIEEntry *E = cast<DIEEntry>(Values[i]); DIE *Origin = E->getEntry(); @@ -1617,7 +1607,7 @@ void DwarfDebug::emitDIE(DIE *Die) { // DW_AT_range Value encodes offset in debug_range section. DIEInteger *V = cast<DIEInteger>(Values[i]); - if (Asm->MAI->doesDwarfUsesLabelOffsetForRanges()) { + if (Asm->MAI->doesDwarfUseLabelOffsetForRanges()) { Asm->EmitLabelPlusOffset(DwarfDebugRangeSectionSym, V->getValue(), 4); @@ -1768,7 +1758,7 @@ void DwarfDebug::emitAccelNames() { for (StringMap<std::vector<DIE*> >::const_iterator GI = Names.begin(), GE = Names.end(); GI != GE; ++GI) { const char *Name = GI->getKeyData(); - std::vector<DIE *> Entities = GI->second; + const std::vector<DIE *> &Entities = GI->second; for (std::vector<DIE *>::const_iterator DI = Entities.begin(), DE = Entities.end(); DI != DE; ++DI) AT.AddName(Name, (*DI)); @@ -1797,7 +1787,7 @@ void DwarfDebug::emitAccelObjC() { for (StringMap<std::vector<DIE*> >::const_iterator GI = Names.begin(), GE = Names.end(); GI != GE; ++GI) { const char *Name = GI->getKeyData(); - std::vector<DIE *> Entities = GI->second; + const std::vector<DIE *> &Entities = GI->second; for (std::vector<DIE *>::const_iterator DI = Entities.begin(), DE = Entities.end(); DI != DE; ++DI) AT.AddName(Name, (*DI)); @@ -1826,7 +1816,7 @@ void DwarfDebug::emitAccelNamespaces() { for (StringMap<std::vector<DIE*> >::const_iterator GI = Names.begin(), GE = Names.end(); GI != GE; ++GI) { const char *Name = GI->getKeyData(); - std::vector<DIE *> Entities = GI->second; + const std::vector<DIE *> &Entities = GI->second; for (std::vector<DIE *>::const_iterator DI = Entities.begin(), DE = Entities.end(); DI != DE; ++DI) AT.AddName(Name, (*DI)); @@ -1845,19 +1835,26 @@ void DwarfDebug::emitAccelNamespaces() { /// emitAccelTypes() - Emit type dies into a hashed accelerator table. void DwarfDebug::emitAccelTypes() { - DwarfAccelTable AT(DwarfAccelTable::Atom(DwarfAccelTable::eAtomTypeDIEOffset, - dwarf::DW_FORM_data4)); + std::vector<DwarfAccelTable::Atom> Atoms; + Atoms.push_back(DwarfAccelTable::Atom(DwarfAccelTable::eAtomTypeDIEOffset, + dwarf::DW_FORM_data4)); + Atoms.push_back(DwarfAccelTable::Atom(DwarfAccelTable::eAtomTypeTag, + dwarf::DW_FORM_data2)); + Atoms.push_back(DwarfAccelTable::Atom(DwarfAccelTable::eAtomTypeTypeFlags, + dwarf::DW_FORM_data1)); + DwarfAccelTable AT(Atoms); for (DenseMap<const MDNode *, CompileUnit *>::iterator I = CUMap.begin(), E = CUMap.end(); I != E; ++I) { CompileUnit *TheCU = I->second; - const StringMap<std::vector<DIE*> > &Names = TheCU->getAccelTypes(); - for (StringMap<std::vector<DIE*> >::const_iterator + const StringMap<std::vector<std::pair<DIE*, unsigned > > > &Names + = TheCU->getAccelTypes(); + for (StringMap<std::vector<std::pair<DIE*, unsigned> > >::const_iterator GI = Names.begin(), GE = Names.end(); GI != GE; ++GI) { const char *Name = GI->getKeyData(); - std::vector<DIE *> Entities = GI->second; - for (std::vector<DIE *>::const_iterator DI = Entities.begin(), - DE= Entities.end(); DI !=DE; ++DI) - AT.AddName(Name, (*DI)); + const std::vector<std::pair<DIE *, unsigned> > &Entities = GI->second; + for (std::vector<std::pair<DIE *, unsigned> >::const_iterator DI + = Entities.begin(), DE = Entities.end(); DI !=DE; ++DI) + AT.AddName(Name, (*DI).first, (*DI).second); } } @@ -2103,7 +2100,7 @@ void DwarfDebug::emitDebugMacInfo() { /// __debug_info section, and the low_pc is the starting address for the /// inlining instance. void DwarfDebug::emitDebugInlineInfo() { - if (!Asm->MAI->doesDwarfUsesInlineInfoSection()) + if (!Asm->MAI->doesDwarfUseInlineInfoSection()) return; if (!FirstCU) @@ -2135,10 +2132,9 @@ void DwarfDebug::emitDebugInlineInfo() { StringRef Name = SP.getName(); Asm->OutStreamer.AddComment("MIPS linkage name"); - if (LName.empty()) { - Asm->OutStreamer.EmitBytes(Name, 0); - Asm->OutStreamer.EmitIntValue(0, 1, 0); // nul terminator. - } else + if (LName.empty()) + Asm->EmitSectionOffset(getStringPoolEntry(Name), DwarfStrSectionSym); + else Asm->EmitSectionOffset(getStringPoolEntry(getRealLinkageName(LName)), DwarfStrSectionSym); diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.h b/lib/CodeGen/AsmPrinter/DwarfDebug.h index 16e9137..8b802d2 100644 --- a/lib/CodeGen/AsmPrinter/DwarfDebug.h +++ b/lib/CodeGen/AsmPrinter/DwarfDebug.h @@ -31,6 +31,8 @@ namespace llvm { class CompileUnit; +class ConstantInt; +class ConstantFP; class DbgVariable; class MachineFrameInfo; class MachineModuleInfo; @@ -242,7 +244,7 @@ class DwarfDebug { SmallPtrSet<DIE *, 4> InlinedSubprogramDIEs; /// InlineInfo - Keep track of inlined functions and their location. This - /// information is used to populate debug_inlined section. + /// 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; diff --git a/lib/CodeGen/AsmPrinter/DwarfException.cpp b/lib/CodeGen/AsmPrinter/DwarfException.cpp index bf7f7ee..70cc2e5 100644 --- a/lib/CodeGen/AsmPrinter/DwarfException.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfException.cpp @@ -31,6 +31,7 @@ #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" @@ -714,17 +715,17 @@ void DwarfException::EmitExceptionTable() { /// EndModule - Emit all exception information that should come after the /// content. void DwarfException::EndModule() { - assert(0 && "Should be implemented"); + llvm_unreachable("Should be implemented"); } /// BeginFunction - Gather pre-function exception information. Assumes it's /// being emitted immediately after the function entry point. void DwarfException::BeginFunction(const MachineFunction *MF) { - assert(0 && "Should be implemented"); + llvm_unreachable("Should be implemented"); } /// EndFunction - Gather and emit post-function exception information. /// void DwarfException::EndFunction() { - assert(0 && "Should be implemented"); + llvm_unreachable("Should be implemented"); } |