Skip to content

Commit

Permalink
re-vendor ocamlrep dependencies
Browse files Browse the repository at this point in the history
Summary:
We need to upgrade ocamlrep such that it is ocaml 5.1.0 compatible.

This diff vendors in code from `/fbcode/common/ocaml/interop` (minus changes to `TARGETS` files of which there are functionally none)

In a future diff I will introduce a way to achieve this automatically for the OSS version of ERRPY (and will remove the vendoring for the internal version)

Reviewed By: vsiles

Differential Revision: D51024748

fbshipit-source-id: cacecd437d6b9a96722ef786d90d440108c70266
  • Loading branch information
jasontatton authored and facebook-github-bot committed Nov 7, 2023
1 parent cdcda95 commit 75ddb53
Show file tree
Hide file tree
Showing 24 changed files with 130 additions and 83 deletions.
13 changes: 13 additions & 0 deletions vendor/ocaml/interop/.cargo/config.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Copyright (c) Meta Platforms, Inc. and affiliates.
#
# This source code is licensed under both the MIT license found in the
# LICENSE-MIT file in the root directory of this source tree and the Apache
# License, Version 2.0 found in the LICENSE-APACHE file in the root directory
# of this source tree.

[build]
rustflags = [
"-Drust-2018-idioms",
"-Dwarnings",
"-Dunused-crate-dependencies"
]
21 changes: 9 additions & 12 deletions vendor/ocaml/interop/.circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,15 @@ commands:
- run:
name: Download rust
command: |
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- --default-toolchain nightly-2023-04-23 -y
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- --default-toolchain nightly-2023-07-10 -y
init_opam:
description: Initialize opam
steps:
- run:
name: Init opam
command: |
opam init --compiler=4.14.0 --disable-sandboxing -y
opam init --compiler=5.1.0 --disable-sandboxing -y
setup_ocaml_tp:
description: Write symlinks shim/third-party/ocaml
Expand Down Expand Up @@ -52,17 +52,14 @@ commands:
- run:
name: Brew install
command: |
# Avoid `brew link` step errors
rm -f '/usr/local/lib/python3.9/site-packages/six.py'
brew unlink python@3.9
brew install cmake coreutils opam llvm zstd wget
- init_opam
- run:
name: Set environment variables
command: |
echo 'source "$HOME"/.cargo/env' >> "$BASH_ENV"
echo 'export PATH=/usr/local/opt/llvm/bin:/opt/homebrew/bin:"$PATH"' >> "$BASH_ENV"
echo 'eval $(opam env)' >> "$BASH_ENV"
echo 'export PATH=/usr/local/opt/llvm/bin:"$PATH"' >> "$BASH_ENV"
- setup_ocaml_tp

cargo:
Expand Down Expand Up @@ -95,7 +92,7 @@ commands:
- run:
name: Install reindeer
command: |
cargo +nightly-2023-04-23 install --git https://github.com/facebookincubator/reindeer.git reindeer --force
cargo install --git https://github.com/facebookincubator/reindeer.git reindeer --force
reindeer:
description: Use reindeer to vendor & buckify rust 3rd-party deps
Expand Down Expand Up @@ -141,8 +138,8 @@ jobs:
description: |
macOS cargo build & test
macos:
xcode: 13.4.1
resource_class: macos.x86.medium.gen2
xcode: "14.2.0"
resource_class: macos.m1.medium.gen1
steps:
- checkout
- setup_macos_env
Expand All @@ -168,13 +165,13 @@ jobs:
description: |
macOS buck build
macos:
xcode: 13.4.1
resource_class: macos.x86.medium.gen2
xcode: "14.2.0"
resource_class: macos.m1.medium.gen1
steps:
- checkout
- setup_macos_env
- install_buck:
triple: "x86_64-apple-darwin"
triple: "aarch64-apple-darwin"
- install_reindeer
- reindeer
- buck_tp
Expand Down
2 changes: 0 additions & 2 deletions vendor/ocaml/interop/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ members = [
"ocamlrep_caml_builtins",
"ocamlrep_custom",
"ocamlrep_derive",
"ocamlrep_marshal",
"ocamlrep_ocamlpool",
"rust_to_ocaml/attr_parser",
"rust_to_ocaml/rust_to_ocaml",
Expand All @@ -21,7 +20,6 @@ members = [
"cargo_test_utils",
"ocamlrep_custom/test",
"ocamlrep_ocamlpool/test",
"ocamlrep_marshal/test",
"ocamlrep/test/test_bindings",
"ocamlrep/test/test_from_ocamlrep",
"ocamlrep/test/test_from_ocamlrep_in",
Expand Down
4 changes: 1 addition & 3 deletions vendor/ocaml/interop/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,7 @@ The goal of this project is to make OCaml and Rust code interoperable. While in
## Requirements
This project is stand-alone and requires or works with:
- OCaml 4.14.0;
- A rust nightly toolchain [^1].

[^1]: If you plan on using Buck2 for [building ocamlrep](#building-ocamlrep) we recommend `nightly-2023-01-24` at this time.
- A rust nightly toolchain.

## Building ocamlrep

Expand Down
7 changes: 7 additions & 0 deletions vendor/ocaml/interop/ocamlrep/arena.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,13 @@ pub struct Arena {
cache: MemoizationCache,
}

impl Default for Arena {
/// Create a new Arena with 4KB of capacity preallocated.
fn default() -> Self {
Arena::new()
}
}

impl Arena {
/// Create a new Arena with 4KB of capacity preallocated.
pub fn new() -> Self {
Expand Down
7 changes: 7 additions & 0 deletions vendor/ocaml/interop/ocamlrep/cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,13 @@ pub struct MemoizationCache {
cache: RefCell<Option<HashMap<(usize, usize), usize>>>,
}

impl Default for MemoizationCache {
#[inline(always)]
fn default() -> Self {
MemoizationCache::new()
}
}

impl MemoizationCache {
#[inline(always)]
pub fn new() -> Self {
Expand Down
4 changes: 2 additions & 2 deletions vendor/ocaml/interop/ocamlrep/from.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ pub fn expect_nullary_variant(value: Value<'_>, max: usize) -> Result<isize, Fro
}
}

pub fn expect_block<'a>(value: Value<'a>) -> Result<Block<'a>, FromError> {
pub fn expect_block(value: Value<'_>) -> Result<Block<'_>, FromError> {
match value.as_block() {
Some(block) => Ok(block),
None => Err(FromError::ExpectedBlock(value.as_int().unwrap())),
Expand Down Expand Up @@ -69,7 +69,7 @@ pub fn expect_block_with_size_and_tag(
Ok(block)
}

pub fn expect_tuple<'a>(value: Value<'a>, size: usize) -> Result<Block<'a>, FromError> {
pub fn expect_tuple(value: Value<'_>, size: usize) -> Result<Block<'_>, FromError> {
let block = expect_block(value)?;
expect_block_size(block, size)?;
if block.tag() != 0 {
Expand Down
2 changes: 1 addition & 1 deletion vendor/ocaml/interop/ocamlrep/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -478,7 +478,7 @@ pub trait Allocator: Sized {
/// Allocate a block with tag `STRING_TAG` and enough space for a string of
/// `len` bytes. Write its header and return a `BlockBytes` wrapping the
/// buffer and the block.
fn byte_string_with_len<'a>(&'a self, len: usize) -> BlockBytes<'a> {
fn byte_string_with_len(&self, len: usize) -> BlockBytes<'_> {
let word_size = std::mem::size_of::<*const u8>();
let words = (len + 1 /*null-ending*/ + (word_size - 1)/*rounding*/) / word_size;
let length = words * word_size;
Expand Down
7 changes: 7 additions & 0 deletions vendor/ocaml/interop/ocamlrep/ptr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ use crate::Value;
pub struct UnsafeOcamlPtr(NonZeroUsize);

impl UnsafeOcamlPtr {
/// # Safety
///
/// `ptr` must be rooted or the garbage collector can not be allowed to run
/// while an `UnsafeOcamlPtr` wrapper that contains it exists.
pub unsafe fn new(ptr: usize) -> Self {
Self(NonZeroUsize::new(ptr).unwrap())
}
Expand All @@ -53,6 +57,9 @@ impl UnsafeOcamlPtr {
}

/// Interpret this pointer as an OCaml value which is valid for lifetime 'a.
///
/// # Safety
///
/// The OCaml garbage collector must not run during this lifetime (even if
/// the value is rooted).
#[inline(always)]
Expand Down
8 changes: 5 additions & 3 deletions vendor/ocaml/interop/ocamlrep/test/test_bindings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ fn val<T: FromOcamlRep + ToOcamlRep>(value: T) -> usize {
value.to_bits()
}

/// # Safety
/// `value` must be a valid pointer to an OCaml value.
#[no_mangle]
pub unsafe extern "C" fn convert_to_ocamlrep(value: usize) -> usize {
let arena = Box::leak(Box::new(ocamlrep::Arena::new()));
Expand Down Expand Up @@ -108,7 +110,7 @@ pub extern "C" fn get_byte_slice(_unit: usize) -> usize {
#[no_mangle]
pub extern "C" fn get_int_opt_slice(_unit: usize) -> usize {
let arena = Box::leak(Box::new(ocamlrep::Arena::new()));
let vec = vec![None, Some(2), Some(3)];
let vec = [None, Some(2), Some(3)];
let slice = &vec[..];
arena.add(slice).to_bits()
}
Expand Down Expand Up @@ -322,7 +324,7 @@ mod tests {
"-o",
"test_ocamlrep_ml.cmx",
],
Some(&tmp_dir.path()),
Some(tmp_dir.path()),
);
assert_eq!(run(compile_cmd).map_err(fmt_exit_status_err), Ok(()));
let link_cmd = cmd(
Expand All @@ -339,7 +341,7 @@ mod tests {
"-cclib",
"-locamlrep_ocamlpool",
],
Some(&tmp_dir.path()),
Some(tmp_dir.path()),
);
assert_eq!(run(link_cmd).map_err(fmt_exit_status_err), Ok(()));
let ocamlrep_test_cmd = cmd(
Expand Down
30 changes: 15 additions & 15 deletions vendor/ocaml/interop/ocamlrep/test/test_from_ocamlrep.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,10 +75,10 @@ struct Foo {
fn bad_struct_field() {
let arena = Arena::new();
let value = {
let mut foo = arena.block_with_size_and_tag(2, 0);
arena.set_field(&mut foo, 0, Value::int(0));
arena.set_field(&mut foo, 1, Value::int(42));
foo.build()
let mut block = arena.block_with_size_and_tag(2, 0);
arena.set_field(&mut block, 0, Value::int(0));
arena.set_field(&mut block, 1, Value::int(42));
block.build()
};
let err = Foo::from_ocamlrep(value).err().unwrap();
assert_eq!(err, ErrorInField(1, Box::new(ExpectedBool(42))));
Expand All @@ -94,21 +94,21 @@ struct Bar {
fn bad_nested_struct_field() {
let arena = Arena::new();

let foo = {
let mut foo = arena.block_with_size_and_tag(2, 0);
arena.set_field(&mut foo, 0, Value::int(0));
arena.set_field(&mut foo, 1, Value::int(42));
foo.build()
let inner = {
let mut block = arena.block_with_size_and_tag(2, 0);
arena.set_field(&mut block, 0, Value::int(0));
arena.set_field(&mut block, 1, Value::int(42));
block.build()
};

let bar = {
let mut bar = arena.block_with_size_and_tag(2, 0);
arena.set_field(&mut bar, 0, foo);
arena.set_field(&mut bar, 1, Value::int(0));
bar.build()
let outer = {
let mut block = arena.block_with_size_and_tag(2, 0);
arena.set_field(&mut block, 0, inner);
arena.set_field(&mut block, 1, Value::int(0));
block.build()
};

let err = Bar::from_ocamlrep(bar).err().unwrap();
let err = Bar::from_ocamlrep(outer).err().unwrap();
assert_eq!(
err,
ErrorInField(0, Box::new(ErrorInField(1, Box::new(ExpectedBool(42)))))
Expand Down
4 changes: 3 additions & 1 deletion vendor/ocaml/interop/ocamlrep_custom/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ impl<T: CamlSerialize> FromOcamlRep for Custom<T> {

/// Helper function to fetch a reference to the `Rc` from the OCaml representation
/// of a custom block.
fn rc_from_value<'a, T: CamlSerialize>(value: Value<'a>) -> Result<&'a Rc<T>, FromError> {
fn rc_from_value<T: CamlSerialize>(value: Value<'_>) -> Result<&Rc<T>, FromError> {
let block = from::expect_block(value)?;
from::expect_block_tag(block, CUSTOM_TAG)?;
from::expect_block_size(block, CUSTOM_BLOCK_SIZE_IN_WORDS)?;
Expand Down Expand Up @@ -402,6 +402,8 @@ pub fn operations_helper<T: CamlSerialize>() -> CustomOperations {

/// Helper used for the `caml_serialize_default_impls` macro
///
/// # Safety
///
/// Should not be used directly. Interacts with the OCaml runtime and is
/// thus unsafe to call in a multi-threaded context.
pub unsafe fn register_helper<T>(ops: &'static CustomOperations) {
Expand Down
3 changes: 1 addition & 2 deletions vendor/ocaml/interop/ocamlrep_derive/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -195,8 +195,7 @@ fn parse_ocamlrep_attr(attrs: &[Attribute]) -> Option<Vec<NestedMeta>> {
Meta::List(list) => {
// #[foo(bar)]
if list.path.is_ident("ocamlrep") {
res.get_or_insert_with(Vec::new)
.extend(list.nested.into_iter());
res.get_or_insert_with(Vec::new).extend(list.nested);
}
}
Meta::NameValue(_) => {
Expand Down
22 changes: 17 additions & 5 deletions vendor/ocaml/interop/ocamlrep_ocamlpool/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,24 @@ fn ocamllib_dir() -> std::path::PathBuf {
"-c",
"ocamlopt.opt -config | grep standard_library: | awk '{ print $2 }'",
]);
std::path::Path::new(
std::str::from_utf8(&sh.output().unwrap().stdout)
let output = sh.output().unwrap().stdout;
let proposed_path = std::path::Path::new(std::str::from_utf8(&output).unwrap().trim());
// A supercaml 'ocamlopt.opt' can report standard library paths that don't
// exist.
if proposed_path.exists() {
proposed_path.to_path_buf()
} else {
// Fallback to guessing the location given knowledge of where
// 'ocamlopt.opt' itself it.
let mut sh = std::process::Command::new("sh");
sh.args(["-c", "which ocamlopt.opt"]);
let output = sh.output().unwrap().stdout;
std::path::Path::new(std::str::from_utf8(&output).unwrap().trim())
.ancestors()
.nth(2)
.unwrap()
.trim(),
)
.to_path_buf()
.join("lib/ocaml")
}
}

fn main() {
Expand Down
3 changes: 2 additions & 1 deletion vendor/ocaml/interop/ocamlrep_ocamlpool/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -404,7 +404,8 @@ macro_rules! ocaml_registered_function_fn {
($ocaml_name:expr, fn $name:ident($($param:ident: $ty:ty),+ $(,)?) -> $ret:ty) => {
#[no_mangle]
pub unsafe fn $name ($($param: $ty,)*) -> $ret {
static FN: once_cell::sync::OnceCell<usize> = once_cell::sync::OnceCell::new();
use std::sync::OnceLock;
static FN: OnceLock<usize> = OnceLock::new();
let the_function_to_call = *FN.get_or_init(|| {
let the_function_to_call_name = std::ffi::CString::new($ocaml_name).expect("string contained null byte");
let the_function_to_call = $crate::caml_named_value(the_function_to_call_name.as_ptr());
Expand Down
9 changes: 8 additions & 1 deletion vendor/ocaml/interop/ocamlrep_ocamlpool/ocamlpool.c
Original file line number Diff line number Diff line change
Expand Up @@ -380,7 +380,14 @@ void ocamlpool_leave(void) {
*/
value ocamlpool_reserve_block(tag_t tag, mlsize_t wosize) {
caml_domain_state* d = Caml_state;
value* p = caml_shared_try_alloc(d->shared_heap, wosize, tag, 0);
value* p = caml_shared_try_alloc(
d->shared_heap,
wosize,
tag,
#if OCAML_VERSION >= 50100
0, /* no reserved bits */
#endif
0 /* not pinned*/);
d->allocated_words += Whsize_wosize(wosize);

if (p == NULL) {
Expand Down

0 comments on commit 75ddb53

Please sign in to comment.