Skip to content

Commit

Permalink
Move isConst into validation, check mutability of globals
Browse files Browse the repository at this point in the history
  • Loading branch information
Mauro Bringolf committed Jun 7, 2018
1 parent f47b672 commit efe0844
Show file tree
Hide file tree
Showing 10 changed files with 56 additions and 81 deletions.
2 changes: 1 addition & 1 deletion packages/helper-module-context/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ export class ModuleContext {

defineGlobal(global /*: Global*/) {
const type = global.globalType.valtype;
const mutability = global.mutability;
const mutability = global.globalType.mutability;

this.globals.push({ type, mutability });

Expand Down
21 changes: 16 additions & 5 deletions packages/validation/src/index.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
// @flow

import importOrderValidate from "./import-order";
import isConst from "./is-const";
import typeChecker from "./type-checker";
import { moduleContextFromModuleAST } from "@webassemblyjs/helper-module-context";

export default function validateAST(ast: Program) {
const errors = [];

errors.push(...importOrderValidate(ast));
errors.push(...typeChecker(ast));
const errors = getValidationErrors(ast);

if (errors.length !== 0) {
const errorMessage = "Validation errors:\n" + errors.join("\n");
Expand All @@ -16,7 +15,19 @@ export default function validateAST(ast: Program) {
}
}

export { isConst } from "./is-const";
export function getValidationErrors(ast: Program): Array<string> {
const errors = [];
const moduleContext = moduleContextFromModuleAST(ast.body[0]);

errors.push(...isConst(ast, moduleContext));
errors.push(...importOrderValidate(ast));
errors.push(...typeChecker(ast, moduleContext));

return errors
}

export { getType, typeEq } from "./type-inference";
export { isConst };

export const stack = typeChecker;

52 changes: 31 additions & 21 deletions packages/validation/src/is-const.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
// @flow

import { traverse } from "@webassemblyjs/ast";

/**
* Determine if a sequence of instructions form a constant expression
*
Expand All @@ -8,31 +10,39 @@
* TODO(sven): get_global x should check the mutability of x, but we don't have
* access to the program at this point.
*/
export function isConst(instrs: Array<Instruction>): boolean {
if (instrs.length === 0) {
return false;
}
export default function isConst(ast: Program, moduleContext): Array<string> {

return instrs.reduce((acc, instr) => {
// Bailout
if (acc === false) {
return acc;
}
function isConstInstruction(instr) {
if (instr.id === "const") {
return true;
}

if (instr.id === "const") {
return true;
}
if (instr.id === "get_global") {
const index = instr.args[0].value
return !moduleContext.isMutableGlobal(index);
}

if (instr.id === "get_global") {
return true;
}
// FIXME(sven): this shoudln't be needed, we need to inject our end
// instructions after the validations
if (instr.id === "end") {
return true;
}

// FIXME(sven): this shoudln't be needed, we need to inject our end
// instructions after the validations
if (instr.id === "end") {
return true;
return false;
}

let index = 0;
const errors = []

traverse(ast, {
Global(path) {
const isValid = path.node.init.reduce((acc, instr) => acc && isConstInstruction(instr), true)
if(!isValid) {
errors.push('initializer expression cannot reference mutable global')
}
}
})

return false;
}, true);
return errors;
}

5 changes: 1 addition & 4 deletions packages/validation/src/type-checker.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,11 @@ function checkTypes(a, b) {
}
}

export default function validate(ast) {
export default function validate(ast, moduleContext) {
if (!ast.body || !ast.body[0] || !ast.body[0].fields) {
return [];
}

// Module context
const moduleContext = moduleContextFromModuleAST(ast.body[0]);

errors = [];

// Simulate stack types throughout all function bodies
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
(module
(global (mut i32) (i32.const 1))
(global i32 (get_global 0))

(global i32 (i32.const 0))
(global i32 (get_global 1))
)
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
initializer expression cannot reference mutable global

This file was deleted.

4 changes: 2 additions & 2 deletions packages/validation/test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ describe("validation", () => {

describe("wast", () => {
const pre = f => {
const errors = validations.stack(parse(f));
const errors = validations.getValidationErrors(parse(f));

return errorsToString(errors);
};
Expand All @@ -35,7 +35,7 @@ describe("validation", () => {
const module = wabt.parseWat(suite, f);
const { buffer } = module.toBinary({ write_debug_names: false });

const errors = validations.stack(decode(buffer));
const errors = validations.getValidationErrors(decode(buffer));

return errorsToString(errors);
};
Expand Down
42 changes: 0 additions & 42 deletions packages/validation/test/is-const.js

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// @flow

import { isConst, getType, typeEq } from "@webassemblyjs/validation";
import { getType, typeEq } from "@webassemblyjs/validation";

const { evaluate } = require("../../partial-evaluation");
const { CompileError } = require("../../../errors");
Expand All @@ -12,10 +12,6 @@ export function createInstance(
let value;
const { valtype, mutability } = node.globalType;

if (node.init.length > 0 && isConst(node.init) === false) {
throw new CompileError("constant expression required");
}

// None or multiple constant expressions in the initializer seems not possible
// TODO(sven): find a specification reference for that
// FIXME(sven): +1 because of the implicit end, change the order of validations
Expand Down

0 comments on commit efe0844

Please sign in to comment.