// Copyright 2017 The Fuchsia 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 <algorithm>
#include <ctime>

#include "generator.h"
#include "header_generator.h"
#include "vdso_wrapper_generator.h"

#include "abigen_generator.h"

using std::map;
using std::string;
using std::vector;

const map<string, string> user_attrs = {
    {"noreturn", "__NO_RETURN"},
    {"const", "__CONST"},
    {"deprecated", "__DEPRECATE"},

    // All vDSO calls are "leaf" in the sense of the GCC attribute.
    // It just means they can't ever call back into their callers'
    // own translation unit.  No vDSO calls make callbacks at all.
    {"*", "__LEAF_FN"},
};

const map<string, string> kernel_attrs = {
    {"noreturn", "__NO_RETURN"},
};

static TestWrapper test_wrapper;
static BlockingRetryWrapper blocking_wrapper;
static vector<CallWrapper*> wrappers = {&test_wrapper, &blocking_wrapper};

static VdsoWrapperGenerator vdso_wrapper_generator(
    "_zx_",        // wrapper function name
    "SYSCALL_zx_", // syscall implementation name
    wrappers);

static KernelBranchGenerator kernel_branch;

static KernelWrapperGenerator kernel_wrappers(
    "sys_",     // function prefix
    "wrapper_", // wrapper prefix
    "ZX_SYS_"); // syscall numbers constant prefix

static bool skip_nothing(const Syscall&) {
    return false;
}

static bool skip_internal(const Syscall& sc) {
    return sc.is_internal();
}

static bool skip_vdso(const Syscall& sc) {
    return sc.is_vdso();
}

static HeaderGenerator user_header(
    "extern ", // function prefix
    {
        {"zx_", skip_internal},
        {"_zx_", skip_internal},
    },
    "void", // no-args special type
    false,  // wrap pointers
    user_attrs);

static HeaderGenerator vdso_header(
    "__LOCAL extern ", // function prefix
    {
        {"VDSO_zx_", skip_nothing},
        {"SYSCALL_zx_", skip_vdso},
    },
    "void", // no-args special type
    false,
    user_attrs);

static HeaderGenerator kernel_header(
    "",
    {
        {"sys_", skip_vdso},
    },
    "",
    true,
    kernel_attrs);

static VDsoAsmGenerator vdso_asm_generator(
    "m_syscall", // syscall macro name
    "zx_",       // syscall name prefix
    wrappers);

static SyscallNumbersGenerator syscall_num_generator("#define ZX_SYS_");

static RustBindingGenerator rust_binding_generator;
static TraceInfoGenerator trace_generator;
static CategoryGenerator category_generator;
static JsonGenerator json_generator;

const map<string, Generator&> type_to_generator = {
    // The user header, pure C.
    {"user-header", user_header},

    // The vDSO-internal header, pure C.  (VDsoHeaderC)
    {"vdso-header", vdso_header},

    // The kernel header, C++.
    {"kernel-header", kernel_header},

    // The kernel assembly branches and jump table.
    {"kernel-branch", kernel_branch},

    // The kernel C++ wrappers.
    {"kernel-wrappers", kernel_wrappers},

    //  The assembly file for x86-64.
    {"x86-asm", vdso_asm_generator},

    //  The assembly include file for ARM64.
    {"arm-asm", vdso_asm_generator},

    // A C header defining ZX_SYS_* syscall number macros.
    {"numbers", syscall_num_generator},

    // The trace subsystem data, to be interpreted as an array of structs.
    {"trace", trace_generator},

    // Rust bindings.
    {"rust", rust_binding_generator},

    // vDSO wrappers for additional behaviour in user space.
    {"vdso-wrappers", vdso_wrapper_generator},

    // Category list.
    {"category", category_generator},

    // JSON list of syscalls.
    {"json", json_generator},
};

const map<string, string> type_to_default_suffix = {
    {"user-header", ".user.h"},
    {"vdso-header", ".vdso.h"},
    {"kernel-header", ".kernel.h"},
    {"kernel-branch", ".kernel-branch.S"},
    {"kernel-wrappers", ".kernel-wrappers.inc"},
    {"x86-asm", ".x86-64.S"},
    {"arm-asm", ".arm64.S"},
    {"numbers", ".syscall-numbers.h"},
    {"trace", ".trace.inc"},
    {"rust", ".rs"},
    {"vdso-wrappers", ".vdso-wrappers.inc"},
    {"category", ".category.inc"},
    {"json", ".json"},
};

const map<string, string>& get_type_to_default_suffix() {
    return type_to_default_suffix;
}

const map<string, Generator&>& get_type_to_generator() {
    return type_to_generator;
}

bool AbigenGenerator::AddSyscall(Syscall&& syscall) {
    if (!syscall.validate())
        return false;

    syscall.requirements = pending_requirements_;
    pending_requirements_.clear();

    syscall.top_description = pending_top_description_;
    pending_top_description_ = TopDescription();

    syscall.assign_index(&next_index_);
    calls_.emplace_back(std::move(syscall));
    return true;
}

bool AbigenGenerator::Generate(const map<string, string>& type_to_filename) {
    for (auto& entry : type_to_filename) {
        if (!generate_one(entry.second, type_to_generator.at(entry.first), entry.first))
            return false;
    }
    return true;
}

bool AbigenGenerator::verbose() const {
    return verbose_;
}

void AbigenGenerator::AppendRequirement(Requirement&& req) {
    pending_requirements_.emplace_back(req);
}

void AbigenGenerator::SetTopDescription(TopDescription&& td) {
    pending_top_description_ = std::move(td);
}

bool AbigenGenerator::generate_one(
    const string& output_file, Generator& generator, const string& type) {
    std::ofstream ofile;
    ofile.open(output_file.c_str(), std::ofstream::out);

    if (!generator.header(ofile)) {
        print_error("i/o error", output_file);
        return false;
    }

    if (!std::all_of(calls_.begin(), calls_.end(),
                     [&generator, &ofile](const Syscall& sc) {
                         return generator.syscall(ofile, sc);
                     })) {
        print_error("generation failed", output_file);
        return false;
    }

    if (!generator.footer(ofile)) {
        print_error("i/o error", output_file);
        return false;
    }

    return true;
}

void AbigenGenerator::print_error(const char* what, const string& file) {
    fprintf(stderr, "error: %s for %s\n", what, file.c_str());
}
