Skip to content

Commit 7614e77

Browse files
committed
Save an unconditional close of guest params
Signed-off-by: Ludvig Liljenberg <4257730+ludfjig@users.noreply.github.com>
1 parent b164763 commit 7614e77

File tree

9 files changed

+69
-53
lines changed

9 files changed

+69
-53
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
44

55
## [Prerelease] - Unreleased
66

7+
### Changed
8+
* **Breaking:** `GuestFunctionDefinition::new` now takes a typed function pointer instead of `usize` by @ludfjig in https://github.com/hyperlight-dev/hyperlight/pull/1241
9+
710
## [v0.12.0] - 2025-12-09
811

912
### Fixed

src/hyperlight_component_util/src/guest.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,7 @@ fn emit_export_extern_decl<'a, 'b, 'c>(
210210
let marshal_result = emit_hl_marshal_result(s, ret.clone(), &ft.result);
211211
let trait_path = s.cur_trait_path();
212212
quote! {
213-
fn #n<T: Guest>(fc: &::hyperlight_common::flatbuffer_wrappers::function_call::FunctionCall) -> ::hyperlight_guest::error::Result<::alloc::vec::Vec<u8>> {
213+
fn #n<T: Guest>(fc: ::hyperlight_common::flatbuffer_wrappers::function_call::FunctionCall) -> ::hyperlight_guest::error::Result<::alloc::vec::Vec<u8>> {
214214
<T as Guest>::with_guest_state(|state| {
215215
#(#pds)*
216216
#(#get_instance)*
@@ -223,7 +223,7 @@ fn emit_export_extern_decl<'a, 'b, 'c>(
223223
::alloc::string::ToString::to_string(#fname),
224224
::alloc::vec![#(#pts),*],
225225
::hyperlight_common::flatbuffer_wrappers::function_types::ReturnType::VecBytes,
226-
#n::<T> as usize
226+
#n::<T>
227227
)
228228
);
229229
}

src/hyperlight_guest_bin/src/guest_function/call.rs

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,6 @@ use tracing::{Span, instrument};
2727

2828
use crate::{GUEST_HANDLE, REGISTERED_GUEST_FUNCTIONS};
2929

30-
type GuestFunc = fn(FunctionCall) -> Result<Vec<u8>>;
31-
3230
#[instrument(skip_all, parent = Span::current(), level= "Trace")]
3331
pub(crate) fn call_guest_function(function_call: FunctionCall) -> Result<Vec<u8>> {
3432
// Validate this is a Guest Function Call
@@ -59,14 +57,10 @@ pub(crate) fn call_guest_function(function_call: FunctionCall) -> Result<Vec<u8>
5957
// Verify that the function call has the correct parameter types and length.
6058
registered_function_definition.verify_parameters(&function_call_parameter_types)?;
6159

62-
let p_function = unsafe {
63-
let function_pointer = registered_function_definition.function_pointer;
64-
core::mem::transmute::<usize, GuestFunc>(function_pointer)
65-
};
66-
67-
p_function(function_call)
60+
(registered_function_definition.function_pointer)(function_call)
6861
} else {
69-
// The given function is not registered. The guest should implement a function called guest_dispatch_function to handle this.
62+
// The given function is not registered. The guest should implement a function called
63+
// guest_dispatch_function to handle this.
7064

7165
// TODO: ideally we would define a default implementation of this with weak linkage so the guest is not required
7266
// to implement the function but its seems that weak linkage is an unstable feature so for now its probably better

src/hyperlight_guest_bin/src/guest_function/definition.rs

Lines changed: 25 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -28,17 +28,23 @@ use hyperlight_common::func::{
2828
};
2929
use hyperlight_guest::error::{HyperlightGuestError, Result};
3030

31-
/// The definition of a function exposed from the guest to the host
32-
#[derive(Debug, Clone, PartialEq, Eq)]
33-
pub struct GuestFunctionDefinition {
31+
/// The function pointer type for Rust guest functions.
32+
pub type GuestFunc = fn(FunctionCall) -> Result<Vec<u8>>;
33+
34+
/// The definition of a function exposed from the guest to the host.
35+
///
36+
/// The type parameter `F` is the function pointer type. For Rust guests this
37+
/// is [`GuestFunc`]; the C API uses its own `CGuestFunc` type.
38+
#[derive(Debug, Clone)]
39+
pub struct GuestFunctionDefinition<F: Copy> {
3440
/// The function name
3541
pub function_name: String,
3642
/// The type of the parameter values for the host function call.
3743
pub parameter_types: Vec<ParameterType>,
3844
/// The type of the return value from the host function call
3945
pub return_type: ReturnType,
40-
/// The function pointer to the guest function
41-
pub function_pointer: usize,
46+
/// The function pointer to the guest function.
47+
pub function_pointer: F,
4248
}
4349

4450
/// Trait for functions that can be converted to a `fn(FunctionCall) -> Result<Vec<u8>>`
@@ -57,7 +63,7 @@ where
5763
fn into_guest_function(self) -> fn(FunctionCall) -> Result<Vec<u8>>;
5864
}
5965

60-
/// Trait for functions that can be converted to a `GuestFunctionDefinition`
66+
/// Trait for functions that can be converted to a `GuestFunctionDefinition<GuestFunc>`
6167
pub trait AsGuestFunctionDefinition<Output, Args>
6268
where
6369
Self: Function<Output, Args, HyperlightGuestError>,
@@ -66,7 +72,10 @@ where
6672
Args: ParameterTuple,
6773
{
6874
/// Get the `GuestFunctionDefinition` for this function
69-
fn as_guest_function_definition(&self, name: impl Into<String>) -> GuestFunctionDefinition;
75+
fn as_guest_function_definition(
76+
&self,
77+
name: impl Into<String>,
78+
) -> GuestFunctionDefinition<GuestFunc>;
7079
}
7180

7281
fn into_flatbuffer_result(value: ReturnValue) -> Vec<u8> {
@@ -147,11 +156,13 @@ where
147156
Args: ParameterTuple,
148157
Output: SupportedReturnType,
149158
{
150-
fn as_guest_function_definition(&self, name: impl Into<String>) -> GuestFunctionDefinition {
159+
fn as_guest_function_definition(
160+
&self,
161+
name: impl Into<String>,
162+
) -> GuestFunctionDefinition<GuestFunc> {
151163
let parameter_types = Args::TYPE.to_vec();
152164
let return_type = Output::TYPE;
153165
let function_pointer = self.into_guest_function();
154-
let function_pointer = function_pointer as usize;
155166

156167
GuestFunctionDefinition {
157168
function_name: name.into(),
@@ -164,13 +175,13 @@ where
164175

165176
for_each_tuple!(impl_host_function);
166177

167-
impl GuestFunctionDefinition {
178+
impl<F: Copy> GuestFunctionDefinition<F> {
168179
/// Create a new `GuestFunctionDefinition`.
169180
pub fn new(
170181
function_name: String,
171182
parameter_types: Vec<ParameterType>,
172183
return_type: ReturnType,
173-
function_pointer: usize,
184+
function_pointer: F,
174185
) -> Self {
175186
Self {
176187
function_name,
@@ -180,12 +191,12 @@ impl GuestFunctionDefinition {
180191
}
181192
}
182193

183-
/// Create a new `GuestFunctionDefinition` from a function that implements
184-
/// `AsGuestFunctionDefinition`.
194+
/// Create a new `GuestFunctionDefinition<GuestFunc>` from a function that
195+
/// implements `AsGuestFunctionDefinition`.
185196
pub fn from_fn<Output, Args>(
186197
function_name: String,
187198
function: impl AsGuestFunctionDefinition<Output, Args>,
188-
) -> Self
199+
) -> GuestFunctionDefinition<GuestFunc>
189200
where
190201
Args: ParameterTuple,
191202
Output: SupportedReturnType,

src/hyperlight_guest_bin/src/guest_function/register.rs

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -19,19 +19,27 @@ use alloc::string::String;
1919

2020
use hyperlight_common::func::{ParameterTuple, SupportedReturnType};
2121

22-
use super::definition::GuestFunctionDefinition;
22+
use super::definition::{GuestFunc, GuestFunctionDefinition};
2323
use crate::REGISTERED_GUEST_FUNCTIONS;
2424
use crate::guest_function::definition::AsGuestFunctionDefinition;
2525

2626
/// Represents the functions that the guest exposes to the host.
27-
#[derive(Debug, Default, Clone)]
28-
pub struct GuestFunctionRegister {
27+
#[derive(Debug, Clone)]
28+
pub struct GuestFunctionRegister<F: Copy> {
2929
/// Currently registered guest functions
30-
guest_functions: BTreeMap<String, GuestFunctionDefinition>,
30+
guest_functions: BTreeMap<String, GuestFunctionDefinition<F>>,
3131
}
3232

33-
impl GuestFunctionRegister {
34-
/// Create a new `GuestFunctionDetails`.
33+
impl<F: Copy> Default for GuestFunctionRegister<F> {
34+
fn default() -> Self {
35+
Self {
36+
guest_functions: BTreeMap::new(),
37+
}
38+
}
39+
}
40+
41+
impl<F: Copy> GuestFunctionRegister<F> {
42+
/// Create a new `GuestFunctionRegister`.
3543
pub const fn new() -> Self {
3644
Self {
3745
guest_functions: BTreeMap::new(),
@@ -44,12 +52,19 @@ impl GuestFunctionRegister {
4452
/// otherwise the previous `GuestFunctionDefinition` is returned.
4553
pub fn register(
4654
&mut self,
47-
guest_function: GuestFunctionDefinition,
48-
) -> Option<GuestFunctionDefinition> {
55+
guest_function: GuestFunctionDefinition<F>,
56+
) -> Option<GuestFunctionDefinition<F>> {
4957
self.guest_functions
5058
.insert(guest_function.function_name.clone(), guest_function)
5159
}
5260

61+
/// Gets a `GuestFunctionDefinition` by its `name` field.
62+
pub fn get(&self, function_name: &str) -> Option<&GuestFunctionDefinition<F>> {
63+
self.guest_functions.get(function_name)
64+
}
65+
}
66+
67+
impl GuestFunctionRegister<GuestFunc> {
5368
pub fn register_fn<Output, Args>(
5469
&mut self,
5570
name: impl Into<String>,
@@ -61,14 +76,9 @@ impl GuestFunctionRegister {
6176
let gfd = f.as_guest_function_definition(name);
6277
self.register(gfd);
6378
}
64-
65-
/// Gets a `GuestFunctionDefinition` by its `name` field.
66-
pub fn get(&self, function_name: &str) -> Option<&GuestFunctionDefinition> {
67-
self.guest_functions.get(function_name)
68-
}
6979
}
7080

71-
pub fn register_function(function_definition: GuestFunctionDefinition) {
81+
pub fn register_function(function_definition: GuestFunctionDefinition<GuestFunc>) {
7282
unsafe {
7383
// This is currently safe, because we are single threaded, but we
7484
// should find a better way to do this, see issue #808

src/hyperlight_guest_bin/src/host_comm.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,9 +80,9 @@ pub fn read_n_bytes_from_user_memory(num: u64) -> Result<Vec<u8>> {
8080
///
8181
/// This function requires memory to be setup to be used. In particular, the
8282
/// existence of the input and output memory regions.
83-
pub fn print_output_with_host_print(function_call: &FunctionCall) -> Result<Vec<u8>> {
83+
pub fn print_output_with_host_print(function_call: FunctionCall) -> Result<Vec<u8>> {
8484
let handle = unsafe { GUEST_HANDLE };
85-
if let ParameterValue::String(message) = function_call.parameters.clone().unwrap()[0].clone() {
85+
if let ParameterValue::String(message) = function_call.parameters.unwrap().remove(0) {
8686
let res = handle.call_host_function::<i32>(
8787
"HostPrint",
8888
Some(Vec::from(&[ParameterValue::String(message.to_string())])),

src/hyperlight_guest_bin/src/lib.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ pub(crate) static HEAP_ALLOCATOR: ProfiledLockedHeap<32> =
116116
ProfiledLockedHeap(LockedHeap::<32>::empty());
117117

118118
pub static mut GUEST_HANDLE: GuestHandle = GuestHandle::new();
119-
pub(crate) static mut REGISTERED_GUEST_FUNCTIONS: GuestFunctionRegister =
119+
pub(crate) static mut REGISTERED_GUEST_FUNCTIONS: GuestFunctionRegister<GuestFunc> =
120120
GuestFunctionRegister::new();
121121

122122
/// The size of one page in the host OS, which may have some impacts
@@ -278,3 +278,5 @@ pub mod __private {
278278

279279
#[cfg(feature = "macros")]
280280
pub use hyperlight_guest_macro::{guest_function, host_function};
281+
282+
pub use crate::guest_function::definition::GuestFunc;

src/hyperlight_guest_capi/src/dispatch.rs

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ use alloc::boxed::Box;
1818
use alloc::slice;
1919
use alloc::vec::Vec;
2020
use core::ffi::{CStr, c_char};
21-
use core::mem;
2221

2322
use hyperlight_common::flatbuffer_wrappers::function_call::FunctionCall;
2423
use hyperlight_common::flatbuffer_wrappers::function_types::{ParameterType, ReturnType};
@@ -29,7 +28,8 @@ use hyperlight_guest_bin::guest_function::register::GuestFunctionRegister;
2928
use hyperlight_guest_bin::host_comm::call_host_function_without_returning_result;
3029

3130
use crate::types::{FfiFunctionCall, FfiVec};
32-
static mut REGISTERED_C_GUEST_FUNCTIONS: GuestFunctionRegister = GuestFunctionRegister::new();
31+
static mut REGISTERED_C_GUEST_FUNCTIONS: GuestFunctionRegister<CGuestFunc> =
32+
GuestFunctionRegister::new();
3333

3434
type CGuestFunc = extern "C" fn(&FfiFunctionCall) -> Box<FfiVec>;
3535

@@ -55,10 +55,7 @@ pub fn guest_dispatch_function(function_call: FunctionCall) -> Result<Vec<u8>> {
5555
registered_func.verify_parameters(&function_call_parameter_types)?;
5656

5757
let ffi_func_call = FfiFunctionCall::from_function_call(function_call)?;
58-
59-
let guest_func =
60-
unsafe { mem::transmute::<usize, CGuestFunc>(registered_func.function_pointer) };
61-
let function_result = guest_func(&ffi_func_call);
58+
let function_result = (registered_func.function_pointer)(&ffi_func_call);
6259

6360
unsafe { Ok(FfiVec::into_vec(*function_result)) }
6461
} else {
@@ -94,8 +91,7 @@ pub extern "C" fn hl_register_function_definition(
9491

9592
let func_params = unsafe { slice::from_raw_parts(params_type, param_no).to_vec() };
9693

97-
let func_def =
98-
GuestFunctionDefinition::new(func_name, func_params, return_type, func_ptr as usize);
94+
let func_def = GuestFunctionDefinition::new(func_name, func_params, return_type, func_ptr);
9995

10096
// Use &raw mut to get a mutable raw pointer, then dereference it
10197
// this is to avoid the clippy warning "shared reference to mutable static"

src/tests/rust_guests/simpleguest/src/main.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ use hyperlight_common::flatbuffer_wrappers::util::get_flatbuffer_result;
4444
use hyperlight_guest::error::{HyperlightGuestError, Result};
4545
use hyperlight_guest::exit::{abort_with_code, abort_with_code_and_message};
4646
use hyperlight_guest_bin::exception::arch::{Context, ExceptionInfo};
47-
use hyperlight_guest_bin::guest_function::definition::GuestFunctionDefinition;
47+
use hyperlight_guest_bin::guest_function::definition::{GuestFunc, GuestFunctionDefinition};
4848
use hyperlight_guest_bin::guest_function::register::register_function;
4949
use hyperlight_guest_bin::host_comm::{
5050
call_host_function, call_host_function_without_returning_result, get_host_return_value_raw,
@@ -652,11 +652,11 @@ fn call_host_expect_error(hostfuncname: String) -> Result<()> {
652652
#[no_mangle]
653653
#[instrument(skip_all, parent = Span::current(), level= "Trace")]
654654
pub extern "C" fn hyperlight_main() {
655-
let print_output_def = GuestFunctionDefinition::new(
655+
let print_output_def = GuestFunctionDefinition::<GuestFunc>::new(
656656
"PrintOutputWithHostPrint".to_string(),
657657
Vec::from(&[ParameterType::String]),
658658
ReturnType::Int,
659-
print_output_with_host_print as usize,
659+
print_output_with_host_print,
660660
);
661661
register_function(print_output_def);
662662
}

0 commit comments

Comments
 (0)