// 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 "src/wasm/function-compiler.h"

#include "src/compiler/wasm-compiler.h"
#include "src/counters.h"
#include "src/macro-assembler-inl.h"
#include "src/wasm/baseline/liftoff-compiler.h"
#include "src/wasm/wasm-code-manager.h"

namespace v8 {
namespace internal {
namespace wasm {

namespace {
const char* GetCompilationModeAsString(
    WasmCompilationUnit::CompilationMode mode) {
  switch (mode) {
    case WasmCompilationUnit::CompilationMode::kLiftoff:
      return "liftoff";
    case WasmCompilationUnit::CompilationMode::kTurbofan:
      return "turbofan";
  }
  UNREACHABLE();
}
}  // namespace

// static
WasmCompilationUnit::CompilationMode
WasmCompilationUnit::GetDefaultCompilationMode() {
  return FLAG_liftoff ? CompilationMode::kLiftoff : CompilationMode::kTurbofan;
}

WasmCompilationUnit::WasmCompilationUnit(Isolate* isolate, ModuleEnv* env,
                                         wasm::NativeModule* native_module,
                                         wasm::FunctionBody body,
                                         wasm::WasmName name, int index,
                                         CompilationMode mode,
                                         Counters* counters, bool lower_simd)
    : isolate_(isolate),
      env_(env),
      func_body_(body),
      func_name_(name),
      counters_(counters ? counters : isolate->counters()),
      func_index_(index),
      native_module_(native_module),
      lower_simd_(lower_simd),
      mode_(mode) {
  DCHECK_GE(index, env->module->num_imported_functions);
  DCHECK_LT(index, env->module->functions.size());
  // Always disable Liftoff for asm.js, for two reasons:
  //    1) asm-specific opcodes are not implemented, and
  //    2) tier-up does not work with lazy compilation.
  if (env->module->origin == kAsmJsOrigin) mode = CompilationMode::kTurbofan;
  SwitchMode(mode);
}

// Declared here such that {LiftoffCompilationUnit} and
// {TurbofanWasmCompilationUnit} can be opaque in the header file.
WasmCompilationUnit::~WasmCompilationUnit() {}

void WasmCompilationUnit::ExecuteCompilation() {
  auto size_histogram = SELECT_WASM_COUNTER(counters_, env_->module->origin,
                                            wasm, function_size_bytes);
  size_histogram->AddSample(
      static_cast<int>(func_body_.end - func_body_.start));
  auto timed_histogram = SELECT_WASM_COUNTER(counters_, env_->module->origin,
                                             wasm_compile, function_time);
  TimedHistogramScope wasm_compile_function_time_scope(timed_histogram);

  if (FLAG_trace_wasm_compiler) {
    PrintF("Compiling wasm function %d with %s\n\n", func_index_,
           GetCompilationModeAsString(mode_));
  }

  switch (mode_) {
    case WasmCompilationUnit::CompilationMode::kLiftoff:
      if (liftoff_unit_->ExecuteCompilation()) break;
      // Otherwise, fall back to turbofan.
      SwitchMode(CompilationMode::kTurbofan);
      V8_FALLTHROUGH;
    case WasmCompilationUnit::CompilationMode::kTurbofan:
      turbofan_unit_->ExecuteCompilation();
      break;
  }
}

wasm::WasmCode* WasmCompilationUnit::FinishCompilation(
    wasm::ErrorThrower* thrower) {
  wasm::WasmCode* ret;
  switch (mode_) {
    case CompilationMode::kLiftoff:
      ret = liftoff_unit_->FinishCompilation(thrower);
      break;
    case CompilationMode::kTurbofan:
      ret = turbofan_unit_->FinishCompilation(thrower);
      break;
    default:
      UNREACHABLE();
  }
  if (ret == nullptr) {
    thrower->RuntimeError("Error finalizing code.");
  }
  return ret;
}

void WasmCompilationUnit::SwitchMode(CompilationMode new_mode) {
  // This method is being called in the constructor, where neither
  // {liftoff_unit_} nor {turbofan_unit_} are set, or to switch mode from
  // kLiftoff to kTurbofan, in which case {liftoff_unit_} is already set.
  mode_ = new_mode;
  switch (new_mode) {
    case CompilationMode::kLiftoff:
      DCHECK(!turbofan_unit_);
      DCHECK(!liftoff_unit_);
      liftoff_unit_.reset(new LiftoffCompilationUnit(this));
      return;
    case CompilationMode::kTurbofan:
      DCHECK(!turbofan_unit_);
      liftoff_unit_.reset();
      turbofan_unit_.reset(new compiler::TurbofanWasmCompilationUnit(this));
      return;
  }
  UNREACHABLE();
}

// static
wasm::WasmCode* WasmCompilationUnit::CompileWasmFunction(
    wasm::NativeModule* native_module, wasm::ErrorThrower* thrower,
    Isolate* isolate, ModuleEnv* env, const wasm::WasmFunction* function,
    CompilationMode mode) {
  ModuleWireBytes wire_bytes(native_module->wire_bytes());
  wasm::FunctionBody function_body{
      function->sig, function->code.offset(),
      wire_bytes.start() + function->code.offset(),
      wire_bytes.start() + function->code.end_offset()};

  WasmCompilationUnit unit(isolate, env, native_module, function_body,
                           wire_bytes.GetNameOrNull(function, env->module),
                           function->func_index, mode);
  unit.ExecuteCompilation();
  return unit.FinishCompilation(thrower);
}

}  // namespace wasm
}  // namespace internal
}  // namespace v8
