diff --git a/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp b/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp index 6abf45591d78e..96b0ef0ec40aa 100644 --- a/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp @@ -2239,3 +2239,12 @@ void RISCVFrameLowering::inlineStackProbe(MachineFunction &MF, } } } + +int RISCVFrameLowering::getInitialCFAOffset(const MachineFunction &MF) const { + return 0; +} + +Register +RISCVFrameLowering::getInitialCFARegister(const MachineFunction &MF) const { + return RISCV::X2; +} diff --git a/llvm/lib/Target/RISCV/RISCVFrameLowering.h b/llvm/lib/Target/RISCV/RISCVFrameLowering.h index d013755ce58a0..faad93a513258 100644 --- a/llvm/lib/Target/RISCV/RISCVFrameLowering.h +++ b/llvm/lib/Target/RISCV/RISCVFrameLowering.h @@ -112,6 +112,8 @@ class RISCVFrameLowering : public TargetFrameLowering { const DebugLoc &DL, int64_t Amount, MachineInstr::MIFlag Flag, bool EmitCFI, bool DynAllocation) const; + int getInitialCFAOffset(const MachineFunction &MF) const override; + Register getInitialCFARegister(const MachineFunction &MF) const override; }; } // namespace llvm #endif diff --git a/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp b/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp index 167dbb53c5950..2be3981f2b815 100644 --- a/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp +++ b/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp @@ -117,6 +117,11 @@ static cl::opt cl::desc("Enable Machine Pipeliner for RISC-V"), cl::init(false), cl::Hidden); +static cl::opt EnableCFIInstrInserter( + "riscv-enable-cfi-instr-inserter", + cl::desc("Enable CFI Instruction Inserter for RISC-V"), cl::init(false), + cl::Hidden); + extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeRISCVTarget() { RegisterTargetMachine X(getTheRISCV32Target()); RegisterTargetMachine Y(getTheRISCV64Target()); @@ -187,7 +192,7 @@ RISCVTargetMachine::RISCVTargetMachine(const Target &T, const Triple &TT, if (TT.isOSFuchsia() && !TT.isArch64Bit()) report_fatal_error("Fuchsia is only supported for 64-bit"); - setCFIFixup(true); + setCFIFixup(!EnableCFIInstrInserter); } const RISCVSubtarget * @@ -584,6 +589,9 @@ void RISCVPassConfig::addPreEmitPass2() { addPass(createUnpackMachineBundles([&](const MachineFunction &MF) { return MF.getFunction().getParent()->getModuleFlag("kcfi"); })); + + if (EnableCFIInstrInserter) + addPass(createCFIInstrInserter()); } void RISCVPassConfig::addMachineSSAOptimization() { diff --git a/llvm/test/CodeGen/RISCV/cfi-escape.mir b/llvm/test/CodeGen/RISCV/cfi-escape.mir new file mode 100644 index 0000000000000..a15825caa9fb8 --- /dev/null +++ b/llvm/test/CodeGen/RISCV/cfi-escape.mir @@ -0,0 +1,88 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 5 +# RUN: llc %s -mtriple=riscv64 -mattr=+v \ +# RUN: -run-pass=prologepilog,cfi-instr-inserter \ +# RUN: -riscv-enable-cfi-instr-inserter=true \ +# RUN: | FileCheck %s +# +# In this test prolog will be inserted in bb.3. We need to save the scalable vector register v1. +# This will emit cfi_escape in bb.3. We need to emit the same cfi_escape in the begining of bb.2. +# Currently, CFIInstrInserter doesn't handle escape, so we have wrong cfi in this example. + +--- | + + define riscv_vector_cc void @test0(ptr %p0, ptr %p1) #0 { + entry: + %v = load <4 x i32>, ptr %p0, align 16 + store <4 x i32> %v, ptr %p1, align 16 + ret void + } + + attributes #0 = { "target-features"="+v" } + +... +--- +name: test0 +tracksRegLiveness: true +frameInfo: + savePoint: '%bb.3' + restorePoint: '%bb.2' +body: | + ; CHECK-LABEL: name: test0 + ; CHECK: bb.0.entry: + ; CHECK-NEXT: successors: %bb.3(0x40000000), %bb.1(0x40000000) + ; CHECK-NEXT: liveins: $x10, $x11, $v1 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: BEQ $x10, $x0, %bb.3 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: bb.1: + ; CHECK-NEXT: liveins: $v1 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: PseudoRET + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: bb.2: + ; CHECK-NEXT: successors: %bb.1(0x80000000) + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: CFI_INSTRUCTION def_cfa_offset 16 + ; CHECK-NEXT: $x10 = ADDI $x2, 16 + ; CHECK-NEXT: $v1 = frame-destroy VL1RE8_V killed $x10 :: (load unknown-size from %stack.0, align 8) + ; CHECK-NEXT: $x10 = frame-destroy PseudoReadVLENB + ; CHECK-NEXT: $x2 = frame-destroy ADD $x2, killed $x10 + ; CHECK-NEXT: frame-destroy CFI_INSTRUCTION def_cfa $x2, 16 + ; CHECK-NEXT: frame-destroy CFI_INSTRUCTION restore $v1 + ; CHECK-NEXT: $x2 = frame-destroy ADDI $x2, 16 + ; CHECK-NEXT: frame-destroy CFI_INSTRUCTION def_cfa_offset 0 + ; CHECK-NEXT: PseudoBR %bb.1 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: bb.3: + ; CHECK-NEXT: successors: %bb.2(0x80000000) + ; CHECK-NEXT: liveins: $x10, $x11, $v1 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: $x2 = frame-setup ADDI $x2, -16 + ; CHECK-NEXT: frame-setup CFI_INSTRUCTION def_cfa_offset 16 + ; CHECK-NEXT: $x12 = frame-setup PseudoReadVLENB + ; CHECK-NEXT: $x2 = frame-setup SUB $x2, killed $x12 + ; CHECK-NEXT: frame-setup CFI_INSTRUCTION escape 0x0f, 0x0d, 0x72, 0x00, 0x11, 0x10, 0x22, 0x11, 0x01, 0x92, 0xa2, 0x38, 0x00, 0x1e, 0x22 + ; CHECK-NEXT: $x12 = ADDI $x2, 16 + ; CHECK-NEXT: frame-setup VS1R_V killed $v1, killed $x12 :: (store unknown-size into %stack.0, align 8) + ; CHECK-NEXT: frame-setup CFI_INSTRUCTION escape 0x10, 0x61, 0x08, 0x11, 0x7f, 0x92, 0xa2, 0x38, 0x00, 0x1e, 0x22 + ; CHECK-NEXT: dead $x0 = PseudoVSETIVLI 4, 208 /* e32, m1, ta, ma */, implicit-def $vl, implicit-def $vtype + ; CHECK-NEXT: renamable $v1 = PseudoVLE32_V_M1 undef renamable $v1, killed renamable $x10, 4, 5 /* e32 */, 2 /* tu, ma */, implicit $vl, implicit $vtype + ; CHECK-NEXT: PseudoVSE32_V_M1 killed renamable $v1, killed renamable $x11, 4, 5 /* e32 */, implicit $vl, implicit $vtype + ; CHECK-NEXT: PseudoBR %bb.2 + bb.0.entry: + liveins: $x10, $x11 + BEQ $x10, $x0, %bb.3 + + bb.1: + PseudoRET + + bb.2: + PseudoBR %bb.1 + + bb.3: + liveins: $x10, $x11 + dead $x0 = PseudoVSETIVLI 4, 208, implicit-def $vl, implicit-def $vtype + renamable $v1 = PseudoVLE32_V_M1 undef renamable $v1, killed renamable $x10, 4, 5, 2, implicit $vl, implicit $vtype + PseudoVSE32_V_M1 killed renamable $v1, killed renamable $x11, 4, 5, implicit $vl, implicit $vtype + PseudoBR %bb.2 +... diff --git a/llvm/test/CodeGen/RISCV/cfi-multiple-locations.mir b/llvm/test/CodeGen/RISCV/cfi-multiple-locations.mir new file mode 100644 index 0000000000000..f40a55a29d15f --- /dev/null +++ b/llvm/test/CodeGen/RISCV/cfi-multiple-locations.mir @@ -0,0 +1,35 @@ +# RUN: llc %s -mtriple=riscv64 \ +# RUN: -run-pass=cfi-instr-inserter \ +# RUN: -riscv-enable-cfi-instr-inserter=true \ +# RUN: | FileCheck %s +# XFAIL: * + +# Technically, it is possible that the a callee-saved register is saved in different locations. +# CFIInstrInserter should handle this, but currently it does not. +--- +name: multiple_locations +tracksRegLiveness: true +body: | + bb.0.entry: + liveins: $x10, $x9, $x2 + BEQ $x10, $x0, %bb.3 + + bb.1: + liveins: $x10, $x9, $x2 + $x5 = COPY $x9 + CFI_INSTRUCTION register $x9, $x5 + $x9 = COPY $x5 + CFI_INSTRUCTION register $x9, $x9 + PseudoBR %bb.3 + + bb.2: + liveins: $x10, $x9, $x2 + SD $x10, $x2, 0 :: (store (s64)) + CFI_INSTRUCTION offset $x9, 0 + $x10 = LD $x2, 0 :: (load (s64)) + CFI_INSTRUCTION register $x9, $x9 + PseudoBR %bb.1 + + bb.3: + PseudoRET +...