1// Copyright 2022 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef V8_MAGLEV_MAGLEV_BASIC_BLOCK_H_
6#define V8_MAGLEV_MAGLEV_BASIC_BLOCK_H_
7
8#include <vector>
9
10#include "src/codegen/label.h"
11#include "src/maglev/maglev-interpreter-frame-state.h"
12#include "src/maglev/maglev-ir.h"
13#include "src/zone/zone.h"
14
15namespace v8 {
16namespace internal {
17namespace maglev {
18
19using NodeIterator = Node::List::Iterator;
20using NodeConstIterator = Node::List::Iterator;
21
22class BasicBlock {
23 public:
24  explicit BasicBlock(MergePointInterpreterFrameState* state)
25      : control_node_(nullptr), state_(state) {}
26
27  uint32_t first_id() const {
28    if (has_phi()) return phis()->first()->id();
29    return nodes_.is_empty() ? control_node()->id() : nodes_.first()->id();
30  }
31
32  uint32_t FirstNonGapMoveId() const {
33    if (has_phi()) return phis()->first()->id();
34    if (!nodes_.is_empty()) {
35      for (const Node* node : nodes_) {
36        if (node->Is<GapMove>()) continue;
37        return node->id();
38      }
39    }
40    return control_node()->id();
41  }
42
43  Node::List& nodes() { return nodes_; }
44
45  ControlNode* control_node() const { return control_node_; }
46  void set_control_node(ControlNode* control_node) {
47    DCHECK_NULL(control_node_);
48    control_node_ = control_node;
49  }
50
51  bool has_phi() const { return has_state() && state_->has_phi(); }
52
53  bool is_empty_block() const { return is_empty_block_; }
54
55  BasicBlock* empty_block_predecessor() const {
56    DCHECK(is_empty_block());
57    return empty_block_predecessor_;
58  }
59
60  void set_empty_block_predecessor(BasicBlock* predecessor) {
61    DCHECK(nodes_.is_empty());
62    DCHECK(control_node()->Is<Jump>());
63    DCHECK_NULL(state_);
64    is_empty_block_ = true;
65    empty_block_predecessor_ = predecessor;
66  }
67
68  Phi::List* phis() const {
69    DCHECK(has_phi());
70    return state_->phis();
71  }
72
73  BasicBlock* predecessor_at(int i) const {
74    DCHECK_NOT_NULL(state_);
75    return state_->predecessor_at(i);
76  }
77
78  int predecessor_id() const {
79    return control_node()->Cast<UnconditionalControlNode>()->predecessor_id();
80  }
81  void set_predecessor_id(int id) {
82    control_node()->Cast<UnconditionalControlNode>()->set_predecessor_id(id);
83  }
84
85  Label* label() { return &label_; }
86  MergePointInterpreterFrameState* state() const {
87    DCHECK(has_state());
88    return state_;
89  }
90  bool has_state() const { return state_ != nullptr && !is_empty_block(); }
91
92 private:
93  bool is_empty_block_ = false;
94  Node::List nodes_;
95  ControlNode* control_node_;
96  union {
97    MergePointInterpreterFrameState* state_;
98    BasicBlock* empty_block_predecessor_;
99  };
100  Label label_;
101};
102
103}  // namespace maglev
104}  // namespace internal
105}  // namespace v8
106
107#endif  // V8_MAGLEV_MAGLEV_BASIC_BLOCK_H_
108