
Currenlty assume x18 is used as pointer to shadow call stack. User shall pass flags: "-fsanitize=shadow-call-stack -ffixed-x18" Runtime supported is needed to setup x18. If SCS is desired, all parts of the program should be built with -ffixed-x18 to maintain inter-operatability. There's no particuluar reason that we must use x18 as SCS pointer. Any register may be used, as long as it does not have designated purpose already, like RA or passing call arguments. Differential Revision: https://reviews.llvm.org/D84414
85 lines
2.9 KiB
C++
85 lines
2.9 KiB
C++
#include "RISCVBaseInfo.h"
|
|
#include "llvm/ADT/ArrayRef.h"
|
|
#include "llvm/ADT/Triple.h"
|
|
#include "llvm/Support/raw_ostream.h"
|
|
|
|
namespace llvm {
|
|
namespace RISCVSysReg {
|
|
#define GET_SysRegsList_IMPL
|
|
#include "RISCVGenSystemOperands.inc"
|
|
} // namespace RISCVSysReg
|
|
|
|
namespace RISCVABI {
|
|
ABI computeTargetABI(const Triple &TT, FeatureBitset FeatureBits,
|
|
StringRef ABIName) {
|
|
auto TargetABI = getTargetABI(ABIName);
|
|
bool IsRV64 = TT.isArch64Bit();
|
|
bool IsRV32E = FeatureBits[RISCV::FeatureRV32E];
|
|
|
|
if (!ABIName.empty() && TargetABI == ABI_Unknown) {
|
|
errs()
|
|
<< "'" << ABIName
|
|
<< "' is not a recognized ABI for this target (ignoring target-abi)\n";
|
|
} else if (ABIName.startswith("ilp32") && IsRV64) {
|
|
errs() << "32-bit ABIs are not supported for 64-bit targets (ignoring "
|
|
"target-abi)\n";
|
|
TargetABI = ABI_Unknown;
|
|
} else if (ABIName.startswith("lp64") && !IsRV64) {
|
|
errs() << "64-bit ABIs are not supported for 32-bit targets (ignoring "
|
|
"target-abi)\n";
|
|
TargetABI = ABI_Unknown;
|
|
} else if (IsRV32E && TargetABI != ABI_ILP32E && TargetABI != ABI_Unknown) {
|
|
// TODO: move this checking to RISCVTargetLowering and RISCVAsmParser
|
|
errs()
|
|
<< "Only the ilp32e ABI is supported for RV32E (ignoring target-abi)\n";
|
|
TargetABI = ABI_Unknown;
|
|
}
|
|
|
|
if (TargetABI != ABI_Unknown)
|
|
return TargetABI;
|
|
|
|
// For now, default to the ilp32/ilp32e/lp64 ABI if no explicit ABI is given
|
|
// or an invalid/unrecognised string is given. In the future, it might be
|
|
// worth changing this to default to ilp32f/lp64f and ilp32d/lp64d when
|
|
// hardware support for floating point is present.
|
|
if (IsRV32E)
|
|
return ABI_ILP32E;
|
|
if (IsRV64)
|
|
return ABI_LP64;
|
|
return ABI_ILP32;
|
|
}
|
|
|
|
ABI getTargetABI(StringRef ABIName) {
|
|
auto TargetABI = StringSwitch<ABI>(ABIName)
|
|
.Case("ilp32", ABI_ILP32)
|
|
.Case("ilp32f", ABI_ILP32F)
|
|
.Case("ilp32d", ABI_ILP32D)
|
|
.Case("ilp32e", ABI_ILP32E)
|
|
.Case("lp64", ABI_LP64)
|
|
.Case("lp64f", ABI_LP64F)
|
|
.Case("lp64d", ABI_LP64D)
|
|
.Default(ABI_Unknown);
|
|
return TargetABI;
|
|
}
|
|
|
|
// To avoid the BP value clobbered by a function call, we need to choose a
|
|
// callee saved register to save the value. RV32E only has X8 and X9 as callee
|
|
// saved registers and X8 will be used as fp. So we choose X9 as bp.
|
|
Register getBPReg() { return RISCV::X9; }
|
|
|
|
// Returns the register holding shadow call stack pointer.
|
|
Register getSCSPReg() { return RISCV::X18; }
|
|
|
|
} // namespace RISCVABI
|
|
|
|
namespace RISCVFeatures {
|
|
|
|
void validate(const Triple &TT, const FeatureBitset &FeatureBits) {
|
|
if (TT.isArch64Bit() && FeatureBits[RISCV::FeatureRV32E])
|
|
report_fatal_error("RV32E can't be enabled for an RV64 target");
|
|
}
|
|
|
|
} // namespace RISCVFeatures
|
|
|
|
} // namespace llvm
|