238 lines · c
1//===--- RISCV.h - Declare RISC-V target feature support --------*- 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-exception6//7//===----------------------------------------------------------------------===//8//9// This file declares RISC-V TargetInfo objects.10//11//===----------------------------------------------------------------------===//12 13#ifndef LLVM_CLANG_LIB_BASIC_TARGETS_RISCV_H14#define LLVM_CLANG_LIB_BASIC_TARGETS_RISCV_H15 16#include "clang/Basic/TargetInfo.h"17#include "clang/Basic/TargetOptions.h"18#include "llvm/Support/Compiler.h"19#include "llvm/TargetParser/RISCVISAInfo.h"20#include "llvm/TargetParser/Triple.h"21#include <optional>22 23namespace clang {24namespace targets {25 26// RISC-V Target27class RISCVTargetInfo : public TargetInfo {28protected:29 std::string ABI, CPU;30 std::unique_ptr<llvm::RISCVISAInfo> ISAInfo;31 32private:33 bool FastScalarUnalignedAccess;34 bool HasExperimental = false;35 36public:37 RISCVTargetInfo(const llvm::Triple &Triple, const TargetOptions &)38 : TargetInfo(Triple) {39 BFloat16Width = 16;40 BFloat16Align = 16;41 BFloat16Format = &llvm::APFloat::BFloat();42 LongDoubleWidth = 128;43 LongDoubleAlign = 128;44 LongDoubleFormat = &llvm::APFloat::IEEEquad();45 SuitableAlign = 128;46 WCharType = SignedInt;47 WIntType = UnsignedInt;48 HasRISCVVTypes = true;49 MCountName = "_mcount";50 HasFloat16 = true;51 HasStrictFP = true;52 }53 54 bool setCPU(const std::string &Name) override {55 if (!isValidCPUName(Name))56 return false;57 CPU = Name;58 return true;59 }60 61 StringRef getABI() const override { return ABI; }62 void getTargetDefines(const LangOptions &Opts,63 MacroBuilder &Builder) const override;64 65 llvm::SmallVector<Builtin::InfosShard> getTargetBuiltins() const override;66 67 BuiltinVaListKind getBuiltinVaListKind() const override {68 return TargetInfo::VoidPtrBuiltinVaList;69 }70 71 std::string_view getClobbers() const override { return ""; }72 73 StringRef getConstraintRegister(StringRef Constraint,74 StringRef Expression) const override {75 return Expression;76 }77 78 ArrayRef<const char *> getGCCRegNames() const override;79 80 int getEHDataRegisterNumber(unsigned RegNo) const override {81 if (RegNo == 0)82 return 10;83 else if (RegNo == 1)84 return 11;85 else86 return -1;87 }88 89 ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override;90 91 bool validateAsmConstraint(const char *&Name,92 TargetInfo::ConstraintInfo &Info) const override;93 94 std::string convertConstraint(const char *&Constraint) const override;95 96 bool97 initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags,98 StringRef CPU,99 const std::vector<std::string> &FeaturesVec) const override;100 101 std::optional<std::pair<unsigned, unsigned>>102 getVScaleRange(const LangOptions &LangOpts, ArmStreamingKind Mode,103 llvm::StringMap<bool> *FeatureMap = nullptr) const override;104 105 bool hasFeature(StringRef Feature) const override;106 107 bool handleTargetFeatures(std::vector<std::string> &Features,108 DiagnosticsEngine &Diags) override;109 110 bool hasBitIntType() const override { return true; }111 112 bool hasBFloat16Type() const override { return true; }113 114 CallingConvCheckResult checkCallingConvention(CallingConv CC) const override;115 116 bool useFP16ConversionIntrinsics() const override {117 return false;118 }119 120 bool isValidCPUName(StringRef Name) const override;121 void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override;122 bool isValidTuneCPUName(StringRef Name) const override;123 void fillValidTuneCPUList(SmallVectorImpl<StringRef> &Values) const override;124 bool supportsTargetAttributeTune() const override { return true; }125 ParsedTargetAttr parseTargetAttr(StringRef Str) const override;126 llvm::APInt getFMVPriority(ArrayRef<StringRef> Features) const override;127 128 std::pair<unsigned, unsigned> hardwareInterferenceSizes() const override {129 return std::make_pair(64, 64);130 }131 132 bool supportsCpuSupports() const override { return getTriple().isOSLinux(); }133 bool supportsCpuIs() const override { return getTriple().isOSLinux(); }134 bool supportsCpuInit() const override { return getTriple().isOSLinux(); }135 bool validateCpuSupports(StringRef Feature) const override;136 bool validateCpuIs(StringRef CPUName) const override;137 bool isValidFeatureName(StringRef Name) const override;138 139 bool validateGlobalRegisterVariable(StringRef RegName, unsigned RegSize,140 bool &HasSizeMismatch) const override;141 142 bool checkCFProtectionBranchSupported(DiagnosticsEngine &) const override {143 // Always generate Zicfilp lpad insns144 // Non-zicfilp CPUs would read them as NOP145 return true;146 }147 148 bool149 checkCFProtectionReturnSupported(DiagnosticsEngine &Diags) const override {150 if (ISAInfo->hasExtension("zimop"))151 return true;152 return TargetInfo::checkCFProtectionReturnSupported(Diags);153 }154 155 CFBranchLabelSchemeKind getDefaultCFBranchLabelScheme() const override {156 return CFBranchLabelSchemeKind::FuncSig;157 }158 159 bool160 checkCFBranchLabelSchemeSupported(const CFBranchLabelSchemeKind Scheme,161 DiagnosticsEngine &Diags) const override {162 switch (Scheme) {163 case CFBranchLabelSchemeKind::Default:164 case CFBranchLabelSchemeKind::Unlabeled:165 case CFBranchLabelSchemeKind::FuncSig:166 return true;167 }168 return TargetInfo::checkCFBranchLabelSchemeSupported(Scheme, Diags);169 }170};171class LLVM_LIBRARY_VISIBILITY RISCV32TargetInfo : public RISCVTargetInfo {172public:173 RISCV32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)174 : RISCVTargetInfo(Triple, Opts) {175 IntPtrType = SignedInt;176 PtrDiffType = SignedInt;177 SizeType = UnsignedInt;178 resetDataLayout("e-m:e-p:32:32-i64:64-n32-S128");179 }180 181 bool setABI(const std::string &Name) override {182 if (Name == "ilp32e") {183 ABI = Name;184 resetDataLayout("e-m:e-p:32:32-i64:64-n32-S32");185 return true;186 }187 188 if (Name == "ilp32" || Name == "ilp32f" || Name == "ilp32d") {189 ABI = Name;190 return true;191 }192 return false;193 }194 195 void setMaxAtomicWidth() override {196 MaxAtomicPromoteWidth = 128;197 198 // "a" implies "zalrsc" which is sufficient to inline atomics199 if (ISAInfo->hasExtension("zalrsc"))200 MaxAtomicInlineWidth = 32;201 }202};203class LLVM_LIBRARY_VISIBILITY RISCV64TargetInfo : public RISCVTargetInfo {204public:205 RISCV64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)206 : RISCVTargetInfo(Triple, Opts) {207 LongWidth = LongAlign = PointerWidth = PointerAlign = 64;208 IntMaxType = Int64Type = SignedLong;209 resetDataLayout("e-m:e-p:64:64-i64:64-i128:128-n32:64-S128");210 }211 212 bool setABI(const std::string &Name) override {213 if (Name == "lp64e") {214 ABI = Name;215 resetDataLayout("e-m:e-p:64:64-i64:64-i128:128-n32:64-S64");216 return true;217 }218 219 if (Name == "lp64" || Name == "lp64f" || Name == "lp64d") {220 ABI = Name;221 return true;222 }223 return false;224 }225 226 void setMaxAtomicWidth() override {227 MaxAtomicPromoteWidth = 128;228 229 // "a" implies "zalrsc" which is sufficient to inline atomics230 if (ISAInfo->hasExtension("zalrsc"))231 MaxAtomicInlineWidth = 64;232 }233};234} // namespace targets235} // namespace clang236 237#endif // LLVM_CLANG_LIB_BASIC_TARGETS_RISCV_H238