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

#include "include/dart_api.h"

#include "vm/bootstrap_natives.h"
#include "vm/dart_api_impl.h"
#include "vm/object.h"
#include "vm/object_store.h"
#include "vm/service_isolate.h"

namespace dart {

// Helper macros for declaring and defining native entries.
#define REGISTER_NATIVE_ENTRY(name, count)                                     \
  {"" #name, reinterpret_cast<void*>(BootstrapNatives::DN_##name), count},

// List all native functions implemented in the vm or core bootstrap dart
// libraries so that we can resolve the native function to it's entry
// point.
static const struct NativeEntries {
  const char* const name_;
  void* const function_;
  const int argument_count_;
} BootStrapEntries[] = {BOOTSTRAP_NATIVE_LIST(REGISTER_NATIVE_ENTRY)
#if !defined(DART_PRECOMPILED_RUNTIME)
                            MIRRORS_BOOTSTRAP_NATIVE_LIST(REGISTER_NATIVE_ENTRY)
#endif  // !DART_PRECOMPILED_RUNTIME
};

#define REGISTER_FFI_NATIVE_ENTRY(name, return_type, argument_types)           \
  {"" #name, reinterpret_cast<void*>(BootstrapNatives::FN_##name)},

static const struct FfiNativeEntries {
  const char* const name_;
  void* const function_;
} BootStrapFfiEntries[] = {
    BOOTSTRAP_FFI_NATIVE_LIST(REGISTER_FFI_NATIVE_ENTRY)};

Dart_NativeFunction BootstrapNatives::Lookup(Dart_Handle name,
                                             int argument_count,
                                             bool* auto_setup_scope) {
  Thread* thread = Thread::Current();
  TransitionNativeToVM transition(thread);
  const Object& obj = Object::Handle(thread->zone(), Api::UnwrapHandle(name));
  if (!obj.IsString()) {
    return nullptr;
  }
  ASSERT(auto_setup_scope);
  *auto_setup_scope = false;
  const char* function_name = obj.ToCString();
  ASSERT(function_name != nullptr);
  int num_entries = sizeof(BootStrapEntries) / sizeof(struct NativeEntries);
  for (int i = 0; i < num_entries; i++) {
    const struct NativeEntries* entry = &(BootStrapEntries[i]);
    if ((strcmp(function_name, entry->name_) == 0) &&
        (entry->argument_count_ == argument_count)) {
      return reinterpret_cast<Dart_NativeFunction>(entry->function_);
    }
  }
  return nullptr;
}

void* BootstrapNatives::LookupFfiNative(const char* name,
                                        uintptr_t argument_count) {
  int num_entries =
      sizeof(BootStrapFfiEntries) / sizeof(struct FfiNativeEntries);
  for (int i = 0; i < num_entries; i++) {
    const struct FfiNativeEntries* entry = &(BootStrapFfiEntries[i]);
    if (strcmp(name, entry->name_) == 0) {
      return entry->function_;
    }
  }
  return nullptr;
}

const uint8_t* BootstrapNatives::Symbol(Dart_NativeFunction nf) {
  int num_entries = sizeof(BootStrapEntries) / sizeof(struct NativeEntries);
  for (int i = 0; i < num_entries; i++) {
    const struct NativeEntries* entry = &(BootStrapEntries[i]);
    if (reinterpret_cast<Dart_NativeFunction>(entry->function_) == nf) {
      return reinterpret_cast<const uint8_t*>(entry->name_);
    }
  }
  return nullptr;
}

void Bootstrap::SetupNativeResolver() {
  Library& library = Library::Handle();

  Dart_NativeEntryResolver resolver = BootstrapNatives::Lookup;

  Dart_FfiNativeResolver ffi_native_resolver =
      BootstrapNatives::LookupFfiNative;

  Dart_NativeEntrySymbol symbol_resolver = BootstrapNatives::Symbol;

  library = Library::AsyncLibrary();
  ASSERT(!library.IsNull());
  library.set_native_entry_resolver(resolver);
  library.set_native_entry_symbol_resolver(symbol_resolver);

  library = Library::CollectionLibrary();
  ASSERT(!library.IsNull());
  library.set_native_entry_resolver(resolver);
  library.set_native_entry_symbol_resolver(symbol_resolver);

  library = Library::ConvertLibrary();
  ASSERT(!library.IsNull());
  library.set_native_entry_resolver(resolver);
  library.set_native_entry_symbol_resolver(symbol_resolver);

  library = Library::ConcurrentLibrary();
  ASSERT(!library.IsNull());
  library.set_native_entry_resolver(resolver);
  library.set_native_entry_symbol_resolver(symbol_resolver);
  library.set_ffi_native_resolver(ffi_native_resolver);

  library = Library::CoreLibrary();
  ASSERT(!library.IsNull());
  library.set_native_entry_resolver(resolver);
  library.set_native_entry_symbol_resolver(symbol_resolver);

  library = Library::DeveloperLibrary();
  ASSERT(!library.IsNull());
  library.set_native_entry_resolver(resolver);
  library.set_native_entry_symbol_resolver(symbol_resolver);

  library = Library::FfiLibrary();
  ASSERT(!library.IsNull());
  library.set_native_entry_resolver(resolver);
  library.set_native_entry_symbol_resolver(symbol_resolver);
  library.set_ffi_native_resolver(ffi_native_resolver);

  library = Library::InternalLibrary();
  ASSERT(!library.IsNull());
  library.set_native_entry_resolver(resolver);
  library.set_native_entry_symbol_resolver(symbol_resolver);
  library.set_ffi_native_resolver(ffi_native_resolver);

  library = Library::IsolateLibrary();
  ASSERT(!library.IsNull());
  library.set_native_entry_resolver(resolver);
  library.set_native_entry_symbol_resolver(symbol_resolver);

  library = Library::MathLibrary();
  ASSERT(!library.IsNull());
  library.set_native_entry_resolver(resolver);
  library.set_native_entry_symbol_resolver(symbol_resolver);

#if !defined(DART_PRECOMPILED_RUNTIME)
  library = Library::MirrorsLibrary();
  ASSERT(!library.IsNull());
  library.set_native_entry_resolver(resolver);
  library.set_native_entry_symbol_resolver(symbol_resolver);
#endif

  library = Library::TypedDataLibrary();
  ASSERT(!library.IsNull());
  library.set_native_entry_resolver(resolver);
  library.set_native_entry_symbol_resolver(symbol_resolver);

  library = Library::VMServiceLibrary();
  ASSERT(!library.IsNull());
  library.set_native_entry_resolver(resolver);
  library.set_native_entry_symbol_resolver(symbol_resolver);
}

bool Bootstrap::IsBootstrapResolver(Dart_NativeEntryResolver resolver) {
  return resolver == BootstrapNatives::Lookup;
}

}  // namespace dart
