@@ -1993,8 +1993,8 @@ ModuleImport::convertCallOperands(llvm::CallBase *callInst,
1993
1993
// / Checks if `callType` and `calleeType` are compatible and can be represented
1994
1994
// / in MLIR.
1995
1995
static LogicalResult
1996
- verifyFunctionTypeCompatibility (LLVMFunctionType callType,
1997
- LLVMFunctionType calleeType) {
1996
+ checkFunctionTypeCompatibility (LLVMFunctionType callType,
1997
+ LLVMFunctionType calleeType) {
1998
1998
if (callType.getReturnType () != calleeType.getReturnType ())
1999
1999
return failure ();
2000
2000
@@ -2020,7 +2020,9 @@ verifyFunctionTypeCompatibility(LLVMFunctionType callType,
2020
2020
}
2021
2021
2022
2022
FailureOr<LLVMFunctionType>
2023
- ModuleImport::convertFunctionType (llvm::CallBase *callInst) {
2023
+ ModuleImport::convertFunctionType (llvm::CallBase *callInst,
2024
+ bool &isIncompatibleCall) {
2025
+ isIncompatibleCall = false ;
2024
2026
auto castOrFailure = [](Type convertedType) -> FailureOr<LLVMFunctionType> {
2025
2027
auto funcTy = dyn_cast_or_null<LLVMFunctionType>(convertedType);
2026
2028
if (!funcTy)
@@ -2043,11 +2045,14 @@ ModuleImport::convertFunctionType(llvm::CallBase *callInst) {
2043
2045
if (failed (calleeType))
2044
2046
return failure ();
2045
2047
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 ;
2048
2052
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;
2051
2056
}
2052
2057
2053
2058
return calleeType;
@@ -2164,16 +2169,34 @@ LogicalResult ModuleImport::convertInstruction(llvm::Instruction *inst) {
2164
2169
/* operand_attrs=*/ nullptr )
2165
2170
.getOperation ();
2166
2171
}
2167
- FailureOr<LLVMFunctionType> funcTy = convertFunctionType (callInst);
2172
+ bool isIncompatibleCall;
2173
+ FailureOr<LLVMFunctionType> funcTy =
2174
+ convertFunctionType (callInst, isIncompatibleCall);
2168
2175
if (failed (funcTy))
2169
2176
return failure ();
2170
2177
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
+
2173
2193
if (failed (convertCallAttributes (callInst, callOp)))
2174
2194
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);
2177
2200
return callOp.getOperation ();
2178
2201
}();
2179
2202
@@ -2238,12 +2261,25 @@ LogicalResult ModuleImport::convertInstruction(llvm::Instruction *inst) {
2238
2261
unwindArgs)))
2239
2262
return failure ();
2240
2263
2241
- FailureOr<LLVMFunctionType> funcTy = convertFunctionType (invokeInst);
2264
+ bool isIncompatibleInvoke;
2265
+ FailureOr<LLVMFunctionType> funcTy =
2266
+ convertFunctionType (invokeInst, isIncompatibleInvoke);
2242
2267
if (failed (funcTy))
2243
2268
return failure ();
2244
2269
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
+ }
2247
2283
// Create the invoke operation. Normal destination block arguments will be
2248
2284
// added later on to handle the case in which the operation result is
2249
2285
// included in this list.
@@ -2254,8 +2290,10 @@ LogicalResult ModuleImport::convertInstruction(llvm::Instruction *inst) {
2254
2290
if (failed (convertInvokeAttributes (invokeInst, invokeOp)))
2255
2291
return failure ();
2256
2292
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);
2259
2297
2260
2298
if (!invokeInst->getType ()->isVoidTy ())
2261
2299
mapValue (inst, invokeOp.getResults ().front ());
0 commit comments