@@ -1612,8 +1612,8 @@ ModuleImport::convertCallOperands(llvm::CallBase *callInst,
1612
1612
// / Checks if `callType` and `calleeType` are compatible and can be represented
1613
1613
// / in MLIR.
1614
1614
static LogicalResult
1615
- verifyFunctionTypeCompatibility (LLVMFunctionType callType,
1616
- LLVMFunctionType calleeType) {
1615
+ checkFunctionTypeCompatibility (LLVMFunctionType callType,
1616
+ LLVMFunctionType calleeType) {
1617
1617
if (callType.getReturnType () != calleeType.getReturnType ())
1618
1618
return failure ();
1619
1619
@@ -1639,7 +1639,9 @@ verifyFunctionTypeCompatibility(LLVMFunctionType callType,
1639
1639
}
1640
1640
1641
1641
FailureOr<LLVMFunctionType>
1642
- ModuleImport::convertFunctionType (llvm::CallBase *callInst) {
1642
+ ModuleImport::convertFunctionType (llvm::CallBase *callInst,
1643
+ bool &isIncompatibleCall) {
1644
+ isIncompatibleCall = false ;
1643
1645
auto castOrFailure = [](Type convertedType) -> FailureOr<LLVMFunctionType> {
1644
1646
auto funcTy = dyn_cast_or_null<LLVMFunctionType>(convertedType);
1645
1647
if (!funcTy)
@@ -1662,11 +1664,14 @@ ModuleImport::convertFunctionType(llvm::CallBase *callInst) {
1662
1664
if (failed (calleeType))
1663
1665
return failure ();
1664
1666
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 ;
1667
1671
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;
1670
1675
}
1671
1676
1672
1677
return calleeType;
@@ -1783,16 +1788,34 @@ LogicalResult ModuleImport::convertInstruction(llvm::Instruction *inst) {
1783
1788
/* operand_attrs=*/ nullptr )
1784
1789
.getOperation ();
1785
1790
}
1786
- FailureOr<LLVMFunctionType> funcTy = convertFunctionType (callInst);
1791
+ bool isIncompatibleCall;
1792
+ FailureOr<LLVMFunctionType> funcTy =
1793
+ convertFunctionType (callInst, isIncompatibleCall);
1787
1794
if (failed (funcTy))
1788
1795
return failure ();
1789
1796
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
+
1792
1812
if (failed (convertCallAttributes (callInst, callOp)))
1793
1813
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);
1796
1819
return callOp.getOperation ();
1797
1820
}();
1798
1821
@@ -1857,12 +1880,25 @@ LogicalResult ModuleImport::convertInstruction(llvm::Instruction *inst) {
1857
1880
unwindArgs)))
1858
1881
return failure ();
1859
1882
1860
- FailureOr<LLVMFunctionType> funcTy = convertFunctionType (invokeInst);
1883
+ bool isIncompatibleInvoke;
1884
+ FailureOr<LLVMFunctionType> funcTy =
1885
+ convertFunctionType (invokeInst, isIncompatibleInvoke);
1861
1886
if (failed (funcTy))
1862
1887
return failure ();
1863
1888
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
+ }
1866
1902
// Create the invoke operation. Normal destination block arguments will be
1867
1903
// added later on to handle the case in which the operation result is
1868
1904
// included in this list.
@@ -1873,8 +1909,10 @@ LogicalResult ModuleImport::convertInstruction(llvm::Instruction *inst) {
1873
1909
if (failed (convertInvokeAttributes (invokeInst, invokeOp)))
1874
1910
return failure ();
1875
1911
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);
1878
1916
1879
1917
if (!invokeInst->getType ()->isVoidTy ())
1880
1918
mapValue (inst, invokeOp.getResults ().front ());
0 commit comments