1 //===--- RISCV.cpp - RISC-V Helpers for Tools -------------------*- C++ -*-===//
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 #include "RISCV.h"
10 #include "../Clang.h"
11 #include "ToolChains/CommonArgs.h"
12 #include "clang/Basic/CharInfo.h"
13 #include "clang/Driver/Driver.h"
14 #include "clang/Driver/DriverDiagnostic.h"
15 #include "clang/Driver/Options.h"
16 #include "llvm/Option/ArgList.h"
17 #include "llvm/Support/Error.h"
18 #include "llvm/Support/raw_ostream.h"
19 #include "llvm/TargetParser/Host.h"
20 #include "llvm/TargetParser/RISCVISAInfo.h"
21 #include "llvm/TargetParser/RISCVTargetParser.h"
22
23 using namespace clang::driver;
24 using namespace clang::driver::tools;
25 using namespace clang;
26 using namespace llvm::opt;
27
28 // Returns false if an error is diagnosed.
getArchFeatures(const Driver & D,StringRef Arch,std::vector<StringRef> & Features,const ArgList & Args)29 static bool getArchFeatures(const Driver &D, StringRef Arch,
30 std::vector<StringRef> &Features,
31 const ArgList &Args) {
32 bool EnableExperimentalExtensions =
33 Args.hasArg(options::OPT_menable_experimental_extensions);
34 auto ISAInfo =
35 llvm::RISCVISAInfo::parseArchString(Arch, EnableExperimentalExtensions);
36 if (!ISAInfo) {
37 handleAllErrors(ISAInfo.takeError(), [&](llvm::StringError &ErrMsg) {
38 D.Diag(diag::err_drv_invalid_riscv_arch_name)
39 << Arch << ErrMsg.getMessage();
40 });
41
42 return false;
43 }
44
45 for (const std::string &Str : (*ISAInfo)->toFeatures(/*AddAllExtension=*/true,
46 /*IgnoreUnknown=*/false))
47 Features.push_back(Args.MakeArgString(Str));
48
49 if (EnableExperimentalExtensions)
50 Features.push_back(Args.MakeArgString("+experimental"));
51
52 return true;
53 }
54
55 // Get features except standard extension feature
getRISCFeaturesFromMcpu(const Driver & D,const Arg * A,const llvm::Triple & Triple,StringRef Mcpu,std::vector<StringRef> & Features)56 static void getRISCFeaturesFromMcpu(const Driver &D, const Arg *A,
57 const llvm::Triple &Triple,
58 StringRef Mcpu,
59 std::vector<StringRef> &Features) {
60 bool Is64Bit = Triple.isRISCV64();
61 if (!llvm::RISCV::parseCPU(Mcpu, Is64Bit)) {
62 // Try inverting Is64Bit in case the CPU is valid, but for the wrong target.
63 if (llvm::RISCV::parseCPU(Mcpu, !Is64Bit))
64 D.Diag(clang::diag::err_drv_invalid_riscv_cpu_name_for_target)
65 << Mcpu << Is64Bit;
66 else
67 D.Diag(clang::diag::err_drv_unsupported_option_argument)
68 << A->getSpelling() << Mcpu;
69 }
70 }
71
getRISCVTargetFeatures(const Driver & D,const llvm::Triple & Triple,const ArgList & Args,std::vector<StringRef> & Features)72 void riscv::getRISCVTargetFeatures(const Driver &D, const llvm::Triple &Triple,
73 const ArgList &Args,
74 std::vector<StringRef> &Features) {
75 std::string MArch = getRISCVArch(Args, Triple);
76
77 if (!getArchFeatures(D, MArch, Features, Args))
78 return;
79
80 bool CPUFastScalarUnaligned = false;
81 bool CPUFastVectorUnaligned = false;
82
83 // If users give march and mcpu, get std extension feature from MArch
84 // and other features (ex. mirco architecture feature) from mcpu
85 if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) {
86 StringRef CPU = A->getValue();
87 if (CPU == "native")
88 CPU = llvm::sys::getHostCPUName();
89
90 getRISCFeaturesFromMcpu(D, A, Triple, CPU, Features);
91
92 if (llvm::RISCV::hasFastScalarUnalignedAccess(CPU))
93 CPUFastScalarUnaligned = true;
94 if (llvm::RISCV::hasFastVectorUnalignedAccess(CPU))
95 CPUFastVectorUnaligned = true;
96 }
97
98 // Handle features corresponding to "-ffixed-X" options
99 if (Args.hasArg(options::OPT_ffixed_x1))
100 Features.push_back("+reserve-x1");
101 if (Args.hasArg(options::OPT_ffixed_x2))
102 Features.push_back("+reserve-x2");
103 if (Args.hasArg(options::OPT_ffixed_x3))
104 Features.push_back("+reserve-x3");
105 if (Args.hasArg(options::OPT_ffixed_x4))
106 Features.push_back("+reserve-x4");
107 if (Args.hasArg(options::OPT_ffixed_x5))
108 Features.push_back("+reserve-x5");
109 if (Args.hasArg(options::OPT_ffixed_x6))
110 Features.push_back("+reserve-x6");
111 if (Args.hasArg(options::OPT_ffixed_x7))
112 Features.push_back("+reserve-x7");
113 if (Args.hasArg(options::OPT_ffixed_x8))
114 Features.push_back("+reserve-x8");
115 if (Args.hasArg(options::OPT_ffixed_x9))
116 Features.push_back("+reserve-x9");
117 if (Args.hasArg(options::OPT_ffixed_x10))
118 Features.push_back("+reserve-x10");
119 if (Args.hasArg(options::OPT_ffixed_x11))
120 Features.push_back("+reserve-x11");
121 if (Args.hasArg(options::OPT_ffixed_x12))
122 Features.push_back("+reserve-x12");
123 if (Args.hasArg(options::OPT_ffixed_x13))
124 Features.push_back("+reserve-x13");
125 if (Args.hasArg(options::OPT_ffixed_x14))
126 Features.push_back("+reserve-x14");
127 if (Args.hasArg(options::OPT_ffixed_x15))
128 Features.push_back("+reserve-x15");
129 if (Args.hasArg(options::OPT_ffixed_x16))
130 Features.push_back("+reserve-x16");
131 if (Args.hasArg(options::OPT_ffixed_x17))
132 Features.push_back("+reserve-x17");
133 if (Args.hasArg(options::OPT_ffixed_x18))
134 Features.push_back("+reserve-x18");
135 if (Args.hasArg(options::OPT_ffixed_x19))
136 Features.push_back("+reserve-x19");
137 if (Args.hasArg(options::OPT_ffixed_x20))
138 Features.push_back("+reserve-x20");
139 if (Args.hasArg(options::OPT_ffixed_x21))
140 Features.push_back("+reserve-x21");
141 if (Args.hasArg(options::OPT_ffixed_x22))
142 Features.push_back("+reserve-x22");
143 if (Args.hasArg(options::OPT_ffixed_x23))
144 Features.push_back("+reserve-x23");
145 if (Args.hasArg(options::OPT_ffixed_x24))
146 Features.push_back("+reserve-x24");
147 if (Args.hasArg(options::OPT_ffixed_x25))
148 Features.push_back("+reserve-x25");
149 if (Args.hasArg(options::OPT_ffixed_x26))
150 Features.push_back("+reserve-x26");
151 if (Args.hasArg(options::OPT_ffixed_x27))
152 Features.push_back("+reserve-x27");
153 if (Args.hasArg(options::OPT_ffixed_x28))
154 Features.push_back("+reserve-x28");
155 if (Args.hasArg(options::OPT_ffixed_x29))
156 Features.push_back("+reserve-x29");
157 if (Args.hasArg(options::OPT_ffixed_x30))
158 Features.push_back("+reserve-x30");
159 if (Args.hasArg(options::OPT_ffixed_x31))
160 Features.push_back("+reserve-x31");
161
162 // FreeBSD local, because ld.lld doesn't support relaxations
163 // -mno-relax is default, unless -mrelax is specified.
164 if (Args.hasFlag(options::OPT_mrelax, options::OPT_mno_relax, false)) {
165 Features.push_back("+relax");
166 // -gsplit-dwarf -mrelax requires DW_AT_high_pc/DW_AT_ranges/... indexing
167 // into .debug_addr, which is currently not implemented.
168 Arg *A;
169 if (getDebugFissionKind(D, Args, A) != DwarfFissionKind::None)
170 D.Diag(clang::diag::err_drv_riscv_unsupported_with_linker_relaxation)
171 << A->getAsString(Args);
172 } else {
173 Features.push_back("-relax");
174 }
175
176 // If -mstrict-align, -mno-strict-align, -mscalar-strict-align, or
177 // -mno-scalar-strict-align is passed, use it. Otherwise, the
178 // unaligned-scalar-mem is enabled if the CPU supports it or the target is
179 // Android.
180 if (const Arg *A = Args.getLastArg(
181 options::OPT_mno_strict_align, options::OPT_mscalar_strict_align,
182 options::OPT_mstrict_align, options::OPT_mno_scalar_strict_align)) {
183 if (A->getOption().matches(options::OPT_mno_strict_align) ||
184 A->getOption().matches(options::OPT_mno_scalar_strict_align)) {
185 Features.push_back("+unaligned-scalar-mem");
186 } else {
187 Features.push_back("-unaligned-scalar-mem");
188 }
189 } else if (CPUFastScalarUnaligned || Triple.isAndroid()) {
190 Features.push_back("+unaligned-scalar-mem");
191 }
192
193 // If -mstrict-align, -mno-strict-align, -mvector-strict-align, or
194 // -mno-vector-strict-align is passed, use it. Otherwise, the
195 // unaligned-vector-mem is enabled if the CPU supports it or the target is
196 // Android.
197 if (const Arg *A = Args.getLastArg(
198 options::OPT_mno_strict_align, options::OPT_mvector_strict_align,
199 options::OPT_mstrict_align, options::OPT_mno_vector_strict_align)) {
200 if (A->getOption().matches(options::OPT_mno_strict_align) ||
201 A->getOption().matches(options::OPT_mno_vector_strict_align)) {
202 Features.push_back("+unaligned-vector-mem");
203 } else {
204 Features.push_back("-unaligned-vector-mem");
205 }
206 } else if (CPUFastVectorUnaligned || Triple.isAndroid()) {
207 Features.push_back("+unaligned-vector-mem");
208 }
209
210 // Now add any that the user explicitly requested on the command line,
211 // which may override the defaults.
212 handleTargetFeaturesGroup(D, Triple, Args, Features,
213 options::OPT_m_riscv_Features_Group);
214 }
215
getRISCVABI(const ArgList & Args,const llvm::Triple & Triple)216 StringRef riscv::getRISCVABI(const ArgList &Args, const llvm::Triple &Triple) {
217 assert(Triple.isRISCV() && "Unexpected triple");
218
219 // GCC's logic around choosing a default `-mabi=` is complex. If GCC is not
220 // configured using `--with-abi=`, then the logic for the default choice is
221 // defined in config.gcc. This function is based on the logic in GCC 9.2.0.
222 //
223 // The logic used in GCC 9.2.0 is the following, in order:
224 // 1. Explicit choices using `--with-abi=`
225 // 2. A default based on `--with-arch=`, if provided
226 // 3. A default based on the target triple's arch
227 //
228 // The logic in config.gcc is a little circular but it is not inconsistent.
229 //
230 // Clang does not have `--with-arch=` or `--with-abi=`, so we use `-march=`
231 // and `-mabi=` respectively instead.
232 //
233 // In order to make chosing logic more clear, Clang uses the following logic,
234 // in order:
235 // 1. Explicit choices using `-mabi=`
236 // 2. A default based on the architecture as determined by getRISCVArch
237 // 3. Choose a default based on the triple
238
239 // 1. If `-mabi=` is specified, use it.
240 if (const Arg *A = Args.getLastArg(options::OPT_mabi_EQ))
241 return A->getValue();
242
243 // 2. Choose a default based on the target architecture.
244 //
245 // rv32g | rv32*d -> ilp32d
246 // rv32e -> ilp32e
247 // rv32* -> ilp32
248 // rv64g | rv64*d -> lp64d
249 // rv64e -> lp64e
250 // rv64* -> lp64
251 std::string Arch = getRISCVArch(Args, Triple);
252
253 auto ParseResult = llvm::RISCVISAInfo::parseArchString(
254 Arch, /* EnableExperimentalExtension */ true);
255 // Ignore parsing error, just go 3rd step.
256 if (!llvm::errorToBool(ParseResult.takeError()))
257 return (*ParseResult)->computeDefaultABI();
258
259 // 3. Choose a default based on the triple
260 //
261 // We deviate from GCC's defaults here:
262 // - On `riscv{XLEN}-unknown-elf` we use the integer calling convention only.
263 // - On all other OSs we use the double floating point calling convention.
264 if (Triple.isRISCV32()) {
265 if (Triple.getOS() == llvm::Triple::UnknownOS)
266 return "ilp32";
267 else
268 return "ilp32d";
269 } else {
270 if (Triple.getOS() == llvm::Triple::UnknownOS)
271 return "lp64";
272 else
273 return "lp64d";
274 }
275 }
276
getRISCVArch(const llvm::opt::ArgList & Args,const llvm::Triple & Triple)277 std::string riscv::getRISCVArch(const llvm::opt::ArgList &Args,
278 const llvm::Triple &Triple) {
279 assert(Triple.isRISCV() && "Unexpected triple");
280
281 // GCC's logic around choosing a default `-march=` is complex. If GCC is not
282 // configured using `--with-arch=`, then the logic for the default choice is
283 // defined in config.gcc. This function is based on the logic in GCC 9.2.0. We
284 // deviate from GCC's default on additional `-mcpu` option (GCC does not
285 // support `-mcpu`) and baremetal targets (UnknownOS) where neither `-march`
286 // nor `-mabi` is specified.
287 //
288 // The logic used in GCC 9.2.0 is the following, in order:
289 // 1. Explicit choices using `--with-arch=`
290 // 2. A default based on `--with-abi=`, if provided
291 // 3. A default based on the target triple's arch
292 //
293 // The logic in config.gcc is a little circular but it is not inconsistent.
294 //
295 // Clang does not have `--with-arch=` or `--with-abi=`, so we use `-march=`
296 // and `-mabi=` respectively instead.
297 //
298 // Clang uses the following logic, in order:
299 // 1. Explicit choices using `-march=`
300 // 2. Based on `-mcpu` if the target CPU has a default ISA string
301 // 3. A default based on `-mabi`, if provided
302 // 4. A default based on the target triple's arch
303 //
304 // Clang does not yet support MULTILIB_REUSE, so we use `rv{XLEN}imafdc`
305 // instead of `rv{XLEN}gc` though they are (currently) equivalent.
306
307 // 1. If `-march=` is specified, use it.
308 if (const Arg *A = Args.getLastArg(options::OPT_march_EQ))
309 return A->getValue();
310
311 // 2. Get march (isa string) based on `-mcpu=`
312 if (const Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) {
313 StringRef CPU = A->getValue();
314 if (CPU == "native") {
315 CPU = llvm::sys::getHostCPUName();
316 // If the target cpu is unrecognized, use target features.
317 if (CPU.starts_with("generic")) {
318 auto FeatureMap = llvm::sys::getHostCPUFeatures();
319 // hwprobe may be unavailable on older Linux versions.
320 if (!FeatureMap.empty()) {
321 std::vector<std::string> Features;
322 for (auto &F : FeatureMap)
323 Features.push_back(((F.second ? "+" : "-") + F.first()).str());
324 auto ParseResult = llvm::RISCVISAInfo::parseFeatures(
325 Triple.isRISCV32() ? 32 : 64, Features);
326 if (ParseResult)
327 return (*ParseResult)->toString();
328 }
329 }
330 }
331
332 StringRef MArch = llvm::RISCV::getMArchFromMcpu(CPU);
333 // Bypass if target cpu's default march is empty.
334 if (MArch != "")
335 return MArch.str();
336 }
337
338 // 3. Choose a default based on `-mabi=`
339 //
340 // ilp32e -> rv32e
341 // lp64e -> rv64e
342 // ilp32 | ilp32f | ilp32d -> rv32imafdc
343 // lp64 | lp64f | lp64d -> rv64imafdc
344 if (const Arg *A = Args.getLastArg(options::OPT_mabi_EQ)) {
345 StringRef MABI = A->getValue();
346
347 if (MABI.equals_insensitive("ilp32e"))
348 return "rv32e";
349 else if (MABI.equals_insensitive("lp64e"))
350 return "rv64e";
351 else if (MABI.starts_with_insensitive("ilp32"))
352 return "rv32imafdc";
353 else if (MABI.starts_with_insensitive("lp64")) {
354 if (Triple.isAndroid())
355 return "rv64imafdcv_zba_zbb_zbs";
356
357 return "rv64imafdc";
358 }
359 }
360
361 // 4. Choose a default based on the triple
362 //
363 // We deviate from GCC's defaults here:
364 // - On `riscv{XLEN}-unknown-elf` we default to `rv{XLEN}imac`
365 // - On all other OSs we use `rv{XLEN}imafdc` (equivalent to `rv{XLEN}gc`)
366 if (Triple.isRISCV32()) {
367 if (Triple.getOS() == llvm::Triple::UnknownOS)
368 return "rv32imac";
369 else
370 return "rv32imafdc";
371 } else {
372 if (Triple.getOS() == llvm::Triple::UnknownOS)
373 return "rv64imac";
374 else if (Triple.isAndroid())
375 return "rv64imafdcv_zba_zbb_zbs";
376 else
377 return "rv64imafdc";
378 }
379 }
380
getRISCVTargetCPU(const llvm::opt::ArgList & Args,const llvm::Triple & Triple)381 std::string riscv::getRISCVTargetCPU(const llvm::opt::ArgList &Args,
382 const llvm::Triple &Triple) {
383 std::string CPU;
384 // If we have -mcpu, use that.
385 if (const Arg *A = Args.getLastArg(options::OPT_mcpu_EQ))
386 CPU = A->getValue();
387
388 // Handle CPU name is 'native'.
389 if (CPU == "native")
390 CPU = llvm::sys::getHostCPUName();
391
392 if (!CPU.empty())
393 return CPU;
394
395 return Triple.isRISCV64() ? "generic-rv64" : "generic-rv32";
396 }
397