Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,7 @@ lakefile.olean
Test/**/Output/**

**/.ruff_cache

# Python bytecode from the tools in Tools/
__pycache__/
*.pyc
25 changes: 25 additions & 0 deletions Test/Interpreter/LLVM/addressof_function.mlir
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// RUN: veir-interpret %s | filecheck %s

// Functions get objects of their own, so their addresses are distinct from
// every other object's and from null. The addresses themselves are chosen by
// the interpreter, so the test compares two of them rather than naming one.

"builtin.module"() ({
"llvm.func"() <{function_type = !llvm.func<void ()>, sym_name = "f"}> ({
"llvm.return"() : () -> ()
}) : () -> ()
"llvm.func"() <{function_type = !llvm.func<void ()>, sym_name = "g"}> ({
"llvm.return"() : () -> ()
}) : () -> ()
"llvm.func"() <{function_type = !llvm.func<i64 ()>, sym_name = "main"}> ({
%f = "llvm.mlir.addressof"() <{global_name = @f}> : () -> !llvm.ptr
%g = "llvm.mlir.addressof"() <{global_name = @g}> : () -> !llvm.ptr
%fi = "llvm.ptrtoint"(%f) : (!llvm.ptr) -> i64
%gi = "llvm.ptrtoint"(%g) : (!llvm.ptr) -> i64
%same = "llvm.icmp"(%fi, %gi) <{predicate = 0 : i64}> : (i64, i64) -> i1
%wide = "llvm.zext"(%same) : (i1) -> i64
"llvm.return"(%wide) : (i64) -> ()
}) : () -> ()
}) : () -> ()

// CHECK: Program output: #[0x0000000000000000#64]
17 changes: 17 additions & 0 deletions Test/Interpreter/LLVM/alloca_alignment.mlir
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// RUN: veir-interpret %s | filecheck %s

// An object is laid out at the alignment its allocation declares, so the low
// bits of its address are clear.

"builtin.module"() ({
"func.func"() <{sym_name = "main", function_type = () -> i64}> ({
%one = "llvm.mlir.constant"() <{value = 1 : i64}> : () -> i64
%mask = "llvm.mlir.constant"() <{value = 63 : i64}> : () -> i64
%p = "llvm.alloca"(%one) <{alignment = 64 : i64, elem_type = i64}> : (i64) -> !llvm.ptr
%a = "llvm.ptrtoint"(%p) : (!llvm.ptr) -> i64
%low = "llvm.and"(%a, %mask) : (i64, i64) -> i64
"func.return"(%low) : (i64) -> ()
}) : () -> ()
}) : () -> ()

// CHECK: Program output: #[0x0000000000000000#64]
22 changes: 22 additions & 0 deletions Test/Interpreter/LLVM/alloca_distinct_objects.mlir
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// RUN: veir-interpret %s | filecheck %s

// Each `alloca` is its own object, so writing past the end of one cannot
// be seen through the other. Walking eight bytes past an 8-byte object
// leaves it, and the access is undefined rather than landing in its
// neighbour.

"builtin.module"() ({
"func.func"() <{sym_name = "main", function_type = () -> i32}> ({
%one = "llvm.mlir.constant"() <{value = 1 : i64}> : () -> i64
%eight = "llvm.mlir.constant"() <{value = 8 : i64}> : () -> i64
%five = "llvm.mlir.constant"() <{value = 5 : i32}> : () -> i32
%p = "llvm.alloca"(%one) <{elem_type = i64}> : (i64) -> !llvm.ptr
%q = "llvm.alloca"(%one) <{elem_type = i64}> : (i64) -> !llvm.ptr
%past = "llvm.getelementptr"(%p, %eight) <{elem_type = i8, rawConstantIndices = array<i32: -2147483648>}> : (!llvm.ptr, i64) -> !llvm.ptr
"llvm.store"(%five, %past) : (i32, !llvm.ptr) -> ()
%v = "llvm.load"(%q) : (!llvm.ptr) -> i32
"func.return"(%v) : (i32) -> ()
}) : () -> ()
}) : () -> ()

// CHECK: Undefined behavior
19 changes: 19 additions & 0 deletions Test/Interpreter/LLVM/alloca_out_of_bounds.mlir
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// RUN: veir-interpret %s | filecheck %s

"builtin.module"() ({
"func.func"() <{sym_name = "main", function_type = () -> i32}> ({
%one = "llvm.mlir.constant"() <{value = 1 : i64}> : () -> i64
%i = "llvm.mlir.constant"() <{value = 8 : i64}> : () -> i64
%three = "llvm.mlir.constant"() <{value = 3 : i32}> : () -> i32
%five = "llvm.mlir.constant"() <{value = 5 : i32}> : () -> i32
%p = "llvm.alloca"(%one) <{elem_type = i64}> : (i64) -> !llvm.ptr
%q = "llvm.alloca"(%one) <{elem_type = i64}> : (i64) -> !llvm.ptr
%p1 = "llvm.getelementptr"(%p, %i) <{elem_type = i8, rawConstantIndices = array<i32: -2147483648>}> : (!llvm.ptr, i64) -> !llvm.ptr
"llvm.store"(%five, %q) : (i32, !llvm.ptr) -> ()
"llvm.store"(%three, %p1) : (i32, !llvm.ptr) -> ()
%v = "llvm.load"(%q) : (!llvm.ptr) -> i32
"func.return"(%v) : (i32) -> ()
}) : () -> ()
}) : () -> ()

// CHECK: Undefined behavior
18 changes: 18 additions & 0 deletions Test/Interpreter/LLVM/call_align_violation.mlir
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// RUN: veir-interpret %s | filecheck %s

// A pointer at offset 1 does not satisfy `llvm.align = 8`.

"builtin.module"() ({
"llvm.func"() <{function_type = !llvm.func<void (ptr)>, linkage = #llvm.linkage<external>, sym_name = "foo"}> ({
}) : () -> ()
"func.func"() <{sym_name = "main", function_type = () -> i32}> ({
%one = "llvm.mlir.constant"() <{value = 1 : i64}> : () -> i64
%zero = "llvm.mlir.constant"() <{value = 0 : i32}> : () -> i32
%p = "llvm.alloca"(%one) <{elem_type = i64}> : (i64) -> !llvm.ptr
%q = "llvm.getelementptr"(%p, %one) <{elem_type = i8, rawConstantIndices = array<i32: -2147483648>}> : (!llvm.ptr, i64) -> !llvm.ptr
"llvm.call"(%q) <{callee = @foo, arg_attrs = [{llvm.align = 8 : i64}], op_bundle_sizes = array<i32>, operandSegmentSizes = array<i32: 1, 0>}> : (!llvm.ptr) -> ()
"func.return"(%zero) : (i32) -> ()
}) : () -> ()
}) : () -> ()

// CHECK: Undefined behavior
17 changes: 17 additions & 0 deletions Test/Interpreter/LLVM/call_arg_attrs_satisfied.mlir
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// RUN: veir-interpret %s | filecheck %s

// All three attributes hold for an aligned, live, 8-byte alloca.

"builtin.module"() ({
"llvm.func"() <{function_type = !llvm.func<void (ptr)>, linkage = #llvm.linkage<external>, sym_name = "foo"}> ({
}) : () -> ()
"func.func"() <{sym_name = "main", function_type = () -> i32}> ({
%one = "llvm.mlir.constant"() <{value = 1 : i64}> : () -> i64
%zero = "llvm.mlir.constant"() <{value = 0 : i32}> : () -> i32
%p = "llvm.alloca"(%one) <{elem_type = i64}> : (i64) -> !llvm.ptr
"llvm.call"(%p) <{callee = @foo, arg_attrs = [{llvm.align = 8 : i64, llvm.dereferenceable = 8 : i64, llvm.nonnull}], op_bundle_sizes = array<i32>, operandSegmentSizes = array<i32: 1, 0>}> : (!llvm.ptr) -> ()
"func.return"(%zero) : (i32) -> ()
}) : () -> ()
}) : () -> ()

// CHECK: Program output: #[0x00000000#32]
17 changes: 17 additions & 0 deletions Test/Interpreter/LLVM/call_dereferenceable_short.mlir
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// RUN: veir-interpret %s | filecheck %s

// `llvm.dereferenceable = 8` on a one-byte object is UB.

"builtin.module"() ({
"llvm.func"() <{function_type = !llvm.func<void (ptr)>, linkage = #llvm.linkage<external>, sym_name = "foo"}> ({
}) : () -> ()
"func.func"() <{sym_name = "main", function_type = () -> i32}> ({
%one = "llvm.mlir.constant"() <{value = 1 : i64}> : () -> i64
%zero = "llvm.mlir.constant"() <{value = 0 : i32}> : () -> i32
%p = "llvm.alloca"(%one) <{elem_type = i8}> : (i64) -> !llvm.ptr
"llvm.call"(%p) <{callee = @foo, arg_attrs = [{llvm.dereferenceable = 8 : i64}], op_bundle_sizes = array<i32>, operandSegmentSizes = array<i32: 1, 0>}> : (!llvm.ptr) -> ()
"func.return"(%zero) : (i32) -> ()
}) : () -> ()
}) : () -> ()

// CHECK: Undefined behavior
16 changes: 16 additions & 0 deletions Test/Interpreter/LLVM/call_nonnull_null.mlir
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// RUN: veir-interpret %s | filecheck %s

// Passing null to a `llvm.nonnull` argument is UB.

"builtin.module"() ({
"llvm.func"() <{function_type = !llvm.func<void (ptr)>, linkage = #llvm.linkage<external>, sym_name = "foo"}> ({
}) : () -> ()
"func.func"() <{sym_name = "main", function_type = () -> i32}> ({
%zero = "llvm.mlir.constant"() <{value = 0 : i32}> : () -> i32
%null = "llvm.mlir.zero"() : () -> !llvm.ptr
"llvm.call"(%null) <{callee = @foo, arg_attrs = [{llvm.nonnull}], op_bundle_sizes = array<i32>, operandSegmentSizes = array<i32: 1, 0>}> : (!llvm.ptr) -> ()
"func.return"(%zero) : (i32) -> ()
}) : () -> ()
}) : () -> ()

// CHECK: Undefined behavior
15 changes: 15 additions & 0 deletions Test/Interpreter/LLVM/calloc_zeroed.mlir
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// RUN: veir-interpret %s | filecheck %s

"builtin.module"() ({
"llvm.func"() <{function_type = !llvm.func<ptr (i64, i64)>, linkage = #llvm.linkage<external>, sym_name = "calloc"}> ({
}) : () -> ()
"func.func"() <{sym_name = "main", function_type = () -> i64}> ({
%two = "llvm.mlir.constant"() <{value = 2 : i64}> : () -> i64
%four = "llvm.mlir.constant"() <{value = 4 : i64}> : () -> i64
%p = "llvm.call"(%two, %four) <{callee = @calloc, op_bundle_sizes = array<i32>, operandSegmentSizes = array<i32: 2, 0>}> : (i64, i64) -> !llvm.ptr
%r = "llvm.load"(%p) : (!llvm.ptr) -> i64
"func.return"(%r) : (i64) -> ()
}) : () -> ()
}) : () -> ()

// CHECK: Program output: #[0x0000000000000000#64]
17 changes: 17 additions & 0 deletions Test/Interpreter/LLVM/free_alloca.mlir
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// RUN: veir-interpret %s | filecheck %s

// Only heap objects may be freed.

"builtin.module"() ({
"llvm.func"() <{function_type = !llvm.func<void (ptr)>, linkage = #llvm.linkage<external>, sym_name = "free"}> ({
}) : () -> ()
"func.func"() <{sym_name = "main", function_type = () -> i32}> ({
%one = "llvm.mlir.constant"() <{value = 1 : i64}> : () -> i64
%zero = "llvm.mlir.constant"() <{value = 0 : i32}> : () -> i32
%p = "llvm.alloca"(%one) <{elem_type = i64}> : (i64) -> !llvm.ptr
"llvm.call"(%p) <{callee = @free, op_bundle_sizes = array<i32>, operandSegmentSizes = array<i32: 1, 0>}> : (!llvm.ptr) -> ()
"func.return"(%zero) : (i32) -> ()
}) : () -> ()
}) : () -> ()

// CHECK: Undefined behavior
18 changes: 18 additions & 0 deletions Test/Interpreter/LLVM/free_double.mlir
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// RUN: veir-interpret %s | filecheck %s

"builtin.module"() ({
"llvm.func"() <{function_type = !llvm.func<ptr (i64)>, linkage = #llvm.linkage<external>, sym_name = "malloc"}> ({
}) : () -> ()
"llvm.func"() <{function_type = !llvm.func<void (ptr)>, linkage = #llvm.linkage<external>, sym_name = "free"}> ({
}) : () -> ()
"func.func"() <{sym_name = "main", function_type = () -> i32}> ({
%eight = "llvm.mlir.constant"() <{value = 8 : i64}> : () -> i64
%zero = "llvm.mlir.constant"() <{value = 0 : i32}> : () -> i32
%p = "llvm.call"(%eight) <{callee = @malloc, op_bundle_sizes = array<i32>, operandSegmentSizes = array<i32: 1, 0>}> : (i64) -> !llvm.ptr
"llvm.call"(%p) <{callee = @free, op_bundle_sizes = array<i32>, operandSegmentSizes = array<i32: 1, 0>}> : (!llvm.ptr) -> ()
"llvm.call"(%p) <{callee = @free, op_bundle_sizes = array<i32>, operandSegmentSizes = array<i32: 1, 0>}> : (!llvm.ptr) -> ()
"func.return"(%zero) : (i32) -> ()
}) : () -> ()
}) : () -> ()

// CHECK: Undefined behavior
26 changes: 26 additions & 0 deletions Test/Interpreter/LLVM/free_use_after_free.mlir
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// RUN: veir-interpret %s | filecheck %s

"builtin.module"() ({
"llvm.func"() <{function_type = !llvm.func<ptr (i64)>, linkage = #llvm.linkage<external>, sym_name = "malloc"}> ({
}) : () -> ()
"llvm.func"() <{function_type = !llvm.func<void (ptr)>, linkage = #llvm.linkage<external>, sym_name = "free"}> ({
}) : () -> ()
"func.func"() <{sym_name = "main", function_type = () -> i32}> ({
%eight = "llvm.mlir.constant"() <{value = 8 : i64}> : () -> i64
%i = "llvm.mlir.constant"() <{value = 0 : i64}> : () -> i64
%j = "llvm.mlir.constant"() <{value = 0 : i64}> : () -> i64
%three = "llvm.mlir.constant"() <{value = 3 : i32}> : () -> i32
%five = "llvm.mlir.constant"() <{value = 5 : i32}> : () -> i32
%p = "llvm.call"(%eight) <{callee = @malloc, op_bundle_sizes = array<i32>, operandSegmentSizes = array<i32: 1, 0>}> : (i64) -> !llvm.ptr
%q = "llvm.call"(%eight) <{callee = @malloc, op_bundle_sizes = array<i32>, operandSegmentSizes = array<i32: 1, 0>}> : (i64) -> !llvm.ptr
%p1 = "llvm.getelementptr"(%p, %i) <{elem_type = i8, rawConstantIndices = array<i32: -2147483648>}> : (!llvm.ptr, i64) -> !llvm.ptr
%q1 = "llvm.getelementptr"(%q, %j) <{elem_type = i8, rawConstantIndices = array<i32: -2147483648>}> : (!llvm.ptr, i64) -> !llvm.ptr
"llvm.store"(%three, %p1) : (i32, !llvm.ptr) -> ()
"llvm.store"(%five, %q1) : (i32, !llvm.ptr) -> ()
"llvm.call"(%p) <{callee = @free, op_bundle_sizes = array<i32>, operandSegmentSizes = array<i32: 1, 0>}> : (!llvm.ptr) -> ()
%v = "llvm.load"(%p1) : (!llvm.ptr) -> i32
"func.return"(%v) : (i32) -> ()
}) : () -> ()
}) : () -> ()

// CHECK: Undefined behavior
19 changes: 19 additions & 0 deletions Test/Interpreter/LLVM/getelementptr_past_4gib.mlir
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// RUN: veir-interpret %s | filecheck %s

// Pointer offsets are 64 bits wide. Stepping 4 GiB past an 8-byte object
// leaves it, so the load is UB rather than wrapping back to the start.

"builtin.module"() ({
"func.func"() <{sym_name = "main", function_type = () -> i64}> ({
%one = "llvm.mlir.constant"() <{value = 1 : i64}> : () -> i64
%seven = "llvm.mlir.constant"() <{value = 7 : i64}> : () -> i64
%far = "llvm.mlir.constant"() <{value = 4294967296 : i64}> : () -> i64
%p = "llvm.alloca"(%one) <{elem_type = i64}> : (i64) -> !llvm.ptr
"llvm.store"(%seven, %p) : (i64, !llvm.ptr) -> ()
%q = "llvm.getelementptr"(%p, %far) <{elem_type = i8, rawConstantIndices = array<i32: -2147483648>}> : (!llvm.ptr, i64) -> !llvm.ptr
%v = "llvm.load"(%q) : (!llvm.ptr) -> i64
"func.return"(%v) : (i64) -> ()
}) : () -> ()
}) : () -> ()

// CHECK: Undefined behavior
20 changes: 20 additions & 0 deletions Test/Interpreter/LLVM/global_load.mlir
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// RUN: veir-interpret %s | filecheck %s

// Globals are materialized as objects before `main` runs, initialised from
// their `value`, and `llvm.mlir.addressof` yields a pointer to them.

"builtin.module"() ({
"llvm.mlir.global"() <{addr_space = 0 : i32, global_type = i32, linkage = #llvm.linkage<external>, sym_name = "g", value = 41 : i32}> ({
}) : () -> ()
"llvm.func"() <{function_type = !llvm.func<i32 ()>, sym_name = "main"}> ({
%one = "llvm.mlir.constant"() <{value = 1 : i32}> : () -> i32
%g = "llvm.mlir.addressof"() <{global_name = @g}> : () -> !llvm.ptr
%old = "llvm.load"(%g) : (!llvm.ptr) -> i32
%new = "llvm.add"(%old, %one) : (i32, i32) -> i32
"llvm.store"(%new, %g) : (i32, !llvm.ptr) -> ()
%r = "llvm.load"(%g) : (!llvm.ptr) -> i32
"llvm.return"(%r) : (i32) -> ()
}) : () -> ()
}) : () -> ()

// CHECK: Program output: #[0x0000002a#32]
18 changes: 18 additions & 0 deletions Test/Interpreter/LLVM/global_region_initializer.mlir
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// RUN: veir-interpret %s | filecheck %s

// A global with an initializer region starts with the value the region returns.

"builtin.module"() ({
"llvm.mlir.global"() <{addr_space = 0 : i32, global_type = i64, linkage = #llvm.linkage<internal>, sym_name = "g"}> ({
%c = "llvm.mlir.constant"() <{value = 7 : i64}> : () -> i64
%d = "llvm.mul"(%c, %c) : (i64, i64) -> i64
"llvm.return"(%d) : (i64) -> ()
}) : () -> ()
"llvm.func"() <{function_type = !llvm.func<i64 ()>, sym_name = "main"}> ({
%g = "llvm.mlir.addressof"() <{global_name = @g}> : () -> !llvm.ptr
%r = "llvm.load"(%g) : (!llvm.ptr) -> i64
"llvm.return"(%r) : (i64) -> ()
}) : () -> ()
}) : () -> ()

// CHECK: Program output: #[0x0000000000000031#64]
16 changes: 16 additions & 0 deletions Test/Interpreter/LLVM/global_store_constant.mlir
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// RUN: veir-interpret %s | filecheck %s

// Storing to a constant global is UB.

"builtin.module"() ({
"llvm.mlir.global"() <{addr_space = 0 : i32, constant, global_type = i32, linkage = #llvm.linkage<external>, sym_name = "g", value = 41 : i32}> ({
}) : () -> ()
"llvm.func"() <{function_type = !llvm.func<i32 ()>, sym_name = "main"}> ({
%one = "llvm.mlir.constant"() <{value = 1 : i32}> : () -> i32
%g = "llvm.mlir.addressof"() <{global_name = @g}> : () -> !llvm.ptr
"llvm.store"(%one, %g) : (i32, !llvm.ptr) -> ()
"llvm.return"(%one) : (i32) -> ()
}) : () -> ()
}) : () -> ()

// CHECK: Undefined behavior
17 changes: 17 additions & 0 deletions Test/Interpreter/LLVM/global_string.mlir
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// RUN: veir-interpret %s | filecheck %s

// A string-valued global holds its bytes verbatim.

"builtin.module"() ({
"llvm.mlir.global"() <{addr_space = 0 : i32, constant, global_type = !llvm.array<3 x i8>, linkage = #llvm.linkage<internal>, sym_name = "s", value = "hi\00"}> ({
}) : () -> ()
"llvm.func"() <{function_type = !llvm.func<i8 ()>, sym_name = "main"}> ({
%one = "llvm.mlir.constant"() <{value = 1 : i64}> : () -> i64
%s = "llvm.mlir.addressof"() <{global_name = @s}> : () -> !llvm.ptr
%s1 = "llvm.getelementptr"(%s, %one) <{elem_type = i8, rawConstantIndices = array<i32: -2147483648>}> : (!llvm.ptr, i64) -> !llvm.ptr
%c = "llvm.load"(%s1) : (!llvm.ptr) -> i8
"llvm.return"(%c) : (i8) -> ()
}) : () -> ()
}) : () -> ()

// CHECK: Program output: #[0x69#8]
20 changes: 20 additions & 0 deletions Test/Interpreter/LLVM/inttoptr_gap.mlir
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// RUN: veir-interpret %s | filecheck %s

// Objects are separated by guard bytes. An address forged into the gap after
// the first alloca decodes to a pointer past that object's end, so loading
// through it is UB rather than reading the neighbour.

"builtin.module"() ({
"func.func"() <{sym_name = "main", function_type = () -> i8}> ({
%one = "llvm.mlir.constant"() <{value = 1 : i64}> : () -> i64
%p = "llvm.alloca"(%one) <{elem_type = i64}> : (i64) -> !llvm.ptr
%q = "llvm.alloca"(%one) <{elem_type = i64}> : (i64) -> !llvm.ptr
%r = "builtin.unrealized_conversion_cast"(%p) : (!llvm.ptr) -> !riscv.reg
%s = "riscv.addi"(%r) <{value = 10 : i12}> : (!riscv.reg) -> !riscv.reg
%t = "builtin.unrealized_conversion_cast"(%s) : (!riscv.reg) -> !llvm.ptr
%v = "llvm.load"(%t) : (!llvm.ptr) -> i8
"func.return"(%v) : (i8) -> ()
}) : () -> ()
}) : () -> ()

// CHECK: Undefined behavior
21 changes: 21 additions & 0 deletions Test/Interpreter/LLVM/inttoptr_through_memory.mlir
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// RUN: veir-interpret %s | filecheck %s

// An address stored as an integer and loaded back as a pointer denotes the
// object at that address, so the load through it succeeds.

"builtin.module"() ({
"func.func"() <{sym_name = "main", function_type = () -> i64}> ({
%one = "llvm.mlir.constant"() <{value = 1 : i64}> : () -> i64
%v = "llvm.mlir.constant"() <{value = 91 : i64}> : () -> i64
%a = "llvm.alloca"(%one) <{elem_type = i64}> : (i64) -> !llvm.ptr
%b = "llvm.alloca"(%one) <{elem_type = i64}> : (i64) -> !llvm.ptr
"llvm.store"(%v, %a) : (i64, !llvm.ptr) -> ()
%addr = "llvm.ptrtoint"(%a) : (!llvm.ptr) -> i64
"llvm.store"(%addr, %b) : (i64, !llvm.ptr) -> ()
%p = "llvm.load"(%b) : (!llvm.ptr) -> !llvm.ptr
%r = "llvm.load"(%p) : (!llvm.ptr) -> i64
"func.return"(%r) : (i64) -> ()
}) : () -> ()
}) : () -> ()

// CHECK: Program output: #[0x000000000000005b#64]
Loading
Loading