blob: b93ec66338a228b919d25b40d0f140be7d47bfa4 [file] [log] [blame]
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001// 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.
4
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"
9
10namespace v8 {
11namespace internal {
12namespace compiler {
13
14RawMachineAssembler::RawMachineAssembler(Graph* graph,
15 MachineSignature* machine_sig,
Emily Bernierd0a1eb72015-03-24 16:35:39 -040016 MachineType word,
17 MachineOperatorBuilder::Flags flags)
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018 : GraphBuilder(graph),
19 schedule_(new (zone()) Schedule(zone())),
Emily Bernierd0a1eb72015-03-24 16:35:39 -040020 machine_(zone(), word, flags),
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021 common_(zone()),
22 machine_sig_(machine_sig),
23 call_descriptor_(
24 Linkage::GetSimplifiedCDescriptor(graph->zone(), machine_sig)),
25 parameters_(NULL),
26 exit_label_(schedule()->end()),
27 current_block_(schedule()->start()) {
28 int param_count = static_cast<int>(parameter_count());
29 Node* s = graph->NewNode(common_.Start(param_count));
30 graph->SetStart(s);
31 if (parameter_count() == 0) return;
32 parameters_ = zone()->NewArray<Node*>(param_count);
33 for (size_t i = 0; i < parameter_count(); ++i) {
34 parameters_[i] =
35 NewNode(common()->Parameter(static_cast<int>(i)), graph->start());
36 }
37}
38
39
40Schedule* RawMachineAssembler::Export() {
41 // Compute the correct codegen order.
42 DCHECK(schedule_->rpo_order()->empty());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040043 Scheduler::ComputeSpecialRPO(zone(), schedule_);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000044 // Invalidate MachineAssembler.
45 Schedule* schedule = schedule_;
46 schedule_ = NULL;
47 return schedule;
48}
49
50
51Node* RawMachineAssembler::Parameter(size_t index) {
52 DCHECK(index < parameter_count());
53 return parameters_[index];
54}
55
56
57RawMachineAssembler::Label* RawMachineAssembler::Exit() {
58 exit_label_.used_ = true;
59 return &exit_label_;
60}
61
62
63void RawMachineAssembler::Goto(Label* label) {
64 DCHECK(current_block_ != schedule()->end());
65 schedule()->AddGoto(CurrentBlock(), Use(label));
66 current_block_ = NULL;
67}
68
69
70void RawMachineAssembler::Branch(Node* condition, Label* true_val,
71 Label* false_val) {
72 DCHECK(current_block_ != schedule()->end());
73 Node* branch = NewNode(common()->Branch(), condition);
74 schedule()->AddBranch(CurrentBlock(), branch, Use(true_val), Use(false_val));
75 current_block_ = NULL;
76}
77
78
79void RawMachineAssembler::Return(Node* value) {
80 schedule()->AddReturn(CurrentBlock(), value);
81 current_block_ = NULL;
82}
83
84
85Node* RawMachineAssembler::CallFunctionStub0(Node* function, Node* receiver,
86 Node* context, Node* frame_state,
87 CallFunctionFlags flags) {
88 Callable callable = CodeFactory::CallFunction(isolate(), 0, flags);
89 CallDescriptor* desc = Linkage::GetStubCallDescriptor(
Emily Bernierd0a1eb72015-03-24 16:35:39 -040090 callable.descriptor(), 1, CallDescriptor::kNeedsFrameState,
91 Operator::kNoProperties, zone());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000092 Node* stub_code = HeapConstant(callable.code());
93 Node* call = graph()->NewNode(common()->Call(desc), stub_code, function,
94 receiver, context, frame_state);
95 schedule()->AddNode(CurrentBlock(), call);
96 return call;
97}
98
99
100Node* RawMachineAssembler::CallJS0(Node* function, Node* receiver,
101 Node* context, Node* frame_state) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400102 CallDescriptor* descriptor =
103 Linkage::GetJSCallDescriptor(1, zone(), CallDescriptor::kNeedsFrameState);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000104 Node* call = graph()->NewNode(common()->Call(descriptor), function, receiver,
105 context, frame_state);
106 schedule()->AddNode(CurrentBlock(), call);
107 return call;
108}
109
110
111Node* RawMachineAssembler::CallRuntime1(Runtime::FunctionId function,
112 Node* arg0, Node* context,
113 Node* frame_state) {
114 CallDescriptor* descriptor = Linkage::GetRuntimeCallDescriptor(
115 function, 1, Operator::kNoProperties, zone());
116
117 Node* centry = HeapConstant(CEntryStub(isolate(), 1).GetCode());
118 Node* ref = NewNode(
119 common()->ExternalConstant(ExternalReference(function, isolate())));
120 Node* arity = Int32Constant(1);
121
122 Node* call = graph()->NewNode(common()->Call(descriptor), centry, arg0, ref,
123 arity, context, frame_state);
124 schedule()->AddNode(CurrentBlock(), call);
125 return call;
126}
127
128
129void RawMachineAssembler::Bind(Label* label) {
130 DCHECK(current_block_ == NULL);
131 DCHECK(!label->bound_);
132 label->bound_ = true;
133 current_block_ = EnsureBlock(label);
134}
135
136
137BasicBlock* RawMachineAssembler::Use(Label* label) {
138 label->used_ = true;
139 return EnsureBlock(label);
140}
141
142
143BasicBlock* RawMachineAssembler::EnsureBlock(Label* label) {
144 if (label->block_ == NULL) label->block_ = schedule()->NewBasicBlock();
145 return label->block_;
146}
147
148
149BasicBlock* RawMachineAssembler::CurrentBlock() {
150 DCHECK(current_block_);
151 return current_block_;
152}
153
154
155Node* RawMachineAssembler::MakeNode(const Operator* op, int input_count,
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400156 Node** inputs, bool incomplete) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000157 DCHECK(ScheduleValid());
158 DCHECK(current_block_ != NULL);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400159 Node* node = graph()->NewNode(op, input_count, inputs, incomplete);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000160 BasicBlock* block = op->opcode() == IrOpcode::kParameter ? schedule()->start()
161 : CurrentBlock();
162 schedule()->AddNode(block, node);
163 return node;
164}
165
166} // namespace compiler
167} // namespace internal
168} // namespace v8