1e5dd7070Spatrick //===--- RISCV.cpp - RISCV Helpers for Tools --------------------*- C++ -*-===//
2e5dd7070Spatrick //
3e5dd7070Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e5dd7070Spatrick // See https://llvm.org/LICENSE.txt for license information.
5e5dd7070Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6e5dd7070Spatrick //
7e5dd7070Spatrick //===----------------------------------------------------------------------===//
8e5dd7070Spatrick
9e5dd7070Spatrick #include "RISCV.h"
10*7a9b00ceSrobert #include "../Clang.h"
11*7a9b00ceSrobert #include "ToolChains/CommonArgs.h"
12e5dd7070Spatrick #include "clang/Basic/CharInfo.h"
13e5dd7070Spatrick #include "clang/Driver/Driver.h"
14e5dd7070Spatrick #include "clang/Driver/DriverDiagnostic.h"
15e5dd7070Spatrick #include "clang/Driver/Options.h"
16e5dd7070Spatrick #include "llvm/Option/ArgList.h"
17*7a9b00ceSrobert #include "llvm/Support/Error.h"
18*7a9b00ceSrobert #include "llvm/Support/Host.h"
19*7a9b00ceSrobert #include "llvm/Support/RISCVISAInfo.h"
20e5dd7070Spatrick #include "llvm/Support/raw_ostream.h"
21*7a9b00ceSrobert #include "llvm/TargetParser/RISCVTargetParser.h"
22e5dd7070Spatrick
23e5dd7070Spatrick using namespace clang::driver;
24e5dd7070Spatrick using namespace clang::driver::tools;
25e5dd7070Spatrick using namespace clang;
26e5dd7070Spatrick using namespace llvm::opt;
27e5dd7070Spatrick
28e5dd7070Spatrick // Returns false if an error is diagnosed.
getArchFeatures(const Driver & D,StringRef Arch,std::vector<StringRef> & Features,const ArgList & Args)29*7a9b00ceSrobert static bool getArchFeatures(const Driver &D, StringRef Arch,
30e5dd7070Spatrick std::vector<StringRef> &Features,
31e5dd7070Spatrick const ArgList &Args) {
32*7a9b00ceSrobert bool EnableExperimentalExtensions =
33*7a9b00ceSrobert Args.hasArg(options::OPT_menable_experimental_extensions);
34*7a9b00ceSrobert auto ISAInfo =
35*7a9b00ceSrobert llvm::RISCVISAInfo::parseArchString(Arch, EnableExperimentalExtensions);
36*7a9b00ceSrobert if (!ISAInfo) {
37*7a9b00ceSrobert handleAllErrors(ISAInfo.takeError(), [&](llvm::StringError &ErrMsg) {
38e5dd7070Spatrick D.Diag(diag::err_drv_invalid_riscv_arch_name)
39*7a9b00ceSrobert << Arch << ErrMsg.getMessage();
40*7a9b00ceSrobert });
41*7a9b00ceSrobert
42e5dd7070Spatrick return false;
43e5dd7070Spatrick }
44e5dd7070Spatrick
45*7a9b00ceSrobert (*ISAInfo)->toFeatures(
46*7a9b00ceSrobert Features, [&Args](const Twine &Str) { return Args.MakeArgString(Str); },
47*7a9b00ceSrobert /*AddAllExtensions=*/true);
48e5dd7070Spatrick return true;
49e5dd7070Spatrick }
50e5dd7070Spatrick
51ec727ea7Spatrick // Get features except standard extension feature
getRISCFeaturesFromMcpu(const llvm::Triple & Triple,StringRef Mcpu,std::vector<StringRef> & Features)52*7a9b00ceSrobert static bool getRISCFeaturesFromMcpu(const llvm::Triple &Triple, StringRef Mcpu,
53ec727ea7Spatrick std::vector<StringRef> &Features) {
54*7a9b00ceSrobert bool Is64Bit = Triple.isRISCV64();
55ec727ea7Spatrick llvm::RISCV::CPUKind CPUKind = llvm::RISCV::parseCPUKind(Mcpu);
56*7a9b00ceSrobert return llvm::RISCV::checkCPUKind(CPUKind, Is64Bit) &&
57*7a9b00ceSrobert llvm::RISCV::getCPUFeaturesExceptStdExt(CPUKind, Features);
58ec727ea7Spatrick }
59ec727ea7Spatrick
getRISCVTargetFeatures(const Driver & D,const llvm::Triple & Triple,const ArgList & Args,std::vector<StringRef> & Features)60e5dd7070Spatrick void riscv::getRISCVTargetFeatures(const Driver &D, const llvm::Triple &Triple,
61e5dd7070Spatrick const ArgList &Args,
62e5dd7070Spatrick std::vector<StringRef> &Features) {
63e5dd7070Spatrick StringRef MArch = getRISCVArch(Args, Triple);
64e5dd7070Spatrick
65e5dd7070Spatrick if (!getArchFeatures(D, MArch, Features, Args))
66e5dd7070Spatrick return;
67e5dd7070Spatrick
68ec727ea7Spatrick // If users give march and mcpu, get std extension feature from MArch
69ec727ea7Spatrick // and other features (ex. mirco architecture feature) from mcpu
70*7a9b00ceSrobert if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) {
71*7a9b00ceSrobert StringRef CPU = A->getValue();
72*7a9b00ceSrobert if (CPU == "native")
73*7a9b00ceSrobert CPU = llvm::sys::getHostCPUName();
74*7a9b00ceSrobert if (!getRISCFeaturesFromMcpu(Triple, CPU, Features))
75*7a9b00ceSrobert D.Diag(clang::diag::err_drv_unsupported_option_argument)
76*7a9b00ceSrobert << A->getSpelling() << CPU;
77*7a9b00ceSrobert }
78ec727ea7Spatrick
79e5dd7070Spatrick // Handle features corresponding to "-ffixed-X" options
80e5dd7070Spatrick if (Args.hasArg(options::OPT_ffixed_x1))
81e5dd7070Spatrick Features.push_back("+reserve-x1");
82e5dd7070Spatrick if (Args.hasArg(options::OPT_ffixed_x2))
83e5dd7070Spatrick Features.push_back("+reserve-x2");
84e5dd7070Spatrick if (Args.hasArg(options::OPT_ffixed_x3))
85e5dd7070Spatrick Features.push_back("+reserve-x3");
86e5dd7070Spatrick if (Args.hasArg(options::OPT_ffixed_x4))
87e5dd7070Spatrick Features.push_back("+reserve-x4");
88e5dd7070Spatrick if (Args.hasArg(options::OPT_ffixed_x5))
89e5dd7070Spatrick Features.push_back("+reserve-x5");
90e5dd7070Spatrick if (Args.hasArg(options::OPT_ffixed_x6))
91e5dd7070Spatrick Features.push_back("+reserve-x6");
92e5dd7070Spatrick if (Args.hasArg(options::OPT_ffixed_x7))
93e5dd7070Spatrick Features.push_back("+reserve-x7");
94e5dd7070Spatrick if (Args.hasArg(options::OPT_ffixed_x8))
95e5dd7070Spatrick Features.push_back("+reserve-x8");
96e5dd7070Spatrick if (Args.hasArg(options::OPT_ffixed_x9))
97e5dd7070Spatrick Features.push_back("+reserve-x9");
98e5dd7070Spatrick if (Args.hasArg(options::OPT_ffixed_x10))
99e5dd7070Spatrick Features.push_back("+reserve-x10");
100e5dd7070Spatrick if (Args.hasArg(options::OPT_ffixed_x11))
101e5dd7070Spatrick Features.push_back("+reserve-x11");
102e5dd7070Spatrick if (Args.hasArg(options::OPT_ffixed_x12))
103e5dd7070Spatrick Features.push_back("+reserve-x12");
104e5dd7070Spatrick if (Args.hasArg(options::OPT_ffixed_x13))
105e5dd7070Spatrick Features.push_back("+reserve-x13");
106e5dd7070Spatrick if (Args.hasArg(options::OPT_ffixed_x14))
107e5dd7070Spatrick Features.push_back("+reserve-x14");
108e5dd7070Spatrick if (Args.hasArg(options::OPT_ffixed_x15))
109e5dd7070Spatrick Features.push_back("+reserve-x15");
110e5dd7070Spatrick if (Args.hasArg(options::OPT_ffixed_x16))
111e5dd7070Spatrick Features.push_back("+reserve-x16");
112e5dd7070Spatrick if (Args.hasArg(options::OPT_ffixed_x17))
113e5dd7070Spatrick Features.push_back("+reserve-x17");
114e5dd7070Spatrick if (Args.hasArg(options::OPT_ffixed_x18))
115e5dd7070Spatrick Features.push_back("+reserve-x18");
116e5dd7070Spatrick if (Args.hasArg(options::OPT_ffixed_x19))
117e5dd7070Spatrick Features.push_back("+reserve-x19");
118e5dd7070Spatrick if (Args.hasArg(options::OPT_ffixed_x20))
119e5dd7070Spatrick Features.push_back("+reserve-x20");
120e5dd7070Spatrick if (Args.hasArg(options::OPT_ffixed_x21))
121e5dd7070Spatrick Features.push_back("+reserve-x21");
122e5dd7070Spatrick if (Args.hasArg(options::OPT_ffixed_x22))
123e5dd7070Spatrick Features.push_back("+reserve-x22");
124e5dd7070Spatrick if (Args.hasArg(options::OPT_ffixed_x23))
125e5dd7070Spatrick Features.push_back("+reserve-x23");
126e5dd7070Spatrick if (Args.hasArg(options::OPT_ffixed_x24))
127e5dd7070Spatrick Features.push_back("+reserve-x24");
128e5dd7070Spatrick if (Args.hasArg(options::OPT_ffixed_x25))
129e5dd7070Spatrick Features.push_back("+reserve-x25");
130e5dd7070Spatrick if (Args.hasArg(options::OPT_ffixed_x26))
131e5dd7070Spatrick Features.push_back("+reserve-x26");
132e5dd7070Spatrick if (Args.hasArg(options::OPT_ffixed_x27))
133e5dd7070Spatrick Features.push_back("+reserve-x27");
134e5dd7070Spatrick if (Args.hasArg(options::OPT_ffixed_x28))
135e5dd7070Spatrick Features.push_back("+reserve-x28");
136e5dd7070Spatrick if (Args.hasArg(options::OPT_ffixed_x29))
137e5dd7070Spatrick Features.push_back("+reserve-x29");
138e5dd7070Spatrick if (Args.hasArg(options::OPT_ffixed_x30))
139e5dd7070Spatrick Features.push_back("+reserve-x30");
140e5dd7070Spatrick if (Args.hasArg(options::OPT_ffixed_x31))
141e5dd7070Spatrick Features.push_back("+reserve-x31");
142e5dd7070Spatrick
143e15071f8Skettenis #ifdef __OpenBSD__
144e15071f8Skettenis // -mno-relax is default, unless -mrelax is specified.
145e15071f8Skettenis if (Args.hasFlag(options::OPT_mrelax, options::OPT_mno_relax, false))
146e15071f8Skettenis Features.push_back("+relax");
147e15071f8Skettenis else
148e15071f8Skettenis Features.push_back("-relax");
149e15071f8Skettenis #else
150e5dd7070Spatrick // -mrelax is default, unless -mno-relax is specified.
151*7a9b00ceSrobert if (Args.hasFlag(options::OPT_mrelax, options::OPT_mno_relax, true)) {
152e5dd7070Spatrick Features.push_back("+relax");
153*7a9b00ceSrobert // -gsplit-dwarf -mrelax requires DW_AT_high_pc/DW_AT_ranges/... indexing
154*7a9b00ceSrobert // into .debug_addr, which is currently not implemented.
155*7a9b00ceSrobert Arg *A;
156*7a9b00ceSrobert if (getDebugFissionKind(D, Args, A) != DwarfFissionKind::None)
157*7a9b00ceSrobert D.Diag(clang::diag::err_drv_riscv_unsupported_with_linker_relaxation)
158*7a9b00ceSrobert << A->getAsString(Args);
159*7a9b00ceSrobert } else {
160e5dd7070Spatrick Features.push_back("-relax");
161*7a9b00ceSrobert }
162e15071f8Skettenis #endif
163e5dd7070Spatrick
164e5dd7070Spatrick // GCC Compatibility: -mno-save-restore is default, unless -msave-restore is
165ec727ea7Spatrick // specified.
166ec727ea7Spatrick if (Args.hasFlag(options::OPT_msave_restore, options::OPT_mno_save_restore, false))
167ec727ea7Spatrick Features.push_back("+save-restore");
168ec727ea7Spatrick else
169ec727ea7Spatrick Features.push_back("-save-restore");
170e5dd7070Spatrick
171e5dd7070Spatrick // Now add any that the user explicitly requested on the command line,
172e5dd7070Spatrick // which may override the defaults.
173e5dd7070Spatrick handleTargetFeaturesGroup(Args, Features, options::OPT_m_riscv_Features_Group);
174e5dd7070Spatrick }
175e5dd7070Spatrick
getRISCVABI(const ArgList & Args,const llvm::Triple & Triple)176e5dd7070Spatrick StringRef riscv::getRISCVABI(const ArgList &Args, const llvm::Triple &Triple) {
177*7a9b00ceSrobert assert(Triple.isRISCV() && "Unexpected triple");
178e5dd7070Spatrick
179e5dd7070Spatrick // GCC's logic around choosing a default `-mabi=` is complex. If GCC is not
180e5dd7070Spatrick // configured using `--with-abi=`, then the logic for the default choice is
181ec727ea7Spatrick // defined in config.gcc. This function is based on the logic in GCC 9.2.0.
182e5dd7070Spatrick //
183ec727ea7Spatrick // The logic used in GCC 9.2.0 is the following, in order:
184e5dd7070Spatrick // 1. Explicit choices using `--with-abi=`
185e5dd7070Spatrick // 2. A default based on `--with-arch=`, if provided
186e5dd7070Spatrick // 3. A default based on the target triple's arch
187e5dd7070Spatrick //
188e5dd7070Spatrick // The logic in config.gcc is a little circular but it is not inconsistent.
189e5dd7070Spatrick //
190e5dd7070Spatrick // Clang does not have `--with-arch=` or `--with-abi=`, so we use `-march=`
191e5dd7070Spatrick // and `-mabi=` respectively instead.
192ec727ea7Spatrick //
193ec727ea7Spatrick // In order to make chosing logic more clear, Clang uses the following logic,
194ec727ea7Spatrick // in order:
195ec727ea7Spatrick // 1. Explicit choices using `-mabi=`
196ec727ea7Spatrick // 2. A default based on the architecture as determined by getRISCVArch
197ec727ea7Spatrick // 3. Choose a default based on the triple
198e5dd7070Spatrick
199e5dd7070Spatrick // 1. If `-mabi=` is specified, use it.
200e5dd7070Spatrick if (const Arg *A = Args.getLastArg(options::OPT_mabi_EQ))
201e5dd7070Spatrick return A->getValue();
202e5dd7070Spatrick
203ec727ea7Spatrick // 2. Choose a default based on the target architecture.
204e5dd7070Spatrick //
205e5dd7070Spatrick // rv32g | rv32*d -> ilp32d
206e5dd7070Spatrick // rv32e -> ilp32e
207e5dd7070Spatrick // rv32* -> ilp32
208e5dd7070Spatrick // rv64g | rv64*d -> lp64d
209e5dd7070Spatrick // rv64* -> lp64
210*7a9b00ceSrobert StringRef Arch = getRISCVArch(Args, Triple);
211e5dd7070Spatrick
212*7a9b00ceSrobert auto ParseResult = llvm::RISCVISAInfo::parseArchString(
213*7a9b00ceSrobert Arch, /* EnableExperimentalExtension */ true);
214*7a9b00ceSrobert if (!ParseResult)
215*7a9b00ceSrobert // Ignore parsing error, just go 3rd step.
216*7a9b00ceSrobert consumeError(ParseResult.takeError());
217e5dd7070Spatrick else
218*7a9b00ceSrobert return (*ParseResult)->computeDefaultABI();
219e5dd7070Spatrick
220e5dd7070Spatrick // 3. Choose a default based on the triple
221e5dd7070Spatrick //
222e5dd7070Spatrick // We deviate from GCC's defaults here:
223e5dd7070Spatrick // - On `riscv{XLEN}-unknown-elf` we use the integer calling convention only.
224e5dd7070Spatrick // - On all other OSs we use the double floating point calling convention.
225*7a9b00ceSrobert if (Triple.isRISCV32()) {
226e5dd7070Spatrick if (Triple.getOS() == llvm::Triple::UnknownOS)
227e5dd7070Spatrick return "ilp32";
228e5dd7070Spatrick else
229e5dd7070Spatrick return "ilp32d";
230e5dd7070Spatrick } else {
231e5dd7070Spatrick if (Triple.getOS() == llvm::Triple::UnknownOS)
232e5dd7070Spatrick return "lp64";
233e5dd7070Spatrick else
234e5dd7070Spatrick return "lp64d";
235e5dd7070Spatrick }
236e5dd7070Spatrick }
237e5dd7070Spatrick
getRISCVArch(const llvm::opt::ArgList & Args,const llvm::Triple & Triple)238e5dd7070Spatrick StringRef riscv::getRISCVArch(const llvm::opt::ArgList &Args,
239e5dd7070Spatrick const llvm::Triple &Triple) {
240*7a9b00ceSrobert assert(Triple.isRISCV() && "Unexpected triple");
241e5dd7070Spatrick
242e5dd7070Spatrick // GCC's logic around choosing a default `-march=` is complex. If GCC is not
243e5dd7070Spatrick // configured using `--with-arch=`, then the logic for the default choice is
244e5dd7070Spatrick // defined in config.gcc. This function is based on the logic in GCC 9.2.0. We
245ec727ea7Spatrick // deviate from GCC's default on additional `-mcpu` option (GCC does not
246ec727ea7Spatrick // support `-mcpu`) and baremetal targets (UnknownOS) where neither `-march`
247ec727ea7Spatrick // nor `-mabi` is specified.
248e5dd7070Spatrick //
249ec727ea7Spatrick // The logic used in GCC 9.2.0 is the following, in order:
250e5dd7070Spatrick // 1. Explicit choices using `--with-arch=`
251e5dd7070Spatrick // 2. A default based on `--with-abi=`, if provided
252e5dd7070Spatrick // 3. A default based on the target triple's arch
253e5dd7070Spatrick //
254e5dd7070Spatrick // The logic in config.gcc is a little circular but it is not inconsistent.
255e5dd7070Spatrick //
256e5dd7070Spatrick // Clang does not have `--with-arch=` or `--with-abi=`, so we use `-march=`
257e5dd7070Spatrick // and `-mabi=` respectively instead.
258e5dd7070Spatrick //
259ec727ea7Spatrick // Clang uses the following logic, in order:
260ec727ea7Spatrick // 1. Explicit choices using `-march=`
261ec727ea7Spatrick // 2. Based on `-mcpu` if the target CPU has a default ISA string
262ec727ea7Spatrick // 3. A default based on `-mabi`, if provided
263ec727ea7Spatrick // 4. A default based on the target triple's arch
264ec727ea7Spatrick //
265e5dd7070Spatrick // Clang does not yet support MULTILIB_REUSE, so we use `rv{XLEN}imafdc`
266e5dd7070Spatrick // instead of `rv{XLEN}gc` though they are (currently) equivalent.
267e5dd7070Spatrick
268e5dd7070Spatrick // 1. If `-march=` is specified, use it.
269e5dd7070Spatrick if (const Arg *A = Args.getLastArg(options::OPT_march_EQ))
270e5dd7070Spatrick return A->getValue();
271e5dd7070Spatrick
272ec727ea7Spatrick // 2. Get march (isa string) based on `-mcpu=`
273ec727ea7Spatrick if (const Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) {
274*7a9b00ceSrobert StringRef CPU = A->getValue();
275*7a9b00ceSrobert if (CPU == "native")
276*7a9b00ceSrobert CPU = llvm::sys::getHostCPUName();
277*7a9b00ceSrobert StringRef MArch = llvm::RISCV::getMArchFromMcpu(CPU);
278ec727ea7Spatrick // Bypass if target cpu's default march is empty.
279ec727ea7Spatrick if (MArch != "")
280ec727ea7Spatrick return MArch;
281ec727ea7Spatrick }
282ec727ea7Spatrick
283ec727ea7Spatrick // 3. Choose a default based on `-mabi=`
284e5dd7070Spatrick //
285e5dd7070Spatrick // ilp32e -> rv32e
286e5dd7070Spatrick // ilp32 | ilp32f | ilp32d -> rv32imafdc
287e5dd7070Spatrick // lp64 | lp64f | lp64d -> rv64imafdc
288e5dd7070Spatrick if (const Arg *A = Args.getLastArg(options::OPT_mabi_EQ)) {
289e5dd7070Spatrick StringRef MABI = A->getValue();
290e5dd7070Spatrick
291a0747c9fSpatrick if (MABI.equals_insensitive("ilp32e"))
292e5dd7070Spatrick return "rv32e";
293a0747c9fSpatrick else if (MABI.startswith_insensitive("ilp32"))
294e5dd7070Spatrick return "rv32imafdc";
295a0747c9fSpatrick else if (MABI.startswith_insensitive("lp64"))
296e5dd7070Spatrick return "rv64imafdc";
297e5dd7070Spatrick }
298e5dd7070Spatrick
299ec727ea7Spatrick // 4. Choose a default based on the triple
300e5dd7070Spatrick //
301e5dd7070Spatrick // We deviate from GCC's defaults here:
302e5dd7070Spatrick // - On `riscv{XLEN}-unknown-elf` we default to `rv{XLEN}imac`
303e5dd7070Spatrick // - On all other OSs we use `rv{XLEN}imafdc` (equivalent to `rv{XLEN}gc`)
304*7a9b00ceSrobert if (Triple.isRISCV32()) {
305e5dd7070Spatrick if (Triple.getOS() == llvm::Triple::UnknownOS)
306e5dd7070Spatrick return "rv32imac";
307e5dd7070Spatrick else
308e5dd7070Spatrick return "rv32imafdc";
309e5dd7070Spatrick } else {
310e5dd7070Spatrick if (Triple.getOS() == llvm::Triple::UnknownOS)
311e5dd7070Spatrick return "rv64imac";
312e5dd7070Spatrick else
313e5dd7070Spatrick return "rv64imafdc";
314e5dd7070Spatrick }
315e5dd7070Spatrick }
316*7a9b00ceSrobert
getRISCVTargetCPU(const llvm::opt::ArgList & Args,const llvm::Triple & Triple)317*7a9b00ceSrobert std::string riscv::getRISCVTargetCPU(const llvm::opt::ArgList &Args,
318*7a9b00ceSrobert const llvm::Triple &Triple) {
319*7a9b00ceSrobert std::string CPU;
320*7a9b00ceSrobert // If we have -mcpu, use that.
321*7a9b00ceSrobert if (const Arg *A = Args.getLastArg(options::OPT_mcpu_EQ))
322*7a9b00ceSrobert CPU = A->getValue();
323*7a9b00ceSrobert
324*7a9b00ceSrobert // Handle CPU name is 'native'.
325*7a9b00ceSrobert if (CPU == "native")
326*7a9b00ceSrobert CPU = llvm::sys::getHostCPUName();
327*7a9b00ceSrobert
328*7a9b00ceSrobert if (!CPU.empty())
329*7a9b00ceSrobert return CPU;
330*7a9b00ceSrobert
331*7a9b00ceSrobert return Triple.isRISCV64() ? "generic-rv64" : "generic-rv32";
332*7a9b00ceSrobert }
333