Skip to content
Open
Show file tree
Hide file tree
Changes from 12 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 @@ -176,6 +176,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
18 changes: 18 additions & 0 deletions clang/test/Driver/riscv-features.c
Original file line number Diff line number Diff line change
Expand Up @@ -85,3 +85,21 @@
// FUCHSIA-SAME: "-target-feature" "+zbb"
// FUCHSIA-SAME: "-target-feature" "+zbs"

// 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
14 changes: 12 additions & 2 deletions llvm/lib/Target/RISCV/RISCVFeatures.td
Original file line number Diff line number Diff line change
Expand Up @@ -170,8 +170,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 @@ -1802,3 +1800,15 @@ def FeatureTaggedGlobals : SubtargetFeature<"tagged-globals",
"AllowTaggedGlobals",
"true", "Use an instruction sequence for taking the address of a global "
"that allows a memory tag in the upper address bits">;

// Zicfilp-based CFI
def FeatureZicfilpUnlabeled
: SubtargetFeature<
"zicfilp-unlabeled", "HasZicfilpUnlabeled", "true",
"Enforce forward-edge control-flow integrity with ZICFILP-unlabeled">;
def FeatureZicfilpFuncSig
: SubtargetFeature<
"zicfilp-func-sig", "HasZicfilpFuncSig", "true",
"Enforce forward-edge control-flow integrity with ZICFILP-func-sig">;
def HasZicfilpCFI : Predicate<"Subtarget->hasZicfilpCFI()">;
def HasNoZicfilpCFI : 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 @@ -8528,10 +8528,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 @@ -22953,11 +22950,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 @@ -24546,8 +24542,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
11 changes: 9 additions & 2 deletions llvm/lib/Target/RISCV/RISCVIndirectBranchTracking.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,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-indrect-branch-tracking"
#define PASS_NAME "RISC-V Indirect Branch Tracking"
Expand Down Expand Up @@ -63,10 +64,16 @@ static void emitLpad(MachineBasicBlock &MBB, const RISCVInstrInfo *TII,

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.getZicfilpLabelScheme() !=
RISCVSubtarget::ZicfilpLabelSchemeEnum::Unlabeled)
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
16 changes: 8 additions & 8 deletions llvm/lib/Target/RISCV/RISCVInstrInfo.td
Original file line number Diff line number Diff line change
Expand Up @@ -1746,12 +1746,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 = [HasNoZicfilpCFI],
isBarrier = 1, isBranch = 1, isIndirectBranch = 1, isTerminator = 1 in
def PseudoBRIND : Pseudo<(outs), (ins GPRJALR:$rs1, simm12:$imm12), []>,
PseudoInstExpansion<(JALR X0, GPR:$rs1, simm12:$imm12)>;

let Predicates = [HasStdExtZicfilp],
let Predicates = [HasZicfilpCFI],
isBarrier = 1, isBranch = 1, isIndirectBranch = 1, isTerminator = 1 in {
def PseudoBRINDNonX7 : Pseudo<(outs), (ins GPRJALRNonX7:$rs1, simm12:$imm12), []>,
PseudoInstExpansion<(JALR X0, GPR:$rs1, simm12:$imm12)>;
Expand All @@ -1761,7 +1761,7 @@ def PseudoBRINDX7 : Pseudo<(outs), (ins GPRX7:$rs1, simm12:$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:$imm12)),
(PseudoBRINDNonX7 GPRJALRNonX7:$rs1, simm12:$imm12)>;
Expand All @@ -1771,7 +1771,7 @@ def : Pat<(riscv_sw_guarded_brind (add GPRX7:$rs1, simm12:$imm12)),
(PseudoBRINDX7 GPRX7:$rs1, simm12:$imm12)>;
}

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

let isCall = 1, Defs = [X1] in {
let Predicates = [NoStdExtZicfilp] in
let Predicates = [HasNoZicfilpCFI] 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 @@ -1837,11 +1837,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 = [HasNoZicfilpCFI] 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
18 changes: 18 additions & 0 deletions llvm/lib/Target/RISCV/RISCVSubtarget.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,13 @@ class RISCVSubtarget : public RISCVGenSubtargetInfo {
NLog2N,
};
// clang-format on

enum class ZicfilpLabelSchemeEnum {
Disabled,
Unlabeled,
FuncSig,
};

private:
virtual void anchor();

Expand Down Expand Up @@ -186,6 +193,17 @@ class RISCVSubtarget : public RISCVGenSubtargetInfo {
return HasStdExtZfhmin || HasStdExtZfbfmin;
}

ZicfilpLabelSchemeEnum getZicfilpLabelScheme() const {
if (hasZicfilpFuncSig())
return ZicfilpLabelSchemeEnum::FuncSig;
if (hasZicfilpUnlabeled())
return ZicfilpLabelSchemeEnum::Unlabeled;
return ZicfilpLabelSchemeEnum::Disabled;
}
bool hasZicfilpCFI() const {
return getZicfilpLabelScheme() != ZicfilpLabelSchemeEnum::Disabled;
}

bool hasConditionalMoveFusion() const {
// Do we support fusing a branch+mv or branch+c.mv as a conditional move.
return (hasConditionalCompressedMoveFusion() && hasStdExtZca()) ||
Expand Down
33 changes: 33 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,6 +32,9 @@
#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"
Expand Down Expand Up @@ -268,6 +272,35 @@ 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()) {
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");
}

using ZicfilpLabelSchemeEnum = RISCVSubtarget::ZicfilpLabelSchemeEnum;
const ZicfilpLabelSchemeEnum SupportedScheme = I->getZicfilpLabelScheme();
if ((SupportedScheme != ZicfilpLabelSchemeEnum::FuncSig &&
LabelScheme == "func-sig") ||
(SupportedScheme != ZicfilpLabelSchemeEnum::Unlabeled &&
LabelScheme == "unlabeled"))
reportFatalUsageError(
"require target feature (+zicfilp-" + LabelScheme +
") to handle cf-branch-label-scheme=" + LabelScheme +
" module flag");
} else if (I->hasZicfilpCFI()) {
reportFatalUsageError("require cf-protection-branch != 0 module flag");
}
}
return I.get();
}

Expand Down
Loading