1 //===--- RISCV.cpp - Implement RISCV target feature support ---------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file implements RISCV TargetInfo objects.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "RISCV.h"
14 #include "clang/Basic/MacroBuilder.h"
15 #include "llvm/ADT/StringSwitch.h"
16 
17 using namespace clang;
18 using namespace clang::targets;
19 
20 ArrayRef<const char *> RISCVTargetInfo::getGCCRegNames() const {
21   static const char *const GCCRegNames[] = {
22       // Integer registers
23       "x0",  "x1",  "x2",  "x3",  "x4",  "x5",  "x6",  "x7",
24       "x8",  "x9",  "x10", "x11", "x12", "x13", "x14", "x15",
25       "x16", "x17", "x18", "x19", "x20", "x21", "x22", "x23",
26       "x24", "x25", "x26", "x27", "x28", "x29", "x30", "x31",
27 
28       // Floating point registers
29       "f0",  "f1",  "f2",  "f3",  "f4",  "f5",  "f6",  "f7",
30       "f8",  "f9",  "f10", "f11", "f12", "f13", "f14", "f15",
31       "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
32       "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31"};
33   return llvm::makeArrayRef(GCCRegNames);
34 }
35 
36 ArrayRef<TargetInfo::GCCRegAlias> RISCVTargetInfo::getGCCRegAliases() const {
37   static const TargetInfo::GCCRegAlias GCCRegAliases[] = {
38       {{"zero"}, "x0"}, {{"ra"}, "x1"},   {{"sp"}, "x2"},    {{"gp"}, "x3"},
39       {{"tp"}, "x4"},   {{"t0"}, "x5"},   {{"t1"}, "x6"},    {{"t2"}, "x7"},
40       {{"s0"}, "x8"},   {{"s1"}, "x9"},   {{"a0"}, "x10"},   {{"a1"}, "x11"},
41       {{"a2"}, "x12"},  {{"a3"}, "x13"},  {{"a4"}, "x14"},   {{"a5"}, "x15"},
42       {{"a6"}, "x16"},  {{"a7"}, "x17"},  {{"s2"}, "x18"},   {{"s3"}, "x19"},
43       {{"s4"}, "x20"},  {{"s5"}, "x21"},  {{"s6"}, "x22"},   {{"s7"}, "x23"},
44       {{"s8"}, "x24"},  {{"s9"}, "x25"},  {{"s10"}, "x26"},  {{"s11"}, "x27"},
45       {{"t3"}, "x28"},  {{"t4"}, "x29"},  {{"t5"}, "x30"},   {{"t6"}, "x31"},
46       {{"ft0"}, "f0"},  {{"ft1"}, "f1"},  {{"ft2"}, "f2"},   {{"ft3"}, "f3"},
47       {{"ft4"}, "f4"},  {{"ft5"}, "f5"},  {{"ft6"}, "f6"},   {{"ft7"}, "f7"},
48       {{"fs0"}, "f8"},  {{"fs1"}, "f9"},  {{"fa0"}, "f10"},  {{"fa1"}, "f11"},
49       {{"fa2"}, "f12"}, {{"fa3"}, "f13"}, {{"fa4"}, "f14"},  {{"fa5"}, "f15"},
50       {{"fa6"}, "f16"}, {{"fa7"}, "f17"}, {{"fs2"}, "f18"},  {{"fs3"}, "f19"},
51       {{"fs4"}, "f20"}, {{"fs5"}, "f21"}, {{"fs6"}, "f22"},  {{"fs7"}, "f23"},
52       {{"fs8"}, "f24"}, {{"fs9"}, "f25"}, {{"fs10"}, "f26"}, {{"fs11"}, "f27"},
53       {{"ft8"}, "f28"}, {{"ft9"}, "f29"}, {{"ft10"}, "f30"}, {{"ft11"}, "f31"}};
54   return llvm::makeArrayRef(GCCRegAliases);
55 }
56 
57 bool RISCVTargetInfo::validateAsmConstraint(
58     const char *&Name, TargetInfo::ConstraintInfo &Info) const {
59   switch (*Name) {
60   default:
61     return false;
62   case 'I':
63     // A 12-bit signed immediate.
64     Info.setRequiresImmediate(-2048, 2047);
65     return true;
66   case 'J':
67     // Integer zero.
68     Info.setRequiresImmediate(0);
69     return true;
70   case 'K':
71     // A 5-bit unsigned immediate for CSR access instructions.
72     Info.setRequiresImmediate(0, 31);
73     return true;
74   case 'f':
75     // A floating-point register.
76     Info.setAllowsRegister();
77     return true;
78   case 'A':
79     // An address that is held in a general-purpose register.
80     Info.setAllowsMemory();
81     return true;
82   }
83 }
84 
85 void RISCVTargetInfo::getTargetDefines(const LangOptions &Opts,
86                                        MacroBuilder &Builder) const {
87   Builder.defineMacro("__ELF__");
88   Builder.defineMacro("__riscv");
89   bool Is64Bit = getTriple().getArch() == llvm::Triple::riscv64;
90   Builder.defineMacro("__riscv_xlen", Is64Bit ? "64" : "32");
91   StringRef CodeModel = getTargetOpts().CodeModel;
92   if (CodeModel == "default")
93     CodeModel = "small";
94 
95   if (CodeModel == "small")
96     Builder.defineMacro("__riscv_cmodel_medlow");
97   else if (CodeModel == "medium")
98     Builder.defineMacro("__riscv_cmodel_medany");
99 
100   StringRef ABIName = getABI();
101   if (ABIName == "ilp32f" || ABIName == "lp64f")
102     Builder.defineMacro("__riscv_float_abi_single");
103   else if (ABIName == "ilp32d" || ABIName == "lp64d")
104     Builder.defineMacro("__riscv_float_abi_double");
105   else
106     Builder.defineMacro("__riscv_float_abi_soft");
107 
108   if (ABIName == "ilp32e")
109     Builder.defineMacro("__riscv_abi_rve");
110 
111   if (HasM) {
112     Builder.defineMacro("__riscv_mul");
113     Builder.defineMacro("__riscv_div");
114     Builder.defineMacro("__riscv_muldiv");
115   }
116 
117   if (HasA)
118     Builder.defineMacro("__riscv_atomic");
119 
120   if (HasF || HasD) {
121     Builder.defineMacro("__riscv_flen", HasD ? "64" : "32");
122     Builder.defineMacro("__riscv_fdiv");
123     Builder.defineMacro("__riscv_fsqrt");
124   }
125 
126   if (HasC)
127     Builder.defineMacro("__riscv_compressed");
128 }
129 
130 /// Return true if has this feature, need to sync with handleTargetFeatures.
131 bool RISCVTargetInfo::hasFeature(StringRef Feature) const {
132   bool Is64Bit = getTriple().getArch() == llvm::Triple::riscv64;
133   return llvm::StringSwitch<bool>(Feature)
134       .Case("riscv", true)
135       .Case("riscv32", !Is64Bit)
136       .Case("riscv64", Is64Bit)
137       .Case("m", HasM)
138       .Case("a", HasA)
139       .Case("f", HasF)
140       .Case("d", HasD)
141       .Case("c", HasC)
142       .Default(false);
143 }
144 
145 /// Perform initialization based on the user configured set of features.
146 bool RISCVTargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
147                                            DiagnosticsEngine &Diags) {
148   for (const auto &Feature : Features) {
149     if (Feature == "+m")
150       HasM = true;
151     else if (Feature == "+a")
152       HasA = true;
153     else if (Feature == "+f")
154       HasF = true;
155     else if (Feature == "+d")
156       HasD = true;
157     else if (Feature == "+c")
158       HasC = true;
159   }
160 
161   return true;
162 }
163