Skip to content

Commit 875ad34

Browse files
committed
chore: unix clippy happy
1 parent 48cd132 commit 875ad34

4 files changed

Lines changed: 157 additions & 15 deletions

File tree

pd-vm/src/vm/builtins_impl/runtime.rs

Lines changed: 117 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,28 @@
11
use std::time::Duration;
22

33
use super::super::{CallOutcome, HostFunctionRegistry, Value, Vm, VmError, VmResult};
4+
use super::print::format_value;
45

6+
pub(crate) const PRINT_NAME: &str = "print";
7+
pub(crate) const PRINTLN_NAME: &str = "println";
58
pub(crate) const RUNTIME_SLEEP_NAME: &str = "runtime::sleep";
69

710
pub(crate) fn register_default_host_functions(registry: &mut HostFunctionRegistry) {
11+
registry.register_static(PRINT_NAME, 1, runtime_print);
12+
registry.register_static(PRINTLN_NAME, 1, runtime_println);
813
registry.register_static(RUNTIME_SLEEP_NAME, 1, runtime_sleep);
914
}
1015

1116
pub(crate) fn bind_default_host_function(vm: &mut Vm, name: &str) -> bool {
1217
match name {
18+
PRINT_NAME => {
19+
vm.bind_static_function(PRINT_NAME, runtime_print);
20+
true
21+
}
22+
PRINTLN_NAME => {
23+
vm.bind_static_function(PRINTLN_NAME, runtime_println);
24+
true
25+
}
1326
RUNTIME_SLEEP_NAME => {
1427
vm.bind_static_function(RUNTIME_SLEEP_NAME, runtime_sleep);
1528
true
@@ -18,6 +31,24 @@ pub(crate) fn bind_default_host_function(vm: &mut Vm, name: &str) -> bool {
1831
}
1932
}
2033

34+
fn render_print_args(args: &[Value], newline: bool) -> String {
35+
let mut rendered = args.iter().map(format_value).collect::<Vec<_>>().join(" ");
36+
if newline {
37+
rendered.push('\n');
38+
}
39+
rendered
40+
}
41+
42+
fn runtime_print(vm: &mut Vm, args: &[Value]) -> VmResult<CallOutcome> {
43+
vm.write_runtime_print(render_print_args(args, false))?;
44+
Ok(CallOutcome::Return(args.to_vec()))
45+
}
46+
47+
fn runtime_println(vm: &mut Vm, args: &[Value]) -> VmResult<CallOutcome> {
48+
vm.write_runtime_print(render_print_args(args, true))?;
49+
Ok(CallOutcome::Return(args.to_vec()))
50+
}
51+
2152
fn sleep_duration(args: &[Value]) -> VmResult<Duration> {
2253
let millis = match args.first() {
2354
Some(Value::Int(value)) => *value,
@@ -47,10 +78,29 @@ fn runtime_sleep(_vm: &mut Vm, args: &[Value]) -> VmResult<CallOutcome> {
4778

4879
#[cfg(test)]
4980
mod tests {
50-
use crate::bytecode::Program;
51-
use crate::vm::{Value, Vm};
81+
use std::sync::{Arc, Mutex};
82+
83+
use crate::assembler::BytecodeBuilder;
84+
use crate::bytecode::{HostImport, Program};
85+
use crate::vm::{HostFunctionRegistry, Value, Vm, VmStatus};
5286

53-
use super::{RUNTIME_SLEEP_NAME, runtime_sleep};
87+
use super::{PRINT_NAME, PRINTLN_NAME, RUNTIME_SLEEP_NAME, runtime_sleep};
88+
89+
fn host_call_program(name: &str) -> Program {
90+
let mut bc = BytecodeBuilder::new();
91+
bc.ldc(0);
92+
bc.call(0, 1);
93+
bc.ret();
94+
Program::with_imports_and_debug(
95+
vec![Value::string("line")],
96+
bc.finish(),
97+
vec![HostImport {
98+
name: name.to_string(),
99+
arity: 1,
100+
}],
101+
None,
102+
)
103+
}
54104

55105
#[test]
56106
fn runtime_sleep_rejects_negative_milliseconds() {
@@ -71,4 +121,68 @@ mod tests {
71121
fn runtime_sleep_name_is_stable() {
72122
assert_eq!(RUNTIME_SLEEP_NAME, "runtime::sleep");
73123
}
124+
125+
#[test]
126+
fn default_print_binding_uses_vm_runtime_sink() {
127+
let lines = Arc::new(Mutex::new(Vec::<String>::new()));
128+
let sink_lines = Arc::clone(&lines);
129+
let mut vm = Vm::new(host_call_program(PRINT_NAME));
130+
vm.set_runtime_print_sink(move |rendered| {
131+
sink_lines
132+
.lock()
133+
.expect("sink should be lockable")
134+
.push(rendered);
135+
});
136+
137+
let status = vm.run().expect("vm should run");
138+
assert_eq!(status, VmStatus::Halted);
139+
assert_eq!(
140+
lines.lock().expect("sink should be lockable").as_slice(),
141+
["line"]
142+
);
143+
}
144+
145+
#[test]
146+
fn host_function_registry_includes_default_print_binding() {
147+
let lines = Arc::new(Mutex::new(Vec::<String>::new()));
148+
let sink_lines = Arc::clone(&lines);
149+
let mut vm = Vm::new(host_call_program(PRINT_NAME));
150+
vm.set_runtime_print_sink(move |rendered| {
151+
sink_lines
152+
.lock()
153+
.expect("sink should be lockable")
154+
.push(rendered);
155+
});
156+
let mut registry = HostFunctionRegistry::new();
157+
registry
158+
.bind_vm_cached(&mut vm)
159+
.expect("registry should bind print");
160+
161+
let status = vm.run().expect("vm should run");
162+
assert_eq!(status, VmStatus::Halted);
163+
assert_eq!(
164+
lines.lock().expect("sink should be lockable").as_slice(),
165+
["line"]
166+
);
167+
}
168+
169+
#[test]
170+
fn default_println_binding_appends_newline_before_sink() {
171+
let lines = Arc::new(Mutex::new(Vec::<String>::new()));
172+
let sink_lines = Arc::clone(&lines);
173+
let mut vm = Vm::new(host_call_program(PRINTLN_NAME));
174+
vm.set_runtime_print_sink(move |rendered| {
175+
sink_lines
176+
.lock()
177+
.expect("sink should be lockable")
178+
.push(rendered);
179+
});
180+
181+
let status = vm.run().expect("vm should run");
182+
assert_eq!(status, VmStatus::Halted);
183+
assert_eq!(
184+
lines.lock().expect("sink should be lockable").as_slice(),
185+
["line\n"]
186+
);
187+
}
74188
}

pd-vm/src/vm/jit/native/cranelift.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ struct ResolvedOffsets {
169169
}
170170

171171
pub(crate) fn helper_entry_address() -> usize {
172-
pd_vm_cranelift_step as usize
172+
pd_vm_cranelift_step as *const () as usize
173173
}
174174

175175
pub(crate) fn layout_fingerprint() -> VmResult<u64> {

pd-vm/src/vm/jit/native/exec.rs

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -99,14 +99,16 @@ unsafe fn flush_instruction_cache(ptr: *mut u8, len: usize) {
9999

100100
#[cfg(unix)]
101101
unsafe fn alloc_executable(len: usize) -> VmResult<*mut u8> {
102-
let ptr = libc::mmap(
103-
std::ptr::null_mut(),
104-
len,
105-
libc::PROT_READ | libc::PROT_WRITE | libc::PROT_EXEC,
106-
libc::MAP_PRIVATE | map_anon_flag(),
107-
-1,
108-
0,
109-
);
102+
let ptr = unsafe {
103+
libc::mmap(
104+
std::ptr::null_mut(),
105+
len,
106+
libc::PROT_READ | libc::PROT_WRITE | libc::PROT_EXEC,
107+
libc::MAP_PRIVATE | map_anon_flag(),
108+
-1,
109+
0,
110+
)
111+
};
110112
if ptr == libc::MAP_FAILED {
111113
return Err(VmError::JitNative(
112114
"mmap failed for executable trace buffer".to_string(),
@@ -117,18 +119,20 @@ unsafe fn alloc_executable(len: usize) -> VmResult<*mut u8> {
117119

118120
#[cfg(unix)]
119121
unsafe fn free_executable(ptr: *mut u8, len: usize) {
120-
let _ = libc::munmap(ptr.cast(), len);
122+
let _ = unsafe { libc::munmap(ptr.cast(), len) };
121123
}
122124

123125
#[cfg(unix)]
124126
unsafe fn flush_instruction_cache(ptr: *mut u8, len: usize) {
127+
let _ = (ptr, len);
128+
125129
#[cfg(all(target_arch = "aarch64", target_os = "macos"))]
126130
{
127131
unsafe extern "C" {
128132
fn sys_icache_invalidate(start: *mut core::ffi::c_void, len: usize);
129133
}
130134

131-
sys_icache_invalidate(ptr.cast(), len);
135+
unsafe { sys_icache_invalidate(ptr.cast(), len) };
132136
}
133137

134138
#[cfg(all(target_arch = "aarch64", not(target_os = "macos")))]
@@ -137,7 +141,7 @@ unsafe fn flush_instruction_cache(ptr: *mut u8, len: usize) {
137141
fn __clear_cache(start: *mut u8, end: *mut u8);
138142
}
139143

140-
__clear_cache(ptr, ptr.add(len));
144+
unsafe { __clear_cache(ptr, ptr.add(len)) };
141145
}
142146
}
143147

pd-vm/src/vm/mod.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,7 @@ pub trait HostAsyncBridge: Send {
256256
pub type StaticHostFunction = fn(&mut Vm, &[Value]) -> VmResult<CallOutcome>;
257257

258258
type HostFactory = dyn Fn() -> Box<dyn HostFunction> + Send + Sync;
259+
type RuntimePrintSink = dyn FnMut(String) + Send;
259260

260261
enum RegistryEntryKind {
261262
Factory(Box<HostFactory>),
@@ -463,6 +464,7 @@ pub struct Vm {
463464
jit_native_bridge_stats_enabled: bool,
464465
jit_native_bridge_counts: HashMap<&'static str, u64>,
465466
async_bridge: Option<Box<dyn HostAsyncBridge>>,
467+
runtime_print_sink: Option<Box<RuntimePrintSink>>,
466468
waiting_host_op: Option<WaitingHostOp>,
467469
next_host_op_id: HostOpId,
468470
io_state: builtins_impl::IoState,
@@ -658,6 +660,7 @@ impl Vm {
658660
jit_native_bridge_stats_enabled: false,
659661
jit_native_bridge_counts: HashMap::new(),
660662
async_bridge: None,
663+
runtime_print_sink: None,
661664
waiting_host_op: None,
662665
next_host_op_id: 1,
663666
io_state: builtins_impl::IoState::default(),
@@ -898,6 +901,27 @@ impl Vm {
898901
self.async_bridge = None;
899902
}
900903

904+
pub fn set_runtime_print_sink<F>(&mut self, sink: F)
905+
where
906+
F: FnMut(String) + Send + 'static,
907+
{
908+
self.runtime_print_sink = Some(Box::new(sink));
909+
}
910+
911+
pub fn clear_runtime_print_sink(&mut self) {
912+
self.runtime_print_sink = None;
913+
}
914+
915+
pub(crate) fn write_runtime_print(&mut self, rendered: String) -> VmResult<()> {
916+
let Some(sink) = self.runtime_print_sink.as_mut() else {
917+
return Err(VmError::HostError(
918+
"runtime print sink is not configured".to_string(),
919+
));
920+
};
921+
sink(rendered);
922+
Ok(())
923+
}
924+
901925
pub fn allocate_host_op_id(&mut self) -> HostOpId {
902926
let op_id = self.next_host_op_id;
903927
self.next_host_op_id = self.next_host_op_id.wrapping_add(1).max(1);

0 commit comments

Comments
 (0)