RISCV.cpp revision 360784
160484Sobrien//===--- RISCV.cpp - Implement RISCV target feature support ---------------===// 278828Sobrien// 360484Sobrien// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 460484Sobrien// See https://llvm.org/LICENSE.txt for license information. 560484Sobrien// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 660484Sobrien// 760484Sobrien//===----------------------------------------------------------------------===// 860484Sobrien// 960484Sobrien// This file implements RISCV TargetInfo objects. 1060484Sobrien// 1160484Sobrien//===----------------------------------------------------------------------===// 1260484Sobrien 1360484Sobrien#include "RISCV.h" 1460484Sobrien#include "clang/Basic/MacroBuilder.h" 1560484Sobrien#include "llvm/ADT/StringSwitch.h" 1660484Sobrien 1760484Sobrienusing namespace clang; 1860484Sobrienusing namespace clang::targets; 1960484Sobrien 2060484SobrienArrayRef<const char *> RISCVTargetInfo::getGCCRegNames() const { 2160484Sobrien static const char *const GCCRegNames[] = { 2260484Sobrien // Integer registers 2360484Sobrien "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", 2460484Sobrien "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", 2560484Sobrien "x16", "x17", "x18", "x19", "x20", "x21", "x22", "x23", 2660484Sobrien "x24", "x25", "x26", "x27", "x28", "x29", "x30", "x31", 2760484Sobrien 2860484Sobrien // Floating point registers 2960484Sobrien "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", 3060484Sobrien "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", 3160484Sobrien "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23", 3260484Sobrien "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31"}; 3360484Sobrien return llvm::makeArrayRef(GCCRegNames); 3460484Sobrien} 3560484Sobrien 3660484SobrienArrayRef<TargetInfo::GCCRegAlias> RISCVTargetInfo::getGCCRegAliases() const { 3760484Sobrien static const TargetInfo::GCCRegAlias GCCRegAliases[] = { 3860484Sobrien {{"zero"}, "x0"}, {{"ra"}, "x1"}, {{"sp"}, "x2"}, {{"gp"}, "x3"}, 3960484Sobrien {{"tp"}, "x4"}, {{"t0"}, "x5"}, {{"t1"}, "x6"}, {{"t2"}, "x7"}, 4060484Sobrien {{"s0"}, "x8"}, {{"s1"}, "x9"}, {{"a0"}, "x10"}, {{"a1"}, "x11"}, 4160484Sobrien {{"a2"}, "x12"}, {{"a3"}, "x13"}, {{"a4"}, "x14"}, {{"a5"}, "x15"}, 4260484Sobrien {{"a6"}, "x16"}, {{"a7"}, "x17"}, {{"s2"}, "x18"}, {{"s3"}, "x19"}, 4360484Sobrien {{"s4"}, "x20"}, {{"s5"}, "x21"}, {{"s6"}, "x22"}, {{"s7"}, "x23"}, 4460484Sobrien {{"s8"}, "x24"}, {{"s9"}, "x25"}, {{"s10"}, "x26"}, {{"s11"}, "x27"}, 4560484Sobrien {{"t3"}, "x28"}, {{"t4"}, "x29"}, {{"t5"}, "x30"}, {{"t6"}, "x31"}, 4660484Sobrien {{"ft0"}, "f0"}, {{"ft1"}, "f1"}, {{"ft2"}, "f2"}, {{"ft3"}, "f3"}, 4760484Sobrien {{"ft4"}, "f4"}, {{"ft5"}, "f5"}, {{"ft6"}, "f6"}, {{"ft7"}, "f7"}, 4860484Sobrien {{"fs0"}, "f8"}, {{"fs1"}, "f9"}, {{"fa0"}, "f10"}, {{"fa1"}, "f11"}, 4960484Sobrien {{"fa2"}, "f12"}, {{"fa3"}, "f13"}, {{"fa4"}, "f14"}, {{"fa5"}, "f15"}, 5060484Sobrien {{"fa6"}, "f16"}, {{"fa7"}, "f17"}, {{"fs2"}, "f18"}, {{"fs3"}, "f19"}, 5160484Sobrien {{"fs4"}, "f20"}, {{"fs5"}, "f21"}, {{"fs6"}, "f22"}, {{"fs7"}, "f23"}, 5260484Sobrien {{"fs8"}, "f24"}, {{"fs9"}, "f25"}, {{"fs10"}, "f26"}, {{"fs11"}, "f27"}, 5360484Sobrien {{"ft8"}, "f28"}, {{"ft9"}, "f29"}, {{"ft10"}, "f30"}, {{"ft11"}, "f31"}}; 5460484Sobrien return llvm::makeArrayRef(GCCRegAliases); 5560484Sobrien} 5660484Sobrien 5760484Sobrienbool RISCVTargetInfo::validateAsmConstraint( 5860484Sobrien const char *&Name, TargetInfo::ConstraintInfo &Info) const { 5960484Sobrien switch (*Name) { 6060484Sobrien default: 6160484Sobrien return false; 6260484Sobrien case 'I': 6360484Sobrien // A 12-bit signed immediate. 6460484Sobrien Info.setRequiresImmediate(-2048, 2047); 6560484Sobrien return true; 6660484Sobrien case 'J': 6760484Sobrien // Integer zero. 6860484Sobrien Info.setRequiresImmediate(0); 6960484Sobrien return true; 7060484Sobrien case 'K': 7160484Sobrien // A 5-bit unsigned immediate for CSR access instructions. 7260484Sobrien Info.setRequiresImmediate(0, 31); 7360484Sobrien return true; 7460484Sobrien case 'f': 7560484Sobrien // A floating-point register. 7660484Sobrien Info.setAllowsRegister(); 7760484Sobrien return true; 7860484Sobrien case 'A': 7960484Sobrien // An address that is held in a general-purpose register. 8060484Sobrien Info.setAllowsMemory(); 8160484Sobrien return true; 8260484Sobrien } 8360484Sobrien} 8460484Sobrien 8560484Sobrienvoid RISCVTargetInfo::getTargetDefines(const LangOptions &Opts, 8660484Sobrien MacroBuilder &Builder) const { 8760484Sobrien Builder.defineMacro("__ELF__"); 8860484Sobrien Builder.defineMacro("__riscv"); 8960484Sobrien bool Is64Bit = getTriple().getArch() == llvm::Triple::riscv64; 9060484Sobrien Builder.defineMacro("__riscv_xlen", Is64Bit ? "64" : "32"); 9160484Sobrien StringRef CodeModel = getTargetOpts().CodeModel; 9260484Sobrien if (CodeModel == "default") 9360484Sobrien CodeModel = "small"; 9460484Sobrien 9560484Sobrien if (CodeModel == "small") 9660484Sobrien Builder.defineMacro("__riscv_cmodel_medlow"); 9760484Sobrien else if (CodeModel == "medium") 9860484Sobrien Builder.defineMacro("__riscv_cmodel_medany"); 9960484Sobrien 10060484Sobrien StringRef ABIName = getABI(); 10160484Sobrien if (ABIName == "ilp32f" || ABIName == "lp64f") 10260484Sobrien Builder.defineMacro("__riscv_float_abi_single"); 10360484Sobrien else if (ABIName == "ilp32d" || ABIName == "lp64d") 10460484Sobrien Builder.defineMacro("__riscv_float_abi_double"); 10560484Sobrien else 10660484Sobrien Builder.defineMacro("__riscv_float_abi_soft"); 10760484Sobrien 10860484Sobrien if (ABIName == "ilp32e") 10960484Sobrien Builder.defineMacro("__riscv_abi_rve"); 11060484Sobrien 11160484Sobrien if (HasM) { 11260484Sobrien Builder.defineMacro("__riscv_mul"); 11360484Sobrien Builder.defineMacro("__riscv_div"); 11460484Sobrien Builder.defineMacro("__riscv_muldiv"); 11560484Sobrien } 11660484Sobrien 11760484Sobrien if (HasA) 11860484Sobrien Builder.defineMacro("__riscv_atomic"); 11960484Sobrien 12060484Sobrien if (HasF || HasD) { 12160484Sobrien Builder.defineMacro("__riscv_flen", HasD ? "64" : "32"); 12260484Sobrien Builder.defineMacro("__riscv_fdiv"); 12360484Sobrien Builder.defineMacro("__riscv_fsqrt"); 12460484Sobrien } 12560484Sobrien 12660484Sobrien if (HasC) 12760484Sobrien Builder.defineMacro("__riscv_compressed"); 12860484Sobrien} 12960484Sobrien 13060484Sobrien/// Return true if has this feature, need to sync with handleTargetFeatures. 13160484Sobrienbool RISCVTargetInfo::hasFeature(StringRef Feature) const { 13260484Sobrien bool Is64Bit = getTriple().getArch() == llvm::Triple::riscv64; 13360484Sobrien return llvm::StringSwitch<bool>(Feature) 13460484Sobrien .Case("riscv", true) 13560484Sobrien .Case("riscv32", !Is64Bit) 13660484Sobrien .Case("riscv64", Is64Bit) 13760484Sobrien .Case("m", HasM) 13860484Sobrien .Case("a", HasA) 13960484Sobrien .Case("f", HasF) 14060484Sobrien .Case("d", HasD) 14160484Sobrien .Case("c", HasC) 14260484Sobrien .Default(false); 14360484Sobrien} 14460484Sobrien 14560484Sobrien/// Perform initialization based on the user configured set of features. 14660484Sobrienbool RISCVTargetInfo::handleTargetFeatures(std::vector<std::string> &Features, 14760484Sobrien DiagnosticsEngine &Diags) { 14860484Sobrien for (const auto &Feature : Features) { 14960484Sobrien if (Feature == "+m") 15060484Sobrien HasM = true; 15160484Sobrien else if (Feature == "+a") 15260484Sobrien HasA = true; 15360484Sobrien else if (Feature == "+f") 15460484Sobrien HasF = true; 15560484Sobrien else if (Feature == "+d") 15660484Sobrien HasD = true; 15760484Sobrien else if (Feature == "+c") 15860484Sobrien HasC = true; 15960484Sobrien } 16060484Sobrien 16160484Sobrien return true; 16260484Sobrien} 16360484Sobrien