From 3f7b7f8ce0b050fc6a0100839d9c5a84198b2aed Mon Sep 17 00:00:00 2001 From: Sean Silva Date: Wed, 10 Oct 2012 20:24:47 +0000 Subject: [PATCH] tblgen: Use semantically correct RTTI functions. Also, some minor cleanup. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@165647 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/TableGen/Record.cpp | 46 ++++++++--------------- lib/TableGen/TGParser.cpp | 11 +++--- utils/TableGen/AsmMatcherEmitter.cpp | 8 ++-- utils/TableGen/AsmWriterEmitter.cpp | 2 +- utils/TableGen/CodeGenDAGPatterns.cpp | 40 ++++++++++---------- utils/TableGen/CodeGenInstruction.cpp | 11 +++--- utils/TableGen/FastISelEmitter.cpp | 7 ++-- utils/TableGen/FixedLenDecoderEmitter.cpp | 4 +- utils/TableGen/InstrInfoEmitter.cpp | 2 +- utils/TableGen/RegisterInfoEmitter.cpp | 2 +- utils/TableGen/SetTheory.cpp | 2 +- 11 files changed, 57 insertions(+), 78 deletions(-) diff --git a/lib/TableGen/Record.cpp b/lib/TableGen/Record.cpp index 3f5d9a1c27c..c7b2de2b0fe 100644 --- a/lib/TableGen/Record.cpp +++ b/lib/TableGen/Record.cpp @@ -650,7 +650,7 @@ Init *ListInit::resolveListElementReference(Record &R, const RecordVal *IRV, // If the element is set to some value, or if we are resolving a reference // to a specific variable and that variable is explicitly unset, then // replace the VarListElementInit with it. - if (IRV || !dyn_cast(E)) + if (IRV || !isa(E)) return E; return 0; } @@ -709,23 +709,16 @@ Init *UnOpInit::Fold(Record *CurRec, MultiClass *CurMultiClass) const { switch (getOpcode()) { case CAST: { if (getType()->getAsString() == "string") { - StringInit *LHSs = dyn_cast(LHS); - if (LHSs) { + if (StringInit *LHSs = dyn_cast(LHS)) return LHSs; - } - DefInit *LHSd = dyn_cast(LHS); - if (LHSd) { + if (DefInit *LHSd = dyn_cast(LHS)) return StringInit::get(LHSd->getDef()->getName()); - } - IntInit *LHSi = dyn_cast(LHS); - if (LHSi) { + if (IntInit *LHSi = dyn_cast(LHS)) return StringInit::get(LHSi->getAsString()); - } } else { - StringInit *LHSs = dyn_cast(LHS); - if (LHSs) { + if (StringInit *LHSs = dyn_cast(LHS)) { std::string Name = LHSs->getValue(); // From TGParser::ParseIDValue @@ -773,8 +766,7 @@ Init *UnOpInit::Fold(Record *CurRec, MultiClass *CurMultiClass) const { break; } case HEAD: { - ListInit *LHSl = dyn_cast(LHS); - if (LHSl) { + if (ListInit *LHSl = dyn_cast(LHS)) { if (LHSl->getSize() == 0) { assert(0 && "Empty list in car"); return 0; @@ -784,8 +776,7 @@ Init *UnOpInit::Fold(Record *CurRec, MultiClass *CurMultiClass) const { break; } case TAIL: { - ListInit *LHSl = dyn_cast(LHS); - if (LHSl) { + if (ListInit *LHSl = dyn_cast(LHS)) { if (LHSl->getSize() == 0) { assert(0 && "Empty list in cdr"); return 0; @@ -802,16 +793,14 @@ Init *UnOpInit::Fold(Record *CurRec, MultiClass *CurMultiClass) const { break; } case EMPTY: { - ListInit *LHSl = dyn_cast(LHS); - if (LHSl) { + if (ListInit *LHSl = dyn_cast(LHS)) { if (LHSl->getSize() == 0) { return IntInit::get(1); } else { return IntInit::get(0); } } - StringInit *LHSs = dyn_cast(LHS); - if (LHSs) { + if (StringInit *LHSs = dyn_cast(LHS)) { if (LHSs->getValue().empty()) { return IntInit::get(1); } else { @@ -1285,8 +1274,7 @@ VarInit *VarInit::get(Init *VN, RecTy *T) { } const std::string &VarInit::getName() const { - StringInit *NameString = - dyn_cast(getNameInit()); + StringInit *NameString = dyn_cast(getNameInit()); assert(NameString && "VarInit name is not a string!"); return NameString->getValue(); } @@ -1318,7 +1306,7 @@ Init *VarInit::resolveListElementReference(Record &R, // If the element is set to some value, or if we are resolving a reference // to a specific variable and that variable is explicitly unset, then // replace the VarListElementInit with it. - if (IRV || !dyn_cast(E)) + if (IRV || !isa(E)) return E; return 0; } @@ -1335,7 +1323,7 @@ Init *VarInit::getFieldInit(Record &R, const RecordVal *RV, const std::string &FieldName) const { if (isa(getType())) if (const RecordVal *Val = R.getValue(VarName)) { - if (RV != Val && (RV || dyn_cast(Val->getValue()))) + if (RV != Val && (RV || isa(Val->getValue()))) return 0; Init *TheInit = Val->getValue(); assert(TheInit != this && "Infinite loop detected!"); @@ -1354,7 +1342,7 @@ Init *VarInit::getFieldInit(Record &R, const RecordVal *RV, /// Init *VarInit::resolveReferences(Record &R, const RecordVal *RV) const { if (RecordVal *Val = R.getValue(VarName)) - if (RV == Val || (RV == 0 && !dyn_cast(Val->getValue()))) + if (RV == Val || (RV == 0 && !isa(Val->getValue()))) return Val->getValue(); return const_cast(this); } @@ -1422,8 +1410,7 @@ Init *VarListElementInit:: resolveListElementReference(Record &R, Init *Result = TI->resolveListElementReference(R, RV, Element); if (Result) { - TypedInit *TInit = dyn_cast(Result); - if (TInit) { + if (TypedInit *TInit = dyn_cast(Result)) { Init *Result2 = TInit->resolveListElementReference(R, RV, Elt); if (Result2) return Result2; return new VarListElementInit(TInit, Elt); @@ -1482,7 +1469,7 @@ Init *FieldInit::resolveListElementReference(Record &R, const RecordVal *RV, // If the element is set to some value, or if we are resolving a // reference to a specific variable and that variable is explicitly // unset, then replace the VarListElementInit with it. - if (RV || !dyn_cast(E)) + if (RV || !isa(E)) return E; } return 0; @@ -1655,8 +1642,7 @@ DefInit *Record::getDefInit() { } const std::string &Record::getName() const { - const StringInit *NameString = - dyn_cast(Name); + const StringInit *NameString = dyn_cast(Name); assert(NameString && "Record name is not a string!"); return NameString->getValue(); } diff --git a/lib/TableGen/TGParser.cpp b/lib/TableGen/TGParser.cpp index 1b1c18b589a..b1f9f724efd 100644 --- a/lib/TableGen/TGParser.cpp +++ b/lib/TableGen/TGParser.cpp @@ -406,8 +406,7 @@ Init *TGParser::ParseObjectName(MultiClass *CurMultiClass) { RecTy *Type = 0; if (CurRec) { - const TypedInit *CurRecName = - dyn_cast(CurRec->getNameInit()); + const TypedInit *CurRecName = dyn_cast(CurRec->getNameInit()); if (!CurRecName) { TokError("Record name is not typed!"); return 0; @@ -1050,20 +1049,20 @@ Init *TGParser::ParseOperation(Record *CurRec) { MHSTy = MHSt->getType(); if (BitsInit *MHSbits = dyn_cast(MHS)) MHSTy = BitsRecTy::get(MHSbits->getNumBits()); - if (dyn_cast(MHS)) + if (isa(MHS)) MHSTy = BitRecTy::get(); if (TypedInit *RHSt = dyn_cast(RHS)) RHSTy = RHSt->getType(); if (BitsInit *RHSbits = dyn_cast(RHS)) RHSTy = BitsRecTy::get(RHSbits->getNumBits()); - if (dyn_cast(RHS)) + if (isa(RHS)) RHSTy = BitRecTy::get(); // For UnsetInit, it's typed from the other hand. - if (dyn_cast(MHS)) + if (isa(MHS)) MHSTy = RHSTy; - if (dyn_cast(RHS)) + if (isa(RHS)) RHSTy = MHSTy; if (!MHSTy || !RHSTy) { diff --git a/utils/TableGen/AsmMatcherEmitter.cpp b/utils/TableGen/AsmMatcherEmitter.cpp index 0000f7e0dd7..38ddb8021b9 100644 --- a/utils/TableGen/AsmMatcherEmitter.cpp +++ b/utils/TableGen/AsmMatcherEmitter.cpp @@ -993,7 +993,7 @@ AsmMatcherInfo::getOperandClass(const CGIOperandList::OperandInfo &OI, int SubOpIdx) { Record *Rec = OI.Rec; if (SubOpIdx != -1) - Rec = dyn_cast(OI.MIOperandInfo->getArg(SubOpIdx))->getDef(); + Rec = cast(OI.MIOperandInfo->getArg(SubOpIdx))->getDef(); return getOperandClass(Rec, SubOpIdx); } @@ -1206,8 +1206,7 @@ void AsmMatcherInfo::buildOperandClasses() { if (StringInit *SI = dyn_cast(PMName)) { CI->PredicateMethod = SI->getValue(); } else { - assert(dyn_cast(PMName) && - "Unexpected PredicateMethod field!"); + assert(isa(PMName) && "Unexpected PredicateMethod field!"); CI->PredicateMethod = "is" + CI->ClassName; } @@ -1216,8 +1215,7 @@ void AsmMatcherInfo::buildOperandClasses() { if (StringInit *SI = dyn_cast(RMName)) { CI->RenderMethod = SI->getValue(); } else { - assert(dyn_cast(RMName) && - "Unexpected RenderMethod field!"); + assert(isa(RMName) && "Unexpected RenderMethod field!"); CI->RenderMethod = "add" + CI->ClassName + "Operands"; } diff --git a/utils/TableGen/AsmWriterEmitter.cpp b/utils/TableGen/AsmWriterEmitter.cpp index 1497074d3f6..9e453e0f6d2 100644 --- a/utils/TableGen/AsmWriterEmitter.cpp +++ b/utils/TableGen/AsmWriterEmitter.cpp @@ -792,7 +792,7 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) { if (!R->getValueAsBit("EmitAlias")) continue; // We were told not to emit the alias, but to emit the aliasee. const DagInit *DI = R->getValueAsDag("ResultInst"); - const DefInit *Op = dyn_cast(DI->getOperator()); + const DefInit *Op = cast(DI->getOperator()); AliasMap[getQualifiedName(Op->getDef())].push_back(Alias); } diff --git a/utils/TableGen/CodeGenDAGPatterns.cpp b/utils/TableGen/CodeGenDAGPatterns.cpp index f33e83efb73..3b5511c0563 100644 --- a/utils/TableGen/CodeGenDAGPatterns.cpp +++ b/utils/TableGen/CodeGenDAGPatterns.cpp @@ -582,7 +582,7 @@ typedef DepVarMap::const_iterator DepVarMap_citer; static void FindDepVarsOf(TreePatternNode *N, DepVarMap &DepMap) { if (N->isLeaf()) { - if (dyn_cast(N->getLeafValue()) != NULL) + if (isa(N->getLeafValue())) DepMap[N->getName()]++; } else { for (size_t i = 0, e = N->getNumChildren(); i != e; ++i) @@ -691,7 +691,7 @@ static unsigned getPatternSize(const TreePatternNode *P, unsigned Size = 3; // The node itself. // If the root node is a ConstantSDNode, increases its size. // e.g. (set R32:$dst, 0). - if (P->isLeaf() && dyn_cast(P->getLeafValue())) + if (P->isLeaf() && isa(P->getLeafValue())) Size += 2; // FIXME: This is a hack to statically increase the priority of patterns @@ -715,7 +715,7 @@ static unsigned getPatternSize(const TreePatternNode *P, Child->getType(0) != MVT::Other) Size += getPatternSize(Child, CGP); else if (Child->isLeaf()) { - if (dyn_cast(Child->getLeafValue())) + if (isa(Child->getLeafValue())) Size += 5; // Matches a ConstantSDNode (+3) and a specific value (+2). else if (Child->getComplexPatternInfo(CGP)) Size += getPatternSize(Child, CGP); @@ -864,7 +864,7 @@ bool SDTypeConstraint::ApplyTypeConstraint(TreePatternNode *N, // The NodeToApply must be a leaf node that is a VT. OtherOperandNum must // have an integer type that is smaller than the VT. if (!NodeToApply->isLeaf() || - !dyn_cast(NodeToApply->getLeafValue()) || + !isa(NodeToApply->getLeafValue()) || !static_cast(NodeToApply->getLeafValue())->getDef() ->isSubClassOf("ValueType")) TP.error(N->getOperator()->getName() + " expects a VT operand!"); @@ -1021,8 +1021,9 @@ static unsigned GetNumNodeResults(Record *Operator, CodeGenDAGPatterns &CDP) { // Get the result tree. DagInit *Tree = Operator->getValueAsDag("Fragment"); Record *Op = 0; - if (Tree && dyn_cast(Tree->getOperator())) - Op = dyn_cast(Tree->getOperator())->getDef(); + if (Tree) + if (DefInit *DI = dyn_cast(Tree->getOperator())) + Op = DI->getDef(); assert(Op && "Invalid Fragment"); return GetNumNodeResults(Op, CDP); } @@ -1154,8 +1155,8 @@ SubstituteFormalArguments(std::map &ArgMap) { TreePatternNode *Child = getChild(i); if (Child->isLeaf()) { Init *Val = Child->getLeafValue(); - if (dyn_cast(Val) && - static_cast(Val)->getDef()->getName() == "node") { + if (isa(Val) && + cast(Val)->getDef()->getName() == "node") { // We found a use of a formal argument, replace it with its value. TreePatternNode *NewChild = ArgMap[Child->getName()]; assert(NewChild && "Couldn't find formal argument!"); @@ -1316,8 +1317,7 @@ getIntrinsicInfo(const CodeGenDAGPatterns &CDP) const { getOperator() != CDP.get_intrinsic_wo_chain_sdnode()) return 0; - unsigned IID = - dyn_cast(getChild(0)->getLeafValue())->getValue(); + unsigned IID = cast(getChild(0)->getLeafValue())->getValue(); return &CDP.getIntrinsicInfo(IID); } @@ -1641,7 +1641,7 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) { static bool OnlyOnRHSOfCommutative(TreePatternNode *N) { if (!N->isLeaf() && N->getOperator()->getName() == "imm") return true; - if (N->isLeaf() && dyn_cast(N->getLeafValue())) + if (N->isLeaf() && isa(N->getLeafValue())) return true; return false; } @@ -1763,7 +1763,7 @@ TreePatternNode *TreePattern::ParseTreePattern(Init *TheInit, StringRef OpName){ if (BitsInit *BI = dyn_cast(TheInit)) { // Turn this into an IntInit. Init *II = BI->convertInitializerTo(IntRecTy::get()); - if (II == 0 || !dyn_cast(II)) + if (II == 0 || !isa(II)) error("Bits value must be constants!"); return ParseTreePattern(II, OpName); } @@ -2115,9 +2115,8 @@ void CodeGenDAGPatterns::ParsePatternFragments() { // Copy over the arguments. Args.clear(); for (unsigned j = 0, e = OpsList->getNumArgs(); j != e; ++j) { - if (!dyn_cast(OpsList->getArg(j)) || - static_cast(OpsList->getArg(j))-> - getDef()->getName() != "node") + if (!isa(OpsList->getArg(j)) || + cast(OpsList->getArg(j))->getDef()->getName() != "node") P->error("Operands list should all be 'node' values."); if (OpsList->getArgName(j).empty()) P->error("Operands list should have names for each operand!"); @@ -2246,7 +2245,7 @@ static bool HandleUse(TreePattern *I, TreePatternNode *Pat, } Record *SlotRec; if (Slot->isLeaf()) { - SlotRec = dyn_cast(Slot->getLeafValue())->getDef(); + SlotRec = cast(Slot->getLeafValue())->getDef(); } else { assert(Slot->getNumChildren() == 0 && "can't be a use with children!"); SlotRec = Slot->getOperator(); @@ -2381,7 +2380,7 @@ private: return false; const TreePatternNode *N0 = N->getChild(0); - if (!N0->isLeaf() || !dyn_cast(N0->getLeafValue())) + if (!N0->isLeaf() || !isa(N0->getLeafValue())) return false; const TreePatternNode *N1 = N->getChild(1); @@ -2552,7 +2551,7 @@ void CodeGenDAGPatterns::ParseInstructions() { for (unsigned i = 0, e = Instrs.size(); i != e; ++i) { ListInit *LI = 0; - if (dyn_cast(Instrs[i]->getValueInit("Pattern"))) + if (isa(Instrs[i]->getValueInit("Pattern"))) LI = Instrs[i]->getValueAsListInit("Pattern"); // If there is no pattern, only collect minimal information about the @@ -2647,7 +2646,7 @@ void CodeGenDAGPatterns::ParseInstructions() { if (i == 0) Res0Node = RNode; - Record *R = dyn_cast(RNode->getLeafValue())->getDef(); + Record *R = cast(RNode->getLeafValue())->getDef(); if (R == 0) I->error("Operand $" + OpName + " should be a set destination: all " "outputs must occur before inputs in operand list!"); @@ -2689,8 +2688,7 @@ void CodeGenDAGPatterns::ParseInstructions() { TreePatternNode *InVal = InstInputsCheck[OpName]; InstInputsCheck.erase(OpName); // It occurred, remove from map. - if (InVal->isLeaf() && - dyn_cast(InVal->getLeafValue())) { + if (InVal->isLeaf() && isa(InVal->getLeafValue())) { Record *InRec = static_cast(InVal->getLeafValue())->getDef(); if (Op.Rec != InRec && !InRec->isSubClassOf("ComplexPattern")) I->error("Operand $" + OpName + "'s register class disagrees" diff --git a/utils/TableGen/CodeGenInstruction.cpp b/utils/TableGen/CodeGenInstruction.cpp index 82335cf9f39..99d2f173a87 100644 --- a/utils/TableGen/CodeGenInstruction.cpp +++ b/utils/TableGen/CodeGenInstruction.cpp @@ -80,9 +80,8 @@ CGIOperandList::CGIOperandList(Record *R) : TheDef(R) { MIOpInfo = Rec->getValueAsDag("MIOperandInfo"); // Verify that MIOpInfo has an 'ops' root value. - if (!dyn_cast(MIOpInfo->getOperator()) || - dyn_cast(MIOpInfo->getOperator()) - ->getDef()->getName() != "ops") + if (!isa(MIOpInfo->getOperator()) || + cast(MIOpInfo->getOperator())->getDef()->getName() != "ops") throw "Bad value for MIOperandInfo in operand '" + Rec->getName() + "'\n"; @@ -446,7 +445,7 @@ bool CodeGenInstAlias::tryAliasOpMatch(DagInit *Result, unsigned AliasOpNo, DagInit *DI = InstOpRec->getValueAsDag("MIOperandInfo"); // The operand info should only have a single (register) entry. We // want the register class of it. - InstOpRec = dyn_cast(DI->getArg(0))->getDef(); + InstOpRec = cast(DI->getArg(0))->getDef(); } if (InstOpRec->isSubClassOf("RegisterOperand")) @@ -575,7 +574,7 @@ CodeGenInstAlias::CodeGenInstAlias(Record *R, CodeGenTarget &T) : TheDef(R) { } else { DagInit *MIOI = ResultInst->Operands[i].MIOperandInfo; for (unsigned SubOp = 0; SubOp != NumSubOps; ++SubOp) { - Record *SubRec = dyn_cast(MIOI->getArg(SubOp))->getDef(); + Record *SubRec = cast(MIOI->getArg(SubOp))->getDef(); // Take care to instantiate each of the suboperands with the correct // nomenclature: $foo.bar @@ -596,7 +595,7 @@ CodeGenInstAlias::CodeGenInstAlias(Record *R, CodeGenTarget &T) : TheDef(R) { for (unsigned SubOp = 0; SubOp != NumSubOps; ++SubOp) { if (AliasOpNo >= Result->getNumArgs()) throw TGError(R->getLoc(), "not enough arguments for instruction!"); - Record *SubRec = dyn_cast(MIOI->getArg(SubOp))->getDef(); + Record *SubRec = cast(MIOI->getArg(SubOp))->getDef(); if (tryAliasOpMatch(Result, AliasOpNo, SubRec, false, R->getLoc(), T, ResOp)) { ResultOperands.push_back(ResOp); diff --git a/utils/TableGen/FastISelEmitter.cpp b/utils/TableGen/FastISelEmitter.cpp index c6d71ff8cf4..03e918fa4b0 100644 --- a/utils/TableGen/FastISelEmitter.cpp +++ b/utils/TableGen/FastISelEmitter.cpp @@ -406,13 +406,12 @@ static std::string PhyRegForNode(TreePatternNode *Op, if (!Op->isLeaf()) return PhysReg; - DefInit *OpDI = dyn_cast(Op->getLeafValue()); - Record *OpLeafRec = OpDI->getDef(); + Record *OpLeafRec = cast(Op->getLeafValue())->getDef(); if (!OpLeafRec->isSubClassOf("Register")) return PhysReg; - PhysReg += static_cast(OpLeafRec->getValue( \ - "Namespace")->getValue())->getValue(); + PhysReg += cast(OpLeafRec->getValue("Namespace")->getValue()) + ->getValue(); PhysReg += "::"; PhysReg += Target.getRegBank().getReg(OpLeafRec)->getName(); return PhysReg; diff --git a/utils/TableGen/FixedLenDecoderEmitter.cpp b/utils/TableGen/FixedLenDecoderEmitter.cpp index aa4dd8a762f..c53776b9ffb 100644 --- a/utils/TableGen/FixedLenDecoderEmitter.cpp +++ b/utils/TableGen/FixedLenDecoderEmitter.cpp @@ -1757,8 +1757,8 @@ static bool populateInstruction(const CodeGenInstruction &CGI, unsigned Opc, // for decoding register classes. // FIXME: This need to be extended to handle instructions with custom // decoder methods, and operands with (simple) MIOperandInfo's. - TypedInit *TI = dyn_cast(NI->first); - RecordRecTy *Type = dyn_cast(TI->getType()); + TypedInit *TI = cast(NI->first); + RecordRecTy *Type = cast(TI->getType()); Record *TypeRecord = Type->getRecord(); bool isReg = false; if (TypeRecord->isSubClassOf("RegisterOperand")) diff --git a/utils/TableGen/InstrInfoEmitter.cpp b/utils/TableGen/InstrInfoEmitter.cpp index 34e363d6692..4e97cf4693b 100644 --- a/utils/TableGen/InstrInfoEmitter.cpp +++ b/utils/TableGen/InstrInfoEmitter.cpp @@ -89,7 +89,7 @@ InstrInfoEmitter::GetOperandInfo(const CodeGenInstruction &Inst) { for (unsigned j = 0, e = Inst.Operands[i].MINumOperands; j != e; ++j) { OperandList.push_back(Inst.Operands[i]); - Record *OpR = dyn_cast(MIOI->getArg(j))->getDef(); + Record *OpR = cast(MIOI->getArg(j))->getDef(); OperandList.back().Rec = OpR; } } diff --git a/utils/TableGen/RegisterInfoEmitter.cpp b/utils/TableGen/RegisterInfoEmitter.cpp index dcd0510768a..ad1dab4ac08 100644 --- a/utils/TableGen/RegisterInfoEmitter.cpp +++ b/utils/TableGen/RegisterInfoEmitter.cpp @@ -325,7 +325,7 @@ RegisterInfoEmitter::EmitRegMappingTables(raw_ostream &OS, if (!V || !V->getValue()) continue; - DefInit *DI = dyn_cast(V->getValue()); + DefInit *DI = cast(V->getValue()); Record *Alias = DI->getDef(); DwarfRegNums[Reg] = DwarfRegNums[Alias]; } diff --git a/utils/TableGen/SetTheory.cpp b/utils/TableGen/SetTheory.cpp index dcc887125ea..5b760e7a233 100644 --- a/utils/TableGen/SetTheory.cpp +++ b/utils/TableGen/SetTheory.cpp @@ -193,7 +193,7 @@ struct SequenceOp : public SetTheory::Operator { throw "To out of range"; RecordKeeper &Records = - dyn_cast(Expr->getOperator())->getDef()->getRecords(); + cast(Expr->getOperator())->getDef()->getRecords(); Step *= From <= To ? 1 : -1; while (true) { -- 2.34.1