2023-03-27 09:15:53 -07:00
|
|
|
//===--- RISCV.cpp - Implement RISC-V target feature support --------------===//
|
2018-01-11 13:36:56 +00:00
|
|
|
//
|
2019-01-19 08:50:56 +00:00
|
|
|
// 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
|
2018-01-11 13:36:56 +00:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
2023-03-27 09:15:53 -07:00
|
|
|
// This file implements RISC-V TargetInfo objects.
|
2018-01-11 13:36:56 +00:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "RISCV.h"
|
2021-06-23 16:18:54 +08:00
|
|
|
#include "clang/Basic/Diagnostic.h"
|
2018-01-11 13:36:56 +00:00
|
|
|
#include "clang/Basic/MacroBuilder.h"
|
2021-02-04 12:57:44 +08:00
|
|
|
#include "clang/Basic/TargetBuiltins.h"
|
2018-01-11 13:36:56 +00:00
|
|
|
#include "llvm/ADT/StringSwitch.h"
|
2021-06-23 16:18:54 +08:00
|
|
|
#include "llvm/Support/raw_ostream.h"
|
2023-01-11 10:23:55 +01:00
|
|
|
#include "llvm/TargetParser/RISCVTargetParser.h"
|
2022-12-09 22:52:29 -08:00
|
|
|
#include <optional>
|
2018-01-11 13:36:56 +00:00
|
|
|
|
|
|
|
using namespace clang;
|
|
|
|
using namespace clang::targets;
|
|
|
|
|
|
|
|
ArrayRef<const char *> RISCVTargetInfo::getGCCRegNames() const {
|
2023-10-23 11:15:20 +08:00
|
|
|
// clang-format off
|
2018-01-11 13:36:56 +00:00
|
|
|
static const char *const GCCRegNames[] = {
|
2019-07-31 09:12:00 +00:00
|
|
|
// Integer registers
|
2018-01-11 13:36:56 +00:00
|
|
|
"x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7",
|
|
|
|
"x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15",
|
|
|
|
"x16", "x17", "x18", "x19", "x20", "x21", "x22", "x23",
|
2019-07-31 09:12:00 +00:00
|
|
|
"x24", "x25", "x26", "x27", "x28", "x29", "x30", "x31",
|
|
|
|
|
|
|
|
// Floating point registers
|
|
|
|
"f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
|
|
|
|
"f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
|
|
|
|
"f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
|
2021-03-29 18:27:27 +08:00
|
|
|
"f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
|
|
|
|
|
|
|
|
// Vector registers
|
|
|
|
"v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7",
|
|
|
|
"v8", "v9", "v10", "v11", "v12", "v13", "v14", "v15",
|
|
|
|
"v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23",
|
2023-10-23 11:15:20 +08:00
|
|
|
"v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31",
|
|
|
|
|
|
|
|
// CSRs
|
2024-09-30 23:52:35 -07:00
|
|
|
"fflags", "frm", "vtype", "vl", "vxsat", "vxrm", "sf.vcix_state"
|
2023-10-23 11:15:20 +08:00
|
|
|
};
|
|
|
|
// clang-format on
|
2023-01-06 16:56:23 +01:00
|
|
|
return llvm::ArrayRef(GCCRegNames);
|
2018-01-11 13:36:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ArrayRef<TargetInfo::GCCRegAlias> RISCVTargetInfo::getGCCRegAliases() const {
|
|
|
|
static const TargetInfo::GCCRegAlias GCCRegAliases[] = {
|
2019-07-31 09:12:00 +00:00
|
|
|
{{"zero"}, "x0"}, {{"ra"}, "x1"}, {{"sp"}, "x2"}, {{"gp"}, "x3"},
|
|
|
|
{{"tp"}, "x4"}, {{"t0"}, "x5"}, {{"t1"}, "x6"}, {{"t2"}, "x7"},
|
|
|
|
{{"s0"}, "x8"}, {{"s1"}, "x9"}, {{"a0"}, "x10"}, {{"a1"}, "x11"},
|
|
|
|
{{"a2"}, "x12"}, {{"a3"}, "x13"}, {{"a4"}, "x14"}, {{"a5"}, "x15"},
|
|
|
|
{{"a6"}, "x16"}, {{"a7"}, "x17"}, {{"s2"}, "x18"}, {{"s3"}, "x19"},
|
|
|
|
{{"s4"}, "x20"}, {{"s5"}, "x21"}, {{"s6"}, "x22"}, {{"s7"}, "x23"},
|
|
|
|
{{"s8"}, "x24"}, {{"s9"}, "x25"}, {{"s10"}, "x26"}, {{"s11"}, "x27"},
|
|
|
|
{{"t3"}, "x28"}, {{"t4"}, "x29"}, {{"t5"}, "x30"}, {{"t6"}, "x31"},
|
|
|
|
{{"ft0"}, "f0"}, {{"ft1"}, "f1"}, {{"ft2"}, "f2"}, {{"ft3"}, "f3"},
|
|
|
|
{{"ft4"}, "f4"}, {{"ft5"}, "f5"}, {{"ft6"}, "f6"}, {{"ft7"}, "f7"},
|
|
|
|
{{"fs0"}, "f8"}, {{"fs1"}, "f9"}, {{"fa0"}, "f10"}, {{"fa1"}, "f11"},
|
|
|
|
{{"fa2"}, "f12"}, {{"fa3"}, "f13"}, {{"fa4"}, "f14"}, {{"fa5"}, "f15"},
|
|
|
|
{{"fa6"}, "f16"}, {{"fa7"}, "f17"}, {{"fs2"}, "f18"}, {{"fs3"}, "f19"},
|
|
|
|
{{"fs4"}, "f20"}, {{"fs5"}, "f21"}, {{"fs6"}, "f22"}, {{"fs7"}, "f23"},
|
|
|
|
{{"fs8"}, "f24"}, {{"fs9"}, "f25"}, {{"fs10"}, "f26"}, {{"fs11"}, "f27"},
|
|
|
|
{{"ft8"}, "f28"}, {{"ft9"}, "f29"}, {{"ft10"}, "f30"}, {{"ft11"}, "f31"}};
|
2023-01-06 16:56:23 +01:00
|
|
|
return llvm::ArrayRef(GCCRegAliases);
|
2018-01-11 13:36:56 +00:00
|
|
|
}
|
|
|
|
|
2019-06-11 12:44:01 +00:00
|
|
|
bool RISCVTargetInfo::validateAsmConstraint(
|
|
|
|
const char *&Name, TargetInfo::ConstraintInfo &Info) const {
|
|
|
|
switch (*Name) {
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
case 'I':
|
|
|
|
// A 12-bit signed immediate.
|
|
|
|
Info.setRequiresImmediate(-2048, 2047);
|
|
|
|
return true;
|
|
|
|
case 'J':
|
|
|
|
// Integer zero.
|
|
|
|
Info.setRequiresImmediate(0);
|
|
|
|
return true;
|
|
|
|
case 'K':
|
|
|
|
// A 5-bit unsigned immediate for CSR access instructions.
|
|
|
|
Info.setRequiresImmediate(0, 31);
|
|
|
|
return true;
|
[RISCV] Support 'f' Inline Assembly Constraint
Summary:
This adds the 'f' inline assembly constraint, as supported by GCC. An
'f'-constrained operand is passed in a floating point register. Exactly
which kind of floating-point register (32-bit or 64-bit) is decided
based on the operand type and the available standard extensions (-f and
-d, respectively).
This patch adds support in both the clang frontend, and LLVM itself.
Reviewers: asb, lewis-revill
Reviewed By: asb
Subscribers: hiraditya, rbar, johnrusso, simoncook, apazos, sabuasal, niosHD, kito-cheng, shiva0217, jrtc27, MaskRay, zzheng, edward-jones, rogfer01, MartinMosbeck, brucehoult, the_o, rkruppe, PkmX, jocewei, psnobl, benna, Jim, s.egerton, cfe-commits, llvm-commits
Tags: #clang, #llvm
Differential Revision: https://reviews.llvm.org/D65500
llvm-svn: 367403
2019-07-31 09:45:55 +00:00
|
|
|
case 'f':
|
|
|
|
// A floating-point register.
|
|
|
|
Info.setAllowsRegister();
|
|
|
|
return true;
|
2019-08-16 10:23:56 +00:00
|
|
|
case 'A':
|
|
|
|
// An address that is held in a general-purpose register.
|
|
|
|
Info.setAllowsMemory();
|
|
|
|
return true;
|
2024-02-01 10:18:42 -08:00
|
|
|
case 's':
|
|
|
|
case 'S': // A symbol or label reference with a constant offset
|
2021-07-13 09:30:09 -07:00
|
|
|
Info.setAllowsRegister();
|
|
|
|
return true;
|
2024-10-18 11:40:38 +02:00
|
|
|
case 'c':
|
|
|
|
// A RVC register - GPR or FPR
|
2025-01-23 16:19:19 -08:00
|
|
|
if (Name[1] == 'r' || Name[1] == 'R' || Name[1] == 'f') {
|
2024-10-18 11:40:38 +02:00
|
|
|
Info.setAllowsRegister();
|
|
|
|
Name += 1;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
2024-11-18 17:45:58 +00:00
|
|
|
case 'R':
|
|
|
|
// An even-odd GPR pair
|
|
|
|
Info.setAllowsRegister();
|
|
|
|
return true;
|
2021-03-29 18:27:27 +08:00
|
|
|
case 'v':
|
|
|
|
// A vector register.
|
2024-10-14 10:47:59 +08:00
|
|
|
if (Name[1] == 'r' || Name[1] == 'd' || Name[1] == 'm') {
|
2021-03-29 18:27:27 +08:00
|
|
|
Info.setAllowsRegister();
|
|
|
|
Name += 1;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string RISCVTargetInfo::convertConstraint(const char *&Constraint) const {
|
|
|
|
std::string R;
|
|
|
|
switch (*Constraint) {
|
2024-10-18 11:40:38 +02:00
|
|
|
// c* and v* are two-letter constraints on RISC-V.
|
|
|
|
case 'c':
|
2021-03-29 18:27:27 +08:00
|
|
|
case 'v':
|
2021-07-30 17:10:30 +08:00
|
|
|
R = std::string("^") + std::string(Constraint, 2);
|
2021-03-29 18:27:27 +08:00
|
|
|
Constraint += 1;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
R = TargetInfo::convertConstraint(Constraint);
|
|
|
|
break;
|
2019-06-11 12:44:01 +00:00
|
|
|
}
|
2021-03-29 18:27:27 +08:00
|
|
|
return R;
|
2019-06-11 12:44:01 +00:00
|
|
|
}
|
|
|
|
|
2022-12-20 02:34:52 -08:00
|
|
|
static unsigned getVersionValue(unsigned MajorVersion, unsigned MinorVersion) {
|
|
|
|
return MajorVersion * 1000000 + MinorVersion * 1000;
|
|
|
|
}
|
|
|
|
|
2018-01-11 13:36:56 +00:00
|
|
|
void RISCVTargetInfo::getTargetDefines(const LangOptions &Opts,
|
|
|
|
MacroBuilder &Builder) const {
|
|
|
|
Builder.defineMacro("__riscv");
|
2023-12-09 14:02:11 -08:00
|
|
|
bool Is64Bit = getTriple().isRISCV64();
|
2018-01-11 13:36:56 +00:00
|
|
|
Builder.defineMacro("__riscv_xlen", Is64Bit ? "64" : "32");
|
2019-09-17 08:09:56 +00:00
|
|
|
StringRef CodeModel = getTargetOpts().CodeModel;
|
2021-06-23 16:18:54 +08:00
|
|
|
unsigned FLen = ISAInfo->getFLen();
|
2021-10-23 03:18:24 -07:00
|
|
|
unsigned MinVLen = ISAInfo->getMinVLen();
|
2021-10-27 05:52:20 -07:00
|
|
|
unsigned MaxELen = ISAInfo->getMaxELen();
|
|
|
|
unsigned MaxELenFp = ISAInfo->getMaxELenFp();
|
2019-09-17 08:09:56 +00:00
|
|
|
if (CodeModel == "default")
|
|
|
|
CodeModel = "small";
|
|
|
|
|
|
|
|
if (CodeModel == "small")
|
|
|
|
Builder.defineMacro("__riscv_cmodel_medlow");
|
|
|
|
else if (CodeModel == "medium")
|
|
|
|
Builder.defineMacro("__riscv_cmodel_medany");
|
2024-09-13 10:37:48 +08:00
|
|
|
else if (CodeModel == "large")
|
|
|
|
Builder.defineMacro("__riscv_cmodel_large");
|
2019-07-18 18:29:59 +00:00
|
|
|
|
|
|
|
StringRef ABIName = getABI();
|
|
|
|
if (ABIName == "ilp32f" || ABIName == "lp64f")
|
|
|
|
Builder.defineMacro("__riscv_float_abi_single");
|
|
|
|
else if (ABIName == "ilp32d" || ABIName == "lp64d")
|
|
|
|
Builder.defineMacro("__riscv_float_abi_double");
|
|
|
|
else
|
|
|
|
Builder.defineMacro("__riscv_float_abi_soft");
|
2018-04-05 12:54:00 +00:00
|
|
|
|
2024-01-16 20:44:30 +08:00
|
|
|
if (ABIName == "ilp32e" || ABIName == "lp64e")
|
[RISCV] Correct Logic around ilp32e macros
Summary:
GCC seperates the `__riscv_float_abi_*` macros and the
`__riscv_abi_rve` macro. If the chosen abi is ilp32e, `gcc -march=rv32i
-mabi=ilp32i -E -dM` shows that both `__riscv_float_abi_soft` and
`__riscv_abi_rve` are set.
This patch corrects the compiler logic around these defines.
At the moment, this patch will not change clang's behaviour, because we do not
accept the `ilp32e` abi yet.
Reviewers: luismarques, asb
Reviewed By: luismarques
Subscribers: rbar, johnrusso, simoncook, apazos, sabuasal, niosHD, kito-cheng, shiva0217, jrtc27, MaskRay, zzheng, edward-jones, rogfer01, MartinMosbeck, brucehoult, the_o, rkruppe, PkmX, jocewei, psnobl, benna, Jim, s.egerton, pzheng, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D66591
llvm-svn: 370709
2019-09-03 08:47:58 +00:00
|
|
|
Builder.defineMacro("__riscv_abi_rve");
|
|
|
|
|
2021-01-25 08:58:46 +00:00
|
|
|
Builder.defineMacro("__riscv_arch_test");
|
|
|
|
|
2021-06-23 16:18:54 +08:00
|
|
|
for (auto &Extension : ISAInfo->getExtensions()) {
|
|
|
|
auto ExtName = Extension.first;
|
|
|
|
auto ExtInfo = Extension.second;
|
|
|
|
|
2024-01-11 15:07:24 +07:00
|
|
|
Builder.defineMacro(Twine("__riscv_", ExtName),
|
|
|
|
Twine(getVersionValue(ExtInfo.Major, ExtInfo.Minor)));
|
2021-06-23 16:18:54 +08:00
|
|
|
}
|
|
|
|
|
2024-06-21 11:11:10 +08:00
|
|
|
if (ISAInfo->hasExtension("zmmul"))
|
2018-04-05 12:54:00 +00:00
|
|
|
Builder.defineMacro("__riscv_mul");
|
2022-06-25 21:36:02 -04:00
|
|
|
|
|
|
|
if (ISAInfo->hasExtension("m")) {
|
2018-04-05 12:54:00 +00:00
|
|
|
Builder.defineMacro("__riscv_div");
|
|
|
|
Builder.defineMacro("__riscv_muldiv");
|
|
|
|
}
|
|
|
|
|
2021-06-23 16:18:54 +08:00
|
|
|
if (ISAInfo->hasExtension("a")) {
|
2018-04-05 12:54:00 +00:00
|
|
|
Builder.defineMacro("__riscv_atomic");
|
2020-11-24 22:46:38 +00:00
|
|
|
Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
|
|
|
|
Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
|
|
|
|
Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
|
|
|
|
if (Is64Bit)
|
|
|
|
Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
|
|
|
|
}
|
2018-04-05 12:54:00 +00:00
|
|
|
|
2021-06-23 16:18:54 +08:00
|
|
|
if (FLen) {
|
|
|
|
Builder.defineMacro("__riscv_flen", Twine(FLen));
|
2018-04-05 12:54:00 +00:00
|
|
|
Builder.defineMacro("__riscv_fdiv");
|
|
|
|
Builder.defineMacro("__riscv_fsqrt");
|
|
|
|
}
|
|
|
|
|
2021-10-27 05:52:20 -07:00
|
|
|
if (MinVLen) {
|
2021-10-23 03:18:24 -07:00
|
|
|
Builder.defineMacro("__riscv_v_min_vlen", Twine(MinVLen));
|
2021-10-27 05:52:20 -07:00
|
|
|
Builder.defineMacro("__riscv_v_elen", Twine(MaxELen));
|
|
|
|
Builder.defineMacro("__riscv_v_elen_fp", Twine(MaxELenFp));
|
|
|
|
}
|
2021-10-23 03:18:24 -07:00
|
|
|
|
2021-06-23 16:18:54 +08:00
|
|
|
if (ISAInfo->hasExtension("c"))
|
2018-04-05 12:54:00 +00:00
|
|
|
Builder.defineMacro("__riscv_compressed");
|
2020-04-09 17:51:26 +01:00
|
|
|
|
2024-11-27 10:35:38 +08:00
|
|
|
if (ISAInfo->hasExtension("zve32x"))
|
2020-12-04 20:45:41 +08:00
|
|
|
Builder.defineMacro("__riscv_vector");
|
2024-11-27 10:35:38 +08:00
|
|
|
|
|
|
|
// Currently we support the v1.0 RISC-V V intrinsics.
|
|
|
|
Builder.defineMacro("__riscv_v_intrinsic", Twine(getVersionValue(1, 0)));
|
2023-04-28 15:41:17 -07:00
|
|
|
|
2025-01-31 07:57:43 +00:00
|
|
|
auto VScale = getVScaleRange(Opts, false);
|
2023-04-28 15:41:17 -07:00
|
|
|
if (VScale && VScale->first && VScale->first == VScale->second)
|
|
|
|
Builder.defineMacro("__riscv_v_fixed_vlen",
|
|
|
|
Twine(VScale->first * llvm::RISCV::RVVBitsPerBlock));
|
2023-10-26 15:10:57 +08:00
|
|
|
|
2024-07-14 13:39:17 -07:00
|
|
|
if (FastScalarUnalignedAccess)
|
2023-10-26 15:10:57 +08:00
|
|
|
Builder.defineMacro("__riscv_misaligned_fast");
|
|
|
|
else
|
|
|
|
Builder.defineMacro("__riscv_misaligned_avoid");
|
2024-01-16 20:44:30 +08:00
|
|
|
|
|
|
|
if (ISAInfo->hasExtension("e")) {
|
|
|
|
if (Is64Bit)
|
|
|
|
Builder.defineMacro("__riscv_64e");
|
|
|
|
else
|
|
|
|
Builder.defineMacro("__riscv_32e");
|
|
|
|
}
|
2025-02-18 17:27:20 +08:00
|
|
|
|
|
|
|
if (Opts.CFProtectionReturn && ISAInfo->hasExtension("zicfiss"))
|
|
|
|
Builder.defineMacro("__riscv_shadow_stack");
|
2018-04-05 12:54:00 +00:00
|
|
|
}
|
|
|
|
|
[StrTable] Switch Clang builtins to use string tables
This both reapplies #118734, the initial attempt at this, and updates it
significantly.
First, it uses the newly added `StringTable` abstraction for string
tables, and simplifies the construction to build the string table and
info arrays separately. This should reduce any `constexpr` compile time
memory or CPU cost of the original PR while significantly improving the
APIs throughout.
It also restructures the builtins to support sharding across several
independent tables. This accomplishes two improvements from the
original PR:
1) It improves the APIs used significantly.
2) When builtins are defined from different sources (like SVE vs MVE in
AArch64), this allows each of them to build their own string table
independently rather than having to merge the string tables and info
structures.
3) It allows each shard to factor out a common prefix, often cutting the
size of the strings needed for the builtins by a factor two.
The second point is important both to allow different mechanisms of
construction (for example a `.def` file and a tablegen'ed `.inc` file,
or different tablegen'ed `.inc files), it also simply reduces the sizes
of these tables which is valuable given how large they are in some
cases. The third builds on that size reduction.
Initially, we use this new sharding rather than merging tables in
AArch64, LoongArch, RISCV, and X86. Mostly this helps ensure the system
works, as without further changes these still push scaling limits.
Subsequent commits will more deeply leverage the new structure,
including using the prefix capabilities which cannot be easily factored
out here and requires deep changes to the targets.
2024-12-14 09:09:47 +00:00
|
|
|
static constexpr int NumRVVBuiltins =
|
2024-12-15 03:20:15 +00:00
|
|
|
RISCVVector::FirstSiFiveBuiltin - Builtin::FirstTSBuiltin;
|
|
|
|
static constexpr int NumRVVSiFiveBuiltins =
|
|
|
|
RISCVVector::FirstTSBuiltin - RISCVVector::FirstSiFiveBuiltin;
|
[StrTable] Switch Clang builtins to use string tables
This both reapplies #118734, the initial attempt at this, and updates it
significantly.
First, it uses the newly added `StringTable` abstraction for string
tables, and simplifies the construction to build the string table and
info arrays separately. This should reduce any `constexpr` compile time
memory or CPU cost of the original PR while significantly improving the
APIs throughout.
It also restructures the builtins to support sharding across several
independent tables. This accomplishes two improvements from the
original PR:
1) It improves the APIs used significantly.
2) When builtins are defined from different sources (like SVE vs MVE in
AArch64), this allows each of them to build their own string table
independently rather than having to merge the string tables and info
structures.
3) It allows each shard to factor out a common prefix, often cutting the
size of the strings needed for the builtins by a factor two.
The second point is important both to allow different mechanisms of
construction (for example a `.def` file and a tablegen'ed `.inc` file,
or different tablegen'ed `.inc files), it also simply reduces the sizes
of these tables which is valuable given how large they are in some
cases. The third builds on that size reduction.
Initially, we use this new sharding rather than merging tables in
AArch64, LoongArch, RISCV, and X86. Mostly this helps ensure the system
works, as without further changes these still push scaling limits.
Subsequent commits will more deeply leverage the new structure,
including using the prefix capabilities which cannot be easily factored
out here and requires deep changes to the targets.
2024-12-14 09:09:47 +00:00
|
|
|
static constexpr int NumRISCVBuiltins =
|
2024-12-15 03:20:15 +00:00
|
|
|
RISCV::LastTSBuiltin - RISCVVector::FirstTSBuiltin;
|
[StrTable] Switch Clang builtins to use string tables
This both reapplies #118734, the initial attempt at this, and updates it
significantly.
First, it uses the newly added `StringTable` abstraction for string
tables, and simplifies the construction to build the string table and
info arrays separately. This should reduce any `constexpr` compile time
memory or CPU cost of the original PR while significantly improving the
APIs throughout.
It also restructures the builtins to support sharding across several
independent tables. This accomplishes two improvements from the
original PR:
1) It improves the APIs used significantly.
2) When builtins are defined from different sources (like SVE vs MVE in
AArch64), this allows each of them to build their own string table
independently rather than having to merge the string tables and info
structures.
3) It allows each shard to factor out a common prefix, often cutting the
size of the strings needed for the builtins by a factor two.
The second point is important both to allow different mechanisms of
construction (for example a `.def` file and a tablegen'ed `.inc` file,
or different tablegen'ed `.inc files), it also simply reduces the sizes
of these tables which is valuable given how large they are in some
cases. The third builds on that size reduction.
Initially, we use this new sharding rather than merging tables in
AArch64, LoongArch, RISCV, and X86. Mostly this helps ensure the system
works, as without further changes these still push scaling limits.
Subsequent commits will more deeply leverage the new structure,
including using the prefix capabilities which cannot be easily factored
out here and requires deep changes to the targets.
2024-12-14 09:09:47 +00:00
|
|
|
static constexpr int NumBuiltins =
|
2024-12-15 03:20:15 +00:00
|
|
|
RISCV::LastTSBuiltin - Builtin::FirstTSBuiltin;
|
|
|
|
static_assert(NumBuiltins ==
|
|
|
|
(NumRVVBuiltins + NumRVVSiFiveBuiltins + NumRISCVBuiltins));
|
|
|
|
|
|
|
|
namespace RVV {
|
|
|
|
#define GET_RISCVV_BUILTIN_STR_TABLE
|
|
|
|
#include "clang/Basic/riscv_vector_builtins.inc"
|
|
|
|
#undef GET_RISCVV_BUILTIN_STR_TABLE
|
|
|
|
static_assert(BuiltinStrings.size() < 100'000);
|
|
|
|
|
|
|
|
static constexpr std::array<Builtin::Info, NumRVVBuiltins> BuiltinInfos = {
|
|
|
|
#define GET_RISCVV_BUILTIN_INFOS
|
|
|
|
#include "clang/Basic/riscv_vector_builtins.inc"
|
|
|
|
#undef GET_RISCVV_BUILTIN_INFOS
|
|
|
|
};
|
|
|
|
} // namespace RVV
|
|
|
|
|
|
|
|
namespace RVVSiFive {
|
|
|
|
#define GET_RISCVV_BUILTIN_STR_TABLE
|
|
|
|
#include "clang/Basic/riscv_sifive_vector_builtins.inc"
|
|
|
|
#undef GET_RISCVV_BUILTIN_STR_TABLE
|
|
|
|
|
|
|
|
static constexpr std::array<Builtin::Info, NumRVVSiFiveBuiltins> BuiltinInfos =
|
|
|
|
{
|
|
|
|
#define GET_RISCVV_BUILTIN_INFOS
|
|
|
|
#include "clang/Basic/riscv_sifive_vector_builtins.inc"
|
|
|
|
#undef GET_RISCVV_BUILTIN_INFOS
|
|
|
|
};
|
|
|
|
} // namespace RVVSiFive
|
|
|
|
|
2024-12-17 19:21:27 +00:00
|
|
|
#define GET_BUILTIN_STR_TABLE
|
2024-02-09 20:27:17 +08:00
|
|
|
#include "clang/Basic/BuiltinsRISCV.inc"
|
2024-12-17 19:21:27 +00:00
|
|
|
#undef GET_BUILTIN_STR_TABLE
|
2021-02-04 12:57:44 +08:00
|
|
|
|
2024-12-17 19:21:27 +00:00
|
|
|
static constexpr Builtin::Info BuiltinInfos[] = {
|
|
|
|
#define GET_BUILTIN_INFOS
|
[StrTable] Switch Clang builtins to use string tables
This both reapplies #118734, the initial attempt at this, and updates it
significantly.
First, it uses the newly added `StringTable` abstraction for string
tables, and simplifies the construction to build the string table and
info arrays separately. This should reduce any `constexpr` compile time
memory or CPU cost of the original PR while significantly improving the
APIs throughout.
It also restructures the builtins to support sharding across several
independent tables. This accomplishes two improvements from the
original PR:
1) It improves the APIs used significantly.
2) When builtins are defined from different sources (like SVE vs MVE in
AArch64), this allows each of them to build their own string table
independently rather than having to merge the string tables and info
structures.
3) It allows each shard to factor out a common prefix, often cutting the
size of the strings needed for the builtins by a factor two.
The second point is important both to allow different mechanisms of
construction (for example a `.def` file and a tablegen'ed `.inc` file,
or different tablegen'ed `.inc files), it also simply reduces the sizes
of these tables which is valuable given how large they are in some
cases. The third builds on that size reduction.
Initially, we use this new sharding rather than merging tables in
AArch64, LoongArch, RISCV, and X86. Mostly this helps ensure the system
works, as without further changes these still push scaling limits.
Subsequent commits will more deeply leverage the new structure,
including using the prefix capabilities which cannot be easily factored
out here and requires deep changes to the targets.
2024-12-14 09:09:47 +00:00
|
|
|
#include "clang/Basic/BuiltinsRISCV.inc"
|
2024-12-17 19:21:27 +00:00
|
|
|
#undef GET_BUILTIN_INFOS
|
|
|
|
};
|
|
|
|
static_assert(std::size(BuiltinInfos) == NumRISCVBuiltins);
|
[StrTable] Switch Clang builtins to use string tables
This both reapplies #118734, the initial attempt at this, and updates it
significantly.
First, it uses the newly added `StringTable` abstraction for string
tables, and simplifies the construction to build the string table and
info arrays separately. This should reduce any `constexpr` compile time
memory or CPU cost of the original PR while significantly improving the
APIs throughout.
It also restructures the builtins to support sharding across several
independent tables. This accomplishes two improvements from the
original PR:
1) It improves the APIs used significantly.
2) When builtins are defined from different sources (like SVE vs MVE in
AArch64), this allows each of them to build their own string table
independently rather than having to merge the string tables and info
structures.
3) It allows each shard to factor out a common prefix, often cutting the
size of the strings needed for the builtins by a factor two.
The second point is important both to allow different mechanisms of
construction (for example a `.def` file and a tablegen'ed `.inc` file,
or different tablegen'ed `.inc files), it also simply reduces the sizes
of these tables which is valuable given how large they are in some
cases. The third builds on that size reduction.
Initially, we use this new sharding rather than merging tables in
AArch64, LoongArch, RISCV, and X86. Mostly this helps ensure the system
works, as without further changes these still push scaling limits.
Subsequent commits will more deeply leverage the new structure,
including using the prefix capabilities which cannot be easily factored
out here and requires deep changes to the targets.
2024-12-14 09:09:47 +00:00
|
|
|
|
|
|
|
llvm::SmallVector<Builtin::InfosShard>
|
|
|
|
RISCVTargetInfo::getTargetBuiltins() const {
|
|
|
|
return {
|
2024-12-15 03:20:15 +00:00
|
|
|
{&RVV::BuiltinStrings, RVV::BuiltinInfos, "__builtin_rvv_"},
|
|
|
|
{&RVVSiFive::BuiltinStrings, RVVSiFive::BuiltinInfos, "__builtin_rvv_"},
|
|
|
|
{&BuiltinStrings, BuiltinInfos},
|
[StrTable] Switch Clang builtins to use string tables
This both reapplies #118734, the initial attempt at this, and updates it
significantly.
First, it uses the newly added `StringTable` abstraction for string
tables, and simplifies the construction to build the string table and
info arrays separately. This should reduce any `constexpr` compile time
memory or CPU cost of the original PR while significantly improving the
APIs throughout.
It also restructures the builtins to support sharding across several
independent tables. This accomplishes two improvements from the
original PR:
1) It improves the APIs used significantly.
2) When builtins are defined from different sources (like SVE vs MVE in
AArch64), this allows each of them to build their own string table
independently rather than having to merge the string tables and info
structures.
3) It allows each shard to factor out a common prefix, often cutting the
size of the strings needed for the builtins by a factor two.
The second point is important both to allow different mechanisms of
construction (for example a `.def` file and a tablegen'ed `.inc` file,
or different tablegen'ed `.inc files), it also simply reduces the sizes
of these tables which is valuable given how large they are in some
cases. The third builds on that size reduction.
Initially, we use this new sharding rather than merging tables in
AArch64, LoongArch, RISCV, and X86. Mostly this helps ensure the system
works, as without further changes these still push scaling limits.
Subsequent commits will more deeply leverage the new structure,
including using the prefix capabilities which cannot be easily factored
out here and requires deep changes to the targets.
2024-12-14 09:09:47 +00:00
|
|
|
};
|
2021-02-04 12:57:44 +08:00
|
|
|
}
|
|
|
|
|
2021-04-08 09:12:57 -07:00
|
|
|
bool RISCVTargetInfo::initFeatureMap(
|
|
|
|
llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU,
|
|
|
|
const std::vector<std::string> &FeaturesVec) const {
|
|
|
|
|
2021-11-06 02:05:43 -07:00
|
|
|
unsigned XLen = 32;
|
|
|
|
|
2023-12-09 14:02:11 -08:00
|
|
|
if (getTriple().isRISCV64()) {
|
2021-04-08 09:12:57 -07:00
|
|
|
Features["64bit"] = true;
|
2021-11-06 02:05:43 -07:00
|
|
|
XLen = 64;
|
2022-09-06 14:45:17 -07:00
|
|
|
} else {
|
|
|
|
Features["32bit"] = true;
|
2021-11-06 02:05:43 -07:00
|
|
|
}
|
|
|
|
|
[RISCV] Overwrite cpu target features for full arch string in target attribute (#77426)
This patch reworks RISCVTargetInfo::initFeatureMap to fix the issue
described
in
https://github.com/llvm/llvm-project/pull/74889#pullrequestreview-1773445559
(and is an alternative to #75804)
When a full arch string is specified, a "full" list of extensions is now
passed
after the __RISCV_TargetAttrNeedOverride marker feature, which includes
any
negative features that disable ISA extensions.
In initFeatureMap, there are now two code paths:
1. If the arch string was overriden, use the "full" list of override
features,
only adding back any non-isa features that were specified.
Using the full list of positive and negative features will mean that the
target-cpu will have no effect on the final arch, e.g.
__attribute__((target("arch=rv64i"))) with -mcpu=sifive-x280 will have
the
features for rv64i, not a mix of both.
2. Otherwise, parse and *append* the list of implied features. By
appending, we
turn back on any features that might have been disabled by a negative
extension, i.e. this handles the case fixed in #74889.
2024-01-17 13:32:03 +07:00
|
|
|
std::vector<std::string> AllFeatures = FeaturesVec;
|
|
|
|
auto ParseResult = llvm::RISCVISAInfo::parseFeatures(XLen, FeaturesVec);
|
2021-11-06 02:05:43 -07:00
|
|
|
if (!ParseResult) {
|
|
|
|
std::string Buffer;
|
|
|
|
llvm::raw_string_ostream OutputErrMsg(Buffer);
|
|
|
|
handleAllErrors(ParseResult.takeError(), [&](llvm::StringError &ErrMsg) {
|
|
|
|
OutputErrMsg << ErrMsg.getMessage();
|
|
|
|
});
|
|
|
|
Diags.Report(diag::err_invalid_feature_combination) << OutputErrMsg.str();
|
|
|
|
return false;
|
|
|
|
}
|
2021-04-08 09:12:57 -07:00
|
|
|
|
[RISCV] Overwrite cpu target features for full arch string in target attribute (#77426)
This patch reworks RISCVTargetInfo::initFeatureMap to fix the issue
described
in
https://github.com/llvm/llvm-project/pull/74889#pullrequestreview-1773445559
(and is an alternative to #75804)
When a full arch string is specified, a "full" list of extensions is now
passed
after the __RISCV_TargetAttrNeedOverride marker feature, which includes
any
negative features that disable ISA extensions.
In initFeatureMap, there are now two code paths:
1. If the arch string was overriden, use the "full" list of override
features,
only adding back any non-isa features that were specified.
Using the full list of positive and negative features will mean that the
target-cpu will have no effect on the final arch, e.g.
__attribute__((target("arch=rv64i"))) with -mcpu=sifive-x280 will have
the
features for rv64i, not a mix of both.
2. Otherwise, parse and *append* the list of implied features. By
appending, we
turn back on any features that might have been disabled by a negative
extension, i.e. this handles the case fixed in #74889.
2024-01-17 13:32:03 +07:00
|
|
|
// Append all features, not just new ones, so we override any negatives.
|
|
|
|
llvm::append_range(AllFeatures, (*ParseResult)->toFeatures());
|
|
|
|
return TargetInfo::initFeatureMap(Features, Diags, CPU, AllFeatures);
|
2021-04-08 09:12:57 -07:00
|
|
|
}
|
|
|
|
|
2023-01-14 12:31:01 -08:00
|
|
|
std::optional<std::pair<unsigned, unsigned>>
|
2025-01-31 07:57:43 +00:00
|
|
|
RISCVTargetInfo::getVScaleRange(const LangOptions &LangOpts,
|
|
|
|
bool IsArmStreamingFunction) const {
|
2023-01-17 11:32:08 -08:00
|
|
|
// RISCV::RVVBitsPerBlock is 64.
|
|
|
|
unsigned VScaleMin = ISAInfo->getMinVLen() / llvm::RISCV::RVVBitsPerBlock;
|
|
|
|
|
|
|
|
if (LangOpts.VScaleMin || LangOpts.VScaleMax) {
|
|
|
|
// Treat Zvl*b as a lower bound on vscale.
|
|
|
|
VScaleMin = std::max(VScaleMin, LangOpts.VScaleMin);
|
|
|
|
unsigned VScaleMax = LangOpts.VScaleMax;
|
|
|
|
if (VScaleMax != 0 && VScaleMax < VScaleMin)
|
|
|
|
VScaleMax = VScaleMin;
|
|
|
|
return std::pair<unsigned, unsigned>(VScaleMin ? VScaleMin : 1, VScaleMax);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (VScaleMin > 0) {
|
|
|
|
unsigned VScaleMax = ISAInfo->getMaxVLen() / llvm::RISCV::RVVBitsPerBlock;
|
|
|
|
return std::make_pair(VScaleMin, VScaleMax);
|
2022-10-19 16:05:39 -07:00
|
|
|
}
|
2022-10-17 10:09:58 -07:00
|
|
|
|
2022-12-03 11:34:27 -08:00
|
|
|
return std::nullopt;
|
2022-10-17 10:09:58 -07:00
|
|
|
}
|
|
|
|
|
2018-04-05 12:54:00 +00:00
|
|
|
/// Return true if has this feature, need to sync with handleTargetFeatures.
|
|
|
|
bool RISCVTargetInfo::hasFeature(StringRef Feature) const {
|
2023-12-09 14:02:11 -08:00
|
|
|
bool Is64Bit = getTriple().isRISCV64();
|
2022-12-09 22:52:29 -08:00
|
|
|
auto Result = llvm::StringSwitch<std::optional<bool>>(Feature)
|
2021-06-23 16:18:54 +08:00
|
|
|
.Case("riscv", true)
|
|
|
|
.Case("riscv32", !Is64Bit)
|
|
|
|
.Case("riscv64", Is64Bit)
|
2022-09-06 14:45:17 -07:00
|
|
|
.Case("32bit", !Is64Bit)
|
2021-06-23 16:18:54 +08:00
|
|
|
.Case("64bit", Is64Bit)
|
2023-12-18 22:04:22 -08:00
|
|
|
.Case("experimental", HasExperimental)
|
2022-12-03 11:34:27 -08:00
|
|
|
.Default(std::nullopt);
|
2022-06-25 22:26:24 -07:00
|
|
|
if (Result)
|
2022-12-17 00:42:05 +00:00
|
|
|
return *Result;
|
2021-06-23 16:18:54 +08:00
|
|
|
|
2023-12-09 14:16:09 -08:00
|
|
|
return ISAInfo->hasExtension(Feature);
|
2018-04-05 12:54:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Perform initialization based on the user configured set of features.
|
|
|
|
bool RISCVTargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
|
|
|
|
DiagnosticsEngine &Diags) {
|
2021-06-23 16:18:54 +08:00
|
|
|
unsigned XLen = getTriple().isArch64Bit() ? 64 : 32;
|
|
|
|
auto ParseResult = llvm::RISCVISAInfo::parseFeatures(XLen, Features);
|
|
|
|
if (!ParseResult) {
|
|
|
|
std::string Buffer;
|
|
|
|
llvm::raw_string_ostream OutputErrMsg(Buffer);
|
|
|
|
handleAllErrors(ParseResult.takeError(), [&](llvm::StringError &ErrMsg) {
|
|
|
|
OutputErrMsg << ErrMsg.getMessage();
|
|
|
|
});
|
|
|
|
Diags.Report(diag::err_invalid_feature_combination) << OutputErrMsg.str();
|
|
|
|
return false;
|
|
|
|
} else {
|
|
|
|
ISAInfo = std::move(*ParseResult);
|
2018-04-05 12:54:00 +00:00
|
|
|
}
|
|
|
|
|
2021-11-04 10:13:50 -07:00
|
|
|
if (ABI.empty())
|
2022-02-08 07:42:48 -08:00
|
|
|
ABI = ISAInfo->computeDefaultABI().str();
|
2021-11-04 10:13:50 -07:00
|
|
|
|
2023-05-18 15:01:48 +01:00
|
|
|
if (ISAInfo->hasExtension("zfh") || ISAInfo->hasExtension("zhinx"))
|
2023-05-05 13:53:50 +01:00
|
|
|
HasLegalHalfType = true;
|
|
|
|
|
2024-07-14 13:39:17 -07:00
|
|
|
FastScalarUnalignedAccess =
|
|
|
|
llvm::is_contained(Features, "+unaligned-scalar-mem");
|
2023-10-26 15:10:57 +08:00
|
|
|
|
2023-12-18 22:04:22 -08:00
|
|
|
if (llvm::is_contained(Features, "+experimental"))
|
|
|
|
HasExperimental = true;
|
|
|
|
|
2024-01-16 20:44:30 +08:00
|
|
|
if (ABI == "ilp32e" && ISAInfo->hasExtension("d")) {
|
|
|
|
Diags.Report(diag::err_invalid_feature_combination)
|
|
|
|
<< "ILP32E cannot be used with the D ISA extension";
|
|
|
|
return false;
|
|
|
|
}
|
2018-04-05 12:54:00 +00:00
|
|
|
return true;
|
2018-01-11 13:36:56 +00:00
|
|
|
}
|
2020-07-16 10:32:01 -07:00
|
|
|
|
2022-08-11 09:45:32 -07:00
|
|
|
bool RISCVTargetInfo::isValidCPUName(StringRef Name) const {
|
|
|
|
bool Is64Bit = getTriple().isArch64Bit();
|
2023-05-01 13:00:05 -07:00
|
|
|
return llvm::RISCV::parseCPU(Name, Is64Bit);
|
2020-07-16 10:32:01 -07:00
|
|
|
}
|
|
|
|
|
2022-08-11 09:45:32 -07:00
|
|
|
void RISCVTargetInfo::fillValidCPUList(
|
2020-07-16 10:32:01 -07:00
|
|
|
SmallVectorImpl<StringRef> &Values) const {
|
2022-08-11 09:45:32 -07:00
|
|
|
bool Is64Bit = getTriple().isArch64Bit();
|
|
|
|
llvm::RISCV::fillValidCPUArchList(Values, Is64Bit);
|
2020-07-16 10:32:01 -07:00
|
|
|
}
|
|
|
|
|
2022-08-11 09:45:32 -07:00
|
|
|
bool RISCVTargetInfo::isValidTuneCPUName(StringRef Name) const {
|
|
|
|
bool Is64Bit = getTriple().isArch64Bit();
|
2023-05-01 13:00:05 -07:00
|
|
|
return llvm::RISCV::parseTuneCPU(Name, Is64Bit);
|
2020-10-06 14:33:43 +08:00
|
|
|
}
|
|
|
|
|
2022-08-11 09:45:32 -07:00
|
|
|
void RISCVTargetInfo::fillValidTuneCPUList(
|
2020-10-06 14:33:43 +08:00
|
|
|
SmallVectorImpl<StringRef> &Values) const {
|
2022-08-11 09:45:32 -07:00
|
|
|
bool Is64Bit = getTriple().isArch64Bit();
|
|
|
|
llvm::RISCV::fillValidTuneCPUArchList(Values, Is64Bit);
|
2020-10-06 14:33:43 +08:00
|
|
|
}
|
2023-11-23 22:58:35 -08:00
|
|
|
|
2024-08-31 20:02:46 +08:00
|
|
|
static void populateNegativeRISCVFeatures(std::vector<std::string> &Features) {
|
|
|
|
auto RII = llvm::RISCVISAInfo::parseArchString(
|
|
|
|
"rv64i", /* EnableExperimentalExtension */ true);
|
|
|
|
|
|
|
|
if (llvm::errorToBool(RII.takeError()))
|
|
|
|
llvm_unreachable("unsupport rv64i");
|
|
|
|
|
|
|
|
std::vector<std::string> FeatStrings =
|
|
|
|
(*RII)->toFeatures(/* AddAllExtensions */ true);
|
|
|
|
Features.insert(Features.end(), FeatStrings.begin(), FeatStrings.end());
|
|
|
|
}
|
|
|
|
|
2023-11-23 22:58:35 -08:00
|
|
|
static void handleFullArchString(StringRef FullArchStr,
|
|
|
|
std::vector<std::string> &Features) {
|
|
|
|
auto RII = llvm::RISCVISAInfo::parseArchString(
|
|
|
|
FullArchStr, /* EnableExperimentalExtension */ true);
|
2023-12-28 12:59:11 +08:00
|
|
|
if (llvm::errorToBool(RII.takeError())) {
|
2023-11-23 22:58:35 -08:00
|
|
|
// Forward the invalid FullArchStr.
|
2024-09-09 15:07:39 +08:00
|
|
|
Features.push_back(FullArchStr.str());
|
2023-11-23 22:58:35 -08:00
|
|
|
} else {
|
[RISCV] Overwrite cpu target features for full arch string in target attribute (#77426)
This patch reworks RISCVTargetInfo::initFeatureMap to fix the issue
described
in
https://github.com/llvm/llvm-project/pull/74889#pullrequestreview-1773445559
(and is an alternative to #75804)
When a full arch string is specified, a "full" list of extensions is now
passed
after the __RISCV_TargetAttrNeedOverride marker feature, which includes
any
negative features that disable ISA extensions.
In initFeatureMap, there are now two code paths:
1. If the arch string was overriden, use the "full" list of override
features,
only adding back any non-isa features that were specified.
Using the full list of positive and negative features will mean that the
target-cpu will have no effect on the final arch, e.g.
__attribute__((target("arch=rv64i"))) with -mcpu=sifive-x280 will have
the
features for rv64i, not a mix of both.
2. Otherwise, parse and *append* the list of implied features. By
appending, we
turn back on any features that might have been disabled by a negative
extension, i.e. this handles the case fixed in #74889.
2024-01-17 13:32:03 +07:00
|
|
|
// Append a full list of features, including any negative extensions so that
|
|
|
|
// we override the CPU's features.
|
2024-08-31 20:02:46 +08:00
|
|
|
populateNegativeRISCVFeatures(Features);
|
[RISCV] Overwrite cpu target features for full arch string in target attribute (#77426)
This patch reworks RISCVTargetInfo::initFeatureMap to fix the issue
described
in
https://github.com/llvm/llvm-project/pull/74889#pullrequestreview-1773445559
(and is an alternative to #75804)
When a full arch string is specified, a "full" list of extensions is now
passed
after the __RISCV_TargetAttrNeedOverride marker feature, which includes
any
negative features that disable ISA extensions.
In initFeatureMap, there are now two code paths:
1. If the arch string was overriden, use the "full" list of override
features,
only adding back any non-isa features that were specified.
Using the full list of positive and negative features will mean that the
target-cpu will have no effect on the final arch, e.g.
__attribute__((target("arch=rv64i"))) with -mcpu=sifive-x280 will have
the
features for rv64i, not a mix of both.
2. Otherwise, parse and *append* the list of implied features. By
appending, we
turn back on any features that might have been disabled by a negative
extension, i.e. this handles the case fixed in #74889.
2024-01-17 13:32:03 +07:00
|
|
|
std::vector<std::string> FeatStrings =
|
|
|
|
(*RII)->toFeatures(/* AddAllExtensions */ true);
|
2023-11-29 12:57:48 -08:00
|
|
|
Features.insert(Features.end(), FeatStrings.begin(), FeatStrings.end());
|
2023-11-23 22:58:35 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ParsedTargetAttr RISCVTargetInfo::parseTargetAttr(StringRef Features) const {
|
|
|
|
ParsedTargetAttr Ret;
|
|
|
|
if (Features == "default")
|
|
|
|
return Ret;
|
|
|
|
SmallVector<StringRef, 1> AttrFeatures;
|
|
|
|
Features.split(AttrFeatures, ";");
|
|
|
|
bool FoundArch = false;
|
|
|
|
|
2024-11-28 09:22:05 +00:00
|
|
|
auto handleArchExtension = [](StringRef AttrString,
|
|
|
|
std::vector<std::string> &Features) {
|
|
|
|
SmallVector<StringRef, 1> Exts;
|
|
|
|
AttrString.split(Exts, ",");
|
|
|
|
for (auto Ext : Exts) {
|
|
|
|
if (Ext.empty())
|
|
|
|
continue;
|
|
|
|
|
|
|
|
StringRef ExtName = Ext.substr(1);
|
|
|
|
std::string TargetFeature =
|
|
|
|
llvm::RISCVISAInfo::getTargetFeatureForExtension(ExtName);
|
|
|
|
if (!TargetFeature.empty())
|
|
|
|
Features.push_back(Ext.front() + TargetFeature);
|
|
|
|
else
|
|
|
|
Features.push_back(Ext.str());
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2023-11-23 22:58:35 -08:00
|
|
|
for (auto &Feature : AttrFeatures) {
|
|
|
|
Feature = Feature.trim();
|
|
|
|
StringRef AttrString = Feature.split("=").second.trim();
|
|
|
|
|
2023-12-13 08:54:13 -08:00
|
|
|
if (Feature.starts_with("arch=")) {
|
2023-11-23 22:58:35 -08:00
|
|
|
// Override last features
|
|
|
|
Ret.Features.clear();
|
|
|
|
if (FoundArch)
|
|
|
|
Ret.Duplicate = "arch=";
|
|
|
|
FoundArch = true;
|
|
|
|
|
2023-12-13 08:54:13 -08:00
|
|
|
if (AttrString.starts_with("+")) {
|
2023-11-23 22:58:35 -08:00
|
|
|
// EXTENSION like arch=+v,+zbb
|
2024-11-28 09:22:05 +00:00
|
|
|
handleArchExtension(AttrString, Ret.Features);
|
2023-11-23 22:58:35 -08:00
|
|
|
} else {
|
|
|
|
// full-arch-string like arch=rv64gcv
|
|
|
|
handleFullArchString(AttrString, Ret.Features);
|
|
|
|
}
|
2023-12-13 08:54:13 -08:00
|
|
|
} else if (Feature.starts_with("cpu=")) {
|
2023-11-23 22:58:35 -08:00
|
|
|
if (!Ret.CPU.empty())
|
|
|
|
Ret.Duplicate = "cpu=";
|
|
|
|
|
|
|
|
Ret.CPU = AttrString;
|
|
|
|
|
|
|
|
if (!FoundArch) {
|
|
|
|
// Update Features with CPU's features
|
|
|
|
StringRef MarchFromCPU = llvm::RISCV::getMArchFromMcpu(Ret.CPU);
|
|
|
|
if (MarchFromCPU != "") {
|
|
|
|
Ret.Features.clear();
|
|
|
|
handleFullArchString(MarchFromCPU, Ret.Features);
|
|
|
|
}
|
|
|
|
}
|
2023-12-13 08:54:13 -08:00
|
|
|
} else if (Feature.starts_with("tune=")) {
|
2023-11-23 22:58:35 -08:00
|
|
|
if (!Ret.Tune.empty())
|
|
|
|
Ret.Duplicate = "tune=";
|
|
|
|
|
|
|
|
Ret.Tune = AttrString;
|
2024-09-13 18:04:53 +08:00
|
|
|
} else if (Feature.starts_with("priority")) {
|
|
|
|
// Skip because it only use for FMV.
|
2024-11-28 09:22:05 +00:00
|
|
|
} else if (Feature.starts_with("+")) {
|
|
|
|
// Handle target_version/target_clones attribute strings
|
|
|
|
// that are already delimited by ','
|
|
|
|
handleArchExtension(Feature, Ret.Features);
|
2023-11-23 22:58:35 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return Ret;
|
|
|
|
}
|
2024-03-27 23:03:13 +08:00
|
|
|
|
2025-01-08 18:59:07 +00:00
|
|
|
uint64_t RISCVTargetInfo::getFMVPriority(ArrayRef<StringRef> Features) const {
|
2024-11-28 09:22:05 +00:00
|
|
|
// Priority is explicitly specified on RISC-V unlike on other targets, where
|
|
|
|
// it is derived by all the features of a specific version. Therefore if a
|
|
|
|
// feature contains the priority string, then return it immediately.
|
|
|
|
for (StringRef Feature : Features) {
|
|
|
|
auto [LHS, RHS] = Feature.rsplit(';');
|
|
|
|
if (LHS.consume_front("priority="))
|
|
|
|
Feature = LHS;
|
|
|
|
else if (RHS.consume_front("priority="))
|
|
|
|
Feature = RHS;
|
|
|
|
else
|
|
|
|
continue;
|
2025-01-08 18:59:07 +00:00
|
|
|
uint64_t Priority;
|
2024-11-28 09:22:05 +00:00
|
|
|
if (!Feature.getAsInteger(0, Priority))
|
|
|
|
return Priority;
|
|
|
|
}
|
|
|
|
// Default Priority is zero.
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2024-03-27 23:03:13 +08:00
|
|
|
TargetInfo::CallingConvCheckResult
|
|
|
|
RISCVTargetInfo::checkCallingConvention(CallingConv CC) const {
|
|
|
|
switch (CC) {
|
|
|
|
default:
|
|
|
|
return CCCR_Warning;
|
|
|
|
case CC_C:
|
|
|
|
case CC_RISCVVectorCall:
|
2025-03-03 12:39:35 +08:00
|
|
|
case CC_RISCVVLSCall_32:
|
|
|
|
case CC_RISCVVLSCall_64:
|
|
|
|
case CC_RISCVVLSCall_128:
|
|
|
|
case CC_RISCVVLSCall_256:
|
|
|
|
case CC_RISCVVLSCall_512:
|
|
|
|
case CC_RISCVVLSCall_1024:
|
|
|
|
case CC_RISCVVLSCall_2048:
|
|
|
|
case CC_RISCVVLSCall_4096:
|
|
|
|
case CC_RISCVVLSCall_8192:
|
|
|
|
case CC_RISCVVLSCall_16384:
|
|
|
|
case CC_RISCVVLSCall_32768:
|
|
|
|
case CC_RISCVVLSCall_65536:
|
2024-03-27 23:03:13 +08:00
|
|
|
return CCCR_OK;
|
|
|
|
}
|
|
|
|
}
|
2024-07-23 08:48:28 -07:00
|
|
|
|
|
|
|
bool RISCVTargetInfo::validateCpuSupports(StringRef Feature) const {
|
|
|
|
// Only allow extensions we have a known bit position for in the
|
|
|
|
// __riscv_feature_bits structure.
|
2024-08-08 14:42:41 +08:00
|
|
|
return -1 != llvm::RISCVISAInfo::getRISCVFeaturesBitsInfo(Feature).second;
|
2024-07-23 08:48:28 -07:00
|
|
|
}
|
2024-09-09 15:07:39 +08:00
|
|
|
|
|
|
|
bool RISCVTargetInfo::isValidFeatureName(StringRef Name) const {
|
|
|
|
return llvm::RISCVISAInfo::isSupportedExtensionFeature(Name);
|
|
|
|
}
|
2024-09-23 10:24:27 -07:00
|
|
|
|
|
|
|
bool RISCVTargetInfo::validateGlobalRegisterVariable(
|
|
|
|
StringRef RegName, unsigned RegSize, bool &HasSizeMismatch) const {
|
|
|
|
if (RegName == "ra" || RegName == "sp" || RegName == "gp" ||
|
|
|
|
RegName == "tp" || RegName.starts_with("x") || RegName.starts_with("a") ||
|
|
|
|
RegName.starts_with("s") || RegName.starts_with("t")) {
|
|
|
|
unsigned XLen = getTriple().isArch64Bit() ? 64 : 32;
|
|
|
|
HasSizeMismatch = RegSize != XLen;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
2024-11-22 20:04:57 +08:00
|
|
|
|
|
|
|
bool RISCVTargetInfo::validateCpuIs(StringRef CPUName) const {
|
|
|
|
assert(getTriple().isOSLinux() &&
|
|
|
|
"__builtin_cpu_is() is only supported for Linux.");
|
|
|
|
|
|
|
|
return llvm::RISCV::hasValidCPUModel(CPUName);
|
|
|
|
}
|