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 diff --git a/docs/source/user-guide/deprecation.rst b/docs/source/user-guide/deprecation.rst index cb0c36f2c..5167970e7 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 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 ------------------------- -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 +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 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. +- 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 diff --git a/docs/source/user-guide/ir/types.rst b/docs/source/user-guide/ir/types.rst index 220b8fcd1..be2765ea1 100644 --- a/docs/source/user-guide/ir/types.rst +++ b/docs/source/user-guide/ir/types.rst @@ -100,15 +100,14 @@ 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*. +Support for Typed Pointers will 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) @@ -126,23 +125,24 @@ 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: +Printing of Typed Pointers as Opaque Pointers can be enabled 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: +Opaque Pointers can be created by using: .. class:: PointerType(addrspace=0) :no-index: 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 diff --git a/llvmlite/__init__.py b/llvmlite/__init__.py index f830f73f9..d53654370 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(): +# Opaque pointers unconditionally required for later LLVM versions +opaque_pointers_enabled = True +# 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_OPAQUE_POINTERS', '0') == '1' -opaque_pointers_enabled = _opaque_pointers_enabled() -del _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 eac3ada7a..9a6ba0943 100644 --- a/llvmlite/ir/types.py +++ b/llvmlite/ir/types.py @@ -4,11 +4,9 @@ import struct +from llvmlite import ir_layer_typed_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 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() @@ -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): """ diff --git a/llvmlite/tests/test_ir.py b/llvmlite/tests/test_ir.py index 5b29aa82f..410b3b235 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 ir_layer_typed_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 ir_layer_typed_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 ir_layer_typed_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 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 ) @@ -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 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(), """\ @@ -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 ir_layer_typed_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 ir_layer_typed_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 ir_layer_typed_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 ir_layer_typed_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 ir_layer_typed_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 ir_layer_typed_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 ir_layer_typed_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 ir_layer_typed_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 ir_layer_typed_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 ir_layer_typed_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 ir_layer_typed_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 ir_layer_typed_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 ir_layer_typed_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 ir_layer_typed_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 ir_layer_typed_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 ir_layer_typed_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 ir_layer_typed_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 ir_layer_typed_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 ir_layer_typed_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 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') @@ -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 ir_layer_typed_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 ir_layer_typed_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 ir_layer_typed_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 ir_layer_typed_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 ir_layer_typed_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 ir_layer_typed_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 ir_layer_typed_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 ir_layer_typed_pointers_enabled: self.assertEqual(str(c), 'inttoptr (i32 1 to ptr)') else: self.assertEqual(str(c), 'inttoptr (i32 1 to i64*)')