diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/apply-names.cc | 221 | ||||
-rw-r--r-- | src/generate-names.cc | 182 | ||||
-rw-r--r-- | src/resolve-names.cc | 347 |
3 files changed, 406 insertions, 344 deletions
diff --git a/src/apply-names.cc b/src/apply-names.cc index b61cd7f7..acfd511b 100644 --- a/src/apply-names.cc +++ b/src/apply-names.cc @@ -33,9 +33,13 @@ namespace wabt { namespace { -struct Context : ExprVisitor::DelegateNop { - Context(); +class NameApplier : public ExprVisitor::DelegateNop { + public: + NameApplier(); + Result VisitModule(Module* module); + + // Implementation of ExprVisitor::DelegateNop. Result BeginBlockExpr(Expr*) override; Result EndBlockExpr(Expr*) override; Result OnBrExpr(Expr*) override; @@ -53,42 +57,57 @@ struct Context : ExprVisitor::DelegateNop { Result OnSetLocalExpr(Expr*) override; Result OnTeeLocalExpr(Expr*) override; - Module* module = nullptr; - Func* current_func = nullptr; - ExprVisitor visitor; + private: + void PushLabel(Label* label); + void PopLabel(); + Label* FindLabelByVar(Var* var); + void UseNameForVar(StringSlice* name, Var* var); + Result UseNameForFuncTypeVar(Module* module, Var* var); + Result UseNameForFuncVar(Module* module, Var* var); + Result UseNameForGlobalVar(Module* module, Var* var); + Result UseNameForTableVar(Module* module, Var* var); + Result UseNameForMemoryVar(Module* module, Var* var); + Result UseNameForParamAndLocalVar(Func* func, Var* var); + Result VisitFunc(Index func_index, Func* func); + Result VisitExport(Index export_index, Export* export_); + Result VisitElemSegment(Index elem_segment_index, ElemSegment* segment); + Result VisitDataSegment(Index data_segment_index, DataSegment* segment); + + Module* module_ = nullptr; + Func* current_func_ = nullptr; + ExprVisitor visitor_; /* mapping from param index to its name, if any, for the current func */ - std::vector<std::string> param_index_to_name; - std::vector<std::string> local_index_to_name; - std::vector<Label*> labels; + std::vector<std::string> param_index_to_name_; + std::vector<std::string> local_index_to_name_; + std::vector<Label*> labels_; }; -Context::Context() : visitor(this) { -} +NameApplier::NameApplier() : visitor_(this) {} -void push_label(Context* ctx, Label* label) { - ctx->labels.push_back(label); +void NameApplier::PushLabel(Label* label) { + labels_.push_back(label); } -void pop_label(Context* ctx) { - ctx->labels.pop_back(); +void NameApplier::PopLabel() { + labels_.pop_back(); } -Label* find_label_by_var(Context* ctx, Var* var) { +Label* NameApplier::FindLabelByVar(Var* var) { if (var->type == VarType::Name) { - for (int i = ctx->labels.size() - 1; i >= 0; --i) { - Label* label = ctx->labels[i]; + for (int i = labels_.size() - 1; i >= 0; --i) { + Label* label = labels_[i]; if (string_slices_are_equal(label, &var->name)) return label; } return nullptr; } else { - if (var->index >= ctx->labels.size()) + if (var->index >= labels_.size()) return nullptr; - return ctx->labels[ctx->labels.size() - 1 - var->index]; + return labels_[labels_.size() - 1 - var->index]; } } -void use_name_for_var(StringSlice* name, Var* var) { +void NameApplier::UseNameForVar(StringSlice* name, Var* var) { if (var->type == VarType::Name) { assert(string_slices_are_equal(name, &var->name)); } @@ -99,47 +118,47 @@ void use_name_for_var(StringSlice* name, Var* var) { } } -Result use_name_for_func_type_var(Module* module, Var* var) { +Result NameApplier::UseNameForFuncTypeVar(Module* module, Var* var) { FuncType* func_type = get_func_type_by_var(module, var); if (!func_type) return Result::Error; - use_name_for_var(&func_type->name, var); + UseNameForVar(&func_type->name, var); return Result::Ok; } -Result use_name_for_func_var(Module* module, Var* var) { +Result NameApplier::UseNameForFuncVar(Module* module, Var* var) { Func* func = get_func_by_var(module, var); if (!func) return Result::Error; - use_name_for_var(&func->name, var); + UseNameForVar(&func->name, var); return Result::Ok; } -Result use_name_for_global_var(Module* module, Var* var) { +Result NameApplier::UseNameForGlobalVar(Module* module, Var* var) { Global* global = get_global_by_var(module, var); if (!global) return Result::Error; - use_name_for_var(&global->name, var); + UseNameForVar(&global->name, var); return Result::Ok; } -Result use_name_for_table_var(Module* module, Var* var) { +Result NameApplier::UseNameForTableVar(Module* module, Var* var) { Table* table = get_table_by_var(module, var); if (!table) return Result::Error; - use_name_for_var(&table->name, var); + UseNameForVar(&table->name, var); return Result::Ok; } -Result use_name_for_memory_var(Module* module, Var* var) { +Result NameApplier::UseNameForMemoryVar(Module* module, Var* var) { Memory* memory = get_memory_by_var(module, var); if (!memory) return Result::Error; - use_name_for_var(&memory->name, var); + UseNameForVar(&memory->name, var); return Result::Ok; } -Result use_name_for_param_and_local_var(Context* ctx, Func* func, Var* var) { +Result NameApplier::UseNameForParamAndLocalVar(Func* func, Var* var) { Index local_index = get_local_index_by_var(func, var); if (local_index >= get_num_params_and_locals(func)) return Result::Error; @@ -148,13 +167,13 @@ Result use_name_for_param_and_local_var(Context* ctx, Func* func, Var* var) { std::string* name; if (local_index < num_params) { /* param */ - assert(local_index < ctx->param_index_to_name.size()); - name = &ctx->param_index_to_name[local_index]; + assert(local_index < param_index_to_name_.size()); + name = ¶m_index_to_name_[local_index]; } else { /* local */ local_index -= num_params; - assert(local_index < ctx->local_index_to_name.size()); - name = &ctx->local_index_to_name[local_index]; + assert(local_index < local_index_to_name_.size()); + name = &local_index_to_name_[local_index]; } if (var->type == VarType::Name) { @@ -170,159 +189,153 @@ Result use_name_for_param_and_local_var(Context* ctx, Func* func, Var* var) { return Result::Ok; } -Result Context::BeginBlockExpr(Expr* expr) { - push_label(this, &expr->block->label); +Result NameApplier::BeginBlockExpr(Expr* expr) { + PushLabel(&expr->block->label); return Result::Ok; } -Result Context::EndBlockExpr(Expr* expr) { - pop_label(this); +Result NameApplier::EndBlockExpr(Expr* expr) { + PopLabel(); return Result::Ok; } -Result Context::BeginLoopExpr(Expr* expr) { - push_label(this, &expr->loop->label); +Result NameApplier::BeginLoopExpr(Expr* expr) { + PushLabel(&expr->loop->label); return Result::Ok; } -Result Context::EndLoopExpr(Expr* expr) { - pop_label(this); +Result NameApplier::EndLoopExpr(Expr* expr) { + PopLabel(); return Result::Ok; } -Result Context::OnBrExpr(Expr* expr) { - Label* label = find_label_by_var(this, &expr->br.var); - use_name_for_var(label, &expr->br.var); +Result NameApplier::OnBrExpr(Expr* expr) { + Label* label = FindLabelByVar(&expr->br.var); + UseNameForVar(label, &expr->br.var); return Result::Ok; } -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); +Result NameApplier::OnBrIfExpr(Expr* expr) { + Label* label = FindLabelByVar(&expr->br_if.var); + UseNameForVar(label, &expr->br_if.var); return Result::Ok; } -Result Context::OnBrTableExpr(Expr* expr) { +Result NameApplier::OnBrTableExpr(Expr* expr) { VarVector& targets = *expr->br_table.targets; for (Var& target : targets) { - Label* label = find_label_by_var(this, &target); - use_name_for_var(label, &target); + Label* label = FindLabelByVar(&target); + UseNameForVar(label, &target); } - Label* label = find_label_by_var(this, &expr->br_table.default_target); - use_name_for_var(label, &expr->br_table.default_target); + Label* label = FindLabelByVar(&expr->br_table.default_target); + UseNameForVar(label, &expr->br_table.default_target); return Result::Ok; } -Result Context::OnCallExpr(Expr* expr) { - CHECK_RESULT(use_name_for_func_var(module, &expr->call.var)); +Result NameApplier::OnCallExpr(Expr* expr) { + CHECK_RESULT(UseNameForFuncVar(module_, &expr->call.var)); return Result::Ok; } -Result Context::OnCallIndirectExpr(Expr* expr) { - CHECK_RESULT(use_name_for_func_type_var(module, &expr->call_indirect.var)); +Result NameApplier::OnCallIndirectExpr(Expr* expr) { + CHECK_RESULT(UseNameForFuncTypeVar(module_, &expr->call_indirect.var)); return Result::Ok; } -Result Context::OnGetGlobalExpr(Expr* expr) { - CHECK_RESULT(use_name_for_global_var(module, &expr->get_global.var)); +Result NameApplier::OnGetGlobalExpr(Expr* expr) { + CHECK_RESULT(UseNameForGlobalVar(module_, &expr->get_global.var)); return Result::Ok; } -Result Context::OnGetLocalExpr(Expr* expr) { - CHECK_RESULT(use_name_for_param_and_local_var(this, current_func, - &expr->get_local.var)); +Result NameApplier::OnGetLocalExpr(Expr* expr) { + CHECK_RESULT(UseNameForParamAndLocalVar(current_func_, &expr->get_local.var)); return Result::Ok; } -Result Context::BeginIfExpr(Expr* expr) { - push_label(this, &expr->if_.true_->label); +Result NameApplier::BeginIfExpr(Expr* expr) { + PushLabel(&expr->if_.true_->label); return Result::Ok; } -Result Context::EndIfExpr(Expr* expr) { - pop_label(this); +Result NameApplier::EndIfExpr(Expr* expr) { + PopLabel(); return Result::Ok; } -Result Context::OnSetGlobalExpr(Expr* expr) { - CHECK_RESULT(use_name_for_global_var(module, &expr->set_global.var)); +Result NameApplier::OnSetGlobalExpr(Expr* expr) { + CHECK_RESULT(UseNameForGlobalVar(module_, &expr->set_global.var)); return Result::Ok; } -Result Context::OnSetLocalExpr(Expr* expr) { - CHECK_RESULT(use_name_for_param_and_local_var(this, current_func, - &expr->set_local.var)); +Result NameApplier::OnSetLocalExpr(Expr* expr) { + CHECK_RESULT(UseNameForParamAndLocalVar(current_func_, &expr->set_local.var)); return Result::Ok; } -Result Context::OnTeeLocalExpr(Expr* expr) { - CHECK_RESULT(use_name_for_param_and_local_var(this, current_func, - &expr->tee_local.var)); +Result NameApplier::OnTeeLocalExpr(Expr* expr) { + CHECK_RESULT(UseNameForParamAndLocalVar(current_func_, &expr->tee_local.var)); return Result::Ok; } -Result visit_func(Context* ctx, Index func_index, Func* func) { - ctx->current_func = func; +Result NameApplier::VisitFunc(Index func_index, Func* func) { + current_func_ = func; if (decl_has_func_type(&func->decl)) { - CHECK_RESULT(use_name_for_func_type_var(ctx->module, &func->decl.type_var)); + CHECK_RESULT(UseNameForFuncTypeVar(module_, &func->decl.type_var)); } - make_type_binding_reverse_mapping(func->decl.sig.param_types, - func->param_bindings, - &ctx->param_index_to_name); + make_type_binding_reverse_mapping( + func->decl.sig.param_types, func->param_bindings, ¶m_index_to_name_); make_type_binding_reverse_mapping(func->local_types, func->local_bindings, - &ctx->local_index_to_name); + &local_index_to_name_); - CHECK_RESULT(ctx->visitor.VisitFunc(func)); - ctx->current_func = nullptr; + CHECK_RESULT(visitor_.VisitFunc(func)); + current_func_ = nullptr; return Result::Ok; } -Result visit_export(Context* ctx, Index export_index, Export* export_) { +Result NameApplier::VisitExport(Index export_index, Export* export_) { if (export_->kind == ExternalKind::Func) { - use_name_for_func_var(ctx->module, &export_->var); + UseNameForFuncVar(module_, &export_->var); } return Result::Ok; } -Result visit_elem_segment(Context* ctx, - Index elem_segment_index, - ElemSegment* segment) { - CHECK_RESULT(use_name_for_table_var(ctx->module, &segment->table_var)); +Result NameApplier::VisitElemSegment(Index elem_segment_index, + ElemSegment* segment) { + CHECK_RESULT(UseNameForTableVar(module_, &segment->table_var)); for (Var& var : segment->vars) { - CHECK_RESULT(use_name_for_func_var(ctx->module, &var)); + CHECK_RESULT(UseNameForFuncVar(module_, &var)); } return Result::Ok; } -Result visit_data_segment(Context* ctx, - Index data_segment_index, - DataSegment* segment) { - CHECK_RESULT(use_name_for_memory_var(ctx->module, &segment->memory_var)); +Result NameApplier::VisitDataSegment(Index data_segment_index, + DataSegment* segment) { + CHECK_RESULT(UseNameForMemoryVar(module_, &segment->memory_var)); return Result::Ok; } -Result visit_module(Context* ctx, Module* module) { +Result NameApplier::VisitModule(Module* module) { + module_ = module; for (size_t i = 0; i < module->funcs.size(); ++i) - CHECK_RESULT(visit_func(ctx, i, module->funcs[i])); + CHECK_RESULT(VisitFunc(i, module->funcs[i])); for (size_t i = 0; i < module->exports.size(); ++i) - CHECK_RESULT(visit_export(ctx, i, module->exports[i])); + CHECK_RESULT(VisitExport(i, module->exports[i])); for (size_t i = 0; i < module->elem_segments.size(); ++i) - CHECK_RESULT(visit_elem_segment(ctx, i, module->elem_segments[i])); + CHECK_RESULT(VisitElemSegment(i, module->elem_segments[i])); for (size_t i = 0; i < module->data_segments.size(); ++i) - CHECK_RESULT(visit_data_segment(ctx, i, module->data_segments[i])); + CHECK_RESULT(VisitDataSegment(i, module->data_segments[i])); + module_ = nullptr; return Result::Ok; } } // namespace Result apply_names(Module* module) { - Context ctx; - ctx.module = module; - Result result = visit_module(&ctx, module); - return result; + NameApplier applier; + return applier.VisitModule(module); } } // namespace wabt diff --git a/src/generate-names.cc b/src/generate-names.cc index 667e3ecf..a2b286d2 100644 --- a/src/generate-names.cc +++ b/src/generate-names.cc @@ -24,36 +24,65 @@ #include "expr-visitor.h" #include "ir.h" -#define CHECK_RESULT(expr) \ - do { \ - if (WABT_FAILED(expr)) \ - return Result::Error; \ +#define CHECK_RESULT(expr) \ + do { \ + if (WABT_FAILED(expr)) \ + return Result::Error; \ } while (0) namespace wabt { namespace { -struct Context : public ExprVisitor::DelegateNop { - Context() : module(nullptr), visitor(this), label_count(0) {} +class NameGenerator : public ExprVisitor::DelegateNop { + public: + NameGenerator(); + Result VisitModule(Module* module); + + // Implementation of ExprVisitor::DelegateNop. Result BeginBlockExpr(Expr* expr) override; Result BeginLoopExpr(Expr* expr) override; Result BeginIfExpr(Expr* expr) override; - Module* module; - ExprVisitor visitor; - std::vector<std::string> index_to_name; - Index label_count; + private: + static bool HasName(StringSlice* str); + static void GenerateName(const char* prefix, Index index, StringSlice* str); + static void MaybeGenerateName(const char* prefix, + Index index, + StringSlice* str); + static void GenerateAndBindName(BindingHash* bindings, + const char* prefix, + Index index, + StringSlice* str); + static void MaybeGenerateAndBindName(BindingHash* bindings, + const char* prefix, + Index index, + StringSlice* str); + void GenerateAndBindLocalNames(BindingHash* bindings, const char* prefix); + Result VisitFunc(Index func_index, Func* func); + Result VisitGlobal(Index global_index, Global* global); + Result VisitFuncType(Index func_type_index, FuncType* func_type); + Result VisitTable(Index table_index, Table* table); + Result VisitMemory(Index memory_index, Memory* memory); + + Module* module_ = nullptr; + ExprVisitor visitor_; + std::vector<std::string> index_to_name_; + Index label_count_ = 0; }; -} // namespace +NameGenerator::NameGenerator() : visitor_(this) {} -static bool has_name(StringSlice* str) { +// static +bool NameGenerator::HasName(StringSlice* str) { return str->length > 0; } -static void generate_name(const char* prefix, Index index, StringSlice* str) { +// static +void NameGenerator::GenerateName(const char* prefix, + Index index, + StringSlice* str) { size_t prefix_len = strlen(prefix); size_t buffer_len = prefix_len + 20; /* add space for the number */ char* buffer = static_cast<char*>(alloca(buffer_len)); @@ -65,121 +94,124 @@ static void generate_name(const char* prefix, Index index, StringSlice* str) { *str = dup_string_slice(buf); } -static void maybe_generate_name(const char* prefix, - Index index, - StringSlice* str) { - if (!has_name(str)) - generate_name(prefix, index, str); +// static +void NameGenerator::MaybeGenerateName(const char* prefix, + Index index, + StringSlice* str) { + if (!HasName(str)) + GenerateName(prefix, index, str); } -static void generate_and_bind_name(BindingHash* bindings, - const char* prefix, - Index index, - StringSlice* str) { - generate_name(prefix, index, str); +// static +void NameGenerator::GenerateAndBindName(BindingHash* bindings, + const char* prefix, + Index index, + StringSlice* str) { + GenerateName(prefix, index, str); bindings->emplace(string_slice_to_string(*str), Binding(index)); } -static void maybe_generate_and_bind_name(BindingHash* bindings, - const char* prefix, - Index index, - StringSlice* str) { - if (!has_name(str)) - generate_and_bind_name(bindings, prefix, index, str); +// static +void NameGenerator::MaybeGenerateAndBindName(BindingHash* bindings, + const char* prefix, + Index index, + StringSlice* str) { + if (!HasName(str)) + GenerateAndBindName(bindings, prefix, index, str); } -static void generate_and_bind_local_names(Context* ctx, - BindingHash* bindings, - const char* prefix) { - for (size_t i = 0; i < ctx->index_to_name.size(); ++i) { - const std::string& old_name = ctx->index_to_name[i]; +void NameGenerator::GenerateAndBindLocalNames(BindingHash* bindings, + const char* prefix) { + for (size_t i = 0; i < index_to_name_.size(); ++i) { + const std::string& old_name = index_to_name_[i]; if (!old_name.empty()) continue; StringSlice new_name; - generate_and_bind_name(bindings, prefix, i, &new_name); - ctx->index_to_name[i] = string_slice_to_string(new_name); + GenerateAndBindName(bindings, prefix, i, &new_name); + index_to_name_[i] = string_slice_to_string(new_name); destroy_string_slice(&new_name); } } -Result Context::BeginBlockExpr(Expr* expr) { - maybe_generate_name("$B", label_count++, &expr->block->label); +Result NameGenerator::BeginBlockExpr(Expr* expr) { + MaybeGenerateName("$B", label_count_++, &expr->block->label); return Result::Ok; } -Result Context::BeginLoopExpr(Expr* expr) { - maybe_generate_name("$L", label_count++, &expr->loop->label); +Result NameGenerator::BeginLoopExpr(Expr* expr) { + MaybeGenerateName("$L", label_count_++, &expr->loop->label); return Result::Ok; } -Result Context::BeginIfExpr(Expr* expr) { - maybe_generate_name("$I", label_count++, &expr->if_.true_->label); +Result NameGenerator::BeginIfExpr(Expr* expr) { + MaybeGenerateName("$I", label_count_++, &expr->if_.true_->label); return Result::Ok; } -static Result visit_func(Context* ctx, Index func_index, Func* func) { - maybe_generate_and_bind_name(&ctx->module->func_bindings, "$f", func_index, - &func->name); +Result NameGenerator::VisitFunc(Index func_index, Func* func) { + MaybeGenerateAndBindName(&module_->func_bindings, "$f", func_index, + &func->name); make_type_binding_reverse_mapping(func->decl.sig.param_types, - func->param_bindings, &ctx->index_to_name); - generate_and_bind_local_names(ctx, &func->param_bindings, "$p"); + func->param_bindings, &index_to_name_); + GenerateAndBindLocalNames(&func->param_bindings, "$p"); make_type_binding_reverse_mapping(func->local_types, func->local_bindings, - &ctx->index_to_name); - generate_and_bind_local_names(ctx, &func->local_bindings, "$l"); + &index_to_name_); + GenerateAndBindLocalNames(&func->local_bindings, "$l"); - ctx->label_count = 0; - CHECK_RESULT(ctx->visitor.VisitFunc(func)); + label_count_ = 0; + CHECK_RESULT(visitor_.VisitFunc(func)); return Result::Ok; } -static Result visit_global(Context* ctx, Index global_index, Global* global) { - maybe_generate_and_bind_name(&ctx->module->global_bindings, "$g", - global_index, &global->name); +Result NameGenerator::VisitGlobal(Index global_index, Global* global) { + MaybeGenerateAndBindName(&module_->global_bindings, "$g", global_index, + &global->name); return Result::Ok; } -static Result visit_func_type(Context* ctx, - Index func_type_index, - FuncType* func_type) { - maybe_generate_and_bind_name(&ctx->module->func_type_bindings, "$t", - func_type_index, &func_type->name); +Result NameGenerator::VisitFuncType(Index func_type_index, + FuncType* func_type) { + MaybeGenerateAndBindName(&module_->func_type_bindings, "$t", func_type_index, + &func_type->name); return Result::Ok; } -static Result visit_table(Context* ctx, Index table_index, Table* table) { - maybe_generate_and_bind_name(&ctx->module->table_bindings, "$T", table_index, - &table->name); +Result NameGenerator::VisitTable(Index table_index, Table* table) { + MaybeGenerateAndBindName(&module_->table_bindings, "$T", table_index, + &table->name); return Result::Ok; } -static Result visit_memory(Context* ctx, Index memory_index, Memory* memory) { - maybe_generate_and_bind_name(&ctx->module->memory_bindings, "$M", - memory_index, &memory->name); +Result NameGenerator::VisitMemory(Index memory_index, Memory* memory) { + MaybeGenerateAndBindName(&module_->memory_bindings, "$M", memory_index, + &memory->name); return Result::Ok; } -static Result visit_module(Context* ctx, Module* module) { +Result NameGenerator::VisitModule(Module* module) { + module_ = module; for (Index i = 0; i < module->globals.size(); ++i) - CHECK_RESULT(visit_global(ctx, i, module->globals[i])); + CHECK_RESULT(VisitGlobal(i, module->globals[i])); for (Index i = 0; i < module->func_types.size(); ++i) - CHECK_RESULT(visit_func_type(ctx, i, module->func_types[i])); + CHECK_RESULT(VisitFuncType(i, module->func_types[i])); for (Index i = 0; i < module->funcs.size(); ++i) - CHECK_RESULT(visit_func(ctx, i, module->funcs[i])); + CHECK_RESULT(VisitFunc(i, module->funcs[i])); for (Index i = 0; i < module->tables.size(); ++i) - CHECK_RESULT(visit_table(ctx, i, module->tables[i])); + CHECK_RESULT(VisitTable(i, module->tables[i])); for (Index i = 0; i < module->memories.size(); ++i) - CHECK_RESULT(visit_memory(ctx, i, module->memories[i])); + CHECK_RESULT(VisitMemory(i, module->memories[i])); + module_ = nullptr; return Result::Ok; } +} // namespace + Result generate_names(Module* module) { - Context ctx; - ctx.module = module; - Result result = visit_module(&ctx, module); - return result; + NameGenerator generator; + return generator.VisitModule(module); } } // namespace wabt diff --git a/src/resolve-names.cc b/src/resolve-names.cc index 70eff09c..b5958f4a 100644 --- a/src/resolve-names.cc +++ b/src/resolve-names.cc @@ -29,9 +29,16 @@ namespace { typedef Label* LabelPtr; -struct Context : ExprVisitor::DelegateNop { - Context(); +class NameResolver : public ExprVisitor::DelegateNop { + public: + NameResolver(WastLexer* lexer, + Script* script, + SourceErrorHandler* error_handler); + Result VisitModule(Module* module); + Result VisitScript(Script* script); + + // Implementation of ExprVisitor::DelegateNop. Result BeginBlockExpr(Expr*) override; Result EndBlockExpr(Expr*) override; Result OnBrExpr(Expr*) override; @@ -49,91 +56,119 @@ struct Context : ExprVisitor::DelegateNop { Result OnSetLocalExpr(Expr*) override; Result OnTeeLocalExpr(Expr*) override; - SourceErrorHandler* error_handler = nullptr; - WastLexer* lexer = nullptr; - Script* script = nullptr; - Module* current_module = nullptr; - Func* current_func = nullptr; - ExprVisitor visitor; - std::vector<Label*> labels; - Result result = Result::Ok; + private: + void PrintError(const Location* loc, const char* fmt, ...); + void PushLabel(Label* label); + void PopLabel(); + static void OnDuplicateBinding(const BindingHash::value_type& a, + const BindingHash::value_type& b, + void* user_data); + void CheckDuplicateBindings(const BindingHash* bindings, const char* desc); + void ResolveLabelVar(Var* var); + void ResolveVar(const BindingHash* bindings, Var* var, const char* desc); + void ResolveFuncVar(Var* var); + void ResolveGlobalVar(Var* var); + void ResolveFuncTypeVar(Var* var); + void ResolveTableVar(Var* var); + void ResolveMemoryVar(Var* var); + void ResolveLocalVar(Var* var); + void VisitFunc(Func* func); + void VisitExport(Export* export_); + void VisitGlobal(Global* global); + void VisitElemSegment(ElemSegment* segment); + void VisitDataSegment(DataSegment* segment); + void VisitRawModule(RawModule* raw_module); + void VisitCommand(Command* command); + + SourceErrorHandler* error_handler_ = nullptr; + WastLexer* lexer_ = nullptr; + Script* script_ = nullptr; + Module* current_module_ = nullptr; + Func* current_func_ = nullptr; + ExprVisitor visitor_; + std::vector<Label*> labels_; + Result result_ = Result::Ok; }; -Context::Context() : visitor(this) {} +NameResolver::NameResolver(WastLexer* lexer, + Script* script, + SourceErrorHandler* error_handler) + : error_handler_(error_handler), + lexer_(lexer), + script_(script), + visitor_(this) {} } // namespace -static void WABT_PRINTF_FORMAT(3, 4) - print_error(Context* ctx, const Location* loc, const char* fmt, ...) { - ctx->result = Result::Error; +void WABT_PRINTF_FORMAT(3, 4) NameResolver::PrintError(const Location* loc, + const char* fmt, + ...) { + result_ = Result::Error; va_list args; va_start(args, fmt); - wast_format_error(ctx->error_handler, loc, ctx->lexer, fmt, args); + wast_format_error(error_handler_, loc, lexer_, fmt, args); va_end(args); } -static void push_label(Context* ctx, Label* label) { - ctx->labels.push_back(label); +void NameResolver::PushLabel(Label* label) { + labels_.push_back(label); } -static void pop_label(Context* ctx) { - ctx->labels.pop_back(); +void NameResolver::PopLabel() { + labels_.pop_back(); } struct FindDuplicateBindingContext { - Context* ctx; + NameResolver* resolver; const char* desc; }; -static void on_duplicate_binding(const BindingHash::value_type& a, - const BindingHash::value_type& b, - void* user_data) { +// static +void NameResolver::OnDuplicateBinding(const BindingHash::value_type& a, + const BindingHash::value_type& b, + void* user_data) { FindDuplicateBindingContext* fdbc = static_cast<FindDuplicateBindingContext*>(user_data); /* choose the location that is later in the file */ const Location& a_loc = a.second.loc; const Location& b_loc = b.second.loc; const Location& loc = a_loc.line > b_loc.line ? a_loc : b_loc; - print_error(fdbc->ctx, &loc, "redefinition of %s \"%s\"", fdbc->desc, - a.first.c_str()); + fdbc->resolver->PrintError(&loc, "redefinition of %s \"%s\"", fdbc->desc, + a.first.c_str()); } -static void check_duplicate_bindings(Context* ctx, - const BindingHash* bindings, - const char* desc) { +void NameResolver::CheckDuplicateBindings(const BindingHash* bindings, + const char* desc) { FindDuplicateBindingContext fdbc; - fdbc.ctx = ctx; + fdbc.resolver = this; fdbc.desc = desc; - bindings->find_duplicates(on_duplicate_binding, &fdbc); + bindings->find_duplicates(OnDuplicateBinding, &fdbc); } -static void resolve_label_var(Context* ctx, Var* var) { +void NameResolver::ResolveLabelVar(Var* var) { if (var->type == VarType::Name) { - for (int i = ctx->labels.size() - 1; i >= 0; --i) { - Label* label = ctx->labels[i]; + for (int i = labels_.size() - 1; i >= 0; --i) { + Label* label = labels_[i]; if (string_slices_are_equal(label, &var->name)) { destroy_string_slice(&var->name); var->type = VarType::Index; - var->index = ctx->labels.size() - i - 1; + var->index = labels_.size() - i - 1; return; } } - print_error(ctx, &var->loc, - "undefined label variable \"" PRIstringslice "\"", - WABT_PRINTF_STRING_SLICE_ARG(var->name)); + PrintError(&var->loc, "undefined label variable \"" PRIstringslice "\"", + WABT_PRINTF_STRING_SLICE_ARG(var->name)); } } -static void resolve_var(Context* ctx, - const BindingHash* bindings, - Var* var, - const char* desc) { +void NameResolver::ResolveVar(const BindingHash* bindings, + Var* var, + const char* desc) { if (var->type == VarType::Name) { int index = get_index_from_var(bindings, var); if (index == -1) { - print_error(ctx, &var->loc, - "undefined %s variable \"" PRIstringslice "\"", desc, - WABT_PRINTF_STRING_SLICE_ARG(var->name)); + PrintError(&var->loc, "undefined %s variable \"" PRIstringslice "\"", + desc, WABT_PRINTF_STRING_SLICE_ARG(var->name)); return; } @@ -143,37 +178,35 @@ static void resolve_var(Context* ctx, } } -static void resolve_func_var(Context* ctx, Var* var) { - resolve_var(ctx, &ctx->current_module->func_bindings, var, "function"); +void NameResolver::ResolveFuncVar(Var* var) { + ResolveVar(¤t_module_->func_bindings, var, "function"); } -static void resolve_global_var(Context* ctx, Var* var) { - resolve_var(ctx, &ctx->current_module->global_bindings, var, "global"); +void NameResolver::ResolveGlobalVar(Var* var) { + ResolveVar(¤t_module_->global_bindings, var, "global"); } -static void resolve_func_type_var(Context* ctx, Var* var) { - resolve_var(ctx, &ctx->current_module->func_type_bindings, var, - "function type"); +void NameResolver::ResolveFuncTypeVar(Var* var) { + ResolveVar(¤t_module_->func_type_bindings, var, "function type"); } -static void resolve_table_var(Context* ctx, Var* var) { - resolve_var(ctx, &ctx->current_module->table_bindings, var, "table"); +void NameResolver::ResolveTableVar(Var* var) { + ResolveVar(¤t_module_->table_bindings, var, "table"); } -static void resolve_memory_var(Context* ctx, Var* var) { - resolve_var(ctx, &ctx->current_module->memory_bindings, var, "memory"); +void NameResolver::ResolveMemoryVar(Var* var) { + ResolveVar(¤t_module_->memory_bindings, var, "memory"); } -static void resolve_local_var(Context* ctx, Var* var) { +void NameResolver::ResolveLocalVar(Var* var) { if (var->type == VarType::Name) { - if (!ctx->current_func) + if (!current_func_) return; - int index = get_local_index_by_var(ctx->current_func, var); + int index = get_local_index_by_var(current_func_, var); if (index == -1) { - print_error(ctx, &var->loc, - "undefined local variable \"" PRIstringslice "\"", - WABT_PRINTF_STRING_SLICE_ARG(var->name)); + PrintError(&var->loc, "undefined local variable \"" PRIstringslice "\"", + WABT_PRINTF_STRING_SLICE_ARG(var->name)); return; } @@ -183,168 +216,169 @@ static void resolve_local_var(Context* ctx, Var* var) { } } -Result Context::BeginBlockExpr(Expr* expr) { - push_label(this, &expr->block->label); +Result NameResolver::BeginBlockExpr(Expr* expr) { + PushLabel(&expr->block->label); return Result::Ok; } -Result Context::EndBlockExpr(Expr* expr) { - pop_label(this); +Result NameResolver::EndBlockExpr(Expr* expr) { + PopLabel(); return Result::Ok; } -Result Context::BeginLoopExpr(Expr* expr) { - push_label(this, &expr->loop->label); +Result NameResolver::BeginLoopExpr(Expr* expr) { + PushLabel(&expr->loop->label); return Result::Ok; } -Result Context::EndLoopExpr(Expr* expr) { - pop_label(this); +Result NameResolver::EndLoopExpr(Expr* expr) { + PopLabel(); return Result::Ok; } -Result Context::OnBrExpr(Expr* expr) { - resolve_label_var(this, &expr->br.var); +Result NameResolver::OnBrExpr(Expr* expr) { + ResolveLabelVar(&expr->br.var); return Result::Ok; } -Result Context::OnBrIfExpr(Expr* expr) { - resolve_label_var(this, &expr->br_if.var); +Result NameResolver::OnBrIfExpr(Expr* expr) { + ResolveLabelVar(&expr->br_if.var); return Result::Ok; } -Result Context::OnBrTableExpr(Expr* expr) { - for (Var& target: *expr->br_table.targets) - resolve_label_var(this, &target); - resolve_label_var(this, &expr->br_table.default_target); +Result NameResolver::OnBrTableExpr(Expr* expr) { + for (Var& target : *expr->br_table.targets) + ResolveLabelVar(&target); + ResolveLabelVar(&expr->br_table.default_target); return Result::Ok; } -Result Context::OnCallExpr(Expr* expr) { - resolve_func_var(this, &expr->call.var); +Result NameResolver::OnCallExpr(Expr* expr) { + ResolveFuncVar(&expr->call.var); return Result::Ok; } -Result Context::OnCallIndirectExpr(Expr* expr) { - resolve_func_type_var(this, &expr->call_indirect.var); +Result NameResolver::OnCallIndirectExpr(Expr* expr) { + ResolveFuncTypeVar(&expr->call_indirect.var); return Result::Ok; } -Result Context::OnGetGlobalExpr(Expr* expr) { - resolve_global_var(this, &expr->get_global.var); +Result NameResolver::OnGetGlobalExpr(Expr* expr) { + ResolveGlobalVar(&expr->get_global.var); return Result::Ok; } -Result Context::OnGetLocalExpr(Expr* expr) { - resolve_local_var(this, &expr->get_local.var); +Result NameResolver::OnGetLocalExpr(Expr* expr) { + ResolveLocalVar(&expr->get_local.var); return Result::Ok; } -Result Context::BeginIfExpr(Expr* expr) { - push_label(this, &expr->if_.true_->label); +Result NameResolver::BeginIfExpr(Expr* expr) { + PushLabel(&expr->if_.true_->label); return Result::Ok; } -Result Context::EndIfExpr(Expr* expr) { - pop_label(this); +Result NameResolver::EndIfExpr(Expr* expr) { + PopLabel(); return Result::Ok; } -Result Context::OnSetGlobalExpr(Expr* expr) { - resolve_global_var(this, &expr->set_global.var); +Result NameResolver::OnSetGlobalExpr(Expr* expr) { + ResolveGlobalVar(&expr->set_global.var); return Result::Ok; } -Result Context::OnSetLocalExpr(Expr* expr) { - resolve_local_var(this, &expr->set_local.var); +Result NameResolver::OnSetLocalExpr(Expr* expr) { + ResolveLocalVar(&expr->set_local.var); return Result::Ok; } -Result Context::OnTeeLocalExpr(Expr* expr) { - resolve_local_var(this, &expr->tee_local.var); +Result NameResolver::OnTeeLocalExpr(Expr* expr) { + ResolveLocalVar(&expr->tee_local.var); return Result::Ok; } -static void visit_func(Context* ctx, Func* func) { - ctx->current_func = func; +void NameResolver::VisitFunc(Func* func) { + current_func_ = func; if (decl_has_func_type(&func->decl)) - resolve_func_type_var(ctx, &func->decl.type_var); + ResolveFuncTypeVar(&func->decl.type_var); - check_duplicate_bindings(ctx, &func->param_bindings, "parameter"); - check_duplicate_bindings(ctx, &func->local_bindings, "local"); + CheckDuplicateBindings(&func->param_bindings, "parameter"); + CheckDuplicateBindings(&func->local_bindings, "local"); - ctx->visitor.VisitFunc(func); - ctx->current_func = nullptr; + visitor_.VisitFunc(func); + current_func_ = nullptr; } -static void visit_export(Context* ctx, Export* export_) { +void NameResolver::VisitExport(Export* export_) { switch (export_->kind) { case ExternalKind::Func: - resolve_func_var(ctx, &export_->var); + ResolveFuncVar(&export_->var); break; case ExternalKind::Table: - resolve_table_var(ctx, &export_->var); + ResolveTableVar(&export_->var); break; case ExternalKind::Memory: - resolve_memory_var(ctx, &export_->var); + ResolveMemoryVar(&export_->var); break; case ExternalKind::Global: - resolve_global_var(ctx, &export_->var); + ResolveGlobalVar(&export_->var); break; } } -static void visit_global(Context* ctx, Global* global) { - ctx->visitor.VisitExprList(global->init_expr); +void NameResolver::VisitGlobal(Global* global) { + visitor_.VisitExprList(global->init_expr); } -static void visit_elem_segment(Context* ctx, ElemSegment* segment) { - resolve_table_var(ctx, &segment->table_var); - ctx->visitor.VisitExprList(segment->offset); - for (Var& var: segment->vars) - resolve_func_var(ctx, &var); +void NameResolver::VisitElemSegment(ElemSegment* segment) { + ResolveTableVar(&segment->table_var); + visitor_.VisitExprList(segment->offset); + for (Var& var : segment->vars) + ResolveFuncVar(&var); } -static void visit_data_segment(Context* ctx, DataSegment* segment) { - resolve_memory_var(ctx, &segment->memory_var); - ctx->visitor.VisitExprList(segment->offset); +void NameResolver::VisitDataSegment(DataSegment* segment) { + ResolveMemoryVar(&segment->memory_var); + visitor_.VisitExprList(segment->offset); } -static void visit_module(Context* ctx, Module* module) { - ctx->current_module = module; - check_duplicate_bindings(ctx, &module->func_bindings, "function"); - check_duplicate_bindings(ctx, &module->global_bindings, "global"); - check_duplicate_bindings(ctx, &module->func_type_bindings, "function type"); - check_duplicate_bindings(ctx, &module->table_bindings, "table"); - check_duplicate_bindings(ctx, &module->memory_bindings, "memory"); +Result NameResolver::VisitModule(Module* module) { + current_module_ = module; + CheckDuplicateBindings(&module->func_bindings, "function"); + CheckDuplicateBindings(&module->global_bindings, "global"); + CheckDuplicateBindings(&module->func_type_bindings, "function type"); + CheckDuplicateBindings(&module->table_bindings, "table"); + CheckDuplicateBindings(&module->memory_bindings, "memory"); for (Func* func : module->funcs) - visit_func(ctx, func); + VisitFunc(func); for (Export* export_ : module->exports) - visit_export(ctx, export_); + VisitExport(export_); for (Global* global : module->globals) - visit_global(ctx, global); + VisitGlobal(global); for (ElemSegment* elem_segment : module->elem_segments) - visit_elem_segment(ctx, elem_segment); + VisitElemSegment(elem_segment); for (DataSegment* data_segment : module->data_segments) - visit_data_segment(ctx, data_segment); + VisitDataSegment(data_segment); if (module->start) - resolve_func_var(ctx, module->start); - ctx->current_module = nullptr; + ResolveFuncVar(module->start); + current_module_ = nullptr; + return result_; } -static void visit_raw_module(Context* ctx, RawModule* raw_module) { +void NameResolver::VisitRawModule(RawModule* raw_module) { if (raw_module->type == RawModuleType::Text) - visit_module(ctx, raw_module->text); + VisitModule(raw_module->text); } -static void visit_command(Context* ctx, Command* command) { +void NameResolver::VisitCommand(Command* command) { switch (command->type) { case CommandType::Module: - visit_module(ctx, command->module); + VisitModule(command->module); break; case CommandType::Action: @@ -369,13 +403,9 @@ static void visit_command(Context* ctx, Command* command) { * should try to resolve names when possible. */ SourceErrorHandlerNop new_error_handler; - Context new_ctx; - new_ctx.error_handler = &new_error_handler; - new_ctx.lexer = ctx->lexer; - new_ctx.result = Result::Ok; - - visit_raw_module(&new_ctx, command->assert_invalid.module); - if (WABT_FAILED(new_ctx.result)) { + NameResolver new_resolver(lexer_, script_, &new_error_handler); + new_resolver.VisitRawModule(command->assert_invalid.module); + if (WABT_FAILED(new_resolver.result_)) { command->type = CommandType::AssertInvalidNonBinary; } break; @@ -388,46 +418,33 @@ static void visit_command(Context* ctx, Command* command) { break; case CommandType::AssertUnlinkable: - visit_raw_module(ctx, command->assert_unlinkable.module); + VisitRawModule(command->assert_unlinkable.module); break; case CommandType::AssertUninstantiable: - visit_raw_module(ctx, command->assert_uninstantiable.module); + VisitRawModule(command->assert_uninstantiable.module); break; } } -static void visit_script(Context* ctx, Script* script) { - for (const std::unique_ptr<Command>& command: script->commands) - visit_command(ctx, command.get()); -} - -static void init_context(Context* ctx, - WastLexer* lexer, - Script* script, - SourceErrorHandler* error_handler) { - ctx->lexer = lexer; - ctx->error_handler = error_handler; - ctx->result = Result::Ok; - ctx->script = script; +Result NameResolver::VisitScript(Script* script) { + for (const std::unique_ptr<Command>& command : script->commands) + VisitCommand(command.get()); + return result_; } Result resolve_names_module(WastLexer* lexer, Module* module, SourceErrorHandler* error_handler) { - Context ctx; - init_context(&ctx, lexer, nullptr, error_handler); - visit_module(&ctx, module); - return ctx.result; + NameResolver resolver(lexer, nullptr, error_handler); + return resolver.VisitModule(module); } Result resolve_names_script(WastLexer* lexer, Script* script, SourceErrorHandler* error_handler) { - Context ctx; - init_context(&ctx, lexer, script, error_handler); - visit_script(&ctx, script); - return ctx.result; + NameResolver resolver(lexer, script, error_handler); + return resolver.VisitScript(script); } } // namespace wabt |