diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:22:09 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:22:09 +0000 |
commit | 43a97878ce14b72f0981164f87f2e35e14151312 (patch) | |
tree | 620249daf56c0258faa40cbdcf9cfba06de2a846 /third_party/wasm2c/src/generate-names.cc | |
parent | Initial commit. (diff) | |
download | firefox-43a97878ce14b72f0981164f87f2e35e14151312.tar.xz firefox-43a97878ce14b72f0981164f87f2e35e14151312.zip |
Adding upstream version 110.0.1.upstream/110.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/wasm2c/src/generate-names.cc')
-rw-r--r-- | third_party/wasm2c/src/generate-names.cc | 430 |
1 files changed, 430 insertions, 0 deletions
diff --git a/third_party/wasm2c/src/generate-names.cc b/third_party/wasm2c/src/generate-names.cc new file mode 100644 index 0000000000..5f99f0e84c --- /dev/null +++ b/third_party/wasm2c/src/generate-names.cc @@ -0,0 +1,430 @@ +/* + * 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 "src/generate-names.h" + +#include <cassert> +#include <cstdio> +#include <string> +#include <vector> + +#include "src/cast.h" +#include "src/expr-visitor.h" +#include "src/ir.h" + +namespace wabt { + +namespace { + +class NameGenerator : public ExprVisitor::DelegateNop { + public: + NameGenerator(NameOpts opts); + + Result VisitModule(Module* module); + + // Implementation of ExprVisitor::DelegateNop. + Result BeginBlockExpr(BlockExpr* expr) override; + Result BeginLoopExpr(LoopExpr* expr) override; + Result BeginIfExpr(IfExpr* expr) override; + + private: + static bool HasName(const std::string& str); + + // Generate a name with the given prefix, followed by the index and + // optionally a disambiguating number. If index == kInvalidIndex, the index + // is not appended. + void GenerateName(const char* prefix, + Index index, + unsigned disambiguator, + std::string* out_str); + + // Like GenerateName, but only generates a name if |out_str| is empty. + void MaybeGenerateName(const char* prefix, + Index index, + std::string* out_str); + + // Generate a name via GenerateName and bind it to the given binding hash. If + // the name already exists, the name will be disambiguated until it can be + // added. + void GenerateAndBindName(BindingHash* bindings, + const char* prefix, + Index index, + std::string* out_str); + + // Like GenerateAndBindName, but only generates a name if |out_str| is empty. + void MaybeGenerateAndBindName(BindingHash* bindings, + const char* prefix, + Index index, + std::string* out_str); + + // Like MaybeGenerateAndBindName but uses the name directly, without + // appending the index. If the name already exists, a disambiguating suffix + // is added. + void MaybeUseAndBindName(BindingHash* bindings, + const char* name, + Index index, + std::string* out_str); + + void GenerateAndBindLocalNames(Func* func); + + template <typename T> + Result VisitAll(const std::vector<T*>& items, + Result (NameGenerator::*func)(Index, T*)); + + Result VisitFunc(Index func_index, Func* func); + Result VisitGlobal(Index global_index, Global* global); + Result VisitType(Index func_type_index, TypeEntry* type); + Result VisitTable(Index table_index, Table* table); + Result VisitMemory(Index memory_index, Memory* memory); + Result VisitTag(Index tag_index, Tag* tag); + Result VisitDataSegment(Index data_segment_index, DataSegment* data_segment); + Result VisitElemSegment(Index elem_segment_index, ElemSegment* elem_segment); + Result VisitImport(Import* import); + Result VisitExport(Export* export_); + + Module* module_ = nullptr; + ExprVisitor visitor_; + Index label_count_ = 0; + + Index num_func_imports_ = 0; + Index num_table_imports_ = 0; + Index num_memory_imports_ = 0; + Index num_global_imports_ = 0; + Index num_tag_imports_ = 0; + + NameOpts opts_; +}; + +NameGenerator::NameGenerator(NameOpts opts) + : visitor_(this), opts_(opts) {} + +// static +bool NameGenerator::HasName(const std::string& str) { + return !str.empty(); +} + +void NameGenerator::GenerateName(const char* prefix, + Index index, + unsigned disambiguator, + std::string* str) { + *str = "$"; + *str += prefix; + if (index != kInvalidIndex) { + if (opts_ & NameOpts::AlphaNames) { + // For params and locals, do not use a prefix char. + if (!strcmp(prefix, "p") || !strcmp(prefix, "l")) { + str->pop_back(); + } else { + *str += '_'; + } + *str += IndexToAlphaName(index); + } else { + *str += std::to_string(index); + } + } + if (disambiguator != 0) { + *str += '_' + std::to_string(disambiguator); + } +} + +void NameGenerator::MaybeGenerateName(const char* prefix, + Index index, + std::string* str) { + if (!HasName(*str)) { + // There's no bindings hash, so the name can't be a duplicate. Therefore it + // doesn't need a disambiguating number. + GenerateName(prefix, index, 0, str); + } +} + +void NameGenerator::GenerateAndBindName(BindingHash* bindings, + const char* prefix, + Index index, + std::string* str) { + unsigned disambiguator = 0; + while (true) { + GenerateName(prefix, index, disambiguator, str); + if (bindings->find(*str) == bindings->end()) { + bindings->emplace(*str, Binding(index)); + break; + } + + disambiguator++; + } +} + +void NameGenerator::MaybeGenerateAndBindName(BindingHash* bindings, + const char* prefix, + Index index, + std::string* str) { + if (!HasName(*str)) { + GenerateAndBindName(bindings, prefix, index, str); + } +} + +void NameGenerator::MaybeUseAndBindName(BindingHash* bindings, + const char* name, + Index index, + std::string* str) { + if (!HasName(*str)) { + unsigned disambiguator = 0; + while (true) { + GenerateName(name, kInvalidIndex, disambiguator, str); + if (bindings->find(*str) == bindings->end()) { + bindings->emplace(*str, Binding(index)); + break; + } + + disambiguator++; + } + } +} + +void NameGenerator::GenerateAndBindLocalNames(Func* func) { + std::vector<std::string> index_to_name; + MakeTypeBindingReverseMapping(func->GetNumParamsAndLocals(), func->bindings, + &index_to_name); + 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; + } + + const char* prefix = i < func->GetNumParams() ? "p" : "l"; + std::string new_name; + GenerateAndBindName(&func->bindings, prefix, i, &new_name); + index_to_name[i] = new_name; + } +} + +Result NameGenerator::BeginBlockExpr(BlockExpr* expr) { + MaybeGenerateName("B", label_count_++, &expr->block.label); + return Result::Ok; +} + +Result NameGenerator::BeginLoopExpr(LoopExpr* expr) { + MaybeGenerateName("L", label_count_++, &expr->block.label); + return Result::Ok; +} + +Result NameGenerator::BeginIfExpr(IfExpr* expr) { + MaybeGenerateName("I", label_count_++, &expr->true_.label); + return Result::Ok; +} + +Result NameGenerator::VisitFunc(Index func_index, Func* func) { + MaybeGenerateAndBindName(&module_->func_bindings, "f", func_index, + &func->name); + GenerateAndBindLocalNames(func); + + label_count_ = 0; + CHECK_RESULT(visitor_.VisitFunc(func)); + return Result::Ok; +} + +Result NameGenerator::VisitGlobal(Index global_index, Global* global) { + MaybeGenerateAndBindName(&module_->global_bindings, "g", global_index, + &global->name); + return Result::Ok; +} + +Result NameGenerator::VisitType(Index type_index, TypeEntry* type) { + MaybeGenerateAndBindName(&module_->type_bindings, "t", type_index, + &type->name); + return Result::Ok; +} + +Result NameGenerator::VisitTable(Index table_index, Table* table) { + MaybeGenerateAndBindName(&module_->table_bindings, "T", table_index, + &table->name); + return Result::Ok; +} + +Result NameGenerator::VisitMemory(Index memory_index, Memory* memory) { + MaybeGenerateAndBindName(&module_->memory_bindings, "M", memory_index, + &memory->name); + return Result::Ok; +} + +Result NameGenerator::VisitTag(Index tag_index, Tag* tag) { + MaybeGenerateAndBindName(&module_->tag_bindings, "e", tag_index, &tag->name); + return Result::Ok; +} + +Result NameGenerator::VisitDataSegment(Index data_segment_index, + DataSegment* data_segment) { + MaybeGenerateAndBindName(&module_->data_segment_bindings, "d", + data_segment_index, &data_segment->name); + return Result::Ok; +} + +Result NameGenerator::VisitElemSegment(Index elem_segment_index, + ElemSegment* elem_segment) { + MaybeGenerateAndBindName(&module_->elem_segment_bindings, "e", + elem_segment_index, &elem_segment->name); + return Result::Ok; +} + +Result NameGenerator::VisitImport(Import* import) { + BindingHash* bindings = nullptr; + std::string* name = nullptr; + Index index = kInvalidIndex; + + switch (import->kind()) { + case ExternalKind::Func: + if (auto* func_import = cast<FuncImport>(import)) { + bindings = &module_->func_bindings; + name = &func_import->func.name; + index = num_func_imports_++; + } + break; + + case ExternalKind::Table: + if (auto* table_import = cast<TableImport>(import)) { + bindings = &module_->table_bindings; + name = &table_import->table.name; + index = num_table_imports_++; + } + break; + + case ExternalKind::Memory: + if (auto* memory_import = cast<MemoryImport>(import)) { + bindings = &module_->memory_bindings; + name = &memory_import->memory.name; + index = num_memory_imports_++; + } + break; + + case ExternalKind::Global: + if (auto* global_import = cast<GlobalImport>(import)) { + bindings = &module_->global_bindings; + name = &global_import->global.name; + index = num_global_imports_++; + } + break; + + case ExternalKind::Tag: + if (auto* tag_import = cast<TagImport>(import)) { + bindings = &module_->tag_bindings; + name = &tag_import->tag.name; + index = num_tag_imports_++; + } + break; + } + + if (bindings && name) { + assert(index != kInvalidIndex); + std::string new_name = import->module_name + '.' + import->field_name; + MaybeUseAndBindName(bindings, new_name.c_str(), index, name); + } + + return Result::Ok; +} + +Result NameGenerator::VisitExport(Export* export_) { + BindingHash* bindings = nullptr; + std::string* name = nullptr; + Index index = kInvalidIndex; + + switch (export_->kind) { + case ExternalKind::Func: + if (Func* func = module_->GetFunc(export_->var)) { + index = module_->GetFuncIndex(export_->var); + bindings = &module_->func_bindings; + name = &func->name; + } + break; + + case ExternalKind::Table: + if (Table* table = module_->GetTable(export_->var)) { + index = module_->GetTableIndex(export_->var); + bindings = &module_->table_bindings; + name = &table->name; + } + break; + + case ExternalKind::Memory: + if (Memory* memory = module_->GetMemory(export_->var)) { + index = module_->GetMemoryIndex(export_->var); + bindings = &module_->memory_bindings; + name = &memory->name; + } + break; + + case ExternalKind::Global: + if (Global* global = module_->GetGlobal(export_->var)) { + index = module_->GetGlobalIndex(export_->var); + bindings = &module_->global_bindings; + name = &global->name; + } + break; + + case ExternalKind::Tag: + if (Tag* tag = module_->GetTag(export_->var)) { + index = module_->GetTagIndex(export_->var); + bindings = &module_->tag_bindings; + name = &tag->name; + } + break; + } + + if (bindings && name) { + MaybeUseAndBindName(bindings, export_->name.c_str(), index, name); + } + + return Result::Ok; +} + +template <typename T> +Result NameGenerator::VisitAll(const std::vector<T*>& items, + Result (NameGenerator::*func)(Index, T*)) { + for (Index i = 0; i < items.size(); ++i) { + CHECK_RESULT((this->*func)(i, items[i])); + } + return Result::Ok; +} + +Result NameGenerator::VisitModule(Module* module) { + module_ = module; + // Visit imports and exports first to give better names, derived from the + // import/export name. + for (auto* import : module->imports) { + CHECK_RESULT(VisitImport(import)); + } + for (auto* export_ : module->exports) { + CHECK_RESULT(VisitExport(export_)); + } + + VisitAll(module->globals, &NameGenerator::VisitGlobal); + VisitAll(module->types, &NameGenerator::VisitType); + VisitAll(module->funcs, &NameGenerator::VisitFunc); + VisitAll(module->tables, &NameGenerator::VisitTable); + VisitAll(module->memories, &NameGenerator::VisitMemory); + VisitAll(module->tags, &NameGenerator::VisitTag); + VisitAll(module->data_segments, &NameGenerator::VisitDataSegment); + VisitAll(module->elem_segments, &NameGenerator::VisitElemSegment); + module_ = nullptr; + return Result::Ok; +} + +} // end anonymous namespace + +Result GenerateNames(Module* module, NameOpts opts) { + NameGenerator generator(opts); + return generator.VisitModule(module); +} + +} // namespace wabt |