blob: 8596327290b0643340868475e0a9580ad5ddb964 [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,
Ben Murdochc5610432016-08-08 18:44:38 +0100155 kHasExceptionHandler = 1u << 1,
156 kHasLocalCatchHandler = 1u << 2,
157 kSupportsTailCalls = 1u << 3,
158 kCanUseRoots = 1u << 4,
Ben Murdoch097c5b22016-05-18 11:27:45 +0100159 // (arm64 only) native stack should be used for arguments.
Ben Murdochc5610432016-08-08 18:44:38 +0100160 kUseNativeStack = 1u << 5,
Ben Murdochda12d292016-06-02 14:46:10 +0100161 // (arm64 only) call instruction has to restore JSSP or CSP.
Ben Murdochc5610432016-08-08 18:44:38 +0100162 kRestoreJSSP = 1u << 6,
163 kRestoreCSP = 1u << 7,
Ben Murdoch097c5b22016-05-18 11:27:45 +0100164 // Causes the code generator to initialize the root register.
Ben Murdochc5610432016-08-08 18:44:38 +0100165 kInitializeRootRegister = 1u << 8,
166 // Does not ever try to allocate space on our heap.
167 kNoAllocate = 1u << 9
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000168 };
169 typedef base::Flags<Flag> Flags;
170
171 CallDescriptor(Kind kind, MachineType target_type, LinkageLocation target_loc,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000172 const MachineSignature* machine_sig,
173 LocationSignature* location_sig, size_t stack_param_count,
174 Operator::Properties properties,
175 RegList callee_saved_registers,
176 RegList callee_saved_fp_registers, Flags flags,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000177 const char* debug_name = "")
178 : kind_(kind),
179 target_type_(target_type),
180 target_loc_(target_loc),
181 machine_sig_(machine_sig),
182 location_sig_(location_sig),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000183 stack_param_count_(stack_param_count),
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000184 properties_(properties),
185 callee_saved_registers_(callee_saved_registers),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000186 callee_saved_fp_registers_(callee_saved_fp_registers),
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000187 flags_(flags),
188 debug_name_(debug_name) {
189 DCHECK(machine_sig->return_count() == location_sig->return_count());
190 DCHECK(machine_sig->parameter_count() == location_sig->parameter_count());
191 }
192
193 // Returns the kind of this call.
194 Kind kind() const { return kind_; }
195
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000196 // Returns {true} if this descriptor is a call to a C function.
197 bool IsCFunctionCall() const { return kind_ == kCallAddress; }
198
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000199 // Returns {true} if this descriptor is a call to a JSFunction.
200 bool IsJSFunctionCall() const { return kind_ == kCallJSFunction; }
201
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000202 bool RequiresFrameAsIncoming() const {
203 return IsCFunctionCall() || IsJSFunctionCall();
204 }
205
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000206 // The number of return values from this call.
207 size_t ReturnCount() const { return machine_sig_->return_count(); }
208
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000209 // The number of C parameters to this call.
210 size_t CParameterCount() const { return machine_sig_->parameter_count(); }
211
212 // The number of stack parameters to the call.
213 size_t StackParameterCount() const { return stack_param_count_; }
214
215 // The number of parameters to the JS function call.
216 size_t JSParameterCount() const {
217 DCHECK(IsJSFunctionCall());
218 return stack_param_count_;
219 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000220
221 // The total number of inputs to this call, which includes the target,
222 // receiver, context, etc.
223 // TODO(titzer): this should input the framestate input too.
224 size_t InputCount() const { return 1 + machine_sig_->parameter_count(); }
225
226 size_t FrameStateCount() const { return NeedsFrameState() ? 1 : 0; }
227
228 Flags flags() const { return flags_; }
229
230 bool NeedsFrameState() const { return flags() & kNeedsFrameState; }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000231 bool SupportsTailCalls() const { return flags() & kSupportsTailCalls; }
232 bool UseNativeStack() const { return flags() & kUseNativeStack; }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100233 bool InitializeRootRegister() const {
234 return flags() & kInitializeRootRegister;
235 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000236
237 LinkageLocation GetReturnLocation(size_t index) const {
238 return location_sig_->GetReturn(index);
239 }
240
241 LinkageLocation GetInputLocation(size_t index) const {
242 if (index == 0) return target_loc_;
243 return location_sig_->GetParam(index - 1);
244 }
245
246 const MachineSignature* GetMachineSignature() const { return machine_sig_; }
247
248 MachineType GetReturnType(size_t index) const {
249 return machine_sig_->GetReturn(index);
250 }
251
252 MachineType GetInputType(size_t index) const {
253 if (index == 0) return target_type_;
254 return machine_sig_->GetParam(index - 1);
255 }
256
257 // Operator properties describe how this call can be optimized, if at all.
258 Operator::Properties properties() const { return properties_; }
259
260 // Get the callee-saved registers, if any, across this call.
261 RegList CalleeSavedRegisters() const { return callee_saved_registers_; }
262
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000263 // Get the callee-saved FP registers, if any, across this call.
264 RegList CalleeSavedFPRegisters() const { return callee_saved_fp_registers_; }
265
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000266 const char* debug_name() const { return debug_name_; }
267
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000268 bool UsesOnlyRegisters() const;
269
270 bool HasSameReturnLocationsAs(const CallDescriptor* other) const;
271
272 bool CanTailCall(const Node* call, int* stack_param_delta) const;
273
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000274 private:
275 friend class Linkage;
276
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400277 const Kind kind_;
278 const MachineType target_type_;
279 const LinkageLocation target_loc_;
280 const MachineSignature* const machine_sig_;
281 const LocationSignature* const location_sig_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000282 const size_t stack_param_count_;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400283 const Operator::Properties properties_;
284 const RegList callee_saved_registers_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000285 const RegList callee_saved_fp_registers_;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400286 const Flags flags_;
287 const char* const debug_name_;
288
289 DISALLOW_COPY_AND_ASSIGN(CallDescriptor);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000290};
291
292DEFINE_OPERATORS_FOR_FLAGS(CallDescriptor::Flags)
293
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400294std::ostream& operator<<(std::ostream& os, const CallDescriptor& d);
295std::ostream& operator<<(std::ostream& os, const CallDescriptor::Kind& k);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000296
297// Defines the linkage for a compilation, including the calling conventions
298// for incoming parameters and return value(s) as well as the outgoing calling
299// convention for any kind of call. Linkage is generally architecture-specific.
300//
301// Can be used to translate {arg_index} (i.e. index of the call node input) as
302// well as {param_index} (i.e. as stored in parameter nodes) into an operator
303// representing the architecture-specific location. The following call node
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000304// layouts are supported (where {n} is the number of value inputs):
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000305//
Ben Murdochc5610432016-08-08 18:44:38 +0100306// #0 #1 #2 [...] #n
307// Call[CodeStub] code, arg 1, arg 2, [...], context
308// Call[JSFunction] function, rcvr, arg 1, [...], new, #arg, context
309// Call[Runtime] CEntryStub, arg 1, arg 2, [...], fun, #arg, context
310// Call[BytecodeDispatch] address, arg 1, arg 2, [...]
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000311class 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
Ben Murdochc5610432016-08-08 18:44:38 +0100335 static CallDescriptor* GetAllocateCallDescriptor(Zone* zone);
336 static CallDescriptor* GetBytecodeDispatchCallDescriptor(
337 Isolate* isolate, Zone* zone, const CallInterfaceDescriptor& descriptor,
338 int stack_parameter_count);
339
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000340 // Creates a call descriptor for simplified C calls that is appropriate
341 // for the host platform. This simplified calling convention only supports
342 // integers and pointers of one word size each, i.e. no floating point,
343 // structs, pointers to members, etc.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100344 static CallDescriptor* GetSimplifiedCDescriptor(
345 Zone* zone, const MachineSignature* sig,
346 bool set_initialize_root_flag = false);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000347
348 // Get the location of an (incoming) parameter to this function.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400349 LinkageLocation GetParameterLocation(int index) const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000350 return incoming_->GetInputLocation(index + 1); // + 1 to skip target.
351 }
352
353 // Get the machine type of an (incoming) parameter to this function.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400354 MachineType GetParameterType(int index) const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000355 return incoming_->GetInputType(index + 1); // + 1 to skip target.
356 }
357
358 // Get the location where this function should place its return value.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000359 LinkageLocation GetReturnLocation(size_t index = 0) const {
360 return incoming_->GetReturnLocation(index);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000361 }
362
363 // Get the machine type of this function's return value.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000364 MachineType GetReturnType(size_t index = 0) const {
365 return incoming_->GetReturnType(index);
366 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000367
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000368 bool ParameterHasSecondaryLocation(int index) const;
369 LinkageLocation GetParameterSecondaryLocation(int index) const;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000370
Ben Murdoch61f157c2016-09-16 13:49:30 +0100371 static bool NeedsFrameStateInput(Runtime::FunctionId function);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000372
373 // Get the location where an incoming OSR value is stored.
374 LinkageLocation GetOsrValueLocation(int index) const;
375
Ben Murdochda12d292016-06-02 14:46:10 +0100376 // A special {Parameter} index for Stub Calls that represents context.
377 static int GetStubCallContextParamIndex(int parameter_count) {
378 return parameter_count + 0; // Parameter (arity + 0) is special.
379 }
380
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000381 // A special {Parameter} index for JSCalls that represents the new target.
382 static int GetJSCallNewTargetParamIndex(int parameter_count) {
383 return parameter_count + 0; // Parameter (arity + 0) is special.
384 }
385
386 // A special {Parameter} index for JSCalls that represents the argument count.
387 static int GetJSCallArgCountParamIndex(int parameter_count) {
388 return parameter_count + 1; // Parameter (arity + 1) is special.
389 }
390
391 // A special {Parameter} index for JSCalls that represents the context.
392 static int GetJSCallContextParamIndex(int parameter_count) {
393 return parameter_count + 2; // Parameter (arity + 2) is special.
394 }
395
396 // A special {Parameter} index for JSCalls that represents the closure.
397 static const int kJSCallClosureParamIndex = -1;
398
399 // A special {OsrValue} index to indicate the context spill slot.
400 static const int kOsrContextSpillSlotIndex = -1;
401
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000402 private:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400403 CallDescriptor* const incoming_;
404
405 DISALLOW_COPY_AND_ASSIGN(Linkage);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000406};
407
408} // namespace compiler
409} // namespace internal
410} // namespace v8
411
412#endif // V8_COMPILER_LINKAGE_H_