11cb0ef41Sopenharmony_ci// Copyright 2014 the V8 project authors. All rights reserved. 21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be 31cb0ef41Sopenharmony_ci// found in the LICENSE file. 41cb0ef41Sopenharmony_ci 51cb0ef41Sopenharmony_ci#include "src/compiler/raw-machine-assembler.h" 61cb0ef41Sopenharmony_ci 71cb0ef41Sopenharmony_ci#include "src/base/small-vector.h" 81cb0ef41Sopenharmony_ci#include "src/compiler/compiler-source-position-table.h" 91cb0ef41Sopenharmony_ci#include "src/compiler/node-properties.h" 101cb0ef41Sopenharmony_ci#include "src/compiler/pipeline.h" 111cb0ef41Sopenharmony_ci#include "src/compiler/scheduler.h" 121cb0ef41Sopenharmony_ci#include "src/heap/factory-inl.h" 131cb0ef41Sopenharmony_ci 141cb0ef41Sopenharmony_cinamespace v8 { 151cb0ef41Sopenharmony_cinamespace internal { 161cb0ef41Sopenharmony_cinamespace compiler { 171cb0ef41Sopenharmony_ci 181cb0ef41Sopenharmony_ciRawMachineAssembler::RawMachineAssembler( 191cb0ef41Sopenharmony_ci Isolate* isolate, Graph* graph, CallDescriptor* call_descriptor, 201cb0ef41Sopenharmony_ci MachineRepresentation word, MachineOperatorBuilder::Flags flags, 211cb0ef41Sopenharmony_ci MachineOperatorBuilder::AlignmentRequirements alignment_requirements) 221cb0ef41Sopenharmony_ci : isolate_(isolate), 231cb0ef41Sopenharmony_ci graph_(graph), 241cb0ef41Sopenharmony_ci schedule_(zone()->New<Schedule>(zone())), 251cb0ef41Sopenharmony_ci source_positions_(zone()->New<SourcePositionTable>(graph)), 261cb0ef41Sopenharmony_ci machine_(zone(), word, flags, alignment_requirements), 271cb0ef41Sopenharmony_ci common_(zone()), 281cb0ef41Sopenharmony_ci simplified_(zone()), 291cb0ef41Sopenharmony_ci call_descriptor_(call_descriptor), 301cb0ef41Sopenharmony_ci target_parameter_(nullptr), 311cb0ef41Sopenharmony_ci parameters_(parameter_count(), zone()), 321cb0ef41Sopenharmony_ci current_block_(schedule()->start()) { 331cb0ef41Sopenharmony_ci int param_count = static_cast<int>(parameter_count()); 341cb0ef41Sopenharmony_ci // Add an extra input for the JSFunction parameter to the start node. 351cb0ef41Sopenharmony_ci graph->SetStart(graph->NewNode(common_.Start(param_count + 1))); 361cb0ef41Sopenharmony_ci if (call_descriptor->IsJSFunctionCall()) { 371cb0ef41Sopenharmony_ci target_parameter_ = AddNode( 381cb0ef41Sopenharmony_ci common()->Parameter(Linkage::kJSCallClosureParamIndex), graph->start()); 391cb0ef41Sopenharmony_ci } 401cb0ef41Sopenharmony_ci for (size_t i = 0; i < parameter_count(); ++i) { 411cb0ef41Sopenharmony_ci parameters_[i] = 421cb0ef41Sopenharmony_ci AddNode(common()->Parameter(static_cast<int>(i)), graph->start()); 431cb0ef41Sopenharmony_ci } 441cb0ef41Sopenharmony_ci graph->SetEnd(graph->NewNode(common_.End(0))); 451cb0ef41Sopenharmony_ci source_positions_->AddDecorator(); 461cb0ef41Sopenharmony_ci} 471cb0ef41Sopenharmony_ci 481cb0ef41Sopenharmony_civoid RawMachineAssembler::SetCurrentExternalSourcePosition( 491cb0ef41Sopenharmony_ci FileAndLine file_and_line) { 501cb0ef41Sopenharmony_ci int file_id = 511cb0ef41Sopenharmony_ci isolate()->LookupOrAddExternallyCompiledFilename(file_and_line.first); 521cb0ef41Sopenharmony_ci SourcePosition p = SourcePosition::External(file_and_line.second, file_id); 531cb0ef41Sopenharmony_ci DCHECK(p.ExternalLine() == file_and_line.second); 541cb0ef41Sopenharmony_ci source_positions()->SetCurrentPosition(p); 551cb0ef41Sopenharmony_ci} 561cb0ef41Sopenharmony_ci 571cb0ef41Sopenharmony_ciFileAndLine RawMachineAssembler::GetCurrentExternalSourcePosition() const { 581cb0ef41Sopenharmony_ci SourcePosition p = source_positions_->GetCurrentPosition(); 591cb0ef41Sopenharmony_ci if (!p.IsKnown()) return {nullptr, -1}; 601cb0ef41Sopenharmony_ci int file_id = p.ExternalFileId(); 611cb0ef41Sopenharmony_ci const char* file_name = isolate()->GetExternallyCompiledFilename(file_id); 621cb0ef41Sopenharmony_ci int line = p.ExternalLine(); 631cb0ef41Sopenharmony_ci return {file_name, line}; 641cb0ef41Sopenharmony_ci} 651cb0ef41Sopenharmony_ci 661cb0ef41Sopenharmony_ciNode* RawMachineAssembler::NullConstant() { 671cb0ef41Sopenharmony_ci return HeapConstant(isolate()->factory()->null_value()); 681cb0ef41Sopenharmony_ci} 691cb0ef41Sopenharmony_ci 701cb0ef41Sopenharmony_ciNode* RawMachineAssembler::UndefinedConstant() { 711cb0ef41Sopenharmony_ci return HeapConstant(isolate()->factory()->undefined_value()); 721cb0ef41Sopenharmony_ci} 731cb0ef41Sopenharmony_ci 741cb0ef41Sopenharmony_ciNode* RawMachineAssembler::RelocatableIntPtrConstant(intptr_t value, 751cb0ef41Sopenharmony_ci RelocInfo::Mode rmode) { 761cb0ef41Sopenharmony_ci return kSystemPointerSize == 8 771cb0ef41Sopenharmony_ci ? RelocatableInt64Constant(value, rmode) 781cb0ef41Sopenharmony_ci : RelocatableInt32Constant(static_cast<int>(value), rmode); 791cb0ef41Sopenharmony_ci} 801cb0ef41Sopenharmony_ci 811cb0ef41Sopenharmony_ciNode* RawMachineAssembler::OptimizedAllocate( 821cb0ef41Sopenharmony_ci Node* size, AllocationType allocation, 831cb0ef41Sopenharmony_ci AllowLargeObjects allow_large_objects) { 841cb0ef41Sopenharmony_ci return AddNode( 851cb0ef41Sopenharmony_ci simplified()->AllocateRaw(Type::Any(), allocation, allow_large_objects), 861cb0ef41Sopenharmony_ci size); 871cb0ef41Sopenharmony_ci} 881cb0ef41Sopenharmony_ci 891cb0ef41Sopenharmony_ciSchedule* RawMachineAssembler::ExportForTest() { 901cb0ef41Sopenharmony_ci // Compute the correct codegen order. 911cb0ef41Sopenharmony_ci DCHECK(schedule_->rpo_order()->empty()); 921cb0ef41Sopenharmony_ci if (FLAG_trace_turbo_scheduler) { 931cb0ef41Sopenharmony_ci PrintF("--- RAW SCHEDULE -------------------------------------------\n"); 941cb0ef41Sopenharmony_ci StdoutStream{} << *schedule_; 951cb0ef41Sopenharmony_ci } 961cb0ef41Sopenharmony_ci schedule_->EnsureCFGWellFormedness(); 971cb0ef41Sopenharmony_ci Scheduler::ComputeSpecialRPO(zone(), schedule_); 981cb0ef41Sopenharmony_ci Scheduler::GenerateDominatorTree(schedule_); 991cb0ef41Sopenharmony_ci schedule_->PropagateDeferredMark(); 1001cb0ef41Sopenharmony_ci if (FLAG_trace_turbo_scheduler) { 1011cb0ef41Sopenharmony_ci PrintF("--- EDGE SPLIT AND PROPAGATED DEFERRED SCHEDULE ------------\n"); 1021cb0ef41Sopenharmony_ci StdoutStream{} << *schedule_; 1031cb0ef41Sopenharmony_ci } 1041cb0ef41Sopenharmony_ci // Invalidate RawMachineAssembler. 1051cb0ef41Sopenharmony_ci source_positions_->RemoveDecorator(); 1061cb0ef41Sopenharmony_ci Schedule* schedule = schedule_; 1071cb0ef41Sopenharmony_ci schedule_ = nullptr; 1081cb0ef41Sopenharmony_ci return schedule; 1091cb0ef41Sopenharmony_ci} 1101cb0ef41Sopenharmony_ci 1111cb0ef41Sopenharmony_ciGraph* RawMachineAssembler::ExportForOptimization() { 1121cb0ef41Sopenharmony_ci // Compute the correct codegen order. 1131cb0ef41Sopenharmony_ci DCHECK(schedule_->rpo_order()->empty()); 1141cb0ef41Sopenharmony_ci if (FLAG_trace_turbo_scheduler) { 1151cb0ef41Sopenharmony_ci PrintF("--- RAW SCHEDULE -------------------------------------------\n"); 1161cb0ef41Sopenharmony_ci StdoutStream{} << *schedule_; 1171cb0ef41Sopenharmony_ci } 1181cb0ef41Sopenharmony_ci schedule_->EnsureCFGWellFormedness(); 1191cb0ef41Sopenharmony_ci OptimizeControlFlow(schedule_, graph(), common()); 1201cb0ef41Sopenharmony_ci Scheduler::ComputeSpecialRPO(zone(), schedule_); 1211cb0ef41Sopenharmony_ci if (FLAG_trace_turbo_scheduler) { 1221cb0ef41Sopenharmony_ci PrintF("--- SCHEDULE BEFORE GRAPH CREATION -------------------------\n"); 1231cb0ef41Sopenharmony_ci StdoutStream{} << *schedule_; 1241cb0ef41Sopenharmony_ci } 1251cb0ef41Sopenharmony_ci MakeReschedulable(); 1261cb0ef41Sopenharmony_ci // Invalidate RawMachineAssembler. 1271cb0ef41Sopenharmony_ci schedule_ = nullptr; 1281cb0ef41Sopenharmony_ci return graph(); 1291cb0ef41Sopenharmony_ci} 1301cb0ef41Sopenharmony_ci 1311cb0ef41Sopenharmony_civoid RawMachineAssembler::OptimizeControlFlow(Schedule* schedule, Graph* graph, 1321cb0ef41Sopenharmony_ci CommonOperatorBuilder* common) { 1331cb0ef41Sopenharmony_ci for (bool changed = true; changed;) { 1341cb0ef41Sopenharmony_ci changed = false; 1351cb0ef41Sopenharmony_ci for (size_t i = 0; i < schedule->all_blocks()->size(); ++i) { 1361cb0ef41Sopenharmony_ci BasicBlock* block = (*schedule->all_blocks())[i]; 1371cb0ef41Sopenharmony_ci if (block == nullptr) continue; 1381cb0ef41Sopenharmony_ci 1391cb0ef41Sopenharmony_ci // Short-circuit a goto if the succeeding block is not a control-flow 1401cb0ef41Sopenharmony_ci // merge. This is not really useful on it's own since graph construction 1411cb0ef41Sopenharmony_ci // has the same effect, but combining blocks improves the pattern-match on 1421cb0ef41Sopenharmony_ci // their structure below. 1431cb0ef41Sopenharmony_ci if (block->control() == BasicBlock::kGoto) { 1441cb0ef41Sopenharmony_ci DCHECK_EQ(block->SuccessorCount(), 1); 1451cb0ef41Sopenharmony_ci BasicBlock* successor = block->SuccessorAt(0); 1461cb0ef41Sopenharmony_ci if (successor->PredecessorCount() == 1) { 1471cb0ef41Sopenharmony_ci DCHECK_EQ(successor->PredecessorAt(0), block); 1481cb0ef41Sopenharmony_ci for (Node* node : *successor) { 1491cb0ef41Sopenharmony_ci schedule->SetBlockForNode(nullptr, node); 1501cb0ef41Sopenharmony_ci schedule->AddNode(block, node); 1511cb0ef41Sopenharmony_ci } 1521cb0ef41Sopenharmony_ci block->set_control(successor->control()); 1531cb0ef41Sopenharmony_ci Node* control_input = successor->control_input(); 1541cb0ef41Sopenharmony_ci block->set_control_input(control_input); 1551cb0ef41Sopenharmony_ci if (control_input) { 1561cb0ef41Sopenharmony_ci schedule->SetBlockForNode(block, control_input); 1571cb0ef41Sopenharmony_ci } 1581cb0ef41Sopenharmony_ci if (successor->deferred()) block->set_deferred(true); 1591cb0ef41Sopenharmony_ci block->ClearSuccessors(); 1601cb0ef41Sopenharmony_ci schedule->MoveSuccessors(successor, block); 1611cb0ef41Sopenharmony_ci schedule->ClearBlockById(successor->id()); 1621cb0ef41Sopenharmony_ci changed = true; 1631cb0ef41Sopenharmony_ci --i; 1641cb0ef41Sopenharmony_ci continue; 1651cb0ef41Sopenharmony_ci } 1661cb0ef41Sopenharmony_ci } 1671cb0ef41Sopenharmony_ci // Block-cloning in the simple case where a block consists only of a phi 1681cb0ef41Sopenharmony_ci // node and a branch on that phi. This just duplicates the branch block 1691cb0ef41Sopenharmony_ci // for each predecessor, replacing the phi node with the corresponding phi 1701cb0ef41Sopenharmony_ci // input. 1711cb0ef41Sopenharmony_ci if (block->control() == BasicBlock::kBranch && block->NodeCount() == 1) { 1721cb0ef41Sopenharmony_ci Node* phi = block->NodeAt(0); 1731cb0ef41Sopenharmony_ci if (phi->opcode() != IrOpcode::kPhi) continue; 1741cb0ef41Sopenharmony_ci Node* branch = block->control_input(); 1751cb0ef41Sopenharmony_ci DCHECK_EQ(branch->opcode(), IrOpcode::kBranch); 1761cb0ef41Sopenharmony_ci if (NodeProperties::GetValueInput(branch, 0) != phi) continue; 1771cb0ef41Sopenharmony_ci if (phi->UseCount() != 1) continue; 1781cb0ef41Sopenharmony_ci DCHECK_EQ(phi->op()->ValueInputCount(), block->PredecessorCount()); 1791cb0ef41Sopenharmony_ci 1801cb0ef41Sopenharmony_ci // Turn projection blocks into normal blocks. 1811cb0ef41Sopenharmony_ci DCHECK_EQ(block->SuccessorCount(), 2); 1821cb0ef41Sopenharmony_ci BasicBlock* true_block = block->SuccessorAt(0); 1831cb0ef41Sopenharmony_ci BasicBlock* false_block = block->SuccessorAt(1); 1841cb0ef41Sopenharmony_ci DCHECK_EQ(true_block->NodeAt(0)->opcode(), IrOpcode::kIfTrue); 1851cb0ef41Sopenharmony_ci DCHECK_EQ(false_block->NodeAt(0)->opcode(), IrOpcode::kIfFalse); 1861cb0ef41Sopenharmony_ci (*true_block->begin())->Kill(); 1871cb0ef41Sopenharmony_ci true_block->RemoveNode(true_block->begin()); 1881cb0ef41Sopenharmony_ci (*false_block->begin())->Kill(); 1891cb0ef41Sopenharmony_ci false_block->RemoveNode(false_block->begin()); 1901cb0ef41Sopenharmony_ci true_block->ClearPredecessors(); 1911cb0ef41Sopenharmony_ci false_block->ClearPredecessors(); 1921cb0ef41Sopenharmony_ci 1931cb0ef41Sopenharmony_ci size_t arity = block->PredecessorCount(); 1941cb0ef41Sopenharmony_ci for (size_t j = 0; j < arity; ++j) { 1951cb0ef41Sopenharmony_ci BasicBlock* predecessor = block->PredecessorAt(j); 1961cb0ef41Sopenharmony_ci predecessor->ClearSuccessors(); 1971cb0ef41Sopenharmony_ci if (block->deferred()) predecessor->set_deferred(true); 1981cb0ef41Sopenharmony_ci Node* branch_clone = graph->CloneNode(branch); 1991cb0ef41Sopenharmony_ci int phi_input = static_cast<int>(j); 2001cb0ef41Sopenharmony_ci NodeProperties::ReplaceValueInput( 2011cb0ef41Sopenharmony_ci branch_clone, NodeProperties::GetValueInput(phi, phi_input), 0); 2021cb0ef41Sopenharmony_ci BasicBlock* new_true_block = schedule->NewBasicBlock(); 2031cb0ef41Sopenharmony_ci BasicBlock* new_false_block = schedule->NewBasicBlock(); 2041cb0ef41Sopenharmony_ci new_true_block->AddNode( 2051cb0ef41Sopenharmony_ci graph->NewNode(common->IfTrue(), branch_clone)); 2061cb0ef41Sopenharmony_ci new_false_block->AddNode( 2071cb0ef41Sopenharmony_ci graph->NewNode(common->IfFalse(), branch_clone)); 2081cb0ef41Sopenharmony_ci schedule->AddGoto(new_true_block, true_block); 2091cb0ef41Sopenharmony_ci schedule->AddGoto(new_false_block, false_block); 2101cb0ef41Sopenharmony_ci DCHECK_EQ(predecessor->control(), BasicBlock::kGoto); 2111cb0ef41Sopenharmony_ci predecessor->set_control(BasicBlock::kNone); 2121cb0ef41Sopenharmony_ci schedule->AddBranch(predecessor, branch_clone, new_true_block, 2131cb0ef41Sopenharmony_ci new_false_block); 2141cb0ef41Sopenharmony_ci } 2151cb0ef41Sopenharmony_ci branch->Kill(); 2161cb0ef41Sopenharmony_ci schedule->ClearBlockById(block->id()); 2171cb0ef41Sopenharmony_ci changed = true; 2181cb0ef41Sopenharmony_ci continue; 2191cb0ef41Sopenharmony_ci } 2201cb0ef41Sopenharmony_ci } 2211cb0ef41Sopenharmony_ci } 2221cb0ef41Sopenharmony_ci} 2231cb0ef41Sopenharmony_ci 2241cb0ef41Sopenharmony_civoid RawMachineAssembler::MakeReschedulable() { 2251cb0ef41Sopenharmony_ci std::vector<Node*> block_final_control(schedule_->all_blocks_.size()); 2261cb0ef41Sopenharmony_ci std::vector<Node*> block_final_effect(schedule_->all_blocks_.size()); 2271cb0ef41Sopenharmony_ci 2281cb0ef41Sopenharmony_ci struct LoopHeader { 2291cb0ef41Sopenharmony_ci BasicBlock* block; 2301cb0ef41Sopenharmony_ci Node* loop_node; 2311cb0ef41Sopenharmony_ci Node* effect_phi; 2321cb0ef41Sopenharmony_ci }; 2331cb0ef41Sopenharmony_ci std::vector<LoopHeader> loop_headers; 2341cb0ef41Sopenharmony_ci 2351cb0ef41Sopenharmony_ci // These are hoisted outside of the loop to avoid re-allocation. 2361cb0ef41Sopenharmony_ci std::vector<Node*> merge_inputs; 2371cb0ef41Sopenharmony_ci std::vector<Node*> effect_phi_inputs; 2381cb0ef41Sopenharmony_ci 2391cb0ef41Sopenharmony_ci for (BasicBlock* block : *schedule_->rpo_order()) { 2401cb0ef41Sopenharmony_ci Node* current_control; 2411cb0ef41Sopenharmony_ci Node* current_effect; 2421cb0ef41Sopenharmony_ci if (block == schedule_->start()) { 2431cb0ef41Sopenharmony_ci current_control = current_effect = graph()->start(); 2441cb0ef41Sopenharmony_ci } else if (block == schedule_->end()) { 2451cb0ef41Sopenharmony_ci for (size_t i = 0; i < block->PredecessorCount(); ++i) { 2461cb0ef41Sopenharmony_ci NodeProperties::MergeControlToEnd( 2471cb0ef41Sopenharmony_ci graph(), common(), block->PredecessorAt(i)->control_input()); 2481cb0ef41Sopenharmony_ci } 2491cb0ef41Sopenharmony_ci } else if (block->IsLoopHeader()) { 2501cb0ef41Sopenharmony_ci // The graph()->start() inputs are just placeholders until we computed the 2511cb0ef41Sopenharmony_ci // real back-edges and re-structure the control flow so the loop has 2521cb0ef41Sopenharmony_ci // exactly two predecessors. 2531cb0ef41Sopenharmony_ci current_control = graph()->NewNode(common()->Loop(2), graph()->start(), 2541cb0ef41Sopenharmony_ci graph()->start()); 2551cb0ef41Sopenharmony_ci current_effect = 2561cb0ef41Sopenharmony_ci graph()->NewNode(common()->EffectPhi(2), graph()->start(), 2571cb0ef41Sopenharmony_ci graph()->start(), current_control); 2581cb0ef41Sopenharmony_ci 2591cb0ef41Sopenharmony_ci Node* terminate = graph()->NewNode(common()->Terminate(), current_effect, 2601cb0ef41Sopenharmony_ci current_control); 2611cb0ef41Sopenharmony_ci NodeProperties::MergeControlToEnd(graph(), common(), terminate); 2621cb0ef41Sopenharmony_ci loop_headers.push_back( 2631cb0ef41Sopenharmony_ci LoopHeader{block, current_control, current_effect}); 2641cb0ef41Sopenharmony_ci } else if (block->PredecessorCount() == 1) { 2651cb0ef41Sopenharmony_ci BasicBlock* predecessor = block->PredecessorAt(0); 2661cb0ef41Sopenharmony_ci DCHECK_LT(predecessor->rpo_number(), block->rpo_number()); 2671cb0ef41Sopenharmony_ci current_effect = block_final_effect[predecessor->id().ToSize()]; 2681cb0ef41Sopenharmony_ci current_control = block_final_control[predecessor->id().ToSize()]; 2691cb0ef41Sopenharmony_ci } else { 2701cb0ef41Sopenharmony_ci // Create control merge nodes and effect phis for all predecessor blocks. 2711cb0ef41Sopenharmony_ci merge_inputs.clear(); 2721cb0ef41Sopenharmony_ci effect_phi_inputs.clear(); 2731cb0ef41Sopenharmony_ci int predecessor_count = static_cast<int>(block->PredecessorCount()); 2741cb0ef41Sopenharmony_ci for (int i = 0; i < predecessor_count; ++i) { 2751cb0ef41Sopenharmony_ci BasicBlock* predecessor = block->PredecessorAt(i); 2761cb0ef41Sopenharmony_ci DCHECK_LT(predecessor->rpo_number(), block->rpo_number()); 2771cb0ef41Sopenharmony_ci merge_inputs.push_back(block_final_control[predecessor->id().ToSize()]); 2781cb0ef41Sopenharmony_ci effect_phi_inputs.push_back( 2791cb0ef41Sopenharmony_ci block_final_effect[predecessor->id().ToSize()]); 2801cb0ef41Sopenharmony_ci } 2811cb0ef41Sopenharmony_ci current_control = graph()->NewNode(common()->Merge(predecessor_count), 2821cb0ef41Sopenharmony_ci static_cast<int>(merge_inputs.size()), 2831cb0ef41Sopenharmony_ci merge_inputs.data()); 2841cb0ef41Sopenharmony_ci effect_phi_inputs.push_back(current_control); 2851cb0ef41Sopenharmony_ci current_effect = graph()->NewNode( 2861cb0ef41Sopenharmony_ci common()->EffectPhi(predecessor_count), 2871cb0ef41Sopenharmony_ci static_cast<int>(effect_phi_inputs.size()), effect_phi_inputs.data()); 2881cb0ef41Sopenharmony_ci } 2891cb0ef41Sopenharmony_ci 2901cb0ef41Sopenharmony_ci auto update_current_control_and_effect = [&](Node* node) { 2911cb0ef41Sopenharmony_ci bool existing_effect_and_control = 2921cb0ef41Sopenharmony_ci IrOpcode::IsIfProjectionOpcode(node->opcode()) || 2931cb0ef41Sopenharmony_ci IrOpcode::IsPhiOpcode(node->opcode()); 2941cb0ef41Sopenharmony_ci if (node->op()->EffectInputCount() > 0) { 2951cb0ef41Sopenharmony_ci DCHECK_EQ(1, node->op()->EffectInputCount()); 2961cb0ef41Sopenharmony_ci if (existing_effect_and_control) { 2971cb0ef41Sopenharmony_ci NodeProperties::ReplaceEffectInput(node, current_effect); 2981cb0ef41Sopenharmony_ci } else { 2991cb0ef41Sopenharmony_ci node->AppendInput(graph()->zone(), current_effect); 3001cb0ef41Sopenharmony_ci } 3011cb0ef41Sopenharmony_ci } 3021cb0ef41Sopenharmony_ci if (node->op()->ControlInputCount() > 0) { 3031cb0ef41Sopenharmony_ci DCHECK_EQ(1, node->op()->ControlInputCount()); 3041cb0ef41Sopenharmony_ci if (existing_effect_and_control) { 3051cb0ef41Sopenharmony_ci NodeProperties::ReplaceControlInput(node, current_control); 3061cb0ef41Sopenharmony_ci } else { 3071cb0ef41Sopenharmony_ci node->AppendInput(graph()->zone(), current_control); 3081cb0ef41Sopenharmony_ci } 3091cb0ef41Sopenharmony_ci } 3101cb0ef41Sopenharmony_ci if (node->op()->EffectOutputCount() > 0) { 3111cb0ef41Sopenharmony_ci DCHECK_EQ(1, node->op()->EffectOutputCount()); 3121cb0ef41Sopenharmony_ci current_effect = node; 3131cb0ef41Sopenharmony_ci } 3141cb0ef41Sopenharmony_ci if (node->op()->ControlOutputCount() > 0) { 3151cb0ef41Sopenharmony_ci current_control = node; 3161cb0ef41Sopenharmony_ci } 3171cb0ef41Sopenharmony_ci }; 3181cb0ef41Sopenharmony_ci 3191cb0ef41Sopenharmony_ci for (Node* node : *block) { 3201cb0ef41Sopenharmony_ci update_current_control_and_effect(node); 3211cb0ef41Sopenharmony_ci } 3221cb0ef41Sopenharmony_ci if (block->deferred()) MarkControlDeferred(current_control); 3231cb0ef41Sopenharmony_ci 3241cb0ef41Sopenharmony_ci if (Node* block_terminator = block->control_input()) { 3251cb0ef41Sopenharmony_ci update_current_control_and_effect(block_terminator); 3261cb0ef41Sopenharmony_ci } 3271cb0ef41Sopenharmony_ci 3281cb0ef41Sopenharmony_ci block_final_effect[block->id().ToSize()] = current_effect; 3291cb0ef41Sopenharmony_ci block_final_control[block->id().ToSize()] = current_control; 3301cb0ef41Sopenharmony_ci } 3311cb0ef41Sopenharmony_ci 3321cb0ef41Sopenharmony_ci // Fix-up loop backedges and re-structure control flow so that loop nodes have 3331cb0ef41Sopenharmony_ci // exactly two control predecessors. 3341cb0ef41Sopenharmony_ci for (const LoopHeader& loop_header : loop_headers) { 3351cb0ef41Sopenharmony_ci BasicBlock* block = loop_header.block; 3361cb0ef41Sopenharmony_ci std::vector<BasicBlock*> loop_entries; 3371cb0ef41Sopenharmony_ci std::vector<BasicBlock*> loop_backedges; 3381cb0ef41Sopenharmony_ci for (size_t i = 0; i < block->PredecessorCount(); ++i) { 3391cb0ef41Sopenharmony_ci BasicBlock* predecessor = block->PredecessorAt(i); 3401cb0ef41Sopenharmony_ci if (block->LoopContains(predecessor)) { 3411cb0ef41Sopenharmony_ci loop_backedges.push_back(predecessor); 3421cb0ef41Sopenharmony_ci } else { 3431cb0ef41Sopenharmony_ci DCHECK(loop_backedges.empty()); 3441cb0ef41Sopenharmony_ci loop_entries.push_back(predecessor); 3451cb0ef41Sopenharmony_ci } 3461cb0ef41Sopenharmony_ci } 3471cb0ef41Sopenharmony_ci DCHECK(!loop_entries.empty()); 3481cb0ef41Sopenharmony_ci DCHECK(!loop_backedges.empty()); 3491cb0ef41Sopenharmony_ci 3501cb0ef41Sopenharmony_ci int entrance_count = static_cast<int>(loop_entries.size()); 3511cb0ef41Sopenharmony_ci int backedge_count = static_cast<int>(loop_backedges.size()); 3521cb0ef41Sopenharmony_ci Node* control_loop_entry = CreateNodeFromPredecessors( 3531cb0ef41Sopenharmony_ci loop_entries, block_final_control, common()->Merge(entrance_count), {}); 3541cb0ef41Sopenharmony_ci Node* control_backedge = 3551cb0ef41Sopenharmony_ci CreateNodeFromPredecessors(loop_backedges, block_final_control, 3561cb0ef41Sopenharmony_ci common()->Merge(backedge_count), {}); 3571cb0ef41Sopenharmony_ci Node* effect_loop_entry = CreateNodeFromPredecessors( 3581cb0ef41Sopenharmony_ci loop_entries, block_final_effect, common()->EffectPhi(entrance_count), 3591cb0ef41Sopenharmony_ci {control_loop_entry}); 3601cb0ef41Sopenharmony_ci Node* effect_backedge = CreateNodeFromPredecessors( 3611cb0ef41Sopenharmony_ci loop_backedges, block_final_effect, common()->EffectPhi(backedge_count), 3621cb0ef41Sopenharmony_ci {control_backedge}); 3631cb0ef41Sopenharmony_ci 3641cb0ef41Sopenharmony_ci loop_header.loop_node->ReplaceInput(0, control_loop_entry); 3651cb0ef41Sopenharmony_ci loop_header.loop_node->ReplaceInput(1, control_backedge); 3661cb0ef41Sopenharmony_ci loop_header.effect_phi->ReplaceInput(0, effect_loop_entry); 3671cb0ef41Sopenharmony_ci loop_header.effect_phi->ReplaceInput(1, effect_backedge); 3681cb0ef41Sopenharmony_ci 3691cb0ef41Sopenharmony_ci for (Node* node : *block) { 3701cb0ef41Sopenharmony_ci if (node->opcode() == IrOpcode::kPhi) { 3711cb0ef41Sopenharmony_ci MakePhiBinary(node, static_cast<int>(loop_entries.size()), 3721cb0ef41Sopenharmony_ci control_loop_entry, control_backedge); 3731cb0ef41Sopenharmony_ci } 3741cb0ef41Sopenharmony_ci } 3751cb0ef41Sopenharmony_ci } 3761cb0ef41Sopenharmony_ci} 3771cb0ef41Sopenharmony_ci 3781cb0ef41Sopenharmony_ciNode* RawMachineAssembler::CreateNodeFromPredecessors( 3791cb0ef41Sopenharmony_ci const std::vector<BasicBlock*>& predecessors, 3801cb0ef41Sopenharmony_ci const std::vector<Node*>& sidetable, const Operator* op, 3811cb0ef41Sopenharmony_ci const std::vector<Node*>& additional_inputs) { 3821cb0ef41Sopenharmony_ci if (predecessors.size() == 1) { 3831cb0ef41Sopenharmony_ci return sidetable[predecessors.front()->id().ToSize()]; 3841cb0ef41Sopenharmony_ci } 3851cb0ef41Sopenharmony_ci std::vector<Node*> inputs; 3861cb0ef41Sopenharmony_ci inputs.reserve(predecessors.size()); 3871cb0ef41Sopenharmony_ci for (BasicBlock* predecessor : predecessors) { 3881cb0ef41Sopenharmony_ci inputs.push_back(sidetable[predecessor->id().ToSize()]); 3891cb0ef41Sopenharmony_ci } 3901cb0ef41Sopenharmony_ci for (Node* additional_input : additional_inputs) { 3911cb0ef41Sopenharmony_ci inputs.push_back(additional_input); 3921cb0ef41Sopenharmony_ci } 3931cb0ef41Sopenharmony_ci return graph()->NewNode(op, static_cast<int>(inputs.size()), inputs.data()); 3941cb0ef41Sopenharmony_ci} 3951cb0ef41Sopenharmony_ci 3961cb0ef41Sopenharmony_civoid RawMachineAssembler::MakePhiBinary(Node* phi, int split_point, 3971cb0ef41Sopenharmony_ci Node* left_control, 3981cb0ef41Sopenharmony_ci Node* right_control) { 3991cb0ef41Sopenharmony_ci int value_count = phi->op()->ValueInputCount(); 4001cb0ef41Sopenharmony_ci if (value_count == 2) return; 4011cb0ef41Sopenharmony_ci DCHECK_LT(split_point, value_count); 4021cb0ef41Sopenharmony_ci DCHECK_GT(split_point, 0); 4031cb0ef41Sopenharmony_ci 4041cb0ef41Sopenharmony_ci MachineRepresentation rep = PhiRepresentationOf(phi->op()); 4051cb0ef41Sopenharmony_ci int left_input_count = split_point; 4061cb0ef41Sopenharmony_ci int right_input_count = value_count - split_point; 4071cb0ef41Sopenharmony_ci 4081cb0ef41Sopenharmony_ci Node* left_input; 4091cb0ef41Sopenharmony_ci if (left_input_count == 1) { 4101cb0ef41Sopenharmony_ci left_input = NodeProperties::GetValueInput(phi, 0); 4111cb0ef41Sopenharmony_ci } else { 4121cb0ef41Sopenharmony_ci std::vector<Node*> inputs; 4131cb0ef41Sopenharmony_ci inputs.reserve(left_input_count); 4141cb0ef41Sopenharmony_ci for (int i = 0; i < left_input_count; ++i) { 4151cb0ef41Sopenharmony_ci inputs.push_back(NodeProperties::GetValueInput(phi, i)); 4161cb0ef41Sopenharmony_ci } 4171cb0ef41Sopenharmony_ci inputs.push_back(left_control); 4181cb0ef41Sopenharmony_ci left_input = 4191cb0ef41Sopenharmony_ci graph()->NewNode(common()->Phi(rep, static_cast<int>(left_input_count)), 4201cb0ef41Sopenharmony_ci static_cast<int>(inputs.size()), inputs.data()); 4211cb0ef41Sopenharmony_ci } 4221cb0ef41Sopenharmony_ci 4231cb0ef41Sopenharmony_ci Node* right_input; 4241cb0ef41Sopenharmony_ci if (right_input_count == 1) { 4251cb0ef41Sopenharmony_ci right_input = NodeProperties::GetValueInput(phi, split_point); 4261cb0ef41Sopenharmony_ci } else { 4271cb0ef41Sopenharmony_ci std::vector<Node*> inputs; 4281cb0ef41Sopenharmony_ci for (int i = split_point; i < value_count; ++i) { 4291cb0ef41Sopenharmony_ci inputs.push_back(NodeProperties::GetValueInput(phi, i)); 4301cb0ef41Sopenharmony_ci } 4311cb0ef41Sopenharmony_ci inputs.push_back(right_control); 4321cb0ef41Sopenharmony_ci right_input = graph()->NewNode( 4331cb0ef41Sopenharmony_ci common()->Phi(rep, static_cast<int>(right_input_count)), 4341cb0ef41Sopenharmony_ci static_cast<int>(inputs.size()), inputs.data()); 4351cb0ef41Sopenharmony_ci } 4361cb0ef41Sopenharmony_ci 4371cb0ef41Sopenharmony_ci Node* control = NodeProperties::GetControlInput(phi); 4381cb0ef41Sopenharmony_ci phi->TrimInputCount(3); 4391cb0ef41Sopenharmony_ci phi->ReplaceInput(0, left_input); 4401cb0ef41Sopenharmony_ci phi->ReplaceInput(1, right_input); 4411cb0ef41Sopenharmony_ci phi->ReplaceInput(2, control); 4421cb0ef41Sopenharmony_ci NodeProperties::ChangeOp(phi, common()->Phi(rep, 2)); 4431cb0ef41Sopenharmony_ci} 4441cb0ef41Sopenharmony_ci 4451cb0ef41Sopenharmony_civoid RawMachineAssembler::MarkControlDeferred(Node* control_node) { 4461cb0ef41Sopenharmony_ci BranchHint new_branch_hint; 4471cb0ef41Sopenharmony_ci Node* responsible_branch = nullptr; 4481cb0ef41Sopenharmony_ci while (responsible_branch == nullptr) { 4491cb0ef41Sopenharmony_ci switch (control_node->opcode()) { 4501cb0ef41Sopenharmony_ci case IrOpcode::kIfException: 4511cb0ef41Sopenharmony_ci // IfException projections are deferred by default. 4521cb0ef41Sopenharmony_ci return; 4531cb0ef41Sopenharmony_ci case IrOpcode::kIfSuccess: 4541cb0ef41Sopenharmony_ci control_node = NodeProperties::GetControlInput(control_node); 4551cb0ef41Sopenharmony_ci continue; 4561cb0ef41Sopenharmony_ci case IrOpcode::kIfValue: { 4571cb0ef41Sopenharmony_ci IfValueParameters parameters = IfValueParametersOf(control_node->op()); 4581cb0ef41Sopenharmony_ci if (parameters.hint() != BranchHint::kFalse) { 4591cb0ef41Sopenharmony_ci NodeProperties::ChangeOp( 4601cb0ef41Sopenharmony_ci control_node, common()->IfValue(parameters.value(), 4611cb0ef41Sopenharmony_ci parameters.comparison_order(), 4621cb0ef41Sopenharmony_ci BranchHint::kFalse)); 4631cb0ef41Sopenharmony_ci } 4641cb0ef41Sopenharmony_ci return; 4651cb0ef41Sopenharmony_ci } 4661cb0ef41Sopenharmony_ci case IrOpcode::kIfDefault: 4671cb0ef41Sopenharmony_ci if (BranchHintOf(control_node->op()) != BranchHint::kFalse) { 4681cb0ef41Sopenharmony_ci NodeProperties::ChangeOp(control_node, 4691cb0ef41Sopenharmony_ci common()->IfDefault(BranchHint::kFalse)); 4701cb0ef41Sopenharmony_ci } 4711cb0ef41Sopenharmony_ci return; 4721cb0ef41Sopenharmony_ci case IrOpcode::kIfTrue: { 4731cb0ef41Sopenharmony_ci Node* branch = NodeProperties::GetControlInput(control_node); 4741cb0ef41Sopenharmony_ci BranchHint hint = BranchHintOf(branch->op()); 4751cb0ef41Sopenharmony_ci if (hint == BranchHint::kTrue) { 4761cb0ef41Sopenharmony_ci // The other possibility is also deferred, so the responsible branch 4771cb0ef41Sopenharmony_ci // has to be before. 4781cb0ef41Sopenharmony_ci control_node = NodeProperties::GetControlInput(branch); 4791cb0ef41Sopenharmony_ci continue; 4801cb0ef41Sopenharmony_ci } 4811cb0ef41Sopenharmony_ci new_branch_hint = BranchHint::kFalse; 4821cb0ef41Sopenharmony_ci responsible_branch = branch; 4831cb0ef41Sopenharmony_ci break; 4841cb0ef41Sopenharmony_ci } 4851cb0ef41Sopenharmony_ci case IrOpcode::kIfFalse: { 4861cb0ef41Sopenharmony_ci Node* branch = NodeProperties::GetControlInput(control_node); 4871cb0ef41Sopenharmony_ci BranchHint hint = BranchHintOf(branch->op()); 4881cb0ef41Sopenharmony_ci if (hint == BranchHint::kFalse) { 4891cb0ef41Sopenharmony_ci // The other possibility is also deferred, so the responsible branch 4901cb0ef41Sopenharmony_ci // has to be before. 4911cb0ef41Sopenharmony_ci control_node = NodeProperties::GetControlInput(branch); 4921cb0ef41Sopenharmony_ci continue; 4931cb0ef41Sopenharmony_ci } 4941cb0ef41Sopenharmony_ci new_branch_hint = BranchHint::kTrue; 4951cb0ef41Sopenharmony_ci responsible_branch = branch; 4961cb0ef41Sopenharmony_ci break; 4971cb0ef41Sopenharmony_ci } 4981cb0ef41Sopenharmony_ci case IrOpcode::kMerge: 4991cb0ef41Sopenharmony_ci for (int i = 0; i < control_node->op()->ControlInputCount(); ++i) { 5001cb0ef41Sopenharmony_ci MarkControlDeferred(NodeProperties::GetControlInput(control_node, i)); 5011cb0ef41Sopenharmony_ci } 5021cb0ef41Sopenharmony_ci return; 5031cb0ef41Sopenharmony_ci case IrOpcode::kLoop: 5041cb0ef41Sopenharmony_ci control_node = NodeProperties::GetControlInput(control_node, 0); 5051cb0ef41Sopenharmony_ci continue; 5061cb0ef41Sopenharmony_ci case IrOpcode::kBranch: 5071cb0ef41Sopenharmony_ci case IrOpcode::kSwitch: 5081cb0ef41Sopenharmony_ci UNREACHABLE(); 5091cb0ef41Sopenharmony_ci case IrOpcode::kStart: 5101cb0ef41Sopenharmony_ci return; 5111cb0ef41Sopenharmony_ci default: 5121cb0ef41Sopenharmony_ci DCHECK_EQ(1, control_node->op()->ControlInputCount()); 5131cb0ef41Sopenharmony_ci control_node = NodeProperties::GetControlInput(control_node); 5141cb0ef41Sopenharmony_ci continue; 5151cb0ef41Sopenharmony_ci } 5161cb0ef41Sopenharmony_ci } 5171cb0ef41Sopenharmony_ci 5181cb0ef41Sopenharmony_ci BranchHint hint = BranchHintOf(responsible_branch->op()); 5191cb0ef41Sopenharmony_ci if (hint == new_branch_hint) return; 5201cb0ef41Sopenharmony_ci NodeProperties::ChangeOp(responsible_branch, 5211cb0ef41Sopenharmony_ci common()->Branch(new_branch_hint)); 5221cb0ef41Sopenharmony_ci} 5231cb0ef41Sopenharmony_ci 5241cb0ef41Sopenharmony_ciNode* RawMachineAssembler::TargetParameter() { 5251cb0ef41Sopenharmony_ci DCHECK_NOT_NULL(target_parameter_); 5261cb0ef41Sopenharmony_ci return target_parameter_; 5271cb0ef41Sopenharmony_ci} 5281cb0ef41Sopenharmony_ci 5291cb0ef41Sopenharmony_ciNode* RawMachineAssembler::Parameter(size_t index) { 5301cb0ef41Sopenharmony_ci DCHECK_LT(index, parameter_count()); 5311cb0ef41Sopenharmony_ci return parameters_[index]; 5321cb0ef41Sopenharmony_ci} 5331cb0ef41Sopenharmony_ci 5341cb0ef41Sopenharmony_ci 5351cb0ef41Sopenharmony_civoid RawMachineAssembler::Goto(RawMachineLabel* label) { 5361cb0ef41Sopenharmony_ci DCHECK(current_block_ != schedule()->end()); 5371cb0ef41Sopenharmony_ci schedule()->AddGoto(CurrentBlock(), Use(label)); 5381cb0ef41Sopenharmony_ci current_block_ = nullptr; 5391cb0ef41Sopenharmony_ci} 5401cb0ef41Sopenharmony_ci 5411cb0ef41Sopenharmony_ci 5421cb0ef41Sopenharmony_civoid RawMachineAssembler::Branch(Node* condition, RawMachineLabel* true_val, 5431cb0ef41Sopenharmony_ci RawMachineLabel* false_val) { 5441cb0ef41Sopenharmony_ci DCHECK(current_block_ != schedule()->end()); 5451cb0ef41Sopenharmony_ci Node* branch = MakeNode(common()->Branch(BranchHint::kNone), 1, &condition); 5461cb0ef41Sopenharmony_ci BasicBlock* true_block = schedule()->NewBasicBlock(); 5471cb0ef41Sopenharmony_ci BasicBlock* false_block = schedule()->NewBasicBlock(); 5481cb0ef41Sopenharmony_ci schedule()->AddBranch(CurrentBlock(), branch, true_block, false_block); 5491cb0ef41Sopenharmony_ci 5501cb0ef41Sopenharmony_ci true_block->AddNode(MakeNode(common()->IfTrue(), 1, &branch)); 5511cb0ef41Sopenharmony_ci schedule()->AddGoto(true_block, Use(true_val)); 5521cb0ef41Sopenharmony_ci 5531cb0ef41Sopenharmony_ci false_block->AddNode(MakeNode(common()->IfFalse(), 1, &branch)); 5541cb0ef41Sopenharmony_ci schedule()->AddGoto(false_block, Use(false_val)); 5551cb0ef41Sopenharmony_ci 5561cb0ef41Sopenharmony_ci current_block_ = nullptr; 5571cb0ef41Sopenharmony_ci} 5581cb0ef41Sopenharmony_ci 5591cb0ef41Sopenharmony_civoid RawMachineAssembler::Continuations(Node* call, RawMachineLabel* if_success, 5601cb0ef41Sopenharmony_ci RawMachineLabel* if_exception) { 5611cb0ef41Sopenharmony_ci DCHECK_NOT_NULL(schedule_); 5621cb0ef41Sopenharmony_ci DCHECK_NOT_NULL(current_block_); 5631cb0ef41Sopenharmony_ci schedule()->AddCall(CurrentBlock(), call, Use(if_success), Use(if_exception)); 5641cb0ef41Sopenharmony_ci current_block_ = nullptr; 5651cb0ef41Sopenharmony_ci} 5661cb0ef41Sopenharmony_ci 5671cb0ef41Sopenharmony_civoid RawMachineAssembler::Switch(Node* index, RawMachineLabel* default_label, 5681cb0ef41Sopenharmony_ci const int32_t* case_values, 5691cb0ef41Sopenharmony_ci RawMachineLabel** case_labels, 5701cb0ef41Sopenharmony_ci size_t case_count) { 5711cb0ef41Sopenharmony_ci DCHECK_NE(schedule()->end(), current_block_); 5721cb0ef41Sopenharmony_ci size_t succ_count = case_count + 1; 5731cb0ef41Sopenharmony_ci Node* switch_node = MakeNode(common()->Switch(succ_count), 1, &index); 5741cb0ef41Sopenharmony_ci BasicBlock** succ_blocks = zone()->NewArray<BasicBlock*>(succ_count); 5751cb0ef41Sopenharmony_ci for (size_t i = 0; i < case_count; ++i) { 5761cb0ef41Sopenharmony_ci int32_t case_value = case_values[i]; 5771cb0ef41Sopenharmony_ci BasicBlock* case_block = schedule()->NewBasicBlock(); 5781cb0ef41Sopenharmony_ci Node* case_node = 5791cb0ef41Sopenharmony_ci graph()->NewNode(common()->IfValue(case_value), switch_node); 5801cb0ef41Sopenharmony_ci schedule()->AddNode(case_block, case_node); 5811cb0ef41Sopenharmony_ci schedule()->AddGoto(case_block, Use(case_labels[i])); 5821cb0ef41Sopenharmony_ci succ_blocks[i] = case_block; 5831cb0ef41Sopenharmony_ci } 5841cb0ef41Sopenharmony_ci BasicBlock* default_block = schedule()->NewBasicBlock(); 5851cb0ef41Sopenharmony_ci Node* default_node = graph()->NewNode(common()->IfDefault(), switch_node); 5861cb0ef41Sopenharmony_ci schedule()->AddNode(default_block, default_node); 5871cb0ef41Sopenharmony_ci schedule()->AddGoto(default_block, Use(default_label)); 5881cb0ef41Sopenharmony_ci succ_blocks[case_count] = default_block; 5891cb0ef41Sopenharmony_ci schedule()->AddSwitch(CurrentBlock(), switch_node, succ_blocks, succ_count); 5901cb0ef41Sopenharmony_ci current_block_ = nullptr; 5911cb0ef41Sopenharmony_ci} 5921cb0ef41Sopenharmony_ci 5931cb0ef41Sopenharmony_civoid RawMachineAssembler::Return(Node* value) { 5941cb0ef41Sopenharmony_ci Node* values[] = {Int32Constant(0), value}; 5951cb0ef41Sopenharmony_ci Node* ret = MakeNode(common()->Return(1), 2, values); 5961cb0ef41Sopenharmony_ci schedule()->AddReturn(CurrentBlock(), ret); 5971cb0ef41Sopenharmony_ci current_block_ = nullptr; 5981cb0ef41Sopenharmony_ci} 5991cb0ef41Sopenharmony_ci 6001cb0ef41Sopenharmony_civoid RawMachineAssembler::Return(Node* v1, Node* v2) { 6011cb0ef41Sopenharmony_ci Node* values[] = {Int32Constant(0), v1, v2}; 6021cb0ef41Sopenharmony_ci Node* ret = MakeNode(common()->Return(2), 3, values); 6031cb0ef41Sopenharmony_ci schedule()->AddReturn(CurrentBlock(), ret); 6041cb0ef41Sopenharmony_ci current_block_ = nullptr; 6051cb0ef41Sopenharmony_ci} 6061cb0ef41Sopenharmony_ci 6071cb0ef41Sopenharmony_civoid RawMachineAssembler::Return(Node* v1, Node* v2, Node* v3) { 6081cb0ef41Sopenharmony_ci Node* values[] = {Int32Constant(0), v1, v2, v3}; 6091cb0ef41Sopenharmony_ci Node* ret = MakeNode(common()->Return(3), 4, values); 6101cb0ef41Sopenharmony_ci schedule()->AddReturn(CurrentBlock(), ret); 6111cb0ef41Sopenharmony_ci current_block_ = nullptr; 6121cb0ef41Sopenharmony_ci} 6131cb0ef41Sopenharmony_ci 6141cb0ef41Sopenharmony_civoid RawMachineAssembler::Return(Node* v1, Node* v2, Node* v3, Node* v4) { 6151cb0ef41Sopenharmony_ci Node* values[] = {Int32Constant(0), v1, v2, v3, v4}; 6161cb0ef41Sopenharmony_ci Node* ret = MakeNode(common()->Return(4), 5, values); 6171cb0ef41Sopenharmony_ci schedule()->AddReturn(CurrentBlock(), ret); 6181cb0ef41Sopenharmony_ci current_block_ = nullptr; 6191cb0ef41Sopenharmony_ci} 6201cb0ef41Sopenharmony_ci 6211cb0ef41Sopenharmony_civoid RawMachineAssembler::Return(int count, Node* vs[]) { 6221cb0ef41Sopenharmony_ci using Node_ptr = Node*; 6231cb0ef41Sopenharmony_ci Node** values = new Node_ptr[count + 1]; 6241cb0ef41Sopenharmony_ci values[0] = Int32Constant(0); 6251cb0ef41Sopenharmony_ci for (int i = 0; i < count; ++i) values[i + 1] = vs[i]; 6261cb0ef41Sopenharmony_ci Node* ret = MakeNode(common()->Return(count), count + 1, values); 6271cb0ef41Sopenharmony_ci schedule()->AddReturn(CurrentBlock(), ret); 6281cb0ef41Sopenharmony_ci current_block_ = nullptr; 6291cb0ef41Sopenharmony_ci delete[] values; 6301cb0ef41Sopenharmony_ci} 6311cb0ef41Sopenharmony_ci 6321cb0ef41Sopenharmony_civoid RawMachineAssembler::PopAndReturn(Node* pop, Node* value) { 6331cb0ef41Sopenharmony_ci // PopAndReturn is supposed to be using ONLY in CSA/Torque builtins for 6341cb0ef41Sopenharmony_ci // dropping ALL JS arguments that are currently located on the stack. 6351cb0ef41Sopenharmony_ci // The check below ensures that there are no directly accessible stack 6361cb0ef41Sopenharmony_ci // parameters from current builtin, which implies that the builtin with 6371cb0ef41Sopenharmony_ci // JS calling convention (TFJ) was created with kDontAdaptArgumentsSentinel. 6381cb0ef41Sopenharmony_ci // This simplifies semantics of this instruction because in case of presence 6391cb0ef41Sopenharmony_ci // of directly accessible stack parameters it's impossible to distinguish 6401cb0ef41Sopenharmony_ci // the following cases: 6411cb0ef41Sopenharmony_ci // 1) stack parameter is included in JS arguments (and therefore it will be 6421cb0ef41Sopenharmony_ci // dropped as a part of 'pop' number of arguments), 6431cb0ef41Sopenharmony_ci // 2) stack parameter is NOT included in JS arguments (and therefore it should 6441cb0ef41Sopenharmony_ci // be dropped in ADDITION to the 'pop' number of arguments). 6451cb0ef41Sopenharmony_ci // Additionally, in order to simplify assembly code, PopAndReturn is also 6461cb0ef41Sopenharmony_ci // not allowed in builtins with stub linkage and parameters on stack. 6471cb0ef41Sopenharmony_ci CHECK_EQ(call_descriptor()->ParameterSlotCount(), 0); 6481cb0ef41Sopenharmony_ci Node* values[] = {pop, value}; 6491cb0ef41Sopenharmony_ci Node* ret = MakeNode(common()->Return(1), 2, values); 6501cb0ef41Sopenharmony_ci schedule()->AddReturn(CurrentBlock(), ret); 6511cb0ef41Sopenharmony_ci current_block_ = nullptr; 6521cb0ef41Sopenharmony_ci} 6531cb0ef41Sopenharmony_ci 6541cb0ef41Sopenharmony_civoid RawMachineAssembler::PopAndReturn(Node* pop, Node* v1, Node* v2) { 6551cb0ef41Sopenharmony_ci Node* values[] = {pop, v1, v2}; 6561cb0ef41Sopenharmony_ci Node* ret = MakeNode(common()->Return(2), 3, values); 6571cb0ef41Sopenharmony_ci schedule()->AddReturn(CurrentBlock(), ret); 6581cb0ef41Sopenharmony_ci current_block_ = nullptr; 6591cb0ef41Sopenharmony_ci} 6601cb0ef41Sopenharmony_ci 6611cb0ef41Sopenharmony_civoid RawMachineAssembler::PopAndReturn(Node* pop, Node* v1, Node* v2, 6621cb0ef41Sopenharmony_ci Node* v3) { 6631cb0ef41Sopenharmony_ci Node* values[] = {pop, v1, v2, v3}; 6641cb0ef41Sopenharmony_ci Node* ret = MakeNode(common()->Return(3), 4, values); 6651cb0ef41Sopenharmony_ci schedule()->AddReturn(CurrentBlock(), ret); 6661cb0ef41Sopenharmony_ci current_block_ = nullptr; 6671cb0ef41Sopenharmony_ci} 6681cb0ef41Sopenharmony_ci 6691cb0ef41Sopenharmony_civoid RawMachineAssembler::PopAndReturn(Node* pop, Node* v1, Node* v2, Node* v3, 6701cb0ef41Sopenharmony_ci Node* v4) { 6711cb0ef41Sopenharmony_ci Node* values[] = {pop, v1, v2, v3, v4}; 6721cb0ef41Sopenharmony_ci Node* ret = MakeNode(common()->Return(4), 5, values); 6731cb0ef41Sopenharmony_ci schedule()->AddReturn(CurrentBlock(), ret); 6741cb0ef41Sopenharmony_ci current_block_ = nullptr; 6751cb0ef41Sopenharmony_ci} 6761cb0ef41Sopenharmony_ci 6771cb0ef41Sopenharmony_civoid RawMachineAssembler::AbortCSADcheck(Node* message) { 6781cb0ef41Sopenharmony_ci AddNode(machine()->AbortCSADcheck(), message); 6791cb0ef41Sopenharmony_ci} 6801cb0ef41Sopenharmony_ci 6811cb0ef41Sopenharmony_civoid RawMachineAssembler::DebugBreak() { AddNode(machine()->DebugBreak()); } 6821cb0ef41Sopenharmony_ci 6831cb0ef41Sopenharmony_civoid RawMachineAssembler::Unreachable() { 6841cb0ef41Sopenharmony_ci Node* ret = MakeNode(common()->Throw(), 0, nullptr); 6851cb0ef41Sopenharmony_ci schedule()->AddThrow(CurrentBlock(), ret); 6861cb0ef41Sopenharmony_ci current_block_ = nullptr; 6871cb0ef41Sopenharmony_ci} 6881cb0ef41Sopenharmony_ci 6891cb0ef41Sopenharmony_civoid RawMachineAssembler::Comment(const std::string& msg) { 6901cb0ef41Sopenharmony_ci size_t length = msg.length() + 1; 6911cb0ef41Sopenharmony_ci char* zone_buffer = zone()->NewArray<char>(length); 6921cb0ef41Sopenharmony_ci MemCopy(zone_buffer, msg.c_str(), length); 6931cb0ef41Sopenharmony_ci AddNode(machine()->Comment(zone_buffer)); 6941cb0ef41Sopenharmony_ci} 6951cb0ef41Sopenharmony_ci 6961cb0ef41Sopenharmony_civoid RawMachineAssembler::StaticAssert(Node* value, const char* source) { 6971cb0ef41Sopenharmony_ci AddNode(common()->StaticAssert(source), value); 6981cb0ef41Sopenharmony_ci} 6991cb0ef41Sopenharmony_ci 7001cb0ef41Sopenharmony_ciNode* RawMachineAssembler::CallN(CallDescriptor* call_descriptor, 7011cb0ef41Sopenharmony_ci int input_count, Node* const* inputs) { 7021cb0ef41Sopenharmony_ci DCHECK(!call_descriptor->NeedsFrameState()); 7031cb0ef41Sopenharmony_ci // +1 is for target. 7041cb0ef41Sopenharmony_ci DCHECK_EQ(input_count, call_descriptor->ParameterCount() + 1); 7051cb0ef41Sopenharmony_ci return AddNode(common()->Call(call_descriptor), input_count, inputs); 7061cb0ef41Sopenharmony_ci} 7071cb0ef41Sopenharmony_ci 7081cb0ef41Sopenharmony_ciNode* RawMachineAssembler::CallNWithFrameState(CallDescriptor* call_descriptor, 7091cb0ef41Sopenharmony_ci int input_count, 7101cb0ef41Sopenharmony_ci Node* const* inputs) { 7111cb0ef41Sopenharmony_ci DCHECK(call_descriptor->NeedsFrameState()); 7121cb0ef41Sopenharmony_ci // +2 is for target and frame state. 7131cb0ef41Sopenharmony_ci DCHECK_EQ(input_count, call_descriptor->ParameterCount() + 2); 7141cb0ef41Sopenharmony_ci return AddNode(common()->Call(call_descriptor), input_count, inputs); 7151cb0ef41Sopenharmony_ci} 7161cb0ef41Sopenharmony_ci 7171cb0ef41Sopenharmony_civoid RawMachineAssembler::TailCallN(CallDescriptor* call_descriptor, 7181cb0ef41Sopenharmony_ci int input_count, Node* const* inputs) { 7191cb0ef41Sopenharmony_ci // +1 is for target. 7201cb0ef41Sopenharmony_ci DCHECK_EQ(input_count, call_descriptor->ParameterCount() + 1); 7211cb0ef41Sopenharmony_ci Node* tail_call = 7221cb0ef41Sopenharmony_ci MakeNode(common()->TailCall(call_descriptor), input_count, inputs); 7231cb0ef41Sopenharmony_ci schedule()->AddTailCall(CurrentBlock(), tail_call); 7241cb0ef41Sopenharmony_ci current_block_ = nullptr; 7251cb0ef41Sopenharmony_ci} 7261cb0ef41Sopenharmony_ci 7271cb0ef41Sopenharmony_cinamespace { 7281cb0ef41Sopenharmony_ci 7291cb0ef41Sopenharmony_cienum FunctionDescriptorMode { kHasFunctionDescriptor, kNoFunctionDescriptor }; 7301cb0ef41Sopenharmony_ci 7311cb0ef41Sopenharmony_ciNode* CallCFunctionImpl( 7321cb0ef41Sopenharmony_ci RawMachineAssembler* rasm, Node* function, 7331cb0ef41Sopenharmony_ci base::Optional<MachineType> return_type, 7341cb0ef41Sopenharmony_ci std::initializer_list<RawMachineAssembler::CFunctionArg> args, 7351cb0ef41Sopenharmony_ci bool caller_saved_regs, SaveFPRegsMode mode, 7361cb0ef41Sopenharmony_ci FunctionDescriptorMode no_function_descriptor) { 7371cb0ef41Sopenharmony_ci static constexpr std::size_t kNumCArgs = 10; 7381cb0ef41Sopenharmony_ci 7391cb0ef41Sopenharmony_ci MachineSignature::Builder builder(rasm->zone(), return_type ? 1 : 0, 7401cb0ef41Sopenharmony_ci args.size()); 7411cb0ef41Sopenharmony_ci if (return_type) { 7421cb0ef41Sopenharmony_ci builder.AddReturn(*return_type); 7431cb0ef41Sopenharmony_ci } 7441cb0ef41Sopenharmony_ci for (const auto& arg : args) builder.AddParam(arg.first); 7451cb0ef41Sopenharmony_ci 7461cb0ef41Sopenharmony_ci bool caller_saved_fp_regs = 7471cb0ef41Sopenharmony_ci caller_saved_regs && (mode == SaveFPRegsMode::kSave); 7481cb0ef41Sopenharmony_ci CallDescriptor::Flags flags = CallDescriptor::kNoFlags; 7491cb0ef41Sopenharmony_ci if (caller_saved_regs) flags |= CallDescriptor::kCallerSavedRegisters; 7501cb0ef41Sopenharmony_ci if (caller_saved_fp_regs) flags |= CallDescriptor::kCallerSavedFPRegisters; 7511cb0ef41Sopenharmony_ci if (no_function_descriptor) flags |= CallDescriptor::kNoFunctionDescriptor; 7521cb0ef41Sopenharmony_ci auto call_descriptor = 7531cb0ef41Sopenharmony_ci Linkage::GetSimplifiedCDescriptor(rasm->zone(), builder.Build(), flags); 7541cb0ef41Sopenharmony_ci 7551cb0ef41Sopenharmony_ci base::SmallVector<Node*, kNumCArgs> nodes(args.size() + 1); 7561cb0ef41Sopenharmony_ci nodes[0] = function; 7571cb0ef41Sopenharmony_ci std::transform( 7581cb0ef41Sopenharmony_ci args.begin(), args.end(), std::next(nodes.begin()), 7591cb0ef41Sopenharmony_ci [](const RawMachineAssembler::CFunctionArg& arg) { return arg.second; }); 7601cb0ef41Sopenharmony_ci 7611cb0ef41Sopenharmony_ci auto common = rasm->common(); 7621cb0ef41Sopenharmony_ci return rasm->AddNode(common->Call(call_descriptor), 7631cb0ef41Sopenharmony_ci static_cast<int>(nodes.size()), nodes.begin()); 7641cb0ef41Sopenharmony_ci} 7651cb0ef41Sopenharmony_ci 7661cb0ef41Sopenharmony_ci} // namespace 7671cb0ef41Sopenharmony_ci 7681cb0ef41Sopenharmony_ciNode* RawMachineAssembler::CallCFunction( 7691cb0ef41Sopenharmony_ci Node* function, base::Optional<MachineType> return_type, 7701cb0ef41Sopenharmony_ci std::initializer_list<RawMachineAssembler::CFunctionArg> args) { 7711cb0ef41Sopenharmony_ci return CallCFunctionImpl(this, function, return_type, args, false, 7721cb0ef41Sopenharmony_ci SaveFPRegsMode::kIgnore, kHasFunctionDescriptor); 7731cb0ef41Sopenharmony_ci} 7741cb0ef41Sopenharmony_ci 7751cb0ef41Sopenharmony_ciNode* RawMachineAssembler::CallCFunctionWithoutFunctionDescriptor( 7761cb0ef41Sopenharmony_ci Node* function, MachineType return_type, 7771cb0ef41Sopenharmony_ci std::initializer_list<RawMachineAssembler::CFunctionArg> args) { 7781cb0ef41Sopenharmony_ci return CallCFunctionImpl(this, function, return_type, args, false, 7791cb0ef41Sopenharmony_ci SaveFPRegsMode::kIgnore, kNoFunctionDescriptor); 7801cb0ef41Sopenharmony_ci} 7811cb0ef41Sopenharmony_ci 7821cb0ef41Sopenharmony_ciNode* RawMachineAssembler::CallCFunctionWithCallerSavedRegisters( 7831cb0ef41Sopenharmony_ci Node* function, MachineType return_type, SaveFPRegsMode mode, 7841cb0ef41Sopenharmony_ci std::initializer_list<RawMachineAssembler::CFunctionArg> args) { 7851cb0ef41Sopenharmony_ci return CallCFunctionImpl(this, function, return_type, args, true, mode, 7861cb0ef41Sopenharmony_ci kHasFunctionDescriptor); 7871cb0ef41Sopenharmony_ci} 7881cb0ef41Sopenharmony_ci 7891cb0ef41Sopenharmony_ciBasicBlock* RawMachineAssembler::Use(RawMachineLabel* label) { 7901cb0ef41Sopenharmony_ci label->used_ = true; 7911cb0ef41Sopenharmony_ci return EnsureBlock(label); 7921cb0ef41Sopenharmony_ci} 7931cb0ef41Sopenharmony_ci 7941cb0ef41Sopenharmony_ciBasicBlock* RawMachineAssembler::EnsureBlock(RawMachineLabel* label) { 7951cb0ef41Sopenharmony_ci if (label->block_ == nullptr) { 7961cb0ef41Sopenharmony_ci label->block_ = schedule()->NewBasicBlock(); 7971cb0ef41Sopenharmony_ci } 7981cb0ef41Sopenharmony_ci return label->block_; 7991cb0ef41Sopenharmony_ci} 8001cb0ef41Sopenharmony_ci 8011cb0ef41Sopenharmony_civoid RawMachineAssembler::Bind(RawMachineLabel* label) { 8021cb0ef41Sopenharmony_ci DCHECK_NULL(current_block_); 8031cb0ef41Sopenharmony_ci DCHECK(!label->bound_); 8041cb0ef41Sopenharmony_ci label->bound_ = true; 8051cb0ef41Sopenharmony_ci current_block_ = EnsureBlock(label); 8061cb0ef41Sopenharmony_ci current_block_->set_deferred(label->deferred_); 8071cb0ef41Sopenharmony_ci} 8081cb0ef41Sopenharmony_ci 8091cb0ef41Sopenharmony_ci#if DEBUG 8101cb0ef41Sopenharmony_civoid RawMachineAssembler::Bind(RawMachineLabel* label, 8111cb0ef41Sopenharmony_ci AssemblerDebugInfo info) { 8121cb0ef41Sopenharmony_ci if (current_block_ != nullptr) { 8131cb0ef41Sopenharmony_ci std::stringstream str; 8141cb0ef41Sopenharmony_ci str << "Binding label without closing previous block:" 8151cb0ef41Sopenharmony_ci << "\n# label: " << info 8161cb0ef41Sopenharmony_ci << "\n# previous block: " << *current_block_; 8171cb0ef41Sopenharmony_ci FATAL("%s", str.str().c_str()); 8181cb0ef41Sopenharmony_ci } 8191cb0ef41Sopenharmony_ci Bind(label); 8201cb0ef41Sopenharmony_ci current_block_->set_debug_info(info); 8211cb0ef41Sopenharmony_ci} 8221cb0ef41Sopenharmony_ci 8231cb0ef41Sopenharmony_civoid RawMachineAssembler::PrintCurrentBlock(std::ostream& os) { 8241cb0ef41Sopenharmony_ci os << CurrentBlock(); 8251cb0ef41Sopenharmony_ci} 8261cb0ef41Sopenharmony_ci 8271cb0ef41Sopenharmony_civoid RawMachineAssembler::SetInitialDebugInformation( 8281cb0ef41Sopenharmony_ci AssemblerDebugInfo debug_info) { 8291cb0ef41Sopenharmony_ci CurrentBlock()->set_debug_info(debug_info); 8301cb0ef41Sopenharmony_ci} 8311cb0ef41Sopenharmony_ci#endif // DEBUG 8321cb0ef41Sopenharmony_ci 8331cb0ef41Sopenharmony_cibool RawMachineAssembler::InsideBlock() { return current_block_ != nullptr; } 8341cb0ef41Sopenharmony_ci 8351cb0ef41Sopenharmony_ciBasicBlock* RawMachineAssembler::CurrentBlock() { 8361cb0ef41Sopenharmony_ci DCHECK(current_block_); 8371cb0ef41Sopenharmony_ci return current_block_; 8381cb0ef41Sopenharmony_ci} 8391cb0ef41Sopenharmony_ci 8401cb0ef41Sopenharmony_ciNode* RawMachineAssembler::Phi(MachineRepresentation rep, int input_count, 8411cb0ef41Sopenharmony_ci Node* const* inputs) { 8421cb0ef41Sopenharmony_ci Node** buffer = zone()->NewArray<Node*>(input_count + 1); 8431cb0ef41Sopenharmony_ci std::copy(inputs, inputs + input_count, buffer); 8441cb0ef41Sopenharmony_ci buffer[input_count] = graph()->start(); 8451cb0ef41Sopenharmony_ci return AddNode(common()->Phi(rep, input_count), input_count + 1, buffer); 8461cb0ef41Sopenharmony_ci} 8471cb0ef41Sopenharmony_ci 8481cb0ef41Sopenharmony_civoid RawMachineAssembler::AppendPhiInput(Node* phi, Node* new_input) { 8491cb0ef41Sopenharmony_ci const Operator* op = phi->op(); 8501cb0ef41Sopenharmony_ci const Operator* new_op = common()->ResizeMergeOrPhi(op, phi->InputCount()); 8511cb0ef41Sopenharmony_ci phi->InsertInput(zone(), phi->InputCount() - 1, new_input); 8521cb0ef41Sopenharmony_ci NodeProperties::ChangeOp(phi, new_op); 8531cb0ef41Sopenharmony_ci} 8541cb0ef41Sopenharmony_ci 8551cb0ef41Sopenharmony_ciNode* RawMachineAssembler::AddNode(const Operator* op, int input_count, 8561cb0ef41Sopenharmony_ci Node* const* inputs) { 8571cb0ef41Sopenharmony_ci DCHECK_NOT_NULL(schedule_); 8581cb0ef41Sopenharmony_ci DCHECK_NOT_NULL(current_block_); 8591cb0ef41Sopenharmony_ci Node* node = MakeNode(op, input_count, inputs); 8601cb0ef41Sopenharmony_ci schedule()->AddNode(CurrentBlock(), node); 8611cb0ef41Sopenharmony_ci return node; 8621cb0ef41Sopenharmony_ci} 8631cb0ef41Sopenharmony_ci 8641cb0ef41Sopenharmony_ciNode* RawMachineAssembler::MakeNode(const Operator* op, int input_count, 8651cb0ef41Sopenharmony_ci Node* const* inputs) { 8661cb0ef41Sopenharmony_ci // The raw machine assembler nodes do not have effect and control inputs, 8671cb0ef41Sopenharmony_ci // so we disable checking input counts here. 8681cb0ef41Sopenharmony_ci return graph()->NewNodeUnchecked(op, input_count, inputs); 8691cb0ef41Sopenharmony_ci} 8701cb0ef41Sopenharmony_ci 8711cb0ef41Sopenharmony_ciRawMachineLabel::~RawMachineLabel() { 8721cb0ef41Sopenharmony_ci#if DEBUG 8731cb0ef41Sopenharmony_ci if (bound_ == used_) return; 8741cb0ef41Sopenharmony_ci std::stringstream str; 8751cb0ef41Sopenharmony_ci if (bound_) { 8761cb0ef41Sopenharmony_ci str << "A label has been bound but it's not used." 8771cb0ef41Sopenharmony_ci << "\n# label: " << *block_; 8781cb0ef41Sopenharmony_ci } else { 8791cb0ef41Sopenharmony_ci str << "A label has been used but it's not bound."; 8801cb0ef41Sopenharmony_ci } 8811cb0ef41Sopenharmony_ci FATAL("%s", str.str().c_str()); 8821cb0ef41Sopenharmony_ci#endif // DEBUG 8831cb0ef41Sopenharmony_ci} 8841cb0ef41Sopenharmony_ci 8851cb0ef41Sopenharmony_ci} // namespace compiler 8861cb0ef41Sopenharmony_ci} // namespace internal 8871cb0ef41Sopenharmony_ci} // namespace v8 888