blob: a0434f8afff6c2651bf8ac60e7f588c07bb77c28 [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_H_
6#define V8_COMPILER_LINKAGE_H_
7
8#include "src/base/flags.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009#include "src/compiler/frame.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010#include "src/compiler/operator.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011#include "src/frames.h"
12#include "src/machine-type.h"
13#include "src/runtime/runtime.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014#include "src/zone.h"
15
16namespace v8 {
17namespace internal {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040018
19class CallInterfaceDescriptor;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020class CompilationInfo;
Emily Bernierd0a1eb72015-03-24 16:35:39 -040021
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022namespace compiler {
23
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000024const RegList kNoCalleeSaved = 0;
25
26class Node;
27class OsrHelper;
28
Ben Murdochb8a8cc12014-11-26 15:28:44 +000029// Describes the location for a parameter or a return value to a call.
30class LinkageLocation {
31 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000032 bool operator==(const LinkageLocation& other) const {
33 return bit_field_ == other.bit_field_;
34 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000035
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000036 bool operator!=(const LinkageLocation& other) const {
37 return !(*this == other);
38 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000039
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000040 static LinkageLocation ForAnyRegister() {
41 return LinkageLocation(REGISTER, ANY_REGISTER);
42 }
43
44 static LinkageLocation ForRegister(int32_t reg) {
45 DCHECK(reg >= 0);
46 return LinkageLocation(REGISTER, reg);
47 }
48
49 static LinkageLocation ForCallerFrameSlot(int32_t slot) {
50 DCHECK(slot < 0);
51 return LinkageLocation(STACK_SLOT, slot);
52 }
53
54 static LinkageLocation ForCalleeFrameSlot(int32_t slot) {
55 // TODO(titzer): bailout instead of crashing here.
56 DCHECK(slot >= 0 && slot < LinkageLocation::MAX_STACK_SLOT);
57 return LinkageLocation(STACK_SLOT, slot);
58 }
59
60 static LinkageLocation ForSavedCallerReturnAddress() {
61 return ForCalleeFrameSlot((StandardFrameConstants::kCallerPCOffset -
62 StandardFrameConstants::kCallerPCOffset) /
63 kPointerSize);
64 }
65
66 static LinkageLocation ForSavedCallerFramePtr() {
67 return ForCalleeFrameSlot((StandardFrameConstants::kCallerPCOffset -
68 StandardFrameConstants::kCallerFPOffset) /
69 kPointerSize);
70 }
71
72 static LinkageLocation ForSavedCallerConstantPool() {
73 DCHECK(V8_EMBEDDED_CONSTANT_POOL);
74 return ForCalleeFrameSlot((StandardFrameConstants::kCallerPCOffset -
75 StandardFrameConstants::kConstantPoolOffset) /
76 kPointerSize);
77 }
78
Ben Murdochda12d292016-06-02 14:46:10 +010079 static LinkageLocation ForSavedCallerFunction() {
Ben Murdoch097c5b22016-05-18 11:27:45 +010080 return ForCalleeFrameSlot((StandardFrameConstants::kCallerPCOffset -
Ben Murdochda12d292016-06-02 14:46:10 +010081 StandardFrameConstants::kFunctionOffset) /
Ben Murdoch097c5b22016-05-18 11:27:45 +010082 kPointerSize);
83 }
84
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000085 static LinkageLocation ConvertToTailCallerLocation(
86 LinkageLocation caller_location, int stack_param_delta) {
87 if (!caller_location.IsRegister()) {
88 return LinkageLocation(STACK_SLOT,
89 caller_location.GetLocation() - stack_param_delta);
90 }
91 return caller_location;
92 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000093
94 private:
95 friend class CallDescriptor;
96 friend class OperandGenerator;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000097
98 enum LocationType { REGISTER, STACK_SLOT };
99
100 class TypeField : public BitField<LocationType, 0, 1> {};
101 class LocationField : public BitField<int32_t, TypeField::kNext, 31> {};
102
103 static const int32_t ANY_REGISTER = -1;
104 static const int32_t MAX_STACK_SLOT = 32767;
105
106 LinkageLocation(LocationType type, int32_t location) {
107 bit_field_ = TypeField::encode(type) |
108 ((location << LocationField::kShift) & LocationField::kMask);
109 }
110
111 int32_t GetLocation() const {
112 return static_cast<int32_t>(bit_field_ & LocationField::kMask) >>
113 LocationField::kShift;
114 }
115
116 bool IsRegister() const { return TypeField::decode(bit_field_) == REGISTER; }
117 bool IsAnyRegister() const {
118 return IsRegister() && GetLocation() == ANY_REGISTER;
119 }
120 bool IsCallerFrameSlot() const { return !IsRegister() && GetLocation() < 0; }
121 bool IsCalleeFrameSlot() const { return !IsRegister() && GetLocation() >= 0; }
122
123 int32_t AsRegister() const {
124 DCHECK(IsRegister());
125 return GetLocation();
126 }
127 int32_t AsCallerFrameSlot() const {
128 DCHECK(IsCallerFrameSlot());
129 return GetLocation();
130 }
131 int32_t AsCalleeFrameSlot() const {
132 DCHECK(IsCalleeFrameSlot());
133 return GetLocation();
134 }
135
136 int32_t bit_field_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000137};
138
139typedef Signature<LinkageLocation> LocationSignature;
140
141// Describes a call to various parts of the compiler. Every call has the notion
142// of a "target", which is the first input to the call.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000143class CallDescriptor final : public ZoneObject {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000144 public:
145 // Describes the kind of this call, which determines the target.
146 enum Kind {
147 kCallCodeObject, // target is a Code object
148 kCallJSFunction, // target is a JSFunction object
Ben Murdoch097c5b22016-05-18 11:27:45 +0100149 kCallAddress // target is a machine pointer
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000150 };
151
152 enum Flag {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000153 kNoFlags = 0u,
154 kNeedsFrameState = 1u << 0,
155 kPatchableCallSite = 1u << 1,
156 kNeedsNopAfterCall = 1u << 2,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000157 kHasExceptionHandler = 1u << 3,
158 kHasLocalCatchHandler = 1u << 4,
159 kSupportsTailCalls = 1u << 5,
160 kCanUseRoots = 1u << 6,
Ben Murdoch097c5b22016-05-18 11:27:45 +0100161 // (arm64 only) native stack should be used for arguments.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000162 kUseNativeStack = 1u << 7,
Ben Murdochda12d292016-06-02 14:46:10 +0100163 // (arm64 only) call instruction has to restore JSSP or CSP.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100164 kRestoreJSSP = 1u << 8,
Ben Murdochda12d292016-06-02 14:46:10 +0100165 kRestoreCSP = 1u << 9,
Ben Murdoch097c5b22016-05-18 11:27:45 +0100166 // Causes the code generator to initialize the root register.
Ben Murdochda12d292016-06-02 14:46:10 +0100167 kInitializeRootRegister = 1u << 10,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000168 kPatchableCallSiteWithNop = kPatchableCallSite | kNeedsNopAfterCall
169 };
170 typedef base::Flags<Flag> Flags;
171
172 CallDescriptor(Kind kind, MachineType target_type, LinkageLocation target_loc,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000173 const MachineSignature* machine_sig,
174 LocationSignature* location_sig, size_t stack_param_count,
175 Operator::Properties properties,
176 RegList callee_saved_registers,
177 RegList callee_saved_fp_registers, Flags flags,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000178 const char* debug_name = "")
179 : kind_(kind),
180 target_type_(target_type),
181 target_loc_(target_loc),
182 machine_sig_(machine_sig),
183 location_sig_(location_sig),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000184 stack_param_count_(stack_param_count),
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000185 properties_(properties),
186 callee_saved_registers_(callee_saved_registers),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000187 callee_saved_fp_registers_(callee_saved_fp_registers),
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000188 flags_(flags),
189 debug_name_(debug_name) {
190 DCHECK(machine_sig->return_count() == location_sig->return_count());
191 DCHECK(machine_sig->parameter_count() == location_sig->parameter_count());
192 }
193
194 // Returns the kind of this call.
195 Kind kind() const { return kind_; }
196
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000197 // Returns {true} if this descriptor is a call to a C function.
198 bool IsCFunctionCall() const { return kind_ == kCallAddress; }
199
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000200 // Returns {true} if this descriptor is a call to a JSFunction.
201 bool IsJSFunctionCall() const { return kind_ == kCallJSFunction; }
202
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000203 bool RequiresFrameAsIncoming() const {
204 return IsCFunctionCall() || IsJSFunctionCall();
205 }
206
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000207 // The number of return values from this call.
208 size_t ReturnCount() const { return machine_sig_->return_count(); }
209
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000210 // The number of C parameters to this call.
211 size_t CParameterCount() const { return machine_sig_->parameter_count(); }
212
213 // The number of stack parameters to the call.
214 size_t StackParameterCount() const { return stack_param_count_; }
215
216 // The number of parameters to the JS function call.
217 size_t JSParameterCount() const {
218 DCHECK(IsJSFunctionCall());
219 return stack_param_count_;
220 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000221
222 // The total number of inputs to this call, which includes the target,
223 // receiver, context, etc.
224 // TODO(titzer): this should input the framestate input too.
225 size_t InputCount() const { return 1 + machine_sig_->parameter_count(); }
226
227 size_t FrameStateCount() const { return NeedsFrameState() ? 1 : 0; }
228
229 Flags flags() const { return flags_; }
230
231 bool NeedsFrameState() const { return flags() & kNeedsFrameState; }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000232 bool SupportsTailCalls() const { return flags() & kSupportsTailCalls; }
233 bool UseNativeStack() const { return flags() & kUseNativeStack; }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100234 bool InitializeRootRegister() const {
235 return flags() & kInitializeRootRegister;
236 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000237
238 LinkageLocation GetReturnLocation(size_t index) const {
239 return location_sig_->GetReturn(index);
240 }
241
242 LinkageLocation GetInputLocation(size_t index) const {
243 if (index == 0) return target_loc_;
244 return location_sig_->GetParam(index - 1);
245 }
246
247 const MachineSignature* GetMachineSignature() const { return machine_sig_; }
248
249 MachineType GetReturnType(size_t index) const {
250 return machine_sig_->GetReturn(index);
251 }
252
253 MachineType GetInputType(size_t index) const {
254 if (index == 0) return target_type_;
255 return machine_sig_->GetParam(index - 1);
256 }
257
258 // Operator properties describe how this call can be optimized, if at all.
259 Operator::Properties properties() const { return properties_; }
260
261 // Get the callee-saved registers, if any, across this call.
262 RegList CalleeSavedRegisters() const { return callee_saved_registers_; }
263
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000264 // Get the callee-saved FP registers, if any, across this call.
265 RegList CalleeSavedFPRegisters() const { return callee_saved_fp_registers_; }
266
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000267 const char* debug_name() const { return debug_name_; }
268
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000269 bool UsesOnlyRegisters() const;
270
271 bool HasSameReturnLocationsAs(const CallDescriptor* other) const;
272
273 bool CanTailCall(const Node* call, int* stack_param_delta) const;
274
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000275 private:
276 friend class Linkage;
277
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400278 const Kind kind_;
279 const MachineType target_type_;
280 const LinkageLocation target_loc_;
281 const MachineSignature* const machine_sig_;
282 const LocationSignature* const location_sig_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000283 const size_t stack_param_count_;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400284 const Operator::Properties properties_;
285 const RegList callee_saved_registers_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000286 const RegList callee_saved_fp_registers_;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400287 const Flags flags_;
288 const char* const debug_name_;
289
290 DISALLOW_COPY_AND_ASSIGN(CallDescriptor);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000291};
292
293DEFINE_OPERATORS_FOR_FLAGS(CallDescriptor::Flags)
294
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400295std::ostream& operator<<(std::ostream& os, const CallDescriptor& d);
296std::ostream& operator<<(std::ostream& os, const CallDescriptor::Kind& k);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000297
298// Defines the linkage for a compilation, including the calling conventions
299// for incoming parameters and return value(s) as well as the outgoing calling
300// convention for any kind of call. Linkage is generally architecture-specific.
301//
302// Can be used to translate {arg_index} (i.e. index of the call node input) as
303// well as {param_index} (i.e. as stored in parameter nodes) into an operator
304// representing the architecture-specific location. The following call node
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000305// layouts are supported (where {n} is the number of value inputs):
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000306//
307// #0 #1 #2 #3 [...] #n
308// Call[CodeStub] code, arg 1, arg 2, arg 3, [...], context
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000309// Call[JSFunction] function, rcvr, arg 1, arg 2, [...], new, #arg, context
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000310// Call[Runtime] CEntryStub, arg 1, arg 2, arg 3, [...], fun, #arg, context
311class Linkage : public ZoneObject {
312 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000313 explicit Linkage(CallDescriptor* incoming) : incoming_(incoming) {}
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400314
315 static CallDescriptor* ComputeIncoming(Zone* zone, CompilationInfo* info);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000316
317 // The call descriptor for this compilation unit describes the locations
318 // of incoming parameters and the outgoing return value(s).
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400319 CallDescriptor* GetIncomingDescriptor() const { return incoming_; }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000320 static CallDescriptor* GetJSCallDescriptor(Zone* zone, bool is_osr,
321 int parameter_count,
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400322 CallDescriptor::Flags flags);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000323
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000324 static CallDescriptor* GetRuntimeCallDescriptor(
325 Zone* zone, Runtime::FunctionId function, int parameter_count,
326 Operator::Properties properties, CallDescriptor::Flags flags);
327
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000328 static CallDescriptor* GetStubCallDescriptor(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000329 Isolate* isolate, Zone* zone, const CallInterfaceDescriptor& descriptor,
330 int stack_parameter_count, CallDescriptor::Flags flags,
331 Operator::Properties properties = Operator::kNoProperties,
332 MachineType return_type = MachineType::AnyTagged(),
333 size_t return_count = 1);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000334
335 // Creates a call descriptor for simplified C calls that is appropriate
336 // for the host platform. This simplified calling convention only supports
337 // integers and pointers of one word size each, i.e. no floating point,
338 // structs, pointers to members, etc.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100339 static CallDescriptor* GetSimplifiedCDescriptor(
340 Zone* zone, const MachineSignature* sig,
341 bool set_initialize_root_flag = false);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000342
343 // Get the location of an (incoming) parameter to this function.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400344 LinkageLocation GetParameterLocation(int index) const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000345 return incoming_->GetInputLocation(index + 1); // + 1 to skip target.
346 }
347
348 // Get the machine type of an (incoming) parameter to this function.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400349 MachineType GetParameterType(int index) const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000350 return incoming_->GetInputType(index + 1); // + 1 to skip target.
351 }
352
353 // Get the location where this function should place its return value.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000354 LinkageLocation GetReturnLocation(size_t index = 0) const {
355 return incoming_->GetReturnLocation(index);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000356 }
357
358 // Get the machine type of this function's return value.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000359 MachineType GetReturnType(size_t index = 0) const {
360 return incoming_->GetReturnType(index);
361 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000362
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000363 bool ParameterHasSecondaryLocation(int index) const;
364 LinkageLocation GetParameterSecondaryLocation(int index) const;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000365
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000366 static int FrameStateInputCount(Runtime::FunctionId function);
367
368 // Get the location where an incoming OSR value is stored.
369 LinkageLocation GetOsrValueLocation(int index) const;
370
Ben Murdochda12d292016-06-02 14:46:10 +0100371 // A special {Parameter} index for Stub Calls that represents context.
372 static int GetStubCallContextParamIndex(int parameter_count) {
373 return parameter_count + 0; // Parameter (arity + 0) is special.
374 }
375
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000376 // A special {Parameter} index for JSCalls that represents the new target.
377 static int GetJSCallNewTargetParamIndex(int parameter_count) {
378 return parameter_count + 0; // Parameter (arity + 0) is special.
379 }
380
381 // A special {Parameter} index for JSCalls that represents the argument count.
382 static int GetJSCallArgCountParamIndex(int parameter_count) {
383 return parameter_count + 1; // Parameter (arity + 1) is special.
384 }
385
386 // A special {Parameter} index for JSCalls that represents the context.
387 static int GetJSCallContextParamIndex(int parameter_count) {
388 return parameter_count + 2; // Parameter (arity + 2) is special.
389 }
390
391 // A special {Parameter} index for JSCalls that represents the closure.
392 static const int kJSCallClosureParamIndex = -1;
393
394 // A special {OsrValue} index to indicate the context spill slot.
395 static const int kOsrContextSpillSlotIndex = -1;
396
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000397 private:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400398 CallDescriptor* const incoming_;
399
400 DISALLOW_COPY_AND_ASSIGN(Linkage);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000401};
402
403} // namespace compiler
404} // namespace internal
405} // namespace v8
406
407#endif // V8_COMPILER_LINKAGE_H_