#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCObjectWriter.h"
#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/Twine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
MCContext &context = streamer.getContext();
const TargetAsmInfo &asmInfo = context.getTargetAsmInfo();
int size = asmInfo.getPointerSize();
- if (asmInfo.getStackGrowthDirection() == TargetFrameInfo::StackGrowsUp)
+ if (asmInfo.getStackGrowthDirection() == TargetFrameLowering::StackGrowsUp)
return size;
else
return -size;
}
-static void EmitCFIInstruction(MCStreamer &Streamer,
- const MCCFIInstruction &Instr) {
+static unsigned getSizeForEncoding(MCStreamer &streamer,
+ unsigned symbolEncoding) {
+ MCContext &context = streamer.getContext();
+ const TargetAsmInfo &asmInfo = context.getTargetAsmInfo();
+ unsigned format = symbolEncoding & 0x0f;
+ switch (format) {
+ default:
+ assert(0 && "Unknown Encoding");
+ case dwarf::DW_EH_PE_absptr:
+ case dwarf::DW_EH_PE_signed:
+ return asmInfo.getPointerSize();
+ case dwarf::DW_EH_PE_udata2:
+ case dwarf::DW_EH_PE_sdata2:
+ return 2;
+ case dwarf::DW_EH_PE_udata4:
+ case dwarf::DW_EH_PE_sdata4:
+ return 4;
+ case dwarf::DW_EH_PE_udata8:
+ case dwarf::DW_EH_PE_sdata8:
+ return 8;
+ }
+}
+
+static void EmitSymbol(MCStreamer &streamer, const MCSymbol &symbol,
+ unsigned symbolEncoding) {
+ MCContext &context = streamer.getContext();
+ const MCAsmInfo &asmInfo = context.getAsmInfo();
+ const MCExpr *v = asmInfo.getExprForFDESymbol(&symbol,
+ symbolEncoding,
+ streamer);
+ unsigned size = getSizeForEncoding(streamer, symbolEncoding);
+ streamer.EmitAbsValue(v, size);
+}
+
+static void EmitPersonality(MCStreamer &streamer, const MCSymbol &symbol,
+ unsigned symbolEncoding) {
+ MCContext &context = streamer.getContext();
+ const MCAsmInfo &asmInfo = context.getAsmInfo();
+ const MCExpr *v = asmInfo.getExprForPersonalitySymbol(&symbol,
+ symbolEncoding,
+ streamer);
+ unsigned size = getSizeForEncoding(streamer, symbolEncoding);
+ streamer.EmitValue(v, size);
+}
+
+static const MachineLocation TranslateMachineLocation(
+ const TargetAsmInfo &AsmInfo,
+ const MachineLocation &Loc) {
+ unsigned Reg = Loc.getReg() == MachineLocation::VirtualFP ?
+ MachineLocation::VirtualFP :
+ unsigned(AsmInfo.getDwarfRegNum(Loc.getReg(), true));
+ const MachineLocation &NewLoc = Loc.isReg() ?
+ MachineLocation(Reg) : MachineLocation(Reg, Loc.getOffset());
+ return NewLoc;
+}
+
+namespace {
+ class FrameEmitterImpl {
+ int CFAOffset;
+ int CIENum;
+ bool UsingCFI;
+ bool IsEH;
+ const MCSymbol *SectionStart;
+
+ public:
+ FrameEmitterImpl(bool usingCFI, bool isEH, const MCSymbol *sectionStart) :
+ CFAOffset(0), CIENum(0), UsingCFI(usingCFI), IsEH(isEH),
+ SectionStart(sectionStart) {
+ }
+
+ const MCSymbol &EmitCIE(MCStreamer &streamer,
+ const MCSymbol *personality,
+ unsigned personalityEncoding,
+ const MCSymbol *lsda,
+ unsigned lsdaEncoding);
+ MCSymbol *EmitFDE(MCStreamer &streamer,
+ const MCSymbol &cieStart,
+ const MCDwarfFrameInfo &frame);
+ void EmitCFIInstructions(MCStreamer &streamer,
+ const std::vector<MCCFIInstruction> &Instrs,
+ MCSymbol *BaseLabel);
+ void EmitCFIInstruction(MCStreamer &Streamer,
+ const MCCFIInstruction &Instr);
+ };
+}
+
+void FrameEmitterImpl::EmitCFIInstruction(MCStreamer &Streamer,
+ const MCCFIInstruction &Instr) {
int dataAlignmentFactor = getDataAlignmentFactor(Streamer);
switch (Instr.getOperation()) {
- case MCCFIInstruction::Move: {
+ case MCCFIInstruction::Move:
+ case MCCFIInstruction::RelMove: {
const MachineLocation &Dst = Instr.getDestination();
const MachineLocation &Src = Instr.getSource();
+ const bool IsRelative = Instr.getOperation() == MCCFIInstruction::RelMove;
// If advancing cfa.
if (Dst.isReg() && Dst.getReg() == MachineLocation::VirtualFP) {
- assert(!Src.isReg() && "Machine move not supported yet.");
-
if (Src.getReg() == MachineLocation::VirtualFP) {
Streamer.EmitIntValue(dwarf::DW_CFA_def_cfa_offset, 1);
} else {
Streamer.EmitULEB128IntValue(Src.getReg());
}
- Streamer.EmitULEB128IntValue(-Src.getOffset(), 1);
+ if (IsRelative)
+ CFAOffset += Src.getOffset();
+ else
+ CFAOffset = -Src.getOffset();
+
+ Streamer.EmitULEB128IntValue(CFAOffset);
return;
}
}
unsigned Reg = Src.getReg();
- int Offset = Dst.getOffset() / dataAlignmentFactor;
+
+ int Offset = Dst.getOffset();
+ if (IsRelative)
+ Offset -= CFAOffset;
+ Offset = Offset / dataAlignmentFactor;
if (Offset < 0) {
Streamer.EmitIntValue(dwarf::DW_CFA_offset_extended_sf, 1);
Streamer.EmitSLEB128IntValue(Offset);
} else if (Reg < 64) {
Streamer.EmitIntValue(dwarf::DW_CFA_offset + Reg, 1);
- Streamer.EmitULEB128IntValue(Offset, 1);
+ Streamer.EmitULEB128IntValue(Offset);
} else {
Streamer.EmitIntValue(dwarf::DW_CFA_offset_extended, 1);
- Streamer.EmitULEB128IntValue(Reg, 1);
- Streamer.EmitULEB128IntValue(Offset, 1);
+ Streamer.EmitULEB128IntValue(Reg);
+ Streamer.EmitULEB128IntValue(Offset);
}
return;
}
case MCCFIInstruction::Restore:
Streamer.EmitIntValue(dwarf::DW_CFA_restore_state, 1);
return;
+ case MCCFIInstruction::SameValue: {
+ unsigned Reg = Instr.getDestination().getReg();
+ Streamer.EmitIntValue(dwarf::DW_CFA_same_value, 1);
+ Streamer.EmitULEB128IntValue(Reg);
+ return;
+ }
}
llvm_unreachable("Unhandled case in switch");
}
/// EmitFrameMoves - Emit frame instructions to describe the layout of the
/// frame.
-static void EmitCFIInstructions(MCStreamer &streamer,
- const std::vector<MCCFIInstruction> &Instrs,
- MCSymbol *BaseLabel) {
+void FrameEmitterImpl::EmitCFIInstructions(MCStreamer &streamer,
+ const std::vector<MCCFIInstruction> &Instrs,
+ MCSymbol *BaseLabel) {
for (unsigned i = 0, N = Instrs.size(); i < N; ++i) {
const MCCFIInstruction &Instr = Instrs[i];
MCSymbol *Label = Instr.getLabel();
}
}
-static void EmitSymbol(MCStreamer &streamer, const MCSymbol &symbol,
- unsigned symbolEncoding) {
+const MCSymbol &FrameEmitterImpl::EmitCIE(MCStreamer &streamer,
+ const MCSymbol *personality,
+ unsigned personalityEncoding,
+ const MCSymbol *lsda,
+ unsigned lsdaEncoding) {
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");
- 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 MachineLocation TranslateMachineLocation(
- const TargetAsmInfo &AsmInfo,
- const MachineLocation &Loc) {
- unsigned Reg = Loc.getReg() == MachineLocation::VirtualFP ?
- MachineLocation::VirtualFP :
- unsigned(AsmInfo.getDwarfRegNum(Loc.getReg(), true));
- const MachineLocation &NewLoc = Loc.isReg() ?
- MachineLocation(Reg) : MachineLocation(Reg, Loc.getOffset());
- return NewLoc;
-}
+ MCSymbol *sectionStart;
+ if (asmInfo.isFunctionEHFrameSymbolPrivate() || !IsEH)
+ sectionStart = context.CreateTempSymbol();
+ else
+ sectionStart = context.GetOrCreateSymbol(Twine("EH_frame") + Twine(CIENum));
+
+ CIENum++;
-static const MCSymbol &EmitCIE(MCStreamer &streamer,
- const MCSymbol *personality,
- unsigned personalityEncoding,
- const MCSymbol *lsda,
- unsigned lsdaEncoding) {
- MCContext &context = streamer.getContext();
- const TargetAsmInfo &asmInfo = context.getTargetAsmInfo();
- const MCSection §ion = *asmInfo.getEHFrameSection();
- streamer.SwitchSection(§ion);
- MCSymbol *sectionStart = streamer.getContext().CreateTempSymbol();
MCSymbol *sectionEnd = streamer.getContext().CreateTempSymbol();
// Length
const MCExpr *Length = MakeStartMinusEndExpr(streamer, *sectionStart,
*sectionEnd, 4);
streamer.EmitLabel(sectionStart);
- streamer.EmitValue(Length, 4);
+ streamer.EmitAbsValue(Length, 4);
// CIE ID
- streamer.EmitIntValue(0, 4);
+ unsigned CIE_ID = IsEH ? 0 : -1;
+ streamer.EmitIntValue(CIE_ID, 4);
// Version
streamer.EmitIntValue(dwarf::DW_CIE_VERSION, 1);
// Augmentation String
SmallString<8> Augmentation;
- Augmentation += "z";
- if (personality)
- Augmentation += "P";
- if (lsda)
- Augmentation += "L";
- Augmentation += "R";
- streamer.EmitBytes(Augmentation.str(), 0);
+ if (IsEH) {
+ Augmentation += "z";
+ if (personality)
+ Augmentation += "P";
+ if (lsda)
+ Augmentation += "L";
+ Augmentation += "R";
+ streamer.EmitBytes(Augmentation.str(), 0);
+ }
streamer.EmitIntValue(0, 1);
// Code Alignment Factor
streamer.EmitULEB128IntValue(asmInfo.getDwarfRARegNum(true));
// Augmentation Data Length (optional)
- MCSymbol *augmentationStart = streamer.getContext().CreateTempSymbol();
- MCSymbol *augmentationEnd = streamer.getContext().CreateTempSymbol();
- const MCExpr *augmentationLength = MakeStartMinusEndExpr(streamer,
- *augmentationStart,
- *augmentationEnd, 0);
- streamer.EmitULEB128Value(augmentationLength);
-
- // Augmentation Data (optional)
- streamer.EmitLabel(augmentationStart);
- if (personality) {
- // Personality Encoding
- streamer.EmitIntValue(personalityEncoding, 1);
- // Personality
- EmitSymbol(streamer, *personality, personalityEncoding);
- }
- if (lsda) {
- // LSDA Encoding
- streamer.EmitIntValue(lsdaEncoding, 1);
+
+ unsigned augmentationLength = 0;
+ if (IsEH) {
+ if (personality) {
+ // Personality Encoding
+ augmentationLength += 1;
+ // Personality
+ augmentationLength += getSizeForEncoding(streamer, personalityEncoding);
+ }
+ if (lsda)
+ augmentationLength += 1;
+ // Encoding of the FDE pointers
+ augmentationLength += 1;
+
+ streamer.EmitULEB128IntValue(augmentationLength);
+
+ // Augmentation Data (optional)
+ if (personality) {
+ // Personality Encoding
+ streamer.EmitIntValue(personalityEncoding, 1);
+ // Personality
+ EmitPersonality(streamer, *personality, personalityEncoding);
+ }
+ if (lsda)
+ streamer.EmitIntValue(lsdaEncoding, 1); // LSDA Encoding
+ // Encoding of the FDE pointers
+ streamer.EmitIntValue(asmInfo.getFDEEncoding(UsingCFI), 1);
}
- // Encoding of the FDE pointers
- streamer.EmitIntValue(dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4, 1);
- streamer.EmitLabel(augmentationEnd);
// Initial Instructions
EmitCFIInstructions(streamer, Instructions, NULL);
// Padding
- streamer.EmitValueToAlignment(4);
+ streamer.EmitValueToAlignment(IsEH ? 4 : asmInfo.getPointerSize());
streamer.EmitLabel(sectionEnd);
return *sectionStart;
}
-static MCSymbol *EmitFDE(MCStreamer &streamer,
- const MCSymbol &cieStart,
- const MCDwarfFrameInfo &frame) {
+MCSymbol *FrameEmitterImpl::EmitFDE(MCStreamer &streamer,
+ const MCSymbol &cieStart,
+ const MCDwarfFrameInfo &frame) {
MCContext &context = streamer.getContext();
MCSymbol *fdeStart = context.CreateTempSymbol();
MCSymbol *fdeEnd = context.CreateTempSymbol();
+ const TargetAsmInfo &TAsmInfo = context.getTargetAsmInfo();
+
+ if (!TAsmInfo.isFunctionEHFrameSymbolPrivate() && IsEH) {
+ MCSymbol *EHSym = context.GetOrCreateSymbol(
+ frame.Function->getName() + Twine(".eh"));
+ streamer.EmitEHSymAttributes(frame.Function, EHSym);
+ streamer.EmitLabel(EHSym);
+ }
// Length
const MCExpr *Length = MakeStartMinusEndExpr(streamer, *fdeStart, *fdeEnd, 0);
- streamer.EmitValue(Length, 4);
+ streamer.EmitAbsValue(Length, 4);
streamer.EmitLabel(fdeStart);
+
// CIE Pointer
- const MCExpr *offset = MakeStartMinusEndExpr(streamer, cieStart, *fdeStart,
- 0);
- streamer.EmitValue(offset, 4);
+ const MCAsmInfo &asmInfo = context.getAsmInfo();
+ if (IsEH) {
+ const MCExpr *offset = MakeStartMinusEndExpr(streamer, cieStart, *fdeStart,
+ 0);
+ streamer.EmitAbsValue(offset, 4);
+ } else if (!asmInfo.doesDwarfRequireRelocationForSectionOffset()) {
+ const MCExpr *offset = MakeStartMinusEndExpr(streamer, *SectionStart,
+ cieStart, 0);
+ streamer.EmitAbsValue(offset, 4);
+ } else {
+ streamer.EmitSymbolValue(&cieStart, 4);
+ }
+ unsigned fdeEncoding = TAsmInfo.getFDEEncoding(UsingCFI);
+ unsigned size = getSizeForEncoding(streamer, fdeEncoding);
// PC Begin
- streamer.EmitPCRelSymbolValue(frame.Begin, 4);
+ unsigned PCBeginEncoding = IsEH ? fdeEncoding :
+ (unsigned)dwarf::DW_EH_PE_absptr;
+ unsigned PCBeginSize = getSizeForEncoding(streamer, PCBeginEncoding);
+ EmitSymbol(streamer, *frame.Begin, PCBeginEncoding);
// PC Range
const MCExpr *Range = MakeStartMinusEndExpr(streamer, *frame.Begin,
*frame.End, 0);
- streamer.EmitValue(Range, 4);
-
- // Augmentation Data Length
- 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);
+ streamer.EmitAbsValue(Range, size);
+
+ if (IsEH) {
+ // Augmentation Data Length
+ unsigned augmentationLength = 0;
+
+ if (frame.Lsda)
+ augmentationLength += getSizeForEncoding(streamer, frame.LsdaEncoding);
+
+ streamer.EmitULEB128IntValue(augmentationLength);
+
+ // Augmentation Data
+ if (frame.Lsda)
+ EmitSymbol(streamer, *frame.Lsda, frame.LsdaEncoding);
+ }
+
// Call Frame Instructions
EmitCFIInstructions(streamer, frame.Instructions, frame.Begin);
// Padding
- streamer.EmitValueToAlignment(4);
+ streamer.EmitValueToAlignment(PCBeginSize);
return fdeEnd;
}
-struct CIEKey {
- static const CIEKey EmptyKey;
- static const CIEKey TombstoneKey;
+namespace {
+ struct CIEKey {
+ static const CIEKey getEmptyKey() { return CIEKey(0, 0, -1); }
+ static const CIEKey getTombstoneKey() { return CIEKey(0, -1, 0); }
- 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);
+ CIEKey(const MCSymbol* Personality_, unsigned PersonalityEncoding_,
+ unsigned LsdaEncoding_) : Personality(Personality_),
+ PersonalityEncoding(PersonalityEncoding_),
+ LsdaEncoding(LsdaEncoding_) {
+ }
+ const MCSymbol* Personality;
+ unsigned PersonalityEncoding;
+ unsigned LsdaEncoding;
+ };
+}
namespace llvm {
template <>
struct DenseMapInfo<CIEKey> {
static CIEKey getEmptyKey() {
- return CIEKey::EmptyKey;
+ return CIEKey::getEmptyKey();
}
static CIEKey getTombstoneKey() {
- return CIEKey::TombstoneKey;
+ return CIEKey::getTombstoneKey();
}
static unsigned getHashValue(const CIEKey &Key) {
FoldingSetNodeID ID;
};
}
-void MCDwarfFrameEmitter::Emit(MCStreamer &streamer) {
- const MCContext &context = streamer.getContext();
+void MCDwarfFrameEmitter::Emit(MCStreamer &streamer,
+ bool usingCFI,
+ bool isEH) {
+ MCContext &context = streamer.getContext();
const TargetAsmInfo &asmInfo = context.getTargetAsmInfo();
+ const MCSection §ion = isEH ?
+ *asmInfo.getEHFrameSection() : *asmInfo.getDwarfFrameSection();
+ streamer.SwitchSection(§ion);
+ MCSymbol *SectionStart = context.CreateTempSymbol();
+ streamer.EmitLabel(SectionStart);
+
MCSymbol *fdeEnd = NULL;
DenseMap<CIEKey, const MCSymbol*> CIEStarts;
+ FrameEmitterImpl Emitter(usingCFI, isEH, SectionStart);
+ const MCSymbol *DummyDebugKey = NULL;
for (unsigned i = 0, n = streamer.getNumFrameInfos(); i < n; ++i) {
const MCDwarfFrameInfo &frame = streamer.getFrameInfo(i);
CIEKey key(frame.Personality, frame.PersonalityEncoding,
frame.LsdaEncoding);
- const MCSymbol *&cieStart = CIEStarts[key];
+ const MCSymbol *&cieStart = isEH ? CIEStarts[key] : DummyDebugKey;
if (!cieStart)
- cieStart = &EmitCIE(streamer, frame.Personality,
- frame.PersonalityEncoding, frame.Lsda,
- frame.LsdaEncoding);
- fdeEnd = EmitFDE(streamer, *cieStart, frame);
+ cieStart = &Emitter.EmitCIE(streamer, frame.Personality,
+ frame.PersonalityEncoding, frame.Lsda,
+ frame.LsdaEncoding);
+ fdeEnd = Emitter.EmitFDE(streamer, *cieStart, frame);
if (i != n - 1)
streamer.EmitLabel(fdeEnd);
}
OS << uint8_t(dwarf::DW_CFA_advance_loc1);
OS << uint8_t(AddrDelta);
} else if (isUInt<16>(AddrDelta)) {
+ // FIXME: check what is the correct behavior on a big endian machine.
OS << uint8_t(dwarf::DW_CFA_advance_loc2);
- OS << uint16_t(AddrDelta);
+ OS << uint8_t( AddrDelta & 0xff);
+ OS << uint8_t((AddrDelta >> 8) & 0xff);
} else {
+ // FIXME: check what is the correct behavior on a big endian machine.
assert(isUInt<32>(AddrDelta));
OS << uint8_t(dwarf::DW_CFA_advance_loc4);
- OS << uint32_t(AddrDelta);
+ OS << uint8_t( AddrDelta & 0xff);
+ OS << uint8_t((AddrDelta >> 8) & 0xff);
+ OS << uint8_t((AddrDelta >> 16) & 0xff);
+ OS << uint8_t((AddrDelta >> 24) & 0xff);
+
}
}