Skip to content

Commit 6feb4a8

Browse files
authored
[IR] Don't allow values of opaque type (#137625)
Consider opaque types as non-first-class types, i.e. do not allow SSA values to have opaque type.
1 parent f1248d6 commit 6feb4a8

26 files changed

+87
-114
lines changed

llvm/docs/LangRef.rst

Lines changed: 24 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -4122,6 +4122,30 @@ except :ref:`label <t_label>` and :ref:`metadata <t_metadata>`.
41224122
| ``{i32, i32} (i32)`` | A function taking an ``i32``, returning a :ref:`structure <t_struct>` containing two ``i32`` values |
41234123
+---------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------+
41244124

4125+
.. _t_opaque:
4126+
4127+
Opaque Structure Types
4128+
----------------------
4129+
4130+
:Overview:
4131+
4132+
Opaque structure types are used to represent structure types that
4133+
do not have a body specified. This corresponds (for example) to the C
4134+
notion of a forward declared structure. They can be named (``%X``) or
4135+
unnamed (``%52``).
4136+
4137+
It is not possible to create SSA values with an opaque structure type. In
4138+
practice, this largely limits their use to the value type of external globals.
4139+
4140+
:Syntax:
4141+
4142+
::
4143+
4144+
%X = type opaque
4145+
%52 = type opaque
4146+
4147+
@g = external global %X
4148+
41254149
.. _t_firstclass:
41264150

41274151
First Class Types
@@ -4562,31 +4586,6 @@ opaqued and are never uniqued. Identified types must not be recursive.
45624586
| ``<{ i8, i32 }>`` | A packed struct known to be 5 bytes in size. |
45634587
+------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
45644588

4565-
.. _t_opaque:
4566-
4567-
Opaque Structure Types
4568-
""""""""""""""""""""""
4569-
4570-
:Overview:
4571-
4572-
Opaque structure types are used to represent structure types that
4573-
do not have a body specified. This corresponds (for example) to the C
4574-
notion of a forward declared structure. They can be named (``%X``) or
4575-
unnamed (``%52``).
4576-
4577-
:Syntax:
4578-
4579-
::
4580-
4581-
%X = type opaque
4582-
%52 = type opaque
4583-
4584-
:Examples:
4585-
4586-
+--------------+-------------------+
4587-
| ``opaque`` | An opaque type. |
4588-
+--------------+-------------------+
4589-
45904589
.. _constants:
45914590

45924591
Constants

llvm/include/llvm/IR/Type.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -286,9 +286,7 @@ class Type {
286286

287287
/// Return true if the type is "first class", meaning it is a valid type for a
288288
/// Value.
289-
bool isFirstClassType() const {
290-
return getTypeID() != FunctionTyID && getTypeID() != VoidTyID;
291-
}
289+
bool isFirstClassType() const;
292290

293291
/// Return true if the type is a valid type for a register in codegen. This
294292
/// includes all first-class types except struct and array types.

llvm/lib/IR/Type.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,20 @@ int Type::getFPMantissaWidth() const {
247247
return -1;
248248
}
249249

250+
bool Type::isFirstClassType() const {
251+
switch (getTypeID()) {
252+
default:
253+
return true;
254+
case FunctionTyID:
255+
case VoidTyID:
256+
return false;
257+
case StructTyID: {
258+
auto *ST = cast<StructType>(this);
259+
return !ST->isOpaque();
260+
}
261+
}
262+
}
263+
250264
bool Type::isSizedDerivedType(SmallPtrSetImpl<Type*> *Visited) const {
251265
if (auto *ATy = dyn_cast<ArrayType>(this))
252266
return ATy->getElementType()->isSized(Visited);

llvm/lib/Linker/IRMover.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1640,6 +1640,8 @@ Error IRLinker::run() {
16401640
if (GV.hasAppendingLinkage())
16411641
continue;
16421642
Value *NewValue = Mapper.mapValue(GV);
1643+
if (FoundError)
1644+
return std::move(*FoundError);
16431645
if (NewValue) {
16441646
auto *NewGV = dyn_cast<GlobalVariable>(NewValue->stripPointerCasts());
16451647
if (NewGV) {
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
; Test for PR463. This program is erroneous, but should not crash llvm-as.
22
; RUN: not llvm-as %s -o /dev/null 2>&1 | FileCheck %s
3-
; CHECK: use of undefined type named 'struct.none'
3+
; CHECK: invalid type for null constant
44

55
@.FOO = internal global %struct.none zeroinitializer
Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
; RUN: llvm-as < %s | llvm-dis | llvm-as > /dev/null
2-
; RUN: verify-uselistorder %s
1+
; RUN: not llvm-as < %s 2>&1 | FileCheck %s
2+
3+
; CHECK: error: invalid type for undef constant
34

45
%t = type opaque
56
@x = global %t undef

llvm/test/Assembler/2007-01-02-Undefined-Arg-Type.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
; The assembler should catch an undefined argument type .
22
; RUN: not llvm-as %s -o /dev/null 2>&1 | FileCheck %s
33

4-
; CHECK: use of undefined type named 'typedef.bc_struct'
4+
; CHECK: invalid type for function argument
55

66
; %typedef.bc_struct = type opaque
77

llvm/test/CodeGen/WebAssembly/externref-unsized-load.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,4 @@ define void @load_extern(%externref %ref) {
77
ret void
88
}
99

10-
; CHECK-ERROR: error: loading unsized types is not allowed
10+
; CHECK-ERROR: error: load operand must be a pointer to a first class type

llvm/test/CodeGen/WebAssembly/externref-unsized-store.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,4 @@ define void @store_extern(%externref %ref) {
77
ret void
88
}
99

10-
; CHECK-ERROR: error: storing unsized types is not allowed
10+
; CHECK-ERROR: error: invalid type for undef constant

llvm/test/CodeGen/X86/cfguard-x86-64-vectorcall.ll

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
; RUN: llc < %s -mtriple=x86_64-w64-windows-gnu | FileCheck %s -check-prefix=X64
44
; Control Flow Guard is currently only available on Windows
55

6+
%struct.HVA = type { double, double, double, double }
67

78
; Test that Control Flow Guard checks are correctly added for x86_64 vector calls.
89
define void @func_cf_vector_x64(ptr %0, ptr %1) #0 {
@@ -37,8 +38,6 @@ entry:
3738
}
3839
attributes #0 = { "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" }
3940

40-
%struct.HVA = type { double, double, double, double }
41-
4241
declare void @llvm.memcpy.p0.p0.i64(ptr nocapture writeonly, ptr nocapture readonly, i64, i1 immarg) #1
4342
attributes #1 = { argmemonly nounwind willreturn }
4443

0 commit comments

Comments
 (0)