diff --git a/include/llvm/MC/MCStreamer.h b/include/llvm/MC/MCStreamer.h index f75e9100d77..7c2de30649f 100644 --- a/include/llvm/MC/MCStreamer.h +++ b/include/llvm/MC/MCStreamer.h @@ -395,6 +395,7 @@ namespace llvm { virtual bool EmitCFIStartProc(); virtual bool EmitCFIEndProc(); + virtual bool EmitCFIDefCfa(int64_t Register, int64_t Offset); virtual bool EmitCFIDefCfaOffset(int64_t Offset); virtual bool EmitCFIDefCfaRegister(int64_t Register); virtual bool EmitCFIOffset(int64_t Register, int64_t Offset); diff --git a/lib/MC/MCDwarf.cpp b/lib/MC/MCDwarf.cpp index f3ba2bbb82f..e11da3737ec 100644 --- a/lib/MC/MCDwarf.cpp +++ b/lib/MC/MCDwarf.cpp @@ -440,10 +440,7 @@ static int getDataAlignmentFactor(MCStreamer &streamer) { } static void EmitCFIInstruction(MCStreamer &Streamer, - const MCCFIInstruction &Instr, - bool isEH) { - MCContext &context = Streamer.getContext(); - const TargetAsmInfo &asmInfo = context.getTargetAsmInfo(); + const MCCFIInstruction &Instr) { int dataAlignmentFactor = getDataAlignmentFactor(Streamer); switch (Instr.getOperation()) { @@ -459,8 +456,7 @@ static void EmitCFIInstruction(MCStreamer &Streamer, Streamer.EmitIntValue(dwarf::DW_CFA_def_cfa_offset, 1); } else { Streamer.EmitIntValue(dwarf::DW_CFA_def_cfa, 1); - Streamer.EmitULEB128IntValue(asmInfo.getDwarfRegNum(Src.getReg(), - isEH)); + Streamer.EmitULEB128IntValue(Src.getReg()); } Streamer.EmitULEB128IntValue(-Src.getOffset(), 1); @@ -470,11 +466,11 @@ static void EmitCFIInstruction(MCStreamer &Streamer, if (Src.isReg() && Src.getReg() == MachineLocation::VirtualFP) { assert(Dst.isReg() && "Machine move not supported yet."); Streamer.EmitIntValue(dwarf::DW_CFA_def_cfa_register, 1); - Streamer.EmitULEB128IntValue(asmInfo.getDwarfRegNum(Dst.getReg(), isEH)); + Streamer.EmitULEB128IntValue(Dst.getReg()); return; } - unsigned Reg = asmInfo.getDwarfRegNum(Src.getReg(), isEH); + unsigned Reg = Src.getReg(); int Offset = Dst.getOffset() / dataAlignmentFactor; if (Offset < 0) { @@ -505,7 +501,7 @@ static void EmitCFIInstruction(MCStreamer &Streamer, /// frame. static void EmitCFIInstructions(MCStreamer &streamer, const std::vector &Instrs, - MCSymbol *BaseLabel, bool isEH) { + MCSymbol *BaseLabel) { for (unsigned i = 0, N = Instrs.size(); i < N; ++i) { const MCCFIInstruction &Instr = Instrs[i]; MCSymbol *Label = Instr.getLabel(); @@ -521,7 +517,7 @@ static void EmitCFIInstructions(MCStreamer &streamer, } } - EmitCFIInstruction(streamer, Instr, isEH); + EmitCFIInstruction(streamer, Instr); } } @@ -566,6 +562,17 @@ static void EmitSymbol(MCStreamer &streamer, const MCSymbol &symbol, } } +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; +} + static const MCSymbol &EmitCIE(MCStreamer &streamer, const MCSymbol *personality, unsigned personalityEncoding, @@ -640,12 +647,16 @@ static const MCSymbol &EmitCIE(MCStreamer &streamer, std::vector Instructions; for (int i = 0, n = Moves.size(); i != n; ++i) { - MCCFIInstruction Inst(Moves[i].getLabel(), Moves[i].getDestination(), - Moves[i].getSource()); + MCSymbol *Label = Moves[i].getLabel(); + const MachineLocation &Dst = + TranslateMachineLocation(asmInfo, Moves[i].getDestination()); + const MachineLocation &Src = + TranslateMachineLocation(asmInfo, Moves[i].getSource()); + MCCFIInstruction Inst(Label, Dst, Src); Instructions.push_back(Inst); } - EmitCFIInstructions(streamer, Instructions, NULL, true); + EmitCFIInstructions(streamer, Instructions, NULL); // Padding streamer.EmitValueToAlignment(4); @@ -694,7 +705,7 @@ static MCSymbol *EmitFDE(MCStreamer &streamer, streamer.EmitLabel(augmentationEnd); // Call Frame Instructions - EmitCFIInstructions(streamer, frame.Instructions, frame.Begin, true); + EmitCFIInstructions(streamer, frame.Instructions, frame.Begin); // Padding streamer.EmitValueToAlignment(4); diff --git a/lib/MC/MCParser/AsmParser.cpp b/lib/MC/MCParser/AsmParser.cpp index 76c309e0276..d8a166cc713 100644 --- a/lib/MC/MCParser/AsmParser.cpp +++ b/lib/MC/MCParser/AsmParser.cpp @@ -244,6 +244,8 @@ public: ".cfi_startproc"); AddDirectiveHandler<&GenericAsmParser::ParseDirectiveCFIEndProc>( ".cfi_endproc"); + AddDirectiveHandler<&GenericAsmParser::ParseDirectiveCFIDefCfa>( + ".cfi_def_cfa"); AddDirectiveHandler<&GenericAsmParser::ParseDirectiveCFIDefCfaOffset>( ".cfi_def_cfa_offset"); AddDirectiveHandler<&GenericAsmParser::ParseDirectiveCFIDefCfaRegister>( @@ -278,6 +280,7 @@ public: bool ParseDirectiveStabs(StringRef, SMLoc DirectiveLoc); bool ParseDirectiveCFIStartProc(StringRef, SMLoc DirectiveLoc); bool ParseDirectiveCFIEndProc(StringRef, SMLoc DirectiveLoc); + bool ParseDirectiveCFIDefCfa(StringRef, SMLoc DirectiveLoc); bool ParseDirectiveCFIDefCfaOffset(StringRef, SMLoc DirectiveLoc); bool ParseDirectiveCFIDefCfaRegister(StringRef, SMLoc DirectiveLoc); bool ParseDirectiveCFIOffset(StringRef, SMLoc DirectiveLoc); @@ -2172,6 +2175,25 @@ bool GenericAsmParser::ParseDirectiveCFIEndProc(StringRef, SMLoc DirectiveLoc) { return getStreamer().EmitCFIEndProc(); } +/// ParseDirectiveCFIDefCfa +/// ::= .cfi_def_cfa register, offset +bool GenericAsmParser::ParseDirectiveCFIDefCfa(StringRef, + SMLoc DirectiveLoc) { + int64_t Register = 0; + if (getParser().ParseAbsoluteExpression(Register)) + return true; + + if (getLexer().isNot(AsmToken::Comma)) + return TokError("unexpected token in directive"); + Lex(); + + int64_t Offset = 0; + if (getParser().ParseAbsoluteExpression(Offset)) + return true; + + return getStreamer().EmitCFIDefCfa(Register, Offset); +} + /// ParseDirectiveCFIDefCfaOffset /// ::= .cfi_def_cfa_offset offset bool GenericAsmParser::ParseDirectiveCFIDefCfaOffset(StringRef, diff --git a/lib/MC/MCStreamer.cpp b/lib/MC/MCStreamer.cpp index 4d7d486ea91..c5dc1c7ff36 100644 --- a/lib/MC/MCStreamer.cpp +++ b/lib/MC/MCStreamer.cpp @@ -172,6 +172,18 @@ bool MCStreamer::EmitCFIEndProc() { return false; } +bool MCStreamer::EmitCFIDefCfa(int64_t Register, int64_t Offset) { + EnsureValidFrame(); + MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo(); + MCSymbol *Label = getContext().CreateTempSymbol(); + EmitLabel(Label); + MachineLocation Dest(MachineLocation::VirtualFP); + MachineLocation Source(Register, -Offset); + MCCFIInstruction Instruction(Label, Dest, Source); + CurFrame->Instructions.push_back(Instruction); + return false; +} + bool MCStreamer::EmitCFIDefCfaOffset(int64_t Offset) { EnsureValidFrame(); MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo(); diff --git a/test/MC/ELF/cfi-def-cfa.s b/test/MC/ELF/cfi-def-cfa.s new file mode 100644 index 00000000000..1ad427b310c --- /dev/null +++ b/test/MC/ELF/cfi-def-cfa.s @@ -0,0 +1,42 @@ +// RUN: llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu %s -o - | elf-dump --dump-section-data | FileCheck %s + +f: + .cfi_startproc + nop + .cfi_def_cfa 7, 8 + nop + .cfi_endproc + +// CHECK: (('sh_name', 0x00000012) # '.eh_frame' +// CHECK-NEXT: ('sh_type', 0x00000001) +// CHECK-NEXT: ('sh_flags', 0x00000002) +// CHECK-NEXT: ('sh_addr', 0x00000000) +// CHECK-NEXT: ('sh_offset', 0x00000048) +// CHECK-NEXT: ('sh_size', 0x00000030) +// CHECK-NEXT: ('sh_link', 0x00000000) +// CHECK-NEXT: ('sh_info', 0x00000000) +// CHECK-NEXT: ('sh_addralign', 0x00000008) +// CHECK-NEXT: ('sh_entsize', 0x00000000) +// CHECK-NEXT: ('_section_data', '14000000 00000000 017a5200 01781001 1b0c0708 90010000 14000000 1c000000 00000000 02000000 00410c07 08000000') +// CHECK-NEXT: ), + + +// CHECK: (('sh_name', 0x00000036) # '.rela.eh_frame' +// CHECK-NEXT: ('sh_type', 0x00000004) +// CHECK-NEXT: ('sh_flags', 0x00000000) +// CHECK-NEXT: ('sh_addr', 0x00000000) +// CHECK-NEXT: ('sh_offset', 0x00000158) +// CHECK-NEXT: ('sh_size', 0x00000018) +// CHECK-NEXT: ('sh_link', 0x00000006) +// CHECK-NEXT: ('sh_info', 0x00000004) +// CHECK-NEXT: ('sh_addralign', 0x00000008) +// CHECK-NEXT: ('sh_entsize', 0x00000018) +// CHECK-NEXT: ('_relocations', [ +// CHECK-NEXT: # Relocation 0x00000000 +// CHECK-NEXT: (('r_offset', 0x00000020) +// CHECK-NEXT: ('r_sym', 0x00000002) +// CHECK-NEXT: ('r_type', 0x00000002) +// CHECK-NEXT: ('r_addend', 0x00000000) +// CHECK-NEXT: ), +// CHECK-NEXT: ]) +// CHECK-NEXT: ),