summaryrefslogtreecommitdiff
path: root/deps/v8/src/torque/cfg.h
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/torque/cfg.h')
-rw-r--r--deps/v8/src/torque/cfg.h149
1 files changed, 149 insertions, 0 deletions
diff --git a/deps/v8/src/torque/cfg.h b/deps/v8/src/torque/cfg.h
new file mode 100644
index 0000000000..6fca593505
--- /dev/null
+++ b/deps/v8/src/torque/cfg.h
@@ -0,0 +1,149 @@
+// Copyright 2018 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef V8_TORQUE_CFG_H_
+#define V8_TORQUE_CFG_H_
+
+#include <list>
+#include <memory>
+#include <unordered_map>
+#include <vector>
+
+#include "src/torque/ast.h"
+#include "src/torque/instructions.h"
+#include "src/torque/source-positions.h"
+#include "src/torque/types.h"
+
+namespace v8 {
+namespace internal {
+namespace torque {
+
+class Block {
+ public:
+ explicit Block(size_t id, base::Optional<Stack<const Type*>> input_types,
+ bool is_deferred)
+ : input_types_(std::move(input_types)),
+ id_(id),
+ is_deferred_(is_deferred) {}
+ void Add(Instruction instruction) {
+ DCHECK(!IsComplete());
+ instructions_.push_back(std::move(instruction));
+ }
+
+ bool HasInputTypes() const { return input_types_ != base::nullopt; }
+ const Stack<const Type*>& InputTypes() const { return *input_types_; }
+ void SetInputTypes(const Stack<const Type*>& input_types);
+
+ const std::vector<Instruction>& instructions() const { return instructions_; }
+ bool IsComplete() const {
+ return !instructions_.empty() && instructions_.back()->IsBlockTerminator();
+ }
+ size_t id() const { return id_; }
+ bool IsDeferred() const { return is_deferred_; }
+
+ private:
+ std::vector<Instruction> instructions_;
+ base::Optional<Stack<const Type*>> input_types_;
+ const size_t id_;
+ bool is_deferred_;
+};
+
+class ControlFlowGraph {
+ public:
+ explicit ControlFlowGraph(Stack<const Type*> input_types) {
+ start_ = NewBlock(std::move(input_types), false);
+ PlaceBlock(start_);
+ }
+
+ Block* NewBlock(base::Optional<Stack<const Type*>> input_types,
+ bool is_deferred) {
+ blocks_.emplace_back(next_block_id_++, std::move(input_types), is_deferred);
+ return &blocks_.back();
+ }
+ void PlaceBlock(Block* block) { placed_blocks_.push_back(block); }
+ Block* start() const { return start_; }
+ base::Optional<Block*> end() const { return end_; }
+ void set_end(Block* end) { end_ = end; }
+ void SetReturnType(const Type* t) {
+ if (!return_type_) {
+ return_type_ = t;
+ return;
+ }
+ if (t != *return_type_) {
+ ReportError("expected return type ", **return_type_, " instead of ", *t);
+ }
+ }
+ const std::vector<Block*>& blocks() const { return placed_blocks_; }
+
+ private:
+ std::list<Block> blocks_;
+ Block* start_;
+ std::vector<Block*> placed_blocks_;
+ base::Optional<Block*> end_;
+ base::Optional<const Type*> return_type_;
+ size_t next_block_id_ = 0;
+};
+
+class CfgAssembler {
+ public:
+ explicit CfgAssembler(Stack<const Type*> input_types)
+ : current_stack_(std::move(input_types)), cfg_(current_stack_) {}
+
+ const ControlFlowGraph& Result() {
+ if (!CurrentBlockIsComplete()) {
+ cfg_.set_end(current_block_);
+ }
+ return cfg_;
+ }
+
+ Block* NewBlock(
+ base::Optional<Stack<const Type*>> input_types = base::nullopt,
+ bool is_deferred = false) {
+ return cfg_.NewBlock(std::move(input_types), is_deferred);
+ }
+
+ bool CurrentBlockIsComplete() const { return current_block_->IsComplete(); }
+
+ void Emit(Instruction instruction) {
+ instruction.TypeInstruction(&current_stack_, &cfg_);
+ current_block_->Add(std::move(instruction));
+ }
+
+ const Stack<const Type*>& CurrentStack() const { return current_stack_; }
+
+ StackRange TopRange(size_t slot_count) const {
+ return CurrentStack().TopRange(slot_count);
+ }
+
+ void Bind(Block* block);
+ void Goto(Block* block);
+ // Goto block while keeping {preserved_slots} many slots on the top and
+ // deleting additional the slots below these to match the input type of the
+ // target block.
+ // Returns the StackRange of the preserved slots in the target block.
+ StackRange Goto(Block* block, size_t preserved_slots);
+ // The condition must be of type bool and on the top of stack. It is removed
+ // from the stack before branching.
+ void Branch(Block* if_true, Block* if_false);
+ // Delete the specified range of slots, moving upper slots to fill the gap.
+ void DeleteRange(StackRange range);
+ void DropTo(BottomOffset new_level);
+ StackRange Peek(StackRange range, base::Optional<const Type*> type);
+ void Poke(StackRange destination, StackRange origin,
+ base::Optional<const Type*> type);
+ void Print(std::string s);
+ void Unreachable();
+ void DebugBreak();
+
+ private:
+ Stack<const Type*> current_stack_;
+ ControlFlowGraph cfg_;
+ Block* current_block_ = cfg_.start();
+};
+
+} // namespace torque
+} // namespace internal
+} // namespace v8
+
+#endif // V8_TORQUE_CFG_H_