// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

#ifndef RUNTIME_VM_COMPILER_FFI_NATIVE_LOCATION_H_
#define RUNTIME_VM_COMPILER_FFI_NATIVE_LOCATION_H_

#if defined(DART_PRECOMPILED_RUNTIME)
#error "AOT runtime should not use compiler sources (including header files)"
#endif  // defined(DART_PRECOMPILED_RUNTIME)

#include "platform/assert.h"
#include "vm/compiler/backend/locations.h"
#include "vm/compiler/ffi/native_type.h"
#include "vm/growable_array.h"
#include "vm/thread.h"

namespace dart {

class BaseTextBuffer;

namespace compiler {

namespace ffi {

class NativeRegistersLocation;
class NativeFpuRegistersLocation;
class NativeStackLocation;

// NativeLocation objects are used in the FFI to describe argument and return
// value locations in all native ABIs that the FFI supports.
//
// NativeLocations contain two NativeTypes.
// * The payload type.
// * The container type, equal to or larger than the payload. If the
//   container is larger than the payload, the upper bits are defined by sign
//   or zero extension.
//   Container type is also used to denote an integer container when floating
//   point values are passed in integer registers.
//
// NativeLocations can express things that dart::Locations cannot express:
// * Multiple consecutive registers.
// * Multiple sizes of FPU registers (e.g. S, D, and Q on Arm32).
// * Arbitrary byte-size stack locations, at byte-size offsets.
//   (The Location class uses word-size offsets.)
// * Pointers to a memory location.
// * Split between multiple registers and stack.
//
// NativeLocations cannot express the following dart::Locations:
// * No PairLocations. Instead, NativeRegistersLocations can have multiple
//   registers, and NativeStackLocations can have arbitrary types.
// * No ConstantLocations.
//
// NativeLocation does not satisfy the invariant of Location: bitwise
// inequality cannot be used to determine disjointness.
class NativeLocation : public ZoneAllocated {
 public:
  static bool LocationCanBeExpressed(Location loc, Representation rep);
  static NativeLocation& FromLocation(Zone* zone,
                                      Location loc,
                                      Representation rep);
  static NativeLocation& FromPairLocation(Zone* zone,
                                          Location loc,
                                          Representation rep,
                                          intptr_t index);

  // The type of the data at this location.
  const NativeType& payload_type() const { return payload_type_; }

  // The location container size, possibly larger than data.
  //
  // If the container is larger than the data, the remaining bits are _not_
  // undefined. For example a uint8 inside a uint32 has the upper 24 bits set
  // to 0. Effectively allowing the value to be read as uint8, uint16 and
  // uint32.
  const NativeType& container_type() const { return container_type_; }

  virtual NativeLocation& WithOtherNativeType(
      Zone* zone,
      const NativeType& new_payload_type,
      const NativeType& new_container_type) const = 0;

#if defined(TARGET_ARCH_ARM)
  const NativeLocation& WidenToQFpuRegister(Zone* zone) const;
#endif  // defined(TARGET_ARCH_ARM)

  NativeLocation& WidenTo4Bytes(Zone* zone) const;

  virtual bool IsRegisters() const { return false; }
  virtual bool IsFpuRegisters() const { return false; }
  virtual bool IsStack() const { return false; }

  virtual bool IsExpressibleAsLocation() const { return false; }
  virtual Location AsLocation() const {
    ASSERT(IsExpressibleAsLocation());
    UNREACHABLE();
  }

  virtual void PrintTo(BaseTextBuffer* f) const;
  const char* ToCString() const;

  const NativeRegistersLocation& AsRegisters() const;
  const NativeFpuRegistersLocation& AsFpuRegisters() const;
  const NativeStackLocation& AsStack() const;

  virtual NativeLocation& Split(Zone* zone, intptr_t index) const {
    ASSERT(index == 0 || index == 1);
    UNREACHABLE();
  }

  // Return the top of the stack in bytes.
  virtual intptr_t StackTopInBytes() const { return 0; }

  // Equality of location, ignores the payload and container native types.
  virtual bool Equals(const NativeLocation& other) const { UNREACHABLE(); }

  virtual ~NativeLocation() {}

 protected:
  NativeLocation(const NativeType& payload_type,
                 const NativeType& container_type)
      : payload_type_(payload_type), container_type_(container_type) {}

 private:
  const NativeType& payload_type_;
  // The location container size, possibly larger than data.
  //
  // If the container is larger than the data, the remaining bits are _not_
  // undefined. For example a uint8 inside a uint32 has the upper 24 bits set
  // to 0. Effectively allowing the value to be read as uint8, uint16 and
  // uint32.
  const NativeType& container_type_;
};

class NativeRegistersLocation : public NativeLocation {
 public:
  NativeRegistersLocation(const NativeType& payload_type,
                          const NativeType& container_type,
                          ZoneGrowableArray<Register>* registers)
      : NativeLocation(payload_type, container_type), regs_(registers) {}
  NativeRegistersLocation(const NativeType& payload_type,
                          const NativeType& container_type,
                          Register reg)
      : NativeLocation(payload_type, container_type) {
    regs_ = new ZoneGrowableArray<Register>();
    regs_->Add(reg);
  }
  NativeRegistersLocation(const NativeType& payload_type,
                          const NativeType& container_type,
                          Register register1,
                          Register register2)
      : NativeLocation(payload_type, container_type) {
    regs_ = new ZoneGrowableArray<Register>();
    regs_->Add(register1);
    regs_->Add(register2);
  }
  virtual ~NativeRegistersLocation() {}

  virtual NativeRegistersLocation& WithOtherNativeType(
      Zone* zone,
      const NativeType& new_payload_type,
      const NativeType& new_container_type) const {
    return *new (zone)
        NativeRegistersLocation(new_payload_type, new_container_type, regs_);
  }

  virtual bool IsRegisters() const { return true; }
  virtual bool IsExpressibleAsLocation() const {
    return num_regs() == 1 || num_regs() == 2;
  }
  virtual Location AsLocation() const;
  intptr_t num_regs() const { return regs_->length(); }
  Register reg_at(intptr_t index) const { return regs_->At(index); }

  virtual NativeRegistersLocation& Split(Zone* zone, intptr_t index) const;

  virtual void PrintTo(BaseTextBuffer* f) const;

  virtual bool Equals(const NativeLocation& other) const;

 private:
  ZoneGrowableArray<Register>* regs_;

  DISALLOW_COPY_AND_ASSIGN(NativeRegistersLocation);
};

enum FpuRegisterKind {
  kQuadFpuReg,    // 16 bytes
  kDoubleFpuReg,  //  8 bytes, a double
  kSingleFpuReg   //  4 bytes, a float
};

intptr_t SizeFromFpuRegisterKind(FpuRegisterKind kind);
FpuRegisterKind FpuRegisterKindFromSize(intptr_t size_in_bytes);

class NativeFpuRegistersLocation : public NativeLocation {
 public:
  NativeFpuRegistersLocation(const NativeType& payload_type,
                             const NativeType& container_type,
                             FpuRegisterKind fpu_reg_kind,
                             intptr_t fpu_register)
      : NativeLocation(payload_type, container_type),
        fpu_reg_kind_(fpu_reg_kind),
        fpu_reg_(fpu_register) {}
  NativeFpuRegistersLocation(const NativeType& payload_type,
                             const NativeType& container_type,
                             FpuRegister fpu_register)
      : NativeLocation(payload_type, container_type),
        fpu_reg_kind_(kQuadFpuReg),
        fpu_reg_(fpu_register) {}
#if defined(TARGET_ARCH_ARM)
  NativeFpuRegistersLocation(const NativeType& payload_type,
                             const NativeType& container_type,
                             DRegister fpu_register)
      : NativeLocation(payload_type, container_type),
        fpu_reg_kind_(kDoubleFpuReg),
        fpu_reg_(fpu_register) {}
  NativeFpuRegistersLocation(const NativeType& payload_type,
                             const NativeType& container_type,
                             SRegister fpu_register)
      : NativeLocation(payload_type, container_type),
        fpu_reg_kind_(kSingleFpuReg),
        fpu_reg_(fpu_register) {}
#endif  // defined(TARGET_ARCH_ARM)
  virtual ~NativeFpuRegistersLocation() {}

  virtual NativeFpuRegistersLocation& WithOtherNativeType(
      Zone* zone,
      const NativeType& new_payload_type,
      const NativeType& new_container_type) const {
    return *new (zone) NativeFpuRegistersLocation(
        new_payload_type, new_container_type, fpu_reg_kind_, fpu_reg_);
  }
  virtual bool IsFpuRegisters() const { return true; }
  virtual bool IsExpressibleAsLocation() const {
    return fpu_reg_kind_ == kQuadFpuReg;
  }
  virtual Location AsLocation() const {
    ASSERT(IsExpressibleAsLocation());
    return Location::FpuRegisterLocation(fpu_reg());
  }
  FpuRegisterKind fpu_reg_kind() const { return fpu_reg_kind_; }
  FpuRegister fpu_reg() const {
    ASSERT(fpu_reg_kind_ == kQuadFpuReg);
    return static_cast<FpuRegister>(fpu_reg_);
  }
#if defined(TARGET_ARCH_ARM)
  DRegister fpu_d_reg() const {
    ASSERT(fpu_reg_kind_ == kDoubleFpuReg);
    return static_cast<DRegister>(fpu_reg_);
  }
  SRegister fpu_s_reg() const {
    ASSERT(fpu_reg_kind_ == kSingleFpuReg);
    return static_cast<SRegister>(fpu_reg_);
  }
  DRegister fpu_as_d_reg() const;
  SRegister fpu_as_s_reg() const;

  bool IsLowestBits() const;
#endif  // defined(TARGET_ARCH_ARM)

  virtual void PrintTo(BaseTextBuffer* f) const;

  virtual bool Equals(const NativeLocation& other) const;

 private:
  FpuRegisterKind fpu_reg_kind_;
  intptr_t fpu_reg_;
  DISALLOW_COPY_AND_ASSIGN(NativeFpuRegistersLocation);
};

class NativeStackLocation : public NativeLocation {
 public:
  NativeStackLocation(const NativeType& payload_type,
                      const NativeType& container_type,
                      Register base_register,
                      intptr_t offset_in_bytes)
      : NativeLocation(payload_type, container_type),
        base_register_(base_register),
        offset_in_bytes_(offset_in_bytes) {}
  virtual ~NativeStackLocation() {}

  virtual NativeStackLocation& WithOtherNativeType(
      Zone* zone,
      const NativeType& new_payload_type,
      const NativeType& new_container_type) const {
    return *new (zone) NativeStackLocation(new_payload_type, new_container_type,
                                           base_register_, offset_in_bytes_);
  }

  virtual bool IsStack() const { return true; }
  virtual bool IsExpressibleAsLocation() const {
    const intptr_t size = payload_type().SizeInBytes();
    const intptr_t size_slots = size / compiler::target::kWordSize;
    return offset_in_bytes_ % compiler::target::kWordSize == 0 &&
           size % compiler::target::kWordSize == 0 &&
           (size_slots == 1 || size_slots == 2);
  }
  virtual Location AsLocation() const;

  // ConstantInstr expects DoubleStackSlot for doubles, even on 64-bit systems.
  //
  // So this return a wrong-sized Location on purpose.
  Location AsDoubleStackSlotLocation() const {
    ASSERT(compiler::target::kWordSize == 8);
    return Location::DoubleStackSlot(offset_in_words(), base_register_);
  }

  virtual NativeStackLocation& Split(Zone* zone, intptr_t index) const;

  virtual intptr_t StackTopInBytes() const {
    return offset_in_bytes() + container_type().SizeInBytes();
  }

  virtual void PrintTo(BaseTextBuffer* f) const;

  virtual bool Equals(const NativeLocation& other) const;

  Register base_register() const { return base_register_; }
  intptr_t offset_in_bytes() const { return offset_in_bytes_; }

 private:
  intptr_t offset_in_words() const {
    ASSERT(offset_in_bytes_ % compiler::target::kWordSize == 0);
    return offset_in_bytes_ / compiler::target::kWordSize;
  }

  Register base_register_;
  intptr_t offset_in_bytes_;

  DISALLOW_COPY_AND_ASSIGN(NativeStackLocation);
};

// Return a memory operand for stack slot locations.
compiler::Address NativeLocationToStackSlotAddress(
    const NativeStackLocation& loc);

}  // namespace ffi

}  // namespace compiler

}  // namespace dart

#endif  // RUNTIME_VM_COMPILER_FFI_NATIVE_LOCATION_H_
