1193323Sed//===- CodeGenTarget.cpp - CodeGen Target Class Wrapper -------------------===// 2193323Sed// 3193323Sed// The LLVM Compiler Infrastructure 4193323Sed// 5193323Sed// This file is distributed under the University of Illinois Open Source 6193323Sed// License. See LICENSE.TXT for details. 7193323Sed// 8193323Sed//===----------------------------------------------------------------------===// 9193323Sed// 10193323Sed// This class wraps target description classes used by the various code 11193323Sed// generation TableGen backends. This makes it easier to access the data and 12193323Sed// provides a single place that needs to check it for validity. All of these 13245431Sdim// classes abort on error conditions. 14193323Sed// 15193323Sed//===----------------------------------------------------------------------===// 16193323Sed 17193323Sed#include "CodeGenTarget.h" 18193323Sed#include "CodeGenIntrinsics.h" 19245431Sdim#include "CodeGenSchedule.h" 20252723Sdim#include "llvm/ADT/STLExtras.h" 21252723Sdim#include "llvm/ADT/StringExtras.h" 22252723Sdim#include "llvm/Support/CommandLine.h" 23245431Sdim#include "llvm/TableGen/Error.h" 24226890Sdim#include "llvm/TableGen/Record.h" 25193323Sed#include <algorithm> 26193323Sedusing namespace llvm; 27193323Sed 28193323Sedstatic cl::opt<unsigned> 29198090SrdivackyAsmParserNum("asmparsernum", cl::init(0), 30198090Srdivacky cl::desc("Make -gen-asm-parser emit assembly parser #N")); 31198090Srdivacky 32198090Srdivackystatic cl::opt<unsigned> 33193323SedAsmWriterNum("asmwriternum", cl::init(0), 34193323Sed cl::desc("Make -gen-asm-writer emit assembly writer #N")); 35193323Sed 36193323Sed/// getValueType - Return the MVT::SimpleValueType that the specified TableGen 37193323Sed/// record corresponds to. 38193323SedMVT::SimpleValueType llvm::getValueType(Record *Rec) { 39193323Sed return (MVT::SimpleValueType)Rec->getValueAsInt("Value"); 40193323Sed} 41193323Sed 42193323Sedstd::string llvm::getName(MVT::SimpleValueType T) { 43193323Sed switch (T) { 44198090Srdivacky case MVT::Other: return "UNKNOWN"; 45198090Srdivacky case MVT::iPTR: return "TLI.getPointerTy()"; 46198090Srdivacky case MVT::iPTRAny: return "TLI.getPointerTy()"; 47198090Srdivacky default: return getEnumName(T); 48193323Sed } 49193323Sed} 50193323Sed 51193323Sedstd::string llvm::getEnumName(MVT::SimpleValueType T) { 52193323Sed switch (T) { 53218893Sdim case MVT::Other: return "MVT::Other"; 54218893Sdim case MVT::i1: return "MVT::i1"; 55218893Sdim case MVT::i8: return "MVT::i8"; 56218893Sdim case MVT::i16: return "MVT::i16"; 57218893Sdim case MVT::i32: return "MVT::i32"; 58218893Sdim case MVT::i64: return "MVT::i64"; 59218893Sdim case MVT::i128: return "MVT::i128"; 60218893Sdim case MVT::iAny: return "MVT::iAny"; 61218893Sdim case MVT::fAny: return "MVT::fAny"; 62218893Sdim case MVT::vAny: return "MVT::vAny"; 63235633Sdim case MVT::f16: return "MVT::f16"; 64218893Sdim case MVT::f32: return "MVT::f32"; 65218893Sdim case MVT::f64: return "MVT::f64"; 66218893Sdim case MVT::f80: return "MVT::f80"; 67218893Sdim case MVT::f128: return "MVT::f128"; 68193323Sed case MVT::ppcf128: return "MVT::ppcf128"; 69218893Sdim case MVT::x86mmx: return "MVT::x86mmx"; 70218893Sdim case MVT::Glue: return "MVT::Glue"; 71218893Sdim case MVT::isVoid: return "MVT::isVoid"; 72245431Sdim case MVT::v2i1: return "MVT::v2i1"; 73245431Sdim case MVT::v4i1: return "MVT::v4i1"; 74245431Sdim case MVT::v8i1: return "MVT::v8i1"; 75245431Sdim case MVT::v16i1: return "MVT::v16i1"; 76252723Sdim case MVT::v32i1: return "MVT::v32i1"; 77252723Sdim case MVT::v64i1: return "MVT::v64i1"; 78263509Sdim case MVT::v1i8: return "MVT::v1i8"; 79218893Sdim case MVT::v2i8: return "MVT::v2i8"; 80218893Sdim case MVT::v4i8: return "MVT::v4i8"; 81218893Sdim case MVT::v8i8: return "MVT::v8i8"; 82218893Sdim case MVT::v16i8: return "MVT::v16i8"; 83218893Sdim case MVT::v32i8: return "MVT::v32i8"; 84252723Sdim case MVT::v64i8: return "MVT::v64i8"; 85245431Sdim case MVT::v1i16: return "MVT::v1i16"; 86218893Sdim case MVT::v2i16: return "MVT::v2i16"; 87218893Sdim case MVT::v4i16: return "MVT::v4i16"; 88218893Sdim case MVT::v8i16: return "MVT::v8i16"; 89218893Sdim case MVT::v16i16: return "MVT::v16i16"; 90252723Sdim case MVT::v32i16: return "MVT::v32i16"; 91245431Sdim case MVT::v1i32: return "MVT::v1i32"; 92218893Sdim case MVT::v2i32: return "MVT::v2i32"; 93218893Sdim case MVT::v4i32: return "MVT::v4i32"; 94218893Sdim case MVT::v8i32: return "MVT::v8i32"; 95245431Sdim case MVT::v16i32: return "MVT::v16i32"; 96218893Sdim case MVT::v1i64: return "MVT::v1i64"; 97218893Sdim case MVT::v2i64: return "MVT::v2i64"; 98218893Sdim case MVT::v4i64: return "MVT::v4i64"; 99218893Sdim case MVT::v8i64: return "MVT::v8i64"; 100245431Sdim case MVT::v16i64: return "MVT::v16i64"; 101235633Sdim case MVT::v2f16: return "MVT::v2f16"; 102263509Sdim case MVT::v4f16: return "MVT::v4f16"; 103263509Sdim case MVT::v8f16: return "MVT::v8f16"; 104263509Sdim case MVT::v1f32: return "MVT::v1f32"; 105218893Sdim case MVT::v2f32: return "MVT::v2f32"; 106218893Sdim case MVT::v4f32: return "MVT::v4f32"; 107218893Sdim case MVT::v8f32: return "MVT::v8f32"; 108252723Sdim case MVT::v16f32: return "MVT::v16f32"; 109263509Sdim case MVT::v1f64: return "MVT::v1f64"; 110218893Sdim case MVT::v2f64: return "MVT::v2f64"; 111218893Sdim case MVT::v4f64: return "MVT::v4f64"; 112252723Sdim case MVT::v8f64: return "MVT::v8f64"; 113198090Srdivacky case MVT::Metadata: return "MVT::Metadata"; 114218893Sdim case MVT::iPTR: return "MVT::iPTR"; 115193323Sed case MVT::iPTRAny: return "MVT::iPTRAny"; 116235633Sdim case MVT::Untyped: return "MVT::Untyped"; 117235633Sdim default: llvm_unreachable("ILLEGAL VALUE TYPE!"); 118193323Sed } 119193323Sed} 120193323Sed 121193323Sed/// getQualifiedName - Return the name of the specified record, with a 122193323Sed/// namespace qualifier if the record contains one. 123193323Sed/// 124193323Sedstd::string llvm::getQualifiedName(const Record *R) { 125223017Sdim std::string Namespace; 126223017Sdim if (R->getValue("Namespace")) 127223017Sdim Namespace = R->getValueAsString("Namespace"); 128193323Sed if (Namespace.empty()) return R->getName(); 129193323Sed return Namespace + "::" + R->getName(); 130193323Sed} 131193323Sed 132193323Sed 133193323Sed/// getTarget - Return the current instance of the Target class. 134193323Sed/// 135223017SdimCodeGenTarget::CodeGenTarget(RecordKeeper &records) 136245431Sdim : Records(records), RegBank(0), SchedModels(0) { 137193323Sed std::vector<Record*> Targets = Records.getAllDerivedDefinitions("Target"); 138193323Sed if (Targets.size() == 0) 139245431Sdim PrintFatalError("ERROR: No 'Target' subclasses defined!"); 140193323Sed if (Targets.size() != 1) 141245431Sdim PrintFatalError("ERROR: Multiple subclasses of Target defined!"); 142193323Sed TargetRec = Targets[0]; 143193323Sed} 144193323Sed 145245431SdimCodeGenTarget::~CodeGenTarget() { 146245431Sdim delete RegBank; 147245431Sdim delete SchedModels; 148245431Sdim} 149193323Sed 150193323Sedconst std::string &CodeGenTarget::getName() const { 151193323Sed return TargetRec->getName(); 152193323Sed} 153193323Sed 154193323Sedstd::string CodeGenTarget::getInstNamespace() const { 155193323Sed for (inst_iterator i = inst_begin(), e = inst_end(); i != e; ++i) { 156205407Srdivacky // Make sure not to pick up "TargetOpcode" by accidentally getting 157193323Sed // the namespace off the PHI instruction or something. 158205407Srdivacky if ((*i)->Namespace != "TargetOpcode") 159205407Srdivacky return (*i)->Namespace; 160193323Sed } 161193323Sed 162205407Srdivacky return ""; 163193323Sed} 164193323Sed 165193323SedRecord *CodeGenTarget::getInstructionSet() const { 166193323Sed return TargetRec->getValueAsDef("InstructionSet"); 167193323Sed} 168193323Sed 169205407Srdivacky 170198090Srdivacky/// getAsmParser - Return the AssemblyParser definition for this target. 171198090Srdivacky/// 172198090SrdivackyRecord *CodeGenTarget::getAsmParser() const { 173198090Srdivacky std::vector<Record*> LI = TargetRec->getValueAsListOfDefs("AssemblyParsers"); 174198090Srdivacky if (AsmParserNum >= LI.size()) 175245431Sdim PrintFatalError("Target does not have an AsmParser #" + utostr(AsmParserNum) + "!"); 176198090Srdivacky return LI[AsmParserNum]; 177198090Srdivacky} 178198090Srdivacky 179235633Sdim/// getAsmParserVariant - Return the AssmblyParserVariant definition for 180235633Sdim/// this target. 181235633Sdim/// 182235633SdimRecord *CodeGenTarget::getAsmParserVariant(unsigned i) const { 183245431Sdim std::vector<Record*> LI = 184235633Sdim TargetRec->getValueAsListOfDefs("AssemblyParserVariants"); 185235633Sdim if (i >= LI.size()) 186245431Sdim PrintFatalError("Target does not have an AsmParserVariant #" + utostr(i) + "!"); 187235633Sdim return LI[i]; 188235633Sdim} 189235633Sdim 190245431Sdim/// getAsmParserVariantCount - Return the AssmblyParserVariant definition 191235633Sdim/// available for this target. 192235633Sdim/// 193235633Sdimunsigned CodeGenTarget::getAsmParserVariantCount() const { 194245431Sdim std::vector<Record*> LI = 195235633Sdim TargetRec->getValueAsListOfDefs("AssemblyParserVariants"); 196235633Sdim return LI.size(); 197235633Sdim} 198235633Sdim 199193323Sed/// getAsmWriter - Return the AssemblyWriter definition for this target. 200193323Sed/// 201193323SedRecord *CodeGenTarget::getAsmWriter() const { 202193323Sed std::vector<Record*> LI = TargetRec->getValueAsListOfDefs("AssemblyWriters"); 203193323Sed if (AsmWriterNum >= LI.size()) 204245431Sdim PrintFatalError("Target does not have an AsmWriter #" + utostr(AsmWriterNum) + "!"); 205193323Sed return LI[AsmWriterNum]; 206193323Sed} 207193323Sed 208223017SdimCodeGenRegBank &CodeGenTarget::getRegBank() const { 209223017Sdim if (!RegBank) 210223017Sdim RegBank = new CodeGenRegBank(Records); 211223017Sdim return *RegBank; 212193323Sed} 213193323Sed 214224145Sdimvoid CodeGenTarget::ReadRegAltNameIndices() const { 215224145Sdim RegAltNameIndices = Records.getAllDerivedDefinitions("RegAltNameIndex"); 216224145Sdim std::sort(RegAltNameIndices.begin(), RegAltNameIndices.end(), LessRecord()); 217193323Sed} 218193323Sed 219218893Sdim/// getRegisterByName - If there is a register with the specific AsmName, 220218893Sdim/// return it. 221218893Sdimconst CodeGenRegister *CodeGenTarget::getRegisterByName(StringRef Name) const { 222245431Sdim const StringMap<CodeGenRegister*> &Regs = getRegBank().getRegistersByName(); 223245431Sdim StringMap<CodeGenRegister*>::const_iterator I = Regs.find(Name); 224245431Sdim if (I == Regs.end()) 225245431Sdim return 0; 226245431Sdim return I->second; 227218893Sdim} 228218893Sdim 229205218Srdivackystd::vector<MVT::SimpleValueType> CodeGenTarget:: 230205218SrdivackygetRegisterVTs(Record *R) const { 231224145Sdim const CodeGenRegister *Reg = getRegBank().getReg(R); 232205218Srdivacky std::vector<MVT::SimpleValueType> Result; 233226890Sdim ArrayRef<CodeGenRegisterClass*> RCs = getRegBank().getRegClasses(); 234193323Sed for (unsigned i = 0, e = RCs.size(); i != e; ++i) { 235226890Sdim const CodeGenRegisterClass &RC = *RCs[i]; 236224145Sdim if (RC.contains(Reg)) { 237252723Sdim ArrayRef<MVT::SimpleValueType> InVTs = RC.getValueTypes(); 238224145Sdim Result.insert(Result.end(), InVTs.begin(), InVTs.end()); 239193323Sed } 240193323Sed } 241221345Sdim 242206083Srdivacky // Remove duplicates. 243206083Srdivacky array_pod_sort(Result.begin(), Result.end()); 244206083Srdivacky Result.erase(std::unique(Result.begin(), Result.end()), Result.end()); 245193323Sed return Result; 246193323Sed} 247193323Sed 248193323Sed 249193323Sedvoid CodeGenTarget::ReadLegalValueTypes() const { 250226890Sdim ArrayRef<CodeGenRegisterClass*> RCs = getRegBank().getRegClasses(); 251193323Sed for (unsigned i = 0, e = RCs.size(); i != e; ++i) 252226890Sdim for (unsigned ri = 0, re = RCs[i]->VTs.size(); ri != re; ++ri) 253226890Sdim LegalValueTypes.push_back(RCs[i]->VTs[ri]); 254221345Sdim 255193323Sed // Remove duplicates. 256193323Sed std::sort(LegalValueTypes.begin(), LegalValueTypes.end()); 257193323Sed LegalValueTypes.erase(std::unique(LegalValueTypes.begin(), 258193323Sed LegalValueTypes.end()), 259193323Sed LegalValueTypes.end()); 260193323Sed} 261193323Sed 262245431SdimCodeGenSchedModels &CodeGenTarget::getSchedModels() const { 263245431Sdim if (!SchedModels) 264245431Sdim SchedModels = new CodeGenSchedModels(Records, *this); 265245431Sdim return *SchedModels; 266245431Sdim} 267193323Sed 268193323Sedvoid CodeGenTarget::ReadInstructions() const { 269193323Sed std::vector<Record*> Insts = Records.getAllDerivedDefinitions("Instruction"); 270193323Sed if (Insts.size() <= 2) 271245431Sdim PrintFatalError("No 'Instruction' subclasses defined!"); 272193323Sed 273193323Sed // Parse the instructions defined in the .td file. 274218893Sdim for (unsigned i = 0, e = Insts.size(); i != e; ++i) 275218893Sdim Instructions[Insts[i]] = new CodeGenInstruction(Insts[i]); 276193323Sed} 277193323Sed 278205407Srdivackystatic const CodeGenInstruction * 279205407SrdivackyGetInstByName(const char *Name, 280221345Sdim const DenseMap<const Record*, CodeGenInstruction*> &Insts, 281218893Sdim RecordKeeper &Records) { 282205407Srdivacky const Record *Rec = Records.getDef(Name); 283221345Sdim 284205407Srdivacky DenseMap<const Record*, CodeGenInstruction*>::const_iterator 285205407Srdivacky I = Insts.find(Rec); 286205407Srdivacky if (Rec == 0 || I == Insts.end()) 287245431Sdim PrintFatalError(std::string("Could not find '") + Name + "' instruction!"); 288205407Srdivacky return I->second; 289205407Srdivacky} 290205407Srdivacky 291205407Srdivackynamespace { 292205407Srdivacky/// SortInstByName - Sorting predicate to sort instructions by name. 293205407Srdivacky/// 294205407Srdivackystruct SortInstByName { 295205407Srdivacky bool operator()(const CodeGenInstruction *Rec1, 296205407Srdivacky const CodeGenInstruction *Rec2) const { 297205407Srdivacky return Rec1->TheDef->getName() < Rec2->TheDef->getName(); 298205407Srdivacky } 299205407Srdivacky}; 300205407Srdivacky} 301205407Srdivacky 302193323Sed/// getInstructionsByEnumValue - Return all of the instructions defined by the 303193323Sed/// target, ordered by their enum value. 304205407Srdivackyvoid CodeGenTarget::ComputeInstrsByEnum() const { 305210299Sed // The ordering here must match the ordering in TargetOpcodes.h. 306263509Sdim static const char *const FixedInstrs[] = { 307210299Sed "PHI", 308210299Sed "INLINEASM", 309212904Sdim "PROLOG_LABEL", 310210299Sed "EH_LABEL", 311210299Sed "GC_LABEL", 312210299Sed "KILL", 313210299Sed "EXTRACT_SUBREG", 314210299Sed "INSERT_SUBREG", 315210299Sed "IMPLICIT_DEF", 316210299Sed "SUBREG_TO_REG", 317210299Sed "COPY_TO_REGCLASS", 318210299Sed "DBG_VALUE", 319210299Sed "REG_SEQUENCE", 320210299Sed "COPY", 321235633Sdim "BUNDLE", 322245431Sdim "LIFETIME_START", 323245431Sdim "LIFETIME_END", 324263509Sdim "STACKMAP", 325263509Sdim "PATCHPOINT", 326210299Sed 0 327210299Sed }; 328205407Srdivacky const DenseMap<const Record*, CodeGenInstruction*> &Insts = getInstructions(); 329210299Sed for (const char *const *p = FixedInstrs; *p; ++p) { 330218893Sdim const CodeGenInstruction *Instr = GetInstByName(*p, Insts, Records); 331210299Sed assert(Instr && "Missing target independent instruction"); 332210299Sed assert(Instr->Namespace == "TargetOpcode" && "Bad namespace"); 333210299Sed InstrsByEnum.push_back(Instr); 334210299Sed } 335210299Sed unsigned EndOfPredefines = InstrsByEnum.size(); 336205407Srdivacky 337205407Srdivacky for (DenseMap<const Record*, CodeGenInstruction*>::const_iterator 338205407Srdivacky I = Insts.begin(), E = Insts.end(); I != E; ++I) { 339205407Srdivacky const CodeGenInstruction *CGI = I->second; 340210299Sed if (CGI->Namespace != "TargetOpcode") 341205407Srdivacky InstrsByEnum.push_back(CGI); 342205407Srdivacky } 343210299Sed 344210299Sed assert(InstrsByEnum.size() == Insts.size() && "Missing predefined instr"); 345210299Sed 346205407Srdivacky // All of the instructions are now in random order based on the map iteration. 347205407Srdivacky // Sort them by name. 348205407Srdivacky std::sort(InstrsByEnum.begin()+EndOfPredefines, InstrsByEnum.end(), 349205407Srdivacky SortInstByName()); 350193323Sed} 351193323Sed 352193323Sed 353193323Sed/// isLittleEndianEncoding - Return whether this target encodes its instruction 354193323Sed/// in little-endian format, i.e. bits laid out in the order [0..n] 355193323Sed/// 356193323Sedbool CodeGenTarget::isLittleEndianEncoding() const { 357193323Sed return getInstructionSet()->getValueAsBit("isLittleEndianEncoding"); 358193323Sed} 359193323Sed 360245431Sdim/// guessInstructionProperties - Return true if it's OK to guess instruction 361245431Sdim/// properties instead of raising an error. 362245431Sdim/// 363245431Sdim/// This is configurable as a temporary migration aid. It will eventually be 364245431Sdim/// permanently false. 365245431Sdimbool CodeGenTarget::guessInstructionProperties() const { 366245431Sdim return getInstructionSet()->getValueAsBit("guessInstructionProperties"); 367245431Sdim} 368245431Sdim 369193323Sed//===----------------------------------------------------------------------===// 370193323Sed// ComplexPattern implementation 371193323Sed// 372193323SedComplexPattern::ComplexPattern(Record *R) { 373193323Sed Ty = ::getValueType(R->getValueAsDef("Ty")); 374193323Sed NumOperands = R->getValueAsInt("NumOperands"); 375193323Sed SelectFunc = R->getValueAsString("SelectFunc"); 376193323Sed RootNodes = R->getValueAsListOfDefs("RootNodes"); 377193323Sed 378193323Sed // Parse the properties. 379193323Sed Properties = 0; 380193323Sed std::vector<Record*> PropList = R->getValueAsListOfDefs("Properties"); 381193323Sed for (unsigned i = 0, e = PropList.size(); i != e; ++i) 382193323Sed if (PropList[i]->getName() == "SDNPHasChain") { 383193323Sed Properties |= 1 << SDNPHasChain; 384218893Sdim } else if (PropList[i]->getName() == "SDNPOptInGlue") { 385218893Sdim Properties |= 1 << SDNPOptInGlue; 386193323Sed } else if (PropList[i]->getName() == "SDNPMayStore") { 387193323Sed Properties |= 1 << SDNPMayStore; 388193323Sed } else if (PropList[i]->getName() == "SDNPMayLoad") { 389193323Sed Properties |= 1 << SDNPMayLoad; 390193323Sed } else if (PropList[i]->getName() == "SDNPSideEffect") { 391193323Sed Properties |= 1 << SDNPSideEffect; 392193323Sed } else if (PropList[i]->getName() == "SDNPMemOperand") { 393193323Sed Properties |= 1 << SDNPMemOperand; 394205407Srdivacky } else if (PropList[i]->getName() == "SDNPVariadic") { 395205407Srdivacky Properties |= 1 << SDNPVariadic; 396218893Sdim } else if (PropList[i]->getName() == "SDNPWantRoot") { 397218893Sdim Properties |= 1 << SDNPWantRoot; 398218893Sdim } else if (PropList[i]->getName() == "SDNPWantParent") { 399218893Sdim Properties |= 1 << SDNPWantParent; 400193323Sed } else { 401195340Sed errs() << "Unsupported SD Node property '" << PropList[i]->getName() 402195340Sed << "' on ComplexPattern '" << R->getName() << "'!\n"; 403193323Sed exit(1); 404193323Sed } 405193323Sed} 406193323Sed 407193323Sed//===----------------------------------------------------------------------===// 408193323Sed// CodeGenIntrinsic Implementation 409193323Sed//===----------------------------------------------------------------------===// 410193323Sed 411193323Sedstd::vector<CodeGenIntrinsic> llvm::LoadIntrinsics(const RecordKeeper &RC, 412193323Sed bool TargetOnly) { 413193323Sed std::vector<Record*> I = RC.getAllDerivedDefinitions("Intrinsic"); 414221345Sdim 415193323Sed std::vector<CodeGenIntrinsic> Result; 416193323Sed 417193323Sed for (unsigned i = 0, e = I.size(); i != e; ++i) { 418193323Sed bool isTarget = I[i]->getValueAsBit("isTarget"); 419193323Sed if (isTarget == TargetOnly) 420193323Sed Result.push_back(CodeGenIntrinsic(I[i])); 421193323Sed } 422193323Sed return Result; 423193323Sed} 424193323Sed 425193323SedCodeGenIntrinsic::CodeGenIntrinsic(Record *R) { 426193323Sed TheDef = R; 427193323Sed std::string DefName = R->getName(); 428212904Sdim ModRef = ReadWriteMem; 429193323Sed isOverloaded = false; 430193323Sed isCommutative = false; 431223017Sdim canThrow = false; 432245431Sdim isNoReturn = false; 433221345Sdim 434221345Sdim if (DefName.size() <= 4 || 435193323Sed std::string(DefName.begin(), DefName.begin() + 4) != "int_") 436245431Sdim PrintFatalError("Intrinsic '" + DefName + "' does not start with 'int_'!"); 437193323Sed 438193323Sed EnumName = std::string(DefName.begin()+4, DefName.end()); 439193323Sed 440193323Sed if (R->getValue("GCCBuiltinName")) // Ignore a missing GCCBuiltinName field. 441193323Sed GCCBuiltinName = R->getValueAsString("GCCBuiltinName"); 442193323Sed 443193323Sed TargetPrefix = R->getValueAsString("TargetPrefix"); 444193323Sed Name = R->getValueAsString("LLVMName"); 445193323Sed 446193323Sed if (Name == "") { 447193323Sed // If an explicit name isn't specified, derive one from the DefName. 448193323Sed Name = "llvm."; 449193323Sed 450193323Sed for (unsigned i = 0, e = EnumName.size(); i != e; ++i) 451193323Sed Name += (EnumName[i] == '_') ? '.' : EnumName[i]; 452193323Sed } else { 453193323Sed // Verify it starts with "llvm.". 454221345Sdim if (Name.size() <= 5 || 455193323Sed std::string(Name.begin(), Name.begin() + 5) != "llvm.") 456245431Sdim PrintFatalError("Intrinsic '" + DefName + "'s name does not start with 'llvm.'!"); 457193323Sed } 458221345Sdim 459193323Sed // If TargetPrefix is specified, make sure that Name starts with 460193323Sed // "llvm.<targetprefix>.". 461193323Sed if (!TargetPrefix.empty()) { 462193323Sed if (Name.size() < 6+TargetPrefix.size() || 463193323Sed std::string(Name.begin() + 5, Name.begin() + 6 + TargetPrefix.size()) 464193323Sed != (TargetPrefix + ".")) 465245431Sdim PrintFatalError("Intrinsic '" + DefName + "' does not start with 'llvm." + 466245431Sdim TargetPrefix + ".'!"); 467193323Sed } 468221345Sdim 469193323Sed // Parse the list of return types. 470193323Sed std::vector<MVT::SimpleValueType> OverloadedVTs; 471193323Sed ListInit *TypeList = R->getValueAsListInit("RetTypes"); 472193323Sed for (unsigned i = 0, e = TypeList->getSize(); i != e; ++i) { 473193323Sed Record *TyEl = TypeList->getElementAsRecord(i); 474193323Sed assert(TyEl->isSubClassOf("LLVMType") && "Expected a type!"); 475193323Sed MVT::SimpleValueType VT; 476193323Sed if (TyEl->isSubClassOf("LLVMMatchType")) { 477193323Sed unsigned MatchTy = TyEl->getValueAsInt("Number"); 478193323Sed assert(MatchTy < OverloadedVTs.size() && 479193323Sed "Invalid matching number!"); 480193323Sed VT = OverloadedVTs[MatchTy]; 481193323Sed // It only makes sense to use the extended and truncated vector element 482193323Sed // variants with iAny types; otherwise, if the intrinsic is not 483193323Sed // overloaded, all the types can be specified directly. 484193323Sed assert(((!TyEl->isSubClassOf("LLVMExtendedElementVectorType") && 485193323Sed !TyEl->isSubClassOf("LLVMTruncatedElementVectorType")) || 486198090Srdivacky VT == MVT::iAny || VT == MVT::vAny) && 487198090Srdivacky "Expected iAny or vAny type"); 488193323Sed } else { 489193323Sed VT = getValueType(TyEl->getValueAsDef("VT")); 490193323Sed } 491198090Srdivacky if (EVT(VT).isOverloaded()) { 492193323Sed OverloadedVTs.push_back(VT); 493206083Srdivacky isOverloaded = true; 494193323Sed } 495206083Srdivacky 496206083Srdivacky // Reject invalid types. 497206083Srdivacky if (VT == MVT::isVoid) 498245431Sdim PrintFatalError("Intrinsic '" + DefName + " has void in result type list!"); 499221345Sdim 500193323Sed IS.RetVTs.push_back(VT); 501193323Sed IS.RetTypeDefs.push_back(TyEl); 502193323Sed } 503221345Sdim 504193323Sed // Parse the list of parameter types. 505193323Sed TypeList = R->getValueAsListInit("ParamTypes"); 506193323Sed for (unsigned i = 0, e = TypeList->getSize(); i != e; ++i) { 507193323Sed Record *TyEl = TypeList->getElementAsRecord(i); 508193323Sed assert(TyEl->isSubClassOf("LLVMType") && "Expected a type!"); 509193323Sed MVT::SimpleValueType VT; 510193323Sed if (TyEl->isSubClassOf("LLVMMatchType")) { 511193323Sed unsigned MatchTy = TyEl->getValueAsInt("Number"); 512193323Sed assert(MatchTy < OverloadedVTs.size() && 513193323Sed "Invalid matching number!"); 514193323Sed VT = OverloadedVTs[MatchTy]; 515193323Sed // It only makes sense to use the extended and truncated vector element 516193323Sed // variants with iAny types; otherwise, if the intrinsic is not 517193323Sed // overloaded, all the types can be specified directly. 518193323Sed assert(((!TyEl->isSubClassOf("LLVMExtendedElementVectorType") && 519193323Sed !TyEl->isSubClassOf("LLVMTruncatedElementVectorType")) || 520198090Srdivacky VT == MVT::iAny || VT == MVT::vAny) && 521198090Srdivacky "Expected iAny or vAny type"); 522193323Sed } else 523193323Sed VT = getValueType(TyEl->getValueAsDef("VT")); 524221345Sdim 525198090Srdivacky if (EVT(VT).isOverloaded()) { 526193323Sed OverloadedVTs.push_back(VT); 527206083Srdivacky isOverloaded = true; 528193323Sed } 529221345Sdim 530206083Srdivacky // Reject invalid types. 531206083Srdivacky if (VT == MVT::isVoid && i != e-1 /*void at end means varargs*/) 532245431Sdim PrintFatalError("Intrinsic '" + DefName + " has void in result type list!"); 533221345Sdim 534193323Sed IS.ParamVTs.push_back(VT); 535193323Sed IS.ParamTypeDefs.push_back(TyEl); 536193323Sed } 537193323Sed 538193323Sed // Parse the intrinsic properties. 539193323Sed ListInit *PropList = R->getValueAsListInit("Properties"); 540193323Sed for (unsigned i = 0, e = PropList->getSize(); i != e; ++i) { 541193323Sed Record *Property = PropList->getElementAsRecord(i); 542193323Sed assert(Property->isSubClassOf("IntrinsicProperty") && 543193323Sed "Expected a property!"); 544221345Sdim 545193323Sed if (Property->getName() == "IntrNoMem") 546193323Sed ModRef = NoMem; 547193323Sed else if (Property->getName() == "IntrReadArgMem") 548193323Sed ModRef = ReadArgMem; 549193323Sed else if (Property->getName() == "IntrReadMem") 550193323Sed ModRef = ReadMem; 551212904Sdim else if (Property->getName() == "IntrReadWriteArgMem") 552212904Sdim ModRef = ReadWriteArgMem; 553193323Sed else if (Property->getName() == "Commutative") 554193323Sed isCommutative = true; 555223017Sdim else if (Property->getName() == "Throws") 556223017Sdim canThrow = true; 557245431Sdim else if (Property->getName() == "IntrNoReturn") 558245431Sdim isNoReturn = true; 559193323Sed else if (Property->isSubClassOf("NoCapture")) { 560193323Sed unsigned ArgNo = Property->getValueAsInt("ArgNo"); 561193323Sed ArgumentAttributes.push_back(std::make_pair(ArgNo, NoCapture)); 562263509Sdim } else if (Property->isSubClassOf("ReadOnly")) { 563263509Sdim unsigned ArgNo = Property->getValueAsInt("ArgNo"); 564263509Sdim ArgumentAttributes.push_back(std::make_pair(ArgNo, ReadOnly)); 565263509Sdim } else if (Property->isSubClassOf("ReadNone")) { 566263509Sdim unsigned ArgNo = Property->getValueAsInt("ArgNo"); 567263509Sdim ArgumentAttributes.push_back(std::make_pair(ArgNo, ReadNone)); 568193323Sed } else 569235633Sdim llvm_unreachable("Unknown property!"); 570193323Sed } 571223017Sdim 572223017Sdim // Sort the argument attributes for later benefit. 573223017Sdim std::sort(ArgumentAttributes.begin(), ArgumentAttributes.end()); 574193323Sed} 575