summaryrefslogtreecommitdiff
path: root/src/generate-names.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/generate-names.cc')
-rw-r--r--src/generate-names.cc185
1 files changed, 176 insertions, 9 deletions
diff --git a/src/generate-names.cc b/src/generate-names.cc
index f225442a..618aa25e 100644
--- a/src/generate-names.cc
+++ b/src/generate-names.cc
@@ -21,6 +21,7 @@
#include <string>
#include <vector>
+#include "src/cast.h"
#include "src/expr-visitor.h"
#include "src/ir.h"
@@ -41,20 +42,42 @@ class NameGenerator : public ExprVisitor::DelegateNop {
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.
static 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.
static 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.
static 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.
static 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.
+ static void MaybeUseAndBindName(BindingHash* bindings,
+ const char* name,
+ Index index,
+ std::string* out_str);
+
void GenerateAndBindLocalNames(BindingHash* bindings, const char* prefix);
Result VisitFunc(Index func_index, Func* func);
Result VisitGlobal(Index global_index, Global* global);
@@ -62,6 +85,8 @@ class NameGenerator : public ExprVisitor::DelegateNop {
Result VisitTable(Index table_index, Table* table);
Result VisitMemory(Index memory_index, Memory* memory);
Result VisitExcept(Index except_index, Exception* except);
+ Result VisitImport(Index import_index, Import* import);
+ Result VisitExport(Index export_index, Export* export_);
Module* module_ = nullptr;
ExprVisitor visitor_;
@@ -79,20 +104,24 @@ bool NameGenerator::HasName(const std::string& str) {
// static
void NameGenerator::GenerateName(const char* prefix,
Index index,
+ unsigned disambiguator,
std::string* 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));
- int actual_len = wabt_snprintf(buffer, buffer_len, "%s%u", prefix, index);
- str->assign(buffer, actual_len);
+ *str = prefix;
+ if (index != kInvalidIndex)
+ *str += std::to_string(index);
+ if (disambiguator != 0)
+ *str += '_' + std::to_string(disambiguator);
}
// static
void NameGenerator::MaybeGenerateName(const char* prefix,
Index index,
std::string* str) {
- if (!HasName(*str))
- GenerateName(prefix, index, 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);
+ }
}
// static
@@ -100,8 +129,16 @@ void NameGenerator::GenerateAndBindName(BindingHash* bindings,
const char* prefix,
Index index,
std::string* str) {
- GenerateName(prefix, index, str);
- bindings->emplace(*str, Binding(index));
+ unsigned disambiguator = 0;
+ while (true) {
+ GenerateName(prefix, index, disambiguator, str);
+ if (bindings->find(*str) == bindings->end()) {
+ bindings->emplace(*str, Binding(index));
+ break;
+ }
+
+ disambiguator++;
+ }
}
// static
@@ -113,6 +150,25 @@ void NameGenerator::MaybeGenerateAndBindName(BindingHash* bindings,
GenerateAndBindName(bindings, prefix, index, str);
}
+// static
+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(BindingHash* bindings,
const char* prefix) {
for (size_t i = 0; i < index_to_name_.size(); ++i) {
@@ -189,8 +245,119 @@ Result NameGenerator::VisitExcept(Index except_index, Exception* except) {
return Result::Ok;
}
+Result NameGenerator::VisitImport(Index import_index, Import* import) {
+ BindingHash* bindings = nullptr;
+ std::string* name = nullptr;
+
+ switch (import->kind()) {
+ case ExternalKind::Func:
+ if (auto* func_import = cast<FuncImport>(import)) {
+ bindings = &module_->func_bindings;
+ name = &func_import->func.name;
+ }
+ break;
+
+ case ExternalKind::Table:
+ if (auto* table_import = cast<TableImport>(import)) {
+ bindings = &module_->table_bindings;
+ name = &table_import->table.name;
+ }
+ break;
+
+ case ExternalKind::Memory:
+ if (auto* memory_import = cast<MemoryImport>(import)) {
+ bindings = &module_->memory_bindings;
+ name = &memory_import->memory.name;
+ }
+ break;
+
+ case ExternalKind::Global:
+ if (auto* global_import = cast<GlobalImport>(import)) {
+ bindings = &module_->global_bindings;
+ name = &global_import->global.name;
+ }
+ break;
+
+ case ExternalKind::Except:
+ if (auto* except_import = cast<ExceptionImport>(import)) {
+ bindings = &module_->except_bindings;
+ name = &except_import->except.name;
+ }
+ break;
+ }
+
+ if (bindings && name) {
+ std::string new_name = '$' + import->module_name + '.' + import->field_name;
+ MaybeUseAndBindName(bindings, new_name.c_str(), import_index, name);
+ }
+
+ return Result::Ok;
+}
+
+Result NameGenerator::VisitExport(Index export_index, 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::Except:
+ if (Exception* except = module_->GetExcept(export_->var)) {
+ index = module_->GetExceptIndex(export_->var);
+ bindings = &module_->except_bindings;
+ name = &except->name;
+ }
+ break;
+ }
+
+ if (bindings && name) {
+ std::string new_name = '$' + export_->name;
+ MaybeUseAndBindName(bindings, new_name.c_str(), index, name);
+ }
+
+ 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 (Index i = 0; i < module->imports.size(); ++i)
+ CHECK_RESULT(VisitImport(i, module->imports[i]));
+ for (Index i = 0; i < module->exports.size(); ++i)
+ CHECK_RESULT(VisitExport(i, module->exports[i]));
+
for (Index i = 0; i < module->globals.size(); ++i)
CHECK_RESULT(VisitGlobal(i, module->globals[i]));
for (Index i = 0; i < module->func_types.size(); ++i)