@@ -1668,8 +1668,8 @@ ModuleImport::convertCallOperands(llvm::CallBase *callInst,
1668
1668
// / Checks if `callType` and `calleeType` are compatible and can be represented
1669
1669
// / in MLIR.
1670
1670
static LogicalResult
1671
- verifyFunctionTypeCompatibility (LLVMFunctionType callType,
1672
- LLVMFunctionType calleeType) {
1671
+ checkFunctionTypeCompatibility (LLVMFunctionType callType,
1672
+ LLVMFunctionType calleeType) {
1673
1673
if (callType.getReturnType () != calleeType.getReturnType ())
1674
1674
return failure ();
1675
1675
@@ -1695,7 +1695,7 @@ verifyFunctionTypeCompatibility(LLVMFunctionType callType,
1695
1695
}
1696
1696
1697
1697
FailureOr<LLVMFunctionType>
1698
- ModuleImport::convertFunctionType (llvm::CallBase *callInst) {
1698
+ ModuleImport::convertFunctionType (llvm::CallBase *callInst, Value &castResult ) {
1699
1699
auto castOrFailure = [](Type convertedType) -> FailureOr<LLVMFunctionType> {
1700
1700
auto funcTy = dyn_cast_or_null<LLVMFunctionType>(convertedType);
1701
1701
if (!funcTy)
@@ -1718,11 +1718,17 @@ ModuleImport::convertFunctionType(llvm::CallBase *callInst) {
1718
1718
if (failed (calleeType))
1719
1719
return failure ();
1720
1720
1721
- // Compare the types to avoid constructing illegal call/invoke operations.
1722
- if (failed (verifyFunctionTypeCompatibility (*callType, *calleeType))) {
1721
+ // Compare the types, if they are not compatible, avoid illegal call/invoke
1722
+ // operations by casting to the callsite type and issuing an indirect call.
1723
+ // LLVM IR currently supports this usage.
1724
+ if (failed (checkFunctionTypeCompatibility (*callType, *calleeType))) {
1723
1725
Location loc = translateLoc (callInst->getDebugLoc ());
1724
- return emitError (loc) << " incompatible call and callee types: " << *callType
1725
- << " and " << *calleeType;
1726
+ FlatSymbolRefAttr calleeSym = convertCalleeName (callInst);
1727
+ castResult = builder.create <LLVM::AddressOfOp>(
1728
+ loc, LLVM::LLVMPointerType::get (context), calleeSym);
1729
+ emitWarning (loc) << " incompatible call and callee types: " << *callType
1730
+ << " and " << *calleeType;
1731
+ return callType;
1726
1732
}
1727
1733
1728
1734
return calleeType;
@@ -1839,16 +1845,29 @@ LogicalResult ModuleImport::convertInstruction(llvm::Instruction *inst) {
1839
1845
/* operand_attrs=*/ nullptr )
1840
1846
.getOperation ();
1841
1847
}
1842
- FailureOr<LLVMFunctionType> funcTy = convertFunctionType (callInst);
1848
+ Value castResult;
1849
+ FailureOr<LLVMFunctionType> funcTy =
1850
+ convertFunctionType (callInst, castResult);
1843
1851
if (failed (funcTy))
1844
1852
return failure ();
1845
1853
1846
- FlatSymbolRefAttr callee = convertCalleeName (callInst);
1847
- auto callOp = builder.create <CallOp>(loc, *funcTy, callee, *operands);
1854
+ FlatSymbolRefAttr callee = nullptr ;
1855
+ // If no cast is needed, use the original callee name. Otherwise patch
1856
+ // operands to include the indirect call target. Build indirect call by
1857
+ // passing using a nullptr `callee`.
1858
+ if (!castResult)
1859
+ callee = convertCalleeName (callInst);
1860
+ else
1861
+ operands->insert (operands->begin (), castResult);
1862
+ CallOp callOp = builder.create <CallOp>(loc, *funcTy, callee, *operands);
1863
+
1848
1864
if (failed (convertCallAttributes (callInst, callOp)))
1849
1865
return failure ();
1850
- // Handle parameter and result attributes.
1851
- convertParameterAttributes (callInst, callOp, builder);
1866
+
1867
+ // Handle parameter and result attributes. Don't bother if there's a
1868
+ // type mismatch.
1869
+ if (!castResult)
1870
+ convertParameterAttributes (callInst, callOp, builder);
1852
1871
return callOp.getOperation ();
1853
1872
}();
1854
1873
@@ -1913,11 +1932,20 @@ LogicalResult ModuleImport::convertInstruction(llvm::Instruction *inst) {
1913
1932
unwindArgs)))
1914
1933
return failure ();
1915
1934
1916
- FailureOr<LLVMFunctionType> funcTy = convertFunctionType (invokeInst);
1935
+ Value castResult;
1936
+ FailureOr<LLVMFunctionType> funcTy =
1937
+ convertFunctionType (invokeInst, castResult);
1917
1938
if (failed (funcTy))
1918
1939
return failure ();
1919
1940
1920
- FlatSymbolRefAttr calleeName = convertCalleeName (invokeInst);
1941
+ FlatSymbolRefAttr calleeName = nullptr ;
1942
+ // If no cast is needed, use the original callee name. Otherwise patch
1943
+ // operands to include the indirect call target. Build indirect call by
1944
+ // passing using a nullptr `callee`.
1945
+ if (!castResult)
1946
+ calleeName = convertCalleeName (invokeInst);
1947
+ else
1948
+ operands->insert (operands->begin (), castResult);
1921
1949
1922
1950
// Create the invoke operation. Normal destination block arguments will be
1923
1951
// added later on to handle the case in which the operation result is
@@ -1929,8 +1957,10 @@ LogicalResult ModuleImport::convertInstruction(llvm::Instruction *inst) {
1929
1957
if (failed (convertInvokeAttributes (invokeInst, invokeOp)))
1930
1958
return failure ();
1931
1959
1932
- // Handle parameter and result attributes.
1933
- convertParameterAttributes (invokeInst, invokeOp, builder);
1960
+ // Handle parameter and result attributes. Don't bother if there's a
1961
+ // type mismatch.
1962
+ if (!castResult)
1963
+ convertParameterAttributes (invokeInst, invokeOp, builder);
1934
1964
1935
1965
if (!invokeInst->getType ()->isVoidTy ())
1936
1966
mapValue (inst, invokeOp.getResults ().front ());
0 commit comments