@@ -1749,8 +1749,8 @@ checkFunctionTypeCompatibility(LLVMFunctionType callType,
17491749
17501750FailureOr<LLVMFunctionType>
17511751ModuleImport::convertFunctionType (llvm::CallBase *callInst,
1752- Value &indirectCallVal ) {
1753- indirectCallVal = nullptr ;
1752+ bool &isIncompatibleCall ) {
1753+ isIncompatibleCall = false ;
17541754 auto castOrFailure = [](Type convertedType) -> FailureOr<LLVMFunctionType> {
17551755 auto funcTy = dyn_cast_or_null<LLVMFunctionType>(convertedType);
17561756 if (!funcTy)
@@ -1773,14 +1773,11 @@ ModuleImport::convertFunctionType(llvm::CallBase *callInst,
17731773 if (failed (calleeType))
17741774 return failure ();
17751775
1776- // Compare the types, if they are not compatible, avoid illegal call/invoke
1777- // operations by issuing an indirect call. Note that LLVM IR currently
1778- // supports this usage.
1776+ // Compare the types and notify users via `isIncompatibleCall` if they are not
1777+ // compatible.
17791778 if (failed (checkFunctionTypeCompatibility (*callType, *calleeType))) {
1779+ isIncompatibleCall = true ;
17801780 Location loc = translateLoc (callInst->getDebugLoc ());
1781- FlatSymbolRefAttr calleeSym = convertCalleeName (callInst);
1782- indirectCallVal = builder.create <LLVM::AddressOfOp>(
1783- loc, LLVM::LLVMPointerType::get (context), calleeSym);
17841781 emitWarning (loc) << " incompatible call and callee types: " << *callType
17851782 << " and " << *calleeType;
17861783 return callType;
@@ -1900,27 +1897,34 @@ LogicalResult ModuleImport::convertInstruction(llvm::Instruction *inst) {
19001897 /* operand_attrs=*/ nullptr )
19011898 .getOperation ();
19021899 }
1903- Value indirectCallVal ;
1900+ bool isIncompatibleCall ;
19041901 FailureOr<LLVMFunctionType> funcTy =
1905- convertFunctionType (callInst, indirectCallVal );
1902+ convertFunctionType (callInst, isIncompatibleCall );
19061903 if (failed (funcTy))
19071904 return failure ();
19081905
19091906 FlatSymbolRefAttr callee = nullptr ;
1910- // If `indirectCallVal` is available emit an indirect call, otherwise use
1911- // the callee name. Build an indirect call by passing an empty `callee`
1912- // operand and insert into `operands` to include the indirect call target.
1913- if (indirectCallVal)
1907+ if (isIncompatibleCall) {
1908+ // Use an indirect call (in order to represent valid and verifiable LLVM
1909+ // IR). Build the indirect call by passing an empty `callee` operand and
1910+ // insert into `operands` to include the indirect call target.
1911+ FlatSymbolRefAttr calleeSym = convertCalleeName (callInst);
1912+ Value indirectCallVal = builder.create <LLVM::AddressOfOp>(
1913+ translateLoc (callInst->getDebugLoc ()),
1914+ LLVM::LLVMPointerType::get (context), calleeSym);
19141915 operands->insert (operands->begin (), indirectCallVal);
1915- else
1916+ } else {
1917+ // Regular direct call using callee name.
19161918 callee = convertCalleeName (callInst);
1919+ }
19171920 CallOp callOp = builder.create <CallOp>(loc, *funcTy, callee, *operands);
19181921
19191922 if (failed (convertCallAttributes (callInst, callOp)))
19201923 return failure ();
19211924
1922- // Handle parameter and result attributes unless it's an indirect call.
1923- if (!indirectCallVal)
1925+ // Handle parameter and result attributes unless it's an incompatible
1926+ // call.
1927+ if (!isIncompatibleCall)
19241928 convertParameterAttributes (callInst, callOp, builder);
19251929 return callOp.getOperation ();
19261930 }();
@@ -1986,21 +1990,26 @@ LogicalResult ModuleImport::convertInstruction(llvm::Instruction *inst) {
19861990 unwindArgs)))
19871991 return failure ();
19881992
1989- Value indirectCallVal ;
1993+ bool isIncompatibleInvoke ;
19901994 FailureOr<LLVMFunctionType> funcTy =
1991- convertFunctionType (invokeInst, indirectCallVal );
1995+ convertFunctionType (invokeInst, isIncompatibleInvoke );
19921996 if (failed (funcTy))
19931997 return failure ();
19941998
19951999 FlatSymbolRefAttr calleeName = nullptr ;
1996- // If `indirectCallVal` is available emit an indirect call, otherwise use
1997- // the callee name. Build an indirect call by passing an empty `callee`
1998- // operand and insert into `operands` to include the indirect call target.
1999- if (!indirectCallVal)
2000+ if (isIncompatibleInvoke) {
2001+ // Use an indirect invoke (in order to represent valid and verifiable LLVM
2002+ // IR). Build the indirect invoke by passing an empty `callee` operand and
2003+ // insert into `operands` to include the indirect invoke target.
2004+ FlatSymbolRefAttr calleeSym = convertCalleeName (invokeInst);
2005+ Value indirectInvokeVal = builder.create <LLVM::AddressOfOp>(
2006+ translateLoc (invokeInst->getDebugLoc ()),
2007+ LLVM::LLVMPointerType::get (context), calleeSym);
2008+ operands->insert (operands->begin (), indirectInvokeVal);
2009+ } else {
2010+ // Regular direct invoke using callee name.
20002011 calleeName = convertCalleeName (invokeInst);
2001- else
2002- operands->insert (operands->begin (), indirectCallVal);
2003-
2012+ }
20042013 // Create the invoke operation. Normal destination block arguments will be
20052014 // added later on to handle the case in which the operation result is
20062015 // included in this list.
@@ -2011,8 +2020,9 @@ LogicalResult ModuleImport::convertInstruction(llvm::Instruction *inst) {
20112020 if (failed (convertInvokeAttributes (invokeInst, invokeOp)))
20122021 return failure ();
20132022
2014- // Handle parameter and result attributes unless it's an indirect call.
2015- if (!indirectCallVal)
2023+ // Handle parameter and result attributes unless it's an incompatible
2024+ // invoke.
2025+ if (!isIncompatibleInvoke)
20162026 convertParameterAttributes (invokeInst, invokeOp, builder);
20172027
20182028 if (!invokeInst->getType ()->isVoidTy ())
0 commit comments