summaryrefslogtreecommitdiff
path: root/src/wast-parser.cc
diff options
context:
space:
mode:
authorBen Smith <binji@chromium.org>2020-06-16 20:47:37 -0700
committerGitHub <noreply@github.com>2020-06-16 20:47:37 -0700
commit6bff9f079a8e7b33bb616ea0731d592072dc53dd (patch)
tree0e16226b594f1132b652d55cfc0211e0ab3563db /src/wast-parser.cc
parent3239018f403d8fe0f20a914032c7fb1bf8c1c358 (diff)
downloadwabt-6bff9f079a8e7b33bb616ea0731d592072dc53dd.tar.gz
wabt-6bff9f079a8e7b33bb616ea0731d592072dc53dd.tar.bz2
wabt-6bff9f079a8e7b33bb616ea0731d592072dc53dd.zip
Update local bindings on function with type use (#1466)
When a function is specified like this: (func (type $t) ...) the type can have any sequence of params and results, but it is not known what that signature is until it is resolved. However, locals that are parsed will be given a binding index under the assumption that the signature is empty, e.g. (func (type $t) (local $v0 i32) (local $v1 i32) ... ) So `$v0` will have index 0, and `$v1` will have index 1. If it turns out later that type `$t` has any parameters, then these indexes need to be updated.
Diffstat (limited to 'src/wast-parser.cc')
-rw-r--r--src/wast-parser.cc21
1 files changed, 18 insertions, 3 deletions
diff --git a/src/wast-parser.cc b/src/wast-parser.cc
index 526ab868..90d92f87 100644
--- a/src/wast-parser.cc
+++ b/src/wast-parser.cc
@@ -243,7 +243,7 @@ bool IsEmptySignature(const FuncSignature& sig) {
return sig.result_types.empty() && sig.param_types.empty();
}
-void ResolveFuncTypeWithEmptySignature(const Module& module,
+bool ResolveFuncTypeWithEmptySignature(const Module& module,
FuncDeclaration* decl) {
// Resolve func type variables where the signature was not specified
// explicitly, e.g.: (func (type 1) ...)
@@ -251,9 +251,10 @@ void ResolveFuncTypeWithEmptySignature(const Module& module,
const FuncType* func_type = module.GetFuncType(decl->type_var);
if (func_type) {
decl->sig = func_type->sig;
+ return true;
}
}
-
+ return false;
}
void ResolveImplicitlyDefinedFunctionType(const Location& loc,
@@ -419,14 +420,28 @@ Result ResolveFuncTypes(Module* module, Errors* errors) {
continue;
}
+ bool has_func_type_and_empty_signature = false;
+
if (decl) {
- ResolveFuncTypeWithEmptySignature(*module, decl);
+ has_func_type_and_empty_signature =
+ ResolveFuncTypeWithEmptySignature(*module, decl);
ResolveImplicitlyDefinedFunctionType(field.loc, module, *decl);
result |=
CheckFuncTypeVarMatchesExplicit(field.loc, *module, *decl, errors);
}
if (func) {
+ if (has_func_type_and_empty_signature) {
+ // The call to ResolveFuncTypeWithEmptySignature may have updated the
+ // function signature so there are parameters. Since parameters and
+ // local variables share the same index space, we need to increment the
+ // local indexes bound to a given name by the number of parameters in
+ // the function.
+ for (auto& pair: func->bindings) {
+ pair.second.index += func->GetNumParams();
+ }
+ }
+
ResolveFuncTypesExprVisitorDelegate delegate(module, errors);
ExprVisitor visitor(&delegate);
result |= visitor.VisitFunc(func);