diff --git a/llvm/include/llvm/BinaryFormat/Dwarf.def b/llvm/include/llvm/BinaryFormat/Dwarf.def --- a/llvm/include/llvm/BinaryFormat/Dwarf.def +++ b/llvm/include/llvm/BinaryFormat/Dwarf.def @@ -912,6 +912,10 @@ HANDLE_DW_CFA_PRED(0x2d, GNU_window_save, SELECT_SPARC) HANDLE_DW_CFA_PRED(0x2d, AARCH64_negate_ra_state, SELECT_AARCH64) HANDLE_DW_CFA_PRED(0x2e, GNU_args_size, SELECT_X86) +// Heterogeneous Debugging Extension defined at +// https://llvm.org/docs/AMDGPUDwarfExtensionsForHeterogeneousDebugging.html +HANDLE_DW_CFA(0x30, LLVM_def_aspace_cfa) +HANDLE_DW_CFA(0x31, LLVM_def_aspace_cfa_sf) // Apple Objective-C Property Attributes. // Keep this list in sync with clang's DeclObjCCommon.h diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h --- a/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h +++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h @@ -33,7 +33,7 @@ /// manual, "6.4.1 Structure of Call Frame Information". class CFIProgram { public: - typedef SmallVector Operands; + typedef SmallVector Operands; /// An instruction consists of a DWARF CFI opcode and an optional sequence of /// operands. If it refers to an expression, then this expression has its own @@ -98,6 +98,15 @@ Instructions.back().Ops.push_back(Operand2); } + /// Add a new instruction that has three operands. + void addInstruction(uint8_t Opcode, uint64_t Operand1, uint64_t Operand2, + uint64_t Operand3) { + Instructions.push_back(Instruction(Opcode)); + Instructions.back().Ops.push_back(Operand1); + Instructions.back().Ops.push_back(Operand2); + Instructions.back().Ops.push_back(Operand3); + } + /// Types of operands to CFI instructions /// In DWARF, this type is implicitly tied to a CFI instruction opcode and /// thus this type doesn't need to be explictly written to the file (this is @@ -113,12 +122,13 @@ OT_SignedFactDataOffset, OT_UnsignedFactDataOffset, OT_Register, + OT_AddressSpace, OT_Expression }; /// Retrieve the array describing the types of operands according to the enum /// above. This is indexed by opcode. - static ArrayRef getOperandTypes(); + static ArrayRef getOperandTypes(); /// Print \p Opcode's operand number \p OperandIdx which has value \p Operand. void printOperand(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH, diff --git a/llvm/include/llvm/MC/MCDwarf.h b/llvm/include/llvm/MC/MCDwarf.h --- a/llvm/include/llvm/MC/MCDwarf.h +++ b/llvm/include/llvm/MC/MCDwarf.h @@ -444,6 +444,7 @@ OpRememberState, OpRestoreState, OpOffset, + OpLLVMDefAspaceCfa, OpDefCfaRegister, OpDefCfaOffset, OpDefCfa, @@ -466,6 +467,7 @@ int Offset; unsigned Register2; }; + unsigned AddressSpace; std::vector Values; std::string Comment; @@ -473,7 +475,7 @@ StringRef Comment = "") : Operation(Op), Label(L), Register(R), Offset(O), Values(V.begin(), V.end()), Comment(Comment) { - assert(Op != OpRegister); + assert(Op != OpRegister && Op != OpLLVMDefAspaceCfa); } MCCFIInstruction(OpType Op, MCSymbol *L, unsigned R1, unsigned R2) @@ -481,6 +483,11 @@ assert(Op == OpRegister); } + MCCFIInstruction(OpType Op, MCSymbol *L, unsigned R, int O, unsigned AS) + : Operation(Op), Label(L), Register(R), Offset(O), AddressSpace(AS) { + assert(Op == OpLLVMDefAspaceCfa); + } + public: /// .cfi_def_cfa defines a rule for computing CFA as: take address from /// Register and add Offset to it. @@ -509,6 +516,17 @@ return MCCFIInstruction(OpAdjustCfaOffset, L, 0, Adjustment, ""); } + // FIXME: Update the remaining docs to use the new proposal wording. + /// .cfi_llvm_def_aspace_cfa defines the rule for computing the CFA to + /// be the result of evaluating the DWARF operation expression + /// `DW_OP_constu AS; DW_OP_aspace_bregx R, B` as a location description. + static MCCFIInstruction createLLVMDefAspaceCfa(MCSymbol *L, unsigned Register, + int Offset, + unsigned AddressSpace) { + return MCCFIInstruction(OpLLVMDefAspaceCfa, L, Register, Offset, + AddressSpace); + } + /// .cfi_offset Previous value of Register is saved at offset Offset /// from CFA. static MCCFIInstruction createOffset(MCSymbol *L, unsigned Register, @@ -589,7 +607,8 @@ assert(Operation == OpDefCfa || Operation == OpOffset || Operation == OpRestore || Operation == OpUndefined || Operation == OpSameValue || Operation == OpDefCfaRegister || - Operation == OpRelOffset || Operation == OpRegister); + Operation == OpRelOffset || Operation == OpRegister || + Operation == OpLLVMDefAspaceCfa); return Register; } @@ -598,10 +617,16 @@ return Register2; } + unsigned getAddressSpace() const { + assert(Operation == OpLLVMDefAspaceCfa); + return AddressSpace; + } + int getOffset() const { assert(Operation == OpDefCfa || Operation == OpOffset || Operation == OpRelOffset || Operation == OpDefCfaOffset || - Operation == OpAdjustCfaOffset || Operation == OpGnuArgsSize); + Operation == OpAdjustCfaOffset || Operation == OpGnuArgsSize || + Operation == OpLLVMDefAspaceCfa); return Offset; } diff --git a/llvm/include/llvm/MC/MCStreamer.h b/llvm/include/llvm/MC/MCStreamer.h --- a/llvm/include/llvm/MC/MCStreamer.h +++ b/llvm/include/llvm/MC/MCStreamer.h @@ -965,6 +965,8 @@ virtual void emitCFIDefCfa(int64_t Register, int64_t Offset); virtual void emitCFIDefCfaOffset(int64_t Offset); virtual void emitCFIDefCfaRegister(int64_t Register); + virtual void emitCFILLVMDefAspaceCfa(int64_t Register, int64_t Offset, + int64_t AddressSpace); virtual void emitCFIOffset(int64_t Register, int64_t Offset); virtual void emitCFIPersonality(const MCSymbol *Sym, unsigned Encoding); virtual void emitCFILsda(const MCSymbol *Sym, unsigned Encoding); diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp @@ -252,6 +252,10 @@ case MCCFIInstruction::OpDefCfaRegister: OutStreamer->emitCFIDefCfaRegister(Inst.getRegister()); break; + case MCCFIInstruction::OpLLVMDefAspaceCfa: + OutStreamer->emitCFILLVMDefAspaceCfa(Inst.getRegister(), Inst.getOffset(), + Inst.getAddressSpace()); + break; case MCCFIInstruction::OpOffset: OutStreamer->emitCFIOffset(Inst.getRegister(), Inst.getOffset()); break; diff --git a/llvm/lib/CodeGen/CFIInstrInserter.cpp b/llvm/lib/CodeGen/CFIInstrInserter.cpp --- a/llvm/lib/CodeGen/CFIInstrInserter.cpp +++ b/llvm/lib/CodeGen/CFIInstrInserter.cpp @@ -220,6 +220,14 @@ case MCCFIInstruction::OpRestore: CSRRestored.set(CFI.getRegister()); break; + case MCCFIInstruction::OpLLVMDefAspaceCfa: + // TODO: Add support for handling cfi_def_aspace_cfa. +#ifndef NDEBUG + report_fatal_error( + "Support for cfi_llvm_def_aspace_cfa not implemented! Value of CFA " + "may be incorrect!\n"); +#endif + break; case MCCFIInstruction::OpRememberState: // TODO: Add support for handling cfi_remember_state. #ifndef NDEBUG diff --git a/llvm/lib/CodeGen/MIRParser/MILexer.h b/llvm/lib/CodeGen/MIRParser/MILexer.h --- a/llvm/lib/CodeGen/MIRParser/MILexer.h +++ b/llvm/lib/CodeGen/MIRParser/MILexer.h @@ -82,6 +82,7 @@ kw_cfi_adjust_cfa_offset, kw_cfi_escape, kw_cfi_def_cfa, + kw_cfi_llvm_def_aspace_cfa, kw_cfi_register, kw_cfi_remember_state, kw_cfi_restore, diff --git a/llvm/lib/CodeGen/MIRParser/MILexer.cpp b/llvm/lib/CodeGen/MIRParser/MILexer.cpp --- a/llvm/lib/CodeGen/MIRParser/MILexer.cpp +++ b/llvm/lib/CodeGen/MIRParser/MILexer.cpp @@ -225,6 +225,7 @@ .Case("adjust_cfa_offset", MIToken::kw_cfi_adjust_cfa_offset) .Case("escape", MIToken::kw_cfi_escape) .Case("def_cfa", MIToken::kw_cfi_def_cfa) + .Case("llvm_def_aspace_cfa", MIToken::kw_cfi_llvm_def_aspace_cfa) .Case("remember_state", MIToken::kw_cfi_remember_state) .Case("restore", MIToken::kw_cfi_restore) .Case("restore_state", MIToken::kw_cfi_restore_state) diff --git a/llvm/lib/CodeGen/MIRParser/MIParser.cpp b/llvm/lib/CodeGen/MIRParser/MIParser.cpp --- a/llvm/lib/CodeGen/MIRParser/MIParser.cpp +++ b/llvm/lib/CodeGen/MIRParser/MIParser.cpp @@ -475,6 +475,7 @@ bool parseMetadataOperand(MachineOperand &Dest); bool parseCFIOffset(int &Offset); bool parseCFIRegister(Register &Reg); + bool parseCFIAddressSpace(unsigned &AddressSpace); bool parseCFIEscapeValues(std::string& Values); bool parseCFIOperand(MachineOperand &Dest); bool parseIRBlock(BasicBlock *&BB, const Function &F); @@ -2192,6 +2193,16 @@ return false; } +bool MIParser::parseCFIAddressSpace(unsigned &AddressSpace) { + if (Token.isNot(MIToken::IntegerLiteral)) + return error("expected a cfi address space"); + if (Token.integerValue().isSigned()) + return error("expected an unsigned integer (cfi address space)"); + AddressSpace = Token.integerValue().getZExtValue(); + lex(); + return false; +} + bool MIParser::parseCFIEscapeValues(std::string &Values) { do { if (Token.isNot(MIToken::HexLiteral)) @@ -2212,6 +2223,7 @@ lex(); int Offset; Register Reg; + unsigned AddressSpace; unsigned CFIIndex; switch (Kind) { case MIToken::kw_cfi_same_value: @@ -2258,6 +2270,14 @@ CFIIndex = MF.addFrameInst(MCCFIInstruction::cfiDefCfa(nullptr, Reg, Offset)); break; + case MIToken::kw_cfi_llvm_def_aspace_cfa: + if (parseCFIRegister(Reg) || expectAndConsume(MIToken::comma) || + parseCFIOffset(Offset) || expectAndConsume(MIToken::comma) || + parseCFIAddressSpace(AddressSpace)) + return true; + CFIIndex = MF.addFrameInst(MCCFIInstruction::createLLVMDefAspaceCfa( + nullptr, Reg, Offset, AddressSpace)); + break; case MIToken::kw_cfi_remember_state: CFIIndex = MF.addFrameInst(MCCFIInstruction::createRememberState(nullptr)); break; @@ -2605,6 +2625,7 @@ case MIToken::kw_cfi_adjust_cfa_offset: case MIToken::kw_cfi_escape: case MIToken::kw_cfi_def_cfa: + case MIToken::kw_cfi_llvm_def_aspace_cfa: case MIToken::kw_cfi_register: case MIToken::kw_cfi_remember_state: case MIToken::kw_cfi_restore: diff --git a/llvm/lib/CodeGen/MachineOperand.cpp b/llvm/lib/CodeGen/MachineOperand.cpp --- a/llvm/lib/CodeGen/MachineOperand.cpp +++ b/llvm/lib/CodeGen/MachineOperand.cpp @@ -653,6 +653,14 @@ printCFIRegister(CFI.getRegister(), OS, TRI); OS << ", " << CFI.getOffset(); break; + case MCCFIInstruction::OpLLVMDefAspaceCfa: + OS << "llvm_def_aspace_cfa "; + if (MCSymbol *Label = CFI.getLabel()) + MachineOperand::printSymbol(OS, *Label); + printCFIRegister(CFI.getRegister(), OS, TRI); + OS << ", " << CFI.getOffset(); + OS << ", " << CFI.getAddressSpace(); + break; case MCCFIInstruction::OpRelOffset: OS << "rel_offset "; if (MCSymbol *Label = CFI.getLabel()) diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp --- a/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp @@ -115,6 +115,16 @@ // Operands: SLEB128 addInstruction(Opcode, Data.getSLEB128(C)); break; + case DW_CFA_LLVM_def_aspace_cfa: + case DW_CFA_LLVM_def_aspace_cfa_sf: { + auto RegNum = Data.getULEB128(C); + auto CfaOffset = Opcode == DW_CFA_LLVM_def_aspace_cfa + ? Data.getULEB128(C) + : Data.getSLEB128(C); + auto AddressSpace = Data.getULEB128(C); + addInstruction(Opcode, RegNum, CfaOffset, AddressSpace); + break; + } case DW_CFA_offset_extended: case DW_CFA_register: case DW_CFA_def_cfa: @@ -180,19 +190,22 @@ } // end anonymous namespace -ArrayRef CFIProgram::getOperandTypes() { - static OperandType OpTypes[DW_CFA_restore+1][2]; +ArrayRef CFIProgram::getOperandTypes() { + static OperandType OpTypes[DW_CFA_restore + 1][3]; static bool Initialized = false; if (Initialized) { - return ArrayRef(&OpTypes[0], DW_CFA_restore+1); + return ArrayRef(&OpTypes[0], DW_CFA_restore + 1); } Initialized = true; -#define DECLARE_OP2(OP, OPTYPE0, OPTYPE1) \ - do { \ - OpTypes[OP][0] = OPTYPE0; \ - OpTypes[OP][1] = OPTYPE1; \ +#define DECLARE_OP3(OP, OPTYPE0, OPTYPE1, OPTYPE2) \ + do { \ + OpTypes[OP][0] = OPTYPE0; \ + OpTypes[OP][1] = OPTYPE1; \ + OpTypes[OP][2] = OPTYPE2; \ } while (false) +#define DECLARE_OP2(OP, OPTYPE0, OPTYPE1) \ + DECLARE_OP3(OP, OPTYPE0, OPTYPE1, OT_None) #define DECLARE_OP1(OP, OPTYPE0) DECLARE_OP2(OP, OPTYPE0, OT_None) #define DECLARE_OP0(OP) DECLARE_OP1(OP, OT_None) @@ -205,6 +218,10 @@ DECLARE_OP2(DW_CFA_def_cfa, OT_Register, OT_Offset); DECLARE_OP2(DW_CFA_def_cfa_sf, OT_Register, OT_SignedFactDataOffset); DECLARE_OP1(DW_CFA_def_cfa_register, OT_Register); + DECLARE_OP3(DW_CFA_LLVM_def_aspace_cfa, OT_Register, OT_Offset, + OT_AddressSpace); + DECLARE_OP3(DW_CFA_LLVM_def_aspace_cfa_sf, OT_Register, + OT_SignedFactDataOffset, OT_AddressSpace); DECLARE_OP1(DW_CFA_def_cfa_offset, OT_Offset); DECLARE_OP1(DW_CFA_def_cfa_offset_sf, OT_SignedFactDataOffset); DECLARE_OP1(DW_CFA_def_cfa_expression, OT_Expression); @@ -230,14 +247,14 @@ #undef DECLARE_OP1 #undef DECLARE_OP2 - return ArrayRef(&OpTypes[0], DW_CFA_restore+1); + return ArrayRef(&OpTypes[0], DW_CFA_restore + 1); } /// Print \p Opcode's operand number \p OperandIdx which has value \p Operand. void CFIProgram::printOperand(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH, const Instruction &Instr, unsigned OperandIdx, uint64_t Operand) const { - assert(OperandIdx < 2); + assert(OperandIdx < 3); uint8_t Opcode = Instr.Opcode; OperandType Type = getOperandTypes()[Opcode][OperandIdx]; @@ -284,6 +301,9 @@ OS << ' '; printRegister(OS, MRI, IsEH, Operand); break; + case OT_AddressSpace: + OS << format(" as%" PRId64, Operand); + break; case OT_Expression: assert(Instr.Expression && "missing DWARFExpression object"); OS << " "; diff --git a/llvm/lib/MC/MCAsmStreamer.cpp b/llvm/lib/MC/MCAsmStreamer.cpp --- a/llvm/lib/MC/MCAsmStreamer.cpp +++ b/llvm/lib/MC/MCAsmStreamer.cpp @@ -302,6 +302,8 @@ void emitCFIDefCfa(int64_t Register, int64_t Offset) override; void emitCFIDefCfaOffset(int64_t Offset) override; void emitCFIDefCfaRegister(int64_t Register) override; + void emitCFILLVMDefAspaceCfa(int64_t Register, int64_t Offset, + int64_t AddressSpace) override; void emitCFIOffset(int64_t Register, int64_t Offset) override; void emitCFIPersonality(const MCSymbol *Sym, unsigned Encoding) override; void emitCFILsda(const MCSymbol *Sym, unsigned Encoding) override; @@ -1714,6 +1716,19 @@ EmitEOL(); } +void MCAsmStreamer::emitCFILLVMDefAspaceCfa(int64_t Register, int64_t Offset, + int64_t AddressSpace) { + MCStreamer::emitCFILLVMDefAspaceCfa(Register, Offset, AddressSpace); + OS << "\t.cfi_llvm_def_aspace_cfa "; + EmitRegisterName(Register); + OS << ", " << Offset; + OS << ", " << AddressSpace; + // FIXME: When going from ASM->ASM a lot of these directives seem to add too + // much whitespace; maybe something isn't consuming whitespace eagerly enough + // while parsing? + EmitEOL(); +} + static void PrintCFIEscape(llvm::formatted_raw_ostream &OS, StringRef Values) { OS << "\t.cfi_escape "; if (!Values.empty()) { diff --git a/llvm/lib/MC/MCDwarf.cpp b/llvm/lib/MC/MCDwarf.cpp --- a/llvm/lib/MC/MCDwarf.cpp +++ b/llvm/lib/MC/MCDwarf.cpp @@ -1440,6 +1440,16 @@ return; } + // TODO: Implement `_sf` variants if/when they need to be emitted. + case MCCFIInstruction::OpLLVMDefAspaceCfa: { + Streamer.emitIntValue(dwarf::DW_CFA_LLVM_def_aspace_cfa, 1); + Streamer.emitULEB128IntValue(Instr.getRegister()); + CFAOffset = Instr.getOffset(); + Streamer.emitULEB128IntValue(CFAOffset); + Streamer.emitULEB128IntValue(Instr.getAddressSpace()); + + return; + } case MCCFIInstruction::OpOffset: case MCCFIInstruction::OpRelOffset: { const bool IsRelative = diff --git a/llvm/lib/MC/MCParser/AsmParser.cpp b/llvm/lib/MC/MCParser/AsmParser.cpp --- a/llvm/lib/MC/MCParser/AsmParser.cpp +++ b/llvm/lib/MC/MCParser/AsmParser.cpp @@ -482,6 +482,7 @@ DK_CFI_DEF_CFA_OFFSET, DK_CFI_ADJUST_CFA_OFFSET, DK_CFI_DEF_CFA_REGISTER, + DK_CFI_LLVM_DEF_ASPACE_CFA, DK_CFI_OFFSET, DK_CFI_REL_OFFSET, DK_CFI_PERSONALITY, @@ -581,6 +582,7 @@ bool parseDirectiveCFIDefCfa(SMLoc DirectiveLoc); bool parseDirectiveCFIAdjustCfaOffset(); bool parseDirectiveCFIDefCfaRegister(SMLoc DirectiveLoc); + bool parseDirectiveCFILLVMDefAspaceCfa(SMLoc DirectiveLoc); bool parseDirectiveCFIOffset(SMLoc DirectiveLoc); bool parseDirectiveCFIRelOffset(SMLoc DirectiveLoc); bool parseDirectiveCFIPersonalityOrLsda(bool IsPersonality); @@ -2109,6 +2111,8 @@ return parseDirectiveCFIAdjustCfaOffset(); case DK_CFI_DEF_CFA_REGISTER: return parseDirectiveCFIDefCfaRegister(IDLoc); + case DK_CFI_LLVM_DEF_ASPACE_CFA: + return parseDirectiveCFILLVMDefAspaceCfa(IDLoc); case DK_CFI_OFFSET: return parseDirectiveCFIOffset(IDLoc); case DK_CFI_REL_OFFSET: @@ -4183,6 +4187,21 @@ return false; } +/// parseDirectiveCFILLVMDefAspaceCfa +/// ::= .cfi_llvm_def_aspace_cfa register, offset, address_space +bool AsmParser::parseDirectiveCFILLVMDefAspaceCfa(SMLoc DirectiveLoc) { + int64_t Register = 0, Offset = 0, AddressSpace = 0; + if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || + parseToken(AsmToken::Comma, "unexpected token in directive") || + parseAbsoluteExpression(Offset) || + parseToken(AsmToken::Comma, "unexpected token in directive") || + parseAbsoluteExpression(AddressSpace)) + return true; + + getStreamer().emitCFILLVMDefAspaceCfa(Register, Offset, AddressSpace); + return false; +} + /// parseDirectiveCFIOffset /// ::= .cfi_offset register, offset bool AsmParser::parseDirectiveCFIOffset(SMLoc DirectiveLoc) { @@ -5455,6 +5474,7 @@ DirectiveKindMap[".cfi_def_cfa_offset"] = DK_CFI_DEF_CFA_OFFSET; DirectiveKindMap[".cfi_adjust_cfa_offset"] = DK_CFI_ADJUST_CFA_OFFSET; DirectiveKindMap[".cfi_def_cfa_register"] = DK_CFI_DEF_CFA_REGISTER; + DirectiveKindMap[".cfi_llvm_def_aspace_cfa"] = DK_CFI_LLVM_DEF_ASPACE_CFA; DirectiveKindMap[".cfi_offset"] = DK_CFI_OFFSET; DirectiveKindMap[".cfi_rel_offset"] = DK_CFI_REL_OFFSET; DirectiveKindMap[".cfi_personality"] = DK_CFI_PERSONALITY; diff --git a/llvm/lib/MC/MCStreamer.cpp b/llvm/lib/MC/MCStreamer.cpp --- a/llvm/lib/MC/MCStreamer.cpp +++ b/llvm/lib/MC/MCStreamer.cpp @@ -518,6 +518,18 @@ CurFrame->CurrentCfaRegister = static_cast(Register); } +void MCStreamer::emitCFILLVMDefAspaceCfa(int64_t Register, int64_t Offset, + int64_t AddressSpace) { + MCSymbol *Label = emitCFILabel(); + MCCFIInstruction Instruction = MCCFIInstruction::createLLVMDefAspaceCfa( + Label, Register, Offset, AddressSpace); + MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo(); + if (!CurFrame) + return; + CurFrame->Instructions.push_back(Instruction); + CurFrame->CurrentCfaRegister = static_cast(Register); +} + void MCStreamer::emitCFIOffset(int64_t Register, int64_t Offset) { MCSymbol *Label = emitCFILabel(); MCCFIInstruction Instruction = diff --git a/llvm/test/CodeGen/MIR/AArch64/cfi.mir b/llvm/test/CodeGen/MIR/AArch64/cfi.mir --- a/llvm/test/CodeGen/MIR/AArch64/cfi.mir +++ b/llvm/test/CodeGen/MIR/AArch64/cfi.mir @@ -23,6 +23,8 @@ frame-setup CFI_INSTRUCTION def_cfa_register $w29 ; CHECK: CFI_INSTRUCTION def_cfa_offset -8 frame-setup CFI_INSTRUCTION def_cfa_offset -8 + ; CHECK: CFI_INSTRUCTION llvm_def_aspace_cfa $w29, 16, 6 + frame-setup CFI_INSTRUCTION llvm_def_aspace_cfa $w29, 16, 6 ; CHECK: CFI_INSTRUCTION offset $w30, -8 frame-setup CFI_INSTRUCTION offset $w30, -8 ; CHECK: CFI_INSTRUCTION rel_offset $w30, -8 diff --git a/llvm/test/MC/ELF/cfi-llvm-def-aspace-cfa-errors.s b/llvm/test/MC/ELF/cfi-llvm-def-aspace-cfa-errors.s new file mode 100644 --- /dev/null +++ b/llvm/test/MC/ELF/cfi-llvm-def-aspace-cfa-errors.s @@ -0,0 +1,25 @@ +// RUN: not llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu %s -o /dev/null 2>&1 | FileCheck %s + +// Check that we diagnose malformed .cfi_llvm_def_aspace_cfa directives. + +.cfi_startproc + +// CHECK: [[#@LINE+1]]:{{[0-9]+}}: error: invalid register name +.cfi_llvm_def_aspace_cfa foo + +// CHECK: [[#@LINE+1]]:{{[0-9]+}}: error: unexpected token in directive +.cfi_llvm_def_aspace_cfa %rcx . + +// CHECK: [[#@LINE+1]]:{{[0-9]+}}: error: expected absolute expression +.cfi_llvm_def_aspace_cfa %rcx, .+1 + +// CHECK: [[#@LINE+1]]:{{[0-9]+}}: error: unexpected token in directive +.cfi_llvm_def_aspace_cfa %rcx, 1 . + +// CHECK: [[#@LINE+1]]:{{[0-9]+}}: error: expected absolute expression +.cfi_llvm_def_aspace_cfa %rcx, 1, .+1 + +// CHECK: [[#@LINE+1]]:{{[0-9]+}}: error: unexpected token at start of statement +.cfi_llvm_def_aspace_cfa %rcx, 1, 1, + +.cfi_endproc diff --git a/llvm/test/MC/ELF/cfi-llvm-def-aspace-cfa.s b/llvm/test/MC/ELF/cfi-llvm-def-aspace-cfa.s new file mode 100644 --- /dev/null +++ b/llvm/test/MC/ELF/cfi-llvm-def-aspace-cfa.s @@ -0,0 +1,32 @@ +# RUN: llvm-mc -filetype=asm -triple x86_64-pc-linux-gnu %s -o - | FileCheck --check-prefix=ASM %s +# RUN: llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu %s -o %t +# RUN: llvm-readelf -S -r -x .eh_frame %t | FileCheck --check-prefix=READELF %s + +f: + .cfi_startproc + nop + .cfi_llvm_def_aspace_cfa %rcx, 0, 6 + nop + .cfi_endproc + +# ASM: f: +# ASM-NEXT: .cfi_startproc +# ASM-NEXT: nop +# ASM-NEXT: .cfi_llvm_def_aspace_cfa %rcx, 0, 6 +# FIXME Why emit an extra empty line? +# ASM-EMPTY: +# ASM-NEXT: nop +# ASM-NEXT: .cfi_endproc + +# READELF: Section Headers: +# READELF: Name Type Address Off Size ES Flg Lk Inf Al +# READELF: .eh_frame X86_64_UNWIND 0000000000000000 000048 000030 00 A 0 0 8 + +# READELF: Relocation section '.rela.eh_frame' at offset 0xc0 contains 1 entries: +# READELF-NEXT: Offset Info Type Symbol's Value Symbol's Name + Addend +# READELF-NEXT: 0000000000000020 0000000200000002 R_X86_64_PC32 0000000000000000 .text + 0 + +# READELF: Hex dump of section '.eh_frame': +# READELF-NEXT: 0x00000000 14000000 00000000 017a5200 01781001 +# READELF-NEXT: 0x00000010 1b0c0708 90010000 14000000 1c000000 +# READELF-NEXT: 0x00000020 00000000 02000000 00413002 00060000 diff --git a/llvm/test/tools/llvm-dwarfdump/X86/debug_frame_LLVM_def_aspace_cfa.s b/llvm/test/tools/llvm-dwarfdump/X86/debug_frame_LLVM_def_aspace_cfa.s new file mode 100644 --- /dev/null +++ b/llvm/test/tools/llvm-dwarfdump/X86/debug_frame_LLVM_def_aspace_cfa.s @@ -0,0 +1,16 @@ +# RUN: llvm-mc %s -filetype=obj -triple=i686-pc-linux -o %t +# RUN: llvm-dwarfdump -v %t | FileCheck %s + +# CHECK: .eh_frame contents: +# CHECK: FDE +# CHECK-NEXT: Format: +# CHECK-NEXT: DW_CFA_LLVM_def_aspace_cfa: EDX +0 as6 +# CHECK-NEXT: DW_CFA_nop: + +.text +.globl foo +.type foo,@function +foo: + .cfi_startproc + .cfi_llvm_def_aspace_cfa %edx, 0, 6 + .cfi_endproc diff --git a/llvm/unittests/DebugInfo/DWARF/DWARFDebugFrameTest.cpp b/llvm/unittests/DebugInfo/DWARF/DWARFDebugFrameTest.cpp --- a/llvm/unittests/DebugInfo/DWARF/DWARFDebugFrameTest.cpp +++ b/llvm/unittests/DebugInfo/DWARF/DWARFDebugFrameTest.cpp @@ -155,6 +155,8 @@ dwarf::DW_CFA_offset_extended_sf, dwarf::DW_CFA_def_cfa_sf, dwarf::DW_CFA_def_cfa_offset_sf, + dwarf::DW_CFA_LLVM_def_aspace_cfa, + dwarf::DW_CFA_LLVM_def_aspace_cfa_sf, dwarf::DW_CFA_val_offset, dwarf::DW_CFA_val_offset_sf, dwarf::DW_CFA_val_expression,