[llvm] [llvm-c][ocaml] Deprecate/replace constexpr GEP APIs (PR #228998)
Nikita Popov via llvm-commits
llvm-commits at lists.llvm.org
Mon Oct 5 02:08:11 PDT 2026
https://github.com/nikic updated https://github.com/llvm/llvm-project/pull/228998
>From 82937b1704d9d46eafd7f9e7a0baeceab99912e0 Mon Sep 17 00:00:00 2001
From: Nikita Popov <npopov at redhat.com>
Date: Wed, 30 Sep 2026 12:14:44 +0200
Subject: [PATCH 1/4] [llvm-c][ocaml] Deprecate/replace constexpr GEP APIs
In the C API, this deprecates LLVMConstGEP and LLVMConstInBoundsGEP.
The replacement APIs are LLVMConstPtrAdd and LLVMConstPtrAddFromIndices.
The latter exposes the DataLayout-aware `getGetElementPtr()` API,
and only exists for the sake of convience.
Similarly, in the OCaml API, remove const_gep and const_inbounds_gep
in favor of const_ptradd and const_ptradd_from_indices, which mirror
the C APIs translated to OCaml.
Unlike the older APIs, the new ones work directly on GEPNoWrapFlags
instead of providing (an incomplete set of) separate APIs for
different flavors.
---
llvm/bindings/ocaml/llvm/llvm.ml | 16 +++++---
llvm/bindings/ocaml/llvm/llvm.mli | 30 ++++++++++-----
llvm/bindings/ocaml/llvm/llvm_ocaml.c | 26 +++++++------
llvm/docs/ReleaseNotes.md | 13 +++++++
llvm/include/llvm-c/Core.h | 53 +++++++++++++++++++--------
llvm/lib/IR/Core.cpp | 19 ++++++++++
llvm/test/Bindings/OCaml/core.ml | 24 ++++++++++--
llvm/test/Bindings/llvm-c/echo.ll | 10 ++---
llvm/tools/llvm-c-test/echo.cpp | 5 ++-
llvm/unittests/IR/ConstantsTest.cpp | 28 ++++++++++++++
10 files changed, 171 insertions(+), 53 deletions(-)
diff --git a/llvm/bindings/ocaml/llvm/llvm.ml b/llvm/bindings/ocaml/llvm/llvm.ml
index 48bd48b9e4eba..f1a985be81aa0 100644
--- a/llvm/bindings/ocaml/llvm/llvm.ml
+++ b/llvm/bindings/ocaml/llvm/llvm.ml
@@ -355,6 +355,12 @@ module ModuleFlagBehavior = struct
| AppendUnique
end
+module GEPNoWrapFlags = struct
+ let inbounds = 1
+ let nusw = 2
+ let nuw = 4
+end
+
module Endian = struct
type t =
| Big
@@ -394,7 +400,6 @@ module DataLayout = struct
= "llvm_datalayout_offset_of_element"
end
-
exception IoError of string
let () = Callback.register_exception "Llvm.IoError" (IoError "")
@@ -697,10 +702,11 @@ external const_sub : llvalue -> llvalue -> llvalue = "llvm_const_sub"
external const_nsw_sub : llvalue -> llvalue -> llvalue = "llvm_const_nsw_sub"
external const_nuw_sub : llvalue -> llvalue -> llvalue = "llvm_const_nuw_sub"
external const_xor : llvalue -> llvalue -> llvalue = "llvm_const_xor"
-external const_gep : lltype -> llvalue -> llvalue array -> llvalue
- = "llvm_const_gep"
-external const_in_bounds_gep : lltype -> llvalue -> llvalue array -> llvalue
- = "llvm_const_in_bounds_gep"
+external const_ptradd : llvalue -> llvalue -> int -> llvalue
+ = "llvm_const_ptradd"
+external const_ptradd_from_indices : DataLayout.t -> lltype -> llvalue ->
+ llvalue array -> int -> llvalue option
+ = "llvm_const_ptradd_from_indices"
external const_trunc : llvalue -> lltype -> llvalue = "llvm_const_trunc"
external const_ptrtoint : llvalue -> lltype -> llvalue = "llvm_const_ptrtoint"
external const_inttoptr : llvalue -> lltype -> llvalue = "llvm_const_inttoptr"
diff --git a/llvm/bindings/ocaml/llvm/llvm.mli b/llvm/bindings/ocaml/llvm/llvm.mli
index 294f88c70f8f1..25104ed53e1e1 100644
--- a/llvm/bindings/ocaml/llvm/llvm.mli
+++ b/llvm/bindings/ocaml/llvm/llvm.mli
@@ -394,6 +394,12 @@ module ModuleFlagBehavior :sig
| AppendUnique
end
+module GEPNoWrapFlags : sig
+ val inbounds : int
+ val nusw : int
+ val nuw : int
+end
+
(** {6 Data Layout} *)
module Endian : sig
@@ -472,7 +478,6 @@ module DataLayout : sig
val offset_of_element : lltype -> int -> t -> Int64.t
end
-
(** {6 Iteration} *)
(** [Before b] and [At_end a] specify positions from the start of the ['b] list
@@ -1199,16 +1204,21 @@ val const_nuw_sub : llvalue -> llvalue -> llvalue
See the method [llvm::ConstantExpr::getXor]. *)
val const_xor : llvalue -> llvalue -> llvalue
-(** [const_gep srcty pc indices] returns the constant [getElementPtr] of [pc]
- with source element type [srcty] and the constant integers indices from the
- array [indices].
+(** [const_ptradd pc offset flags] returns the constant ptradd
+ (getelementptr i8) of [pc] with constant [offset] and the given
+ {!GEPNoWrapFlags} no-wrap flags (combined with [lor], or [0] for none).
+ See the method [llvm::ConstantExpr::getPtrAdd]. *)
+val const_ptradd : llvalue -> llvalue -> int -> llvalue
+
+(** [const_ptradd_from_indices dl srcty pc indices flags] returns the constant
+ ptradd of [pc] with the offset derived from the data layout [dl], the
+ source element type [srcty] and the constant integers indices from the
+ array [indices]. The flags are {!GEPNoWrapFlags} (combined with [lor], or
+ [0] for none). The result may be [None] if the indices cannot be converted
+ to ptradd representation.
See the method [llvm::ConstantExpr::getGetElementPtr]. *)
-val const_gep : lltype -> llvalue -> llvalue array -> llvalue
-
-(** [const_in_bounds_gep ty pc indices] returns the constant [getElementPtr] of
- [pc] with the constant integers indices from the array [indices].
- See the method [llvm::ConstantExpr::getInBoundsGetElementPtr]. *)
-val const_in_bounds_gep : lltype -> llvalue -> llvalue array -> llvalue
+val const_ptradd_from_indices : DataLayout.t -> lltype -> llvalue ->
+ llvalue array -> int -> llvalue option
(** [const_trunc c ty] returns the constant truncation of integer constant [c]
to the smaller integer type [ty].
diff --git a/llvm/bindings/ocaml/llvm/llvm_ocaml.c b/llvm/bindings/ocaml/llvm/llvm_ocaml.c
index e08797cf0e3d9..75ae700de70ed 100644
--- a/llvm/bindings/ocaml/llvm/llvm_ocaml.c
+++ b/llvm/bindings/ocaml/llvm/llvm_ocaml.c
@@ -1195,24 +1195,26 @@ value llvm_const_xor(value LHS, value RHS) {
return to_val(Value);
}
-/* lltype -> llvalue -> llvalue array -> llvalue */
-value llvm_const_gep(value Ty, value ConstantVal, value Indices) {
- mlsize_t Length = Wosize_val(Indices);
- LLVMValueRef *Temp = from_val_array(Indices);
- LLVMValueRef Value =
- LLVMConstGEP2(Type_val(Ty), Value_val(ConstantVal), Temp, Length);
- free(Temp);
+/* llvalue -> llvalue -> int -> llvalue */
+value llvm_const_ptradd(value ConstantVal, value ConstantOffset,
+ value NoWrapFlags) {
+ LLVMValueRef Value = LLVMConstPtrAdd(
+ Value_val(ConstantVal), Value_val(ConstantOffset), Int_val(NoWrapFlags));
return to_val(Value);
}
-/* lltype -> llvalue -> llvalue array -> llvalue */
-value llvm_const_in_bounds_gep(value Ty, value ConstantVal, value Indices) {
+/* DataLayout.t -> lltype -> llvalue -> llvalue array -> int ->
+ * llvalue option */
+value llvm_const_ptradd_from_indices(value DataLayout, value Ty,
+ value ConstantVal, value Indices,
+ value NoWrapFlags) {
mlsize_t Length = Wosize_val(Indices);
LLVMValueRef *Temp = from_val_array(Indices);
- LLVMValueRef Value =
- LLVMConstInBoundsGEP2(Type_val(Ty), Value_val(ConstantVal), Temp, Length);
+ LLVMValueRef Value = LLVMConstPtrAddFromIndices(
+ DataLayout_val(DataLayout), Type_val(Ty), Value_val(ConstantVal), Temp,
+ Length, Int_val(NoWrapFlags));
free(Temp);
- return to_val(Value);
+ return ptr_to_option(Value);
}
/* llvalue -> lltype -> llvalue */
diff --git a/llvm/docs/ReleaseNotes.md b/llvm/docs/ReleaseNotes.md
index 93674c1825367..d1797ef165f06 100644
--- a/llvm/docs/ReleaseNotes.md
+++ b/llvm/docs/ReleaseNotes.md
@@ -314,6 +314,12 @@ Makes programs 10x faster by doing Special New Thing.
`set_data_layout` now accepts a `DataLayout` instead of a `string`. You can
use `DataLayout.of_string` and `DataLayout.as_string` to convert between them.
+* `const_gep` and `const_inbounds_gep` have been removed in favor of
+ `const_ptradd` and `const_ptradd_from_indices`. Both create `getelementptr i8`
+ constant expressions, the former using an integero ffset, and the latter using
+ a data layout, base type and index sequence. The latter API returns an option,
+ as it may fail if the indices cannot be converted into ptradd representation.
+
### Changes to the Python bindings
### Changes to the C API
@@ -325,6 +331,13 @@ Makes programs 10x faster by doing Special New Thing.
* Bindings operating on data layout (`LLVMTargetDataRef`) have been moved
from `Target.h` (`Target` library) to `Core.h` (`IR` library).
+* `LLVMConstGEP2()` and `LLVMConstInBoundsGEP2()` have been deprecated.
+ `LLVMConstPtrAdd()` and `LLVMConstPtrAddFromIndices()` can be used instead.
+ Both create `getelementptr i8` constant expressions, the former using an
+ integer offset, and the latter using a data layout, base type and index
+ sequence. The latter API may fail if the indices cannot be converted into
+ ptradd representation.
+
### Changes to the CodeGen infrastructure
* Fixed a crash
diff --git a/llvm/include/llvm-c/Core.h b/llvm/include/llvm-c/Core.h
index ecff14ee644ce..b359267543e73 100644
--- a/llvm/include/llvm-c/Core.h
+++ b/llvm/include/llvm-c/Core.h
@@ -19,7 +19,6 @@
#include "llvm-c/ErrorHandling.h"
#include "llvm-c/ExternC.h"
#include "llvm-c/Visibility.h"
-
#include "llvm-c/Types.h"
LLVM_C_EXTERN_C_BEGIN
@@ -32,6 +31,8 @@ LLVM_C_EXTERN_C_BEGIN
* @{
*/
+typedef struct LLVMOpaqueTargetData *LLVMTargetDataRef;
+
/**
* @defgroup LLVMCTransforms Transforms
*/
@@ -2777,22 +2778,46 @@ LLVM_C_ABI LLVMValueRef LLVMConstNUWSub(LLVMValueRef LHSConstant,
LLVMValueRef RHSConstant);
LLVM_C_ABI LLVMValueRef LLVMConstXor(LLVMValueRef LHSConstant,
LLVMValueRef RHSConstant);
-LLVM_C_ABI LLVMValueRef LLVMConstGEP2(LLVMTypeRef Ty, LLVMValueRef ConstantVal,
- LLVMValueRef *ConstantIndices,
- unsigned NumIndices);
-LLVM_C_ABI LLVMValueRef LLVMConstInBoundsGEP2(LLVMTypeRef Ty,
- LLVMValueRef ConstantVal,
- LLVMValueRef *ConstantIndices,
- unsigned NumIndices);
+
+LLVM_C_ABI LLVM_ATTRIBUTE_C_DEPRECATED(
+ LLVMValueRef LLVMConstGEP2(LLVMTypeRef Ty, LLVMValueRef ConstantVal,
+ LLVMValueRef *ConstantIndices,
+ unsigned NumIndices),
+ "Use LLVMConstPtrAdd() or LLVMConstPtrAddFromIndices() instead");
+LLVM_C_ABI LLVM_ATTRIBUTE_C_DEPRECATED(
+ LLVMValueRef LLVMConstInBoundsGEP2(LLVMTypeRef Ty, LLVMValueRef ConstantVal,
+ LLVMValueRef *ConstantIndices,
+ unsigned NumIndices),
+ "Use LLVMConstPtrAdd() or LLVMConstPtrAddFromIndices() instead");
+LLVM_C_ABI LLVM_ATTRIBUTE_C_DEPRECATED(
+ LLVMValueRef LLVMConstGEPWithNoWrapFlags(
+ LLVMTypeRef Ty, LLVMValueRef ConstantVal, LLVMValueRef *ConstantIndices,
+ unsigned NumIndices, LLVMGEPNoWrapFlags NoWrapFlags),
+ "Use LLVMConstPtrAdd() or LLVMConstPtrAddFromIndices() instead");
+
/**
- * Creates a constant GetElementPtr expression. Similar to LLVMConstGEP2, but
- * allows specifying the no-wrap flags.
+ * Creates a constant ptradd expression (getelementptr i8).
+ *
+ * @see llvm::ConstantExpr::getPtrAdd()
+ */
+LLVM_C_ABI LLVMValueRef LLVMConstPtrAdd(LLVMValueRef ConstantVal,
+ LLVMValueRef ConstantOffset,
+ LLVMGEPNoWrapFlags NoWrapFlags);
+
+/**
+ * Creates a constant ptradd expression (getelementptr i8) by converting the
+ * provided GEP indices for the provided source element type into a constant
+ * offset using the provided data layout.
+ *
+ * May return null if the indices are not representable as a constant ptradd.
*
* @see llvm::ConstantExpr::getGetElementPtr()
*/
-LLVM_C_ABI LLVMValueRef LLVMConstGEPWithNoWrapFlags(
- LLVMTypeRef Ty, LLVMValueRef ConstantVal, LLVMValueRef *ConstantIndices,
- unsigned NumIndices, LLVMGEPNoWrapFlags NoWrapFlags);
+LLVM_C_ABI LLVMValueRef LLVMConstPtrAddFromIndices(
+ LLVMTargetDataRef DataLayout, LLVMTypeRef Ty, LLVMValueRef ConstantVal,
+ LLVMValueRef *ConstantIndices, unsigned NumIndices,
+ LLVMGEPNoWrapFlags NoWrapFlags);
+
LLVM_C_ABI LLVMValueRef LLVMConstTrunc(LLVMValueRef ConstantVal,
LLVMTypeRef ToType);
LLVM_C_ABI LLVMValueRef LLVMConstPtrToInt(LLVMValueRef ConstantVal,
@@ -5376,8 +5401,6 @@ LLVM_C_ABI LLVMBool LLVMIsMultithreaded(void);
enum LLVMByteOrdering { LLVMBigEndian, LLVMLittleEndian };
-typedef struct LLVMOpaqueTargetData *LLVMTargetDataRef;
-
/**
* Obtain the data layout for a module.
*
diff --git a/llvm/lib/IR/Core.cpp b/llvm/lib/IR/Core.cpp
index 0025b7b78ccc7..87c1ba389985d 100644
--- a/llvm/lib/IR/Core.cpp
+++ b/llvm/lib/IR/Core.cpp
@@ -1944,6 +1944,25 @@ LLVMValueRef LLVMConstGEPWithNoWrapFlags(LLVMTypeRef Ty,
LLVM_SUPPRESS_DEPRECATED_DECLARATIONS_POP
}
+LLVMValueRef LLVMConstPtrAdd(LLVMValueRef ConstantVal,
+ LLVMValueRef ConstantOffset,
+ LLVMGEPNoWrapFlags NoWrapFlags) {
+ return wrap(ConstantExpr::getPtrAdd(unwrap<Constant>(ConstantVal),
+ unwrap<Constant>(ConstantOffset),
+ mapFromLLVMGEPNoWrapFlags(NoWrapFlags)));
+}
+
+LLVM_C_ABI LLVMValueRef LLVMConstPtrAddFromIndices(
+ LLVMTargetDataRef DataLayout, LLVMTypeRef Ty, LLVMValueRef ConstantVal,
+ LLVMValueRef *ConstantIndices, unsigned NumIndices,
+ LLVMGEPNoWrapFlags NoWrapFlags) {
+ ArrayRef<Constant *> IdxList(unwrap<Constant>(ConstantIndices, NumIndices),
+ NumIndices);
+ return wrap(ConstantExpr::getGetElementPtr(
+ *unwrap(DataLayout), unwrap(Ty), unwrap<Constant>(ConstantVal), IdxList,
+ mapFromLLVMGEPNoWrapFlags(NoWrapFlags)));
+}
+
LLVMValueRef LLVMConstTrunc(LLVMValueRef ConstantVal, LLVMTypeRef ToType) {
return wrap(ConstantExpr::getTrunc(unwrap<Constant>(ConstantVal),
unwrap(ToType)));
diff --git a/llvm/test/Bindings/OCaml/core.ml b/llvm/test/Bindings/OCaml/core.ml
index b44058b2ad25a..7c1a683aa601d 100644
--- a/llvm/test/Bindings/OCaml/core.ml
+++ b/llvm/test/Bindings/OCaml/core.ml
@@ -297,21 +297,37 @@ let test_constants () =
ignore (define_global "const_trunc" (const_trunc (const_add foldbomb five)
i8_type) m);
ignore (define_global "const_ptrtoint" (const_ptrtoint
- (const_gep i8_type (const_null (pointer_type context))
- [| const_int i32_type 1 |])
+ (const_ptradd (const_null (pointer_type context)) (const_int i32_type 1) 0)
i32_type) m);
ignore (define_global "const_inttoptr" (const_inttoptr (const_add foldbomb five)
void_ptr) m);
ignore (define_global "const_bitcast" (const_bitcast foldbomb double_type) m);
group "misc constants";
- (* CHECK: const_gep{{.*}}getelementptr
+ (* CHECK: const_ptradd = global ptr getelementptr (i8, ptr @FoldBomb, i64 5)
+ * CHECK: const_ptradd_inbounds = global ptr
+ * CHECK-SAME: getelementptr inbounds (i8, ptr @FoldBomb, i64 5)
+ * CHECK: const_ptradd_inbounds_nuw = global ptr
+ * CHECK-SAME: getelementptr inbounds nuw (i8, ptr @FoldBomb, i64 5)
+ * CHECK: const_ptradd_from_indices = global ptr
+ * CHECK-SAME: getelementptr nusw (i8, ptr @FoldBomb, i32 20)
* CHECK: const_extractelement{{.*}}extractelement
* CHECK: const_insertelement{{.*}}insertelement
* CHECK: const_shufflevector = global <4 x i32> <i32 0, i32 1, i32 1, i32 0>
*)
- ignore (define_global "const_gep" (const_gep i8_type foldbomb_gv [| five |])
+ ignore (define_global "const_ptradd" (const_ptradd foldbomb_gv five 0) m);
+ ignore (define_global "const_ptradd_inbounds"
+ (const_ptradd foldbomb_gv five GEPNoWrapFlags.inbounds) m);
+ ignore (define_global "const_ptradd_inbounds_nuw"
+ (const_ptradd foldbomb_gv five
+ (GEPNoWrapFlags.inbounds lor GEPNoWrapFlags.nuw)) m);
+ ignore (define_global "const_ptradd_from_indices"
+ (Option.get (const_ptradd_from_indices (data_layout m) i32_type
+ foldbomb_gv [| five |] GEPNoWrapFlags.nusw))
m);
+ assert (Option.is_none (const_ptradd_from_indices (data_layout m) i32_type
+ foldbomb_gv
+ [| (const_ptrtoint foldbomb_gv i32_type) |] 0));
let zero = const_int i32_type 0 in
let one = const_int i32_type 1 in
ignore (define_global "const_extractelement" (const_extractelement
diff --git a/llvm/test/Bindings/llvm-c/echo.ll b/llvm/test/Bindings/llvm-c/echo.ll
index 285285a55c073..8d8ac9c75dbf8 100644
--- a/llvm/test/Bindings/llvm-c/echo.ll
+++ b/llvm/test/Bindings/llvm-c/echo.ll
@@ -24,11 +24,11 @@ module asm "classical GAS"
@align = global i32 31, align 4
@nullptr = global ptr null
- at const_gep = global ptr getelementptr (i32, ptr @var, i64 2)
- at const_inbounds_gep = global ptr getelementptr inbounds (i32, ptr @var, i64 1)
- at const_gep_nuw = global ptr getelementptr nuw (i32, ptr @var, i64 1)
- at const_gep_nusw = global ptr getelementptr nusw (i32, ptr @var, i64 1)
- at const_gep_nuw_inbounds = global ptr getelementptr nuw inbounds (i32, ptr @var, i64 1)
+ at const_gep = global ptr getelementptr (i8, ptr @var, i64 8)
+ at const_inbounds_gep = global ptr getelementptr inbounds (i8, ptr @var, i64 4)
+ at const_gep_nuw = global ptr getelementptr nuw (i8, ptr @var, i64 4)
+ at const_gep_nusw = global ptr getelementptr nusw (i8, ptr @var, i64 4)
+ at const_gep_nuw_inbounds = global ptr getelementptr nuw inbounds (i8, ptr @var, i64 4)
@aliased1 = alias i32, ptr @var
@aliased2 = internal alias i32, ptr @var
diff --git a/llvm/tools/llvm-c-test/echo.cpp b/llvm/tools/llvm-c-test/echo.cpp
index 717722c58a268..b807bef59dcee 100644
--- a/llvm/tools/llvm-c-test/echo.cpp
+++ b/llvm/tools/llvm-c-test/echo.cpp
@@ -422,8 +422,9 @@ static LLVMValueRef clone_constant_impl(LLVMValueRef Cst, LLVMModuleRef M) {
for (int i = 1; i <= NumIdx; i++)
Idx.push_back(clone_constant(LLVMGetOperand(Cst, i), M));
- return LLVMConstGEPWithNoWrapFlags(ElemTy, Ptr, Idx.data(), NumIdx,
- LLVMGEPGetNoWrapFlags(Cst));
+ return LLVMConstPtrAddFromIndices(LLVMGetModuleDataLayout(M), ElemTy, Ptr,
+ Idx.data(), NumIdx,
+ LLVMGEPGetNoWrapFlags(Cst));
}
default:
fprintf(stderr, "%d is not a supported opcode for constant expressions\n",
diff --git a/llvm/unittests/IR/ConstantsTest.cpp b/llvm/unittests/IR/ConstantsTest.cpp
index 0f1cefb234a79..920385c4caaab 100644
--- a/llvm/unittests/IR/ConstantsTest.cpp
+++ b/llvm/unittests/IR/ConstantsTest.cpp
@@ -998,4 +998,32 @@ TEST(ConstantsTest, GetElementPtrDataLayout) {
EXPECT_EQ(nullptr, ConstantExpr::getGetElementPtr(DL, I8, Ptr, PtrToInt32));
}
+TEST(ConstantsTest, PtrAddCAPI) {
+ LLVMContext Context;
+ DataLayout DL;
+ Module M("", Context);
+
+ Type *I8 = Type::getInt8Ty(Context);
+ Type *I32 = Type::getInt32Ty(Context);
+ Type *I64 = Type::getInt64Ty(Context);
+ Constant *Ptr = M.getOrInsertGlobal("dummy", I8);
+ Constant *PtrToInt = ConstantExpr::getPtrToInt(Ptr, I64);
+ Constant *I64_1 = ConstantInt::get(I64, 1);
+
+ EXPECT_EQ(
+ unwrap(LLVMConstPtrAdd(wrap(Ptr), wrap(I64_1), LLVMGEPFlagNUW)),
+ ConstantExpr::getPtrAdd(Ptr, I64_1, GEPNoWrapFlags::noUnsignedWrap()));
+
+ LLVMValueRef Indices[1] = {wrap(I64_1)};
+ EXPECT_EQ(unwrap(LLVMConstPtrAddFromIndices(wrap(&DL), wrap(I32), wrap(Ptr),
+ Indices, 1, LLVMGEPFlagInBounds)),
+ ConstantExpr::getGetElementPtr(DL, I32, Ptr, I64_1,
+ GEPNoWrapFlags::inBounds()));
+
+ LLVMValueRef Indices2[1] = {wrap(PtrToInt)};
+ EXPECT_EQ(unwrap(LLVMConstPtrAddFromIndices(wrap(&DL), wrap(I32), wrap(Ptr),
+ Indices2, 1, 0)),
+ nullptr);
+}
+
} // end anonymous namespace
>From 5dc551e9e323e9d9d65019104508510bfd126e17 Mon Sep 17 00:00:00 2001
From: Nikita Popov <npopov at redhat.com>
Date: Mon, 5 Oct 2026 10:19:10 +0200
Subject: [PATCH 2/4] Fixes
---
llvm/docs/ReleaseNotes.md | 4 ++--
llvm/include/llvm-c/Core.h | 2 +-
llvm/lib/IR/Core.cpp | 10 ++++++----
3 files changed, 9 insertions(+), 7 deletions(-)
diff --git a/llvm/docs/ReleaseNotes.md b/llvm/docs/ReleaseNotes.md
index d1797ef165f06..4dd657c0f5843 100644
--- a/llvm/docs/ReleaseNotes.md
+++ b/llvm/docs/ReleaseNotes.md
@@ -314,9 +314,9 @@ Makes programs 10x faster by doing Special New Thing.
`set_data_layout` now accepts a `DataLayout` instead of a `string`. You can
use `DataLayout.of_string` and `DataLayout.as_string` to convert between them.
-* `const_gep` and `const_inbounds_gep` have been removed in favor of
+* `const_gep` and `const_in_bounds_gep` have been removed in favor of
`const_ptradd` and `const_ptradd_from_indices`. Both create `getelementptr i8`
- constant expressions, the former using an integero ffset, and the latter using
+ constant expressions, the former using an integer offset, and the latter using
a data layout, base type and index sequence. The latter API returns an option,
as it may fail if the indices cannot be converted into ptradd representation.
diff --git a/llvm/include/llvm-c/Core.h b/llvm/include/llvm-c/Core.h
index b359267543e73..8d55f33e553ae 100644
--- a/llvm/include/llvm-c/Core.h
+++ b/llvm/include/llvm-c/Core.h
@@ -18,8 +18,8 @@
#include "llvm-c/Deprecated.h"
#include "llvm-c/ErrorHandling.h"
#include "llvm-c/ExternC.h"
-#include "llvm-c/Visibility.h"
#include "llvm-c/Types.h"
+#include "llvm-c/Visibility.h"
LLVM_C_EXTERN_C_BEGIN
diff --git a/llvm/lib/IR/Core.cpp b/llvm/lib/IR/Core.cpp
index 87c1ba389985d..3aab78bdf2d2a 100644
--- a/llvm/lib/IR/Core.cpp
+++ b/llvm/lib/IR/Core.cpp
@@ -1952,10 +1952,12 @@ LLVMValueRef LLVMConstPtrAdd(LLVMValueRef ConstantVal,
mapFromLLVMGEPNoWrapFlags(NoWrapFlags)));
}
-LLVM_C_ABI LLVMValueRef LLVMConstPtrAddFromIndices(
- LLVMTargetDataRef DataLayout, LLVMTypeRef Ty, LLVMValueRef ConstantVal,
- LLVMValueRef *ConstantIndices, unsigned NumIndices,
- LLVMGEPNoWrapFlags NoWrapFlags) {
+LLVMValueRef LLVMConstPtrAddFromIndices(LLVMTargetDataRef DataLayout,
+ LLVMTypeRef Ty,
+ LLVMValueRef ConstantVal,
+ LLVMValueRef *ConstantIndices,
+ unsigned NumIndices,
+ LLVMGEPNoWrapFlags NoWrapFlags) {
ArrayRef<Constant *> IdxList(unwrap<Constant>(ConstantIndices, NumIndices),
NumIndices);
return wrap(ConstantExpr::getGetElementPtr(
>From b6542491be95d601304f16c6ac9563f1e8eeb7d4 Mon Sep 17 00:00:00 2001
From: Nikita Popov <npopov at redhat.com>
Date: Mon, 5 Oct 2026 10:22:19 +0200
Subject: [PATCH 3/4] Mention deprecation of LLVMConstGEPWithNoWrapFlags() as
well
---
llvm/docs/ReleaseNotes.md | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/llvm/docs/ReleaseNotes.md b/llvm/docs/ReleaseNotes.md
index 4dd657c0f5843..7c09b303442a3 100644
--- a/llvm/docs/ReleaseNotes.md
+++ b/llvm/docs/ReleaseNotes.md
@@ -331,7 +331,8 @@ Makes programs 10x faster by doing Special New Thing.
* Bindings operating on data layout (`LLVMTargetDataRef`) have been moved
from `Target.h` (`Target` library) to `Core.h` (`IR` library).
-* `LLVMConstGEP2()` and `LLVMConstInBoundsGEP2()` have been deprecated.
+* `LLVMConstGEP2()`, `LLVMConstInBoundsGEP2()` and
+ `LLVMConstGEPWithNoWrapFlags()` have been deprecated.
`LLVMConstPtrAdd()` and `LLVMConstPtrAddFromIndices()` can be used instead.
Both create `getelementptr i8` constant expressions, the former using an
integer offset, and the latter using a data layout, base type and index
>From d1a7d9c75e26569218d25b37138d1db20564e29a Mon Sep 17 00:00:00 2001
From: Nikita Popov <npopov at redhat.com>
Date: Mon, 5 Oct 2026 11:07:43 +0200
Subject: [PATCH 4/4] Add GEPNoWrapFlags.none
---
llvm/bindings/ocaml/llvm/llvm.ml | 1 +
llvm/bindings/ocaml/llvm/llvm.mli | 9 +++++----
llvm/test/Bindings/OCaml/core.ml | 9 ++++++---
3 files changed, 12 insertions(+), 7 deletions(-)
diff --git a/llvm/bindings/ocaml/llvm/llvm.ml b/llvm/bindings/ocaml/llvm/llvm.ml
index f1a985be81aa0..574fa149a47c6 100644
--- a/llvm/bindings/ocaml/llvm/llvm.ml
+++ b/llvm/bindings/ocaml/llvm/llvm.ml
@@ -356,6 +356,7 @@ module ModuleFlagBehavior = struct
end
module GEPNoWrapFlags = struct
+ let none = 0
let inbounds = 1
let nusw = 2
let nuw = 4
diff --git a/llvm/bindings/ocaml/llvm/llvm.mli b/llvm/bindings/ocaml/llvm/llvm.mli
index 25104ed53e1e1..ca525043caf3f 100644
--- a/llvm/bindings/ocaml/llvm/llvm.mli
+++ b/llvm/bindings/ocaml/llvm/llvm.mli
@@ -395,6 +395,7 @@ module ModuleFlagBehavior :sig
end
module GEPNoWrapFlags : sig
+ val none : int
val inbounds : int
val nusw : int
val nuw : int
@@ -1206,16 +1207,16 @@ val const_xor : llvalue -> llvalue -> llvalue
(** [const_ptradd pc offset flags] returns the constant ptradd
(getelementptr i8) of [pc] with constant [offset] and the given
- {!GEPNoWrapFlags} no-wrap flags (combined with [lor], or [0] for none).
+ {!GEPNoWrapFlags} no-wrap flags (combined with [lor]).
See the method [llvm::ConstantExpr::getPtrAdd]. *)
val const_ptradd : llvalue -> llvalue -> int -> llvalue
(** [const_ptradd_from_indices dl srcty pc indices flags] returns the constant
ptradd of [pc] with the offset derived from the data layout [dl], the
source element type [srcty] and the constant integers indices from the
- array [indices]. The flags are {!GEPNoWrapFlags} (combined with [lor], or
- [0] for none). The result may be [None] if the indices cannot be converted
- to ptradd representation.
+ array [indices]. The flags are {!GEPNoWrapFlags} (combined with [lor]).
+ The result may be [None] if the indices cannot be converted to ptradd
+ representation.
See the method [llvm::ConstantExpr::getGetElementPtr]. *)
val const_ptradd_from_indices : DataLayout.t -> lltype -> llvalue ->
llvalue array -> int -> llvalue option
diff --git a/llvm/test/Bindings/OCaml/core.ml b/llvm/test/Bindings/OCaml/core.ml
index 7c1a683aa601d..31e5dd8ae87ae 100644
--- a/llvm/test/Bindings/OCaml/core.ml
+++ b/llvm/test/Bindings/OCaml/core.ml
@@ -297,7 +297,8 @@ let test_constants () =
ignore (define_global "const_trunc" (const_trunc (const_add foldbomb five)
i8_type) m);
ignore (define_global "const_ptrtoint" (const_ptrtoint
- (const_ptradd (const_null (pointer_type context)) (const_int i32_type 1) 0)
+ (const_ptradd (const_null (pointer_type context)) (const_int i32_type 1)
+ GEPNoWrapFlags.none)
i32_type) m);
ignore (define_global "const_inttoptr" (const_inttoptr (const_add foldbomb five)
void_ptr) m);
@@ -315,7 +316,8 @@ let test_constants () =
* CHECK: const_insertelement{{.*}}insertelement
* CHECK: const_shufflevector = global <4 x i32> <i32 0, i32 1, i32 1, i32 0>
*)
- ignore (define_global "const_ptradd" (const_ptradd foldbomb_gv five 0) m);
+ ignore (define_global "const_ptradd"
+ (const_ptradd foldbomb_gv five GEPNoWrapFlags.none) m);
ignore (define_global "const_ptradd_inbounds"
(const_ptradd foldbomb_gv five GEPNoWrapFlags.inbounds) m);
ignore (define_global "const_ptradd_inbounds_nuw"
@@ -327,7 +329,8 @@ let test_constants () =
m);
assert (Option.is_none (const_ptradd_from_indices (data_layout m) i32_type
foldbomb_gv
- [| (const_ptrtoint foldbomb_gv i32_type) |] 0));
+ [| (const_ptrtoint foldbomb_gv i32_type) |]
+ GEPNoWrapFlags.none));
let zero = const_int i32_type 0 in
let one = const_int i32_type 1 in
ignore (define_global "const_extractelement" (const_extractelement
More information about the llvm-commits
mailing list