blob: e7aafc3885d8415554a170c8c53144260b49fa9d [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_IMPL_H_
#define V8_COMPILER_LINKAGE_IMPL_H_
namespace v8 {
namespace internal {
namespace compiler {
class LinkageHelper {
public:
static LinkageLocation TaggedStackSlot(int index) {
DCHECK(index < 0);
return LinkageLocation(kMachineTagged, index);
}
static LinkageLocation TaggedRegisterLocation(Register reg) {
return LinkageLocation(kMachineTagged, Register::ToAllocationIndex(reg));
}
static inline LinkageLocation WordRegisterLocation(Register reg) {
return LinkageLocation(MachineOperatorBuilder::pointer_rep(),
Register::ToAllocationIndex(reg));
}
static LinkageLocation UnconstrainedRegister(MachineType rep) {
return LinkageLocation(rep, LinkageLocation::ANY_REGISTER);
}
static const RegList kNoCalleeSaved = 0;
// TODO(turbofan): cache call descriptors for JSFunction calls.
template <typename LinkageTraits>
static CallDescriptor* GetJSCallDescriptor(Zone* zone, int parameter_count) {
const int jsfunction_count = 1;
const int context_count = 1;
int input_count = jsfunction_count + parameter_count + context_count;
const int return_count = 1;
LinkageLocation* locations =
zone->NewArray<LinkageLocation>(return_count + input_count);
int index = 0;
locations[index++] =
TaggedRegisterLocation(LinkageTraits::ReturnValueReg());
locations[index++] =
TaggedRegisterLocation(LinkageTraits::JSCallFunctionReg());
for (int i = 0; i < parameter_count; i++) {
// All parameters to JS calls go on the stack.
int spill_slot_index = i - parameter_count;
locations[index++] = TaggedStackSlot(spill_slot_index);
}
locations[index++] = TaggedRegisterLocation(LinkageTraits::ContextReg());
// TODO(titzer): refactor TurboFan graph to consider context a value input.
return new (zone)
CallDescriptor(CallDescriptor::kCallJSFunction, // kind
return_count, // return_count
parameter_count, // parameter_count
input_count - context_count, // input_count
locations, // locations
Operator::kNoProperties, // properties
kNoCalleeSaved, // callee-saved registers
CallDescriptor::kCanDeoptimize); // deoptimization
}
// TODO(turbofan): cache call descriptors for runtime calls.
template <typename LinkageTraits>
static CallDescriptor* GetRuntimeCallDescriptor(
Zone* zone, Runtime::FunctionId function_id, int parameter_count,
Operator::Property properties,
CallDescriptor::DeoptimizationSupport can_deoptimize) {
const int code_count = 1;
const int function_count = 1;
const int num_args_count = 1;
const int context_count = 1;
const int input_count = code_count + parameter_count + function_count +
num_args_count + context_count;
const Runtime::Function* function = Runtime::FunctionForId(function_id);
const int return_count = function->result_size;
LinkageLocation* locations =
zone->NewArray<LinkageLocation>(return_count + input_count);
int index = 0;
if (return_count > 0) {
locations[index++] =
TaggedRegisterLocation(LinkageTraits::ReturnValueReg());
}
if (return_count > 1) {
locations[index++] =
TaggedRegisterLocation(LinkageTraits::ReturnValue2Reg());
}
DCHECK_LE(return_count, 2);
locations[index++] = UnconstrainedRegister(kMachineTagged); // CEntryStub
for (int i = 0; i < parameter_count; i++) {
// All parameters to runtime calls go on the stack.
int spill_slot_index = i - parameter_count;
locations[index++] = TaggedStackSlot(spill_slot_index);
}
locations[index++] =
TaggedRegisterLocation(LinkageTraits::RuntimeCallFunctionReg());
locations[index++] =
WordRegisterLocation(LinkageTraits::RuntimeCallArgCountReg());
locations[index++] = TaggedRegisterLocation(LinkageTraits::ContextReg());
// TODO(titzer): refactor TurboFan graph to consider context a value input.
return new (zone) CallDescriptor(CallDescriptor::kCallCodeObject, // kind
return_count, // return_count
parameter_count, // parameter_count
input_count, // input_count
locations, // locations
properties, // properties
kNoCalleeSaved, // callee-saved registers
can_deoptimize, // deoptimization
function->name);
}
// TODO(turbofan): cache call descriptors for code stub calls.
template <typename LinkageTraits>
static CallDescriptor* GetStubCallDescriptor(
Zone* zone, CodeStubInterfaceDescriptor* descriptor,
int stack_parameter_count,
CallDescriptor::DeoptimizationSupport can_deoptimize) {
int register_parameter_count = descriptor->GetEnvironmentParameterCount();
int parameter_count = register_parameter_count + stack_parameter_count;
const int code_count = 1;
const int context_count = 1;
int input_count = code_count + parameter_count + context_count;
const int return_count = 1;
LinkageLocation* locations =
zone->NewArray<LinkageLocation>(return_count + input_count);
int index = 0;
locations[index++] =
TaggedRegisterLocation(LinkageTraits::ReturnValueReg());
locations[index++] = UnconstrainedRegister(kMachineTagged); // code
for (int i = 0; i < parameter_count; i++) {
if (i < register_parameter_count) {
// The first parameters to code stub calls go in registers.
Register reg = descriptor->GetEnvironmentParameterRegister(i);
locations[index++] = TaggedRegisterLocation(reg);
} else {
// The rest of the parameters go on the stack.
int stack_slot = i - register_parameter_count - stack_parameter_count;
locations[index++] = TaggedStackSlot(stack_slot);
}
}
locations[index++] = TaggedRegisterLocation(LinkageTraits::ContextReg());
// TODO(titzer): refactor TurboFan graph to consider context a value input.
return new (zone)
CallDescriptor(CallDescriptor::kCallCodeObject, // kind
return_count, // return_count
parameter_count, // parameter_count
input_count, // input_count
locations, // locations
Operator::kNoProperties, // properties
kNoCalleeSaved, // callee-saved registers
can_deoptimize, // deoptimization
CodeStub::MajorName(descriptor->MajorKey(), false));
}
template <typename LinkageTraits>
static CallDescriptor* GetSimplifiedCDescriptor(
Zone* zone, int num_params, MachineType return_type,
const MachineType* param_types) {
LinkageLocation* locations =
zone->NewArray<LinkageLocation>(num_params + 2);
int index = 0;
locations[index++] =
TaggedRegisterLocation(LinkageTraits::ReturnValueReg());
locations[index++] = LinkageHelper::UnconstrainedRegister(
MachineOperatorBuilder::pointer_rep());
// TODO(dcarney): test with lots of parameters.
int i = 0;
for (; i < LinkageTraits::CRegisterParametersLength() && i < num_params;
i++) {
locations[index++] = LinkageLocation(
param_types[i],
Register::ToAllocationIndex(LinkageTraits::CRegisterParameter(i)));
}
for (; i < num_params; i++) {
locations[index++] = LinkageLocation(param_types[i], -1 - i);
}
return new (zone) CallDescriptor(
CallDescriptor::kCallAddress, 1, num_params, num_params + 1, locations,
Operator::kNoProperties, LinkageTraits::CCalleeSaveRegisters(),
CallDescriptor::kCannotDeoptimize); // TODO(jarin) should deoptimize!
}
};
}
}
} // namespace v8::internal::compiler
#endif // V8_COMPILER_LINKAGE_IMPL_H_