@@ -3584,6 +3584,24 @@ void OpEmitter::genTypeInterfaceMethods() {
3584
3584
fctx.addSubst (" _ctxt" , " context" );
3585
3585
body << " ::mlir::Builder odsBuilder(context);\n " ;
3586
3586
3587
+ // Preprocessing stage to verify all accesses to operands are valid.
3588
+ int maxAccessedIndex = -1 ;
3589
+ for (int i = 0 , e = op.getNumResults (); i != e; ++i) {
3590
+ const InferredResultType &infer = op.getInferredResultType (i);
3591
+ if (!infer.isArg ())
3592
+ continue ;
3593
+ Operator::OperandOrAttribute arg =
3594
+ op.getArgToOperandOrAttribute (infer.getIndex ());
3595
+ if (arg.kind () == Operator::OperandOrAttribute::Kind::Operand) {
3596
+ maxAccessedIndex =
3597
+ std::max (maxAccessedIndex, arg.operandOrAttributeIndex ());
3598
+ }
3599
+ }
3600
+ if (maxAccessedIndex != -1 ) {
3601
+ body << " if (operands.size() <= " << Twine (maxAccessedIndex) << " )\n " ;
3602
+ body << " return ::mlir::failure();\n " ;
3603
+ }
3604
+
3587
3605
// Process the type inference graph in topological order, starting from types
3588
3606
// that are always fully-inferred: operands and results with constructible
3589
3607
// types. The type inference graph here will always be a DAG, so this gives
@@ -3600,7 +3618,8 @@ void OpEmitter::genTypeInterfaceMethods() {
3600
3618
if (infer.isArg ()) {
3601
3619
// If this is an operand, just index into operand list to access the
3602
3620
// type.
3603
- auto arg = op.getArgToOperandOrAttribute (infer.getIndex ());
3621
+ Operator::OperandOrAttribute arg =
3622
+ op.getArgToOperandOrAttribute (infer.getIndex ());
3604
3623
if (arg.kind () == Operator::OperandOrAttribute::Kind::Operand) {
3605
3624
typeStr = (" operands[" + Twine (arg.operandOrAttributeIndex ()) +
3606
3625
" ].getType()" )
0 commit comments