@@ -1721,8 +1721,8 @@ ModuleImport::convertCallOperands(llvm::CallBase *callInst,
1721
1721
// / Checks if `callType` and `calleeType` are compatible and can be represented
1722
1722
// / in MLIR.
1723
1723
static LogicalResult
1724
- verifyFunctionTypeCompatibility (LLVMFunctionType callType,
1725
- LLVMFunctionType calleeType) {
1724
+ checkFunctionTypeCompatibility (LLVMFunctionType callType,
1725
+ LLVMFunctionType calleeType) {
1726
1726
if (callType.getReturnType () != calleeType.getReturnType ())
1727
1727
return failure ();
1728
1728
@@ -1748,7 +1748,7 @@ verifyFunctionTypeCompatibility(LLVMFunctionType callType,
1748
1748
}
1749
1749
1750
1750
FailureOr<LLVMFunctionType>
1751
- ModuleImport::convertFunctionType (llvm::CallBase *callInst) {
1751
+ ModuleImport::convertFunctionType (llvm::CallBase *callInst, Value &castResult ) {
1752
1752
auto castOrFailure = [](Type convertedType) -> FailureOr<LLVMFunctionType> {
1753
1753
auto funcTy = dyn_cast_or_null<LLVMFunctionType>(convertedType);
1754
1754
if (!funcTy)
@@ -1771,11 +1771,17 @@ ModuleImport::convertFunctionType(llvm::CallBase *callInst) {
1771
1771
if (failed (calleeType))
1772
1772
return failure ();
1773
1773
1774
- // Compare the types to avoid constructing illegal call/invoke operations.
1775
- if (failed (verifyFunctionTypeCompatibility (*callType, *calleeType))) {
1774
+ // Compare the types, if they are not compatible, avoid illegal call/invoke
1775
+ // operations by casting to the callsite type and issuing an indirect call.
1776
+ // LLVM IR currently supports this usage.
1777
+ if (failed (checkFunctionTypeCompatibility (*callType, *calleeType))) {
1776
1778
Location loc = translateLoc (callInst->getDebugLoc ());
1777
- return emitError (loc) << " incompatible call and callee types: " << *callType
1778
- << " and " << *calleeType;
1779
+ FlatSymbolRefAttr calleeSym = convertCalleeName (callInst);
1780
+ castResult = builder.create <LLVM::AddressOfOp>(
1781
+ loc, LLVM::LLVMPointerType::get (context), calleeSym);
1782
+ emitWarning (loc) << " incompatible call and callee types: " << *callType
1783
+ << " and " << *calleeType;
1784
+ return callType;
1779
1785
}
1780
1786
1781
1787
return calleeType;
@@ -1892,16 +1898,29 @@ LogicalResult ModuleImport::convertInstruction(llvm::Instruction *inst) {
1892
1898
/* operand_attrs=*/ nullptr )
1893
1899
.getOperation ();
1894
1900
}
1895
- FailureOr<LLVMFunctionType> funcTy = convertFunctionType (callInst);
1901
+ Value castResult;
1902
+ FailureOr<LLVMFunctionType> funcTy =
1903
+ convertFunctionType (callInst, castResult);
1896
1904
if (failed (funcTy))
1897
1905
return failure ();
1898
1906
1899
- FlatSymbolRefAttr callee = convertCalleeName (callInst);
1900
- auto callOp = builder.create <CallOp>(loc, *funcTy, callee, *operands);
1907
+ FlatSymbolRefAttr callee = nullptr ;
1908
+ // If no cast is needed, use the original callee name. Otherwise patch
1909
+ // operands to include the indirect call target. Build indirect call by
1910
+ // passing using a nullptr `callee`.
1911
+ if (!castResult)
1912
+ callee = convertCalleeName (callInst);
1913
+ else
1914
+ operands->insert (operands->begin (), castResult);
1915
+ CallOp callOp = builder.create <CallOp>(loc, *funcTy, callee, *operands);
1916
+
1901
1917
if (failed (convertCallAttributes (callInst, callOp)))
1902
1918
return failure ();
1903
- // Handle parameter and result attributes.
1904
- convertParameterAttributes (callInst, callOp, builder);
1919
+
1920
+ // Handle parameter and result attributes. Don't bother if there's a
1921
+ // type mismatch.
1922
+ if (!castResult)
1923
+ convertParameterAttributes (callInst, callOp, builder);
1905
1924
return callOp.getOperation ();
1906
1925
}();
1907
1926
@@ -1966,11 +1985,20 @@ LogicalResult ModuleImport::convertInstruction(llvm::Instruction *inst) {
1966
1985
unwindArgs)))
1967
1986
return failure ();
1968
1987
1969
- FailureOr<LLVMFunctionType> funcTy = convertFunctionType (invokeInst);
1988
+ Value castResult;
1989
+ FailureOr<LLVMFunctionType> funcTy =
1990
+ convertFunctionType (invokeInst, castResult);
1970
1991
if (failed (funcTy))
1971
1992
return failure ();
1972
1993
1973
- FlatSymbolRefAttr calleeName = convertCalleeName (invokeInst);
1994
+ FlatSymbolRefAttr calleeName = nullptr ;
1995
+ // If no cast is needed, use the original callee name. Otherwise patch
1996
+ // operands to include the indirect call target. Build indirect call by
1997
+ // passing using a nullptr `callee`.
1998
+ if (!castResult)
1999
+ calleeName = convertCalleeName (invokeInst);
2000
+ else
2001
+ operands->insert (operands->begin (), castResult);
1974
2002
1975
2003
// Create the invoke operation. Normal destination block arguments will be
1976
2004
// added later on to handle the case in which the operation result is
@@ -1982,8 +2010,10 @@ LogicalResult ModuleImport::convertInstruction(llvm::Instruction *inst) {
1982
2010
if (failed (convertInvokeAttributes (invokeInst, invokeOp)))
1983
2011
return failure ();
1984
2012
1985
- // Handle parameter and result attributes.
1986
- convertParameterAttributes (invokeInst, invokeOp, builder);
2013
+ // Handle parameter and result attributes. Don't bother if there's a
2014
+ // type mismatch.
2015
+ if (!castResult)
2016
+ convertParameterAttributes (invokeInst, invokeOp, builder);
1987
2017
1988
2018
if (!invokeInst->getType ()->isVoidTy ())
1989
2019
mapValue (inst, invokeOp.getResults ().front ());
0 commit comments