authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-12-30 22:31:56-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-12-30 21:41:02-08:00
log3f7d9b5fc19e4081236b3b63aebbc80e1b17f5b5
treea577bd97edf5d5da357d576c777861d443210aec
parent133da8692e80532797dd91b32539cf2175280a95

stage2: rework Value Payload layout

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

12 files changed, 573 insertions(+), 515 deletions(-)

src/Compilation.zig+6-5
......@@ -1457,11 +1457,12 @@ pub fn performAllTheWork(self: *Compilation) error{ TimerUnsupported, OutOfMemor
14571457
14581458 .complete, .codegen_failure_retryable => {
14591459 const module = self.bin_file.options.module.?;
1460 if (decl.typed_value.most_recent.typed_value.val.cast(Value.Payload.Function)) |payload| {
1461 switch (payload.func.analysis) {
1462 .queued => module.analyzeFnBody(decl, payload.func) catch |err| switch (err) {
1460 if (decl.typed_value.most_recent.typed_value.val.castTag(.function)) |payload| {
1461 const func = payload.data;
1462 switch (func.analysis) {
1463 .queued => module.analyzeFnBody(decl, func) catch |err| switch (err) {
14631464 error.AnalysisFail => {
1464 assert(payload.func.analysis != .in_progress);
1465 assert(func.analysis != .in_progress);
14651466 continue;
14661467 },
14671468 error.OutOfMemory => return error.OutOfMemory,
......@@ -1475,7 +1476,7 @@ pub fn performAllTheWork(self: *Compilation) error{ TimerUnsupported, OutOfMemor
14751476 var decl_arena = decl.typed_value.most_recent.arena.?.promote(module.gpa);
14761477 defer decl.typed_value.most_recent.arena.?.* = decl_arena.state;
14771478 log.debug("analyze liveness of {}\n", .{decl.name});
1478 try liveness.analyze(module.gpa, &decl_arena.allocator, payload.func.analysis.success);
1479 try liveness.analyze(module.gpa, &decl_arena.allocator, func.analysis.success);
14791480 }
14801481
14811482 assert(decl.typed_value.most_recent.typed_value.ty.hasCodeGenBits());
src/Module.zig+83-110
......@@ -1092,16 +1092,12 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool {
10921092
10931093 tvm.deinit(self.gpa);
10941094 }
1095 const value_payload = try decl_arena.allocator.create(Value.Payload.ExternFn);
1096 value_payload.* = .{ .decl = decl };
1095 const fn_val = try Value.Tag.extern_fn.create(&decl_arena.allocator, decl);
10971096
10981097 decl_arena_state.* = decl_arena.state;
10991098 decl.typed_value = .{
11001099 .most_recent = .{
1101 .typed_value = .{
1102 .ty = fn_type,
1103 .val = Value.initPayload(&value_payload.base),
1104 },
1100 .typed_value = .{ .ty = fn_type, .val = fn_val },
11051101 .arena = decl_arena_state,
11061102 },
11071103 };
......@@ -1187,7 +1183,10 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool {
11871183 .analysis = .{ .queued = fn_zir },
11881184 .owner_decl = decl,
11891185 };
1190 fn_payload.* = .{ .func = new_func };
1186 fn_payload.* = .{
1187 .base = .{ .tag = .function },
1188 .data = new_func,
1189 };
11911190
11921191 var prev_type_has_bits = false;
11931192 var type_changed = true;
......@@ -1375,7 +1374,6 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool {
13751374 }
13761375
13771376 const new_variable = try decl_arena.allocator.create(Var);
1378 const var_payload = try decl_arena.allocator.create(Value.Payload.Variable);
13791377 new_variable.* = .{
13801378 .owner_decl = decl,
13811379 .init = var_info.val orelse undefined,
......@@ -1383,14 +1381,14 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool {
13831381 .is_mutable = is_mutable,
13841382 .is_threadlocal = is_threadlocal,
13851383 };
1386 var_payload.* = .{ .variable = new_variable };
1384 const var_val = try Value.Tag.variable.create(&decl_arena.allocator, new_variable);
13871385
13881386 decl_arena_state.* = decl_arena.state;
13891387 decl.typed_value = .{
13901388 .most_recent = .{
13911389 .typed_value = .{
13921390 .ty = var_info.ty,
1393 .val = Value.initPayload(&var_payload.base),
1391 .val = var_val,
13941392 },
13951393 .arena = decl_arena_state,
13961394 },
......@@ -2232,52 +2230,43 @@ pub fn constBool(self: *Module, scope: *Scope, src: usize, v: bool) !*Inst {
22322230}
22332231
22342232pub fn constIntUnsigned(self: *Module, scope: *Scope, src: usize, ty: Type, int: u64) !*Inst {
2235 const int_payload = try scope.arena().create(Value.Payload.Int_u64);
2236 int_payload.* = .{ .int = int };
2237
22382233 return self.constInst(scope, src, .{
22392234 .ty = ty,
2240 .val = Value.initPayload(&int_payload.base),
2235 .val = try Value.Tag.int_u64.create(scope.arena(), int),
22412236 });
22422237}
22432238
22442239pub fn constIntSigned(self: *Module, scope: *Scope, src: usize, ty: Type, int: i64) !*Inst {
2245 const int_payload = try scope.arena().create(Value.Payload.Int_i64);
2246 int_payload.* = .{ .int = int };
2247
22482240 return self.constInst(scope, src, .{
22492241 .ty = ty,
2250 .val = Value.initPayload(&int_payload.base),
2242 .val = try Value.Tag.int_i64.create(scope.arena(), int),
22512243 });
22522244}
22532245
22542246pub fn constIntBig(self: *Module, scope: *Scope, src: usize, ty: Type, big_int: BigIntConst) !*Inst {
2255 const val_payload = if (big_int.positive) blk: {
2247 if (big_int.positive) {
22562248 if (big_int.to(u64)) |x| {
22572249 return self.constIntUnsigned(scope, src, ty, x);
22582250 } else |err| switch (err) {
22592251 error.NegativeIntoUnsigned => unreachable,
22602252 error.TargetTooSmall => {}, // handled below
22612253 }
2262 const big_int_payload = try scope.arena().create(Value.Payload.IntBigPositive);
2263 big_int_payload.* = .{ .limbs = big_int.limbs };
2264 break :blk &big_int_payload.base;
2265 } else blk: {
2254 return self.constInst(scope, src, .{
2255 .ty = ty,
2256 .val = try Value.Tag.int_big_positive.create(scope.arena(), big_int.limbs),
2257 });
2258 } else {
22662259 if (big_int.to(i64)) |x| {
22672260 return self.constIntSigned(scope, src, ty, x);
22682261 } else |err| switch (err) {
22692262 error.NegativeIntoUnsigned => unreachable,
22702263 error.TargetTooSmall => {}, // handled below
22712264 }
2272 const big_int_payload = try scope.arena().create(Value.Payload.IntBigNegative);
2273 big_int_payload.* = .{ .limbs = big_int.limbs };
2274 break :blk &big_int_payload.base;
2275 };
2276
2277 return self.constInst(scope, src, .{
2278 .ty = ty,
2279 .val = Value.initPayload(val_payload),
2280 });
2265 return self.constInst(scope, src, .{
2266 .ty = ty,
2267 .val = try Value.Tag.int_big_negative.create(scope.arena(), big_int.limbs),
2268 });
2269 }
22812270}
22822271
22832272pub fn createAnonymousDecl(
......@@ -2346,26 +2335,20 @@ pub fn analyzeDeclRef(self: *Module, scope: *Scope, src: usize, decl: *Decl) Inn
23462335 if (decl_tv.val.tag() == .variable) {
23472336 return self.analyzeVarRef(scope, src, decl_tv);
23482337 }
2349 const ty = try self.simplePtrType(scope, src, decl_tv.ty, false, .One);
2350 const val_payload = try scope.arena().create(Value.Payload.DeclRef);
2351 val_payload.* = .{ .decl = decl };
2352
23532338 return self.constInst(scope, src, .{
2354 .ty = ty,
2355 .val = Value.initPayload(&val_payload.base),
2339 .ty = try self.simplePtrType(scope, src, decl_tv.ty, false, .One),
2340 .val = try Value.Tag.decl_ref.create(scope.arena(), decl),
23562341 });
23572342}
23582343
23592344fn analyzeVarRef(self: *Module, scope: *Scope, src: usize, tv: TypedValue) InnerError!*Inst {
2360 const variable = tv.val.cast(Value.Payload.Variable).?.variable;
2345 const variable = tv.val.castTag(.variable).?.data;
23612346
23622347 const ty = try self.simplePtrType(scope, src, tv.ty, variable.is_mutable, .One);
23632348 if (!variable.is_mutable and !variable.is_extern) {
2364 const val_payload = try scope.arena().create(Value.Payload.RefVal);
2365 val_payload.* = .{ .val = variable.init };
23662349 return self.constInst(scope, src, .{
23672350 .ty = ty,
2368 .val = Value.initPayload(&val_payload.base),
2351 .val = try Value.Tag.ref_val.create(scope.arena(), variable.init),
23692352 });
23702353 }
23712354
......@@ -3107,17 +3090,11 @@ pub fn intAdd(allocator: *Allocator, lhs: Value, rhs: Value) !Value {
31073090 result_bigint.add(lhs_bigint, rhs_bigint);
31083091 const result_limbs = result_bigint.limbs[0..result_bigint.len];
31093092
3110 const val_payload = if (result_bigint.positive) blk: {
3111 const val_payload = try allocator.create(Value.Payload.IntBigPositive);
3112 val_payload.* = .{ .limbs = result_limbs };
3113 break :blk &val_payload.base;
3114 } else blk: {
3115 const val_payload = try allocator.create(Value.Payload.IntBigNegative);
3116 val_payload.* = .{ .limbs = result_limbs };
3117 break :blk &val_payload.base;
3118 };
3119
3120 return Value.initPayload(val_payload);
3093 if (result_bigint.positive) {
3094 return Value.Tag.int_big_positive.create(allocator, result_limbs);
3095 } else {
3096 return Value.Tag.int_big_negative.create(allocator, result_limbs);
3097 }
31213098}
31223099
31233100pub fn intSub(allocator: *Allocator, lhs: Value, rhs: Value) !Value {
......@@ -3135,85 +3112,81 @@ pub fn intSub(allocator: *Allocator, lhs: Value, rhs: Value) !Value {
31353112 result_bigint.sub(lhs_bigint, rhs_bigint);
31363113 const result_limbs = result_bigint.limbs[0..result_bigint.len];
31373114
3138 const val_payload = if (result_bigint.positive) blk: {
3139 const val_payload = try allocator.create(Value.Payload.IntBigPositive);
3140 val_payload.* = .{ .limbs = result_limbs };
3141 break :blk &val_payload.base;
3142 } else blk: {
3143 const val_payload = try allocator.create(Value.Payload.IntBigNegative);
3144 val_payload.* = .{ .limbs = result_limbs };
3145 break :blk &val_payload.base;
3146 };
3147
3148 return Value.initPayload(val_payload);
3115 if (result_bigint.positive) {
3116 return Value.Tag.int_big_positive.create(allocator, result_limbs);
3117 } else {
3118 return Value.Tag.int_big_negative.create(allocator, result_limbs);
3119 }
31493120}
31503121
3151pub fn floatAdd(self: *Module, scope: *Scope, float_type: Type, src: usize, lhs: Value, rhs: Value) !Value {
3152 var bit_count = switch (float_type.tag()) {
3153 .comptime_float => 128,
3154 else => float_type.floatBits(self.getTarget()),
3155 };
3156
3157 const allocator = scope.arena();
3158 const val_payload = switch (bit_count) {
3159 16 => {
3160 return self.fail(scope, src, "TODO Implement addition for soft floats", .{});
3122pub fn floatAdd(
3123 self: *Module,
3124 scope: *Scope,
3125 float_type: Type,
3126 src: usize,
3127 lhs: Value,
3128 rhs: Value,
3129) !Value {
3130 const arena = scope.arena();
3131 switch (float_type.tag()) {
3132 .f16 => {
3133 @panic("TODO add __trunctfhf2 to compiler-rt");
3134 //const lhs_val = lhs.toFloat(f16);
3135 //const rhs_val = rhs.toFloat(f16);
3136 //return Value.Tag.float_16.create(arena, lhs_val + rhs_val);
31613137 },
3162 32 => blk: {
3138 .f32 => {
31633139 const lhs_val = lhs.toFloat(f32);
31643140 const rhs_val = rhs.toFloat(f32);
3165 const val_payload = try allocator.create(Value.Payload.Float_32);
3166 val_payload.* = .{ .val = lhs_val + rhs_val };
3167 break :blk &val_payload.base;
3141 return Value.Tag.float_32.create(arena, lhs_val + rhs_val);
31683142 },
3169 64 => blk: {
3143 .f64 => {
31703144 const lhs_val = lhs.toFloat(f64);
31713145 const rhs_val = rhs.toFloat(f64);
3172 const val_payload = try allocator.create(Value.Payload.Float_64);
3173 val_payload.* = .{ .val = lhs_val + rhs_val };
3174 break :blk &val_payload.base;
3146 return Value.Tag.float_64.create(arena, lhs_val + rhs_val);
31753147 },
3176 128 => {
3177 return self.fail(scope, src, "TODO Implement addition for big floats", .{});
3148 .f128, .comptime_float, .c_longdouble => {
3149 const lhs_val = lhs.toFloat(f128);
3150 const rhs_val = rhs.toFloat(f128);
3151 return Value.Tag.float_128.create(arena, lhs_val + rhs_val);
31783152 },
31793153 else => unreachable,
3180 };
3181
3182 return Value.initPayload(val_payload);
3154 }
31833155}
31843156
3185pub fn floatSub(self: *Module, scope: *Scope, float_type: Type, src: usize, lhs: Value, rhs: Value) !Value {
3186 var bit_count = switch (float_type.tag()) {
3187 .comptime_float => 128,
3188 else => float_type.floatBits(self.getTarget()),
3189 };
3190
3191 const allocator = scope.arena();
3192 const val_payload = switch (bit_count) {
3193 16 => {
3194 return self.fail(scope, src, "TODO Implement substraction for soft floats", .{});
3157pub fn floatSub(
3158 self: *Module,
3159 scope: *Scope,
3160 float_type: Type,
3161 src: usize,
3162 lhs: Value,
3163 rhs: Value,
3164) !Value {
3165 const arena = scope.arena();
3166 switch (float_type.tag()) {
3167 .f16 => {
3168 @panic("TODO add __trunctfhf2 to compiler-rt");
3169 //const lhs_val = lhs.toFloat(f16);
3170 //const rhs_val = rhs.toFloat(f16);
3171 //return Value.Tag.float_16.create(arena, lhs_val - rhs_val);
31953172 },
3196 32 => blk: {
3173 .f32 => {
31973174 const lhs_val = lhs.toFloat(f32);
31983175 const rhs_val = rhs.toFloat(f32);
3199 const val_payload = try allocator.create(Value.Payload.Float_32);
3200 val_payload.* = .{ .val = lhs_val - rhs_val };
3201 break :blk &val_payload.base;
3176 return Value.Tag.float_32.create(arena, lhs_val - rhs_val);
32023177 },
3203 64 => blk: {
3178 .f64 => {
32043179 const lhs_val = lhs.toFloat(f64);
32053180 const rhs_val = rhs.toFloat(f64);
3206 const val_payload = try allocator.create(Value.Payload.Float_64);
3207 val_payload.* = .{ .val = lhs_val - rhs_val };
3208 break :blk &val_payload.base;
3181 return Value.Tag.float_64.create(arena, lhs_val - rhs_val);
32093182 },
3210 128 => {
3211 return self.fail(scope, src, "TODO Implement substraction for big floats", .{});
3183 .f128, .comptime_float, .c_longdouble => {
3184 const lhs_val = lhs.toFloat(f128);
3185 const rhs_val = rhs.toFloat(f128);
3186 return Value.Tag.float_128.create(arena, lhs_val - rhs_val);
32123187 },
32133188 else => unreachable,
3214 };
3215
3216 return Value.initPayload(val_payload);
3189 }
32173190}
32183191
32193192pub fn simplePtrType(self: *Module, scope: *Scope, src: usize, elem_ty: Type, mutable: bool, size: std.builtin.TypeInfo.Pointer.Size) Allocator.Error!Type {
src/astgen.zig+10-16
......@@ -1956,13 +1956,13 @@ fn identifier(mod: *Module, scope: *Scope, rl: ResultLoc, ident: *ast.Node.OneTo
19561956 32 => if (is_signed) Value.initTag(.i32_type) else Value.initTag(.u32_type),
19571957 64 => if (is_signed) Value.initTag(.i64_type) else Value.initTag(.u64_type),
19581958 else => {
1959 const int_type_payload = try scope.arena().create(Value.Payload.IntType);
1960 int_type_payload.* = .{ .signed = is_signed, .bits = bit_count };
1961 const result = try addZIRInstConst(mod, scope, src, .{
1959 return rlWrap(mod, scope, rl, try addZIRInstConst(mod, scope, src, .{
19621960 .ty = Type.initTag(.type),
1963 .val = Value.initPayload(&int_type_payload.base),
1964 });
1965 return rlWrap(mod, scope, rl, result);
1961 .val = try Value.Tag.int_type.create(scope.arena(), .{
1962 .signed = is_signed,
1963 .bits = bit_count,
1964 }),
1965 }));
19661966 },
19671967 };
19681968 const result = try addZIRInstConst(mod, scope, src, .{
......@@ -2062,11 +2062,9 @@ fn charLiteral(mod: *Module, scope: *Scope, node: *ast.Node.OneToken) !*zir.Inst
20622062 },
20632063 };
20642064
2065 const int_payload = try scope.arena().create(Value.Payload.Int_u64);
2066 int_payload.* = .{ .int = value };
20672065 return addZIRInstConst(mod, scope, src, .{
20682066 .ty = Type.initTag(.comptime_int),
2069 .val = Value.initPayload(&int_payload.base),
2067 .val = try Value.Tag.int_u64.create(scope.arena(), value),
20702068 });
20712069}
20722070
......@@ -2089,12 +2087,10 @@ fn integerLiteral(mod: *Module, scope: *Scope, int_lit: *ast.Node.OneToken) Inne
20892087 prefixed_bytes[2..];
20902088
20912089 if (std.fmt.parseInt(u64, bytes, base)) |small_int| {
2092 const int_payload = try arena.create(Value.Payload.Int_u64);
2093 int_payload.* = .{ .int = small_int };
20942090 const src = tree.token_locs[int_lit.token].start;
20952091 return addZIRInstConst(mod, scope, src, .{
20962092 .ty = Type.initTag(.comptime_int),
2097 .val = Value.initPayload(&int_payload.base),
2093 .val = try Value.Tag.int_u64.create(arena, small_int),
20982094 });
20992095 } else |err| {
21002096 return mod.failTok(scope, int_lit.token, "TODO implement int literals that don't fit in a u64", .{});
......@@ -2109,15 +2105,13 @@ fn floatLiteral(mod: *Module, scope: *Scope, float_lit: *ast.Node.OneToken) Inne
21092105 return mod.failTok(scope, float_lit.token, "TODO hex floats", .{});
21102106 }
21112107
2112 const val = std.fmt.parseFloat(f128, bytes) catch |e| switch (e) {
2108 const float_number = std.fmt.parseFloat(f128, bytes) catch |e| switch (e) {
21132109 error.InvalidCharacter => unreachable, // validated by tokenizer
21142110 };
2115 const float_payload = try arena.create(Value.Payload.Float_128);
2116 float_payload.* = .{ .val = val };
21172111 const src = tree.token_locs[float_lit.token].start;
21182112 return addZIRInstConst(mod, scope, src, .{
21192113 .ty = Type.initTag(.comptime_float),
2120 .val = Value.initPayload(&float_payload.base),
2114 .val = try Value.Tag.float_128.create(arena, float_number),
21212115 });
21222116}
21232117
src/codegen.zig+26-26
......@@ -137,7 +137,7 @@ pub fn generateSymbol(
137137 },
138138 .Array => {
139139 // TODO populate .debug_info for the array
140 if (typed_value.val.cast(Value.Payload.Bytes)) |payload| {
140 if (typed_value.val.castTag(.bytes)) |payload| {
141141 if (typed_value.ty.sentinel()) |sentinel| {
142142 try code.ensureCapacity(code.items.len + payload.data.len + 1);
143143 code.appendSliceAssumeCapacity(payload.data);
......@@ -168,8 +168,8 @@ pub fn generateSymbol(
168168 },
169169 .Pointer => {
170170 // TODO populate .debug_info for the pointer
171 if (typed_value.val.cast(Value.Payload.DeclRef)) |payload| {
172 const decl = payload.decl;
171 if (typed_value.val.castTag(.decl_ref)) |payload| {
172 const decl = payload.data;
173173 if (decl.analysis != .complete) return error.AnalysisFail;
174174 // TODO handle the dependency of this symbol on the decl's vaddr.
175175 // If the decl changes vaddr, then this symbol needs to get regenerated.
......@@ -432,7 +432,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
432432 @panic("Attempted to compile for architecture that was disabled by build configuration");
433433 }
434434
435 const module_fn = typed_value.val.cast(Value.Payload.Function).?.func;
435 const module_fn = typed_value.val.castTag(.function).?.data;
436436
437437 const fn_type = module_fn.owner_decl.typed_value.most_recent.typed_value.ty;
438438
......@@ -1579,9 +1579,9 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
15791579 }
15801580 }
15811581
1582 if (inst.func.cast(ir.Inst.Constant)) |func_inst| {
1583 if (func_inst.val.cast(Value.Payload.Function)) |func_val| {
1584 const func = func_val.func;
1582 if (inst.func.value()) |func_value| {
1583 if (func_value.castTag(.function)) |func_payload| {
1584 const func = func_payload.data;
15851585
15861586 const ptr_bits = self.target.cpu.arch.ptrBitWidth();
15871587 const ptr_bytes: u64 = @divExact(ptr_bits, 8);
......@@ -1607,9 +1607,9 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
16071607 .riscv64 => {
16081608 if (info.args.len > 0) return self.fail(inst.base.src, "TODO implement fn args for {}", .{self.target.cpu.arch});
16091609
1610 if (inst.func.cast(ir.Inst.Constant)) |func_inst| {
1611 if (func_inst.val.cast(Value.Payload.Function)) |func_val| {
1612 const func = func_val.func;
1610 if (inst.func.value()) |func_value| {
1611 if (func_value.castTag(.function)) |func_payload| {
1612 const func = func_payload.data;
16131613
16141614 const ptr_bits = self.target.cpu.arch.ptrBitWidth();
16151615 const ptr_bytes: u64 = @divExact(ptr_bits, 8);
......@@ -1631,12 +1631,12 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
16311631 }
16321632 },
16331633 .spu_2 => {
1634 if (inst.func.cast(ir.Inst.Constant)) |func_inst| {
1634 if (inst.func.value()) |func_value| {
16351635 if (info.args.len != 0) {
16361636 return self.fail(inst.base.src, "TODO implement call with more than 0 parameters", .{});
16371637 }
1638 if (func_inst.val.cast(Value.Payload.Function)) |func_val| {
1639 const func = func_val.func;
1638 if (func_value.castTag(.function)) |func_payload| {
1639 const func = func_payload.data;
16401640 const got_addr = if (self.bin_file.cast(link.File.Elf)) |elf_file| blk: {
16411641 const got = &elf_file.program_headers.items[elf_file.phdr_got_index.?];
16421642 break :blk @intCast(u16, got.p_vaddr + func.owner_decl.link.elf.offset_table_index * 2);
......@@ -1705,9 +1705,9 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
17051705 }
17061706 }
17071707
1708 if (inst.func.cast(ir.Inst.Constant)) |func_inst| {
1709 if (func_inst.val.cast(Value.Payload.Function)) |func_val| {
1710 const func = func_val.func;
1708 if (inst.func.value()) |func_value| {
1709 if (func_value.castTag(.function)) |func_payload| {
1710 const func = func_payload.data;
17111711 const ptr_bits = self.target.cpu.arch.ptrBitWidth();
17121712 const ptr_bytes: u64 = @divExact(ptr_bits, 8);
17131713 const got_addr = if (self.bin_file.cast(link.File.Elf)) |elf_file| blk: {
......@@ -1766,9 +1766,9 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
17661766 }
17671767 }
17681768
1769 if (inst.func.cast(ir.Inst.Constant)) |func_inst| {
1770 if (func_inst.val.cast(Value.Payload.Function)) |func_val| {
1771 const func = func_val.func;
1769 if (inst.func.value()) |func_value| {
1770 if (func_value.castTag(.function)) |func_payload| {
1771 const func = func_payload.data;
17721772 const ptr_bits = self.target.cpu.arch.ptrBitWidth();
17731773 const ptr_bytes: u64 = @divExact(ptr_bits, 8);
17741774 const got_addr = if (self.bin_file.cast(link.File.Elf)) |elf_file| blk: {
......@@ -1825,9 +1825,9 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
18251825 }
18261826 }
18271827
1828 if (inst.func.cast(ir.Inst.Constant)) |func_inst| {
1829 if (func_inst.val.cast(Value.Payload.Function)) |func_val| {
1830 const func = func_val.func;
1828 if (inst.func.value()) |func_value| {
1829 if (func_value.castTag(.function)) |func_payload| {
1830 const func = func_payload.data;
18311831 const text_segment = &macho_file.load_commands.items[macho_file.text_segment_cmd_index.?].Segment;
18321832 const got = &text_segment.sections.items[macho_file.got_section_index.?];
18331833 const got_addr = got.addr + func.owner_decl.link.macho.offset_table_index * @sizeOf(u64);
......@@ -3223,20 +3223,20 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
32233223 const ptr_bytes: u64 = @divExact(ptr_bits, 8);
32243224 switch (typed_value.ty.zigTypeTag()) {
32253225 .Pointer => {
3226 if (typed_value.val.cast(Value.Payload.DeclRef)) |payload| {
3226 if (typed_value.val.castTag(.decl_ref)) |payload| {
32273227 if (self.bin_file.cast(link.File.Elf)) |elf_file| {
3228 const decl = payload.decl;
3228 const decl = payload.data;
32293229 const got = &elf_file.program_headers.items[elf_file.phdr_got_index.?];
32303230 const got_addr = got.p_vaddr + decl.link.elf.offset_table_index * ptr_bytes;
32313231 return MCValue{ .memory = got_addr };
32323232 } else if (self.bin_file.cast(link.File.MachO)) |macho_file| {
3233 const decl = payload.decl;
3233 const decl = payload.data;
32343234 const text_segment = &macho_file.load_commands.items[macho_file.text_segment_cmd_index.?].Segment;
32353235 const got = &text_segment.sections.items[macho_file.got_section_index.?];
32363236 const got_addr = got.addr + decl.link.macho.offset_table_index * ptr_bytes;
32373237 return MCValue{ .memory = got_addr };
32383238 } else if (self.bin_file.cast(link.File.Coff)) |coff_file| {
3239 const decl = payload.decl;
3239 const decl = payload.data;
32403240 const got_addr = coff_file.offset_table_virtual_address + decl.link.coff.offset_table_index * ptr_bytes;
32413241 return MCValue{ .memory = got_addr };
32423242 } else {
src/codegen/c.zig+18-18
......@@ -138,25 +138,25 @@ fn renderValue(
138138 .undef, .zero => try writer.writeAll("0"),
139139 .one => try writer.writeAll("1"),
140140 .decl_ref => {
141 const decl_ref_payload = val.cast(Value.Payload.DeclRef).?;
141 const decl = val.castTag(.decl_ref).?.data;
142142
143143 // Determine if we must pointer cast.
144 const decl_tv = decl_ref_payload.decl.typed_value.most_recent.typed_value;
144 const decl_tv = decl.typed_value.most_recent.typed_value;
145145 if (t.eql(decl_tv.ty)) {
146 try writer.print("&{s}", .{decl_ref_payload.decl.name});
146 try writer.print("&{s}", .{decl.name});
147147 } else {
148148 try writer.writeAll("(");
149149 try renderType(ctx, writer, t);
150 try writer.print(")&{s}", .{decl_ref_payload.decl.name});
150 try writer.print(")&{s}", .{decl.name});
151151 }
152152 },
153153 .function => {
154 const payload = val.cast(Value.Payload.Function).?;
155 try writer.print("{s}", .{payload.func.owner_decl.name});
154 const func = val.castTag(.function).?.data;
155 try writer.print("{s}", .{func.owner_decl.name});
156156 },
157157 .extern_fn => {
158 const payload = val.cast(Value.Payload.ExternFn).?;
159 try writer.print("{s}", .{payload.decl.name});
158 const decl = val.castTag(.extern_fn).?.data;
159 try writer.print("{s}", .{decl.name});
160160 },
161161 else => |e| return ctx.fail(
162162 ctx.decl.src(),
......@@ -169,7 +169,7 @@ fn renderValue(
169169 switch (val.tag()) {
170170 .undef, .empty_struct_value, .empty_array => try writer.writeAll("{}"),
171171 .bytes => {
172 const bytes = val.cast(Value.Payload.Bytes).?.data;
172 const bytes = val.castTag(.bytes).?.data;
173173 // TODO: make our own C string escape instead of using {Z}
174174 try writer.print("\"{Z}\"", .{bytes});
175175 },
......@@ -209,7 +209,7 @@ fn renderFunctionSignature(
209209 switch (tv.val.tag()) {
210210 .extern_fn => break :blk true,
211211 .function => {
212 const func = tv.val.cast(Value.Payload.Function).?.func;
212 const func = tv.val.castTag(.function).?.data;
213213 break :blk ctx.module.decl_exports.contains(func.owner_decl);
214214 },
215215 else => unreachable,
......@@ -268,13 +268,13 @@ pub fn generate(file: *C, module: *Module, decl: *Decl) !void {
268268 ctx.deinit();
269269 }
270270
271 if (tv.val.cast(Value.Payload.Function)) |func_payload| {
271 if (tv.val.castTag(.function)) |func_payload| {
272272 const writer = file.main.writer();
273273 try renderFunctionSignature(&ctx, writer, decl);
274274
275275 try writer.writeAll(" {");
276276
277 const func: *Module.Fn = func_payload.func;
277 const func: *Module.Fn = func_payload.data;
278278 const instructions = func.analysis.success.instructions;
279279 if (instructions.len > 0) {
280280 try writer.writeAll("\n");
......@@ -480,10 +480,10 @@ fn genCall(ctx: *Context, file: *C, inst: *Inst.Call) !?[]u8 {
480480 const writer = file.main.writer();
481481 const header = file.header.buf.writer();
482482 if (inst.func.castTag(.constant)) |func_inst| {
483 const fn_decl = if (func_inst.val.cast(Value.Payload.ExternFn)) |extern_fn|
484 extern_fn.decl
485 else if (func_inst.val.cast(Value.Payload.Function)) |func_val|
486 func_val.func.owner_decl
483 const fn_decl = if (func_inst.val.castTag(.extern_fn)) |extern_fn|
484 extern_fn.data
485 else if (func_inst.val.castTag(.function)) |func_payload|
486 func_payload.data.owner_decl
487487 else
488488 unreachable;
489489
......@@ -513,8 +513,8 @@ fn genCall(ctx: *Context, file: *C, inst: *Inst.Call) !?[]u8 {
513513 if (i > 0) {
514514 try writer.writeAll(", ");
515515 }
516 if (arg.cast(Inst.Constant)) |con| {
517 try renderValue(ctx, writer, arg.ty, con.val);
516 if (arg.value()) |val| {
517 try renderValue(ctx, writer, arg.ty, val);
518518 } else {
519519 const val = try ctx.resolveInst(arg);
520520 try writer.print("{}", .{val});
src/codegen/wasm.zig+3-3
......@@ -62,7 +62,7 @@ pub fn genCode(buf: *ArrayList(u8), decl: *Decl) !void {
6262 // Write instructions
6363 // TODO: check for and handle death of instructions
6464 const tv = decl.typed_value.most_recent.typed_value;
65 const mod_fn = tv.val.cast(Value.Payload.Function).?.func;
65 const mod_fn = tv.val.castTag(.function).?.data;
6666 for (mod_fn.analysis.success.instructions) |inst| try genInst(buf, decl, inst);
6767
6868 // Write 'end' opcode
......@@ -125,8 +125,8 @@ fn genRet(buf: *ArrayList(u8), decl: *Decl, inst: *Inst.UnOp) !void {
125125
126126fn genCall(buf: *ArrayList(u8), decl: *Decl, inst: *Inst.Call) !void {
127127 const func_inst = inst.func.castTag(.constant).?;
128 const func_val = func_inst.val.cast(Value.Payload.Function).?;
129 const target = func_val.func.owner_decl;
128 const func = func_inst.val.castTag(.function).?.data;
129 const target = func.owner_decl;
130130 const target_ty = target.typed_value.most_recent.typed_value.ty;
131131
132132 if (inst.args.len != 0) return error.TODOImplementMoreWasmCodegen;
src/link/Elf.zig+1-1
......@@ -2183,7 +2183,7 @@ pub fn updateDecl(self: *Elf, module: *Module, decl: *Module.Decl) !void {
21832183 for (zir_dumps) |fn_name| {
21842184 if (mem.eql(u8, mem.spanZ(decl.name), fn_name)) {
21852185 std.debug.print("\n{}\n", .{decl.name});
2186 typed_value.val.cast(Value.Payload.Function).?.func.dump(module.*);
2186 typed_value.val.castTag(.function).?.data.dump(module.*);
21872187 }
21882188 }
21892189 }
src/llvm_backend.zig+4-4
......@@ -280,7 +280,7 @@ pub const LLVMIRModule = struct {
280280 fn gen(self: *LLVMIRModule, module: *Module, typed_value: TypedValue, src: usize) !void {
281281 switch (typed_value.ty.zigTypeTag()) {
282282 .Fn => {
283 const func = typed_value.val.cast(Value.Payload.Function).?.func;
283 const func = typed_value.val.castTag(.function).?.data;
284284
285285 const llvm_func = try self.resolveLLVMFunction(func);
286286
......@@ -314,9 +314,9 @@ pub const LLVMIRModule = struct {
314314 }
315315
316316 fn genCall(self: *LLVMIRModule, inst: *Inst.Call) !void {
317 if (inst.func.cast(Inst.Constant)) |func_inst| {
318 if (func_inst.val.cast(Value.Payload.Function)) |func_val| {
319 const func = func_val.func;
317 if (inst.func.value()) |func_value| {
318 if (func_value.castTag(.function)) |func_payload| {
319 const func = func_payload.data;
320320 const zig_fn_type = func.owner_decl.typed_value.most_recent.typed_value.ty;
321321 const llvm_fn = try self.resolveLLVMFunction(func);
322322
src/type.zig+11-32
......@@ -733,11 +733,7 @@ pub const Type = extern union {
733733 .single_const_pointer_to_comptime_int => return Value.initTag(.single_const_pointer_to_comptime_int_type),
734734 .const_slice_u8 => return Value.initTag(.const_slice_u8_type),
735735 .enum_literal => return Value.initTag(.enum_literal_type),
736 else => {
737 const ty_payload = try allocator.create(Value.Payload.Ty);
738 ty_payload.* = .{ .ty = self };
739 return Value.initPayload(&ty_payload.base);
740 },
736 else => return Value.Tag.ty.create(allocator, self),
741737 }
742738 }
743739
......@@ -2951,11 +2947,8 @@ pub const Type = extern union {
29512947 }
29522948
29532949 if ((info.bits - 1) <= std.math.maxInt(u6)) {
2954 const payload = try arena.allocator.create(Value.Payload.Int_i64);
2955 payload.* = .{
2956 .int = -(@as(i64, 1) << @truncate(u6, info.bits - 1)),
2957 };
2958 return Value.initPayload(&payload.base);
2950 const n: i64 = -(@as(i64, 1) << @truncate(u6, info.bits - 1));
2951 return Value.Tag.int_i64.create(&arena.allocator, n);
29592952 }
29602953
29612954 var res = try std.math.big.int.Managed.initSet(&arena.allocator, 1);
......@@ -2964,13 +2957,9 @@ pub const Type = extern union {
29642957
29652958 const res_const = res.toConst();
29662959 if (res_const.positive) {
2967 const val_payload = try arena.allocator.create(Value.Payload.IntBigPositive);
2968 val_payload.* = .{ .limbs = res_const.limbs };
2969 return Value.initPayload(&val_payload.base);
2960 return Value.Tag.int_big_positive.create(&arena.allocator, res_const.limbs);
29702961 } else {
2971 const val_payload = try arena.allocator.create(Value.Payload.IntBigNegative);
2972 val_payload.* = .{ .limbs = res_const.limbs };
2973 return Value.initPayload(&val_payload.base);
2962 return Value.Tag.int_big_negative.create(&arena.allocator, res_const.limbs);
29742963 }
29752964 }
29762965
......@@ -2980,17 +2969,11 @@ pub const Type = extern union {
29802969 const info = self.intInfo(target);
29812970
29822971 if (info.signedness == .signed and (info.bits - 1) <= std.math.maxInt(u6)) {
2983 const payload = try arena.allocator.create(Value.Payload.Int_i64);
2984 payload.* = .{
2985 .int = (@as(i64, 1) << @truncate(u6, info.bits - 1)) - 1,
2986 };
2987 return Value.initPayload(&payload.base);
2972 const n: i64 = (@as(i64, 1) << @truncate(u6, info.bits - 1)) - 1;
2973 return Value.Tag.int_i64.create(&arena.allocator, n);
29882974 } else if (info.signedness == .signed and info.bits <= std.math.maxInt(u6)) {
2989 const payload = try arena.allocator.create(Value.Payload.Int_u64);
2990 payload.* = .{
2991 .int = (@as(u64, 1) << @truncate(u6, info.bits)) - 1,
2992 };
2993 return Value.initPayload(&payload.base);
2975 const n: u64 = (@as(u64, 1) << @truncate(u6, info.bits)) - 1;
2976 return Value.Tag.int_u64.create(&arena.allocator, n);
29942977 }
29952978
29962979 var res = try std.math.big.int.Managed.initSet(&arena.allocator, 1);
......@@ -3003,13 +2986,9 @@ pub const Type = extern union {
30032986
30042987 const res_const = res.toConst();
30052988 if (res_const.positive) {
3006 const val_payload = try arena.allocator.create(Value.Payload.IntBigPositive);
3007 val_payload.* = .{ .limbs = res_const.limbs };
3008 return Value.initPayload(&val_payload.base);
2989 return Value.Tag.int_big_positive.create(&arena.allocator, res_const.limbs);
30092990 } else {
3010 const val_payload = try arena.allocator.create(Value.Payload.IntBigNegative);
3011 val_payload.* = .{ .limbs = res_const.limbs };
3012 return Value.initPayload(&val_payload.base);
2991 return Value.Tag.int_big_negative.create(&arena.allocator, res_const.limbs);
30132992 }
30142993 }
30152994
src/value.zig+363-236
......@@ -84,11 +84,16 @@ pub const Value = extern union {
8484 function,
8585 extern_fn,
8686 variable,
87 /// Represents a pointer to another immutable value.
8788 ref_val,
89 /// Represents a pointer to a decl, not the value of the decl.
8890 decl_ref,
8991 elem_ptr,
92 /// A slice of u8 whose memory is managed externally.
9093 bytes,
91 repeated, // the value is a value repeated some number of times
94 /// This value is repeated some number of times. The amount of times to repeat
95 /// is stored externally.
96 repeated,
9297 float_16,
9398 float_32,
9499 float_64,
......@@ -99,6 +104,106 @@ pub const Value = extern union {
99104
100105 pub const last_no_payload_tag = Tag.bool_false;
101106 pub const no_payload_count = @enumToInt(last_no_payload_tag) + 1;
107
108 pub fn Type(comptime t: Tag) type {
109 return switch (t) {
110 .u8_type,
111 .i8_type,
112 .u16_type,
113 .i16_type,
114 .u32_type,
115 .i32_type,
116 .u64_type,
117 .i64_type,
118 .usize_type,
119 .isize_type,
120 .c_short_type,
121 .c_ushort_type,
122 .c_int_type,
123 .c_uint_type,
124 .c_long_type,
125 .c_ulong_type,
126 .c_longlong_type,
127 .c_ulonglong_type,
128 .c_longdouble_type,
129 .f16_type,
130 .f32_type,
131 .f64_type,
132 .f128_type,
133 .c_void_type,
134 .bool_type,
135 .void_type,
136 .type_type,
137 .anyerror_type,
138 .comptime_int_type,
139 .comptime_float_type,
140 .noreturn_type,
141 .null_type,
142 .undefined_type,
143 .fn_noreturn_no_args_type,
144 .fn_void_no_args_type,
145 .fn_naked_noreturn_no_args_type,
146 .fn_ccc_void_no_args_type,
147 .single_const_pointer_to_comptime_int_type,
148 .const_slice_u8_type,
149 .enum_literal_type,
150 .anyframe_type,
151 .undef,
152 .zero,
153 .one,
154 .void_value,
155 .unreachable_value,
156 .empty_struct_value,
157 .empty_array,
158 .null_value,
159 .bool_true,
160 .bool_false,
161 => @compileError("Value Tag " ++ @tagName(t) ++ " has no payload"),
162
163 .int_big_positive,
164 .int_big_negative,
165 => Payload.BigInt,
166
167 .extern_fn,
168 .decl_ref,
169 => Payload.Decl,
170
171 .ref_val,
172 .repeated,
173 => Payload.SubValue,
174
175 .bytes,
176 .enum_literal,
177 => Payload.Bytes,
178
179 .ty => Payload.Ty,
180 .int_type => Payload.IntType,
181 .int_u64 => Payload.U64,
182 .int_i64 => Payload.I64,
183 .function => Payload.Function,
184 .variable => Payload.Variable,
185 .elem_ptr => Payload.ElemPtr,
186 .float_16 => Payload.Float_16,
187 .float_32 => Payload.Float_32,
188 .float_64 => Payload.Float_64,
189 .float_128 => Payload.Float_128,
190 .error_set => Payload.ErrorSet,
191 .@"error" => Payload.Error,
192 };
193 }
194
195 pub fn create(comptime t: Tag, ally: *Allocator, data: Data(t)) error{OutOfMemory}!Value {
196 const ptr = try ally.create(t.Type());
197 ptr.* = .{
198 .base = .{ .tag = t },
199 .data = data,
200 };
201 return Value{ .ptr_otherwise = &ptr.base };
202 }
203
204 pub fn Data(comptime t: Tag) type {
205 return std.meta.fieldInfo(t.Type(), "data").field_type;
206 }
102207 };
103208
104209 pub fn initTag(small_tag: Tag) Value {
......@@ -119,15 +224,36 @@ pub const Value = extern union {
119224 }
120225 }
121226
227 /// Prefer `castTag` to this.
122228 pub fn cast(self: Value, comptime T: type) ?*T {
123 if (self.tag_if_small_enough < Tag.no_payload_count)
229 if (@hasField(T, "base_tag")) {
230 return base.castTag(T.base_tag);
231 }
232 if (self.tag_if_small_enough < Tag.no_payload_count) {
124233 return null;
234 }
235 inline for (@typeInfo(Tag).Enum.fields) |field| {
236 if (field.value < Tag.no_payload_count)
237 continue;
238 const t = @intToEnum(Tag, field.value);
239 if (self.ptr_otherwise.tag == t) {
240 if (T == t.Type()) {
241 return @fieldParentPtr(T, "base", self.ptr_otherwise);
242 }
243 return null;
244 }
245 }
246 unreachable;
247 }
125248
126 const expected_tag = std.meta.fieldInfo(T, "base").default_value.?.tag;
127 if (self.ptr_otherwise.tag != expected_tag)
249 pub fn castTag(self: Value, comptime t: Tag) ?*t.Type() {
250 if (self.tag_if_small_enough < Tag.no_payload_count)
128251 return null;
129252
130 return @fieldParentPtr(T, "base", self.ptr_otherwise);
253 if (self.ptr_otherwise.tag == t)
254 return @fieldParentPtr(t.Type(), "base", self.ptr_otherwise);
255
256 return null;
131257 }
132258
133259 pub fn copy(self: Value, allocator: *Allocator) error{OutOfMemory}!Value {
......@@ -188,17 +314,17 @@ pub const Value = extern union {
188314 => unreachable,
189315
190316 .ty => {
191 const payload = @fieldParentPtr(Payload.Ty, "base", self.ptr_otherwise);
317 const payload = self.castTag(.ty).?;
192318 const new_payload = try allocator.create(Payload.Ty);
193319 new_payload.* = .{
194320 .base = payload.base,
195 .ty = try payload.ty.copy(allocator),
321 .data = try payload.data.copy(allocator),
196322 };
197323 return Value{ .ptr_otherwise = &new_payload.base };
198324 },
199325 .int_type => return self.copyPayloadShallow(allocator, Payload.IntType),
200 .int_u64 => return self.copyPayloadShallow(allocator, Payload.Int_u64),
201 .int_i64 => return self.copyPayloadShallow(allocator, Payload.Int_i64),
326 .int_u64 => return self.copyPayloadShallow(allocator, Payload.U64),
327 .int_i64 => return self.copyPayloadShallow(allocator, Payload.I64),
202328 .int_big_positive => {
203329 @panic("TODO implement copying of big ints");
204330 },
......@@ -206,35 +332,37 @@ pub const Value = extern union {
206332 @panic("TODO implement copying of big ints");
207333 },
208334 .function => return self.copyPayloadShallow(allocator, Payload.Function),
209 .extern_fn => return self.copyPayloadShallow(allocator, Payload.ExternFn),
335 .extern_fn => return self.copyPayloadShallow(allocator, Payload.Decl),
210336 .variable => return self.copyPayloadShallow(allocator, Payload.Variable),
211337 .ref_val => {
212 const payload = @fieldParentPtr(Payload.RefVal, "base", self.ptr_otherwise);
213 const new_payload = try allocator.create(Payload.RefVal);
338 const payload = self.castTag(.ref_val).?;
339 const new_payload = try allocator.create(Payload.SubValue);
214340 new_payload.* = .{
215341 .base = payload.base,
216 .val = try payload.val.copy(allocator),
342 .data = try payload.data.copy(allocator),
217343 };
218344 return Value{ .ptr_otherwise = &new_payload.base };
219345 },
220 .decl_ref => return self.copyPayloadShallow(allocator, Payload.DeclRef),
346 .decl_ref => return self.copyPayloadShallow(allocator, Payload.Decl),
221347 .elem_ptr => {
222 const payload = @fieldParentPtr(Payload.ElemPtr, "base", self.ptr_otherwise);
348 const payload = self.castTag(.elem_ptr).?;
223349 const new_payload = try allocator.create(Payload.ElemPtr);
224350 new_payload.* = .{
225351 .base = payload.base,
226 .array_ptr = try payload.array_ptr.copy(allocator),
227 .index = payload.index,
352 .data = .{
353 .array_ptr = try payload.data.array_ptr.copy(allocator),
354 .index = payload.data.index,
355 },
228356 };
229357 return Value{ .ptr_otherwise = &new_payload.base };
230358 },
231359 .bytes => return self.copyPayloadShallow(allocator, Payload.Bytes),
232360 .repeated => {
233 const payload = @fieldParentPtr(Payload.Repeated, "base", self.ptr_otherwise);
234 const new_payload = try allocator.create(Payload.Repeated);
361 const payload = self.castTag(.repeated).?;
362 const new_payload = try allocator.create(Payload.SubValue);
235363 new_payload.* = .{
236364 .base = payload.base,
237 .val = try payload.val.copy(allocator),
365 .data = try payload.data.copy(allocator),
238366 };
239367 return Value{ .ptr_otherwise = &new_payload.base };
240368 },
......@@ -243,7 +371,7 @@ pub const Value = extern union {
243371 .float_64 => return self.copyPayloadShallow(allocator, Payload.Float_64),
244372 .float_128 => return self.copyPayloadShallow(allocator, Payload.Float_128),
245373 .enum_literal => {
246 const payload = @fieldParentPtr(Payload.Bytes, "base", self.ptr_otherwise);
374 const payload = self.castTag(.enum_literal).?;
247375 const new_payload = try allocator.create(Payload.Bytes);
248376 new_payload.* = .{
249377 .base = payload.base,
......@@ -259,7 +387,7 @@ pub const Value = extern union {
259387 }
260388
261389 fn copyPayloadShallow(self: Value, allocator: *Allocator, comptime T: type) error{OutOfMemory}!Value {
262 const payload = @fieldParentPtr(T, "base", self.ptr_otherwise);
390 const payload = self.cast(T).?;
263391 const new_payload = try allocator.create(T);
264392 new_payload.* = payload.*;
265393 return Value{ .ptr_otherwise = &new_payload.base };
......@@ -326,45 +454,45 @@ pub const Value = extern union {
326454 .unreachable_value => return out_stream.writeAll("unreachable"),
327455 .bool_true => return out_stream.writeAll("true"),
328456 .bool_false => return out_stream.writeAll("false"),
329 .ty => return val.cast(Payload.Ty).?.ty.format("", options, out_stream),
457 .ty => return val.castTag(.ty).?.data.format("", options, out_stream),
330458 .int_type => {
331 const int_type = val.cast(Payload.IntType).?;
459 const int_type = val.castTag(.int_type).?.data;
332460 return out_stream.print("{}{}", .{
333461 if (int_type.signed) "s" else "u",
334462 int_type.bits,
335463 });
336464 },
337 .int_u64 => return std.fmt.formatIntValue(val.cast(Payload.Int_u64).?.int, "", options, out_stream),
338 .int_i64 => return std.fmt.formatIntValue(val.cast(Payload.Int_i64).?.int, "", options, out_stream),
339 .int_big_positive => return out_stream.print("{}", .{val.cast(Payload.IntBigPositive).?.asBigInt()}),
340 .int_big_negative => return out_stream.print("{}", .{val.cast(Payload.IntBigNegative).?.asBigInt()}),
465 .int_u64 => return std.fmt.formatIntValue(val.castTag(.int_u64).?.data, "", options, out_stream),
466 .int_i64 => return std.fmt.formatIntValue(val.castTag(.int_i64).?.data, "", options, out_stream),
467 .int_big_positive => return out_stream.print("{}", .{val.castTag(.int_big_positive).?.asBigInt()}),
468 .int_big_negative => return out_stream.print("{}", .{val.castTag(.int_big_negative).?.asBigInt()}),
341469 .function => return out_stream.writeAll("(function)"),
342470 .extern_fn => return out_stream.writeAll("(extern function)"),
343471 .variable => return out_stream.writeAll("(variable)"),
344472 .ref_val => {
345 const ref_val = val.cast(Payload.RefVal).?;
473 const ref_val = val.castTag(.ref_val).?.data;
346474 try out_stream.writeAll("&const ");
347 val = ref_val.val;
475 val = ref_val;
348476 },
349477 .decl_ref => return out_stream.writeAll("(decl ref)"),
350478 .elem_ptr => {
351 const elem_ptr = val.cast(Payload.ElemPtr).?;
479 const elem_ptr = val.castTag(.elem_ptr).?.data;
352480 try out_stream.print("&[{}] ", .{elem_ptr.index});
353481 val = elem_ptr.array_ptr;
354482 },
355483 .empty_array => return out_stream.writeAll(".{}"),
356 .enum_literal => return out_stream.print(".{z}", .{self.cast(Payload.Bytes).?.data}),
357 .bytes => return out_stream.print("\"{Z}\"", .{self.cast(Payload.Bytes).?.data}),
484 .enum_literal => return out_stream.print(".{z}", .{self.castTag(.enum_literal).?.data}),
485 .bytes => return out_stream.print("\"{Z}\"", .{self.castTag(.bytes).?.data}),
358486 .repeated => {
359487 try out_stream.writeAll("(repeated) ");
360 val = val.cast(Payload.Repeated).?.val;
488 val = val.castTag(.repeated).?.data;
361489 },
362 .float_16 => return out_stream.print("{}", .{val.cast(Payload.Float_16).?.val}),
363 .float_32 => return out_stream.print("{}", .{val.cast(Payload.Float_32).?.val}),
364 .float_64 => return out_stream.print("{}", .{val.cast(Payload.Float_64).?.val}),
365 .float_128 => return out_stream.print("{}", .{val.cast(Payload.Float_128).?.val}),
490 .float_16 => return out_stream.print("{}", .{val.castTag(.float_16).?.data}),
491 .float_32 => return out_stream.print("{}", .{val.castTag(.float_32).?.data}),
492 .float_64 => return out_stream.print("{}", .{val.castTag(.float_64).?.data}),
493 .float_128 => return out_stream.print("{}", .{val.castTag(.float_128).?.data}),
366494 .error_set => {
367 const error_set = val.cast(Payload.ErrorSet).?;
495 const error_set = val.castTag(.error_set).?.data;
368496 try out_stream.writeAll("error{");
369497 var it = error_set.fields.iterator();
370498 while (it.next()) |entry| {
......@@ -372,21 +500,24 @@ pub const Value = extern union {
372500 }
373501 return out_stream.writeAll("}");
374502 },
375 .@"error" => return out_stream.print("error.{}", .{val.cast(Payload.Error).?.name}),
503 .@"error" => return out_stream.print("error.{}", .{val.castTag(.@"error").?.data.name}),
376504 };
377505 }
378506
379507 /// Asserts that the value is representable as an array of bytes.
380508 /// Copies the value into a freshly allocated slice of memory, which is owned by the caller.
381509 pub fn toAllocatedBytes(self: Value, allocator: *Allocator) ![]u8 {
382 if (self.cast(Payload.Bytes)) |bytes| {
383 return std.mem.dupe(allocator, u8, bytes.data);
510 if (self.castTag(.bytes)) |payload| {
511 return std.mem.dupe(allocator, u8, payload.data);
384512 }
385 if (self.cast(Payload.Repeated)) |repeated| {
513 if (self.castTag(.enum_literal)) |payload| {
514 return std.mem.dupe(allocator, u8, payload.data);
515 }
516 if (self.castTag(.repeated)) |payload| {
386517 @panic("TODO implement toAllocatedBytes for this Value tag");
387518 }
388 if (self.cast(Payload.DeclRef)) |declref| {
389 const val = try declref.decl.value();
519 if (self.castTag(.decl_ref)) |payload| {
520 const val = try payload.data.value();
390521 return val.toAllocatedBytes(allocator);
391522 }
392523 unreachable;
......@@ -395,7 +526,7 @@ pub const Value = extern union {
395526 /// Asserts that the value is representable as a type.
396527 pub fn toType(self: Value, allocator: *Allocator) !Type {
397528 return switch (self.tag()) {
398 .ty => self.cast(Payload.Ty).?.ty,
529 .ty => self.castTag(.ty).?.data,
399530 .u8_type => Type.initTag(.u8),
400531 .i8_type => Type.initTag(.i8),
401532 .u16_type => Type.initTag(.u16),
......@@ -439,7 +570,7 @@ pub const Value = extern union {
439570 .anyframe_type => Type.initTag(.@"anyframe"),
440571
441572 .int_type => {
442 const payload = self.cast(Payload.IntType).?;
573 const payload = self.castTag(.int_type).?.data;
443574 const new = try allocator.create(Type.Payload.Bits);
444575 new.* = .{
445576 .base = .{
......@@ -450,7 +581,7 @@ pub const Value = extern union {
450581 return Type.initPayload(&new.base);
451582 },
452583 .error_set => {
453 const payload = self.cast(Payload.ErrorSet).?;
584 const payload = self.castTag(.error_set).?.data;
454585 return Type.Tag.error_set.create(allocator, payload.decl);
455586 },
456587
......@@ -564,10 +695,10 @@ pub const Value = extern union {
564695 .bool_true,
565696 => return BigIntMutable.init(&space.limbs, 1).toConst(),
566697
567 .int_u64 => return BigIntMutable.init(&space.limbs, self.cast(Payload.Int_u64).?.int).toConst(),
568 .int_i64 => return BigIntMutable.init(&space.limbs, self.cast(Payload.Int_i64).?.int).toConst(),
569 .int_big_positive => return self.cast(Payload.IntBigPositive).?.asBigInt(),
570 .int_big_negative => return self.cast(Payload.IntBigNegative).?.asBigInt(),
698 .int_u64 => return BigIntMutable.init(&space.limbs, self.castTag(.int_u64).?.data).toConst(),
699 .int_i64 => return BigIntMutable.init(&space.limbs, self.castTag(.int_i64).?.data).toConst(),
700 .int_big_positive => return self.castTag(.int_big_positive).?.asBigInt(),
701 .int_big_negative => return self.castTag(.int_big_negative).?.asBigInt(),
571702 }
572703 }
573704
......@@ -649,10 +780,10 @@ pub const Value = extern union {
649780 .bool_true,
650781 => return 1,
651782
652 .int_u64 => return self.cast(Payload.Int_u64).?.int,
653 .int_i64 => return @intCast(u64, self.cast(Payload.Int_i64).?.int),
654 .int_big_positive => return self.cast(Payload.IntBigPositive).?.asBigInt().to(u64) catch unreachable,
655 .int_big_negative => return self.cast(Payload.IntBigNegative).?.asBigInt().to(u64) catch unreachable,
783 .int_u64 => return self.castTag(.int_u64).?.data,
784 .int_i64 => return @intCast(u64, self.castTag(.int_i64).?.data),
785 .int_big_positive => return self.castTag(.int_big_positive).?.asBigInt().to(u64) catch unreachable,
786 .int_big_negative => return self.castTag(.int_big_negative).?.asBigInt().to(u64) catch unreachable,
656787 }
657788 }
658789
......@@ -734,10 +865,10 @@ pub const Value = extern union {
734865 .bool_true,
735866 => return 1,
736867
737 .int_u64 => return @intCast(i64, self.cast(Payload.Int_u64).?.int),
738 .int_i64 => return self.cast(Payload.Int_i64).?.int,
739 .int_big_positive => return self.cast(Payload.IntBigPositive).?.asBigInt().to(i64) catch unreachable,
740 .int_big_negative => return self.cast(Payload.IntBigNegative).?.asBigInt().to(i64) catch unreachable,
868 .int_u64 => return @intCast(i64, self.castTag(.int_u64).?.data),
869 .int_i64 => return self.castTag(.int_i64).?.data,
870 .int_big_positive => return self.castTag(.int_big_positive).?.asBigInt().to(i64) catch unreachable,
871 .int_big_negative => return self.castTag(.int_big_negative).?.asBigInt().to(i64) catch unreachable,
741872 }
742873 }
743874
......@@ -753,14 +884,14 @@ pub const Value = extern union {
753884 pub fn toFloat(self: Value, comptime T: type) T {
754885 return switch (self.tag()) {
755886 .float_16 => @panic("TODO soft float"),
756 .float_32 => @floatCast(T, self.cast(Payload.Float_32).?.val),
757 .float_64 => @floatCast(T, self.cast(Payload.Float_64).?.val),
758 .float_128 => @floatCast(T, self.cast(Payload.Float_128).?.val),
887 .float_32 => @floatCast(T, self.castTag(.float_32).?.data),
888 .float_64 => @floatCast(T, self.castTag(.float_64).?.data),
889 .float_128 => @floatCast(T, self.castTag(.float_128).?.data),
759890
760891 .zero => 0,
761892 .one => 1,
762 .int_u64 => @intToFloat(T, self.cast(Payload.Int_u64).?.int),
763 .int_i64 => @intToFloat(T, self.cast(Payload.Int_i64).?.int),
893 .int_u64 => @intToFloat(T, self.castTag(.int_u64).?.data),
894 .int_i64 => @intToFloat(T, self.castTag(.int_i64).?.data),
764895
765896 .int_big_positive, .int_big_negative => @panic("big int to f128"),
766897 else => unreachable,
......@@ -846,15 +977,15 @@ pub const Value = extern union {
846977 => return 1,
847978
848979 .int_u64 => {
849 const x = self.cast(Payload.Int_u64).?.int;
980 const x = self.castTag(.int_u64).?.data;
850981 if (x == 0) return 0;
851982 return @intCast(usize, std.math.log2(x) + 1);
852983 },
853984 .int_i64 => {
854985 @panic("TODO implement i64 intBitCountTwosComp");
855986 },
856 .int_big_positive => return self.cast(Payload.IntBigPositive).?.asBigInt().bitCountTwosComp(),
857 .int_big_negative => return self.cast(Payload.IntBigNegative).?.asBigInt().bitCountTwosComp(),
987 .int_big_positive => return self.castTag(.int_big_positive).?.asBigInt().bitCountTwosComp(),
988 .int_big_negative => return self.castTag(.int_big_negative).?.asBigInt().bitCountTwosComp(),
858989 }
859990 }
860991
......@@ -943,7 +1074,7 @@ pub const Value = extern union {
9431074
9441075 .int_u64 => switch (ty.zigTypeTag()) {
9451076 .Int => {
946 const x = self.cast(Payload.Int_u64).?.int;
1077 const x = self.castTag(.int_u64).?.data;
9471078 if (x == 0) return true;
9481079 const info = ty.intInfo(target);
9491080 const needed_bits = std.math.log2(x) + 1 + @boolToInt(info.signedness == .signed);
......@@ -954,7 +1085,7 @@ pub const Value = extern union {
9541085 },
9551086 .int_i64 => switch (ty.zigTypeTag()) {
9561087 .Int => {
957 const x = self.cast(Payload.Int_i64).?.int;
1088 const x = self.castTag(.int_i64).?.data;
9581089 if (x == 0) return true;
9591090 const info = ty.intInfo(target);
9601091 if (info.signedness == .unsigned and x < 0)
......@@ -967,7 +1098,7 @@ pub const Value = extern union {
9671098 .int_big_positive => switch (ty.zigTypeTag()) {
9681099 .Int => {
9691100 const info = ty.intInfo(target);
970 return self.cast(Payload.IntBigPositive).?.asBigInt().fitsInTwosComp(info.signedness, info.bits);
1101 return self.castTag(.int_big_positive).?.asBigInt().fitsInTwosComp(info.signedness, info.bits);
9711102 },
9721103 .ComptimeInt => return true,
9731104 else => unreachable,
......@@ -975,7 +1106,7 @@ pub const Value = extern union {
9751106 .int_big_negative => switch (ty.zigTypeTag()) {
9761107 .Int => {
9771108 const info = ty.intInfo(target);
978 return self.cast(Payload.IntBigNegative).?.asBigInt().fitsInTwosComp(info.signedness, info.bits);
1109 return self.castTag(.int_big_negative).?.asBigInt().fitsInTwosComp(info.signedness, info.bits);
9791110 },
9801111 .ComptimeInt => return true,
9811112 else => unreachable,
......@@ -986,42 +1117,28 @@ pub const Value = extern union {
9861117 /// Converts an integer or a float to a float.
9871118 /// Returns `error.Overflow` if the value does not fit in the new type.
9881119 pub fn floatCast(self: Value, allocator: *Allocator, ty: Type, target: Target) !Value {
989 const dest_bit_count = switch (ty.tag()) {
990 .comptime_float => 128,
991 else => ty.floatBits(target),
992 };
993 switch (dest_bit_count) {
994 16, 32, 64, 128 => {},
995 else => std.debug.panic("TODO float cast bit count {}\n", .{dest_bit_count}),
996 }
997 if (ty.isInt()) {
998 @panic("TODO int to float");
999 }
1000
1001 switch (dest_bit_count) {
1002 16 => {
1003 @panic("TODO soft float");
1004 // var res_payload = Value.Payload.Float_16{.val = self.toFloat(f16)};
1005 // if (!self.eql(Value.initPayload(&res_payload.base)))
1006 // return error.Overflow;
1007 // return Value.initPayload(&res_payload.base).copy(allocator);
1120 switch (ty.tag()) {
1121 .f16 => {
1122 @panic("TODO add __trunctfhf2 to compiler-rt");
1123 //const res = try Value.Tag.float_16.create(allocator, self.toFloat(f16));
1124 //if (!self.eql(res))
1125 // return error.Overflow;
1126 //return res;
10081127 },
1009 32 => {
1010 var res_payload = Value.Payload.Float_32{ .val = self.toFloat(f32) };
1011 if (!self.eql(Value.initPayload(&res_payload.base)))
1128 .f32 => {
1129 const res = try Value.Tag.float_32.create(allocator, self.toFloat(f32));
1130 if (!self.eql(res))
10121131 return error.Overflow;
1013 return Value.initPayload(&res_payload.base).copy(allocator);
1132 return res;
10141133 },
1015 64 => {
1016 var res_payload = Value.Payload.Float_64{ .val = self.toFloat(f64) };
1017 if (!self.eql(Value.initPayload(&res_payload.base)))
1134 .f64 => {
1135 const res = try Value.Tag.float_64.create(allocator, self.toFloat(f64));
1136 if (!self.eql(res))
10181137 return error.Overflow;
1019 return Value.initPayload(&res_payload.base).copy(allocator);
1138 return res;
10201139 },
1021 128 => {
1022 const float_payload = try allocator.create(Value.Payload.Float_128);
1023 float_payload.* = .{ .val = self.toFloat(f128) };
1024 return Value.initPayload(&float_payload.base);
1140 .f128, .comptime_float, .c_longdouble => {
1141 return Value.Tag.float_128.create(allocator, self.toFloat(f128));
10251142 },
10261143 else => unreachable,
10271144 }
......@@ -1102,10 +1219,10 @@ pub const Value = extern union {
11021219 .one,
11031220 => false,
11041221
1105 .float_16 => @rem(self.cast(Payload.Float_16).?.val, 1) != 0,
1106 .float_32 => @rem(self.cast(Payload.Float_32).?.val, 1) != 0,
1107 .float_64 => @rem(self.cast(Payload.Float_64).?.val, 1) != 0,
1108 // .float_128 => @rem(self.cast(Payload.Float_128).?.val, 1) != 0,
1222 .float_16 => @rem(self.castTag(.float_16).?.data, 1) != 0,
1223 .float_32 => @rem(self.castTag(.float_32).?.data, 1) != 0,
1224 .float_64 => @rem(self.castTag(.float_64).?.data, 1) != 0,
1225 // .float_128 => @rem(self.castTag(.float_128).?.data, 1) != 0,
11091226 .float_128 => @panic("TODO lld: error: undefined symbol: fmodl"),
11101227 };
11111228 }
......@@ -1182,15 +1299,15 @@ pub const Value = extern union {
11821299 .bool_true,
11831300 => .gt,
11841301
1185 .int_u64 => std.math.order(lhs.cast(Payload.Int_u64).?.int, 0),
1186 .int_i64 => std.math.order(lhs.cast(Payload.Int_i64).?.int, 0),
1187 .int_big_positive => lhs.cast(Payload.IntBigPositive).?.asBigInt().orderAgainstScalar(0),
1188 .int_big_negative => lhs.cast(Payload.IntBigNegative).?.asBigInt().orderAgainstScalar(0),
1302 .int_u64 => std.math.order(lhs.castTag(.int_u64).?.data, 0),
1303 .int_i64 => std.math.order(lhs.castTag(.int_i64).?.data, 0),
1304 .int_big_positive => lhs.castTag(.int_big_positive).?.asBigInt().orderAgainstScalar(0),
1305 .int_big_negative => lhs.castTag(.int_big_negative).?.asBigInt().orderAgainstScalar(0),
11891306
1190 .float_16 => std.math.order(lhs.cast(Payload.Float_16).?.val, 0),
1191 .float_32 => std.math.order(lhs.cast(Payload.Float_32).?.val, 0),
1192 .float_64 => std.math.order(lhs.cast(Payload.Float_64).?.val, 0),
1193 .float_128 => std.math.order(lhs.cast(Payload.Float_128).?.val, 0),
1307 .float_16 => std.math.order(lhs.castTag(.float_16).?.data, 0),
1308 .float_32 => std.math.order(lhs.castTag(.float_32).?.data, 0),
1309 .float_64 => std.math.order(lhs.castTag(.float_64).?.data, 0),
1310 .float_128 => std.math.order(lhs.castTag(.float_128).?.data, 0),
11941311 };
11951312 }
11961313
......@@ -1208,10 +1325,10 @@ pub const Value = extern union {
12081325 if (lhs_float and rhs_float) {
12091326 if (lhs_tag == rhs_tag) {
12101327 return switch (lhs.tag()) {
1211 .float_16 => return std.math.order(lhs.cast(Payload.Float_16).?.val, rhs.cast(Payload.Float_16).?.val),
1212 .float_32 => return std.math.order(lhs.cast(Payload.Float_32).?.val, rhs.cast(Payload.Float_32).?.val),
1213 .float_64 => return std.math.order(lhs.cast(Payload.Float_64).?.val, rhs.cast(Payload.Float_64).?.val),
1214 .float_128 => return std.math.order(lhs.cast(Payload.Float_128).?.val, rhs.cast(Payload.Float_128).?.val),
1328 .float_16 => return std.math.order(lhs.castTag(.float_16).?.data, rhs.castTag(.float_16).?.data),
1329 .float_32 => return std.math.order(lhs.castTag(.float_32).?.data, rhs.castTag(.float_32).?.data),
1330 .float_64 => return std.math.order(lhs.castTag(.float_64).?.data, rhs.castTag(.float_64).?.data),
1331 .float_128 => return std.math.order(lhs.castTag(.float_128).?.data, rhs.castTag(.float_128).?.data),
12151332 else => unreachable,
12161333 };
12171334 }
......@@ -1244,8 +1361,8 @@ pub const Value = extern union {
12441361 if (a.tag() == .void_value or a.tag() == .null_value) {
12451362 return true;
12461363 } else if (a.tag() == .enum_literal) {
1247 const a_name = @fieldParentPtr(Payload.Bytes, "base", a.ptr_otherwise).data;
1248 const b_name = @fieldParentPtr(Payload.Bytes, "base", b.ptr_otherwise).data;
1364 const a_name = a.castTag(.enum_literal).?.data;
1365 const b_name = b.castTag(.enum_literal).?.data;
12491366 return std.mem.eql(u8, a_name, b_name);
12501367 }
12511368 }
......@@ -1313,11 +1430,11 @@ pub const Value = extern union {
13131430 },
13141431 .error_set => {
13151432 // Payload.decl should be same for all instances of the type.
1316 const payload = @fieldParentPtr(Payload.ErrorSet, "base", self.ptr_otherwise);
1433 const payload = self.castTag(.error_set).?.data;
13171434 std.hash.autoHash(&hasher, payload.decl);
13181435 },
13191436 .int_type => {
1320 const payload = self.cast(Payload.IntType).?;
1437 const payload = self.castTag(.int_type).?.data;
13211438 var int_payload = Type.Payload.Bits{
13221439 .base = .{
13231440 .tag = if (payload.signed) .int_signed else .int_unsigned,
......@@ -1341,25 +1458,29 @@ pub const Value = extern union {
13411458 .one, .bool_true => std.hash.autoHash(&hasher, @as(u64, 1)),
13421459
13431460 .float_16, .float_32, .float_64, .float_128 => {},
1344 .enum_literal, .bytes => {
1345 const payload = @fieldParentPtr(Payload.Bytes, "base", self.ptr_otherwise);
1461 .enum_literal => {
1462 const payload = self.castTag(.enum_literal).?;
1463 hasher.update(payload.data);
1464 },
1465 .bytes => {
1466 const payload = self.castTag(.bytes).?;
13461467 hasher.update(payload.data);
13471468 },
13481469 .int_u64 => {
1349 const payload = @fieldParentPtr(Payload.Int_u64, "base", self.ptr_otherwise);
1350 std.hash.autoHash(&hasher, payload.int);
1470 const payload = self.castTag(.int_u64).?;
1471 std.hash.autoHash(&hasher, payload.data);
13511472 },
13521473 .int_i64 => {
1353 const payload = @fieldParentPtr(Payload.Int_i64, "base", self.ptr_otherwise);
1354 std.hash.autoHash(&hasher, payload.int);
1474 const payload = self.castTag(.int_i64).?;
1475 std.hash.autoHash(&hasher, payload.data);
13551476 },
13561477 .repeated => {
1357 const payload = @fieldParentPtr(Payload.Repeated, "base", self.ptr_otherwise);
1358 std.hash.autoHash(&hasher, payload.val.hash());
1478 const payload = self.castTag(.repeated).?;
1479 std.hash.autoHash(&hasher, payload.data.hash());
13591480 },
13601481 .ref_val => {
1361 const payload = @fieldParentPtr(Payload.RefVal, "base", self.ptr_otherwise);
1362 std.hash.autoHash(&hasher, payload.val.hash());
1482 const payload = self.castTag(.ref_val).?;
1483 std.hash.autoHash(&hasher, payload.data.hash());
13631484 },
13641485 .int_big_positive, .int_big_negative => {
13651486 var space: BigIntSpace = undefined;
......@@ -1379,28 +1500,28 @@ pub const Value = extern union {
13791500 }
13801501 },
13811502 .elem_ptr => {
1382 const payload = @fieldParentPtr(Payload.ElemPtr, "base", self.ptr_otherwise);
1503 const payload = self.castTag(.elem_ptr).?.data;
13831504 std.hash.autoHash(&hasher, payload.array_ptr.hash());
13841505 std.hash.autoHash(&hasher, payload.index);
13851506 },
13861507 .decl_ref => {
1387 const payload = @fieldParentPtr(Payload.DeclRef, "base", self.ptr_otherwise);
1388 std.hash.autoHash(&hasher, payload.decl);
1508 const decl = self.castTag(.decl_ref).?.data;
1509 std.hash.autoHash(&hasher, decl);
13891510 },
13901511 .function => {
1391 const payload = @fieldParentPtr(Payload.Function, "base", self.ptr_otherwise);
1392 std.hash.autoHash(&hasher, payload.func);
1512 const func = self.castTag(.function).?.data;
1513 std.hash.autoHash(&hasher, func);
13931514 },
13941515 .extern_fn => {
1395 const payload = @fieldParentPtr(Payload.ExternFn, "base", self.ptr_otherwise);
1396 std.hash.autoHash(&hasher, payload.decl);
1516 const decl = self.castTag(.extern_fn).?.data;
1517 std.hash.autoHash(&hasher, decl);
13971518 },
13981519 .variable => {
1399 const payload = @fieldParentPtr(Payload.Variable, "base", self.ptr_otherwise);
1400 std.hash.autoHash(&hasher, payload.variable);
1520 const variable = self.castTag(.variable).?.data;
1521 std.hash.autoHash(&hasher, variable);
14011522 },
14021523 .@"error" => {
1403 const payload = @fieldParentPtr(Payload.Error, "base", self.ptr_otherwise);
1524 const payload = self.castTag(.@"error").?.data;
14041525 hasher.update(payload.name);
14051526 std.hash.autoHash(&hasher, payload.value);
14061527 },
......@@ -1483,10 +1604,10 @@ pub const Value = extern union {
14831604 .empty_struct_value,
14841605 => unreachable,
14851606
1486 .ref_val => self.cast(Payload.RefVal).?.val,
1487 .decl_ref => self.cast(Payload.DeclRef).?.decl.value(),
1607 .ref_val => self.castTag(.ref_val).?.data,
1608 .decl_ref => self.castTag(.decl_ref).?.data.value(),
14881609 .elem_ptr => {
1489 const elem_ptr = self.cast(Payload.ElemPtr).?;
1610 const elem_ptr = self.castTag(.elem_ptr).?.data;
14901611 const array_val = try elem_ptr.array_ptr.pointerDeref(allocator);
14911612 return array_val.elemValue(allocator, elem_ptr.index);
14921613 },
......@@ -1570,26 +1691,26 @@ pub const Value = extern union {
15701691
15711692 .empty_array => unreachable, // out of bounds array index
15721693
1573 .bytes => {
1574 const int_payload = try allocator.create(Payload.Int_u64);
1575 int_payload.* = .{ .int = self.cast(Payload.Bytes).?.data[index] };
1576 return Value.initPayload(&int_payload.base);
1577 },
1694 .bytes => return Tag.int_u64.create(allocator, self.castTag(.bytes).?.data[index]),
15781695
15791696 // No matter the index; all the elements are the same!
1580 .repeated => return self.cast(Payload.Repeated).?.val,
1697 .repeated => return self.castTag(.repeated).?.data,
15811698 }
15821699 }
15831700
15841701 /// Returns a pointer to the element value at the index.
15851702 pub fn elemPtr(self: Value, allocator: *Allocator, index: usize) !Value {
1586 const payload = try allocator.create(Payload.ElemPtr);
1587 if (self.cast(Payload.ElemPtr)) |elem_ptr| {
1588 payload.* = .{ .array_ptr = elem_ptr.array_ptr, .index = elem_ptr.index + index };
1589 } else {
1590 payload.* = .{ .array_ptr = self, .index = index };
1703 if (self.castTag(.elem_ptr)) |elem_ptr| {
1704 return Tag.elem_ptr.create(allocator, .{
1705 .array_ptr = elem_ptr.data.array_ptr,
1706 .index = elem_ptr.data.index + index,
1707 });
15911708 }
1592 return Value.initPayload(&payload.base);
1709
1710 return Tag.elem_ptr.create(allocator, .{
1711 .array_ptr = self,
1712 .index = index,
1713 });
15931714 }
15941715
15951716 pub fn isUndef(self: Value) bool {
......@@ -1776,131 +1897,128 @@ pub const Value = extern union {
17761897 pub const Payload = struct {
17771898 tag: Tag,
17781899
1779 pub const Int_u64 = struct {
1780 base: Payload = Payload{ .tag = .int_u64 },
1781 int: u64,
1900 pub const U64 = struct {
1901 base: Payload,
1902 data: u64,
17821903 };
17831904
1784 pub const Int_i64 = struct {
1785 base: Payload = Payload{ .tag = .int_i64 },
1786 int: i64,
1787 };
1788
1789 pub const IntBigPositive = struct {
1790 base: Payload = Payload{ .tag = .int_big_positive },
1791 limbs: []const std.math.big.Limb,
1792
1793 pub fn asBigInt(self: IntBigPositive) BigIntConst {
1794 return BigIntConst{ .limbs = self.limbs, .positive = true };
1795 }
1905 pub const I64 = struct {
1906 base: Payload,
1907 data: i64,
17961908 };
17971909
1798 pub const IntBigNegative = struct {
1799 base: Payload = Payload{ .tag = .int_big_negative },
1800 limbs: []const std.math.big.Limb,
1910 pub const BigInt = struct {
1911 base: Payload,
1912 data: []const std.math.big.Limb,
18011913
1802 pub fn asBigInt(self: IntBigNegative) BigIntConst {
1803 return BigIntConst{ .limbs = self.limbs, .positive = false };
1914 pub fn asBigInt(self: BigInt) BigIntConst {
1915 const positive = switch (self.base.tag) {
1916 .int_big_positive => true,
1917 .int_big_negative => false,
1918 else => unreachable,
1919 };
1920 return BigIntConst{ .limbs = self.data, .positive = positive };
18041921 }
18051922 };
18061923
18071924 pub const Function = struct {
1808 base: Payload = Payload{ .tag = .function },
1809 func: *Module.Fn,
1925 base: Payload,
1926 data: *Module.Fn,
18101927 };
18111928
1812 pub const ExternFn = struct {
1813 base: Payload = Payload{ .tag = .extern_fn },
1814 decl: *Module.Decl,
1929 pub const Decl = struct {
1930 base: Payload,
1931 data: *Module.Decl,
18151932 };
18161933
18171934 pub const Variable = struct {
1818 base: Payload = Payload{ .tag = .variable },
1819 variable: *Module.Var,
1820 };
1821
1822 pub const ArraySentinel0_u8_Type = struct {
1823 base: Payload = Payload{ .tag = .array_sentinel_0_u8_type },
1824 len: u64,
1825 };
1826
1827 /// Represents a pointer to another immutable value.
1828 pub const RefVal = struct {
1829 base: Payload = Payload{ .tag = .ref_val },
1830 val: Value,
1935 base: Payload,
1936 data: *Module.Var,
18311937 };
18321938
1833 /// Represents a pointer to a decl, not the value of the decl.
1834 pub const DeclRef = struct {
1835 base: Payload = Payload{ .tag = .decl_ref },
1836 decl: *Module.Decl,
1939 pub const SubValue = struct {
1940 base: Payload,
1941 data: Value,
18371942 };
18381943
18391944 pub const ElemPtr = struct {
1840 base: Payload = Payload{ .tag = .elem_ptr },
1841 array_ptr: Value,
1842 index: usize,
1945 pub const base_tag = Tag.elem_ptr;
1946
1947 base: Payload = Payload{ .tag = base_tag },
1948 data: struct {
1949 array_ptr: Value,
1950 index: usize,
1951 },
18431952 };
18441953
18451954 pub const Bytes = struct {
1846 base: Payload = Payload{ .tag = .bytes },
1955 base: Payload,
18471956 data: []const u8,
18481957 };
18491958
18501959 pub const Ty = struct {
1851 base: Payload = Payload{ .tag = .ty },
1852 ty: Type,
1960 base: Payload,
1961 data: Type,
18531962 };
18541963
18551964 pub const IntType = struct {
1856 base: Payload = Payload{ .tag = .int_type },
1857 bits: u16,
1858 signed: bool,
1859 };
1965 pub const base_tag = Tag.int_type;
18601966
1861 pub const Repeated = struct {
1862 base: Payload = Payload{ .tag = .ty },
1863 /// This value is repeated some number of times. The amount of times to repeat
1864 /// is stored externally.
1865 val: Value,
1967 base: Payload = Payload{ .tag = base_tag },
1968 data: struct {
1969 bits: u16,
1970 signed: bool,
1971 },
18661972 };
18671973
18681974 pub const Float_16 = struct {
1869 base: Payload = .{ .tag = .float_16 },
1870 val: f16,
1975 pub const base_tag = Tag.float_16;
1976
1977 base: Payload = .{ .tag = base_tag },
1978 data: f16,
18711979 };
18721980
18731981 pub const Float_32 = struct {
1874 base: Payload = .{ .tag = .float_32 },
1875 val: f32,
1982 pub const base_tag = Tag.float_32;
1983
1984 base: Payload = .{ .tag = base_tag },
1985 data: f32,
18761986 };
18771987
18781988 pub const Float_64 = struct {
1879 base: Payload = .{ .tag = .float_64 },
1880 val: f64,
1989 pub const base_tag = Tag.float_64;
1990
1991 base: Payload = .{ .tag = base_tag },
1992 data: f64,
18811993 };
18821994
18831995 pub const Float_128 = struct {
1884 base: Payload = .{ .tag = .float_128 },
1885 val: f128,
1996 pub const base_tag = Tag.float_128;
1997
1998 base: Payload = .{ .tag = base_tag },
1999 data: f128,
18862000 };
18872001
18882002 pub const ErrorSet = struct {
1889 base: Payload = .{ .tag = .error_set },
2003 pub const base_tag = Tag.error_set;
18902004
1891 // TODO revisit this when we have the concept of the error tag type
1892 fields: std.StringHashMapUnmanaged(u16),
1893 decl: *Module.Decl,
2005 base: Payload = .{ .tag = base_tag },
2006 data: struct {
2007 // TODO revisit this when we have the concept of the error tag type
2008 fields: std.StringHashMapUnmanaged(u16),
2009 decl: *Module.Decl,
2010 },
18942011 };
18952012
18962013 pub const Error = struct {
18972014 base: Payload = .{ .tag = .@"error" },
1898
1899 // TODO revisit this when we have the concept of the error tag type
1900 /// `name` is owned by `Module` and will be valid for the entire
1901 /// duration of the compilation.
1902 name: []const u8,
1903 value: u16,
2015 data: struct {
2016 // TODO revisit this when we have the concept of the error tag type
2017 /// `name` is owned by `Module` and will be valid for the entire
2018 /// duration of the compilation.
2019 name: []const u8,
2020 value: u16,
2021 },
19042022 };
19052023 };
19062024
......@@ -1914,15 +2032,24 @@ pub const Value = extern union {
19142032
19152033test "hash same value different representation" {
19162034 const zero_1 = Value.initTag(.zero);
1917 var payload_1 = Value.Payload.Int_u64{ .int = 0 };
2035 var payload_1 = Value.Payload.U64{
2036 .base = .{ .tag = .int_u64 },
2037 .data = 0,
2038 };
19182039 const zero_2 = Value.initPayload(&payload_1.base);
19192040 std.testing.expectEqual(zero_1.hash(), zero_2.hash());
19202041
1921 var payload_2 = Value.Payload.Int_i64{ .int = 0 };
2042 var payload_2 = Value.Payload.I64{
2043 .base = .{ .tag = .int_i64 },
2044 .data = 0,
2045 };
19222046 const zero_3 = Value.initPayload(&payload_2.base);
19232047 std.testing.expectEqual(zero_2.hash(), zero_3.hash());
19242048
1925 var payload_3 = Value.Payload.IntBigNegative{ .limbs = &[_]std.math.big.Limb{0} };
2049 var payload_3 = Value.Payload.BigInt{
2050 .base = .{ .tag = .int_big_negative },
2051 .data = &[_]std.math.big.Limb{0},
2052 };
19262053 const zero_4 = Value.initPayload(&payload_3.base);
19272054 std.testing.expectEqual(zero_3.hash(), zero_4.hash());
19282055}
src/zir.zig+18-16
......@@ -1990,15 +1990,15 @@ const EmitZIR = struct {
19901990
19911991 fn resolveInst(self: *EmitZIR, new_body: ZirBody, inst: *ir.Inst) !*Inst {
19921992 if (inst.cast(ir.Inst.Constant)) |const_inst| {
1993 const new_inst = if (const_inst.val.cast(Value.Payload.Function)) |func_pl| blk: {
1994 const owner_decl = func_pl.func.owner_decl;
1993 const new_inst = if (const_inst.val.castTag(.function)) |func_pl| blk: {
1994 const owner_decl = func_pl.data.owner_decl;
19951995 break :blk try self.emitDeclVal(inst.src, mem.spanZ(owner_decl.name));
1996 } else if (const_inst.val.cast(Value.Payload.DeclRef)) |declref| blk: {
1997 const decl_ref = try self.emitDeclRef(inst.src, declref.decl);
1996 } else if (const_inst.val.castTag(.decl_ref)) |declref| blk: {
1997 const decl_ref = try self.emitDeclRef(inst.src, declref.data);
19981998 try new_body.instructions.append(decl_ref);
19991999 break :blk decl_ref;
2000 } else if (const_inst.val.cast(Value.Payload.Variable)) |var_pl| blk: {
2001 const owner_decl = var_pl.variable.owner_decl;
2000 } else if (const_inst.val.castTag(.variable)) |var_pl| blk: {
2001 const owner_decl = var_pl.data.owner_decl;
20022002 break :blk try self.emitDeclVal(inst.src, mem.spanZ(owner_decl.name));
20032003 } else blk: {
20042004 break :blk (try self.emitTypedValue(inst.src, .{ .ty = inst.ty, .val = const_inst.val })).inst;
......@@ -2150,13 +2150,13 @@ const EmitZIR = struct {
21502150
21512151 fn emitTypedValue(self: *EmitZIR, src: usize, typed_value: TypedValue) Allocator.Error!*Decl {
21522152 const allocator = &self.arena.allocator;
2153 if (typed_value.val.cast(Value.Payload.DeclRef)) |decl_ref| {
2154 const decl = decl_ref.decl;
2153 if (typed_value.val.castTag(.decl_ref)) |decl_ref| {
2154 const decl = decl_ref.data;
21552155 return try self.emitUnnamedDecl(try self.emitDeclRef(src, decl));
2156 } else if (typed_value.val.cast(Value.Payload.Variable)) |variable| {
2156 } else if (typed_value.val.castTag(.variable)) |variable| {
21572157 return self.emitTypedValue(src, .{
21582158 .ty = typed_value.ty,
2159 .val = variable.variable.init,
2159 .val = variable.data.init,
21602160 });
21612161 }
21622162 if (typed_value.val.isUndef()) {
......@@ -2215,7 +2215,7 @@ const EmitZIR = struct {
22152215 return self.emitType(src, ty);
22162216 },
22172217 .Fn => {
2218 const module_fn = typed_value.val.cast(Value.Payload.Function).?.func;
2218 const module_fn = typed_value.val.castTag(.function).?.data;
22192219 return self.emitFn(module_fn, src, typed_value.ty);
22202220 },
22212221 .Array => {
......@@ -2248,7 +2248,7 @@ const EmitZIR = struct {
22482248 else
22492249 return self.emitPrimitive(src, .@"false"),
22502250 .EnumLiteral => {
2251 const enum_literal = @fieldParentPtr(Value.Payload.Bytes, "base", typed_value.val.ptr_otherwise);
2251 const enum_literal = typed_value.val.castTag(.enum_literal).?;
22522252 const inst = try self.arena.allocator.create(Inst.Str);
22532253 inst.* = .{
22542254 .base = .{
......@@ -2748,9 +2748,8 @@ const EmitZIR = struct {
27482748 .signed => .@"true",
27492749 .unsigned => .@"false",
27502750 });
2751 const bits_payload = try self.arena.allocator.create(Value.Payload.Int_u64);
2752 bits_payload.* = .{ .int = info.bits };
2753 const bits = try self.emitComptimeIntVal(src, Value.initPayload(&bits_payload.base));
2751 const bits_val = try Value.Tag.int_u64.create(&self.arena.allocator, info.bits);
2752 const bits = try self.emitComptimeIntVal(src, bits_val);
27542753 const inttype_inst = try self.arena.allocator.create(Inst.IntType);
27552754 inttype_inst.* = .{
27562755 .base = .{
......@@ -2800,7 +2799,10 @@ const EmitZIR = struct {
28002799 return self.emitUnnamedDecl(&inst.base);
28012800 },
28022801 .Array => {
2803 var len_pl = Value.Payload.Int_u64{ .int = ty.arrayLen() };
2802 var len_pl = Value.Payload.U64{
2803 .base = .{ .tag = .int_u64 },
2804 .data = ty.arrayLen(),
2805 };
28042806 const len = Value.initPayload(&len_pl.base);
28052807
28062808 const inst = if (ty.sentinel()) |sentinel| blk: {
src/zir_sema.zig+30-48
......@@ -364,12 +364,9 @@ fn analyzeInstRef(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!
364364 const ptr_type = try mod.simplePtrType(scope, inst.base.src, operand.ty, false, .One);
365365
366366 if (operand.value()) |val| {
367 const ref_payload = try scope.arena().create(Value.Payload.RefVal);
368 ref_payload.* = .{ .val = val };
369
370367 return mod.constInst(scope, inst.base.src, .{
371368 .ty = ptr_type,
372 .val = Value.initPayload(&ref_payload.base),
369 .val = try Value.Tag.ref_val.create(scope.arena(), val),
373370 });
374371 }
375372
......@@ -480,12 +477,9 @@ fn analyzeInstStr(mod: *Module, scope: *Scope, str_inst: *zir.Inst.Str) InnerErr
480477 errdefer new_decl_arena.deinit();
481478 const arena_bytes = try new_decl_arena.allocator.dupe(u8, str_inst.positionals.bytes);
482479
483 const bytes_payload = try scope.arena().create(Value.Payload.Bytes);
484 bytes_payload.* = .{ .data = arena_bytes };
485
486480 const new_decl = try mod.createAnonymousDecl(scope, &new_decl_arena, .{
487481 .ty = try Type.Tag.array_u8_sentinel_0.create(scope.arena(), arena_bytes.len),
488 .val = Value.initPayload(&bytes_payload.base),
482 .val = try Value.Tag.bytes.create(scope.arena(), arena_bytes),
489483 });
490484 return mod.analyzeDeclRef(scope, str_inst.base.src, new_decl);
491485}
......@@ -779,11 +773,9 @@ fn analyzeInstFn(mod: *Module, scope: *Scope, fn_inst: *zir.Inst.Fn) InnerError!
779773 .analysis = .{ .queued = fn_zir },
780774 .owner_decl = scope.decl().?,
781775 };
782 const fn_payload = try scope.arena().create(Value.Payload.Function);
783 fn_payload.* = .{ .func = new_func };
784776 return mod.constInst(scope, fn_inst.base.src, .{
785777 .ty = fn_type,
786 .val = Value.initPayload(&fn_payload.base),
778 .val = try Value.Tag.function.create(scope.arena(), new_func),
787779 });
788780}
789781
......@@ -838,14 +830,17 @@ fn analyzeInstErrorSet(mod: *Module, scope: *Scope, inst: *zir.Inst.ErrorSet) In
838830
839831 const payload = try scope.arena().create(Value.Payload.ErrorSet);
840832 payload.* = .{
841 .fields = .{},
842 .decl = undefined, // populated below
833 .base = .{ .tag = .error_set },
834 .data = .{
835 .fields = .{},
836 .decl = undefined, // populated below
837 },
843838 };
844 try payload.fields.ensureCapacity(&new_decl_arena.allocator, @intCast(u32, inst.positionals.fields.len));
839 try payload.data.fields.ensureCapacity(&new_decl_arena.allocator, @intCast(u32, inst.positionals.fields.len));
845840
846841 for (inst.positionals.fields) |field_name| {
847842 const entry = try mod.getErrorValue(field_name);
848 if (payload.fields.fetchPutAssumeCapacity(entry.key, entry.value)) |prev| {
843 if (payload.data.fields.fetchPutAssumeCapacity(entry.key, entry.value)) |prev| {
849844 return mod.fail(scope, inst.base.src, "duplicate error: '{}'", .{field_name});
850845 }
851846 }
......@@ -854,7 +849,7 @@ fn analyzeInstErrorSet(mod: *Module, scope: *Scope, inst: *zir.Inst.ErrorSet) In
854849 .ty = Type.initTag(.type),
855850 .val = Value.initPayload(&payload.base),
856851 });
857 payload.decl = new_decl;
852 payload.data.decl = new_decl;
858853 return mod.analyzeDeclRef(scope, inst.base.src, new_decl);
859854}
860855
......@@ -863,14 +858,10 @@ fn analyzeInstMergeErrorSets(mod: *Module, scope: *Scope, inst: *zir.Inst.BinOp)
863858}
864859
865860fn analyzeInstEnumLiteral(mod: *Module, scope: *Scope, inst: *zir.Inst.EnumLiteral) InnerError!*Inst {
866 const payload = try scope.arena().create(Value.Payload.Bytes);
867 payload.* = .{
868 .base = .{ .tag = .enum_literal },
869 .data = try scope.arena().dupe(u8, inst.positionals.name),
870 };
861 const duped_name = try scope.arena().dupe(u8, inst.positionals.name);
871862 return mod.constInst(scope, inst.base.src, .{
872863 .ty = Type.initTag(.enum_literal),
873 .val = Value.initPayload(&payload.base),
864 .val = try Value.Tag.enum_literal.create(scope.arena(), duped_name),
874865 });
875866}
876867
......@@ -989,15 +980,12 @@ fn analyzeInstFieldPtr(mod: *Module, scope: *Scope, fieldptr: *zir.Inst.FieldPtr
989980 switch (elem_ty.zigTypeTag()) {
990981 .Array => {
991982 if (mem.eql(u8, field_name, "len")) {
992 const len_payload = try scope.arena().create(Value.Payload.Int_u64);
993 len_payload.* = .{ .int = elem_ty.arrayLen() };
994
995 const ref_payload = try scope.arena().create(Value.Payload.RefVal);
996 ref_payload.* = .{ .val = Value.initPayload(&len_payload.base) };
997
998983 return mod.constInst(scope, fieldptr.base.src, .{
999984 .ty = Type.initTag(.single_const_pointer_to_comptime_int),
1000 .val = Value.initPayload(&ref_payload.base),
985 .val = try Value.Tag.ref_val.create(
986 scope.arena(),
987 try Value.Tag.int_u64.create(scope.arena(), elem_ty.arrayLen()),
988 ),
1001989 });
1002990 } else {
1003991 return mod.fail(
......@@ -1013,15 +1001,12 @@ fn analyzeInstFieldPtr(mod: *Module, scope: *Scope, fieldptr: *zir.Inst.FieldPtr
10131001 switch (ptr_child.zigTypeTag()) {
10141002 .Array => {
10151003 if (mem.eql(u8, field_name, "len")) {
1016 const len_payload = try scope.arena().create(Value.Payload.Int_u64);
1017 len_payload.* = .{ .int = ptr_child.arrayLen() };
1018
1019 const ref_payload = try scope.arena().create(Value.Payload.RefVal);
1020 ref_payload.* = .{ .val = Value.initPayload(&len_payload.base) };
1021
10221004 return mod.constInst(scope, fieldptr.base.src, .{
10231005 .ty = Type.initTag(.single_const_pointer_to_comptime_int),
1024 .val = Value.initPayload(&ref_payload.base),
1006 .val = try Value.Tag.ref_val.create(
1007 scope.arena(),
1008 try Value.Tag.int_u64.create(scope.arena(), ptr_child.arrayLen()),
1009 ),
10251010 });
10261011 } else {
10271012 return mod.fail(
......@@ -1043,21 +1028,12 @@ fn analyzeInstFieldPtr(mod: *Module, scope: *Scope, fieldptr: *zir.Inst.FieldPtr
10431028 switch (child_type.zigTypeTag()) {
10441029 .ErrorSet => {
10451030 // TODO resolve inferred error sets
1046 const entry = if (val.cast(Value.Payload.ErrorSet)) |payload|
1047 (payload.fields.getEntry(field_name) orelse
1031 const entry = if (val.castTag(.error_set)) |payload|
1032 (payload.data.fields.getEntry(field_name) orelse
10481033 return mod.fail(scope, fieldptr.base.src, "no error named '{}' in '{}'", .{ field_name, child_type })).*
10491034 else
10501035 try mod.getErrorValue(field_name);
10511036
1052 const error_payload = try scope.arena().create(Value.Payload.Error);
1053 error_payload.* = .{
1054 .name = entry.key,
1055 .value = entry.value,
1056 };
1057
1058 const ref_payload = try scope.arena().create(Value.Payload.RefVal);
1059 ref_payload.* = .{ .val = Value.initPayload(&error_payload.base) };
1060
10611037 const result_type = if (child_type.tag() == .anyerror)
10621038 try Type.Tag.error_set_single.create(scope.arena(), entry.key)
10631039 else
......@@ -1065,7 +1041,13 @@ fn analyzeInstFieldPtr(mod: *Module, scope: *Scope, fieldptr: *zir.Inst.FieldPtr
10651041
10661042 return mod.constInst(scope, fieldptr.base.src, .{
10671043 .ty = try mod.simplePtrType(scope, fieldptr.base.src, result_type, false, .One),
1068 .val = Value.initPayload(&ref_payload.base),
1044 .val = try Value.Tag.ref_val.create(
1045 scope.arena(),
1046 try Value.Tag.@"error".create(scope.arena(), .{
1047 .name = entry.key,
1048 .value = entry.value,
1049 }),
1050 ),
10691051 });
10701052 },
10711053 .Struct => {