#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineLocation.h"
+#include "llvm/Support/Debug.h"
#include "llvm/Support/Dwarf.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/DataTypes.h"
unsigned getOffset() const { return Offset; }
unsigned getSize() const { return Size; }
const std::vector<DIE *> &getChildren() const { return Children; }
- const std::vector<DIEValue *> &getValues() const { return Values; }
+ std::vector<DIEValue *> &getValues() { return Values; }
void setTag(unsigned Tag) { Abbrev.setTag(Tag); }
void setOffset(unsigned O) { Offset = O; }
void setSize(unsigned S) { Size = S; }
/// EmitValue - Emit value via the Dwarf writer.
///
- virtual void EmitValue(const DwarfDebug &DD, unsigned Form) const = 0;
+ virtual void EmitValue(DwarfDebug &DD, unsigned Form) = 0;
/// SizeOf - Return the size of a value in bytes.
///
/// EmitValue - Emit integer of appropriate size.
///
- virtual void EmitValue(const DwarfDebug &DD, unsigned Form) const;
+ virtual void EmitValue(DwarfDebug &DD, unsigned Form);
/// SizeOf - Determine size of integer value in bytes.
///
/// EmitValue - Emit string value.
///
- virtual void EmitValue(const DwarfDebug &DD, unsigned Form) const;
+ virtual void EmitValue(DwarfDebug &DD, unsigned Form);
/// SizeOf - Determine size of string value in bytes.
///
/// EmitValue - Emit label value.
///
- virtual void EmitValue(const DwarfDebug &DD, unsigned Form) const;
+ virtual void EmitValue(DwarfDebug &DD, unsigned Form);
/// SizeOf - Determine size of label value in bytes.
///
/// EmitValue - Emit label value.
///
- virtual void EmitValue(const DwarfDebug &DD, unsigned Form) const;
+ virtual void EmitValue(DwarfDebug &DD, unsigned Form);
/// SizeOf - Determine size of label value in bytes.
///
/// EmitValue - Emit delta value.
///
- virtual void EmitValue(const DwarfDebug &DD, unsigned Form) const;
+ virtual void EmitValue(DwarfDebug &DD, unsigned Form);
/// SizeOf - Determine size of delta value in bytes.
///
/// EmitValue - Emit debug information entry offset.
///
- virtual void EmitValue(const DwarfDebug &DD, unsigned Form) const;
+ virtual void EmitValue(DwarfDebug &DD, unsigned Form);
/// SizeOf - Determine size of debug information entry in bytes.
///
/// EmitValue - Emit block data.
///
- virtual void EmitValue(const DwarfDebug &DD, unsigned Form) const;
+ virtual void EmitValue(DwarfDebug &DD, unsigned Form);
/// SizeOf - Determine size of block data in bytes.
///
/// SubprogramCount - The running count of functions being compiled.
///
unsigned SubprogramCount;
-
+
+ unsigned SetCounter;
Dwarf(std::ostream &OS, AsmPrinter *A, const TargetAsmInfo *T)
: O(OS)
, Asm(A)
, MF(NULL)
, MMI(NULL)
, SubprogramCount(0)
+ , SetCounter(1)
{
}
void PrintLabelName(DWLabel Label) const {
PrintLabelName(Label.Tag, Label.Number);
}
- void PrintLabelName(const char *Tag, unsigned Number) const {
- O << TAI->getPrivateGlobalPrefix() << Tag;
+ void PrintLabelName(const char *Tag, unsigned Number,
+ bool isInSection = false) const {
+ if (isInSection && TAI->getDwarfSectionOffsetDirective())
+ O << TAI->getDwarfSectionOffsetDirective() << Tag;
+ else
+ O << TAI->getPrivateGlobalPrefix() << Tag;
if (Number) O << Number;
}
/// assemblers do not behave with absolute expressions with data directives,
/// so there is an option (needsSet) to use an intermediary set expression.
void EmitDifference(DWLabel LabelHi, DWLabel LabelLo,
- bool IsSmall = false) const {
+ bool IsSmall = false) {
EmitDifference(LabelHi.Tag, LabelHi.Number,
LabelLo.Tag, LabelLo.Number,
IsSmall);
}
void EmitDifference(const char *TagHi, unsigned NumberHi,
const char *TagLo, unsigned NumberLo,
- bool IsSmall = false) const {
+ bool IsSmall = false) {
if (TAI->needsSet()) {
- static unsigned SetCounter = 1;
-
O << "\t.set\t";
PrintLabelName("set", SetCounter);
O << ",";
PrintLabelName(TagLo, NumberLo);
}
}
-
+
+ void EmitSectionOffset(const char* Label, const char* Section,
+ unsigned LabelNumber, unsigned SectionNumber,
+ bool IsSmall = false) {
+ if (TAI->needsSet()) {
+ O << "\t.set\t";
+ PrintLabelName("set", SetCounter);
+ O << ",";
+ PrintLabelName(Label, LabelNumber, true);
+ if (!TAI->isAbsoluteSectionOffsets()) {
+ O << "-";
+ PrintLabelName(Section, SectionNumber);
+ }
+ O << "\n";
+
+ if (IsSmall || TAI->getAddressSize() == sizeof(int32_t))
+ O << TAI->getData32bitsDirective();
+ else
+ O << TAI->getData64bitsDirective();
+
+ PrintLabelName("set", SetCounter);
+ ++SetCounter;
+ } else {
+ if (IsSmall || TAI->getAddressSize() == sizeof(int32_t))
+ O << TAI->getData32bitsDirective();
+ else
+ O << TAI->getData64bitsDirective();
+
+ PrintLabelName(Label, LabelNumber, true);
+ if (!TAI->isAbsoluteSectionOffsets()) {
+ O << "-";
+ PrintLabelName(Section, SectionNumber);
+ }
+ }
+ }
+
/// EmitFrameMoves - Emit frame instructions to describe the layout of the
/// frame.
void EmitFrameMoves(const char *BaseLabel, unsigned BaseLabelID,
CompileUnit *NewCompileUnit(CompileUnitDesc *UnitDesc, unsigned ID) {
// Construct debug information entry.
DIE *Die = new DIE(DW_TAG_compile_unit);
- AddDelta(Die, DW_AT_stmt_list, DW_FORM_data4, DWLabel("section_line", 0),
- DWLabel("section_line", 0));
+ if (TAI->isAbsoluteSectionOffsets())
+ AddLabel(Die, DW_AT_stmt_list, DW_FORM_data4, DWLabel("section_line", 0));
+ else
+ AddDelta(Die, DW_AT_stmt_list, DW_FORM_data4, DWLabel("section_line", 0),
+ DWLabel("section_line", 0));
AddString(Die, DW_AT_producer, DW_FORM_string, UnitDesc->getProducer());
AddUInt (Die, DW_AT_language, DW_FORM_data1, UnitDesc->getLanguage());
AddString(Die, DW_AT_name, DW_FORM_string, UnitDesc->getFileName());
/// EmitDIE - Recusively Emits a debug information entry.
///
- void EmitDIE(DIE *Die) const {
+ void EmitDIE(DIE *Die) {
// Get the abbreviation for this DIE.
unsigned AbbrevNumber = Die->getAbbrevNumber();
const DIEAbbrev *Abbrev = Abbreviations[AbbrevNumber - 1];
":0x" + utohexstr(Die->getSize()) + " " +
TagString(Abbrev->getTag())));
- const std::vector<DIEValue *> &Values = Die->getValues();
+ std::vector<DIEValue *> &Values = Die->getValues();
const std::vector<DIEAbbrevData> &AbbrevData = Abbrev->getData();
// Emit the DIE attribute values.
/// EmitDebugInfo - Emit the debug info section.
///
- void EmitDebugInfo() const {
+ void EmitDebugInfo() {
// Start debug info section.
Asm->SwitchToDataSection(TAI->getDwarfInfoSection());
Asm->EmitInt32(ContentSize); Asm->EOL("Length of Compilation Unit Info");
Asm->EmitInt16(DWARF_VERSION); Asm->EOL("DWARF version number");
- EmitDifference("abbrev_begin", 0, "section_abbrev", 0, true);
+ EmitSectionOffset("abbrev_begin", "section_abbrev", 0, 0, true);
Asm->EOL("Offset Into Abbrev. Section");
Asm->EmitInt8(TAI->getAddressSize()); Asm->EOL("Address Size (in bytes)");
Asm->EOL();
}
+ // Mark end of abbreviations.
+ Asm->EmitULEB128Bytes(0); Asm->EOL("EOM(3)");
+
EmitLabel("abbrev_end", 0);
Asm->EOL();
/// EmitDebugLines - Emit source line information.
///
- void EmitDebugLines() const {
+ void EmitDebugLines() {
// Minimum line delta, thus ranging from -10..(255-10).
const int MinLineDelta = -(DW_LNS_fixed_advance_pc + 1);
// Maximum line delta, thus ranging from -10..(255-10).
Asm->EOL("Length of Frame Information Entry");
EmitLabel("frame_begin", SubprogramCount);
-
- EmitDifference("frame_common_begin", 0, "section_frame", 0, true);
+
+ EmitSectionOffset("frame_common_begin", "section_frame", 0, 0, true);
Asm->EOL("FDE CIE offset");
EmitReference("func_begin", SubprogramCount);
EmitLabel("pubnames_begin", Unit->getID());
Asm->EmitInt16(DWARF_VERSION); Asm->EOL("DWARF Version");
-
- EmitDifference("info_begin", Unit->getID(), "section_info", 0, true);
+
+ EmitSectionOffset("info_begin", "section_info", Unit->getID(), 0, true);
Asm->EOL("Offset of Compilation Unit Info");
EmitDifference("info_end", Unit->getID(), "info_begin", Unit->getID(),true);
/// shouldEmit - Flag to indicate if debug information should be emitted.
///
bool shouldEmit;
+
+ /// FuncCPPPersonality - C++ persoanlity function.
+ ///
+ Function *FuncCPPPersonality;
- /// EmitInitial - Emit the common eh unwind frame.
+ /// EmitCommonEHFrame - Emit the common eh unwind frame.
///
- void EmitInitial() {
+ void EmitCommonEHFrame() {
+ // Only do it once.
+ if (didInitial) return;
+ didInitial = true;
+
// If there is a personality present then we need to indicate that
// in the common eh frame.
- Function *Personality = MMI->getPersonality();
+ Function *Personality = FuncCPPPersonality;
// Size and sign of stack growth.
int stackGrowth =
void EmitEHFrame() {
// If there is a personality present then we need to indicate that
// in the common eh frame.
- Function *Personality = MMI->getPersonality();
+ Function *Personality = FuncCPPPersonality;
+// Function *Personality = MMI->getPersonality();
MachineFrameInfo *MFI = MF->getFrameInfo();
Asm->SwitchToTextSection(TAI->getDwarfEHFrameSection());
Asm->EOL("Length of Frame Information Entry");
EmitLabel("eh_frame_begin", SubprogramCount);
-
- EmitDifference("eh_frame_begin", SubprogramCount,
- "section_eh_frame", 0, true);
+
+ EmitSectionOffset("eh_frame_begin", "section_eh_frame",
+ SubprogramCount, 0, true);
Asm->EOL("FDE CIE offset");
EmitReference("eh_func_begin", SubprogramCount, true);
"eh_func_begin", SubprogramCount);
Asm->EOL("FDE address range");
- // If there is a personality then point to the language specific data
- // area in the exception table.
+ // If there is a personality and landing pads then point to the language
+ // specific data area in the exception table.
if (Personality) {
Asm->EmitULEB128Bytes(4);
Asm->EOL("Augmentation size");
- EmitReference("exception", SubprogramCount, true);
+
+ if (!MMI->getLandingPads().empty()) {
+ EmitReference("exception", SubprogramCount, true);
+ } else if(TAI->getAddressSize() == 8) {
+ Asm->EmitInt64((int)0);
+ } else {
+ Asm->EmitInt32((int)0);
+ }
Asm->EOL("Language Specific Data Area");
} else {
Asm->EmitULEB128Bytes(0);
// Gather first action index for each landing pad site.
SmallVector<unsigned, 8> Actions;
+
+ // FIXME - Assume there is only one filter typeinfo list per function
+ // time being. I.E., Each call to eh_filter will have the same list.
+ // This can change if a function is inlined.
+ const LandingPadInfo *Filter = 0;
// Compute sizes for exception table.
unsigned SizeHeader = sizeof(int8_t) + // LPStart format
// landing pad site info and the size of the landing pad's actions.
for (unsigned i = 0, N = LandingPads.size(); i != N; ++i) {
const LandingPadInfo &LandingPad = LandingPads[i];
+ bool IsFilter = LandingPad.IsFilter;
unsigned SizeSiteActions = 0;
const std::vector<unsigned> &TypeIds = LandingPad.TypeIds;
unsigned SizeAction = 0;
-
- // Gather the action sizes
- for (unsigned j = 0, M = TypeIds.size(); j != M; ++j) {
- unsigned TypeID = TypeIds[i];
- unsigned SizeTypeID = Asm->SizeULEB128(TypeID);
- signed Action = j ? -(SizeAction + SizeTypeID) : 0;
- SizeAction = SizeTypeID + Asm->SizeSLEB128(Action);
+ signed FirstAction;
+
+ if (IsFilter) {
+ // FIXME - Assume there is only one filter typeinfo list per function
+ // time being. I.E., Each call to eh_filter will have the same list.
+ // This can change if a function is inlined.
+ Filter = &LandingPad;
+ SizeAction = Asm->SizeSLEB128(-1) + Asm->SizeSLEB128(0);
SizeSiteActions += SizeAction;
+ // Record the first action of the landing pad site.
+ FirstAction = SizeActions + SizeSiteActions - SizeAction + 1;
+ } else if (TypeIds.empty()) {
+ FirstAction = 0;
+ } else {
+ // Gather the action sizes
+ for (unsigned j = 0, M = TypeIds.size(); j != M; ++j) {
+ unsigned TypeID = TypeIds[i];
+ unsigned SizeTypeID = Asm->SizeSLEB128(TypeID);
+ signed Action = j ? -(SizeAction + SizeTypeID) : 0;
+ SizeAction = SizeTypeID + Asm->SizeSLEB128(Action);
+ SizeSiteActions += SizeAction;
+ }
+
+ // Record the first action of the landing pad site.
+ FirstAction = SizeActions + SizeSiteActions - SizeAction + 1;
}
- // Record the first action of the landing pad site.
- signed FirstAction = SizeActions + SizeSiteActions - SizeAction + 1;
Actions.push_back(FirstAction);
// Compute this sites contribution to size.
SizeSites += sizeof(int32_t) + // Site start.
sizeof(int32_t) + // Site length.
sizeof(int32_t) + // Landing pad.
- Asm->SizeULEB128(FirstAction); // Action.
+ Asm->SizeSLEB128(FirstAction); // Action.
}
// Final tallies.
// Emit the landng pad site information.
for (unsigned i = 0, N = LandingPads.size(); i != N; ++i) {
const LandingPadInfo &LandingPad = LandingPads[i];
- EmitDifference("label", LandingPad.BeginLabel,
- "eh_func_begin", SubprogramCount);
+ EmitSectionOffset("label", "eh_func_begin",
+ LandingPad.BeginLabel, SubprogramCount);
Asm->EOL("Region start");
EmitDifference("label", LandingPad.EndLabel,
"label", LandingPad.BeginLabel);
Asm->EOL("Region length");
- EmitDifference("label", LandingPad.LandingPadLabel,
- "eh_func_begin", SubprogramCount);
+ if (LandingPad.TypeIds.empty()) {
+ if (TAI->getAddressSize() == sizeof(int32_t))
+ Asm->EmitInt32(0);
+ else
+ Asm->EmitInt64(0);
+ } else {
+ EmitSectionOffset("label", "eh_func_begin",
+ LandingPad.LandingPadLabel, SubprogramCount);
+ }
Asm->EOL("Landing pad");
Asm->EmitULEB128Bytes(Actions[i]);
const std::vector<unsigned> &TypeIds = LandingPad.TypeIds;
unsigned SizeAction = 0;
- for (unsigned j = 0, M = TypeIds.size(); j < M; ++j) {
- unsigned TypeID = TypeIds[j];
- unsigned SizeTypeID = Asm->SizeULEB128(TypeID);
- Asm->EmitSLEB128Bytes(TypeID);
+ if (LandingPad.IsFilter) {
+ Asm->EmitSLEB128Bytes(-1);
Asm->EOL("TypeInfo index");
- signed Action = j ? -(SizeAction + SizeTypeID) : 0;
- SizeAction = SizeTypeID + Asm->SizeSLEB128(Action);
- Asm->EmitSLEB128Bytes(Action);
+ Asm->EmitSLEB128Bytes(0);
Asm->EOL("Next action");
+ } else {
+ for (unsigned j = 0, M = TypeIds.size(); j < M; ++j) {
+ unsigned TypeID = TypeIds[j];
+ unsigned SizeTypeID = Asm->SizeSLEB128(TypeID);
+ Asm->EmitSLEB128Bytes(TypeID);
+ Asm->EOL("TypeInfo index");
+ signed Action = j ? -(SizeAction + SizeTypeID) : 0;
+ SizeAction = SizeTypeID + Asm->SizeSLEB128(Action);
+ Asm->EmitSLEB128Bytes(Action);
+ Asm->EOL("Next action");
+ }
}
}
Asm->EOL("TypeInfo");
}
+ // Emit the filter typeinfo.
+ if (Filter) {
+ const std::vector<unsigned> &TypeIds = Filter->TypeIds;
+ for (unsigned j = 0, M = TypeIds.size(); j < M; ++j) {
+ unsigned TypeID = TypeIds[j];
+ Asm->EmitSLEB128Bytes(TypeID);
+ Asm->EOL("TypeInfo index");
+ }
+ Asm->EmitSLEB128Bytes(0);
+ Asm->EOL("End of filter typeinfo");
+ }
+
+ Asm->EmitAlignment(2);
}
public:
: Dwarf(OS, A, T)
, didInitial(false)
, shouldEmit(false)
+ , FuncCPPPersonality(NULL)
{}
virtual ~DwarfException() {}
- /// ShouldEmitDwarf - Returns true if Dwarf declarations should be made.
- ///
- bool ShouldEmitDwarf() const { return shouldEmit; }
-
/// SetModuleInfo - Set machine module information when it's known that pass
/// manager has created it. Set by the target AsmPrinter.
void SetModuleInfo(MachineModuleInfo *mmi) {
- // Make sure initial declarations are made.
- if (!MMI &&
- ExceptionHandling &&
- TAI->getSupportsExceptionHandling() &&
- mmi->getPersonality()) {
- MMI = mmi;
- shouldEmit = true;
-
- EmitInitial();
- }
+ MMI = mmi;
}
/// BeginModule - Emit all exception information that should come prior to the
/// content.
void BeginModule(Module *M) {
this->M = M;
-
- if (!ShouldEmitDwarf()) return;
+ FuncCPPPersonality = M->getFunction("__gxx_personality_v0");
}
/// EndModule - Emit all exception information that should come after the
/// content.
void EndModule() {
- if (!ShouldEmitDwarf()) return;
}
/// BeginFunction - Gather pre-function exception information. Assumes being
void BeginFunction(MachineFunction *MF) {
this->MF = MF;
- if (!ShouldEmitDwarf()) return;
-
- // Assumes in correct section after the entry point.
- EmitLabel("eh_func_begin", ++SubprogramCount);
+ if (MMI &&
+ ExceptionHandling &&
+ TAI->getSupportsExceptionHandling()) {
+ shouldEmit = true;
+ // Assumes in correct section after the entry point.
+ EmitLabel("eh_func_begin", ++SubprogramCount);
+ }
}
/// EndFunction - Gather and emit post-function exception information.
///
void EndFunction() {
- if (!ShouldEmitDwarf()) return;
+ if (!shouldEmit) return;
EmitLabel("eh_func_end", SubprogramCount);
EmitExceptionTable();
+ EmitCommonEHFrame();
EmitEHFrame();
}
};
/// EmitValue - Emit integer of appropriate size.
///
-void DIEInteger::EmitValue(const DwarfDebug &DD, unsigned Form) const {
+void DIEInteger::EmitValue(DwarfDebug &DD, unsigned Form) {
switch (Form) {
case DW_FORM_flag: // Fall thru
case DW_FORM_ref1: // Fall thru
/// EmitValue - Emit string value.
///
-void DIEString::EmitValue(const DwarfDebug &DD, unsigned Form) const {
+void DIEString::EmitValue(DwarfDebug &DD, unsigned Form) {
DD.getAsm()->EmitString(String);
}
/// EmitValue - Emit label value.
///
-void DIEDwarfLabel::EmitValue(const DwarfDebug &DD, unsigned Form) const {
+void DIEDwarfLabel::EmitValue(DwarfDebug &DD, unsigned Form) {
DD.EmitReference(Label);
}
/// EmitValue - Emit label value.
///
-void DIEObjectLabel::EmitValue(const DwarfDebug &DD, unsigned Form) const {
+void DIEObjectLabel::EmitValue(DwarfDebug &DD, unsigned Form) {
DD.EmitReference(Label);
}
/// EmitValue - Emit delta value.
///
-void DIEDelta::EmitValue(const DwarfDebug &DD, unsigned Form) const {
+void DIEDelta::EmitValue(DwarfDebug &DD, unsigned Form) {
bool IsSmall = Form == DW_FORM_data4;
DD.EmitDifference(LabelHi, LabelLo, IsSmall);
}
/// EmitValue - Emit debug information entry offset.
///
-void DIEntry::EmitValue(const DwarfDebug &DD, unsigned Form) const {
+void DIEntry::EmitValue(DwarfDebug &DD, unsigned Form) {
DD.getAsm()->EmitInt32(Entry->getOffset());
}
/// EmitValue - Emit block data.
///
-void DIEBlock::EmitValue(const DwarfDebug &DD, unsigned Form) const {
+void DIEBlock::EmitValue(DwarfDebug &DD, unsigned Form) {
switch (Form) {
case DW_FORM_block1: DD.getAsm()->EmitInt8(Size); break;
case DW_FORM_block2: DD.getAsm()->EmitInt16(Size); break;
DD->EndFunction();
DE->EndFunction();
- if (MachineModuleInfo *MMI = DD->getMMI()) {
+ if (MachineModuleInfo *MMI = DD->getMMI() ? DD->getMMI() : DE->getMMI()) {
// Clear function debug information.
MMI->EndFunction();
}