diff options
-rw-r--r-- | src/apply-names.cc | 31 | ||||
-rw-r--r-- | src/binary-reader-ir.cc | 16 | ||||
-rw-r--r-- | src/binary-writer.cc | 17 | ||||
-rw-r--r-- | src/c-writer.cc | 32 | ||||
-rw-r--r-- | src/generate-names.cc | 28 | ||||
-rw-r--r-- | src/ir.cc | 14 | ||||
-rw-r--r-- | src/ir.h | 3 | ||||
-rw-r--r-- | src/resolve-names.cc | 27 | ||||
-rw-r--r-- | src/wast-parser.cc | 16 | ||||
-rw-r--r-- | src/wast-parser.h | 5 | ||||
-rw-r--r-- | src/wat-writer.cc | 22 | ||||
-rw-r--r-- | test/parse/func/bad-local-redefinition.txt | 8 | ||||
-rw-r--r-- | test/roundtrip/generate-local-names.txt | 10 | ||||
-rw-r--r-- | test/roundtrip/generate-some-names.txt | 4 |
14 files changed, 103 insertions, 130 deletions
diff --git a/src/apply-names.cc b/src/apply-names.cc index 4a3b0042..e03b2377 100644 --- a/src/apply-names.cc +++ b/src/apply-names.cc @@ -86,9 +86,7 @@ class NameApplier : public ExprVisitor::DelegateNop { Module* module_ = nullptr; Func* current_func_ = nullptr; ExprVisitor visitor_; - /* mapping from param index to its name, if any, for the current func */ - std::vector<std::string> param_index_to_name_; - std::vector<std::string> local_index_to_name_; + std::vector<std::string> param_and_local_index_to_name_; std::vector<std::string> labels_; }; @@ -208,26 +206,14 @@ Result NameApplier::UseNameForParamAndLocalVar(Func* func, Var* var) { return Result::Error; } - Index num_params = func->GetNumParams(); - std::string* name; - if (local_index < num_params) { - /* param */ - assert(local_index < param_index_to_name_.size()); - name = ¶m_index_to_name_[local_index]; - } else { - /* local */ - local_index -= num_params; - assert(local_index < local_index_to_name_.size()); - name = &local_index_to_name_[local_index]; - } - + std::string name = param_and_local_index_to_name_[local_index]; if (var->is_name()) { - assert(*name == var->name()); + assert(name == var->name()); return Result::Ok; } - if (!name->empty()) { - var->set_name(*name); + if (!name.empty()) { + var->set_name(name); } return Result::Ok; } @@ -386,11 +372,8 @@ Result NameApplier::VisitFunc(Index func_index, Func* func) { CHECK_RESULT(UseNameForFuncTypeVar(&func->decl.type_var)); } - MakeTypeBindingReverseMapping(func->decl.sig.param_types.size(), - func->param_bindings, ¶m_index_to_name_); - - MakeTypeBindingReverseMapping(func->local_types.size(), func->local_bindings, - &local_index_to_name_); + MakeTypeBindingReverseMapping(func->GetNumParamsAndLocals(), func->bindings, + ¶m_and_local_index_to_name_); CHECK_RESULT(visitor_.VisitFunc(func)); current_func_ = nullptr; diff --git a/src/binary-reader-ir.cc b/src/binary-reader-ir.cc index 7c4b9699..24828f2e 100644 --- a/src/binary-reader-ir.cc +++ b/src/binary-reader-ir.cc @@ -1144,20 +1144,8 @@ Result BinaryReaderIR::OnLocalName(Index func_index, } Func* func = module_->funcs[func_index]; - Index num_params = func->GetNumParams(); - BindingHash* bindings; - Index index; - if (local_index < num_params) { - // param name - bindings = &func->param_bindings; - index = local_index; - } else { - // local name - bindings = &func->local_bindings; - index = local_index - num_params; - } - bindings->emplace(GetUniqueName(bindings, MakeDollarName(name)), - Binding(index)); + func->bindings.emplace(GetUniqueName(&func->bindings, MakeDollarName(name)), + Binding(local_index)); return Result::Ok; } diff --git a/src/binary-writer.cc b/src/binary-writer.cc index 9be23410..dc26128d 100644 --- a/src/binary-writer.cc +++ b/src/binary-writer.cc @@ -1075,30 +1075,19 @@ Result BinaryWriter::WriteModule() { WriteU32Leb128(stream_, module_->funcs.size(), "num functions"); for (size_t i = 0; i < module_->funcs.size(); ++i) { const Func* func = module_->funcs[i]; - Index num_params = func->GetNumParams(); - Index num_locals = func->local_types.size(); Index num_params_and_locals = func->GetNumParamsAndLocals(); WriteU32Leb128(stream_, i, "function index"); WriteU32Leb128(stream_, num_params_and_locals, "num locals"); - MakeTypeBindingReverseMapping(func->decl.sig.param_types.size(), - func->param_bindings, &index_to_name); - for (size_t j = 0; j < num_params; ++j) { + MakeTypeBindingReverseMapping(num_params_and_locals, func->bindings, + &index_to_name); + for (size_t j = 0; j < num_params_and_locals; ++j) { const std::string& name = index_to_name[j]; wabt_snprintf(desc, sizeof(desc), "local name %" PRIzd, j); WriteU32Leb128(stream_, j, "local index"); WriteDebugName(stream_, name, desc); } - - MakeTypeBindingReverseMapping(func->local_types.size(), - func->local_bindings, &index_to_name); - for (size_t j = 0; j < num_locals; ++j) { - const std::string& name = index_to_name[j]; - wabt_snprintf(desc, sizeof(desc), "local name %" PRIzd, num_params + j); - WriteU32Leb128(stream_, num_params + j, "local index"); - WriteDebugName(stream_, name, desc); - } } EndSubsection(); EndSection(); diff --git a/src/c-writer.cc b/src/c-writer.cc index 280ef5f7..0e8d6f91 100644 --- a/src/c-writer.cc +++ b/src/c-writer.cc @@ -240,8 +240,9 @@ class CWriter { void WriteInit(); void WriteFuncs(); void Write(const Func&); - void WriteParams(); - void WriteLocals(); + void WriteParamsAndLocals(); + void WriteParams(const std::vector<std::string>& index_to_name); + void WriteLocals(const std::vector<std::string>& index_to_name); void WriteStackVarDeclarations(); void Write(const ExprList&); @@ -1281,8 +1282,7 @@ void CWriter::Write(const Func& func) { Write("static ", ResultType(func.decl.sig.result_types), " ", GlobalName(func.name), "("); - WriteParams(); - WriteLocals(); + WriteParamsAndLocals(); Write("FUNC_PROLOGUE;", Newline()); stream_ = &func_stream_; @@ -1316,13 +1316,18 @@ void CWriter::Write(const Func& func) { func_ = nullptr; } -void CWriter::WriteParams() { - if (func_->decl.sig.param_types.empty()) { +void CWriter::WriteParamsAndLocals() { + std::vector<std::string> index_to_name; + MakeTypeBindingReverseMapping(func_->GetNumParamsAndLocals(), func_->bindings, + &index_to_name); + WriteParams(index_to_name); + WriteLocals(index_to_name); +} + +void CWriter::WriteParams(const std::vector<std::string>& index_to_name) { + if (func_->GetNumParams() == 0) { Write("void"); } else { - std::vector<std::string> index_to_name; - MakeTypeBindingReverseMapping(func_->decl.sig.param_types.size(), - func_->param_bindings, &index_to_name); Indent(4); for (Index i = 0; i < func_->GetNumParams(); ++i) { if (i != 0) { @@ -1338,10 +1343,8 @@ void CWriter::WriteParams() { Write(") ", OpenBrace()); } -void CWriter::WriteLocals() { - std::vector<std::string> index_to_name; - MakeTypeBindingReverseMapping(func_->local_types.size(), - func_->local_bindings, &index_to_name); +void CWriter::WriteLocals(const std::vector<std::string>& index_to_name) { + Index num_params = func_->GetNumParams(); for (Type type : {Type::I32, Type::I64, Type::F32, Type::F64}) { Index local_index = 0; size_t count = 0; @@ -1356,7 +1359,8 @@ void CWriter::WriteLocals() { Write(Newline()); } - Write(DefineLocalScopeName(index_to_name[local_index]), " = 0"); + Write(DefineLocalScopeName(index_to_name[num_params + local_index]), + " = 0"); ++count; } ++local_index; diff --git a/src/generate-names.cc b/src/generate-names.cc index 875f684f..b7760886 100644 --- a/src/generate-names.cc +++ b/src/generate-names.cc @@ -79,7 +79,8 @@ class NameGenerator : public ExprVisitor::DelegateNop { Index index, std::string* out_str); - void GenerateAndBindLocalNames(BindingHash* bindings, const char* prefix); + void GenerateAndBindLocalNames(Func* func); + template <typename T> Result VisitAll(const std::vector<T*>& items, Result (NameGenerator::*func)(Index, T*)); @@ -97,7 +98,6 @@ class NameGenerator : public ExprVisitor::DelegateNop { Module* module_ = nullptr; ExprVisitor visitor_; - std::vector<std::string> index_to_name_; Index label_count_ = 0; Index num_func_imports_ = 0; @@ -185,17 +185,20 @@ void NameGenerator::MaybeUseAndBindName(BindingHash* bindings, } } -void NameGenerator::GenerateAndBindLocalNames(BindingHash* bindings, - const char* prefix) { - for (size_t i = 0; i < index_to_name_.size(); ++i) { - const std::string& old_name = index_to_name_[i]; +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(bindings, prefix, i, &new_name); - index_to_name_[i] = new_name; + GenerateAndBindName(&func->bindings, prefix, i, &new_name); + index_to_name[i] = new_name; } } @@ -222,14 +225,7 @@ Result NameGenerator::BeginIfExceptExpr(IfExceptExpr* expr) { Result NameGenerator::VisitFunc(Index func_index, Func* func) { MaybeGenerateAndBindName(&module_->func_bindings, "$f", func_index, &func->name); - - MakeTypeBindingReverseMapping(func->decl.sig.param_types.size(), - func->param_bindings, &index_to_name_); - GenerateAndBindLocalNames(&func->param_bindings, "$p"); - - MakeTypeBindingReverseMapping(func->local_types.size(), func->local_bindings, - &index_to_name_); - GenerateAndBindLocalNames(&func->local_bindings, "$l"); + GenerateAndBindLocalNames(func); label_count_ = 0; CHECK_RESULT(visitor_.VisitFunc(func)); @@ -213,19 +213,7 @@ Index Func::GetLocalIndex(const Var& var) const { if (var.is_index()) { return var.index(); } - - Index result = param_bindings.FindIndex(var); - if (result != kInvalidIndex) { - return result; - } - - result = local_bindings.FindIndex(var); - if (result == kInvalidIndex) { - return result; - } - - // The locals start after all the params. - return decl.GetNumParams() + result; + return bindings.FindIndex(var); } const Func* Module::GetFunc(const Var& var) const { @@ -510,8 +510,7 @@ struct Func { std::string name; FuncDeclaration decl; LocalTypes local_types; - BindingHash param_bindings; - BindingHash local_bindings; + BindingHash bindings; ExprList exprs; }; diff --git a/src/resolve-names.cc b/src/resolve-names.cc index 9d24f2a7..1a6ec79f 100644 --- a/src/resolve-names.cc +++ b/src/resolve-names.cc @@ -69,6 +69,9 @@ class NameResolver : public ExprVisitor::DelegateNop { void PushLabel(const std::string& label); void PopLabel(); void CheckDuplicateBindings(const BindingHash* bindings, const char* desc); + void PrintDuplicateBindingsError(const BindingHash::value_type&, + const BindingHash::value_type&, + const char* desc); void ResolveLabelVar(Var* var); void ResolveVar(const BindingHash* bindings, Var* var, const char* desc); void ResolveFuncVar(Var* var); @@ -125,14 +128,20 @@ void NameResolver::CheckDuplicateBindings(const BindingHash* bindings, const char* desc) { bindings->FindDuplicates([this, desc](const BindingHash::value_type& a, const BindingHash::value_type& b) { - // 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()); + PrintDuplicateBindingsError(a, b, desc); }); } +void NameResolver::PrintDuplicateBindingsError(const BindingHash::value_type& a, + const BindingHash::value_type& b, + const char* 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) { @@ -370,8 +379,12 @@ void NameResolver::VisitFunc(Func* func) { ResolveFuncTypeVar(&func->decl.type_var); } - CheckDuplicateBindings(&func->param_bindings, "parameter"); - CheckDuplicateBindings(&func->local_bindings, "local"); + func->bindings.FindDuplicates( + [=](const BindingHash::value_type& a, const BindingHash::value_type& b) { + const char* desc = + (a.second.index < func->GetNumParams()) ? "parameter" : "local"; + PrintDuplicateBindingsError(a, b, desc); + }); visitor_.VisitFunc(func); current_func_ = nullptr; diff --git a/src/wast-parser.cc b/src/wast-parser.cc index 7b3b6e48..f9e89151 100644 --- a/src/wast-parser.cc +++ b/src/wast-parser.cc @@ -887,7 +887,7 @@ Result WastParser::ParseFuncModuleField(Module* module) { Func& func = import->func; CHECK_RESULT(ParseInlineImport(import.get())); CHECK_RESULT(ParseTypeUseOpt(&func.decl)); - CHECK_RESULT(ParseFuncSignature(&func.decl.sig, &func.param_bindings)); + CHECK_RESULT(ParseFuncSignature(&func.decl.sig, &func.bindings)); CHECK_RESULT(ErrorIfLpar({"type", "param", "result"})); auto field = MakeUnique<ImportModuleField>(std::move(import), GetLocation()); @@ -896,10 +896,10 @@ Result WastParser::ParseFuncModuleField(Module* module) { auto field = MakeUnique<FuncModuleField>(loc, name); Func& func = field->func; CHECK_RESULT(ParseTypeUseOpt(&func.decl)); - CHECK_RESULT(ParseFuncSignature(&func.decl.sig, &func.param_bindings)); + CHECK_RESULT(ParseFuncSignature(&func.decl.sig, &func.bindings)); TypeVector local_types; CHECK_RESULT(ParseBoundValueTypeList(TokenType::Local, &local_types, - &func.local_bindings)); + &func.bindings, func.GetNumParams())); func.local_types.Set(local_types); CHECK_RESULT(ParseTerminatingInstrList(&func.exprs)); module->AppendField(std::move(field)); @@ -985,8 +985,8 @@ Result WastParser::ParseImportModuleField(Module* module) { CHECK_RESULT(ParseTypeUseOpt(&import->func.decl)); EXPECT(Rpar); } else { - CHECK_RESULT(ParseFuncSignature(&import->func.decl.sig, - &import->func.param_bindings)); + CHECK_RESULT( + ParseFuncSignature(&import->func.decl.sig, &import->func.bindings)); CHECK_RESULT(ErrorIfLpar({"param", "result"})); EXPECT(Rpar); } @@ -1232,7 +1232,8 @@ Result WastParser::ParseUnboundFuncSignature(FuncSignature* sig) { Result WastParser::ParseBoundValueTypeList(TokenType token, TypeVector* types, - BindingHash* bindings) { + BindingHash* bindings, + Index binding_index_offset) { WABT_TRACE(ParseBoundValueTypeList); while (MatchLpar(token)) { if (PeekMatch(TokenType::Var)) { @@ -1241,7 +1242,8 @@ Result WastParser::ParseBoundValueTypeList(TokenType token, Location loc = GetLocation(); ParseBindVarOpt(&name); CHECK_RESULT(ParseValueType(&type)); - bindings->emplace(name, Binding(loc, types->size())); + bindings->emplace(name, + Binding(loc, binding_index_offset + types->size())); types->push_back(type); } else { CHECK_RESULT(ParseValueTypeList(types)); diff --git a/src/wast-parser.h b/src/wast-parser.h index 8a1b0a69..09e19e55 100644 --- a/src/wast-parser.h +++ b/src/wast-parser.h @@ -149,7 +149,10 @@ class WastParser { Result ParseTypeUseOpt(FuncDeclaration*); Result ParseFuncSignature(FuncSignature*, BindingHash* param_bindings); Result ParseUnboundFuncSignature(FuncSignature*); - Result ParseBoundValueTypeList(TokenType, TypeVector*, BindingHash*); + Result ParseBoundValueTypeList(TokenType, + TypeVector*, + BindingHash*, + Index binding_index_offset = 0); Result ParseUnboundValueTypeList(TokenType, TypeVector*); Result ParseResultList(TypeVector*); Result ParseInstrList(ExprList*); diff --git a/src/wat-writer.cc b/src/wat-writer.cc index 9297b14a..9f646e50 100644 --- a/src/wat-writer.cc +++ b/src/wat-writer.cc @@ -157,9 +157,9 @@ class WatWriter { void WriteInitExpr(const ExprList& expr); template <typename T> void WriteTypeBindings(const char* prefix, - const Func& func, const T& types, - const BindingHash& bindings); + const std::vector<std::string>& index_to_name, + Index binding_index_offset = 0); void WriteBeginFunc(const Func& func); void WriteFunc(const Func& func); void WriteBeginGlobal(const Global& global); @@ -203,7 +203,6 @@ class WatWriter { Result result_ = Result::Ok; int indent_ = 0; NextChar next_char_ = NextChar::None; - std::vector<std::string> index_to_name_; std::vector<Label> label_stack_; std::vector<ExprTree> expr_tree_stack_; std::multimap<std::pair<ExternalKind, Index>, const Export*> @@ -1325,11 +1324,9 @@ void WatWriter::WriteInitExpr(const ExprList& expr) { template <typename T> void WatWriter::WriteTypeBindings(const char* prefix, - const Func& func, const T& types, - const BindingHash& bindings) { - MakeTypeBindingReverseMapping(types.size(), bindings, &index_to_name_); - + const std::vector<std::string>& index_to_name, + Index binding_index_offset) { /* named params/locals must be specified by themselves, but nameless * params/locals can be compressed, e.g.: * (param $foo i32) @@ -1343,7 +1340,7 @@ void WatWriter::WriteTypeBindings(const char* prefix, is_open = true; } - const std::string& name = index_to_name_[index]; + const std::string& name = index_to_name[binding_index_offset + index]; if (!name.empty()) { WriteString(name, NextChar::Space); } @@ -1390,12 +1387,15 @@ void WatWriter::WriteBeginFunc(const Func& func) { void WatWriter::WriteFunc(const Func& func) { WriteBeginFunc(func); - WriteTypeBindings("param", func, func.decl.sig.param_types, - func.param_bindings); + std::vector<std::string> index_to_name; + MakeTypeBindingReverseMapping(func.GetNumParamsAndLocals(), func.bindings, + &index_to_name); + WriteTypeBindings("param", func.decl.sig.param_types, index_to_name); WriteTypes(func.decl.sig.result_types, "result"); WriteNewline(NO_FORCE_NEWLINE); if (func.local_types.size()) { - WriteTypeBindings("local", func, func.local_types, func.local_bindings); + WriteTypeBindings("local", func.local_types, index_to_name, + func.GetNumParams()); } WriteNewline(NO_FORCE_NEWLINE); label_stack_.clear(); diff --git a/test/parse/func/bad-local-redefinition.txt b/test/parse/func/bad-local-redefinition.txt new file mode 100644 index 00000000..ee603c61 --- /dev/null +++ b/test/parse/func/bad-local-redefinition.txt @@ -0,0 +1,8 @@ +;;; TOOL: wat2wasm +;;; ERROR: 1 +(module (func (param $n i32) (local $n f32))) +(;; STDERR ;;; +out/test/parse/func/bad-local-redefinition.txt:3:37: error: redefinition of parameter "$n" +(module (func (param $n i32) (local $n f32))) + ^^ +;;; STDERR ;;) diff --git a/test/roundtrip/generate-local-names.txt b/test/roundtrip/generate-local-names.txt index 935b9ac6..925e830c 100644 --- a/test/roundtrip/generate-local-names.txt +++ b/test/roundtrip/generate-local-names.txt @@ -24,21 +24,21 @@ (module (type $t0 (func (param i32 f32))) (func $f0 (type $t0) (param $p0 i32) (param $p1 f32) - (local $l0 f64) (local $l1 i64) + (local $l2 f64) (local $l3 i64) get_local $p0 drop get_local $p1 drop - get_local $l0 + get_local $l2 drop - get_local $l1 + get_local $l3 drop i32.const 1 set_local $p0 f32.const 0x1p+0 (;=1;) set_local $p1 f64.const 0x1p+0 (;=1;) - set_local $l0 + set_local $l2 i64.const 1 - set_local $l1)) + set_local $l3)) ;;; STDOUT ;;) diff --git a/test/roundtrip/generate-some-names.txt b/test/roundtrip/generate-some-names.txt index 765beb05..08c36abb 100644 --- a/test/roundtrip/generate-some-names.txt +++ b/test/roundtrip/generate-some-names.txt @@ -37,7 +37,7 @@ (func $func0 (type $t0) (param $p0 i32) (result f32) f32.const 0x1p+0 (;=1;)) (func $f2 (type $t2) (param $p0 i32) (param $param1 i64) - (local $l0 f32) (local $local1 f64) + (local $l2 f32) (local $local1 f64) call $import drop i32.const 0 @@ -50,7 +50,7 @@ get_local $param1 drop f32.const 0x0p+0 (;=0;) - set_local $l0) + set_local $l2) (table $T0 1 1 anyfunc) (export "baz" (func $import)) (export "quux" (func $func0)) |