summaryrefslogtreecommitdiffstats
path: root/lib/CodeGen/AsmPrinter
diff options
context:
space:
mode:
Diffstat (limited to 'lib/CodeGen/AsmPrinter')
-rw-r--r--lib/CodeGen/AsmPrinter/AsmPrinter.cpp1194
-rw-r--r--lib/CodeGen/AsmPrinter/DIE.cpp57
-rw-r--r--lib/CodeGen/AsmPrinter/DIE.h34
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfDebug.cpp1161
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfDebug.h115
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfException.cpp917
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfException.h60
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfLabel.cpp7
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfLabel.h10
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfPrinter.cpp40
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfPrinter.h10
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfWriter.cpp34
-rw-r--r--lib/CodeGen/AsmPrinter/OcamlGCPrinter.cpp70
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);
OpenPOWER on IntegriCloud