| ... | ... | @@ -410,6 +410,44 @@ pub const DeclGen = struct { |
| 410 | 410 | .value = value, |
| 411 | 411 | }); |
| 412 | 412 | }, |
| 413 | .Array => switch (val.tag()) { |
| 414 | .aggregate => { // todo: combine with Vector |
| 415 | const elem_vals = val.castTag(.aggregate).?.data; |
| 416 | const elem_ty = ty.elemType(); |
| 417 | const len = @intCast(u32, ty.arrayLenIncludingSentinel()); // TODO: limit spir-v to 32 bit arrays in a more elegant way. |
| 418 | const constituents = try self.spv.gpa.alloc(IdRef, len); |
| 419 | defer self.spv.gpa.free(constituents); |
| 420 | for (elem_vals[0..len]) |elem_val, i| { |
| 421 | constituents[i] = try self.genConstant(elem_ty, elem_val); |
| 422 | } |
| 423 | try section.emit(self.spv.gpa, .OpConstantComposite, .{ |
| 424 | .id_result_type = result_type_id, |
| 425 | .id_result = result_id, |
| 426 | .constituents = constituents, |
| 427 | }); |
| 428 | }, |
| 429 | .repeated => { |
| 430 | const elem_val = val.castTag(.repeated).?.data; |
| 431 | const elem_ty = ty.elemType(); |
| 432 | const len = @intCast(u32, ty.arrayLenIncludingSentinel()); // TODO: limit spir-v to 32 bit arrays in a more elegant way. |
| 433 | const constituents = try self.spv.gpa.alloc(IdRef, len); |
| 434 | defer self.spv.gpa.free(constituents); |
| 435 | |
| 436 | const elem_val_id = try self.genConstant(elem_ty, elem_val); |
| 437 | for (constituents[0..len]) |*elem| { |
| 438 | elem.* = elem_val_id; |
| 439 | } |
| 440 | if (ty.sentinel()) |sentinel| { |
| 441 | constituents[len] = try self.genConstant(elem_ty, sentinel); |
| 442 | } |
| 443 | try section.emit(self.spv.gpa, .OpConstantComposite, .{ |
| 444 | .id_result_type = result_type_id, |
| 445 | .id_result = result_id, |
| 446 | .constituents = constituents, |
| 447 | }); |
| 448 | }, |
| 449 | else => return self.todo("array constant with tag {s}", .{@tagName(val.tag())}), |
| 450 | }, |
| 413 | 451 | .Vector => switch (val.tag()) { |
| 414 | 452 | .aggregate => { |
| 415 | 453 | const elem_vals = val.castTag(.aggregate).?.data; |
| ... | ... | @@ -427,20 +465,20 @@ pub const DeclGen = struct { |
| 427 | 465 | .constituents = elem_refs, |
| 428 | 466 | }); |
| 429 | 467 | }, |
| 430 | | else => unreachable, // TODO |
| 468 | else => return self.todo("vector constant with tag {s}", .{@tagName(val.tag())}), |
| 431 | 469 | }, |
| 432 | 470 | .Enum => { |
| 433 | | var int_buffer: Value.Payload.U64 = undefined; |
| 434 | | const int_val = val.enumToInt(ty, &int_buffer).toUnsignedInt(target); |
| 435 | | |
| 436 | | var buffer: Type.Payload.Bits = undefined; |
| 437 | | const int_ty = ty.intTagType(&buffer); |
| 471 | var ty_buffer: Type.Payload.Bits = undefined; |
| 472 | const int_ty = ty.intTagType(&ty_buffer); |
| 438 | 473 | const int_info = int_ty.intInfo(target); |
| 439 | 474 | |
| 440 | 475 | const backing_bits = self.backingIntBits(int_info.bits) orelse { |
| 441 | 476 | return self.todo("implement composite int constants for {}", .{int_ty.fmtDebug()}); |
| 442 | 477 | }; |
| 443 | 478 | |
| 479 | var int_buffer: Value.Payload.U64 = undefined; |
| 480 | const int_val = val.enumToInt(ty, &int_buffer).toUnsignedInt(target); // TODO: composite integer constants |
| 481 | |
| 444 | 482 | const value: spec.LiteralContextDependentNumber = switch (backing_bits) { |
| 445 | 483 | 1...32 => .{ .uint32 = @truncate(u32, int_val) }, |
| 446 | 484 | 33...64 => .{ .uint64 = int_val }, |
| ... | ... | @@ -453,6 +491,48 @@ pub const DeclGen = struct { |
| 453 | 491 | .value = value, |
| 454 | 492 | }); |
| 455 | 493 | }, |
| 494 | .Struct => { |
| 495 | const constituents = if (ty.isSimpleTupleOrAnonStruct()) blk: { |
| 496 | const tuple = ty.tupleFields(); |
| 497 | const constituents = try self.spv.gpa.alloc(IdRef, tuple.types.len); |
| 498 | errdefer self.spv.gpa.free(constituents); |
| 499 | |
| 500 | var member_index: usize = 0; |
| 501 | for (tuple.types) |field_ty, i| { |
| 502 | const field_val = tuple.values[i]; |
| 503 | if (field_val.tag() != .unreachable_value or !field_ty.hasRuntimeBits()) continue; |
| 504 | constituents[member_index] = try self.genConstant(field_ty, field_val); |
| 505 | member_index += 1; |
| 506 | } |
| 507 | |
| 508 | break :blk constituents[0..member_index]; |
| 509 | } else blk: { |
| 510 | const struct_ty = ty.castTag(.@"struct").?.data; |
| 511 | |
| 512 | if (struct_ty.layout == .Packed) { |
| 513 | return self.todo("packed struct constants", .{}); |
| 514 | } |
| 515 | |
| 516 | const field_vals = val.castTag(.aggregate).?.data; |
| 517 | const constituents = try self.spv.gpa.alloc(IdRef, struct_ty.fields.count()); |
| 518 | errdefer self.spv.gpa.free(constituents); |
| 519 | var member_index: usize = 0; |
| 520 | for (struct_ty.fields.values()) |field, i| { |
| 521 | if (field.is_comptime or !field.ty.hasRuntimeBits()) continue; |
| 522 | constituents[member_index] = try self.genConstant(field.ty, field_vals[i]); |
| 523 | member_index += 1; |
| 524 | } |
| 525 | |
| 526 | break :blk constituents[0..member_index]; |
| 527 | }; |
| 528 | defer self.spv.gpa.free(constituents); |
| 529 | |
| 530 | try section.emit(self.spv.gpa, .OpConstantComposite, .{ |
| 531 | .id_result_type = result_type_id, |
| 532 | .id_result = result_id, |
| 533 | .constituents = constituents, |
| 534 | }); |
| 535 | }, |
| 456 | 536 | .Void => unreachable, |
| 457 | 537 | .Fn => unreachable, |
| 458 | 538 | else => return self.todo("constant generation of type {s}: {}", .{ @tagName(ty.zigTypeTag()), ty.fmtDebug() }), |
| ... | ... | @@ -539,9 +619,8 @@ pub const DeclGen = struct { |
| 539 | 619 | }, |
| 540 | 620 | .Array => { |
| 541 | 621 | const elem_ty = ty.childType(); |
| 542 | | const total_len_u64 = ty.arrayLen() + @boolToInt(ty.sentinel() != null); |
| 543 | | const total_len = std.math.cast(u32, total_len_u64) orelse { |
| 544 | | return self.fail("array type of {} elements is too large", .{total_len_u64}); |
| 622 | const total_len = std.math.cast(u32, ty.arrayLenIncludingSentinel()) orelse { |
| 623 | return self.fail("array type of {} elements is too large", .{ty.arrayLenIncludingSentinel()}); |
| 545 | 624 | }; |
| 546 | 625 | |
| 547 | 626 | const payload = try self.spv.arena.create(SpvType.Payload.Array); |
| ... | ... | @@ -630,6 +709,7 @@ pub const DeclGen = struct { |
| 630 | 709 | .ty = try self.resolveType(field_ty), |
| 631 | 710 | .offset = 0, |
| 632 | 711 | }; |
| 712 | member_index += 1; |
| 633 | 713 | } |
| 634 | 714 | |
| 635 | 715 | const payload = try self.spv.arena.create(SpvType.Payload.Struct); |