class NameResolver : public ExprVisitor::DelegateNop { public:
NameResolver(Script* script, Errors* errors);
Result VisitModule(Module* module);
Result VisitScript(Script* script);
// 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 OnCallIndirectExpr(CallIndirectExpr*) override;
Result OnCatchExpr(TryExpr*, Catch*) override;
Result OnDelegateExpr(TryExpr*) 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 OnRefFuncExpr(RefFuncExpr*) override;
Result OnStoreExpr(StoreExpr*) override;
Result BeginTryExpr(TryExpr*) override;
Result EndTryExpr(TryExpr*) override;
Result OnThrowExpr(ThrowExpr*) override;
Result OnRethrowExpr(RethrowExpr*) override;
Result OnSimdLoadLaneExpr(SimdLoadLaneExpr*) override;
Result OnSimdStoreLaneExpr(SimdStoreLaneExpr*) override;
void NameResolver::CheckDuplicateBindings(const BindingHash* bindings, constchar* desc) {
bindings->FindDuplicates([this, desc](const BindingHash::value_type& a, const BindingHash::value_type& b) {
PrintDuplicateBindingsError(a, b, desc);
});
}
void NameResolver::PrintDuplicateBindingsError(const BindingHash::value_type& a, const BindingHash::value_type& b, constchar* desc) { // 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;
PrintError(&loc, "redefinition of %s \"%s\"", desc, a.first.c_str());
}
void NameResolver::ResolveLabelVar(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()) {
var->set_index(labels_.size() - i - 1); return;
}
}
PrintError(&var->loc, "undefined label variable \"%s\"",
var->name().c_str());
}
}
void NameResolver::ResolveVar(const BindingHash* bindings,
Var* var, constchar* desc) { if (var->is_name()) {
Index index = bindings->FindIndex(*var); if (index == kInvalidIndex) {
PrintError(&var->loc, "undefined %s variable \"%s\"", desc,
var->name().c_str()); return;
}
var->set_index(index);
}
}
void NameResolver::ResolveFuncVar(Var* var) {
ResolveVar(¤t_module_->func_bindings, var, "function");
}
void NameResolver::ResolveGlobalVar(Var* var) {
ResolveVar(¤t_module_->global_bindings, var, "global");
}
void NameResolver::ResolveFuncTypeVar(Var* var) {
ResolveVar(¤t_module_->type_bindings, var, "type");
}
void NameResolver::ResolveTableVar(Var* var) {
ResolveVar(¤t_module_->table_bindings, var, "table");
}
void NameResolver::ResolveMemoryVar(Var* var) {
ResolveVar(¤t_module_->memory_bindings, var, "memory");
}
void NameResolver::ResolveTagVar(Var* var) {
ResolveVar(¤t_module_->tag_bindings, var, "tag");
}
void NameResolver::ResolveDataSegmentVar(Var* var) {
ResolveVar(¤t_module_->data_segment_bindings, var, "data segment");
}
void NameResolver::ResolveElemSegmentVar(Var* var) {
ResolveVar(¤t_module_->elem_segment_bindings, var, "elem segment");
}
void NameResolver::ResolveLocalVar(Var* var) { if (var->is_name()) { if (!current_func_) { return;
}
Index index = current_func_->GetLocalIndex(*var); if (index == kInvalidIndex) {
PrintError(&var->loc, "undefined local variable \"%s\"",
var->name().c_str()); return;
}
var->set_index(index);
}
}
void NameResolver::ResolveBlockDeclarationVar(BlockDeclaration* decl) { if (decl->has_func_type) {
ResolveFuncTypeVar(&decl->type_var);
}
}
Result NameResolver::BeginBlockExpr(BlockExpr* expr) {
PushLabel(expr->block.label);
ResolveBlockDeclarationVar(&expr->block.decl); return Result::Ok;
}
Result NameResolver::EndBlockExpr(BlockExpr* expr) {
PopLabel(); return Result::Ok;
}
Result NameResolver::BeginLoopExpr(LoopExpr* expr) {
PushLabel(expr->block.label);
ResolveBlockDeclarationVar(&expr->block.decl); return Result::Ok;
}
Result NameResolver::EndLoopExpr(LoopExpr* expr) {
PopLabel(); return Result::Ok;
}
Result NameResolver::OnBrExpr(BrExpr* expr) {
ResolveLabelVar(&expr->var); return Result::Ok;
}
Result NameResolver::OnBrIfExpr(BrIfExpr* expr) {
ResolveLabelVar(&expr->var); return Result::Ok;
}
Result NameResolver::OnBrTableExpr(BrTableExpr* expr) { for (Var& target : expr->targets)
ResolveLabelVar(&target);
ResolveLabelVar(&expr->default_target); return Result::Ok;
}
Result NameResolver::OnCallExpr(CallExpr* expr) {
ResolveFuncVar(&expr->var); return Result::Ok;
}
Result NameResolver::OnCallIndirectExpr(CallIndirectExpr* expr) { if (expr->decl.has_func_type) {
ResolveFuncTypeVar(&expr->decl.type_var);
}
ResolveTableVar(&expr->table); return Result::Ok;
}
Result NameResolver::OnReturnCallExpr(ReturnCallExpr* expr) {
ResolveFuncVar(&expr->var); return Result::Ok;
}
Result NameResolver::OnReturnCallIndirectExpr(ReturnCallIndirectExpr* expr) { if (expr->decl.has_func_type) {
ResolveFuncTypeVar(&expr->decl.type_var);
}
ResolveTableVar(&expr->table); return Result::Ok;
}
Result NameResolver::OnGlobalGetExpr(GlobalGetExpr* expr) {
ResolveGlobalVar(&expr->var); return Result::Ok;
}
Result NameResolver::OnGlobalSetExpr(GlobalSetExpr* expr) {
ResolveGlobalVar(&expr->var); return Result::Ok;
}
Result NameResolver::BeginIfExpr(IfExpr* expr) {
PushLabel(expr->true_.label);
ResolveBlockDeclarationVar(&expr->true_.decl); return Result::Ok;
}
Result NameResolver::EndIfExpr(IfExpr* expr) {
PopLabel(); return Result::Ok;
}
Result NameResolver::OnLoadExpr(LoadExpr* expr) {
ResolveMemoryVar(&expr->memidx); return Result::Ok;
}
Result NameResolver::OnLocalGetExpr(LocalGetExpr* expr) {
ResolveLocalVar(&expr->var); return Result::Ok;
}
Result NameResolver::OnLocalSetExpr(LocalSetExpr* expr) {
ResolveLocalVar(&expr->var); return Result::Ok;
}
Result NameResolver::OnLocalTeeExpr(LocalTeeExpr* expr) {
ResolveLocalVar(&expr->var); return Result::Ok;
}
Result NameResolver::OnMemoryCopyExpr(MemoryCopyExpr* expr) {
ResolveMemoryVar(&expr->destmemidx);
ResolveMemoryVar(&expr->srcmemidx); return Result::Ok;
}
Result NameResolver::OnDataDropExpr(DataDropExpr* expr) {
ResolveDataSegmentVar(&expr->var); return Result::Ok;
}
Result NameResolver::OnMemoryFillExpr(MemoryFillExpr* expr) {
ResolveMemoryVar(&expr->memidx); return Result::Ok;
}
Result NameResolver::OnMemoryGrowExpr(MemoryGrowExpr* expr) {
ResolveMemoryVar(&expr->memidx); return Result::Ok;
}
Result NameResolver::OnMemoryInitExpr(MemoryInitExpr* expr) {
ResolveDataSegmentVar(&expr->var);
ResolveMemoryVar(&expr->memidx); return Result::Ok;
}
Result NameResolver::OnMemorySizeExpr(MemorySizeExpr* expr) {
ResolveMemoryVar(&expr->memidx); return Result::Ok;
}
Result NameResolver::OnElemDropExpr(ElemDropExpr* expr) {
ResolveElemSegmentVar(&expr->var); return Result::Ok;
}
Result NameResolver::OnTableCopyExpr(TableCopyExpr* expr) {
ResolveTableVar(&expr->dst_table);
ResolveTableVar(&expr->src_table); return Result::Ok;
}
Result NameResolver::OnTableInitExpr(TableInitExpr* expr) {
ResolveElemSegmentVar(&expr->segment_index);
ResolveTableVar(&expr->table_index); return Result::Ok;
}
Result NameResolver::OnTableGetExpr(TableGetExpr* expr) {
ResolveTableVar(&expr->var); return Result::Ok;
}
Result NameResolver::OnTableSetExpr(TableSetExpr* expr) {
ResolveTableVar(&expr->var); return Result::Ok;
}
Result NameResolver::OnTableGrowExpr(TableGrowExpr* expr) {
ResolveTableVar(&expr->var); return Result::Ok;
}
Result NameResolver::OnTableSizeExpr(TableSizeExpr* expr) {
ResolveTableVar(&expr->var); return Result::Ok;
}
Result NameResolver::OnTableFillExpr(TableFillExpr* expr) {
ResolveTableVar(&expr->var); return Result::Ok;
}
Result NameResolver::OnRefFuncExpr(RefFuncExpr* expr) {
ResolveFuncVar(&expr->var); return Result::Ok;
}
Result NameResolver::OnStoreExpr(StoreExpr* expr) {
ResolveMemoryVar(&expr->memidx); return Result::Ok;
}
Result NameResolver::BeginTryExpr(TryExpr* expr) {
PushLabel(expr->block.label);
ResolveBlockDeclarationVar(&expr->block.decl); return Result::Ok;
}
Result NameResolver::EndTryExpr(TryExpr*) {
PopLabel(); return Result::Ok;
}
Result NameResolver::OnCatchExpr(TryExpr*, Catch* catch_) { if (!catch_->IsCatchAll()) {
ResolveTagVar(&catch_->var);
} return Result::Ok;
}
Result NameResolver::OnDelegateExpr(TryExpr* expr) { // Pop the label here as a try-delegate has no `end` instruction.
PopLabel();
// We resolve *after* popping the label in order to ensure that the // delegate label starts counting after the current try-delegate.
ResolveLabelVar(&expr->delegate_target);
return Result::Ok;
}
Result NameResolver::OnThrowExpr(ThrowExpr* expr) {
ResolveTagVar(&expr->var); return Result::Ok;
}
Result NameResolver::OnRethrowExpr(RethrowExpr* expr) { // Note: the variable refers to corresponding (enclosing) catch, using the try // block label for context.
ResolveLabelVar(&expr->var); return Result::Ok;
}
Result NameResolver::OnSimdLoadLaneExpr(SimdLoadLaneExpr* expr) {
ResolveMemoryVar(&expr->memidx); return Result::Ok;
}
Result NameResolver::OnSimdStoreLaneExpr(SimdStoreLaneExpr* expr) {
ResolveMemoryVar(&expr->memidx); return Result::Ok;
}
case CommandType::ScriptModule:
VisitModule(&cast<ScriptModuleCommand>(command)->module); break;
case CommandType::Action: case CommandType::AssertReturn: case CommandType::AssertTrap: case CommandType::AssertExhaustion: case CommandType::AssertException: case CommandType::Register: /* Don't resolve a module_var, since it doesn't really behave like other
* vars. You can't reference a module by index. */ break;
case CommandType::AssertMalformed: /* Malformed modules should not be text; the whole point of this
* assertion is to test for malformed binary modules. */ break;
case CommandType::AssertInvalid: { auto* assert_invalid_command = cast<AssertInvalidCommand>(command); /* The module may be invalid because the names cannot be resolved; we *don'twanttoprinterrorsorfailifthat'sthecase,butwestill
* should try to resolve names when possible. */
Errors errors;
NameResolver new_resolver(script_, &errors);
new_resolver.VisitScriptModule(assert_invalid_command->module.get()); break;
}
case CommandType::AssertUnlinkable:
VisitScriptModule(cast<AssertUnlinkableCommand>(command)->module.get()); break;
case CommandType::AssertUninstantiable:
VisitScriptModule(
cast<AssertUninstantiableCommand>(command)->module.get()); break;
}
}
Result NameResolver::VisitScript(Script* script) { for (const std::unique_ptr<Command>& command : script->commands)
VisitCommand(command.get()); return result_;
}
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.