Skip to content

Commit

Permalink
add support for runtime-light in compiler (#1026)
Browse files Browse the repository at this point in the history
  • Loading branch information
astrophysik authored Jun 26, 2024
1 parent 7496cee commit 63e7833
Show file tree
Hide file tree
Showing 17 changed files with 204 additions and 33 deletions.
1 change: 1 addition & 0 deletions compiler/code-gen/code-generator.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ struct CGContext {
std::vector<int> catch_label_used;
FunctionPtr parent_func;
bool resumable_flag{false};
bool interruptible_flag{false};
bool namespace_opened{false};
int inside_macro{0};
size_t inside_null_coalesce_fallback{0};
Expand Down
6 changes: 5 additions & 1 deletion compiler/code-gen/declarations.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,11 @@ void FunctionDeclaration::compile(CodeGenerator &W) const {
switch (style) {
case gen_out_style::tagger:
case gen_out_style::cpp: {
FunctionSignatureGenerator(W) << ret_type_gen << " " << FunctionName(function) << "(" << params_gen << ")";
if (function->is_interruptible) {
FunctionSignatureGenerator(W) << "task_t<" << ret_type_gen << ">" << " " << FunctionName(function) << "(" << params_gen << ")";
} else {
FunctionSignatureGenerator(W) << ret_type_gen << " " << FunctionName(function) << "(" << params_gen << ")";
}
break;
}
case gen_out_style::txt: {
Expand Down
96 changes: 73 additions & 23 deletions compiler/code-gen/files/init-scripts.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,25 +40,30 @@ void StaticInit::compile(CodeGenerator &W) const {
W << "extern array<tl_storer_ptr> gen$tl_storers_ht;" << NL;
FunctionSignatureGenerator(W) << "void fill_tl_storers_ht()" << SemicolonAndNL() << NL;
}
FunctionSignatureGenerator(W) << ("const char *get_php_scripts_version()") << BEGIN << "return " << RawString(G->settings().php_code_version.get()) << ";"
<< NL << END << NL << NL;
if (!G->is_output_mode_k2_component()) {
FunctionSignatureGenerator(W) << ("const char *get_php_scripts_version()") << BEGIN << "return " << RawString(G->settings().php_code_version.get()) << ";"
<< NL << END << NL << NL;
}

FunctionSignatureGenerator(W) << ("char **get_runtime_options([[maybe_unused]] int *count)") << BEGIN;
const auto &runtime_opts = G->get_kphp_runtime_opts();
if (runtime_opts.empty()) {
W << "return nullptr;" << NL;
} else {
W << "*count = " << runtime_opts.size() << ";" << NL;
for (size_t i = 0; i != runtime_opts.size(); ++i) {
W << "static char arg" << i << "[] = " << RawString{runtime_opts[i]} << ";" << NL;
}
W << "static char *argv[] = " << BEGIN;
for (size_t i = 0; i != runtime_opts.size(); ++i) {
W << "arg" << i << "," << NL;
if (!G->is_output_mode_k2_component()) {
FunctionSignatureGenerator(W) << ("char **get_runtime_options([[maybe_unused]] int *count)") << BEGIN;

const auto &runtime_opts = G->get_kphp_runtime_opts();
if (runtime_opts.empty()) {
W << "return nullptr;" << NL;
} else {
W << "*count = " << runtime_opts.size() << ";" << NL;
for (size_t i = 0; i != runtime_opts.size(); ++i) {
W << "static char arg" << i << "[] = " << RawString{runtime_opts[i]} << ";" << NL;
}
W << "static char *argv[] = " << BEGIN;
for (size_t i = 0; i != runtime_opts.size(); ++i) {
W << "arg" << i << "," << NL;
}
W << END << ";" << NL << "return argv;" << NL;
}
W << END << ";" << NL << "return argv;" << NL;
W << END << NL << NL;
}
W << END << NL << NL;

FunctionSignatureGenerator(W) << ("void init_php_scripts_once_in_master() ") << BEGIN;

Expand Down Expand Up @@ -102,6 +107,20 @@ void StaticInit::compile(CodeGenerator &W) const {
W << END << NL;
}

struct RunInterruptedFunction {
FunctionPtr function;
RunInterruptedFunction(FunctionPtr function) : function(function) {}

void compile(CodeGenerator &W) const {
std::string await_prefix = function->is_interruptible ? "co_await " : "";
FunctionSignatureGenerator(W) << "task_t<void> " << FunctionName(function) << "$run() " << BEGIN
<< await_prefix << FunctionName(function) << "();" << NL
<< "co_return;"
<< END;
W << NL;
}
};

struct RunFunction {
FunctionPtr function;
RunFunction(FunctionPtr function) : function(function) {}
Expand Down Expand Up @@ -178,8 +197,11 @@ InitScriptsCpp::InitScriptsCpp(SrcFilePtr main_file_id) :
void InitScriptsCpp::compile(CodeGenerator &W) const {
W << OpenFile("init_php_scripts.cpp", "", false);

W << ExternInclude(G->settings().runtime_headers.get()) <<
ExternInclude("server/php-init-scripts.h");
W << ExternInclude(G->settings().runtime_headers.get());
if (!G->is_output_mode_k2_component()) {
W << ExternInclude("server/php-init-scripts.h");
}


W << Include(main_file_id->main_function->header_full_name);

Expand All @@ -196,10 +218,18 @@ void InitScriptsCpp::compile(CodeGenerator &W) const {
return;
}

W << RunFunction(main_file_id->main_function) << NL;
if (G->is_output_mode_k2_component()) {
W << RunInterruptedFunction(main_file_id->main_function) << NL;
} else {
W << RunFunction(main_file_id->main_function) << NL;
}
W << GlobalsResetFunction(main_file_id->main_function) << NL;

FunctionSignatureGenerator(W) << "void init_php_scripts_in_each_worker(" << PhpMutableGlobalsRefArgument() << ")" << BEGIN;
if (G->is_output_mode_k2_component()) {
FunctionSignatureGenerator(W) << "void init_php_scripts_in_each_worker(" << PhpMutableGlobalsRefArgument() << ", task_t<void>&run" ")" << BEGIN;
} else {
FunctionSignatureGenerator(W) << "void init_php_scripts_in_each_worker(" << PhpMutableGlobalsRefArgument() << ")" << BEGIN;
}

W << "global_vars_allocate(php_globals);" << NL;
for (LibPtr lib: G->get_libs()) {
Expand All @@ -211,9 +241,13 @@ void InitScriptsCpp::compile(CodeGenerator &W) const {

W << FunctionName(main_file_id->main_function) << "$globals_reset(php_globals);" << NL;

W << "set_script ("
<< FunctionName(main_file_id->main_function) << "$run, "
<< FunctionName(main_file_id->main_function) << "$globals_reset);" << NL;
if (G->is_output_mode_k2_component()) {
W << "run = " << FunctionName(main_file_id->main_function) << "$run();" << NL;
} else {
W << "set_script ("
<< FunctionName(main_file_id->main_function) << "$run, "
<< FunctionName(main_file_id->main_function) << "$globals_reset);" << NL;
}

W << END;

Expand All @@ -239,3 +273,19 @@ void CppMainFile::compile(CodeGenerator &W) const {
<< END;
W << CloseFile();
}

void ComponentInfoFile::compile(CodeGenerator &W) const {
kphp_assert(G->is_output_mode_k2_component());
G->settings().get_version();
auto now = std::chrono::system_clock::now();
W << OpenFile("image_info.cpp");
W << ExternInclude(G->settings().runtime_headers.get());
W << "const ImageInfo *vk_k2_describe() " << BEGIN
<< "static ImageInfo imageInfo {\"" << G->settings().k2_component_name.get() << "\"" << ","
<< std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch()).count() << ","
<< "K2_PLATFORM_HEADER_H_VERSION, "
<< "{" << "}};" << NL //todo:k2 add commit hash
<< "return &imageInfo;" << NL
<< END;
W << CloseFile();
}
4 changes: 4 additions & 0 deletions compiler/code-gen/files/init-scripts.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,7 @@ struct LibVersionHFile : CodeGenRootCmd {
struct CppMainFile : CodeGenRootCmd {
void compile(CodeGenerator &W) const final;
};

struct ComponentInfoFile : CodeGenRootCmd {
void compile(CodeGenerator &W) const final;
};
14 changes: 13 additions & 1 deletion compiler/code-gen/vertex-compiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -631,14 +631,19 @@ void compile_do(VertexAdaptor<op_do> root, CodeGenerator &W) {

void compile_return(VertexAdaptor<op_return> root, CodeGenerator &W) {
bool resumable_flag = W.get_context().resumable_flag;
bool interruptible_flag = W.get_context().interruptible_flag;
if (resumable_flag) {
if (root->has_expr()) {
W << "RETURN " << MacroBegin{};
} else {
W << "RETURN_VOID " << MacroBegin{};
}
} else {
W << "return ";
if (interruptible_flag) {
W << "co_return ";
} else {
W << "return ";
}
}

if (root->has_expr()) {
Expand Down Expand Up @@ -841,6 +846,9 @@ void compile_func_call(VertexAdaptor<op_func_call> root, CodeGenerator &W, func_
if (mode == func_call_mode::fork_call) {
W << FunctionForkName(func);
} else {
if (func->is_interruptible) {
W << "(" << "co_await ";
}
W << FunctionName(func);
}
}
Expand All @@ -865,6 +873,9 @@ void compile_func_call(VertexAdaptor<op_func_call> root, CodeGenerator &W, func_

W << JoinValues(args, ", ");
W << ")";
if (func->is_interruptible) {
W << ")";
}
}

void compile_func_call_fast(VertexAdaptor<op_func_call> root, CodeGenerator &W) {
Expand Down Expand Up @@ -1448,6 +1459,7 @@ void compile_function(VertexAdaptor<op_function> func_root, CodeGenerator &W) {

W.get_context().parent_func = func;
W.get_context().resumable_flag = func->is_resumable;
W.get_context().interruptible_flag = func->is_interruptible;

if (func->is_resumable) {
compile_function_resumable(func_root, W);
Expand Down
2 changes: 2 additions & 0 deletions compiler/compiler-core.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,8 @@ void CompilerCore::register_settings(CompilerSettings *settings) {
output_mode = OutputMode::cli;
} else if (settings->mode.get() == "lib") {
output_mode = OutputMode::lib;
} else if (settings->mode.get() == "k2-component") {
output_mode = OutputMode::k2_component;
} else {
output_mode = OutputMode::server;
}
Expand Down
5 changes: 5 additions & 0 deletions compiler/compiler-core.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ enum class OutputMode {
server, // -M server
cli, // -M cli
lib, // -M lib
k2_component // -M k2-component
};

class CompilerCore {
Expand Down Expand Up @@ -176,6 +177,10 @@ class CompilerCore {
return output_mode == OutputMode::lib;
}

bool is_output_mode_k2_component() const {
return output_mode == OutputMode::k2_component;
}

Stats stats;
};

Expand Down
15 changes: 13 additions & 2 deletions compiler/compiler-settings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,13 @@ void CompilerSettings::init() {
option_as_dir(kphp_src_path);
functions_file.value_ = get_full_path(functions_file.get());
runtime_sha256_file.value_ = get_full_path(runtime_sha256_file.get());
if (link_file.value_.empty()) {
if (mode.get() == "k2-component") {
link_file.value_ = kphp_src_path.get() + "/objs/libkphp-light-runtime.a";
} else {
link_file.value_ = kphp_src_path.get() + "/objs/libkphp-full-runtime.a";
}
}
link_file.value_ = get_full_path(link_file.get());

if (mode.get() == "lib") {
Expand Down Expand Up @@ -283,7 +290,7 @@ void CompilerSettings::init() {
if (!no_pch.get()) {
ss << " -Winvalid-pch -fpch-preprocess";
}
if (dynamic_incremental_linkage.get()) {
if (mode.get() == "k2-component" || dynamic_incremental_linkage.get()) {
ss << " -fPIC";
}
if (vk::contains(cxx.get(), "clang")) {
Expand Down Expand Up @@ -386,7 +393,11 @@ void CompilerSettings::init() {
option_as_dir(dest_dir);
dest_cpp_dir.value_ = dest_dir.get() + "kphp/";
dest_objs_dir.value_ = dest_dir.get() + "objs/";
binary_path.value_ = dest_dir.get() + mode.get();
if (mode.get() == "k2-component") {
binary_path.value_ = dest_dir.get() + k2_component_name.get() + ".so";
} else {
binary_path.value_ = dest_dir.get() + mode.get();
}
performance_analyze_report_path.value_ = dest_dir.get() + "performance_issues.json";
generated_runtime_path.value_ = kphp_src_path.get() + "objs/generated/auto/runtime/";

Expand Down
1 change: 1 addition & 0 deletions compiler/compiler-settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ class CompilerSettings : vk::not_copyable {
KphpOption<std::string> compilation_metrics_file;
KphpOption<std::string> override_kphp_version;
KphpOption<std::string> php_code_version;
KphpOption<std::string> k2_component_name;

KphpOption<std::string> cxx;
KphpOption<std::string> cxx_toolchain_dir;
Expand Down
1 change: 1 addition & 0 deletions compiler/data/function-data.h
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ class FunctionData {
bool cpp_template_call = false;
bool cpp_variadic_call = false;
bool is_resumable = false;
bool is_interruptible = false;
bool can_be_implicitly_interrupted_by_other_resumable = false;
bool is_virtual_method = false;
bool is_overridden_method = false;
Expand Down
8 changes: 5 additions & 3 deletions compiler/kphp2cpp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -215,10 +215,10 @@ int main(int argc, char *argv[]) {
'f', "functions-file", "KPHP_FUNCTIONS", "${KPHP_PATH}/builtin-functions/kphp-full/_functions.txt");
parser.add("File with kphp runtime sha256 hash", settings->runtime_sha256_file,
"runtime-sha256", "KPHP_RUNTIME_SHA256", "${KPHP_PATH}/objs/php_lib_version.sha256");
parser.add("The output binary type: server, cli or lib", settings->mode,
'M', "mode", "KPHP_MODE", "server", {"server", "cli", "lib"});
parser.add("The output binary type: server, k2-component, cli or lib", settings->mode,
'M', "mode", "KPHP_MODE", "server", {"server", "k2-component", "cli", "lib"});
parser.add("A runtime library for building the output binary", settings->link_file,
'l', "link-with", "KPHP_LINK_FILE", "${KPHP_PATH}/objs/libkphp-full-runtime.a");
'l', "link-with", "KPHP_LINK_FILE");
parser.add("Directory where php files will be searched", settings->includes,
'I', "include-dir", "KPHP_INCLUDE_DIR");
parser.add("Destination directory", settings->dest_dir,
Expand Down Expand Up @@ -293,6 +293,8 @@ int main(int argc, char *argv[]) {
"require-functions-typing", "KPHP_REQUIRE_FUNCTIONS_TYPING");
parser.add("Require class typing (1 - @var / default value is mandatory, 0 - auto infer or check if exists)", settings->require_class_typing,
"require-class-typing", "KPHP_REQUIRE_CLASS_TYPING");
parser.add("Define k2 component name. Default is \"KPHP\"", settings->k2_component_name,
"k2-component-name", "KPHP_K2_COMPONENT_NAME", "KPHP");

parser.add_implicit_option("Linker flags", settings->ld_flags);
parser.add_implicit_option("Incremental linker flags", settings->incremental_linker_flags);
Expand Down
8 changes: 8 additions & 0 deletions compiler/make/make.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include "compiler/make/make-runner.h"
#include "compiler/make/objs-to-bin-target.h"
#include "compiler/make/objs-to-obj-target.h"
#include "compiler/make/objs-to-k2-component-target.h"
#include "compiler/make/objs-to-static-lib-target.h"
#include "compiler/stage.h"
#include "compiler/threading/profiler.h"
Expand Down Expand Up @@ -98,6 +99,10 @@ class MakeSetup {
return create_target(new Objs2StaticLibTarget, to_targets(std::move(objs)), lib);
}

Target *create_objs2k2_component_target(std::vector<File *> objs, File *lib) {
return create_target(new Objs2K2ComponentTarget, to_targets(std::move(objs)), lib);
}

bool make_target(File *bin, const std::string &build_message, int jobs_count) {
return make.make_targets(to_targets(bin), build_message, jobs_count);
}
Expand Down Expand Up @@ -177,6 +182,7 @@ static long long get_imported_header_mtime(const std::string &header_path, const
return 0;
}


// prepare dir kphp_out/objs/pch_{flags} and make a target runtime-headers.h.gch inside it
// in production, there will be two pch_ folders: with debug symbols and without them
// later on, we'll copy this folder inside /tmp/kphp_pch — that's why if it exists, don't do anything
Expand Down Expand Up @@ -431,6 +437,8 @@ void run_make() {

if (output_mode == OutputMode::lib) {
make.create_objs2static_lib_target(objs, &bin_file);
} else if (output_mode == OutputMode::k2_component) {
make.create_objs2k2_component_target(objs, &bin_file);
} else {
const std::string build_stage{"Compiling"};
AutoProfiler profiler{get_profiler(build_stage)};
Expand Down
Loading

0 comments on commit 63e7833

Please sign in to comment.