mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-26 12:50:30 +00:00
Implement a !foreach operator analogous to GNU make's $(foreach).
Use it on dags and lists like this: class decls { string name; } def Decls : decls; class B<list<string> names> : A<!foreach(Decls.name, names, !strconcat(Decls.name, ", Sr."))>; llvm-svn: 71803
This commit is contained in:
parent
26054a566e
commit
fab0ee79db
@ -407,6 +407,10 @@ aborts with an error. </dd>
|
||||
<dt><tt>!subst(a, b, c)</tt></dt>
|
||||
<dd>If 'a' and 'b' are of string type or are symbol references, substitute
|
||||
'b' for 'a' in 'c.' This operation is analogous to $(subst) in GNU make.</dd>
|
||||
<dt><tt>!foreach(a, b, c)</tt></dt>
|
||||
<dd>For each member 'b' of dag or list 'a' apply operator 'c.' 'b' is a
|
||||
dummy variable that should be declared as a member variable of an instantiated
|
||||
class. This operation is analogous to $(foreach) in GNU make.</dd>
|
||||
</dl>
|
||||
|
||||
<p>Note that all of the values have rules specifying how they convert to values
|
||||
|
97
test/TableGen/TargetInstrSpec.td
Normal file
97
test/TableGen/TargetInstrSpec.td
Normal file
@ -0,0 +1,97 @@
|
||||
// RUN: tblgen %s | grep {[(set VR128:$dst, (int_x86_sse2_add_pd VR128:$src1, VR128:$src2))]} | count 1
|
||||
// RUN: tblgen %s | grep {[(set VR128:$dst, (int_x86_sse2_add_ps VR128:$src1, VR128:$src2))]} | count 2
|
||||
|
||||
class ValueType<int size, int value> {
|
||||
int Size = size;
|
||||
int Value = value;
|
||||
}
|
||||
|
||||
def v2i64 : ValueType<128, 22>; // 2 x i64 vector value
|
||||
def v2f64 : ValueType<128, 28>; // 2 x f64 vector value
|
||||
|
||||
class Intrinsic<string name> {
|
||||
string Name = name;
|
||||
}
|
||||
|
||||
class Inst<bits<8> opcode, dag oopnds, dag iopnds, string asmstr,
|
||||
list<dag> pattern> {
|
||||
bits<8> Opcode = opcode;
|
||||
dag OutOperands = oopnds;
|
||||
dag InOperands = iopnds;
|
||||
string AssemblyString = asmstr;
|
||||
list<dag> Pattern = pattern;
|
||||
}
|
||||
|
||||
def ops;
|
||||
def outs;
|
||||
def ins;
|
||||
|
||||
def set;
|
||||
|
||||
// Define registers
|
||||
class Register<string n> {
|
||||
string Name = n;
|
||||
}
|
||||
|
||||
class RegisterClass<list<ValueType> regTypes, list<Register> regList> {
|
||||
list<ValueType> RegTypes = regTypes;
|
||||
list<Register> 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 VR128 : RegisterClass<[v2i64, v2f64],
|
||||
[XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7,
|
||||
XMM8, XMM9, XMM10, XMM11,
|
||||
XMM12, XMM13, XMM14, XMM15]>;
|
||||
|
||||
// Dummy for subst
|
||||
def REGCLASS : RegisterClass<[], []>;
|
||||
|
||||
class decls {
|
||||
// Dummy for foreach
|
||||
dag pattern;
|
||||
int operand;
|
||||
}
|
||||
|
||||
def Decls : decls;
|
||||
|
||||
// Define intrinsics
|
||||
def int_x86_sse2_add_ps : Intrinsic<"addps">;
|
||||
def int_x86_sse2_add_pd : Intrinsic<"addpd">;
|
||||
def INTRINSIC : Intrinsic<"Dummy">;
|
||||
|
||||
multiclass arith<bits<8> opcode, string asmstr, string intr, list<dag> patterns> {
|
||||
def PS : Inst<opcode, (outs VR128:$dst), (ins VR128:$src1, VR128:$src2),
|
||||
!strconcat(asmstr, "\t$dst, $src1, $src2"),
|
||||
!foreach(Decls.pattern, patterns,
|
||||
!foreach(Decls.operand, Decls.pattern,
|
||||
!subst(INTRINSIC, !cast<Intrinsic>(!subst("SUFFIX", "_ps", intr)),
|
||||
!subst(REGCLASS, VR128, Decls.operand))))>;
|
||||
|
||||
def PD : Inst<opcode, (outs VR128:$dst), (ins VR128:$src1, VR128:$src2),
|
||||
!strconcat(asmstr, "\t$dst, $src1, $src2"),
|
||||
!foreach(Decls.pattern, patterns,
|
||||
!foreach(Decls.operand, Decls.pattern,
|
||||
!subst(INTRINSIC, !cast<Intrinsic>(!subst("SUFFIX", "_pd", intr)),
|
||||
!subst(REGCLASS, VR128, Decls.operand))))>;
|
||||
}
|
||||
|
||||
defm ADD : arith<0x58, "add", "int_x86_sse2_addSUFFIX",
|
||||
[(set REGCLASS:$dst, (INTRINSIC REGCLASS:$src1, REGCLASS:$src2))]>;
|
||||
|
31
test/TableGen/foreach.td
Normal file
31
test/TableGen/foreach.td
Normal file
@ -0,0 +1,31 @@
|
||||
// RUN: tblgen %s | grep {Jr} | count 2
|
||||
// RUN: tblgen %s | grep {Sr} | count 2
|
||||
// RUN: tblgen %s | not grep {NAME}
|
||||
|
||||
// Variables for foreach
|
||||
class decls {
|
||||
string name;
|
||||
}
|
||||
|
||||
def Decls : decls;
|
||||
|
||||
class A<list<string> names> {
|
||||
list<string> Names = names;
|
||||
}
|
||||
|
||||
class B<list<string> names> : A<!foreach(Decls.name, names, !strconcat(Decls.name, ", Sr."))>;
|
||||
|
||||
class C<list<string> names> : A<!foreach(Decls.name, names, !strconcat(Decls.name, ", Jr."))>;
|
||||
|
||||
class D<list<string> names> : A<!foreach(Decls.name, names, !subst("NAME", "John Smith", Decls.name))>;
|
||||
|
||||
class Names {
|
||||
list<string> values = ["Ken Griffey", "Seymour Cray"];
|
||||
}
|
||||
|
||||
def People : Names;
|
||||
|
||||
def Seniors : B<People.values>;
|
||||
def Juniors : C<People.values>;
|
||||
def Smiths : D<["NAME", "Jane Smith"]>;
|
||||
def Unprocessed : D<People.values>;
|
@ -678,6 +678,144 @@ std::string BinOpInit::getAsString() const {
|
||||
return Result + "(" + LHS->getAsString() + ", " + RHS->getAsString() + ")";
|
||||
}
|
||||
|
||||
static Init *ForeachHelper(Init *LHS, Init *MHS, Init *RHS, RecTy *Type,
|
||||
Record *CurRec, MultiClass *CurMultiClass);
|
||||
|
||||
static Init *EvaluateOperation(OpInit *RHSo, Init *LHS, Init *Arg,
|
||||
RecTy *Type, Record *CurRec,
|
||||
MultiClass *CurMultiClass) {
|
||||
std::vector<Init *> NewOperands;
|
||||
|
||||
TypedInit *TArg = dynamic_cast<TypedInit*>(Arg);
|
||||
|
||||
// If this is a dag, recurse
|
||||
if (TArg && TArg->getType()->getAsString() == "dag") {
|
||||
Init *Result = ForeachHelper(LHS, Arg, RHSo, Type,
|
||||
CurRec, CurMultiClass);
|
||||
if (Result != 0) {
|
||||
return Result;
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < RHSo->getNumOperands(); ++i) {
|
||||
OpInit *RHSoo = dynamic_cast<OpInit*>(RHSo->getOperand(i));
|
||||
|
||||
if (RHSoo) {
|
||||
Init *Result = EvaluateOperation(RHSoo, LHS, Arg,
|
||||
Type, CurRec, CurMultiClass);
|
||||
if (Result != 0) {
|
||||
NewOperands.push_back(Result);
|
||||
}
|
||||
else {
|
||||
NewOperands.push_back(Arg);
|
||||
}
|
||||
}
|
||||
else if (LHS->getAsString() == RHSo->getOperand(i)->getAsString()) {
|
||||
NewOperands.push_back(Arg);
|
||||
}
|
||||
else {
|
||||
NewOperands.push_back(RHSo->getOperand(i));
|
||||
}
|
||||
}
|
||||
|
||||
// Now run the operator and use its result as the new leaf
|
||||
OpInit *NewOp = RHSo->clone(NewOperands);
|
||||
Init *NewVal = NewOp->Fold(CurRec, CurMultiClass);
|
||||
if (NewVal != NewOp) {
|
||||
delete NewOp;
|
||||
return NewVal;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static Init *ForeachHelper(Init *LHS, Init *MHS, Init *RHS, RecTy *Type,
|
||||
Record *CurRec, MultiClass *CurMultiClass) {
|
||||
DagInit *MHSd = dynamic_cast<DagInit*>(MHS);
|
||||
ListInit *MHSl = dynamic_cast<ListInit*>(MHS);
|
||||
|
||||
DagRecTy *DagType = dynamic_cast<DagRecTy*>(Type);
|
||||
ListRecTy *ListType = dynamic_cast<ListRecTy*>(Type);
|
||||
|
||||
OpInit *RHSo = dynamic_cast<OpInit*>(RHS);
|
||||
|
||||
if (!RHSo) {
|
||||
cerr << "!foreach requires an operator\n";
|
||||
assert(0 && "No operator for !foreach");
|
||||
}
|
||||
|
||||
TypedInit *LHSt = dynamic_cast<TypedInit*>(LHS);
|
||||
|
||||
if (!LHSt) {
|
||||
cerr << "!foreach requires typed variable\n";
|
||||
assert(0 && "No typed variable for !foreach");
|
||||
}
|
||||
|
||||
if (MHSd && DagType || MHSl && ListType) {
|
||||
if (MHSd) {
|
||||
Init *Val = MHSd->getOperator();
|
||||
Init *Result = EvaluateOperation(RHSo, LHS, Val,
|
||||
Type, CurRec, CurMultiClass);
|
||||
if (Result != 0) {
|
||||
Val = Result;
|
||||
}
|
||||
|
||||
std::vector<std::pair<Init *, std::string> > args;
|
||||
for (unsigned int i = 0; i < MHSd->getNumArgs(); ++i) {
|
||||
Init *Arg;
|
||||
std::string ArgName;
|
||||
Arg = MHSd->getArg(i);
|
||||
ArgName = MHSd->getArgName(i);
|
||||
|
||||
// Process args
|
||||
Init *Result = EvaluateOperation(RHSo, LHS, Arg, Type,
|
||||
CurRec, CurMultiClass);
|
||||
if (Result != 0) {
|
||||
Arg = Result;
|
||||
}
|
||||
|
||||
// TODO: Process arg names
|
||||
args.push_back(std::make_pair(Arg, ArgName));
|
||||
}
|
||||
|
||||
return new DagInit(Val, "", args);
|
||||
}
|
||||
if (MHSl) {
|
||||
std::vector<Init *> NewOperands;
|
||||
std::vector<Init *> NewList(MHSl->begin(), MHSl->end());
|
||||
|
||||
for (ListInit::iterator li = NewList.begin(),
|
||||
liend = NewList.end();
|
||||
li != liend;
|
||||
++li) {
|
||||
Init *Item = *li;
|
||||
NewOperands.clear();
|
||||
for(int i = 0; i < RHSo->getNumOperands(); ++i) {
|
||||
// First, replace the foreach variable with the list item
|
||||
if (LHS->getAsString() == RHSo->getOperand(i)->getAsString()) {
|
||||
NewOperands.push_back(Item);
|
||||
}
|
||||
else {
|
||||
NewOperands.push_back(RHSo->getOperand(i));
|
||||
}
|
||||
}
|
||||
|
||||
// Now run the operator and use its result as the new list item
|
||||
OpInit *NewOp = RHSo->clone(NewOperands);
|
||||
Init *NewItem = NewOp->Fold(CurRec, CurMultiClass);
|
||||
if (NewItem != NewOp) {
|
||||
*li = NewItem;
|
||||
delete NewOp;
|
||||
}
|
||||
}
|
||||
return new ListInit(NewList);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
Init *TernOpInit::Fold(Record *CurRec, MultiClass *CurMultiClass) {
|
||||
switch (getOpcode()) {
|
||||
default: assert(0 && "Unknown binop");
|
||||
@ -729,144 +867,10 @@ Init *TernOpInit::Fold(Record *CurRec, MultiClass *CurMultiClass) {
|
||||
}
|
||||
|
||||
case FOREACH: {
|
||||
DagInit *MHSd = dynamic_cast<DagInit*>(MHS);
|
||||
ListInit *MHSl = dynamic_cast<ListInit*>(MHS);
|
||||
|
||||
DagRecTy *DagType = dynamic_cast<DagRecTy*>(getType());
|
||||
ListRecTy *ListType = dynamic_cast<ListRecTy*>(getType());
|
||||
|
||||
OpInit *RHSo = dynamic_cast<OpInit*>(RHS);
|
||||
|
||||
if (!RHSo) {
|
||||
cerr << "!foreach requires an operator\n";
|
||||
assert(0 && "No operator for !foreach");
|
||||
}
|
||||
|
||||
TypedInit *LHSt = dynamic_cast<TypedInit*>(LHS);
|
||||
|
||||
if (!LHSt) {
|
||||
cerr << "!foreach requires typed variable\n";
|
||||
assert(0 && "No typed variable for !foreach");
|
||||
}
|
||||
|
||||
if (MHSd && DagType || MHSl && ListType) {
|
||||
std::vector<Init *> NewOperands;
|
||||
if (MHSd) {
|
||||
Init *Val = MHSd->getOperator();
|
||||
TypedInit *TVal = dynamic_cast<TypedInit*>(Val);
|
||||
|
||||
if (TVal && TVal->getType()->typeIsConvertibleTo(LHSt->getType())) {
|
||||
|
||||
// First, replace the foreach variable with the DAG leaf
|
||||
for (int i = 0; i < RHSo->getNumOperands(); ++i) {
|
||||
if (LHS->getAsString() == RHSo->getOperand(i)->getAsString()) {
|
||||
NewOperands.push_back(Val);
|
||||
}
|
||||
else {
|
||||
NewOperands.push_back(RHSo->getOperand(i));
|
||||
}
|
||||
}
|
||||
|
||||
// Now run the operator and use its result as the new leaf
|
||||
OpInit *NewOp = RHSo->clone(NewOperands);
|
||||
Val = NewOp->Fold(CurRec, CurMultiClass);
|
||||
if (Val != NewOp) {
|
||||
delete NewOp;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::pair<Init *, std::string> > args;
|
||||
for (unsigned int i = 0; i < MHSd->getNumArgs(); ++i) {
|
||||
Init *Arg;
|
||||
std::string ArgName;
|
||||
Arg = MHSd->getArg(i);
|
||||
ArgName = MHSd->getArgName(i);
|
||||
|
||||
TypedInit *TArg = dynamic_cast<TypedInit*>(Arg);
|
||||
|
||||
if (TArg && TArg->getType()->typeIsConvertibleTo(LHSt->getType())) {
|
||||
NewOperands.clear();
|
||||
|
||||
// First, replace the foreach variable with the DAG leaf
|
||||
for (int i = 0; i < RHSo->getNumOperands(); ++i) {
|
||||
if (LHS->getAsString() == RHSo->getOperand(i)->getAsString()) {
|
||||
NewOperands.push_back(Arg);
|
||||
}
|
||||
else {
|
||||
NewOperands.push_back(RHSo->getOperand(i));
|
||||
}
|
||||
}
|
||||
|
||||
// Now run the operator and use its result as the new leaf
|
||||
OpInit *NewOp = RHSo->clone(NewOperands);
|
||||
Arg = NewOp->Fold(CurRec, CurMultiClass);
|
||||
if (Arg != NewOp) {
|
||||
delete NewOp;
|
||||
}
|
||||
}
|
||||
|
||||
if (LHSt->getType()->getAsString() == "string") {
|
||||
NewOperands.clear();
|
||||
|
||||
// First, replace the foreach variable with the DAG leaf
|
||||
for (int i = 0; i < RHSo->getNumOperands(); ++i) {
|
||||
if (LHS->getAsString() == RHSo->getOperand(i)->getAsString()) {
|
||||
NewOperands.push_back(new StringInit(ArgName));
|
||||
}
|
||||
else {
|
||||
NewOperands.push_back(RHSo->getOperand(i));
|
||||
}
|
||||
}
|
||||
|
||||
// Now run the operator and use its result as the new leaf
|
||||
OpInit *NewOp = RHSo->clone(NewOperands);
|
||||
Init *ArgNameInit = NewOp->Fold(CurRec, CurMultiClass);
|
||||
StringInit *SArgNameInit = dynamic_cast<StringInit*>(ArgNameInit);
|
||||
if (SArgNameInit) {
|
||||
ArgName = SArgNameInit->getValue();
|
||||
}
|
||||
if (ArgNameInit != NewOp) {
|
||||
delete NewOp;
|
||||
}
|
||||
delete ArgNameInit;
|
||||
}
|
||||
|
||||
args.push_back(std::make_pair(Arg, ArgName));
|
||||
}
|
||||
|
||||
return new DagInit(Val, "", args);
|
||||
}
|
||||
if (MHSl) {
|
||||
std::vector<Init *> NewList(MHSl->begin(), MHSl->end());
|
||||
|
||||
for (ListInit::iterator li = NewList.begin(),
|
||||
liend = NewList.end();
|
||||
li != liend;
|
||||
++li) {
|
||||
Init *Item = *li;
|
||||
TypedInit *TItem = dynamic_cast<TypedInit*>(Item);
|
||||
if (TItem && TItem->getType()->typeIsConvertibleTo(LHSt->getType())) {
|
||||
// First, replace the foreach variable with the list item
|
||||
for (int i = 0; i < RHSo->getNumOperands(); ++i) {
|
||||
if (LHS->getAsString() == RHSo->getOperand(i)->getAsString()) {
|
||||
NewOperands.push_back(Item);
|
||||
}
|
||||
else {
|
||||
NewOperands.push_back(RHSo->getOperand(i));
|
||||
}
|
||||
}
|
||||
|
||||
// Now run the operator and use its result as the new list item
|
||||
OpInit *NewOp = RHSo->clone(NewOperands);
|
||||
*li = NewOp->Fold(CurRec, CurMultiClass);
|
||||
if (*li != NewOp) {
|
||||
delete NewOp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new ListInit(NewList);
|
||||
}
|
||||
Init *Result = ForeachHelper(LHS, MHS, RHS, getType(),
|
||||
CurRec, CurMultiClass);
|
||||
if (Result != 0) {
|
||||
return Result;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -517,6 +517,33 @@ inline std::ostream &operator<<(std::ostream &OS, const Init &I) {
|
||||
I.print(OS); return OS;
|
||||
}
|
||||
|
||||
/// TypedInit - This is the common super-class of types that have a specific,
|
||||
/// explicit, type.
|
||||
///
|
||||
class TypedInit : public Init {
|
||||
RecTy *Ty;
|
||||
public:
|
||||
explicit TypedInit(RecTy *T) : Ty(T) {}
|
||||
|
||||
RecTy *getType() const { return Ty; }
|
||||
|
||||
virtual Init *convertInitializerBitRange(const std::vector<unsigned> &Bits);
|
||||
virtual Init *convertInitListSlice(const std::vector<unsigned> &Elements);
|
||||
|
||||
/// 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) = 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) = 0;
|
||||
};
|
||||
|
||||
|
||||
/// UnsetInit - ? - Represents an uninitialized value
|
||||
///
|
||||
@ -609,10 +636,10 @@ public:
|
||||
|
||||
/// StringInit - "foo" - Represent an initialization by a string value.
|
||||
///
|
||||
class StringInit : public Init {
|
||||
class StringInit : public TypedInit {
|
||||
std::string Value;
|
||||
public:
|
||||
explicit StringInit(const std::string &V) : Value(V) {}
|
||||
explicit StringInit(const std::string &V) : TypedInit(new StringRecTy), Value(V) {}
|
||||
|
||||
const std::string &getValue() const { return Value; }
|
||||
|
||||
@ -621,6 +648,25 @@ public:
|
||||
}
|
||||
|
||||
virtual std::string getAsString() const { return "\"" + Value + "\""; }
|
||||
|
||||
/// 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 string");
|
||||
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 string");
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
/// CodeInit - "[{...}]" - Represent a code fragment.
|
||||
@ -684,33 +730,6 @@ public:
|
||||
};
|
||||
|
||||
|
||||
/// TypedInit - This is the common super-class of types that have a specific,
|
||||
/// explicit, type.
|
||||
///
|
||||
class TypedInit : public Init {
|
||||
RecTy *Ty;
|
||||
public:
|
||||
explicit TypedInit(RecTy *T) : Ty(T) {}
|
||||
|
||||
RecTy *getType() const { return Ty; }
|
||||
|
||||
virtual Init *convertInitializerBitRange(const std::vector<unsigned> &Bits);
|
||||
virtual Init *convertInitListSlice(const std::vector<unsigned> &Elements);
|
||||
|
||||
/// 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) = 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) = 0;
|
||||
};
|
||||
|
||||
/// OpInit - Base class for operators
|
||||
///
|
||||
class OpInit : public TypedInit {
|
||||
@ -957,10 +976,10 @@ public:
|
||||
|
||||
/// DefInit - AL - Represent a reference to a 'def' in the description
|
||||
///
|
||||
class DefInit : public Init {
|
||||
class DefInit : public TypedInit {
|
||||
Record *Def;
|
||||
public:
|
||||
explicit DefInit(Record *D) : Def(D) {}
|
||||
explicit DefInit(Record *D) : TypedInit(new RecordRecTy(D)), Def(D) {}
|
||||
|
||||
virtual Init *convertInitializerTo(RecTy *Ty) {
|
||||
return Ty->convertValue(this);
|
||||
@ -974,6 +993,25 @@ public:
|
||||
virtual Init *getFieldInit(Record &R, const std::string &FieldName) const;
|
||||
|
||||
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 def");
|
||||
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 def");
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -1008,7 +1046,7 @@ public:
|
||||
/// to have at least one value then a (possibly empty) list of arguments. Each
|
||||
/// argument can have a name associated with it.
|
||||
///
|
||||
class DagInit : public Init {
|
||||
class DagInit : public TypedInit {
|
||||
Init *Val;
|
||||
std::string ValName;
|
||||
std::vector<Init*> Args;
|
||||
@ -1016,7 +1054,7 @@ class DagInit : public Init {
|
||||
public:
|
||||
DagInit(Init *V, std::string VN,
|
||||
const std::vector<std::pair<Init*, std::string> > &args)
|
||||
: Val(V), ValName(VN) {
|
||||
: TypedInit(new DagRecTy), Val(V), ValName(VN) {
|
||||
Args.reserve(args.size());
|
||||
ArgNames.reserve(args.size());
|
||||
for (unsigned i = 0, e = args.size(); i != e; ++i) {
|
||||
@ -1026,7 +1064,7 @@ public:
|
||||
}
|
||||
DagInit(Init *V, std::string VN, const std::vector<Init*> &args,
|
||||
const std::vector<std::string> &argNames)
|
||||
: Val(V), ValName(VN), Args(args), ArgNames(argNames) {
|
||||
: TypedInit(new DagRecTy), Val(V), ValName(VN), Args(args), ArgNames(argNames) {
|
||||
}
|
||||
|
||||
virtual Init *convertInitializerTo(RecTy *Ty) {
|
||||
@ -1077,6 +1115,18 @@ public:
|
||||
inline size_t name_size () const { return ArgNames.size(); }
|
||||
inline bool name_empty() const { return ArgNames.empty(); }
|
||||
|
||||
virtual Init *resolveBitReference(Record &R, const RecordVal *RV,
|
||||
unsigned Bit) {
|
||||
assert(0 && "Illegal bit reference off dag");
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual Init *resolveListElementReference(Record &R, const RecordVal *RV,
|
||||
unsigned Elt) {
|
||||
assert(0 && "Illegal element reference off dag");
|
||||
return 0;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -448,7 +448,7 @@ tgtok::TokKind TGLexer::LexExclaim() {
|
||||
if (Len == 9 && !memcmp(Start, "strconcat", 9)) return tgtok::XStrConcat;
|
||||
if (Len == 10 && !memcmp(Start, "nameconcat", 10)) return tgtok::XNameConcat;
|
||||
if (Len == 5 && !memcmp(Start, "subst", 5)) return tgtok::XSubst;
|
||||
// if (Len == 7 && !memcmp(Start, "foreach", 7)) return tgtok::XForEach;
|
||||
if (Len == 7 && !memcmp(Start, "foreach", 7)) return tgtok::XForEach;
|
||||
if (Len == 4 && !memcmp(Start, "cast", 4)) return tgtok::XCast;
|
||||
|
||||
return ReturnError(Start-1, "Unknown operator");
|
||||
|
@ -46,7 +46,7 @@ namespace tgtok {
|
||||
|
||||
// !keywords.
|
||||
XConcat, XSRA, XSRL, XSHL, XStrConcat, XNameConcat, XCast, XSubst,
|
||||
//XForEach,
|
||||
XForEach,
|
||||
|
||||
// Integer value.
|
||||
IntVal,
|
||||
|
@ -792,7 +792,7 @@ Init *TGParser::ParseOperation(Record *CurRec) {
|
||||
return (new BinOpInit(Code, LHS, RHS, Type))->Fold(CurRec, CurMultiClass);
|
||||
}
|
||||
|
||||
// case tgtok::XForEach:
|
||||
case tgtok::XForEach:
|
||||
case tgtok::XSubst: { // Value ::= !ternop '(' Value ',' Value ',' Value ')'
|
||||
TernOpInit::TernaryOp Code;
|
||||
RecTy *Type = 0;
|
||||
@ -802,9 +802,9 @@ Init *TGParser::ParseOperation(Record *CurRec) {
|
||||
Lex.Lex(); // eat the operation
|
||||
switch (LexCode) {
|
||||
default: assert(0 && "Unhandled code!");
|
||||
//case tgtok::XForEach:
|
||||
//Code = TernOpInit::FOREACH;
|
||||
//break;
|
||||
case tgtok::XForEach:
|
||||
Code = TernOpInit::FOREACH;
|
||||
break;
|
||||
case tgtok::XSubst:
|
||||
Code = TernOpInit::SUBST;
|
||||
break;
|
||||
@ -844,15 +844,15 @@ Init *TGParser::ParseOperation(Record *CurRec) {
|
||||
|
||||
switch (LexCode) {
|
||||
default: assert(0 && "Unhandled code!");
|
||||
//case tgtok::XForEach: {
|
||||
//TypedInit *MHSt = dynamic_cast<TypedInit *>(MHS);
|
||||
//if (MHSt == 0) {
|
||||
// TokError("could not get type for !foreach");
|
||||
// return 0;
|
||||
//}
|
||||
//Type = MHSt->getType();
|
||||
//break;
|
||||
//}
|
||||
case tgtok::XForEach: {
|
||||
TypedInit *MHSt = dynamic_cast<TypedInit *>(MHS);
|
||||
if (MHSt == 0) {
|
||||
TokError("could not get type for !foreach");
|
||||
return 0;
|
||||
}
|
||||
Type = MHSt->getType();
|
||||
break;
|
||||
}
|
||||
case tgtok::XSubst: {
|
||||
TypedInit *RHSt = dynamic_cast<TypedInit *>(RHS);
|
||||
if (RHSt == 0) {
|
||||
@ -1079,7 +1079,7 @@ Init *TGParser::ParseSimpleValue(Record *CurRec) {
|
||||
case tgtok::XSHL:
|
||||
case tgtok::XStrConcat:
|
||||
case tgtok::XNameConcat: // Value ::= !binop '(' Value ',' Value ')'
|
||||
// case tgtok::XForEach:
|
||||
case tgtok::XForEach:
|
||||
case tgtok::XSubst: { // Value ::= !ternop '(' Value ',' Value ',' Value ')'
|
||||
return ParseOperation(CurRec);
|
||||
break;
|
||||
|
Loading…
Reference in New Issue
Block a user