xref: /freebsd/contrib/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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.
checkABIStandardized(ABI Abi)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 
getTripleABI(const Triple & TT)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 
computeTargetABI(const Triple & TT,const FeatureBitset & FeatureBits,StringRef ABIName)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 
getTargetABI(StringRef ABIName)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.
getBPReg()191 MCRegister getBPReg() { return LoongArch::R31; }
192 
193 } // end namespace LoongArchABI
194 
195 } // end namespace llvm
196