.. _deprecation:

===================
Deprecation Notices
===================

This section contains information about deprecation of behaviours, features and
APIs that have become undesirable/obsolete. Any information about the schedule
for their deprecation and reasoning behind the changes, along with examples, is
provided.


Deprecation of LLVM initialization
==================================

A breaking change occurred with the upgrade to LLVM 20 in llvmlite 0.45.
Initialization of LLVM core is now automatic, and ``llvm.binding.initialize()`` 
will raise a ``RuntimeError`` with a suitable message.
LLVM 20 included many behavior changes that may break user code
or expectations. This hard error warns users of such potential breakage.
See :ref:`llvm20` for details on the LLVM 20 upgrade (llvmlite 0.45--0.47)
and :ref:`llvm22` for the LLVM 22 upgrade (llvmlite 0.48+).

Reason for deprecation
----------------------

This is an unscheduled deprecation due to removal of the underlying API in LLVM 20.


Schedule
--------

- In llvmlite 0.45, ``llvm.binding.initialize()`` will raise a hard error to 
  notify users of the breaking change. 
- In llvmlite 0.46, ``llvm.binding.initialize()`` will be removed.


Recommendations
---------------

Simply remove ``llvm.binding.initialize()``.


.. _deprecation-of-typed-pointers:

Deprecation of Typed Pointers
=============================

.. note:: Typed pointers support has been removed as llvmlite uses LLVM 20 or
          later (0.45+), which dropped support for typed pointers. All pointer
          operations now use opaque pointers. See the migration guide below for
          updating existing code.

The use of Typed Pointers is deprecated, and :ref:`Opaque Pointers
<pointer-types>` will be the default (and eventually required) in a future
llvmlite version.

Reason for deprecation
----------------------

llvmlite aims to move forward to newer LLVM versions, which will necessitate
switching to `Opaque Pointers <https://llvm.org/docs/OpaquePointers.html>`_:

- In LLVM 15, Opaque Pointers are the default.
- In LLVM 16, Typed Pointers are only supported on a best-effort basis (and
  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 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
<https://docs.nvidia.com/cuda/nvvm-ir-spec/>`_.

Examples(s) of the impact
-------------------------

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.45, support for Typed Pointers in the binding layer was
  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
---------------

Code using llvmlite should be updated as follows when switching to Opaque
Pointers.

IR layer
~~~~~~~~

Modify uses of ``.type.pointee`` of instructions to use ``.allocated_type``
instead. For example:

.. code:: python

   # Allocating an integer on the stack and storing a value to it
   stackint = builder.alloca(ir.IntType(32))
   builder.store(ir.Constant(stackint.type.pointee, 123), stackint)

becomes:

.. code:: python

   # Allocating an integer on the stack and storing a value to it
   stackint = builder.alloca(ir.IntType(32))
   builder.store(ir.Constant(stackint.allocated_type, 123), stackint)


Replace the use of ``.as_pointer()`` of types with the ``PointerType`` class.
For example:

.. code:: python

   # Declaring a function of type i32(i32*, i32)
   fnty = ir.FunctionType(ir.IntType(32), [ir.IntType(32).as_pointer(),
                          ir.IntType(32)])


becomes:

.. code:: python

   # Declaring a function of type i32(ptr, i32)
   fnty = ir.FunctionType(ir.IntType(32), [ir.PointerType(),
                          ir.IntType(32)])


Modify calls to ``ir.load``, ``ir.load_atomic``, and ``ir.gep`` instructions to
pass in pointer types. For example:

.. code:: python

   ptr = builder.gep(func.args[0], [index])
   value = builder.load(ptr)

becomes:

.. code:: python

   ptr = builder.gep(func.args[0], [index], source_etype=ll.IntType(32))
   value = builder.load(ptr, typ=ll.IntType(32))


Binding layer
~~~~~~~~~~~~~

When working with :class:`TargetData <llvmlite.binding.TargetData>` instances:

- Replace calls to :meth:`get_pointee_abi_size()
  <llvmlite.binding.TargetData.get_pointee_abi_size>` with calls to
  :meth:`get_abi_size() <llvmlite.binding.TargetData.get_abi_size>`.
- Replace calls to :meth:`get_pointee_abi_alignment()
  <llvmlite.binding.TargetData.get_pointee_abi_alignment>` with calls to
  :meth:`get_abi_alignment() <llvmlite.binding.TargetData.get_abi_alignment>`.

When working with global variables and functions (which will be :class:`ValueRef
<llvmlite.binding.ValueRef>` instances):

- Replace any use of ``valueref.type`` with ``valueref.global_value_type`` for
  any ``valueref`` that is a global variable or function.

When passing assembly to :func:`llvmlite.binding.parse_assembly`:

- IR passed to ``parse_assembly()`` is free to use either Typed or Opaque
  Pointers.

