[OpaquePtr] Make loads and stores work with opaque pointers
Don't check that types match when the pointer operand is an opaque pointer. I would separate the Assembler and Verifier changes, but verify-uselistorder in the Assembler test ends up running the verifier. Reviewed By: dblaikie Differential Revision: https://reviews.llvm.org/D102450
This commit is contained in:
parent
832f7af283
commit
6013d84392
|
@ -676,6 +676,14 @@ public:
|
|||
/// Return the address space of the Pointer type.
|
||||
inline unsigned getAddressSpace() const { return getSubclassData(); }
|
||||
|
||||
/// Return true if either this is an opaque pointer type or if this pointee
|
||||
/// type matches Ty. Primarily used for checking if an instruction's pointer
|
||||
/// operands are valid types. Will be useless after non-opaque pointers are
|
||||
/// removed.
|
||||
bool isOpaqueOrPointeeTypeMatches(Type *Ty) {
|
||||
return isOpaque() || PointeeTy == Ty;
|
||||
}
|
||||
|
||||
/// Implement support type inquiry through isa, cast, and dyn_cast.
|
||||
static bool classof(const Type *T) {
|
||||
return T->getTypeID() == PointerTyID;
|
||||
|
|
|
@ -7483,7 +7483,7 @@ int LLParser::parseLoad(Instruction *&Inst, PerFunctionState &PFS) {
|
|||
Ordering == AtomicOrdering::AcquireRelease)
|
||||
return error(Loc, "atomic load cannot use Release ordering");
|
||||
|
||||
if (Ty != cast<PointerType>(Val->getType())->getElementType()) {
|
||||
if (!cast<PointerType>(Val->getType())->isOpaqueOrPointeeTypeMatches(Ty)) {
|
||||
return error(
|
||||
ExplicitTypeLoc,
|
||||
typeComparisonErrorMessage(
|
||||
|
@ -7534,7 +7534,8 @@ int LLParser::parseStore(Instruction *&Inst, PerFunctionState &PFS) {
|
|||
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<PointerType>(Ptr->getType())->getElementType() != Val->getType())
|
||||
if (!cast<PointerType>(Ptr->getType())
|
||||
->isOpaqueOrPointeeTypeMatches(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");
|
||||
|
|
|
@ -3844,12 +3844,11 @@ Error BitcodeReader::parseBitcodeInto(Module *M, bool ShouldLazyLoadMetadata,
|
|||
Error BitcodeReader::typeCheckLoadStoreInst(Type *ValType, Type *PtrType) {
|
||||
if (!isa<PointerType>(PtrType))
|
||||
return error("Load/Store operand is not a pointer type");
|
||||
Type *ElemType = cast<PointerType>(PtrType)->getElementType();
|
||||
|
||||
if (ValType && ValType != ElemType)
|
||||
if (!cast<PointerType>(PtrType)->isOpaqueOrPointeeTypeMatches(ValType))
|
||||
return error("Explicit load/store type does not match pointee "
|
||||
"type of pointer operand");
|
||||
if (!PointerType::isLoadableOrStorableType(ElemType))
|
||||
if (!PointerType::isLoadableOrStorableType(ValType))
|
||||
return error("Cannot load/store from pointer");
|
||||
return Error::success();
|
||||
}
|
||||
|
|
|
@ -1436,7 +1436,7 @@ LoadInst::LoadInst(Type *Ty, Value *Ptr, const Twine &Name, bool isVolatile,
|
|||
Align Align, AtomicOrdering Order, SyncScope::ID SSID,
|
||||
Instruction *InsertBef)
|
||||
: UnaryInstruction(Ty, Load, Ptr, InsertBef) {
|
||||
assert(Ty == cast<PointerType>(Ptr->getType())->getElementType());
|
||||
assert(cast<PointerType>(Ptr->getType())->isOpaqueOrPointeeTypeMatches(Ty));
|
||||
setVolatile(isVolatile);
|
||||
setAlignment(Align);
|
||||
setAtomic(Order, SSID);
|
||||
|
@ -1448,7 +1448,7 @@ LoadInst::LoadInst(Type *Ty, Value *Ptr, const Twine &Name, bool isVolatile,
|
|||
Align Align, AtomicOrdering Order, SyncScope::ID SSID,
|
||||
BasicBlock *InsertAE)
|
||||
: UnaryInstruction(Ty, Load, Ptr, InsertAE) {
|
||||
assert(Ty == cast<PointerType>(Ptr->getType())->getElementType());
|
||||
assert(cast<PointerType>(Ptr->getType())->isOpaqueOrPointeeTypeMatches(Ty));
|
||||
setVolatile(isVolatile);
|
||||
setAlignment(Align);
|
||||
setAtomic(Order, SSID);
|
||||
|
@ -1464,9 +1464,9 @@ void StoreInst::AssertOK() {
|
|||
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<PointerType>(getOperand(1)->getType())->getElementType()
|
||||
&& "Ptr must be a pointer to Val type!");
|
||||
assert(cast<PointerType>(getOperand(1)->getType())
|
||||
->isOpaqueOrPointeeTypeMatches(getOperand(0)->getType()) &&
|
||||
"Ptr must be a pointer to Val type!");
|
||||
assert(!(isAtomic() && getAlignment() == 0) &&
|
||||
"Alignment required for atomic store");
|
||||
}
|
||||
|
|
|
@ -3753,8 +3753,8 @@ void Verifier::visitLoadInst(LoadInst &LI) {
|
|||
void Verifier::visitStoreInst(StoreInst &SI) {
|
||||
PointerType *PTy = dyn_cast<PointerType>(SI.getOperand(1)->getType());
|
||||
Assert(PTy, "Store operand must be a pointer.", &SI);
|
||||
Type *ElTy = PTy->getElementType();
|
||||
Assert(ElTy == SI.getOperand(0)->getType(),
|
||||
Type *ElTy = SI.getOperand(0)->getType();
|
||||
Assert(PTy->isOpaqueOrPointeeTypeMatches(ElTy),
|
||||
"Stored value type does not match pointer operand type!", &SI, ElTy);
|
||||
Assert(SI.getAlignment() <= Value::MaximumAlignment,
|
||||
"huge alignment values are unsupported", &SI);
|
||||
|
|
|
@ -24,3 +24,19 @@ define ptr addrspace(2) @g2(ptr addrspace(0) %a) {
|
|||
%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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
Loading…
Reference in New Issue