[llvm] [llubi] Global variables with simple initializers and global-address constants (PR #200547)
Zhige Chen via llvm-commits
llvm-commits at lists.llvm.org
Tue Jun 2 01:47:28 PDT 2026
https://github.com/nofe1248 updated https://github.com/llvm/llvm-project/pull/200547
>From 6718323b1a69d7748c821fce75a0aadc40d6f540 Mon Sep 17 00:00:00 2001
From: Zhige Chen <zhigec_cpp at outlook.com>
Date: Sat, 30 May 2026 15:10:47 +0800
Subject: [PATCH 1/5] [llubi] Global variables with simple initializers &
address constants
---
llvm/test/tools/llubi/global.ll | 25 +++++++
.../test/tools/llubi/global_constant_store.ll | 14 ++++
.../llubi/global_constexpr_initializer.ll | 10 +++
llvm/tools/llubi/lib/Context.cpp | 70 ++++++++++++++++++-
llvm/tools/llubi/lib/Context.h | 2 +
llvm/tools/llubi/lib/ExecutorBase.cpp | 6 ++
6 files changed, 126 insertions(+), 1 deletion(-)
create mode 100644 llvm/test/tools/llubi/global.ll
create mode 100644 llvm/test/tools/llubi/global_constant_store.ll
create mode 100644 llvm/test/tools/llubi/global_constexpr_initializer.ll
diff --git a/llvm/test/tools/llubi/global.ll b/llvm/test/tools/llubi/global.ll
new file mode 100644
index 0000000000000..ddb707f4e5fdc
--- /dev/null
+++ b/llvm/test/tools/llubi/global.ll
@@ -0,0 +1,25 @@
+; RUN: llubi --verbose < %s 2>&1 | FileCheck %s
+
+target datalayout = "e-p:64:64:64-i32:32:32"
+
+ at value = global i32 41
+ at value_ptr = global ptr @value
+ at aggregate = global { i32, [2 x i8] } { i32 7, [2 x i8] c"hi" }
+
+define void @main() {
+ %initial = load i32, ptr @value
+ store i32 42, ptr @value
+ %ptr = load ptr, ptr @value_ptr
+ %updated = load i32, ptr %ptr
+ %aggregate_value = load { i32, [2 x i8] }, ptr @aggregate
+ ret void
+}
+
+; CHECK: Entering function: main
+; CHECK-NEXT: %initial = load i32, ptr @value, align 4 => i32 41
+; CHECK-NEXT: store i32 42, ptr @value, align 4
+; CHECK-NEXT: %ptr = load ptr, ptr @value_ptr, align 8 => ptr 0x8 [value]
+; CHECK-NEXT: %updated = load i32, ptr %ptr, align 4 => i32 42
+; CHECK-NEXT: %aggregate_value = load { i32, [2 x i8] }, ptr @aggregate, align 4 => { i32 7, { i8 104, i8 105 } }
+; CHECK-NEXT: ret void
+; CHECK-NEXT: Exiting function: main
diff --git a/llvm/test/tools/llubi/global_constant_store.ll b/llvm/test/tools/llubi/global_constant_store.ll
new file mode 100644
index 0000000000000..bf5f6322bb014
--- /dev/null
+++ b/llvm/test/tools/llubi/global_constant_store.ll
@@ -0,0 +1,14 @@
+; RUN: not llubi --verbose < %s 2>&1 | FileCheck %s
+
+ at constant = constant i32 1
+
+define void @main() {
+ store i32 2, ptr @constant
+ ret void
+}
+
+; CHECK: Entering function: main
+; CHECK-NEXT: Stacktrace:
+; CHECK-NEXT: #0 store i32 2, ptr @constant, align 4 at @main
+; CHECK-NEXT: Immediate UB detected: Try to write to a constant memory object at address 0x8.
+; CHECK-NEXT: error: Execution of function 'main' failed.
diff --git a/llvm/test/tools/llubi/global_constexpr_initializer.ll b/llvm/test/tools/llubi/global_constexpr_initializer.ll
new file mode 100644
index 0000000000000..c4b2ee2e78384
--- /dev/null
+++ b/llvm/test/tools/llubi/global_constexpr_initializer.ll
@@ -0,0 +1,10 @@
+; RUN: not llubi < %s 2>&1 | FileCheck %s
+
+ at value = global i32 0
+ at aggregate = global [1 x ptr] [ptr getelementptr (i32, ptr @value, i64 1)]
+
+define void @main() {
+ ret void
+}
+
+; CHECK: error: Failed to initialize global values
diff --git a/llvm/tools/llubi/lib/Context.cpp b/llvm/tools/llubi/lib/Context.cpp
index fbb952f9ccc75..cf6b5042690f8 100644
--- a/llvm/tools/llubi/lib/Context.cpp
+++ b/llvm/tools/llubi/lib/Context.cpp
@@ -21,6 +21,37 @@ Context::Context(Module &M, const AsmParserContext *ParserContext)
Context::~Context() = default;
+bool Context::isSupportedGlobalInitializer(Constant *C) const {
+ if (isa<PoisonValue, ConstantAggregateZero, ConstantPointerNull, ConstantInt,
+ ConstantFP>(C))
+ return true;
+
+ if (auto const *CDS = dyn_cast<ConstantDataSequential>(C)) {
+ for (uint32_t I = 0, E = CDS->getNumElements(); I != E; ++I)
+ if (!isSupportedGlobalInitializer(CDS->getElementAsConstant(I)))
+ return false;
+ return true;
+ }
+
+ if (auto *CA = dyn_cast<ConstantAggregate>(C)) {
+ for (Value *Op : CA->operands())
+ if (!isSupportedGlobalInitializer(cast<Constant>(Op)))
+ return false;
+ return true;
+ }
+
+ if (auto const *BA = dyn_cast<BlockAddress>(C))
+ return BlockAddrMap.contains(BA->getBasicBlock());
+
+ if (auto const *GV = dyn_cast<GlobalVariable>(C))
+ return GlobalAddrMap.contains(GV);
+
+ if (auto const *F = dyn_cast<Function>(C))
+ return FuncAddrMap.contains(F);
+
+ return false;
+}
+
bool Context::initGlobalValues() {
// Register all function and block targets that may be used by indirect calls
// and branches.
@@ -49,7 +80,41 @@ bool Context::initGlobalValues() {
BlockAddrMap.try_emplace(&BB, deriveFromMemoryObject(BlockObj));
}
}
- // TODO: initialize global variables.
+
+ for (GlobalVariable &GV : M.globals()) {
+ if (!GV.hasInitializer())
+ continue;
+
+ Type *ValueTy = GV.getValueType();
+ uint64_t const Size = getEffectiveTypeAllocSize(ValueTy);
+ Align Alignment = GV.getPointerAlignment(DL);
+ auto const Obj =
+ allocate(Size, Alignment.value(), GV.getName(), GV.getAddressSpace(),
+ MemInitKind::Zeroed, MemAllocKind::Global);
+
+ if (!Obj)
+ return false;
+
+ Obj->setIsConstant(GV.isConstant());
+ GlobalAddrMap.try_emplace(&GV, deriveFromMemoryObject(Obj));
+ }
+
+ for (GlobalVariable &GV : M.globals()) {
+ if (!GV.hasInitializer())
+ continue;
+
+ MemoryObject *Obj = GlobalAddrMap.at(&GV).getMemoryObject();
+ assert(Obj && "global pointer should have memory object provenance");
+
+ Constant *Init = GV.getInitializer();
+
+ // TODO: Constant expression support
+ if (!isSupportedGlobalInitializer(Init))
+ return false;
+
+ AnyValue InitVal = getConstantValue(Init);
+ store(*Obj, 0, InitVal, GV.getValueType());
+ }
return true;
}
@@ -96,6 +161,9 @@ AnyValue Context::getConstantValueImpl(Constant *C) {
if (auto *BA = dyn_cast<BlockAddress>(C))
return BlockAddrMap.at(BA->getBasicBlock());
+ if (auto *GV = dyn_cast<GlobalVariable>(C))
+ return GlobalAddrMap.at(GV);
+
if (auto *F = dyn_cast<Function>(C))
return FuncAddrMap.at(F);
diff --git a/llvm/tools/llubi/lib/Context.h b/llvm/tools/llubi/lib/Context.h
index 78d99f2cc5f13..72e0e21ea74fa 100644
--- a/llvm/tools/llubi/lib/Context.h
+++ b/llvm/tools/llubi/lib/Context.h
@@ -251,6 +251,8 @@ class Context {
ValidFuncTargets;
DenseMap<uint64_t, std::pair<BasicBlock *, IntrusiveRefCntPtr<MemoryObject>>>
ValidBlockTargets;
+ DenseMap<GlobalVariable *, Pointer> GlobalAddrMap;
+ bool isSupportedGlobalInitializer(Constant *C) const;
AnyValue getConstantValueImpl(Constant *C);
// Floating-point environment
diff --git a/llvm/tools/llubi/lib/ExecutorBase.cpp b/llvm/tools/llubi/lib/ExecutorBase.cpp
index 3b5a4c6ab0dd5..8ff4d931e191b 100644
--- a/llvm/tools/llubi/lib/ExecutorBase.cpp
+++ b/llvm/tools/llubi/lib/ExecutorBase.cpp
@@ -145,6 +145,12 @@ void ExecutorBase::store(const AnyValue &Ptr, Align Alignment,
<< "Invalid memory access via a pointer with nullary provenance.";
return;
}
+ if (MO->isConstant()) {
+ reportImmediateUB()
+ << "Try to write to a constant memory object at address 0x"
+ << Twine::utohexstr(PtrVal.address().getZExtValue()) << ".";
+ return;
+ }
// TODO: pointer capability check
if (auto Offset =
verifyMemAccess(*MO, PtrVal.address(),
>From f221b87bf25bbe4b10f13ea88295b7ca4e4e5f96 Mon Sep 17 00:00:00 2001
From: Zhige Chen <zhige_chen at outlook.com>
Date: Sat, 30 May 2026 16:44:10 +0800
Subject: [PATCH 2/5] [llubi] Address comments
---
llvm/test/tools/llubi/controlflow.ll | 30 ++---
llvm/test/tools/llubi/global.ll | 2 +-
.../test/tools/llubi/global_constant_store.ll | 2 +-
llvm/test/tools/llubi/global_external.ll | 20 +++
llvm/tools/llubi/lib/Context.cpp | 115 ++++++++----------
llvm/tools/llubi/lib/Context.h | 15 ++-
llvm/tools/llubi/lib/ExecutorBase.cpp | 5 +-
llvm/tools/llubi/lib/Interpreter.cpp | 10 +-
llvm/tools/llubi/lib/Value.cpp | 2 +
llvm/tools/llubi/lib/Value.h | 5 +
llvm/tools/llubi/llubi.cpp | 9 +-
11 files changed, 125 insertions(+), 90 deletions(-)
create mode 100644 llvm/test/tools/llubi/global_external.ll
diff --git a/llvm/test/tools/llubi/controlflow.ll b/llvm/test/tools/llubi/controlflow.ll
index 7b14d90b688d9..8a00b30013b16 100644
--- a/llvm/test/tools/llubi/controlflow.ll
+++ b/llvm/test/tools/llubi/controlflow.ll
@@ -243,35 +243,35 @@ exit:
; CHECK-NEXT: to label %next5 unwind label %cleanup jump to %next5
; CHECK-NEXT: indirectbr ptr blockaddress(@main, %exit), [label %exit] jump to %exit
; CHECK-NEXT: Entering function: fib
-; CHECK-NEXT: ptr %self = ptr 0x8 [fib]
+; CHECK-NEXT: ptr %self = ptr 0x8 [@fib]
; CHECK-NEXT: i32 %n = i32 5
; CHECK-NEXT: %cond = icmp ugt i32 %n, 1 => T
; CHECK-NEXT: br i1 %cond, label %if.then, label %if.else jump to %if.then
; CHECK-NEXT: %sub1 = sub i32 %n, 1 => i32 4
; CHECK-NEXT: %sub2 = sub i32 %n, 2 => i32 3
; CHECK-NEXT: Entering function: fib
-; CHECK-NEXT: ptr %self = ptr 0x8 [fib]
+; CHECK-NEXT: ptr %self = ptr 0x8 [@fib]
; CHECK-NEXT: i32 %n = i32 4
; CHECK-NEXT: %cond = icmp ugt i32 %n, 1 => T
; CHECK-NEXT: br i1 %cond, label %if.then, label %if.else jump to %if.then
; CHECK-NEXT: %sub1 = sub i32 %n, 1 => i32 3
; CHECK-NEXT: %sub2 = sub i32 %n, 2 => i32 2
; CHECK-NEXT: Entering function: fib
-; CHECK-NEXT: ptr %self = ptr 0x8 [fib]
+; CHECK-NEXT: ptr %self = ptr 0x8 [@fib]
; CHECK-NEXT: i32 %n = i32 3
; CHECK-NEXT: %cond = icmp ugt i32 %n, 1 => T
; CHECK-NEXT: br i1 %cond, label %if.then, label %if.else jump to %if.then
; CHECK-NEXT: %sub1 = sub i32 %n, 1 => i32 2
; CHECK-NEXT: %sub2 = sub i32 %n, 2 => i32 1
; CHECK-NEXT: Entering function: fib
-; CHECK-NEXT: ptr %self = ptr 0x8 [fib]
+; CHECK-NEXT: ptr %self = ptr 0x8 [@fib]
; CHECK-NEXT: i32 %n = i32 2
; CHECK-NEXT: %cond = icmp ugt i32 %n, 1 => T
; CHECK-NEXT: br i1 %cond, label %if.then, label %if.else jump to %if.then
; CHECK-NEXT: %sub1 = sub i32 %n, 1 => i32 1
; CHECK-NEXT: %sub2 = sub i32 %n, 2 => i32 0
; CHECK-NEXT: Entering function: fib
-; CHECK-NEXT: ptr %self = ptr 0x8 [fib]
+; CHECK-NEXT: ptr %self = ptr 0x8 [@fib]
; CHECK-NEXT: i32 %n = i32 1
; CHECK-NEXT: %cond = icmp ugt i32 %n, 1 => F
; CHECK-NEXT: br i1 %cond, label %if.then, label %if.else jump to %if.else
@@ -279,7 +279,7 @@ exit:
; CHECK-NEXT: Exiting function: fib
; CHECK-NEXT: %res1 = call i32 @fib(ptr %self, i32 %sub1) => i32 1
; CHECK-NEXT: Entering function: fib
-; CHECK-NEXT: ptr %self = ptr 0x8 [fib]
+; CHECK-NEXT: ptr %self = ptr 0x8 [@fib]
; CHECK-NEXT: i32 %n = i32 0
; CHECK-NEXT: %cond = icmp ugt i32 %n, 1 => F
; CHECK-NEXT: br i1 %cond, label %if.then, label %if.else jump to %if.else
@@ -291,7 +291,7 @@ exit:
; CHECK-NEXT: Exiting function: fib
; CHECK-NEXT: %res1 = call i32 @fib(ptr %self, i32 %sub1) => i32 2
; CHECK-NEXT: Entering function: fib
-; CHECK-NEXT: ptr %self = ptr 0x8 [fib]
+; CHECK-NEXT: ptr %self = ptr 0x8 [@fib]
; CHECK-NEXT: i32 %n = i32 1
; CHECK-NEXT: %cond = icmp ugt i32 %n, 1 => F
; CHECK-NEXT: br i1 %cond, label %if.then, label %if.else jump to %if.else
@@ -303,14 +303,14 @@ exit:
; CHECK-NEXT: Exiting function: fib
; CHECK-NEXT: %res1 = call i32 @fib(ptr %self, i32 %sub1) => i32 3
; CHECK-NEXT: Entering function: fib
-; CHECK-NEXT: ptr %self = ptr 0x8 [fib]
+; CHECK-NEXT: ptr %self = ptr 0x8 [@fib]
; CHECK-NEXT: i32 %n = i32 2
; CHECK-NEXT: %cond = icmp ugt i32 %n, 1 => T
; CHECK-NEXT: br i1 %cond, label %if.then, label %if.else jump to %if.then
; CHECK-NEXT: %sub1 = sub i32 %n, 1 => i32 1
; CHECK-NEXT: %sub2 = sub i32 %n, 2 => i32 0
; CHECK-NEXT: Entering function: fib
-; CHECK-NEXT: ptr %self = ptr 0x8 [fib]
+; CHECK-NEXT: ptr %self = ptr 0x8 [@fib]
; CHECK-NEXT: i32 %n = i32 1
; CHECK-NEXT: %cond = icmp ugt i32 %n, 1 => F
; CHECK-NEXT: br i1 %cond, label %if.then, label %if.else jump to %if.else
@@ -318,7 +318,7 @@ exit:
; CHECK-NEXT: Exiting function: fib
; CHECK-NEXT: %res1 = call i32 @fib(ptr %self, i32 %sub1) => i32 1
; CHECK-NEXT: Entering function: fib
-; CHECK-NEXT: ptr %self = ptr 0x8 [fib]
+; CHECK-NEXT: ptr %self = ptr 0x8 [@fib]
; CHECK-NEXT: i32 %n = i32 0
; CHECK-NEXT: %cond = icmp ugt i32 %n, 1 => F
; CHECK-NEXT: br i1 %cond, label %if.then, label %if.else jump to %if.else
@@ -334,21 +334,21 @@ exit:
; CHECK-NEXT: Exiting function: fib
; CHECK-NEXT: %res1 = call i32 @fib(ptr %self, i32 %sub1) => i32 5
; CHECK-NEXT: Entering function: fib
-; CHECK-NEXT: ptr %self = ptr 0x8 [fib]
+; CHECK-NEXT: ptr %self = ptr 0x8 [@fib]
; CHECK-NEXT: i32 %n = i32 3
; CHECK-NEXT: %cond = icmp ugt i32 %n, 1 => T
; CHECK-NEXT: br i1 %cond, label %if.then, label %if.else jump to %if.then
; CHECK-NEXT: %sub1 = sub i32 %n, 1 => i32 2
; CHECK-NEXT: %sub2 = sub i32 %n, 2 => i32 1
; CHECK-NEXT: Entering function: fib
-; CHECK-NEXT: ptr %self = ptr 0x8 [fib]
+; CHECK-NEXT: ptr %self = ptr 0x8 [@fib]
; CHECK-NEXT: i32 %n = i32 2
; CHECK-NEXT: %cond = icmp ugt i32 %n, 1 => T
; CHECK-NEXT: br i1 %cond, label %if.then, label %if.else jump to %if.then
; CHECK-NEXT: %sub1 = sub i32 %n, 1 => i32 1
; CHECK-NEXT: %sub2 = sub i32 %n, 2 => i32 0
; CHECK-NEXT: Entering function: fib
-; CHECK-NEXT: ptr %self = ptr 0x8 [fib]
+; CHECK-NEXT: ptr %self = ptr 0x8 [@fib]
; CHECK-NEXT: i32 %n = i32 1
; CHECK-NEXT: %cond = icmp ugt i32 %n, 1 => F
; CHECK-NEXT: br i1 %cond, label %if.then, label %if.else jump to %if.else
@@ -356,7 +356,7 @@ exit:
; CHECK-NEXT: Exiting function: fib
; CHECK-NEXT: %res1 = call i32 @fib(ptr %self, i32 %sub1) => i32 1
; CHECK-NEXT: Entering function: fib
-; CHECK-NEXT: ptr %self = ptr 0x8 [fib]
+; CHECK-NEXT: ptr %self = ptr 0x8 [@fib]
; CHECK-NEXT: i32 %n = i32 0
; CHECK-NEXT: %cond = icmp ugt i32 %n, 1 => F
; CHECK-NEXT: br i1 %cond, label %if.then, label %if.else jump to %if.else
@@ -368,7 +368,7 @@ exit:
; CHECK-NEXT: Exiting function: fib
; CHECK-NEXT: %res1 = call i32 @fib(ptr %self, i32 %sub1) => i32 2
; CHECK-NEXT: Entering function: fib
-; CHECK-NEXT: ptr %self = ptr 0x8 [fib]
+; CHECK-NEXT: ptr %self = ptr 0x8 [@fib]
; CHECK-NEXT: i32 %n = i32 1
; CHECK-NEXT: %cond = icmp ugt i32 %n, 1 => F
; CHECK-NEXT: br i1 %cond, label %if.then, label %if.else jump to %if.else
diff --git a/llvm/test/tools/llubi/global.ll b/llvm/test/tools/llubi/global.ll
index ddb707f4e5fdc..3cff71b21769f 100644
--- a/llvm/test/tools/llubi/global.ll
+++ b/llvm/test/tools/llubi/global.ll
@@ -18,7 +18,7 @@ define void @main() {
; CHECK: Entering function: main
; CHECK-NEXT: %initial = load i32, ptr @value, align 4 => i32 41
; CHECK-NEXT: store i32 42, ptr @value, align 4
-; CHECK-NEXT: %ptr = load ptr, ptr @value_ptr, align 8 => ptr 0x8 [value]
+; CHECK-NEXT: %ptr = load ptr, ptr @value_ptr, align 8 => ptr 0x8 [@value]
; CHECK-NEXT: %updated = load i32, ptr %ptr, align 4 => i32 42
; CHECK-NEXT: %aggregate_value = load { i32, [2 x i8] }, ptr @aggregate, align 4 => { i32 7, { i8 104, i8 105 } }
; CHECK-NEXT: ret void
diff --git a/llvm/test/tools/llubi/global_constant_store.ll b/llvm/test/tools/llubi/global_constant_store.ll
index bf5f6322bb014..6a8c4e48d0885 100644
--- a/llvm/test/tools/llubi/global_constant_store.ll
+++ b/llvm/test/tools/llubi/global_constant_store.ll
@@ -10,5 +10,5 @@ define void @main() {
; CHECK: Entering function: main
; CHECK-NEXT: Stacktrace:
; CHECK-NEXT: #0 store i32 2, ptr @constant, align 4 at @main
-; CHECK-NEXT: Immediate UB detected: Try to write to a constant memory object at address 0x8.
+; CHECK-NEXT: Immediate UB detected: Try to write to a constant memory object: ptr 0x8 [@constant].
; CHECK-NEXT: error: Execution of function 'main' failed.
diff --git a/llvm/test/tools/llubi/global_external.ll b/llvm/test/tools/llubi/global_external.ll
new file mode 100644
index 0000000000000..5d26be98a2350
--- /dev/null
+++ b/llvm/test/tools/llubi/global_external.ll
@@ -0,0 +1,20 @@
+; RUN: llubi --verbose < %s 2>&1 | FileCheck %s
+
+target datalayout = "e-p:64:64:64-i32:32:32"
+
+ at external = external global i32
+ at external_ptr = global ptr @external
+
+define void @main() {
+ %ptr = load ptr, ptr @external_ptr
+ store i32 42, ptr @external
+ %loaded = load i32, ptr @external
+ ret void
+}
+
+; CHECK: Entering function: main
+; CHECK-NEXT: %ptr = load ptr, ptr @external_ptr, align 8 => ptr 0x8 [@external]
+; CHECK-NEXT: store i32 42, ptr @external, align 4
+; CHECK-NEXT: %loaded = load i32, ptr @external, align 4 => i32 42
+; CHECK-NEXT: ret void
+; CHECK-NEXT: Exiting function: main
diff --git a/llvm/tools/llubi/lib/Context.cpp b/llvm/tools/llubi/lib/Context.cpp
index cf6b5042690f8..f693c60c49ab8 100644
--- a/llvm/tools/llubi/lib/Context.cpp
+++ b/llvm/tools/llubi/lib/Context.cpp
@@ -21,37 +21,6 @@ Context::Context(Module &M, const AsmParserContext *ParserContext)
Context::~Context() = default;
-bool Context::isSupportedGlobalInitializer(Constant *C) const {
- if (isa<PoisonValue, ConstantAggregateZero, ConstantPointerNull, ConstantInt,
- ConstantFP>(C))
- return true;
-
- if (auto const *CDS = dyn_cast<ConstantDataSequential>(C)) {
- for (uint32_t I = 0, E = CDS->getNumElements(); I != E; ++I)
- if (!isSupportedGlobalInitializer(CDS->getElementAsConstant(I)))
- return false;
- return true;
- }
-
- if (auto *CA = dyn_cast<ConstantAggregate>(C)) {
- for (Value *Op : CA->operands())
- if (!isSupportedGlobalInitializer(cast<Constant>(Op)))
- return false;
- return true;
- }
-
- if (auto const *BA = dyn_cast<BlockAddress>(C))
- return BlockAddrMap.contains(BA->getBasicBlock());
-
- if (auto const *GV = dyn_cast<GlobalVariable>(C))
- return GlobalAddrMap.contains(GV);
-
- if (auto const *F = dyn_cast<Function>(C))
- return FuncAddrMap.contains(F);
-
- return false;
-}
-
bool Context::initGlobalValues() {
// Register all function and block targets that may be used by indirect calls
// and branches.
@@ -60,7 +29,7 @@ bool Context::initGlobalValues() {
// TODO: Use precise alignment for function pointers if it is necessary.
auto FuncObj = allocate(0, F.getPointerAlignment(DL).value(), F.getName(),
DL.getProgramAddressSpace(), MemInitKind::Zeroed,
- MemAllocKind::Global);
+ MemAllocKind::Global, /*IsGlobalValue=*/true);
if (!FuncObj)
return false;
ValidFuncTargets.try_emplace(FuncObj->getAddress(),
@@ -72,7 +41,7 @@ bool Context::initGlobalValues() {
if (!BB.hasAddressTaken())
continue;
auto BlockObj = allocate(0, 1, BB.getName(), DL.getProgramAddressSpace(),
- MemInitKind::Zeroed, MemAllocKind::Global);
+ MemInitKind::Zeroed, MemAllocKind::BlockAddress);
if (!BlockObj)
return false;
ValidBlockTargets.try_emplace(BlockObj->getAddress(),
@@ -82,15 +51,14 @@ bool Context::initGlobalValues() {
}
for (GlobalVariable &GV : M.globals()) {
- if (!GV.hasInitializer())
- continue;
-
Type *ValueTy = GV.getValueType();
uint64_t const Size = getEffectiveTypeAllocSize(ValueTy);
Align Alignment = GV.getPointerAlignment(DL);
+ auto InitKind =
+ GV.hasInitializer() ? MemInitKind::Zeroed : MemInitKind::Uninitialized;
auto const Obj =
allocate(Size, Alignment.value(), GV.getName(), GV.getAddressSpace(),
- MemInitKind::Zeroed, MemAllocKind::Global);
+ InitKind, MemAllocKind::Global, /*IsGlobalValue=*/true);
if (!Obj)
return false;
@@ -108,17 +76,16 @@ bool Context::initGlobalValues() {
Constant *Init = GV.getInitializer();
- // TODO: Constant expression support
- if (!isSupportedGlobalInitializer(Init))
+ const AnyValue *InitVal = getConstantValue(Init);
+ if (!InitVal)
return false;
- AnyValue InitVal = getConstantValue(Init);
- store(*Obj, 0, InitVal, GV.getValueType());
+ store(*Obj, 0, *InitVal, GV.getValueType());
}
return true;
}
-AnyValue Context::getConstantValueImpl(Constant *C) {
+std::optional<AnyValue> Context::getConstantValueImpl(Constant *C) {
if (isa<PoisonValue>(C))
return AnyValue::getPoisonValue(*this, C->getType());
@@ -145,37 +112,61 @@ AnyValue Context::getConstantValueImpl(Constant *C) {
if (auto *CDS = dyn_cast<ConstantDataSequential>(C)) {
std::vector<AnyValue> Elts;
Elts.reserve(CDS->getNumElements());
- for (uint32_t I = 0, E = CDS->getNumElements(); I != E; ++I)
- Elts.push_back(getConstantValue(CDS->getElementAsConstant(I)));
+ for (uint32_t I = 0, E = CDS->getNumElements(); I != E; ++I) {
+ const AnyValue *Elt = getConstantValue(CDS->getElementAsConstant(I));
+ if (!Elt)
+ return std::nullopt;
+ Elts.push_back(*Elt);
+ }
return std::move(Elts);
}
if (auto *CA = dyn_cast<ConstantAggregate>(C)) {
std::vector<AnyValue> Elts;
Elts.reserve(CA->getNumOperands());
- for (uint32_t I = 0, E = CA->getNumOperands(); I != E; ++I)
- Elts.push_back(getConstantValue(CA->getOperand(I)));
+ for (uint32_t I = 0, E = CA->getNumOperands(); I != E; ++I) {
+ const AnyValue *Elt = getConstantValue(CA->getOperand(I));
+ if (!Elt)
+ return std::nullopt;
+ Elts.push_back(*Elt);
+ }
return std::move(Elts);
}
- if (auto *BA = dyn_cast<BlockAddress>(C))
- return BlockAddrMap.at(BA->getBasicBlock());
+ if (auto *BA = dyn_cast<BlockAddress>(C)) {
+ auto It = BlockAddrMap.find(BA->getBasicBlock());
+ if (It == BlockAddrMap.end())
+ return std::nullopt;
+ return It->second;
+ }
- if (auto *GV = dyn_cast<GlobalVariable>(C))
- return GlobalAddrMap.at(GV);
+ if (auto *GV = dyn_cast<GlobalVariable>(C)) {
+ auto It = GlobalAddrMap.find(GV);
+ if (It == GlobalAddrMap.end())
+ return std::nullopt;
+ return It->second;
+ }
- if (auto *F = dyn_cast<Function>(C))
- return FuncAddrMap.at(F);
+ if (auto *F = dyn_cast<Function>(C)) {
+ auto It = FuncAddrMap.find(F);
+ if (It == FuncAddrMap.end())
+ return std::nullopt;
+ return It->second;
+ }
- llvm_unreachable("Unrecognized constant");
+ return std::nullopt;
}
-const AnyValue &Context::getConstantValue(Constant *C) {
+const AnyValue *Context::getConstantValue(Constant *C) {
auto It = ConstCache.find(C);
if (It != ConstCache.end())
- return It->second;
+ return &It->second;
+
+ std::optional<AnyValue> Val = getConstantValueImpl(C);
+ if (!Val)
+ return nullptr;
- return ConstCache.emplace(C, getConstantValueImpl(C)).first->second;
+ return &ConstCache.emplace(C, std::move(*Val)).first->second;
}
APInt Context::getTag(uint32_t BitWidth, Provenance &Prov) {
@@ -569,11 +560,11 @@ void Context::freeze(AnyValue &Val, Type *Ty) {
MemoryObject::~MemoryObject() = default;
MemoryObject::MemoryObject(uint64_t Addr, uint64_t Size, StringRef Name,
unsigned AS, MemInitKind InitKind,
- MemAllocKind AllocKind)
+ MemAllocKind AllocKind, bool IsGlobalValue)
: Address(Addr), Size(Size), Name(Name), AS(AS),
State(InitKind != MemInitKind::Poisoned ? MemoryObjectState::Alive
: MemoryObjectState::Dead),
- AllocKind(AllocKind) {
+ AllocKind(AllocKind), IsGlobalValue(IsGlobalValue) {
switch (InitKind) {
case MemInitKind::Zeroed:
Bytes.resize(Size, Byte::concrete(0));
@@ -589,15 +580,16 @@ MemoryObject::MemoryObject(uint64_t Addr, uint64_t Size, StringRef Name,
IntrusiveRefCntPtr<MemoryObject>
Context::allocate(uint64_t Size, uint64_t Align, StringRef Name, unsigned AS,
- MemInitKind InitKind, MemAllocKind AllocKind) {
+ MemInitKind InitKind, MemAllocKind AllocKind,
+ bool IsGlobalValue) {
// Even if the memory object is zero-sized, it still occupies a byte to obtain
// a unique address.
uint64_t AllocateSize = std::max(Size, (uint64_t)1);
if (MaxMem != 0 && SaturatingAdd(UsedMem, AllocateSize) >= MaxMem)
return nullptr;
uint64_t AlignedAddr = alignTo(AllocationBase, Align);
- auto MemObj = makeIntrusiveRefCnt<MemoryObject>(AlignedAddr, Size, Name, AS,
- InitKind, AllocKind);
+ auto MemObj = makeIntrusiveRefCnt<MemoryObject>(
+ AlignedAddr, Size, Name, AS, InitKind, AllocKind, IsGlobalValue);
MemoryObjects[AlignedAddr] = MemObj;
AllocationBase = AlignedAddr + AllocateSize;
UsedMem += AllocateSize;
@@ -713,6 +705,7 @@ bool MemoryObject::isStackAllocated() const {
bool MemoryObject::isHeapAllocated() const {
switch (AllocKind) {
case MemAllocKind::Global:
+ case MemAllocKind::BlockAddress:
case MemAllocKind::Stack:
return false;
case MemAllocKind::Malloc:
diff --git a/llvm/tools/llubi/lib/Context.h b/llvm/tools/llubi/lib/Context.h
index 72e0e21ea74fa..f4225fbee3eec 100644
--- a/llvm/tools/llubi/lib/Context.h
+++ b/llvm/tools/llubi/lib/Context.h
@@ -16,6 +16,7 @@
#include "llvm/IR/FPEnv.h"
#include "llvm/IR/Module.h"
#include <map>
+#include <optional>
#include <random>
namespace llvm::ubi {
@@ -28,6 +29,7 @@ enum class MemInitKind {
enum class MemAllocKind {
Global,
+ BlockAddress,
Stack,
Malloc,
New,
@@ -107,6 +109,7 @@ class MemoryObject : public RefCountedBase<MemoryObject> {
MemoryObjectState State;
MemAllocKind AllocKind;
bool IsConstant = false;
+ bool IsGlobalValue = false;
// Tagged provenances related to this memory object.
// It is used to erasing the tags after the memory object is freed.
@@ -116,7 +119,8 @@ class MemoryObject : public RefCountedBase<MemoryObject> {
public:
MemoryObject(uint64_t Addr, uint64_t Size, StringRef Name, unsigned AS,
- MemInitKind InitKind, MemAllocKind AllocKind);
+ MemInitKind InitKind, MemAllocKind AllocKind,
+ bool IsGlobalValue = false);
MemoryObject(const MemoryObject &) = delete;
MemoryObject(MemoryObject &&) = delete;
MemoryObject &operator=(const MemoryObject &) = delete;
@@ -130,6 +134,7 @@ class MemoryObject : public RefCountedBase<MemoryObject> {
MemoryObjectState getState() const { return State; }
void setState(MemoryObjectState S) { State = S; }
MemAllocKind getAllocKind() const { return AllocKind; }
+ bool isGlobalValue() const { return IsGlobalValue; }
bool isConstant() const { return IsConstant; }
void setIsConstant(bool C) { IsConstant = C; }
@@ -252,8 +257,7 @@ class Context {
DenseMap<uint64_t, std::pair<BasicBlock *, IntrusiveRefCntPtr<MemoryObject>>>
ValidBlockTargets;
DenseMap<GlobalVariable *, Pointer> GlobalAddrMap;
- bool isSupportedGlobalInitializer(Constant *C) const;
- AnyValue getConstantValueImpl(Constant *C);
+ std::optional<AnyValue> getConstantValueImpl(Constant *C);
// Floating-point environment
RoundingMode CurrentRoundingMode = RoundingMode::NearestTiesToEven;
@@ -315,11 +319,12 @@ class Context {
uint64_t getEffectiveTypeAllocSize(Type *Ty);
uint64_t getEffectiveTypeStoreSize(Type *Ty);
- const AnyValue &getConstantValue(Constant *C);
+ const AnyValue *getConstantValue(Constant *C);
IntrusiveRefCntPtr<MemoryObject> allocate(uint64_t Size, uint64_t Align,
StringRef Name, unsigned AS,
MemInitKind InitKind,
- MemAllocKind AllocKind);
+ MemAllocKind AllocKind,
+ bool IsGlobalValue = false);
bool free(const MemoryObject &Obj);
/// Derive a pointer from a memory object with offset 0.
/// Please use Pointer's interface for further manipulations.
diff --git a/llvm/tools/llubi/lib/ExecutorBase.cpp b/llvm/tools/llubi/lib/ExecutorBase.cpp
index 8ff4d931e191b..1433526f18d3a 100644
--- a/llvm/tools/llubi/lib/ExecutorBase.cpp
+++ b/llvm/tools/llubi/lib/ExecutorBase.cpp
@@ -146,9 +146,8 @@ void ExecutorBase::store(const AnyValue &Ptr, Align Alignment,
return;
}
if (MO->isConstant()) {
- reportImmediateUB()
- << "Try to write to a constant memory object at address 0x"
- << Twine::utohexstr(PtrVal.address().getZExtValue()) << ".";
+ reportImmediateUB() << "Try to write to a constant memory object: "
+ << PtrVal << ".";
return;
}
// TODO: pointer capability check
diff --git a/llvm/tools/llubi/lib/Interpreter.cpp b/llvm/tools/llubi/lib/Interpreter.cpp
index 3c21f8ff175f7..8b9dc8e8c1335 100644
--- a/llvm/tools/llubi/lib/Interpreter.cpp
+++ b/llvm/tools/llubi/lib/Interpreter.cpp
@@ -150,11 +150,17 @@ class InstExecutor : public InstVisitor<InstExecutor, void>,
const DataLayout &DL;
std::list<Frame> CallStack;
AnyValue None;
+ AnyValue UnsupportedConstantValue;
Library Lib;
const AnyValue &getValue(Value *V) {
- if (auto *C = dyn_cast<Constant>(V))
- return Ctx.getConstantValue(C);
+ if (auto *C = dyn_cast<Constant>(V)) {
+ if (const AnyValue *Val = Ctx.getConstantValue(C))
+ return *Val;
+ reportError() << "Unsupported constant: " << *C << ".";
+ UnsupportedConstantValue = AnyValue::getPoisonValue(Ctx, C->getType());
+ return UnsupportedConstantValue;
+ }
return CurrentFrame->ValueMap.at(V);
}
diff --git a/llvm/tools/llubi/lib/Value.cpp b/llvm/tools/llubi/lib/Value.cpp
index fe8e0f3cff330..f90cd8d9db4a4 100644
--- a/llvm/tools/llubi/lib/Value.cpp
+++ b/llvm/tools/llubi/lib/Value.cpp
@@ -27,6 +27,8 @@ void Pointer::print(raw_ostream &OS) const {
Address.toStringUnsigned(AddrStr, 16);
OS << "ptr 0x" << AddrStr << " [";
if (MemoryObject *Obj = getMemoryObject()) {
+ if (Obj->isGlobalValue())
+ OS << "@";
OS << Obj->getName();
if (Address != Obj->getAddress())
OS << " + " << (Address - Obj->getAddress());
diff --git a/llvm/tools/llubi/lib/Value.h b/llvm/tools/llubi/lib/Value.h
index 60e656342f116..27407251506ce 100644
--- a/llvm/tools/llubi/lib/Value.h
+++ b/llvm/tools/llubi/lib/Value.h
@@ -254,6 +254,11 @@ inline raw_ostream &operator<<(raw_ostream &OS, const AnyValue &V) {
return OS;
}
+inline raw_ostream &operator<<(raw_ostream &OS, const Pointer &P) {
+ P.print(OS);
+ return OS;
+}
+
} // namespace llvm::ubi
#endif
diff --git a/llvm/tools/llubi/llubi.cpp b/llvm/tools/llubi/llubi.cpp
index 5f5e451282714..d96bd2fe9e79b 100644
--- a/llvm/tools/llubi/llubi.cpp
+++ b/llvm/tools/llubi/llubi.cpp
@@ -267,8 +267,13 @@ int main(int argc, char **argv) {
auto *MainFuncTy = FunctionType::get(IntTy, {IntTy, PtrTy}, false);
SmallVector<ubi::AnyValue> Args;
if (EntryFn->getFunctionType() == MainFuncTy) {
- Args.push_back(
- Ctx.getConstantValue(ConstantInt::get(IntTy, InputArgv.size())));
+ const ubi::AnyValue *Argc =
+ Ctx.getConstantValue(ConstantInt::get(IntTy, InputArgv.size()));
+ if (!Argc) {
+ WithColor::error() << "Failed to initialize argc.\n";
+ return 1;
+ }
+ Args.push_back(*Argc);
uint32_t PtrSize = Ctx.getDataLayout().getPointerSize();
uint64_t PtrsSize = PtrSize * (InputArgv.size() + 1);
>From 238f9cdb96aeeed65cb9515aca8407f4deee083d Mon Sep 17 00:00:00 2001
From: Zhige Chen <zhige_chen at outlook.com>
Date: Mon, 1 Jun 2026 14:25:17 +0800
Subject: [PATCH 3/5] [llubi] Address comments again
---
llvm/tools/llubi/lib/Context.cpp | 28 ++++++++--------------------
llvm/tools/llubi/lib/Context.h | 6 +++---
llvm/tools/llubi/lib/Interpreter.cpp | 7 ++++---
llvm/tools/llubi/lib/Value.cpp | 2 +-
llvm/tools/llubi/llubi.cpp | 5 +----
5 files changed, 17 insertions(+), 31 deletions(-)
diff --git a/llvm/tools/llubi/lib/Context.cpp b/llvm/tools/llubi/lib/Context.cpp
index f693c60c49ab8..a6881c91da336 100644
--- a/llvm/tools/llubi/lib/Context.cpp
+++ b/llvm/tools/llubi/lib/Context.cpp
@@ -133,26 +133,14 @@ std::optional<AnyValue> Context::getConstantValueImpl(Constant *C) {
return std::move(Elts);
}
- if (auto *BA = dyn_cast<BlockAddress>(C)) {
- auto It = BlockAddrMap.find(BA->getBasicBlock());
- if (It == BlockAddrMap.end())
- return std::nullopt;
- return It->second;
- }
+ if (auto *BA = dyn_cast<BlockAddress>(C))
+ return BlockAddrMap.at(BA->getBasicBlock());
- if (auto *GV = dyn_cast<GlobalVariable>(C)) {
- auto It = GlobalAddrMap.find(GV);
- if (It == GlobalAddrMap.end())
- return std::nullopt;
- return It->second;
- }
+ if (auto *GV = dyn_cast<GlobalVariable>(C))
+ return GlobalAddrMap.at(GV);
- if (auto *F = dyn_cast<Function>(C)) {
- auto It = FuncAddrMap.find(F);
- if (It == FuncAddrMap.end())
- return std::nullopt;
- return It->second;
- }
+ if (auto *F = dyn_cast<Function>(C))
+ return FuncAddrMap.at(F);
return std::nullopt;
}
@@ -560,11 +548,11 @@ void Context::freeze(AnyValue &Val, Type *Ty) {
MemoryObject::~MemoryObject() = default;
MemoryObject::MemoryObject(uint64_t Addr, uint64_t Size, StringRef Name,
unsigned AS, MemInitKind InitKind,
- MemAllocKind AllocKind, bool IsGlobalValue)
+ MemAllocKind AllocKind, bool IsIRGlobalValue)
: Address(Addr), Size(Size), Name(Name), AS(AS),
State(InitKind != MemInitKind::Poisoned ? MemoryObjectState::Alive
: MemoryObjectState::Dead),
- AllocKind(AllocKind), IsGlobalValue(IsGlobalValue) {
+ AllocKind(AllocKind), IsIRGlobalValue(IsIRGlobalValue) {
switch (InitKind) {
case MemInitKind::Zeroed:
Bytes.resize(Size, Byte::concrete(0));
diff --git a/llvm/tools/llubi/lib/Context.h b/llvm/tools/llubi/lib/Context.h
index f4225fbee3eec..5ceb787285f3f 100644
--- a/llvm/tools/llubi/lib/Context.h
+++ b/llvm/tools/llubi/lib/Context.h
@@ -109,7 +109,7 @@ class MemoryObject : public RefCountedBase<MemoryObject> {
MemoryObjectState State;
MemAllocKind AllocKind;
bool IsConstant = false;
- bool IsGlobalValue = false;
+ bool IsIRGlobalValue = false;
// Tagged provenances related to this memory object.
// It is used to erasing the tags after the memory object is freed.
@@ -120,7 +120,7 @@ class MemoryObject : public RefCountedBase<MemoryObject> {
public:
MemoryObject(uint64_t Addr, uint64_t Size, StringRef Name, unsigned AS,
MemInitKind InitKind, MemAllocKind AllocKind,
- bool IsGlobalValue = false);
+ bool IsIRGlobalValue = false);
MemoryObject(const MemoryObject &) = delete;
MemoryObject(MemoryObject &&) = delete;
MemoryObject &operator=(const MemoryObject &) = delete;
@@ -134,7 +134,7 @@ class MemoryObject : public RefCountedBase<MemoryObject> {
MemoryObjectState getState() const { return State; }
void setState(MemoryObjectState S) { State = S; }
MemAllocKind getAllocKind() const { return AllocKind; }
- bool isGlobalValue() const { return IsGlobalValue; }
+ bool isIRGlobalValue() const { return IsIRGlobalValue; }
bool isConstant() const { return IsConstant; }
void setIsConstant(bool C) { IsConstant = C; }
diff --git a/llvm/tools/llubi/lib/Interpreter.cpp b/llvm/tools/llubi/lib/Interpreter.cpp
index 8b9dc8e8c1335..6f5f74477f48f 100644
--- a/llvm/tools/llubi/lib/Interpreter.cpp
+++ b/llvm/tools/llubi/lib/Interpreter.cpp
@@ -150,7 +150,7 @@ class InstExecutor : public InstVisitor<InstExecutor, void>,
const DataLayout &DL;
std::list<Frame> CallStack;
AnyValue None;
- AnyValue UnsupportedConstantValue;
+ std::list<AnyValue> UnsupportedConstantValues;
Library Lib;
const AnyValue &getValue(Value *V) {
@@ -158,8 +158,9 @@ class InstExecutor : public InstVisitor<InstExecutor, void>,
if (const AnyValue *Val = Ctx.getConstantValue(C))
return *Val;
reportError() << "Unsupported constant: " << *C << ".";
- UnsupportedConstantValue = AnyValue::getPoisonValue(Ctx, C->getType());
- return UnsupportedConstantValue;
+ UnsupportedConstantValues.push_back(
+ AnyValue::getPoisonValue(Ctx, C->getType()));
+ return UnsupportedConstantValues.back();
}
return CurrentFrame->ValueMap.at(V);
}
diff --git a/llvm/tools/llubi/lib/Value.cpp b/llvm/tools/llubi/lib/Value.cpp
index f90cd8d9db4a4..04a1aa803f66c 100644
--- a/llvm/tools/llubi/lib/Value.cpp
+++ b/llvm/tools/llubi/lib/Value.cpp
@@ -27,7 +27,7 @@ void Pointer::print(raw_ostream &OS) const {
Address.toStringUnsigned(AddrStr, 16);
OS << "ptr 0x" << AddrStr << " [";
if (MemoryObject *Obj = getMemoryObject()) {
- if (Obj->isGlobalValue())
+ if (Obj->isIRGlobalValue())
OS << "@";
OS << Obj->getName();
if (Address != Obj->getAddress())
diff --git a/llvm/tools/llubi/llubi.cpp b/llvm/tools/llubi/llubi.cpp
index d96bd2fe9e79b..c433e53167743 100644
--- a/llvm/tools/llubi/llubi.cpp
+++ b/llvm/tools/llubi/llubi.cpp
@@ -269,10 +269,7 @@ int main(int argc, char **argv) {
if (EntryFn->getFunctionType() == MainFuncTy) {
const ubi::AnyValue *Argc =
Ctx.getConstantValue(ConstantInt::get(IntTy, InputArgv.size()));
- if (!Argc) {
- WithColor::error() << "Failed to initialize argc.\n";
- return 1;
- }
+ assert(Argc && "failed to initialize argc");
Args.push_back(*Argc);
uint32_t PtrSize = Ctx.getDataLayout().getPointerSize();
>From 27d6d83e460cb5955ebb18cdd37ecd84da059cd9 Mon Sep 17 00:00:00 2001
From: Zhige Chen <zhige_chen at outlook.com>
Date: Mon, 1 Jun 2026 19:29:39 +0800
Subject: [PATCH 4/5] [llubi] Just some nits
---
llvm/tools/llubi/lib/Context.cpp | 12 ++++++------
llvm/tools/llubi/lib/Context.h | 2 +-
2 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/llvm/tools/llubi/lib/Context.cpp b/llvm/tools/llubi/lib/Context.cpp
index a6881c91da336..aa210aa78e36a 100644
--- a/llvm/tools/llubi/lib/Context.cpp
+++ b/llvm/tools/llubi/lib/Context.cpp
@@ -29,7 +29,7 @@ bool Context::initGlobalValues() {
// TODO: Use precise alignment for function pointers if it is necessary.
auto FuncObj = allocate(0, F.getPointerAlignment(DL).value(), F.getName(),
DL.getProgramAddressSpace(), MemInitKind::Zeroed,
- MemAllocKind::Global, /*IsGlobalValue=*/true);
+ MemAllocKind::Global, /*IsIRGlobalValue=*/true);
if (!FuncObj)
return false;
ValidFuncTargets.try_emplace(FuncObj->getAddress(),
@@ -52,13 +52,13 @@ bool Context::initGlobalValues() {
for (GlobalVariable &GV : M.globals()) {
Type *ValueTy = GV.getValueType();
- uint64_t const Size = getEffectiveTypeAllocSize(ValueTy);
+ const uint64_t Size = getEffectiveTypeAllocSize(ValueTy);
Align Alignment = GV.getPointerAlignment(DL);
auto InitKind =
GV.hasInitializer() ? MemInitKind::Zeroed : MemInitKind::Uninitialized;
- auto const Obj =
+ const auto Obj =
allocate(Size, Alignment.value(), GV.getName(), GV.getAddressSpace(),
- InitKind, MemAllocKind::Global, /*IsGlobalValue=*/true);
+ InitKind, MemAllocKind::Global, /*IsIRGlobalValue=*/true);
if (!Obj)
return false;
@@ -569,7 +569,7 @@ MemoryObject::MemoryObject(uint64_t Addr, uint64_t Size, StringRef Name,
IntrusiveRefCntPtr<MemoryObject>
Context::allocate(uint64_t Size, uint64_t Align, StringRef Name, unsigned AS,
MemInitKind InitKind, MemAllocKind AllocKind,
- bool IsGlobalValue) {
+ bool IsIRGlobalValue) {
// Even if the memory object is zero-sized, it still occupies a byte to obtain
// a unique address.
uint64_t AllocateSize = std::max(Size, (uint64_t)1);
@@ -577,7 +577,7 @@ Context::allocate(uint64_t Size, uint64_t Align, StringRef Name, unsigned AS,
return nullptr;
uint64_t AlignedAddr = alignTo(AllocationBase, Align);
auto MemObj = makeIntrusiveRefCnt<MemoryObject>(
- AlignedAddr, Size, Name, AS, InitKind, AllocKind, IsGlobalValue);
+ AlignedAddr, Size, Name, AS, InitKind, AllocKind, IsIRGlobalValue);
MemoryObjects[AlignedAddr] = MemObj;
AllocationBase = AlignedAddr + AllocateSize;
UsedMem += AllocateSize;
diff --git a/llvm/tools/llubi/lib/Context.h b/llvm/tools/llubi/lib/Context.h
index 5ceb787285f3f..5daa9e816f145 100644
--- a/llvm/tools/llubi/lib/Context.h
+++ b/llvm/tools/llubi/lib/Context.h
@@ -324,7 +324,7 @@ class Context {
StringRef Name, unsigned AS,
MemInitKind InitKind,
MemAllocKind AllocKind,
- bool IsGlobalValue = false);
+ bool IsIRGlobalValue = false);
bool free(const MemoryObject &Obj);
/// Derive a pointer from a memory object with offset 0.
/// Please use Pointer's interface for further manipulations.
>From 7961a7d560a78f5075c02e6dd17e2a958bfb90b7 Mon Sep 17 00:00:00 2001
From: Zhige Chen <zhige_chen at outlook.com>
Date: Tue, 2 Jun 2026 16:03:34 +0800
Subject: [PATCH 5/5] [llubi] Test update
---
llvm/test/tools/llubi/global_external.ll | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/llvm/test/tools/llubi/global_external.ll b/llvm/test/tools/llubi/global_external.ll
index 5d26be98a2350..761f2e82dd691 100644
--- a/llvm/test/tools/llubi/global_external.ll
+++ b/llvm/test/tools/llubi/global_external.ll
@@ -7,14 +7,16 @@ target datalayout = "e-p:64:64:64-i32:32:32"
define void @main() {
%ptr = load ptr, ptr @external_ptr
+ %load1 = load i32, ptr @external
store i32 42, ptr @external
- %loaded = load i32, ptr @external
+ %load2 = load i32, ptr @external
ret void
}
; CHECK: Entering function: main
; CHECK-NEXT: %ptr = load ptr, ptr @external_ptr, align 8 => ptr 0x8 [@external]
+; CHECK-NEXT: %load1 = load i32, ptr @external, align 4 => i32 -1393641077
; CHECK-NEXT: store i32 42, ptr @external, align 4
-; CHECK-NEXT: %loaded = load i32, ptr @external, align 4 => i32 42
+; CHECK-NEXT: %load2 = load i32, ptr @external, align 4 => i32 42
; CHECK-NEXT: ret void
; CHECK-NEXT: Exiting function: main
More information about the llvm-commits
mailing list