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-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file implements helper functions for the LoongArch target useful for the 10 // 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 20 namespace llvm { 21 22 namespace 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. 26 static 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 51 static ABI getTripleABI(const Triple &TT) { 52 bool Is64Bit = TT.isArch64Bit(); 53 ABI TripleABI; 54 switch (TT.getEnvironment()) { 55 case llvm::Triple::EnvironmentType::GNUSF: 56 case llvm::Triple::EnvironmentType::MuslSF: 57 TripleABI = Is64Bit ? ABI_LP64S : ABI_ILP32S; 58 break; 59 case llvm::Triple::EnvironmentType::GNUF32: 60 case llvm::Triple::EnvironmentType::MuslF32: 61 TripleABI = Is64Bit ? ABI_LP64F : ABI_ILP32F; 62 break; 63 // Let the fallback case behave like {ILP32,LP64}D. 64 case llvm::Triple::EnvironmentType::GNUF64: 65 default: 66 TripleABI = Is64Bit ? ABI_LP64D : ABI_ILP32D; 67 break; 68 } 69 return TripleABI; 70 } 71 72 ABI computeTargetABI(const Triple &TT, const FeatureBitset &FeatureBits, 73 StringRef ABIName) { 74 bool Is64Bit = TT.isArch64Bit(); 75 ABI ArgProvidedABI = getTargetABI(ABIName); 76 ABI TripleABI = getTripleABI(TT); 77 78 auto IsABIValidForFeature = [=](ABI Abi) { 79 switch (Abi) { 80 default: 81 return false; 82 case ABI_ILP32S: 83 return !Is64Bit; 84 case ABI_ILP32F: 85 return !Is64Bit && FeatureBits[LoongArch::FeatureBasicF]; 86 case ABI_ILP32D: 87 return !Is64Bit && FeatureBits[LoongArch::FeatureBasicD]; 88 case ABI_LP64S: 89 return Is64Bit; 90 case ABI_LP64F: 91 return Is64Bit && FeatureBits[LoongArch::FeatureBasicF]; 92 case ABI_LP64D: 93 return Is64Bit && FeatureBits[LoongArch::FeatureBasicD]; 94 } 95 }; 96 97 // 1. If the '-target-abi' is valid, use it. 98 if (IsABIValidForFeature(ArgProvidedABI)) { 99 if (TT.hasEnvironment() && ArgProvidedABI != TripleABI) 100 errs() 101 << "warning: triple-implied ABI conflicts with provided target-abi '" 102 << ABIName << "', using target-abi\n"; 103 return checkABIStandardized(ArgProvidedABI); 104 } 105 106 // 2. If the triple-implied ABI is valid, use it. 107 if (IsABIValidForFeature(TripleABI)) { 108 // If target-abi is not specified, use the valid triple-implied ABI. 109 if (ABIName.empty()) 110 return checkABIStandardized(TripleABI); 111 112 switch (ArgProvidedABI) { 113 case ABI_Unknown: 114 // Fallback to the triple-implied ABI if ABI name is specified but 115 // invalid. 116 errs() << "warning: the '" << ABIName 117 << "' is not a recognized ABI for this target, ignoring and " 118 "using triple-implied ABI\n"; 119 return checkABIStandardized(TripleABI); 120 case ABI_ILP32S: 121 case ABI_ILP32F: 122 case ABI_ILP32D: 123 if (Is64Bit) { 124 errs() << "warning: 32-bit ABIs are not supported for 64-bit targets, " 125 "ignoring and using triple-implied ABI\n"; 126 return checkABIStandardized(TripleABI); 127 } 128 break; 129 case ABI_LP64S: 130 case ABI_LP64F: 131 case ABI_LP64D: 132 if (!Is64Bit) { 133 errs() << "warning: 64-bit ABIs are not supported for 32-bit targets, " 134 "ignoring and using triple-implied ABI\n"; 135 return checkABIStandardized(TripleABI); 136 } 137 break; 138 } 139 140 switch (ArgProvidedABI) { 141 case ABI_ILP32F: 142 case ABI_LP64F: 143 errs() << "warning: the '" << ABIName 144 << "' ABI can't be used for a target that doesn't support the 'F' " 145 "instruction set, ignoring and using triple-implied ABI\n"; 146 break; 147 case ABI_ILP32D: 148 case ABI_LP64D: 149 errs() << "warning: the '" << ABIName 150 << "' ABI can't be used for a target that doesn't support the 'D' " 151 "instruction set, ignoring and using triple-implied ABI\n"; 152 break; 153 default: 154 llvm_unreachable(""); 155 } 156 return checkABIStandardized(TripleABI); 157 } 158 159 // 3. Parse the 'feature-abi', and use it. 160 auto GetFeatureABI = [=]() { 161 if (FeatureBits[LoongArch::FeatureBasicD]) 162 return Is64Bit ? ABI_LP64D : ABI_ILP32D; 163 if (FeatureBits[LoongArch::FeatureBasicF]) 164 return Is64Bit ? ABI_LP64F : ABI_ILP32F; 165 return Is64Bit ? ABI_LP64S : ABI_ILP32S; 166 }; 167 if (ABIName.empty()) 168 errs() << "warning: the triple-implied ABI is invalid, ignoring and using " 169 "feature-implied ABI\n"; 170 else 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 176 ABI 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 a 189 // callee saved register to save the value. The `last` `S` register (s9) is 190 // used for FP. So we choose the previous (s8) as BP. 191 MCRegister getBPReg() { return LoongArch::R31; } 192 193 } // end namespace LoongArchABI 194 195 } // end namespace llvm 196