// 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/frontend/bytecode_scope_builder.h"

#include "vm/compiler/frontend/bytecode_reader.h"

#if !defined(DART_PRECOMPILED_RUNTIME)

namespace dart {
namespace kernel {

#define Z (zone_)

BytecodeScopeBuilder::BytecodeScopeBuilder(ParsedFunction* parsed_function)
    : parsed_function_(parsed_function),
      zone_(parsed_function->zone()),
      scope_(nullptr) {}

void BytecodeScopeBuilder::BuildScopes() {
  if (parsed_function_->scope() != nullptr) {
    return;  // Scopes are already built.
  }

  const Function& function = parsed_function_->function();

  LocalScope* enclosing_scope = nullptr;
  if (function.IsImplicitClosureFunction() && !function.is_static()) {
    // Create artificial enclosing scope for the tear-off that contains
    // captured receiver value. This ensure that AssertAssignable will correctly
    // load instantiator type arguments if they are needed.
    LocalVariable* receiver_variable =
        MakeReceiverVariable(/* is_parameter = */ false);
    receiver_variable->set_is_captured();
    enclosing_scope = new (Z) LocalScope(NULL, 0, 0);
    enclosing_scope->set_context_level(0);
    enclosing_scope->AddVariable(receiver_variable);
    enclosing_scope->AddContextVariable(receiver_variable);
  }
  scope_ = new (Z) LocalScope(enclosing_scope, 0, 0);
  scope_->set_begin_token_pos(function.token_pos());
  scope_->set_end_token_pos(function.end_token_pos());

  // Add function type arguments variable before current context variable.
  if ((function.IsGeneric() || function.HasGenericParent())) {
    LocalVariable* type_args_var = MakeVariable(
        Symbols::FunctionTypeArgumentsVar(), AbstractType::dynamic_type());
    scope_->AddVariable(type_args_var);
    parsed_function_->set_function_type_arguments(type_args_var);
  }

  bool needs_expr_temp = false;
  if (parsed_function_->has_arg_desc_var()) {
    needs_expr_temp = true;
    scope_->AddVariable(parsed_function_->arg_desc_var());
  }

  LocalVariable* context_var = parsed_function_->current_context_var();
  context_var->set_is_forced_stack();
  scope_->AddVariable(context_var);

  parsed_function_->set_scope(scope_);

  switch (function.kind()) {
    case RawFunction::kImplicitClosureFunction: {
      ASSERT(function.NumImplicitParameters() == 1);

      LocalVariable* closure_parameter = MakeVariable(
          Symbols::ClosureParameter(), AbstractType::dynamic_type());
      closure_parameter->set_is_forced_stack();
      scope_->InsertParameterAt(0, closure_parameter);

      // Type check all parameters by default.
      // This may be overridden with parameter flags in
      // BytecodeReaderHelper::ParseForwarderFunction.
      AddParameters(function, LocalVariable::kDoTypeCheck);
      break;
    }

    case RawFunction::kImplicitGetter:
    case RawFunction::kImplicitSetter: {
      const bool is_setter = function.IsImplicitSetterFunction();
      const bool is_method = !function.IsStaticFunction();
      intptr_t pos = 0;
      if (is_method) {
        MakeReceiverVariable(/* is_parameter = */ true);
        ++pos;
      }
      if (is_setter) {
        LocalVariable* setter_value = MakeVariable(
            Symbols::Value(),
            AbstractType::ZoneHandle(Z, function.ParameterTypeAt(pos)));
        scope_->InsertParameterAt(pos++, setter_value);

        if (is_method) {
          const Field& field = Field::Handle(Z, function.accessor_field());
          if (field.is_covariant()) {
            setter_value->set_is_explicit_covariant_parameter();
          } else if (!field.is_generic_covariant_impl()) {
            setter_value->set_type_check_mode(
                LocalVariable::kTypeCheckedByCaller);
          }
        }
      }
      break;
    }
    case RawFunction::kImplicitStaticGetter:
      ASSERT(!IsStaticFieldGetterGeneratedAsInitializer(function, Z));
      break;
    case RawFunction::kDynamicInvocationForwarder: {
      // Create [this] variable.
      MakeReceiverVariable(/* is_parameter = */ true);

      // Type check all parameters by default.
      // This may be overridden with parameter flags in
      // BytecodeReaderHelper::ParseForwarderFunction.
      AddParameters(function, LocalVariable::kDoTypeCheck);
      break;
    }
    case RawFunction::kMethodExtractor: {
      // Add a receiver parameter.  Though it is captured, we emit code to
      // explicitly copy it to a fixed offset in a freshly-allocated context
      // instead of using the generic code for regular functions.
      // Therefore, it isn't necessary to mark it as captured here.
      MakeReceiverVariable(/* is_parameter = */ true);
      break;
    }
    default:
      UNREACHABLE();
  }

  if (needs_expr_temp) {
    scope_->AddVariable(parsed_function_->EnsureExpressionTemp());
  }
  if (parsed_function_->function().MayHaveUncheckedEntryPoint(
          parsed_function_->isolate())) {
    scope_->AddVariable(parsed_function_->EnsureEntryPointsTemp());
  }
  parsed_function_->AllocateVariables();
}

// TODO(alexmarkov): pass bitvectors of parameter covariance to set type
// check mode before AllocateVariables.
void BytecodeScopeBuilder::AddParameters(const Function& function,
                                         LocalVariable::TypeCheckMode mode) {
  for (intptr_t i = function.NumImplicitParameters(),
                n = function.NumParameters();
       i < n; ++i) {
    // LocalVariable caches handles, so new handles are created for each
    // parameter.
    String& name = String::ZoneHandle(Z, function.ParameterNameAt(i));
    AbstractType& type =
        AbstractType::ZoneHandle(Z, function.ParameterTypeAt(i));

    LocalVariable* variable = MakeVariable(name, type);
    variable->set_type_check_mode(mode);
    scope_->InsertParameterAt(i, variable);
  }
}

LocalVariable* BytecodeScopeBuilder::MakeVariable(const String& name,
                                                  const AbstractType& type) {
  return new (Z) LocalVariable(TokenPosition::kNoSource,
                               TokenPosition::kNoSource, name, type, nullptr);
}

LocalVariable* BytecodeScopeBuilder::MakeReceiverVariable(bool is_parameter) {
  const auto& cls = Class::Handle(Z, parsed_function_->function().Owner());
  const auto& type = Type::ZoneHandle(Z, cls.DeclarationType());
  LocalVariable* receiver_variable = MakeVariable(Symbols::This(), type);
  parsed_function_->set_receiver_var(receiver_variable);
  if (is_parameter) {
    scope_->InsertParameterAt(0, receiver_variable);
  }
  return receiver_variable;
}

}  // namespace kernel
}  // namespace dart

#endif  // !defined(DART_PRECOMPILED_RUNTIME)
