196 lines · cpp
1//= LoongArchBaseInfo.cpp - Top level definitions for LoongArch MC -*- 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 implements helper functions for the LoongArch target useful for the10// compiler back-end and the MC libraries.11//12//===----------------------------------------------------------------------===//13 14#include "LoongArchBaseInfo.h"15#include "LoongArchMCTargetDesc.h"16#include "llvm/Support/ErrorHandling.h"17#include "llvm/Support/raw_ostream.h"18#include "llvm/TargetParser/Triple.h"19 20namespace llvm {21 22namespace LoongArchABI {23 24// Check if ABI has been standardized; issue a warning if it hasn't.25// FIXME: Once all ABIs are standardized, this will be removed.26static ABI checkABIStandardized(ABI Abi) {27 StringRef ABIName;28 switch (Abi) {29 case ABI_ILP32S:30 ABIName = "ilp32s";31 break;32 case ABI_ILP32F:33 ABIName = "ilp32f";34 break;35 case ABI_ILP32D:36 ABIName = "ilp32d";37 break;38 case ABI_LP64F:39 ABIName = "lp64f";40 break;41 case ABI_LP64S:42 case ABI_LP64D:43 return Abi;44 default:45 llvm_unreachable("");46 }47 errs() << "warning: '" << ABIName << "' has not been standardized\n";48 return Abi;49}50 51static ABI getTripleABI(const Triple &TT) {52 bool Is64Bit = TT.isArch64Bit();53 ABI TripleABI;54 switch (TT.getEnvironment()) {55 case llvm::Triple::EnvironmentType::UnknownEnvironment:56 TripleABI = ABI_Unknown;57 break;58 case llvm::Triple::EnvironmentType::GNUSF:59 case llvm::Triple::EnvironmentType::MuslSF:60 TripleABI = Is64Bit ? ABI_LP64S : ABI_ILP32S;61 break;62 case llvm::Triple::EnvironmentType::GNUF32:63 case llvm::Triple::EnvironmentType::MuslF32:64 TripleABI = Is64Bit ? ABI_LP64F : ABI_ILP32F;65 break;66 // Let the fallback case behave like {ILP32,LP64}D.67 case llvm::Triple::EnvironmentType::GNUF64:68 default:69 TripleABI = Is64Bit ? ABI_LP64D : ABI_ILP32D;70 break;71 }72 return TripleABI;73}74 75ABI computeTargetABI(const Triple &TT, const FeatureBitset &FeatureBits,76 StringRef ABIName) {77 bool Is64Bit = TT.isArch64Bit();78 ABI ArgProvidedABI = getTargetABI(ABIName);79 ABI TripleABI = getTripleABI(TT);80 81 auto IsABIValidForFeature = [=](ABI Abi) {82 switch (Abi) {83 default:84 return false;85 case ABI_ILP32S:86 return !Is64Bit;87 case ABI_ILP32F:88 return !Is64Bit && FeatureBits[LoongArch::FeatureBasicF];89 case ABI_ILP32D:90 return !Is64Bit && FeatureBits[LoongArch::FeatureBasicD];91 case ABI_LP64S:92 return Is64Bit;93 case ABI_LP64F:94 return Is64Bit && FeatureBits[LoongArch::FeatureBasicF];95 case ABI_LP64D:96 return Is64Bit && FeatureBits[LoongArch::FeatureBasicD];97 }98 };99 100 // 1. If the '-target-abi' is valid, use it.101 if (IsABIValidForFeature(ArgProvidedABI)) {102 if (IsABIValidForFeature(TripleABI) && ArgProvidedABI != TripleABI)103 errs()104 << "warning: triple-implied ABI conflicts with provided target-abi '"105 << ABIName << "', using target-abi\n";106 return checkABIStandardized(ArgProvidedABI);107 }108 109 // 2. If the triple-implied ABI is valid, use it.110 if (IsABIValidForFeature(TripleABI)) {111 // If target-abi is not specified, use the valid triple-implied ABI.112 if (ABIName.empty())113 return checkABIStandardized(TripleABI);114 115 switch (ArgProvidedABI) {116 case ABI_Unknown:117 // Fallback to the triple-implied ABI if ABI name is specified but118 // invalid.119 errs() << "warning: the '" << ABIName120 << "' is not a recognized ABI for this target, ignoring and "121 "using triple-implied ABI\n";122 return checkABIStandardized(TripleABI);123 case ABI_ILP32S:124 case ABI_ILP32F:125 case ABI_ILP32D:126 if (Is64Bit) {127 errs() << "warning: 32-bit ABIs are not supported for 64-bit targets, "128 "ignoring and using triple-implied ABI\n";129 return checkABIStandardized(TripleABI);130 }131 break;132 case ABI_LP64S:133 case ABI_LP64F:134 case ABI_LP64D:135 if (!Is64Bit) {136 errs() << "warning: 64-bit ABIs are not supported for 32-bit targets, "137 "ignoring and using triple-implied ABI\n";138 return checkABIStandardized(TripleABI);139 }140 break;141 }142 143 switch (ArgProvidedABI) {144 case ABI_ILP32F:145 case ABI_LP64F:146 errs() << "warning: the '" << ABIName147 << "' ABI can't be used for a target that doesn't support the 'F' "148 "instruction set, ignoring and using triple-implied ABI\n";149 break;150 case ABI_ILP32D:151 case ABI_LP64D:152 errs() << "warning: the '" << ABIName153 << "' ABI can't be used for a target that doesn't support the 'D' "154 "instruction set, ignoring and using triple-implied ABI\n";155 break;156 default:157 llvm_unreachable("");158 }159 return checkABIStandardized(TripleABI);160 }161 162 // 3. Parse the 'feature-abi', and use it.163 auto GetFeatureABI = [=]() {164 if (FeatureBits[LoongArch::FeatureBasicD])165 return Is64Bit ? ABI_LP64D : ABI_ILP32D;166 if (FeatureBits[LoongArch::FeatureBasicF])167 return Is64Bit ? ABI_LP64F : ABI_ILP32F;168 return Is64Bit ? ABI_LP64S : ABI_ILP32S;169 };170 if (!ABIName.empty())171 errs() << "warning: both target-abi and the triple-implied ABI are "172 "invalid, ignoring and using feature-implied ABI\n";173 return checkABIStandardized(GetFeatureABI());174}175 176ABI getTargetABI(StringRef ABIName) {177 auto TargetABI = StringSwitch<ABI>(ABIName)178 .Case("ilp32s", ABI_ILP32S)179 .Case("ilp32f", ABI_ILP32F)180 .Case("ilp32d", ABI_ILP32D)181 .Case("lp64s", ABI_LP64S)182 .Case("lp64f", ABI_LP64F)183 .Case("lp64d", ABI_LP64D)184 .Default(ABI_Unknown);185 return TargetABI;186}187 188// To avoid the BP value clobbered by a function call, we need to choose a189// callee saved register to save the value. The `last` `S` register (s9) is190// used for FP. So we choose the previous (s8) as BP.191MCRegister getBPReg() { return LoongArch::R31; }192 193} // end namespace LoongArchABI194 195} // end namespace llvm196