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