// Copyright (c) 2012, 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/parser.h"
#include "vm/flags.h"

#if !defined(DART_PRECOMPILED_RUNTIME)

#include "lib/invocation_mirror.h"
#include "platform/utils.h"
#include "vm/bit_vector.h"
#include "vm/bootstrap.h"
#include "vm/class_finalizer.h"
#include "vm/compiler/aot/precompiler.h"
#include "vm/compiler/backend/il_printer.h"
#include "vm/compiler/frontend/scope_builder.h"
#include "vm/compiler/jit/compiler.h"
#include "vm/dart_api_impl.h"
#include "vm/dart_entry.h"
#include "vm/growable_array.h"
#include "vm/handles.h"
#include "vm/hash_table.h"
#include "vm/isolate.h"
#include "vm/longjump.h"
#include "vm/native_arguments.h"
#include "vm/native_entry.h"
#include "vm/object.h"
#include "vm/object_store.h"
#include "vm/os.h"
#include "vm/regexp/regexp_assembler.h"
#include "vm/resolver.h"
#include "vm/scopes.h"
#include "vm/stack_frame.h"
#include "vm/symbols.h"
#include "vm/tags.h"
#include "vm/timeline.h"
#include "vm/zone.h"

namespace dart {

// Quick access to the current thread, isolate and zone.
#define T (thread())
#define I (isolate())
#define Z (zone())

ParsedFunction::ParsedFunction(Thread* thread, const Function& function)
    : thread_(thread),
      function_(function),
      code_(Code::Handle(zone(), function.unoptimized_code())),
      scope_(nullptr),
      regexp_compile_data_(nullptr),
      function_type_arguments_(nullptr),
      parent_type_arguments_(nullptr),
      current_context_var_(nullptr),
      arg_desc_var_(nullptr),
      expression_temp_var_(nullptr),
      entry_points_temp_var_(nullptr),
      finally_return_temp_var_(nullptr),
      dynamic_closure_call_vars_(nullptr),
      guarded_fields_(),
      default_parameter_values_(nullptr),
      raw_type_arguments_var_(nullptr),
      first_parameter_index_(),
      num_stack_locals_(0),
      have_seen_await_expr_(false),
      kernel_scopes_(nullptr) {
  DEBUG_ASSERT(function.IsNotTemporaryScopedHandle());
  // Every function has a local variable for the current context.
  LocalVariable* temp = new (zone())
      LocalVariable(function.token_pos(), function.token_pos(),
                    Symbols::CurrentContextVar(), Object::dynamic_type());
  current_context_var_ = temp;

  if (function.PrologueNeedsArgumentsDescriptor()) {
    arg_desc_var_ = new (zone())
        LocalVariable(TokenPosition::kNoSource, TokenPosition::kNoSource,
                      Symbols::ArgDescVar(), Object::dynamic_type());
  }

  // The code generated by the prologue builder for loading optional arguments
  // requires the expression temporary variable.
  if (function.HasOptionalParameters()) {
    EnsureExpressionTemp();
  }
}

void ParsedFunction::AddToGuardedFields(const Field* field) const {
  if ((field->guarded_cid() == kDynamicCid) ||
      (field->guarded_cid() == kIllegalCid)) {
    return;
  }

  const Field** other = guarded_fields_.Lookup(field);
  if (other != nullptr) {
    ASSERT(field->Original() == (*other)->Original());
    // Abort background compilation early if the guarded state of this field
    // has changed during compilation. We will not be able to commit
    // the resulting code anyway.
    if (Compiler::IsBackgroundCompilation()) {
      if (!(*other)->IsConsistentWith(*field)) {
        Compiler::AbortBackgroundCompilation(
            DeoptId::kNone, "Field's guarded state changed during compilation");
      }
    }
    return;
  }

  // Note: the list of guarded fields must contain copies during optimizing
  // compilation because we will look at their guarded_cid when copying
  // the array of guarded fields from callee into the caller during
  // inlining.
  ASSERT(field->IsOriginal() ==
         !CompilerState::Current().should_clone_fields());
  guarded_fields_.Insert(&Field::ZoneHandle(Z, field->ptr()));
}

void ParsedFunction::Bailout(const char* origin, const char* reason) const {
  Report::MessageF(Report::kBailout, Script::Handle(function_.script()),
                   function_.token_pos(), Report::AtLocation,
                   "%s Bailout in %s: %s", origin,
                   String::Handle(function_.name()).ToCString(), reason);
  UNREACHABLE();
}

kernel::ScopeBuildingResult* ParsedFunction::EnsureKernelScopes() {
  if (kernel_scopes_ == nullptr) {
    kernel::ScopeBuilder builder(this);
    kernel_scopes_ = builder.BuildScopes();
  }
  return kernel_scopes_;
}

LocalVariable* ParsedFunction::EnsureExpressionTemp() {
  if (!has_expression_temp_var()) {
    LocalVariable* temp =
        new (Z) LocalVariable(function_.token_pos(), function_.token_pos(),
                              Symbols::ExprTemp(), Object::dynamic_type());
    ASSERT(temp != nullptr);
    set_expression_temp_var(temp);
  }
  ASSERT(has_expression_temp_var());
  return expression_temp_var();
}

LocalVariable* ParsedFunction::EnsureEntryPointsTemp() {
  if (!has_entry_points_temp_var()) {
    LocalVariable* temp = new (Z)
        LocalVariable(function_.token_pos(), function_.token_pos(),
                      Symbols::EntryPointsTemp(), Object::dynamic_type());
    ASSERT(temp != nullptr);
    set_entry_points_temp_var(temp);
  }
  ASSERT(has_entry_points_temp_var());
  return entry_points_temp_var();
}

void ParsedFunction::EnsureFinallyReturnTemp(bool is_async) {
  if (!has_finally_return_temp_var()) {
    LocalVariable* temp =
        new (Z) LocalVariable(function_.token_pos(), function_.token_pos(),
                              Symbols::FinallyRetVal(), Object::dynamic_type());
    ASSERT(temp != nullptr);
    temp->set_is_final();
    if (is_async) {
      temp->set_is_captured();
    }
    set_finally_return_temp_var(temp);
  }
  ASSERT(has_finally_return_temp_var());
}

void ParsedFunction::SetRegExpCompileData(
    RegExpCompileData* regexp_compile_data) {
  ASSERT(regexp_compile_data_ == nullptr);
  ASSERT(regexp_compile_data != nullptr);
  regexp_compile_data_ = regexp_compile_data;
}

void ParsedFunction::AllocateVariables() {
  ASSERT(!function().IsIrregexpFunction());
  LocalScope* scope = this->scope();
  const intptr_t num_fixed_params = function().num_fixed_parameters();
  const intptr_t num_opt_params = function().NumOptionalParameters();
  const intptr_t num_params = num_fixed_params + num_opt_params;
  const bool copy_parameters = function().MakesCopyOfParameters();

  // Before we start allocating indices to variables, we'll setup the
  // parameters array, which can be used to access the raw parameters (i.e. not
  // the potentially variables which are in the context)

  raw_parameters_ = new (Z) ZoneGrowableArray<LocalVariable*>(Z, num_params);
  for (intptr_t param = 0; param < num_params; ++param) {
    LocalVariable* variable = ParameterVariable(param);
    LocalVariable* raw_parameter = variable;
    if (variable->is_captured()) {
      String& tmp = String::ZoneHandle(Z);
      tmp = Symbols::FromConcat(T, Symbols::OriginalParam(), variable->name());

      RELEASE_ASSERT(scope->LocalLookupVariable(
                         tmp, LocalVariable::kNoKernelOffset) == nullptr);
      raw_parameter = new LocalVariable(
          variable->declaration_token_pos(), variable->token_pos(), tmp,
          variable->static_type(), LocalVariable::kNoKernelOffset,
          variable->inferred_type(), variable->inferred_arg_type(),
          variable->inferred_arg_value());
      raw_parameter->set_annotations_offset(variable->annotations_offset());
      if (variable->is_explicit_covariant_parameter()) {
        raw_parameter->set_is_explicit_covariant_parameter();
      }
      if (variable->needs_covariant_check_in_method()) {
        raw_parameter->set_needs_covariant_check_in_method();
      }
      raw_parameter->set_type_check_mode(variable->type_check_mode());
      if (copy_parameters) {
        bool ok = scope->AddVariable(raw_parameter);
        ASSERT(ok);
      } else {
        raw_parameter->set_index(
            VariableIndex(function().NumParameters() - param));
      }
    }
    raw_parameters_->Add(raw_parameter);
  }
  if (function_type_arguments_ != nullptr) {
    LocalVariable* raw_type_args_parameter = function_type_arguments_;
    if (function_type_arguments_->is_captured()) {
      String& tmp = String::ZoneHandle(Z);
      tmp = Symbols::FromConcat(T, Symbols::OriginalParam(),
                                function_type_arguments_->name());

      ASSERT(scope->LocalLookupVariable(tmp, LocalVariable::kNoKernelOffset) ==
             nullptr);
      raw_type_args_parameter =
          new LocalVariable(function_type_arguments_->declaration_token_pos(),
                            function_type_arguments_->token_pos(), tmp,
                            function_type_arguments_->static_type(),
                            LocalVariable::kNoKernelOffset);
      bool ok = scope->AddVariable(raw_type_args_parameter);
      ASSERT(ok);
    }
    raw_type_arguments_var_ = raw_type_args_parameter;
  }

  // The copy parameters implementation will still write to local variables
  // which we assign indices as with the old CopyParams implementation.
  VariableIndex first_local_index;
  {
    // Compute start indices to parameters and locals, and the number of
    // parameters to copy.
    if (!copy_parameters) {
      ASSERT(suspend_state_var() == nullptr);
      first_parameter_index_ = VariableIndex(num_params);
      first_local_index = VariableIndex(0);
    } else {
      // :suspend_state variable is inserted at the fixed slot
      // before the copied parameters.
      const intptr_t reserved_var_slot_count =
          (suspend_state_var() != nullptr) ? 1 : 0;
      first_parameter_index_ = VariableIndex(-reserved_var_slot_count);
      first_local_index =
          VariableIndex(first_parameter_index_.value() - num_params);
    }
  }

  // Allocate parameters and local variables, either in the local frame or
  // in the context(s).
  bool found_captured_variables = false;
  VariableIndex next_free_index = scope->AllocateVariables(
      function(), first_parameter_index_, num_params, first_local_index,
      nullptr, &found_captured_variables);

  num_stack_locals_ = -next_free_index.value();
}

void ParsedFunction::AllocateIrregexpVariables(intptr_t num_stack_locals) {
  ASSERT(function().IsIrregexpFunction());
  ASSERT(function().NumOptionalParameters() == 0);
  const intptr_t num_params = function().num_fixed_parameters();
  ASSERT(num_params == RegExpMacroAssembler::kParamCount);
  // Compute start indices to parameters and locals, and the number of
  // parameters to copy.
  first_parameter_index_ = VariableIndex(num_params);

  // Frame indices are relative to the frame pointer and are decreasing.
  num_stack_locals_ = num_stack_locals;
}

void ParsedFunction::SetCovariantParameters(
    const BitVector* covariant_parameters) {
  ASSERT(covariant_parameters_ == nullptr);
  ASSERT(covariant_parameters->length() == function_.NumParameters());
  covariant_parameters_ = covariant_parameters;
}

void ParsedFunction::SetGenericCovariantImplParameters(
    const BitVector* generic_covariant_impl_parameters) {
  ASSERT(generic_covariant_impl_parameters_ == nullptr);
  ASSERT(generic_covariant_impl_parameters->length() ==
         function_.NumParameters());
  generic_covariant_impl_parameters_ = generic_covariant_impl_parameters;
}

bool ParsedFunction::IsCovariantParameter(intptr_t i) const {
  ASSERT(covariant_parameters_ != nullptr);
  ASSERT((i >= 0) && (i < function_.NumParameters()));
  return covariant_parameters_->Contains(i);
}

bool ParsedFunction::IsGenericCovariantImplParameter(intptr_t i) const {
  ASSERT(generic_covariant_impl_parameters_ != nullptr);
  ASSERT((i >= 0) && (i < function_.NumParameters()));
  return generic_covariant_impl_parameters_->Contains(i);
}

ParsedFunction::DynamicClosureCallVars*
ParsedFunction::EnsureDynamicClosureCallVars() {
  ASSERT(function().IsDynamicClosureCallDispatcher());
  if (dynamic_closure_call_vars_ != nullptr) return dynamic_closure_call_vars_;
  const auto& saved_args_desc =
      Array::Handle(zone(), function().saved_args_desc());
  const ArgumentsDescriptor descriptor(saved_args_desc);

  dynamic_closure_call_vars_ =
      new (zone()) DynamicClosureCallVars(zone(), descriptor.NamedCount());

  auto const pos = function().token_pos();
  const auto& type_Dynamic = Object::dynamic_type();
  const auto& type_Function =
      Type::ZoneHandle(zone(), Type::DartFunctionType());
  const auto& type_Smi = Type::ZoneHandle(zone(), Type::SmiType());
#define INIT_FIELD(Name, TypeName, Symbol)                                     \
  dynamic_closure_call_vars_->Name = new (zone()) LocalVariable(               \
      pos, pos, Symbols::DynamicCall##Symbol##Var(), type_##TypeName);
  FOR_EACH_DYNAMIC_CLOSURE_CALL_VARIABLE(INIT_FIELD);
#undef INIT_FIELD

  for (intptr_t i = 0; i < descriptor.NamedCount(); i++) {
    auto const name = OS::SCreate(
        zone(), ":dyn_call_named_argument_%" Pd "_parameter_index", i);
    auto const var = new (zone()) LocalVariable(
        pos, pos, String::ZoneHandle(zone(), Symbols::New(thread(), name)),
        type_Smi);
    dynamic_closure_call_vars_->named_argument_parameter_indices.Add(var);
  }

  return dynamic_closure_call_vars_;
}

}  // namespace dart

#endif  // !defined(DART_PRECOMPILED_RUNTIME)
