| author | |
| committer | |
| log | 3f7d9b5fc19e4081236b3b63aebbc80e1b17f5b5 |
| tree | a577bd97edf5d5da357d576c777861d443210aec |
| parent | 133da8692e80532797dd91b32539cf2175280a95 |
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 |
| 1457 | 1457 | ||
| 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 | } |
| 1480 | 1481 | ||
| 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 { |
| 1092 | 1092 | ||
| 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 }; | ||
| 1097 | 1096 | ||
| 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 | }; | ||
| 1191 | 1190 | ||
| 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 | } |
| 1376 | 1375 | ||
| 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); |
| 1387 | 1385 | ||
| 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 | } |
| 2233 | 2231 | ||
| 2234 | pub fn constIntUnsigned(self: *Module, scope: *Scope, src: usize, ty: Type, int: u64) !*Inst { | 2232 | pub 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 | } |
| 2243 | 2238 | ||
| 2244 | pub fn constIntSigned(self: *Module, scope: *Scope, src: usize, ty: Type, int: i64) !*Inst { | 2239 | pub 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 | } |
| 2253 | 2245 | ||
| 2254 | pub fn constIntBig(self: *Module, scope: *Scope, src: usize, ty: Type, big_int: BigIntConst) !*Inst { | 2246 | pub 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 below | 2252 | 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 below | 2263 | 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 | }); |
| 2276 | 2269 | } | |
| 2277 | return self.constInst(scope, src, .{ | ||
| 2278 | .ty = ty, | ||
| 2279 | .val = Value.initPayload(val_payload), | ||
| 2280 | }); | ||
| 2281 | } | 2270 | } |
| 2282 | 2271 | ||
| 2283 | pub fn createAnonymousDecl( | 2272 | pub 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 | } |
| 2358 | 2343 | ||
| 2359 | fn analyzeVarRef(self: *Module, scope: *Scope, src: usize, tv: TypedValue) InnerError!*Inst { | 2344 | fn 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; |
| 2361 | 2346 | ||
| 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 | } |
| 2371 | 2354 | ||
| ... | @@ -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]; |
| 3109 | 3092 | ||
| 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 | } |
| 3122 | 3099 | ||
| 3123 | pub fn intSub(allocator: *Allocator, lhs: Value, rhs: Value) !Value { | 3100 | 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,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]; |
| 3137 | 3114 | ||
| 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 | } |
| 3150 | 3121 | ||
| 3151 | pub fn floatAdd(self: *Module, scope: *Scope, float_type: Type, src: usize, lhs: Value, rhs: Value) !Value { | 3122 | pub 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, |
| 3156 | 3127 | 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 | } |
| 3184 | 3156 | ||
| 3185 | pub fn floatSub(self: *Module, scope: *Scope, float_type: Type, src: usize, lhs: Value, rhs: Value) !Value { | 3157 | pub 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, |
| 3190 | 3162 | 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 | } |
| 3218 | 3191 | ||
| 3219 | pub fn simplePtrType(self: *Module, scope: *Scope, src: usize, elem_ty: Type, mutable: bool, size: std.builtin.TypeInfo.Pointer.Size) Allocator.Error!Type { | 3192 | pub 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 | }; |
| 2064 | 2064 | ||
| 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 | } |
| 2072 | 2070 | ||
| ... | @@ -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..]; |
| 2090 | 2088 | ||
| 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 | } |
| 2111 | 2107 | ||
| 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 tokenizer | 2109 | 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 | } |
| 2123 | 2117 |
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 array | 139 | // 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 pointer | 170 | // 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 | } |
| 434 | 434 | ||
| 435 | const module_fn = typed_value.val.cast(Value.Payload.Function).?.func; | 435 | const module_fn = typed_value.val.castTag(.function).?.data; |
| 436 | 436 | ||
| 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; |
| 438 | 438 | ||
| ... | @@ -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 | } |
| 1581 | 1581 | ||
| 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; |
| 1585 | 1585 | ||
| 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}); |
| 1609 | 1609 | ||
| 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; |
| 1613 | 1613 | ||
| 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 | } |
| 1707 | 1707 | ||
| 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 | } |
| 1768 | 1768 | ||
| 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 | } |
| 1827 | 1827 | ||
| 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; |
| 142 | 142 | ||
| 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 | } |
| 270 | 270 | ||
| 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); |
| 274 | 274 | ||
| 275 | try writer.writeAll(" {"); | 275 | try writer.writeAll(" {"); |
| 276 | 276 | ||
| 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.decl | 484 | 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_decl | 486 | func_payload.data.owner_decl |
| 487 | else | 487 | else |
| 488 | unreachable; | 488 | unreachable; |
| 489 | 489 | ||
| ... | @@ -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 instructions | 62 | // Write instructions |
| 63 | // TODO: check for and handle death of instructions | 63 | // 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); |
| 67 | 67 | ||
| 68 | // Write 'end' opcode | 68 | // 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 { |
| 125 | 125 | ||
| 126 | fn genCall(buf: *ArrayList(u8), decl: *Decl, inst: *Inst.Call) !void { | 126 | fn 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; |
| 131 | 131 | ||
| 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; |
| 284 | 284 | ||
| 285 | const llvm_func = try self.resolveLLVMFunction(func); | 285 | const llvm_func = try self.resolveLLVMFunction(func); |
| 286 | 286 | ||
| ... | @@ -314,9 +314,9 @@ pub const LLVMIRModule = struct { | ... | @@ -314,9 +314,9 @@ pub const LLVMIRModule = struct { |
| 314 | } | 314 | } |
| 315 | 315 | ||
| 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); |
| 322 | 322 |
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 | } |
| 743 | 739 | ||
| ... | @@ -2951,11 +2947,8 @@ pub const Type = extern union { | ... | @@ -2951,11 +2947,8 @@ pub const Type = extern union { |
| 2951 | } | 2947 | } |
| 2952 | 2948 | ||
| 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 | } |
| 2960 | 2953 | ||
| 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 { |
| 2964 | 2957 | ||
| 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 | } |
| 2976 | 2965 | ||
| ... | @@ -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); |
| 2981 | 2970 | ||
| 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 | } |
| 2995 | 2978 | ||
| 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 { |
| 3003 | 2986 | ||
| 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 | } |
| 3015 | 2994 |
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 times | 94 | /// 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 { |
| 99 | 104 | ||
| 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 | }; |
| 103 | 208 | ||
| 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 | } |
| 121 | 226 | ||
| 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 | } | ||
| 125 | 248 | ||
| 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; |
| 129 | 252 | ||
| 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 | } |
| 132 | 258 | ||
| 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, |
| 189 | 315 | ||
| 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 | } |
| 260 | 388 | ||
| 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 | } |
| 378 | 506 | ||
| 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"), |
| 440 | 571 | ||
| 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 | }, |
| 456 | 587 | ||
| ... | @@ -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(), |
| 566 | 697 | ||
| 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 | } |
| 573 | 704 | ||
| ... | @@ -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, |
| 651 | 782 | ||
| 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 | } |
| 658 | 789 | ||
| ... | @@ -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, |
| 736 | 867 | ||
| 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 | } |
| 743 | 874 | ||
| ... | @@ -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), |
| 759 | 890 | ||
| 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), |
| 764 | 895 | ||
| 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, |
| 847 | 978 | ||
| 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 | } |
| 860 | 991 | ||
| ... | @@ -943,7 +1074,7 @@ pub const Value = extern union { | ... | @@ -943,7 +1074,7 @@ pub const Value = extern union { |
| 943 | 1074 | ||
| 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, |
| 1104 | 1221 | ||
| 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, |
| 1184 | 1301 | ||
| 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), |
| 1189 | 1306 | ||
| 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 | } |
| 1196 | 1313 | ||
| ... | @@ -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)), |
| 1342 | 1459 | ||
| 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, |
| 1485 | 1606 | ||
| 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 { |
| 1570 | 1691 | ||
| 1571 | .empty_array => unreachable, // out of bounds array index | 1692 | .empty_array => unreachable, // out of bounds array index |
| 1572 | 1693 | ||
| 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 | }, | ||
| 1578 | 1695 | ||
| 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 | } |
| 1583 | 1700 | ||
| 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 | } |
| 1594 | 1715 | ||
| 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, |
| 1778 | 1899 | ||
| 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 | }; |
| 1783 | 1904 | ||
| 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 | }; |
| 1797 | 1909 | ||
| 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, |
| 1801 | 1913 | ||
| 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 | }; |
| 1806 | 1923 | ||
| 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 | }; |
| 1811 | 1928 | ||
| 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 | }; |
| 1816 | 1933 | ||
| 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 | }; |
| 1832 | 1938 | ||
| 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 | }; |
| 1838 | 1943 | ||
| 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 | }; |
| 1844 | 1953 | ||
| 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 | }; |
| 1849 | 1958 | ||
| 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 | }; |
| 1854 | 1963 | ||
| 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 | }; | ||
| 1860 | 1966 | ||
| 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 repeat | 1969 | bits: u16, |
| 1864 | /// is stored externally. | 1970 | signed: bool, |
| 1865 | val: Value, | 1971 | }, |
| 1866 | }; | 1972 | }; |
| 1867 | 1973 | ||
| 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 | }; |
| 1872 | 1980 | ||
| 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 | }; |
| 1877 | 1987 | ||
| 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 | }; |
| 1882 | 1994 | ||
| 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 | }; |
| 1887 | 2001 | ||
| 1888 | pub const ErrorSet = struct { | 2002 | pub const ErrorSet = struct { |
| 1889 | base: Payload = .{ .tag = .error_set }, | 2003 | pub const base_tag = Tag.error_set; |
| 1890 | 2004 | ||
| 1891 | // TODO revisit this when we have the concept of the error tag type | 2005 | 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 | }; |
| 1895 | 2012 | ||
| 1896 | pub const Error = struct { | 2013 | pub const Error = struct { |
| 1897 | base: Payload = .{ .tag = .@"error" }, | 2014 | base: Payload = .{ .tag = .@"error" }, |
| 1898 | 2015 | data: struct { | |
| 1899 | // TODO revisit this when we have the concept of the error tag type | 2016 | // TODO revisit this when we have the concept of the error tag type |
| 1900 | /// `name` is owned by `Module` and will be valid for the entire | 2017 | /// `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 | }; |
| 1906 | 2024 | ||
| ... | @@ -1914,15 +2032,24 @@ pub const Value = extern union { | ... | @@ -1914,15 +2032,24 @@ pub const Value = extern union { |
| 1914 | 2032 | ||
| 1915 | test "hash same value different representation" { | 2033 | test "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()); |
| 1920 | 2041 | ||
| 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()); |
| 1924 | 2048 | ||
| 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 { |
| 1990 | 1990 | ||
| 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 { |
| 2150 | 2150 | ||
| 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 | else | 2248 | 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); |
| 2805 | 2807 | ||
| 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); |
| 365 | 365 | ||
| 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 | } |
| 375 | 372 | ||
| ... | @@ -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); |
| 482 | 479 | ||
| 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 | } |
| 789 | 781 | ||
| ... | @@ -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 |
| 838 | 830 | ||
| 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 below | 834 | .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)); |
| 845 | 840 | ||
| 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 | } |
| 860 | 855 | ||
| ... | @@ -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 | } |
| 864 | 859 | ||
| 865 | fn analyzeInstEnumLiteral(mod: *Module, scope: *Scope, inst: *zir.Inst.EnumLiteral) InnerError!*Inst { | 860 | fn 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 | } |
| 876 | 867 | ||
| ... | @@ -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 sets | 1030 | // 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) orelse | 1032 | (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 | else | 1034 | else |
| 1050 | try mod.getErrorValue(field_name); | 1035 | try mod.getErrorValue(field_name); |
| 1051 | 1036 | ||
| 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 | else | 1039 | 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 |
| 1065 | 1041 | ||
| 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 => { |