| author | |
| committer | |
| log | 015c899297c9fdc8ef9d0d22af29a7a0d0bdbc5c |
| tree | dc7f91bfdd2d218628a99b9c4484533b4b890246 |
| parent | 4b8077ea8e888382fc73dd8a19c6e9160f2cef46 |
In Wasm, specifying alignment of function pointers makes little sense
since function pointers are in fact indices to a Wasm table, therefore
any alignment check on those is invalid. This can cause unexpected
behaviour when checking expected alignment with `@ptrToInt(fn_ptr)`
or similar. This commit proposes to make `align` expressions a
compile error when compiled to Wasm architecture.
Some references:
[1] [Mozilla: WebAssembly Tables](https://developer.mozilla.org/en-US/docs/WebAssembly/Understanding_the_text_format#WebAssembly_tables)
[2] [Sunfishcode's Wasm Ref Manual](https://github.com/sunfishcode/wasm-reference-manual/blob/master/WebAssembly.md#indirect-call)2 files changed, 28 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/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 | } |