summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/apply-names.cc125
-rw-r--r--src/expr-visitor.cc163
-rw-r--r--src/expr-visitor.h116
-rw-r--r--src/generate-names.cc30
-rw-r--r--src/ir.cc146
-rw-r--r--src/ir.h53
-rw-r--r--src/resolve-names.cc133
7 files changed, 412 insertions, 354 deletions
diff --git a/src/apply-names.cc b/src/apply-names.cc
index 4521db0c..b61cd7f7 100644
--- a/src/apply-names.cc
+++ b/src/apply-names.cc
@@ -20,6 +20,7 @@
#include <cstdio>
#include <vector>
+#include "expr-visitor.h"
#include "ir.h"
#define CHECK_RESULT(expr) \
@@ -32,9 +33,26 @@ namespace wabt {
namespace {
-struct Context {
+struct Context : ExprVisitor::DelegateNop {
Context();
+ Result BeginBlockExpr(Expr*) override;
+ Result EndBlockExpr(Expr*) override;
+ Result OnBrExpr(Expr*) override;
+ Result OnBrIfExpr(Expr*) override;
+ Result OnBrTableExpr(Expr*) override;
+ Result OnCallExpr(Expr*) override;
+ Result OnCallIndirectExpr(Expr*) override;
+ Result OnGetGlobalExpr(Expr*) override;
+ Result OnGetLocalExpr(Expr*) override;
+ Result BeginIfExpr(Expr*) override;
+ Result EndIfExpr(Expr*) override;
+ Result BeginLoopExpr(Expr*) override;
+ Result EndLoopExpr(Expr*) override;
+ Result OnSetGlobalExpr(Expr*) override;
+ Result OnSetLocalExpr(Expr*) override;
+ Result OnTeeLocalExpr(Expr*) override;
+
Module* module = nullptr;
Func* current_func = nullptr;
ExprVisitor visitor;
@@ -44,8 +62,7 @@ struct Context {
std::vector<Label*> labels;
};
-Context::Context() {
- WABT_ZERO_MEMORY(visitor);
+Context::Context() : visitor(this) {
}
void push_label(Context* ctx, Label* label) {
@@ -153,111 +170,94 @@ Result use_name_for_param_and_local_var(Context* ctx, Func* func, Var* var) {
return Result::Ok;
}
-Result begin_block_expr(Expr* expr, void* user_data) {
- Context* ctx = static_cast<Context*>(user_data);
- push_label(ctx, &expr->block->label);
+Result Context::BeginBlockExpr(Expr* expr) {
+ push_label(this, &expr->block->label);
return Result::Ok;
}
-Result end_block_expr(Expr* expr, void* user_data) {
- Context* ctx = static_cast<Context*>(user_data);
- pop_label(ctx);
+Result Context::EndBlockExpr(Expr* expr) {
+ pop_label(this);
return Result::Ok;
}
-Result begin_loop_expr(Expr* expr, void* user_data) {
- Context* ctx = static_cast<Context*>(user_data);
- push_label(ctx, &expr->loop->label);
+Result Context::BeginLoopExpr(Expr* expr) {
+ push_label(this, &expr->loop->label);
return Result::Ok;
}
-Result end_loop_expr(Expr* expr, void* user_data) {
- Context* ctx = static_cast<Context*>(user_data);
- pop_label(ctx);
+Result Context::EndLoopExpr(Expr* expr) {
+ pop_label(this);
return Result::Ok;
}
-Result on_br_expr(Expr* expr, void* user_data) {
- Context* ctx = static_cast<Context*>(user_data);
- Label* label = find_label_by_var(ctx, &expr->br.var);
+Result Context::OnBrExpr(Expr* expr) {
+ Label* label = find_label_by_var(this, &expr->br.var);
use_name_for_var(label, &expr->br.var);
return Result::Ok;
}
-Result on_br_if_expr(Expr* expr, void* user_data) {
- Context* ctx = static_cast<Context*>(user_data);
- Label* label = find_label_by_var(ctx, &expr->br_if.var);
+Result Context::OnBrIfExpr(Expr* expr) {
+ Label* label = find_label_by_var(this, &expr->br_if.var);
use_name_for_var(label, &expr->br_if.var);
return Result::Ok;
}
-Result on_br_table_expr(Expr* expr, void* user_data) {
- Context* ctx = static_cast<Context*>(user_data);
+Result Context::OnBrTableExpr(Expr* expr) {
VarVector& targets = *expr->br_table.targets;
for (Var& target : targets) {
- Label* label = find_label_by_var(ctx, &target);
+ Label* label = find_label_by_var(this, &target);
use_name_for_var(label, &target);
}
- Label* label = find_label_by_var(ctx, &expr->br_table.default_target);
+ Label* label = find_label_by_var(this, &expr->br_table.default_target);
use_name_for_var(label, &expr->br_table.default_target);
return Result::Ok;
}
-Result on_call_expr(Expr* expr, void* user_data) {
- Context* ctx = static_cast<Context*>(user_data);
- CHECK_RESULT(use_name_for_func_var(ctx->module, &expr->call.var));
+Result Context::OnCallExpr(Expr* expr) {
+ CHECK_RESULT(use_name_for_func_var(module, &expr->call.var));
return Result::Ok;
}
-Result on_call_indirect_expr(Expr* expr, void* user_data) {
- Context* ctx = static_cast<Context*>(user_data);
- CHECK_RESULT(
- use_name_for_func_type_var(ctx->module, &expr->call_indirect.var));
+Result Context::OnCallIndirectExpr(Expr* expr) {
+ CHECK_RESULT(use_name_for_func_type_var(module, &expr->call_indirect.var));
return Result::Ok;
}
-Result on_get_global_expr(Expr* expr, void* user_data) {
- Context* ctx = static_cast<Context*>(user_data);
- CHECK_RESULT(use_name_for_global_var(ctx->module, &expr->get_global.var));
+Result Context::OnGetGlobalExpr(Expr* expr) {
+ CHECK_RESULT(use_name_for_global_var(module, &expr->get_global.var));
return Result::Ok;
}
-Result on_get_local_expr(Expr* expr, void* user_data) {
- Context* ctx = static_cast<Context*>(user_data);
- CHECK_RESULT(use_name_for_param_and_local_var(ctx, ctx->current_func,
+Result Context::OnGetLocalExpr(Expr* expr) {
+ CHECK_RESULT(use_name_for_param_and_local_var(this, current_func,
&expr->get_local.var));
return Result::Ok;
}
-Result begin_if_expr(Expr* expr, void* user_data) {
- Context* ctx = static_cast<Context*>(user_data);
- push_label(ctx, &expr->if_.true_->label);
+Result Context::BeginIfExpr(Expr* expr) {
+ push_label(this, &expr->if_.true_->label);
return Result::Ok;
}
-Result end_if_expr(Expr* expr, void* user_data) {
- Context* ctx = static_cast<Context*>(user_data);
- pop_label(ctx);
+Result Context::EndIfExpr(Expr* expr) {
+ pop_label(this);
return Result::Ok;
}
-Result on_set_global_expr(Expr* expr, void* user_data) {
- Context* ctx = static_cast<Context*>(user_data);
- CHECK_RESULT(use_name_for_global_var(ctx->module, &expr->set_global.var));
+Result Context::OnSetGlobalExpr(Expr* expr) {
+ CHECK_RESULT(use_name_for_global_var(module, &expr->set_global.var));
return Result::Ok;
}
-Result on_set_local_expr(Expr* expr, void* user_data) {
- Context* ctx = static_cast<Context*>(user_data);
- CHECK_RESULT(use_name_for_param_and_local_var(ctx, ctx->current_func,
+Result Context::OnSetLocalExpr(Expr* expr) {
+ CHECK_RESULT(use_name_for_param_and_local_var(this, current_func,
&expr->set_local.var));
return Result::Ok;
}
-Result on_tee_local_expr(Expr* expr, void* user_data) {
- Context* ctx = static_cast<Context*>(user_data);
- CHECK_RESULT(use_name_for_param_and_local_var(ctx, ctx->current_func,
+Result Context::OnTeeLocalExpr(Expr* expr) {
+ CHECK_RESULT(use_name_for_param_and_local_var(this, current_func,
&expr->tee_local.var));
return Result::Ok;
}
@@ -275,7 +275,7 @@ Result visit_func(Context* ctx, Index func_index, Func* func) {
make_type_binding_reverse_mapping(func->local_types, func->local_bindings,
&ctx->local_index_to_name);
- CHECK_RESULT(visit_func(func, &ctx->visitor));
+ CHECK_RESULT(ctx->visitor.VisitFunc(func));
ctx->current_func = nullptr;
return Result::Ok;
}
@@ -321,23 +321,6 @@ Result visit_module(Context* ctx, Module* module) {
Result apply_names(Module* module) {
Context ctx;
ctx.module = module;
- ctx.visitor.user_data = &ctx;
- ctx.visitor.begin_block_expr = begin_block_expr;
- ctx.visitor.end_block_expr = end_block_expr;
- ctx.visitor.begin_loop_expr = begin_loop_expr;
- ctx.visitor.end_loop_expr = end_loop_expr;
- ctx.visitor.on_br_expr = on_br_expr;
- ctx.visitor.on_br_if_expr = on_br_if_expr;
- ctx.visitor.on_br_table_expr = on_br_table_expr;
- ctx.visitor.on_call_expr = on_call_expr;
- ctx.visitor.on_call_indirect_expr = on_call_indirect_expr;
- ctx.visitor.on_get_global_expr = on_get_global_expr;
- ctx.visitor.on_get_local_expr = on_get_local_expr;
- ctx.visitor.begin_if_expr = begin_if_expr;
- ctx.visitor.end_if_expr = end_if_expr;
- ctx.visitor.on_set_global_expr = on_set_global_expr;
- ctx.visitor.on_set_local_expr = on_set_local_expr;
- ctx.visitor.on_tee_local_expr = on_tee_local_expr;
Result result = visit_module(&ctx, module);
return result;
}
diff --git a/src/expr-visitor.cc b/src/expr-visitor.cc
new file mode 100644
index 00000000..0300cb5e
--- /dev/null
+++ b/src/expr-visitor.cc
@@ -0,0 +1,163 @@
+/*
+ * Copyright 2017 WebAssembly Community Group participants
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "expr-visitor.h"
+
+#include "ir.h"
+
+#define CHECK_RESULT(expr) \
+ do { \
+ if (WABT_FAILED((expr))) \
+ return Result::Error; \
+ } while (0)
+
+namespace wabt {
+
+ExprVisitor::ExprVisitor(Delegate* delegate) : delegate_(delegate) {}
+
+Result ExprVisitor::VisitExpr(Expr* expr) {
+ switch (expr->type) {
+ case ExprType::Binary:
+ CHECK_RESULT(delegate_->OnBinaryExpr(expr));
+ break;
+
+ case ExprType::Block:
+ CHECK_RESULT(delegate_->BeginBlockExpr(expr));
+ CHECK_RESULT(VisitExprList(expr->block->first));
+ CHECK_RESULT(delegate_->EndBlockExpr(expr));
+ break;
+
+ case ExprType::Br:
+ CHECK_RESULT(delegate_->OnBrExpr(expr));
+ break;
+
+ case ExprType::BrIf:
+ CHECK_RESULT(delegate_->OnBrIfExpr(expr));
+ break;
+
+ case ExprType::BrTable:
+ CHECK_RESULT(delegate_->OnBrTableExpr(expr));
+ break;
+
+ case ExprType::Call:
+ CHECK_RESULT(delegate_->OnCallExpr(expr));
+ break;
+
+ case ExprType::CallIndirect:
+ CHECK_RESULT(delegate_->OnCallIndirectExpr(expr));
+ break;
+
+ case ExprType::Compare:
+ CHECK_RESULT(delegate_->OnCompareExpr(expr));
+ break;
+
+ case ExprType::Const:
+ CHECK_RESULT(delegate_->OnConstExpr(expr));
+ break;
+
+ case ExprType::Convert:
+ CHECK_RESULT(delegate_->OnConvertExpr(expr));
+ break;
+
+ case ExprType::CurrentMemory:
+ CHECK_RESULT(delegate_->OnCurrentMemoryExpr(expr));
+ break;
+
+ case ExprType::Drop:
+ CHECK_RESULT(delegate_->OnDropExpr(expr));
+ break;
+
+ case ExprType::GetGlobal:
+ CHECK_RESULT(delegate_->OnGetGlobalExpr(expr));
+ break;
+
+ case ExprType::GetLocal:
+ CHECK_RESULT(delegate_->OnGetLocalExpr(expr));
+ break;
+
+ case ExprType::GrowMemory:
+ CHECK_RESULT(delegate_->OnGrowMemoryExpr(expr));
+ break;
+
+ case ExprType::If:
+ CHECK_RESULT(delegate_->BeginIfExpr(expr));
+ CHECK_RESULT(VisitExprList(expr->if_.true_->first));
+ CHECK_RESULT(delegate_->AfterIfTrueExpr(expr));
+ CHECK_RESULT(VisitExprList(expr->if_.false_));
+ CHECK_RESULT(delegate_->EndIfExpr(expr));
+ break;
+
+ case ExprType::Load:
+ CHECK_RESULT(delegate_->OnLoadExpr(expr));
+ break;
+
+ case ExprType::Loop:
+ CHECK_RESULT(delegate_->BeginLoopExpr(expr));
+ CHECK_RESULT(VisitExprList(expr->loop->first));
+ CHECK_RESULT(delegate_->EndLoopExpr(expr));
+ break;
+
+ case ExprType::Nop:
+ CHECK_RESULT(delegate_->OnNopExpr(expr));
+ break;
+
+ case ExprType::Return:
+ CHECK_RESULT(delegate_->OnReturnExpr(expr));
+ break;
+
+ case ExprType::Select:
+ CHECK_RESULT(delegate_->OnSelectExpr(expr));
+ break;
+
+ case ExprType::SetGlobal:
+ CHECK_RESULT(delegate_->OnSetGlobalExpr(expr));
+ break;
+
+ case ExprType::SetLocal:
+ CHECK_RESULT(delegate_->OnSetLocalExpr(expr));
+ break;
+
+ case ExprType::Store:
+ CHECK_RESULT(delegate_->OnStoreExpr(expr));
+ break;
+
+ case ExprType::TeeLocal:
+ CHECK_RESULT(delegate_->OnTeeLocalExpr(expr));
+ break;
+
+ case ExprType::Unary:
+ CHECK_RESULT(delegate_->OnUnaryExpr(expr));
+ break;
+
+ case ExprType::Unreachable:
+ CHECK_RESULT(delegate_->OnUnreachableExpr(expr));
+ break;
+ }
+
+ return Result::Ok;
+}
+
+Result ExprVisitor::VisitExprList(Expr* first) {
+ for (Expr* expr = first; expr; expr = expr->next)
+ CHECK_RESULT(VisitExpr(expr));
+ return Result::Ok;
+}
+
+Result ExprVisitor::VisitFunc(Func* func) {
+ return VisitExprList(func->first_expr);
+}
+
+} // namespace wabt
diff --git a/src/expr-visitor.h b/src/expr-visitor.h
new file mode 100644
index 00000000..11103d5e
--- /dev/null
+++ b/src/expr-visitor.h
@@ -0,0 +1,116 @@
+/*
+ * Copyright 2017 WebAssembly Community Group participants
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef WABT_EXPR_VISITOR_H_
+#define WABT_EXPR_VISITOR_H_
+
+#include "common.h"
+
+namespace wabt {
+
+struct Expr;
+struct Func;
+
+class ExprVisitor {
+ public:
+ class Delegate;
+ class DelegateNop;
+
+ explicit ExprVisitor(Delegate* delegate);
+
+ Result VisitExpr(Expr*);
+ Result VisitExprList(Expr*);
+ Result VisitFunc(Func*);
+
+ private:
+ Delegate* delegate_;
+};
+
+class ExprVisitor::Delegate {
+ public:
+ virtual ~Delegate() {}
+
+ virtual Result OnBinaryExpr(Expr*) = 0;
+ virtual Result BeginBlockExpr(Expr*) = 0;
+ virtual Result EndBlockExpr(Expr*) = 0;
+ virtual Result OnBrExpr(Expr*) = 0;
+ virtual Result OnBrIfExpr(Expr*) = 0;
+ virtual Result OnBrTableExpr(Expr*) = 0;
+ virtual Result OnCallExpr(Expr*) = 0;
+ virtual Result OnCallIndirectExpr(Expr*) = 0;
+ virtual Result OnCompareExpr(Expr*) = 0;
+ virtual Result OnConstExpr(Expr*) = 0;
+ virtual Result OnConvertExpr(Expr*) = 0;
+ virtual Result OnCurrentMemoryExpr(Expr*) = 0;
+ virtual Result OnDropExpr(Expr*) = 0;
+ virtual Result OnGetGlobalExpr(Expr*) = 0;
+ virtual Result OnGetLocalExpr(Expr*) = 0;
+ virtual Result OnGrowMemoryExpr(Expr*) = 0;
+ virtual Result BeginIfExpr(Expr*) = 0;
+ virtual Result AfterIfTrueExpr(Expr*) = 0;
+ virtual Result EndIfExpr(Expr*) = 0;
+ virtual Result OnLoadExpr(Expr*) = 0;
+ virtual Result BeginLoopExpr(Expr*) = 0;
+ virtual Result EndLoopExpr(Expr*) = 0;
+ virtual Result OnNopExpr(Expr*) = 0;
+ virtual Result OnReturnExpr(Expr*) = 0;
+ virtual Result OnSelectExpr(Expr*) = 0;
+ virtual Result OnSetGlobalExpr(Expr*) = 0;
+ virtual Result OnSetLocalExpr(Expr*) = 0;
+ virtual Result OnStoreExpr(Expr*) = 0;
+ virtual Result OnTeeLocalExpr(Expr*) = 0;
+ virtual Result OnUnaryExpr(Expr*) = 0;
+ virtual Result OnUnreachableExpr(Expr*) = 0;
+};
+
+class ExprVisitor::DelegateNop : public ExprVisitor::Delegate {
+ public:
+ Result OnBinaryExpr(Expr*) override { return Result::Ok; }
+ Result BeginBlockExpr(Expr*) override { return Result::Ok; }
+ Result EndBlockExpr(Expr*) override { return Result::Ok; }
+ Result OnBrExpr(Expr*) override { return Result::Ok; }
+ Result OnBrIfExpr(Expr*) override { return Result::Ok; }
+ Result OnBrTableExpr(Expr*) override { return Result::Ok; }
+ Result OnCallExpr(Expr*) override { return Result::Ok; }
+ Result OnCallIndirectExpr(Expr*) override { return Result::Ok; }
+ Result OnCompareExpr(Expr*) override { return Result::Ok; }
+ Result OnConstExpr(Expr*) override { return Result::Ok; }
+ Result OnConvertExpr(Expr*) override { return Result::Ok; }
+ Result OnCurrentMemoryExpr(Expr*) override { return Result::Ok; }
+ Result OnDropExpr(Expr*) override { return Result::Ok; }
+ Result OnGetGlobalExpr(Expr*) override { return Result::Ok; }
+ Result OnGetLocalExpr(Expr*) override { return Result::Ok; }
+ Result OnGrowMemoryExpr(Expr*) override { return Result::Ok; }
+ Result BeginIfExpr(Expr*) override { return Result::Ok; }
+ Result AfterIfTrueExpr(Expr*) override { return Result::Ok; }
+ Result EndIfExpr(Expr*) override { return Result::Ok; }
+ Result OnLoadExpr(Expr*) override { return Result::Ok; }
+ Result BeginLoopExpr(Expr*) override { return Result::Ok; }
+ Result EndLoopExpr(Expr*) override { return Result::Ok; }
+ Result OnNopExpr(Expr*) override { return Result::Ok; }
+ Result OnReturnExpr(Expr*) override { return Result::Ok; }
+ Result OnSelectExpr(Expr*) override { return Result::Ok; }
+ Result OnSetGlobalExpr(Expr*) override { return Result::Ok; }
+ Result OnSetLocalExpr(Expr*) override { return Result::Ok; }
+ Result OnStoreExpr(Expr*) override { return Result::Ok; }
+ Result OnTeeLocalExpr(Expr*) override { return Result::Ok; }
+ Result OnUnaryExpr(Expr*) override { return Result::Ok; }
+ Result OnUnreachableExpr(Expr*) override { return Result::Ok; }
+};
+
+} // namespace wabt
+
+#endif // WABT_EXPR_VISITOR_H_
diff --git a/src/generate-names.cc b/src/generate-names.cc
index 7358893e..667e3ecf 100644
--- a/src/generate-names.cc
+++ b/src/generate-names.cc
@@ -21,6 +21,7 @@
#include <string>
#include <vector>
+#include "expr-visitor.h"
#include "ir.h"
#define CHECK_RESULT(expr) \
@@ -33,8 +34,12 @@ namespace wabt {
namespace {
-struct Context {
- Context() : module(nullptr), label_count(0) { WABT_ZERO_MEMORY(visitor); }
+struct Context : public ExprVisitor::DelegateNop {
+ Context() : module(nullptr), visitor(this), label_count(0) {}
+
+ Result BeginBlockExpr(Expr* expr) override;
+ Result BeginLoopExpr(Expr* expr) override;
+ Result BeginIfExpr(Expr* expr) override;
Module* module;
ExprVisitor visitor;
@@ -98,21 +103,18 @@ static void generate_and_bind_local_names(Context* ctx,
}
}
-static Result begin_block_expr(Expr* expr, void* user_data) {
- Context* ctx = static_cast<Context*>(user_data);
- maybe_generate_name("$B", ctx->label_count++, &expr->block->label);
+Result Context::BeginBlockExpr(Expr* expr) {
+ maybe_generate_name("$B", label_count++, &expr->block->label);
return Result::Ok;
}
-static Result begin_loop_expr(Expr* expr, void* user_data) {
- Context* ctx = static_cast<Context*>(user_data);
- maybe_generate_name("$L", ctx->label_count++, &expr->loop->label);
+Result Context::BeginLoopExpr(Expr* expr) {
+ maybe_generate_name("$L", label_count++, &expr->loop->label);
return Result::Ok;
}
-static Result begin_if_expr(Expr* expr, void* user_data) {
- Context* ctx = static_cast<Context*>(user_data);
- maybe_generate_name("$I", ctx->label_count++, &expr->if_.true_->label);
+Result Context::BeginIfExpr(Expr* expr) {
+ maybe_generate_name("$I", label_count++, &expr->if_.true_->label);
return Result::Ok;
}
@@ -129,7 +131,7 @@ static Result visit_func(Context* ctx, Index func_index, Func* func) {
generate_and_bind_local_names(ctx, &func->local_bindings, "$l");
ctx->label_count = 0;
- CHECK_RESULT(visit_func(func, &ctx->visitor));
+ CHECK_RESULT(ctx->visitor.VisitFunc(func));
return Result::Ok;
}
@@ -175,10 +177,6 @@ static Result visit_module(Context* ctx, Module* module) {
Result generate_names(Module* module) {
Context ctx;
- ctx.visitor.user_data = &ctx;
- ctx.visitor.begin_block_expr = begin_block_expr;
- ctx.visitor.begin_loop_expr = begin_loop_expr;
- ctx.visitor.begin_if_expr = begin_if_expr;
ctx.module = module;
Result result = visit_module(&ctx, module);
return result;
diff --git a/src/ir.cc b/src/ir.cc
index 59c587ed..a04b477e 100644
--- a/src/ir.cc
+++ b/src/ir.cc
@@ -744,150 +744,4 @@ Command::~Command() {
Script::Script() {}
-#define CHECK_RESULT(expr) \
- do { \
- if (WABT_FAILED((expr))) \
- return Result::Error; \
- } while (0)
-
-#define CALLBACK(member) \
- CHECK_RESULT((visitor)->member \
- ? (visitor)->member(expr, (visitor)->user_data) \
- : Result::Ok)
-
-static Result visit_expr(Expr* expr, ExprVisitor* visitor);
-
-Result visit_expr_list(Expr* first, ExprVisitor* visitor) {
- for (Expr* expr = first; expr; expr = expr->next)
- CHECK_RESULT(visit_expr(expr, visitor));
- return Result::Ok;
-}
-
-static Result visit_expr(Expr* expr, ExprVisitor* visitor) {
- switch (expr->type) {
- case ExprType::Binary:
- CALLBACK(on_binary_expr);
- break;
-
- case ExprType::Block:
- CALLBACK(begin_block_expr);
- CHECK_RESULT(visit_expr_list(expr->block->first, visitor));
- CALLBACK(end_block_expr);
- break;
-
- case ExprType::Br:
- CALLBACK(on_br_expr);
- break;
-
- case ExprType::BrIf:
- CALLBACK(on_br_if_expr);
- break;
-
- case ExprType::BrTable:
- CALLBACK(on_br_table_expr);
- break;
-
- case ExprType::Call:
- CALLBACK(on_call_expr);
- break;
-
- case ExprType::CallIndirect:
- CALLBACK(on_call_indirect_expr);
- break;
-
- case ExprType::Compare:
- CALLBACK(on_compare_expr);
- break;
-
- case ExprType::Const:
- CALLBACK(on_const_expr);
- break;
-
- case ExprType::Convert:
- CALLBACK(on_convert_expr);
- break;
-
- case ExprType::CurrentMemory:
- CALLBACK(on_current_memory_expr);
- break;
-
- case ExprType::Drop:
- CALLBACK(on_drop_expr);
- break;
-
- case ExprType::GetGlobal:
- CALLBACK(on_get_global_expr);
- break;
-
- case ExprType::GetLocal:
- CALLBACK(on_get_local_expr);
- break;
-
- case ExprType::GrowMemory:
- CALLBACK(on_grow_memory_expr);
- break;
-
- case ExprType::If:
- CALLBACK(begin_if_expr);
- CHECK_RESULT(visit_expr_list(expr->if_.true_->first, visitor));
- CALLBACK(after_if_true_expr);
- CHECK_RESULT(visit_expr_list(expr->if_.false_, visitor));
- CALLBACK(end_if_expr);
- break;
-
- case ExprType::Load:
- CALLBACK(on_load_expr);
- break;
-
- case ExprType::Loop:
- CALLBACK(begin_loop_expr);
- CHECK_RESULT(visit_expr_list(expr->loop->first, visitor));
- CALLBACK(end_loop_expr);
- break;
-
- case ExprType::Nop:
- CALLBACK(on_nop_expr);
- break;
-
- case ExprType::Return:
- CALLBACK(on_return_expr);
- break;
-
- case ExprType::Select:
- CALLBACK(on_select_expr);
- break;
-
- case ExprType::SetGlobal:
- CALLBACK(on_set_global_expr);
- break;
-
- case ExprType::SetLocal:
- CALLBACK(on_set_local_expr);
- break;
-
- case ExprType::Store:
- CALLBACK(on_store_expr);
- break;
-
- case ExprType::TeeLocal:
- CALLBACK(on_tee_local_expr);
- break;
-
- case ExprType::Unary:
- CALLBACK(on_unary_expr);
- break;
-
- case ExprType::Unreachable:
- CALLBACK(on_unreachable_expr);
- break;
- }
-
- return Result::Ok;
-}
-
-/* TODO(binji): make the visitor non-recursive */
-Result visit_func(Func* func, ExprVisitor* visitor) {
- return visit_expr_list(func->first_expr, visitor);
-}
-
} // namespace wabt
diff --git a/src/ir.h b/src/ir.h
index 448538a6..1d98bc20 100644
--- a/src/ir.h
+++ b/src/ir.h
@@ -109,15 +109,17 @@ enum class ExprType {
typedef TypeVector BlockSignature;
+struct Expr;
+
struct Block {
WABT_DISALLOW_COPY_AND_ASSIGN(Block);
Block();
- explicit Block(struct Expr* first);
+ explicit Block(Expr* first);
~Block();
Label label;
BlockSignature sig;
- struct Expr* first;
+ Expr* first;
};
struct Expr {
@@ -141,9 +143,9 @@ struct Expr {
static Expr* CreateGetGlobal(Var);
static Expr* CreateGetLocal(Var);
static Expr* CreateGrowMemory();
- static Expr* CreateIf(struct Block* true_, struct Expr* false_ = nullptr);
+ static Expr* CreateIf(Block* true_, Expr* false_ = nullptr);
static Expr* CreateLoad(Opcode, Address align, uint64_t offset);
- static Expr* CreateLoop(struct Block*);
+ static Expr* CreateLoop(Block*);
static Expr* CreateNop();
static Expr* CreateReturn();
static Expr* CreateSelect();
@@ -166,7 +168,7 @@ struct Expr {
struct Const const_;
struct { Var var; } get_global, set_global;
struct { Var var; } get_local, set_local, tee_local;
- struct { struct Block* true_; struct Expr* false_; } if_;
+ struct { Block* true_; Expr* false_; } if_;
struct { Opcode opcode; Address align; uint64_t offset; } load, store;
};
};
@@ -307,7 +309,7 @@ struct ModuleField {
Location loc;
ModuleFieldType type;
- struct ModuleField* next;
+ ModuleField* next;
union {
Func* func;
Global* global;
@@ -466,41 +468,6 @@ struct Script {
BindingHash module_bindings;
};
-struct ExprVisitor {
- void* user_data;
- Result (*on_binary_expr)(Expr*, void* user_data);
- Result (*begin_block_expr)(Expr*, void* user_data);
- Result (*end_block_expr)(Expr*, void* user_data);
- Result (*on_br_expr)(Expr*, void* user_data);
- Result (*on_br_if_expr)(Expr*, void* user_data);
- Result (*on_br_table_expr)(Expr*, void* user_data);
- Result (*on_call_expr)(Expr*, void* user_data);
- Result (*on_call_indirect_expr)(Expr*, void* user_data);
- Result (*on_compare_expr)(Expr*, void* user_data);
- Result (*on_const_expr)(Expr*, void* user_data);
- Result (*on_convert_expr)(Expr*, void* user_data);
- Result (*on_current_memory_expr)(Expr*, void* user_data);
- Result (*on_drop_expr)(Expr*, void* user_data);
- Result (*on_get_global_expr)(Expr*, void* user_data);
- Result (*on_get_local_expr)(Expr*, void* user_data);
- Result (*on_grow_memory_expr)(Expr*, void* user_data);
- Result (*begin_if_expr)(Expr*, void* user_data);
- Result (*after_if_true_expr)(Expr*, void* user_data);
- Result (*end_if_expr)(Expr*, void* user_data);
- Result (*on_load_expr)(Expr*, void* user_data);
- Result (*begin_loop_expr)(Expr*, void* user_data);
- Result (*end_loop_expr)(Expr*, void* user_data);
- Result (*on_nop_expr)(Expr*, void* user_data);
- Result (*on_return_expr)(Expr*, void* user_data);
- Result (*on_select_expr)(Expr*, void* user_data);
- Result (*on_set_global_expr)(Expr*, void* user_data);
- Result (*on_set_local_expr)(Expr*, void* user_data);
- Result (*on_store_expr)(Expr*, void* user_data);
- Result (*on_tee_local_expr)(Expr*, void* user_data);
- Result (*on_unary_expr)(Expr*, void* user_data);
- Result (*on_unreachable_expr)(Expr*, void* user_data);
-};
-
ModuleField* append_module_field(Module*);
/* ownership of the function signature is passed to the module */
FuncType* append_implicit_func_type(Location*, Module*, FuncSignature*);
@@ -510,10 +477,6 @@ FuncType* append_implicit_func_type(Location*, Module*, FuncSignature*);
void destroy_expr_list(Expr*);
void destroy_var(Var*);
-/* traversal functions */
-Result visit_func(Func* func, ExprVisitor*);
-Result visit_expr_list(Expr* expr, ExprVisitor*);
-
/* convenience functions for looking through the IR */
Index get_index_from_var(const BindingHash* bindings, const Var* var);
Index get_func_index_by_var(const Module* module, const Var* var);
diff --git a/src/resolve-names.cc b/src/resolve-names.cc
index fb823c5c..70eff09c 100644
--- a/src/resolve-names.cc
+++ b/src/resolve-names.cc
@@ -19,6 +19,7 @@
#include <cassert>
#include <cstdio>
+#include "expr-visitor.h"
#include "ir.h"
#include "wast-parser-lexer-shared.h"
@@ -28,9 +29,26 @@ namespace {
typedef Label* LabelPtr;
-struct Context {
+struct Context : ExprVisitor::DelegateNop {
Context();
+ Result BeginBlockExpr(Expr*) override;
+ Result EndBlockExpr(Expr*) override;
+ Result OnBrExpr(Expr*) override;
+ Result OnBrIfExpr(Expr*) override;
+ Result OnBrTableExpr(Expr*) override;
+ Result OnCallExpr(Expr*) override;
+ Result OnCallIndirectExpr(Expr*) override;
+ Result OnGetGlobalExpr(Expr*) override;
+ Result OnGetLocalExpr(Expr*) override;
+ Result BeginIfExpr(Expr*) override;
+ Result EndIfExpr(Expr*) override;
+ Result BeginLoopExpr(Expr*) override;
+ Result EndLoopExpr(Expr*) override;
+ Result OnSetGlobalExpr(Expr*) override;
+ Result OnSetLocalExpr(Expr*) override;
+ Result OnTeeLocalExpr(Expr*) override;
+
SourceErrorHandler* error_handler = nullptr;
WastLexer* lexer = nullptr;
Script* script = nullptr;
@@ -41,9 +59,7 @@ struct Context {
Result result = Result::Ok;
};
-Context::Context() {
- WABT_ZERO_MEMORY(visitor);
-}
+Context::Context() : visitor(this) {}
} // namespace
@@ -167,101 +183,85 @@ static void resolve_local_var(Context* ctx, Var* var) {
}
}
-static Result begin_block_expr(Expr* expr, void* user_data) {
- Context* ctx = static_cast<Context*>(user_data);
- push_label(ctx, &expr->block->label);
+Result Context::BeginBlockExpr(Expr* expr) {
+ push_label(this, &expr->block->label);
return Result::Ok;
}
-static Result end_block_expr(Expr* expr, void* user_data) {
- Context* ctx = static_cast<Context*>(user_data);
- pop_label(ctx);
+Result Context::EndBlockExpr(Expr* expr) {
+ pop_label(this);
return Result::Ok;
}
-static Result begin_loop_expr(Expr* expr, void* user_data) {
- Context* ctx = static_cast<Context*>(user_data);
- push_label(ctx, &expr->loop->label);
+Result Context::BeginLoopExpr(Expr* expr) {
+ push_label(this, &expr->loop->label);
return Result::Ok;
}
-static Result end_loop_expr(Expr* expr, void* user_data) {
- Context* ctx = static_cast<Context*>(user_data);
- pop_label(ctx);
+Result Context::EndLoopExpr(Expr* expr) {
+ pop_label(this);
return Result::Ok;
}
-static Result on_br_expr(Expr* expr, void* user_data) {
- Context* ctx = static_cast<Context*>(user_data);
- resolve_label_var(ctx, &expr->br.var);
+Result Context::OnBrExpr(Expr* expr) {
+ resolve_label_var(this, &expr->br.var);
return Result::Ok;
}
-static Result on_br_if_expr(Expr* expr, void* user_data) {
- Context* ctx = static_cast<Context*>(user_data);
- resolve_label_var(ctx, &expr->br_if.var);
+Result Context::OnBrIfExpr(Expr* expr) {
+ resolve_label_var(this, &expr->br_if.var);
return Result::Ok;
}
-static Result on_br_table_expr(Expr* expr, void* user_data) {
- Context* ctx = static_cast<Context*>(user_data);
+Result Context::OnBrTableExpr(Expr* expr) {
for (Var& target: *expr->br_table.targets)
- resolve_label_var(ctx, &target);
- resolve_label_var(ctx, &expr->br_table.default_target);
+ resolve_label_var(this, &target);
+ resolve_label_var(this, &expr->br_table.default_target);
return Result::Ok;
}
-static Result on_call_expr(Expr* expr, void* user_data) {
- Context* ctx = static_cast<Context*>(user_data);
- resolve_func_var(ctx, &expr->call.var);
+Result Context::OnCallExpr(Expr* expr) {
+ resolve_func_var(this, &expr->call.var);
return Result::Ok;
}
-static Result on_call_indirect_expr(Expr* expr, void* user_data) {
- Context* ctx = static_cast<Context*>(user_data);
- resolve_func_type_var(ctx, &expr->call_indirect.var);
+Result Context::OnCallIndirectExpr(Expr* expr) {
+ resolve_func_type_var(this, &expr->call_indirect.var);
return Result::Ok;
}
-static Result on_get_global_expr(Expr* expr, void* user_data) {
- Context* ctx = static_cast<Context*>(user_data);
- resolve_global_var(ctx, &expr->get_global.var);
+Result Context::OnGetGlobalExpr(Expr* expr) {
+ resolve_global_var(this, &expr->get_global.var);
return Result::Ok;
}
-static Result on_get_local_expr(Expr* expr, void* user_data) {
- Context* ctx = static_cast<Context*>(user_data);
- resolve_local_var(ctx, &expr->get_local.var);
+Result Context::OnGetLocalExpr(Expr* expr) {
+ resolve_local_var(this, &expr->get_local.var);
return Result::Ok;
}
-static Result begin_if_expr(Expr* expr, void* user_data) {
- Context* ctx = static_cast<Context*>(user_data);
- push_label(ctx, &expr->if_.true_->label);
+Result Context::BeginIfExpr(Expr* expr) {
+ push_label(this, &expr->if_.true_->label);
return Result::Ok;
}
-static Result end_if_expr(Expr* expr, void* user_data) {
- Context* ctx = static_cast<Context*>(user_data);
- pop_label(ctx);
+Result Context::EndIfExpr(Expr* expr) {
+ pop_label(this);
return Result::Ok;
}
-static Result on_set_global_expr(Expr* expr, void* user_data) {
- Context* ctx = static_cast<Context*>(user_data);
- resolve_global_var(ctx, &expr->set_global.var);
+Result Context::OnSetGlobalExpr(Expr* expr) {
+ resolve_global_var(this, &expr->set_global.var);
return Result::Ok;
}
-static Result on_set_local_expr(Expr* expr, void* user_data) {
- Context* ctx = static_cast<Context*>(user_data);
- resolve_local_var(ctx, &expr->set_local.var);
+Result Context::OnSetLocalExpr(Expr* expr) {
+ resolve_local_var(this, &expr->set_local.var);
return Result::Ok;
}
-static Result on_tee_local_expr(Expr* expr, void* user_data) {
- Context* ctx = static_cast<Context*>(user_data);
- resolve_local_var(ctx, &expr->tee_local.var);
+Result Context::OnTeeLocalExpr(Expr* expr) {
+ resolve_local_var(this, &expr->tee_local.var);
return Result::Ok;
}
@@ -273,7 +273,7 @@ static void visit_func(Context* ctx, Func* func) {
check_duplicate_bindings(ctx, &func->param_bindings, "parameter");
check_duplicate_bindings(ctx, &func->local_bindings, "local");
- visit_func(func, &ctx->visitor);
+ ctx->visitor.VisitFunc(func);
ctx->current_func = nullptr;
}
@@ -298,19 +298,19 @@ static void visit_export(Context* ctx, Export* export_) {
}
static void visit_global(Context* ctx, Global* global) {
- visit_expr_list(global->init_expr, &ctx->visitor);
+ ctx->visitor.VisitExprList(global->init_expr);
}
static void visit_elem_segment(Context* ctx, ElemSegment* segment) {
resolve_table_var(ctx, &segment->table_var);
- visit_expr_list(segment->offset, &ctx->visitor);
+ ctx->visitor.VisitExprList(segment->offset);
for (Var& var: segment->vars)
resolve_func_var(ctx, &var);
}
static void visit_data_segment(Context* ctx, DataSegment* segment) {
resolve_memory_var(ctx, &segment->memory_var);
- visit_expr_list(segment->offset, &ctx->visitor);
+ ctx->visitor.VisitExprList(segment->offset);
}
static void visit_module(Context* ctx, Module* module) {
@@ -372,8 +372,6 @@ static void visit_command(Context* ctx, Command* command) {
Context new_ctx;
new_ctx.error_handler = &new_error_handler;
new_ctx.lexer = ctx->lexer;
- new_ctx.visitor = ctx->visitor;
- new_ctx.visitor.user_data = &new_ctx;
new_ctx.result = Result::Ok;
visit_raw_module(&new_ctx, command->assert_invalid.module);
@@ -412,23 +410,6 @@ static void init_context(Context* ctx,
ctx->error_handler = error_handler;
ctx->result = Result::Ok;
ctx->script = script;
- ctx->visitor.user_data = ctx;
- ctx->visitor.begin_block_expr = begin_block_expr;
- ctx->visitor.end_block_expr = end_block_expr;
- ctx->visitor.begin_loop_expr = begin_loop_expr;
- ctx->visitor.end_loop_expr = end_loop_expr;
- ctx->visitor.on_br_expr = on_br_expr;
- ctx->visitor.on_br_if_expr = on_br_if_expr;
- ctx->visitor.on_br_table_expr = on_br_table_expr;
- ctx->visitor.on_call_expr = on_call_expr;
- ctx->visitor.on_call_indirect_expr = on_call_indirect_expr;
- ctx->visitor.on_get_global_expr = on_get_global_expr;
- ctx->visitor.on_get_local_expr = on_get_local_expr;
- ctx->visitor.begin_if_expr = begin_if_expr;
- ctx->visitor.end_if_expr = end_if_expr;
- ctx->visitor.on_set_global_expr = on_set_global_expr;
- ctx->visitor.on_set_local_expr = on_set_local_expr;
- ctx->visitor.on_tee_local_expr = on_tee_local_expr;
}
Result resolve_names_module(WastLexer* lexer,