llvm.resume is similar to llvm.return except that has to be exactly one operand and that should be derived from a llvm.landingpad instruction.
Any function having llvm.landingpad instruction must have a personality attribute.
Example:
LLVM IR
define dso_local i32 @main() personality i32 (...)* @__gxx_personality_v0 { invoke void @foo(i32 42) to label %3 unwind label %1 1: ; preds = %0 %2 = landingpad i8* catch i8** @_ZTIi catch i8* bitcast (i8** @_ZTIi to i8*) resume i8* %2 3: ; preds = %0 ret i32 1 }
MLIR - LLVM IR Dialect
llvm.func @main() -> !llvm.i32 attributes {personality = @__gxx_personality_v0} { %0 = llvm.mlir.constant(1 : i32) : !llvm.i32 %1 = llvm.mlir.addressof @_ZTIi : !llvm<"i8**"> %2 = llvm.bitcast %1 : !llvm<"i8**"> to !llvm<"i8*"> %3 = llvm.mlir.addressof @_ZTIi : !llvm<"i8**"> %4 = llvm.mlir.constant(42 : i32) : !llvm.i32 llvm.invoke @foo(%4) to ^bb2 unwind ^bb1 : (!llvm.i32) -> () ^bb1: // pred: ^bb0 %5 = llvm.landingpad (catch %3 : !llvm<"i8**">) (catch %2 : !llvm<"i8*">) : !llvm<"i8*"> llvm.resume %5 : !llvm<"i8*"> ^bb2: // pred: ^bb0 llvm.return %0 : !llvm.i32 }
The number of operands should be checked by declaring them in the "arguments" list with appropriate types. This will need another check to make sure the type matches that mentioned in some "landingpad", but that check can assume the "arguments"-based check passed.
Note that in MLIR, operation verifiers are not allowed to inspect sibling operations (since operations can be processed in parallel). So the type-match verifier should be implemented on the enclosing operation, likely in LLVMFuncOp.