diff options
Diffstat (limited to '')
-rw-r--r-- | third_party/wasm2c/src/apply-names.cc | 581 |
1 files changed, 581 insertions, 0 deletions
diff --git a/third_party/wasm2c/src/apply-names.cc b/third_party/wasm2c/src/apply-names.cc new file mode 100644 index 0000000000..506ab1fe71 --- /dev/null +++ b/third_party/wasm2c/src/apply-names.cc @@ -0,0 +1,581 @@ +/* + * Copyright 2016 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 "wabt/apply-names.h" + +#include <cassert> +#include <cstdio> +#include <string_view> +#include <vector> + +#include "wabt/cast.h" +#include "wabt/expr-visitor.h" +#include "wabt/ir.h" + +namespace wabt { + +namespace { + +class NameApplier : public ExprVisitor::DelegateNop { + public: + NameApplier(); + + Result VisitModule(Module* module); + + // Implementation of ExprVisitor::DelegateNop. + Result BeginBlockExpr(BlockExpr*) override; + Result EndBlockExpr(BlockExpr*) override; + Result OnBrExpr(BrExpr*) override; + Result OnBrIfExpr(BrIfExpr*) override; + Result OnBrTableExpr(BrTableExpr*) override; + Result OnCallExpr(CallExpr*) override; + Result OnRefFuncExpr(RefFuncExpr*) override; + Result OnCallIndirectExpr(CallIndirectExpr*) override; + Result OnReturnCallExpr(ReturnCallExpr*) override; + Result OnReturnCallIndirectExpr(ReturnCallIndirectExpr*) override; + Result OnGlobalGetExpr(GlobalGetExpr*) override; + Result OnGlobalSetExpr(GlobalSetExpr*) override; + Result BeginIfExpr(IfExpr*) override; + Result EndIfExpr(IfExpr*) override; + Result OnLoadExpr(LoadExpr*) override; + Result OnLocalGetExpr(LocalGetExpr*) override; + Result OnLocalSetExpr(LocalSetExpr*) override; + Result OnLocalTeeExpr(LocalTeeExpr*) override; + Result BeginLoopExpr(LoopExpr*) override; + Result EndLoopExpr(LoopExpr*) override; + Result OnMemoryCopyExpr(MemoryCopyExpr*) override; + Result OnDataDropExpr(DataDropExpr*) override; + Result OnMemoryFillExpr(MemoryFillExpr*) override; + Result OnMemoryGrowExpr(MemoryGrowExpr*) override; + Result OnMemoryInitExpr(MemoryInitExpr*) override; + Result OnMemorySizeExpr(MemorySizeExpr*) override; + Result OnElemDropExpr(ElemDropExpr*) override; + Result OnTableCopyExpr(TableCopyExpr*) override; + Result OnTableInitExpr(TableInitExpr*) override; + Result OnTableGetExpr(TableGetExpr*) override; + Result OnTableSetExpr(TableSetExpr*) override; + Result OnTableGrowExpr(TableGrowExpr*) override; + Result OnTableSizeExpr(TableSizeExpr*) override; + Result OnTableFillExpr(TableFillExpr*) override; + Result OnStoreExpr(StoreExpr*) override; + Result BeginTryExpr(TryExpr*) override; + Result EndTryExpr(TryExpr*) override; + Result OnCatchExpr(TryExpr*, Catch*) override; + Result OnDelegateExpr(TryExpr*) override; + Result OnThrowExpr(ThrowExpr*) override; + Result OnRethrowExpr(RethrowExpr*) override; + Result OnSimdLoadLaneExpr(SimdLoadLaneExpr*) override; + Result OnSimdStoreLaneExpr(SimdStoreLaneExpr*) override; + + private: + void PushLabel(const std::string& label); + void PopLabel(); + std::string_view FindLabelByVar(Var* var); + void UseNameForVar(std::string_view name, Var* var); + Result UseNameForFuncTypeVar(Var* var); + Result UseNameForFuncVar(Var* var); + Result UseNameForGlobalVar(Var* var); + Result UseNameForTableVar(Var* var); + Result UseNameForMemoryVar(Var* var); + Result UseNameForTagVar(Var* var); + Result UseNameForDataSegmentVar(Var* var); + Result UseNameForElemSegmentVar(Var* var); + Result UseNameForParamAndLocalVar(Func* func, Var* var); + Result VisitFunc(Index func_index, Func* func); + Result VisitGlobal(Global* global); + Result VisitTag(Tag* tag); + Result VisitExport(Index export_index, Export* export_); + Result VisitElemSegment(Index elem_segment_index, ElemSegment* segment); + Result VisitDataSegment(Index data_segment_index, DataSegment* segment); + Result VisitStart(Var* start_var); + + Module* module_ = nullptr; + Func* current_func_ = nullptr; + ExprVisitor visitor_; + std::vector<std::string> param_and_local_index_to_name_; + std::vector<std::string> labels_; +}; + +NameApplier::NameApplier() : visitor_(this) {} + +void NameApplier::PushLabel(const std::string& label) { + labels_.push_back(label); +} + +void NameApplier::PopLabel() { + labels_.pop_back(); +} + +std::string_view NameApplier::FindLabelByVar(Var* var) { + if (var->is_name()) { + for (int i = labels_.size() - 1; i >= 0; --i) { + const std::string& label = labels_[i]; + if (label == var->name()) { + return label; + } + } + return std::string_view(); + } else { + if (var->index() >= labels_.size()) { + return std::string_view(); + } + return labels_[labels_.size() - 1 - var->index()]; + } +} + +void NameApplier::UseNameForVar(std::string_view name, Var* var) { + if (var->is_name()) { + assert(name == var->name()); + return; + } + + if (!name.empty()) { + var->set_name(name); + } +} + +Result NameApplier::UseNameForFuncTypeVar(Var* var) { + FuncType* func_type = module_->GetFuncType(*var); + if (!func_type) { + return Result::Error; + } + UseNameForVar(func_type->name, var); + return Result::Ok; +} + +Result NameApplier::UseNameForFuncVar(Var* var) { + Func* func = module_->GetFunc(*var); + if (!func) { + return Result::Error; + } + UseNameForVar(func->name, var); + return Result::Ok; +} + +Result NameApplier::UseNameForGlobalVar(Var* var) { + Global* global = module_->GetGlobal(*var); + if (!global) { + return Result::Error; + } + UseNameForVar(global->name, var); + return Result::Ok; +} + +Result NameApplier::UseNameForTableVar(Var* var) { + Table* table = module_->GetTable(*var); + if (!table) { + return Result::Error; + } + UseNameForVar(table->name, var); + return Result::Ok; +} + +Result NameApplier::UseNameForMemoryVar(Var* var) { + Memory* memory = module_->GetMemory(*var); + if (!memory) { + return Result::Error; + } + UseNameForVar(memory->name, var); + return Result::Ok; +} + +Result NameApplier::UseNameForTagVar(Var* var) { + Tag* tag = module_->GetTag(*var); + if (!tag) { + return Result::Error; + } + UseNameForVar(tag->name, var); + return Result::Ok; +} + +Result NameApplier::UseNameForDataSegmentVar(Var* var) { + DataSegment* data_segment = module_->GetDataSegment(*var); + if (!data_segment) { + return Result::Error; + } + UseNameForVar(data_segment->name, var); + return Result::Ok; +} + +Result NameApplier::UseNameForElemSegmentVar(Var* var) { + ElemSegment* elem_segment = module_->GetElemSegment(*var); + if (!elem_segment) { + return Result::Error; + } + UseNameForVar(elem_segment->name, var); + return Result::Ok; +} + +Result NameApplier::UseNameForParamAndLocalVar(Func* func, Var* var) { + Index local_index = func->GetLocalIndex(*var); + if (local_index >= func->GetNumParamsAndLocals()) { + return Result::Error; + } + + std::string name = param_and_local_index_to_name_[local_index]; + if (var->is_name()) { + assert(name == var->name()); + return Result::Ok; + } + + if (!name.empty()) { + var->set_name(name); + } + return Result::Ok; +} + +Result NameApplier::BeginBlockExpr(BlockExpr* expr) { + PushLabel(expr->block.label); + return Result::Ok; +} + +Result NameApplier::EndBlockExpr(BlockExpr* expr) { + PopLabel(); + return Result::Ok; +} + +Result NameApplier::BeginLoopExpr(LoopExpr* expr) { + PushLabel(expr->block.label); + return Result::Ok; +} + +Result NameApplier::EndLoopExpr(LoopExpr* expr) { + PopLabel(); + return Result::Ok; +} + +Result NameApplier::OnDataDropExpr(DataDropExpr* expr) { + CHECK_RESULT(UseNameForDataSegmentVar(&expr->var)); + return Result::Ok; +} + +Result NameApplier::OnMemoryCopyExpr(MemoryCopyExpr* expr) { + CHECK_RESULT(UseNameForMemoryVar(&expr->srcmemidx)); + CHECK_RESULT(UseNameForMemoryVar(&expr->destmemidx)); + return Result::Ok; +} + +Result NameApplier::OnMemoryFillExpr(MemoryFillExpr* expr) { + CHECK_RESULT(UseNameForMemoryVar(&expr->memidx)); + return Result::Ok; +} + +Result NameApplier::OnMemoryGrowExpr(MemoryGrowExpr* expr) { + CHECK_RESULT(UseNameForMemoryVar(&expr->memidx)); + return Result::Ok; +} + +Result NameApplier::OnMemoryInitExpr(MemoryInitExpr* expr) { + CHECK_RESULT(UseNameForDataSegmentVar(&expr->var)); + CHECK_RESULT(UseNameForMemoryVar(&expr->memidx)); + return Result::Ok; +} + +Result NameApplier::OnMemorySizeExpr(MemorySizeExpr* expr) { + CHECK_RESULT(UseNameForMemoryVar(&expr->memidx)); + return Result::Ok; +} + +Result NameApplier::OnElemDropExpr(ElemDropExpr* expr) { + CHECK_RESULT(UseNameForElemSegmentVar(&expr->var)); + return Result::Ok; +} + +Result NameApplier::OnTableCopyExpr(TableCopyExpr* expr) { + CHECK_RESULT(UseNameForTableVar(&expr->dst_table)); + CHECK_RESULT(UseNameForTableVar(&expr->src_table)); + return Result::Ok; +} + +Result NameApplier::OnTableInitExpr(TableInitExpr* expr) { + CHECK_RESULT(UseNameForElemSegmentVar(&expr->segment_index)); + CHECK_RESULT(UseNameForTableVar(&expr->table_index)); + return Result::Ok; +} + +Result NameApplier::OnTableGetExpr(TableGetExpr* expr) { + CHECK_RESULT(UseNameForTableVar(&expr->var)); + return Result::Ok; +} + +Result NameApplier::OnTableSetExpr(TableSetExpr* expr) { + CHECK_RESULT(UseNameForTableVar(&expr->var)); + return Result::Ok; +} + +Result NameApplier::OnTableGrowExpr(TableGrowExpr* expr) { + CHECK_RESULT(UseNameForTableVar(&expr->var)); + return Result::Ok; +} + +Result NameApplier::OnTableSizeExpr(TableSizeExpr* expr) { + CHECK_RESULT(UseNameForTableVar(&expr->var)); + return Result::Ok; +} + +Result NameApplier::OnTableFillExpr(TableFillExpr* expr) { + CHECK_RESULT(UseNameForTableVar(&expr->var)); + return Result::Ok; +} + +Result NameApplier::OnStoreExpr(StoreExpr* expr) { + CHECK_RESULT(UseNameForMemoryVar(&expr->memidx)); + return Result::Ok; +} + +Result NameApplier::OnBrExpr(BrExpr* expr) { + std::string_view label = FindLabelByVar(&expr->var); + UseNameForVar(label, &expr->var); + return Result::Ok; +} + +Result NameApplier::OnBrIfExpr(BrIfExpr* expr) { + std::string_view label = FindLabelByVar(&expr->var); + UseNameForVar(label, &expr->var); + return Result::Ok; +} + +Result NameApplier::OnBrTableExpr(BrTableExpr* expr) { + for (Var& target : expr->targets) { + std::string_view label = FindLabelByVar(&target); + UseNameForVar(label, &target); + } + + std::string_view label = FindLabelByVar(&expr->default_target); + UseNameForVar(label, &expr->default_target); + return Result::Ok; +} + +Result NameApplier::BeginTryExpr(TryExpr* expr) { + PushLabel(expr->block.label); + return Result::Ok; +} + +Result NameApplier::EndTryExpr(TryExpr*) { + PopLabel(); + return Result::Ok; +} + +Result NameApplier::OnCatchExpr(TryExpr*, Catch* expr) { + if (!expr->IsCatchAll()) { + CHECK_RESULT(UseNameForTagVar(&expr->var)); + } + return Result::Ok; +} + +Result NameApplier::OnDelegateExpr(TryExpr* expr) { + PopLabel(); + std::string_view label = FindLabelByVar(&expr->delegate_target); + UseNameForVar(label, &expr->delegate_target); + return Result::Ok; +} + +Result NameApplier::OnThrowExpr(ThrowExpr* expr) { + CHECK_RESULT(UseNameForTagVar(&expr->var)); + return Result::Ok; +} + +Result NameApplier::OnRethrowExpr(RethrowExpr* expr) { + std::string_view label = FindLabelByVar(&expr->var); + UseNameForVar(label, &expr->var); + return Result::Ok; +} + +Result NameApplier::OnCallExpr(CallExpr* expr) { + CHECK_RESULT(UseNameForFuncVar(&expr->var)); + return Result::Ok; +} + +Result NameApplier::OnRefFuncExpr(RefFuncExpr* expr) { + CHECK_RESULT(UseNameForFuncVar(&expr->var)); + return Result::Ok; +} + +Result NameApplier::OnCallIndirectExpr(CallIndirectExpr* expr) { + if (expr->decl.has_func_type) { + CHECK_RESULT(UseNameForFuncTypeVar(&expr->decl.type_var)); + } + CHECK_RESULT(UseNameForTableVar(&expr->table)); + return Result::Ok; +} + +Result NameApplier::OnReturnCallExpr(ReturnCallExpr* expr) { + CHECK_RESULT(UseNameForFuncVar(&expr->var)); + return Result::Ok; +} + +Result NameApplier::OnReturnCallIndirectExpr(ReturnCallIndirectExpr* expr) { + if (expr->decl.has_func_type) { + CHECK_RESULT(UseNameForFuncTypeVar(&expr->decl.type_var)); + } + CHECK_RESULT(UseNameForTableVar(&expr->table)); + return Result::Ok; +} + +Result NameApplier::OnGlobalGetExpr(GlobalGetExpr* expr) { + CHECK_RESULT(UseNameForGlobalVar(&expr->var)); + return Result::Ok; +} + +Result NameApplier::OnLocalGetExpr(LocalGetExpr* expr) { + CHECK_RESULT(UseNameForParamAndLocalVar(current_func_, &expr->var)); + return Result::Ok; +} + +Result NameApplier::BeginIfExpr(IfExpr* expr) { + PushLabel(expr->true_.label); + return Result::Ok; +} + +Result NameApplier::EndIfExpr(IfExpr* expr) { + PopLabel(); + return Result::Ok; +} + +Result NameApplier::OnLoadExpr(LoadExpr* expr) { + CHECK_RESULT(UseNameForMemoryVar(&expr->memidx)); + return Result::Ok; +} + +Result NameApplier::OnGlobalSetExpr(GlobalSetExpr* expr) { + CHECK_RESULT(UseNameForGlobalVar(&expr->var)); + return Result::Ok; +} + +Result NameApplier::OnLocalSetExpr(LocalSetExpr* expr) { + CHECK_RESULT(UseNameForParamAndLocalVar(current_func_, &expr->var)); + return Result::Ok; +} + +Result NameApplier::OnLocalTeeExpr(LocalTeeExpr* expr) { + CHECK_RESULT(UseNameForParamAndLocalVar(current_func_, &expr->var)); + return Result::Ok; +} + +Result NameApplier::OnSimdLoadLaneExpr(SimdLoadLaneExpr* expr) { + CHECK_RESULT(UseNameForMemoryVar(&expr->memidx)); + return Result::Ok; +} + +Result NameApplier::OnSimdStoreLaneExpr(SimdStoreLaneExpr* expr) { + CHECK_RESULT(UseNameForMemoryVar(&expr->memidx)); + return Result::Ok; +} + +Result NameApplier::VisitFunc(Index func_index, Func* func) { + current_func_ = func; + if (func->decl.has_func_type) { + CHECK_RESULT(UseNameForFuncTypeVar(&func->decl.type_var)); + } + + MakeTypeBindingReverseMapping(func->GetNumParamsAndLocals(), func->bindings, + ¶m_and_local_index_to_name_); + + CHECK_RESULT(visitor_.VisitFunc(func)); + current_func_ = nullptr; + return Result::Ok; +} + +Result NameApplier::VisitGlobal(Global* global) { + CHECK_RESULT(visitor_.VisitExprList(global->init_expr)); + return Result::Ok; +} + +Result NameApplier::VisitTag(Tag* tag) { + if (tag->decl.has_func_type) { + CHECK_RESULT(UseNameForFuncTypeVar(&tag->decl.type_var)); + } + return Result::Ok; +} + +Result NameApplier::VisitExport(Index export_index, Export* export_) { + switch (export_->kind) { + case ExternalKind::Func: + UseNameForFuncVar(&export_->var); + break; + + case ExternalKind::Table: + UseNameForTableVar(&export_->var); + break; + + case ExternalKind::Memory: + UseNameForMemoryVar(&export_->var); + break; + + case ExternalKind::Global: + UseNameForGlobalVar(&export_->var); + break; + + case ExternalKind::Tag: + UseNameForTagVar(&export_->var); + break; + } + return Result::Ok; +} + +Result NameApplier::VisitElemSegment(Index elem_segment_index, + ElemSegment* segment) { + CHECK_RESULT(UseNameForTableVar(&segment->table_var)); + CHECK_RESULT(visitor_.VisitExprList(segment->offset)); + for (ExprList& elem_expr : segment->elem_exprs) { + Expr* expr = &elem_expr.front(); + if (expr->type() == ExprType::RefFunc) { + CHECK_RESULT(UseNameForFuncVar(&cast<RefFuncExpr>(expr)->var)); + } + } + return Result::Ok; +} + +Result NameApplier::VisitDataSegment(Index data_segment_index, + DataSegment* segment) { + CHECK_RESULT(UseNameForMemoryVar(&segment->memory_var)); + CHECK_RESULT(visitor_.VisitExprList(segment->offset)); + return Result::Ok; +} + +Result NameApplier::VisitStart(Var* start_var) { + CHECK_RESULT(UseNameForFuncVar(start_var)); + return Result::Ok; +} + +Result NameApplier::VisitModule(Module* module) { + module_ = module; + for (size_t i = 0; i < module->funcs.size(); ++i) + CHECK_RESULT(VisitFunc(i, module->funcs[i])); + for (size_t i = 0; i < module->globals.size(); ++i) + CHECK_RESULT(VisitGlobal(module->globals[i])); + for (size_t i = 0; i < module->tags.size(); ++i) + CHECK_RESULT(VisitTag(module->tags[i])); + for (size_t i = 0; i < module->exports.size(); ++i) + CHECK_RESULT(VisitExport(i, module->exports[i])); + for (size_t i = 0; i < module->elem_segments.size(); ++i) + CHECK_RESULT(VisitElemSegment(i, module->elem_segments[i])); + for (size_t i = 0; i < module->data_segments.size(); ++i) + CHECK_RESULT(VisitDataSegment(i, module->data_segments[i])); + for (size_t i = 0; i < module->starts.size(); ++i) + CHECK_RESULT(VisitStart(module->starts[i])); + module_ = nullptr; + return Result::Ok; +} + +} // end anonymous namespace + +Result ApplyNames(Module* module) { + NameApplier applier; + return applier.VisitModule(module); +} + +} // namespace wabt |