[llvm] [llubi] Reject invalid types (PR #230495)
Yingwei Zheng via llvm-commits
llvm-commits at lists.llvm.org
Sun Oct 11 09:30:09 PDT 2026
https://github.com/dtcxzyw updated https://github.com/llvm/llvm-project/pull/230495
>From a6ae7b2f9ad96c078dcdf9b9795a445dfe7f7a42 Mon Sep 17 00:00:00 2001
From: Yingwei Zheng <dtcxzyw2333 at gmail.com>
Date: Fri, 9 Oct 2026 20:58:28 +0800
Subject: [PATCH 1/7] [llubi] Reject invalid types
---
llvm/test/tools/llubi/load_target_ext.ll | 10 +++
.../tools/llubi/shufflevector_large_size.ll | 9 +++
.../tools/llubi/target_ext_extractvalue.ll | 9 +++
.../tools/llubi/target_ext_freeze_poison.ll | 9 +++
llvm/test/tools/llubi/target_ext_global.ll | 10 +++
.../tools/llubi/target_ext_indirect_call.ll | 9 +++
llvm/test/tools/llubi/target_ext_main_arg.ll | 8 ++
llvm/test/tools/llubi/target_ext_return.ll | 8 ++
llvm/test/tools/llubi/target_ext_store.ll | 10 +++
.../tools/llubi/target_ext_store_array.ll | 9 +++
.../target_ext_store_nested_aggregate.ll | 9 +++
.../tools/llubi/target_ext_store_struct.ll | 9 +++
.../llubi/target_ext_store_vector_element.ll | 9 +++
llvm/test/tools/llubi/target_ext_vararg.ll | 13 ++++
.../tools/llubi/vector_reduce_fmax_empty.ll | 9 +++
.../llubi/vector_reduce_fmaximum_empty.ll | 9 +++
llvm/test/tools/llubi/x86_amx_bitcast.ll | 9 +++
llvm/test/tools/llubi/x86_amx_store_struct.ll | 9 +++
llvm/tools/llubi/lib/Context.cpp | 77 +++++++++++++++++++
llvm/tools/llubi/lib/Context.h | 5 ++
llvm/tools/llubi/llubi.cpp | 5 ++
21 files changed, 254 insertions(+)
create mode 100644 llvm/test/tools/llubi/load_target_ext.ll
create mode 100644 llvm/test/tools/llubi/shufflevector_large_size.ll
create mode 100644 llvm/test/tools/llubi/target_ext_extractvalue.ll
create mode 100644 llvm/test/tools/llubi/target_ext_freeze_poison.ll
create mode 100644 llvm/test/tools/llubi/target_ext_global.ll
create mode 100644 llvm/test/tools/llubi/target_ext_indirect_call.ll
create mode 100644 llvm/test/tools/llubi/target_ext_main_arg.ll
create mode 100644 llvm/test/tools/llubi/target_ext_return.ll
create mode 100644 llvm/test/tools/llubi/target_ext_store.ll
create mode 100644 llvm/test/tools/llubi/target_ext_store_array.ll
create mode 100644 llvm/test/tools/llubi/target_ext_store_nested_aggregate.ll
create mode 100644 llvm/test/tools/llubi/target_ext_store_struct.ll
create mode 100644 llvm/test/tools/llubi/target_ext_store_vector_element.ll
create mode 100644 llvm/test/tools/llubi/target_ext_vararg.ll
create mode 100644 llvm/test/tools/llubi/vector_reduce_fmax_empty.ll
create mode 100644 llvm/test/tools/llubi/vector_reduce_fmaximum_empty.ll
create mode 100644 llvm/test/tools/llubi/x86_amx_bitcast.ll
create mode 100644 llvm/test/tools/llubi/x86_amx_store_struct.ll
diff --git a/llvm/test/tools/llubi/load_target_ext.ll b/llvm/test/tools/llubi/load_target_ext.ll
new file mode 100644
index 0000000000000..d89e891cecfe4
--- /dev/null
+++ b/llvm/test/tools/llubi/load_target_ext.ll
@@ -0,0 +1,10 @@
+; NOTE: Assertions have been autogenerated by utils/update_llubi_test_checks.py UTC_ARGS: --version 6
+; RUN: not llubi --verbose < %s 2>&1 | FileCheck %s
+
+define void @main() {
+ %a = alloca i64
+ %v = load target("spirv.Event"), ptr %a
+ ret void
+}
+; CHECK: Unsupported type target("spirv.Event")
+; CHECK-NEXT: error: -: input module cannot be executed!
diff --git a/llvm/test/tools/llubi/shufflevector_large_size.ll b/llvm/test/tools/llubi/shufflevector_large_size.ll
new file mode 100644
index 0000000000000..cf106a4d1e337
--- /dev/null
+++ b/llvm/test/tools/llubi/shufflevector_large_size.ll
@@ -0,0 +1,9 @@
+; RUN: not llubi --verbose < %s 2>&1 | FileCheck %s
+
+define void @main() {
+ %x = shufflevector <vscale x 1073741823 x i32> poison, <vscale x 1073741823 x i32> poison, <vscale x 1 x i32> zeroinitializer
+ ret void
+}
+
+; CHECK: The number of elements of <vscale x 1073741823 x i32> is too large!
+; CHECK-NEXT: error: -: input module cannot be executed!
diff --git a/llvm/test/tools/llubi/target_ext_extractvalue.ll b/llvm/test/tools/llubi/target_ext_extractvalue.ll
new file mode 100644
index 0000000000000..7bfd61bbf51b8
--- /dev/null
+++ b/llvm/test/tools/llubi/target_ext_extractvalue.ll
@@ -0,0 +1,9 @@
+; NOTE: Assertions have been autogenerated by utils/update_llubi_test_checks.py UTC_ARGS: --version 6
+; RUN: not llubi --verbose < %s 2>&1 | FileCheck %s
+
+define void @main() {
+ %x = extractvalue {i32, target("wasm.externref")} undef, 0
+ ret void
+}
+; CHECK: Unsupported type target("wasm.externref")
+; CHECK-NEXT: error: -: input module cannot be executed!
diff --git a/llvm/test/tools/llubi/target_ext_freeze_poison.ll b/llvm/test/tools/llubi/target_ext_freeze_poison.ll
new file mode 100644
index 0000000000000..366aa5340d14d
--- /dev/null
+++ b/llvm/test/tools/llubi/target_ext_freeze_poison.ll
@@ -0,0 +1,9 @@
+; NOTE: Assertions have been autogenerated by utils/update_llubi_test_checks.py UTC_ARGS: --version 6
+; RUN: not llubi --verbose < %s 2>&1 | FileCheck %s
+
+define void @main() {
+ %x = freeze target("wasm.externref") poison
+ ret void
+}
+; CHECK: Unsupported type target("wasm.externref")
+; CHECK-NEXT: error: -: input module cannot be executed!
diff --git a/llvm/test/tools/llubi/target_ext_global.ll b/llvm/test/tools/llubi/target_ext_global.ll
new file mode 100644
index 0000000000000..052a6042f4d60
--- /dev/null
+++ b/llvm/test/tools/llubi/target_ext_global.ll
@@ -0,0 +1,10 @@
+; NOTE: Assertions have been autogenerated by utils/update_llubi_test_checks.py UTC_ARGS: --version 6
+; RUN: not llubi --verbose < %s 2>&1 | FileCheck %s
+
+ at g = global target("wasm.externref") poison
+
+define i32 @main() {
+ ret i32 0
+}
+; CHECK: Unsupported type target("wasm.externref")
+; CHECK-NEXT: error: -: input module cannot be executed!
diff --git a/llvm/test/tools/llubi/target_ext_indirect_call.ll b/llvm/test/tools/llubi/target_ext_indirect_call.ll
new file mode 100644
index 0000000000000..b3fef6e388c30
--- /dev/null
+++ b/llvm/test/tools/llubi/target_ext_indirect_call.ll
@@ -0,0 +1,9 @@
+; NOTE: Assertions have been autogenerated by utils/update_llubi_test_checks.py UTC_ARGS: --version 6
+; RUN: not llubi --verbose < %s 2>&1 | FileCheck %s
+
+define void @main() {
+ call void null(target("wasm.externref") poison)
+ ret void
+}
+; CHECK: Unsupported type target("wasm.externref")
+; CHECK-NEXT: error: -: input module cannot be executed!
diff --git a/llvm/test/tools/llubi/target_ext_main_arg.ll b/llvm/test/tools/llubi/target_ext_main_arg.ll
new file mode 100644
index 0000000000000..2981a324d28b7
--- /dev/null
+++ b/llvm/test/tools/llubi/target_ext_main_arg.ll
@@ -0,0 +1,8 @@
+; NOTE: Assertions have been autogenerated by utils/update_llubi_test_checks.py UTC_ARGS: --version 6
+; RUN: not llubi --verbose < %s 2>&1 | FileCheck %s
+
+define i32 @main(target("wasm.externref") %a) {
+ ret i32 0
+}
+; CHECK: Unsupported type target("wasm.externref")
+; CHECK-NEXT: error: -: input module cannot be executed!
diff --git a/llvm/test/tools/llubi/target_ext_return.ll b/llvm/test/tools/llubi/target_ext_return.ll
new file mode 100644
index 0000000000000..60e3d3564f607
--- /dev/null
+++ b/llvm/test/tools/llubi/target_ext_return.ll
@@ -0,0 +1,8 @@
+; NOTE: Assertions have been autogenerated by utils/update_llubi_test_checks.py UTC_ARGS: --version 6
+; RUN: not llubi --verbose < %s 2>&1 | FileCheck %s
+
+define target("wasm.externref") @main() {
+ ret target("wasm.externref") poison
+}
+; CHECK: Unsupported type target("wasm.externref")
+; CHECK-NEXT: error: -: input module cannot be executed!
diff --git a/llvm/test/tools/llubi/target_ext_store.ll b/llvm/test/tools/llubi/target_ext_store.ll
new file mode 100644
index 0000000000000..883a83436dadc
--- /dev/null
+++ b/llvm/test/tools/llubi/target_ext_store.ll
@@ -0,0 +1,10 @@
+; NOTE: Assertions have been autogenerated by utils/update_llubi_test_checks.py UTC_ARGS: --version 6
+; RUN: not llubi --verbose < %s 2>&1 | FileCheck %s
+
+define void @main() {
+ %a = alloca i8
+ store target("wasm.externref") poison, ptr %a
+ ret void
+}
+; CHECK: Unsupported type target("wasm.externref")
+; CHECK-NEXT: error: -: input module cannot be executed!
diff --git a/llvm/test/tools/llubi/target_ext_store_array.ll b/llvm/test/tools/llubi/target_ext_store_array.ll
new file mode 100644
index 0000000000000..e09730d7bf486
--- /dev/null
+++ b/llvm/test/tools/llubi/target_ext_store_array.ll
@@ -0,0 +1,9 @@
+; NOTE: Assertions have been autogenerated by utils/update_llubi_test_checks.py UTC_ARGS: --version 6
+; RUN: not llubi --verbose < %s 2>&1 | FileCheck %s
+
+define void @main() {
+ store [2 x target("wasm.externref")] poison, ptr null
+ ret void
+}
+; CHECK: Unsupported type target("wasm.externref")
+; CHECK-NEXT: error: -: input module cannot be executed!
diff --git a/llvm/test/tools/llubi/target_ext_store_nested_aggregate.ll b/llvm/test/tools/llubi/target_ext_store_nested_aggregate.ll
new file mode 100644
index 0000000000000..01c6585849983
--- /dev/null
+++ b/llvm/test/tools/llubi/target_ext_store_nested_aggregate.ll
@@ -0,0 +1,9 @@
+; NOTE: Assertions have been autogenerated by utils/update_llubi_test_checks.py UTC_ARGS: --version 6
+; RUN: not llubi --verbose < %s 2>&1 | FileCheck %s
+
+define void @main() {
+ store {i32, [2 x target("wasm.externref")]} poison, ptr null
+ ret void
+}
+; CHECK: Unsupported type target("wasm.externref")
+; CHECK-NEXT: error: -: input module cannot be executed!
diff --git a/llvm/test/tools/llubi/target_ext_store_struct.ll b/llvm/test/tools/llubi/target_ext_store_struct.ll
new file mode 100644
index 0000000000000..02c281bc44329
--- /dev/null
+++ b/llvm/test/tools/llubi/target_ext_store_struct.ll
@@ -0,0 +1,9 @@
+; NOTE: Assertions have been autogenerated by utils/update_llubi_test_checks.py UTC_ARGS: --version 6
+; RUN: not llubi --verbose < %s 2>&1 | FileCheck %s
+
+define void @main() {
+ store {i32, target("wasm.externref")} poison, ptr null
+ ret void
+}
+; CHECK: Unsupported type target("wasm.externref")
+; CHECK-NEXT: error: -: input module cannot be executed!
diff --git a/llvm/test/tools/llubi/target_ext_store_vector_element.ll b/llvm/test/tools/llubi/target_ext_store_vector_element.ll
new file mode 100644
index 0000000000000..9d001b0926840
--- /dev/null
+++ b/llvm/test/tools/llubi/target_ext_store_vector_element.ll
@@ -0,0 +1,9 @@
+; NOTE: Assertions have been autogenerated by utils/update_llubi_test_checks.py UTC_ARGS: --version 6
+; RUN: not llubi --verbose < %s 2>&1 | FileCheck %s
+
+define void @main() {
+ store <2 x target("llvm.test.vectorelement")> poison, ptr null
+ ret void
+}
+; CHECK: Unsupported type <2 x target("llvm.test.vectorelement")>
+; CHECK-NEXT: error: -: input module cannot be executed!
diff --git a/llvm/test/tools/llubi/target_ext_vararg.ll b/llvm/test/tools/llubi/target_ext_vararg.ll
new file mode 100644
index 0000000000000..1d6f6079b2d66
--- /dev/null
+++ b/llvm/test/tools/llubi/target_ext_vararg.ll
@@ -0,0 +1,13 @@
+; NOTE: Assertions have been autogenerated by utils/update_llubi_test_checks.py UTC_ARGS: --version 6
+; RUN: not llubi --verbose < %s 2>&1 | FileCheck %s
+
+ at .str = private constant [3 x i8] c"%d\00"
+
+declare i32 @printf(ptr, ...)
+
+define void @main() {
+ %r = call i32 (ptr, ...) @printf(ptr @.str, target("wasm.externref") poison)
+ ret void
+}
+; CHECK: Unsupported type target("wasm.externref")
+; CHECK-NEXT: error: -: input module cannot be executed!
diff --git a/llvm/test/tools/llubi/vector_reduce_fmax_empty.ll b/llvm/test/tools/llubi/vector_reduce_fmax_empty.ll
new file mode 100644
index 0000000000000..c481bf8890b5d
--- /dev/null
+++ b/llvm/test/tools/llubi/vector_reduce_fmax_empty.ll
@@ -0,0 +1,9 @@
+; NOTE: Assertions have been autogenerated by utils/update_llubi_test_checks.py UTC_ARGS: --version 6
+; RUN: not llubi --verbose < %s 2>&1 | FileCheck %s
+
+define void @main() {
+ %r = call float @llvm.vector.reduce.fmax.nxv1073741824f32(<vscale x 1073741824 x float> zeroinitializer)
+ ret void
+}
+; CHECK: The number of elements of <vscale x 1073741824 x float> is too large!
+; CHECK-NEXT: error: -: input module cannot be executed!
diff --git a/llvm/test/tools/llubi/vector_reduce_fmaximum_empty.ll b/llvm/test/tools/llubi/vector_reduce_fmaximum_empty.ll
new file mode 100644
index 0000000000000..b383f90f3ef27
--- /dev/null
+++ b/llvm/test/tools/llubi/vector_reduce_fmaximum_empty.ll
@@ -0,0 +1,9 @@
+; NOTE: Assertions have been autogenerated by utils/update_llubi_test_checks.py UTC_ARGS: --version 6
+; RUN: not llubi --verbose < %s 2>&1 | FileCheck %s
+
+define void @main() {
+ %r = call float @llvm.vector.reduce.fmaximum.nxv1073741824f32(<vscale x 1073741824 x float> zeroinitializer)
+ ret void
+}
+; CHECK: The number of elements of <vscale x 1073741824 x float> is too large!
+; CHECK-NEXT: error: -: input module cannot be executed!
diff --git a/llvm/test/tools/llubi/x86_amx_bitcast.ll b/llvm/test/tools/llubi/x86_amx_bitcast.ll
new file mode 100644
index 0000000000000..0263648936776
--- /dev/null
+++ b/llvm/test/tools/llubi/x86_amx_bitcast.ll
@@ -0,0 +1,9 @@
+; NOTE: Assertions have been autogenerated by utils/update_llubi_test_checks.py UTC_ARGS: --version 6
+; RUN: not llubi --verbose < %s 2>&1 | FileCheck %s
+
+define void @main() {
+ %x = bitcast x86_amx poison to i8192
+ ret void
+}
+; CHECK: Unsupported type x86_amx
+; CHECK-NEXT: error: -: input module cannot be executed!
diff --git a/llvm/test/tools/llubi/x86_amx_store_struct.ll b/llvm/test/tools/llubi/x86_amx_store_struct.ll
new file mode 100644
index 0000000000000..cd8065d8534b1
--- /dev/null
+++ b/llvm/test/tools/llubi/x86_amx_store_struct.ll
@@ -0,0 +1,9 @@
+; NOTE: Assertions have been autogenerated by utils/update_llubi_test_checks.py UTC_ARGS: --version 6
+; RUN: not llubi --verbose < %s 2>&1 | FileCheck %s
+
+define void @main() {
+ store {i32, x86_amx} poison, ptr null
+ ret void
+}
+; CHECK: Unsupported type x86_amx
+; CHECK-NEXT: error: -: input module cannot be executed!
diff --git a/llvm/tools/llubi/lib/Context.cpp b/llvm/tools/llubi/lib/Context.cpp
index e78263a2bab76..d70d054b4887f 100644
--- a/llvm/tools/llubi/lib/Context.cpp
+++ b/llvm/tools/llubi/lib/Context.cpp
@@ -1270,6 +1270,83 @@ uint64_t Context::getEffectiveTypeStoreSize(Type *Ty) {
return getEffectiveTypeSize(DL.getTypeStoreSize(Ty));
}
+bool Context::isValid(raw_ostream &OS) const {
+ assert(isPowerOf2_32(VScale) && "VScale must be a power of two.");
+ uint32_t MaxNumElements = UINT32_MAX / VScale;
+
+ SmallPtrSet<Type *, 16> ValidAggTys;
+ auto IsSupportedType = [&](auto &&Self, Type *Ty) {
+ switch (Ty->getTypeID()) {
+ case Type::X86_AMXTyID:
+ case Type::TargetExtTyID:
+ OS << "Unsupported type " << *Ty << '\n';
+ return false;
+ case Type::ScalableVectorTyID:
+ // Avoid overflow when computing EVL.
+ if (cast<VectorType>(Ty)->getElementCount().getKnownMinValue() >=
+ MaxNumElements) {
+ OS << "The number of elements of " << *Ty << " is too large!\n";
+ return false;
+ }
+ [[fallthrough]];
+ case Type::FixedVectorTyID:
+ if (cast<VectorType>(Ty)->getElementType()->isTargetExtTy()) {
+ OS << "Unsupported type " << *Ty << '\n';
+ return false;
+ }
+ return true;
+ case Type::StructTyID:
+ case Type::ArrayTyID:
+ if (ValidAggTys.contains(Ty))
+ return true;
+ for (unsigned I = 0, E = Ty->getNumContainedTypes(); I != E; ++I)
+ if (!Self(Self, Ty->getContainedType(I)))
+ return false;
+ ValidAggTys.insert(Ty);
+ return true;
+ default:
+ return true;
+ }
+ };
+
+#define CHECK(TYPE) \
+ if (!IsSupportedType(IsSupportedType, TYPE)) \
+ return false
+
+ for (auto &F : M) {
+ CHECK(F.getReturnType());
+ for (auto &Arg : F.args())
+ CHECK(Arg.getType());
+ for (auto &BB : F)
+ for (auto &I : BB) {
+ CHECK(I.getType());
+ switch (I.getOpcode()) {
+ case Instruction::Call:
+ case Instruction::Invoke:
+ for (auto &Op : I.operands())
+ CHECK(Op->getType());
+ break;
+ case Instruction::Store:
+ case Instruction::ExtractElement:
+ case Instruction::ExtractValue:
+ case Instruction::BitCast:
+ case Instruction::ShuffleVector:
+ CHECK(I.getOperand(0)->getType());
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ for (auto &G : M.globals())
+ CHECK(G.getValueType());
+
+#undef CHECK
+
+ return true;
+}
+
RoundingMode Context::getCurrentRoundingMode() const {
return CurrentRoundingMode;
}
diff --git a/llvm/tools/llubi/lib/Context.h b/llvm/tools/llubi/lib/Context.h
index 571be140cc83f..10c6effea90ac 100644
--- a/llvm/tools/llubi/lib/Context.h
+++ b/llvm/tools/llubi/lib/Context.h
@@ -381,6 +381,11 @@ class Context {
uint64_t getEffectiveTypeAllocSize(Type *Ty);
uint64_t getEffectiveTypeStoreSize(Type *Ty);
+ /// Check if the input module is compatible with the current setting.
+ /// Otherwise the interpreter might crash on some untrusted inputs, even if it
+ /// passes IRVerifier.
+ bool isValid(raw_ostream &OS) const;
+
/// Returns a pointer to an evaluated constant \p C. If it cannot be
/// evaluated, returns nullptr. Note that it returns a pointer to a temporary
/// buffer when \p C is not context-free. The caller is responsible for
diff --git a/llvm/tools/llubi/llubi.cpp b/llvm/tools/llubi/llubi.cpp
index 00863dd5ecb39..2bc47227610f4 100644
--- a/llvm/tools/llubi/llubi.cpp
+++ b/llvm/tools/llubi/llubi.cpp
@@ -262,6 +262,11 @@ int main(int argc, char **argv) {
Ctx.setNaNPropagationBehavior(NaNPropagationBehavior);
Ctx.reseed(Seed);
+ if (!NoVerify && !Ctx.isValid(errs())) {
+ WithColor::error() << InputFile << ": input module cannot be executed!\n";
+ return 1;
+ }
+
if (!Ctx.initGlobalValues()) {
WithColor::error() << "Failed to initialize global values (e.g., the "
"memory limit may be too low).\n";
>From 75ba601f18767162d72418c41d5f75a30d99bdbd Mon Sep 17 00:00:00 2001
From: Yingwei Zheng <dtcxzyw2333 at gmail.com>
Date: Sat, 10 Oct 2026 02:03:20 +0800
Subject: [PATCH 2/7] [llubi] Reject large arrays
---
llvm/test/tools/llubi/array_count_truncation.ll | 11 +++++++++++
llvm/tools/llubi/lib/Context.cpp | 10 +++++++++-
2 files changed, 20 insertions(+), 1 deletion(-)
create mode 100644 llvm/test/tools/llubi/array_count_truncation.ll
diff --git a/llvm/test/tools/llubi/array_count_truncation.ll b/llvm/test/tools/llubi/array_count_truncation.ll
new file mode 100644
index 0000000000000..5c646e36cf9b9
--- /dev/null
+++ b/llvm/test/tools/llubi/array_count_truncation.ll
@@ -0,0 +1,11 @@
+; RUN: not llubi --verbose < %s 2>&1 | FileCheck %s
+
+ at g = global i8 0
+define void @main() {
+ %v = load [4294967296 x [0 x i8]], ptr @g
+ %e = extractvalue [4294967296 x [0 x i8]] %v, 0
+ ret void
+}
+
+; CHECK: The number of elements of [4294967296 x [0 x i8]] is too large!
+; CHECK-NEXT: error: -: input module cannot be executed!
diff --git a/llvm/tools/llubi/lib/Context.cpp b/llvm/tools/llubi/lib/Context.cpp
index d70d054b4887f..726146e9e6cf3 100644
--- a/llvm/tools/llubi/lib/Context.cpp
+++ b/llvm/tools/llubi/lib/Context.cpp
@@ -1295,8 +1295,16 @@ bool Context::isValid(raw_ostream &OS) const {
return false;
}
return true;
- case Type::StructTyID:
case Type::ArrayTyID:
+ // The number of elements is used as uint32_t in the value
+ // representation. Reject arrays with too many elements to avoid
+ // truncation.
+ if (cast<ArrayType>(Ty)->getNumElements() > UINT32_MAX) {
+ OS << "The number of elements of " << *Ty << " is too large!\n";
+ return false;
+ }
+ [[fallthrough]];
+ case Type::StructTyID:
if (ValidAggTys.contains(Ty))
return true;
for (unsigned I = 0, E = Ty->getNumContainedTypes(); I != E; ++I)
>From 082a25eb8c84a6986b11c71d0396953bd2b13c48 Mon Sep 17 00:00:00 2001
From: Yingwei Zheng <dtcxzyw2333 at gmail.com>
Date: Sat, 10 Oct 2026 03:34:48 +0800
Subject: [PATCH 3/7] [llubi][NFC] Use UTC
---
llvm/test/tools/llubi/array_count_truncation.ll | 1 +
1 file changed, 1 insertion(+)
diff --git a/llvm/test/tools/llubi/array_count_truncation.ll b/llvm/test/tools/llubi/array_count_truncation.ll
index 5c646e36cf9b9..65044115e9bca 100644
--- a/llvm/test/tools/llubi/array_count_truncation.ll
+++ b/llvm/test/tools/llubi/array_count_truncation.ll
@@ -1,3 +1,4 @@
+; NOTE: Assertions have been autogenerated by utils/update_llubi_test_checks.py UTC_ARGS: --version 6
; RUN: not llubi --verbose < %s 2>&1 | FileCheck %s
@g = global i8 0
>From fd6bf2d615bef42f7c7ffacb620ebefddf8724f1 Mon Sep 17 00:00:00 2001
From: Yingwei Zheng <dtcxzyw2333 at gmail.com>
Date: Sat, 10 Oct 2026 04:02:16 +0800
Subject: [PATCH 4/7] [llubi] Dump position
---
.../tools/llubi/array_count_truncation.ll | 1 +
llvm/test/tools/llubi/load_target_ext.ll | 1 +
.../tools/llubi/shufflevector_large_size.ll | 2 +
.../tools/llubi/target_ext_extractvalue.ll | 1 +
.../tools/llubi/target_ext_freeze_poison.ll | 1 +
llvm/test/tools/llubi/target_ext_global.ll | 1 +
.../tools/llubi/target_ext_indirect_call.ll | 1 +
llvm/test/tools/llubi/target_ext_main_arg.ll | 1 +
llvm/test/tools/llubi/target_ext_return.ll | 1 +
llvm/test/tools/llubi/target_ext_store.ll | 1 +
.../tools/llubi/target_ext_store_array.ll | 1 +
.../target_ext_store_nested_aggregate.ll | 1 +
.../tools/llubi/target_ext_store_struct.ll | 1 +
.../llubi/target_ext_store_vector_element.ll | 1 +
llvm/test/tools/llubi/target_ext_vararg.ll | 1 +
.../tools/llubi/vector_reduce_fmax_empty.ll | 1 +
.../llubi/vector_reduce_fmaximum_empty.ll | 1 +
llvm/test/tools/llubi/x86_amx_bitcast.ll | 1 +
llvm/test/tools/llubi/x86_amx_store_struct.ll | 1 +
llvm/tools/llubi/lib/Context.cpp | 62 ++++++++++++++++---
20 files changed, 74 insertions(+), 8 deletions(-)
diff --git a/llvm/test/tools/llubi/array_count_truncation.ll b/llvm/test/tools/llubi/array_count_truncation.ll
index 65044115e9bca..52362bff98a2d 100644
--- a/llvm/test/tools/llubi/array_count_truncation.ll
+++ b/llvm/test/tools/llubi/array_count_truncation.ll
@@ -9,4 +9,5 @@ define void @main() {
}
; CHECK: The number of elements of [4294967296 x [0 x i8]] is too large!
+; CHECK-NEXT: %v = load [4294967296 x [0 x i8]], ptr @g, align 1 at @main <stdin>:6
; CHECK-NEXT: error: -: input module cannot be executed!
diff --git a/llvm/test/tools/llubi/load_target_ext.ll b/llvm/test/tools/llubi/load_target_ext.ll
index d89e891cecfe4..6a11dd3a2727a 100644
--- a/llvm/test/tools/llubi/load_target_ext.ll
+++ b/llvm/test/tools/llubi/load_target_ext.ll
@@ -7,4 +7,5 @@ define void @main() {
ret void
}
; CHECK: Unsupported type target("spirv.Event")
+; CHECK-NEXT: %v = load target("spirv.Event"), ptr %a, align 8 at @main <stdin>:6
; CHECK-NEXT: error: -: input module cannot be executed!
diff --git a/llvm/test/tools/llubi/shufflevector_large_size.ll b/llvm/test/tools/llubi/shufflevector_large_size.ll
index cf106a4d1e337..1c3fe8227bdaa 100644
--- a/llvm/test/tools/llubi/shufflevector_large_size.ll
+++ b/llvm/test/tools/llubi/shufflevector_large_size.ll
@@ -1,3 +1,4 @@
+; NOTE: Assertions have been autogenerated by utils/update_llubi_test_checks.py UTC_ARGS: --version 6
; RUN: not llubi --verbose < %s 2>&1 | FileCheck %s
define void @main() {
@@ -6,4 +7,5 @@ define void @main() {
}
; CHECK: The number of elements of <vscale x 1073741823 x i32> is too large!
+; CHECK-NEXT: %x = shufflevector <vscale x 1073741823 x i32> poison, <vscale x 1073741823 x i32> poison, <vscale x 1 x i32> zeroinitializer at @main <stdin>:5
; CHECK-NEXT: error: -: input module cannot be executed!
diff --git a/llvm/test/tools/llubi/target_ext_extractvalue.ll b/llvm/test/tools/llubi/target_ext_extractvalue.ll
index 7bfd61bbf51b8..22afa4256bbd4 100644
--- a/llvm/test/tools/llubi/target_ext_extractvalue.ll
+++ b/llvm/test/tools/llubi/target_ext_extractvalue.ll
@@ -6,4 +6,5 @@ define void @main() {
ret void
}
; CHECK: Unsupported type target("wasm.externref")
+; CHECK-NEXT: %x = extractvalue { i32, target("wasm.externref") } undef, 0 at @main <stdin>:5
; CHECK-NEXT: error: -: input module cannot be executed!
diff --git a/llvm/test/tools/llubi/target_ext_freeze_poison.ll b/llvm/test/tools/llubi/target_ext_freeze_poison.ll
index 366aa5340d14d..af45642f60a05 100644
--- a/llvm/test/tools/llubi/target_ext_freeze_poison.ll
+++ b/llvm/test/tools/llubi/target_ext_freeze_poison.ll
@@ -6,4 +6,5 @@ define void @main() {
ret void
}
; CHECK: Unsupported type target("wasm.externref")
+; CHECK-NEXT: %x = freeze target("wasm.externref") poison at @main <stdin>:5
; CHECK-NEXT: error: -: input module cannot be executed!
diff --git a/llvm/test/tools/llubi/target_ext_global.ll b/llvm/test/tools/llubi/target_ext_global.ll
index 052a6042f4d60..99b9dc716362f 100644
--- a/llvm/test/tools/llubi/target_ext_global.ll
+++ b/llvm/test/tools/llubi/target_ext_global.ll
@@ -7,4 +7,5 @@ define i32 @main() {
ret i32 0
}
; CHECK: Unsupported type target("wasm.externref")
+; CHECK-NEXT: at @g
; CHECK-NEXT: error: -: input module cannot be executed!
diff --git a/llvm/test/tools/llubi/target_ext_indirect_call.ll b/llvm/test/tools/llubi/target_ext_indirect_call.ll
index b3fef6e388c30..fac80beb3d895 100644
--- a/llvm/test/tools/llubi/target_ext_indirect_call.ll
+++ b/llvm/test/tools/llubi/target_ext_indirect_call.ll
@@ -6,4 +6,5 @@ define void @main() {
ret void
}
; CHECK: Unsupported type target("wasm.externref")
+; CHECK-NEXT: call void null(target("wasm.externref") poison) at @main <stdin>:5
; CHECK-NEXT: error: -: input module cannot be executed!
diff --git a/llvm/test/tools/llubi/target_ext_main_arg.ll b/llvm/test/tools/llubi/target_ext_main_arg.ll
index 2981a324d28b7..00c179a22b6dd 100644
--- a/llvm/test/tools/llubi/target_ext_main_arg.ll
+++ b/llvm/test/tools/llubi/target_ext_main_arg.ll
@@ -5,4 +5,5 @@ define i32 @main(target("wasm.externref") %a) {
ret i32 0
}
; CHECK: Unsupported type target("wasm.externref")
+; CHECK-NEXT: target("wasm.externref") %a at @main <stdin>:4
; CHECK-NEXT: error: -: input module cannot be executed!
diff --git a/llvm/test/tools/llubi/target_ext_return.ll b/llvm/test/tools/llubi/target_ext_return.ll
index 60e3d3564f607..c25606229fa77 100644
--- a/llvm/test/tools/llubi/target_ext_return.ll
+++ b/llvm/test/tools/llubi/target_ext_return.ll
@@ -5,4 +5,5 @@ define target("wasm.externref") @main() {
ret target("wasm.externref") poison
}
; CHECK: Unsupported type target("wasm.externref")
+; CHECK-NEXT: at @main <stdin>:4
; CHECK-NEXT: error: -: input module cannot be executed!
diff --git a/llvm/test/tools/llubi/target_ext_store.ll b/llvm/test/tools/llubi/target_ext_store.ll
index 883a83436dadc..2d2694fbcc75b 100644
--- a/llvm/test/tools/llubi/target_ext_store.ll
+++ b/llvm/test/tools/llubi/target_ext_store.ll
@@ -7,4 +7,5 @@ define void @main() {
ret void
}
; CHECK: Unsupported type target("wasm.externref")
+; CHECK-NEXT: store target("wasm.externref") poison, ptr %a, align 8 at @main <stdin>:6
; CHECK-NEXT: error: -: input module cannot be executed!
diff --git a/llvm/test/tools/llubi/target_ext_store_array.ll b/llvm/test/tools/llubi/target_ext_store_array.ll
index e09730d7bf486..297a600ddda85 100644
--- a/llvm/test/tools/llubi/target_ext_store_array.ll
+++ b/llvm/test/tools/llubi/target_ext_store_array.ll
@@ -6,4 +6,5 @@ define void @main() {
ret void
}
; CHECK: Unsupported type target("wasm.externref")
+; CHECK-NEXT: store [2 x target("wasm.externref")] poison, ptr null, align 8 at @main <stdin>:5
; CHECK-NEXT: error: -: input module cannot be executed!
diff --git a/llvm/test/tools/llubi/target_ext_store_nested_aggregate.ll b/llvm/test/tools/llubi/target_ext_store_nested_aggregate.ll
index 01c6585849983..b186d93b9739c 100644
--- a/llvm/test/tools/llubi/target_ext_store_nested_aggregate.ll
+++ b/llvm/test/tools/llubi/target_ext_store_nested_aggregate.ll
@@ -6,4 +6,5 @@ define void @main() {
ret void
}
; CHECK: Unsupported type target("wasm.externref")
+; CHECK-NEXT: store { i32, [2 x target("wasm.externref")] } poison, ptr null, align 8 at @main <stdin>:5
; CHECK-NEXT: error: -: input module cannot be executed!
diff --git a/llvm/test/tools/llubi/target_ext_store_struct.ll b/llvm/test/tools/llubi/target_ext_store_struct.ll
index 02c281bc44329..58042ec612b3d 100644
--- a/llvm/test/tools/llubi/target_ext_store_struct.ll
+++ b/llvm/test/tools/llubi/target_ext_store_struct.ll
@@ -6,4 +6,5 @@ define void @main() {
ret void
}
; CHECK: Unsupported type target("wasm.externref")
+; CHECK-NEXT: store { i32, target("wasm.externref") } poison, ptr null, align 8 at @main <stdin>:5
; CHECK-NEXT: error: -: input module cannot be executed!
diff --git a/llvm/test/tools/llubi/target_ext_store_vector_element.ll b/llvm/test/tools/llubi/target_ext_store_vector_element.ll
index 9d001b0926840..e9d9894affb8c 100644
--- a/llvm/test/tools/llubi/target_ext_store_vector_element.ll
+++ b/llvm/test/tools/llubi/target_ext_store_vector_element.ll
@@ -6,4 +6,5 @@ define void @main() {
ret void
}
; CHECK: Unsupported type <2 x target("llvm.test.vectorelement")>
+; CHECK-NEXT: store <2 x target("llvm.test.vectorelement")> poison, ptr null, align 8 at @main <stdin>:5
; CHECK-NEXT: error: -: input module cannot be executed!
diff --git a/llvm/test/tools/llubi/target_ext_vararg.ll b/llvm/test/tools/llubi/target_ext_vararg.ll
index 1d6f6079b2d66..88b2f84edd6cd 100644
--- a/llvm/test/tools/llubi/target_ext_vararg.ll
+++ b/llvm/test/tools/llubi/target_ext_vararg.ll
@@ -10,4 +10,5 @@ define void @main() {
ret void
}
; CHECK: Unsupported type target("wasm.externref")
+; CHECK-NEXT: %r = call i32 (ptr, ...) @printf(ptr @.str, target("wasm.externref") poison) at @main <stdin>:9
; CHECK-NEXT: error: -: input module cannot be executed!
diff --git a/llvm/test/tools/llubi/vector_reduce_fmax_empty.ll b/llvm/test/tools/llubi/vector_reduce_fmax_empty.ll
index c481bf8890b5d..934716e76c234 100644
--- a/llvm/test/tools/llubi/vector_reduce_fmax_empty.ll
+++ b/llvm/test/tools/llubi/vector_reduce_fmax_empty.ll
@@ -6,4 +6,5 @@ define void @main() {
ret void
}
; CHECK: The number of elements of <vscale x 1073741824 x float> is too large!
+; CHECK-NEXT: %r = call float @llvm.vector.reduce.fmax.nxv1073741824f32(<vscale x 1073741824 x float> zeroinitializer) at @main <stdin>:5
; CHECK-NEXT: error: -: input module cannot be executed!
diff --git a/llvm/test/tools/llubi/vector_reduce_fmaximum_empty.ll b/llvm/test/tools/llubi/vector_reduce_fmaximum_empty.ll
index b383f90f3ef27..7c4a404131b2a 100644
--- a/llvm/test/tools/llubi/vector_reduce_fmaximum_empty.ll
+++ b/llvm/test/tools/llubi/vector_reduce_fmaximum_empty.ll
@@ -6,4 +6,5 @@ define void @main() {
ret void
}
; CHECK: The number of elements of <vscale x 1073741824 x float> is too large!
+; CHECK-NEXT: %r = call float @llvm.vector.reduce.fmaximum.nxv1073741824f32(<vscale x 1073741824 x float> zeroinitializer) at @main <stdin>:5
; CHECK-NEXT: error: -: input module cannot be executed!
diff --git a/llvm/test/tools/llubi/x86_amx_bitcast.ll b/llvm/test/tools/llubi/x86_amx_bitcast.ll
index 0263648936776..d36267e93d4e3 100644
--- a/llvm/test/tools/llubi/x86_amx_bitcast.ll
+++ b/llvm/test/tools/llubi/x86_amx_bitcast.ll
@@ -6,4 +6,5 @@ define void @main() {
ret void
}
; CHECK: Unsupported type x86_amx
+; CHECK-NEXT: %x = bitcast x86_amx poison to i8192 at @main <stdin>:5
; CHECK-NEXT: error: -: input module cannot be executed!
diff --git a/llvm/test/tools/llubi/x86_amx_store_struct.ll b/llvm/test/tools/llubi/x86_amx_store_struct.ll
index cd8065d8534b1..240172219f65d 100644
--- a/llvm/test/tools/llubi/x86_amx_store_struct.ll
+++ b/llvm/test/tools/llubi/x86_amx_store_struct.ll
@@ -6,4 +6,5 @@ define void @main() {
ret void
}
; CHECK: Unsupported type x86_amx
+; CHECK-NEXT: store { i32, x86_amx } poison, ptr null, align 64 at @main <stdin>:5
; CHECK-NEXT: error: -: input module cannot be executed!
diff --git a/llvm/tools/llubi/lib/Context.cpp b/llvm/tools/llubi/lib/Context.cpp
index 726146e9e6cf3..223239a1a0bf3 100644
--- a/llvm/tools/llubi/lib/Context.cpp
+++ b/llvm/tools/llubi/lib/Context.cpp
@@ -1317,29 +1317,75 @@ bool Context::isValid(raw_ostream &OS) const {
}
};
-#define CHECK(TYPE) \
+ StringRef ModuleFileName = M.getModuleIdentifier();
+
+ auto DumpFunction = [&](Function *F) {
+ OS << " at ";
+ F->printAsOperand(errs(), /*PrintType=*/false);
+ if (ParserContext) {
+ if (auto Loc = ParserContext->getFunctionLocation(F))
+ OS << ' ' << ModuleFileName << ':' << Loc->Start.Line + 1;
+ }
+ OS << '\n';
+
+ return false;
+ };
+
+ auto DumpArg = [&](Argument *Arg) {
+ OS << " " << *Arg << " at ";
+ Arg->getParent()->printAsOperand(errs(), /*PrintType=*/false);
+ if (ParserContext) {
+ if (auto Loc = ParserContext->getInstructionOrArgumentLocation(Arg))
+ OS << ' ' << ModuleFileName << ':' << Loc->Start.Line + 1;
+ }
+ OS << '\n';
+
+ return false;
+ };
+
+ auto DumpInst = [&](Instruction *Inst) {
+ OS << *Inst << " at ";
+ Inst->getFunction()->printAsOperand(errs(), /*PrintType=*/false);
+ if (ParserContext) {
+ if (auto Loc = ParserContext->getInstructionOrArgumentLocation(Inst))
+ OS << ' ' << ModuleFileName << ':' << Loc->Start.Line + 1;
+ }
+ OS << '\n';
+
+ return false;
+ };
+
+ auto DumpGlobal = [&](GlobalObject *GO) {
+ OS << " at ";
+ GO->printAsOperand(errs(), /*PrintType=*/false);
+ OS << '\n';
+
+ return false;
+ };
+
+#define CHECK(TYPE, LOC) \
if (!IsSupportedType(IsSupportedType, TYPE)) \
- return false
+ return LOC;
for (auto &F : M) {
- CHECK(F.getReturnType());
+ CHECK(F.getReturnType(), DumpFunction(&F));
for (auto &Arg : F.args())
- CHECK(Arg.getType());
+ CHECK(Arg.getType(), DumpArg(&Arg));
for (auto &BB : F)
for (auto &I : BB) {
- CHECK(I.getType());
+ CHECK(I.getType(), DumpInst(&I));
switch (I.getOpcode()) {
case Instruction::Call:
case Instruction::Invoke:
for (auto &Op : I.operands())
- CHECK(Op->getType());
+ CHECK(Op->getType(), DumpInst(&I));
break;
case Instruction::Store:
case Instruction::ExtractElement:
case Instruction::ExtractValue:
case Instruction::BitCast:
case Instruction::ShuffleVector:
- CHECK(I.getOperand(0)->getType());
+ CHECK(I.getOperand(0)->getType(), DumpInst(&I));
break;
default:
break;
@@ -1348,7 +1394,7 @@ bool Context::isValid(raw_ostream &OS) const {
}
for (auto &G : M.globals())
- CHECK(G.getValueType());
+ CHECK(G.getValueType(), DumpGlobal(&G));
#undef CHECK
>From 8fac4853aac58e0a7e338d46204f92dd6daf6289 Mon Sep 17 00:00:00 2001
From: Yingwei Zheng <dtcxzyw2333 at gmail.com>
Date: Sun, 11 Oct 2026 01:56:14 +0800
Subject: [PATCH 5/7] [llubi] Reject token types
---
llvm/test/tools/llubi/token_constant.ll | 10 ++++++++++
llvm/tools/llubi/lib/Context.cpp | 1 +
2 files changed, 11 insertions(+)
create mode 100644 llvm/test/tools/llubi/token_constant.ll
diff --git a/llvm/test/tools/llubi/token_constant.ll b/llvm/test/tools/llubi/token_constant.ll
new file mode 100644
index 0000000000000..83c2cbfb23bd0
--- /dev/null
+++ b/llvm/test/tools/llubi/token_constant.ll
@@ -0,0 +1,10 @@
+; NOTE: Assertions have been autogenerated by utils/update_llubi_test_checks.py UTC_ARGS: --version 6
+; RUN: not llubi --verbose < %s 2>&1 | FileCheck %s
+
+define void @main() {
+ call i8 @llvm.coro.suspend(token none, i1 false)
+ ret void
+}
+; CHECK: Unsupported type token
+; CHECK-NEXT: %1 = call i8 @llvm.coro.suspend(token none, i1 false) at @main <stdin>:5
+; CHECK-NEXT: error: -: input module cannot be executed!
diff --git a/llvm/tools/llubi/lib/Context.cpp b/llvm/tools/llubi/lib/Context.cpp
index 223239a1a0bf3..d522d48c39a74 100644
--- a/llvm/tools/llubi/lib/Context.cpp
+++ b/llvm/tools/llubi/lib/Context.cpp
@@ -1279,6 +1279,7 @@ bool Context::isValid(raw_ostream &OS) const {
switch (Ty->getTypeID()) {
case Type::X86_AMXTyID:
case Type::TargetExtTyID:
+ case Type::TokenTyID:
OS << "Unsupported type " << *Ty << '\n';
return false;
case Type::ScalableVectorTyID:
>From 0d58a8bfe773bab1cc3b57b9b53b433d07c3f5e6 Mon Sep 17 00:00:00 2001
From: Yingwei Zheng <dtcxzyw2333 at gmail.com>
Date: Sun, 11 Oct 2026 03:21:52 +0800
Subject: [PATCH 6/7] [llubi] Reject opaque types
---
llvm/test/tools/llubi/global_unsized.ll | 12 ++++++++++++
llvm/tools/llubi/lib/Context.cpp | 4 ++++
2 files changed, 16 insertions(+)
create mode 100644 llvm/test/tools/llubi/global_unsized.ll
diff --git a/llvm/test/tools/llubi/global_unsized.ll b/llvm/test/tools/llubi/global_unsized.ll
new file mode 100644
index 0000000000000..69d3ef5930281
--- /dev/null
+++ b/llvm/test/tools/llubi/global_unsized.ll
@@ -0,0 +1,12 @@
+; NOTE: Assertions have been autogenerated by utils/update_llubi_test_checks.py UTC_ARGS: --version 6
+; RUN: not llubi --verbose < %s 2>&1 | FileCheck %s
+
+%opaque = type opaque
+ at unsized = external global %opaque
+
+define void @main() {
+ ret void
+}
+; CHECK: Unsupported opaque struct type %opaque
+; CHECK-NEXT: at @unsized
+; CHECK-NEXT: error: -: input module cannot be executed!
diff --git a/llvm/tools/llubi/lib/Context.cpp b/llvm/tools/llubi/lib/Context.cpp
index d522d48c39a74..9dd953e63507e 100644
--- a/llvm/tools/llubi/lib/Context.cpp
+++ b/llvm/tools/llubi/lib/Context.cpp
@@ -1306,6 +1306,10 @@ bool Context::isValid(raw_ostream &OS) const {
}
[[fallthrough]];
case Type::StructTyID:
+ if (auto *STy = dyn_cast<StructType>(Ty); STy && STy->isOpaque()) {
+ OS << "Unsupported opaque struct type %" << STy->getName() << "\n";
+ return false;
+ }
if (ValidAggTys.contains(Ty))
return true;
for (unsigned I = 0, E = Ty->getNumContainedTypes(); I != E; ++I)
>From 29b323d4058e7f5cfd790ea565edbb70598f0616 Mon Sep 17 00:00:00 2001
From: Yingwei Zheng <dtcxzyw2333 at gmail.com>
Date: Mon, 12 Oct 2026 00:29:15 +0800
Subject: [PATCH 7/7] [llubi] Check total size in bits
---
llvm/test/tools/llubi/array_count_overflow.ll | 11 ++
.../tools/llubi/array_count_truncation.ll | 2 +-
.../tools/llubi/shufflevector_large_size.ll | 2 +-
.../llubi/target_ext_store_vector_element.ll | 2 +-
.../tools/llubi/vector_reduce_fmax_empty.ll | 2 +-
.../llubi/vector_reduce_fmaximum_empty.ll | 2 +-
llvm/tools/llubi/lib/Context.cpp | 145 ++++++++++++------
llvm/tools/llubi/lib/Context.h | 4 +
8 files changed, 115 insertions(+), 55 deletions(-)
create mode 100644 llvm/test/tools/llubi/array_count_overflow.ll
diff --git a/llvm/test/tools/llubi/array_count_overflow.ll b/llvm/test/tools/llubi/array_count_overflow.ll
new file mode 100644
index 0000000000000..a6cef78ec5a50
--- /dev/null
+++ b/llvm/test/tools/llubi/array_count_overflow.ll
@@ -0,0 +1,11 @@
+; NOTE: Assertions have been autogenerated by utils/update_llubi_test_checks.py UTC_ARGS: --version 6
+; RUN: not llubi --verbose < %s 2>&1 | FileCheck %s
+
+define void @main() {
+ %a = alloca [4 x [2147483648 x [2147483648 x i8]]], align 8
+ %v = load [4 x [2147483648 x [2147483648 x i8]]], ptr %a
+ ret void
+}
+; CHECK: [2147483648 x i8] is too large!
+; CHECK-NEXT: %v = load [4 x [2147483648 x [2147483648 x i8]]], ptr %a, align 1 at @main <stdin>:6
+; CHECK-NEXT: error: -: input module cannot be executed!
diff --git a/llvm/test/tools/llubi/array_count_truncation.ll b/llvm/test/tools/llubi/array_count_truncation.ll
index 52362bff98a2d..bc2971e95b1f8 100644
--- a/llvm/test/tools/llubi/array_count_truncation.ll
+++ b/llvm/test/tools/llubi/array_count_truncation.ll
@@ -8,6 +8,6 @@ define void @main() {
ret void
}
-; CHECK: The number of elements of [4294967296 x [0 x i8]] is too large!
+; CHECK: [4294967296 x [0 x i8]] is too large!
; CHECK-NEXT: %v = load [4294967296 x [0 x i8]], ptr @g, align 1 at @main <stdin>:6
; CHECK-NEXT: error: -: input module cannot be executed!
diff --git a/llvm/test/tools/llubi/shufflevector_large_size.ll b/llvm/test/tools/llubi/shufflevector_large_size.ll
index 1c3fe8227bdaa..b223e6b1e9437 100644
--- a/llvm/test/tools/llubi/shufflevector_large_size.ll
+++ b/llvm/test/tools/llubi/shufflevector_large_size.ll
@@ -6,6 +6,6 @@ define void @main() {
ret void
}
-; CHECK: The number of elements of <vscale x 1073741823 x i32> is too large!
+; CHECK: <vscale x 1073741823 x i32> is too large!
; CHECK-NEXT: %x = shufflevector <vscale x 1073741823 x i32> poison, <vscale x 1073741823 x i32> poison, <vscale x 1 x i32> zeroinitializer at @main <stdin>:5
; CHECK-NEXT: error: -: input module cannot be executed!
diff --git a/llvm/test/tools/llubi/target_ext_store_vector_element.ll b/llvm/test/tools/llubi/target_ext_store_vector_element.ll
index e9d9894affb8c..cc51ed229d554 100644
--- a/llvm/test/tools/llubi/target_ext_store_vector_element.ll
+++ b/llvm/test/tools/llubi/target_ext_store_vector_element.ll
@@ -5,6 +5,6 @@ define void @main() {
store <2 x target("llvm.test.vectorelement")> poison, ptr null
ret void
}
-; CHECK: Unsupported type <2 x target("llvm.test.vectorelement")>
+; CHECK: Unsupported type target("llvm.test.vectorelement")
; CHECK-NEXT: store <2 x target("llvm.test.vectorelement")> poison, ptr null, align 8 at @main <stdin>:5
; CHECK-NEXT: error: -: input module cannot be executed!
diff --git a/llvm/test/tools/llubi/vector_reduce_fmax_empty.ll b/llvm/test/tools/llubi/vector_reduce_fmax_empty.ll
index 934716e76c234..b2558fad6bed3 100644
--- a/llvm/test/tools/llubi/vector_reduce_fmax_empty.ll
+++ b/llvm/test/tools/llubi/vector_reduce_fmax_empty.ll
@@ -5,6 +5,6 @@ define void @main() {
%r = call float @llvm.vector.reduce.fmax.nxv1073741824f32(<vscale x 1073741824 x float> zeroinitializer)
ret void
}
-; CHECK: The number of elements of <vscale x 1073741824 x float> is too large!
+; CHECK: <vscale x 1073741824 x float> is too large!
; CHECK-NEXT: %r = call float @llvm.vector.reduce.fmax.nxv1073741824f32(<vscale x 1073741824 x float> zeroinitializer) at @main <stdin>:5
; CHECK-NEXT: error: -: input module cannot be executed!
diff --git a/llvm/test/tools/llubi/vector_reduce_fmaximum_empty.ll b/llvm/test/tools/llubi/vector_reduce_fmaximum_empty.ll
index 7c4a404131b2a..60f4f28cb4296 100644
--- a/llvm/test/tools/llubi/vector_reduce_fmaximum_empty.ll
+++ b/llvm/test/tools/llubi/vector_reduce_fmaximum_empty.ll
@@ -5,6 +5,6 @@ define void @main() {
%r = call float @llvm.vector.reduce.fmaximum.nxv1073741824f32(<vscale x 1073741824 x float> zeroinitializer)
ret void
}
-; CHECK: The number of elements of <vscale x 1073741824 x float> is too large!
+; CHECK: <vscale x 1073741824 x float> is too large!
; CHECK-NEXT: %r = call float @llvm.vector.reduce.fmaximum.nxv1073741824f32(<vscale x 1073741824 x float> zeroinitializer) at @main <stdin>:5
; CHECK-NEXT: error: -: input module cannot be executed!
diff --git a/llvm/tools/llubi/lib/Context.cpp b/llvm/tools/llubi/lib/Context.cpp
index 9dd953e63507e..de085fc0b9c9f 100644
--- a/llvm/tools/llubi/lib/Context.cpp
+++ b/llvm/tools/llubi/lib/Context.cpp
@@ -1270,58 +1270,102 @@ uint64_t Context::getEffectiveTypeStoreSize(Type *Ty) {
return getEffectiveTypeSize(DL.getTypeStoreSize(Ty));
}
-bool Context::isValid(raw_ostream &OS) const {
- assert(isPowerOf2_32(VScale) && "VScale must be a power of two.");
- uint32_t MaxNumElements = UINT32_MAX / VScale;
-
- SmallPtrSet<Type *, 16> ValidAggTys;
- auto IsSupportedType = [&](auto &&Self, Type *Ty) {
- switch (Ty->getTypeID()) {
- case Type::X86_AMXTyID:
- case Type::TargetExtTyID:
- case Type::TokenTyID:
- OS << "Unsupported type " << *Ty << '\n';
- return false;
- case Type::ScalableVectorTyID:
- // Avoid overflow when computing EVL.
- if (cast<VectorType>(Ty)->getElementCount().getKnownMinValue() >=
- MaxNumElements) {
- OS << "The number of elements of " << *Ty << " is too large!\n";
- return false;
- }
- [[fallthrough]];
- case Type::FixedVectorTyID:
- if (cast<VectorType>(Ty)->getElementType()->isTargetExtTy()) {
- OS << "Unsupported type " << *Ty << '\n';
- return false;
- }
- return true;
- case Type::ArrayTyID:
- // The number of elements is used as uint32_t in the value
- // representation. Reject arrays with too many elements to avoid
- // truncation.
- if (cast<ArrayType>(Ty)->getNumElements() > UINT32_MAX) {
- OS << "The number of elements of " << *Ty << " is too large!\n";
- return false;
- }
- [[fallthrough]];
- case Type::StructTyID:
- if (auto *STy = dyn_cast<StructType>(Ty); STy && STy->isOpaque()) {
- OS << "Unsupported opaque struct type %" << STy->getName() << "\n";
- return false;
+/// Check whether \p Ty is small enough to be emulated. Return the total bits
+/// the type (we use the allocation size as a overestimation) if it is
+/// supported. Otherwise, return std::nullopt.
+/// In fact it duplicates the logic from DL.getTypeAllocSizeInBits, with careful
+/// handling of overflows.
+std::optional<uint64_t> Context::isSupportedType(
+ raw_ostream &OS, DenseMap<Type *, uint64_t> &ValidAggTys, Type *Ty) const {
+ constexpr uint64_t MaxNumBits = UINT32_MAX;
+ uint32_t MaxNumBitsPerElement = MaxNumBits;
+
+ switch (Ty->getTypeID()) {
+ case Type::X86_AMXTyID:
+ case Type::TargetExtTyID:
+ case Type::TokenTyID:
+ OS << "Unsupported type " << *Ty << '\n';
+ return std::nullopt;
+ case Type::ScalableVectorTyID:
+ assert(isPowerOf2_32(VScale) && "VScale must be a power of two.");
+ MaxNumBitsPerElement /= VScale;
+ [[fallthrough]];
+ case Type::FixedVectorTyID: {
+ ElementCount EC = cast<VectorType>(Ty)->getElementCount();
+ MaxNumBitsPerElement /= EC.getKnownMinValue();
+ auto ElementBits = isSupportedType(OS, ValidAggTys,
+ cast<VectorType>(Ty)->getElementType());
+ if (!ElementBits)
+ return std::nullopt;
+ if (*ElementBits > MaxNumBitsPerElement) {
+ OS << *Ty << " is too large!\n";
+ return std::nullopt;
+ }
+ // Now the multiplication never overflows.
+ return *ElementBits * getEVL(EC);
+ }
+ case Type::ArrayTyID: {
+ if (uint64_t Size = ValidAggTys.lookup(Ty))
+ return Size;
+ uint64_t Scale =
+ std::max(cast<ArrayType>(Ty)->getNumElements(), (uint64_t)1);
+ MaxNumBitsPerElement /= Scale;
+ auto ElementBits =
+ isSupportedType(OS, ValidAggTys, cast<ArrayType>(Ty)->getElementType());
+ if (!ElementBits)
+ return std::nullopt;
+ if (*ElementBits > MaxNumBitsPerElement) {
+ OS << *Ty << " is too large!\n";
+ return std::nullopt;
+ }
+ // Now the multiplication never overflows.
+ return ValidAggTys.insert({Ty, *ElementBits * Scale}).first->second;
+ }
+ case Type::StructTyID: {
+ auto *STy = cast<StructType>(Ty);
+ if (STy->isOpaque()) {
+ OS << "Unsupported opaque struct type %" << STy->getName() << '\n';
+ return std::nullopt;
+ }
+ if (uint64_t Size = ValidAggTys.lookup(Ty))
+ return Size;
+ uint64_t Size = 0, Alignment = 8;
+ for (unsigned I = 0, E = STy->getNumElements(); I != E; ++I) {
+ Type *ElementType = STy->getElementType(I);
+ auto ElementBits = isSupportedType(OS, ValidAggTys, ElementType);
+ if (!ElementBits)
+ return std::nullopt;
+ if (!STy->isPacked()) {
+ uint64_t ElementAlignment = DL.getABITypeAlign(ElementType).value() * 8;
+ Size = alignTo(Size, ElementAlignment);
+ Alignment = std::max(Alignment, ElementAlignment);
}
- if (ValidAggTys.contains(Ty))
- return true;
- for (unsigned I = 0, E = Ty->getNumContainedTypes(); I != E; ++I)
- if (!Self(Self, Ty->getContainedType(I)))
- return false;
- ValidAggTys.insert(Ty);
- return true;
- default:
- return true;
+ // The addition never overflows.
+ Size += *ElementBits;
}
- };
+ Size = std::max(Size, (uint64_t)1);
+ if (!STy->isPacked()) {
+ // If it is not packed, we need to respect StructABIAlignment specified in
+ // the DL string.
+ Alignment = std::max(Alignment, DL.getABITypeAlign(STy).value() * 8);
+ }
+ Size = alignTo(Size, Alignment);
+ if (Size > MaxNumBits) {
+ OS << *Ty << " is too large!\n";
+ return std::nullopt;
+ }
+ return ValidAggTys.insert({Ty, Size}).first->second;
+ }
+ default:
+ // All scalar single value types are known smaller than MaxNumBits.
+ if (Ty->isSingleValueType())
+ return DL.getTypeAllocSizeInBits(Ty);
+ // void/metadata/label/function types are always supported.
+ return 0;
+ }
+}
+bool Context::isValid(raw_ostream &OS) const {
StringRef ModuleFileName = M.getModuleIdentifier();
auto DumpFunction = [&](Function *F) {
@@ -1368,8 +1412,9 @@ bool Context::isValid(raw_ostream &OS) const {
return false;
};
+ DenseMap<Type *, uint64_t> ValidAggTys;
#define CHECK(TYPE, LOC) \
- if (!IsSupportedType(IsSupportedType, TYPE)) \
+ if (!isSupportedType(OS, ValidAggTys, TYPE)) \
return LOC;
for (auto &F : M) {
diff --git a/llvm/tools/llubi/lib/Context.h b/llvm/tools/llubi/lib/Context.h
index 10c6effea90ac..646881b7c02eb 100644
--- a/llvm/tools/llubi/lib/Context.h
+++ b/llvm/tools/llubi/lib/Context.h
@@ -228,6 +228,10 @@ class Context {
const DataLayout &DL;
const TargetLibraryInfoImpl TLIImpl;
+ std::optional<uint64_t>
+ isSupportedType(raw_ostream &OS, DenseMap<Type *, uint64_t> &ValidAggTys,
+ Type *Ty) const;
+
// Configuration
uint64_t MaxMem = 0;
uint32_t VScale = 4;
More information about the llvm-commits
mailing list