1*81ad6265SDimitry Andric //===--- CSKY.cpp - CSKY Helpers for Tools --------------------*- C++ -*-===// 2*81ad6265SDimitry Andric // 3*81ad6265SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*81ad6265SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*81ad6265SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*81ad6265SDimitry Andric // 7*81ad6265SDimitry Andric //===----------------------------------------------------------------------===// 8*81ad6265SDimitry Andric 9*81ad6265SDimitry Andric #include "CSKY.h" 10*81ad6265SDimitry Andric #include "ToolChains/CommonArgs.h" 11*81ad6265SDimitry Andric #include "clang/Basic/CharInfo.h" 12*81ad6265SDimitry Andric #include "clang/Driver/Driver.h" 13*81ad6265SDimitry Andric #include "clang/Driver/DriverDiagnostic.h" 14*81ad6265SDimitry Andric #include "clang/Driver/Options.h" 15*81ad6265SDimitry Andric #include "llvm/ADT/Optional.h" 16*81ad6265SDimitry Andric #include "llvm/ADT/StringSwitch.h" 17*81ad6265SDimitry Andric #include "llvm/Option/ArgList.h" 18*81ad6265SDimitry Andric #include "llvm/Support/CSKYTargetParser.h" 19*81ad6265SDimitry Andric #include "llvm/Support/Host.h" 20*81ad6265SDimitry Andric #include "llvm/Support/TargetParser.h" 21*81ad6265SDimitry Andric #include "llvm/Support/raw_ostream.h" 22*81ad6265SDimitry Andric 23*81ad6265SDimitry Andric using namespace clang::driver; 24*81ad6265SDimitry Andric using namespace clang::driver::tools; 25*81ad6265SDimitry Andric using namespace clang; 26*81ad6265SDimitry Andric using namespace llvm::opt; 27*81ad6265SDimitry Andric 28*81ad6265SDimitry Andric llvm::Optional<llvm::StringRef> 29*81ad6265SDimitry Andric csky::getCSKYArchName(const Driver &D, const ArgList &Args, 30*81ad6265SDimitry Andric const llvm::Triple &Triple) { 31*81ad6265SDimitry Andric if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) { 32*81ad6265SDimitry Andric llvm::CSKY::ArchKind ArchKind = llvm::CSKY::parseArch(A->getValue()); 33*81ad6265SDimitry Andric 34*81ad6265SDimitry Andric if (ArchKind == llvm::CSKY::ArchKind::INVALID) { 35*81ad6265SDimitry Andric D.Diag(clang::diag::err_drv_invalid_arch_name) << A->getAsString(Args); 36*81ad6265SDimitry Andric return llvm::Optional<llvm::StringRef>(); 37*81ad6265SDimitry Andric } 38*81ad6265SDimitry Andric return llvm::Optional<llvm::StringRef>(A->getValue()); 39*81ad6265SDimitry Andric } 40*81ad6265SDimitry Andric 41*81ad6265SDimitry Andric if (const Arg *A = Args.getLastArg(clang::driver::options::OPT_mcpu_EQ)) { 42*81ad6265SDimitry Andric llvm::CSKY::ArchKind ArchKind = llvm::CSKY::parseCPUArch(A->getValue()); 43*81ad6265SDimitry Andric if (ArchKind == llvm::CSKY::ArchKind::INVALID) { 44*81ad6265SDimitry Andric D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args); 45*81ad6265SDimitry Andric return llvm::Optional<llvm::StringRef>(); 46*81ad6265SDimitry Andric } 47*81ad6265SDimitry Andric return llvm::Optional<llvm::StringRef>(llvm::CSKY::getArchName(ArchKind)); 48*81ad6265SDimitry Andric } 49*81ad6265SDimitry Andric 50*81ad6265SDimitry Andric return llvm::Optional<llvm::StringRef>("ck810"); 51*81ad6265SDimitry Andric } 52*81ad6265SDimitry Andric 53*81ad6265SDimitry Andric csky::FloatABI csky::getCSKYFloatABI(const Driver &D, const ArgList &Args) { 54*81ad6265SDimitry Andric csky::FloatABI ABI = FloatABI::Soft; 55*81ad6265SDimitry Andric if (Arg *A = 56*81ad6265SDimitry Andric Args.getLastArg(options::OPT_msoft_float, options::OPT_mhard_float, 57*81ad6265SDimitry Andric options::OPT_mfloat_abi_EQ)) { 58*81ad6265SDimitry Andric if (A->getOption().matches(options::OPT_msoft_float)) { 59*81ad6265SDimitry Andric ABI = FloatABI::Soft; 60*81ad6265SDimitry Andric } else if (A->getOption().matches(options::OPT_mhard_float)) { 61*81ad6265SDimitry Andric ABI = FloatABI::Hard; 62*81ad6265SDimitry Andric } else { 63*81ad6265SDimitry Andric ABI = llvm::StringSwitch<csky::FloatABI>(A->getValue()) 64*81ad6265SDimitry Andric .Case("soft", FloatABI::Soft) 65*81ad6265SDimitry Andric .Case("softfp", FloatABI::SoftFP) 66*81ad6265SDimitry Andric .Case("hard", FloatABI::Hard) 67*81ad6265SDimitry Andric .Default(FloatABI::Invalid); 68*81ad6265SDimitry Andric if (ABI == FloatABI::Invalid) { 69*81ad6265SDimitry Andric D.Diag(diag::err_drv_invalid_mfloat_abi) << A->getAsString(Args); 70*81ad6265SDimitry Andric ABI = FloatABI::Soft; 71*81ad6265SDimitry Andric } 72*81ad6265SDimitry Andric } 73*81ad6265SDimitry Andric } 74*81ad6265SDimitry Andric 75*81ad6265SDimitry Andric return ABI; 76*81ad6265SDimitry Andric } 77*81ad6265SDimitry Andric 78*81ad6265SDimitry Andric // Handle -mfpu=. 79*81ad6265SDimitry Andric static llvm::CSKY::CSKYFPUKind 80*81ad6265SDimitry Andric getCSKYFPUFeatures(const Driver &D, const Arg *A, const ArgList &Args, 81*81ad6265SDimitry Andric StringRef FPU, std::vector<StringRef> &Features) { 82*81ad6265SDimitry Andric 83*81ad6265SDimitry Andric llvm::CSKY::CSKYFPUKind FPUID = 84*81ad6265SDimitry Andric llvm::StringSwitch<llvm::CSKY::CSKYFPUKind>(FPU) 85*81ad6265SDimitry Andric .Case("auto", llvm::CSKY::FK_AUTO) 86*81ad6265SDimitry Andric .Case("fpv2", llvm::CSKY::FK_FPV2) 87*81ad6265SDimitry Andric .Case("fpv2_divd", llvm::CSKY::FK_FPV2_DIVD) 88*81ad6265SDimitry Andric .Case("fpv2_sf", llvm::CSKY::FK_FPV2_SF) 89*81ad6265SDimitry Andric .Case("fpv3", llvm::CSKY::FK_FPV3) 90*81ad6265SDimitry Andric .Case("fpv3_hf", llvm::CSKY::FK_FPV3_HF) 91*81ad6265SDimitry Andric .Case("fpv3_hsf", llvm::CSKY::FK_FPV3_HSF) 92*81ad6265SDimitry Andric .Case("fpv3_sdf", llvm::CSKY::FK_FPV3_SDF) 93*81ad6265SDimitry Andric .Default(llvm::CSKY::FK_INVALID); 94*81ad6265SDimitry Andric if (FPUID == llvm::CSKY::FK_INVALID) { 95*81ad6265SDimitry Andric D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args); 96*81ad6265SDimitry Andric return llvm::CSKY::FK_INVALID; 97*81ad6265SDimitry Andric } 98*81ad6265SDimitry Andric 99*81ad6265SDimitry Andric auto RemoveTargetFPUFeature = 100*81ad6265SDimitry Andric [&Features](ArrayRef<const char *> FPUFeatures) { 101*81ad6265SDimitry Andric for (auto FPUFeature : FPUFeatures) { 102*81ad6265SDimitry Andric auto it = std::find(Features.begin(), Features.end(), FPUFeature); 103*81ad6265SDimitry Andric if (it != Features.end()) 104*81ad6265SDimitry Andric Features.erase(it); 105*81ad6265SDimitry Andric } 106*81ad6265SDimitry Andric }; 107*81ad6265SDimitry Andric 108*81ad6265SDimitry Andric RemoveTargetFPUFeature({"+fpuv2_sf", "+fpuv2_df", "+fdivdu", "+fpuv3_hi", 109*81ad6265SDimitry Andric "+fpuv3_hf", "+fpuv3_sf", "+fpuv3_df"}); 110*81ad6265SDimitry Andric 111*81ad6265SDimitry Andric if (!llvm::CSKY::getFPUFeatures(FPUID, Features)) { 112*81ad6265SDimitry Andric D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args); 113*81ad6265SDimitry Andric return llvm::CSKY::FK_INVALID; 114*81ad6265SDimitry Andric } 115*81ad6265SDimitry Andric 116*81ad6265SDimitry Andric return FPUID; 117*81ad6265SDimitry Andric } 118*81ad6265SDimitry Andric 119*81ad6265SDimitry Andric void csky::getCSKYTargetFeatures(const Driver &D, const llvm::Triple &Triple, 120*81ad6265SDimitry Andric const ArgList &Args, ArgStringList &CmdArgs, 121*81ad6265SDimitry Andric std::vector<llvm::StringRef> &Features) { 122*81ad6265SDimitry Andric llvm::StringRef archName; 123*81ad6265SDimitry Andric llvm::StringRef cpuName; 124*81ad6265SDimitry Andric llvm::CSKY::ArchKind ArchKind = llvm::CSKY::ArchKind::INVALID; 125*81ad6265SDimitry Andric if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) { 126*81ad6265SDimitry Andric ArchKind = llvm::CSKY::parseArch(A->getValue()); 127*81ad6265SDimitry Andric if (ArchKind == llvm::CSKY::ArchKind::INVALID) { 128*81ad6265SDimitry Andric D.Diag(clang::diag::err_drv_invalid_arch_name) << A->getAsString(Args); 129*81ad6265SDimitry Andric return; 130*81ad6265SDimitry Andric } 131*81ad6265SDimitry Andric archName = A->getValue(); 132*81ad6265SDimitry Andric } 133*81ad6265SDimitry Andric 134*81ad6265SDimitry Andric if (const Arg *A = Args.getLastArg(clang::driver::options::OPT_mcpu_EQ)) { 135*81ad6265SDimitry Andric llvm::CSKY::ArchKind Kind = llvm::CSKY::parseCPUArch(A->getValue()); 136*81ad6265SDimitry Andric if (Kind == llvm::CSKY::ArchKind::INVALID) { 137*81ad6265SDimitry Andric D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args); 138*81ad6265SDimitry Andric return; 139*81ad6265SDimitry Andric } 140*81ad6265SDimitry Andric if (!archName.empty() && Kind != ArchKind) { 141*81ad6265SDimitry Andric D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args); 142*81ad6265SDimitry Andric return; 143*81ad6265SDimitry Andric } 144*81ad6265SDimitry Andric cpuName = A->getValue(); 145*81ad6265SDimitry Andric if (archName.empty()) 146*81ad6265SDimitry Andric archName = llvm::CSKY::getArchName(Kind); 147*81ad6265SDimitry Andric } 148*81ad6265SDimitry Andric 149*81ad6265SDimitry Andric if (archName.empty() && cpuName.empty()) { 150*81ad6265SDimitry Andric archName = "ck810"; 151*81ad6265SDimitry Andric cpuName = "ck810"; 152*81ad6265SDimitry Andric } else if (!archName.empty() && cpuName.empty()) { 153*81ad6265SDimitry Andric cpuName = archName; 154*81ad6265SDimitry Andric } 155*81ad6265SDimitry Andric 156*81ad6265SDimitry Andric csky::FloatABI FloatABI = csky::getCSKYFloatABI(D, Args); 157*81ad6265SDimitry Andric 158*81ad6265SDimitry Andric if (FloatABI == csky::FloatABI::Hard) { 159*81ad6265SDimitry Andric Features.push_back("+hard-float-abi"); 160*81ad6265SDimitry Andric Features.push_back("+hard-float"); 161*81ad6265SDimitry Andric } else if (FloatABI == csky::FloatABI::SoftFP) { 162*81ad6265SDimitry Andric Features.push_back("+hard-float"); 163*81ad6265SDimitry Andric } 164*81ad6265SDimitry Andric 165*81ad6265SDimitry Andric uint64_t Extension = llvm::CSKY::getDefaultExtensions(cpuName); 166*81ad6265SDimitry Andric llvm::CSKY::getExtensionFeatures(Extension, Features); 167*81ad6265SDimitry Andric 168*81ad6265SDimitry Andric if (const Arg *FPUArg = Args.getLastArg(options::OPT_mfpu_EQ)) 169*81ad6265SDimitry Andric getCSKYFPUFeatures(D, FPUArg, Args, FPUArg->getValue(), Features); 170*81ad6265SDimitry Andric } 171