From 95fe9cbccd2d8302f7c461c00bb4ff7105f615da Mon Sep 17 00:00:00 2001 From: Folkert Date: Thu, 8 Dec 2022 23:22:06 +0100 Subject: [PATCH] pass the pointer to shared memory around, instead of using a global --- .../compiler/builtins/bitcode/src/expect.zig | 33 +++------ crates/compiler/builtins/bitcode/src/main.zig | 4 +- crates/compiler/builtins/src/bitcode.rs | 4 +- crates/compiler/gen_llvm/src/llvm/build.rs | 10 ++- crates/compiler/gen_llvm/src/llvm/expect.rs | 67 ++++++++++++------- crates/compiler/gen_llvm/src/llvm/lowlevel.rs | 5 +- 6 files changed, 68 insertions(+), 55 deletions(-) diff --git a/crates/compiler/builtins/bitcode/src/expect.zig b/crates/compiler/builtins/bitcode/src/expect.zig index de53a4038d..0c1c51f583 100644 --- a/crates/compiler/builtins/bitcode/src/expect.zig +++ b/crates/compiler/builtins/bitcode/src/expect.zig @@ -44,8 +44,6 @@ pub fn expectFailedStartSharedFile() callconv(.C) [*]u8 { const ptr = @ptrCast([*]u8, shared_ptr); - SHARED_BUFFER = ptr[0..length]; - return ptr; } else { unreachable; @@ -81,17 +79,11 @@ pub fn readSharedBufferEnv() callconv(.C) void { } } -fn get_atomic_ptr() *Atomic(u32) { - const usize_ptr = @ptrCast([*]u32, @alignCast(@alignOf(usize), SHARED_BUFFER.ptr)); - const atomic_ptr = @ptrCast(*Atomic(u32), &usize_ptr[5]); - - return atomic_ptr; -} - -pub fn expectFailedFinalize() callconv(.C) void { +pub fn notifyParent(shared_buffer: [*]u8, tag: u32) callconv(.C) void { if (builtin.os.tag == .macos or builtin.os.tag == .linux) { - const atomic_ptr = get_atomic_ptr(); - atomic_ptr.storeUnchecked(1); + const usize_ptr = @ptrCast([*]u32, @alignCast(@alignOf(usize), shared_buffer)); + const atomic_ptr = @ptrCast(*Atomic(u32), &usize_ptr[5]); + atomic_ptr.storeUnchecked(tag); // wait till the parent is done before proceeding const Ordering = std.atomic.Ordering; @@ -101,15 +93,10 @@ pub fn expectFailedFinalize() callconv(.C) void { } } -pub fn sendDbg() callconv(.C) void { - if (builtin.os.tag == .macos or builtin.os.tag == .linux) { - const atomic_ptr = get_atomic_ptr(); - atomic_ptr.storeUnchecked(2); - - // wait till the parent is done before proceeding - const Ordering = std.atomic.Ordering; - while (atomic_ptr.load(Ordering.Acquire) != 0) { - std.atomic.spinLoopHint(); - } - } +pub fn notifyParentExpect(shared_buffer: [*]u8) callconv(.C) void { + notifyParent(shared_buffer, 1); +} + +pub fn notifyParentDbg(shared_buffer: [*]u8) callconv(.C) void { + notifyParent(shared_buffer, 2); } diff --git a/crates/compiler/builtins/bitcode/src/main.zig b/crates/compiler/builtins/bitcode/src/main.zig index 5b2ebb5bef..56a403a8c8 100644 --- a/crates/compiler/builtins/bitcode/src/main.zig +++ b/crates/compiler/builtins/bitcode/src/main.zig @@ -172,8 +172,8 @@ comptime { if (builtin.target.cpu.arch != .wasm32) { exportUtilsFn(expect.expectFailedStartSharedBuffer, "expect_failed_start_shared_buffer"); exportUtilsFn(expect.expectFailedStartSharedFile, "expect_failed_start_shared_file"); - exportUtilsFn(expect.expectFailedFinalize, "expect_failed_finalize"); - exportUtilsFn(expect.sendDbg, "send_dbg"); + exportUtilsFn(expect.notifyParentExpect, "notify_parent_expect"); + exportUtilsFn(expect.notifyParentDbg, "notify_parent_dbg"); // sets the buffer used for expect failures @export(expect.setSharedBuffer, .{ .name = "set_shared_buffer", .linkage = .Weak }); diff --git a/crates/compiler/builtins/src/bitcode.rs b/crates/compiler/builtins/src/bitcode.rs index 1a77570dc1..f6733f7f4c 100644 --- a/crates/compiler/builtins/src/bitcode.rs +++ b/crates/compiler/builtins/src/bitcode.rs @@ -424,9 +424,9 @@ pub const UTILS_EXPECT_FAILED_START_SHARED_BUFFER: &str = "roc_builtins.utils.expect_failed_start_shared_buffer"; pub const UTILS_EXPECT_FAILED_START_SHARED_FILE: &str = "roc_builtins.utils.expect_failed_start_shared_file"; -pub const UTILS_EXPECT_FAILED_FINALIZE: &str = "roc_builtins.utils.expect_failed_finalize"; pub const UTILS_EXPECT_READ_ENV_SHARED_BUFFER: &str = "roc_builtins.utils.read_env_shared_buffer"; -pub const UTILS_SEND_DBG: &str = "roc_builtins.utils.send_dbg"; +pub const NOTIFY_PARENT_EXPECT: &str = "roc_builtins.utils.notify_parent_expect"; +pub const NOTIFY_PARENT_DBG: &str = "roc_builtins.utils.notify_parent_dbg"; pub const UTILS_LONGJMP: &str = "longjmp"; pub const UTILS_SETJMP: &str = "setjmp"; diff --git a/crates/compiler/gen_llvm/src/llvm/build.rs b/crates/compiler/gen_llvm/src/llvm/build.rs index ded14b2b82..5c710e6939 100644 --- a/crates/compiler/gen_llvm/src/llvm/build.rs +++ b/crates/compiler/gen_llvm/src/llvm/build.rs @@ -3,7 +3,7 @@ use crate::llvm::build_list::{self, allocate_list, empty_polymorphic_list}; use crate::llvm::convert::{ argument_type_from_layout, basic_type_from_builtin, basic_type_from_layout, zig_str_type, }; -use crate::llvm::expect::clone_to_shared_memory; +use crate::llvm::expect::{clone_to_shared_memory, SharedMemoryPointer}; use crate::llvm::refcounting::{ build_reset, decrement_refcount_layout, increment_refcount_layout, PointerToRefcount, }; @@ -2611,17 +2611,20 @@ pub fn build_exp_stmt<'a, 'ctx, 'env>( match env.target_info.ptr_width() { roc_target::PtrWidth::Bytes8 => { + let shared_memory = SharedMemoryPointer::get(env); + clone_to_shared_memory( env, scope, layout_ids, + &shared_memory, *cond_symbol, *region, lookups, ); if let LlvmBackendMode::BinaryDev = env.mode { - crate::llvm::expect::finalize(env); + crate::llvm::expect::notify_parent_expect(env, &shared_memory); } bd.build_unconditional_branch(then_block); @@ -2677,10 +2680,13 @@ pub fn build_exp_stmt<'a, 'ctx, 'env>( match env.target_info.ptr_width() { roc_target::PtrWidth::Bytes8 => { + let shared_memory = SharedMemoryPointer::get(env); + clone_to_shared_memory( env, scope, layout_ids, + &shared_memory, *cond_symbol, *region, lookups, diff --git a/crates/compiler/gen_llvm/src/llvm/expect.rs b/crates/compiler/gen_llvm/src/llvm/expect.rs index 606e0aab52..567ccdf642 100644 --- a/crates/compiler/gen_llvm/src/llvm/expect.rs +++ b/crates/compiler/gen_llvm/src/llvm/expect.rs @@ -18,6 +18,32 @@ use super::build::{ Scope, }; +pub(crate) struct SharedMemoryPointer<'ctx>(PointerValue<'ctx>); + +impl<'ctx> SharedMemoryPointer<'ctx> { + pub(crate) fn get<'a, 'env>(env: &Env<'a, 'ctx, 'env>) -> Self { + let start_function = if let LlvmBackendMode::BinaryDev = env.mode { + bitcode::UTILS_EXPECT_FAILED_START_SHARED_FILE + } else { + bitcode::UTILS_EXPECT_FAILED_START_SHARED_BUFFER + }; + + let func = env.module.get_function(start_function).unwrap(); + + let call_result = env + .builder + .build_call(func, &[], "call_expect_start_failed"); + + let ptr = call_result + .try_as_basic_value() + .left() + .unwrap() + .into_pointer_value(); + + Self(ptr) + } +} + #[derive(Debug, Clone, Copy)] struct Cursors<'ctx> { offset: IntValue<'ctx>, @@ -94,48 +120,39 @@ fn write_state<'a, 'ctx, 'env>( env.builder.build_store(offset_ptr, offset); } -pub(crate) fn finalize(env: &Env) { +pub(crate) fn notify_parent_expect(env: &Env, shared_memory: &SharedMemoryPointer) { let func = env .module - .get_function(bitcode::UTILS_EXPECT_FAILED_FINALIZE) + .get_function(bitcode::NOTIFY_PARENT_EXPECT) .unwrap(); - env.builder - .build_call(func, &[], "call_expect_failed_finalize"); + env.builder.build_call( + func, + &[shared_memory.0.into()], + "call_expect_failed_finalize", + ); } -pub(crate) fn send_dbg(env: &Env) { - let func = env.module.get_function(bitcode::UTILS_SEND_DBG).unwrap(); +pub(crate) fn notify_parent_dbg(env: &Env, shared_memory: &SharedMemoryPointer) { + let func = env.module.get_function(bitcode::NOTIFY_PARENT_DBG).unwrap(); - env.builder - .build_call(func, &[], "call_expect_failed_finalize"); + env.builder.build_call( + func, + &[shared_memory.0.into()], + "call_expect_failed_finalize", + ); } pub(crate) fn clone_to_shared_memory<'a, 'ctx, 'env>( env: &Env<'a, 'ctx, 'env>, scope: &Scope<'a, 'ctx>, layout_ids: &mut LayoutIds<'a>, + shared_memory: &SharedMemoryPointer<'ctx>, condition: Symbol, region: Region, lookups: &[Symbol], ) { - let start_function = if let LlvmBackendMode::BinaryDev = env.mode { - bitcode::UTILS_EXPECT_FAILED_START_SHARED_FILE - } else { - bitcode::UTILS_EXPECT_FAILED_START_SHARED_BUFFER - }; - - let func = env.module.get_function(start_function).unwrap(); - - let call_result = env - .builder - .build_call(func, &[], "call_expect_start_failed"); - - let original_ptr = call_result - .try_as_basic_value() - .left() - .unwrap() - .into_pointer_value(); + let original_ptr = shared_memory.0; let (count, mut offset) = read_state(env, original_ptr); diff --git a/crates/compiler/gen_llvm/src/llvm/lowlevel.rs b/crates/compiler/gen_llvm/src/llvm/lowlevel.rs index 5eb6fbb2b6..d732b6ce1e 100644 --- a/crates/compiler/gen_llvm/src/llvm/lowlevel.rs +++ b/crates/compiler/gen_llvm/src/llvm/lowlevel.rs @@ -1126,16 +1126,19 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>( if env.mode.runs_expects() { let region = unsafe { std::mem::transmute::<_, roc_region::all::Region>(args[0]) }; + let shared_memory = crate::llvm::expect::SharedMemoryPointer::get(env); + crate::llvm::expect::clone_to_shared_memory( env, scope, layout_ids, + &shared_memory, args[0], region, &[args[0]], ); - crate::llvm::expect::send_dbg(env); + crate::llvm::expect::notify_parent_dbg(env, &shared_memory); } condition