+ if (i) Result += ", ";
+ Result += Values[i]->getAsString();
+ }
+ return Result + "]";
+}
+
+Init *OpInit::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 *OpInit::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 *UnOpInit::Fold(Record *CurRec, MultiClass *CurMultiClass) {
+ switch (getOpcode()) {
+ default: assert(0 && "Unknown unop");
+ case CAST: {
+ if (getType()->getAsString() == "string") {
+ StringInit *LHSs = dynamic_cast<StringInit*>(LHS);
+ if (LHSs) {
+ return LHSs;
+ }
+
+ DefInit *LHSd = dynamic_cast<DefInit*>(LHS);
+ if (LHSd) {
+ return new StringInit(LHSd->getDef()->getName());
+ }
+ } else {
+ StringInit *LHSs = dynamic_cast<StringInit*>(LHS);
+ if (LHSs) {
+ std::string Name = LHSs->getValue();
+
+ // From TGParser::ParseIDValue
+ if (CurRec) {
+ if (const RecordVal *RV = CurRec->getValue(Name)) {
+ if (RV->getType() != getType())
+ throw "type mismatch in cast";
+ 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 cast";
+
+ return new VarInit(TemplateArgName, RV->getType());
+ }
+ }
+
+ if (CurMultiClass) {
+ std::string MCName = CurMultiClass->Rec.getName()+"::"+Name;
+ 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 cast";
+
+ return new VarInit(MCName, RV->getType());
+ }
+ }
+
+ if (Record *D = (CurRec->getRecords()).getDef(Name))
+ return new DefInit(D);
+
+ errs() << "Variable not defined: '" + Name + "'\n";
+ assert(0 && "Variable not found");
+ return 0;
+ }
+ }
+ break;
+ }
+ case HEAD: {
+ ListInit *LHSl = dynamic_cast<ListInit*>(LHS);
+ if (LHSl) {
+ if (LHSl->getSize() == 0) {
+ assert(0 && "Empty list in car");
+ return 0;
+ }
+ return LHSl->getElement(0);
+ }
+ break;
+ }
+ case TAIL: {
+ ListInit *LHSl = dynamic_cast<ListInit*>(LHS);
+ if (LHSl) {
+ if (LHSl->getSize() == 0) {
+ assert(0 && "Empty list in cdr");
+ return 0;
+ }
+ ListInit *Result = new ListInit(LHSl->begin()+1, LHSl->end(),
+ LHSl->getType());
+ return Result;
+ }
+ break;
+ }
+ case EMPTY: {
+ ListInit *LHSl = dynamic_cast<ListInit*>(LHS);
+ if (LHSl) {
+ if (LHSl->getSize() == 0) {
+ return new IntInit(1);
+ } else {
+ 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;
+ }
+ }
+ return this;
+}
+
+Init *UnOpInit::resolveReferences(Record &R, const RecordVal *RV) {
+ Init *lhs = LHS->resolveReferences(R, RV);
+
+ if (LHS != lhs)
+ return (new UnOpInit(getOpcode(), lhs, getType()))->Fold(&R, 0);
+ return Fold(&R, 0);
+}
+
+std::string UnOpInit::getAsString() const {
+ std::string Result;
+ switch (Opc) {
+ case CAST: Result = "!cast<" + getType()->getAsString() + ">"; break;
+ case HEAD: Result = "!head"; break;
+ case TAIL: Result = "!tail"; break;
+ case EMPTY: Result = "!empty"; break;
+ }
+ return Result + "(" + LHS->getAsString() + ")";
+}
+
+Init *BinOpInit::Fold(Record *CurRec, MultiClass *CurMultiClass) {
+ switch (getOpcode()) {
+ default: assert(0 && "Unknown binop");
+ case CONCAT: {
+ DagInit *LHSs = dynamic_cast<DagInit*>(LHS);
+ DagInit *RHSs = dynamic_cast<DagInit*>(RHS);
+ if (LHSs && RHSs) {
+ DefInit *LOp = dynamic_cast<DefInit*>(LHSs->getOperator());
+ DefInit *ROp = dynamic_cast<DefInit*>(RHSs->getOperator());
+ if (LOp == 0 || ROp == 0 || LOp->getDef() != ROp->getDef())
+ throw "Concated Dag operators do not match!";
+ std::vector<Init*> Args;
+ std::vector<std::string> ArgNames;
+ for (unsigned i = 0, e = LHSs->getNumArgs(); i != e; ++i) {
+ Args.push_back(LHSs->getArg(i));
+ ArgNames.push_back(LHSs->getArgName(i));
+ }
+ for (unsigned i = 0, e = RHSs->getNumArgs(); i != e; ++i) {
+ Args.push_back(RHSs->getArg(i));
+ ArgNames.push_back(RHSs->getArgName(i));
+ }
+ return new DagInit(LHSs->getOperator(), "", Args, ArgNames);
+ }
+ break;
+ }
+ case STRCONCAT: {
+ StringInit *LHSs = dynamic_cast<StringInit*>(LHS);
+ StringInit *RHSs = dynamic_cast<StringInit*>(RHS);
+ if (LHSs && RHSs)
+ return new StringInit(LHSs->getValue() + RHSs->getValue());
+ break;
+ }
+ case EQ: {
+ // try to fold eq comparison for 'bit' and 'int', otherwise fallback
+ // to string objects.
+ IntInit* L =
+ dynamic_cast<IntInit*>(LHS->convertInitializerTo(new IntRecTy()));
+ IntInit* R =
+ dynamic_cast<IntInit*>(RHS->convertInitializerTo(new IntRecTy()));
+
+ if (L && R)
+ return new IntInit(L->getValue() == R->getValue());
+
+ StringInit *LHSs = dynamic_cast<StringInit*>(LHS);
+ StringInit *RHSs = dynamic_cast<StringInit*>(RHS);
+
+ // Make sure we've resolved
+ if (LHSs && RHSs)
+ return new IntInit(LHSs->getValue() == RHSs->getValue());
+
+ break;
+ }
+ case SHL:
+ case SRA:
+ case SRL: {
+ IntInit *LHSi = dynamic_cast<IntInit*>(LHS);
+ IntInit *RHSi = dynamic_cast<IntInit*>(RHS);
+ if (LHSi && RHSi) {
+ int64_t LHSv = LHSi->getValue(), RHSv = RHSi->getValue();
+ int64_t Result;
+ switch (getOpcode()) {
+ default: assert(0 && "Bad opcode!");
+ case SHL: Result = LHSv << RHSv; break;
+ case SRA: Result = LHSv >> RHSv; break;
+ case SRL: Result = (uint64_t)LHSv >> (uint64_t)RHSv; break;
+ }
+ return new IntInit(Result);
+ }
+ break;
+ }
+ }
+ return this;
+}
+
+Init *BinOpInit::resolveReferences(Record &R, const RecordVal *RV) {
+ Init *lhs = LHS->resolveReferences(R, RV);
+ Init *rhs = RHS->resolveReferences(R, RV);
+
+ if (LHS != lhs || RHS != rhs)
+ return (new BinOpInit(getOpcode(), lhs, rhs, getType()))->Fold(&R, 0);
+ return Fold(&R, 0);
+}
+
+std::string BinOpInit::getAsString() const {
+ std::string Result;
+ switch (Opc) {
+ case CONCAT: Result = "!con"; break;
+ case SHL: Result = "!shl"; break;
+ case SRA: Result = "!sra"; break;
+ case SRL: Result = "!srl"; break;
+ case EQ: Result = "!eq"; break;
+ case STRCONCAT: Result = "!strconcat"; break;
+ }
+ 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;
+ }