diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td --- a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td +++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td @@ -426,11 +426,7 @@ result.addAttributes(attributes); result.addOperands(operands); }]>]; - let verifier = [{ - if (getNumResults() > 1) - return emitOpError("must have 0 or 1 result"); - return success(); - }]; + let verifier = [{ return ::verify(*this); }]; let parser = [{ return parseCallOp(parser, result); }]; let printer = [{ printCallOp(p, *this); }]; } diff --git a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp --- a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp +++ b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp @@ -638,6 +638,17 @@ return success(); } +static LogicalResult verify(CallOp op) { + if (op.getNumResults() > 1) + return op.emitOpError("must have 0 or 1 result"); + + if (op.callee().hasValue() && + !SymbolTable::lookupNearestSymbolFrom(op, op.callee().getValue())) + return op.emitOpError("calls an undeclared function"); + + return success(); +} + //===----------------------------------------------------------------------===// // Printing/parsing for LLVM::ExtractElementOp. //===----------------------------------------------------------------------===// diff --git a/mlir/test/Dialect/LLVMIR/invalid.mlir b/mlir/test/Dialect/LLVMIR/invalid.mlir --- a/mlir/test/Dialect/LLVMIR/invalid.mlir +++ b/mlir/test/Dialect/LLVMIR/invalid.mlir @@ -118,6 +118,13 @@ // ----- +func @call_undeclared() { + // expected-error@+1 {{calls an undeclared function}} + llvm.call @undeclared() : () -> () +} + +// ----- + func @call_non_function_type(%callee : !llvm.func, %arg : !llvm.i8) { // expected-error@+1 {{expected function type}} llvm.call %callee(%arg) : !llvm.func