Make BinOps typed and require a type specifier for !nameconcat. This

allows binops to be used in typed contexts such as when passing
arguments to classes.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@69921 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
David Greene 2009-04-23 21:25:15 +00:00
parent aa809fbde1
commit e8cf21e8e3
6 changed files with 210 additions and 60 deletions

View File

@ -398,11 +398,11 @@ supported include:</p>
<dt><tt>!strconcat(a, b)</tt></dt>
<dd>A string value that is the result of concatenating the 'a' and 'b'
strings.</dd>
<dt><tt>!nameconcat(a, b)</tt></dt>
<dt><tt>!nameconcat<type>(a, b)</tt></dt>
<dd>A value that is the result of concatenating the 'a' and 'b'
strings and looking up the resulting name in the symbol table. The symbol type
determines the type of the resulting value. If the symbol is not found,
TableGen emits an error and aborts.</dd>
determines the type of the resulting value. If the symbol is not found
or the symbol type does not match 'type,' TableGen emits an error and aborts.</dd>
</dl>
<p>Note that all of the values have rules specifying how they convert to values

View File

@ -1,4 +1,4 @@
// RUN: tblgen %s | grep {add_ps} | count 2
// RUN: tblgen %s | grep {add_ps} | count 3
class ValueType<int size, int value> {
int Size = size;
@ -66,11 +66,25 @@ def int_x86_sse2_add_pd : Intrinsic<"addpd">;
multiclass arith<bits<8> opcode, string asmstr, string Intr> {
def PS : Inst<opcode, (outs VR128:$dst), (ins VR128:$src1, VR128:$src2),
!strconcat(asmstr, "\t$dst, $src1, $src2"),
[(set VR128:$dst, (!nameconcat(Intr, "_ps") VR128:$src1, VR128:$src2))]>;
[(set VR128:$dst, (!nameconcat<Intrinsic>(Intr, "_ps") VR128:$src1, VR128:$src2))]>;
def PD : Inst<opcode, (outs VR128:$dst), (ins VR128:$src1, VR128:$src2),
!strconcat(asmstr, "\t$dst, $src1, $src2"),
[(set VR128:$dst, (!nameconcat(Intr, "_pd") VR128:$src1, VR128:$src2))]>;
[(set VR128:$dst, (!nameconcat<Intrinsic>(Intr, "_pd") VR128:$src1, VR128:$src2))]>;
}
defm ADD : arith<0x58, "add", "int_x86_sse2_add">;
class IntInst<bits<8> opcode, string asmstr, Intrinsic Intr> :
Inst<opcode,(outs VR128:$dst), (ins VR128:$src1, VR128:$src2),
!strconcat(asmstr, "\t$dst, $src1, $src2"),
[(set VR128:$dst, (Intr VR128:$src1, VR128:$src2))]>;
multiclass arith_int<bits<8> opcode, string asmstr, string Intr> {
def PS_Int : IntInst<opcode, asmstr, !nameconcat<Intrinsic>(Intr, "_ps")>;
def PD_Int : IntInst<opcode, asmstr, !nameconcat<Intrinsic>(Intr, "_pd")>;
}
defm ADD : arith_int<0x58, "add", "int_x86_sse2_add">;

View File

@ -127,7 +127,7 @@ CodeGenInstruction::CodeGenInstruction(Record *R, const std::string &AsmStr)
OperandList.clear();
return;
}
DI = (DagInit*)(new BinOpInit(BinOpInit::CONCAT, DI, IDI))->Fold(R, 0);
DI = (DagInit*)(new BinOpInit(BinOpInit::CONCAT, DI, IDI, new DagRecTy))->Fold(R, 0);
unsigned MIOperandNo = 0;
std::set<std::string> OperandNames;

View File

@ -138,10 +138,21 @@ Init *StringRecTy::convertValue(BinOpInit *BO) {
Init *R = BO->getRHS()->convertInitializerTo(this);
if (L == 0 || R == 0) return 0;
if (L != BO->getLHS() || R != BO->getRHS())
return new BinOpInit(BinOpInit::STRCONCAT, L, R);
return new BinOpInit(BinOpInit::STRCONCAT, L, R, new StringRecTy);
return BO;
}
return 0;
if (BO->getOpcode() == BinOpInit::NAMECONCAT) {
if (BO->getType()->getAsString() == getAsString()) {
Init *L = BO->getLHS()->convertInitializerTo(this);
Init *R = BO->getRHS()->convertInitializerTo(this);
if (L == 0 || R == 0) return 0;
if (L != BO->getLHS() || R != BO->getRHS())
return new BinOpInit(BinOpInit::NAMECONCAT, L, R, new StringRecTy);
return BO;
}
}
return convertValue((TypedInit*)BO);
}
@ -195,9 +206,19 @@ Init *DagRecTy::convertValue(BinOpInit *BO) {
Init *R = BO->getRHS()->convertInitializerTo(this);
if (L == 0 || R == 0) return 0;
if (L != BO->getLHS() || R != BO->getRHS())
return new BinOpInit(BinOpInit::CONCAT, L, R);
return new BinOpInit(BinOpInit::CONCAT, L, R, new DagRecTy);
return BO;
}
if (BO->getOpcode() == BinOpInit::NAMECONCAT) {
if (BO->getType()->getAsString() == getAsString()) {
Init *L = BO->getLHS()->convertInitializerTo(this);
Init *R = BO->getRHS()->convertInitializerTo(this);
if (L == 0 || R == 0) return 0;
if (L != BO->getLHS() || R != BO->getRHS())
return new BinOpInit(BinOpInit::CONCAT, L, R, new DagRecTy);
return BO;
}
}
return 0;
}
@ -445,13 +466,22 @@ Init *BinOpInit::Fold(Record *CurRec, MultiClass *CurMultiClass) {
// From TGParser::ParseIDValue
if (CurRec) {
if (const RecordVal *RV = CurRec->getValue(Name))
if (const RecordVal *RV = CurRec->getValue(Name)) {
if (RV->getType() != getType()) {
throw "type mismatch in nameconcat";
}
return new VarInit(Name, RV->getType());
}
std::string TemplateArgName = CurRec->getName()+":"+Name;
if (CurRec->isTemplateArg(TemplateArgName)) {
const RecordVal *RV = CurRec->getValue(TemplateArgName);
assert(RV && "Template arg doesn't exist??");
if (RV->getType() != getType()) {
throw "type mismatch in nameconcat";
}
return new VarInit(TemplateArgName, RV->getType());
}
}
@ -461,6 +491,11 @@ Init *BinOpInit::Fold(Record *CurRec, MultiClass *CurMultiClass) {
if (CurMultiClass->Rec.isTemplateArg(MCName)) {
const RecordVal *RV = CurMultiClass->Rec.getValue(MCName);
assert(RV && "Template arg doesn't exist??");
if (RV->getType() != getType()) {
throw "type mismatch in nameconcat";
}
return new VarInit(MCName, RV->getType());
}
}
@ -501,7 +536,7 @@ Init *BinOpInit::resolveReferences(Record &R, const RecordVal *RV) {
Init *rhs = RHS->resolveReferences(R, RV);
if (LHS != lhs || RHS != rhs)
return (new BinOpInit(getOpcode(), lhs, rhs))->Fold(&R, 0);
return (new BinOpInit(getOpcode(), lhs, rhs, getType()))->Fold(&R, 0);
return Fold(&R, 0);
}
@ -513,11 +548,40 @@ std::string BinOpInit::getAsString() const {
case SRA: Result = "!sra"; break;
case SRL: Result = "!srl"; break;
case STRCONCAT: Result = "!strconcat"; break;
case NAMECONCAT: Result = "!nameconcat"; break;
case NAMECONCAT:
Result = "!nameconcat<" + getType()->getAsString() + ">"; break;
}
return Result + "(" + LHS->getAsString() + ", " + RHS->getAsString() + ")";
}
Init *BinOpInit::resolveBitReference(Record &R, const RecordVal *IRV,
unsigned Bit) {
Init *Folded = Fold(&R, 0);
if (Folded != this) {
TypedInit *Typed = dynamic_cast<TypedInit *>(Folded);
if (Typed) {
return Typed->resolveBitReference(R, IRV, Bit);
}
}
return 0;
}
Init *BinOpInit::resolveListElementReference(Record &R, const RecordVal *IRV,
unsigned Elt) {
Init *Folded = Fold(&R, 0);
if (Folded != this) {
TypedInit *Typed = dynamic_cast<TypedInit *>(Folded);
if (Typed) {
return Typed->resolveListElementReference(R, IRV, Elt);
}
}
return 0;
}
Init *TypedInit::convertInitializerBitRange(const std::vector<unsigned> &Bits) {
BitsRecTy *T = dynamic_cast<BitsRecTy*>(getType());
if (T == 0) return 0; // Cannot subscript a non-bits variable...

View File

@ -77,7 +77,9 @@ public: // These methods should only be called from subclasses of Init
virtual Init *convertValue( IntInit *II) { return 0; }
virtual Init *convertValue(StringInit *SI) { return 0; }
virtual Init *convertValue( ListInit *LI) { return 0; }
virtual Init *convertValue( BinOpInit *UI) { return 0; }
virtual Init *convertValue( BinOpInit *UI) {
return convertValue((TypedInit*)UI);
}
virtual Init *convertValue( CodeInit *CI) { return 0; }
virtual Init *convertValue(VarBitInit *VB) { return 0; }
virtual Init *convertValue( DefInit *DI) { return 0; }
@ -123,7 +125,7 @@ public:
virtual Init *convertValue(VarBitInit *VB) { return (Init*)VB; }
virtual Init *convertValue( DefInit *DI) { return 0; }
virtual Init *convertValue( DagInit *DI) { return 0; }
virtual Init *convertValue( BinOpInit *UI) { return 0; }
virtual Init *convertValue( BinOpInit *UI) { return RecTy::convertValue(UI);}
virtual Init *convertValue( TypedInit *TI);
virtual Init *convertValue( VarInit *VI) { return RecTy::convertValue(VI);}
virtual Init *convertValue( FieldInit *FI) { return RecTy::convertValue(FI);}
@ -165,7 +167,7 @@ public:
virtual Init *convertValue(VarBitInit *VB) { return 0; }
virtual Init *convertValue( DefInit *DI) { return 0; }
virtual Init *convertValue( DagInit *DI) { return 0; }
virtual Init *convertValue( BinOpInit *UI) { return 0; }
virtual Init *convertValue( BinOpInit *UI) { return RecTy::convertValue(UI);}
virtual Init *convertValue( TypedInit *TI);
virtual Init *convertValue( VarInit *VI) { return RecTy::convertValue(VI);}
virtual Init *convertValue( FieldInit *FI) { return RecTy::convertValue(FI);}
@ -203,7 +205,7 @@ public:
virtual Init *convertValue(VarBitInit *VB) { return 0; }
virtual Init *convertValue( DefInit *DI) { return 0; }
virtual Init *convertValue( DagInit *DI) { return 0; }
virtual Init *convertValue( BinOpInit *UI) { return 0; }
virtual Init *convertValue( BinOpInit *UI) { return RecTy::convertValue(UI);}
virtual Init *convertValue( TypedInit *TI);
virtual Init *convertValue( VarInit *VI) { return RecTy::convertValue(VI);}
virtual Init *convertValue( FieldInit *FI) { return RecTy::convertValue(FI);}
@ -282,7 +284,7 @@ public:
virtual Init *convertValue(VarBitInit *VB) { return 0; }
virtual Init *convertValue( DefInit *DI) { return 0; }
virtual Init *convertValue( DagInit *DI) { return 0; }
virtual Init *convertValue( BinOpInit *UI) { return 0; }
virtual Init *convertValue( BinOpInit *UI) { return RecTy::convertValue(UI);}
virtual Init *convertValue( TypedInit *TI);
virtual Init *convertValue( VarInit *VI) { return RecTy::convertValue(VI);}
virtual Init *convertValue( FieldInit *FI) { return RecTy::convertValue(FI);}
@ -319,7 +321,7 @@ public:
virtual Init *convertValue(VarBitInit *VB) { return 0; }
virtual Init *convertValue( DefInit *DI) { return 0; }
virtual Init *convertValue( DagInit *DI) { return 0; }
virtual Init *convertValue( BinOpInit *UI) { return 0; }
virtual Init *convertValue( BinOpInit *UI) { return RecTy::convertValue(UI);}
virtual Init *convertValue( TypedInit *TI);
virtual Init *convertValue( VarInit *VI) { return RecTy::convertValue(VI);}
virtual Init *convertValue( FieldInit *FI) { return RecTy::convertValue(FI);}
@ -393,7 +395,7 @@ public:
virtual Init *convertValue( ListInit *LI) { return 0; }
virtual Init *convertValue( CodeInit *CI) { return 0; }
virtual Init *convertValue(VarBitInit *VB) { return 0; }
virtual Init *convertValue( BinOpInit *UI) { return 0; }
virtual Init *convertValue( BinOpInit *UI) { return RecTy::convertValue(UI);}
virtual Init *convertValue( DefInit *DI);
virtual Init *convertValue( DagInit *DI) { return 0; }
virtual Init *convertValue( TypedInit *VI);
@ -656,36 +658,6 @@ public:
inline bool empty() const { return Values.empty(); }
};
/// BinOpInit - !op (X, Y) - Combine two inits.
///
class BinOpInit : public Init {
public:
enum BinaryOp { SHL, SRA, SRL, STRCONCAT, CONCAT, NAMECONCAT };
private:
BinaryOp Opc;
Init *LHS, *RHS;
public:
BinOpInit(BinaryOp opc, Init *lhs, Init *rhs) : Opc(opc), LHS(lhs), RHS(rhs) {
}
BinaryOp getOpcode() const { return Opc; }
Init *getLHS() const { return LHS; }
Init *getRHS() const { return RHS; }
// Fold - If possible, fold this to a simpler init. Return this if not
// possible to fold.
Init *Fold(Record *CurRec, MultiClass *CurMultiClass);
virtual Init *convertInitializerTo(RecTy *Ty) {
return Ty->convertValue(this);
}
virtual Init *resolveReferences(Record &R, const RecordVal *RV);
virtual std::string getAsString() const;
};
/// TypedInit - This is the common super-class of types that have a specific,
/// explicit, type.
@ -714,6 +686,43 @@ public:
unsigned Elt) = 0;
};
/// BinOpInit - !op (X, Y) - Combine two inits.
///
class BinOpInit : public TypedInit {
public:
enum BinaryOp { SHL, SRA, SRL, STRCONCAT, CONCAT, NAMECONCAT };
private:
BinaryOp Opc;
Init *LHS, *RHS;
public:
BinOpInit(BinaryOp opc, Init *lhs, Init *rhs, RecTy *Type) :
TypedInit(Type), Opc(opc), LHS(lhs), RHS(rhs) {
}
BinaryOp getOpcode() const { return Opc; }
Init *getLHS() const { return LHS; }
Init *getRHS() const { return RHS; }
// Fold - If possible, fold this to a simpler init. Return this if not
// possible to fold.
Init *Fold(Record *CurRec, MultiClass *CurMultiClass);
virtual Init *convertInitializerTo(RecTy *Ty) {
return Ty->convertValue(this);
}
virtual Init *resolveBitReference(Record &R, const RecordVal *RV,
unsigned Bit);
virtual Init *resolveListElementReference(Record &R, const RecordVal *RV,
unsigned Elt);
virtual Init *resolveReferences(Record &R, const RecordVal *RV);
virtual std::string getAsString() const;
};
/// VarInit - 'Opcode' - Represent a reference to an entire variable object.
///
class VarInit : public TypedInit {

View File

@ -784,6 +784,26 @@ Init *TGParser::ParseSimpleValue(Record *CurRec) {
BinOpInit::BinaryOp Code = BinOpInit::NAMECONCAT;
Lex.Lex(); // eat the operation
if (Lex.getCode() != tgtok::less) {
TokError("expected type name for nameconcat");
return 0;
}
Lex.Lex(); // eat the <
RecTy *Type = ParseType();
if (Type == 0) {
TokError("expected type name for nameconcat");
return 0;
}
if (Lex.getCode() != tgtok::greater) {
TokError("expected type name for nameconcat");
return 0;
}
Lex.Lex(); // eat the >
if (Lex.getCode() != tgtok::l_paren) {
TokError("expected '(' after binary operator");
return 0;
@ -807,7 +827,7 @@ Init *TGParser::ParseSimpleValue(Record *CurRec) {
return 0;
}
Lex.Lex(); // eat the ')'
Operator = (new BinOpInit(Code, LHS, RHS))->Fold(CurRec, CurMultiClass);
Operator = (new BinOpInit(Code, LHS, RHS, Type))->Fold(CurRec, CurMultiClass);
}
// If the operator name is present, parse it.
@ -842,16 +862,59 @@ Init *TGParser::ParseSimpleValue(Record *CurRec) {
case tgtok::XStrConcat:
case tgtok::XNameConcat: { // Value ::= !binop '(' Value ',' Value ')'
BinOpInit::BinaryOp Code;
RecTy *Type = 0;
switch (Lex.getCode()) {
default: assert(0 && "Unhandled code!");
case tgtok::XConcat: Code = BinOpInit::CONCAT; break;
case tgtok::XSRA: Code = BinOpInit::SRA; break;
case tgtok::XSRL: Code = BinOpInit::SRL; break;
case tgtok::XSHL: Code = BinOpInit::SHL; break;
case tgtok::XStrConcat: Code = BinOpInit::STRCONCAT; break;
case tgtok::XNameConcat: Code = BinOpInit::NAMECONCAT; break;
case tgtok::XConcat:
Lex.Lex(); // eat the operation
Code = BinOpInit::CONCAT;
Type = new DagRecTy();
break;
case tgtok::XSRA:
Lex.Lex(); // eat the operation
Code = BinOpInit::SRA;
Type = new IntRecTy();
break;
case tgtok::XSRL:
Lex.Lex(); // eat the operation
Code = BinOpInit::SRL;
Type = new IntRecTy();
break;
case tgtok::XSHL:
Lex.Lex(); // eat the operation
Code = BinOpInit::SHL;
Type = new IntRecTy();
break;
case tgtok::XStrConcat:
Lex.Lex(); // eat the operation
Code = BinOpInit::STRCONCAT;
Type = new StringRecTy();
break;
case tgtok::XNameConcat:
Lex.Lex(); // eat the operation
Code = BinOpInit::NAMECONCAT;
if (Lex.getCode() != tgtok::less) {
TokError("expected type name for nameconcat");
return 0;
}
Lex.Lex(); // eat the <
Type = ParseType();
if (Type == 0) {
TokError("expected type name for nameconcat");
return 0;
}
if (Lex.getCode() != tgtok::greater) {
TokError("expected type name for nameconcat");
return 0;
}
Lex.Lex(); // eat the >
break;
}
Lex.Lex(); // eat the operation
if (Lex.getCode() != tgtok::l_paren) {
TokError("expected '(' after binary operator");
return 0;
@ -875,7 +938,7 @@ Init *TGParser::ParseSimpleValue(Record *CurRec) {
return 0;
}
Lex.Lex(); // eat the ')'
return (new BinOpInit(Code, LHS, RHS))->Fold(CurRec, CurMultiClass);
return (new BinOpInit(Code, LHS, RHS, Type))->Fold(CurRec, CurMultiClass);
}
}