| 1 | const std = @import("std"); |
| 2 | const builtin = @import("builtin"); |
| 3 | const expect = std.testing.expect; |
| 4 | |
| 5 | var pos = [2]f32{ 0.0, 0.0 }; |
| 6 | test "store to global array" { |
| 7 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; |
| 8 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 9 | |
| 10 | try expect(pos[1] == 0.0); |
| 11 | pos = [2]f32{ 0.0, 1.0 }; |
| 12 | try expect(pos[1] == 1.0); |
| 13 | } |
| 14 | |
| 15 | var vpos = @Vector(2, f32){ 0.0, 0.0 }; |
| 16 | test "store to global vector" { |
| 17 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; |
| 18 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 19 | |
| 20 | try expect(vpos[1] == 0.0); |
| 21 | vpos = @Vector(2, f32){ 0.0, 1.0 }; |
| 22 | try expect(vpos[1] == 1.0); |
| 23 | } |
| 24 | |
| 25 | test "slices pointing at the same address as global array." { |
| 26 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 27 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 28 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; |
| 29 | |
| 30 | const S = struct { |
| 31 | const a = [_]u8{ 1, 2, 3 }; |
| 32 | |
| 33 | fn checkAddress(s: []const u8) !void { |
| 34 | for (s, 0..) |*i, j| { |
| 35 | try expect(i == &a[j]); |
| 36 | } |
| 37 | } |
| 38 | }; |
| 39 | |
| 40 | try S.checkAddress(&S.a); |
| 41 | try comptime S.checkAddress(&S.a); |
| 42 | } |
| 43 | |
| 44 | test "global loads can affect liveness" { |
| 45 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; |
| 46 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; |
| 47 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 48 | |
| 49 | const S = struct { |
| 50 | const ByRef = struct { |
| 51 | a: u32, |
| 52 | }; |
| 53 | |
| 54 | var global_ptr: *ByRef = undefined; |
| 55 | |
| 56 | fn f() void { |
| 57 | global_ptr.* = .{ .a = 42 }; |
| 58 | } |
| 59 | }; |
| 60 | |
| 61 | var x: S.ByRef = .{ .a = 1 }; |
| 62 | S.global_ptr = &x; |
| 63 | const y = x; |
| 64 | S.f(); |
| 65 | try std.testing.expect(y.a == 1); |
| 66 | } |
| 67 | |
| 68 | test "global const can be self-referential" { |
| 69 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; |
| 70 | |
| 71 | const S = struct { |
| 72 | self: *const @This(), |
| 73 | x: u32, |
| 74 | |
| 75 | const foo: @This() = .{ .self = &foo, .x = 123 }; |
| 76 | }; |
| 77 | |
| 78 | try std.testing.expect(S.foo.x == 123); |
| 79 | try std.testing.expect(S.foo.self.x == 123); |
| 80 | try std.testing.expect(S.foo.self.self.x == 123); |
| 81 | try std.testing.expect(S.foo.self == &S.foo); |
| 82 | try std.testing.expect(S.foo.self.self == &S.foo); |
| 83 | } |
| 84 | |
| 85 | test "global var can be self-referential" { |
| 86 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; |
| 87 | |
| 88 | const S = struct { |
| 89 | self: *@This(), |
| 90 | x: u32, |
| 91 | |
| 92 | var foo: @This() = .{ .self = &foo, .x = undefined }; |
| 93 | }; |
| 94 | |
| 95 | S.foo.x = 123; |
| 96 | |
| 97 | try std.testing.expect(S.foo.x == 123); |
| 98 | try std.testing.expect(S.foo.self.x == 123); |
| 99 | try std.testing.expect(S.foo.self == &S.foo); |
| 100 | |
| 101 | S.foo.self.x = 456; |
| 102 | |
| 103 | try std.testing.expect(S.foo.x == 456); |
| 104 | try std.testing.expect(S.foo.self.x == 456); |
| 105 | try std.testing.expect(S.foo.self == &S.foo); |
| 106 | |
| 107 | S.foo.self.self.x = 789; |
| 108 | |
| 109 | try std.testing.expect(S.foo.x == 789); |
| 110 | try std.testing.expect(S.foo.self.x == 789); |
| 111 | try std.testing.expect(S.foo.self == &S.foo); |
| 112 | } |
| 113 | |
| 114 | test "global const can be indirectly self-referential" { |
| 115 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; |
| 116 | |
| 117 | const S = struct { |
| 118 | other: *const @This(), |
| 119 | x: u32, |
| 120 | |
| 121 | const foo: @This() = .{ .other = &bar, .x = 123 }; |
| 122 | const bar: @This() = .{ .other = &foo, .x = 456 }; |
| 123 | }; |
| 124 | |
| 125 | try std.testing.expect(S.foo.x == 123); |
| 126 | try std.testing.expect(S.foo.other.x == 456); |
| 127 | try std.testing.expect(S.foo.other.other.x == 123); |
| 128 | try std.testing.expect(S.foo.other.other.other.x == 456); |
| 129 | try std.testing.expect(S.foo.other == &S.bar); |
| 130 | try std.testing.expect(S.foo.other.other == &S.foo); |
| 131 | |
| 132 | try std.testing.expect(S.bar.x == 456); |
| 133 | try std.testing.expect(S.bar.other.x == 123); |
| 134 | try std.testing.expect(S.bar.other.other.x == 456); |
| 135 | try std.testing.expect(S.bar.other.other.other.x == 123); |
| 136 | try std.testing.expect(S.bar.other == &S.foo); |
| 137 | try std.testing.expect(S.bar.other.other == &S.bar); |
| 138 | } |
| 139 | |
| 140 | test "global var can be indirectly self-referential" { |
| 141 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; |
| 142 | |
| 143 | const S = struct { |
| 144 | other: *@This(), |
| 145 | x: u32, |
| 146 | |
| 147 | var foo: @This() = .{ .other = &bar, .x = undefined }; |
| 148 | var bar: @This() = .{ .other = &foo, .x = undefined }; |
| 149 | }; |
| 150 | |
| 151 | S.foo.other.x = 123; // bar.x |
| 152 | S.foo.other.other.x = 456; // foo.x |
| 153 | |
| 154 | try std.testing.expect(S.foo.x == 456); |
| 155 | try std.testing.expect(S.foo.other.x == 123); |
| 156 | try std.testing.expect(S.foo.other.other.x == 456); |
| 157 | try std.testing.expect(S.foo.other.other.other.x == 123); |
| 158 | try std.testing.expect(S.foo.other == &S.bar); |
| 159 | try std.testing.expect(S.foo.other.other == &S.foo); |
| 160 | |
| 161 | S.bar.other.x = 111; // foo.x |
| 162 | S.bar.other.other.x = 222; // bar.x |
| 163 | |
| 164 | try std.testing.expect(S.bar.x == 222); |
| 165 | try std.testing.expect(S.bar.other.x == 111); |
| 166 | try std.testing.expect(S.bar.other.other.x == 222); |
| 167 | try std.testing.expect(S.bar.other.other.other.x == 111); |
| 168 | try std.testing.expect(S.bar.other == &S.foo); |
| 169 | try std.testing.expect(S.bar.other.other == &S.bar); |
| 170 | } |
| 171 | |
| 172 | pub const Callbacks = extern struct { |
| 173 | key_callback: *const fn (key: i32) callconv(.c) i32, |
| 174 | }; |
| 175 | |
| 176 | var callbacks: Callbacks = undefined; |
| 177 | var callbacks_loaded: bool = false; |
| 178 | |
| 179 | test "function pointer field call on global extern struct, conditional on global" { |
| 180 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; |
| 181 | |
| 182 | if (callbacks_loaded) { |
| 183 | try std.testing.expectEqual(42, callbacks.key_callback(42)); |
| 184 | } |
| 185 | } |
| 186 | |
| 187 | test "function pointer field call on global extern struct" { |
| 188 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 189 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; |
| 190 | |
| 191 | const S = struct { |
| 192 | fn keyCallback(key: i32) callconv(.c) i32 { |
| 193 | return key; |
| 194 | } |
| 195 | }; |
| 196 | |
| 197 | callbacks = Callbacks{ .key_callback = S.keyCallback }; |
| 198 | try std.testing.expectEqual(42, callbacks.key_callback(42)); |
| 199 | } |