authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-08-30 14:53:44-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-08-30 14:53:44-04:00
logd9fed5cdfdfa6ac944856cd360d3385296f136e8
tree6c57968453032c3e3cb8605bf925533bddd94705
parent966670645a382e6c660b4a002e5eb1264a00cbe5
signaturelock-open Commit is signed but in an unrecognized format.

align(@alignOf(T)) T does not force resolution of T


4 files changed, 75 insertions(+), 22 deletions(-)

src/ir.cpp+34-15
......@@ -12613,10 +12613,27 @@ static bool ir_resolve_const_align(CodeGen *codegen, IrExecutable *exec, AstNode
1261312613 return true;
1261412614}
1261512615
12616static bool ir_resolve_align(IrAnalyze *ira, IrInstruction *value, uint32_t *out) {
12616static bool ir_resolve_align(IrAnalyze *ira, IrInstruction *value, ZigType *elem_type, uint32_t *out) {
1261712617 if (type_is_invalid(value->value.type))
1261812618 return false;
1261912619
12620 // Look for this pattern: `*align(@alignOf(T)) T`.
12621 // This can be resolved to be `*out = 0` without resolving any alignment.
12622 if (elem_type != nullptr && value->value.special == ConstValSpecialLazy &&
12623 value->value.data.x_lazy->id == LazyValueIdAlignOf)
12624 {
12625 LazyValueAlignOf *lazy_align_of = reinterpret_cast<LazyValueAlignOf *>(value->value.data.x_lazy);
12626
12627 ZigType *lazy_elem_type = ir_resolve_type(lazy_align_of->ira, lazy_align_of->target_type);
12628 if (type_is_invalid(lazy_elem_type))
12629 return false;
12630
12631 if (elem_type == lazy_elem_type) {
12632 *out = 0;
12633 return true;
12634 }
12635 }
12636
1262012637 IrInstruction *casted_value = ir_implicit_cast(ira, value, get_align_amt_type(ira->codegen));
1262112638 if (type_is_invalid(casted_value->value.type))
1262212639 return false;
......@@ -14424,7 +14441,7 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira,
1442414441 }
1442514442 var->align_bytes = get_abi_alignment(ira->codegen, result_type);
1442614443 } else {
14427 if (!ir_resolve_align(ira, decl_var_instruction->align_value->child, &var->align_bytes)) {
14444 if (!ir_resolve_align(ira, decl_var_instruction->align_value->child, nullptr, &var->align_bytes)) {
1442814445 var->var_type = ira->codegen->builtin_types.entry_invalid;
1442914446 }
1443014447 }
......@@ -14879,7 +14896,7 @@ static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspe
1487914896
1488014897 if (alloca_src->base.child == nullptr || is_comptime) {
1488114898 uint32_t align = 0;
14882 if (alloca_src->align != nullptr && !ir_resolve_align(ira, alloca_src->align->child, &align)) {
14899 if (alloca_src->align != nullptr && !ir_resolve_align(ira, alloca_src->align->child, nullptr, &align)) {
1488314900 return ira->codegen->invalid_instruction;
1488414901 }
1488514902 IrInstruction *alloca_gen;
......@@ -15896,7 +15913,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c
1589615913 copy_const_val(&const_instruction->base.value, align_result, true);
1589715914
1589815915 uint32_t align_bytes = 0;
15899 ir_resolve_align(ira, &const_instruction->base, &align_bytes);
15916 ir_resolve_align(ira, &const_instruction->base, nullptr, &align_bytes);
1590015917 impl_fn->align_bytes = align_bytes;
1590115918 inst_fn_type_id.alignment = align_bytes;
1590215919 }
......@@ -23948,7 +23965,7 @@ static IrInstruction *ir_analyze_instruction_ptr_type(IrAnalyze *ira, IrInstruct
2394823965static IrInstruction *ir_analyze_instruction_align_cast(IrAnalyze *ira, IrInstructionAlignCast *instruction) {
2394923966 uint32_t align_bytes;
2395023967 IrInstruction *align_bytes_inst = instruction->align_bytes->child;
23951 if (!ir_resolve_align(ira, align_bytes_inst, &align_bytes))
23968 if (!ir_resolve_align(ira, align_bytes_inst, nullptr, &align_bytes))
2395223969 return ira->codegen->invalid_instruction;
2395323970
2395423971 IrInstruction *target = instruction->target->child;
......@@ -23974,7 +23991,7 @@ static IrInstruction *ir_analyze_instruction_opaque_type(IrAnalyze *ira, IrInstr
2397423991static IrInstruction *ir_analyze_instruction_set_align_stack(IrAnalyze *ira, IrInstructionSetAlignStack *instruction) {
2397523992 uint32_t align_bytes;
2397623993 IrInstruction *align_bytes_inst = instruction->align_bytes->child;
23977 if (!ir_resolve_align(ira, align_bytes_inst, &align_bytes))
23994 if (!ir_resolve_align(ira, align_bytes_inst, nullptr, &align_bytes))
2397823995 return ira->codegen->invalid_instruction;
2397923996
2398023997 if (align_bytes > 256) {
......@@ -25555,7 +25572,7 @@ static ZigType *ir_resolve_lazy_fn_type(IrAnalyze *ira, AstNode *source_node, La
2555525572 }
2555625573
2555725574 if (lazy_fn_type->align_inst != nullptr) {
25558 if (!ir_resolve_align(ira, lazy_fn_type->align_inst, &fn_type_id.alignment))
25575 if (!ir_resolve_align(ira, lazy_fn_type->align_inst, nullptr, &fn_type_id.alignment))
2555925576 return nullptr;
2556025577 }
2556125578
......@@ -25690,14 +25707,15 @@ static Error ir_resolve_lazy_raw(AstNode *source_node, ConstExprValue *val) {
2569025707 LazyValueSliceType *lazy_slice_type = reinterpret_cast<LazyValueSliceType *>(val->data.x_lazy);
2569125708 IrAnalyze *ira = lazy_slice_type->ira;
2569225709
25710 ZigType *elem_type = ir_resolve_type(ira, lazy_slice_type->elem_type);
25711 if (type_is_invalid(elem_type))
25712 return ErrorSemanticAnalyzeFail;
25713
2569325714 uint32_t align_bytes = 0;
2569425715 if (lazy_slice_type->align_inst != nullptr) {
25695 if (!ir_resolve_align(ira, lazy_slice_type->align_inst, &align_bytes))
25716 if (!ir_resolve_align(ira, lazy_slice_type->align_inst, elem_type, &align_bytes))
2569625717 return ErrorSemanticAnalyzeFail;
2569725718 }
25698 ZigType *elem_type = ir_resolve_type(ira, lazy_slice_type->elem_type);
25699 if (type_is_invalid(elem_type))
25700 return ErrorSemanticAnalyzeFail;
2570125719
2570225720 switch (elem_type->id) {
2570325721 case ZigTypeIdInvalid: // handled above
......@@ -25750,14 +25768,15 @@ static Error ir_resolve_lazy_raw(AstNode *source_node, ConstExprValue *val) {
2575025768 LazyValuePtrType *lazy_ptr_type = reinterpret_cast<LazyValuePtrType *>(val->data.x_lazy);
2575125769 IrAnalyze *ira = lazy_ptr_type->ira;
2575225770
25771 ZigType *elem_type = ir_resolve_type(ira, lazy_ptr_type->elem_type);
25772 if (type_is_invalid(elem_type))
25773 return ErrorSemanticAnalyzeFail;
25774
2575325775 uint32_t align_bytes = 0;
2575425776 if (lazy_ptr_type->align_inst != nullptr) {
25755 if (!ir_resolve_align(ira, lazy_ptr_type->align_inst, &align_bytes))
25777 if (!ir_resolve_align(ira, lazy_ptr_type->align_inst, elem_type, &align_bytes))
2575625778 return ErrorSemanticAnalyzeFail;
2575725779 }
25758 ZigType *elem_type = ir_resolve_type(ira, lazy_ptr_type->elem_type);
25759 if (type_is_invalid(elem_type))
25760 return ErrorSemanticAnalyzeFail;
2576125780
2576225781 if (elem_type->id == ZigTypeIdUnreachable) {
2576325782 ir_add_error(ira, lazy_ptr_type->elem_type,
std/array_list.zig+5
......@@ -10,6 +10,11 @@ pub fn ArrayList(comptime T: type) type {
1010}
1111
1212pub fn AlignedArrayList(comptime T: type, comptime alignment: ?u29) type {
13 if (alignment) |a| {
14 if (a == @alignOf(T)) {
15 return AlignedArrayList(T, null);
16 }
17 }
1318 return struct {
1419 const Self = @This();
1520
std/mem.zig+12-6
......@@ -94,24 +94,30 @@ pub const Allocator = struct {
9494 }
9595
9696 pub fn alloc(self: *Allocator, comptime T: type, n: usize) Error![]T {
97 return self.alignedAlloc(T, @alignOf(T), n);
97 return self.alignedAlloc(T, null, n);
9898 }
9999
100100 pub fn alignedAlloc(
101101 self: *Allocator,
102102 comptime T: type,
103 comptime alignment: u29,
103 /// null means naturally aligned
104 comptime alignment: ?u29,
104105 n: usize,
105 ) Error![]align(alignment) T {
106 ) Error![]align(alignment orelse @alignOf(T)) T {
107 const a = if (alignment) |a| blk: {
108 if (a == @alignOf(T)) return alignedAlloc(self, T, null, n);
109 break :blk a;
110 } else @alignOf(T);
111
106112 if (n == 0) {
107 return ([*]align(alignment) T)(undefined)[0..0];
113 return ([*]align(a) T)(undefined)[0..0];
108114 }
109115
110116 const byte_count = math.mul(usize, @sizeOf(T), n) catch return Error.OutOfMemory;
111 const byte_slice = try self.reallocFn(self, ([*]u8)(undefined)[0..0], undefined, byte_count, alignment);
117 const byte_slice = try self.reallocFn(self, ([*]u8)(undefined)[0..0], undefined, byte_count, a);
112118 assert(byte_slice.len == byte_count);
113119 @memset(byte_slice.ptr, undefined, byte_slice.len);
114 return @bytesToSlice(T, @alignCast(alignment, byte_slice));
120 return @bytesToSlice(T, @alignCast(a, byte_slice));
115121 }
116122
117123 /// This function requests a new byte size for an existing allocation,
test/stage1/behavior/align.zig+24-1
......@@ -1,4 +1,5 @@
1const expect = @import("std").testing.expect;
1const std = @import("std");
2const expect = std.testing.expect;
23const builtin = @import("builtin");
34
45var foo: u8 align(4) = 100;
......@@ -305,3 +306,25 @@ test "struct field explicit alignment" {
305306 comptime expect(@typeOf(&node.massive_byte) == *align(64) u8);
306307 expect(@ptrToInt(&node.massive_byte) % 64 == 0);
307308}
309
310test "align(@alignOf(T)) T does not force resolution of T" {
311 const S = struct {
312 const A = struct {
313 a: *align(@alignOf(A)) A,
314 };
315 fn doTheTest() void {
316 suspend {
317 resume @frame();
318 }
319 _ = bar(@Frame(doTheTest));
320 }
321 fn bar(comptime T: type) *align(@alignOf(T)) T {
322 ok = true;
323 return undefined;
324 }
325
326 var ok = false;
327 };
328 _ = async S.doTheTest();
329 expect(S.ok);
330}