X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=utils%2FTableGen%2FCodeGenTarget.cpp;h=3c97e14e01281fa4c06334b731b4281d5e8569c7;hb=8dd6f0c8353f80de6526810899f271d539f6929c;hp=c5d4c494c030a64768f086236e290a8b9ca97861;hpb=f8c7394781f7cf27ac52ca087e289436d36844da;p=oota-llvm.git diff --git a/utils/TableGen/CodeGenTarget.cpp b/utils/TableGen/CodeGenTarget.cpp index c5d4c494c03..3c97e14e012 100644 --- a/utils/TableGen/CodeGenTarget.cpp +++ b/utils/TableGen/CodeGenTarget.cpp @@ -16,13 +16,17 @@ #include "CodeGenTarget.h" #include "CodeGenIntrinsics.h" -#include "Record.h" +#include "llvm/TableGen/Record.h" #include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/Support/CommandLine.h" -#include "llvm/Support/Streams.h" #include using namespace llvm; +static cl::opt +AsmParserNum("asmparsernum", cl::init(0), + cl::desc("Make -gen-asm-parser emit assembly parser #N")); + static cl::opt AsmWriterNum("asmwriternum", cl::init(0), cl::desc("Make -gen-asm-writer emit assembly writer #N")); @@ -35,80 +39,60 @@ MVT::SimpleValueType llvm::getValueType(Record *Rec) { std::string llvm::getName(MVT::SimpleValueType T) { switch (T) { - case MVT::Other: return "UNKNOWN"; - case MVT::i1: return "MVT::i1"; - case MVT::i8: return "MVT::i8"; - case MVT::i16: return "MVT::i16"; - case MVT::i32: return "MVT::i32"; - case MVT::i64: return "MVT::i64"; - case MVT::i128: return "MVT::i128"; - case MVT::iAny: return "MVT::iAny"; - case MVT::fAny: return "MVT::fAny"; - case MVT::f32: return "MVT::f32"; - case MVT::f64: return "MVT::f64"; - case MVT::f80: return "MVT::f80"; - case MVT::f128: return "MVT::f128"; - case MVT::ppcf128: return "MVT::ppcf128"; - case MVT::Flag: return "MVT::Flag"; - case MVT::isVoid:return "MVT::isVoid"; - case MVT::v2i8: return "MVT::v2i8"; - case MVT::v4i8: return "MVT::v4i8"; - case MVT::v2i16: return "MVT::v2i16"; - case MVT::v8i8: return "MVT::v8i8"; - case MVT::v4i16: return "MVT::v4i16"; - case MVT::v2i32: return "MVT::v2i32"; - case MVT::v1i64: return "MVT::v1i64"; - case MVT::v16i8: return "MVT::v16i8"; - case MVT::v8i16: return "MVT::v8i16"; - case MVT::v4i32: return "MVT::v4i32"; - case MVT::v2i64: return "MVT::v2i64"; - case MVT::v2f32: return "MVT::v2f32"; - case MVT::v4f32: return "MVT::v4f32"; - case MVT::v2f64: return "MVT::v2f64"; - case MVT::v3i32: return "MVT::v3i32"; - case MVT::v3f32: return "MVT::v3f32"; - case MVT::iPTR: return "TLI.getPointerTy()"; - case MVT::iPTRAny: return "TLI.getPointerTy()"; - default: assert(0 && "ILLEGAL VALUE TYPE!"); return ""; + case MVT::Other: return "UNKNOWN"; + case MVT::iPTR: return "TLI.getPointerTy()"; + case MVT::iPTRAny: return "TLI.getPointerTy()"; + default: return getEnumName(T); } } std::string llvm::getEnumName(MVT::SimpleValueType T) { switch (T) { - case MVT::Other: return "MVT::Other"; - case MVT::i1: return "MVT::i1"; - case MVT::i8: return "MVT::i8"; - case MVT::i16: return "MVT::i16"; - case MVT::i32: return "MVT::i32"; - case MVT::i64: return "MVT::i64"; - case MVT::i128: return "MVT::i128"; - case MVT::iAny: return "MVT::iAny"; - case MVT::fAny: return "MVT::fAny"; - case MVT::f32: return "MVT::f32"; - case MVT::f64: return "MVT::f64"; - case MVT::f80: return "MVT::f80"; - case MVT::f128: return "MVT::f128"; + case MVT::Other: return "MVT::Other"; + case MVT::i1: return "MVT::i1"; + case MVT::i8: return "MVT::i8"; + case MVT::i16: return "MVT::i16"; + case MVT::i32: return "MVT::i32"; + case MVT::i64: return "MVT::i64"; + case MVT::i128: return "MVT::i128"; + case MVT::iAny: return "MVT::iAny"; + case MVT::fAny: return "MVT::fAny"; + case MVT::vAny: return "MVT::vAny"; + case MVT::f16: return "MVT::f16"; + case MVT::f32: return "MVT::f32"; + case MVT::f64: return "MVT::f64"; + case MVT::f80: return "MVT::f80"; + case MVT::f128: return "MVT::f128"; case MVT::ppcf128: return "MVT::ppcf128"; - case MVT::Flag: return "MVT::Flag"; - case MVT::isVoid:return "MVT::isVoid"; - case MVT::v2i8: return "MVT::v2i8"; - case MVT::v4i8: return "MVT::v4i8"; - case MVT::v2i16: return "MVT::v2i16"; - case MVT::v8i8: return "MVT::v8i8"; - case MVT::v4i16: return "MVT::v4i16"; - case MVT::v2i32: return "MVT::v2i32"; - case MVT::v1i64: return "MVT::v1i64"; - case MVT::v16i8: return "MVT::v16i8"; - case MVT::v8i16: return "MVT::v8i16"; - case MVT::v4i32: return "MVT::v4i32"; - case MVT::v2i64: return "MVT::v2i64"; - case MVT::v2f32: return "MVT::v2f32"; - case MVT::v4f32: return "MVT::v4f32"; - case MVT::v2f64: return "MVT::v2f64"; - case MVT::v3i32: return "MVT::v3i32"; - case MVT::v3f32: return "MVT::v3f32"; - case MVT::iPTR: return "MVT::iPTR"; + case MVT::x86mmx: return "MVT::x86mmx"; + case MVT::Glue: return "MVT::Glue"; + case MVT::isVoid: return "MVT::isVoid"; + case MVT::v2i8: return "MVT::v2i8"; + case MVT::v4i8: return "MVT::v4i8"; + case MVT::v8i8: return "MVT::v8i8"; + case MVT::v16i8: return "MVT::v16i8"; + case MVT::v32i8: return "MVT::v32i8"; + case MVT::v2i16: return "MVT::v2i16"; + case MVT::v4i16: return "MVT::v4i16"; + case MVT::v8i16: return "MVT::v8i16"; + case MVT::v16i16: return "MVT::v16i16"; + case MVT::v2i32: return "MVT::v2i32"; + case MVT::v4i32: return "MVT::v4i32"; + case MVT::v8i32: return "MVT::v8i32"; + case MVT::v1i64: return "MVT::v1i64"; + case MVT::v2i64: return "MVT::v2i64"; + case MVT::v4i64: return "MVT::v4i64"; + case MVT::v8i64: return "MVT::v8i64"; + case MVT::v2f16: return "MVT::v2f16"; + case MVT::v2f32: return "MVT::v2f32"; + case MVT::v4f32: return "MVT::v4f32"; + case MVT::v8f32: return "MVT::v8f32"; + case MVT::v2f64: return "MVT::v2f64"; + case MVT::v4f64: return "MVT::v4f64"; + case MVT::Metadata: return "MVT::Metadata"; + case MVT::iPTR: return "MVT::iPTR"; case MVT::iPTRAny: return "MVT::iPTRAny"; + case MVT::Untyped: return "MVT::Untyped"; default: assert(0 && "ILLEGAL VALUE TYPE!"); return ""; } } @@ -117,17 +101,18 @@ std::string llvm::getEnumName(MVT::SimpleValueType T) { /// namespace qualifier if the record contains one. /// std::string llvm::getQualifiedName(const Record *R) { - std::string Namespace = R->getValueAsString("Namespace"); + std::string Namespace; + if (R->getValue("Namespace")) + Namespace = R->getValueAsString("Namespace"); if (Namespace.empty()) return R->getName(); return Namespace + "::" + R->getName(); } - - /// getTarget - Return the current instance of the Target class. /// -CodeGenTarget::CodeGenTarget() { +CodeGenTarget::CodeGenTarget(RecordKeeper &records) + : Records(records), RegBank(0) { std::vector Targets = Records.getAllDerivedDefinitions("Target"); if (Targets.size() == 0) throw std::string("ERROR: No 'Target' subclasses defined!"); @@ -142,24 +127,50 @@ const std::string &CodeGenTarget::getName() const { } std::string CodeGenTarget::getInstNamespace() const { - std::string InstNS; - for (inst_iterator i = inst_begin(), e = inst_end(); i != e; ++i) { - InstNS = i->second.Namespace; - - // Make sure not to pick up "TargetInstrInfo" by accidentally getting + // Make sure not to pick up "TargetOpcode" by accidentally getting // the namespace off the PHI instruction or something. - if (InstNS != "TargetInstrInfo") - break; + if ((*i)->Namespace != "TargetOpcode") + return (*i)->Namespace; } - return InstNS; + return ""; } Record *CodeGenTarget::getInstructionSet() const { return TargetRec->getValueAsDef("InstructionSet"); } + +/// getAsmParser - Return the AssemblyParser definition for this target. +/// +Record *CodeGenTarget::getAsmParser() const { + std::vector LI = TargetRec->getValueAsListOfDefs("AssemblyParsers"); + if (AsmParserNum >= LI.size()) + throw "Target does not have an AsmParser #" + utostr(AsmParserNum) + "!"; + return LI[AsmParserNum]; +} + +/// getAsmParserVariant - Return the AssmblyParserVariant definition for +/// this target. +/// +Record *CodeGenTarget::getAsmParserVariant(unsigned i) const { + std::vector LI = + TargetRec->getValueAsListOfDefs("AssemblyParserVariants"); + if (i >= LI.size()) + throw "Target does not have an AsmParserVariant #" + utostr(i) + "!"; + return LI[i]; +} + +/// getAsmParserVariantCount - Return the AssmblyParserVariant definition +/// available for this target. +/// +unsigned CodeGenTarget::getAsmParserVariantCount() const { + std::vector LI = + TargetRec->getValueAsListOfDefs("AssemblyParserVariants"); + return LI.size(); +} + /// getAsmWriter - Return the AssemblyWriter definition for this target. /// Record *CodeGenTarget::getAsmWriter() const { @@ -169,108 +180,54 @@ Record *CodeGenTarget::getAsmWriter() const { return LI[AsmWriterNum]; } -void CodeGenTarget::ReadRegisters() const { - std::vector Regs = Records.getAllDerivedDefinitions("Register"); - if (Regs.empty()) - throw std::string("No 'Register' subclasses defined!"); - - Registers.reserve(Regs.size()); - Registers.assign(Regs.begin(), Regs.end()); -} - -CodeGenRegister::CodeGenRegister(Record *R) : TheDef(R) { - DeclaredSpillSize = R->getValueAsInt("SpillSize"); - DeclaredSpillAlignment = R->getValueAsInt("SpillAlignment"); +CodeGenRegBank &CodeGenTarget::getRegBank() const { + if (!RegBank) + RegBank = new CodeGenRegBank(Records); + return *RegBank; } -const std::string &CodeGenRegister::getName() const { - return TheDef->getName(); +void CodeGenTarget::ReadRegAltNameIndices() const { + RegAltNameIndices = Records.getAllDerivedDefinitions("RegAltNameIndex"); + std::sort(RegAltNameIndices.begin(), RegAltNameIndices.end(), LessRecord()); } -void CodeGenTarget::ReadRegisterClasses() const { - std::vector RegClasses = - Records.getAllDerivedDefinitions("RegisterClass"); - if (RegClasses.empty()) - throw std::string("No 'RegisterClass' subclasses defined!"); +/// getRegisterByName - If there is a register with the specific AsmName, +/// return it. +const CodeGenRegister *CodeGenTarget::getRegisterByName(StringRef Name) const { + const std::vector &Regs = getRegBank().getRegisters(); + for (unsigned i = 0, e = Regs.size(); i != e; ++i) + if (Regs[i]->TheDef->getValueAsString("AsmName") == Name) + return Regs[i]; - RegisterClasses.reserve(RegClasses.size()); - RegisterClasses.assign(RegClasses.begin(), RegClasses.end()); + return 0; } -std::vector CodeGenTarget::getRegisterVTs(Record *R) const { - std::vector Result; - const std::vector &RCs = getRegisterClasses(); +std::vector CodeGenTarget:: +getRegisterVTs(Record *R) const { + const CodeGenRegister *Reg = getRegBank().getReg(R); + std::vector Result; + ArrayRef RCs = getRegBank().getRegClasses(); for (unsigned i = 0, e = RCs.size(); i != e; ++i) { - const CodeGenRegisterClass &RC = RegisterClasses[i]; - for (unsigned ei = 0, ee = RC.Elements.size(); ei != ee; ++ei) { - if (R == RC.Elements[ei]) { - const std::vector &InVTs = RC.getValueTypes(); - for (unsigned i = 0, e = InVTs.size(); i != e; ++i) - Result.push_back(InVTs[i]); - } + const CodeGenRegisterClass &RC = *RCs[i]; + if (RC.contains(Reg)) { + const std::vector &InVTs = RC.getValueTypes(); + Result.insert(Result.end(), InVTs.begin(), InVTs.end()); } } - return Result; -} - -CodeGenRegisterClass::CodeGenRegisterClass(Record *R) : TheDef(R) { - // Rename anonymous register classes. - if (R->getName().size() > 9 && R->getName()[9] == '.') { - static unsigned AnonCounter = 0; - R->setName("AnonRegClass_"+utostr(AnonCounter++)); - } - - std::vector TypeList = R->getValueAsListOfDefs("RegTypes"); - for (unsigned i = 0, e = TypeList.size(); i != e; ++i) { - Record *Type = TypeList[i]; - if (!Type->isSubClassOf("ValueType")) - throw "RegTypes list member '" + Type->getName() + - "' does not derive from the ValueType class!"; - VTs.push_back(getValueType(Type)); - } - assert(!VTs.empty() && "RegisterClass must contain at least one ValueType!"); - - std::vector RegList = R->getValueAsListOfDefs("MemberList"); - for (unsigned i = 0, e = RegList.size(); i != e; ++i) { - Record *Reg = RegList[i]; - if (!Reg->isSubClassOf("Register")) - throw "Register Class member '" + Reg->getName() + - "' does not derive from the Register class!"; - Elements.push_back(Reg); - } - - std::vector SubRegClassList = - R->getValueAsListOfDefs("SubRegClassList"); - for (unsigned i = 0, e = SubRegClassList.size(); i != e; ++i) { - Record *SubRegClass = SubRegClassList[i]; - if (!SubRegClass->isSubClassOf("RegisterClass")) - throw "Register Class member '" + SubRegClass->getName() + - "' does not derive from the RegisterClass class!"; - SubRegClasses.push_back(SubRegClass); - } - - // Allow targets to override the size in bits of the RegisterClass. - unsigned Size = R->getValueAsInt("Size"); - - Namespace = R->getValueAsString("Namespace"); - SpillSize = Size ? Size : MVT(VTs[0]).getSizeInBits(); - SpillAlignment = R->getValueAsInt("Alignment"); - CopyCost = R->getValueAsInt("CopyCost"); - MethodBodies = R->getValueAsCode("MethodBodies"); - MethodProtos = R->getValueAsCode("MethodProtos"); + // Remove duplicates. + array_pod_sort(Result.begin(), Result.end()); + Result.erase(std::unique(Result.begin(), Result.end()), Result.end()); + return Result; } -const std::string &CodeGenRegisterClass::getName() const { - return TheDef->getName(); -} void CodeGenTarget::ReadLegalValueTypes() const { - const std::vector &RCs = getRegisterClasses(); + ArrayRef RCs = getRegBank().getRegClasses(); for (unsigned i = 0, e = RCs.size(); i != e; ++i) - for (unsigned ri = 0, re = RCs[i].VTs.size(); ri != re; ++ri) - LegalValueTypes.push_back(RCs[i].VTs[ri]); - + for (unsigned ri = 0, re = RCs[i]->VTs.size(); ri != re; ++ri) + LegalValueTypes.push_back(RCs[i]->VTs[ri]); + // Remove duplicates. std::sort(LegalValueTypes.begin(), LegalValueTypes.end()); LegalValueTypes.erase(std::unique(LegalValueTypes.begin(), @@ -285,96 +242,78 @@ void CodeGenTarget::ReadInstructions() const { throw std::string("No 'Instruction' subclasses defined!"); // Parse the instructions defined in the .td file. - std::string InstFormatName = - getAsmWriter()->getValueAsString("InstFormatName"); + for (unsigned i = 0, e = Insts.size(); i != e; ++i) + Instructions[Insts[i]] = new CodeGenInstruction(Insts[i]); +} - for (unsigned i = 0, e = Insts.size(); i != e; ++i) { - std::string AsmStr = Insts[i]->getValueAsString(InstFormatName); - Instructions.insert(std::make_pair(Insts[i]->getName(), - CodeGenInstruction(Insts[i], AsmStr))); +static const CodeGenInstruction * +GetInstByName(const char *Name, + const DenseMap &Insts, + RecordKeeper &Records) { + const Record *Rec = Records.getDef(Name); + + DenseMap::const_iterator + I = Insts.find(Rec); + if (Rec == 0 || I == Insts.end()) + throw std::string("Could not find '") + Name + "' instruction!"; + return I->second; +} + +namespace { +/// SortInstByName - Sorting predicate to sort instructions by name. +/// +struct SortInstByName { + bool operator()(const CodeGenInstruction *Rec1, + const CodeGenInstruction *Rec2) const { + return Rec1->TheDef->getName() < Rec2->TheDef->getName(); } +}; } /// getInstructionsByEnumValue - Return all of the instructions defined by the /// target, ordered by their enum value. -void CodeGenTarget:: -getInstructionsByEnumValue(std::vector - &NumberedInstructions) { - std::map::const_iterator I; - I = getInstructions().find("PHI"); - if (I == Instructions.end()) throw "Could not find 'PHI' instruction!"; - const CodeGenInstruction *PHI = &I->second; - - I = getInstructions().find("INLINEASM"); - if (I == Instructions.end()) throw "Could not find 'INLINEASM' instruction!"; - const CodeGenInstruction *INLINEASM = &I->second; - - I = getInstructions().find("DBG_LABEL"); - if (I == Instructions.end()) throw "Could not find 'DBG_LABEL' instruction!"; - const CodeGenInstruction *DBG_LABEL = &I->second; - - I = getInstructions().find("EH_LABEL"); - if (I == Instructions.end()) throw "Could not find 'EH_LABEL' instruction!"; - const CodeGenInstruction *EH_LABEL = &I->second; - - I = getInstructions().find("GC_LABEL"); - if (I == Instructions.end()) throw "Could not find 'GC_LABEL' instruction!"; - const CodeGenInstruction *GC_LABEL = &I->second; - - I = getInstructions().find("DECLARE"); - if (I == Instructions.end()) throw "Could not find 'DECLARE' instruction!"; - const CodeGenInstruction *DECLARE = &I->second; - - I = getInstructions().find("EXTRACT_SUBREG"); - if (I == Instructions.end()) - throw "Could not find 'EXTRACT_SUBREG' instruction!"; - const CodeGenInstruction *EXTRACT_SUBREG = &I->second; - - I = getInstructions().find("INSERT_SUBREG"); - if (I == Instructions.end()) - throw "Could not find 'INSERT_SUBREG' instruction!"; - const CodeGenInstruction *INSERT_SUBREG = &I->second; - - I = getInstructions().find("IMPLICIT_DEF"); - if (I == Instructions.end()) - throw "Could not find 'IMPLICIT_DEF' instruction!"; - const CodeGenInstruction *IMPLICIT_DEF = &I->second; - - I = getInstructions().find("SUBREG_TO_REG"); - if (I == Instructions.end()) - throw "Could not find 'SUBREG_TO_REG' instruction!"; - const CodeGenInstruction *SUBREG_TO_REG = &I->second; - - I = getInstructions().find("COPY_TO_SUBCLASS"); - if (I == Instructions.end()) - throw "Could not find 'COPY_TO_SUBCLASS' instruction!"; - const CodeGenInstruction *COPY_TO_SUBCLASS = &I->second; - - // Print out the rest of the instructions now. - NumberedInstructions.push_back(PHI); - NumberedInstructions.push_back(INLINEASM); - NumberedInstructions.push_back(DBG_LABEL); - NumberedInstructions.push_back(EH_LABEL); - NumberedInstructions.push_back(GC_LABEL); - NumberedInstructions.push_back(DECLARE); - NumberedInstructions.push_back(EXTRACT_SUBREG); - NumberedInstructions.push_back(INSERT_SUBREG); - NumberedInstructions.push_back(IMPLICIT_DEF); - NumberedInstructions.push_back(SUBREG_TO_REG); - NumberedInstructions.push_back(COPY_TO_SUBCLASS); - for (inst_iterator II = inst_begin(), E = inst_end(); II != E; ++II) - if (&II->second != PHI && - &II->second != INLINEASM && - &II->second != DBG_LABEL && - &II->second != EH_LABEL && - &II->second != GC_LABEL && - &II->second != DECLARE && - &II->second != EXTRACT_SUBREG && - &II->second != INSERT_SUBREG && - &II->second != IMPLICIT_DEF && - &II->second != SUBREG_TO_REG && - &II->second != COPY_TO_SUBCLASS) - NumberedInstructions.push_back(&II->second); +void CodeGenTarget::ComputeInstrsByEnum() const { + // The ordering here must match the ordering in TargetOpcodes.h. + const char *const FixedInstrs[] = { + "PHI", + "INLINEASM", + "PROLOG_LABEL", + "EH_LABEL", + "GC_LABEL", + "KILL", + "EXTRACT_SUBREG", + "INSERT_SUBREG", + "IMPLICIT_DEF", + "SUBREG_TO_REG", + "COPY_TO_REGCLASS", + "DBG_VALUE", + "REG_SEQUENCE", + "COPY", + "BUNDLE", + 0 + }; + const DenseMap &Insts = getInstructions(); + for (const char *const *p = FixedInstrs; *p; ++p) { + const CodeGenInstruction *Instr = GetInstByName(*p, Insts, Records); + assert(Instr && "Missing target independent instruction"); + assert(Instr->Namespace == "TargetOpcode" && "Bad namespace"); + InstrsByEnum.push_back(Instr); + } + unsigned EndOfPredefines = InstrsByEnum.size(); + + for (DenseMap::const_iterator + I = Insts.begin(), E = Insts.end(); I != E; ++I) { + const CodeGenInstruction *CGI = I->second; + if (CGI->Namespace != "TargetOpcode") + InstrsByEnum.push_back(CGI); + } + + assert(InstrsByEnum.size() == Insts.size() && "Missing predefined instr"); + + // All of the instructions are now in random order based on the map iteration. + // Sort them by name. + std::sort(InstrsByEnum.begin()+EndOfPredefines, InstrsByEnum.end(), + SortInstByName()); } @@ -400,8 +339,8 @@ ComplexPattern::ComplexPattern(Record *R) { for (unsigned i = 0, e = PropList.size(); i != e; ++i) if (PropList[i]->getName() == "SDNPHasChain") { Properties |= 1 << SDNPHasChain; - } else if (PropList[i]->getName() == "SDNPOptInFlag") { - Properties |= 1 << SDNPOptInFlag; + } else if (PropList[i]->getName() == "SDNPOptInGlue") { + Properties |= 1 << SDNPOptInGlue; } else if (PropList[i]->getName() == "SDNPMayStore") { Properties |= 1 << SDNPMayStore; } else if (PropList[i]->getName() == "SDNPMayLoad") { @@ -410,21 +349,15 @@ ComplexPattern::ComplexPattern(Record *R) { Properties |= 1 << SDNPSideEffect; } else if (PropList[i]->getName() == "SDNPMemOperand") { Properties |= 1 << SDNPMemOperand; + } else if (PropList[i]->getName() == "SDNPVariadic") { + Properties |= 1 << SDNPVariadic; + } else if (PropList[i]->getName() == "SDNPWantRoot") { + Properties |= 1 << SDNPWantRoot; + } else if (PropList[i]->getName() == "SDNPWantParent") { + Properties |= 1 << SDNPWantParent; } else { - cerr << "Unsupported SD Node property '" << PropList[i]->getName() - << "' on ComplexPattern '" << R->getName() << "'!\n"; - exit(1); - } - - // Parse the attributes. - Attributes = 0; - PropList = R->getValueAsListOfDefs("Attributes"); - for (unsigned i = 0, e = PropList.size(); i != e; ++i) - if (PropList[i]->getName() == "CPAttrParentAsRoot") { - Attributes |= 1 << CPAttrParentAsRoot; - } else { - cerr << "Unsupported pattern attribute '" << PropList[i]->getName() - << "' on ComplexPattern '" << R->getName() << "'!\n"; + errs() << "Unsupported SD Node property '" << PropList[i]->getName() + << "' on ComplexPattern '" << R->getName() << "'!\n"; exit(1); } } @@ -436,7 +369,7 @@ ComplexPattern::ComplexPattern(Record *R) { std::vector llvm::LoadIntrinsics(const RecordKeeper &RC, bool TargetOnly) { std::vector I = RC.getAllDerivedDefinitions("Intrinsic"); - + std::vector Result; for (unsigned i = 0, e = I.size(); i != e; ++i) { @@ -450,11 +383,12 @@ std::vector llvm::LoadIntrinsics(const RecordKeeper &RC, CodeGenIntrinsic::CodeGenIntrinsic(Record *R) { TheDef = R; std::string DefName = R->getName(); - ModRef = WriteMem; + ModRef = ReadWriteMem; isOverloaded = false; isCommutative = false; - - if (DefName.size() <= 4 || + canThrow = false; + + if (DefName.size() <= 4 || std::string(DefName.begin(), DefName.begin() + 4) != "int_") throw "Intrinsic '" + DefName + "' does not start with 'int_'!"; @@ -474,11 +408,11 @@ CodeGenIntrinsic::CodeGenIntrinsic(Record *R) { Name += (EnumName[i] == '_') ? '.' : EnumName[i]; } else { // Verify it starts with "llvm.". - if (Name.size() <= 5 || + if (Name.size() <= 5 || std::string(Name.begin(), Name.begin() + 5) != "llvm.") throw "Intrinsic '" + DefName + "'s name does not start with 'llvm.'!"; } - + // If TargetPrefix is specified, make sure that Name starts with // "llvm..". if (!TargetPrefix.empty()) { @@ -488,31 +422,42 @@ CodeGenIntrinsic::CodeGenIntrinsic(Record *R) { throw "Intrinsic '" + DefName + "' does not start with 'llvm." + TargetPrefix + ".'!"; } - + // Parse the list of return types. + std::vector OverloadedVTs; ListInit *TypeList = R->getValueAsListInit("RetTypes"); for (unsigned i = 0, e = TypeList->getSize(); i != e; ++i) { Record *TyEl = TypeList->getElementAsRecord(i); assert(TyEl->isSubClassOf("LLVMType") && "Expected a type!"); MVT::SimpleValueType VT; if (TyEl->isSubClassOf("LLVMMatchType")) { - VT = IS.RetVTs[TyEl->getValueAsInt("Number")]; + unsigned MatchTy = TyEl->getValueAsInt("Number"); + assert(MatchTy < OverloadedVTs.size() && + "Invalid matching number!"); + VT = OverloadedVTs[MatchTy]; // It only makes sense to use the extended and truncated vector element // variants with iAny types; otherwise, if the intrinsic is not // overloaded, all the types can be specified directly. assert(((!TyEl->isSubClassOf("LLVMExtendedElementVectorType") && !TyEl->isSubClassOf("LLVMTruncatedElementVectorType")) || - VT == MVT::iAny) && "Expected iAny type"); - } else + VT == MVT::iAny || VT == MVT::vAny) && + "Expected iAny or vAny type"); + } else { VT = getValueType(TyEl->getValueAsDef("VT")); - isOverloaded |= VT == MVT::iAny || VT == MVT::fAny || VT == MVT::iPTRAny; + } + if (EVT(VT).isOverloaded()) { + OverloadedVTs.push_back(VT); + isOverloaded = true; + } + + // Reject invalid types. + if (VT == MVT::isVoid) + throw "Intrinsic '" + DefName + " has void in result type list!"; + IS.RetVTs.push_back(VT); IS.RetTypeDefs.push_back(TyEl); } - if (IS.RetVTs.size() == 0) - throw "Intrinsic '"+DefName+"' needs at least a type for the ret value!"; - // Parse the list of parameter types. TypeList = R->getValueAsListInit("ParamTypes"); for (unsigned i = 0, e = TypeList->getSize(); i != e; ++i) { @@ -521,19 +466,28 @@ CodeGenIntrinsic::CodeGenIntrinsic(Record *R) { MVT::SimpleValueType VT; if (TyEl->isSubClassOf("LLVMMatchType")) { unsigned MatchTy = TyEl->getValueAsInt("Number"); - if (MatchTy < IS.RetVTs.size()) - VT = IS.RetVTs[MatchTy]; - else - VT = IS.ParamVTs[MatchTy - IS.RetVTs.size()]; + assert(MatchTy < OverloadedVTs.size() && + "Invalid matching number!"); + VT = OverloadedVTs[MatchTy]; // It only makes sense to use the extended and truncated vector element // variants with iAny types; otherwise, if the intrinsic is not // overloaded, all the types can be specified directly. assert(((!TyEl->isSubClassOf("LLVMExtendedElementVectorType") && !TyEl->isSubClassOf("LLVMTruncatedElementVectorType")) || - VT == MVT::iAny) && "Expected iAny type"); + VT == MVT::iAny || VT == MVT::vAny) && + "Expected iAny or vAny type"); } else VT = getValueType(TyEl->getValueAsDef("VT")); - isOverloaded |= VT == MVT::iAny || VT == MVT::fAny || VT == MVT::iPTRAny; + + if (EVT(VT).isOverloaded()) { + OverloadedVTs.push_back(VT); + isOverloaded = true; + } + + // Reject invalid types. + if (VT == MVT::isVoid && i != e-1 /*void at end means varargs*/) + throw "Intrinsic '" + DefName + " has void in result type list!"; + IS.ParamVTs.push_back(VT); IS.ParamTypeDefs.push_back(TyEl); } @@ -544,23 +498,26 @@ CodeGenIntrinsic::CodeGenIntrinsic(Record *R) { Record *Property = PropList->getElementAsRecord(i); assert(Property->isSubClassOf("IntrinsicProperty") && "Expected a property!"); - + if (Property->getName() == "IntrNoMem") ModRef = NoMem; else if (Property->getName() == "IntrReadArgMem") ModRef = ReadArgMem; else if (Property->getName() == "IntrReadMem") ModRef = ReadMem; - else if (Property->getName() == "IntrWriteArgMem") - ModRef = WriteArgMem; - else if (Property->getName() == "IntrWriteMem") - ModRef = WriteMem; + else if (Property->getName() == "IntrReadWriteArgMem") + ModRef = ReadWriteArgMem; else if (Property->getName() == "Commutative") isCommutative = true; + else if (Property->getName() == "Throws") + canThrow = true; else if (Property->isSubClassOf("NoCapture")) { unsigned ArgNo = Property->getValueAsInt("ArgNo"); ArgumentAttributes.push_back(std::make_pair(ArgNo, NoCapture)); } else assert(0 && "Unknown property!"); } + + // Sort the argument attributes for later benefit. + std::sort(ArgumentAttributes.begin(), ArgumentAttributes.end()); }