RISCV.cpp revision 360784
160484Sobrien//===--- RISCV.cpp - Implement RISCV target feature support ---------------===//
278828Sobrien//
360484Sobrien// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
460484Sobrien// See https://llvm.org/LICENSE.txt for license information.
560484Sobrien// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
660484Sobrien//
760484Sobrien//===----------------------------------------------------------------------===//
860484Sobrien//
960484Sobrien// This file implements RISCV TargetInfo objects.
1060484Sobrien//
1160484Sobrien//===----------------------------------------------------------------------===//
1260484Sobrien
1360484Sobrien#include "RISCV.h"
1460484Sobrien#include "clang/Basic/MacroBuilder.h"
1560484Sobrien#include "llvm/ADT/StringSwitch.h"
1660484Sobrien
1760484Sobrienusing namespace clang;
1860484Sobrienusing namespace clang::targets;
1960484Sobrien
2060484SobrienArrayRef<const char *> RISCVTargetInfo::getGCCRegNames() const {
2160484Sobrien  static const char *const GCCRegNames[] = {
2260484Sobrien      // Integer registers
2360484Sobrien      "x0",  "x1",  "x2",  "x3",  "x4",  "x5",  "x6",  "x7",
2460484Sobrien      "x8",  "x9",  "x10", "x11", "x12", "x13", "x14", "x15",
2560484Sobrien      "x16", "x17", "x18", "x19", "x20", "x21", "x22", "x23",
2660484Sobrien      "x24", "x25", "x26", "x27", "x28", "x29", "x30", "x31",
2760484Sobrien
2860484Sobrien      // Floating point registers
2960484Sobrien      "f0",  "f1",  "f2",  "f3",  "f4",  "f5",  "f6",  "f7",
3060484Sobrien      "f8",  "f9",  "f10", "f11", "f12", "f13", "f14", "f15",
3160484Sobrien      "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
3260484Sobrien      "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31"};
3360484Sobrien  return llvm::makeArrayRef(GCCRegNames);
3460484Sobrien}
3560484Sobrien
3660484SobrienArrayRef<TargetInfo::GCCRegAlias> RISCVTargetInfo::getGCCRegAliases() const {
3760484Sobrien  static const TargetInfo::GCCRegAlias GCCRegAliases[] = {
3860484Sobrien      {{"zero"}, "x0"}, {{"ra"}, "x1"},   {{"sp"}, "x2"},    {{"gp"}, "x3"},
3960484Sobrien      {{"tp"}, "x4"},   {{"t0"}, "x5"},   {{"t1"}, "x6"},    {{"t2"}, "x7"},
4060484Sobrien      {{"s0"}, "x8"},   {{"s1"}, "x9"},   {{"a0"}, "x10"},   {{"a1"}, "x11"},
4160484Sobrien      {{"a2"}, "x12"},  {{"a3"}, "x13"},  {{"a4"}, "x14"},   {{"a5"}, "x15"},
4260484Sobrien      {{"a6"}, "x16"},  {{"a7"}, "x17"},  {{"s2"}, "x18"},   {{"s3"}, "x19"},
4360484Sobrien      {{"s4"}, "x20"},  {{"s5"}, "x21"},  {{"s6"}, "x22"},   {{"s7"}, "x23"},
4460484Sobrien      {{"s8"}, "x24"},  {{"s9"}, "x25"},  {{"s10"}, "x26"},  {{"s11"}, "x27"},
4560484Sobrien      {{"t3"}, "x28"},  {{"t4"}, "x29"},  {{"t5"}, "x30"},   {{"t6"}, "x31"},
4660484Sobrien      {{"ft0"}, "f0"},  {{"ft1"}, "f1"},  {{"ft2"}, "f2"},   {{"ft3"}, "f3"},
4760484Sobrien      {{"ft4"}, "f4"},  {{"ft5"}, "f5"},  {{"ft6"}, "f6"},   {{"ft7"}, "f7"},
4860484Sobrien      {{"fs0"}, "f8"},  {{"fs1"}, "f9"},  {{"fa0"}, "f10"},  {{"fa1"}, "f11"},
4960484Sobrien      {{"fa2"}, "f12"}, {{"fa3"}, "f13"}, {{"fa4"}, "f14"},  {{"fa5"}, "f15"},
5060484Sobrien      {{"fa6"}, "f16"}, {{"fa7"}, "f17"}, {{"fs2"}, "f18"},  {{"fs3"}, "f19"},
5160484Sobrien      {{"fs4"}, "f20"}, {{"fs5"}, "f21"}, {{"fs6"}, "f22"},  {{"fs7"}, "f23"},
5260484Sobrien      {{"fs8"}, "f24"}, {{"fs9"}, "f25"}, {{"fs10"}, "f26"}, {{"fs11"}, "f27"},
5360484Sobrien      {{"ft8"}, "f28"}, {{"ft9"}, "f29"}, {{"ft10"}, "f30"}, {{"ft11"}, "f31"}};
5460484Sobrien  return llvm::makeArrayRef(GCCRegAliases);
5560484Sobrien}
5660484Sobrien
5760484Sobrienbool RISCVTargetInfo::validateAsmConstraint(
5860484Sobrien    const char *&Name, TargetInfo::ConstraintInfo &Info) const {
5960484Sobrien  switch (*Name) {
6060484Sobrien  default:
6160484Sobrien    return false;
6260484Sobrien  case 'I':
6360484Sobrien    // A 12-bit signed immediate.
6460484Sobrien    Info.setRequiresImmediate(-2048, 2047);
6560484Sobrien    return true;
6660484Sobrien  case 'J':
6760484Sobrien    // Integer zero.
6860484Sobrien    Info.setRequiresImmediate(0);
6960484Sobrien    return true;
7060484Sobrien  case 'K':
7160484Sobrien    // A 5-bit unsigned immediate for CSR access instructions.
7260484Sobrien    Info.setRequiresImmediate(0, 31);
7360484Sobrien    return true;
7460484Sobrien  case 'f':
7560484Sobrien    // A floating-point register.
7660484Sobrien    Info.setAllowsRegister();
7760484Sobrien    return true;
7860484Sobrien  case 'A':
7960484Sobrien    // An address that is held in a general-purpose register.
8060484Sobrien    Info.setAllowsMemory();
8160484Sobrien    return true;
8260484Sobrien  }
8360484Sobrien}
8460484Sobrien
8560484Sobrienvoid RISCVTargetInfo::getTargetDefines(const LangOptions &Opts,
8660484Sobrien                                       MacroBuilder &Builder) const {
8760484Sobrien  Builder.defineMacro("__ELF__");
8860484Sobrien  Builder.defineMacro("__riscv");
8960484Sobrien  bool Is64Bit = getTriple().getArch() == llvm::Triple::riscv64;
9060484Sobrien  Builder.defineMacro("__riscv_xlen", Is64Bit ? "64" : "32");
9160484Sobrien  StringRef CodeModel = getTargetOpts().CodeModel;
9260484Sobrien  if (CodeModel == "default")
9360484Sobrien    CodeModel = "small";
9460484Sobrien
9560484Sobrien  if (CodeModel == "small")
9660484Sobrien    Builder.defineMacro("__riscv_cmodel_medlow");
9760484Sobrien  else if (CodeModel == "medium")
9860484Sobrien    Builder.defineMacro("__riscv_cmodel_medany");
9960484Sobrien
10060484Sobrien  StringRef ABIName = getABI();
10160484Sobrien  if (ABIName == "ilp32f" || ABIName == "lp64f")
10260484Sobrien    Builder.defineMacro("__riscv_float_abi_single");
10360484Sobrien  else if (ABIName == "ilp32d" || ABIName == "lp64d")
10460484Sobrien    Builder.defineMacro("__riscv_float_abi_double");
10560484Sobrien  else
10660484Sobrien    Builder.defineMacro("__riscv_float_abi_soft");
10760484Sobrien
10860484Sobrien  if (ABIName == "ilp32e")
10960484Sobrien    Builder.defineMacro("__riscv_abi_rve");
11060484Sobrien
11160484Sobrien  if (HasM) {
11260484Sobrien    Builder.defineMacro("__riscv_mul");
11360484Sobrien    Builder.defineMacro("__riscv_div");
11460484Sobrien    Builder.defineMacro("__riscv_muldiv");
11560484Sobrien  }
11660484Sobrien
11760484Sobrien  if (HasA)
11860484Sobrien    Builder.defineMacro("__riscv_atomic");
11960484Sobrien
12060484Sobrien  if (HasF || HasD) {
12160484Sobrien    Builder.defineMacro("__riscv_flen", HasD ? "64" : "32");
12260484Sobrien    Builder.defineMacro("__riscv_fdiv");
12360484Sobrien    Builder.defineMacro("__riscv_fsqrt");
12460484Sobrien  }
12560484Sobrien
12660484Sobrien  if (HasC)
12760484Sobrien    Builder.defineMacro("__riscv_compressed");
12860484Sobrien}
12960484Sobrien
13060484Sobrien/// Return true if has this feature, need to sync with handleTargetFeatures.
13160484Sobrienbool RISCVTargetInfo::hasFeature(StringRef Feature) const {
13260484Sobrien  bool Is64Bit = getTriple().getArch() == llvm::Triple::riscv64;
13360484Sobrien  return llvm::StringSwitch<bool>(Feature)
13460484Sobrien      .Case("riscv", true)
13560484Sobrien      .Case("riscv32", !Is64Bit)
13660484Sobrien      .Case("riscv64", Is64Bit)
13760484Sobrien      .Case("m", HasM)
13860484Sobrien      .Case("a", HasA)
13960484Sobrien      .Case("f", HasF)
14060484Sobrien      .Case("d", HasD)
14160484Sobrien      .Case("c", HasC)
14260484Sobrien      .Default(false);
14360484Sobrien}
14460484Sobrien
14560484Sobrien/// Perform initialization based on the user configured set of features.
14660484Sobrienbool RISCVTargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
14760484Sobrien                                           DiagnosticsEngine &Diags) {
14860484Sobrien  for (const auto &Feature : Features) {
14960484Sobrien    if (Feature == "+m")
15060484Sobrien      HasM = true;
15160484Sobrien    else if (Feature == "+a")
15260484Sobrien      HasA = true;
15360484Sobrien    else if (Feature == "+f")
15460484Sobrien      HasF = true;
15560484Sobrien    else if (Feature == "+d")
15660484Sobrien      HasD = true;
15760484Sobrien    else if (Feature == "+c")
15860484Sobrien      HasC = true;
15960484Sobrien  }
16060484Sobrien
16160484Sobrien  return true;
16260484Sobrien}
16360484Sobrien