panic cleanup and misc
This commit is contained in:
parent
230acc6ce7
commit
e291ff1bee
125
src/lib.zig
125
src/lib.zig
@ -41,9 +41,7 @@ const value_from_flag_kind = ValueFromFlag.sub;
|
|||||||
pub fn value_from_flag(value: anytype, flag: anytype) @TypeOf(value) {
|
pub fn value_from_flag(value: anytype, flag: anytype) @TypeOf(value) {
|
||||||
const flag_int: @TypeOf(value) = switch (@TypeOf(flag)) {
|
const flag_int: @TypeOf(value) = switch (@TypeOf(flag)) {
|
||||||
comptime_int => b: {
|
comptime_int => b: {
|
||||||
if (flag != 1 and flag != 0) {
|
assert(flag == 1 or flag == 0);
|
||||||
unreachable;
|
|
||||||
}
|
|
||||||
break :b flag;
|
break :b flag;
|
||||||
},
|
},
|
||||||
bool => @intFromBool(flag),
|
bool => @intFromBool(flag),
|
||||||
@ -127,21 +125,63 @@ pub const os = struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const linux = struct {
|
const linux = struct {
|
||||||
const PROT_READ: u32 = 1 << 0;
|
const PROT = packed struct(u32) {
|
||||||
const PROT_WRITE: u32 = 1 << 1;
|
read: u1,
|
||||||
const PROT_EXEC: u32 = 1 << 2;
|
write: u1,
|
||||||
|
exec: u1,
|
||||||
|
sem: u1 = 0,
|
||||||
|
_: u28 = 0,
|
||||||
|
};
|
||||||
|
const MAP = packed struct(u32) {
|
||||||
|
const Type = enum(u4) {
|
||||||
|
shared = 0x1,
|
||||||
|
private = 0x2,
|
||||||
|
shared_validate = 0x3,
|
||||||
|
};
|
||||||
|
|
||||||
const MAP_PRIVATE: u32 = 1 << 1;
|
type: Type = .private,
|
||||||
const MAP_ANONYMOUS: u32 = 1 << 5;
|
FIXED: u1 = 0,
|
||||||
const MAP_NORESERVE: u32 = 1 << 14;
|
ANONYMOUS: u1 = 0,
|
||||||
const MAP_POPULATE: u32 = 1 << 15;
|
@"32BIT": u1 = 0,
|
||||||
|
_7: u1 = 0,
|
||||||
|
GROWSDOWN: u1 = 0,
|
||||||
|
_9: u2 = 0,
|
||||||
|
DENYWRITE: u1 = 0,
|
||||||
|
EXECUTABLE: u1 = 0,
|
||||||
|
LOCKED: u1 = 0,
|
||||||
|
NORESERVE: u1 = 0,
|
||||||
|
POPULATE: u1 = 0,
|
||||||
|
NONBLOCK: u1 = 0,
|
||||||
|
STACK: u1 = 0,
|
||||||
|
HUGETLB: u1 = 0,
|
||||||
|
SYNC: u1 = 0,
|
||||||
|
FIXED_NOREPLACE: u1 = 0,
|
||||||
|
_21: u5 = 0,
|
||||||
|
UNINITIALIZED: u1 = 0,
|
||||||
|
_: u5 = 0,
|
||||||
|
};
|
||||||
|
|
||||||
extern "c" fn ptrace(c_int, c_int, usize, usize) c_long;
|
extern "c" fn ptrace(c_int, c_int, usize, usize) c_long;
|
||||||
extern "c" fn mmap(usize, usize, u32, u32, c_int, isize) *align(4096) anyopaque;
|
extern "c" fn mmap(usize, usize, PROT, MAP, c_int, isize) *align(4096) anyopaque;
|
||||||
extern "c" fn mprotect(*anyopaque, usize, u32) c_int;
|
extern "c" fn mprotect(*anyopaque, usize, PROT) c_int;
|
||||||
|
|
||||||
|
fn protection_flags(protection: ProtectionFlags) PROT {
|
||||||
|
const result = PROT{
|
||||||
|
.read = protection.read,
|
||||||
|
.write = protection.write,
|
||||||
|
.exec = protection.execute,
|
||||||
|
};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn map_flags(map: MapFlags) MAP {
|
||||||
|
const result = MAP{
|
||||||
|
.type = if (map.private != 0) .private else .shared,
|
||||||
|
.ANONYMOUS = map.anonymous,
|
||||||
|
.NORESERVE = map.no_reserve,
|
||||||
|
.POPULATE = map.populate,
|
||||||
|
};
|
||||||
|
|
||||||
fn protection_flags(protection: ProtectionFlags) u32 {
|
|
||||||
const result = value_from_flag(linux.PROT_READ, protection.read) | value_from_flag(linux.PROT_WRITE, protection.write) | value_from_flag(linux.PROT_EXEC, protection.execute);
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -162,11 +202,8 @@ pub const os = struct {
|
|||||||
switch (builtin.os.tag) {
|
switch (builtin.os.tag) {
|
||||||
.windows => @compileError("TODO"),
|
.windows => @compileError("TODO"),
|
||||||
else => {
|
else => {
|
||||||
const protection_flags: u32 = value_from_flag(linux.PROT_READ, protection.read) | value_from_flag(linux.PROT_WRITE, protection.write) | value_from_flag(linux.PROT_EXEC, protection.execute);
|
const protection_flags = linux.protection_flags(protection);
|
||||||
const map_flags = value_from_flag(linux.MAP_ANONYMOUS, map.anonymous) | value_from_flag(linux.MAP_PRIVATE, map.private) | value_from_flag(linux.MAP_NORESERVE, map.no_reserve) | switch (builtin.os.tag) {
|
const map_flags = linux.map_flags(map);
|
||||||
.linux => value_from_flag(linux.MAP_POPULATE, map.populate),
|
|
||||||
else => 0,
|
|
||||||
};
|
|
||||||
const address = linux.mmap(base, size, protection_flags, map_flags, -1, 0);
|
const address = linux.mmap(base, size, protection_flags, map_flags, -1, 0);
|
||||||
if (@intFromPtr(address) == u64_max) {
|
if (@intFromPtr(address) == u64_max) {
|
||||||
@branchHint(.unlikely);
|
@branchHint(.unlikely);
|
||||||
@ -177,7 +214,7 @@ pub const os = struct {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn commit(address: *anyopaque, size: u64, protection: ProtectionFlags) void {
|
pub fn commit(address: *anyopaque, size: u64, protection: ProtectionFlags) void {
|
||||||
switch (builtin.os.tag) {
|
switch (builtin.os.tag) {
|
||||||
.windows => @compileError("TODO"),
|
.windows => @compileError("TODO"),
|
||||||
else => {
|
else => {
|
||||||
@ -189,6 +226,14 @@ pub const os = struct {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn abort() noreturn {
|
||||||
|
if (os.is_being_debugged()) {
|
||||||
|
@trap();
|
||||||
|
} else {
|
||||||
|
os.exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const Arena = struct {
|
pub const Arena = struct {
|
||||||
@ -247,7 +292,7 @@ pub const Arena = struct {
|
|||||||
return arena;
|
return arena;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn allocate_bytes(arena: *Arena, size: u64, alignment: u64) *u8 {
|
pub fn allocate_bytes(arena: *Arena, size: u64, alignment: u64) [*]u8 {
|
||||||
const aligned_offset = align_forward_u64(arena.position, alignment);
|
const aligned_offset = align_forward_u64(arena.position, alignment);
|
||||||
const aligned_size_after = aligned_offset + size;
|
const aligned_size_after = aligned_offset + size;
|
||||||
|
|
||||||
@ -263,10 +308,46 @@ pub const Arena = struct {
|
|||||||
arena.os_position = target_committed_size;
|
arena.os_position = target_committed_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
const result = @as(*u8, @ptrFromInt(@intFromPtr(arena) + aligned_offset));
|
const result = @as([*]u8, @ptrFromInt(@intFromPtr(arena) + aligned_offset));
|
||||||
arena.position = aligned_size_after;
|
arena.position = aligned_size_after;
|
||||||
assert(arena.position <= arena.os_position);
|
assert(arena.position <= arena.os_position);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn join_string(arena: *Arena, pieces: []const []const u8) [:0]u8 {
|
||||||
|
var size: u64 = 0;
|
||||||
|
for (pieces) |piece| {
|
||||||
|
size += piece.len;
|
||||||
|
}
|
||||||
|
|
||||||
|
const pointer = arena.allocate_bytes(size + 1, 1);
|
||||||
|
var i: u64 = 0;
|
||||||
|
for (pieces) |piece| {
|
||||||
|
@memcpy(pointer + i, piece);
|
||||||
|
i += piece.len;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(i == size);
|
||||||
|
pointer[i] = 0;
|
||||||
|
|
||||||
|
return pointer[0..size :0];
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn duplicate_string(arena: *Arena, string: []const u8) [:0]u8 {
|
||||||
|
const memory = arena.allocate_bytes(string.len + 1, 1);
|
||||||
|
@memcpy(memory, string);
|
||||||
|
memory[string.len] = 0;
|
||||||
|
return memory[0..string.len :0];
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn restore(arena: *Arena, position: u64) void {
|
||||||
|
assert(position <= arena.position);
|
||||||
|
@memset(@as([*]u8, @ptrCast(arena))[position..][0 .. arena.position - position], 0);
|
||||||
|
arena.position = position;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn reset(arena: *Arena) void {
|
||||||
|
arena.restore(minimum_position);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
143
src/main.zig
143
src/main.zig
@ -1,18 +1,143 @@
|
|||||||
const lib = @import("lib.zig");
|
const lib = @import("lib.zig");
|
||||||
pub fn panic(message: []const u8, stack_trace: ?*anyopaque, return_address: ?usize) noreturn {
|
|
||||||
_ = return_address;
|
pub const panic = struct {
|
||||||
_ = message;
|
const abort = lib.os.abort;
|
||||||
_ = stack_trace;
|
pub fn call(_: []const u8, _: ?usize) noreturn {
|
||||||
if (lib.os.is_being_debugged()) {
|
@branchHint(.cold);
|
||||||
@trap();
|
abort();
|
||||||
} else {
|
|
||||||
lib.os.exit(1);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
pub fn sentinelMismatch(_: anytype, _: anytype) noreturn {
|
||||||
|
@branchHint(.cold);
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn unwrapError(_: anyerror) noreturn {
|
||||||
|
@branchHint(.cold);
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn outOfBounds(_: usize, _: usize) noreturn {
|
||||||
|
@branchHint(.cold);
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn startGreaterThanEnd(_: usize, _: usize) noreturn {
|
||||||
|
@branchHint(.cold);
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn inactiveUnionField(_: anytype, _: anytype) noreturn {
|
||||||
|
@branchHint(.cold);
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn reachedUnreachable() noreturn {
|
||||||
|
@branchHint(.cold);
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn unwrapNull() noreturn {
|
||||||
|
@branchHint(.cold);
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn castToNull() noreturn {
|
||||||
|
@branchHint(.cold);
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn incorrectAlignment() noreturn {
|
||||||
|
@branchHint(.cold);
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn invalidErrorCode() noreturn {
|
||||||
|
@branchHint(.cold);
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn castTruncatedData() noreturn {
|
||||||
|
@branchHint(.cold);
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn negativeToUnsigned() noreturn {
|
||||||
|
@branchHint(.cold);
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn integerOverflow() noreturn {
|
||||||
|
@branchHint(.cold);
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn shlOverflow() noreturn {
|
||||||
|
@branchHint(.cold);
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn shrOverflow() noreturn {
|
||||||
|
@branchHint(.cold);
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn divideByZero() noreturn {
|
||||||
|
@branchHint(.cold);
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn exactDivisionRemainder() noreturn {
|
||||||
|
@branchHint(.cold);
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn integerPartOutOfBounds() noreturn {
|
||||||
|
@branchHint(.cold);
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn corruptSwitch() noreturn {
|
||||||
|
@branchHint(.cold);
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn shiftRhsTooBig() noreturn {
|
||||||
|
@branchHint(.cold);
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn invalidEnumValue() noreturn {
|
||||||
|
@branchHint(.cold);
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn forLenMismatch() noreturn {
|
||||||
|
@branchHint(.cold);
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn memcpyLenMismatch() noreturn {
|
||||||
|
@branchHint(.cold);
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn memcpyAlias() noreturn {
|
||||||
|
@branchHint(.cold);
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn noreturnReturned() noreturn {
|
||||||
|
@branchHint(.cold);
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
pub fn main() callconv(.C) c_int {
|
pub fn main() callconv(.C) c_int {
|
||||||
const arena = lib.Arena.initialize_default(2 * lib.MB);
|
const arena = lib.Arena.initialize_default(2 * lib.MB);
|
||||||
_ = arena.allocate_bytes(1024, 1);
|
_ = arena.allocate_bytes(1024, 1);
|
||||||
|
_ = arena.join_string(&.{ "foo", "fa" });
|
||||||
|
arena.reset();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user