-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[RISCV] Add MC layer support for Zicfiss. #66043
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@llvm/pr-subscribers-clang ChangesThe patch adds the instructions in Zicfiss extension. Zicfiss extension is to support shadow stack for control flow integrity. This patch is based on version 0.3.1. -- Patch is 23.44 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/66043.diff 14 Files Affected:
diff --git a/clang/test/Preprocessor/riscv-target-features.c b/clang/test/Preprocessor/riscv-target-features.c index 02b67dc7944ba88..163eba81543ee5b 100644 --- a/clang/test/Preprocessor/riscv-target-features.c +++ b/clang/test/Preprocessor/riscv-target-features.c @@ -113,6 +113,7 @@ // CHECK-NOT: __riscv_zfa {{.*$}} // CHECK-NOT: __riscv_zfbfmin {{.*$}} // CHECK-NOT: __riscv_zicfilp {{.*$}} +// CHECK-NOT: __riscv_zicfiss {{.*$}} // CHECK-NOT: __riscv_zicond {{.*$}} // CHECK-NOT: __riscv_ztso {{.*$}} // CHECK-NOT: __riscv_zvbb {{.*$}} @@ -1220,3 +1221,11 @@ // RUN: -march=rv64i_zve32x_zvkt1p0 -x c -E -dM %s \ // RUN: -o - | FileCheck --check-prefix=CHECK-ZVKT-EXT %s // CHECK-ZVKT-EXT: __riscv_zvkt 1000000{{$}} + +// RUN: %clang -target riscv32 -menable-experimental-extensions \ +// RUN: -march=rv32izicfiss0p3 -x c -E -dM %s \ +// RUN: -o - | FileCheck --check-prefix=CHECK-ZICFISS-EXT %s +// RUN: %clang -target riscv64 -menable-experimental-extensions \ +// RUN: -march=rv64izicfiss0p3 -x c -E -dM %s \ +// RUN: -o - | FileCheck --check-prefix=CHECK-ZICFISS-EXT %s +// CHECK-ZICFISS-EXT: __riscv_zicfiss 3000{{$}} diff --git a/llvm/docs/RISCVUsage.rst b/llvm/docs/RISCVUsage.rst index 8d12d58738c609a..31c55def0a7694a 100644 --- a/llvm/docs/RISCVUsage.rst +++ b/llvm/docs/RISCVUsage.rst @@ -205,6 +205,9 @@ The primary goal of experimental support is to assist in the process of ratifica ``experimental-zicfilp`` LLVM implements the `0.2 draft specification `__. +``experimental-zicfiss`` + LLVM implements the `0.3.1 draft specification `__. + ``experimental-zicond`` LLVM implements the `1.0-rc1 draft specification `__. diff --git a/llvm/lib/Support/RISCVISAInfo.cpp b/llvm/lib/Support/RISCVISAInfo.cpp index a02c9842e85839a..c414b62c5f31092 100644 --- a/llvm/lib/Support/RISCVISAInfo.cpp +++ b/llvm/lib/Support/RISCVISAInfo.cpp @@ -170,6 +170,8 @@ static const RISCVSupportedExtension SupportedExperimentalExtensions[] = { {"zfbfmin", RISCVExtensionVersion{0, 8}}, {"zicfilp", RISCVExtensionVersion{0, 2}}, + {"zicfiss", RISCVExtensionVersion{0, 3}}, + {"zicond", RISCVExtensionVersion{1, 0}}, {"ztso", RISCVExtensionVersion{0, 1}}, diff --git a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp index d561d90d3088c1a..14b3122f0fecbdb 100644 --- a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp +++ b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp @@ -74,6 +74,17 @@ static DecodeStatus DecodeGPRRegisterClass(MCInst &Inst, uint32_t RegNo, return MCDisassembler::Success; } +static DecodeStatus DecodeGPRRARegisterClass(MCInst &Inst, uint32_t RegNo, + uint64_t Address, + const MCDisassembler *Decoder) { + MCRegister Reg = RISCV::X0 + RegNo; + if (Reg != RISCV::X1 && Reg != RISCV::X5) + return MCDisassembler::Fail; + + Inst.addOperand(MCOperand::createReg(Reg)); + return MCDisassembler::Success; +} + static DecodeStatus DecodeFPR16RegisterClass(MCInst &Inst, uint32_t RegNo, uint64_t Address, const MCDisassembler *Decoder) { @@ -370,6 +381,10 @@ static DecodeStatus decodeZcmpRlist(MCInst &Inst, unsigned Imm, static DecodeStatus decodeZcmpSpimm(MCInst &Inst, unsigned Imm, uint64_t Address, const void *Decoder); +static DecodeStatus decodeCSSPushPopchk(MCInst &Inst, uint32_t Insn, + uint64_t Address, + const MCDisassembler *Decoder); + #include "RISCVGenDisassemblerTables.inc" static DecodeStatus decodeRVCInstrRdRs1ImmZero(MCInst &Inst, uint32_t Insn, @@ -384,6 +399,16 @@ static DecodeStatus decodeRVCInstrRdRs1ImmZero(MCInst &Inst, uint32_t Insn, return MCDisassembler::Success; } +static DecodeStatus decodeCSSPushPopchk(MCInst &Inst, uint32_t Insn, + uint64_t Address, + const MCDisassembler *Decoder) { + uint32_t Rs1 = fieldFromInstruction(Insn, 7, 5); + DecodeStatus Result = DecodeGPRRARegisterClass(Inst, Rs1, Address, Decoder); + (void)Result; + assert(Result == MCDisassembler::Success && "Invalid register"); + return MCDisassembler::Success; +} + static DecodeStatus decodeRVCInstrRdSImm(MCInst &Inst, uint32_t Insn, uint64_t Address, const MCDisassembler *Decoder) { @@ -527,6 +552,10 @@ DecodeStatus RISCVDisassembler::getInstruction(MCInst &MI, uint64_t &Size, "RV32Zdinx table (Double in Integer and rv32)"); TRY_TO_DECODE_FEATURE(RISCV::FeatureStdExtZfinx, DecoderTableRVZfinx32, "RVZfinx table (Float in Integer)"); + TRY_TO_DECODE(STI.hasFeature(RISCV::FeatureStdExtZicfiss) && + !STI.hasFeature(RISCV::Feature64Bit), + DecoderTableRV32Zicfiss32, + "RV32Zicfiss table (Shadow stack and rv32)"); TRY_TO_DECODE_FEATURE(RISCV::FeatureVendorXVentanaCondOps, DecoderTableXVentana32, "Ventana custom opcode table"); TRY_TO_DECODE_FEATURE(RISCV::FeatureVendorXTHeadBa, DecoderTableXTHeadBa32, diff --git a/llvm/lib/Target/RISCV/RISCVFeatures.td b/llvm/lib/Target/RISCV/RISCVFeatures.td index 6381263b37613b3..286320c6c52eb12 100644 --- a/llvm/lib/Target/RISCV/RISCVFeatures.td +++ b/llvm/lib/Target/RISCV/RISCVFeatures.td @@ -79,6 +79,13 @@ def HasStdExtZihintntl : Predicate<"Subtarget->hasStdExtZihintntl()">, AssemblerPredicate<(all_of FeatureStdExtZihintntl), "'Zihintntl' (Non-Temporal Locality Hints)">; +def FeatureStdExtZicfiss + : SubtargetFeature<"experimental-zicfiss", "HasStdExtZicfiss", "true", + "'Zicfiss' (Shadow stack)">; +def HasStdExtZicfiss : Predicate<"Subtarget->hasStdExtZicfiss()">, + AssemblerPredicate<(all_of FeatureStdExtZicfiss), + "'Zicfiss' (Shadow stack)">; + def FeatureStdExtZifencei : SubtargetFeature<"zifencei", "HasStdExtZifencei", "true", "'Zifencei' (fence.i)">; diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.td b/llvm/lib/Target/RISCV/RISCVInstrInfo.td index 582fe60fd0368e9..e6a8ba1fe2fc17d 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfo.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.td @@ -1970,14 +1970,15 @@ include "RISCVInstrInfoZk.td" include "RISCVInstrInfoV.td" include "RISCVInstrInfoZvk.td" -// Integer -include "RISCVInstrInfoZicbo.td" -include "RISCVInstrInfoZicond.td" - // Compressed include "RISCVInstrInfoC.td" include "RISCVInstrInfoZc.td" +// Integer +include "RISCVInstrInfoZicbo.td" +include "RISCVInstrInfoZicond.td" +include "RISCVInstrInfoZicfiss.td" + //===----------------------------------------------------------------------===// // Vendor extensions //===----------------------------------------------------------------------===// diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoZicfiss.td b/llvm/lib/Target/RISCV/RISCVInstrInfoZicfiss.td new file mode 100644 index 000000000000000..f787a260a8ca9da --- /dev/null +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoZicfiss.td @@ -0,0 +1,86 @@ +//===------ RISCVInstrInfoZicfiss.td - RISC-V Zicfiss -*- tablegen -*------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// Instruction class templates +//===----------------------------------------------------------------------===// + +class RVC_SSInst rs1val, RegisterClass reg_class, string opcodestr> : + RVInst16<(outs), (ins reg_class:$rs1), opcodestr, "$rs1", [], InstFormatOther> { + let Inst{15-13} = 0b011; + let Inst{12} = 0; + let Inst{11-7} = rs1val; + let Inst{6-2} = 0b00000; + let Inst{1-0} = 0b01; + let DecoderMethod = "decodeCSSPushPopchk"; +} + +//===----------------------------------------------------------------------===// +// Instructions +//===----------------------------------------------------------------------===// + +let Uses = [SSP], hasSideEffects = 0, mayLoad = 1, mayStore = 0 in { +let DecoderNamespace = "RV32Zicfiss", Predicates = [HasStdExtZicfiss, IsRV32] in +def SSLW : RVInstI<0b100, OPC_SYSTEM, (outs GPRRA:$rd), (ins), "sslw", "$rd"> { + let rs1 = 0; + let imm12 = 0b100000011100; +} + +let Predicates = [HasStdExtZicfiss, IsRV64] in +def SSLD : RVInstI<0b100, OPC_SYSTEM, (outs GPRRA:$rd), (ins), "ssld", "$rd"> { + let rs1 = 0; + let imm12 = 0b100000011100; +} +} // Uses = [SSP], hasSideEffects = 0, mayLoad = 1, mayStore = 0 + +let Predicates = [HasStdExtZicfiss] in { +let Uses = [SSP], hasSideEffects = 0, mayLoad = 1, mayStore = 0 in +def SSPOPCHK : RVInstI<0b100, OPC_SYSTEM, (outs), (ins GPRRA:$rs1), "sspopchk", + "$rs1"> { + let rd = 0; + let imm12 = 0b100000011100; +} // Uses = [SSP], hasSideEffects = 0, mayLoad = 1, mayStore = 0 + +let Uses = [SSP], hasSideEffects = 0, mayLoad = 0, mayStore = 0 in { +def SSINCP : RVInstI<0b100, OPC_SYSTEM, (outs), (ins), "ssincp", ""> { + let imm12 = 0b100000011100; + let rs1 = 0b00000; + let rd = 0b00000; +} + +def SSRDP : RVInstI<0b100, OPC_SYSTEM, (outs GPRNoX0:$rd), (ins), "ssrdp", "$rd"> { + let imm12 = 0b100000011101; + let rs1 = 0b00000; +} +} // Uses = [SSP], hasSideEffects = 0, mayLoad = 0, mayStore = 0 + +let Uses = [SSP], Defs = [SSP], hasSideEffects = 0, mayLoad = 0, mayStore = 1 in +def SSPUSH : RVInstR<0b1000001, 0b100, OPC_SYSTEM, (outs), (ins GPRRA:$rs2), + "sspush", "$rs2"> { + let rd = 0b00000; + let rs1 = 0b00000; +} +} // Predicates = [HasStdExtZicfiss] + +let Predicates = [HasStdExtZicfiss, HasStdExtCOrZca] in { +let Uses = [SSP], Defs = [SSP], hasSideEffects = 0, mayLoad = 0, mayStore = 1 in +def C_SSPUSH : RVC_SSInst<0b00001, GPRX1, "c.sspush">; + +let Uses = [SSP], Defs = [SSP], hasSideEffects = 0, mayLoad = 0, mayStore = 1 in +def C_SSPOPCHK : RVC_SSInst<0b00101, GPRX5, "c.sspopchk">; +} // Predicates = [HasStdExtZicfiss, HasStdExtCOrZca] + +let Predicates = [HasStdExtZicfiss, HasStdExtC], Uses = [SSP], Defs = [SSP], + hasSideEffects = 0, mayLoad = 0, mayStore = 0 in +def C_SSINCP : RVInst16<(outs), (ins), "c.ssincp", "", [], InstFormatOther> { + let Inst{15-13} = 0b011; + let Inst{12} = 0; + let Inst{11-7} = 0b00011; + let Inst{6-2} = 0b00000; + let Inst{1-0} = 0b01; +} diff --git a/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp b/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp index 3e44cf4781f643c..7934da40ac4aadc 100644 --- a/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp +++ b/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp @@ -119,6 +119,9 @@ BitVector RISCVRegisterInfo::getReservedRegs(const MachineFunction &MF) const { markSuperRegs(Reserved, RISCV::FRM); markSuperRegs(Reserved, RISCV::FFLAGS); + // Shadow stack pointer. + markSuperRegs(Reserved, RISCV::SSP); + assert(checkAllSuperRegsMarked(Reserved)); return Reserved; } diff --git a/llvm/lib/Target/RISCV/RISCVRegisterInfo.td b/llvm/lib/Target/RISCV/RISCVRegisterInfo.td index 1a6145f92908134..87ad1d5ecd179e9 100644 --- a/llvm/lib/Target/RISCV/RISCVRegisterInfo.td +++ b/llvm/lib/Target/RISCV/RISCVRegisterInfo.td @@ -137,6 +137,8 @@ def GPR : GPRRegisterClass<(add (sequence "X%u", 10, 17), (sequence "X%u", 0, 4))>; def GPRX0 : GPRRegisterClass<(add X0)>; +def GPRX1 : GPRRegisterClass<(add X1)>; +def GPRX5 : GPRRegisterClass<(add X5)>; def GPRNoX0 : GPRRegisterClass<(sub GPR, X0)>; @@ -165,6 +167,10 @@ def SP : GPRRegisterClass<(add X2)>; def SR07 : GPRRegisterClass<(add (sequence "X%u", 8, 9), (sequence "X%u", 18, 23))>; +def GPRRA : RegisterClass<"RISCV", [XLenVT], 32, (add X1, X5)> { + let RegInfos = XLenRI; +} + // Floating point registers let RegAltNameIndices = [ABIRegAltName] in { def F0_H : RISCVReg16<0, "f0", ["ft0"]>, DwarfRegNum<[32]>; @@ -597,3 +603,6 @@ foreach m = LMULList in { // Special registers def FFLAGS : RISCVReg<0, "fflags">; def FRM : RISCVReg<0, "frm">; + +// Shadow Stack register +def SSP : RISCVReg<0, "ssp">; diff --git a/llvm/test/MC/RISCV/attribute-arch.s b/llvm/test/MC/RISCV/attribute-arch.s index bf40eda456edf13..4f201d2afde3164 100644 --- a/llvm/test/MC/RISCV/attribute-arch.s +++ b/llvm/test/MC/RISCV/attribute-arch.s @@ -305,3 +305,6 @@ .attribute arch, "rv32i_zicfilp0p2" # CHECK: attribute 5, "rv32i2p1_zicfilp0p2" + +.attribute arch, "rv32i_zicfiss0p3" +# CHECK: .attribute 5, "rv32i2p1_zicfiss0p3" diff --git a/llvm/test/MC/RISCV/rv32zicfiss-invalid.s b/llvm/test/MC/RISCV/rv32zicfiss-invalid.s new file mode 100644 index 000000000000000..6b4959043d0180b --- /dev/null +++ b/llvm/test/MC/RISCV/rv32zicfiss-invalid.s @@ -0,0 +1,20 @@ +# RUN: not llvm-mc %s -triple=riscv32 -mattr=+experimental-zicfiss,+c -riscv-no-aliases -show-encoding \ +# RUN: 2>&1 | FileCheck -check-prefixes=CHECK-ERR %s + +# CHECK-ERR: error: invalid operand for instruction +sslw a0 + +# CHECK-ERR: error: invalid operand for instruction +sspopchk a1 + +# CHECK-ERR: error: invalid operand for instruction +c.sspush t0 + +# CHECK-ERR: error: invalid operand for instruction +c.sspopchk ra + +# CHECK-ERR: error: invalid operand for instruction +sspush a0 + +# CHECK-ERR: error: invalid operand for instruction +ssrdp zero diff --git a/llvm/test/MC/RISCV/rv32zicfiss-valid.s b/llvm/test/MC/RISCV/rv32zicfiss-valid.s new file mode 100644 index 000000000000000..46a1d3103afac6e --- /dev/null +++ b/llvm/test/MC/RISCV/rv32zicfiss-valid.s @@ -0,0 +1,103 @@ +# RUN: llvm-mc %s -triple=riscv32 -mattr=+experimental-zicfiss,+c -riscv-no-aliases -show-encoding \ +# RUN: | FileCheck -check-prefixes=CHECK-ASM,CHECK-ASM-AND-OBJ %s +# RUN: llvm-mc -filetype=obj -triple=riscv32 -mattr=+experimental-zicfiss,+c < %s \ +# RUN: | llvm-objdump --mattr=+experimental-zicfiss -M no-aliases -d -r - \ +# RUN: | FileCheck --check-prefix=CHECK-ASM-AND-OBJ %s +# +# RUN: not llvm-mc -triple riscv32 -riscv-no-aliases -show-encoding < %s 2>&1 \ +# RUN: | FileCheck -check-prefixes=CHECK-NO-EXT %s + +# CHECK-ASM-AND-OBJ: sslw ra +# CHECK-ASM: encoding: [0xf3,0x40,0xc0,0x81] +# CHECK-NO-EXT: error: instruction requires the following: 'Zicfiss' (Shadow stack) +sslw x1 + +# CHECK-ASM-AND-OBJ: sslw ra +# CHECK-ASM: encoding: [0xf3,0x40,0xc0,0x81] +# CHECK-NO-EXT: error: instruction requires the following: 'Zicfiss' (Shadow stack) +sslw ra + +# CHECK-ASM-AND-OBJ: sslw t0 +# CHECK-ASM: encoding: [0xf3,0x42,0xc0,0x81] +# CHECK-NO-EXT: error: instruction requires the following: 'Zicfiss' (Shadow stack) +sslw x5 + +# CHECK-ASM-AND-OBJ: sslw t0 +# CHECK-ASM: encoding: [0xf3,0x42,0xc0,0x81] +# CHECK-NO-EXT: error: instruction requires the following: 'Zicfiss' (Shadow stack) +sslw t0 + +# CHECK-ASM-AND-OBJ: sspopchk ra +# CHECK-ASM: encoding: [0x73,0xc0,0xc0,0x81] +# CHECK-NO-EXT: error: instruction requires the following: 'Zicfiss' (Shadow stack) +sspopchk x1 + +# CHECK-ASM-AND-OBJ: sspopchk ra +# CHECK-ASM: encoding: [0x73,0xc0,0xc0,0x81] +# CHECK-NO-EXT: error: instruction requires the following: 'Zicfiss' (Shadow stack) +sspopchk ra + +# CHECK-ASM-AND-OBJ: sspopchk t0 +# CHECK-ASM: encoding: [0x73,0xc0,0xc2,0x81] +# CHECK-NO-EXT: error: instruction requires the following: 'Zicfiss' (Shadow stack) +sspopchk x5 + +# CHECK-ASM-AND-OBJ: sspopchk t0 +# CHECK-ASM: encoding: [0x73,0xc0,0xc2,0x81] +# CHECK-NO-EXT: error: instruction requires the following: 'Zicfiss' (Shadow stack) +sspopchk t0 + +# CHECK-ASM-AND-OBJ: ssincp +# CHECK-ASM: encoding: [0x73,0x40,0xc0,0x81] +# CHECK-NO-EXT: error: instruction requires the following: 'Zicfiss' (Shadow stack) +ssincp + +# CHECK-ASM-AND-OBJ: sspush ra +# CHECK-ASM: encoding: [0x73,0x40,0x10,0x82] +# CHECK-NO-EXT: error: instruction requires the following: 'Zicfiss' (Shadow stack) +sspush x1 + +# CHECK-ASM-AND-OBJ: sspush ra +# CHECK-ASM: encoding: [0x73,0x40,0x10,0x82] +# CHECK-NO-EXT: error: instruction requires the following: 'Zicfiss' (Shadow stack) +sspush ra + +# check-asm-and-obj: sspush t0 +# check-asm: encoding: [0x73,0x40,0x50,0x82] +# check-no-ext: error: instruction requires the following: 'Zicfiss' (Shadow stack) +sspush x5 + +# check-asm-and-obj: sspush t0 +# check-asm: encoding: [0x73,0x40,0x50,0x82] +# check-no-ext: error: instruction requires the following: 'Zicfiss' (Shadow stack) +sspush t0 + +# CHECK-ASM-AND-OBJ: ssrdp ra +# CHECK-ASM: encoding: [0xf3,0x40,0xd0,0x81] +# CHECK-NO-EXT: error: instruction requires the following: 'Zicfiss' (Shadow stack) +ssrdp ra + +# CHECK-ASM-AND-OBJ: c.sspush ra +# CHECK-ASM: encoding: [0x81,0x60] +# CHECK-NO-EXT: error: instruction requires the following: 'C' (Compressed Instructions) or 'Zca' (part of the C extension, excluding compressed floating point loads/stores), 'Zicfiss' (Shadow stack) +c.sspush x1 + +# CHECK-ASM-AND-OBJ: c.sspush ra +# CHECK-ASM: encoding: [0x81,0x60] +# CHECK-NO-EXT: error: instruction requires the following: 'C' (Compressed Instructions) or 'Zca' (part of the C extension, excluding compressed floating point loads/stores), 'Zicfiss' (Shadow stack) +c.sspush ra + +# CHECK-ASM-AND-OBJ: c.sspopchk t0 +# CHECK-ASM: encoding: [0x81,0x62] +# CHECK-NO-EXT: error: instruction requires the following: 'C' (Compressed Instructions) or 'Zca' (part of the C extension, excluding compressed floating point loads/stores), 'Zicfiss' (Shadow stack) +c.sspopchk x5 + +# CHECK-ASM-AND-OBJ: c.sspopchk t0 +# CHECK-ASM: encoding: [0x81,0x62] +# CHECK-NO-EXT: error: instruction requires the following: 'C' (Compressed Instructions) or 'Zca' (part of the C extension, excluding compressed floating point loads/stores), 'Zicfiss' (Shadow stack) +c.sspopchk t0 + +# CHECK-ASM-AND-OBJ: c.ssincp +# CHECK-ASM: encoding: [0x81,0x61] +# CHECK-NO-EXT: error: instruction requires the following: 'C' (Compressed Instructions), 'Zicfiss' (Shadow stack) +c.ssincp diff --git a/llvm/test/MC/RISCV/rv64zicfiss-invalid.s b/llvm/test/MC/RISCV/rv64zicfiss-invalid.s new file mode 100644 index 000000000000000..aef5e17e33aff9e --- /dev/null +++ b/llvm/test/MC/RISCV/rv64zicfiss-invalid.s @@ -0,0 +1,20 @@ +# RUN: not llvm-mc %s -triple=riscv64 -mattr=+experimental-zicfiss,+c -riscv-no-aliases -show-encoding \ +# RUN: 2>&1 | FileCheck -check-prefixes=CHECK-ERR %s + +# CHECK-ERR: error: invalid operand for instruction +ssld a0 + +# CHECK-ERR: error: invalid operand for instruction +sspopchk a1 + +# CHECK-ERR: error: invalid operand for instruction +c.sspush t0 + +# CHECK-ERR: error: invalid operand for instruction +c.sspopchk ra + +# CHECK-ERR: error: invalid operand for instruction +sspush a0 + +# CHECK-ERR: error: invalid operand for instruction +ssrdp zero diff --git a/llvm/test/MC/RISCV/rv64zicfiss-valid.s b/llvm/test/MC/RISCV/rv64zicfiss-valid.s new file mode 100644 index 000000000000000..8bba15cc3b22bec --- /dev/null +++ b/llvm/test/MC/RI... |
@llvm/pr-subscribers-mc ChangesThe patch adds the instructions in Zicfiss extension. Zicfiss extension is to support shadow stack for control flow integrity. This patch is based on version 0.3.1. -- Patch is 23.44 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/66043.diff 14 Files Affected:
diff --git a/clang/test/Preprocessor/riscv-target-features.c b/clang/test/Preprocessor/riscv-target-features.c index 02b67dc7944ba88..163eba81543ee5b 100644 --- a/clang/test/Preprocessor/riscv-target-features.c +++ b/clang/test/Preprocessor/riscv-target-features.c @@ -113,6 +113,7 @@ // CHECK-NOT: __riscv_zfa {{.*$}} // CHECK-NOT: __riscv_zfbfmin {{.*$}} // CHECK-NOT: __riscv_zicfilp {{.*$}} +// CHECK-NOT: __riscv_zicfiss {{.*$}} // CHECK-NOT: __riscv_zicond {{.*$}} // CHECK-NOT: __riscv_ztso {{.*$}} // CHECK-NOT: __riscv_zvbb {{.*$}} @@ -1220,3 +1221,11 @@ // RUN: -march=rv64i_zve32x_zvkt1p0 -x c -E -dM %s \ // RUN: -o - | FileCheck --check-prefix=CHECK-ZVKT-EXT %s // CHECK-ZVKT-EXT: __riscv_zvkt 1000000{{$}} + +// RUN: %clang -target riscv32 -menable-experimental-extensions \ +// RUN: -march=rv32izicfiss0p3 -x c -E -dM %s \ +// RUN: -o - | FileCheck --check-prefix=CHECK-ZICFISS-EXT %s +// RUN: %clang -target riscv64 -menable-experimental-extensions \ +// RUN: -march=rv64izicfiss0p3 -x c -E -dM %s \ +// RUN: -o - | FileCheck --check-prefix=CHECK-ZICFISS-EXT %s +// CHECK-ZICFISS-EXT: __riscv_zicfiss 3000{{$}} diff --git a/llvm/docs/RISCVUsage.rst b/llvm/docs/RISCVUsage.rst index 8d12d58738c609a..31c55def0a7694a 100644 --- a/llvm/docs/RISCVUsage.rst +++ b/llvm/docs/RISCVUsage.rst @@ -205,6 +205,9 @@ The primary goal of experimental support is to assist in the process of ratifica ``experimental-zicfilp`` LLVM implements the `0.2 draft specification `__. +``experimental-zicfiss`` + LLVM implements the `0.3.1 draft specification `__. + ``experimental-zicond`` LLVM implements the `1.0-rc1 draft specification `__. diff --git a/llvm/lib/Support/RISCVISAInfo.cpp b/llvm/lib/Support/RISCVISAInfo.cpp index a02c9842e85839a..c414b62c5f31092 100644 --- a/llvm/lib/Support/RISCVISAInfo.cpp +++ b/llvm/lib/Support/RISCVISAInfo.cpp @@ -170,6 +170,8 @@ static const RISCVSupportedExtension SupportedExperimentalExtensions[] = { {"zfbfmin", RISCVExtensionVersion{0, 8}}, {"zicfilp", RISCVExtensionVersion{0, 2}}, + {"zicfiss", RISCVExtensionVersion{0, 3}}, + {"zicond", RISCVExtensionVersion{1, 0}}, {"ztso", RISCVExtensionVersion{0, 1}}, diff --git a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp index d561d90d3088c1a..14b3122f0fecbdb 100644 --- a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp +++ b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp @@ -74,6 +74,17 @@ static DecodeStatus DecodeGPRRegisterClass(MCInst &Inst, uint32_t RegNo, return MCDisassembler::Success; } +static DecodeStatus DecodeGPRRARegisterClass(MCInst &Inst, uint32_t RegNo, + uint64_t Address, + const MCDisassembler *Decoder) { + MCRegister Reg = RISCV::X0 + RegNo; + if (Reg != RISCV::X1 && Reg != RISCV::X5) + return MCDisassembler::Fail; + + Inst.addOperand(MCOperand::createReg(Reg)); + return MCDisassembler::Success; +} + static DecodeStatus DecodeFPR16RegisterClass(MCInst &Inst, uint32_t RegNo, uint64_t Address, const MCDisassembler *Decoder) { @@ -370,6 +381,10 @@ static DecodeStatus decodeZcmpRlist(MCInst &Inst, unsigned Imm, static DecodeStatus decodeZcmpSpimm(MCInst &Inst, unsigned Imm, uint64_t Address, const void *Decoder); +static DecodeStatus decodeCSSPushPopchk(MCInst &Inst, uint32_t Insn, + uint64_t Address, + const MCDisassembler *Decoder); + #include "RISCVGenDisassemblerTables.inc" static DecodeStatus decodeRVCInstrRdRs1ImmZero(MCInst &Inst, uint32_t Insn, @@ -384,6 +399,16 @@ static DecodeStatus decodeRVCInstrRdRs1ImmZero(MCInst &Inst, uint32_t Insn, return MCDisassembler::Success; } +static DecodeStatus decodeCSSPushPopchk(MCInst &Inst, uint32_t Insn, + uint64_t Address, + const MCDisassembler *Decoder) { + uint32_t Rs1 = fieldFromInstruction(Insn, 7, 5); + DecodeStatus Result = DecodeGPRRARegisterClass(Inst, Rs1, Address, Decoder); + (void)Result; + assert(Result == MCDisassembler::Success && "Invalid register"); + return MCDisassembler::Success; +} + static DecodeStatus decodeRVCInstrRdSImm(MCInst &Inst, uint32_t Insn, uint64_t Address, const MCDisassembler *Decoder) { @@ -527,6 +552,10 @@ DecodeStatus RISCVDisassembler::getInstruction(MCInst &MI, uint64_t &Size, "RV32Zdinx table (Double in Integer and rv32)"); TRY_TO_DECODE_FEATURE(RISCV::FeatureStdExtZfinx, DecoderTableRVZfinx32, "RVZfinx table (Float in Integer)"); + TRY_TO_DECODE(STI.hasFeature(RISCV::FeatureStdExtZicfiss) && + !STI.hasFeature(RISCV::Feature64Bit), + DecoderTableRV32Zicfiss32, + "RV32Zicfiss table (Shadow stack and rv32)"); TRY_TO_DECODE_FEATURE(RISCV::FeatureVendorXVentanaCondOps, DecoderTableXVentana32, "Ventana custom opcode table"); TRY_TO_DECODE_FEATURE(RISCV::FeatureVendorXTHeadBa, DecoderTableXTHeadBa32, diff --git a/llvm/lib/Target/RISCV/RISCVFeatures.td b/llvm/lib/Target/RISCV/RISCVFeatures.td index 6381263b37613b3..286320c6c52eb12 100644 --- a/llvm/lib/Target/RISCV/RISCVFeatures.td +++ b/llvm/lib/Target/RISCV/RISCVFeatures.td @@ -79,6 +79,13 @@ def HasStdExtZihintntl : Predicate<"Subtarget->hasStdExtZihintntl()">, AssemblerPredicate<(all_of FeatureStdExtZihintntl), "'Zihintntl' (Non-Temporal Locality Hints)">; +def FeatureStdExtZicfiss + : SubtargetFeature<"experimental-zicfiss", "HasStdExtZicfiss", "true", + "'Zicfiss' (Shadow stack)">; +def HasStdExtZicfiss : Predicate<"Subtarget->hasStdExtZicfiss()">, + AssemblerPredicate<(all_of FeatureStdExtZicfiss), + "'Zicfiss' (Shadow stack)">; + def FeatureStdExtZifencei : SubtargetFeature<"zifencei", "HasStdExtZifencei", "true", "'Zifencei' (fence.i)">; diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.td b/llvm/lib/Target/RISCV/RISCVInstrInfo.td index 582fe60fd0368e9..e6a8ba1fe2fc17d 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfo.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.td @@ -1970,14 +1970,15 @@ include "RISCVInstrInfoZk.td" include "RISCVInstrInfoV.td" include "RISCVInstrInfoZvk.td" -// Integer -include "RISCVInstrInfoZicbo.td" -include "RISCVInstrInfoZicond.td" - // Compressed include "RISCVInstrInfoC.td" include "RISCVInstrInfoZc.td" +// Integer +include "RISCVInstrInfoZicbo.td" +include "RISCVInstrInfoZicond.td" +include "RISCVInstrInfoZicfiss.td" + //===----------------------------------------------------------------------===// // Vendor extensions //===----------------------------------------------------------------------===// diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoZicfiss.td b/llvm/lib/Target/RISCV/RISCVInstrInfoZicfiss.td new file mode 100644 index 000000000000000..f787a260a8ca9da --- /dev/null +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoZicfiss.td @@ -0,0 +1,86 @@ +//===------ RISCVInstrInfoZicfiss.td - RISC-V Zicfiss -*- tablegen -*------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// Instruction class templates +//===----------------------------------------------------------------------===// + +class RVC_SSInst rs1val, RegisterClass reg_class, string opcodestr> : + RVInst16<(outs), (ins reg_class:$rs1), opcodestr, "$rs1", [], InstFormatOther> { + let Inst{15-13} = 0b011; + let Inst{12} = 0; + let Inst{11-7} = rs1val; + let Inst{6-2} = 0b00000; + let Inst{1-0} = 0b01; + let DecoderMethod = "decodeCSSPushPopchk"; +} + +//===----------------------------------------------------------------------===// +// Instructions +//===----------------------------------------------------------------------===// + +let Uses = [SSP], hasSideEffects = 0, mayLoad = 1, mayStore = 0 in { +let DecoderNamespace = "RV32Zicfiss", Predicates = [HasStdExtZicfiss, IsRV32] in +def SSLW : RVInstI<0b100, OPC_SYSTEM, (outs GPRRA:$rd), (ins), "sslw", "$rd"> { + let rs1 = 0; + let imm12 = 0b100000011100; +} + +let Predicates = [HasStdExtZicfiss, IsRV64] in +def SSLD : RVInstI<0b100, OPC_SYSTEM, (outs GPRRA:$rd), (ins), "ssld", "$rd"> { + let rs1 = 0; + let imm12 = 0b100000011100; +} +} // Uses = [SSP], hasSideEffects = 0, mayLoad = 1, mayStore = 0 + +let Predicates = [HasStdExtZicfiss] in { +let Uses = [SSP], hasSideEffects = 0, mayLoad = 1, mayStore = 0 in +def SSPOPCHK : RVInstI<0b100, OPC_SYSTEM, (outs), (ins GPRRA:$rs1), "sspopchk", + "$rs1"> { + let rd = 0; + let imm12 = 0b100000011100; +} // Uses = [SSP], hasSideEffects = 0, mayLoad = 1, mayStore = 0 + +let Uses = [SSP], hasSideEffects = 0, mayLoad = 0, mayStore = 0 in { +def SSINCP : RVInstI<0b100, OPC_SYSTEM, (outs), (ins), "ssincp", ""> { + let imm12 = 0b100000011100; + let rs1 = 0b00000; + let rd = 0b00000; +} + +def SSRDP : RVInstI<0b100, OPC_SYSTEM, (outs GPRNoX0:$rd), (ins), "ssrdp", "$rd"> { + let imm12 = 0b100000011101; + let rs1 = 0b00000; +} +} // Uses = [SSP], hasSideEffects = 0, mayLoad = 0, mayStore = 0 + +let Uses = [SSP], Defs = [SSP], hasSideEffects = 0, mayLoad = 0, mayStore = 1 in +def SSPUSH : RVInstR<0b1000001, 0b100, OPC_SYSTEM, (outs), (ins GPRRA:$rs2), + "sspush", "$rs2"> { + let rd = 0b00000; + let rs1 = 0b00000; +} +} // Predicates = [HasStdExtZicfiss] + +let Predicates = [HasStdExtZicfiss, HasStdExtCOrZca] in { +let Uses = [SSP], Defs = [SSP], hasSideEffects = 0, mayLoad = 0, mayStore = 1 in +def C_SSPUSH : RVC_SSInst<0b00001, GPRX1, "c.sspush">; + +let Uses = [SSP], Defs = [SSP], hasSideEffects = 0, mayLoad = 0, mayStore = 1 in +def C_SSPOPCHK : RVC_SSInst<0b00101, GPRX5, "c.sspopchk">; +} // Predicates = [HasStdExtZicfiss, HasStdExtCOrZca] + +let Predicates = [HasStdExtZicfiss, HasStdExtC], Uses = [SSP], Defs = [SSP], + hasSideEffects = 0, mayLoad = 0, mayStore = 0 in +def C_SSINCP : RVInst16<(outs), (ins), "c.ssincp", "", [], InstFormatOther> { + let Inst{15-13} = 0b011; + let Inst{12} = 0; + let Inst{11-7} = 0b00011; + let Inst{6-2} = 0b00000; + let Inst{1-0} = 0b01; +} diff --git a/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp b/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp index 3e44cf4781f643c..7934da40ac4aadc 100644 --- a/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp +++ b/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp @@ -119,6 +119,9 @@ BitVector RISCVRegisterInfo::getReservedRegs(const MachineFunction &MF) const { markSuperRegs(Reserved, RISCV::FRM); markSuperRegs(Reserved, RISCV::FFLAGS); + // Shadow stack pointer. + markSuperRegs(Reserved, RISCV::SSP); + assert(checkAllSuperRegsMarked(Reserved)); return Reserved; } diff --git a/llvm/lib/Target/RISCV/RISCVRegisterInfo.td b/llvm/lib/Target/RISCV/RISCVRegisterInfo.td index 1a6145f92908134..87ad1d5ecd179e9 100644 --- a/llvm/lib/Target/RISCV/RISCVRegisterInfo.td +++ b/llvm/lib/Target/RISCV/RISCVRegisterInfo.td @@ -137,6 +137,8 @@ def GPR : GPRRegisterClass<(add (sequence "X%u", 10, 17), (sequence "X%u", 0, 4))>; def GPRX0 : GPRRegisterClass<(add X0)>; +def GPRX1 : GPRRegisterClass<(add X1)>; +def GPRX5 : GPRRegisterClass<(add X5)>; def GPRNoX0 : GPRRegisterClass<(sub GPR, X0)>; @@ -165,6 +167,10 @@ def SP : GPRRegisterClass<(add X2)>; def SR07 : GPRRegisterClass<(add (sequence "X%u", 8, 9), (sequence "X%u", 18, 23))>; +def GPRRA : RegisterClass<"RISCV", [XLenVT], 32, (add X1, X5)> { + let RegInfos = XLenRI; +} + // Floating point registers let RegAltNameIndices = [ABIRegAltName] in { def F0_H : RISCVReg16<0, "f0", ["ft0"]>, DwarfRegNum<[32]>; @@ -597,3 +603,6 @@ foreach m = LMULList in { // Special registers def FFLAGS : RISCVReg<0, "fflags">; def FRM : RISCVReg<0, "frm">; + +// Shadow Stack register +def SSP : RISCVReg<0, "ssp">; diff --git a/llvm/test/MC/RISCV/attribute-arch.s b/llvm/test/MC/RISCV/attribute-arch.s index bf40eda456edf13..4f201d2afde3164 100644 --- a/llvm/test/MC/RISCV/attribute-arch.s +++ b/llvm/test/MC/RISCV/attribute-arch.s @@ -305,3 +305,6 @@ .attribute arch, "rv32i_zicfilp0p2" # CHECK: attribute 5, "rv32i2p1_zicfilp0p2" + +.attribute arch, "rv32i_zicfiss0p3" +# CHECK: .attribute 5, "rv32i2p1_zicfiss0p3" diff --git a/llvm/test/MC/RISCV/rv32zicfiss-invalid.s b/llvm/test/MC/RISCV/rv32zicfiss-invalid.s new file mode 100644 index 000000000000000..6b4959043d0180b --- /dev/null +++ b/llvm/test/MC/RISCV/rv32zicfiss-invalid.s @@ -0,0 +1,20 @@ +# RUN: not llvm-mc %s -triple=riscv32 -mattr=+experimental-zicfiss,+c -riscv-no-aliases -show-encoding \ +# RUN: 2>&1 | FileCheck -check-prefixes=CHECK-ERR %s + +# CHECK-ERR: error: invalid operand for instruction +sslw a0 + +# CHECK-ERR: error: invalid operand for instruction +sspopchk a1 + +# CHECK-ERR: error: invalid operand for instruction +c.sspush t0 + +# CHECK-ERR: error: invalid operand for instruction +c.sspopchk ra + +# CHECK-ERR: error: invalid operand for instruction +sspush a0 + +# CHECK-ERR: error: invalid operand for instruction +ssrdp zero diff --git a/llvm/test/MC/RISCV/rv32zicfiss-valid.s b/llvm/test/MC/RISCV/rv32zicfiss-valid.s new file mode 100644 index 000000000000000..46a1d3103afac6e --- /dev/null +++ b/llvm/test/MC/RISCV/rv32zicfiss-valid.s @@ -0,0 +1,103 @@ +# RUN: llvm-mc %s -triple=riscv32 -mattr=+experimental-zicfiss,+c -riscv-no-aliases -show-encoding \ +# RUN: | FileCheck -check-prefixes=CHECK-ASM,CHECK-ASM-AND-OBJ %s +# RUN: llvm-mc -filetype=obj -triple=riscv32 -mattr=+experimental-zicfiss,+c < %s \ +# RUN: | llvm-objdump --mattr=+experimental-zicfiss -M no-aliases -d -r - \ +# RUN: | FileCheck --check-prefix=CHECK-ASM-AND-OBJ %s +# +# RUN: not llvm-mc -triple riscv32 -riscv-no-aliases -show-encoding < %s 2>&1 \ +# RUN: | FileCheck -check-prefixes=CHECK-NO-EXT %s + +# CHECK-ASM-AND-OBJ: sslw ra +# CHECK-ASM: encoding: [0xf3,0x40,0xc0,0x81] +# CHECK-NO-EXT: error: instruction requires the following: 'Zicfiss' (Shadow stack) +sslw x1 + +# CHECK-ASM-AND-OBJ: sslw ra +# CHECK-ASM: encoding: [0xf3,0x40,0xc0,0x81] +# CHECK-NO-EXT: error: instruction requires the following: 'Zicfiss' (Shadow stack) +sslw ra + +# CHECK-ASM-AND-OBJ: sslw t0 +# CHECK-ASM: encoding: [0xf3,0x42,0xc0,0x81] +# CHECK-NO-EXT: error: instruction requires the following: 'Zicfiss' (Shadow stack) +sslw x5 + +# CHECK-ASM-AND-OBJ: sslw t0 +# CHECK-ASM: encoding: [0xf3,0x42,0xc0,0x81] +# CHECK-NO-EXT: error: instruction requires the following: 'Zicfiss' (Shadow stack) +sslw t0 + +# CHECK-ASM-AND-OBJ: sspopchk ra +# CHECK-ASM: encoding: [0x73,0xc0,0xc0,0x81] +# CHECK-NO-EXT: error: instruction requires the following: 'Zicfiss' (Shadow stack) +sspopchk x1 + +# CHECK-ASM-AND-OBJ: sspopchk ra +# CHECK-ASM: encoding: [0x73,0xc0,0xc0,0x81] +# CHECK-NO-EXT: error: instruction requires the following: 'Zicfiss' (Shadow stack) +sspopchk ra + +# CHECK-ASM-AND-OBJ: sspopchk t0 +# CHECK-ASM: encoding: [0x73,0xc0,0xc2,0x81] +# CHECK-NO-EXT: error: instruction requires the following: 'Zicfiss' (Shadow stack) +sspopchk x5 + +# CHECK-ASM-AND-OBJ: sspopchk t0 +# CHECK-ASM: encoding: [0x73,0xc0,0xc2,0x81] +# CHECK-NO-EXT: error: instruction requires the following: 'Zicfiss' (Shadow stack) +sspopchk t0 + +# CHECK-ASM-AND-OBJ: ssincp +# CHECK-ASM: encoding: [0x73,0x40,0xc0,0x81] +# CHECK-NO-EXT: error: instruction requires the following: 'Zicfiss' (Shadow stack) +ssincp + +# CHECK-ASM-AND-OBJ: sspush ra +# CHECK-ASM: encoding: [0x73,0x40,0x10,0x82] +# CHECK-NO-EXT: error: instruction requires the following: 'Zicfiss' (Shadow stack) +sspush x1 + +# CHECK-ASM-AND-OBJ: sspush ra +# CHECK-ASM: encoding: [0x73,0x40,0x10,0x82] +# CHECK-NO-EXT: error: instruction requires the following: 'Zicfiss' (Shadow stack) +sspush ra + +# check-asm-and-obj: sspush t0 +# check-asm: encoding: [0x73,0x40,0x50,0x82] +# check-no-ext: error: instruction requires the following: 'Zicfiss' (Shadow stack) +sspush x5 + +# check-asm-and-obj: sspush t0 +# check-asm: encoding: [0x73,0x40,0x50,0x82] +# check-no-ext: error: instruction requires the following: 'Zicfiss' (Shadow stack) +sspush t0 + +# CHECK-ASM-AND-OBJ: ssrdp ra +# CHECK-ASM: encoding: [0xf3,0x40,0xd0,0x81] +# CHECK-NO-EXT: error: instruction requires the following: 'Zicfiss' (Shadow stack) +ssrdp ra + +# CHECK-ASM-AND-OBJ: c.sspush ra +# CHECK-ASM: encoding: [0x81,0x60] +# CHECK-NO-EXT: error: instruction requires the following: 'C' (Compressed Instructions) or 'Zca' (part of the C extension, excluding compressed floating point loads/stores), 'Zicfiss' (Shadow stack) +c.sspush x1 + +# CHECK-ASM-AND-OBJ: c.sspush ra +# CHECK-ASM: encoding: [0x81,0x60] +# CHECK-NO-EXT: error: instruction requires the following: 'C' (Compressed Instructions) or 'Zca' (part of the C extension, excluding compressed floating point loads/stores), 'Zicfiss' (Shadow stack) +c.sspush ra + +# CHECK-ASM-AND-OBJ: c.sspopchk t0 +# CHECK-ASM: encoding: [0x81,0x62] +# CHECK-NO-EXT: error: instruction requires the following: 'C' (Compressed Instructions) or 'Zca' (part of the C extension, excluding compressed floating point loads/stores), 'Zicfiss' (Shadow stack) +c.sspopchk x5 + +# CHECK-ASM-AND-OBJ: c.sspopchk t0 +# CHECK-ASM: encoding: [0x81,0x62] +# CHECK-NO-EXT: error: instruction requires the following: 'C' (Compressed Instructions) or 'Zca' (part of the C extension, excluding compressed floating point loads/stores), 'Zicfiss' (Shadow stack) +c.sspopchk t0 + +# CHECK-ASM-AND-OBJ: c.ssincp +# CHECK-ASM: encoding: [0x81,0x61] +# CHECK-NO-EXT: error: instruction requires the following: 'C' (Compressed Instructions), 'Zicfiss' (Shadow stack) +c.ssincp diff --git a/llvm/test/MC/RISCV/rv64zicfiss-invalid.s b/llvm/test/MC/RISCV/rv64zicfiss-invalid.s new file mode 100644 index 000000000000000..aef5e17e33aff9e --- /dev/null +++ b/llvm/test/MC/RISCV/rv64zicfiss-invalid.s @@ -0,0 +1,20 @@ +# RUN: not llvm-mc %s -triple=riscv64 -mattr=+experimental-zicfiss,+c -riscv-no-aliases -show-encoding \ +# RUN: 2>&1 | FileCheck -check-prefixes=CHECK-ERR %s + +# CHECK-ERR: error: invalid operand for instruction +ssld a0 + +# CHECK-ERR: error: invalid operand for instruction +sspopchk a1 + +# CHECK-ERR: error: invalid operand for instruction +c.sspush t0 + +# CHECK-ERR: error: invalid operand for instruction +c.sspopchk ra + +# CHECK-ERR: error: invalid operand for instruction +sspush a0 + +# CHECK-ERR: error: invalid operand for instruction +ssrdp zero diff --git a/llvm/test/MC/RISCV/rv64zicfiss-valid.s b/llvm/test/MC/RISCV/rv64zicfiss-valid.s new file mode 100644 index 000000000000000..8bba15cc3b22bec --- /dev/null +++ b/llvm/test/MC/RI... |
@llvm/pr-subscribers-backend-risc-v ChangesThe patch adds the instructions in Zicfiss extension. Zicfiss extension is to support shadow stack for control flow integrity. This patch is based on version 0.3.1. -- Patch is 23.44 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/66043.diff 14 Files Affected:
diff --git a/clang/test/Preprocessor/riscv-target-features.c b/clang/test/Preprocessor/riscv-target-features.c index 02b67dc7944ba88..163eba81543ee5b 100644 --- a/clang/test/Preprocessor/riscv-target-features.c +++ b/clang/test/Preprocessor/riscv-target-features.c @@ -113,6 +113,7 @@ // CHECK-NOT: __riscv_zfa {{.*$}} // CHECK-NOT: __riscv_zfbfmin {{.*$}} // CHECK-NOT: __riscv_zicfilp {{.*$}} +// CHECK-NOT: __riscv_zicfiss {{.*$}} // CHECK-NOT: __riscv_zicond {{.*$}} // CHECK-NOT: __riscv_ztso {{.*$}} // CHECK-NOT: __riscv_zvbb {{.*$}} @@ -1220,3 +1221,11 @@ // RUN: -march=rv64i_zve32x_zvkt1p0 -x c -E -dM %s \ // RUN: -o - | FileCheck --check-prefix=CHECK-ZVKT-EXT %s // CHECK-ZVKT-EXT: __riscv_zvkt 1000000{{$}} + +// RUN: %clang -target riscv32 -menable-experimental-extensions \ +// RUN: -march=rv32izicfiss0p3 -x c -E -dM %s \ +// RUN: -o - | FileCheck --check-prefix=CHECK-ZICFISS-EXT %s +// RUN: %clang -target riscv64 -menable-experimental-extensions \ +// RUN: -march=rv64izicfiss0p3 -x c -E -dM %s \ +// RUN: -o - | FileCheck --check-prefix=CHECK-ZICFISS-EXT %s +// CHECK-ZICFISS-EXT: __riscv_zicfiss 3000{{$}} diff --git a/llvm/docs/RISCVUsage.rst b/llvm/docs/RISCVUsage.rst index 8d12d58738c609a..31c55def0a7694a 100644 --- a/llvm/docs/RISCVUsage.rst +++ b/llvm/docs/RISCVUsage.rst @@ -205,6 +205,9 @@ The primary goal of experimental support is to assist in the process of ratifica ``experimental-zicfilp`` LLVM implements the `0.2 draft specification `__. +``experimental-zicfiss`` + LLVM implements the `0.3.1 draft specification `__. + ``experimental-zicond`` LLVM implements the `1.0-rc1 draft specification `__. diff --git a/llvm/lib/Support/RISCVISAInfo.cpp b/llvm/lib/Support/RISCVISAInfo.cpp index a02c9842e85839a..c414b62c5f31092 100644 --- a/llvm/lib/Support/RISCVISAInfo.cpp +++ b/llvm/lib/Support/RISCVISAInfo.cpp @@ -170,6 +170,8 @@ static const RISCVSupportedExtension SupportedExperimentalExtensions[] = { {"zfbfmin", RISCVExtensionVersion{0, 8}}, {"zicfilp", RISCVExtensionVersion{0, 2}}, + {"zicfiss", RISCVExtensionVersion{0, 3}}, + {"zicond", RISCVExtensionVersion{1, 0}}, {"ztso", RISCVExtensionVersion{0, 1}}, diff --git a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp index d561d90d3088c1a..14b3122f0fecbdb 100644 --- a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp +++ b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp @@ -74,6 +74,17 @@ static DecodeStatus DecodeGPRRegisterClass(MCInst &Inst, uint32_t RegNo, return MCDisassembler::Success; } +static DecodeStatus DecodeGPRRARegisterClass(MCInst &Inst, uint32_t RegNo, + uint64_t Address, + const MCDisassembler *Decoder) { + MCRegister Reg = RISCV::X0 + RegNo; + if (Reg != RISCV::X1 && Reg != RISCV::X5) + return MCDisassembler::Fail; + + Inst.addOperand(MCOperand::createReg(Reg)); + return MCDisassembler::Success; +} + static DecodeStatus DecodeFPR16RegisterClass(MCInst &Inst, uint32_t RegNo, uint64_t Address, const MCDisassembler *Decoder) { @@ -370,6 +381,10 @@ static DecodeStatus decodeZcmpRlist(MCInst &Inst, unsigned Imm, static DecodeStatus decodeZcmpSpimm(MCInst &Inst, unsigned Imm, uint64_t Address, const void *Decoder); +static DecodeStatus decodeCSSPushPopchk(MCInst &Inst, uint32_t Insn, + uint64_t Address, + const MCDisassembler *Decoder); + #include "RISCVGenDisassemblerTables.inc" static DecodeStatus decodeRVCInstrRdRs1ImmZero(MCInst &Inst, uint32_t Insn, @@ -384,6 +399,16 @@ static DecodeStatus decodeRVCInstrRdRs1ImmZero(MCInst &Inst, uint32_t Insn, return MCDisassembler::Success; } +static DecodeStatus decodeCSSPushPopchk(MCInst &Inst, uint32_t Insn, + uint64_t Address, + const MCDisassembler *Decoder) { + uint32_t Rs1 = fieldFromInstruction(Insn, 7, 5); + DecodeStatus Result = DecodeGPRRARegisterClass(Inst, Rs1, Address, Decoder); + (void)Result; + assert(Result == MCDisassembler::Success && "Invalid register"); + return MCDisassembler::Success; +} + static DecodeStatus decodeRVCInstrRdSImm(MCInst &Inst, uint32_t Insn, uint64_t Address, const MCDisassembler *Decoder) { @@ -527,6 +552,10 @@ DecodeStatus RISCVDisassembler::getInstruction(MCInst &MI, uint64_t &Size, "RV32Zdinx table (Double in Integer and rv32)"); TRY_TO_DECODE_FEATURE(RISCV::FeatureStdExtZfinx, DecoderTableRVZfinx32, "RVZfinx table (Float in Integer)"); + TRY_TO_DECODE(STI.hasFeature(RISCV::FeatureStdExtZicfiss) && + !STI.hasFeature(RISCV::Feature64Bit), + DecoderTableRV32Zicfiss32, + "RV32Zicfiss table (Shadow stack and rv32)"); TRY_TO_DECODE_FEATURE(RISCV::FeatureVendorXVentanaCondOps, DecoderTableXVentana32, "Ventana custom opcode table"); TRY_TO_DECODE_FEATURE(RISCV::FeatureVendorXTHeadBa, DecoderTableXTHeadBa32, diff --git a/llvm/lib/Target/RISCV/RISCVFeatures.td b/llvm/lib/Target/RISCV/RISCVFeatures.td index 6381263b37613b3..286320c6c52eb12 100644 --- a/llvm/lib/Target/RISCV/RISCVFeatures.td +++ b/llvm/lib/Target/RISCV/RISCVFeatures.td @@ -79,6 +79,13 @@ def HasStdExtZihintntl : Predicate<"Subtarget->hasStdExtZihintntl()">, AssemblerPredicate<(all_of FeatureStdExtZihintntl), "'Zihintntl' (Non-Temporal Locality Hints)">; +def FeatureStdExtZicfiss + : SubtargetFeature<"experimental-zicfiss", "HasStdExtZicfiss", "true", + "'Zicfiss' (Shadow stack)">; +def HasStdExtZicfiss : Predicate<"Subtarget->hasStdExtZicfiss()">, + AssemblerPredicate<(all_of FeatureStdExtZicfiss), + "'Zicfiss' (Shadow stack)">; + def FeatureStdExtZifencei : SubtargetFeature<"zifencei", "HasStdExtZifencei", "true", "'Zifencei' (fence.i)">; diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.td b/llvm/lib/Target/RISCV/RISCVInstrInfo.td index 582fe60fd0368e9..e6a8ba1fe2fc17d 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfo.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.td @@ -1970,14 +1970,15 @@ include "RISCVInstrInfoZk.td" include "RISCVInstrInfoV.td" include "RISCVInstrInfoZvk.td" -// Integer -include "RISCVInstrInfoZicbo.td" -include "RISCVInstrInfoZicond.td" - // Compressed include "RISCVInstrInfoC.td" include "RISCVInstrInfoZc.td" +// Integer +include "RISCVInstrInfoZicbo.td" +include "RISCVInstrInfoZicond.td" +include "RISCVInstrInfoZicfiss.td" + //===----------------------------------------------------------------------===// // Vendor extensions //===----------------------------------------------------------------------===// diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoZicfiss.td b/llvm/lib/Target/RISCV/RISCVInstrInfoZicfiss.td new file mode 100644 index 000000000000000..f787a260a8ca9da --- /dev/null +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoZicfiss.td @@ -0,0 +1,86 @@ +//===------ RISCVInstrInfoZicfiss.td - RISC-V Zicfiss -*- tablegen -*------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// Instruction class templates +//===----------------------------------------------------------------------===// + +class RVC_SSInst rs1val, RegisterClass reg_class, string opcodestr> : + RVInst16<(outs), (ins reg_class:$rs1), opcodestr, "$rs1", [], InstFormatOther> { + let Inst{15-13} = 0b011; + let Inst{12} = 0; + let Inst{11-7} = rs1val; + let Inst{6-2} = 0b00000; + let Inst{1-0} = 0b01; + let DecoderMethod = "decodeCSSPushPopchk"; +} + +//===----------------------------------------------------------------------===// +// Instructions +//===----------------------------------------------------------------------===// + +let Uses = [SSP], hasSideEffects = 0, mayLoad = 1, mayStore = 0 in { +let DecoderNamespace = "RV32Zicfiss", Predicates = [HasStdExtZicfiss, IsRV32] in +def SSLW : RVInstI<0b100, OPC_SYSTEM, (outs GPRRA:$rd), (ins), "sslw", "$rd"> { + let rs1 = 0; + let imm12 = 0b100000011100; +} + +let Predicates = [HasStdExtZicfiss, IsRV64] in +def SSLD : RVInstI<0b100, OPC_SYSTEM, (outs GPRRA:$rd), (ins), "ssld", "$rd"> { + let rs1 = 0; + let imm12 = 0b100000011100; +} +} // Uses = [SSP], hasSideEffects = 0, mayLoad = 1, mayStore = 0 + +let Predicates = [HasStdExtZicfiss] in { +let Uses = [SSP], hasSideEffects = 0, mayLoad = 1, mayStore = 0 in +def SSPOPCHK : RVInstI<0b100, OPC_SYSTEM, (outs), (ins GPRRA:$rs1), "sspopchk", + "$rs1"> { + let rd = 0; + let imm12 = 0b100000011100; +} // Uses = [SSP], hasSideEffects = 0, mayLoad = 1, mayStore = 0 + +let Uses = [SSP], hasSideEffects = 0, mayLoad = 0, mayStore = 0 in { +def SSINCP : RVInstI<0b100, OPC_SYSTEM, (outs), (ins), "ssincp", ""> { + let imm12 = 0b100000011100; + let rs1 = 0b00000; + let rd = 0b00000; +} + +def SSRDP : RVInstI<0b100, OPC_SYSTEM, (outs GPRNoX0:$rd), (ins), "ssrdp", "$rd"> { + let imm12 = 0b100000011101; + let rs1 = 0b00000; +} +} // Uses = [SSP], hasSideEffects = 0, mayLoad = 0, mayStore = 0 + +let Uses = [SSP], Defs = [SSP], hasSideEffects = 0, mayLoad = 0, mayStore = 1 in +def SSPUSH : RVInstR<0b1000001, 0b100, OPC_SYSTEM, (outs), (ins GPRRA:$rs2), + "sspush", "$rs2"> { + let rd = 0b00000; + let rs1 = 0b00000; +} +} // Predicates = [HasStdExtZicfiss] + +let Predicates = [HasStdExtZicfiss, HasStdExtCOrZca] in { +let Uses = [SSP], Defs = [SSP], hasSideEffects = 0, mayLoad = 0, mayStore = 1 in +def C_SSPUSH : RVC_SSInst<0b00001, GPRX1, "c.sspush">; + +let Uses = [SSP], Defs = [SSP], hasSideEffects = 0, mayLoad = 0, mayStore = 1 in +def C_SSPOPCHK : RVC_SSInst<0b00101, GPRX5, "c.sspopchk">; +} // Predicates = [HasStdExtZicfiss, HasStdExtCOrZca] + +let Predicates = [HasStdExtZicfiss, HasStdExtC], Uses = [SSP], Defs = [SSP], + hasSideEffects = 0, mayLoad = 0, mayStore = 0 in +def C_SSINCP : RVInst16<(outs), (ins), "c.ssincp", "", [], InstFormatOther> { + let Inst{15-13} = 0b011; + let Inst{12} = 0; + let Inst{11-7} = 0b00011; + let Inst{6-2} = 0b00000; + let Inst{1-0} = 0b01; +} diff --git a/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp b/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp index 3e44cf4781f643c..7934da40ac4aadc 100644 --- a/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp +++ b/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp @@ -119,6 +119,9 @@ BitVector RISCVRegisterInfo::getReservedRegs(const MachineFunction &MF) const { markSuperRegs(Reserved, RISCV::FRM); markSuperRegs(Reserved, RISCV::FFLAGS); + // Shadow stack pointer. + markSuperRegs(Reserved, RISCV::SSP); + assert(checkAllSuperRegsMarked(Reserved)); return Reserved; } diff --git a/llvm/lib/Target/RISCV/RISCVRegisterInfo.td b/llvm/lib/Target/RISCV/RISCVRegisterInfo.td index 1a6145f92908134..87ad1d5ecd179e9 100644 --- a/llvm/lib/Target/RISCV/RISCVRegisterInfo.td +++ b/llvm/lib/Target/RISCV/RISCVRegisterInfo.td @@ -137,6 +137,8 @@ def GPR : GPRRegisterClass<(add (sequence "X%u", 10, 17), (sequence "X%u", 0, 4))>; def GPRX0 : GPRRegisterClass<(add X0)>; +def GPRX1 : GPRRegisterClass<(add X1)>; +def GPRX5 : GPRRegisterClass<(add X5)>; def GPRNoX0 : GPRRegisterClass<(sub GPR, X0)>; @@ -165,6 +167,10 @@ def SP : GPRRegisterClass<(add X2)>; def SR07 : GPRRegisterClass<(add (sequence "X%u", 8, 9), (sequence "X%u", 18, 23))>; +def GPRRA : RegisterClass<"RISCV", [XLenVT], 32, (add X1, X5)> { + let RegInfos = XLenRI; +} + // Floating point registers let RegAltNameIndices = [ABIRegAltName] in { def F0_H : RISCVReg16<0, "f0", ["ft0"]>, DwarfRegNum<[32]>; @@ -597,3 +603,6 @@ foreach m = LMULList in { // Special registers def FFLAGS : RISCVReg<0, "fflags">; def FRM : RISCVReg<0, "frm">; + +// Shadow Stack register +def SSP : RISCVReg<0, "ssp">; diff --git a/llvm/test/MC/RISCV/attribute-arch.s b/llvm/test/MC/RISCV/attribute-arch.s index bf40eda456edf13..4f201d2afde3164 100644 --- a/llvm/test/MC/RISCV/attribute-arch.s +++ b/llvm/test/MC/RISCV/attribute-arch.s @@ -305,3 +305,6 @@ .attribute arch, "rv32i_zicfilp0p2" # CHECK: attribute 5, "rv32i2p1_zicfilp0p2" + +.attribute arch, "rv32i_zicfiss0p3" +# CHECK: .attribute 5, "rv32i2p1_zicfiss0p3" diff --git a/llvm/test/MC/RISCV/rv32zicfiss-invalid.s b/llvm/test/MC/RISCV/rv32zicfiss-invalid.s new file mode 100644 index 000000000000000..6b4959043d0180b --- /dev/null +++ b/llvm/test/MC/RISCV/rv32zicfiss-invalid.s @@ -0,0 +1,20 @@ +# RUN: not llvm-mc %s -triple=riscv32 -mattr=+experimental-zicfiss,+c -riscv-no-aliases -show-encoding \ +# RUN: 2>&1 | FileCheck -check-prefixes=CHECK-ERR %s + +# CHECK-ERR: error: invalid operand for instruction +sslw a0 + +# CHECK-ERR: error: invalid operand for instruction +sspopchk a1 + +# CHECK-ERR: error: invalid operand for instruction +c.sspush t0 + +# CHECK-ERR: error: invalid operand for instruction +c.sspopchk ra + +# CHECK-ERR: error: invalid operand for instruction +sspush a0 + +# CHECK-ERR: error: invalid operand for instruction +ssrdp zero diff --git a/llvm/test/MC/RISCV/rv32zicfiss-valid.s b/llvm/test/MC/RISCV/rv32zicfiss-valid.s new file mode 100644 index 000000000000000..46a1d3103afac6e --- /dev/null +++ b/llvm/test/MC/RISCV/rv32zicfiss-valid.s @@ -0,0 +1,103 @@ +# RUN: llvm-mc %s -triple=riscv32 -mattr=+experimental-zicfiss,+c -riscv-no-aliases -show-encoding \ +# RUN: | FileCheck -check-prefixes=CHECK-ASM,CHECK-ASM-AND-OBJ %s +# RUN: llvm-mc -filetype=obj -triple=riscv32 -mattr=+experimental-zicfiss,+c < %s \ +# RUN: | llvm-objdump --mattr=+experimental-zicfiss -M no-aliases -d -r - \ +# RUN: | FileCheck --check-prefix=CHECK-ASM-AND-OBJ %s +# +# RUN: not llvm-mc -triple riscv32 -riscv-no-aliases -show-encoding < %s 2>&1 \ +# RUN: | FileCheck -check-prefixes=CHECK-NO-EXT %s + +# CHECK-ASM-AND-OBJ: sslw ra +# CHECK-ASM: encoding: [0xf3,0x40,0xc0,0x81] +# CHECK-NO-EXT: error: instruction requires the following: 'Zicfiss' (Shadow stack) +sslw x1 + +# CHECK-ASM-AND-OBJ: sslw ra +# CHECK-ASM: encoding: [0xf3,0x40,0xc0,0x81] +# CHECK-NO-EXT: error: instruction requires the following: 'Zicfiss' (Shadow stack) +sslw ra + +# CHECK-ASM-AND-OBJ: sslw t0 +# CHECK-ASM: encoding: [0xf3,0x42,0xc0,0x81] +# CHECK-NO-EXT: error: instruction requires the following: 'Zicfiss' (Shadow stack) +sslw x5 + +# CHECK-ASM-AND-OBJ: sslw t0 +# CHECK-ASM: encoding: [0xf3,0x42,0xc0,0x81] +# CHECK-NO-EXT: error: instruction requires the following: 'Zicfiss' (Shadow stack) +sslw t0 + +# CHECK-ASM-AND-OBJ: sspopchk ra +# CHECK-ASM: encoding: [0x73,0xc0,0xc0,0x81] +# CHECK-NO-EXT: error: instruction requires the following: 'Zicfiss' (Shadow stack) +sspopchk x1 + +# CHECK-ASM-AND-OBJ: sspopchk ra +# CHECK-ASM: encoding: [0x73,0xc0,0xc0,0x81] +# CHECK-NO-EXT: error: instruction requires the following: 'Zicfiss' (Shadow stack) +sspopchk ra + +# CHECK-ASM-AND-OBJ: sspopchk t0 +# CHECK-ASM: encoding: [0x73,0xc0,0xc2,0x81] +# CHECK-NO-EXT: error: instruction requires the following: 'Zicfiss' (Shadow stack) +sspopchk x5 + +# CHECK-ASM-AND-OBJ: sspopchk t0 +# CHECK-ASM: encoding: [0x73,0xc0,0xc2,0x81] +# CHECK-NO-EXT: error: instruction requires the following: 'Zicfiss' (Shadow stack) +sspopchk t0 + +# CHECK-ASM-AND-OBJ: ssincp +# CHECK-ASM: encoding: [0x73,0x40,0xc0,0x81] +# CHECK-NO-EXT: error: instruction requires the following: 'Zicfiss' (Shadow stack) +ssincp + +# CHECK-ASM-AND-OBJ: sspush ra +# CHECK-ASM: encoding: [0x73,0x40,0x10,0x82] +# CHECK-NO-EXT: error: instruction requires the following: 'Zicfiss' (Shadow stack) +sspush x1 + +# CHECK-ASM-AND-OBJ: sspush ra +# CHECK-ASM: encoding: [0x73,0x40,0x10,0x82] +# CHECK-NO-EXT: error: instruction requires the following: 'Zicfiss' (Shadow stack) +sspush ra + +# check-asm-and-obj: sspush t0 +# check-asm: encoding: [0x73,0x40,0x50,0x82] +# check-no-ext: error: instruction requires the following: 'Zicfiss' (Shadow stack) +sspush x5 + +# check-asm-and-obj: sspush t0 +# check-asm: encoding: [0x73,0x40,0x50,0x82] +# check-no-ext: error: instruction requires the following: 'Zicfiss' (Shadow stack) +sspush t0 + +# CHECK-ASM-AND-OBJ: ssrdp ra +# CHECK-ASM: encoding: [0xf3,0x40,0xd0,0x81] +# CHECK-NO-EXT: error: instruction requires the following: 'Zicfiss' (Shadow stack) +ssrdp ra + +# CHECK-ASM-AND-OBJ: c.sspush ra +# CHECK-ASM: encoding: [0x81,0x60] +# CHECK-NO-EXT: error: instruction requires the following: 'C' (Compressed Instructions) or 'Zca' (part of the C extension, excluding compressed floating point loads/stores), 'Zicfiss' (Shadow stack) +c.sspush x1 + +# CHECK-ASM-AND-OBJ: c.sspush ra +# CHECK-ASM: encoding: [0x81,0x60] +# CHECK-NO-EXT: error: instruction requires the following: 'C' (Compressed Instructions) or 'Zca' (part of the C extension, excluding compressed floating point loads/stores), 'Zicfiss' (Shadow stack) +c.sspush ra + +# CHECK-ASM-AND-OBJ: c.sspopchk t0 +# CHECK-ASM: encoding: [0x81,0x62] +# CHECK-NO-EXT: error: instruction requires the following: 'C' (Compressed Instructions) or 'Zca' (part of the C extension, excluding compressed floating point loads/stores), 'Zicfiss' (Shadow stack) +c.sspopchk x5 + +# CHECK-ASM-AND-OBJ: c.sspopchk t0 +# CHECK-ASM: encoding: [0x81,0x62] +# CHECK-NO-EXT: error: instruction requires the following: 'C' (Compressed Instructions) or 'Zca' (part of the C extension, excluding compressed floating point loads/stores), 'Zicfiss' (Shadow stack) +c.sspopchk t0 + +# CHECK-ASM-AND-OBJ: c.ssincp +# CHECK-ASM: encoding: [0x81,0x61] +# CHECK-NO-EXT: error: instruction requires the following: 'C' (Compressed Instructions), 'Zicfiss' (Shadow stack) +c.ssincp diff --git a/llvm/test/MC/RISCV/rv64zicfiss-invalid.s b/llvm/test/MC/RISCV/rv64zicfiss-invalid.s new file mode 100644 index 000000000000000..aef5e17e33aff9e --- /dev/null +++ b/llvm/test/MC/RISCV/rv64zicfiss-invalid.s @@ -0,0 +1,20 @@ +# RUN: not llvm-mc %s -triple=riscv64 -mattr=+experimental-zicfiss,+c -riscv-no-aliases -show-encoding \ +# RUN: 2>&1 | FileCheck -check-prefixes=CHECK-ERR %s + +# CHECK-ERR: error: invalid operand for instruction +ssld a0 + +# CHECK-ERR: error: invalid operand for instruction +sspopchk a1 + +# CHECK-ERR: error: invalid operand for instruction +c.sspush t0 + +# CHECK-ERR: error: invalid operand for instruction +c.sspopchk ra + +# CHECK-ERR: error: invalid operand for instruction +sspush a0 + +# CHECK-ERR: error: invalid operand for instruction +ssrdp zero diff --git a/llvm/test/MC/RISCV/rv64zicfiss-valid.s b/llvm/test/MC/RISCV/rv64zicfiss-valid.s new file mode 100644 index 000000000000000..8bba15cc3b22bec --- /dev/null +++ b/llvm/test/MC/RI... |
@@ -165,6 +167,10 @@ def SP : GPRRegisterClass<(add X2)>; | |||
def SR07 : GPRRegisterClass<(add (sequence "X%u", 8, 9), | |||
(sequence "X%u", 18, 23))>; | |||
|
|||
def GPRRA : RegisterClass<"RISCV", [XLenVT], 32, (add X1, X5)> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is GPRX1X5 better?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
@llvm/pr-subscribers-llvm-support ChangesThe patch adds the instructions in Zicfiss extension. Zicfiss extension is to support shadow stack for control flow integrity. This patch is based on version 0.3.1. Patch is 23.46 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/66043.diff 14 Files Affected:
diff --git a/clang/test/Preprocessor/riscv-target-features.c b/clang/test/Preprocessor/riscv-target-features.c
index 02b67dc7944ba88..163eba81543ee5b 100644
--- a/clang/test/Preprocessor/riscv-target-features.c
+++ b/clang/test/Preprocessor/riscv-target-features.c
@@ -113,6 +113,7 @@
// CHECK-NOT: __riscv_zfa {{.*$}}
// CHECK-NOT: __riscv_zfbfmin {{.*$}}
// CHECK-NOT: __riscv_zicfilp {{.*$}}
+// CHECK-NOT: __riscv_zicfiss {{.*$}}
// CHECK-NOT: __riscv_zicond {{.*$}}
// CHECK-NOT: __riscv_ztso {{.*$}}
// CHECK-NOT: __riscv_zvbb {{.*$}}
@@ -1220,3 +1221,11 @@
// RUN: -march=rv64i_zve32x_zvkt1p0 -x c -E -dM %s \
// RUN: -o - | FileCheck --check-prefix=CHECK-ZVKT-EXT %s
// CHECK-ZVKT-EXT: __riscv_zvkt 1000000{{$}}
+
+// RUN: %clang -target riscv32 -menable-experimental-extensions \
+// RUN: -march=rv32izicfiss0p3 -x c -E -dM %s \
+// RUN: -o - | FileCheck --check-prefix=CHECK-ZICFISS-EXT %s
+// RUN: %clang -target riscv64 -menable-experimental-extensions \
+// RUN: -march=rv64izicfiss0p3 -x c -E -dM %s \
+// RUN: -o - | FileCheck --check-prefix=CHECK-ZICFISS-EXT %s
+// CHECK-ZICFISS-EXT: __riscv_zicfiss 3000{{$}}
diff --git a/llvm/docs/RISCVUsage.rst b/llvm/docs/RISCVUsage.rst
index 8d12d58738c609a..31c55def0a7694a 100644
--- a/llvm/docs/RISCVUsage.rst
+++ b/llvm/docs/RISCVUsage.rst
@@ -205,6 +205,9 @@ The primary goal of experimental support is to assist in the process of ratifica
``experimental-zicfilp``
LLVM implements the `0.2 draft specification <https://github.com/riscv/riscv-cfi/releases/tag/v0.2.0>`__.
+``experimental-zicfiss``
+ LLVM implements the `0.3.1 draft specification <https://github.com/riscv/riscv-cfi/releases/tag/v0.3.1>`__.
+
``experimental-zicond``
LLVM implements the `1.0-rc1 draft specification <https://github.com/riscv/riscv-zicond/releases/tag/v1.0-rc1>`__.
diff --git a/llvm/lib/Support/RISCVISAInfo.cpp b/llvm/lib/Support/RISCVISAInfo.cpp
index a02c9842e85839a..c414b62c5f31092 100644
--- a/llvm/lib/Support/RISCVISAInfo.cpp
+++ b/llvm/lib/Support/RISCVISAInfo.cpp
@@ -170,6 +170,8 @@ static const RISCVSupportedExtension SupportedExperimentalExtensions[] = {
{"zfbfmin", RISCVExtensionVersion{0, 8}},
{"zicfilp", RISCVExtensionVersion{0, 2}},
+ {"zicfiss", RISCVExtensionVersion{0, 3}},
+
{"zicond", RISCVExtensionVersion{1, 0}},
{"ztso", RISCVExtensionVersion{0, 1}},
diff --git a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
index d561d90d3088c1a..9f088b6f3bf6492 100644
--- a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
+++ b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
@@ -74,6 +74,17 @@ static DecodeStatus DecodeGPRRegisterClass(MCInst &Inst, uint32_t RegNo,
return MCDisassembler::Success;
}
+static DecodeStatus DecodeGPRX1X5RegisterClass(MCInst &Inst, uint32_t RegNo,
+ uint64_t Address,
+ const MCDisassembler *Decoder) {
+ MCRegister Reg = RISCV::X0 + RegNo;
+ if (Reg != RISCV::X1 && Reg != RISCV::X5)
+ return MCDisassembler::Fail;
+
+ Inst.addOperand(MCOperand::createReg(Reg));
+ return MCDisassembler::Success;
+}
+
static DecodeStatus DecodeFPR16RegisterClass(MCInst &Inst, uint32_t RegNo,
uint64_t Address,
const MCDisassembler *Decoder) {
@@ -370,6 +381,10 @@ static DecodeStatus decodeZcmpRlist(MCInst &Inst, unsigned Imm,
static DecodeStatus decodeZcmpSpimm(MCInst &Inst, unsigned Imm,
uint64_t Address, const void *Decoder);
+static DecodeStatus decodeCSSPushPopchk(MCInst &Inst, uint32_t Insn,
+ uint64_t Address,
+ const MCDisassembler *Decoder);
+
#include "RISCVGenDisassemblerTables.inc"
static DecodeStatus decodeRVCInstrRdRs1ImmZero(MCInst &Inst, uint32_t Insn,
@@ -384,6 +399,16 @@ static DecodeStatus decodeRVCInstrRdRs1ImmZero(MCInst &Inst, uint32_t Insn,
return MCDisassembler::Success;
}
+static DecodeStatus decodeCSSPushPopchk(MCInst &Inst, uint32_t Insn,
+ uint64_t Address,
+ const MCDisassembler *Decoder) {
+ uint32_t Rs1 = fieldFromInstruction(Insn, 7, 5);
+ DecodeStatus Result = DecodeGPRX1X5RegisterClass(Inst, Rs1, Address, Decoder);
+ (void)Result;
+ assert(Result == MCDisassembler::Success && "Invalid register");
+ return MCDisassembler::Success;
+}
+
static DecodeStatus decodeRVCInstrRdSImm(MCInst &Inst, uint32_t Insn,
uint64_t Address,
const MCDisassembler *Decoder) {
@@ -527,6 +552,10 @@ DecodeStatus RISCVDisassembler::getInstruction(MCInst &MI, uint64_t &Size,
"RV32Zdinx table (Double in Integer and rv32)");
TRY_TO_DECODE_FEATURE(RISCV::FeatureStdExtZfinx, DecoderTableRVZfinx32,
"RVZfinx table (Float in Integer)");
+ TRY_TO_DECODE(STI.hasFeature(RISCV::FeatureStdExtZicfiss) &&
+ !STI.hasFeature(RISCV::Feature64Bit),
+ DecoderTableRV32Zicfiss32,
+ "RV32Zicfiss table (Shadow stack and rv32)");
TRY_TO_DECODE_FEATURE(RISCV::FeatureVendorXVentanaCondOps,
DecoderTableXVentana32, "Ventana custom opcode table");
TRY_TO_DECODE_FEATURE(RISCV::FeatureVendorXTHeadBa, DecoderTableXTHeadBa32,
diff --git a/llvm/lib/Target/RISCV/RISCVFeatures.td b/llvm/lib/Target/RISCV/RISCVFeatures.td
index 6381263b37613b3..286320c6c52eb12 100644
--- a/llvm/lib/Target/RISCV/RISCVFeatures.td
+++ b/llvm/lib/Target/RISCV/RISCVFeatures.td
@@ -79,6 +79,13 @@ def HasStdExtZihintntl : Predicate<"Subtarget->hasStdExtZihintntl()">,
AssemblerPredicate<(all_of FeatureStdExtZihintntl),
"'Zihintntl' (Non-Temporal Locality Hints)">;
+def FeatureStdExtZicfiss
+ : SubtargetFeature<"experimental-zicfiss", "HasStdExtZicfiss", "true",
+ "'Zicfiss' (Shadow stack)">;
+def HasStdExtZicfiss : Predicate<"Subtarget->hasStdExtZicfiss()">,
+ AssemblerPredicate<(all_of FeatureStdExtZicfiss),
+ "'Zicfiss' (Shadow stack)">;
+
def FeatureStdExtZifencei
: SubtargetFeature<"zifencei", "HasStdExtZifencei", "true",
"'Zifencei' (fence.i)">;
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.td b/llvm/lib/Target/RISCV/RISCVInstrInfo.td
index 582fe60fd0368e9..e6a8ba1fe2fc17d 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfo.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.td
@@ -1970,14 +1970,15 @@ include "RISCVInstrInfoZk.td"
include "RISCVInstrInfoV.td"
include "RISCVInstrInfoZvk.td"
-// Integer
-include "RISCVInstrInfoZicbo.td"
-include "RISCVInstrInfoZicond.td"
-
// Compressed
include "RISCVInstrInfoC.td"
include "RISCVInstrInfoZc.td"
+// Integer
+include "RISCVInstrInfoZicbo.td"
+include "RISCVInstrInfoZicond.td"
+include "RISCVInstrInfoZicfiss.td"
+
//===----------------------------------------------------------------------===//
// Vendor extensions
//===----------------------------------------------------------------------===//
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoZicfiss.td b/llvm/lib/Target/RISCV/RISCVInstrInfoZicfiss.td
new file mode 100644
index 000000000000000..95864664e43f2ae
--- /dev/null
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoZicfiss.td
@@ -0,0 +1,86 @@
+//===------ RISCVInstrInfoZicfiss.td - RISC-V Zicfiss -*- tablegen -*------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+// Instruction class templates
+//===----------------------------------------------------------------------===//
+
+class RVC_SSInst<bits<5> rs1val, RegisterClass reg_class, string opcodestr> :
+ RVInst16<(outs), (ins reg_class:$rs1), opcodestr, "$rs1", [], InstFormatOther> {
+ let Inst{15-13} = 0b011;
+ let Inst{12} = 0;
+ let Inst{11-7} = rs1val;
+ let Inst{6-2} = 0b00000;
+ let Inst{1-0} = 0b01;
+ let DecoderMethod = "decodeCSSPushPopchk";
+}
+
+//===----------------------------------------------------------------------===//
+// Instructions
+//===----------------------------------------------------------------------===//
+
+let Uses = [SSP], hasSideEffects = 0, mayLoad = 1, mayStore = 0 in {
+let DecoderNamespace = "RV32Zicfiss", Predicates = [HasStdExtZicfiss, IsRV32] in
+def SSLW : RVInstI<0b100, OPC_SYSTEM, (outs GPRX1X5:$rd), (ins), "sslw", "$rd"> {
+ let rs1 = 0;
+ let imm12 = 0b100000011100;
+}
+
+let Predicates = [HasStdExtZicfiss, IsRV64] in
+def SSLD : RVInstI<0b100, OPC_SYSTEM, (outs GPRX1X5:$rd), (ins), "ssld", "$rd"> {
+ let rs1 = 0;
+ let imm12 = 0b100000011100;
+}
+} // Uses = [SSP], hasSideEffects = 0, mayLoad = 1, mayStore = 0
+
+let Predicates = [HasStdExtZicfiss] in {
+let Uses = [SSP], hasSideEffects = 0, mayLoad = 1, mayStore = 0 in
+def SSPOPCHK : RVInstI<0b100, OPC_SYSTEM, (outs), (ins GPRX1X5:$rs1), "sspopchk",
+ "$rs1"> {
+ let rd = 0;
+ let imm12 = 0b100000011100;
+} // Uses = [SSP], hasSideEffects = 0, mayLoad = 1, mayStore = 0
+
+let Uses = [SSP], hasSideEffects = 0, mayLoad = 0, mayStore = 0 in {
+def SSINCP : RVInstI<0b100, OPC_SYSTEM, (outs), (ins), "ssincp", ""> {
+ let imm12 = 0b100000011100;
+ let rs1 = 0b00000;
+ let rd = 0b00000;
+}
+
+def SSRDP : RVInstI<0b100, OPC_SYSTEM, (outs GPRNoX0:$rd), (ins), "ssrdp", "$rd"> {
+ let imm12 = 0b100000011101;
+ let rs1 = 0b00000;
+}
+} // Uses = [SSP], hasSideEffects = 0, mayLoad = 0, mayStore = 0
+
+let Uses = [SSP], Defs = [SSP], hasSideEffects = 0, mayLoad = 0, mayStore = 1 in
+def SSPUSH : RVInstR<0b1000001, 0b100, OPC_SYSTEM, (outs), (ins GPRX1X5:$rs2),
+ "sspush", "$rs2"> {
+ let rd = 0b00000;
+ let rs1 = 0b00000;
+}
+} // Predicates = [HasStdExtZicfiss]
+
+let Predicates = [HasStdExtZicfiss, HasStdExtCOrZca] in {
+let Uses = [SSP], Defs = [SSP], hasSideEffects = 0, mayLoad = 0, mayStore = 1 in
+def C_SSPUSH : RVC_SSInst<0b00001, GPRX1, "c.sspush">;
+
+let Uses = [SSP], Defs = [SSP], hasSideEffects = 0, mayLoad = 0, mayStore = 1 in
+def C_SSPOPCHK : RVC_SSInst<0b00101, GPRX5, "c.sspopchk">;
+} // Predicates = [HasStdExtZicfiss, HasStdExtCOrZca]
+
+let Predicates = [HasStdExtZicfiss, HasStdExtC], Uses = [SSP], Defs = [SSP],
+ hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
+def C_SSINCP : RVInst16<(outs), (ins), "c.ssincp", "", [], InstFormatOther> {
+ let Inst{15-13} = 0b011;
+ let Inst{12} = 0;
+ let Inst{11-7} = 0b00011;
+ let Inst{6-2} = 0b00000;
+ let Inst{1-0} = 0b01;
+}
diff --git a/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp b/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp
index 3e44cf4781f643c..7934da40ac4aadc 100644
--- a/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp
+++ b/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp
@@ -119,6 +119,9 @@ BitVector RISCVRegisterInfo::getReservedRegs(const MachineFunction &MF) const {
markSuperRegs(Reserved, RISCV::FRM);
markSuperRegs(Reserved, RISCV::FFLAGS);
+ // Shadow stack pointer.
+ markSuperRegs(Reserved, RISCV::SSP);
+
assert(checkAllSuperRegsMarked(Reserved));
return Reserved;
}
diff --git a/llvm/lib/Target/RISCV/RISCVRegisterInfo.td b/llvm/lib/Target/RISCV/RISCVRegisterInfo.td
index 1a6145f92908134..5a6ad940398cac1 100644
--- a/llvm/lib/Target/RISCV/RISCVRegisterInfo.td
+++ b/llvm/lib/Target/RISCV/RISCVRegisterInfo.td
@@ -137,6 +137,8 @@ def GPR : GPRRegisterClass<(add (sequence "X%u", 10, 17),
(sequence "X%u", 0, 4))>;
def GPRX0 : GPRRegisterClass<(add X0)>;
+def GPRX1 : GPRRegisterClass<(add X1)>;
+def GPRX5 : GPRRegisterClass<(add X5)>;
def GPRNoX0 : GPRRegisterClass<(sub GPR, X0)>;
@@ -165,6 +167,10 @@ def SP : GPRRegisterClass<(add X2)>;
def SR07 : GPRRegisterClass<(add (sequence "X%u", 8, 9),
(sequence "X%u", 18, 23))>;
+def GPRX1X5 : RegisterClass<"RISCV", [XLenVT], 32, (add X1, X5)> {
+ let RegInfos = XLenRI;
+}
+
// Floating point registers
let RegAltNameIndices = [ABIRegAltName] in {
def F0_H : RISCVReg16<0, "f0", ["ft0"]>, DwarfRegNum<[32]>;
@@ -597,3 +603,6 @@ foreach m = LMULList in {
// Special registers
def FFLAGS : RISCVReg<0, "fflags">;
def FRM : RISCVReg<0, "frm">;
+
+// Shadow Stack register
+def SSP : RISCVReg<0, "ssp">;
diff --git a/llvm/test/MC/RISCV/attribute-arch.s b/llvm/test/MC/RISCV/attribute-arch.s
index bf40eda456edf13..4f201d2afde3164 100644
--- a/llvm/test/MC/RISCV/attribute-arch.s
+++ b/llvm/test/MC/RISCV/attribute-arch.s
@@ -305,3 +305,6 @@
.attribute arch, "rv32i_zicfilp0p2"
# CHECK: attribute 5, "rv32i2p1_zicfilp0p2"
+
+.attribute arch, "rv32i_zicfiss0p3"
+# CHECK: .attribute 5, "rv32i2p1_zicfiss0p3"
diff --git a/llvm/test/MC/RISCV/rv32zicfiss-invalid.s b/llvm/test/MC/RISCV/rv32zicfiss-invalid.s
new file mode 100644
index 000000000000000..6b4959043d0180b
--- /dev/null
+++ b/llvm/test/MC/RISCV/rv32zicfiss-invalid.s
@@ -0,0 +1,20 @@
+# RUN: not llvm-mc %s -triple=riscv32 -mattr=+experimental-zicfiss,+c -riscv-no-aliases -show-encoding \
+# RUN: 2>&1 | FileCheck -check-prefixes=CHECK-ERR %s
+
+# CHECK-ERR: error: invalid operand for instruction
+sslw a0
+
+# CHECK-ERR: error: invalid operand for instruction
+sspopchk a1
+
+# CHECK-ERR: error: invalid operand for instruction
+c.sspush t0
+
+# CHECK-ERR: error: invalid operand for instruction
+c.sspopchk ra
+
+# CHECK-ERR: error: invalid operand for instruction
+sspush a0
+
+# CHECK-ERR: error: invalid operand for instruction
+ssrdp zero
diff --git a/llvm/test/MC/RISCV/rv32zicfiss-valid.s b/llvm/test/MC/RISCV/rv32zicfiss-valid.s
new file mode 100644
index 000000000000000..46a1d3103afac6e
--- /dev/null
+++ b/llvm/test/MC/RISCV/rv32zicfiss-valid.s
@@ -0,0 +1,103 @@
+# RUN: llvm-mc %s -triple=riscv32 -mattr=+experimental-zicfiss,+c -riscv-no-aliases -show-encoding \
+# RUN: | FileCheck -check-prefixes=CHECK-ASM,CHECK-ASM-AND-OBJ %s
+# RUN: llvm-mc -filetype=obj -triple=riscv32 -mattr=+experimental-zicfiss,+c < %s \
+# RUN: | llvm-objdump --mattr=+experimental-zicfiss -M no-aliases -d -r - \
+# RUN: | FileCheck --check-prefix=CHECK-ASM-AND-OBJ %s
+#
+# RUN: not llvm-mc -triple riscv32 -riscv-no-aliases -show-encoding < %s 2>&1 \
+# RUN: | FileCheck -check-prefixes=CHECK-NO-EXT %s
+
+# CHECK-ASM-AND-OBJ: sslw ra
+# CHECK-ASM: encoding: [0xf3,0x40,0xc0,0x81]
+# CHECK-NO-EXT: error: instruction requires the following: 'Zicfiss' (Shadow stack)
+sslw x1
+
+# CHECK-ASM-AND-OBJ: sslw ra
+# CHECK-ASM: encoding: [0xf3,0x40,0xc0,0x81]
+# CHECK-NO-EXT: error: instruction requires the following: 'Zicfiss' (Shadow stack)
+sslw ra
+
+# CHECK-ASM-AND-OBJ: sslw t0
+# CHECK-ASM: encoding: [0xf3,0x42,0xc0,0x81]
+# CHECK-NO-EXT: error: instruction requires the following: 'Zicfiss' (Shadow stack)
+sslw x5
+
+# CHECK-ASM-AND-OBJ: sslw t0
+# CHECK-ASM: encoding: [0xf3,0x42,0xc0,0x81]
+# CHECK-NO-EXT: error: instruction requires the following: 'Zicfiss' (Shadow stack)
+sslw t0
+
+# CHECK-ASM-AND-OBJ: sspopchk ra
+# CHECK-ASM: encoding: [0x73,0xc0,0xc0,0x81]
+# CHECK-NO-EXT: error: instruction requires the following: 'Zicfiss' (Shadow stack)
+sspopchk x1
+
+# CHECK-ASM-AND-OBJ: sspopchk ra
+# CHECK-ASM: encoding: [0x73,0xc0,0xc0,0x81]
+# CHECK-NO-EXT: error: instruction requires the following: 'Zicfiss' (Shadow stack)
+sspopchk ra
+
+# CHECK-ASM-AND-OBJ: sspopchk t0
+# CHECK-ASM: encoding: [0x73,0xc0,0xc2,0x81]
+# CHECK-NO-EXT: error: instruction requires the following: 'Zicfiss' (Shadow stack)
+sspopchk x5
+
+# CHECK-ASM-AND-OBJ: sspopchk t0
+# CHECK-ASM: encoding: [0x73,0xc0,0xc2,0x81]
+# CHECK-NO-EXT: error: instruction requires the following: 'Zicfiss' (Shadow stack)
+sspopchk t0
+
+# CHECK-ASM-AND-OBJ: ssincp
+# CHECK-ASM: encoding: [0x73,0x40,0xc0,0x81]
+# CHECK-NO-EXT: error: instruction requires the following: 'Zicfiss' (Shadow stack)
+ssincp
+
+# CHECK-ASM-AND-OBJ: sspush ra
+# CHECK-ASM: encoding: [0x73,0x40,0x10,0x82]
+# CHECK-NO-EXT: error: instruction requires the following: 'Zicfiss' (Shadow stack)
+sspush x1
+
+# CHECK-ASM-AND-OBJ: sspush ra
+# CHECK-ASM: encoding: [0x73,0x40,0x10,0x82]
+# CHECK-NO-EXT: error: instruction requires the following: 'Zicfiss' (Shadow stack)
+sspush ra
+
+# check-asm-and-obj: sspush t0
+# check-asm: encoding: [0x73,0x40,0x50,0x82]
+# check-no-ext: error: instruction requires the following: 'Zicfiss' (Shadow stack)
+sspush x5
+
+# check-asm-and-obj: sspush t0
+# check-asm: encoding: [0x73,0x40,0x50,0x82]
+# check-no-ext: error: instruction requires the following: 'Zicfiss' (Shadow stack)
+sspush t0
+
+# CHECK-ASM-AND-OBJ: ssrdp ra
+# CHECK-ASM: encoding: [0xf3,0x40,0xd0,0x81]
+# CHECK-NO-EXT: error: instruction requires the following: 'Zicfiss' (Shadow stack)
+ssrdp ra
+
+# CHECK-ASM-AND-OBJ: c.sspush ra
+# CHECK-ASM: encoding: [0x81,0x60]
+# CHECK-NO-EXT: error: instruction requires the following: 'C' (Compressed Instructions) or 'Zca' (part of the C extension, excluding compressed floating point loads/stores), 'Zicfiss' (Shadow stack)
+c.sspush x1
+
+# CHECK-ASM-AND-OBJ: c.sspush ra
+# CHECK-ASM: encoding: [0x81,0x60]
+# CHECK-NO-EXT: error: instruction requires the following: 'C' (Compressed Instructions) or 'Zca' (part of the C extension, excluding compressed floating point loads/stores), 'Zicfiss' (Shadow stack)
+c.sspush ra
+
+# CHECK-ASM-AND-OBJ: c.sspopchk t0
+# CHECK-ASM: encoding: [0x81,0x62]
+# CHECK-NO-EXT: error: instruction requires the following: 'C' (Compressed Instructions) or 'Zca' (part of the C extension, excluding compressed floating point loads/stores), 'Zicfiss' (Shadow stack)
+c.sspopchk x5
+
+# CHECK-ASM-AND-OBJ: c.sspopchk t0
+# CHECK-ASM: encoding: [0x81,0x62]
+# CHECK-NO-EXT: error: instruction requires the following: 'C' (Compressed Instructions) or 'Zca' (part of the C extension, excluding compressed floating point loads/stores), 'Zicfiss' (Shadow stack)
+c.sspopchk t0
+
+# CHECK-ASM-AND-OBJ: c.ssincp
+# CHECK-ASM: encoding: [0x81,0x61]
+# CHECK-NO-EXT: error: instruction requires the following: 'C' (Compressed Instructions), 'Zicfiss' (Shadow stack)
+c.ssincp
diff --git a/llvm/test/MC/RISCV/rv64zicfiss-invalid.s b/llvm/test/MC/RISCV/rv64zicfiss-invalid.s
new file mode 100644
index 000000000000000..aef5e17e33aff9e
--- /dev/null
+++ b/llvm/test/MC/RISCV/rv64zicfiss-invalid.s
@@ -0,0 +1,20 @@
+# RUN: not llvm-mc %s -triple=riscv64 -mattr=+experimental-zicfiss,+c -riscv-no-aliases -show-encoding \
+# RUN: 2>&1 | FileCheck -check-prefixes=CHECK-ERR %s
+
+# CHECK-ERR: error: invalid operand for instruction
+ssld a0
+
+# CHECK-ERR: error: invalid operand for instruction
+sspopchk a1
+
+# CHECK-ERR: error: invalid operand for instruction
+c.sspush t0
+
+# CHECK-ERR: error: invalid operand for instruction
+c.sspopchk ra
+
+# CHECK-ERR: error: invalid operand for instruction
+sspush a0
+
+# CHECK-ERR: error: invalid operand for instruction
+ssrdp zero
diff --git a/llvm/test/MC/RISCV/rv64zicfiss-valid.s b/llvm/test/MC/RISCV/rv64zicfiss-valid.s
new file mode 100644
index 000000000000000..8bba15cc3b22bec
--- /dev/null
+++ b/llvm/test/MC/RISCV/rv64zicfiss-valid.s
@@ -0,0 +1,103 @@
+# RUN: llvm-mc %s -triple=riscv64 -mattr=+experimental-zicfiss,+c -riscv-no-aliases -show-encoding \
+# RUN: | FileCheck -check-prefixes=CHECK-ASM,CHECK-ASM-AND-OBJ %s
+# RUN: llvm-mc -filetype=obj -triple=riscv64 -mattr=+experimental-zicfiss,+c < %s \
+# RUN: | llvm-objdump --mattr=+experimental-zicfiss -M no-aliases -d -r - \
+# RUN: | FileCheck --check-prefix=CHECK-ASM-AND-OBJ %s
+#
+# RUN: not llvm-mc -triple riscv64 -riscv-no-aliases -show-encoding < %s 2>&1 \
+# RUN: | FileCheck -check-prefixes=CHECK-NO-EXT %s
+
+# CHECK-ASM-AND-OBJ: ssld ra
+# CHECK-ASM: encoding: [0xf3,0x40,0xc0,0x81]
+# CHECK-NO-EXT: error: instruction requires the following: 'Zicfiss' (Shadow stack)
+ssld x1
+
+# CHECK-ASM-AND-OBJ: ssld ra
+# CHECK-ASM: encoding: [0xf3,0x40,0xc0,0x81]
+# CHECK-NO-E...
[truncated]
|
} // Uses = [SSP], hasSideEffects = 0, mayLoad = 1, mayStore = 0 | ||
|
||
let Uses = [SSP], hasSideEffects = 0, mayLoad = 0, mayStore = 0 in { | ||
def SSINCP : RVInstI<0b100, OPC_SYSTEM, (outs), (ins), "ssincp", ""> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should SSINCP also have Defs = [SSP]
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
Rebase and bump to 0.4 |
Rebase and ping. |
@@ -165,6 +167,10 @@ def SP : GPRRegisterClass<(add X2)>; | |||
def SR07 : GPRRegisterClass<(add (sequence "X%u", 8, 9), | |||
(sequence "X%u", 18, 23))>; | |||
|
|||
def GPRX1X5 : RegisterClass<"RISCV", [XLenVT], 32, (add X1, X5)> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please use GPRRegisterClass
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
Ping. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
Should this be rebased on Zimop(#75182) commit? Though I don't know why it has been merged yet... |
It seems that the author of Zimop implementation doesn't have commit access. @yetingk Would you mind to commit it and rebase your PR on that? It will make this PR simpler. |
Sure. |
Rebase.
It's weird that |
|
||
let Predicates = [HasStdExtZicfiss] in { | ||
let Uses = [SSP], Defs = [SSP], hasSideEffects = 0, mayLoad = 1, mayStore = 0 in | ||
def SSPOPCHK : RVInstI<0b100, OPC_SYSTEM, (outs), (ins GPRX1X5:$rs1), "sspopchk", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should these instructions be aliases of MOPs now?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
They should use same encoding as some instructions of Zimop, but currently, there is no mop.r
could be fitted to sspush
and sspopchk
. The 24th bit of sspush
is 0 but the 24th bit of all mop.r
is 1. The 25th bit of sspopchk
is 0 but but the 25th bit of all mop.r
is 1.
ref:
https://github.com/riscv/riscv-isa-manual/blob/main/src/images/wavedrom/mop-r.adoc
https://github.com/riscv/riscv-cfi/blob/main/cfi_backward.adoc
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmmm, I haven't looked at it in details, is this a document mistake? They should have the same encoding.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I don't find any mistake, sspush
uses mop.rr
and sspopchk
uses mop.r
.
The 25th bit of sspopchk is 0 but but the 25th bit of all mop.r is 1.
This is wrong as it's { bits: 4, name: 0x7 }
, so its value is 0b0111
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, I will give a fix for this.
The patch adds the instructions in Zicfiss extension. Zicfiss extension is to support shadow stack for control flow integrity. Differential Revision: https://reviews.llvm.org/D152793
Rebase but I didn't use alias to Zimop and Zcmop ways to achieve this code, since using them will lose some information like |
// Compress Instruction tablegen backend. | ||
//===----------------------------------------------------------------------===// | ||
|
||
let Predicates = [HasStdExtZicfiss, HasStdExtCOrZca] in { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I remove some CompressPat since I don't know how to test sspush/sspopchk without transforming to compressed ones.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't understand. If Zca isn't on the command line they should shouldn't compress.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess you can't test is because Zicfiss implies Zcmop. But you should be able to disable compression with .option norvc
llvm/lib/Support/RISCVISAInfo.cpp
Outdated
@@ -1024,6 +1024,7 @@ static const char *ImpliedExtsZfinx[] = {"zicsr"}; | |||
static const char *ImpliedExtsZhinx[] = {"zhinxmin"}; | |||
static const char *ImpliedExtsZhinxmin[] = {"zfinx"}; | |||
static const char *ImpliedExtsZicntr[] = {"zicsr"}; | |||
static const char *ImpliedExtsZicfiss[] = {"zicsr", "zimop", "zcmop"}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Zcmop should not be here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok I guess the spec does say that, but it seems weird. That would mean that there would be no need for sspush x1 if you can always use c.sspush x1. I'll file an issue on the spec.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here's my issue riscv/riscv-cfi#201 (comment). From the response I got, I think we should drop Zcmop here and make the CompressPat depend on Zcmop.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added a patch to not imply Zcmop and enable c.sspush when Zcmop enabled.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
The patch adds the instructions in Zicfiss extension. Zicfiss extension is to support shadow stack for control flow integrity. This patch is based on version 0.3.1.