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