// Copyright 2012 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.

#include "src/interface-descriptors.h"

namespace v8 {
namespace internal {

namespace {
// Constructors for common combined semantic and representation types.
Type* SmiType(Zone* zone) {
  return Type::Intersect(Type::SignedSmall(), Type::TaggedSigned(), zone);
}


Type* UntaggedIntegral32(Zone* zone) {
  return Type::Intersect(Type::Signed32(), Type::UntaggedIntegral32(), zone);
}


Type* AnyTagged(Zone* zone) {
  return Type::Intersect(
      Type::Any(),
      Type::Union(Type::TaggedPointer(), Type::TaggedSigned(), zone), zone);
}


Type* ExternalPointer(Zone* zone) {
  return Type::Intersect(Type::Internal(), Type::UntaggedPointer(), zone);
}
}  // namespace

FunctionType* CallInterfaceDescriptor::BuildDefaultFunctionType(
    Isolate* isolate, int parameter_count) {
  Zone* zone = isolate->interface_descriptor_zone();
  FunctionType* function =
      Type::Function(AnyTagged(zone), Type::Undefined(), parameter_count, zone)
          ->AsFunction();
  while (parameter_count-- != 0) {
    function->InitParameter(parameter_count, AnyTagged(zone));
  }
  return function;
}

void CallInterfaceDescriptorData::InitializePlatformSpecific(
    int register_parameter_count, const Register* registers,
    PlatformInterfaceDescriptor* platform_descriptor) {
  platform_specific_descriptor_ = platform_descriptor;
  register_param_count_ = register_parameter_count;

  // InterfaceDescriptor owns a copy of the registers array.
  register_params_.Reset(NewArray<Register>(register_parameter_count));
  for (int i = 0; i < register_parameter_count; i++) {
    register_params_[i] = registers[i];
  }
}

const char* CallInterfaceDescriptor::DebugName(Isolate* isolate) const {
  CallInterfaceDescriptorData* start = isolate->call_descriptor_data(0);
  size_t index = data_ - start;
  DCHECK(index < CallDescriptors::NUMBER_OF_DESCRIPTORS);
  CallDescriptors::Key key = static_cast<CallDescriptors::Key>(index);
  switch (key) {
#define DEF_CASE(NAME)        \
  case CallDescriptors::NAME: \
    return #NAME " Descriptor";
    INTERFACE_DESCRIPTOR_LIST(DEF_CASE)
#undef DEF_CASE
    case CallDescriptors::NUMBER_OF_DESCRIPTORS:
      break;
  }
  return "";
}


void VoidDescriptor::InitializePlatformSpecific(
    CallInterfaceDescriptorData* data) {
  data->InitializePlatformSpecific(0, nullptr);
}

FunctionType* LoadDescriptor::BuildCallInterfaceDescriptorFunctionType(
    Isolate* isolate, int paramater_count) {
  Zone* zone = isolate->interface_descriptor_zone();
  FunctionType* function =
      Type::Function(AnyTagged(zone), Type::Undefined(), 3, zone)->AsFunction();
  function->InitParameter(0, AnyTagged(zone));
  function->InitParameter(1, AnyTagged(zone));
  function->InitParameter(2, SmiType(zone));
  return function;
}


void LoadDescriptor::InitializePlatformSpecific(
    CallInterfaceDescriptorData* data) {
  Register registers[] = {ReceiverRegister(), NameRegister(), SlotRegister()};
  data->InitializePlatformSpecific(arraysize(registers), registers);
}

FunctionType* LoadGlobalDescriptor::BuildCallInterfaceDescriptorFunctionType(
    Isolate* isolate, int paramater_count) {
  Zone* zone = isolate->interface_descriptor_zone();
  FunctionType* function =
      Type::Function(AnyTagged(zone), Type::Undefined(), 1, zone)->AsFunction();
  function->InitParameter(0, SmiType(zone));
  return function;
}

void LoadGlobalDescriptor::InitializePlatformSpecific(
    CallInterfaceDescriptorData* data) {
  Register registers[] = {LoadWithVectorDescriptor::SlotRegister()};
  data->InitializePlatformSpecific(arraysize(registers), registers);
}

FunctionType*
LoadGlobalWithVectorDescriptor::BuildCallInterfaceDescriptorFunctionType(
    Isolate* isolate, int paramater_count) {
  Zone* zone = isolate->interface_descriptor_zone();
  FunctionType* function =
      Type::Function(AnyTagged(zone), Type::Undefined(), 2, zone)->AsFunction();
  function->InitParameter(0, SmiType(zone));
  function->InitParameter(1, AnyTagged(zone));
  return function;
}

void LoadGlobalWithVectorDescriptor::InitializePlatformSpecific(
    CallInterfaceDescriptorData* data) {
  Register registers[] = {LoadWithVectorDescriptor::SlotRegister(),
                          LoadWithVectorDescriptor::VectorRegister()};
  data->InitializePlatformSpecific(arraysize(registers), registers);
}

void StoreDescriptor::InitializePlatformSpecific(
    CallInterfaceDescriptorData* data) {
  Register registers[] = {ReceiverRegister(), NameRegister(), ValueRegister()};
  data->InitializePlatformSpecific(arraysize(registers), registers);
}


void StoreTransitionDescriptor::InitializePlatformSpecific(
    CallInterfaceDescriptorData* data) {
  Register registers[] = {ReceiverRegister(), NameRegister(), ValueRegister(),
                          MapRegister()};

  data->InitializePlatformSpecific(arraysize(registers), registers);
}


void VectorStoreTransitionDescriptor::InitializePlatformSpecific(
    CallInterfaceDescriptorData* data) {
  if (SlotRegister().is(no_reg)) {
    Register registers[] = {ReceiverRegister(), NameRegister(), ValueRegister(),
                            MapRegister(), VectorRegister()};
    data->InitializePlatformSpecific(arraysize(registers), registers);
  } else {
    Register registers[] = {ReceiverRegister(), NameRegister(),
                            ValueRegister(),    MapRegister(),
                            SlotRegister(),     VectorRegister()};
    data->InitializePlatformSpecific(arraysize(registers), registers);
  }
}

FunctionType*
StoreTransitionDescriptor::BuildCallInterfaceDescriptorFunctionType(
    Isolate* isolate, int paramater_count) {
  Zone* zone = isolate->interface_descriptor_zone();
  FunctionType* function =
      Type::Function(AnyTagged(zone), Type::Undefined(), 4, zone)->AsFunction();
  function->InitParameter(0, AnyTagged(zone));  // Receiver
  function->InitParameter(1, AnyTagged(zone));  // Name
  function->InitParameter(2, AnyTagged(zone));  // Value
  function->InitParameter(3, AnyTagged(zone));  // Map
  return function;
}

FunctionType*
StoreGlobalViaContextDescriptor::BuildCallInterfaceDescriptorFunctionType(
    Isolate* isolate, int paramater_count) {
  Zone* zone = isolate->interface_descriptor_zone();
  FunctionType* function =
      Type::Function(AnyTagged(zone), Type::Undefined(), 2, zone)->AsFunction();
  function->InitParameter(0, UntaggedIntegral32(zone));
  function->InitParameter(1, AnyTagged(zone));
  return function;
}


void StoreGlobalViaContextDescriptor::InitializePlatformSpecific(
    CallInterfaceDescriptorData* data) {
  Register registers[] = {SlotRegister(), ValueRegister()};
  data->InitializePlatformSpecific(arraysize(registers), registers);
}


void StringCompareDescriptor::InitializePlatformSpecific(
    CallInterfaceDescriptorData* data) {
  Register registers[] = {LeftRegister(), RightRegister()};
  data->InitializePlatformSpecific(arraysize(registers), registers);
}

void TypeConversionDescriptor::InitializePlatformSpecific(
    CallInterfaceDescriptorData* data) {
  Register registers[] = {ArgumentRegister()};
  data->InitializePlatformSpecific(arraysize(registers), registers);
}

void MathPowTaggedDescriptor::InitializePlatformSpecific(
    CallInterfaceDescriptorData* data) {
  Register registers[] = {exponent()};
  data->InitializePlatformSpecific(arraysize(registers), registers);
}

void MathPowIntegerDescriptor::InitializePlatformSpecific(
    CallInterfaceDescriptorData* data) {
  Register registers[] = {exponent()};
  data->InitializePlatformSpecific(arraysize(registers), registers);
}

FunctionType*
LoadWithVectorDescriptor::BuildCallInterfaceDescriptorFunctionType(
    Isolate* isolate, int paramater_count) {
  Zone* zone = isolate->interface_descriptor_zone();
  FunctionType* function =
      Type::Function(AnyTagged(zone), Type::Undefined(), 4, zone)->AsFunction();
  function->InitParameter(0, AnyTagged(zone));
  function->InitParameter(1, AnyTagged(zone));
  function->InitParameter(2, SmiType(zone));
  function->InitParameter(3, AnyTagged(zone));
  return function;
}


void LoadWithVectorDescriptor::InitializePlatformSpecific(
    CallInterfaceDescriptorData* data) {
  Register registers[] = {ReceiverRegister(), NameRegister(), SlotRegister(),
                          VectorRegister()};
  data->InitializePlatformSpecific(arraysize(registers), registers);
}

FunctionType*
VectorStoreTransitionDescriptor::BuildCallInterfaceDescriptorFunctionType(
    Isolate* isolate, int paramater_count) {
  Zone* zone = isolate->interface_descriptor_zone();
  bool has_slot = !VectorStoreTransitionDescriptor::SlotRegister().is(no_reg);
  int arg_count = has_slot ? 6 : 5;
  FunctionType* function =
      Type::Function(AnyTagged(zone), Type::Undefined(), arg_count, zone)
          ->AsFunction();
  int index = 0;
  function->InitParameter(index++, AnyTagged(zone));  // receiver
  function->InitParameter(index++, AnyTagged(zone));  // name
  function->InitParameter(index++, AnyTagged(zone));  // value
  function->InitParameter(index++, AnyTagged(zone));  // map
  if (has_slot) {
    function->InitParameter(index++, SmiType(zone));  // slot
  }
  function->InitParameter(index++, AnyTagged(zone));  // vector
  return function;
}

FunctionType* VectorStoreICDescriptor::BuildCallInterfaceDescriptorFunctionType(
    Isolate* isolate, int paramater_count) {
  Zone* zone = isolate->interface_descriptor_zone();
  FunctionType* function =
      Type::Function(AnyTagged(zone), Type::Undefined(), 5, zone)->AsFunction();
  function->InitParameter(0, AnyTagged(zone));
  function->InitParameter(1, AnyTagged(zone));
  function->InitParameter(2, AnyTagged(zone));
  function->InitParameter(3, SmiType(zone));
  function->InitParameter(4, AnyTagged(zone));
  return function;
}


void VectorStoreICDescriptor::InitializePlatformSpecific(
    CallInterfaceDescriptorData* data) {
  Register registers[] = {ReceiverRegister(), NameRegister(), ValueRegister(),
                          SlotRegister(), VectorRegister()};
  data->InitializePlatformSpecific(arraysize(registers), registers);
}

FunctionType*
VectorStoreICTrampolineDescriptor::BuildCallInterfaceDescriptorFunctionType(
    Isolate* isolate, int paramater_count) {
  Zone* zone = isolate->interface_descriptor_zone();
  FunctionType* function =
      Type::Function(AnyTagged(zone), Type::Undefined(), 4, zone)->AsFunction();
  function->InitParameter(0, AnyTagged(zone));
  function->InitParameter(1, AnyTagged(zone));
  function->InitParameter(2, AnyTagged(zone));
  function->InitParameter(3, SmiType(zone));
  return function;
}


void VectorStoreICTrampolineDescriptor::InitializePlatformSpecific(
    CallInterfaceDescriptorData* data) {
  Register registers[] = {ReceiverRegister(), NameRegister(), ValueRegister(),
                          SlotRegister()};
  data->InitializePlatformSpecific(arraysize(registers), registers);
}

const Register ApiGetterDescriptor::ReceiverRegister() {
  return LoadDescriptor::ReceiverRegister();
}

void ApiGetterDescriptor::InitializePlatformSpecific(
    CallInterfaceDescriptorData* data) {
  Register registers[] = {ReceiverRegister(), HolderRegister(),
                          CallbackRegister()};
  data->InitializePlatformSpecific(arraysize(registers), registers);
}

void ContextOnlyDescriptor::InitializePlatformSpecific(
    CallInterfaceDescriptorData* data) {
  data->InitializePlatformSpecific(0, nullptr);
}

CallInterfaceDescriptor OnStackArgsDescriptorBase::ForArgs(
    Isolate* isolate, int parameter_count) {
  switch (parameter_count) {
    case 1:
      return OnStackWith1ArgsDescriptor(isolate);
    case 2:
      return OnStackWith2ArgsDescriptor(isolate);
    case 3:
      return OnStackWith3ArgsDescriptor(isolate);
    case 4:
      return OnStackWith4ArgsDescriptor(isolate);
    case 5:
      return OnStackWith5ArgsDescriptor(isolate);
    case 6:
      return OnStackWith6ArgsDescriptor(isolate);
    case 7:
      return OnStackWith7ArgsDescriptor(isolate);
    default:
      UNREACHABLE();
      return VoidDescriptor(isolate);
  }
}

FunctionType*
OnStackArgsDescriptorBase::BuildCallInterfaceDescriptorFunctionTypeWithArg(
    Isolate* isolate, int register_parameter_count, int parameter_count) {
  DCHECK_EQ(0, register_parameter_count);
  DCHECK_GT(parameter_count, 0);
  Zone* zone = isolate->interface_descriptor_zone();
  FunctionType* function =
      Type::Function(AnyTagged(zone), AnyTagged(zone), parameter_count, zone)
          ->AsFunction();
  for (int i = 0; i < parameter_count; i++) {
    function->InitParameter(i, AnyTagged(zone));
  }
  return function;
}

void OnStackArgsDescriptorBase::InitializePlatformSpecific(
    CallInterfaceDescriptorData* data) {
  data->InitializePlatformSpecific(0, nullptr);
}

void GrowArrayElementsDescriptor::InitializePlatformSpecific(
    CallInterfaceDescriptorData* data) {
  Register registers[] = {ObjectRegister(), KeyRegister()};
  data->InitializePlatformSpecific(arraysize(registers), registers);
}

FunctionType*
VarArgFunctionDescriptor::BuildCallInterfaceDescriptorFunctionType(
    Isolate* isolate, int paramater_count) {
  Zone* zone = isolate->interface_descriptor_zone();
  FunctionType* function =
      Type::Function(AnyTagged(zone), AnyTagged(zone), 1, zone)->AsFunction();
  function->InitParameter(0, UntaggedIntegral32(zone));  // actual #arguments
  return function;
}

FunctionType*
FastCloneRegExpDescriptor::BuildCallInterfaceDescriptorFunctionType(
    Isolate* isolate, int paramater_count) {
  Zone* zone = isolate->interface_descriptor_zone();
  FunctionType* function =
      Type::Function(AnyTagged(zone), Type::Undefined(), 4, zone)->AsFunction();
  function->InitParameter(0, AnyTagged(zone));  // closure
  function->InitParameter(1, SmiType(zone));    // literal_index
  function->InitParameter(2, AnyTagged(zone));  // pattern
  function->InitParameter(3, AnyTagged(zone));  // flags
  return function;
}

FunctionType*
FastCloneShallowArrayDescriptor::BuildCallInterfaceDescriptorFunctionType(
    Isolate* isolate, int paramater_count) {
  Zone* zone = isolate->interface_descriptor_zone();
  FunctionType* function =
      Type::Function(AnyTagged(zone), Type::Undefined(), 3, zone)->AsFunction();
  function->InitParameter(0, AnyTagged(zone));
  function->InitParameter(1, SmiType(zone));
  function->InitParameter(2, AnyTagged(zone));
  return function;
}

FunctionType*
CreateAllocationSiteDescriptor::BuildCallInterfaceDescriptorFunctionType(
    Isolate* isolate, int paramater_count) {
  Zone* zone = isolate->interface_descriptor_zone();
  FunctionType* function =
      Type::Function(AnyTagged(zone), Type::Undefined(), 2, zone)->AsFunction();
  function->InitParameter(0, AnyTagged(zone));
  function->InitParameter(1, SmiType(zone));
  return function;
}

FunctionType*
CreateWeakCellDescriptor::BuildCallInterfaceDescriptorFunctionType(
    Isolate* isolate, int paramater_count) {
  Zone* zone = isolate->interface_descriptor_zone();
  FunctionType* function =
      Type::Function(AnyTagged(zone), Type::Undefined(), 3, zone)->AsFunction();
  function->InitParameter(0, AnyTagged(zone));
  function->InitParameter(1, SmiType(zone));
  function->InitParameter(2, AnyTagged(zone));
  return function;
}

FunctionType*
CallTrampolineDescriptor::BuildCallInterfaceDescriptorFunctionType(
    Isolate* isolate, int paramater_count) {
  Zone* zone = isolate->interface_descriptor_zone();
  FunctionType* function =
      Type::Function(AnyTagged(zone), Type::Undefined(), 2, zone)->AsFunction();
  function->InitParameter(0, AnyTagged(zone));           // target
  function->InitParameter(1, UntaggedIntegral32(zone));  // actual #arguments
  return function;
}

FunctionType* ConstructStubDescriptor::BuildCallInterfaceDescriptorFunctionType(
    Isolate* isolate, int paramater_count) {
  Zone* zone = isolate->interface_descriptor_zone();
  FunctionType* function =
      Type::Function(AnyTagged(zone), Type::Undefined(), 4, zone)->AsFunction();
  function->InitParameter(0, AnyTagged(zone));           // target
  function->InitParameter(1, AnyTagged(zone));           // new.target
  function->InitParameter(2, UntaggedIntegral32(zone));  // actual #arguments
  function->InitParameter(3, AnyTagged(zone));           // opt. allocation site
  return function;
}

FunctionType*
ConstructTrampolineDescriptor::BuildCallInterfaceDescriptorFunctionType(
    Isolate* isolate, int paramater_count) {
  Zone* zone = isolate->interface_descriptor_zone();
  FunctionType* function =
      Type::Function(AnyTagged(zone), Type::Undefined(), 3, zone)->AsFunction();
  function->InitParameter(0, AnyTagged(zone));           // target
  function->InitParameter(1, AnyTagged(zone));           // new.target
  function->InitParameter(2, UntaggedIntegral32(zone));  // actual #arguments
  return function;
}

FunctionType*
CallFunctionWithFeedbackDescriptor::BuildCallInterfaceDescriptorFunctionType(
    Isolate* isolate, int paramater_count) {
  Zone* zone = isolate->interface_descriptor_zone();
  FunctionType* function =
      Type::Function(AnyTagged(zone), Type::Undefined(), 2, zone)->AsFunction();
  function->InitParameter(0, Type::Receiver());  // JSFunction
  function->InitParameter(1, SmiType(zone));
  return function;
}

FunctionType* CallFunctionWithFeedbackAndVectorDescriptor::
    BuildCallInterfaceDescriptorFunctionType(Isolate* isolate,
                                             int paramater_count) {
  Zone* zone = isolate->interface_descriptor_zone();
  FunctionType* function =
      Type::Function(AnyTagged(zone), Type::Undefined(), 3, zone)->AsFunction();
  function->InitParameter(0, Type::Receiver());  // JSFunction
  function->InitParameter(1, SmiType(zone));
  function->InitParameter(2, AnyTagged(zone));
  return function;
}

FunctionType*
ArrayNoArgumentConstructorDescriptor::BuildCallInterfaceDescriptorFunctionType(
    Isolate* isolate, int paramater_count) {
  Zone* zone = isolate->interface_descriptor_zone();
  FunctionType* function =
      Type::Function(AnyTagged(zone), Type::Undefined(), 4, zone)->AsFunction();
  function->InitParameter(0, Type::Receiver());  // JSFunction
  function->InitParameter(1, AnyTagged(zone));
  function->InitParameter(2, UntaggedIntegral32(zone));
  function->InitParameter(3, AnyTagged(zone));
  return function;
}

FunctionType* ArraySingleArgumentConstructorDescriptor::
    BuildCallInterfaceDescriptorFunctionType(Isolate* isolate,
                                             int paramater_count) {
  Zone* zone = isolate->interface_descriptor_zone();
  FunctionType* function =
      Type::Function(AnyTagged(zone), Type::Undefined(), 5, zone)->AsFunction();
  function->InitParameter(0, Type::Receiver());  // JSFunction
  function->InitParameter(1, AnyTagged(zone));
  function->InitParameter(2, UntaggedIntegral32(zone));
  function->InitParameter(3, AnyTagged(zone));
  function->InitParameter(4, AnyTagged(zone));
  return function;
}

FunctionType*
ArrayNArgumentsConstructorDescriptor::BuildCallInterfaceDescriptorFunctionType(
    Isolate* isolate, int paramater_count) {
  Zone* zone = isolate->interface_descriptor_zone();
  FunctionType* function =
      Type::Function(AnyTagged(zone), Type::Undefined(), 3, zone)->AsFunction();
  function->InitParameter(0, Type::Receiver());  // JSFunction
  function->InitParameter(1, AnyTagged(zone));   // Allocation site or undefined
  function->InitParameter(2, UntaggedIntegral32(zone));  //  Arg count
  return function;
}

FunctionType*
ArgumentAdaptorDescriptor::BuildCallInterfaceDescriptorFunctionType(
    Isolate* isolate, int paramater_count) {
  Zone* zone = isolate->interface_descriptor_zone();
  FunctionType* function =
      Type::Function(AnyTagged(zone), Type::Undefined(), 4, zone)->AsFunction();
  function->InitParameter(0, Type::Receiver());          // JSFunction
  function->InitParameter(1, AnyTagged(zone));           // the new target
  function->InitParameter(2, UntaggedIntegral32(zone));  // actual #arguments
  function->InitParameter(3, UntaggedIntegral32(zone));  // expected #arguments
  return function;
}

CallInterfaceDescriptor ApiCallbackDescriptorBase::ForArgs(Isolate* isolate,
                                                           int argc) {
  switch (argc) {
    case 0:
      return ApiCallbackWith0ArgsDescriptor(isolate);
    case 1:
      return ApiCallbackWith1ArgsDescriptor(isolate);
    case 2:
      return ApiCallbackWith2ArgsDescriptor(isolate);
    case 3:
      return ApiCallbackWith3ArgsDescriptor(isolate);
    case 4:
      return ApiCallbackWith4ArgsDescriptor(isolate);
    case 5:
      return ApiCallbackWith5ArgsDescriptor(isolate);
    case 6:
      return ApiCallbackWith6ArgsDescriptor(isolate);
    case 7:
      return ApiCallbackWith7ArgsDescriptor(isolate);
    default:
      UNREACHABLE();
      return VoidDescriptor(isolate);
  }
}

FunctionType*
ApiCallbackDescriptorBase::BuildCallInterfaceDescriptorFunctionTypeWithArg(
    Isolate* isolate, int parameter_count, int argc) {
  Zone* zone = isolate->interface_descriptor_zone();
  FunctionType* function =
      Type::Function(AnyTagged(zone), Type::Undefined(), 4 + argc, zone)
          ->AsFunction();
  function->InitParameter(0, AnyTagged(zone));        // callee
  function->InitParameter(1, AnyTagged(zone));        // call_data
  function->InitParameter(2, AnyTagged(zone));        // holder
  function->InitParameter(3, ExternalPointer(zone));  // api_function_address
  for (int i = 0; i < argc; i++) {
    function->InitParameter(i, AnyTagged(zone));
  }
  return function;
}

FunctionType*
InterpreterDispatchDescriptor::BuildCallInterfaceDescriptorFunctionType(
    Isolate* isolate, int parameter_count) {
  Zone* zone = isolate->interface_descriptor_zone();
  FunctionType* function =
      Type::Function(AnyTagged(zone), Type::Undefined(), 4, zone)->AsFunction();
  function->InitParameter(kAccumulatorParameter, AnyTagged(zone));
  function->InitParameter(kBytecodeOffsetParameter, UntaggedIntegral32(zone));
  function->InitParameter(kBytecodeArrayParameter, AnyTagged(zone));
  function->InitParameter(kDispatchTableParameter, AnyTagged(zone));
  return function;
}

}  // namespace internal
}  // namespace v8
