From 966670645a382e6c660b4a002e5eb1264a00cbe5 Mon Sep 17 00:00:00 2001 From: Michael Dusan Date: Fri, 30 Aug 2019 06:39:01 -0400 Subject: fix stage1 to build on macOS + xcode/clang --- src/ir.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/ir.cpp') diff --git a/src/ir.cpp b/src/ir.cpp index dfe9132e2d..d9d1c7aa57 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -25673,8 +25673,8 @@ static Error ir_resolve_lazy_raw(AstNode *source_node, ConstExprValue *val) { } } - uint64_t abi_size; - uint64_t size_in_bits; + size_t abi_size; + size_t size_in_bits; if ((err = type_val_resolve_abi_size(ira->codegen, source_node, &lazy_size_of->target_type->value, &abi_size, &size_in_bits))) { -- cgit v1.2.3 From d9fed5cdfdfa6ac944856cd360d3385296f136e8 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Fri, 30 Aug 2019 14:53:44 -0400 Subject: align(@alignOf(T)) T does not force resolution of T --- src/ir.cpp | 49 +++++++++++++++++++++++++++++------------- std/array_list.zig | 5 +++++ std/mem.zig | 18 ++++++++++------ test/stage1/behavior/align.zig | 25 ++++++++++++++++++++- 4 files changed, 75 insertions(+), 22 deletions(-) (limited to 'src/ir.cpp') diff --git a/src/ir.cpp b/src/ir.cpp index d9d1c7aa57..6f740cc937 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -12613,10 +12613,27 @@ static bool ir_resolve_const_align(CodeGen *codegen, IrExecutable *exec, AstNode return true; } -static bool ir_resolve_align(IrAnalyze *ira, IrInstruction *value, uint32_t *out) { +static bool ir_resolve_align(IrAnalyze *ira, IrInstruction *value, ZigType *elem_type, uint32_t *out) { if (type_is_invalid(value->value.type)) return false; + // Look for this pattern: `*align(@alignOf(T)) T`. + // This can be resolved to be `*out = 0` without resolving any alignment. + if (elem_type != nullptr && value->value.special == ConstValSpecialLazy && + value->value.data.x_lazy->id == LazyValueIdAlignOf) + { + LazyValueAlignOf *lazy_align_of = reinterpret_cast(value->value.data.x_lazy); + + ZigType *lazy_elem_type = ir_resolve_type(lazy_align_of->ira, lazy_align_of->target_type); + if (type_is_invalid(lazy_elem_type)) + return false; + + if (elem_type == lazy_elem_type) { + *out = 0; + return true; + } + } + IrInstruction *casted_value = ir_implicit_cast(ira, value, get_align_amt_type(ira->codegen)); if (type_is_invalid(casted_value->value.type)) return false; @@ -14424,7 +14441,7 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, } var->align_bytes = get_abi_alignment(ira->codegen, result_type); } else { - if (!ir_resolve_align(ira, decl_var_instruction->align_value->child, &var->align_bytes)) { + if (!ir_resolve_align(ira, decl_var_instruction->align_value->child, nullptr, &var->align_bytes)) { var->var_type = ira->codegen->builtin_types.entry_invalid; } } @@ -14879,7 +14896,7 @@ static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspe if (alloca_src->base.child == nullptr || is_comptime) { uint32_t align = 0; - if (alloca_src->align != nullptr && !ir_resolve_align(ira, alloca_src->align->child, &align)) { + if (alloca_src->align != nullptr && !ir_resolve_align(ira, alloca_src->align->child, nullptr, &align)) { return ira->codegen->invalid_instruction; } IrInstruction *alloca_gen; @@ -15896,7 +15913,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c copy_const_val(&const_instruction->base.value, align_result, true); uint32_t align_bytes = 0; - ir_resolve_align(ira, &const_instruction->base, &align_bytes); + ir_resolve_align(ira, &const_instruction->base, nullptr, &align_bytes); impl_fn->align_bytes = align_bytes; inst_fn_type_id.alignment = align_bytes; } @@ -23948,7 +23965,7 @@ static IrInstruction *ir_analyze_instruction_ptr_type(IrAnalyze *ira, IrInstruct static IrInstruction *ir_analyze_instruction_align_cast(IrAnalyze *ira, IrInstructionAlignCast *instruction) { uint32_t align_bytes; IrInstruction *align_bytes_inst = instruction->align_bytes->child; - if (!ir_resolve_align(ira, align_bytes_inst, &align_bytes)) + if (!ir_resolve_align(ira, align_bytes_inst, nullptr, &align_bytes)) return ira->codegen->invalid_instruction; IrInstruction *target = instruction->target->child; @@ -23974,7 +23991,7 @@ static IrInstruction *ir_analyze_instruction_opaque_type(IrAnalyze *ira, IrInstr static IrInstruction *ir_analyze_instruction_set_align_stack(IrAnalyze *ira, IrInstructionSetAlignStack *instruction) { uint32_t align_bytes; IrInstruction *align_bytes_inst = instruction->align_bytes->child; - if (!ir_resolve_align(ira, align_bytes_inst, &align_bytes)) + if (!ir_resolve_align(ira, align_bytes_inst, nullptr, &align_bytes)) return ira->codegen->invalid_instruction; if (align_bytes > 256) { @@ -25555,7 +25572,7 @@ static ZigType *ir_resolve_lazy_fn_type(IrAnalyze *ira, AstNode *source_node, La } if (lazy_fn_type->align_inst != nullptr) { - if (!ir_resolve_align(ira, lazy_fn_type->align_inst, &fn_type_id.alignment)) + if (!ir_resolve_align(ira, lazy_fn_type->align_inst, nullptr, &fn_type_id.alignment)) return nullptr; } @@ -25690,14 +25707,15 @@ static Error ir_resolve_lazy_raw(AstNode *source_node, ConstExprValue *val) { LazyValueSliceType *lazy_slice_type = reinterpret_cast(val->data.x_lazy); IrAnalyze *ira = lazy_slice_type->ira; + ZigType *elem_type = ir_resolve_type(ira, lazy_slice_type->elem_type); + if (type_is_invalid(elem_type)) + return ErrorSemanticAnalyzeFail; + uint32_t align_bytes = 0; if (lazy_slice_type->align_inst != nullptr) { - if (!ir_resolve_align(ira, lazy_slice_type->align_inst, &align_bytes)) + if (!ir_resolve_align(ira, lazy_slice_type->align_inst, elem_type, &align_bytes)) return ErrorSemanticAnalyzeFail; } - ZigType *elem_type = ir_resolve_type(ira, lazy_slice_type->elem_type); - if (type_is_invalid(elem_type)) - return ErrorSemanticAnalyzeFail; switch (elem_type->id) { case ZigTypeIdInvalid: // handled above @@ -25750,14 +25768,15 @@ static Error ir_resolve_lazy_raw(AstNode *source_node, ConstExprValue *val) { LazyValuePtrType *lazy_ptr_type = reinterpret_cast(val->data.x_lazy); IrAnalyze *ira = lazy_ptr_type->ira; + ZigType *elem_type = ir_resolve_type(ira, lazy_ptr_type->elem_type); + if (type_is_invalid(elem_type)) + return ErrorSemanticAnalyzeFail; + uint32_t align_bytes = 0; if (lazy_ptr_type->align_inst != nullptr) { - if (!ir_resolve_align(ira, lazy_ptr_type->align_inst, &align_bytes)) + if (!ir_resolve_align(ira, lazy_ptr_type->align_inst, elem_type, &align_bytes)) return ErrorSemanticAnalyzeFail; } - ZigType *elem_type = ir_resolve_type(ira, lazy_ptr_type->elem_type); - if (type_is_invalid(elem_type)) - return ErrorSemanticAnalyzeFail; if (elem_type->id == ZigTypeIdUnreachable) { ir_add_error(ira, lazy_ptr_type->elem_type, diff --git a/std/array_list.zig b/std/array_list.zig index a527d818d6..31ae02b291 100644 --- a/std/array_list.zig +++ b/std/array_list.zig @@ -10,6 +10,11 @@ pub fn ArrayList(comptime T: type) type { } pub fn AlignedArrayList(comptime T: type, comptime alignment: ?u29) type { + if (alignment) |a| { + if (a == @alignOf(T)) { + return AlignedArrayList(T, null); + } + } return struct { const Self = @This(); diff --git a/std/mem.zig b/std/mem.zig index 49a143dffc..014be487cc 100644 --- a/std/mem.zig +++ b/std/mem.zig @@ -94,24 +94,30 @@ pub const Allocator = struct { } pub fn alloc(self: *Allocator, comptime T: type, n: usize) Error![]T { - return self.alignedAlloc(T, @alignOf(T), n); + return self.alignedAlloc(T, null, n); } pub fn alignedAlloc( self: *Allocator, comptime T: type, - comptime alignment: u29, + /// null means naturally aligned + comptime alignment: ?u29, n: usize, - ) Error![]align(alignment) T { + ) Error![]align(alignment orelse @alignOf(T)) T { + const a = if (alignment) |a| blk: { + if (a == @alignOf(T)) return alignedAlloc(self, T, null, n); + break :blk a; + } else @alignOf(T); + if (n == 0) { - return ([*]align(alignment) T)(undefined)[0..0]; + return ([*]align(a) T)(undefined)[0..0]; } const byte_count = math.mul(usize, @sizeOf(T), n) catch return Error.OutOfMemory; - const byte_slice = try self.reallocFn(self, ([*]u8)(undefined)[0..0], undefined, byte_count, alignment); + const byte_slice = try self.reallocFn(self, ([*]u8)(undefined)[0..0], undefined, byte_count, a); assert(byte_slice.len == byte_count); @memset(byte_slice.ptr, undefined, byte_slice.len); - return @bytesToSlice(T, @alignCast(alignment, byte_slice)); + return @bytesToSlice(T, @alignCast(a, byte_slice)); } /// This function requests a new byte size for an existing allocation, diff --git a/test/stage1/behavior/align.zig b/test/stage1/behavior/align.zig index 677ae85b68..266e5d3519 100644 --- a/test/stage1/behavior/align.zig +++ b/test/stage1/behavior/align.zig @@ -1,4 +1,5 @@ -const expect = @import("std").testing.expect; +const std = @import("std"); +const expect = std.testing.expect; const builtin = @import("builtin"); var foo: u8 align(4) = 100; @@ -305,3 +306,25 @@ test "struct field explicit alignment" { comptime expect(@typeOf(&node.massive_byte) == *align(64) u8); expect(@ptrToInt(&node.massive_byte) % 64 == 0); } + +test "align(@alignOf(T)) T does not force resolution of T" { + const S = struct { + const A = struct { + a: *align(@alignOf(A)) A, + }; + fn doTheTest() void { + suspend { + resume @frame(); + } + _ = bar(@Frame(doTheTest)); + } + fn bar(comptime T: type) *align(@alignOf(T)) T { + ok = true; + return undefined; + } + + var ok = false; + }; + _ = async S.doTheTest(); + expect(S.ok); +} -- cgit v1.2.3