blob: 9fe02183ec4bdc8448415e2793f75d3d9c56652b [file] [log] [blame]
// Copyright 2014 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef V8_COMPILER_LINKAGE_H_
#define V8_COMPILER_LINKAGE_H_
#include "src/v8.h"
#include "src/code-stubs.h"
#include "src/compiler/frame.h"
#include "src/compiler/machine-operator.h"
#include "src/compiler/node.h"
#include "src/compiler/operator.h"
#include "src/zone.h"
namespace v8 {
namespace internal {
namespace compiler {
// Describes the location for a parameter or a return value to a call.
// TODO(titzer): replace with Radium locations when they are ready.
class LinkageLocation {
public:
LinkageLocation(MachineType rep, int location)
: rep_(rep), location_(location) {}
inline MachineType representation() const { return rep_; }
static const int16_t ANY_REGISTER = 32767;
private:
friend class CallDescriptor;
friend class OperandGenerator;
MachineType rep_;
int16_t location_; // >= 0 implies register, otherwise stack slot.
};
class CallDescriptor : public ZoneObject {
public:
// Describes whether the first parameter is a code object, a JSFunction,
// or an address--all of which require different machine sequences to call.
enum Kind { kCallCodeObject, kCallJSFunction, kCallAddress };
enum DeoptimizationSupport { kCanDeoptimize, kCannotDeoptimize };
CallDescriptor(Kind kind, int8_t return_count, int16_t parameter_count,
int16_t input_count, LinkageLocation* locations,
Operator::Property properties, RegList callee_saved_registers,
DeoptimizationSupport deoptimization_support,
const char* debug_name = "")
: kind_(kind),
return_count_(return_count),
parameter_count_(parameter_count),
input_count_(input_count),
locations_(locations),
properties_(properties),
callee_saved_registers_(callee_saved_registers),
deoptimization_support_(deoptimization_support),
debug_name_(debug_name) {}
// Returns the kind of this call.
Kind kind() const { return kind_; }
// Returns {true} if this descriptor is a call to a JSFunction.
bool IsJSFunctionCall() const { return kind_ == kCallJSFunction; }
// The number of return values from this call, usually 0 or 1.
int ReturnCount() const { return return_count_; }
// The number of JavaScript parameters to this call, including receiver,
// but not the context.
int ParameterCount() const { return parameter_count_; }
int InputCount() const { return input_count_; }
bool CanLazilyDeoptimize() const {
return deoptimization_support_ == kCanDeoptimize;
}
LinkageLocation GetReturnLocation(int index) {
DCHECK(index < return_count_);
return locations_[0 + index]; // return locations start at 0.
}
LinkageLocation GetInputLocation(int index) {
DCHECK(index < input_count_ + 1); // input_count + 1 is the context.
return locations_[return_count_ + index]; // inputs start after returns.
}
// Operator properties describe how this call can be optimized, if at all.
Operator::Property properties() const { return properties_; }
// Get the callee-saved registers, if any, across this call.
RegList CalleeSavedRegisters() { return callee_saved_registers_; }
const char* debug_name() const { return debug_name_; }
private:
friend class Linkage;
Kind kind_;
int8_t return_count_;
int16_t parameter_count_;
int16_t input_count_;
LinkageLocation* locations_;
Operator::Property properties_;
RegList callee_saved_registers_;
DeoptimizationSupport deoptimization_support_;
const char* debug_name_;
};
OStream& operator<<(OStream& os, const CallDescriptor& d);
OStream& operator<<(OStream& os, const CallDescriptor::Kind& k);
// Defines the linkage for a compilation, including the calling conventions
// for incoming parameters and return value(s) as well as the outgoing calling
// convention for any kind of call. Linkage is generally architecture-specific.
//
// Can be used to translate {arg_index} (i.e. index of the call node input) as
// well as {param_index} (i.e. as stored in parameter nodes) into an operator
// representing the architecture-specific location. The following call node
// layouts are supported (where {n} is the number value inputs):
//
// #0 #1 #2 #3 [...] #n
// Call[CodeStub] code, arg 1, arg 2, arg 3, [...], context
// Call[JSFunction] function, rcvr, arg 1, arg 2, [...], context
// Call[Runtime] CEntryStub, arg 1, arg 2, arg 3, [...], fun, #arg, context
class Linkage : public ZoneObject {
public:
explicit Linkage(CompilationInfo* info);
explicit Linkage(CompilationInfo* info, CallDescriptor* incoming)
: info_(info), incoming_(incoming) {}
// The call descriptor for this compilation unit describes the locations
// of incoming parameters and the outgoing return value(s).
CallDescriptor* GetIncomingDescriptor() { return incoming_; }
CallDescriptor* GetJSCallDescriptor(int parameter_count);
static CallDescriptor* GetJSCallDescriptor(int parameter_count, Zone* zone);
CallDescriptor* GetRuntimeCallDescriptor(
Runtime::FunctionId function, int parameter_count,
Operator::Property properties,
CallDescriptor::DeoptimizationSupport can_deoptimize =
CallDescriptor::kCannotDeoptimize);
static CallDescriptor* GetRuntimeCallDescriptor(
Runtime::FunctionId function, int parameter_count,
Operator::Property properties,
CallDescriptor::DeoptimizationSupport can_deoptimize, Zone* zone);
CallDescriptor* GetStubCallDescriptor(
CodeStubInterfaceDescriptor* descriptor, int stack_parameter_count = 0,
CallDescriptor::DeoptimizationSupport can_deoptimize =
CallDescriptor::kCannotDeoptimize);
static CallDescriptor* GetStubCallDescriptor(
CodeStubInterfaceDescriptor* descriptor, int stack_parameter_count,
CallDescriptor::DeoptimizationSupport can_deoptimize, Zone* zone);
// Creates a call descriptor for simplified C calls that is appropriate
// for the host platform. This simplified calling convention only supports
// integers and pointers of one word size each, i.e. no floating point,
// structs, pointers to members, etc.
static CallDescriptor* GetSimplifiedCDescriptor(
Zone* zone, int num_params, MachineType return_type,
const MachineType* param_types);
// Get the location of an (incoming) parameter to this function.
LinkageLocation GetParameterLocation(int index) {
return incoming_->GetInputLocation(index + 1);
}
// Get the location where this function should place its return value.
LinkageLocation GetReturnLocation() {
return incoming_->GetReturnLocation(0);
}
// Get the frame offset for a given spill slot. The location depends on the
// calling convention and the specific frame layout, and may thus be
// architecture-specific. Negative spill slots indicate arguments on the
// caller's frame. The {extra} parameter indicates an additional offset from
// the frame offset, e.g. to index into part of a double slot.
FrameOffset GetFrameOffset(int spill_slot, Frame* frame, int extra = 0);
CompilationInfo* info() const { return info_; }
private:
CompilationInfo* info_;
CallDescriptor* incoming_;
};
}
}
} // namespace v8::internal::compiler
#endif // V8_COMPILER_LINKAGE_H_