Skip to content

Commit 04f717e

Browse files
committed
Initial component model and GC support in fused adapters
This lays down the initial infrastructure for support for GC in our fused adapters for the component model. We keep track of whether each lifted/lowered function wants args/results as GC values or in linear memory. We additionally plumb through the core function types of the functions being lifted and lowered for (eventual) use with GC adapters. Ultimately, this commit is enough to fuse together lifted and lowered functions where one or both are using the GC variant of the canonical ABI. Attempting to actually pass arguments will hit `todo!()`s. The work of implementing those `todo!()`s is left to future commits.
1 parent a8e0d07 commit 04f717e

File tree

14 files changed

+1190
-435
lines changed

14 files changed

+1190
-435
lines changed

crates/cranelift/src/compiler/component.rs

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -388,6 +388,11 @@ impl<'a> TrampolineCompiler<'a> {
388388
}
389389

390390
fn translate_task_return_call(&mut self, results: TypeTupleIndex, options: &CanonicalOptions) {
391+
let mem_opts = match &options.data_model {
392+
CanonicalOptionsDataModel::Gc { core_type: _ } => todo!("CM+GC"),
393+
CanonicalOptionsDataModel::LinearMemory(opts) => opts,
394+
};
395+
391396
let args = self.builder.func.dfg.block_params(self.block0).to_vec();
392397
let vmctx = args[0];
393398

@@ -398,7 +403,7 @@ impl<'a> TrampolineCompiler<'a> {
398403
.ins()
399404
.iconst(ir::types::I32, i64::from(results.as_u32()));
400405

401-
let memory = self.load_optional_memory(vmctx, options.memory);
406+
let memory = self.load_optional_memory(vmctx, mem_opts.memory);
402407
let string_encoding = self.string_encoding(options.string_encoding);
403408

404409
self.translate_intrinsic_libcall(
@@ -739,16 +744,20 @@ impl<'a> TrampolineCompiler<'a> {
739744

740745
let CanonicalOptions {
741746
instance,
742-
memory,
743-
realloc,
744747
callback,
745748
post_return,
746749
string_encoding,
747750
async_,
751+
data_model,
748752
} = *options;
749753

750754
assert!(callback.is_none());
751755

756+
let LinearMemoryOptions { memory, realloc } = match data_model {
757+
CanonicalOptionsDataModel::Gc { core_type: _ } => todo!("CM+GC"),
758+
CanonicalOptionsDataModel::LinearMemory(opts) => opts,
759+
};
760+
752761
// vmctx: *mut VMComponentContext
753762
host_sig.params.push(ir::AbiParam::new(pointer_type));
754763
callee_args.push(vmctx);
@@ -1298,10 +1307,15 @@ impl<'a> TrampolineCompiler<'a> {
12981307
let mut callee_args = vec![vmctx];
12991308

13001309
if let Some(options) = options {
1310+
let mem_opts = match options.data_model {
1311+
CanonicalOptionsDataModel::Gc { core_type: _ } => todo!("CM+GC"),
1312+
CanonicalOptionsDataModel::LinearMemory(opts) => opts,
1313+
};
1314+
13011315
// memory: *mut VMMemoryDefinition
1302-
callee_args.push(self.load_memory(vmctx, options.memory.unwrap()));
1316+
callee_args.push(self.load_memory(vmctx, mem_opts.memory.unwrap()));
13031317
// realloc: *mut VMFuncRef
1304-
callee_args.push(self.load_realloc(vmctx, options.realloc));
1318+
callee_args.push(self.load_realloc(vmctx, mem_opts.realloc));
13051319
// string_encoding: StringEncoding
13061320
callee_args.push(self.string_encoding(options.string_encoding));
13071321
// async: bool
@@ -1328,12 +1342,17 @@ impl<'a> TrampolineCompiler<'a> {
13281342
get_libcall: GetLibcallFn,
13291343
info: &CanonicalAbiInfo,
13301344
) {
1345+
let mem_opts = match &options.data_model {
1346+
CanonicalOptionsDataModel::Gc { core_type: _ } => todo!("CM+GC"),
1347+
CanonicalOptionsDataModel::LinearMemory(opts) => opts,
1348+
};
1349+
13311350
let args = self.builder.func.dfg.block_params(self.block0).to_vec();
13321351
let vmctx = args[0];
13331352
let mut callee_args = vec![
13341353
vmctx,
1335-
self.load_memory(vmctx, options.memory.unwrap()),
1336-
self.load_realloc(vmctx, options.realloc),
1354+
self.load_memory(vmctx, mem_opts.memory.unwrap()),
1355+
self.load_realloc(vmctx, mem_opts.realloc),
13371356
self.builder
13381357
.ins()
13391358
.iconst(ir::types::I8, if options.async_ { 1 } else { 0 }),
@@ -1368,12 +1387,17 @@ impl<'a> TrampolineCompiler<'a> {
13681387
get_libcall: GetLibcallFn,
13691388
sentinel: TrapSentinel,
13701389
) {
1390+
let mem_opts = match &options.data_model {
1391+
CanonicalOptionsDataModel::Gc { core_type: _ } => todo!("CM+GC"),
1392+
CanonicalOptionsDataModel::LinearMemory(opts) => opts,
1393+
};
1394+
13711395
let args = self.builder.func.dfg.block_params(self.block0).to_vec();
13721396
let vmctx = args[0];
13731397
let mut callee_args = vec![
13741398
vmctx,
1375-
self.load_memory(vmctx, options.memory.unwrap()),
1376-
self.load_realloc(vmctx, options.realloc),
1399+
self.load_memory(vmctx, mem_opts.memory.unwrap()),
1400+
self.load_realloc(vmctx, mem_opts.realloc),
13771401
self.string_encoding(options.string_encoding),
13781402
self.builder
13791403
.ins()

crates/environ/src/component/dfg.rs

Lines changed: 35 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ use crate::prelude::*;
3232
use crate::{EntityIndex, EntityRef, ModuleInternedTypeIndex, PrimaryMap, WasmValType};
3333
use anyhow::Result;
3434
use indexmap::IndexMap;
35+
use info::LinearMemoryOptions;
3536
use std::collections::HashMap;
3637
use std::hash::Hash;
3738
use std::ops::Index;
@@ -194,6 +195,7 @@ pub enum Export {
194195
LiftedFunction {
195196
ty: TypeFuncIndex,
196197
func: CoreDef,
198+
func_ty: ModuleInternedTypeIndex,
197199
options: CanonicalOptions,
198200
},
199201
ModuleStatic {
@@ -414,17 +416,29 @@ pub struct StreamInfo {
414416
pub payload_type: InterfaceType,
415417
}
416418

419+
/// Same as `info::CanonicalOptionsDataModel`.
420+
#[derive(Clone, Hash, Eq, PartialEq)]
421+
#[expect(missing_docs, reason = "self-describing fields")]
422+
pub enum CanonicalOptionsDataModel {
423+
Gc {
424+
core_type: ModuleInternedTypeIndex,
425+
},
426+
LinearMemory {
427+
memory: Option<MemoryId>,
428+
realloc: Option<ReallocId>,
429+
},
430+
}
431+
417432
/// Same as `info::CanonicalOptions`
418433
#[derive(Clone, Hash, Eq, PartialEq)]
419434
#[expect(missing_docs, reason = "self-describing fields")]
420435
pub struct CanonicalOptions {
421436
pub instance: RuntimeComponentInstanceIndex,
422437
pub string_encoding: StringEncoding,
423-
pub memory: Option<MemoryId>,
424-
pub realloc: Option<ReallocId>,
425438
pub callback: Option<CallbackId>,
426439
pub post_return: Option<PostReturnId>,
427440
pub async_: bool,
441+
pub data_model: CanonicalOptionsDataModel,
428442
}
429443

430444
/// Same as `info::Resource`
@@ -651,12 +665,18 @@ impl LinearizeDfg<'_> {
651665
wasmparser_types: wasmparser::types::TypesRef<'_>,
652666
) -> Result<ExportIndex> {
653667
let item = match export {
654-
Export::LiftedFunction { ty, func, options } => {
668+
Export::LiftedFunction {
669+
ty,
670+
func,
671+
func_ty,
672+
options,
673+
} => {
655674
let func = self.core_def(func);
656675
let options = self.options(options);
657676
info::Export::LiftedFunction {
658677
ty: *ty,
659678
func,
679+
func_ty: *func_ty,
660680
options,
661681
}
662682
}
@@ -686,18 +706,26 @@ impl LinearizeDfg<'_> {
686706
}
687707

688708
fn options(&mut self, options: &CanonicalOptions) -> info::CanonicalOptions {
689-
let memory = options.memory.map(|mem| self.runtime_memory(mem));
690-
let realloc = options.realloc.map(|mem| self.runtime_realloc(mem));
709+
let data_model = match options.data_model {
710+
CanonicalOptionsDataModel::Gc { core_type } => {
711+
info::CanonicalOptionsDataModel::Gc { core_type }
712+
}
713+
CanonicalOptionsDataModel::LinearMemory { memory, realloc } => {
714+
info::CanonicalOptionsDataModel::LinearMemory(LinearMemoryOptions {
715+
memory: memory.map(|mem| self.runtime_memory(mem)),
716+
realloc: realloc.map(|mem| self.runtime_realloc(mem)),
717+
})
718+
}
719+
};
691720
let callback = options.callback.map(|mem| self.runtime_callback(mem));
692721
let post_return = options.post_return.map(|mem| self.runtime_post_return(mem));
693722
info::CanonicalOptions {
694723
instance: options.instance,
695724
string_encoding: options.string_encoding,
696-
memory,
697-
realloc,
698725
callback,
699726
post_return,
700727
async_: options.async_,
728+
data_model,
701729
}
702730
}
703731

crates/environ/src/component/info.rs

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -450,6 +450,8 @@ pub enum Export {
450450
ty: TypeFuncIndex,
451451
/// Which core WebAssembly export is being lifted.
452452
func: CoreDef,
453+
/// The core function's type.
454+
func_ty: ModuleInternedTypeIndex,
453455
/// Any options, if present, associated with this lifting.
454456
options: CanonicalOptions,
455457
},
@@ -480,6 +482,28 @@ pub enum Export {
480482
Type(TypeDef),
481483
}
482484

485+
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
486+
/// Data is stored in a linear memory.
487+
pub struct LinearMemoryOptions {
488+
/// The memory used by these options, if specified.
489+
pub memory: Option<RuntimeMemoryIndex>,
490+
/// The realloc function used by these options, if specified.
491+
pub realloc: Option<RuntimeReallocIndex>,
492+
}
493+
494+
/// The data model for objects that are not unboxed in locals.
495+
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
496+
pub enum CanonicalOptionsDataModel {
497+
/// Data is stored in GC objects.
498+
Gc {
499+
/// The core function type that is being lifted from / lowered to.
500+
core_type: ModuleInternedTypeIndex,
501+
},
502+
503+
/// Data is stored in a linear memory.
504+
LinearMemory(LinearMemoryOptions),
505+
}
506+
483507
/// Canonical ABI options associated with a lifted or lowered function.
484508
#[derive(Debug, Clone, Serialize, Deserialize)]
485509
pub struct CanonicalOptions {
@@ -489,12 +513,6 @@ pub struct CanonicalOptions {
489513
/// The encoding used for strings.
490514
pub string_encoding: StringEncoding,
491515

492-
/// The memory used by these options, if specified.
493-
pub memory: Option<RuntimeMemoryIndex>,
494-
495-
/// The realloc function used by these options, if specified.
496-
pub realloc: Option<RuntimeReallocIndex>,
497-
498516
/// The async callback function used by these options, if specified.
499517
pub callback: Option<RuntimeCallbackIndex>,
500518

@@ -503,6 +521,10 @@ pub struct CanonicalOptions {
503521

504522
/// Whether to use the async ABI for lifting or lowering.
505523
pub async_: bool,
524+
525+
/// The data model (GC objects or linear memory) used with these canonical
526+
/// options.
527+
pub data_model: CanonicalOptionsDataModel,
506528
}
507529

508530
/// Possible encodings of strings within the component model.

0 commit comments

Comments
 (0)