1 //===--- CSKY.cpp - CSKY 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 "CSKY.h" 10 #include "ToolChains/CommonArgs.h" 11 #include "clang/Basic/CharInfo.h" 12 #include "clang/Driver/Driver.h" 13 #include "clang/Driver/DriverDiagnostic.h" 14 #include "clang/Driver/Options.h" 15 #include "llvm/ADT/Optional.h" 16 #include "llvm/ADT/StringSwitch.h" 17 #include "llvm/Option/ArgList.h" 18 #include "llvm/Support/CSKYTargetParser.h" 19 #include "llvm/Support/Host.h" 20 #include "llvm/Support/TargetParser.h" 21 #include "llvm/Support/raw_ostream.h" 22 23 using namespace clang::driver; 24 using namespace clang::driver::tools; 25 using namespace clang; 26 using namespace llvm::opt; 27 28 llvm::Optional<llvm::StringRef> 29 csky::getCSKYArchName(const Driver &D, const ArgList &Args, 30 const llvm::Triple &Triple) { 31 if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) { 32 llvm::CSKY::ArchKind ArchKind = llvm::CSKY::parseArch(A->getValue()); 33 34 if (ArchKind == llvm::CSKY::ArchKind::INVALID) { 35 D.Diag(clang::diag::err_drv_invalid_arch_name) << A->getAsString(Args); 36 return llvm::Optional<llvm::StringRef>(); 37 } 38 return llvm::Optional<llvm::StringRef>(A->getValue()); 39 } 40 41 if (const Arg *A = Args.getLastArg(clang::driver::options::OPT_mcpu_EQ)) { 42 llvm::CSKY::ArchKind ArchKind = llvm::CSKY::parseCPUArch(A->getValue()); 43 if (ArchKind == llvm::CSKY::ArchKind::INVALID) { 44 D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args); 45 return llvm::Optional<llvm::StringRef>(); 46 } 47 return llvm::Optional<llvm::StringRef>(llvm::CSKY::getArchName(ArchKind)); 48 } 49 50 return llvm::Optional<llvm::StringRef>("ck810"); 51 } 52 53 csky::FloatABI csky::getCSKYFloatABI(const Driver &D, const ArgList &Args) { 54 csky::FloatABI ABI = FloatABI::Soft; 55 if (Arg *A = 56 Args.getLastArg(options::OPT_msoft_float, options::OPT_mhard_float, 57 options::OPT_mfloat_abi_EQ)) { 58 if (A->getOption().matches(options::OPT_msoft_float)) { 59 ABI = FloatABI::Soft; 60 } else if (A->getOption().matches(options::OPT_mhard_float)) { 61 ABI = FloatABI::Hard; 62 } else { 63 ABI = llvm::StringSwitch<csky::FloatABI>(A->getValue()) 64 .Case("soft", FloatABI::Soft) 65 .Case("softfp", FloatABI::SoftFP) 66 .Case("hard", FloatABI::Hard) 67 .Default(FloatABI::Invalid); 68 if (ABI == FloatABI::Invalid) { 69 D.Diag(diag::err_drv_invalid_mfloat_abi) << A->getAsString(Args); 70 ABI = FloatABI::Soft; 71 } 72 } 73 } 74 75 return ABI; 76 } 77 78 // Handle -mfpu=. 79 static llvm::CSKY::CSKYFPUKind 80 getCSKYFPUFeatures(const Driver &D, const Arg *A, const ArgList &Args, 81 StringRef FPU, std::vector<StringRef> &Features) { 82 83 llvm::CSKY::CSKYFPUKind FPUID = 84 llvm::StringSwitch<llvm::CSKY::CSKYFPUKind>(FPU) 85 .Case("auto", llvm::CSKY::FK_AUTO) 86 .Case("fpv2", llvm::CSKY::FK_FPV2) 87 .Case("fpv2_divd", llvm::CSKY::FK_FPV2_DIVD) 88 .Case("fpv2_sf", llvm::CSKY::FK_FPV2_SF) 89 .Case("fpv3", llvm::CSKY::FK_FPV3) 90 .Case("fpv3_hf", llvm::CSKY::FK_FPV3_HF) 91 .Case("fpv3_hsf", llvm::CSKY::FK_FPV3_HSF) 92 .Case("fpv3_sdf", llvm::CSKY::FK_FPV3_SDF) 93 .Default(llvm::CSKY::FK_INVALID); 94 95 if (!llvm::CSKY::getFPUFeatures(FPUID, Features)) { 96 D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args); 97 return llvm::CSKY::FK_INVALID; 98 } 99 100 return FPUID; 101 } 102 103 void csky::getCSKYTargetFeatures(const Driver &D, const llvm::Triple &Triple, 104 const ArgList &Args, ArgStringList &CmdArgs, 105 std::vector<llvm::StringRef> &Features) { 106 llvm::StringRef archName; 107 llvm::StringRef cpuName; 108 llvm::CSKY::ArchKind ArchKind = llvm::CSKY::ArchKind::INVALID; 109 if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) { 110 ArchKind = llvm::CSKY::parseArch(A->getValue()); 111 if (ArchKind == llvm::CSKY::ArchKind::INVALID) { 112 D.Diag(clang::diag::err_drv_invalid_arch_name) << A->getAsString(Args); 113 return; 114 } 115 archName = A->getValue(); 116 } 117 118 if (const Arg *A = Args.getLastArg(clang::driver::options::OPT_mcpu_EQ)) { 119 llvm::CSKY::ArchKind Kind = llvm::CSKY::parseCPUArch(A->getValue()); 120 if (Kind == llvm::CSKY::ArchKind::INVALID) { 121 D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args); 122 return; 123 } 124 if (!archName.empty() && Kind != ArchKind) { 125 D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args); 126 return; 127 } 128 cpuName = A->getValue(); 129 } 130 131 if (archName.empty() && cpuName.empty()) { 132 archName = "ck810"; 133 cpuName = "ck810"; 134 } else if (!archName.empty() && cpuName.empty()) { 135 cpuName = archName; 136 } 137 138 csky::FloatABI FloatABI = csky::getCSKYFloatABI(D, Args); 139 140 if (FloatABI == csky::FloatABI::Hard) { 141 Features.push_back("+hard-float-abi"); 142 Features.push_back("+hard-float"); 143 } else if (FloatABI == csky::FloatABI::SoftFP) { 144 Features.push_back("+hard-float"); 145 } 146 147 if (const Arg *FPUArg = Args.getLastArg(options::OPT_mfpu_EQ)) 148 getCSKYFPUFeatures(D, FPUArg, Args, FPUArg->getValue(), Features); 149 else if (FloatABI != csky::FloatABI::Soft && archName.empty()) 150 llvm::CSKY::getFPUFeatures(llvm::CSKY::FK_AUTO, Features); 151 152 uint64_t Extension = llvm::CSKY::getDefaultExtensions(cpuName); 153 llvm::CSKY::getExtensionFeatures(Extension, Features); 154 } 155