1 //===-- RISCVTargetParser.cpp - Parser for target features ------*- 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 // This file implements a target parser to recognise hardware features
10 // FOR RISC-V CPUS.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "llvm/TargetParser/RISCVTargetParser.h"
15 #include "llvm/ADT/SmallVector.h"
16 #include "llvm/ADT/StringSwitch.h"
17 #include "llvm/TargetParser/Triple.h"
18
19 namespace llvm {
20 namespace RISCV {
21
22 struct CPUInfo {
23 StringLiteral Name;
24 CPUKind Kind;
25 StringLiteral DefaultMarch;
isInvalidllvm::RISCV::CPUInfo26 bool isInvalid() const { return DefaultMarch.empty(); }
is64Bitllvm::RISCV::CPUInfo27 bool is64Bit() const { return DefaultMarch.starts_with("rv64"); }
28 };
29
30 constexpr CPUInfo RISCVCPUInfo[] = {
31 #define PROC(ENUM, NAME, DEFAULT_MARCH) \
32 {NAME, CK_##ENUM, DEFAULT_MARCH},
33 #include "llvm/TargetParser/RISCVTargetParserDef.inc"
34 };
35
checkCPUKind(CPUKind Kind,bool IsRV64)36 bool checkCPUKind(CPUKind Kind, bool IsRV64) {
37 if (Kind == CK_INVALID)
38 return false;
39 return RISCVCPUInfo[static_cast<unsigned>(Kind)].is64Bit() == IsRV64;
40 }
41
checkTuneCPUKind(CPUKind Kind,bool IsRV64)42 bool checkTuneCPUKind(CPUKind Kind, bool IsRV64) {
43 if (Kind == CK_INVALID)
44 return false;
45 #define TUNE_PROC(ENUM, NAME) \
46 if (Kind == CK_##ENUM) \
47 return true;
48 #include "llvm/TargetParser/RISCVTargetParserDef.inc"
49 return RISCVCPUInfo[static_cast<unsigned>(Kind)].is64Bit() == IsRV64;
50 }
51
parseCPUKind(StringRef CPU)52 CPUKind parseCPUKind(StringRef CPU) {
53 return llvm::StringSwitch<CPUKind>(CPU)
54 #define PROC(ENUM, NAME, DEFAULT_MARCH) .Case(NAME, CK_##ENUM)
55 #include "llvm/TargetParser/RISCVTargetParserDef.inc"
56 .Default(CK_INVALID);
57 }
58
parseTuneCPUKind(StringRef TuneCPU,bool IsRV64)59 CPUKind parseTuneCPUKind(StringRef TuneCPU, bool IsRV64) {
60 return llvm::StringSwitch<CPUKind>(TuneCPU)
61 #define PROC(ENUM, NAME, DEFAULT_MARCH) .Case(NAME, CK_##ENUM)
62 #define TUNE_PROC(ENUM, NAME) .Case(NAME, CK_##ENUM)
63 #include "llvm/TargetParser/RISCVTargetParserDef.inc"
64 .Default(CK_INVALID);
65 }
66
getMArchFromMcpu(StringRef CPU)67 StringRef getMArchFromMcpu(StringRef CPU) {
68 CPUKind Kind = parseCPUKind(CPU);
69 return RISCVCPUInfo[static_cast<unsigned>(Kind)].DefaultMarch;
70 }
71
fillValidCPUArchList(SmallVectorImpl<StringRef> & Values,bool IsRV64)72 void fillValidCPUArchList(SmallVectorImpl<StringRef> &Values, bool IsRV64) {
73 for (const auto &C : RISCVCPUInfo) {
74 if (C.Kind != CK_INVALID && IsRV64 == C.is64Bit())
75 Values.emplace_back(C.Name);
76 }
77 }
78
fillValidTuneCPUArchList(SmallVectorImpl<StringRef> & Values,bool IsRV64)79 void fillValidTuneCPUArchList(SmallVectorImpl<StringRef> &Values, bool IsRV64) {
80 for (const auto &C : RISCVCPUInfo) {
81 if (C.Kind != CK_INVALID && IsRV64 == C.is64Bit())
82 Values.emplace_back(C.Name);
83 }
84 #define TUNE_PROC(ENUM, NAME) Values.emplace_back(StringRef(NAME));
85 #include "llvm/TargetParser/RISCVTargetParserDef.inc"
86 }
87
88 // Get all features except standard extension feature
getCPUFeaturesExceptStdExt(CPUKind Kind,std::vector<StringRef> & Features)89 bool getCPUFeaturesExceptStdExt(CPUKind Kind,
90 std::vector<StringRef> &Features) {
91 const CPUInfo &Info = RISCVCPUInfo[static_cast<unsigned>(Kind)];
92
93 if (Info.isInvalid())
94 return false;
95
96 if (Info.is64Bit())
97 Features.push_back("+64bit");
98 else
99 Features.push_back("-64bit");
100
101 return true;
102 }
103
isX18ReservedByDefault(const Triple & TT)104 bool isX18ReservedByDefault(const Triple &TT) {
105 // X18 is reserved for the ShadowCallStack ABI (even when not enabled).
106 return TT.isOSFuchsia();
107 }
108
109 } // namespace RISCV
110 } // namespace llvm
111