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 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 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