Skip to content

Commit

Permalink
Make hh_single_compile an OSS executable (#8979)
Browse files Browse the repository at this point in the history
Summary: Pull Request resolved: #8979

Differential Revision: D33922794

fbshipit-source-id: 8f5ab91788ba8d8045b5685c28f89a7a1306b345
  • Loading branch information
voorka authored and facebook-github-bot committed Feb 1, 2022
1 parent 93aadad commit fb0cc2b
Show file tree
Hide file tree
Showing 8 changed files with 2,188 additions and 0 deletions.
1 change: 1 addition & 0 deletions hphp/hack/.cargo/Cargo.toml.ocaml_build
Expand Up @@ -83,6 +83,7 @@ members = [
"src/hackc/emitter/cargo/statement_state",
"src/hackc//emitter/cargo/symbol_refs_state",
"src/hackc/ffi_bridge",
"src/hackc/helpers",
"src/hackc/hhbc/cargo/decl_vars",
"src/hackc/hhbc/cargo/hhas_pos",
"src/hackc/hhbc/cargo/adata_state",
Expand Down
4 changes: 4 additions & 0 deletions hphp/hack/CMakeLists.txt
Expand Up @@ -244,6 +244,10 @@ endfunction()

build_cxx_bridge(parser "src/parser/ffi_bridge")
build_cxx_bridge(compiler "src/hackc/ffi_bridge")
build_cxx_bridge(compiler_helpers "src/hackc/helpers")

add_executable(hh_single_compile "${CMAKE_CURRENT_SOURCE_DIR}/src/hackc/hh_single_compile.cpp")
target_link_libraries(hh_single_compile parser_ffi compiler_ffi compiler_helpers_ffi hhbc_ast_header)

if (NOT LZ4_FOUND)
add_dependencies(hack_dune lz4)
Expand Down
41 changes: 41 additions & 0 deletions hphp/hack/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 17 additions & 0 deletions hphp/hack/src/hackc/helpers/Cargo.toml
@@ -0,0 +1,17 @@
# @generated by autocargo from //hphp/hack/src/hackc/helpers:compiler_helpers_ffi@rust
[package]
name = "compiler_helpers_ffi"
version = "0.0.0"
edition = "2021"

[lib]
path = "compiler_helpers_ffi.rs"
crate-type = ["lib", "staticlib"]

[dependencies]
compile = { path = "../compile/cargo/compile" }
cxx = "1.0.54"
hhvm_options = { path = "../../utils/hhvm_options" }

[build-dependencies]
cxx-build = "1.0.54"
3 changes: 3 additions & 0 deletions hphp/hack/src/hackc/helpers/build.rs
@@ -0,0 +1,3 @@
fn main() {
let _build = cxx_build::bridge("compiler_helpers_ffi.rs");
}
217 changes: 217 additions & 0 deletions hphp/hack/src/hackc/helpers/compiler_helpers_ffi.rs
@@ -0,0 +1,217 @@
// Copyright (c) 2019, Facebook, Inc.
// All rights reserved.
//
// This source code is licensed under the MIT license found in the
// LICENSE file in the "hack" directory of this source tree.

use cxx::CxxString;

#[cxx::bridge]
pub mod compile_ffi {
extern "Rust" {
fn hackc_parser_flags_ffi(
config_path: &CxxString,
hdf_options: &CxxString,
ini_options: &CxxString,
) -> u32;

fn hackc_hhbc_flags_ffi(
config_path: &CxxString,
hdf_options: &CxxString,
ini_options: &CxxString,
) -> u32;
}
}

///////////////////////////////////////////////////////////////////////////////////
// Opaque to C++.

fn get_hhvm_options(
config_path: &CxxString,
hdf_options: &CxxString,
ini_options: &CxxString,
) -> hhvm_options::HhvmOptions {
use std::os::unix::ffi::OsStrExt;

let path = std::ffi::OsStr::from_bytes(config_path.as_bytes()); // std::path::PathBuf::from();
let config_files = if path == "" {
vec![]
} else {
vec![std::path::PathBuf::from(path)]
};

let hdf_values = std::ffi::OsStr::from_bytes(hdf_options.as_bytes())
.to_str()
.expect("hdf_options don't work")
.split(' ')
.map(str::to_string)
.collect();

let ini_values = std::ffi::OsStr::from_bytes(ini_options.as_bytes())
.to_str()
.expect("ini_values don't work")
.split(' ')
.map(str::to_string)
.collect();

hhvm_options::HhvmOptions {
config_files,
hdf_values,
ini_values,
}
}

fn hackc_parser_flags_ffi(
config_path: &CxxString,
hdf_options: &CxxString,
ini_options: &CxxString,
) -> u32 {
use compile::ParserFlags;
let options = get_hhvm_options(config_path, hdf_options, ini_options);

let mut parser_options = ParserFlags::empty();
let config = options.to_config().expect("Invalid configuration options");

// Note: Could only find examples of Hack.Lang.AbstractStaticProps
if let Some(true) = config.get_bool("Hack.Lang.AbstractStaticProps") {
parser_options |= ParserFlags::ABSTRACT_STATIC_PROPS;
}
// TODO: I'm pretty sure allow_new_attribute_syntax is dead and we can kill this option
if let Some(true) = config.get_bool("hack.lang.allow_new_attribute_syntax") {
parser_options |= ParserFlags::ALLOW_NEW_ATTRIBUTE_SYNTAX;
}
// Both hdf and ini versions are being used
if let Some(true) = config.get_bool("Hack.Lang.AllowUnstableFeatures") {
parser_options |= ParserFlags::ALLOW_UNSTABLE_FEATURES;
}
// TODO: could not find examples of const_default_func_args, kill it in options_cli.rs
if let Some(true) = config.get_bool("Hack.Lang.ConstDefaultFuncArgs") {
parser_options |= ParserFlags::CONST_DEFAULT_FUNC_ARGS;
}
// Only hdf version found in use
if let Some(true) = config.get_bool("Hack.Lang.ConstStaticProps") {
parser_options |= ParserFlags::CONST_STATIC_PROPS;
}
// TODO: Only seems to exist in HackFuzzEmitter.php, look to kill this
if let Some(true) = config.get_bool("Hack.Lang.DisableArray") {
parser_options |= ParserFlags::DISABLE_ARRAY;
}
// TODO: Kill disable_array_typehint
// TODO: Kill disable_lval_as_an_expression
// Only hdf option in use. Kill variant in options_cli.rs
if let Some(true) = config.get_bool("Hack.Lang.DisableUnsetClassConst") {
parser_options |= ParserFlags::DISABLE_UNSET_CLASS_CONST;
}
// Only hdf option in use
if let Some(true) = config.get_bool("Hack.Lang.DisallowInstMeth") {
parser_options |= ParserFlags::DISALLOW_INST_METH;
}
// Both ini and hdf variants in use
if let Some(true) = config.get_bool("Hack.Lang.DisableXHPElementMangling") {
parser_options |= ParserFlags::DISABLE_XHP_ELEMENT_MANGLING;
}
// Both ini and hdf variants in use
if let Some(true) = config.get_bool("Hack.Lang.DisallowFunAndClsMethPseudoFuncs") {
parser_options |= ParserFlags::DISALLOW_FUN_AND_CLS_METH_PSEUDO_FUNCS;
}
// Only hdf option in use
if let Some(true) = config.get_bool("Hack.Lang.DisallowFuncPtrsInConstants") {
parser_options |= ParserFlags::DISALLOW_FUNC_PTRS_IN_CONSTANTS;
}
// Only hdf option in use
if let Some(true) = config.get_bool("Hack.Lang.EnableEnumClasses") {
parser_options |= ParserFlags::ENABLE_ENUM_CLASSES;
}
// Both options in use
if let Some(true) = config.get_bool("Hack.Lang.EnableXHPClassModifier") {
parser_options |= ParserFlags::ENABLE_XHP_CLASS_MODIFIER;
}
// Only hdf option in use. Kill variant in options_cli.rs
if let Some(true) = config.get_bool("Hack.Lang.EnableClassLevelWhereClauses") {
parser_options |= ParserFlags::ENABLE_CLASS_LEVEL_WHERE_CLAUSES;
}
return parser_options.bits();
}

fn hackc_hhbc_flags_ffi(
config_path: &CxxString,
hdf_options: &CxxString,
ini_options: &CxxString,
) -> u32 {
use compile::HHBCFlags;
let options = get_hhvm_options(config_path, hdf_options, ini_options);

let mut hhbc_options = HHBCFlags::empty();
// Defaults
hhbc_options |= HHBCFlags::EMIT_METH_CALLER_FUNC_POINTERS;
hhbc_options |= HHBCFlags::FOLD_LAZY_CLASS_KEYS;
let config = options.to_config().expect("Invalid configuration options");

// Only ini version in use
if let Some(true) = config.get_bool("php7.ltr_assign") {
hhbc_options |= HHBCFlags::LTR_ASSIGN;
}
// Only ini version in use
if let Some(true) = config.get_bool("php7.uvs") {
hhbc_options |= HHBCFlags::UVS;
}
// Both variants in use
if let Some(true) = config.get_bool("Repo.Authoritative") {
hhbc_options |= HHBCFlags::AUTHORITATIVE;
}
// HDF uses both Eval.JitEnableRenameFunction and JitEnableRenameFunction
// ini only uses the hhvm.jit_enable_rename_function
if let Some(true) = config.get_bool("Eval.JitEnableRenameFunction") {
hhbc_options |= HHBCFlags::JIT_ENABLE_RENAME_FUNCTION;
}
if let Some(true) = config.get_bool("JitEnableRenameFunction") {
hhbc_options |= HHBCFlags::JIT_ENABLE_RENAME_FUNCTION;
}
// Only hdf version in use
if let Some(true) = config.get_bool("Eval.LogExternCompilerPerf") {
hhbc_options |= HHBCFlags::LOG_EXTERN_COMPILER_PERF;
}
// I think only the hdf is used correctly
if let Some(true) = config.get_bool("Eval.EnableIntrinsicsExtension") {
hhbc_options |= HHBCFlags::ENABLE_INTRINSICS_EXTENSION;
}
// Only the hdf versions used
if let Some(true) = config.get_bool("Eval.EmitClsMethPointers") {
hhbc_options |= HHBCFlags::EMIT_CLS_METH_POINTERS;
}
// Only the hdf versions used. Can kill variant in options_cli.rs
if let Some(b) = config.get_bool("Eval.EmitMethCallerFuncPointers") {
if b {
hhbc_options |= HHBCFlags::EMIT_METH_CALLER_FUNC_POINTERS;
} else {
hhbc_options &= !(HHBCFlags::EMIT_METH_CALLER_FUNC_POINTERS);
}
}
// ini just uses hhvm.enable_implicit_context
// hdf uses Eval.EnableImplicitContext
if let Some(true) = config.get_bool("Eval.EnableImplicitContext") {
hhbc_options |= HHBCFlags::ENABLE_IMPLICIT_CONTEXT;
}
if let Some(true) = config.get_bool("enable_implicit_context") {
hhbc_options |= HHBCFlags::ENABLE_IMPLICIT_CONTEXT;
}
// ini might use hhvm.array_provenance
// hdf might use Eval.ArrayProvenance
// But super unclear here
if let Some(true) = config.get_bool("Eval.ArrayProvenance") {
hhbc_options |= HHBCFlags::ARRAY_PROVENANCE;
}
if let Some(true) = config.get_bool("array_provenance") {
hhbc_options |= HHBCFlags::ARRAY_PROVENANCE;
}
// Only hdf version
if let Some(b) = config.get_bool("Eval.FoldLazyClassKeys") {
if b {
hhbc_options |= HHBCFlags::FOLD_LAZY_CLASS_KEYS;
} else {
hhbc_options &= !(HHBCFlags::FOLD_LAZY_CLASS_KEYS);
}
}

return hhbc_options.bits();
}

0 comments on commit fb0cc2b

Please sign in to comment.