Index: llvm/lib/AsmParser/LLParser.cpp =================================================================== --- llvm/lib/AsmParser/LLParser.cpp +++ llvm/lib/AsmParser/LLParser.cpp @@ -1470,15 +1470,26 @@ Value *LLParser::checkValidVariableType(LocTy Loc, const Twine &Name, Type *Ty, Value *Val, bool IsCall) { - if (Val->getType() == Ty) + auto CheckType = [&](Type *Ty) { + Type *ValTy = Val->getType(); + if (ValTy == Ty) + return true; + // For calls, we also allow opaque pointers. + if (IsCall && ValTy == PointerType::get(Ty->getContext(), + Ty->getPointerAddressSpace())) + return true; + return false; + }; + if (CheckType(Ty)) return Val; + // For calls we also accept variables in the program address space. Type *SuggestedTy = Ty; if (IsCall && isa(Ty)) { Type *TyInProgAS = cast(Ty)->getElementType()->getPointerTo( M->getDataLayout().getProgramAddressSpace()); SuggestedTy = TyInProgAS; - if (Val->getType() == TyInProgAS) + if (CheckType(TyInProgAS)) return Val; } if (Ty->isLabelTy()) Index: llvm/lib/Bitcode/Reader/BitcodeReader.cpp =================================================================== --- llvm/lib/Bitcode/Reader/BitcodeReader.cpp +++ 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) Index: llvm/lib/Bitcode/Writer/ValueEnumerator.cpp =================================================================== --- llvm/lib/Bitcode/Writer/ValueEnumerator.cpp +++ 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(); Index: llvm/lib/IR/Verifier.cpp =================================================================== --- llvm/lib/IR/Verifier.cpp +++ 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(); Index: llvm/test/Assembler/opaque-ptr.ll =================================================================== --- llvm/test/Assembler/opaque-ptr.ll +++ 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 +}