Skip to content

Commit 86f76c3

Browse files
authored
[AArch64][Libunwind] Add Support for FEAT_PAuthLR DWARF Instruction (#112171)
As part of FEAT_PAuthLR, a new DWARF Frame Instruction was introduced, `DW_CFA_AARCH64_negate_ra_state_with_pc`. This instructs Libunwind that the PC has been used with the signing instruction. This change includes three commits - Libunwind support for the newly introduced DWARF Instruction - CodeGen Support for the DWARF Instructions - Reversing the changes made in #96377. Due to `DW_CFA_AARCH64_negate_ra_state_with_pc`'s requirements to be placed immediately after the signing instruction, this would mean the CFI Instruction location was not consistent with the generated location when not using FEAT_PAuthLR. The commit reverses the changes and makes the location consistent across the different branch protection options. While this does have a code size effect, this is a negligible one. For the ABI information, see here: https://github.com/ARM-software/abi-aa/blob/853286c7ab66048e4b819682ce17f567b77a0291/aadwarf64/aadwarf64.rst#id23
1 parent a4fd3db commit 86f76c3

34 files changed

+733
-241
lines changed

libunwind/src/DwarfInstructions.hpp

Lines changed: 47 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,10 @@ class DwarfInstructions {
7474
__builtin_unreachable();
7575
}
7676
#if defined(_LIBUNWIND_TARGET_AARCH64)
77-
static bool getRA_SIGN_STATE(A &addressSpace, R registers, pint_t cfa,
78-
PrologInfo &prolog);
77+
static bool isReturnAddressSigned(A &addressSpace, R registers, pint_t cfa,
78+
PrologInfo &prolog);
79+
static bool isReturnAddressSignedWithPC(A &addressSpace, R registers,
80+
pint_t cfa, PrologInfo &prolog);
7981
#endif
8082
};
8183

@@ -173,8 +175,9 @@ v128 DwarfInstructions<A, R>::getSavedVectorRegister(
173175
}
174176
#if defined(_LIBUNWIND_TARGET_AARCH64)
175177
template <typename A, typename R>
176-
bool DwarfInstructions<A, R>::getRA_SIGN_STATE(A &addressSpace, R registers,
177-
pint_t cfa, PrologInfo &prolog) {
178+
bool DwarfInstructions<A, R>::isReturnAddressSigned(A &addressSpace,
179+
R registers, pint_t cfa,
180+
PrologInfo &prolog) {
178181
pint_t raSignState;
179182
auto regloc = prolog.savedRegisters[UNW_AARCH64_RA_SIGN_STATE];
180183
if (regloc.location == CFI_Parser<A>::kRegisterUnused)
@@ -185,6 +188,22 @@ bool DwarfInstructions<A, R>::getRA_SIGN_STATE(A &addressSpace, R registers,
185188
// Only bit[0] is meaningful.
186189
return raSignState & 0x01;
187190
}
191+
192+
template <typename A, typename R>
193+
bool DwarfInstructions<A, R>::isReturnAddressSignedWithPC(A &addressSpace,
194+
R registers,
195+
pint_t cfa,
196+
PrologInfo &prolog) {
197+
pint_t raSignState;
198+
auto regloc = prolog.savedRegisters[UNW_AARCH64_RA_SIGN_STATE];
199+
if (regloc.location == CFI_Parser<A>::kRegisterUnused)
200+
raSignState = static_cast<pint_t>(regloc.value);
201+
else
202+
raSignState = getSavedRegister(addressSpace, registers, cfa, regloc);
203+
204+
// Only bit[1] is meaningful.
205+
return raSignState & 0x02;
206+
}
188207
#endif
189208

190209
template <typename A, typename R>
@@ -288,21 +307,37 @@ int DwarfInstructions<A, R>::stepWithDwarf(A &addressSpace, pint_t pc,
288307
// restored. autia1716 is used instead of autia as autia1716 assembles
289308
// to a NOP on pre-v8.3a architectures.
290309
if ((R::getArch() == REGISTERS_ARM64) &&
291-
getRA_SIGN_STATE(addressSpace, registers, cfa, prolog) &&
310+
isReturnAddressSigned(addressSpace, registers, cfa, prolog) &&
292311
returnAddress != 0) {
293312
#if !defined(_LIBUNWIND_IS_NATIVE_ONLY)
294313
return UNW_ECROSSRASIGNING;
295314
#else
296315
register unsigned long long x17 __asm("x17") = returnAddress;
297316
register unsigned long long x16 __asm("x16") = cfa;
298317

299-
// These are the autia1716/autib1716 instructions. The hint instructions
300-
// are used here as gcc does not assemble autia1716/autib1716 for pre
301-
// armv8.3a targets.
302-
if (cieInfo.addressesSignedWithBKey)
303-
asm("hint 0xe" : "+r"(x17) : "r"(x16)); // autib1716
304-
else
305-
asm("hint 0xc" : "+r"(x17) : "r"(x16)); // autia1716
318+
// We use the hint versions of the authentication instructions below to
319+
// ensure they're assembled by the compiler even for targets with no
320+
// FEAT_PAuth/FEAT_PAuth_LR support.
321+
if (isReturnAddressSignedWithPC(addressSpace, registers, cfa, prolog)) {
322+
register unsigned long long x15 __asm("x15") =
323+
prolog.ptrAuthDiversifier;
324+
if (cieInfo.addressesSignedWithBKey) {
325+
asm("hint 0x27\n\t" // pacm
326+
"hint 0xe"
327+
: "+r"(x17)
328+
: "r"(x16), "r"(x15)); // autib1716
329+
} else {
330+
asm("hint 0x27\n\t" // pacm
331+
"hint 0xc"
332+
: "+r"(x17)
333+
: "r"(x16), "r"(x15)); // autia1716
334+
}
335+
} else {
336+
if (cieInfo.addressesSignedWithBKey)
337+
asm("hint 0xe" : "+r"(x17) : "r"(x16)); // autib1716
338+
else
339+
asm("hint 0xc" : "+r"(x17) : "r"(x16)); // autia1716
340+
}
306341
returnAddress = x17;
307342
#endif
308343
}

libunwind/src/DwarfParser.hpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,9 @@ class CFI_Parser {
9191
int64_t cfaExpression; // CFA = expression
9292
uint32_t spExtraArgSize;
9393
RegisterLocation savedRegisters[kMaxRegisterNumber + 1];
94+
#if defined(_LIBUNWIND_TARGET_AARCH64)
95+
pint_t ptrAuthDiversifier;
96+
#endif
9497
enum class InitializeTime { kLazy, kNormal };
9598

9699
// When saving registers, this data structure is lazily initialized.
@@ -799,6 +802,24 @@ bool CFI_Parser<A>::parseFDEInstructions(A &addressSpace,
799802
}
800803
break;
801804

805+
#if defined(_LIBUNWIND_TARGET_AARCH64)
806+
case DW_CFA_AARCH64_negate_ra_state_with_pc: {
807+
int64_t value =
808+
results->savedRegisters[UNW_AARCH64_RA_SIGN_STATE].value ^ 0x3;
809+
results->setRegisterValue(UNW_AARCH64_RA_SIGN_STATE, value,
810+
initialState);
811+
// When calculating the value of the PC, it is assumed that the CFI
812+
// instruction is placed before the signing instruction, however it is
813+
// placed after. Because of this, we need to take into account the CFI
814+
// instruction is one instruction call later than expected, and reduce
815+
// the PC value by 4 bytes to compensate.
816+
results->ptrAuthDiversifier = fdeInfo.pcStart + codeOffset - 0x4;
817+
_LIBUNWIND_TRACE_DWARF(
818+
"DW_CFA_AARCH64_negate_ra_state_with_pc(pc=0x%" PRIx64 ")\n",
819+
static_cast<uint64_t>(results->ptrAuthDiversifier));
820+
} break;
821+
#endif
822+
802823
#else
803824
(void)arch;
804825
#endif

libunwind/src/dwarf2.h

Lines changed: 29 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -18,43 +18,43 @@
1818

1919
// DWARF unwind instructions
2020
enum {
21-
DW_CFA_nop = 0x0,
22-
DW_CFA_set_loc = 0x1,
23-
DW_CFA_advance_loc1 = 0x2,
24-
DW_CFA_advance_loc2 = 0x3,
25-
DW_CFA_advance_loc4 = 0x4,
26-
DW_CFA_offset_extended = 0x5,
27-
DW_CFA_restore_extended = 0x6,
28-
DW_CFA_undefined = 0x7,
29-
DW_CFA_same_value = 0x8,
30-
DW_CFA_register = 0x9,
31-
DW_CFA_remember_state = 0xA,
32-
DW_CFA_restore_state = 0xB,
33-
DW_CFA_def_cfa = 0xC,
34-
DW_CFA_def_cfa_register = 0xD,
35-
DW_CFA_def_cfa_offset = 0xE,
36-
DW_CFA_def_cfa_expression = 0xF,
37-
DW_CFA_expression = 0x10,
21+
DW_CFA_nop = 0x0,
22+
DW_CFA_set_loc = 0x1,
23+
DW_CFA_advance_loc1 = 0x2,
24+
DW_CFA_advance_loc2 = 0x3,
25+
DW_CFA_advance_loc4 = 0x4,
26+
DW_CFA_offset_extended = 0x5,
27+
DW_CFA_restore_extended = 0x6,
28+
DW_CFA_undefined = 0x7,
29+
DW_CFA_same_value = 0x8,
30+
DW_CFA_register = 0x9,
31+
DW_CFA_remember_state = 0xA,
32+
DW_CFA_restore_state = 0xB,
33+
DW_CFA_def_cfa = 0xC,
34+
DW_CFA_def_cfa_register = 0xD,
35+
DW_CFA_def_cfa_offset = 0xE,
36+
DW_CFA_def_cfa_expression = 0xF,
37+
DW_CFA_expression = 0x10,
3838
DW_CFA_offset_extended_sf = 0x11,
39-
DW_CFA_def_cfa_sf = 0x12,
40-
DW_CFA_def_cfa_offset_sf = 0x13,
41-
DW_CFA_val_offset = 0x14,
42-
DW_CFA_val_offset_sf = 0x15,
43-
DW_CFA_val_expression = 0x16,
44-
DW_CFA_advance_loc = 0x40, // high 2 bits are 0x1, lower 6 bits are delta
45-
DW_CFA_offset = 0x80, // high 2 bits are 0x2, lower 6 bits are register
46-
DW_CFA_restore = 0xC0, // high 2 bits are 0x3, lower 6 bits are register
39+
DW_CFA_def_cfa_sf = 0x12,
40+
DW_CFA_def_cfa_offset_sf = 0x13,
41+
DW_CFA_val_offset = 0x14,
42+
DW_CFA_val_offset_sf = 0x15,
43+
DW_CFA_val_expression = 0x16,
44+
DW_CFA_advance_loc = 0x40, // high 2 bits are 0x1, lower 6 bits are delta
45+
DW_CFA_offset = 0x80, // high 2 bits are 0x2, lower 6 bits are register
46+
DW_CFA_restore = 0xC0, // high 2 bits are 0x3, lower 6 bits are register
4747

4848
// GNU extensions
49-
DW_CFA_GNU_window_save = 0x2D,
50-
DW_CFA_GNU_args_size = 0x2E,
49+
DW_CFA_GNU_window_save = 0x2D,
50+
DW_CFA_GNU_args_size = 0x2E,
5151
DW_CFA_GNU_negative_offset_extended = 0x2F,
5252

5353
// AARCH64 extensions
54-
DW_CFA_AARCH64_negate_ra_state = 0x2D
54+
DW_CFA_AARCH64_negate_ra_state_with_pc = 0x2C,
55+
DW_CFA_AARCH64_negate_ra_state = 0x2D
5556
};
5657

57-
5858
// FSF exception handling Pointer-Encoding constants
5959
// Used in CFI augmentation by GCC
6060
enum {

llvm/include/llvm/BinaryFormat/Dwarf.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1238,6 +1238,7 @@ HANDLE_DW_CFA(0x16, val_expression)
12381238
// Vendor extensions:
12391239
HANDLE_DW_CFA_PRED(0x1d, MIPS_advance_loc8, SELECT_MIPS64)
12401240
HANDLE_DW_CFA_PRED(0x2d, GNU_window_save, SELECT_SPARC)
1241+
HANDLE_DW_CFA_PRED(0x2c, AARCH64_negate_ra_state_with_pc, SELECT_AARCH64)
12411242
HANDLE_DW_CFA_PRED(0x2d, AARCH64_negate_ra_state, SELECT_AARCH64)
12421243
HANDLE_DW_CFA_PRED(0x2e, GNU_args_size, SELECT_X86)
12431244
// Heterogeneous Debugging Extension defined at

llvm/include/llvm/MC/MCDwarf.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -515,6 +515,7 @@ class MCCFIInstruction {
515515
OpRegister,
516516
OpWindowSave,
517517
OpNegateRAState,
518+
OpNegateRAStateWithPC,
518519
OpGnuArgsSize,
519520
OpLabel,
520521
};
@@ -642,6 +643,12 @@ class MCCFIInstruction {
642643
return MCCFIInstruction(OpNegateRAState, L, 0, INT64_C(0), Loc);
643644
}
644645

646+
/// .cfi_negate_ra_state_with_pc AArch64 negate RA state with PC.
647+
static MCCFIInstruction createNegateRAStateWithPC(MCSymbol *L,
648+
SMLoc Loc = {}) {
649+
return MCCFIInstruction(OpNegateRAStateWithPC, L, 0, INT64_C(0), Loc);
650+
}
651+
645652
/// .cfi_restore says that the rule for Register is now the same as it
646653
/// was at the beginning of the function, after all initial instructions added
647654
/// by .cfi_startproc were executed.

llvm/include/llvm/MC/MCStreamer.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1022,6 +1022,7 @@ class MCStreamer {
10221022
SMLoc Loc = {});
10231023
virtual void emitCFIWindowSave(SMLoc Loc = {});
10241024
virtual void emitCFINegateRAState(SMLoc Loc = {});
1025+
virtual void emitCFINegateRAStateWithPC(SMLoc Loc = {});
10251026
virtual void emitCFILabelDirective(SMLoc Loc, StringRef Name);
10261027

10271028
virtual void emitWinCFIStartProc(const MCSymbol *Symbol, SMLoc Loc = SMLoc());

llvm/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,9 @@ void AsmPrinter::emitCFIInstruction(const MCCFIInstruction &Inst) const {
236236
case MCCFIInstruction::OpNegateRAState:
237237
OutStreamer->emitCFINegateRAState(Loc);
238238
break;
239+
case MCCFIInstruction::OpNegateRAStateWithPC:
240+
OutStreamer->emitCFINegateRAStateWithPC(Loc);
241+
break;
239242
case MCCFIInstruction::OpSameValue:
240243
OutStreamer->emitCFISameValue(Inst.getRegister(), Loc);
241244
break;

llvm/lib/CodeGen/CFIInstrInserter.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,7 @@ void CFIInstrInserter::calculateOutgoingCFAInfo(MBBCFAInfo &MBBInfo) {
260260
case MCCFIInstruction::OpEscape:
261261
case MCCFIInstruction::OpWindowSave:
262262
case MCCFIInstruction::OpNegateRAState:
263+
case MCCFIInstruction::OpNegateRAStateWithPC:
263264
case MCCFIInstruction::OpGnuArgsSize:
264265
case MCCFIInstruction::OpLabel:
265266
break;

llvm/lib/CodeGen/MIRParser/MILexer.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,8 @@ static MIToken::TokenKind getIdentifierKind(StringRef Identifier) {
238238
.Case("window_save", MIToken::kw_cfi_window_save)
239239
.Case("negate_ra_sign_state",
240240
MIToken::kw_cfi_aarch64_negate_ra_sign_state)
241+
.Case("negate_ra_sign_state_with_pc",
242+
MIToken::kw_cfi_aarch64_negate_ra_sign_state_with_pc)
241243
.Case("blockaddress", MIToken::kw_blockaddress)
242244
.Case("intrinsic", MIToken::kw_intrinsic)
243245
.Case("target-index", MIToken::kw_target_index)

llvm/lib/CodeGen/MIRParser/MILexer.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ struct MIToken {
9696
kw_cfi_undefined,
9797
kw_cfi_window_save,
9898
kw_cfi_aarch64_negate_ra_sign_state,
99+
kw_cfi_aarch64_negate_ra_sign_state_with_pc,
99100
kw_blockaddress,
100101
kw_intrinsic,
101102
kw_target_index,

llvm/lib/CodeGen/MIRParser/MIParser.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2576,6 +2576,10 @@ bool MIParser::parseCFIOperand(MachineOperand &Dest) {
25762576
case MIToken::kw_cfi_aarch64_negate_ra_sign_state:
25772577
CFIIndex = MF.addFrameInst(MCCFIInstruction::createNegateRAState(nullptr));
25782578
break;
2579+
case MIToken::kw_cfi_aarch64_negate_ra_sign_state_with_pc:
2580+
CFIIndex =
2581+
MF.addFrameInst(MCCFIInstruction::createNegateRAStateWithPC(nullptr));
2582+
break;
25792583
case MIToken::kw_cfi_escape: {
25802584
std::string Values;
25812585
if (parseCFIEscapeValues(Values))
@@ -2931,6 +2935,7 @@ bool MIParser::parseMachineOperand(const unsigned OpCode, const unsigned OpIdx,
29312935
case MIToken::kw_cfi_undefined:
29322936
case MIToken::kw_cfi_window_save:
29332937
case MIToken::kw_cfi_aarch64_negate_ra_sign_state:
2938+
case MIToken::kw_cfi_aarch64_negate_ra_sign_state_with_pc:
29342939
return parseCFIOperand(Dest);
29352940
case MIToken::kw_blockaddress:
29362941
return parseBlockAddressOperand(Dest);

llvm/lib/CodeGen/MachineOperand.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -768,6 +768,10 @@ static void printCFI(raw_ostream &OS, const MCCFIInstruction &CFI,
768768
if (MCSymbol *Label = CFI.getLabel())
769769
MachineOperand::printSymbol(OS, *Label);
770770
break;
771+
case MCCFIInstruction::OpNegateRAStateWithPC:
772+
OS << "negate_ra_sign_state_with_pc ";
773+
if (MCSymbol *Label = CFI.getLabel())
774+
MachineOperand::printSymbol(OS, *Label);
771775
default:
772776
// TODO: Print the other CFI Operations.
773777
OS << "<unserializable cfi directive>";

llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,7 @@ Error CFIProgram::parse(DWARFDataExtractor Data, uint64_t *Offset,
288288
case DW_CFA_remember_state:
289289
case DW_CFA_restore_state:
290290
case DW_CFA_GNU_window_save:
291+
case DW_CFA_AARCH64_negate_ra_state_with_pc:
291292
// No operands
292293
addInstruction(Opcode);
293294
break;
@@ -666,6 +667,28 @@ Error UnwindTable::parseRows(const CFIProgram &CFIP, UnwindRow &Row,
666667
}
667668
break;
668669

670+
case dwarf::DW_CFA_AARCH64_negate_ra_state_with_pc: {
671+
constexpr uint32_t AArch64DWARFPAuthRaState = 34;
672+
auto LRLoc = Row.getRegisterLocations().getRegisterLocation(
673+
AArch64DWARFPAuthRaState);
674+
if (LRLoc) {
675+
if (LRLoc->getLocation() == UnwindLocation::Constant) {
676+
// Toggle the constant value of bits[1:0] from 0 to 1 or 1 to 0.
677+
LRLoc->setConstant(LRLoc->getConstant() ^ 0x3);
678+
} else {
679+
return createStringError(
680+
errc::invalid_argument,
681+
"%s encountered when existing rule for this register is not "
682+
"a constant",
683+
CFIP.callFrameString(Inst.Opcode).str().c_str());
684+
}
685+
} else {
686+
Row.getRegisterLocations().setRegisterLocation(
687+
AArch64DWARFPAuthRaState, UnwindLocation::createIsConstant(0x3));
688+
}
689+
break;
690+
}
691+
669692
case dwarf::DW_CFA_undefined: {
670693
llvm::Expected<uint64_t> RegNum = Inst.getOperandAsUnsigned(CFIP, 0);
671694
if (!RegNum)
@@ -847,6 +870,7 @@ CFIProgram::getOperandTypes() {
847870
DECLARE_OP0(DW_CFA_remember_state);
848871
DECLARE_OP0(DW_CFA_restore_state);
849872
DECLARE_OP0(DW_CFA_GNU_window_save);
873+
DECLARE_OP0(DW_CFA_AARCH64_negate_ra_state_with_pc);
850874
DECLARE_OP1(DW_CFA_GNU_args_size, OT_Offset);
851875
DECLARE_OP0(DW_CFA_nop);
852876

llvm/lib/MC/MCAsmStreamer.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -373,6 +373,7 @@ class MCAsmStreamer final : public MCStreamer {
373373
SMLoc Loc) override;
374374
void emitCFIWindowSave(SMLoc Loc) override;
375375
void emitCFINegateRAState(SMLoc Loc) override;
376+
void emitCFINegateRAStateWithPC(SMLoc Loc) override;
376377
void emitCFIReturnColumn(int64_t Register) override;
377378
void emitCFILabelDirective(SMLoc Loc, StringRef Name) override;
378379

@@ -2145,6 +2146,12 @@ void MCAsmStreamer::emitCFINegateRAState(SMLoc Loc) {
21452146
EmitEOL();
21462147
}
21472148

2149+
void MCAsmStreamer::emitCFINegateRAStateWithPC(SMLoc Loc) {
2150+
MCStreamer::emitCFINegateRAStateWithPC(Loc);
2151+
OS << "\t.cfi_negate_ra_state_with_pc";
2152+
EmitEOL();
2153+
}
2154+
21482155
void MCAsmStreamer::emitCFIReturnColumn(int64_t Register) {
21492156
MCStreamer::emitCFIReturnColumn(Register);
21502157
OS << "\t.cfi_return_column ";

llvm/lib/MC/MCDwarf.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1381,6 +1381,10 @@ void FrameEmitterImpl::emitCFIInstruction(const MCCFIInstruction &Instr) {
13811381
Streamer.emitInt8(dwarf::DW_CFA_AARCH64_negate_ra_state);
13821382
return;
13831383

1384+
case MCCFIInstruction::OpNegateRAStateWithPC:
1385+
Streamer.emitInt8(dwarf::DW_CFA_AARCH64_negate_ra_state_with_pc);
1386+
return;
1387+
13841388
case MCCFIInstruction::OpUndefined: {
13851389
unsigned Reg = Instr.getRegister();
13861390
Streamer.emitInt8(dwarf::DW_CFA_undefined);

llvm/lib/MC/MCStreamer.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -688,6 +688,16 @@ void MCStreamer::emitCFINegateRAState(SMLoc Loc) {
688688
CurFrame->Instructions.push_back(Instruction);
689689
}
690690

691+
void MCStreamer::emitCFINegateRAStateWithPC(SMLoc Loc) {
692+
MCSymbol *Label = emitCFILabel();
693+
MCCFIInstruction Instruction =
694+
MCCFIInstruction::createNegateRAStateWithPC(Label, Loc);
695+
MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
696+
if (!CurFrame)
697+
return;
698+
CurFrame->Instructions.push_back(Instruction);
699+
}
700+
691701
void MCStreamer::emitCFIReturnColumn(int64_t Register) {
692702
MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
693703
if (!CurFrame)

0 commit comments

Comments
 (0)