[OpaquePtr] Allow globals with opaque pointer value type

Do this by making opaque pointers a valid pointer element type,
for which we implicitly create an opaque pointer (moving the logic
from getPointerTo into PointerType::get).

We'll never create something like a "pointer to opaque pointer",
but accept it in the API, because a lot of code reasonably assumes
that you can create a pointer to pointer type.

Differential Revision: https://reviews.llvm.org/D104902
This commit is contained in:
Nikita Popov 2021-06-25 11:26:15 +02:00
parent 4d8156ef87
commit 1e6303e60c
3 changed files with 7 additions and 15 deletions

View File

@ -690,7 +690,9 @@ PointerType *PointerType::get(Type *EltTy, unsigned AddressSpace) {
LLVMContextImpl *CImpl = EltTy->getContext().pImpl; LLVMContextImpl *CImpl = EltTy->getContext().pImpl;
if (CImpl->ForceOpaquePointers) // Create opaque pointer for pointer to opaque pointer.
if (CImpl->ForceOpaquePointers ||
(isa<PointerType>(EltTy) && cast<PointerType>(EltTy)->isOpaque()))
return get(EltTy->getContext(), AddressSpace); return get(EltTy->getContext(), AddressSpace);
// Since AddressSpace #0 is the common case, we special case it. // Since AddressSpace #0 is the common case, we special case it.
@ -729,19 +731,13 @@ PointerType::PointerType(LLVMContext &C, unsigned AddrSpace)
} }
PointerType *Type::getPointerTo(unsigned AddrSpace) const { PointerType *Type::getPointerTo(unsigned AddrSpace) const {
// Pointer to opaque pointer is opaque pointer.
if (auto *PTy = dyn_cast<PointerType>(this))
if (PTy->isOpaque())
return PointerType::get(getContext(), AddrSpace);
return PointerType::get(const_cast<Type*>(this), AddrSpace); return PointerType::get(const_cast<Type*>(this), AddrSpace);
} }
bool PointerType::isValidElementType(Type *ElemTy) { bool PointerType::isValidElementType(Type *ElemTy) {
return !ElemTy->isVoidTy() && !ElemTy->isLabelTy() && return !ElemTy->isVoidTy() && !ElemTy->isLabelTy() &&
!ElemTy->isMetadataTy() && !ElemTy->isTokenTy() && !ElemTy->isMetadataTy() && !ElemTy->isTokenTy() &&
!ElemTy->isX86_AMXTy() && !ElemTy->isX86_AMXTy();
!(ElemTy->isPointerTy() && cast<PointerType>(ElemTy)->isOpaque());
} }
bool PointerType::isLoadableOrStorableType(Type *ElemTy) { bool PointerType::isLoadableOrStorableType(Type *ElemTy) {

View File

@ -1,7 +0,0 @@
; RUN: not llvm-as < %s -disable-output 2>&1 | FileCheck %s
; CHECK: pointer to this type is invalid
define void @f(ptr %a) {
%b = bitcast ptr %a to ptr*
ret void
}

View File

@ -1,6 +1,9 @@
; RUN: llvm-as < %s | llvm-dis | llvm-as | llvm-dis | FileCheck %s ; RUN: llvm-as < %s | llvm-dis | llvm-as | llvm-dis | FileCheck %s
; RUN: verify-uselistorder %s ; RUN: verify-uselistorder %s
; CHECK: @global = external global ptr
@global = external global ptr
; CHECK: define ptr @f(ptr %a) { ; CHECK: define ptr @f(ptr %a) {
; CHECK: %b = bitcast ptr %a to ptr ; CHECK: %b = bitcast ptr %a to ptr
; CHECK: ret ptr %b ; CHECK: ret ptr %b