Add support for .cfi_lsda.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@122584 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/MC/MCAsmStreamer.cpp b/lib/MC/MCAsmStreamer.cpp
index ee13429..f8c3a8a 100644
--- a/lib/MC/MCAsmStreamer.cpp
+++ b/lib/MC/MCAsmStreamer.cpp
@@ -190,7 +190,7 @@
virtual bool EmitCFIDefCfaRegister(int64_t Register);
virtual bool EmitCFIOffset(int64_t Register, int64_t Offset);
virtual bool EmitCFIPersonality(const MCSymbol *Sym, unsigned Encoding);
- virtual bool EmitCFILsda(const MCSymbol *Sym);
+ virtual bool EmitCFILsda(const MCSymbol *Sym, unsigned Encoding);
virtual void EmitInstruction(const MCInst &Inst);
@@ -769,11 +769,11 @@
return false;
}
-bool MCAsmStreamer::EmitCFILsda(const MCSymbol *Sym) {
- if (this->MCStreamer::EmitCFILsda(Sym))
+bool MCAsmStreamer::EmitCFILsda(const MCSymbol *Sym, unsigned Encoding) {
+ if (this->MCStreamer::EmitCFILsda(Sym, Encoding))
return true;
- OS << ".cfi_lsda 0, " << *Sym;
+ OS << ".cfi_lsda " << Encoding << ", " << *Sym;
EmitEOL();
return false;
diff --git a/lib/MC/MCDwarf.cpp b/lib/MC/MCDwarf.cpp
index 9d26bec..cd51410 100644
--- a/lib/MC/MCDwarf.cpp
+++ b/lib/MC/MCDwarf.cpp
@@ -7,6 +7,7 @@
//
//===----------------------------------------------------------------------===//
+#include "llvm/ADT/FoldingSet.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCDwarf.h"
#include "llvm/MC/MCAssembler.h"
@@ -508,9 +509,53 @@
}
}
+static void EmitSymbol(MCStreamer &streamer, const MCSymbol &symbol,
+ unsigned symbolEncoding) {
+ MCContext &context = streamer.getContext();
+ const TargetAsmInfo &asmInfo = context.getTargetAsmInfo();
+ unsigned format = symbolEncoding & 0x0f;
+ unsigned application = symbolEncoding & 0xf0;
+ unsigned size;
+ switch (format) {
+ default:
+ assert(0 && "Unknown Encoding");
+ break;
+ case dwarf::DW_EH_PE_absptr:
+ case dwarf::DW_EH_PE_signed:
+ size = asmInfo.getPointerSize();
+ break;
+ case dwarf::DW_EH_PE_udata2:
+ case dwarf::DW_EH_PE_sdata2:
+ size = 2;
+ break;
+ case dwarf::DW_EH_PE_udata4:
+ case dwarf::DW_EH_PE_sdata4:
+ size = 4;
+ break;
+ case dwarf::DW_EH_PE_udata8:
+ case dwarf::DW_EH_PE_sdata8:
+ size = 8;
+ break;
+ }
+ switch (application) {
+ default:
+ assert(0 && "Unknown Encoding");
+ break;
+ case 0:
+ case dwarf::DW_EH_PE_indirect:
+ streamer.EmitSymbolValue(&symbol, size);
+ break;
+ case dwarf::DW_EH_PE_pcrel:
+ streamer.EmitPCRelSymbolValue(&symbol, size);
+ break;
+ }
+}
+
static const MCSymbol &EmitCIE(MCStreamer &streamer,
const MCSymbol *personality,
- unsigned personalityEncoding) {
+ unsigned personalityEncoding,
+ const MCSymbol *lsda,
+ unsigned lsdaEncoding) {
MCContext &context = streamer.getContext();
const TargetAsmInfo &asmInfo = context.getTargetAsmInfo();
const MCSection §ion = *asmInfo.getEHFrameSection();
@@ -535,6 +580,8 @@
Augmentation += "z";
if (personality)
Augmentation += "P";
+ if (lsda)
+ Augmentation += "L";
Augmentation += "R";
streamer.EmitBytes(Augmentation.str(), 0);
streamer.EmitIntValue(0, 1);
@@ -562,42 +609,11 @@
// Personality Encoding
streamer.EmitIntValue(personalityEncoding, 1);
// Personality
- unsigned format = personalityEncoding & 0x0f;
- unsigned application = personalityEncoding & 0xf0;
- unsigned size;
- switch (format) {
- default:
- assert(0 && "Unknown Encoding");
- break;
- case dwarf::DW_EH_PE_absptr:
- case dwarf::DW_EH_PE_signed:
- size = asmInfo.getPointerSize();
- break;
- case dwarf::DW_EH_PE_udata2:
- case dwarf::DW_EH_PE_sdata2:
- size = 2;
- break;
- case dwarf::DW_EH_PE_udata4:
- case dwarf::DW_EH_PE_sdata4:
- size = 4;
- break;
- case dwarf::DW_EH_PE_udata8:
- case dwarf::DW_EH_PE_sdata8:
- size = 8;
- break;
- }
- switch (application) {
- default:
- assert(0 && "Unknown Encoding");
- break;
- case 0:
- case dwarf::DW_EH_PE_indirect:
- streamer.EmitSymbolValue(personality, size);
- break;
- case dwarf::DW_EH_PE_pcrel:
- streamer.EmitPCRelSymbolValue(personality, size);
- break;
- }
+ EmitSymbol(streamer, *personality, personalityEncoding);
+ }
+ if (lsda) {
+ // LSDA Encoding
+ streamer.EmitIntValue(lsdaEncoding, 1);
}
// Encoding of the FDE pointers
streamer.EmitIntValue(dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4, 1);
@@ -619,8 +635,9 @@
static MCSymbol *EmitFDE(MCStreamer &streamer,
const MCSymbol &cieStart,
const MCDwarfFrameInfo &frame) {
- MCSymbol *fdeStart = streamer.getContext().CreateTempSymbol();
- MCSymbol *fdeEnd = streamer.getContext().CreateTempSymbol();
+ MCContext &context = streamer.getContext();
+ MCSymbol *fdeStart = context.CreateTempSymbol();
+ MCSymbol *fdeEnd = context.CreateTempSymbol();
// Length
const MCExpr *Length = MakeStartMinusEndExpr(streamer, *fdeStart, *fdeEnd, 0);
@@ -641,9 +658,18 @@
streamer.EmitValue(Range, 4);
// Augmentation Data Length
- streamer.EmitULEB128IntValue(0);
+ MCSymbol *augmentationStart = streamer.getContext().CreateTempSymbol();
+ MCSymbol *augmentationEnd = streamer.getContext().CreateTempSymbol();
+ const MCExpr *augmentationLength = MakeStartMinusEndExpr(streamer,
+ *augmentationStart,
+ *augmentationEnd, 0);
+ streamer.EmitULEB128Value(augmentationLength);
// Augmentation Data
+ streamer.EmitLabel(augmentationStart);
+ if (frame.Lsda)
+ EmitSymbol(streamer, *frame.Lsda, frame.LsdaEncoding);
+ streamer.EmitLabel(augmentationEnd);
// Call Frame Instructions
// Padding
@@ -652,20 +678,63 @@
return fdeEnd;
}
+struct CIEKey {
+ static const CIEKey EmptyKey;
+ static const CIEKey TombstoneKey;
+
+ CIEKey(const MCSymbol* Personality_, unsigned PersonalityEncoding_,
+ unsigned LsdaEncoding_) : Personality(Personality_),
+ PersonalityEncoding(PersonalityEncoding_),
+ LsdaEncoding(LsdaEncoding_) {
+ }
+ const MCSymbol* Personality;
+ unsigned PersonalityEncoding;
+ unsigned LsdaEncoding;
+};
+
+const CIEKey CIEKey::EmptyKey(0, 0, -1);
+const CIEKey CIEKey::TombstoneKey(0, -1, 0);
+
+namespace llvm {
+ template <>
+ struct DenseMapInfo<CIEKey> {
+ static CIEKey getEmptyKey() {
+ return CIEKey::EmptyKey;
+ }
+ static CIEKey getTombstoneKey() {
+ return CIEKey::TombstoneKey;
+ }
+ static unsigned getHashValue(const CIEKey &Key) {
+ FoldingSetNodeID ID;
+ ID.AddPointer(Key.Personality);
+ ID.AddInteger(Key.PersonalityEncoding);
+ ID.AddInteger(Key.LsdaEncoding);
+ return ID.ComputeHash();
+ }
+ static bool isEqual(const CIEKey &LHS,
+ const CIEKey &RHS) {
+ return LHS.Personality == RHS.Personality &&
+ LHS.PersonalityEncoding == RHS.PersonalityEncoding &&
+ LHS.LsdaEncoding == RHS.LsdaEncoding;
+ }
+ };
+}
+
void MCDwarfFrameEmitter::Emit(MCStreamer &streamer) {
const MCContext &context = streamer.getContext();
const TargetAsmInfo &asmInfo = context.getTargetAsmInfo();
MCSymbol *fdeEnd = NULL;
- typedef std::pair<const MCSymbol*, unsigned> personalityKey;
- DenseMap<personalityKey, const MCSymbol*> personalities;
+ DenseMap<CIEKey, const MCSymbol*> CIEStarts;
for (unsigned i = 0, n = streamer.getNumFrameInfos(); i < n; ++i) {
const MCDwarfFrameInfo &frame = streamer.getFrameInfo(i);
- personalityKey key(frame.Personality, frame.PersonalityEncoding);
- const MCSymbol *&cieStart = personalities[key];
+ CIEKey key(frame.Personality, frame.PersonalityEncoding,
+ frame.LsdaEncoding);
+ const MCSymbol *&cieStart = CIEStarts[key];
if (!cieStart)
cieStart = &EmitCIE(streamer, frame.Personality,
- frame.PersonalityEncoding);
+ frame.PersonalityEncoding, frame.Lsda,
+ frame.LsdaEncoding);
fdeEnd = EmitFDE(streamer, *cieStart, frame);
if (i != n - 1)
streamer.EmitLabel(fdeEnd);
diff --git a/lib/MC/MCParser/AsmParser.cpp b/lib/MC/MCParser/AsmParser.cpp
index 450a927..27b2dce 100644
--- a/lib/MC/MCParser/AsmParser.cpp
+++ b/lib/MC/MCParser/AsmParser.cpp
@@ -2257,7 +2257,7 @@
return getStreamer().EmitCFIPersonality(Sym, Encoding);
else {
assert(IDVal == ".cfi_lsda");
- return getStreamer().EmitCFILsda(Sym);
+ return getStreamer().EmitCFILsda(Sym, Encoding);
}
}
diff --git a/lib/MC/MCStreamer.cpp b/lib/MC/MCStreamer.cpp
index 399b4ba..922a40c 100644
--- a/lib/MC/MCStreamer.cpp
+++ b/lib/MC/MCStreamer.cpp
@@ -157,7 +157,7 @@
report_fatal_error("Starting a frame before finishing the previous one!");
return true;
}
- MCDwarfFrameInfo Frame = {0, 0, 0, 0};
+ MCDwarfFrameInfo Frame = {0, 0, 0, 0, 0, 0};
Frame.Begin = getContext().CreateTempSymbol();
EmitLabel(Frame.Begin);
FrameInfos.push_back(Frame);
@@ -196,10 +196,11 @@
return false;
}
-bool MCStreamer::EmitCFILsda(const MCSymbol *Sym) {
+bool MCStreamer::EmitCFILsda(const MCSymbol *Sym, unsigned Encoding) {
EnsureValidFrame();
MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo();
CurFrame->Lsda = Sym;
+ CurFrame->LsdaEncoding = Encoding;
return false;
}