diff options
Diffstat (limited to 'lib/CodeGen/AsmPrinter')
-rw-r--r-- | lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 730 | ||||
-rw-r--r-- | lib/CodeGen/AsmPrinter/DIE.cpp | 1 | ||||
-rw-r--r-- | lib/CodeGen/AsmPrinter/DwarfDebug.cpp | 104 | ||||
-rw-r--r-- | lib/CodeGen/AsmPrinter/DwarfDebug.h | 8 | ||||
-rw-r--r-- | lib/CodeGen/AsmPrinter/DwarfException.cpp | 195 | ||||
-rw-r--r-- | lib/CodeGen/AsmPrinter/DwarfException.h | 9 | ||||
-rw-r--r-- | lib/CodeGen/AsmPrinter/DwarfPrinter.cpp | 70 | ||||
-rw-r--r-- | lib/CodeGen/AsmPrinter/DwarfPrinter.h | 17 | ||||
-rw-r--r-- | lib/CodeGen/AsmPrinter/DwarfWriter.cpp | 4 | ||||
-rw-r--r-- | lib/CodeGen/AsmPrinter/Makefile | 1 |
10 files changed, 649 insertions, 490 deletions
diff --git a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index f4d886492c53d..fc0838459388b 100644 --- a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -11,6 +11,7 @@ // //===----------------------------------------------------------------------===// +#define DEBUG_TYPE "asm-printer" #include "llvm/CodeGen/AsmPrinter.h" #include "llvm/Assembly/Writer.h" #include "llvm/DerivedTypes.h" @@ -24,6 +25,7 @@ #include "llvm/CodeGen/MachineJumpTableInfo.h" #include "llvm/CodeGen/MachineLoopInfo.h" #include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/Analysis/ConstantFolding.h" #include "llvm/Analysis/DebugInfo.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCExpr.h" @@ -31,10 +33,6 @@ #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/Format.h" -#include "llvm/Support/FormattedStream.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/Target/Mangler.h" #include "llvm/Target/TargetData.h" @@ -45,37 +43,27 @@ #include "llvm/Target/TargetRegisterInfo.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallString.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/Format.h" +#include "llvm/Support/FormattedStream.h" #include <cerrno> using namespace llvm; -static cl::opt<cl::boolOrDefault> -AsmVerbose("asm-verbose", cl::desc("Add comments to directives."), - cl::init(cl::BOU_UNSET)); - -static bool getVerboseAsm(bool VDef) { - switch (AsmVerbose) { - default: - case cl::BOU_UNSET: return VDef; - case cl::BOU_TRUE: return true; - case cl::BOU_FALSE: return false; - } -} +STATISTIC(EmittedInsts, "Number of machine instrs printed"); char AsmPrinter::ID = 0; AsmPrinter::AsmPrinter(formatted_raw_ostream &o, TargetMachine &tm, - const MCAsmInfo *T, bool VDef) - : MachineFunctionPass(&ID), FunctionNumber(0), O(o), + MCContext &Ctx, MCStreamer &Streamer, + const MCAsmInfo *T) + : MachineFunctionPass(&ID), O(o), TM(tm), MAI(T), TRI(tm.getRegisterInfo()), - - OutContext(*new MCContext()), - // FIXME: Pass instprinter to streamer. - OutStreamer(*createAsmStreamer(OutContext, O, *T, - TM.getTargetData()->isLittleEndian(), - getVerboseAsm(VDef), 0)), - + OutContext(Ctx), OutStreamer(Streamer), LastMI(0), LastFn(0), Counter(~0U), PrevDLT(NULL) { DW = 0; MMI = 0; - VerboseAsm = getVerboseAsm(VDef); + VerboseAsm = Streamer.isVerboseAsm(); } AsmPrinter::~AsmPrinter() { @@ -87,6 +75,12 @@ AsmPrinter::~AsmPrinter() { delete &OutContext; } +/// getFunctionNumber - Return a unique ID for the current function. +/// +unsigned AsmPrinter::getFunctionNumber() const { + return MF->getFunctionNumber(); +} + TargetLoweringObjectFile &AsmPrinter::getObjFileLowering() const { return TM.getTargetLowering()->getObjFileLowering(); } @@ -115,11 +109,11 @@ bool AsmPrinter::doInitialization(Module &M) { // Allow the target to emit any magic that it wants at the start of the file. EmitStartOfAsmFile(M); + // Very minimal debug info. It is ignored if we emit actual debug info. If we + // don't, this at least helps the user find where a global came from. if (MAI->hasSingleParameterDotFile()) { - // Very minimal debug info. It is ignored if we emit actual - // 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"; + // .file "foo.c" + OutStreamer.EmitFileDirective(M.getModuleIdentifier()); } GCModuleInfo *MI = getAnalysisIfAvailable<GCModuleInfo>(); @@ -144,6 +138,52 @@ bool AsmPrinter::doInitialization(Module &M) { return false; } +void AsmPrinter::EmitLinkage(unsigned Linkage, MCSymbol *GVSym) const { + switch ((GlobalValue::LinkageTypes)Linkage) { + case GlobalValue::CommonLinkage: + case GlobalValue::LinkOnceAnyLinkage: + case GlobalValue::LinkOnceODRLinkage: + case GlobalValue::WeakAnyLinkage: + case GlobalValue::WeakODRLinkage: + case GlobalValue::LinkerPrivateLinkage: + if (MAI->getWeakDefDirective() != 0) { + // .globl _foo + OutStreamer.EmitSymbolAttribute(GVSym, MCSA_Global); + // .weak_definition _foo + OutStreamer.EmitSymbolAttribute(GVSym, MCSA_WeakDefinition); + } else if (const char *LinkOnce = MAI->getLinkOnceDirective()) { + // .globl _foo + OutStreamer.EmitSymbolAttribute(GVSym, MCSA_Global); + // FIXME: linkonce should be a section attribute, handled by COFF Section + // assignment. + // http://sourceware.org/binutils/docs-2.20/as/Linkonce.html#Linkonce + // .linkonce discard + // FIXME: It would be nice to use .linkonce samesize for non-common + // globals. + O << LinkOnce; + } else { + // .weak _foo + OutStreamer.EmitSymbolAttribute(GVSym, MCSA_Weak); + } + break; + case GlobalValue::DLLExportLinkage: + case GlobalValue::AppendingLinkage: + // FIXME: appending linkage variables should go into a section of + // their name or something. For now, just emit them as external. + case GlobalValue::ExternalLinkage: + // If external or appending, declare as a global symbol. + // .globl _foo + OutStreamer.EmitSymbolAttribute(GVSym, MCSA_Global); + break; + case GlobalValue::PrivateLinkage: + case GlobalValue::InternalLinkage: + break; + default: + llvm_unreachable("Unknown linkage type!"); + } +} + + /// EmitGlobalVariable - Emit the specified global variable to the .s file. void AsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) { if (!GV->hasInitializer()) // External globals require no code. @@ -154,15 +194,10 @@ void AsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) { return; MCSymbol *GVSym = GetGlobalValueSymbol(GV); - printVisibility(GVSym, GV->getVisibility()); + EmitVisibility(GVSym, GV->getVisibility()); - if (MAI->hasDotTypeDotSizeDirective()) { - O << "\t.type\t" << *GVSym; - if (MAI->getCommentString()[0] != '@') - O << ",@object\n"; - else - O << ",%object\n"; - } + if (MAI->hasDotTypeDotSizeDirective()) + OutStreamer.EmitSymbolAttribute(GVSym, MCSA_ELF_TypeObject); SectionKind GVKind = TargetLoweringObjectFile::getKindForGlobal(GV, TM); @@ -224,47 +259,9 @@ void AsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) { OutStreamer.SwitchSection(TheSection); - // TODO: Factor into an 'emit linkage' thing that is shared with function - // bodies. - switch (GV->getLinkage()) { - case GlobalValue::CommonLinkage: - case GlobalValue::LinkOnceAnyLinkage: - case GlobalValue::LinkOnceODRLinkage: - case GlobalValue::WeakAnyLinkage: - case GlobalValue::WeakODRLinkage: - case GlobalValue::LinkerPrivateLinkage: - if (MAI->getWeakDefDirective() != 0) { - // .globl _foo - OutStreamer.EmitSymbolAttribute(GVSym, MCSA_Global); - // .weak_definition _foo - OutStreamer.EmitSymbolAttribute(GVSym, MCSA_WeakDefinition); - } else if (const char *LinkOnce = MAI->getLinkOnceDirective()) { - // .globl _foo - OutStreamer.EmitSymbolAttribute(GVSym, MCSA_Global); - // .linkonce same_size - O << LinkOnce; - } else { - // .weak _foo - OutStreamer.EmitSymbolAttribute(GVSym, MCSA_Weak); - } - break; - case GlobalValue::DLLExportLinkage: - case GlobalValue::AppendingLinkage: - // FIXME: appending linkage variables should go into a section of - // their name or something. For now, just emit them as external. - case GlobalValue::ExternalLinkage: - // If external or appending, declare as a global symbol. - // .globl _foo - OutStreamer.EmitSymbolAttribute(GVSym, MCSA_Global); - break; - case GlobalValue::PrivateLinkage: - case GlobalValue::InternalLinkage: - break; - default: - llvm_unreachable("Unknown linkage type!"); - } - + EmitLinkage(GV->getLinkage(), GVSym); EmitAlignment(AlignLog, GV); + if (VerboseAsm) { WriteAsOperand(OutStreamer.GetCommentOS(), GV, /*PrintType=*/false, GV->getParent()); @@ -275,7 +272,185 @@ void AsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) { EmitGlobalConstant(GV->getInitializer()); if (MAI->hasDotTypeDotSizeDirective()) - O << "\t.size\t" << *GVSym << ", " << Size << '\n'; + // .size foo, 42 + OutStreamer.EmitELFSize(GVSym, MCConstantExpr::Create(Size, OutContext)); + + OutStreamer.AddBlankLine(); +} + +/// EmitFunctionHeader - This method emits the header for the current +/// function. +void AsmPrinter::EmitFunctionHeader() { + // Print out constants referenced by the function + EmitConstantPool(); + + // Print the 'header' of function. + const Function *F = MF->getFunction(); + + OutStreamer.SwitchSection(getObjFileLowering().SectionForGlobal(F, Mang, TM)); + EmitVisibility(CurrentFnSym, F->getVisibility()); + + EmitLinkage(F->getLinkage(), CurrentFnSym); + EmitAlignment(MF->getAlignment(), F); + + if (MAI->hasDotTypeDotSizeDirective()) + OutStreamer.EmitSymbolAttribute(CurrentFnSym, MCSA_ELF_TypeFunction); + + if (VerboseAsm) { + WriteAsOperand(OutStreamer.GetCommentOS(), F, + /*PrintType=*/false, F->getParent()); + OutStreamer.GetCommentOS() << '\n'; + } + + // Emit the CurrentFnSym. This is a virtual function to allow targets to + // do their wild and crazy things as required. + EmitFunctionEntryLabel(); + + // Add some workaround for linkonce linkage on Cygwin\MinGW. + if (MAI->getLinkOnceDirective() != 0 && + (F->hasLinkOnceLinkage() || F->hasWeakLinkage())) + // FIXME: What is this? + O << "Lllvm$workaround$fake$stub$" << *CurrentFnSym << ":\n"; + + // Emit pre-function debug and/or EH information. + if (MAI->doesSupportDebugInformation() || MAI->doesSupportExceptionHandling()) + DW->BeginFunction(MF); +} + +/// EmitFunctionEntryLabel - Emit the label that is the entrypoint for the +/// function. This can be overridden by targets as required to do custom stuff. +void AsmPrinter::EmitFunctionEntryLabel() { + OutStreamer.EmitLabel(CurrentFnSym); +} + + +/// EmitComments - Pretty-print comments for instructions. +static void EmitComments(const MachineInstr &MI, raw_ostream &CommentOS) { + const MachineFunction *MF = MI.getParent()->getParent(); + const TargetMachine &TM = MF->getTarget(); + + if (!MI.getDebugLoc().isUnknown()) { + DILocation DLT = MF->getDILocation(MI.getDebugLoc()); + + // Print source line info. + DIScope Scope = DLT.getScope(); + // Omit the directory, because it's likely to be long and uninteresting. + if (!Scope.isNull()) + CommentOS << Scope.getFilename(); + else + CommentOS << "<unknown>"; + CommentOS << ':' << DLT.getLineNumber(); + if (DLT.getColumnNumber() != 0) + CommentOS << ':' << DLT.getColumnNumber(); + CommentOS << '\n'; + } + + // Check for spills and reloads + int FI; + + const MachineFrameInfo *FrameInfo = MF->getFrameInfo(); + + // We assume a single instruction only has a spill or reload, not + // both. + const MachineMemOperand *MMO; + if (TM.getInstrInfo()->isLoadFromStackSlotPostFE(&MI, FI)) { + if (FrameInfo->isSpillSlotObjectIndex(FI)) { + MMO = *MI.memoperands_begin(); + CommentOS << MMO->getSize() << "-byte Reload\n"; + } + } else if (TM.getInstrInfo()->hasLoadFromStackSlot(&MI, MMO, FI)) { + if (FrameInfo->isSpillSlotObjectIndex(FI)) + CommentOS << MMO->getSize() << "-byte Folded Reload\n"; + } else if (TM.getInstrInfo()->isStoreToStackSlotPostFE(&MI, FI)) { + if (FrameInfo->isSpillSlotObjectIndex(FI)) { + MMO = *MI.memoperands_begin(); + CommentOS << MMO->getSize() << "-byte Spill\n"; + } + } else if (TM.getInstrInfo()->hasStoreToStackSlot(&MI, MMO, FI)) { + if (FrameInfo->isSpillSlotObjectIndex(FI)) + CommentOS << MMO->getSize() << "-byte Folded Spill\n"; + } + + // Check for spill-induced copies + unsigned SrcReg, DstReg, SrcSubIdx, DstSubIdx; + if (TM.getInstrInfo()->isMoveInstr(MI, SrcReg, DstReg, + SrcSubIdx, DstSubIdx)) { + if (MI.getAsmPrinterFlag(MachineInstr::ReloadReuse)) + CommentOS << " Reload Reuse\n"; + } +} + + + +/// EmitFunctionBody - This method emits the body and trailer for a +/// function. +void AsmPrinter::EmitFunctionBody() { + // Emit target-specific gunk before the function body. + EmitFunctionBodyStart(); + + // Print out code for the function. + bool HasAnyRealCode = false; + for (MachineFunction::const_iterator I = MF->begin(), E = MF->end(); + I != E; ++I) { + // Print a label for the basic block. + EmitBasicBlockStart(I); + for (MachineBasicBlock::const_iterator II = I->begin(), IE = I->end(); + II != IE; ++II) { + // Print the assembly for the instruction. + if (!II->isLabel()) + HasAnyRealCode = true; + + ++EmittedInsts; + + // FIXME: Clean up processDebugLoc. + processDebugLoc(II, true); + + if (VerboseAsm) + EmitComments(*II, OutStreamer.GetCommentOS()); + + switch (II->getOpcode()) { + case TargetOpcode::DBG_LABEL: + case TargetOpcode::EH_LABEL: + case TargetOpcode::GC_LABEL: + printLabelInst(II); + break; + case TargetOpcode::INLINEASM: + printInlineAsm(II); + break; + case TargetOpcode::IMPLICIT_DEF: + printImplicitDef(II); + break; + case TargetOpcode::KILL: + printKill(II); + break; + default: + EmitInstruction(II); + break; + } + + // FIXME: Clean up processDebugLoc. + processDebugLoc(II, false); + } + } + + // If the function is empty and the object file uses .subsections_via_symbols, + // then we need to emit *something* to the function body to prevent the + // labels from collapsing together. Just emit a 0 byte. + if (MAI->hasSubsectionsViaSymbols() && !HasAnyRealCode) + OutStreamer.EmitIntValue(0, 1, 0/*addrspace*/); + + // Emit target-specific gunk after the function body. + EmitFunctionBodyEnd(); + + if (MAI->hasDotTypeDotSizeDirective()) + O << "\t.size\t" << *CurrentFnSym << ", .-" << *CurrentFnSym << '\n'; + + // Emit post-function debug information. + if (MAI->doesSupportDebugInformation() || MAI->doesSupportExceptionHandling()) + DW->EndFunction(MF); + + // Print out jump tables referenced by the function. + EmitJumpTableInfo(); OutStreamer.AddBlankLine(); } @@ -313,7 +488,7 @@ bool AsmPrinter::doFinalization(Module &M) { } } - if (MAI->getSetDirective()) { + if (MAI->hasSetDirective()) { OutStreamer.AddBlankLine(); for (Module::const_alias_iterator I = M.alias_begin(), E = M.alias_end(); I != E; ++I) { @@ -329,9 +504,11 @@ bool AsmPrinter::doFinalization(Module &M) { else assert(I->hasLocalLinkage() && "Invalid alias linkage"); - printVisibility(Name, I->getVisibility()); + EmitVisibility(Name, I->getVisibility()); - O << MAI->getSetDirective() << ' ' << *Name << ", " << *Target << '\n'; + // Emit the directives as assignments aka .set: + OutStreamer.EmitAssignment(Name, + MCSymbolRefExpr::Create(Target, OutContext)); } } @@ -360,9 +537,9 @@ bool AsmPrinter::doFinalization(Module &M) { } void AsmPrinter::SetupMachineFunction(MachineFunction &MF) { + this->MF = &MF; // Get the function symbol. CurrentFnSym = GetGlobalValueSymbol(MF.getFunction()); - IncrementFunctionNumber(); if (VerboseAsm) LI = &getAnalysis<MachineLoopInfo>(); @@ -383,7 +560,8 @@ namespace { /// used to print out constants which have been "spilled to memory" by /// the code generator. /// -void AsmPrinter::EmitConstantPool(MachineConstantPool *MCP) { +void AsmPrinter::EmitConstantPool() { + const MachineConstantPool *MCP = MF->getConstantPool(); const std::vector<MachineConstantPoolEntry> &CP = MCP->getConstants(); if (CP.empty()) return; @@ -470,27 +648,26 @@ void AsmPrinter::EmitConstantPool(MachineConstantPool *MCP) { /// EmitJumpTableInfo - Print assembly representations of the jump tables used /// by the current function to the current output stream. /// -void AsmPrinter::EmitJumpTableInfo(MachineJumpTableInfo *MJTI, - MachineFunction &MF) { +void AsmPrinter::EmitJumpTableInfo() { + const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo(); + if (MJTI == 0) return; const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables(); if (JT.empty()) return; - bool IsPic = TM.getRelocationModel() == Reloc::PIC_; - // Pick the directive to use to print the jump table entries, and switch to // the appropriate section. - TargetLowering *LoweringInfo = TM.getTargetLowering(); - - const Function *F = MF.getFunction(); + const Function *F = MF->getFunction(); bool JTInDiffSection = false; - 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. - OutStreamer.SwitchSection(getObjFileLowering().SectionForGlobal(F, Mang, - TM)); + if (// 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. + // FIXME: Need a better predicate for this: what about custom entries? + MJTI->getEntryKind() == MachineJumpTableInfo::EK_LabelDifference32 || + // We should also do if the section name is NULL or function is declared + // in discardable section + // FIXME: this isn't the right predicate, should be based on the MCSection + // for the function. + F->isWeakForLinker()) { + OutStreamer.SwitchSection(getObjFileLowering().SectionForGlobal(F,Mang,TM)); } else { // Otherwise, drop it in the readonly section. const MCSection *ReadOnlySection = @@ -498,73 +675,106 @@ void AsmPrinter::EmitJumpTableInfo(MachineJumpTableInfo *MJTI, OutStreamer.SwitchSection(ReadOnlySection); JTInDiffSection = true; } + + EmitAlignment(Log2_32(MJTI->getEntryAlignment(*TM.getTargetData()))); - EmitAlignment(Log2_32(MJTI->getAlignment())); - - for (unsigned i = 0, e = JT.size(); i != e; ++i) { - const std::vector<MachineBasicBlock*> &JTBBs = JT[i].MBBs; + for (unsigned JTI = 0, e = JT.size(); JTI != e; ++JTI) { + const std::vector<MachineBasicBlock*> &JTBBs = JT[JTI].MBBs; // If this jump table was deleted, ignore it. if (JTBBs.empty()) continue; - // For PIC codegen, if possible we want to use the SetDirective to reduce - // 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 (MAI->getSetDirective() && IsPic) - for (unsigned ii = 0, ee = JTBBs.size(); ii != ee; ++ii) - if (EmittedSets.insert(JTBBs[ii])) - printPICJumpTableSetLabel(i, JTBBs[ii]); + // For the EK_LabelDifference32 entry, if the target supports .set, emit a + // .set directive for each unique entry. This reduces the number of + // relocations the assembler will generate for the jump table. + if (MJTI->getEntryKind() == MachineJumpTableInfo::EK_LabelDifference32 && + MAI->hasSetDirective()) { + SmallPtrSet<const MachineBasicBlock*, 16> EmittedSets; + const TargetLowering *TLI = TM.getTargetLowering(); + const MCExpr *Base = TLI->getPICJumpTableRelocBaseExpr(MF,JTI,OutContext); + for (unsigned ii = 0, ee = JTBBs.size(); ii != ee; ++ii) { + const MachineBasicBlock *MBB = JTBBs[ii]; + if (!EmittedSets.insert(MBB)) continue; + + // .set LJTSet, LBB32-base + const MCExpr *LHS = + MCSymbolRefExpr::Create(MBB->getSymbol(OutContext), OutContext); + OutStreamer.EmitAssignment(GetJTSetSymbol(JTI, MBB->getNumber()), + MCBinaryExpr::CreateSub(LHS, Base, OutContext)); + } + } // 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 && MAI->getLinkerPrivateGlobalPrefix()[0]) - OutStreamer.EmitLabel(GetJTISymbol(i, true)); + // FIXME: This doesn't have to have any specific name, just any randomly + // named and numbered 'l' label would work. Simplify GetJTISymbol. + OutStreamer.EmitLabel(GetJTISymbol(JTI, true)); - OutStreamer.EmitLabel(GetJTISymbol(i)); + OutStreamer.EmitLabel(GetJTISymbol(JTI)); - for (unsigned ii = 0, ee = JTBBs.size(); ii != ee; ++ii) { - printPICJumpTableEntry(MJTI, JTBBs[ii], i); - O << '\n'; - } + for (unsigned ii = 0, ee = JTBBs.size(); ii != ee; ++ii) + EmitJumpTableEntry(MJTI, JTBBs[ii], JTI); } } -void AsmPrinter::printPICJumpTableEntry(const MachineJumpTableInfo *MJTI, - const MachineBasicBlock *MBB, - unsigned uid) const { - bool isPIC = TM.getRelocationModel() == Reloc::PIC_; - - // Use JumpTableDirective otherwise honor the entry size from the jump table - // info. - const char *JTEntryDirective = MAI->getJumpTableDirective(isPIC); - bool HadJTEntryDirective = JTEntryDirective != NULL; - if (!HadJTEntryDirective) { - JTEntryDirective = MJTI->getEntrySize() == 4 ? - MAI->getData32bitsDirective() : MAI->getData64bitsDirective(); +/// EmitJumpTableEntry - Emit a jump table entry for the specified MBB to the +/// current stream. +void AsmPrinter::EmitJumpTableEntry(const MachineJumpTableInfo *MJTI, + const MachineBasicBlock *MBB, + unsigned UID) const { + const MCExpr *Value = 0; + switch (MJTI->getEntryKind()) { + case MachineJumpTableInfo::EK_Custom32: + Value = TM.getTargetLowering()->LowerCustomJumpTableEntry(MJTI, MBB, UID, + OutContext); + break; + case MachineJumpTableInfo::EK_BlockAddress: + // EK_BlockAddress - Each entry is a plain address of block, e.g.: + // .word LBB123 + Value = MCSymbolRefExpr::Create(MBB->getSymbol(OutContext), OutContext); + break; + case MachineJumpTableInfo::EK_GPRel32BlockAddress: { + // EK_GPRel32BlockAddress - Each entry is an address of block, encoded + // with a relocation as gp-relative, e.g.: + // .gprel32 LBB123 + MCSymbol *MBBSym = MBB->getSymbol(OutContext); + OutStreamer.EmitGPRel32Value(MCSymbolRefExpr::Create(MBBSym, OutContext)); + return; } - O << JTEntryDirective << ' '; - - // If we have emitted set directives for the jump table entries, print - // them rather than the entries themselves. If we're emitting PIC, then - // 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) { - O << *GetMBBSymbol(MBB->getNumber()); - } else if (MAI->getSetDirective()) { - O << MAI->getPrivateGlobalPrefix() << getFunctionNumber() - << '_' << uid << "_set_" << MBB->getNumber(); - } else { - O << *GetMBBSymbol(MBB->getNumber()); - // If the arch uses custom Jump Table directives, don't calc relative to - // JT. - if (!HadJTEntryDirective) - O << '-' << *GetJTISymbol(uid); + case MachineJumpTableInfo::EK_LabelDifference32: { + // EK_LabelDifference32 - Each entry is the address of the block minus + // the address of the jump table. This is used for PIC jump tables where + // gprel32 is not supported. e.g.: + // .word LBB123 - LJTI1_2 + // If the .set directive is supported, this is emitted as: + // .set L4_5_set_123, LBB123 - LJTI1_2 + // .word L4_5_set_123 + + // If we have emitted set directives for the jump table entries, print + // them rather than the entries themselves. If we're emitting PIC, then + // emit the table entries as differences between two text section labels. + if (MAI->hasSetDirective()) { + // If we used .set, reference the .set's symbol. + Value = MCSymbolRefExpr::Create(GetJTSetSymbol(UID, MBB->getNumber()), + OutContext); + break; + } + // Otherwise, use the difference as the jump table entry. + Value = MCSymbolRefExpr::Create(MBB->getSymbol(OutContext), OutContext); + const MCExpr *JTI = MCSymbolRefExpr::Create(GetJTISymbol(UID), OutContext); + Value = MCBinaryExpr::CreateSub(Value, JTI, OutContext); + break; + } } + + assert(Value && "Unknown entry kind!"); + + unsigned EntrySize = MJTI->getEntrySize(*TM.getTargetData()); + OutStreamer.EmitValue(Value, EntrySize, /*addrspace*/0); } @@ -683,48 +893,6 @@ void AsmPrinter::EmitInt64(uint64_t Value) const { OutStreamer.EmitIntValue(Value, 8, 0/*addrspace*/); } - -/// toOctal - Convert the low order bits of X into an octal digit. -/// -static inline char toOctal(int X) { - return (X&7)+'0'; -} - -/// printStringChar - Print a char, escaped if necessary. -/// -static void printStringChar(formatted_raw_ostream &O, unsigned char C) { - if (C == '"') { - O << "\\\""; - } else if (C == '\\') { - O << "\\\\"; - } else if (isprint((unsigned char)C)) { - O << C; - } else { - switch(C) { - case '\b': O << "\\b"; break; - case '\f': O << "\\f"; break; - case '\n': O << "\\n"; break; - case '\r': O << "\\r"; break; - case '\t': O << "\\t"; break; - default: - O << '\\'; - O << toOctal(C >> 6); - O << toOctal(C >> 3); - O << toOctal(C >> 0); - break; - } - } -} - -/// EmitFile - Emit a .file directive. -void AsmPrinter::EmitFile(unsigned Number, StringRef Name) const { - O << "\t.file\t" << Number << " \""; - for (unsigned i = 0, N = Name.size(); i < N; ++i) - printStringChar(O, Name[i]); - O << '\"'; -} - - //===----------------------------------------------------------------------===// // EmitAlignment - Emit an alignment directive to the specified power of @@ -779,15 +947,18 @@ static const MCExpr *LowerConstant(const Constant *CV, AsmPrinter &AP) { } switch (CE->getOpcode()) { - case Instruction::ZExt: - case Instruction::SExt: - case Instruction::FPTrunc: - case Instruction::FPExt: - case Instruction::UIToFP: - case Instruction::SIToFP: - case Instruction::FPToUI: - case Instruction::FPToSI: - default: llvm_unreachable("FIXME: Don't support this constant cast expr"); + default: + // If the code isn't optimized, there may be outstanding folding + // opportunities. Attempt to fold the expression using TargetData as a + // last resort before giving up. + if (Constant *C = + ConstantFoldConstantExpression(CE, AP.TM.getTargetData())) + if (C != CE) + return LowerConstant(C, AP); +#ifndef NDEBUG + CE->dump(); +#endif + llvm_unreachable("FIXME: Don't support this constant expr"); case Instruction::GetElementPtr: { const TargetData &TD = *AP.TM.getTargetData(); // Generate a symbolic expression for the byte address @@ -851,8 +1022,14 @@ static const MCExpr *LowerConstant(const Constant *CV, AsmPrinter &AP) { return MCBinaryExpr::CreateAnd(OpExpr, MaskExpr, Ctx); } + // The MC library also has a right-shift operator, but it isn't consistently + // signed or unsigned between different targets. case Instruction::Add: case Instruction::Sub: + case Instruction::Mul: + case Instruction::SDiv: + case Instruction::SRem: + case Instruction::Shl: case Instruction::And: case Instruction::Or: case Instruction::Xor: { @@ -862,6 +1039,10 @@ static const MCExpr *LowerConstant(const Constant *CV, AsmPrinter &AP) { default: llvm_unreachable("Unknown binary operator constant cast expr"); case Instruction::Add: return MCBinaryExpr::CreateAdd(LHS, RHS, Ctx); case Instruction::Sub: return MCBinaryExpr::CreateSub(LHS, RHS, Ctx); + case Instruction::Mul: return MCBinaryExpr::CreateMul(LHS, RHS, Ctx); + case Instruction::SDiv: return MCBinaryExpr::CreateDiv(LHS, RHS, Ctx); + case Instruction::SRem: return MCBinaryExpr::CreateMod(LHS, RHS, Ctx); + case Instruction::Shl: return MCBinaryExpr::CreateShl(LHS, RHS, Ctx); case Instruction::And: return MCBinaryExpr::CreateAnd(LHS, RHS, Ctx); case Instruction::Or: return MCBinaryExpr::CreateOr (LHS, RHS, Ctx); case Instruction::Xor: return MCBinaryExpr::CreateXor(LHS, RHS, Ctx); @@ -1012,6 +1193,7 @@ static void EmitGlobalConstantLargeInt(const ConstantInt *CI, void AsmPrinter::EmitGlobalConstant(const Constant *CV, unsigned AddrSpace) { if (isa<ConstantAggregateZero>(CV) || isa<UndefValue>(CV)) { uint64_t Size = TM.getTargetData()->getTypeAllocSize(CV->getType()); + if (Size == 0) Size = 1; // An empty "_foo:" followed by a section is undef. return OutStreamer.EmitZeros(Size, AddrSpace); } @@ -1295,7 +1477,7 @@ void AsmPrinter::printInlineAsm(const MachineInstr *MI) const { ++OpNo; // Skip over the ID number. if (Modifier[0] == 'l') // labels are target independent - O << *GetMBBSymbol(MI->getOperand(OpNo).getMBB()->getNumber()); + O << *MI->getOperand(OpNo).getMBB()->getSymbol(OutContext); else { AsmPrinter *AP = const_cast<AsmPrinter*>(this); if ((OpFlags & 7) == 4) { @@ -1320,6 +1502,7 @@ void AsmPrinter::printInlineAsm(const MachineInstr *MI) const { } } O << "\n\t" << MAI->getCommentString() << MAI->getInlineAsmEnd(); + OutStreamer.AddBlankLine(); } /// printImplicitDef - This method prints the specified machine instruction @@ -1329,6 +1512,7 @@ void AsmPrinter::printImplicitDef(const MachineInstr *MI) const { O.PadToColumn(MAI->getCommentColumn()); O << MAI->getCommentString() << " implicit-def: " << TRI->getName(MI->getOperand(0).getReg()); + OutStreamer.AddBlankLine(); } void AsmPrinter::printKill(const MachineInstr *MI) const { @@ -1340,12 +1524,14 @@ void AsmPrinter::printKill(const MachineInstr *MI) const { assert(op.isReg() && "KILL instruction must have only register operands"); O << ' ' << TRI->getName(op.getReg()) << (op.isDef() ? "<def>" : "<kill>"); } + OutStreamer.AddBlankLine(); } /// printLabel - This method prints a local label used by debug and /// exception handling tables. -void AsmPrinter::printLabel(const MachineInstr *MI) const { +void AsmPrinter::printLabelInst(const MachineInstr *MI) const { printLabel(MI->getOperand(0).getImm()); + OutStreamer.AddBlankLine(); } void AsmPrinter::printLabel(unsigned Id) const { @@ -1368,14 +1554,12 @@ bool AsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, return true; } -MCSymbol *AsmPrinter::GetBlockAddressSymbol(const BlockAddress *BA, - const char *Suffix) const { - return GetBlockAddressSymbol(BA->getFunction(), BA->getBasicBlock(), Suffix); +MCSymbol *AsmPrinter::GetBlockAddressSymbol(const BlockAddress *BA) const { + return GetBlockAddressSymbol(BA->getFunction(), BA->getBasicBlock()); } MCSymbol *AsmPrinter::GetBlockAddressSymbol(const Function *F, - const BasicBlock *BB, - const char *Suffix) const { + const BasicBlock *BB) const { assert(BB->hasName() && "Address of anonymous basic block not supported yet!"); @@ -1389,19 +1573,12 @@ MCSymbol *AsmPrinter::GetBlockAddressSymbol(const Function *F, SmallString<60> NameResult; Mang->getNameWithPrefix(NameResult, StringRef("BA") + Twine((unsigned)FnName.size()) + - "_" + FnName.str() + "_" + BB->getName() + Suffix, + "_" + FnName.str() + "_" + BB->getName(), Mangler::Private); return OutContext.GetOrCreateSymbol(NameResult.str()); } -MCSymbol *AsmPrinter::GetMBBSymbol(unsigned MBBID) const { - SmallString<60> Name; - raw_svector_ostream(Name) << MAI->getPrivateGlobalPrefix() << "BB" - << getFunctionNumber() << '_' << MBBID; - return OutContext.GetOrCreateSymbol(Name.str()); -} - /// GetCPISymbol - Return the symbol for the specified constant pool entry. MCSymbol *AsmPrinter::GetCPISymbol(unsigned CPID) const { SmallString<60> Name; @@ -1412,11 +1589,15 @@ MCSymbol *AsmPrinter::GetCPISymbol(unsigned CPID) const { /// GetJTISymbol - Return the symbol for the specified jump table entry. MCSymbol *AsmPrinter::GetJTISymbol(unsigned JTID, bool isLinkerPrivate) const { - const char *Prefix = isLinkerPrivate ? MAI->getLinkerPrivateGlobalPrefix() : - MAI->getPrivateGlobalPrefix(); + return MF->getJTISymbol(JTID, OutContext, isLinkerPrivate); +} + +/// GetJTSetSymbol - Return the symbol for the specified jump table .set +/// FIXME: privatize to AsmPrinter. +MCSymbol *AsmPrinter::GetJTSetSymbol(unsigned UID, unsigned MBBID) const { SmallString<60> Name; - raw_svector_ostream(Name) << Prefix << "JTI" << getFunctionNumber() << '_' - << JTID; + raw_svector_ostream(Name) << MAI->getPrivateGlobalPrefix() + << getFunctionNumber() << '_' << UID << "_set_" << MBBID; return OutContext.GetOrCreateSymbol(Name.str()); } @@ -1476,7 +1657,7 @@ static void PrintChildLoopComment(raw_ostream &OS, const MachineLoop *Loop, } } -/// EmitComments - Pretty-print comments for basic blocks. +/// PrintBasicBlockLoopComments - Pretty-print comments for basic blocks. static void PrintBasicBlockLoopComments(const MachineBasicBlock &MBB, const MachineLoopInfo *LI, const AsmPrinter &AP) { @@ -1555,37 +1736,11 @@ void AsmPrinter::EmitBasicBlockStart(const MachineBasicBlock *MBB) const { PrintBasicBlockLoopComments(*MBB, LI, *this); } - OutStreamer.EmitLabel(GetMBBSymbol(MBB->getNumber())); + OutStreamer.EmitLabel(MBB->getSymbol(OutContext)); } } -/// 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 (!MAI->getSetDirective()) - return; - - O << MAI->getSetDirective() << ' ' << MAI->getPrivateGlobalPrefix() - << getFunctionNumber() << '_' << uid << "_set_" << MBB->getNumber() << ',' - << *GetMBBSymbol(MBB->getNumber()) - << '-' << *GetJTISymbol(uid) << '\n'; -} - -void AsmPrinter::printPICJumpTableSetLabel(unsigned uid, unsigned uid2, - const MachineBasicBlock *MBB) const { - if (!MAI->getSetDirective()) - return; - - O << MAI->getSetDirective() << ' ' << MAI->getPrivateGlobalPrefix() - << getFunctionNumber() << '_' << uid << '_' << uid2 - << "_set_" << MBB->getNumber() << ',' - << *GetMBBSymbol(MBB->getNumber()) - << '-' << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() - << '_' << uid << '_' << uid2 << '\n'; -} - -void AsmPrinter::printVisibility(MCSymbol *Sym, unsigned Visibility) const { +void AsmPrinter::EmitVisibility(MCSymbol *Sym, unsigned Visibility) const { MCSymbolAttr Attr = MCSA_Invalid; switch (Visibility) { @@ -1633,86 +1788,3 @@ GCMetadataPrinter *AsmPrinter::GetOrCreateGCPrinter(GCStrategy *S) { return 0; } -/// EmitComments - Pretty-print comments for instructions -void AsmPrinter::EmitComments(const MachineInstr &MI) const { - if (!VerboseAsm) - return; - - bool Newline = false; - - if (!MI.getDebugLoc().isUnknown()) { - DILocation DLT = MF->getDILocation(MI.getDebugLoc()); - - // Print source line info. - O.PadToColumn(MAI->getCommentColumn()); - O << MAI->getCommentString() << ' '; - DIScope Scope = DLT.getScope(); - // Omit the directory, because it's likely to be long and uninteresting. - if (!Scope.isNull()) - O << Scope.getFilename(); - else - O << "<unknown>"; - O << ':' << DLT.getLineNumber(); - if (DLT.getColumnNumber() != 0) - O << ':' << DLT.getColumnNumber(); - Newline = true; - } - - // Check for spills and reloads - int FI; - - const MachineFrameInfo *FrameInfo = - MI.getParent()->getParent()->getFrameInfo(); - - // We assume a single instruction only has a spill or reload, not - // both. - const MachineMemOperand *MMO; - if (TM.getInstrInfo()->isLoadFromStackSlotPostFE(&MI, FI)) { - if (FrameInfo->isSpillSlotObjectIndex(FI)) { - MMO = *MI.memoperands_begin(); - if (Newline) O << '\n'; - O.PadToColumn(MAI->getCommentColumn()); - O << MAI->getCommentString() << ' ' << MMO->getSize() << "-byte Reload"; - Newline = true; - } - } - else if (TM.getInstrInfo()->hasLoadFromStackSlot(&MI, MMO, FI)) { - if (FrameInfo->isSpillSlotObjectIndex(FI)) { - if (Newline) O << '\n'; - O.PadToColumn(MAI->getCommentColumn()); - O << MAI->getCommentString() << ' ' - << MMO->getSize() << "-byte Folded Reload"; - Newline = true; - } - } - else if (TM.getInstrInfo()->isStoreToStackSlotPostFE(&MI, FI)) { - if (FrameInfo->isSpillSlotObjectIndex(FI)) { - MMO = *MI.memoperands_begin(); - if (Newline) O << '\n'; - O.PadToColumn(MAI->getCommentColumn()); - O << MAI->getCommentString() << ' ' << MMO->getSize() << "-byte Spill"; - Newline = true; - } - } - else if (TM.getInstrInfo()->hasStoreToStackSlot(&MI, MMO, FI)) { - if (FrameInfo->isSpillSlotObjectIndex(FI)) { - if (Newline) O << '\n'; - O.PadToColumn(MAI->getCommentColumn()); - O << MAI->getCommentString() << ' ' - << MMO->getSize() << "-byte Folded Spill"; - Newline = true; - } - } - - // Check for spill-induced copies - unsigned SrcReg, DstReg, SrcSubIdx, DstSubIdx; - if (TM.getInstrInfo()->isMoveInstr(MI, SrcReg, DstReg, - SrcSubIdx, DstSubIdx)) { - if (MI.getAsmPrinterFlag(ReloadReuse)) { - if (Newline) O << '\n'; - O.PadToColumn(MAI->getCommentColumn()); - O << MAI->getCommentString() << " Reload Reuse"; - } - } -} - diff --git a/lib/CodeGen/AsmPrinter/DIE.cpp b/lib/CodeGen/AsmPrinter/DIE.cpp index 349e0ac40f1ed..63360c0892cc8 100644 --- a/lib/CodeGen/AsmPrinter/DIE.cpp +++ b/lib/CodeGen/AsmPrinter/DIE.cpp @@ -313,6 +313,7 @@ void DIESectionOffset::EmitValue(DwarfPrinter *D, unsigned Form) const { D->EmitSectionOffset(Label.getTag(), Section.getTag(), Label.getNumber(), Section.getNumber(), IsSmall, IsEH, UseSet); + D->getAsm()->O << '\n'; // FIXME: Necesssary? } /// SizeOf - Determine size of delta value in bytes. diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp index 513987f902037..5093dd9a9c11b 100644 --- a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -26,6 +26,7 @@ #include "llvm/ADT/StringExtras.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/ValueHandle.h" #include "llvm/Support/FormattedStream.h" #include "llvm/Support/Timer.h" #include "llvm/System/Path.h" @@ -166,7 +167,8 @@ public: class DbgScope { DbgScope *Parent; // Parent to this scope. DIDescriptor Desc; // Debug info descriptor for scope. - MDNode * InlinedAtLocation; // Location at which scope is inlined. + // Location at which this scope is inlined. + AssertingVH<MDNode> InlinedAtLocation; bool AbstractScope; // Abstract Scope unsigned StartLabelID; // Label ID of the beginning of scope. unsigned EndLabelID; // Label ID of the end of scope. @@ -189,7 +191,7 @@ public: void setParent(DbgScope *P) { Parent = P; } DIDescriptor getDesc() const { return Desc; } MDNode *getInlinedAt() const { - return dyn_cast_or_null<MDNode>(InlinedAtLocation); + return InlinedAtLocation; } MDNode *getScopeNode() const { return Desc.getNode(); } unsigned getStartLabelID() const { return StartLabelID; } @@ -616,7 +618,7 @@ void DwarfDebug::addComplexAddress(DbgVariable *&DV, DIE *Die, 1). Add the offset of the forwarding field. - 2). Follow that pointer to get the the real __Block_byref_x_VarName + 2). Follow that pointer to get 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. @@ -937,7 +939,16 @@ void DwarfDebug::constructTypeDIE(DIE &Buffer, DICompositeType CTy) { DIE *ElemDie = NULL; if (Element.getTag() == dwarf::DW_TAG_subprogram) ElemDie = createSubprogramDIE(DISubprogram(Element.getNode())); - else + else if (Element.getTag() == dwarf::DW_TAG_auto_variable) { + DIVariable DV(Element.getNode()); + ElemDie = new DIE(dwarf::DW_TAG_variable); + addString(ElemDie, dwarf::DW_AT_name, dwarf::DW_FORM_string, + DV.getName()); + addType(ElemDie, DV.getType()); + addUInt(ElemDie, dwarf::DW_AT_declaration, dwarf::DW_FORM_flag, 1); + addUInt(ElemDie, dwarf::DW_AT_external, dwarf::DW_FORM_flag, 1); + addSourceLine(ElemDie, &DV); + } else ElemDie = createMemberDIE(DIDerivedType(Element.getNode())); Buffer.addChild(ElemDie); } @@ -949,6 +960,11 @@ void DwarfDebug::constructTypeDIE(DIE &Buffer, DICompositeType CTy) { if (RLang) addUInt(&Buffer, dwarf::DW_AT_APPLE_runtime_class, dwarf::DW_FORM_data1, RLang); + + DICompositeType ContainingType = CTy.getContainingType(); + if (!ContainingType.isNull()) + addDIEEntry(&Buffer, dwarf::DW_AT_containing_type, dwarf::DW_FORM_ref4, + getOrCreateTypeDIE(DIType(ContainingType.getNode()))); break; } default: @@ -959,7 +975,7 @@ void DwarfDebug::constructTypeDIE(DIE &Buffer, DICompositeType CTy) { if (!Name.empty()) addString(&Buffer, dwarf::DW_AT_name, dwarf::DW_FORM_string, Name); - if (Tag == dwarf::DW_TAG_enumeration_type || + if (Tag == dwarf::DW_TAG_enumeration_type || Tag == dwarf::DW_TAG_class_type || Tag == dwarf::DW_TAG_structure_type || Tag == dwarf::DW_TAG_union_type) { // Add size if non-zero (derived types might be zero-sized.) if (Size) @@ -1107,7 +1123,26 @@ DIE *DwarfDebug::createMemberDIE(const DIDerivedType &DT) { // This is not a bitfield. addUInt(MemLocationDie, 0, dwarf::DW_FORM_udata, DT.getOffsetInBits() >> 3); - addBlock(MemberDie, dwarf::DW_AT_data_member_location, 0, MemLocationDie); + if (DT.getTag() == dwarf::DW_TAG_inheritance + && DT.isVirtual()) { + + // For C++, virtual base classes are not at fixed offset. Use following + // expression to extract appropriate offset from vtable. + // BaseAddr = ObAddr + *((*ObAddr) - Offset) + + DIEBlock *VBaseLocationDie = new DIEBlock(); + addUInt(VBaseLocationDie, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_dup); + addUInt(VBaseLocationDie, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_deref); + addUInt(VBaseLocationDie, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_constu); + addUInt(VBaseLocationDie, 0, dwarf::DW_FORM_udata, DT.getOffsetInBits()); + addUInt(VBaseLocationDie, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_minus); + addUInt(VBaseLocationDie, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_deref); + addUInt(VBaseLocationDie, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_plus); + + addBlock(MemberDie, dwarf::DW_AT_data_member_location, 0, + VBaseLocationDie); + } else + addBlock(MemberDie, dwarf::DW_AT_data_member_location, 0, MemLocationDie); if (DT.isProtected()) addUInt(MemberDie, dwarf::DW_AT_accessibility, dwarf::DW_FORM_flag, @@ -1179,12 +1214,17 @@ DIE *DwarfDebug::createSubprogramDIE(const DISubprogram &SP, bool MakeDecl) { 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(Arg, DIType(Args.getElement(i).getNode())); - addUInt(Arg, dwarf::DW_AT_artificial, dwarf::DW_FORM_flag, 1); // ?? + DIType ATy = DIType(DIType(Args.getElement(i).getNode())); + addType(Arg, ATy); + if (ATy.isArtificial()) + addUInt(Arg, dwarf::DW_AT_artificial, dwarf::DW_FORM_flag, 1); SPDie->addChild(Arg); } } + if (SP.isArtificial()) + addUInt(SPDie, dwarf::DW_AT_artificial, dwarf::DW_FORM_flag, 1); + // DW_TAG_inlined_subroutine may refer to this DIE. ModuleCU->insertDIE(SP.getNode(), SPDie); return SPDie; @@ -1289,7 +1329,13 @@ DIE *DwarfDebug::updateSubprogramScopeDIE(MDNode *SPNode) { DIE *SPDie = ModuleCU->getDIE(SPNode); assert (SPDie && "Unable to find subprogram DIE!"); DISubprogram SP(SPNode); - if (SP.isDefinition() && !SP.getContext().isCompileUnit()) { + // There is not any need to generate specification DIE for a function + // defined at compile unit level. If a function is defined inside another + // function then gdb prefers the definition at top level and but does not + // expect specification DIE in parent function. So avoid creating + // specification DIE for a function defined inside a function. + if (SP.isDefinition() && !SP.getContext().isCompileUnit() + && !SP.getContext().isSubprogram()) { addUInt(SPDie, dwarf::DW_AT_declaration, dwarf::DW_FORM_flag, 1); // Add arguments. DICompositeType SPTy = SP.getType(); @@ -1298,8 +1344,10 @@ DIE *DwarfDebug::updateSubprogramScopeDIE(MDNode *SPNode) { 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(Arg, DIType(Args.getElement(i).getNode())); - addUInt(Arg, dwarf::DW_AT_artificial, dwarf::DW_FORM_flag, 1); // ?? + DIType ATy = DIType(DIType(Args.getElement(i).getNode())); + addType(Arg, ATy); + if (ATy.isArtificial()) + addUInt(Arg, dwarf::DW_AT_artificial, dwarf::DW_FORM_flag, 1); SPDie->addChild(Arg); } DIE *SPDeclDie = SPDie; @@ -1308,7 +1356,7 @@ DIE *DwarfDebug::updateSubprogramScopeDIE(MDNode *SPNode) { SPDeclDie); ModuleCU->addDie(SPDie); } - + 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, @@ -1471,6 +1519,9 @@ DIE *DwarfDebug::constructVariableDIE(DbgVariable *DV, DbgScope *Scope) { else addAddress(VariableDie, dwarf::DW_AT_location, Location); } + + if (Tag == dwarf::DW_TAG_formal_parameter && VD.getType().isArtificial()) + addUInt(VariableDie, dwarf::DW_AT_artificial, dwarf::DW_FORM_flag, 1); DV->setDIE(VariableDie); return VariableDie; @@ -1669,6 +1720,7 @@ void DwarfDebug::constructGlobalVariableDIE(MDNode *N) { addObjectLabel(Block, 0, dwarf::DW_FORM_udata, Asm->GetGlobalValueSymbol(DI_GV.getGlobal())); addBlock(VariableSpecDIE, dwarf::DW_AT_location, 0, Block); + addUInt(VariableDie, dwarf::DW_AT_declaration, dwarf::DW_FORM_flag, 1); ModuleCU->addDie(VariableSpecDIE); } else { DIEBlock *Block = new DIEBlock(); @@ -1779,8 +1831,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.str()); - Asm->O << '\n'; + Asm->OutStreamer.EmitDwarfFileDirective(i, FullPath.str()); } } @@ -1986,7 +2037,7 @@ void DwarfDebug::createDbgScope(MDNode *Scope, MDNode *InlinedAt) { /// extractScopeInformation - Scan machine instructions in this function /// and collect DbgScopes. Return true, if atleast one scope was found. -bool DwarfDebug::extractScopeInformation(MachineFunction *MF) { +bool DwarfDebug::extractScopeInformation() { // If scope information was extracted using .dbg intrinsics then there is not // any need to extract these information by scanning each instruction. if (!DbgScopeMap.empty()) @@ -2081,7 +2132,7 @@ bool DwarfDebug::extractScopeInformation(MachineFunction *MF) { /// beginFunction - Gather pre-function debug information. Assumes being /// emitted immediately after the function entry point. -void DwarfDebug::beginFunction(MachineFunction *MF) { +void DwarfDebug::beginFunction(const MachineFunction *MF) { this->MF = MF; if (!ShouldEmitDwarfDebug()) return; @@ -2089,14 +2140,11 @@ void DwarfDebug::beginFunction(MachineFunction *MF) { if (TimePassesIsEnabled) DebugTimer->startTimer(); - if (!extractScopeInformation(MF)) + if (!extractScopeInformation()) return; collectVariableInfo(); - // Begin accumulating function debug information. - MMI->BeginFunction(MF); - // Assumes in correct section after the entry point. EmitLabel("func_begin", ++SubprogramCount); @@ -2123,7 +2171,7 @@ void DwarfDebug::beginFunction(MachineFunction *MF) { /// endFunction - Gather and emit post-function debug information. /// -void DwarfDebug::endFunction(MachineFunction *MF) { +void DwarfDebug::endFunction(const MachineFunction *MF) { if (!ShouldEmitDwarfDebug()) return; if (TimePassesIsEnabled) @@ -2366,6 +2414,9 @@ void DwarfDebug::emitDIE(DIE *Die) { unsigned Form = AbbrevData[i].getForm(); assert(Form && "Too many attributes for DIE (check abbreviation)"); + if (Asm->VerboseAsm) + Asm->OutStreamer.AddComment(dwarf::AttributeString(Attr)); + switch (Attr) { case dwarf::DW_AT_sibling: Asm->EmitInt32(Die->getSiblingOffset()); @@ -2380,10 +2431,9 @@ void DwarfDebug::emitDIE(DIE *Die) { default: // Emit an attribute using the defined form. Values[i]->EmitValue(this, Form); + O << "\n"; // REMOVE This once all EmitValue impls emit their own newline. break; } - - EOL(dwarf::AttributeString(Attr)); } // Emit the DIE children if any. @@ -2767,7 +2817,8 @@ void DwarfDebug::emitDebugPubTypes() { EmitLabel("pubtypes_begin", ModuleCU->getID()); - Asm->EmitInt16(dwarf::DWARF_VERSION); EOL("DWARF Version"); + if (Asm->VerboseAsm) Asm->OutStreamer.AddComment("DWARF Version"); + Asm->EmitInt16(dwarf::DWARF_VERSION); EmitSectionOffset("info_begin", "section_info", ModuleCU->getID(), 0, true, false); @@ -2783,10 +2834,11 @@ void DwarfDebug::emitDebugPubTypes() { const char *Name = GI->getKeyData(); DIE * Entity = GI->second; - Asm->EmitInt32(Entity->getOffset()); EOL("DIE offset"); + if (Asm->VerboseAsm) Asm->OutStreamer.AddComment("DIE offset"); + Asm->EmitInt32(Entity->getOffset()); if (Asm->VerboseAsm) Asm->OutStreamer.AddComment("External Name"); - Asm->OutStreamer.EmitBytes(StringRef(Name, strlen(Name)), 0); + Asm->OutStreamer.EmitBytes(StringRef(Name, GI->getKeyLength()+1), 0); } Asm->EmitInt32(0); EOL("End Mark"); diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.h b/lib/CodeGen/AsmPrinter/DwarfDebug.h index e723621ce9979..55baa92100664 100644 --- a/lib/CodeGen/AsmPrinter/DwarfDebug.h +++ b/lib/CodeGen/AsmPrinter/DwarfDebug.h @@ -103,7 +103,7 @@ class DwarfDebug : public DwarfPrinter { /// SmallVector<std::pair<unsigned, unsigned>, 8> SourceIds; - /// Lines - List of of source line correspondence. + /// Lines - List of source line correspondence. std::vector<SrcLineInfo> Lines; /// DIEValues - A list of all the unique values in use. @@ -523,11 +523,11 @@ public: /// beginFunction - Gather pre-function debug information. Assumes being /// emitted immediately after the function entry point. - void beginFunction(MachineFunction *MF); + void beginFunction(const MachineFunction *MF); /// endFunction - Gather and emit post-function debug information. /// - void endFunction(MachineFunction *MF); + void endFunction(const MachineFunction *MF); /// recordSourceLine - Records location information and associates it with a /// label. Returns a unique label ID used to generate a label and provide @@ -550,7 +550,7 @@ public: /// extractScopeInformation - Scan machine instructions in this function /// and collect DbgScopes. Return true, if atleast one scope was found. - bool extractScopeInformation(MachineFunction *MF); + bool extractScopeInformation(); /// collectVariableInfo - Populate DbgScope entries with variables' info. void collectVariableInfo(); diff --git a/lib/CodeGen/AsmPrinter/DwarfException.cpp b/lib/CodeGen/AsmPrinter/DwarfException.cpp index 2ae16c0664a81..c6c59f5998568 100644 --- a/lib/CodeGen/AsmPrinter/DwarfException.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfException.cpp @@ -34,6 +34,7 @@ #include "llvm/Support/Timer.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/Twine.h" using namespace llvm; DwarfException::DwarfException(raw_ostream &OS, AsmPrinter *A, @@ -49,26 +50,6 @@ DwarfException::~DwarfException() { delete ExceptionTimer; } -/// 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; -} - /// CreateLabelDiff - Emit a label and subtract it from the expression we /// already have. This is equivalent to emitting "foo - .", but we have to emit /// the label for "." directly. @@ -99,7 +80,7 @@ void DwarfException::EmitCIE(const Function *PersonalityFn, unsigned Index) { TD->getPointerSize() : -TD->getPointerSize(); const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering(); - + // Begin eh frame section. Asm->OutStreamer.SwitchSection(TLOF.getEHFrameSection()); @@ -127,30 +108,16 @@ void DwarfException::EmitCIE(const Function *PersonalityFn, unsigned Index) { // The personality presence indicates that language specific information will // 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; + + unsigned LSDAEncoding = TLOF.getLSDAEncoding(); + unsigned FDEEncoding = TLOF.getFDEEncoding(); + unsigned PerEncoding = TLOF.getPersonalityEncoding(); char Augmentation[6] = { 0 }; unsigned AugmentationSize = 0; char *APtr = Augmentation + 1; - if (PersonalityRef) { + if (PersonalityFn) { // There is a personality function. *APtr++ = 'P'; AugmentationSize += 1 + SizeOfEncodedValue(PerEncoding); @@ -180,20 +147,19 @@ void DwarfException::EmitCIE(const Function *PersonalityFn, unsigned Index) { Asm->EmitInt8(RI->getDwarfRegNum(RI->getRARegister(), true)); EOL("CIE Return Address Column"); - EmitULEB128(AugmentationSize, "Augmentation Size"); - EmitEncodingByte(PerEncoding, "Personality"); - - // If there is a personality, we need to indicate the function's location. - if (PersonalityRef) { - if (!IsPersonalityPCRel) - PersonalityRef = CreateLabelDiff(PersonalityRef, "personalityref_addr", - Index); - - O << MAI->getData32bitsDirective() << *PersonalityRef; - EOL("Personality"); + if (Augmentation[0]) { + EmitULEB128(AugmentationSize, "Augmentation Size"); - EmitEncodingByte(LSDAEncoding, "LSDA"); - EmitEncodingByte(FDEEncoding, "FDE"); + // If there is a personality, we need to indicate the function's location. + if (PersonalityFn) { + EmitEncodingByte(PerEncoding, "Personality"); + EmitReference(PersonalityFn, PerEncoding); + EOL("Personality"); + } + if (UsesLSDA[Index]) + EmitEncodingByte(LSDAEncoding, "LSDA"); + if (FDEEncoding != dwarf::DW_EH_PE_absptr) + EmitEncodingByte(FDEEncoding, "FDE"); } // Indicate locations of general callee saved registers in frame. @@ -215,8 +181,12 @@ void DwarfException::EmitFDE(const FunctionEHFrameInfo &EHFrameInfo) { "Should not emit 'available externally' functions at all"); const Function *TheFunc = EHFrameInfo.function; + const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering(); - Asm->OutStreamer.SwitchSection(Asm->getObjFileLowering().getEHFrameSection()); + unsigned LSDAEncoding = TLOF.getLSDAEncoding(); + unsigned FDEEncoding = TLOF.getFDEEncoding(); + + Asm->OutStreamer.SwitchSection(TLOF.getEHFrameSection()); // Externally visible entry into the functions eh frame info. If the // corresponding function is static, this should not be externally visible. @@ -254,7 +224,8 @@ void DwarfException::EmitFDE(const FunctionEHFrameInfo &EHFrameInfo) { // EH frame header. EmitDifference("eh_frame_end", EHFrameInfo.Number, - "eh_frame_begin", EHFrameInfo.Number, true); + "eh_frame_begin", EHFrameInfo.Number, + true); EOL("Length of Frame Information Entry"); EmitLabel("eh_frame_begin", EHFrameInfo.Number); @@ -265,33 +236,23 @@ void DwarfException::EmitFDE(const FunctionEHFrameInfo &EHFrameInfo) { EOL("FDE CIE offset"); - EmitReference("eh_func_begin", EHFrameInfo.Number, true, true); + EmitReference("eh_func_begin", EHFrameInfo.Number, FDEEncoding); EOL("FDE initial location"); EmitDifference("eh_func_end", EHFrameInfo.Number, - "eh_func_begin", EHFrameInfo.Number, true); + "eh_func_begin", EHFrameInfo.Number, + SizeOfEncodedValue(FDEEncoding) == 4); EOL("FDE address range"); // If there is a personality and landing pads then point to the language // specific data area in the exception table. if (MMI->getPersonalities()[0] != NULL) { + unsigned Size = SizeOfEncodedValue(LSDAEncoding); - if (Asm->TM.getLSDAEncoding() != DwarfLSDAEncoding::EightByte) { - EmitULEB128(4, "Augmentation size"); - - if (EHFrameInfo.hasLandingPads) - EmitReference("exception", EHFrameInfo.Number, true, true); - else - Asm->OutStreamer.EmitIntValue(0, 4/*size*/, 0/*addrspace*/); - } else { - EmitULEB128(TD->getPointerSize(), "Augmentation size"); - - if (EHFrameInfo.hasLandingPads) { - EmitReference("exception", EHFrameInfo.Number, true, false); - } else { - Asm->OutStreamer.EmitIntValue(0, TD->getPointerSize(), - 0/*addrspace*/); - } - } + EmitULEB128(Size, "Augmentation size"); + if (EHFrameInfo.hasLandingPads) + EmitReference("exception", EHFrameInfo.Number, LSDAEncoding); + else + Asm->OutStreamer.EmitIntValue(0, Size/*size*/, 0/*addrspace*/); EOL("Language Specific Data Area"); } else { @@ -406,20 +367,22 @@ ComputeActionsTable(const SmallVectorImpl<const LandingPadInfo*> &LandingPads, if (NumShared < TypeIds.size()) { unsigned SizeAction = 0; - ActionEntry *PrevAction = 0; + unsigned PrevAction = (unsigned)-1; if (NumShared) { const unsigned SizePrevIds = PrevLPI->TypeIds.size(); assert(Actions.size()); - PrevAction = &Actions.back(); - SizeAction = MCAsmInfo::getSLEB128Size(PrevAction->NextAction) + - MCAsmInfo::getSLEB128Size(PrevAction->ValueForTypeID); + PrevAction = Actions.size() - 1; + SizeAction = + MCAsmInfo::getSLEB128Size(Actions[PrevAction].NextAction) + + MCAsmInfo::getSLEB128Size(Actions[PrevAction].ValueForTypeID); for (unsigned j = NumShared; j != SizePrevIds; ++j) { + assert(PrevAction != (unsigned)-1 && "PrevAction is invalid!"); SizeAction -= - MCAsmInfo::getSLEB128Size(PrevAction->ValueForTypeID); - SizeAction += -PrevAction->NextAction; - PrevAction = PrevAction->Previous; + MCAsmInfo::getSLEB128Size(Actions[PrevAction].ValueForTypeID); + SizeAction += -Actions[PrevAction].NextAction; + PrevAction = Actions[PrevAction].Previous; } } @@ -436,7 +399,7 @@ ComputeActionsTable(const SmallVectorImpl<const LandingPadInfo*> &LandingPads, ActionEntry Action = { ValueForTypeID, NextAction, PrevAction }; Actions.push_back(Action); - PrevAction = &Actions.back(); + PrevAction = Actions.size() - 1; } // Record the first action of the landing pad site. @@ -446,7 +409,7 @@ ComputeActionsTable(const SmallVectorImpl<const LandingPadInfo*> &LandingPads, // 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 + // biased by 1 (1 indicating the start of the actions table), and 0 // indicates that there are no actions. FirstActions.push_back(FirstAction); @@ -579,7 +542,16 @@ ComputeCallSiteTable(SmallVectorImpl<CallSiteEntry> &CallSites, } // Otherwise, create a new call-site. - CallSites.push_back(Site); + if (MAI->getExceptionHandlingType() == ExceptionHandling::Dwarf) + CallSites.push_back(Site); + else { + // SjLj EH must maintain the call sites in the order assigned + // to them by the SjLjPrepare pass. + unsigned SiteNo = MMI->getCallSiteBeginLabel(BeginLabel); + if (CallSites.size() < SiteNo) + CallSites.resize(SiteNo); + CallSites[SiteNo - 1] = Site; + } PreviousIsInvoke = true; } else { // Create a gap. @@ -638,8 +610,7 @@ void DwarfException::EmitExceptionTable() { // landing pad site. SmallVector<ActionEntry, 32> Actions; SmallVector<unsigned, 64> FirstActions; - unsigned SizeActions = ComputeActionsTable(LandingPads, Actions, - 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 @@ -683,13 +654,13 @@ void DwarfException::EmitExceptionTable() { // Type infos. const MCSection *LSDASection = Asm->getObjFileLowering().getLSDASection(); - unsigned TTypeFormat; + unsigned TTypeEncoding; 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; + TTypeEncoding = 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 @@ -719,14 +690,8 @@ void DwarfException::EmitExceptionTable() { // 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; - - TypeFormatSize = SizeOfEncodedValue(TTypeFormat); + TTypeEncoding = Asm->getObjFileLowering().getTTypeEncoding(); + TypeFormatSize = SizeOfEncodedValue(TTypeEncoding); } // Begin the exception table. @@ -752,7 +717,7 @@ void DwarfException::EmitExceptionTable() { // 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 + MCAsmInfo::getULEB128Size(SizeSites) + // Call site table length SizeSites + SizeActions + SizeTypes; unsigned TotalSize = sizeof(int8_t) + // LPStart format sizeof(int8_t) + // TType format @@ -777,7 +742,7 @@ void DwarfException::EmitExceptionTable() { // Emit the header. EmitEncodingByte(dwarf::DW_EH_PE_omit, "@LPStart"); - EmitEncodingByte(TTypeFormat, "@TType"); + EmitEncodingByte(TTypeEncoding, "@TType"); if (HaveTTData) EmitULEB128(TyOffset, "@TType base offset"); @@ -826,7 +791,7 @@ void DwarfException::EmitExceptionTable() { // Emit the landing pad call site table. EmitEncodingByte(dwarf::DW_EH_PE_udata4, "Call site"); - EmitULEB128(SizeSites, "Call site table size"); + EmitULEB128(SizeSites, "Call site table length"); for (SmallVectorImpl<CallSiteEntry>::const_iterator I = CallSites.begin(), E = CallSites.end(); I != E; ++I) { @@ -859,13 +824,14 @@ void DwarfException::EmitExceptionTable() { // Offset of the landing pad, counted in 16-byte bundles relative to the // @LPStart address. - if (!S.PadLabel) + if (!S.PadLabel) { + Asm->OutStreamer.AddComment("Landing pad"); Asm->OutStreamer.EmitIntValue(0, 4/*size*/, 0/*addrspace*/); - else + } else { EmitSectionOffset("label", "eh_func_begin", S.PadLabel, SubprogramCount, true, true); - - EOL("Landing pad"); + 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 @@ -875,38 +841,43 @@ void DwarfException::EmitExceptionTable() { } // Emit the Action Table. + if (Actions.size() != 0) EOL("-- Action Record Table --"); for (SmallVectorImpl<ActionEntry>::const_iterator I = Actions.begin(), E = Actions.end(); I != E; ++I) { const ActionEntry &Action = *I; + EOL("Action Record:"); // 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. - EmitSLEB128(Action.ValueForTypeID, "TypeInfo index"); + EmitSLEB128(Action.ValueForTypeID, " TypeInfo index"); // Action Record // // Self-relative signed displacement in bytes of the next action record, // or 0 if there is no next action record. - EmitSLEB128(Action.NextAction, "Next action"); + EmitSLEB128(Action.NextAction, " Next action"); } // Emit the Catch TypeInfos. + if (!TypeInfos.empty()) EOL("-- Catch TypeInfos --"); for (std::vector<GlobalVariable *>::const_reverse_iterator I = TypeInfos.rbegin(), E = TypeInfos.rend(); I != E; ++I) { const GlobalVariable *GV = *I; - PrintRelDirective(); - if (GV) - O << *Asm->GetGlobalValueSymbol(GV); - else + if (GV) { + EmitReference(GV, TTypeEncoding); + EOL("TypeInfo"); + } else { + PrintRelDirective(TTypeEncoding); O << "0x0"; - - EOL("TypeInfo"); + EOL(""); + } } // Emit the Exception Specifications. + if (!FilterIds.empty()) EOL("-- Filter IDs --"); for (std::vector<unsigned>::const_iterator I = FilterIds.begin(), E = FilterIds.end(); I < E; ++I) { unsigned TypeID = *I; @@ -943,7 +914,7 @@ void DwarfException::EndModule() { /// BeginFunction - Gather pre-function exception information. Assumes it's /// being emitted immediately after the function entry point. -void DwarfException::BeginFunction(MachineFunction *MF) { +void DwarfException::BeginFunction(const MachineFunction *MF) { if (!MMI || !MAI->doesSupportExceptionHandling()) return; if (TimePassesIsEnabled) diff --git a/lib/CodeGen/AsmPrinter/DwarfException.h b/lib/CodeGen/AsmPrinter/DwarfException.h index 3921e91ea5007..3db1a00802d6e 100644 --- a/lib/CodeGen/AsmPrinter/DwarfException.h +++ b/lib/CodeGen/AsmPrinter/DwarfException.h @@ -76,9 +76,6 @@ class DwarfException : public DwarfPrinter { /// ExceptionTimer - Timer for the Dwarf exception writer. Timer *ExceptionTimer; - /// SizeOfEncodedValue - Return the size of the encoding in bytes. - unsigned SizeOfEncodedValue(unsigned Encoding); - /// 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. @@ -103,7 +100,7 @@ class DwarfException : public DwarfPrinter { /// 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. + /// found 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. @@ -135,7 +132,7 @@ class DwarfException : public DwarfPrinter { struct ActionEntry { int ValueForTypeID; // The value to write - may not be equal to the type id. int NextAction; - struct ActionEntry *Previous; + unsigned Previous; }; /// CallSiteEntry - Structure describing an entry in the call-site table. @@ -197,7 +194,7 @@ public: /// BeginFunction - Gather pre-function exception information. Assumes being /// emitted immediately after the function entry point. - void BeginFunction(MachineFunction *MF); + void BeginFunction(const MachineFunction *MF); /// EndFunction - Gather and emit post-function exception information. void EndFunction(); diff --git a/lib/CodeGen/AsmPrinter/DwarfPrinter.cpp b/lib/CodeGen/AsmPrinter/DwarfPrinter.cpp index d204bba7e9934..1299d048e4be6 100644 --- a/lib/CodeGen/AsmPrinter/DwarfPrinter.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfPrinter.cpp @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// // // Emit general DWARF directives. -// +// //===----------------------------------------------------------------------===// #include "DwarfPrinter.h" @@ -18,13 +18,17 @@ #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCExpr.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSymbol.h" #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetFrameInfo.h" +#include "llvm/Target/TargetLoweringObjectFile.h" #include "llvm/Target/TargetRegisterInfo.h" #include "llvm/Support/Dwarf.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/ADT/SmallString.h" using namespace llvm; DwarfPrinter::DwarfPrinter(raw_ostream &OS, AsmPrinter *A, const MCAsmInfo *T, @@ -33,6 +37,26 @@ DwarfPrinter::DwarfPrinter(raw_ostream &OS, AsmPrinter *A, const MCAsmInfo *T, RI(Asm->TM.getRegisterInfo()), M(NULL), MF(NULL), MMI(NULL), SubprogramCount(0), Flavor(flavor), SetCounter(1) {} +/// SizeOfEncodedValue - Return the size of the encoding in bytes. +unsigned DwarfPrinter::SizeOfEncodedValue(unsigned Encoding) const { + 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; +} + void DwarfPrinter::PrintRelDirective(bool Force32Bit, bool isInSection) const { if (isInSection && MAI->getDwarfSectionOffsetDirective()) O << MAI->getDwarfSectionOffsetDirective(); @@ -42,6 +66,14 @@ void DwarfPrinter::PrintRelDirective(bool Force32Bit, bool isInSection) const { O << MAI->getData64bitsDirective(); } +void DwarfPrinter::PrintRelDirective(unsigned Encoding) const { + unsigned Size = SizeOfEncodedValue(Encoding); + assert((Size == 4 || Size == 8) && "Do not support other types or rels!"); + + O << (Size == 4 ? + MAI->getData32bitsDirective() : MAI->getData64bitsDirective()); +} + /// EOL - Print a newline character to asm stream. If a comment is present /// then it will be printed first. Comments should not contain '\n'. void DwarfPrinter::EOL(const Twine &Comment) const { @@ -195,13 +227,38 @@ void DwarfPrinter::EmitReference(const MCSymbol *Sym, bool IsPCRelative, if (IsPCRelative) O << "-" << MAI->getPCSymbol(); } -/// EmitDifference - Emit the difference between two labels. Some assemblers do -/// not behave with absolute expressions with data directives, so there is an -/// option (needsSet) to use an intermediary set expression. +void DwarfPrinter::EmitReference(const char *Tag, unsigned Number, + unsigned Encoding) const { + SmallString<64> Name; + raw_svector_ostream(Name) << MAI->getPrivateGlobalPrefix() + << Tag << Number; + + MCSymbol *Sym = Asm->OutContext.GetOrCreateSymbol(Name.str()); + EmitReference(Sym, Encoding); +} + +void DwarfPrinter::EmitReference(const MCSymbol *Sym, unsigned Encoding) const { + const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering(); + + PrintRelDirective(Encoding); + O << *TLOF.getSymbolForDwarfReference(Sym, Asm->MMI, Encoding);; +} + +void DwarfPrinter::EmitReference(const GlobalValue *GV, unsigned Encoding)const { + const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering(); + + PrintRelDirective(Encoding); + O << *TLOF.getSymbolForDwarfGlobalReference(GV, Asm->Mang, + Asm->MMI, Encoding);; +} + +/// EmitDifference - Emit the difference between two labels. If this assembler +/// supports .set, we emit a .set of a temporary and then use it in the .word. void DwarfPrinter::EmitDifference(const char *TagHi, unsigned NumberHi, const char *TagLo, unsigned NumberLo, bool IsSmall) { - if (MAI->needsSet()) { + if (MAI->hasSetDirective()) { + // FIXME: switch to OutStreamer.EmitAssignment. O << "\t.set\t"; PrintLabelName("set", SetCounter, Flavor); O << ","; @@ -232,7 +289,8 @@ void DwarfPrinter::EmitSectionOffset(const char* Label, const char* Section, else printAbsolute = MAI->isAbsoluteDebugSectionOffsets(); - if (MAI->needsSet() && useSet) { + if (MAI->hasSetDirective() && useSet) { + // FIXME: switch to OutStreamer.EmitAssignment. O << "\t.set\t"; PrintLabelName("set", SetCounter, Flavor); O << ","; diff --git a/lib/CodeGen/AsmPrinter/DwarfPrinter.h b/lib/CodeGen/AsmPrinter/DwarfPrinter.h index 86fe2abc88eed..73de398e35e56 100644 --- a/lib/CodeGen/AsmPrinter/DwarfPrinter.h +++ b/lib/CodeGen/AsmPrinter/DwarfPrinter.h @@ -28,11 +28,14 @@ class Module; class MCAsmInfo; class TargetData; class TargetRegisterInfo; +class GlobalValue; class MCSymbol; class Twine; class DwarfPrinter { protected: + ~DwarfPrinter() {} + //===-------------------------------------------------------------==---===// // Core attributes used by the DWARF printer. // @@ -56,7 +59,7 @@ protected: Module *M; /// MF - Current machine function. - MachineFunction *MF; + const MachineFunction *MF; /// MMI - Collected machine module information. MachineModuleInfo *MMI; @@ -83,6 +86,10 @@ public: const MCAsmInfo *getMCAsmInfo() const { return MAI; } const TargetData *getTargetData() const { return TD; } + /// SizeOfEncodedValue - Return the size of the encoding in bytes. + unsigned SizeOfEncodedValue(unsigned Encoding) const; + + void PrintRelDirective(unsigned Encoding) const; void PrintRelDirective(bool Force32Bit = false, bool isInSection = false) const; @@ -138,9 +145,11 @@ public: void EmitReference(const MCSymbol *Sym, bool IsPCRelative = false, bool Force32Bit = false) const; - /// EmitDifference - Emit the difference between two labels. Some - /// assemblers do not behave with absolute expressions with data directives, - /// so there is an option (needsSet) to use an intermediary set expression. + void EmitReference(const char *Tag, unsigned Number, unsigned Encoding) const; + void EmitReference(const MCSymbol *Sym, unsigned Encoding) const; + void EmitReference(const GlobalValue *GV, unsigned Encoding) const; + + /// EmitDifference - Emit the difference between two labels. void EmitDifference(const DWLabel &LabelHi, const DWLabel &LabelLo, bool IsSmall = false) { EmitDifference(LabelHi.getTag(), LabelHi.getNumber(), diff --git a/lib/CodeGen/AsmPrinter/DwarfWriter.cpp b/lib/CodeGen/AsmPrinter/DwarfWriter.cpp index dd8d88a2e4af0..08e1bbce08f48 100644 --- a/lib/CodeGen/AsmPrinter/DwarfWriter.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfWriter.cpp @@ -57,14 +57,14 @@ void DwarfWriter::EndModule() { /// BeginFunction - Gather pre-function debug information. Assumes being /// emitted immediately after the function entry point. -void DwarfWriter::BeginFunction(MachineFunction *MF) { +void DwarfWriter::BeginFunction(const MachineFunction *MF) { DE->BeginFunction(MF); DD->beginFunction(MF); } /// EndFunction - Gather and emit post-function debug information. /// -void DwarfWriter::EndFunction(MachineFunction *MF) { +void DwarfWriter::EndFunction(const MachineFunction *MF) { DD->endFunction(MF); DE->EndFunction(); diff --git a/lib/CodeGen/AsmPrinter/Makefile b/lib/CodeGen/AsmPrinter/Makefile index b0071d0ea3dbe..60aa6cbcf6f3e 100644 --- a/lib/CodeGen/AsmPrinter/Makefile +++ b/lib/CodeGen/AsmPrinter/Makefile @@ -9,6 +9,5 @@ LEVEL = ../../.. LIBRARYNAME = LLVMAsmPrinter -CXXFLAGS = -fno-rtti include $(LEVEL)/Makefile.common |