1b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Copyright 2014 the V8 project authors. All rights reserved.
2b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// found in the LICENSE file.
4b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/code-factory.h"
6b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/compiler/pipeline.h"
7b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/compiler/raw-machine-assembler.h"
8b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/compiler/scheduler.h"
9b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
10b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace v8 {
11b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace internal {
12b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace compiler {
13b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
14b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochRawMachineAssembler::RawMachineAssembler(Graph* graph,
15b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                         MachineSignature* machine_sig,
16b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                         MachineType word)
17b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    : GraphBuilder(graph),
18b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      schedule_(new (zone()) Schedule(zone())),
19b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      machine_(word),
20b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      common_(zone()),
21b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      machine_sig_(machine_sig),
22b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      call_descriptor_(
23b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          Linkage::GetSimplifiedCDescriptor(graph->zone(), machine_sig)),
24b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      parameters_(NULL),
25b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      exit_label_(schedule()->end()),
26b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      current_block_(schedule()->start()) {
27b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int param_count = static_cast<int>(parameter_count());
28b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Node* s = graph->NewNode(common_.Start(param_count));
29b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  graph->SetStart(s);
30b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (parameter_count() == 0) return;
31b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  parameters_ = zone()->NewArray<Node*>(param_count);
32b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (size_t i = 0; i < parameter_count(); ++i) {
33b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    parameters_[i] =
34b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        NewNode(common()->Parameter(static_cast<int>(i)), graph->start());
35b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
36b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
37b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
38b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
39b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochSchedule* RawMachineAssembler::Export() {
40b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Compute the correct codegen order.
41b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(schedule_->rpo_order()->empty());
42b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Scheduler::ComputeSpecialRPO(schedule_);
43b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Invalidate MachineAssembler.
44b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Schedule* schedule = schedule_;
45b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  schedule_ = NULL;
46b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return schedule;
47b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
48b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
49b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
50b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochNode* RawMachineAssembler::Parameter(size_t index) {
51b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(index < parameter_count());
52b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return parameters_[index];
53b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
54b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
55b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
56b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochRawMachineAssembler::Label* RawMachineAssembler::Exit() {
57b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  exit_label_.used_ = true;
58b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return &exit_label_;
59b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
60b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
61b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
62b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid RawMachineAssembler::Goto(Label* label) {
63b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(current_block_ != schedule()->end());
64b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  schedule()->AddGoto(CurrentBlock(), Use(label));
65b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  current_block_ = NULL;
66b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
67b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
68b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
69b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid RawMachineAssembler::Branch(Node* condition, Label* true_val,
70b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                 Label* false_val) {
71b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(current_block_ != schedule()->end());
72b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Node* branch = NewNode(common()->Branch(), condition);
73b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  schedule()->AddBranch(CurrentBlock(), branch, Use(true_val), Use(false_val));
74b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  current_block_ = NULL;
75b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
76b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
77b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
78b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid RawMachineAssembler::Return(Node* value) {
79b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  schedule()->AddReturn(CurrentBlock(), value);
80b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  current_block_ = NULL;
81b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
82b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
83b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
84b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochNode* RawMachineAssembler::CallFunctionStub0(Node* function, Node* receiver,
85b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                             Node* context, Node* frame_state,
86b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                             CallFunctionFlags flags) {
87b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Callable callable = CodeFactory::CallFunction(isolate(), 0, flags);
88b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CallDescriptor* desc = Linkage::GetStubCallDescriptor(
89b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      callable.descriptor(), 1, CallDescriptor::kNeedsFrameState, zone());
90b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Node* stub_code = HeapConstant(callable.code());
91b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Node* call = graph()->NewNode(common()->Call(desc), stub_code, function,
92b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                receiver, context, frame_state);
93b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  schedule()->AddNode(CurrentBlock(), call);
94b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return call;
95b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
96b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
97b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
98b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochNode* RawMachineAssembler::CallJS0(Node* function, Node* receiver,
99b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                   Node* context, Node* frame_state) {
100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CallDescriptor* descriptor = Linkage::GetJSCallDescriptor(1, zone());
101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Node* call = graph()->NewNode(common()->Call(descriptor), function, receiver,
102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                context, frame_state);
103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  schedule()->AddNode(CurrentBlock(), call);
104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return call;
105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochNode* RawMachineAssembler::CallRuntime1(Runtime::FunctionId function,
109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                        Node* arg0, Node* context,
110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                        Node* frame_state) {
111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CallDescriptor* descriptor = Linkage::GetRuntimeCallDescriptor(
112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      function, 1, Operator::kNoProperties, zone());
113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Node* centry = HeapConstant(CEntryStub(isolate(), 1).GetCode());
115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Node* ref = NewNode(
116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      common()->ExternalConstant(ExternalReference(function, isolate())));
117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Node* arity = Int32Constant(1);
118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Node* call = graph()->NewNode(common()->Call(descriptor), centry, arg0, ref,
120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                arity, context, frame_state);
121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  schedule()->AddNode(CurrentBlock(), call);
122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return call;
123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid RawMachineAssembler::Bind(Label* label) {
127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(current_block_ == NULL);
128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!label->bound_);
129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  label->bound_ = true;
130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  current_block_ = EnsureBlock(label);
131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochBasicBlock* RawMachineAssembler::Use(Label* label) {
135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  label->used_ = true;
136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return EnsureBlock(label);
137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochBasicBlock* RawMachineAssembler::EnsureBlock(Label* label) {
141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (label->block_ == NULL) label->block_ = schedule()->NewBasicBlock();
142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return label->block_;
143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochBasicBlock* RawMachineAssembler::CurrentBlock() {
147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(current_block_);
148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return current_block_;
149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochNode* RawMachineAssembler::MakeNode(const Operator* op, int input_count,
153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                    Node** inputs) {
154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(ScheduleValid());
155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(current_block_ != NULL);
156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Node* node = graph()->NewNode(op, input_count, inputs);
157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  BasicBlock* block = op->opcode() == IrOpcode::kParameter ? schedule()->start()
158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                           : CurrentBlock();
159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  schedule()->AddNode(block, node);
160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return node;
161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}  // namespace compiler
164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}  // namespace internal
165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}  // namespace v8
166