#include "llvm/CodeGen/DwarfWriter.h"
+#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/UniqueVector.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/DataTypes.h"
#include "llvm/Support/Mangler.h"
+#include "llvm/System/Path.h"
#include "llvm/Target/TargetAsmInfo.h"
#include "llvm/Target/MRegisterInfo.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetFrameInfo.h"
+#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetOptions.h"
#include <ostream>
//===----------------------------------------------------------------------===//
/// DWLabel - Labels are used to track locations in the assembler file.
-/// Labels appear in the form <prefix><Tag><Number>, where the tag is a
-/// category of label (Ex. location) and number is a value unique in that
-/// category.
+/// 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 DWLabel {
public:
/// Tag - Label category tag. Should always be a staticly declared C string.
std::vector<DIEValue *> Values;
public:
- DIE(unsigned Tag)
+ explicit DIE(unsigned Tag)
: Abbrev(Tag, DW_CHILDREN_no)
, Offset(0)
, Size(0)
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; }
///
unsigned Type;
- DIEValue(unsigned T)
+ explicit DIEValue(unsigned T)
: Type(T)
{}
virtual ~DIEValue() {}
/// 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.
///
uint64_t Integer;
public:
- DIEInteger(uint64_t I) : DIEValue(isInteger), Integer(I) {}
+ explicit DIEInteger(uint64_t I) : DIEValue(isInteger), Integer(I) {}
// Implement isa/cast/dyncast.
static bool classof(const DIEInteger *) { return true; }
/// 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.
///
public:
const std::string String;
- DIEString(const std::string &S) : DIEValue(isString), String(S) {}
+ explicit DIEString(const std::string &S) : DIEValue(isString), String(S) {}
// Implement isa/cast/dyncast.
static bool classof(const DIEString *) { return true; }
/// 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.
///
const DWLabel Label;
- DIEDwarfLabel(const DWLabel &L) : DIEValue(isLabel), Label(L) {}
+ explicit DIEDwarfLabel(const DWLabel &L) : DIEValue(isLabel), Label(L) {}
// Implement isa/cast/dyncast.
static bool classof(const DIEDwarfLabel *) { return true; }
/// 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.
///
public:
const std::string Label;
- DIEObjectLabel(const std::string &L) : DIEValue(isAsIsLabel), Label(L) {}
+ explicit DIEObjectLabel(const std::string &L)
+ : DIEValue(isAsIsLabel), Label(L) {}
// Implement isa/cast/dyncast.
static bool classof(const DIEObjectLabel *) { return true; }
/// 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.
///
public:
DIE *Entry;
- DIEntry(DIE *E) : DIEValue(isEntry), Entry(E) {}
+ explicit DIEntry(DIE *E) : DIEValue(isEntry), Entry(E) {}
// Implement isa/cast/dyncast.
static bool classof(const DIEntry *) { return true; }
/// 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.
///
///
unsigned SubprogramCount;
- Dwarf(std::ostream &OS, AsmPrinter *A, const TargetAsmInfo *T)
+ /// Flavor - A unique string indicating what dwarf producer this is, used to
+ /// unique labels.
+ const char * const Flavor;
+
+ unsigned SetCounter;
+ Dwarf(std::ostream &OS, AsmPrinter *A, const TargetAsmInfo *T,
+ const char *flavor)
: O(OS)
, Asm(A)
, TAI(T)
, MF(NULL)
, MMI(NULL)
, SubprogramCount(0)
+ , Flavor(flavor)
+ , SetCounter(1)
{
}
AsmPrinter *getAsm() const { return Asm; }
MachineModuleInfo *getMMI() const { return MMI; }
const TargetAsmInfo *getTargetAsmInfo() const { return TAI; }
+ const TargetData *getTargetData() const { return TD; }
+ void PrintRelDirective(bool Force32Bit = false, bool isInSection = false)
+ const {
+ if (isInSection && TAI->getDwarfSectionOffsetDirective())
+ O << TAI->getDwarfSectionOffsetDirective();
+ else if (Force32Bit || TD->getPointerSize() == sizeof(int32_t))
+ O << TAI->getData32bitsDirective();
+ else
+ O << TAI->getData64bitsDirective();
+ }
+
/// PrintLabelName - Print label name in form used by Dwarf writer.
///
void PrintLabelName(DWLabel Label) const {
if (Number) O << Number;
}
+ void PrintLabelName(const char *Tag, unsigned Number,
+ const char *Suffix) const {
+ O << TAI->getPrivateGlobalPrefix() << Tag;
+ if (Number) O << Number;
+ O << Suffix;
+ }
+
/// EmitLabel - Emit location label for internal use by Dwarf.
///
void EmitLabel(DWLabel Label) const {
/// EmitReference - Emit a reference to a label.
///
- void EmitReference(DWLabel Label, bool IsPCRelative = false) const {
- EmitReference(Label.Tag, Label.Number, IsPCRelative);
+ void EmitReference(DWLabel Label, bool IsPCRelative = false,
+ bool Force32Bit = false) const {
+ EmitReference(Label.Tag, Label.Number, IsPCRelative, Force32Bit);
}
void EmitReference(const char *Tag, unsigned Number,
- bool IsPCRelative = false) const {
- if (TAI->getAddressSize() == sizeof(int32_t))
- O << TAI->getData32bitsDirective();
- else
- O << TAI->getData64bitsDirective();
-
+ bool IsPCRelative = false, bool Force32Bit = false) const {
+ PrintRelDirective(Force32Bit);
PrintLabelName(Tag, Number);
if (IsPCRelative) O << "-" << TAI->getPCSymbol();
}
- void EmitReference(const std::string &Name, bool IsPCRelative = false) const {
- if (TAI->getAddressSize() == sizeof(int32_t))
- O << TAI->getData32bitsDirective();
- else
- O << TAI->getData64bitsDirective();
-
+ void EmitReference(const std::string &Name, bool IsPCRelative = false,
+ bool Force32Bit = false) const {
+ PrintRelDirective(Force32Bit);
+
O << Name;
if (IsPCRelative) O << "-" << TAI->getPCSymbol();
/// 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);
+ PrintLabelName("set", SetCounter, Flavor);
O << ",";
PrintLabelName(TagHi, NumberHi);
O << "-";
PrintLabelName(TagLo, NumberLo);
O << "\n";
-
- if (IsSmall || TAI->getAddressSize() == sizeof(int32_t))
- O << TAI->getData32bitsDirective();
- else
- O << TAI->getData64bitsDirective();
-
- PrintLabelName("set", SetCounter);
-
+
+ PrintRelDirective(IsSmall);
+ PrintLabelName("set", SetCounter, Flavor);
++SetCounter;
} else {
- if (IsSmall || TAI->getAddressSize() == sizeof(int32_t))
- O << TAI->getData32bitsDirective();
- else
- O << TAI->getData64bitsDirective();
+ PrintRelDirective(IsSmall);
PrintLabelName(TagHi, NumberHi);
O << "-";
PrintLabelName(TagLo, NumberLo);
}
}
-
+
+ void EmitSectionOffset(const char* Label, const char* Section,
+ unsigned LabelNumber, unsigned SectionNumber,
+ bool IsSmall = false, bool isEH = false) {
+ bool printAbsolute = false;
+ if (TAI->needsSet()) {
+ O << "\t.set\t";
+ PrintLabelName("set", SetCounter, Flavor);
+ O << ",";
+ PrintLabelName(Label, LabelNumber);
+
+ if (isEH)
+ printAbsolute = TAI->isAbsoluteEHSectionOffsets();
+ else
+ printAbsolute = TAI->isAbsoluteDebugSectionOffsets();
+
+ if (!printAbsolute) {
+ O << "-";
+ PrintLabelName(Section, SectionNumber);
+ }
+ O << "\n";
+
+ PrintRelDirective(IsSmall);
+
+ PrintLabelName("set", SetCounter, Flavor);
+ ++SetCounter;
+ } else {
+ PrintRelDirective(IsSmall, true);
+
+ PrintLabelName(Label, LabelNumber);
+
+ if (isEH)
+ printAbsolute = TAI->isAbsoluteEHSectionOffsets();
+ else
+ printAbsolute = TAI->isAbsoluteDebugSectionOffsets();
+
+ if (!printAbsolute) {
+ O << "-";
+ PrintLabelName(Section, SectionNumber);
+ }
+ }
+ }
+
/// EmitFrameMoves - Emit frame instructions to describe the layout of the
/// frame.
void EmitFrameMoves(const char *BaseLabel, unsigned BaseLabelID,
- std::vector<MachineMove> &Moves) {
+ const std::vector<MachineMove> &Moves) {
int stackGrowth =
Asm->TM.getFrameInfo()->getStackGrowthDirection() ==
TargetFrameInfo::StackGrowsUp ?
- TAI->getAddressSize() : -TAI->getAddressSize();
+ TD->getPointerSize() : -TD->getPointerSize();
bool IsLocal = BaseLabel && strcmp(BaseLabel, "label") == 0;
for (unsigned i = 0, N = Moves.size(); i < N; ++i) {
- MachineMove &Move = Moves[i];
+ const MachineMove &Move = Moves[i];
unsigned LabelID = Move.getLabelID();
if (LabelID) {
Asm->EOL("Offset");
} else if (Reg < 64) {
Asm->EmitInt8(DW_CFA_offset + Reg);
- Asm->EOL("DW_CFA_offset + Reg");
+ Asm->EOL("DW_CFA_offset + Reg (" + utostr(Reg) + ")");
Asm->EmitULEB128Bytes(Offset);
Asm->EOL("Offset");
} else {
///
bool shouldEmit;
+ struct FunctionDebugFrameInfo {
+ unsigned Number;
+ std::vector<MachineMove> Moves;
+
+ FunctionDebugFrameInfo(unsigned Num, const std::vector<MachineMove> &M):
+ Number(Num), Moves(M) { }
+ };
+
+ std::vector<FunctionDebugFrameInfo> DebugFrames;
+
public:
/// ShouldEmitDwarf - Returns true if Dwarf declarations should be made.
ValuesSet.InsertNode(Value, Where);
Values.push_back(Value);
} else {
+ // Already exists, reuse the previous one.
delete Block;
+ Block = cast<DIEBlock>(Value);
}
Die->AddValue(Attribute, Block->BestForm(), Value);
///
DIE *ConstructPointerType(CompileUnit *Unit, const std::string &Name) {
DIE Buffer(DW_TAG_pointer_type);
- AddUInt(&Buffer, DW_AT_byte_size, 0, TAI->getAddressSize());
+ AddUInt(&Buffer, DW_AT_byte_size, 0, TD->getPointerSize());
if (!Name.empty()) AddString(&Buffer, DW_AT_name, DW_FORM_string, Name);
return Unit->AddDie(Buffer);
}
break;
}
- FromTy = dyn_cast<DerivedTypeDesc>(FromTy)->getFromType();
+ FromTy = cast<DerivedTypeDesc>(FromTy)->getFromType();
}
// Unless we have a bit field.
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->isAbsoluteDebugSectionOffsets())
+ 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());
didInitial = true;
// Dwarf sections base addresses.
- if (TAI->getDwarfRequiresFrameSection()) {
+ if (TAI->doesDwarfRequireFrameSection()) {
Asm->SwitchToDataSection(TAI->getDwarfFrameSection());
- EmitLabel("section_frame", 0);
+ EmitLabel("section_debug_frame", 0);
}
Asm->SwitchToDataSection(TAI->getDwarfInfoSection());
EmitLabel("section_info", 0);
EmitLabel("text_begin", 0);
Asm->SwitchToDataSection(TAI->getDataSection());
EmitLabel("data_begin", 0);
-
- // Emit common frame information.
- EmitInitialDebugFrame();
}
/// 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, false);
Asm->EOL("Offset Into Abbrev. Section");
- Asm->EmitInt8(TAI->getAddressSize()); Asm->EOL("Address Size (in bytes)");
+ Asm->EmitInt8(TD->getPointerSize()); Asm->EOL("Address Size (in bytes)");
EmitDIE(Die);
// FIXME - extra padding for gdb bug.
/// EmitDebugLines - Emit source line information.
///
- void EmitDebugLines() const {
+ void EmitDebugLines() {
+ // If there are no lines to emit (such as when we're using .loc directives
+ // to emit .debug_line information) don't emit a .debug_line header.
+ if (SectionSourceLines.empty())
+ return;
+
// 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).
// Define the line address.
Asm->EmitInt8(0); Asm->EOL("Extended Op");
- Asm->EmitInt8(TAI->getAddressSize() + 1); Asm->EOL("Op size");
+ Asm->EmitInt8(TD->getPointerSize() + 1); Asm->EOL("Op size");
Asm->EmitInt8(DW_LNE_set_address); Asm->EOL("DW_LNE_set_address");
EmitReference("label", LabelID); Asm->EOL("Location label");
// Define last address of section.
Asm->EmitInt8(0); Asm->EOL("Extended Op");
- Asm->EmitInt8(TAI->getAddressSize() + 1); Asm->EOL("Op size");
+ Asm->EmitInt8(TD->getPointerSize() + 1); Asm->EOL("Op size");
Asm->EmitInt8(DW_LNE_set_address); Asm->EOL("DW_LNE_set_address");
EmitReference("section_end", j + 1); Asm->EOL("Section end label");
Asm->EOL();
}
- /// EmitInitialDebugFrame - Emit common frame info into a debug frame section.
+ /// EmitCommonDebugFrame - Emit common frame info into a debug frame section.
///
- void EmitInitialDebugFrame() {
- if (!TAI->getDwarfRequiresFrameSection())
+ void EmitCommonDebugFrame() {
+ if (!TAI->doesDwarfRequireFrameSection())
return;
int stackGrowth =
Asm->TM.getFrameInfo()->getStackGrowthDirection() ==
TargetFrameInfo::StackGrowsUp ?
- TAI->getAddressSize() : -TAI->getAddressSize();
+ TD->getPointerSize() : -TD->getPointerSize();
// Start the dwarf frame section.
Asm->SwitchToDataSection(TAI->getDwarfFrameSection());
- EmitLabel("frame_common", 0);
- EmitDifference("frame_common_end", 0,
- "frame_common_begin", 0, true);
+ EmitLabel("debug_frame_common", 0);
+ EmitDifference("debug_frame_common_end", 0,
+ "debug_frame_common_begin", 0, true);
Asm->EOL("Length of Common Information Entry");
- EmitLabel("frame_common_begin", 0);
+ EmitLabel("debug_frame_common_begin", 0);
Asm->EmitInt32((int)DW_CIE_ID);
Asm->EOL("CIE Identifier Tag");
Asm->EmitInt8(DW_CIE_VERSION);
std::vector<MachineMove> Moves;
RI->getInitialFrameState(Moves);
+
EmitFrameMoves(NULL, 0, Moves);
Asm->EmitAlignment(2);
- EmitLabel("frame_common_end", 0);
+ EmitLabel("debug_frame_common_end", 0);
Asm->EOL();
}
/// EmitFunctionDebugFrame - Emit per function frame info into a debug frame
/// section.
- void EmitFunctionDebugFrame() {
- if (!TAI->getDwarfRequiresFrameSection())
+ void EmitFunctionDebugFrame(const FunctionDebugFrameInfo &DebugFrameInfo) {
+ if (!TAI->doesDwarfRequireFrameSection())
return;
// Start the dwarf frame section.
Asm->SwitchToDataSection(TAI->getDwarfFrameSection());
- EmitDifference("frame_end", SubprogramCount,
- "frame_begin", SubprogramCount, true);
+ EmitDifference("debug_frame_end", DebugFrameInfo.Number,
+ "debug_frame_begin", DebugFrameInfo.Number, true);
Asm->EOL("Length of Frame Information Entry");
- EmitLabel("frame_begin", SubprogramCount);
-
- EmitDifference("frame_common_begin", 0, "section_frame", 0, true);
+ EmitLabel("debug_frame_begin", DebugFrameInfo.Number);
+
+ EmitSectionOffset("debug_frame_common", "section_debug_frame",
+ 0, 0, true, false);
Asm->EOL("FDE CIE offset");
- EmitReference("func_begin", SubprogramCount);
+ EmitReference("func_begin", DebugFrameInfo.Number);
Asm->EOL("FDE initial location");
- EmitDifference("func_end", SubprogramCount,
- "func_begin", SubprogramCount);
+ EmitDifference("func_end", DebugFrameInfo.Number,
+ "func_begin", DebugFrameInfo.Number);
Asm->EOL("FDE address range");
- std::vector<MachineMove> &Moves = MMI->getFrameMoves();
-
- EmitFrameMoves("func_begin", SubprogramCount, Moves);
+ EmitFrameMoves("func_begin", DebugFrameInfo.Number, DebugFrameInfo.Moves);
Asm->EmitAlignment(2);
- EmitLabel("frame_end", SubprogramCount);
+ EmitLabel("debug_frame_end", DebugFrameInfo.Number);
Asm->EOL();
}
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, false);
Asm->EOL("Offset of Compilation Unit Info");
EmitDifference("info_end", Unit->getID(), "info_begin", Unit->getID(),true);
EmitReference("info_begin", Unit->getID());
Asm->EOL("Offset of Compilation Unit Info");
- Asm->EmitInt8(TAI->getAddressSize()); Asm->EOL("Size of Address");
+ Asm->EmitInt8(TD->getPointerSize()); Asm->EOL("Size of Address");
Asm->EmitInt8(0); Asm->EOL("Size of Segment Descriptor");
Asm->EmitInt32(0); Asm->EOL("EOM (1)");
Asm->EmitInt32(0); Asm->EOL("EOM (2)");
+ #endif
Asm->EOL();
- #endif
}
/// EmitDebugRanges - Emit visible names into a debug ranges section.
// Main entry points.
//
DwarfDebug(std::ostream &OS, AsmPrinter *A, const TargetAsmInfo *T)
- : Dwarf(OS, A, T)
+ : Dwarf(OS, A, T, "dbg")
, CompileUnits()
, AbbreviationsSet(InitAbbreviationsSetSize)
, Abbreviations()
MMI = mmi;
shouldEmit = true;
- // Emit initial sections
- EmitInitial();
-
// Create all the compile unit DIEs.
ConstructCompileUnitDIEs();
// Prime section data.
SectionMap.insert(TAI->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()) {
+ const UniqueVector<SourceFileInfo> &SourceFiles = MMI->getSourceFiles();
+ const UniqueVector<std::string> &Directories = MMI->getDirectories();
+ for (unsigned i = 1, e = SourceFiles.size(); i <= e; ++i) {
+ sys::Path FullPath(Directories[SourceFiles[i].getDirectoryID()]);
+ bool AppendOk = FullPath.appendComponent(SourceFiles[i].getName());
+ assert(AppendOk && "Could not append filename to directory!");
+ Asm->EmitFile(i, FullPath.toString());
+ Asm->EOL();
+ }
+ }
+
+ // Emit initial sections
+ EmitInitial();
}
}
Asm->SwitchToTextSection(SectionMap[i].c_str());
EmitLabel("section_end", i);
}
-
+
+ // Emit common frame information.
+ EmitCommonDebugFrame();
+
+ // Emit function debug frame information
+ for (std::vector<FunctionDebugFrameInfo>::iterator I = DebugFrames.begin(),
+ E = DebugFrames.end(); I != E; ++I)
+ EmitFunctionDebugFrame(*I);
+
// Compute DIE offsets and sizes.
SizeAndOffsets();
// Construct scopes for subprogram.
ConstructRootScope(MMI->getRootScope());
-
- // Emit function frame information.
- EmitFunctionDebugFrame();
+
+ DebugFrames.push_back(FunctionDebugFrameInfo(SubprogramCount,
+ MMI->getFrameMoves()));
}
};
class DwarfException : public Dwarf {
private:
+ struct FunctionEHFrameInfo {
+ std::string FnName;
+ unsigned Number;
+ unsigned PersonalityIndex;
+ bool hasCalls;
+ bool hasLandingPads;
+ std::vector<MachineMove> Moves;
- /// didInitial - Flag to indicate if initial emission has been done.
- ///
- bool didInitial;
-
+ FunctionEHFrameInfo(const std::string &FN, unsigned Num, unsigned P,
+ bool hC, bool hL,
+ const std::vector<MachineMove> &M):
+ FnName(FN), Number(Num), PersonalityIndex(P),
+ hasCalls(hC), hasLandingPads(hL), Moves(M) { }
+ };
+
+ std::vector<FunctionEHFrameInfo> EHFrames;
+
/// shouldEmit - Flag to indicate if debug information should be emitted.
///
bool shouldEmit;
- /// FuncCPPPersonality - C++ persoanlity function.
- ///
- Function *FuncCPPPersonality;
-
/// EmitCommonEHFrame - Emit the common eh unwind frame.
///
- 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 = FuncCPPPersonality;
-
+ void EmitCommonEHFrame(const Function *Personality, unsigned Index) {
// Size and sign of stack growth.
int stackGrowth =
Asm->TM.getFrameInfo()->getStackGrowthDirection() ==
TargetFrameInfo::StackGrowsUp ?
- TAI->getAddressSize() : -TAI->getAddressSize();
+ TD->getPointerSize() : -TD->getPointerSize();
// Begin eh frame section.
Asm->SwitchToTextSection(TAI->getDwarfEHFrameSection());
- O << "EH_frame:\n";
- EmitLabel("section_eh_frame", 0);
+ O << "EH_frame" << Index << ":\n";
+ EmitLabel("section_eh_frame", Index);
// Define base labels.
- EmitLabel("eh_frame_common", 0);
+ EmitLabel("eh_frame_common", Index);
// Define the eh frame length.
- EmitDifference("eh_frame_common_end", 0,
- "eh_frame_common_begin", 0, true);
+ EmitDifference("eh_frame_common_end", Index,
+ "eh_frame_common_begin", Index, true);
Asm->EOL("Length of Common Information Entry");
// EH frame header.
- EmitLabel("eh_frame_common_begin", 0);
+ EmitLabel("eh_frame_common_begin", Index);
Asm->EmitInt32((int)0);
Asm->EOL("CIE Identifier Tag");
Asm->EmitInt8(DW_CIE_VERSION);
if (Personality) {
Asm->EmitULEB128Bytes(7);
Asm->EOL("Augmentation Size");
- Asm->EmitInt8(DW_EH_PE_indirect |
- DW_EH_PE_pcrel |
- DW_EH_PE_sdata4);
- Asm->EOL("Personality (indirect pcrel sdata4)");
+
+ if (TAI->getNeedsIndirectEncoding())
+ Asm->EmitInt8(DW_EH_PE_pcrel | DW_EH_PE_sdata4 | DW_EH_PE_indirect);
+ else
+ Asm->EmitInt8(DW_EH_PE_pcrel | DW_EH_PE_sdata4);
+
+ Asm->EOL("Personality (pcrel sdata4 indirect)");
- O << TAI->getData32bitsDirective();
+ PrintRelDirective();
+ O << TAI->getPersonalityPrefix();
Asm->EmitExternalGlobal((const GlobalVariable *)(Personality));
+ O << TAI->getPersonalitySuffix();
O << "-" << TAI->getPCSymbol();
Asm->EOL("Personality");
-
+
Asm->EmitULEB128Bytes(DW_EH_PE_pcrel);
Asm->EOL("LSDA Encoding (pcrel)");
Asm->EmitULEB128Bytes(DW_EH_PE_pcrel);
EmitFrameMoves(NULL, 0, Moves);
Asm->EmitAlignment(2);
- EmitLabel("eh_frame_common_end", 0);
+ EmitLabel("eh_frame_common_end", Index);
Asm->EOL();
}
- /// EmitEHFrame - Emit initial exception information.
+ /// EmitEHFrame - Emit function exception frame information.
///
- void EmitEHFrame() {
- // If there is a personality present then we need to indicate that
- // in the common eh frame.
- Function *Personality = FuncCPPPersonality;
-// Function *Personality = MMI->getPersonality();
- MachineFrameInfo *MFI = MF->getFrameInfo();
-
+ void EmitEHFrame(const FunctionEHFrameInfo &EHFrameInfo) {
Asm->SwitchToTextSection(TAI->getDwarfEHFrameSection());
// Externally visible entry into the functions eh frame info.
if (const char *GlobalDirective = TAI->getGlobalDirective())
- O << GlobalDirective << getAsm()->CurrentFnName << ".eh\n";
+ O << GlobalDirective << EHFrameInfo.FnName << "\n";
// If there are no calls then you can't unwind.
- if (!MFI->hasCalls()) {
- O << getAsm()->CurrentFnName << ".eh = 0\n";
+ if (!EHFrameInfo.hasCalls) {
+ O << EHFrameInfo.FnName << " = 0\n";
} else {
- O << getAsm()->CurrentFnName << ".eh:\n";
+ O << EHFrameInfo.FnName << ":\n";
// EH frame header.
- EmitDifference("eh_frame_end", SubprogramCount,
- "eh_frame_begin", SubprogramCount, true);
+ EmitDifference("eh_frame_end", EHFrameInfo.Number,
+ "eh_frame_begin", EHFrameInfo.Number, true);
Asm->EOL("Length of Frame Information Entry");
- EmitLabel("eh_frame_begin", SubprogramCount);
-
- EmitDifference("eh_frame_begin", SubprogramCount,
- "section_eh_frame", 0, true);
+ EmitLabel("eh_frame_begin", EHFrameInfo.Number);
+
+ EmitSectionOffset("eh_frame_begin", "eh_frame_common",
+ EHFrameInfo.Number, EHFrameInfo.PersonalityIndex,
+ true, true);
Asm->EOL("FDE CIE offset");
- EmitReference("eh_func_begin", SubprogramCount, true);
+ EmitReference("eh_func_begin", EHFrameInfo.Number, true);
Asm->EOL("FDE initial location");
- EmitDifference("eh_func_end", SubprogramCount,
- "eh_func_begin", SubprogramCount);
+ EmitDifference("eh_func_end", EHFrameInfo.Number,
+ "eh_func_begin", EHFrameInfo.Number);
Asm->EOL("FDE address range");
// If there is a personality and landing pads then point to the language
// specific data area in the exception table.
- if (Personality) {
+ if (EHFrameInfo.PersonalityIndex) {
Asm->EmitULEB128Bytes(4);
Asm->EOL("Augmentation size");
- if (!MMI->getLandingPads().empty()) {
- EmitReference("exception", SubprogramCount, true);
- } else if(TAI->getAddressSize() == 8) {
+ if (EHFrameInfo.hasLandingPads) {
+ EmitReference("exception", EHFrameInfo.Number, true);
+ } else if (TD->getPointerSize() == 8) {
Asm->EmitInt64((int)0);
} else {
Asm->EmitInt32((int)0);
// Indicate locations of function specific callee saved registers in
// frame.
- std::vector<MachineMove> &Moves = MMI->getFrameMoves();
- EmitFrameMoves("eh_func_begin", SubprogramCount, Moves);
+ EmitFrameMoves("eh_func_begin", EHFrameInfo.Number, EHFrameInfo.Moves);
Asm->EmitAlignment(2);
- EmitLabel("eh_frame_end", SubprogramCount);
+ EmitLabel("eh_frame_end", EHFrameInfo.Number);
}
if (const char *UsedDirective = TAI->getUsedDirective())
- O << UsedDirective << getAsm()->CurrentFnName << ".eh\n\n";
+ O << UsedDirective << EHFrameInfo.FnName << "\n\n";
}
-
- /// EmitExceptionTable - Emit landpads and actions.
+
+ /// 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
/// 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.
+
+ /// SharedTypeIds - How many leading type ids two landing pads have in common.
+ static unsigned SharedTypeIds(const LandingPadInfo *L,
+ const LandingPadInfo *R) {
+ const std::vector<int> &LIds = L->TypeIds, &RIds = R->TypeIds;
+ unsigned LSize = LIds.size(), RSize = RIds.size();
+ unsigned MinSize = LSize < RSize ? LSize : RSize;
+ unsigned Count = 0;
+
+ for (; Count != MinSize; ++Count)
+ if (LIds[Count] != RIds[Count])
+ return Count;
+
+ return Count;
+ }
+
+ /// PadLT - Order landing pads lexicographically by type id.
+ static bool PadLT(const LandingPadInfo *L, const LandingPadInfo *R) {
+ const std::vector<int> &LIds = L->TypeIds, &RIds = R->TypeIds;
+ unsigned LSize = LIds.size(), RSize = RIds.size();
+ unsigned MinSize = LSize < RSize ? LSize : RSize;
+
+ for (unsigned i = 0; i != MinSize; ++i)
+ if (LIds[i] != RIds[i])
+ return LIds[i] < RIds[i];
+
+ return LSize < RSize;
+ }
+
+ struct KeyInfo {
+ static inline unsigned getEmptyKey() { return -1U; }
+ static inline unsigned getTombstoneKey() { return -2U; }
+ static unsigned getHashValue(const unsigned &Key) { return Key; }
+ static bool isEqual(unsigned LHS, unsigned RHS) { return LHS == RHS; }
+ 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.
+ unsigned PadIndex;
+ // The index of the begin and end labels in the landing pad's label lists.
+ unsigned RangeIndex;
+ };
+
+ typedef DenseMap<unsigned, PadRange, KeyInfo> RangeMapType;
+
+ /// CallSiteEntry - Structure describing an entry in the call-site table.
+ struct CallSiteEntry {
+ unsigned BeginLabel; // zero indicates the start of the function.
+ unsigned EndLabel; // zero indicates the end of the function.
+ unsigned PadLabel; // zero indicates that there is no landing pad.
+ unsigned Action;
+ };
+
void EmitExceptionTable() {
// Map all labels and get rid of any dead landing pads.
MMI->TidyLandingPads();
-
+
const std::vector<GlobalVariable *> &TypeInfos = MMI->getTypeInfos();
- const std::vector<LandingPadInfo> &LandingPads = MMI->getLandingPads();
- if (LandingPads.empty()) return;
-
- // FIXME - Should fold actions for multiple landing pads.
-
- // Gather first action index for each landing pad site.
- SmallVector<unsigned, 8> Actions;
+ 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
+ // (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 output using a fixed width encoding.
+ // FilterOffsets[i] holds the byte offset corresponding to FilterIds[i].
+ 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) {
+ FilterOffsets.push_back(Offset);
+ Offset -= Asm->SizeULEB128(*I);
+ }
- // Compute sizes for exception table.
- unsigned SizeHeader = sizeof(int8_t) + // LPStart format
- sizeof(int8_t) + // TType format
- sizeof(int8_t) + // TType base offset (NEED ULEB128)
- sizeof(int8_t) + // Call site format
- sizeof(int8_t); // Call-site table length
- unsigned SizeSites = 0;
- unsigned SizeActions = 0;
+ // 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());
- // Look at each landing pad site to compute size. We need the size of each
- // landing pad site info and the size of the landing pad's actions.
+ int FirstAction = 0;
+ unsigned SizeActions = 0;
for (unsigned i = 0, N = LandingPads.size(); i != N; ++i) {
- const LandingPadInfo &LandingPad = LandingPads[i];
+ const LandingPadInfo *LP = LandingPads[i];
+ const std::vector<int> &TypeIds = LP->TypeIds;
+ const unsigned NumShared = i ? SharedTypeIds(LP, LandingPads[i-1]) : 0;
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);
- SizeSiteActions += SizeAction;
- }
-
- // Record the first action of the landing pad site.
- signed FirstAction = SizeActions + SizeSiteActions - SizeAction + 1;
- Actions.push_back(FirstAction);
-
+
+ if (NumShared < TypeIds.size()) {
+ unsigned SizeAction = 0;
+ ActionEntry *PrevAction = 0;
+
+ if (NumShared) {
+ const unsigned SizePrevIds = LandingPads[i-1]->TypeIds.size();
+ assert(Actions.size());
+ PrevAction = &Actions.back();
+ SizeAction = Asm->SizeSLEB128(PrevAction->NextAction) +
+ Asm->SizeSLEB128(PrevAction->ValueForTypeID);
+ for (unsigned j = NumShared; j != SizePrevIds; ++j) {
+ SizeAction -= Asm->SizeSLEB128(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!");
+ int ValueForTypeID = TypeID < 0 ? FilterOffsets[-1 - TypeID] : TypeID;
+ unsigned SizeTypeID = Asm->SizeSLEB128(ValueForTypeID);
+
+ int NextAction = SizeAction ? -(SizeAction + SizeTypeID) : 0;
+ SizeAction = SizeTypeID + Asm->SizeSLEB128(NextAction);
+ SizeSiteActions += SizeAction;
+
+ ActionEntry Action = {ValueForTypeID, NextAction, PrevAction};
+ Actions.push_back(Action);
+
+ PrevAction = &Actions.back();
+ }
+
+ // Record the first action of the landing pad site.
+ FirstAction = SizeActions + SizeSiteActions - SizeAction + 1;
+ } // else identical - re-use previous FirstAction
+
+ FirstActions.push_back(FirstAction);
+
// Compute this sites contribution to size.
SizeActions += SizeSiteActions;
- SizeSites += sizeof(int32_t) + // Site start.
- sizeof(int32_t) + // Site length.
- sizeof(int32_t) + // Landing pad.
- Asm->SizeULEB128(FirstAction); // Action.
}
-
+
+ // Compute the call-site table. Entries must be ordered by address.
+ SmallVector<CallSiteEntry, 64> CallSites;
+
+ 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;
+ }
+ }
+
+ bool MayThrow = false;
+ unsigned LastLabel = 0;
+ const TargetInstrInfo *TII = MF->getTarget().getInstrInfo();
+ for (MachineFunction::const_iterator I = MF->begin(), E = MF->end();
+ I != E; ++I) {
+ for (MachineBasicBlock::const_iterator MI = I->begin(), E = I->end();
+ MI != E; ++MI) {
+ if (MI->getOpcode() != TargetInstrInfo::LABEL) {
+ MayThrow |= TII->isCall(MI->getOpcode());
+ continue;
+ }
+
+ unsigned BeginLabel = MI->getOperand(0).getImmedValue();
+ assert(BeginLabel && "Invalid label!");
+
+ if (BeginLabel == LastLabel)
+ MayThrow = false;
+
+ RangeMapType::iterator L = PadMap.find(BeginLabel);
+
+ if (L == PadMap.end())
+ continue;
+
+ 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 (MayThrow) {
+ CallSiteEntry Site = {LastLabel, BeginLabel, 0, 0};
+ CallSites.push_back(Site);
+ }
+
+ LastLabel = LandingPad->EndLabels[P.RangeIndex];
+ CallSiteEntry Site = {BeginLabel, LastLabel,
+ LandingPad->LandingPadLabel, FirstActions[P.PadIndex]};
+
+ assert(Site.BeginLabel && Site.EndLabel && Site.PadLabel &&
+ "Invalid landing pad!");
+
+ // Try to merge with the previous call-site.
+ if (CallSites.size()) {
+ CallSiteEntry &Prev = CallSites[CallSites.size()-1];
+ if (Site.PadLabel == Prev.PadLabel && Site.Action == Prev.Action) {
+ // Extend the range of the previous entry.
+ Prev.EndLabel = Site.EndLabel;
+ continue;
+ }
+ }
+
+ // Otherwise, create a new call-site.
+ CallSites.push_back(Site);
+ }
+ }
+ // 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 (MayThrow) {
+ CallSiteEntry Site = {LastLabel, 0, 0, 0};
+ CallSites.push_back(Site);
+ }
+
// Final tallies.
- unsigned SizeTypes = TypeInfos.size() * TAI->getAddressSize();
- unsigned SizePreType = SizeHeader + SizeSites + SizeActions;
- unsigned SizeAlign = (4 - SizePreType) & 3;
- unsigned TypeOffset = SizePreType +
- SizeTypes +
- SizeAlign -
- sizeof(int8_t) - // LPStart format
- sizeof(int8_t) - // TType format
- sizeof(int8_t); // TType base offset (NEED ULEB128)
-
+ unsigned SizeSites = CallSites.size() * (sizeof(int32_t) + // Site start.
+ sizeof(int32_t) + // Site length.
+ sizeof(int32_t)); // Landing pad.
+ for (unsigned i = 0, e = CallSites.size(); i < e; ++i)
+ SizeSites += Asm->SizeULEB128(CallSites[i].Action);
+
+ unsigned SizeTypes = TypeInfos.size() * TD->getPointerSize();
+
+ unsigned TypeOffset = sizeof(int8_t) + // Call site format
+ Asm->SizeULEB128(SizeSites) + // Call-site table length
+ SizeSites + SizeActions + SizeTypes;
+
+ unsigned TotalSize = sizeof(int8_t) + // LPStart format
+ sizeof(int8_t) + // TType format
+ Asm->SizeULEB128(TypeOffset) + // TType base offset
+ TypeOffset;
+
+ unsigned SizeAlign = (4 - TotalSize) & 3;
+
// Begin the exception table.
Asm->SwitchToDataSection(TAI->getDwarfExceptionSection());
O << "GCC_except_table" << SubprogramCount << ":\n";
+ Asm->EmitAlignment(2);
+ for (unsigned i = 0; i != SizeAlign; ++i) {
+ Asm->EmitInt8(0);
+ Asm->EOL("Padding");
+ }
EmitLabel("exception", SubprogramCount);
-
+
// Emit the header.
Asm->EmitInt8(DW_EH_PE_omit);
Asm->EOL("LPStart format (DW_EH_PE_omit)");
Asm->EOL("Call site format (DW_EH_PE_udata4)");
Asm->EmitULEB128Bytes(SizeSites);
Asm->EOL("Call-site table length");
-
- // 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);
+
+ // 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;
+ }
+
+ EmitSectionOffset(BeginTag, "eh_func_begin", BeginNumber, SubprogramCount,
+ false, true);
Asm->EOL("Region start");
-
- EmitDifference("label", LandingPad.EndLabel,
- "label", LandingPad.BeginLabel);
+
+ if (!S.EndLabel) {
+ EmitDifference("eh_func_end", SubprogramCount, BeginTag, BeginNumber);
+ } else {
+ EmitDifference("label", S.EndLabel, BeginTag, BeginNumber);
+ }
Asm->EOL("Region length");
-
- EmitDifference("label", LandingPad.LandingPadLabel,
- "eh_func_begin", SubprogramCount);
+
+ if (!S.PadLabel) {
+ if (TD->getPointerSize() == sizeof(int32_t))
+ Asm->EmitInt32(0);
+ else
+ Asm->EmitInt64(0);
+ } else {
+ EmitSectionOffset("label", "eh_func_begin", S.PadLabel, SubprogramCount,
+ false, true);
+ }
Asm->EOL("Landing pad");
- Asm->EmitULEB128Bytes(Actions[i]);
+ Asm->EmitULEB128Bytes(S.Action);
Asm->EOL("Action");
}
-
+
// Emit the actions.
- for (unsigned i = 0, N = LandingPads.size(); i != N; ++i) {
- const LandingPadInfo &LandingPad = LandingPads[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);
- Asm->EOL("TypeInfo index");
- signed Action = j ? -(SizeAction + SizeTypeID) : 0;
- SizeAction = SizeTypeID + Asm->SizeSLEB128(Action);
- Asm->EmitSLEB128Bytes(Action);
- Asm->EOL("Next action");
- }
+ for (unsigned I = 0, N = Actions.size(); I != N; ++I) {
+ ActionEntry &Action = Actions[I];
+
+ Asm->EmitSLEB128Bytes(Action.ValueForTypeID);
+ Asm->EOL("TypeInfo index");
+ Asm->EmitSLEB128Bytes(Action.NextAction);
+ Asm->EOL("Next action");
}
// Emit the type ids.
- Asm->EmitAlignment(2);
for (unsigned M = TypeInfos.size(); M; --M) {
GlobalVariable *GV = TypeInfos[M - 1];
-
- if (TAI->getAddressSize() == sizeof(int32_t))
- O << TAI->getData32bitsDirective();
- else
- O << TAI->getData64bitsDirective();
+
+ PrintRelDirective();
if (GV)
O << Asm->getGlobalLinkName(GV);
else
O << "0";
-
+
Asm->EOL("TypeInfo");
}
+ // Emit the filter typeids.
+ for (unsigned j = 0, M = FilterIds.size(); j < M; ++j) {
+ unsigned TypeID = FilterIds[j];
+ Asm->EmitULEB128Bytes(TypeID);
+ Asm->EOL("Filter TypeInfo index");
+ }
+
+ Asm->EmitAlignment(2);
}
public:
// Main entry points.
//
DwarfException(std::ostream &OS, AsmPrinter *A, const TargetAsmInfo *T)
- : Dwarf(OS, A, T)
- , didInitial(false)
+ : Dwarf(OS, A, T, "eh")
, shouldEmit(false)
- , FuncCPPPersonality(NULL)
{}
virtual ~DwarfException() {}
/// content.
void BeginModule(Module *M) {
this->M = M;
- FuncCPPPersonality = M->getFunction("__gxx_personality_v0");
}
/// EndModule - Emit all exception information that should come after the
/// content.
void EndModule() {
+ if (!shouldEmit) return;
+
+ const std::vector<Function *> Personalities = MMI->getPersonalities();
+ for (unsigned i =0; i < Personalities.size(); ++i)
+ EmitCommonEHFrame(Personalities[i], i);
+
+ for (std::vector<FunctionEHFrameInfo>::iterator I = EHFrames.begin(),
+ E = EHFrames.end(); I != E; ++I)
+ EmitEHFrame(*I);
}
/// BeginFunction - Gather pre-function exception information. Assumes being
if (MMI &&
ExceptionHandling &&
- TAI->getSupportsExceptionHandling()) {
+ TAI->doesSupportExceptionHandling()) {
shouldEmit = true;
// Assumes in correct section after the entry point.
EmitLabel("eh_func_begin", ++SubprogramCount);
EmitLabel("eh_func_end", SubprogramCount);
EmitExceptionTable();
- EmitCommonEHFrame();
- EmitEHFrame();
+
+ // Save EH frame information
+ EHFrames.
+ push_back(FunctionEHFrameInfo(getAsm()->getCurrentFunctionEHName(MF),
+ SubprogramCount,
+ MMI->getPersonalityIndex(),
+ MF->getFrameInfo()->hasCalls(),
+ !MMI->getLandingPads().empty(),
+ MMI->getFrameMoves()));
}
};
/// 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 {
- DD.EmitReference(Label);
+void DIEDwarfLabel::EmitValue(DwarfDebug &DD, unsigned Form) {
+ bool IsSmall = Form == DW_FORM_data4;
+ DD.EmitReference(Label, false, IsSmall);
}
/// SizeOf - Determine size of label value in bytes.
///
unsigned DIEDwarfLabel::SizeOf(const DwarfDebug &DD, unsigned Form) const {
- return DD.getTargetAsmInfo()->getAddressSize();
+ if (Form == DW_FORM_data4) return 4;
+ return DD.getTargetData()->getPointerSize();
}
//===----------------------------------------------------------------------===//
/// EmitValue - Emit label value.
///
-void DIEObjectLabel::EmitValue(const DwarfDebug &DD, unsigned Form) const {
- DD.EmitReference(Label);
+void DIEObjectLabel::EmitValue(DwarfDebug &DD, unsigned Form) {
+ bool IsSmall = Form == DW_FORM_data4;
+ DD.EmitReference(Label, false, IsSmall);
}
/// SizeOf - Determine size of label value in bytes.
///
unsigned DIEObjectLabel::SizeOf(const DwarfDebug &DD, unsigned Form) const {
- return DD.getTargetAsmInfo()->getAddressSize();
+ if (Form == DW_FORM_data4) return 4;
+ return DD.getTargetData()->getPointerSize();
}
//===----------------------------------------------------------------------===//
/// 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);
}
///
unsigned DIEDelta::SizeOf(const DwarfDebug &DD, unsigned Form) const {
if (Form == DW_FORM_data4) return 4;
- return DD.getTargetAsmInfo()->getAddressSize();
+ return DD.getTargetData()->getPointerSize();
}
//===----------------------------------------------------------------------===//
/// 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;