#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/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>
///
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.
// Dwarf sections base addresses.
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.
Asm->EOL();
}
- /// EmitInitialDebugFrame - Emit common frame info into a debug frame section.
+ /// EmitCommonDebugFrame - Emit common frame info into a debug frame section.
///
- void EmitInitialDebugFrame() {
+ void EmitCommonDebugFrame() {
if (!TAI->doesDwarfRequireFrameSection())
return;
// 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);
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() {
+ 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);
+ EmitLabel("debug_frame_begin", DebugFrameInfo.Number);
- EmitSectionOffset("frame_common", "section_frame", 0, 0, true, false);
+ 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();
}
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()));
}
};
struct FunctionEHFrameInfo {
std::string FnName;
unsigned Number;
+ unsigned PersonalityIndex;
bool hasCalls;
bool hasLandingPads;
std::vector<MachineMove> Moves;
- FunctionEHFrameInfo(const std::string &FN, unsigned Num, bool hC, bool hL,
+ FunctionEHFrameInfo(const std::string &FN, unsigned Num, unsigned P,
+ bool hC, bool hL,
const std::vector<MachineMove> &M):
- FnName(FN), Number(Num), hasCalls(hC), hasLandingPads(hL), Moves(M) { };
+ FnName(FN), Number(Num), PersonalityIndex(P),
+ hasCalls(hC), hasLandingPads(hL), Moves(M) { };
};
std::vector<FunctionEHFrameInfo> EHFrames;
/// EmitCommonEHFrame - Emit the common eh unwind frame.
///
- void EmitCommonEHFrame() {
- // If there is a personality present then we need to indicate that
- // in the common eh frame.
- Function *Personality = MMI->getPersonality();
-
+ void EmitCommonEHFrame(const Function *Personality, unsigned Index) {
// Size and sign of stack growth.
int stackGrowth =
Asm->TM.getFrameInfo()->getStackGrowthDirection() ==
// 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);
EmitFrameMoves(NULL, 0, Moves);
Asm->EmitAlignment(2);
- EmitLabel("eh_frame_common_end", 0);
+ EmitLabel("eh_frame_common_end", Index);
Asm->EOL();
}
/// EmitEHFrame - Emit function exception frame information.
///
void EmitEHFrame(const FunctionEHFrameInfo &EHFrameInfo) {
- // If there is a personality present then we need to indicate that
- // in the common eh frame.
- Function *Personality = MMI->getPersonality();
-
Asm->SwitchToTextSection(TAI->getDwarfEHFrameSection());
// Externally visible entry into the functions eh frame info.
EmitLabel("eh_frame_begin", EHFrameInfo.Number);
- EmitSectionOffset("eh_frame_begin", "section_eh_frame",
- EHFrameInfo.Number, 0, true, true);
+ EmitSectionOffset("eh_frame_begin", "eh_frame_common",
+ EHFrameInfo.Number, EHFrameInfo.PersonalityIndex,
+ true, true);
Asm->EOL("FDE CIE offset");
EmitReference("eh_func_begin", EHFrameInfo.Number, true);
// 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 (const char *UsedDirective = TAI->getUsedDirective())
O << UsedDirective << EHFrameInfo.FnName << ".eh\n\n";
}
-
+
/// EmitExceptionTable - Emit landpads and actions.
///
/// The general organization of the table is complex, but the basic concepts
/// 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 isPod() { return true; }
+ };
+
+ struct PadSite {
+ unsigned PadIndex;
+ unsigned SiteIndex;
+ };
+
+ typedef DenseMap<unsigned, PadSite, KeyInfo> PadMapType;
+
+ struct ActionEntry {
+ int ValueForTypeID; // The value to write - may not be equal to the type id.
+ int NextAction;
+ struct ActionEntry *Previous;
+ };
+
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.
-
+ 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);
+
// 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;
+ SmallVector<unsigned, 64> FirstActions;
+ FirstActions.reserve(PadInfos.size());
+
+ // The actions table.
+ SmallVector<ActionEntry, 32> Actions;
+
+ // 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->SizeSLEB128(*I);
+ }
// Compute sizes for exception table.
unsigned SizeSites = 0;
// 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;
+
for (unsigned i = 0, N = LandingPads.size(); i != N; ++i) {
- const LandingPadInfo &LandingPad = LandingPads[i];
- bool IsFilter = LandingPad.IsFilter;
+ 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;
- 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[j];
- unsigned SizeTypeID = Asm->SizeSLEB128(TypeID);
- signed Action = j ? -(SizeAction + SizeTypeID) : 0;
- SizeAction = SizeTypeID + Asm->SizeSLEB128(Action);
+
+ 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;
- }
- Actions.push_back(FirstAction);
-
+ } // else identical - re-use previous FirstAction
+
+ FirstActions.push_back(FirstAction);
+
// Compute this sites contribution to size.
SizeActions += SizeSiteActions;
- unsigned M = LandingPad.BeginLabels.size();
+ unsigned M = LP->BeginLabels.size();
SizeSites += M*(sizeof(int32_t) + // Site start.
sizeof(int32_t) + // Site length.
sizeof(int32_t) + // Landing pad.
- Asm->SizeSLEB128(FirstAction)); // Action.
+ Asm->SizeULEB128(FirstAction)); // Action.
}
// Final tallies.
Asm->EOL("Call site format (DW_EH_PE_udata4)");
Asm->EmitULEB128Bytes(SizeSites);
Asm->EOL("Call-site table length");
-
- // Emit the landing pad site information.
+
+ // Emit the landing pad site information in order of address.
+ PadMapType 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) {
- EmitSectionOffset("label", "eh_func_begin",
- LandingPad.BeginLabels[j], SubprogramCount,
+ 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!");
+ PadSite P = { i, j };
+ PadMap[BeginLabel] = P;
+ }
+ }
+
+ 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)
+ continue;
+
+ unsigned BeginLabel = MI->getOperand(0).getImmedValue();
+ PadMapType::iterator L = PadMap.find(BeginLabel);
+
+ if (L == PadMap.end())
+ continue;
+
+ PadSite P = L->second;
+ const LandingPadInfo *LandingPad = LandingPads[P.PadIndex];
+
+ assert(BeginLabel == LandingPad->BeginLabels[P.SiteIndex] &&
+ "Inconsistent landing pad map!");
+
+ EmitSectionOffset("label", "eh_func_begin", BeginLabel, SubprogramCount,
false, true);
Asm->EOL("Region start");
-
- EmitDifference("label", LandingPad.EndLabels[j],
- "label", LandingPad.BeginLabels[j]);
+
+ EmitDifference("label", LandingPad->EndLabels[P.SiteIndex],
+ "label", BeginLabel);
Asm->EOL("Region length");
-
- if (LandingPad.TypeIds.empty()) {
+
+ 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, false, true);
+ EmitSectionOffset("label", "eh_func_begin",
+ LandingPad->LandingPadLabel, SubprogramCount,
+ false, true);
}
Asm->EOL("Landing pad");
- Asm->EmitULEB128Bytes(Actions[i]);
+ Asm->EmitULEB128Bytes(FirstActions[P.PadIndex]);
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;
-
- if (LandingPad.IsFilter) {
- Asm->EmitSLEB128Bytes(-1);
- Asm->EOL("TypeInfo index");
- 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");
- }
- }
+ 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->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");
+ // Emit the filter typeids.
+ for (unsigned j = 0, M = FilterIds.size(); j < M; ++j) {
+ unsigned TypeID = FilterIds[j];
+ Asm->EmitSLEB128Bytes(TypeID);
+ Asm->EOL("Filter TypeInfo index");
}
Asm->EmitAlignment(2);
/// 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);
- EmitCommonEHFrame();
for (std::vector<FunctionEHFrameInfo>::iterator I = EHFrames.begin(),
E = EHFrames.end(); I != E; ++I)
EmitEHFrame(*I);
// Save EH frame information
EHFrames.push_back(FunctionEHFrameInfo(getAsm()->CurrentFnName,
SubprogramCount,
+ MMI->getPersonalityIndex(),
MF->getFrameInfo()->hasCalls(),
!MMI->getLandingPads().empty(),
MMI->getFrameMoves()));