Skip to content
Draft
6 changes: 3 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ publish = false
serde = { version = "1.0", default-features = false, features = ["derive", "alloc"] }
serde_json = { version = "1.0.150", default-features = false, features = ["alloc"] }
enum-field-getter = { path = "enum-field-getter" }
wasm-encoder = "0.245.1"
wasm-encoder = "0.258.0"
indexmap = { version = "2.14.0", default-features = false }
hashers = "1.0.1"
uuid = { version = "1.23.3", default-features = false, features = ["v4", "js"] }
Expand All @@ -22,8 +22,8 @@ wasm-gen = { path = "wasm-gen", version = "0.2.0" }
petgraph = { version = "0.8.1", default-features = false, features = ["stable_graph"] }

[dev-dependencies]
wasmparser = { git = "https://github.com/pufferfish101007/wasm-tools.git", rev = "4e9ffc0" }
wasmprinter = "0.245.1"
wasmparser = "0.258.0"
wasmprinter = "0.258.0"

[target.'cfg(not(target_family = "wasm"))'.dev-dependencies]
# ezno-checker = { git = "https://github.com/kaleidawave/ezno.git", rev = "96d5058bdbb0cde924be008ca1e5a67fe39f46b9" }
Expand Down
2 changes: 1 addition & 1 deletion rust-toolchain.toml
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
[toolchain]
channel = "nightly-2026-08-07"
channel = "nightly-2026-08-31"
targets = [ "wasm32-unknown-unknown" ]
65 changes: 48 additions & 17 deletions src/instructions/control/stop_all.rs
Original file line number Diff line number Diff line change
@@ -1,30 +1,61 @@
use wasm_encoder::{ConstExpr, HeapType};
use wasm_encoder::HeapType;

use super::super::prelude::*;
use crate::instructions_test;
use crate::wasm::{GlobalExportable, GlobalMutable, ThreadsTable};
use crate::wasm::registries::functions::static_functions::DynArrayClear;
use crate::wasm::registries::types::{TNullable, TTargetThreadArray, TThreadArray};

pub fn wasm(func: &StepFunc, _inputs: Rc<[IrType]>) -> HQResult<Vec<InternalInstruction>> {
let threads_count = func.registries().globals().register(
"threads_count".into(),
(
ValType::I32,
ConstExpr::i32_const(0),
GlobalMutable(true),
GlobalExportable(true),
),
)?;

let threads_table = func.registries().tables().register::<ThreadsTable, _>()?;
let thread_struct_type = func.registries().types().thread_struct_type()?;

Ok(wasm![
fn clear_thread(
threads_count: u32,
threads_table: u32,
thread_struct_type: u32,
) -> Vec<InternalInstruction> {
wasm![
I32Const(0),
#LazyGlobalSet(threads_count),
I32Const(0),
RefNull(HeapType::Concrete(thread_struct_type)),
TableSize(threads_table),
TableFill(threads_table),
]
}

pub fn wasm(func: &StepFunc, _inputs: Rc<[IrType]>) -> HQResult<Vec<InternalInstruction>> {
let local_target_counter = func.local(ValType::I32)?;
func.free_local(local_target_counter)?;
let threadss_global = func
.registries()
.globals()
.threadss(func.registries().types(), func.costume_names().len() as u32)?;
let total_threads_count = func.registries().globals().threads_count()?;
let num_targets = 1 + func.costume_names().len() as i32;
let array_type = func
.registries()
.types()
.register_comp::<TTargetThreadArray, _>()?;
let dyn_array_clear = func
.registries()
.static_functions()
.register::<DynArrayClear<TNullable<TThreadArray>>, _>()?;

Ok(wasm![
I32Const(0),
#LazyGlobalSet(total_threads_count),
I32Const(0),
LocalSet(local_target_counter),
Loop(wasm_encoder::BlockType::Empty),
#LazyGlobalGet(threadss_global),
LocalGet(local_target_counter),
ArrayGet(array_type),
#StaticFunctionCall(dyn_array_clear),
LocalGet(local_target_counter),
I32Const(1),
I32Add,
LocalTee(local_target_counter),
I32Const(num_targets),
I32LtS,
BrIf(0),
End,
])
}

Expand Down
103 changes: 54 additions & 49 deletions src/instructions/event/poll_waiting_threads.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,45 +4,48 @@
//!
//! Returns 1 if still waiting on any threads, 0 otherwise.

use wasm_encoder::{BlockType as WasmBlockType, FieldType, HeapType, StorageType};
use wasm_encoder::BlockType as WasmBlockType;

use super::super::prelude::*;
use crate::wasm::{StepFunc, ThreadsTable};
use crate::wasm::StepFunc;
use crate::wasm::registries::functions::static_functions::DynArrayLen;
use crate::wasm::registries::types::{
TArray, TConstField, THeapType, TMutField, TNonNullable, TNullable, TStackArray, TStackStruct,

Check failure on line 13 in src/instructions/event/poll_waiting_threads.rs

View workflow job for this annotation

GitHub Actions / Build check

unresolved imports `crate::wasm::registries::types::THeapType`, `crate::wasm::registries::types::TValType`

Check failure on line 13 in src/instructions/event/poll_waiting_threads.rs

View workflow job for this annotation

GitHub Actions / Lint (clippy)

unresolved imports `crate::wasm::registries::types::THeapType`, `crate::wasm::registries::types::TValType`

Check failure on line 13 in src/instructions/event/poll_waiting_threads.rs

View workflow job for this annotation

GitHub Actions / Run rust unit tests

unresolved imports `crate::wasm::registries::types::THeapType`, `crate::wasm::registries::types::TValType`

Check failure on line 13 in src/instructions/event/poll_waiting_threads.rs

View workflow job for this annotation

GitHub Actions / Build WASM & website

unresolved imports `crate::wasm::registries::types::THeapType`, `crate::wasm::registries::types::TValType`

Check failure on line 13 in src/instructions/event/poll_waiting_threads.rs

View workflow job for this annotation

GitHub Actions / Run integration tests

unresolved imports `crate::wasm::registries::types::THeapType`, `crate::wasm::registries::types::TValType`

Check failure on line 13 in src/instructions/event/poll_waiting_threads.rs

View workflow job for this annotation

GitHub Actions / Lint (clippy)

unresolved imports `crate::wasm::registries::types::THeapType`, `crate::wasm::registries::types::TValType`

Check failure on line 13 in src/instructions/event/poll_waiting_threads.rs

View workflow job for this annotation

GitHub Actions / Build check

unresolved imports `crate::wasm::registries::types::THeapType`, `crate::wasm::registries::types::TValType`

Check failure on line 13 in src/instructions/event/poll_waiting_threads.rs

View workflow job for this annotation

GitHub Actions / Run rust unit tests

unresolved imports `crate::wasm::registries::types::THeapType`, `crate::wasm::registries::types::TValType`

Check failure on line 13 in src/instructions/event/poll_waiting_threads.rs

View workflow job for this annotation

GitHub Actions / Run integration tests

unresolved imports `crate::wasm::registries::types::THeapType`, `crate::wasm::registries::types::TValType`
TStruct, TValType,
};

type TWaitingThreadArray = TArray<TMutField<TNullable<TStackArray>>>;
type TPollStruct = TStruct<((), TConstField<TNonNullable<TWaitingThreadArray>>)>;

pub fn wasm(func: &StepFunc, _inputs: Rc<[IrType]>) -> HQResult<Vec<InternalInstruction>> {
let i32_array_type = func
.registries()
.types()
.array(StorageType::Val(ValType::I32), true)?;
let poll_struct_type = func.registries().types().struct_(vec![FieldType {
mutable: false,
element_type: StorageType::Val(ValType::Ref(RefType {
nullable: false,
heap_type: HeapType::Concrete(i32_array_type),
})),
}])?;

let arr_local = func.local(ValType::Ref(RefType {
nullable: false,
heap_type: HeapType::Concrete(i32_array_type),
}))?;
let types = Rc::clone(func.registries().types());

let thread_array_type = types.register_comp::<TWaitingThreadArray, _>()?;
let poll_struct_type = types.register_comp::<TPollStruct, _>()?;

let arr_local = func.local(<TNonNullable<TWaitingThreadArray>>::val_type(&types)?)?;
func.free_local(arr_local)?;

let arr_len_local = func.local(ValType::I32)?;
let i_local = func.local(ValType::I32)?;
let stack_local = func.local(<TNullable<TStackStruct>>::val_type(&types)?)?;
let wait_local = func.local(ValType::I32)?;
func.free_local(arr_len_local)?;
func.free_local(stack_local)?;
func.free_local(i_local)?;
func.free_local(wait_local)?;

let threads_table = func.registries().tables().register::<ThreadsTable, _>()?;
let dyn_array_len = func
.registries()
.static_functions()
.register::<DynArrayLen<TNullable<TStackArray>>, _>()?;

Ok(wasm![
LocalGet(1), // this should never have additional function arguments so this is fine
RefCastNonNull(HeapType::Concrete(poll_struct_type)),
LocalGet(1), // this step should never have additional function arguments so this is fine
RefCastNonNull(TPollStruct::heap_type(&types)?),
StructGet {
struct_type_index: poll_struct_type,
field_index: 0
field_index: 0,
},
LocalTee(arr_local),
ArrayLen,
Expand All @@ -51,35 +54,37 @@
LocalSet(i_local),
I32Const(0),
LocalSet(wait_local),

Block(WasmBlockType::Empty),
Loop(WasmBlockType::Empty),
LocalGet(i_local),
I32Const(1),
I32Add,
LocalTee(i_local),
LocalGet(arr_len_local),
I32Eq,
BrIf(1),
LocalGet(i_local),
I32Const(0),
I32LtS,
BrIf(0),
Block(WasmBlockType::Empty),
LocalGet(arr_local),
LocalGet(i_local),
ArrayGet(i32_array_type),
TableGet(threads_table),
RefIsNull,
BrIf(0),
I32Const(1),
LocalSet(wait_local),
Br(1),
End,
LocalGet(arr_local),
LocalGet(i_local),
I32Const(-1),
ArraySet(i32_array_type),
Br(0),
LocalGet(i_local),
I32Const(1),
I32Add,
LocalTee(i_local),
LocalGet(arr_len_local),
I32Eq,
BrIf(1),

LocalGet(arr_local),
LocalGet(i_local),
ArrayGet(thread_array_type),
LocalTee(stack_local),
RefIsNull,
BrIf(0),

LocalGet(stack_local),
#StaticFunctionCall(dyn_array_len),
I32Eqz,
If(WasmBlockType::Empty),
LocalGet(arr_local),
LocalGet(i_local),
RefNull(TStackArray::heap_type(&types)?),
Br(1),
End,

I32Const(1),
LocalSet(wait_local),
Br(1),
End,
End,
LocalGet(wait_local),
Expand Down
27 changes: 13 additions & 14 deletions src/instructions/hq/yield.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
use wasm_encoder::{BlockType, ConstExpr, HeapType};
use wasm_encoder::{BlockType, HeapType};

use super::super::prelude::*;
use crate::instructions_test;
use crate::ir::{Step, StepIndex};
use crate::wasm::{GlobalExportable, GlobalMutable, StepFunc, ThreadsTable};
use crate::wasm::StepFunc;
use crate::wasm::registries::types::TStepFunc;

#[derive(Debug, Clone)]
pub enum YieldMode {
Expand Down Expand Up @@ -55,19 +56,14 @@ pub fn wasm(
_inputs: Rc<[IrType]>,
Fields { mode: yield_mode }: &Fields,
) -> HQResult<Vec<InternalInstruction>> {
let threads_count = func.registries().globals().register(
"threads_count".into(),
(
ValType::I32,
ConstExpr::i32_const(0),
GlobalMutable(true),
GlobalExportable(true),
),
)?;
let threads_count = func.registries().globals().threads_count()?;

Ok(match yield_mode {
YieldMode::None => {
let threads_table = func.registries().tables().register::<ThreadsTable, _>()?;
let threads_table = func
.registries()
.tables()
.threads_table(func.target(), func.registries().types())?;
let thread_struct_ty = func.registries().types().thread_struct_type()?;
let stack_array_ty = func.registries().types().stack_array_type()?;
let stack_struct_ty = func.registries().types().stack_struct_type()?;
Expand All @@ -80,7 +76,7 @@ pub fn wasm(
heap_type: HeapType::Concrete(stack_struct_ty),
}))?;
let i32_local = func.local(ValType::I32)?;
let step_func_ty = func.registries().types().step_func_type()?;
let step_func_ty = func.registries().types().register_comp::<TStepFunc, _>()?;
func.free_local(thread_struct_local)?;
func.free_local(stack_struct_local)?;
func.free_local(i32_local)?;
Expand Down Expand Up @@ -146,7 +142,10 @@ pub fn wasm(
func.compile_inner_step(Rc::clone(step))?
}
YieldMode::Schedule(step_index) => {
let threads_table = func.registries().tables().register::<ThreadsTable, _>()?;
let threads_table = func
.registries()
.tables()
.threads_table(func.target(), func.registries().types())?;
let thread_struct_ty = func.registries().types().thread_struct_type()?;
let local = func.local(ValType::Ref(RefType {
nullable: false,
Expand Down
4 changes: 2 additions & 2 deletions src/instructions/procedures/argument.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use wasm_encoder::{AbstractHeapType, HeapType};

use super::super::prelude::*;
use crate::ir::RcVar;
use crate::wasm::registries::types::WasmType;
use crate::wasm::registries::types::CompoundType;
use crate::wasm::{StepFunc, WasmProject};

#[derive(Clone, Debug)]
Expand Down Expand Up @@ -72,7 +72,7 @@ pub fn wasm(
.proc_arg_struct_type(&(**arg_vars).borrow())?;
let registries = func.registries();
let type_registry = registries.types().registry().borrow();
let WasmType::Struct(struct_type_fields) = type_registry
let CompoundType::Struct(struct_type_fields) = type_registry
.get_index(struct_type_index as usize)
.ok_or_else(|| make_hq_bug!("type index not found in type registry"))?
.0
Expand Down
3 changes: 2 additions & 1 deletion src/instructions/procedures/call_nonwarp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use super::super::prelude::*;
use crate::instructions_test;
use crate::ir::{Proc, StepIndex};
use crate::wasm::registries::functions::static_functions::SpawnThreadInStack;
use crate::wasm::registries::types::TStepFunc;
use crate::wasm::{StepFunc, WasmProject};

#[derive(Clone, Debug)]
Expand Down Expand Up @@ -102,7 +103,7 @@ pub fn wasm(
LocalGet((func.params().len() - 2).try_into().map_err(|_| make_hq_bug!("local index out of bounds"))?),
LocalGet(arg_struct_local),
#LazyNonWarpedProcRef(Rc::clone(proc)),
ReturnCallRef(func.registries().types().step_func_type()?)
ReturnCallRef(func.registries().types().register_comp::<TStepFunc, _>()?)
]);

Ok(wasm)
Expand Down
2 changes: 1 addition & 1 deletion src/ir/blocks/special.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ pub fn from_special_block(
9 => {
let hex = (*SHORTHAND_HEX_COLOUR_REGEX).replace(value, "$1$1$2$2$3$3");
if let Some(captures) = (*HEX_COLOUR_REGEX).captures(&hex) {
if let box [r, g, b] = (1..4)
if let deref!([r, g, b]) = (1..4)
.map(|i| &captures[i])
.map(|capture| {
u8::from_str_radix(capture, 16)
Expand Down
7 changes: 6 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
#![feature(stmt_expr_attributes)] // used in error.rs for panic mode
#![feature(associated_type_defaults)] // used in registry.rs for default key type for NamedRegistry
#![feature(box_patterns)] // used in ir/blocks/special.rs to match Box<[_]> as array
#![feature(deref_patterns)] // used in ir/blocks/special.rs to match Box<[_]> as array
#![feature(iterator_try_reduce)] // used in instructions/input_switcher.rs for building return type
#![feature(try_find)] // used in ir/proc.rs for finding prototype/def blocks
#![feature(arbitrary_self_types)] // used in ir/types.rs to take `&mut Rc<Self>` as self type for `TypeStack`
#![feature(macro_metavar_expr_concat)]
#![feature(macro_metavar_expr)]

Check warning on line 8 in src/lib.rs

View workflow job for this annotation

GitHub Actions / Format

Diff in /home/runner/work/hyperquark/hyperquark/src/lib.rs

Check warning on line 8 in src/lib.rs

View workflow job for this annotation

GitHub Actions / Format

Diff in /home/runner/work/hyperquark/hyperquark/src/lib.rs
#![feature(impl_restriction)]
#![feature(min_specialization)]

#![doc(html_logo_url = "https://hyperquark.edgecompute.app/logo.png")]
#![doc(html_favicon_url = "https://hyperquark.edgecompute.app/favicon.ico")]
#![warn(clippy::cargo, clippy::nursery, clippy::pedantic)]
Expand Down
Loading
Loading