blob: c13bd74f40833f62ea6de944d1982ba872496ecc [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#ifndef V8_COMPILER_LINKAGE_IMPL_H_
6#define V8_COMPILER_LINKAGE_IMPL_H_
7
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008#include "src/code-stubs.h"
9
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010namespace v8 {
11namespace internal {
12namespace compiler {
13
14// TODO(titzer): replace uses of int with size_t in LinkageHelper.
15template <typename LinkageTraits>
16class LinkageHelper {
17 public:
18 static const RegList kNoCalleeSaved = 0;
19
20 static void AddReturnLocations(LocationSignature::Builder* locations) {
21 DCHECK(locations->return_count_ <= 2);
22 if (locations->return_count_ > 0) {
23 locations->AddReturn(regloc(LinkageTraits::ReturnValueReg()));
24 }
25 if (locations->return_count_ > 1) {
26 locations->AddReturn(regloc(LinkageTraits::ReturnValue2Reg()));
27 }
28 }
29
30 // TODO(turbofan): cache call descriptors for JSFunction calls.
Emily Bernierd0a1eb72015-03-24 16:35:39 -040031 static CallDescriptor* GetJSCallDescriptor(Zone* zone, int js_parameter_count,
32 CallDescriptor::Flags flags) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000033 const size_t return_count = 1;
34 const size_t context_count = 1;
35 const size_t parameter_count = js_parameter_count + context_count;
36
37 LocationSignature::Builder locations(zone, return_count, parameter_count);
38 MachineSignature::Builder types(zone, return_count, parameter_count);
39
40 // Add returns.
41 AddReturnLocations(&locations);
42 for (size_t i = 0; i < return_count; i++) {
43 types.AddReturn(kMachAnyTagged);
44 }
45
46 // All parameters to JS calls go on the stack.
47 for (int i = 0; i < js_parameter_count; i++) {
48 int spill_slot_index = i - js_parameter_count;
49 locations.AddParam(stackloc(spill_slot_index));
50 types.AddParam(kMachAnyTagged);
51 }
52 // Add context.
53 locations.AddParam(regloc(LinkageTraits::ContextReg()));
54 types.AddParam(kMachAnyTagged);
55
56 // The target for JS function calls is the JSFunction object.
57 MachineType target_type = kMachAnyTagged;
58 LinkageLocation target_loc = regloc(LinkageTraits::JSCallFunctionReg());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040059 return new (zone) CallDescriptor( // --
60 CallDescriptor::kCallJSFunction, // kind
61 target_type, // target MachineType
62 target_loc, // target location
63 types.Build(), // machine_sig
64 locations.Build(), // location_sig
65 js_parameter_count, // js_parameter_count
66 Operator::kNoProperties, // properties
67 kNoCalleeSaved, // callee-saved
68 flags, // flags
69 "js-call");
Ben Murdochb8a8cc12014-11-26 15:28:44 +000070 }
71
72
73 // TODO(turbofan): cache call descriptors for runtime calls.
74 static CallDescriptor* GetRuntimeCallDescriptor(
75 Zone* zone, Runtime::FunctionId function_id, int js_parameter_count,
76 Operator::Properties properties) {
77 const size_t function_count = 1;
78 const size_t num_args_count = 1;
79 const size_t context_count = 1;
80 const size_t parameter_count = function_count +
81 static_cast<size_t>(js_parameter_count) +
82 num_args_count + context_count;
83
84 const Runtime::Function* function = Runtime::FunctionForId(function_id);
85 const size_t return_count = static_cast<size_t>(function->result_size);
86
87 LocationSignature::Builder locations(zone, return_count, parameter_count);
88 MachineSignature::Builder types(zone, return_count, parameter_count);
89
90 // Add returns.
91 AddReturnLocations(&locations);
92 for (size_t i = 0; i < return_count; i++) {
93 types.AddReturn(kMachAnyTagged);
94 }
95
96 // All parameters to the runtime call go on the stack.
97 for (int i = 0; i < js_parameter_count; i++) {
98 locations.AddParam(stackloc(i - js_parameter_count));
99 types.AddParam(kMachAnyTagged);
100 }
101 // Add runtime function itself.
102 locations.AddParam(regloc(LinkageTraits::RuntimeCallFunctionReg()));
103 types.AddParam(kMachAnyTagged);
104
105 // Add runtime call argument count.
106 locations.AddParam(regloc(LinkageTraits::RuntimeCallArgCountReg()));
107 types.AddParam(kMachPtr);
108
109 // Add context.
110 locations.AddParam(regloc(LinkageTraits::ContextReg()));
111 types.AddParam(kMachAnyTagged);
112
113 CallDescriptor::Flags flags = Linkage::NeedsFrameState(function_id)
114 ? CallDescriptor::kNeedsFrameState
115 : CallDescriptor::kNoFlags;
116
117 // The target for runtime calls is a code object.
118 MachineType target_type = kMachAnyTagged;
119 LinkageLocation target_loc = LinkageLocation::AnyRegister();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400120 return new (zone) CallDescriptor( // --
121 CallDescriptor::kCallCodeObject, // kind
122 target_type, // target MachineType
123 target_loc, // target location
124 types.Build(), // machine_sig
125 locations.Build(), // location_sig
126 js_parameter_count, // js_parameter_count
127 properties, // properties
128 kNoCalleeSaved, // callee-saved
129 flags, // flags
130 function->name); // debug name
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000131 }
132
133
134 // TODO(turbofan): cache call descriptors for code stub calls.
135 static CallDescriptor* GetStubCallDescriptor(
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400136 Zone* zone, const CallInterfaceDescriptor& descriptor,
137 int stack_parameter_count, CallDescriptor::Flags flags,
138 Operator::Properties properties) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000139 const int register_parameter_count =
140 descriptor.GetEnvironmentParameterCount();
141 const int js_parameter_count =
142 register_parameter_count + stack_parameter_count;
143 const int context_count = 1;
144 const size_t return_count = 1;
145 const size_t parameter_count =
146 static_cast<size_t>(js_parameter_count + context_count);
147
148 LocationSignature::Builder locations(zone, return_count, parameter_count);
149 MachineSignature::Builder types(zone, return_count, parameter_count);
150
151 // Add return location.
152 AddReturnLocations(&locations);
153 types.AddReturn(kMachAnyTagged);
154
155 // Add parameters in registers and on the stack.
156 for (int i = 0; i < js_parameter_count; i++) {
157 if (i < register_parameter_count) {
158 // The first parameters go in registers.
159 Register reg = descriptor.GetEnvironmentParameterRegister(i);
160 locations.AddParam(regloc(reg));
161 } else {
162 // The rest of the parameters go on the stack.
163 int stack_slot = i - register_parameter_count - stack_parameter_count;
164 locations.AddParam(stackloc(stack_slot));
165 }
166 types.AddParam(kMachAnyTagged);
167 }
168 // Add context.
169 locations.AddParam(regloc(LinkageTraits::ContextReg()));
170 types.AddParam(kMachAnyTagged);
171
172 // The target for stub calls is a code object.
173 MachineType target_type = kMachAnyTagged;
174 LinkageLocation target_loc = LinkageLocation::AnyRegister();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400175 return new (zone) CallDescriptor( // --
176 CallDescriptor::kCallCodeObject, // kind
177 target_type, // target MachineType
178 target_loc, // target location
179 types.Build(), // machine_sig
180 locations.Build(), // location_sig
181 js_parameter_count, // js_parameter_count
182 properties, // properties
183 kNoCalleeSaved, // callee-saved registers
184 flags, // flags
185 descriptor.DebugName(zone->isolate()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000186 }
187
188 static CallDescriptor* GetSimplifiedCDescriptor(Zone* zone,
189 MachineSignature* msig) {
190 LocationSignature::Builder locations(zone, msig->return_count(),
191 msig->parameter_count());
192 // Add return location(s).
193 AddReturnLocations(&locations);
194
195 // Add register and/or stack parameter(s).
196 const int parameter_count = static_cast<int>(msig->parameter_count());
197 for (int i = 0; i < parameter_count; i++) {
198 if (i < LinkageTraits::CRegisterParametersLength()) {
199 locations.AddParam(regloc(LinkageTraits::CRegisterParameter(i)));
200 } else {
201 locations.AddParam(stackloc(-1 - i));
202 }
203 }
204
205 // The target for C calls is always an address (i.e. machine pointer).
206 MachineType target_type = kMachPtr;
207 LinkageLocation target_loc = LinkageLocation::AnyRegister();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400208 return new (zone) CallDescriptor( // --
209 CallDescriptor::kCallAddress, // kind
210 target_type, // target MachineType
211 target_loc, // target location
212 msig, // machine_sig
213 locations.Build(), // location_sig
214 0, // js_parameter_count
215 Operator::kNoProperties, // properties
216 LinkageTraits::CCalleeSaveRegisters(), CallDescriptor::kNoFlags,
217 "c-call");
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000218 }
219
220 static LinkageLocation regloc(Register reg) {
221 return LinkageLocation(Register::ToAllocationIndex(reg));
222 }
223
224 static LinkageLocation stackloc(int i) {
225 DCHECK_LT(i, 0);
226 return LinkageLocation(i);
227 }
228};
229} // namespace compiler
230} // namespace internal
231} // namespace v8
232
233#endif // V8_COMPILER_LINKAGE_IMPL_H_