Bug 1249524 - Baldr: add the other (param) declaration form to the text format (r=mbx)

MozReview-Commit-ID: o6CjKm19LM
This commit is contained in:
Luke Wagner 2016-02-19 14:26:48 -06:00
parent 0fa868f3ee
commit b63f04a989
3 changed files with 85 additions and 71 deletions

View File

@ -69,7 +69,7 @@ class WasmName
const char16_t* begin() const { return begin_; } const char16_t* begin() const { return begin_; }
const char16_t* end() const { return end_; } const char16_t* end() const { return end_; }
size_t length() const { MOZ_ASSERT(begin_ != nullptr); return end_ - begin_; } size_t length() const { MOZ_ASSERT(begin_ != nullptr); return end_ - begin_; }
bool isEmpty() const { return begin_ == nullptr; } bool empty() const { return begin_ == nullptr; }
}; };
class WasmRef class WasmRef
@ -86,11 +86,11 @@ class WasmRef
WasmRef(WasmName name, uint32_t index) WasmRef(WasmName name, uint32_t index)
: name_(name), index_(index) : name_(name), index_(index)
{ {
MOZ_ASSERT(name.isEmpty() ^ (index == WasmNoIndex)); MOZ_ASSERT(name.empty() ^ (index == WasmNoIndex));
MOZ_ASSERT(!isInvalid()); MOZ_ASSERT(!isInvalid());
} }
bool isInvalid() const { bool isInvalid() const {
return name_.isEmpty() && index_ == WasmNoIndex; return name_.empty() && index_ == WasmNoIndex;
} }
WasmName name() const { WasmName name() const {
return name_; return name_;
@ -421,22 +421,22 @@ class WasmAstFunc : public WasmAstNode
{ {
WasmName name_; WasmName name_;
WasmRef sig_; WasmRef sig_;
WasmAstValTypeVector varTypes_; WasmAstValTypeVector vars_;
WasmNameVector varNames_; WasmNameVector localNames_;
WasmAstExprVector body_; WasmAstExprVector body_;
public: public:
WasmAstFunc(WasmName name, WasmRef sig, WasmAstValTypeVector&& varTypes, WasmAstFunc(WasmName name, WasmRef sig, WasmAstValTypeVector&& vars,
WasmNameVector&& varNames, WasmAstExprVector&& body) WasmNameVector&& locals, WasmAstExprVector&& body)
: name_(name), : name_(name),
sig_(sig), sig_(sig),
varTypes_(Move(varTypes)), vars_(Move(vars)),
varNames_(Move(varNames)), localNames_(Move(locals)),
body_(Move(body)) body_(Move(body))
{} {}
WasmRef& sig() { return sig_; } WasmRef& sig() { return sig_; }
const WasmAstValTypeVector& varTypes() const { return varTypes_; } const WasmAstValTypeVector& vars() const { return vars_; }
const WasmNameVector& varNames() const { return varNames_; } const WasmNameVector& locals() const { return localNames_; }
const WasmAstExprVector& body() const { return body_; } const WasmAstExprVector& body() const { return body_; }
WasmName name() const { return name_; } WasmName name() const { return name_; }
}; };
@ -2523,9 +2523,21 @@ ParseExprInsideParens(WasmParseContext& c)
static bool static bool
ParseValueType(WasmParseContext& c, WasmAstValTypeVector* vec) ParseValueType(WasmParseContext& c, WasmAstValTypeVector* vec)
{ {
WasmToken valueType; WasmToken token;
return c.ts.match(WasmToken::ValueType, &valueType, c.error) && return c.ts.match(WasmToken::ValueType, &token, c.error) &&
vec->append(valueType.valueType()); vec->append(token.valueType());
}
static bool
ParseValueTypeList(WasmParseContext& c, WasmAstValTypeVector* vec)
{
WasmToken token;
while (c.ts.getIf(WasmToken::ValueType, &token)) {
if (!vec->append(token.valueType()))
return false;
}
return true;
} }
static bool static bool
@ -2536,20 +2548,37 @@ ParseResult(WasmParseContext& c, ExprType* result)
return false; return false;
} }
WasmToken valueType; WasmToken token;
if (!c.ts.match(WasmToken::ValueType, &valueType, c.error)) if (!c.ts.match(WasmToken::ValueType, &token, c.error))
return false; return false;
*result = ToExprType(valueType.valueType()); *result = ToExprType(token.valueType());
return true; return true;
} }
static bool
ParseLocal(WasmParseContext& c, WasmNameVector* locals, WasmAstValTypeVector* localTypes)
{
return locals->append(c.ts.getIfName()) &&
ParseValueType(c, localTypes);
}
static bool
ParseParam(WasmParseContext& c, WasmNameVector* locals, WasmAstValTypeVector* args)
{
if (c.ts.peek().kind() == WasmToken::Name)
return ParseLocal(c, locals, args);
return locals->append(WasmName()) &&
ParseValueTypeList(c, args);
}
static WasmAstFunc* static WasmAstFunc*
ParseFunc(WasmParseContext& c, WasmAstModule* module) ParseFunc(WasmParseContext& c, WasmAstModule* module)
{ {
WasmAstValTypeVector vars(c.lifo); WasmAstValTypeVector vars(c.lifo);
WasmAstValTypeVector args(c.lifo); WasmAstValTypeVector args(c.lifo);
WasmNameVector varNames(c.lifo); WasmNameVector locals(c.lifo);
WasmName funcName = c.ts.getIfName(); WasmName funcName = c.ts.getIfName();
@ -2574,14 +2603,17 @@ ParseFunc(WasmParseContext& c, WasmAstModule* module)
WasmToken token = c.ts.get(); WasmToken token = c.ts.get();
switch (token.kind()) { switch (token.kind()) {
case WasmToken::Local: case WasmToken::Local:
case WasmToken::Param: { if (!ParseLocal(c, &locals, &vars))
WasmName name = c.ts.getIfName(); return nullptr;
if (!varNames.append(name)) break;
return nullptr; case WasmToken::Param:
if (!ParseValueType(c, token.kind() == WasmToken::Local ? &vars : &args)) if (!vars.empty()) {
c.ts.generateError(token, c.error);
return nullptr;
}
if (!ParseParam(c, &locals, &args))
return nullptr; return nullptr;
break; break;
}
case WasmToken::Result: case WasmToken::Result:
if (!ParseResult(c, &result)) if (!ParseResult(c, &result))
return nullptr; return nullptr;
@ -2604,7 +2636,7 @@ ParseFunc(WasmParseContext& c, WasmAstModule* module)
sig.setIndex(sigIndex); sig.setIndex(sigIndex);
} }
return new(c.lifo) WasmAstFunc(funcName, sig, Move(vars), Move(varNames), Move(body)); return new(c.lifo) WasmAstFunc(funcName, sig, Move(vars), Move(locals), Move(body));
} }
static bool static bool
@ -2617,7 +2649,7 @@ ParseFuncType(WasmParseContext& c, WasmAstSig* sig)
WasmToken token = c.ts.get(); WasmToken token = c.ts.get();
switch (token.kind()) { switch (token.kind()) {
case WasmToken::Param: case WasmToken::Param:
if (!ParseValueType(c, &args)) if (!ParseValueTypeList(c, &args))
return false; return false;
break; break;
case WasmToken::Result: case WasmToken::Result:
@ -2884,28 +2916,28 @@ class Resolver
varMap_.clear(); varMap_.clear();
} }
bool registerSigName(WasmName name, size_t index) { bool registerSigName(WasmName name, size_t index) {
return registerName(sigMap_, name, index); return name.empty() || registerName(sigMap_, name, index);
} }
bool registerFuncName(WasmName name, size_t index) { bool registerFuncName(WasmName name, size_t index) {
return registerName(funcMap_, name, index); return name.empty() || registerName(funcMap_, name, index);
} }
bool registerImportName(WasmName name, size_t index) { bool registerImportName(WasmName name, size_t index) {
return registerName(importMap_, name, index); return name.empty() || registerName(importMap_, name, index);
} }
bool registerVarName(WasmName name, size_t index) { bool registerVarName(WasmName name, size_t index) {
return registerName(varMap_, name, index); return name.empty() || registerName(varMap_, name, index);
} }
bool resolveSigRef(WasmRef& ref) { bool resolveSigRef(WasmRef& ref) {
return resolveRef(sigMap_, ref); return ref.name().empty() || resolveRef(sigMap_, ref);
} }
bool resolveFuncRef(WasmRef& ref) { bool resolveFuncRef(WasmRef& ref) {
return resolveRef(funcMap_, ref); return ref.name().empty() || resolveRef(funcMap_, ref);
} }
bool resolveImportRef(WasmRef& ref) { bool resolveImportRef(WasmRef& ref) {
return resolveRef(importMap_, ref); return ref.name().empty() || resolveRef(importMap_, ref);
} }
bool resolveVarRef(WasmRef& ref) { bool resolveVarRef(WasmRef& ref) {
return resolveRef(varMap_, ref); return ref.name().empty() || resolveRef(varMap_, ref);
} }
bool fail(const char*message) { bool fail(const char*message) {
error_->reset(JS_smprintf("%s", message)); error_->reset(JS_smprintf("%s", message));
@ -2947,12 +2979,13 @@ ResolveCall(Resolver& r, WasmAstCall& c)
if (!ResolveArgs(r, c.args())) if (!ResolveArgs(r, c.args()))
return false; return false;
if (c.func().name().isEmpty()) if (c.expr() == Expr::Call) {
return true; if (!r.resolveFuncRef(c.func()))
return r.fail("function not found");
if (c.expr() == Expr::Call ? !r.resolveFuncRef(c.func()) } else {
: !r.resolveImportRef(c.func())) { MOZ_ASSERT(c.expr() == Expr::CallImport);
return r.fail("function not found"); if (!r.resolveImportRef(c.func()))
return r.fail("import not found");
} }
return true; return true;
@ -2967,9 +3000,6 @@ ResolveCallIndirect(Resolver& r, WasmAstCallIndirect& c)
if (!ResolveArgs(r, c.args())) if (!ResolveArgs(r, c.args()))
return false; return false;
if (c.sig().name().isEmpty())
return true;
if (!r.resolveSigRef(c.sig())) if (!r.resolveSigRef(c.sig()))
return r.fail("signature not found"); return r.fail("signature not found");
@ -2979,9 +3009,6 @@ ResolveCallIndirect(Resolver& r, WasmAstCallIndirect& c)
static bool static bool
ResolveGetLocal(Resolver& r, WasmAstGetLocal& gl) ResolveGetLocal(Resolver& r, WasmAstGetLocal& gl)
{ {
if (gl.local().name().isEmpty())
return true;
if (!r.resolveVarRef(gl.local())) if (!r.resolveVarRef(gl.local()))
return r.fail("local not found"); return r.fail("local not found");
@ -2994,9 +3021,6 @@ ResolveSetLocal(Resolver& r, WasmAstSetLocal& sl)
if (!ResolveExpr(r, sl.value())) if (!ResolveExpr(r, sl.value()))
return false; return false;
if (sl.local().name().isEmpty())
return true;
if (!r.resolveVarRef(sl.local())) if (!r.resolveVarRef(sl.local()))
return r.fail("local not found"); return r.fail("local not found");
@ -3105,12 +3129,9 @@ ResolveFunc(Resolver& r, WasmAstFunc& func)
{ {
r.beginFunc(); r.beginFunc();
size_t numVars = func.varNames().length(); size_t numVars = func.locals().length();
for (size_t i = 0; i < numVars; i++) { for (size_t i = 0; i < numVars; i++) {
WasmName name = func.varNames()[i]; if (!r.registerVarName(func.locals()[i], i))
if (name.isEmpty())
continue;
if (!r.registerVarName(name, i))
return r.fail("duplicate var"); return r.fail("duplicate var");
} }
@ -3132,8 +3153,6 @@ ResolveModule(LifoAlloc& lifo, WasmAstModule* module, UniqueChars* error)
size_t numSigs = module->sigs().length(); size_t numSigs = module->sigs().length();
for (size_t i = 0; i < numSigs; i++) { for (size_t i = 0; i < numSigs; i++) {
WasmAstSig* sig = module->sigs()[i]; WasmAstSig* sig = module->sigs()[i];
if (sig->name().isEmpty())
continue;
if (!r.registerSigName(sig->name(), i)) if (!r.registerSigName(sig->name(), i))
return r.fail("duplicate signature"); return r.fail("duplicate signature");
} }
@ -3141,20 +3160,14 @@ ResolveModule(LifoAlloc& lifo, WasmAstModule* module, UniqueChars* error)
size_t numFuncs = module->funcs().length(); size_t numFuncs = module->funcs().length();
for (size_t i = 0; i < numFuncs; i++) { for (size_t i = 0; i < numFuncs; i++) {
WasmAstFunc* func = module->funcs()[i]; WasmAstFunc* func = module->funcs()[i];
if (!func->sig().name().isEmpty()) { if (!r.resolveSigRef(func->sig()))
if (!r.resolveSigRef(func->sig())) return r.fail("signature not found");
return r.fail("signature not found");
}
if (func->name().isEmpty())
continue;
if (!r.registerFuncName(func->name(), i)) if (!r.registerFuncName(func->name(), i))
return r.fail("duplicate function"); return r.fail("duplicate function");
} }
if (module->maybeTable()) { if (module->maybeTable()) {
for (WasmRef& ref : module->maybeTable()->elems()) { for (WasmRef& ref : module->maybeTable()->elems()) {
if (ref.name().isEmpty())
continue;
if (!r.resolveFuncRef(ref)) if (!r.resolveFuncRef(ref))
return r.fail("function not found"); return r.fail("function not found");
} }
@ -3163,8 +3176,6 @@ ResolveModule(LifoAlloc& lifo, WasmAstModule* module, UniqueChars* error)
size_t numImports = module->imports().length(); size_t numImports = module->imports().length();
for (size_t i = 0; i < numImports; i++) { for (size_t i = 0; i < numImports; i++) {
WasmAstImport* imp = module->imports()[i]; WasmAstImport* imp = module->imports()[i];
if (imp->name().isEmpty())
continue;
if (!r.registerImportName(imp->name(), i)) if (!r.registerImportName(imp->name(), i))
return r.fail("duplicate import"); return r.fail("duplicate import");
} }
@ -3172,8 +3183,6 @@ ResolveModule(LifoAlloc& lifo, WasmAstModule* module, UniqueChars* error)
for (WasmAstExport* export_ : module->exports()) { for (WasmAstExport* export_ : module->exports()) {
if (export_->kind() != WasmAstExportKind::Func) if (export_->kind() != WasmAstExportKind::Func)
continue; continue;
if (export_->func().name().isEmpty())
continue;
if (!r.resolveFuncRef(export_->func())) if (!r.resolveFuncRef(export_->func()))
return r.fail("function not found"); return r.fail("function not found");
} }
@ -3630,10 +3639,10 @@ EncodeFunctionSection(Encoder& e, WasmAstFunc& func)
if (!e.startSection(&offset)) if (!e.startSection(&offset))
return false; return false;
if (!e.writeVarU32(func.varTypes().length())) if (!e.writeVarU32(func.vars().length()))
return false; return false;
for (ValType type : func.varTypes()) { for (ValType type : func.vars()) {
if (!e.writeValType(type)) if (!e.writeValType(type))
return false; return false;
} }

View File

@ -233,6 +233,8 @@ assertEq(wasmEvalText('(module (func (param $a i32) (local $b i32) (result i32)
assertErrorMessage(() => wasmEvalText('(module (func (param $a i32) (local $a i32)))'), SyntaxError, /duplicate var/); assertErrorMessage(() => wasmEvalText('(module (func (param $a i32) (local $a i32)))'), SyntaxError, /duplicate var/);
assertErrorMessage(() => wasmEvalText('(module (func (get_local $a)))'), SyntaxError, /local not found/); assertErrorMessage(() => wasmEvalText('(module (func (get_local $a)))'), SyntaxError, /local not found/);
wasmEvalText('(module (func (local i32) (local $a f32) (set_local 0 (i32.const 1)) (set_local $a (f32.const nan))))');
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// blocks // blocks
@ -264,6 +266,8 @@ wasmEvalText('(module (func (param i32) (nop)) (func (call 0 (i32.const 0))))');
assertEq(wasmEvalText('(module (func (result i32) (i32.const 42)) (func (result i32) (call 0)) (export "" 1))')(), 42); assertEq(wasmEvalText('(module (func (result i32) (i32.const 42)) (func (result i32) (call 0)) (export "" 1))')(), 42);
assertThrowsInstanceOf(() => wasmEvalText('(module (func (call 0)) (export "" 0))')(), InternalError); assertThrowsInstanceOf(() => wasmEvalText('(module (func (call 0)) (export "" 0))')(), InternalError);
assertThrowsInstanceOf(() => wasmEvalText('(module (func (call 1)) (func (call 0)) (export "" 0))')(), InternalError); assertThrowsInstanceOf(() => wasmEvalText('(module (func (call 1)) (func (call 0)) (export "" 0))')(), InternalError);
wasmEvalText('(module (func (param i32 f32)) (func (call 0 (i32.const 0) (f32.const nan))))');
assertErrorMessage(() => wasmEvalText('(module (func (param i32 f32)) (func (call 0 (i32.const 0) (i32.const 0))))'), TypeError, mismatchError("i32", "f32"));
assertThrowsInstanceOf(() => wasmEvalText('(module (import "a" "") (func (call_import 0 (i32.const 0))))', {a:()=>{}}), TypeError); assertThrowsInstanceOf(() => wasmEvalText('(module (import "a" "") (func (call_import 0 (i32.const 0))))', {a:()=>{}}), TypeError);
assertThrowsInstanceOf(() => wasmEvalText('(module (import "a" "" (param i32)) (func (call_import 0)))', {a:()=>{}}), TypeError); assertThrowsInstanceOf(() => wasmEvalText('(module (import "a" "" (param i32)) (func (call_import 0)))', {a:()=>{}}), TypeError);
@ -375,5 +379,5 @@ var {v2i, i2i, i2v} = wasmEvalText(`(module
wasmEvalText('(module (func $foo (nop)) (func (call $foo)))'); wasmEvalText('(module (func $foo (nop)) (func (call $foo)))');
wasmEvalText('(module (func (call $foo)) (func $foo (nop)))'); wasmEvalText('(module (func (call $foo)) (func $foo (nop)))');
wasmEvalText('(module (import $bar "a" "") (func (call_import $bar)) (func $foo (nop)))', {a:()=>{}}); wasmEvalText('(module (import $bar "a" "") (func (call_import $bar)) (func $foo (nop)))', {a:()=>{}});
assertErrorMessage(() => wasmEvalText('(module (import "a" "") (func (call_import $abc)))'), SyntaxError, /function not found/); assertErrorMessage(() => wasmEvalText('(module (import "a" "") (func (call_import $abc)))'), SyntaxError, /import not found/);

View File

@ -8,6 +8,7 @@ assertErrorMessage(() => wasmEvalText('(m'), SyntaxError, parsingError);
assertErrorMessage(() => wasmEvalText('(module'), SyntaxError, parsingError); assertErrorMessage(() => wasmEvalText('(module'), SyntaxError, parsingError);
assertErrorMessage(() => wasmEvalText('(moduler'), SyntaxError, parsingError); assertErrorMessage(() => wasmEvalText('(moduler'), SyntaxError, parsingError);
assertErrorMessage(() => wasmEvalText('(module (func) (export "a'), SyntaxError, parsingError); assertErrorMessage(() => wasmEvalText('(module (func) (export "a'), SyntaxError, parsingError);
assertErrorMessage(() => wasmEvalText('(module (func (local $a i32) (param $b f32)))'), SyntaxError, parsingError);
// Note: the s-expression text format is temporary, this file is mostly just to // Note: the s-expression text format is temporary, this file is mostly just to
// hold basic error smoke tests. // hold basic error smoke tests.