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_H_
6 #define V8_COMPILER_LINKAGE_H_
8 #include "src/base/flags.h"
9 #include "src/compiler/frame.h"
10 #include "src/compiler/machine-type.h"
11 #include "src/compiler/operator.h"
12 #include "src/frames.h"
13 #include "src/runtime/runtime.h"
19 class CallInterfaceDescriptor;
25 // Describes the location for a parameter or a return value to a call.
26 class LinkageLocation {
28 explicit LinkageLocation(int location) : location_(location) {}
30 static const int16_t ANY_REGISTER = 1023;
31 static const int16_t MAX_STACK_SLOT = 32767;
33 static LinkageLocation AnyRegister() { return LinkageLocation(ANY_REGISTER); }
36 friend class CallDescriptor;
37 friend class OperandGenerator;
38 // location < 0 -> a stack slot on the caller frame
39 // 0 <= location < 1023 -> a specific machine register
40 // 1023 <= location < 1024 -> any machine register
41 // 1024 <= location -> a stack slot in the callee frame
45 typedef Signature<LinkageLocation> LocationSignature;
47 // Describes a call to various parts of the compiler. Every call has the notion
48 // of a "target", which is the first input to the call.
49 class CallDescriptor FINAL : public ZoneObject {
51 // Describes the kind of this call, which determines the target.
53 kCallCodeObject, // target is a Code object
54 kCallJSFunction, // target is a JSFunction object
55 kCallAddress // target is a machine pointer
60 kNeedsFrameState = 1u << 0,
61 kPatchableCallSite = 1u << 1,
62 kNeedsNopAfterCall = 1u << 2,
63 kHasExceptionHandler = 1u << 3,
64 kPatchableCallSiteWithNop = kPatchableCallSite | kNeedsNopAfterCall
66 typedef base::Flags<Flag> Flags;
68 CallDescriptor(Kind kind, MachineType target_type, LinkageLocation target_loc,
69 const MachineSignature* machine_sig,
70 LocationSignature* location_sig, size_t js_param_count,
71 Operator::Properties properties,
72 RegList callee_saved_registers, Flags flags,
73 const char* debug_name = "")
75 target_type_(target_type),
76 target_loc_(target_loc),
77 machine_sig_(machine_sig),
78 location_sig_(location_sig),
79 js_param_count_(js_param_count),
80 properties_(properties),
81 callee_saved_registers_(callee_saved_registers),
83 debug_name_(debug_name) {
84 DCHECK(machine_sig->return_count() == location_sig->return_count());
85 DCHECK(machine_sig->parameter_count() == location_sig->parameter_count());
88 // Returns the kind of this call.
89 Kind kind() const { return kind_; }
91 // Returns {true} if this descriptor is a call to a JSFunction.
92 bool IsJSFunctionCall() const { return kind_ == kCallJSFunction; }
94 // The number of return values from this call.
95 size_t ReturnCount() const { return machine_sig_->return_count(); }
97 // The number of JavaScript parameters to this call, including the receiver
99 size_t JSParameterCount() const { return js_param_count_; }
101 // The total number of inputs to this call, which includes the target,
102 // receiver, context, etc.
103 // TODO(titzer): this should input the framestate input too.
104 size_t InputCount() const { return 1 + machine_sig_->parameter_count(); }
106 size_t FrameStateCount() const { return NeedsFrameState() ? 1 : 0; }
108 Flags flags() const { return flags_; }
110 bool NeedsFrameState() const { return flags() & kNeedsFrameState; }
112 LinkageLocation GetReturnLocation(size_t index) const {
113 return location_sig_->GetReturn(index);
116 LinkageLocation GetInputLocation(size_t index) const {
117 if (index == 0) return target_loc_;
118 return location_sig_->GetParam(index - 1);
121 const MachineSignature* GetMachineSignature() const { return machine_sig_; }
123 MachineType GetReturnType(size_t index) const {
124 return machine_sig_->GetReturn(index);
127 MachineType GetInputType(size_t index) const {
128 if (index == 0) return target_type_;
129 return machine_sig_->GetParam(index - 1);
132 // Operator properties describe how this call can be optimized, if at all.
133 Operator::Properties properties() const { return properties_; }
135 // Get the callee-saved registers, if any, across this call.
136 RegList CalleeSavedRegisters() const { return callee_saved_registers_; }
138 const char* debug_name() const { return debug_name_; }
141 friend class Linkage;
144 const MachineType target_type_;
145 const LinkageLocation target_loc_;
146 const MachineSignature* const machine_sig_;
147 const LocationSignature* const location_sig_;
148 const size_t js_param_count_;
149 const Operator::Properties properties_;
150 const RegList callee_saved_registers_;
152 const char* const debug_name_;
154 DISALLOW_COPY_AND_ASSIGN(CallDescriptor);
157 DEFINE_OPERATORS_FOR_FLAGS(CallDescriptor::Flags)
159 std::ostream& operator<<(std::ostream& os, const CallDescriptor& d);
160 std::ostream& operator<<(std::ostream& os, const CallDescriptor::Kind& k);
162 // Defines the linkage for a compilation, including the calling conventions
163 // for incoming parameters and return value(s) as well as the outgoing calling
164 // convention for any kind of call. Linkage is generally architecture-specific.
166 // Can be used to translate {arg_index} (i.e. index of the call node input) as
167 // well as {param_index} (i.e. as stored in parameter nodes) into an operator
168 // representing the architecture-specific location. The following call node
169 // layouts are supported (where {n} is the number value inputs):
171 // #0 #1 #2 #3 [...] #n
172 // Call[CodeStub] code, arg 1, arg 2, arg 3, [...], context
173 // Call[JSFunction] function, rcvr, arg 1, arg 2, [...], context
174 // Call[Runtime] CEntryStub, arg 1, arg 2, arg 3, [...], fun, #arg, context
175 class Linkage : public ZoneObject {
177 explicit Linkage(CallDescriptor* incoming) : incoming_(incoming) {}
179 static CallDescriptor* ComputeIncoming(Zone* zone, CompilationInfo* info);
181 // The call descriptor for this compilation unit describes the locations
182 // of incoming parameters and the outgoing return value(s).
183 CallDescriptor* GetIncomingDescriptor() const { return incoming_; }
184 static CallDescriptor* GetJSCallDescriptor(Zone* zone, bool is_osr,
186 CallDescriptor::Flags flags);
187 static CallDescriptor* GetRuntimeCallDescriptor(
188 Zone* zone, Runtime::FunctionId function, int parameter_count,
189 Operator::Properties properties);
191 static CallDescriptor* GetStubCallDescriptor(
192 Isolate* isolate, Zone* zone, const CallInterfaceDescriptor& descriptor,
193 int stack_parameter_count, CallDescriptor::Flags flags,
194 Operator::Properties properties = Operator::kNoProperties,
195 MachineType return_type = kMachAnyTagged);
197 // Creates a call descriptor for simplified C calls that is appropriate
198 // for the host platform. This simplified calling convention only supports
199 // integers and pointers of one word size each, i.e. no floating point,
200 // structs, pointers to members, etc.
201 static CallDescriptor* GetSimplifiedCDescriptor(Zone* zone,
202 const MachineSignature* sig);
204 // Get the location of an (incoming) parameter to this function.
205 LinkageLocation GetParameterLocation(int index) const {
206 return incoming_->GetInputLocation(index + 1); // + 1 to skip target.
209 // Get the machine type of an (incoming) parameter to this function.
210 MachineType GetParameterType(int index) const {
211 return incoming_->GetInputType(index + 1); // + 1 to skip target.
214 // Get the location where this function should place its return value.
215 LinkageLocation GetReturnLocation() const {
216 return incoming_->GetReturnLocation(0);
219 // Get the machine type of this function's return value.
220 MachineType GetReturnType() const { return incoming_->GetReturnType(0); }
222 // Get the frame offset for a given spill slot. The location depends on the
223 // calling convention and the specific frame layout, and may thus be
224 // architecture-specific. Negative spill slots indicate arguments on the
225 // caller's frame. The {extra} parameter indicates an additional offset from
226 // the frame offset, e.g. to index into part of a double slot.
227 FrameOffset GetFrameOffset(int spill_slot, Frame* frame, int extra = 0) const;
229 static bool NeedsFrameState(Runtime::FunctionId function);
231 // Get the location where an incoming OSR value is stored.
232 LinkageLocation GetOsrValueLocation(int index) const;
234 // A special parameter index for JSCalls that represents the closure.
235 static const int kJSFunctionCallClosureParamIndex = -1;
238 CallDescriptor* const incoming_;
240 DISALLOW_COPY_AND_ASSIGN(Linkage);
243 } // namespace compiler
244 } // namespace internal
247 #endif // V8_COMPILER_LINKAGE_H_