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...@@ -1457,11 +1457,12 @@ pub fn performAllTheWork(self: *Compilation) error{ TimerUnsupported, OutOfMemor
14571457
1458 .complete, .codegen_failure_retryable => {1458 .complete, .codegen_failure_retryable => {
1459 const module = self.bin_file.options.module.?;1459 const module = self.bin_file.options.module.?;
1460 if (decl.typed_value.most_recent.typed_value.val.cast(Value.Payload.Function)) |payload| {1460 if (decl.typed_value.most_recent.typed_value.val.castTag(.function)) |payload| {
1461 switch (payload.func.analysis) {1461 const func = payload.data;
1462 .queued => module.analyzeFnBody(decl, payload.func) catch |err| switch (err) {1462 switch (func.analysis) {
1463 .queued => module.analyzeFnBody(decl, func) catch |err| switch (err) {
1463 error.AnalysisFail => {1464 error.AnalysisFail => {
1464 assert(payload.func.analysis != .in_progress);1465 assert(func.analysis != .in_progress);
1465 continue;1466 continue;
1466 },1467 },
1467 error.OutOfMemory => return error.OutOfMemory,1468 error.OutOfMemory => return error.OutOfMemory,
...@@ -1475,7 +1476,7 @@ pub fn performAllTheWork(self: *Compilation) error{ TimerUnsupported, OutOfMemor...@@ -1475,7 +1476,7 @@ pub fn performAllTheWork(self: *Compilation) error{ TimerUnsupported, OutOfMemor
1475 var decl_arena = decl.typed_value.most_recent.arena.?.promote(module.gpa);1476 var decl_arena = decl.typed_value.most_recent.arena.?.promote(module.gpa);
1476 defer decl.typed_value.most_recent.arena.?.* = decl_arena.state;1477 defer decl.typed_value.most_recent.arena.?.* = decl_arena.state;
1477 log.debug("analyze liveness of {}\n", .{decl.name});1478 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);
1479 }1480 }
14801481
1481 assert(decl.typed_value.most_recent.typed_value.ty.hasCodeGenBits());1482 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 {...@@ -1092,16 +1092,12 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool {
10921092
1093 tvm.deinit(self.gpa);1093 tvm.deinit(self.gpa);
1094 }1094 }
1095 const value_payload = try decl_arena.allocator.create(Value.Payload.ExternFn);1095 const fn_val = try Value.Tag.extern_fn.create(&decl_arena.allocator, decl);
1096 value_payload.* = .{ .decl = decl };
10971096
1098 decl_arena_state.* = decl_arena.state;1097 decl_arena_state.* = decl_arena.state;
1099 decl.typed_value = .{1098 decl.typed_value = .{
1100 .most_recent = .{1099 .most_recent = .{
1101 .typed_value = .{1100 .typed_value = .{ .ty = fn_type, .val = fn_val },
1102 .ty = fn_type,
1103 .val = Value.initPayload(&value_payload.base),
1104 },
1105 .arena = decl_arena_state,1101 .arena = decl_arena_state,
1106 },1102 },
1107 };1103 };
...@@ -1187,7 +1183,10 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool {...@@ -1187,7 +1183,10 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool {
1187 .analysis = .{ .queued = fn_zir },1183 .analysis = .{ .queued = fn_zir },
1188 .owner_decl = decl,1184 .owner_decl = decl,
1189 };1185 };
1190 fn_payload.* = .{ .func = new_func };1186 fn_payload.* = .{
1187 .base = .{ .tag = .function },
1188 .data = new_func,
1189 };
11911190
1192 var prev_type_has_bits = false;1191 var prev_type_has_bits = false;
1193 var type_changed = true;1192 var type_changed = true;
...@@ -1375,7 +1374,6 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool {...@@ -1375,7 +1374,6 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool {
1375 }1374 }
13761375
1377 const new_variable = try decl_arena.allocator.create(Var);1376 const new_variable = try decl_arena.allocator.create(Var);
1378 const var_payload = try decl_arena.allocator.create(Value.Payload.Variable);
1379 new_variable.* = .{1377 new_variable.* = .{
1380 .owner_decl = decl,1378 .owner_decl = decl,
1381 .init = var_info.val orelse undefined,1379 .init = var_info.val orelse undefined,
...@@ -1383,14 +1381,14 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool {...@@ -1383,14 +1381,14 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool {
1383 .is_mutable = is_mutable,1381 .is_mutable = is_mutable,
1384 .is_threadlocal = is_threadlocal,1382 .is_threadlocal = is_threadlocal,
1385 };1383 };
1386 var_payload.* = .{ .variable = new_variable };1384 const var_val = try Value.Tag.variable.create(&decl_arena.allocator, new_variable);
13871385
1388 decl_arena_state.* = decl_arena.state;1386 decl_arena_state.* = decl_arena.state;
1389 decl.typed_value = .{1387 decl.typed_value = .{
1390 .most_recent = .{1388 .most_recent = .{
1391 .typed_value = .{1389 .typed_value = .{
1392 .ty = var_info.ty,1390 .ty = var_info.ty,
1393 .val = Value.initPayload(&var_payload.base),1391 .val = var_val,
1394 },1392 },
1395 .arena = decl_arena_state,1393 .arena = decl_arena_state,
1396 },1394 },
...@@ -2232,52 +2230,43 @@ pub fn constBool(self: *Module, scope: *Scope, src: usize, v: bool) !*Inst {...@@ -2232,52 +2230,43 @@ pub fn constBool(self: *Module, scope: *Scope, src: usize, v: bool) !*Inst {
2232}2230}
22332231
2234pub fn constIntUnsigned(self: *Module, scope: *Scope, src: usize, ty: Type, int: u64) !*Inst {2232pub 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
2238 return self.constInst(scope, src, .{2233 return self.constInst(scope, src, .{
2239 .ty = ty,2234 .ty = ty,
2240 .val = Value.initPayload(&int_payload.base),2235 .val = try Value.Tag.int_u64.create(scope.arena(), int),
2241 });2236 });
2242}2237}
22432238
2244pub fn constIntSigned(self: *Module, scope: *Scope, src: usize, ty: Type, int: i64) !*Inst {2239pub 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
2248 return self.constInst(scope, src, .{2240 return self.constInst(scope, src, .{
2249 .ty = ty,2241 .ty = ty,
2250 .val = Value.initPayload(&int_payload.base),2242 .val = try Value.Tag.int_i64.create(scope.arena(), int),
2251 });2243 });
2252}2244}
22532245
2254pub fn constIntBig(self: *Module, scope: *Scope, src: usize, ty: Type, big_int: BigIntConst) !*Inst {2246pub 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) {
2256 if (big_int.to(u64)) |x| {2248 if (big_int.to(u64)) |x| {
2257 return self.constIntUnsigned(scope, src, ty, x);2249 return self.constIntUnsigned(scope, src, ty, x);
2258 } else |err| switch (err) {2250 } else |err| switch (err) {
2259 error.NegativeIntoUnsigned => unreachable,2251 error.NegativeIntoUnsigned => unreachable,
2260 error.TargetTooSmall => {}, // handled below2252 error.TargetTooSmall => {}, // handled below
2261 }2253 }
2262 const big_int_payload = try scope.arena().create(Value.Payload.IntBigPositive);2254 return self.constInst(scope, src, .{
2263 big_int_payload.* = .{ .limbs = big_int.limbs };2255 .ty = ty,
2264 break :blk &big_int_payload.base;2256 .val = try Value.Tag.int_big_positive.create(scope.arena(), big_int.limbs),
2265 } else blk: {2257 });
2258 } else {
2266 if (big_int.to(i64)) |x| {2259 if (big_int.to(i64)) |x| {
2267 return self.constIntSigned(scope, src, ty, x);2260 return self.constIntSigned(scope, src, ty, x);
2268 } else |err| switch (err) {2261 } else |err| switch (err) {
2269 error.NegativeIntoUnsigned => unreachable,2262 error.NegativeIntoUnsigned => unreachable,
2270 error.TargetTooSmall => {}, // handled below2263 error.TargetTooSmall => {}, // handled below
2271 }2264 }
2272 const big_int_payload = try scope.arena().create(Value.Payload.IntBigNegative);2265 return self.constInst(scope, src, .{
2273 big_int_payload.* = .{ .limbs = big_int.limbs };2266 .ty = ty,
2274 break :blk &big_int_payload.base;2267 .val = try Value.Tag.int_big_negative.create(scope.arena(), big_int.limbs),
2275 };2268 });
22762269 }
2277 return self.constInst(scope, src, .{
2278 .ty = ty,
2279 .val = Value.initPayload(val_payload),
2280 });
2281}2270}
22822271
2283pub fn createAnonymousDecl(2272pub fn createAnonymousDecl(
...@@ -2346,26 +2335,20 @@ pub fn analyzeDeclRef(self: *Module, scope: *Scope, src: usize, decl: *Decl) Inn...@@ -2346,26 +2335,20 @@ pub fn analyzeDeclRef(self: *Module, scope: *Scope, src: usize, decl: *Decl) Inn
2346 if (decl_tv.val.tag() == .variable) {2335 if (decl_tv.val.tag() == .variable) {
2347 return self.analyzeVarRef(scope, src, decl_tv);2336 return self.analyzeVarRef(scope, src, decl_tv);
2348 }2337 }
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
2353 return self.constInst(scope, src, .{2338 return self.constInst(scope, src, .{
2354 .ty = ty,2339 .ty = try self.simplePtrType(scope, src, decl_tv.ty, false, .One),
2355 .val = Value.initPayload(&val_payload.base),2340 .val = try Value.Tag.decl_ref.create(scope.arena(), decl),
2356 });2341 });
2357}2342}
23582343
2359fn analyzeVarRef(self: *Module, scope: *Scope, src: usize, tv: TypedValue) InnerError!*Inst {2344fn 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
2362 const ty = try self.simplePtrType(scope, src, tv.ty, variable.is_mutable, .One);2347 const ty = try self.simplePtrType(scope, src, tv.ty, variable.is_mutable, .One);
2363 if (!variable.is_mutable and !variable.is_extern) {2348 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 };
2366 return self.constInst(scope, src, .{2349 return self.constInst(scope, src, .{
2367 .ty = ty,2350 .ty = ty,
2368 .val = Value.initPayload(&val_payload.base),2351 .val = try Value.Tag.ref_val.create(scope.arena(), variable.init),
2369 });2352 });
2370 }2353 }
23712354
...@@ -3107,17 +3090,11 @@ pub fn intAdd(allocator: *Allocator, lhs: Value, rhs: Value) !Value {...@@ -3107,17 +3090,11 @@ pub fn intAdd(allocator: *Allocator, lhs: Value, rhs: Value) !Value {
3107 result_bigint.add(lhs_bigint, rhs_bigint);3090 result_bigint.add(lhs_bigint, rhs_bigint);
3108 const result_limbs = result_bigint.limbs[0..result_bigint.len];3091 const result_limbs = result_bigint.limbs[0..result_bigint.len];
31093092
3110 const val_payload = if (result_bigint.positive) blk: {3093 if (result_bigint.positive) {
3111 const val_payload = try allocator.create(Value.Payload.IntBigPositive);3094 return Value.Tag.int_big_positive.create(allocator, result_limbs);
3112 val_payload.* = .{ .limbs = result_limbs };3095 } else {
3113 break :blk &val_payload.base;3096 return Value.Tag.int_big_negative.create(allocator, result_limbs);
3114 } else blk: {3097 }
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);
3121}3098}
31223099
3123pub fn intSub(allocator: *Allocator, lhs: Value, rhs: Value) !Value {3100pub fn intSub(allocator: *Allocator, lhs: Value, rhs: Value) !Value {
...@@ -3135,85 +3112,81 @@ pub fn intSub(allocator: *Allocator, lhs: Value, rhs: Value) !Value {...@@ -3135,85 +3112,81 @@ pub fn intSub(allocator: *Allocator, lhs: Value, rhs: Value) !Value {
3135 result_bigint.sub(lhs_bigint, rhs_bigint);3112 result_bigint.sub(lhs_bigint, rhs_bigint);
3136 const result_limbs = result_bigint.limbs[0..result_bigint.len];3113 const result_limbs = result_bigint.limbs[0..result_bigint.len];
31373114
3138 const val_payload = if (result_bigint.positive) blk: {3115 if (result_bigint.positive) {
3139 const val_payload = try allocator.create(Value.Payload.IntBigPositive);3116 return Value.Tag.int_big_positive.create(allocator, result_limbs);
3140 val_payload.* = .{ .limbs = result_limbs };3117 } else {
3141 break :blk &val_payload.base;3118 return Value.Tag.int_big_negative.create(allocator, result_limbs);
3142 } else blk: {3119 }
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);
3149}3120}
31503121
3151pub fn floatAdd(self: *Module, scope: *Scope, float_type: Type, src: usize, lhs: Value, rhs: Value) !Value {3122pub fn floatAdd(
3152 var bit_count = switch (float_type.tag()) {3123 self: *Module,
3153 .comptime_float => 128,3124 scope: *Scope,
3154 else => float_type.floatBits(self.getTarget()),3125 float_type: Type,
3155 };3126 src: usize,
31563127 lhs: Value,
3157 const allocator = scope.arena();3128 rhs: Value,
3158 const val_payload = switch (bit_count) {3129) !Value {
3159 16 => {3130 const arena = scope.arena();
3160 return self.fail(scope, src, "TODO Implement addition for soft floats", .{});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);
3161 },3137 },
3162 32 => blk: {3138 .f32 => {
3163 const lhs_val = lhs.toFloat(f32);3139 const lhs_val = lhs.toFloat(f32);
3164 const rhs_val = rhs.toFloat(f32);3140 const rhs_val = rhs.toFloat(f32);
3165 const val_payload = try allocator.create(Value.Payload.Float_32);3141 return Value.Tag.float_32.create(arena, lhs_val + rhs_val);
3166 val_payload.* = .{ .val = lhs_val + rhs_val };
3167 break :blk &val_payload.base;
3168 },3142 },
3169 64 => blk: {3143 .f64 => {
3170 const lhs_val = lhs.toFloat(f64);3144 const lhs_val = lhs.toFloat(f64);
3171 const rhs_val = rhs.toFloat(f64);3145 const rhs_val = rhs.toFloat(f64);
3172 const val_payload = try allocator.create(Value.Payload.Float_64);3146 return Value.Tag.float_64.create(arena, lhs_val + rhs_val);
3173 val_payload.* = .{ .val = lhs_val + rhs_val };
3174 break :blk &val_payload.base;
3175 },3147 },
3176 128 => {3148 .f128, .comptime_float, .c_longdouble => {
3177 return self.fail(scope, src, "TODO Implement addition for big floats", .{});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);
3178 },3152 },
3179 else => unreachable,3153 else => unreachable,
3180 };3154 }
3181
3182 return Value.initPayload(val_payload);
3183}3155}
31843156
3185pub fn floatSub(self: *Module, scope: *Scope, float_type: Type, src: usize, lhs: Value, rhs: Value) !Value {3157pub fn floatSub(
3186 var bit_count = switch (float_type.tag()) {3158 self: *Module,
3187 .comptime_float => 128,3159 scope: *Scope,
3188 else => float_type.floatBits(self.getTarget()),3160 float_type: Type,
3189 };3161 src: usize,
31903162 lhs: Value,
3191 const allocator = scope.arena();3163 rhs: Value,
3192 const val_payload = switch (bit_count) {3164) !Value {
3193 16 => {3165 const arena = scope.arena();
3194 return self.fail(scope, src, "TODO Implement substraction for soft floats", .{});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);
3195 },3172 },
3196 32 => blk: {3173 .f32 => {
3197 const lhs_val = lhs.toFloat(f32);3174 const lhs_val = lhs.toFloat(f32);
3198 const rhs_val = rhs.toFloat(f32);3175 const rhs_val = rhs.toFloat(f32);
3199 const val_payload = try allocator.create(Value.Payload.Float_32);3176 return Value.Tag.float_32.create(arena, lhs_val - rhs_val);
3200 val_payload.* = .{ .val = lhs_val - rhs_val };
3201 break :blk &val_payload.base;
3202 },3177 },
3203 64 => blk: {3178 .f64 => {
3204 const lhs_val = lhs.toFloat(f64);3179 const lhs_val = lhs.toFloat(f64);
3205 const rhs_val = rhs.toFloat(f64);3180 const rhs_val = rhs.toFloat(f64);
3206 const val_payload = try allocator.create(Value.Payload.Float_64);3181 return Value.Tag.float_64.create(arena, lhs_val - rhs_val);
3207 val_payload.* = .{ .val = lhs_val - rhs_val };
3208 break :blk &val_payload.base;
3209 },3182 },
3210 128 => {3183 .f128, .comptime_float, .c_longdouble => {
3211 return self.fail(scope, src, "TODO Implement substraction for big floats", .{});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);
3212 },3187 },
3213 else => unreachable,3188 else => unreachable,
3214 };3189 }
3215
3216 return Value.initPayload(val_payload);
3217}3190}
32183191
3219pub fn simplePtrType(self: *Module, scope: *Scope, src: usize, elem_ty: Type, mutable: bool, size: std.builtin.TypeInfo.Pointer.Size) Allocator.Error!Type {3192pub 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...@@ -1956,13 +1956,13 @@ fn identifier(mod: *Module, scope: *Scope, rl: ResultLoc, ident: *ast.Node.OneTo
1956 32 => if (is_signed) Value.initTag(.i32_type) else Value.initTag(.u32_type),1956 32 => if (is_signed) Value.initTag(.i32_type) else Value.initTag(.u32_type),
1957 64 => if (is_signed) Value.initTag(.i64_type) else Value.initTag(.u64_type),1957 64 => if (is_signed) Value.initTag(.i64_type) else Value.initTag(.u64_type),
1958 else => {1958 else => {
1959 const int_type_payload = try scope.arena().create(Value.Payload.IntType);1959 return rlWrap(mod, scope, rl, try addZIRInstConst(mod, scope, src, .{
1960 int_type_payload.* = .{ .signed = is_signed, .bits = bit_count };
1961 const result = try addZIRInstConst(mod, scope, src, .{
1962 .ty = Type.initTag(.type),1960 .ty = Type.initTag(.type),
1963 .val = Value.initPayload(&int_type_payload.base),1961 .val = try Value.Tag.int_type.create(scope.arena(), .{
1964 });1962 .signed = is_signed,
1965 return rlWrap(mod, scope, rl, result);1963 .bits = bit_count,
1964 }),
1965 }));
1966 },1966 },
1967 };1967 };
1968 const result = try addZIRInstConst(mod, scope, src, .{1968 const result = try addZIRInstConst(mod, scope, src, .{
...@@ -2062,11 +2062,9 @@ fn charLiteral(mod: *Module, scope: *Scope, node: *ast.Node.OneToken) !*zir.Inst...@@ -2062,11 +2062,9 @@ fn charLiteral(mod: *Module, scope: *Scope, node: *ast.Node.OneToken) !*zir.Inst
2062 },2062 },
2063 };2063 };
20642064
2065 const int_payload = try scope.arena().create(Value.Payload.Int_u64);
2066 int_payload.* = .{ .int = value };
2067 return addZIRInstConst(mod, scope, src, .{2065 return addZIRInstConst(mod, scope, src, .{
2068 .ty = Type.initTag(.comptime_int),2066 .ty = Type.initTag(.comptime_int),
2069 .val = Value.initPayload(&int_payload.base),2067 .val = try Value.Tag.int_u64.create(scope.arena(), value),
2070 });2068 });
2071}2069}
20722070
...@@ -2089,12 +2087,10 @@ fn integerLiteral(mod: *Module, scope: *Scope, int_lit: *ast.Node.OneToken) Inne...@@ -2089,12 +2087,10 @@ fn integerLiteral(mod: *Module, scope: *Scope, int_lit: *ast.Node.OneToken) Inne
2089 prefixed_bytes[2..];2087 prefixed_bytes[2..];
20902088
2091 if (std.fmt.parseInt(u64, bytes, base)) |small_int| {2089 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 };
2094 const src = tree.token_locs[int_lit.token].start;2090 const src = tree.token_locs[int_lit.token].start;
2095 return addZIRInstConst(mod, scope, src, .{2091 return addZIRInstConst(mod, scope, src, .{
2096 .ty = Type.initTag(.comptime_int),2092 .ty = Type.initTag(.comptime_int),
2097 .val = Value.initPayload(&int_payload.base),2093 .val = try Value.Tag.int_u64.create(arena, small_int),
2098 });2094 });
2099 } else |err| {2095 } else |err| {
2100 return mod.failTok(scope, int_lit.token, "TODO implement int literals that don't fit in a u64", .{});2096 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...@@ -2109,15 +2105,13 @@ fn floatLiteral(mod: *Module, scope: *Scope, float_lit: *ast.Node.OneToken) Inne
2109 return mod.failTok(scope, float_lit.token, "TODO hex floats", .{});2105 return mod.failTok(scope, float_lit.token, "TODO hex floats", .{});
2110 }2106 }
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) {
2113 error.InvalidCharacter => unreachable, // validated by tokenizer2109 error.InvalidCharacter => unreachable, // validated by tokenizer
2114 };2110 };
2115 const float_payload = try arena.create(Value.Payload.Float_128);
2116 float_payload.* = .{ .val = val };
2117 const src = tree.token_locs[float_lit.token].start;2111 const src = tree.token_locs[float_lit.token].start;
2118 return addZIRInstConst(mod, scope, src, .{2112 return addZIRInstConst(mod, scope, src, .{
2119 .ty = Type.initTag(.comptime_float),2113 .ty = Type.initTag(.comptime_float),
2120 .val = Value.initPayload(&float_payload.base),2114 .val = try Value.Tag.float_128.create(arena, float_number),
2121 });2115 });
2122}2116}
21232117
src/codegen.zig+26-26
...@@ -137,7 +137,7 @@ pub fn generateSymbol(...@@ -137,7 +137,7 @@ pub fn generateSymbol(
137 },137 },
138 .Array => {138 .Array => {
139 // TODO populate .debug_info for the array139 // 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| {
141 if (typed_value.ty.sentinel()) |sentinel| {141 if (typed_value.ty.sentinel()) |sentinel| {
142 try code.ensureCapacity(code.items.len + payload.data.len + 1);142 try code.ensureCapacity(code.items.len + payload.data.len + 1);
143 code.appendSliceAssumeCapacity(payload.data);143 code.appendSliceAssumeCapacity(payload.data);
...@@ -168,8 +168,8 @@ pub fn generateSymbol(...@@ -168,8 +168,8 @@ pub fn generateSymbol(
168 },168 },
169 .Pointer => {169 .Pointer => {
170 // TODO populate .debug_info for the pointer170 // TODO populate .debug_info for the pointer
171 if (typed_value.val.cast(Value.Payload.DeclRef)) |payload| {171 if (typed_value.val.castTag(.decl_ref)) |payload| {
172 const decl = payload.decl;172 const decl = payload.data;
173 if (decl.analysis != .complete) return error.AnalysisFail;173 if (decl.analysis != .complete) return error.AnalysisFail;
174 // TODO handle the dependency of this symbol on the decl's vaddr.174 // TODO handle the dependency of this symbol on the decl's vaddr.
175 // If the decl changes vaddr, then this symbol needs to get regenerated.175 // 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 {...@@ -432,7 +432,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
432 @panic("Attempted to compile for architecture that was disabled by build configuration");432 @panic("Attempted to compile for architecture that was disabled by build configuration");
433 }433 }
434434
435 const module_fn = typed_value.val.cast(Value.Payload.Function).?.func;435 const module_fn = typed_value.val.castTag(.function).?.data;
436436
437 const fn_type = module_fn.owner_decl.typed_value.most_recent.typed_value.ty;437 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 {...@@ -1579,9 +1579,9 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
1579 }1579 }
1580 }1580 }
15811581
1582 if (inst.func.cast(ir.Inst.Constant)) |func_inst| {1582 if (inst.func.value()) |func_value| {
1583 if (func_inst.val.cast(Value.Payload.Function)) |func_val| {1583 if (func_value.castTag(.function)) |func_payload| {
1584 const func = func_val.func;1584 const func = func_payload.data;
15851585
1586 const ptr_bits = self.target.cpu.arch.ptrBitWidth();1586 const ptr_bits = self.target.cpu.arch.ptrBitWidth();
1587 const ptr_bytes: u64 = @divExact(ptr_bits, 8);1587 const ptr_bytes: u64 = @divExact(ptr_bits, 8);
...@@ -1607,9 +1607,9 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -1607,9 +1607,9 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
1607 .riscv64 => {1607 .riscv64 => {
1608 if (info.args.len > 0) return self.fail(inst.base.src, "TODO implement fn args for {}", .{self.target.cpu.arch});1608 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| {1610 if (inst.func.value()) |func_value| {
1611 if (func_inst.val.cast(Value.Payload.Function)) |func_val| {1611 if (func_value.castTag(.function)) |func_payload| {
1612 const func = func_val.func;1612 const func = func_payload.data;
16131613
1614 const ptr_bits = self.target.cpu.arch.ptrBitWidth();1614 const ptr_bits = self.target.cpu.arch.ptrBitWidth();
1615 const ptr_bytes: u64 = @divExact(ptr_bits, 8);1615 const ptr_bytes: u64 = @divExact(ptr_bits, 8);
...@@ -1631,12 +1631,12 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -1631,12 +1631,12 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
1631 }1631 }
1632 },1632 },
1633 .spu_2 => {1633 .spu_2 => {
1634 if (inst.func.cast(ir.Inst.Constant)) |func_inst| {1634 if (inst.func.value()) |func_value| {
1635 if (info.args.len != 0) {1635 if (info.args.len != 0) {
1636 return self.fail(inst.base.src, "TODO implement call with more than 0 parameters", .{});1636 return self.fail(inst.base.src, "TODO implement call with more than 0 parameters", .{});
1637 }1637 }
1638 if (func_inst.val.cast(Value.Payload.Function)) |func_val| {1638 if (func_value.castTag(.function)) |func_payload| {
1639 const func = func_val.func;1639 const func = func_payload.data;
1640 const got_addr = if (self.bin_file.cast(link.File.Elf)) |elf_file| blk: {1640 const got_addr = if (self.bin_file.cast(link.File.Elf)) |elf_file| blk: {
1641 const got = &elf_file.program_headers.items[elf_file.phdr_got_index.?];1641 const got = &elf_file.program_headers.items[elf_file.phdr_got_index.?];
1642 break :blk @intCast(u16, got.p_vaddr + func.owner_decl.link.elf.offset_table_index * 2);1642 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 {...@@ -1705,9 +1705,9 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
1705 }1705 }
1706 }1706 }
17071707
1708 if (inst.func.cast(ir.Inst.Constant)) |func_inst| {1708 if (inst.func.value()) |func_value| {
1709 if (func_inst.val.cast(Value.Payload.Function)) |func_val| {1709 if (func_value.castTag(.function)) |func_payload| {
1710 const func = func_val.func;1710 const func = func_payload.data;
1711 const ptr_bits = self.target.cpu.arch.ptrBitWidth();1711 const ptr_bits = self.target.cpu.arch.ptrBitWidth();
1712 const ptr_bytes: u64 = @divExact(ptr_bits, 8);1712 const ptr_bytes: u64 = @divExact(ptr_bits, 8);
1713 const got_addr = if (self.bin_file.cast(link.File.Elf)) |elf_file| blk: {1713 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 {...@@ -1766,9 +1766,9 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
1766 }1766 }
1767 }1767 }
17681768
1769 if (inst.func.cast(ir.Inst.Constant)) |func_inst| {1769 if (inst.func.value()) |func_value| {
1770 if (func_inst.val.cast(Value.Payload.Function)) |func_val| {1770 if (func_value.castTag(.function)) |func_payload| {
1771 const func = func_val.func;1771 const func = func_payload.data;
1772 const ptr_bits = self.target.cpu.arch.ptrBitWidth();1772 const ptr_bits = self.target.cpu.arch.ptrBitWidth();
1773 const ptr_bytes: u64 = @divExact(ptr_bits, 8);1773 const ptr_bytes: u64 = @divExact(ptr_bits, 8);
1774 const got_addr = if (self.bin_file.cast(link.File.Elf)) |elf_file| blk: {1774 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 {...@@ -1825,9 +1825,9 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
1825 }1825 }
1826 }1826 }
18271827
1828 if (inst.func.cast(ir.Inst.Constant)) |func_inst| {1828 if (inst.func.value()) |func_value| {
1829 if (func_inst.val.cast(Value.Payload.Function)) |func_val| {1829 if (func_value.castTag(.function)) |func_payload| {
1830 const func = func_val.func;1830 const func = func_payload.data;
1831 const text_segment = &macho_file.load_commands.items[macho_file.text_segment_cmd_index.?].Segment;1831 const text_segment = &macho_file.load_commands.items[macho_file.text_segment_cmd_index.?].Segment;
1832 const got = &text_segment.sections.items[macho_file.got_section_index.?];1832 const got = &text_segment.sections.items[macho_file.got_section_index.?];
1833 const got_addr = got.addr + func.owner_decl.link.macho.offset_table_index * @sizeOf(u64);1833 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 {...@@ -3223,20 +3223,20 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
3223 const ptr_bytes: u64 = @divExact(ptr_bits, 8);3223 const ptr_bytes: u64 = @divExact(ptr_bits, 8);
3224 switch (typed_value.ty.zigTypeTag()) {3224 switch (typed_value.ty.zigTypeTag()) {
3225 .Pointer => {3225 .Pointer => {
3226 if (typed_value.val.cast(Value.Payload.DeclRef)) |payload| {3226 if (typed_value.val.castTag(.decl_ref)) |payload| {
3227 if (self.bin_file.cast(link.File.Elf)) |elf_file| {3227 if (self.bin_file.cast(link.File.Elf)) |elf_file| {
3228 const decl = payload.decl;3228 const decl = payload.data;
3229 const got = &elf_file.program_headers.items[elf_file.phdr_got_index.?];3229 const got = &elf_file.program_headers.items[elf_file.phdr_got_index.?];
3230 const got_addr = got.p_vaddr + decl.link.elf.offset_table_index * ptr_bytes;3230 const got_addr = got.p_vaddr + decl.link.elf.offset_table_index * ptr_bytes;
3231 return MCValue{ .memory = got_addr };3231 return MCValue{ .memory = got_addr };
3232 } else if (self.bin_file.cast(link.File.MachO)) |macho_file| {3232 } else if (self.bin_file.cast(link.File.MachO)) |macho_file| {
3233 const decl = payload.decl;3233 const decl = payload.data;
3234 const text_segment = &macho_file.load_commands.items[macho_file.text_segment_cmd_index.?].Segment;3234 const text_segment = &macho_file.load_commands.items[macho_file.text_segment_cmd_index.?].Segment;
3235 const got = &text_segment.sections.items[macho_file.got_section_index.?];3235 const got = &text_segment.sections.items[macho_file.got_section_index.?];
3236 const got_addr = got.addr + decl.link.macho.offset_table_index * ptr_bytes;3236 const got_addr = got.addr + decl.link.macho.offset_table_index * ptr_bytes;
3237 return MCValue{ .memory = got_addr };3237 return MCValue{ .memory = got_addr };
3238 } else if (self.bin_file.cast(link.File.Coff)) |coff_file| {3238 } else if (self.bin_file.cast(link.File.Coff)) |coff_file| {
3239 const decl = payload.decl;3239 const decl = payload.data;
3240 const got_addr = coff_file.offset_table_virtual_address + decl.link.coff.offset_table_index * ptr_bytes;3240 const got_addr = coff_file.offset_table_virtual_address + decl.link.coff.offset_table_index * ptr_bytes;
3241 return MCValue{ .memory = got_addr };3241 return MCValue{ .memory = got_addr };
3242 } else {3242 } else {
src/codegen/c.zig+18-18
...@@ -138,25 +138,25 @@ fn renderValue(...@@ -138,25 +138,25 @@ fn renderValue(
138 .undef, .zero => try writer.writeAll("0"),138 .undef, .zero => try writer.writeAll("0"),
139 .one => try writer.writeAll("1"),139 .one => try writer.writeAll("1"),
140 .decl_ref => {140 .decl_ref => {
141 const decl_ref_payload = val.cast(Value.Payload.DeclRef).?;141 const decl = val.castTag(.decl_ref).?.data;
142142
143 // Determine if we must pointer cast.143 // 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;
145 if (t.eql(decl_tv.ty)) {145 if (t.eql(decl_tv.ty)) {
146 try writer.print("&{s}", .{decl_ref_payload.decl.name});146 try writer.print("&{s}", .{decl.name});
147 } else {147 } else {
148 try writer.writeAll("(");148 try writer.writeAll("(");
149 try renderType(ctx, writer, t);149 try renderType(ctx, writer, t);
150 try writer.print(")&{s}", .{decl_ref_payload.decl.name});150 try writer.print(")&{s}", .{decl.name});
151 }151 }
152 },152 },
153 .function => {153 .function => {
154 const payload = val.cast(Value.Payload.Function).?;154 const func = val.castTag(.function).?.data;
155 try writer.print("{s}", .{payload.func.owner_decl.name});155 try writer.print("{s}", .{func.owner_decl.name});
156 },156 },
157 .extern_fn => {157 .extern_fn => {
158 const payload = val.cast(Value.Payload.ExternFn).?;158 const decl = val.castTag(.extern_fn).?.data;
159 try writer.print("{s}", .{payload.decl.name});159 try writer.print("{s}", .{decl.name});
160 },160 },
161 else => |e| return ctx.fail(161 else => |e| return ctx.fail(
162 ctx.decl.src(),162 ctx.decl.src(),
...@@ -169,7 +169,7 @@ fn renderValue(...@@ -169,7 +169,7 @@ fn renderValue(
169 switch (val.tag()) {169 switch (val.tag()) {
170 .undef, .empty_struct_value, .empty_array => try writer.writeAll("{}"),170 .undef, .empty_struct_value, .empty_array => try writer.writeAll("{}"),
171 .bytes => {171 .bytes => {
172 const bytes = val.cast(Value.Payload.Bytes).?.data;172 const bytes = val.castTag(.bytes).?.data;
173 // TODO: make our own C string escape instead of using {Z}173 // TODO: make our own C string escape instead of using {Z}
174 try writer.print("\"{Z}\"", .{bytes});174 try writer.print("\"{Z}\"", .{bytes});
175 },175 },
...@@ -209,7 +209,7 @@ fn renderFunctionSignature(...@@ -209,7 +209,7 @@ fn renderFunctionSignature(
209 switch (tv.val.tag()) {209 switch (tv.val.tag()) {
210 .extern_fn => break :blk true,210 .extern_fn => break :blk true,
211 .function => {211 .function => {
212 const func = tv.val.cast(Value.Payload.Function).?.func;212 const func = tv.val.castTag(.function).?.data;
213 break :blk ctx.module.decl_exports.contains(func.owner_decl);213 break :blk ctx.module.decl_exports.contains(func.owner_decl);
214 },214 },
215 else => unreachable,215 else => unreachable,
...@@ -268,13 +268,13 @@ pub fn generate(file: *C, module: *Module, decl: *Decl) !void {...@@ -268,13 +268,13 @@ pub fn generate(file: *C, module: *Module, decl: *Decl) !void {
268 ctx.deinit();268 ctx.deinit();
269 }269 }
270270
271 if (tv.val.cast(Value.Payload.Function)) |func_payload| {271 if (tv.val.castTag(.function)) |func_payload| {
272 const writer = file.main.writer();272 const writer = file.main.writer();
273 try renderFunctionSignature(&ctx, writer, decl);273 try renderFunctionSignature(&ctx, writer, decl);
274274
275 try writer.writeAll(" {");275 try writer.writeAll(" {");
276276
277 const func: *Module.Fn = func_payload.func;277 const func: *Module.Fn = func_payload.data;
278 const instructions = func.analysis.success.instructions;278 const instructions = func.analysis.success.instructions;
279 if (instructions.len > 0) {279 if (instructions.len > 0) {
280 try writer.writeAll("\n");280 try writer.writeAll("\n");
...@@ -480,10 +480,10 @@ fn genCall(ctx: *Context, file: *C, inst: *Inst.Call) !?[]u8 {...@@ -480,10 +480,10 @@ fn genCall(ctx: *Context, file: *C, inst: *Inst.Call) !?[]u8 {
480 const writer = file.main.writer();480 const writer = file.main.writer();
481 const header = file.header.buf.writer();481 const header = file.header.buf.writer();
482 if (inst.func.castTag(.constant)) |func_inst| {482 if (inst.func.castTag(.constant)) |func_inst| {
483 const fn_decl = if (func_inst.val.cast(Value.Payload.ExternFn)) |extern_fn|483 const fn_decl = if (func_inst.val.castTag(.extern_fn)) |extern_fn|
484 extern_fn.decl484 extern_fn.data
485 else if (func_inst.val.cast(Value.Payload.Function)) |func_val|485 else if (func_inst.val.castTag(.function)) |func_payload|
486 func_val.func.owner_decl486 func_payload.data.owner_decl
487 else487 else
488 unreachable;488 unreachable;
489489
...@@ -513,8 +513,8 @@ fn genCall(ctx: *Context, file: *C, inst: *Inst.Call) !?[]u8 {...@@ -513,8 +513,8 @@ fn genCall(ctx: *Context, file: *C, inst: *Inst.Call) !?[]u8 {
513 if (i > 0) {513 if (i > 0) {
514 try writer.writeAll(", ");514 try writer.writeAll(", ");
515 }515 }
516 if (arg.cast(Inst.Constant)) |con| {516 if (arg.value()) |val| {
517 try renderValue(ctx, writer, arg.ty, con.val);517 try renderValue(ctx, writer, arg.ty, val);
518 } else {518 } else {
519 const val = try ctx.resolveInst(arg);519 const val = try ctx.resolveInst(arg);
520 try writer.print("{}", .{val});520 try writer.print("{}", .{val});
src/codegen/wasm.zig+3-3
...@@ -62,7 +62,7 @@ pub fn genCode(buf: *ArrayList(u8), decl: *Decl) !void {...@@ -62,7 +62,7 @@ pub fn genCode(buf: *ArrayList(u8), decl: *Decl) !void {
62 // Write instructions62 // Write instructions
63 // TODO: check for and handle death of instructions63 // TODO: check for and handle death of instructions
64 const tv = decl.typed_value.most_recent.typed_value;64 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;
66 for (mod_fn.analysis.success.instructions) |inst| try genInst(buf, decl, inst);66 for (mod_fn.analysis.success.instructions) |inst| try genInst(buf, decl, inst);
6767
68 // Write 'end' opcode68 // Write 'end' opcode
...@@ -125,8 +125,8 @@ fn genRet(buf: *ArrayList(u8), decl: *Decl, inst: *Inst.UnOp) !void {...@@ -125,8 +125,8 @@ fn genRet(buf: *ArrayList(u8), decl: *Decl, inst: *Inst.UnOp) !void {
125125
126fn genCall(buf: *ArrayList(u8), decl: *Decl, inst: *Inst.Call) !void {126fn genCall(buf: *ArrayList(u8), decl: *Decl, inst: *Inst.Call) !void {
127 const func_inst = inst.func.castTag(.constant).?;127 const func_inst = inst.func.castTag(.constant).?;
128 const func_val = func_inst.val.cast(Value.Payload.Function).?;128 const func = func_inst.val.castTag(.function).?.data;
129 const target = func_val.func.owner_decl;129 const target = func.owner_decl;
130 const target_ty = target.typed_value.most_recent.typed_value.ty;130 const target_ty = target.typed_value.most_recent.typed_value.ty;
131131
132 if (inst.args.len != 0) return error.TODOImplementMoreWasmCodegen;132 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 {...@@ -2183,7 +2183,7 @@ pub fn updateDecl(self: *Elf, module: *Module, decl: *Module.Decl) !void {
2183 for (zir_dumps) |fn_name| {2183 for (zir_dumps) |fn_name| {
2184 if (mem.eql(u8, mem.spanZ(decl.name), fn_name)) {2184 if (mem.eql(u8, mem.spanZ(decl.name), fn_name)) {
2185 std.debug.print("\n{}\n", .{decl.name});2185 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.*);
2187 }2187 }
2188 }2188 }
2189 }2189 }
src/llvm_backend.zig+4-4
...@@ -280,7 +280,7 @@ pub const LLVMIRModule = struct {...@@ -280,7 +280,7 @@ pub const LLVMIRModule = struct {
280 fn gen(self: *LLVMIRModule, module: *Module, typed_value: TypedValue, src: usize) !void {280 fn gen(self: *LLVMIRModule, module: *Module, typed_value: TypedValue, src: usize) !void {
281 switch (typed_value.ty.zigTypeTag()) {281 switch (typed_value.ty.zigTypeTag()) {
282 .Fn => {282 .Fn => {
283 const func = typed_value.val.cast(Value.Payload.Function).?.func;283 const func = typed_value.val.castTag(.function).?.data;
284284
285 const llvm_func = try self.resolveLLVMFunction(func);285 const llvm_func = try self.resolveLLVMFunction(func);
286286
...@@ -314,9 +314,9 @@ pub const LLVMIRModule = struct {...@@ -314,9 +314,9 @@ pub const LLVMIRModule = struct {
314 }314 }
315315
316 fn genCall(self: *LLVMIRModule, inst: *Inst.Call) !void {316 fn genCall(self: *LLVMIRModule, inst: *Inst.Call) !void {
317 if (inst.func.cast(Inst.Constant)) |func_inst| {317 if (inst.func.value()) |func_value| {
318 if (func_inst.val.cast(Value.Payload.Function)) |func_val| {318 if (func_value.castTag(.function)) |func_payload| {
319 const func = func_val.func;319 const func = func_payload.data;
320 const zig_fn_type = func.owner_decl.typed_value.most_recent.typed_value.ty;320 const zig_fn_type = func.owner_decl.typed_value.most_recent.typed_value.ty;
321 const llvm_fn = try self.resolveLLVMFunction(func);321 const llvm_fn = try self.resolveLLVMFunction(func);
322322
src/type.zig+11-32
...@@ -733,11 +733,7 @@ pub const Type = extern union {...@@ -733,11 +733,7 @@ pub const Type = extern union {
733 .single_const_pointer_to_comptime_int => return Value.initTag(.single_const_pointer_to_comptime_int_type),733 .single_const_pointer_to_comptime_int => return Value.initTag(.single_const_pointer_to_comptime_int_type),
734 .const_slice_u8 => return Value.initTag(.const_slice_u8_type),734 .const_slice_u8 => return Value.initTag(.const_slice_u8_type),
735 .enum_literal => return Value.initTag(.enum_literal_type),735 .enum_literal => return Value.initTag(.enum_literal_type),
736 else => {736 else => return Value.Tag.ty.create(allocator, self),
737 const ty_payload = try allocator.create(Value.Payload.Ty);
738 ty_payload.* = .{ .ty = self };
739 return Value.initPayload(&ty_payload.base);
740 },
741 }737 }
742 }738 }
743739
...@@ -2951,11 +2947,8 @@ pub const Type = extern union {...@@ -2951,11 +2947,8 @@ pub const Type = extern union {
2951 }2947 }
29522948
2953 if ((info.bits - 1) <= std.math.maxInt(u6)) {2949 if ((info.bits - 1) <= std.math.maxInt(u6)) {
2954 const payload = try arena.allocator.create(Value.Payload.Int_i64);2950 const n: i64 = -(@as(i64, 1) << @truncate(u6, info.bits - 1));
2955 payload.* = .{2951 return Value.Tag.int_i64.create(&arena.allocator, n);
2956 .int = -(@as(i64, 1) << @truncate(u6, info.bits - 1)),
2957 };
2958 return Value.initPayload(&payload.base);
2959 }2952 }
29602953
2961 var res = try std.math.big.int.Managed.initSet(&arena.allocator, 1);2954 var res = try std.math.big.int.Managed.initSet(&arena.allocator, 1);
...@@ -2964,13 +2957,9 @@ pub const Type = extern union {...@@ -2964,13 +2957,9 @@ pub const Type = extern union {
29642957
2965 const res_const = res.toConst();2958 const res_const = res.toConst();
2966 if (res_const.positive) {2959 if (res_const.positive) {
2967 const val_payload = try arena.allocator.create(Value.Payload.IntBigPositive);2960 return Value.Tag.int_big_positive.create(&arena.allocator, res_const.limbs);
2968 val_payload.* = .{ .limbs = res_const.limbs };
2969 return Value.initPayload(&val_payload.base);
2970 } else {2961 } else {
2971 const val_payload = try arena.allocator.create(Value.Payload.IntBigNegative);2962 return Value.Tag.int_big_negative.create(&arena.allocator, res_const.limbs);
2972 val_payload.* = .{ .limbs = res_const.limbs };
2973 return Value.initPayload(&val_payload.base);
2974 }2963 }
2975 }2964 }
29762965
...@@ -2980,17 +2969,11 @@ pub const Type = extern union {...@@ -2980,17 +2969,11 @@ pub const Type = extern union {
2980 const info = self.intInfo(target);2969 const info = self.intInfo(target);
29812970
2982 if (info.signedness == .signed and (info.bits - 1) <= std.math.maxInt(u6)) {2971 if (info.signedness == .signed and (info.bits - 1) <= std.math.maxInt(u6)) {
2983 const payload = try arena.allocator.create(Value.Payload.Int_i64);2972 const n: i64 = (@as(i64, 1) << @truncate(u6, info.bits - 1)) - 1;
2984 payload.* = .{2973 return Value.Tag.int_i64.create(&arena.allocator, n);
2985 .int = (@as(i64, 1) << @truncate(u6, info.bits - 1)) - 1,
2986 };
2987 return Value.initPayload(&payload.base);
2988 } else if (info.signedness == .signed and info.bits <= std.math.maxInt(u6)) {2974 } else if (info.signedness == .signed and info.bits <= std.math.maxInt(u6)) {
2989 const payload = try arena.allocator.create(Value.Payload.Int_u64);2975 const n: u64 = (@as(u64, 1) << @truncate(u6, info.bits)) - 1;
2990 payload.* = .{2976 return Value.Tag.int_u64.create(&arena.allocator, n);
2991 .int = (@as(u64, 1) << @truncate(u6, info.bits)) - 1,
2992 };
2993 return Value.initPayload(&payload.base);
2994 }2977 }
29952978
2996 var res = try std.math.big.int.Managed.initSet(&arena.allocator, 1);2979 var res = try std.math.big.int.Managed.initSet(&arena.allocator, 1);
...@@ -3003,13 +2986,9 @@ pub const Type = extern union {...@@ -3003,13 +2986,9 @@ pub const Type = extern union {
30032986
3004 const res_const = res.toConst();2987 const res_const = res.toConst();
3005 if (res_const.positive) {2988 if (res_const.positive) {
3006 const val_payload = try arena.allocator.create(Value.Payload.IntBigPositive);2989 return Value.Tag.int_big_positive.create(&arena.allocator, res_const.limbs);
3007 val_payload.* = .{ .limbs = res_const.limbs };
3008 return Value.initPayload(&val_payload.base);
3009 } else {2990 } else {
3010 const val_payload = try arena.allocator.create(Value.Payload.IntBigNegative);2991 return Value.Tag.int_big_negative.create(&arena.allocator, res_const.limbs);
3011 val_payload.* = .{ .limbs = res_const.limbs };
3012 return Value.initPayload(&val_payload.base);
3013 }2992 }
3014 }2993 }
30152994
src/value.zig+363-236
...@@ -84,11 +84,16 @@ pub const Value = extern union {...@@ -84,11 +84,16 @@ pub const Value = extern union {
84 function,84 function,
85 extern_fn,85 extern_fn,
86 variable,86 variable,
87 /// Represents a pointer to another immutable value.
87 ref_val,88 ref_val,
89 /// Represents a pointer to a decl, not the value of the decl.
88 decl_ref,90 decl_ref,
89 elem_ptr,91 elem_ptr,
92 /// A slice of u8 whose memory is managed externally.
90 bytes,93 bytes,
91 repeated, // the value is a value repeated some number of times94 /// This value is repeated some number of times. The amount of times to repeat
95 /// is stored externally.
96 repeated,
92 float_16,97 float_16,
93 float_32,98 float_32,
94 float_64,99 float_64,
...@@ -99,6 +104,106 @@ pub const Value = extern union {...@@ -99,6 +104,106 @@ pub const Value = extern union {
99104
100 pub const last_no_payload_tag = Tag.bool_false;105 pub const last_no_payload_tag = Tag.bool_false;
101 pub const no_payload_count = @enumToInt(last_no_payload_tag) + 1;106 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 }
102 };207 };
103208
104 pub fn initTag(small_tag: Tag) Value {209 pub fn initTag(small_tag: Tag) Value {
...@@ -119,15 +224,36 @@ pub const Value = extern union {...@@ -119,15 +224,36 @@ pub const Value = extern union {
119 }224 }
120 }225 }
121226
227 /// Prefer `castTag` to this.
122 pub fn cast(self: Value, comptime T: type) ?*T {228 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) {
124 return null;233 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;249 pub fn castTag(self: Value, comptime t: Tag) ?*t.Type() {
127 if (self.ptr_otherwise.tag != expected_tag)250 if (self.tag_if_small_enough < Tag.no_payload_count)
128 return null;251 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;
131 }257 }
132258
133 pub fn copy(self: Value, allocator: *Allocator) error{OutOfMemory}!Value {259 pub fn copy(self: Value, allocator: *Allocator) error{OutOfMemory}!Value {
...@@ -188,17 +314,17 @@ pub const Value = extern union {...@@ -188,17 +314,17 @@ pub const Value = extern union {
188 => unreachable,314 => unreachable,
189315
190 .ty => {316 .ty => {
191 const payload = @fieldParentPtr(Payload.Ty, "base", self.ptr_otherwise);317 const payload = self.castTag(.ty).?;
192 const new_payload = try allocator.create(Payload.Ty);318 const new_payload = try allocator.create(Payload.Ty);
193 new_payload.* = .{319 new_payload.* = .{
194 .base = payload.base,320 .base = payload.base,
195 .ty = try payload.ty.copy(allocator),321 .data = try payload.data.copy(allocator),
196 };322 };
197 return Value{ .ptr_otherwise = &new_payload.base };323 return Value{ .ptr_otherwise = &new_payload.base };
198 },324 },
199 .int_type => return self.copyPayloadShallow(allocator, Payload.IntType),325 .int_type => return self.copyPayloadShallow(allocator, Payload.IntType),
200 .int_u64 => return self.copyPayloadShallow(allocator, Payload.Int_u64),326 .int_u64 => return self.copyPayloadShallow(allocator, Payload.U64),
201 .int_i64 => return self.copyPayloadShallow(allocator, Payload.Int_i64),327 .int_i64 => return self.copyPayloadShallow(allocator, Payload.I64),
202 .int_big_positive => {328 .int_big_positive => {
203 @panic("TODO implement copying of big ints");329 @panic("TODO implement copying of big ints");
204 },330 },
...@@ -206,35 +332,37 @@ pub const Value = extern union {...@@ -206,35 +332,37 @@ pub const Value = extern union {
206 @panic("TODO implement copying of big ints");332 @panic("TODO implement copying of big ints");
207 },333 },
208 .function => return self.copyPayloadShallow(allocator, Payload.Function),334 .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),
210 .variable => return self.copyPayloadShallow(allocator, Payload.Variable),336 .variable => return self.copyPayloadShallow(allocator, Payload.Variable),
211 .ref_val => {337 .ref_val => {
212 const payload = @fieldParentPtr(Payload.RefVal, "base", self.ptr_otherwise);338 const payload = self.castTag(.ref_val).?;
213 const new_payload = try allocator.create(Payload.RefVal);339 const new_payload = try allocator.create(Payload.SubValue);
214 new_payload.* = .{340 new_payload.* = .{
215 .base = payload.base,341 .base = payload.base,
216 .val = try payload.val.copy(allocator),342 .data = try payload.data.copy(allocator),
217 };343 };
218 return Value{ .ptr_otherwise = &new_payload.base };344 return Value{ .ptr_otherwise = &new_payload.base };
219 },345 },
220 .decl_ref => return self.copyPayloadShallow(allocator, Payload.DeclRef),346 .decl_ref => return self.copyPayloadShallow(allocator, Payload.Decl),
221 .elem_ptr => {347 .elem_ptr => {
222 const payload = @fieldParentPtr(Payload.ElemPtr, "base", self.ptr_otherwise);348 const payload = self.castTag(.elem_ptr).?;
223 const new_payload = try allocator.create(Payload.ElemPtr);349 const new_payload = try allocator.create(Payload.ElemPtr);
224 new_payload.* = .{350 new_payload.* = .{
225 .base = payload.base,351 .base = payload.base,
226 .array_ptr = try payload.array_ptr.copy(allocator),352 .data = .{
227 .index = payload.index,353 .array_ptr = try payload.data.array_ptr.copy(allocator),
354 .index = payload.data.index,
355 },
228 };356 };
229 return Value{ .ptr_otherwise = &new_payload.base };357 return Value{ .ptr_otherwise = &new_payload.base };
230 },358 },
231 .bytes => return self.copyPayloadShallow(allocator, Payload.Bytes),359 .bytes => return self.copyPayloadShallow(allocator, Payload.Bytes),
232 .repeated => {360 .repeated => {
233 const payload = @fieldParentPtr(Payload.Repeated, "base", self.ptr_otherwise);361 const payload = self.castTag(.repeated).?;
234 const new_payload = try allocator.create(Payload.Repeated);362 const new_payload = try allocator.create(Payload.SubValue);
235 new_payload.* = .{363 new_payload.* = .{
236 .base = payload.base,364 .base = payload.base,
237 .val = try payload.val.copy(allocator),365 .data = try payload.data.copy(allocator),
238 };366 };
239 return Value{ .ptr_otherwise = &new_payload.base };367 return Value{ .ptr_otherwise = &new_payload.base };
240 },368 },
...@@ -243,7 +371,7 @@ pub const Value = extern union {...@@ -243,7 +371,7 @@ pub const Value = extern union {
243 .float_64 => return self.copyPayloadShallow(allocator, Payload.Float_64),371 .float_64 => return self.copyPayloadShallow(allocator, Payload.Float_64),
244 .float_128 => return self.copyPayloadShallow(allocator, Payload.Float_128),372 .float_128 => return self.copyPayloadShallow(allocator, Payload.Float_128),
245 .enum_literal => {373 .enum_literal => {
246 const payload = @fieldParentPtr(Payload.Bytes, "base", self.ptr_otherwise);374 const payload = self.castTag(.enum_literal).?;
247 const new_payload = try allocator.create(Payload.Bytes);375 const new_payload = try allocator.create(Payload.Bytes);
248 new_payload.* = .{376 new_payload.* = .{
249 .base = payload.base,377 .base = payload.base,
...@@ -259,7 +387,7 @@ pub const Value = extern union {...@@ -259,7 +387,7 @@ pub const Value = extern union {
259 }387 }
260388
261 fn copyPayloadShallow(self: Value, allocator: *Allocator, comptime T: type) error{OutOfMemory}!Value {389 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).?;
263 const new_payload = try allocator.create(T);391 const new_payload = try allocator.create(T);
264 new_payload.* = payload.*;392 new_payload.* = payload.*;
265 return Value{ .ptr_otherwise = &new_payload.base };393 return Value{ .ptr_otherwise = &new_payload.base };
...@@ -326,45 +454,45 @@ pub const Value = extern union {...@@ -326,45 +454,45 @@ pub const Value = extern union {
326 .unreachable_value => return out_stream.writeAll("unreachable"),454 .unreachable_value => return out_stream.writeAll("unreachable"),
327 .bool_true => return out_stream.writeAll("true"),455 .bool_true => return out_stream.writeAll("true"),
328 .bool_false => return out_stream.writeAll("false"),456 .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),
330 .int_type => {458 .int_type => {
331 const int_type = val.cast(Payload.IntType).?;459 const int_type = val.castTag(.int_type).?.data;
332 return out_stream.print("{}{}", .{460 return out_stream.print("{}{}", .{
333 if (int_type.signed) "s" else "u",461 if (int_type.signed) "s" else "u",
334 int_type.bits,462 int_type.bits,
335 });463 });
336 },464 },
337 .int_u64 => return std.fmt.formatIntValue(val.cast(Payload.Int_u64).?.int, "", options, out_stream),465 .int_u64 => return std.fmt.formatIntValue(val.castTag(.int_u64).?.data, "", options, out_stream),
338 .int_i64 => return std.fmt.formatIntValue(val.cast(Payload.Int_i64).?.int, "", options, out_stream),466 .int_i64 => return std.fmt.formatIntValue(val.castTag(.int_i64).?.data, "", options, out_stream),
339 .int_big_positive => return out_stream.print("{}", .{val.cast(Payload.IntBigPositive).?.asBigInt()}),467 .int_big_positive => return out_stream.print("{}", .{val.castTag(.int_big_positive).?.asBigInt()}),
340 .int_big_negative => return out_stream.print("{}", .{val.cast(Payload.IntBigNegative).?.asBigInt()}),468 .int_big_negative => return out_stream.print("{}", .{val.castTag(.int_big_negative).?.asBigInt()}),
341 .function => return out_stream.writeAll("(function)"),469 .function => return out_stream.writeAll("(function)"),
342 .extern_fn => return out_stream.writeAll("(extern function)"),470 .extern_fn => return out_stream.writeAll("(extern function)"),
343 .variable => return out_stream.writeAll("(variable)"),471 .variable => return out_stream.writeAll("(variable)"),
344 .ref_val => {472 .ref_val => {
345 const ref_val = val.cast(Payload.RefVal).?;473 const ref_val = val.castTag(.ref_val).?.data;
346 try out_stream.writeAll("&const ");474 try out_stream.writeAll("&const ");
347 val = ref_val.val;475 val = ref_val;
348 },476 },
349 .decl_ref => return out_stream.writeAll("(decl ref)"),477 .decl_ref => return out_stream.writeAll("(decl ref)"),
350 .elem_ptr => {478 .elem_ptr => {
351 const elem_ptr = val.cast(Payload.ElemPtr).?;479 const elem_ptr = val.castTag(.elem_ptr).?.data;
352 try out_stream.print("&[{}] ", .{elem_ptr.index});480 try out_stream.print("&[{}] ", .{elem_ptr.index});
353 val = elem_ptr.array_ptr;481 val = elem_ptr.array_ptr;
354 },482 },
355 .empty_array => return out_stream.writeAll(".{}"),483 .empty_array => return out_stream.writeAll(".{}"),
356 .enum_literal => return out_stream.print(".{z}", .{self.cast(Payload.Bytes).?.data}),484 .enum_literal => return out_stream.print(".{z}", .{self.castTag(.enum_literal).?.data}),
357 .bytes => return out_stream.print("\"{Z}\"", .{self.cast(Payload.Bytes).?.data}),485 .bytes => return out_stream.print("\"{Z}\"", .{self.castTag(.bytes).?.data}),
358 .repeated => {486 .repeated => {
359 try out_stream.writeAll("(repeated) ");487 try out_stream.writeAll("(repeated) ");
360 val = val.cast(Payload.Repeated).?.val;488 val = val.castTag(.repeated).?.data;
361 },489 },
362 .float_16 => return out_stream.print("{}", .{val.cast(Payload.Float_16).?.val}),490 .float_16 => return out_stream.print("{}", .{val.castTag(.float_16).?.data}),
363 .float_32 => return out_stream.print("{}", .{val.cast(Payload.Float_32).?.val}),491 .float_32 => return out_stream.print("{}", .{val.castTag(.float_32).?.data}),
364 .float_64 => return out_stream.print("{}", .{val.cast(Payload.Float_64).?.val}),492 .float_64 => return out_stream.print("{}", .{val.castTag(.float_64).?.data}),
365 .float_128 => return out_stream.print("{}", .{val.cast(Payload.Float_128).?.val}),493 .float_128 => return out_stream.print("{}", .{val.castTag(.float_128).?.data}),
366 .error_set => {494 .error_set => {
367 const error_set = val.cast(Payload.ErrorSet).?;495 const error_set = val.castTag(.error_set).?.data;
368 try out_stream.writeAll("error{");496 try out_stream.writeAll("error{");
369 var it = error_set.fields.iterator();497 var it = error_set.fields.iterator();
370 while (it.next()) |entry| {498 while (it.next()) |entry| {
...@@ -372,21 +500,24 @@ pub const Value = extern union {...@@ -372,21 +500,24 @@ pub const Value = extern union {
372 }500 }
373 return out_stream.writeAll("}");501 return out_stream.writeAll("}");
374 },502 },
375 .@"error" => return out_stream.print("error.{}", .{val.cast(Payload.Error).?.name}),503 .@"error" => return out_stream.print("error.{}", .{val.castTag(.@"error").?.data.name}),
376 };504 };
377 }505 }
378506
379 /// Asserts that the value is representable as an array of bytes.507 /// Asserts that the value is representable as an array of bytes.
380 /// Copies the value into a freshly allocated slice of memory, which is owned by the caller.508 /// Copies the value into a freshly allocated slice of memory, which is owned by the caller.
381 pub fn toAllocatedBytes(self: Value, allocator: *Allocator) ![]u8 {509 pub fn toAllocatedBytes(self: Value, allocator: *Allocator) ![]u8 {
382 if (self.cast(Payload.Bytes)) |bytes| {510 if (self.castTag(.bytes)) |payload| {
383 return std.mem.dupe(allocator, u8, bytes.data);511 return std.mem.dupe(allocator, u8, payload.data);
384 }512 }
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| {
386 @panic("TODO implement toAllocatedBytes for this Value tag");517 @panic("TODO implement toAllocatedBytes for this Value tag");
387 }518 }
388 if (self.cast(Payload.DeclRef)) |declref| {519 if (self.castTag(.decl_ref)) |payload| {
389 const val = try declref.decl.value();520 const val = try payload.data.value();
390 return val.toAllocatedBytes(allocator);521 return val.toAllocatedBytes(allocator);
391 }522 }
392 unreachable;523 unreachable;
...@@ -395,7 +526,7 @@ pub const Value = extern union {...@@ -395,7 +526,7 @@ pub const Value = extern union {
395 /// Asserts that the value is representable as a type.526 /// Asserts that the value is representable as a type.
396 pub fn toType(self: Value, allocator: *Allocator) !Type {527 pub fn toType(self: Value, allocator: *Allocator) !Type {
397 return switch (self.tag()) {528 return switch (self.tag()) {
398 .ty => self.cast(Payload.Ty).?.ty,529 .ty => self.castTag(.ty).?.data,
399 .u8_type => Type.initTag(.u8),530 .u8_type => Type.initTag(.u8),
400 .i8_type => Type.initTag(.i8),531 .i8_type => Type.initTag(.i8),
401 .u16_type => Type.initTag(.u16),532 .u16_type => Type.initTag(.u16),
...@@ -439,7 +570,7 @@ pub const Value = extern union {...@@ -439,7 +570,7 @@ pub const Value = extern union {
439 .anyframe_type => Type.initTag(.@"anyframe"),570 .anyframe_type => Type.initTag(.@"anyframe"),
440571
441 .int_type => {572 .int_type => {
442 const payload = self.cast(Payload.IntType).?;573 const payload = self.castTag(.int_type).?.data;
443 const new = try allocator.create(Type.Payload.Bits);574 const new = try allocator.create(Type.Payload.Bits);
444 new.* = .{575 new.* = .{
445 .base = .{576 .base = .{
...@@ -450,7 +581,7 @@ pub const Value = extern union {...@@ -450,7 +581,7 @@ pub const Value = extern union {
450 return Type.initPayload(&new.base);581 return Type.initPayload(&new.base);
451 },582 },
452 .error_set => {583 .error_set => {
453 const payload = self.cast(Payload.ErrorSet).?;584 const payload = self.castTag(.error_set).?.data;
454 return Type.Tag.error_set.create(allocator, payload.decl);585 return Type.Tag.error_set.create(allocator, payload.decl);
455 },586 },
456587
...@@ -564,10 +695,10 @@ pub const Value = extern union {...@@ -564,10 +695,10 @@ pub const Value = extern union {
564 .bool_true,695 .bool_true,
565 => return BigIntMutable.init(&space.limbs, 1).toConst(),696 => return BigIntMutable.init(&space.limbs, 1).toConst(),
566697
567 .int_u64 => return BigIntMutable.init(&space.limbs, self.cast(Payload.Int_u64).?.int).toConst(),698 .int_u64 => return BigIntMutable.init(&space.limbs, self.castTag(.int_u64).?.data).toConst(),
568 .int_i64 => return BigIntMutable.init(&space.limbs, self.cast(Payload.Int_i64).?.int).toConst(),699 .int_i64 => return BigIntMutable.init(&space.limbs, self.castTag(.int_i64).?.data).toConst(),
569 .int_big_positive => return self.cast(Payload.IntBigPositive).?.asBigInt(),700 .int_big_positive => return self.castTag(.int_big_positive).?.asBigInt(),
570 .int_big_negative => return self.cast(Payload.IntBigNegative).?.asBigInt(),701 .int_big_negative => return self.castTag(.int_big_negative).?.asBigInt(),
571 }702 }
572 }703 }
573704
...@@ -649,10 +780,10 @@ pub const Value = extern union {...@@ -649,10 +780,10 @@ pub const Value = extern union {
649 .bool_true,780 .bool_true,
650 => return 1,781 => return 1,
651782
652 .int_u64 => return self.cast(Payload.Int_u64).?.int,783 .int_u64 => return self.castTag(.int_u64).?.data,
653 .int_i64 => return @intCast(u64, self.cast(Payload.Int_i64).?.int),784 .int_i64 => return @intCast(u64, self.castTag(.int_i64).?.data),
654 .int_big_positive => return self.cast(Payload.IntBigPositive).?.asBigInt().to(u64) catch unreachable,785 .int_big_positive => return self.castTag(.int_big_positive).?.asBigInt().to(u64) catch unreachable,
655 .int_big_negative => return self.cast(Payload.IntBigNegative).?.asBigInt().to(u64) catch unreachable,786 .int_big_negative => return self.castTag(.int_big_negative).?.asBigInt().to(u64) catch unreachable,
656 }787 }
657 }788 }
658789
...@@ -734,10 +865,10 @@ pub const Value = extern union {...@@ -734,10 +865,10 @@ pub const Value = extern union {
734 .bool_true,865 .bool_true,
735 => return 1,866 => return 1,
736867
737 .int_u64 => return @intCast(i64, self.cast(Payload.Int_u64).?.int),868 .int_u64 => return @intCast(i64, self.castTag(.int_u64).?.data),
738 .int_i64 => return self.cast(Payload.Int_i64).?.int,869 .int_i64 => return self.castTag(.int_i64).?.data,
739 .int_big_positive => return self.cast(Payload.IntBigPositive).?.asBigInt().to(i64) catch unreachable,870 .int_big_positive => return self.castTag(.int_big_positive).?.asBigInt().to(i64) catch unreachable,
740 .int_big_negative => return self.cast(Payload.IntBigNegative).?.asBigInt().to(i64) catch unreachable,871 .int_big_negative => return self.castTag(.int_big_negative).?.asBigInt().to(i64) catch unreachable,
741 }872 }
742 }873 }
743874
...@@ -753,14 +884,14 @@ pub const Value = extern union {...@@ -753,14 +884,14 @@ pub const Value = extern union {
753 pub fn toFloat(self: Value, comptime T: type) T {884 pub fn toFloat(self: Value, comptime T: type) T {
754 return switch (self.tag()) {885 return switch (self.tag()) {
755 .float_16 => @panic("TODO soft float"),886 .float_16 => @panic("TODO soft float"),
756 .float_32 => @floatCast(T, self.cast(Payload.Float_32).?.val),887 .float_32 => @floatCast(T, self.castTag(.float_32).?.data),
757 .float_64 => @floatCast(T, self.cast(Payload.Float_64).?.val),888 .float_64 => @floatCast(T, self.castTag(.float_64).?.data),
758 .float_128 => @floatCast(T, self.cast(Payload.Float_128).?.val),889 .float_128 => @floatCast(T, self.castTag(.float_128).?.data),
759890
760 .zero => 0,891 .zero => 0,
761 .one => 1,892 .one => 1,
762 .int_u64 => @intToFloat(T, self.cast(Payload.Int_u64).?.int),893 .int_u64 => @intToFloat(T, self.castTag(.int_u64).?.data),
763 .int_i64 => @intToFloat(T, self.cast(Payload.Int_i64).?.int),894 .int_i64 => @intToFloat(T, self.castTag(.int_i64).?.data),
764895
765 .int_big_positive, .int_big_negative => @panic("big int to f128"),896 .int_big_positive, .int_big_negative => @panic("big int to f128"),
766 else => unreachable,897 else => unreachable,
...@@ -846,15 +977,15 @@ pub const Value = extern union {...@@ -846,15 +977,15 @@ pub const Value = extern union {
846 => return 1,977 => return 1,
847978
848 .int_u64 => {979 .int_u64 => {
849 const x = self.cast(Payload.Int_u64).?.int;980 const x = self.castTag(.int_u64).?.data;
850 if (x == 0) return 0;981 if (x == 0) return 0;
851 return @intCast(usize, std.math.log2(x) + 1);982 return @intCast(usize, std.math.log2(x) + 1);
852 },983 },
853 .int_i64 => {984 .int_i64 => {
854 @panic("TODO implement i64 intBitCountTwosComp");985 @panic("TODO implement i64 intBitCountTwosComp");
855 },986 },
856 .int_big_positive => return self.cast(Payload.IntBigPositive).?.asBigInt().bitCountTwosComp(),987 .int_big_positive => return self.castTag(.int_big_positive).?.asBigInt().bitCountTwosComp(),
857 .int_big_negative => return self.cast(Payload.IntBigNegative).?.asBigInt().bitCountTwosComp(),988 .int_big_negative => return self.castTag(.int_big_negative).?.asBigInt().bitCountTwosComp(),
858 }989 }
859 }990 }
860991
...@@ -943,7 +1074,7 @@ pub const Value = extern union {...@@ -943,7 +1074,7 @@ pub const Value = extern union {
9431074
944 .int_u64 => switch (ty.zigTypeTag()) {1075 .int_u64 => switch (ty.zigTypeTag()) {
945 .Int => {1076 .Int => {
946 const x = self.cast(Payload.Int_u64).?.int;1077 const x = self.castTag(.int_u64).?.data;
947 if (x == 0) return true;1078 if (x == 0) return true;
948 const info = ty.intInfo(target);1079 const info = ty.intInfo(target);
949 const needed_bits = std.math.log2(x) + 1 + @boolToInt(info.signedness == .signed);1080 const needed_bits = std.math.log2(x) + 1 + @boolToInt(info.signedness == .signed);
...@@ -954,7 +1085,7 @@ pub const Value = extern union {...@@ -954,7 +1085,7 @@ pub const Value = extern union {
954 },1085 },
955 .int_i64 => switch (ty.zigTypeTag()) {1086 .int_i64 => switch (ty.zigTypeTag()) {
956 .Int => {1087 .Int => {
957 const x = self.cast(Payload.Int_i64).?.int;1088 const x = self.castTag(.int_i64).?.data;
958 if (x == 0) return true;1089 if (x == 0) return true;
959 const info = ty.intInfo(target);1090 const info = ty.intInfo(target);
960 if (info.signedness == .unsigned and x < 0)1091 if (info.signedness == .unsigned and x < 0)
...@@ -967,7 +1098,7 @@ pub const Value = extern union {...@@ -967,7 +1098,7 @@ pub const Value = extern union {
967 .int_big_positive => switch (ty.zigTypeTag()) {1098 .int_big_positive => switch (ty.zigTypeTag()) {
968 .Int => {1099 .Int => {
969 const info = ty.intInfo(target);1100 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);
971 },1102 },
972 .ComptimeInt => return true,1103 .ComptimeInt => return true,
973 else => unreachable,1104 else => unreachable,
...@@ -975,7 +1106,7 @@ pub const Value = extern union {...@@ -975,7 +1106,7 @@ pub const Value = extern union {
975 .int_big_negative => switch (ty.zigTypeTag()) {1106 .int_big_negative => switch (ty.zigTypeTag()) {
976 .Int => {1107 .Int => {
977 const info = ty.intInfo(target);1108 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);
979 },1110 },
980 .ComptimeInt => return true,1111 .ComptimeInt => return true,
981 else => unreachable,1112 else => unreachable,
...@@ -986,42 +1117,28 @@ pub const Value = extern union {...@@ -986,42 +1117,28 @@ pub const Value = extern union {
986 /// Converts an integer or a float to a float.1117 /// Converts an integer or a float to a float.
987 /// Returns `error.Overflow` if the value does not fit in the new type.1118 /// Returns `error.Overflow` if the value does not fit in the new type.
988 pub fn floatCast(self: Value, allocator: *Allocator, ty: Type, target: Target) !Value {1119 pub fn floatCast(self: Value, allocator: *Allocator, ty: Type, target: Target) !Value {
989 const dest_bit_count = switch (ty.tag()) {1120 switch (ty.tag()) {
990 .comptime_float => 128,1121 .f16 => {
991 else => ty.floatBits(target),1122 @panic("TODO add __trunctfhf2 to compiler-rt");
992 };1123 //const res = try Value.Tag.float_16.create(allocator, self.toFloat(f16));
993 switch (dest_bit_count) {1124 //if (!self.eql(res))
994 16, 32, 64, 128 => {},1125 // return error.Overflow;
995 else => std.debug.panic("TODO float cast bit count {}\n", .{dest_bit_count}),1126 //return res;
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);
1008 },1127 },
1009 32 => {1128 .f32 => {
1010 var res_payload = Value.Payload.Float_32{ .val = self.toFloat(f32) };1129 const res = try Value.Tag.float_32.create(allocator, self.toFloat(f32));
1011 if (!self.eql(Value.initPayload(&res_payload.base)))1130 if (!self.eql(res))
1012 return error.Overflow;1131 return error.Overflow;
1013 return Value.initPayload(&res_payload.base).copy(allocator);1132 return res;
1014 },1133 },
1015 64 => {1134 .f64 => {
1016 var res_payload = Value.Payload.Float_64{ .val = self.toFloat(f64) };1135 const res = try Value.Tag.float_64.create(allocator, self.toFloat(f64));
1017 if (!self.eql(Value.initPayload(&res_payload.base)))1136 if (!self.eql(res))
1018 return error.Overflow;1137 return error.Overflow;
1019 return Value.initPayload(&res_payload.base).copy(allocator);1138 return res;
1020 },1139 },
1021 128 => {1140 .f128, .comptime_float, .c_longdouble => {
1022 const float_payload = try allocator.create(Value.Payload.Float_128);1141 return Value.Tag.float_128.create(allocator, self.toFloat(f128));
1023 float_payload.* = .{ .val = self.toFloat(f128) };
1024 return Value.initPayload(&float_payload.base);
1025 },1142 },
1026 else => unreachable,1143 else => unreachable,
1027 }1144 }
...@@ -1102,10 +1219,10 @@ pub const Value = extern union {...@@ -1102,10 +1219,10 @@ pub const Value = extern union {
1102 .one,1219 .one,
1103 => false,1220 => false,
11041221
1105 .float_16 => @rem(self.cast(Payload.Float_16).?.val, 1) != 0,1222 .float_16 => @rem(self.castTag(.float_16).?.data, 1) != 0,
1106 .float_32 => @rem(self.cast(Payload.Float_32).?.val, 1) != 0,1223 .float_32 => @rem(self.castTag(.float_32).?.data, 1) != 0,
1107 .float_64 => @rem(self.cast(Payload.Float_64).?.val, 1) != 0,1224 .float_64 => @rem(self.castTag(.float_64).?.data, 1) != 0,
1108 // .float_128 => @rem(self.cast(Payload.Float_128).?.val, 1) != 0,1225 // .float_128 => @rem(self.castTag(.float_128).?.data, 1) != 0,
1109 .float_128 => @panic("TODO lld: error: undefined symbol: fmodl"),1226 .float_128 => @panic("TODO lld: error: undefined symbol: fmodl"),
1110 };1227 };
1111 }1228 }
...@@ -1182,15 +1299,15 @@ pub const Value = extern union {...@@ -1182,15 +1299,15 @@ pub const Value = extern union {
1182 .bool_true,1299 .bool_true,
1183 => .gt,1300 => .gt,
11841301
1185 .int_u64 => std.math.order(lhs.cast(Payload.Int_u64).?.int, 0),1302 .int_u64 => std.math.order(lhs.castTag(.int_u64).?.data, 0),
1186 .int_i64 => std.math.order(lhs.cast(Payload.Int_i64).?.int, 0),1303 .int_i64 => std.math.order(lhs.castTag(.int_i64).?.data, 0),
1187 .int_big_positive => lhs.cast(Payload.IntBigPositive).?.asBigInt().orderAgainstScalar(0),1304 .int_big_positive => lhs.castTag(.int_big_positive).?.asBigInt().orderAgainstScalar(0),
1188 .int_big_negative => lhs.cast(Payload.IntBigNegative).?.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),1307 .float_16 => std.math.order(lhs.castTag(.float_16).?.data, 0),
1191 .float_32 => std.math.order(lhs.cast(Payload.Float_32).?.val, 0),1308 .float_32 => std.math.order(lhs.castTag(.float_32).?.data, 0),
1192 .float_64 => std.math.order(lhs.cast(Payload.Float_64).?.val, 0),1309 .float_64 => std.math.order(lhs.castTag(.float_64).?.data, 0),
1193 .float_128 => std.math.order(lhs.cast(Payload.Float_128).?.val, 0),1310 .float_128 => std.math.order(lhs.castTag(.float_128).?.data, 0),
1194 };1311 };
1195 }1312 }
11961313
...@@ -1208,10 +1325,10 @@ pub const Value = extern union {...@@ -1208,10 +1325,10 @@ pub const Value = extern union {
1208 if (lhs_float and rhs_float) {1325 if (lhs_float and rhs_float) {
1209 if (lhs_tag == rhs_tag) {1326 if (lhs_tag == rhs_tag) {
1210 return switch (lhs.tag()) {1327 return switch (lhs.tag()) {
1211 .float_16 => return std.math.order(lhs.cast(Payload.Float_16).?.val, rhs.cast(Payload.Float_16).?.val),1328 .float_16 => return std.math.order(lhs.castTag(.float_16).?.data, rhs.castTag(.float_16).?.data),
1212 .float_32 => return std.math.order(lhs.cast(Payload.Float_32).?.val, rhs.cast(Payload.Float_32).?.val),1329 .float_32 => return std.math.order(lhs.castTag(.float_32).?.data, rhs.castTag(.float_32).?.data),
1213 .float_64 => return std.math.order(lhs.cast(Payload.Float_64).?.val, rhs.cast(Payload.Float_64).?.val),1330 .float_64 => return std.math.order(lhs.castTag(.float_64).?.data, rhs.castTag(.float_64).?.data),
1214 .float_128 => return std.math.order(lhs.cast(Payload.Float_128).?.val, rhs.cast(Payload.Float_128).?.val),1331 .float_128 => return std.math.order(lhs.castTag(.float_128).?.data, rhs.castTag(.float_128).?.data),
1215 else => unreachable,1332 else => unreachable,
1216 };1333 };
1217 }1334 }
...@@ -1244,8 +1361,8 @@ pub const Value = extern union {...@@ -1244,8 +1361,8 @@ pub const Value = extern union {
1244 if (a.tag() == .void_value or a.tag() == .null_value) {1361 if (a.tag() == .void_value or a.tag() == .null_value) {
1245 return true;1362 return true;
1246 } else if (a.tag() == .enum_literal) {1363 } else if (a.tag() == .enum_literal) {
1247 const a_name = @fieldParentPtr(Payload.Bytes, "base", a.ptr_otherwise).data;1364 const a_name = a.castTag(.enum_literal).?.data;
1248 const b_name = @fieldParentPtr(Payload.Bytes, "base", b.ptr_otherwise).data;1365 const b_name = b.castTag(.enum_literal).?.data;
1249 return std.mem.eql(u8, a_name, b_name);1366 return std.mem.eql(u8, a_name, b_name);
1250 }1367 }
1251 }1368 }
...@@ -1313,11 +1430,11 @@ pub const Value = extern union {...@@ -1313,11 +1430,11 @@ pub const Value = extern union {
1313 },1430 },
1314 .error_set => {1431 .error_set => {
1315 // Payload.decl should be same for all instances of the type.1432 // 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;
1317 std.hash.autoHash(&hasher, payload.decl);1434 std.hash.autoHash(&hasher, payload.decl);
1318 },1435 },
1319 .int_type => {1436 .int_type => {
1320 const payload = self.cast(Payload.IntType).?;1437 const payload = self.castTag(.int_type).?.data;
1321 var int_payload = Type.Payload.Bits{1438 var int_payload = Type.Payload.Bits{
1322 .base = .{1439 .base = .{
1323 .tag = if (payload.signed) .int_signed else .int_unsigned,1440 .tag = if (payload.signed) .int_signed else .int_unsigned,
...@@ -1341,25 +1458,29 @@ pub const Value = extern union {...@@ -1341,25 +1458,29 @@ pub const Value = extern union {
1341 .one, .bool_true => std.hash.autoHash(&hasher, @as(u64, 1)),1458 .one, .bool_true => std.hash.autoHash(&hasher, @as(u64, 1)),
13421459
1343 .float_16, .float_32, .float_64, .float_128 => {},1460 .float_16, .float_32, .float_64, .float_128 => {},
1344 .enum_literal, .bytes => {1461 .enum_literal => {
1345 const payload = @fieldParentPtr(Payload.Bytes, "base", self.ptr_otherwise);1462 const payload = self.castTag(.enum_literal).?;
1463 hasher.update(payload.data);
1464 },
1465 .bytes => {
1466 const payload = self.castTag(.bytes).?;
1346 hasher.update(payload.data);1467 hasher.update(payload.data);
1347 },1468 },
1348 .int_u64 => {1469 .int_u64 => {
1349 const payload = @fieldParentPtr(Payload.Int_u64, "base", self.ptr_otherwise);1470 const payload = self.castTag(.int_u64).?;
1350 std.hash.autoHash(&hasher, payload.int);1471 std.hash.autoHash(&hasher, payload.data);
1351 },1472 },
1352 .int_i64 => {1473 .int_i64 => {
1353 const payload = @fieldParentPtr(Payload.Int_i64, "base", self.ptr_otherwise);1474 const payload = self.castTag(.int_i64).?;
1354 std.hash.autoHash(&hasher, payload.int);1475 std.hash.autoHash(&hasher, payload.data);
1355 },1476 },
1356 .repeated => {1477 .repeated => {
1357 const payload = @fieldParentPtr(Payload.Repeated, "base", self.ptr_otherwise);1478 const payload = self.castTag(.repeated).?;
1358 std.hash.autoHash(&hasher, payload.val.hash());1479 std.hash.autoHash(&hasher, payload.data.hash());
1359 },1480 },
1360 .ref_val => {1481 .ref_val => {
1361 const payload = @fieldParentPtr(Payload.RefVal, "base", self.ptr_otherwise);1482 const payload = self.castTag(.ref_val).?;
1362 std.hash.autoHash(&hasher, payload.val.hash());1483 std.hash.autoHash(&hasher, payload.data.hash());
1363 },1484 },
1364 .int_big_positive, .int_big_negative => {1485 .int_big_positive, .int_big_negative => {
1365 var space: BigIntSpace = undefined;1486 var space: BigIntSpace = undefined;
...@@ -1379,28 +1500,28 @@ pub const Value = extern union {...@@ -1379,28 +1500,28 @@ pub const Value = extern union {
1379 }1500 }
1380 },1501 },
1381 .elem_ptr => {1502 .elem_ptr => {
1382 const payload = @fieldParentPtr(Payload.ElemPtr, "base", self.ptr_otherwise);1503 const payload = self.castTag(.elem_ptr).?.data;
1383 std.hash.autoHash(&hasher, payload.array_ptr.hash());1504 std.hash.autoHash(&hasher, payload.array_ptr.hash());
1384 std.hash.autoHash(&hasher, payload.index);1505 std.hash.autoHash(&hasher, payload.index);
1385 },1506 },
1386 .decl_ref => {1507 .decl_ref => {
1387 const payload = @fieldParentPtr(Payload.DeclRef, "base", self.ptr_otherwise);1508 const decl = self.castTag(.decl_ref).?.data;
1388 std.hash.autoHash(&hasher, payload.decl);1509 std.hash.autoHash(&hasher, decl);
1389 },1510 },
1390 .function => {1511 .function => {
1391 const payload = @fieldParentPtr(Payload.Function, "base", self.ptr_otherwise);1512 const func = self.castTag(.function).?.data;
1392 std.hash.autoHash(&hasher, payload.func);1513 std.hash.autoHash(&hasher, func);
1393 },1514 },
1394 .extern_fn => {1515 .extern_fn => {
1395 const payload = @fieldParentPtr(Payload.ExternFn, "base", self.ptr_otherwise);1516 const decl = self.castTag(.extern_fn).?.data;
1396 std.hash.autoHash(&hasher, payload.decl);1517 std.hash.autoHash(&hasher, decl);
1397 },1518 },
1398 .variable => {1519 .variable => {
1399 const payload = @fieldParentPtr(Payload.Variable, "base", self.ptr_otherwise);1520 const variable = self.castTag(.variable).?.data;
1400 std.hash.autoHash(&hasher, payload.variable);1521 std.hash.autoHash(&hasher, variable);
1401 },1522 },
1402 .@"error" => {1523 .@"error" => {
1403 const payload = @fieldParentPtr(Payload.Error, "base", self.ptr_otherwise);1524 const payload = self.castTag(.@"error").?.data;
1404 hasher.update(payload.name);1525 hasher.update(payload.name);
1405 std.hash.autoHash(&hasher, payload.value);1526 std.hash.autoHash(&hasher, payload.value);
1406 },1527 },
...@@ -1483,10 +1604,10 @@ pub const Value = extern union {...@@ -1483,10 +1604,10 @@ pub const Value = extern union {
1483 .empty_struct_value,1604 .empty_struct_value,
1484 => unreachable,1605 => unreachable,
14851606
1486 .ref_val => self.cast(Payload.RefVal).?.val,1607 .ref_val => self.castTag(.ref_val).?.data,
1487 .decl_ref => self.cast(Payload.DeclRef).?.decl.value(),1608 .decl_ref => self.castTag(.decl_ref).?.data.value(),
1488 .elem_ptr => {1609 .elem_ptr => {
1489 const elem_ptr = self.cast(Payload.ElemPtr).?;1610 const elem_ptr = self.castTag(.elem_ptr).?.data;
1490 const array_val = try elem_ptr.array_ptr.pointerDeref(allocator);1611 const array_val = try elem_ptr.array_ptr.pointerDeref(allocator);
1491 return array_val.elemValue(allocator, elem_ptr.index);1612 return array_val.elemValue(allocator, elem_ptr.index);
1492 },1613 },
...@@ -1570,26 +1691,26 @@ pub const Value = extern union {...@@ -1570,26 +1691,26 @@ pub const Value = extern union {
15701691
1571 .empty_array => unreachable, // out of bounds array index1692 .empty_array => unreachable, // out of bounds array index
15721693
1573 .bytes => {1694 .bytes => return Tag.int_u64.create(allocator, self.castTag(.bytes).?.data[index]),
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 },
15781695
1579 // No matter the index; all the elements are the same!1696 // 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,
1581 }1698 }
1582 }1699 }
15831700
1584 /// Returns a pointer to the element value at the index.1701 /// Returns a pointer to the element value at the index.
1585 pub fn elemPtr(self: Value, allocator: *Allocator, index: usize) !Value {1702 pub fn elemPtr(self: Value, allocator: *Allocator, index: usize) !Value {
1586 const payload = try allocator.create(Payload.ElemPtr);1703 if (self.castTag(.elem_ptr)) |elem_ptr| {
1587 if (self.cast(Payload.ElemPtr)) |elem_ptr| {1704 return Tag.elem_ptr.create(allocator, .{
1588 payload.* = .{ .array_ptr = elem_ptr.array_ptr, .index = elem_ptr.index + index };1705 .array_ptr = elem_ptr.data.array_ptr,
1589 } else {1706 .index = elem_ptr.data.index + index,
1590 payload.* = .{ .array_ptr = self, .index = index };1707 });
1591 }1708 }
1592 return Value.initPayload(&payload.base);1709
1710 return Tag.elem_ptr.create(allocator, .{
1711 .array_ptr = self,
1712 .index = index,
1713 });
1593 }1714 }
15941715
1595 pub fn isUndef(self: Value) bool {1716 pub fn isUndef(self: Value) bool {
...@@ -1776,131 +1897,128 @@ pub const Value = extern union {...@@ -1776,131 +1897,128 @@ pub const Value = extern union {
1776 pub const Payload = struct {1897 pub const Payload = struct {
1777 tag: Tag,1898 tag: Tag,
17781899
1779 pub const Int_u64 = struct {1900 pub const U64 = struct {
1780 base: Payload = Payload{ .tag = .int_u64 },1901 base: Payload,
1781 int: u64,1902 data: u64,
1782 };1903 };
17831904
1784 pub const Int_i64 = struct {1905 pub const I64 = struct {
1785 base: Payload = Payload{ .tag = .int_i64 },1906 base: Payload,
1786 int: i64,1907 data: 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 }
1796 };1908 };
17971909
1798 pub const IntBigNegative = struct {1910 pub const BigInt = struct {
1799 base: Payload = Payload{ .tag = .int_big_negative },1911 base: Payload,
1800 limbs: []const std.math.big.Limb,1912 data: []const std.math.big.Limb,
18011913
1802 pub fn asBigInt(self: IntBigNegative) BigIntConst {1914 pub fn asBigInt(self: BigInt) BigIntConst {
1803 return BigIntConst{ .limbs = self.limbs, .positive = false };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 };
1804 }1921 }
1805 };1922 };
18061923
1807 pub const Function = struct {1924 pub const Function = struct {
1808 base: Payload = Payload{ .tag = .function },1925 base: Payload,
1809 func: *Module.Fn,1926 data: *Module.Fn,
1810 };1927 };
18111928
1812 pub const ExternFn = struct {1929 pub const Decl = struct {
1813 base: Payload = Payload{ .tag = .extern_fn },1930 base: Payload,
1814 decl: *Module.Decl,1931 data: *Module.Decl,
1815 };1932 };
18161933
1817 pub const Variable = struct {1934 pub const Variable = struct {
1818 base: Payload = Payload{ .tag = .variable },1935 base: Payload,
1819 variable: *Module.Var,1936 data: *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,
1831 };1937 };
18321938
1833 /// Represents a pointer to a decl, not the value of the decl.1939 pub const SubValue = struct {
1834 pub const DeclRef = struct {1940 base: Payload,
1835 base: Payload = Payload{ .tag = .decl_ref },1941 data: Value,
1836 decl: *Module.Decl,
1837 };1942 };
18381943
1839 pub const ElemPtr = struct {1944 pub const ElemPtr = struct {
1840 base: Payload = Payload{ .tag = .elem_ptr },1945 pub const base_tag = Tag.elem_ptr;
1841 array_ptr: Value,1946
1842 index: usize,1947 base: Payload = Payload{ .tag = base_tag },
1948 data: struct {
1949 array_ptr: Value,
1950 index: usize,
1951 },
1843 };1952 };
18441953
1845 pub const Bytes = struct {1954 pub const Bytes = struct {
1846 base: Payload = Payload{ .tag = .bytes },1955 base: Payload,
1847 data: []const u8,1956 data: []const u8,
1848 };1957 };
18491958
1850 pub const Ty = struct {1959 pub const Ty = struct {
1851 base: Payload = Payload{ .tag = .ty },1960 base: Payload,
1852 ty: Type,1961 data: Type,
1853 };1962 };
18541963
1855 pub const IntType = struct {1964 pub const IntType = struct {
1856 base: Payload = Payload{ .tag = .int_type },1965 pub const base_tag = Tag.int_type;
1857 bits: u16,
1858 signed: bool,
1859 };
18601966
1861 pub const Repeated = struct {1967 base: Payload = Payload{ .tag = base_tag },
1862 base: Payload = Payload{ .tag = .ty },1968 data: struct {
1863 /// This value is repeated some number of times. The amount of times to repeat1969 bits: u16,
1864 /// is stored externally.1970 signed: bool,
1865 val: Value,1971 },
1866 };1972 };
18671973
1868 pub const Float_16 = struct {1974 pub const Float_16 = struct {
1869 base: Payload = .{ .tag = .float_16 },1975 pub const base_tag = Tag.float_16;
1870 val: f16,1976
1977 base: Payload = .{ .tag = base_tag },
1978 data: f16,
1871 };1979 };
18721980
1873 pub const Float_32 = struct {1981 pub const Float_32 = struct {
1874 base: Payload = .{ .tag = .float_32 },1982 pub const base_tag = Tag.float_32;
1875 val: f32,1983
1984 base: Payload = .{ .tag = base_tag },
1985 data: f32,
1876 };1986 };
18771987
1878 pub const Float_64 = struct {1988 pub const Float_64 = struct {
1879 base: Payload = .{ .tag = .float_64 },1989 pub const base_tag = Tag.float_64;
1880 val: f64,1990
1991 base: Payload = .{ .tag = base_tag },
1992 data: f64,
1881 };1993 };
18821994
1883 pub const Float_128 = struct {1995 pub const Float_128 = struct {
1884 base: Payload = .{ .tag = .float_128 },1996 pub const base_tag = Tag.float_128;
1885 val: f128,1997
1998 base: Payload = .{ .tag = base_tag },
1999 data: f128,
1886 };2000 };
18872001
1888 pub const ErrorSet = struct {2002 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 type2005 base: Payload = .{ .tag = base_tag },
1892 fields: std.StringHashMapUnmanaged(u16),2006 data: struct {
1893 decl: *Module.Decl,2007 // TODO revisit this when we have the concept of the error tag type
2008 fields: std.StringHashMapUnmanaged(u16),
2009 decl: *Module.Decl,
2010 },
1894 };2011 };
18952012
1896 pub const Error = struct {2013 pub const Error = struct {
1897 base: Payload = .{ .tag = .@"error" },2014 base: Payload = .{ .tag = .@"error" },
18982015 data: struct {
1899 // TODO revisit this when we have the concept of the error tag type2016 // 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 entire2017 /// `name` is owned by `Module` and will be valid for the entire
1901 /// duration of the compilation.2018 /// duration of the compilation.
1902 name: []const u8,2019 name: []const u8,
1903 value: u16,2020 value: u16,
2021 },
1904 };2022 };
1905 };2023 };
19062024
...@@ -1914,15 +2032,24 @@ pub const Value = extern union {...@@ -1914,15 +2032,24 @@ pub const Value = extern union {
19142032
1915test "hash same value different representation" {2033test "hash same value different representation" {
1916 const zero_1 = Value.initTag(.zero);2034 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 };
1918 const zero_2 = Value.initPayload(&payload_1.base);2039 const zero_2 = Value.initPayload(&payload_1.base);
1919 std.testing.expectEqual(zero_1.hash(), zero_2.hash());2040 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 };
1922 const zero_3 = Value.initPayload(&payload_2.base);2046 const zero_3 = Value.initPayload(&payload_2.base);
1923 std.testing.expectEqual(zero_2.hash(), zero_3.hash());2047 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 };
1926 const zero_4 = Value.initPayload(&payload_3.base);2053 const zero_4 = Value.initPayload(&payload_3.base);
1927 std.testing.expectEqual(zero_3.hash(), zero_4.hash());2054 std.testing.expectEqual(zero_3.hash(), zero_4.hash());
1928}2055}
src/zir.zig+18-16
...@@ -1990,15 +1990,15 @@ const EmitZIR = struct {...@@ -1990,15 +1990,15 @@ const EmitZIR = struct {
19901990
1991 fn resolveInst(self: *EmitZIR, new_body: ZirBody, inst: *ir.Inst) !*Inst {1991 fn resolveInst(self: *EmitZIR, new_body: ZirBody, inst: *ir.Inst) !*Inst {
1992 if (inst.cast(ir.Inst.Constant)) |const_inst| {1992 if (inst.cast(ir.Inst.Constant)) |const_inst| {
1993 const new_inst = if (const_inst.val.cast(Value.Payload.Function)) |func_pl| blk: {1993 const new_inst = if (const_inst.val.castTag(.function)) |func_pl| blk: {
1994 const owner_decl = func_pl.func.owner_decl;1994 const owner_decl = func_pl.data.owner_decl;
1995 break :blk try self.emitDeclVal(inst.src, mem.spanZ(owner_decl.name));1995 break :blk try self.emitDeclVal(inst.src, mem.spanZ(owner_decl.name));
1996 } else if (const_inst.val.cast(Value.Payload.DeclRef)) |declref| blk: {1996 } else if (const_inst.val.castTag(.decl_ref)) |declref| blk: {
1997 const decl_ref = try self.emitDeclRef(inst.src, declref.decl);1997 const decl_ref = try self.emitDeclRef(inst.src, declref.data);
1998 try new_body.instructions.append(decl_ref);1998 try new_body.instructions.append(decl_ref);
1999 break :blk decl_ref;1999 break :blk decl_ref;
2000 } else if (const_inst.val.cast(Value.Payload.Variable)) |var_pl| blk: {2000 } else if (const_inst.val.castTag(.variable)) |var_pl| blk: {
2001 const owner_decl = var_pl.variable.owner_decl;2001 const owner_decl = var_pl.data.owner_decl;
2002 break :blk try self.emitDeclVal(inst.src, mem.spanZ(owner_decl.name));2002 break :blk try self.emitDeclVal(inst.src, mem.spanZ(owner_decl.name));
2003 } else blk: {2003 } else blk: {
2004 break :blk (try self.emitTypedValue(inst.src, .{ .ty = inst.ty, .val = const_inst.val })).inst;2004 break :blk (try self.emitTypedValue(inst.src, .{ .ty = inst.ty, .val = const_inst.val })).inst;
...@@ -2150,13 +2150,13 @@ const EmitZIR = struct {...@@ -2150,13 +2150,13 @@ const EmitZIR = struct {
21502150
2151 fn emitTypedValue(self: *EmitZIR, src: usize, typed_value: TypedValue) Allocator.Error!*Decl {2151 fn emitTypedValue(self: *EmitZIR, src: usize, typed_value: TypedValue) Allocator.Error!*Decl {
2152 const allocator = &self.arena.allocator;2152 const allocator = &self.arena.allocator;
2153 if (typed_value.val.cast(Value.Payload.DeclRef)) |decl_ref| {2153 if (typed_value.val.castTag(.decl_ref)) |decl_ref| {
2154 const decl = decl_ref.decl;2154 const decl = decl_ref.data;
2155 return try self.emitUnnamedDecl(try self.emitDeclRef(src, decl));2155 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| {
2157 return self.emitTypedValue(src, .{2157 return self.emitTypedValue(src, .{
2158 .ty = typed_value.ty,2158 .ty = typed_value.ty,
2159 .val = variable.variable.init,2159 .val = variable.data.init,
2160 });2160 });
2161 }2161 }
2162 if (typed_value.val.isUndef()) {2162 if (typed_value.val.isUndef()) {
...@@ -2215,7 +2215,7 @@ const EmitZIR = struct {...@@ -2215,7 +2215,7 @@ const EmitZIR = struct {
2215 return self.emitType(src, ty);2215 return self.emitType(src, ty);
2216 },2216 },
2217 .Fn => {2217 .Fn => {
2218 const module_fn = typed_value.val.cast(Value.Payload.Function).?.func;2218 const module_fn = typed_value.val.castTag(.function).?.data;
2219 return self.emitFn(module_fn, src, typed_value.ty);2219 return self.emitFn(module_fn, src, typed_value.ty);
2220 },2220 },
2221 .Array => {2221 .Array => {
...@@ -2248,7 +2248,7 @@ const EmitZIR = struct {...@@ -2248,7 +2248,7 @@ const EmitZIR = struct {
2248 else2248 else
2249 return self.emitPrimitive(src, .@"false"),2249 return self.emitPrimitive(src, .@"false"),
2250 .EnumLiteral => {2250 .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).?;
2252 const inst = try self.arena.allocator.create(Inst.Str);2252 const inst = try self.arena.allocator.create(Inst.Str);
2253 inst.* = .{2253 inst.* = .{
2254 .base = .{2254 .base = .{
...@@ -2748,9 +2748,8 @@ const EmitZIR = struct {...@@ -2748,9 +2748,8 @@ const EmitZIR = struct {
2748 .signed => .@"true",2748 .signed => .@"true",
2749 .unsigned => .@"false",2749 .unsigned => .@"false",
2750 });2750 });
2751 const bits_payload = try self.arena.allocator.create(Value.Payload.Int_u64);2751 const bits_val = try Value.Tag.int_u64.create(&self.arena.allocator, info.bits);
2752 bits_payload.* = .{ .int = info.bits };2752 const bits = try self.emitComptimeIntVal(src, bits_val);
2753 const bits = try self.emitComptimeIntVal(src, Value.initPayload(&bits_payload.base));
2754 const inttype_inst = try self.arena.allocator.create(Inst.IntType);2753 const inttype_inst = try self.arena.allocator.create(Inst.IntType);
2755 inttype_inst.* = .{2754 inttype_inst.* = .{
2756 .base = .{2755 .base = .{
...@@ -2800,7 +2799,10 @@ const EmitZIR = struct {...@@ -2800,7 +2799,10 @@ const EmitZIR = struct {
2800 return self.emitUnnamedDecl(&inst.base);2799 return self.emitUnnamedDecl(&inst.base);
2801 },2800 },
2802 .Array => {2801 .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 };
2804 const len = Value.initPayload(&len_pl.base);2806 const len = Value.initPayload(&len_pl.base);
28052807
2806 const inst = if (ty.sentinel()) |sentinel| blk: {2808 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!...@@ -364,12 +364,9 @@ fn analyzeInstRef(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!
364 const ptr_type = try mod.simplePtrType(scope, inst.base.src, operand.ty, false, .One);364 const ptr_type = try mod.simplePtrType(scope, inst.base.src, operand.ty, false, .One);
365365
366 if (operand.value()) |val| {366 if (operand.value()) |val| {
367 const ref_payload = try scope.arena().create(Value.Payload.RefVal);
368 ref_payload.* = .{ .val = val };
369
370 return mod.constInst(scope, inst.base.src, .{367 return mod.constInst(scope, inst.base.src, .{
371 .ty = ptr_type,368 .ty = ptr_type,
372 .val = Value.initPayload(&ref_payload.base),369 .val = try Value.Tag.ref_val.create(scope.arena(), val),
373 });370 });
374 }371 }
375372
...@@ -480,12 +477,9 @@ fn analyzeInstStr(mod: *Module, scope: *Scope, str_inst: *zir.Inst.Str) InnerErr...@@ -480,12 +477,9 @@ fn analyzeInstStr(mod: *Module, scope: *Scope, str_inst: *zir.Inst.Str) InnerErr
480 errdefer new_decl_arena.deinit();477 errdefer new_decl_arena.deinit();
481 const arena_bytes = try new_decl_arena.allocator.dupe(u8, str_inst.positionals.bytes);478 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
486 const new_decl = try mod.createAnonymousDecl(scope, &new_decl_arena, .{480 const new_decl = try mod.createAnonymousDecl(scope, &new_decl_arena, .{
487 .ty = try Type.Tag.array_u8_sentinel_0.create(scope.arena(), arena_bytes.len),481 .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),
489 });483 });
490 return mod.analyzeDeclRef(scope, str_inst.base.src, new_decl);484 return mod.analyzeDeclRef(scope, str_inst.base.src, new_decl);
491}485}
...@@ -779,11 +773,9 @@ fn analyzeInstFn(mod: *Module, scope: *Scope, fn_inst: *zir.Inst.Fn) InnerError!...@@ -779,11 +773,9 @@ fn analyzeInstFn(mod: *Module, scope: *Scope, fn_inst: *zir.Inst.Fn) InnerError!
779 .analysis = .{ .queued = fn_zir },773 .analysis = .{ .queued = fn_zir },
780 .owner_decl = scope.decl().?,774 .owner_decl = scope.decl().?,
781 };775 };
782 const fn_payload = try scope.arena().create(Value.Payload.Function);
783 fn_payload.* = .{ .func = new_func };
784 return mod.constInst(scope, fn_inst.base.src, .{776 return mod.constInst(scope, fn_inst.base.src, .{
785 .ty = fn_type,777 .ty = fn_type,
786 .val = Value.initPayload(&fn_payload.base),778 .val = try Value.Tag.function.create(scope.arena(), new_func),
787 });779 });
788}780}
789781
...@@ -838,14 +830,17 @@ fn analyzeInstErrorSet(mod: *Module, scope: *Scope, inst: *zir.Inst.ErrorSet) In...@@ -838,14 +830,17 @@ fn analyzeInstErrorSet(mod: *Module, scope: *Scope, inst: *zir.Inst.ErrorSet) In
838830
839 const payload = try scope.arena().create(Value.Payload.ErrorSet);831 const payload = try scope.arena().create(Value.Payload.ErrorSet);
840 payload.* = .{832 payload.* = .{
841 .fields = .{},833 .base = .{ .tag = .error_set },
842 .decl = undefined, // populated below834 .data = .{
835 .fields = .{},
836 .decl = undefined, // populated below
837 },
843 };838 };
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
846 for (inst.positionals.fields) |field_name| {841 for (inst.positionals.fields) |field_name| {
847 const entry = try mod.getErrorValue(field_name);842 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| {
849 return mod.fail(scope, inst.base.src, "duplicate error: '{}'", .{field_name});844 return mod.fail(scope, inst.base.src, "duplicate error: '{}'", .{field_name});
850 }845 }
851 }846 }
...@@ -854,7 +849,7 @@ fn analyzeInstErrorSet(mod: *Module, scope: *Scope, inst: *zir.Inst.ErrorSet) In...@@ -854,7 +849,7 @@ fn analyzeInstErrorSet(mod: *Module, scope: *Scope, inst: *zir.Inst.ErrorSet) In
854 .ty = Type.initTag(.type),849 .ty = Type.initTag(.type),
855 .val = Value.initPayload(&payload.base),850 .val = Value.initPayload(&payload.base),
856 });851 });
857 payload.decl = new_decl;852 payload.data.decl = new_decl;
858 return mod.analyzeDeclRef(scope, inst.base.src, new_decl);853 return mod.analyzeDeclRef(scope, inst.base.src, new_decl);
859}854}
860855
...@@ -863,14 +858,10 @@ fn analyzeInstMergeErrorSets(mod: *Module, scope: *Scope, inst: *zir.Inst.BinOp)...@@ -863,14 +858,10 @@ fn analyzeInstMergeErrorSets(mod: *Module, scope: *Scope, inst: *zir.Inst.BinOp)
863}858}
864859
865fn analyzeInstEnumLiteral(mod: *Module, scope: *Scope, inst: *zir.Inst.EnumLiteral) InnerError!*Inst {860fn analyzeInstEnumLiteral(mod: *Module, scope: *Scope, inst: *zir.Inst.EnumLiteral) InnerError!*Inst {
866 const payload = try scope.arena().create(Value.Payload.Bytes);861 const duped_name = try scope.arena().dupe(u8, inst.positionals.name);
867 payload.* = .{
868 .base = .{ .tag = .enum_literal },
869 .data = try scope.arena().dupe(u8, inst.positionals.name),
870 };
871 return mod.constInst(scope, inst.base.src, .{862 return mod.constInst(scope, inst.base.src, .{
872 .ty = Type.initTag(.enum_literal),863 .ty = Type.initTag(.enum_literal),
873 .val = Value.initPayload(&payload.base),864 .val = try Value.Tag.enum_literal.create(scope.arena(), duped_name),
874 });865 });
875}866}
876867
...@@ -989,15 +980,12 @@ fn analyzeInstFieldPtr(mod: *Module, scope: *Scope, fieldptr: *zir.Inst.FieldPtr...@@ -989,15 +980,12 @@ fn analyzeInstFieldPtr(mod: *Module, scope: *Scope, fieldptr: *zir.Inst.FieldPtr
989 switch (elem_ty.zigTypeTag()) {980 switch (elem_ty.zigTypeTag()) {
990 .Array => {981 .Array => {
991 if (mem.eql(u8, field_name, "len")) {982 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
998 return mod.constInst(scope, fieldptr.base.src, .{983 return mod.constInst(scope, fieldptr.base.src, .{
999 .ty = Type.initTag(.single_const_pointer_to_comptime_int),984 .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 ),
1001 });989 });
1002 } else {990 } else {
1003 return mod.fail(991 return mod.fail(
...@@ -1013,15 +1001,12 @@ fn analyzeInstFieldPtr(mod: *Module, scope: *Scope, fieldptr: *zir.Inst.FieldPtr...@@ -1013,15 +1001,12 @@ fn analyzeInstFieldPtr(mod: *Module, scope: *Scope, fieldptr: *zir.Inst.FieldPtr
1013 switch (ptr_child.zigTypeTag()) {1001 switch (ptr_child.zigTypeTag()) {
1014 .Array => {1002 .Array => {
1015 if (mem.eql(u8, field_name, "len")) {1003 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
1022 return mod.constInst(scope, fieldptr.base.src, .{1004 return mod.constInst(scope, fieldptr.base.src, .{
1023 .ty = Type.initTag(.single_const_pointer_to_comptime_int),1005 .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 ),
1025 });1010 });
1026 } else {1011 } else {
1027 return mod.fail(1012 return mod.fail(
...@@ -1043,21 +1028,12 @@ fn analyzeInstFieldPtr(mod: *Module, scope: *Scope, fieldptr: *zir.Inst.FieldPtr...@@ -1043,21 +1028,12 @@ fn analyzeInstFieldPtr(mod: *Module, scope: *Scope, fieldptr: *zir.Inst.FieldPtr
1043 switch (child_type.zigTypeTag()) {1028 switch (child_type.zigTypeTag()) {
1044 .ErrorSet => {1029 .ErrorSet => {
1045 // TODO resolve inferred error sets1030 // TODO resolve inferred error sets
1046 const entry = if (val.cast(Value.Payload.ErrorSet)) |payload|1031 const entry = if (val.castTag(.error_set)) |payload|
1047 (payload.fields.getEntry(field_name) orelse1032 (payload.data.fields.getEntry(field_name) orelse
1048 return mod.fail(scope, fieldptr.base.src, "no error named '{}' in '{}'", .{ field_name, child_type })).*1033 return mod.fail(scope, fieldptr.base.src, "no error named '{}' in '{}'", .{ field_name, child_type })).*
1049 else1034 else
1050 try mod.getErrorValue(field_name);1035 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
1061 const result_type = if (child_type.tag() == .anyerror)1037 const result_type = if (child_type.tag() == .anyerror)
1062 try Type.Tag.error_set_single.create(scope.arena(), entry.key)1038 try Type.Tag.error_set_single.create(scope.arena(), entry.key)
1063 else1039 else
...@@ -1065,7 +1041,13 @@ fn analyzeInstFieldPtr(mod: *Module, scope: *Scope, fieldptr: *zir.Inst.FieldPtr...@@ -1065,7 +1041,13 @@ fn analyzeInstFieldPtr(mod: *Module, scope: *Scope, fieldptr: *zir.Inst.FieldPtr
10651041
1066 return mod.constInst(scope, fieldptr.base.src, .{1042 return mod.constInst(scope, fieldptr.base.src, .{
1067 .ty = try mod.simplePtrType(scope, fieldptr.base.src, result_type, false, .One),1043 .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 ),
1069 });1051 });
1070 },1052 },
1071 .Struct => {1053 .Struct => {