authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2020-05-26 17:16:25+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2020-05-26 17:17:32+02:00
log015c899297c9fdc8ef9d0d22af29a7a0d0bdbc5c
treedc7f91bfdd2d218628a99b9c4484533b4b890246
parent4b8077ea8e888382fc73dd8a19c6e9160f2cef46

Make align expr on fns a compile error in Wasm

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,6 +1921,21 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc
1921 }1921 }
19221922
1923 if (fn_proto->align_expr != nullptr) {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 if (!analyze_const_align(g, child_scope, fn_proto->align_expr, &fn_type_id.alignment)) {1939 if (!analyze_const_align(g, child_scope, fn_proto->align_expr, &fn_type_id.alignment)) {
1925 return g->builtin_types.entry_invalid;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,6 +25,9 @@ fn noop1() align(1) void {}
25fn noop4() align(4) void {}25fn noop4() align(4) void {}
2626
27test "function alignment" {27test "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 expect(derp() == 1234);31 expect(derp() == 1234);
29 expect(@TypeOf(noop1) == fn () align(1) void);32 expect(@TypeOf(noop1) == fn () align(1) void);
30 expect(@TypeOf(noop4) == fn () align(4) void);33 expect(@TypeOf(noop4) == fn () align(4) void);
...@@ -117,6 +120,9 @@ fn sliceExpects4(slice: []align(4) u32) void {...@@ -117,6 +120,9 @@ fn sliceExpects4(slice: []align(4) u32) void {
117}120}
118121
119test "implicitly decreasing fn alignment" {122test "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 testImplicitlyDecreaseFnAlign(alignedSmall, 1234);126 testImplicitlyDecreaseFnAlign(alignedSmall, 1234);
121 testImplicitlyDecreaseFnAlign(alignedBig, 5678);127 testImplicitlyDecreaseFnAlign(alignedBig, 5678);
122}128}
...@@ -133,8 +139,8 @@ fn alignedBig() align(16) i32 {...@@ -133,8 +139,8 @@ fn alignedBig() align(16) i32 {
133}139}
134140
135test "@alignCast functions" {141test "@alignCast functions" {
136 // TODO investigate why this fails when cross-compiled to wasm.142 // function alignment is a compile error on wasm32/wasm64
137 if (builtin.os.tag == .wasi) return error.SkipZigTest;143 if (builtin.arch == .wasm32 or builtin.arch == .wasm64) return error.SkipZigTest;
138144
139 expect(fnExpectsOnly1(simple4) == 0x19);145 expect(fnExpectsOnly1(simple4) == 0x19);
140}146}
...@@ -149,6 +155,9 @@ fn simple4() align(4) i32 {...@@ -149,6 +155,9 @@ fn simple4() align(4) i32 {
149}155}
150156
151test "generic function with align param" {157test "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 expect(whyWouldYouEverDoThis(1) == 0x1);161 expect(whyWouldYouEverDoThis(1) == 0x1);
153 expect(whyWouldYouEverDoThis(4) == 0x1);162 expect(whyWouldYouEverDoThis(4) == 0x1);
154 expect(whyWouldYouEverDoThis(8) == 0x1);163 expect(whyWouldYouEverDoThis(8) == 0x1);
...@@ -327,8 +336,8 @@ test "align(@alignOf(T)) T does not force resolution of T" {...@@ -327,8 +336,8 @@ test "align(@alignOf(T)) T does not force resolution of T" {
327}336}
328337
329test "align(N) on functions" {338test "align(N) on functions" {
330 // TODO investigate why this fails when cross-compiled to wasm.339 // function alignment is a compile error on wasm32/wasm64
331 if (builtin.os.tag == .wasi) return error.SkipZigTest;340 if (builtin.arch == .wasm32 or builtin.arch == .wasm64) return error.SkipZigTest;
332341
333 expect((@ptrToInt(overaligned_fn) & (0x1000 - 1)) == 0);342 expect((@ptrToInt(overaligned_fn) & (0x1000 - 1)) == 0);
334}343}