diff options
-rw-r--r-- | CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/apply-names.cc | 125 | ||||
-rw-r--r-- | src/expr-visitor.cc | 163 | ||||
-rw-r--r-- | src/expr-visitor.h | 116 | ||||
-rw-r--r-- | src/generate-names.cc | 30 | ||||
-rw-r--r-- | src/ir.cc | 146 | ||||
-rw-r--r-- | src/ir.h | 53 | ||||
-rw-r--r-- | src/resolve-names.cc | 133 |
8 files changed, 413 insertions, 354 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 227b4563..721e0427 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -228,6 +228,7 @@ add_library(libwabt STATIC src/hash-util.cc src/string-view.cc src/ir.cc + src/expr-visitor.cc src/lexer-source.cc src/lexer-source-line-finder.cc src/wast-parser-lexer-shared.cc 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; @@ -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 @@ -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, |