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 @@ -7478,7 +7478,8 @@ Ordering == AtomicOrdering::AcquireRelease) return error(Loc, "atomic load cannot use Release ordering"); - if (Ty != cast(Val->getType())->getElementType()) { + if (!cast(Val->getType())->isOpaque() && + Ty != cast(Val->getType())->getElementType()) { return error( ExplicitTypeLoc, typeComparisonErrorMessage( @@ -7529,7 +7530,8 @@ return error(PtrLoc, "store operand must be a pointer"); if (!Val->getType()->isFirstClassType()) return error(Loc, "store operand must be a first class value"); - if (cast(Ptr->getType())->getElementType() != Val->getType()) + if (!cast(Ptr->getType())->isOpaque() && + cast(Ptr->getType())->getElementType() != Val->getType()) return error(Loc, "stored value and pointer type do not match"); if (isAtomic && !Alignment) return error(Loc, "atomic store must have explicit non-zero alignment"); diff --git a/llvm/lib/IR/Instructions.cpp b/llvm/lib/IR/Instructions.cpp --- a/llvm/lib/IR/Instructions.cpp +++ b/llvm/lib/IR/Instructions.cpp @@ -1436,7 +1436,8 @@ Align Align, AtomicOrdering Order, SyncScope::ID SSID, Instruction *InsertBef) : UnaryInstruction(Ty, Load, Ptr, InsertBef) { - assert(Ty == cast(Ptr->getType())->getElementType()); + assert(cast(Ptr->getType())->isOpaque() || + Ty == cast(Ptr->getType())->getElementType()); setVolatile(isVolatile); setAlignment(Align); setAtomic(Order, SSID); @@ -1448,7 +1449,8 @@ Align Align, AtomicOrdering Order, SyncScope::ID SSID, BasicBlock *InsertAE) : UnaryInstruction(Ty, Load, Ptr, InsertAE) { - assert(Ty == cast(Ptr->getType())->getElementType()); + assert(cast(Ptr->getType())->isOpaque() || + Ty == cast(Ptr->getType())->getElementType()); setVolatile(isVolatile); setAlignment(Align); setAtomic(Order, SSID); @@ -1464,9 +1466,11 @@ assert(getOperand(0) && getOperand(1) && "Both operands must be non-null!"); assert(getOperand(1)->getType()->isPointerTy() && "Ptr must have pointer type!"); - assert(getOperand(0)->getType() == - cast(getOperand(1)->getType())->getElementType() - && "Ptr must be a pointer to Val type!"); + assert( + cast(getOperand(1)->getType())->isOpaque() || + getOperand(0)->getType() == + cast(getOperand(1)->getType())->getElementType() && + "Ptr must be a pointer to Val type!"); assert(!(isAtomic() && getAlignment() == 0) && "Alignment required for atomic store"); } 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 @@ -3745,9 +3745,11 @@ void Verifier::visitStoreInst(StoreInst &SI) { PointerType *PTy = dyn_cast(SI.getOperand(1)->getType()); Assert(PTy, "Store operand must be a pointer.", &SI); - Type *ElTy = PTy->getElementType(); - Assert(ElTy == SI.getOperand(0)->getType(), - "Stored value type does not match pointer operand type!", &SI, ElTy); + Type *ElTy = SI.getOperand(0)->getType(); + if (!PTy->isOpaque()) { + Assert(ElTy == PTy->getElementType(), + "Stored value type does not match pointer operand type!", &SI, ElTy); + } Assert(SI.getAlignment() <= Value::MaximumAlignment, "huge alignment values are unsupported", &SI); Assert(ElTy->isSized(), "storing unsized types is not allowed", &SI); 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 @@ -24,3 +24,19 @@ %b = addrspacecast ptr addrspace(0) %a to ptr addrspace(2) ret ptr addrspace(2) %b } + +; CHECK: define i32 @load(ptr %a) +; CHECK: %i = load i32, ptr %a +; CHECK: ret i32 %i +define i32 @load(ptr %a) { + %i = load i32, ptr %a + ret i32 %i +} + +; CHECK: define void @store(ptr %a, i32 %i) +; CHECK: store i32 %i, ptr %a +; CHECK: ret void +define void @store(ptr %a, i32 %i) { + store i32 %i, ptr %a + ret void +} diff --git a/llvm/test/Verifier/opaque-ptr.ll b/llvm/test/Verifier/opaque-ptr.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Verifier/opaque-ptr.ll @@ -0,0 +1,13 @@ +; RUN: opt -passes=verify -S < %s | FileCheck %s + +; CHECK: @load +define i32 @load(ptr %a) { + %i = load i32, ptr %a + ret i32 %i +} + +; CHECK: @store +define void @store(ptr %a, i32 %i) { + store i32 %i, ptr %a + ret void +}