Merge branch 'master' into fbsd2
commit
773bf80133
|
@ -0,0 +1,22 @@
|
||||||
|
arch: x86_64
|
||||||
|
image: freebsd
|
||||||
|
packages:
|
||||||
|
- cmake
|
||||||
|
- ninja
|
||||||
|
- llvm70
|
||||||
|
sources:
|
||||||
|
- https://github.com/ziglang/zig.git
|
||||||
|
tasks:
|
||||||
|
- build: |
|
||||||
|
cd zig && mkdir build && cd build
|
||||||
|
cmake .. -GNinja -DCMAKE_BUILD_TYPE=Release
|
||||||
|
ninja install
|
||||||
|
- test: |
|
||||||
|
cd zig/build
|
||||||
|
bin/zig test ../test/behavior.zig
|
||||||
|
# TODO enable all tests
|
||||||
|
#bin/zig build --build-file ../build.zig test
|
||||||
|
# TODO integrate with the download page updater and make a
|
||||||
|
# static build available to download for FreeBSD.
|
||||||
|
# This will require setting up a cache of LLVM/Clang built
|
||||||
|
# statically.
|
|
@ -165,7 +165,7 @@ const std = @import("std");
|
||||||
|
|
||||||
pub fn main() !void {
|
pub fn main() !void {
|
||||||
// If this program is run without stdout attached, exit with an error.
|
// If this program is run without stdout attached, exit with an error.
|
||||||
var stdout_file = try std.io.getStdOut();
|
const stdout_file = try std.io.getStdOut();
|
||||||
// If this program encounters pipe failure when printing to stdout, exit
|
// If this program encounters pipe failure when printing to stdout, exit
|
||||||
// with an error.
|
// with an error.
|
||||||
try stdout_file.write("Hello, world!\n");
|
try stdout_file.write("Hello, world!\n");
|
||||||
|
|
|
@ -2,7 +2,7 @@ const std = @import("std");
|
||||||
|
|
||||||
pub fn main() !void {
|
pub fn main() !void {
|
||||||
// If this program is run without stdout attached, exit with an error.
|
// If this program is run without stdout attached, exit with an error.
|
||||||
var stdout_file = try std.io.getStdOut();
|
const stdout_file = try std.io.getStdOut();
|
||||||
// If this program encounters pipe failure when printing to stdout, exit
|
// If this program encounters pipe failure when printing to stdout, exit
|
||||||
// with an error.
|
// with an error.
|
||||||
try stdout_file.write("Hello, world!\n");
|
try stdout_file.write("Hello, world!\n");
|
||||||
|
|
|
@ -300,6 +300,7 @@ pub const Compilation = struct {
|
||||||
UserResourceLimitReached,
|
UserResourceLimitReached,
|
||||||
InvalidUtf8,
|
InvalidUtf8,
|
||||||
BadPathName,
|
BadPathName,
|
||||||
|
DeviceBusy,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const Event = union(enum) {
|
pub const Event = union(enum) {
|
||||||
|
|
|
@ -2681,39 +2681,50 @@ static Error resolve_struct_alignment(CodeGen *g, ZigType *struct_type) {
|
||||||
assert(decl_node->type == NodeTypeContainerDecl);
|
assert(decl_node->type == NodeTypeContainerDecl);
|
||||||
assert(struct_type->di_type);
|
assert(struct_type->di_type);
|
||||||
|
|
||||||
|
size_t field_count = struct_type->data.structure.src_field_count;
|
||||||
if (struct_type->data.structure.layout == ContainerLayoutPacked) {
|
if (struct_type->data.structure.layout == ContainerLayoutPacked) {
|
||||||
struct_type->data.structure.abi_alignment = 1;
|
struct_type->data.structure.abi_alignment = 1;
|
||||||
}
|
for (size_t i = 0; i < field_count; i += 1) {
|
||||||
|
TypeStructField *field = &struct_type->data.structure.fields[i];
|
||||||
size_t field_count = struct_type->data.structure.src_field_count;
|
if (field->type_entry != nullptr && type_is_invalid(field->type_entry)) {
|
||||||
for (size_t i = 0; i < field_count; i += 1) {
|
struct_type->data.structure.resolve_status = ResolveStatusInvalid;
|
||||||
TypeStructField *field = &struct_type->data.structure.fields[i];
|
break;
|
||||||
|
}
|
||||||
// If this assertion trips, look up the call stack. Probably something is
|
|
||||||
// calling type_resolve with ResolveStatusAlignmentKnown when it should only
|
|
||||||
// be resolving ResolveStatusZeroBitsKnown
|
|
||||||
assert(field->type_entry != nullptr);
|
|
||||||
|
|
||||||
if (type_is_invalid(field->type_entry)) {
|
|
||||||
struct_type->data.structure.resolve_status = ResolveStatusInvalid;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
} else for (size_t i = 0; i < field_count; i += 1) {
|
||||||
|
TypeStructField *field = &struct_type->data.structure.fields[i];
|
||||||
|
uint32_t this_field_align;
|
||||||
|
|
||||||
if (!type_has_bits(field->type_entry))
|
// TODO If we have no type_entry for the field, we've already failed to
|
||||||
continue;
|
// compile the program correctly. This stage1 compiler needs a deeper
|
||||||
|
// reworking to make this correct, or we can ignore the problem
|
||||||
|
// and make sure it is fixed in stage2. This workaround is for when
|
||||||
|
// there is a false positive of a dependency loop, of alignment depending
|
||||||
|
// on itself. When this false positive happens we assume a pointer-aligned
|
||||||
|
// field, which is usually fine but could be incorrectly over-aligned or
|
||||||
|
// even under-aligned. See https://github.com/ziglang/zig/issues/1512
|
||||||
|
if (field->type_entry == nullptr) {
|
||||||
|
this_field_align = LLVMABIAlignmentOfType(g->target_data_ref, LLVMPointerType(LLVMInt8Type(), 0));
|
||||||
|
} else {
|
||||||
|
if (type_is_invalid(field->type_entry)) {
|
||||||
|
struct_type->data.structure.resolve_status = ResolveStatusInvalid;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!type_has_bits(field->type_entry))
|
||||||
|
continue;
|
||||||
|
|
||||||
// alignment of structs is the alignment of the most-aligned field
|
|
||||||
if (struct_type->data.structure.layout != ContainerLayoutPacked) {
|
|
||||||
if ((err = type_resolve(g, field->type_entry, ResolveStatusAlignmentKnown))) {
|
if ((err = type_resolve(g, field->type_entry, ResolveStatusAlignmentKnown))) {
|
||||||
struct_type->data.structure.resolve_status = ResolveStatusInvalid;
|
struct_type->data.structure.resolve_status = ResolveStatusInvalid;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t this_field_align = get_abi_alignment(g, field->type_entry);
|
this_field_align = get_abi_alignment(g, field->type_entry);
|
||||||
assert(this_field_align != 0);
|
assert(this_field_align != 0);
|
||||||
if (this_field_align > struct_type->data.structure.abi_alignment) {
|
}
|
||||||
struct_type->data.structure.abi_alignment = this_field_align;
|
// alignment of structs is the alignment of the most-aligned field
|
||||||
}
|
if (this_field_align > struct_type->data.structure.abi_alignment) {
|
||||||
|
struct_type->data.structure.abi_alignment = this_field_align;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
65
src/ir.cpp
65
src/ir.cpp
|
@ -159,7 +159,7 @@ static ZigType *ir_resolve_atomic_operand_type(IrAnalyze *ira, IrInstruction *op
|
||||||
static IrInstruction *ir_lval_wrap(IrBuilder *irb, Scope *scope, IrInstruction *value, LVal lval);
|
static IrInstruction *ir_lval_wrap(IrBuilder *irb, Scope *scope, IrInstruction *value, LVal lval);
|
||||||
static ZigType *adjust_ptr_align(CodeGen *g, ZigType *ptr_type, uint32_t new_align);
|
static ZigType *adjust_ptr_align(CodeGen *g, ZigType *ptr_type, uint32_t new_align);
|
||||||
static ZigType *adjust_slice_align(CodeGen *g, ZigType *slice_type, uint32_t new_align);
|
static ZigType *adjust_slice_align(CodeGen *g, ZigType *slice_type, uint32_t new_align);
|
||||||
static void buf_read_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue *val);
|
static Error buf_read_value_bytes(IrAnalyze *ira, AstNode *source_node, uint8_t *buf, ConstExprValue *val);
|
||||||
static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue *val);
|
static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue *val);
|
||||||
static Error ir_read_const_ptr(IrAnalyze *ira, AstNode *source_node,
|
static Error ir_read_const_ptr(IrAnalyze *ira, AstNode *source_node,
|
||||||
ConstExprValue *out_val, ConstExprValue *ptr_val);
|
ConstExprValue *out_val, ConstExprValue *ptr_val);
|
||||||
|
@ -12495,6 +12495,7 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct
|
||||||
case ReqCompTimeNo:
|
case ReqCompTimeNo:
|
||||||
if (casted_init_value->value.special == ConstValSpecialStatic &&
|
if (casted_init_value->value.special == ConstValSpecialStatic &&
|
||||||
casted_init_value->value.type->id == ZigTypeIdFn &&
|
casted_init_value->value.type->id == ZigTypeIdFn &&
|
||||||
|
casted_init_value->value.data.x_ptr.special != ConstPtrSpecialHardCodedAddr &&
|
||||||
casted_init_value->value.data.x_ptr.data.fn.fn_entry->fn_inline == FnInlineAlways)
|
casted_init_value->value.data.x_ptr.data.fn.fn_entry->fn_inline == FnInlineAlways)
|
||||||
{
|
{
|
||||||
var_class_requires_const = true;
|
var_class_requires_const = true;
|
||||||
|
@ -13724,7 +13725,8 @@ static Error ir_read_const_ptr(IrAnalyze *ira, AstNode *source_node,
|
||||||
Buf buf = BUF_INIT;
|
Buf buf = BUF_INIT;
|
||||||
buf_resize(&buf, src_size);
|
buf_resize(&buf, src_size);
|
||||||
buf_write_value_bytes(ira->codegen, (uint8_t*)buf_ptr(&buf), pointee);
|
buf_write_value_bytes(ira->codegen, (uint8_t*)buf_ptr(&buf), pointee);
|
||||||
buf_read_value_bytes(ira->codegen, (uint8_t*)buf_ptr(&buf), out_val);
|
if ((err = buf_read_value_bytes(ira, source_node, (uint8_t*)buf_ptr(&buf), out_val)))
|
||||||
|
return err;
|
||||||
return ErrorNone;
|
return ErrorNone;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13758,7 +13760,8 @@ static Error ir_read_const_ptr(IrAnalyze *ira, AstNode *source_node,
|
||||||
ConstExprValue *elem_val = &array_val->data.x_array.data.s_none.elements[elem_index + i];
|
ConstExprValue *elem_val = &array_val->data.x_array.data.s_none.elements[elem_index + i];
|
||||||
buf_write_value_bytes(ira->codegen, (uint8_t*)buf_ptr(&buf) + (i * elem_size), elem_val);
|
buf_write_value_bytes(ira->codegen, (uint8_t*)buf_ptr(&buf) + (i * elem_size), elem_val);
|
||||||
}
|
}
|
||||||
buf_read_value_bytes(ira->codegen, (uint8_t*)buf_ptr(&buf), out_val);
|
if ((err = buf_read_value_bytes(ira, source_node, (uint8_t*)buf_ptr(&buf), out_val)))
|
||||||
|
return err;
|
||||||
return ErrorNone;
|
return ErrorNone;
|
||||||
}
|
}
|
||||||
case ConstPtrSpecialBaseStruct:
|
case ConstPtrSpecialBaseStruct:
|
||||||
|
@ -20076,7 +20079,8 @@ static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue
|
||||||
zig_unreachable();
|
zig_unreachable();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void buf_read_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue *val) {
|
static Error buf_read_value_bytes(IrAnalyze *ira, AstNode *source_node, uint8_t *buf, ConstExprValue *val) {
|
||||||
|
Error err;
|
||||||
assert(val->special == ConstValSpecialStatic);
|
assert(val->special == ConstValSpecialStatic);
|
||||||
switch (val->type->id) {
|
switch (val->type->id) {
|
||||||
case ZigTypeIdInvalid:
|
case ZigTypeIdInvalid:
|
||||||
|
@ -20093,30 +20097,60 @@ static void buf_read_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue
|
||||||
case ZigTypeIdPromise:
|
case ZigTypeIdPromise:
|
||||||
zig_unreachable();
|
zig_unreachable();
|
||||||
case ZigTypeIdVoid:
|
case ZigTypeIdVoid:
|
||||||
return;
|
return ErrorNone;
|
||||||
case ZigTypeIdBool:
|
case ZigTypeIdBool:
|
||||||
val->data.x_bool = (buf[0] != 0);
|
val->data.x_bool = (buf[0] != 0);
|
||||||
return;
|
return ErrorNone;
|
||||||
case ZigTypeIdInt:
|
case ZigTypeIdInt:
|
||||||
bigint_read_twos_complement(&val->data.x_bigint, buf, val->type->data.integral.bit_count,
|
bigint_read_twos_complement(&val->data.x_bigint, buf, val->type->data.integral.bit_count,
|
||||||
codegen->is_big_endian, val->type->data.integral.is_signed);
|
ira->codegen->is_big_endian, val->type->data.integral.is_signed);
|
||||||
return;
|
return ErrorNone;
|
||||||
case ZigTypeIdFloat:
|
case ZigTypeIdFloat:
|
||||||
float_read_ieee597(val, buf, codegen->is_big_endian);
|
float_read_ieee597(val, buf, ira->codegen->is_big_endian);
|
||||||
return;
|
return ErrorNone;
|
||||||
case ZigTypeIdPointer:
|
case ZigTypeIdPointer:
|
||||||
{
|
{
|
||||||
val->data.x_ptr.special = ConstPtrSpecialHardCodedAddr;
|
val->data.x_ptr.special = ConstPtrSpecialHardCodedAddr;
|
||||||
BigInt bn;
|
BigInt bn;
|
||||||
bigint_read_twos_complement(&bn, buf, codegen->builtin_types.entry_usize->data.integral.bit_count,
|
bigint_read_twos_complement(&bn, buf, ira->codegen->builtin_types.entry_usize->data.integral.bit_count,
|
||||||
codegen->is_big_endian, false);
|
ira->codegen->is_big_endian, false);
|
||||||
val->data.x_ptr.data.hard_coded_addr.addr = bigint_as_unsigned(&bn);
|
val->data.x_ptr.data.hard_coded_addr.addr = bigint_as_unsigned(&bn);
|
||||||
return;
|
return ErrorNone;
|
||||||
}
|
}
|
||||||
case ZigTypeIdArray:
|
case ZigTypeIdArray:
|
||||||
zig_panic("TODO buf_read_value_bytes array type");
|
zig_panic("TODO buf_read_value_bytes array type");
|
||||||
case ZigTypeIdStruct:
|
case ZigTypeIdStruct:
|
||||||
zig_panic("TODO buf_read_value_bytes struct type");
|
switch (val->type->data.structure.layout) {
|
||||||
|
case ContainerLayoutAuto: {
|
||||||
|
ErrorMsg *msg = ir_add_error_node(ira, source_node,
|
||||||
|
buf_sprintf("non-extern, non-packed struct '%s' cannot have its bytes reinterpreted",
|
||||||
|
buf_ptr(&val->type->name)));
|
||||||
|
add_error_note(ira->codegen, msg, val->type->data.structure.decl_node,
|
||||||
|
buf_sprintf("declared here"));
|
||||||
|
return ErrorSemanticAnalyzeFail;
|
||||||
|
}
|
||||||
|
case ContainerLayoutExtern: {
|
||||||
|
size_t src_field_count = val->type->data.structure.src_field_count;
|
||||||
|
val->data.x_struct.fields = create_const_vals(src_field_count);
|
||||||
|
for (size_t field_i = 0; field_i < src_field_count; field_i += 1) {
|
||||||
|
ConstExprValue *field_val = &val->data.x_struct.fields[field_i];
|
||||||
|
field_val->special = ConstValSpecialStatic;
|
||||||
|
TypeStructField *type_field = &val->type->data.structure.fields[field_i];
|
||||||
|
field_val->type = type_field->type_entry;
|
||||||
|
if (type_field->gen_index == SIZE_MAX)
|
||||||
|
continue;
|
||||||
|
size_t offset = LLVMOffsetOfElement(ira->codegen->target_data_ref, val->type->type_ref,
|
||||||
|
type_field->gen_index);
|
||||||
|
uint8_t *new_buf = buf + offset;
|
||||||
|
if ((err = buf_read_value_bytes(ira, source_node, new_buf, field_val)))
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
return ErrorNone;
|
||||||
|
}
|
||||||
|
case ContainerLayoutPacked:
|
||||||
|
zig_panic("TODO buf_read_value_bytes packed struct");
|
||||||
|
}
|
||||||
|
zig_unreachable();
|
||||||
case ZigTypeIdOptional:
|
case ZigTypeIdOptional:
|
||||||
zig_panic("TODO buf_read_value_bytes maybe type");
|
zig_panic("TODO buf_read_value_bytes maybe type");
|
||||||
case ZigTypeIdErrorUnion:
|
case ZigTypeIdErrorUnion:
|
||||||
|
@ -20219,7 +20253,8 @@ static IrInstruction *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstruct
|
||||||
IrInstruction *result = ir_const(ira, &instruction->base, dest_type);
|
IrInstruction *result = ir_const(ira, &instruction->base, dest_type);
|
||||||
uint8_t *buf = allocate_nonzero<uint8_t>(src_size_bytes);
|
uint8_t *buf = allocate_nonzero<uint8_t>(src_size_bytes);
|
||||||
buf_write_value_bytes(ira->codegen, buf, val);
|
buf_write_value_bytes(ira->codegen, buf, val);
|
||||||
buf_read_value_bytes(ira->codegen, buf, &result->value);
|
if ((err = buf_read_value_bytes(ira, instruction->base.source_node, buf, &result->value)))
|
||||||
|
return ira->codegen->invalid_instruction;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4776,6 +4776,14 @@ Error parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const
|
||||||
|
|
||||||
clang_argv.append(target_file);
|
clang_argv.append(target_file);
|
||||||
|
|
||||||
|
if (codegen->verbose_cimport) {
|
||||||
|
fprintf(stderr, "clang");
|
||||||
|
for (size_t i = 0; i < clang_argv.length; i += 1) {
|
||||||
|
fprintf(stderr, " %s", clang_argv.at(i));
|
||||||
|
}
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
}
|
||||||
|
|
||||||
// to make the [start...end] argument work
|
// to make the [start...end] argument work
|
||||||
clang_argv.append(nullptr);
|
clang_argv.append(nullptr);
|
||||||
|
|
||||||
|
|
|
@ -398,3 +398,14 @@ test "std.ArrayList.insertSlice" {
|
||||||
assert(list.len == 6);
|
assert(list.len == 6);
|
||||||
assert(list.items[0] == 1);
|
assert(list.items[0] == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const Item = struct {
|
||||||
|
integer: i32,
|
||||||
|
sub_items: ArrayList(Item),
|
||||||
|
};
|
||||||
|
|
||||||
|
test "std.ArrayList: ArrayList(T) of struct T" {
|
||||||
|
var root = Item{ .integer = 1, .sub_items = ArrayList(Item).init(debug.global_allocator) };
|
||||||
|
try root.sub_items.append( Item{ .integer = 42, .sub_items = ArrayList(Item).init(debug.global_allocator) } );
|
||||||
|
assert(root.sub_items.items[0].integer == 42);
|
||||||
|
}
|
||||||
|
|
|
@ -19,7 +19,6 @@ pub const DynLib = switch (builtin.os) {
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const LinuxDynLib = struct {
|
pub const LinuxDynLib = struct {
|
||||||
allocator: *mem.Allocator,
|
|
||||||
elf_lib: ElfLib,
|
elf_lib: ElfLib,
|
||||||
fd: i32,
|
fd: i32,
|
||||||
map_addr: usize,
|
map_addr: usize,
|
||||||
|
@ -27,7 +26,7 @@ pub const LinuxDynLib = struct {
|
||||||
|
|
||||||
/// Trusts the file
|
/// Trusts the file
|
||||||
pub fn open(allocator: *mem.Allocator, path: []const u8) !DynLib {
|
pub fn open(allocator: *mem.Allocator, path: []const u8) !DynLib {
|
||||||
const fd = try std.os.posixOpen(allocator, path, 0, linux.O_RDONLY | linux.O_CLOEXEC);
|
const fd = try std.os.posixOpen(path, 0, linux.O_RDONLY | linux.O_CLOEXEC);
|
||||||
errdefer std.os.close(fd);
|
errdefer std.os.close(fd);
|
||||||
|
|
||||||
const size = @intCast(usize, (try std.os.posixFStat(fd)).size);
|
const size = @intCast(usize, (try std.os.posixFStat(fd)).size);
|
||||||
|
@ -45,7 +44,6 @@ pub const LinuxDynLib = struct {
|
||||||
const bytes = @intToPtr([*]align(std.os.page_size) u8, addr)[0..size];
|
const bytes = @intToPtr([*]align(std.os.page_size) u8, addr)[0..size];
|
||||||
|
|
||||||
return DynLib{
|
return DynLib{
|
||||||
.allocator = allocator,
|
|
||||||
.elf_lib = try ElfLib.init(bytes),
|
.elf_lib = try ElfLib.init(bytes),
|
||||||
.fd = fd,
|
.fd = fd,
|
||||||
.map_addr = addr,
|
.map_addr = addr,
|
||||||
|
|
|
@ -243,6 +243,9 @@ pub fn formatType(
|
||||||
}
|
}
|
||||||
return format(context, Errors, output, "{}@{x}", @typeName(T.Child), @ptrToInt(&value));
|
return format(context, Errors, output, "{}@{x}", @typeName(T.Child), @ptrToInt(&value));
|
||||||
},
|
},
|
||||||
|
builtin.TypeId.Fn => {
|
||||||
|
return format(context, Errors, output, "{}@{x}", @typeName(T), @ptrToInt(value));
|
||||||
|
},
|
||||||
else => @compileError("Unable to format type '" ++ @typeName(T) ++ "'"),
|
else => @compileError("Unable to format type '" ++ @typeName(T) ++ "'"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1013,6 +1016,10 @@ test "fmt.format" {
|
||||||
const value = @intToPtr(fn () void, 0xdeadbeef);
|
const value = @intToPtr(fn () void, 0xdeadbeef);
|
||||||
try testFmt("pointer: fn() void@deadbeef\n", "pointer: {}\n", value);
|
try testFmt("pointer: fn() void@deadbeef\n", "pointer: {}\n", value);
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
const value = @intToPtr(fn () void, 0xdeadbeef);
|
||||||
|
try testFmt("pointer: fn() void@deadbeef\n", "pointer: {}\n", value);
|
||||||
|
}
|
||||||
try testFmt("buf: Test \n", "buf: {s5}\n", "Test");
|
try testFmt("buf: Test \n", "buf: {s5}\n", "Test");
|
||||||
try testFmt("buf: Test\n Other text", "buf: {s}\n Other text", "Test");
|
try testFmt("buf: Test\n Other text", "buf: {s}\n Other text", "Test");
|
||||||
try testFmt("cstr: Test C\n", "cstr: {s}\n", c"Test C");
|
try testFmt("cstr: Test C\n", "cstr: {s}\n", c"Test C");
|
||||||
|
|
|
@ -57,7 +57,8 @@ test "std" {
|
||||||
_ = @import("mutex.zig");
|
_ = @import("mutex.zig");
|
||||||
_ = @import("segmented_list.zig");
|
_ = @import("segmented_list.zig");
|
||||||
_ = @import("spinlock.zig");
|
_ = @import("spinlock.zig");
|
||||||
|
|
||||||
|
_ = @import("dynamic_library.zig");
|
||||||
_ = @import("base64.zig");
|
_ = @import("base64.zig");
|
||||||
_ = @import("build.zig");
|
_ = @import("build.zig");
|
||||||
_ = @import("c/index.zig");
|
_ = @import("c/index.zig");
|
||||||
|
|
10
std/io.zig
10
std/io.zig
|
@ -155,32 +155,32 @@ pub fn InStream(comptime ReadError: type) type {
|
||||||
pub fn readIntNative(self: *Self, comptime T: type) !T {
|
pub fn readIntNative(self: *Self, comptime T: type) !T {
|
||||||
var bytes: [@sizeOf(T)]u8 = undefined;
|
var bytes: [@sizeOf(T)]u8 = undefined;
|
||||||
try self.readNoEof(bytes[0..]);
|
try self.readNoEof(bytes[0..]);
|
||||||
return mem.readIntSliceNative(T, bytes);
|
return mem.readIntNative(T, &bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Reads a foreign-endian integer
|
/// Reads a foreign-endian integer
|
||||||
pub fn readIntForeign(self: *Self, comptime T: type) !T {
|
pub fn readIntForeign(self: *Self, comptime T: type) !T {
|
||||||
var bytes: [@sizeOf(T)]u8 = undefined;
|
var bytes: [@sizeOf(T)]u8 = undefined;
|
||||||
try self.readNoEof(bytes[0..]);
|
try self.readNoEof(bytes[0..]);
|
||||||
return mem.readIntSliceForeign(T, bytes);
|
return mem.readIntForeign(T, &bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn readIntLittle(self: *Self, comptime T: type) !T {
|
pub fn readIntLittle(self: *Self, comptime T: type) !T {
|
||||||
var bytes: [@sizeOf(T)]u8 = undefined;
|
var bytes: [@sizeOf(T)]u8 = undefined;
|
||||||
try self.readNoEof(bytes[0..]);
|
try self.readNoEof(bytes[0..]);
|
||||||
return mem.readIntSliceLittle(T, bytes);
|
return mem.readIntLittle(T, &bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn readIntBig(self: *Self, comptime T: type) !T {
|
pub fn readIntBig(self: *Self, comptime T: type) !T {
|
||||||
var bytes: [@sizeOf(T)]u8 = undefined;
|
var bytes: [@sizeOf(T)]u8 = undefined;
|
||||||
try self.readNoEof(bytes[0..]);
|
try self.readNoEof(bytes[0..]);
|
||||||
return mem.readIntSliceBig(T, bytes);
|
return mem.readIntBig(T, &bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn readInt(self: *Self, comptime T: type, endian: builtin.Endian) !T {
|
pub fn readInt(self: *Self, comptime T: type, endian: builtin.Endian) !T {
|
||||||
var bytes: [@sizeOf(T)]u8 = undefined;
|
var bytes: [@sizeOf(T)]u8 = undefined;
|
||||||
try self.readNoEof(bytes[0..]);
|
try self.readNoEof(bytes[0..]);
|
||||||
return mem.readIntSlice(T, bytes, endian);
|
return mem.readInt(T, &bytes, endian);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn readVarInt(self: *Self, comptime ReturnType: type, endian: builtin.Endian, size: usize) !ReturnType {
|
pub fn readVarInt(self: *Self, comptime ReturnType: type, endian: builtin.Endian, size: usize) !ReturnType {
|
||||||
|
|
|
@ -459,6 +459,7 @@ pub const PosixOpenError = error{
|
||||||
NoSpaceLeft,
|
NoSpaceLeft,
|
||||||
NotDir,
|
NotDir,
|
||||||
PathAlreadyExists,
|
PathAlreadyExists,
|
||||||
|
DeviceBusy,
|
||||||
|
|
||||||
/// See https://github.com/ziglang/zig/issues/1396
|
/// See https://github.com/ziglang/zig/issues/1396
|
||||||
Unexpected,
|
Unexpected,
|
||||||
|
@ -497,6 +498,7 @@ pub fn posixOpenC(file_path: [*]const u8, flags: u32, perm: usize) !i32 {
|
||||||
posix.ENOTDIR => return PosixOpenError.NotDir,
|
posix.ENOTDIR => return PosixOpenError.NotDir,
|
||||||
posix.EPERM => return PosixOpenError.AccessDenied,
|
posix.EPERM => return PosixOpenError.AccessDenied,
|
||||||
posix.EEXIST => return PosixOpenError.PathAlreadyExists,
|
posix.EEXIST => return PosixOpenError.PathAlreadyExists,
|
||||||
|
posix.EBUSY => return PosixOpenError.DeviceBusy,
|
||||||
else => return unexpectedErrorPosix(err),
|
else => return unexpectedErrorPosix(err),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1402,6 +1404,7 @@ const DeleteTreeError = error{
|
||||||
FileSystem,
|
FileSystem,
|
||||||
FileBusy,
|
FileBusy,
|
||||||
DirNotEmpty,
|
DirNotEmpty,
|
||||||
|
DeviceBusy,
|
||||||
|
|
||||||
/// On Windows, file paths must be valid Unicode.
|
/// On Windows, file paths must be valid Unicode.
|
||||||
InvalidUtf8,
|
InvalidUtf8,
|
||||||
|
@ -1463,6 +1466,7 @@ pub fn deleteTree(allocator: *Allocator, full_path: []const u8) DeleteTreeError!
|
||||||
error.Unexpected,
|
error.Unexpected,
|
||||||
error.InvalidUtf8,
|
error.InvalidUtf8,
|
||||||
error.BadPathName,
|
error.BadPathName,
|
||||||
|
error.DeviceBusy,
|
||||||
=> return err,
|
=> return err,
|
||||||
};
|
};
|
||||||
defer dir.close();
|
defer dir.close();
|
||||||
|
@ -1545,6 +1549,7 @@ pub const Dir = struct {
|
||||||
OutOfMemory,
|
OutOfMemory,
|
||||||
InvalidUtf8,
|
InvalidUtf8,
|
||||||
BadPathName,
|
BadPathName,
|
||||||
|
DeviceBusy,
|
||||||
|
|
||||||
/// See https://github.com/ziglang/zig/issues/1396
|
/// See https://github.com/ziglang/zig/issues/1396
|
||||||
Unexpected,
|
Unexpected,
|
||||||
|
|
|
@ -1093,6 +1093,7 @@ pub const RealError = error{
|
||||||
NoSpaceLeft,
|
NoSpaceLeft,
|
||||||
FileSystem,
|
FileSystem,
|
||||||
BadPathName,
|
BadPathName,
|
||||||
|
DeviceBusy,
|
||||||
|
|
||||||
/// On Windows, file paths must be valid Unicode.
|
/// On Windows, file paths must be valid Unicode.
|
||||||
InvalidUtf8,
|
InvalidUtf8,
|
||||||
|
|
|
@ -42,6 +42,7 @@ comptime {
|
||||||
_ = @import("cases/if.zig");
|
_ = @import("cases/if.zig");
|
||||||
_ = @import("cases/import.zig");
|
_ = @import("cases/import.zig");
|
||||||
_ = @import("cases/incomplete_struct_param_tld.zig");
|
_ = @import("cases/incomplete_struct_param_tld.zig");
|
||||||
|
_ = @import("cases/inttoptr.zig");
|
||||||
_ = @import("cases/ir_block_deps.zig");
|
_ = @import("cases/ir_block_deps.zig");
|
||||||
_ = @import("cases/math.zig");
|
_ = @import("cases/math.zig");
|
||||||
_ = @import("cases/merge_error_sets.zig");
|
_ = @import("cases/merge_error_sets.zig");
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
const builtin = @import("builtin");
|
||||||
|
const std = @import("std");
|
||||||
|
const assertOrPanic = std.debug.assertOrPanic;
|
||||||
|
|
||||||
|
test "casting random address to function pointer" {
|
||||||
|
randomAddressToFunction();
|
||||||
|
comptime randomAddressToFunction();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn randomAddressToFunction() void {
|
||||||
|
var addr: usize = 0xdeadbeef;
|
||||||
|
var ptr = @intToPtr(fn () void, addr);
|
||||||
|
}
|
|
@ -15,3 +15,22 @@ fn testReinterpretBytesAsInteger() void {
|
||||||
};
|
};
|
||||||
assertOrPanic(@ptrCast(*align(1) const u32, bytes[1..5].ptr).* == expected);
|
assertOrPanic(@ptrCast(*align(1) const u32, bytes[1..5].ptr).* == expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test "reinterpret bytes of an array into an extern struct" {
|
||||||
|
testReinterpretBytesAsExternStruct();
|
||||||
|
comptime testReinterpretBytesAsExternStruct();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn testReinterpretBytesAsExternStruct() void {
|
||||||
|
var bytes align(2) = []u8{ 1, 2, 3, 4, 5, 6 };
|
||||||
|
|
||||||
|
const S = extern struct {
|
||||||
|
a: u8,
|
||||||
|
b: u16,
|
||||||
|
c: u8,
|
||||||
|
};
|
||||||
|
|
||||||
|
var ptr = @ptrCast(*const S, &bytes);
|
||||||
|
var val = ptr.c;
|
||||||
|
assertOrPanic(val == 5);
|
||||||
|
}
|
||||||
|
|
|
@ -5,6 +5,11 @@ const Node = struct {
|
||||||
children: []Node,
|
children: []Node,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const NodeAligned = struct {
|
||||||
|
payload: i32,
|
||||||
|
children: []align(@alignOf(NodeAligned)) NodeAligned,
|
||||||
|
};
|
||||||
|
|
||||||
test "struct contains slice of itself" {
|
test "struct contains slice of itself" {
|
||||||
var other_nodes = []Node{
|
var other_nodes = []Node{
|
||||||
Node{
|
Node{
|
||||||
|
@ -41,3 +46,40 @@ test "struct contains slice of itself" {
|
||||||
assert(root.children[2].children[0].payload == 31);
|
assert(root.children[2].children[0].payload == 31);
|
||||||
assert(root.children[2].children[1].payload == 32);
|
assert(root.children[2].children[1].payload == 32);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test "struct contains aligned slice of itself" {
|
||||||
|
var other_nodes = []NodeAligned{
|
||||||
|
NodeAligned{
|
||||||
|
.payload = 31,
|
||||||
|
.children = []NodeAligned{},
|
||||||
|
},
|
||||||
|
NodeAligned{
|
||||||
|
.payload = 32,
|
||||||
|
.children = []NodeAligned{},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
var nodes = []NodeAligned{
|
||||||
|
NodeAligned{
|
||||||
|
.payload = 1,
|
||||||
|
.children = []NodeAligned{},
|
||||||
|
},
|
||||||
|
NodeAligned{
|
||||||
|
.payload = 2,
|
||||||
|
.children = []NodeAligned{},
|
||||||
|
},
|
||||||
|
NodeAligned{
|
||||||
|
.payload = 3,
|
||||||
|
.children = other_nodes[0..],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const root = NodeAligned{
|
||||||
|
.payload = 1234,
|
||||||
|
.children = nodes[0..],
|
||||||
|
};
|
||||||
|
assert(root.payload == 1234);
|
||||||
|
assert(root.children[0].payload == 1);
|
||||||
|
assert(root.children[1].payload == 2);
|
||||||
|
assert(root.children[2].payload == 3);
|
||||||
|
assert(root.children[2].children[0].payload == 31);
|
||||||
|
assert(root.children[2].children[1].payload == 32);
|
||||||
|
}
|
||||||
|
|
|
@ -144,15 +144,20 @@ test "type info: enum info" {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn testEnum() void {
|
fn testEnum() void {
|
||||||
const Os = @import("builtin").Os;
|
const Os = enum {
|
||||||
|
Windows,
|
||||||
|
Macos,
|
||||||
|
Linux,
|
||||||
|
FreeBSD,
|
||||||
|
};
|
||||||
|
|
||||||
const os_info = @typeInfo(Os);
|
const os_info = @typeInfo(Os);
|
||||||
assert(TypeId(os_info) == TypeId.Enum);
|
assert(TypeId(os_info) == TypeId.Enum);
|
||||||
assert(os_info.Enum.layout == TypeInfo.ContainerLayout.Auto);
|
assert(os_info.Enum.layout == TypeInfo.ContainerLayout.Auto);
|
||||||
assert(os_info.Enum.fields.len == 32);
|
assert(os_info.Enum.fields.len == 4);
|
||||||
assert(mem.eql(u8, os_info.Enum.fields[1].name, "ananas"));
|
assert(mem.eql(u8, os_info.Enum.fields[1].name, "Macos"));
|
||||||
assert(os_info.Enum.fields[10].value == 10);
|
assert(os_info.Enum.fields[3].value == 3);
|
||||||
assert(os_info.Enum.tag_type == u5);
|
assert(os_info.Enum.tag_type == u2);
|
||||||
assert(os_info.Enum.defs.len == 0);
|
assert(os_info.Enum.defs.len == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue