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 13f22ef01cSRoman Divacky // classes throw exceptions on error conditions. 14f22ef01cSRoman Divacky // 15f22ef01cSRoman Divacky //===----------------------------------------------------------------------===// 16f22ef01cSRoman Divacky 17f22ef01cSRoman Divacky #include "CodeGenTarget.h" 18f22ef01cSRoman Divacky #include "CodeGenIntrinsics.h" 19f22ef01cSRoman Divacky #include "Record.h" 20f22ef01cSRoman Divacky #include "llvm/ADT/StringExtras.h" 21f22ef01cSRoman Divacky #include "llvm/ADT/STLExtras.h" 22f22ef01cSRoman Divacky #include "llvm/Support/CommandLine.h" 23f22ef01cSRoman Divacky #include <algorithm> 24f22ef01cSRoman Divacky using namespace llvm; 25f22ef01cSRoman Divacky 26f22ef01cSRoman Divacky static cl::opt<unsigned> 27f22ef01cSRoman Divacky AsmParserNum("asmparsernum", cl::init(0), 28f22ef01cSRoman Divacky cl::desc("Make -gen-asm-parser emit assembly parser #N")); 29f22ef01cSRoman Divacky 30f22ef01cSRoman Divacky static cl::opt<unsigned> 31f22ef01cSRoman Divacky AsmWriterNum("asmwriternum", cl::init(0), 32f22ef01cSRoman Divacky cl::desc("Make -gen-asm-writer emit assembly writer #N")); 33f22ef01cSRoman Divacky 34f22ef01cSRoman Divacky /// getValueType - Return the MVT::SimpleValueType that the specified TableGen 35f22ef01cSRoman Divacky /// record corresponds to. 36f22ef01cSRoman Divacky MVT::SimpleValueType llvm::getValueType(Record *Rec) { 37f22ef01cSRoman Divacky return (MVT::SimpleValueType)Rec->getValueAsInt("Value"); 38f22ef01cSRoman Divacky } 39f22ef01cSRoman Divacky 40f22ef01cSRoman Divacky std::string llvm::getName(MVT::SimpleValueType T) { 41f22ef01cSRoman Divacky switch (T) { 42f22ef01cSRoman Divacky case MVT::Other: return "UNKNOWN"; 43f22ef01cSRoman Divacky case MVT::iPTR: return "TLI.getPointerTy()"; 44f22ef01cSRoman Divacky case MVT::iPTRAny: return "TLI.getPointerTy()"; 45f22ef01cSRoman Divacky default: return getEnumName(T); 46f22ef01cSRoman Divacky } 47f22ef01cSRoman Divacky } 48f22ef01cSRoman Divacky 49f22ef01cSRoman Divacky std::string llvm::getEnumName(MVT::SimpleValueType T) { 50f22ef01cSRoman Divacky switch (T) { 51f22ef01cSRoman Divacky case MVT::Other: return "MVT::Other"; 52f22ef01cSRoman Divacky case MVT::i1: return "MVT::i1"; 53f22ef01cSRoman Divacky case MVT::i8: return "MVT::i8"; 54f22ef01cSRoman Divacky case MVT::i16: return "MVT::i16"; 55f22ef01cSRoman Divacky case MVT::i32: return "MVT::i32"; 56f22ef01cSRoman Divacky case MVT::i64: return "MVT::i64"; 57f22ef01cSRoman Divacky case MVT::i128: return "MVT::i128"; 58f22ef01cSRoman Divacky case MVT::iAny: return "MVT::iAny"; 59f22ef01cSRoman Divacky case MVT::fAny: return "MVT::fAny"; 60f22ef01cSRoman Divacky case MVT::vAny: return "MVT::vAny"; 61f22ef01cSRoman Divacky case MVT::f32: return "MVT::f32"; 62f22ef01cSRoman Divacky case MVT::f64: return "MVT::f64"; 63f22ef01cSRoman Divacky case MVT::f80: return "MVT::f80"; 64f22ef01cSRoman Divacky case MVT::f128: return "MVT::f128"; 65f22ef01cSRoman Divacky case MVT::ppcf128: return "MVT::ppcf128"; 66f22ef01cSRoman Divacky case MVT::Flag: return "MVT::Flag"; 67f22ef01cSRoman Divacky case MVT::isVoid:return "MVT::isVoid"; 68f22ef01cSRoman Divacky case MVT::v2i8: return "MVT::v2i8"; 69f22ef01cSRoman Divacky case MVT::v4i8: return "MVT::v4i8"; 70f22ef01cSRoman Divacky case MVT::v8i8: return "MVT::v8i8"; 71f22ef01cSRoman Divacky case MVT::v16i8: return "MVT::v16i8"; 72f22ef01cSRoman Divacky case MVT::v32i8: return "MVT::v32i8"; 73f22ef01cSRoman Divacky case MVT::v2i16: return "MVT::v2i16"; 74f22ef01cSRoman Divacky case MVT::v4i16: return "MVT::v4i16"; 75f22ef01cSRoman Divacky case MVT::v8i16: return "MVT::v8i16"; 76f22ef01cSRoman Divacky case MVT::v16i16: return "MVT::v16i16"; 77f22ef01cSRoman Divacky case MVT::v2i32: return "MVT::v2i32"; 78f22ef01cSRoman Divacky case MVT::v4i32: return "MVT::v4i32"; 79f22ef01cSRoman Divacky case MVT::v8i32: return "MVT::v8i32"; 80f22ef01cSRoman Divacky case MVT::v1i64: return "MVT::v1i64"; 81f22ef01cSRoman Divacky case MVT::v2i64: return "MVT::v2i64"; 82f22ef01cSRoman Divacky case MVT::v4i64: return "MVT::v4i64"; 83f22ef01cSRoman Divacky case MVT::v8i64: return "MVT::v8i64"; 84f22ef01cSRoman Divacky case MVT::v2f32: return "MVT::v2f32"; 85f22ef01cSRoman Divacky case MVT::v4f32: return "MVT::v4f32"; 86f22ef01cSRoman Divacky case MVT::v8f32: return "MVT::v8f32"; 87f22ef01cSRoman Divacky case MVT::v2f64: return "MVT::v2f64"; 88f22ef01cSRoman Divacky case MVT::v4f64: return "MVT::v4f64"; 89f22ef01cSRoman Divacky case MVT::Metadata: return "MVT::Metadata"; 90f22ef01cSRoman Divacky case MVT::iPTR: return "MVT::iPTR"; 91f22ef01cSRoman Divacky case MVT::iPTRAny: return "MVT::iPTRAny"; 92f22ef01cSRoman Divacky default: assert(0 && "ILLEGAL VALUE TYPE!"); return ""; 93f22ef01cSRoman Divacky } 94f22ef01cSRoman Divacky } 95f22ef01cSRoman Divacky 96f22ef01cSRoman Divacky /// getQualifiedName - Return the name of the specified record, with a 97f22ef01cSRoman Divacky /// namespace qualifier if the record contains one. 98f22ef01cSRoman Divacky /// 99f22ef01cSRoman Divacky std::string llvm::getQualifiedName(const Record *R) { 100f22ef01cSRoman Divacky std::string Namespace = R->getValueAsString("Namespace"); 101f22ef01cSRoman Divacky if (Namespace.empty()) return R->getName(); 102f22ef01cSRoman Divacky return Namespace + "::" + R->getName(); 103f22ef01cSRoman Divacky } 104f22ef01cSRoman Divacky 105f22ef01cSRoman Divacky 106f22ef01cSRoman Divacky 107f22ef01cSRoman Divacky 108f22ef01cSRoman Divacky /// getTarget - Return the current instance of the Target class. 109f22ef01cSRoman Divacky /// 110f22ef01cSRoman Divacky CodeGenTarget::CodeGenTarget() { 111f22ef01cSRoman Divacky std::vector<Record*> Targets = Records.getAllDerivedDefinitions("Target"); 112f22ef01cSRoman Divacky if (Targets.size() == 0) 113f22ef01cSRoman Divacky throw std::string("ERROR: No 'Target' subclasses defined!"); 114f22ef01cSRoman Divacky if (Targets.size() != 1) 115f22ef01cSRoman Divacky throw std::string("ERROR: Multiple subclasses of Target defined!"); 116f22ef01cSRoman Divacky TargetRec = Targets[0]; 117f22ef01cSRoman Divacky } 118f22ef01cSRoman Divacky 119f22ef01cSRoman Divacky 120f22ef01cSRoman Divacky const std::string &CodeGenTarget::getName() const { 121f22ef01cSRoman Divacky return TargetRec->getName(); 122f22ef01cSRoman Divacky } 123f22ef01cSRoman Divacky 124f22ef01cSRoman Divacky std::string CodeGenTarget::getInstNamespace() const { 125f22ef01cSRoman Divacky for (inst_iterator i = inst_begin(), e = inst_end(); i != e; ++i) { 126f22ef01cSRoman Divacky // Make sure not to pick up "TargetOpcode" by accidentally getting 127f22ef01cSRoman Divacky // the namespace off the PHI instruction or something. 128f22ef01cSRoman Divacky if ((*i)->Namespace != "TargetOpcode") 129f22ef01cSRoman Divacky return (*i)->Namespace; 130f22ef01cSRoman Divacky } 131f22ef01cSRoman Divacky 132f22ef01cSRoman Divacky return ""; 133f22ef01cSRoman Divacky } 134f22ef01cSRoman Divacky 135f22ef01cSRoman Divacky Record *CodeGenTarget::getInstructionSet() const { 136f22ef01cSRoman Divacky return TargetRec->getValueAsDef("InstructionSet"); 137f22ef01cSRoman Divacky } 138f22ef01cSRoman Divacky 139f22ef01cSRoman Divacky 140f22ef01cSRoman Divacky /// getAsmParser - Return the AssemblyParser definition for this target. 141f22ef01cSRoman Divacky /// 142f22ef01cSRoman Divacky Record *CodeGenTarget::getAsmParser() const { 143f22ef01cSRoman Divacky std::vector<Record*> LI = TargetRec->getValueAsListOfDefs("AssemblyParsers"); 144f22ef01cSRoman Divacky if (AsmParserNum >= LI.size()) 145f22ef01cSRoman Divacky throw "Target does not have an AsmParser #" + utostr(AsmParserNum) + "!"; 146f22ef01cSRoman Divacky return LI[AsmParserNum]; 147f22ef01cSRoman Divacky } 148f22ef01cSRoman Divacky 149f22ef01cSRoman Divacky /// getAsmWriter - Return the AssemblyWriter definition for this target. 150f22ef01cSRoman Divacky /// 151f22ef01cSRoman Divacky Record *CodeGenTarget::getAsmWriter() const { 152f22ef01cSRoman Divacky std::vector<Record*> LI = TargetRec->getValueAsListOfDefs("AssemblyWriters"); 153f22ef01cSRoman Divacky if (AsmWriterNum >= LI.size()) 154f22ef01cSRoman Divacky throw "Target does not have an AsmWriter #" + utostr(AsmWriterNum) + "!"; 155f22ef01cSRoman Divacky return LI[AsmWriterNum]; 156f22ef01cSRoman Divacky } 157f22ef01cSRoman Divacky 158f22ef01cSRoman Divacky void CodeGenTarget::ReadRegisters() const { 159f22ef01cSRoman Divacky std::vector<Record*> Regs = Records.getAllDerivedDefinitions("Register"); 160f22ef01cSRoman Divacky if (Regs.empty()) 161f22ef01cSRoman Divacky throw std::string("No 'Register' subclasses defined!"); 162f22ef01cSRoman Divacky std::sort(Regs.begin(), Regs.end(), LessRecord()); 163f22ef01cSRoman Divacky 164f22ef01cSRoman Divacky Registers.reserve(Regs.size()); 165f22ef01cSRoman Divacky Registers.assign(Regs.begin(), Regs.end()); 166f22ef01cSRoman Divacky } 167f22ef01cSRoman Divacky 168f22ef01cSRoman Divacky CodeGenRegister::CodeGenRegister(Record *R) : TheDef(R) { 169f22ef01cSRoman Divacky DeclaredSpillSize = R->getValueAsInt("SpillSize"); 170f22ef01cSRoman Divacky DeclaredSpillAlignment = R->getValueAsInt("SpillAlignment"); 171f22ef01cSRoman Divacky } 172f22ef01cSRoman Divacky 173f22ef01cSRoman Divacky const std::string &CodeGenRegister::getName() const { 174f22ef01cSRoman Divacky return TheDef->getName(); 175f22ef01cSRoman Divacky } 176f22ef01cSRoman Divacky 177f22ef01cSRoman Divacky void CodeGenTarget::ReadSubRegIndices() const { 178f22ef01cSRoman Divacky SubRegIndices = Records.getAllDerivedDefinitions("SubRegIndex"); 179f22ef01cSRoman Divacky std::sort(SubRegIndices.begin(), SubRegIndices.end(), LessRecord()); 180f22ef01cSRoman Divacky } 181f22ef01cSRoman Divacky 182f22ef01cSRoman Divacky void CodeGenTarget::ReadRegisterClasses() const { 183f22ef01cSRoman Divacky std::vector<Record*> RegClasses = 184f22ef01cSRoman Divacky Records.getAllDerivedDefinitions("RegisterClass"); 185f22ef01cSRoman Divacky if (RegClasses.empty()) 186f22ef01cSRoman Divacky throw std::string("No 'RegisterClass' subclasses defined!"); 187f22ef01cSRoman Divacky 188f22ef01cSRoman Divacky RegisterClasses.reserve(RegClasses.size()); 189f22ef01cSRoman Divacky RegisterClasses.assign(RegClasses.begin(), RegClasses.end()); 190f22ef01cSRoman Divacky } 191f22ef01cSRoman Divacky 192f22ef01cSRoman Divacky std::vector<MVT::SimpleValueType> CodeGenTarget:: 193f22ef01cSRoman Divacky getRegisterVTs(Record *R) const { 194f22ef01cSRoman Divacky std::vector<MVT::SimpleValueType> Result; 195f22ef01cSRoman Divacky const std::vector<CodeGenRegisterClass> &RCs = getRegisterClasses(); 196f22ef01cSRoman Divacky for (unsigned i = 0, e = RCs.size(); i != e; ++i) { 197f22ef01cSRoman Divacky const CodeGenRegisterClass &RC = RegisterClasses[i]; 198f22ef01cSRoman Divacky for (unsigned ei = 0, ee = RC.Elements.size(); ei != ee; ++ei) { 199f22ef01cSRoman Divacky if (R == RC.Elements[ei]) { 200f22ef01cSRoman Divacky const std::vector<MVT::SimpleValueType> &InVTs = RC.getValueTypes(); 201f22ef01cSRoman Divacky Result.insert(Result.end(), InVTs.begin(), InVTs.end()); 202f22ef01cSRoman Divacky } 203f22ef01cSRoman Divacky } 204f22ef01cSRoman Divacky } 205f22ef01cSRoman Divacky 206f22ef01cSRoman Divacky // Remove duplicates. 207f22ef01cSRoman Divacky array_pod_sort(Result.begin(), Result.end()); 208f22ef01cSRoman Divacky Result.erase(std::unique(Result.begin(), Result.end()), Result.end()); 209f22ef01cSRoman Divacky return Result; 210f22ef01cSRoman Divacky } 211f22ef01cSRoman Divacky 212f22ef01cSRoman Divacky 213f22ef01cSRoman Divacky CodeGenRegisterClass::CodeGenRegisterClass(Record *R) : TheDef(R) { 214f22ef01cSRoman Divacky // Rename anonymous register classes. 215f22ef01cSRoman Divacky if (R->getName().size() > 9 && R->getName()[9] == '.') { 216f22ef01cSRoman Divacky static unsigned AnonCounter = 0; 217f22ef01cSRoman Divacky R->setName("AnonRegClass_"+utostr(AnonCounter++)); 218f22ef01cSRoman Divacky } 219f22ef01cSRoman Divacky 220f22ef01cSRoman Divacky std::vector<Record*> TypeList = R->getValueAsListOfDefs("RegTypes"); 221f22ef01cSRoman Divacky for (unsigned i = 0, e = TypeList.size(); i != e; ++i) { 222f22ef01cSRoman Divacky Record *Type = TypeList[i]; 223f22ef01cSRoman Divacky if (!Type->isSubClassOf("ValueType")) 224f22ef01cSRoman Divacky throw "RegTypes list member '" + Type->getName() + 225f22ef01cSRoman Divacky "' does not derive from the ValueType class!"; 226f22ef01cSRoman Divacky VTs.push_back(getValueType(Type)); 227f22ef01cSRoman Divacky } 228f22ef01cSRoman Divacky assert(!VTs.empty() && "RegisterClass must contain at least one ValueType!"); 229f22ef01cSRoman Divacky 230f22ef01cSRoman Divacky std::vector<Record*> RegList = R->getValueAsListOfDefs("MemberList"); 231f22ef01cSRoman Divacky for (unsigned i = 0, e = RegList.size(); i != e; ++i) { 232f22ef01cSRoman Divacky Record *Reg = RegList[i]; 233f22ef01cSRoman Divacky if (!Reg->isSubClassOf("Register")) 234f22ef01cSRoman Divacky throw "Register Class member '" + Reg->getName() + 235f22ef01cSRoman Divacky "' does not derive from the Register class!"; 236f22ef01cSRoman Divacky Elements.push_back(Reg); 237f22ef01cSRoman Divacky } 238f22ef01cSRoman Divacky 239f22ef01cSRoman Divacky // SubRegClasses is a list<dag> containing (RC, subregindex, ...) dags. 240f22ef01cSRoman Divacky ListInit *SRC = R->getValueAsListInit("SubRegClasses"); 241f22ef01cSRoman Divacky for (ListInit::const_iterator i = SRC->begin(), e = SRC->end(); i != e; ++i) { 242f22ef01cSRoman Divacky DagInit *DAG = dynamic_cast<DagInit*>(*i); 243f22ef01cSRoman Divacky if (!DAG) throw "SubRegClasses must contain DAGs"; 244f22ef01cSRoman Divacky DefInit *DAGOp = dynamic_cast<DefInit*>(DAG->getOperator()); 245f22ef01cSRoman Divacky Record *RCRec; 246f22ef01cSRoman Divacky if (!DAGOp || !(RCRec = DAGOp->getDef())->isSubClassOf("RegisterClass")) 247f22ef01cSRoman Divacky throw "Operator '" + DAG->getOperator()->getAsString() + 248f22ef01cSRoman Divacky "' in SubRegClasses is not a RegisterClass"; 249f22ef01cSRoman Divacky // Iterate over args, all SubRegIndex instances. 250f22ef01cSRoman Divacky for (DagInit::const_arg_iterator ai = DAG->arg_begin(), ae = DAG->arg_end(); 251f22ef01cSRoman Divacky ai != ae; ++ai) { 252f22ef01cSRoman Divacky DefInit *Idx = dynamic_cast<DefInit*>(*ai); 253f22ef01cSRoman Divacky Record *IdxRec; 254f22ef01cSRoman Divacky if (!Idx || !(IdxRec = Idx->getDef())->isSubClassOf("SubRegIndex")) 255f22ef01cSRoman Divacky throw "Argument '" + (*ai)->getAsString() + 256f22ef01cSRoman Divacky "' in SubRegClasses is not a SubRegIndex"; 257f22ef01cSRoman Divacky if (!SubRegClasses.insert(std::make_pair(IdxRec, RCRec)).second) 258f22ef01cSRoman Divacky throw "SubRegIndex '" + IdxRec->getName() + "' mentioned twice"; 259f22ef01cSRoman Divacky } 260f22ef01cSRoman Divacky } 261f22ef01cSRoman Divacky 262f22ef01cSRoman Divacky // Allow targets to override the size in bits of the RegisterClass. 263f22ef01cSRoman Divacky unsigned Size = R->getValueAsInt("Size"); 264f22ef01cSRoman Divacky 265f22ef01cSRoman Divacky Namespace = R->getValueAsString("Namespace"); 266f22ef01cSRoman Divacky SpillSize = Size ? Size : EVT(VTs[0]).getSizeInBits(); 267f22ef01cSRoman Divacky SpillAlignment = R->getValueAsInt("Alignment"); 268f22ef01cSRoman Divacky CopyCost = R->getValueAsInt("CopyCost"); 269f22ef01cSRoman Divacky MethodBodies = R->getValueAsCode("MethodBodies"); 270f22ef01cSRoman Divacky MethodProtos = R->getValueAsCode("MethodProtos"); 271f22ef01cSRoman Divacky } 272f22ef01cSRoman Divacky 273f22ef01cSRoman Divacky const std::string &CodeGenRegisterClass::getName() const { 274f22ef01cSRoman Divacky return TheDef->getName(); 275f22ef01cSRoman Divacky } 276f22ef01cSRoman Divacky 277f22ef01cSRoman Divacky void CodeGenTarget::ReadLegalValueTypes() const { 278f22ef01cSRoman Divacky const std::vector<CodeGenRegisterClass> &RCs = getRegisterClasses(); 279f22ef01cSRoman Divacky for (unsigned i = 0, e = RCs.size(); i != e; ++i) 280f22ef01cSRoman Divacky for (unsigned ri = 0, re = RCs[i].VTs.size(); ri != re; ++ri) 281f22ef01cSRoman Divacky LegalValueTypes.push_back(RCs[i].VTs[ri]); 282f22ef01cSRoman Divacky 283f22ef01cSRoman Divacky // Remove duplicates. 284f22ef01cSRoman Divacky std::sort(LegalValueTypes.begin(), LegalValueTypes.end()); 285f22ef01cSRoman Divacky LegalValueTypes.erase(std::unique(LegalValueTypes.begin(), 286f22ef01cSRoman Divacky LegalValueTypes.end()), 287f22ef01cSRoman Divacky LegalValueTypes.end()); 288f22ef01cSRoman Divacky } 289f22ef01cSRoman Divacky 290f22ef01cSRoman Divacky 291f22ef01cSRoman Divacky void CodeGenTarget::ReadInstructions() const { 292f22ef01cSRoman Divacky std::vector<Record*> Insts = Records.getAllDerivedDefinitions("Instruction"); 293f22ef01cSRoman Divacky if (Insts.size() <= 2) 294f22ef01cSRoman Divacky throw std::string("No 'Instruction' subclasses defined!"); 295f22ef01cSRoman Divacky 296f22ef01cSRoman Divacky // Parse the instructions defined in the .td file. 297f22ef01cSRoman Divacky std::string InstFormatName = 298f22ef01cSRoman Divacky getAsmWriter()->getValueAsString("InstFormatName"); 299f22ef01cSRoman Divacky 300f22ef01cSRoman Divacky for (unsigned i = 0, e = Insts.size(); i != e; ++i) { 301f22ef01cSRoman Divacky std::string AsmStr = Insts[i]->getValueAsString(InstFormatName); 302f22ef01cSRoman Divacky Instructions[Insts[i]] = new CodeGenInstruction(Insts[i], AsmStr); 303f22ef01cSRoman Divacky } 304f22ef01cSRoman Divacky } 305f22ef01cSRoman Divacky 306f22ef01cSRoman Divacky static const CodeGenInstruction * 307f22ef01cSRoman Divacky GetInstByName(const char *Name, 308f22ef01cSRoman Divacky const DenseMap<const Record*, CodeGenInstruction*> &Insts) { 309f22ef01cSRoman Divacky const Record *Rec = Records.getDef(Name); 310f22ef01cSRoman Divacky 311f22ef01cSRoman Divacky DenseMap<const Record*, CodeGenInstruction*>::const_iterator 312f22ef01cSRoman Divacky I = Insts.find(Rec); 313f22ef01cSRoman Divacky if (Rec == 0 || I == Insts.end()) 314f22ef01cSRoman Divacky throw std::string("Could not find '") + Name + "' instruction!"; 315f22ef01cSRoman Divacky return I->second; 316f22ef01cSRoman Divacky } 317f22ef01cSRoman Divacky 318f22ef01cSRoman Divacky namespace { 319f22ef01cSRoman Divacky /// SortInstByName - Sorting predicate to sort instructions by name. 320f22ef01cSRoman Divacky /// 321f22ef01cSRoman Divacky struct SortInstByName { 322f22ef01cSRoman Divacky bool operator()(const CodeGenInstruction *Rec1, 323f22ef01cSRoman Divacky const CodeGenInstruction *Rec2) const { 324f22ef01cSRoman Divacky return Rec1->TheDef->getName() < Rec2->TheDef->getName(); 325f22ef01cSRoman Divacky } 326f22ef01cSRoman Divacky }; 327f22ef01cSRoman Divacky } 328f22ef01cSRoman Divacky 329f22ef01cSRoman Divacky /// getInstructionsByEnumValue - Return all of the instructions defined by the 330f22ef01cSRoman Divacky /// target, ordered by their enum value. 331f22ef01cSRoman Divacky void CodeGenTarget::ComputeInstrsByEnum() const { 332ffd1746dSEd Schouten // The ordering here must match the ordering in TargetOpcodes.h. 333ffd1746dSEd Schouten const char *const FixedInstrs[] = { 334ffd1746dSEd Schouten "PHI", 335ffd1746dSEd Schouten "INLINEASM", 336ffd1746dSEd Schouten "DBG_LABEL", 337ffd1746dSEd Schouten "EH_LABEL", 338ffd1746dSEd Schouten "GC_LABEL", 339ffd1746dSEd Schouten "KILL", 340ffd1746dSEd Schouten "EXTRACT_SUBREG", 341ffd1746dSEd Schouten "INSERT_SUBREG", 342ffd1746dSEd Schouten "IMPLICIT_DEF", 343ffd1746dSEd Schouten "SUBREG_TO_REG", 344ffd1746dSEd Schouten "COPY_TO_REGCLASS", 345ffd1746dSEd Schouten "DBG_VALUE", 346ffd1746dSEd Schouten "REG_SEQUENCE", 347ffd1746dSEd Schouten "COPY", 348ffd1746dSEd Schouten 0 349ffd1746dSEd Schouten }; 350f22ef01cSRoman Divacky const DenseMap<const Record*, CodeGenInstruction*> &Insts = getInstructions(); 351ffd1746dSEd Schouten for (const char *const *p = FixedInstrs; *p; ++p) { 352ffd1746dSEd Schouten const CodeGenInstruction *Instr = GetInstByName(*p, Insts); 353ffd1746dSEd Schouten assert(Instr && "Missing target independent instruction"); 354ffd1746dSEd Schouten assert(Instr->Namespace == "TargetOpcode" && "Bad namespace"); 355ffd1746dSEd Schouten InstrsByEnum.push_back(Instr); 356ffd1746dSEd Schouten } 357f22ef01cSRoman Divacky unsigned EndOfPredefines = InstrsByEnum.size(); 358f22ef01cSRoman Divacky 359f22ef01cSRoman Divacky for (DenseMap<const Record*, CodeGenInstruction*>::const_iterator 360f22ef01cSRoman Divacky I = Insts.begin(), E = Insts.end(); I != E; ++I) { 361f22ef01cSRoman Divacky const CodeGenInstruction *CGI = I->second; 362ffd1746dSEd Schouten if (CGI->Namespace != "TargetOpcode") 363f22ef01cSRoman Divacky InstrsByEnum.push_back(CGI); 364f22ef01cSRoman Divacky } 365f22ef01cSRoman Divacky 366ffd1746dSEd Schouten assert(InstrsByEnum.size() == Insts.size() && "Missing predefined instr"); 367ffd1746dSEd Schouten 368f22ef01cSRoman Divacky // All of the instructions are now in random order based on the map iteration. 369f22ef01cSRoman Divacky // Sort them by name. 370f22ef01cSRoman Divacky std::sort(InstrsByEnum.begin()+EndOfPredefines, InstrsByEnum.end(), 371f22ef01cSRoman Divacky SortInstByName()); 372f22ef01cSRoman Divacky } 373f22ef01cSRoman Divacky 374f22ef01cSRoman Divacky 375f22ef01cSRoman Divacky /// isLittleEndianEncoding - Return whether this target encodes its instruction 376f22ef01cSRoman Divacky /// in little-endian format, i.e. bits laid out in the order [0..n] 377f22ef01cSRoman Divacky /// 378f22ef01cSRoman Divacky bool CodeGenTarget::isLittleEndianEncoding() const { 379f22ef01cSRoman Divacky return getInstructionSet()->getValueAsBit("isLittleEndianEncoding"); 380f22ef01cSRoman Divacky } 381f22ef01cSRoman Divacky 382f22ef01cSRoman Divacky //===----------------------------------------------------------------------===// 383f22ef01cSRoman Divacky // ComplexPattern implementation 384f22ef01cSRoman Divacky // 385f22ef01cSRoman Divacky ComplexPattern::ComplexPattern(Record *R) { 386f22ef01cSRoman Divacky Ty = ::getValueType(R->getValueAsDef("Ty")); 387f22ef01cSRoman Divacky NumOperands = R->getValueAsInt("NumOperands"); 388f22ef01cSRoman Divacky SelectFunc = R->getValueAsString("SelectFunc"); 389f22ef01cSRoman Divacky RootNodes = R->getValueAsListOfDefs("RootNodes"); 390f22ef01cSRoman Divacky 391f22ef01cSRoman Divacky // Parse the properties. 392f22ef01cSRoman Divacky Properties = 0; 393f22ef01cSRoman Divacky std::vector<Record*> PropList = R->getValueAsListOfDefs("Properties"); 394f22ef01cSRoman Divacky for (unsigned i = 0, e = PropList.size(); i != e; ++i) 395f22ef01cSRoman Divacky if (PropList[i]->getName() == "SDNPHasChain") { 396f22ef01cSRoman Divacky Properties |= 1 << SDNPHasChain; 397f22ef01cSRoman Divacky } else if (PropList[i]->getName() == "SDNPOptInFlag") { 398f22ef01cSRoman Divacky Properties |= 1 << SDNPOptInFlag; 399f22ef01cSRoman Divacky } else if (PropList[i]->getName() == "SDNPMayStore") { 400f22ef01cSRoman Divacky Properties |= 1 << SDNPMayStore; 401f22ef01cSRoman Divacky } else if (PropList[i]->getName() == "SDNPMayLoad") { 402f22ef01cSRoman Divacky Properties |= 1 << SDNPMayLoad; 403f22ef01cSRoman Divacky } else if (PropList[i]->getName() == "SDNPSideEffect") { 404f22ef01cSRoman Divacky Properties |= 1 << SDNPSideEffect; 405f22ef01cSRoman Divacky } else if (PropList[i]->getName() == "SDNPMemOperand") { 406f22ef01cSRoman Divacky Properties |= 1 << SDNPMemOperand; 407f22ef01cSRoman Divacky } else if (PropList[i]->getName() == "SDNPVariadic") { 408f22ef01cSRoman Divacky Properties |= 1 << SDNPVariadic; 409f22ef01cSRoman Divacky } else { 410f22ef01cSRoman Divacky errs() << "Unsupported SD Node property '" << PropList[i]->getName() 411f22ef01cSRoman Divacky << "' on ComplexPattern '" << R->getName() << "'!\n"; 412f22ef01cSRoman Divacky exit(1); 413f22ef01cSRoman Divacky } 414f22ef01cSRoman Divacky } 415f22ef01cSRoman Divacky 416f22ef01cSRoman Divacky //===----------------------------------------------------------------------===// 417f22ef01cSRoman Divacky // CodeGenIntrinsic Implementation 418f22ef01cSRoman Divacky //===----------------------------------------------------------------------===// 419f22ef01cSRoman Divacky 420f22ef01cSRoman Divacky std::vector<CodeGenIntrinsic> llvm::LoadIntrinsics(const RecordKeeper &RC, 421f22ef01cSRoman Divacky bool TargetOnly) { 422f22ef01cSRoman Divacky std::vector<Record*> I = RC.getAllDerivedDefinitions("Intrinsic"); 423f22ef01cSRoman Divacky 424f22ef01cSRoman Divacky std::vector<CodeGenIntrinsic> Result; 425f22ef01cSRoman Divacky 426f22ef01cSRoman Divacky for (unsigned i = 0, e = I.size(); i != e; ++i) { 427f22ef01cSRoman Divacky bool isTarget = I[i]->getValueAsBit("isTarget"); 428f22ef01cSRoman Divacky if (isTarget == TargetOnly) 429f22ef01cSRoman Divacky Result.push_back(CodeGenIntrinsic(I[i])); 430f22ef01cSRoman Divacky } 431f22ef01cSRoman Divacky return Result; 432f22ef01cSRoman Divacky } 433f22ef01cSRoman Divacky 434f22ef01cSRoman Divacky CodeGenIntrinsic::CodeGenIntrinsic(Record *R) { 435f22ef01cSRoman Divacky TheDef = R; 436f22ef01cSRoman Divacky std::string DefName = R->getName(); 437f22ef01cSRoman Divacky ModRef = WriteMem; 438f22ef01cSRoman Divacky isOverloaded = false; 439f22ef01cSRoman Divacky isCommutative = false; 440f22ef01cSRoman Divacky 441f22ef01cSRoman Divacky if (DefName.size() <= 4 || 442f22ef01cSRoman Divacky std::string(DefName.begin(), DefName.begin() + 4) != "int_") 443f22ef01cSRoman Divacky throw "Intrinsic '" + DefName + "' does not start with 'int_'!"; 444f22ef01cSRoman Divacky 445f22ef01cSRoman Divacky EnumName = std::string(DefName.begin()+4, DefName.end()); 446f22ef01cSRoman Divacky 447f22ef01cSRoman Divacky if (R->getValue("GCCBuiltinName")) // Ignore a missing GCCBuiltinName field. 448f22ef01cSRoman Divacky GCCBuiltinName = R->getValueAsString("GCCBuiltinName"); 449f22ef01cSRoman Divacky 450f22ef01cSRoman Divacky TargetPrefix = R->getValueAsString("TargetPrefix"); 451f22ef01cSRoman Divacky Name = R->getValueAsString("LLVMName"); 452f22ef01cSRoman Divacky 453f22ef01cSRoman Divacky if (Name == "") { 454f22ef01cSRoman Divacky // If an explicit name isn't specified, derive one from the DefName. 455f22ef01cSRoman Divacky Name = "llvm."; 456f22ef01cSRoman Divacky 457f22ef01cSRoman Divacky for (unsigned i = 0, e = EnumName.size(); i != e; ++i) 458f22ef01cSRoman Divacky Name += (EnumName[i] == '_') ? '.' : EnumName[i]; 459f22ef01cSRoman Divacky } else { 460f22ef01cSRoman Divacky // Verify it starts with "llvm.". 461f22ef01cSRoman Divacky if (Name.size() <= 5 || 462f22ef01cSRoman Divacky std::string(Name.begin(), Name.begin() + 5) != "llvm.") 463f22ef01cSRoman Divacky throw "Intrinsic '" + DefName + "'s name does not start with 'llvm.'!"; 464f22ef01cSRoman Divacky } 465f22ef01cSRoman Divacky 466f22ef01cSRoman Divacky // If TargetPrefix is specified, make sure that Name starts with 467f22ef01cSRoman Divacky // "llvm.<targetprefix>.". 468f22ef01cSRoman Divacky if (!TargetPrefix.empty()) { 469f22ef01cSRoman Divacky if (Name.size() < 6+TargetPrefix.size() || 470f22ef01cSRoman Divacky std::string(Name.begin() + 5, Name.begin() + 6 + TargetPrefix.size()) 471f22ef01cSRoman Divacky != (TargetPrefix + ".")) 472f22ef01cSRoman Divacky throw "Intrinsic '" + DefName + "' does not start with 'llvm." + 473f22ef01cSRoman Divacky TargetPrefix + ".'!"; 474f22ef01cSRoman Divacky } 475f22ef01cSRoman Divacky 476f22ef01cSRoman Divacky // Parse the list of return types. 477f22ef01cSRoman Divacky std::vector<MVT::SimpleValueType> OverloadedVTs; 478f22ef01cSRoman Divacky ListInit *TypeList = R->getValueAsListInit("RetTypes"); 479f22ef01cSRoman Divacky for (unsigned i = 0, e = TypeList->getSize(); i != e; ++i) { 480f22ef01cSRoman Divacky Record *TyEl = TypeList->getElementAsRecord(i); 481f22ef01cSRoman Divacky assert(TyEl->isSubClassOf("LLVMType") && "Expected a type!"); 482f22ef01cSRoman Divacky MVT::SimpleValueType VT; 483f22ef01cSRoman Divacky if (TyEl->isSubClassOf("LLVMMatchType")) { 484f22ef01cSRoman Divacky unsigned MatchTy = TyEl->getValueAsInt("Number"); 485f22ef01cSRoman Divacky assert(MatchTy < OverloadedVTs.size() && 486f22ef01cSRoman Divacky "Invalid matching number!"); 487f22ef01cSRoman Divacky VT = OverloadedVTs[MatchTy]; 488f22ef01cSRoman Divacky // It only makes sense to use the extended and truncated vector element 489f22ef01cSRoman Divacky // variants with iAny types; otherwise, if the intrinsic is not 490f22ef01cSRoman Divacky // overloaded, all the types can be specified directly. 491f22ef01cSRoman Divacky assert(((!TyEl->isSubClassOf("LLVMExtendedElementVectorType") && 492f22ef01cSRoman Divacky !TyEl->isSubClassOf("LLVMTruncatedElementVectorType")) || 493f22ef01cSRoman Divacky VT == MVT::iAny || VT == MVT::vAny) && 494f22ef01cSRoman Divacky "Expected iAny or vAny type"); 495f22ef01cSRoman Divacky } else { 496f22ef01cSRoman Divacky VT = getValueType(TyEl->getValueAsDef("VT")); 497f22ef01cSRoman Divacky } 498f22ef01cSRoman Divacky if (EVT(VT).isOverloaded()) { 499f22ef01cSRoman Divacky OverloadedVTs.push_back(VT); 500f22ef01cSRoman Divacky isOverloaded = true; 501f22ef01cSRoman Divacky } 502f22ef01cSRoman Divacky 503f22ef01cSRoman Divacky // Reject invalid types. 504f22ef01cSRoman Divacky if (VT == MVT::isVoid) 505f22ef01cSRoman Divacky throw "Intrinsic '" + DefName + " has void in result type list!"; 506f22ef01cSRoman Divacky 507f22ef01cSRoman Divacky IS.RetVTs.push_back(VT); 508f22ef01cSRoman Divacky IS.RetTypeDefs.push_back(TyEl); 509f22ef01cSRoman Divacky } 510f22ef01cSRoman Divacky 511f22ef01cSRoman Divacky // Parse the list of parameter types. 512f22ef01cSRoman Divacky TypeList = R->getValueAsListInit("ParamTypes"); 513f22ef01cSRoman Divacky for (unsigned i = 0, e = TypeList->getSize(); i != e; ++i) { 514f22ef01cSRoman Divacky Record *TyEl = TypeList->getElementAsRecord(i); 515f22ef01cSRoman Divacky assert(TyEl->isSubClassOf("LLVMType") && "Expected a type!"); 516f22ef01cSRoman Divacky MVT::SimpleValueType VT; 517f22ef01cSRoman Divacky if (TyEl->isSubClassOf("LLVMMatchType")) { 518f22ef01cSRoman Divacky unsigned MatchTy = TyEl->getValueAsInt("Number"); 519f22ef01cSRoman Divacky assert(MatchTy < OverloadedVTs.size() && 520f22ef01cSRoman Divacky "Invalid matching number!"); 521f22ef01cSRoman Divacky VT = OverloadedVTs[MatchTy]; 522f22ef01cSRoman Divacky // It only makes sense to use the extended and truncated vector element 523f22ef01cSRoman Divacky // variants with iAny types; otherwise, if the intrinsic is not 524f22ef01cSRoman Divacky // overloaded, all the types can be specified directly. 525f22ef01cSRoman Divacky assert(((!TyEl->isSubClassOf("LLVMExtendedElementVectorType") && 526f22ef01cSRoman Divacky !TyEl->isSubClassOf("LLVMTruncatedElementVectorType")) || 527f22ef01cSRoman Divacky VT == MVT::iAny || VT == MVT::vAny) && 528f22ef01cSRoman Divacky "Expected iAny or vAny type"); 529f22ef01cSRoman Divacky } else 530f22ef01cSRoman Divacky VT = getValueType(TyEl->getValueAsDef("VT")); 531f22ef01cSRoman Divacky 532f22ef01cSRoman Divacky if (EVT(VT).isOverloaded()) { 533f22ef01cSRoman Divacky OverloadedVTs.push_back(VT); 534f22ef01cSRoman Divacky isOverloaded = true; 535f22ef01cSRoman Divacky } 536f22ef01cSRoman Divacky 537f22ef01cSRoman Divacky // Reject invalid types. 538f22ef01cSRoman Divacky if (VT == MVT::isVoid && i != e-1 /*void at end means varargs*/) 539f22ef01cSRoman Divacky throw "Intrinsic '" + DefName + " has void in result type list!"; 540f22ef01cSRoman Divacky 541f22ef01cSRoman Divacky IS.ParamVTs.push_back(VT); 542f22ef01cSRoman Divacky IS.ParamTypeDefs.push_back(TyEl); 543f22ef01cSRoman Divacky } 544f22ef01cSRoman Divacky 545f22ef01cSRoman Divacky // Parse the intrinsic properties. 546f22ef01cSRoman Divacky ListInit *PropList = R->getValueAsListInit("Properties"); 547f22ef01cSRoman Divacky for (unsigned i = 0, e = PropList->getSize(); i != e; ++i) { 548f22ef01cSRoman Divacky Record *Property = PropList->getElementAsRecord(i); 549f22ef01cSRoman Divacky assert(Property->isSubClassOf("IntrinsicProperty") && 550f22ef01cSRoman Divacky "Expected a property!"); 551f22ef01cSRoman Divacky 552f22ef01cSRoman Divacky if (Property->getName() == "IntrNoMem") 553f22ef01cSRoman Divacky ModRef = NoMem; 554f22ef01cSRoman Divacky else if (Property->getName() == "IntrReadArgMem") 555f22ef01cSRoman Divacky ModRef = ReadArgMem; 556f22ef01cSRoman Divacky else if (Property->getName() == "IntrReadMem") 557f22ef01cSRoman Divacky ModRef = ReadMem; 558f22ef01cSRoman Divacky else if (Property->getName() == "IntrWriteArgMem") 559f22ef01cSRoman Divacky ModRef = WriteArgMem; 560f22ef01cSRoman Divacky else if (Property->getName() == "IntrWriteMem") 561f22ef01cSRoman Divacky ModRef = WriteMem; 562f22ef01cSRoman Divacky else if (Property->getName() == "Commutative") 563f22ef01cSRoman Divacky isCommutative = true; 564f22ef01cSRoman Divacky else if (Property->isSubClassOf("NoCapture")) { 565f22ef01cSRoman Divacky unsigned ArgNo = Property->getValueAsInt("ArgNo"); 566f22ef01cSRoman Divacky ArgumentAttributes.push_back(std::make_pair(ArgNo, NoCapture)); 567f22ef01cSRoman Divacky } else 568f22ef01cSRoman Divacky assert(0 && "Unknown property!"); 569f22ef01cSRoman Divacky } 570f22ef01cSRoman Divacky } 571