@@ -1612,8 +1612,8 @@ ModuleImport::convertCallOperands(llvm::CallBase *callInst,
16121612// / Checks if `callType` and `calleeType` are compatible and can be represented
16131613// / in MLIR.
16141614static LogicalResult
1615- verifyFunctionTypeCompatibility (LLVMFunctionType callType,
1616- LLVMFunctionType calleeType) {
1615+ checkFunctionTypeCompatibility (LLVMFunctionType callType,
1616+ LLVMFunctionType calleeType) {
16171617 if (callType.getReturnType () != calleeType.getReturnType ())
16181618 return failure ();
16191619
@@ -1639,7 +1639,9 @@ verifyFunctionTypeCompatibility(LLVMFunctionType callType,
16391639}
16401640
16411641FailureOr<LLVMFunctionType>
1642- ModuleImport::convertFunctionType (llvm::CallBase *callInst) {
1642+ ModuleImport::convertFunctionType (llvm::CallBase *callInst,
1643+ bool &isIncompatibleCall) {
1644+ isIncompatibleCall = false ;
16431645 auto castOrFailure = [](Type convertedType) -> FailureOr<LLVMFunctionType> {
16441646 auto funcTy = dyn_cast_or_null<LLVMFunctionType>(convertedType);
16451647 if (!funcTy)
@@ -1662,11 +1664,14 @@ ModuleImport::convertFunctionType(llvm::CallBase *callInst) {
16621664 if (failed (calleeType))
16631665 return failure ();
16641666
1665- // Compare the types to avoid constructing illegal call/invoke operations.
1666- if (failed (verifyFunctionTypeCompatibility (*callType, *calleeType))) {
1667+ // Compare the types and notify users via `isIncompatibleCall` if they are not
1668+ // compatible.
1669+ if (failed (checkFunctionTypeCompatibility (*callType, *calleeType))) {
1670+ isIncompatibleCall = true ;
16671671 Location loc = translateLoc (callInst->getDebugLoc ());
1668- return emitError (loc) << " incompatible call and callee types: " << *callType
1669- << " and " << *calleeType;
1672+ emitWarning (loc) << " incompatible call and callee types: " << *callType
1673+ << " and " << *calleeType;
1674+ return callType;
16701675 }
16711676
16721677 return calleeType;
@@ -1783,16 +1788,34 @@ LogicalResult ModuleImport::convertInstruction(llvm::Instruction *inst) {
17831788 /* operand_attrs=*/ nullptr )
17841789 .getOperation ();
17851790 }
1786- FailureOr<LLVMFunctionType> funcTy = convertFunctionType (callInst);
1791+ bool isIncompatibleCall;
1792+ FailureOr<LLVMFunctionType> funcTy =
1793+ convertFunctionType (callInst, isIncompatibleCall);
17871794 if (failed (funcTy))
17881795 return failure ();
17891796
1790- FlatSymbolRefAttr callee = convertCalleeName (callInst);
1791- auto callOp = builder.create <CallOp>(loc, *funcTy, callee, *operands);
1797+ FlatSymbolRefAttr callee = nullptr ;
1798+ if (isIncompatibleCall) {
1799+ // Use an indirect call (in order to represent valid and verifiable LLVM
1800+ // IR). Build the indirect call by passing an empty `callee` operand and
1801+ // insert into `operands` to include the indirect call target.
1802+ FlatSymbolRefAttr calleeSym = convertCalleeName (callInst);
1803+ Value indirectCallVal = builder.create <LLVM::AddressOfOp>(
1804+ loc, LLVM::LLVMPointerType::get (context), calleeSym);
1805+ operands->insert (operands->begin (), indirectCallVal);
1806+ } else {
1807+ // Regular direct call using callee name.
1808+ callee = convertCalleeName (callInst);
1809+ }
1810+ CallOp callOp = builder.create <CallOp>(loc, *funcTy, callee, *operands);
1811+
17921812 if (failed (convertCallAttributes (callInst, callOp)))
17931813 return failure ();
1794- // Handle parameter and result attributes.
1795- convertParameterAttributes (callInst, callOp, builder);
1814+
1815+ // Handle parameter and result attributes unless it's an incompatible
1816+ // call.
1817+ if (!isIncompatibleCall)
1818+ convertParameterAttributes (callInst, callOp, builder);
17961819 return callOp.getOperation ();
17971820 }();
17981821
@@ -1857,12 +1880,25 @@ LogicalResult ModuleImport::convertInstruction(llvm::Instruction *inst) {
18571880 unwindArgs)))
18581881 return failure ();
18591882
1860- FailureOr<LLVMFunctionType> funcTy = convertFunctionType (invokeInst);
1883+ bool isIncompatibleInvoke;
1884+ FailureOr<LLVMFunctionType> funcTy =
1885+ convertFunctionType (invokeInst, isIncompatibleInvoke);
18611886 if (failed (funcTy))
18621887 return failure ();
18631888
1864- FlatSymbolRefAttr calleeName = convertCalleeName (invokeInst);
1865-
1889+ FlatSymbolRefAttr calleeName = nullptr ;
1890+ if (isIncompatibleInvoke) {
1891+ // Use an indirect invoke (in order to represent valid and verifiable LLVM
1892+ // IR). Build the indirect invoke by passing an empty `callee` operand and
1893+ // insert into `operands` to include the indirect invoke target.
1894+ FlatSymbolRefAttr calleeSym = convertCalleeName (invokeInst);
1895+ Value indirectInvokeVal = builder.create <LLVM::AddressOfOp>(
1896+ loc, LLVM::LLVMPointerType::get (context), calleeSym);
1897+ operands->insert (operands->begin (), indirectInvokeVal);
1898+ } else {
1899+ // Regular direct invoke using callee name.
1900+ calleeName = convertCalleeName (invokeInst);
1901+ }
18661902 // Create the invoke operation. Normal destination block arguments will be
18671903 // added later on to handle the case in which the operation result is
18681904 // included in this list.
@@ -1873,8 +1909,10 @@ LogicalResult ModuleImport::convertInstruction(llvm::Instruction *inst) {
18731909 if (failed (convertInvokeAttributes (invokeInst, invokeOp)))
18741910 return failure ();
18751911
1876- // Handle parameter and result attributes.
1877- convertParameterAttributes (invokeInst, invokeOp, builder);
1912+ // Handle parameter and result attributes unless it's an incompatible
1913+ // invoke.
1914+ if (!isIncompatibleInvoke)
1915+ convertParameterAttributes (invokeInst, invokeOp, builder);
18781916
18791917 if (!invokeInst->getType ()->isVoidTy ())
18801918 mapValue (inst, invokeOp.getResults ().front ());
0 commit comments