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