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

Commit 3029fef

Browse files
authored
Merge pull request #234 from alexcrichton/merge
Merge with upstream
2 parents 0c2d68c + aa31cba commit 3029fef

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

90 files changed

+4423
-1083
lines changed

.github/workflows/main.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,7 @@ jobs:
327327
-p wasmtime --no-default-features --features pooling-allocator
328328
-p wasmtime --no-default-features --features cranelift
329329
-p wasmtime --no-default-features --features component-model
330+
-p wasmtime --no-default-features --features component-model-async
330331
-p wasmtime --no-default-features --features runtime,component-model
331332
-p wasmtime --no-default-features --features cranelift,wat,async,std,cache
332333
-p wasmtime --no-default-features --features winch

cranelift/codegen/src/isa/x64/lower.isle

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3618,10 +3618,15 @@
36183618
(lower_select (is_nonzero_cmp cond) x y))
36193619

36203620
;; Note that for GPR-based spectre guards everything is forced into a register
3621-
;; so go straight to the `lower_select_gpr` helper forcing `x` to be in a `Gpr`
3622-
;; not `GprMem`.
3621+
;; not `GprMem`. The `lower_select_spectre_gpr` helper below handles "and"
3622+
;; conditions which the `lower_select_gpr` helper does not.
36233623
(rule 1 (lower (has_type (is_single_register_gpr_type ty) (select_spectre_guard cond x y)))
3624-
(lower_select_gpr ty (is_nonzero_cmp cond) (put_in_gpr x) y))
3624+
(lower_select_spectre_gpr ty (is_nonzero_cmp cond) (put_in_gpr x) y))
3625+
3626+
(decl lower_select_spectre_gpr (Type CondResult Gpr Gpr) Gpr)
3627+
(rule 0 (lower_select_spectre_gpr ty cond a b) (lower_select_gpr ty cond a b))
3628+
(rule 1 (lower_select_spectre_gpr ty cond @ (CondResult.And _ _ _) a b)
3629+
(lower_select_gpr ty (cond_invert cond) b a))
36253630

36263631
;; Rules for `fcvt_from_sint` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
36273632

cranelift/entity/src/set.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,14 @@ where
148148
self.bitset.insert(index)
149149
}
150150

151+
/// Remove `k` from this bitset.
152+
///
153+
/// Returns whether `k` was previously in this set or not.
154+
pub fn remove(&mut self, k: K) -> bool {
155+
let index = k.index();
156+
self.bitset.remove(index)
157+
}
158+
151159
/// Removes and returns the entity from the set if it exists.
152160
pub fn pop(&mut self) -> Option<K> {
153161
let index = self.bitset.pop()?;

cranelift/filetests/filetests/isa/x64/select.clif

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,3 +193,67 @@ block0(v0: i8, v1: f128, v2: f128):
193193
; popq %rbp
194194
; retq
195195

196+
function %select_gpr_with_and_condition(f32, f32, i64, i64) -> i64 {
197+
block0(v0: f32, v1: f32, v2: i64, v3: i64):
198+
v4 = fcmp eq v0, v1
199+
v5 = select v4, v2, v3
200+
return v5
201+
}
202+
203+
; VCode:
204+
; pushq %rbp
205+
; movq %rsp, %rbp
206+
; block0:
207+
; ucomiss %xmm1, %xmm0
208+
; cmovpq %rsi, %rdi
209+
; movq %rdi, %rax
210+
; cmovneq %rsi, %rax
211+
; movq %rbp, %rsp
212+
; popq %rbp
213+
; retq
214+
;
215+
; Disassembled:
216+
; block0: ; offset 0x0
217+
; pushq %rbp
218+
; movq %rsp, %rbp
219+
; block1: ; offset 0x4
220+
; ucomiss %xmm1, %xmm0
221+
; cmovpq %rsi, %rdi
222+
; movq %rdi, %rax
223+
; cmovneq %rsi, %rax
224+
; movq %rbp, %rsp
225+
; popq %rbp
226+
; retq
227+
228+
function %select_spectre_gpr_with_and_condition(f32, f32, i64, i64) -> i64 {
229+
block0(v0: f32, v1: f32, v2: i64, v3: i64):
230+
v4 = fcmp eq v0, v1
231+
v5 = select_spectre_guard v4, v2, v3
232+
return v5
233+
}
234+
235+
; VCode:
236+
; pushq %rbp
237+
; movq %rsp, %rbp
238+
; block0:
239+
; ucomiss %xmm1, %xmm0
240+
; cmovpq %rsi, %rdi
241+
; movq %rdi, %rax
242+
; cmovneq %rsi, %rax
243+
; movq %rbp, %rsp
244+
; popq %rbp
245+
; retq
246+
;
247+
; Disassembled:
248+
; block0: ; offset 0x0
249+
; pushq %rbp
250+
; movq %rsp, %rbp
251+
; block1: ; offset 0x4
252+
; ucomiss %xmm1, %xmm0
253+
; cmovpq %rsi, %rdi
254+
; movq %rdi, %rax
255+
; cmovneq %rsi, %rax
256+
; movq %rbp, %rsp
257+
; popq %rbp
258+
; retq
259+

crates/c-api/src/val.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ impl wasm_val_t {
9696
},
9797
Val::AnyRef(_) => crate::abort("creating a wasm_val_t from an anyref"),
9898
Val::ExternRef(_) => crate::abort("creating a wasm_val_t from an externref"),
99+
Val::ExnRef(_) => crate::abort("creating a wasm_val_t from an exnref"),
99100
Val::V128(_) => crate::abort("creating a wasm_val_t from a v128"),
100101
}
101102
}
@@ -251,6 +252,7 @@ impl wasmtime_val_t {
251252
funcref: func.into(),
252253
},
253254
},
255+
Val::ExnRef(_) => crate::abort("exnrefs not yet supported in C API"),
254256
Val::V128(val) => wasmtime_val_t {
255257
kind: crate::WASMTIME_V128,
256258
of: wasmtime_val_union {

crates/cranelift/src/func_environ.rs

Lines changed: 27 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,6 @@ pub struct FuncEnvironment<'module_environment> {
118118
#[cfg(feature = "gc")]
119119
gc_heap_bound: Option<ir::GlobalValue>,
120120

121-
#[cfg(feature = "wmemcheck")]
122121
translation: &'module_environment ModuleTranslation<'module_environment>,
123122

124123
/// Heaps implementing WebAssembly linear memories.
@@ -224,7 +223,6 @@ impl<'module_environment> FuncEnvironment<'module_environment> {
224223
// functions should consume at least some fuel.
225224
fuel_consumed: 1,
226225

227-
#[cfg(feature = "wmemcheck")]
228226
translation,
229227

230228
stack_limit_at_function_entry: None,
@@ -1321,26 +1319,34 @@ impl<'a, 'func, 'module_env> Call<'a, 'func, 'module_env> {
13211319
.vmctx_vmfunction_import_wasm_call(callee_index),
13221320
)
13231321
.unwrap();
1324-
let func_addr = self
1325-
.builder
1326-
.ins()
1327-
.load(pointer_type, mem_flags, base, body_offset);
13281322

13291323
// First append the callee vmctx address.
13301324
let vmctx_offset =
13311325
i32::try_from(self.env.offsets.vmctx_vmfunction_import_vmctx(callee_index)).unwrap();
1332-
let vmctx = self
1326+
let callee_vmctx = self
13331327
.builder
13341328
.ins()
13351329
.load(pointer_type, mem_flags, base, vmctx_offset);
1336-
real_call_args.push(vmctx);
1330+
real_call_args.push(callee_vmctx);
13371331
real_call_args.push(caller_vmctx);
13381332

13391333
// Then append the regular call arguments.
13401334
real_call_args.extend_from_slice(call_args);
13411335

1342-
// Finally, make the indirect call!
1343-
Ok(self.indirect_call_inst(sig_ref, func_addr, &real_call_args))
1336+
// If we statically know the imported function (e.g. this is a
1337+
// component-to-component call where we statically know both components)
1338+
// then we can actually still make a direct call (although we do have to
1339+
// pass the callee's vmctx that we just loaded, not our own). Otherwise,
1340+
// we really do an indirect call.
1341+
if self.env.translation.known_imported_functions[callee_index].is_some() {
1342+
Ok(self.direct_call_inst(callee, &real_call_args))
1343+
} else {
1344+
let func_addr = self
1345+
.builder
1346+
.ins()
1347+
.load(pointer_type, mem_flags, base, body_offset);
1348+
Ok(self.indirect_call_inst(sig_ref, func_addr, &real_call_args))
1349+
}
13441350
}
13451351

13461352
/// Do an indirect call through the given funcref table.
@@ -1514,6 +1520,9 @@ impl<'a, 'func, 'module_env> Call<'a, 'func, 'module_env> {
15141520
| WasmHeapType::ConcreteArray(_)
15151521
| WasmHeapType::Struct
15161522
| WasmHeapType::ConcreteStruct(_)
1523+
| WasmHeapType::Exn
1524+
| WasmHeapType::ConcreteExn(_)
1525+
| WasmHeapType::NoExn
15171526
| WasmHeapType::None => {
15181527
unreachable!()
15191528
}
@@ -1741,7 +1750,7 @@ impl<'module_environment> TargetEnvironment for FuncEnvironment<'module_environm
17411750
fn reference_type(&self, wasm_ty: WasmHeapType) -> (ir::Type, bool) {
17421751
let ty = crate::reference_type(wasm_ty, self.pointer_type());
17431752
let needs_stack_map = match wasm_ty.top() {
1744-
WasmHeapTopType::Extern | WasmHeapTopType::Any => true,
1753+
WasmHeapTopType::Extern | WasmHeapTopType::Any | WasmHeapTopType::Exn => true,
17451754
WasmHeapTopType::Func => false,
17461755
WasmHeapTopType::Cont => todo!(), // FIXME: #10248 stack switching support.
17471756
};
@@ -1838,7 +1847,7 @@ impl FuncEnvironment<'_> {
18381847
let heap_ty = table.ref_type.heap_type;
18391848
match heap_ty.top() {
18401849
// GC-managed types.
1841-
WasmHeapTopType::Any | WasmHeapTopType::Extern => {
1850+
WasmHeapTopType::Any | WasmHeapTopType::Extern | WasmHeapTopType::Exn => {
18421851
let (src, flags) = table_data.prepare_table_addr(self, builder, index);
18431852
gc::gc_compiler(self)?.translate_read_gc_reference(
18441853
self,
@@ -1872,7 +1881,7 @@ impl FuncEnvironment<'_> {
18721881
let heap_ty = table.ref_type.heap_type;
18731882
match heap_ty.top() {
18741883
// GC-managed types.
1875-
WasmHeapTopType::Any | WasmHeapTopType::Extern => {
1884+
WasmHeapTopType::Any | WasmHeapTopType::Extern | WasmHeapTopType::Exn => {
18761885
let (dst, flags) = table_data.prepare_table_addr(self, builder, index);
18771886
gc::gc_compiler(self)?.translate_write_gc_reference(
18781887
self,
@@ -2254,7 +2263,9 @@ impl FuncEnvironment<'_> {
22542263
Ok(match ht.top() {
22552264
WasmHeapTopType::Func => pos.ins().iconst(self.pointer_type(), 0),
22562265
// NB: null GC references don't need to be in stack maps.
2257-
WasmHeapTopType::Any | WasmHeapTopType::Extern => pos.ins().iconst(types::I32, 0),
2266+
WasmHeapTopType::Any | WasmHeapTopType::Extern | WasmHeapTopType::Exn => {
2267+
pos.ins().iconst(types::I32, 0)
2268+
}
22582269
WasmHeapTopType::Cont => todo!(), // FIXME: #10248 stack switching support.
22592270
})
22602271
}
@@ -2646,7 +2657,8 @@ impl FuncEnvironment<'_> {
26462657
// wasm module (e.g. imports or libcalls) are either encoded through
26472658
// the `vmcontext` as relative jumps (hence no relocations) or
26482659
// they're libcalls with absolute relocations.
2649-
colocated: self.module.defined_func_index(index).is_some(),
2660+
colocated: self.module.defined_func_index(index).is_some()
2661+
|| self.translation.known_imported_functions[index].is_some(),
26502662
}))
26512663
}
26522664

crates/cranelift/src/func_environ/gc/enabled.rs

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -117,8 +117,10 @@ fn read_field_at_addr(
117117
WasmValType::F64 => builder.ins().load(ir::types::F64, flags, addr, 0),
118118
WasmValType::V128 => builder.ins().load(ir::types::I8X16, flags, addr, 0),
119119
WasmValType::Ref(r) => match r.heap_type.top() {
120-
WasmHeapTopType::Any | WasmHeapTopType::Extern => gc_compiler(func_env)?
121-
.translate_read_gc_reference(func_env, builder, r, addr, flags)?,
120+
WasmHeapTopType::Any | WasmHeapTopType::Extern | WasmHeapTopType::Exn => {
121+
gc_compiler(func_env)?
122+
.translate_read_gc_reference(func_env, builder, r, addr, flags)?
123+
}
122124
WasmHeapTopType::Func => {
123125
let expected_ty = match r.heap_type {
124126
WasmHeapType::Func => ModuleInternedTypeIndex::reserved_value(),
@@ -1042,6 +1044,8 @@ pub fn translate_ref_test(
10421044
| WasmHeapType::NoFunc
10431045
| WasmHeapType::Cont
10441046
| WasmHeapType::NoCont
1047+
| WasmHeapType::Exn
1048+
| WasmHeapType::NoExn
10451049
| WasmHeapType::I31 => unreachable!("handled top, bottom, and i31 types above"),
10461050

10471051
// For these abstract but non-top and non-bottom types, we check the
@@ -1057,7 +1061,9 @@ pub fn translate_ref_test(
10571061
// TODO: This check should ideally be done inline, but we don't have a
10581062
// good way to access the `TypeRegistry`'s supertypes arrays from Wasm
10591063
// code at the moment.
1060-
WasmHeapType::ConcreteArray(ty) | WasmHeapType::ConcreteStruct(ty) => {
1064+
WasmHeapType::ConcreteArray(ty)
1065+
| WasmHeapType::ConcreteStruct(ty)
1066+
| WasmHeapType::ConcreteExn(ty) => {
10611067
let expected_interned_ty = ty.unwrap_module_type_index();
10621068
let expected_shared_ty =
10631069
func_env.module_interned_to_shared_ty(&mut builder.cursor(), expected_interned_ty);
@@ -1417,6 +1423,8 @@ impl FuncEnvironment<'_> {
14171423
// Can only ever be `null`.
14181424
WasmHeapType::NoExtern => false,
14191425

1426+
WasmHeapType::Exn | WasmHeapType::ConcreteExn(_) | WasmHeapType::NoExn => false,
1427+
14201428
// Wrong type hierarchy, and also funcrefs are not GC-managed
14211429
// types. Should have been caught by the assertion at the start of
14221430
// the function.

crates/cranelift/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@ fn wasm_call_signature(
212212
fn reference_type(wasm_ht: WasmHeapType, pointer_type: ir::Type) -> ir::Type {
213213
match wasm_ht.top() {
214214
WasmHeapTopType::Func => pointer_type,
215-
WasmHeapTopType::Any | WasmHeapTopType::Extern => ir::types::I32,
215+
WasmHeapTopType::Any | WasmHeapTopType::Extern | WasmHeapTopType::Exn => ir::types::I32,
216216
WasmHeapTopType::Cont =>
217217
// TODO(10248) This is added in a follow-up PR
218218
{

crates/environ/src/compile/module_environ.rs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,16 @@ use crate::module::{
22
FuncRefIndex, Initializer, MemoryInitialization, MemoryInitializer, Module, TableSegment,
33
TableSegmentElements,
44
};
5-
use crate::prelude::*;
65
use crate::{
76
ConstExpr, ConstOp, DataIndex, DefinedFuncIndex, ElemIndex, EngineOrModuleTypeIndex,
87
EntityIndex, EntityType, FuncIndex, GlobalIndex, IndexType, InitMemory, MemoryIndex,
98
ModuleInternedTypeIndex, ModuleTypesBuilder, PrimaryMap, SizeOverflow, StaticMemoryInitializer,
109
TableIndex, TableInitialValue, Tag, TagIndex, Tunables, TypeConvert, TypeIndex, Unsigned,
1110
WasmError, WasmHeapTopType, WasmHeapType, WasmResult, WasmValType, WasmparserTypeConverter,
1211
};
12+
use crate::{StaticModuleIndex, prelude::*};
1313
use anyhow::{Result, bail};
14+
use cranelift_entity::SecondaryMap;
1415
use cranelift_entity::packed_option::ReservedValue;
1516
use std::borrow::Cow;
1617
use std::collections::HashMap;
@@ -54,6 +55,13 @@ pub struct ModuleTranslation<'data> {
5455
/// References to the function bodies.
5556
pub function_body_inputs: PrimaryMap<DefinedFuncIndex, FunctionBodyData<'data>>,
5657

58+
/// For each imported function, the single statically-known defined function
59+
/// that satisfies that import, if any. This is used to turn what would
60+
/// otherwise be indirect calls through the imports table into direct calls,
61+
/// when possible.
62+
pub known_imported_functions:
63+
SecondaryMap<FuncIndex, Option<(StaticModuleIndex, DefinedFuncIndex)>>,
64+
5765
/// A list of type signatures which are considered exported from this
5866
/// module, or those that can possibly be called. This list is sorted, and
5967
/// trampolines for each of these signatures are required.
@@ -1220,7 +1228,10 @@ impl ModuleTranslation<'_> {
12201228
// initializer won't trap so we could continue processing
12211229
// segments, but that's left as a future optimization if
12221230
// necessary.
1223-
WasmHeapTopType::Any | WasmHeapTopType::Extern | WasmHeapTopType::Cont => break,
1231+
WasmHeapTopType::Any
1232+
| WasmHeapTopType::Extern
1233+
| WasmHeapTopType::Cont
1234+
| WasmHeapTopType::Exn => break,
12241235
}
12251236

12261237
// Function indices can be optimized here, but fully general

crates/environ/src/compile/module_types.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -441,6 +441,7 @@ where
441441
WasmCompositeInnerType::Func(_) => WasmHeapType::ConcreteFunc(index),
442442
WasmCompositeInnerType::Struct(_) => WasmHeapType::ConcreteStruct(index),
443443
WasmCompositeInnerType::Cont(_) => WasmHeapType::ConcreteCont(index),
444+
WasmCompositeInnerType::Exn(_) => WasmHeapType::ConcreteExn(index),
444445
}
445446
} else if let Some((wasmparser_types, _)) = self.rec_group_context.as_ref() {
446447
let wasmparser_ty = &wasmparser_types[id].composite_type;
@@ -481,6 +482,7 @@ where
481482
WasmCompositeInnerType::Func(_) => WasmHeapType::ConcreteFunc(index),
482483
WasmCompositeInnerType::Struct(_) => WasmHeapType::ConcreteStruct(index),
483484
WasmCompositeInnerType::Cont(_) => WasmHeapType::ConcreteCont(index),
485+
WasmCompositeInnerType::Exn(_) => WasmHeapType::ConcreteExn(index),
484486
}
485487
} else if let Some((parser_types, rec_group)) = self.rec_group_context.as_ref() {
486488
let rec_group_index = interned.index() - self.types.types.len_types();

0 commit comments

Comments
 (0)