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/ADT/ArrayRef.h" 17 #include "llvm/MC/MCSubtargetInfo.h" 18 #include "llvm/Support/ErrorHandling.h" 19 #include "llvm/Support/raw_ostream.h" 20 #include "llvm/TargetParser/Triple.h" 21 22 namespace llvm { 23 24 namespace LoongArchABI { 25 26 // Check if ABI has been standardized; issue a warning if it hasn't. 27 // FIXME: Once all ABIs are standardized, this will be removed. 28 static ABI checkABIStandardized(ABI Abi) { 29 StringRef ABIName; 30 switch (Abi) { 31 case ABI_ILP32S: 32 ABIName = "ilp32s"; 33 break; 34 case ABI_ILP32F: 35 ABIName = "ilp32f"; 36 break; 37 case ABI_ILP32D: 38 ABIName = "ilp32d"; 39 break; 40 case ABI_LP64F: 41 ABIName = "lp64f"; 42 break; 43 case ABI_LP64S: 44 case ABI_LP64D: 45 return Abi; 46 default: 47 llvm_unreachable(""); 48 } 49 errs() << "warning: '" << ABIName << "' has not been standardized\n"; 50 return Abi; 51 } 52 53 static ABI getTripleABI(const Triple &TT) { 54 bool Is64Bit = TT.isArch64Bit(); 55 ABI TripleABI; 56 switch (TT.getEnvironment()) { 57 case llvm::Triple::EnvironmentType::GNUSF: 58 TripleABI = Is64Bit ? ABI_LP64S : ABI_ILP32S; 59 break; 60 case llvm::Triple::EnvironmentType::GNUF32: 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