Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions clang/lib/Driver/ToolChains/Arch/RISCV.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,35 @@ void riscv::getRISCVTargetFeatures(const Driver &D, const llvm::Triple &Triple,
Features.push_back("+unaligned-vector-mem");
}

if (const Arg *A = Args.getLastArg(options::OPT_fcf_protection_EQ)) {
const StringRef CFProtection{A->getValue()};
const bool CFProtectionBranch =
CFProtection == "full" || CFProtection == "branch";
if (CFProtectionBranch) {
bool FuncSig;
if (const Arg *SA =
Args.getLastArg(options::OPT_mcf_branch_label_scheme_EQ)) {
const StringRef Scheme{SA->getValue()};
if (Scheme == "unlabeled") {
FuncSig = false;
} else {
assert(Scheme == "func-sig" &&
"-mcf-branch-label-scheme should be either `unlabeled` or "
"`func-sig`");
FuncSig = true;
}
} else {
// `func-sig` is assumed if `-mcf-branch-label-scheme` is not given.
FuncSig = true;
}

if (FuncSig)
Features.push_back("+zicfilp-func-sig");
else
Features.push_back("+zicfilp-unlabeled");
}
}

// Now add any that the user explicitly requested on the command line,
// which may override the defaults.
handleTargetFeaturesGroup(D, Triple, Args, Features,
Expand Down
19 changes: 19 additions & 0 deletions clang/test/Driver/riscv-features.c
Original file line number Diff line number Diff line change
Expand Up @@ -90,3 +90,22 @@

// RVE: "-target-feature" "+e"
// RVE-SAME: "-target-feature" "-i"

// RUN: %clang --target=riscv32 -fcf-protection=full -### %s -fsyntax-only 2>&1 | FileCheck %s -check-prefixes=ZICFILP-FUNC-SIG
// RUN: %clang --target=riscv32 -fcf-protection=full -mcf-branch-label-scheme=func-sig -### %s -fsyntax-only 2>&1 | FileCheck %s -check-prefixes=ZICFILP-FUNC-SIG
// RUN: %clang --target=riscv32 -fcf-protection=full -mcf-branch-label-scheme=unlabeled -### %s -fsyntax-only 2>&1 | FileCheck %s -check-prefixes=ZICFILP-UNLABELED
// RUN: %clang --target=riscv32 -fcf-protection=branch -### %s -fsyntax-only 2>&1 | FileCheck %s -check-prefixes=ZICFILP-FUNC-SIG
// RUN: %clang --target=riscv32 -fcf-protection=branch -mcf-branch-label-scheme=func-sig -### %s -fsyntax-only 2>&1 | FileCheck %s -check-prefixes=ZICFILP-FUNC-SIG
// RUN: %clang --target=riscv32 -fcf-protection=branch -mcf-branch-label-scheme=unlabeled -### %s -fsyntax-only 2>&1 | FileCheck %s -check-prefixes=ZICFILP-UNLABELED
// RUN: %clang --target=riscv64 -fcf-protection=full -### %s -fsyntax-only 2>&1 | FileCheck %s -check-prefixes=ZICFILP-FUNC-SIG
// RUN: %clang --target=riscv64 -fcf-protection=full -mcf-branch-label-scheme=func-sig -### %s -fsyntax-only 2>&1 | FileCheck %s -check-prefixes=ZICFILP-FUNC-SIG
// RUN: %clang --target=riscv64 -fcf-protection=full -mcf-branch-label-scheme=unlabeled -### %s -fsyntax-only 2>&1 | FileCheck %s -check-prefixes=ZICFILP-UNLABELED
// RUN: %clang --target=riscv64 -fcf-protection=branch -### %s -fsyntax-only 2>&1 | FileCheck %s -check-prefixes=ZICFILP-FUNC-SIG
// RUN: %clang --target=riscv64 -fcf-protection=branch -mcf-branch-label-scheme=func-sig -### %s -fsyntax-only 2>&1 | FileCheck %s -check-prefixes=ZICFILP-FUNC-SIG
// RUN: %clang --target=riscv64 -fcf-protection=branch -mcf-branch-label-scheme=unlabeled -### %s -fsyntax-only 2>&1 | FileCheck %s -check-prefixes=ZICFILP-UNLABELED
// ZICFILP-FUNC-SIG-NOT: "-target-feature" "-zicfilp-unlabeled"
// ZICFILP-FUNC-SIG: "-target-feature" "+zicfilp-func-sig"
// ZICFILP-FUNC-SIG-NOT: "-target-feature" "-zicfilp-unlabeled"
// ZICFILP-UNLABELED-NOT: "-target-feature" "-zicfilp-func-sig"
// ZICFILP-UNLABELED: "-target-feature" "+zicfilp-unlabeled"
// ZICFILP-UNLABELED-NOT: "-target-feature" "-zicfilp-func-sig"
4 changes: 4 additions & 0 deletions llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,10 @@ void validate(const Triple &TT, const FeatureBitset &FeatureBits) {
if (FeatureBits[RISCV::Feature32Bit] &&
FeatureBits[RISCV::Feature64Bit])
reportFatalUsageError("RV32 and RV64 can't be combined");
if (FeatureBits[RISCV::FeatureZicfilpFuncSig] &&
FeatureBits[RISCV::FeatureZicfilpUnlabeled])
reportFatalUsageError(
"+zicfilp-func-sig and +zicfilp-unlabeled can't be combined");
}

llvm::Expected<std::unique_ptr<RISCVISAInfo>>
Expand Down
4 changes: 1 addition & 3 deletions llvm/lib/Target/RISCV/RISCVCallingConv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -337,9 +337,7 @@ bool llvm::CC_RISCV(unsigned ValNo, MVT ValVT, MVT LocVT,
// Static chain parameter must not be passed in normal argument registers,
// so we assign t2/t3 for it as done in GCC's
// __builtin_call_with_static_chain
bool HasCFBranch =
Subtarget.hasStdExtZicfilp() &&
MF.getFunction().getParent()->getModuleFlag("cf-protection-branch");
bool HasCFBranch = Subtarget.hasZicfilpCFI();

// Normal: t2, Branch control flow protection: t3
const auto StaticChainReg = HasCFBranch ? RISCV::X28 : RISCV::X7;
Expand Down
13 changes: 11 additions & 2 deletions llvm/lib/Target/RISCV/RISCVFeatures.td
Original file line number Diff line number Diff line change
Expand Up @@ -176,8 +176,6 @@ def FeatureStdExtZicfilp
def HasStdExtZicfilp : Predicate<"Subtarget->hasStdExtZicfilp()">,
AssemblerPredicate<(all_of FeatureStdExtZicfilp),
"'Zicfilp' (Landing pad)">;
def NoStdExtZicfilp : Predicate<"!Subtarget->hasStdExtZicfilp()">,
AssemblerPredicate<(all_of (not FeatureStdExtZicfilp))>;

def FeatureStdExtZicfiss
: RISCVExperimentalExtension<1, 0, "Shadow stack",
Expand Down Expand Up @@ -1976,3 +1974,14 @@ def TuneSiFive7 : SubtargetFeature<"sifive7", "RISCVProcFamily", "SiFive7",
def TuneVentanaVeyron : SubtargetFeature<"ventana-veyron", "RISCVProcFamily", "VentanaVeyron",
"Ventana Veyron-Series processors">;

// Zicfilp-based CFI
def FeatureZicfilpUnlabeled
: SubtargetFeature<
"zicfilp-unlabeled", "RISCVZicfilpCFIScheme", "ZicfilpUnlabeled",
"Enforce forward-edge control-flow integrity with ZICFILP-unlabeled">;
def FeatureZicfilpFuncSig
: SubtargetFeature<
"zicfilp-func-sig", "RISCVZicfilpCFIScheme", "ZicfilpFuncSig",
"Enforce forward-edge control-flow integrity with ZICFILP-func-sig">;
def HasZicfilpCFI : Predicate<"Subtarget->hasZicfilpCFI()">;
def NoZicfilpCFI : Predicate<"!Subtarget->hasZicfilpCFI()">;
18 changes: 7 additions & 11 deletions llvm/lib/Target/RISCV/RISCVISelLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8969,10 +8969,7 @@ SDValue RISCVTargetLowering::lowerINIT_TRAMPOLINE(SDValue Op,
// 28: <FunctionAddressOffset>
// 36:

const bool HasCFBranch =
Subtarget.hasStdExtZicfilp() &&
DAG.getMachineFunction().getFunction().getParent()->getModuleFlag(
"cf-protection-branch");
const bool HasCFBranch = Subtarget.hasZicfilpCFI();
const unsigned StaticChainIdx = HasCFBranch ? 5 : 4;
const unsigned StaticChainOffset = StaticChainIdx * 4;
const unsigned FunctionAddressOffset = StaticChainOffset + 8;
Expand Down Expand Up @@ -24082,11 +24079,10 @@ SDValue RISCVTargetLowering::LowerCall(CallLoweringInfo &CLI,
// Use software guarded branch for large code model non-indirect calls
// Tail call to external symbol will have a null CLI.CB and we need another
// way to determine the callsite type
bool NeedSWGuarded = false;
if (getTargetMachine().getCodeModel() == CodeModel::Large &&
Subtarget.hasStdExtZicfilp() &&
((CLI.CB && !CLI.CB->isIndirectCall()) || CalleeIsLargeExternalSymbol))
NeedSWGuarded = true;
const bool NeedSWGuarded =
getTargetMachine().getCodeModel() == CodeModel::Large &&
Subtarget.hasZicfilpCFI() &&
((CLI.CB && !CLI.CB->isIndirectCall()) || CalleeIsLargeExternalSymbol);

if (IsTailCall) {
MF.getFrameInfo().setHasTailCall();
Expand Down Expand Up @@ -25722,8 +25718,8 @@ SDValue RISCVTargetLowering::expandIndirectJTBranch(const SDLoc &dl,
SDValue Value, SDValue Addr,
int JTI,
SelectionDAG &DAG) const {
if (Subtarget.hasStdExtZicfilp()) {
// When Zicfilp enabled, we need to use software guarded branch for jump
if (Subtarget.hasZicfilpCFI()) {
// When Zicfilp CFI is used, we need to use software guarded branch for jump
// table branch.
SDValue Chain = Value;
// Jump table debug info is only needed if CodeView is enabled.
Expand Down
10 changes: 8 additions & 2 deletions llvm/lib/Target/RISCV/RISCVIndirectBranchTracking.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/Support/Error.h"

#define DEBUG_TYPE "riscv-indirect-branch-tracking"
#define PASS_NAME "RISC-V Indirect Branch Tracking"
Expand Down Expand Up @@ -76,10 +77,15 @@ static bool isCallReturnTwice(const MachineOperand &MOp) {

bool RISCVIndirectBranchTracking::runOnMachineFunction(MachineFunction &MF) {
const auto &Subtarget = MF.getSubtarget<RISCVSubtarget>();
const RISCVInstrInfo *TII = Subtarget.getInstrInfo();
if (!Subtarget.hasStdExtZicfilp())
if (!Subtarget.hasZicfilpCFI())
return false;

const RISCVInstrInfo *TII = Subtarget.getInstrInfo();

if (Subtarget.getZicfilpCFIScheme() != RISCVSubtarget::ZicfilpUnlabeled)
reportFatalUsageError(
"only cf-branch-label-scheme=unlabeled is supported for now");

uint32_t FixedLabel = 0;
if (PreferredLandingPadLabel.getNumOccurrences() > 0) {
if (!isUInt<20>(PreferredLandingPadLabel))
Expand Down
4 changes: 2 additions & 2 deletions llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1373,7 +1373,7 @@ void RISCVInstrInfo::insertIndirectBranch(MachineBasicBlock &MBB,

RS->enterBasicBlockEnd(MBB);
const TargetRegisterClass *RC = &RISCV::GPRRegClass;
if (STI.hasStdExtZicfilp())
if (STI.hasZicfilpCFI())
RC = &RISCV::GPRX7RegClass;
Register TmpGPR =
RS->scavengeRegisterBackwards(*RC, MI.getIterator(),
Expand All @@ -1387,7 +1387,7 @@ void RISCVInstrInfo::insertIndirectBranch(MachineBasicBlock &MBB,
// Pick s11(or s1 for rve) because it doesn't make a difference.
TmpGPR = STI.hasStdExtE() ? RISCV::X9 : RISCV::X27;
// Force t2 if Zicfilp is on
if (STI.hasStdExtZicfilp())
if (STI.hasZicfilpCFI())
TmpGPR = RISCV::X7;

int FrameIndex = RVFI->getBranchRelaxationScratchFrameIndex();
Expand Down
16 changes: 8 additions & 8 deletions llvm/lib/Target/RISCV/RISCVInstrInfo.td
Original file line number Diff line number Diff line change
Expand Up @@ -1758,12 +1758,12 @@ let isBarrier = 1, isBranch = 1, isTerminator = 1 in
def PseudoBR : Pseudo<(outs), (ins simm21_lsb0_jal:$imm20), [(br bb:$imm20)]>,
PseudoInstExpansion<(JAL X0, simm21_lsb0_jal:$imm20)>;

let Predicates = [NoStdExtZicfilp],
let Predicates = [NoZicfilpCFI],
isBarrier = 1, isBranch = 1, isIndirectBranch = 1, isTerminator = 1 in
def PseudoBRIND : Pseudo<(outs), (ins GPRJALR:$rs1, simm12_lo:$imm12), []>,
PseudoInstExpansion<(JALR X0, GPR:$rs1, simm12_lo:$imm12)>;

let Predicates = [HasStdExtZicfilp],
let Predicates = [HasZicfilpCFI],
isBarrier = 1, isBranch = 1, isIndirectBranch = 1, isTerminator = 1 in {
def PseudoBRINDNonX7 : Pseudo<(outs), (ins GPRJALRNonX7:$rs1, simm12_lo:$imm12), []>,
PseudoInstExpansion<(JALR X0, GPR:$rs1, simm12_lo:$imm12)>;
Expand All @@ -1773,7 +1773,7 @@ def PseudoBRINDX7 : Pseudo<(outs), (ins GPRX7:$rs1, simm12_lo:$imm12), []>,

// For Zicfilp, need to avoid using X7/T2 for indirect branches which need
// landing pad.
let Predicates = [HasStdExtZicfilp] in {
let Predicates = [HasZicfilpCFI] in {
def : Pat<(brind GPRJALRNonX7:$rs1), (PseudoBRINDNonX7 GPRJALRNonX7:$rs1, 0)>;
def : Pat<(brind (add GPRJALRNonX7:$rs1, simm12_lo:$imm12)),
(PseudoBRINDNonX7 GPRJALRNonX7:$rs1, simm12_lo:$imm12)>;
Expand All @@ -1783,7 +1783,7 @@ def : Pat<(riscv_sw_guarded_brind (add GPRX7:$rs1, simm12_lo:$imm12)),
(PseudoBRINDX7 GPRX7:$rs1, simm12_lo:$imm12)>;
}

let Predicates = [NoStdExtZicfilp] in {
let Predicates = [NoZicfilpCFI] in {
def : Pat<(brind GPRJALR:$rs1), (PseudoBRIND GPRJALR:$rs1, 0)>;
def : Pat<(brind (add GPRJALR:$rs1, simm12_lo:$imm12)),
(PseudoBRIND GPRJALR:$rs1, simm12_lo:$imm12)>;
Expand Down Expand Up @@ -1820,11 +1820,11 @@ let Predicates = [HasStdExtSmrnmi] in
def : Pat<(riscv_mnret_glue), (MNRET)>;

let isCall = 1, Defs = [X1] in {
let Predicates = [NoStdExtZicfilp] in
let Predicates = [NoZicfilpCFI] in
def PseudoCALLIndirect : Pseudo<(outs), (ins GPRJALR:$rs1),
[(riscv_call GPRJALR:$rs1)]>,
PseudoInstExpansion<(JALR X1, GPR:$rs1, 0)>;
let Predicates = [HasStdExtZicfilp] in {
let Predicates = [HasZicfilpCFI] in {
def PseudoCALLIndirectNonX7 : Pseudo<(outs), (ins GPRJALRNonX7:$rs1),
[(riscv_call GPRJALRNonX7:$rs1)]>,
PseudoInstExpansion<(JALR X1, GPR:$rs1, 0)>;
Expand All @@ -1849,11 +1849,11 @@ def PseudoTAIL : Pseudo<(outs), (ins call_symbol:$dst), [],
Sched<[WriteIALU, WriteJalr, ReadJalr]>;

let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, Uses = [X2] in {
let Predicates = [NoStdExtZicfilp] in
let Predicates = [NoZicfilpCFI] in
def PseudoTAILIndirect : Pseudo<(outs), (ins GPRTC:$rs1),
[(riscv_tail GPRTC:$rs1)]>,
PseudoInstExpansion<(JALR X0, GPR:$rs1, 0)>;
let Predicates = [HasStdExtZicfilp] in {
let Predicates = [HasZicfilpCFI] in {
def PseudoTAILIndirectNonX7 : Pseudo<(outs), (ins GPRTCNonX7:$rs1),
[(riscv_tail GPRTCNonX7:$rs1)]>,
PseudoInstExpansion<(JALR X0, GPR:$rs1, 0)>;
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/Target/RISCV/RISCVLandingPadSetup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ bool RISCVLandingPadSetup::runOnMachineFunction(MachineFunction &MF) {
const auto &STI = MF.getSubtarget<RISCVSubtarget>();
const RISCVInstrInfo &TII = *STI.getInstrInfo();

if (!STI.hasStdExtZicfilp())
if (!STI.hasZicfilpCFI())
return false;

uint32_t Label = 0;
Expand Down
14 changes: 14 additions & 0 deletions llvm/lib/Target/RISCV/RISCVSubtarget.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,12 +90,19 @@ class RISCVSubtarget : public RISCVGenSubtargetInfo {
Quadratic,
NLog2N,
};
enum RISCVZicfilpCFISchemeEnum : uint8_t {
ZicfilpDisabled,
ZicfilpUnlabeled,
ZicfilpFuncSig,
};
// clang-format on

private:
virtual void anchor();

RISCVProcFamilyEnum RISCVProcFamily = Others;
RISCVVRGatherCostModelEnum RISCVVRGatherCostModel = Quadratic;
RISCVZicfilpCFISchemeEnum RISCVZicfilpCFIScheme = ZicfilpDisabled;

#define GET_SUBTARGETINFO_MACRO(ATTRIBUTE, DEFAULT, GETTER) \
bool ATTRIBUTE = DEFAULT;
Expand Down Expand Up @@ -205,6 +212,13 @@ class RISCVSubtarget : public RISCVGenSubtargetInfo {
return HasStdExtZicond || HasVendorXVentanaCondOps;
}

RISCVZicfilpCFISchemeEnum getZicfilpCFIScheme() const {
return RISCVZicfilpCFIScheme;
}
bool hasZicfilpCFI() const {
return getZicfilpCFIScheme() != ZicfilpDisabled;
}

bool hasConditionalMoveFusion() const {
// Do we support fusing a branch+mv or branch+c.mv as a conditional move.
return (hasConditionalCompressedMoveFusion() && hasStdExtZca()) ||
Expand Down
35 changes: 35 additions & 0 deletions llvm/lib/Target/RISCV/RISCVTargetMachine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include "RISCVTargetObjectFile.h"
#include "RISCVTargetTransformInfo.h"
#include "TargetInfo/RISCVTargetInfo.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Analysis/TargetTransformInfo.h"
#include "llvm/CodeGen/GlobalISel/CSEInfo.h"
#include "llvm/CodeGen/GlobalISel/IRTranslator.h"
Expand All @@ -31,11 +32,15 @@
#include "llvm/CodeGen/RegAllocRegistry.h"
#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
#include "llvm/CodeGen/TargetPassConfig.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/Metadata.h"
#include "llvm/IR/Module.h"
#include "llvm/InitializePasses.h"
#include "llvm/MC/TargetRegistry.h"
#include "llvm/Passes/PassBuilder.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/TargetParser/SubtargetFeature.h"
#include "llvm/Transforms/IPO.h"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Transforms/Vectorize/LoopIdiomVectorize.h"
Expand Down Expand Up @@ -178,6 +183,33 @@ RISCVTargetMachine::RISCVTargetMachine(const Target &T, const Triple &TT,
setCFIFixup(!EnableCFIInstrInserter);
}

static void reportBadZicfilpUsage(const FeatureBitset &Features,
const Module &M) {
if (const Metadata *const CF = M.getModuleFlag("cf-protection-branch");
CF && !mdconst::extract<ConstantInt>(CF)->isZero()) {
StringRef LabelScheme;
if (const Metadata *const MD = M.getModuleFlag("cf-branch-label-scheme")) {
LabelScheme = cast<MDString>(MD)->getString();
if (LabelScheme != "func-sig" && LabelScheme != "unlabeled")
reportFatalUsageError("cf-branch-label-scheme=" + LabelScheme +
" module flag is unsupported");
} else {
reportFatalUsageError("missing cf-branch-label-scheme module flag");
}

if ((!Features[RISCV::FeatureZicfilpFuncSig] &&
LabelScheme == "func-sig") ||
(!Features[RISCV::FeatureZicfilpUnlabeled] &&
LabelScheme == "unlabeled"))
reportFatalUsageError(
"require target feature (+zicfilp-" + LabelScheme +
") to handle cf-branch-label-scheme=" + LabelScheme + " module flag");
} else if (Features[RISCV::FeatureZicfilpFuncSig] ||
Features[RISCV::FeatureZicfilpUnlabeled]) {
reportFatalUsageError("require cf-protection-branch != 0 module flag");
}
}

const RISCVSubtarget *
RISCVTargetMachine::getSubtargetImpl(const Function &F) const {
Attribute CPUAttr = F.getFnAttribute("target-cpu");
Expand Down Expand Up @@ -252,6 +284,9 @@ RISCVTargetMachine::getSubtargetImpl(const Function &F) const {
I = std::make_unique<RISCVSubtarget>(
TargetTriple, CPU, TuneCPU, FS, ABIName, RVVBitsMin, RVVBitsMax, *this);
}

if (const Module *const M = F.getParent())
reportBadZicfilpUsage(I->getFeatureBits(), *M);
return I.get();
}

Expand Down
Loading
Loading