// CHECK: class AOpOperandAdaptor {
// CHECK: public:
// CHECK: AOpOperandAdaptor(ArrayRef<Value *> values);
+// CHECK: ArrayRef<Value *> getODSOperands(unsigned index);
// CHECK: Value *a();
// CHECK: ArrayRef<Value *> b();
// CHECK: private:
// CHECK: using Op::Op;
// CHECK: using OperandAdaptor = AOpOperandAdaptor;
// CHECK: static StringRef getOperationName();
+// CHECK: Operation::operand_range getODSOperands(unsigned index);
// CHECK: Value *a();
// CHECK: Operation::operand_range b();
+// CHECK: Operation::result_range getODSResults(unsigned index);
// CHECK: Value *r();
// CHECK: APInt attr1();
// CHECK: Optional< APFloat > attr2();
// CHECK: OpAOperandAdaptor::OpAOperandAdaptor
// CHECK-NEXT: tblgen_operands = values
-// CHECK: OpAOperandAdaptor::input
-// CHECK-NEXT: return tblgen_operands[0]
-
// CHECK: void OpA::build
// CHECK-SAME: Value *input
// CHECK: tblgen_state->operands.push_back(input);
// CHECK-NOT: assert
// CHECK: tblgen_state->addOperands(input);
-def OpC : NS_Op<"all_variadic_inputs_op", [SameVariadicOperandSize]> {
- let arguments = (ins Variadic<AnyTensor>:$input1, Variadic<AnyTensor>:$input2);
+def OpD : NS_Op<"mix_variadic_and_normal_inputs_op", [SameVariadicOperandSize]> {
+ let arguments = (ins Variadic<AnyTensor>:$input1, AnyTensor:$input2, Variadic<AnyTensor>:$input3);
}
-// CHECK-LABEL: OpCOperandAdaptor::input1
-// CHECK-NEXT: variadicOperandSize = (tblgen_operands.size() - 0) / 2;
-// CHECK-NEXT: offset = 0 + variadicOperandSize * 0;
-// CHECK-NEXT: return {std::next(tblgen_operands.begin(), offset), std::next(tblgen_operands.begin(), offset + variadicOperandSize)};
+// CHECK-LABEL: ArrayRef<Value *> OpDOperandAdaptor::input1
+// CHECK-NEXT: return getODSOperands(0);
-// CHECK-LABEL: OpCOperandAdaptor::input2
-// CHECK-NEXT: variadicOperandSize = (tblgen_operands.size() - 0) / 2;
-// CHECK-NEXT: offset = 0 + variadicOperandSize * 1;
-// CHECK-NEXT: return {std::next(tblgen_operands.begin(), offset), std::next(tblgen_operands.begin(), offset + variadicOperandSize)};
+// CHECK-LABEL: Value *OpDOperandAdaptor::input2
+// CHECK-NEXT: return *getODSOperands(1).begin();
-// CHECK-LABEL: Operation::operand_range OpC::input1()
-// CHECK-NEXT: variadicOperandSize = (this->getNumOperands() - 0) / 2;
-// CHECK-NEXT: offset = 0 + variadicOperandSize * 0;
-// CHECK-NEXT: return {std::next(operand_begin(), offset), std::next(operand_begin(), offset + variadicOperandSize)};
+// CHECK-LABEL: ArrayRef<Value *> OpDOperandAdaptor::input3
+// CHECK-NEXT: return getODSOperands(2);
-// CHECK-LABEL: Operation::operand_range OpC::input2()
-// CHECK-NEXT: variadicOperandSize = (this->getNumOperands() - 0) / 2;
-// CHECK-NEXT: offset = 0 + variadicOperandSize * 1;
-// CHECK-NEXT: return {std::next(operand_begin(), offset), std::next(operand_begin(), offset + variadicOperandSize)};
+// TODO(b/134305899): Move to use TestDialect after fixing verification.
-// CHECK-LABEL: OpC::build
-// CHECK-NEXT: tblgen_state->addOperands(input1);
-// CHECK-NEXT: tblgen_state->addOperands(input2);
+// CHECK-LABEL: Operation::operand_range OpD::getODSOperands(unsigned index)
+// CHECK-NEXT: bool isVariadic[] = {true, false, true};
+// CHECK-NEXT: int prevVariadicCount = 0;
+// CHECK-NEXT: for (int i = 0; i < index; ++i)
+// CHECK-NEXT: if (isVariadic[i]) ++prevVariadicCount;
-def OpD : NS_Op<"mix_variadic_and_normal_inputs_op", [SameVariadicOperandSize]> {
- let arguments = (ins Variadic<AnyTensor>:$input1, AnyTensor:$input2, Variadic<AnyTensor>:$input3);
-}
-
-// CHECK-LABEL: OpDOperandAdaptor::input1() {
-// CHECK-NEXT: variadicOperandSize = (tblgen_operands.size() - 1) / 2;
-// CHECK-NEXT: offset = 0 + variadicOperandSize * 0;
-// CHECK-NEXT: return {std::next(tblgen_operands.begin(), offset), std::next(tblgen_operands.begin(), offset + variadicOperandSize)};
-
-// CHECK-LABEL: Value *OpDOperandAdaptor::input2() {
-// CHECK-NEXT: variadicOperandSize = (tblgen_operands.size() - 1) / 2;
-// CHECK-NEXT: offset = 0 + variadicOperandSize * 1;
-// CHECK-NEXT: return tblgen_operands[offset];
+// CHECK: int variadicSize = (getOperation()->getNumOperands() - 1) / 2;
+// CHECK: int offset = index + (variadicSize - 1) * prevVariadicCount;
+// CHECK-NEXT: int size = isVariadic[index] ? variadicSize : 1;
-// CHECK-LABEL: OpDOperandAdaptor::input3() {
-// CHECK-NEXT: variadicOperandSize = (tblgen_operands.size() - 1) / 2;
-// CHECK-NEXT: offset = 1 + variadicOperandSize * 1;
-// CHECK-NEXT: return {std::next(tblgen_operands.begin(), offset), std::next(tblgen_operands.begin(), offset + variadicOperandSize)};
+// CHECK: return {std::next(getOperation()->operand_begin(), offset), std::next(getOperation()->operand_begin(), offset + size)};
-// CHECK-LABEL: Operation::operand_range OpD::input1()
-// CHECK-NEXT: variadicOperandSize = (this->getNumOperands() - 1) / 2;
-// CHECK-NEXT: offset = 0 + variadicOperandSize * 0;
-// CHECK-NEXT: return {std::next(operand_begin(), offset), std::next(operand_begin(), offset + variadicOperandSize)};
+// CHECK-LABEL: Operation::operand_range OpD::input1
+// CHECK-NEXT: return getODSOperands(0);
-// CHECK-LABEL: Value *OpD::input2()
-// CHECK-NEXT: variadicOperandSize = (this->getNumOperands() - 1) / 2;
-// CHECK-NEXT: offset = 0 + variadicOperandSize * 1;
-// CHECK-NEXT: return this->getOperation()->getOperand(offset);
-
-// CHECK-LABEL: Operation::operand_range OpD::input3()
-// CHECK-NEXT: variadicOperandSize = (this->getNumOperands() - 1) / 2;
-// CHECK-NEXT: offset = 1 + variadicOperandSize * 1;
-// CHECK-NEXT: return {std::next(operand_begin(), offset), std::next(operand_begin(), offset + variadicOperandSize)};
+// CHECK-LABEL: Value *OpD::input2
+// CHECK-NEXT: return *getODSOperands(1).begin();
// CHECK-LABEL: OpD::build
// CHECK-NEXT: tblgen_state->addOperands(input1);
// CHECK-NEXT: tblgen_state->operands.push_back(input2);
// CHECK-NEXT: tblgen_state->addOperands(input3);
-
-def OpE : NS_Op<"one_variadic_among_multi_normal_inputs_op", []> {
- let arguments = (ins AnyTensor:$input1, AnyTensor:$input2, Variadic<AnyTensor>:$input3, AnyTensor:$input4, AnyTensor:$input5);
-}
-
-// CHECK-LABEL: Value *OpEOperandAdaptor::input1() {
-// CHECK-NEXT: return tblgen_operands[0];
-
-// CHECK-LABEL: Value *OpEOperandAdaptor::input2() {
-// CHECK-NEXT: return tblgen_operands[1];
-
-// CHECK-LABEL: OpEOperandAdaptor::input3() {
-// CHECK-NEXT: return {std::next(tblgen_operands.begin(), 2), std::next(tblgen_operands.begin(), 2 + tblgen_operands.size() - 4)};
-
-// CHECK-LABEL: Value *OpEOperandAdaptor::input4() {
-// CHECK-NEXT: return tblgen_operands[tblgen_operands.size() - 2];
-
-// CHECK-LABEL: Value *OpEOperandAdaptor::input5() {
-// CHECK-NEXT: return tblgen_operands[tblgen_operands.size() - 1];
-
-// CHECK-LABEL: Value *OpE::input1()
-// CHECK-NEXT: return this->getOperation()->getOperand(0);
-
-// CHECK-LABEL: Value *OpE::input2()
-// CHECK-NEXT: return this->getOperation()->getOperand(1);
-
-// CHECK-LABEL: Operation::operand_range OpE::input3()
-// CHECK-NEXT: return {std::next(operand_begin(), 2), std::next(operand_begin(), 2 + this->getNumOperands() - 4)};
-
-// CHECK-LABEL: Value *OpE::input4()
-// CHECK-NEXT: return this->getOperation()->getOperand(this->getNumOperands() - 2);
-
-// CHECK-LABEL: Value *OpE::input5()
-// CHECK-NEXT: return this->getOperation()->getOperand(this->getNumOperands() - 1);
let results = (outs I32:$result);
}
-// CHECK-LABEL: Value *OpA::result()
-// CHECK-NEXT: return this->getOperation()->getResult(0)
-
// CHECK-LABEL: void OpA::build
// CHECK: ArrayRef<Type> resultTypes, ArrayRef<Value *> operands
// CHECK: assert(resultTypes.size() == 1u && "mismatched number of return types");
let results = (outs Variadic<I32>:$x);
}
-// CHECK-LABEL: Operation::result_range OpF::x()
-// CHECK-NEXT: return {std::next(result_begin(), 0), std::next(result_begin(), 0 + this->getNumResults() - 0)};
-
// CHECK-LABEL: void OpF::build
// CHECK-SAME: ArrayRef<Type> x
// CHECK-NOT: assert
// CHECK-NEXT: tblgen_state->types.push_back(x);
// CHECK-NEXT: tblgen_state->addTypes(y);
-// CHECK: void OpG::build
+// CHECK: void OpG::build
// CHECK: ArrayRef<Type> resultTypes
// CHECK: assert(resultTypes.size() >= 1u && "mismatched number of return types");
// CHECK-NEXT: tblgen_state->addTypes(resultTypes);
-
-def OpH : NS_Op<"all_variadic_results_op", [SameVariadicResultSize]> {
- let results = (outs Variadic<AnyTensor>:$output1, Variadic<AnyTensor>:$output2);
+def OpI : NS_Op<"mix_variadic_and_normal_results_op", [SameVariadicResultSize]> {
+ let results = (outs Variadic<AnyTensor>:$output1, AnyTensor:$output2, Variadic<AnyTensor>:$output3);
}
-// CHECK-LABEL: Operation::result_range OpH::output1()
-// CHECK-NEXT: variadicResultSize = (this->getNumResults() - 0) / 2;
-// CHECK-NEXT: offset = 0 + variadicResultSize * 0;
-// CHECK-NEXT: return {std::next(result_begin(), offset), std::next(result_begin(), offset + variadicResultSize)};
+// TODO(b/134305899): Move to use TestDialect after fixing verification.
-// CHECK-LABEL: Operation::result_range OpH::output2()
-// CHECK-NEXT: variadicResultSize = (this->getNumResults() - 0) / 2;
-// CHECK-NEXT: offset = 0 + variadicResultSize * 1;
-// CHECK-NEXT: return {std::next(result_begin(), offset), std::next(result_begin(), offset + variadicResultSize)};
+// CHECK-LABEL: Operation::result_range OpI::getODSResults(unsigned index)
+// CHECK-NEXT: bool isVariadic[] = {true, false, true};
+// CHECK-NEXT: int prevVariadicCount = 0;
+// CHECK-NEXT: for (int i = 0; i < index; ++i)
+// CHECK-NEXT: if (isVariadic[i]) ++prevVariadicCount;
+// CHECK: int variadicSize = (getOperation()->getNumResults() - 1) / 2;
+// CHECK: int offset = index + (variadicSize - 1) * prevVariadicCount;
+// CHECK-NEXT: int size = isVariadic[index] ? variadicSize : 1;
-// CHECK-LABEL: OpH::build
-// CHECK-NEXT: tblgen_state->addTypes(output1);
-// CHECK-NEXT: tblgen_state->addTypes(output2);
-
-def OpI : NS_Op<"mix_variadic_and_normal_results_op", [SameVariadicResultSize]> {
- let results = (outs Variadic<AnyTensor>:$output1, AnyTensor:$output2, Variadic<AnyTensor>:$output3);
-}
-
-// CHECK-LABEL: Operation::result_range OpI::output1()
-// CHECK-NEXT: variadicResultSize = (this->getNumResults() - 1) / 2;
-// CHECK-NEXT: offset = 0 + variadicResultSize * 0;
-// CHECK-NEXT: return {std::next(result_begin(), offset), std::next(result_begin(), offset + variadicResultSize)};
+// CHECK: return {std::next(getOperation()->result_begin(), offset), std::next(getOperation()->result_begin(), offset + size)};
-// CHECK-LABEL: Value *OpI::output2()
-// CHECK-NEXT: variadicResultSize = (this->getNumResults() - 1) / 2;
-// CHECK-NEXT: offset = 0 + variadicResultSize * 1;
-// CHECK-NEXT: return this->getResult(offset);
+// CHECK-LABEL: Operation::result_range OpI::output1
+// CHECK-NEXT: return getODSResults(0);
-// CHECK-LABEL: Operation::result_range OpI::output3()
-// CHECK-NEXT: variadicResultSize = (this->getNumResults() - 1) / 2;
-// CHECK-NEXT: offset = 1 + variadicResultSize * 1;
-// CHECK-NEXT: return {std::next(result_begin(), offset), std::next(result_begin(), offset + variadicResultSize)};
+// CHECK-LABEL: Value *OpI::output2
+// CHECK-NEXT: return *getODSResults(1).begin();
// CHECK-LABEL: OpI::build
// CHECK-NEXT: tblgen_state->addTypes(output1);
// CHECK-NEXT: tblgen_state->types.push_back(output2);
// CHECK-NEXT: tblgen_state->addTypes(output3);
-def OpJ : NS_Op<"one_variadic_among_multi_normal_results_op", []> {
- let results = (outs AnyTensor:$output1, AnyTensor:$output2, Variadic<AnyTensor>:$output3, AnyTensor:$output4, AnyTensor:$output5);
-}
-
-// CHECK-LABEL: Value *OpJ::output1()
-// CHECK-NEXT: return this->getOperation()->getResult(0);
-
-// CHECK-LABEL: Value *OpJ::output2()
-// CHECK-NEXT: return this->getOperation()->getResult(1);
-
-// CHECK-LABEL: Operation::result_range OpJ::output3()
-// CHECK-NEXT: return {std::next(result_begin(), 2), std::next(result_begin(), 2 + this->getNumResults() - 4)};
-
-// CHECK-LABEL: Value *OpJ::output4()
-// CHECK-NEXT: return this->getOperation()->getResult(this->getNumResults() - 2);
-
-// CHECK-LABEL: Value *OpJ::output5()
-// CHECK-NEXT: return this->getOperation()->getResult(this->getNumResults() - 1);
-
// Test that if the only operand is variadic, we acess the first value in the
// pack to set result type
// ---
static const char *const generatedArgName = "tblgen_arg";
static const char *const builderOpState = "tblgen_state";
+// The logic to calculate the dynamic value range for an static operand/result
+// of an op with variadic operands/results. Note that this logic is not for
+// general use; it assumes all variadic operands/results must have the same
+// number of values.
+//
+// {0}: The list of whether each static operand/result is variadic.
+// {1}: The total number of non-variadic operands/results.
+// {2}: The total number of variadic operands/results.
+// {3}: The total number of dynamic values.
+// {4}: The begin iterator of the dynamic values.
+// {5}: "operand" or "result"
+const char *valueRangeCalcCode = R"(
+ bool isVariadic[] = {{{0}};
+ int prevVariadicCount = 0;
+ for (int i = 0; i < index; ++i)
+ if (isVariadic[i]) ++prevVariadicCount;
+
+ // Calculate how many dynamic values a static variadic {5} corresponds to.
+ // This assumes all static variadic {5}s have the same dynamic value count.
+ int variadicSize = ({3} - {1}) / {2};
+ // `index` passed in as the parameter is the static index which counts each
+ // {5} (variadic or not) as size 1. So here for each previous static variadic
+ // {5}, we need to offset by (variadicSize - 1) to get where the dynamic
+ // value pack for this static {5} starts.
+ int offset = index + (variadicSize - 1) * prevVariadicCount;
+ int size = isVariadic[index] ? variadicSize : 1;
+
+ return {{std::next({4}, offset), std::next({4}, offset + size)};
+)";
+
static const char *const opCommentHeader = R"(
//===----------------------------------------------------------------------===//
// {0} {1}
const int numVariadicOperands = op.getNumVariadicOperands();
const int numNormalOperands = numOperands - numVariadicOperands;
- // Special case for ops without variadic operands: the i-th value is for the
- // i-th operand defined in the op.
- // Special case for ops with one variadic operand: the variadic operand can
- // appear at any place, so the i-th value may not necessarily belong to the
- // i-th operand definition. we need to calculate the index (range) for each
- // operand.
- if (numVariadicOperands <= 1) {
- bool emittedVariadicOperand = false;
- for (int i = 0; i != numOperands; ++i) {
- const auto &operand = op.getOperand(i);
- if (operand.name.empty())
- continue;
-
- if (operand.isVariadic()) {
- auto &m = opClass.newMethod(rangeType, operand.name);
- m.body() << formatv(
- " return {{std::next({2}, {0}), std::next({2}, {0} + {3} - {1})};",
- i, numNormalOperands, rangeBeginCall, rangeSizeCall);
- emittedVariadicOperand = true;
- } else {
- auto &m = opClass.newMethod("Value *", operand.name);
+ if (numVariadicOperands > 1 && !op.hasTrait("SameVariadicOperandSize")) {
+ PrintFatalError(op.getLoc(), "op has multiple variadic operands but no "
+ "specification over their sizes");
+ }
- auto operandIndex =
- emittedVariadicOperand
- ? formatv("{0} - {1}", rangeSizeCall, numOperands - i).str()
- : std::to_string(i);
+ // First emit a "sink" getter method upon which we layer all nicer named
+ // getter methods.
+ auto &m = opClass.newMethod(rangeType, "getODSOperands", "unsigned index");
- m.body() << " return "
- << formatv(getOperandCallPattern.data(), operandIndex)
- << ";\n";
- }
+ if (numVariadicOperands == 0) {
+ // We still need to match the return type, which is a range.
+ m.body() << "return {std::next(" << rangeBeginCall << ", index), std::next("
+ << rangeBeginCall << ", index + 1)};";
+ } else {
+ // Because the op can have arbitrarily interleaved variadic and non-variadic
+ // operands, we need to embed a list in the "sink" getter method for
+ // calculation at run-time.
+ llvm::SmallVector<StringRef, 4> isVariadic;
+ isVariadic.reserve(numOperands);
+ for (int i = 0; i < numOperands; ++i) {
+ isVariadic.push_back(llvm::toStringRef(op.getOperand(i).isVariadic()));
}
- return;
- }
-
- // If we have more than one variadic operands, we need more complicated logic
- // to calculate the value range for each operand.
+ std::string isVariadicList = llvm::join(isVariadic, ", ");
- if (!op.hasTrait("SameVariadicOperandSize")) {
- PrintFatalError(op.getLoc(), "op has multiple variadic operands but no "
- "specification over their sizes");
+ m.body() << formatv(valueRangeCalcCode, isVariadicList, numNormalOperands,
+ numVariadicOperands, rangeSizeCall, rangeBeginCall,
+ "operand");
}
- int emittedNormalOperands = 0;
- int emittedVariadicOperands = 0;
+ // Then we emit nicer named getter methods by redirecting to the "sink" getter
+ // method.
for (int i = 0; i != numOperands; ++i) {
const auto &operand = op.getOperand(i);
if (operand.name.empty())
continue;
- const char *code = R"(
- int variadicOperandSize = ({4} - {0}) / {1};
- int offset = {2} + variadicOperandSize * {3};
- return )";
- auto sizeAndOffset =
- formatv(code, numNormalOperands, numVariadicOperands,
- emittedNormalOperands, emittedVariadicOperands, rangeSizeCall);
-
if (operand.isVariadic()) {
auto &m = opClass.newMethod(rangeType, operand.name);
- m.body() << sizeAndOffset << "{std::next(" << rangeBeginCall
- << ", offset), std::next(" << rangeBeginCall
- << ", offset + variadicOperandSize)};";
- ++emittedVariadicOperands;
+ m.body() << "return getODSOperands(" << i << ");";
} else {
auto &m = opClass.newMethod("Value *", operand.name);
- m.body() << sizeAndOffset
- << formatv(getOperandCallPattern.data(), "offset") << ";";
- ++emittedNormalOperands;
+ m.body() << "return *getODSOperands(" << i << ").begin();";
}
}
}
void OpEmitter::genNamedOperandGetters() {
generateNamedOperandGetters(
op, opClass, /*rangeType=*/"Operation::operand_range",
- /*rangeBeginCall=*/"operand_begin()",
- /*rangeSizeCall=*/"this->getNumOperands()",
- /*getOperandCallPattern=*/"this->getOperation()->getOperand({0})");
+ /*rangeBeginCall=*/"getOperation()->operand_begin()",
+ /*rangeSizeCall=*/"getOperation()->getNumOperands()",
+ /*getOperandCallPattern=*/"getOperation()->getOperand({0})");
}
void OpEmitter::genNamedResultGetters() {
const int numVariadicResults = op.getNumVariadicResults();
const int numNormalResults = numResults - numVariadicResults;
- // Special case for ops without variadic results: the i-th value is for the
- // i-th result defined in the op.
- // Special case for ops with one variadic result: the variadic result can
- // appear at any place, so the i-th value may not necessarily belong to the
- // i-th result definition. we need to calculate the index (range) for each
- // result.
- if (numVariadicResults <= 1) {
- bool emittedVariadicResult = false;
- for (int i = 0; i != numResults; ++i) {
- const auto &result = op.getResult(i);
- if (result.name.empty())
- continue;
-
- if (result.isVariadic()) {
- auto &m = opClass.newMethod("Operation::result_range", result.name);
- m.body() << formatv(
- " return {{std::next(result_begin(), {0}), "
- "std::next(result_begin(), {0} + this->getNumResults() - {1})};",
- i, numNormalResults);
- emittedVariadicResult = true;
- } else {
- auto &m = opClass.newMethod("Value *", result.name);
- m.body() << " return this->getOperation()->getResult(";
- if (emittedVariadicResult)
- m.body() << "this->getNumResults() - " << numResults - i;
- else
- m.body() << i;
- m.body() << ");\n";
- }
- }
- return;
- }
-
// If we have more than one variadic results, we need more complicated logic
// to calculate the value range for each result.
- if (!op.hasTrait("SameVariadicResultSize")) {
+ if (numVariadicResults > 1 && !op.hasTrait("SameVariadicResultSize")) {
PrintFatalError(op.getLoc(), "op has multiple variadic results but no "
"specification over their sizes");
}
- int emittedNormalResults = 0;
- int emittedVariadicResults = 0;
+ auto &m = opClass.newMethod("Operation::result_range", "getODSResults",
+ "unsigned index");
+
+ if (numVariadicResults == 0) {
+ m.body() << "return {std::next(getOperation()->result_begin(), index), "
+ "std::next(getOperation()->result_begin(), index + 1)};";
+ } else {
+ llvm::SmallVector<StringRef, 4> isVariadic;
+ isVariadic.reserve(numResults);
+ for (int i = 0; i < numResults; ++i) {
+ isVariadic.push_back(llvm::toStringRef(op.getResult(i).isVariadic()));
+ }
+ std::string isVariadicList = llvm::join(isVariadic, ", ");
+
+ m.body() << formatv(valueRangeCalcCode, isVariadicList, numNormalResults,
+ numVariadicResults, "getOperation()->getNumResults()",
+ "getOperation()->result_begin()", "result");
+ }
for (int i = 0; i != numResults; ++i) {
const auto &result = op.getResult(i);
if (result.name.empty())
continue;
- const char *code = R"(
- int variadicResultSize = (this->getNumResults() - {0}) / {1};
- int offset = {2} + variadicResultSize * {3};
- return )";
- auto sizeAndOffset = formatv(code, numNormalResults, numVariadicResults,
- emittedNormalResults, emittedVariadicResults);
-
if (result.isVariadic()) {
auto &m = opClass.newMethod("Operation::result_range", result.name);
- m.body() << sizeAndOffset
- << "{std::next(result_begin(), offset), "
- "std::next(result_begin(), offset + variadicResultSize)};";
- ++emittedVariadicResults;
+ m.body() << "return getODSResults(" << i << ");";
} else {
auto &m = opClass.newMethod("Value *", result.name);
- m.body() << sizeAndOffset << "this->getResult(offset);";
- ++emittedNormalResults;
+ m.body() << "return *getODSResults(" << i << ").begin();";
}
}
}