xref: /freebsd/contrib/llvm-project/llvm/utils/TableGen/Common/CodeGenTarget.cpp (revision 770cf0a5f02dc8983a89c6568d741fbc25baa999)
1 //===- CodeGenTarget.cpp - CodeGen Target Class Wrapper -------------------===//
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 class wraps target description classes used by the various code
10 // generation TableGen backends.  This makes it easier to access the data and
11 // provides a single place that needs to check it for validity.  All of these
12 // classes abort on error conditions.
13 //
14 //===----------------------------------------------------------------------===//
15 
16 #include "CodeGenTarget.h"
17 #include "CodeGenInstruction.h"
18 #include "CodeGenRegisters.h"
19 #include "CodeGenSchedule.h"
20 #include "llvm/ADT/STLExtras.h"
21 #include "llvm/ADT/Twine.h"
22 #include "llvm/Support/CommandLine.h"
23 #include "llvm/Support/ErrorHandling.h"
24 #include "llvm/TableGen/Error.h"
25 #include "llvm/TableGen/Record.h"
26 #include <iterator>
27 #include <tuple>
28 using namespace llvm;
29 
30 static cl::OptionCategory AsmParserCat("Options for -gen-asm-parser");
31 static cl::OptionCategory AsmWriterCat("Options for -gen-asm-writer");
32 
33 static cl::opt<unsigned>
34     AsmParserNum("asmparsernum", cl::init(0),
35                  cl::desc("Make -gen-asm-parser emit assembly parser #N"),
36                  cl::cat(AsmParserCat));
37 
38 static cl::opt<unsigned>
39     AsmWriterNum("asmwriternum", cl::init(0),
40                  cl::desc("Make -gen-asm-writer emit assembly writer #N"),
41                  cl::cat(AsmWriterCat));
42 
43 /// getValueType - Return the MVT::SimpleValueType that the specified TableGen
44 /// record corresponds to.
45 MVT::SimpleValueType llvm::getValueType(const Record *Rec) {
46   return (MVT::SimpleValueType)Rec->getValueAsInt("Value");
47 }
48 
49 StringRef llvm::getEnumName(MVT::SimpleValueType T) {
50   // clang-format off
51   switch (T) {
52 #define GET_VT_ATTR(Ty, N, Sz, Any, Int, FP, Vec, Sc, Tup, NF, NElem, EltTy)   \
53   case MVT::Ty: return "MVT::" # Ty;
54 #include "llvm/CodeGen/GenVT.inc"
55   default: llvm_unreachable("ILLEGAL VALUE TYPE!");
56   }
57   // clang-format on
58 }
59 
60 /// getQualifiedName - Return the name of the specified record, with a
61 /// namespace qualifier if the record contains one.
62 ///
63 std::string llvm::getQualifiedName(const Record *R) {
64   std::string Namespace;
65   if (R->getValue("Namespace"))
66     Namespace = R->getValueAsString("Namespace").str();
67   if (Namespace.empty())
68     return R->getName().str();
69   return Namespace + "::" + R->getName().str();
70 }
71 
72 CodeGenTarget::CodeGenTarget(const RecordKeeper &records)
73     : Records(records), CGH(records), Intrinsics(records) {
74   ArrayRef<const Record *> Targets = Records.getAllDerivedDefinitions("Target");
75   if (Targets.size() == 0)
76     PrintFatalError("No 'Target' subclasses defined!");
77   if (Targets.size() != 1)
78     PrintFatalError("Multiple subclasses of Target defined!");
79   TargetRec = Targets[0];
80   MacroFusions = Records.getAllDerivedDefinitions("Fusion");
81 }
82 
83 CodeGenTarget::~CodeGenTarget() {}
84 
85 StringRef CodeGenTarget::getName() const { return TargetRec->getName(); }
86 
87 /// getInstNamespace - Find and return the target machine's instruction
88 /// namespace. The namespace is cached because it is requested multiple times.
89 StringRef CodeGenTarget::getInstNamespace() const {
90   if (InstNamespace.empty()) {
91     for (const CodeGenInstruction *Inst : getInstructions()) {
92       // We are not interested in the "TargetOpcode" namespace.
93       if (Inst->Namespace != "TargetOpcode") {
94         InstNamespace = Inst->Namespace;
95         break;
96       }
97     }
98   }
99 
100   return InstNamespace;
101 }
102 
103 StringRef CodeGenTarget::getRegNamespace() const {
104   auto &RegClasses = RegBank->getRegClasses();
105   return RegClasses.size() > 0 ? RegClasses.front().Namespace : "";
106 }
107 
108 const Record *CodeGenTarget::getInstructionSet() const {
109   return TargetRec->getValueAsDef("InstructionSet");
110 }
111 
112 bool CodeGenTarget::getAllowRegisterRenaming() const {
113   return TargetRec->getValueAsInt("AllowRegisterRenaming");
114 }
115 
116 /// getAsmParser - Return the AssemblyParser definition for this target.
117 ///
118 const Record *CodeGenTarget::getAsmParser() const {
119   std::vector<const Record *> LI =
120       TargetRec->getValueAsListOfDefs("AssemblyParsers");
121   if (AsmParserNum >= LI.size())
122     PrintFatalError("Target does not have an AsmParser #" +
123                     Twine(AsmParserNum) + "!");
124   return LI[AsmParserNum];
125 }
126 
127 /// getAsmParserVariant - Return the AssemblyParserVariant definition for
128 /// this target.
129 ///
130 const Record *CodeGenTarget::getAsmParserVariant(unsigned Idx) const {
131   std::vector<const Record *> LI =
132       TargetRec->getValueAsListOfDefs("AssemblyParserVariants");
133   if (Idx >= LI.size())
134     PrintFatalError("Target does not have an AsmParserVariant #" + Twine(Idx) +
135                     "!");
136   return LI[Idx];
137 }
138 
139 /// getAsmParserVariantCount - Return the AssemblyParserVariant definition
140 /// available for this target.
141 ///
142 unsigned CodeGenTarget::getAsmParserVariantCount() const {
143   return TargetRec->getValueAsListOfDefs("AssemblyParserVariants").size();
144 }
145 
146 /// getAsmWriter - Return the AssemblyWriter definition for this target.
147 ///
148 const Record *CodeGenTarget::getAsmWriter() const {
149   std::vector<const Record *> LI =
150       TargetRec->getValueAsListOfDefs("AssemblyWriters");
151   if (AsmWriterNum >= LI.size())
152     PrintFatalError("Target does not have an AsmWriter #" +
153                     Twine(AsmWriterNum) + "!");
154   return LI[AsmWriterNum];
155 }
156 
157 CodeGenRegBank &CodeGenTarget::getRegBank() const {
158   if (!RegBank)
159     RegBank = std::make_unique<CodeGenRegBank>(Records, getHwModes());
160   return *RegBank;
161 }
162 
163 /// getRegisterByName - If there is a register with the specific AsmName,
164 /// return it.
165 const CodeGenRegister *CodeGenTarget::getRegisterByName(StringRef Name) const {
166   return getRegBank().getRegistersByName().lookup(Name);
167 }
168 
169 const CodeGenRegisterClass &
170 CodeGenTarget::getRegisterClass(const Record *R) const {
171   return *getRegBank().getRegClass(R);
172 }
173 
174 std::vector<ValueTypeByHwMode>
175 CodeGenTarget::getRegisterVTs(const Record *R) const {
176   const CodeGenRegister *Reg = getRegBank().getReg(R);
177   std::vector<ValueTypeByHwMode> Result;
178   for (const auto &RC : getRegBank().getRegClasses()) {
179     if (RC.contains(Reg)) {
180       ArrayRef<ValueTypeByHwMode> InVTs = RC.getValueTypes();
181       llvm::append_range(Result, InVTs);
182     }
183   }
184 
185   // Remove duplicates.
186   llvm::sort(Result);
187   Result.erase(llvm::unique(Result), Result.end());
188   return Result;
189 }
190 
191 void CodeGenTarget::ReadLegalValueTypes() const {
192   for (const auto &RC : getRegBank().getRegClasses())
193     llvm::append_range(LegalValueTypes, RC.VTs);
194 
195   // Remove duplicates.
196   llvm::sort(LegalValueTypes);
197   LegalValueTypes.erase(llvm::unique(LegalValueTypes), LegalValueTypes.end());
198 }
199 
200 CodeGenSchedModels &CodeGenTarget::getSchedModels() const {
201   if (!SchedModels)
202     SchedModels = std::make_unique<CodeGenSchedModels>(Records, *this);
203   return *SchedModels;
204 }
205 
206 void CodeGenTarget::ReadInstructions() const {
207   ArrayRef<const Record *> Insts =
208       Records.getAllDerivedDefinitions("Instruction");
209   if (Insts.size() <= 2)
210     PrintFatalError("No 'Instruction' subclasses defined!");
211 
212   // Parse the instructions defined in the .td file.
213   for (const Record *R : Insts) {
214     auto [II, _] =
215         InstructionMap.try_emplace(R, std::make_unique<CodeGenInstruction>(R));
216     HasVariableLengthEncodings |= II->second->isVariableLengthEncoding();
217   }
218 }
219 
220 static const CodeGenInstruction *GetInstByName(
221     StringRef Name,
222     const DenseMap<const Record *, std::unique_ptr<CodeGenInstruction>> &Insts,
223     const RecordKeeper &Records) {
224   const Record *Rec = Records.getDef(Name);
225 
226   const auto I = Insts.find(Rec);
227   if (!Rec || I == Insts.end())
228     PrintFatalError("Could not find '" + Name + "' instruction!");
229   return I->second.get();
230 }
231 
232 static const char *FixedInstrs[] = {
233 #define HANDLE_TARGET_OPCODE(OPC) #OPC,
234 #include "llvm/Support/TargetOpcodes.def"
235 };
236 
237 unsigned CodeGenTarget::getNumFixedInstructions() {
238   return std::size(FixedInstrs);
239 }
240 
241 /// Return all of the instructions defined by the target, ordered by
242 /// their enum value.
243 void CodeGenTarget::ComputeInstrsByEnum() const {
244   const auto &InstMap = getInstructionMap();
245   for (const char *Name : FixedInstrs) {
246     const CodeGenInstruction *Instr = GetInstByName(Name, InstMap, Records);
247     assert(Instr && "Missing target independent instruction");
248     assert(Instr->Namespace == "TargetOpcode" && "Bad namespace");
249     InstrsByEnum.push_back(Instr);
250   }
251   unsigned EndOfPredefines = InstrsByEnum.size();
252   assert(EndOfPredefines == getNumFixedInstructions() &&
253          "Missing generic opcode");
254 
255   for (const auto &[_, CGIUp] : InstMap) {
256     const CodeGenInstruction *CGI = CGIUp.get();
257     if (CGI->Namespace != "TargetOpcode") {
258       InstrsByEnum.push_back(CGI);
259       NumPseudoInstructions += CGI->TheDef->getValueAsBit("isPseudo");
260     }
261   }
262 
263   assert(InstrsByEnum.size() == InstMap.size() && "Missing predefined instr");
264 
265   // All of the instructions are now in random order based on the map iteration.
266   llvm::sort(
267       InstrsByEnum.begin() + EndOfPredefines, InstrsByEnum.end(),
268       [](const CodeGenInstruction *Rec1, const CodeGenInstruction *Rec2) {
269         const Record &D1 = *Rec1->TheDef;
270         const Record &D2 = *Rec2->TheDef;
271         // Sort all pseudo instructions before non-pseudo ones, and sort by name
272         // within.
273         return std::tuple(!D1.getValueAsBit("isPseudo"), D1.getName()) <
274                std::tuple(!D2.getValueAsBit("isPseudo"), D2.getName());
275       });
276 
277   // Assign an enum value to each instruction according to the sorted order.
278   for (const auto &[Idx, Inst] : enumerate(InstrsByEnum))
279     Inst->EnumVal = Idx;
280 }
281 
282 /// isLittleEndianEncoding - Return whether this target encodes its instruction
283 /// in little-endian format, i.e. bits laid out in the order [0..n]
284 ///
285 bool CodeGenTarget::isLittleEndianEncoding() const {
286   return getInstructionSet()->getValueAsBit("isLittleEndianEncoding");
287 }
288 
289 /// reverseBitsForLittleEndianEncoding - For little-endian instruction bit
290 /// encodings, reverse the bit order of all instructions.
291 void CodeGenTarget::reverseBitsForLittleEndianEncoding() {
292   if (!isLittleEndianEncoding())
293     return;
294 
295   for (const Record *R :
296        Records.getAllDerivedDefinitions("InstructionEncoding")) {
297     if (R->getValueAsString("Namespace") == "TargetOpcode" ||
298         R->getValueAsBit("isPseudo"))
299       continue;
300 
301     const BitsInit *BI = R->getValueAsBitsInit("Inst");
302 
303     unsigned numBits = BI->getNumBits();
304 
305     SmallVector<const Init *, 16> NewBits(numBits);
306 
307     for (unsigned bit = 0, end = numBits / 2; bit != end; ++bit) {
308       unsigned bitSwapIdx = numBits - bit - 1;
309       const Init *OrigBit = BI->getBit(bit);
310       const Init *BitSwap = BI->getBit(bitSwapIdx);
311       NewBits[bit] = BitSwap;
312       NewBits[bitSwapIdx] = OrigBit;
313     }
314     if (numBits % 2) {
315       unsigned middle = (numBits + 1) / 2;
316       NewBits[middle] = BI->getBit(middle);
317     }
318 
319     RecordKeeper &MutableRC = const_cast<RecordKeeper &>(Records);
320     const BitsInit *NewBI = BitsInit::get(MutableRC, NewBits);
321 
322     // Update the bits in reversed order so that emitters will get the correct
323     // endianness.
324     // FIXME: Eliminate mutation of TG records by creating a helper function
325     // to reverse bits and maintain a cache instead of mutating records.
326     Record *MutableR = const_cast<Record *>(R);
327     MutableR->getValue("Inst")->setValue(NewBI);
328   }
329 }
330 
331 /// guessInstructionProperties - Return true if it's OK to guess instruction
332 /// properties instead of raising an error.
333 ///
334 /// This is configurable as a temporary migration aid. It will eventually be
335 /// permanently false.
336 bool CodeGenTarget::guessInstructionProperties() const {
337   return getInstructionSet()->getValueAsBit("guessInstructionProperties");
338 }
339 
340 //===----------------------------------------------------------------------===//
341 // ComplexPattern implementation
342 //
343 ComplexPattern::ComplexPattern(const Record *R) {
344   Ty = R->getValueAsDef("Ty");
345   NumOperands = R->getValueAsInt("NumOperands");
346   SelectFunc = R->getValueAsString("SelectFunc").str();
347   RootNodes = R->getValueAsListOfDefs("RootNodes");
348 
349   // FIXME: This is a hack to statically increase the priority of patterns which
350   // maps a sub-dag to a complex pattern. e.g. favors LEA over ADD. To get best
351   // possible pattern match we'll need to dynamically calculate the complexity
352   // of all patterns a dag can potentially map to.
353   int64_t RawComplexity = R->getValueAsInt("Complexity");
354   if (RawComplexity == -1)
355     Complexity = NumOperands * 3;
356   else
357     Complexity = RawComplexity;
358 
359   // FIXME: Why is this different from parseSDPatternOperatorProperties?
360   // Parse the properties.
361   Properties = 0;
362   for (const Record *Prop : R->getValueAsListOfDefs("Properties")) {
363     if (Prop->getName() == "SDNPHasChain") {
364       Properties |= 1 << SDNPHasChain;
365     } else if (Prop->getName() == "SDNPOptInGlue") {
366       Properties |= 1 << SDNPOptInGlue;
367     } else if (Prop->getName() == "SDNPMayStore") {
368       Properties |= 1 << SDNPMayStore;
369     } else if (Prop->getName() == "SDNPMayLoad") {
370       Properties |= 1 << SDNPMayLoad;
371     } else if (Prop->getName() == "SDNPSideEffect") {
372       Properties |= 1 << SDNPSideEffect;
373     } else if (Prop->getName() == "SDNPMemOperand") {
374       Properties |= 1 << SDNPMemOperand;
375     } else if (Prop->getName() == "SDNPVariadic") {
376       Properties |= 1 << SDNPVariadic;
377     } else {
378       PrintFatalError(R->getLoc(),
379                       "Unsupported SD Node property '" + Prop->getName() +
380                           "' on ComplexPattern '" + R->getName() + "'!");
381     }
382   }
383 
384   WantsRoot = R->getValueAsBit("WantsRoot");
385   WantsParent = R->getValueAsBit("WantsParent");
386 }
387