Skip to content

Commit 09346ac

Browse files
authored
Guest function improvements and macros (#851)
* move function type traits to hyperlight_common Signed-off-by: Jorge Prendes <[email protected]> * Use function type traits to improve registration ergonomics Signed-off-by: Jorge Prendes <[email protected]> * Add from_result method to ResultType Signed-off-by: Jorge Prendes <[email protected]> * Add guest macro crate Signed-off-by: Jorge Prendes <[email protected]> * use guest_function and host_function macros in simpleguest Signed-off-by: Jorge Prendes <[email protected]> * update test guests Cargo.lock files Signed-off-by: Jorge Prendes <[email protected]> * Move result unwrap used in host_function macro from hl-common to hl-guest-bin Signed-off-by: Jorge Prendes <[email protected]> * Add comments on tricky areas Signed-off-by: Jorge Prendes <[email protected]> * update README.md to use new macros Signed-off-by: Jorge Prendes <[email protected]> --------- Signed-off-by: Jorge Prendes <[email protected]>
1 parent 2c69974 commit 09346ac

File tree

29 files changed

+1665
-1796
lines changed

29 files changed

+1665
-1796
lines changed

Cargo.lock

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

Cargo.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ members = [
1414
"src/hyperlight_testing",
1515
"fuzz",
1616
"src/hyperlight_guest_bin",
17+
"src/hyperlight_guest_macro",
1718
"src/hyperlight_component_util",
1819
"src/hyperlight_component_macro",
1920
"src/trace_dump",
@@ -28,7 +29,7 @@ exclude = [
2829
[workspace.package]
2930
version = "0.11.0"
3031
edition = "2024"
31-
rust-version = "1.88"
32+
rust-version = "1.89"
3233
license = "Apache-2.0"
3334
homepage = "https://github.com/hyperlight-dev/hyperlight"
3435
repository = "https://github.com/hyperlight-dev/hyperlight"
@@ -39,6 +40,7 @@ hyperlight-common = { path = "src/hyperlight_common", version = "0.11.0", defaul
3940
hyperlight-host = { path = "src/hyperlight_host", version = "0.11.0", default-features = false }
4041
hyperlight-guest = { path = "src/hyperlight_guest", version = "0.11.0", default-features = false }
4142
hyperlight-guest-bin = { path = "src/hyperlight_guest_bin", version = "0.11.0", default-features = false }
43+
hyperlight-guest-macro = { path = "src/hyperlight_guest_macro", version = "0.11.0", default-features = false }
4244
hyperlight-testing = { path = "src/hyperlight_testing", default-features = false }
4345
hyperlight-guest-tracing = { path = "src/hyperlight_guest_tracing", version = "0.11.0", default-features = false }
4446
hyperlight-component-util = { path = "src/hyperlight_component_util", version = "0.11.0", default-features = false }

Justfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,7 @@ clippy-exhaustive target=default-target: (witguest-wit)
261261
./hack/clippy-package-features.sh hyperlight-host {{ target }} {{ target-triple }}
262262
./hack/clippy-package-features.sh hyperlight-guest {{ target }}
263263
./hack/clippy-package-features.sh hyperlight-guest-bin {{ target }}
264+
./hack/clippy-package-features.sh hyperlight-guest-macro {{ target }}
264265
./hack/clippy-package-features.sh hyperlight-common {{ target }} {{ target-triple }}
265266
./hack/clippy-package-features.sh hyperlight-testing {{ target }} {{ target-triple }}
266267
./hack/clippy-package-features.sh hyperlight-component-macro {{ target }} {{ target-triple }}

README.md

Lines changed: 16 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -74,54 +74,33 @@ fn main() -> hyperlight_host::Result<()> {
7474
#![no_main]
7575
extern crate alloc;
7676

77-
use alloc::string::ToString;
7877
use alloc::vec::Vec;
78+
use alloc::string::String;
7979
use hyperlight_common::flatbuffer_wrappers::function_call::FunctionCall;
80-
use hyperlight_common::flatbuffer_wrappers::function_types::{
81-
ParameterType, ParameterValue, ReturnType,
82-
};
8380
use hyperlight_common::flatbuffer_wrappers::guest_error::ErrorCode;
84-
use hyperlight_common::flatbuffer_wrappers::util::get_flatbuffer_result;
85-
86-
use hyperlight_guest::error::{HyperlightGuestError, Result};
87-
use hyperlight_guest_bin::guest_function::definition::GuestFunctionDefinition;
88-
use hyperlight_guest_bin::guest_function::register::register_function;
89-
use hyperlight_guest_bin::host_comm::call_host_function;
90-
91-
fn print_output(function_call: &FunctionCall) -> Result<Vec<u8>> {
92-
if let ParameterValue::String(message) = function_call.parameters.clone().unwrap()[0].clone() {
93-
let result = call_host_function::<i32>(
94-
"HostPrint",
95-
Some(Vec::from(&[ParameterValue::String(message.to_string())])),
96-
ReturnType::Int,
97-
)?;
98-
Ok(get_flatbuffer_result(result))
99-
} else {
100-
Err(HyperlightGuestError::new(
101-
ErrorCode::GuestFunctionParameterTypeMismatch,
102-
"Invalid parameters passed to simple_print_output".to_string(),
103-
))
104-
}
81+
82+
use hyperlight_guest::bail;
83+
use hyperlight_guest::error::Result;
84+
use hyperlight_guest_bin::{guest_function, host_function};
85+
86+
#[host_function("HostPrint")]
87+
fn host_print(message: String) -> Result<i32>;
88+
89+
#[guest_function("PrintOutput")]
90+
fn print_output(message: String) -> Result<i32> {
91+
let result = host_print(message)?;
92+
Ok(result)
10593
}
10694

10795
#[no_mangle]
10896
pub extern "C" fn hyperlight_main() {
109-
let print_output_def = GuestFunctionDefinition::new(
110-
"PrintOutput".to_string(),
111-
Vec::from(&[ParameterType::String]),
112-
ReturnType::Int,
113-
print_output as usize,
114-
);
115-
register_function(print_output_def);
97+
// any initialization code goes here
11698
}
11799

118100
#[no_mangle]
119101
pub fn guest_dispatch_function(function_call: FunctionCall) -> Result<Vec<u8>> {
120-
let function_name = function_call.function_name.clone();
121-
return Err(HyperlightGuestError::new(
122-
ErrorCode::GuestFunctionNotFound,
123-
function_name,
124-
));
102+
let function_name = function_call.function_name;
103+
bail!(ErrorCode::GuestFunctionNotFound => "{function_name}");
125104
}
126105
```
127106

src/hyperlight_common/Cargo.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,15 @@ log = "0.4.29"
2121
tracing = { version = "0.1.43", optional = true }
2222
arbitrary = {version = "1.4.2", optional = true, features = ["derive"]}
2323
spin = "0.10.0"
24+
thiserror = { version = "2.0.16", default-features = false }
2425

2526
[features]
2627
default = ["tracing"]
28+
tracing = ["dep:tracing"]
2729
fuzzing = ["dep:arbitrary"]
2830
trace_guest = []
2931
mem_profile = []
30-
std = []
32+
std = ["thiserror/std", "log/std", "tracing/std"]
3133

3234
[lib]
3335
bench = false # see https://bheisler.github.io/criterion.rs/book/faq.html#cargo-bench-gives-unrecognized-option-errors-for-valid-command-line-options
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/*
2+
Copyright 2025 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+
17+
use alloc::string::String;
18+
19+
use thiserror::Error;
20+
21+
use crate::func::{ParameterValue, ReturnValue};
22+
23+
/// The error type for Hyperlight operations
24+
#[derive(Error, Debug)]
25+
pub enum Error {
26+
/// Failed to get value from parameter value
27+
#[error("Failed To Convert Parameter Value {0:?} to {1:?}")]
28+
ParameterValueConversionFailure(ParameterValue, &'static str),
29+
30+
/// Failed to get value from return value
31+
#[error("Failed To Convert Return Value {0:?} to {1:?}")]
32+
ReturnValueConversionFailure(ReturnValue, &'static str),
33+
34+
/// A function was called with an incorrect number of arguments
35+
#[error("The number of arguments to the function is wrong: got {0:?} expected {1:?}")]
36+
UnexpectedNoOfArguments(usize, usize),
37+
38+
/// The parameter value type is unexpected
39+
#[error("The parameter value type is unexpected got {0:?} expected {1:?}")]
40+
UnexpectedParameterValueType(ParameterValue, String),
41+
42+
/// The return value type is unexpected
43+
#[error("The return value type is unexpected got {0:?} expected {1:?}")]
44+
UnexpectedReturnValueType(ReturnValue, String),
45+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/*
2+
Copyright 2025 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+
17+
use super::utils::for_each_tuple;
18+
use super::{Error, ParameterTuple, ResultType, SupportedReturnType};
19+
20+
pub trait Function<Output: SupportedReturnType, Args: ParameterTuple, E: From<Error>> {
21+
fn call(&self, args: Args) -> Result<Output, E>;
22+
}
23+
24+
macro_rules! impl_function {
25+
([$N:expr] ($($p:ident: $P:ident),*)) => {
26+
impl<F, R, E, $($P),*> Function<R::ReturnType, ($($P,)*), E> for F
27+
where
28+
F: Fn($($P),*) -> R,
29+
($($P,)*): ParameterTuple,
30+
R: ResultType<E>,
31+
E: From<Error> + core::fmt::Debug,
32+
{
33+
fn call(&self, ($($p,)*): ($($P,)*)) -> Result<R::ReturnType, E> {
34+
(self)($($p),*).into_result()
35+
}
36+
}
37+
};
38+
}
39+
40+
for_each_tuple!(impl_function);
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/*
2+
Copyright 2025 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+
17+
/// Error types related to function support
18+
pub(crate) mod error;
19+
/// Definitions and functionality to enable guest-to-host function calling,
20+
/// also called "host functions"
21+
///
22+
/// This module includes functionality to do the following
23+
///
24+
/// - Define several prototypes for what a host function must look like,
25+
/// including the number of arguments (arity) they can have, supported argument
26+
/// types, and supported return types
27+
/// - Registering host functions to be callable by the guest
28+
/// - Dynamically dispatching a call from the guest to the appropriate
29+
/// host function
30+
pub(crate) mod functions;
31+
/// Definitions and functionality for supported parameter types
32+
pub(crate) mod param_type;
33+
/// Definitions and functionality for supported return types
34+
pub(crate) mod ret_type;
35+
36+
pub use error::Error;
37+
/// Re-export for `HostFunction` trait
38+
pub use functions::Function;
39+
pub use param_type::{ParameterTuple, SupportedParameterType};
40+
pub use ret_type::{ResultType, SupportedReturnType};
41+
42+
/// Re-export for `ParameterValue` enum
43+
pub use crate::flatbuffer_wrappers::function_types::ParameterValue;
44+
/// Re-export for `ReturnType` enum
45+
pub use crate::flatbuffer_wrappers::function_types::ReturnType;
46+
/// Re-export for `ReturnType` enum
47+
pub use crate::flatbuffer_wrappers::function_types::ReturnValue;
48+
49+
mod utils;

0 commit comments

Comments
 (0)