blob: 430a86901b0234b94879fb0955ab8bd915164c9e [file] [log] [blame]
// 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.
#import "generator.h"
using std::ofstream;
using std::string;
using std::vector;
static const string in = " ";
static const string inin = in + in;
static string invocation(ofstream& os, const string& out_type,
const string& syscall_name, const Syscall& sc) {
if (sc.is_noreturn()) {
// no return - no need to set anything. the compiler
// should know that we're never going anywhere from here
os << syscall_name << "(";
return ")";
}
os << "return static_cast<" << out_type << ">(" << syscall_name << "(";
return "))";
}
static void write_x86_syscall_signature_line(ofstream& os, const Syscall& sc, string name_prefix) {
auto syscall_name = name_prefix + sc.name;
os << "x86_64_syscall_result " << syscall_name << "(";
// Writes all arguments.
sc.for_each_kernel_arg([&](const TypeSpec& arg) {
os << arg.as_cpp_declaration(false) << ", ";
});
os << "uint64_t ip) {\n";
}
bool KernelWrapperGenerator::header(ofstream& os) {
if (!Generator::header(os))
return false;
os << "extern \"C\" {\n";
return os.good();
}
bool KernelWrapperGenerator::syscall(ofstream& os, const Syscall& sc) {
// TODO(andymutton): Generate arm wrappers too.
if (sc.is_vdso())
return true;
auto syscall_name = syscall_prefix_ + sc.name;
os << "#if ARCH_X86_64\n";
write_x86_syscall_signature_line(os, sc, wrapper_prefix_);
os << in << "return do_syscall("
<< define_prefix_ << sc.name << ", "
<< "ip, "
<< "&VDso::ValidSyscallPC::" << sc.name << ", "
<< "[&]() {\n"
<< inin;
string close_invocation = invocation(os, "uint64_t", syscall_name, sc);
// Writes all arguments.
sc.for_each_kernel_arg([&](const TypeSpec& arg) {
if (arg.arr_spec) {
os << "make_user_ptr(" << arg.name << "), ";
} else {
os << arg.name << ", ";
}
});
if (sc.num_kernel_args() > 0) {
// remove the comma space.
os.seekp(-2, std::ios_base::end);
}
os << close_invocation;
if (sc.is_noreturn()) {
os << "; // __noreturn__\n";
os << inin << "/* NOTREACHED */\n";
os << inin << "return ZX_ERR_BAD_STATE;\n";
} else {
os << ";\n";
}
os << in << "});\n";
os << "}\n";
os << "#endif\n";
return os.good();
}
bool KernelWrapperGenerator::footer(ofstream& os) {
os << "}\n";
return os.good();
}