1ac9a064cSDimitry Andric //===- CodeGenTarget.cpp - CodeGen Target Class Wrapper -------------------===//
2ac9a064cSDimitry Andric //
3ac9a064cSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4ac9a064cSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5ac9a064cSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6ac9a064cSDimitry Andric //
7ac9a064cSDimitry Andric //===----------------------------------------------------------------------===//
8ac9a064cSDimitry Andric //
9ac9a064cSDimitry Andric // This class wraps target description classes used by the various code
10ac9a064cSDimitry Andric // generation TableGen backends. This makes it easier to access the data and
11ac9a064cSDimitry Andric // provides a single place that needs to check it for validity. All of these
12ac9a064cSDimitry Andric // classes abort on error conditions.
13ac9a064cSDimitry Andric //
14ac9a064cSDimitry Andric //===----------------------------------------------------------------------===//
15ac9a064cSDimitry Andric
16ac9a064cSDimitry Andric #include "CodeGenTarget.h"
17ac9a064cSDimitry Andric #include "CodeGenInstruction.h"
18ac9a064cSDimitry Andric #include "CodeGenRegisters.h"
19ac9a064cSDimitry Andric #include "CodeGenSchedule.h"
20ac9a064cSDimitry Andric #include "llvm/ADT/STLExtras.h"
21ac9a064cSDimitry Andric #include "llvm/ADT/Twine.h"
22ac9a064cSDimitry Andric #include "llvm/Support/CommandLine.h"
23ac9a064cSDimitry Andric #include "llvm/Support/ErrorHandling.h"
24ac9a064cSDimitry Andric #include "llvm/TableGen/Error.h"
25ac9a064cSDimitry Andric #include "llvm/TableGen/Record.h"
26ac9a064cSDimitry Andric #include <algorithm>
27ac9a064cSDimitry Andric #include <iterator>
28ac9a064cSDimitry Andric #include <tuple>
29ac9a064cSDimitry Andric using namespace llvm;
30ac9a064cSDimitry Andric
31ac9a064cSDimitry Andric cl::OptionCategory AsmParserCat("Options for -gen-asm-parser");
32ac9a064cSDimitry Andric cl::OptionCategory AsmWriterCat("Options for -gen-asm-writer");
33ac9a064cSDimitry Andric
34ac9a064cSDimitry Andric static cl::opt<unsigned>
35ac9a064cSDimitry Andric AsmParserNum("asmparsernum", cl::init(0),
36ac9a064cSDimitry Andric cl::desc("Make -gen-asm-parser emit assembly parser #N"),
37ac9a064cSDimitry Andric cl::cat(AsmParserCat));
38ac9a064cSDimitry Andric
39ac9a064cSDimitry Andric static cl::opt<unsigned>
40ac9a064cSDimitry Andric AsmWriterNum("asmwriternum", cl::init(0),
41ac9a064cSDimitry Andric cl::desc("Make -gen-asm-writer emit assembly writer #N"),
42ac9a064cSDimitry Andric cl::cat(AsmWriterCat));
43ac9a064cSDimitry Andric
44ac9a064cSDimitry Andric /// getValueType - Return the MVT::SimpleValueType that the specified TableGen
45ac9a064cSDimitry Andric /// record corresponds to.
getValueType(const Record * Rec)46ac9a064cSDimitry Andric MVT::SimpleValueType llvm::getValueType(const Record *Rec) {
47ac9a064cSDimitry Andric return (MVT::SimpleValueType)Rec->getValueAsInt("Value");
48ac9a064cSDimitry Andric }
49ac9a064cSDimitry Andric
getName(MVT::SimpleValueType T)50ac9a064cSDimitry Andric StringRef llvm::getName(MVT::SimpleValueType T) {
51ac9a064cSDimitry Andric switch (T) {
52ac9a064cSDimitry Andric case MVT::Other:
53ac9a064cSDimitry Andric return "UNKNOWN";
54ac9a064cSDimitry Andric case MVT::iPTR:
55ac9a064cSDimitry Andric return "TLI.getPointerTy()";
56ac9a064cSDimitry Andric case MVT::iPTRAny:
57ac9a064cSDimitry Andric return "TLI.getPointerTy()";
58ac9a064cSDimitry Andric default:
59ac9a064cSDimitry Andric return getEnumName(T);
60ac9a064cSDimitry Andric }
61ac9a064cSDimitry Andric }
62ac9a064cSDimitry Andric
getEnumName(MVT::SimpleValueType T)63ac9a064cSDimitry Andric StringRef llvm::getEnumName(MVT::SimpleValueType T) {
64ac9a064cSDimitry Andric // clang-format off
65ac9a064cSDimitry Andric switch (T) {
66ac9a064cSDimitry Andric #define GET_VT_ATTR(Ty, N, Sz, Any, Int, FP, Vec, Sc, NElem, EltTy) \
67ac9a064cSDimitry Andric case MVT::Ty: return "MVT::" # Ty;
68ac9a064cSDimitry Andric #include "llvm/CodeGen/GenVT.inc"
69ac9a064cSDimitry Andric default: llvm_unreachable("ILLEGAL VALUE TYPE!");
70ac9a064cSDimitry Andric }
71ac9a064cSDimitry Andric // clang-format on
72ac9a064cSDimitry Andric }
73ac9a064cSDimitry Andric
74ac9a064cSDimitry Andric /// getQualifiedName - Return the name of the specified record, with a
75ac9a064cSDimitry Andric /// namespace qualifier if the record contains one.
76ac9a064cSDimitry Andric ///
getQualifiedName(const Record * R)77ac9a064cSDimitry Andric std::string llvm::getQualifiedName(const Record *R) {
78ac9a064cSDimitry Andric std::string Namespace;
79ac9a064cSDimitry Andric if (R->getValue("Namespace"))
80ac9a064cSDimitry Andric Namespace = std::string(R->getValueAsString("Namespace"));
81ac9a064cSDimitry Andric if (Namespace.empty())
82ac9a064cSDimitry Andric return std::string(R->getName());
83ac9a064cSDimitry Andric return Namespace + "::" + R->getName().str();
84ac9a064cSDimitry Andric }
85ac9a064cSDimitry Andric
86ac9a064cSDimitry Andric /// getTarget - Return the current instance of the Target class.
87ac9a064cSDimitry Andric ///
CodeGenTarget(RecordKeeper & records)88ac9a064cSDimitry Andric CodeGenTarget::CodeGenTarget(RecordKeeper &records)
89ac9a064cSDimitry Andric : Records(records), CGH(records) {
90ac9a064cSDimitry Andric std::vector<Record *> Targets = Records.getAllDerivedDefinitions("Target");
91ac9a064cSDimitry Andric if (Targets.size() == 0)
92ac9a064cSDimitry Andric PrintFatalError("No 'Target' subclasses defined!");
93ac9a064cSDimitry Andric if (Targets.size() != 1)
94ac9a064cSDimitry Andric PrintFatalError("Multiple subclasses of Target defined!");
95ac9a064cSDimitry Andric TargetRec = Targets[0];
96ac9a064cSDimitry Andric MacroFusions = Records.getAllDerivedDefinitions("Fusion");
97ac9a064cSDimitry Andric }
98ac9a064cSDimitry Andric
~CodeGenTarget()99ac9a064cSDimitry Andric CodeGenTarget::~CodeGenTarget() {}
100ac9a064cSDimitry Andric
getName() const101ac9a064cSDimitry Andric StringRef CodeGenTarget::getName() const { return TargetRec->getName(); }
102ac9a064cSDimitry Andric
103ac9a064cSDimitry Andric /// getInstNamespace - Find and return the target machine's instruction
104ac9a064cSDimitry Andric /// namespace. The namespace is cached because it is requested multiple times.
getInstNamespace() const105ac9a064cSDimitry Andric StringRef CodeGenTarget::getInstNamespace() const {
106ac9a064cSDimitry Andric if (InstNamespace.empty()) {
107ac9a064cSDimitry Andric for (const CodeGenInstruction *Inst : getInstructionsByEnumValue()) {
108ac9a064cSDimitry Andric // We are not interested in the "TargetOpcode" namespace.
109ac9a064cSDimitry Andric if (Inst->Namespace != "TargetOpcode") {
110ac9a064cSDimitry Andric InstNamespace = Inst->Namespace;
111ac9a064cSDimitry Andric break;
112ac9a064cSDimitry Andric }
113ac9a064cSDimitry Andric }
114ac9a064cSDimitry Andric }
115ac9a064cSDimitry Andric
116ac9a064cSDimitry Andric return InstNamespace;
117ac9a064cSDimitry Andric }
118ac9a064cSDimitry Andric
getRegNamespace() const119ac9a064cSDimitry Andric StringRef CodeGenTarget::getRegNamespace() const {
120ac9a064cSDimitry Andric auto &RegClasses = RegBank->getRegClasses();
121ac9a064cSDimitry Andric return RegClasses.size() > 0 ? RegClasses.front().Namespace : "";
122ac9a064cSDimitry Andric }
123ac9a064cSDimitry Andric
getInstructionSet() const124ac9a064cSDimitry Andric Record *CodeGenTarget::getInstructionSet() const {
125ac9a064cSDimitry Andric return TargetRec->getValueAsDef("InstructionSet");
126ac9a064cSDimitry Andric }
127ac9a064cSDimitry Andric
getAllowRegisterRenaming() const128ac9a064cSDimitry Andric bool CodeGenTarget::getAllowRegisterRenaming() const {
129ac9a064cSDimitry Andric return TargetRec->getValueAsInt("AllowRegisterRenaming");
130ac9a064cSDimitry Andric }
131ac9a064cSDimitry Andric
132ac9a064cSDimitry Andric /// getAsmParser - Return the AssemblyParser definition for this target.
133ac9a064cSDimitry Andric ///
getAsmParser() const134ac9a064cSDimitry Andric Record *CodeGenTarget::getAsmParser() const {
135ac9a064cSDimitry Andric std::vector<Record *> LI = TargetRec->getValueAsListOfDefs("AssemblyParsers");
136ac9a064cSDimitry Andric if (AsmParserNum >= LI.size())
137ac9a064cSDimitry Andric PrintFatalError("Target does not have an AsmParser #" +
138ac9a064cSDimitry Andric Twine(AsmParserNum) + "!");
139ac9a064cSDimitry Andric return LI[AsmParserNum];
140ac9a064cSDimitry Andric }
141ac9a064cSDimitry Andric
142ac9a064cSDimitry Andric /// getAsmParserVariant - Return the AssemblyParserVariant definition for
143ac9a064cSDimitry Andric /// this target.
144ac9a064cSDimitry Andric ///
getAsmParserVariant(unsigned i) const145ac9a064cSDimitry Andric Record *CodeGenTarget::getAsmParserVariant(unsigned i) const {
146ac9a064cSDimitry Andric std::vector<Record *> LI =
147ac9a064cSDimitry Andric TargetRec->getValueAsListOfDefs("AssemblyParserVariants");
148ac9a064cSDimitry Andric if (i >= LI.size())
149ac9a064cSDimitry Andric PrintFatalError("Target does not have an AsmParserVariant #" + Twine(i) +
150ac9a064cSDimitry Andric "!");
151ac9a064cSDimitry Andric return LI[i];
152ac9a064cSDimitry Andric }
153ac9a064cSDimitry Andric
154ac9a064cSDimitry Andric /// getAsmParserVariantCount - Return the AssemblyParserVariant definition
155ac9a064cSDimitry Andric /// available for this target.
156ac9a064cSDimitry Andric ///
getAsmParserVariantCount() const157ac9a064cSDimitry Andric unsigned CodeGenTarget::getAsmParserVariantCount() const {
158ac9a064cSDimitry Andric std::vector<Record *> LI =
159ac9a064cSDimitry Andric TargetRec->getValueAsListOfDefs("AssemblyParserVariants");
160ac9a064cSDimitry Andric return LI.size();
161ac9a064cSDimitry Andric }
162ac9a064cSDimitry Andric
163ac9a064cSDimitry Andric /// getAsmWriter - Return the AssemblyWriter definition for this target.
164ac9a064cSDimitry Andric ///
getAsmWriter() const165ac9a064cSDimitry Andric Record *CodeGenTarget::getAsmWriter() const {
166ac9a064cSDimitry Andric std::vector<Record *> LI = TargetRec->getValueAsListOfDefs("AssemblyWriters");
167ac9a064cSDimitry Andric if (AsmWriterNum >= LI.size())
168ac9a064cSDimitry Andric PrintFatalError("Target does not have an AsmWriter #" +
169ac9a064cSDimitry Andric Twine(AsmWriterNum) + "!");
170ac9a064cSDimitry Andric return LI[AsmWriterNum];
171ac9a064cSDimitry Andric }
172ac9a064cSDimitry Andric
getRegBank() const173ac9a064cSDimitry Andric CodeGenRegBank &CodeGenTarget::getRegBank() const {
174ac9a064cSDimitry Andric if (!RegBank)
175ac9a064cSDimitry Andric RegBank = std::make_unique<CodeGenRegBank>(Records, getHwModes());
176ac9a064cSDimitry Andric return *RegBank;
177ac9a064cSDimitry Andric }
178ac9a064cSDimitry Andric
getSuperRegForSubReg(const ValueTypeByHwMode & ValueTy,CodeGenRegBank & RegBank,const CodeGenSubRegIndex * SubIdx,bool MustBeAllocatable) const179ac9a064cSDimitry Andric std::optional<CodeGenRegisterClass *> CodeGenTarget::getSuperRegForSubReg(
180ac9a064cSDimitry Andric const ValueTypeByHwMode &ValueTy, CodeGenRegBank &RegBank,
181ac9a064cSDimitry Andric const CodeGenSubRegIndex *SubIdx, bool MustBeAllocatable) const {
182ac9a064cSDimitry Andric std::vector<CodeGenRegisterClass *> Candidates;
183ac9a064cSDimitry Andric auto &RegClasses = RegBank.getRegClasses();
184ac9a064cSDimitry Andric
185ac9a064cSDimitry Andric // Try to find a register class which supports ValueTy, and also contains
186ac9a064cSDimitry Andric // SubIdx.
187ac9a064cSDimitry Andric for (CodeGenRegisterClass &RC : RegClasses) {
188ac9a064cSDimitry Andric // Is there a subclass of this class which contains this subregister index?
189ac9a064cSDimitry Andric CodeGenRegisterClass *SubClassWithSubReg = RC.getSubClassWithSubReg(SubIdx);
190ac9a064cSDimitry Andric if (!SubClassWithSubReg)
191ac9a064cSDimitry Andric continue;
192ac9a064cSDimitry Andric
193ac9a064cSDimitry Andric // We have a class. Check if it supports this value type.
194ac9a064cSDimitry Andric if (!llvm::is_contained(SubClassWithSubReg->VTs, ValueTy))
195ac9a064cSDimitry Andric continue;
196ac9a064cSDimitry Andric
197ac9a064cSDimitry Andric // If necessary, check that it is allocatable.
198ac9a064cSDimitry Andric if (MustBeAllocatable && !SubClassWithSubReg->Allocatable)
199ac9a064cSDimitry Andric continue;
200ac9a064cSDimitry Andric
201ac9a064cSDimitry Andric // We have a register class which supports both the value type and
202ac9a064cSDimitry Andric // subregister index. Remember it.
203ac9a064cSDimitry Andric Candidates.push_back(SubClassWithSubReg);
204ac9a064cSDimitry Andric }
205ac9a064cSDimitry Andric
206ac9a064cSDimitry Andric // If we didn't find anything, we're done.
207ac9a064cSDimitry Andric if (Candidates.empty())
208ac9a064cSDimitry Andric return std::nullopt;
209ac9a064cSDimitry Andric
210ac9a064cSDimitry Andric // Find and return the largest of our candidate classes.
211ac9a064cSDimitry Andric llvm::stable_sort(Candidates, [&](const CodeGenRegisterClass *A,
212ac9a064cSDimitry Andric const CodeGenRegisterClass *B) {
213ac9a064cSDimitry Andric if (A->getMembers().size() > B->getMembers().size())
214ac9a064cSDimitry Andric return true;
215ac9a064cSDimitry Andric
216ac9a064cSDimitry Andric if (A->getMembers().size() < B->getMembers().size())
217ac9a064cSDimitry Andric return false;
218ac9a064cSDimitry Andric
219ac9a064cSDimitry Andric // Order by name as a tie-breaker.
220ac9a064cSDimitry Andric return StringRef(A->getName()) < B->getName();
221ac9a064cSDimitry Andric });
222ac9a064cSDimitry Andric
223ac9a064cSDimitry Andric return Candidates[0];
224ac9a064cSDimitry Andric }
225ac9a064cSDimitry Andric
ReadRegAltNameIndices() const226ac9a064cSDimitry Andric void CodeGenTarget::ReadRegAltNameIndices() const {
227ac9a064cSDimitry Andric RegAltNameIndices = Records.getAllDerivedDefinitions("RegAltNameIndex");
228ac9a064cSDimitry Andric llvm::sort(RegAltNameIndices, LessRecord());
229ac9a064cSDimitry Andric }
230ac9a064cSDimitry Andric
231ac9a064cSDimitry Andric /// getRegisterByName - If there is a register with the specific AsmName,
232ac9a064cSDimitry Andric /// return it.
getRegisterByName(StringRef Name) const233ac9a064cSDimitry Andric const CodeGenRegister *CodeGenTarget::getRegisterByName(StringRef Name) const {
234ac9a064cSDimitry Andric return getRegBank().getRegistersByName().lookup(Name);
235ac9a064cSDimitry Andric }
236ac9a064cSDimitry Andric
getRegisterClass(Record * R) const237ac9a064cSDimitry Andric const CodeGenRegisterClass &CodeGenTarget::getRegisterClass(Record *R) const {
238ac9a064cSDimitry Andric return *getRegBank().getRegClass(R);
239ac9a064cSDimitry Andric }
240ac9a064cSDimitry Andric
getRegisterVTs(Record * R) const241ac9a064cSDimitry Andric std::vector<ValueTypeByHwMode> CodeGenTarget::getRegisterVTs(Record *R) const {
242ac9a064cSDimitry Andric const CodeGenRegister *Reg = getRegBank().getReg(R);
243ac9a064cSDimitry Andric std::vector<ValueTypeByHwMode> Result;
244ac9a064cSDimitry Andric for (const auto &RC : getRegBank().getRegClasses()) {
245ac9a064cSDimitry Andric if (RC.contains(Reg)) {
246ac9a064cSDimitry Andric ArrayRef<ValueTypeByHwMode> InVTs = RC.getValueTypes();
247ac9a064cSDimitry Andric llvm::append_range(Result, InVTs);
248ac9a064cSDimitry Andric }
249ac9a064cSDimitry Andric }
250ac9a064cSDimitry Andric
251ac9a064cSDimitry Andric // Remove duplicates.
252ac9a064cSDimitry Andric llvm::sort(Result);
253ac9a064cSDimitry Andric Result.erase(llvm::unique(Result), Result.end());
254ac9a064cSDimitry Andric return Result;
255ac9a064cSDimitry Andric }
256ac9a064cSDimitry Andric
ReadLegalValueTypes() const257ac9a064cSDimitry Andric void CodeGenTarget::ReadLegalValueTypes() const {
258ac9a064cSDimitry Andric for (const auto &RC : getRegBank().getRegClasses())
259ac9a064cSDimitry Andric llvm::append_range(LegalValueTypes, RC.VTs);
260ac9a064cSDimitry Andric
261ac9a064cSDimitry Andric // Remove duplicates.
262ac9a064cSDimitry Andric llvm::sort(LegalValueTypes);
263ac9a064cSDimitry Andric LegalValueTypes.erase(llvm::unique(LegalValueTypes), LegalValueTypes.end());
264ac9a064cSDimitry Andric }
265ac9a064cSDimitry Andric
getSchedModels() const266ac9a064cSDimitry Andric CodeGenSchedModels &CodeGenTarget::getSchedModels() const {
267ac9a064cSDimitry Andric if (!SchedModels)
268ac9a064cSDimitry Andric SchedModels = std::make_unique<CodeGenSchedModels>(Records, *this);
269ac9a064cSDimitry Andric return *SchedModels;
270ac9a064cSDimitry Andric }
271ac9a064cSDimitry Andric
ReadInstructions() const272ac9a064cSDimitry Andric void CodeGenTarget::ReadInstructions() const {
273ac9a064cSDimitry Andric std::vector<Record *> Insts = Records.getAllDerivedDefinitions("Instruction");
274ac9a064cSDimitry Andric if (Insts.size() <= 2)
275ac9a064cSDimitry Andric PrintFatalError("No 'Instruction' subclasses defined!");
276ac9a064cSDimitry Andric
277ac9a064cSDimitry Andric // Parse the instructions defined in the .td file.
278ac9a064cSDimitry Andric for (Record *R : Insts) {
279ac9a064cSDimitry Andric Instructions[R] = std::make_unique<CodeGenInstruction>(R);
280ac9a064cSDimitry Andric if (Instructions[R]->isVariableLengthEncoding())
281ac9a064cSDimitry Andric HasVariableLengthEncodings = true;
282ac9a064cSDimitry Andric }
283ac9a064cSDimitry Andric }
284ac9a064cSDimitry Andric
GetInstByName(const char * Name,const DenseMap<const Record *,std::unique_ptr<CodeGenInstruction>> & Insts,RecordKeeper & Records)285ac9a064cSDimitry Andric static const CodeGenInstruction *GetInstByName(
286ac9a064cSDimitry Andric const char *Name,
287ac9a064cSDimitry Andric const DenseMap<const Record *, std::unique_ptr<CodeGenInstruction>> &Insts,
288ac9a064cSDimitry Andric RecordKeeper &Records) {
289ac9a064cSDimitry Andric const Record *Rec = Records.getDef(Name);
290ac9a064cSDimitry Andric
291ac9a064cSDimitry Andric const auto I = Insts.find(Rec);
292ac9a064cSDimitry Andric if (!Rec || I == Insts.end())
293ac9a064cSDimitry Andric PrintFatalError(Twine("Could not find '") + Name + "' instruction!");
294ac9a064cSDimitry Andric return I->second.get();
295ac9a064cSDimitry Andric }
296ac9a064cSDimitry Andric
297ac9a064cSDimitry Andric static const char *FixedInstrs[] = {
298ac9a064cSDimitry Andric #define HANDLE_TARGET_OPCODE(OPC) #OPC,
299ac9a064cSDimitry Andric #include "llvm/Support/TargetOpcodes.def"
300ac9a064cSDimitry Andric nullptr};
301ac9a064cSDimitry Andric
getNumFixedInstructions()302ac9a064cSDimitry Andric unsigned CodeGenTarget::getNumFixedInstructions() {
303ac9a064cSDimitry Andric return std::size(FixedInstrs) - 1;
304ac9a064cSDimitry Andric }
305ac9a064cSDimitry Andric
306ac9a064cSDimitry Andric /// Return all of the instructions defined by the target, ordered by
307ac9a064cSDimitry Andric /// their enum value.
ComputeInstrsByEnum() const308ac9a064cSDimitry Andric void CodeGenTarget::ComputeInstrsByEnum() const {
309ac9a064cSDimitry Andric const auto &Insts = getInstructions();
310ac9a064cSDimitry Andric for (const char *const *p = FixedInstrs; *p; ++p) {
311ac9a064cSDimitry Andric const CodeGenInstruction *Instr = GetInstByName(*p, Insts, Records);
312ac9a064cSDimitry Andric assert(Instr && "Missing target independent instruction");
313ac9a064cSDimitry Andric assert(Instr->Namespace == "TargetOpcode" && "Bad namespace");
314ac9a064cSDimitry Andric InstrsByEnum.push_back(Instr);
315ac9a064cSDimitry Andric }
316ac9a064cSDimitry Andric unsigned EndOfPredefines = InstrsByEnum.size();
317ac9a064cSDimitry Andric assert(EndOfPredefines == getNumFixedInstructions() &&
318ac9a064cSDimitry Andric "Missing generic opcode");
319ac9a064cSDimitry Andric
320ac9a064cSDimitry Andric for (const auto &I : Insts) {
321ac9a064cSDimitry Andric const CodeGenInstruction *CGI = I.second.get();
322ac9a064cSDimitry Andric if (CGI->Namespace != "TargetOpcode") {
323ac9a064cSDimitry Andric InstrsByEnum.push_back(CGI);
324ac9a064cSDimitry Andric if (CGI->TheDef->getValueAsBit("isPseudo"))
325ac9a064cSDimitry Andric ++NumPseudoInstructions;
326ac9a064cSDimitry Andric }
327ac9a064cSDimitry Andric }
328ac9a064cSDimitry Andric
329ac9a064cSDimitry Andric assert(InstrsByEnum.size() == Insts.size() && "Missing predefined instr");
330ac9a064cSDimitry Andric
331ac9a064cSDimitry Andric // All of the instructions are now in random order based on the map iteration.
332ac9a064cSDimitry Andric llvm::sort(
333ac9a064cSDimitry Andric InstrsByEnum.begin() + EndOfPredefines, InstrsByEnum.end(),
334ac9a064cSDimitry Andric [](const CodeGenInstruction *Rec1, const CodeGenInstruction *Rec2) {
335ac9a064cSDimitry Andric const auto &D1 = *Rec1->TheDef;
336ac9a064cSDimitry Andric const auto &D2 = *Rec2->TheDef;
337ac9a064cSDimitry Andric return std::tuple(!D1.getValueAsBit("isPseudo"), D1.getName()) <
338ac9a064cSDimitry Andric std::tuple(!D2.getValueAsBit("isPseudo"), D2.getName());
339ac9a064cSDimitry Andric });
340ac9a064cSDimitry Andric
341ac9a064cSDimitry Andric // Assign an enum value to each instruction according to the sorted order.
342ac9a064cSDimitry Andric unsigned Num = 0;
343ac9a064cSDimitry Andric for (const CodeGenInstruction *Inst : InstrsByEnum)
344ac9a064cSDimitry Andric Inst->EnumVal = Num++;
345ac9a064cSDimitry Andric }
346ac9a064cSDimitry Andric
347ac9a064cSDimitry Andric /// isLittleEndianEncoding - Return whether this target encodes its instruction
348ac9a064cSDimitry Andric /// in little-endian format, i.e. bits laid out in the order [0..n]
349ac9a064cSDimitry Andric ///
isLittleEndianEncoding() const350ac9a064cSDimitry Andric bool CodeGenTarget::isLittleEndianEncoding() const {
351ac9a064cSDimitry Andric return getInstructionSet()->getValueAsBit("isLittleEndianEncoding");
352ac9a064cSDimitry Andric }
353ac9a064cSDimitry Andric
354ac9a064cSDimitry Andric /// reverseBitsForLittleEndianEncoding - For little-endian instruction bit
355ac9a064cSDimitry Andric /// encodings, reverse the bit order of all instructions.
reverseBitsForLittleEndianEncoding()356ac9a064cSDimitry Andric void CodeGenTarget::reverseBitsForLittleEndianEncoding() {
357ac9a064cSDimitry Andric if (!isLittleEndianEncoding())
358ac9a064cSDimitry Andric return;
359ac9a064cSDimitry Andric
360ac9a064cSDimitry Andric std::vector<Record *> Insts =
361ac9a064cSDimitry Andric Records.getAllDerivedDefinitions("InstructionEncoding");
362ac9a064cSDimitry Andric for (Record *R : Insts) {
363ac9a064cSDimitry Andric if (R->getValueAsString("Namespace") == "TargetOpcode" ||
364ac9a064cSDimitry Andric R->getValueAsBit("isPseudo"))
365ac9a064cSDimitry Andric continue;
366ac9a064cSDimitry Andric
367ac9a064cSDimitry Andric BitsInit *BI = R->getValueAsBitsInit("Inst");
368ac9a064cSDimitry Andric
369ac9a064cSDimitry Andric unsigned numBits = BI->getNumBits();
370ac9a064cSDimitry Andric
371ac9a064cSDimitry Andric SmallVector<Init *, 16> NewBits(numBits);
372ac9a064cSDimitry Andric
373ac9a064cSDimitry Andric for (unsigned bit = 0, end = numBits / 2; bit != end; ++bit) {
374ac9a064cSDimitry Andric unsigned bitSwapIdx = numBits - bit - 1;
375ac9a064cSDimitry Andric Init *OrigBit = BI->getBit(bit);
376ac9a064cSDimitry Andric Init *BitSwap = BI->getBit(bitSwapIdx);
377ac9a064cSDimitry Andric NewBits[bit] = BitSwap;
378ac9a064cSDimitry Andric NewBits[bitSwapIdx] = OrigBit;
379ac9a064cSDimitry Andric }
380ac9a064cSDimitry Andric if (numBits % 2) {
381ac9a064cSDimitry Andric unsigned middle = (numBits + 1) / 2;
382ac9a064cSDimitry Andric NewBits[middle] = BI->getBit(middle);
383ac9a064cSDimitry Andric }
384ac9a064cSDimitry Andric
385ac9a064cSDimitry Andric BitsInit *NewBI = BitsInit::get(Records, NewBits);
386ac9a064cSDimitry Andric
387ac9a064cSDimitry Andric // Update the bits in reversed order so that emitInstrOpBits will get the
388ac9a064cSDimitry Andric // correct endianness.
389ac9a064cSDimitry Andric R->getValue("Inst")->setValue(NewBI);
390ac9a064cSDimitry Andric }
391ac9a064cSDimitry Andric }
392ac9a064cSDimitry Andric
393ac9a064cSDimitry Andric /// guessInstructionProperties - Return true if it's OK to guess instruction
394ac9a064cSDimitry Andric /// properties instead of raising an error.
395ac9a064cSDimitry Andric ///
396ac9a064cSDimitry Andric /// This is configurable as a temporary migration aid. It will eventually be
397ac9a064cSDimitry Andric /// permanently false.
guessInstructionProperties() const398ac9a064cSDimitry Andric bool CodeGenTarget::guessInstructionProperties() const {
399ac9a064cSDimitry Andric return getInstructionSet()->getValueAsBit("guessInstructionProperties");
400ac9a064cSDimitry Andric }
401ac9a064cSDimitry Andric
402ac9a064cSDimitry Andric //===----------------------------------------------------------------------===//
403ac9a064cSDimitry Andric // ComplexPattern implementation
404ac9a064cSDimitry Andric //
ComplexPattern(Record * R)405ac9a064cSDimitry Andric ComplexPattern::ComplexPattern(Record *R) {
406ac9a064cSDimitry Andric Ty = R->getValueAsDef("Ty");
407ac9a064cSDimitry Andric NumOperands = R->getValueAsInt("NumOperands");
408ac9a064cSDimitry Andric SelectFunc = std::string(R->getValueAsString("SelectFunc"));
409ac9a064cSDimitry Andric RootNodes = R->getValueAsListOfDefs("RootNodes");
410ac9a064cSDimitry Andric
411ac9a064cSDimitry Andric // FIXME: This is a hack to statically increase the priority of patterns which
412ac9a064cSDimitry Andric // maps a sub-dag to a complex pattern. e.g. favors LEA over ADD. To get best
413ac9a064cSDimitry Andric // possible pattern match we'll need to dynamically calculate the complexity
414ac9a064cSDimitry Andric // of all patterns a dag can potentially map to.
415ac9a064cSDimitry Andric int64_t RawComplexity = R->getValueAsInt("Complexity");
416ac9a064cSDimitry Andric if (RawComplexity == -1)
417ac9a064cSDimitry Andric Complexity = NumOperands * 3;
418ac9a064cSDimitry Andric else
419ac9a064cSDimitry Andric Complexity = RawComplexity;
420ac9a064cSDimitry Andric
421ac9a064cSDimitry Andric // FIXME: Why is this different from parseSDPatternOperatorProperties?
422ac9a064cSDimitry Andric // Parse the properties.
423ac9a064cSDimitry Andric Properties = 0;
424ac9a064cSDimitry Andric std::vector<Record *> PropList = R->getValueAsListOfDefs("Properties");
425ac9a064cSDimitry Andric for (unsigned i = 0, e = PropList.size(); i != e; ++i)
426ac9a064cSDimitry Andric if (PropList[i]->getName() == "SDNPHasChain") {
427ac9a064cSDimitry Andric Properties |= 1 << SDNPHasChain;
428ac9a064cSDimitry Andric } else if (PropList[i]->getName() == "SDNPOptInGlue") {
429ac9a064cSDimitry Andric Properties |= 1 << SDNPOptInGlue;
430ac9a064cSDimitry Andric } else if (PropList[i]->getName() == "SDNPMayStore") {
431ac9a064cSDimitry Andric Properties |= 1 << SDNPMayStore;
432ac9a064cSDimitry Andric } else if (PropList[i]->getName() == "SDNPMayLoad") {
433ac9a064cSDimitry Andric Properties |= 1 << SDNPMayLoad;
434ac9a064cSDimitry Andric } else if (PropList[i]->getName() == "SDNPSideEffect") {
435ac9a064cSDimitry Andric Properties |= 1 << SDNPSideEffect;
436ac9a064cSDimitry Andric } else if (PropList[i]->getName() == "SDNPMemOperand") {
437ac9a064cSDimitry Andric Properties |= 1 << SDNPMemOperand;
438ac9a064cSDimitry Andric } else if (PropList[i]->getName() == "SDNPVariadic") {
439ac9a064cSDimitry Andric Properties |= 1 << SDNPVariadic;
440ac9a064cSDimitry Andric } else if (PropList[i]->getName() == "SDNPWantRoot") {
441ac9a064cSDimitry Andric Properties |= 1 << SDNPWantRoot;
442ac9a064cSDimitry Andric } else if (PropList[i]->getName() == "SDNPWantParent") {
443ac9a064cSDimitry Andric Properties |= 1 << SDNPWantParent;
444ac9a064cSDimitry Andric } else {
445ac9a064cSDimitry Andric PrintFatalError(R->getLoc(), "Unsupported SD Node property '" +
446ac9a064cSDimitry Andric PropList[i]->getName() +
447ac9a064cSDimitry Andric "' on ComplexPattern '" + R->getName() +
448ac9a064cSDimitry Andric "'!");
449ac9a064cSDimitry Andric }
450ac9a064cSDimitry Andric }
451