blob: 833deb208c332c225e4e62ecdfcd5ff29cb13018 [file] [log] [blame]
// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#ifndef RUNTIME_VM_COMPILER_FRONTEND_BYTECODE_FLOW_GRAPH_BUILDER_H_
#define RUNTIME_VM_COMPILER_FRONTEND_BYTECODE_FLOW_GRAPH_BUILDER_H_
#include "vm/compiler/backend/il.h"
#include "vm/compiler/frontend/base_flow_graph_builder.h"
#include "vm/constants_kbc.h"
#if !defined(DART_PRECOMPILED_RUNTIME)
namespace dart {
namespace kernel {
// This class builds flow graph from bytecode. It is used either to compile
// from bytecode, or generate bytecode interpreter (the latter is not
// fully implemented yet).
// TODO(alexmarkov): extend this class and IL to generate an interpreter in
// addition to compiling bytecode.
class BytecodeFlowGraphBuilder {
public:
BytecodeFlowGraphBuilder(BaseFlowGraphBuilder* flow_graph_builder,
ParsedFunction* parsed_function,
ZoneGrowableArray<const ICData*>* ic_data_array)
: flow_graph_builder_(flow_graph_builder),
zone_(flow_graph_builder->zone_),
is_generating_interpreter_(
false), // TODO(alexmarkov): pass as argument
parsed_function_(parsed_function),
ic_data_array_(ic_data_array),
object_pool_(ObjectPool::Handle(zone_)),
bytecode_length_(0),
pc_(0),
position_(TokenPosition::kNoSource),
local_vars_(zone_, 0),
parameters_(zone_, 0),
exception_var_(nullptr),
stacktrace_var_(nullptr),
scratch_var_(nullptr),
prologue_info_(-1, -1),
throw_no_such_method_(nullptr) {}
FlowGraph* BuildGraph();
protected:
// Returns `true` if building a flow graph for a bytecode interpreter, or
// `false` if compiling a function from bytecode.
bool is_generating_interpreter() const { return is_generating_interpreter_; }
private:
// Operand of bytecode instruction, either intptr_t value (if compiling
// bytecode) or Definition (if generating interpreter).
class Operand {
public:
explicit Operand(Definition* definition)
: definition_(definition), value_(0) {
ASSERT(definition != nullptr);
}
explicit Operand(intptr_t value) : definition_(nullptr), value_(value) {}
Definition* definition() const {
ASSERT(definition_ != nullptr);
return definition_;
}
intptr_t value() const {
ASSERT(definition_ == nullptr);
return value_;
}
private:
Definition* definition_;
intptr_t value_;
};
// Constant from a constant pool.
// It is either Object (if compiling bytecode) or Definition
// (if generating interpreter).
class Constant {
public:
explicit Constant(Definition* definition)
: definition_(definition), value_(Object::null_object()) {
ASSERT(definition != nullptr);
}
explicit Constant(Zone* zone, const Object& value)
: definition_(nullptr), value_(value) {}
Definition* definition() const {
ASSERT(definition_ != nullptr);
return definition_;
}
const Object& value() const {
ASSERT(definition_ == nullptr);
return value_;
}
private:
Definition* definition_;
const Object& value_;
};
Operand DecodeOperandA();
Operand DecodeOperandB();
Operand DecodeOperandC();
Operand DecodeOperandD();
Operand DecodeOperandE();
Operand DecodeOperandF();
Operand DecodeOperandX();
Operand DecodeOperandY();
Operand DecodeOperandT();
Constant ConstantAt(Operand entry_index, intptr_t add_index = 0);
void PushConstant(Constant constant);
Constant PopConstant();
void LoadStackSlots(intptr_t num_slots);
void AllocateLocalVariables(Operand frame_size,
intptr_t num_param_locals = 0);
LocalVariable* AllocateParameter(intptr_t param_index,
VariableIndex var_index);
void AllocateFixedParameters();
LocalVariable* LocalVariableAt(intptr_t local_index);
void StoreLocal(Operand local_index);
void LoadLocal(Operand local_index);
Value* Pop();
intptr_t GetStackDepth() const;
bool IsStackEmpty() const;
ArgumentArray GetArguments(int count);
void PropagateStackState(intptr_t target_pc);
void DropUnusedValuesFromStack();
void BuildJumpIfStrictCompare(Token::Kind cmp_kind);
void BuildPrimitiveOp(const String& name,
Token::Kind token_kind,
const AbstractType& static_receiver_type,
int num_args);
void BuildIntOp(const String& name, Token::Kind token_kind, int num_args);
void BuildDoubleOp(const String& name, Token::Kind token_kind, int num_args);
void BuildInterfaceCallCommon(bool is_unchecked_call);
void BuildInstruction(KernelBytecode::Opcode opcode);
#define DECLARE_BUILD_METHOD(name, encoding, kind, op1, op2, op3) \
void Build##name();
KERNEL_BYTECODES_LIST(DECLARE_BUILD_METHOD)
#undef DECLARE_BUILD_METHOD
void ProcessICDataInObjectPool(const ObjectPool& object_pool);
intptr_t GetTryIndex(const PcDescriptors& descriptors, intptr_t pc);
JoinEntryInstr* EnsureControlFlowJoin(const PcDescriptors& descriptors,
intptr_t pc);
bool RequiresScratchVar(const KBCInstr* instr);
void CollectControlFlow(const PcDescriptors& descriptors,
const ExceptionHandlers& handlers,
GraphEntryInstr* graph_entry);
Thread* thread() const { return flow_graph_builder_->thread_; }
Isolate* isolate() const { return thread()->isolate(); }
ParsedFunction* parsed_function() {
ASSERT(!is_generating_interpreter());
return parsed_function_;
}
const Function& function() { return parsed_function()->function(); }
BaseFlowGraphBuilder* flow_graph_builder_;
Zone* zone_;
bool is_generating_interpreter_;
// The following members are available only when compiling bytecode.
ParsedFunction* parsed_function_;
ZoneGrowableArray<const ICData*>* ic_data_array_;
ObjectPool& object_pool_;
const KBCInstr* raw_bytecode_ = nullptr;
intptr_t bytecode_length_;
intptr_t pc_;
intptr_t next_pc_ = -1;
const KBCInstr* bytecode_instr_ = nullptr;
TokenPosition position_; // TODO(alexmarkov): Set/update.
Fragment code_;
ZoneGrowableArray<LocalVariable*> local_vars_;
ZoneGrowableArray<LocalVariable*> parameters_;
LocalVariable* exception_var_;
LocalVariable* stacktrace_var_;
LocalVariable* scratch_var_;
IntMap<JoinEntryInstr*> jump_targets_;
IntMap<Value*> stack_states_;
PrologueInfo prologue_info_;
JoinEntryInstr* throw_no_such_method_;
};
} // namespace kernel
} // namespace dart
#endif // !defined(DART_PRECOMPILED_RUNTIME)
#endif // RUNTIME_VM_COMPILER_FRONTEND_BYTECODE_FLOW_GRAPH_BUILDER_H_