Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 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. |
| 4 | |
| 5 | #ifndef V8_COMPILER_LINKAGE_H_ |
| 6 | #define V8_COMPILER_LINKAGE_H_ |
| 7 | |
| 8 | #include "src/base/flags.h" |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 9 | #include "src/compiler/frame.h" |
| 10 | #include "src/compiler/machine-type.h" |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 11 | #include "src/compiler/operator.h" |
| 12 | #include "src/zone.h" |
| 13 | |
| 14 | namespace v8 { |
| 15 | namespace internal { |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame^] | 16 | |
| 17 | class CallInterfaceDescriptor; |
| 18 | |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 19 | namespace compiler { |
| 20 | |
| 21 | // Describes the location for a parameter or a return value to a call. |
| 22 | class LinkageLocation { |
| 23 | public: |
| 24 | explicit LinkageLocation(int location) : location_(location) {} |
| 25 | |
| 26 | static const int16_t ANY_REGISTER = 32767; |
| 27 | |
| 28 | static LinkageLocation AnyRegister() { return LinkageLocation(ANY_REGISTER); } |
| 29 | |
| 30 | private: |
| 31 | friend class CallDescriptor; |
| 32 | friend class OperandGenerator; |
| 33 | int16_t location_; // >= 0 implies register, otherwise stack slot. |
| 34 | }; |
| 35 | |
| 36 | typedef Signature<LinkageLocation> LocationSignature; |
| 37 | |
| 38 | // Describes a call to various parts of the compiler. Every call has the notion |
| 39 | // of a "target", which is the first input to the call. |
| 40 | class CallDescriptor FINAL : public ZoneObject { |
| 41 | public: |
| 42 | // Describes the kind of this call, which determines the target. |
| 43 | enum Kind { |
| 44 | kCallCodeObject, // target is a Code object |
| 45 | kCallJSFunction, // target is a JSFunction object |
| 46 | kCallAddress // target is a machine pointer |
| 47 | }; |
| 48 | |
| 49 | enum Flag { |
| 50 | // TODO(jarin) kLazyDeoptimization and kNeedsFrameState should be unified. |
| 51 | kNoFlags = 0u, |
| 52 | kNeedsFrameState = 1u << 0, |
| 53 | kPatchableCallSite = 1u << 1, |
| 54 | kNeedsNopAfterCall = 1u << 2, |
| 55 | kPatchableCallSiteWithNop = kPatchableCallSite | kNeedsNopAfterCall |
| 56 | }; |
| 57 | typedef base::Flags<Flag> Flags; |
| 58 | |
| 59 | CallDescriptor(Kind kind, MachineType target_type, LinkageLocation target_loc, |
| 60 | MachineSignature* machine_sig, LocationSignature* location_sig, |
| 61 | size_t js_param_count, Operator::Properties properties, |
| 62 | RegList callee_saved_registers, Flags flags, |
| 63 | const char* debug_name = "") |
| 64 | : kind_(kind), |
| 65 | target_type_(target_type), |
| 66 | target_loc_(target_loc), |
| 67 | machine_sig_(machine_sig), |
| 68 | location_sig_(location_sig), |
| 69 | js_param_count_(js_param_count), |
| 70 | properties_(properties), |
| 71 | callee_saved_registers_(callee_saved_registers), |
| 72 | flags_(flags), |
| 73 | debug_name_(debug_name) { |
| 74 | DCHECK(machine_sig->return_count() == location_sig->return_count()); |
| 75 | DCHECK(machine_sig->parameter_count() == location_sig->parameter_count()); |
| 76 | } |
| 77 | |
| 78 | // Returns the kind of this call. |
| 79 | Kind kind() const { return kind_; } |
| 80 | |
| 81 | // Returns {true} if this descriptor is a call to a JSFunction. |
| 82 | bool IsJSFunctionCall() const { return kind_ == kCallJSFunction; } |
| 83 | |
| 84 | // The number of return values from this call. |
| 85 | size_t ReturnCount() const { return machine_sig_->return_count(); } |
| 86 | |
| 87 | // The number of JavaScript parameters to this call, including the receiver |
| 88 | // object. |
| 89 | size_t JSParameterCount() const { return js_param_count_; } |
| 90 | |
| 91 | // The total number of inputs to this call, which includes the target, |
| 92 | // receiver, context, etc. |
| 93 | // TODO(titzer): this should input the framestate input too. |
| 94 | size_t InputCount() const { return 1 + machine_sig_->parameter_count(); } |
| 95 | |
| 96 | size_t FrameStateCount() const { return NeedsFrameState() ? 1 : 0; } |
| 97 | |
| 98 | Flags flags() const { return flags_; } |
| 99 | |
| 100 | bool NeedsFrameState() const { return flags() & kNeedsFrameState; } |
| 101 | |
| 102 | LinkageLocation GetReturnLocation(size_t index) const { |
| 103 | return location_sig_->GetReturn(index); |
| 104 | } |
| 105 | |
| 106 | LinkageLocation GetInputLocation(size_t index) const { |
| 107 | if (index == 0) return target_loc_; |
| 108 | return location_sig_->GetParam(index - 1); |
| 109 | } |
| 110 | |
| 111 | const MachineSignature* GetMachineSignature() const { return machine_sig_; } |
| 112 | |
| 113 | MachineType GetReturnType(size_t index) const { |
| 114 | return machine_sig_->GetReturn(index); |
| 115 | } |
| 116 | |
| 117 | MachineType GetInputType(size_t index) const { |
| 118 | if (index == 0) return target_type_; |
| 119 | return machine_sig_->GetParam(index - 1); |
| 120 | } |
| 121 | |
| 122 | // Operator properties describe how this call can be optimized, if at all. |
| 123 | Operator::Properties properties() const { return properties_; } |
| 124 | |
| 125 | // Get the callee-saved registers, if any, across this call. |
| 126 | RegList CalleeSavedRegisters() const { return callee_saved_registers_; } |
| 127 | |
| 128 | const char* debug_name() const { return debug_name_; } |
| 129 | |
| 130 | private: |
| 131 | friend class Linkage; |
| 132 | |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame^] | 133 | const Kind kind_; |
| 134 | const MachineType target_type_; |
| 135 | const LinkageLocation target_loc_; |
| 136 | const MachineSignature* const machine_sig_; |
| 137 | const LocationSignature* const location_sig_; |
| 138 | const size_t js_param_count_; |
| 139 | const Operator::Properties properties_; |
| 140 | const RegList callee_saved_registers_; |
| 141 | const Flags flags_; |
| 142 | const char* const debug_name_; |
| 143 | |
| 144 | DISALLOW_COPY_AND_ASSIGN(CallDescriptor); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 145 | }; |
| 146 | |
| 147 | DEFINE_OPERATORS_FOR_FLAGS(CallDescriptor::Flags) |
| 148 | |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame^] | 149 | std::ostream& operator<<(std::ostream& os, const CallDescriptor& d); |
| 150 | std::ostream& operator<<(std::ostream& os, const CallDescriptor::Kind& k); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 151 | |
| 152 | // Defines the linkage for a compilation, including the calling conventions |
| 153 | // for incoming parameters and return value(s) as well as the outgoing calling |
| 154 | // convention for any kind of call. Linkage is generally architecture-specific. |
| 155 | // |
| 156 | // Can be used to translate {arg_index} (i.e. index of the call node input) as |
| 157 | // well as {param_index} (i.e. as stored in parameter nodes) into an operator |
| 158 | // representing the architecture-specific location. The following call node |
| 159 | // layouts are supported (where {n} is the number value inputs): |
| 160 | // |
| 161 | // #0 #1 #2 #3 [...] #n |
| 162 | // Call[CodeStub] code, arg 1, arg 2, arg 3, [...], context |
| 163 | // Call[JSFunction] function, rcvr, arg 1, arg 2, [...], context |
| 164 | // Call[Runtime] CEntryStub, arg 1, arg 2, arg 3, [...], fun, #arg, context |
| 165 | class Linkage : public ZoneObject { |
| 166 | public: |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame^] | 167 | Linkage(Zone* zone, CompilationInfo* info) |
| 168 | : zone_(zone), incoming_(ComputeIncoming(zone, info)) {} |
| 169 | Linkage(Zone* zone, CallDescriptor* incoming) |
| 170 | : zone_(zone), incoming_(incoming) {} |
| 171 | |
| 172 | static CallDescriptor* ComputeIncoming(Zone* zone, CompilationInfo* info); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 173 | |
| 174 | // The call descriptor for this compilation unit describes the locations |
| 175 | // of incoming parameters and the outgoing return value(s). |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame^] | 176 | CallDescriptor* GetIncomingDescriptor() const { return incoming_; } |
| 177 | CallDescriptor* GetJSCallDescriptor(int parameter_count, |
| 178 | CallDescriptor::Flags flags) const; |
| 179 | static CallDescriptor* GetJSCallDescriptor(int parameter_count, Zone* zone, |
| 180 | CallDescriptor::Flags flags); |
| 181 | CallDescriptor* GetRuntimeCallDescriptor( |
| 182 | Runtime::FunctionId function, int parameter_count, |
| 183 | Operator::Properties properties) const; |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 184 | static CallDescriptor* GetRuntimeCallDescriptor( |
| 185 | Runtime::FunctionId function, int parameter_count, |
| 186 | Operator::Properties properties, Zone* zone); |
| 187 | |
| 188 | CallDescriptor* GetStubCallDescriptor( |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame^] | 189 | const CallInterfaceDescriptor& descriptor, int stack_parameter_count = 0, |
| 190 | CallDescriptor::Flags flags = CallDescriptor::kNoFlags, |
| 191 | Operator::Properties properties = Operator::kNoProperties) const; |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 192 | static CallDescriptor* GetStubCallDescriptor( |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame^] | 193 | const CallInterfaceDescriptor& descriptor, int stack_parameter_count, |
| 194 | CallDescriptor::Flags flags, Operator::Properties properties, Zone* zone); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 195 | |
| 196 | // Creates a call descriptor for simplified C calls that is appropriate |
| 197 | // for the host platform. This simplified calling convention only supports |
| 198 | // integers and pointers of one word size each, i.e. no floating point, |
| 199 | // structs, pointers to members, etc. |
| 200 | static CallDescriptor* GetSimplifiedCDescriptor(Zone* zone, |
| 201 | MachineSignature* sig); |
| 202 | |
| 203 | // Get the location of an (incoming) parameter to this function. |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame^] | 204 | LinkageLocation GetParameterLocation(int index) const { |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 205 | return incoming_->GetInputLocation(index + 1); // + 1 to skip target. |
| 206 | } |
| 207 | |
| 208 | // Get the machine type of an (incoming) parameter to this function. |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame^] | 209 | MachineType GetParameterType(int index) const { |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 210 | return incoming_->GetInputType(index + 1); // + 1 to skip target. |
| 211 | } |
| 212 | |
| 213 | // Get the location where this function should place its return value. |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame^] | 214 | LinkageLocation GetReturnLocation() const { |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 215 | return incoming_->GetReturnLocation(0); |
| 216 | } |
| 217 | |
| 218 | // Get the machine type of this function's return value. |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame^] | 219 | MachineType GetReturnType() const { return incoming_->GetReturnType(0); } |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 220 | |
| 221 | // Get the frame offset for a given spill slot. The location depends on the |
| 222 | // calling convention and the specific frame layout, and may thus be |
| 223 | // architecture-specific. Negative spill slots indicate arguments on the |
| 224 | // caller's frame. The {extra} parameter indicates an additional offset from |
| 225 | // the frame offset, e.g. to index into part of a double slot. |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame^] | 226 | FrameOffset GetFrameOffset(int spill_slot, Frame* frame, int extra = 0) const; |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 227 | |
| 228 | static bool NeedsFrameState(Runtime::FunctionId function); |
| 229 | |
| 230 | private: |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame^] | 231 | Zone* const zone_; |
| 232 | CallDescriptor* const incoming_; |
| 233 | |
| 234 | DISALLOW_COPY_AND_ASSIGN(Linkage); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 235 | }; |
| 236 | |
| 237 | } // namespace compiler |
| 238 | } // namespace internal |
| 239 | } // namespace v8 |
| 240 | |
| 241 | #endif // V8_COMPILER_LINKAGE_H_ |