class NameGenerator : public ExprVisitor::DelegateNop { public:
NameGenerator(NameOpts opts);
Result VisitModule(Module* module);
// Implementation of ExprVisitor::DelegateNop.
Result BeginBlockExpr(BlockExpr* expr) override;
Result BeginTryExpr(TryExpr* expr) override;
Result BeginLoopExpr(LoopExpr* expr) override;
Result BeginIfExpr(IfExpr* expr) override;
// 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(constchar* prefix,
Index index, unsigned disambiguator,
std::string* out_str);
// Like GenerateName, but only generates a name if |out_str| is empty. void MaybeGenerateName(constchar* 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, constchar* prefix,
Index index,
std::string* out_str);
// Like GenerateAndBindName, but only generates a name if |out_str| is empty. void MaybeGenerateAndBindName(BindingHash* bindings, constchar* 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, constchar* 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;
void NameGenerator::GenerateName(constchar* 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(constchar* 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, constchar* 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, constchar* prefix,
Index index,
std::string* str) { if (!HasName(*str)) {
GenerateAndBindName(bindings, prefix, index, str);
}
}
void NameGenerator::MaybeUseAndBindName(BindingHash* bindings, constchar* 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;
}
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;
}
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_));
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.