Skip to content
This repository was archived by the owner on Sep 8, 2025. It is now read-only.

Commit cd5c643

Browse files
authored
Merge pull request #121 from alexcrichton/update-mismatch
Align return code of imports with the spec
2 parents 7335ae7 + 409431d commit cd5c643

8 files changed

Lines changed: 47 additions & 37 deletions

File tree

Cargo.lock

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

crates/environ/src/component/info.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -643,6 +643,7 @@ pub struct Resource {
643643
///
644644
/// Note that this type does not implement `Serialize` or `Deserialize` and
645645
/// that's intentional as this isn't stored in the final compilation artifact.
646+
#[derive(Debug)]
646647
pub enum Trampoline {
647648
/// Description of a lowered import used in conjunction with
648649
/// `GlobalInitializer::LowerImport`.

crates/test-programs/src/bin/async_poll_stackless.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,8 +79,8 @@ unsafe extern "C" fn callback_run(event0: u32, event1: u32, _event2: u32) -> u32
7979

8080
let set = *set;
8181
let result = async_when_ready();
82-
let status = result >> 30;
83-
let call = result & !(0b11 << 30);
82+
let status = result & 0xf;
83+
let call = result >> 4;
8484
assert!(status != STATUS_RETURNED);
8585
waitable_join(call, set);
8686

@@ -117,7 +117,7 @@ unsafe extern "C" fn callback_run(event0: u32, event1: u32, _event2: u32) -> u32
117117
assert_eq!(event0, EVENT_NONE);
118118

119119
let set = *set;
120-
assert!(async_when_ready() == STATUS_RETURNED << 30);
120+
assert!(async_when_ready() == STATUS_RETURNED);
121121

122122
*state = State::S5 { set };
123123

crates/test-programs/src/bin/async_poll_synchronous.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,8 @@ impl Guest for Component {
4545
assert!(waitable_set_poll(set).is_none());
4646

4747
let result = async_when_ready();
48-
let status = result >> 30;
49-
let call = result & !(0b11 << 30);
48+
let status = result & 0xf;
49+
let call = result >> 4;
5050
assert!(status != STATUS_RETURNED);
5151
waitable_join(call, set);
5252

@@ -64,7 +64,7 @@ impl Guest for Component {
6464

6565
assert!(waitable_set_poll(set).is_none());
6666

67-
assert!(async_when_ready() == STATUS_RETURNED << 30);
67+
assert!(async_when_ready() == STATUS_RETURNED);
6868

6969
assert!(waitable_set_poll(set).is_none());
7070

crates/test-programs/src/bin/async_round_trip_many_stackful.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,8 +86,8 @@ unsafe extern "C" fn export_foo(args: *mut u8) {
8686
let results = alloc::alloc(layout);
8787

8888
let result = import_foo(params, results);
89-
let mut status = result >> 30;
90-
let call = result & !(0b11 << 30);
89+
let mut status = result & 0xf;
90+
let call = result >> 4;
9191
let set = waitable_set_new();
9292
if call != 0 {
9393
waitable_join(call, set);

crates/test-programs/src/bin/async_round_trip_stackful.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,8 @@ unsafe extern "C" fn export_foo(ptr: *mut u8, len: usize) {
7272
let results = alloc::alloc(layout);
7373

7474
let result = import_foo(params, results);
75-
let mut status = result >> 30;
76-
let call = result & !(0b11 << 30);
75+
let mut status = result & 0xf;
76+
let call = result >> 4;
7777
let set = waitable_set_new();
7878
if call != 0 {
7979
waitable_join(call, set);

crates/wasmtime/src/runtime/component/concurrent.rs

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -70,12 +70,26 @@ mod ready_chunks;
7070
mod states;
7171
mod table;
7272

73+
/// Corresponds to `CallState` in the upstream spec.
7374
#[derive(Clone, Copy, Eq, PartialEq, Debug)]
74-
#[repr(u32)]
75-
enum Status {
75+
pub enum Status {
7676
Starting = 1,
77-
Started,
78-
Returned,
77+
Started = 2,
78+
Returned = 3,
79+
}
80+
81+
impl Status {
82+
/// Packs this status and the optional `waitable` provided into a 32-bit
83+
/// result that the canonical ABI requires.
84+
///
85+
/// The low 4 bits are reserved for the status while the upper 28 bits are
86+
/// the waitable, if present.
87+
pub fn pack(self, waitable: Option<u32>) -> u32 {
88+
assert!(matches!(self, Status::Returned) == waitable.is_none());
89+
let waitable = waitable.unwrap_or(0);
90+
assert!(waitable < (1 << 28));
91+
(waitable << 4) | (self as u32)
92+
}
7993
}
8094

8195
#[derive(Clone, Copy, Debug)]
@@ -1602,12 +1616,14 @@ impl ComponentInstance {
16021616

16031617
log::trace!("status {status:?} for {}", guest_task.rep());
16041618

1605-
let call = if status != Status::Returned {
1619+
let waitable = if status != Status::Returned {
16061620
if async_caller {
16071621
self.get_mut(guest_task)?.has_suspended = true;
16081622

1609-
self.waitable_tables()[caller_instance]
1610-
.insert(guest_task.rep(), WaitableState::GuestTask)?
1623+
Some(
1624+
self.waitable_tables()[caller_instance]
1625+
.insert(guest_task.rep(), WaitableState::GuestTask)?,
1626+
)
16111627
} else {
16121628
let caller = if let Caller::Guest { task, .. } = &self.get(guest_task)?.caller {
16131629
*task
@@ -1621,10 +1637,10 @@ impl ComponentInstance {
16211637

16221638
self.poll_for_result(guest_task)?;
16231639
status = Status::Returned;
1624-
0
1640+
None
16251641
}
16261642
} else {
1627-
0
1643+
None
16281644
};
16291645

16301646
if let Some(storage) = storage {
@@ -1635,10 +1651,8 @@ impl ComponentInstance {
16351651
} else {
16361652
return Err(anyhow!(crate::Trap::NoAsyncResult));
16371653
}
1638-
Ok(0)
1639-
} else {
1640-
Ok(((status as u32) << 30) | call)
16411654
}
1655+
Ok(status.pack(waitable))
16421656
}
16431657

16441658
pub(crate) fn wrap_call<T, F, P, R>(

crates/wasmtime/src/runtime/component/func/host.rs

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#[cfg(feature = "component-model-async")]
2-
use crate::component::concurrent::Accessor;
2+
use crate::component::concurrent::{Accessor, Status};
33
use crate::component::func::{LiftContext, LowerContext, Options};
44
use crate::component::matching::InstanceType;
55
use crate::component::storage::slice_to_storage_mut;
@@ -23,11 +23,6 @@ use wasmtime_environ::component::{
2323
TypeFuncIndex, MAX_FLAT_PARAMS, MAX_FLAT_RESULTS,
2424
};
2525

26-
#[cfg(feature = "component-model-async")]
27-
const STATUS_PARAMS_READ: u32 = 1;
28-
#[cfg(feature = "component-model-async")]
29-
const STATUS_DONE: u32 = 3;
30-
3126
pub struct HostFunc {
3227
entrypoint: VMLoweringCallee,
3328
typecheck: Box<dyn (Fn(TypeFuncIndex, &InstanceType<'_>) -> Result<()>) + Send + Sync>,
@@ -335,9 +330,9 @@ where
335330
})?;
336331

337332
let status = if let Some(task) = task {
338-
(STATUS_PARAMS_READ << 30) | task
333+
Status::Started.pack(Some(task))
339334
} else {
340-
STATUS_DONE << 30
335+
Status::Returned.pack(None)
341336
};
342337

343338
storage[0] = MaybeUninit::new(ValRaw::i32(status as i32));
@@ -591,9 +586,9 @@ where
591586
})?;
592587

593588
let status = if let Some(task) = task {
594-
(STATUS_PARAMS_READ << 30) | task
589+
Status::Started.pack(Some(task))
595590
} else {
596-
STATUS_DONE << 30
591+
Status::Returned.pack(None)
597592
};
598593

599594
storage[0] = MaybeUninit::new(ValRaw::i32(status as i32));

0 commit comments

Comments
 (0)