1 #![allow(non_camel_case_types)] 2 3 pub use self::lucet_result::*; 4 pub use self::lucet_val::*; 5 6 use crate::alloc::Limits; 7 use crate::error::Error; 8 use crate::instance::signals::SignalBehavior; 9 use libc::{c_int, c_void}; 10 use num_derive::FromPrimitive; 11 12 #[macro_export] 13 macro_rules! assert_nonnull { 14 ( $name:ident ) => { 15 if $name.is_null() { 16 return lucet_error::InvalidArgument; 17 } 18 }; 19 } 20 21 /// Wrap up the management of `Arc`s that go across the FFI boundary. 22 /// 23 /// Trait objects must be wrapped in two `Arc`s in order to yield a thin pointer. 24 #[macro_export] 25 macro_rules! with_ffi_arcs { 26 ( [ $name:ident : dyn $ty:ident ], $body:block ) => {{ 27 assert_nonnull!($name); 28 let $name = Arc::from_raw($name as *const Arc<dyn $ty>); 29 let res = $body; 30 Arc::into_raw($name); 31 res 32 }}; 33 ( [ $name:ident : $ty:ty ], $body:block ) => {{ 34 assert_nonnull!($name); 35 let $name = Arc::from_raw($name as *const $ty); 36 let res = $body; 37 Arc::into_raw($name); 38 res 39 }}; 40 ( [ $name:ident : dyn $ty:ident, $($tail:tt)* ], $body:block ) => {{ 41 assert_nonnull!($name); 42 let $name = Arc::from_raw($name as *const Arc<dyn $ty>); 43 let rec = with_ffi_arcs!([$($tail)*], $body); 44 Arc::into_raw($name); 45 rec 46 }}; 47 ( [ $name:ident : $ty:ty, $($tail:tt)* ], $body:block ) => {{ 48 assert_nonnull!($name); 49 let $name = Arc::from_raw($name as *const $ty); 50 let rec = with_ffi_arcs!([$($tail)*], $body); 51 Arc::into_raw($name); 52 rec 53 }}; 54 } 55 56 /// Marker type for the `vmctx` pointer argument. 57 /// 58 /// This type should only be used with [`Vmctx::from_raw()`](struct.Vmctx.html#method.from_raw) or 59 /// the C API. 60 #[repr(C)] 61 pub struct lucet_vmctx { 62 _unused: [u8; 0], 63 } 64 65 #[repr(C)] 66 #[derive(Clone, Copy, Debug, FromPrimitive)] 67 pub enum lucet_error { 68 Ok, 69 InvalidArgument, 70 RegionFull, 71 Module, 72 LimitsExceeded, 73 NoLinearMemory, 74 SymbolNotFound, 75 FuncNotFound, 76 RuntimeFault, 77 RuntimeTerminated, 78 Dl, 79 InstanceNotReturned, 80 InstanceNotYielded, 81 StartYielded, 82 Internal, 83 Unsupported, 84 } 85 86 impl From<Error> for lucet_error { from(e: Error) -> lucet_error87 fn from(e: Error) -> lucet_error { 88 lucet_error::from(&e) 89 } 90 } 91 92 impl From<&Error> for lucet_error { from(e: &Error) -> lucet_error93 fn from(e: &Error) -> lucet_error { 94 match e { 95 Error::InvalidArgument(_) => lucet_error::InvalidArgument, 96 Error::RegionFull(_) => lucet_error::RegionFull, 97 Error::ModuleError(_) => lucet_error::Module, 98 Error::LimitsExceeded(_) => lucet_error::LimitsExceeded, 99 Error::NoLinearMemory(_) => lucet_error::NoLinearMemory, 100 Error::SymbolNotFound(_) => lucet_error::SymbolNotFound, 101 Error::FuncNotFound(_, _) => lucet_error::FuncNotFound, 102 Error::RuntimeFault(_) => lucet_error::RuntimeFault, 103 Error::RuntimeTerminated(_) => lucet_error::RuntimeTerminated, 104 Error::DlError(_) => lucet_error::Dl, 105 Error::InstanceNotReturned => lucet_error::InstanceNotReturned, 106 Error::InstanceNotYielded => lucet_error::InstanceNotYielded, 107 Error::StartYielded => lucet_error::StartYielded, 108 Error::InternalError(_) => lucet_error::Internal, 109 Error::Unsupported(_) => lucet_error::Unsupported, 110 } 111 } 112 } 113 114 #[repr(C)] 115 pub struct lucet_instance { 116 _unused: [u8; 0], 117 } 118 119 #[repr(C)] 120 pub struct lucet_region { 121 _unused: [u8; 0], 122 } 123 124 #[repr(C)] 125 pub struct lucet_dl_module { 126 _unused: [u8; 0], 127 } 128 129 /// Runtime limits for the various memories that back a Lucet instance. 130 /// 131 /// Each value is specified in bytes, and must be evenly divisible by the host page size (4K). 132 #[derive(Clone, Debug)] 133 #[repr(C)] 134 pub struct lucet_alloc_limits { 135 /// Max size of the heap, which can be backed by real memory. (default 1M) 136 pub heap_memory_size: u64, 137 /// Size of total virtual memory. (default 8G) 138 pub heap_address_space_size: u64, 139 /// Size of the guest stack. (default 128K) 140 pub stack_size: u64, 141 /// Size of the globals region in bytes; each global uses 8 bytes. (default 4K) 142 pub globals_size: u64, 143 /// Size of the signal stack in bytes. (default SIGSTKSZ for Rust release builds, 12K for Rust 144 /// debug builds) 145 /// 146 /// This difference is to account for the greatly increased stack size usage in the signal 147 /// handler when running without optimizations. 148 /// 149 /// Note that debug vs. release mode is determined by `cfg(debug_assertions)`, so if you are 150 /// specifically enabling Rust debug assertions in your Cargo release builds, the default signal 151 /// stack will be larger. 152 pub signal_stack_size: u64, 153 } 154 155 impl From<Limits> for lucet_alloc_limits { from(limits: Limits) -> lucet_alloc_limits156 fn from(limits: Limits) -> lucet_alloc_limits { 157 (&limits).into() 158 } 159 } 160 161 impl From<&Limits> for lucet_alloc_limits { from(limits: &Limits) -> lucet_alloc_limits162 fn from(limits: &Limits) -> lucet_alloc_limits { 163 lucet_alloc_limits { 164 heap_memory_size: limits.heap_memory_size as u64, 165 heap_address_space_size: limits.heap_address_space_size as u64, 166 stack_size: limits.stack_size as u64, 167 globals_size: limits.globals_size as u64, 168 signal_stack_size: limits.signal_stack_size as u64, 169 } 170 } 171 } 172 173 impl From<lucet_alloc_limits> for Limits { from(limits: lucet_alloc_limits) -> Limits174 fn from(limits: lucet_alloc_limits) -> Limits { 175 (&limits).into() 176 } 177 } 178 179 impl From<&lucet_alloc_limits> for Limits { from(limits: &lucet_alloc_limits) -> Limits180 fn from(limits: &lucet_alloc_limits) -> Limits { 181 Limits { 182 heap_memory_size: limits.heap_memory_size as usize, 183 heap_address_space_size: limits.heap_address_space_size as usize, 184 stack_size: limits.stack_size as usize, 185 globals_size: limits.globals_size as usize, 186 signal_stack_size: limits.signal_stack_size as usize, 187 } 188 } 189 } 190 191 #[repr(C)] 192 #[derive(Clone, Copy, Debug)] 193 pub enum lucet_signal_behavior { 194 Default, 195 Continue, 196 Terminate, 197 } 198 199 impl From<lucet_signal_behavior> for SignalBehavior { from(sb: lucet_signal_behavior) -> SignalBehavior200 fn from(sb: lucet_signal_behavior) -> SignalBehavior { 201 sb.into() 202 } 203 } 204 205 impl From<&lucet_signal_behavior> for SignalBehavior { from(sb: &lucet_signal_behavior) -> SignalBehavior206 fn from(sb: &lucet_signal_behavior) -> SignalBehavior { 207 match sb { 208 lucet_signal_behavior::Default => SignalBehavior::Default, 209 lucet_signal_behavior::Continue => SignalBehavior::Continue, 210 lucet_signal_behavior::Terminate => SignalBehavior::Terminate, 211 } 212 } 213 } 214 215 pub type lucet_signal_handler = unsafe extern "C" fn( 216 inst: *mut lucet_instance, 217 trap: lucet_result::lucet_trapcode, 218 signum: c_int, 219 siginfo: *const libc::siginfo_t, 220 context: *const c_void, 221 ) -> lucet_signal_behavior; 222 223 pub type lucet_fatal_handler = unsafe extern "C" fn(inst: *mut lucet_instance); 224 225 pub struct CTerminationDetails { 226 pub details: *mut c_void, 227 } 228 229 unsafe impl Send for CTerminationDetails {} 230 unsafe impl Sync for CTerminationDetails {} 231 232 pub struct CYieldedVal { 233 pub val: *mut c_void, 234 } 235 236 unsafe impl Send for CYieldedVal {} 237 unsafe impl Sync for CYieldedVal {} 238 239 pub mod lucet_result { 240 use super::lucet_error; 241 use crate::c_api::{lucet_val, CTerminationDetails, CYieldedVal}; 242 use crate::error::Error; 243 use crate::instance::{RunResult, TerminationDetails}; 244 use crate::module::{AddrDetails, TrapCode}; 245 use libc::{c_uchar, c_void}; 246 use num_derive::FromPrimitive; 247 use std::ffi::CString; 248 use std::ptr; 249 250 impl From<Result<RunResult, Error>> for lucet_result { from(res: Result<RunResult, Error>) -> lucet_result251 fn from(res: Result<RunResult, Error>) -> lucet_result { 252 match res { 253 Ok(RunResult::Returned(retval)) => lucet_result { 254 tag: lucet_result_tag::Returned, 255 val: lucet_result_val { 256 returned: retval.into(), 257 }, 258 }, 259 Ok(RunResult::Yielded(val)) => lucet_result { 260 tag: lucet_result_tag::Yielded, 261 val: lucet_result_val { 262 yielded: lucet_yielded { 263 val: val 264 .downcast_ref() 265 .map(|CYieldedVal { val }| *val) 266 .unwrap_or(ptr::null_mut()), 267 }, 268 }, 269 }, 270 // TODO: test this path; currently our C API tests don't include any faulting tests 271 Err(Error::RuntimeFault(details)) => lucet_result { 272 tag: lucet_result_tag::Faulted, 273 val: lucet_result_val { 274 fault: lucet_runtime_faulted { 275 fatal: details.fatal, 276 trapcode: details.trapcode.into(), 277 rip_addr: details.rip_addr, 278 rip_addr_details: details.rip_addr_details.into(), 279 }, 280 }, 281 }, 282 // TODO: test this path; currently our C API tests don't include any terminating tests 283 Err(Error::RuntimeTerminated(details)) => lucet_result { 284 tag: lucet_result_tag::Terminated, 285 val: lucet_result_val { 286 terminated: match details { 287 TerminationDetails::Signal => lucet_terminated { 288 reason: lucet_terminated_reason::Signal, 289 provided: ptr::null_mut(), 290 }, 291 TerminationDetails::CtxNotFound => lucet_terminated { 292 reason: lucet_terminated_reason::CtxNotFound, 293 provided: ptr::null_mut(), 294 }, 295 TerminationDetails::YieldTypeMismatch => lucet_terminated { 296 reason: lucet_terminated_reason::YieldTypeMismatch, 297 provided: ptr::null_mut(), 298 }, 299 TerminationDetails::BorrowError(_) => lucet_terminated { 300 reason: lucet_terminated_reason::BorrowError, 301 provided: ptr::null_mut(), 302 }, 303 TerminationDetails::Provided(p) => lucet_terminated { 304 reason: lucet_terminated_reason::Provided, 305 provided: p 306 .downcast_ref() 307 .map(|CTerminationDetails { details }| *details) 308 .unwrap_or(ptr::null_mut()), 309 }, 310 }, 311 }, 312 }, 313 Err(e) => lucet_result { 314 tag: lucet_result_tag::Errored, 315 val: lucet_result_val { errored: e.into() }, 316 }, 317 } 318 } 319 } 320 321 #[repr(C)] 322 #[derive(Clone, Copy)] 323 pub struct lucet_result { 324 pub tag: lucet_result_tag, 325 pub val: lucet_result_val, 326 } 327 328 #[repr(C)] 329 #[derive(Clone, Copy, Debug, FromPrimitive)] 330 pub enum lucet_result_tag { 331 Returned, 332 Yielded, 333 Faulted, 334 Terminated, 335 Errored, 336 } 337 338 #[repr(C)] 339 #[derive(Clone, Copy)] 340 pub union lucet_result_val { 341 pub returned: lucet_val::lucet_untyped_retval, 342 pub yielded: lucet_yielded, 343 pub fault: lucet_runtime_faulted, 344 pub terminated: lucet_terminated, 345 pub errored: lucet_error, 346 } 347 348 #[repr(C)] 349 #[derive(Clone, Copy)] 350 pub struct lucet_terminated { 351 pub reason: lucet_terminated_reason, 352 pub provided: *mut c_void, 353 } 354 355 #[repr(C)] 356 #[derive(Clone, Copy)] 357 pub enum lucet_terminated_reason { 358 Signal, 359 CtxNotFound, 360 YieldTypeMismatch, 361 BorrowError, 362 Provided, 363 } 364 365 #[repr(C)] 366 #[derive(Clone, Copy)] 367 pub struct lucet_yielded { 368 pub val: *mut c_void, 369 } 370 371 #[repr(C)] 372 #[derive(Clone, Copy)] 373 pub struct lucet_runtime_faulted { 374 pub fatal: bool, 375 pub trapcode: lucet_trapcode, 376 pub rip_addr: libc::uintptr_t, 377 pub rip_addr_details: lucet_module_addr_details, 378 } 379 380 #[repr(C)] 381 #[derive(Clone, Copy, Debug)] 382 pub enum lucet_trapcode { 383 StackOverflow, 384 HeapOutOfBounds, 385 OutOfBounds, 386 IndirectCallToNull, 387 BadSignature, 388 IntegerOverflow, 389 IntegerDivByZero, 390 BadConversionToInteger, 391 Interrupt, 392 TableOutOfBounds, 393 Unreachable, 394 Unknown, 395 } 396 397 impl From<Option<TrapCode>> for lucet_trapcode { from(ty: Option<TrapCode>) -> lucet_trapcode398 fn from(ty: Option<TrapCode>) -> lucet_trapcode { 399 (&ty).into() 400 } 401 } 402 403 impl From<&Option<TrapCode>> for lucet_trapcode { from(ty: &Option<TrapCode>) -> lucet_trapcode404 fn from(ty: &Option<TrapCode>) -> lucet_trapcode { 405 if let Some(ty) = ty { 406 match ty { 407 TrapCode::StackOverflow => lucet_trapcode::StackOverflow, 408 TrapCode::HeapOutOfBounds => lucet_trapcode::HeapOutOfBounds, 409 TrapCode::OutOfBounds => lucet_trapcode::OutOfBounds, 410 TrapCode::IndirectCallToNull => lucet_trapcode::IndirectCallToNull, 411 TrapCode::BadSignature => lucet_trapcode::BadSignature, 412 TrapCode::IntegerOverflow => lucet_trapcode::IntegerOverflow, 413 TrapCode::IntegerDivByZero => lucet_trapcode::IntegerDivByZero, 414 TrapCode::BadConversionToInteger => lucet_trapcode::BadConversionToInteger, 415 TrapCode::Interrupt => lucet_trapcode::Interrupt, 416 TrapCode::TableOutOfBounds => lucet_trapcode::TableOutOfBounds, 417 TrapCode::Unreachable => lucet_trapcode::Unreachable, 418 } 419 } else { 420 lucet_trapcode::Unknown 421 } 422 } 423 } 424 425 const ADDR_DETAILS_NAME_LEN: usize = 256; 426 427 /// Half a kilobyte is too substantial for `Copy`, but we must have it because [unions with 428 /// non-`Copy` fields are unstable](https://github.com/rust-lang/rust/issues/32836). 429 #[repr(C)] 430 #[derive(Clone, Copy)] 431 pub struct lucet_module_addr_details { 432 pub module_code_resolvable: bool, 433 pub in_module_code: bool, 434 pub file_name: [c_uchar; ADDR_DETAILS_NAME_LEN], 435 pub sym_name: [c_uchar; ADDR_DETAILS_NAME_LEN], 436 } 437 438 impl Default for lucet_module_addr_details { default() -> Self439 fn default() -> Self { 440 lucet_module_addr_details { 441 module_code_resolvable: false, 442 in_module_code: false, 443 file_name: [0; ADDR_DETAILS_NAME_LEN], 444 sym_name: [0; ADDR_DETAILS_NAME_LEN], 445 } 446 } 447 } 448 449 impl From<Option<AddrDetails>> for lucet_module_addr_details { from(details: Option<AddrDetails>) -> Self450 fn from(details: Option<AddrDetails>) -> Self { 451 /// Convert a string into C-compatible bytes, truncate it to length 452 /// `ADDR_DETAILS_NAME_LEN`, and make sure it has a trailing nul. 453 fn trunc_c_str_bytes(s: &str) -> Vec<u8> { 454 let s = CString::new(s); 455 let mut bytes = s.ok().map(|s| s.into_bytes_with_nul()).unwrap_or(vec![0]); 456 bytes.truncate(ADDR_DETAILS_NAME_LEN); 457 // we always have at least the 0, so this `last` can be unwrapped 458 *bytes.last_mut().unwrap() = 0; 459 bytes 460 } 461 462 let mut ret = details 463 .as_ref() 464 .map(|details| lucet_module_addr_details { 465 module_code_resolvable: true, 466 in_module_code: details.in_module_code, 467 file_name: [0; ADDR_DETAILS_NAME_LEN], 468 sym_name: [0; ADDR_DETAILS_NAME_LEN], 469 }) 470 .unwrap_or_default(); 471 472 // get truncated C-compatible bytes for each string, or "\0" if they're not present 473 let file_name_bytes = details 474 .as_ref() 475 .and_then(|details| details.file_name.as_ref().map(|s| trunc_c_str_bytes(s))) 476 .unwrap_or_else(|| vec![0]); 477 let sym_name_bytes = details 478 .and_then(|details| details.sym_name.as_ref().map(|s| trunc_c_str_bytes(s))) 479 .unwrap_or_else(|| vec![0]); 480 481 // copy the bytes into the array, making sure to copy only as many as are in the string 482 ret.file_name[0..file_name_bytes.len()].copy_from_slice(file_name_bytes.as_slice()); 483 ret.sym_name[0..sym_name_bytes.len()].copy_from_slice(sym_name_bytes.as_slice()); 484 485 ret 486 } 487 } 488 } 489 490 pub mod lucet_val { 491 use crate::val::{UntypedRetVal, UntypedRetValInternal, Val}; 492 use libc::{c_char, c_void}; 493 494 // Note on the value associated with each type: the most significant bits represent the "class" 495 // of the type (1: a C pointer, 2: something unsigned that fits in 64 bits, 3: something signed 496 // that fits in 64 bits, 4: f32, 5: f64). The remain bits can be anything as long as it is 497 // unique. 498 #[repr(C)] 499 #[derive(Clone, Copy, Debug)] 500 pub enum lucet_val_type { 501 C_Ptr, // = (1 << 16) | 0x0100, 502 GuestPtr, // = (2 << 16) | 0x0101, 503 U8, // = (2 << 16) | 0x0201, 504 U16, // = (2 << 16) | 0x0202, 505 U32, // = (2 << 16) | 0x0203, 506 U64, // = (2 << 16) | 0x0204, 507 I8, // = (3 << 16) | 0x0300, 508 I16, // = (3 << 16) | 0x0301, 509 I32, // = (3 << 16) | 0x0302, 510 I64, // = (3 << 16) | 0x0303, 511 USize, // = (2 << 16) | 0x0400, 512 ISize, // = (3 << 16) | 0x0401, 513 Bool, // = (2 << 16) | 0x0700, 514 F32, // = (4 << 16) | 0x0800, 515 F64, // = (5 << 16) | 0x0801, 516 } 517 518 #[repr(C)] 519 #[derive(Clone, Copy)] 520 pub union lucet_val_inner_val { 521 as_c_ptr: *mut c_void, // (1 << 16) 522 as_u64: u64, // (2 << 16) 523 as_i64: i64, // (3 << 16) 524 as_f32: f32, // (4 << 16) 525 as_f64: f64, // (5 << 16) 526 } 527 528 #[repr(C)] 529 #[derive(Clone, Copy)] 530 pub struct lucet_val { 531 ty: lucet_val_type, 532 inner_val: lucet_val_inner_val, 533 } 534 535 impl From<lucet_val> for Val { from(val: lucet_val) -> Val536 fn from(val: lucet_val) -> Val { 537 (&val).into() 538 } 539 } 540 541 impl From<&lucet_val> for Val { from(val: &lucet_val) -> Val542 fn from(val: &lucet_val) -> Val { 543 match val.ty { 544 lucet_val_type::C_Ptr => Val::CPtr(unsafe { val.inner_val.as_u64 } as _), 545 lucet_val_type::GuestPtr => Val::GuestPtr(unsafe { val.inner_val.as_u64 } as _), 546 lucet_val_type::U8 => Val::U8(unsafe { val.inner_val.as_u64 } as _), 547 lucet_val_type::U16 => Val::U16(unsafe { val.inner_val.as_u64 } as _), 548 lucet_val_type::U32 => Val::U32(unsafe { val.inner_val.as_u64 } as _), 549 lucet_val_type::U64 => Val::U64(unsafe { val.inner_val.as_u64 } as _), 550 lucet_val_type::I8 => Val::I16(unsafe { val.inner_val.as_i64 } as _), 551 lucet_val_type::I16 => Val::I32(unsafe { val.inner_val.as_i64 } as _), 552 lucet_val_type::I32 => Val::I32(unsafe { val.inner_val.as_i64 } as _), 553 lucet_val_type::I64 => Val::I64(unsafe { val.inner_val.as_i64 } as _), 554 lucet_val_type::USize => Val::USize(unsafe { val.inner_val.as_u64 } as _), 555 lucet_val_type::ISize => Val::ISize(unsafe { val.inner_val.as_i64 } as _), 556 lucet_val_type::Bool => Val::Bool(unsafe { val.inner_val.as_u64 } != 0), 557 lucet_val_type::F32 => Val::F32(unsafe { val.inner_val.as_f32 } as _), 558 lucet_val_type::F64 => Val::F64(unsafe { val.inner_val.as_f64 } as _), 559 } 560 } 561 } 562 563 impl From<Val> for lucet_val { from(val: Val) -> Self564 fn from(val: Val) -> Self { 565 (&val).into() 566 } 567 } 568 569 impl From<&Val> for lucet_val { from(val: &Val) -> Self570 fn from(val: &Val) -> Self { 571 match val { 572 Val::CPtr(a) => lucet_val { 573 ty: lucet_val_type::C_Ptr, 574 inner_val: lucet_val_inner_val { as_u64: *a as _ }, 575 }, 576 Val::GuestPtr(a) => lucet_val { 577 ty: lucet_val_type::GuestPtr, 578 inner_val: lucet_val_inner_val { as_u64: *a as _ }, 579 }, 580 Val::U8(a) => lucet_val { 581 ty: lucet_val_type::U8, 582 inner_val: lucet_val_inner_val { as_u64: *a as _ }, 583 }, 584 Val::U16(a) => lucet_val { 585 ty: lucet_val_type::U16, 586 inner_val: lucet_val_inner_val { as_u64: *a as _ }, 587 }, 588 Val::U32(a) => lucet_val { 589 ty: lucet_val_type::U32, 590 inner_val: lucet_val_inner_val { as_u64: *a as _ }, 591 }, 592 Val::U64(a) => lucet_val { 593 ty: lucet_val_type::U64, 594 inner_val: lucet_val_inner_val { as_u64: *a as _ }, 595 }, 596 Val::I8(a) => lucet_val { 597 ty: lucet_val_type::I8, 598 inner_val: lucet_val_inner_val { as_i64: *a as _ }, 599 }, 600 Val::I16(a) => lucet_val { 601 ty: lucet_val_type::I16, 602 inner_val: lucet_val_inner_val { as_i64: *a as _ }, 603 }, 604 Val::I32(a) => lucet_val { 605 ty: lucet_val_type::I32, 606 inner_val: lucet_val_inner_val { as_i64: *a as _ }, 607 }, 608 Val::I64(a) => lucet_val { 609 ty: lucet_val_type::I64, 610 inner_val: lucet_val_inner_val { as_i64: *a as _ }, 611 }, 612 Val::USize(a) => lucet_val { 613 ty: lucet_val_type::USize, 614 inner_val: lucet_val_inner_val { as_u64: *a as _ }, 615 }, 616 Val::ISize(a) => lucet_val { 617 ty: lucet_val_type::ISize, 618 inner_val: lucet_val_inner_val { as_i64: *a as _ }, 619 }, 620 Val::Bool(a) => lucet_val { 621 ty: lucet_val_type::Bool, 622 inner_val: lucet_val_inner_val { as_u64: *a as _ }, 623 }, 624 Val::F32(a) => lucet_val { 625 ty: lucet_val_type::F32, 626 inner_val: lucet_val_inner_val { as_f32: *a as _ }, 627 }, 628 Val::F64(a) => lucet_val { 629 ty: lucet_val_type::F64, 630 inner_val: lucet_val_inner_val { as_f64: *a as _ }, 631 }, 632 } 633 } 634 } 635 636 #[repr(C)] 637 #[derive(Clone, Copy, Debug)] 638 pub struct lucet_untyped_retval { 639 pub fp: [c_char; 16], 640 pub gp: [c_char; 8], 641 } 642 643 #[repr(C)] 644 #[derive(Clone, Copy)] 645 pub union lucet_retval_gp { 646 pub as_untyped: [c_char; 8], 647 pub as_c_ptr: *mut c_void, 648 pub as_u64: u64, 649 pub as_i64: i64, 650 } 651 652 impl From<UntypedRetVal> for lucet_untyped_retval { from(retval: UntypedRetVal) -> lucet_untyped_retval653 fn from(retval: UntypedRetVal) -> lucet_untyped_retval { 654 let mut v = lucet_untyped_retval { 655 fp: [0; 16], 656 gp: [0; 8], 657 }; 658 unsafe { 659 core::arch::x86_64::_mm_storeu_ps( 660 v.fp.as_mut().as_mut_ptr() as *mut f32, 661 retval.fp(), 662 ); 663 *(v.gp.as_mut().as_mut_ptr() as *mut u64) = retval.gp(); 664 } 665 v 666 } 667 } 668 } 669