Skip to content

Commit 6ed8e48

Browse files
committed
Added Wait / Notify opcode to LLVM compiler (for #3157)
1 parent 04a03fc commit 6ed8e48

File tree

3 files changed

+313
-0
lines changed

3 files changed

+313
-0
lines changed

lib/compiler-llvm/src/object_file.rs

+24
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,30 @@ where
9696
libcalls.insert("wasmer_vm_memory32_init".to_string(), LibCall::Memory32Init);
9797
libcalls.insert("wasmer_vm_data_drop".to_string(), LibCall::DataDrop);
9898
libcalls.insert("wasmer_vm_raise_trap".to_string(), LibCall::RaiseTrap);
99+
libcalls.insert(
100+
"wasmer_vm_memory32_atomic_wait32".to_string(),
101+
LibCall::Memory32AtomicWait32,
102+
);
103+
libcalls.insert(
104+
"wasmer_vm_imported_memory32_atomic_wait32".to_string(),
105+
LibCall::ImportedMemory32AtomicWait32,
106+
);
107+
libcalls.insert(
108+
"wasmer_vm_memory32_atomic_wait64".to_string(),
109+
LibCall::Memory32AtomicWait64,
110+
);
111+
libcalls.insert(
112+
"wasmer_vm_imported_memory32_atomic_wait64".to_string(),
113+
LibCall::ImportedMemory32AtomicWait64,
114+
);
115+
libcalls.insert(
116+
"wasmer_vm_memory32_atomic_notify".to_string(),
117+
LibCall::Memory32AtomicNotify,
118+
);
119+
libcalls.insert(
120+
"wasmer_vm_imported_memory32_atomic_notify".to_string(),
121+
LibCall::ImportedMemory32AtomicNotify,
122+
);
99123

100124
let elf = object::File::parse(contents).map_err(map_object_err)?;
101125

lib/compiler-llvm/src/translator/code.rs

+53
Original file line numberDiff line numberDiff line change
@@ -11231,6 +11231,59 @@ impl<'ctx, 'a> LLVMFunctionCodeGenerator<'ctx, 'a> {
1123111231
.unwrap();
1123211232
self.state.push1(size);
1123311233
}
11234+
Operator::MemoryAtomicWait32 { memarg } => {
11235+
let memory_index = MemoryIndex::from_u32(memarg.memory);
11236+
let (dst, val, timeout) = self.state.pop3()?;
11237+
let wait32_fn_ptr = self.ctx.memory_wait32(memory_index, self.intrinsics);
11238+
let callable_func = inkwell::values::CallableValue::try_from(wait32_fn_ptr).unwrap();
11239+
let ret = self.builder.build_call(
11240+
callable_func,
11241+
&[
11242+
vmctx.as_basic_value_enum().into(),
11243+
self.intrinsics.i32_ty.const_int(memarg.memory as u64, false).into(),
11244+
dst.into(),
11245+
val.into(),
11246+
timeout.into(),
11247+
],
11248+
"",
11249+
);
11250+
self.state.push1(ret.try_as_basic_value().left().unwrap());
11251+
}
11252+
Operator::MemoryAtomicWait64 { memarg } => {
11253+
let memory_index = MemoryIndex::from_u32(memarg.memory);
11254+
let (dst, val, timeout) = self.state.pop3()?;
11255+
let wait64_fn_ptr = self.ctx.memory_wait64(memory_index, self.intrinsics);
11256+
let callable_func = inkwell::values::CallableValue::try_from(wait64_fn_ptr).unwrap();
11257+
let ret = self.builder.build_call(
11258+
callable_func,
11259+
&[
11260+
vmctx.as_basic_value_enum().into(),
11261+
self.intrinsics.i32_ty.const_int(memarg.memory as u64, false).into(),
11262+
dst.into(),
11263+
val.into(),
11264+
timeout.into(),
11265+
],
11266+
"",
11267+
);
11268+
self.state.push1(ret.try_as_basic_value().left().unwrap());
11269+
}
11270+
Operator::MemoryAtomicNotify { memarg } => {
11271+
let memory_index = MemoryIndex::from_u32(memarg.memory);
11272+
let (dst, count) = self.state.pop2()?;
11273+
let notify_fn_ptr = self.ctx.memory_notify(memory_index, self.intrinsics);
11274+
let callable_func = inkwell::values::CallableValue::try_from(notify_fn_ptr).unwrap();
11275+
let cnt = self.builder.build_call(
11276+
callable_func,
11277+
&[
11278+
vmctx.as_basic_value_enum().into(),
11279+
self.intrinsics.i32_ty.const_int(memarg.memory as u64, false).into(),
11280+
dst.into(),
11281+
count.into(),
11282+
],
11283+
"",
11284+
);
11285+
self.state.push1(cnt.try_as_basic_value().left().unwrap());
11286+
}
1123411287
_ => {
1123511288
return Err(CompileError::Codegen(format!(
1123611289
"Operator {:?} unimplemented",

lib/compiler-llvm/src/translator/intrinsics.rs

+236
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,12 @@ pub struct Intrinsics<'ctx> {
240240
pub imported_memory_copy: FunctionValue<'ctx>,
241241
pub memory_fill: FunctionValue<'ctx>,
242242
pub imported_memory_fill: FunctionValue<'ctx>,
243+
pub memory_wait32: FunctionValue<'ctx>,
244+
pub imported_memory_wait32: FunctionValue<'ctx>,
245+
pub memory_wait64: FunctionValue<'ctx>,
246+
pub imported_memory_wait64: FunctionValue<'ctx>,
247+
pub memory_notify: FunctionValue<'ctx>,
248+
pub imported_memory_notify: FunctionValue<'ctx>,
243249

244250
pub throw_trap: FunctionValue<'ctx>,
245251

@@ -256,6 +262,12 @@ pub struct Intrinsics<'ctx> {
256262
pub imported_memory32_grow_ptr_ty: PointerType<'ctx>,
257263
pub memory32_size_ptr_ty: PointerType<'ctx>,
258264
pub imported_memory32_size_ptr_ty: PointerType<'ctx>,
265+
pub memory32_wait32_ptr_ty: PointerType<'ctx>,
266+
pub imported_memory32_wait32_ptr_ty: PointerType<'ctx>,
267+
pub memory32_wait64_ptr_ty: PointerType<'ctx>,
268+
pub imported_memory32_wait64_ptr_ty: PointerType<'ctx>,
269+
pub memory32_notify_ptr_ty: PointerType<'ctx>,
270+
pub imported_memory32_notify_ptr_ty: PointerType<'ctx>,
259271

260272
// Pointer to the VM.
261273
pub ctx_ptr_ty: PointerType<'ctx>,
@@ -1007,6 +1019,86 @@ impl<'ctx> Intrinsics<'ctx> {
10071019
void_ty.fn_type(&[i32_ty_basic_md], false),
10081020
None,
10091021
),
1022+
memory_wait32: module.add_function(
1023+
"wasmer_vm_memory32_atomic_wait32",
1024+
i32_ty.fn_type(
1025+
&[
1026+
ctx_ptr_ty_basic_md,
1027+
i32_ty_basic_md,
1028+
i32_ty_basic_md,
1029+
i32_ty_basic_md,
1030+
i64_ty_basic_md,
1031+
],
1032+
false,
1033+
),
1034+
None,
1035+
),
1036+
imported_memory_wait32: module.add_function(
1037+
"wasmer_vm_imported_memory32_atomic_wait32",
1038+
i32_ty.fn_type(
1039+
&[
1040+
ctx_ptr_ty_basic_md,
1041+
i32_ty_basic_md,
1042+
i32_ty_basic_md,
1043+
i32_ty_basic_md,
1044+
i64_ty_basic_md,
1045+
],
1046+
false,
1047+
),
1048+
None,
1049+
),
1050+
memory_wait64: module.add_function(
1051+
"wasmer_vm_memory32_atomic_wait64",
1052+
i32_ty.fn_type(
1053+
&[
1054+
ctx_ptr_ty_basic_md,
1055+
i32_ty_basic_md,
1056+
i32_ty_basic_md,
1057+
i64_ty_basic_md,
1058+
i64_ty_basic_md,
1059+
],
1060+
false,
1061+
),
1062+
None,
1063+
),
1064+
imported_memory_wait64: module.add_function(
1065+
"wasmer_vm_imported_memory32_atomic_wait64",
1066+
i32_ty.fn_type(
1067+
&[
1068+
ctx_ptr_ty_basic_md,
1069+
i32_ty_basic_md,
1070+
i32_ty_basic_md,
1071+
i64_ty_basic_md,
1072+
i64_ty_basic_md,
1073+
],
1074+
false,
1075+
),
1076+
None,
1077+
),
1078+
memory_notify: module.add_function(
1079+
"wasmer_vm_memory32_atomic_notify",
1080+
i32_ty.fn_type(
1081+
&[
1082+
ctx_ptr_ty_basic_md,
1083+
i32_ty_basic_md,
1084+
i32_ty_basic_md,
1085+
],
1086+
false,
1087+
),
1088+
None,
1089+
),
1090+
imported_memory_notify: module.add_function(
1091+
"wasmer_vm_imported_memory32_atomic_notify",
1092+
i32_ty.fn_type(
1093+
&[
1094+
ctx_ptr_ty_basic_md,
1095+
i32_ty_basic_md,
1096+
i32_ty_basic_md,
1097+
],
1098+
false,
1099+
),
1100+
None,
1101+
),
10101102

10111103
vmfunction_import_ptr_ty: context
10121104
.struct_type(&[i8_ptr_ty_basic, i8_ptr_ty_basic], false)
@@ -1038,6 +1130,24 @@ impl<'ctx> Intrinsics<'ctx> {
10381130
imported_memory32_size_ptr_ty: i32_ty
10391131
.fn_type(&[ctx_ptr_ty_basic_md, i32_ty_basic_md], false)
10401132
.ptr_type(AddressSpace::Generic),
1133+
memory32_wait32_ptr_ty: i32_ty
1134+
.fn_type(&[ctx_ptr_ty_basic_md, i32_ty_basic_md, i32_ty_basic_md, i32_ty_basic_md, i64_ty_basic_md], false)
1135+
.ptr_type(AddressSpace::Generic),
1136+
imported_memory32_wait32_ptr_ty: i32_ty
1137+
.fn_type(&[ctx_ptr_ty_basic_md, i32_ty_basic_md, i32_ty_basic_md, i32_ty_basic_md, i64_ty_basic_md], false)
1138+
.ptr_type(AddressSpace::Generic),
1139+
memory32_wait64_ptr_ty: i32_ty
1140+
.fn_type(&[ctx_ptr_ty_basic_md, i32_ty_basic_md, i32_ty_basic_md, i64_ty_basic_md, i64_ty_basic_md], false)
1141+
.ptr_type(AddressSpace::Generic),
1142+
imported_memory32_wait64_ptr_ty: i32_ty
1143+
.fn_type(&[ctx_ptr_ty_basic_md, i32_ty_basic_md, i32_ty_basic_md, i64_ty_basic_md, i64_ty_basic_md], false)
1144+
.ptr_type(AddressSpace::Generic),
1145+
memory32_notify_ptr_ty: i32_ty
1146+
.fn_type(&[ctx_ptr_ty_basic_md, i32_ty_basic_md, i32_ty_basic_md, i32_ty_basic_md], false)
1147+
.ptr_type(AddressSpace::Generic),
1148+
imported_memory32_notify_ptr_ty: i32_ty
1149+
.fn_type(&[ctx_ptr_ty_basic_md, i32_ty_basic_md, i32_ty_basic_md, i32_ty_basic_md], false)
1150+
.ptr_type(AddressSpace::Generic),
10411151

10421152
ctx_ptr_ty,
10431153
};
@@ -1658,6 +1768,132 @@ impl<'ctx, 'a> CtxType<'ctx, 'a> {
16581768
})
16591769
}
16601770

1771+
pub fn memory_wait32(
1772+
&mut self,
1773+
memory_index: MemoryIndex,
1774+
intrinsics: &Intrinsics<'ctx>,
1775+
) -> PointerValue<'ctx> {
1776+
let (cached_memory_size, wasm_module, offsets, cache_builder, ctx_ptr_value) = (
1777+
&mut self.cached_memory_size,
1778+
&self.wasm_module,
1779+
&self.offsets,
1780+
&self.cache_builder,
1781+
&self.ctx_ptr_value,
1782+
);
1783+
*cached_memory_size.entry(memory_index).or_insert_with(|| {
1784+
let (size_fn, size_fn_ty) = if wasm_module.local_memory_index(memory_index).is_some() {
1785+
(
1786+
VMBuiltinFunctionIndex::get_memory_atomic_wait32_index(),
1787+
intrinsics.memory32_wait32_ptr_ty,
1788+
)
1789+
} else {
1790+
(
1791+
VMBuiltinFunctionIndex::get_imported_memory_atomic_wait32_index(),
1792+
intrinsics.imported_memory32_wait32_ptr_ty,
1793+
)
1794+
};
1795+
let offset = offsets.vmctx_builtin_function(size_fn);
1796+
let offset = intrinsics.i32_ty.const_int(offset.into(), false);
1797+
let size_fn_ptr_ptr = unsafe { cache_builder.build_gep(*ctx_ptr_value, &[offset], "") };
1798+
1799+
let size_fn_ptr_ptr = cache_builder
1800+
.build_bitcast(
1801+
size_fn_ptr_ptr,
1802+
size_fn_ty.ptr_type(AddressSpace::Generic),
1803+
"",
1804+
)
1805+
.into_pointer_value();
1806+
1807+
cache_builder
1808+
.build_load(size_fn_ptr_ptr, "")
1809+
.into_pointer_value()
1810+
})
1811+
}
1812+
1813+
pub fn memory_wait64(
1814+
&mut self,
1815+
memory_index: MemoryIndex,
1816+
intrinsics: &Intrinsics<'ctx>,
1817+
) -> PointerValue<'ctx> {
1818+
let (cached_memory_size, wasm_module, offsets, cache_builder, ctx_ptr_value) = (
1819+
&mut self.cached_memory_size,
1820+
&self.wasm_module,
1821+
&self.offsets,
1822+
&self.cache_builder,
1823+
&self.ctx_ptr_value,
1824+
);
1825+
*cached_memory_size.entry(memory_index).or_insert_with(|| {
1826+
let (size_fn, size_fn_ty) = if wasm_module.local_memory_index(memory_index).is_some() {
1827+
(
1828+
VMBuiltinFunctionIndex::get_memory_atomic_wait64_index(),
1829+
intrinsics.memory32_wait64_ptr_ty,
1830+
)
1831+
} else {
1832+
(
1833+
VMBuiltinFunctionIndex::get_imported_memory_atomic_wait64_index(),
1834+
intrinsics.imported_memory32_wait64_ptr_ty,
1835+
)
1836+
};
1837+
let offset = offsets.vmctx_builtin_function(size_fn);
1838+
let offset = intrinsics.i32_ty.const_int(offset.into(), false);
1839+
let size_fn_ptr_ptr = unsafe { cache_builder.build_gep(*ctx_ptr_value, &[offset], "") };
1840+
1841+
let size_fn_ptr_ptr = cache_builder
1842+
.build_bitcast(
1843+
size_fn_ptr_ptr,
1844+
size_fn_ty.ptr_type(AddressSpace::Generic),
1845+
"",
1846+
)
1847+
.into_pointer_value();
1848+
1849+
cache_builder
1850+
.build_load(size_fn_ptr_ptr, "")
1851+
.into_pointer_value()
1852+
})
1853+
}
1854+
1855+
pub fn memory_notify(
1856+
&mut self,
1857+
memory_index: MemoryIndex,
1858+
intrinsics: &Intrinsics<'ctx>,
1859+
) -> PointerValue<'ctx> {
1860+
let (cached_memory_size, wasm_module, offsets, cache_builder, ctx_ptr_value) = (
1861+
&mut self.cached_memory_size,
1862+
&self.wasm_module,
1863+
&self.offsets,
1864+
&self.cache_builder,
1865+
&self.ctx_ptr_value,
1866+
);
1867+
*cached_memory_size.entry(memory_index).or_insert_with(|| {
1868+
let (size_fn, size_fn_ty) = if wasm_module.local_memory_index(memory_index).is_some() {
1869+
(
1870+
VMBuiltinFunctionIndex::get_memory_atomic_notify_index(),
1871+
intrinsics.memory32_notify_ptr_ty,
1872+
)
1873+
} else {
1874+
(
1875+
VMBuiltinFunctionIndex::get_imported_memory_atomic_notify_index(),
1876+
intrinsics.imported_memory32_notify_ptr_ty,
1877+
)
1878+
};
1879+
let offset = offsets.vmctx_builtin_function(size_fn);
1880+
let offset = intrinsics.i32_ty.const_int(offset.into(), false);
1881+
let size_fn_ptr_ptr = unsafe { cache_builder.build_gep(*ctx_ptr_value, &[offset], "") };
1882+
1883+
let size_fn_ptr_ptr = cache_builder
1884+
.build_bitcast(
1885+
size_fn_ptr_ptr,
1886+
size_fn_ty.ptr_type(AddressSpace::Generic),
1887+
"",
1888+
)
1889+
.into_pointer_value();
1890+
1891+
cache_builder
1892+
.build_load(size_fn_ptr_ptr, "")
1893+
.into_pointer_value()
1894+
})
1895+
}
1896+
16611897
pub fn get_offsets(&self) -> &VMOffsets {
16621898
&self.offsets
16631899
}

0 commit comments

Comments
 (0)