Merge branch 'master' into fbsd2

master
Marcio Giaxa 2018-12-23 23:21:59 -02:00
commit 773bf80133
19 changed files with 233 additions and 53 deletions

22
.builds/freebsd.yml Normal file
View File

@ -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.

View File

@ -165,7 +165,7 @@ const std = @import("std");
pub fn main() !void {
// 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
// with an error.
try stdout_file.write("Hello, world!\n");

View File

@ -2,7 +2,7 @@ const std = @import("std");
pub fn main() !void {
// 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
// with an error.
try stdout_file.write("Hello, world!\n");

View File

@ -300,6 +300,7 @@ pub const Compilation = struct {
UserResourceLimitReached,
InvalidUtf8,
BadPathName,
DeviceBusy,
};
pub const Event = union(enum) {

View File

@ -2681,39 +2681,50 @@ static Error resolve_struct_alignment(CodeGen *g, ZigType *struct_type) {
assert(decl_node->type == NodeTypeContainerDecl);
assert(struct_type->di_type);
size_t field_count = struct_type->data.structure.src_field_count;
if (struct_type->data.structure.layout == ContainerLayoutPacked) {
struct_type->data.structure.abi_alignment = 1;
}
size_t field_count = struct_type->data.structure.src_field_count;
for (size_t i = 0; i < field_count; i += 1) {
TypeStructField *field = &struct_type->data.structure.fields[i];
// 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;
for (size_t i = 0; i < field_count; i += 1) {
TypeStructField *field = &struct_type->data.structure.fields[i];
if (field->type_entry != nullptr && 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))
continue;
// TODO If we have no type_entry for the field, we've already failed to
// 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))) {
struct_type->data.structure.resolve_status = ResolveStatusInvalid;
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);
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;
}
}

View File

@ -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 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 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 Error ir_read_const_ptr(IrAnalyze *ira, AstNode *source_node,
ConstExprValue *out_val, ConstExprValue *ptr_val);
@ -12495,6 +12495,7 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct
case ReqCompTimeNo:
if (casted_init_value->value.special == ConstValSpecialStatic &&
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)
{
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_resize(&buf, src_size);
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;
}
@ -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];
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;
}
case ConstPtrSpecialBaseStruct:
@ -20076,7 +20079,8 @@ static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue
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);
switch (val->type->id) {
case ZigTypeIdInvalid:
@ -20093,30 +20097,60 @@ static void buf_read_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue
case ZigTypeIdPromise:
zig_unreachable();
case ZigTypeIdVoid:
return;
return ErrorNone;
case ZigTypeIdBool:
val->data.x_bool = (buf[0] != 0);
return;
return ErrorNone;
case ZigTypeIdInt:
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);
return;
ira->codegen->is_big_endian, val->type->data.integral.is_signed);
return ErrorNone;
case ZigTypeIdFloat:
float_read_ieee597(val, buf, codegen->is_big_endian);
return;
float_read_ieee597(val, buf, ira->codegen->is_big_endian);
return ErrorNone;
case ZigTypeIdPointer:
{
val->data.x_ptr.special = ConstPtrSpecialHardCodedAddr;
BigInt bn;
bigint_read_twos_complement(&bn, buf, codegen->builtin_types.entry_usize->data.integral.bit_count,
codegen->is_big_endian, false);
bigint_read_twos_complement(&bn, buf, ira->codegen->builtin_types.entry_usize->data.integral.bit_count,
ira->codegen->is_big_endian, false);
val->data.x_ptr.data.hard_coded_addr.addr = bigint_as_unsigned(&bn);
return;
return ErrorNone;
}
case ZigTypeIdArray:
zig_panic("TODO buf_read_value_bytes array type");
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:
zig_panic("TODO buf_read_value_bytes maybe type");
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);
uint8_t *buf = allocate_nonzero<uint8_t>(src_size_bytes);
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;
}

View File

@ -4776,6 +4776,14 @@ Error parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const
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
clang_argv.append(nullptr);

View File

@ -398,3 +398,14 @@ test "std.ArrayList.insertSlice" {
assert(list.len == 6);
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);
}

View File

@ -19,7 +19,6 @@ pub const DynLib = switch (builtin.os) {
};
pub const LinuxDynLib = struct {
allocator: *mem.Allocator,
elf_lib: ElfLib,
fd: i32,
map_addr: usize,
@ -27,7 +26,7 @@ pub const LinuxDynLib = struct {
/// Trusts the file
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);
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];
return DynLib{
.allocator = allocator,
.elf_lib = try ElfLib.init(bytes),
.fd = fd,
.map_addr = addr,

View File

@ -243,6 +243,9 @@ pub fn formatType(
}
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) ++ "'"),
}
}
@ -1013,6 +1016,10 @@ test "fmt.format" {
const value = @intToPtr(fn () void, 0xdeadbeef);
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 Other text", "buf: {s}\n Other text", "Test");
try testFmt("cstr: Test C\n", "cstr: {s}\n", c"Test C");

View File

@ -57,7 +57,8 @@ test "std" {
_ = @import("mutex.zig");
_ = @import("segmented_list.zig");
_ = @import("spinlock.zig");
_ = @import("dynamic_library.zig");
_ = @import("base64.zig");
_ = @import("build.zig");
_ = @import("c/index.zig");

View File

@ -155,32 +155,32 @@ pub fn InStream(comptime ReadError: type) type {
pub fn readIntNative(self: *Self, comptime T: type) !T {
var bytes: [@sizeOf(T)]u8 = undefined;
try self.readNoEof(bytes[0..]);
return mem.readIntSliceNative(T, bytes);
return mem.readIntNative(T, &bytes);
}
/// Reads a foreign-endian integer
pub fn readIntForeign(self: *Self, comptime T: type) !T {
var bytes: [@sizeOf(T)]u8 = undefined;
try self.readNoEof(bytes[0..]);
return mem.readIntSliceForeign(T, bytes);
return mem.readIntForeign(T, &bytes);
}
pub fn readIntLittle(self: *Self, comptime T: type) !T {
var bytes: [@sizeOf(T)]u8 = undefined;
try self.readNoEof(bytes[0..]);
return mem.readIntSliceLittle(T, bytes);
return mem.readIntLittle(T, &bytes);
}
pub fn readIntBig(self: *Self, comptime T: type) !T {
var bytes: [@sizeOf(T)]u8 = undefined;
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 {
var bytes: [@sizeOf(T)]u8 = undefined;
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 {

View File

@ -459,6 +459,7 @@ pub const PosixOpenError = error{
NoSpaceLeft,
NotDir,
PathAlreadyExists,
DeviceBusy,
/// See https://github.com/ziglang/zig/issues/1396
Unexpected,
@ -497,6 +498,7 @@ pub fn posixOpenC(file_path: [*]const u8, flags: u32, perm: usize) !i32 {
posix.ENOTDIR => return PosixOpenError.NotDir,
posix.EPERM => return PosixOpenError.AccessDenied,
posix.EEXIST => return PosixOpenError.PathAlreadyExists,
posix.EBUSY => return PosixOpenError.DeviceBusy,
else => return unexpectedErrorPosix(err),
}
}
@ -1402,6 +1404,7 @@ const DeleteTreeError = error{
FileSystem,
FileBusy,
DirNotEmpty,
DeviceBusy,
/// On Windows, file paths must be valid Unicode.
InvalidUtf8,
@ -1463,6 +1466,7 @@ pub fn deleteTree(allocator: *Allocator, full_path: []const u8) DeleteTreeError!
error.Unexpected,
error.InvalidUtf8,
error.BadPathName,
error.DeviceBusy,
=> return err,
};
defer dir.close();
@ -1545,6 +1549,7 @@ pub const Dir = struct {
OutOfMemory,
InvalidUtf8,
BadPathName,
DeviceBusy,
/// See https://github.com/ziglang/zig/issues/1396
Unexpected,

View File

@ -1093,6 +1093,7 @@ pub const RealError = error{
NoSpaceLeft,
FileSystem,
BadPathName,
DeviceBusy,
/// On Windows, file paths must be valid Unicode.
InvalidUtf8,

View File

@ -42,6 +42,7 @@ comptime {
_ = @import("cases/if.zig");
_ = @import("cases/import.zig");
_ = @import("cases/incomplete_struct_param_tld.zig");
_ = @import("cases/inttoptr.zig");
_ = @import("cases/ir_block_deps.zig");
_ = @import("cases/math.zig");
_ = @import("cases/merge_error_sets.zig");

13
test/cases/inttoptr.zig Normal file
View File

@ -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);
}

View File

@ -15,3 +15,22 @@ fn testReinterpretBytesAsInteger() void {
};
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);
}

View File

@ -5,6 +5,11 @@ const Node = struct {
children: []Node,
};
const NodeAligned = struct {
payload: i32,
children: []align(@alignOf(NodeAligned)) NodeAligned,
};
test "struct contains slice of itself" {
var other_nodes = []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[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);
}

View File

@ -144,15 +144,20 @@ test "type info: enum info" {
}
fn testEnum() void {
const Os = @import("builtin").Os;
const Os = enum {
Windows,
Macos,
Linux,
FreeBSD,
};
const os_info = @typeInfo(Os);
assert(TypeId(os_info) == TypeId.Enum);
assert(os_info.Enum.layout == TypeInfo.ContainerLayout.Auto);
assert(os_info.Enum.fields.len == 32);
assert(mem.eql(u8, os_info.Enum.fields[1].name, "ananas"));
assert(os_info.Enum.fields[10].value == 10);
assert(os_info.Enum.tag_type == u5);
assert(os_info.Enum.fields.len == 4);
assert(mem.eql(u8, os_info.Enum.fields[1].name, "Macos"));
assert(os_info.Enum.fields[3].value == 3);
assert(os_info.Enum.tag_type == u2);
assert(os_info.Enum.defs.len == 0);
}