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