diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp --- a/llvm/lib/AsmParser/LLParser.cpp +++ b/llvm/lib/AsmParser/LLParser.cpp @@ -1469,8 +1469,13 @@ } Value *LLParser::checkValidVariableType(LocTy Loc, const Twine &Name, Type *Ty, - Value *Val, bool /* IsCall */) { - if (Val->getType() == Ty) + Value *Val, bool IsCall) { + Type *ValTy = Val->getType(); + if (ValTy == Ty) + return Val; + // For calls, we also allow opaque pointers. + if (IsCall && ValTy == PointerType::get(Ty->getContext(), + Ty->getPointerAddressSpace())) return Val; if (Ty->isLabelTy()) error(Loc, "'" + Name + "' is not a basic block"); diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp --- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp @@ -5266,7 +5266,7 @@ cast(Callee->getType())->getElementType()); if (!FTy) return error("Callee is not of pointer to function type"); - } else if (cast(Callee->getType())->getElementType() != FTy) + } else if (!OpTy->isOpaqueOrPointeeTypeMatches(FTy)) return error("Explicit call type does not match pointee type of " "callee operand"); if (Record.size() < FTy->getNumParams() + OpNum) diff --git a/llvm/lib/Bitcode/Writer/ValueEnumerator.cpp b/llvm/lib/Bitcode/Writer/ValueEnumerator.cpp --- a/llvm/lib/Bitcode/Writer/ValueEnumerator.cpp +++ b/llvm/lib/Bitcode/Writer/ValueEnumerator.cpp @@ -467,8 +467,10 @@ if (auto *GEP = dyn_cast(&I)) EnumerateType(GEP->getSourceElementType()); EnumerateType(I.getType()); - if (const auto *Call = dyn_cast(&I)) + if (const auto *Call = dyn_cast(&I)) { EnumerateAttributes(Call->getAttributes()); + EnumerateType(Call->getFunctionType()); + } // Enumerate metadata attached with this instruction. MDs.clear(); diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp --- a/llvm/lib/IR/Verifier.cpp +++ b/llvm/lib/IR/Verifier.cpp @@ -3124,10 +3124,7 @@ "Called function must be a pointer!", Call); PointerType *FPTy = cast(Call.getCalledOperand()->getType()); - Assert(FPTy->getElementType()->isFunctionTy(), - "Called function is not pointer to function type!", Call); - - Assert(FPTy->getElementType() == Call.getFunctionType(), + Assert(FPTy->isOpaqueOrPointeeTypeMatches(Call.getFunctionType()), "Called function is not the same type as the call!", Call); FunctionType *FTy = Call.getFunctionType(); diff --git a/llvm/test/Assembler/opaque-ptr.ll b/llvm/test/Assembler/opaque-ptr.ll --- a/llvm/test/Assembler/opaque-ptr.ll +++ b/llvm/test/Assembler/opaque-ptr.ll @@ -98,3 +98,19 @@ %b = atomicrmw add ptr %a, i32 %i acquire ret void } + +; CHECK: define void @call(ptr %p) +; CHECK: call void %p() +; CHECK: ret void +define void @call(ptr %p) { + call void %p() + ret void +} + +; CHECK: define void @call_arg(ptr %p, i32 %a) +; CHECK: call void %p(i32 %a) +; CHECK: ret void +define void @call_arg(ptr %p, i32 %a) { + call void %p(i32 %a) + ret void +}