63e170a242
This change removes duplicate management of inputs in variadic IL instructions by introducing VariadicDefinition and VariadicDefinitionWithEmbeddedInputs base classes. TemplateInstruction and TemplateDefinition are used in more places where appropriate. Number of inputs no longer depends on the values of the inputs (DropTempsInstr and AllocateObjectInstr). This change also prepares IL for the future implementation of binary serialization/deserialization in the following ways: * Environment now holds Function and not ParsedFunction (which are not going to be serialized). * Instructions no longer keep Zone* pointer (it's redundant). * NativeCallInstr keeps references to handles instead of pointers. TEST=ci (pure refactoring) Change-Id: I932b62c1c207bbf60cddbded8a39b41beabd3e83 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/253480 Reviewed-by: Slava Egorov <vegorov@google.com> Reviewed-by: Martin Kustermann <kustermann@google.com> Commit-Queue: Alexander Markov <alexmarkov@google.com>
169 lines
5.8 KiB
C++
169 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(),
|
|
UntaggedPcDescriptors::kInvalidYieldIndex, 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(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);
|
|
}
|
|
|
|
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_
|