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 42f22ef01cSRoman Divacky std::string 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 51f22ef01cSRoman Divacky std::string 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"; 60f22ef01cSRoman Divacky case MVT::iAny: return "MVT::iAny"; 61f22ef01cSRoman Divacky case MVT::fAny: return "MVT::fAny"; 62f22ef01cSRoman Divacky case MVT::vAny: return "MVT::vAny"; 63dff0c46cSDimitry Andric case MVT::f16: return "MVT::f16"; 64f22ef01cSRoman Divacky case MVT::f32: return "MVT::f32"; 65f22ef01cSRoman Divacky case MVT::f64: return "MVT::f64"; 66f22ef01cSRoman Divacky case MVT::f80: return "MVT::f80"; 67f22ef01cSRoman Divacky case MVT::f128: return "MVT::f128"; 68f22ef01cSRoman Divacky case MVT::ppcf128: return "MVT::ppcf128"; 692754fe60SDimitry Andric case MVT::x86mmx: return "MVT::x86mmx"; 702754fe60SDimitry Andric case MVT::Glue: return "MVT::Glue"; 71f22ef01cSRoman Divacky case MVT::isVoid: return "MVT::isVoid"; 723861d79fSDimitry Andric case MVT::v2i1: return "MVT::v2i1"; 733861d79fSDimitry Andric case MVT::v4i1: return "MVT::v4i1"; 743861d79fSDimitry Andric case MVT::v8i1: return "MVT::v8i1"; 753861d79fSDimitry Andric case MVT::v16i1: return "MVT::v16i1"; 76139f7f9bSDimitry Andric case MVT::v32i1: return "MVT::v32i1"; 77139f7f9bSDimitry Andric case MVT::v64i1: return "MVT::v64i1"; 78f785676fSDimitry Andric case MVT::v1i8: return "MVT::v1i8"; 79f22ef01cSRoman Divacky case MVT::v2i8: return "MVT::v2i8"; 80f22ef01cSRoman Divacky case MVT::v4i8: return "MVT::v4i8"; 81f22ef01cSRoman Divacky case MVT::v8i8: return "MVT::v8i8"; 82f22ef01cSRoman Divacky case MVT::v16i8: return "MVT::v16i8"; 83f22ef01cSRoman Divacky case MVT::v32i8: return "MVT::v32i8"; 84139f7f9bSDimitry Andric case MVT::v64i8: return "MVT::v64i8"; 853861d79fSDimitry Andric case MVT::v1i16: return "MVT::v1i16"; 86f22ef01cSRoman Divacky case MVT::v2i16: return "MVT::v2i16"; 87f22ef01cSRoman Divacky case MVT::v4i16: return "MVT::v4i16"; 88f22ef01cSRoman Divacky case MVT::v8i16: return "MVT::v8i16"; 89f22ef01cSRoman Divacky case MVT::v16i16: return "MVT::v16i16"; 90139f7f9bSDimitry Andric case MVT::v32i16: return "MVT::v32i16"; 913861d79fSDimitry Andric case MVT::v1i32: return "MVT::v1i32"; 92f22ef01cSRoman Divacky case MVT::v2i32: return "MVT::v2i32"; 93f22ef01cSRoman Divacky case MVT::v4i32: return "MVT::v4i32"; 94f22ef01cSRoman Divacky case MVT::v8i32: return "MVT::v8i32"; 953861d79fSDimitry Andric case MVT::v16i32: return "MVT::v16i32"; 96f22ef01cSRoman Divacky case MVT::v1i64: return "MVT::v1i64"; 97f22ef01cSRoman Divacky case MVT::v2i64: return "MVT::v2i64"; 98f22ef01cSRoman Divacky case MVT::v4i64: return "MVT::v4i64"; 99f22ef01cSRoman Divacky case MVT::v8i64: return "MVT::v8i64"; 1003861d79fSDimitry Andric case MVT::v16i64: return "MVT::v16i64"; 101dff0c46cSDimitry Andric case MVT::v2f16: return "MVT::v2f16"; 102f785676fSDimitry Andric case MVT::v4f16: return "MVT::v4f16"; 103f785676fSDimitry Andric case MVT::v8f16: return "MVT::v8f16"; 104f785676fSDimitry Andric case MVT::v1f32: return "MVT::v1f32"; 105f22ef01cSRoman Divacky case MVT::v2f32: return "MVT::v2f32"; 106f22ef01cSRoman Divacky case MVT::v4f32: return "MVT::v4f32"; 107f22ef01cSRoman Divacky case MVT::v8f32: return "MVT::v8f32"; 108139f7f9bSDimitry Andric case MVT::v16f32: return "MVT::v16f32"; 109f785676fSDimitry Andric case MVT::v1f64: return "MVT::v1f64"; 110f22ef01cSRoman Divacky case MVT::v2f64: return "MVT::v2f64"; 111f22ef01cSRoman Divacky case MVT::v4f64: return "MVT::v4f64"; 112139f7f9bSDimitry Andric case MVT::v8f64: return "MVT::v8f64"; 113f22ef01cSRoman Divacky case MVT::Metadata: return "MVT::Metadata"; 114f22ef01cSRoman Divacky case MVT::iPTR: return "MVT::iPTR"; 115f22ef01cSRoman Divacky case MVT::iPTRAny: return "MVT::iPTRAny"; 116dff0c46cSDimitry Andric case MVT::Untyped: return "MVT::Untyped"; 117dff0c46cSDimitry Andric default: llvm_unreachable("ILLEGAL VALUE TYPE!"); 118f22ef01cSRoman Divacky } 119f22ef01cSRoman Divacky } 120f22ef01cSRoman Divacky 121f22ef01cSRoman Divacky /// getQualifiedName - Return the name of the specified record, with a 122f22ef01cSRoman Divacky /// namespace qualifier if the record contains one. 123f22ef01cSRoman Divacky /// 124f22ef01cSRoman Divacky std::string llvm::getQualifiedName(const Record *R) { 125bd5abe19SDimitry Andric std::string Namespace; 126bd5abe19SDimitry Andric if (R->getValue("Namespace")) 127bd5abe19SDimitry Andric Namespace = R->getValueAsString("Namespace"); 128f22ef01cSRoman Divacky if (Namespace.empty()) return R->getName(); 129f22ef01cSRoman Divacky return Namespace + "::" + R->getName(); 130f22ef01cSRoman Divacky } 131f22ef01cSRoman Divacky 132f22ef01cSRoman Divacky 133f22ef01cSRoman Divacky /// getTarget - Return the current instance of the Target class. 134f22ef01cSRoman Divacky /// 135bd5abe19SDimitry Andric CodeGenTarget::CodeGenTarget(RecordKeeper &records) 13691bc56edSDimitry Andric : Records(records), RegBank(nullptr), SchedModels(nullptr) { 137f22ef01cSRoman Divacky std::vector<Record*> Targets = Records.getAllDerivedDefinitions("Target"); 138f22ef01cSRoman Divacky if (Targets.size() == 0) 1393861d79fSDimitry Andric PrintFatalError("ERROR: No 'Target' subclasses defined!"); 140f22ef01cSRoman Divacky if (Targets.size() != 1) 1413861d79fSDimitry Andric PrintFatalError("ERROR: Multiple subclasses of Target defined!"); 142f22ef01cSRoman Divacky TargetRec = Targets[0]; 143f22ef01cSRoman Divacky } 144f22ef01cSRoman Divacky 1457ae0e2c9SDimitry Andric CodeGenTarget::~CodeGenTarget() { 14691bc56edSDimitry Andric DeleteContainerSeconds(Instructions); 1477ae0e2c9SDimitry Andric delete RegBank; 1487ae0e2c9SDimitry Andric delete SchedModels; 1497ae0e2c9SDimitry Andric } 150f22ef01cSRoman Divacky 151f22ef01cSRoman Divacky const std::string &CodeGenTarget::getName() const { 152f22ef01cSRoman Divacky return TargetRec->getName(); 153f22ef01cSRoman Divacky } 154f22ef01cSRoman Divacky 155f22ef01cSRoman Divacky std::string CodeGenTarget::getInstNamespace() const { 156f22ef01cSRoman Divacky for (inst_iterator i = inst_begin(), e = inst_end(); i != e; ++i) { 157f22ef01cSRoman Divacky // Make sure not to pick up "TargetOpcode" by accidentally getting 158f22ef01cSRoman Divacky // the namespace off the PHI instruction or something. 159f22ef01cSRoman Divacky if ((*i)->Namespace != "TargetOpcode") 160f22ef01cSRoman Divacky return (*i)->Namespace; 161f22ef01cSRoman Divacky } 162f22ef01cSRoman Divacky 163f22ef01cSRoman Divacky return ""; 164f22ef01cSRoman Divacky } 165f22ef01cSRoman Divacky 166f22ef01cSRoman Divacky Record *CodeGenTarget::getInstructionSet() const { 167f22ef01cSRoman Divacky return TargetRec->getValueAsDef("InstructionSet"); 168f22ef01cSRoman Divacky } 169f22ef01cSRoman Divacky 170f22ef01cSRoman Divacky 171f22ef01cSRoman Divacky /// getAsmParser - Return the AssemblyParser definition for this target. 172f22ef01cSRoman Divacky /// 173f22ef01cSRoman Divacky Record *CodeGenTarget::getAsmParser() const { 174f22ef01cSRoman Divacky std::vector<Record*> LI = TargetRec->getValueAsListOfDefs("AssemblyParsers"); 175f22ef01cSRoman Divacky if (AsmParserNum >= LI.size()) 17691bc56edSDimitry Andric PrintFatalError("Target does not have an AsmParser #" + 17791bc56edSDimitry Andric Twine(AsmParserNum) + "!"); 178f22ef01cSRoman Divacky return LI[AsmParserNum]; 179f22ef01cSRoman Divacky } 180f22ef01cSRoman Divacky 181dff0c46cSDimitry Andric /// getAsmParserVariant - Return the AssmblyParserVariant definition for 182dff0c46cSDimitry Andric /// this target. 183dff0c46cSDimitry Andric /// 184dff0c46cSDimitry Andric Record *CodeGenTarget::getAsmParserVariant(unsigned i) const { 185dff0c46cSDimitry Andric std::vector<Record*> LI = 186dff0c46cSDimitry Andric TargetRec->getValueAsListOfDefs("AssemblyParserVariants"); 187dff0c46cSDimitry Andric if (i >= LI.size()) 18891bc56edSDimitry Andric PrintFatalError("Target does not have an AsmParserVariant #" + Twine(i) + 18991bc56edSDimitry Andric "!"); 190dff0c46cSDimitry Andric return LI[i]; 191dff0c46cSDimitry Andric } 192dff0c46cSDimitry Andric 193dff0c46cSDimitry Andric /// getAsmParserVariantCount - Return the AssmblyParserVariant definition 194dff0c46cSDimitry Andric /// available for this target. 195dff0c46cSDimitry Andric /// 196dff0c46cSDimitry Andric unsigned CodeGenTarget::getAsmParserVariantCount() const { 197dff0c46cSDimitry Andric std::vector<Record*> LI = 198dff0c46cSDimitry Andric TargetRec->getValueAsListOfDefs("AssemblyParserVariants"); 199dff0c46cSDimitry Andric return LI.size(); 200dff0c46cSDimitry Andric } 201dff0c46cSDimitry Andric 202f22ef01cSRoman Divacky /// getAsmWriter - Return the AssemblyWriter definition for this target. 203f22ef01cSRoman Divacky /// 204f22ef01cSRoman Divacky Record *CodeGenTarget::getAsmWriter() const { 205f22ef01cSRoman Divacky std::vector<Record*> LI = TargetRec->getValueAsListOfDefs("AssemblyWriters"); 206f22ef01cSRoman Divacky if (AsmWriterNum >= LI.size()) 20791bc56edSDimitry Andric PrintFatalError("Target does not have an AsmWriter #" + 20891bc56edSDimitry Andric Twine(AsmWriterNum) + "!"); 209f22ef01cSRoman Divacky return LI[AsmWriterNum]; 210f22ef01cSRoman Divacky } 211f22ef01cSRoman Divacky 212bd5abe19SDimitry Andric CodeGenRegBank &CodeGenTarget::getRegBank() const { 213bd5abe19SDimitry Andric if (!RegBank) 214bd5abe19SDimitry Andric RegBank = new CodeGenRegBank(Records); 215bd5abe19SDimitry Andric return *RegBank; 216f22ef01cSRoman Divacky } 217f22ef01cSRoman Divacky 21817a519f9SDimitry Andric void CodeGenTarget::ReadRegAltNameIndices() const { 21917a519f9SDimitry Andric RegAltNameIndices = Records.getAllDerivedDefinitions("RegAltNameIndex"); 22017a519f9SDimitry Andric std::sort(RegAltNameIndices.begin(), RegAltNameIndices.end(), LessRecord()); 221f22ef01cSRoman Divacky } 222f22ef01cSRoman Divacky 2232754fe60SDimitry Andric /// getRegisterByName - If there is a register with the specific AsmName, 2242754fe60SDimitry Andric /// return it. 2252754fe60SDimitry Andric const CodeGenRegister *CodeGenTarget::getRegisterByName(StringRef Name) const { 2263861d79fSDimitry Andric const StringMap<CodeGenRegister*> &Regs = getRegBank().getRegistersByName(); 2273861d79fSDimitry Andric StringMap<CodeGenRegister*>::const_iterator I = Regs.find(Name); 2283861d79fSDimitry Andric if (I == Regs.end()) 22991bc56edSDimitry Andric return nullptr; 2303861d79fSDimitry Andric return I->second; 2312754fe60SDimitry Andric } 2322754fe60SDimitry Andric 233f22ef01cSRoman Divacky std::vector<MVT::SimpleValueType> CodeGenTarget:: 234f22ef01cSRoman Divacky getRegisterVTs(Record *R) const { 23517a519f9SDimitry Andric const CodeGenRegister *Reg = getRegBank().getReg(R); 236f22ef01cSRoman Divacky std::vector<MVT::SimpleValueType> Result; 2376122f3e6SDimitry Andric ArrayRef<CodeGenRegisterClass*> RCs = getRegBank().getRegClasses(); 238f22ef01cSRoman Divacky for (unsigned i = 0, e = RCs.size(); i != e; ++i) { 2396122f3e6SDimitry Andric const CodeGenRegisterClass &RC = *RCs[i]; 24017a519f9SDimitry Andric if (RC.contains(Reg)) { 241139f7f9bSDimitry Andric ArrayRef<MVT::SimpleValueType> InVTs = RC.getValueTypes(); 242f22ef01cSRoman Divacky Result.insert(Result.end(), InVTs.begin(), InVTs.end()); 243f22ef01cSRoman Divacky } 244f22ef01cSRoman Divacky } 245f22ef01cSRoman Divacky 246f22ef01cSRoman Divacky // Remove duplicates. 247f22ef01cSRoman Divacky array_pod_sort(Result.begin(), Result.end()); 248f22ef01cSRoman Divacky Result.erase(std::unique(Result.begin(), Result.end()), Result.end()); 249f22ef01cSRoman Divacky return Result; 250f22ef01cSRoman Divacky } 251f22ef01cSRoman Divacky 252f22ef01cSRoman Divacky 253f22ef01cSRoman Divacky void CodeGenTarget::ReadLegalValueTypes() const { 2546122f3e6SDimitry Andric ArrayRef<CodeGenRegisterClass*> RCs = getRegBank().getRegClasses(); 255f22ef01cSRoman Divacky for (unsigned i = 0, e = RCs.size(); i != e; ++i) 2566122f3e6SDimitry Andric for (unsigned ri = 0, re = RCs[i]->VTs.size(); ri != re; ++ri) 2576122f3e6SDimitry Andric LegalValueTypes.push_back(RCs[i]->VTs[ri]); 258f22ef01cSRoman Divacky 259f22ef01cSRoman Divacky // Remove duplicates. 260f22ef01cSRoman Divacky std::sort(LegalValueTypes.begin(), LegalValueTypes.end()); 261f22ef01cSRoman Divacky LegalValueTypes.erase(std::unique(LegalValueTypes.begin(), 262f22ef01cSRoman Divacky LegalValueTypes.end()), 263f22ef01cSRoman Divacky LegalValueTypes.end()); 264f22ef01cSRoman Divacky } 265f22ef01cSRoman Divacky 2667ae0e2c9SDimitry Andric CodeGenSchedModels &CodeGenTarget::getSchedModels() const { 2677ae0e2c9SDimitry Andric if (!SchedModels) 2687ae0e2c9SDimitry Andric SchedModels = new CodeGenSchedModels(Records, *this); 2697ae0e2c9SDimitry Andric return *SchedModels; 2707ae0e2c9SDimitry Andric } 271f22ef01cSRoman Divacky 272f22ef01cSRoman Divacky void CodeGenTarget::ReadInstructions() const { 273f22ef01cSRoman Divacky std::vector<Record*> Insts = Records.getAllDerivedDefinitions("Instruction"); 274f22ef01cSRoman Divacky if (Insts.size() <= 2) 2753861d79fSDimitry Andric PrintFatalError("No 'Instruction' subclasses defined!"); 276f22ef01cSRoman Divacky 277f22ef01cSRoman Divacky // Parse the instructions defined in the .td file. 2782754fe60SDimitry Andric for (unsigned i = 0, e = Insts.size(); i != e; ++i) 2792754fe60SDimitry Andric Instructions[Insts[i]] = new CodeGenInstruction(Insts[i]); 280f22ef01cSRoman Divacky } 281f22ef01cSRoman Divacky 282f22ef01cSRoman Divacky static const CodeGenInstruction * 283f22ef01cSRoman Divacky GetInstByName(const char *Name, 2842754fe60SDimitry Andric const DenseMap<const Record*, CodeGenInstruction*> &Insts, 2852754fe60SDimitry Andric RecordKeeper &Records) { 286f22ef01cSRoman Divacky const Record *Rec = Records.getDef(Name); 287f22ef01cSRoman Divacky 288f22ef01cSRoman Divacky DenseMap<const Record*, CodeGenInstruction*>::const_iterator 289f22ef01cSRoman Divacky I = Insts.find(Rec); 29091bc56edSDimitry Andric if (!Rec || I == Insts.end()) 29191bc56edSDimitry Andric PrintFatalError(Twine("Could not find '") + Name + "' instruction!"); 292f22ef01cSRoman Divacky return I->second; 293f22ef01cSRoman Divacky } 294f22ef01cSRoman Divacky 29591bc56edSDimitry Andric /// \brief Return all of the instructions defined by the target, ordered by 29691bc56edSDimitry Andric /// their enum value. 297f22ef01cSRoman Divacky void CodeGenTarget::ComputeInstrsByEnum() const { 298ffd1746dSEd Schouten // The ordering here must match the ordering in TargetOpcodes.h. 299f785676fSDimitry Andric static const char *const FixedInstrs[] = { 30091bc56edSDimitry Andric "PHI", "INLINEASM", "CFI_INSTRUCTION", "EH_LABEL", 30191bc56edSDimitry Andric "GC_LABEL", "KILL", "EXTRACT_SUBREG", "INSERT_SUBREG", 30291bc56edSDimitry Andric "IMPLICIT_DEF", "SUBREG_TO_REG", "COPY_TO_REGCLASS", "DBG_VALUE", 30391bc56edSDimitry Andric "REG_SEQUENCE", "COPY", "BUNDLE", "LIFETIME_START", 30491bc56edSDimitry Andric "LIFETIME_END", "STACKMAP", "PATCHPOINT", nullptr}; 305f22ef01cSRoman Divacky const DenseMap<const Record*, CodeGenInstruction*> &Insts = getInstructions(); 306ffd1746dSEd Schouten for (const char *const *p = FixedInstrs; *p; ++p) { 3072754fe60SDimitry Andric const CodeGenInstruction *Instr = GetInstByName(*p, Insts, Records); 308ffd1746dSEd Schouten assert(Instr && "Missing target independent instruction"); 309ffd1746dSEd Schouten assert(Instr->Namespace == "TargetOpcode" && "Bad namespace"); 310ffd1746dSEd Schouten InstrsByEnum.push_back(Instr); 311ffd1746dSEd Schouten } 312f22ef01cSRoman Divacky unsigned EndOfPredefines = InstrsByEnum.size(); 313f22ef01cSRoman Divacky 314f22ef01cSRoman Divacky for (DenseMap<const Record*, CodeGenInstruction*>::const_iterator 315f22ef01cSRoman Divacky I = Insts.begin(), E = Insts.end(); I != E; ++I) { 316f22ef01cSRoman Divacky const CodeGenInstruction *CGI = I->second; 317ffd1746dSEd Schouten if (CGI->Namespace != "TargetOpcode") 318f22ef01cSRoman Divacky InstrsByEnum.push_back(CGI); 319f22ef01cSRoman Divacky } 320f22ef01cSRoman Divacky 321ffd1746dSEd Schouten assert(InstrsByEnum.size() == Insts.size() && "Missing predefined instr"); 322ffd1746dSEd Schouten 323f22ef01cSRoman Divacky // All of the instructions are now in random order based on the map iteration. 324f22ef01cSRoman Divacky // Sort them by name. 325f22ef01cSRoman Divacky std::sort(InstrsByEnum.begin() + EndOfPredefines, InstrsByEnum.end(), 32691bc56edSDimitry Andric [](const CodeGenInstruction *Rec1, const CodeGenInstruction *Rec2) { 32791bc56edSDimitry Andric return Rec1->TheDef->getName() < Rec2->TheDef->getName(); 32891bc56edSDimitry Andric }); 329f22ef01cSRoman Divacky } 330f22ef01cSRoman Divacky 331f22ef01cSRoman Divacky 332f22ef01cSRoman Divacky /// isLittleEndianEncoding - Return whether this target encodes its instruction 333f22ef01cSRoman Divacky /// in little-endian format, i.e. bits laid out in the order [0..n] 334f22ef01cSRoman Divacky /// 335f22ef01cSRoman Divacky bool CodeGenTarget::isLittleEndianEncoding() const { 336f22ef01cSRoman Divacky return getInstructionSet()->getValueAsBit("isLittleEndianEncoding"); 337f22ef01cSRoman Divacky } 338f22ef01cSRoman Divacky 33991bc56edSDimitry Andric /// reverseBitsForLittleEndianEncoding - For little-endian instruction bit 34091bc56edSDimitry Andric /// encodings, reverse the bit order of all instructions. 34191bc56edSDimitry Andric void CodeGenTarget::reverseBitsForLittleEndianEncoding() { 34291bc56edSDimitry Andric if (!isLittleEndianEncoding()) 34391bc56edSDimitry Andric return; 34491bc56edSDimitry Andric 34591bc56edSDimitry Andric std::vector<Record*> Insts = Records.getAllDerivedDefinitions("Instruction"); 34691bc56edSDimitry Andric for (std::vector<Record*>::iterator I = Insts.begin(), E = Insts.end(); 34791bc56edSDimitry Andric I != E; ++I) { 34891bc56edSDimitry Andric Record *R = *I; 34991bc56edSDimitry Andric if (R->getValueAsString("Namespace") == "TargetOpcode" || 35091bc56edSDimitry Andric R->getValueAsBit("isPseudo")) 35191bc56edSDimitry Andric continue; 35291bc56edSDimitry Andric 35391bc56edSDimitry Andric BitsInit *BI = R->getValueAsBitsInit("Inst"); 35491bc56edSDimitry Andric 35591bc56edSDimitry Andric unsigned numBits = BI->getNumBits(); 35691bc56edSDimitry Andric 35791bc56edSDimitry Andric SmallVector<Init *, 16> NewBits(numBits); 35891bc56edSDimitry Andric 35991bc56edSDimitry Andric for (unsigned bit = 0, end = numBits / 2; bit != end; ++bit) { 36091bc56edSDimitry Andric unsigned bitSwapIdx = numBits - bit - 1; 36191bc56edSDimitry Andric Init *OrigBit = BI->getBit(bit); 36291bc56edSDimitry Andric Init *BitSwap = BI->getBit(bitSwapIdx); 36391bc56edSDimitry Andric NewBits[bit] = BitSwap; 36491bc56edSDimitry Andric NewBits[bitSwapIdx] = OrigBit; 36591bc56edSDimitry Andric } 36691bc56edSDimitry Andric if (numBits % 2) { 36791bc56edSDimitry Andric unsigned middle = (numBits + 1) / 2; 36891bc56edSDimitry Andric NewBits[middle] = BI->getBit(middle); 36991bc56edSDimitry Andric } 37091bc56edSDimitry Andric 37191bc56edSDimitry Andric BitsInit *NewBI = BitsInit::get(NewBits); 37291bc56edSDimitry Andric 37391bc56edSDimitry Andric // Update the bits in reversed order so that emitInstrOpBits will get the 37491bc56edSDimitry Andric // correct endianness. 37591bc56edSDimitry Andric R->getValue("Inst")->setValue(NewBI); 37691bc56edSDimitry Andric } 37791bc56edSDimitry Andric } 37891bc56edSDimitry Andric 3793861d79fSDimitry Andric /// guessInstructionProperties - Return true if it's OK to guess instruction 3803861d79fSDimitry Andric /// properties instead of raising an error. 3813861d79fSDimitry Andric /// 3823861d79fSDimitry Andric /// This is configurable as a temporary migration aid. It will eventually be 3833861d79fSDimitry Andric /// permanently false. 3843861d79fSDimitry Andric bool CodeGenTarget::guessInstructionProperties() const { 3853861d79fSDimitry Andric return getInstructionSet()->getValueAsBit("guessInstructionProperties"); 3863861d79fSDimitry Andric } 3873861d79fSDimitry Andric 388f22ef01cSRoman Divacky //===----------------------------------------------------------------------===// 389f22ef01cSRoman Divacky // ComplexPattern implementation 390f22ef01cSRoman Divacky // 391f22ef01cSRoman Divacky ComplexPattern::ComplexPattern(Record *R) { 392f22ef01cSRoman Divacky Ty = ::getValueType(R->getValueAsDef("Ty")); 393f22ef01cSRoman Divacky NumOperands = R->getValueAsInt("NumOperands"); 394f22ef01cSRoman Divacky SelectFunc = R->getValueAsString("SelectFunc"); 395f22ef01cSRoman Divacky RootNodes = R->getValueAsListOfDefs("RootNodes"); 396f22ef01cSRoman Divacky 397f22ef01cSRoman Divacky // Parse the properties. 398f22ef01cSRoman Divacky Properties = 0; 399f22ef01cSRoman Divacky std::vector<Record*> PropList = R->getValueAsListOfDefs("Properties"); 400f22ef01cSRoman Divacky for (unsigned i = 0, e = PropList.size(); i != e; ++i) 401f22ef01cSRoman Divacky if (PropList[i]->getName() == "SDNPHasChain") { 402f22ef01cSRoman Divacky Properties |= 1 << SDNPHasChain; 4032754fe60SDimitry Andric } else if (PropList[i]->getName() == "SDNPOptInGlue") { 4042754fe60SDimitry Andric Properties |= 1 << SDNPOptInGlue; 405f22ef01cSRoman Divacky } else if (PropList[i]->getName() == "SDNPMayStore") { 406f22ef01cSRoman Divacky Properties |= 1 << SDNPMayStore; 407f22ef01cSRoman Divacky } else if (PropList[i]->getName() == "SDNPMayLoad") { 408f22ef01cSRoman Divacky Properties |= 1 << SDNPMayLoad; 409f22ef01cSRoman Divacky } else if (PropList[i]->getName() == "SDNPSideEffect") { 410f22ef01cSRoman Divacky Properties |= 1 << SDNPSideEffect; 411f22ef01cSRoman Divacky } else if (PropList[i]->getName() == "SDNPMemOperand") { 412f22ef01cSRoman Divacky Properties |= 1 << SDNPMemOperand; 413f22ef01cSRoman Divacky } else if (PropList[i]->getName() == "SDNPVariadic") { 414f22ef01cSRoman Divacky Properties |= 1 << SDNPVariadic; 4152754fe60SDimitry Andric } else if (PropList[i]->getName() == "SDNPWantRoot") { 4162754fe60SDimitry Andric Properties |= 1 << SDNPWantRoot; 4172754fe60SDimitry Andric } else if (PropList[i]->getName() == "SDNPWantParent") { 4182754fe60SDimitry Andric Properties |= 1 << SDNPWantParent; 419f22ef01cSRoman Divacky } else { 420f22ef01cSRoman Divacky errs() << "Unsupported SD Node property '" << PropList[i]->getName() 421f22ef01cSRoman Divacky << "' on ComplexPattern '" << R->getName() << "'!\n"; 422f22ef01cSRoman Divacky exit(1); 423f22ef01cSRoman Divacky } 424f22ef01cSRoman Divacky } 425f22ef01cSRoman Divacky 426f22ef01cSRoman Divacky //===----------------------------------------------------------------------===// 427f22ef01cSRoman Divacky // CodeGenIntrinsic Implementation 428f22ef01cSRoman Divacky //===----------------------------------------------------------------------===// 429f22ef01cSRoman Divacky 430f22ef01cSRoman Divacky std::vector<CodeGenIntrinsic> llvm::LoadIntrinsics(const RecordKeeper &RC, 431f22ef01cSRoman Divacky bool TargetOnly) { 432f22ef01cSRoman Divacky std::vector<Record*> I = RC.getAllDerivedDefinitions("Intrinsic"); 433f22ef01cSRoman Divacky 434f22ef01cSRoman Divacky std::vector<CodeGenIntrinsic> Result; 435f22ef01cSRoman Divacky 436f22ef01cSRoman Divacky for (unsigned i = 0, e = I.size(); i != e; ++i) { 437f22ef01cSRoman Divacky bool isTarget = I[i]->getValueAsBit("isTarget"); 438f22ef01cSRoman Divacky if (isTarget == TargetOnly) 439f22ef01cSRoman Divacky Result.push_back(CodeGenIntrinsic(I[i])); 440f22ef01cSRoman Divacky } 441f22ef01cSRoman Divacky return Result; 442f22ef01cSRoman Divacky } 443f22ef01cSRoman Divacky 444f22ef01cSRoman Divacky CodeGenIntrinsic::CodeGenIntrinsic(Record *R) { 445f22ef01cSRoman Divacky TheDef = R; 446f22ef01cSRoman Divacky std::string DefName = R->getName(); 447e580952dSDimitry Andric ModRef = ReadWriteMem; 448f22ef01cSRoman Divacky isOverloaded = false; 449f22ef01cSRoman Divacky isCommutative = false; 450bd5abe19SDimitry Andric canThrow = false; 4517ae0e2c9SDimitry Andric isNoReturn = false; 45291bc56edSDimitry Andric isNoDuplicate = false; 453f22ef01cSRoman Divacky 454f22ef01cSRoman Divacky if (DefName.size() <= 4 || 455f22ef01cSRoman Divacky std::string(DefName.begin(), DefName.begin() + 4) != "int_") 4563861d79fSDimitry Andric PrintFatalError("Intrinsic '" + DefName + "' does not start with 'int_'!"); 457f22ef01cSRoman Divacky 458f22ef01cSRoman Divacky EnumName = std::string(DefName.begin()+4, DefName.end()); 459f22ef01cSRoman Divacky 460f22ef01cSRoman Divacky if (R->getValue("GCCBuiltinName")) // Ignore a missing GCCBuiltinName field. 461f22ef01cSRoman Divacky GCCBuiltinName = R->getValueAsString("GCCBuiltinName"); 46291bc56edSDimitry Andric if (R->getValue("MSBuiltinName")) // Ignore a missing MSBuiltinName field. 46391bc56edSDimitry Andric MSBuiltinName = R->getValueAsString("MSBuiltinName"); 464f22ef01cSRoman Divacky 465f22ef01cSRoman Divacky TargetPrefix = R->getValueAsString("TargetPrefix"); 466f22ef01cSRoman Divacky Name = R->getValueAsString("LLVMName"); 467f22ef01cSRoman Divacky 468f22ef01cSRoman Divacky if (Name == "") { 469f22ef01cSRoman Divacky // If an explicit name isn't specified, derive one from the DefName. 470f22ef01cSRoman Divacky Name = "llvm."; 471f22ef01cSRoman Divacky 472f22ef01cSRoman Divacky for (unsigned i = 0, e = EnumName.size(); i != e; ++i) 473f22ef01cSRoman Divacky Name += (EnumName[i] == '_') ? '.' : EnumName[i]; 474f22ef01cSRoman Divacky } else { 475f22ef01cSRoman Divacky // Verify it starts with "llvm.". 476f22ef01cSRoman Divacky if (Name.size() <= 5 || 477f22ef01cSRoman Divacky std::string(Name.begin(), Name.begin() + 5) != "llvm.") 4783861d79fSDimitry Andric PrintFatalError("Intrinsic '" + DefName + "'s name does not start with 'llvm.'!"); 479f22ef01cSRoman Divacky } 480f22ef01cSRoman Divacky 481f22ef01cSRoman Divacky // If TargetPrefix is specified, make sure that Name starts with 482f22ef01cSRoman Divacky // "llvm.<targetprefix>.". 483f22ef01cSRoman Divacky if (!TargetPrefix.empty()) { 484f22ef01cSRoman Divacky if (Name.size() < 6+TargetPrefix.size() || 485f22ef01cSRoman Divacky std::string(Name.begin() + 5, Name.begin() + 6 + TargetPrefix.size()) 486f22ef01cSRoman Divacky != (TargetPrefix + ".")) 4873861d79fSDimitry Andric PrintFatalError("Intrinsic '" + DefName + "' does not start with 'llvm." + 4883861d79fSDimitry Andric TargetPrefix + ".'!"); 489f22ef01cSRoman Divacky } 490f22ef01cSRoman Divacky 491f22ef01cSRoman Divacky // Parse the list of return types. 492f22ef01cSRoman Divacky std::vector<MVT::SimpleValueType> OverloadedVTs; 493f22ef01cSRoman Divacky ListInit *TypeList = R->getValueAsListInit("RetTypes"); 494f22ef01cSRoman Divacky for (unsigned i = 0, e = TypeList->getSize(); i != e; ++i) { 495f22ef01cSRoman Divacky Record *TyEl = TypeList->getElementAsRecord(i); 496f22ef01cSRoman Divacky assert(TyEl->isSubClassOf("LLVMType") && "Expected a type!"); 497f22ef01cSRoman Divacky MVT::SimpleValueType VT; 498f22ef01cSRoman Divacky if (TyEl->isSubClassOf("LLVMMatchType")) { 499f22ef01cSRoman Divacky unsigned MatchTy = TyEl->getValueAsInt("Number"); 500f22ef01cSRoman Divacky assert(MatchTy < OverloadedVTs.size() && 501f22ef01cSRoman Divacky "Invalid matching number!"); 502f22ef01cSRoman Divacky VT = OverloadedVTs[MatchTy]; 503f22ef01cSRoman Divacky // It only makes sense to use the extended and truncated vector element 504f22ef01cSRoman Divacky // variants with iAny types; otherwise, if the intrinsic is not 505f22ef01cSRoman Divacky // overloaded, all the types can be specified directly. 50691bc56edSDimitry Andric assert(((!TyEl->isSubClassOf("LLVMExtendedType") && 50791bc56edSDimitry Andric !TyEl->isSubClassOf("LLVMTruncatedType")) || 508f22ef01cSRoman Divacky VT == MVT::iAny || VT == MVT::vAny) && 509f22ef01cSRoman Divacky "Expected iAny or vAny type"); 510f22ef01cSRoman Divacky } else { 511f22ef01cSRoman Divacky VT = getValueType(TyEl->getValueAsDef("VT")); 512f22ef01cSRoman Divacky } 51391bc56edSDimitry Andric if (MVT(VT).isOverloaded()) { 514f22ef01cSRoman Divacky OverloadedVTs.push_back(VT); 515f22ef01cSRoman Divacky isOverloaded = true; 516f22ef01cSRoman Divacky } 517f22ef01cSRoman Divacky 518f22ef01cSRoman Divacky // Reject invalid types. 519f22ef01cSRoman Divacky if (VT == MVT::isVoid) 5203861d79fSDimitry Andric PrintFatalError("Intrinsic '" + DefName + " has void in result type list!"); 521f22ef01cSRoman Divacky 522f22ef01cSRoman Divacky IS.RetVTs.push_back(VT); 523f22ef01cSRoman Divacky IS.RetTypeDefs.push_back(TyEl); 524f22ef01cSRoman Divacky } 525f22ef01cSRoman Divacky 526f22ef01cSRoman Divacky // Parse the list of parameter types. 527f22ef01cSRoman Divacky TypeList = R->getValueAsListInit("ParamTypes"); 528f22ef01cSRoman Divacky for (unsigned i = 0, e = TypeList->getSize(); i != e; ++i) { 529f22ef01cSRoman Divacky Record *TyEl = TypeList->getElementAsRecord(i); 530f22ef01cSRoman Divacky assert(TyEl->isSubClassOf("LLVMType") && "Expected a type!"); 531f22ef01cSRoman Divacky MVT::SimpleValueType VT; 532f22ef01cSRoman Divacky if (TyEl->isSubClassOf("LLVMMatchType")) { 533f22ef01cSRoman Divacky unsigned MatchTy = TyEl->getValueAsInt("Number"); 534f22ef01cSRoman Divacky assert(MatchTy < OverloadedVTs.size() && 535f22ef01cSRoman Divacky "Invalid matching number!"); 536f22ef01cSRoman Divacky VT = OverloadedVTs[MatchTy]; 537f22ef01cSRoman Divacky // It only makes sense to use the extended and truncated vector element 538f22ef01cSRoman Divacky // variants with iAny types; otherwise, if the intrinsic is not 539f22ef01cSRoman Divacky // overloaded, all the types can be specified directly. 54091bc56edSDimitry Andric assert(((!TyEl->isSubClassOf("LLVMExtendedType") && 54191bc56edSDimitry Andric !TyEl->isSubClassOf("LLVMTruncatedType")) || 542f22ef01cSRoman Divacky VT == MVT::iAny || VT == MVT::vAny) && 543f22ef01cSRoman Divacky "Expected iAny or vAny type"); 544f22ef01cSRoman Divacky } else 545f22ef01cSRoman Divacky VT = getValueType(TyEl->getValueAsDef("VT")); 546f22ef01cSRoman Divacky 54791bc56edSDimitry Andric if (MVT(VT).isOverloaded()) { 548f22ef01cSRoman Divacky OverloadedVTs.push_back(VT); 549f22ef01cSRoman Divacky isOverloaded = true; 550f22ef01cSRoman Divacky } 551f22ef01cSRoman Divacky 552f22ef01cSRoman Divacky // Reject invalid types. 553f22ef01cSRoman Divacky if (VT == MVT::isVoid && i != e-1 /*void at end means varargs*/) 5543861d79fSDimitry Andric PrintFatalError("Intrinsic '" + DefName + " has void in result type list!"); 555f22ef01cSRoman Divacky 556f22ef01cSRoman Divacky IS.ParamVTs.push_back(VT); 557f22ef01cSRoman Divacky IS.ParamTypeDefs.push_back(TyEl); 558f22ef01cSRoman Divacky } 559f22ef01cSRoman Divacky 560f22ef01cSRoman Divacky // Parse the intrinsic properties. 561f22ef01cSRoman Divacky ListInit *PropList = R->getValueAsListInit("Properties"); 562f22ef01cSRoman Divacky for (unsigned i = 0, e = PropList->getSize(); i != e; ++i) { 563f22ef01cSRoman Divacky Record *Property = PropList->getElementAsRecord(i); 564f22ef01cSRoman Divacky assert(Property->isSubClassOf("IntrinsicProperty") && 565f22ef01cSRoman Divacky "Expected a property!"); 566f22ef01cSRoman Divacky 567f22ef01cSRoman Divacky if (Property->getName() == "IntrNoMem") 568f22ef01cSRoman Divacky ModRef = NoMem; 569f22ef01cSRoman Divacky else if (Property->getName() == "IntrReadArgMem") 570f22ef01cSRoman Divacky ModRef = ReadArgMem; 571f22ef01cSRoman Divacky else if (Property->getName() == "IntrReadMem") 572f22ef01cSRoman Divacky ModRef = ReadMem; 573e580952dSDimitry Andric else if (Property->getName() == "IntrReadWriteArgMem") 574e580952dSDimitry Andric ModRef = ReadWriteArgMem; 575f22ef01cSRoman Divacky else if (Property->getName() == "Commutative") 576f22ef01cSRoman Divacky isCommutative = true; 577bd5abe19SDimitry Andric else if (Property->getName() == "Throws") 578bd5abe19SDimitry Andric canThrow = true; 57991bc56edSDimitry Andric else if (Property->getName() == "IntrNoDuplicate") 58091bc56edSDimitry Andric isNoDuplicate = true; 5817ae0e2c9SDimitry Andric else if (Property->getName() == "IntrNoReturn") 5827ae0e2c9SDimitry Andric isNoReturn = true; 583f22ef01cSRoman Divacky else if (Property->isSubClassOf("NoCapture")) { 584f22ef01cSRoman Divacky unsigned ArgNo = Property->getValueAsInt("ArgNo"); 585f22ef01cSRoman Divacky ArgumentAttributes.push_back(std::make_pair(ArgNo, NoCapture)); 586f785676fSDimitry Andric } else if (Property->isSubClassOf("ReadOnly")) { 587f785676fSDimitry Andric unsigned ArgNo = Property->getValueAsInt("ArgNo"); 588f785676fSDimitry Andric ArgumentAttributes.push_back(std::make_pair(ArgNo, ReadOnly)); 589f785676fSDimitry Andric } else if (Property->isSubClassOf("ReadNone")) { 590f785676fSDimitry Andric unsigned ArgNo = Property->getValueAsInt("ArgNo"); 591f785676fSDimitry Andric ArgumentAttributes.push_back(std::make_pair(ArgNo, ReadNone)); 592f22ef01cSRoman Divacky } else 593dff0c46cSDimitry Andric llvm_unreachable("Unknown property!"); 594f22ef01cSRoman Divacky } 595bd5abe19SDimitry Andric 596bd5abe19SDimitry Andric // Sort the argument attributes for later benefit. 597bd5abe19SDimitry Andric std::sort(ArgumentAttributes.begin(), ArgumentAttributes.end()); 598f22ef01cSRoman Divacky } 599