Add support for the same encodings of the personality function that gnu as
supports.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@122577 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/MC/ELFObjectWriter.cpp b/lib/MC/ELFObjectWriter.cpp
index 5ff12bc..88c7200 100644
--- a/lib/MC/ELFObjectWriter.cpp
+++ b/lib/MC/ELFObjectWriter.cpp
@@ -1604,26 +1604,41 @@
unsigned Type;
if (is64Bit()) {
if (IsPCRel) {
- switch (Modifier) {
- default:
- llvm_unreachable("Unimplemented");
- case MCSymbolRefExpr::VK_None:
- Type = ELF::R_X86_64_PC32;
+ switch ((unsigned)Fixup.getKind()) {
+ default: llvm_unreachable("invalid fixup kind!");
+ case FK_PCRel_8:
+ assert(Modifier == MCSymbolRefExpr::VK_None);
+ Type = ELF::R_X86_64_PC64;
break;
- case MCSymbolRefExpr::VK_PLT:
- Type = ELF::R_X86_64_PLT32;
+ case FK_Data_4: // FIXME?
+ case X86::reloc_riprel_4byte:
+ case FK_PCRel_4:
+ switch (Modifier) {
+ default:
+ llvm_unreachable("Unimplemented");
+ case MCSymbolRefExpr::VK_None:
+ Type = ELF::R_X86_64_PC32;
+ break;
+ case MCSymbolRefExpr::VK_PLT:
+ Type = ELF::R_X86_64_PLT32;
+ break;
+ case MCSymbolRefExpr::VK_GOTPCREL:
+ Type = ELF::R_X86_64_GOTPCREL;
+ break;
+ case MCSymbolRefExpr::VK_GOTTPOFF:
+ Type = ELF::R_X86_64_GOTTPOFF;
break;
- case MCSymbolRefExpr::VK_GOTPCREL:
- Type = ELF::R_X86_64_GOTPCREL;
+ case MCSymbolRefExpr::VK_TLSGD:
+ Type = ELF::R_X86_64_TLSGD;
+ break;
+ case MCSymbolRefExpr::VK_TLSLD:
+ Type = ELF::R_X86_64_TLSLD;
+ break;
+ }
break;
- case MCSymbolRefExpr::VK_GOTTPOFF:
- Type = ELF::R_X86_64_GOTTPOFF;
- break;
- case MCSymbolRefExpr::VK_TLSGD:
- Type = ELF::R_X86_64_TLSGD;
- break;
- case MCSymbolRefExpr::VK_TLSLD:
- Type = ELF::R_X86_64_TLSLD;
+ case FK_PCRel_2:
+ assert(Modifier == MCSymbolRefExpr::VK_None);
+ Type = ELF::R_X86_64_PC16;
break;
}
} else {
@@ -1631,7 +1646,6 @@
default: llvm_unreachable("invalid fixup kind!");
case FK_Data_8: Type = ELF::R_X86_64_64; break;
case X86::reloc_signed_4byte:
- case FK_PCRel_4:
assert(isInt<32>(Target.getConstant()));
switch (Modifier) {
default:
diff --git a/lib/MC/MCAsmStreamer.cpp b/lib/MC/MCAsmStreamer.cpp
index a171ba1..ee13429 100644
--- a/lib/MC/MCAsmStreamer.cpp
+++ b/lib/MC/MCAsmStreamer.cpp
@@ -189,7 +189,7 @@
virtual bool EmitCFIDefCfaOffset(int64_t Offset);
virtual bool EmitCFIDefCfaRegister(int64_t Register);
virtual bool EmitCFIOffset(int64_t Register, int64_t Offset);
- virtual bool EmitCFIPersonality(const MCSymbol *Sym);
+ virtual bool EmitCFIPersonality(const MCSymbol *Sym, unsigned Encoding);
virtual bool EmitCFILsda(const MCSymbol *Sym);
virtual void EmitInstruction(const MCInst &Inst);
@@ -758,11 +758,12 @@
return false;
}
-bool MCAsmStreamer::EmitCFIPersonality(const MCSymbol *Sym) {
- if (this->MCStreamer::EmitCFIPersonality(Sym))
+bool MCAsmStreamer::EmitCFIPersonality(const MCSymbol *Sym,
+ unsigned Encoding) {
+ if (this->MCStreamer::EmitCFIPersonality(Sym, Encoding))
return true;
- OS << ".cfi_personality 0, " << *Sym;
+ OS << ".cfi_personality " << Encoding << ", " << *Sym;
EmitEOL();
return false;
diff --git a/lib/MC/MCDwarf.cpp b/lib/MC/MCDwarf.cpp
index 75c844f..9d26bec 100644
--- a/lib/MC/MCDwarf.cpp
+++ b/lib/MC/MCDwarf.cpp
@@ -509,7 +509,8 @@
}
static const MCSymbol &EmitCIE(MCStreamer &streamer,
- const MCSymbol *personality) {
+ const MCSymbol *personality,
+ unsigned personalityEncoding) {
MCContext &context = streamer.getContext();
const TargetAsmInfo &asmInfo = context.getTargetAsmInfo();
const MCSection §ion = *asmInfo.getEHFrameSection();
@@ -559,9 +560,44 @@
streamer.EmitLabel(augmentationStart);
if (personality) {
// Personality Encoding
- streamer.EmitIntValue(dwarf::DW_EH_PE_absptr, 1);
+ streamer.EmitIntValue(personalityEncoding, 1);
// Personality
- streamer.EmitSymbolValue(personality, asmInfo.getPointerSize());
+ 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;
+ }
}
// Encoding of the FDE pointers
streamer.EmitIntValue(dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4, 1);
@@ -620,13 +656,16 @@
const MCContext &context = streamer.getContext();
const TargetAsmInfo &asmInfo = context.getTargetAsmInfo();
MCSymbol *fdeEnd = NULL;
- DenseMap<const MCSymbol*, const MCSymbol*> Personalities;
+ typedef std::pair<const MCSymbol*, unsigned> personalityKey;
+ DenseMap<personalityKey, const MCSymbol*> personalities;
for (unsigned i = 0, n = streamer.getNumFrameInfos(); i < n; ++i) {
const MCDwarfFrameInfo &frame = streamer.getFrameInfo(i);
- const MCSymbol *&cieStart = Personalities[frame.Personality];
+ personalityKey key(frame.Personality, frame.PersonalityEncoding);
+ const MCSymbol *&cieStart = personalities[key];
if (!cieStart)
- cieStart = &EmitCIE(streamer, frame.Personality);
+ cieStart = &EmitCIE(streamer, frame.Personality,
+ frame.PersonalityEncoding);
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 cf11ca9..450a927 100644
--- a/lib/MC/MCParser/AsmParser.cpp
+++ b/lib/MC/MCParser/AsmParser.cpp
@@ -2254,7 +2254,7 @@
MCSymbol *Sym = getContext().GetOrCreateSymbol(Name);
if (IDVal == ".cfi_personality")
- return getStreamer().EmitCFIPersonality(Sym);
+ return getStreamer().EmitCFIPersonality(Sym, Encoding);
else {
assert(IDVal == ".cfi_lsda");
return getStreamer().EmitCFILsda(Sym);
diff --git a/lib/MC/MCStreamer.cpp b/lib/MC/MCStreamer.cpp
index 68146de..399b4ba 100644
--- a/lib/MC/MCStreamer.cpp
+++ b/lib/MC/MCStreamer.cpp
@@ -187,10 +187,12 @@
return false;
}
-bool MCStreamer::EmitCFIPersonality(const MCSymbol *Sym) {
+bool MCStreamer::EmitCFIPersonality(const MCSymbol *Sym,
+ unsigned Encoding) {
EnsureValidFrame();
MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo();
CurFrame->Personality = Sym;
+ CurFrame->PersonalityEncoding = Encoding;
return false;
}
diff --git a/lib/MC/TargetAsmBackend.cpp b/lib/MC/TargetAsmBackend.cpp
index e0653d0..b13aa1d 100644
--- a/lib/MC/TargetAsmBackend.cpp
+++ b/lib/MC/TargetAsmBackend.cpp
@@ -27,7 +27,8 @@
{ "FK_Data_8", 0, 64, 0 },
{ "FK_PCRel_1", 0, 8, MCFixupKindInfo::FKF_IsPCRel },
{ "FK_PCRel_2", 0, 16, MCFixupKindInfo::FKF_IsPCRel },
- { "FK_PCRel_4", 0, 32, MCFixupKindInfo::FKF_IsPCRel }
+ { "FK_PCRel_4", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
+ { "FK_PCRel_8", 0, 64, MCFixupKindInfo::FKF_IsPCRel }
};
assert(Kind <= sizeof(Builtins) / sizeof(Builtins[0]) &&