1 // Copyright 2014 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "src/code-factory.h"
6 #include "src/compiler/pipeline.h"
7 #include "src/compiler/raw-machine-assembler.h"
8 #include "src/compiler/scheduler.h"
14 RawMachineAssembler::RawMachineAssembler(Graph* graph,
15 MachineSignature* machine_sig,
17 : GraphBuilder(graph),
18 schedule_(new (zone()) Schedule(zone())),
21 machine_sig_(machine_sig),
23 Linkage::GetSimplifiedCDescriptor(graph->zone(), machine_sig)),
25 exit_label_(schedule()->end()),
26 current_block_(schedule()->start()) {
27 int param_count = static_cast<int>(parameter_count());
28 Node* s = graph->NewNode(common_.Start(param_count));
30 if (parameter_count() == 0) return;
31 parameters_ = zone()->NewArray<Node*>(param_count);
32 for (size_t i = 0; i < parameter_count(); ++i) {
34 NewNode(common()->Parameter(static_cast<int>(i)), graph->start());
39 Schedule* RawMachineAssembler::Export() {
40 // Compute the correct codegen order.
41 DCHECK(schedule_->rpo_order()->empty());
42 Scheduler::ComputeSpecialRPO(schedule_);
43 // Invalidate MachineAssembler.
44 Schedule* schedule = schedule_;
50 Node* RawMachineAssembler::Parameter(size_t index) {
51 DCHECK(index < parameter_count());
52 return parameters_[index];
56 RawMachineAssembler::Label* RawMachineAssembler::Exit() {
57 exit_label_.used_ = true;
62 void RawMachineAssembler::Goto(Label* label) {
63 DCHECK(current_block_ != schedule()->end());
64 schedule()->AddGoto(CurrentBlock(), Use(label));
65 current_block_ = NULL;
69 void RawMachineAssembler::Branch(Node* condition, Label* true_val,
71 DCHECK(current_block_ != schedule()->end());
72 Node* branch = NewNode(common()->Branch(), condition);
73 schedule()->AddBranch(CurrentBlock(), branch, Use(true_val), Use(false_val));
74 current_block_ = NULL;
78 void RawMachineAssembler::Return(Node* value) {
79 schedule()->AddReturn(CurrentBlock(), value);
80 current_block_ = NULL;
84 Node* RawMachineAssembler::CallFunctionStub0(Node* function, Node* receiver,
85 Node* context, Node* frame_state,
86 CallFunctionFlags flags) {
87 Callable callable = CodeFactory::CallFunction(isolate(), 0, flags);
88 CallDescriptor* desc = Linkage::GetStubCallDescriptor(
89 callable.descriptor(), 1, CallDescriptor::kNeedsFrameState, zone());
90 Node* stub_code = HeapConstant(callable.code());
91 Node* call = graph()->NewNode(common()->Call(desc), stub_code, function,
92 receiver, context, frame_state);
93 schedule()->AddNode(CurrentBlock(), call);
98 Node* RawMachineAssembler::CallJS0(Node* function, Node* receiver,
99 Node* context, Node* frame_state) {
100 CallDescriptor* descriptor = Linkage::GetJSCallDescriptor(1, zone());
101 Node* call = graph()->NewNode(common()->Call(descriptor), function, receiver,
102 context, frame_state);
103 schedule()->AddNode(CurrentBlock(), call);
108 Node* RawMachineAssembler::CallRuntime1(Runtime::FunctionId function,
109 Node* arg0, Node* context,
111 CallDescriptor* descriptor = Linkage::GetRuntimeCallDescriptor(
112 function, 1, Operator::kNoProperties, zone());
114 Node* centry = HeapConstant(CEntryStub(isolate(), 1).GetCode());
116 common()->ExternalConstant(ExternalReference(function, isolate())));
117 Node* arity = Int32Constant(1);
119 Node* call = graph()->NewNode(common()->Call(descriptor), centry, arg0, ref,
120 arity, context, frame_state);
121 schedule()->AddNode(CurrentBlock(), call);
126 void RawMachineAssembler::Bind(Label* label) {
127 DCHECK(current_block_ == NULL);
128 DCHECK(!label->bound_);
129 label->bound_ = true;
130 current_block_ = EnsureBlock(label);
134 BasicBlock* RawMachineAssembler::Use(Label* label) {
136 return EnsureBlock(label);
140 BasicBlock* RawMachineAssembler::EnsureBlock(Label* label) {
141 if (label->block_ == NULL) label->block_ = schedule()->NewBasicBlock();
142 return label->block_;
146 BasicBlock* RawMachineAssembler::CurrentBlock() {
147 DCHECK(current_block_);
148 return current_block_;
152 Node* RawMachineAssembler::MakeNode(const Operator* op, int input_count,
154 DCHECK(ScheduleValid());
155 DCHECK(current_block_ != NULL);
156 Node* node = graph()->NewNode(op, input_count, inputs);
157 BasicBlock* block = op->opcode() == IrOpcode::kParameter ? schedule()->start()
159 schedule()->AddNode(block, node);
163 } // namespace compiler
164 } // namespace internal