1f22ef01cSRoman Divacky //===- CodeGenTarget.cpp - CodeGen Target Class Wrapper -------------------===//
2f22ef01cSRoman Divacky //
3f22ef01cSRoman Divacky //                     The LLVM Compiler Infrastructure
4f22ef01cSRoman Divacky //
5f22ef01cSRoman Divacky // This file is distributed under the University of Illinois Open Source
6f22ef01cSRoman Divacky // License. See LICENSE.TXT for details.
7f22ef01cSRoman Divacky //
8f22ef01cSRoman Divacky //===----------------------------------------------------------------------===//
9f22ef01cSRoman Divacky //
10f22ef01cSRoman Divacky // This class wraps target description classes used by the various code
11f22ef01cSRoman Divacky // generation TableGen backends.  This makes it easier to access the data and
12f22ef01cSRoman Divacky // provides a single place that needs to check it for validity.  All of these
133861d79fSDimitry Andric // classes abort on error conditions.
14f22ef01cSRoman Divacky //
15f22ef01cSRoman Divacky //===----------------------------------------------------------------------===//
16f22ef01cSRoman Divacky 
17f22ef01cSRoman Divacky #include "CodeGenTarget.h"
18f22ef01cSRoman Divacky #include "CodeGenIntrinsics.h"
197ae0e2c9SDimitry Andric #include "CodeGenSchedule.h"
20139f7f9bSDimitry Andric #include "llvm/ADT/STLExtras.h"
21139f7f9bSDimitry Andric #include "llvm/ADT/StringExtras.h"
22139f7f9bSDimitry Andric #include "llvm/Support/CommandLine.h"
233861d79fSDimitry Andric #include "llvm/TableGen/Error.h"
246122f3e6SDimitry Andric #include "llvm/TableGen/Record.h"
25f22ef01cSRoman Divacky #include <algorithm>
26f22ef01cSRoman Divacky using namespace llvm;
27f22ef01cSRoman Divacky 
28f22ef01cSRoman Divacky static cl::opt<unsigned>
29f22ef01cSRoman Divacky AsmParserNum("asmparsernum", cl::init(0),
30f22ef01cSRoman Divacky              cl::desc("Make -gen-asm-parser emit assembly parser #N"));
31f22ef01cSRoman Divacky 
32f22ef01cSRoman Divacky static cl::opt<unsigned>
33f22ef01cSRoman Divacky AsmWriterNum("asmwriternum", cl::init(0),
34f22ef01cSRoman Divacky              cl::desc("Make -gen-asm-writer emit assembly writer #N"));
35f22ef01cSRoman Divacky 
36f22ef01cSRoman Divacky /// getValueType - Return the MVT::SimpleValueType that the specified TableGen
37f22ef01cSRoman Divacky /// record corresponds to.
38f22ef01cSRoman Divacky MVT::SimpleValueType llvm::getValueType(Record *Rec) {
39f22ef01cSRoman Divacky   return (MVT::SimpleValueType)Rec->getValueAsInt("Value");
40f22ef01cSRoman Divacky }
41f22ef01cSRoman Divacky 
423ca95b02SDimitry Andric StringRef llvm::getName(MVT::SimpleValueType T) {
43f22ef01cSRoman Divacky   switch (T) {
44f22ef01cSRoman Divacky   case MVT::Other:   return "UNKNOWN";
45f22ef01cSRoman Divacky   case MVT::iPTR:    return "TLI.getPointerTy()";
46f22ef01cSRoman Divacky   case MVT::iPTRAny: return "TLI.getPointerTy()";
47f22ef01cSRoman Divacky   default: return getEnumName(T);
48f22ef01cSRoman Divacky   }
49f22ef01cSRoman Divacky }
50f22ef01cSRoman Divacky 
513ca95b02SDimitry Andric StringRef llvm::getEnumName(MVT::SimpleValueType T) {
52f22ef01cSRoman Divacky   switch (T) {
53f22ef01cSRoman Divacky   case MVT::Other:    return "MVT::Other";
54f22ef01cSRoman Divacky   case MVT::i1:       return "MVT::i1";
55f22ef01cSRoman Divacky   case MVT::i8:       return "MVT::i8";
56f22ef01cSRoman Divacky   case MVT::i16:      return "MVT::i16";
57f22ef01cSRoman Divacky   case MVT::i32:      return "MVT::i32";
58f22ef01cSRoman Divacky   case MVT::i64:      return "MVT::i64";
59f22ef01cSRoman Divacky   case MVT::i128:     return "MVT::i128";
60ff0cc061SDimitry Andric   case MVT::Any:      return "MVT::Any";
61f22ef01cSRoman Divacky   case MVT::iAny:     return "MVT::iAny";
62f22ef01cSRoman Divacky   case MVT::fAny:     return "MVT::fAny";
63f22ef01cSRoman Divacky   case MVT::vAny:     return "MVT::vAny";
64dff0c46cSDimitry Andric   case MVT::f16:      return "MVT::f16";
65f22ef01cSRoman Divacky   case MVT::f32:      return "MVT::f32";
66f22ef01cSRoman Divacky   case MVT::f64:      return "MVT::f64";
67f22ef01cSRoman Divacky   case MVT::f80:      return "MVT::f80";
68f22ef01cSRoman Divacky   case MVT::f128:     return "MVT::f128";
69f22ef01cSRoman Divacky   case MVT::ppcf128:  return "MVT::ppcf128";
702754fe60SDimitry Andric   case MVT::x86mmx:   return "MVT::x86mmx";
712754fe60SDimitry Andric   case MVT::Glue:     return "MVT::Glue";
72f22ef01cSRoman Divacky   case MVT::isVoid:   return "MVT::isVoid";
733861d79fSDimitry Andric   case MVT::v2i1:     return "MVT::v2i1";
743861d79fSDimitry Andric   case MVT::v4i1:     return "MVT::v4i1";
753861d79fSDimitry Andric   case MVT::v8i1:     return "MVT::v8i1";
763861d79fSDimitry Andric   case MVT::v16i1:    return "MVT::v16i1";
77139f7f9bSDimitry Andric   case MVT::v32i1:    return "MVT::v32i1";
78139f7f9bSDimitry Andric   case MVT::v64i1:    return "MVT::v64i1";
797d523365SDimitry Andric   case MVT::v512i1:   return "MVT::v512i1";
807d523365SDimitry Andric   case MVT::v1024i1:  return "MVT::v1024i1";
81f785676fSDimitry Andric   case MVT::v1i8:     return "MVT::v1i8";
82f22ef01cSRoman Divacky   case MVT::v2i8:     return "MVT::v2i8";
83f22ef01cSRoman Divacky   case MVT::v4i8:     return "MVT::v4i8";
84f22ef01cSRoman Divacky   case MVT::v8i8:     return "MVT::v8i8";
85f22ef01cSRoman Divacky   case MVT::v16i8:    return "MVT::v16i8";
86f22ef01cSRoman Divacky   case MVT::v32i8:    return "MVT::v32i8";
87139f7f9bSDimitry Andric   case MVT::v64i8:    return "MVT::v64i8";
887d523365SDimitry Andric   case MVT::v128i8:   return "MVT::v128i8";
897d523365SDimitry Andric   case MVT::v256i8:   return "MVT::v256i8";
903861d79fSDimitry Andric   case MVT::v1i16:    return "MVT::v1i16";
91f22ef01cSRoman Divacky   case MVT::v2i16:    return "MVT::v2i16";
92f22ef01cSRoman Divacky   case MVT::v4i16:    return "MVT::v4i16";
93f22ef01cSRoman Divacky   case MVT::v8i16:    return "MVT::v8i16";
94f22ef01cSRoman Divacky   case MVT::v16i16:   return "MVT::v16i16";
95139f7f9bSDimitry Andric   case MVT::v32i16:   return "MVT::v32i16";
967d523365SDimitry Andric   case MVT::v64i16:   return "MVT::v64i16";
977d523365SDimitry Andric   case MVT::v128i16:  return "MVT::v128i16";
983861d79fSDimitry Andric   case MVT::v1i32:    return "MVT::v1i32";
99f22ef01cSRoman Divacky   case MVT::v2i32:    return "MVT::v2i32";
100f22ef01cSRoman Divacky   case MVT::v4i32:    return "MVT::v4i32";
101f22ef01cSRoman Divacky   case MVT::v8i32:    return "MVT::v8i32";
1023861d79fSDimitry Andric   case MVT::v16i32:   return "MVT::v16i32";
1037d523365SDimitry Andric   case MVT::v32i32:   return "MVT::v32i32";
1047d523365SDimitry Andric   case MVT::v64i32:   return "MVT::v64i32";
105f22ef01cSRoman Divacky   case MVT::v1i64:    return "MVT::v1i64";
106f22ef01cSRoman Divacky   case MVT::v2i64:    return "MVT::v2i64";
107f22ef01cSRoman Divacky   case MVT::v4i64:    return "MVT::v4i64";
108f22ef01cSRoman Divacky   case MVT::v8i64:    return "MVT::v8i64";
1093861d79fSDimitry Andric   case MVT::v16i64:   return "MVT::v16i64";
1107d523365SDimitry Andric   case MVT::v32i64:   return "MVT::v32i64";
111ff0cc061SDimitry Andric   case MVT::v1i128:   return "MVT::v1i128";
112dff0c46cSDimitry Andric   case MVT::v2f16:    return "MVT::v2f16";
113f785676fSDimitry Andric   case MVT::v4f16:    return "MVT::v4f16";
114f785676fSDimitry Andric   case MVT::v8f16:    return "MVT::v8f16";
115f785676fSDimitry Andric   case MVT::v1f32:    return "MVT::v1f32";
116f22ef01cSRoman Divacky   case MVT::v2f32:    return "MVT::v2f32";
117f22ef01cSRoman Divacky   case MVT::v4f32:    return "MVT::v4f32";
118f22ef01cSRoman Divacky   case MVT::v8f32:    return "MVT::v8f32";
119139f7f9bSDimitry Andric   case MVT::v16f32:   return "MVT::v16f32";
120f785676fSDimitry Andric   case MVT::v1f64:    return "MVT::v1f64";
121f22ef01cSRoman Divacky   case MVT::v2f64:    return "MVT::v2f64";
122f22ef01cSRoman Divacky   case MVT::v4f64:    return "MVT::v4f64";
123139f7f9bSDimitry Andric   case MVT::v8f64:    return "MVT::v8f64";
1247d523365SDimitry Andric   case MVT::token:    return "MVT::token";
125f22ef01cSRoman Divacky   case MVT::Metadata: return "MVT::Metadata";
126f22ef01cSRoman Divacky   case MVT::iPTR:     return "MVT::iPTR";
127f22ef01cSRoman Divacky   case MVT::iPTRAny:  return "MVT::iPTRAny";
128dff0c46cSDimitry Andric   case MVT::Untyped:  return "MVT::Untyped";
129dff0c46cSDimitry Andric   default: llvm_unreachable("ILLEGAL VALUE TYPE!");
130f22ef01cSRoman Divacky   }
131f22ef01cSRoman Divacky }
132f22ef01cSRoman Divacky 
133f22ef01cSRoman Divacky /// getQualifiedName - Return the name of the specified record, with a
134f22ef01cSRoman Divacky /// namespace qualifier if the record contains one.
135f22ef01cSRoman Divacky ///
136f22ef01cSRoman Divacky std::string llvm::getQualifiedName(const Record *R) {
137bd5abe19SDimitry Andric   std::string Namespace;
138bd5abe19SDimitry Andric   if (R->getValue("Namespace"))
139bd5abe19SDimitry Andric      Namespace = R->getValueAsString("Namespace");
140f22ef01cSRoman Divacky   if (Namespace.empty()) return R->getName();
141f22ef01cSRoman Divacky   return Namespace + "::" + R->getName();
142f22ef01cSRoman Divacky }
143f22ef01cSRoman Divacky 
144f22ef01cSRoman Divacky 
145f22ef01cSRoman Divacky /// getTarget - Return the current instance of the Target class.
146f22ef01cSRoman Divacky ///
147bd5abe19SDimitry Andric CodeGenTarget::CodeGenTarget(RecordKeeper &records)
14839d628a0SDimitry Andric   : Records(records) {
149f22ef01cSRoman Divacky   std::vector<Record*> Targets = Records.getAllDerivedDefinitions("Target");
150f22ef01cSRoman Divacky   if (Targets.size() == 0)
1513861d79fSDimitry Andric     PrintFatalError("ERROR: No 'Target' subclasses defined!");
152f22ef01cSRoman Divacky   if (Targets.size() != 1)
1533861d79fSDimitry Andric     PrintFatalError("ERROR: Multiple subclasses of Target defined!");
154f22ef01cSRoman Divacky   TargetRec = Targets[0];
155f22ef01cSRoman Divacky }
156f22ef01cSRoman Divacky 
1577ae0e2c9SDimitry Andric CodeGenTarget::~CodeGenTarget() {
1587ae0e2c9SDimitry Andric }
159f22ef01cSRoman Divacky 
160f22ef01cSRoman Divacky const std::string &CodeGenTarget::getName() const {
161f22ef01cSRoman Divacky   return TargetRec->getName();
162f22ef01cSRoman Divacky }
163f22ef01cSRoman Divacky 
164f22ef01cSRoman Divacky std::string CodeGenTarget::getInstNamespace() const {
1653ca95b02SDimitry Andric   for (const CodeGenInstruction *Inst : getInstructionsByEnumValue()) {
166f22ef01cSRoman Divacky     // Make sure not to pick up "TargetOpcode" by accidentally getting
167f22ef01cSRoman Divacky     // the namespace off the PHI instruction or something.
16839d628a0SDimitry Andric     if (Inst->Namespace != "TargetOpcode")
16939d628a0SDimitry Andric       return Inst->Namespace;
170f22ef01cSRoman Divacky   }
171f22ef01cSRoman Divacky 
172f22ef01cSRoman Divacky   return "";
173f22ef01cSRoman Divacky }
174f22ef01cSRoman Divacky 
175f22ef01cSRoman Divacky Record *CodeGenTarget::getInstructionSet() const {
176f22ef01cSRoman Divacky   return TargetRec->getValueAsDef("InstructionSet");
177f22ef01cSRoman Divacky }
178f22ef01cSRoman Divacky 
179f22ef01cSRoman Divacky 
180f22ef01cSRoman Divacky /// getAsmParser - Return the AssemblyParser definition for this target.
181f22ef01cSRoman Divacky ///
182f22ef01cSRoman Divacky Record *CodeGenTarget::getAsmParser() const {
183f22ef01cSRoman Divacky   std::vector<Record*> LI = TargetRec->getValueAsListOfDefs("AssemblyParsers");
184f22ef01cSRoman Divacky   if (AsmParserNum >= LI.size())
18591bc56edSDimitry Andric     PrintFatalError("Target does not have an AsmParser #" +
18691bc56edSDimitry Andric                     Twine(AsmParserNum) + "!");
187f22ef01cSRoman Divacky   return LI[AsmParserNum];
188f22ef01cSRoman Divacky }
189f22ef01cSRoman Divacky 
190dff0c46cSDimitry Andric /// getAsmParserVariant - Return the AssmblyParserVariant definition for
191dff0c46cSDimitry Andric /// this target.
192dff0c46cSDimitry Andric ///
193dff0c46cSDimitry Andric Record *CodeGenTarget::getAsmParserVariant(unsigned i) const {
194dff0c46cSDimitry Andric   std::vector<Record*> LI =
195dff0c46cSDimitry Andric     TargetRec->getValueAsListOfDefs("AssemblyParserVariants");
196dff0c46cSDimitry Andric   if (i >= LI.size())
19791bc56edSDimitry Andric     PrintFatalError("Target does not have an AsmParserVariant #" + Twine(i) +
19891bc56edSDimitry Andric                     "!");
199dff0c46cSDimitry Andric   return LI[i];
200dff0c46cSDimitry Andric }
201dff0c46cSDimitry Andric 
202dff0c46cSDimitry Andric /// getAsmParserVariantCount - Return the AssmblyParserVariant definition
203dff0c46cSDimitry Andric /// available for this target.
204dff0c46cSDimitry Andric ///
205dff0c46cSDimitry Andric unsigned CodeGenTarget::getAsmParserVariantCount() const {
206dff0c46cSDimitry Andric   std::vector<Record*> LI =
207dff0c46cSDimitry Andric     TargetRec->getValueAsListOfDefs("AssemblyParserVariants");
208dff0c46cSDimitry Andric   return LI.size();
209dff0c46cSDimitry Andric }
210dff0c46cSDimitry Andric 
211f22ef01cSRoman Divacky /// getAsmWriter - Return the AssemblyWriter definition for this target.
212f22ef01cSRoman Divacky ///
213f22ef01cSRoman Divacky Record *CodeGenTarget::getAsmWriter() const {
214f22ef01cSRoman Divacky   std::vector<Record*> LI = TargetRec->getValueAsListOfDefs("AssemblyWriters");
215f22ef01cSRoman Divacky   if (AsmWriterNum >= LI.size())
21691bc56edSDimitry Andric     PrintFatalError("Target does not have an AsmWriter #" +
21791bc56edSDimitry Andric                     Twine(AsmWriterNum) + "!");
218f22ef01cSRoman Divacky   return LI[AsmWriterNum];
219f22ef01cSRoman Divacky }
220f22ef01cSRoman Divacky 
221bd5abe19SDimitry Andric CodeGenRegBank &CodeGenTarget::getRegBank() const {
222bd5abe19SDimitry Andric   if (!RegBank)
22339d628a0SDimitry Andric     RegBank = llvm::make_unique<CodeGenRegBank>(Records);
224bd5abe19SDimitry Andric   return *RegBank;
225f22ef01cSRoman Divacky }
226f22ef01cSRoman Divacky 
22717a519f9SDimitry Andric void CodeGenTarget::ReadRegAltNameIndices() const {
22817a519f9SDimitry Andric   RegAltNameIndices = Records.getAllDerivedDefinitions("RegAltNameIndex");
22917a519f9SDimitry Andric   std::sort(RegAltNameIndices.begin(), RegAltNameIndices.end(), LessRecord());
230f22ef01cSRoman Divacky }
231f22ef01cSRoman Divacky 
2322754fe60SDimitry Andric /// getRegisterByName - If there is a register with the specific AsmName,
2332754fe60SDimitry Andric /// return it.
2342754fe60SDimitry Andric const CodeGenRegister *CodeGenTarget::getRegisterByName(StringRef Name) const {
2353861d79fSDimitry Andric   const StringMap<CodeGenRegister*> &Regs = getRegBank().getRegistersByName();
2363861d79fSDimitry Andric   StringMap<CodeGenRegister*>::const_iterator I = Regs.find(Name);
2373861d79fSDimitry Andric   if (I == Regs.end())
23891bc56edSDimitry Andric     return nullptr;
2393861d79fSDimitry Andric   return I->second;
2402754fe60SDimitry Andric }
2412754fe60SDimitry Andric 
242f22ef01cSRoman Divacky std::vector<MVT::SimpleValueType> CodeGenTarget::
243f22ef01cSRoman Divacky getRegisterVTs(Record *R) const {
24417a519f9SDimitry Andric   const CodeGenRegister *Reg = getRegBank().getReg(R);
245f22ef01cSRoman Divacky   std::vector<MVT::SimpleValueType> Result;
24639d628a0SDimitry Andric   for (const auto &RC : getRegBank().getRegClasses()) {
24717a519f9SDimitry Andric     if (RC.contains(Reg)) {
248139f7f9bSDimitry Andric       ArrayRef<MVT::SimpleValueType> InVTs = RC.getValueTypes();
249f22ef01cSRoman Divacky       Result.insert(Result.end(), InVTs.begin(), InVTs.end());
250f22ef01cSRoman Divacky     }
251f22ef01cSRoman Divacky   }
252f22ef01cSRoman Divacky 
253f22ef01cSRoman Divacky   // Remove duplicates.
254f22ef01cSRoman Divacky   array_pod_sort(Result.begin(), Result.end());
255f22ef01cSRoman Divacky   Result.erase(std::unique(Result.begin(), Result.end()), Result.end());
256f22ef01cSRoman Divacky   return Result;
257f22ef01cSRoman Divacky }
258f22ef01cSRoman Divacky 
259f22ef01cSRoman Divacky 
260f22ef01cSRoman Divacky void CodeGenTarget::ReadLegalValueTypes() const {
26139d628a0SDimitry Andric   for (const auto &RC : getRegBank().getRegClasses())
26239d628a0SDimitry Andric     LegalValueTypes.insert(LegalValueTypes.end(), RC.VTs.begin(), RC.VTs.end());
263f22ef01cSRoman Divacky 
264f22ef01cSRoman Divacky   // Remove duplicates.
2657d523365SDimitry Andric   array_pod_sort(LegalValueTypes.begin(), LegalValueTypes.end());
266f22ef01cSRoman Divacky   LegalValueTypes.erase(std::unique(LegalValueTypes.begin(),
267f22ef01cSRoman Divacky                                     LegalValueTypes.end()),
268f22ef01cSRoman Divacky                         LegalValueTypes.end());
269f22ef01cSRoman Divacky }
270f22ef01cSRoman Divacky 
2717ae0e2c9SDimitry Andric CodeGenSchedModels &CodeGenTarget::getSchedModels() const {
2727ae0e2c9SDimitry Andric   if (!SchedModels)
27339d628a0SDimitry Andric     SchedModels = llvm::make_unique<CodeGenSchedModels>(Records, *this);
2747ae0e2c9SDimitry Andric   return *SchedModels;
2757ae0e2c9SDimitry Andric }
276f22ef01cSRoman Divacky 
277f22ef01cSRoman Divacky void CodeGenTarget::ReadInstructions() const {
278f22ef01cSRoman Divacky   std::vector<Record*> Insts = Records.getAllDerivedDefinitions("Instruction");
279f22ef01cSRoman Divacky   if (Insts.size() <= 2)
2803861d79fSDimitry Andric     PrintFatalError("No 'Instruction' subclasses defined!");
281f22ef01cSRoman Divacky 
282f22ef01cSRoman Divacky   // Parse the instructions defined in the .td file.
2832754fe60SDimitry Andric   for (unsigned i = 0, e = Insts.size(); i != e; ++i)
28439d628a0SDimitry Andric     Instructions[Insts[i]] = llvm::make_unique<CodeGenInstruction>(Insts[i]);
285f22ef01cSRoman Divacky }
286f22ef01cSRoman Divacky 
287f22ef01cSRoman Divacky static const CodeGenInstruction *
288f22ef01cSRoman Divacky GetInstByName(const char *Name,
28939d628a0SDimitry Andric               const DenseMap<const Record*,
29039d628a0SDimitry Andric                              std::unique_ptr<CodeGenInstruction>> &Insts,
2912754fe60SDimitry Andric               RecordKeeper &Records) {
292f22ef01cSRoman Divacky   const Record *Rec = Records.getDef(Name);
293f22ef01cSRoman Divacky 
29439d628a0SDimitry Andric   const auto I = Insts.find(Rec);
29591bc56edSDimitry Andric   if (!Rec || I == Insts.end())
29691bc56edSDimitry Andric     PrintFatalError(Twine("Could not find '") + Name + "' instruction!");
29739d628a0SDimitry Andric   return I->second.get();
298f22ef01cSRoman Divacky }
299f22ef01cSRoman Divacky 
30091bc56edSDimitry Andric /// \brief Return all of the instructions defined by the target, ordered by
30191bc56edSDimitry Andric /// their enum value.
302f22ef01cSRoman Divacky void CodeGenTarget::ComputeInstrsByEnum() const {
303f785676fSDimitry Andric   static const char *const FixedInstrs[] = {
3043ca95b02SDimitry Andric #define HANDLE_TARGET_OPCODE(OPC, NUM) #OPC,
3053ca95b02SDimitry Andric #include "llvm/Target/TargetOpcodes.def"
30639d628a0SDimitry Andric       nullptr};
30739d628a0SDimitry Andric   const auto &Insts = getInstructions();
308ffd1746dSEd Schouten   for (const char *const *p = FixedInstrs; *p; ++p) {
3092754fe60SDimitry Andric     const CodeGenInstruction *Instr = GetInstByName(*p, Insts, Records);
310ffd1746dSEd Schouten     assert(Instr && "Missing target independent instruction");
311ffd1746dSEd Schouten     assert(Instr->Namespace == "TargetOpcode" && "Bad namespace");
312ffd1746dSEd Schouten     InstrsByEnum.push_back(Instr);
313ffd1746dSEd Schouten   }
314f22ef01cSRoman Divacky   unsigned EndOfPredefines = InstrsByEnum.size();
315f22ef01cSRoman Divacky 
31639d628a0SDimitry Andric   for (const auto &I : Insts) {
31739d628a0SDimitry Andric     const CodeGenInstruction *CGI = I.second.get();
318ffd1746dSEd Schouten     if (CGI->Namespace != "TargetOpcode")
319f22ef01cSRoman Divacky       InstrsByEnum.push_back(CGI);
320f22ef01cSRoman Divacky   }
321f22ef01cSRoman Divacky 
322ffd1746dSEd Schouten   assert(InstrsByEnum.size() == Insts.size() && "Missing predefined instr");
323ffd1746dSEd Schouten 
324f22ef01cSRoman Divacky   // All of the instructions are now in random order based on the map iteration.
325f22ef01cSRoman Divacky   // Sort them by name.
326f22ef01cSRoman Divacky   std::sort(InstrsByEnum.begin() + EndOfPredefines, InstrsByEnum.end(),
32791bc56edSDimitry Andric             [](const CodeGenInstruction *Rec1, const CodeGenInstruction *Rec2) {
32891bc56edSDimitry Andric     return Rec1->TheDef->getName() < Rec2->TheDef->getName();
32991bc56edSDimitry Andric   });
330f22ef01cSRoman Divacky }
331f22ef01cSRoman Divacky 
332f22ef01cSRoman Divacky 
333f22ef01cSRoman Divacky /// isLittleEndianEncoding - Return whether this target encodes its instruction
334f22ef01cSRoman Divacky /// in little-endian format, i.e. bits laid out in the order [0..n]
335f22ef01cSRoman Divacky ///
336f22ef01cSRoman Divacky bool CodeGenTarget::isLittleEndianEncoding() const {
337f22ef01cSRoman Divacky   return getInstructionSet()->getValueAsBit("isLittleEndianEncoding");
338f22ef01cSRoman Divacky }
339f22ef01cSRoman Divacky 
34091bc56edSDimitry Andric /// reverseBitsForLittleEndianEncoding - For little-endian instruction bit
34191bc56edSDimitry Andric /// encodings, reverse the bit order of all instructions.
34291bc56edSDimitry Andric void CodeGenTarget::reverseBitsForLittleEndianEncoding() {
34391bc56edSDimitry Andric   if (!isLittleEndianEncoding())
34491bc56edSDimitry Andric     return;
34591bc56edSDimitry Andric 
34691bc56edSDimitry Andric   std::vector<Record*> Insts = Records.getAllDerivedDefinitions("Instruction");
34739d628a0SDimitry Andric   for (Record *R : Insts) {
34891bc56edSDimitry Andric     if (R->getValueAsString("Namespace") == "TargetOpcode" ||
34991bc56edSDimitry Andric         R->getValueAsBit("isPseudo"))
35091bc56edSDimitry Andric       continue;
35191bc56edSDimitry Andric 
35291bc56edSDimitry Andric     BitsInit *BI = R->getValueAsBitsInit("Inst");
35391bc56edSDimitry Andric 
35491bc56edSDimitry Andric     unsigned numBits = BI->getNumBits();
35591bc56edSDimitry Andric 
35691bc56edSDimitry Andric     SmallVector<Init *, 16> NewBits(numBits);
35791bc56edSDimitry Andric 
35891bc56edSDimitry Andric     for (unsigned bit = 0, end = numBits / 2; bit != end; ++bit) {
35991bc56edSDimitry Andric       unsigned bitSwapIdx = numBits - bit - 1;
36091bc56edSDimitry Andric       Init *OrigBit = BI->getBit(bit);
36191bc56edSDimitry Andric       Init *BitSwap = BI->getBit(bitSwapIdx);
36291bc56edSDimitry Andric       NewBits[bit]        = BitSwap;
36391bc56edSDimitry Andric       NewBits[bitSwapIdx] = OrigBit;
36491bc56edSDimitry Andric     }
36591bc56edSDimitry Andric     if (numBits % 2) {
36691bc56edSDimitry Andric       unsigned middle = (numBits + 1) / 2;
36791bc56edSDimitry Andric       NewBits[middle] = BI->getBit(middle);
36891bc56edSDimitry Andric     }
36991bc56edSDimitry Andric 
37091bc56edSDimitry Andric     BitsInit *NewBI = BitsInit::get(NewBits);
37191bc56edSDimitry Andric 
37291bc56edSDimitry Andric     // Update the bits in reversed order so that emitInstrOpBits will get the
37391bc56edSDimitry Andric     // correct endianness.
37491bc56edSDimitry Andric     R->getValue("Inst")->setValue(NewBI);
37591bc56edSDimitry Andric   }
37691bc56edSDimitry Andric }
37791bc56edSDimitry Andric 
3783861d79fSDimitry Andric /// guessInstructionProperties - Return true if it's OK to guess instruction
3793861d79fSDimitry Andric /// properties instead of raising an error.
3803861d79fSDimitry Andric ///
3813861d79fSDimitry Andric /// This is configurable as a temporary migration aid. It will eventually be
3823861d79fSDimitry Andric /// permanently false.
3833861d79fSDimitry Andric bool CodeGenTarget::guessInstructionProperties() const {
3843861d79fSDimitry Andric   return getInstructionSet()->getValueAsBit("guessInstructionProperties");
3853861d79fSDimitry Andric }
3863861d79fSDimitry Andric 
387f22ef01cSRoman Divacky //===----------------------------------------------------------------------===//
388f22ef01cSRoman Divacky // ComplexPattern implementation
389f22ef01cSRoman Divacky //
390f22ef01cSRoman Divacky ComplexPattern::ComplexPattern(Record *R) {
391f22ef01cSRoman Divacky   Ty          = ::getValueType(R->getValueAsDef("Ty"));
392f22ef01cSRoman Divacky   NumOperands = R->getValueAsInt("NumOperands");
393f22ef01cSRoman Divacky   SelectFunc  = R->getValueAsString("SelectFunc");
394f22ef01cSRoman Divacky   RootNodes   = R->getValueAsListOfDefs("RootNodes");
395f22ef01cSRoman Divacky 
396f22ef01cSRoman Divacky   // Parse the properties.
397f22ef01cSRoman Divacky   Properties = 0;
398f22ef01cSRoman Divacky   std::vector<Record*> PropList = R->getValueAsListOfDefs("Properties");
399f22ef01cSRoman Divacky   for (unsigned i = 0, e = PropList.size(); i != e; ++i)
400f22ef01cSRoman Divacky     if (PropList[i]->getName() == "SDNPHasChain") {
401f22ef01cSRoman Divacky       Properties |= 1 << SDNPHasChain;
4022754fe60SDimitry Andric     } else if (PropList[i]->getName() == "SDNPOptInGlue") {
4032754fe60SDimitry Andric       Properties |= 1 << SDNPOptInGlue;
404f22ef01cSRoman Divacky     } else if (PropList[i]->getName() == "SDNPMayStore") {
405f22ef01cSRoman Divacky       Properties |= 1 << SDNPMayStore;
406f22ef01cSRoman Divacky     } else if (PropList[i]->getName() == "SDNPMayLoad") {
407f22ef01cSRoman Divacky       Properties |= 1 << SDNPMayLoad;
408f22ef01cSRoman Divacky     } else if (PropList[i]->getName() == "SDNPSideEffect") {
409f22ef01cSRoman Divacky       Properties |= 1 << SDNPSideEffect;
410f22ef01cSRoman Divacky     } else if (PropList[i]->getName() == "SDNPMemOperand") {
411f22ef01cSRoman Divacky       Properties |= 1 << SDNPMemOperand;
412f22ef01cSRoman Divacky     } else if (PropList[i]->getName() == "SDNPVariadic") {
413f22ef01cSRoman Divacky       Properties |= 1 << SDNPVariadic;
4142754fe60SDimitry Andric     } else if (PropList[i]->getName() == "SDNPWantRoot") {
4152754fe60SDimitry Andric       Properties |= 1 << SDNPWantRoot;
4162754fe60SDimitry Andric     } else if (PropList[i]->getName() == "SDNPWantParent") {
4172754fe60SDimitry Andric       Properties |= 1 << SDNPWantParent;
418f22ef01cSRoman Divacky     } else {
419ff0cc061SDimitry Andric       PrintFatalError("Unsupported SD Node property '" +
420ff0cc061SDimitry Andric                       PropList[i]->getName() + "' on ComplexPattern '" +
421ff0cc061SDimitry Andric                       R->getName() + "'!");
422f22ef01cSRoman Divacky     }
423f22ef01cSRoman Divacky }
424f22ef01cSRoman Divacky 
425f22ef01cSRoman Divacky //===----------------------------------------------------------------------===//
426f22ef01cSRoman Divacky // CodeGenIntrinsic Implementation
427f22ef01cSRoman Divacky //===----------------------------------------------------------------------===//
428f22ef01cSRoman Divacky 
4293ca95b02SDimitry Andric CodeGenIntrinsicTable::CodeGenIntrinsicTable(const RecordKeeper &RC,
430f22ef01cSRoman Divacky                                              bool TargetOnly) {
4313ca95b02SDimitry Andric   std::vector<Record*> Defs = RC.getAllDerivedDefinitions("Intrinsic");
432f22ef01cSRoman Divacky 
4333ca95b02SDimitry Andric   Intrinsics.reserve(Defs.size());
434f22ef01cSRoman Divacky 
4353ca95b02SDimitry Andric   for (unsigned I = 0, e = Defs.size(); I != e; ++I) {
4363ca95b02SDimitry Andric     bool isTarget = Defs[I]->getValueAsBit("isTarget");
437f22ef01cSRoman Divacky     if (isTarget == TargetOnly)
4383ca95b02SDimitry Andric       Intrinsics.push_back(CodeGenIntrinsic(Defs[I]));
439f22ef01cSRoman Divacky   }
4403ca95b02SDimitry Andric   std::sort(Intrinsics.begin(), Intrinsics.end(),
4413ca95b02SDimitry Andric             [](const CodeGenIntrinsic &LHS, const CodeGenIntrinsic &RHS) {
4423ca95b02SDimitry Andric               return std::tie(LHS.TargetPrefix, LHS.Name) <
4433ca95b02SDimitry Andric                      std::tie(RHS.TargetPrefix, RHS.Name);
4443ca95b02SDimitry Andric             });
4453ca95b02SDimitry Andric   Targets.push_back({"", 0, 0});
4463ca95b02SDimitry Andric   for (size_t I = 0, E = Intrinsics.size(); I < E; ++I)
4473ca95b02SDimitry Andric     if (Intrinsics[I].TargetPrefix != Targets.back().Name) {
4483ca95b02SDimitry Andric       Targets.back().Count = I - Targets.back().Offset;
4493ca95b02SDimitry Andric       Targets.push_back({Intrinsics[I].TargetPrefix, I, 0});
4503ca95b02SDimitry Andric     }
4513ca95b02SDimitry Andric   Targets.back().Count = Intrinsics.size() - Targets.back().Offset;
452f22ef01cSRoman Divacky }
453f22ef01cSRoman Divacky 
454f22ef01cSRoman Divacky CodeGenIntrinsic::CodeGenIntrinsic(Record *R) {
455f22ef01cSRoman Divacky   TheDef = R;
456f22ef01cSRoman Divacky   std::string DefName = R->getName();
457e580952dSDimitry Andric   ModRef = ReadWriteMem;
458f22ef01cSRoman Divacky   isOverloaded = false;
459f22ef01cSRoman Divacky   isCommutative = false;
460bd5abe19SDimitry Andric   canThrow = false;
4617ae0e2c9SDimitry Andric   isNoReturn = false;
46291bc56edSDimitry Andric   isNoDuplicate = false;
463ff0cc061SDimitry Andric   isConvergent = false;
464f22ef01cSRoman Divacky 
465f22ef01cSRoman Divacky   if (DefName.size() <= 4 ||
466f22ef01cSRoman Divacky       std::string(DefName.begin(), DefName.begin() + 4) != "int_")
4673861d79fSDimitry Andric     PrintFatalError("Intrinsic '" + DefName + "' does not start with 'int_'!");
468f22ef01cSRoman Divacky 
469f22ef01cSRoman Divacky   EnumName = std::string(DefName.begin()+4, DefName.end());
470f22ef01cSRoman Divacky 
471f22ef01cSRoman Divacky   if (R->getValue("GCCBuiltinName"))  // Ignore a missing GCCBuiltinName field.
472f22ef01cSRoman Divacky     GCCBuiltinName = R->getValueAsString("GCCBuiltinName");
47391bc56edSDimitry Andric   if (R->getValue("MSBuiltinName"))   // Ignore a missing MSBuiltinName field.
47491bc56edSDimitry Andric     MSBuiltinName = R->getValueAsString("MSBuiltinName");
475f22ef01cSRoman Divacky 
476f22ef01cSRoman Divacky   TargetPrefix = R->getValueAsString("TargetPrefix");
477f22ef01cSRoman Divacky   Name = R->getValueAsString("LLVMName");
478f22ef01cSRoman Divacky 
479f22ef01cSRoman Divacky   if (Name == "") {
480f22ef01cSRoman Divacky     // If an explicit name isn't specified, derive one from the DefName.
481f22ef01cSRoman Divacky     Name = "llvm.";
482f22ef01cSRoman Divacky 
483f22ef01cSRoman Divacky     for (unsigned i = 0, e = EnumName.size(); i != e; ++i)
484f22ef01cSRoman Divacky       Name += (EnumName[i] == '_') ? '.' : EnumName[i];
485f22ef01cSRoman Divacky   } else {
486f22ef01cSRoman Divacky     // Verify it starts with "llvm.".
487f22ef01cSRoman Divacky     if (Name.size() <= 5 ||
488f22ef01cSRoman Divacky         std::string(Name.begin(), Name.begin() + 5) != "llvm.")
4893861d79fSDimitry Andric       PrintFatalError("Intrinsic '" + DefName + "'s name does not start with 'llvm.'!");
490f22ef01cSRoman Divacky   }
491f22ef01cSRoman Divacky 
492f22ef01cSRoman Divacky   // If TargetPrefix is specified, make sure that Name starts with
493f22ef01cSRoman Divacky   // "llvm.<targetprefix>.".
494f22ef01cSRoman Divacky   if (!TargetPrefix.empty()) {
495f22ef01cSRoman Divacky     if (Name.size() < 6+TargetPrefix.size() ||
496f22ef01cSRoman Divacky         std::string(Name.begin() + 5, Name.begin() + 6 + TargetPrefix.size())
497f22ef01cSRoman Divacky         != (TargetPrefix + "."))
4983861d79fSDimitry Andric       PrintFatalError("Intrinsic '" + DefName + "' does not start with 'llvm." +
4993861d79fSDimitry Andric         TargetPrefix + ".'!");
500f22ef01cSRoman Divacky   }
501f22ef01cSRoman Divacky 
502f22ef01cSRoman Divacky   // Parse the list of return types.
503f22ef01cSRoman Divacky   std::vector<MVT::SimpleValueType> OverloadedVTs;
504f22ef01cSRoman Divacky   ListInit *TypeList = R->getValueAsListInit("RetTypes");
50597bc6c73SDimitry Andric   for (unsigned i = 0, e = TypeList->size(); i != e; ++i) {
506f22ef01cSRoman Divacky     Record *TyEl = TypeList->getElementAsRecord(i);
507f22ef01cSRoman Divacky     assert(TyEl->isSubClassOf("LLVMType") && "Expected a type!");
508f22ef01cSRoman Divacky     MVT::SimpleValueType VT;
509f22ef01cSRoman Divacky     if (TyEl->isSubClassOf("LLVMMatchType")) {
510f22ef01cSRoman Divacky       unsigned MatchTy = TyEl->getValueAsInt("Number");
511f22ef01cSRoman Divacky       assert(MatchTy < OverloadedVTs.size() &&
512f22ef01cSRoman Divacky              "Invalid matching number!");
513f22ef01cSRoman Divacky       VT = OverloadedVTs[MatchTy];
514f22ef01cSRoman Divacky       // It only makes sense to use the extended and truncated vector element
515f22ef01cSRoman Divacky       // variants with iAny types; otherwise, if the intrinsic is not
516f22ef01cSRoman Divacky       // overloaded, all the types can be specified directly.
51791bc56edSDimitry Andric       assert(((!TyEl->isSubClassOf("LLVMExtendedType") &&
51891bc56edSDimitry Andric                !TyEl->isSubClassOf("LLVMTruncatedType")) ||
519f22ef01cSRoman Divacky               VT == MVT::iAny || VT == MVT::vAny) &&
520f22ef01cSRoman Divacky              "Expected iAny or vAny type");
521f22ef01cSRoman Divacky     } else {
522f22ef01cSRoman Divacky       VT = getValueType(TyEl->getValueAsDef("VT"));
523f22ef01cSRoman Divacky     }
52491bc56edSDimitry Andric     if (MVT(VT).isOverloaded()) {
525f22ef01cSRoman Divacky       OverloadedVTs.push_back(VT);
526f22ef01cSRoman Divacky       isOverloaded = true;
527f22ef01cSRoman Divacky     }
528f22ef01cSRoman Divacky 
529f22ef01cSRoman Divacky     // Reject invalid types.
530f22ef01cSRoman Divacky     if (VT == MVT::isVoid)
5313861d79fSDimitry Andric       PrintFatalError("Intrinsic '" + DefName + " has void in result type list!");
532f22ef01cSRoman Divacky 
533f22ef01cSRoman Divacky     IS.RetVTs.push_back(VT);
534f22ef01cSRoman Divacky     IS.RetTypeDefs.push_back(TyEl);
535f22ef01cSRoman Divacky   }
536f22ef01cSRoman Divacky 
537f22ef01cSRoman Divacky   // Parse the list of parameter types.
538f22ef01cSRoman Divacky   TypeList = R->getValueAsListInit("ParamTypes");
53997bc6c73SDimitry Andric   for (unsigned i = 0, e = TypeList->size(); i != e; ++i) {
540f22ef01cSRoman Divacky     Record *TyEl = TypeList->getElementAsRecord(i);
541f22ef01cSRoman Divacky     assert(TyEl->isSubClassOf("LLVMType") && "Expected a type!");
542f22ef01cSRoman Divacky     MVT::SimpleValueType VT;
543f22ef01cSRoman Divacky     if (TyEl->isSubClassOf("LLVMMatchType")) {
544f22ef01cSRoman Divacky       unsigned MatchTy = TyEl->getValueAsInt("Number");
545f22ef01cSRoman Divacky       assert(MatchTy < OverloadedVTs.size() &&
546f22ef01cSRoman Divacky              "Invalid matching number!");
547f22ef01cSRoman Divacky       VT = OverloadedVTs[MatchTy];
548f22ef01cSRoman Divacky       // It only makes sense to use the extended and truncated vector element
549f22ef01cSRoman Divacky       // variants with iAny types; otherwise, if the intrinsic is not
550f22ef01cSRoman Divacky       // overloaded, all the types can be specified directly.
55191bc56edSDimitry Andric       assert(((!TyEl->isSubClassOf("LLVMExtendedType") &&
55239d628a0SDimitry Andric                !TyEl->isSubClassOf("LLVMTruncatedType") &&
55339d628a0SDimitry Andric                !TyEl->isSubClassOf("LLVMVectorSameWidth") &&
55439d628a0SDimitry Andric                !TyEl->isSubClassOf("LLVMPointerToElt")) ||
555f22ef01cSRoman Divacky               VT == MVT::iAny || VT == MVT::vAny) &&
556f22ef01cSRoman Divacky              "Expected iAny or vAny type");
557f22ef01cSRoman Divacky     } else
558f22ef01cSRoman Divacky       VT = getValueType(TyEl->getValueAsDef("VT"));
559f22ef01cSRoman Divacky 
56091bc56edSDimitry Andric     if (MVT(VT).isOverloaded()) {
561f22ef01cSRoman Divacky       OverloadedVTs.push_back(VT);
562f22ef01cSRoman Divacky       isOverloaded = true;
563f22ef01cSRoman Divacky     }
564f22ef01cSRoman Divacky 
565f22ef01cSRoman Divacky     // Reject invalid types.
566f22ef01cSRoman Divacky     if (VT == MVT::isVoid && i != e-1 /*void at end means varargs*/)
5673861d79fSDimitry Andric       PrintFatalError("Intrinsic '" + DefName + " has void in result type list!");
568f22ef01cSRoman Divacky 
569f22ef01cSRoman Divacky     IS.ParamVTs.push_back(VT);
570f22ef01cSRoman Divacky     IS.ParamTypeDefs.push_back(TyEl);
571f22ef01cSRoman Divacky   }
572f22ef01cSRoman Divacky 
573f22ef01cSRoman Divacky   // Parse the intrinsic properties.
5743ca95b02SDimitry Andric   ListInit *PropList = R->getValueAsListInit("IntrProperties");
57597bc6c73SDimitry Andric   for (unsigned i = 0, e = PropList->size(); i != e; ++i) {
576f22ef01cSRoman Divacky     Record *Property = PropList->getElementAsRecord(i);
577f22ef01cSRoman Divacky     assert(Property->isSubClassOf("IntrinsicProperty") &&
578f22ef01cSRoman Divacky            "Expected a property!");
579f22ef01cSRoman Divacky 
580f22ef01cSRoman Divacky     if (Property->getName() == "IntrNoMem")
581f22ef01cSRoman Divacky       ModRef = NoMem;
582f22ef01cSRoman Divacky     else if (Property->getName() == "IntrReadMem")
5833ca95b02SDimitry Andric       ModRef = ModRefBehavior(ModRef & ~MR_Mod);
5843ca95b02SDimitry Andric     else if (Property->getName() == "IntrWriteMem")
5853ca95b02SDimitry Andric       ModRef = ModRefBehavior(ModRef & ~MR_Ref);
5863ca95b02SDimitry Andric     else if (Property->getName() == "IntrArgMemOnly")
5873ca95b02SDimitry Andric       ModRef = ModRefBehavior(ModRef & ~MR_Anywhere);
588f22ef01cSRoman Divacky     else if (Property->getName() == "Commutative")
589f22ef01cSRoman Divacky       isCommutative = true;
590bd5abe19SDimitry Andric     else if (Property->getName() == "Throws")
591bd5abe19SDimitry Andric       canThrow = true;
59291bc56edSDimitry Andric     else if (Property->getName() == "IntrNoDuplicate")
59391bc56edSDimitry Andric       isNoDuplicate = true;
594ff0cc061SDimitry Andric     else if (Property->getName() == "IntrConvergent")
595ff0cc061SDimitry Andric       isConvergent = true;
5967ae0e2c9SDimitry Andric     else if (Property->getName() == "IntrNoReturn")
5977ae0e2c9SDimitry Andric       isNoReturn = true;
598f22ef01cSRoman Divacky     else if (Property->isSubClassOf("NoCapture")) {
599f22ef01cSRoman Divacky       unsigned ArgNo = Property->getValueAsInt("ArgNo");
600f22ef01cSRoman Divacky       ArgumentAttributes.push_back(std::make_pair(ArgNo, NoCapture));
6013ca95b02SDimitry Andric     } else if (Property->isSubClassOf("Returned")) {
6023ca95b02SDimitry Andric       unsigned ArgNo = Property->getValueAsInt("ArgNo");
6033ca95b02SDimitry Andric       ArgumentAttributes.push_back(std::make_pair(ArgNo, Returned));
604f785676fSDimitry Andric     } else if (Property->isSubClassOf("ReadOnly")) {
605f785676fSDimitry Andric       unsigned ArgNo = Property->getValueAsInt("ArgNo");
606f785676fSDimitry Andric       ArgumentAttributes.push_back(std::make_pair(ArgNo, ReadOnly));
6073ca95b02SDimitry Andric     } else if (Property->isSubClassOf("WriteOnly")) {
6083ca95b02SDimitry Andric       unsigned ArgNo = Property->getValueAsInt("ArgNo");
6093ca95b02SDimitry Andric       ArgumentAttributes.push_back(std::make_pair(ArgNo, WriteOnly));
610f785676fSDimitry Andric     } else if (Property->isSubClassOf("ReadNone")) {
611f785676fSDimitry Andric       unsigned ArgNo = Property->getValueAsInt("ArgNo");
612f785676fSDimitry Andric       ArgumentAttributes.push_back(std::make_pair(ArgNo, ReadNone));
613f22ef01cSRoman Divacky     } else
614dff0c46cSDimitry Andric       llvm_unreachable("Unknown property!");
615f22ef01cSRoman Divacky   }
616bd5abe19SDimitry Andric 
617bd5abe19SDimitry Andric   // Sort the argument attributes for later benefit.
618bd5abe19SDimitry Andric   std::sort(ArgumentAttributes.begin(), ArgumentAttributes.end());
619f22ef01cSRoman Divacky }
620