summaryrefslogtreecommitdiff
path: root/utils
diff options
context:
space:
mode:
authorDavid Greene <greened@obbligato.org>2009-06-08 20:23:18 +0000
committerDavid Greene <greened@obbligato.org>2009-06-08 20:23:18 +0000
commite1b469170bb3ab259fd488fb95c29efe802cdd6a (patch)
treeb3c98585bc4d30950a3c48ba9c865c47792aec89 /utils
parent77c489dcae2d7906fae653e2d25e023004d1b9e4 (diff)
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 []<type> syntax, where <type> is the list element type. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@73078 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'utils')
-rw-r--r--utils/TableGen/CodeGenDAGPatterns.cpp23
-rw-r--r--utils/TableGen/Record.cpp92
-rw-r--r--utils/TableGen/Record.h53
-rw-r--r--utils/TableGen/TGParser.cpp165
-rw-r--r--utils/TableGen/TGParser.h6
5 files changed, 294 insertions, 45 deletions
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<Init*> 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<TypedInit*>(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<ListRecTy*>(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<RecordRecTy*>(T1);
+ if (RecTy1) {
+ // See if T2 inherits from a type T1 also inherits from
+ const std::vector<Record *> &T1SuperClasses = RecTy1->getRecord()->getSuperClasses();
+ for(std::vector<Record *>::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<RecordRecTy*>(T2);
+ if (RecTy2) {
+ // See if T1 inherits from a type T2 also inherits from
+ const std::vector<Record *> &T2SuperClasses = RecTy2->getRecord()->getSuperClasses();
+ for(std::vector<Record *>::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<unsigned> &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<UnsetInit*>(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<StringInit*>(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<unsigned> &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<unsigned> &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<Init*> Values;
public:
typedef std::vector<Init*>::iterator iterator;
typedef std::vector<Init*>::const_iterator const_iterator;
- explicit ListInit(std::vector<Init*> &Vs) {
+ explicit ListInit(std::vector<Init*> &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 <algorithm>
+#include <sstream>
#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<ListInit*>(LHS);
+ StringInit *LHSs = dynamic_cast<StringInit*>(LHS);
TypedInit *LHSt = dynamic_cast<TypedInit*>(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<ListRecTy*>(LHSt->getType());
- if (LType == 0) {
- TokError("expected list type argumnet in unary operator");
+ StringRecTy *SType = dynamic_cast<StringRecTy*>(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<Init*> 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<initvalslist> expression. This is supposed to synthesize
// a new anonymous definition, deriving from CLASS<initvalslist> with no
// body.
@@ -1066,6 +1066,15 @@ Init *TGParser::ParseSimpleValue(Record *CurRec) {
Error(NameLoc, "Expected a class name, got '" + Name + "'");
return 0;
}
+
+ std::vector<Init*> 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<Init*> Vals;
+ RecTy *DeducedEltTy = 0;
+ ListRecTy *GivenListTy = 0;
+
+ if (ItemType != 0) {
+ ListRecTy *ListType = dynamic_cast<ListRecTy*>(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<Init *>::iterator i = Vals.begin(), ie = Vals.end();
+ i != ie;
+ ++i) {
+ TypedInit *TArg = dynamic_cast<TypedInit*>(*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<Init*> TGParser::ParseValueList(Record *CurRec) {
+std::vector<Init*> TGParser::ParseValueList(Record *CurRec, Record *ArgsRec, RecTy *EltTy) {
std::vector<Init*> Result;
- Result.push_back(ParseValue(CurRec));
+ RecTy *ItemType = EltTy;
+ int ArgN = 0;
+ if (ArgsRec != 0 && EltTy == 0) {
+ const std::vector<std::string> &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<Init*>();
while (Lex.getCode() == tgtok::comma) {
Lex.Lex(); // Eat the comma
- Result.push_back(ParseValue(CurRec));
+ if (ArgsRec != 0 && EltTy == 0) {
+ const std::vector<std::string> &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<Init*>();
}
@@ -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<unsigned>(), 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<Init*> ParseValueList(Record *CurRec);
+ Init *ParseSimpleValue(Record *CurRec, RecTy *ItemType = 0);
+ Init *ParseValue(Record *CurRec, RecTy *ItemType = 0);
+ std::vector<Init*> ParseValueList(Record *CurRec, Record *ArgsRec = 0, RecTy *EltTy = 0);
std::vector<std::pair<llvm::Init*, std::string> > ParseDagArgList(Record *);
bool ParseOptionalRangeList(std::vector<unsigned> &Ranges);
bool ParseOptionalBitList(std::vector<unsigned> &Ranges);