| author | |
| committer | |
| log | 220708e7c3f437958fbf8376975b70542b9ac199 |
| tree | 46aba172a40fc29fc9d376bbc316855cc2438ead |
| parent | 446324a1d82514157f5a11a6ca775711bc48c419 |
in addition to tuples3 files changed, 61 insertions(+), 13 deletions(-)
src/Sema.zig+2-2| ... | ... | @@ -394,11 +394,11 @@ pub const Block = struct { |
| 394 | 394 | |
| 395 | 395 | fn addAggregateInit( |
| 396 | 396 | block: *Block, |
| 397 | vector_ty: Type, | |
| 397 | aggregate_ty: Type, | |
| 398 | 398 | elements: []const Air.Inst.Ref, |
| 399 | 399 | ) !Air.Inst.Ref { |
| 400 | 400 | const sema = block.sema; |
| 401 | const ty_ref = try sema.addType(vector_ty); | |
| 401 | const ty_ref = try sema.addType(aggregate_ty); | |
| 402 | 402 | try sema.air_extra.ensureUnusedCapacity(sema.gpa, elements.len); |
| 403 | 403 | const extra_index = @intCast(u32, sema.air_extra.items.len); |
| 404 | 404 | sema.appendRefsAssumeCapacity(elements); |
src/codegen/llvm.zig+10-11| ... | ... | @@ -2106,7 +2106,7 @@ pub const DeclGen = struct { |
| 2106 | 2106 | fn llvmFieldIndex( |
| 2107 | 2107 | dg: *DeclGen, |
| 2108 | 2108 | ty: Type, |
| 2109 | field_index: u32, | |
| 2109 | field_index: usize, | |
| 2110 | 2110 | ptr_pl_buf: *Type.Payload.Pointer, |
| 2111 | 2111 | ) ?c_uint { |
| 2112 | 2112 | const target = dg.module.getTarget(); |
| ... | ... | @@ -4921,38 +4921,37 @@ pub const FuncGen = struct { |
| 4921 | 4921 | return vector; |
| 4922 | 4922 | }, |
| 4923 | 4923 | .Struct => { |
| 4924 | const tuple = result_ty.castTag(.tuple).?.data; | |
| 4924 | var ptr_ty_buf: Type.Payload.Pointer = undefined; | |
| 4925 | 4925 | |
| 4926 | 4926 | if (isByRef(result_ty)) { |
| 4927 | 4927 | const llvm_u32 = self.context.intType(32); |
| 4928 | 4928 | const alloca_inst = self.buildAlloca(llvm_result_ty); |
| 4929 | // TODO in debug builds init to undef so that the padding will be 0xaa | |
| 4930 | // even if we fully populate the fields. | |
| 4929 | 4931 | const target = self.dg.module.getTarget(); |
| 4930 | 4932 | alloca_inst.setAlignment(result_ty.abiAlignment(target)); |
| 4931 | 4933 | |
| 4932 | 4934 | var indices: [2]*const llvm.Value = .{ llvm_u32.constNull(), undefined }; |
| 4933 | var llvm_i: u32 = 0; | |
| 4934 | ||
| 4935 | 4935 | for (elements) |elem, i| { |
| 4936 | if (tuple.values[i].tag() != .unreachable_value) continue; | |
| 4937 | const field_ty = tuple.types[i]; | |
| 4936 | if (result_ty.structFieldValueComptime(i) != null) continue; | |
| 4937 | ||
| 4938 | 4938 | const llvm_elem = try self.resolveInst(elem); |
| 4939 | const llvm_i = self.dg.llvmFieldIndex(result_ty, i, &ptr_ty_buf).?; | |
| 4939 | 4940 | indices[1] = llvm_u32.constInt(llvm_i, .False); |
| 4940 | llvm_i += 1; | |
| 4941 | 4941 | const field_ptr = self.builder.buildInBoundsGEP(alloca_inst, &indices, indices.len, ""); |
| 4942 | 4942 | const store_inst = self.builder.buildStore(llvm_elem, field_ptr); |
| 4943 | store_inst.setAlignment(field_ty.abiAlignment(target)); | |
| 4943 | store_inst.setAlignment(result_ty.structFieldAlign(i, target)); | |
| 4944 | 4944 | } |
| 4945 | 4945 | |
| 4946 | 4946 | return alloca_inst; |
| 4947 | 4947 | } else { |
| 4948 | 4948 | var result = llvm_result_ty.getUndef(); |
| 4949 | var llvm_i: u32 = 0; | |
| 4950 | 4949 | for (elements) |elem, i| { |
| 4951 | if (tuple.values[i].tag() != .unreachable_value) continue; | |
| 4950 | if (result_ty.structFieldValueComptime(i) != null) continue; | |
| 4952 | 4951 | |
| 4953 | 4952 | const llvm_elem = try self.resolveInst(elem); |
| 4953 | const llvm_i = self.dg.llvmFieldIndex(result_ty, i, &ptr_ty_buf).?; | |
| 4954 | 4954 | result = self.builder.buildInsertValue(result, llvm_elem, llvm_i, ""); |
| 4955 | llvm_i += 1; | |
| 4956 | 4955 | } |
| 4957 | 4956 | return result; |
| 4958 | 4957 | } |
src/type.zig+49| ... | ... | @@ -4479,6 +4479,55 @@ pub const Type = extern union { |
| 4479 | 4479 | } |
| 4480 | 4480 | } |
| 4481 | 4481 | |
| 4482 | pub fn structFieldAlign(ty: Type, index: usize, target: Target) u32 { | |
| 4483 | switch (ty.tag()) { | |
| 4484 | .@"struct" => { | |
| 4485 | const struct_obj = ty.castTag(.@"struct").?.data; | |
| 4486 | assert(struct_obj.layout != .Packed); | |
| 4487 | return struct_obj.fields.values()[index].normalAlignment(target); | |
| 4488 | }, | |
| 4489 | .@"union", .union_tagged => { | |
| 4490 | const union_obj = ty.cast(Payload.Union).?.data; | |
| 4491 | return union_obj.fields.values()[index].normalAlignment(target); | |
| 4492 | }, | |
| 4493 | .tuple => return ty.castTag(.tuple).?.data.types[index].abiAlignment(target), | |
| 4494 | .anon_struct => return ty.castTag(.anon_struct).?.data.types[index].abiAlignment(target), | |
| 4495 | else => unreachable, | |
| 4496 | } | |
| 4497 | } | |
| 4498 | ||
| 4499 | pub fn structFieldValueComptime(ty: Type, index: usize) ?Value { | |
| 4500 | switch (ty.tag()) { | |
| 4501 | .@"struct" => { | |
| 4502 | const struct_obj = ty.castTag(.@"struct").?.data; | |
| 4503 | assert(struct_obj.layout != .Packed); | |
| 4504 | const field = struct_obj.fields.values()[index]; | |
| 4505 | if (field.is_comptime) { | |
| 4506 | return field.default_val; | |
| 4507 | } else { | |
| 4508 | return null; | |
| 4509 | } | |
| 4510 | }, | |
| 4511 | .tuple => { | |
| 4512 | const val = ty.castTag(.tuple).?.data.values[index]; | |
| 4513 | if (val.tag() == .unreachable_value) { | |
| 4514 | return null; | |
| 4515 | } else { | |
| 4516 | return val; | |
| 4517 | } | |
| 4518 | }, | |
| 4519 | .anon_struct => { | |
| 4520 | const val = ty.castTag(.anon_struct).?.data.values[index]; | |
| 4521 | if (val.tag() == .unreachable_value) { | |
| 4522 | return null; | |
| 4523 | } else { | |
| 4524 | return val; | |
| 4525 | } | |
| 4526 | }, | |
| 4527 | else => unreachable, | |
| 4528 | } | |
| 4529 | } | |
| 4530 | ||
| 4482 | 4531 | pub const FieldOffset = struct { |
| 4483 | 4532 | field: usize, |
| 4484 | 4533 | offset: u64, |