//
//===----------------------------------------------------------------------===//
-#include <algorithm>
-
#include "TGParser.h"
#include "Record.h"
#include "llvm/ADT/StringExtras.h"
-#include "llvm/Support/Streams.h"
+#include <algorithm>
+#include <sstream>
using namespace llvm;
//===----------------------------------------------------------------------===//
namespace llvm {
struct SubClassReference {
- TGLoc RefLoc;
+ SMLoc RefLoc;
Record *Rec;
std::vector<Init*> TemplateArgs;
SubClassReference() : Rec(0) {}
};
struct SubMultiClassReference {
- TGLoc RefLoc;
+ SMLoc RefLoc;
MultiClass *MC;
std::vector<Init*> TemplateArgs;
SubMultiClassReference() : MC(0) {}
};
void SubMultiClassReference::dump() const {
- cerr << "Multiclass:\n";
+ errs() << "Multiclass:\n";
MC->dump();
- cerr << "Template args:\n";
+ errs() << "Template args:\n";
for (std::vector<Init *>::const_iterator i = TemplateArgs.begin(),
iend = TemplateArgs.end();
i != iend;
} // end namespace llvm
-bool TGParser::AddValue(Record *CurRec, TGLoc Loc, const RecordVal &RV) {
+bool TGParser::AddValue(Record *CurRec, SMLoc Loc, const RecordVal &RV) {
if (CurRec == 0)
CurRec = &CurMultiClass->Rec;
/// SetValue -
/// Return true on error, false on success.
-bool TGParser::SetValue(Record *CurRec, TGLoc Loc, const std::string &ValName,
+bool TGParser::SetValue(Record *CurRec, SMLoc Loc, const std::string &ValName,
const std::vector<unsigned> &BitList, Init *V) {
if (!V) return false;
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;
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;
if (Lex.getCode() != tgtok::less)
return false;
- TGLoc StartLoc = Lex.getLoc();
+ SMLoc StartLoc = Lex.getLoc();
Lex.Lex(); // eat the '<'
// Parse the range list.
if (Lex.getCode() != tgtok::l_brace)
return false;
- TGLoc StartLoc = Lex.getLoc();
+ SMLoc StartLoc = Lex.getLoc();
Lex.Lex(); // eat the '{'
// Parse the range list.
Init *TGParser::ParseIDValue(Record *CurRec) {
assert(Lex.getCode() == tgtok::Id && "Expected ID in ParseIDValue");
std::string Name = Lex.getCurStrVal();
- TGLoc Loc = Lex.getLoc();
+ SMLoc Loc = Lex.getLoc();
Lex.Lex();
return ParseIDValue(CurRec, Name, Loc);
}
/// ParseIDValue - This is just like ParseIDValue above, but it assumes the ID
/// has already been read.
Init *TGParser::ParseIDValue(Record *CurRec,
- const std::string &Name, TGLoc NameLoc) {
+ const std::string &Name, SMLoc NameLoc) {
if (CurRec) {
if (const RecordVal *RV = CurRec->getValue(Name))
return new VarInit(Name, RV->getType());
|| 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;
/// 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;
R = new CodeInit(Lex.getCurStrVal()); Lex.Lex(); break;
case tgtok::question: R = new UnsetInit(); Lex.Lex(); break;
case tgtok::Id: {
- TGLoc NameLoc = Lex.getLoc();
+ SMLoc NameLoc = Lex.getLoc();
std::string Name = Lex.getCurStrVal();
if (Lex.Lex() != tgtok::less) // consume the Id.
return ParseIDValue(CurRec, Name, NameLoc); // Value ::= IDValue
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.
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;
return new DefInit(NewRec);
}
case tgtok::l_brace: { // Value ::= '{' ValueList '}'
- TGLoc BraceLoc = Lex.getLoc();
+ SMLoc BraceLoc = Lex.getLoc();
Lex.Lex(); // eat the '{'
std::vector<Init*> Vals;
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) {
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 '('
/// 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.
switch (Lex.getCode()) {
default: return Result;
case tgtok::l_brace: {
- TGLoc CurlyLoc = Lex.getLoc();
+ SMLoc CurlyLoc = Lex.getLoc();
Lex.Lex(); // eat the '{'
std::vector<unsigned> Ranges = ParseRangeList();
if (Ranges.empty()) return 0;
break;
}
case tgtok::l_square: {
- TGLoc SquareLoc = Lex.getLoc();
+ SMLoc SquareLoc = Lex.getLoc();
Lex.Lex(); // eat the '['
std::vector<unsigned> Ranges = ParseRangeList();
if (Ranges.empty()) return 0;
///
/// 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;
+ unsigned 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();
+ if (ArgN >= TArgs.size()) {
+ TokError("too many template arguments");
+ return std::vector<Init*>();
+ }
+ 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*>();
}
return "";
}
- TGLoc IdLoc = Lex.getLoc();
+ SMLoc IdLoc = Lex.getLoc();
std::string DeclName = Lex.getCurStrVal();
Lex.Lex();
// If a value is present, parse it.
if (Lex.getCode() == tgtok::equal) {
Lex.Lex();
- TGLoc ValLoc = Lex.getLoc();
- Init *Val = ParseValue(CurRec);
+ SMLoc ValLoc = Lex.getLoc();
+ Init *Val = ParseValue(CurRec, Type);
if (Val == 0 ||
SetValue(CurRec, ValLoc, DeclName, std::vector<unsigned>(), Val))
return "";
if (Lex.Lex() != tgtok::Id)
return TokError("expected field identifier after let");
- TGLoc IdLoc = Lex.getLoc();
+ SMLoc IdLoc = Lex.getLoc();
std::string FieldName = Lex.getCurStrVal();
Lex.Lex(); // eat the field name.
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)
/// DefInst ::= DEF ObjectName ObjectBody
///
llvm::Record *TGParser::ParseDef(MultiClass *CurMultiClass) {
- TGLoc DefLoc = Lex.getLoc();
+ SMLoc DefLoc = Lex.getLoc();
assert(Lex.getCode() == tgtok::Def && "Unknown tok");
Lex.Lex(); // Eat the 'def' token.
return std::vector<LetRecord>();
}
std::string Name = Lex.getCurStrVal();
- TGLoc NameLoc = Lex.getLoc();
+ SMLoc NameLoc = Lex.getLoc();
Lex.Lex(); // Eat the identifier.
// Check for an optional RangeList.
if (ParseObject())
return true;
} else { // Object ::= LETCommand '{' ObjectList '}'
- TGLoc BraceLoc = Lex.getLoc();
+ SMLoc BraceLoc = Lex.getLoc();
// Otherwise, this is a group let.
Lex.Lex(); // eat the '{'.
if (Lex.Lex() != tgtok::Id) // eat the defm.
return TokError("expected identifier after defm");
- TGLoc DefmPrefixLoc = Lex.getLoc();
+ SMLoc DefmPrefixLoc = Lex.getLoc();
std::string DefmPrefix = Lex.getCurStrVal();
if (Lex.Lex() != tgtok::colon)
return TokError("expected ':' after defm identifier");
// eat the colon.
Lex.Lex();
- TGLoc SubClassLoc = Lex.getLoc();
+ SMLoc SubClassLoc = Lex.getLoc();
SubClassReference Ref = ParseSubClassReference(0, true);
while (1) {