| author | |
| committer | |
| log | f736cde397a6abb1399827ed5988c43001706580 |
| tree | c1ce080f82846a4322eac7be653a78044338e740 |
| parent | 017d3864de1f337d01726e87534a4e2093c7265f |
This involved an LLVM backend fix for the aggregate_init instruction.8 files changed, 80 insertions(+), 41 deletions(-)
src/Sema.zig+44-18| ... | ... | @@ -16005,9 +16005,17 @@ fn coerce( |
| 16005 | 16005 | return sema.coerceCompatiblePtrs(block, dest_ty, inst, inst_src); |
| 16006 | 16006 | } |
| 16007 | 16007 | |
| 16008 | // coercion to C pointer | |
| 16009 | if (dest_info.size == .C) { | |
| 16010 | switch (inst_ty.zigTypeTag()) { | |
| 16008 | // cast from *T and [*]T to *anyopaque | |
| 16009 | // but don't do it if the source type is a double pointer | |
| 16010 | if (dest_info.pointee_type.tag() == .anyopaque and inst_ty.zigTypeTag() == .Pointer and | |
| 16011 | inst_ty.childType().zigTypeTag() != .Pointer) | |
| 16012 | { | |
| 16013 | return sema.coerceCompatiblePtrs(block, dest_ty, inst, inst_src); | |
| 16014 | } | |
| 16015 | ||
| 16016 | switch (dest_info.size) { | |
| 16017 | // coercion to C pointer | |
| 16018 | .C => switch (inst_ty.zigTypeTag()) { | |
| 16011 | 16019 | .Null => { |
| 16012 | 16020 | return sema.addConstant(dest_ty, Value.@"null"); |
| 16013 | 16021 | }, |
| ... | ... | @@ -16041,22 +16049,10 @@ fn coerce( |
| 16041 | 16049 | return sema.coerceCompatiblePtrs(block, dest_ty, inst, inst_src); |
| 16042 | 16050 | }, |
| 16043 | 16051 | else => {}, |
| 16044 | } | |
| 16045 | } | |
| 16046 | ||
| 16047 | // cast from *T and [*]T to *anyopaque | |
| 16048 | // but don't do it if the source type is a double pointer | |
| 16049 | if (dest_info.pointee_type.tag() == .anyopaque and inst_ty.zigTypeTag() == .Pointer and | |
| 16050 | inst_ty.childType().zigTypeTag() != .Pointer) | |
| 16051 | { | |
| 16052 | return sema.coerceCompatiblePtrs(block, dest_ty, inst, inst_src); | |
| 16053 | } | |
| 16054 | ||
| 16055 | switch (dest_info.size) { | |
| 16056 | .C, .Many => {}, | |
| 16052 | }, | |
| 16057 | 16053 | .One => switch (dest_info.pointee_type.zigTypeTag()) { |
| 16058 | 16054 | .Union => { |
| 16059 | // cast from pointer to anonymous struct to pointer to union | |
| 16055 | // pointer to anonymous struct to pointer to union | |
| 16060 | 16056 | if (inst_ty.isSinglePointer() and |
| 16061 | 16057 | inst_ty.childType().isAnonStruct() and |
| 16062 | 16058 | !dest_info.mutable) |
| ... | ... | @@ -16065,7 +16061,7 @@ fn coerce( |
| 16065 | 16061 | } |
| 16066 | 16062 | }, |
| 16067 | 16063 | .Struct => { |
| 16068 | // cast from pointer to anonymous struct to pointer to struct | |
| 16064 | // pointer to anonymous struct to pointer to struct | |
| 16069 | 16065 | if (inst_ty.isSinglePointer() and |
| 16070 | 16066 | inst_ty.childType().isAnonStruct() and |
| 16071 | 16067 | !dest_info.mutable) |
| ... | ... | @@ -16073,6 +16069,15 @@ fn coerce( |
| 16073 | 16069 | return sema.coerceAnonStructToStructPtrs(block, dest_ty, dest_ty_src, inst, inst_src); |
| 16074 | 16070 | } |
| 16075 | 16071 | }, |
| 16072 | .Array => { | |
| 16073 | // pointer to tuple to pointer to array | |
| 16074 | if (inst_ty.isSinglePointer() and | |
| 16075 | inst_ty.childType().isTuple() and | |
| 16076 | !dest_info.mutable) | |
| 16077 | { | |
| 16078 | return sema.coerceTupleToArrayPtrs(block, dest_ty, dest_ty_src, inst, inst_src); | |
| 16079 | } | |
| 16080 | }, | |
| 16076 | 16081 | else => {}, |
| 16077 | 16082 | }, |
| 16078 | 16083 | .Slice => { |
| ... | ... | @@ -16084,6 +16089,7 @@ fn coerce( |
| 16084 | 16089 | return sema.coerceTupleToSlicePtrs(block, dest_ty, dest_ty_src, inst, inst_src); |
| 16085 | 16090 | } |
| 16086 | 16091 | }, |
| 16092 | .Many => {}, | |
| 16087 | 16093 | } |
| 16088 | 16094 | |
| 16089 | 16095 | // This will give an extra hint on top of what the bottom of this func would provide. |
| ... | ... | @@ -17554,6 +17560,26 @@ fn coerceTupleToSlicePtrs( |
| 17554 | 17560 | return sema.coerceArrayPtrToSlice(block, slice_ty, ptr_array, slice_ty_src); |
| 17555 | 17561 | } |
| 17556 | 17562 | |
| 17563 | /// If the lengths match, coerces element-wise. | |
| 17564 | fn coerceTupleToArrayPtrs( | |
| 17565 | sema: *Sema, | |
| 17566 | block: *Block, | |
| 17567 | ptr_array_ty: Type, | |
| 17568 | array_ty_src: LazySrcLoc, | |
| 17569 | ptr_tuple: Air.Inst.Ref, | |
| 17570 | tuple_src: LazySrcLoc, | |
| 17571 | ) !Air.Inst.Ref { | |
| 17572 | const tuple = try sema.analyzeLoad(block, tuple_src, ptr_tuple, tuple_src); | |
| 17573 | const ptr_info = ptr_array_ty.ptrInfo().data; | |
| 17574 | const array_ty = ptr_info.pointee_type; | |
| 17575 | const array_inst = try sema.coerceTupleToArray(block, array_ty, array_ty_src, tuple, tuple_src); | |
| 17576 | if (ptr_info.@"align" != 0) { | |
| 17577 | return sema.fail(block, array_ty_src, "TODO: override the alignment of the array decl we create here", .{}); | |
| 17578 | } | |
| 17579 | const ptr_array = try sema.analyzeRef(block, array_ty_src, array_inst); | |
| 17580 | return ptr_array; | |
| 17581 | } | |
| 17582 | ||
| 17557 | 17583 | /// Handles both tuples and anon struct literals. Coerces field-wise. Reports |
| 17558 | 17584 | /// errors for both extra fields and missing fields. |
| 17559 | 17585 | fn coerceTupleToStruct( |
src/codegen/llvm.zig+17-4| ... | ... | @@ -5838,8 +5838,15 @@ pub const FuncGen = struct { |
| 5838 | 5838 | const llvm_i = llvmFieldIndex(result_ty, i, target, &ptr_ty_buf).?; |
| 5839 | 5839 | indices[1] = llvm_u32.constInt(llvm_i, .False); |
| 5840 | 5840 | const field_ptr = self.builder.buildInBoundsGEP(alloca_inst, &indices, indices.len, ""); |
| 5841 | const store_inst = self.builder.buildStore(llvm_elem, field_ptr); | |
| 5842 | store_inst.setAlignment(result_ty.structFieldAlign(i, target)); | |
| 5841 | var field_ptr_payload: Type.Payload.Pointer = .{ | |
| 5842 | .data = .{ | |
| 5843 | .pointee_type = self.air.typeOf(elem), | |
| 5844 | .@"align" = result_ty.structFieldAlign(i, target), | |
| 5845 | .@"addrspace" = .generic, | |
| 5846 | }, | |
| 5847 | }; | |
| 5848 | const field_ptr_ty = Type.initPayload(&field_ptr_payload.base); | |
| 5849 | self.store(field_ptr, field_ptr_ty, llvm_elem, .NotAtomic); | |
| 5843 | 5850 | } |
| 5844 | 5851 | |
| 5845 | 5852 | return alloca_inst; |
| ... | ... | @@ -5871,8 +5878,14 @@ pub const FuncGen = struct { |
| 5871 | 5878 | }; |
| 5872 | 5879 | const elem_ptr = self.builder.buildInBoundsGEP(alloca_inst, &indices, indices.len, ""); |
| 5873 | 5880 | const llvm_elem = try self.resolveInst(elem); |
| 5874 | const store_inst = self.builder.buildStore(llvm_elem, elem_ptr); | |
| 5875 | store_inst.setAlignment(elem_ty.abiAlignment(target)); | |
| 5881 | var elem_ptr_payload: Type.Payload.Pointer = .{ | |
| 5882 | .data = .{ | |
| 5883 | .pointee_type = elem_ty, | |
| 5884 | .@"addrspace" = .generic, | |
| 5885 | }, | |
| 5886 | }; | |
| 5887 | const elem_ptr_ty = Type.initPayload(&elem_ptr_payload.base); | |
| 5888 | self.store(elem_ptr, elem_ptr_ty, llvm_elem, .NotAtomic); | |
| 5876 | 5889 | } |
| 5877 | 5890 | |
| 5878 | 5891 | return alloca_inst; |
test/behavior/align.zig+4-6| ... | ... | @@ -193,11 +193,9 @@ test "function alignment" { |
| 193 | 193 | } |
| 194 | 194 | |
| 195 | 195 | test "implicitly decreasing fn alignment" { |
| 196 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 197 | 196 | if (builtin.zig_backend == .stage1) return error.SkipZigTest; |
| 198 | if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; | |
| 199 | 197 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; |
| 200 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | |
| 198 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 201 | 199 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 202 | 200 | |
| 203 | 201 | // function alignment is a compile error on wasm32/wasm64 |
| ... | ... | @@ -321,7 +319,6 @@ const DefaultAligned = struct { |
| 321 | 319 | |
| 322 | 320 | test "read 128-bit field from default aligned struct in stack memory" { |
| 323 | 321 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 324 | if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; | |
| 325 | 322 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; |
| 326 | 323 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; |
| 327 | 324 | 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" { |
| 353 | 350 | |
| 354 | 351 | test "struct field explicit alignment" { |
| 355 | 352 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 356 | if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; | |
| 357 | 353 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; |
| 358 | 354 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; |
| 359 | 355 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 356 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 360 | 357 | |
| 361 | 358 | const S = struct { |
| 362 | 359 | const Node = struct { |
| ... | ... | @@ -402,8 +399,9 @@ test "align(@alignOf(T)) T does not force resolution of T" { |
| 402 | 399 | } |
| 403 | 400 | |
| 404 | 401 | test "align(N) on functions" { |
| 405 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 406 | 402 | if (builtin.zig_backend == .stage1) return error.SkipZigTest; |
| 403 | ||
| 404 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 407 | 405 | if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; |
| 408 | 406 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; |
| 409 | 407 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; |
test/behavior/array.zig+2-3| ... | ... | @@ -553,12 +553,11 @@ test "type coercion of anon struct literal to array" { |
| 553 | 553 | } |
| 554 | 554 | |
| 555 | 555 | test "type coercion of pointer to anon struct literal to pointer to array" { |
| 556 | if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; // TODO | |
| 557 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | |
| 558 | 556 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO |
| 559 | 557 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO |
| 560 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | |
| 558 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | |
| 561 | 559 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 560 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | |
| 562 | 561 | |
| 563 | 562 | const S = struct { |
| 564 | 563 | const U = union { |
test/behavior/basic.zig+2-1| ... | ... | @@ -760,7 +760,8 @@ test "pointer to thread local array" { |
| 760 | 760 | threadlocal var buffer: [11]u8 = undefined; |
| 761 | 761 | |
| 762 | 762 | test "auto created variables have correct alignment" { |
| 763 | if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO | |
| 763 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | |
| 764 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | |
| 764 | 765 | |
| 765 | 766 | const S = struct { |
| 766 | 767 | fn foo(str: [*]const u8) u32 { |
test/behavior/slice.zig+6-4| ... | ... | @@ -518,7 +518,11 @@ test "slice syntax resulting in pointer-to-array" { |
| 518 | 518 | } |
| 519 | 519 | |
| 520 | 520 | test "type coercion of pointer to anon struct literal to pointer to slice" { |
| 521 | if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO | |
| 521 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO | |
| 522 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | |
| 523 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | |
| 524 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | |
| 525 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | |
| 522 | 526 | |
| 523 | 527 | const S = struct { |
| 524 | 528 | const U = union { |
| ... | ... | @@ -546,7 +550,7 @@ test "type coercion of pointer to anon struct literal to pointer to slice" { |
| 546 | 550 | try expect(mem.eql(u8, slice2[2], "world!")); |
| 547 | 551 | } |
| 548 | 552 | }; |
| 549 | // try S.doTheTest(); | |
| 553 | try S.doTheTest(); | |
| 550 | 554 | comptime try S.doTheTest(); |
| 551 | 555 | } |
| 552 | 556 | |
| ... | ... | @@ -578,8 +582,6 @@ test "slice bounds in comptime concatenation" { |
| 578 | 582 | } |
| 579 | 583 | |
| 580 | 584 | test "slice sentinel access at comptime" { |
| 581 | if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO | |
| 582 | ||
| 583 | 585 | { |
| 584 | 586 | const str0 = &[_:0]u8{ '1', '2', '3' }; |
| 585 | 587 | const slice0: [:0]const u8 = str0; |
test/behavior/struct.zig+1-1| ... | ... | @@ -426,7 +426,7 @@ test "packed struct 24bits" { |
| 426 | 426 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO |
| 427 | 427 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 428 | 428 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO |
| 429 | if (builtin.zig_backend == .stage2_llvm and builtin.stage2_arch == .wasm32) return error.SkipZigTest; // TODO | |
| 429 | if (builtin.cpu.arch == .wasm32) return error.SkipZigTest; // TODO | |
| 430 | 430 | |
| 431 | 431 | comptime { |
| 432 | 432 | try expect(@sizeOf(Foo24Bits) == 4); |
test/behavior/while.zig+4-4| ... | ... | @@ -289,9 +289,8 @@ test "while bool 2 break statements and an else" { |
| 289 | 289 | } |
| 290 | 290 | |
| 291 | 291 | test "while optional 2 break statements and an else" { |
| 292 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | |
| 293 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; | |
| 294 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 292 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | |
| 293 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | |
| 295 | 294 | |
| 296 | 295 | const S = struct { |
| 297 | 296 | fn entry(opt_t: ?bool, f: bool) !void { |
| ... | ... | @@ -308,7 +307,8 @@ test "while optional 2 break statements and an else" { |
| 308 | 307 | } |
| 309 | 308 | |
| 310 | 309 | test "while error 2 break statements and an else" { |
| 311 | if (@import("builtin").zig_backend != .stage1) return error.SkipZigTest; // TODO | |
| 310 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | |
| 311 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | |
| 312 | 312 | |
| 313 | 313 | const S = struct { |
| 314 | 314 | fn entry(opt_t: anyerror!bool, f: bool) !void { |