ef1c3098a1
This relands commit 460bd7a03a.
TEST=ci
Change-Id: I0b5e91a3b8b6e8afa3f889afa21afed7c1a7e62c
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/327821
Reviewed-by: Slava Egorov <vegorov@google.com>
Reviewed-by: Alexander Markov <alexmarkov@google.com>
Commit-Queue: Ryan Macnak <rmacnak@google.com>
171 lines
5.8 KiB
C++
171 lines
5.8 KiB
C++
// Copyright (c) 2019, 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_BACKEND_BLOCK_BUILDER_H_
|
|
#define RUNTIME_VM_COMPILER_BACKEND_BLOCK_BUILDER_H_
|
|
|
|
#if defined(DART_PRECOMPILED_RUNTIME)
|
|
#error "AOT runtime should not use compiler sources (including header files)"
|
|
#endif // defined(DART_PRECOMPILED_RUNTIME)
|
|
|
|
#include "vm/compiler/backend/flow_graph.h"
|
|
#include "vm/compiler/backend/il.h"
|
|
|
|
namespace dart {
|
|
namespace compiler {
|
|
|
|
// Helper class for building basic blocks in SSA form.
|
|
class BlockBuilder : public ValueObject {
|
|
public:
|
|
BlockBuilder(FlowGraph* flow_graph, BlockEntryInstr* entry)
|
|
: flow_graph_(flow_graph),
|
|
source_(InstructionSource(flow_graph_->function().token_pos(),
|
|
flow_graph->inlining_id())),
|
|
entry_(entry),
|
|
current_(entry),
|
|
dummy_env_(new Environment(0, 0, 0, flow_graph->function(), nullptr)) {
|
|
// Some graph transformations use environments from block entries.
|
|
entry->SetEnvironment(dummy_env_);
|
|
}
|
|
|
|
Definition* AddToInitialDefinitions(Definition* def) {
|
|
flow_graph_->AllocateSSAIndex(def);
|
|
auto normal_entry = flow_graph_->graph_entry()->normal_entry();
|
|
flow_graph_->AddToInitialDefinitions(normal_entry, def);
|
|
return def;
|
|
}
|
|
|
|
template <typename T>
|
|
T* AddDefinition(T* def) {
|
|
flow_graph_->AllocateSSAIndex(def);
|
|
AddInstruction(def);
|
|
return def;
|
|
}
|
|
|
|
template <typename T>
|
|
T* AddInstruction(T* instr) {
|
|
if (instr->ComputeCanDeoptimize() ||
|
|
instr->ComputeCanDeoptimizeAfterCall() ||
|
|
instr->CanBecomeDeoptimizationTarget()) {
|
|
// All instructions that can deoptimize must have an environment attached
|
|
// to them.
|
|
instr->SetEnvironment(dummy_env_);
|
|
}
|
|
current_ = current_->AppendInstruction(instr);
|
|
return instr;
|
|
}
|
|
|
|
const Function& function() const { return flow_graph_->function(); }
|
|
|
|
ReturnInstr* AddReturn(Value* value) {
|
|
const auto& function = flow_graph_->function();
|
|
const auto representation = FlowGraph::ReturnRepresentationOf(function);
|
|
ReturnInstr* instr = new ReturnInstr(
|
|
Source(), value, CompilerState::Current().GetNextDeoptId(),
|
|
representation);
|
|
AddInstruction(instr);
|
|
entry_->set_last_instruction(instr);
|
|
return instr;
|
|
}
|
|
|
|
Definition* AddParameter(intptr_t index, bool with_frame) {
|
|
const auto& function = flow_graph_->function();
|
|
const intptr_t param_offset = FlowGraph::ParameterOffsetAt(function, index);
|
|
const auto representation =
|
|
FlowGraph::ParameterRepresentationAt(function, index);
|
|
return AddParameter(index, param_offset, with_frame, representation);
|
|
}
|
|
|
|
Definition* AddParameter(intptr_t index,
|
|
intptr_t param_offset,
|
|
bool with_frame,
|
|
Representation representation) {
|
|
auto normal_entry = flow_graph_->graph_entry()->normal_entry();
|
|
return AddToInitialDefinitions(new ParameterInstr(
|
|
/*env_index=*/index, /*param_index=*/index, param_offset, normal_entry,
|
|
representation, with_frame ? FPREG : SPREG));
|
|
}
|
|
|
|
TokenPosition TokenPos() const { return source_.token_pos; }
|
|
const InstructionSource& Source() const { return source_; }
|
|
|
|
Definition* AddNullDefinition() {
|
|
return flow_graph_->GetConstant(Object::ZoneHandle());
|
|
}
|
|
|
|
Definition* AddUnboxInstr(Representation rep, Value* value, bool is_checked) {
|
|
Definition* unboxed_value =
|
|
AddDefinition(UnboxInstr::Create(rep, value, DeoptId::kNone));
|
|
if (is_checked) {
|
|
// The type of |value| has already been checked and it is safe to
|
|
// adjust reaching type. This is done manually because there is no type
|
|
// propagation when building intrinsics.
|
|
unboxed_value->AsUnbox()->value()->SetReachingType(
|
|
TypeForRepresentation(rep));
|
|
}
|
|
return unboxed_value;
|
|
}
|
|
|
|
Definition* AddUnboxInstr(Representation rep,
|
|
Definition* boxed,
|
|
bool is_checked) {
|
|
return AddUnboxInstr(rep, new Value(boxed), is_checked);
|
|
}
|
|
|
|
BranchInstr* AddBranch(ComparisonInstr* comp,
|
|
TargetEntryInstr* true_successor,
|
|
TargetEntryInstr* false_successor) {
|
|
auto branch =
|
|
new BranchInstr(comp, CompilerState::Current().GetNextDeoptId());
|
|
// Some graph transformations use environments from branches.
|
|
branch->SetEnvironment(dummy_env_);
|
|
current_->AppendInstruction(branch);
|
|
current_ = nullptr;
|
|
|
|
*branch->true_successor_address() = true_successor;
|
|
*branch->false_successor_address() = false_successor;
|
|
|
|
return branch;
|
|
}
|
|
|
|
void AddPhi(PhiInstr* phi) {
|
|
flow_graph_->AllocateSSAIndex(phi);
|
|
phi->mark_alive();
|
|
entry_->AsJoinEntry()->InsertPhi(phi);
|
|
}
|
|
|
|
Instruction* last() const { return current_; }
|
|
|
|
private:
|
|
static CompileType* TypeForRepresentation(Representation rep) {
|
|
switch (rep) {
|
|
case kUnboxedDouble:
|
|
return new CompileType(CompileType::FromCid(kDoubleCid));
|
|
case kUnboxedFloat32x4:
|
|
return new CompileType(CompileType::FromCid(kFloat32x4Cid));
|
|
case kUnboxedInt32x4:
|
|
return new CompileType(CompileType::FromCid(kInt32x4Cid));
|
|
case kUnboxedFloat64x2:
|
|
return new CompileType(CompileType::FromCid(kFloat64x2Cid));
|
|
case kUnboxedUint32:
|
|
case kUnboxedInt64:
|
|
return new CompileType(CompileType::Int());
|
|
default:
|
|
UNREACHABLE();
|
|
return nullptr;
|
|
}
|
|
}
|
|
|
|
FlowGraph* const flow_graph_;
|
|
const InstructionSource source_;
|
|
BlockEntryInstr* entry_;
|
|
Instruction* current_;
|
|
Environment* dummy_env_;
|
|
};
|
|
|
|
} // namespace compiler
|
|
} // namespace dart
|
|
|
|
#endif // RUNTIME_VM_COMPILER_BACKEND_BLOCK_BUILDER_H_
|