diff --git a/CMakeLists.txt b/CMakeLists.txt index a40574578..56666370f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -704,7 +704,6 @@ if (BUILD_TESTS) set(UNITTESTS_SRCS src/test-binary-reader.cc src/test-interp.cc - src/test-intrusive-list.cc src/test-literal.cc src/test-option-parser.cc src/test-filenames.cc diff --git a/include/wabt/decompiler-ast.h b/include/wabt/decompiler-ast.h index 33cc26c11..d3506e3e5 100644 --- a/include/wabt/decompiler-ast.h +++ b/include/wabt/decompiler-ast.h @@ -22,6 +22,7 @@ #include "wabt/ir-util.h" #include "wabt/ir.h" +#include #include namespace wabt { @@ -250,8 +251,8 @@ struct AST { auto value_stack_in_variables = value_stack_depth; bool unreachable = false; for (auto& e : es) { - Construct(e); - auto arity = mc.GetExprArity(e); + Construct(*e); + auto arity = mc.GetExprArity(*e); value_stack_depth -= arity.nargs; value_stack_in_variables = std::min(value_stack_in_variables, value_stack_depth); @@ -337,7 +338,7 @@ struct AST { // TODO: this would be nice to also do for local.get and maybe others, // though that needs a way to ensure there's no local.set in between // when they get lifted, so complicates matters a bit. - if (e.type() == ExprType::Const && + if (e->type() == ExprType::Const && value_stack_in_variables == value_stack_depth - 1) { value_stack_in_variables++; } diff --git a/include/wabt/intrusive-list.h b/include/wabt/intrusive-list.h deleted file mode 100644 index 34332345a..000000000 --- a/include/wabt/intrusive-list.h +++ /dev/null @@ -1,631 +0,0 @@ -/* - * Copyright 2017 WebAssembly Community Group participants - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef WABT_INTRUSIVE_LIST_H_ -#define WABT_INTRUSIVE_LIST_H_ - -#include -#include -#include - -// This uses a similar interface as std::list, but is missing the following -// features: -// -// * Add "extract_" functions that remove an element from the list and return -// it. -// * Only supports move-only operations -// * No allocator support -// * No initializer lists -// * Asserts instead of exceptions -// * Some functions are not implemented (merge, remove, remove_if, reverse, -// unique, sort, non-member comparison operators) - -namespace wabt { - -template -class intrusive_list; - -template -class intrusive_list_base { - private: - friend class intrusive_list; - - mutable T* next_ = nullptr; - mutable T* prev_ = nullptr; -}; - -template -class intrusive_list { - public: - // types: - using value_type = T; - using reference = value_type&; - using const_reference = const value_type&; - class iterator; - class const_iterator; - using size_type = std::size_t; - using difference_type = std::ptrdiff_t; - using reverse_iterator = std::reverse_iterator; - using const_reverse_iterator = std::reverse_iterator; - - // construct/copy/destroy: - intrusive_list(); - explicit intrusive_list(std::unique_ptr node); - explicit intrusive_list(T&& node); - intrusive_list(const intrusive_list&) = delete; - intrusive_list(intrusive_list&&); - ~intrusive_list(); - intrusive_list& operator=(const intrusive_list& other) = delete; - intrusive_list& operator=(intrusive_list&& other); - - // iterators: - iterator begin() noexcept; - const_iterator begin() const noexcept; - iterator end() noexcept; - const_iterator end() const noexcept; - - reverse_iterator rbegin() noexcept; - const_reverse_iterator rbegin() const noexcept; - reverse_iterator rend() noexcept; - const_reverse_iterator rend() const noexcept; - - const_iterator cbegin() const noexcept; - const_iterator cend() const noexcept; - const_reverse_iterator crbegin() const noexcept; - const_reverse_iterator crend() const noexcept; - - // capacity: - size_type size() const noexcept; - bool empty() const noexcept; - - // element access: - reference front(); - const_reference front() const; - reference back(); - const_reference back() const; - - // modifiers: - template - void emplace_front(Args&&... args); - template - void emplace_back(Args&&... args); - void push_front(std::unique_ptr node); - void push_front(T&& node); - void push_back(std::unique_ptr node); - void push_back(T&& node); - void pop_front(); - void pop_back(); - std::unique_ptr extract_front(); - std::unique_ptr extract_back(); - - template - iterator emplace(iterator pos, Args&&... args); - iterator insert(iterator pos, std::unique_ptr node); - iterator insert(iterator pos, T&& node); - std::unique_ptr extract(iterator it); - - iterator erase(iterator pos); - iterator erase(iterator first, iterator last); - void swap(intrusive_list&); - void clear() noexcept; - - void splice(iterator pos, intrusive_list& node); - void splice(iterator pos, intrusive_list&& node); - void splice(iterator pos, intrusive_list& node, iterator it); - void splice(iterator pos, - intrusive_list& node, - iterator first, - iterator last); - - private: - T* first_ = nullptr; - T* last_ = nullptr; - size_t size_ = 0; -}; - -/// iterator -template -class intrusive_list::iterator { - public: - using difference_type = std::ptrdiff_t; - using iterator_category = std::bidirectional_iterator_tag; - using value_type = T; - using pointer = T*; - using reference = T&; - - iterator(const intrusive_list& list, T* node) - : list_(&list), node_(node) {} - - reference operator*() const { - assert(node_); - return *node_; - } - - pointer operator->() const { - assert(node_); - return node_; - } - - iterator& operator++() { - assert(node_); - node_ = node_->next_; - return *this; - } - - iterator operator++(int) { - iterator tmp = *this; - operator++(); - return tmp; - } - - iterator& operator--() { - node_ = node_ ? node_->prev_ : list_->last_; - return *this; - } - - iterator operator--(int) { - iterator tmp = *this; - operator--(); - return tmp; - } - - bool operator==(iterator rhs) const { - assert(list_ == rhs.list_); - return node_ == rhs.node_; - } - - bool operator!=(iterator rhs) const { - assert(list_ == rhs.list_); - return node_ != rhs.node_; - } - - private: - friend class const_iterator; - - const intrusive_list* list_; - T* node_; -}; - -/// const_iterator -template -class intrusive_list::const_iterator { - public: - using difference_type = std::ptrdiff_t; - using iterator_category = std::bidirectional_iterator_tag; - using value_type = T; - using pointer = const T*; - using reference = const T&; - - const_iterator(const intrusive_list& list, T* node) - : list_(&list), node_(node) {} - - const_iterator(const iterator& other) - : list_(other.list_), node_(other.node_) {} - - reference operator*() const { - assert(node_); - return *node_; - } - - pointer operator->() const { - assert(node_); - return node_; - } - - const_iterator& operator++() { - assert(node_); - node_ = node_->next_; - return *this; - } - - const_iterator operator++(int) { - const_iterator tmp = *this; - operator++(); - return tmp; - } - - const_iterator& operator--() { - node_ = node_ ? node_->prev_ : list_->last_; - return *this; - } - - const_iterator operator--(int) { - const_iterator tmp = *this; - operator--(); - return tmp; - } - - bool operator==(const_iterator rhs) const { - assert(list_ == rhs.list_); - return node_ == rhs.node_; - } - - bool operator!=(const_iterator rhs) const { - assert(list_ == rhs.list_); - return node_ != rhs.node_; - } - - private: - const intrusive_list* list_; - T* node_; -}; - -template -inline intrusive_list::intrusive_list() {} - -template -inline intrusive_list::intrusive_list(std::unique_ptr node) { - push_back(std::move(node)); -} - -template -inline intrusive_list::intrusive_list(T&& node) { - push_back(std::move(node)); -} - -template -inline intrusive_list::intrusive_list(intrusive_list&& other) - : first_(other.first_), last_(other.last_), size_(other.size_) { - other.first_ = other.last_ = nullptr; - other.size_ = 0; -} - -template -inline intrusive_list::~intrusive_list() { - clear(); -} - -template -inline intrusive_list& intrusive_list::operator=( - intrusive_list&& other) { - clear(); - first_ = other.first_; - last_ = other.last_; - size_ = other.size_; - other.first_ = other.last_ = nullptr; - other.size_ = 0; - return *this; -} - -template -inline typename intrusive_list::iterator -intrusive_list::begin() noexcept { - return iterator(*this, first_); -} - -template -inline typename intrusive_list::const_iterator intrusive_list::begin() - const noexcept { - return const_iterator(*this, first_); -} - -template -inline typename intrusive_list::iterator intrusive_list::end() noexcept { - return iterator(*this, nullptr); -} - -template -inline typename intrusive_list::const_iterator intrusive_list::end() - const noexcept { - return const_iterator(*this, nullptr); -} - -template -inline typename intrusive_list::reverse_iterator -intrusive_list::rbegin() noexcept { - return reverse_iterator(iterator(*this, nullptr)); -} - -template -inline typename intrusive_list::const_reverse_iterator -intrusive_list::rbegin() const noexcept { - return const_reverse_iterator(const_iterator(*this, nullptr)); -} - -template -inline typename intrusive_list::reverse_iterator -intrusive_list::rend() noexcept { - return reverse_iterator(iterator(*this, first_)); -} - -template -inline typename intrusive_list::const_reverse_iterator -intrusive_list::rend() const noexcept { - return const_reverse_iterator(const_iterator(*this, first_)); -} - -template -inline typename intrusive_list::const_iterator intrusive_list::cbegin() - const noexcept { - return const_iterator(*this, first_); -} - -template -inline typename intrusive_list::const_iterator intrusive_list::cend() - const noexcept { - return const_iterator(*this, nullptr); -} - -template -inline typename intrusive_list::const_reverse_iterator -intrusive_list::crbegin() const noexcept { - return const_reverse_iterator(const_iterator(*this, nullptr)); -} - -template -inline typename intrusive_list::const_reverse_iterator -intrusive_list::crend() const noexcept { - return const_reverse_iterator(const_iterator(*this, first_)); -} - -template -inline typename intrusive_list::size_type intrusive_list::size() - const noexcept { - return size_; -} - -template -inline bool intrusive_list::empty() const noexcept { - return size_ == 0; -} - -template -inline typename intrusive_list::reference intrusive_list::front() { - assert(!empty()); - return *first_; -} - -template -inline typename intrusive_list::const_reference intrusive_list::front() - const { - assert(!empty()); - return *first_; -} - -template -inline typename intrusive_list::reference intrusive_list::back() { - assert(!empty()); - return *last_; -} - -template -inline typename intrusive_list::const_reference intrusive_list::back() - const { - assert(!empty()); - return *last_; -} - -template -template -inline void intrusive_list::emplace_front(Args&&... args) { - push_front(std::make_unique(std::forward(args)...)); -} - -template -template -inline void intrusive_list::emplace_back(Args&&... args) { - push_back(std::make_unique(std::forward(args)...)); -} - -template -inline void intrusive_list::push_front(std::unique_ptr node) { - assert(node->prev_ == nullptr && node->next_ == nullptr); - - T* node_p = node.release(); - if (first_) { - node_p->next_ = first_; - first_->prev_ = node_p; - } else { - last_ = node_p; - } - first_ = node_p; - size_++; -} - -template -inline void intrusive_list::push_front(T&& node) { - push_front(std::make_unique(std::move(node))); -} - -template -inline void intrusive_list::push_back(std::unique_ptr node) { - assert(node->prev_ == nullptr && node->next_ == nullptr); - - T* node_p = node.release(); - if (last_) { - node_p->prev_ = last_; - last_->next_ = node_p; - } else { - first_ = node_p; - } - last_ = node_p; - size_++; -} - -template -inline void intrusive_list::push_back(T&& node) { - push_back(std::make_unique(std::move(node))); -} - -template -inline void intrusive_list::pop_front() { - extract_front(); -} - -template -inline void intrusive_list::pop_back() { - extract_back(); -} - -template -inline std::unique_ptr intrusive_list::extract_front() { - assert(!empty()); - T* node = first_; - if (first_ == last_) { - first_ = last_ = nullptr; - } else { - first_ = first_->next_; - first_->prev_ = nullptr; - } - node->next_ = node->prev_ = nullptr; - size_--; - return std::unique_ptr(node); -} - -template -inline std::unique_ptr intrusive_list::extract_back() { - assert(!empty()); - T* node = last_; - if (first_ == last_) { - first_ = last_ = nullptr; - } else { - last_ = last_->prev_; - last_->next_ = nullptr; - } - node->next_ = node->prev_ = nullptr; - size_--; - return std::unique_ptr(node); -} - -template -template -inline typename intrusive_list::iterator intrusive_list::emplace( - iterator pos, - Args&&... args) { - return insert(pos, std::make_unique(std::forward(args)...)); -} - -template -inline typename intrusive_list::iterator intrusive_list::insert( - iterator pos, - std::unique_ptr node) { - assert(node->prev_ == nullptr && node->next_ == nullptr); - - T* node_p; - if (pos == end()) { - push_back(std::move(node)); - node_p = &back(); - } else { - node_p = node.release(); - node_p->prev_ = pos->prev_; - node_p->next_ = &*pos; - if (pos->prev_) { - pos->prev_->next_ = node_p; - } else { - first_ = node_p; - } - pos->prev_ = node_p; - size_++; - } - return iterator(*this, node_p); -} - -template -inline typename intrusive_list::iterator intrusive_list::insert( - iterator pos, - T&& node) { - return insert(pos, std::make_unique(std::move(node))); -} - -template -inline std::unique_ptr intrusive_list::extract(iterator pos) { - assert(!empty()); - assert(pos != end()); - T* node = &*pos; - if (first_ == last_) { - first_ = last_ = nullptr; - } else { - if (node->prev_) { - node->prev_->next_ = node->next_; - } else { - first_ = node->next_; - } - - if (node->next_) { - node->next_->prev_ = node->prev_; - } else { - last_ = node->prev_; - } - } - node->next_ = node->prev_ = nullptr; - size_--; - return std::unique_ptr(node); -} - -template -inline typename intrusive_list::iterator intrusive_list::erase( - iterator pos) { - iterator next = std::next(pos); - extract(pos); - return next; -} - -template -inline typename intrusive_list::iterator intrusive_list::erase( - iterator first, - iterator last) { - while (first != last) - first = erase(first); - return first; -} - -template -inline void intrusive_list::swap(intrusive_list& other) { - std::swap(first_, other.first_); - std::swap(last_, other.last_); - std::swap(size_, other.size_); -} - -template -inline void intrusive_list::clear() noexcept { - for (T* iter = first_; iter;) { - T* next = iter->next_; - delete iter; - iter = next; - } - first_ = last_ = nullptr; - size_ = 0; -} - -template -inline void intrusive_list::splice(iterator pos, intrusive_list& other) { - splice(pos, other, other.begin(), other.end()); -} - -template -inline void intrusive_list::splice(iterator pos, intrusive_list&& other) { - splice(pos, other, other.begin(), other.end()); -} - -template -inline void intrusive_list::splice(iterator pos, - intrusive_list& other, - iterator it) { - insert(pos, other.extract(it)); -} - -template -inline void intrusive_list::splice(iterator pos, - intrusive_list& other, - iterator first, - iterator last) { - while (first != last) - insert(pos, other.extract(first++)); -} - -} // namespace wabt - -#endif // WABT_INTRUSIVE_LIST_H_ diff --git a/include/wabt/ir.h b/include/wabt/ir.h index 49b7e2b04..7413555c6 100644 --- a/include/wabt/ir.h +++ b/include/wabt/ir.h @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -28,7 +29,6 @@ #include "wabt/binding-hash.h" #include "wabt/common.h" -#include "wabt/intrusive-list.h" #include "wabt/opcode.h" namespace wabt { @@ -432,7 +432,8 @@ enum class ExprType { const char* GetExprTypeName(ExprType type); class Expr; -using ExprList = intrusive_list; + +using ExprList = std::vector>; using BlockDeclaration = FuncDeclaration; @@ -456,12 +457,14 @@ struct Catch { bool IsCatchAll() const { return var.is_index() && var.index() == kInvalidIndex; } + Catch(Catch&&) = default; + Catch& operator=(Catch&&) = default; }; using CatchVector = std::vector; enum class TryKind { Plain, Catch, Delegate }; -class Expr : public intrusive_list_base { +class Expr { public: WABT_DISALLOW_COPY_AND_ASSIGN(Expr); Expr() = delete; @@ -1046,7 +1049,7 @@ enum class ModuleFieldType { Tag }; -class ModuleField : public intrusive_list_base { +class ModuleField { public: WABT_DISALLOW_COPY_AND_ASSIGN(ModuleField); ModuleField() = delete; @@ -1063,7 +1066,7 @@ class ModuleField : public intrusive_list_base { ModuleFieldType type_; }; -using ModuleFieldList = intrusive_list; +using ModuleFieldList = std::list>; template class ModuleFieldMixin : public ModuleField { diff --git a/include/wabt/wast-parser.h b/include/wabt/wast-parser.h index 36447c586..5189313d6 100644 --- a/include/wabt/wast-parser.h +++ b/include/wabt/wast-parser.h @@ -24,7 +24,6 @@ #include "wabt/error.h" #include "wabt/feature.h" -#include "wabt/intrusive-list.h" #include "wabt/ir.h" #include "wabt/wast-lexer.h" diff --git a/src/apply-names.cc b/src/apply-names.cc index 6d531be25..922689b20 100644 --- a/src/apply-names.cc +++ b/src/apply-names.cc @@ -531,7 +531,7 @@ Result NameApplier::VisitElemSegment(Index elem_segment_index, CHECK_RESULT(UseNameForTableVar(&segment->table_var)); CHECK_RESULT(visitor_.VisitExprList(segment->offset)); for (ExprList& elem_expr : segment->elem_exprs) { - Expr* expr = &elem_expr.front(); + Expr* expr = elem_expr.front().get(); if (expr->type() == ExprType::RefFunc) { CHECK_RESULT(UseNameForFuncVar(&cast(expr)->var)); } diff --git a/src/binary-reader-ir.cc b/src/binary-reader-ir.cc index 82500b93f..425caadd5 100644 --- a/src/binary-reader-ir.cc +++ b/src/binary-reader-ir.cc @@ -456,7 +456,7 @@ Result BinaryReaderIR::TopLabelExpr(LabelNode** label, Expr** expr) { PrintError("TopLabelExpr: parent label has empty expr list"); return Result::Error; } - *expr = &parent_label->exprs->back(); + *expr = parent_label->exprs->back().get(); return Result::Ok; } diff --git a/src/binary-writer.cc b/src/binary-writer.cc index 19443a44a..356406be2 100644 --- a/src/binary-writer.cc +++ b/src/binary-writer.cc @@ -1124,8 +1124,8 @@ void BinaryWriter::WriteExpr(const Func* func, const Expr* expr) { } void BinaryWriter::WriteExprList(const Func* func, const ExprList& exprs) { - for (const Expr& expr : exprs) { - WriteExpr(func, &expr); + for (const auto& expr : exprs) { + WriteExpr(func, expr.get()); } } @@ -1562,7 +1562,7 @@ Result BinaryWriter::WriteModule() { } else { for (const ExprList& elem_expr : segment->elem_exprs) { assert(elem_expr.size() == 1); - const Expr* expr = &elem_expr.front(); + const Expr* expr = elem_expr.front().get(); assert(expr->type() == ExprType::RefFunc); WriteU32Leb128(stream_, module_->GetFuncIndex(cast(expr)->var), diff --git a/src/c-writer.cc b/src/c-writer.cc index 0a7cfe3a0..a2b297fc4 100644 --- a/src/c-writer.cc +++ b/src/c-writer.cc @@ -1336,14 +1336,14 @@ void CWriter::WriteInitExpr(const ExprList& expr_list) { std::vector mini_stack; for (const auto& expr : expr_list) { - if (expr.type() == ExprType::Binary) { + if (expr->type() == ExprType::Binary) { // Extended const expressions include at least one binary op. // This builds a C expression from the operands. if (mini_stack.size() < 2) { WABT_UNREACHABLE; } - const auto binexpr = cast(&expr); + const auto binexpr = cast(expr.get()); char op; switch (binexpr->opcode) { case Opcode::I32Add: @@ -1383,7 +1383,7 @@ void CWriter::WriteInitExpr(const ExprList& expr_list) { Stream* existing_stream = stream_; MemoryStream terminal_stream; stream_ = &terminal_stream; - WriteInitExprTerminal(&expr); + WriteInitExprTerminal(expr.get()); const auto& buf = terminal_stream.output_buffer(); mini_stack.emplace_back(reinterpret_cast(buf.data.data()), buf.data.size()); @@ -2271,7 +2271,7 @@ void CWriter::WriteElemInitializers() { for (const ExprList& elem_expr : elem_segment->elem_exprs) { assert(elem_expr.size() == 1); - const Expr& expr = elem_expr.front(); + const Expr& expr = *elem_expr.front(); switch (expr.type()) { case ExprType::RefFunc: { const Func* func = module_->GetFunc(cast(&expr)->var); @@ -3295,7 +3295,8 @@ void CWriter::WriteTryDelegate(const TryExpr& tryexpr) { } void CWriter::Write(const ExprList& exprs) { - for (const Expr& expr : exprs) { + for (const auto& expr_ptr : exprs) { + const Expr& expr = *expr_ptr; switch (expr.type()) { case ExprType::Binary: Write(*cast(&expr)); @@ -3868,7 +3869,10 @@ void CWriter::Write(const ExprList& exprs) { if (!IsImport(func.name) && !func.features_used.tailcall) { // make normal call, then return - Write(ExprList{std::make_unique(inst->var, inst->loc)}); + auto expr = std::make_unique(inst->var, inst->loc); + ExprList expr_list; + expr_list.push_back(std::move(expr)); + Write(expr_list); Write("goto ", LabelName(kImplicitFuncLabel), ";", Newline()); return; } @@ -3918,7 +3922,9 @@ void CWriter::Write(const ExprList& exprs) { ".data[", StackVar(0), "].func_tailcallee.fn) ", OpenBrace()); auto ci = std::make_unique(inst->loc); std::tie(ci->decl, ci->table) = std::make_pair(inst->decl, inst->table); - Write(ExprList{std::move(ci)}); + ExprList expr_list; + expr_list.push_back(std::move(ci)); + Write(expr_list); if (in_tail_callee_) { Write("next->fn = NULL;", Newline()); } diff --git a/src/decompiler.cc b/src/decompiler.cc index 3eab2dd0b..b6db057c0 100644 --- a/src/decompiler.cc +++ b/src/decompiler.cc @@ -288,7 +288,7 @@ struct Decompiler { for (auto dat : mc.module.data_segments) { uint64_t dat_base; if (dat->offset.size() == 1 && - ConstIntVal(&dat->offset.front(), dat_base) && + ConstIntVal(dat->offset.front().get(), dat_base) && abs_base >= dat_base && abs_base < dat_base + dat->data.size()) { // We are inside the range of this data segment! // Turn expression into data_name[index] diff --git a/src/expr-visitor.cc b/src/expr-visitor.cc index 05cd2798c..e6169b566 100644 --- a/src/expr-visitor.cc +++ b/src/expr-visitor.cc @@ -45,7 +45,8 @@ Result ExprVisitor::VisitExpr(Expr* root_expr) { auto block_expr = cast(expr); auto& iter = expr_iter_stack_.back(); if (iter != block_expr->block.exprs.end()) { - PushDefault(&*iter++); + PushDefault(iter->get()); + ++iter; } else { CHECK_RESULT(delegate_->EndBlockExpr(block_expr)); PopExprlist(); @@ -57,7 +58,8 @@ Result ExprVisitor::VisitExpr(Expr* root_expr) { auto if_expr = cast(expr); auto& iter = expr_iter_stack_.back(); if (iter != if_expr->true_.exprs.end()) { - PushDefault(&*iter++); + PushDefault(iter->get()); + ++iter; } else { CHECK_RESULT(delegate_->AfterIfTrueExpr(if_expr)); PopExprlist(); @@ -70,7 +72,8 @@ Result ExprVisitor::VisitExpr(Expr* root_expr) { auto if_expr = cast(expr); auto& iter = expr_iter_stack_.back(); if (iter != if_expr->false_.end()) { - PushDefault(&*iter++); + PushDefault(iter->get()); + ++iter; } else { CHECK_RESULT(delegate_->EndIfExpr(if_expr)); PopExprlist(); @@ -82,7 +85,8 @@ Result ExprVisitor::VisitExpr(Expr* root_expr) { auto loop_expr = cast(expr); auto& iter = expr_iter_stack_.back(); if (iter != loop_expr->block.exprs.end()) { - PushDefault(&*iter++); + PushDefault(iter->get()); + ++iter; } else { CHECK_RESULT(delegate_->EndLoopExpr(loop_expr)); PopExprlist(); @@ -94,7 +98,8 @@ Result ExprVisitor::VisitExpr(Expr* root_expr) { auto try_expr = cast(expr); auto& iter = expr_iter_stack_.back(); if (iter != try_expr->block.exprs.end()) { - PushDefault(&*iter++); + PushDefault(iter->get()); + ++iter; } else { PopExprlist(); switch (try_expr->kind) { @@ -123,7 +128,8 @@ Result ExprVisitor::VisitExpr(Expr* root_expr) { Index catch_index = catch_index_stack_.back(); auto& iter = expr_iter_stack_.back(); if (iter != try_expr->catches[catch_index].exprs.end()) { - PushDefault(&*iter++); + PushDefault(iter->get()); + ++iter; } else { PopCatch(); catch_index++; @@ -144,8 +150,8 @@ Result ExprVisitor::VisitExpr(Expr* root_expr) { } Result ExprVisitor::VisitExprList(ExprList& exprs) { - for (Expr& expr : exprs) - CHECK_RESULT(VisitExpr(&expr)); + for (auto& expr : exprs) + CHECK_RESULT(VisitExpr(expr.get())); return Result::Ok; } diff --git a/src/ir.cc b/src/ir.cc index 88db7d5f4..732e91cb0 100644 --- a/src/ir.cc +++ b/src/ir.cc @@ -543,8 +543,9 @@ void Module::AppendField(std::unique_ptr field) { } void Module::AppendFields(ModuleFieldList* fields) { - while (!fields->empty()) - AppendField(std::unique_ptr(fields->extract_front())); + for (auto& field : *fields) { + AppendField(std::move(field)); + } } const Module* Script::GetFirstModule() const { @@ -673,7 +674,7 @@ uint8_t ElemSegment::GetFlags(const Module* module) const { elem_type == Type::FuncRef && std::all_of(elem_exprs.begin(), elem_exprs.end(), [](const ExprList& elem_expr) { - return elem_expr.front().type() == ExprType::RefFunc; + return elem_expr.front()->type() == ExprType::RefFunc; }); if (!all_ref_func) { diff --git a/src/resolve-names.cc b/src/resolve-names.cc index 9fc8e4430..8c5f4b7ee 100644 --- a/src/resolve-names.cc +++ b/src/resolve-names.cc @@ -538,8 +538,8 @@ void NameResolver::VisitElemSegment(ElemSegment* segment) { visitor_.VisitExprList(segment->offset); for (ExprList& elem_expr : segment->elem_exprs) { if (elem_expr.size() == 1 && - elem_expr.front().type() == ExprType::RefFunc) { - ResolveFuncVar(&cast(&elem_expr.front())->var); + elem_expr.front()->type() == ExprType::RefFunc) { + ResolveFuncVar(&cast(elem_expr.front().get())->var); } } } diff --git a/src/test-intrusive-list.cc b/src/test-intrusive-list.cc deleted file mode 100644 index 25059caba..000000000 --- a/src/test-intrusive-list.cc +++ /dev/null @@ -1,583 +0,0 @@ -/* - * Copyright 2017 WebAssembly Community Group participants - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "gtest/gtest.h" - -#include - -#include "wabt/intrusive-list.h" - -using namespace wabt; - -namespace { - -struct TestObject : intrusive_list_base { - static int creation_count; - - TestObject(int data = 0, int data2 = 0) : data(data), data2(data2) { - ++creation_count; - } - - // Allow move. - TestObject(TestObject&& other) { - // Don't increment creation_count; we're moving from other. - *this = std::move(other); - } - - TestObject& operator=(TestObject&& other) { - data = other.data; - data2 = other.data2; - other.moved = true; - return *this; - } - - // Disallow copy. - TestObject(const TestObject&) = delete; - TestObject& operator=(const TestObject&) = delete; - - ~TestObject() { - if (!moved) { - creation_count--; - } - } - - int data; - int data2; - bool moved = false; -}; - -// static -int TestObject::creation_count = 0; - -using TestObjectList = intrusive_list; - -class IntrusiveListTest : public ::testing::Test { - protected: - virtual void SetUp() { - // Reset to 0 even if the previous test leaked objects to keep the tests - // independent. - TestObject::creation_count = 0; - } - - virtual void TearDown() { ASSERT_EQ(0, TestObject::creation_count); } - - TestObjectList NewList(const std::vector& data_values) { - TestObjectList result; - for (auto data_value : data_values) - result.emplace_back(data_value); - return result; - } - - void AssertListEq(const TestObjectList& list, - const std::vector& expected) { - size_t count = 0; - for (const TestObject& node : list) { - ASSERT_EQ(expected[count++], node.data); - } - ASSERT_EQ(count, expected.size()); - } - - void AssertListEq(const TestObjectList& list, - const std::vector& expected, - const std::vector& expected2) { - assert(expected.size() == expected2.size()); - size_t count = 0; - for (const TestObject& node : list) { - ASSERT_EQ(expected[count], node.data); - ASSERT_EQ(expected2[count], node.data2); - count++; - } - ASSERT_EQ(count, expected.size()); - } -}; - -} // end anonymous namespace - -TEST_F(IntrusiveListTest, default_constructor) { - TestObjectList list; -} - -TEST_F(IntrusiveListTest, node_constructor) { - TestObjectList list(std::make_unique(1)); - AssertListEq(list, {1}); -} - -TEST_F(IntrusiveListTest, node_move_constructor) { - TestObjectList list(TestObject(1)); - AssertListEq(list, {1}); -} - -TEST_F(IntrusiveListTest, move_constructor) { - TestObjectList list1 = NewList({1, 2, 3}); - TestObjectList list2(std::move(list1)); - AssertListEq(list1, {}); - AssertListEq(list2, {1, 2, 3}); -} - -TEST_F(IntrusiveListTest, move_assignment_operator) { - TestObjectList list1 = NewList({1, 2, 3}); - TestObjectList list2; - - list2 = std::move(list1); - AssertListEq(list1, {}); - AssertListEq(list2, {1, 2, 3}); -} - -namespace { - -class IntrusiveListIteratorTest : public IntrusiveListTest { - protected: - virtual void SetUp() { - IntrusiveListTest::SetUp(); - - list_.emplace_back(1); - list_.emplace_back(2); - list_.emplace_back(3); - } - - virtual void TearDown() { - list_.clear(); - - IntrusiveListTest::TearDown(); - } - - template - void TestForward(Iter first, Iter last, const std::vector& expected) { - size_t count = 0; - while (first != last) { - ASSERT_EQ(expected[count], first->data); - ++first; - ++count; - } - ASSERT_EQ(count, expected.size()); - } - - template - void TestBackward(Iter first, Iter last, const std::vector& expected) { - size_t count = 0; - while (first != last) { - --last; - ASSERT_EQ(expected[count], last->data); - ++count; - } - ASSERT_EQ(count, expected.size()); - } - - TestObjectList list_; - const TestObjectList& clist_ = list_; -}; - -} // end of anonymous namespace - -TEST_F(IntrusiveListIteratorTest, begin_end_forward) { - TestForward(list_.begin(), list_.end(), {1, 2, 3}); - TestForward(clist_.begin(), clist_.end(), {1, 2, 3}); -} - -TEST_F(IntrusiveListIteratorTest, rbegin_rend_forward) { - TestForward(list_.rbegin(), list_.rend(), {3, 2, 1}); - TestForward(clist_.rbegin(), clist_.rend(), {3, 2, 1}); -} - -TEST_F(IntrusiveListIteratorTest, cbegin_cend_forward) { - TestForward(list_.cbegin(), list_.cend(), {1, 2, 3}); - TestForward(clist_.cbegin(), clist_.cend(), {1, 2, 3}); -} - -TEST_F(IntrusiveListIteratorTest, crbegin_crend_forward) { - TestForward(list_.crbegin(), list_.crend(), {3, 2, 1}); - TestForward(clist_.crbegin(), clist_.crend(), {3, 2, 1}); -} - -TEST_F(IntrusiveListIteratorTest, begin_end_backward) { - TestBackward(list_.begin(), list_.end(), {3, 2, 1}); - TestBackward(clist_.begin(), clist_.end(), {3, 2, 1}); -} - -TEST_F(IntrusiveListIteratorTest, rbegin_rend_backward) { - TestBackward(list_.rbegin(), list_.rend(), {1, 2, 3}); - TestBackward(clist_.rbegin(), clist_.rend(), {1, 2, 3}); -} - -TEST_F(IntrusiveListIteratorTest, cbegin_cend_backward) { - TestBackward(list_.cbegin(), list_.cend(), {3, 2, 1}); - TestBackward(clist_.cbegin(), clist_.cend(), {3, 2, 1}); -} - -TEST_F(IntrusiveListIteratorTest, crbegin_crend_backward) { - TestBackward(list_.crbegin(), list_.crend(), {1, 2, 3}); - TestBackward(clist_.crbegin(), clist_.crend(), {1, 2, 3}); -} - -TEST_F(IntrusiveListTest, size_empty) { - TestObjectList list; - ASSERT_EQ(0U, list.size()); - ASSERT_TRUE(list.empty()); - - list.emplace_back(1); - ASSERT_EQ(1U, list.size()); - ASSERT_FALSE(list.empty()); -} - -TEST_F(IntrusiveListTest, front_back) { - TestObjectList list; - - list.emplace_back(1); - ASSERT_EQ(1, list.front().data); - ASSERT_EQ(1, list.back().data); - - list.emplace_back(2); - ASSERT_EQ(1, list.front().data); - ASSERT_EQ(2, list.back().data); - - const TestObjectList& clist = list; - ASSERT_EQ(1, clist.front().data); - ASSERT_EQ(2, clist.back().data); -} - -TEST_F(IntrusiveListTest, emplace_front) { - TestObjectList list; - - // Pass an additional arg to show that forwarding works properly. - list.emplace_front(1, 100); - list.emplace_front(2, 200); - list.emplace_front(3, 300); - list.emplace_front(4, 400); - - AssertListEq(list, {4, 3, 2, 1}, {400, 300, 200, 100}); -} - -TEST_F(IntrusiveListTest, emplace_back) { - TestObjectList list; - - // Pass an additional arg to show that forwarding works properly. - list.emplace_back(1, 100); - list.emplace_back(2, 200); - list.emplace_back(3, 300); - list.emplace_back(4, 400); - - AssertListEq(list, {1, 2, 3, 4}, {100, 200, 300, 400}); -} - -TEST_F(IntrusiveListTest, push_front_pointer) { - TestObjectList list; - - list.push_front(std::make_unique(1)); - list.push_front(std::make_unique(2)); - list.push_front(std::make_unique(3)); - - AssertListEq(list, {3, 2, 1}); -} - -TEST_F(IntrusiveListTest, push_back_pointer) { - TestObjectList list; - - list.push_back(std::make_unique(1)); - list.push_back(std::make_unique(2)); - list.push_back(std::make_unique(3)); - - AssertListEq(list, {1, 2, 3}); -} - -TEST_F(IntrusiveListTest, push_front_move) { - TestObjectList list; - - list.push_front(TestObject(1)); - list.push_front(TestObject(2)); - list.push_front(TestObject(3)); - - AssertListEq(list, {3, 2, 1}); -} - -TEST_F(IntrusiveListTest, push_back_move) { - TestObjectList list; - - list.push_back(TestObject(1)); - list.push_back(TestObject(2)); - list.push_back(TestObject(3)); - - AssertListEq(list, {1, 2, 3}); -} - -TEST_F(IntrusiveListTest, pop_front) { - TestObjectList list = NewList({1, 2, 3, 4}); - - list.pop_front(); - AssertListEq(list, {2, 3, 4}); - list.pop_front(); - AssertListEq(list, {3, 4}); - list.pop_front(); - AssertListEq(list, {4}); - list.pop_front(); - AssertListEq(list, {}); -} - -TEST_F(IntrusiveListTest, pop_back) { - TestObjectList list = NewList({1, 2, 3, 4}); - - list.pop_back(); - AssertListEq(list, {1, 2, 3}); - list.pop_back(); - AssertListEq(list, {1, 2}); - list.pop_back(); - AssertListEq(list, {1}); - list.pop_back(); - AssertListEq(list, {}); -} - -TEST_F(IntrusiveListTest, extract_front) { - TestObjectList list = NewList({1, 2, 3}); - - std::unique_ptr t1(list.extract_front()); - ASSERT_EQ(1, t1->data); - AssertListEq(list, {2, 3}); - - std::unique_ptr t2(list.extract_front()); - ASSERT_EQ(2, t2->data); - AssertListEq(list, {3}); - - std::unique_ptr t3(list.extract_front()); - ASSERT_EQ(3, t3->data); - AssertListEq(list, {}); -} - -TEST_F(IntrusiveListTest, extract_back) { - TestObjectList list = NewList({1, 2, 3}); - - std::unique_ptr t1(list.extract_back()); - ASSERT_EQ(3, t1->data); - AssertListEq(list, {1, 2}); - - std::unique_ptr t2(list.extract_back()); - ASSERT_EQ(2, t2->data); - AssertListEq(list, {1}); - - std::unique_ptr t3(list.extract_back()); - ASSERT_EQ(1, t3->data); - AssertListEq(list, {}); -} - -TEST_F(IntrusiveListTest, emplace) { - TestObjectList list; - - // Pass an additional arg to show that forwarding works properly. - list.emplace(list.begin(), 2, 200); - list.emplace(list.end(), 4, 400); - list.emplace(std::next(list.begin()), 3, 300); - list.emplace(list.begin(), 1, 100); - - AssertListEq(list, {1, 2, 3, 4}, {100, 200, 300, 400}); -} - -TEST_F(IntrusiveListTest, insert_pointer) { - TestObjectList list; - - list.insert(list.begin(), std::make_unique(2)); - list.insert(list.end(), std::make_unique(4)); - list.insert(std::next(list.begin()), std::make_unique(3)); - list.insert(list.begin(), std::make_unique(1)); - - AssertListEq(list, {1, 2, 3, 4}); -} - -TEST_F(IntrusiveListTest, insert_move) { - TestObjectList list; - - list.insert(list.begin(), TestObject(2)); - list.insert(list.end(), TestObject(4)); - list.insert(std::next(list.begin()), TestObject(3)); - list.insert(list.begin(), TestObject(1)); - - AssertListEq(list, {1, 2, 3, 4}); -} - -TEST_F(IntrusiveListTest, extract) { - TestObjectList list = NewList({1, 2, 3, 4}); - - TestObjectList::iterator t1_iter = std::next(list.begin(), 0); - TestObjectList::iterator t2_iter = std::next(list.begin(), 1); - TestObjectList::iterator t3_iter = std::next(list.begin(), 2); - TestObjectList::iterator t4_iter = std::next(list.begin(), 3); - - std::unique_ptr t2(list.extract(t2_iter)); - ASSERT_EQ(2, t2->data); - AssertListEq(list, {1, 3, 4}); - - std::unique_ptr t4(list.extract(t4_iter)); - ASSERT_EQ(4, t4->data); - AssertListEq(list, {1, 3}); - - std::unique_ptr t1(list.extract(t1_iter)); - ASSERT_EQ(1, t1->data); - AssertListEq(list, {3}); - - std::unique_ptr t3(list.extract(t3_iter)); - ASSERT_EQ(3, t3->data); - AssertListEq(list, {}); -} - -TEST_F(IntrusiveListTest, erase) { - TestObjectList list = NewList({1, 2, 3, 4}); - - TestObjectList::iterator t1_iter = std::next(list.begin(), 0); - TestObjectList::iterator t2_iter = std::next(list.begin(), 1); - TestObjectList::iterator t3_iter = std::next(list.begin(), 2); - TestObjectList::iterator t4_iter = std::next(list.begin(), 3); - - // erase returns an iterator to the following node. - ASSERT_EQ(3, list.erase(t2_iter)->data); - AssertListEq(list, {1, 3, 4}); - - ASSERT_EQ(list.end(), list.erase(t4_iter)); - AssertListEq(list, {1, 3}); - - ASSERT_EQ(3, list.erase(t1_iter)->data); - AssertListEq(list, {3}); - - ASSERT_EQ(list.end(), list.erase(t3_iter)); - AssertListEq(list, {}); -} - -TEST_F(IntrusiveListTest, erase_range) { - TestObjectList list = NewList({1, 2, 3, 4, 5, 6}); - - // OK to erase an empty range. - list.erase(list.begin(), list.begin()); - list.erase(list.end(), list.end()); - - // Erase the first element (1). - list.erase(list.begin(), std::next(list.begin())); - AssertListEq(list, {2, 3, 4, 5, 6}); - - // Erase the last element (6). - list.erase(std::prev(list.end()), list.end()); - AssertListEq(list, {2, 3, 4, 5}); - - // Erase [3, 4] => [2, 5] - list.erase(std::next(list.begin()), std::prev(list.end())); - AssertListEq(list, {2, 5}); - - // Erase the rest. - list.erase(list.begin(), list.end()); - AssertListEq(list, {}); -} - -TEST_F(IntrusiveListTest, swap) { - TestObjectList list1 = NewList({1, 2, 3, 4}); - - TestObjectList list2 = NewList({100, 200, 300}); - - AssertListEq(list1, {1, 2, 3, 4}); - AssertListEq(list2, {100, 200, 300}); - - list1.swap(list2); - - AssertListEq(list1, {100, 200, 300}); - AssertListEq(list2, {1, 2, 3, 4}); -} - -TEST_F(IntrusiveListTest, clear) { - TestObjectList list = NewList({1, 2, 3, 4}); - - ASSERT_FALSE(list.empty()); - - list.clear(); - - ASSERT_EQ(0U, list.size()); - ASSERT_TRUE(list.empty()); -} - -TEST_F(IntrusiveListTest, splice_list) { - TestObjectList list1 = NewList({1, 2, 3}); - - // Splice at beginning. - TestObjectList list2 = NewList({100, 200}); - list1.splice(list1.begin(), list2); - AssertListEq(list1, {100, 200, 1, 2, 3}); - AssertListEq(list2, {}); - - // Splice at end. - TestObjectList list3 = NewList({500, 600, 700}); - list1.splice(list1.end(), list3); - AssertListEq(list1, {100, 200, 1, 2, 3, 500, 600, 700}); - AssertListEq(list3, {}); - - // Splice in the middle. - TestObjectList list4 = NewList({400}); - list1.splice(std::next(list1.begin(), 4), list4); - AssertListEq(list1, {100, 200, 1, 2, 400, 3, 500, 600, 700}); - AssertListEq(list4, {}); -} - -TEST_F(IntrusiveListTest, splice_list_move) { - TestObjectList list1 = NewList({1, 2, 3}); - - // Splice at beginning. - list1.splice(list1.begin(), NewList({100, 200})); - AssertListEq(list1, {100, 200, 1, 2, 3}); - - // Splice at end. - list1.splice(list1.end(), NewList({500, 600, 700})); - AssertListEq(list1, {100, 200, 1, 2, 3, 500, 600, 700}); - - // Splice in the middle. - list1.splice(std::next(list1.begin(), 4), NewList({400})); - AssertListEq(list1, {100, 200, 1, 2, 400, 3, 500, 600, 700}); -} - -TEST_F(IntrusiveListTest, splice_node) { - TestObjectList list1 = NewList({1, 2, 3}); - - // Splice at beginning. - TestObjectList list2 = NewList({100, 200}); - list1.splice(list1.begin(), list2, list2.begin()); - AssertListEq(list1, {100, 1, 2, 3}); - AssertListEq(list2, {200}); - - // Splice at end. - TestObjectList list3 = NewList({500, 600, 700}); - list1.splice(list1.end(), list3, std::next(list3.begin(), 2)); - AssertListEq(list1, {100, 1, 2, 3, 700}); - AssertListEq(list3, {500, 600}); - - // Splice in the middle. - TestObjectList list4 = NewList({400}); - list1.splice(std::next(list1.begin(), 3), list4, list4.begin()); - AssertListEq(list1, {100, 1, 2, 400, 3, 700}); - AssertListEq(list4, {}); -} - -TEST_F(IntrusiveListTest, splice_range) { - TestObjectList list1 = NewList({1, 2, 3}); - - // Splice at beginning. - TestObjectList list2 = NewList({100, 200, 300}); - list1.splice(list1.begin(), list2, list2.begin(), std::prev(list2.end())); - AssertListEq(list1, {100, 200, 1, 2, 3}); - AssertListEq(list2, {300}); - - // Splice at end. - TestObjectList list3 = NewList({500, 600, 700}); - list1.splice(list1.end(), list3, std::next(list3.begin()), list3.end()); - AssertListEq(list1, {100, 200, 1, 2, 3, 600, 700}); - AssertListEq(list3, {500}); - - // Splice in the middle. - TestObjectList list4 = NewList({400}); - list1.splice(std::next(list1.begin(), 4), list4, list4.begin(), list4.end()); - AssertListEq(list1, {100, 200, 1, 2, 400, 3, 600, 700}); - AssertListEq(list4, {}); -} diff --git a/src/validator.cc b/src/validator.cc index dbf3914de..9cc4af163 100644 --- a/src/validator.cc +++ b/src/validator.cc @@ -676,13 +676,13 @@ Result Validator::CheckModule() { const Module* module = current_module_; // Type section. - for (const ModuleField& field : module->fields) { - if (auto* f = dyn_cast(&field)) { + for (const auto& field : module->fields) { + if (auto* f = dyn_cast(field.get())) { switch (f->type->kind()) { case TypeEntryKind::Func: { FuncType* func_type = cast(f->type.get()); result_ |= validator_.OnFuncType( - field.loc, func_type->sig.param_types.size(), + field->loc, func_type->sig.param_types.size(), func_type->sig.param_types.data(), func_type->sig.result_types.size(), func_type->sig.result_types.data(), @@ -696,7 +696,7 @@ Result Validator::CheckModule() { for (auto&& field : struct_type->fields) { type_muts.push_back(TypeMut{field.type, field.mutable_}); } - result_ |= validator_.OnStructType(field.loc, type_muts.size(), + result_ |= validator_.OnStructType(field->loc, type_muts.size(), type_muts.data()); break; } @@ -704,7 +704,7 @@ Result Validator::CheckModule() { case TypeEntryKind::Array: { ArrayType* array_type = cast(f->type.get()); result_ |= validator_.OnArrayType( - field.loc, + field->loc, TypeMut{array_type->field.type, array_type->field.mutable_}); break; } @@ -713,40 +713,40 @@ Result Validator::CheckModule() { } // Import section. - for (const ModuleField& field : module->fields) { - if (auto* f = dyn_cast(&field)) { + for (const auto& field : module->fields) { + if (auto* f = dyn_cast(field.get())) { switch (f->import->kind()) { case ExternalKind::Func: { auto&& func = cast(f->import.get())->func; result_ |= validator_.OnFunction( - field.loc, GetFuncTypeIndex(field.loc, func.decl)); + field->loc, GetFuncTypeIndex(field->loc, func.decl)); break; } case ExternalKind::Table: { auto&& table = cast(f->import.get())->table; - result_ |= - validator_.OnTable(field.loc, table.elem_type, table.elem_limits); + result_ |= validator_.OnTable(field->loc, table.elem_type, + table.elem_limits); break; } case ExternalKind::Memory: { auto&& memory = cast(f->import.get())->memory; - result_ |= validator_.OnMemory(field.loc, memory.page_limits); + result_ |= validator_.OnMemory(field->loc, memory.page_limits); break; } case ExternalKind::Global: { auto&& global = cast(f->import.get())->global; - result_ |= validator_.OnGlobalImport(field.loc, global.type, + result_ |= validator_.OnGlobalImport(field->loc, global.type, global.mutable_); break; } case ExternalKind::Tag: { auto&& tag = cast(f->import.get())->tag; - result_ |= validator_.OnTag(field.loc, - GetFuncTypeIndex(field.loc, tag.decl)); + result_ |= validator_.OnTag(field->loc, + GetFuncTypeIndex(field->loc, tag.decl)); break; } } @@ -754,36 +754,36 @@ Result Validator::CheckModule() { } // Func section. - for (const ModuleField& field : module->fields) { - if (auto* f = dyn_cast(&field)) { + for (const auto& field : module->fields) { + if (auto* f = dyn_cast(field.get())) { result_ |= validator_.OnFunction( - field.loc, GetFuncTypeIndex(field.loc, f->func.decl)); + field->loc, GetFuncTypeIndex(field->loc, f->func.decl)); } } // Table section. - for (const ModuleField& field : module->fields) { - if (auto* f = dyn_cast(&field)) { - result_ |= validator_.OnTable(field.loc, f->table.elem_type, + for (const auto& field : module->fields) { + if (auto* f = dyn_cast(field.get())) { + result_ |= validator_.OnTable(field->loc, f->table.elem_type, f->table.elem_limits); } } // Memory section. - for (const ModuleField& field : module->fields) { - if (auto* f = dyn_cast(&field)) { - result_ |= validator_.OnMemory(field.loc, f->memory.page_limits); + for (const auto& field : module->fields) { + if (auto* f = dyn_cast(field.get())) { + result_ |= validator_.OnMemory(field->loc, f->memory.page_limits); } } // Global section. - for (const ModuleField& field : module->fields) { - if (auto* f = dyn_cast(&field)) { + for (const auto& field : module->fields) { + if (auto* f = dyn_cast(field.get())) { result_ |= - validator_.OnGlobal(field.loc, f->global.type, f->global.mutable_); + validator_.OnGlobal(field->loc, f->global.type, f->global.mutable_); // Init expr. - result_ |= validator_.BeginInitExpr(field.loc, f->global.type); + result_ |= validator_.BeginInitExpr(field->loc, f->global.type); ExprVisitor visitor(this); result_ |= visitor.VisitExprList(const_cast(f->global.init_expr)); @@ -792,40 +792,40 @@ Result Validator::CheckModule() { } // Tag section. - for (const ModuleField& field : module->fields) { - if (auto* f = dyn_cast(&field)) { - result_ |= - validator_.OnTag(field.loc, GetFuncTypeIndex(field.loc, f->tag.decl)); + for (const auto& field : module->fields) { + if (auto* f = dyn_cast(field.get())) { + result_ |= validator_.OnTag(field->loc, + GetFuncTypeIndex(field->loc, f->tag.decl)); } } // Export section. - for (const ModuleField& field : module->fields) { - if (auto* f = dyn_cast(&field)) { - result_ |= validator_.OnExport(field.loc, f->export_.kind, f->export_.var, - f->export_.name); + for (const auto& field : module->fields) { + if (auto* f = dyn_cast(field.get())) { + result_ |= validator_.OnExport(field->loc, f->export_.kind, + f->export_.var, f->export_.name); } } // Start section. - for (const ModuleField& field : module->fields) { - if (auto* f = dyn_cast(&field)) { - result_ |= validator_.OnStart(field.loc, f->start); + for (const auto& field : module->fields) { + if (auto* f = dyn_cast(field.get())) { + result_ |= validator_.OnStart(field->loc, f->start); } } // Elem segment section. - for (const ModuleField& field : module->fields) { - if (auto* f = dyn_cast(&field)) { - result_ |= validator_.OnElemSegment(field.loc, f->elem_segment.table_var, + for (const auto& field : module->fields) { + if (auto* f = dyn_cast(field.get())) { + result_ |= validator_.OnElemSegment(field->loc, f->elem_segment.table_var, f->elem_segment.kind); - result_ |= validator_.OnElemSegmentElemType(field.loc, + result_ |= validator_.OnElemSegmentElemType(field->loc, f->elem_segment.elem_type); // Init expr. if (f->elem_segment.kind == SegmentKind::Active) { - result_ |= validator_.BeginInitExpr(field.loc, Type::I32); + result_ |= validator_.BeginInitExpr(field->loc, Type::I32); ExprVisitor visitor(this); result_ |= visitor.VisitExprList( const_cast(f->elem_segment.offset)); @@ -834,7 +834,7 @@ Result Validator::CheckModule() { // Element expr. for (auto&& elem_expr : f->elem_segment.elem_exprs) { - result_ |= validator_.BeginInitExpr(elem_expr.front().loc, + result_ |= validator_.BeginInitExpr(elem_expr.front()->loc, f->elem_segment.elem_type); ExprVisitor visitor(this); result_ |= visitor.VisitExprList(const_cast(elem_expr)); @@ -848,11 +848,11 @@ Result Validator::CheckModule() { // Code section. Index func_index = module->num_func_imports; - for (const ModuleField& field : module->fields) { - if (auto* f = dyn_cast(&field)) { + for (const auto& field : module->fields) { + if (auto* f = dyn_cast(field.get())) { const Location& body_start = f->func.loc; const Location& body_end = - f->func.exprs.empty() ? body_start : f->func.exprs.back().loc; + f->func.exprs.empty() ? body_start : f->func.exprs.back()->loc; result_ |= validator_.BeginFunctionBody(body_start, func_index++); for (auto&& decl : f->func.local_types.decls()) { @@ -866,10 +866,10 @@ Result Validator::CheckModule() { } // Data segment section. - for (const ModuleField& field : module->fields) { - if (auto* f = dyn_cast(&field)) { - result_ |= validator_.OnDataSegment(field.loc, f->data_segment.memory_var, - f->data_segment.kind); + for (const auto& field : module->fields) { + if (auto* f = dyn_cast(field.get())) { + result_ |= validator_.OnDataSegment( + field->loc, f->data_segment.memory_var, f->data_segment.kind); // Init expr. if (f->data_segment.kind == SegmentKind::Active) { @@ -879,7 +879,7 @@ Result Validator::CheckModule() { module->memories[memory_index]->page_limits.is_64) { offset_type = Type::I64; } - result_ |= validator_.BeginInitExpr(field.loc, offset_type); + result_ |= validator_.BeginInitExpr(field->loc, offset_type); ExprVisitor visitor(this); result_ |= visitor.VisitExprList( const_cast(f->data_segment.offset)); diff --git a/src/wast-parser.cc b/src/wast-parser.cc index 5d0306682..36831e00c 100644 --- a/src/wast-parser.cc +++ b/src/wast-parser.cc @@ -16,6 +16,8 @@ #include "wabt/wast-parser.h" +#include + #include "wabt/binary-reader-ir.h" #include "wabt/binary-reader.h" #include "wabt/cast.h" @@ -501,15 +503,15 @@ class ResolveFuncTypesExprVisitorDelegate : public ExprVisitor::DelegateNop { Result ResolveFuncTypes(Module* module, Errors* errors) { Result result = Result::Ok; - for (ModuleField& field : module->fields) { + for (auto& field : module->fields) { Func* func = nullptr; FuncDeclaration* decl = nullptr; - if (auto* func_field = dyn_cast(&field)) { + if (auto* func_field = dyn_cast(field.get())) { func = &func_field->func; decl = &func->decl; - } else if (auto* tag_field = dyn_cast(&field)) { + } else if (auto* tag_field = dyn_cast(field.get())) { decl = &tag_field->tag.decl; - } else if (auto* import_field = dyn_cast(&field)) { + } else if (auto* import_field = dyn_cast(field.get())) { if (auto* func_import = dyn_cast(import_field->import.get())) { // Only check the declaration, not the function itself, since it is an @@ -531,9 +533,9 @@ Result ResolveFuncTypes(Module* module, Errors* errors) { ResolveTypeNames(*module, decl); has_func_type_and_empty_signature = ResolveFuncTypeWithEmptySignature(*module, decl); - ResolveImplicitlyDefinedFunctionType(field.loc, module, *decl); + ResolveImplicitlyDefinedFunctionType(field->loc, module, *decl); result |= - CheckFuncTypeVarMatchesExplicit(field.loc, *module, *decl, errors); + CheckFuncTypeVarMatchesExplicit(field->loc, *module, *decl, errors); } if (func) { @@ -559,10 +561,10 @@ Result ResolveFuncTypes(Module* module, Errors* errors) { void AppendInlineExportFields(Module* module, ModuleFieldList* fields, Index index) { - Location last_field_loc = module->fields.back().loc; + Location last_field_loc = module->fields.back()->loc; - for (ModuleField& field : *fields) { - auto* export_field = cast(&field); + for (auto& field : *fields) { + auto* export_field = cast(field.get()); export_field->export_.var = Var(index, last_field_loc); } @@ -1738,7 +1740,7 @@ Result WastParser::ParseMemoryModuleField(Module* module) { data_segment.memory_var = Var(module->memories.size(), GetLocation()); data_segment.offset.push_back(std::make_unique( field->memory.page_limits.is_64 ? Const::I64(0) : Const::I32(0))); - data_segment.offset.back().loc = loc; + data_segment.offset.back()->loc = loc; ParseTextListOpt(&data_segment.data); EXPECT(Rpar); @@ -1809,7 +1811,7 @@ Result WastParser::ParseTableModuleField(Module* module) { ElemSegment& elem_segment = elem_segment_field->elem_segment; elem_segment.table_var = Var(module->tables.size(), GetLocation()); elem_segment.offset.push_back(std::make_unique(Const::I32(0))); - elem_segment.offset.back().loc = loc; + elem_segment.offset.back()->loc = loc; elem_segment.elem_type = elem_type; // Syntax is either an optional list of var (legacy), or a non-empty list // of elem expr. @@ -1968,19 +1970,14 @@ Result WastParser::ParseResultList( Result WastParser::ParseInstrList(ExprList* exprs) { WABT_TRACE(ParseInstrList); - ExprList new_exprs; while (true) { auto pair = PeekPair(); if (IsInstr(pair)) { - if (Succeeded(ParseInstr(&new_exprs))) { - exprs->splice(exprs->end(), new_exprs); - } else { + if (Failed(ParseInstr(exprs))) { CHECK_RESULT(Synchronize(IsInstr)); } } else if (IsLparAnn(pair)) { - if (Succeeded(ParseCodeMetadataAnnotation(&new_exprs))) { - exprs->splice(exprs->end(), new_exprs); - } else { + if (Failed(ParseCodeMetadataAnnotation(exprs))) { CHECK_RESULT(Synchronize(IsLparAnn)); } } else { @@ -3034,11 +3031,8 @@ Result WastParser::ParseBlock(Block* block) { Result WastParser::ParseExprList(ExprList* exprs) { WABT_TRACE(ParseExprList); - ExprList new_exprs; while (PeekMatchExpr()) { - if (Succeeded(ParseExpr(&new_exprs))) { - exprs->splice(exprs->end(), new_exprs); - } else { + if (Failed(ParseExpr(exprs))) { CHECK_RESULT(Synchronize(IsExpr)); } } @@ -3091,9 +3085,7 @@ Result WastParser::ParseExpr(ExprList* exprs) { CHECK_RESULT(ParseBlockDeclaration(&expr->true_.decl)); if (PeekMatchExpr()) { - ExprList cond; - CHECK_RESULT(ParseExpr(&cond)); - exprs->splice(exprs->end(), cond); + CHECK_RESULT(ParseExpr(exprs)); } if (MatchLpar(TokenType::Then)) { diff --git a/src/wat-writer.cc b/src/wat-writer.cc index 88ff60ba5..2754cdd79 100644 --- a/src/wat-writer.cc +++ b/src/wat-writer.cc @@ -1124,8 +1124,8 @@ void WatWriter::WriteFoldedExpr(const Expr* expr) { void WatWriter::WriteFoldedExprList(const ExprList& exprs) { WABT_TRACE(WriteFoldedExprList); - for (const Expr& expr : exprs) { - WriteFoldedExpr(&expr); + for (const auto& expr : exprs) { + WriteFoldedExpr(expr.get()); } } @@ -1482,8 +1482,9 @@ void WatWriter::WriteElemSegment(const ElemSegment& segment) { WriteInitExpr(expr); } else { assert(expr.size() == 1); - assert(expr.front().type() == ExprType::RefFunc); - WriteVar(cast(&expr.front())->var, NextChar::Space); + assert(expr.front()->type() == ExprType::RefFunc); + WriteVar(cast(expr.front().get())->var, + NextChar::Space); } } WriteCloseNewline(); @@ -1630,40 +1631,42 @@ Result WatWriter::WriteModule() { } else { WriteName(module.name, NextChar::Newline); } - for (const ModuleField& field : module.fields) { - switch (field.type()) { + for (const auto& field : module.fields) { + switch (field->type()) { case ModuleFieldType::Func: - WriteFunc(cast(&field)->func); + WriteFunc(cast(field.get())->func); break; case ModuleFieldType::Global: - WriteGlobal(cast(&field)->global); + WriteGlobal(cast(field.get())->global); break; case ModuleFieldType::Import: - WriteImport(*cast(&field)->import); + WriteImport(*cast(field.get())->import); break; case ModuleFieldType::Tag: - WriteTag(cast(&field)->tag); + WriteTag(cast(field.get())->tag); break; case ModuleFieldType::Export: - WriteExport(cast(&field)->export_); + WriteExport(cast(field.get())->export_); break; case ModuleFieldType::Table: - WriteTable(cast(&field)->table); + WriteTable(cast(field.get())->table); break; case ModuleFieldType::ElemSegment: - WriteElemSegment(cast(&field)->elem_segment); + WriteElemSegment( + cast(field.get())->elem_segment); break; case ModuleFieldType::Memory: - WriteMemory(cast(&field)->memory); + WriteMemory(cast(field.get())->memory); break; case ModuleFieldType::DataSegment: - WriteDataSegment(cast(&field)->data_segment); + WriteDataSegment( + cast(field.get())->data_segment); break; case ModuleFieldType::Type: - WriteTypeEntry(*cast(&field)->type); + WriteTypeEntry(*cast(field.get())->type); break; case ModuleFieldType::Start: - WriteStartFunction(cast(&field)->start); + WriteStartFunction(cast(field.get())->start); break; } }