Bug 1253877 - Baldr: print missing text labels in resolving phase (r=mbx)
authorLuke Wagner <luke@mozilla.com>
Mon, 07 Mar 2016 09:07:39 -0600
changeset 324975 2c9739f8236f390fe107568f26d0e830865f1a3a
parent 324974 278c268d2e0a034620bc20c991a73d100ee08bc6
child 324976 c2b008a0c7ccb608b0248ed5d1ec711184cf22a0
push id6048
push userkmoir@mozilla.com
push dateMon, 06 Jun 2016 19:02:08 +0000
treeherdermozilla-beta@46d72a56c57d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmbx
bugs1253877
milestone47.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1253877 - Baldr: print missing text labels in resolving phase (r=mbx) MozReview-Commit-ID: EWXT88havql
js/src/asmjs/WasmText.cpp
js/src/jit-test/tests/wasm/basic.js
js/src/jit-test/tests/wasm/text.js
--- a/js/src/asmjs/WasmText.cpp
+++ b/js/src/asmjs/WasmText.cpp
@@ -3112,16 +3112,25 @@ class Resolver
     bool resolveRef(WasmNameMap& map, WasmRef& ref) {
         WasmNameMap::Ptr p = map.lookup(ref.name());
         if (p) {
             ref.setIndex(p->value());
             return true;
         }
         return false;
     }
+    bool failResolveLabel(const char* kind, WasmName name) {
+        Vector<char16_t, 0, SystemAllocPolicy> nameWithNull;
+        if (!nameWithNull.append(name.begin(), name.length()))
+            return false;
+        if (!nameWithNull.append(0))
+            return false;
+        error_->reset(JS_smprintf("%s label '%hs' not found", kind, nameWithNull.begin()));
+        return false;
+    }
 
   public:
     explicit Resolver(LifoAlloc& lifo, UniqueChars* error)
       : error_(error),
         varMap_(lifo),
         sigMap_(lifo),
         funcMap_(lifo),
         importMap_(lifo),
@@ -3148,38 +3157,50 @@ class Resolver
     }
     bool pushTarget(WasmName name) {
         return targetStack_.append(name);
     }
     void popTarget(WasmName name) {
         MOZ_ASSERT(targetStack_.back() == name);
         targetStack_.popBack();
     }
-    bool resolveSigRef(WasmRef& ref) {
-        return ref.name().empty() || resolveRef(sigMap_, ref);
+
+    bool resolveSignature(WasmRef& ref) {
+        if (!ref.name().empty() && !resolveRef(sigMap_, ref))
+            return failResolveLabel("signature", ref.name());
+        return true;
     }
-    bool resolveFuncRef(WasmRef& ref) {
-        return ref.name().empty() || resolveRef(funcMap_, ref);
+    bool resolveFunction(WasmRef& ref) {
+        if (!ref.name().empty() && !resolveRef(funcMap_, ref))
+            return failResolveLabel("function", ref.name());
+        return true;
     }
-    bool resolveImportRef(WasmRef& ref) {
-        return ref.name().empty() || resolveRef(importMap_, ref);
+    bool resolveImport(WasmRef& ref) {
+        if (!ref.name().empty() && !resolveRef(importMap_, ref))
+            return failResolveLabel("import", ref.name());
+        return true;
     }
-    bool resolveVarRef(WasmRef& ref) {
-        return ref.name().empty() || resolveRef(varMap_, ref);
+    bool resolveLocal(WasmRef& ref) {
+        if (!ref.name().empty() && !resolveRef(varMap_, ref))
+            return failResolveLabel("local", ref.name());
+        return true;
     }
-    bool resolveTarget(WasmRef& ref) {
+    bool resolveBranchTarget(WasmRef& ref) {
+        if (ref.name().empty())
+            return true;
         for (size_t i = 0, e = targetStack_.length(); i < e; i++) {
             if (targetStack_[e - i - 1] == ref.name()) {
                 ref.setIndex(i);
                 return true;
             }
         }
-        return false;
+        return failResolveLabel("branch target", ref.name());
     }
-    bool fail(const char*message) {
+
+    bool fail(const char* message) {
         error_->reset(JS_smprintf("%s", message));
         return false;
     }
 };
 
 } // end anonymous namespace
 
 static bool
@@ -3206,18 +3227,18 @@ ResolveBlock(Resolver& r, WasmAstBlock& 
         r.popTarget(b.continueName());
     r.popTarget(b.breakName());
     return true;
 }
 
 static bool
 ResolveBranch(Resolver& r, WasmAstBranch& br)
 {
-    if (!br.target().name().empty() && !r.resolveTarget(br.target()))
-        return r.fail("label not found");
+    if (!r.resolveBranchTarget(br.target()))
+        return false;
 
     if (br.expr() == Expr::BrIf) {
         if (!ResolveExpr(r, br.cond()))
             return false;
     }
 
     return true;
 }
@@ -3235,59 +3256,56 @@ ResolveArgs(Resolver& r, const WasmAstEx
 
 static bool
 ResolveCall(Resolver& r, WasmAstCall& c)
 {
     if (!ResolveArgs(r, c.args()))
         return false;
 
     if (c.expr() == Expr::Call) {
-        if (!r.resolveFuncRef(c.func()))
-            return r.fail("function not found");
+        if (!r.resolveFunction(c.func()))
+            return false;
     } else {
         MOZ_ASSERT(c.expr() == Expr::CallImport);
-        if (!r.resolveImportRef(c.func()))
-            return r.fail("import not found");
+        if (!r.resolveImport(c.func()))
+            return false;
     }
 
     return true;
 }
 
 static bool
 ResolveCallIndirect(Resolver& r, WasmAstCallIndirect& c)
 {
     if (!ResolveExpr(r, *c.index()))
         return false;
 
     if (!ResolveArgs(r, c.args()))
         return false;
 
-    if (!r.resolveSigRef(c.sig()))
-        return r.fail("signature not found");
+    if (!r.resolveSignature(c.sig()))
+        return false;
 
     return true;
 }
 
 static bool
 ResolveGetLocal(Resolver& r, WasmAstGetLocal& gl)
 {
-    if (!r.resolveVarRef(gl.local()))
-        return r.fail("local not found");
-
-    return true;
+    return r.resolveLocal(gl.local());
 }
 
 static bool
 ResolveSetLocal(Resolver& r, WasmAstSetLocal& sl)
 {
     if (!ResolveExpr(r, sl.value()))
         return false;
 
-    if (!r.resolveVarRef(sl.local()))
-        return r.fail("local not found");
+    if (!r.resolveLocal(sl.local()))
+        return false;
 
     return true;
 }
 
 static bool
 ResolveUnaryOperator(Resolver& r, WasmAstUnaryOperator& b)
 {
     return ResolveExpr(r, *b.op());
@@ -3344,22 +3362,22 @@ static bool
 ResolveReturn(Resolver& r, WasmAstReturn& ret)
 {
     return !ret.maybeExpr() || ResolveExpr(r, *ret.maybeExpr());
 }
 
 static bool
 ResolveBranchTable(Resolver& r, WasmAstBranchTable& bt)
 {
-    if (!bt.def().name().empty() && !r.resolveTarget(bt.def()))
-        return r.fail("switch default not found");
+    if (!r.resolveBranchTarget(bt.def()))
+        return false;
 
     for (WasmRef& elem : bt.table()) {
-        if (!elem.name().empty() && !r.resolveTarget(elem))
-            return r.fail("switch element not found");
+        if (!r.resolveBranchTarget(elem))
+            return false;
     }
 
     return ResolveExpr(r, bt.index());
 }
 
 static bool
 ResolveExpr(Resolver& r, WasmAstExpr& expr)
 {
@@ -3433,41 +3451,41 @@ ResolveModule(LifoAlloc& lifo, WasmAstMo
         WasmAstSig* sig = module->sigs()[i];
         if (!r.registerSigName(sig->name(), i))
             return r.fail("duplicate signature");
     }
 
     size_t numFuncs = module->funcs().length();
     for (size_t i = 0; i < numFuncs; i++) {
         WasmAstFunc* func = module->funcs()[i];
-        if (!r.resolveSigRef(func->sig()))
-            return r.fail("signature not found");
+        if (!r.resolveSignature(func->sig()))
+            return false;
         if (!r.registerFuncName(func->name(), i))
             return r.fail("duplicate function");
     }
 
     if (module->maybeTable()) {
         for (WasmRef& ref : module->maybeTable()->elems()) {
-            if (!r.resolveFuncRef(ref))
-                return r.fail("function not found");
+            if (!r.resolveFunction(ref))
+                return false;
         }
     }
 
     size_t numImports = module->imports().length();
     for (size_t i = 0; i < numImports; i++) {
         WasmAstImport* imp = module->imports()[i];
         if (!r.registerImportName(imp->name(), i))
             return r.fail("duplicate import");
     }
 
     for (WasmAstExport* export_ : module->exports()) {
         if (export_->kind() != WasmAstExportKind::Func)
             continue;
-        if (!r.resolveFuncRef(export_->func()))
-            return r.fail("function not found");
+        if (!r.resolveFunction(export_->func()))
+            return false;
     }
 
     for (WasmAstFunc* func : module->funcs()) {
         if (!ResolveFunc(r, *func))
             return false;
     }
 
     return true;
--- a/js/src/jit-test/tests/wasm/basic.js
+++ b/js/src/jit-test/tests/wasm/basic.js
@@ -427,10 +427,9 @@ var {v2i, i2i, i2v} = wasmEvalText(`(mod
     (export "v2i" 6)
     (export "i2i" 7)
     (export "i2v" 8)
 )`);
 
 wasmEvalText('(module (func $foo (nop)) (func (call $foo)))');
 wasmEvalText('(module (func (call $foo)) (func $foo (nop)))');
 wasmEvalText('(module (import $bar "a" "") (func (call_import $bar)) (func $foo (nop)))', {a:()=>{}});
-assertErrorMessage(() => wasmEvalText('(module (import "a" "") (func (call_import $abc)))'), SyntaxError, /import not found/);
 
--- a/js/src/jit-test/tests/wasm/text.js
+++ b/js/src/jit-test/tests/wasm/text.js
@@ -5,22 +5,22 @@ var parsingError = /parsing wasm text at
 assertErrorMessage(() => wasmEvalText(''), SyntaxError, parsingError);
 assertErrorMessage(() => wasmEvalText('('), SyntaxError, parsingError);
 assertErrorMessage(() => wasmEvalText('(m'), SyntaxError, parsingError);
 assertErrorMessage(() => wasmEvalText('(module'), SyntaxError, parsingError);
 assertErrorMessage(() => wasmEvalText('(moduler'), SyntaxError, parsingError);
 assertErrorMessage(() => wasmEvalText('(module (func) (export "a'), SyntaxError, parsingError);
 assertErrorMessage(() => wasmEvalText('(module (func (local $a i32) (param $b f32)))'), SyntaxError, parsingError);
 
-assertErrorMessage(() => wasmEvalText('(module (func $a) (func) (export "a" $a) (export "b" $b))'), SyntaxError, /function not found/);
+assertErrorMessage(() => wasmEvalText('(module (func $a) (func) (export "a" $a) (export "b" $b))'), SyntaxError, /function label '\$b' not found/);
 assertErrorMessage(() => wasmEvalText('(module (import $foo "a" "b") (import $foo "a" "b"))'), SyntaxError, /duplicate import/);
 assertErrorMessage(() => wasmEvalText('(module (func $foo) (func $foo))'), SyntaxError, /duplicate function/);
 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 label '\$a' not found/);
 assertErrorMessage(() => wasmEvalText('(module (type $a (func)) (type $a (func (param i32))))'), SyntaxError, /duplicate signature/);
-assertErrorMessage(() => wasmEvalText('(module (import "a" "") (func (call_import $abc)))'), SyntaxError, /import not found/);
-assertErrorMessage(() => wasmEvalText('(module (type $a (func)) (func (type $b) (i32.const 13)))'), SyntaxError, /signature not found/);
-assertErrorMessage(() => wasmEvalText('(module (type $a (func)) (func (call_indirect $c (get_local 0) (i32.const 0))))'), SyntaxError, /signature not found/);
-assertErrorMessage(() => wasmEvalText('(module (func (br $a)))'), SyntaxError, /label not found/);
-assertErrorMessage(() => wasmEvalText('(module (func (block $a) (br $a)))'), SyntaxError, /label not found/);
+assertErrorMessage(() => wasmEvalText('(module (import "a" "") (func (call_import $abc)))'), SyntaxError, /import label '\$abc' not found/);
+assertErrorMessage(() => wasmEvalText('(module (type $a (func)) (func (type $b) (i32.const 13)))'), SyntaxError, /signature label '\$b' not found/);
+assertErrorMessage(() => wasmEvalText('(module (type $a (func)) (func (call_indirect $c (get_local 0) (i32.const 0))))'), SyntaxError, /signature label '\$c' not found/);
+assertErrorMessage(() => wasmEvalText('(module (func (br $a)))'), SyntaxError, /branch target label '\$a' not found/);
+assertErrorMessage(() => wasmEvalText('(module (func (block $a) (br $a)))'), SyntaxError, /branch target label '\$a' not found/);
 
 // Note: the s-expression text format is temporary, this file is mostly just to
 // hold basic error smoke tests.