diff options
Diffstat (limited to 'lib/MC/MCDwarf.cpp')
-rw-r--r-- | lib/MC/MCDwarf.cpp | 135 |
1 files changed, 47 insertions, 88 deletions
diff --git a/lib/MC/MCDwarf.cpp b/lib/MC/MCDwarf.cpp index 0f8f074..21ccc3e 100644 --- a/lib/MC/MCDwarf.cpp +++ b/lib/MC/MCDwarf.cpp @@ -16,7 +16,6 @@ #include "llvm/MC/MCContext.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCObjectFileInfo.h" -#include "llvm/MC/MCObjectWriter.h" #include "llvm/MC/MCRegisterInfo.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSymbol.h" @@ -47,20 +46,15 @@ using namespace llvm; // Range of line offsets in a special line info. opcode. #define DWARF2_LINE_RANGE 14 -// Define the architecture-dependent minimum instruction length (in bytes). -// This value should be rather too small than too big. -#define DWARF2_LINE_MIN_INSN_LENGTH 1 - -// Note: when DWARF2_LINE_MIN_INSN_LENGTH == 1 which is the current setting, -// this routine is a nop and will be optimized away. -static inline uint64_t ScaleAddrDelta(uint64_t AddrDelta) { - if (DWARF2_LINE_MIN_INSN_LENGTH == 1) +static inline uint64_t ScaleAddrDelta(MCContext &Context, uint64_t AddrDelta) { + unsigned MinInsnLength = Context.getAsmInfo().getMinInstAlignment(); + if (MinInsnLength == 1) return AddrDelta; - if (AddrDelta % DWARF2_LINE_MIN_INSN_LENGTH != 0) { + if (AddrDelta % MinInsnLength != 0) { // TODO: report this error, but really only once. ; } - return AddrDelta / DWARF2_LINE_MIN_INSN_LENGTH; + return AddrDelta / MinInsnLength; } // @@ -197,6 +191,8 @@ static inline void EmitDwarfLineTable(MCStreamer *MCOS, // actually a DW_LNE_end_sequence. // Switch to the section to be able to create a symbol at its end. + // TODO: keep track of the last subsection so that this symbol appears in the + // correct place. MCOS->SwitchSection(Section); MCContext &context = MCOS->getContext(); @@ -275,7 +271,7 @@ const MCSymbol *MCDwarfFileTable::EmitCU(MCStreamer *MCOS, unsigned CUID) { (4 + 2 + 4)), 4, 0); // Parameters of the state machine, are next. - MCOS->EmitIntValue(DWARF2_LINE_MIN_INSN_LENGTH, 1); + MCOS->EmitIntValue(context.getAsmInfo().getMinInstAlignment(), 1); MCOS->EmitIntValue(DWARF2_LINE_DEFAULT_IS_STMT, 1); MCOS->EmitIntValue(DWARF2_LINE_BASE, 1); MCOS->EmitIntValue(DWARF2_LINE_RANGE, 1); @@ -355,32 +351,24 @@ const MCSymbol *MCDwarfFileTable::EmitCU(MCStreamer *MCOS, unsigned CUID) { return LineStartSym; } -/// Utility function to write the encoding to an object writer. -void MCDwarfLineAddr::Write(MCObjectWriter *OW, int64_t LineDelta, - uint64_t AddrDelta) { - SmallString<256> Tmp; - raw_svector_ostream OS(Tmp); - MCDwarfLineAddr::Encode(LineDelta, AddrDelta, OS); - OW->WriteBytes(OS.str()); -} - /// Utility function to emit the encoding to a streamer. void MCDwarfLineAddr::Emit(MCStreamer *MCOS, int64_t LineDelta, uint64_t AddrDelta) { + MCContext &Context = MCOS->getContext(); SmallString<256> Tmp; raw_svector_ostream OS(Tmp); - MCDwarfLineAddr::Encode(LineDelta, AddrDelta, OS); + MCDwarfLineAddr::Encode(Context, LineDelta, AddrDelta, OS); MCOS->EmitBytes(OS.str()); } /// Utility function to encode a Dwarf pair of LineDelta and AddrDeltas. -void MCDwarfLineAddr::Encode(int64_t LineDelta, uint64_t AddrDelta, - raw_ostream &OS) { +void MCDwarfLineAddr::Encode(MCContext &Context, int64_t LineDelta, + uint64_t AddrDelta, raw_ostream &OS) { uint64_t Temp, Opcode; bool NeedCopy = false; // Scale the address delta by the minimum instruction length. - AddrDelta = ScaleAddrDelta(AddrDelta); + AddrDelta = ScaleAddrDelta(Context, AddrDelta); // A LineDelta of INT64_MAX is a signal that this is actually a // DW_LNE_end_sequence. We cannot use special opcodes here, since we want the @@ -787,7 +775,7 @@ void MCGenDwarfLabelEntry::Make(MCSymbol *Symbol, MCStreamer *MCOS, if (Symbol->isTemporary()) return; MCContext &context = MCOS->getContext(); - if (context.getGenDwarfSection() != MCOS->getCurrentSection()) + if (context.getGenDwarfSection() != MCOS->getCurrentSection().first) return; // The dwarf label's name does not have the symbol name's leading @@ -871,17 +859,6 @@ static void EmitPersonality(MCStreamer &streamer, const MCSymbol &symbol, streamer.EmitValue(v, size); } -static const MachineLocation TranslateMachineLocation( - const MCRegisterInfo &MRI, - const MachineLocation &Loc) { - unsigned Reg = Loc.getReg() == MachineLocation::VirtualFP ? - MachineLocation::VirtualFP : - unsigned(MRI.getDwarfRegNum(Loc.getReg(), true)); - const MachineLocation &NewLoc = Loc.isReg() ? - MachineLocation(Reg) : MachineLocation(Reg, Loc.getOffset()); - return NewLoc; -} - namespace { class FrameEmitterImpl { int CFAOffset; @@ -899,7 +876,7 @@ namespace { /// EmitCompactUnwind - Emit the unwind information in a compact way. If /// we're successful, return 'true'. Otherwise, return 'false' and it will /// emit the normal CIE and FDE. - bool EmitCompactUnwind(MCStreamer &streamer, + void EmitCompactUnwind(MCStreamer &streamer, const MCDwarfFrameInfo &frame); const MCSymbol &EmitCIE(MCStreamer &streamer, @@ -1139,7 +1116,7 @@ void FrameEmitterImpl::EmitCFIInstructions(MCStreamer &streamer, /// EmitCompactUnwind - Emit the unwind information in a compact way. If we're /// successful, return 'true'. Otherwise, return 'false' and it will emit the /// normal CIE and FDE. -bool FrameEmitterImpl::EmitCompactUnwind(MCStreamer &Streamer, +void FrameEmitterImpl::EmitCompactUnwind(MCStreamer &Streamer, const MCDwarfFrameInfo &Frame) { MCContext &Context = Streamer.getContext(); const MCObjectFileInfo *MOFI = Context.getObjectFileInfo(); @@ -1168,14 +1145,13 @@ bool FrameEmitterImpl::EmitCompactUnwind(MCStreamer &Streamer, // .quad except_tab1 uint32_t Encoding = Frame.CompactUnwindEncoding; - if (!Encoding) return false; + if (!Encoding) return; + bool DwarfEHFrameOnly = (Encoding == MOFI->getCompactUnwindDwarfEHFrameOnly()); // The encoding needs to know we have an LSDA. - if (Frame.Lsda) + if (!DwarfEHFrameOnly && Frame.Lsda) Encoding |= 0x40000000; - Streamer.SwitchSection(MOFI->getCompactUnwindSection()); - // Range Start unsigned FDEEncoding = MOFI->getFDEEncoding(UsingCFI); unsigned Size = getSizeForEncoding(Streamer, FDEEncoding); @@ -1194,11 +1170,10 @@ bool FrameEmitterImpl::EmitCompactUnwind(MCStreamer &Streamer, Twine::utohexstr(Encoding)); Streamer.EmitIntValue(Encoding, Size); - // Personality Function Size = getSizeForEncoding(Streamer, dwarf::DW_EH_PE_absptr); if (VerboseAsm) Streamer.AddComment("Personality Function"); - if (Frame.Personality) + if (!DwarfEHFrameOnly && Frame.Personality) Streamer.EmitSymbolValue(Frame.Personality, Size); else Streamer.EmitIntValue(0, Size); // No personality fn @@ -1206,12 +1181,10 @@ bool FrameEmitterImpl::EmitCompactUnwind(MCStreamer &Streamer, // LSDA Size = getSizeForEncoding(Streamer, Frame.LsdaEncoding); if (VerboseAsm) Streamer.AddComment("LSDA"); - if (Frame.Lsda) + if (!DwarfEHFrameOnly && Frame.Lsda) Streamer.EmitSymbolValue(Frame.Lsda, Size); else Streamer.EmitIntValue(0, Size); // No LSDA - - return true; } const MCSymbol &FrameEmitterImpl::EmitCIE(MCStreamer &streamer, @@ -1269,7 +1242,7 @@ const MCSymbol &FrameEmitterImpl::EmitCIE(MCStreamer &streamer, // Code Alignment Factor if (verboseAsm) streamer.AddComment("CIE Code Alignment Factor"); - streamer.EmitULEB128IntValue(1); + streamer.EmitULEB128IntValue(context.getAsmInfo().getMinInstAlignment()); // Data Alignment Factor if (verboseAsm) streamer.AddComment("CIE Data Alignment Factor"); @@ -1318,32 +1291,8 @@ const MCSymbol &FrameEmitterImpl::EmitCIE(MCStreamer &streamer, // Initial Instructions const MCAsmInfo &MAI = context.getAsmInfo(); - const std::vector<MachineMove> &Moves = MAI.getInitialFrameState(); - std::vector<MCCFIInstruction> Instructions; - - for (int i = 0, n = Moves.size(); i != n; ++i) { - MCSymbol *Label = Moves[i].getLabel(); - const MachineLocation &Dst = - TranslateMachineLocation(MRI, Moves[i].getDestination()); - const MachineLocation &Src = - TranslateMachineLocation(MRI, Moves[i].getSource()); - - if (Dst.isReg()) { - assert(Dst.getReg() == MachineLocation::VirtualFP); - assert(!Src.isReg()); - MCCFIInstruction Inst = - MCCFIInstruction::createDefCfa(Label, Src.getReg(), -Src.getOffset()); - Instructions.push_back(Inst); - } else { - assert(Src.isReg()); - unsigned Reg = Src.getReg(); - int Offset = Dst.getOffset(); - MCCFIInstruction Inst = - MCCFIInstruction::createOffset(Label, Reg, Offset); - Instructions.push_back(Inst); - } - } - + const std::vector<MCCFIInstruction> &Instructions = + MAI.getInitialFrameState(); EmitCFIInstructions(streamer, Instructions, NULL); // Padding @@ -1421,7 +1370,6 @@ MCSymbol *FrameEmitterImpl::EmitFDE(MCStreamer &streamer, } // Call Frame Instructions - EmitCFIInstructions(streamer, frame.Instructions, frame.Begin); // Padding @@ -1476,21 +1424,28 @@ void MCDwarfFrameEmitter::Emit(MCStreamer &Streamer, bool UsingCFI, bool IsEH) { MCContext &Context = Streamer.getContext(); - MCObjectFileInfo *MOFI = - const_cast<MCObjectFileInfo*>(Context.getObjectFileInfo()); + const MCObjectFileInfo *MOFI = Context.getObjectFileInfo(); FrameEmitterImpl Emitter(UsingCFI, IsEH); ArrayRef<MCDwarfFrameInfo> FrameArray = Streamer.getFrameInfos(); // Emit the compact unwind info if available. - if (IsEH && MOFI->getCompactUnwindSection()) - for (unsigned i = 0, n = Streamer.getNumFrameInfos(); i < n; ++i) { - const MCDwarfFrameInfo &Frame = Streamer.getFrameInfo(i); - if (Frame.CompactUnwindEncoding) - Emitter.EmitCompactUnwind(Streamer, Frame); + if (IsEH && MOFI->getCompactUnwindSection()) { + bool SectionEmitted = false; + for (unsigned i = 0, n = FrameArray.size(); i < n; ++i) { + const MCDwarfFrameInfo &Frame = FrameArray[i]; + if (Frame.CompactUnwindEncoding == 0) continue; + if (!SectionEmitted) { + Streamer.SwitchSection(MOFI->getCompactUnwindSection()); + Streamer.EmitValueToAlignment(Context.getAsmInfo().getPointerSize()); + SectionEmitted = true; + } + Emitter.EmitCompactUnwind(Streamer, Frame); } + } - const MCSection &Section = IsEH ? *MOFI->getEHFrameSection() : - *MOFI->getDwarfFrameSection(); + const MCSection &Section = + IsEH ? *const_cast<MCObjectFileInfo*>(MOFI)->getEHFrameSection() : + *MOFI->getDwarfFrameSection(); Streamer.SwitchSection(&Section); MCSymbol *SectionStart = Context.CreateTempSymbol(); Streamer.EmitLabel(SectionStart); @@ -1524,15 +1479,19 @@ void MCDwarfFrameEmitter::Emit(MCStreamer &Streamer, void MCDwarfFrameEmitter::EmitAdvanceLoc(MCStreamer &Streamer, uint64_t AddrDelta) { + MCContext &Context = Streamer.getContext(); SmallString<256> Tmp; raw_svector_ostream OS(Tmp); - MCDwarfFrameEmitter::EncodeAdvanceLoc(AddrDelta, OS); + MCDwarfFrameEmitter::EncodeAdvanceLoc(Context, AddrDelta, OS); Streamer.EmitBytes(OS.str()); } -void MCDwarfFrameEmitter::EncodeAdvanceLoc(uint64_t AddrDelta, +void MCDwarfFrameEmitter::EncodeAdvanceLoc(MCContext &Context, + uint64_t AddrDelta, raw_ostream &OS) { - // FIXME: Assumes the code alignment factor is 1. + // Scale the address delta by the minimum instruction length. + AddrDelta = ScaleAddrDelta(Context, AddrDelta); + if (AddrDelta == 0) { } else if (isUIntN(6, AddrDelta)) { uint8_t Opcode = dwarf::DW_CFA_advance_loc | AddrDelta; |