Path: blob/main/contrib/llvm-project/clang/lib/Basic/Targets/LoongArch.cpp
35269 views
//===--- LoongArch.cpp - Implement LoongArch target feature support -------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file implements LoongArch TargetInfo objects.9//10//===----------------------------------------------------------------------===//1112#include "LoongArch.h"13#include "clang/Basic/Diagnostic.h"14#include "clang/Basic/MacroBuilder.h"15#include "clang/Basic/TargetBuiltins.h"16#include "llvm/Support/raw_ostream.h"17#include "llvm/TargetParser/LoongArchTargetParser.h"1819using namespace clang;20using namespace clang::targets;2122ArrayRef<const char *> LoongArchTargetInfo::getGCCRegNames() const {23static const char *const GCCRegNames[] = {24// General purpose registers.25"$r0", "$r1", "$r2", "$r3", "$r4", "$r5", "$r6", "$r7", "$r8", "$r9",26"$r10", "$r11", "$r12", "$r13", "$r14", "$r15", "$r16", "$r17", "$r18",27"$r19", "$r20", "$r21", "$r22", "$r23", "$r24", "$r25", "$r26", "$r27",28"$r28", "$r29", "$r30", "$r31",29// Floating point registers.30"$f0", "$f1", "$f2", "$f3", "$f4", "$f5", "$f6", "$f7", "$f8", "$f9",31"$f10", "$f11", "$f12", "$f13", "$f14", "$f15", "$f16", "$f17", "$f18",32"$f19", "$f20", "$f21", "$f22", "$f23", "$f24", "$f25", "$f26", "$f27",33"$f28", "$f29", "$f30", "$f31",34// Condition flag registers.35"$fcc0", "$fcc1", "$fcc2", "$fcc3", "$fcc4", "$fcc5", "$fcc6", "$fcc7",36// 128-bit vector registers.37"$vr0", "$vr1", "$vr2", "$vr3", "$vr4", "$vr5", "$vr6", "$vr7", "$vr8",38"$vr9", "$vr10", "$vr11", "$vr12", "$vr13", "$vr14", "$vr15", "$vr16",39"$vr17", "$vr18", "$vr19", "$vr20", "$vr21", "$vr22", "$vr23", "$vr24",40"$vr25", "$vr26", "$vr27", "$vr28", "$vr29", "$vr30", "$vr31",41// 256-bit vector registers.42"$xr0", "$xr1", "$xr2", "$xr3", "$xr4", "$xr5", "$xr6", "$xr7", "$xr8",43"$xr9", "$xr10", "$xr11", "$xr12", "$xr13", "$xr14", "$xr15", "$xr16",44"$xr17", "$xr18", "$xr19", "$xr20", "$xr21", "$xr22", "$xr23", "$xr24",45"$xr25", "$xr26", "$xr27", "$xr28", "$xr29", "$xr30", "$xr31"};46return llvm::ArrayRef(GCCRegNames);47}4849ArrayRef<TargetInfo::GCCRegAlias>50LoongArchTargetInfo::getGCCRegAliases() const {51static const TargetInfo::GCCRegAlias GCCRegAliases[] = {52{{"zero", "$zero", "r0"}, "$r0"},53{{"ra", "$ra", "r1"}, "$r1"},54{{"tp", "$tp", "r2"}, "$r2"},55{{"sp", "$sp", "r3"}, "$r3"},56{{"a0", "$a0", "r4"}, "$r4"},57{{"a1", "$a1", "r5"}, "$r5"},58{{"a2", "$a2", "r6"}, "$r6"},59{{"a3", "$a3", "r7"}, "$r7"},60{{"a4", "$a4", "r8"}, "$r8"},61{{"a5", "$a5", "r9"}, "$r9"},62{{"a6", "$a6", "r10"}, "$r10"},63{{"a7", "$a7", "r11"}, "$r11"},64{{"t0", "$t0", "r12"}, "$r12"},65{{"t1", "$t1", "r13"}, "$r13"},66{{"t2", "$t2", "r14"}, "$r14"},67{{"t3", "$t3", "r15"}, "$r15"},68{{"t4", "$t4", "r16"}, "$r16"},69{{"t5", "$t5", "r17"}, "$r17"},70{{"t6", "$t6", "r18"}, "$r18"},71{{"t7", "$t7", "r19"}, "$r19"},72{{"t8", "$t8", "r20"}, "$r20"},73{{"r21"}, "$r21"},74{{"s9", "$s9", "r22", "fp", "$fp"}, "$r22"},75{{"s0", "$s0", "r23"}, "$r23"},76{{"s1", "$s1", "r24"}, "$r24"},77{{"s2", "$s2", "r25"}, "$r25"},78{{"s3", "$s3", "r26"}, "$r26"},79{{"s4", "$s4", "r27"}, "$r27"},80{{"s5", "$s5", "r28"}, "$r28"},81{{"s6", "$s6", "r29"}, "$r29"},82{{"s7", "$s7", "r30"}, "$r30"},83{{"s8", "$s8", "r31"}, "$r31"},84{{"$fa0"}, "$f0"},85{{"$fa1"}, "$f1"},86{{"$fa2"}, "$f2"},87{{"$fa3"}, "$f3"},88{{"$fa4"}, "$f4"},89{{"$fa5"}, "$f5"},90{{"$fa6"}, "$f6"},91{{"$fa7"}, "$f7"},92{{"$ft0"}, "$f8"},93{{"$ft1"}, "$f9"},94{{"$ft2"}, "$f10"},95{{"$ft3"}, "$f11"},96{{"$ft4"}, "$f12"},97{{"$ft5"}, "$f13"},98{{"$ft6"}, "$f14"},99{{"$ft7"}, "$f15"},100{{"$ft8"}, "$f16"},101{{"$ft9"}, "$f17"},102{{"$ft10"}, "$f18"},103{{"$ft11"}, "$f19"},104{{"$ft12"}, "$f20"},105{{"$ft13"}, "$f21"},106{{"$ft14"}, "$f22"},107{{"$ft15"}, "$f23"},108{{"$fs0"}, "$f24"},109{{"$fs1"}, "$f25"},110{{"$fs2"}, "$f26"},111{{"$fs3"}, "$f27"},112{{"$fs4"}, "$f28"},113{{"$fs5"}, "$f29"},114{{"$fs6"}, "$f30"},115{{"$fs7"}, "$f31"},116};117return llvm::ArrayRef(GCCRegAliases);118}119120bool LoongArchTargetInfo::validateAsmConstraint(121const char *&Name, TargetInfo::ConstraintInfo &Info) const {122// See the GCC definitions here:123// https://gcc.gnu.org/onlinedocs/gccint/Machine-Constraints.html124// Note that the 'm' constraint is handled in TargetInfo.125switch (*Name) {126default:127return false;128case 'f':129// A floating-point register (if available).130Info.setAllowsRegister();131return true;132case 'k':133// A memory operand whose address is formed by a base register and134// (optionally scaled) index register.135Info.setAllowsMemory();136return true;137case 'l':138// A signed 16-bit constant.139Info.setRequiresImmediate(-32768, 32767);140return true;141case 'I':142// A signed 12-bit constant (for arithmetic instructions).143Info.setRequiresImmediate(-2048, 2047);144return true;145case 'J':146// Integer zero.147Info.setRequiresImmediate(0);148return true;149case 'K':150// An unsigned 12-bit constant (for logic instructions).151Info.setRequiresImmediate(0, 4095);152return true;153case 'Z':154// ZB: An address that is held in a general-purpose register. The offset is155// zero.156// ZC: A memory operand whose address is formed by a base register157// and offset that is suitable for use in instructions with the same158// addressing mode as ll.w and sc.w.159if (Name[1] == 'C' || Name[1] == 'B') {160Info.setAllowsMemory();161++Name; // Skip over 'Z'.162return true;163}164return false;165}166}167168std::string169LoongArchTargetInfo::convertConstraint(const char *&Constraint) const {170std::string R;171switch (*Constraint) {172case 'Z':173// "ZC"/"ZB" are two-character constraints; add "^" hint for later174// parsing.175R = "^" + std::string(Constraint, 2);176++Constraint;177break;178default:179R = TargetInfo::convertConstraint(Constraint);180break;181}182return R;183}184185void LoongArchTargetInfo::getTargetDefines(const LangOptions &Opts,186MacroBuilder &Builder) const {187Builder.defineMacro("__loongarch__");188unsigned GRLen = getRegisterWidth();189Builder.defineMacro("__loongarch_grlen", Twine(GRLen));190if (GRLen == 64)191Builder.defineMacro("__loongarch64");192193if (HasFeatureD)194Builder.defineMacro("__loongarch_frlen", "64");195else if (HasFeatureF)196Builder.defineMacro("__loongarch_frlen", "32");197else198Builder.defineMacro("__loongarch_frlen", "0");199200// Define __loongarch_arch.201StringRef ArchName = getCPU();202if (ArchName == "loongarch64") {203if (HasFeatureLSX) {204// TODO: As more features of the V1.1 ISA are supported, a unified "v1.1"205// arch feature set will be used to include all sub-features belonging to206// the V1.1 ISA version.207if (HasFeatureFrecipe)208Builder.defineMacro("__loongarch_arch",209Twine('"') + "la64v1.1" + Twine('"'));210else211Builder.defineMacro("__loongarch_arch",212Twine('"') + "la64v1.0" + Twine('"'));213} else {214Builder.defineMacro("__loongarch_arch",215Twine('"') + ArchName + Twine('"'));216}217} else {218Builder.defineMacro("__loongarch_arch", Twine('"') + ArchName + Twine('"'));219}220221// Define __loongarch_tune.222StringRef TuneCPU = getTargetOpts().TuneCPU;223if (TuneCPU.empty())224TuneCPU = ArchName;225Builder.defineMacro("__loongarch_tune", Twine('"') + TuneCPU + Twine('"'));226227if (HasFeatureLASX) {228Builder.defineMacro("__loongarch_simd_width", "256");229Builder.defineMacro("__loongarch_sx", Twine(1));230Builder.defineMacro("__loongarch_asx", Twine(1));231} else if (HasFeatureLSX) {232Builder.defineMacro("__loongarch_simd_width", "128");233Builder.defineMacro("__loongarch_sx", Twine(1));234}235if (HasFeatureFrecipe)236Builder.defineMacro("__loongarch_frecipe", Twine(1));237238StringRef ABI = getABI();239if (ABI == "lp64d" || ABI == "lp64f" || ABI == "lp64s")240Builder.defineMacro("__loongarch_lp64");241242if (ABI == "lp64d" || ABI == "ilp32d") {243Builder.defineMacro("__loongarch_hard_float");244Builder.defineMacro("__loongarch_double_float");245} else if (ABI == "lp64f" || ABI == "ilp32f") {246Builder.defineMacro("__loongarch_hard_float");247Builder.defineMacro("__loongarch_single_float");248} else if (ABI == "lp64s" || ABI == "ilp32s") {249Builder.defineMacro("__loongarch_soft_float");250}251252Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");253Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");254Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");255if (GRLen == 64)256Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");257}258259static constexpr Builtin::Info BuiltinInfo[] = {260#define BUILTIN(ID, TYPE, ATTRS) \261{#ID, TYPE, ATTRS, nullptr, HeaderDesc::NO_HEADER, ALL_LANGUAGES},262#define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \263{#ID, TYPE, ATTRS, FEATURE, HeaderDesc::NO_HEADER, ALL_LANGUAGES},264#include "clang/Basic/BuiltinsLoongArch.def"265};266267bool LoongArchTargetInfo::initFeatureMap(268llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU,269const std::vector<std::string> &FeaturesVec) const {270if (getTriple().getArch() == llvm::Triple::loongarch64)271Features["64bit"] = true;272if (getTriple().getArch() == llvm::Triple::loongarch32)273Features["32bit"] = true;274275return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec);276}277278/// Return true if has this feature.279bool LoongArchTargetInfo::hasFeature(StringRef Feature) const {280bool Is64Bit = getTriple().getArch() == llvm::Triple::loongarch64;281// TODO: Handle more features.282return llvm::StringSwitch<bool>(Feature)283.Case("loongarch32", !Is64Bit)284.Case("loongarch64", Is64Bit)285.Case("32bit", !Is64Bit)286.Case("64bit", Is64Bit)287.Case("lsx", HasFeatureLSX)288.Case("lasx", HasFeatureLASX)289.Default(false);290}291292ArrayRef<Builtin::Info> LoongArchTargetInfo::getTargetBuiltins() const {293return llvm::ArrayRef(BuiltinInfo, clang::LoongArch::LastTSBuiltin -294Builtin::FirstTSBuiltin);295}296297bool LoongArchTargetInfo::handleTargetFeatures(298std::vector<std::string> &Features, DiagnosticsEngine &Diags) {299for (const auto &Feature : Features) {300if (Feature == "+d" || Feature == "+f") {301// "d" implies "f".302HasFeatureF = true;303if (Feature == "+d") {304HasFeatureD = true;305}306} else if (Feature == "+lsx")307HasFeatureLSX = true;308else if (Feature == "+lasx")309HasFeatureLASX = true;310else if (Feature == "-ual")311HasUnalignedAccess = false;312else if (Feature == "+frecipe")313HasFeatureFrecipe = true;314}315return true;316}317318bool LoongArchTargetInfo::isValidCPUName(StringRef Name) const {319return llvm::LoongArch::isValidCPUName(Name);320}321322void LoongArchTargetInfo::fillValidCPUList(323SmallVectorImpl<StringRef> &Values) const {324llvm::LoongArch::fillValidCPUList(Values);325}326327328