diff --git a/src/Sema.zig b/src/Sema.zig index 64d6e1b373..11f250e44c 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -16005,9 +16005,17 @@ fn coerce( return sema.coerceCompatiblePtrs(block, dest_ty, inst, inst_src); } - // coercion to C pointer - if (dest_info.size == .C) { - switch (inst_ty.zigTypeTag()) { + // cast from *T and [*]T to *anyopaque + // but don't do it if the source type is a double pointer + if (dest_info.pointee_type.tag() == .anyopaque and inst_ty.zigTypeTag() == .Pointer and + inst_ty.childType().zigTypeTag() != .Pointer) + { + return sema.coerceCompatiblePtrs(block, dest_ty, inst, inst_src); + } + + switch (dest_info.size) { + // coercion to C pointer + .C => switch (inst_ty.zigTypeTag()) { .Null => { return sema.addConstant(dest_ty, Value.@"null"); }, @@ -16041,22 +16049,10 @@ fn coerce( return sema.coerceCompatiblePtrs(block, dest_ty, inst, inst_src); }, else => {}, - } - } - - // cast from *T and [*]T to *anyopaque - // but don't do it if the source type is a double pointer - if (dest_info.pointee_type.tag() == .anyopaque and inst_ty.zigTypeTag() == .Pointer and - inst_ty.childType().zigTypeTag() != .Pointer) - { - return sema.coerceCompatiblePtrs(block, dest_ty, inst, inst_src); - } - - switch (dest_info.size) { - .C, .Many => {}, + }, .One => switch (dest_info.pointee_type.zigTypeTag()) { .Union => { - // cast from pointer to anonymous struct to pointer to union + // pointer to anonymous struct to pointer to union if (inst_ty.isSinglePointer() and inst_ty.childType().isAnonStruct() and !dest_info.mutable) @@ -16065,7 +16061,7 @@ fn coerce( } }, .Struct => { - // cast from pointer to anonymous struct to pointer to struct + // pointer to anonymous struct to pointer to struct if (inst_ty.isSinglePointer() and inst_ty.childType().isAnonStruct() and !dest_info.mutable) @@ -16073,6 +16069,15 @@ fn coerce( return sema.coerceAnonStructToStructPtrs(block, dest_ty, dest_ty_src, inst, inst_src); } }, + .Array => { + // pointer to tuple to pointer to array + if (inst_ty.isSinglePointer() and + inst_ty.childType().isTuple() and + !dest_info.mutable) + { + return sema.coerceTupleToArrayPtrs(block, dest_ty, dest_ty_src, inst, inst_src); + } + }, else => {}, }, .Slice => { @@ -16084,6 +16089,7 @@ fn coerce( return sema.coerceTupleToSlicePtrs(block, dest_ty, dest_ty_src, inst, inst_src); } }, + .Many => {}, } // This will give an extra hint on top of what the bottom of this func would provide. @@ -17554,6 +17560,26 @@ fn coerceTupleToSlicePtrs( return sema.coerceArrayPtrToSlice(block, slice_ty, ptr_array, slice_ty_src); } +/// If the lengths match, coerces element-wise. +fn coerceTupleToArrayPtrs( + sema: *Sema, + block: *Block, + ptr_array_ty: Type, + array_ty_src: LazySrcLoc, + ptr_tuple: Air.Inst.Ref, + tuple_src: LazySrcLoc, +) !Air.Inst.Ref { + const tuple = try sema.analyzeLoad(block, tuple_src, ptr_tuple, tuple_src); + const ptr_info = ptr_array_ty.ptrInfo().data; + const array_ty = ptr_info.pointee_type; + const array_inst = try sema.coerceTupleToArray(block, array_ty, array_ty_src, tuple, tuple_src); + if (ptr_info.@"align" != 0) { + return sema.fail(block, array_ty_src, "TODO: override the alignment of the array decl we create here", .{}); + } + const ptr_array = try sema.analyzeRef(block, array_ty_src, array_inst); + return ptr_array; +} + /// Handles both tuples and anon struct literals. Coerces field-wise. Reports /// errors for both extra fields and missing fields. fn coerceTupleToStruct( diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index fb7daa80ec..aacb3af47d 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -5838,8 +5838,15 @@ pub const FuncGen = struct { const llvm_i = llvmFieldIndex(result_ty, i, target, &ptr_ty_buf).?; indices[1] = llvm_u32.constInt(llvm_i, .False); const field_ptr = self.builder.buildInBoundsGEP(alloca_inst, &indices, indices.len, ""); - const store_inst = self.builder.buildStore(llvm_elem, field_ptr); - store_inst.setAlignment(result_ty.structFieldAlign(i, target)); + var field_ptr_payload: Type.Payload.Pointer = .{ + .data = .{ + .pointee_type = self.air.typeOf(elem), + .@"align" = result_ty.structFieldAlign(i, target), + .@"addrspace" = .generic, + }, + }; + const field_ptr_ty = Type.initPayload(&field_ptr_payload.base); + self.store(field_ptr, field_ptr_ty, llvm_elem, .NotAtomic); } return alloca_inst; @@ -5871,8 +5878,14 @@ pub const FuncGen = struct { }; const elem_ptr = self.builder.buildInBoundsGEP(alloca_inst, &indices, indices.len, ""); const llvm_elem = try self.resolveInst(elem); - const store_inst = self.builder.buildStore(llvm_elem, elem_ptr); - store_inst.setAlignment(elem_ty.abiAlignment(target)); + var elem_ptr_payload: Type.Payload.Pointer = .{ + .data = .{ + .pointee_type = elem_ty, + .@"addrspace" = .generic, + }, + }; + const elem_ptr_ty = Type.initPayload(&elem_ptr_payload.base); + self.store(elem_ptr, elem_ptr_ty, llvm_elem, .NotAtomic); } return alloca_inst; diff --git a/test/behavior/align.zig b/test/behavior/align.zig index c9a43526f6..50ba13073d 100644 --- a/test/behavior/align.zig +++ b/test/behavior/align.zig @@ -193,11 +193,9 @@ test "function alignment" { } test "implicitly decreasing fn alignment" { - if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage1) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // function alignment is a compile error on wasm32/wasm64 @@ -321,7 +319,6 @@ const DefaultAligned = struct { test "read 128-bit field from default aligned struct in stack memory" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; @@ -353,10 +350,10 @@ test "read 128-bit field from default aligned struct in global memory" { test "struct field explicit alignment" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; const S = struct { const Node = struct { @@ -402,8 +399,9 @@ test "align(@alignOf(T)) T does not force resolution of T" { } test "align(N) on functions" { - if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage1) return error.SkipZigTest; + + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; diff --git a/test/behavior/array.zig b/test/behavior/array.zig index e6204729d4..efd6624445 100644 --- a/test/behavior/array.zig +++ b/test/behavior/array.zig @@ -553,12 +553,11 @@ test "type coercion of anon struct literal to array" { } test "type coercion of pointer to anon struct literal to pointer to array" { - if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO const S = struct { const U = union { diff --git a/test/behavior/basic.zig b/test/behavior/basic.zig index 25a302398b..481a15bbe5 100644 --- a/test/behavior/basic.zig +++ b/test/behavior/basic.zig @@ -760,7 +760,8 @@ test "pointer to thread local array" { threadlocal var buffer: [11]u8 = undefined; test "auto created variables have correct alignment" { - if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO const S = struct { fn foo(str: [*]const u8) u32 { diff --git a/test/behavior/slice.zig b/test/behavior/slice.zig index f5421f9159..09025df69f 100644 --- a/test/behavior/slice.zig +++ b/test/behavior/slice.zig @@ -518,7 +518,11 @@ test "slice syntax resulting in pointer-to-array" { } test "type coercion of pointer to anon struct literal to pointer to slice" { - if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO const S = struct { const U = union { @@ -546,7 +550,7 @@ test "type coercion of pointer to anon struct literal to pointer to slice" { try expect(mem.eql(u8, slice2[2], "world!")); } }; - // try S.doTheTest(); + try S.doTheTest(); comptime try S.doTheTest(); } @@ -578,8 +582,6 @@ test "slice bounds in comptime concatenation" { } test "slice sentinel access at comptime" { - if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO - { const str0 = &[_:0]u8{ '1', '2', '3' }; const slice0: [:0]const u8 = str0; diff --git a/test/behavior/struct.zig b/test/behavior/struct.zig index 02bfd2fa5b..6e48f7ca21 100644 --- a/test/behavior/struct.zig +++ b/test/behavior/struct.zig @@ -426,7 +426,7 @@ test "packed struct 24bits" { if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_llvm and builtin.stage2_arch == .wasm32) return error.SkipZigTest; // TODO + if (builtin.cpu.arch == .wasm32) return error.SkipZigTest; // TODO comptime { try expect(@sizeOf(Foo24Bits) == 4); diff --git a/test/behavior/while.zig b/test/behavior/while.zig index dced1ee208..a5b777640a 100644 --- a/test/behavior/while.zig +++ b/test/behavior/while.zig @@ -289,9 +289,8 @@ test "while bool 2 break statements and an else" { } test "while optional 2 break statements and an else" { - if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO const S = struct { fn entry(opt_t: ?bool, f: bool) !void { @@ -308,7 +307,8 @@ test "while optional 2 break statements and an else" { } test "while error 2 break statements and an else" { - if (@import("builtin").zig_backend != .stage1) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO const S = struct { fn entry(opt_t: anyerror!bool, f: bool) !void {