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 #ifndef V8_COMPILER_LINKAGE_IMPL_H_
6 #define V8_COMPILER_LINKAGE_IMPL_H_
8 #include "src/code-stubs.h"
14 // TODO(titzer): replace uses of int with size_t in LinkageHelper.
15 template <typename LinkageTraits>
18 static const RegList kNoCalleeSaved = 0;
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()));
25 if (locations->return_count_ > 1) {
26 locations->AddReturn(regloc(LinkageTraits::ReturnValue2Reg()));
30 // TODO(turbofan): cache call descriptors for JSFunction calls.
31 static CallDescriptor* GetJSCallDescriptor(Zone* zone, int js_parameter_count,
32 CallDescriptor::Flags flags) {
33 const size_t return_count = 1;
34 const size_t context_count = 1;
35 const size_t parameter_count = js_parameter_count + context_count;
37 LocationSignature::Builder locations(zone, return_count, parameter_count);
38 MachineSignature::Builder types(zone, return_count, parameter_count);
41 AddReturnLocations(&locations);
42 for (size_t i = 0; i < return_count; i++) {
43 types.AddReturn(kMachAnyTagged);
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);
53 locations.AddParam(regloc(LinkageTraits::ContextReg()));
54 types.AddParam(kMachAnyTagged);
56 // The target for JS function calls is the JSFunction object.
57 MachineType target_type = kMachAnyTagged;
58 LinkageLocation target_loc = regloc(LinkageTraits::JSCallFunctionReg());
59 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
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;
84 const Runtime::Function* function = Runtime::FunctionForId(function_id);
85 const size_t return_count = static_cast<size_t>(function->result_size);
87 LocationSignature::Builder locations(zone, return_count, parameter_count);
88 MachineSignature::Builder types(zone, return_count, parameter_count);
91 AddReturnLocations(&locations);
92 for (size_t i = 0; i < return_count; i++) {
93 types.AddReturn(kMachAnyTagged);
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);
101 // Add runtime function itself.
102 locations.AddParam(regloc(LinkageTraits::RuntimeCallFunctionReg()));
103 types.AddParam(kMachAnyTagged);
105 // Add runtime call argument count.
106 locations.AddParam(regloc(LinkageTraits::RuntimeCallArgCountReg()));
107 types.AddParam(kMachPtr);
110 locations.AddParam(regloc(LinkageTraits::ContextReg()));
111 types.AddParam(kMachAnyTagged);
113 CallDescriptor::Flags flags = Linkage::NeedsFrameState(function_id)
114 ? CallDescriptor::kNeedsFrameState
115 : CallDescriptor::kNoFlags;
117 // The target for runtime calls is a code object.
118 MachineType target_type = kMachAnyTagged;
119 LinkageLocation target_loc = LinkageLocation::AnyRegister();
120 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
130 function->name); // debug name
134 // TODO(turbofan): cache call descriptors for code stub calls.
135 static CallDescriptor* GetStubCallDescriptor(
136 Zone* zone, const CallInterfaceDescriptor& descriptor,
137 int stack_parameter_count, CallDescriptor::Flags flags) {
138 const int register_parameter_count =
139 descriptor.GetEnvironmentParameterCount();
140 const int js_parameter_count =
141 register_parameter_count + stack_parameter_count;
142 const int context_count = 1;
143 const size_t return_count = 1;
144 const size_t parameter_count =
145 static_cast<size_t>(js_parameter_count + context_count);
147 LocationSignature::Builder locations(zone, return_count, parameter_count);
148 MachineSignature::Builder types(zone, return_count, parameter_count);
150 // Add return location.
151 AddReturnLocations(&locations);
152 types.AddReturn(kMachAnyTagged);
154 // Add parameters in registers and on the stack.
155 for (int i = 0; i < js_parameter_count; i++) {
156 if (i < register_parameter_count) {
157 // The first parameters go in registers.
158 Register reg = descriptor.GetEnvironmentParameterRegister(i);
159 locations.AddParam(regloc(reg));
161 // The rest of the parameters go on the stack.
162 int stack_slot = i - register_parameter_count - stack_parameter_count;
163 locations.AddParam(stackloc(stack_slot));
165 types.AddParam(kMachAnyTagged);
168 locations.AddParam(regloc(LinkageTraits::ContextReg()));
169 types.AddParam(kMachAnyTagged);
171 // The target for stub calls is a code object.
172 MachineType target_type = kMachAnyTagged;
173 LinkageLocation target_loc = LinkageLocation::AnyRegister();
174 return new (zone) CallDescriptor( // --
175 CallDescriptor::kCallCodeObject, // kind
176 target_type, // target MachineType
177 target_loc, // target location
178 types.Build(), // machine_sig
179 locations.Build(), // location_sig
180 js_parameter_count, // js_parameter_count
181 Operator::kNoProperties, // properties
182 kNoCalleeSaved, // callee-saved registers
184 descriptor.DebugName(zone->isolate()));
187 static CallDescriptor* GetSimplifiedCDescriptor(Zone* zone,
188 MachineSignature* msig) {
189 LocationSignature::Builder locations(zone, msig->return_count(),
190 msig->parameter_count());
191 // Add return location(s).
192 AddReturnLocations(&locations);
194 // Add register and/or stack parameter(s).
195 const int parameter_count = static_cast<int>(msig->parameter_count());
196 for (int i = 0; i < parameter_count; i++) {
197 if (i < LinkageTraits::CRegisterParametersLength()) {
198 locations.AddParam(regloc(LinkageTraits::CRegisterParameter(i)));
200 locations.AddParam(stackloc(-1 - i));
204 // The target for C calls is always an address (i.e. machine pointer).
205 MachineType target_type = kMachPtr;
206 LinkageLocation target_loc = LinkageLocation::AnyRegister();
207 return new (zone) CallDescriptor( // --
208 CallDescriptor::kCallAddress, // kind
209 target_type, // target MachineType
210 target_loc, // target location
212 locations.Build(), // location_sig
213 0, // js_parameter_count
214 Operator::kNoProperties, // properties
215 LinkageTraits::CCalleeSaveRegisters(), CallDescriptor::kNoFlags,
219 static LinkageLocation regloc(Register reg) {
220 return LinkageLocation(Register::ToAllocationIndex(reg));
223 static LinkageLocation stackloc(int i) {
225 return LinkageLocation(i);
228 } // namespace compiler
229 } // namespace internal
232 #endif // V8_COMPILER_LINKAGE_IMPL_H_