aboutsummaryrefslogtreecommitdiffstats
path: root/lib/CodeGen/AsmPrinter
diff options
context:
space:
mode:
Diffstat (limited to 'lib/CodeGen/AsmPrinter')
-rw-r--r--lib/CodeGen/AsmPrinter/AsmPrinter.cpp17
-rw-r--r--lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp2
-rw-r--r--lib/CodeGen/AsmPrinter/CMakeLists.txt1
-rw-r--r--lib/CodeGen/AsmPrinter/DIE.cpp6
-rw-r--r--lib/CodeGen/AsmPrinter/DIE.h10
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp6
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfDebug.cpp130
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfDebug.h5
-rw-r--r--lib/CodeGen/AsmPrinter/ErlangGCPrinter.cpp120
9 files changed, 235 insertions, 62 deletions
diff --git a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
index d4a745d..84162ace 100644
--- a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -133,9 +133,13 @@ const DataLayout &AsmPrinter::getDataLayout() const {
return *TM.getDataLayout();
}
+StringRef AsmPrinter::getTargetTriple() const {
+ return TM.getTargetTriple();
+}
+
/// getCurrentSection() - Return the current section we are emitting to.
const MCSection *AsmPrinter::getCurrentSection() const {
- return OutStreamer.getCurrentSection();
+ return OutStreamer.getCurrentSection().first;
}
@@ -813,7 +817,7 @@ void AsmPrinter::EmitDwarfRegOp(const MachineLocation &MLoc) const {
// caller might be in the middle of an dwarf expression. We should
// probably assert that Reg >= 0 once debug info generation is more mature.
- if (int Offset = MLoc.getOffset()) {
+ if (MLoc.isIndirect()) {
if (Reg < 32) {
OutStreamer.AddComment(
dwarf::OperationEncodingString(dwarf::DW_OP_breg0 + Reg));
@@ -824,7 +828,7 @@ void AsmPrinter::EmitDwarfRegOp(const MachineLocation &MLoc) const {
OutStreamer.AddComment(Twine(Reg));
EmitULEB128(Reg);
}
- EmitSLEB128(Offset);
+ EmitSLEB128(MLoc.getOffset());
} else {
if (Reg < 32) {
OutStreamer.AddComment(
@@ -1213,7 +1217,7 @@ void AsmPrinter::EmitJumpTableEntry(const MachineJumpTableInfo *MJTI,
bool AsmPrinter::EmitSpecialLLVMGlobal(const GlobalVariable *GV) {
if (GV->getName() == "llvm.used") {
if (MAI->hasNoDeadStrip()) // No need to emit this at all.
- EmitLLVMUsedList(GV->getInitializer());
+ EmitLLVMUsedList(cast<ConstantArray>(GV->getInitializer()));
return true;
}
@@ -1256,11 +1260,8 @@ bool AsmPrinter::EmitSpecialLLVMGlobal(const GlobalVariable *GV) {
/// 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(const Constant *List) {
+void AsmPrinter::EmitLLVMUsedList(const ConstantArray *InitList) {
// Should be an array of 'i8*'.
- const ConstantArray *InitList = dyn_cast<ConstantArray>(List);
- if (InitList == 0) return;
-
for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) {
const GlobalValue *GV =
dyn_cast<GlobalValue>(InitList->getOperand(i)->stripPointerCasts());
diff --git a/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp b/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp
index 156acac..31e42d4 100644
--- a/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp
+++ b/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp
@@ -141,7 +141,7 @@ void AsmPrinter::EmitTTypeReference(const GlobalValue *GV,
void AsmPrinter::EmitSectionOffset(const MCSymbol *Label,
const MCSymbol *SectionLabel) const {
// On COFF targets, we have to emit the special .secrel32 directive.
- if (MAI->getDwarfSectionOffsetDirective()) {
+ if (MAI->needsDwarfSectionOffsetDirective()) {
OutStreamer.EmitCOFFSecRel32(Label);
return;
}
diff --git a/lib/CodeGen/AsmPrinter/CMakeLists.txt b/lib/CodeGen/AsmPrinter/CMakeLists.txt
index 58fe2ed..8d15c06 100644
--- a/lib/CodeGen/AsmPrinter/CMakeLists.txt
+++ b/lib/CodeGen/AsmPrinter/CMakeLists.txt
@@ -9,6 +9,7 @@ add_llvm_library(LLVMAsmPrinter
DwarfCompileUnit.cpp
DwarfDebug.cpp
DwarfException.cpp
+ ErlangGCPrinter.cpp
OcamlGCPrinter.cpp
Win64Exception.cpp
)
diff --git a/lib/CodeGen/AsmPrinter/DIE.cpp b/lib/CodeGen/AsmPrinter/DIE.cpp
index bbb0432..57e0acd 100644
--- a/lib/CodeGen/AsmPrinter/DIE.cpp
+++ b/lib/CodeGen/AsmPrinter/DIE.cpp
@@ -144,7 +144,7 @@ void DIE::print(raw_ostream &O, unsigned IncIndent) {
O << "Size: " << Size << "\n";
}
- const SmallVector<DIEAbbrevData, 8> &Data = Abbrev.getData();
+ const SmallVectorImpl<DIEAbbrevData> &Data = Abbrev.getData();
IndentCount += 2;
for (unsigned i = 0, N = Data.size(); i < N; ++i) {
@@ -324,7 +324,7 @@ void DIEEntry::print(raw_ostream &O) {
///
unsigned DIEBlock::ComputeSize(AsmPrinter *AP) {
if (!Size) {
- const SmallVector<DIEAbbrevData, 8> &AbbrevData = Abbrev.getData();
+ const SmallVectorImpl<DIEAbbrevData> &AbbrevData = Abbrev.getData();
for (unsigned i = 0, N = Values.size(); i < N; ++i)
Size += Values[i]->SizeOf(AP, AbbrevData[i].getForm());
}
@@ -343,7 +343,7 @@ void DIEBlock::EmitValue(AsmPrinter *Asm, unsigned Form) const {
case dwarf::DW_FORM_block: Asm->EmitULEB128(Size); break;
}
- const SmallVector<DIEAbbrevData, 8> &AbbrevData = Abbrev.getData();
+ const SmallVectorImpl<DIEAbbrevData> &AbbrevData = Abbrev.getData();
for (unsigned i = 0, N = Values.size(); i < N; ++i)
Values[i]->EmitValue(Asm, AbbrevData[i].getForm());
}
diff --git a/lib/CodeGen/AsmPrinter/DIE.h b/lib/CodeGen/AsmPrinter/DIE.h
index d087c54..c332aa2 100644
--- a/lib/CodeGen/AsmPrinter/DIE.h
+++ b/lib/CodeGen/AsmPrinter/DIE.h
@@ -66,7 +66,7 @@ namespace llvm {
/// Data - Raw data bytes for abbreviation.
///
- SmallVector<DIEAbbrevData, 8> Data;
+ SmallVector<DIEAbbrevData, 12> Data;
public:
DIEAbbrev(uint16_t T, uint16_t C) : Tag(T), ChildrenFlag(C), Data() {}
@@ -75,7 +75,7 @@ namespace llvm {
uint16_t getTag() const { return Tag; }
unsigned getNumber() const { return Number; }
uint16_t getChildrenFlag() const { return ChildrenFlag; }
- const SmallVector<DIEAbbrevData, 8> &getData() const { return Data; }
+ const SmallVectorImpl<DIEAbbrevData> &getData() const { return Data; }
void setTag(uint16_t T) { Tag = T; }
void setChildrenFlag(uint16_t CF) { ChildrenFlag = CF; }
void setNumber(unsigned N) { Number = N; }
@@ -108,7 +108,7 @@ namespace llvm {
//===--------------------------------------------------------------------===//
/// DIE - A structured debug information entry. Has an abbreviation which
- /// describes it's organization.
+ /// describes its organization.
class DIEValue;
class DIE {
@@ -133,7 +133,7 @@ namespace llvm {
/// Attribute values.
///
- SmallVector<DIEValue*, 32> Values;
+ SmallVector<DIEValue*, 12> Values;
// Private data for print()
mutable unsigned IndentCount;
@@ -150,7 +150,7 @@ namespace llvm {
unsigned getOffset() const { return Offset; }
unsigned getSize() const { return Size; }
const std::vector<DIE *> &getChildren() const { return Children; }
- const SmallVector<DIEValue*, 32> &getValues() const { return Values; }
+ const SmallVectorImpl<DIEValue*> &getValues() const { return Values; }
DIE *getParent() const { return Parent; }
/// Climb up the parent chain to get the compile unit DIE this DIE belongs
/// to.
diff --git a/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp b/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
index 1c743c2..89abcff 100644
--- a/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
+++ b/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
@@ -685,7 +685,7 @@ bool CompileUnit::addConstantValue(DIE *Die, const APInt &Val,
return true;
}
-/// addTemplateParams - Add template parameters in buffer.
+/// addTemplateParams - Add template parameters into buffer.
void CompileUnit::addTemplateParams(DIE &Buffer, DIArray TParams) {
// Add template parameters.
for (unsigned i = 0, e = TParams.getNumElements(); i != e; ++i) {
@@ -707,7 +707,7 @@ DIE *CompileUnit::getOrCreateContextDIE(DIDescriptor Context) {
return getOrCreateNameSpace(DINameSpace(Context));
else if (Context.isSubprogram())
return getOrCreateSubprogramDIE(DISubprogram(Context));
- else
+ else
return getDIE(Context);
}
@@ -1366,7 +1366,7 @@ void CompileUnit::createGlobalVariableDIE(const MDNode *N) {
}
} else if (const ConstantInt *CI =
dyn_cast_or_null<ConstantInt>(GV.getConstant())) {
- // AT_const_value was added when the static memeber was created. To avoid
+ // AT_const_value was added when the static member was created. To avoid
// emitting AT_const_value multiple times, we only add AT_const_value when
// it is not a static member.
if (!IsStaticMember)
diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
index b169602..ee6308c 100644
--- a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
+++ b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
@@ -55,7 +55,7 @@ static cl::opt<bool> UnknownLocations("use-unknown-locations", cl::Hidden,
cl::init(false));
static cl::opt<bool> GenerateDwarfPubNamesSection("generate-dwarf-pubnames",
- cl::Hidden, cl::ZeroOrMore, cl::init(false),
+ cl::Hidden, cl::init(false),
cl::desc("Generate DWARF pubnames section"));
namespace {
@@ -170,12 +170,13 @@ DwarfDebug::DwarfDebug(AsmPrinter *A, Module *M)
DwarfInfoSectionSym = DwarfAbbrevSectionSym = 0;
DwarfStrSectionSym = TextSectionSym = 0;
DwarfDebugRangeSectionSym = DwarfDebugLocSectionSym = DwarfLineSectionSym = 0;
+ DwarfAddrSectionSym = 0;
DwarfAbbrevDWOSectionSym = DwarfStrDWOSectionSym = 0;
FunctionBeginSym = FunctionEndSym = 0;
// Turn on accelerator tables and older gdb compatibility
// for Darwin.
- bool IsDarwin = Triple(M->getTargetTriple()).isOSDarwin();
+ bool IsDarwin = Triple(A->getTargetTriple()).isOSDarwin();
if (DarwinGDBCompat == Default) {
if (IsDarwin)
IsDarwinGDBCompat = true;
@@ -643,7 +644,7 @@ unsigned DwarfDebug::getOrCreateSourceID(StringRef FileName,
// We look up the CUID/file/dir by concatenating them with a zero byte.
SmallString<128> NamePair;
- NamePair += CUID;
+ NamePair += utostr(CUID);
NamePair += '\0';
NamePair += DirName;
NamePair += '\0'; // Zero bytes are not allowed in paths.
@@ -681,9 +682,12 @@ CompileUnit *DwarfDebug::constructCompileUnit(const MDNode *N) {
NewCU->addUInt(Die, dwarf::DW_AT_language, dwarf::DW_FORM_data2,
DIUnit.getLanguage());
NewCU->addString(Die, dwarf::DW_AT_name, FN);
+
// 2.17.1 requires that we use DW_AT_low_pc for a single entry point
- // into an entity. We're using 0 (or a NULL label) for this.
- NewCU->addLabelAddress(Die, dwarf::DW_AT_low_pc, NULL);
+ // into an entity. We're using 0 (or a NULL label) for this. For
+ // split dwarf it's in the skeleton CU so omit it here.
+ if (!useSplitDwarf())
+ NewCU->addLabelAddress(Die, dwarf::DW_AT_low_pc, NULL);
// Define start line table label for each Compile Unit.
MCSymbol *LineTableStartSym = Asm->GetTempSymbol("line_table_start",
@@ -692,20 +696,25 @@ CompileUnit *DwarfDebug::constructCompileUnit(const MDNode *N) {
NewCU->getUniqueID());
// DW_AT_stmt_list is a offset of line number information for this
- // compile unit in debug_line section.
+ // compile unit in debug_line section. For split dwarf this is
+ // left in the skeleton CU and so not included.
// The line table entries are not always emitted in assembly, so it
// is not okay to use line_table_start here.
- if (Asm->MAI->doesDwarfUseRelocationsAcrossSections())
- NewCU->addLabel(Die, dwarf::DW_AT_stmt_list, dwarf::DW_FORM_data4,
- NewCU->getUniqueID() == 0 ?
- Asm->GetTempSymbol("section_line") : LineTableStartSym);
- else if (NewCU->getUniqueID() == 0)
- NewCU->addUInt(Die, dwarf::DW_AT_stmt_list, dwarf::DW_FORM_data4, 0);
- else
- NewCU->addDelta(Die, dwarf::DW_AT_stmt_list, dwarf::DW_FORM_data4,
- LineTableStartSym, DwarfLineSectionSym);
+ if (!useSplitDwarf()) {
+ if (Asm->MAI->doesDwarfUseRelocationsAcrossSections())
+ NewCU->addLabel(Die, dwarf::DW_AT_stmt_list, dwarf::DW_FORM_data4,
+ NewCU->getUniqueID() == 0 ?
+ Asm->GetTempSymbol("section_line") : LineTableStartSym);
+ else if (NewCU->getUniqueID() == 0)
+ NewCU->addUInt(Die, dwarf::DW_AT_stmt_list, dwarf::DW_FORM_data4, 0);
+ else
+ NewCU->addDelta(Die, dwarf::DW_AT_stmt_list, dwarf::DW_FORM_data4,
+ LineTableStartSym, DwarfLineSectionSym);
+ }
- if (!CompilationDir.empty())
+ // If we're using split dwarf the compilation dir is going to be in the
+ // skeleton CU and so we don't need to duplicate it here.
+ if (!useSplitDwarf() && !CompilationDir.empty())
NewCU->addString(Die, dwarf::DW_AT_comp_dir, CompilationDir);
if (DIUnit.isOptimized())
NewCU->addFlag(Die, dwarf::DW_AT_APPLE_optimized);
@@ -721,13 +730,6 @@ CompileUnit *DwarfDebug::constructCompileUnit(const MDNode *N) {
if (!FirstCU)
FirstCU = NewCU;
- if (useSplitDwarf()) {
- // This should be a unique identifier when we want to build .dwp files.
- NewCU->addUInt(Die, dwarf::DW_AT_GNU_dwo_id, dwarf::DW_FORM_data8, 0);
- // Now construct the skeleton CU associated.
- constructSkeletonCU(N);
- }
-
InfoHolder.addUnit(NewCU);
CUMap.insert(std::make_pair(N, NewCU));
@@ -761,6 +763,23 @@ void DwarfDebug::constructSubprogramDIE(CompileUnit *TheCU,
TheCU->addGlobalName(SP.getName(), SubprogramDie);
}
+void DwarfDebug::constructImportedModuleDIE(CompileUnit *TheCU,
+ const MDNode *N) {
+ DIImportedModule Module(N);
+ if (!Module.Verify())
+ return;
+ DIE *IMDie = new DIE(dwarf::DW_TAG_imported_module);
+ TheCU->insertDIE(Module, IMDie);
+ DIE *NSDie = TheCU->getOrCreateNameSpace(Module.getNameSpace());
+ unsigned FileID = getOrCreateSourceID(Module.getContext().getFilename(),
+ Module.getContext().getDirectory(),
+ TheCU->getUniqueID());
+ TheCU->addUInt(IMDie, dwarf::DW_AT_decl_file, 0, FileID);
+ TheCU->addUInt(IMDie, dwarf::DW_AT_decl_line, 0, Module.getLineNumber());
+ TheCU->addDIEEntry(IMDie, dwarf::DW_AT_import, dwarf::DW_FORM_ref4, NSDie);
+ TheCU->addToContextOwner(IMDie, Module.getContext());
+}
+
// Emit all Dwarf sections that should come prior to the content. Create
// global DIEs and emit initial debug info sections. This is invoked by
// the target AsmPrinter.
@@ -794,6 +813,20 @@ void DwarfDebug::beginModule() {
DIArray RetainedTypes = CUNode.getRetainedTypes();
for (unsigned i = 0, e = RetainedTypes.getNumElements(); i != e; ++i)
CU->getOrCreateTypeDIE(RetainedTypes.getElement(i));
+ // Emit imported_modules last so that the relevant context is already
+ // available.
+ DIArray ImportedModules = CUNode.getImportedModules();
+ for (unsigned i = 0, e = ImportedModules.getNumElements(); i != e; ++i)
+ constructImportedModuleDIE(CU, ImportedModules.getElement(i));
+ // If we're splitting the dwarf out now that we've got the entire
+ // CU then construct a skeleton CU based upon it.
+ if (useSplitDwarf()) {
+ // This should be a unique identifier when we want to build .dwp files.
+ CU->addUInt(CU->getCUDie(), dwarf::DW_AT_GNU_dwo_id,
+ dwarf::DW_FORM_data8, 0);
+ // Now construct the skeleton CU associated.
+ constructSkeletonCU(CUNode);
+ }
}
// Tell MMI that we have debug info.
@@ -1098,7 +1131,13 @@ static DotDebugLocEntry getDebugLocEntry(AsmPrinter *Asm,
}
if (MI->getOperand(0).isReg() && MI->getOperand(1).isImm()) {
MachineLocation MLoc;
- MLoc.set(MI->getOperand(0).getReg(), MI->getOperand(1).getImm());
+ // TODO: Currently an offset of 0 in a DBG_VALUE means
+ // we need to generate a direct register value.
+ // There is no way to specify an indirect value with offset 0.
+ if (MI->getOperand(1).getImm() == 0)
+ MLoc.set(MI->getOperand(0).getReg());
+ else
+ MLoc.set(MI->getOperand(0).getReg(), MI->getOperand(1).getImm());
return DotDebugLocEntry(FLabel, SLabel, MLoc, Var);
}
if (MI->getOperand(0).isImm())
@@ -1671,8 +1710,8 @@ DwarfUnits::computeSizeAndOffset(DIE *Die, unsigned Offset) {
// Start the size with the size of abbreviation code.
Offset += MCAsmInfo::getULEB128Size(AbbrevNumber);
- const SmallVector<DIEValue*, 32> &Values = Die->getValues();
- const SmallVector<DIEAbbrevData, 8> &AbbrevData = Abbrev->getData();
+ const SmallVectorImpl<DIEValue*> &Values = Die->getValues();
+ const SmallVectorImpl<DIEAbbrevData> &AbbrevData = Abbrev->getData();
// Size the DIE attribute values.
for (unsigned i = 0, N = Values.size(); i < N; ++i)
@@ -1699,7 +1738,7 @@ DwarfUnits::computeSizeAndOffset(DIE *Die, unsigned Offset) {
void DwarfUnits::computeSizeAndOffsets() {
// Offset from the beginning of debug info section.
unsigned AccuOffset = 0;
- for (SmallVector<CompileUnit *, 1>::iterator I = CUs.begin(),
+ for (SmallVectorImpl<CompileUnit *>::iterator I = CUs.begin(),
E = CUs.end(); I != E; ++I) {
(*I)->setDebugInfoOffset(AccuOffset);
unsigned Offset =
@@ -1739,9 +1778,12 @@ void DwarfDebug::emitSectionLabels() {
emitSectionSym(Asm, TLOF.getDwarfPubTypesSection());
DwarfStrSectionSym =
emitSectionSym(Asm, TLOF.getDwarfStrSection(), "info_string");
- if (useSplitDwarf())
+ if (useSplitDwarf()) {
DwarfStrDWOSectionSym =
emitSectionSym(Asm, TLOF.getDwarfStrDWOSection(), "skel_string");
+ DwarfAddrSectionSym =
+ emitSectionSym(Asm, TLOF.getDwarfAddrSection(), "addr_sec");
+ }
DwarfDebugRangeSectionSym = emitSectionSym(Asm, TLOF.getDwarfRangesSection(),
"debug_range");
@@ -1766,8 +1808,8 @@ void DwarfDebug::emitDIE(DIE *Die, std::vector<DIEAbbrev *> *Abbrevs) {
dwarf::TagString(Abbrev->getTag()));
Asm->EmitULEB128(AbbrevNumber);
- const SmallVector<DIEValue*, 32> &Values = Die->getValues();
- const SmallVector<DIEAbbrevData, 8> &AbbrevData = Abbrev->getData();
+ const SmallVectorImpl<DIEValue*> &Values = Die->getValues();
+ const SmallVectorImpl<DIEAbbrevData> &AbbrevData = Abbrev->getData();
// Emit the DIE attribute values.
for (unsigned i = 0, N = Values.size(); i < N; ++i) {
@@ -1855,7 +1897,7 @@ void DwarfUnits::emitUnits(DwarfDebug *DD,
const MCSection *ASection,
const MCSymbol *ASectionSym) {
Asm->OutStreamer.SwitchSection(USection);
- for (SmallVector<CompileUnit *, 1>::iterator I = CUs.begin(),
+ for (SmallVectorImpl<CompileUnit *>::iterator I = CUs.begin(),
E = CUs.end(); I != E; ++I) {
CompileUnit *TheCU = *I;
DIE *Die = TheCU->getCUDie();
@@ -1891,7 +1933,7 @@ void DwarfUnits::emitUnits(DwarfDebug *DD,
unsigned DwarfUnits::getCUOffset(DIE *Die) {
assert(Die->getTag() == dwarf::DW_TAG_compile_unit &&
"Input DIE should be compile unit in getCUOffset.");
- for (SmallVector<CompileUnit *, 1>::iterator I = CUs.begin(),
+ for (SmallVectorImpl<CompileUnit *>::iterator I = CUs.begin(),
E = CUs.end(); I != E; ++I) {
CompileUnit *TheCU = *I;
if (TheCU->getCUDie() == Die)
@@ -2284,7 +2326,7 @@ void DwarfDebug::emitDebugLoc() {
if (DotDebugLocEntries.empty())
return;
- for (SmallVector<DotDebugLocEntry, 4>::iterator
+ for (SmallVectorImpl<DotDebugLocEntry>::iterator
I = DotDebugLocEntries.begin(), E = DotDebugLocEntries.end();
I != E; ++I) {
DotDebugLocEntry &Entry = *I;
@@ -2298,7 +2340,7 @@ void DwarfDebug::emitDebugLoc() {
unsigned char Size = Asm->getDataLayout().getPointerSize();
Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("debug_loc", 0));
unsigned index = 1;
- for (SmallVector<DotDebugLocEntry, 4>::iterator
+ for (SmallVectorImpl<DotDebugLocEntry>::iterator
I = DotDebugLocEntries.begin(), E = DotDebugLocEntries.end();
I != E; ++I, ++index) {
DotDebugLocEntry &Entry = *I;
@@ -2391,7 +2433,7 @@ void DwarfDebug::emitDebugRanges() {
Asm->OutStreamer.SwitchSection(
Asm->getObjFileLowering().getDwarfRangesSection());
unsigned char Size = Asm->getDataLayout().getPointerSize();
- for (SmallVector<const MCSymbol *, 8>::iterator
+ for (SmallVectorImpl<const MCSymbol *>::iterator
I = DebugRangeSymbols.begin(), E = DebugRangeSymbols.end();
I != E; ++I) {
if (*I)
@@ -2449,13 +2491,13 @@ void DwarfDebug::emitDebugInlineInfo() {
Asm->OutStreamer.AddComment("Address Size (in bytes)");
Asm->EmitInt8(Asm->getDataLayout().getPointerSize());
- for (SmallVector<const MDNode *, 4>::iterator I = InlinedSPNodes.begin(),
+ for (SmallVectorImpl<const MDNode *>::iterator I = InlinedSPNodes.begin(),
E = InlinedSPNodes.end(); I != E; ++I) {
const MDNode *Node = *I;
DenseMap<const MDNode *, SmallVector<InlineInfoLabels, 4> >::iterator II
= InlineInfo.find(Node);
- SmallVector<InlineInfoLabels, 4> &Labels = II->second;
+ SmallVectorImpl<InlineInfoLabels> &Labels = II->second;
DISubprogram SP(Node);
StringRef LName = SP.getLinkageName();
StringRef Name = SP.getName();
@@ -2474,7 +2516,7 @@ void DwarfDebug::emitDebugInlineInfo() {
DwarfStrSectionSym);
Asm->EmitULEB128(Labels.size(), "Inline count");
- for (SmallVector<InlineInfoLabels, 4>::iterator LI = Labels.begin(),
+ for (SmallVectorImpl<InlineInfoLabels>::iterator LI = Labels.begin(),
LE = Labels.end(); LI != LE; ++LI) {
if (Asm->isVerbose()) Asm->OutStreamer.AddComment("DIE offset");
Asm->EmitInt32(LI->second->getOffset());
@@ -2509,9 +2551,14 @@ CompileUnit *DwarfDebug::constructSkeletonCU(const MDNode *N) {
// This should be a unique identifier when we want to build .dwp files.
NewCU->addUInt(Die, dwarf::DW_AT_GNU_dwo_id, dwarf::DW_FORM_data8, 0);
- // FIXME: The addr base should be relative for each compile unit, however,
- // this one is going to be 0 anyhow.
- NewCU->addUInt(Die, dwarf::DW_AT_GNU_addr_base, dwarf::DW_FORM_sec_offset, 0);
+ // Relocate to the beginning of the addr_base section, else 0 for the
+ // beginning of the one for this compile unit.
+ if (Asm->MAI->doesDwarfUseRelocationsAcrossSections())
+ NewCU->addLabel(Die, dwarf::DW_AT_GNU_addr_base, dwarf::DW_FORM_sec_offset,
+ DwarfAddrSectionSym);
+ else
+ NewCU->addUInt(Die, dwarf::DW_AT_GNU_addr_base,
+ dwarf::DW_FORM_sec_offset, 0);
// 2.17.1 requires that we use DW_AT_low_pc for a single entry point
// into an entity. We're using 0, or a NULL label for this.
@@ -2519,6 +2566,7 @@ CompileUnit *DwarfDebug::constructSkeletonCU(const MDNode *N) {
// DW_AT_stmt_list is a offset of line number information for this
// compile unit in debug_line section.
+ // FIXME: Should handle multiple compile units.
if (Asm->MAI->doesDwarfUseRelocationsAcrossSections())
NewCU->addLabel(Die, dwarf::DW_AT_stmt_list, dwarf::DW_FORM_sec_offset,
DwarfLineSectionSym);
diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.h b/lib/CodeGen/AsmPrinter/DwarfDebug.h
index 81e345e..1eb7e3e 100644
--- a/lib/CodeGen/AsmPrinter/DwarfDebug.h
+++ b/lib/CodeGen/AsmPrinter/DwarfDebug.h
@@ -392,7 +392,7 @@ class DwarfDebug {
// section offsets and are created by EmitSectionLabels.
MCSymbol *DwarfInfoSectionSym, *DwarfAbbrevSectionSym;
MCSymbol *DwarfStrSectionSym, *TextSectionSym, *DwarfDebugRangeSectionSym;
- MCSymbol *DwarfDebugLocSectionSym, *DwarfLineSectionSym;
+ MCSymbol *DwarfDebugLocSectionSym, *DwarfLineSectionSym, *DwarfAddrSectionSym;
MCSymbol *FunctionBeginSym, *FunctionEndSym;
MCSymbol *DwarfAbbrevDWOSectionSym, *DwarfStrDWOSectionSym;
@@ -555,6 +555,9 @@ private:
/// \brief Construct subprogram DIE.
void constructSubprogramDIE(CompileUnit *TheCU, const MDNode *N);
+ /// \brief Construct import_module DIE.
+ void constructImportedModuleDIE(CompileUnit *TheCU, const MDNode *N);
+
/// \brief Register a source line with debug info. Returns the unique
/// label that was emitted and which provides correspondence to the
/// source line list.
diff --git a/lib/CodeGen/AsmPrinter/ErlangGCPrinter.cpp b/lib/CodeGen/AsmPrinter/ErlangGCPrinter.cpp
new file mode 100644
index 0000000..a8fb66d
--- /dev/null
+++ b/lib/CodeGen/AsmPrinter/ErlangGCPrinter.cpp
@@ -0,0 +1,120 @@
+//===-- ErlangGCPrinter.cpp - Erlang/OTP frametable emitter -----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the compiler plugin that is used in order to emit
+// garbage collection information in a convenient layout for parsing and
+// loading in the Erlang/OTP runtime.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/CodeGen/AsmPrinter.h"
+#include "llvm/CodeGen/GCs.h"
+#include "llvm/CodeGen/GCMetadataPrinter.h"
+#include "llvm/IR/DataLayout.h"
+#include "llvm/IR/Function.h"
+#include "llvm/IR/Instruction.h"
+#include "llvm/IR/IntrinsicInst.h"
+#include "llvm/IR/Metadata.h"
+#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCSectionELF.h"
+#include "llvm/MC/MCStreamer.h"
+#include "llvm/MC/MCSymbol.h"
+#include "llvm/Target/TargetLoweringObjectFile.h"
+#include "llvm/Target/TargetMachine.h"
+
+using namespace llvm;
+
+namespace {
+
+ class ErlangGCPrinter : public GCMetadataPrinter {
+ public:
+ void beginAssembly(AsmPrinter &AP);
+ void finishAssembly(AsmPrinter &AP);
+ };
+
+}
+
+static GCMetadataPrinterRegistry::Add<ErlangGCPrinter>
+X("erlang", "erlang-compatible garbage collector");
+
+void llvm::linkErlangGCPrinter() { }
+
+void ErlangGCPrinter::beginAssembly(AsmPrinter &AP) { }
+
+void ErlangGCPrinter::finishAssembly(AsmPrinter &AP) {
+ MCStreamer &OS = AP.OutStreamer;
+ unsigned IntPtrSize = AP.TM.getDataLayout()->getPointerSize();
+
+ // Put this in a custom .note section.
+ AP.OutStreamer.SwitchSection(AP.getObjFileLowering().getContext()
+ .getELFSection(".note.gc", ELF::SHT_PROGBITS, 0,
+ SectionKind::getDataRel()));
+
+ // For each function...
+ for (iterator FI = begin(), FE = end(); FI != FE; ++FI) {
+ GCFunctionInfo &MD = **FI;
+
+ /** A compact GC layout. Emit this data structure:
+ *
+ * struct {
+ * int16_t PointCount;
+ * void *SafePointAddress[PointCount];
+ * int16_t StackFrameSize; (in words)
+ * int16_t StackArity;
+ * int16_t LiveCount;
+ * int16_t LiveOffsets[LiveCount];
+ * } __gcmap_<FUNCTIONNAME>;
+ **/
+
+ // Align to address width.
+ AP.EmitAlignment(IntPtrSize == 4 ? 2 : 3);
+
+ // Emit PointCount.
+ OS.AddComment("safe point count");
+ AP.EmitInt16(MD.size());
+
+ // And each safe point...
+ for (GCFunctionInfo::iterator PI = MD.begin(), PE = MD.end(); PI != PE;
+ ++PI) {
+ // Emit the address of the safe point.
+ OS.AddComment("safe point address");
+ MCSymbol *Label = PI->Label;
+ AP.EmitLabelPlusOffset(Label/*Hi*/, 0/*Offset*/, 4/*Size*/);
+ }
+
+ // Stack information never change in safe points! Only print info from the
+ // first call-site.
+ GCFunctionInfo::iterator PI = MD.begin();
+
+ // Emit the stack frame size.
+ OS.AddComment("stack frame size (in words)");
+ AP.EmitInt16(MD.getFrameSize() / IntPtrSize);
+
+ // Emit stack arity, i.e. the number of stacked arguments.
+ unsigned RegisteredArgs = IntPtrSize == 4 ? 5 : 6;
+ unsigned StackArity = MD.getFunction().arg_size() > RegisteredArgs ?
+ MD.getFunction().arg_size() - RegisteredArgs : 0;
+ OS.AddComment("stack arity");
+ AP.EmitInt16(StackArity);
+
+ // Emit the number of live roots in the function.
+ OS.AddComment("live root count");
+ AP.EmitInt16(MD.live_size(PI));
+
+ // And for each live root...
+ for (GCFunctionInfo::live_iterator LI = MD.live_begin(PI),
+ LE = MD.live_end(PI);
+ LI != LE; ++LI) {
+ // Emit live root's offset within the stack frame.
+ OS.AddComment("stack index (offset / wordsize)");
+ AP.EmitInt16(LI->StackOffset / IntPtrSize);
+ }
+ }
+}