// Copyright (c) 2018, 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.

#include "vm/compiler/compiler_state.h"

#include <functional>

#include "vm/compiler/aot/precompiler.h"
#include "vm/compiler/backend/flow_graph_compiler.h"
#include "vm/compiler/backend/il_printer.h"
#include "vm/compiler/backend/slot.h"
#include "vm/growable_array.h"
#include "vm/scopes.h"

namespace dart {

template <typename T>
T* PutIfAbsent(Thread* thread,
               ZoneGrowableArray<T*>** array_slot,
               intptr_t index,
               std::function<T*()> create) {
  auto array = *array_slot;

  if (array == nullptr) {
    Zone* const Z = thread->zone();
    *array_slot = array = new (Z) ZoneGrowableArray<T*>(Z, index + 1);
  }

  while (array->length() <= index) {
    array->Add(nullptr);
  }

  if (array->At(index) == nullptr) {
    (*array)[index] = create();
  }
  return array->At(index);
}

LocalVariable* CompilerState::GetDummyCapturedVariable(intptr_t context_id,
                                                       intptr_t index) {
  return PutIfAbsent<LocalVariable>(
      thread(), &dummy_captured_vars_, index, [&]() {
        Zone* const Z = thread()->zone();
        const AbstractType& dynamic_type =
            AbstractType::ZoneHandle(Z, Type::DynamicType());
        const String& name = String::ZoneHandle(
            Z, Symbols::NewFormatted(thread(), ":context_var%" Pd, index));
        LocalVariable* var =
            new (Z) LocalVariable(TokenPosition::kNoSource,
                                  TokenPosition::kNoSource, name, dynamic_type);
        var->set_is_captured();
        var->set_index(VariableIndex(index));
        return var;
      });
}

const ZoneGrowableArray<const Slot*>& CompilerState::GetDummyContextSlots(
    intptr_t context_id,
    intptr_t num_context_variables) {
  return *PutIfAbsent<ZoneGrowableArray<const Slot*>>(
      thread(), &dummy_slots_, num_context_variables, [&]() {
        Zone* const Z = thread()->zone();

        auto slots =
            new (Z) ZoneGrowableArray<const Slot*>(num_context_variables);
        for (intptr_t i = 0; i < num_context_variables; i++) {
          LocalVariable* var = GetDummyCapturedVariable(context_id, i);
          slots->Add(&Slot::GetContextVariableSlotFor(thread(), *var));
        }

        return slots;
      });
}

CompilerTracing CompilerState::ShouldTrace(const Function& func) {
  return FlowGraphPrinter::ShouldPrint(func) ? CompilerTracing::kOn
                                             : CompilerTracing::kOff;
}

const Class& CompilerState::ComparableClass() {
  if (comparable_class_ == nullptr) {
    Thread* thread = Thread::Current();
    Zone* zone = thread->zone();

    // When obfuscation is enabled we need to obfuscate the name of the
    // class before looking it up.
    String& name = String::Handle(zone, Symbols::New(thread, "Comparable"));
    if (thread->isolate_group()->obfuscate()) {
      Obfuscator obfuscator(thread, Object::null_string());
      name = obfuscator.Rename(name);
    }

    const Library& lib = Library::Handle(zone, Library::CoreLibrary());
    const Class& cls = Class::ZoneHandle(zone, lib.LookupClass(name));
    ASSERT(!cls.IsNull());
    comparable_class_ = &cls;
  }
  return *comparable_class_;
}

const Function& CompilerState::StringBaseInterpolateSingle() {
  if (interpolate_single_ == nullptr) {
    Thread* thread = Thread::Current();
    Zone* zone = thread->zone();

    const Class& cls =
        Class::Handle(Library::LookupCoreClass(Symbols::StringBase()));
    ASSERT(!cls.IsNull());
    interpolate_single_ = &Function::ZoneHandle(
        zone, cls.LookupFunctionAllowPrivate(Symbols::InterpolateSingle()));
    ASSERT(!interpolate_single_->IsNull());
  }
  return *interpolate_single_;
}

const Function& CompilerState::StringBaseInterpolate() {
  if (interpolate_ == nullptr) {
    Thread* thread = Thread::Current();
    Zone* zone = thread->zone();

    const Class& cls =
        Class::Handle(Library::LookupCoreClass(Symbols::StringBase()));
    ASSERT(!cls.IsNull());
    interpolate_ = &Function::ZoneHandle(
        zone, cls.LookupFunctionAllowPrivate(Symbols::Interpolate()));
    ASSERT(!interpolate_->IsNull());
  }
  return *interpolate_;
}

const Class& CompilerState::TypedListClass() {
  if (typed_list_class_ == nullptr) {
    Thread* thread = Thread::Current();
    Zone* zone = thread->zone();

    const Library& lib = Library::Handle(zone, Library::TypedDataLibrary());
    const Class& cls = Class::ZoneHandle(
        zone, lib.LookupClassAllowPrivate(Symbols::_TypedList()));
    ASSERT(!cls.IsNull());
    const Error& error = Error::Handle(zone, cls.EnsureIsFinalized(thread));
    ASSERT(error.IsNull());
    typed_list_class_ = &cls;
  }
  return *typed_list_class_;
}

#define DEFINE_TYPED_LIST_NATIVE_FUNCTION_GETTER(Upper, Lower)                 \
  const Function& CompilerState::TypedListGet##Upper() {                       \
    if (typed_list_get_##Lower##_ == nullptr) {                                \
      Thread* thread = Thread::Current();                                      \
      Zone* zone = thread->zone();                                             \
      const auto& cls = CompilerState::TypedListClass();                       \
      typed_list_get_##Lower##_ = &Function::ZoneHandle(                       \
          zone, cls.LookupFunctionAllowPrivate(Symbols::_nativeGet##Upper())); \
      ASSERT(!typed_list_get_##Lower##_->IsNull());                            \
    }                                                                          \
    return *typed_list_get_##Lower##_;                                         \
  }                                                                            \
  const Function& CompilerState::TypedListSet##Upper() {                       \
    if (typed_list_set_##Lower##_ == nullptr) {                                \
      Thread* thread = Thread::Current();                                      \
      Zone* zone = thread->zone();                                             \
      const auto& cls = CompilerState::TypedListClass();                       \
      typed_list_set_##Lower##_ = &Function::ZoneHandle(                       \
          zone, cls.LookupFunctionAllowPrivate(Symbols::_nativeSet##Upper())); \
      ASSERT(!typed_list_set_##Lower##_->IsNull());                            \
    }                                                                          \
    return *typed_list_set_##Lower##_;                                         \
  }

DEFINE_TYPED_LIST_NATIVE_FUNCTION_GETTER(Float32, float32)
DEFINE_TYPED_LIST_NATIVE_FUNCTION_GETTER(Float64, float64)
DEFINE_TYPED_LIST_NATIVE_FUNCTION_GETTER(Float32x4, float32x4)
DEFINE_TYPED_LIST_NATIVE_FUNCTION_GETTER(Int32x4, int32x4)
DEFINE_TYPED_LIST_NATIVE_FUNCTION_GETTER(Float64x2, float64x2)

#undef DEFINE_TYPED_LIST_NATIVE_FUNCTION_GETTER

void CompilerState::ReportCrash() {
  OS::PrintErr("=== Crash occurred when compiling %s in %s mode in %s pass\n",
               function() != nullptr ? function()->ToFullyQualifiedCString()
                                     : "unknown function",
               is_aot()          ? "AOT"
               : is_optimizing() ? "optimizing JIT"
                                 : "unoptimized JIT",
               pass() != nullptr ? pass()->name() : "unknown");
  if (pass_state() != nullptr && pass()->id() == CompilerPass::kGenerateCode) {
    if (pass_state()->graph_compiler->current_block() != nullptr) {
      OS::PrintErr("=== When compiling block %s\n",
                   pass_state()->graph_compiler->current_block()->ToCString());
    }
    if (pass_state()->graph_compiler->current_instruction() != nullptr) {
      OS::PrintErr(
          "=== When compiling instruction %s\n",
          pass_state()->graph_compiler->current_instruction()->ToCString());
    }
  }
  if (pass_state() != nullptr && pass_state()->flow_graph() != nullptr) {
    pass_state()->flow_graph()->Print(pass()->name());
  } else {
    OS::PrintErr("=== Flow Graph not available\n");
  }
}

}  // namespace dart
