// Copyright 2018 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 <cstddef>
#include <cstdint>

#include "src/codegen/machine-type.h"
#include "src/codegen/optimized-compilation-info.h"
#include "src/compiler/backend/instruction-selector.h"
#include "src/compiler/graph.h"
#include "src/compiler/linkage.h"
#include "src/compiler/node.h"
#include "src/compiler/operator.h"
#include "src/compiler/pipeline.h"
#include "src/compiler/raw-machine-assembler.h"
#include "src/compiler/wasm-compiler.h"
#include "src/execution/simulator.h"
#include "src/objects/objects-inl.h"
#include "src/objects/objects.h"
#include "src/wasm/wasm-engine.h"
#include "src/wasm/wasm-features.h"
#include "src/wasm/wasm-limits.h"
#include "src/wasm/wasm-objects-inl.h"
#include "src/wasm/wasm-objects.h"
#include "src/wasm/wasm-opcodes.h"
#include "src/zone/accounting-allocator.h"
#include "src/zone/zone.h"
#include "test/fuzzer/fuzzer-support.h"

namespace v8 {
namespace internal {
namespace compiler {
namespace fuzzer {

constexpr MachineType kTypes[] = {
    // The first entry is just a placeholder, because '0' is a separator.
    MachineType(),
#if !V8_TARGET_ARCH_32_BIT
    MachineType::Int64(),
#endif
    MachineType::Int32(), MachineType::Float32(), MachineType::Float64()};

static constexpr int kNumTypes = arraysize(kTypes);

class InputProvider {
 public:
  InputProvider(const uint8_t* data, size_t size)
      : current_(data), end_(data + size) {}

  size_t NumNonZeroBytes(size_t offset, int limit) {
    DCHECK_LE(limit, std::numeric_limits<uint8_t>::max());
    DCHECK_GE(current_ + offset, current_);
    const uint8_t* p;
    for (p = current_ + offset; p < end_; ++p) {
      if (*p % limit == 0) break;
    }
    return p - current_ - offset;
  }

  int NextInt8(int limit) {
    DCHECK_LE(limit, std::numeric_limits<uint8_t>::max());
    if (current_ == end_) return 0;
    uint8_t result = *current_;
    current_++;
    return static_cast<int>(result) % limit;
  }

  int NextInt32(int limit) {
    if (current_ + sizeof(uint32_t) > end_) return 0;
    int result =
        base::ReadLittleEndianValue<int>(reinterpret_cast<Address>(current_));
    current_ += sizeof(uint32_t);
    return result % limit;
  }

 private:
  const uint8_t* current_;
  const uint8_t* end_;
};

MachineType RandomType(InputProvider* input) {
  return kTypes[input->NextInt8(kNumTypes)];
}

int index(MachineType type) { return static_cast<int>(type.representation()); }

Node* Constant(RawMachineAssembler* m, MachineType type, int value) {
  switch (type.representation()) {
    case MachineRepresentation::kWord32:
      return m->Int32Constant(static_cast<int32_t>(value));
    case MachineRepresentation::kWord64:
      return m->Int64Constant(static_cast<int64_t>(value));
    case MachineRepresentation::kFloat32:
      return m->Float32Constant(static_cast<float>(value));
    case MachineRepresentation::kFloat64:
      return m->Float64Constant(static_cast<double>(value));
    default:
      UNREACHABLE();
  }
}

Node* ToInt32(RawMachineAssembler* m, MachineType type, Node* a) {
  switch (type.representation()) {
    case MachineRepresentation::kWord32:
      return a;
    case MachineRepresentation::kWord64:
      return m->TruncateInt64ToInt32(a);
    case MachineRepresentation::kFloat32:
      return m->TruncateFloat32ToInt32(a);
    case MachineRepresentation::kFloat64:
      return m->RoundFloat64ToInt32(a);
    default:
      UNREACHABLE();
  }
}

CallDescriptor* CreateRandomCallDescriptor(Zone* zone, size_t return_count,
                                           size_t param_count,
                                           InputProvider* input) {
  wasm::FunctionSig::Builder builder(zone, return_count, param_count);
  for (size_t i = 0; i < param_count; i++) {
    MachineType type = RandomType(input);
    builder.AddParam(wasm::ValueTypes::ValueTypeFor(type));
  }
  // Read the end byte of the parameters.
  input->NextInt8(1);

  for (size_t i = 0; i < return_count; i++) {
    MachineType type = RandomType(input);
    builder.AddReturn(wasm::ValueTypes::ValueTypeFor(type));
  }

  return compiler::GetWasmCallDescriptor(zone, builder.Build());
}

std::shared_ptr<wasm::NativeModule> AllocateNativeModule(i::Isolate* isolate,
                                                         size_t code_size) {
  std::shared_ptr<wasm::WasmModule> module(new wasm::WasmModule);
  module->num_declared_functions = 1;

  // We have to add the code object to a NativeModule, because the
  // WasmCallDescriptor assumes that code is on the native heap and not
  // within a code object.
  return isolate->wasm_engine()->NewNativeModule(
      isolate, i::wasm::kAllWasmFeatures, code_size, false, std::move(module));
}

extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
  v8_fuzzer::FuzzerSupport* support = v8_fuzzer::FuzzerSupport::Get();
  v8::Isolate* isolate = support->GetIsolate();
  i::Isolate* i_isolate = reinterpret_cast<Isolate*>(isolate);
  v8::Isolate::Scope isolate_scope(isolate);
  v8::HandleScope handle_scope(isolate);
  v8::Context::Scope context_scope(support->GetContext());
  v8::TryCatch try_catch(isolate);
  v8::internal::AccountingAllocator allocator;
  Zone zone(&allocator, ZONE_NAME);

  InputProvider input(data, size);
  // Create randomized descriptor.
  size_t param_count = input.NumNonZeroBytes(0, kNumTypes);
  if (param_count > Code::kMaxArguments) return 0;

  size_t return_count = input.NumNonZeroBytes(param_count + 1, kNumTypes);
  if (return_count > wasm::kV8MaxWasmFunctionMultiReturns) return 0;

  CallDescriptor* desc =
      CreateRandomCallDescriptor(&zone, return_count, param_count, &input);

  if (FLAG_wasm_fuzzer_gen_test) {
    // Print some debugging output which describes the produced signature.
    printf("[");
    for (size_t j = 0; j < param_count; ++j) {
      // Parameter 0 is the WasmContext.
      printf(" %s", MachineReprToString(
                        desc->GetParameterType(j + 1).representation()));
    }
    printf(" ] -> [");
    for (size_t j = 0; j < desc->ReturnCount(); ++j) {
      printf(" %s",
             MachineReprToString(desc->GetReturnType(j).representation()));
    }
    printf(" ]\n\n");
  }

  // Count parameters of each type.
  constexpr size_t kNumMachineRepresentations =
      static_cast<size_t>(MachineRepresentation::kLastRepresentation) + 1;

  // Trivial hash table for the number of occurrences of parameter types. The
  // MachineRepresentation of the parameter types is used as hash code.
  int counts[kNumMachineRepresentations] = {0};
  for (size_t i = 0; i < param_count; ++i) {
    // Parameter 0 is the WasmContext.
    ++counts[index(desc->GetParameterType(i + 1))];
  }

  // Generate random inputs.
  std::unique_ptr<int[]> inputs(new int[param_count]);
  std::unique_ptr<int[]> outputs(new int[desc->ReturnCount()]);
  for (size_t i = 0; i < param_count; ++i) {
    inputs[i] = input.NextInt32(10000);
  }

  RawMachineAssembler callee(
      i_isolate, new (&zone) Graph(&zone), desc,
      MachineType::PointerRepresentation(),
      InstructionSelector::SupportedMachineOperatorFlags());

  // Generate callee, returning random picks of its parameters.
  std::unique_ptr<Node* []> params(new Node*[desc->ParameterCount() + 2]);
  // The first input of a return is the number of stack slots that should be
  // popped before returning.
  std::unique_ptr<Node* []> returns(new Node*[desc->ReturnCount() + 1]);
  for (size_t i = 0; i < param_count; ++i) {
    // Parameter(0) is the WasmContext.
    params[i] = callee.Parameter(i + 1);
  }

  for (size_t i = 0; i < desc->ReturnCount(); ++i) {
    MachineType type = desc->GetReturnType(i);
    // Find a random same-type parameter to return. Use a constant if none.
    if (counts[index(type)] == 0) {
      returns[i] = Constant(&callee, type, 42);
      outputs[i] = 42;
    } else {
      int n = input.NextInt32(counts[index(type)]);
      int k = 0;
      while (desc->GetParameterType(k + 1) != desc->GetReturnType(i) ||
             --n > 0) {
        ++k;
      }
      returns[i] = params[k];
      outputs[i] = inputs[k];
    }
  }
  callee.Return(static_cast<int>(desc->ReturnCount()), returns.get());

  OptimizedCompilationInfo info(ArrayVector("testing"), &zone, Code::STUB);
  Handle<Code> code = Pipeline::GenerateCodeForTesting(
                          &info, i_isolate, desc, callee.graph(),
                          AssemblerOptions::Default(i_isolate), callee.Export())
                          .ToHandleChecked();

  std::shared_ptr<wasm::NativeModule> module =
      AllocateNativeModule(i_isolate, code->raw_instruction_size());
  wasm::WasmCodeRefScope wasm_code_ref_scope;
  byte* code_start = module->AddCodeForTesting(code)->instructions().begin();
  // Generate wrapper.
  int expect = 0;

  MachineSignature::Builder sig_builder(&zone, 1, 0);
  sig_builder.AddReturn(MachineType::Int32());

  CallDescriptor* wrapper_desc =
      Linkage::GetSimplifiedCDescriptor(&zone, sig_builder.Build());
  RawMachineAssembler caller(
      i_isolate, new (&zone) Graph(&zone), wrapper_desc,
      MachineType::PointerRepresentation(),
      InstructionSelector::SupportedMachineOperatorFlags());

  params[0] = caller.PointerConstant(code_start);
  // WasmContext dummy.
  params[1] = caller.PointerConstant(nullptr);
  for (size_t i = 0; i < param_count; ++i) {
    params[i + 2] = Constant(&caller, desc->GetParameterType(i + 1), inputs[i]);
  }
  Node* call = caller.AddNode(caller.common()->Call(desc),
                              static_cast<int>(param_count + 2), params.get());
  Node* ret = Constant(&caller, MachineType::Int32(), 0);
  for (size_t i = 0; i < desc->ReturnCount(); ++i) {
    // Skip roughly one third of the outputs.
    if (input.NextInt8(3) == 0) continue;
    Node* ret_i = (desc->ReturnCount() == 1)
                      ? call
                      : caller.AddNode(caller.common()->Projection(i), call);
    ret = caller.Int32Add(ret, ToInt32(&caller, desc->GetReturnType(i), ret_i));
    expect += outputs[i];
  }
  caller.Return(ret);

  // Call the wrapper.
  OptimizedCompilationInfo wrapper_info(ArrayVector("wrapper"), &zone,
                                        Code::STUB);
  Handle<Code> wrapper_code =
      Pipeline::GenerateCodeForTesting(
          &wrapper_info, i_isolate, wrapper_desc, caller.graph(),
          AssemblerOptions::Default(i_isolate), caller.Export())
          .ToHandleChecked();

  auto fn = GeneratedCode<int32_t>::FromCode(*wrapper_code);
  int result = fn.Call();

  CHECK_EQ(expect, result);
  return 0;
}

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