Skip to content

Commit 0b8acfc

Browse files
authored
ctor-eval fixes (WebAssembly#996)
* fix wasm-ctor-eval, we need to look for the STACKTOP etc. imports, they may not be named, if this build is not with -g * pack memory after ctor evalling, since we merge it up which is less efficient * do some useful opts after ctor-evalling, to clean things up
1 parent 7ba0e4e commit 0b8acfc

19 files changed

Lines changed: 171 additions & 34 deletions

src/ast/global-utils.h

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/*
2+
* Copyright 2017 WebAssembly Community Group participants
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#ifndef wasm_ast_global_h
18+
#define wasm_ast_global_h
19+
20+
#include <algorithm>
21+
#include <vector>
22+
23+
#include "literal.h"
24+
#include "wasm.h"
25+
26+
namespace wasm {
27+
28+
namespace GlobalUtils {
29+
// find a global initialized to the value of an import, or null if no such global
30+
inline Global* getGlobalInitializedToImport(Module&wasm, Name module, Name base) {
31+
// find the import
32+
Name imported;
33+
for (auto& import : wasm.imports) {
34+
if (import->module == module && import->base == base) {
35+
imported = import->name;
36+
break;
37+
}
38+
}
39+
if (imported.isNull()) return nullptr;
40+
// find a global inited to it
41+
for (auto& global : wasm.globals) {
42+
if (auto* init = global->init->dynCast<GetGlobal>()) {
43+
if (init->name == imported) {
44+
return global.get();
45+
}
46+
}
47+
}
48+
return nullptr;
49+
}
50+
};
51+
52+
} // namespace wasm
53+
54+
#endif // wasm_ast_global_h
55+

src/tools/wasm-ctor-eval.cpp

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#include "wasm-interpreter.h"
3333
#include "wasm-builder.h"
3434
#include "ast/memory-utils.h"
35+
#include "ast/global-utils.h"
3536

3637
using namespace wasm;
3738

@@ -153,10 +154,14 @@ class EvallingModuleInstance : public ModuleInstanceBase<EvallingGlobalManager,
153154
// prepare scratch memory
154155
stack.resize(STACK_SIZE);
155156
// fill usable values for stack imports
156-
auto total = STACK_START + STACK_SIZE;
157-
globals["STACKTOP"] = Literal(int32_t(STACK_START));
158-
globals["STACK_MAX"] = Literal(int32_t(STACK_START + STACK_SIZE));
157+
if (auto* stackTop = GlobalUtils::getGlobalInitializedToImport(wasm, "env", "STACKTOP")) {
158+
globals[stackTop->name] = Literal(int32_t(STACK_START));
159+
}
160+
if (auto* stackMax = GlobalUtils::getGlobalInitializedToImport(wasm, "env", "STACK_MAX")) {
161+
globals[stackMax->name] = Literal(int32_t(STACK_START));
162+
}
159163
// tell the module to accept writes up to the stack end
164+
auto total = STACK_START + STACK_SIZE;
160165
memorySize = total / Memory::kPageSize;
161166
}
162167

@@ -398,6 +403,17 @@ int main(int argc, const char* argv[]) {
398403
}
399404
evalCtors(wasm, ctors);
400405

406+
// Do some useful optimizations after the evalling
407+
{
408+
PassRunner passRunner(&wasm);
409+
passRunner.add("memory-packing"); // we flattened it, so re-optimize
410+
passRunner.add("remove-unused-names");
411+
passRunner.add("dce");
412+
passRunner.add("merge-blocks");
413+
passRunner.add("vacuum");
414+
passRunner.run();
415+
}
416+
401417
if (options.extra.count("output") > 0) {
402418
if (options.debug) std::cerr << "writing..." << std::endl;
403419
ModuleWriter writer;

test/ctor-eval/bad-indirect-call.wast.out

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
(table 1 1 anyfunc)
44
(elem (i32.const 0) $call-indirect)
55
(memory $0 256 256)
6-
(data (i32.const 0) "\00\00\00\00\00\00\00\00\00\00waka waka waka waka waka")
6+
(data (i32.const 10) "waka waka waka waka waka")
77
(export "test1" (func $test1))
88
(func $test1 (type $v)
99
(call_indirect $v

test/ctor-eval/bad-indirect-call2.wast.out

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
(table 2 2 anyfunc)
66
(elem (i32.const 0) $_abort $call-indirect)
77
(memory $0 256 256)
8-
(data (i32.const 0) "\00\00\00\00\00\00\00\00\00\00waka waka waka waka waka")
8+
(data (i32.const 10) "waka waka waka waka waka")
99
(export "test1" (func $test1))
1010
(func $test1 (type $v)
1111
(call_indirect $v

test/ctor-eval/basics-flatten.wast.out

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
(table 1 1 anyfunc)
44
(elem (i32.const 0) $call-indirect)
55
(memory $0 256 256)
6-
(data (i32.const 0) "\00\00\00\00\00\00\00\00\00\00nas\00\00\00aka\00yzkx waka wakm\00\00\00\00\00\00C")
6+
(data (i32.const 10) "nas\00\00\00aka\00yzkx waka wakm\00\00\00\00\00\00C")
77
(export "test1" (func $test1))
88
(export "test2" (func $test2))
99
(export "test3" (func $test3))
@@ -17,9 +17,6 @@
1717
(nop)
1818
)
1919
(func $safe-to-call (type $v)
20-
(drop
21-
(i32.const 1)
22-
)
2320
(i32.store8
2421
(i32.const 10)
2522
(i32.const 110)

test/ctor-eval/basics.wast.out

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
(table 1 1 anyfunc)
44
(elem (i32.const 0) $call-indirect)
55
(memory $0 256 256)
6-
(data (i32.const 0) "\00\00\00\00\00\00\00\00\00\00nas\00\00\00aka yzkx waka wakm\00\00\00\00\00\00C")
6+
(data (i32.const 10) "nas\00\00\00aka yzkx waka wakm\00\00\00\00\00\00C")
77
(export "test1" (func $test1))
88
(export "test2" (func $test2))
99
(export "test3" (func $test3))
@@ -17,9 +17,6 @@
1717
(nop)
1818
)
1919
(func $safe-to-call (type $v)
20-
(drop
21-
(i32.const 1)
22-
)
2320
(i32.store8
2421
(i32.const 10)
2522
(i32.const 110)

test/ctor-eval/imported-min.wast

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
(module
2+
(memory 256 256)
3+
(data (i32.const 10) "waka waka waka waka waka")
4+
;; stack imports are special
5+
(import "env" "STACKTOP" (global $STACKTOP$asm2wasm$import i32))
6+
(import "env" "STACK_MAX" (global $STACK_MAX$asm2wasm$import i32))
7+
;; other imports must not be touched!
8+
(import "env" "tempDoublePtr" (global $tempDoublePtr i32))
9+
(export "test1" $test1)
10+
(export "test2" $test2)
11+
(export "test3" $test3)
12+
;; ok to modify a global, if we keep it the same value
13+
(global $mine (mut i32) (i32.const 1))
14+
;; stack imports are ok to use. their uses are the same as other
15+
;; globals - must keep the same value (which means, unwind the stack)
16+
;; here the global names are "minified"
17+
(global $global0 (mut i32) (get_global $STACKTOP$asm2wasm$import))
18+
(global $global1 (mut i32) (get_global $STACK_MAX$asm2wasm$import))
19+
;; a global initialized by an import, so bad, but ok if not used
20+
(global $do-not-use (mut i32) (get_global $tempDoublePtr))
21+
(func $test1
22+
(local $temp i32)
23+
(set_global $mine (i32.const 1))
24+
(set_local $temp (get_global $global0))
25+
(set_global $global0 (i32.const 1337)) ;; bad
26+
(set_global $global0 (get_local $temp)) ;; save us
27+
(set_global $global1 (i32.const 913370)) ;; bad
28+
(set_global $global1 (get_local $temp)) ;; save us
29+
;; use the stack memory
30+
(i32.store (get_local $temp) (i32.const 1337))
31+
(if
32+
(i32.ne
33+
(i32.load (get_local $temp))
34+
(i32.const 1337)
35+
)
36+
(unreachable) ;; they should be equal, never get here
37+
)
38+
;; finally, do a valid store
39+
(i32.store8 (i32.const 12) (i32.const 115))
40+
)
41+
(func $test2
42+
(set_global $tempDoublePtr (i32.const 1)) ;; bad!
43+
(i32.store8 (i32.const 13) (i32.const 115))
44+
)
45+
(func $test3
46+
(i32.store8 (i32.const 14) (i32.const 115))
47+
)
48+
)
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
test1,test2,test3
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
(module
2+
(type $0 (func))
3+
(import "env" "STACKTOP" (global $STACKTOP$asm2wasm$import i32))
4+
(import "env" "STACK_MAX" (global $STACK_MAX$asm2wasm$import i32))
5+
(import "env" "tempDoublePtr" (global $tempDoublePtr i32))
6+
(global $mine (mut i32) (i32.const 1))
7+
(global $global0 (mut i32) (get_global $STACKTOP$asm2wasm$import))
8+
(global $global1 (mut i32) (get_global $STACK_MAX$asm2wasm$import))
9+
(global $do-not-use (mut i32) (get_global $tempDoublePtr))
10+
(memory $0 256 256)
11+
(data (i32.const 10) "wasa waka waka waka waka")
12+
(export "test1" (func $test1))
13+
(export "test2" (func $test2))
14+
(export "test3" (func $test3))
15+
(func $test1 (type $0)
16+
(local $temp i32)
17+
(nop)
18+
)
19+
(func $test2 (type $0)
20+
(set_global $tempDoublePtr
21+
(i32.const 1)
22+
)
23+
(i32.store8
24+
(i32.const 13)
25+
(i32.const 115)
26+
)
27+
)
28+
(func $test3 (type $0)
29+
(i32.store8
30+
(i32.const 14)
31+
(i32.const 115)
32+
)
33+
)
34+
)

test/ctor-eval/imported.wast.out

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
(global $STACK_MAX (mut i32) (get_global $STACK_MAX$asm2wasm$import))
99
(global $do-not-use (mut i32) (get_global $tempDoublePtr))
1010
(memory $0 256 256)
11-
(data (i32.const 0) "\00\00\00\00\00\00\00\00\00\00wasa waka waka waka waka")
11+
(data (i32.const 10) "wasa waka waka waka waka")
1212
(export "test1" (func $test1))
1313
(export "test2" (func $test2))
1414
(export "test3" (func $test3))

0 commit comments

Comments
 (0)