authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-12-30 19:57:11-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-12-30 21:41:02-08:00
log133da8692e80532797dd91b32539cf2175280a95
tree8ff37b28c783d14be6aa459673202909de47b1ec
parent2622575fde2b5d70926fe62ed272412d72eef7b0

stage2: rework Type Payload layout

Add `Type.castTag` and note that it is preferable to call than `Type.cast`. This matches other abstractions in the codebase. Added a convenience function `Type.Tag.create` which really cleans up the callsites of creating `Type` objects. `Type` payloads can now share types. This is in preparation for another improvement that I want to do.

8 files changed, 424 insertions(+), 395 deletions(-)

src/Compilation.zig+5-3
......@@ -825,9 +825,11 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
825825
826826 const root_scope = rs: {
827827 if (mem.endsWith(u8, root_pkg.root_src_path, ".zig")) {
828 const struct_payload = try gpa.create(Type.Payload.EmptyStruct);
829828 const root_scope = try gpa.create(Module.Scope.File);
830 struct_payload.* = .{ .scope = &root_scope.root_container };
829 const struct_ty = try Type.Tag.empty_struct.create(
830 gpa,
831 &root_scope.root_container,
832 );
831833 root_scope.* = .{
832834 // TODO this is duped so it can be freed in Container.deinit
833835 .sub_file_path = try gpa.dupe(u8, root_pkg.root_src_path),
......@@ -838,7 +840,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
838840 .root_container = .{
839841 .file_scope = root_scope,
840842 .decls = .{},
841 .ty = Type.initPayload(&struct_payload.base),
843 .ty = struct_ty,
842844 },
843845 };
844846 break :rs &root_scope.base;
src/Module.zig+51-76
......@@ -562,7 +562,7 @@ pub const Scope = struct {
562562 pub fn deinit(self: *Container, gpa: *Allocator) void {
563563 self.decls.deinit(gpa);
564564 // TODO either Container of File should have an arena for sub_file_path and ty
565 gpa.destroy(self.ty.cast(Type.Payload.EmptyStruct).?);
565 gpa.destroy(self.ty.castTag(.empty_struct).?);
566566 gpa.free(self.file_scope.sub_file_path);
567567 self.* = undefined;
568568 }
......@@ -2528,12 +2528,11 @@ pub fn analyzeImport(self: *Module, scope: *Scope, src: usize, target_string: []
25282528 }
25292529
25302530 // TODO Scope.Container arena for ty and sub_file_path
2531 const struct_payload = try self.gpa.create(Type.Payload.EmptyStruct);
2532 errdefer self.gpa.destroy(struct_payload);
25332531 const file_scope = try self.gpa.create(Scope.File);
25342532 errdefer self.gpa.destroy(file_scope);
2533 const struct_ty = try Type.Tag.empty_struct.create(self.gpa, &file_scope.root_container);
2534 errdefer self.gpa.destroy(struct_ty.castTag(.empty_struct).?);
25352535
2536 struct_payload.* = .{ .scope = &file_scope.root_container };
25372536 file_scope.* = .{
25382537 .sub_file_path = resolved_path,
25392538 .source = .{ .unloaded = {} },
......@@ -2543,7 +2542,7 @@ pub fn analyzeImport(self: *Module, scope: *Scope, src: usize, target_string: []
25432542 .root_container = .{
25442543 .file_scope = file_scope,
25452544 .decls = .{},
2546 .ty = Type.initPayload(&struct_payload.base),
2545 .ty = struct_ty,
25472546 },
25482547 };
25492548 self.analyzeContainer(&file_scope.root_container) catch |err| switch (err) {
......@@ -2564,7 +2563,7 @@ pub fn cmpNumeric(
25642563 lhs: *Inst,
25652564 rhs: *Inst,
25662565 op: std.math.CompareOperator,
2567) !*Inst {
2566) InnerError!*Inst {
25682567 assert(lhs.ty.isNumeric());
25692568 assert(rhs.ty.isNumeric());
25702569
......@@ -2738,15 +2737,14 @@ fn wrapOptional(self: *Module, scope: *Scope, dest_type: Type, inst: *Inst) !*In
27382737}
27392738
27402739fn makeIntType(self: *Module, scope: *Scope, signed: bool, bits: u16) !Type {
2741 if (signed) {
2742 const int_payload = try scope.arena().create(Type.Payload.IntSigned);
2743 int_payload.* = .{ .bits = bits };
2744 return Type.initPayload(&int_payload.base);
2745 } else {
2746 const int_payload = try scope.arena().create(Type.Payload.IntUnsigned);
2747 int_payload.* = .{ .bits = bits };
2748 return Type.initPayload(&int_payload.base);
2749 }
2740 const int_payload = try scope.arena().create(Type.Payload.Bits);
2741 int_payload.* = .{
2742 .base = .{
2743 .tag = if (signed) .int_signed else .int_unsigned,
2744 },
2745 .data = bits,
2746 };
2747 return Type.initPayload(&int_payload.base);
27502748}
27512749
27522750pub fn resolvePeerTypes(self: *Module, scope: *Scope, instructions: []*Inst) !Type {
......@@ -2829,7 +2827,7 @@ pub fn coerce(self: *Module, scope: *Scope, dest_type: Type, inst: *Inst) !*Inst
28292827
28302828 // T to ?T
28312829 if (dest_type.zigTypeTag() == .Optional) {
2832 var buf: Type.Payload.PointerSimple = undefined;
2830 var buf: Type.Payload.ElemType = undefined;
28332831 const child_type = dest_type.optionalChild(&buf);
28342832 if (child_type.eql(inst.ty)) {
28352833 return self.wrapOptional(scope, dest_type, inst);
......@@ -3225,7 +3223,7 @@ pub fn simplePtrType(self: *Module, scope: *Scope, src: usize, elem_ty: Type, mu
32253223 // TODO stage1 type inference bug
32263224 const T = Type.Tag;
32273225
3228 const type_payload = try scope.arena().create(Type.Payload.PointerSimple);
3226 const type_payload = try scope.arena().create(Type.Payload.ElemType);
32293227 type_payload.* = .{
32303228 .base = .{
32313229 .tag = switch (size) {
......@@ -3235,7 +3233,7 @@ pub fn simplePtrType(self: *Module, scope: *Scope, src: usize, elem_ty: Type, mu
32353233 .Slice => if (mutable) T.mut_slice else T.const_slice,
32363234 },
32373235 },
3238 .pointee_type = elem_ty,
3236 .data = elem_ty,
32393237 };
32403238 return Type.initPayload(&type_payload.base);
32413239}
......@@ -3257,8 +3255,7 @@ pub fn ptrType(
32573255 assert(host_size == 0 or bit_offset < host_size * 8);
32583256
32593257 // TODO check if type can be represented by simplePtrType
3260 const type_payload = try scope.arena().create(Type.Payload.Pointer);
3261 type_payload.* = .{
3258 return Type.Tag.pointer.create(scope.arena(), .{
32623259 .pointee_type = elem_ty,
32633260 .sentinel = sentinel,
32643261 .@"align" = @"align",
......@@ -3268,95 +3265,73 @@ pub fn ptrType(
32683265 .mutable = mutable,
32693266 .@"volatile" = @"volatile",
32703267 .size = size,
3271 };
3272 return Type.initPayload(&type_payload.base);
3268 });
32733269}
32743270
32753271pub fn optionalType(self: *Module, scope: *Scope, child_type: Type) Allocator.Error!Type {
3276 return Type.initPayload(switch (child_type.tag()) {
3277 .single_const_pointer => blk: {
3278 const payload = try scope.arena().create(Type.Payload.PointerSimple);
3279 payload.* = .{
3280 .base = .{ .tag = .optional_single_const_pointer },
3281 .pointee_type = child_type.elemType(),
3282 };
3283 break :blk &payload.base;
3284 },
3285 .single_mut_pointer => blk: {
3286 const payload = try scope.arena().create(Type.Payload.PointerSimple);
3287 payload.* = .{
3288 .base = .{ .tag = .optional_single_mut_pointer },
3289 .pointee_type = child_type.elemType(),
3290 };
3291 break :blk &payload.base;
3292 },
3293 else => blk: {
3294 const payload = try scope.arena().create(Type.Payload.Optional);
3295 payload.* = .{
3296 .child_type = child_type,
3297 };
3298 break :blk &payload.base;
3299 },
3300 });
3272 switch (child_type.tag()) {
3273 .single_const_pointer => return Type.Tag.optional_single_const_pointer.create(
3274 scope.arena(),
3275 child_type.elemType(),
3276 ),
3277 .single_mut_pointer => return Type.Tag.optional_single_mut_pointer.create(
3278 scope.arena(),
3279 child_type.elemType(),
3280 ),
3281 else => return Type.Tag.optional.create(scope.arena(), child_type),
3282 }
33013283}
33023284
3303pub fn arrayType(self: *Module, scope: *Scope, len: u64, sentinel: ?Value, elem_type: Type) Allocator.Error!Type {
3285pub fn arrayType(
3286 self: *Module,
3287 scope: *Scope,
3288 len: u64,
3289 sentinel: ?Value,
3290 elem_type: Type,
3291) Allocator.Error!Type {
33043292 if (elem_type.eql(Type.initTag(.u8))) {
33053293 if (sentinel) |some| {
33063294 if (some.eql(Value.initTag(.zero))) {
3307 const payload = try scope.arena().create(Type.Payload.Array_u8_Sentinel0);
3308 payload.* = .{
3309 .len = len,
3310 };
3311 return Type.initPayload(&payload.base);
3295 return Type.Tag.array_u8_sentinel_0.create(scope.arena(), len);
33123296 }
33133297 } else {
3314 const payload = try scope.arena().create(Type.Payload.Array_u8);
3315 payload.* = .{
3316 .len = len,
3317 };
3318 return Type.initPayload(&payload.base);
3298 return Type.Tag.array_u8.create(scope.arena(), len);
33193299 }
33203300 }
33213301
33223302 if (sentinel) |some| {
3323 const payload = try scope.arena().create(Type.Payload.ArraySentinel);
3324 payload.* = .{
3303 return Type.Tag.array_sentinel.create(scope.arena(), .{
33253304 .len = len,
33263305 .sentinel = some,
33273306 .elem_type = elem_type,
3328 };
3329 return Type.initPayload(&payload.base);
3307 });
33303308 }
33313309
3332 const payload = try scope.arena().create(Type.Payload.Array);
3333 payload.* = .{
3310 return Type.Tag.array.create(scope.arena(), .{
33343311 .len = len,
33353312 .elem_type = elem_type,
3336 };
3337 return Type.initPayload(&payload.base);
3313 });
33383314}
33393315
3340pub fn errorUnionType(self: *Module, scope: *Scope, error_set: Type, payload: Type) Allocator.Error!Type {
3316pub fn errorUnionType(
3317 self: *Module,
3318 scope: *Scope,
3319 error_set: Type,
3320 payload: Type,
3321) Allocator.Error!Type {
33413322 assert(error_set.zigTypeTag() == .ErrorSet);
33423323 if (error_set.eql(Type.initTag(.anyerror)) and payload.eql(Type.initTag(.void))) {
33433324 return Type.initTag(.anyerror_void_error_union);
33443325 }
33453326
3346 const result = try scope.arena().create(Type.Payload.ErrorUnion);
3347 result.* = .{
3327 return Type.Tag.error_union.create(scope.arena(), .{
33483328 .error_set = error_set,
33493329 .payload = payload,
3350 };
3351 return Type.initPayload(&result.base);
3330 });
33523331}
33533332
33543333pub fn anyframeType(self: *Module, scope: *Scope, return_type: Type) Allocator.Error!Type {
3355 const result = try scope.arena().create(Type.Payload.AnyFrame);
3356 result.* = .{
3357 .return_type = return_type,
3358 };
3359 return Type.initPayload(&result.base);
3334 return Type.Tag.anyframe_T.create(scope.arena(), return_type);
33603335}
33613336
33623337pub fn dumpInst(self: *Module, scope: *Scope, inst: *Inst) void {
src/astgen.zig+1-1
......@@ -2723,7 +2723,7 @@ fn rlWrap(mod: *Module, scope: *Scope, rl: ResultLoc, result: *zir.Inst) InnerEr
27232723 return mod.fail(scope, result.src, "TODO implement rlWrap .bitcasted_ptr", .{});
27242724 },
27252725 .inferred_ptr => |alloc| {
2726 return mod.fail(scope, result.src, "TODO implement rlWrap .inferred_ptr", .{});
2726 return addZIRBinOp(mod, scope, result.src, .store, &alloc.base, result);
27272727 },
27282728 .block_ptr => |block_ptr| {
27292729 return mod.fail(scope, result.src, "TODO implement rlWrap .block_ptr", .{});
src/codegen.zig+1-1
......@@ -3262,7 +3262,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
32623262 if (typed_value.val.isNull())
32633263 return MCValue{ .immediate = 0 };
32643264
3265 var buf: Type.Payload.PointerSimple = undefined;
3265 var buf: Type.Payload.ElemType = undefined;
32663266 return self.genTypedValue(src, .{
32673267 .ty = typed_value.ty.optionalChild(&buf),
32683268 .val = typed_value.val,
src/type.zig+339-274
......@@ -112,18 +112,39 @@ pub const Type = extern union {
112112 }
113113 }
114114
115 /// Prefer `castTag` to this.
115116 pub fn cast(self: Type, comptime T: type) ?*T {
116 if (self.tag_if_small_enough < Tag.no_payload_count)
117 if (@hasField(T, "base_tag")) {
118 return base.castTag(T.base_tag);
119 }
120 if (self.tag_if_small_enough < Tag.no_payload_count) {
117121 return null;
122 }
123 inline for (@typeInfo(Tag).Enum.fields) |field| {
124 if (field.value < Tag.no_payload_count)
125 continue;
126 const t = @intToEnum(Tag, field.value);
127 if (self.ptr_otherwise.tag == t) {
128 if (T == t.Type()) {
129 return @fieldParentPtr(T, "base", self.ptr_otherwise);
130 }
131 return null;
132 }
133 }
134 unreachable;
135 }
118136
119 const expected_tag = std.meta.fieldInfo(T, "base").default_value.?.tag;
120 if (self.ptr_otherwise.tag != expected_tag)
137 pub fn castTag(self: Type, comptime t: Tag) ?*t.Type() {
138 if (self.tag_if_small_enough < Tag.no_payload_count)
121139 return null;
122140
123 return @fieldParentPtr(T, "base", self.ptr_otherwise);
141 if (self.ptr_otherwise.tag == t)
142 return @fieldParentPtr(t.Type(), "base", self.ptr_otherwise);
143
144 return null;
124145 }
125146
126 pub fn castPointer(self: Type) ?*Payload.PointerSimple {
147 pub fn castPointer(self: Type) ?*Payload.ElemType {
127148 return switch (self.tag()) {
128149 .single_const_pointer,
129150 .single_mut_pointer,
......@@ -135,7 +156,8 @@ pub const Type = extern union {
135156 .mut_slice,
136157 .optional_single_const_pointer,
137158 .optional_single_mut_pointer,
138 => @fieldParentPtr(Payload.PointerSimple, "base", self.ptr_otherwise),
159 => self.cast(Payload.ElemType),
160
139161 else => null,
140162 };
141163 }
......@@ -165,7 +187,7 @@ pub const Type = extern union {
165187 // Hot path for common case:
166188 if (a.castPointer()) |a_payload| {
167189 if (b.castPointer()) |b_payload| {
168 return a.tag() == b.tag() and eql(a_payload.pointee_type, b_payload.pointee_type);
190 return a.tag() == b.tag() and eql(a_payload.data, b_payload.data);
169191 }
170192 }
171193 const is_slice_a = isSlice(a);
......@@ -230,8 +252,8 @@ pub const Type = extern union {
230252 return true;
231253 },
232254 .Optional => {
233 var buf_a: Payload.PointerSimple = undefined;
234 var buf_b: Payload.PointerSimple = undefined;
255 var buf_a: Payload.ElemType = undefined;
256 var buf_b: Payload.ElemType = undefined;
235257 return a.optionalChild(&buf_a).eql(b.optionalChild(&buf_b));
236258 },
237259 .Float,
......@@ -294,7 +316,7 @@ pub const Type = extern union {
294316 }
295317 },
296318 .Optional => {
297 var buf: Payload.PointerSimple = undefined;
319 var buf: Payload.ElemType = undefined;
298320 std.hash.autoHash(&hasher, self.optionalChild(&buf).hash());
299321 },
300322 .Float,
......@@ -364,68 +386,64 @@ pub const Type = extern union {
364386 .@"anyframe",
365387 => unreachable,
366388
367 .array_u8_sentinel_0 => return self.copyPayloadShallow(allocator, Payload.Array_u8_Sentinel0),
368 .array_u8 => return self.copyPayloadShallow(allocator, Payload.Array_u8),
389 .array_u8,
390 .array_u8_sentinel_0,
391 => return self.copyPayloadShallow(allocator, Payload.Len),
392
393 .single_const_pointer,
394 .single_mut_pointer,
395 .many_const_pointer,
396 .many_mut_pointer,
397 .c_const_pointer,
398 .c_mut_pointer,
399 .const_slice,
400 .mut_slice,
401 .optional,
402 .optional_single_mut_pointer,
403 .optional_single_const_pointer,
404 .anyframe_T,
405 => return self.copyPayloadShallow(allocator, Payload.ElemType),
406
407 .int_signed,
408 .int_unsigned,
409 => return self.copyPayloadShallow(allocator, Payload.Bits),
410
369411 .array => {
370 const payload = @fieldParentPtr(Payload.Array, "base", self.ptr_otherwise);
371 const new_payload = try allocator.create(Payload.Array);
372 new_payload.* = .{
373 .base = payload.base,
412 const payload = self.castTag(.array).?.data;
413 return Tag.array.create(allocator, .{
374414 .len = payload.len,
375415 .elem_type = try payload.elem_type.copy(allocator),
376 };
377 return Type{ .ptr_otherwise = &new_payload.base };
416 });
378417 },
379418 .array_sentinel => {
380 const payload = @fieldParentPtr(Payload.ArraySentinel, "base", self.ptr_otherwise);
381 const new_payload = try allocator.create(Payload.ArraySentinel);
382 new_payload.* = .{
383 .base = payload.base,
419 const payload = self.castTag(.array_sentinel).?.data;
420 return Tag.array_sentinel.create(allocator, .{
384421 .len = payload.len,
385422 .sentinel = try payload.sentinel.copy(allocator),
386423 .elem_type = try payload.elem_type.copy(allocator),
387 };
388 return Type{ .ptr_otherwise = &new_payload.base };
424 });
389425 },
390 .int_signed => return self.copyPayloadShallow(allocator, Payload.IntSigned),
391 .int_unsigned => return self.copyPayloadShallow(allocator, Payload.IntUnsigned),
392426 .function => {
393 const payload = @fieldParentPtr(Payload.Function, "base", self.ptr_otherwise);
394 const new_payload = try allocator.create(Payload.Function);
427 const payload = self.castTag(.function).?.data;
395428 const param_types = try allocator.alloc(Type, payload.param_types.len);
396429 for (payload.param_types) |param_type, i| {
397430 param_types[i] = try param_type.copy(allocator);
398431 }
399 new_payload.* = .{
400 .base = payload.base,
432 return Tag.function.create(allocator, .{
401433 .return_type = try payload.return_type.copy(allocator),
402434 .param_types = param_types,
403435 .cc = payload.cc,
404 };
405 return Type{ .ptr_otherwise = &new_payload.base };
436 });
406437 },
407 .optional => return self.copyPayloadSingleField(allocator, Payload.Optional, "child_type"),
408 .single_const_pointer,
409 .single_mut_pointer,
410 .many_const_pointer,
411 .many_mut_pointer,
412 .c_const_pointer,
413 .c_mut_pointer,
414 .const_slice,
415 .mut_slice,
416 .optional_single_mut_pointer,
417 .optional_single_const_pointer,
418 => return self.copyPayloadSingleField(allocator, Payload.PointerSimple, "pointee_type"),
419 .anyframe_T => return self.copyPayloadSingleField(allocator, Payload.AnyFrame, "return_type"),
420
421438 .pointer => {
422 const payload = @fieldParentPtr(Payload.Pointer, "base", self.ptr_otherwise);
423 const new_payload = try allocator.create(Payload.Pointer);
424 new_payload.* = .{
425 .base = payload.base,
426
439 const payload = self.castTag(.pointer).?.data;
440 const sent: ?Value = if (payload.sentinel) |some|
441 try some.copy(allocator)
442 else
443 null;
444 return Tag.pointer.create(allocator, .{
427445 .pointee_type = try payload.pointee_type.copy(allocator),
428 .sentinel = if (payload.sentinel) |some| try some.copy(allocator) else null,
446 .sentinel = sent,
429447 .@"align" = payload.@"align",
430448 .bit_offset = payload.bit_offset,
431449 .host_size = payload.host_size,
......@@ -433,41 +451,28 @@ pub const Type = extern union {
433451 .mutable = payload.mutable,
434452 .@"volatile" = payload.@"volatile",
435453 .size = payload.size,
436 };
437 return Type{ .ptr_otherwise = &new_payload.base };
454 });
438455 },
439456 .error_union => {
440 const payload = @fieldParentPtr(Payload.ErrorUnion, "base", self.ptr_otherwise);
441 const new_payload = try allocator.create(Payload.ErrorUnion);
442 new_payload.* = .{
443 .base = payload.base,
444
457 const payload = self.castTag(.error_union).?.data;
458 return Tag.error_union.create(allocator, .{
445459 .error_set = try payload.error_set.copy(allocator),
446460 .payload = try payload.payload.copy(allocator),
447 };
448 return Type{ .ptr_otherwise = &new_payload.base };
461 });
449462 },
450 .error_set => return self.copyPayloadShallow(allocator, Payload.ErrorSet),
451 .error_set_single => return self.copyPayloadShallow(allocator, Payload.ErrorSetSingle),
452 .empty_struct => return self.copyPayloadShallow(allocator, Payload.EmptyStruct),
463 .error_set => return self.copyPayloadShallow(allocator, Payload.Decl),
464 .error_set_single => return self.copyPayloadShallow(allocator, Payload.Name),
465 .empty_struct => return self.copyPayloadShallow(allocator, Payload.ContainerScope),
453466 }
454467 }
455468
456469 fn copyPayloadShallow(self: Type, allocator: *Allocator, comptime T: type) error{OutOfMemory}!Type {
457 const payload = @fieldParentPtr(T, "base", self.ptr_otherwise);
470 const payload = self.cast(T).?;
458471 const new_payload = try allocator.create(T);
459472 new_payload.* = payload.*;
460473 return Type{ .ptr_otherwise = &new_payload.base };
461474 }
462475
463 fn copyPayloadSingleField(self: Type, allocator: *Allocator, comptime T: type, comptime field_name: []const u8) error{OutOfMemory}!Type {
464 const payload = @fieldParentPtr(T, "base", self.ptr_otherwise);
465 const new_payload = try allocator.create(T);
466 new_payload.base = payload.base;
467 @field(new_payload, field_name) = try @field(payload, field_name).copy(allocator);
468 return Type{ .ptr_otherwise = &new_payload.base };
469 }
470
471476 pub fn format(
472477 self: Type,
473478 comptime fmt: []const u8,
......@@ -527,7 +532,7 @@ pub const Type = extern union {
527532 .fn_ccc_void_no_args => return out_stream.writeAll("fn() callconv(.C) void"),
528533 .single_const_pointer_to_comptime_int => return out_stream.writeAll("*const comptime_int"),
529534 .function => {
530 const payload = @fieldParentPtr(Payload.Function, "base", ty.ptr_otherwise);
535 const payload = ty.castTag(.function).?.data;
531536 try out_stream.writeAll("fn(");
532537 for (payload.param_types) |param_type, i| {
533538 if (i != 0) try out_stream.writeAll(", ");
......@@ -539,108 +544,108 @@ pub const Type = extern union {
539544 },
540545
541546 .anyframe_T => {
542 const payload = @fieldParentPtr(Payload.AnyFrame, "base", ty.ptr_otherwise);
547 const return_type = ty.castTag(.anyframe_T).?.data;
543548 try out_stream.print("anyframe->", .{});
544 ty = payload.return_type;
549 ty = return_type;
545550 continue;
546551 },
547552 .array_u8 => {
548 const payload = @fieldParentPtr(Payload.Array_u8, "base", ty.ptr_otherwise);
549 return out_stream.print("[{}]u8", .{payload.len});
553 const len = ty.castTag(.array_u8).?.data;
554 return out_stream.print("[{}]u8", .{len});
550555 },
551556 .array_u8_sentinel_0 => {
552 const payload = @fieldParentPtr(Payload.Array_u8_Sentinel0, "base", ty.ptr_otherwise);
553 return out_stream.print("[{}:0]u8", .{payload.len});
557 const len = ty.castTag(.array_u8_sentinel_0).?.data;
558 return out_stream.print("[{}:0]u8", .{len});
554559 },
555560 .array => {
556 const payload = @fieldParentPtr(Payload.Array, "base", ty.ptr_otherwise);
561 const payload = ty.castTag(.array).?.data;
557562 try out_stream.print("[{}]", .{payload.len});
558563 ty = payload.elem_type;
559564 continue;
560565 },
561566 .array_sentinel => {
562 const payload = @fieldParentPtr(Payload.ArraySentinel, "base", ty.ptr_otherwise);
567 const payload = ty.castTag(.array_sentinel).?.data;
563568 try out_stream.print("[{}:{}]", .{ payload.len, payload.sentinel });
564569 ty = payload.elem_type;
565570 continue;
566571 },
567572 .single_const_pointer => {
568 const payload = @fieldParentPtr(Payload.PointerSimple, "base", ty.ptr_otherwise);
573 const pointee_type = ty.castTag(.single_const_pointer).?.data;
569574 try out_stream.writeAll("*const ");
570 ty = payload.pointee_type;
575 ty = pointee_type;
571576 continue;
572577 },
573578 .single_mut_pointer => {
574 const payload = @fieldParentPtr(Payload.PointerSimple, "base", ty.ptr_otherwise);
579 const pointee_type = ty.castTag(.single_mut_pointer).?.data;
575580 try out_stream.writeAll("*");
576 ty = payload.pointee_type;
581 ty = pointee_type;
577582 continue;
578583 },
579584 .many_const_pointer => {
580 const payload = @fieldParentPtr(Payload.PointerSimple, "base", ty.ptr_otherwise);
585 const pointee_type = ty.castTag(.many_const_pointer).?.data;
581586 try out_stream.writeAll("[*]const ");
582 ty = payload.pointee_type;
587 ty = pointee_type;
583588 continue;
584589 },
585590 .many_mut_pointer => {
586 const payload = @fieldParentPtr(Payload.PointerSimple, "base", ty.ptr_otherwise);
591 const pointee_type = ty.castTag(.many_mut_pointer).?.data;
587592 try out_stream.writeAll("[*]");
588 ty = payload.pointee_type;
593 ty = pointee_type;
589594 continue;
590595 },
591596 .c_const_pointer => {
592 const payload = @fieldParentPtr(Payload.PointerSimple, "base", ty.ptr_otherwise);
597 const pointee_type = ty.castTag(.c_const_pointer).?.data;
593598 try out_stream.writeAll("[*c]const ");
594 ty = payload.pointee_type;
599 ty = pointee_type;
595600 continue;
596601 },
597602 .c_mut_pointer => {
598 const payload = @fieldParentPtr(Payload.PointerSimple, "base", ty.ptr_otherwise);
603 const pointee_type = ty.castTag(.c_mut_pointer).?.data;
599604 try out_stream.writeAll("[*c]");
600 ty = payload.pointee_type;
605 ty = pointee_type;
601606 continue;
602607 },
603608 .const_slice => {
604 const payload = @fieldParentPtr(Payload.PointerSimple, "base", ty.ptr_otherwise);
609 const pointee_type = ty.castTag(.const_slice).?.data;
605610 try out_stream.writeAll("[]const ");
606 ty = payload.pointee_type;
611 ty = pointee_type;
607612 continue;
608613 },
609614 .mut_slice => {
610 const payload = @fieldParentPtr(Payload.PointerSimple, "base", ty.ptr_otherwise);
615 const pointee_type = ty.castTag(.mut_slice).?.data;
611616 try out_stream.writeAll("[]");
612 ty = payload.pointee_type;
617 ty = pointee_type;
613618 continue;
614619 },
615620 .int_signed => {
616 const payload = @fieldParentPtr(Payload.IntSigned, "base", ty.ptr_otherwise);
617 return out_stream.print("i{}", .{payload.bits});
621 const bits = ty.castTag(.int_signed).?.data;
622 return out_stream.print("i{d}", .{bits});
618623 },
619624 .int_unsigned => {
620 const payload = @fieldParentPtr(Payload.IntUnsigned, "base", ty.ptr_otherwise);
621 return out_stream.print("u{}", .{payload.bits});
625 const bits = ty.castTag(.int_unsigned).?.data;
626 return out_stream.print("u{d}", .{bits});
622627 },
623628 .optional => {
624 const payload = @fieldParentPtr(Payload.Optional, "base", ty.ptr_otherwise);
629 const child_type = ty.castTag(.optional).?.data;
625630 try out_stream.writeByte('?');
626 ty = payload.child_type;
631 ty = child_type;
627632 continue;
628633 },
629634 .optional_single_const_pointer => {
630 const payload = @fieldParentPtr(Payload.PointerSimple, "base", ty.ptr_otherwise);
635 const pointee_type = ty.castTag(.optional_single_const_pointer).?.data;
631636 try out_stream.writeAll("?*const ");
632 ty = payload.pointee_type;
637 ty = pointee_type;
633638 continue;
634639 },
635640 .optional_single_mut_pointer => {
636 const payload = @fieldParentPtr(Payload.PointerSimple, "base", ty.ptr_otherwise);
641 const pointee_type = ty.castTag(.optional_single_mut_pointer).?.data;
637642 try out_stream.writeAll("?*");
638 ty = payload.pointee_type;
643 ty = pointee_type;
639644 continue;
640645 },
641646
642647 .pointer => {
643 const payload = @fieldParentPtr(Payload.Pointer, "base", ty.ptr_otherwise);
648 const payload = ty.castTag(.pointer).?.data;
644649 if (payload.sentinel) |some| switch (payload.size) {
645650 .One, .C => unreachable,
646651 .Many => try out_stream.print("[*:{}]", .{some}),
......@@ -652,10 +657,10 @@ pub const Type = extern union {
652657 .Slice => try out_stream.writeAll("[]"),
653658 }
654659 if (payload.@"align" != 0) {
655 try out_stream.print("align({}", .{payload.@"align"});
660 try out_stream.print("align({d}", .{payload.@"align"});
656661
657662 if (payload.bit_offset != 0) {
658 try out_stream.print(":{}:{}", .{ payload.bit_offset, payload.host_size });
663 try out_stream.print(":{d}:{d}", .{ payload.bit_offset, payload.host_size });
659664 }
660665 try out_stream.writeAll(") ");
661666 }
......@@ -667,19 +672,19 @@ pub const Type = extern union {
667672 continue;
668673 },
669674 .error_union => {
670 const payload = @fieldParentPtr(Payload.ErrorUnion, "base", ty.ptr_otherwise);
675 const payload = ty.castTag(.error_union).?.data;
671676 try payload.error_set.format("", .{}, out_stream);
672677 try out_stream.writeAll("!");
673678 ty = payload.payload;
674679 continue;
675680 },
676681 .error_set => {
677 const payload = @fieldParentPtr(Payload.ErrorSet, "base", ty.ptr_otherwise);
678 return out_stream.writeAll(std.mem.spanZ(payload.decl.name));
682 const decl = ty.castTag(.error_set).?.data;
683 return out_stream.writeAll(std.mem.spanZ(decl.name));
679684 },
680685 .error_set_single => {
681 const payload = @fieldParentPtr(Payload.ErrorSetSingle, "base", ty.ptr_otherwise);
682 return out_stream.print("error{{{}}}", .{payload.name});
686 const name = ty.castTag(.error_set_single).?.data;
687 return out_stream.print("error{{{s}}}", .{name});
683688 },
684689 }
685690 unreachable;
......@@ -784,11 +789,10 @@ pub const Type = extern union {
784789 .array => self.elemType().hasCodeGenBits() and self.arrayLen() != 0,
785790 .array_u8 => self.arrayLen() != 0,
786791 .array_sentinel, .single_const_pointer, .single_mut_pointer, .many_const_pointer, .many_mut_pointer, .c_const_pointer, .c_mut_pointer, .const_slice, .mut_slice, .pointer => self.elemType().hasCodeGenBits(),
787 .int_signed => self.cast(Payload.IntSigned).?.bits != 0,
788 .int_unsigned => self.cast(Payload.IntUnsigned).?.bits != 0,
792 .int_signed, .int_unsigned => self.cast(Payload.Bits).?.data != 0,
789793
790794 .error_union => {
791 const payload = self.cast(Payload.ErrorUnion).?;
795 const payload = self.castTag(.error_union).?.data;
792796 return payload.error_set.hasCodeGenBits() or payload.payload.hasCodeGenBits();
793797 },
794798
......@@ -855,7 +859,7 @@ pub const Type = extern union {
855859 => return @divExact(target.cpu.arch.ptrBitWidth(), 8),
856860
857861 .pointer => {
858 const payload = @fieldParentPtr(Payload.Pointer, "base", self.ptr_otherwise);
862 const payload = self.castTag(.pointer).?.data;
859863
860864 if (payload.@"align" != 0) return payload.@"align";
861865 return @divExact(target.cpu.arch.ptrBitWidth(), 8);
......@@ -885,18 +889,12 @@ pub const Type = extern union {
885889 .array, .array_sentinel => return self.elemType().abiAlignment(target),
886890
887891 .int_signed, .int_unsigned => {
888 const bits: u16 = if (self.cast(Payload.IntSigned)) |pl|
889 pl.bits
890 else if (self.cast(Payload.IntUnsigned)) |pl|
891 pl.bits
892 else
893 unreachable;
894
892 const bits: u16 = self.cast(Payload.Bits).?.data;
895893 return std.math.ceilPowerOfTwoPromote(u16, (bits + 7) / 8);
896894 },
897895
898896 .optional => {
899 var buf: Payload.PointerSimple = undefined;
897 var buf: Payload.ElemType = undefined;
900898 const child_type = self.optionalChild(&buf);
901899 if (!child_type.hasCodeGenBits()) return 1;
902900
......@@ -907,7 +905,7 @@ pub const Type = extern union {
907905 },
908906
909907 .error_union => {
910 const payload = self.cast(Payload.ErrorUnion).?;
908 const payload = self.castTag(.error_union).?.data;
911909 if (!payload.error_set.hasCodeGenBits()) {
912910 return payload.payload.abiAlignment(target);
913911 } else if (!payload.payload.hasCodeGenBits()) {
......@@ -955,16 +953,19 @@ pub const Type = extern union {
955953 .bool,
956954 => return 1,
957955
958 .array_u8 => @fieldParentPtr(Payload.Array_u8_Sentinel0, "base", self.ptr_otherwise).len,
959 .array_u8_sentinel_0 => @fieldParentPtr(Payload.Array_u8_Sentinel0, "base", self.ptr_otherwise).len + 1,
956 .array_u8 => self.castTag(.array_u8).?.data,
957 .array_u8_sentinel_0 => self.castTag(.array_u8_sentinel_0).?.data + 1,
960958 .array => {
961 const payload = @fieldParentPtr(Payload.Array, "base", self.ptr_otherwise);
959 const payload = self.castTag(.array).?.data;
962960 const elem_size = std.math.max(payload.elem_type.abiAlignment(target), payload.elem_type.abiSize(target));
963961 return payload.len * elem_size;
964962 },
965963 .array_sentinel => {
966 const payload = @fieldParentPtr(Payload.ArraySentinel, "base", self.ptr_otherwise);
967 const elem_size = std.math.max(payload.elem_type.abiAlignment(target), payload.elem_type.abiSize(target));
964 const payload = self.castTag(.array_sentinel).?.data;
965 const elem_size = std.math.max(
966 payload.elem_type.abiAlignment(target),
967 payload.elem_type.abiSize(target),
968 );
968969 return (payload.len + 1) * elem_size;
969970 },
970971 .i16, .u16 => return 2,
......@@ -1022,18 +1023,12 @@ pub const Type = extern union {
10221023 => return 2, // TODO revisit this when we have the concept of the error tag type
10231024
10241025 .int_signed, .int_unsigned => {
1025 const bits: u16 = if (self.cast(Payload.IntSigned)) |pl|
1026 pl.bits
1027 else if (self.cast(Payload.IntUnsigned)) |pl|
1028 pl.bits
1029 else
1030 unreachable;
1031
1026 const bits: u16 = self.cast(Payload.Bits).?.data;
10321027 return std.math.ceilPowerOfTwoPromote(u16, (bits + 7) / 8);
10331028 },
10341029
10351030 .optional => {
1036 var buf: Payload.PointerSimple = undefined;
1031 var buf: Payload.ElemType = undefined;
10371032 const child_type = self.optionalChild(&buf);
10381033 if (!child_type.hasCodeGenBits()) return 1;
10391034
......@@ -1048,7 +1043,7 @@ pub const Type = extern union {
10481043 },
10491044
10501045 .error_union => {
1051 const payload = self.cast(Payload.ErrorUnion).?;
1046 const payload = self.castTag(.error_union).?.data;
10521047 if (!payload.error_set.hasCodeGenBits() and !payload.payload.hasCodeGenBits()) {
10531048 return 0;
10541049 } else if (!payload.error_set.hasCodeGenBits()) {
......@@ -1132,7 +1127,7 @@ pub const Type = extern union {
11321127 .single_const_pointer_to_comptime_int,
11331128 => true,
11341129
1135 .pointer => self.cast(Payload.Pointer).?.size == .One,
1130 .pointer => self.castTag(.pointer).?.data.size == .One,
11361131 };
11371132 }
11381133
......@@ -1214,7 +1209,7 @@ pub const Type = extern union {
12141209 .single_const_pointer_to_comptime_int,
12151210 => .One,
12161211
1217 .pointer => self.cast(Payload.Pointer).?.size,
1212 .pointer => self.castTag(.pointer).?.data.size,
12181213 };
12191214 }
12201215
......@@ -1289,7 +1284,7 @@ pub const Type = extern union {
12891284 .const_slice_u8,
12901285 => true,
12911286
1292 .pointer => self.cast(Payload.Pointer).?.size == .Slice,
1287 .pointer => self.castTag(.pointer).?.data.size == .Slice,
12931288 };
12941289 }
12951290
......@@ -1364,7 +1359,7 @@ pub const Type = extern union {
13641359 .const_slice,
13651360 => true,
13661361
1367 .pointer => !self.cast(Payload.Pointer).?.mutable,
1362 .pointer => !self.castTag(.pointer).?.data.mutable,
13681363 };
13691364 }
13701365
......@@ -1438,7 +1433,7 @@ pub const Type = extern union {
14381433 => false,
14391434
14401435 .pointer => {
1441 const payload = @fieldParentPtr(Payload.Pointer, "base", self.ptr_otherwise);
1436 const payload = self.castTag(.pointer).?.data;
14421437 return payload.@"volatile";
14431438 },
14441439 };
......@@ -1514,7 +1509,7 @@ pub const Type = extern union {
15141509 => false,
15151510
15161511 .pointer => {
1517 const payload = @fieldParentPtr(Payload.Pointer, "base", self.ptr_otherwise);
1512 const payload = self.castTag(.pointer).?.data;
15181513 return payload.@"allowzero";
15191514 },
15201515 };
......@@ -1525,7 +1520,7 @@ pub const Type = extern union {
15251520 switch (self.tag()) {
15261521 .optional_single_const_pointer, .optional_single_mut_pointer => return true,
15271522 .optional => {
1528 var buf: Payload.PointerSimple = undefined;
1523 var buf: Payload.ElemType = undefined;
15291524 const child_type = self.optionalChild(&buf);
15301525 // optionals of zero sized pointers behave like bools
15311526 if (!child_type.hasCodeGenBits()) return false;
......@@ -1563,7 +1558,7 @@ pub const Type = extern union {
15631558 => return false,
15641559
15651560 .Optional => {
1566 var buf: Payload.PointerSimple = undefined;
1561 var buf: Payload.ElemType = undefined;
15671562 return ty.optionalChild(&buf).isValidVarType(is_extern);
15681563 },
15691564 .Pointer, .Array => ty = ty.elemType(),
......@@ -1631,8 +1626,8 @@ pub const Type = extern union {
16311626 .empty_struct,
16321627 => unreachable,
16331628
1634 .array => self.cast(Payload.Array).?.elem_type,
1635 .array_sentinel => self.cast(Payload.ArraySentinel).?.elem_type,
1629 .array => self.castTag(.array).?.data.elem_type,
1630 .array_sentinel => self.castTag(.array_sentinel).?.data.elem_type,
16361631 .single_const_pointer,
16371632 .single_mut_pointer,
16381633 .many_const_pointer,
......@@ -1641,28 +1636,29 @@ pub const Type = extern union {
16411636 .c_mut_pointer,
16421637 .const_slice,
16431638 .mut_slice,
1644 => self.castPointer().?.pointee_type,
1639 => self.castPointer().?.data,
16451640 .array_u8, .array_u8_sentinel_0, .const_slice_u8 => Type.initTag(.u8),
16461641 .single_const_pointer_to_comptime_int => Type.initTag(.comptime_int),
1647 .pointer => self.cast(Payload.Pointer).?.pointee_type,
1642 .pointer => self.castTag(.pointer).?.data.pointee_type,
16481643 };
16491644 }
16501645
16511646 /// Asserts that the type is an optional.
1652 pub fn optionalChild(self: Type, buf: *Payload.PointerSimple) Type {
1647 /// Resulting `Type` will have inner memory referencing `buf`.
1648 pub fn optionalChild(self: Type, buf: *Payload.ElemType) Type {
16531649 return switch (self.tag()) {
1654 .optional => self.cast(Payload.Optional).?.child_type,
1650 .optional => self.castTag(.optional).?.data,
16551651 .optional_single_mut_pointer => {
16561652 buf.* = .{
16571653 .base = .{ .tag = .single_mut_pointer },
1658 .pointee_type = self.castPointer().?.pointee_type,
1654 .data = self.castPointer().?.data,
16591655 };
16601656 return Type.initPayload(&buf.base);
16611657 },
16621658 .optional_single_const_pointer => {
16631659 buf.* = .{
16641660 .base = .{ .tag = .single_const_pointer },
1665 .pointee_type = self.castPointer().?.pointee_type,
1661 .data = self.castPointer().?.data,
16661662 };
16671663 return Type.initPayload(&buf.base);
16681664 },
......@@ -1673,23 +1669,16 @@ pub const Type = extern union {
16731669 /// Asserts that the type is an optional.
16741670 /// Same as `optionalChild` but allocates the buffer if needed.
16751671 pub fn optionalChildAlloc(self: Type, allocator: *Allocator) !Type {
1676 return switch (self.tag()) {
1677 .optional => self.cast(Payload.Optional).?.child_type,
1678 .optional_single_mut_pointer, .optional_single_const_pointer => {
1679 const payload = try allocator.create(Payload.PointerSimple);
1680 payload.* = .{
1681 .base = .{
1682 .tag = if (self.tag() == .optional_single_const_pointer)
1683 .single_const_pointer
1684 else
1685 .single_mut_pointer,
1686 },
1687 .pointee_type = self.castPointer().?.pointee_type,
1688 };
1689 return Type.initPayload(&payload.base);
1672 switch (self.tag()) {
1673 .optional => return self.castTag(.optional).?.data,
1674 .optional_single_mut_pointer => {
1675 return Tag.single_mut_pointer.create(allocator, self.castPointer().?.data);
1676 },
1677 .optional_single_const_pointer => {
1678 return Tag.single_const_pointer.create(allocator, self.castPointer().?.data);
16901679 },
16911680 else => unreachable,
1692 };
1681 }
16931682 }
16941683
16951684 /// Asserts the type is an array or vector.
......@@ -1759,10 +1748,10 @@ pub const Type = extern union {
17591748 .empty_struct,
17601749 => unreachable,
17611750
1762 .array => self.cast(Payload.Array).?.len,
1763 .array_sentinel => self.cast(Payload.ArraySentinel).?.len,
1764 .array_u8 => self.cast(Payload.Array_u8).?.len,
1765 .array_u8_sentinel_0 => self.cast(Payload.Array_u8_Sentinel0).?.len,
1751 .array => self.castTag(.array).?.data.len,
1752 .array_sentinel => self.castTag(.array_sentinel).?.data.len,
1753 .array_u8 => self.castTag(.array_u8).?.data,
1754 .array_u8_sentinel_0 => self.castTag(.array_u8_sentinel_0).?.data,
17661755 };
17671756 }
17681757
......@@ -1836,8 +1825,8 @@ pub const Type = extern union {
18361825 .array_u8,
18371826 => return null,
18381827
1839 .pointer => return self.cast(Payload.Pointer).?.sentinel,
1840 .array_sentinel => return self.cast(Payload.ArraySentinel).?.sentinel,
1828 .pointer => return self.castTag(.pointer).?.data.sentinel,
1829 .array_sentinel => return self.castTag(.array_sentinel).?.data.sentinel,
18411830 .array_u8_sentinel_0 => return Value.initTag(.zero),
18421831 };
18431832 }
......@@ -2048,8 +2037,14 @@ pub const Type = extern union {
20482037 .empty_struct,
20492038 => unreachable,
20502039
2051 .int_unsigned => .{ .signedness = .unsigned, .bits = self.cast(Payload.IntUnsigned).?.bits },
2052 .int_signed => .{ .signedness = .signed, .bits = self.cast(Payload.IntSigned).?.bits },
2040 .int_unsigned => .{
2041 .signedness = .unsigned,
2042 .bits = self.castTag(.int_unsigned).?.data,
2043 },
2044 .int_signed => .{
2045 .signedness = .signed,
2046 .bits = self.castTag(.int_signed).?.data,
2047 },
20532048 .u8 => .{ .signedness = .unsigned, .bits = 8 },
20542049 .i8 => .{ .signedness = .signed, .bits = 8 },
20552050 .u16 => .{ .signedness = .unsigned, .bits = 16 },
......@@ -2178,7 +2173,7 @@ pub const Type = extern union {
21782173 .fn_void_no_args => 0,
21792174 .fn_naked_noreturn_no_args => 0,
21802175 .fn_ccc_void_no_args => 0,
2181 .function => @fieldParentPtr(Payload.Function, "base", self.ptr_otherwise).param_types.len,
2176 .function => self.castTag(.function).?.data.param_types.len,
21822177
21832178 .f16,
21842179 .f32,
......@@ -2254,7 +2249,7 @@ pub const Type = extern union {
22542249 .fn_naked_noreturn_no_args => return,
22552250 .fn_ccc_void_no_args => return,
22562251 .function => {
2257 const payload = @fieldParentPtr(Payload.Function, "base", self.ptr_otherwise);
2252 const payload = self.castTag(.function).?.data;
22582253 std.mem.copy(Type, types, payload.param_types);
22592254 },
22602255
......@@ -2327,7 +2322,7 @@ pub const Type = extern union {
23272322 pub fn fnParamType(self: Type, index: usize) Type {
23282323 switch (self.tag()) {
23292324 .function => {
2330 const payload = @fieldParentPtr(Payload.Function, "base", self.ptr_otherwise);
2325 const payload = self.castTag(.function).?.data;
23312326 return payload.param_types[index];
23322327 },
23332328
......@@ -2410,7 +2405,7 @@ pub const Type = extern union {
24102405 .fn_ccc_void_no_args,
24112406 => Type.initTag(.void),
24122407
2413 .function => @fieldParentPtr(Payload.Function, "base", self.ptr_otherwise).return_type,
2408 .function => self.castTag(.function).?.data.return_type,
24142409
24152410 .f16,
24162411 .f32,
......@@ -2484,7 +2479,7 @@ pub const Type = extern union {
24842479 .fn_void_no_args => .Unspecified,
24852480 .fn_naked_noreturn_no_args => .Naked,
24862481 .fn_ccc_void_no_args => .C,
2487 .function => @fieldParentPtr(Payload.Function, "base", self.ptr_otherwise).cc,
2482 .function => self.castTag(.function).?.data.cc,
24882483
24892484 .f16,
24902485 .f32,
......@@ -2760,15 +2755,8 @@ pub const Type = extern union {
27602755 .@"null" => return Value.initTag(.null_value),
27612756 .@"undefined" => return Value.initTag(.undef),
27622757
2763 .int_unsigned => {
2764 if (ty.cast(Payload.IntUnsigned).?.bits == 0) {
2765 return Value.initTag(.zero);
2766 } else {
2767 return null;
2768 }
2769 },
2770 .int_signed => {
2771 if (ty.cast(Payload.IntSigned).?.bits == 0) {
2758 .int_unsigned, .int_signed => {
2759 if (ty.cast(Payload.Bits).?.data == 0) {
27722760 return Value.initTag(.zero);
27732761 } else {
27742762 return null;
......@@ -2787,12 +2775,11 @@ pub const Type = extern union {
27872775 .single_const_pointer,
27882776 .single_mut_pointer,
27892777 => {
2790 const ptr = ty.castPointer().?;
2791 ty = ptr.pointee_type;
2778 ty = ty.castPointer().?.data;
27922779 continue;
27932780 },
27942781 .pointer => {
2795 ty = ty.cast(Payload.Pointer).?.pointee_type;
2782 ty = ty.castTag(.pointer).?.data.pointee_type;
27962783 continue;
27972784 },
27982785 };
......@@ -2869,7 +2856,7 @@ pub const Type = extern union {
28692856 .c_mut_pointer,
28702857 => return true,
28712858
2872 .pointer => self.cast(Payload.Pointer).?.size == .C,
2859 .pointer => self.castTag(.pointer).?.data.size == .C,
28732860 };
28742861 }
28752862
......@@ -2950,7 +2937,7 @@ pub const Type = extern union {
29502937 .pointer,
29512938 => unreachable,
29522939
2953 .empty_struct => self.cast(Type.Payload.EmptyStruct).?.scope,
2940 .empty_struct => self.castTag(.empty_struct).?.data,
29542941 };
29552942 }
29562943
......@@ -3105,117 +3092,195 @@ pub const Type = extern union {
31053092
31063093 pub const last_no_payload_tag = Tag.const_slice_u8;
31073094 pub const no_payload_count = @enumToInt(last_no_payload_tag) + 1;
3108 };
31093095
3110 pub const Payload = struct {
3111 tag: Tag,
3096 pub fn Type(comptime t: Tag) type {
3097 return switch (t) {
3098 .u8,
3099 .i8,
3100 .u16,
3101 .i16,
3102 .u32,
3103 .i32,
3104 .u64,
3105 .i64,
3106 .usize,
3107 .isize,
3108 .c_short,
3109 .c_ushort,
3110 .c_int,
3111 .c_uint,
3112 .c_long,
3113 .c_ulong,
3114 .c_longlong,
3115 .c_ulonglong,
3116 .c_longdouble,
3117 .f16,
3118 .f32,
3119 .f64,
3120 .f128,
3121 .c_void,
3122 .bool,
3123 .void,
3124 .type,
3125 .anyerror,
3126 .comptime_int,
3127 .comptime_float,
3128 .noreturn,
3129 .enum_literal,
3130 .@"null",
3131 .@"undefined",
3132 .fn_noreturn_no_args,
3133 .fn_void_no_args,
3134 .fn_naked_noreturn_no_args,
3135 .fn_ccc_void_no_args,
3136 .single_const_pointer_to_comptime_int,
3137 .anyerror_void_error_union,
3138 .@"anyframe",
3139 .const_slice_u8,
3140 => @compileError("Type Tag " ++ @tagName(t) ++ " has no payload"),
3141
3142 .array_u8,
3143 .array_u8_sentinel_0,
3144 => Payload.Len,
3145
3146 .single_const_pointer,
3147 .single_mut_pointer,
3148 .many_const_pointer,
3149 .many_mut_pointer,
3150 .c_const_pointer,
3151 .c_mut_pointer,
3152 .const_slice,
3153 .mut_slice,
3154 .optional,
3155 .optional_single_mut_pointer,
3156 .optional_single_const_pointer,
3157 .anyframe_T,
3158 => Payload.ElemType,
3159
3160 .int_signed,
3161 .int_unsigned,
3162 => Payload.Bits,
3163
3164 .array => Payload.Array,
3165 .array_sentinel => Payload.ArraySentinel,
3166 .pointer => Payload.Pointer,
3167 .function => Payload.Function,
3168 .error_union => Payload.ErrorUnion,
3169 .error_set => Payload.Decl,
3170 .error_set_single => Payload.Name,
3171 .empty_struct => Payload.ContainerScope,
3172 };
3173 }
31123174
3113 pub const Array_u8_Sentinel0 = struct {
3114 base: Payload = Payload{ .tag = .array_u8_sentinel_0 },
3175 pub fn create(comptime t: Tag, ally: *Allocator, data: Data(t)) error{OutOfMemory}!Type {
3176 const ptr = try ally.create(t.Type());
3177 ptr.* = .{
3178 .base = .{ .tag = t },
3179 .data = data,
3180 };
3181 return Type{ .ptr_otherwise = &ptr.base };
3182 }
31153183
3116 len: u64,
3117 };
3184 pub fn Data(comptime t: Tag) type {
3185 return std.meta.fieldInfo(t.Type(), "data").field_type;
3186 }
3187 };
31183188
3119 pub const Array_u8 = struct {
3120 base: Payload = Payload{ .tag = .array_u8 },
3189 /// The sub-types are named after what fields they contain.
3190 pub const Payload = struct {
3191 tag: Tag,
31213192
3122 len: u64,
3193 pub const Len = struct {
3194 base: Payload,
3195 data: u64,
31233196 };
31243197
31253198 pub const Array = struct {
3126 base: Payload = Payload{ .tag = .array },
3199 pub const base_tag = Tag.array;
31273200
3128 len: u64,
3129 elem_type: Type,
3201 base: Payload = Payload{ .tag = base_tag },
3202 data: struct {
3203 len: u64,
3204 elem_type: Type,
3205 },
31303206 };
31313207
31323208 pub const ArraySentinel = struct {
3133 base: Payload = Payload{ .tag = .array_sentinel },
3209 pub const base_tag = Tag.array_sentinel;
31343210
3135 len: u64,
3136 sentinel: Value,
3137 elem_type: Type,
3211 base: Payload = Payload{ .tag = base_tag },
3212 data: struct {
3213 len: u64,
3214 sentinel: Value,
3215 elem_type: Type,
3216 },
31383217 };
31393218
3140 pub const PointerSimple = struct {
3219 pub const ElemType = struct {
31413220 base: Payload,
3142
3143 pointee_type: Type,
3221 data: Type,
31443222 };
31453223
3146 pub const IntSigned = struct {
3147 base: Payload = Payload{ .tag = .int_signed },
3148
3149 bits: u16,
3150 };
3151
3152 pub const IntUnsigned = struct {
3153 base: Payload = Payload{ .tag = .int_unsigned },
3154
3155 bits: u16,
3224 pub const Bits = struct {
3225 base: Payload,
3226 data: u16,
31563227 };
31573228
31583229 pub const Function = struct {
3159 base: Payload = Payload{ .tag = .function },
3160
3161 param_types: []Type,
3162 return_type: Type,
3163 cc: std.builtin.CallingConvention,
3164 };
3165
3166 pub const Optional = struct {
3167 base: Payload = Payload{ .tag = .optional },
3230 pub const base_tag = Tag.function;
31683231
3169 child_type: Type,
3232 base: Payload = Payload{ .tag = base_tag },
3233 data: struct {
3234 param_types: []Type,
3235 return_type: Type,
3236 cc: std.builtin.CallingConvention,
3237 },
31703238 };
31713239
31723240 pub const Pointer = struct {
3173 base: Payload = .{ .tag = .pointer },
3174
3175 pointee_type: Type,
3176 sentinel: ?Value,
3177 /// If zero use pointee_type.AbiAlign()
3178 @"align": u32,
3179 bit_offset: u16,
3180 host_size: u16,
3181 @"allowzero": bool,
3182 mutable: bool,
3183 @"volatile": bool,
3184 size: std.builtin.TypeInfo.Pointer.Size,
3241 pub const base_tag = Tag.pointer;
3242
3243 base: Payload = Payload{ .tag = base_tag },
3244 data: struct {
3245 pointee_type: Type,
3246 sentinel: ?Value,
3247 /// If zero use pointee_type.AbiAlign()
3248 @"align": u32,
3249 bit_offset: u16,
3250 host_size: u16,
3251 @"allowzero": bool,
3252 mutable: bool,
3253 @"volatile": bool,
3254 size: std.builtin.TypeInfo.Pointer.Size,
3255 },
31853256 };
31863257
31873258 pub const ErrorUnion = struct {
3188 base: Payload = .{ .tag = .error_union },
3259 pub const base_tag = Tag.error_union;
31893260
3190 error_set: Type,
3191 payload: Type,
3192 };
3193
3194 pub const AnyFrame = struct {
3195 base: Payload = .{ .tag = .anyframe_T },
3196
3197 return_type: Type,
3261 base: Payload = Payload{ .tag = base_tag },
3262 data: struct {
3263 error_set: Type,
3264 payload: Type,
3265 },
31983266 };
31993267
3200 pub const ErrorSet = struct {
3201 base: Payload = .{ .tag = .error_set },
3202
3203 decl: *Module.Decl,
3268 pub const Decl = struct {
3269 base: Payload,
3270 data: *Module.Decl,
32043271 };
32053272
3206 pub const ErrorSetSingle = struct {
3207 base: Payload = .{ .tag = .error_set_single },
3208
3273 pub const Name = struct {
3274 base: Payload,
32093275 /// memory is owned by `Module`
3210 name: []const u8,
3276 data: []const u8,
32113277 };
32123278
32133279 /// Mostly used for namespace like structs with zero fields.
32143280 /// Most commonly used for files.
3215 pub const EmptyStruct = struct {
3216 base: Payload = .{ .tag = .empty_struct },
3217
3218 scope: *Module.Scope.Container,
3281 pub const ContainerScope = struct {
3282 base: Payload,
3283 data: *Module.Scope.Container,
32193284 };
32203285 };
32213286};
src/value.zig+16-19
......@@ -440,21 +440,18 @@ pub const Value = extern union {
440440
441441 .int_type => {
442442 const payload = self.cast(Payload.IntType).?;
443 if (payload.signed) {
444 const new = try allocator.create(Type.Payload.IntSigned);
445 new.* = .{ .bits = payload.bits };
446 return Type.initPayload(&new.base);
447 } else {
448 const new = try allocator.create(Type.Payload.IntUnsigned);
449 new.* = .{ .bits = payload.bits };
450 return Type.initPayload(&new.base);
451 }
443 const new = try allocator.create(Type.Payload.Bits);
444 new.* = .{
445 .base = .{
446 .tag = if (payload.signed) .int_signed else .int_unsigned,
447 },
448 .data = payload.bits,
449 };
450 return Type.initPayload(&new.base);
452451 },
453452 .error_set => {
454453 const payload = self.cast(Payload.ErrorSet).?;
455 const new = try allocator.create(Type.Payload.ErrorSet);
456 new.* = .{ .decl = payload.decl };
457 return Type.initPayload(&new.base);
454 return Type.Tag.error_set.create(allocator, payload.decl);
458455 },
459456
460457 .undef,
......@@ -1321,13 +1318,13 @@ pub const Value = extern union {
13211318 },
13221319 .int_type => {
13231320 const payload = self.cast(Payload.IntType).?;
1324 if (payload.signed) {
1325 var new = Type.Payload.IntSigned{ .bits = payload.bits };
1326 return Type.initPayload(&new.base).hash();
1327 } else {
1328 var new = Type.Payload.IntUnsigned{ .bits = payload.bits };
1329 return Type.initPayload(&new.base).hash();
1330 }
1321 var int_payload = Type.Payload.Bits{
1322 .base = .{
1323 .tag = if (payload.signed) .int_signed else .int_unsigned,
1324 },
1325 .data = payload.bits,
1326 };
1327 return Type.initPayload(&int_payload.base).hash();
13311328 },
13321329
13331330 .empty_struct_value,
src/zir.zig+1-1
......@@ -2785,7 +2785,7 @@ const EmitZIR = struct {
27852785 }
27862786 },
27872787 .Optional => {
2788 var buf: Type.Payload.PointerSimple = undefined;
2788 var buf: Type.Payload.ElemType = undefined;
27892789 const inst = try self.arena.allocator.create(Inst.UnOp);
27902790 inst.* = .{
27912791 .base = .{
src/zir_sema.zig+10-20
......@@ -480,14 +480,11 @@ fn analyzeInstStr(mod: *Module, scope: *Scope, str_inst: *zir.Inst.Str) InnerErr
480480 errdefer new_decl_arena.deinit();
481481 const arena_bytes = try new_decl_arena.allocator.dupe(u8, str_inst.positionals.bytes);
482482
483 const ty_payload = try scope.arena().create(Type.Payload.Array_u8_Sentinel0);
484 ty_payload.* = .{ .len = arena_bytes.len };
485
486483 const bytes_payload = try scope.arena().create(Value.Payload.Bytes);
487484 bytes_payload.* = .{ .data = arena_bytes };
488485
489486 const new_decl = try mod.createAnonymousDecl(scope, &new_decl_arena, .{
490 .ty = Type.initPayload(&ty_payload.base),
487 .ty = try Type.Tag.array_u8_sentinel_0.create(scope.arena(), arena_bytes.len),
491488 .val = Value.initPayload(&bytes_payload.base),
492489 });
493490 return mod.analyzeDeclRef(scope, str_inst.base.src, new_decl);
......@@ -952,13 +949,12 @@ fn analyzeInstFnType(mod: *Module, scope: *Scope, fntype: *zir.Inst.FnType) Inne
952949 param_types[i] = resolved;
953950 }
954951
955 const payload = try arena.create(Type.Payload.Function);
956 payload.* = .{
952 const fn_ty = try Type.Tag.function.create(arena, .{
957953 .cc = fntype.kw_args.cc,
958954 .return_type = return_type,
959955 .param_types = param_types,
960 };
961 return mod.constType(scope, fntype.base.src, Type.initPayload(&payload.base));
956 });
957 return mod.constType(scope, fntype.base.src, fn_ty);
962958}
963959
964960fn analyzeInstPrimitive(mod: *Module, scope: *Scope, primitive: *zir.Inst.Primitive) InnerError!*Inst {
......@@ -1062,11 +1058,10 @@ fn analyzeInstFieldPtr(mod: *Module, scope: *Scope, fieldptr: *zir.Inst.FieldPtr
10621058 const ref_payload = try scope.arena().create(Value.Payload.RefVal);
10631059 ref_payload.* = .{ .val = Value.initPayload(&error_payload.base) };
10641060
1065 const result_type = if (child_type.tag() == .anyerror) blk: {
1066 const result_payload = try scope.arena().create(Type.Payload.ErrorSetSingle);
1067 result_payload.* = .{ .name = entry.key };
1068 break :blk Type.initPayload(&result_payload.base);
1069 } else child_type;
1061 const result_type = if (child_type.tag() == .anyerror)
1062 try Type.Tag.error_set_single.create(scope.arena(), entry.key)
1063 else
1064 child_type;
10701065
10711066 return mod.constInst(scope, fieldptr.base.src, .{
10721067 .ty = try mod.simplePtrType(scope, fieldptr.base.src, result_type, false, .One),
......@@ -1195,15 +1190,10 @@ fn analyzeInstElemPtr(mod: *Module, scope: *Scope, inst: *zir.Inst.ElemPtr) Inne
11951190 // @intCast here because it would have been impossible to construct a value that
11961191 // required a larger index.
11971192 const elem_ptr = try array_ptr_val.elemPtr(scope.arena(), @intCast(usize, index_u64));
1198
1199 const type_payload = try scope.arena().create(Type.Payload.PointerSimple);
1200 type_payload.* = .{
1201 .base = .{ .tag = .single_const_pointer },
1202 .pointee_type = elem_ty.elemType().elemType(),
1203 };
1193 const pointee_type = elem_ty.elemType().elemType();
12041194
12051195 return mod.constInst(scope, inst.base.src, .{
1206 .ty = Type.initPayload(&type_payload.base),
1196 .ty = try Type.Tag.single_const_pointer.create(scope.arena(), pointee_type),
12071197 .val = elem_ptr,
12081198 });
12091199 }