mirror of
https://github.com/roc-lang/roc.git
synced 2025-10-03 08:34:33 +00:00
Move expect
zig code out of utils
This commit is contained in:
parent
06203163eb
commit
9b05d8dd50
5 changed files with 164 additions and 149 deletions
147
compiler/builtins/bitcode/src/expect.zig
Normal file
147
compiler/builtins/bitcode/src/expect.zig
Normal file
|
@ -0,0 +1,147 @@
|
||||||
|
const std = @import("std");
|
||||||
|
const utils = @import("utils.zig");
|
||||||
|
const CSlice = utils.CSlice;
|
||||||
|
const always_inline = std.builtin.CallOptions.Modifier.always_inline;
|
||||||
|
|
||||||
|
const Failure = struct {
|
||||||
|
start_line: u32,
|
||||||
|
end_line: u32,
|
||||||
|
start_col: u16,
|
||||||
|
end_col: u16,
|
||||||
|
};
|
||||||
|
|
||||||
|
// BEGIN FAILURES GLOBALS ///////////////////
|
||||||
|
var failures_mutex = std.Thread.Mutex{};
|
||||||
|
var failures: [*]Failure = undefined;
|
||||||
|
var failure_length: usize = 0;
|
||||||
|
var failure_capacity: usize = 0;
|
||||||
|
// END FAILURES GLOBALS /////////////////////
|
||||||
|
|
||||||
|
pub fn expectFailed(
|
||||||
|
start_line: u32,
|
||||||
|
end_line: u32,
|
||||||
|
start_col: u16,
|
||||||
|
end_col: u16,
|
||||||
|
) void {
|
||||||
|
const new_failure = Failure{ .start_line = start_line, .end_line = end_line, .start_col = start_col, .end_col = end_col };
|
||||||
|
|
||||||
|
// Lock the failures mutex before reading from any of the failures globals,
|
||||||
|
// and then release the lock once we're done modifying things.
|
||||||
|
|
||||||
|
// TODO FOR ZIG 0.9: this API changed in https://github.com/ziglang/zig/commit/008b0ec5e58fc7e31f3b989868a7d1ea4df3f41d
|
||||||
|
// to this: https://github.com/ziglang/zig/blob/c710d5eefe3f83226f1651947239730e77af43cb/lib/std/Thread/Mutex.zig
|
||||||
|
//
|
||||||
|
// ...so just use these two lines of code instead of the non-commented-out ones to make this work in Zig 0.9:
|
||||||
|
//
|
||||||
|
// failures_mutex.lock();
|
||||||
|
// defer failures_mutex.release();
|
||||||
|
//
|
||||||
|
// 👆 👆 👆 IF UPGRADING TO ZIG 0.9, LOOK HERE! 👆 👆 👆
|
||||||
|
const held = failures_mutex.acquire();
|
||||||
|
defer held.release();
|
||||||
|
|
||||||
|
// If we don't have enough capacity to add a failure, allocate a new failures pointer.
|
||||||
|
if (failure_length >= failure_capacity) {
|
||||||
|
if (failure_capacity > 0) {
|
||||||
|
// We already had previous failures allocated, so try to realloc in order
|
||||||
|
// to grow the size in-place without having to memcpy bytes over.
|
||||||
|
const old_pointer = failures;
|
||||||
|
const old_bytes = failure_capacity * @sizeOf(Failure);
|
||||||
|
|
||||||
|
failure_capacity *= 2;
|
||||||
|
|
||||||
|
const new_bytes = failure_capacity * @sizeOf(Failure);
|
||||||
|
const failures_u8 = @ptrCast([*]u8, @alignCast(@alignOf(Failure), failures));
|
||||||
|
const raw_pointer = utils.realloc(failures_u8, new_bytes, old_bytes, @alignOf(Failure));
|
||||||
|
|
||||||
|
failures = @ptrCast([*]Failure, @alignCast(@alignOf(Failure), raw_pointer));
|
||||||
|
|
||||||
|
// If realloc wasn't able to expand in-place (that is, it returned a different pointer),
|
||||||
|
// then copy the data into the new pointer and dealloc the old one.
|
||||||
|
if (failures != old_pointer) {
|
||||||
|
const old_pointer_u8 = @ptrCast([*]u8, old_pointer);
|
||||||
|
utils.memcpy(@ptrCast([*]u8, failures), old_pointer_u8, old_bytes);
|
||||||
|
utils.dealloc(old_pointer_u8, @alignOf(Failure));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// We've never had any failures before, so allocate the failures for the first time.
|
||||||
|
failure_capacity = 10;
|
||||||
|
|
||||||
|
const raw_pointer = utils.alloc(failure_capacity * @sizeOf(Failure), @alignOf(Failure));
|
||||||
|
|
||||||
|
failures = @ptrCast([*]Failure, @alignCast(@alignOf(Failure), raw_pointer));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
failures[failure_length] = new_failure;
|
||||||
|
failure_length += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn expectFailedC(
|
||||||
|
start_line: u32,
|
||||||
|
end_line: u32,
|
||||||
|
start_col: u16,
|
||||||
|
end_col: u16,
|
||||||
|
) callconv(.C) void {
|
||||||
|
return @call(.{ .modifier = always_inline }, expectFailed, .{ start_line, end_line, start_col, end_col });
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn getExpectFailures() []Failure {
|
||||||
|
// TODO FOR ZIG 0.9: this API changed in https://github.com/ziglang/zig/commit/008b0ec5e58fc7e31f3b989868a7d1ea4df3f41d
|
||||||
|
// to this: https://github.com/ziglang/zig/blob/c710d5eefe3f83226f1651947239730e77af43cb/lib/std/Thread/Mutex.zig
|
||||||
|
//
|
||||||
|
// ...so just use these two lines of code instead of the non-commented-out ones to make this work in Zig 0.9:
|
||||||
|
//
|
||||||
|
// failures_mutex.lock();
|
||||||
|
// defer failures_mutex.release();
|
||||||
|
//
|
||||||
|
// 👆 👆 👆 IF UPGRADING TO ZIG 0.9, LOOK HERE! 👆 👆 👆
|
||||||
|
const held = failures_mutex.acquire();
|
||||||
|
defer held.release();
|
||||||
|
|
||||||
|
// defensively clone failures, in case someone modifies the originals after the mutex has been released.
|
||||||
|
const num_bytes = failure_length * @sizeOf(Failure);
|
||||||
|
const raw_clones = utils.alloc(num_bytes, @alignOf(Failure));
|
||||||
|
const clones = @ptrCast([*]Failure, @alignCast(@alignOf(Failure), raw_clones));
|
||||||
|
|
||||||
|
utils.memcpy(@ptrCast([*]u8, clones), @ptrCast([*]u8, raw_clones), num_bytes);
|
||||||
|
|
||||||
|
return clones[0..failure_length];
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn getExpectFailuresC() callconv(.C) CSlice {
|
||||||
|
var bytes = @ptrCast(*c_void, failures);
|
||||||
|
|
||||||
|
return .{ .pointer = bytes, .len = failure_length };
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn deinitFailures() void {
|
||||||
|
// TODO FOR ZIG 0.9: this API changed in https://github.com/ziglang/zig/commit/008b0ec5e58fc7e31f3b989868a7d1ea4df3f41d
|
||||||
|
// to this: https://github.com/ziglang/zig/blob/c710d5eefe3f83226f1651947239730e77af43cb/lib/std/Thread/Mutex.zig
|
||||||
|
//
|
||||||
|
// ...so just use these two lines of code instead of the non-commented-out ones to make this work in Zig 0.9:
|
||||||
|
//
|
||||||
|
// failures_mutex.lock();
|
||||||
|
// defer failures_mutex.release();
|
||||||
|
//
|
||||||
|
// 👆 👆 👆 IF UPGRADING TO ZIG 0.9, LOOK HERE! 👆 👆 👆
|
||||||
|
const held = failures_mutex.acquire();
|
||||||
|
defer held.release();
|
||||||
|
|
||||||
|
utils.dealloc(@ptrCast([*]u8, failures), @alignOf(Failure));
|
||||||
|
failure_length = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn deinitFailuresC() callconv(.C) void {
|
||||||
|
return @call(.{ .modifier = always_inline }, deinitFailures, .{});
|
||||||
|
}
|
||||||
|
|
||||||
|
test "expectFailure does something" {
|
||||||
|
defer deinitFailures();
|
||||||
|
|
||||||
|
try std.testing.expectEqual(getExpectFailures().len, 0);
|
||||||
|
expectFailed(1, 2, 3, 4);
|
||||||
|
try std.testing.expectEqual(getExpectFailures().len, 1);
|
||||||
|
const what_it_should_look_like = Failure{ .start_line = 1, .end_line = 2, .start_col = 3, .end_col = 4 };
|
||||||
|
try std.testing.expectEqual(getExpectFailures()[0], what_it_should_look_like);
|
||||||
|
}
|
|
@ -1,6 +1,7 @@
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const math = std.math;
|
const math = std.math;
|
||||||
const utils = @import("utils.zig");
|
const utils = @import("utils.zig");
|
||||||
|
const expect = @import("expect.zig");
|
||||||
|
|
||||||
const ROC_BUILTINS = "roc_builtins";
|
const ROC_BUILTINS = "roc_builtins";
|
||||||
const NUM = "num";
|
const NUM = "num";
|
||||||
|
@ -146,9 +147,9 @@ comptime {
|
||||||
exportUtilsFn(utils.increfC, "incref");
|
exportUtilsFn(utils.increfC, "incref");
|
||||||
exportUtilsFn(utils.decrefC, "decref");
|
exportUtilsFn(utils.decrefC, "decref");
|
||||||
exportUtilsFn(utils.decrefCheckNullC, "decref_check_null");
|
exportUtilsFn(utils.decrefCheckNullC, "decref_check_null");
|
||||||
exportUtilsFn(utils.expectFailedC, "expect_failed");
|
exportExpectFn(expect.expectFailedC, "expect_failed");
|
||||||
exportUtilsFn(utils.getExpectFailuresC, "get_expect_failures");
|
exportExpectFn(expect.getExpectFailuresC, "get_expect_failures");
|
||||||
exportUtilsFn(utils.deinitFailuresC, "deinit_failures");
|
exportExpectFn(expect.deinitFailuresC, "deinit_failures");
|
||||||
|
|
||||||
@export(utils.panic, .{ .name = "roc_builtins.utils." ++ "panic", .linkage = .Weak });
|
@export(utils.panic, .{ .name = "roc_builtins.utils." ++ "panic", .linkage = .Weak });
|
||||||
}
|
}
|
||||||
|
@ -177,6 +178,10 @@ fn exportUtilsFn(comptime func: anytype, comptime func_name: []const u8) void {
|
||||||
exportBuiltinFn(func, "utils." ++ func_name);
|
exportBuiltinFn(func, "utils." ++ func_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn exportExpectFn(comptime func: anytype, comptime func_name: []const u8) void {
|
||||||
|
exportBuiltinFn(func, "expect." ++ func_name);
|
||||||
|
}
|
||||||
|
|
||||||
// Custom panic function, as builtin Zig version errors during LLVM verification
|
// Custom panic function, as builtin Zig version errors during LLVM verification
|
||||||
pub fn panic(message: []const u8, stacktrace: ?*std.builtin.StackTrace) noreturn {
|
pub fn panic(message: []const u8, stacktrace: ?*std.builtin.StackTrace) noreturn {
|
||||||
const builtin = @import("builtin");
|
const builtin = @import("builtin");
|
||||||
|
|
|
@ -82,6 +82,10 @@ pub fn panic(c_ptr: *c_void, alignment: u32) callconv(.C) void {
|
||||||
return @call(.{ .modifier = always_inline }, roc_panic, .{ c_ptr, alignment });
|
return @call(.{ .modifier = always_inline }, roc_panic, .{ c_ptr, alignment });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn memcpy(dst: [*]u8, src: [*]u8, size: usize) void {
|
||||||
|
@call(.{ .modifier = always_inline }, roc_memcpy, .{ dst, src, size });
|
||||||
|
}
|
||||||
|
|
||||||
// indirection because otherwise zig creates an alias to the panic function which our LLVM code
|
// indirection because otherwise zig creates an alias to the panic function which our LLVM code
|
||||||
// does not know how to deal with
|
// does not know how to deal with
|
||||||
pub fn test_panic(c_ptr: *c_void, alignment: u32) callconv(.C) void {
|
pub fn test_panic(c_ptr: *c_void, alignment: u32) callconv(.C) void {
|
||||||
|
@ -229,142 +233,11 @@ pub fn allocateWithRefcount(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const Failure = struct {
|
pub const CSlice = extern struct {
|
||||||
start_line: u32,
|
|
||||||
end_line: u32,
|
|
||||||
start_col: u16,
|
|
||||||
end_col: u16,
|
|
||||||
};
|
|
||||||
|
|
||||||
// BEGIN FAILURES GLOBALS ///////////////////
|
|
||||||
var failures_mutex = std.Thread.Mutex{};
|
|
||||||
var failures: [*]Failure = undefined;
|
|
||||||
var failure_length: usize = 0;
|
|
||||||
var failure_capacity: usize = 0;
|
|
||||||
// END FAILURES GLOBALS /////////////////////
|
|
||||||
|
|
||||||
pub fn expectFailed(
|
|
||||||
start_line: u32,
|
|
||||||
end_line: u32,
|
|
||||||
start_col: u16,
|
|
||||||
end_col: u16,
|
|
||||||
) void {
|
|
||||||
const new_failure = Failure{ .start_line = start_line, .end_line = end_line, .start_col = start_col, .end_col = end_col };
|
|
||||||
|
|
||||||
// Lock the failures mutex before reading from any of the failures globals,
|
|
||||||
// and then release the lock once we're done modifying things.
|
|
||||||
|
|
||||||
// TODO FOR ZIG 0.9: this API changed in https://github.com/ziglang/zig/commit/008b0ec5e58fc7e31f3b989868a7d1ea4df3f41d
|
|
||||||
// to this: https://github.com/ziglang/zig/blob/c710d5eefe3f83226f1651947239730e77af43cb/lib/std/Thread/Mutex.zig
|
|
||||||
//
|
|
||||||
// ...so just use these two lines of code instead of the non-commented-out ones to make this work in Zig 0.9:
|
|
||||||
//
|
|
||||||
// failures_mutex.lock();
|
|
||||||
// defer failures_mutex.release();
|
|
||||||
//
|
|
||||||
// 👆 👆 👆 IF UPGRADING TO ZIG 0.9, LOOK HERE! 👆 👆 👆
|
|
||||||
const held = failures_mutex.acquire();
|
|
||||||
defer held.release();
|
|
||||||
|
|
||||||
// If we don't have enough capacity to add a failure, allocate a new failures pointer.
|
|
||||||
if (failure_length >= failure_capacity) {
|
|
||||||
if (failure_capacity > 0) {
|
|
||||||
// We already had previous failures allocated, so try to realloc in order
|
|
||||||
// to grow the size in-place without having to memcpy bytes over.
|
|
||||||
const old_pointer = failures;
|
|
||||||
const old_bytes = failure_capacity * @sizeOf(Failure);
|
|
||||||
|
|
||||||
failure_capacity *= 2;
|
|
||||||
|
|
||||||
const new_bytes = failure_capacity * @sizeOf(Failure);
|
|
||||||
const raw_pointer = roc_realloc(failures, new_bytes, old_bytes, @alignOf(Failure));
|
|
||||||
|
|
||||||
failures = @ptrCast([*]Failure, @alignCast(@alignOf(Failure), raw_pointer));
|
|
||||||
|
|
||||||
// If realloc wasn't able to expand in-place (that is, it returned a different pointer),
|
|
||||||
// then copy the data into the new pointer and dealloc the old one.
|
|
||||||
if (failures != old_pointer) {
|
|
||||||
roc_memcpy(@ptrCast([*]u8, failures), @ptrCast([*]u8, old_pointer), old_bytes);
|
|
||||||
roc_dealloc(old_pointer, @alignOf(Failure));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// We've never had any failures before, so allocate the failures for the first time.
|
|
||||||
failure_capacity = 10;
|
|
||||||
|
|
||||||
const raw_pointer = roc_alloc(failure_capacity * @sizeOf(Failure), @alignOf(Failure));
|
|
||||||
|
|
||||||
failures = @ptrCast([*]Failure, @alignCast(@alignOf(Failure), raw_pointer));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
failures[failure_length] = new_failure;
|
|
||||||
failure_length += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn expectFailedC(
|
|
||||||
start_line: u32,
|
|
||||||
end_line: u32,
|
|
||||||
start_col: u16,
|
|
||||||
end_col: u16,
|
|
||||||
) callconv(.C) void {
|
|
||||||
return @call(.{ .modifier = always_inline }, expectFailed, .{ start_line, end_line, start_col, end_col });
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn getExpectFailures() []Failure {
|
|
||||||
// TODO FOR ZIG 0.9: this API changed in https://github.com/ziglang/zig/commit/008b0ec5e58fc7e31f3b989868a7d1ea4df3f41d
|
|
||||||
// to this: https://github.com/ziglang/zig/blob/c710d5eefe3f83226f1651947239730e77af43cb/lib/std/Thread/Mutex.zig
|
|
||||||
//
|
|
||||||
// ...so just use these two lines of code instead of the non-commented-out ones to make this work in Zig 0.9:
|
|
||||||
//
|
|
||||||
// failures_mutex.lock();
|
|
||||||
// defer failures_mutex.release();
|
|
||||||
//
|
|
||||||
// 👆 👆 👆 IF UPGRADING TO ZIG 0.9, LOOK HERE! 👆 👆 👆
|
|
||||||
const held = failures_mutex.acquire();
|
|
||||||
defer held.release();
|
|
||||||
|
|
||||||
// defensively clone failures, in case someone modifies the originals after the mutex has been released.
|
|
||||||
const num_bytes = failure_length * @sizeOf(Failure);
|
|
||||||
const raw_clones = roc_alloc(num_bytes, @alignOf(Failure));
|
|
||||||
const clones = @ptrCast([*]Failure, @alignCast(@alignOf(Failure), raw_clones));
|
|
||||||
|
|
||||||
roc_memcpy(@ptrCast([*]u8, clones), @ptrCast([*]u8, raw_clones), num_bytes);
|
|
||||||
|
|
||||||
return clones[0..failure_length];
|
|
||||||
}
|
|
||||||
|
|
||||||
const CSlice = extern struct {
|
|
||||||
pointer: *c_void,
|
pointer: *c_void,
|
||||||
len: usize,
|
len: usize,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn getExpectFailuresC() callconv(.C) CSlice {
|
|
||||||
var bytes = @ptrCast(*c_void, failures);
|
|
||||||
|
|
||||||
return .{ .pointer = bytes, .len = failure_length };
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn deinitFailures() void {
|
|
||||||
// TODO FOR ZIG 0.9: this API changed in https://github.com/ziglang/zig/commit/008b0ec5e58fc7e31f3b989868a7d1ea4df3f41d
|
|
||||||
// to this: https://github.com/ziglang/zig/blob/c710d5eefe3f83226f1651947239730e77af43cb/lib/std/Thread/Mutex.zig
|
|
||||||
//
|
|
||||||
// ...so just use these two lines of code instead of the non-commented-out ones to make this work in Zig 0.9:
|
|
||||||
//
|
|
||||||
// failures_mutex.lock();
|
|
||||||
// defer failures_mutex.release();
|
|
||||||
//
|
|
||||||
// 👆 👆 👆 IF UPGRADING TO ZIG 0.9, LOOK HERE! 👆 👆 👆
|
|
||||||
const held = failures_mutex.acquire();
|
|
||||||
defer held.release();
|
|
||||||
|
|
||||||
roc_dealloc(failures, @alignOf(Failure));
|
|
||||||
failure_length = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn deinitFailuresC() callconv(.C) void {
|
|
||||||
return @call(.{ .modifier = always_inline }, deinitFailures, .{});
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn unsafeReallocate(
|
pub fn unsafeReallocate(
|
||||||
source_ptr: [*]u8,
|
source_ptr: [*]u8,
|
||||||
alignment: u32,
|
alignment: u32,
|
||||||
|
@ -429,13 +302,3 @@ test "increfC, static data" {
|
||||||
increfC(ptr_to_refcount, 2);
|
increfC(ptr_to_refcount, 2);
|
||||||
try std.testing.expectEqual(mock_rc, REFCOUNT_MAX_ISIZE);
|
try std.testing.expectEqual(mock_rc, REFCOUNT_MAX_ISIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
test "expectFailure does something" {
|
|
||||||
defer deinitFailures();
|
|
||||||
|
|
||||||
try std.testing.expectEqual(getExpectFailures().len, 0);
|
|
||||||
expectFailed(1, 2, 3, 4);
|
|
||||||
try std.testing.expectEqual(getExpectFailures().len, 1);
|
|
||||||
const what_it_should_look_like = Failure{ .start_line = 1, .end_line = 2, .start_col = 3, .end_col = 4 };
|
|
||||||
try std.testing.expectEqual(getExpectFailures()[0], what_it_should_look_like);
|
|
||||||
}
|
|
||||||
|
|
|
@ -336,6 +336,6 @@ pub const UTILS_TEST_PANIC: &str = "roc_builtins.utils.test_panic";
|
||||||
pub const UTILS_INCREF: &str = "roc_builtins.utils.incref";
|
pub const UTILS_INCREF: &str = "roc_builtins.utils.incref";
|
||||||
pub const UTILS_DECREF: &str = "roc_builtins.utils.decref";
|
pub const UTILS_DECREF: &str = "roc_builtins.utils.decref";
|
||||||
pub const UTILS_DECREF_CHECK_NULL: &str = "roc_builtins.utils.decref_check_null";
|
pub const UTILS_DECREF_CHECK_NULL: &str = "roc_builtins.utils.decref_check_null";
|
||||||
pub const UTILS_EXPECT_FAILED: &str = "roc_builtins.utils.expect_failed";
|
pub const UTILS_EXPECT_FAILED: &str = "roc_builtins.expect.expect_failed";
|
||||||
pub const UTILS_GET_EXPECT_FAILURES: &str = "roc_builtins.utils.get_expect_failures";
|
pub const UTILS_GET_EXPECT_FAILURES: &str = "roc_builtins.expect.get_expect_failures";
|
||||||
pub const UTILS_DEINIT_FAILURES: &str = "roc_builtins.utils.deinit_failures";
|
pub const UTILS_DEINIT_FAILURES: &str = "roc_builtins.expect.deinit_failures";
|
||||||
|
|
|
@ -192,7 +192,7 @@ fn create_llvm_module<'a>(
|
||||||
for function in FunctionIterator::from_module(module) {
|
for function in FunctionIterator::from_module(module) {
|
||||||
let name = function.get_name().to_str().unwrap();
|
let name = function.get_name().to_str().unwrap();
|
||||||
if name.starts_with("roc_builtins") {
|
if name.starts_with("roc_builtins") {
|
||||||
if name.starts_with("roc_builtins.utils") {
|
if name.starts_with("roc_builtins.expect") {
|
||||||
function.set_linkage(Linkage::External);
|
function.set_linkage(Linkage::External);
|
||||||
} else {
|
} else {
|
||||||
function.set_linkage(Linkage::Internal);
|
function.set_linkage(Linkage::Internal);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue