| author | |
| committer | |
| log | ef42ef9ce8d36d26f91669a61f4c57fd3e4d58d7 |
| tree | 2f0d5c4175cf0f01f7e3ebf75cfcec4be31ccc2a |
| parent | dd62f63c04fa21427869abea86bbc5fc090b6562 |
| parent | 08b0cae7778ea0946d595df451b9b4a65ff09abd |
| signature |
Make align expr on fns a compile error in Wasm3 files changed, 44 insertions(+), 4 deletions(-)
src/analyze.cpp+15| ... | ... | @@ -1921,6 +1921,21 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc |
| 1921 | 1921 | } |
| 1922 | 1922 | |
| 1923 | 1923 | if (fn_proto->align_expr != nullptr) { |
| 1924 | if (target_is_wasm(g->zig_target)) { | |
| 1925 | // In Wasm, specifying alignment of function pointers makes little sense | |
| 1926 | // since function pointers are in fact indices to a Wasm table, therefore | |
| 1927 | // any alignment check on those is invalid. This can cause unexpected | |
| 1928 | // behaviour when checking expected alignment with `@ptrToInt(fn_ptr)` | |
| 1929 | // or similar. This commit proposes to make `align` expressions a | |
| 1930 | // compile error when compiled to Wasm architecture. | |
| 1931 | // | |
| 1932 | // Some references: | |
| 1933 | // [1] [Mozilla: WebAssembly Tables](https://developer.mozilla.org/en-US/docs/WebAssembly/Understanding_the_text_format#WebAssembly_tables) | |
| 1934 | // [2] [Sunfishcode's Wasm Ref Manual](https://github.com/sunfishcode/wasm-reference-manual/blob/master/WebAssembly.md#indirect-call) | |
| 1935 | add_node_error(g, fn_proto->align_expr, | |
| 1936 | buf_sprintf("align(N) expr is not allowed on function prototypes in wasm32/wasm64")); | |
| 1937 | return g->builtin_types.entry_invalid; | |
| 1938 | } | |
| 1924 | 1939 | if (!analyze_const_align(g, child_scope, fn_proto->align_expr, &fn_type_id.alignment)) { |
| 1925 | 1940 | return g->builtin_types.entry_invalid; |
| 1926 | 1941 | } |
test/compile_errors.zig+16| ... | ... | @@ -7445,4 +7445,20 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 7445 | 7445 | , &[_][]const u8{ |
| 7446 | 7446 | ":2:75: error: operation caused overflow", |
| 7447 | 7447 | }); |
| 7448 | ||
| 7449 | cases.addCase(x: { | |
| 7450 | var tc = cases.create("align(N) expr function pointers is a compile error", | |
| 7451 | \\export fn foo() align(1) void { | |
| 7452 | \\ return; | |
| 7453 | \\} | |
| 7454 | , &[_][]const u8{ | |
| 7455 | "tmp.zig:1:23: error: align(N) expr is not allowed on function prototypes in wasm32/wasm64", | |
| 7456 | }); | |
| 7457 | tc.target = std.zig.CrossTarget{ | |
| 7458 | .cpu_arch = .wasm32, | |
| 7459 | .os_tag = .freestanding, | |
| 7460 | .abi = .none, | |
| 7461 | }; | |
| 7462 | break :x tc; | |
| 7463 | }); | |
| 7448 | 7464 | } |
test/stage1/behavior/align.zig+13-4| ... | ... | @@ -25,6 +25,9 @@ fn noop1() align(1) void {} |
| 25 | 25 | fn noop4() align(4) void {} |
| 26 | 26 | |
| 27 | 27 | test "function alignment" { |
| 28 | // function alignment is a compile error on wasm32/wasm64 | |
| 29 | if (builtin.arch == .wasm32 or builtin.arch == .wasm64) return error.SkipZigTest; | |
| 30 | ||
| 28 | 31 | expect(derp() == 1234); |
| 29 | 32 | expect(@TypeOf(noop1) == fn () align(1) void); |
| 30 | 33 | expect(@TypeOf(noop4) == fn () align(4) void); |
| ... | ... | @@ -117,6 +120,9 @@ fn sliceExpects4(slice: []align(4) u32) void { |
| 117 | 120 | } |
| 118 | 121 | |
| 119 | 122 | test "implicitly decreasing fn alignment" { |
| 123 | // function alignment is a compile error on wasm32/wasm64 | |
| 124 | if (builtin.arch == .wasm32 or builtin.arch == .wasm64) return error.SkipZigTest; | |
| 125 | ||
| 120 | 126 | testImplicitlyDecreaseFnAlign(alignedSmall, 1234); |
| 121 | 127 | testImplicitlyDecreaseFnAlign(alignedBig, 5678); |
| 122 | 128 | } |
| ... | ... | @@ -133,8 +139,8 @@ fn alignedBig() align(16) i32 { |
| 133 | 139 | } |
| 134 | 140 | |
| 135 | 141 | test "@alignCast functions" { |
| 136 | // TODO investigate why this fails when cross-compiled to wasm. | |
| 137 | if (builtin.os.tag == .wasi) return error.SkipZigTest; | |
| 142 | // function alignment is a compile error on wasm32/wasm64 | |
| 143 | if (builtin.arch == .wasm32 or builtin.arch == .wasm64) return error.SkipZigTest; | |
| 138 | 144 | |
| 139 | 145 | expect(fnExpectsOnly1(simple4) == 0x19); |
| 140 | 146 | } |
| ... | ... | @@ -149,6 +155,9 @@ fn simple4() align(4) i32 { |
| 149 | 155 | } |
| 150 | 156 | |
| 151 | 157 | test "generic function with align param" { |
| 158 | // function alignment is a compile error on wasm32/wasm64 | |
| 159 | if (builtin.arch == .wasm32 or builtin.arch == .wasm64) return error.SkipZigTest; | |
| 160 | ||
| 152 | 161 | expect(whyWouldYouEverDoThis(1) == 0x1); |
| 153 | 162 | expect(whyWouldYouEverDoThis(4) == 0x1); |
| 154 | 163 | expect(whyWouldYouEverDoThis(8) == 0x1); |
| ... | ... | @@ -327,8 +336,8 @@ test "align(@alignOf(T)) T does not force resolution of T" { |
| 327 | 336 | } |
| 328 | 337 | |
| 329 | 338 | test "align(N) on functions" { |
| 330 | // TODO investigate why this fails when cross-compiled to wasm. | |
| 331 | if (builtin.os.tag == .wasi) return error.SkipZigTest; | |
| 339 | // function alignment is a compile error on wasm32/wasm64 | |
| 340 | if (builtin.arch == .wasm32 or builtin.arch == .wasm64) return error.SkipZigTest; | |
| 332 | 341 | |
| 333 | 342 | expect((@ptrToInt(overaligned_fn) & (0x1000 - 1)) == 0); |
| 334 | 343 | } |