summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/TableGen/Record.cpp131
-rw-r--r--llvm/lib/TableGen/TGLexer.cpp1
-rw-r--r--llvm/lib/TableGen/TGLexer.h2
-rw-r--r--llvm/lib/TableGen/TGParser.cpp90
-rw-r--r--llvm/lib/TableGen/TGParser.h1
5 files changed, 224 insertions, 1 deletions
diff --git a/llvm/lib/TableGen/Record.cpp b/llvm/lib/TableGen/Record.cpp
index 79f8907d4b5..ab3dfce5e84 100644
--- a/llvm/lib/TableGen/Record.cpp
+++ b/llvm/lib/TableGen/Record.cpp
@@ -1693,6 +1693,137 @@ Init *FieldInit::Fold(Record *CurRec) const {
return const_cast<FieldInit *>(this);
}
+static void ProfileCondOpInit(FoldingSetNodeID &ID,
+ ArrayRef<Init *> CondRange,
+ ArrayRef<Init *> ValRange,
+ const RecTy *ValType) {
+ assert(CondRange.size() == ValRange.size() &&
+ "Number of conditions and values must match!");
+ ID.AddPointer(ValType);
+ ArrayRef<Init *>::iterator Case = CondRange.begin();
+ ArrayRef<Init *>::iterator Val = ValRange.begin();
+
+ while (Case != CondRange.end()) {
+ ID.AddPointer(*Case++);
+ ID.AddPointer(*Val++);
+ }
+}
+
+void CondOpInit::Profile(FoldingSetNodeID &ID) const {
+ ProfileCondOpInit(ID,
+ makeArrayRef(getTrailingObjects<Init *>(), NumConds),
+ makeArrayRef(getTrailingObjects<Init *>() + NumConds, NumConds),
+ ValType);
+}
+
+CondOpInit *
+CondOpInit::get(ArrayRef<Init *> CondRange,
+ ArrayRef<Init *> ValRange, RecTy *Ty) {
+ assert(CondRange.size() == ValRange.size() &&
+ "Number of conditions and values must match!");
+
+ static FoldingSet<CondOpInit> ThePool;
+ FoldingSetNodeID ID;
+ ProfileCondOpInit(ID, CondRange, ValRange, Ty);
+
+ void *IP = nullptr;
+ if (CondOpInit *I = ThePool.FindNodeOrInsertPos(ID, IP))
+ return I;
+
+ void *Mem = Allocator.Allocate(totalSizeToAlloc<Init *>(2*CondRange.size()),
+ alignof(BitsInit));
+ CondOpInit *I = new(Mem) CondOpInit(CondRange.size(), Ty);
+
+ std::uninitialized_copy(CondRange.begin(), CondRange.end(),
+ I->getTrailingObjects<Init *>());
+ std::uninitialized_copy(ValRange.begin(), ValRange.end(),
+ I->getTrailingObjects<Init *>()+CondRange.size());
+ ThePool.InsertNode(I, IP);
+ return I;
+}
+
+Init *CondOpInit::resolveReferences(Resolver &R) const {
+ SmallVector<Init*, 4> NewConds;
+ bool Changed = false;
+ for (const Init *Case : getConds()) {
+ Init *NewCase = Case->resolveReferences(R);
+ NewConds.push_back(NewCase);
+ Changed |= NewCase != Case;
+ }
+
+ SmallVector<Init*, 4> NewVals;
+ for (const Init *Val : getVals()) {
+ Init *NewVal = Val->resolveReferences(R);
+ NewVals.push_back(NewVal);
+ Changed |= NewVal != Val;
+ }
+
+ if (Changed)
+ return (CondOpInit::get(NewConds, NewVals,
+ getValType()))->Fold(R.getCurrentRecord());
+
+ return const_cast<CondOpInit *>(this);
+}
+
+Init *CondOpInit::Fold(Record *CurRec) const {
+ for ( unsigned i = 0; i < NumConds; ++i) {
+ Init *Cond = getCond(i);
+ Init *Val = getVal(i);
+
+ if (IntInit *CondI = dyn_cast_or_null<IntInit>(
+ Cond->convertInitializerTo(IntRecTy::get()))) {
+ if (CondI->getValue())
+ return Val->convertInitializerTo(getValType());
+ } else
+ return const_cast<CondOpInit *>(this);
+ }
+
+ PrintFatalError(CurRec->getLoc(),
+ CurRec->getName() +
+ " does not have any true condition in:" +
+ this->getAsString());
+ return nullptr;
+}
+
+bool CondOpInit::isConcrete() const {
+ for (const Init *Case : getConds())
+ if (!Case->isConcrete())
+ return false;
+
+ for (const Init *Val : getVals())
+ if (!Val->isConcrete())
+ return false;
+
+ return true;
+}
+
+bool CondOpInit::isComplete() const {
+ for (const Init *Case : getConds())
+ if (!Case->isComplete())
+ return false;
+
+ for (const Init *Val : getVals())
+ if (!Val->isConcrete())
+ return false;
+
+ return true;
+}
+
+std::string CondOpInit::getAsString() const {
+ std::string Result = "!cond(";
+ for (unsigned i = 0; i < getNumConds(); i++) {
+ Result += getCond(i)->getAsString() + ": ";
+ Result += getVal(i)->getAsString();
+ if (i != getNumConds()-1)
+ Result += ", ";
+ }
+ return Result + ")";
+}
+
+Init *CondOpInit::getBit(unsigned Bit) const {
+ return VarBitInit::get(const_cast<CondOpInit *>(this), Bit);
+}
+
static void ProfileDagInit(FoldingSetNodeID &ID, Init *V, StringInit *VN,
ArrayRef<Init *> ArgRange,
ArrayRef<StringInit *> NameRange) {
diff --git a/llvm/lib/TableGen/TGLexer.cpp b/llvm/lib/TableGen/TGLexer.cpp
index 5dca134f8e8..dbbffda7b35 100644
--- a/llvm/lib/TableGen/TGLexer.cpp
+++ b/llvm/lib/TableGen/TGLexer.cpp
@@ -544,6 +544,7 @@ tgtok::TokKind TGLexer::LexExclaim() {
.Case("ge", tgtok::XGe)
.Case("gt", tgtok::XGt)
.Case("if", tgtok::XIf)
+ .Case("cond", tgtok::XCond)
.Case("isa", tgtok::XIsA)
.Case("head", tgtok::XHead)
.Case("tail", tgtok::XTail)
diff --git a/llvm/lib/TableGen/TGLexer.h b/llvm/lib/TableGen/TGLexer.h
index fcee028d3ae..0cb9ae3f567 100644
--- a/llvm/lib/TableGen/TGLexer.h
+++ b/llvm/lib/TableGen/TGLexer.h
@@ -50,7 +50,7 @@ namespace tgtok {
// !keywords.
XConcat, XADD, XAND, XOR, XSRA, XSRL, XSHL, XListConcat, XStrConcat, XCast,
- XSubst, XForEach, XFoldl, XHead, XTail, XSize, XEmpty, XIf, XEq, XIsA, XDag,
+ XSubst, XForEach, XFoldl, XHead, XTail, XSize, XEmpty, XIf, XCond, XEq, XIsA, XDag,
XNe, XLe, XLt, XGe, XGt,
// Integer value.
diff --git a/llvm/lib/TableGen/TGParser.cpp b/llvm/lib/TableGen/TGParser.cpp
index cfbab2cf700..22b4b16bc39 100644
--- a/llvm/lib/TableGen/TGParser.cpp
+++ b/llvm/lib/TableGen/TGParser.cpp
@@ -1444,6 +1444,9 @@ Init *TGParser::ParseOperation(Record *CurRec, RecTy *ItemType) {
return (TernOpInit::get(Code, LHS, MHS, RHS, Type))->Fold(CurRec);
}
+ case tgtok::XCond:
+ return ParseOperationCond(CurRec, ItemType);
+
case tgtok::XFoldl: {
// Value ::= !foldl '(' Id ',' Id ',' Value ',' Value ',' Value ')'
Lex.Lex(); // eat the operation
@@ -1602,6 +1605,91 @@ RecTy *TGParser::ParseOperatorType() {
return Type;
}
+Init *TGParser::ParseOperationCond(Record *CurRec, RecTy *ItemType) {
+ Lex.Lex(); // eat the operation 'cond'
+
+ if (Lex.getCode() != tgtok::l_paren) {
+ TokError("expected '(' after !cond operator");
+ return nullptr;
+ }
+ Lex.Lex(); // eat the '('
+
+ // Parse through '[Case: Val,]+'
+ SmallVector<Init *, 4> Case;
+ SmallVector<Init *, 4> Val;
+ while (true) {
+ if (Lex.getCode() == tgtok::r_paren) {
+ Lex.Lex(); // eat the ')'
+ break;
+ }
+
+ Init *V = ParseValue(CurRec);
+ if (!V)
+ return nullptr;
+ Case.push_back(V);
+
+ if (Lex.getCode() != tgtok::colon) {
+ TokError("expected ':' following a condition in !cond operator");
+ return nullptr;
+ }
+ Lex.Lex(); // eat the ':'
+
+ V = ParseValue(CurRec, ItemType);
+ if (!V)
+ return nullptr;
+ Val.push_back(V);
+
+ if (Lex.getCode() == tgtok::r_paren) {
+ Lex.Lex(); // eat the ')'
+ break;
+ }
+
+ if (Lex.getCode() != tgtok::comma) {
+ TokError("expected ',' or ')' following a value in !cond operator");
+ return nullptr;
+ }
+ Lex.Lex(); // eat the ','
+ }
+
+ if (Case.size() < 1) {
+ TokError("there should be at least 1 'condition : value' in the !cond operator");
+ return nullptr;
+ }
+
+ // resolve type
+ RecTy *Type = nullptr;
+ for (Init *V : Val) {
+ RecTy *VTy = nullptr;
+ if (TypedInit *Vt = dyn_cast<TypedInit>(V))
+ VTy = Vt->getType();
+ if (BitsInit *Vbits = dyn_cast<BitsInit>(V))
+ VTy = BitsRecTy::get(Vbits->getNumBits());
+ if (isa<BitInit>(V))
+ VTy = BitRecTy::get();
+
+ if (Type == nullptr) {
+ if (!isa<UnsetInit>(V))
+ Type = VTy;
+ } else {
+ if (!isa<UnsetInit>(V)) {
+ RecTy *RType = resolveTypes(Type, VTy);
+ if (!RType) {
+ TokError(Twine("inconsistent types '") + Type->getAsString() +
+ "' and '" + VTy->getAsString() + "' for !cond");
+ return nullptr;
+ }
+ Type = RType;
+ }
+ }
+ }
+
+ if (!Type) {
+ TokError("could not determine type for !cond from its arguments");
+ return nullptr;
+ }
+ return CondOpInit::get(Case, Val, Type)->Fold(CurRec);
+}
+
/// ParseSimpleValue - Parse a tblgen value. This returns null on error.
///
/// SimpleValue ::= IDValue
@@ -1620,6 +1708,7 @@ RecTy *TGParser::ParseOperatorType() {
/// SimpleValue ::= SRLTOK '(' Value ',' Value ')'
/// SimpleValue ::= LISTCONCATTOK '(' Value ',' Value ')'
/// SimpleValue ::= STRCONCATTOK '(' Value ',' Value ')'
+/// SimpleValue ::= COND '(' [Value ':' Value,]+ ')'
///
Init *TGParser::ParseSimpleValue(Record *CurRec, RecTy *ItemType,
IDParseMode Mode) {
@@ -1932,6 +2021,7 @@ Init *TGParser::ParseSimpleValue(Record *CurRec, RecTy *ItemType,
case tgtok::XListConcat:
case tgtok::XStrConcat: // Value ::= !binop '(' Value ',' Value ')'
case tgtok::XIf:
+ case tgtok::XCond:
case tgtok::XFoldl:
case tgtok::XForEach:
case tgtok::XSubst: { // Value ::= !ternop '(' Value ',' Value ',' Value ')'
diff --git a/llvm/lib/TableGen/TGParser.h b/llvm/lib/TableGen/TGParser.h
index 11d610083e7..38b782461bd 100644
--- a/llvm/lib/TableGen/TGParser.h
+++ b/llvm/lib/TableGen/TGParser.h
@@ -193,6 +193,7 @@ private: // Parser methods.
bool ParseRangePiece(SmallVectorImpl<unsigned> &Ranges);
RecTy *ParseType();
Init *ParseOperation(Record *CurRec, RecTy *ItemType);
+ Init *ParseOperationCond(Record *CurRec, RecTy *ItemType);
RecTy *ParseOperatorType();
Init *ParseObjectName(MultiClass *CurMultiClass);
Record *ParseClassID();
OpenPOWER on IntegriCloud