@@ -1993,8 +1993,8 @@ ModuleImport::convertCallOperands(llvm::CallBase *callInst,
19931993// / Checks if `callType` and `calleeType` are compatible and can be represented
19941994// / in MLIR.
19951995static LogicalResult
1996- verifyFunctionTypeCompatibility (LLVMFunctionType callType,
1997- LLVMFunctionType calleeType) {
1996+ checkFunctionTypeCompatibility (LLVMFunctionType callType,
1997+ LLVMFunctionType calleeType) {
19981998 if (callType.getReturnType () != calleeType.getReturnType ())
19991999 return failure ();
20002000
@@ -2020,7 +2020,9 @@ verifyFunctionTypeCompatibility(LLVMFunctionType callType,
20202020}
20212021
20222022FailureOr<LLVMFunctionType>
2023- ModuleImport::convertFunctionType (llvm::CallBase *callInst) {
2023+ ModuleImport::convertFunctionType (llvm::CallBase *callInst,
2024+ bool &isIncompatibleCall) {
2025+ isIncompatibleCall = false ;
20242026 auto castOrFailure = [](Type convertedType) -> FailureOr<LLVMFunctionType> {
20252027 auto funcTy = dyn_cast_or_null<LLVMFunctionType>(convertedType);
20262028 if (!funcTy)
@@ -2043,11 +2045,14 @@ ModuleImport::convertFunctionType(llvm::CallBase *callInst) {
20432045 if (failed (calleeType))
20442046 return failure ();
20452047
2046- // Compare the types to avoid constructing illegal call/invoke operations.
2047- if (failed (verifyFunctionTypeCompatibility (*callType, *calleeType))) {
2048+ // Compare the types and notify users via `isIncompatibleCall` if they are not
2049+ // compatible.
2050+ if (failed (checkFunctionTypeCompatibility (*callType, *calleeType))) {
2051+ isIncompatibleCall = true ;
20482052 Location loc = translateLoc (callInst->getDebugLoc ());
2049- return emitError (loc) << " incompatible call and callee types: " << *callType
2050- << " and " << *calleeType;
2053+ emitWarning (loc) << " incompatible call and callee types: " << *callType
2054+ << " and " << *calleeType;
2055+ return callType;
20512056 }
20522057
20532058 return calleeType;
@@ -2164,16 +2169,34 @@ LogicalResult ModuleImport::convertInstruction(llvm::Instruction *inst) {
21642169 /* operand_attrs=*/ nullptr )
21652170 .getOperation ();
21662171 }
2167- FailureOr<LLVMFunctionType> funcTy = convertFunctionType (callInst);
2172+ bool isIncompatibleCall;
2173+ FailureOr<LLVMFunctionType> funcTy =
2174+ convertFunctionType (callInst, isIncompatibleCall);
21682175 if (failed (funcTy))
21692176 return failure ();
21702177
2171- FlatSymbolRefAttr callee = convertCalleeName (callInst);
2172- auto callOp = builder.create <CallOp>(loc, *funcTy, callee, *operands);
2178+ FlatSymbolRefAttr callee = nullptr ;
2179+ if (isIncompatibleCall) {
2180+ // Use an indirect call (in order to represent valid and verifiable LLVM
2181+ // IR). Build the indirect call by passing an empty `callee` operand and
2182+ // insert into `operands` to include the indirect call target.
2183+ FlatSymbolRefAttr calleeSym = convertCalleeName (callInst);
2184+ Value indirectCallVal = builder.create <LLVM::AddressOfOp>(
2185+ loc, LLVM::LLVMPointerType::get (context), calleeSym);
2186+ operands->insert (operands->begin (), indirectCallVal);
2187+ } else {
2188+ // Regular direct call using callee name.
2189+ callee = convertCalleeName (callInst);
2190+ }
2191+ CallOp callOp = builder.create <CallOp>(loc, *funcTy, callee, *operands);
2192+
21732193 if (failed (convertCallAttributes (callInst, callOp)))
21742194 return failure ();
2175- // Handle parameter and result attributes.
2176- convertParameterAttributes (callInst, callOp, builder);
2195+
2196+ // Handle parameter and result attributes unless it's an incompatible
2197+ // call.
2198+ if (!isIncompatibleCall)
2199+ convertParameterAttributes (callInst, callOp, builder);
21772200 return callOp.getOperation ();
21782201 }();
21792202
@@ -2238,12 +2261,25 @@ LogicalResult ModuleImport::convertInstruction(llvm::Instruction *inst) {
22382261 unwindArgs)))
22392262 return failure ();
22402263
2241- FailureOr<LLVMFunctionType> funcTy = convertFunctionType (invokeInst);
2264+ bool isIncompatibleInvoke;
2265+ FailureOr<LLVMFunctionType> funcTy =
2266+ convertFunctionType (invokeInst, isIncompatibleInvoke);
22422267 if (failed (funcTy))
22432268 return failure ();
22442269
2245- FlatSymbolRefAttr calleeName = convertCalleeName (invokeInst);
2246-
2270+ FlatSymbolRefAttr calleeName = nullptr ;
2271+ if (isIncompatibleInvoke) {
2272+ // Use an indirect invoke (in order to represent valid and verifiable LLVM
2273+ // IR). Build the indirect invoke by passing an empty `callee` operand and
2274+ // insert into `operands` to include the indirect invoke target.
2275+ FlatSymbolRefAttr calleeSym = convertCalleeName (invokeInst);
2276+ Value indirectInvokeVal = builder.create <LLVM::AddressOfOp>(
2277+ loc, LLVM::LLVMPointerType::get (context), calleeSym);
2278+ operands->insert (operands->begin (), indirectInvokeVal);
2279+ } else {
2280+ // Regular direct invoke using callee name.
2281+ calleeName = convertCalleeName (invokeInst);
2282+ }
22472283 // Create the invoke operation. Normal destination block arguments will be
22482284 // added later on to handle the case in which the operation result is
22492285 // included in this list.
@@ -2254,8 +2290,10 @@ LogicalResult ModuleImport::convertInstruction(llvm::Instruction *inst) {
22542290 if (failed (convertInvokeAttributes (invokeInst, invokeOp)))
22552291 return failure ();
22562292
2257- // Handle parameter and result attributes.
2258- convertParameterAttributes (invokeInst, invokeOp, builder);
2293+ // Handle parameter and result attributes unless it's an incompatible
2294+ // invoke.
2295+ if (!isIncompatibleInvoke)
2296+ convertParameterAttributes (invokeInst, invokeOp, builder);
22592297
22602298 if (!invokeInst->getType ()->isVoidTy ())
22612299 mapValue (inst, invokeOp.getResults ().front ());
0 commit comments