X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=utils%2FTableGen%2FCodeGenTarget.cpp;h=8159ae7bd7fad7a24cc2e5302a1dbfacec9eb79e;hb=02cdb377eca9fedd28180fa396222e78c8e7134a;hp=73730d18a8024d762da45e753773b4490f02d3bf;hpb=86193d1190b30a537415fc1c384f4e51039fab74;p=oota-llvm.git diff --git a/utils/TableGen/CodeGenTarget.cpp b/utils/TableGen/CodeGenTarget.cpp index 73730d18a80..8159ae7bd7f 100644 --- a/utils/TableGen/CodeGenTarget.cpp +++ b/utils/TableGen/CodeGenTarget.cpp @@ -15,6 +15,7 @@ //===----------------------------------------------------------------------===// #include "CodeGenTarget.h" +#include "CodeGenIntrinsics.h" #include "Record.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Support/CommandLine.h" @@ -28,54 +29,66 @@ AsmWriterNum("asmwriternum", cl::init(0), /// getValueType - Return the MCV::ValueType that the specified TableGen record /// corresponds to. -MVT::ValueType llvm::getValueType(Record *Rec) { +MVT::ValueType llvm::getValueType(Record *Rec, const CodeGenTarget *CGT) { return (MVT::ValueType)Rec->getValueAsInt("Value"); } std::string llvm::getName(MVT::ValueType T) { switch (T) { case MVT::Other: return "UNKNOWN"; - case MVT::i1: return "i1"; - case MVT::i8: return "i8"; - case MVT::i16: return "i16"; - case MVT::i32: return "i32"; - case MVT::i64: return "i64"; - case MVT::i128: return "i128"; - case MVT::f32: return "f32"; - case MVT::f64: return "f64"; - case MVT::f80: return "f80"; - case MVT::f128: return "f128"; - case MVT::isVoid:return "void"; - case MVT::v16i8: return "v16i8"; - case MVT::v8i16: return "v8i16"; - case MVT::v4i32: return "v4i32"; - case MVT::v2i64: return "v2i64"; - case MVT::v4f32: return "v4f32"; - case MVT::v2f64: return "v2f64"; + 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::f32: return "MVT::f32"; + case MVT::f64: return "MVT::f64"; + case MVT::f80: return "MVT::f80"; + case MVT::f128: return "MVT::f128"; + case MVT::Flag: return "MVT::Flag"; + case MVT::isVoid:return "MVT::void"; + case MVT::v8i8: return "MVT::v8i8"; + case MVT::v4i16: return "MVT::v4i16"; + case MVT::v2i32: return "MVT::v2i32"; + 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::iPTR: return "TLI.getPointerTy()"; default: assert(0 && "ILLEGAL VALUE TYPE!"); return ""; } } std::string llvm::getEnumName(MVT::ValueType T) { switch (T) { - case MVT::Other: return "Other"; - case MVT::i1: return "i1"; - case MVT::i8: return "i8"; - case MVT::i16: return "i16"; - case MVT::i32: return "i32"; - case MVT::i64: return "i64"; - case MVT::i128: return "i128"; - case MVT::f32: return "f32"; - case MVT::f64: return "f64"; - case MVT::f80: return "f80"; - case MVT::f128: return "f128"; - case MVT::isVoid:return "isVoid"; - case MVT::v16i8: return "v16i8"; - case MVT::v8i16: return "v8i16"; - case MVT::v4i32: return "v4i32"; - case MVT::v2i64: return "v2i64"; - case MVT::v4f32: return "v4f32"; - case MVT::v2f64: return "v2f64"; + 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::f32: return "MVT::f32"; + case MVT::f64: return "MVT::f64"; + case MVT::f80: return "MVT::f80"; + case MVT::f128: return "MVT::f128"; + case MVT::Flag: return "MVT::Flag"; + case MVT::isVoid:return "MVT::isVoid"; + case MVT::v8i8: return "MVT::v8i8"; + case MVT::v4i16: return "MVT::v4i16"; + case MVT::v2i32: return "MVT::v2i32"; + 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::iPTR: return "TLI.getPointerTy()"; default: assert(0 && "ILLEGAL VALUE TYPE!"); return ""; } } @@ -88,17 +101,13 @@ std::ostream &llvm::operator<<(std::ostream &OS, MVT::ValueType T) { /// getTarget - Return the current instance of the Target class. /// -CodeGenTarget::CodeGenTarget() : PointerType(MVT::Other) { +CodeGenTarget::CodeGenTarget() { std::vector Targets = Records.getAllDerivedDefinitions("Target"); if (Targets.size() == 0) throw std::string("ERROR: No 'Target' subclasses defined!"); if (Targets.size() != 1) throw std::string("ERROR: Multiple subclasses of Target defined!"); TargetRec = Targets[0]; - - // Read in all of the CalleeSavedRegisters. - CalleeSavedRegisters =TargetRec->getValueAsListOfDefs("CalleeSavedRegisters"); - PointerType = getValueType(TargetRec->getValueAsDef("PointerType")); } @@ -147,6 +156,23 @@ void CodeGenTarget::ReadRegisterClasses() const { RegisterClasses.assign(RegClasses.begin(), RegClasses.end()); } +std::vector CodeGenTarget::getRegisterVTs(Record *R) const { + std::vector Result; + const std::vector &RCs = getRegisterClasses(); + 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]); + } + } + } + return Result; +} + + CodeGenRegisterClass::CodeGenRegisterClass(Record *R) : TheDef(R) { // Rename anonymous register classes. if (R->getName().size() > 9 && R->getName()[9] == '.') { @@ -154,13 +180,15 @@ CodeGenRegisterClass::CodeGenRegisterClass(Record *R) : TheDef(R) { R->setName("AnonRegClass_"+utostr(AnonCounter++)); } - Namespace = R->getValueAsString("Namespace"); - SpillSize = R->getValueAsInt("Size"); - SpillAlignment = R->getValueAsInt("Alignment"); - VT = getValueType(R->getValueAsDef("RegType")); - - MethodBodies = R->getValueAsCode("MethodBodies"); - MethodProtos = R->getValueAsCode("MethodProtos"); + 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) { @@ -170,6 +198,15 @@ CodeGenRegisterClass::CodeGenRegisterClass(Record *R) : TheDef(R) { "' does not derive from the Register class!"; Elements.push_back(Reg); } + + // Allow targets to override the size in bits of the RegisterClass. + unsigned Size = R->getValueAsInt("Size"); + + Namespace = R->getValueAsString("Namespace"); + SpillSize = Size ? Size : MVT::getSizeInBits(VTs[0]); + SpillAlignment = R->getValueAsInt("Alignment"); + MethodBodies = R->getValueAsCode("MethodBodies"); + MethodProtos = R->getValueAsCode("MethodProtos"); } const std::string &CodeGenRegisterClass::getName() const { @@ -179,7 +216,8 @@ const std::string &CodeGenRegisterClass::getName() const { void CodeGenTarget::ReadLegalValueTypes() const { const std::vector &RCs = getRegisterClasses(); for (unsigned i = 0, e = RCs.size(); i != e; ++i) - LegalValueTypes.push_back(RCs[i].VT); + 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()); @@ -191,10 +229,10 @@ void CodeGenTarget::ReadLegalValueTypes() const { void CodeGenTarget::ReadInstructions() const { std::vector Insts = Records.getAllDerivedDefinitions("Instruction"); - - if (Insts.empty()) + if (Insts.size() <= 2) throw std::string("No 'Instruction' subclasses defined!"); + // Parse the instructions defined in the .td file. std::string InstFormatName = getAsmWriter()->getValueAsString("InstFormatName"); @@ -205,29 +243,25 @@ void CodeGenTarget::ReadInstructions() const { } } -/// getPHIInstruction - Return the designated PHI instruction. -/// -const CodeGenInstruction &CodeGenTarget::getPHIInstruction() const { - Record *PHI = getInstructionSet()->getValueAsDef("PHIInst"); - std::map::const_iterator I = - getInstructions().find(PHI->getName()); - if (I == Instructions.end()) - throw "Could not find PHI instruction named '" + PHI->getName() + "'!"; - return I->second; -} - /// 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; + // Print out the rest of the instructions now. - unsigned i = 0; - const CodeGenInstruction *PHI = &getPHIInstruction(); NumberedInstructions.push_back(PHI); + NumberedInstructions.push_back(INLINEASM); for (inst_iterator II = inst_begin(), E = inst_end(); II != E; ++II) - if (&II->second != PHI) + if (&II->second != PHI &&&II->second != INLINEASM) NumberedInstructions.push_back(&II->second); } @@ -256,6 +290,8 @@ CodeGenInstruction::CodeGenInstruction(Record *R, const std::string &AsmStr) isTerminator = R->getValueAsBit("isTerminator"); hasDelaySlot = R->getValueAsBit("hasDelaySlot"); usesCustomDAGSchedInserter = R->getValueAsBit("usesCustomDAGSchedInserter"); + hasCtrlDep = R->getValueAsBit("hasCtrlDep"); + noResults = R->getValueAsBit("noResults"); hasVariableNumberOfOperands = false; DagInit *DI; @@ -317,3 +353,113 @@ unsigned CodeGenInstruction::getOperandNamed(const std::string &Name) const { throw "Instruction '" + TheDef->getName() + "' does not have an operand named '$" + Name + "'!"; } + +//===----------------------------------------------------------------------===// +// ComplexPattern implementation +// +ComplexPattern::ComplexPattern(Record *R) { + Ty = ::getValueType(R->getValueAsDef("Ty")); + NumOperands = R->getValueAsInt("NumOperands"); + SelectFunc = R->getValueAsString("SelectFunc"); + RootNodes = R->getValueAsListOfDefs("RootNodes"); +} + +//===----------------------------------------------------------------------===// +// CodeGenIntrinsic Implementation +//===----------------------------------------------------------------------===// + +std::vector llvm::LoadIntrinsics(const RecordKeeper &RC) { + std::vector I = RC.getAllDerivedDefinitions("Intrinsic"); + + std::vector Result; + + // If we are in the context of a target .td file, get the target info so that + // we can decode the current intptr_t. + CodeGenTarget *CGT = 0; + if (Records.getClass("Target") && + Records.getAllDerivedDefinitions("Target").size() == 1) + CGT = new CodeGenTarget(); + + for (unsigned i = 0, e = I.size(); i != e; ++i) + Result.push_back(CodeGenIntrinsic(I[i], CGT)); + delete CGT; + return Result; +} + +CodeGenIntrinsic::CodeGenIntrinsic(Record *R, CodeGenTarget *CGT) { + TheDef = R; + std::string DefName = R->getName(); + ModRef = WriteMem; + + if (DefName.size() <= 4 || + std::string(DefName.begin(), DefName.begin()+4) != "int_") + throw "Intrinsic '" + DefName + "' does not start with 'int_'!"; + EnumName = std::string(DefName.begin()+4, DefName.end()); + if (R->getValue("GCCBuiltinName")) // Ignore a missing GCCBuiltinName field. + GCCBuiltinName = R->getValueAsString("GCCBuiltinName"); + TargetPrefix = R->getValueAsString("TargetPrefix"); + Name = R->getValueAsString("LLVMName"); + if (Name == "") { + // If an explicit name isn't specified, derive one from the DefName. + Name = "llvm."; + for (unsigned i = 0, e = EnumName.size(); i != e; ++i) + if (EnumName[i] == '_') + Name += '.'; + else + Name += EnumName[i]; + } else { + // Verify it starts with "llvm.". + 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()) { + if (Name.size() < 6+TargetPrefix.size() || + std::string(Name.begin()+5, Name.begin()+6+TargetPrefix.size()) + != (TargetPrefix+".")) + throw "Intrinsic '" + DefName + "' does not start with 'llvm." + + TargetPrefix + ".'!"; + } + + // Parse the list of argument types. + ListInit *TypeList = R->getValueAsListInit("Types"); + for (unsigned i = 0, e = TypeList->getSize(); i != e; ++i) { + DefInit *DI = dynamic_cast(TypeList->getElement(i)); + assert(DI && "Invalid list type!"); + Record *TyEl = DI->getDef(); + assert(TyEl->isSubClassOf("LLVMType") && "Expected a type!"); + ArgTypes.push_back(TyEl->getValueAsString("TypeVal")); + + if (CGT) + ArgVTs.push_back(getValueType(TyEl->getValueAsDef("VT"), CGT)); + ArgTypeDefs.push_back(TyEl); + } + if (ArgTypes.size() == 0) + throw "Intrinsic '"+DefName+"' needs at least a type for the ret value!"; + + // Parse the intrinsic properties. + ListInit *PropList = R->getValueAsListInit("Properties"); + for (unsigned i = 0, e = PropList->getSize(); i != e; ++i) { + DefInit *DI = dynamic_cast(PropList->getElement(i)); + assert(DI && "Invalid list type!"); + Record *Property = DI->getDef(); + 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 + assert(0 && "Unknown property!"); + } +}