Skip to content

Commit 370555f

Browse files
committed
Use Rust stubs instead of C
Signed-off-by: Jorge Prendes <jorge.prendes@gmail.com>
1 parent 1773722 commit 370555f

20 files changed

Lines changed: 279 additions & 216 deletions

File tree

Cargo.lock

Lines changed: 3 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Justfile

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ export HYPERLIGHT_CFLAGS := \
1818
export CMAKE_GENERATOR := if os() == "windows" { "Ninja" } else { "" }
1919

2020
ensure-tools:
21-
cargo install cargo-hyperlight --locked --version 0.1.3
21+
cargo install cargo-hyperlight --locked --version 0.1.7
2222

2323
# Check if npm is installed, install automatically if missing (Linux)
2424
[private]
@@ -39,8 +39,7 @@ check-license-headers:
3939
./dev/check-license-headers.sh
4040

4141
clippy target=default-target features="": (ensure-tools)
42-
cd src/hyperlight-js-runtime && \
43-
cargo hyperlight clippy \
42+
cargo hyperlight clippy -p hyperlight-js-runtime \
4443
--profile={{ if target == "debug" {"dev"} else { target } }} \
4544
-- -D warnings
4645
cargo clippy --all-targets \

src/hyperlight-js-runtime/Cargo.toml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,17 +33,18 @@ tracing = { version = "0.1.44", default-features = false, features = ["log","att
3333
hyperlight-common = { workspace = true, default-features = false }
3434
hyperlight-guest = { workspace = true }
3535
hyperlight-guest-bin = { workspace = true }
36+
chrono = { version = "0.4", default-features = false }
3637

3738
[target.'cfg(not(hyperlight))'.dependencies]
3839
clap = { version = "4.5", features = ["derive"] }
39-
libc = "0.2"
4040

4141
[target.'cfg(not(hyperlight))'.dev-dependencies]
4242
escargot = "0.5"
4343
tempfile = "3.26"
4444

4545
[build-dependencies]
46-
cc = "1.2"
46+
bindgen = "0.72"
47+
glob = "0.3"
4748

4849
[features]
4950
default = []

src/hyperlight-js-runtime/build.rs

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,36 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1313
See the License for the specific language governing permissions and
1414
limitations under the License.
1515
*/
16-
fn main() {
17-
if std::env::var_os("CARGO_CFG_HYPERLIGHT").is_none() {
18-
return;
19-
}
2016

21-
let files = ["stubs/clock.c", "stubs/localtime.c"];
17+
use std::env;
18+
use std::path::PathBuf;
2219

23-
for file in files {
24-
println!("cargo:rerun-if-changed={}", file);
25-
}
20+
use bindgen::RustEdition::Edition2024;
2621

27-
cc::Build::new().files(files).compile("stubs");
22+
fn main() -> Result<(), Box<dyn std::error::Error>> {
23+
let mut bindings = bindgen::builder()
24+
.use_core()
25+
.wrap_unsafe_ops(true)
26+
.rust_edition(Edition2024)
27+
.clang_arg("-D_POSIX_MONOTONIC_CLOCK=1")
28+
.clang_arg("-D_POSIX_C_SOURCE=200809L");
29+
30+
bindings = bindings.header_contents(
31+
"libc_stubs.h",
32+
"
33+
#pragma once
34+
#include <errno.h>
35+
#include <stdio.h>
36+
#include <time.h>
37+
",
38+
);
39+
40+
println!("cargo:rerun-if-changed=stubs/include/stdio.h");
41+
println!("cargo:rerun-if-changed=stubs/include/time.h");
42+
43+
// Write the generated bindings to an output file.
44+
let out_path = PathBuf::from(env::var("OUT_DIR")?).join("libc_stubs.rs");
45+
bindings.generate()?.write_to_file(out_path)?;
46+
47+
Ok(())
2848
}

src/hyperlight-js-runtime/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ extern crate alloc;
2020
mod globals;
2121
pub mod host;
2222
mod host_fn;
23+
mod libc;
2324
mod modules;
2425
pub(crate) mod utils;
2526

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/*
2+
Copyright 2026 The Hyperlight Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
mod bindings {
17+
#![allow(
18+
non_camel_case_types,
19+
non_snake_case,
20+
non_upper_case_globals,
21+
dead_code,
22+
unnecessary_transmutes,
23+
clippy::upper_case_acronyms,
24+
clippy::ptr_offset_with_cast
25+
)]
26+
include!(concat!(env!("OUT_DIR"), "/libc_stubs.rs"));
27+
}
28+
29+
#[allow(unused_imports)] // not used in native.rs
30+
pub(crate) use core::ffi::*;
31+
32+
#[allow(unused_imports)] // not used in native.rs
33+
pub(crate) use bindings::*;

src/hyperlight-js-runtime/src/main.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ limitations under the License.
1616
#![cfg_attr(hyperlight, no_std)]
1717
#![cfg_attr(hyperlight, no_main)]
1818

19+
mod libc;
20+
1921
#[cfg(hyperlight)]
2022
include!("main/hyperlight.rs");
2123

src/hyperlight-js-runtime/src/main/hyperlight.rs

Lines changed: 2 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,6 @@ limitations under the License.
1515
*/
1616
extern crate alloc;
1717

18-
use core::ffi::*;
19-
use core::time::Duration;
20-
2118
use alloc::format;
2219
use alloc::string::String;
2320
use alloc::vec::Vec;
@@ -32,6 +29,8 @@ use hyperlight_guest_bin::{guest_function, host_function};
3229
use spin::Mutex;
3330
use tracing::instrument;
3431

32+
mod stubs;
33+
3534
struct Host;
3635

3736
pub trait CatchGuestErrorExt {
@@ -126,11 +125,6 @@ fn register_host_modules(host_modules_json: String) -> Result<()> {
126125
Ok(())
127126
}
128127

129-
#[unsafe(no_mangle)]
130-
pub extern "C" fn srand(_seed: u32) {
131-
// No-op
132-
}
133-
134128
#[unsafe(no_mangle)]
135129
pub fn guest_dispatch_function(function_call: FunctionCall) -> Result<Vec<u8>> {
136130
let params = function_call.parameters.unwrap_or_default();
@@ -139,42 +133,3 @@ pub fn guest_dispatch_function(function_call: FunctionCall) -> Result<Vec<u8>> {
139133
let result = RUNTIME.lock().run_handler(function_name, event, run_gc)?;
140134
Ok(get_flatbuffer_result(result.as_str()))
141135
}
142-
143-
/// # Safety
144-
/// This function is used by the C code to get the current time in seconds and nanoseconds.
145-
/// `ts` must be a valid pointer to an array of two `u64` values.
146-
#[unsafe(no_mangle)]
147-
pub unsafe extern "C" fn _current_time(ts: *mut u64) -> c_int {
148-
#[host_function("CurrentTimeMicros")]
149-
fn current_time_micros() -> Result<u64>;
150-
151-
let dur = current_time_micros().unwrap_or(1609459200u64 * 1_000_000u64);
152-
let dur = Duration::from_micros(dur);
153-
154-
let ts = unsafe { core::slice::from_raw_parts_mut(ts, 2) };
155-
ts[0] = dur.as_secs();
156-
ts[1] = dur.subsec_nanos() as u64;
157-
158-
0
159-
}
160-
161-
#[unsafe(no_mangle)]
162-
pub extern "C" fn putchar(c: c_int) -> c_int {
163-
unsafe { hyperlight_guest_bin::host_comm::_putchar(c as c_char) };
164-
if c == '\n' as c_int {
165-
// force a flush of the internal buffer in the hyperlight putchar implementation
166-
unsafe { hyperlight_guest_bin::host_comm::_putchar(0) };
167-
}
168-
(c as c_char) as c_int
169-
}
170-
171-
#[unsafe(no_mangle)]
172-
pub extern "C" fn fflush(f: *mut c_void) -> c_int {
173-
if !f.is_null() {
174-
// we only support flushing all streams, and stdout is our only stream
175-
return -1;
176-
}
177-
// flush stdout
178-
putchar('\0' as _);
179-
0
180-
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/*
2+
Copyright 2026 The Hyperlight Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
use hyperlight_guest::error::Result;
17+
use hyperlight_guest_bin::host_function;
18+
19+
use crate::libc;
20+
21+
fn micros_since_epoch() -> u64 {
22+
#[host_function("CurrentTimeMicros")]
23+
fn current_time_micros() -> Result<u64>;
24+
25+
current_time_micros().unwrap_or(1609459200u64 * 1_000_000u64)
26+
}
27+
28+
#[unsafe(no_mangle)]
29+
extern "C" fn clock_gettime(clk_id: libc::clockid_t, ts: *mut libc::timespec) -> libc::c_int {
30+
const CLOCK_REALTIME: libc::clockid_t = libc::CLOCK_REALTIME as libc::clockid_t;
31+
const CLOCK_MONOTONIC: libc::clockid_t = libc::CLOCK_MONOTONIC as libc::clockid_t;
32+
33+
if clk_id != CLOCK_REALTIME && clk_id != CLOCK_MONOTONIC {
34+
unsafe { libc::__errno_location().write(libc::EINVAL as _) };
35+
return -1;
36+
}
37+
let micros = micros_since_epoch();
38+
unsafe {
39+
ts.write(libc::timespec {
40+
tv_sec: (micros / 1_000_000) as _,
41+
tv_nsec: ((micros % 1_000_000) * 1000) as _,
42+
})
43+
};
44+
0
45+
}
46+
47+
#[unsafe(no_mangle)]
48+
extern "C" fn gettimeofday(tp: *mut libc::timeval, _tz: *mut libc::c_void) -> libc::c_int {
49+
let micros = micros_since_epoch();
50+
unsafe {
51+
tp.write(libc::timeval {
52+
tv_sec: (micros / 1_000_000) as _,
53+
tv_usec: (micros % 1_000_000) as _,
54+
});
55+
}
56+
0
57+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/*
2+
Copyright 2026 The Hyperlight Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
use crate::libc;
17+
18+
#[unsafe(no_mangle)]
19+
extern "C" fn putchar(c: libc::c_int) -> libc::c_int {
20+
unsafe { libc::_putchar(c as libc::c_char) };
21+
if c == '\n' as libc::c_int {
22+
// force a flush of the internal buffer in the hyperlight putchar implementation
23+
unsafe { libc::_putchar(0) };
24+
}
25+
(c as libc::c_char) as libc::c_int
26+
}
27+
28+
#[unsafe(no_mangle)]
29+
extern "C" fn fflush(f: *mut libc::c_void) -> libc::c_int {
30+
if !f.is_null() {
31+
// we only support flushing all streams, and stdout is our only stream
32+
unsafe { libc::__errno_location().write(libc::EINVAL as _) };
33+
return -1;
34+
}
35+
// flush stdout
36+
unsafe { libc::_putchar(0) };
37+
0
38+
}

0 commit comments

Comments
 (0)