diff --git a/llvm/include/llvm/IR/LLVMContext.h b/llvm/include/llvm/IR/LLVMContext.h index 3bd889485dd1d1..50671db30eeb33 100644 --- a/llvm/include/llvm/IR/LLVMContext.h +++ b/llvm/include/llvm/IR/LLVMContext.h @@ -305,6 +305,9 @@ class LLVMContext { /// LLVMContext is used by compilation. void setOptPassGate(OptPassGate&); + /// Whether typed pointers are supported. If false, all pointers are opaque. + bool supportsTypedPointers() const; + private: // Module needs access to the add/removeModule methods. friend class Module; diff --git a/llvm/lib/IR/Function.cpp b/llvm/lib/IR/Function.cpp index 07c603fd98a6ab..8f096f0a69eb47 100644 --- a/llvm/lib/IR/Function.cpp +++ b/llvm/lib/IR/Function.cpp @@ -1404,9 +1404,21 @@ static bool matchIntrinsicType( } case IITDescriptor::Pointer: { PointerType *PT = dyn_cast(Ty); - return !PT || PT->getAddressSpace() != D.Pointer_AddressSpace || - matchIntrinsicType(PT->getElementType(), Infos, ArgTys, - DeferredChecks, IsDeferredCheck); + if (!PT || PT->getAddressSpace() != D.Pointer_AddressSpace) + return true; + if (!PT->isOpaque()) + return matchIntrinsicType(PT->getElementType(), Infos, ArgTys, + DeferredChecks, IsDeferredCheck); + // If typed pointers are supported, do not allow using opaque pointer in + // place of fixed pointer type. This would make the intrinsic signature + // non-unique. + if (Ty->getContext().supportsTypedPointers()) + return true; + // Consume IIT descriptors relating to the pointer element type. + while (Infos.front().Kind == IITDescriptor::Pointer) + Infos = Infos.slice(1); + Infos = Infos.slice(1); + return false; } case IITDescriptor::Struct: { @@ -1517,8 +1529,13 @@ static bool matchIntrinsicType( dyn_cast (ArgTys[D.getArgumentNumber()]); PointerType *ThisArgType = dyn_cast(Ty); - return (!ThisArgType || !ReferenceType || - ThisArgType->getElementType() != ReferenceType->getElementType()); + if (!ThisArgType || !ReferenceType) + return true; + if (!ThisArgType->isOpaque()) + return ThisArgType->getElementType() != ReferenceType->getElementType(); + // If typed pointers are supported, do not allow opaque pointer to ensure + // uniqueness. + return Ty->getContext().supportsTypedPointers(); } case IITDescriptor::VecOfAnyPtrsToElt: { unsigned RefArgNumber = D.getRefArgNumber(); diff --git a/llvm/lib/IR/LLVMContext.cpp b/llvm/lib/IR/LLVMContext.cpp index 79002fb1b1bc7e..234806b5dce03c 100644 --- a/llvm/lib/IR/LLVMContext.cpp +++ b/llvm/lib/IR/LLVMContext.cpp @@ -347,3 +347,7 @@ const DiagnosticHandler *LLVMContext::getDiagHandlerPtr() const { std::unique_ptr LLVMContext::getDiagnosticHandler() { return std::move(pImpl->DiagHandler); } + +bool LLVMContext::supportsTypedPointers() const { + return !pImpl->ForceOpaquePointers; +} diff --git a/llvm/test/Assembler/remangle-intrinsic-opaque-ptr.ll b/llvm/test/Assembler/remangle-intrinsic-opaque-ptr.ll new file mode 100644 index 00000000000000..6f7930ce4e1621 --- /dev/null +++ b/llvm/test/Assembler/remangle-intrinsic-opaque-ptr.ll @@ -0,0 +1,20 @@ +; RUN: not llvm-as < %s -disable-output 2>&1 | FileCheck %s --check-prefix=TYPED +; RUN: llvm-as --force-opaque-pointers < %s | llvm-dis --force-opaque-pointers | FileCheck %s --check-prefix=OPAQUE + +; An opaque pointer type should not be accepted for an intrinsic that +; specifies a fixed pointer type, outside of --force-opaque-pointers mode. + +define void @test() { +; TYPED: Intrinsic has incorrect return type! +; OPAQUE: call ptr @llvm.stacksave() + call ptr @llvm.stacksave() + +; TYPED: Intrinsic has incorrect argument type! +; OPAQUE: call <2 x i64> @llvm.masked.expandload.v2i64(ptr null, <2 x i1> zeroinitializer, <2 x i64> zeroinitializer) + call <2 x i64> @llvm.masked.expandload.v2i64(ptr null, <2 x i1> zeroinitializer, <2 x i64> zeroinitializer) + + ret void +} + +declare ptr @llvm.stacksave() +declare <2 x i64> @llvm.masked.expandload.v2i64(ptr, <2 x i1>, <2 x i64>) diff --git a/llvm/test/Other/force-opaque-ptrs.ll b/llvm/test/Other/force-opaque-ptrs.ll index 1a0738dfcd6379..ee7c752de41134 100644 --- a/llvm/test/Other/force-opaque-ptrs.ll +++ b/llvm/test/Other/force-opaque-ptrs.ll @@ -48,3 +48,22 @@ define void @f3(i32 addrspace(1)* addrspace(2)* %p) { ; unreachable } + +define void @remangle_intrinsic() { +; CHECK-LABEL: define {{[^@]+}}@remangle_intrinsic() { +; CHECK-NEXT: [[A:%.*]] = alloca ptr, align 8 +; CHECK-NEXT: [[TMP1:%.*]] = call ptr @llvm.stacksave() +; CHECK-NEXT: call void @llvm.stackprotector(ptr null, ptr [[A]]) +; CHECK-NEXT: [[TMP2:%.*]] = call <2 x i64> @llvm.masked.expandload.v2i64(ptr null, <2 x i1> zeroinitializer, <2 x i64> zeroinitializer) +; CHECK-NEXT: ret void +; + %a = alloca i8* + call i8* @llvm.stacksave() + call void @llvm.stackprotector(i8* null, i8** %a) + call <2 x i64> @llvm.masked.expandload.v2i64(i64* null, <2 x i1> zeroinitializer, <2 x i64> zeroinitializer) + ret void +} + +declare i8* @llvm.stacksave() +declare void @llvm.stackprotector(i8*, i8**) +declare <2 x i64> @llvm.masked.expandload.v2i64(i64*, <2 x i1>, <2 x i64>)