From e1b469170bb3ab259fd488fb95c29efe802cdd6a Mon Sep 17 00:00:00 2001 From: David Greene Date: Mon, 8 Jun 2009 20:23:18 +0000 Subject: [PATCH] Make IntInits and ListInits typed. This helps deduce types of !if and other operators. For the rare cases where a list type cannot be deduced, provide a [] syntax, where is the list element type. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@73078 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Target/TargetSelectionDAG.td | 1 + test/TableGen/Slice.td | 87 ++++++++++++++++ utils/TableGen/CodeGenDAGPatterns.cpp | 23 ++++- utils/TableGen/Record.cpp | 92 +++++++++++++++-- utils/TableGen/Record.h | 53 ++++++++-- utils/TableGen/TGParser.cpp | 165 +++++++++++++++++++++++++----- utils/TableGen/TGParser.h | 6 +- 7 files changed, 382 insertions(+), 45 deletions(-) create mode 100644 test/TableGen/Slice.td diff --git a/include/llvm/Target/TargetSelectionDAG.td b/include/llvm/Target/TargetSelectionDAG.td index 2cd29676dbf..364d4d0d3cc 100644 --- a/include/llvm/Target/TargetSelectionDAG.td +++ b/include/llvm/Target/TargetSelectionDAG.td @@ -228,6 +228,7 @@ class SDNode { + int Size = size; + int Value = value; +} + +def f32 : ValueType<32, 1>; // 2 x i64 vector value + +class Intrinsic { + string Name = name; +} + +class Inst opcode, dag oopnds, dag iopnds, string asmstr, + list pattern> { + bits<8> Opcode = opcode; + dag OutOperands = oopnds; + dag InOperands = iopnds; + string AssemblyString = asmstr; + list Pattern = pattern; +} + +def ops; +def outs; +def ins; + +def set; + +// Define registers +class Register { + string Name = n; +} + +class RegisterClass regTypes, list regList> { + list RegTypes = regTypes; + list MemberList = regList; +} + +def XMM0: Register<"xmm0">; +def XMM1: Register<"xmm1">; +def XMM2: Register<"xmm2">; +def XMM3: Register<"xmm3">; +def XMM4: Register<"xmm4">; +def XMM5: Register<"xmm5">; +def XMM6: Register<"xmm6">; +def XMM7: Register<"xmm7">; +def XMM8: Register<"xmm8">; +def XMM9: Register<"xmm9">; +def XMM10: Register<"xmm10">; +def XMM11: Register<"xmm11">; +def XMM12: Register<"xmm12">; +def XMM13: Register<"xmm13">; +def XMM14: Register<"xmm14">; +def XMM15: Register<"xmm15">; + +def FR32 : RegisterClass<[f32], + [XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7, + XMM8, XMM9, XMM10, XMM11, + XMM12, XMM13, XMM14, XMM15]>; + +class SDNode {} +def not : SDNode; + +multiclass scalar opcode, string asmstr = "", list> patterns = []> { + def SSrr : Inst,patterns[0])>; + def SSrm : Inst,!if(!null(!cdr(patterns)),patterns[0],patterns[1]))>; +} + +multiclass vscalar opcode, string asmstr = "", list> patterns = []> { + def V#NAME#SSrr : Inst,patterns[0])>; + def V#NAME#SSrm : Inst,!if(!null(!cdr(patterns)),patterns[0],patterns[1]))>; +} + +multiclass myscalar opcode, string asmstr = "", list> patterns = []> : + scalar, + vscalar; + +defm NOT : myscalar<0x10, "not", [[], [(set FR32:$dst, (f32 (not FR32:$src)))]]>; diff --git a/utils/TableGen/CodeGenDAGPatterns.cpp b/utils/TableGen/CodeGenDAGPatterns.cpp index db76dabb537..05bbc0a7fdb 100644 --- a/utils/TableGen/CodeGenDAGPatterns.cpp +++ b/utils/TableGen/CodeGenDAGPatterns.cpp @@ -2007,9 +2007,28 @@ void CodeGenDAGPatterns::ParsePatterns() { Pattern = new TreePattern(Patterns[i], Tree, true, *this); else { std::vector Values; - for (unsigned j = 0, ee = Tree->getNumArgs(); j != ee; ++j) + RecTy *ListTy = 0; + for (unsigned j = 0, ee = Tree->getNumArgs(); j != ee; ++j) { Values.push_back(Tree->getArg(j)); - ListInit *LI = new ListInit(Values); + TypedInit *TArg = dynamic_cast(Tree->getArg(j)); + if (TArg == 0) { + cerr << "In dag: " << Tree->getAsString(); + cerr << " -- Untyped argument in pattern\n"; + assert(0 && "Untyped argument in pattern"); + } + if (ListTy != 0) { + ListTy = resolveTypes(ListTy, TArg->getType()); + if (ListTy == 0) { + cerr << "In dag: " << Tree->getAsString(); + cerr << " -- Incompatible types in pattern arguments\n"; + assert(0 && "Incompatible types in pattern arguments"); + } + } + else { + ListTy - TArg->getType(); + } + } + ListInit *LI = new ListInit(Values, new ListRecTy(ListTy)); Pattern = new TreePattern(Patterns[i], LI, true, *this); } diff --git a/utils/TableGen/Record.cpp b/utils/TableGen/Record.cpp index 18584ec8a01..fa10799622c 100644 --- a/utils/TableGen/Record.cpp +++ b/utils/TableGen/Record.cpp @@ -191,7 +191,12 @@ Init *ListRecTy::convertValue(ListInit *LI) { else return 0; - return new ListInit(Elements); + ListRecTy *LType = dynamic_cast(LI->getType()); + if (LType == 0) { + return 0; + } + + return new ListInit(Elements, new ListRecTy(Ty)); } Init *ListRecTy::convertValue(TypedInit *TI) { @@ -272,6 +277,57 @@ bool RecordRecTy::baseClassOf(const RecordRecTy *RHS) const { } +/// resolveTypes - Find a common type that T1 and T2 convert to. +/// Return 0 if no such type exists. +/// +RecTy *llvm::resolveTypes(RecTy *T1, RecTy *T2) { + if (!T1->typeIsConvertibleTo(T2)) { + if (!T2->typeIsConvertibleTo(T1)) { + // If one is a Record type, check superclasses + RecordRecTy *RecTy1 = dynamic_cast(T1); + if (RecTy1) { + // See if T2 inherits from a type T1 also inherits from + const std::vector &T1SuperClasses = RecTy1->getRecord()->getSuperClasses(); + for(std::vector::const_iterator i = T1SuperClasses.begin(), + iend = T1SuperClasses.end(); + i != iend; + ++i) { + RecordRecTy *SuperRecTy1 = new RecordRecTy(*i); + RecTy *NewType1 = resolveTypes(SuperRecTy1, T2); + if (NewType1 != 0) { + if (NewType1 != SuperRecTy1) { + delete SuperRecTy1; + } + return NewType1; + } + } + } + RecordRecTy *RecTy2 = dynamic_cast(T2); + if (RecTy2) { + // See if T1 inherits from a type T2 also inherits from + const std::vector &T2SuperClasses = RecTy2->getRecord()->getSuperClasses(); + for(std::vector::const_iterator i = T2SuperClasses.begin(), + iend = T2SuperClasses.end(); + i != iend; + ++i) { + RecordRecTy *SuperRecTy2 = new RecordRecTy(*i); + RecTy *NewType2 = resolveTypes(T1, SuperRecTy2); + if (NewType2 != 0) { + if (NewType2 != SuperRecTy2) { + delete SuperRecTy2; + } + return NewType2; + } + } + } + return 0; + } + return T2; + } + return T1; +} + + //===----------------------------------------------------------------------===// // Initializer implementations //===----------------------------------------------------------------------===// @@ -400,7 +456,7 @@ Init *ListInit::convertInitListSlice(const std::vector &Elements) { return 0; Vals.push_back(getElement(Elements[i])); } - return new ListInit(Vals); + return new ListInit(Vals, getType()); } Record *ListInit::getElementAsRecord(unsigned i) const { @@ -428,10 +484,20 @@ Init *ListInit::resolveReferences(Record &R, const RecordVal *RV) { } if (Changed) - return new ListInit(Resolved); + return new ListInit(Resolved, getType()); return this; } +Init *ListInit::resolveListElementReference(Record &R, const RecordVal *IRV, + unsigned Elt) { + if (Elt >= getSize()) + return 0; // Out of range reference. + Init *E = getElement(Elt); + if (!dynamic_cast(E)) // If the element is set + return E; // Replace the VarListElementInit with it. + return 0; +} + std::string ListInit::getAsString() const { std::string Result = "["; for (unsigned i = 0, e = Values.size(); i != e; ++i) { @@ -540,7 +606,7 @@ Init *UnOpInit::Fold(Record *CurRec, MultiClass *CurMultiClass) { assert(0 && "Empty list in cdr"); return 0; } - ListInit *Result = new ListInit(LHSl->begin()+1, LHSl->end()); + ListInit *Result = new ListInit(LHSl->begin()+1, LHSl->end(), LHSl->getType()); return Result; } break; @@ -555,6 +621,16 @@ Init *UnOpInit::Fold(Record *CurRec, MultiClass *CurMultiClass) { return new IntInit(0); } } + StringInit *LHSs = dynamic_cast(LHS); + if (LHSs) { + if (LHSs->getValue().empty()) { + return new IntInit(1); + } + else { + return new IntInit(0); + } + } + break; } } @@ -667,8 +743,8 @@ Init *BinOpInit::Fold(Record *CurRec, MultiClass *CurMultiClass) { if (Record *D = Records.getDef(Name)) return new DefInit(D); - cerr << "Variable not defined: '" + Name + "'\n"; - assert(0 && "Variable not found"); + cerr << "Variable not defined in !nameconcat: '" + Name + "'\n"; + assert(0 && "Variable not found in !nameconcat"); return 0; } break; @@ -881,7 +957,7 @@ static Init *ForeachHelper(Init *LHS, Init *MHS, Init *RHS, RecTy *Type, delete NewOp; } } - return new ListInit(NewList); + return new ListInit(NewList, MHSl->getType()); } } return 0; @@ -1027,7 +1103,7 @@ Init *TypedInit::convertInitListSlice(const std::vector &Elements) { ListInits.reserve(Elements.size()); for (unsigned i = 0, e = Elements.size(); i != e; ++i) ListInits.push_back(new VarListElementInit(this, Elements[i])); - return new ListInit(ListInits); + return new ListInit(ListInits, T); } diff --git a/utils/TableGen/Record.h b/utils/TableGen/Record.h index 3a15ca5767f..8ef833d554d 100644 --- a/utils/TableGen/Record.h +++ b/utils/TableGen/Record.h @@ -442,7 +442,10 @@ public: virtual bool baseClassOf(const RecordRecTy *RHS) const; }; - +/// resolveTypes - Find a common type that T1 and T2 convert to. +/// Return 0 if no such type exists. +/// +RecTy *resolveTypes(RecTy *T1, RecTy *T2); //===----------------------------------------------------------------------===// // Initializer Classes @@ -618,10 +621,10 @@ public: /// IntInit - 7 - Represent an initalization by a literal integer value. /// -class IntInit : public Init { +class IntInit : public TypedInit { int64_t Value; public: - explicit IntInit(int64_t V) : Value(V) {} + explicit IntInit(int64_t V) : TypedInit(new IntRecTy), Value(V) {} int64_t getValue() const { return Value; } @@ -631,6 +634,25 @@ public: virtual Init *convertInitializerBitRange(const std::vector &Bits); virtual std::string getAsString() const; + + /// resolveBitReference - This method is used to implement + /// VarBitInit::resolveReferences. If the bit is able to be resolved, we + /// simply return the resolved value, otherwise we return null. + /// + virtual Init *resolveBitReference(Record &R, const RecordVal *RV, + unsigned Bit) { + assert(0 && "Illegal bit reference off int"); + return 0; + } + + /// resolveListElementReference - This method is used to implement + /// VarListElementInit::resolveReferences. If the list element is resolvable + /// now, we return the resolved value, otherwise we return null. + virtual Init *resolveListElementReference(Record &R, const RecordVal *RV, + unsigned Elt) { + assert(0 && "Illegal element reference off int"); + return 0; + } }; @@ -688,17 +710,18 @@ public: /// ListInit - [AL, AH, CL] - Represent a list of defs /// -class ListInit : public Init { +class ListInit : public TypedInit { std::vector Values; public: typedef std::vector::iterator iterator; typedef std::vector::const_iterator const_iterator; - explicit ListInit(std::vector &Vs) { + explicit ListInit(std::vector &Vs, RecTy *EltTy) + : TypedInit(new ListRecTy(EltTy)) { Values.swap(Vs); } - explicit ListInit(iterator Start, iterator End) - : Values(Start, End) {} + explicit ListInit(iterator Start, iterator End, RecTy *EltTy) + : TypedInit(new ListRecTy(EltTy)), Values(Start, End) {} unsigned getSize() const { return Values.size(); } Init *getElement(unsigned i) const { @@ -730,6 +753,22 @@ public: inline size_t size () const { return Values.size(); } inline bool empty() const { return Values.empty(); } + + /// resolveBitReference - This method is used to implement + /// VarBitInit::resolveReferences. If the bit is able to be resolved, we + /// simply return the resolved value, otherwise we return null. + /// + virtual Init *resolveBitReference(Record &R, const RecordVal *RV, + unsigned Bit) { + assert(0 && "Illegal bit reference off list"); + return 0; + } + + /// resolveListElementReference - This method is used to implement + /// VarListElementInit::resolveReferences. If the list element is resolvable + /// now, we return the resolved value, otherwise we return null. + virtual Init *resolveListElementReference(Record &R, const RecordVal *RV, + unsigned Elt); }; diff --git a/utils/TableGen/TGParser.cpp b/utils/TableGen/TGParser.cpp index b4d448b1e8c..7d3d1b37a94 100644 --- a/utils/TableGen/TGParser.cpp +++ b/utils/TableGen/TGParser.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include +#include #include "TGParser.h" #include "Record.h" @@ -396,7 +397,7 @@ ParseSubClassReference(Record *CurRec, bool isDefm) { return Result; } - Result.TemplateArgs = ParseValueList(CurRec); + Result.TemplateArgs = ParseValueList(CurRec, Result.Rec); if (Result.TemplateArgs.empty()) { Result.Rec = 0; // Error parsing value list. return Result; @@ -438,7 +439,7 @@ ParseSubMultiClassReference(MultiClass *CurMC) { return Result; } - Result.TemplateArgs = ParseValueList(&CurMC->Rec); + Result.TemplateArgs = ParseValueList(&CurMC->Rec, &Result.MC->Rec); if (Result.TemplateArgs.empty()) { Result.MC = 0; // Error parsing value list. return Result; @@ -728,21 +729,28 @@ Init *TGParser::ParseOperation(Record *CurRec) { || Code == UnOpInit::CDR || Code == UnOpInit::LNULL) { ListInit *LHSl = dynamic_cast(LHS); + StringInit *LHSs = dynamic_cast(LHS); TypedInit *LHSt = dynamic_cast(LHS); - if (LHSl == 0 && LHSt == 0) { - TokError("expected list type argument in unary operator"); + if (LHSl == 0 && LHSs == 0 && LHSt == 0) { + TokError("expected list or string type argument in unary operator"); return 0; } if (LHSt) { ListRecTy *LType = dynamic_cast(LHSt->getType()); - if (LType == 0) { - TokError("expected list type argumnet in unary operator"); + StringRecTy *SType = dynamic_cast(LHSt->getType()); + if (LType == 0 && SType == 0) { + TokError("expected list or string type argumnet in unary operator"); return 0; } } if (Code == UnOpInit::CAR || Code == UnOpInit::CDR) { + if (LHSl == 0 && LHSt == 0) { + TokError("expected list type argumnet in unary operator"); + return 0; + } + if (LHSl && LHSl->getSize() == 0) { TokError("empty list argument in unary operator"); return 0; @@ -1017,7 +1025,7 @@ RecTy *TGParser::ParseOperatorType(void) { /// SimpleValue ::= SRLTOK '(' Value ',' Value ')' /// SimpleValue ::= STRCONCATTOK '(' Value ',' Value ')' /// -Init *TGParser::ParseSimpleValue(Record *CurRec) { +Init *TGParser::ParseSimpleValue(Record *CurRec, RecTy *ItemType) { Init *R = 0; switch (Lex.getCode()) { default: TokError("Unknown token when parsing a value"); break; @@ -1049,15 +1057,7 @@ Init *TGParser::ParseSimpleValue(Record *CurRec) { TokError("expected non-empty value list"); return 0; } - std::vector ValueList = ParseValueList(CurRec); - if (ValueList.empty()) return 0; - - if (Lex.getCode() != tgtok::greater) { - TokError("expected '>' at end of value list"); - return 0; - } - Lex.Lex(); // eat the '>' - + // This is a CLASS expression. This is supposed to synthesize // a new anonymous definition, deriving from CLASS with no // body. @@ -1066,6 +1066,15 @@ Init *TGParser::ParseSimpleValue(Record *CurRec) { Error(NameLoc, "Expected a class name, got '" + Name + "'"); return 0; } + + std::vector ValueList = ParseValueList(CurRec, Class); + if (ValueList.empty()) return 0; + + if (Lex.getCode() != tgtok::greater) { + TokError("expected '>' at end of value list"); + return 0; + } + Lex.Lex(); // eat the '>' // Create the new record, set it as CurRec temporarily. static unsigned AnonCounter = 0; @@ -1114,8 +1123,22 @@ Init *TGParser::ParseSimpleValue(Record *CurRec) { Lex.Lex(); // eat the '[' std::vector Vals; + RecTy *DeducedEltTy = 0; + ListRecTy *GivenListTy = 0; + + if (ItemType != 0) { + ListRecTy *ListType = dynamic_cast(ItemType); + if (ListType == 0) { + std::stringstream s; + s << "Type mismatch for list, expected list type, got " + << ItemType->getAsString(); + TokError(s.str()); + } + GivenListTy = ListType; + } + if (Lex.getCode() != tgtok::r_square) { - Vals = ParseValueList(CurRec); + Vals = ParseValueList(CurRec, 0, GivenListTy ? GivenListTy->getElementType() : 0); if (Vals.empty()) return 0; } if (Lex.getCode() != tgtok::r_square) { @@ -1123,7 +1146,77 @@ Init *TGParser::ParseSimpleValue(Record *CurRec) { return 0; } Lex.Lex(); // eat the ']' - return new ListInit(Vals); + + RecTy *GivenEltTy = 0; + if (Lex.getCode() == tgtok::less) { + // Optional list element type + Lex.Lex(); // eat the '<' + + GivenEltTy = ParseType(); + if (GivenEltTy == 0) { + // Couldn't parse element type + return 0; + } + + if (Lex.getCode() != tgtok::greater) { + TokError("expected '>' at end of list element type"); + return 0; + } + Lex.Lex(); // eat the '>' + } + + // Check elements + RecTy *EltTy = 0; + for (std::vector::iterator i = Vals.begin(), ie = Vals.end(); + i != ie; + ++i) { + TypedInit *TArg = dynamic_cast(*i); + if (TArg == 0) { + TokError("Untyped list element"); + return 0; + } + if (EltTy != 0) { + EltTy = resolveTypes(EltTy, TArg->getType()); + if (EltTy == 0) { + TokError("Incompatible types in list elements"); + return 0; + } + } + else { + EltTy = TArg->getType(); + } + } + + if (GivenEltTy != 0) { + if (EltTy != 0) { + // Verify consistency + if (!EltTy->typeIsConvertibleTo(GivenEltTy)) { + TokError("Incompatible types in list elements"); + return 0; + } + } + EltTy = GivenEltTy; + } + + if (EltTy == 0) { + if (ItemType == 0) { + TokError("No type for list"); + return 0; + } + DeducedEltTy = GivenListTy->getElementType(); + } + else { + // Make sure the deduced type is compatible with the given type + if (GivenListTy) { + if (!EltTy->typeIsConvertibleTo(GivenListTy->getElementType())) { + TokError("Element type mismatch for list"); + return 0; + } + } + DeducedEltTy = EltTy; + } + + return new ListInit(Vals, DeducedEltTy); } case tgtok::l_paren: { // Value ::= '(' IDValue DagArgList ')' Lex.Lex(); // eat the '(' @@ -1200,8 +1293,8 @@ Init *TGParser::ParseSimpleValue(Record *CurRec) { /// ValueSuffix ::= '[' BitList ']' /// ValueSuffix ::= '.' ID /// -Init *TGParser::ParseValue(Record *CurRec) { - Init *Result = ParseSimpleValue(CurRec); +Init *TGParser::ParseValue(Record *CurRec, RecTy *ItemType) { + Init *Result = ParseSimpleValue(CurRec, ItemType); if (Result == 0) return 0; // Parse the suffixes now if present. @@ -1306,15 +1399,31 @@ TGParser::ParseDagArgList(Record *CurRec) { /// /// ValueList ::= Value (',' Value) /// -std::vector TGParser::ParseValueList(Record *CurRec) { +std::vector TGParser::ParseValueList(Record *CurRec, Record *ArgsRec, RecTy *EltTy) { std::vector Result; - Result.push_back(ParseValue(CurRec)); + RecTy *ItemType = EltTy; + int ArgN = 0; + if (ArgsRec != 0 && EltTy == 0) { + const std::vector &TArgs = ArgsRec->getTemplateArgs(); + const RecordVal *RV = ArgsRec->getValue(TArgs[ArgN]); + assert(RV && "Template argument record not found??"); + ItemType = RV->getType(); + ++ArgN; + } + Result.push_back(ParseValue(CurRec, ItemType)); if (Result.back() == 0) return std::vector(); while (Lex.getCode() == tgtok::comma) { Lex.Lex(); // Eat the comma - Result.push_back(ParseValue(CurRec)); + if (ArgsRec != 0 && EltTy == 0) { + const std::vector &TArgs = ArgsRec->getTemplateArgs(); + const RecordVal *RV = ArgsRec->getValue(TArgs[ArgN]); + assert(RV && "Template argument record not found??"); + ItemType = RV->getType(); + ++ArgN; + } + Result.push_back(ParseValue(CurRec, ItemType)); if (Result.back() == 0) return std::vector(); } @@ -1369,7 +1478,7 @@ std::string TGParser::ParseDeclaration(Record *CurRec, if (Lex.getCode() == tgtok::equal) { Lex.Lex(); TGLoc ValLoc = Lex.getLoc(); - Init *Val = ParseValue(CurRec); + Init *Val = ParseValue(CurRec, Type); if (Val == 0 || SetValue(CurRec, ValLoc, DeclName, std::vector(), Val)) return ""; @@ -1447,7 +1556,13 @@ bool TGParser::ParseBodyItem(Record *CurRec) { return TokError("expected '=' in let expression"); Lex.Lex(); // eat the '='. - Init *Val = ParseValue(CurRec); + RecordVal *Field = CurRec->getValue(FieldName); + if (Field == 0) + return TokError("Value '" + FieldName + "' unknown!"); + + RecTy *Type = Field->getType(); + + Init *Val = ParseValue(CurRec, Type); if (Val == 0) return true; if (Lex.getCode() != tgtok::semi) diff --git a/utils/TableGen/TGParser.h b/utils/TableGen/TGParser.h index f03052eb799..3af467d16ab 100644 --- a/utils/TableGen/TGParser.h +++ b/utils/TableGen/TGParser.h @@ -93,9 +93,9 @@ private: // Parser methods. Init *ParseIDValue(Record *CurRec); Init *ParseIDValue(Record *CurRec, const std::string &Name, TGLoc NameLoc); - Init *ParseSimpleValue(Record *CurRec); - Init *ParseValue(Record *CurRec); - std::vector ParseValueList(Record *CurRec); + Init *ParseSimpleValue(Record *CurRec, RecTy *ItemType = 0); + Init *ParseValue(Record *CurRec, RecTy *ItemType = 0); + std::vector ParseValueList(Record *CurRec, Record *ArgsRec = 0, RecTy *EltTy = 0); std::vector > ParseDagArgList(Record *); bool ParseOptionalRangeList(std::vector &Ranges); bool ParseOptionalBitList(std::vector &Ranges); -- 2.11.0