From b2619197ec54b9b9f8b1ec3c4323e03a58929fcf Mon Sep 17 00:00:00 2001 From: Ricardo Jesus Date: Fri, 7 Feb 2025 16:07:14 +0000 Subject: [PATCH 01/11] Add lazy opaque pointers mode --- llvmlite/__init__.py | 12 ++++++++---- llvmlite/ir/types.py | 19 ++----------------- 2 files changed, 10 insertions(+), 21 deletions(-) diff --git a/llvmlite/__init__.py b/llvmlite/__init__.py index f830f73f9..e5f6f4c08 100644 --- a/llvmlite/__init__.py +++ b/llvmlite/__init__.py @@ -3,8 +3,12 @@ del get_versions # FIXME: Remove me once typed pointers are no longer supported. -def _opaque_pointers_enabled(): +# Let's enable opaque pointers unconditionally. +opaque_pointers_enabled = True +# Note: We should probably default to lazy opaque pointers disabled, but I want +# us to be able to test with Numba directly. +def _lazy_opaque_pointers_enabled(): import os - return os.environ.get('LLVMLITE_ENABLE_OPAQUE_POINTERS', '0') == '1' -opaque_pointers_enabled = _opaque_pointers_enabled() -del _opaque_pointers_enabled + return os.environ.get('LLVMLITE_ENABLE_LAZY_OPAQUE_POINTERS', '1') == '1' +lazy_opaque_pointers_enabled = _lazy_opaque_pointers_enabled() +del _lazy_opaque_pointers_enabled diff --git a/llvmlite/ir/types.py b/llvmlite/ir/types.py index eac3ada7a..e674a128e 100644 --- a/llvmlite/ir/types.py +++ b/llvmlite/ir/types.py @@ -4,11 +4,9 @@ import struct +from llvmlite import lazy_opaque_pointers_enabled from llvmlite.ir._utils import _StrCaching -# FIXME: Remove me once typed pointers are no longer supported. -from llvmlite import opaque_pointers_enabled - def _wrapname(x): return '"{0}"'.format(x.replace('\\', '\\5c').replace('"', '\\22')) @@ -145,8 +143,6 @@ def from_llvm(cls, typeref, ir_ctx): """ Create from a llvmlite.binding.TypeRef """ - if not opaque_pointers_enabled: - return _TypedPointerType.from_llvm(typeref, ir_ctx) return cls() @@ -163,7 +159,7 @@ def __init__(self, pointee, addrspace=0): self.is_opaque = False def _to_string(self): - if not opaque_pointers_enabled: + if lazy_opaque_pointers_enabled: return "{0}*".format(self.pointee) if self.addrspace == 0 else \ "{0} addrspace({1})*".format(self.pointee, self.addrspace) return super(_TypedPointerType, self)._to_string() @@ -190,17 +186,6 @@ def gep(self, i): def intrinsic_name(self): return 'p%d%s' % (self.addrspace, self.pointee.intrinsic_name) - @classmethod - def from_llvm(cls, typeref, ir_ctx): - """ - Create from a llvmlite.binding.TypeRef - """ - assert not opaque_pointers_enabled - # opaque pointer will change this - [pointee] = typeref.elements - # addrspace is not handled - return cls(pointee.as_ir(ir_ctx=ir_ctx)) - class VoidType(Type): """ From ff60f616b76a9c7faaf069f0c0e6cba69e102a67 Mon Sep 17 00:00:00 2001 From: Ricardo Jesus Date: Fri, 7 Feb 2025 17:37:09 +0000 Subject: [PATCH 02/11] Fix test_ir tests --- llvmlite/tests/test_ir.py | 99 +++++++++++++-------------------------- 1 file changed, 33 insertions(+), 66 deletions(-) diff --git a/llvmlite/tests/test_ir.py b/llvmlite/tests/test_ir.py index 5b29aa82f..df63a140d 100644 --- a/llvmlite/tests/test_ir.py +++ b/llvmlite/tests/test_ir.py @@ -12,9 +12,7 @@ from . import TestCase from llvmlite import ir from llvmlite import binding as llvm - -# FIXME: Remove me once typed pointers are no longer supported. -from llvmlite import opaque_pointers_enabled +from llvmlite import lazy_opaque_pointers_enabled int1 = ir.IntType(1) @@ -123,10 +121,9 @@ def check_func_body(self, func, asm): class TestFunction(TestBase): - # FIXME: Remove `else' once TP are no longer supported. proto = \ """i32 @"my_func"(i32 %".1", i32 %".2", double %".3", ptr %".4")""" \ - if opaque_pointers_enabled else \ + if not lazy_opaque_pointers_enabled else \ """i32 @"my_func"(i32 %".1", i32 %".2", double %".3", i32* %".4")""" def test_declare(self): @@ -146,8 +143,7 @@ def test_declare_attributes(self): pers = ir.Function(self.module(), tp_pers, '__gxx_personality_v0') func.attributes.personality = pers asm = self.descr(func).strip() - # FIXME: Remove `else' once TP are no longer supported. - if opaque_pointers_enabled: + if not lazy_opaque_pointers_enabled: self.assertEqual(asm, ("declare %s alwaysinline convergent optsize " "alignstack(16) " @@ -172,8 +168,7 @@ def test_function_attributes(self): func.args[3].add_attribute("nonnull") func.return_value.add_attribute("noalias") asm = self.descr(func).strip() - # FIXME: Remove `else' once TP are no longer supported. - if opaque_pointers_enabled: + if not lazy_opaque_pointers_enabled: self.assertEqual(asm, """declare noalias i32 @"my_func"(i32 zeroext %".1", i32 dereferenceable(5) dereferenceable_or_null(10) %".2", double %".3", ptr nonnull align 4 %".4")""" # noqa E501 ) @@ -284,8 +279,7 @@ def test_declare_intrinsics(self): assume = module.declare_intrinsic('llvm.assume') self.check_descr(self.descr(powi).strip(), """\ declare double @"llvm.powi.f64"(double %".1", i32 %".2")""") - # FIXME: Remove `else' once TP are no longer supported. - if opaque_pointers_enabled: + if not lazy_opaque_pointers_enabled: self.check_descr(self.descr(memset).strip(), """\ declare void @"llvm.memset.p0i8.i32"(ptr %".1", i8 %".2", i32 %".3", i1 %".4")""") # noqa E501 self.check_descr(self.descr(memcpy).strip(), """\ @@ -402,8 +396,7 @@ def test_metadata_null(self): # A null metadata (typed) value mod = self.module() mod.add_metadata([int32.as_pointer()(None)]) - # FIXME: Remove `else' once TP are no longer supported. - if opaque_pointers_enabled: + if not lazy_opaque_pointers_enabled: self.assert_ir_line("!0 = !{ ptr null }", mod) else: self.assert_ir_line("!0 = !{ i32* null }", mod) @@ -623,8 +616,7 @@ def test_globals_access(self): with self.assertRaises(KeyError): mod.get_global('kkk') # Globals should have a useful repr() - # FIXME: Remove `else' once TP are no longer supported. - if opaque_pointers_enabled: + if not lazy_opaque_pointers_enabled: self.assertEqual(repr(globdouble), "") else: @@ -1027,7 +1019,7 @@ def test_mem_ops(self): self.assertEqual(j.type, ir.VoidType()) k = builder.load_atomic(c, ordering="seq_cst", align=4, name='k') self.assertEqual(k.type, int32) - if opaque_pointers_enabled: + if not lazy_opaque_pointers_enabled: ptr = ir.Constant(ir.PointerType(), None) else: ptr = ir.Constant(ir.PointerType(int32), None) @@ -1041,8 +1033,7 @@ def test_mem_ops(self): with self.assertRaises(TypeError) as cm: builder.store(b, e) - # FIXME: Remove `else' once TP are no longer supported. - if opaque_pointers_enabled: + if not lazy_opaque_pointers_enabled: self.assertEqual(str(cm.exception), "cannot store i32 to ptr: mismatching types") self.check_block(block, """\ @@ -1084,8 +1075,7 @@ def test_gep(self): c = builder.alloca(ir.PointerType(int32), name='c') d = builder.gep(c, [ir.Constant(int32, 5), a], name='d') self.assertEqual(d.type, ir.PointerType(int32)) - # FIXME: Remove `else' once TP are no longer supported. - if opaque_pointers_enabled: + if not lazy_opaque_pointers_enabled: self.check_block(block, """\ my_block: %"c" = alloca ptr @@ -1110,8 +1100,7 @@ def test_gep_castinstr(self): d = builder.bitcast(a, ls.as_pointer(), name='d') e = builder.gep(d, [ir.Constant(int32, x) for x in [0, 3]], name='e') self.assertEqual(e.type, ir.PointerType(int8ptr)) - # FIXME: Remove `else' once TP are no longer supported. - if opaque_pointers_enabled: + if not lazy_opaque_pointers_enabled: self.check_block(block, """\ my_block: %"d" = bitcast i32 %".1" to ptr @@ -1137,8 +1126,7 @@ def test_gep_castinstr_addrspace(self): e = builder.gep(d, [ir.Constant(int32, x) for x in [0, 3]], name='e') self.assertEqual(e.type.addrspace, addrspace) self.assertEqual(e.type, ir.PointerType(int8ptr, addrspace=addrspace)) - # FIXME: Remove `else' once TP are no longer supported. - if opaque_pointers_enabled: + if not lazy_opaque_pointers_enabled: self.check_block(block, """\ my_block: %"d" = bitcast i32 %".1" to ptr addrspace(4) @@ -1157,8 +1145,7 @@ def test_gep_addrspace(self): a, b = builder.function.args[:2] addrspace = 4 c = builder.alloca(ir.PointerType(int32, addrspace=addrspace), name='c') - # FIXME: Remove `else' once TP are no longer supported. - if opaque_pointers_enabled: + if not lazy_opaque_pointers_enabled: self.assertEqual(str(c.type), 'ptr') else: self.assertEqual(str(c.type), 'i32 addrspace(4)**') @@ -1167,8 +1154,7 @@ def test_gep_addrspace(self): self.assertEqual(d.type.addrspace, addrspace) e = builder.gep(d, [ir.Constant(int32, 10)], name='e') self.assertEqual(e.type.addrspace, addrspace) - # FIXME: Remove `else' once TP are no longer supported. - if opaque_pointers_enabled: + if not lazy_opaque_pointers_enabled: self.check_block(block, """\ my_block: %"c" = alloca ptr addrspace(4) @@ -1229,8 +1215,7 @@ def test_extract_insert_value(self): # Replacement value has the wrong type builder.insert_value(c_inner, a, 1) - # FIXME: Remove `else' once TP are no longer supported. - if opaque_pointers_enabled: + if not lazy_opaque_pointers_enabled: self.check_block(block, """\ my_block: %"c" = extractvalue {i32, i1} {i32 4, i1 true}, 0 @@ -1278,8 +1263,7 @@ def test_cast_ops(self): j = builder.inttoptr(i, ir.PointerType(int8), 'j') # noqa F841 k = builder.bitcast(a, flt, "k") # noqa F841 self.assertFalse(block.is_terminated) - # FIXME: Remove `else' once TP are no longer supported. - if opaque_pointers_enabled: + if not lazy_opaque_pointers_enabled: self.check_block(block, """\ my_block: %"c" = trunc i32 %".1" to i8 @@ -1319,8 +1303,7 @@ def test_atomicrmw(self): c = builder.alloca(int32, name='c') d = builder.atomic_rmw('add', c, a, 'monotonic', 'd') self.assertEqual(d.type, int32) - # FIXME: Remove `else' once TP are no longer supported. - if opaque_pointers_enabled: + if not lazy_opaque_pointers_enabled: self.check_block(block, """\ my_block: %"c" = alloca i32 @@ -1382,8 +1365,7 @@ def test_branch_indirect(self): indirectbr.add_destination(bb_1) indirectbr.add_destination(bb_2) self.assertTrue(block.is_terminated) - # FIXME: Remove `else' once TP are no longer supported. - if opaque_pointers_enabled: + if not lazy_opaque_pointers_enabled: self.check_block(block, """\ my_block: indirectbr ptr blockaddress(@"my_func", %"b_1"), [label %"b_1", label %"b_2"] @@ -1505,8 +1487,7 @@ def test_call_metadata(self): a = builder.alloca(int32, name="a") b = builder.module.add_metadata(()) builder.call(dbg_declare, (a, b, b)) - # FIXME: Remove `else' once TP are no longer supported. - if opaque_pointers_enabled: + if not lazy_opaque_pointers_enabled: self.check_block(block, """\ my_block: %"a" = alloca i32 @@ -1536,8 +1517,7 @@ def test_call_attributes(self): 2: 'noalias' } ) - # FIXME: Remove `else' once TP are no longer supported. - if opaque_pointers_enabled: + if not lazy_opaque_pointers_enabled: self.check_block_regex(block, """\ my_block: %"retval" = alloca i32 @@ -1628,8 +1608,7 @@ def test_invoke_attributes(self): 2: 'noalias' } ) - # FIXME: Remove `else' once TP are no longer supported. - if opaque_pointers_enabled: + if not lazy_opaque_pointers_enabled: self.check_block_regex(block, """\ my_block: %"retval" = alloca i32 @@ -1658,8 +1637,7 @@ def test_landingpad(self): lp.add_clause(ir.FilterClause(ir.Constant(ir.ArrayType( int_typeinfo.type, 1), [int_typeinfo]))) builder.resume(lp) - # FIXME: Remove `else' once TP are no longer supported. - if opaque_pointers_enabled: + if not lazy_opaque_pointers_enabled: self.check_block(block, """\ my_block: %"lp" = landingpad {i32, ptr} @@ -2346,8 +2324,7 @@ def test_metadata(self): builder = ir.IRBuilder(block) builder.debug_metadata = builder.module.add_metadata([]) builder.alloca(ir.PointerType(int32), name='c') - # FIXME: Remove `else' once TP are no longer supported. - if opaque_pointers_enabled: + if not lazy_opaque_pointers_enabled: self.check_block(block, """\ my_block: %"c" = alloca ptr, !dbg !0 @@ -2431,8 +2408,7 @@ def test_str(self): 'i1 (float, ...)') self.assertEqual(str(ir.FunctionType(int1, (flt, dbl), var_arg=True)), 'i1 (float, double, ...)') - # FIXME: Remove `else' once TP are no longer supported. - if opaque_pointers_enabled: + if not lazy_opaque_pointers_enabled: self.assertEqual(str(ir.PointerType(int32)), 'ptr') self.assertEqual(str(ir.PointerType(ir.PointerType(int32))), 'ptr') else: @@ -2440,8 +2416,7 @@ def test_str(self): self.assertEqual(str(ir.PointerType(ir.PointerType(int32))), 'i32**') self.assertEqual(str(ir.ArrayType(int1, 5)), '[5 x i1]') - # FIXME: Remove `else' once TP are no longer supported. - if opaque_pointers_enabled: + if not lazy_opaque_pointers_enabled: self.assertEqual(str(ir.ArrayType(ir.PointerType(int1), 5)), '[5 x ptr]') self.assertEqual(str(ir.PointerType(ir.ArrayType(int1, 5))), 'ptr') @@ -2452,8 +2427,7 @@ def test_str(self): '[5 x i1]*') self.assertEqual(str(ir.LiteralStructType((int1,))), '{i1}') self.assertEqual(str(ir.LiteralStructType((int1, flt))), '{i1, float}') - # FIXME: Remove `else' once TP are no longer supported. - if opaque_pointers_enabled: + if not lazy_opaque_pointers_enabled: self.assertEqual(str(ir.LiteralStructType(( ir.PointerType(int1), ir.LiteralStructType((int32, int8))))), '{ptr, {i32, i8}}') @@ -2751,8 +2725,7 @@ def test_gep(self): tp = ir.LiteralStructType((flt, int1)) gv = ir.GlobalVariable(m, tp, "myconstant") c = gv.gep([ir.Constant(int32, x) for x in (0, 1)]) - # FIXME: Remove `else' once TP are no longer supported. - if opaque_pointers_enabled: + if not lazy_opaque_pointers_enabled: self.assertEqual(str(c), 'getelementptr ({float, i1}, ptr @"myconstant", i32 0, i32 1)') # noqa E501 else: @@ -2766,8 +2739,7 @@ def test_gep(self): const_ptr = ir.Constant(tp.as_pointer(), None) c2 = const_ptr.gep([ir.Constant(int32, 0)]) - # FIXME: Remove `else' once TP are no longer supported. - if opaque_pointers_enabled: + if not lazy_opaque_pointers_enabled: self.assertEqual(str(c2), 'getelementptr ({float, i1}, ptr null, i32 0)') # noqa E501 else: @@ -2784,8 +2756,7 @@ def test_gep_addrspace_globalvar(self): self.assertEqual(gv.addrspace, addrspace) c = gv.gep([ir.Constant(int32, x) for x in (0, 1)]) self.assertEqual(c.type.addrspace, addrspace) - # FIXME: Remove `else' once TP are no longer supported. - if opaque_pointers_enabled: + if not lazy_opaque_pointers_enabled: self.assertEqual(str(c), ('getelementptr ({float, i1}, ptr ' 'addrspace(4) @"myconstant", i32 0, i32 1)')) @@ -2819,8 +2790,7 @@ def test_bitcast(self): m = self.module() gv = ir.GlobalVariable(m, int32, "myconstant") c = gv.bitcast(int64.as_pointer()) - # FIXME: Remove `else' once TP are no longer supported. - if opaque_pointers_enabled: + if not lazy_opaque_pointers_enabled: self.assertEqual(str(c), 'bitcast (ptr @"myconstant" to ptr)') else: self.assertEqual(str(c), 'bitcast (i32* @"myconstant" to i64*)') @@ -2848,8 +2818,7 @@ def test_ptrtoint_1(self): self.assertRaises(TypeError, one.ptrtoint, int64) self.assertRaises(TypeError, ptr.ptrtoint, flt) - # FIXME: Remove `else' once TP are no longer supported. - if opaque_pointers_enabled: + if not lazy_opaque_pointers_enabled: self.assertEqual(str(c), 'ptrtoint (ptr null to i32)') else: self.assertEqual(str(c), 'ptrtoint (i64* null to i32)') @@ -2858,8 +2827,7 @@ def test_ptrtoint_2(self): m = self.module() gv = ir.GlobalVariable(m, int32, "myconstant") c = gv.ptrtoint(int64) - # FIXME: Remove `else' once TP are no longer supported. - if opaque_pointers_enabled: + if not lazy_opaque_pointers_enabled: self.assertEqual(str(c), 'ptrtoint (ptr @"myconstant" to i64)') self.assertRaisesRegex( @@ -2890,8 +2858,7 @@ def test_inttoptr(self): self.assertRaises(TypeError, one.inttoptr, int64) self.assertRaises(TypeError, pi.inttoptr, int64.as_pointer()) - # FIXME: Remove `else' once TP are no longer supported. - if opaque_pointers_enabled: + if not lazy_opaque_pointers_enabled: self.assertEqual(str(c), 'inttoptr (i32 1 to ptr)') else: self.assertEqual(str(c), 'inttoptr (i32 1 to i64*)') From dba9682dd0743cb7c88e86dba859c22764dff8b8 Mon Sep 17 00:00:00 2001 From: Ricardo Jesus Date: Wed, 19 Feb 2025 14:48:42 +0000 Subject: [PATCH 03/11] Update llvmlite/__init__.py Co-authored-by: Graham Markall <535640+gmarkall@users.noreply.github.com> --- llvmlite/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/llvmlite/__init__.py b/llvmlite/__init__.py index e5f6f4c08..fc078efd0 100644 --- a/llvmlite/__init__.py +++ b/llvmlite/__init__.py @@ -5,8 +5,8 @@ # FIXME: Remove me once typed pointers are no longer supported. # Let's enable opaque pointers unconditionally. opaque_pointers_enabled = True -# Note: We should probably default to lazy opaque pointers disabled, but I want -# us to be able to test with Numba directly. +# We default to lazy opaque pointers being enabled, since they're needed in the +# most common usage scenarios with later LLVMs def _lazy_opaque_pointers_enabled(): import os return os.environ.get('LLVMLITE_ENABLE_LAZY_OPAQUE_POINTERS', '1') == '1' From d8d6fe6434fb6364c90cfee3dab4f5c12bfe40be Mon Sep 17 00:00:00 2001 From: Ricardo Jesus Date: Wed, 19 Feb 2025 14:48:59 +0000 Subject: [PATCH 04/11] Update llvmlite/__init__.py Co-authored-by: Graham Markall <535640+gmarkall@users.noreply.github.com> --- llvmlite/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvmlite/__init__.py b/llvmlite/__init__.py index fc078efd0..8b47f60e3 100644 --- a/llvmlite/__init__.py +++ b/llvmlite/__init__.py @@ -3,7 +3,7 @@ del get_versions # FIXME: Remove me once typed pointers are no longer supported. -# Let's enable opaque pointers unconditionally. +# Opaque pointers unconditionally required for later LLVM versions opaque_pointers_enabled = True # We default to lazy opaque pointers being enabled, since they're needed in the # most common usage scenarios with later LLVMs From 16c1b4828e19ec2dff0ba6cf175e7aa79aa0e665 Mon Sep 17 00:00:00 2001 From: Ricardo Jesus Date: Thu, 20 Feb 2025 12:11:38 +0000 Subject: [PATCH 05/11] Rename lazy opaque pointers to IR layer typed pointers. --- llvmlite/__init__.py | 12 +++---- llvmlite/ir/types.py | 4 +-- llvmlite/tests/test_ir.py | 66 +++++++++++++++++++-------------------- 3 files changed, 41 insertions(+), 41 deletions(-) diff --git a/llvmlite/__init__.py b/llvmlite/__init__.py index 8b47f60e3..d53654370 100644 --- a/llvmlite/__init__.py +++ b/llvmlite/__init__.py @@ -5,10 +5,10 @@ # FIXME: Remove me once typed pointers are no longer supported. # Opaque pointers unconditionally required for later LLVM versions opaque_pointers_enabled = True -# We default to lazy opaque pointers being enabled, since they're needed in the -# most common usage scenarios with later LLVMs -def _lazy_opaque_pointers_enabled(): +# We default to IR layer typed pointers being enabled, since they're needed in +# the most common usage scenarios with later LLVMs. +def _ir_layer_typed_pointers_enabled(): import os - return os.environ.get('LLVMLITE_ENABLE_LAZY_OPAQUE_POINTERS', '1') == '1' -lazy_opaque_pointers_enabled = _lazy_opaque_pointers_enabled() -del _lazy_opaque_pointers_enabled + return os.environ.get('LLVMLITE_ENABLE_IR_LAYER_TYPED_POINTERS', '1') == '1' +ir_layer_typed_pointers_enabled = _ir_layer_typed_pointers_enabled() +del _ir_layer_typed_pointers_enabled diff --git a/llvmlite/ir/types.py b/llvmlite/ir/types.py index e674a128e..9a6ba0943 100644 --- a/llvmlite/ir/types.py +++ b/llvmlite/ir/types.py @@ -4,7 +4,7 @@ import struct -from llvmlite import lazy_opaque_pointers_enabled +from llvmlite import ir_layer_typed_pointers_enabled from llvmlite.ir._utils import _StrCaching @@ -159,7 +159,7 @@ def __init__(self, pointee, addrspace=0): self.is_opaque = False def _to_string(self): - if lazy_opaque_pointers_enabled: + if ir_layer_typed_pointers_enabled: return "{0}*".format(self.pointee) if self.addrspace == 0 else \ "{0} addrspace({1})*".format(self.pointee, self.addrspace) return super(_TypedPointerType, self)._to_string() diff --git a/llvmlite/tests/test_ir.py b/llvmlite/tests/test_ir.py index df63a140d..410b3b235 100644 --- a/llvmlite/tests/test_ir.py +++ b/llvmlite/tests/test_ir.py @@ -12,7 +12,7 @@ from . import TestCase from llvmlite import ir from llvmlite import binding as llvm -from llvmlite import lazy_opaque_pointers_enabled +from llvmlite import ir_layer_typed_pointers_enabled int1 = ir.IntType(1) @@ -123,7 +123,7 @@ class TestFunction(TestBase): proto = \ """i32 @"my_func"(i32 %".1", i32 %".2", double %".3", ptr %".4")""" \ - if not lazy_opaque_pointers_enabled else \ + if not ir_layer_typed_pointers_enabled else \ """i32 @"my_func"(i32 %".1", i32 %".2", double %".3", i32* %".4")""" def test_declare(self): @@ -143,7 +143,7 @@ def test_declare_attributes(self): pers = ir.Function(self.module(), tp_pers, '__gxx_personality_v0') func.attributes.personality = pers asm = self.descr(func).strip() - if not lazy_opaque_pointers_enabled: + if not ir_layer_typed_pointers_enabled: self.assertEqual(asm, ("declare %s alwaysinline convergent optsize " "alignstack(16) " @@ -168,7 +168,7 @@ def test_function_attributes(self): func.args[3].add_attribute("nonnull") func.return_value.add_attribute("noalias") asm = self.descr(func).strip() - if not lazy_opaque_pointers_enabled: + if not ir_layer_typed_pointers_enabled: self.assertEqual(asm, """declare noalias i32 @"my_func"(i32 zeroext %".1", i32 dereferenceable(5) dereferenceable_or_null(10) %".2", double %".3", ptr nonnull align 4 %".4")""" # noqa E501 ) @@ -279,7 +279,7 @@ def test_declare_intrinsics(self): assume = module.declare_intrinsic('llvm.assume') self.check_descr(self.descr(powi).strip(), """\ declare double @"llvm.powi.f64"(double %".1", i32 %".2")""") - if not lazy_opaque_pointers_enabled: + if not ir_layer_typed_pointers_enabled: self.check_descr(self.descr(memset).strip(), """\ declare void @"llvm.memset.p0i8.i32"(ptr %".1", i8 %".2", i32 %".3", i1 %".4")""") # noqa E501 self.check_descr(self.descr(memcpy).strip(), """\ @@ -396,7 +396,7 @@ def test_metadata_null(self): # A null metadata (typed) value mod = self.module() mod.add_metadata([int32.as_pointer()(None)]) - if not lazy_opaque_pointers_enabled: + if not ir_layer_typed_pointers_enabled: self.assert_ir_line("!0 = !{ ptr null }", mod) else: self.assert_ir_line("!0 = !{ i32* null }", mod) @@ -616,7 +616,7 @@ def test_globals_access(self): with self.assertRaises(KeyError): mod.get_global('kkk') # Globals should have a useful repr() - if not lazy_opaque_pointers_enabled: + if not ir_layer_typed_pointers_enabled: self.assertEqual(repr(globdouble), "") else: @@ -1019,7 +1019,7 @@ def test_mem_ops(self): self.assertEqual(j.type, ir.VoidType()) k = builder.load_atomic(c, ordering="seq_cst", align=4, name='k') self.assertEqual(k.type, int32) - if not lazy_opaque_pointers_enabled: + if not ir_layer_typed_pointers_enabled: ptr = ir.Constant(ir.PointerType(), None) else: ptr = ir.Constant(ir.PointerType(int32), None) @@ -1033,7 +1033,7 @@ def test_mem_ops(self): with self.assertRaises(TypeError) as cm: builder.store(b, e) - if not lazy_opaque_pointers_enabled: + if not ir_layer_typed_pointers_enabled: self.assertEqual(str(cm.exception), "cannot store i32 to ptr: mismatching types") self.check_block(block, """\ @@ -1075,7 +1075,7 @@ def test_gep(self): c = builder.alloca(ir.PointerType(int32), name='c') d = builder.gep(c, [ir.Constant(int32, 5), a], name='d') self.assertEqual(d.type, ir.PointerType(int32)) - if not lazy_opaque_pointers_enabled: + if not ir_layer_typed_pointers_enabled: self.check_block(block, """\ my_block: %"c" = alloca ptr @@ -1100,7 +1100,7 @@ def test_gep_castinstr(self): d = builder.bitcast(a, ls.as_pointer(), name='d') e = builder.gep(d, [ir.Constant(int32, x) for x in [0, 3]], name='e') self.assertEqual(e.type, ir.PointerType(int8ptr)) - if not lazy_opaque_pointers_enabled: + if not ir_layer_typed_pointers_enabled: self.check_block(block, """\ my_block: %"d" = bitcast i32 %".1" to ptr @@ -1126,7 +1126,7 @@ def test_gep_castinstr_addrspace(self): e = builder.gep(d, [ir.Constant(int32, x) for x in [0, 3]], name='e') self.assertEqual(e.type.addrspace, addrspace) self.assertEqual(e.type, ir.PointerType(int8ptr, addrspace=addrspace)) - if not lazy_opaque_pointers_enabled: + if not ir_layer_typed_pointers_enabled: self.check_block(block, """\ my_block: %"d" = bitcast i32 %".1" to ptr addrspace(4) @@ -1145,7 +1145,7 @@ def test_gep_addrspace(self): a, b = builder.function.args[:2] addrspace = 4 c = builder.alloca(ir.PointerType(int32, addrspace=addrspace), name='c') - if not lazy_opaque_pointers_enabled: + if not ir_layer_typed_pointers_enabled: self.assertEqual(str(c.type), 'ptr') else: self.assertEqual(str(c.type), 'i32 addrspace(4)**') @@ -1154,7 +1154,7 @@ def test_gep_addrspace(self): self.assertEqual(d.type.addrspace, addrspace) e = builder.gep(d, [ir.Constant(int32, 10)], name='e') self.assertEqual(e.type.addrspace, addrspace) - if not lazy_opaque_pointers_enabled: + if not ir_layer_typed_pointers_enabled: self.check_block(block, """\ my_block: %"c" = alloca ptr addrspace(4) @@ -1215,7 +1215,7 @@ def test_extract_insert_value(self): # Replacement value has the wrong type builder.insert_value(c_inner, a, 1) - if not lazy_opaque_pointers_enabled: + if not ir_layer_typed_pointers_enabled: self.check_block(block, """\ my_block: %"c" = extractvalue {i32, i1} {i32 4, i1 true}, 0 @@ -1263,7 +1263,7 @@ def test_cast_ops(self): j = builder.inttoptr(i, ir.PointerType(int8), 'j') # noqa F841 k = builder.bitcast(a, flt, "k") # noqa F841 self.assertFalse(block.is_terminated) - if not lazy_opaque_pointers_enabled: + if not ir_layer_typed_pointers_enabled: self.check_block(block, """\ my_block: %"c" = trunc i32 %".1" to i8 @@ -1303,7 +1303,7 @@ def test_atomicrmw(self): c = builder.alloca(int32, name='c') d = builder.atomic_rmw('add', c, a, 'monotonic', 'd') self.assertEqual(d.type, int32) - if not lazy_opaque_pointers_enabled: + if not ir_layer_typed_pointers_enabled: self.check_block(block, """\ my_block: %"c" = alloca i32 @@ -1365,7 +1365,7 @@ def test_branch_indirect(self): indirectbr.add_destination(bb_1) indirectbr.add_destination(bb_2) self.assertTrue(block.is_terminated) - if not lazy_opaque_pointers_enabled: + if not ir_layer_typed_pointers_enabled: self.check_block(block, """\ my_block: indirectbr ptr blockaddress(@"my_func", %"b_1"), [label %"b_1", label %"b_2"] @@ -1487,7 +1487,7 @@ def test_call_metadata(self): a = builder.alloca(int32, name="a") b = builder.module.add_metadata(()) builder.call(dbg_declare, (a, b, b)) - if not lazy_opaque_pointers_enabled: + if not ir_layer_typed_pointers_enabled: self.check_block(block, """\ my_block: %"a" = alloca i32 @@ -1517,7 +1517,7 @@ def test_call_attributes(self): 2: 'noalias' } ) - if not lazy_opaque_pointers_enabled: + if not ir_layer_typed_pointers_enabled: self.check_block_regex(block, """\ my_block: %"retval" = alloca i32 @@ -1608,7 +1608,7 @@ def test_invoke_attributes(self): 2: 'noalias' } ) - if not lazy_opaque_pointers_enabled: + if not ir_layer_typed_pointers_enabled: self.check_block_regex(block, """\ my_block: %"retval" = alloca i32 @@ -1637,7 +1637,7 @@ def test_landingpad(self): lp.add_clause(ir.FilterClause(ir.Constant(ir.ArrayType( int_typeinfo.type, 1), [int_typeinfo]))) builder.resume(lp) - if not lazy_opaque_pointers_enabled: + if not ir_layer_typed_pointers_enabled: self.check_block(block, """\ my_block: %"lp" = landingpad {i32, ptr} @@ -2324,7 +2324,7 @@ def test_metadata(self): builder = ir.IRBuilder(block) builder.debug_metadata = builder.module.add_metadata([]) builder.alloca(ir.PointerType(int32), name='c') - if not lazy_opaque_pointers_enabled: + if not ir_layer_typed_pointers_enabled: self.check_block(block, """\ my_block: %"c" = alloca ptr, !dbg !0 @@ -2408,7 +2408,7 @@ def test_str(self): 'i1 (float, ...)') self.assertEqual(str(ir.FunctionType(int1, (flt, dbl), var_arg=True)), 'i1 (float, double, ...)') - if not lazy_opaque_pointers_enabled: + if not ir_layer_typed_pointers_enabled: self.assertEqual(str(ir.PointerType(int32)), 'ptr') self.assertEqual(str(ir.PointerType(ir.PointerType(int32))), 'ptr') else: @@ -2416,7 +2416,7 @@ def test_str(self): self.assertEqual(str(ir.PointerType(ir.PointerType(int32))), 'i32**') self.assertEqual(str(ir.ArrayType(int1, 5)), '[5 x i1]') - if not lazy_opaque_pointers_enabled: + if not ir_layer_typed_pointers_enabled: self.assertEqual(str(ir.ArrayType(ir.PointerType(int1), 5)), '[5 x ptr]') self.assertEqual(str(ir.PointerType(ir.ArrayType(int1, 5))), 'ptr') @@ -2427,7 +2427,7 @@ def test_str(self): '[5 x i1]*') self.assertEqual(str(ir.LiteralStructType((int1,))), '{i1}') self.assertEqual(str(ir.LiteralStructType((int1, flt))), '{i1, float}') - if not lazy_opaque_pointers_enabled: + if not ir_layer_typed_pointers_enabled: self.assertEqual(str(ir.LiteralStructType(( ir.PointerType(int1), ir.LiteralStructType((int32, int8))))), '{ptr, {i32, i8}}') @@ -2725,7 +2725,7 @@ def test_gep(self): tp = ir.LiteralStructType((flt, int1)) gv = ir.GlobalVariable(m, tp, "myconstant") c = gv.gep([ir.Constant(int32, x) for x in (0, 1)]) - if not lazy_opaque_pointers_enabled: + if not ir_layer_typed_pointers_enabled: self.assertEqual(str(c), 'getelementptr ({float, i1}, ptr @"myconstant", i32 0, i32 1)') # noqa E501 else: @@ -2739,7 +2739,7 @@ def test_gep(self): const_ptr = ir.Constant(tp.as_pointer(), None) c2 = const_ptr.gep([ir.Constant(int32, 0)]) - if not lazy_opaque_pointers_enabled: + if not ir_layer_typed_pointers_enabled: self.assertEqual(str(c2), 'getelementptr ({float, i1}, ptr null, i32 0)') # noqa E501 else: @@ -2756,7 +2756,7 @@ def test_gep_addrspace_globalvar(self): self.assertEqual(gv.addrspace, addrspace) c = gv.gep([ir.Constant(int32, x) for x in (0, 1)]) self.assertEqual(c.type.addrspace, addrspace) - if not lazy_opaque_pointers_enabled: + if not ir_layer_typed_pointers_enabled: self.assertEqual(str(c), ('getelementptr ({float, i1}, ptr ' 'addrspace(4) @"myconstant", i32 0, i32 1)')) @@ -2790,7 +2790,7 @@ def test_bitcast(self): m = self.module() gv = ir.GlobalVariable(m, int32, "myconstant") c = gv.bitcast(int64.as_pointer()) - if not lazy_opaque_pointers_enabled: + if not ir_layer_typed_pointers_enabled: self.assertEqual(str(c), 'bitcast (ptr @"myconstant" to ptr)') else: self.assertEqual(str(c), 'bitcast (i32* @"myconstant" to i64*)') @@ -2818,7 +2818,7 @@ def test_ptrtoint_1(self): self.assertRaises(TypeError, one.ptrtoint, int64) self.assertRaises(TypeError, ptr.ptrtoint, flt) - if not lazy_opaque_pointers_enabled: + if not ir_layer_typed_pointers_enabled: self.assertEqual(str(c), 'ptrtoint (ptr null to i32)') else: self.assertEqual(str(c), 'ptrtoint (i64* null to i32)') @@ -2827,7 +2827,7 @@ def test_ptrtoint_2(self): m = self.module() gv = ir.GlobalVariable(m, int32, "myconstant") c = gv.ptrtoint(int64) - if not lazy_opaque_pointers_enabled: + if not ir_layer_typed_pointers_enabled: self.assertEqual(str(c), 'ptrtoint (ptr @"myconstant" to i64)') self.assertRaisesRegex( @@ -2858,7 +2858,7 @@ def test_inttoptr(self): self.assertRaises(TypeError, one.inttoptr, int64) self.assertRaises(TypeError, pi.inttoptr, int64.as_pointer()) - if not lazy_opaque_pointers_enabled: + if not ir_layer_typed_pointers_enabled: self.assertEqual(str(c), 'inttoptr (i32 1 to ptr)') else: self.assertEqual(str(c), 'inttoptr (i32 1 to i64*)') From be48e7bd79e3e41acae25286154de06c82eed6fa Mon Sep 17 00:00:00 2001 From: Graham Markall Date: Fri, 28 Feb 2025 12:21:00 +0000 Subject: [PATCH 06/11] Update deprecation notice for IR layer typed pointers --- docs/source/user-guide/deprecation.rst | 33 ++++++++++++++++++++------ 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/docs/source/user-guide/deprecation.rst b/docs/source/user-guide/deprecation.rst index cb0c36f2c..488132ed6 100644 --- a/docs/source/user-guide/deprecation.rst +++ b/docs/source/user-guide/deprecation.rst @@ -30,20 +30,38 @@ switching to `Opaque Pointers `_: therefore may have bugs that go unfixed). - In LLVM 17, support for Typed Pointers is removed. -Although Opaque Pointers are already the default in LLVM 15, llvmlite still uses -Typed Pointers by default with LLVM 15. +Although Opaque Pointers are already the default in LLVM 15, llvmlite still used +Typed Pointers by default with LLVM 15 in llvmlite 0.44. + +The binding layer will move to using Opaque Pointers. The IR layer will still +support both Typed and Opaque Pointers, defaulting to Typed Pointers. This +allows llvmlite to continue being used with LLVM-based projects that use an +older LLVM version, such as `NVVM +`_. Examples(s) of the impact ------------------------- -Code that uses llvmlite to work with pointers or to parse assembly that uses -pointers will break if not modified to use opaque pointers. +In a future release of llvmlite, code that uses llvmlite to work with pointers +or to parse assembly that uses pointers will break if not modified to use +Opaque Pointers. + +In the meantime, IR generated by the IR layer and parsed by the binding layer +will be auto-upgraded to use Opaque Pointers transparently; no action is +required by the user. Schedule -------- -- In llvmlite 0.44, Opaque Pointers will be the default pointer kind. -- In llvmlite 0.45, support for Typed Pointers will be removed. +- In llvmlite 0.45, support for Opaque Pointers in the binding layer will be + removed. The IR layer will still use Typed Pointers by default. +- In a future version of llvmlite (>= 0.46), the IR layer will use Opaque + Pointers by default. +- In a subsequent version of llvmlite (>= 0.47), support for Typed Pointers at + the IR layer will be removed. + +This schedule may be updated to push out the deprecation / removal of Typed +Pointer support to still later versions of llvmlite. Recommendations --------------- @@ -127,7 +145,8 @@ When working with global variables and functions (which will be :class:`ValueRef When passing assembly to :func:`llvmlite.binding.parse_assembly`: -- Ensure that any IR passed to ``parse_assembly()`` uses Opaque Pointers. +- IR passed to ``parse_assembly()`` is free to use either Typed or Opaque + Pointers. Deprecation of `llvmlite.llvmpy` module From eca2f5e09c2fa28056cac7bb672bab3377765326 Mon Sep 17 00:00:00 2001 From: Graham Markall Date: Fri, 28 Feb 2025 12:35:30 +0000 Subject: [PATCH 07/11] Update types documentation for IR layer typed pointers --- docs/source/user-guide/ir/types.rst | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/docs/source/user-guide/ir/types.rst b/docs/source/user-guide/ir/types.rst index 220b8fcd1..e5e296b5f 100644 --- a/docs/source/user-guide/ir/types.rst +++ b/docs/source/user-guide/ir/types.rst @@ -100,9 +100,10 @@ Atomic types Pointer Types ============= -llvmlite presently supports both *Typed Pointers* and *Opaque Pointers*. Typed -Pointers are currently the default; Opaque Pointers will become the default in -future, and support for Typed Pointers will be eventually be removed. +The IR layer presently supports both *Typed Pointers* and *Opaque Pointers*. +Typed Pointers are currently the default; Opaque Pointers will become the +default in future, and support for Typed Pointers will be eventually be +removed. .. note:: Further details of the migration to Opaque Pointers are outlined in the @@ -126,23 +127,25 @@ When Typed Pointers are enabled, the pointer type is represented using: The type pointed to. -Opaque pointers can be enabled by setting the environment variable: +Opaque Pointers can be enabled in the IR layer by setting the environment +variable: .. code:: bash - LLVMLITE_ENABLE_OPAQUE_POINTERS=1 + LLVMLITE_ENABLE_IR_LAYER_TYPED_POINTERS=0 -or by setting the ``opaque_pointers_enabled`` attribute after importing +or by setting the ``ir_layer_typed_pointers_enabled`` attribute after importing llvmlite, but prior to using any of its functionality. For example: .. code:: python import llvmlite - llvmlite.opaque_pointers_enabled = True + llvmlite.ir_layer_typed_pointers_enabled = False # ... continue using llvmlite ... -When Opaque Pointers are enabled, the pointer type is represented using: +When Opaque Pointers are enabled (by disabling Typed Pointers), the pointer +type is represented using: .. class:: PointerType(addrspace=0) :no-index: From fac2b281d796ee2b13856587c8cf6bdb769d527c Mon Sep 17 00:00:00 2001 From: Graham Markall Date: Fri, 28 Feb 2025 12:36:43 +0000 Subject: [PATCH 08/11] Update examples for IR layer typed pointers --- examples/opaque_pointers/llvmir.py | 2 +- examples/opaque_pointers/sum.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/opaque_pointers/llvmir.py b/examples/opaque_pointers/llvmir.py index d25f0f2a5..875a2616d 100644 --- a/examples/opaque_pointers/llvmir.py +++ b/examples/opaque_pointers/llvmir.py @@ -1,5 +1,5 @@ import llvmlite -llvmlite.opaque_pointers_enabled = True +llvmlite.ir_layer_typed_pointers_enabled = False import llvmlite.ir as ll diff --git a/examples/opaque_pointers/sum.py b/examples/opaque_pointers/sum.py index f1c525c94..421c0be71 100644 --- a/examples/opaque_pointers/sum.py +++ b/examples/opaque_pointers/sum.py @@ -15,7 +15,7 @@ pass import llvmlite -llvmlite.opaque_pointers_enabled = True +llvmlite.ir_layer_typed_pointers_enabled = False import llvmlite.ir as ll import llvmlite.binding as llvm From 01e1669baaa0b0ce14fa194d4847e68e9b481099 Mon Sep 17 00:00:00 2001 From: Graham Markall Date: Fri, 28 Feb 2025 12:44:36 +0000 Subject: [PATCH 09/11] Update test scripts for IR layer opaque pointers --- buildscripts/incremental/test.cmd | 6 +++--- buildscripts/incremental/test.sh | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/buildscripts/incremental/test.cmd b/buildscripts/incremental/test.cmd index 7e3ab5c0a..c32424a5a 100644 --- a/buildscripts/incremental/test.cmd +++ b/buildscripts/incremental/test.cmd @@ -2,10 +2,10 @@ call activate %CONDA_ENV% if "%OPAQUE_POINTERS%"=="yes" ( - set LLVMLITE_ENABLE_OPAQUE_POINTERS=1 - echo "Testing with opaque pointers enabled" + set LLVMLITE_ENABLE_IR_LAYER_TYPED_POINTERS=0 + echo "Testing with IR layer opaque pointers enabled" ) else ( - echo "Testing with opaque pointers disabled" + echo "Testing with IR layer opaque pointers disabled" ) python runtests.py -v diff --git a/buildscripts/incremental/test.sh b/buildscripts/incremental/test.sh index 2fcf6bbaf..8bf7acb1d 100755 --- a/buildscripts/incremental/test.sh +++ b/buildscripts/incremental/test.sh @@ -10,10 +10,10 @@ set -v -e python --version if [ "$OPAQUE_POINTERS" == "yes" ]; then - export LLVMLITE_ENABLE_OPAQUE_POINTERS=1 - echo "Testing with opaque pointers enabled" + export LLVMLITE_ENABLE_IR_LAYER_TYPED_POINTERS=0 + echo "Testing with IR layer opaque pointers enabled" else - echo "Testing with opaque pointers disabled" + echo "Testing with IR layer opaque pointers disabled" fi if [ "$WHEEL" == "yes" ]; then From 02097b873c1ff388ed87a5cc4c04c82b072abe57 Mon Sep 17 00:00:00 2001 From: Graham Markall Date: Tue, 4 Mar 2025 10:40:11 +0000 Subject: [PATCH 10/11] Modify pointer docs in response to PR #1159 feedback --- docs/source/user-guide/deprecation.rst | 14 +++++++------- docs/source/user-guide/ir/types.rst | 13 +++++-------- 2 files changed, 12 insertions(+), 15 deletions(-) diff --git a/docs/source/user-guide/deprecation.rst b/docs/source/user-guide/deprecation.rst index 488132ed6..5167970e7 100644 --- a/docs/source/user-guide/deprecation.rst +++ b/docs/source/user-guide/deprecation.rst @@ -34,17 +34,17 @@ Although Opaque Pointers are already the default in LLVM 15, llvmlite still used Typed Pointers by default with LLVM 15 in llvmlite 0.44. The binding layer will move to using Opaque Pointers. The IR layer will still -support both Typed and Opaque Pointers, defaulting to Typed Pointers. This -allows llvmlite to continue being used with LLVM-based projects that use an -older LLVM version, such as `NVVM +support both Typed and Opaque Pointers, defaulting to Typed Pointers when +pointee types are provided. This allows llvmlite to continue being used with +LLVM-based projects that use an older LLVM version, such as `NVVM `_. Examples(s) of the impact ------------------------- -In a future release of llvmlite, code that uses llvmlite to work with pointers -or to parse assembly that uses pointers will break if not modified to use -Opaque Pointers. +In a future release, code that uses llvmlite to work with Typed Pointers or +generate IR with Typed Pointers will break if not modified to use Opaque +Pointers. In the meantime, IR generated by the IR layer and parsed by the binding layer will be auto-upgraded to use Opaque Pointers transparently; no action is @@ -53,7 +53,7 @@ required by the user. Schedule -------- -- In llvmlite 0.45, support for Opaque Pointers in the binding layer will be +- In llvmlite 0.45, support for Typed Pointers in the binding layer will be removed. The IR layer will still use Typed Pointers by default. - In a future version of llvmlite (>= 0.46), the IR layer will use Opaque Pointers by default. diff --git a/docs/source/user-guide/ir/types.rst b/docs/source/user-guide/ir/types.rst index e5e296b5f..14d871132 100644 --- a/docs/source/user-guide/ir/types.rst +++ b/docs/source/user-guide/ir/types.rst @@ -101,15 +101,13 @@ Pointer Types ============= The IR layer presently supports both *Typed Pointers* and *Opaque Pointers*. -Typed Pointers are currently the default; Opaque Pointers will become the -default in future, and support for Typed Pointers will be eventually be -removed. +Support for Typed Pointers will be eventually be removed. .. note:: Further details of the migration to Opaque Pointers are outlined in the section on :ref:`deprecation-of-typed-pointers`. -When Typed Pointers are enabled, the pointer type is represented using: +Typed Pointers are created using: .. class:: PointerType(pointee, addrspace=0) @@ -127,8 +125,8 @@ When Typed Pointers are enabled, the pointer type is represented using: The type pointed to. -Opaque Pointers can be enabled in the IR layer by setting the environment -variable: +Printing of Typed Pointers as Opaque Pointers can be enabled by setting the +environment variable: .. code:: bash @@ -144,8 +142,7 @@ llvmlite, but prior to using any of its functionality. For example: # ... continue using llvmlite ... -When Opaque Pointers are enabled (by disabling Typed Pointers), the pointer -type is represented using: +Opaque Pointers can be created by using: .. class:: PointerType(addrspace=0) :no-index: From a563953e8e19ae24441e71c67bf836686a2be484 Mon Sep 17 00:00:00 2001 From: Graham Markall Date: Tue, 4 Mar 2025 15:59:20 +0000 Subject: [PATCH 11/11] Correct grammatical error in pointers docs --- docs/source/user-guide/ir/types.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/user-guide/ir/types.rst b/docs/source/user-guide/ir/types.rst index 14d871132..be2765ea1 100644 --- a/docs/source/user-guide/ir/types.rst +++ b/docs/source/user-guide/ir/types.rst @@ -101,7 +101,7 @@ Pointer Types ============= The IR layer presently supports both *Typed Pointers* and *Opaque Pointers*. -Support for Typed Pointers will be eventually be removed. +Support for Typed Pointers will eventually be removed. .. note:: Further details of the migration to Opaque Pointers are outlined in the