summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/apply-names.cc4
-rw-r--r--src/binary-reader-ir.cc7
-rw-r--r--src/binary-writer.cc45
-rw-r--r--src/c-writer.cc6
-rw-r--r--src/generate-names.cc4
-rw-r--r--src/ir.cc43
-rw-r--r--src/ir.h55
-rw-r--r--src/wast-parser.cc4
-rw-r--r--src/wat-writer.cc16
-rw-r--r--test/regress/regress-20.txt19
10 files changed, 143 insertions, 60 deletions
diff --git a/src/apply-names.cc b/src/apply-names.cc
index 4cabc13e..4b35d18e 100644
--- a/src/apply-names.cc
+++ b/src/apply-names.cc
@@ -328,10 +328,10 @@ Result NameApplier::VisitFunc(Index func_index, Func* func) {
CHECK_RESULT(UseNameForFuncTypeVar(&func->decl.type_var));
}
- MakeTypeBindingReverseMapping(func->decl.sig.param_types,
+ MakeTypeBindingReverseMapping(func->decl.sig.param_types.size(),
func->param_bindings, &param_index_to_name_);
- MakeTypeBindingReverseMapping(func->local_types, func->local_bindings,
+ MakeTypeBindingReverseMapping(func->local_types.size(), func->local_bindings,
&local_index_to_name_);
CHECK_RESULT(visitor_.VisitFunc(func));
diff --git a/src/binary-reader-ir.cc b/src/binary-reader-ir.cc
index 448ac444..b90ed62c 100644
--- a/src/binary-reader-ir.cc
+++ b/src/binary-reader-ir.cc
@@ -541,12 +541,7 @@ Result BinaryReaderIR::BeginFunctionBody(Index index) {
}
Result BinaryReaderIR::OnLocalDecl(Index decl_index, Index count, Type type) {
- TypeVector& types = current_func_->local_types;
- WABT_TRY
- types.reserve(types.size() + count);
- WABT_CATCH_BAD_ALLOC
- for (size_t i = 0; i < count; ++i)
- types.push_back(type);
+ current_func_->local_types.decls.emplace_back(type, count);
return Result::Ok;
}
diff --git a/src/binary-writer.cc b/src/binary-writer.cc
index 7f3d0f96..4c808359 100644
--- a/src/binary-writer.cc
+++ b/src/binary-writer.cc
@@ -139,7 +139,7 @@ class BinaryWriter {
void WriteExpr(const Func* func, const Expr* expr);
void WriteExprList(const Func* func, const ExprList& exprs);
void WriteInitExpr(const ExprList& expr);
- void WriteFuncLocals(const Func* func, const TypeVector& local_types);
+ void WriteFuncLocals(const Func* func, const LocalTypes& local_types);
void WriteFunc(const Func* func);
void WriteTable(const Table* table);
void WriteMemory(const Memory* memory);
@@ -622,44 +622,17 @@ void BinaryWriter::WriteInitExpr(const ExprList& expr) {
}
void BinaryWriter::WriteFuncLocals(const Func* func,
- const TypeVector& local_types) {
+ const LocalTypes& local_types) {
if (local_types.size() == 0) {
WriteU32Leb128(stream_, 0, "local decl count");
return;
}
- Index num_params = func->GetNumParams();
-
-#define FIRST_LOCAL_INDEX (num_params)
-#define LAST_LOCAL_INDEX (num_params + local_types.size())
-#define GET_LOCAL_TYPE(x) (local_types[x - num_params])
-
- /* loop through once to count the number of local declaration runs */
- Type current_type = GET_LOCAL_TYPE(FIRST_LOCAL_INDEX);
- Index local_decl_count = 1;
- for (Index i = FIRST_LOCAL_INDEX + 1; i < LAST_LOCAL_INDEX; ++i) {
- Type type = GET_LOCAL_TYPE(i);
- if (current_type != type) {
- local_decl_count++;
- current_type = type;
- }
- }
-
- /* loop through again to write everything out */
+ Index local_decl_count = local_types.decls.size();
WriteU32Leb128(stream_, local_decl_count, "local decl count");
- current_type = GET_LOCAL_TYPE(FIRST_LOCAL_INDEX);
- Index local_type_count = 1;
- for (Index i = FIRST_LOCAL_INDEX + 1; i <= LAST_LOCAL_INDEX; ++i) {
- /* loop through an extra time to catch the final type transition */
- Type type = i == LAST_LOCAL_INDEX ? Type::Void : GET_LOCAL_TYPE(i);
- if (current_type == type) {
- local_type_count++;
- } else {
- WriteU32Leb128(stream_, local_type_count, "local type count");
- WriteType(stream_, current_type);
- local_type_count = 1;
- current_type = type;
- }
+ for (auto decl : local_types.decls) {
+ WriteU32Leb128(stream_, decl.second, "local type count");
+ WriteType(stream_, decl.first);
}
}
@@ -1034,7 +1007,7 @@ Result BinaryWriter::WriteModule() {
WriteU32Leb128(stream_, i, "function index");
WriteU32Leb128(stream_, num_params_and_locals, "num locals");
- MakeTypeBindingReverseMapping(func->decl.sig.param_types,
+ MakeTypeBindingReverseMapping(func->decl.sig.param_types.size(),
func->param_bindings, &index_to_name);
for (size_t j = 0; j < num_params; ++j) {
const std::string& name = index_to_name[j];
@@ -1043,8 +1016,8 @@ Result BinaryWriter::WriteModule() {
WriteDebugName(stream_, name, desc);
}
- MakeTypeBindingReverseMapping(func->local_types, func->local_bindings,
- &index_to_name);
+ 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);
diff --git a/src/c-writer.cc b/src/c-writer.cc
index 43cf50d8..93dd9eb8 100644
--- a/src/c-writer.cc
+++ b/src/c-writer.cc
@@ -1314,7 +1314,7 @@ void CWriter::WriteParams() {
Write("void");
} else {
std::vector<std::string> index_to_name;
- MakeTypeBindingReverseMapping(func_->decl.sig.param_types,
+ MakeTypeBindingReverseMapping(func_->decl.sig.param_types.size(),
func_->param_bindings, &index_to_name);
Indent(4);
for (Index i = 0; i < func_->GetNumParams(); ++i) {
@@ -1333,8 +1333,8 @@ void CWriter::WriteParams() {
void CWriter::WriteLocals() {
std::vector<std::string> index_to_name;
- MakeTypeBindingReverseMapping(func_->local_types, func_->local_bindings,
- &index_to_name);
+ MakeTypeBindingReverseMapping(func_->local_types.size(),
+ func_->local_bindings, &index_to_name);
for (Type type : {Type::I32, Type::I64, Type::F32, Type::F64}) {
Index local_index = 0;
size_t count = 0;
diff --git a/src/generate-names.cc b/src/generate-names.cc
index a1b02fb4..ef2f8ab8 100644
--- a/src/generate-names.cc
+++ b/src/generate-names.cc
@@ -217,11 +217,11 @@ Result NameGenerator::VisitFunc(Index func_index, Func* func) {
MaybeGenerateAndBindName(&module_->func_bindings, "$f", func_index,
&func->name);
- MakeTypeBindingReverseMapping(func->decl.sig.param_types,
+ MakeTypeBindingReverseMapping(func->decl.sig.param_types.size(),
func->param_bindings, &index_to_name_);
GenerateAndBindLocalNames(&func->param_bindings, "$p");
- MakeTypeBindingReverseMapping(func->local_types, func->local_bindings,
+ MakeTypeBindingReverseMapping(func->local_types.size(), func->local_bindings,
&index_to_name_);
GenerateAndBindLocalNames(&func->local_bindings, "$l");
diff --git a/src/ir.cc b/src/ir.cc
index e81e8525..23778a7e 100644
--- a/src/ir.cc
+++ b/src/ir.cc
@@ -18,6 +18,7 @@
#include <cassert>
#include <cstddef>
+#include <numeric>
#include "src/cast.h"
@@ -138,6 +139,44 @@ bool Module::IsImport(ExternalKind kind, const Var& var) const {
}
}
+void LocalTypes::Set(const TypeVector& types) {
+ decls.clear();
+ if (types.empty()) {
+ return;
+ }
+
+ Type type = types[0];
+ Index count = 1;
+ for (Index i = 1; i < types.size(); ++i) {
+ if (types[i] != type) {
+ decls.emplace_back(type, count);
+ type = types[i];
+ count = 1;
+ } else {
+ ++count;
+ }
+ }
+ decls.emplace_back(type, count);
+}
+
+Index LocalTypes::size() const {
+ return std::accumulate(
+ decls.begin(), decls.end(), 0,
+ [](Index sum, const Decl& decl) { return sum + decl.second; });
+}
+
+Type LocalTypes::operator[](Index i) const {
+ Index count = 0;
+ for (auto decl: decls) {
+ if (i < count + decl.second) {
+ return decl.first;
+ }
+ count += decl.second;
+ }
+ assert(i < count);
+ return Type::Any;
+}
+
Type Func::GetLocalType(Index index) const {
Index num_params = decl.GetNumParams();
if (index < num_params) {
@@ -477,11 +516,11 @@ const Module* Script::GetModule(const Var& var) const {
}
void MakeTypeBindingReverseMapping(
- const TypeVector& types,
+ size_t num_types,
const BindingHash& bindings,
std::vector<std::string>* out_reverse_mapping) {
out_reverse_mapping->clear();
- out_reverse_mapping->resize(types.size());
+ out_reverse_mapping->resize(num_types);
for (const auto& pair : bindings) {
assert(static_cast<size_t>(pair.second.index) <
out_reverse_mapping->size());
diff --git a/src/ir.h b/src/ir.h
index b75b0e91..29e63060 100644
--- a/src/ir.h
+++ b/src/ir.h
@@ -404,6 +404,57 @@ struct Exception {
TypeVector sig;
};
+struct LocalTypes {
+ typedef std::pair<Type, Index> Decl;
+ typedef std::vector<Decl> Decls;
+
+ struct const_iterator {
+ const_iterator(Decls::const_iterator decl, Index index)
+ : decl(decl), index(index) {}
+ Type operator*() const { return decl->first; }
+ const_iterator& operator++();
+ const_iterator operator++(int);
+
+ Decls::const_iterator decl;
+ Index index;
+ };
+
+ void Set(const TypeVector&);
+
+ Index size() const;
+ Type operator[](Index) const;
+
+ const_iterator begin() const { return {decls.begin(), 0}; }
+ const_iterator end() const { return {decls.end(), 0}; }
+
+ Decls decls;
+};
+
+inline LocalTypes::const_iterator& LocalTypes::const_iterator::operator++() {
+ ++index;
+ if (index >= decl->second) {
+ ++decl;
+ index = 0;
+ }
+ return *this;
+}
+
+inline LocalTypes::const_iterator LocalTypes::const_iterator::operator++(int) {
+ const_iterator result = *this;
+ operator++();
+ return result;
+}
+
+inline bool operator==(const LocalTypes::const_iterator& lhs,
+ const LocalTypes::const_iterator& rhs) {
+ return lhs.decl == rhs.decl && lhs.index == rhs.index;
+}
+
+inline bool operator!=(const LocalTypes::const_iterator& lhs,
+ const LocalTypes::const_iterator& rhs) {
+ return !operator==(lhs, rhs);
+}
+
struct Func {
explicit Func(string_view name) : name(name.to_string()) {}
@@ -421,7 +472,7 @@ struct Func {
std::string name;
FuncDeclaration decl;
- TypeVector local_types;
+ LocalTypes local_types;
BindingHash param_bindings;
BindingHash local_bindings;
ExprList exprs;
@@ -969,7 +1020,7 @@ struct Script {
};
void MakeTypeBindingReverseMapping(
- const TypeVector& types,
+ size_t num_types,
const BindingHash& bindings,
std::vector<std::string>* out_reverse_mapping);
diff --git a/src/wast-parser.cc b/src/wast-parser.cc
index a86ab4e1..3381b65e 100644
--- a/src/wast-parser.cc
+++ b/src/wast-parser.cc
@@ -862,8 +862,10 @@ Result WastParser::ParseFuncModuleField(Module* module) {
Func& func = field->func;
CHECK_RESULT(ParseTypeUseOpt(&func.decl));
CHECK_RESULT(ParseFuncSignature(&func.decl.sig, &func.param_bindings));
- CHECK_RESULT(ParseBoundValueTypeList(TokenType::Local, &func.local_types,
+ TypeVector local_types;
+ CHECK_RESULT(ParseBoundValueTypeList(TokenType::Local, &local_types,
&func.local_bindings));
+ func.local_types.Set(local_types);
CHECK_RESULT(ParseTerminatingInstrList(&func.exprs));
module->AppendField(std::move(field));
}
diff --git a/src/wat-writer.cc b/src/wat-writer.cc
index c9db2f83..0f52e6a4 100644
--- a/src/wat-writer.cc
+++ b/src/wat-writer.cc
@@ -150,9 +150,10 @@ class WatWriter {
void WriteLoadStoreExpr(const Expr* expr);
void WriteExprList(const ExprList& exprs);
void WriteInitExpr(const ExprList& expr);
+ template <typename T>
void WriteTypeBindings(const char* prefix,
const Func& func,
- const TypeVector& types,
+ const T& types,
const BindingHash& bindings);
void WriteBeginFunc(const Func& func);
void WriteFunc(const Func& func);
@@ -1216,11 +1217,12 @@ void WatWriter::WriteInitExpr(const ExprList& expr) {
}
}
+template <typename T>
void WatWriter::WriteTypeBindings(const char* prefix,
const Func& func,
- const TypeVector& types,
+ const T& types,
const BindingHash& bindings) {
- MakeTypeBindingReverseMapping(types, bindings, &index_to_name_);
+ MakeTypeBindingReverseMapping(types.size(), bindings, &index_to_name_);
/* named params/locals must be specified by themselves, but nameless
* params/locals can be compressed, e.g.:
@@ -1228,21 +1230,23 @@ void WatWriter::WriteTypeBindings(const char* prefix,
* (param i32 i64 f32)
*/
bool is_open = false;
- for (size_t i = 0; i < types.size(); ++i) {
+ size_t index = 0;
+ for (Type type : types) {
if (!is_open) {
WriteOpenSpace(prefix);
is_open = true;
}
- const std::string& name = index_to_name_[i];
+ const std::string& name = index_to_name_[index];
if (!name.empty()) {
WriteString(name, NextChar::Space);
}
- WriteType(types[i], NextChar::Space);
+ WriteType(type, NextChar::Space);
if (!name.empty()) {
WriteCloseSpace();
is_open = false;
}
+ ++index;
}
if (is_open) {
WriteCloseSpace();
diff --git a/test/regress/regress-20.txt b/test/regress/regress-20.txt
new file mode 100644
index 00000000..c1f409f8
--- /dev/null
+++ b/test/regress/regress-20.txt
@@ -0,0 +1,19 @@
+;;; TOOL: run-gen-wasm-bad
+magic
+version
+section(TYPE) { count[1] function params[0] results[1] i32 }
+section(FUNCTION) { count[1] type[0] }
+section(CODE) {
+ count[1]
+ func {
+ locals[
+ decl_count[1]
+ local_count[leb_i32(3334443763)] ;; <- huge number of locals
+ 42 ;; <- invalid type
+ ]
+ }
+}
+(;; STDERR ;;;
+000001e: error: expected valid local type
+000001e: error: expected valid local type
+;;; STDERR ;;)