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