diff options
author | rdivacky <rdivacky@FreeBSD.org> | 2009-10-14 17:57:32 +0000 |
---|---|---|
committer | rdivacky <rdivacky@FreeBSD.org> | 2009-10-14 17:57:32 +0000 |
commit | cd749a9c07f1de2fb8affde90537efa4bc3e7c54 (patch) | |
tree | b21f6de4e08b89bb7931806bab798fc2a5e3a686 /lib/CodeGen/AsmPrinter | |
parent | 72621d11de5b873f1695f391eb95f0b336c3d2d4 (diff) | |
download | FreeBSD-src-cd749a9c07f1de2fb8affde90537efa4bc3e7c54.zip FreeBSD-src-cd749a9c07f1de2fb8affde90537efa4bc3e7c54.tar.gz |
Update llvm to r84119.
Diffstat (limited to 'lib/CodeGen/AsmPrinter')
-rw-r--r-- | lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 1194 | ||||
-rw-r--r-- | lib/CodeGen/AsmPrinter/DIE.cpp | 57 | ||||
-rw-r--r-- | lib/CodeGen/AsmPrinter/DIE.h | 34 | ||||
-rw-r--r-- | lib/CodeGen/AsmPrinter/DwarfDebug.cpp | 1161 | ||||
-rw-r--r-- | lib/CodeGen/AsmPrinter/DwarfDebug.h | 115 | ||||
-rw-r--r-- | lib/CodeGen/AsmPrinter/DwarfException.cpp | 917 | ||||
-rw-r--r-- | lib/CodeGen/AsmPrinter/DwarfException.h | 60 | ||||
-rw-r--r-- | lib/CodeGen/AsmPrinter/DwarfLabel.cpp | 7 | ||||
-rw-r--r-- | lib/CodeGen/AsmPrinter/DwarfLabel.h | 10 | ||||
-rw-r--r-- | lib/CodeGen/AsmPrinter/DwarfPrinter.cpp | 40 | ||||
-rw-r--r-- | lib/CodeGen/AsmPrinter/DwarfPrinter.h | 10 | ||||
-rw-r--r-- | lib/CodeGen/AsmPrinter/DwarfWriter.cpp | 34 | ||||
-rw-r--r-- | lib/CodeGen/AsmPrinter/OcamlGCPrinter.cpp | 70 |
13 files changed, 2334 insertions, 1375 deletions
diff --git a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index 6d12581..8bc5ef9 100644 --- a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -18,16 +18,25 @@ #include "llvm/Module.h" #include "llvm/CodeGen/GCMetadataPrinter.h" #include "llvm/CodeGen/MachineConstantPool.h" +#include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineJumpTableInfo.h" +#include "llvm/CodeGen/MachineLoopInfo.h" #include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/CodeGen/DwarfWriter.h" #include "llvm/Analysis/DebugInfo.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCInst.h" +#include "llvm/MC/MCSection.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCSymbol.h" #include "llvm/Support/CommandLine.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/FormattedStream.h" #include "llvm/Support/Mangler.h" -#include "llvm/Support/raw_ostream.h" -#include "llvm/Target/TargetAsmInfo.h" +#include "llvm/MC/MCAsmInfo.h" #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetLowering.h" +#include "llvm/Target/TargetLoweringObjectFile.h" #include "llvm/Target/TargetOptions.h" #include "llvm/Target/TargetRegisterInfo.h" #include "llvm/ADT/SmallPtrSet.h" @@ -41,12 +50,17 @@ AsmVerbose("asm-verbose", cl::desc("Add comments to directives."), cl::init(cl::BOU_UNSET)); char AsmPrinter::ID = 0; -AsmPrinter::AsmPrinter(raw_ostream &o, TargetMachine &tm, - const TargetAsmInfo *T, bool VDef) +AsmPrinter::AsmPrinter(formatted_raw_ostream &o, TargetMachine &tm, + const MCAsmInfo *T, bool VDef) : MachineFunctionPass(&ID), FunctionNumber(0), O(o), - TM(tm), TAI(T), TRI(tm.getRegisterInfo()), - IsInTextSection(false), LastMI(0), LastFn(0), Counter(~0U), - PrevDLT(0, ~0U, ~0U) { + TM(tm), MAI(T), TRI(tm.getRegisterInfo()), + + OutContext(*new MCContext()), + // FIXME: Pass instprinter to streamer. + OutStreamer(*createAsmStreamer(OutContext, O, *T, 0)), + + LastMI(0), LastFn(0), Counter(~0U), + PrevDLT(0, 0, ~0U, ~0U) { DW = 0; MMI = 0; switch (AsmVerbose) { case cl::BOU_UNSET: VerboseAsm = VDef; break; @@ -59,188 +73,124 @@ AsmPrinter::~AsmPrinter() { for (gcp_iterator I = GCMetadataPrinters.begin(), E = GCMetadataPrinters.end(); I != E; ++I) delete I->second; -} - -/// SwitchToTextSection - Switch to the specified text section of the executable -/// if we are not already in it! -/// -void AsmPrinter::SwitchToTextSection(const char *NewSection, - const GlobalValue *GV) { - std::string NS; - if (GV && GV->hasSection()) - NS = TAI->getSwitchToSectionDirective() + GV->getSection(); - else - NS = NewSection; - // If we're already in this section, we're done. - if (CurrentSection == NS) return; - - // Close the current section, if applicable. - if (TAI->getSectionEndDirectiveSuffix() && !CurrentSection.empty()) - O << CurrentSection << TAI->getSectionEndDirectiveSuffix() << '\n'; - - CurrentSection = NS; - - if (!CurrentSection.empty()) - O << CurrentSection << TAI->getTextSectionStartSuffix() << '\n'; - - IsInTextSection = true; + delete &OutStreamer; + delete &OutContext; } -/// SwitchToDataSection - Switch to the specified data section of the executable -/// if we are not already in it! -/// -void AsmPrinter::SwitchToDataSection(const char *NewSection, - const GlobalValue *GV) { - std::string NS; - if (GV && GV->hasSection()) - NS = TAI->getSwitchToSectionDirective() + GV->getSection(); - else - NS = NewSection; - - // If we're already in this section, we're done. - if (CurrentSection == NS) return; - - // Close the current section, if applicable. - if (TAI->getSectionEndDirectiveSuffix() && !CurrentSection.empty()) - O << CurrentSection << TAI->getSectionEndDirectiveSuffix() << '\n'; - - CurrentSection = NS; - - if (!CurrentSection.empty()) - O << CurrentSection << TAI->getDataSectionStartSuffix() << '\n'; - - IsInTextSection = false; +TargetLoweringObjectFile &AsmPrinter::getObjFileLowering() const { + return TM.getTargetLowering()->getObjFileLowering(); } -/// SwitchToSection - Switch to the specified section of the executable if we -/// are not already in it! -void AsmPrinter::SwitchToSection(const Section* NS) { - const std::string& NewSection = NS->getName(); - - // If we're already in this section, we're done. - if (CurrentSection == NewSection) return; - - // Close the current section, if applicable. - if (TAI->getSectionEndDirectiveSuffix() && !CurrentSection.empty()) - O << CurrentSection << TAI->getSectionEndDirectiveSuffix() << '\n'; - - // FIXME: Make CurrentSection a Section* in the future - CurrentSection = NewSection; - CurrentSection_ = NS; - - if (!CurrentSection.empty()) { - // If section is named we need to switch into it via special '.section' - // directive and also append funky flags. Otherwise - section name is just - // some magic assembler directive. - if (NS->isNamed()) - O << TAI->getSwitchToSectionDirective() - << CurrentSection - << TAI->getSectionFlags(NS->getFlags()); - else - O << CurrentSection; - O << TAI->getDataSectionStartSuffix() << '\n'; - } - - IsInTextSection = (NS->getFlags() & SectionFlags::Code); +/// getCurrentSection() - Return the current section we are emitting to. +const MCSection *AsmPrinter::getCurrentSection() const { + return OutStreamer.getCurrentSection(); } + void AsmPrinter::getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); MachineFunctionPass::getAnalysisUsage(AU); AU.addRequired<GCModuleInfo>(); + if (VerboseAsm) + AU.addRequired<MachineLoopInfo>(); } bool AsmPrinter::doInitialization(Module &M) { - Mang = new Mangler(M, TAI->getGlobalPrefix(), TAI->getPrivateGlobalPrefix()); + // Initialize TargetLoweringObjectFile. + const_cast<TargetLoweringObjectFile&>(getObjFileLowering()) + .Initialize(OutContext, TM); - if (TAI->doesAllowQuotesInName()) + Mang = new Mangler(M, MAI->getGlobalPrefix(), MAI->getPrivateGlobalPrefix(), + MAI->getLinkerPrivateGlobalPrefix()); + + if (MAI->doesAllowQuotesInName()) Mang->setUseQuotes(true); + + if (MAI->doesAllowNameToStartWithDigit()) + Mang->setSymbolsCanStartWithDigit(true); - GCModuleInfo *MI = getAnalysisIfAvailable<GCModuleInfo>(); - assert(MI && "AsmPrinter didn't require GCModuleInfo?"); + // Allow the target to emit any magic that it wants at the start of the file. + EmitStartOfAsmFile(M); - if (TAI->hasSingleParameterDotFile()) { + if (MAI->hasSingleParameterDotFile()) { /* Very minimal debug info. It is ignored if we emit actual - debug info. If we don't, this at helps the user find where + debug info. If we don't, this at least helps the user find where a function came from. */ O << "\t.file\t\"" << M.getModuleIdentifier() << "\"\n"; } + GCModuleInfo *MI = getAnalysisIfAvailable<GCModuleInfo>(); + assert(MI && "AsmPrinter didn't require GCModuleInfo?"); for (GCModuleInfo::iterator I = MI->begin(), E = MI->end(); I != E; ++I) if (GCMetadataPrinter *MP = GetOrCreateGCPrinter(*I)) - MP->beginAssembly(O, *this, *TAI); + MP->beginAssembly(O, *this, *MAI); if (!M.getModuleInlineAsm().empty()) - O << TAI->getCommentString() << " Start of file scope inline assembly\n" + O << MAI->getCommentString() << " Start of file scope inline assembly\n" << M.getModuleInlineAsm() - << '\n' << TAI->getCommentString() + << '\n' << MAI->getCommentString() << " End of file scope inline assembly\n"; - SwitchToDataSection(""); // Reset back to no section. - - if (TAI->doesSupportDebugInformation() || - TAI->doesSupportExceptionHandling()) { - MMI = getAnalysisIfAvailable<MachineModuleInfo>(); - if (MMI) - MMI->AnalyzeModule(M); - DW = getAnalysisIfAvailable<DwarfWriter>(); - if (DW) - DW->BeginModule(&M, MMI, O, this, TAI); - } + MMI = getAnalysisIfAvailable<MachineModuleInfo>(); + if (MMI) + MMI->AnalyzeModule(M); + DW = getAnalysisIfAvailable<DwarfWriter>(); + if (DW) + DW->BeginModule(&M, MMI, O, this, MAI); return false; } bool AsmPrinter::doFinalization(Module &M) { + // Emit global variables. + for (Module::const_global_iterator I = M.global_begin(), E = M.global_end(); + I != E; ++I) + PrintGlobalVariable(I); + // Emit final debug information. - if (TAI->doesSupportDebugInformation() || TAI->doesSupportExceptionHandling()) + if (MAI->doesSupportDebugInformation() || MAI->doesSupportExceptionHandling()) DW->EndModule(); // If the target wants to know about weak references, print them all. - if (TAI->getWeakRefDirective()) { + if (MAI->getWeakRefDirective()) { // FIXME: This is not lazy, it would be nice to only print weak references // to stuff that is actually used. Note that doing so would require targets // to notice uses in operands (due to constant exprs etc). This should // happen with the MC stuff eventually. - SwitchToDataSection(""); // Print out module-level global variables here. for (Module::const_global_iterator I = M.global_begin(), E = M.global_end(); I != E; ++I) { if (I->hasExternalWeakLinkage()) - O << TAI->getWeakRefDirective() << Mang->getValueName(I) << '\n'; + O << MAI->getWeakRefDirective() << Mang->getMangledName(I) << '\n'; } - for (Module::const_iterator I = M.begin(), E = M.end(); - I != E; ++I) { + for (Module::const_iterator I = M.begin(), E = M.end(); I != E; ++I) { if (I->hasExternalWeakLinkage()) - O << TAI->getWeakRefDirective() << Mang->getValueName(I) << '\n'; + O << MAI->getWeakRefDirective() << Mang->getMangledName(I) << '\n'; } } - if (TAI->getSetDirective()) { - if (!M.alias_empty()) - SwitchToSection(TAI->getTextSection()); - + if (MAI->getSetDirective()) { O << '\n'; for (Module::const_alias_iterator I = M.alias_begin(), E = M.alias_end(); I != E; ++I) { - std::string Name = Mang->getValueName(I); - std::string Target; + std::string Name = Mang->getMangledName(I); const GlobalValue *GV = cast<GlobalValue>(I->getAliasedGlobal()); - Target = Mang->getValueName(GV); + std::string Target = Mang->getMangledName(GV); - if (I->hasExternalLinkage() || !TAI->getWeakRefDirective()) + if (I->hasExternalLinkage() || !MAI->getWeakRefDirective()) O << "\t.globl\t" << Name << '\n'; else if (I->hasWeakLinkage()) - O << TAI->getWeakRefDirective() << Name << '\n'; + O << MAI->getWeakRefDirective() << Name << '\n'; else if (!I->hasLocalLinkage()) - assert(0 && "Invalid alias linkage"); + llvm_unreachable("Invalid alias linkage"); printVisibility(Name, I->getVisibility()); - O << TAI->getSetDirective() << ' ' << Name << ", " << Target << '\n'; + O << MAI->getSetDirective() << ' ' << Name << ", " << Target << '\n'; } } @@ -248,45 +198,43 @@ bool AsmPrinter::doFinalization(Module &M) { assert(MI && "AsmPrinter didn't require GCModuleInfo?"); for (GCModuleInfo::iterator I = MI->end(), E = MI->begin(); I != E; ) if (GCMetadataPrinter *MP = GetOrCreateGCPrinter(*--I)) - MP->finishAssembly(O, *this, *TAI); + MP->finishAssembly(O, *this, *MAI); // If we don't have any trampolines, then we don't require stack memory // to be executable. Some targets have a directive to declare this. Function *InitTrampolineIntrinsic = M.getFunction("llvm.init.trampoline"); if (!InitTrampolineIntrinsic || InitTrampolineIntrinsic->use_empty()) - if (TAI->getNonexecutableStackDirective()) - O << TAI->getNonexecutableStackDirective() << '\n'; + if (MAI->getNonexecutableStackDirective()) + O << MAI->getNonexecutableStackDirective() << '\n'; + + // Allow the target to emit any magic that it wants at the end of the file, + // after everything else has gone out. + EmitEndOfAsmFile(M); + delete Mang; Mang = 0; DW = 0; MMI = 0; + + OutStreamer.Finish(); return false; } -const std::string & -AsmPrinter::getCurrentFunctionEHName(const MachineFunction *MF, - std::string &Name) const { - assert(MF && "No machine function?"); - Name = MF->getFunction()->getName(); - if (Name.empty()) - Name = Mang->getValueName(MF->getFunction()); - Name = Mang->makeNameProper(TAI->getEHGlobalPrefix() + - Name + ".eh", TAI->getGlobalPrefix()); - return Name; -} - void AsmPrinter::SetupMachineFunction(MachineFunction &MF) { // What's my mangled name? - CurrentFnName = Mang->getValueName(MF.getFunction()); + CurrentFnName = Mang->getMangledName(MF.getFunction()); IncrementFunctionNumber(); + + if (VerboseAsm) + LI = &getAnalysis<MachineLoopInfo>(); } namespace { // SectionCPs - Keep track the alignment, constpool entries per Section. struct SectionCPs { - const Section *S; + const MCSection *S; unsigned Alignment; SmallVector<unsigned, 4> CPEs; - SectionCPs(const Section *s, unsigned a) : S(s), Alignment(a) {}; + SectionCPs(const MCSection *s, unsigned a) : S(s), Alignment(a) {}; }; } @@ -303,9 +251,27 @@ void AsmPrinter::EmitConstantPool(MachineConstantPool *MCP) { // the same section together to reduce amount of section switch statements. SmallVector<SectionCPs, 4> CPSections; for (unsigned i = 0, e = CP.size(); i != e; ++i) { - MachineConstantPoolEntry CPE = CP[i]; + const MachineConstantPoolEntry &CPE = CP[i]; unsigned Align = CPE.getAlignment(); - const Section* S = TAI->SelectSectionForMachineConst(CPE.getType()); + + SectionKind Kind; + switch (CPE.getRelocationInfo()) { + default: llvm_unreachable("Unknown section kind"); + case 2: Kind = SectionKind::getReadOnlyWithRel(); break; + case 1: + Kind = SectionKind::getReadOnlyWithRelLocal(); + break; + case 0: + switch (TM.getTargetData()->getTypeAllocSize(CPE.getType())) { + case 4: Kind = SectionKind::getMergeableConst4(); break; + case 8: Kind = SectionKind::getMergeableConst8(); break; + case 16: Kind = SectionKind::getMergeableConst16();break; + default: Kind = SectionKind::getMergeableConst(); break; + } + } + + const MCSection *S = getObjFileLowering().getSectionForConstant(Kind); + // The number of sections are small, just do a linear search from the // last section to the first. bool Found = false; @@ -328,7 +294,7 @@ void AsmPrinter::EmitConstantPool(MachineConstantPool *MCP) { // Now print stuff into the calculated sections. for (unsigned i = 0, e = CPSections.size(); i != e; ++i) { - SwitchToSection(CPSections[i].S); + OutStreamer.SwitchSection(CPSections[i].S); EmitAlignment(Log2_32(CPSections[i].Alignment)); unsigned Offset = 0; @@ -344,11 +310,12 @@ void AsmPrinter::EmitConstantPool(MachineConstantPool *MCP) { const Type *Ty = CPE.getType(); Offset = NewOffset + TM.getTargetData()->getTypeAllocSize(Ty); - O << TAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << '_' - << CPI << ":\t\t\t\t\t"; + O << MAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << '_' + << CPI << ':'; if (VerboseAsm) { - O << TAI->getCommentString() << ' '; - WriteTypeSymbolic(O, CPE.getType(), 0); + O.PadToColumn(MAI->getCommentColumn()); + O << MAI->getCommentString() << " constant "; + WriteTypeSymbolic(O, CPE.getType(), MF->getFunction()->getParent()); } O << '\n'; if (CPE.isMachineConstantPoolEntry()) @@ -373,20 +340,21 @@ void AsmPrinter::EmitJumpTableInfo(MachineJumpTableInfo *MJTI, // the appropriate section. TargetLowering *LoweringInfo = TM.getTargetLowering(); - const char* JumpTableDataSection = TAI->getJumpTableDataSection(); const Function *F = MF.getFunction(); - unsigned SectionFlags = TAI->SectionFlagsForGlobal(F); bool JTInDiffSection = false; - if ((IsPic && !(LoweringInfo && LoweringInfo->usesGlobalOffsetTable())) || - !JumpTableDataSection || - SectionFlags & SectionFlags::Linkonce) { + if (F->isWeakForLinker() || + (IsPic && !LoweringInfo->usesGlobalOffsetTable())) { // In PIC mode, we need to emit the jump table to the same section as the // function body itself, otherwise the label differences won't make sense. // We should also do if the section name is NULL or function is declared in // discardable section. - SwitchToSection(TAI->SectionForGlobal(F)); + OutStreamer.SwitchSection(getObjFileLowering().SectionForGlobal(F, Mang, + TM)); } else { - SwitchToDataSection(JumpTableDataSection); + // Otherwise, drop it in the readonly section. + const MCSection *ReadOnlySection = + getObjFileLowering().getSectionForConstant(SectionKind::getReadOnly()); + OutStreamer.SwitchSection(ReadOnlySection); JTInDiffSection = true; } @@ -402,21 +370,21 @@ void AsmPrinter::EmitJumpTableInfo(MachineJumpTableInfo *MJTI, // the number of relocations the assembler will generate for the jump table. // Set directives are all printed before the jump table itself. SmallPtrSet<MachineBasicBlock*, 16> EmittedSets; - if (TAI->getSetDirective() && IsPic) + if (MAI->getSetDirective() && IsPic) for (unsigned ii = 0, ee = JTBBs.size(); ii != ee; ++ii) if (EmittedSets.insert(JTBBs[ii])) printPICJumpTableSetLabel(i, JTBBs[ii]); - // On some targets (e.g. darwin) we want to emit two consequtive labels + // On some targets (e.g. Darwin) we want to emit two consequtive labels // before each jump table. The first label is never referenced, but tells // the assembler and linker the extents of the jump table object. The // second label is actually referenced by the code. - if (JTInDiffSection) { - if (const char *JTLabelPrefix = TAI->getJumpTableSpecialLabelPrefix()) - O << JTLabelPrefix << "JTI" << getFunctionNumber() << '_' << i << ":\n"; + if (JTInDiffSection && MAI->getLinkerPrivateGlobalPrefix()[0]) { + O << MAI->getLinkerPrivateGlobalPrefix() + << "JTI" << getFunctionNumber() << '_' << i << ":\n"; } - O << TAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() + O << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() << '_' << i << ":\n"; for (unsigned ii = 0, ee = JTBBs.size(); ii != ee; ++ii) { @@ -429,15 +397,15 @@ void AsmPrinter::EmitJumpTableInfo(MachineJumpTableInfo *MJTI, void AsmPrinter::printPICJumpTableEntry(const MachineJumpTableInfo *MJTI, const MachineBasicBlock *MBB, unsigned uid) const { - bool IsPic = TM.getRelocationModel() == Reloc::PIC_; + bool isPIC = TM.getRelocationModel() == Reloc::PIC_; // Use JumpTableDirective otherwise honor the entry size from the jump table // info. - const char *JTEntryDirective = TAI->getJumpTableDirective(); + const char *JTEntryDirective = MAI->getJumpTableDirective(isPIC); bool HadJTEntryDirective = JTEntryDirective != NULL; if (!HadJTEntryDirective) { JTEntryDirective = MJTI->getEntrySize() == 4 ? - TAI->getData32bitsDirective() : TAI->getData64bitsDirective(); + MAI->getData32bitsDirective() : MAI->getData64bitsDirective(); } O << JTEntryDirective << ' '; @@ -447,20 +415,18 @@ void AsmPrinter::printPICJumpTableEntry(const MachineJumpTableInfo *MJTI, // emit the table entries as differences between two text section labels. // If we're emitting non-PIC code, then emit the entries as direct // references to the target basic blocks. - if (IsPic) { - if (TAI->getSetDirective()) { - O << TAI->getPrivateGlobalPrefix() << getFunctionNumber() - << '_' << uid << "_set_" << MBB->getNumber(); - } else { - printBasicBlockLabel(MBB, false, false, false); - // If the arch uses custom Jump Table directives, don't calc relative to - // JT - if (!HadJTEntryDirective) - O << '-' << TAI->getPrivateGlobalPrefix() << "JTI" - << getFunctionNumber() << '_' << uid; - } + if (!isPIC) { + GetMBBSymbol(MBB->getNumber())->print(O, MAI); + } else if (MAI->getSetDirective()) { + O << MAI->getPrivateGlobalPrefix() << getFunctionNumber() + << '_' << uid << "_set_" << MBB->getNumber(); } else { - printBasicBlockLabel(MBB, false, false, false); + GetMBBSymbol(MBB->getNumber())->print(O, MAI); + // If the arch uses custom Jump Table directives, don't calc relative to + // JT + if (!HadJTEntryDirective) + O << '-' << MAI->getPrivateGlobalPrefix() << "JTI" + << getFunctionNumber() << '_' << uid; } } @@ -470,12 +436,12 @@ void AsmPrinter::printPICJumpTableEntry(const MachineJumpTableInfo *MJTI, /// do nothing and return false. bool AsmPrinter::EmitSpecialLLVMGlobal(const GlobalVariable *GV) { if (GV->getName() == "llvm.used") { - if (TAI->getUsedDirective() != 0) // No need to emit this at all. + if (MAI->getUsedDirective() != 0) // No need to emit this at all. EmitLLVMUsedList(GV->getInitializer()); return true; } - // Ignore debug and non-emitted data. + // Ignore debug and non-emitted data. This handles llvm.compiler.used. if (GV->getSection() == "llvm.metadata" || GV->hasAvailableExternallyLinkage()) return true; @@ -487,14 +453,14 @@ bool AsmPrinter::EmitSpecialLLVMGlobal(const GlobalVariable *GV) { const TargetData *TD = TM.getTargetData(); unsigned Align = Log2_32(TD->getPointerPrefAlignment()); if (GV->getName() == "llvm.global_ctors") { - SwitchToDataSection(TAI->getStaticCtorsSection()); + OutStreamer.SwitchSection(getObjFileLowering().getStaticCtorSection()); EmitAlignment(Align, 0); EmitXXStructorList(GV->getInitializer()); return true; } if (GV->getName() == "llvm.global_dtors") { - SwitchToDataSection(TAI->getStaticDtorsSection()); + OutStreamer.SwitchSection(getObjFileLowering().getStaticDtorSection()); EmitAlignment(Align, 0); EmitXXStructorList(GV->getInitializer()); return true; @@ -503,45 +469,20 @@ bool AsmPrinter::EmitSpecialLLVMGlobal(const GlobalVariable *GV) { return false; } -/// findGlobalValue - if CV is an expression equivalent to a single -/// global value, return that value. -const GlobalValue * AsmPrinter::findGlobalValue(const Constant *CV) { - if (const GlobalValue *GV = dyn_cast<GlobalValue>(CV)) - return GV; - else if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(CV)) { - const TargetData *TD = TM.getTargetData(); - unsigned Opcode = CE->getOpcode(); - switch (Opcode) { - case Instruction::GetElementPtr: { - const Constant *ptrVal = CE->getOperand(0); - SmallVector<Value*, 8> idxVec(CE->op_begin()+1, CE->op_end()); - if (TD->getIndexedOffset(ptrVal->getType(), &idxVec[0], idxVec.size())) - return 0; - return findGlobalValue(ptrVal); - } - case Instruction::BitCast: - return findGlobalValue(CE->getOperand(0)); - default: - return 0; - } - } - return 0; -} - -/// EmitLLVMUsedList - For targets that define a TAI::UsedDirective, mark each +/// EmitLLVMUsedList - For targets that define a MAI::UsedDirective, mark each /// global in the specified llvm.used list for which emitUsedDirectiveFor /// is true, as being used with this directive. - void AsmPrinter::EmitLLVMUsedList(Constant *List) { - const char *Directive = TAI->getUsedDirective(); + const char *Directive = MAI->getUsedDirective(); // Should be an array of 'i8*'. ConstantArray *InitList = dyn_cast<ConstantArray>(List); if (InitList == 0) return; for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) { - const GlobalValue *GV = findGlobalValue(InitList->getOperand(i)); - if (TAI->emitUsedDirectiveFor(GV, Mang)) { + const GlobalValue *GV = + dyn_cast<GlobalValue>(InitList->getOperand(i)->stripPointerCasts()); + if (GV && getObjFileLowering().shouldEmitUsedDirectiveFor(GV, Mang)) { O << Directive; EmitConstantValueOnly(InitList->getOperand(i)); O << '\n'; @@ -567,32 +508,6 @@ void AsmPrinter::EmitXXStructorList(Constant *List) { } } -/// getGlobalLinkName - Returns the asm/link name of of the specified -/// global variable. Should be overridden by each target asm printer to -/// generate the appropriate value. -const std::string &AsmPrinter::getGlobalLinkName(const GlobalVariable *GV, - std::string &LinkName) const { - if (isa<Function>(GV)) { - LinkName += TAI->getFunctionAddrPrefix(); - LinkName += Mang->getValueName(GV); - LinkName += TAI->getFunctionAddrSuffix(); - } else { - LinkName += TAI->getGlobalVarAddrPrefix(); - LinkName += Mang->getValueName(GV); - LinkName += TAI->getGlobalVarAddrSuffix(); - } - - return LinkName; -} - -/// EmitExternalGlobal - Emit the external reference to a global variable. -/// Should be overridden if an indirect reference should be used. -void AsmPrinter::EmitExternalGlobal(const GlobalVariable *GV) { - std::string GLN; - O << getGlobalLinkName(GV, GLN); -} - - //===----------------------------------------------------------------------===// /// LEB 128 number encoding. @@ -646,8 +561,8 @@ void AsmPrinter::EOL() const { void AsmPrinter::EOL(const std::string &Comment) const { if (VerboseAsm && !Comment.empty()) { - O << '\t' - << TAI->getCommentString() + O.PadToColumn(MAI->getCommentColumn()); + O << MAI->getCommentString() << ' ' << Comment; } @@ -656,22 +571,72 @@ void AsmPrinter::EOL(const std::string &Comment) const { void AsmPrinter::EOL(const char* Comment) const { if (VerboseAsm && *Comment) { - O << '\t' - << TAI->getCommentString() + O.PadToColumn(MAI->getCommentColumn()); + O << MAI->getCommentString() << ' ' << Comment; } O << '\n'; } +static const char *DecodeDWARFEncoding(unsigned Encoding) { + switch (Encoding) { + case dwarf::DW_EH_PE_absptr: + return "absptr"; + case dwarf::DW_EH_PE_omit: + return "omit"; + case dwarf::DW_EH_PE_pcrel: + return "pcrel"; + case dwarf::DW_EH_PE_udata4: + return "udata4"; + case dwarf::DW_EH_PE_udata8: + return "udata8"; + case dwarf::DW_EH_PE_sdata4: + return "sdata4"; + case dwarf::DW_EH_PE_sdata8: + return "sdata8"; + case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_udata4: + return "pcrel udata4"; + case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4: + return "pcrel sdata4"; + case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_udata8: + return "pcrel udata8"; + case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata8: + return "pcrel sdata8"; + case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |dwarf::DW_EH_PE_udata4: + return "indirect pcrel udata4"; + case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |dwarf::DW_EH_PE_sdata4: + return "indirect pcrel sdata4"; + case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |dwarf::DW_EH_PE_udata8: + return "indirect pcrel udata8"; + case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |dwarf::DW_EH_PE_sdata8: + return "indirect pcrel sdata8"; + } + + return 0; +} + +void AsmPrinter::EOL(const char *Comment, unsigned Encoding) const { + if (VerboseAsm && *Comment) { + O.PadToColumn(MAI->getCommentColumn()); + O << MAI->getCommentString() + << ' ' + << Comment; + + if (const char *EncStr = DecodeDWARFEncoding(Encoding)) + O << " (" << EncStr << ')'; + } + O << '\n'; +} + /// EmitULEB128Bytes - Emit an assembler byte data directive to compose an /// unsigned leb128 value. void AsmPrinter::EmitULEB128Bytes(unsigned Value) const { - if (TAI->hasLEB128()) { + if (MAI->hasLEB128()) { O << "\t.uleb128\t" << Value; } else { - O << TAI->getData8bitsDirective(); + O << MAI->getData8bitsDirective(); PrintULEB128(Value); } } @@ -679,11 +644,11 @@ void AsmPrinter::EmitULEB128Bytes(unsigned Value) const { /// EmitSLEB128Bytes - print an assembler byte data directive to compose a /// signed leb128 value. void AsmPrinter::EmitSLEB128Bytes(int Value) const { - if (TAI->hasLEB128()) { + if (MAI->hasLEB128()) { O << "\t.sleb128\t" << Value; } else { - O << TAI->getData8bitsDirective(); + O << MAI->getData8bitsDirective(); PrintSLEB128(Value); } } @@ -691,29 +656,29 @@ void AsmPrinter::EmitSLEB128Bytes(int Value) const { /// EmitInt8 - Emit a byte directive and value. /// void AsmPrinter::EmitInt8(int Value) const { - O << TAI->getData8bitsDirective(); + O << MAI->getData8bitsDirective(); PrintHex(Value & 0xFF); } /// EmitInt16 - Emit a short directive and value. /// void AsmPrinter::EmitInt16(int Value) const { - O << TAI->getData16bitsDirective(); + O << MAI->getData16bitsDirective(); PrintHex(Value & 0xFFFF); } /// EmitInt32 - Emit a long directive and value. /// void AsmPrinter::EmitInt32(int Value) const { - O << TAI->getData32bitsDirective(); + O << MAI->getData32bitsDirective(); PrintHex(Value); } /// EmitInt64 - Emit a long long directive and value. /// void AsmPrinter::EmitInt64(uint64_t Value) const { - if (TAI->getData64bitsDirective()) { - O << TAI->getData64bitsDirective(); + if (MAI->getData64bitsDirective()) { + O << MAI->getData64bitsDirective(); PrintHex(Value); } else { if (TM.getTargetData()->isBigEndian()) { @@ -734,7 +699,7 @@ static inline char toOctal(int X) { /// printStringChar - Print a char, escaped if necessary. /// -static void printStringChar(raw_ostream &O, unsigned char C) { +static void printStringChar(formatted_raw_ostream &O, unsigned char C) { if (C == '"') { O << "\\\""; } else if (C == '\\') { @@ -766,11 +731,11 @@ void AsmPrinter::EmitString(const std::string &String) const { } void AsmPrinter::EmitString(const char *String, unsigned Size) const { - const char* AscizDirective = TAI->getAscizDirective(); + const char* AscizDirective = MAI->getAscizDirective(); if (AscizDirective) O << AscizDirective; else - O << TAI->getAsciiDirective(); + O << MAI->getAsciiDirective(); O << '\"'; for (unsigned i = 0; i < Size; ++i) printStringChar(O, String[i]); @@ -813,31 +778,26 @@ void AsmPrinter::EmitAlignment(unsigned NumBits, const GlobalValue *GV, NumBits = std::max(NumBits, ForcedAlignBits); if (NumBits == 0) return; // No need to emit alignment. - if (TAI->getAlignmentIsInBytes()) NumBits = 1 << NumBits; - O << TAI->getAlignDirective() << NumBits; - - unsigned FillValue = TAI->getTextAlignFillValue(); - UseFillExpr &= IsInTextSection && FillValue; - if (UseFillExpr) { - O << ','; - PrintHex(FillValue); - } - O << '\n'; + + unsigned FillValue = 0; + if (getCurrentSection()->getKind().isText()) + FillValue = MAI->getTextAlignFillValue(); + + OutStreamer.EmitValueToAlignment(1 << NumBits, FillValue, 1, 0); } - /// EmitZeros - Emit a block of zeros. /// void AsmPrinter::EmitZeros(uint64_t NumZeros, unsigned AddrSpace) const { if (NumZeros) { - if (TAI->getZeroDirective()) { - O << TAI->getZeroDirective() << NumZeros; - if (TAI->getZeroDirectiveSuffix()) - O << TAI->getZeroDirectiveSuffix(); + if (MAI->getZeroDirective()) { + O << MAI->getZeroDirective() << NumZeros; + if (MAI->getZeroDirectiveSuffix()) + O << MAI->getZeroDirectiveSuffix(); O << '\n'; } else { for (; NumZeros; --NumZeros) - O << TAI->getData8bitsDirective(AddrSpace) << "0\n"; + O << MAI->getData8bitsDirective(AddrSpace) << "0\n"; } } } @@ -851,22 +811,22 @@ void AsmPrinter::EmitConstantValueOnly(const Constant *CV) { O << CI->getZExtValue(); } else if (const GlobalValue *GV = dyn_cast<GlobalValue>(CV)) { // This is a constant address for a global variable or function. Use the - // name of the variable or function as the address value, possibly - // decorating it with GlobalVarAddrPrefix/Suffix or - // FunctionAddrPrefix/Suffix (these all default to "" ) - if (isa<Function>(GV)) { - O << TAI->getFunctionAddrPrefix() - << Mang->getValueName(GV) - << TAI->getFunctionAddrSuffix(); - } else { - O << TAI->getGlobalVarAddrPrefix() - << Mang->getValueName(GV) - << TAI->getGlobalVarAddrSuffix(); - } + // name of the variable or function as the address value. + O << Mang->getMangledName(GV); } else if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(CV)) { const TargetData *TD = TM.getTargetData(); unsigned Opcode = CE->getOpcode(); switch (Opcode) { + case Instruction::Trunc: + case Instruction::ZExt: + case Instruction::SExt: + case Instruction::FPTrunc: + case Instruction::FPExt: + case Instruction::UIToFP: + case Instruction::SIToFP: + case Instruction::FPToUI: + case Instruction::FPToSI: + llvm_unreachable("FIXME: Don't support this constant cast expr"); case Instruction::GetElementPtr: { // generate a symbolic expression for the byte address const Constant *ptrVal = CE->getOperand(0); @@ -891,17 +851,6 @@ void AsmPrinter::EmitConstantValueOnly(const Constant *CV) { } break; } - case Instruction::Trunc: - case Instruction::ZExt: - case Instruction::SExt: - case Instruction::FPTrunc: - case Instruction::FPExt: - case Instruction::UIToFP: - case Instruction::SIToFP: - case Instruction::FPToUI: - case Instruction::FPToSI: - assert(0 && "FIXME: Don't yet support this kind of constant cast expr"); - break; case Instruction::BitCast: return EmitConstantValueOnly(CE->getOperand(0)); @@ -909,7 +858,8 @@ void AsmPrinter::EmitConstantValueOnly(const Constant *CV) { // 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); - Op = ConstantExpr::getIntegerCast(Op, TD->getIntPtrType(), false/*ZExt*/); + Op = ConstantExpr::getIntegerCast(Op, TD->getIntPtrType(CV->getContext()), + false/*ZExt*/); return EmitConstantValueOnly(Op); } @@ -922,16 +872,17 @@ void AsmPrinter::EmitConstantValueOnly(const Constant *CV) { // We can emit the pointer value into this slot if the slot is an // integer slot greater or equal to the size of the pointer. - if (TD->getTypeAllocSize(Ty) >= TD->getTypeAllocSize(Op->getType())) + if (TD->getTypeAllocSize(Ty) == TD->getTypeAllocSize(Op->getType())) return EmitConstantValueOnly(Op); O << "(("; EmitConstantValueOnly(Op); - APInt ptrMask = APInt::getAllOnesValue(TD->getTypeAllocSizeInBits(Ty)); + APInt ptrMask = + APInt::getAllOnesValue(TD->getTypeAllocSizeInBits(Op->getType())); SmallString<40> S; ptrMask.toStringUnsigned(S); - O << ") & " << S.c_str() << ')'; + O << ") & " << S.str() << ')'; break; } case Instruction::Add: @@ -966,17 +917,17 @@ void AsmPrinter::EmitConstantValueOnly(const Constant *CV) { O << ')'; break; default: - assert(0 && "Unsupported operator!"); + llvm_unreachable("Unsupported operator!"); } } else { - assert(0 && "Unknown constant value!"); + llvm_unreachable("Unknown constant value!"); } } /// printAsCString - Print the specified array as a C compatible string, only if /// the predicate isString is true. /// -static void printAsCString(raw_ostream &O, const ConstantArray *CVA, +static void printAsCString(formatted_raw_ostream &O, const ConstantArray *CVA, unsigned LastElt) { assert(CVA->isString() && "Array is not string compatible!"); @@ -993,12 +944,12 @@ static void printAsCString(raw_ostream &O, const ConstantArray *CVA, /// void AsmPrinter::EmitString(const ConstantArray *CVA) const { unsigned NumElts = CVA->getNumOperands(); - if (TAI->getAscizDirective() && NumElts && + if (MAI->getAscizDirective() && NumElts && cast<ConstantInt>(CVA->getOperand(NumElts-1))->getZExtValue() == 0) { - O << TAI->getAscizDirective(); + O << MAI->getAscizDirective(); printAsCString(O, CVA, NumElts-1); } else { - O << TAI->getAsciiDirective(); + O << MAI->getAsciiDirective(); printAsCString(O, CVA, NumElts); } O << '\n'; @@ -1053,48 +1004,65 @@ void AsmPrinter::EmitGlobalConstantFP(const ConstantFP *CFP, unsigned AddrSpace) { // FP Constants are printed as integer constants to avoid losing // precision... + LLVMContext &Context = CFP->getContext(); const TargetData *TD = TM.getTargetData(); - if (CFP->getType() == Type::DoubleTy) { + if (CFP->getType()->isDoubleTy()) { double Val = CFP->getValueAPF().convertToDouble(); // for comment only uint64_t i = CFP->getValueAPF().bitcastToAPInt().getZExtValue(); - if (TAI->getData64bitsDirective(AddrSpace)) { - O << TAI->getData64bitsDirective(AddrSpace) << i; - if (VerboseAsm) - O << '\t' << TAI->getCommentString() << " double value: " << Val; + if (MAI->getData64bitsDirective(AddrSpace)) { + O << MAI->getData64bitsDirective(AddrSpace) << i; + if (VerboseAsm) { + O.PadToColumn(MAI->getCommentColumn()); + O << MAI->getCommentString() << " double " << Val; + } O << '\n'; } else if (TD->isBigEndian()) { - O << TAI->getData32bitsDirective(AddrSpace) << unsigned(i >> 32); - if (VerboseAsm) - O << '\t' << TAI->getCommentString() - << " double most significant word " << Val; + O << MAI->getData32bitsDirective(AddrSpace) << unsigned(i >> 32); + if (VerboseAsm) { + O.PadToColumn(MAI->getCommentColumn()); + O << MAI->getCommentString() + << " most significant word of double " << Val; + } O << '\n'; - O << TAI->getData32bitsDirective(AddrSpace) << unsigned(i); - if (VerboseAsm) - O << '\t' << TAI->getCommentString() - << " double least significant word " << Val; + O << MAI->getData32bitsDirective(AddrSpace) << unsigned(i); + if (VerboseAsm) { + O.PadToColumn(MAI->getCommentColumn()); + O << MAI->getCommentString() + << " least significant word of double " << Val; + } O << '\n'; } else { - O << TAI->getData32bitsDirective(AddrSpace) << unsigned(i); - if (VerboseAsm) - O << '\t' << TAI->getCommentString() - << " double least significant word " << Val; + O << MAI->getData32bitsDirective(AddrSpace) << unsigned(i); + if (VerboseAsm) { + O.PadToColumn(MAI->getCommentColumn()); + O << MAI->getCommentString() + << " least significant word of double " << Val; + } O << '\n'; - O << TAI->getData32bitsDirective(AddrSpace) << unsigned(i >> 32); - if (VerboseAsm) - O << '\t' << TAI->getCommentString() - << " double most significant word " << Val; + O << MAI->getData32bitsDirective(AddrSpace) << unsigned(i >> 32); + if (VerboseAsm) { + O.PadToColumn(MAI->getCommentColumn()); + O << MAI->getCommentString() + << " most significant word of double " << Val; + } O << '\n'; } return; - } else if (CFP->getType() == Type::FloatTy) { + } + + if (CFP->getType()->isFloatTy()) { float Val = CFP->getValueAPF().convertToFloat(); // for comment only - O << TAI->getData32bitsDirective(AddrSpace) + O << MAI->getData32bitsDirective(AddrSpace) << CFP->getValueAPF().bitcastToAPInt().getZExtValue(); - if (VerboseAsm) - O << '\t' << TAI->getCommentString() << " float " << Val; + if (VerboseAsm) { + O.PadToColumn(MAI->getCommentColumn()); + O << MAI->getCommentString() << " float " << Val; + } O << '\n'; return; - } else if (CFP->getType() == Type::X86_FP80Ty) { + } + + if (CFP->getType()->isX86_FP80Ty()) { // all long double variants are printed as hex // api needed to prevent premature destruction APInt api = CFP->getValueAPF().bitcastToAPInt(); @@ -1105,110 +1073,148 @@ void AsmPrinter::EmitGlobalConstantFP(const ConstantFP *CFP, DoubleVal.convert(APFloat::IEEEdouble, APFloat::rmNearestTiesToEven, &ignored); if (TD->isBigEndian()) { - O << TAI->getData16bitsDirective(AddrSpace) << uint16_t(p[1]); - if (VerboseAsm) - O << '\t' << TAI->getCommentString() - << " long double most significant halfword of ~" + O << MAI->getData16bitsDirective(AddrSpace) << uint16_t(p[1]); + if (VerboseAsm) { + O.PadToColumn(MAI->getCommentColumn()); + O << MAI->getCommentString() + << " most significant halfword of x86_fp80 ~" << DoubleVal.convertToDouble(); + } O << '\n'; - O << TAI->getData16bitsDirective(AddrSpace) << uint16_t(p[0] >> 48); - if (VerboseAsm) - O << '\t' << TAI->getCommentString() << " long double next halfword"; + O << MAI->getData16bitsDirective(AddrSpace) << uint16_t(p[0] >> 48); + if (VerboseAsm) { + O.PadToColumn(MAI->getCommentColumn()); + O << MAI->getCommentString() << " next halfword"; + } O << '\n'; - O << TAI->getData16bitsDirective(AddrSpace) << uint16_t(p[0] >> 32); - if (VerboseAsm) - O << '\t' << TAI->getCommentString() << " long double next halfword"; + O << MAI->getData16bitsDirective(AddrSpace) << uint16_t(p[0] >> 32); + if (VerboseAsm) { + O.PadToColumn(MAI->getCommentColumn()); + O << MAI->getCommentString() << " next halfword"; + } O << '\n'; - O << TAI->getData16bitsDirective(AddrSpace) << uint16_t(p[0] >> 16); - if (VerboseAsm) - O << '\t' << TAI->getCommentString() << " long double next halfword"; + O << MAI->getData16bitsDirective(AddrSpace) << uint16_t(p[0] >> 16); + if (VerboseAsm) { + O.PadToColumn(MAI->getCommentColumn()); + O << MAI->getCommentString() << " next halfword"; + } O << '\n'; - O << TAI->getData16bitsDirective(AddrSpace) << uint16_t(p[0]); - if (VerboseAsm) - O << '\t' << TAI->getCommentString() - << " long double least significant halfword"; + O << MAI->getData16bitsDirective(AddrSpace) << uint16_t(p[0]); + if (VerboseAsm) { + O.PadToColumn(MAI->getCommentColumn()); + O << MAI->getCommentString() + << " least significant halfword"; + } O << '\n'; } else { - O << TAI->getData16bitsDirective(AddrSpace) << uint16_t(p[0]); - if (VerboseAsm) - O << '\t' << TAI->getCommentString() - << " long double least significant halfword of ~" + O << MAI->getData16bitsDirective(AddrSpace) << uint16_t(p[0]); + if (VerboseAsm) { + O.PadToColumn(MAI->getCommentColumn()); + O << MAI->getCommentString() + << " least significant halfword of x86_fp80 ~" << DoubleVal.convertToDouble(); + } O << '\n'; - O << TAI->getData16bitsDirective(AddrSpace) << uint16_t(p[0] >> 16); - if (VerboseAsm) - O << '\t' << TAI->getCommentString() - << " long double next halfword"; + O << MAI->getData16bitsDirective(AddrSpace) << uint16_t(p[0] >> 16); + if (VerboseAsm) { + O.PadToColumn(MAI->getCommentColumn()); + O << MAI->getCommentString() + << " next halfword"; + } O << '\n'; - O << TAI->getData16bitsDirective(AddrSpace) << uint16_t(p[0] >> 32); - if (VerboseAsm) - O << '\t' << TAI->getCommentString() - << " long double next halfword"; + O << MAI->getData16bitsDirective(AddrSpace) << uint16_t(p[0] >> 32); + if (VerboseAsm) { + O.PadToColumn(MAI->getCommentColumn()); + O << MAI->getCommentString() + << " next halfword"; + } O << '\n'; - O << TAI->getData16bitsDirective(AddrSpace) << uint16_t(p[0] >> 48); - if (VerboseAsm) - O << '\t' << TAI->getCommentString() - << " long double next halfword"; + O << MAI->getData16bitsDirective(AddrSpace) << uint16_t(p[0] >> 48); + if (VerboseAsm) { + O.PadToColumn(MAI->getCommentColumn()); + O << MAI->getCommentString() + << " next halfword"; + } O << '\n'; - O << TAI->getData16bitsDirective(AddrSpace) << uint16_t(p[1]); - if (VerboseAsm) - O << '\t' << TAI->getCommentString() - << " long double most significant halfword"; + O << MAI->getData16bitsDirective(AddrSpace) << uint16_t(p[1]); + if (VerboseAsm) { + O.PadToColumn(MAI->getCommentColumn()); + O << MAI->getCommentString() + << " most significant halfword"; + } O << '\n'; } - EmitZeros(TD->getTypeAllocSize(Type::X86_FP80Ty) - - TD->getTypeStoreSize(Type::X86_FP80Ty), AddrSpace); + EmitZeros(TD->getTypeAllocSize(Type::getX86_FP80Ty(Context)) - + TD->getTypeStoreSize(Type::getX86_FP80Ty(Context)), AddrSpace); return; - } else if (CFP->getType() == Type::PPC_FP128Ty) { + } + + if (CFP->getType()->isPPC_FP128Ty()) { // 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 (TD->isBigEndian()) { - O << TAI->getData32bitsDirective(AddrSpace) << uint32_t(p[0] >> 32); - if (VerboseAsm) - O << '\t' << TAI->getCommentString() - << " long double most significant word"; + O << MAI->getData32bitsDirective(AddrSpace) << uint32_t(p[0] >> 32); + if (VerboseAsm) { + O.PadToColumn(MAI->getCommentColumn()); + O << MAI->getCommentString() + << " most significant word of ppc_fp128"; + } O << '\n'; - O << TAI->getData32bitsDirective(AddrSpace) << uint32_t(p[0]); - if (VerboseAsm) - O << '\t' << TAI->getCommentString() - << " long double next word"; + O << MAI->getData32bitsDirective(AddrSpace) << uint32_t(p[0]); + if (VerboseAsm) { + O.PadToColumn(MAI->getCommentColumn()); + O << MAI->getCommentString() + << " next word"; + } O << '\n'; - O << TAI->getData32bitsDirective(AddrSpace) << uint32_t(p[1] >> 32); - if (VerboseAsm) - O << '\t' << TAI->getCommentString() - << " long double next word"; + O << MAI->getData32bitsDirective(AddrSpace) << uint32_t(p[1] >> 32); + if (VerboseAsm) { + O.PadToColumn(MAI->getCommentColumn()); + O << MAI->getCommentString() + << " next word"; + } O << '\n'; - O << TAI->getData32bitsDirective(AddrSpace) << uint32_t(p[1]); - if (VerboseAsm) - O << '\t' << TAI->getCommentString() - << " long double least significant word"; + O << MAI->getData32bitsDirective(AddrSpace) << uint32_t(p[1]); + if (VerboseAsm) { + O.PadToColumn(MAI->getCommentColumn()); + O << MAI->getCommentString() + << " least significant word"; + } O << '\n'; } else { - O << TAI->getData32bitsDirective(AddrSpace) << uint32_t(p[1]); - if (VerboseAsm) - O << '\t' << TAI->getCommentString() - << " long double least significant word"; + O << MAI->getData32bitsDirective(AddrSpace) << uint32_t(p[1]); + if (VerboseAsm) { + O.PadToColumn(MAI->getCommentColumn()); + O << MAI->getCommentString() + << " least significant word of ppc_fp128"; + } O << '\n'; - O << TAI->getData32bitsDirective(AddrSpace) << uint32_t(p[1] >> 32); - if (VerboseAsm) - O << '\t' << TAI->getCommentString() - << " long double next word"; + O << MAI->getData32bitsDirective(AddrSpace) << uint32_t(p[1] >> 32); + if (VerboseAsm) { + O.PadToColumn(MAI->getCommentColumn()); + O << MAI->getCommentString() + << " next word"; + } O << '\n'; - O << TAI->getData32bitsDirective(AddrSpace) << uint32_t(p[0]); - if (VerboseAsm) - O << '\t' << TAI->getCommentString() - << " long double next word"; + O << MAI->getData32bitsDirective(AddrSpace) << uint32_t(p[0]); + if (VerboseAsm) { + O.PadToColumn(MAI->getCommentColumn()); + O << MAI->getCommentString() + << " next word"; + } O << '\n'; - O << TAI->getData32bitsDirective(AddrSpace) << uint32_t(p[0] >> 32); - if (VerboseAsm) - O << '\t' << TAI->getCommentString() - << " long double most significant word"; + O << MAI->getData32bitsDirective(AddrSpace) << uint32_t(p[0] >> 32); + if (VerboseAsm) { + O.PadToColumn(MAI->getCommentColumn()); + O << MAI->getCommentString() + << " most significant word"; + } O << '\n'; } return; - } else assert(0 && "Floating point constant type not handled"); + } else llvm_unreachable("Floating point constant type not handled"); } void AsmPrinter::EmitGlobalConstantLargeInt(const ConstantInt *CI, @@ -1229,29 +1235,37 @@ void AsmPrinter::EmitGlobalConstantLargeInt(const ConstantInt *CI, else Val = RawData[i]; - if (TAI->getData64bitsDirective(AddrSpace)) - O << TAI->getData64bitsDirective(AddrSpace) << Val << '\n'; + if (MAI->getData64bitsDirective(AddrSpace)) + O << MAI->getData64bitsDirective(AddrSpace) << Val << '\n'; else if (TD->isBigEndian()) { - O << TAI->getData32bitsDirective(AddrSpace) << unsigned(Val >> 32); - if (VerboseAsm) - O << '\t' << TAI->getCommentString() - << " Double-word most significant word " << Val; + O << MAI->getData32bitsDirective(AddrSpace) << unsigned(Val >> 32); + if (VerboseAsm) { + O.PadToColumn(MAI->getCommentColumn()); + O << MAI->getCommentString() + << " most significant half of i64 " << Val; + } O << '\n'; - O << TAI->getData32bitsDirective(AddrSpace) << unsigned(Val); - if (VerboseAsm) - O << '\t' << TAI->getCommentString() - << " Double-word least significant word " << Val; + O << MAI->getData32bitsDirective(AddrSpace) << unsigned(Val); + if (VerboseAsm) { + O.PadToColumn(MAI->getCommentColumn()); + O << MAI->getCommentString() + << " least significant half of i64 " << Val; + } O << '\n'; } else { - O << TAI->getData32bitsDirective(AddrSpace) << unsigned(Val); - if (VerboseAsm) - O << '\t' << TAI->getCommentString() - << " Double-word least significant word " << Val; + O << MAI->getData32bitsDirective(AddrSpace) << unsigned(Val); + if (VerboseAsm) { + O.PadToColumn(MAI->getCommentColumn()); + O << MAI->getCommentString() + << " least significant half of i64 " << Val; + } O << '\n'; - O << TAI->getData32bitsDirective(AddrSpace) << unsigned(Val >> 32); - if (VerboseAsm) - O << '\t' << TAI->getCommentString() - << " Double-word most significant word " << Val; + O << MAI->getData32bitsDirective(AddrSpace) << unsigned(Val >> 32); + if (VerboseAsm) { + O.PadToColumn(MAI->getCommentColumn()); + O << MAI->getCommentString() + << " most significant half of i64 " << Val; + } O << '\n'; } } @@ -1292,7 +1306,8 @@ void AsmPrinter::EmitGlobalConstant(const Constant *CV, unsigned AddrSpace) { if (const ConstantInt *CI = dyn_cast<ConstantInt>(CV)) { SmallString<40> S; CI->getValue().toStringUnsigned(S, 16); - O << "\t\t\t" << TAI->getCommentString() << " 0x" << S.c_str(); + O.PadToColumn(MAI->getCommentColumn()); + O << MAI->getCommentString() << " 0x" << S.str(); } } O << '\n'; @@ -1300,7 +1315,7 @@ void AsmPrinter::EmitGlobalConstant(const Constant *CV, unsigned AddrSpace) { void AsmPrinter::EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) { // Target doesn't support this yet! - abort(); + llvm_unreachable("Target does not support EmitMachineConstantPoolValue"); } /// PrintSpecial - Print information related to the specified machine instr @@ -1311,10 +1326,10 @@ void AsmPrinter::EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) { /// for their own strange codes. void AsmPrinter::PrintSpecial(const MachineInstr *MI, const char *Code) const { if (!strcmp(Code, "private")) { - O << TAI->getPrivateGlobalPrefix(); + O << MAI->getPrivateGlobalPrefix(); } else if (!strcmp(Code, "comment")) { if (VerboseAsm) - O << TAI->getCommentString(); + O << MAI->getCommentString(); } else if (!strcmp(Code, "uid")) { // Comparing the address of MI isn't sufficient, because machineinstrs may // be allocated to the same address across functions. @@ -1328,23 +1343,38 @@ void AsmPrinter::PrintSpecial(const MachineInstr *MI, const char *Code) const { } O << Counter; } else { - cerr << "Unknown special formatter '" << Code + std::string msg; + raw_string_ostream Msg(msg); + Msg << "Unknown special formatter '" << Code << "' for machine instr: " << *MI; - exit(1); + llvm_report_error(Msg.str()); } } /// processDebugLoc - Processes the debug information of each machine /// instruction's DebugLoc. -void AsmPrinter::processDebugLoc(DebugLoc DL) { - if (TAI->doesSupportDebugInformation() && DW->ShouldEmitDwarfDebug()) { +void AsmPrinter::processDebugLoc(const MachineInstr *MI, + bool BeforePrintingInsn) { + if (!MAI || !DW) + return; + DebugLoc DL = MI->getDebugLoc(); + if (MAI->doesSupportDebugInformation() && DW->ShouldEmitDwarfDebug()) { if (!DL.isUnknown()) { DebugLocTuple CurDLT = MF->getDebugLocTuple(DL); - - if (CurDLT.CompileUnit != 0 && PrevDLT != CurDLT) - printLabel(DW->RecordSourceLine(CurDLT.Line, CurDLT.Col, - DICompileUnit(CurDLT.CompileUnit))); - + if (BeforePrintingInsn) { + if (CurDLT.Scope != 0 && PrevDLT != CurDLT) { + unsigned L = DW->RecordSourceLine(CurDLT.Line, CurDLT.Col, + CurDLT.Scope); + printLabel(L); +#ifdef ATTACH_DEBUG_INFO_TO_AN_INSN + DW->SetDbgScopeBeginLabels(MI, L); +#endif + } else { +#ifdef ATTACH_DEBUG_INFO_TO_AN_INSN + DW->SetDbgScopeEndLabels(MI, 0); +#endif + } + } PrevDLT = CurDLT; } } @@ -1369,14 +1399,15 @@ void AsmPrinter::printInlineAsm(const MachineInstr *MI) const { // 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) { - O << TAI->getInlineAsmStart() << "\n\t" << TAI->getInlineAsmEnd() << '\n'; + O << MAI->getCommentString() << MAI->getInlineAsmStart() << "\n\t"; + O << MAI->getCommentString() << MAI->getInlineAsmEnd() << '\n'; return; } - O << TAI->getInlineAsmStart() << "\n\t"; + O << MAI->getCommentString() << MAI->getInlineAsmStart() << "\n\t"; // The variant of the current asmprinter. - int AsmPrinterVariant = TAI->getAssemblerDialect(); + int AsmPrinterVariant = MAI->getAssemblerDialect(); int CurVariant = -1; // The number of the {.|.|.} region we are in. const char *LastEmitted = AsmStr; // One past the last character emitted. @@ -1413,9 +1444,8 @@ void AsmPrinter::printInlineAsm(const MachineInstr *MI) const { case '(': // $( -> same as GCC's { character. ++LastEmitted; // Consume '(' character. if (CurVariant != -1) { - cerr << "Nested variants found in inline asm string: '" - << AsmStr << "'\n"; - exit(1); + llvm_report_error("Nested variants found in inline asm string: '" + + std::string(AsmStr) + "'"); } CurVariant = 0; // We're in the first variant now. break; @@ -1450,9 +1480,8 @@ void AsmPrinter::printInlineAsm(const MachineInstr *MI) const { const char *StrStart = LastEmitted; const char *StrEnd = strchr(StrStart, '}'); if (StrEnd == 0) { - cerr << "Unterminated ${:foo} operand in inline asm string: '" - << AsmStr << "'\n"; - exit(1); + llvm_report_error("Unterminated ${:foo} operand in inline asm string: '" + + std::string(AsmStr) + "'"); } std::string Val(StrStart, StrEnd); @@ -1466,9 +1495,8 @@ void AsmPrinter::printInlineAsm(const MachineInstr *MI) const { errno = 0; long Val = strtol(IDStart, &IDEnd, 10); // We only accept numbers for IDs. if (!isdigit(*IDStart) || (Val == 0 && errno == EINVAL)) { - cerr << "Bad $ operand number in inline asm string: '" - << AsmStr << "'\n"; - exit(1); + llvm_report_error("Bad $ operand number in inline asm string: '" + + std::string(AsmStr) + "'"); } LastEmitted = IDEnd; @@ -1480,9 +1508,8 @@ void AsmPrinter::printInlineAsm(const MachineInstr *MI) const { if (*LastEmitted == ':') { ++LastEmitted; // Consume ':' character. if (*LastEmitted == 0) { - cerr << "Bad ${:} expression in inline asm string: '" - << AsmStr << "'\n"; - exit(1); + llvm_report_error("Bad ${:} expression in inline asm string: '" + + std::string(AsmStr) + "'"); } Modifier[0] = *LastEmitted; @@ -1490,17 +1517,15 @@ void AsmPrinter::printInlineAsm(const MachineInstr *MI) const { } if (*LastEmitted != '}') { - cerr << "Bad ${} expression in inline asm string: '" - << AsmStr << "'\n"; - exit(1); + llvm_report_error("Bad ${} expression in inline asm string: '" + + std::string(AsmStr) + "'"); } ++LastEmitted; // Consume '}' character. } if ((unsigned)Val >= NumOperands-1) { - cerr << "Invalid $ operand number in inline asm string: '" - << AsmStr << "'\n"; - exit(1); + llvm_report_error("Invalid $ operand number in inline asm string: '" + + std::string(AsmStr) + "'"); } // Okay, we finally have a value number. Ask the target to print this @@ -1524,8 +1549,8 @@ void AsmPrinter::printInlineAsm(const MachineInstr *MI) const { ++OpNo; // Skip over the ID number. if (Modifier[0]=='l') // labels are target independent - printBasicBlockLabel(MI->getOperand(OpNo).getMBB(), - false, false, false); + GetMBBSymbol(MI->getOperand(OpNo).getMBB() + ->getNumber())->print(O, MAI); else { AsmPrinter *AP = const_cast<AsmPrinter*>(this); if ((OpFlags & 7) == 4) { @@ -1538,25 +1563,28 @@ void AsmPrinter::printInlineAsm(const MachineInstr *MI) const { } } if (Error) { - cerr << "Invalid operand found in inline asm: '" + std::string msg; + raw_string_ostream Msg(msg); + Msg << "Invalid operand found in inline asm: '" << AsmStr << "'\n"; - MI->dump(); - exit(1); + MI->print(Msg); + llvm_report_error(Msg.str()); } } break; } } } - O << "\n\t" << TAI->getInlineAsmEnd() << '\n'; + O << "\n\t" << MAI->getCommentString() << MAI->getInlineAsmEnd(); } /// printImplicitDef - This method prints the specified machine instruction /// that is an implicit def. void AsmPrinter::printImplicitDef(const MachineInstr *MI) const { - if (VerboseAsm) - O << '\t' << TAI->getCommentString() << " implicit-def: " - << TRI->getAsmName(MI->getOperand(0).getReg()) << '\n'; + if (!VerboseAsm) return; + O.PadToColumn(MAI->getCommentColumn()); + O << MAI->getCommentString() << " implicit-def: " + << TRI->getName(MI->getOperand(0).getReg()); } /// printLabel - This method prints a local label used by debug and @@ -1566,17 +1594,7 @@ void AsmPrinter::printLabel(const MachineInstr *MI) const { } void AsmPrinter::printLabel(unsigned Id) const { - O << TAI->getPrivateGlobalPrefix() << "label" << Id << ":\n"; -} - -/// printDeclare - This method prints a local variable declaration used by -/// debug tables. -/// FIXME: It doesn't really print anything rather it inserts a DebugVariable -/// entry into dwarf table. -void AsmPrinter::printDeclare(const MachineInstr *MI) const { - unsigned FI = MI->getOperand(0).getIndex(); - GlobalValue *GV = MI->getOperand(1).getGlobal(); - DW->RecordVariable(cast<GlobalVariable>(GV), FI, MI); + O << MAI->getPrivateGlobalPrefix() << "label" << Id << ':'; } /// PrintAsmOperand - Print the specified operand of MI, an INLINEASM @@ -1595,51 +1613,69 @@ bool AsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, return true; } -/// printBasicBlockLabel - This method prints the label for the specified -/// MachineBasicBlock -void AsmPrinter::printBasicBlockLabel(const MachineBasicBlock *MBB, - bool printAlign, - bool printColon, - bool printComment) const { - if (printAlign) { - unsigned Align = MBB->getAlignment(); - if (Align) - EmitAlignment(Log2_32(Align)); - } +MCSymbol *AsmPrinter::GetMBBSymbol(unsigned MBBID) const { + SmallString<60> Name; + raw_svector_ostream(Name) << MAI->getPrivateGlobalPrefix() << "BB" + << getFunctionNumber() << '_' << MBBID; + + return OutContext.GetOrCreateSymbol(Name.str()); +} + - O << TAI->getPrivateGlobalPrefix() << "BB" << getFunctionNumber() << '_' - << MBB->getNumber(); - if (printColon) +/// EmitBasicBlockStart - This method prints the label for the specified +/// MachineBasicBlock, an alignment (if present) and a comment describing +/// it if appropriate. +void AsmPrinter::EmitBasicBlockStart(const MachineBasicBlock *MBB) const { + if (unsigned Align = MBB->getAlignment()) + EmitAlignment(Log2_32(Align)); + + if (MBB->pred_empty() || MBB->isOnlyReachableByFallthrough()) { + if (VerboseAsm) + O << MAI->getCommentString() << " BB#" << MBB->getNumber() << ':'; + } else { + GetMBBSymbol(MBB->getNumber())->print(O, MAI); O << ':'; - if (printComment && MBB->getBasicBlock()) - O << '\t' << TAI->getCommentString() << ' ' - << MBB->getBasicBlock()->getNameStart(); + if (!VerboseAsm) + O << '\n'; + } + + if (VerboseAsm) { + if (const BasicBlock *BB = MBB->getBasicBlock()) + if (BB->hasName()) { + O.PadToColumn(MAI->getCommentColumn()); + O << MAI->getCommentString() << ' '; + WriteAsOperand(O, BB, /*PrintType=*/false); + } + + EmitComments(*MBB); + O << '\n'; + } } /// printPICJumpTableSetLabel - This method prints a set label for the /// specified MachineBasicBlock for a jumptable entry. void AsmPrinter::printPICJumpTableSetLabel(unsigned uid, const MachineBasicBlock *MBB) const { - if (!TAI->getSetDirective()) + if (!MAI->getSetDirective()) return; - O << TAI->getSetDirective() << ' ' << TAI->getPrivateGlobalPrefix() + O << MAI->getSetDirective() << ' ' << MAI->getPrivateGlobalPrefix() << getFunctionNumber() << '_' << uid << "_set_" << MBB->getNumber() << ','; - printBasicBlockLabel(MBB, false, false, false); - O << '-' << TAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() + GetMBBSymbol(MBB->getNumber())->print(O, MAI); + O << '-' << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() << '_' << uid << '\n'; } void AsmPrinter::printPICJumpTableSetLabel(unsigned uid, unsigned uid2, const MachineBasicBlock *MBB) const { - if (!TAI->getSetDirective()) + if (!MAI->getSetDirective()) return; - O << TAI->getSetDirective() << ' ' << TAI->getPrivateGlobalPrefix() + O << MAI->getSetDirective() << ' ' << MAI->getPrivateGlobalPrefix() << getFunctionNumber() << '_' << uid << '_' << uid2 << "_set_" << MBB->getNumber() << ','; - printBasicBlockLabel(MBB, false, false, false); - O << '-' << TAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() + GetMBBSymbol(MBB->getNumber())->print(O, MAI); + O << '-' << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() << '_' << uid << '_' << uid2 << '\n'; } @@ -1648,73 +1684,51 @@ void AsmPrinter::printPICJumpTableSetLabel(unsigned uid, unsigned uid2, void AsmPrinter::printDataDirective(const Type *type, unsigned AddrSpace) { const TargetData *TD = TM.getTargetData(); switch (type->getTypeID()) { + case Type::FloatTyID: case Type::DoubleTyID: + case Type::X86_FP80TyID: case Type::FP128TyID: case Type::PPC_FP128TyID: + assert(0 && "Should have already output floating point constant."); + default: + assert(0 && "Can't handle printing this type of thing"); case Type::IntegerTyID: { unsigned BitWidth = cast<IntegerType>(type)->getBitWidth(); if (BitWidth <= 8) - O << TAI->getData8bitsDirective(AddrSpace); + O << MAI->getData8bitsDirective(AddrSpace); else if (BitWidth <= 16) - O << TAI->getData16bitsDirective(AddrSpace); + O << MAI->getData16bitsDirective(AddrSpace); else if (BitWidth <= 32) - O << TAI->getData32bitsDirective(AddrSpace); + O << MAI->getData32bitsDirective(AddrSpace); else if (BitWidth <= 64) { - assert(TAI->getData64bitsDirective(AddrSpace) && + assert(MAI->getData64bitsDirective(AddrSpace) && "Target cannot handle 64-bit constant exprs!"); - O << TAI->getData64bitsDirective(AddrSpace); + O << MAI->getData64bitsDirective(AddrSpace); } else { - assert(0 && "Target cannot handle given data directive width!"); + llvm_unreachable("Target cannot handle given data directive width!"); } break; } case Type::PointerTyID: if (TD->getPointerSize() == 8) { - assert(TAI->getData64bitsDirective(AddrSpace) && + assert(MAI->getData64bitsDirective(AddrSpace) && "Target cannot handle 64-bit pointer exprs!"); - O << TAI->getData64bitsDirective(AddrSpace); + O << MAI->getData64bitsDirective(AddrSpace); } else if (TD->getPointerSize() == 2) { - O << TAI->getData16bitsDirective(AddrSpace); + O << MAI->getData16bitsDirective(AddrSpace); } else if (TD->getPointerSize() == 1) { - O << TAI->getData8bitsDirective(AddrSpace); + O << MAI->getData8bitsDirective(AddrSpace); } else { - O << TAI->getData32bitsDirective(AddrSpace); + O << MAI->getData32bitsDirective(AddrSpace); } break; - case Type::FloatTyID: case Type::DoubleTyID: - case Type::X86_FP80TyID: case Type::FP128TyID: case Type::PPC_FP128TyID: - assert (0 && "Should have already output floating point constant."); - default: - assert (0 && "Can't handle printing this type of thing"); - break; } } -void AsmPrinter::printSuffixedName(const char *Name, const char *Suffix, - const char *Prefix) { - if (Name[0]=='\"') - O << '\"'; - O << TAI->getPrivateGlobalPrefix(); - if (Prefix) O << Prefix; - if (Name[0]=='\"') - O << '\"'; - if (Name[0]=='\"') - O << Name[1]; - else - O << Name; - O << Suffix; - if (Name[0]=='\"') - O << '\"'; -} - -void AsmPrinter::printSuffixedName(const std::string &Name, const char* Suffix) { - printSuffixedName(Name.c_str(), Suffix); -} - void AsmPrinter::printVisibility(const std::string& Name, unsigned Visibility) const { if (Visibility == GlobalValue::HiddenVisibility) { - if (const char *Directive = TAI->getHiddenDirective()) + if (const char *Directive = MAI->getHiddenDirective()) O << Directive << Name << '\n'; } else if (Visibility == GlobalValue::ProtectedVisibility) { - if (const char *Directive = TAI->getProtectedDirective()) + if (const char *Directive = MAI->getProtectedDirective()) O << Directive << Name << '\n'; } } @@ -1746,6 +1760,104 @@ GCMetadataPrinter *AsmPrinter::GetOrCreateGCPrinter(GCStrategy *S) { return GMP; } - cerr << "no GCMetadataPrinter registered for GC: " << Name << "\n"; - abort(); + errs() << "no GCMetadataPrinter registered for GC: " << Name << "\n"; + llvm_unreachable(0); +} + +/// EmitComments - Pretty-print comments for instructions +void AsmPrinter::EmitComments(const MachineInstr &MI) const { + assert(VerboseAsm && !MI.getDebugLoc().isUnknown()); + + DebugLocTuple DLT = MF->getDebugLocTuple(MI.getDebugLoc()); + + // Print source line info. + O.PadToColumn(MAI->getCommentColumn()); + O << MAI->getCommentString() << " SrcLine "; + if (DLT.Scope) { + DICompileUnit CU(DLT.Scope); + if (!CU.isNull()) + O << CU.getFilename() << " "; + } + O << DLT.Line; + if (DLT.Col != 0) + O << ":" << DLT.Col; +} + +/// PrintChildLoopComment - Print comments about child loops within +/// the loop for this basic block, with nesting. +/// +static void PrintChildLoopComment(formatted_raw_ostream &O, + const MachineLoop *loop, + const MCAsmInfo *MAI, + int FunctionNumber) { + // Add child loop information + for(MachineLoop::iterator cl = loop->begin(), + clend = loop->end(); + cl != clend; + ++cl) { + MachineBasicBlock *Header = (*cl)->getHeader(); + assert(Header && "No header for loop"); + + O << '\n'; + O.PadToColumn(MAI->getCommentColumn()); + + O << MAI->getCommentString(); + O.indent(((*cl)->getLoopDepth()-1)*2) + << " Child Loop BB" << FunctionNumber << "_" + << Header->getNumber() << " Depth " << (*cl)->getLoopDepth(); + + PrintChildLoopComment(O, *cl, MAI, FunctionNumber); + } +} + +/// EmitComments - Pretty-print comments for basic blocks +void AsmPrinter::EmitComments(const MachineBasicBlock &MBB) const +{ + if (VerboseAsm) { + // Add loop depth information + const MachineLoop *loop = LI->getLoopFor(&MBB); + + if (loop) { + // Print a newline after bb# annotation. + O << "\n"; + O.PadToColumn(MAI->getCommentColumn()); + O << MAI->getCommentString() << " Loop Depth " << loop->getLoopDepth() + << '\n'; + + O.PadToColumn(MAI->getCommentColumn()); + + MachineBasicBlock *Header = loop->getHeader(); + assert(Header && "No header for loop"); + + if (Header == &MBB) { + O << MAI->getCommentString() << " Loop Header"; + PrintChildLoopComment(O, loop, MAI, getFunctionNumber()); + } + else { + O << MAI->getCommentString() << " Loop Header is BB" + << getFunctionNumber() << "_" << loop->getHeader()->getNumber(); + } + + if (loop->empty()) { + O << '\n'; + O.PadToColumn(MAI->getCommentColumn()); + O << MAI->getCommentString() << " Inner Loop"; + } + + // Add parent loop information + for (const MachineLoop *CurLoop = loop->getParentLoop(); + CurLoop; + CurLoop = CurLoop->getParentLoop()) { + MachineBasicBlock *Header = CurLoop->getHeader(); + assert(Header && "No header for loop"); + + O << '\n'; + O.PadToColumn(MAI->getCommentColumn()); + O << MAI->getCommentString(); + O.indent((CurLoop->getLoopDepth()-1)*2) + << " Inside Loop BB" << getFunctionNumber() << "_" + << Header->getNumber() << " Depth " << CurLoop->getLoopDepth(); + } + } + } } diff --git a/lib/CodeGen/AsmPrinter/DIE.cpp b/lib/CodeGen/AsmPrinter/DIE.cpp index 01c431c..ecf0007 100644 --- a/lib/CodeGen/AsmPrinter/DIE.cpp +++ b/lib/CodeGen/AsmPrinter/DIE.cpp @@ -14,9 +14,10 @@ #include "DIE.h" #include "DwarfPrinter.h" #include "llvm/CodeGen/AsmPrinter.h" -#include "llvm/Target/TargetAsmInfo.h" +#include "llvm/MC/MCAsmInfo.h" #include "llvm/Target/TargetData.h" -#include <ostream> +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/Format.h" using namespace llvm; //===----------------------------------------------------------------------===// @@ -75,24 +76,24 @@ void DIEAbbrev::Emit(const AsmPrinter *Asm) const { } #ifndef NDEBUG -void DIEAbbrev::print(std::ostream &O) { +void DIEAbbrev::print(raw_ostream &O) { O << "Abbreviation @" - << std::hex << (intptr_t)this << std::dec + << format("0x%lx", (long)(intptr_t)this) << " " << dwarf::TagString(Tag) << " " << dwarf::ChildrenString(ChildrenFlag) - << "\n"; + << '\n'; for (unsigned i = 0, N = Data.size(); i < N; ++i) { O << " " << dwarf::AttributeString(Data[i].getAttribute()) << " " << dwarf::FormEncodingString(Data[i].getForm()) - << "\n"; + << '\n'; } } -void DIEAbbrev::dump() { print(cerr); } +void DIEAbbrev::dump() { print(errs()); } #endif //===----------------------------------------------------------------------===// @@ -125,7 +126,7 @@ void DIE::Profile(FoldingSetNodeID &ID) { } #ifndef NDEBUG -void DIE::print(std::ostream &O, unsigned IncIndent) { +void DIE::print(raw_ostream &O, unsigned IncIndent) { IndentCount += IncIndent; const std::string Indent(IndentCount, ' '); bool isBlock = Abbrev.getTag() == 0; @@ -133,7 +134,7 @@ void DIE::print(std::ostream &O, unsigned IncIndent) { if (!isBlock) { O << Indent << "Die: " - << "0x" << std::hex << (intptr_t)this << std::dec + << format("0x%lx", (long)(intptr_t)this) << ", Offset: " << Offset << ", Size: " << Size << "\n"; @@ -175,14 +176,14 @@ void DIE::print(std::ostream &O, unsigned IncIndent) { } void DIE::dump() { - print(cerr); + print(errs()); } #endif #ifndef NDEBUG void DIEValue::dump() { - print(cerr); + print(errs()); } #endif @@ -206,7 +207,7 @@ void DIEInteger::EmitValue(Dwarf *D, unsigned Form) const { case dwarf::DW_FORM_data8: Asm->EmitInt64(Integer); break; case dwarf::DW_FORM_udata: Asm->EmitULEB128Bytes(Integer); break; case dwarf::DW_FORM_sdata: Asm->EmitSLEB128Bytes(Integer); break; - default: assert(0 && "DIE Value form not supported yet"); break; + default: llvm_unreachable("DIE Value form not supported yet"); } } @@ -223,9 +224,9 @@ unsigned DIEInteger::SizeOf(const TargetData *TD, 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_udata: return TargetAsmInfo::getULEB128Size(Integer); - case dwarf::DW_FORM_sdata: return TargetAsmInfo::getSLEB128Size(Integer); - default: assert(0 && "DIE Value form not supported yet"); break; + case dwarf::DW_FORM_udata: return MCAsmInfo::getULEB128Size(Integer); + case dwarf::DW_FORM_sdata: return MCAsmInfo::getSLEB128Size(Integer); + default: llvm_unreachable("DIE Value form not supported yet"); break; } return 0; } @@ -241,9 +242,9 @@ void DIEInteger::Profile(FoldingSetNodeID &ID) { } #ifndef NDEBUG -void DIEInteger::print(std::ostream &O) { +void DIEInteger::print(raw_ostream &O) { O << "Int: " << (int64_t)Integer - << " 0x" << std::hex << Integer << std::dec; + << format(" 0x%llx", (unsigned long long)Integer); } #endif @@ -268,7 +269,7 @@ void DIEString::Profile(FoldingSetNodeID &ID) { } #ifndef NDEBUG -void DIEString::print(std::ostream &O) { +void DIEString::print(raw_ostream &O) { O << "Str: \"" << Str << "\""; } #endif @@ -302,7 +303,7 @@ void DIEDwarfLabel::Profile(FoldingSetNodeID &ID) { } #ifndef NDEBUG -void DIEDwarfLabel::print(std::ostream &O) { +void DIEDwarfLabel::print(raw_ostream &O) { O << "Lbl: "; Label.print(O); } @@ -337,7 +338,7 @@ void DIEObjectLabel::Profile(FoldingSetNodeID &ID) { } #ifndef NDEBUG -void DIEObjectLabel::print(std::ostream &O) { +void DIEObjectLabel::print(raw_ostream &O) { O << "Obj: " << Label; } #endif @@ -377,7 +378,7 @@ void DIESectionOffset::Profile(FoldingSetNodeID &ID) { } #ifndef NDEBUG -void DIESectionOffset::print(std::ostream &O) { +void DIESectionOffset::print(raw_ostream &O) { O << "Off: "; Label.print(O); O << "-"; @@ -417,7 +418,7 @@ void DIEDelta::Profile(FoldingSetNodeID &ID) { } #ifndef NDEBUG -void DIEDelta::print(std::ostream &O) { +void DIEDelta::print(raw_ostream &O) { O << "Del: "; LabelHi.print(O); O << "-"; @@ -451,8 +452,8 @@ void DIEEntry::Profile(FoldingSetNodeID &ID) { } #ifndef NDEBUG -void DIEEntry::print(std::ostream &O) { - O << "Die: 0x" << std::hex << (intptr_t)Entry << std::dec; +void DIEEntry::print(raw_ostream &O) { + O << format("Die: 0x%lx", (long)(intptr_t)Entry); } #endif @@ -481,7 +482,7 @@ void DIEBlock::EmitValue(Dwarf *D, unsigned Form) const { case dwarf::DW_FORM_block2: Asm->EmitInt16(Size); break; case dwarf::DW_FORM_block4: Asm->EmitInt32(Size); break; case dwarf::DW_FORM_block: Asm->EmitULEB128Bytes(Size); break; - default: assert(0 && "Improper form for block"); break; + default: llvm_unreachable("Improper form for block"); break; } const SmallVector<DIEAbbrevData, 8> &AbbrevData = Abbrev.getData(); @@ -498,8 +499,8 @@ unsigned DIEBlock::SizeOf(const TargetData *TD, unsigned Form) const { case dwarf::DW_FORM_block1: return Size + sizeof(int8_t); 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 + TargetAsmInfo::getULEB128Size(Size); - default: assert(0 && "Improper form for block"); break; + case dwarf::DW_FORM_block: return Size + MCAsmInfo::getULEB128Size(Size); + default: llvm_unreachable("Improper form for block"); break; } return 0; } @@ -510,7 +511,7 @@ void DIEBlock::Profile(FoldingSetNodeID &ID) { } #ifndef NDEBUG -void DIEBlock::print(std::ostream &O) { +void DIEBlock::print(raw_ostream &O) { O << "Blk: "; DIE::print(O, 5); } diff --git a/lib/CodeGen/AsmPrinter/DIE.h b/lib/CodeGen/AsmPrinter/DIE.h index 5b60327..62b51ec 100644 --- a/lib/CodeGen/AsmPrinter/DIE.h +++ b/lib/CodeGen/AsmPrinter/DIE.h @@ -19,8 +19,7 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/Dwarf.h" -#include "llvm/Support/raw_ostream.h" -#include <iosfwd> +#include <vector> namespace llvm { class AsmPrinter; @@ -103,10 +102,7 @@ namespace llvm { void Emit(const AsmPrinter *Asm) const; #ifndef NDEBUG - void print(std::ostream *O) { - if (O) print(*O); - } - void print(std::ostream &O); + void print(raw_ostream &O); void dump(); #endif }; @@ -198,10 +194,7 @@ namespace llvm { void Profile(FoldingSetNodeID &ID) ; #ifndef NDEBUG - void print(std::ostream *O, unsigned IncIndent = 0) { - if (O) print(*O, IncIndent); - } - void print(std::ostream &O, unsigned IncIndent = 0); + void print(raw_ostream &O, unsigned IncIndent = 0); void dump(); #endif }; @@ -248,10 +241,7 @@ namespace llvm { static bool classof(const DIEValue *) { return true; } #ifndef NDEBUG - void print(std::ostream *O) { - if (O) print(*O); - } - virtual void print(std::ostream &O) = 0; + virtual void print(raw_ostream &O) = 0; void dump(); #endif }; @@ -297,7 +287,7 @@ namespace llvm { static bool classof(const DIEValue *I) { return I->getType() == isInteger; } #ifndef NDEBUG - virtual void print(std::ostream &O); + virtual void print(raw_ostream &O); #endif }; @@ -329,7 +319,7 @@ namespace llvm { static bool classof(const DIEValue *S) { return S->getType() == isString; } #ifndef NDEBUG - virtual void print(std::ostream &O); + virtual void print(raw_ostream &O); #endif }; @@ -359,7 +349,7 @@ namespace llvm { static bool classof(const DIEValue *L) { return L->getType() == isLabel; } #ifndef NDEBUG - virtual void print(std::ostream &O); + virtual void print(raw_ostream &O); #endif }; @@ -392,7 +382,7 @@ namespace llvm { } #ifndef NDEBUG - virtual void print(std::ostream &O); + virtual void print(raw_ostream &O); #endif }; @@ -431,7 +421,7 @@ namespace llvm { } #ifndef NDEBUG - virtual void print(std::ostream &O); + virtual void print(raw_ostream &O); #endif }; @@ -464,7 +454,7 @@ namespace llvm { static bool classof(const DIEValue *D) { return D->getType() == isDelta; } #ifndef NDEBUG - virtual void print(std::ostream &O); + virtual void print(raw_ostream &O); #endif }; @@ -500,7 +490,7 @@ namespace llvm { static bool classof(const DIEValue *E) { return E->getType() == isEntry; } #ifndef NDEBUG - virtual void print(std::ostream &O); + virtual void print(raw_ostream &O); #endif }; @@ -544,7 +534,7 @@ namespace llvm { static bool classof(const DIEValue *E) { return E->getType() == isBlock; } #ifndef NDEBUG - virtual void print(std::ostream &O); + virtual void print(raw_ostream &O); #endif }; diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp index 547140f..4394ec0 100644 --- a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -10,16 +10,24 @@ // This file contains support for writing dwarf debug info into asm files. // //===----------------------------------------------------------------------===// - +#define DEBUG_TYPE "dwarfdebug" #include "DwarfDebug.h" #include "llvm/Module.h" +#include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineModuleInfo.h" -#include "llvm/Support/Timer.h" -#include "llvm/System/Path.h" -#include "llvm/Target/TargetAsmInfo.h" -#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/MC/MCSection.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCAsmInfo.h" #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetFrameInfo.h" +#include "llvm/Target/TargetLoweringObjectFile.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/Mangler.h" +#include "llvm/Support/Timer.h" +#include "llvm/System/Path.h" using namespace llvm; static TimerGroup &getDwarfTimerGroup() { @@ -51,11 +59,13 @@ class VISIBILITY_HIDDEN CompileUnit { /// GVToDieMap - Tracks the mapping of unit level debug informaton /// variables to debug information entries. - std::map<GlobalVariable *, DIE *> GVToDieMap; + /// FIXME : Rename GVToDieMap -> NodeToDieMap + std::map<MDNode *, DIE *> GVToDieMap; /// GVToDIEEntryMap - Tracks the mapping of unit level debug informaton /// descriptors to debug information entries using a DIEEntry proxy. - std::map<GlobalVariable *, DIEEntry *> GVToDIEEntryMap; + /// FIXME : Rename + std::map<MDNode *, DIEEntry *> GVToDIEEntryMap; /// Globals - A map of globally visible named entities for this unit. /// @@ -84,12 +94,12 @@ public: /// getDieMapSlotFor - Returns the debug information entry map slot for the /// specified debug variable. - DIE *&getDieMapSlotFor(GlobalVariable *GV) { return GVToDieMap[GV]; } + DIE *&getDieMapSlotFor(MDNode *N) { return GVToDieMap[N]; } - /// getDIEEntrySlotFor - Returns the debug information entry proxy slot for the - /// specified debug variable. - DIEEntry *&getDIEEntrySlotFor(GlobalVariable *GV) { - return GVToDIEEntryMap[GV]; + /// getDIEEntrySlotFor - Returns the debug information entry proxy slot for + /// the specified debug variable. + DIEEntry *&getDIEEntrySlotFor(MDNode *N) { + return GVToDIEEntryMap[N]; } /// AddDie - Adds or interns the DIE to the compile unit. @@ -138,15 +148,18 @@ class VISIBILITY_HIDDEN DbgScope { // Either subprogram or block. unsigned StartLabelID; // Label ID of the beginning of scope. unsigned EndLabelID; // Label ID of the end of scope. + const MachineInstr *LastInsn; // Last instruction of this scope. + const MachineInstr *FirstInsn; // First instruction of this scope. SmallVector<DbgScope *, 4> Scopes; // Scopes defined in scope. SmallVector<DbgVariable *, 8> Variables;// Variables declared in scope. SmallVector<DbgConcreteScope *, 8> ConcreteInsts;// Concrete insts of funcs. - + // Private state for dump() mutable unsigned IndentLevel; public: DbgScope(DbgScope *P, DIDescriptor D) - : Parent(P), Desc(D), StartLabelID(0), EndLabelID(0), IndentLevel(0) {} + : Parent(P), Desc(D), StartLabelID(0), EndLabelID(0), LastInsn(0), + FirstInsn(0), IndentLevel(0) {} virtual ~DbgScope(); // Accessors. @@ -159,7 +172,10 @@ public: SmallVector<DbgConcreteScope*,8> &getConcreteInsts() { return ConcreteInsts; } void setStartLabelID(unsigned S) { StartLabelID = S; } void setEndLabelID(unsigned E) { EndLabelID = E; } - + void setLastInsn(const MachineInstr *MI) { LastInsn = MI; } + const MachineInstr *getLastInsn() { return LastInsn; } + void setFirstInsn(const MachineInstr *MI) { FirstInsn = MI; } + const MachineInstr *getFirstInsn() { return FirstInsn; } /// AddScope - Add a scope to the scope. /// void AddScope(DbgScope *S) { Scopes.push_back(S); } @@ -172,6 +188,21 @@ public: /// void AddConcreteInst(DbgConcreteScope *C) { ConcreteInsts.push_back(C); } + void FixInstructionMarkers() { + assert (getFirstInsn() && "First instruction is missing!"); + if (getLastInsn()) + return; + + // If a scope does not have an instruction to mark an end then use + // the end of last child scope. + SmallVector<DbgScope *, 4> &Scopes = getScopes(); + assert (!Scopes.empty() && "Inner most scope does not have last insn!"); + DbgScope *L = Scopes.back(); + if (!L->getLastInsn()) + L->FixInstructionMarkers(); + setLastInsn(L->getLastInsn()); + } + #ifndef NDEBUG void dump() const; #endif @@ -179,10 +210,10 @@ public: #ifndef NDEBUG void DbgScope::dump() const { - std::string Indent(IndentLevel, ' '); - - cerr << Indent; Desc.dump(); - cerr << " [" << StartLabelID << ", " << EndLabelID << "]\n"; + raw_ostream &err = errs(); + err.indent(IndentLevel); + Desc.dump(); + err << " [" << StartLabelID << ", " << EndLabelID << "]\n"; IndentLevel += 2; @@ -220,10 +251,10 @@ DbgScope::~DbgScope() { } // end llvm namespace -DwarfDebug::DwarfDebug(raw_ostream &OS, AsmPrinter *A, const TargetAsmInfo *T) +DwarfDebug::DwarfDebug(raw_ostream &OS, AsmPrinter *A, const MCAsmInfo *T) : Dwarf(OS, A, T, "dbg"), ModuleCU(0), AbbreviationsSet(InitAbbreviationsSetSize), Abbreviations(), - ValuesSet(InitValuesSetSize), Values(), StringPool(), SectionMap(), + ValuesSet(InitValuesSetSize), Values(), StringPool(), SectionSourceLines(), didInitial(false), shouldEmit(false), FunctionDbgScope(0), DebugTimer(0) { if (TimePassesIsEnabled) @@ -234,7 +265,7 @@ DwarfDebug::~DwarfDebug() { for (unsigned j = 0, M = Values.size(); j < M; ++j) delete Values[j]; - for (DenseMap<const GlobalVariable *, DbgScope *>::iterator + for (DenseMap<const MDNode *, DbgScope *>::iterator I = AbstractInstanceRootMap.begin(), E = AbstractInstanceRootMap.end(); I != E;++I) delete I->second; @@ -479,6 +510,27 @@ void DwarfDebug::AddSourceLine(DIE *Die, const DIGlobal *G) { AddUInt(Die, dwarf::DW_AT_decl_file, 0, FileID); AddUInt(Die, dwarf::DW_AT_decl_line, 0, Line); } + +/// AddSourceLine - Add location information to specified debug information +/// entry. +void DwarfDebug::AddSourceLine(DIE *Die, const DISubprogram *SP) { + // If there is no compile unit specified, don't add a line #. + if (SP->getCompileUnit().isNull()) + return; + // If the line number is 0, don't add it. + if (SP->getLineNumber() == 0) + return; + + + unsigned Line = SP->getLineNumber(); + unsigned FileID = FindCompileUnit(SP->getCompileUnit()).getID(); + assert(FileID && "Invalid file id"); + AddUInt(Die, dwarf::DW_AT_decl_file, 0, FileID); + AddUInt(Die, dwarf::DW_AT_decl_line, 0, Line); +} + +/// AddSourceLine - Add location information to specified debug information +/// entry. void DwarfDebug::AddSourceLine(DIE *Die, const DIType *Ty) { // If there is no compile unit specified, don't add a line #. DICompileUnit CU = Ty->getCompileUnit(); @@ -492,6 +544,270 @@ void DwarfDebug::AddSourceLine(DIE *Die, const DIType *Ty) { AddUInt(Die, dwarf::DW_AT_decl_line, 0, Line); } +/* Byref variables, in Blocks, are declared by the programmer as + "SomeType VarName;", but the compiler creates a + __Block_byref_x_VarName struct, and gives the variable VarName + 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 + the pointers and __Block_byref_x_VarName struct to find the actual + value of the variable. The function AddBlockByrefType does this. */ + +/// Find the type the programmer originally declared the variable to be +/// and return that type. +/// +DIType DwarfDebug::GetBlockByrefType(DIType Ty, std::string Name) { + + DIType subType = Ty; + unsigned tag = Ty.getTag(); + + if (tag == dwarf::DW_TAG_pointer_type) { + DIDerivedType DTy = DIDerivedType(Ty.getNode()); + subType = DTy.getTypeDerivedFrom(); + } + + DICompositeType blockStruct = DICompositeType(subType.getNode()); + + DIArray Elements = blockStruct.getTypeArray(); + + if (Elements.isNull()) + return Ty; + + for (unsigned i = 0, N = Elements.getNumElements(); i < N; ++i) { + DIDescriptor Element = Elements.getElement(i); + DIDerivedType DT = DIDerivedType(Element.getNode()); + if (strcmp(Name.c_str(), DT.getName()) == 0) + return (DT.getTypeDerivedFrom()); + } + + return Ty; +} + +/// AddComplexAddress - Start with the address based on the location provided, +/// and generate the DWARF information necessary to find the actual variable +/// given the extra address information encoded in the DIVariable, starting from +/// the starting location. Add the DWARF information to the die. +/// +void DwarfDebug::AddComplexAddress(DbgVariable *&DV, DIE *Die, + unsigned Attribute, + const MachineLocation &Location) { + const DIVariable &VD = DV->getVariable(); + DIType Ty = VD.getType(); + + // Decode the original location, and use that as the start of the byref + // variable's location. + unsigned Reg = RI->getDwarfRegNum(Location.getReg(), false); + DIEBlock *Block = new DIEBlock(); + + if (Location.isReg()) { + if (Reg < 32) { + AddUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_reg0 + Reg); + } else { + Reg = Reg - dwarf::DW_OP_reg0; + AddUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_breg0 + Reg); + AddUInt(Block, 0, dwarf::DW_FORM_udata, Reg); + } + } else { + if (Reg < 32) + AddUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_breg0 + Reg); + else { + AddUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_bregx); + AddUInt(Block, 0, dwarf::DW_FORM_udata, Reg); + } + + AddUInt(Block, 0, dwarf::DW_FORM_sdata, Location.getOffset()); + } + + for (unsigned i = 0, N = VD.getNumAddrElements(); i < N; ++i) { + uint64_t Element = VD.getAddrElement(i); + + if (Element == DIFactory::OpPlus) { + AddUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_plus_uconst); + AddUInt(Block, 0, dwarf::DW_FORM_udata, VD.getAddrElement(++i)); + } else if (Element == DIFactory::OpDeref) { + AddUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_deref); + } else llvm_unreachable("unknown DIFactory Opcode"); + } + + // Now attach the location information to the DIE. + AddBlock(Die, Attribute, 0, Block); +} + +/* Byref variables, in Blocks, are declared by the programmer as "SomeType + VarName;", but the compiler creates a __Block_byref_x_VarName struct, and + gives the variable VarName 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 function GetBlockByrefType dives into the __Block_byref_x_VarName + struct to find the original type of the variable, which is then assigned to + the variable's Debug Information Entry as its real type. So far, so good. + However now the debugger will expect the variable VarName to have the type + SomeType. So we need the location attribute for the variable to be an + expression that explains to the debugger how to navigate through the + pointers and struct to find the actual variable of type SomeType. + + The following function does just that. We start by getting + the "normal" location for the variable. This will be the location + of either the struct __Block_byref_x_VarName or the pointer to the + struct __Block_byref_x_VarName. + + The struct will look something like: + + struct __Block_byref_x_VarName { + ... <various fields> + struct __Block_byref_x_VarName *forwarding; + ... <various other fields> + SomeType VarName; + ... <maybe more fields> + }; + + If we are given the struct directly (as our starting point) we + need to tell the debugger to: + + 1). Add the offset of the forwarding field. + + 2). Follow that pointer to get the the real __Block_byref_x_VarName + struct to use (the real one may have been copied onto the heap). + + 3). Add the offset for the field VarName, to find the actual variable. + + If we started with a pointer to the struct, then we need to + dereference that pointer first, before the other steps. + Translating this into DWARF ops, we will need to append the following + to the current location description for the variable: + + DW_OP_deref -- optional, if we start with a pointer + DW_OP_plus_uconst <forward_fld_offset> + DW_OP_deref + DW_OP_plus_uconst <varName_fld_offset> + + That is what this function does. */ + +/// AddBlockByrefAddress - Start with the address based on the location +/// provided, and generate the DWARF information necessary to find the +/// actual Block variable (navigating the Block struct) based on the +/// starting location. Add the DWARF information to the die. For +/// more information, read large comment just above here. +/// +void DwarfDebug::AddBlockByrefAddress(DbgVariable *&DV, DIE *Die, + unsigned Attribute, + const MachineLocation &Location) { + const DIVariable &VD = DV->getVariable(); + DIType Ty = VD.getType(); + DIType TmpTy = Ty; + unsigned Tag = Ty.getTag(); + bool isPointer = false; + + const char *varName = VD.getName(); + + if (Tag == dwarf::DW_TAG_pointer_type) { + DIDerivedType DTy = DIDerivedType(Ty.getNode()); + TmpTy = DTy.getTypeDerivedFrom(); + isPointer = true; + } + + DICompositeType blockStruct = DICompositeType(TmpTy.getNode()); + + // Find the __forwarding field and the variable field in the __Block_byref + // struct. + DIArray Fields = blockStruct.getTypeArray(); + DIDescriptor varField = DIDescriptor(); + DIDescriptor forwardingField = DIDescriptor(); + + + for (unsigned i = 0, N = Fields.getNumElements(); i < N; ++i) { + DIDescriptor Element = Fields.getElement(i); + DIDerivedType DT = DIDerivedType(Element.getNode()); + const char *fieldName = DT.getName(); + if (strcmp(fieldName, "__forwarding") == 0) + forwardingField = Element; + else if (strcmp(fieldName, varName) == 0) + varField = Element; + } + + assert(!varField.isNull() && "Can't find byref variable in Block struct"); + assert(!forwardingField.isNull() + && "Can't find forwarding field in Block struct"); + + // Get the offsets for the forwarding field and the variable field. + unsigned int forwardingFieldOffset = + DIDerivedType(forwardingField.getNode()).getOffsetInBits() >> 3; + unsigned int varFieldOffset = + DIDerivedType(varField.getNode()).getOffsetInBits() >> 3; + + // Decode the original location, and use that as the start of the byref + // variable's location. + unsigned Reg = RI->getDwarfRegNum(Location.getReg(), false); + DIEBlock *Block = new DIEBlock(); + + if (Location.isReg()) { + if (Reg < 32) + AddUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_reg0 + Reg); + else { + Reg = Reg - dwarf::DW_OP_reg0; + AddUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_breg0 + Reg); + AddUInt(Block, 0, dwarf::DW_FORM_udata, Reg); + } + } else { + if (Reg < 32) + AddUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_breg0 + Reg); + else { + AddUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_bregx); + AddUInt(Block, 0, dwarf::DW_FORM_udata, Reg); + } + + AddUInt(Block, 0, dwarf::DW_FORM_sdata, Location.getOffset()); + } + + // If we started with a pointer to the __Block_byref... struct, then + // the first thing we need to do is dereference the pointer (DW_OP_deref). + if (isPointer) + AddUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_deref); + + // Next add the offset for the '__forwarding' field: + // DW_OP_plus_uconst ForwardingFieldOffset. Note there's no point in + // adding the offset if it's 0. + if (forwardingFieldOffset > 0) { + AddUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_plus_uconst); + AddUInt(Block, 0, dwarf::DW_FORM_udata, forwardingFieldOffset); + } + + // Now dereference the __forwarding field to get to the real __Block_byref + // struct: DW_OP_deref. + AddUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_deref); + + // Now that we've got the real __Block_byref... struct, add the offset + // for the variable's field to get to the location of the actual variable: + // DW_OP_plus_uconst varFieldOffset. Again, don't add if it's 0. + if (varFieldOffset > 0) { + AddUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_plus_uconst); + AddUInt(Block, 0, dwarf::DW_FORM_udata, varFieldOffset); + } + + // Now attach the location information to the DIE. + AddBlock(Die, Attribute, 0, Block); +} + /// AddAddress - Add an address attribute to a die based on the location /// provided. void DwarfDebug::AddAddress(DIE *Die, unsigned Attribute, @@ -526,7 +842,7 @@ void DwarfDebug::AddType(CompileUnit *DW_Unit, DIE *Entity, DIType Ty) { return; // Check for pre-existence. - DIEEntry *&Slot = DW_Unit->getDIEEntrySlotFor(Ty.getGV()); + DIEEntry *&Slot = DW_Unit->getDIEEntrySlotFor(Ty.getNode()); // If it exists then use the existing value. if (Slot) { @@ -539,20 +855,20 @@ void DwarfDebug::AddType(CompileUnit *DW_Unit, DIE *Entity, DIType Ty) { // Construct type. DIE Buffer(dwarf::DW_TAG_base_type); - if (Ty.isBasicType(Ty.getTag())) - ConstructTypeDIE(DW_Unit, Buffer, DIBasicType(Ty.getGV())); - else if (Ty.isDerivedType(Ty.getTag())) - ConstructTypeDIE(DW_Unit, Buffer, DIDerivedType(Ty.getGV())); + if (Ty.isBasicType()) + ConstructTypeDIE(DW_Unit, Buffer, DIBasicType(Ty.getNode())); + else if (Ty.isCompositeType()) + ConstructTypeDIE(DW_Unit, Buffer, DICompositeType(Ty.getNode())); else { - assert(Ty.isCompositeType(Ty.getTag()) && "Unknown kind of DIType"); - ConstructTypeDIE(DW_Unit, Buffer, DICompositeType(Ty.getGV())); + assert(Ty.isDerivedType() && "Unknown kind of DIType"); + ConstructTypeDIE(DW_Unit, Buffer, DIDerivedType(Ty.getNode())); } // Add debug information entry to entity and appropriate context. DIE *Die = NULL; DIDescriptor Context = Ty.getContext(); if (!Context.isNull()) - Die = DW_Unit->getDieMapSlotFor(Context.getGV()); + Die = DW_Unit->getDieMapSlotFor(Context.getNode()); if (Die) { DIE *Child = new DIE(Buffer); @@ -571,14 +887,13 @@ void DwarfDebug::AddType(CompileUnit *DW_Unit, DIE *Entity, DIType Ty) { void DwarfDebug::ConstructTypeDIE(CompileUnit *DW_Unit, DIE &Buffer, DIBasicType BTy) { // Get core information. - std::string Name; - BTy.getName(Name); + const char *Name = BTy.getName(); Buffer.setTag(dwarf::DW_TAG_base_type); AddUInt(&Buffer, dwarf::DW_AT_encoding, dwarf::DW_FORM_data1, BTy.getEncoding()); // Add name if not anonymous or intermediate type. - if (!Name.empty()) + if (Name) AddString(&Buffer, dwarf::DW_AT_name, dwarf::DW_FORM_string, Name); uint64_t Size = BTy.getSizeInBits() >> 3; AddUInt(&Buffer, dwarf::DW_AT_byte_size, 0, Size); @@ -588,8 +903,7 @@ void DwarfDebug::ConstructTypeDIE(CompileUnit *DW_Unit, DIE &Buffer, void DwarfDebug::ConstructTypeDIE(CompileUnit *DW_Unit, DIE &Buffer, DIDerivedType DTy) { // Get core information. - std::string Name; - DTy.getName(Name); + const char *Name = DTy.getName(); uint64_t Size = DTy.getSizeInBits() >> 3; unsigned Tag = DTy.getTag(); @@ -603,7 +917,7 @@ void DwarfDebug::ConstructTypeDIE(CompileUnit *DW_Unit, DIE &Buffer, AddType(DW_Unit, &Buffer, FromTy); // Add name if not anonymous or intermediate type. - if (!Name.empty()) + if (Name) AddString(&Buffer, dwarf::DW_AT_name, dwarf::DW_FORM_string, Name); // Add size if non-zero (derived types might be zero-sized.) @@ -619,8 +933,7 @@ void DwarfDebug::ConstructTypeDIE(CompileUnit *DW_Unit, DIE &Buffer, void DwarfDebug::ConstructTypeDIE(CompileUnit *DW_Unit, DIE &Buffer, DICompositeType CTy) { // Get core information. - std::string Name; - CTy.getName(Name); + const char *Name = CTy.getName(); uint64_t Size = CTy.getSizeInBits() >> 3; unsigned Tag = CTy.getTag(); @@ -637,9 +950,11 @@ void DwarfDebug::ConstructTypeDIE(CompileUnit *DW_Unit, DIE &Buffer, // Add enumerators to enumeration type. for (unsigned i = 0, N = Elements.getNumElements(); i < N; ++i) { DIE *ElemDie = NULL; - DIEnumerator Enum(Elements.getElement(i).getGV()); - ElemDie = ConstructEnumTypeDIE(DW_Unit, &Enum); - Buffer.AddChild(ElemDie); + DIEnumerator Enum(Elements.getElement(i).getNode()); + if (!Enum.isNull()) { + ElemDie = ConstructEnumTypeDIE(DW_Unit, &Enum); + Buffer.AddChild(ElemDie); + } } } break; @@ -647,7 +962,7 @@ void DwarfDebug::ConstructTypeDIE(CompileUnit *DW_Unit, DIE &Buffer, // Add return type. DIArray Elements = CTy.getTypeArray(); DIDescriptor RTy = Elements.getElement(0); - AddType(DW_Unit, &Buffer, DIType(RTy.getGV())); + AddType(DW_Unit, &Buffer, DIType(RTy.getNode())); // Add prototype flag. AddUInt(&Buffer, dwarf::DW_AT_prototyped, dwarf::DW_FORM_flag, 1); @@ -656,7 +971,7 @@ void DwarfDebug::ConstructTypeDIE(CompileUnit *DW_Unit, DIE &Buffer, for (unsigned i = 1, N = Elements.getNumElements(); i < N; ++i) { DIE *Arg = new DIE(dwarf::DW_TAG_formal_parameter); DIDescriptor Ty = Elements.getElement(i); - AddType(DW_Unit, Arg, DIType(Ty.getGV())); + AddType(DW_Unit, Arg, DIType(Ty.getNode())); Buffer.AddChild(Arg); } } @@ -674,20 +989,19 @@ void DwarfDebug::ConstructTypeDIE(CompileUnit *DW_Unit, DIE &Buffer, // Add elements to structure type. for (unsigned i = 0, N = Elements.getNumElements(); i < N; ++i) { DIDescriptor Element = Elements.getElement(i); + if (Element.isNull()) + continue; DIE *ElemDie = NULL; if (Element.getTag() == dwarf::DW_TAG_subprogram) ElemDie = CreateSubprogramDIE(DW_Unit, - DISubprogram(Element.getGV())); + DISubprogram(Element.getNode())); else ElemDie = CreateMemberDIE(DW_Unit, - DIDerivedType(Element.getGV())); + DIDerivedType(Element.getNode())); Buffer.AddChild(ElemDie); } - // FIXME: We'd like an API to register additional attributes for the - // frontend to use while synthesizing, and then we'd use that api in clang - // instead of this. - if (Name == "__block_literal_generic") + if (CTy.isAppleBlockExtension()) AddUInt(&Buffer, dwarf::DW_AT_APPLE_block, dwarf::DW_FORM_flag, 1); unsigned RLang = CTy.getRunTimeLang(); @@ -701,7 +1015,7 @@ void DwarfDebug::ConstructTypeDIE(CompileUnit *DW_Unit, DIE &Buffer, } // Add name if not anonymous or intermediate type. - if (!Name.empty()) + if (Name) AddString(&Buffer, dwarf::DW_AT_name, dwarf::DW_FORM_string, Name); if (Tag == dwarf::DW_TAG_enumeration_type || @@ -729,12 +1043,11 @@ void DwarfDebug::ConstructSubrangeDIE(DIE &Buffer, DISubrange SR, DIE *IndexTy){ int64_t H = SR.getHi(); DIE *DW_Subrange = new DIE(dwarf::DW_TAG_subrange_type); - if (L != H) { - AddDIEEntry(DW_Subrange, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, IndexTy); - if (L) - AddSInt(DW_Subrange, dwarf::DW_AT_lower_bound, 0, L); + AddDIEEntry(DW_Subrange, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, IndexTy); + if (L) + AddSInt(DW_Subrange, dwarf::DW_AT_lower_bound, 0, L); + if (H) AddSInt(DW_Subrange, dwarf::DW_AT_upper_bound, 0, H); - } Buffer.AddChild(DW_Subrange); } @@ -761,15 +1074,14 @@ void DwarfDebug::ConstructArrayTypeDIE(CompileUnit *DW_Unit, DIE &Buffer, for (unsigned i = 0, N = Elements.getNumElements(); i < N; ++i) { DIDescriptor Element = Elements.getElement(i); if (Element.getTag() == dwarf::DW_TAG_subrange_type) - ConstructSubrangeDIE(Buffer, DISubrange(Element.getGV()), IndexTy); + ConstructSubrangeDIE(Buffer, DISubrange(Element.getNode()), IndexTy); } } /// ConstructEnumTypeDIE - Construct enum type DIE from DIEnumerator. DIE *DwarfDebug::ConstructEnumTypeDIE(CompileUnit *DW_Unit, DIEnumerator *ETy) { DIE *Enumerator = new DIE(dwarf::DW_TAG_enumerator); - std::string Name; - ETy->getName(Name); + const char *Name = ETy->getName(); AddString(Enumerator, dwarf::DW_AT_name, dwarf::DW_FORM_string, Name); int64_t Value = ETy->getEnumValue(); AddSInt(Enumerator, dwarf::DW_AT_const_value, dwarf::DW_FORM_sdata, Value); @@ -780,27 +1092,39 @@ DIE *DwarfDebug::ConstructEnumTypeDIE(CompileUnit *DW_Unit, DIEnumerator *ETy) { DIE *DwarfDebug::CreateGlobalVariableDIE(CompileUnit *DW_Unit, const DIGlobalVariable &GV) { DIE *GVDie = new DIE(dwarf::DW_TAG_variable); - std::string Name; - GV.getDisplayName(Name); - AddString(GVDie, dwarf::DW_AT_name, dwarf::DW_FORM_string, Name); - std::string LinkageName; - GV.getLinkageName(LinkageName); - if (!LinkageName.empty()) + AddString(GVDie, dwarf::DW_AT_name, dwarf::DW_FORM_string, + GV.getDisplayName()); + + const char *LinkageName = GV.getLinkageName(); + if (LinkageName) { + // Skip special LLVM prefix that is used to inform the asm printer to not + // emit usual symbol prefix before the symbol name. This happens for + // Objective-C symbol names and symbol whose name is replaced using GCC's + // __asm__ attribute. + if (LinkageName[0] == 1) + LinkageName = &LinkageName[1]; AddString(GVDie, dwarf::DW_AT_MIPS_linkage_name, dwarf::DW_FORM_string, LinkageName); + } AddType(DW_Unit, GVDie, GV.getType()); if (!GV.isLocalToUnit()) AddUInt(GVDie, dwarf::DW_AT_external, dwarf::DW_FORM_flag, 1); AddSourceLine(GVDie, &GV); + + // Add address. + DIEBlock *Block = new DIEBlock(); + AddUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_addr); + AddObjectLabel(Block, 0, dwarf::DW_FORM_udata, + Asm->Mang->getMangledName(GV.getGlobal())); + AddBlock(GVDie, dwarf::DW_AT_location, 0, Block); + return GVDie; } /// CreateMemberDIE - Create new member DIE. DIE *DwarfDebug::CreateMemberDIE(CompileUnit *DW_Unit, const DIDerivedType &DT){ DIE *MemberDie = new DIE(DT.getTag()); - std::string Name; - DT.getName(Name); - if (!Name.empty()) + if (const char *Name = DT.getName()) AddString(MemberDie, dwarf::DW_AT_name, dwarf::DW_FORM_string, Name); AddType(DW_Unit, MemberDie, DT.getTypeDerivedFrom()); @@ -849,17 +1173,19 @@ DIE *DwarfDebug::CreateSubprogramDIE(CompileUnit *DW_Unit, bool IsInlined) { DIE *SPDie = new DIE(dwarf::DW_TAG_subprogram); - std::string Name; - SP.getName(Name); + const char * Name = SP.getName(); AddString(SPDie, dwarf::DW_AT_name, dwarf::DW_FORM_string, Name); - std::string LinkageName; - SP.getLinkageName(LinkageName); - - if (!LinkageName.empty()) + const char *LinkageName = SP.getLinkageName(); + if (LinkageName) { + // Skip special LLVM prefix that is used to inform the asm printer to not emit + // usual symbol prefix before the symbol name. This happens for Objective-C + // symbol names and symbol whose name is replaced using GCC's __asm__ attribute. + if (LinkageName[0] == 1) + LinkageName = &LinkageName[1]; AddString(SPDie, dwarf::DW_AT_MIPS_linkage_name, dwarf::DW_FORM_string, LinkageName); - + } AddSourceLine(SPDie, &SP); DICompositeType SPTy = SP.getType(); @@ -877,7 +1203,7 @@ DIE *DwarfDebug::CreateSubprogramDIE(CompileUnit *DW_Unit, if (Args.isNull() || SPTag != dwarf::DW_TAG_subroutine_type) AddType(DW_Unit, SPDie, SPTy); else - AddType(DW_Unit, SPDie, DIType(Args.getElement(0).getGV())); + AddType(DW_Unit, SPDie, DIType(Args.getElement(0).getNode())); } if (!SP.isDefinition()) { @@ -888,7 +1214,7 @@ DIE *DwarfDebug::CreateSubprogramDIE(CompileUnit *DW_Unit, 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); - AddType(DW_Unit, Arg, DIType(Args.getElement(i).getGV())); + AddType(DW_Unit, Arg, DIType(Args.getElement(i).getNode())); AddUInt(Arg, dwarf::DW_AT_artificial, dwarf::DW_FORM_flag, 1); // ?? SPDie->AddChild(Arg); } @@ -898,7 +1224,7 @@ DIE *DwarfDebug::CreateSubprogramDIE(CompileUnit *DW_Unit, AddUInt(SPDie, dwarf::DW_AT_external, dwarf::DW_FORM_flag, 1); // DW_TAG_inlined_subroutine may refer to this DIE. - DIE *&Slot = DW_Unit->getDieMapSlotFor(SP.getGV()); + DIE *&Slot = DW_Unit->getDieMapSlotFor(SP.getNode()); Slot = SPDie; return SPDie; } @@ -907,7 +1233,7 @@ DIE *DwarfDebug::CreateSubprogramDIE(CompileUnit *DW_Unit, /// CompileUnit &DwarfDebug::FindCompileUnit(DICompileUnit Unit) const { DenseMap<Value *, CompileUnit *>::const_iterator I = - CompileUnitMap.find(Unit.getGV()); + CompileUnitMap.find(Unit.getNode()); assert(I != CompileUnitMap.end() && "Missing compile unit."); return *I->second; } @@ -935,15 +1261,18 @@ DIE *DwarfDebug::CreateDbgScopeVariable(DbgVariable *DV, CompileUnit *Unit) { // Define variable debug information entry. DIE *VariableDie = new DIE(Tag); - std::string Name; - VD.getName(Name); + const char *Name = VD.getName(); AddString(VariableDie, dwarf::DW_AT_name, dwarf::DW_FORM_string, Name); // Add source line info if available. AddSourceLine(VariableDie, &VD); // Add variable type. - AddType(Unit, VariableDie, VD.getType()); + // FIXME: isBlockByrefVariable should be reformulated in terms of complex addresses instead. + if (VD.isBlockByrefVariable()) + AddType(Unit, VariableDie, GetBlockByrefType(VD.getType(), Name)); + else + AddType(Unit, VariableDie, VD.getType()); // Add variable address. if (!DV->isInlinedFnVar()) { @@ -952,7 +1281,14 @@ DIE *DwarfDebug::CreateDbgScopeVariable(DbgVariable *DV, CompileUnit *Unit) { MachineLocation Location; Location.set(RI->getFrameRegister(*MF), RI->getFrameIndexOffset(*MF, DV->getFrameIndex())); - AddAddress(VariableDie, dwarf::DW_AT_location, Location); + + + if (VD.hasComplexAddress()) + AddComplexAddress(DV, VariableDie, dwarf::DW_AT_location, Location); + else if (VD.isBlockByrefVariable()) + AddBlockByrefAddress(DV, VariableDie, dwarf::DW_AT_location, Location); + else + AddAddress(VariableDie, dwarf::DW_AT_location, Location); } return VariableDie; @@ -960,26 +1296,64 @@ DIE *DwarfDebug::CreateDbgScopeVariable(DbgVariable *DV, CompileUnit *Unit) { /// getOrCreateScope - Returns the scope associated with the given descriptor. /// -DbgScope *DwarfDebug::getOrCreateScope(GlobalVariable *V) { - DbgScope *&Slot = DbgScopeMap[V]; +DbgScope *DwarfDebug::getDbgScope(MDNode *N, const MachineInstr *MI) { + DbgScope *&Slot = DbgScopeMap[N]; + if (Slot) return Slot; + + DbgScope *Parent = NULL; + + DIDescriptor Scope(N); + if (Scope.isCompileUnit()) { + return NULL; + } else if (Scope.isSubprogram()) { + DISubprogram SP(N); + DIDescriptor ParentDesc = SP.getContext(); + if (!ParentDesc.isNull() && !ParentDesc.isCompileUnit()) + Parent = getDbgScope(ParentDesc.getNode(), MI); + } else if (Scope.isLexicalBlock()) { + DILexicalBlock DB(N); + DIDescriptor ParentDesc = DB.getContext(); + if (!ParentDesc.isNull()) + Parent = getDbgScope(ParentDesc.getNode(), MI); + } else + assert (0 && "Unexpected scope info"); + + Slot = new DbgScope(Parent, DIDescriptor(N)); + Slot->setFirstInsn(MI); + + if (Parent) + Parent->AddScope(Slot); + else + // First function is top level function. + if (!FunctionDbgScope) + FunctionDbgScope = Slot; + + return Slot; +} + + +/// getOrCreateScope - Returns the scope associated with the given descriptor. +/// FIXME - Remove this method. +DbgScope *DwarfDebug::getOrCreateScope(MDNode *N) { + DbgScope *&Slot = DbgScopeMap[N]; if (Slot) return Slot; DbgScope *Parent = NULL; - DIBlock Block(V); + DILexicalBlock Block(N); // Don't create a new scope if we already created one for an inlined function. - DenseMap<const GlobalVariable *, DbgScope *>::iterator - II = AbstractInstanceRootMap.find(V); + DenseMap<const MDNode *, DbgScope *>::iterator + II = AbstractInstanceRootMap.find(N); if (II != AbstractInstanceRootMap.end()) return LexicalScopeStack.back(); if (!Block.isNull()) { DIDescriptor ParentDesc = Block.getContext(); Parent = - ParentDesc.isNull() ? NULL : getOrCreateScope(ParentDesc.getGV()); + ParentDesc.isNull() ? NULL : getOrCreateScope(ParentDesc.getNode()); } - Slot = new DbgScope(Parent, DIDescriptor(V)); + Slot = new DbgScope(Parent, DIDescriptor(N)); if (Parent) Parent->AddScope(Slot); @@ -1088,10 +1462,14 @@ void DwarfDebug::ConstructFunctionDbgScope(DbgScope *RootScope, return; // Get the subprogram debug information entry. - DISubprogram SPD(Desc.getGV()); + DISubprogram SPD(Desc.getNode()); // Get the subprogram die. - DIE *SPDie = ModuleCU->getDieMapSlotFor(SPD.getGV()); + DIE *SPDie = ModuleCU->getDieMapSlotFor(SPD.getNode()); + if (!SPDie) { + ConstructSubprogram(SPD.getNode()); + SPDie = ModuleCU->getDieMapSlotFor(SPD.getNode()); + } assert(SPDie && "Missing subprogram descriptor"); if (!AbstractScope) { @@ -1105,23 +1483,33 @@ void DwarfDebug::ConstructFunctionDbgScope(DbgScope *RootScope, } ConstructDbgScope(RootScope, 0, 0, SPDie, ModuleCU); + // If there are global variables at this scope then add their dies. + for (SmallVector<WeakVH, 4>::iterator SGI = ScopedGVs.begin(), + SGE = ScopedGVs.end(); SGI != SGE; ++SGI) { + MDNode *N = dyn_cast_or_null<MDNode>(*SGI); + if (!N) continue; + DIGlobalVariable GV(N); + if (GV.getContext().getNode() == RootScope->getDesc().getNode()) { + DIE *ScopedGVDie = CreateGlobalVariableDIE(ModuleCU, GV); + SPDie->AddChild(ScopedGVDie); + } + } } /// ConstructDefaultDbgScope - Construct a default scope for the subprogram. /// void DwarfDebug::ConstructDefaultDbgScope(MachineFunction *MF) { - const char *FnName = MF->getFunction()->getNameStart(); StringMap<DIE*> &Globals = ModuleCU->getGlobals(); - StringMap<DIE*>::iterator GI = Globals.find(FnName); + StringMap<DIE*>::iterator GI = Globals.find(MF->getFunction()->getName()); if (GI != Globals.end()) { DIE *SPDie = GI->second; - + // Add the function bounds. AddLabel(SPDie, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr, DWLabel("func_begin", SubprogramCount)); AddLabel(SPDie, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr, DWLabel("func_end", SubprogramCount)); - + MachineLocation Location(RI->getFrameRegister(*MF)); AddAddress(SPDie, dwarf::DW_AT_frame_base, Location); } @@ -1131,8 +1519,8 @@ void DwarfDebug::ConstructDefaultDbgScope(MachineFunction *MF) { /// 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(const std::string &DirName, - const std::string &FileName) { +unsigned DwarfDebug::GetOrCreateSourceID(const char *DirName, + const char *FileName) { unsigned DId; StringMap<unsigned>::iterator DI = DirectoryIdMap.find(DirName); if (DI != DirectoryIdMap.end()) { @@ -1165,30 +1553,28 @@ unsigned DwarfDebug::GetOrCreateSourceID(const std::string &DirName, return SrcId; } -void DwarfDebug::ConstructCompileUnit(GlobalVariable *GV) { - DICompileUnit DIUnit(GV); - std::string Dir, FN, Prod; - unsigned ID = GetOrCreateSourceID(DIUnit.getDirectory(Dir), - DIUnit.getFilename(FN)); +void DwarfDebug::ConstructCompileUnit(MDNode *N) { + DICompileUnit DIUnit(N); + const char *FN = DIUnit.getFilename(); + const char *Dir = DIUnit.getDirectory(); + unsigned ID = GetOrCreateSourceID(Dir, FN); DIE *Die = new DIE(dwarf::DW_TAG_compile_unit); AddSectionOffset(Die, dwarf::DW_AT_stmt_list, dwarf::DW_FORM_data4, DWLabel("section_line", 0), DWLabel("section_line", 0), false); AddString(Die, dwarf::DW_AT_producer, dwarf::DW_FORM_string, - DIUnit.getProducer(Prod)); + DIUnit.getProducer()); AddUInt(Die, dwarf::DW_AT_language, dwarf::DW_FORM_data1, DIUnit.getLanguage()); AddString(Die, dwarf::DW_AT_name, dwarf::DW_FORM_string, FN); - if (!Dir.empty()) + if (Dir) AddString(Die, dwarf::DW_AT_comp_dir, dwarf::DW_FORM_string, Dir); if (DIUnit.isOptimized()) AddUInt(Die, dwarf::DW_AT_APPLE_optimized, dwarf::DW_FORM_flag, 1); - std::string Flags; - DIUnit.getFlags(Flags); - if (!Flags.empty()) + if (const char *Flags = DIUnit.getFlags()) AddString(Die, dwarf::DW_AT_APPLE_flags, dwarf::DW_FORM_string, Flags); unsigned RVer = DIUnit.getRunTimeVersion(); @@ -1203,28 +1589,24 @@ void DwarfDebug::ConstructCompileUnit(GlobalVariable *GV) { ModuleCU = Unit; } - CompileUnitMap[DIUnit.getGV()] = Unit; + CompileUnitMap[DIUnit.getNode()] = Unit; CompileUnits.push_back(Unit); } -void DwarfDebug::ConstructGlobalVariableDIE(GlobalVariable *GV) { - DIGlobalVariable DI_GV(GV); +void DwarfDebug::ConstructGlobalVariableDIE(MDNode *N) { + DIGlobalVariable DI_GV(N); + + // If debug information is malformed then ignore it. + if (DI_GV.Verify() == false) + return; // Check for pre-existence. - DIE *&Slot = ModuleCU->getDieMapSlotFor(DI_GV.getGV()); + DIE *&Slot = ModuleCU->getDieMapSlotFor(DI_GV.getNode()); if (Slot) return; DIE *VariableDie = CreateGlobalVariableDIE(ModuleCU, DI_GV); - // Add address. - DIEBlock *Block = new DIEBlock(); - AddUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_addr); - std::string GLN; - AddObjectLabel(Block, 0, dwarf::DW_FORM_udata, - Asm->getGlobalLinkName(DI_GV.getGlobal(), GLN)); - AddBlock(VariableDie, dwarf::DW_AT_location, 0, Block); - // Add to map. Slot = VariableDie; @@ -1232,16 +1614,15 @@ void DwarfDebug::ConstructGlobalVariableDIE(GlobalVariable *GV) { ModuleCU->getDie()->AddChild(VariableDie); // Expose as global. FIXME - need to check external flag. - std::string Name; - ModuleCU->AddGlobal(DI_GV.getName(Name), VariableDie); + ModuleCU->AddGlobal(DI_GV.getName(), VariableDie); return; } -void DwarfDebug::ConstructSubprogram(GlobalVariable *GV) { - DISubprogram SP(GV); +void DwarfDebug::ConstructSubprogram(MDNode *N) { + DISubprogram SP(N); // Check for pre-existence. - DIE *&Slot = ModuleCU->getDieMapSlotFor(GV); + DIE *&Slot = ModuleCU->getDieMapSlotFor(N); if (Slot) return; @@ -1259,28 +1640,25 @@ void DwarfDebug::ConstructSubprogram(GlobalVariable *GV) { ModuleCU->getDie()->AddChild(SubprogramDie); // Expose as global. - std::string Name; - ModuleCU->AddGlobal(SP.getName(Name), SubprogramDie); + ModuleCU->AddGlobal(SP.getName(), SubprogramDie); return; } - /// BeginModule - Emit all Dwarf sections that should come prior to the - /// content. Create global DIEs and emit initial debug info sections. - /// This is inovked by the target AsmPrinter. +/// BeginModule - Emit all Dwarf sections that should come prior to the +/// content. Create global DIEs and emit initial debug info sections. +/// This is inovked by the target AsmPrinter. void DwarfDebug::BeginModule(Module *M, MachineModuleInfo *mmi) { this->M = M; if (TimePassesIsEnabled) DebugTimer->startTimer(); - SmallVector<GlobalVariable *, 2> CUs; - SmallVector<GlobalVariable *, 4> GVs; - SmallVector<GlobalVariable *, 4> SPs; - CollectDebugInfoAnchors(*M, CUs, GVs, SPs); + DebugInfoFinder DbgFinder; + DbgFinder.processModule(*M); // Create all the compile unit DIEs. - for (SmallVector<GlobalVariable *, 2>::iterator I = CUs.begin(), - E = CUs.end(); I != E; ++I) + for (DebugInfoFinder::iterator I = DbgFinder.compile_unit_begin(), + E = DbgFinder.compile_unit_end(); I != E; ++I) ConstructCompileUnit(*I); if (CompileUnits.empty()) { @@ -1295,23 +1673,19 @@ void DwarfDebug::BeginModule(Module *M, MachineModuleInfo *mmi) { if (!ModuleCU) ModuleCU = CompileUnits[0]; - // If there is not any debug info available for any global variables and any - // subprograms then there is not any debug info to emit. - if (GVs.empty() && SPs.empty()) { - if (TimePassesIsEnabled) - DebugTimer->stopTimer(); - - return; - } - // Create DIEs for each of the externally visible global variables. - for (SmallVector<GlobalVariable *, 4>::iterator I = GVs.begin(), - E = GVs.end(); I != E; ++I) - ConstructGlobalVariableDIE(*I); + for (DebugInfoFinder::iterator I = DbgFinder.global_variable_begin(), + E = DbgFinder.global_variable_end(); I != E; ++I) { + DIGlobalVariable GV(*I); + if (GV.getContext().getNode() != GV.getCompileUnit().getNode()) + ScopedGVs.push_back(*I); + else + ConstructGlobalVariableDIE(*I); + } // Create DIEs for each of the externally visible subprograms. - for (SmallVector<GlobalVariable *, 4>::iterator I = SPs.begin(), - E = SPs.end(); I != E; ++I) + for (DebugInfoFinder::iterator I = DbgFinder.subprogram_begin(), + E = DbgFinder.subprogram_end(); I != E; ++I) ConstructSubprogram(*I); MMI = mmi; @@ -1319,11 +1693,11 @@ void DwarfDebug::BeginModule(Module *M, MachineModuleInfo *mmi) { MMI->setDebugInfoAvailability(true); // Prime section data. - SectionMap.insert(TAI->getTextSection()); + SectionMap.insert(Asm->getObjFileLowering().getTextSection()); // Print out .file directives to specify files for .loc directives. These are // printed out early so that they precede any .loc directives. - if (TAI->hasDotLocAndDotFile()) { + if (MAI->hasDotLocAndDotFile()) { for (unsigned i = 1, e = getNumSourceIds()+1; i != e; ++i) { // Remember source id starts at 1. std::pair<unsigned, unsigned> Id = getSourceDirectoryAndFileIds(i); @@ -1332,7 +1706,7 @@ void DwarfDebug::BeginModule(Module *M, MachineModuleInfo *mmi) { FullPath.appendComponent(getSourceFileName(Id.second)); assert(AppendOk && "Could not append filename to directory!"); AppendOk = false; - Asm->EmitFile(i, FullPath.toString()); + Asm->EmitFile(i, FullPath.str()); Asm->EOL(); } } @@ -1347,21 +1721,21 @@ void DwarfDebug::BeginModule(Module *M, MachineModuleInfo *mmi) { /// EndModule - Emit all Dwarf sections that should come after the content. /// void DwarfDebug::EndModule() { - if (!ShouldEmitDwarfDebug()) + if (!ModuleCU) return; if (TimePassesIsEnabled) DebugTimer->startTimer(); // Standard sections final addresses. - Asm->SwitchToSection(TAI->getTextSection()); + Asm->OutStreamer.SwitchSection(Asm->getObjFileLowering().getTextSection()); EmitLabel("text_end", 0); - Asm->SwitchToSection(TAI->getDataSection()); + Asm->OutStreamer.SwitchSection(Asm->getObjFileLowering().getDataSection()); EmitLabel("data_end", 0); // End text sections. for (unsigned i = 1, N = SectionMap.size(); i <= N; ++i) { - Asm->SwitchToSection(SectionMap[i]); + Asm->OutStreamer.SwitchSection(SectionMap[i]); EmitLabel("section_end", i); } @@ -1410,6 +1784,135 @@ void DwarfDebug::EndModule() { DebugTimer->stopTimer(); } +/// CollectVariableInfo - Populate DbgScope entries with variables' info. +void DwarfDebug::CollectVariableInfo() { + if (!MMI) return; + MachineModuleInfo::VariableDbgInfoMapTy &VMap = MMI->getVariableDbgInfo(); + for (MachineModuleInfo::VariableDbgInfoMapTy::iterator VI = VMap.begin(), + VE = VMap.end(); VI != VE; ++VI) { + MetadataBase *MB = VI->first; + MDNode *Var = dyn_cast_or_null<MDNode>(MB); + DIVariable DV (Var); + if (DV.isNull()) continue; + unsigned VSlot = VI->second; + DbgScope *Scope = getDbgScope(DV.getContext().getNode(), NULL); + Scope->AddVariable(new DbgVariable(DV, VSlot, false)); + } +} + +/// SetDbgScopeBeginLabels - Update DbgScope begin labels for the scopes that +/// start with this machine instruction. +void DwarfDebug::SetDbgScopeBeginLabels(const MachineInstr *MI, unsigned Label) { + InsnToDbgScopeMapTy::iterator I = DbgScopeBeginMap.find(MI); + if (I == DbgScopeBeginMap.end()) + return; + SmallVector<DbgScope *, 2> &SD = I->second; + for (SmallVector<DbgScope *, 2>::iterator SDI = SD.begin(), SDE = SD.end(); + SDI != SDE; ++SDI) + (*SDI)->setStartLabelID(Label); +} + +/// SetDbgScopeEndLabels - Update DbgScope end labels for the scopes that +/// end with this machine instruction. +void DwarfDebug::SetDbgScopeEndLabels(const MachineInstr *MI, unsigned Label) { + InsnToDbgScopeMapTy::iterator I = DbgScopeEndMap.find(MI); + if (I == DbgScopeEndMap.end()) + return; + SmallVector<DbgScope *, 2> &SD = I->second; + for (SmallVector<DbgScope *, 2>::iterator SDI = SD.begin(), SDE = SD.end(); + SDI != SDE; ++SDI) + (*SDI)->setEndLabelID(Label); +} + +/// ExtractScopeInformation - Scan machine instructions in this function +/// and collect DbgScopes. Return true, if atleast one scope was found. +bool DwarfDebug::ExtractScopeInformation(MachineFunction *MF) { + // If scope information was extracted using .dbg intrinsics then there is not + // any need to extract these information by scanning each instruction. + if (!DbgScopeMap.empty()) + return false; + + // Scan each instruction and create scopes. + for (MachineFunction::const_iterator I = MF->begin(), E = MF->end(); + I != E; ++I) { + for (MachineBasicBlock::const_iterator II = I->begin(), IE = I->end(); + II != IE; ++II) { + const MachineInstr *MInsn = II; + DebugLoc DL = MInsn->getDebugLoc(); + if (DL.isUnknown()) + continue; + DebugLocTuple DLT = MF->getDebugLocTuple(DL); + if (!DLT.Scope) + continue; + // There is no need to create another DIE for compile unit. For all + // other scopes, create one DbgScope now. This will be translated + // into a scope DIE at the end. + DIDescriptor D(DLT.Scope); + if (!D.isCompileUnit()) { + DbgScope *Scope = getDbgScope(DLT.Scope, MInsn); + Scope->setLastInsn(MInsn); + } + } + } + + // If a scope's last instruction is not set then use its child scope's + // last instruction as this scope's last instrunction. + for (DenseMap<MDNode *, DbgScope *>::iterator DI = DbgScopeMap.begin(), + DE = DbgScopeMap.end(); DI != DE; ++DI) { + assert (DI->second->getFirstInsn() && "Invalid first instruction!"); + DI->second->FixInstructionMarkers(); + assert (DI->second->getLastInsn() && "Invalid last instruction!"); + } + + // Each scope 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. + for (DenseMap<MDNode *, DbgScope *>::iterator DI = DbgScopeMap.begin(), + DE = DbgScopeMap.end(); DI != DE; ++DI) { + DbgScope *S = DI->second; + assert (S && "DbgScope is missing!"); + const MachineInstr *MI = S->getFirstInsn(); + assert (MI && "DbgScope does not have first instruction!"); + + InsnToDbgScopeMapTy::iterator IDI = DbgScopeBeginMap.find(MI); + if (IDI != DbgScopeBeginMap.end()) + IDI->second.push_back(S); + else + DbgScopeBeginMap.insert(std::make_pair(MI, + SmallVector<DbgScope *, 2>(2, S))); + + MI = S->getLastInsn(); + assert (MI && "DbgScope does not have last instruction!"); + IDI = DbgScopeEndMap.find(MI); + if (IDI != DbgScopeEndMap.end()) + IDI->second.push_back(S); + else + DbgScopeEndMap.insert(std::make_pair(MI, + SmallVector<DbgScope *, 2>(2, S))); + } + + return !DbgScopeMap.empty(); +} + +static DISubprogram getDISubprogram(MDNode *N) { + + DIDescriptor D(N); + if (D.isNull()) + return DISubprogram(); + + if (D.isCompileUnit()) + return DISubprogram(); + + if (D.isSubprogram()) + return DISubprogram(N); + + if (D.isLexicalBlock()) + return getDISubprogram(DILexicalBlock(N).getContext().getNode()); + + llvm_unreachable("Unexpected Descriptor!"); +} + /// BeginFunction - Gather pre-function debug information. Assumes being /// emitted immediately after the function entry point. void DwarfDebug::BeginFunction(MachineFunction *MF) { @@ -1420,6 +1923,12 @@ void DwarfDebug::BeginFunction(MachineFunction *MF) { if (TimePassesIsEnabled) DebugTimer->startTimer(); +#ifdef ATTACH_DEBUG_INFO_TO_AN_INSN + if (!ExtractScopeInformation(MF)) + return; + CollectVariableInfo(); +#endif + // Begin accumulating function debug information. MMI->BeginFunction(MF); @@ -1428,14 +1937,28 @@ void DwarfDebug::BeginFunction(MachineFunction *MF) { // Emit label for the implicitly defined dbg.stoppoint at the start of the // function. +#ifdef ATTACH_DEBUG_INFO_TO_AN_INSN DebugLoc FDL = MF->getDefaultDebugLoc(); if (!FDL.isUnknown()) { DebugLocTuple DLT = MF->getDebugLocTuple(FDL); - unsigned LabelID = RecordSourceLine(DLT.Line, DLT.Col, - DICompileUnit(DLT.CompileUnit)); + unsigned LabelID = 0; + DISubprogram SP = getDISubprogram(DLT.Scope); + if (!SP.isNull()) + LabelID = RecordSourceLine(SP.getLineNumber(), 0, DLT.Scope); + else + LabelID = RecordSourceLine(DLT.Line, DLT.Col, DLT.Scope); Asm->printLabel(LabelID); + O << '\n'; } - +#else + DebugLoc FDL = MF->getDefaultDebugLoc(); + if (!FDL.isUnknown()) { + DebugLocTuple DLT = MF->getDebugLocTuple(FDL); + unsigned LabelID = RecordSourceLine(DLT.Line, DLT.Col, DLT.Scope); + Asm->printLabel(LabelID); + O << '\n'; + } +#endif if (TimePassesIsEnabled) DebugTimer->stopTimer(); } @@ -1448,13 +1971,17 @@ void DwarfDebug::EndFunction(MachineFunction *MF) { if (TimePassesIsEnabled) DebugTimer->startTimer(); +#ifdef ATTACH_DEBUG_INFO_TO_AN_INSN + if (DbgScopeMap.empty()) + return; +#endif // Define end label for subprogram. EmitLabel("func_end", SubprogramCount); // Get function line info. if (!Lines.empty()) { // Get section line info. - unsigned ID = SectionMap.insert(Asm->CurrentSection_); + unsigned ID = SectionMap.insert(Asm->getCurrentSection()); if (SectionSourceLines.size() < ID) SectionSourceLines.resize(ID); std::vector<SrcLineInfo> &SectionLineInfos = SectionSourceLines[ID-1]; // Append the function info to section info. @@ -1489,9 +2016,10 @@ void DwarfDebug::EndFunction(MachineFunction *MF) { if (FunctionDbgScope) { delete FunctionDbgScope; DbgScopeMap.clear(); + DbgScopeBeginMap.clear(); + DbgScopeEndMap.clear(); DbgAbstractScopeMap.clear(); DbgConcreteScopeMap.clear(); - InlinedVariableScopes.clear(); FunctionDbgScope = NULL; LexicalScopeStack.clear(); AbstractInstanceRootList.clear(); @@ -1507,32 +2035,34 @@ void DwarfDebug::EndFunction(MachineFunction *MF) { /// RecordSourceLine - Records location information and associates it with a /// label. Returns a unique label ID used to generate a label and provide /// correspondence to the source line list. -unsigned DwarfDebug::RecordSourceLine(Value *V, unsigned Line, unsigned Col) { - if (TimePassesIsEnabled) - DebugTimer->startTimer(); - - CompileUnit *Unit = CompileUnitMap[V]; - assert(Unit && "Unable to find CompileUnit"); - unsigned ID = MMI->NextLabelID(); - Lines.push_back(SrcLineInfo(Line, Col, Unit->getID(), ID)); +unsigned DwarfDebug::RecordSourceLine(unsigned Line, unsigned Col, + MDNode *S) { + if (!MMI) + return 0; if (TimePassesIsEnabled) - DebugTimer->stopTimer(); - - return ID; -} - -/// RecordSourceLine - Records location information and associates it with a -/// label. Returns a unique label ID used to generate a label and provide -/// correspondence to the source line list. -unsigned DwarfDebug::RecordSourceLine(unsigned Line, unsigned Col, - DICompileUnit CU) { - if (TimePassesIsEnabled) DebugTimer->startTimer(); - std::string Dir, Fn; - unsigned Src = GetOrCreateSourceID(CU.getDirectory(Dir), - CU.getFilename(Fn)); + const char *Dir = NULL; + const char *Fn = NULL; + + DIDescriptor Scope(S); + if (Scope.isCompileUnit()) { + DICompileUnit CU(S); + Dir = CU.getDirectory(); + Fn = CU.getFilename(); + } else if (Scope.isSubprogram()) { + DISubprogram SP(S); + Dir = SP.getDirectory(); + Fn = SP.getFilename(); + } else if (Scope.isLexicalBlock()) { + DILexicalBlock DB(S); + Dir = DB.getDirectory(); + Fn = DB.getFilename(); + } else + assert (0 && "Unexpected scope info"); + + unsigned Src = GetOrCreateSourceID(Dir, Fn); unsigned ID = MMI->NextLabelID(); Lines.push_back(SrcLineInfo(Line, Col, Src, ID)); @@ -1552,7 +2082,7 @@ unsigned DwarfDebug::getOrCreateSourceID(const std::string &DirName, if (TimePassesIsEnabled) DebugTimer->startTimer(); - unsigned SrcId = GetOrCreateSourceID(DirName, FileName); + unsigned SrcId = GetOrCreateSourceID(DirName.c_str(), FileName.c_str()); if (TimePassesIsEnabled) DebugTimer->stopTimer(); @@ -1561,11 +2091,11 @@ unsigned DwarfDebug::getOrCreateSourceID(const std::string &DirName, } /// RecordRegionStart - Indicate the start of a region. -unsigned DwarfDebug::RecordRegionStart(GlobalVariable *V) { +unsigned DwarfDebug::RecordRegionStart(MDNode *N) { if (TimePassesIsEnabled) DebugTimer->startTimer(); - DbgScope *Scope = getOrCreateScope(V); + DbgScope *Scope = getOrCreateScope(N); unsigned ID = MMI->NextLabelID(); if (!Scope->getStartLabelID()) Scope->setStartLabelID(ID); LexicalScopeStack.push_back(Scope); @@ -1577,11 +2107,11 @@ unsigned DwarfDebug::RecordRegionStart(GlobalVariable *V) { } /// RecordRegionEnd - Indicate the end of a region. -unsigned DwarfDebug::RecordRegionEnd(GlobalVariable *V) { +unsigned DwarfDebug::RecordRegionEnd(MDNode *N) { if (TimePassesIsEnabled) DebugTimer->startTimer(); - DbgScope *Scope = getOrCreateScope(V); + DbgScope *Scope = getOrCreateScope(N); unsigned ID = MMI->NextLabelID(); Scope->setEndLabelID(ID); // FIXME : region.end() may not be in the last basic block. @@ -1598,62 +2128,36 @@ unsigned DwarfDebug::RecordRegionEnd(GlobalVariable *V) { } /// RecordVariable - Indicate the declaration of a local variable. -void DwarfDebug::RecordVariable(GlobalVariable *GV, unsigned FrameIndex, - const MachineInstr *MI) { +void DwarfDebug::RecordVariable(MDNode *N, unsigned FrameIndex) { if (TimePassesIsEnabled) DebugTimer->startTimer(); - DIDescriptor Desc(GV); + DIDescriptor Desc(N); DbgScope *Scope = NULL; bool InlinedFnVar = false; - if (Desc.getTag() == dwarf::DW_TAG_variable) { - // GV is a global variable. - DIGlobalVariable DG(GV); - Scope = getOrCreateScope(DG.getContext().getGV()); - } else { - DenseMap<const MachineInstr *, DbgScope *>::iterator - SI = InlinedVariableScopes.find(MI); - - if (SI != InlinedVariableScopes.end()) { - // or GV is an inlined local variable. - Scope = SI->second; - } else { - DIVariable DV(GV); - GlobalVariable *V = DV.getContext().getGV(); - - // FIXME: The code that checks for the inlined local variable is a hack! - DenseMap<const GlobalVariable *, DbgScope *>::iterator - AI = AbstractInstanceRootMap.find(V); - - if (AI != AbstractInstanceRootMap.end()) { - // This method is called each time a DECLARE node is encountered. For an - // inlined function, this could be many, many times. We don't want to - // re-add variables to that DIE for each time. We just want to add them - // once. Check to make sure that we haven't added them already. - DenseMap<const GlobalVariable *, - SmallSet<const GlobalVariable *, 32> >::iterator - IP = InlinedParamMap.find(V); - - if (IP != InlinedParamMap.end() && IP->second.count(GV) > 0) { - if (TimePassesIsEnabled) - DebugTimer->stopTimer(); - return; - } - - // or GV is an inlined local variable. - Scope = AI->second; - InlinedParamMap[V].insert(GV); - InlinedFnVar = true; - } else { - // or GV is a local variable. - Scope = getOrCreateScope(V); + if (Desc.getTag() == dwarf::DW_TAG_variable) + Scope = getOrCreateScope(DIGlobalVariable(N).getContext().getNode()); + else { + bool InlinedVar = false; + MDNode *Context = DIVariable(N).getContext().getNode(); + DISubprogram SP(Context); + if (!SP.isNull()) { + // SP is inserted into DbgAbstractScopeMap when inlined function + // start was recorded by RecordInlineFnStart. + DenseMap<MDNode *, DbgScope *>::iterator + I = DbgAbstractScopeMap.find(SP.getNode()); + if (I != DbgAbstractScopeMap.end()) { + InlinedVar = true; + Scope = I->second; } } + if (!InlinedVar) + Scope = getOrCreateScope(Context); } assert(Scope && "Unable to find the variable's scope"); - DbgVariable *DV = new DbgVariable(DIVariable(GV), FrameIndex, InlinedFnVar); + DbgVariable *DV = new DbgVariable(DIVariable(N), FrameIndex, InlinedFnVar); Scope->AddVariable(DV); if (TimePassesIsEnabled) @@ -1665,23 +2169,23 @@ unsigned DwarfDebug::RecordInlinedFnStart(DISubprogram &SP, DICompileUnit CU, unsigned Line, unsigned Col) { unsigned LabelID = MMI->NextLabelID(); - if (!TAI->doesDwarfUsesInlineInfoSection()) + if (!MAI->doesDwarfUsesInlineInfoSection()) return LabelID; if (TimePassesIsEnabled) DebugTimer->startTimer(); - GlobalVariable *GV = SP.getGV(); - DenseMap<const GlobalVariable *, DbgScope *>::iterator - II = AbstractInstanceRootMap.find(GV); + MDNode *Node = SP.getNode(); + DenseMap<const MDNode *, DbgScope *>::iterator + II = AbstractInstanceRootMap.find(Node); if (II == AbstractInstanceRootMap.end()) { // Create an abstract instance entry for this inlined function if it doesn't // already exist. - DbgScope *Scope = new DbgScope(NULL, DIDescriptor(GV)); + DbgScope *Scope = new DbgScope(NULL, DIDescriptor(Node)); // Get the compile unit context. - DIE *SPDie = ModuleCU->getDieMapSlotFor(GV); + DIE *SPDie = ModuleCU->getDieMapSlotFor(Node); if (!SPDie) SPDie = CreateSubprogramDIE(ModuleCU, SP, false, true); @@ -1693,18 +2197,18 @@ unsigned DwarfDebug::RecordInlinedFnStart(DISubprogram &SP, DICompileUnit CU, AddUInt(SPDie, dwarf::DW_AT_inline, 0, dwarf::DW_INL_declared_not_inlined); // Keep track of the abstract scope for this function. - DbgAbstractScopeMap[GV] = Scope; + DbgAbstractScopeMap[Node] = Scope; - AbstractInstanceRootMap[GV] = Scope; + AbstractInstanceRootMap[Node] = Scope; AbstractInstanceRootList.push_back(Scope); } // Create a concrete inlined instance for this inlined function. - DbgConcreteScope *ConcreteScope = new DbgConcreteScope(DIDescriptor(GV)); + DbgConcreteScope *ConcreteScope = new DbgConcreteScope(DIDescriptor(Node)); DIE *ScopeDie = new DIE(dwarf::DW_TAG_inlined_subroutine); ScopeDie->setAbstractCompileUnit(ModuleCU); - DIE *Origin = ModuleCU->getDieMapSlotFor(GV); + DIE *Origin = ModuleCU->getDieMapSlotFor(Node); AddDIEEntry(ScopeDie, dwarf::DW_AT_abstract_origin, dwarf::DW_FORM_ref4, Origin); AddUInt(ScopeDie, dwarf::DW_AT_call_file, 0, ModuleCU->getID()); @@ -1718,20 +2222,20 @@ unsigned DwarfDebug::RecordInlinedFnStart(DISubprogram &SP, DICompileUnit CU, LexicalScopeStack.back()->AddConcreteInst(ConcreteScope); // Keep track of the concrete scope that's inlined into this function. - DenseMap<GlobalVariable *, SmallVector<DbgScope *, 8> >::iterator - SI = DbgConcreteScopeMap.find(GV); + DenseMap<MDNode *, SmallVector<DbgScope *, 8> >::iterator + SI = DbgConcreteScopeMap.find(Node); if (SI == DbgConcreteScopeMap.end()) - DbgConcreteScopeMap[GV].push_back(ConcreteScope); + DbgConcreteScopeMap[Node].push_back(ConcreteScope); else SI->second.push_back(ConcreteScope); // Track the start label for this inlined function. - DenseMap<GlobalVariable *, SmallVector<unsigned, 4> >::iterator - I = InlineInfo.find(GV); + DenseMap<MDNode *, SmallVector<unsigned, 4> >::iterator + I = InlineInfo.find(Node); if (I == InlineInfo.end()) - InlineInfo[GV].push_back(LabelID); + InlineInfo[Node].push_back(LabelID); else I->second.push_back(LabelID); @@ -1743,15 +2247,15 @@ unsigned DwarfDebug::RecordInlinedFnStart(DISubprogram &SP, DICompileUnit CU, /// RecordInlinedFnEnd - Indicate the end of inlined subroutine. unsigned DwarfDebug::RecordInlinedFnEnd(DISubprogram &SP) { - if (!TAI->doesDwarfUsesInlineInfoSection()) + if (!MAI->doesDwarfUsesInlineInfoSection()) return 0; if (TimePassesIsEnabled) DebugTimer->startTimer(); - GlobalVariable *GV = SP.getGV(); - DenseMap<GlobalVariable *, SmallVector<DbgScope *, 8> >::iterator - I = DbgConcreteScopeMap.find(GV); + MDNode *Node = SP.getNode(); + DenseMap<MDNode *, SmallVector<DbgScope *, 8> >::iterator + I = DbgConcreteScopeMap.find(Node); if (I == DbgConcreteScopeMap.end()) { // FIXME: Can this situation actually happen? And if so, should it? @@ -1781,33 +2285,6 @@ unsigned DwarfDebug::RecordInlinedFnEnd(DISubprogram &SP) { return ID; } -/// RecordVariableScope - Record scope for the variable declared by -/// DeclareMI. DeclareMI must describe TargetInstrInfo::DECLARE. Record scopes -/// for only inlined subroutine variables. Other variables's scopes are -/// determined during RecordVariable(). -void DwarfDebug::RecordVariableScope(DIVariable &DV, - const MachineInstr *DeclareMI) { - if (TimePassesIsEnabled) - DebugTimer->startTimer(); - - DISubprogram SP(DV.getContext().getGV()); - - if (SP.isNull()) { - if (TimePassesIsEnabled) - DebugTimer->stopTimer(); - - return; - } - - DenseMap<GlobalVariable *, DbgScope *>::iterator - I = DbgAbstractScopeMap.find(SP.getGV()); - if (I != DbgAbstractScopeMap.end()) - InlinedVariableScopes[DeclareMI] = I->second; - - if (TimePassesIsEnabled) - DebugTimer->stopTimer(); -} - //===----------------------------------------------------------------------===// // Emit Methods //===----------------------------------------------------------------------===// @@ -1832,7 +2309,7 @@ unsigned DwarfDebug::SizeAndOffsetDie(DIE *Die, unsigned Offset, bool Last) { Die->setOffset(Offset); // Start the size with the size of abbreviation code. - Offset += TargetAsmInfo::getULEB128Size(AbbrevNumber); + Offset += MCAsmInfo::getULEB128Size(AbbrevNumber); const SmallVector<DIEValue*, 32> &Values = Die->getValues(); const SmallVector<DIEAbbrevData, 8> &AbbrevData = Abbrev->getData(); @@ -1879,38 +2356,40 @@ void DwarfDebug::EmitInitial() { if (didInitial) return; didInitial = true; + const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering(); + // Dwarf sections base addresses. - if (TAI->doesDwarfRequireFrameSection()) { - Asm->SwitchToDataSection(TAI->getDwarfFrameSection()); + if (MAI->doesDwarfRequireFrameSection()) { + Asm->OutStreamer.SwitchSection(TLOF.getDwarfFrameSection()); EmitLabel("section_debug_frame", 0); } - Asm->SwitchToDataSection(TAI->getDwarfInfoSection()); + Asm->OutStreamer.SwitchSection(TLOF.getDwarfInfoSection()); EmitLabel("section_info", 0); - Asm->SwitchToDataSection(TAI->getDwarfAbbrevSection()); + Asm->OutStreamer.SwitchSection(TLOF.getDwarfAbbrevSection()); EmitLabel("section_abbrev", 0); - Asm->SwitchToDataSection(TAI->getDwarfARangesSection()); + Asm->OutStreamer.SwitchSection(TLOF.getDwarfARangesSection()); EmitLabel("section_aranges", 0); - if (const char *LineInfoDirective = TAI->getDwarfMacroInfoSection()) { - Asm->SwitchToDataSection(LineInfoDirective); + if (const MCSection *LineInfoDirective = TLOF.getDwarfMacroInfoSection()) { + Asm->OutStreamer.SwitchSection(LineInfoDirective); EmitLabel("section_macinfo", 0); } - Asm->SwitchToDataSection(TAI->getDwarfLineSection()); + Asm->OutStreamer.SwitchSection(TLOF.getDwarfLineSection()); EmitLabel("section_line", 0); - Asm->SwitchToDataSection(TAI->getDwarfLocSection()); + Asm->OutStreamer.SwitchSection(TLOF.getDwarfLocSection()); EmitLabel("section_loc", 0); - Asm->SwitchToDataSection(TAI->getDwarfPubNamesSection()); + Asm->OutStreamer.SwitchSection(TLOF.getDwarfPubNamesSection()); EmitLabel("section_pubnames", 0); - Asm->SwitchToDataSection(TAI->getDwarfStrSection()); + Asm->OutStreamer.SwitchSection(TLOF.getDwarfStrSection()); EmitLabel("section_str", 0); - Asm->SwitchToDataSection(TAI->getDwarfRangesSection()); + Asm->OutStreamer.SwitchSection(TLOF.getDwarfRangesSection()); EmitLabel("section_ranges", 0); - Asm->SwitchToSection(TAI->getTextSection()); + Asm->OutStreamer.SwitchSection(TLOF.getTextSection()); EmitLabel("text_begin", 0); - Asm->SwitchToSection(TAI->getDataSection()); + Asm->OutStreamer.SwitchSection(TLOF.getDataSection()); EmitLabel("data_begin", 0); } @@ -2012,7 +2491,8 @@ void DwarfDebug::EmitDebugInfoPerCU(CompileUnit *Unit) { void DwarfDebug::EmitDebugInfo() { // Start debug info section. - Asm->SwitchToDataSection(TAI->getDwarfInfoSection()); + Asm->OutStreamer.SwitchSection( + Asm->getObjFileLowering().getDwarfInfoSection()); EmitDebugInfoPerCU(ModuleCU); } @@ -2023,7 +2503,8 @@ void DwarfDebug::EmitAbbreviations() const { // Check to see if it is worth the effort. if (!Abbreviations.empty()) { // Start the debug abbrev section. - Asm->SwitchToDataSection(TAI->getDwarfAbbrevSection()); + Asm->OutStreamer.SwitchSection( + Asm->getObjFileLowering().getDwarfAbbrevSection()); EmitLabel("abbrev_begin", 0); @@ -2071,7 +2552,7 @@ void DwarfDebug::EmitEndOfLineMatrix(unsigned SectionEnd) { void DwarfDebug::EmitDebugLines() { // If the target is using .loc/.file, the assembler will be emitting the // .debug_line table automatically. - if (TAI->hasDotLocAndDotFile()) + if (MAI->hasDotLocAndDotFile()) return; // Minimum line delta, thus ranging from -10..(255-10). @@ -2080,7 +2561,8 @@ void DwarfDebug::EmitDebugLines() { const int MaxLineDelta = 255 + MinLineDelta; // Start the dwarf line section. - Asm->SwitchToDataSection(TAI->getDwarfLineSection()); + Asm->OutStreamer.SwitchSection( + Asm->getObjFileLowering().getDwarfLineSection()); // Construct the section header. EmitDifference("line_end", 0, "line_begin", 0, true); @@ -2147,13 +2629,12 @@ void DwarfDebug::EmitDebugLines() { // Isolate current sections line info. const std::vector<SrcLineInfo> &LineInfos = SectionSourceLines[j]; - if (Asm->isVerbose()) { - const Section* S = SectionMap[j + 1]; - O << '\t' << TAI->getCommentString() << " Section" + /*if (Asm->isVerbose()) { + const MCSection *S = SectionMap[j + 1]; + O << '\t' << MAI->getCommentString() << " Section" << S->getName() << '\n'; - } else { - Asm->EOL(); - } + }*/ + Asm->EOL(); // Dwarf assumes we start with first line of first source file. unsigned Source = 1; @@ -2165,12 +2646,14 @@ void DwarfDebug::EmitDebugLines() { unsigned LabelID = MMI->MappedLabel(LineInfo.getLabelID()); if (!LabelID) continue; + if (LineInfo.getLine() == 0) continue; + if (!Asm->isVerbose()) Asm->EOL(); else { std::pair<unsigned, unsigned> SourceID = getSourceDirectoryAndFileIds(LineInfo.getSourceID()); - O << '\t' << TAI->getCommentString() << ' ' + O << '\t' << MAI->getCommentString() << ' ' << getSourceDirectoryName(SourceID.first) << ' ' << getSourceFileName(SourceID.second) <<" :" << utostr_32(LineInfo.getLine()) << '\n'; @@ -2231,7 +2714,7 @@ void DwarfDebug::EmitDebugLines() { /// EmitCommonDebugFrame - Emit common frame info into a debug frame section. /// void DwarfDebug::EmitCommonDebugFrame() { - if (!TAI->doesDwarfRequireFrameSection()) + if (!MAI->doesDwarfRequireFrameSection()) return; int stackGrowth = @@ -2240,7 +2723,8 @@ void DwarfDebug::EmitCommonDebugFrame() { TD->getPointerSize() : -TD->getPointerSize(); // Start the dwarf frame section. - Asm->SwitchToDataSection(TAI->getDwarfFrameSection()); + Asm->OutStreamer.SwitchSection( + Asm->getObjFileLowering().getDwarfFrameSection()); EmitLabel("debug_frame_common", 0); EmitDifference("debug_frame_common_end", 0, @@ -2276,11 +2760,12 @@ void DwarfDebug::EmitCommonDebugFrame() { /// section. void DwarfDebug::EmitFunctionDebugFrame(const FunctionDebugFrameInfo&DebugFrameInfo){ - if (!TAI->doesDwarfRequireFrameSection()) + if (!MAI->doesDwarfRequireFrameSection()) return; // Start the dwarf frame section. - Asm->SwitchToDataSection(TAI->getDwarfFrameSection()); + Asm->OutStreamer.SwitchSection( + Asm->getObjFileLowering().getDwarfFrameSection()); EmitDifference("debug_frame_end", DebugFrameInfo.Number, "debug_frame_begin", DebugFrameInfo.Number, true); @@ -2344,7 +2829,8 @@ void DwarfDebug::EmitDebugPubNamesPerCU(CompileUnit *Unit) { /// void DwarfDebug::EmitDebugPubNames() { // Start the dwarf pubnames section. - Asm->SwitchToDataSection(TAI->getDwarfPubNamesSection()); + Asm->OutStreamer.SwitchSection( + Asm->getObjFileLowering().getDwarfPubNamesSection()); EmitDebugPubNamesPerCU(ModuleCU); } @@ -2355,7 +2841,8 @@ void DwarfDebug::EmitDebugStr() { // Check to see if it is worth the effort. if (!StringPool.empty()) { // Start the dwarf str section. - Asm->SwitchToDataSection(TAI->getDwarfStrSection()); + Asm->OutStreamer.SwitchSection( + Asm->getObjFileLowering().getDwarfStrSection()); // For each of strings in the string pool. for (unsigned StringID = 1, N = StringPool.size(); @@ -2376,7 +2863,8 @@ void DwarfDebug::EmitDebugStr() { /// void DwarfDebug::EmitDebugLoc() { // Start the dwarf loc section. - Asm->SwitchToDataSection(TAI->getDwarfLocSection()); + Asm->OutStreamer.SwitchSection( + Asm->getObjFileLowering().getDwarfLocSection()); Asm->EOL(); } @@ -2384,7 +2872,8 @@ void DwarfDebug::EmitDebugLoc() { /// void DwarfDebug::EmitDebugARanges() { // Start the dwarf aranges section. - Asm->SwitchToDataSection(TAI->getDwarfARangesSection()); + Asm->OutStreamer.SwitchSection( + Asm->getObjFileLowering().getDwarfARangesSection()); // FIXME - Mock up #if 0 @@ -2420,16 +2909,18 @@ void DwarfDebug::EmitDebugARanges() { /// void DwarfDebug::EmitDebugRanges() { // Start the dwarf ranges section. - Asm->SwitchToDataSection(TAI->getDwarfRangesSection()); + Asm->OutStreamer.SwitchSection( + Asm->getObjFileLowering().getDwarfRangesSection()); Asm->EOL(); } /// EmitDebugMacInfo - Emit visible names into a debug macinfo section. /// void DwarfDebug::EmitDebugMacInfo() { - if (const char *LineInfoDirective = TAI->getDwarfMacroInfoSection()) { + if (const MCSection *LineInfo = + Asm->getObjFileLowering().getDwarfMacroInfoSection()) { // Start the dwarf macinfo section. - Asm->SwitchToDataSection(LineInfoDirective); + Asm->OutStreamer.SwitchSection(LineInfo); Asm->EOL(); } } @@ -2453,13 +2944,14 @@ void DwarfDebug::EmitDebugMacInfo() { /// __debug_info section, and the low_pc is the starting address for the /// inlining instance. void DwarfDebug::EmitDebugInlineInfo() { - if (!TAI->doesDwarfUsesInlineInfoSection()) + if (!MAI->doesDwarfUsesInlineInfoSection()) return; if (!ModuleCU) return; - Asm->SwitchToDataSection(TAI->getDwarfDebugInlineSection()); + Asm->OutStreamer.SwitchSection( + Asm->getObjFileLowering().getDwarfDebugInlineSection()); Asm->EOL(); EmitDifference("debug_inlined_end", 1, "debug_inlined_begin", 1, true); @@ -2470,18 +2962,25 @@ void DwarfDebug::EmitDebugInlineInfo() { Asm->EmitInt16(dwarf::DWARF_VERSION); Asm->EOL("Dwarf Version"); Asm->EmitInt8(TD->getPointerSize()); Asm->EOL("Address Size (in bytes)"); - for (DenseMap<GlobalVariable *, SmallVector<unsigned, 4> >::iterator + for (DenseMap<MDNode *, SmallVector<unsigned, 4> >::iterator I = InlineInfo.begin(), E = InlineInfo.end(); I != E; ++I) { - GlobalVariable *GV = I->first; + MDNode *Node = I->first; SmallVector<unsigned, 4> &Labels = I->second; - DISubprogram SP(GV); - std::string Name; - std::string LName; - - SP.getLinkageName(LName); - SP.getName(Name); + DISubprogram SP(Node); + const char *LName = SP.getLinkageName(); + const char *Name = SP.getName(); - Asm->EmitString(LName.empty() ? Name : LName); + if (!LName) + Asm->EmitString(Name); + else { + // Skip special LLVM prefix that is used to inform the asm printer to not + // emit usual symbol prefix before the symbol name. This happens for + // Objective-C symbol names and symbol whose name is replaced using GCC's + // __asm__ attribute. + if (LName[0] == 1) + LName = &LName[1]; + Asm->EmitString(LName); + } Asm->EOL("MIPS linkage name"); Asm->EmitString(Name); Asm->EOL("Function name"); @@ -2490,13 +2989,13 @@ void DwarfDebug::EmitDebugInlineInfo() { for (SmallVector<unsigned, 4>::iterator LI = Labels.begin(), LE = Labels.end(); LI != LE; ++LI) { - DIE *SP = ModuleCU->getDieMapSlotFor(GV); + DIE *SP = ModuleCU->getDieMapSlotFor(Node); Asm->EmitInt32(SP->getOffset()); Asm->EOL("DIE offset"); if (TD->getPointerSize() == sizeof(int32_t)) - O << TAI->getData32bitsDirective(); + O << MAI->getData32bitsDirective(); else - O << TAI->getData64bitsDirective(); + O << MAI->getData64bitsDirective(); PrintLabelName("label", *LI); Asm->EOL("low_pc"); } diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.h b/lib/CodeGen/AsmPrinter/DwarfDebug.h index 101dc70..bd377c5 100644 --- a/lib/CodeGen/AsmPrinter/DwarfDebug.h +++ b/lib/CodeGen/AsmPrinter/DwarfDebug.h @@ -35,7 +35,7 @@ class DbgScope; class DbgConcreteScope; class MachineFrameInfo; class MachineModuleInfo; -class TargetAsmInfo; +class MCAsmInfo; class Timer; //===----------------------------------------------------------------------===// @@ -120,7 +120,7 @@ class VISIBILITY_HIDDEN DwarfDebug : public Dwarf { /// SectionMap - Provides a unique id per text section. /// - UniqueVector<const Section*> SectionMap; + UniqueVector<const MCSection*> SectionMap; /// SectionSourceLines - Tracks line numbers per text section. /// @@ -139,34 +139,38 @@ class VISIBILITY_HIDDEN DwarfDebug : public Dwarf { DbgScope *FunctionDbgScope; /// DbgScopeMap - Tracks the scopes in the current function. - DenseMap<GlobalVariable *, DbgScope *> DbgScopeMap; + DenseMap<MDNode *, DbgScope *> DbgScopeMap; + + /// ScopedGVs - Tracks global variables that are not at file scope. + /// For example void f() { static int b = 42; } + SmallVector<WeakVH, 4> ScopedGVs; + + typedef DenseMap<const MachineInstr *, SmallVector<DbgScope *, 2> > + InsnToDbgScopeMapTy; + + /// DbgScopeBeginMap - Maps instruction with a list DbgScopes it starts. + InsnToDbgScopeMapTy DbgScopeBeginMap; + + /// DbgScopeEndMap - Maps instruction with a list DbgScopes it ends. + InsnToDbgScopeMapTy DbgScopeEndMap; /// DbgAbstractScopeMap - Tracks abstract instance scopes in the current /// function. - DenseMap<GlobalVariable *, DbgScope *> DbgAbstractScopeMap; + DenseMap<MDNode *, DbgScope *> DbgAbstractScopeMap; /// DbgConcreteScopeMap - Tracks concrete instance scopes in the current /// function. - DenseMap<GlobalVariable *, + DenseMap<MDNode *, SmallVector<DbgScope *, 8> > DbgConcreteScopeMap; /// InlineInfo - Keep track of inlined functions and their location. This /// information is used to populate debug_inlined section. - DenseMap<GlobalVariable *, SmallVector<unsigned, 4> > InlineInfo; - - /// InlinedVariableScopes - Scopes information for the inlined subroutine - /// variables. - DenseMap<const MachineInstr *, DbgScope *> InlinedVariableScopes; + DenseMap<MDNode *, SmallVector<unsigned, 4> > InlineInfo; /// AbstractInstanceRootMap - Map of abstract instance roots of inlined /// functions. These are subroutine entries that contain a DW_AT_inline /// attribute. - DenseMap<const GlobalVariable *, DbgScope *> AbstractInstanceRootMap; - - /// InlinedParamMap - A map keeping track of which parameters are assigned to - /// which abstract instance. - DenseMap<const GlobalVariable *, - SmallSet<const GlobalVariable *, 32> > InlinedParamMap; + DenseMap<const MDNode *, DbgScope *> AbstractInstanceRootMap; /// AbstractInstanceRootList - List of abstract instance roots of inlined /// functions. These are subroutine entries that contain a DW_AT_inline @@ -284,11 +288,8 @@ class VISIBILITY_HIDDEN DwarfDebug : public Dwarf { /// AddSourceLine - Add location information to specified debug information /// entry. void AddSourceLine(DIE *Die, const DIVariable *V); - - /// AddSourceLine - Add location information to specified debug information - /// entry. void AddSourceLine(DIE *Die, const DIGlobal *G); - + void AddSourceLine(DIE *Die, const DISubprogram *SP); void AddSourceLine(DIE *Die, const DIType *Ty); /// AddAddress - Add an address attribute to a die based on the location @@ -296,6 +297,24 @@ class VISIBILITY_HIDDEN DwarfDebug : public Dwarf { void AddAddress(DIE *Die, unsigned Attribute, const MachineLocation &Location); + /// AddComplexAddress - Start with the address based on the location provided, + /// and generate the DWARF information necessary to find the actual variable + /// (navigating the extra location information encoded in the type) based on + /// the starting location. Add the DWARF information to the die. + /// + void AddComplexAddress(DbgVariable *&DV, DIE *Die, unsigned Attribute, + const MachineLocation &Location); + + // FIXME: Should be reformulated in terms of AddComplexAddress. + /// AddBlockByrefAddress - Start with the address based on the location + /// provided, and generate the DWARF information necessary to find the + /// actual Block variable (navigating the Block struct) based on the + /// starting location. Add the DWARF information to the die. Obsolete, + /// please use AddComplexAddress instead. + /// + void AddBlockByrefAddress(DbgVariable *&DV, DIE *Die, unsigned Attribute, + const MachineLocation &Location); + /// AddType - Add a new type attribute to the specified entity. void AddType(CompileUnit *DW_Unit, DIE *Entity, DIType Ty); @@ -342,9 +361,10 @@ class VISIBILITY_HIDDEN DwarfDebug : public Dwarf { /// DIE *CreateDbgScopeVariable(DbgVariable *DV, CompileUnit *Unit); - /// getOrCreateScope - Returns the scope associated with the given descriptor. + /// getDbgScope - Returns the scope associated with the given descriptor. /// - DbgScope *getOrCreateScope(GlobalVariable *V); + DbgScope *getOrCreateScope(MDNode *N); + DbgScope *getDbgScope(MDNode *N, const MachineInstr *MI); /// ConstructDbgScope - Construct the components of a scope. /// @@ -454,20 +474,26 @@ class VISIBILITY_HIDDEN DwarfDebug : public Dwarf { /// 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 GetOrCreateSourceID(const std::string &DirName, - const std::string &FileName); + unsigned GetOrCreateSourceID(const char *DirName, + const char *FileName); - void ConstructCompileUnit(GlobalVariable *GV); + void ConstructCompileUnit(MDNode *N); - void ConstructGlobalVariableDIE(GlobalVariable *GV); + void ConstructGlobalVariableDIE(MDNode *N); - void ConstructSubprogram(GlobalVariable *GV); + void ConstructSubprogram(MDNode *N); + + // FIXME: This should go away in favor of complex addresses. + /// Find the type the programmer originally declared the variable to be + /// and return that type. Obsolete, use GetComplexAddrType instead. + /// + DIType GetBlockByrefType(DIType Ty, std::string Name); public: //===--------------------------------------------------------------------===// // Main entry points. // - DwarfDebug(raw_ostream &OS, AsmPrinter *A, const TargetAsmInfo *T); + DwarfDebug(raw_ostream &OS, AsmPrinter *A, const MCAsmInfo *T); virtual ~DwarfDebug(); /// ShouldEmitDwarfDebug - Returns true if Dwarf debugging declarations should @@ -493,12 +519,7 @@ public: /// RecordSourceLine - Records location information and associates it with a /// label. Returns a unique label ID used to generate a label and provide /// correspondence to the source line list. - unsigned RecordSourceLine(Value *V, unsigned Line, unsigned Col); - - /// RecordSourceLine - Records location information and associates it with a - /// label. Returns a unique label ID used to generate a label and provide - /// correspondence to the source line list. - unsigned RecordSourceLine(unsigned Line, unsigned Col, DICompileUnit CU); + unsigned RecordSourceLine(unsigned Line, unsigned Col, MDNode *Scope); /// getRecordSourceLineCount - Return the number of source lines in the debug /// info. @@ -515,14 +536,13 @@ public: const std::string &FileName); /// RecordRegionStart - Indicate the start of a region. - unsigned RecordRegionStart(GlobalVariable *V); + unsigned RecordRegionStart(MDNode *N); /// RecordRegionEnd - Indicate the end of a region. - unsigned RecordRegionEnd(GlobalVariable *V); + unsigned RecordRegionEnd(MDNode *N); /// RecordVariable - Indicate the declaration of a local variable. - void RecordVariable(GlobalVariable *GV, unsigned FrameIndex, - const MachineInstr *MI); + void RecordVariable(MDNode *N, unsigned FrameIndex); //// RecordInlinedFnStart - Indicate the start of inlined subroutine. unsigned RecordInlinedFnStart(DISubprogram &SP, DICompileUnit CU, @@ -531,11 +551,20 @@ public: /// RecordInlinedFnEnd - Indicate the end of inlined subroutine. unsigned RecordInlinedFnEnd(DISubprogram &SP); - /// RecordVariableScope - Record scope for the variable declared by - /// DeclareMI. DeclareMI must describe TargetInstrInfo::DECLARE. Record scopes - /// for only inlined subroutine variables. Other variables's scopes are - /// determined during RecordVariable(). - void RecordVariableScope(DIVariable &DV, const MachineInstr *DeclareMI); + /// ExtractScopeInformation - Scan machine instructions in this function + /// and collect DbgScopes. Return true, if atleast one scope was found. + bool ExtractScopeInformation(MachineFunction *MF); + + /// CollectVariableInfo - Populate DbgScope entries with variables' info. + void CollectVariableInfo(); + + /// SetDbgScopeBeginLabels - Update DbgScope begin labels for the scopes that + /// start with this machine instruction. + void SetDbgScopeBeginLabels(const MachineInstr *MI, unsigned Label); + + /// SetDbgScopeEndLabels - Update DbgScope end labels for the scopes that + /// end with this machine instruction. + void SetDbgScopeEndLabels(const MachineInstr *MI, unsigned Label); }; } // End of namespace llvm diff --git a/lib/CodeGen/AsmPrinter/DwarfException.cpp b/lib/CodeGen/AsmPrinter/DwarfException.cpp index 37466ab..626523b 100644 --- a/lib/CodeGen/AsmPrinter/DwarfException.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfException.cpp @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// // -// This file contains support for writing dwarf exception info into asm files. +// This file contains support for writing DWARF exception info into asm files. // //===----------------------------------------------------------------------===// @@ -15,30 +15,38 @@ #include "llvm/Module.h" #include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineLocation.h" -#include "llvm/Support/Dwarf.h" -#include "llvm/Support/Timer.h" -#include "llvm/Support/raw_ostream.h" -#include "llvm/Target/TargetAsmInfo.h" -#include "llvm/Target/TargetRegisterInfo.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/Target/TargetData.h" #include "llvm/Target/TargetFrameInfo.h" +#include "llvm/Target/TargetLoweringObjectFile.h" #include "llvm/Target/TargetOptions.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Support/Dwarf.h" +#include "llvm/Support/Mangler.h" +#include "llvm/Support/Timer.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringExtras.h" using namespace llvm; static TimerGroup &getDwarfTimerGroup() { - static TimerGroup DwarfTimerGroup("Dwarf Exception"); + static TimerGroup DwarfTimerGroup("DWARF Exception"); return DwarfTimerGroup; } DwarfException::DwarfException(raw_ostream &OS, AsmPrinter *A, - const TargetAsmInfo *T) + const MCAsmInfo *T) : Dwarf(OS, A, T, "eh"), shouldEmitTable(false), shouldEmitMoves(false), shouldEmitTableModule(false), shouldEmitMovesModule(false), ExceptionTimer(0) { - if (TimePassesIsEnabled) - ExceptionTimer = new Timer("Dwarf Exception Writer", + if (TimePassesIsEnabled) + ExceptionTimer = new Timer("DWARF Exception Writer", getDwarfTimerGroup()); } @@ -46,21 +54,45 @@ DwarfException::~DwarfException() { delete ExceptionTimer; } -void DwarfException::EmitCommonEHFrame(const Function *Personality, - unsigned Index) { +/// SizeOfEncodedValue - Return the size of the encoding in bytes. +unsigned DwarfException::SizeOfEncodedValue(unsigned Encoding) { + if (Encoding == dwarf::DW_EH_PE_omit) + return 0; + + switch (Encoding & 0x07) { + case dwarf::DW_EH_PE_absptr: + return TD->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; + } + + assert(0 && "Invalid encoded value."); + return 0; +} + +/// EmitCIE - Emit a Common Information Entry (CIE). This holds information that +/// is shared among many Frame Description Entries. There is at least one CIE +/// in every non-empty .debug_frame section. +void DwarfException::EmitCIE(const Function *PersonalityFn, unsigned Index) { // Size and sign of stack growth. int stackGrowth = Asm->TM.getFrameInfo()->getStackGrowthDirection() == TargetFrameInfo::StackGrowsUp ? TD->getPointerSize() : -TD->getPointerSize(); + const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering(); + // Begin eh frame section. - Asm->SwitchToTextSection(TAI->getDwarfEHFrameSection()); - - if (!TAI->doesRequireNonLocalEHFrameLabel()) - O << TAI->getEHGlobalPrefix(); + Asm->OutStreamer.SwitchSection(TLOF.getEHFrameSection()); + if (MAI->is_EHSymbolPrivate()) + O << MAI->getPrivateGlobalPrefix(); O << "EH_frame" << Index << ":\n"; + EmitLabel("section_eh_frame", Index); // Define base labels. @@ -79,8 +111,53 @@ void DwarfException::EmitCommonEHFrame(const Function *Personality, Asm->EOL("CIE Version"); // The personality presence indicates that language specific information will - // show up in the eh frame. - Asm->EmitString(Personality ? "zPLR" : "zR"); + // show up in the eh frame. Find out how we are supposed to lower the + // personality function reference: + const MCExpr *PersonalityRef = 0; + bool IsPersonalityIndirect = false, IsPersonalityPCRel = false; + if (PersonalityFn) { + // FIXME: HANDLE STATIC CODEGEN MODEL HERE. + + // In non-static mode, ask the object file how to represent this reference. + PersonalityRef = + TLOF.getSymbolForDwarfGlobalReference(PersonalityFn, Asm->Mang, + Asm->MMI, + IsPersonalityIndirect, + IsPersonalityPCRel); + } + + unsigned PerEncoding = dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4; + if (IsPersonalityIndirect) + PerEncoding |= dwarf::DW_EH_PE_indirect; + unsigned LSDAEncoding = dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4; + unsigned FDEEncoding = dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4; + + char Augmentation[5] = { 0 }; + unsigned AugmentationSize = 0; + char *APtr = Augmentation + 1; + + if (PersonalityRef) { + // There is a personality function. + *APtr++ = 'P'; + AugmentationSize += 1 + SizeOfEncodedValue(PerEncoding); + } + + if (UsesLSDA[Index]) { + // An LSDA pointer is in the FDE augmentation. + *APtr++ = 'L'; + ++AugmentationSize; + } + + if (FDEEncoding != dwarf::DW_EH_PE_absptr) { + // A non-default pointer encoding for the FDE. + *APtr++ = 'R'; + ++AugmentationSize; + } + + if (APtr != Augmentation + 1) + Augmentation[0] = 'z'; + + Asm->EmitString(Augmentation); Asm->EOL("CIE Augmentation"); // Round out reader. @@ -91,39 +168,41 @@ void DwarfException::EmitCommonEHFrame(const Function *Personality, Asm->EmitInt8(RI->getDwarfRegNum(RI->getRARegister(), true)); Asm->EOL("CIE Return Address Column"); - // If there is a personality, we need to indicate the functions location. - if (Personality) { - Asm->EmitULEB128Bytes(7); - Asm->EOL("Augmentation Size"); - - if (TAI->getNeedsIndirectEncoding()) { - Asm->EmitInt8(dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4 | - dwarf::DW_EH_PE_indirect); - Asm->EOL("Personality (pcrel sdata4 indirect)"); - } else { - Asm->EmitInt8(dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4); - Asm->EOL("Personality (pcrel sdata4)"); + Asm->EmitULEB128Bytes(AugmentationSize); + Asm->EOL("Augmentation Size"); + + Asm->EmitInt8(PerEncoding); + Asm->EOL("Personality", PerEncoding); + + // If there is a personality, we need to indicate the function's location. + if (PersonalityRef) { + // If the reference to the personality function symbol is not already + // pc-relative, then we need to subtract our current address from it. Do + // this by emitting a label and subtracting it from the expression we + // already have. This is equivalent to emitting "foo - .", but we have to + // emit the label for "." directly. + if (!IsPersonalityPCRel) { + SmallString<64> Name; + raw_svector_ostream(Name) << MAI->getPrivateGlobalPrefix() + << "personalityref_addr" << Asm->getFunctionNumber() << "_" << Index; + MCSymbol *DotSym = Asm->OutContext.GetOrCreateSymbol(Name.str()); + Asm->OutStreamer.EmitLabel(DotSym); + + PersonalityRef = + MCBinaryExpr::CreateSub(PersonalityRef, + MCSymbolRefExpr::Create(DotSym,Asm->OutContext), + Asm->OutContext); } - - PrintRelDirective(true); - O << TAI->getPersonalityPrefix(); - Asm->EmitExternalGlobal((const GlobalVariable *)(Personality)); - O << TAI->getPersonalitySuffix(); - if (strcmp(TAI->getPersonalitySuffix(), "+4@GOTPCREL")) - O << "-" << TAI->getPCSymbol(); + + O << MAI->getData32bitsDirective(); + PersonalityRef->print(O, MAI); Asm->EOL("Personality"); - Asm->EmitInt8(dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4); - Asm->EOL("LSDA Encoding (pcrel sdata4)"); + Asm->EmitInt8(LSDAEncoding); + Asm->EOL("LSDA Encoding", LSDAEncoding); - Asm->EmitInt8(dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4); - Asm->EOL("FDE Encoding (pcrel sdata4)"); - } else { - Asm->EmitULEB128Bytes(1); - Asm->EOL("Augmentation Size"); - - Asm->EmitInt8(dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4); - Asm->EOL("FDE Encoding (pcrel sdata4)"); + Asm->EmitInt8(FDEEncoding); + Asm->EOL("FDE Encoding", FDEEncoding); } // Indicate locations of general callee saved registers in frame. @@ -134,55 +213,44 @@ void DwarfException::EmitCommonEHFrame(const Function *Personality, // On Darwin the linker honors the alignment of eh_frame, which means it must // be 8-byte on 64-bit targets to match what gcc does. Otherwise you get // holes which confuse readers of eh_frame. - Asm->EmitAlignment(TD->getPointerSize() == sizeof(int32_t) ? 2 : 3, - 0, 0, false); + Asm->EmitAlignment(TD->getPointerSize() == 4 ? 2 : 3, 0, 0, false); EmitLabel("eh_frame_common_end", Index); Asm->EOL(); } -/// EmitEHFrame - Emit function exception frame information. -/// -void DwarfException::EmitEHFrame(const FunctionEHFrameInfo &EHFrameInfo) { - assert(!EHFrameInfo.function->hasAvailableExternallyLinkage() && +/// EmitFDE - Emit the Frame Description Entry (FDE) for the function. +void DwarfException::EmitFDE(const FunctionEHFrameInfo &EHFrameInfo) { + assert(!EHFrameInfo.function->hasAvailableExternallyLinkage() && "Should not emit 'available externally' functions at all"); - Function::LinkageTypes linkage = EHFrameInfo.function->getLinkage(); - Asm->SwitchToTextSection(TAI->getDwarfEHFrameSection()); + const Function *TheFunc = EHFrameInfo.function; + + Asm->OutStreamer.SwitchSection(Asm->getObjFileLowering().getEHFrameSection()); // Externally visible entry into the functions eh frame info. If the // corresponding function is static, this should not be externally visible. - if (linkage != Function::InternalLinkage && - linkage != Function::PrivateLinkage) { - if (const char *GlobalEHDirective = TAI->getGlobalEHDirective()) + if (!TheFunc->hasLocalLinkage()) + if (const char *GlobalEHDirective = MAI->getGlobalEHDirective()) O << GlobalEHDirective << EHFrameInfo.FnName << "\n"; - } // If corresponding function is weak definition, this should be too. - if ((linkage == Function::WeakAnyLinkage || - linkage == Function::WeakODRLinkage || - linkage == Function::LinkOnceAnyLinkage || - linkage == Function::LinkOnceODRLinkage) && - TAI->getWeakDefDirective()) - O << TAI->getWeakDefDirective() << EHFrameInfo.FnName << "\n"; + if (TheFunc->isWeakForLinker() && MAI->getWeakDefDirective()) + O << MAI->getWeakDefDirective() << EHFrameInfo.FnName << "\n"; // If there are no calls then you can't unwind. This may mean we can omit the // EH Frame, but some environments do not handle weak absolute symbols. If // UnwindTablesMandatory is set we cannot do this optimization; the unwind // info is to be available for non-EH uses. - if (!EHFrameInfo.hasCalls && - !UnwindTablesMandatory && - ((linkage != Function::WeakAnyLinkage && - linkage != Function::WeakODRLinkage && - linkage != Function::LinkOnceAnyLinkage && - linkage != Function::LinkOnceODRLinkage) || - !TAI->getWeakDefDirective() || - TAI->getSupportsWeakOmittedEHFrame())) { + if (!EHFrameInfo.hasCalls && !UnwindTablesMandatory && + (!TheFunc->isWeakForLinker() || + !MAI->getWeakDefDirective() || + MAI->getSupportsWeakOmittedEHFrame())) { O << EHFrameInfo.FnName << " = 0\n"; // This name has no connection to the function, so it might get // dead-stripped when the function is not, erroneously. Prohibit // dead-stripping unconditionally. - if (const char *UsedDirective = TAI->getUsedDirective()) + if (const char *UsedDirective = MAI->getUsedDirective()) O << UsedDirective << EHFrameInfo.FnName << "\n\n"; } else { O << EHFrameInfo.FnName << ":\n"; @@ -194,17 +262,9 @@ void DwarfException::EmitEHFrame(const FunctionEHFrameInfo &EHFrameInfo) { EmitLabel("eh_frame_begin", EHFrameInfo.Number); - if (TAI->doesRequireNonLocalEHFrameLabel()) { - PrintRelDirective(true, true); - PrintLabelName("eh_frame_begin", EHFrameInfo.Number); - - if (!TAI->isAbsoluteEHSectionOffsets()) - O << "-EH_frame" << EHFrameInfo.PersonalityIndex; - } else { - EmitSectionOffset("eh_frame_begin", "eh_frame_common", - EHFrameInfo.Number, EHFrameInfo.PersonalityIndex, - true, true, false); - } + EmitSectionOffset("eh_frame_begin", "eh_frame_common", + EHFrameInfo.Number, EHFrameInfo.PersonalityIndex, + true, true, false); Asm->EOL("FDE CIE offset"); @@ -216,14 +276,20 @@ void DwarfException::EmitEHFrame(const FunctionEHFrameInfo &EHFrameInfo) { // If there is a personality and landing pads then point to the language // specific data area in the exception table. - if (EHFrameInfo.PersonalityIndex) { - Asm->EmitULEB128Bytes(4); + if (MMI->getPersonalities()[0] != NULL) { + bool is4Byte = TD->getPointerSize() == sizeof(int32_t); + + Asm->EmitULEB128Bytes(is4Byte ? 4 : 8); Asm->EOL("Augmentation size"); if (EHFrameInfo.hasLandingPads) - EmitReference("exception", EHFrameInfo.Number, true, true); - else - Asm->EmitInt32((int)0); + EmitReference("exception", EHFrameInfo.Number, true, false); + else { + if (is4Byte) + Asm->EmitInt32((int)0); + else + Asm->EmitInt64((int)0); + } Asm->EOL("Language Specific Data Area"); } else { Asm->EmitULEB128Bytes(0); @@ -231,7 +297,7 @@ void DwarfException::EmitEHFrame(const FunctionEHFrameInfo &EHFrameInfo) { } // Indicate locations of function specific callee saved registers in frame. - EmitFrameMoves("eh_func_begin", EHFrameInfo.Number, EHFrameInfo.Moves, + EmitFrameMoves("eh_func_begin", EHFrameInfo.Number, EHFrameInfo.Moves, true); // On Darwin the linker honors the alignment of eh_frame, which means it @@ -246,32 +312,13 @@ void DwarfException::EmitEHFrame(const FunctionEHFrameInfo &EHFrameInfo) { // retains the function in this case, and there is code around that depends // on unused functions (calling undefined externals) being dead-stripped to // link correctly. Yes, there really is. - if (MMI->getUsedFunctions().count(EHFrameInfo.function)) - if (const char *UsedDirective = TAI->getUsedDirective()) + if (MMI->isUsedFunction(EHFrameInfo.function)) + if (const char *UsedDirective = MAI->getUsedDirective()) O << UsedDirective << EHFrameInfo.FnName << "\n\n"; } -} -/// EmitExceptionTable - Emit landing pads and actions. -/// -/// The general organization of the table is complex, but the basic concepts are -/// easy. First there is a header which describes the location and organization -/// of the three components that follow. -/// -/// 1. The landing pad site information describes the range of code covered by -/// the try. In our case it's an accumulation of the ranges covered by the -/// invokes in the try. There is also a reference to the landing pad that -/// handles the exception once processed. Finally an index into the actions -/// table. -/// 2. The action table, in our case, is composed of pairs of type ids and next -/// action offset. Starting with the action index from the landing pad -/// site, each type Id is checked for a match to the current exception. If -/// it matches then the exception and type id are passed on to the landing -/// pad. Otherwise the next action is looked up. This chain is terminated -/// with a next action of zero. If no type id is found the the frame is -/// unwound and handling continues. -/// 3. Type id table contains references to all the C++ typeinfo for all -/// catches in the function. This tables is reversed indexed base 1. + Asm->EOL(); +} /// SharedTypeIds - How many leading type ids two landing pads have in common. unsigned DwarfException::SharedTypeIds(const LandingPadInfo *L, @@ -301,51 +348,58 @@ bool DwarfException::PadLT(const LandingPadInfo *L, const LandingPadInfo *R) { return LSize < RSize; } -void DwarfException::EmitExceptionTable() { - const std::vector<GlobalVariable *> &TypeInfos = MMI->getTypeInfos(); - const std::vector<unsigned> &FilterIds = MMI->getFilterIds(); - const std::vector<LandingPadInfo> &PadInfos = MMI->getLandingPads(); - if (PadInfos.empty()) return; - - // Sort the landing pads in order of their type ids. This is used to fold - // duplicate actions. - SmallVector<const LandingPadInfo *, 64> LandingPads; - LandingPads.reserve(PadInfos.size()); - for (unsigned i = 0, N = PadInfos.size(); i != N; ++i) - LandingPads.push_back(&PadInfos[i]); - std::sort(LandingPads.begin(), LandingPads.end(), PadLT); - - // Negative type ids index into FilterIds, positive type ids index into - // TypeInfos. The value written for a positive type id is just the type id - // itself. For a negative type id, however, the value written is the +/// ComputeActionsTable - Compute the actions table and gather the first action +/// index for each landing pad site. +unsigned DwarfException:: +ComputeActionsTable(const SmallVectorImpl<const LandingPadInfo*> &LandingPads, + SmallVectorImpl<ActionEntry> &Actions, + SmallVectorImpl<unsigned> &FirstActions) { + + // The action table follows the call-site table in the LSDA. The individual + // records are of two types: + // + // * Catch clause + // * Exception specification + // + // The two record kinds have the same format, with only small differences. + // They are distinguished by the "switch value" field: Catch clauses + // (TypeInfos) have strictly positive switch values, and exception + // specifications (FilterIds) have strictly negative switch values. Value 0 + // indicates a catch-all clause. + // + // Negative type IDs index into FilterIds. Positive type IDs index into + // TypeInfos. The value written for a positive type ID is just the type ID + // itself. For a negative type ID, however, the value written is the // (negative) byte offset of the corresponding FilterIds entry. The byte - // offset is usually equal to the type id, because the FilterIds entries are - // written using a variable width encoding which outputs one byte per entry as - // long as the value written is not too large, but can differ. This kind of - // complication does not occur for positive type ids because type infos are + // offset is usually equal to the type ID (because the FilterIds entries are + // written using a variable width encoding, which outputs one byte per entry + // as long as the value written is not too large) but can differ. This kind + // of complication does not occur for positive type IDs because type infos are // output using a fixed width encoding. FilterOffsets[i] holds the byte // offset corresponding to FilterIds[i]. + + const std::vector<unsigned> &FilterIds = MMI->getFilterIds(); SmallVector<int, 16> FilterOffsets; FilterOffsets.reserve(FilterIds.size()); int Offset = -1; - for(std::vector<unsigned>::const_iterator I = FilterIds.begin(), - E = FilterIds.end(); I != E; ++I) { + + for (std::vector<unsigned>::const_iterator + I = FilterIds.begin(), E = FilterIds.end(); I != E; ++I) { FilterOffsets.push_back(Offset); - Offset -= TargetAsmInfo::getULEB128Size(*I); + Offset -= MCAsmInfo::getULEB128Size(*I); } - // Compute the actions table and gather the first action index for each - // landing pad site. - SmallVector<ActionEntry, 32> Actions; - SmallVector<unsigned, 64> FirstActions; FirstActions.reserve(LandingPads.size()); int FirstAction = 0; unsigned SizeActions = 0; - for (unsigned i = 0, N = LandingPads.size(); i != N; ++i) { - const LandingPadInfo *LP = LandingPads[i]; - const std::vector<int> &TypeIds = LP->TypeIds; - const unsigned NumShared = i ? SharedTypeIds(LP, LandingPads[i-1]) : 0; + const LandingPadInfo *PrevLPI = 0; + + for (SmallVectorImpl<const LandingPadInfo *>::const_iterator + I = LandingPads.begin(), E = LandingPads.end(); I != E; ++I) { + const LandingPadInfo *LPI = *I; + const std::vector<int> &TypeIds = LPI->TypeIds; + const unsigned NumShared = PrevLPI ? SharedTypeIds(LPI, PrevLPI) : 0; unsigned SizeSiteActions = 0; if (NumShared < TypeIds.size()) { @@ -353,34 +407,33 @@ void DwarfException::EmitExceptionTable() { ActionEntry *PrevAction = 0; if (NumShared) { - const unsigned SizePrevIds = LandingPads[i-1]->TypeIds.size(); + const unsigned SizePrevIds = PrevLPI->TypeIds.size(); assert(Actions.size()); PrevAction = &Actions.back(); - SizeAction = TargetAsmInfo::getSLEB128Size(PrevAction->NextAction) + - TargetAsmInfo::getSLEB128Size(PrevAction->ValueForTypeID); + SizeAction = MCAsmInfo::getSLEB128Size(PrevAction->NextAction) + + MCAsmInfo::getSLEB128Size(PrevAction->ValueForTypeID); for (unsigned j = NumShared; j != SizePrevIds; ++j) { SizeAction -= - TargetAsmInfo::getSLEB128Size(PrevAction->ValueForTypeID); + MCAsmInfo::getSLEB128Size(PrevAction->ValueForTypeID); SizeAction += -PrevAction->NextAction; PrevAction = PrevAction->Previous; } } // Compute the actions. - for (unsigned I = NumShared, M = TypeIds.size(); I != M; ++I) { - int TypeID = TypeIds[I]; - assert(-1-TypeID < (int)FilterOffsets.size() && "Unknown filter id!"); + for (unsigned J = NumShared, M = TypeIds.size(); J != M; ++J) { + int TypeID = TypeIds[J]; + assert(-1 - TypeID < (int)FilterOffsets.size() && "Unknown filter id!"); int ValueForTypeID = TypeID < 0 ? FilterOffsets[-1 - TypeID] : TypeID; - unsigned SizeTypeID = TargetAsmInfo::getSLEB128Size(ValueForTypeID); + unsigned SizeTypeID = MCAsmInfo::getSLEB128Size(ValueForTypeID); int NextAction = SizeAction ? -(SizeAction + SizeTypeID) : 0; - SizeAction = SizeTypeID + TargetAsmInfo::getSLEB128Size(NextAction); + SizeAction = SizeTypeID + MCAsmInfo::getSLEB128Size(NextAction); SizeSiteActions += SizeAction; - ActionEntry Action = {ValueForTypeID, NextAction, PrevAction}; + ActionEntry Action = { ValueForTypeID, NextAction, PrevAction }; Actions.push_back(Action); - PrevAction = &Actions.back(); } @@ -388,35 +441,34 @@ void DwarfException::EmitExceptionTable() { FirstAction = SizeActions + SizeSiteActions - SizeAction + 1; } // else identical - re-use previous FirstAction + // Information used when created the call-site table. The action record + // field of the call site record is the offset of the first associated + // action record, relative to the start of the actions table. This value is + // biased by 1 (1 in dicating the start of the actions table), and 0 + // indicates that there are no actions. FirstActions.push_back(FirstAction); // Compute this sites contribution to size. SizeActions += SizeSiteActions; - } - - // Compute the call-site table. The entry for an invoke has a try-range - // containing the call, a non-zero landing pad and an appropriate action. The - // entry for an ordinary call has a try-range containing the call and zero for - // the landing pad and the action. Calls marked 'nounwind' have no entry and - // must not be contained in the try-range of any entry - they form gaps in the - // table. Entries must be ordered by try-range address. - SmallVector<CallSiteEntry, 64> CallSites; - - RangeMapType PadMap; - // Invokes and nounwind calls have entries in PadMap (due to being bracketed - // by try-range labels when lowered). Ordinary calls do not, so appropriate - // try-ranges for them need be deduced. - for (unsigned i = 0, N = LandingPads.size(); i != N; ++i) { - const LandingPadInfo *LandingPad = LandingPads[i]; - for (unsigned j = 0, E = LandingPad->BeginLabels.size(); j != E; ++j) { - unsigned BeginLabel = LandingPad->BeginLabels[j]; - assert(!PadMap.count(BeginLabel) && "Duplicate landing pad labels!"); - PadRange P = { i, j }; - PadMap[BeginLabel] = P; - } + PrevLPI = LPI; } + return SizeActions; +} + +/// ComputeCallSiteTable - Compute the call-site table. The entry for an invoke +/// has a try-range containing the call, a non-zero landing pad, and an +/// appropriate action. The entry for an ordinary call has a try-range +/// containing the call and zero for the landing pad and the action. Calls +/// marked 'nounwind' have no entry and must not be contained in the try-range +/// of any entry - they form gaps in the table. Entries must be ordered by +/// try-range address. +void DwarfException:: +ComputeCallSiteTable(SmallVectorImpl<CallSiteEntry> &CallSites, + const RangeMapType &PadMap, + const SmallVectorImpl<const LandingPadInfo *> &LandingPads, + const SmallVectorImpl<unsigned> &FirstActions) { // The end label of the previous invoke or nounwind try-range. unsigned LastLabel = 0; @@ -424,7 +476,7 @@ void DwarfException::EmitExceptionTable() { // an ordinary call) between the end of the previous try-range and now. bool SawPotentiallyThrowing = false; - // Whether the last callsite entry was for an invoke. + // Whether the last CallSite entry was for an invoke. bool PreviousIsInvoke = false; // Visit all instructions in order of address. @@ -450,17 +502,18 @@ void DwarfException::EmitExceptionTable() { // Nope, it was just some random label. continue; - PadRange P = L->second; + const PadRange &P = L->second; const LandingPadInfo *LandingPad = LandingPads[P.PadIndex]; - assert(BeginLabel == LandingPad->BeginLabels[P.RangeIndex] && "Inconsistent landing pad map!"); - // If some instruction between the previous try-range and this one may - // throw, create a call-site entry with no landing pad for the region - // between the try-ranges. - if (SawPotentiallyThrowing) { - CallSiteEntry Site = {LastLabel, BeginLabel, 0, 0}; + // For Dwarf exception handling (SjLj handling doesn't use this). If some + // instruction between the previous try-range and this one may throw, + // create a call-site entry with no landing pad for the region between the + // try-ranges. + if (SawPotentiallyThrowing && + MAI->getExceptionHandlingType() == ExceptionHandling::Dwarf) { + CallSiteEntry Site = { LastLabel, BeginLabel, 0, 0 }; CallSites.push_back(Site); PreviousIsInvoke = false; } @@ -470,12 +523,16 @@ void DwarfException::EmitExceptionTable() { if (LandingPad->LandingPadLabel) { // This try-range is for an invoke. - CallSiteEntry Site = {BeginLabel, LastLabel, - LandingPad->LandingPadLabel, - FirstActions[P.PadIndex]}; - - // Try to merge with the previous call-site. - if (PreviousIsInvoke) { + CallSiteEntry Site = { + BeginLabel, + LastLabel, + LandingPad->LandingPadLabel, + FirstActions[P.PadIndex] + }; + + // Try to merge with the previous call-site. SJLJ doesn't do this + if (PreviousIsInvoke && + MAI->getExceptionHandlingType() == ExceptionHandling::Dwarf) { CallSiteEntry &Prev = CallSites.back(); if (Site.PadLabel == Prev.PadLabel && Site.Action == Prev.Action) { // Extend the range of the previous entry. @@ -497,128 +554,363 @@ void DwarfException::EmitExceptionTable() { // If some instruction between the previous try-range and the end of the // function may throw, create a call-site entry with no landing pad for the // region following the try-range. - if (SawPotentiallyThrowing) { - CallSiteEntry Site = {LastLabel, 0, 0, 0}; + if (SawPotentiallyThrowing && + MAI->getExceptionHandlingType() == ExceptionHandling::Dwarf) { + CallSiteEntry Site = { LastLabel, 0, 0, 0 }; CallSites.push_back(Site); } +} + +/// EmitExceptionTable - Emit landing pads and actions. +/// +/// The general organization of the table is complex, but the basic concepts are +/// easy. First there is a header which describes the location and organization +/// of the three components that follow. +/// +/// 1. The landing pad site information describes the range of code covered by +/// the try. In our case it's an accumulation of the ranges covered by the +/// invokes in the try. There is also a reference to the landing pad that +/// handles the exception once processed. Finally an index into the actions +/// table. +/// 2. The action table, in our case, is composed of pairs of type IDs and next +/// action offset. Starting with the action index from the landing pad +/// site, each type ID is checked for a match to the current exception. If +/// it matches then the exception and type id are passed on to the landing +/// pad. Otherwise the next action is looked up. This chain is terminated +/// with a next action of zero. If no type id is found then the frame is +/// unwound and handling continues. +/// 3. Type ID table contains references to all the C++ typeinfo for all +/// catches in the function. This tables is reverse indexed base 1. +void DwarfException::EmitExceptionTable() { + const std::vector<GlobalVariable *> &TypeInfos = MMI->getTypeInfos(); + const std::vector<unsigned> &FilterIds = MMI->getFilterIds(); + const std::vector<LandingPadInfo> &PadInfos = MMI->getLandingPads(); + if (PadInfos.empty()) return; + + // Sort the landing pads in order of their type ids. This is used to fold + // duplicate actions. + SmallVector<const LandingPadInfo *, 64> LandingPads; + LandingPads.reserve(PadInfos.size()); + + for (unsigned i = 0, N = PadInfos.size(); i != N; ++i) + LandingPads.push_back(&PadInfos[i]); + + std::sort(LandingPads.begin(), LandingPads.end(), PadLT); + + // Compute the actions table and gather the first action index for each + // landing pad site. + SmallVector<ActionEntry, 32> Actions; + SmallVector<unsigned, 64> FirstActions; + unsigned SizeActions = ComputeActionsTable(LandingPads, Actions, + FirstActions); + + // Invokes and nounwind calls have entries in PadMap (due to being bracketed + // by try-range labels when lowered). Ordinary calls do not, so appropriate + // try-ranges for them need be deduced when using DWARF exception handling. + RangeMapType PadMap; + for (unsigned i = 0, N = LandingPads.size(); i != N; ++i) { + const LandingPadInfo *LandingPad = LandingPads[i]; + for (unsigned j = 0, E = LandingPad->BeginLabels.size(); j != E; ++j) { + unsigned BeginLabel = LandingPad->BeginLabels[j]; + assert(!PadMap.count(BeginLabel) && "Duplicate landing pad labels!"); + PadRange P = { i, j }; + PadMap[BeginLabel] = P; + } + } + + // Compute the call-site table. + SmallVector<CallSiteEntry, 64> CallSites; + ComputeCallSiteTable(CallSites, PadMap, LandingPads, FirstActions); // Final tallies. // Call sites. - const unsigned SiteStartSize = sizeof(int32_t); // DW_EH_PE_udata4 - const unsigned SiteLengthSize = sizeof(int32_t); // DW_EH_PE_udata4 - const unsigned LandingPadSize = sizeof(int32_t); // DW_EH_PE_udata4 - unsigned SizeSites = CallSites.size() * (SiteStartSize + - SiteLengthSize + - LandingPadSize); - for (unsigned i = 0, e = CallSites.size(); i < e; ++i) - SizeSites += TargetAsmInfo::getULEB128Size(CallSites[i].Action); + const unsigned SiteStartSize = SizeOfEncodedValue(dwarf::DW_EH_PE_udata4); + const unsigned SiteLengthSize = SizeOfEncodedValue(dwarf::DW_EH_PE_udata4); + const unsigned LandingPadSize = SizeOfEncodedValue(dwarf::DW_EH_PE_udata4); + bool IsSJLJ = MAI->getExceptionHandlingType() == ExceptionHandling::SjLj; + bool HaveTTData = IsSJLJ ? (!TypeInfos.empty() || !FilterIds.empty()) : true; + unsigned SizeSites; + + if (IsSJLJ) + SizeSites = 0; + else + SizeSites = CallSites.size() * + (SiteStartSize + SiteLengthSize + LandingPadSize); + + for (unsigned i = 0, e = CallSites.size(); i < e; ++i) { + SizeSites += MCAsmInfo::getULEB128Size(CallSites[i].Action); + if (IsSJLJ) + SizeSites += MCAsmInfo::getULEB128Size(i); + } // Type infos. - const unsigned TypeInfoSize = TD->getPointerSize(); // DW_EH_PE_absptr - unsigned SizeTypes = TypeInfos.size() * TypeInfoSize; - - unsigned TypeOffset = sizeof(int8_t) + // Call site format - TargetAsmInfo::getULEB128Size(SizeSites) + // Call-site table length - SizeSites + SizeActions + SizeTypes; - - unsigned TotalSize = sizeof(int8_t) + // LPStart format - sizeof(int8_t) + // TType format - TargetAsmInfo::getULEB128Size(TypeOffset) + // TType base offset - TypeOffset; + const MCSection *LSDASection = Asm->getObjFileLowering().getLSDASection(); + unsigned TTypeFormat; + unsigned TypeFormatSize; + + if (!HaveTTData) { + // For SjLj exceptions, if there is no TypeInfo, then we just explicitly say + // that we're omitting that bit. + TTypeFormat = dwarf::DW_EH_PE_omit; + TypeFormatSize = SizeOfEncodedValue(dwarf::DW_EH_PE_absptr); + } 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 + // typeinfo objects at the end of the LSDA. However, unless we're in static + // mode, this reference will require a relocation by the dynamic linker. + // + // Because of this, we have a couple of options: + // + // 1) If we are in -static mode, we can always use an absolute reference + // from the LSDA, because the static linker will resolve it. + // + // 2) Otherwise, if the LSDA section is writable, we can output the direct + // reference to the typeinfo and allow the dynamic linker to relocate + // it. Since it is in a writable section, the dynamic linker won't + // have a problem. + // + // 3) Finally, if we're in PIC mode and the LDSA section isn't writable, + // we need to use some form of indirection. For example, on Darwin, + // we can output a statically-relocatable reference to a dyld stub. The + // offset to the stub is constant, but the contents are in a section + // that is updated by the dynamic linker. This is easy enough, but we + // need to tell the personality function of the unwinder to indirect + // through the dyld stub. + // + // FIXME: When (3) is actually implemented, we'll have to emit the stubs + // somewhere. This predicate should be moved to a shared location that is + // in target-independent code. + // + if (LSDASection->getKind().isWriteable() || + Asm->TM.getRelocationModel() == Reloc::Static) + TTypeFormat = dwarf::DW_EH_PE_absptr; + else + TTypeFormat = dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel | + dwarf::DW_EH_PE_sdata4; - unsigned SizeAlign = (4 - TotalSize) & 3; + TypeFormatSize = SizeOfEncodedValue(TTypeFormat); + } // Begin the exception table. - Asm->SwitchToDataSection(TAI->getDwarfExceptionSection()); + Asm->OutStreamer.SwitchSection(LSDASection); Asm->EmitAlignment(2, 0, 0, false); + O << "GCC_except_table" << SubprogramCount << ":\n"; + // The type infos need to be aligned. GCC does this by inserting padding just + // before the type infos. However, this changes the size of the exception + // table, so you need to take this into account when you output the exception + // table size. However, the size is output using a variable length encoding. + // So by increasing the size by inserting padding, you may increase the number + // of bytes used for writing the size. If it increases, say by one byte, then + // you now need to output one less byte of padding to get the type infos + // aligned. However this decreases the size of the exception table. This + // changes the value you have to output for the exception table size. Due to + // the variable length encoding, the number of bytes used for writing the + // length may decrease. If so, you then have to increase the amount of + // padding. And so on. If you look carefully at the GCC code you will see that + // it indeed does this in a loop, going on and on until the values stabilize. + // We chose another solution: don't output padding inside the table like GCC + // does, instead output it before the table. + unsigned SizeTypes = TypeInfos.size() * TypeFormatSize; + unsigned TyOffset = sizeof(int8_t) + // Call site format + MCAsmInfo::getULEB128Size(SizeSites) + // Call-site table length + SizeSites + SizeActions + SizeTypes; + unsigned TotalSize = sizeof(int8_t) + // LPStart format + sizeof(int8_t) + // TType format + (HaveTTData ? + MCAsmInfo::getULEB128Size(TyOffset) : 0) + // TType base offset + TyOffset; + unsigned SizeAlign = (4 - TotalSize) & 3; + for (unsigned i = 0; i != SizeAlign; ++i) { Asm->EmitInt8(0); Asm->EOL("Padding"); - } + } EmitLabel("exception", SubprogramCount); + if (IsSJLJ) { + SmallString<16> LSDAName; + raw_svector_ostream(LSDAName) << MAI->getPrivateGlobalPrefix() << + "_LSDA_" << Asm->getFunctionNumber(); + O << LSDAName.str() << ":\n"; + } + // Emit the header. Asm->EmitInt8(dwarf::DW_EH_PE_omit); - Asm->EOL("LPStart format (DW_EH_PE_omit)"); - Asm->EmitInt8(dwarf::DW_EH_PE_absptr); - Asm->EOL("TType format (DW_EH_PE_absptr)"); - Asm->EmitULEB128Bytes(TypeOffset); - Asm->EOL("TType base offset"); - Asm->EmitInt8(dwarf::DW_EH_PE_udata4); - Asm->EOL("Call site format (DW_EH_PE_udata4)"); - Asm->EmitULEB128Bytes(SizeSites); - Asm->EOL("Call-site table length"); - - // Emit the landing pad site information. - for (unsigned i = 0; i < CallSites.size(); ++i) { - CallSiteEntry &S = CallSites[i]; - const char *BeginTag; - unsigned BeginNumber; - - if (!S.BeginLabel) { - BeginTag = "eh_func_begin"; - BeginNumber = SubprogramCount; - } else { - BeginTag = "label"; - BeginNumber = S.BeginLabel; - } + Asm->EOL("@LPStart format", dwarf::DW_EH_PE_omit); - EmitSectionOffset(BeginTag, "eh_func_begin", BeginNumber, SubprogramCount, - true, true); - Asm->EOL("Region start"); + Asm->EmitInt8(TTypeFormat); + Asm->EOL("@TType format", TTypeFormat); - if (!S.EndLabel) - EmitDifference("eh_func_end", SubprogramCount, BeginTag, BeginNumber, - true); - else - EmitDifference("label", S.EndLabel, BeginTag, BeginNumber, true); + if (HaveTTData) { + Asm->EmitULEB128Bytes(TyOffset); + Asm->EOL("@TType base offset"); + } - Asm->EOL("Region length"); + // SjLj Exception handling + if (IsSJLJ) { + Asm->EmitInt8(dwarf::DW_EH_PE_udata4); + Asm->EOL("Call site format", dwarf::DW_EH_PE_udata4); + Asm->EmitULEB128Bytes(SizeSites); + Asm->EOL("Call site table length"); + + // Emit the landing pad site information. + unsigned idx = 0; + for (SmallVectorImpl<CallSiteEntry>::const_iterator + I = CallSites.begin(), E = CallSites.end(); I != E; ++I, ++idx) { + const CallSiteEntry &S = *I; + + // Offset of the landing pad, counted in 16-byte bundles relative to the + // @LPStart address. + Asm->EmitULEB128Bytes(idx); + Asm->EOL("Landing pad"); + + // Offset of the first associated action record, relative to the start of + // the action table. This value is biased by 1 (1 indicates the start of + // the action table), and 0 indicates that there are no actions. + Asm->EmitULEB128Bytes(S.Action); + Asm->EOL("Action"); + } + } else { + // DWARF Exception handling + assert(MAI->getExceptionHandlingType() == ExceptionHandling::Dwarf); + + // The call-site table is a list of all call sites that may throw an + // exception (including C++ 'throw' statements) in the procedure + // fragment. It immediately follows the LSDA header. Each entry indicates, + // for a given call, the first corresponding action record and corresponding + // landing pad. + // + // The table begins with the number of bytes, stored as an LEB128 + // compressed, unsigned integer. The records immediately follow the record + // count. They are sorted in increasing call-site address. Each record + // indicates: + // + // * The position of the call-site. + // * The position of the landing pad. + // * The first action record for that call site. + // + // A missing entry in the call-site table indicates that a call is not + // supposed to throw. + + // Emit the landing pad call site table. + Asm->EmitInt8(dwarf::DW_EH_PE_udata4); + Asm->EOL("Call site format", dwarf::DW_EH_PE_udata4); + Asm->EmitULEB128Bytes(SizeSites); + Asm->EOL("Call site table size"); + + for (SmallVectorImpl<CallSiteEntry>::const_iterator + I = CallSites.begin(), E = CallSites.end(); I != E; ++I) { + const CallSiteEntry &S = *I; + const char *BeginTag; + unsigned BeginNumber; + + if (!S.BeginLabel) { + BeginTag = "eh_func_begin"; + BeginNumber = SubprogramCount; + } else { + BeginTag = "label"; + BeginNumber = S.BeginLabel; + } - if (!S.PadLabel) - Asm->EmitInt32(0); - else - EmitSectionOffset("label", "eh_func_begin", S.PadLabel, SubprogramCount, + // Offset of the call site relative to the previous call site, counted in + // number of 16-byte bundles. The first call site is counted relative to + // the start of the procedure fragment. + EmitSectionOffset(BeginTag, "eh_func_begin", BeginNumber, SubprogramCount, true, true); + Asm->EOL("Region start"); + + if (!S.EndLabel) + EmitDifference("eh_func_end", SubprogramCount, BeginTag, BeginNumber, + true); + else + EmitDifference("label", S.EndLabel, BeginTag, BeginNumber, true); + + Asm->EOL("Region length"); - Asm->EOL("Landing pad"); + // Offset of the landing pad, counted in 16-byte bundles relative to the + // @LPStart address. + if (!S.PadLabel) + Asm->EmitInt32(0); + else + EmitSectionOffset("label", "eh_func_begin", S.PadLabel, SubprogramCount, + true, true); + + Asm->EOL("Landing pad"); - Asm->EmitULEB128Bytes(S.Action); - Asm->EOL("Action"); + // Offset of the first associated action record, relative to the start of + // the action table. This value is biased by 1 (1 indicates the start of + // the action table), and 0 indicates that there are no actions. + Asm->EmitULEB128Bytes(S.Action); + Asm->EOL("Action"); + } } - // Emit the actions. - for (unsigned I = 0, N = Actions.size(); I != N; ++I) { - ActionEntry &Action = Actions[I]; + // Emit the Action Table. + for (SmallVectorImpl<ActionEntry>::const_iterator + I = Actions.begin(), E = Actions.end(); I != E; ++I) { + const ActionEntry &Action = *I; + + // Type Filter + // + // Used by the runtime to match the type of the thrown exception to the + // type of the catch clauses or the types in the exception specification. Asm->EmitSLEB128Bytes(Action.ValueForTypeID); Asm->EOL("TypeInfo index"); + + // Action Record + // + // Self-relative signed displacement in bytes of the next action record, + // or 0 if there is no next action record. + Asm->EmitSLEB128Bytes(Action.NextAction); Asm->EOL("Next action"); } - // Emit the type ids. - for (unsigned M = TypeInfos.size(); M; --M) { - GlobalVariable *GV = TypeInfos[M - 1]; + // Emit the Catch Clauses. The code for the catch clauses following the same + // try is similar to a switch statement. The catch clause action record + // informs the runtime about the type of a catch clause and about the + // associated switch value. + // + // Action Record Fields: + // + // * Filter Value + // Positive value, starting at 1. Index in the types table of the + // __typeinfo for the catch-clause type. 1 is the first word preceding + // TTBase, 2 is the second word, and so on. Used by the runtime to check + // if the thrown exception type matches the catch-clause type. Back-end + // generated switch statements check against this value. + // + // * Next + // Signed offset, in bytes from the start of this field, to the next + // chained action record, or zero if none. + // + // The order of the action records determined by the next field is the order + // of the catch clauses as they appear in the source code, and must be kept in + // the same order. As a result, changing the order of the catch clause would + // change the semantics of the program. + for (std::vector<GlobalVariable *>::const_reverse_iterator + I = TypeInfos.rbegin(), E = TypeInfos.rend(); I != E; ++I) { + const GlobalVariable *GV = *I; PrintRelDirective(); if (GV) { - std::string GLN; - O << Asm->getGlobalLinkName(GV, GLN); + O << Asm->Mang->getMangledName(GV); } else { - O << "0"; + O << "0x0"; } Asm->EOL("TypeInfo"); } - // Emit the filter typeids. - for (unsigned j = 0, M = FilterIds.size(); j < M; ++j) { - unsigned TypeID = FilterIds[j]; + // Emit the Type Table. + for (std::vector<unsigned>::const_iterator + I = FilterIds.begin(), E = FilterIds.end(); I < E; ++I) { + unsigned TypeID = *I; Asm->EmitULEB128Bytes(TypeID); Asm->EOL("Filter TypeInfo index"); } @@ -629,48 +921,53 @@ void DwarfException::EmitExceptionTable() { /// EndModule - Emit all exception information that should come after the /// content. void DwarfException::EndModule() { + if (MAI->getExceptionHandlingType() != ExceptionHandling::Dwarf) + return; + + if (!shouldEmitMovesModule && !shouldEmitTableModule) + return; + if (TimePassesIsEnabled) ExceptionTimer->startTimer(); - if (shouldEmitMovesModule || shouldEmitTableModule) { - const std::vector<Function *> Personalities = MMI->getPersonalities(); - for (unsigned i = 0; i < Personalities.size(); ++i) - EmitCommonEHFrame(Personalities[i], i); + const std::vector<Function *> Personalities = MMI->getPersonalities(); - for (std::vector<FunctionEHFrameInfo>::iterator I = EHFrames.begin(), - E = EHFrames.end(); I != E; ++I) - EmitEHFrame(*I); - } + for (unsigned I = 0, E = Personalities.size(); I < E; ++I) + EmitCIE(Personalities[I], I); + + for (std::vector<FunctionEHFrameInfo>::iterator + I = EHFrames.begin(), E = EHFrames.end(); I != E; ++I) + EmitFDE(*I); if (TimePassesIsEnabled) ExceptionTimer->stopTimer(); } -/// BeginFunction - Gather pre-function exception information. Assumes being -/// emitted immediately after the function entry point. +/// BeginFunction - Gather pre-function exception information. Assumes it's +/// being emitted immediately after the function entry point. void DwarfException::BeginFunction(MachineFunction *MF) { + if (!MMI || !MAI->doesSupportExceptionHandling()) return; + if (TimePassesIsEnabled) ExceptionTimer->startTimer(); this->MF = MF; shouldEmitTable = shouldEmitMoves = false; - if (MMI && TAI->doesSupportExceptionHandling()) { - // Map all labels and get rid of any dead landing pads. - MMI->TidyLandingPads(); + // Map all labels and get rid of any dead landing pads. + MMI->TidyLandingPads(); - // If any landing pads survive, we need an EH table. - if (MMI->getLandingPads().size()) - shouldEmitTable = true; + // If any landing pads survive, we need an EH table. + if (!MMI->getLandingPads().empty()) + shouldEmitTable = true; - // See if we need frame move info. - if (!MF->getFunction()->doesNotThrow() || UnwindTablesMandatory) - shouldEmitMoves = true; + // See if we need frame move info. + if (!MF->getFunction()->doesNotThrow() || UnwindTablesMandatory) + shouldEmitMoves = true; - if (shouldEmitMoves || shouldEmitTable) - // Assumes in correct section after the entry point. - EmitLabel("eh_func_begin", ++SubprogramCount); - } + if (shouldEmitMoves || shouldEmitTable) + // Assumes in correct section after the entry point. + EmitLabel("eh_func_begin", ++SubprogramCount); shouldEmitTableModule |= shouldEmitTable; shouldEmitMovesModule |= shouldEmitMoves; @@ -682,25 +979,29 @@ void DwarfException::BeginFunction(MachineFunction *MF) { /// EndFunction - Gather and emit post-function exception information. /// void DwarfException::EndFunction() { - if (TimePassesIsEnabled) + if (!shouldEmitMoves && !shouldEmitTable) return; + + if (TimePassesIsEnabled) ExceptionTimer->startTimer(); - if (shouldEmitMoves || shouldEmitTable) { - EmitLabel("eh_func_end", SubprogramCount); - EmitExceptionTable(); - - // Save EH frame information - std::string Name; - EHFrames.push_back( - FunctionEHFrameInfo(getAsm()->getCurrentFunctionEHName(MF, Name), - SubprogramCount, - MMI->getPersonalityIndex(), - MF->getFrameInfo()->hasCalls(), - !MMI->getLandingPads().empty(), - MMI->getFrameMoves(), - MF->getFunction())); - } + EmitLabel("eh_func_end", SubprogramCount); + EmitExceptionTable(); - if (TimePassesIsEnabled) + std::string FunctionEHName = + Asm->Mang->getMangledName(MF->getFunction(), ".eh", + Asm->MAI->is_EHSymbolPrivate()); + + // Save EH frame information + EHFrames.push_back(FunctionEHFrameInfo(FunctionEHName, SubprogramCount, + MMI->getPersonalityIndex(), + MF->getFrameInfo()->hasCalls(), + !MMI->getLandingPads().empty(), + MMI->getFrameMoves(), + MF->getFunction())); + + // Record if this personality index uses a landing pad. + UsesLSDA[MMI->getPersonalityIndex()] |= !MMI->getLandingPads().empty(); + + if (TimePassesIsEnabled) ExceptionTimer->stopTimer(); } diff --git a/lib/CodeGen/AsmPrinter/DwarfException.h b/lib/CodeGen/AsmPrinter/DwarfException.h index f1c3e56..f6f5025 100644 --- a/lib/CodeGen/AsmPrinter/DwarfException.h +++ b/lib/CodeGen/AsmPrinter/DwarfException.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef CODEGEN_ASMPRINTER_DWARFEXCEPTION_H__ -#define CODEGEN_ASMPRINTER_DWARFEXCEPTION_H__ +#ifndef LLVM_CODEGEN_ASMPRINTER_DWARFEXCEPTION_H +#define LLVM_CODEGEN_ASMPRINTER_DWARFEXCEPTION_H #include "DIE.h" #include "DwarfPrinter.h" @@ -24,7 +24,7 @@ namespace llvm { struct LandingPadInfo; class MachineModuleInfo; -class TargetAsmInfo; +class MCAsmInfo; class Timer; class raw_ostream; @@ -51,6 +51,11 @@ class VISIBILITY_HIDDEN DwarfException : public Dwarf { std::vector<FunctionEHFrameInfo> EHFrames; + /// UsesLSDA - Indicates whether an FDE that uses the CIE at the given index + /// uses an LSDA. If so, then we need to encode that information in the CIE's + /// augmentation. + DenseMap<unsigned, bool> UsesLSDA; + /// shouldEmitTable - Per-function flag to indicate if EH tables should /// be emitted. bool shouldEmitTable; @@ -70,13 +75,16 @@ class VISIBILITY_HIDDEN DwarfException : public Dwarf { /// ExceptionTimer - Timer for the Dwarf exception writer. Timer *ExceptionTimer; - /// EmitCommonEHFrame - Emit the common eh unwind frame. - /// - void EmitCommonEHFrame(const Function *Personality, unsigned Index); + /// SizeOfEncodedValue - Return the size of the encoding in bytes. + unsigned SizeOfEncodedValue(unsigned Encoding); - /// EmitEHFrame - Emit function exception frame information. - /// - void EmitEHFrame(const FunctionEHFrameInfo &EHFrameInfo); + /// EmitCIE - Emit a Common Information Entry (CIE). This holds information + /// that is shared among many Frame Description Entries. There is at least + /// one CIE in every non-empty .debug_frame section. + void EmitCIE(const Function *Personality, unsigned Index); + + /// EmitFDE - Emit the Frame Description Entry (FDE) for the function. + void EmitFDE(const FunctionEHFrameInfo &EHFrameInfo); /// EmitExceptionTable - Emit landing pads and actions. /// @@ -113,13 +121,6 @@ class VISIBILITY_HIDDEN DwarfException : public Dwarf { static bool isPod() { return true; } }; - /// ActionEntry - Structure describing an entry in the actions table. - struct ActionEntry { - int ValueForTypeID; // The value to write - may not be equal to the type id. - int NextAction; - struct ActionEntry *Previous; - }; - /// PadRange - Structure holding a try-range and the associated landing pad. struct PadRange { // The index of the landing pad. @@ -130,23 +131,48 @@ class VISIBILITY_HIDDEN DwarfException : public Dwarf { typedef DenseMap<unsigned, PadRange, KeyInfo> RangeMapType; + /// ActionEntry - Structure describing an entry in the actions table. + struct ActionEntry { + int ValueForTypeID; // The value to write - may not be equal to the type id. + int NextAction; + struct ActionEntry *Previous; + }; + /// CallSiteEntry - Structure describing an entry in the call-site table. struct CallSiteEntry { // The 'try-range' is BeginLabel .. EndLabel. unsigned BeginLabel; // zero indicates the start of the function. unsigned EndLabel; // zero indicates the end of the function. + // The landing pad starts at PadLabel. unsigned PadLabel; // zero indicates that there is no landing pad. unsigned Action; }; + /// ComputeActionsTable - Compute the actions table and gather the first + /// action index for each landing pad site. + unsigned ComputeActionsTable(const SmallVectorImpl<const LandingPadInfo*>&LPs, + SmallVectorImpl<ActionEntry> &Actions, + SmallVectorImpl<unsigned> &FirstActions); + + /// ComputeCallSiteTable - Compute the call-site table. The entry for an + /// invoke has a try-range containing the call, a non-zero landing pad and an + /// appropriate action. The entry for an ordinary call has a try-range + /// containing the call and zero for the landing pad and the action. Calls + /// marked 'nounwind' have no entry and must not be contained in the try-range + /// of any entry - they form gaps in the table. Entries must be ordered by + /// try-range address. + void ComputeCallSiteTable(SmallVectorImpl<CallSiteEntry> &CallSites, + const RangeMapType &PadMap, + const SmallVectorImpl<const LandingPadInfo *> &LPs, + const SmallVectorImpl<unsigned> &FirstActions); void EmitExceptionTable(); public: //===--------------------------------------------------------------------===// // Main entry points. // - DwarfException(raw_ostream &OS, AsmPrinter *A, const TargetAsmInfo *T); + DwarfException(raw_ostream &OS, AsmPrinter *A, const MCAsmInfo *T); virtual ~DwarfException(); /// BeginModule - Emit all exception information that should come prior to the diff --git a/lib/CodeGen/AsmPrinter/DwarfLabel.cpp b/lib/CodeGen/AsmPrinter/DwarfLabel.cpp index 8021b7c..6e9293a 100644 --- a/lib/CodeGen/AsmPrinter/DwarfLabel.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfLabel.cpp @@ -13,7 +13,7 @@ #include "DwarfLabel.h" #include "llvm/ADT/FoldingSet.h" -#include <ostream> +#include "llvm/Support/raw_ostream.h" using namespace llvm; @@ -25,10 +25,7 @@ void DWLabel::Profile(FoldingSetNodeID &ID) const { } #ifndef NDEBUG -void DWLabel::print(std::ostream *O) const { - if (O) print(*O); -} -void DWLabel::print(std::ostream &O) const { +void DWLabel::print(raw_ostream &O) const { O << "." << Tag; if (Number) O << Number; } diff --git a/lib/CodeGen/AsmPrinter/DwarfLabel.h b/lib/CodeGen/AsmPrinter/DwarfLabel.h index b493903..0c0cc4b 100644 --- a/lib/CodeGen/AsmPrinter/DwarfLabel.h +++ b/lib/CodeGen/AsmPrinter/DwarfLabel.h @@ -14,19 +14,16 @@ #ifndef CODEGEN_ASMPRINTER_DWARFLABEL_H__ #define CODEGEN_ASMPRINTER_DWARFLABEL_H__ -#include "llvm/Support/Compiler.h" -#include <iosfwd> -#include <vector> - namespace llvm { class FoldingSetNodeID; + class raw_ostream; //===--------------------------------------------------------------------===// /// DWLabel - Labels are used to track locations in the assembler file. /// Labels appear in the form @verbatim <prefix><Tag><Number> @endverbatim, /// where the tag is a category of label (Ex. location) and number is a value /// unique in that category. - class VISIBILITY_HIDDEN DWLabel { + class DWLabel { /// Tag - Label category tag. Should always be a statically declared C /// string. /// @@ -47,8 +44,7 @@ namespace llvm { void Profile(FoldingSetNodeID &ID) const; #ifndef NDEBUG - void print(std::ostream *O) const; - void print(std::ostream &O) const; + void print(raw_ostream &O) const; #endif }; } // end llvm namespace diff --git a/lib/CodeGen/AsmPrinter/DwarfPrinter.cpp b/lib/CodeGen/AsmPrinter/DwarfPrinter.cpp index a1b97df..20b959b 100644 --- a/lib/CodeGen/AsmPrinter/DwarfPrinter.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfPrinter.cpp @@ -15,39 +15,41 @@ #include "llvm/Module.h" #include "llvm/CodeGen/AsmPrinter.h" #include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineModuleInfo.h" -#include "llvm/Support/Dwarf.h" -#include "llvm/Target/TargetAsmInfo.h" +#include "llvm/MC/MCAsmInfo.h" #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetFrameInfo.h" #include "llvm/Target/TargetRegisterInfo.h" - +#include "llvm/Support/Dwarf.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/ADT/StringExtras.h" using namespace llvm; -Dwarf::Dwarf(raw_ostream &OS, AsmPrinter *A, const TargetAsmInfo *T, +Dwarf::Dwarf(raw_ostream &OS, AsmPrinter *A, const MCAsmInfo *T, const char *flavor) -: O(OS), Asm(A), TAI(T), TD(Asm->TM.getTargetData()), +: O(OS), Asm(A), MAI(T), TD(Asm->TM.getTargetData()), RI(Asm->TM.getRegisterInfo()), M(NULL), MF(NULL), MMI(NULL), SubprogramCount(0), Flavor(flavor), SetCounter(1) {} void Dwarf::PrintRelDirective(bool Force32Bit, bool isInSection) const { - if (isInSection && TAI->getDwarfSectionOffsetDirective()) - O << TAI->getDwarfSectionOffsetDirective(); + if (isInSection && MAI->getDwarfSectionOffsetDirective()) + O << MAI->getDwarfSectionOffsetDirective(); else if (Force32Bit || TD->getPointerSize() == sizeof(int32_t)) - O << TAI->getData32bitsDirective(); + O << MAI->getData32bitsDirective(); else - O << TAI->getData64bitsDirective(); + O << MAI->getData64bitsDirective(); } /// PrintLabelName - Print label name in form used by Dwarf writer. /// void Dwarf::PrintLabelName(const char *Tag, unsigned Number) const { - O << TAI->getPrivateGlobalPrefix() << Tag; + O << MAI->getPrivateGlobalPrefix() << Tag; if (Number) O << Number; } void Dwarf::PrintLabelName(const char *Tag, unsigned Number, const char *Suffix) const { - O << TAI->getPrivateGlobalPrefix() << Tag; + O << MAI->getPrivateGlobalPrefix() << Tag; if (Number) O << Number; O << Suffix; } @@ -65,13 +67,13 @@ void Dwarf::EmitReference(const char *Tag, unsigned Number, bool IsPCRelative, bool Force32Bit) const { PrintRelDirective(Force32Bit); PrintLabelName(Tag, Number); - if (IsPCRelative) O << "-" << TAI->getPCSymbol(); + if (IsPCRelative) O << "-" << MAI->getPCSymbol(); } void Dwarf::EmitReference(const std::string &Name, bool IsPCRelative, bool Force32Bit) const { PrintRelDirective(Force32Bit); O << Name; - if (IsPCRelative) O << "-" << TAI->getPCSymbol(); + if (IsPCRelative) O << "-" << MAI->getPCSymbol(); } /// EmitDifference - Emit the difference between two labels. Some assemblers do @@ -80,7 +82,7 @@ void Dwarf::EmitReference(const std::string &Name, bool IsPCRelative, void Dwarf::EmitDifference(const char *TagHi, unsigned NumberHi, const char *TagLo, unsigned NumberLo, bool IsSmall) { - if (TAI->needsSet()) { + if (MAI->needsSet()) { O << "\t.set\t"; PrintLabelName("set", SetCounter, Flavor); O << ","; @@ -106,11 +108,11 @@ void Dwarf::EmitSectionOffset(const char* Label, const char* Section, bool useSet) { bool printAbsolute = false; if (isEH) - printAbsolute = TAI->isAbsoluteEHSectionOffsets(); + printAbsolute = MAI->isAbsoluteEHSectionOffsets(); else - printAbsolute = TAI->isAbsoluteDebugSectionOffsets(); + printAbsolute = MAI->isAbsoluteDebugSectionOffsets(); - if (TAI->needsSet() && useSet) { + if (MAI->needsSet() && useSet) { O << "\t.set\t"; PrintLabelName("set", SetCounter, Flavor); O << ","; @@ -190,7 +192,7 @@ void Dwarf::EmitFrameMoves(const char *BaseLabel, unsigned BaseLabelID, Asm->EmitULEB128Bytes(Offset); Asm->EOL("Offset"); } else { - assert(0 && "Machine move not supported yet."); + llvm_unreachable("Machine move not supported yet."); } } else if (Src.isReg() && Src.getReg() == MachineLocation::VirtualFP) { @@ -200,7 +202,7 @@ void Dwarf::EmitFrameMoves(const char *BaseLabel, unsigned BaseLabelID, Asm->EmitULEB128Bytes(RI->getDwarfRegNum(Dst.getReg(), isEH)); Asm->EOL("Register"); } else { - assert(0 && "Machine move not supported yet."); + llvm_unreachable("Machine move not supported yet."); } } else { unsigned Reg = RI->getDwarfRegNum(Src.getReg(), isEH); diff --git a/lib/CodeGen/AsmPrinter/DwarfPrinter.h b/lib/CodeGen/AsmPrinter/DwarfPrinter.h index 6e75992..33ebb3b 100644 --- a/lib/CodeGen/AsmPrinter/DwarfPrinter.h +++ b/lib/CodeGen/AsmPrinter/DwarfPrinter.h @@ -25,7 +25,7 @@ namespace llvm { class MachineFunction; class MachineModuleInfo; class Module; - class TargetAsmInfo; + class MCAsmInfo; class TargetData; class TargetRegisterInfo; @@ -43,9 +43,9 @@ namespace llvm { /// AsmPrinter *Asm; - /// TAI - Target asm information. + /// MAI - Target asm information. /// - const TargetAsmInfo *TAI; + const MCAsmInfo *MAI; /// TD - Target data. /// @@ -80,7 +80,7 @@ namespace llvm { /// unsigned SetCounter; - Dwarf(raw_ostream &OS, AsmPrinter *A, const TargetAsmInfo *T, + Dwarf(raw_ostream &OS, AsmPrinter *A, const MCAsmInfo *T, const char *flavor); public: //===------------------------------------------------------------------===// @@ -88,7 +88,7 @@ namespace llvm { // const AsmPrinter *getAsm() const { return Asm; } MachineModuleInfo *getMMI() const { return MMI; } - const TargetAsmInfo *getTargetAsmInfo() const { return TAI; } + const MCAsmInfo *getMCAsmInfo() const { return MAI; } const TargetData *getTargetData() const { return TD; } void PrintRelDirective(bool Force32Bit = false, diff --git a/lib/CodeGen/AsmPrinter/DwarfWriter.cpp b/lib/CodeGen/AsmPrinter/DwarfWriter.cpp index 89084989..0638d35 100644 --- a/lib/CodeGen/AsmPrinter/DwarfWriter.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfWriter.cpp @@ -39,7 +39,7 @@ DwarfWriter::~DwarfWriter() { void DwarfWriter::BeginModule(Module *M, MachineModuleInfo *MMI, raw_ostream &OS, AsmPrinter *A, - const TargetAsmInfo *T) { + const MCAsmInfo *T) { DE = new DwarfException(OS, A, T); DD = new DwarfDebug(OS, A, T); DE->BeginModule(M, MMI); @@ -51,6 +51,8 @@ void DwarfWriter::BeginModule(Module *M, void DwarfWriter::EndModule() { DE->EndModule(); DD->EndModule(); + delete DD; DD = 0; + delete DE; DE = 0; } /// BeginFunction - Gather pre-function debug information. Assumes being @@ -75,18 +77,18 @@ void DwarfWriter::EndFunction(MachineFunction *MF) { /// label. Returns a unique label ID used to generate a label and provide /// correspondence to the source line list. unsigned DwarfWriter::RecordSourceLine(unsigned Line, unsigned Col, - DICompileUnit CU) { - return DD->RecordSourceLine(Line, Col, CU); + MDNode *Scope) { + return DD->RecordSourceLine(Line, Col, Scope); } /// RecordRegionStart - Indicate the start of a region. -unsigned DwarfWriter::RecordRegionStart(GlobalVariable *V) { - return DD->RecordRegionStart(V); +unsigned DwarfWriter::RecordRegionStart(MDNode *N) { + return DD->RecordRegionStart(N); } /// RecordRegionEnd - Indicate the end of a region. -unsigned DwarfWriter::RecordRegionEnd(GlobalVariable *V) { - return DD->RecordRegionEnd(V); +unsigned DwarfWriter::RecordRegionEnd(MDNode *N) { + return DD->RecordRegionEnd(N); } /// getRecordSourceLineCount - Count source lines. @@ -96,9 +98,8 @@ unsigned DwarfWriter::getRecordSourceLineCount() { /// RecordVariable - Indicate the declaration of a local variable. /// -void DwarfWriter::RecordVariable(GlobalVariable *GV, unsigned FrameIndex, - const MachineInstr *MI) { - DD->RecordVariable(GV, FrameIndex, MI); +void DwarfWriter::RecordVariable(MDNode *N, unsigned FrameIndex) { + DD->RecordVariable(N, FrameIndex); } /// ShouldEmitDwarfDebug - Returns true if Dwarf debugging declarations should @@ -107,8 +108,7 @@ bool DwarfWriter::ShouldEmitDwarfDebug() const { return DD && DD->ShouldEmitDwarfDebug(); } -//// RecordInlinedFnStart - Global variable GV is inlined at the location marked -//// by LabelID label. +//// RecordInlinedFnStart unsigned DwarfWriter::RecordInlinedFnStart(DISubprogram SP, DICompileUnit CU, unsigned Line, unsigned Col) { return DD->RecordInlinedFnStart(SP, CU, Line, Col); @@ -119,9 +119,9 @@ unsigned DwarfWriter::RecordInlinedFnEnd(DISubprogram SP) { return DD->RecordInlinedFnEnd(SP); } -/// RecordVariableScope - Record scope for the variable declared by -/// DeclareMI. DeclareMI must describe TargetInstrInfo::DECLARE. -void DwarfWriter::RecordVariableScope(DIVariable &DV, - const MachineInstr *DeclareMI) { - DD->RecordVariableScope(DV, DeclareMI); +void DwarfWriter::SetDbgScopeBeginLabels(const MachineInstr *MI, unsigned L) { + DD->SetDbgScopeEndLabels(MI, L); +} +void DwarfWriter::SetDbgScopeEndLabels(const MachineInstr *MI, unsigned L) { + DD->SetDbgScopeBeginLabels(MI, L); } diff --git a/lib/CodeGen/AsmPrinter/OcamlGCPrinter.cpp b/lib/CodeGen/AsmPrinter/OcamlGCPrinter.cpp index 8ba903a..06b92b7 100644 --- a/lib/CodeGen/AsmPrinter/OcamlGCPrinter.cpp +++ b/lib/CodeGen/AsmPrinter/OcamlGCPrinter.cpp @@ -15,12 +15,14 @@ #include "llvm/CodeGen/AsmPrinter.h" #include "llvm/CodeGen/GCMetadataPrinter.h" #include "llvm/Module.h" -#include "llvm/Support/Compiler.h" -#include "llvm/Support/raw_ostream.h" -#include "llvm/Target/TargetAsmInfo.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCAsmInfo.h" #include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetLoweringObjectFile.h" #include "llvm/Target/TargetMachine.h" - +#include "llvm/Support/Compiler.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" using namespace llvm; namespace { @@ -28,10 +30,10 @@ namespace { class VISIBILITY_HIDDEN OcamlGCMetadataPrinter : public GCMetadataPrinter { public: void beginAssembly(raw_ostream &OS, AsmPrinter &AP, - const TargetAsmInfo &TAI); + const MCAsmInfo &MAI); void finishAssembly(raw_ostream &OS, AsmPrinter &AP, - const TargetAsmInfo &TAI); + const MCAsmInfo &MAI); }; } @@ -42,11 +44,11 @@ Y("ocaml", "ocaml 3.10-compatible collector"); void llvm::linkOcamlGCPrinter() { } static void EmitCamlGlobal(const Module &M, raw_ostream &OS, AsmPrinter &AP, - const TargetAsmInfo &TAI, const char *Id) { + const MCAsmInfo &MAI, const char *Id) { const std::string &MId = M.getModuleIdentifier(); std::string Mangled; - Mangled += TAI.getGlobalPrefix(); + Mangled += MAI.getGlobalPrefix(); Mangled += "caml"; size_t Letter = Mangled.size(); Mangled.append(MId.begin(), std::find(MId.begin(), MId.end(), '.')); @@ -56,18 +58,18 @@ static void EmitCamlGlobal(const Module &M, raw_ostream &OS, AsmPrinter &AP, // Capitalize the first letter of the module name. Mangled[Letter] = toupper(Mangled[Letter]); - if (const char *GlobalDirective = TAI.getGlobalDirective()) + if (const char *GlobalDirective = MAI.getGlobalDirective()) OS << GlobalDirective << Mangled << "\n"; OS << Mangled << ":\n"; } void OcamlGCMetadataPrinter::beginAssembly(raw_ostream &OS, AsmPrinter &AP, - const TargetAsmInfo &TAI) { - AP.SwitchToSection(TAI.getTextSection()); - EmitCamlGlobal(getModule(), OS, AP, TAI, "code_begin"); + const MCAsmInfo &MAI) { + AP.OutStreamer.SwitchSection(AP.getObjFileLowering().getTextSection()); + EmitCamlGlobal(getModule(), OS, AP, MAI, "code_begin"); - AP.SwitchToSection(TAI.getDataSection()); - EmitCamlGlobal(getModule(), OS, AP, TAI, "data_begin"); + AP.OutStreamer.SwitchSection(AP.getObjFileLowering().getDataSection()); + EmitCamlGlobal(getModule(), OS, AP, MAI, "data_begin"); } /// emitAssembly - Print the frametable. The ocaml frametable format is thus: @@ -87,55 +89,59 @@ void OcamlGCMetadataPrinter::beginAssembly(raw_ostream &OS, AsmPrinter &AP, /// either condition is detected in a function which uses the GC. /// void OcamlGCMetadataPrinter::finishAssembly(raw_ostream &OS, AsmPrinter &AP, - const TargetAsmInfo &TAI) { + const MCAsmInfo &MAI) { const char *AddressDirective; int AddressAlignLog; if (AP.TM.getTargetData()->getPointerSize() == sizeof(int32_t)) { - AddressDirective = TAI.getData32bitsDirective(); + AddressDirective = MAI.getData32bitsDirective(); AddressAlignLog = 2; } else { - AddressDirective = TAI.getData64bitsDirective(); + AddressDirective = MAI.getData64bitsDirective(); AddressAlignLog = 3; } - AP.SwitchToSection(TAI.getTextSection()); - EmitCamlGlobal(getModule(), OS, AP, TAI, "code_end"); + AP.OutStreamer.SwitchSection(AP.getObjFileLowering().getTextSection()); + EmitCamlGlobal(getModule(), OS, AP, MAI, "code_end"); - AP.SwitchToSection(TAI.getDataSection()); - EmitCamlGlobal(getModule(), OS, AP, TAI, "data_end"); + AP.OutStreamer.SwitchSection(AP.getObjFileLowering().getDataSection()); + EmitCamlGlobal(getModule(), OS, AP, MAI, "data_end"); OS << AddressDirective << 0; // FIXME: Why does ocaml emit this?? AP.EOL(); - AP.SwitchToSection(TAI.getDataSection()); - EmitCamlGlobal(getModule(), OS, AP, TAI, "frametable"); + AP.OutStreamer.SwitchSection(AP.getObjFileLowering().getDataSection()); + EmitCamlGlobal(getModule(), OS, AP, MAI, "frametable"); for (iterator I = begin(), IE = end(); I != IE; ++I) { GCFunctionInfo &FI = **I; uint64_t FrameSize = FI.getFrameSize(); if (FrameSize >= 1<<16) { - cerr << "Function '" << FI.getFunction().getNameStart() + std::string msg; + raw_string_ostream Msg(msg); + Msg << "Function '" << FI.getFunction().getName() << "' is too large for the ocaml GC! " << "Frame size " << FrameSize << " >= 65536.\n"; - cerr << "(" << uintptr_t(&FI) << ")\n"; - abort(); // Very rude! + Msg << "(" << uintptr_t(&FI) << ")"; + llvm_report_error(Msg.str()); // Very rude! } - OS << "\t" << TAI.getCommentString() << " live roots for " - << FI.getFunction().getNameStart() << "\n"; + OS << "\t" << MAI.getCommentString() << " live roots for " + << FI.getFunction().getName() << "\n"; for (GCFunctionInfo::iterator J = FI.begin(), JE = FI.end(); J != JE; ++J) { size_t LiveCount = FI.live_size(J); if (LiveCount >= 1<<16) { - cerr << "Function '" << FI.getFunction().getNameStart() + std::string msg; + raw_string_ostream Msg(msg); + Msg << "Function '" << FI.getFunction().getName() << "' is too large for the ocaml GC! " - << "Live root count " << LiveCount << " >= 65536.\n"; - abort(); // Very rude! + << "Live root count " << LiveCount << " >= 65536."; + llvm_report_error(Msg.str()); // Very rude! } OS << AddressDirective - << TAI.getPrivateGlobalPrefix() << "label" << J->Num; + << MAI.getPrivateGlobalPrefix() << "label" << J->Num; AP.EOL("call return address"); AP.EmitInt16(FrameSize); |