xref: /freebsd-src/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/LoongArch.cpp (revision bdd1243df58e60e85101c09001d9812a789b6bc4)
1*bdd1243dSDimitry Andric //===--- LoongArch.cpp - LoongArch Helpers for Tools ------------*- C++ -*-===//
2*bdd1243dSDimitry Andric //
3*bdd1243dSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*bdd1243dSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*bdd1243dSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*bdd1243dSDimitry Andric //
7*bdd1243dSDimitry Andric //===----------------------------------------------------------------------===//
8*bdd1243dSDimitry Andric 
9*bdd1243dSDimitry Andric #include "LoongArch.h"
10*bdd1243dSDimitry Andric #include "clang/Basic/DiagnosticDriver.h"
11*bdd1243dSDimitry Andric #include "clang/Driver/Driver.h"
12*bdd1243dSDimitry Andric #include "clang/Driver/DriverDiagnostic.h"
13*bdd1243dSDimitry Andric #include "clang/Driver/Options.h"
14*bdd1243dSDimitry Andric #include "llvm/Support/LoongArchTargetParser.h"
15*bdd1243dSDimitry Andric 
16*bdd1243dSDimitry Andric using namespace clang::driver;
17*bdd1243dSDimitry Andric using namespace clang::driver::tools;
18*bdd1243dSDimitry Andric using namespace clang;
19*bdd1243dSDimitry Andric using namespace llvm::opt;
20*bdd1243dSDimitry Andric 
21*bdd1243dSDimitry Andric StringRef loongarch::getLoongArchABI(const Driver &D, const ArgList &Args,
22*bdd1243dSDimitry Andric                                      const llvm::Triple &Triple) {
23*bdd1243dSDimitry Andric   assert((Triple.getArch() == llvm::Triple::loongarch32 ||
24*bdd1243dSDimitry Andric           Triple.getArch() == llvm::Triple::loongarch64) &&
25*bdd1243dSDimitry Andric          "Unexpected triple");
26*bdd1243dSDimitry Andric   bool IsLA32 = Triple.getArch() == llvm::Triple::loongarch32;
27*bdd1243dSDimitry Andric 
28*bdd1243dSDimitry Andric   // Check -m*-float firstly since they have highest priority.
29*bdd1243dSDimitry Andric   if (const Arg *A = Args.getLastArg(options::OPT_mdouble_float,
30*bdd1243dSDimitry Andric                                      options::OPT_msingle_float,
31*bdd1243dSDimitry Andric                                      options::OPT_msoft_float)) {
32*bdd1243dSDimitry Andric     if (A->getOption().matches(options::OPT_mdouble_float))
33*bdd1243dSDimitry Andric       return IsLA32 ? "ilp32d" : "lp64d";
34*bdd1243dSDimitry Andric     if (A->getOption().matches(options::OPT_msingle_float))
35*bdd1243dSDimitry Andric       return IsLA32 ? "ilp32f" : "lp64f";
36*bdd1243dSDimitry Andric     if (A->getOption().matches(options::OPT_msoft_float))
37*bdd1243dSDimitry Andric       return IsLA32 ? "ilp32s" : "lp64s";
38*bdd1243dSDimitry Andric   }
39*bdd1243dSDimitry Andric 
40*bdd1243dSDimitry Andric   // If `-mabi=` is specified, use it.
41*bdd1243dSDimitry Andric   if (const Arg *A = Args.getLastArg(options::OPT_mabi_EQ))
42*bdd1243dSDimitry Andric     return A->getValue();
43*bdd1243dSDimitry Andric 
44*bdd1243dSDimitry Andric   // Select abi based on -mfpu=xx.
45*bdd1243dSDimitry Andric   if (const Arg *A = Args.getLastArg(options::OPT_mfpu_EQ)) {
46*bdd1243dSDimitry Andric     StringRef FPU = A->getValue();
47*bdd1243dSDimitry Andric     if (FPU == "64")
48*bdd1243dSDimitry Andric       return IsLA32 ? "ilp32d" : "lp64d";
49*bdd1243dSDimitry Andric     if (FPU == "32")
50*bdd1243dSDimitry Andric       return IsLA32 ? "ilp32f" : "lp64f";
51*bdd1243dSDimitry Andric     if (FPU == "0" || FPU == "none")
52*bdd1243dSDimitry Andric       return IsLA32 ? "ilp32s" : "lp64s";
53*bdd1243dSDimitry Andric     D.Diag(diag::err_drv_loongarch_invalid_mfpu_EQ) << FPU;
54*bdd1243dSDimitry Andric   }
55*bdd1243dSDimitry Andric 
56*bdd1243dSDimitry Andric   // Choose a default based on the triple.
57*bdd1243dSDimitry Andric   return IsLA32 ? "ilp32d" : "lp64d";
58*bdd1243dSDimitry Andric }
59*bdd1243dSDimitry Andric 
60*bdd1243dSDimitry Andric void loongarch::getLoongArchTargetFeatures(const Driver &D,
61*bdd1243dSDimitry Andric                                            const llvm::Triple &Triple,
62*bdd1243dSDimitry Andric                                            const ArgList &Args,
63*bdd1243dSDimitry Andric                                            std::vector<StringRef> &Features) {
64*bdd1243dSDimitry Andric   StringRef ArchName;
65*bdd1243dSDimitry Andric   llvm::LoongArch::ArchKind ArchKind = llvm::LoongArch::ArchKind::AK_INVALID;
66*bdd1243dSDimitry Andric   if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) {
67*bdd1243dSDimitry Andric     ArchKind = llvm::LoongArch::parseArch(A->getValue());
68*bdd1243dSDimitry Andric     if (ArchKind == llvm::LoongArch::ArchKind::AK_INVALID) {
69*bdd1243dSDimitry Andric       D.Diag(clang::diag::err_drv_invalid_arch_name) << A->getAsString(Args);
70*bdd1243dSDimitry Andric       return;
71*bdd1243dSDimitry Andric     }
72*bdd1243dSDimitry Andric     ArchName = A->getValue();
73*bdd1243dSDimitry Andric   }
74*bdd1243dSDimitry Andric 
75*bdd1243dSDimitry Andric   // TODO: handle -march=native and -mtune=xx.
76*bdd1243dSDimitry Andric 
77*bdd1243dSDimitry Andric   // Select a default arch name.
78*bdd1243dSDimitry Andric   if (ArchName.empty() && Triple.getArch() == llvm::Triple::loongarch64)
79*bdd1243dSDimitry Andric     ArchName = "loongarch64";
80*bdd1243dSDimitry Andric 
81*bdd1243dSDimitry Andric   if (!ArchName.empty())
82*bdd1243dSDimitry Andric     llvm::LoongArch::getArchFeatures(ArchName, Features);
83*bdd1243dSDimitry Andric 
84*bdd1243dSDimitry Andric   // Select floating-point features determined by -mdouble-float,
85*bdd1243dSDimitry Andric   // -msingle-float, -msoft-float and -mfpu.
86*bdd1243dSDimitry Andric   // Note: -m*-float wins any other options.
87*bdd1243dSDimitry Andric   if (const Arg *A = Args.getLastArg(options::OPT_mdouble_float,
88*bdd1243dSDimitry Andric                                      options::OPT_msingle_float,
89*bdd1243dSDimitry Andric                                      options::OPT_msoft_float)) {
90*bdd1243dSDimitry Andric     if (A->getOption().matches(options::OPT_mdouble_float)) {
91*bdd1243dSDimitry Andric       Features.push_back("+f");
92*bdd1243dSDimitry Andric       Features.push_back("+d");
93*bdd1243dSDimitry Andric     } else if (A->getOption().matches(options::OPT_msingle_float)) {
94*bdd1243dSDimitry Andric       Features.push_back("+f");
95*bdd1243dSDimitry Andric       Features.push_back("-d");
96*bdd1243dSDimitry Andric     } else /*Soft-float*/ {
97*bdd1243dSDimitry Andric       Features.push_back("-f");
98*bdd1243dSDimitry Andric       Features.push_back("-d");
99*bdd1243dSDimitry Andric     }
100*bdd1243dSDimitry Andric   } else if (const Arg *A = Args.getLastArg(options::OPT_mfpu_EQ)) {
101*bdd1243dSDimitry Andric     StringRef FPU = A->getValue();
102*bdd1243dSDimitry Andric     if (FPU == "64") {
103*bdd1243dSDimitry Andric       Features.push_back("+f");
104*bdd1243dSDimitry Andric       Features.push_back("+d");
105*bdd1243dSDimitry Andric     } else if (FPU == "32") {
106*bdd1243dSDimitry Andric       Features.push_back("+f");
107*bdd1243dSDimitry Andric       Features.push_back("-d");
108*bdd1243dSDimitry Andric     } else if (FPU == "0" || FPU == "none") {
109*bdd1243dSDimitry Andric       Features.push_back("-f");
110*bdd1243dSDimitry Andric       Features.push_back("-d");
111*bdd1243dSDimitry Andric     } else {
112*bdd1243dSDimitry Andric       D.Diag(diag::err_drv_loongarch_invalid_mfpu_EQ) << FPU;
113*bdd1243dSDimitry Andric     }
114*bdd1243dSDimitry Andric   }
115*bdd1243dSDimitry Andric }
116