Index: include/llvm/BinaryFormat/Dwarf.h =================================================================== --- include/llvm/BinaryFormat/Dwarf.h +++ include/llvm/BinaryFormat/Dwarf.h @@ -273,6 +273,7 @@ /// Call frame instruction encodings. enum CallFrameInfo { #define HANDLE_DW_CFA(ID, NAME) DW_CFA_##NAME = ID, +#define HANDLE_DW_CFA_DUP(ID, NAME) DW_CFA_##NAME = ID, #include "llvm/BinaryFormat/Dwarf.def" DW_CFA_extended = 0x00, Index: include/llvm/BinaryFormat/Dwarf.def =================================================================== --- include/llvm/BinaryFormat/Dwarf.def +++ include/llvm/BinaryFormat/Dwarf.def @@ -18,7 +18,8 @@ defined HANDLE_DW_VIRTUALITY || defined HANDLE_DW_DEFAULTED || \ defined HANDLE_DW_CC || defined HANDLE_DW_LNS || defined HANDLE_DW_LNE || \ defined HANDLE_DW_LNCT || defined HANDLE_DW_MACRO || \ - defined HANDLE_DW_RLE || defined HANDLE_DW_CFA || \ + defined HANDLE_DW_RLE || \ + (defined HANDLE_DW_CFA && defined HANDLE_DW_CFA_DUP) || \ defined HANDLE_DW_APPLE_PROPERTY || defined HANDLE_DW_UT || \ defined HANDLE_DWARF_SECTION || defined HANDLE_DW_IDX) #error "Missing macro definition of HANDLE_DW*" @@ -84,6 +85,10 @@ #define HANDLE_DW_CFA(ID, NAME) #endif +#ifndef HANDLE_DW_CFA_DUP +#define HANDLE_DW_CFA_DUP(ID, NAME) +#endif + #ifndef HANDLE_DW_APPLE_PROPERTY #define HANDLE_DW_APPLE_PROPERTY(ID, NAME) #endif @@ -823,6 +828,7 @@ // Vendor extensions: HANDLE_DW_CFA(0x1d, MIPS_advance_loc8) HANDLE_DW_CFA(0x2d, GNU_window_save) +HANDLE_DW_CFA_DUP(0x2d, AARCH64_negate_ra_state) HANDLE_DW_CFA(0x2e, GNU_args_size) // Apple Objective-C Property Attributes. @@ -905,6 +911,7 @@ #undef HANDLE_DW_MACRO #undef HANDLE_DW_RLE #undef HANDLE_DW_CFA +#undef HANDLE_DW_CFA_DUP #undef HANDLE_DW_APPLE_PROPERTY #undef HANDLE_DW_UT #undef HANDLE_DWARF_SECTION Index: include/llvm/MC/MCDwarf.h =================================================================== --- include/llvm/MC/MCDwarf.h +++ include/llvm/MC/MCDwarf.h @@ -430,6 +430,7 @@ OpUndefined, OpRegister, OpWindowSave, + OpNegateRAState, OpGnuArgsSize }; @@ -509,6 +510,11 @@ return MCCFIInstruction(OpWindowSave, L, 0, 0, ""); } + /// .cfi_negate_ra_state AArch64 negate RA state. + static MCCFIInstruction createNegateRAState(MCSymbol *L) { + return MCCFIInstruction(OpNegateRAState, L, 0, 0, ""); + } + /// .cfi_restore says that the rule for Register is now the same as it /// was at the beginning of the function, after all initial instructions added /// by .cfi_startproc were executed. Index: include/llvm/MC/MCStreamer.h =================================================================== --- include/llvm/MC/MCStreamer.h +++ include/llvm/MC/MCStreamer.h @@ -888,6 +888,7 @@ virtual void EmitCFIUndefined(int64_t Register); virtual void EmitCFIRegister(int64_t Register1, int64_t Register2); virtual void EmitCFIWindowSave(); + virtual void EmitCFINegateRAState(); virtual void EmitWinCFIStartProc(const MCSymbol *Symbol, SMLoc Loc = SMLoc()); virtual void EmitWinCFIEndProc(SMLoc Loc = SMLoc()); Index: lib/BinaryFormat/Dwarf.cpp =================================================================== --- lib/BinaryFormat/Dwarf.cpp +++ lib/BinaryFormat/Dwarf.cpp @@ -462,6 +462,7 @@ #define HANDLE_DW_CFA(ID, NAME) \ case DW_CFA_##NAME: \ return "DW_CFA_" #NAME; +#define HANDLE_DW_CFA_DUP(ID, NAME) #include "llvm/BinaryFormat/Dwarf.def" } } Index: lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp =================================================================== --- lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp +++ lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp @@ -212,6 +212,9 @@ case MCCFIInstruction::OpWindowSave: OutStreamer->EmitCFIWindowSave(); break; + case MCCFIInstruction::OpNegateRAState: + OutStreamer->EmitCFINegateRAState(); + break; case MCCFIInstruction::OpSameValue: OutStreamer->EmitCFISameValue(Inst.getRegister()); break; Index: lib/CodeGen/CFIInstrInserter.cpp =================================================================== --- lib/CodeGen/CFIInstrInserter.cpp +++ lib/CodeGen/CFIInstrInserter.cpp @@ -207,6 +207,7 @@ case MCCFIInstruction::OpUndefined: case MCCFIInstruction::OpRegister: case MCCFIInstruction::OpWindowSave: + case MCCFIInstruction::OpNegateRAState: case MCCFIInstruction::OpGnuArgsSize: break; } Index: lib/MC/MCAsmStreamer.cpp =================================================================== --- lib/MC/MCAsmStreamer.cpp +++ lib/MC/MCAsmStreamer.cpp @@ -285,6 +285,7 @@ void EmitCFIUndefined(int64_t Register) override; void EmitCFIRegister(int64_t Register1, int64_t Register2) override; void EmitCFIWindowSave() override; + void EmitCFINegateRAState() override; void EmitCFIReturnColumn(int64_t Register) override; void EmitWinCFIStartProc(const MCSymbol *Symbol, SMLoc Loc) override; @@ -1569,6 +1570,12 @@ EmitEOL(); } +void MCAsmStreamer::EmitCFINegateRAState() { + MCStreamer::EmitCFINegateRAState(); + OS << "\t.cfi_negate_ra_state"; + EmitEOL(); +} + void MCAsmStreamer::EmitCFIReturnColumn(int64_t Register) { MCStreamer::EmitCFIReturnColumn(Register); OS << "\t.cfi_return_column " << Register; Index: lib/MC/MCDwarf.cpp =================================================================== --- lib/MC/MCDwarf.cpp +++ lib/MC/MCDwarf.cpp @@ -1335,6 +1335,10 @@ Streamer.EmitIntValue(dwarf::DW_CFA_GNU_window_save, 1); return; + case MCCFIInstruction::OpNegateRAState: + Streamer.EmitIntValue(dwarf::DW_CFA_AARCH64_negate_ra_state, 1); + return; + case MCCFIInstruction::OpUndefined: { unsigned Reg = Instr.getRegister(); Streamer.EmitIntValue(dwarf::DW_CFA_undefined, 1); Index: lib/MC/MCParser/AsmParser.cpp =================================================================== --- lib/MC/MCParser/AsmParser.cpp +++ lib/MC/MCParser/AsmParser.cpp @@ -491,6 +491,7 @@ DK_CFI_UNDEFINED, DK_CFI_REGISTER, DK_CFI_WINDOW_SAVE, + DK_CFI_NEGATE_RA_STATE, DK_MACROS_ON, DK_MACROS_OFF, DK_ALTMACRO, @@ -554,6 +555,7 @@ // .cfi directives bool parseDirectiveCFIRegister(SMLoc DirectiveLoc); bool parseDirectiveCFIWindowSave(); + bool parseDirectiveCFINegateRAState(); bool parseDirectiveCFISections(); bool parseDirectiveCFIStartProc(); bool parseDirectiveCFIEndProc(); @@ -2078,6 +2080,8 @@ return parseDirectiveCFIRegister(IDLoc); case DK_CFI_WINDOW_SAVE: return parseDirectiveCFIWindowSave(); + case DK_CFI_NEGATE_RA_STATE: + return parseDirectiveCFINegateRAState(); case DK_MACROS_ON: case DK_MACROS_OFF: return parseDirectiveMacrosOnOff(IDVal); @@ -3964,6 +3968,13 @@ return false; } +/// parseDirectiveCFINegateRAState +/// ::= .cfi_negate_ra_state +bool AsmParser::parseDirectiveCFINegateRAState() { + getStreamer().EmitCFINegateRAState(); + return false; +} + /// parseDirectiveCFIAdjustCfaOffset /// ::= .cfi_adjust_cfa_offset adjustment bool AsmParser::parseDirectiveCFIAdjustCfaOffset() { @@ -5264,6 +5275,7 @@ DirectiveKindMap[".cfi_undefined"] = DK_CFI_UNDEFINED; DirectiveKindMap[".cfi_register"] = DK_CFI_REGISTER; DirectiveKindMap[".cfi_window_save"] = DK_CFI_WINDOW_SAVE; + DirectiveKindMap[".cfi_negate_ra_state"] = DK_CFI_NEGATE_RA_STATE; DirectiveKindMap[".macros_on"] = DK_MACROS_ON; DirectiveKindMap[".macros_off"] = DK_MACROS_OFF; DirectiveKindMap[".macro"] = DK_MACRO; Index: lib/MC/MCStreamer.cpp =================================================================== --- lib/MC/MCStreamer.cpp +++ lib/MC/MCStreamer.cpp @@ -559,6 +559,15 @@ CurFrame->Instructions.push_back(Instruction); } +void MCStreamer::EmitCFINegateRAState() { + MCSymbol *Label = EmitCFILabel(); + MCCFIInstruction Instruction = MCCFIInstruction::createNegateRAState(Label); + MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo(); + if (!CurFrame) + return; + CurFrame->Instructions.push_back(Instruction); +} + void MCStreamer::EmitCFIReturnColumn(int64_t Register) { MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo(); if (!CurFrame) Index: lib/Target/AArch64/AArch64FrameLowering.cpp =================================================================== --- lib/Target/AArch64/AArch64FrameLowering.cpp +++ lib/Target/AArch64/AArch64FrameLowering.cpp @@ -597,6 +597,12 @@ if (ShouldSignReturnAddress(MF)) { BuildMI(MBB, MBBI, DL, TII->get(AArch64::PACIASP)) .setMIFlag(MachineInstr::FrameSetup); + + unsigned CFIIndex = + MF.addFrameInst(MCCFIInstruction::createNegateRAState(nullptr)); + BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION)) + .addCFIIndex(CFIIndex) + .setMIFlags(MachineInstr::FrameSetup); } // All calls are tail calls in GHC calling conv, and functions have no @@ -884,10 +890,23 @@ if (Subtarget.hasV8_3aOps() && MBBI != MBB.end() && MBBI->getOpcode() == AArch64::RET_ReallyLR) { BuildMI(MBB, MBBI, DL, TII->get(AArch64::RETAA)).copyImplicitOps(*MBBI); + + unsigned CFIIndex = + MF.addFrameInst(MCCFIInstruction::createNegateRAState(nullptr)); + BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION)) + .addCFIIndex(CFIIndex) + .setMIFlags(MachineInstr::FrameSetup); + MBB.erase(MBBI); } else { BuildMI(MBB, MBBI, DL, TII->get(AArch64::AUTIASP)) .setMIFlag(MachineInstr::FrameDestroy); + + unsigned CFIIndex = + MF.addFrameInst(MCCFIInstruction::createNegateRAState(nullptr)); + BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION)) + .addCFIIndex(CFIIndex) + .setMIFlags(MachineInstr::FrameSetup); } } Index: test/CodeGen/AArch64/sign-return-address-cfi-negate-ra-state.ll =================================================================== --- /dev/null +++ test/CodeGen/AArch64/sign-return-address-cfi-negate-ra-state.ll @@ -0,0 +1,29 @@ +; RUN: llc -mtriple=aarch64-none-eabi < %s | FileCheck %s + +@.str = private unnamed_addr constant [15 x i8] c"some exception\00", align 1 +@_ZTIPKc = external dso_local constant i8* + +; CHECK: @_Z3fooi +; CHECK: paciasp +; CHECK-NEXT: .cfi_negate_ra_state +define dso_local i32 @_Z3fooi(i32 %x) #0 { +entry: + %retval = alloca i32, align 4 + %x.addr = alloca i32, align 4 + store i32 %x, i32* %x.addr, align 4 + %exception = call i8* @__cxa_allocate_exception(i64 8) #1 + %0 = bitcast i8* %exception to i8** + store i8* getelementptr inbounds ([15 x i8], [15 x i8]* @.str, i32 0, i32 0), i8** %0, align 16 + call void @__cxa_throw(i8* %exception, i8* bitcast (i8** @_ZTIPKc to i8*), i8* null) #2 + unreachable + +return: ; No predecessors! + %1 = load i32, i32* %retval, align 4 + ret i32 %1 +} + +declare dso_local i8* @__cxa_allocate_exception(i64) + +declare dso_local void @__cxa_throw(i8*, i8*, i8*) + +attributes #0 = { "sign-return-address"="all" } Index: test/CodeGen/AArch64/sign-return-address.ll =================================================================== --- test/CodeGen/AArch64/sign-return-address.ll +++ test/CodeGen/AArch64/sign-return-address.ll @@ -24,17 +24,17 @@ ; CHECK-LABEL: @leaf_sign_all ; CHECK: paciasp ; CHECK: autiasp -; CHECK-NEXT: ret +; CHECK: ret define i32 @leaf_sign_all(i32 %x) "sign-return-address"="all" { ret i32 %x } ; CHECK: @leaf_clobbers_lr ; CHECK: paciasp -; CHECK-NEXT: str x30, [sp, #-16]! +; CHECK: str x30, [sp, #-16]! ; CHECK: ldr x30, [sp], #16 ; CHECK-NEXT: autiasp -; CHECK-NEXT: ret +; CHECK: ret define i64 @leaf_clobbers_lr(i64 %x) "sign-return-address"="non-leaf" { call void asm sideeffect "mov x30, $0", "r,~{lr}"(i64 %x) #1 ret i64 %x @@ -45,7 +45,7 @@ ; CHECK: @non_leaf_sign_all ; CHECK: paciasp ; CHECK: autiasp -; CHECK-NEXT: ret +; CHECK: ret define i32 @non_leaf_sign_all(i32 %x) "sign-return-address"="all" { %call = call i32 @foo(i32 %x) ret i32 %call @@ -53,10 +53,10 @@ ; CHECK: @non_leaf_sign_non_leaf ; CHECK: paciasp -; CHECK-NEXT: str x30, [sp, #-16]! +; CHECK: str x30, [sp, #-16]! ; CHECK: ldr x30, [sp], #16 -; CHECK-NEXT: autiasp -; CHECK-NEXT: ret +; CHECK: autiasp +; CHECK: ret define i32 @non_leaf_sign_non_leaf(i32 %x) "sign-return-address"="non-leaf" { %call = call i32 @foo(i32 %x) ret i32 %call @@ -65,7 +65,7 @@ ; CHECK-LABEL: @leaf_sign_all_v83 ; CHECK: paciasp ; CHECK-NOT: ret -; CHECK-NEXT: retaa +; CHECK: retaa ; CHECK-NOT: ret define i32 @leaf_sign_all_v83(i32 %x) "sign-return-address"="all" "target-features"="+v8.3a" { ret i32 %x @@ -75,10 +75,10 @@ ; CHECK-LABEL: @spill_lr_and_tail_call ; CHECK: paciasp -; CHECK-NEXT: str x30, [sp, #-16]! +; CHECK: str x30, [sp, #-16]! ; CHECK: ldr x30, [sp], #16 -; CHECK-NEXT: autiasp -; CHECK-NEXT: b bar +; CHECK: autiasp +; CHECK: b bar define fastcc void @spill_lr_and_tail_call(i64 %x) "sign-return-address"="all" { call void asm sideeffect "mov x30, $0", "r,~{lr}"(i64 %x) #1 tail call fastcc i64 @bar(i64 %x)