// Copyright 2017 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/assembler-inl.h"
#include "src/base/utils/random-number-generator.h"
#include "src/codegen.h"
#include "src/compilation-info.h"
#include "src/compiler/code-generator.h"
#include "src/compiler/instruction.h"
#include "src/compiler/linkage.h"
#include "src/isolate.h"
#include "src/objects-inl.h"

#include "test/cctest/cctest.h"
#include "test/cctest/compiler/function-tester.h"

namespace v8 {
namespace internal {
namespace compiler {

namespace {

int GetSlotSizeInBytes(MachineRepresentation rep) {
  switch (rep) {
    case MachineRepresentation::kTagged:
    case MachineRepresentation::kFloat32:
      return kPointerSize;
    case MachineRepresentation::kFloat64:
      return kDoubleSize;
    case MachineRepresentation::kSimd128:
      return kSimd128Size;
    default:
      break;
  }
  UNREACHABLE();
}

}  // namespace

// Wrapper around the CodeGenerator with the ability to randomly generate moves
// and swaps which can then be executed. The `slots` map represents how many
// slots should be allocated per representation. Parallel moves will then be
// generated by randomly picking slots. Constants can be provided so that
// parallel moves may use them.
//
// At the moment, only the following representations are tested:
//   - kTagged
//   - kFloat32
//   - kFloat64
//   - kSimd128
// There is no need to test using Word32 or Word64 as they are the same as
// Tagged as far as the code generator is concerned.
class CodeGeneratorTester : public HandleAndZoneScope {
 public:
  CodeGeneratorTester(std::map<MachineRepresentation, int> slots =
                          std::map<MachineRepresentation, int>{},
                      std::initializer_list<Constant> constants = {})
      : info_(ArrayVector("test"), main_isolate(), main_zone(), Code::STUB),
        descriptor_(Linkage::GetStubCallDescriptor(
            main_isolate(), main_zone(), VoidDescriptor(main_isolate()), 0,
            CallDescriptor::kNoFlags, Operator::kNoProperties,
            MachineType::AnyTagged(), 0)),
        linkage_(descriptor_),
        blocks_(main_zone()),
        sequence_(main_isolate(), main_zone(), &blocks_),
        rng_(CcTest::random_number_generator()),
        frame_(descriptor_->CalculateFixedFrameSize()),
        generator_(main_zone(), &frame_, &linkage_, &sequence_, &info_,
                   base::Optional<OsrHelper>(), kNoSourcePosition, nullptr) {
    // Keep track of all supported representations depending on what kind of
    // stack slots are supported.
    for (const auto& slot : slots) {
      supported_reps_.push_back(slot.first);
    }
    // Allocate new slots until we run out of them.
    while (std::any_of(slots.cbegin(), slots.cend(),
                       [](const std::pair<MachineRepresentation, int>& entry) {
                         // True if there are slots left to allocate for this
                         // representation.
                         return entry.second > 0;
                       })) {
      // Pick a random MachineRepresentation from supported_reps_.
      MachineRepresentation rep = CreateRandomMachineRepresentation();
      auto entry = slots.find(rep);
      DCHECK(entry != slots.end());
      // We may have picked a representation for which all slots have already
      // been allocated.
      if (entry->second > 0) {
        // Keep a map of (MachineRepresentation . std::vector<int>) with
        // allocated slots to pick from for each representation.
        RegisterSlot(rep, frame_.AllocateSpillSlot(GetSlotSizeInBytes(rep)));
        entry->second--;
      }
    }
    for (auto constant : constants) {
      int virtual_register = AllocateConstant(constant);
      // Associate constants with their compatible representations.
      // TODO(all): Test all types of constants.
      switch (constant.type()) {
        // Integer constants are always moved to a tagged location, whatever
        // their sizes.
        case Constant::kInt32:
        case Constant::kInt64:
          RegisterConstant(MachineRepresentation::kTagged, virtual_register);
          break;
        // FP constants may be moved to a tagged location using a heap number,
        // or directly to a location of the same size.
        case Constant::kFloat32:
          RegisterConstant(MachineRepresentation::kTagged, virtual_register);
          RegisterConstant(MachineRepresentation::kFloat32, virtual_register);
          break;
        case Constant::kFloat64:
          RegisterConstant(MachineRepresentation::kTagged, virtual_register);
          RegisterConstant(MachineRepresentation::kFloat64, virtual_register);
          break;
        default:
          break;
      }
    }
    // Force a frame to be created.
    generator_.frame_access_state()->MarkHasFrame(true);
    generator_.AssembleConstructFrame();
    // TODO(all): Generate a stack check here so that we fail gracefully if the
    // frame is too big.
  }

  int AllocateConstant(Constant constant) {
    int virtual_register = sequence_.NextVirtualRegister();
    sequence_.AddConstant(virtual_register, constant);
    return virtual_register;
  }

  // Register a constant referenced by `virtual_register` as compatible with
  // `rep`.
  void RegisterConstant(MachineRepresentation rep, int virtual_register) {
    auto entry = constants_.find(rep);
    if (entry == constants_.end()) {
      std::vector<int> vregs = {virtual_register};
      constants_.emplace(rep, vregs);
    } else {
      entry->second.push_back(virtual_register);
    }
  }

  void RegisterSlot(MachineRepresentation rep, int slot) {
    auto entry = allocated_slots_.find(rep);
    if (entry == allocated_slots_.end()) {
      std::vector<int> slots = {slot};
      allocated_slots_.emplace(rep, slots);
    } else {
      entry->second.push_back(slot);
    }
  }

  enum PushTypeFlag {
    kRegisterPush = CodeGenerator::kRegisterPush,
    kStackSlotPush = CodeGenerator::kStackSlotPush,
    kScalarPush = CodeGenerator::kScalarPush
  };

  enum OperandConstraint {
    kNone,
    // Restrict operands to non-constants. This is useful when generating a
    // destination.
    kCannotBeConstant
  };

  // Generate parallel moves at random. Note that they may not be compatible
  // between each other as this doesn't matter to the code generator.
  ParallelMove* GenerateRandomMoves(int size) {
    ParallelMove* parallel_move = new (main_zone()) ParallelMove(main_zone());

    for (int i = 0; i < size;) {
      MachineRepresentation rep = CreateRandomMachineRepresentation();
      MoveOperands mo(CreateRandomOperand(kNone, rep),
                      CreateRandomOperand(kCannotBeConstant, rep));
      // It isn't valid to call `AssembleMove` and `AssembleSwap` with redundant
      // moves.
      if (mo.IsRedundant()) continue;
      parallel_move->AddMove(mo.source(), mo.destination());
      // Iterate only when a move was created.
      i++;
    }

    return parallel_move;
  }

  ParallelMove* GenerateRandomSwaps(int size) {
    ParallelMove* parallel_move = new (main_zone()) ParallelMove(main_zone());

    for (int i = 0; i < size;) {
      MachineRepresentation rep = CreateRandomMachineRepresentation();
      InstructionOperand lhs = CreateRandomOperand(kCannotBeConstant, rep);
      InstructionOperand rhs = CreateRandomOperand(kCannotBeConstant, rep);
      MoveOperands mo(lhs, rhs);
      // It isn't valid to call `AssembleMove` and `AssembleSwap` with redundant
      // moves.
      if (mo.IsRedundant()) continue;
      // Canonicalize the swap: the register operand has to be the left hand
      // side.
      if (lhs.IsStackSlot() || lhs.IsFPStackSlot()) {
        std::swap(lhs, rhs);
      }
      parallel_move->AddMove(lhs, rhs);
      // Iterate only when a swap was created.
      i++;
    }

    return parallel_move;
  }

  MachineRepresentation CreateRandomMachineRepresentation() {
    int index = rng_->NextInt(static_cast<int>(supported_reps_.size()));
    return supported_reps_[index];
  }

  InstructionOperand CreateRandomOperand(OperandConstraint constraint,
                                         MachineRepresentation rep) {
    // Only generate a Constant if the operand is a source and we have a
    // constant with a compatible representation in stock.
    bool generate_constant = (constraint != kCannotBeConstant) &&
                             (constants_.find(rep) != constants_.end());
    switch (rng_->NextInt(generate_constant ? 3 : 2)) {
      case 0:
        return CreateRandomStackSlotOperand(rep);
      case 1:
        return CreateRandomRegisterOperand(rep);
      case 2:
        return CreateRandomConstant(rep);
    }
    UNREACHABLE();
  }

  InstructionOperand CreateRandomRegisterOperand(MachineRepresentation rep) {
    int code;
    const RegisterConfiguration* conf = RegisterConfiguration::Default();
    switch (rep) {
      case MachineRepresentation::kFloat32: {
        int index = rng_->NextInt(conf->num_allocatable_float_registers());
        code = conf->RegisterConfiguration::GetAllocatableFloatCode(index);
        break;
      }
      case MachineRepresentation::kFloat64: {
        int index = rng_->NextInt(conf->num_allocatable_double_registers());
        code = conf->RegisterConfiguration::GetAllocatableDoubleCode(index);
        break;
      }
      case MachineRepresentation::kSimd128: {
        int index = rng_->NextInt(conf->num_allocatable_simd128_registers());
        code = conf->RegisterConfiguration::GetAllocatableSimd128Code(index);
        break;
      }
      case MachineRepresentation::kTagged: {
        // Pick an allocatable register that is not the return register.
        do {
          int index = rng_->NextInt(conf->num_allocatable_general_registers());
          code = conf->RegisterConfiguration::GetAllocatableGeneralCode(index);
        } while (code == kReturnRegister0.code());
        break;
      }
      default:
        UNREACHABLE();
        break;
    }
    return AllocatedOperand(LocationOperand::REGISTER, rep, code);
  }

  InstructionOperand CreateRandomStackSlotOperand(MachineRepresentation rep) {
    int index = rng_->NextInt(static_cast<int>(allocated_slots_[rep].size()));
    return AllocatedOperand(LocationOperand::STACK_SLOT, rep,
                            allocated_slots_[rep][index]);
  }

  InstructionOperand CreateRandomConstant(MachineRepresentation rep) {
    int index = rng_->NextInt(static_cast<int>(constants_[rep].size()));
    return ConstantOperand(constants_[rep][index]);
  }

  void CheckAssembleTailCallGaps(Instruction* instr,
                                 int first_unused_stack_slot,
                                 CodeGeneratorTester::PushTypeFlag push_type) {
    generator_.AssembleTailCallBeforeGap(instr, first_unused_stack_slot);
#if defined(V8_TARGET_ARCH_ARM) || defined(V8_TARGET_ARCH_S390) || \
    defined(V8_TARGET_ARCH_PPC)
    // Only folding register pushes is supported on ARM.
    bool supported = ((push_type & CodeGenerator::kRegisterPush) == push_type);
#elif defined(V8_TARGET_ARCH_X64) || defined(V8_TARGET_ARCH_IA32) || \
    defined(V8_TARGET_ARCH_X87)
    bool supported = ((push_type & CodeGenerator::kScalarPush) == push_type);
#else
    bool supported = false;
#endif
    if (supported) {
      // Architectures supporting folding adjacent pushes should now have
      // resolved all moves.
      for (const auto& move :
           *instr->parallel_moves()[Instruction::FIRST_GAP_POSITION]) {
        CHECK(move->IsEliminated());
      }
    }
    generator_.AssembleGaps(instr);
    generator_.AssembleTailCallAfterGap(instr, first_unused_stack_slot);
  }

  void CheckAssembleMove(InstructionOperand* source,
                         InstructionOperand* destination) {
    int start = generator_.tasm()->pc_offset();
    generator_.AssembleMove(source, destination);
    CHECK(generator_.tasm()->pc_offset() > start);
  }

  void CheckAssembleSwap(InstructionOperand* source,
                         InstructionOperand* destination) {
    int start = generator_.tasm()->pc_offset();
    generator_.AssembleSwap(source, destination);
    CHECK(generator_.tasm()->pc_offset() > start);
  }

  Handle<Code> Finalize() {
    InstructionOperand zero = ImmediateOperand(ImmediateOperand::INLINE, 0);
    generator_.AssembleReturn(&zero);

    generator_.FinishCode();
    generator_.safepoints()->Emit(generator_.tasm(),
                                  frame_.GetTotalFrameSlotCount());
    return generator_.FinalizeCode();
  }

  void Disassemble() {
    HandleScope scope(main_isolate());
    Handle<Code> code = Finalize();
    if (FLAG_print_code) {
      code->Print();
    }
  }

  void Run() {
    HandleScope scope(main_isolate());
    Handle<Code> code = Finalize();
    if (FLAG_print_code) {
      code->Print();
    }
    FunctionTester ft(code);
    ft.Call();
  }

  v8::base::RandomNumberGenerator* rng() const { return rng_; }

 private:
  CompilationInfo info_;
  CallDescriptor* descriptor_;
  Linkage linkage_;
  ZoneVector<InstructionBlock*> blocks_;
  InstructionSequence sequence_;
  std::vector<MachineRepresentation> supported_reps_;
  std::map<MachineRepresentation, std::vector<int>> allocated_slots_;
  std::map<MachineRepresentation, std::vector<int>> constants_;
  v8::base::RandomNumberGenerator* rng_;
  Frame frame_;
  CodeGenerator generator_;
};

// The following fuzz tests will assemble a lot of moves, wrap them in
// executable native code and run them. At this time, we only check that
// something is actually generated, and that it runs on hardware or the
// simulator.

// TODO(all): It would be great to record the data on the stack after all moves
// are executed so that we could test the functionality in an architecture
// independent way. We would also have to make sure we generate moves compatible
// with each other as the gap-resolver tests do.

TEST(FuzzAssembleMove) {
  // Test small and potentially large ranges separately. Note that the number of
  // slots affects how much stack is allocated when running the generated code.
  // This means we have to be careful not to exceed the stack limit, which is
  // lower on Windows.
  for (auto n : {64, 500}) {
    std::map<MachineRepresentation, int> slots = {
        {MachineRepresentation::kTagged, n},
        {MachineRepresentation::kFloat32, n},
        {MachineRepresentation::kFloat64, n}};
    if (CpuFeatures::SupportsWasmSimd128()) {
      // Generate fewer 128-bit slots.
      slots.emplace(MachineRepresentation::kSimd128, n / 4);
    }
    CodeGeneratorTester c(
        slots,
        {Constant(0), Constant(1), Constant(2), Constant(3), Constant(4),
         Constant(5), Constant(6), Constant(7),
         Constant(static_cast<float>(0.1)), Constant(static_cast<float>(0.2)),
         Constant(static_cast<float>(0.3)), Constant(static_cast<float>(0.4)),
         Constant(static_cast<double>(0.5)), Constant(static_cast<double>(0.6)),
         Constant(static_cast<double>(0.7)),
         Constant(static_cast<double>(0.8))});
    ParallelMove* moves = c.GenerateRandomMoves(1000);
    for (const auto m : *moves) {
      c.CheckAssembleMove(&m->source(), &m->destination());
    }
    c.Run();
  }
}

TEST(FuzzAssembleSwap) {
  // Test small and potentially large ranges separately. Note that the number of
  // slots affects how much stack is allocated when running the generated code.
  // This means we have to be careful not to exceed the stack limit, which is
  // lower on Windows.
  for (auto n : {64, 500}) {
    std::map<MachineRepresentation, int> slots = {
        {MachineRepresentation::kTagged, n},
        {MachineRepresentation::kFloat32, n},
        {MachineRepresentation::kFloat64, n}};
    if (CpuFeatures::SupportsWasmSimd128()) {
      // Generate fewer 128-bit slots.
      slots.emplace(MachineRepresentation::kSimd128, n / 4);
    }
    CodeGeneratorTester c(slots);
    ParallelMove* moves = c.GenerateRandomSwaps(1000);
    for (const auto m : *moves) {
      c.CheckAssembleSwap(&m->source(), &m->destination());
    }
    c.Run();
  }
}

TEST(FuzzAssembleMoveAndSwap) {
  // Test small and potentially large ranges separately. Note that the number of
  // slots affects how much stack is allocated when running the generated code.
  // This means we have to be careful not to exceed the stack limit, which is
  // lower on Windows.
  for (auto n : {64, 500}) {
    std::map<MachineRepresentation, int> slots = {
        {MachineRepresentation::kTagged, n},
        {MachineRepresentation::kFloat32, n},
        {MachineRepresentation::kFloat64, n}};
    if (CpuFeatures::SupportsWasmSimd128()) {
      // Generate fewer 128-bit slots.
      slots.emplace(MachineRepresentation::kSimd128, n / 4);
    }
    CodeGeneratorTester c(
        slots,
        {Constant(0), Constant(1), Constant(2), Constant(3), Constant(4),
         Constant(5), Constant(6), Constant(7),
         Constant(static_cast<float>(0.1)), Constant(static_cast<float>(0.2)),
         Constant(static_cast<float>(0.3)), Constant(static_cast<float>(0.4)),
         Constant(static_cast<double>(0.5)), Constant(static_cast<double>(0.6)),
         Constant(static_cast<double>(0.7)),
         Constant(static_cast<double>(0.8))});
    for (int i = 0; i < 1000; i++) {
      // Randomly alternate between swaps and moves.
      if (c.rng()->NextInt(2) == 0) {
        MoveOperands* move = c.GenerateRandomMoves(1)->at(0);
        c.CheckAssembleMove(&move->source(), &move->destination());
      } else {
        MoveOperands* move = c.GenerateRandomSwaps(1)->at(0);
        c.CheckAssembleSwap(&move->source(), &move->destination());
      }
    }
    c.Run();
  }
}

TEST(AssembleTailCallGap) {
  const RegisterConfiguration* conf = RegisterConfiguration::Default();

  // This test assumes at least 4 registers are allocatable.
  CHECK_LE(4, conf->num_allocatable_general_registers());

  auto r0 = AllocatedOperand(LocationOperand::REGISTER,
                             MachineRepresentation::kTagged,
                             conf->GetAllocatableGeneralCode(0));
  auto r1 = AllocatedOperand(LocationOperand::REGISTER,
                             MachineRepresentation::kTagged,
                             conf->GetAllocatableGeneralCode(1));
  auto r2 = AllocatedOperand(LocationOperand::REGISTER,
                             MachineRepresentation::kTagged,
                             conf->GetAllocatableGeneralCode(2));
  auto r3 = AllocatedOperand(LocationOperand::REGISTER,
                             MachineRepresentation::kTagged,
                             conf->GetAllocatableGeneralCode(3));

  auto slot_minus_4 = AllocatedOperand(LocationOperand::STACK_SLOT,
                                       MachineRepresentation::kTagged, -4);
  auto slot_minus_3 = AllocatedOperand(LocationOperand::STACK_SLOT,
                                       MachineRepresentation::kTagged, -3);
  auto slot_minus_2 = AllocatedOperand(LocationOperand::STACK_SLOT,
                                       MachineRepresentation::kTagged, -2);
  auto slot_minus_1 = AllocatedOperand(LocationOperand::STACK_SLOT,
                                       MachineRepresentation::kTagged, -1);

  // Avoid slot 0 for architectures which use it store the return address.
  int first_slot = V8_TARGET_ARCH_STORES_RETURN_ADDRESS_ON_STACK ? 1 : 0;
  auto slot_0 = AllocatedOperand(LocationOperand::STACK_SLOT,
                                 MachineRepresentation::kTagged, first_slot);
  auto slot_1 =
      AllocatedOperand(LocationOperand::STACK_SLOT,
                       MachineRepresentation::kTagged, first_slot + 1);
  auto slot_2 =
      AllocatedOperand(LocationOperand::STACK_SLOT,
                       MachineRepresentation::kTagged, first_slot + 2);
  auto slot_3 =
      AllocatedOperand(LocationOperand::STACK_SLOT,
                       MachineRepresentation::kTagged, first_slot + 3);

  // These tests all generate series of moves that the code generator should
  // detect as adjacent pushes. Depending on the architecture, we make sure
  // these moves get eliminated.
  // Also, disassembling with `--print-code` is useful when debugging.

  {
    // Generate a series of register pushes only.
    CodeGeneratorTester c;
    Instruction* instr = Instruction::New(c.main_zone(), kArchNop);
    instr
        ->GetOrCreateParallelMove(Instruction::FIRST_GAP_POSITION,
                                  c.main_zone())
        ->AddMove(r3, slot_0);
    instr
        ->GetOrCreateParallelMove(Instruction::FIRST_GAP_POSITION,
                                  c.main_zone())
        ->AddMove(r2, slot_1);
    instr
        ->GetOrCreateParallelMove(Instruction::FIRST_GAP_POSITION,
                                  c.main_zone())
        ->AddMove(r1, slot_2);
    instr
        ->GetOrCreateParallelMove(Instruction::FIRST_GAP_POSITION,
                                  c.main_zone())
        ->AddMove(r0, slot_3);

    c.CheckAssembleTailCallGaps(instr, first_slot + 4,
                                CodeGeneratorTester::kRegisterPush);
    c.Disassemble();
  }

  {
    // Generate a series of stack pushes only.
    CodeGeneratorTester c;
    Instruction* instr = Instruction::New(c.main_zone(), kArchNop);
    instr
        ->GetOrCreateParallelMove(Instruction::FIRST_GAP_POSITION,
                                  c.main_zone())
        ->AddMove(slot_minus_4, slot_0);
    instr
        ->GetOrCreateParallelMove(Instruction::FIRST_GAP_POSITION,
                                  c.main_zone())
        ->AddMove(slot_minus_3, slot_1);
    instr
        ->GetOrCreateParallelMove(Instruction::FIRST_GAP_POSITION,
                                  c.main_zone())
        ->AddMove(slot_minus_2, slot_2);
    instr
        ->GetOrCreateParallelMove(Instruction::FIRST_GAP_POSITION,
                                  c.main_zone())
        ->AddMove(slot_minus_1, slot_3);

    c.CheckAssembleTailCallGaps(instr, first_slot + 4,
                                CodeGeneratorTester::kStackSlotPush);
    c.Disassemble();
  }

  {
    // Generate a mix of stack and register pushes.
    CodeGeneratorTester c;
    Instruction* instr = Instruction::New(c.main_zone(), kArchNop);
    instr
        ->GetOrCreateParallelMove(Instruction::FIRST_GAP_POSITION,
                                  c.main_zone())
        ->AddMove(slot_minus_2, slot_0);
    instr
        ->GetOrCreateParallelMove(Instruction::FIRST_GAP_POSITION,
                                  c.main_zone())
        ->AddMove(r1, slot_1);
    instr
        ->GetOrCreateParallelMove(Instruction::FIRST_GAP_POSITION,
                                  c.main_zone())
        ->AddMove(slot_minus_1, slot_2);
    instr
        ->GetOrCreateParallelMove(Instruction::FIRST_GAP_POSITION,
                                  c.main_zone())
        ->AddMove(r0, slot_3);

    c.CheckAssembleTailCallGaps(instr, first_slot + 4,
                                CodeGeneratorTester::kScalarPush);
    c.Disassemble();
  }
}

}  // namespace compiler
}  // namespace internal
}  // namespace v8
