diff --git a/include/llvm/MC/MCAsmInfo.h b/include/llvm/MC/MCAsmInfo.h index 72d325f79c9..781a9d010ba 100644 --- a/include/llvm/MC/MCAsmInfo.h +++ b/include/llvm/MC/MCAsmInfo.h @@ -89,6 +89,10 @@ namespace llvm { /// which is needed to compute the size of an inline asm. unsigned MaxInstLength; // Defaults to 4. + /// MinInstAlignment - Every possible instruction length is a multiple of + /// this value. Factored out in .debug_frame and .debug_line. + unsigned MinInstAlignment; // Defaults to 1. + /// PCSymbol - The symbol used to represent the current PC. Used in PC /// relative expressions. const char *PCSymbol; // Defaults to "$". @@ -429,6 +433,9 @@ namespace llvm { unsigned getMaxInstLength() const { return MaxInstLength; } + unsigned getMinInstAlignment() const { + return MinInstAlignment; + } const char *getPCSymbol() const { return PCSymbol; } diff --git a/include/llvm/MC/MCDwarf.h b/include/llvm/MC/MCDwarf.h index 1a392e8755e..3ece2626a0c 100644 --- a/include/llvm/MC/MCDwarf.h +++ b/include/llvm/MC/MCDwarf.h @@ -24,7 +24,6 @@ namespace llvm { class MCContext; - class MCObjectWriter; class MCSection; class MCStreamer; class MCSymbol; @@ -229,15 +228,12 @@ namespace llvm { class MCDwarfLineAddr { public: /// Utility function to encode a Dwarf pair of LineDelta and AddrDeltas. - static void Encode(int64_t LineDelta, uint64_t AddrDelta, raw_ostream &OS); + static void Encode(MCContext &Context, int64_t LineDelta, + uint64_t AddrDelta, raw_ostream &OS); /// Utility function to emit the encoding to a streamer. static void Emit(MCStreamer *MCOS, int64_t LineDelta,uint64_t AddrDelta); - - /// Utility function to write the encoding to an object writer. - static void Write(MCObjectWriter *OW, - int64_t LineDelta, uint64_t AddrDelta); }; class MCGenDwarfInfo { @@ -418,7 +414,8 @@ namespace llvm { static void Emit(MCStreamer &streamer, bool usingCFI, bool isEH); static void EmitAdvanceLoc(MCStreamer &Streamer, uint64_t AddrDelta); - static void EncodeAdvanceLoc(uint64_t AddrDelta, raw_ostream &OS); + static void EncodeAdvanceLoc(MCContext &Context, uint64_t AddrDelta, + raw_ostream &OS); }; } // end namespace llvm diff --git a/lib/MC/MCAsmInfo.cpp b/lib/MC/MCAsmInfo.cpp index 9e6088490fd..3d843b7c94d 100644 --- a/lib/MC/MCAsmInfo.cpp +++ b/lib/MC/MCAsmInfo.cpp @@ -34,6 +34,7 @@ MCAsmInfo::MCAsmInfo() { HasStaticCtorDtorReferenceInStaticMode = false; LinkerRequiresNonEmptyDwarfLines = false; MaxInstLength = 4; + MinInstAlignment = 1; PCSymbol = "$"; SeparatorString = ";"; CommentColumn = 40; diff --git a/lib/MC/MCAssembler.cpp b/lib/MC/MCAssembler.cpp index fb5ab28bcf5..97f675a1ffa 100644 --- a/lib/MC/MCAssembler.cpp +++ b/lib/MC/MCAssembler.cpp @@ -904,6 +904,7 @@ bool MCAssembler::relaxLEB(MCAsmLayout &Layout, MCLEBFragment &LF) { bool MCAssembler::relaxDwarfLineAddr(MCAsmLayout &Layout, MCDwarfLineAddrFragment &DF) { + MCContext &Context = Layout.getAssembler().getContext(); int64_t AddrDelta = 0; uint64_t OldSize = DF.getContents().size(); bool IsAbs = DF.getAddrDelta().EvaluateAsAbsolute(AddrDelta, Layout); @@ -914,13 +915,14 @@ bool MCAssembler::relaxDwarfLineAddr(MCAsmLayout &Layout, SmallString<8> &Data = DF.getContents(); Data.clear(); raw_svector_ostream OSE(Data); - MCDwarfLineAddr::Encode(LineDelta, AddrDelta, OSE); + MCDwarfLineAddr::Encode(Context, LineDelta, AddrDelta, OSE); OSE.flush(); return OldSize != Data.size(); } bool MCAssembler::relaxDwarfCallFrameFragment(MCAsmLayout &Layout, MCDwarfCallFrameFragment &DF) { + MCContext &Context = Layout.getAssembler().getContext(); int64_t AddrDelta = 0; uint64_t OldSize = DF.getContents().size(); bool IsAbs = DF.getAddrDelta().EvaluateAsAbsolute(AddrDelta, Layout); @@ -929,7 +931,7 @@ bool MCAssembler::relaxDwarfCallFrameFragment(MCAsmLayout &Layout, SmallString<8> &Data = DF.getContents(); Data.clear(); raw_svector_ostream OSE(Data); - MCDwarfFrameEmitter::EncodeAdvanceLoc(AddrDelta, OSE); + MCDwarfFrameEmitter::EncodeAdvanceLoc(Context, AddrDelta, OSE); OSE.flush(); return OldSize != Data.size(); } diff --git a/lib/MC/MCDwarf.cpp b/lib/MC/MCDwarf.cpp index 90221a15f00..21ccc3efd93 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; } // @@ -277,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); @@ -357,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 @@ -1256,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"); @@ -1493,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; diff --git a/lib/Target/PowerPC/MCTargetDesc/PPCMCAsmInfo.cpp b/lib/Target/PowerPC/MCTargetDesc/PPCMCAsmInfo.cpp index a25d7fe64f3..bb7ce6f23c6 100644 --- a/lib/Target/PowerPC/MCTargetDesc/PPCMCAsmInfo.cpp +++ b/lib/Target/PowerPC/MCTargetDesc/PPCMCAsmInfo.cpp @@ -59,6 +59,7 @@ PPCLinuxMCAsmInfo::PPCLinuxMCAsmInfo(bool is64Bit) { // Set up DWARF directives HasLEB128 = true; // Target asm supports leb128 directives (little-endian) + MinInstAlignment = 4; // Exceptions handling ExceptionsType = ExceptionHandling::DwarfCFI; diff --git a/test/MC/PowerPC/ppc64-initial-cfa.s b/test/MC/PowerPC/ppc64-initial-cfa.s index fb45474c16b..f976ae9ffa3 100644 --- a/test/MC/PowerPC/ppc64-initial-cfa.s +++ b/test/MC/PowerPC/ppc64-initial-cfa.s @@ -23,7 +23,7 @@ # STATIC-NEXT: Relocations [ # STATIC-NEXT: ] # STATIC-NEXT: SectionData ( -# STATIC-NEXT: 0000: 00000010 00000000 017A5200 01784101 +# STATIC-NEXT: 0000: 00000010 00000000 017A5200 04784101 # STATIC-NEXT: 0010: 1B0C0100 00000010 00000018 00000000 # STATIC-NEXT: 0020: 00000004 00000000 # STATIC-NEXT: ) @@ -61,7 +61,7 @@ # PIC-NEXT: Relocations [ # PIC-NEXT: ] # PIC-NEXT: SectionData ( -# PIC-NEXT: 0000: 00000010 00000000 017A5200 01784101 +# PIC-NEXT: 0000: 00000010 00000000 017A5200 04784101 # PIC-NEXT: 0010: 1B0C0100 00000010 00000018 00000000 # PIC-NEXT: 0020: 00000004 00000000 # PIC-NEXT: )