File tree Expand file tree Collapse file tree 10 files changed +50
-74
lines changed
helper-module-context/src
webassemblyjs/src/interpreter/runtime/values Expand file tree Collapse file tree 10 files changed +50
-74
lines changed Original file line number Diff line number Diff line change @@ -207,7 +207,7 @@ export class ModuleContext {
207
207
208
208
defineGlobal ( global /*: Global*/ ) {
209
209
const type = global . globalType . valtype ;
210
- const mutability = global . mutability ;
210
+ const mutability = global . globalType . mutability ;
211
211
212
212
this . globals . push ( { type, mutability } ) ;
213
213
Original file line number Diff line number Diff line change 1
1
// @flow
2
2
3
3
import importOrderValidate from "./import-order" ;
4
+ import isConst from "./is-const" ;
4
5
import typeChecker from "./type-checker" ;
6
+ import { moduleContextFromModuleAST } from "@webassemblyjs/helper-module-context" ;
5
7
6
8
export default function validateAST ( ast : Program ) {
7
- const errors = [ ] ;
8
-
9
- errors . push ( ...importOrderValidate ( ast ) ) ;
10
- errors . push ( ...typeChecker ( ast ) ) ;
9
+ const errors = getValidationErrors ( ast ) ;
11
10
12
11
if ( errors . length !== 0 ) {
13
12
const errorMessage = "Validation errors:\n" + errors . join ( "\n" ) ;
@@ -16,7 +15,18 @@ export default function validateAST(ast: Program) {
16
15
}
17
16
}
18
17
19
- export { isConst } from "./is-const" ;
18
+ export function getValidationErrors ( ast : Program ) : Array < string > {
19
+ const errors = [ ] ;
20
+ const moduleContext = moduleContextFromModuleAST ( ast . body [ 0 ] ) ;
21
+
22
+ errors . push ( ...isConst ( ast , moduleContext ) ) ;
23
+ errors . push ( ...importOrderValidate ( ast ) ) ;
24
+ errors . push ( ...typeChecker ( ast , moduleContext ) ) ;
25
+
26
+ return errors ;
27
+ }
28
+
20
29
export { getType , typeEq } from "./type-inference" ;
30
+ export { isConst } ;
21
31
22
32
export const stack = typeChecker ;
Original file line number Diff line number Diff line change 1
1
// @flow
2
2
3
+ import { traverse } from "@webassemblyjs/ast" ;
4
+
3
5
/**
4
6
* Determine if a sequence of instructions form a constant expression
5
7
*
8
10
* TODO(sven): get_global x should check the mutability of x, but we don't have
9
11
* access to the program at this point.
10
12
*/
11
- export function isConst ( instrs : Array < Instruction > ) : boolean {
12
- if ( instrs . length === 0 ) {
13
- return false ;
14
- }
15
-
16
- return instrs . reduce ( ( acc , instr ) => {
17
- // Bailout
18
- if ( acc === false ) {
19
- return acc ;
20
- }
21
-
13
+ export default function isConst (
14
+ ast : Program ,
15
+ moduleContext : Object
16
+ ) : Array < string > {
17
+ function isConstInstruction ( instr ) : boolean {
22
18
if ( instr . id === "const" ) {
23
19
return true ;
24
20
}
25
21
26
22
if ( instr . id === "get_global" ) {
27
- return true ;
23
+ const index = instr . args [ 0 ] . value ;
24
+ return ! moduleContext . isMutableGlobal ( index ) ;
28
25
}
29
26
30
27
// FIXME(sven): this shoudln't be needed, we need to inject our end
@@ -34,5 +31,21 @@ export function isConst(instrs: Array<Instruction>): boolean {
34
31
}
35
32
36
33
return false ;
37
- } , true ) ;
34
+ }
35
+
36
+ const errors = [ ] ;
37
+
38
+ traverse ( ast , {
39
+ Global ( path ) {
40
+ const isValid = path . node . init . reduce (
41
+ ( acc , instr ) => acc && isConstInstruction ( instr ) ,
42
+ true
43
+ ) ;
44
+ if ( ! isValid ) {
45
+ errors . push ( "initializer expression cannot reference mutable global" ) ;
46
+ }
47
+ }
48
+ } ) ;
49
+
50
+ return errors ;
38
51
}
Original file line number Diff line number Diff line change 1
1
import { traverse , isInstruction } from "@webassemblyjs/ast" ;
2
2
3
- import { moduleContextFromModuleAST } from "@webassemblyjs/helper-module-context" ;
4
3
import getType from "./type-checker/get-type.js" ;
5
4
import { ANY , POLYMORPHIC } from "./type-checker/types.js" ;
6
5
@@ -30,14 +29,11 @@ function checkTypes(a, b) {
30
29
}
31
30
}
32
31
33
- export default function validate ( ast ) {
32
+ export default function validate ( ast , moduleContext ) {
34
33
if ( ! ast . body || ! ast . body [ 0 ] || ! ast . body [ 0 ] . fields ) {
35
34
return [ ] ;
36
35
}
37
36
38
- // Module context
39
- const moduleContext = moduleContextFromModuleAST ( ast . body [ 0 ] ) ;
40
-
41
37
errors = [ ] ;
42
38
43
39
// Simulate stack types throughout all function bodies
Original file line number Diff line number Diff line change 1
1
(module
2
2
(global (mut i32 ) (i32.const 1 ))
3
3
(global i32 (get_global 0 ))
4
+
5
+ (global i32 (i32.const 0 ))
6
+ (global i32 (get_global 1 ))
4
7
)
Original file line number Diff line number Diff line change
1
+ initializer expression cannot reference mutable global
Load Diff This file was deleted.
Original file line number Diff line number Diff line change @@ -22,7 +22,7 @@ describe("validation", () => {
22
22
23
23
describe ( "wast" , ( ) => {
24
24
const pre = f => {
25
- const errors = validations . stack ( parse ( f ) ) ;
25
+ const errors = validations . getValidationErrors ( parse ( f ) ) ;
26
26
27
27
return errorsToString ( errors ) ;
28
28
} ;
@@ -35,7 +35,7 @@ describe("validation", () => {
35
35
const module = wabt . parseWat ( suite , f ) ;
36
36
const { buffer } = module . toBinary ( { write_debug_names : false } ) ;
37
37
38
- const errors = validations . stack ( decode ( buffer ) ) ;
38
+ const errors = validations . getValidationErrors ( decode ( buffer ) ) ;
39
39
40
40
return errorsToString ( errors ) ;
41
41
} ;
Load Diff This file was deleted.
Original file line number Diff line number Diff line change 1
1
// @flow
2
2
3
- import { isConst , getType , typeEq } from "@webassemblyjs/validation" ;
3
+ import { getType , typeEq } from "@webassemblyjs/validation" ;
4
4
5
5
const { evaluate } = require ( "../../partial-evaluation" ) ;
6
6
const { CompileError } = require ( "../../../errors" ) ;
@@ -12,10 +12,6 @@ export function createInstance(
12
12
let value ;
13
13
const { valtype, mutability } = node . globalType ;
14
14
15
- if ( node . init . length > 0 && isConst ( node . init ) === false ) {
16
- throw new CompileError ( "constant expression required" ) ;
17
- }
18
-
19
15
// None or multiple constant expressions in the initializer seems not possible
20
16
// TODO(sven): find a specification reference for that
21
17
// FIXME(sven): +1 because of the implicit end, change the order of validations
You can’t perform that action at this time.
0 commit comments