171 lines
6.1 KiB
C++
171 lines
6.1 KiB
C++
//===--- CSKY.cpp - CSKY Helpers for Tools --------------------*- C++ -*-===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "CSKY.h"
|
|
#include "ToolChains/CommonArgs.h"
|
|
#include "clang/Basic/CharInfo.h"
|
|
#include "clang/Driver/Driver.h"
|
|
#include "clang/Driver/DriverDiagnostic.h"
|
|
#include "clang/Driver/Options.h"
|
|
#include "llvm/ADT/Optional.h"
|
|
#include "llvm/ADT/StringSwitch.h"
|
|
#include "llvm/Option/ArgList.h"
|
|
#include "llvm/Support/CSKYTargetParser.h"
|
|
#include "llvm/Support/Host.h"
|
|
#include "llvm/Support/TargetParser.h"
|
|
#include "llvm/Support/raw_ostream.h"
|
|
|
|
using namespace clang::driver;
|
|
using namespace clang::driver::tools;
|
|
using namespace clang;
|
|
using namespace llvm::opt;
|
|
|
|
std::optional<llvm::StringRef>
|
|
csky::getCSKYArchName(const Driver &D, const ArgList &Args,
|
|
const llvm::Triple &Triple) {
|
|
if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) {
|
|
llvm::CSKY::ArchKind ArchKind = llvm::CSKY::parseArch(A->getValue());
|
|
|
|
if (ArchKind == llvm::CSKY::ArchKind::INVALID) {
|
|
D.Diag(clang::diag::err_drv_invalid_arch_name) << A->getAsString(Args);
|
|
return std::nullopt;
|
|
}
|
|
return std::optional<llvm::StringRef>(A->getValue());
|
|
}
|
|
|
|
if (const Arg *A = Args.getLastArg(clang::driver::options::OPT_mcpu_EQ)) {
|
|
llvm::CSKY::ArchKind ArchKind = llvm::CSKY::parseCPUArch(A->getValue());
|
|
if (ArchKind == llvm::CSKY::ArchKind::INVALID) {
|
|
D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args);
|
|
return std::nullopt;
|
|
}
|
|
return std::optional<llvm::StringRef>(llvm::CSKY::getArchName(ArchKind));
|
|
}
|
|
|
|
return std::optional<llvm::StringRef>("ck810");
|
|
}
|
|
|
|
csky::FloatABI csky::getCSKYFloatABI(const Driver &D, const ArgList &Args) {
|
|
csky::FloatABI ABI = FloatABI::Soft;
|
|
if (Arg *A =
|
|
Args.getLastArg(options::OPT_msoft_float, options::OPT_mhard_float,
|
|
options::OPT_mfloat_abi_EQ)) {
|
|
if (A->getOption().matches(options::OPT_msoft_float)) {
|
|
ABI = FloatABI::Soft;
|
|
} else if (A->getOption().matches(options::OPT_mhard_float)) {
|
|
ABI = FloatABI::Hard;
|
|
} else {
|
|
ABI = llvm::StringSwitch<csky::FloatABI>(A->getValue())
|
|
.Case("soft", FloatABI::Soft)
|
|
.Case("softfp", FloatABI::SoftFP)
|
|
.Case("hard", FloatABI::Hard)
|
|
.Default(FloatABI::Invalid);
|
|
if (ABI == FloatABI::Invalid) {
|
|
D.Diag(diag::err_drv_invalid_mfloat_abi) << A->getAsString(Args);
|
|
ABI = FloatABI::Soft;
|
|
}
|
|
}
|
|
}
|
|
|
|
return ABI;
|
|
}
|
|
|
|
// Handle -mfpu=.
|
|
static llvm::CSKY::CSKYFPUKind
|
|
getCSKYFPUFeatures(const Driver &D, const Arg *A, const ArgList &Args,
|
|
StringRef FPU, std::vector<StringRef> &Features) {
|
|
|
|
llvm::CSKY::CSKYFPUKind FPUID =
|
|
llvm::StringSwitch<llvm::CSKY::CSKYFPUKind>(FPU)
|
|
.Case("auto", llvm::CSKY::FK_AUTO)
|
|
.Case("fpv2", llvm::CSKY::FK_FPV2)
|
|
.Case("fpv2_divd", llvm::CSKY::FK_FPV2_DIVD)
|
|
.Case("fpv2_sf", llvm::CSKY::FK_FPV2_SF)
|
|
.Case("fpv3", llvm::CSKY::FK_FPV3)
|
|
.Case("fpv3_hf", llvm::CSKY::FK_FPV3_HF)
|
|
.Case("fpv3_hsf", llvm::CSKY::FK_FPV3_HSF)
|
|
.Case("fpv3_sdf", llvm::CSKY::FK_FPV3_SDF)
|
|
.Default(llvm::CSKY::FK_INVALID);
|
|
if (FPUID == llvm::CSKY::FK_INVALID) {
|
|
D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args);
|
|
return llvm::CSKY::FK_INVALID;
|
|
}
|
|
|
|
auto RemoveTargetFPUFeature =
|
|
[&Features](ArrayRef<const char *> FPUFeatures) {
|
|
for (auto FPUFeature : FPUFeatures) {
|
|
auto it = llvm::find(Features, FPUFeature);
|
|
if (it != Features.end())
|
|
Features.erase(it);
|
|
}
|
|
};
|
|
|
|
RemoveTargetFPUFeature({"+fpuv2_sf", "+fpuv2_df", "+fdivdu", "+fpuv3_hi",
|
|
"+fpuv3_hf", "+fpuv3_sf", "+fpuv3_df"});
|
|
|
|
if (!llvm::CSKY::getFPUFeatures(FPUID, Features)) {
|
|
D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args);
|
|
return llvm::CSKY::FK_INVALID;
|
|
}
|
|
|
|
return FPUID;
|
|
}
|
|
|
|
void csky::getCSKYTargetFeatures(const Driver &D, const llvm::Triple &Triple,
|
|
const ArgList &Args, ArgStringList &CmdArgs,
|
|
std::vector<llvm::StringRef> &Features) {
|
|
llvm::StringRef archName;
|
|
llvm::StringRef cpuName;
|
|
llvm::CSKY::ArchKind ArchKind = llvm::CSKY::ArchKind::INVALID;
|
|
if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) {
|
|
ArchKind = llvm::CSKY::parseArch(A->getValue());
|
|
if (ArchKind == llvm::CSKY::ArchKind::INVALID) {
|
|
D.Diag(clang::diag::err_drv_invalid_arch_name) << A->getAsString(Args);
|
|
return;
|
|
}
|
|
archName = A->getValue();
|
|
}
|
|
|
|
if (const Arg *A = Args.getLastArg(clang::driver::options::OPT_mcpu_EQ)) {
|
|
llvm::CSKY::ArchKind Kind = llvm::CSKY::parseCPUArch(A->getValue());
|
|
if (Kind == llvm::CSKY::ArchKind::INVALID) {
|
|
D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args);
|
|
return;
|
|
}
|
|
if (!archName.empty() && Kind != ArchKind) {
|
|
D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args);
|
|
return;
|
|
}
|
|
cpuName = A->getValue();
|
|
if (archName.empty())
|
|
archName = llvm::CSKY::getArchName(Kind);
|
|
}
|
|
|
|
if (archName.empty() && cpuName.empty()) {
|
|
archName = "ck810";
|
|
cpuName = "ck810";
|
|
} else if (!archName.empty() && cpuName.empty()) {
|
|
cpuName = archName;
|
|
}
|
|
|
|
csky::FloatABI FloatABI = csky::getCSKYFloatABI(D, Args);
|
|
|
|
if (FloatABI == csky::FloatABI::Hard) {
|
|
Features.push_back("+hard-float-abi");
|
|
Features.push_back("+hard-float");
|
|
} else if (FloatABI == csky::FloatABI::SoftFP) {
|
|
Features.push_back("+hard-float");
|
|
}
|
|
|
|
uint64_t Extension = llvm::CSKY::getDefaultExtensions(cpuName);
|
|
llvm::CSKY::getExtensionFeatures(Extension, Features);
|
|
|
|
if (const Arg *FPUArg = Args.getLastArg(options::OPT_mfpu_EQ))
|
|
getCSKYFPUFeatures(D, FPUArg, Args, FPUArg->getValue(), Features);
|
|
}
|