diff options
Diffstat (limited to 'deps/v8/src/torque/cfg.h')
-rw-r--r-- | deps/v8/src/torque/cfg.h | 149 |
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(¤t_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_ |