authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-03-26 21:11:18-07:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2024-03-26 21:11:18-07:00
log5140f2726ae6e09381d9d44a72626dfe319f068b
treeb2163e1439be4858c8e11b7d210ab91e262ab761
parent341857e5cd4fd4453cf9c7d1a6679feb66710d84
parent513254956525f8f970e972f6973ab4df0b19d06a
signaturebadge-check Signed by PGP key B5690EEEBB952194

Merge pull request #19437 from mlugg/value-cleanups

Follow-up to #19414

40 files changed, 2016 insertions(+), 2706 deletions(-)

CMakeLists.txt+2-1
...@@ -526,7 +526,6 @@ set(ZIG_STAGE2_SOURCES...@@ -526,7 +526,6 @@ set(ZIG_STAGE2_SOURCES
526 "${CMAKE_SOURCE_DIR}/src/Package/Fetch.zig"526 "${CMAKE_SOURCE_DIR}/src/Package/Fetch.zig"
527 "${CMAKE_SOURCE_DIR}/src/RangeSet.zig"527 "${CMAKE_SOURCE_DIR}/src/RangeSet.zig"
528 "${CMAKE_SOURCE_DIR}/src/Sema.zig"528 "${CMAKE_SOURCE_DIR}/src/Sema.zig"
529 "${CMAKE_SOURCE_DIR}/src/TypedValue.zig"
530 "${CMAKE_SOURCE_DIR}/src/Value.zig"529 "${CMAKE_SOURCE_DIR}/src/Value.zig"
531 "${CMAKE_SOURCE_DIR}/src/arch/aarch64/CodeGen.zig"530 "${CMAKE_SOURCE_DIR}/src/arch/aarch64/CodeGen.zig"
532 "${CMAKE_SOURCE_DIR}/src/arch/aarch64/Emit.zig"531 "${CMAKE_SOURCE_DIR}/src/arch/aarch64/Emit.zig"
...@@ -634,9 +633,11 @@ set(ZIG_STAGE2_SOURCES...@@ -634,9 +633,11 @@ set(ZIG_STAGE2_SOURCES
634 "${CMAKE_SOURCE_DIR}/src/main.zig"633 "${CMAKE_SOURCE_DIR}/src/main.zig"
635 "${CMAKE_SOURCE_DIR}/src/mingw.zig"634 "${CMAKE_SOURCE_DIR}/src/mingw.zig"
636 "${CMAKE_SOURCE_DIR}/src/musl.zig"635 "${CMAKE_SOURCE_DIR}/src/musl.zig"
636 "${CMAKE_SOURCE_DIR}/src/mutable_value.zig"
637 "${CMAKE_SOURCE_DIR}/src/print_air.zig"637 "${CMAKE_SOURCE_DIR}/src/print_air.zig"
638 "${CMAKE_SOURCE_DIR}/src/print_env.zig"638 "${CMAKE_SOURCE_DIR}/src/print_env.zig"
639 "${CMAKE_SOURCE_DIR}/src/print_targets.zig"639 "${CMAKE_SOURCE_DIR}/src/print_targets.zig"
640 "${CMAKE_SOURCE_DIR}/src/print_value.zig"
640 "${CMAKE_SOURCE_DIR}/src/print_zir.zig"641 "${CMAKE_SOURCE_DIR}/src/print_zir.zig"
641 "${CMAKE_SOURCE_DIR}/src/register_manager.zig"642 "${CMAKE_SOURCE_DIR}/src/register_manager.zig"
642 "${CMAKE_SOURCE_DIR}/src/target.zig"643 "${CMAKE_SOURCE_DIR}/src/target.zig"
src/Compilation.zig+1-18
...@@ -102,7 +102,6 @@ link_errors: std.ArrayListUnmanaged(link.File.ErrorMsg) = .{},...@@ -102,7 +102,6 @@ link_errors: std.ArrayListUnmanaged(link.File.ErrorMsg) = .{},
102lld_errors: std.ArrayListUnmanaged(LldError) = .{},102lld_errors: std.ArrayListUnmanaged(LldError) = .{},
103103
104work_queue: std.fifo.LinearFifo(Job, .Dynamic),104work_queue: std.fifo.LinearFifo(Job, .Dynamic),
105anon_work_queue: std.fifo.LinearFifo(Job, .Dynamic),
106105
107/// These jobs are to invoke the Clang compiler to create an object file, which106/// These jobs are to invoke the Clang compiler to create an object file, which
108/// gets linked with the Compilation.107/// gets linked with the Compilation.
...@@ -1417,7 +1416,6 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil...@@ -1417,7 +1416,6 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
1417 .emit_llvm_ir = options.emit_llvm_ir,1416 .emit_llvm_ir = options.emit_llvm_ir,
1418 .emit_llvm_bc = options.emit_llvm_bc,1417 .emit_llvm_bc = options.emit_llvm_bc,
1419 .work_queue = std.fifo.LinearFifo(Job, .Dynamic).init(gpa),1418 .work_queue = std.fifo.LinearFifo(Job, .Dynamic).init(gpa),
1420 .anon_work_queue = std.fifo.LinearFifo(Job, .Dynamic).init(gpa),
1421 .c_object_work_queue = std.fifo.LinearFifo(*CObject, .Dynamic).init(gpa),1419 .c_object_work_queue = std.fifo.LinearFifo(*CObject, .Dynamic).init(gpa),
1422 .win32_resource_work_queue = if (build_options.only_core_functionality) {} else std.fifo.LinearFifo(*Win32Resource, .Dynamic).init(gpa),1420 .win32_resource_work_queue = if (build_options.only_core_functionality) {} else std.fifo.LinearFifo(*Win32Resource, .Dynamic).init(gpa),
1423 .astgen_work_queue = std.fifo.LinearFifo(*Module.File, .Dynamic).init(gpa),1421 .astgen_work_queue = std.fifo.LinearFifo(*Module.File, .Dynamic).init(gpa),
...@@ -1840,7 +1838,6 @@ pub fn destroy(comp: *Compilation) void {...@@ -1840,7 +1838,6 @@ pub fn destroy(comp: *Compilation) void {
1840 if (comp.module) |zcu| zcu.deinit();1838 if (comp.module) |zcu| zcu.deinit();
1841 comp.cache_use.deinit();1839 comp.cache_use.deinit();
1842 comp.work_queue.deinit();1840 comp.work_queue.deinit();
1843 comp.anon_work_queue.deinit();
1844 comp.c_object_work_queue.deinit();1841 comp.c_object_work_queue.deinit();
1845 if (!build_options.only_core_functionality) {1842 if (!build_options.only_core_functionality) {
1846 comp.win32_resource_work_queue.deinit();1843 comp.win32_resource_work_queue.deinit();
...@@ -3354,18 +3351,11 @@ pub fn performAllTheWork(...@@ -3354,18 +3351,11 @@ pub fn performAllTheWork(
3354 mod.sema_prog_node = undefined;3351 mod.sema_prog_node = undefined;
3355 };3352 };
33563353
3357 // In this main loop we give priority to non-anonymous Decls in the work queue, so
3358 // that they can establish references to anonymous Decls, setting alive=true in the
3359 // backend, preventing anonymous Decls from being prematurely destroyed.
3360 while (true) {3354 while (true) {
3361 if (comp.work_queue.readItem()) |work_item| {3355 if (comp.work_queue.readItem()) |work_item| {
3362 try processOneJob(comp, work_item, main_progress_node);3356 try processOneJob(comp, work_item, main_progress_node);
3363 continue;3357 continue;
3364 }3358 }
3365 if (comp.anon_work_queue.readItem()) |work_item| {
3366 try processOneJob(comp, work_item, main_progress_node);
3367 continue;
3368 }
3369 if (comp.module) |zcu| {3359 if (comp.module) |zcu| {
3370 // If there's no work queued, check if there's anything outdated3360 // If there's no work queued, check if there's anything outdated
3371 // which we need to work on, and queue it if so.3361 // which we need to work on, and queue it if so.
...@@ -3413,14 +3403,7 @@ fn processOneJob(comp: *Compilation, job: Job, prog_node: *std.Progress.Node) !v...@@ -3413,14 +3403,7 @@ fn processOneJob(comp: *Compilation, job: Job, prog_node: *std.Progress.Node) !v
34133403
3414 assert(decl.has_tv);3404 assert(decl.has_tv);
34153405
3416 if (decl.alive) {3406 try module.linkerUpdateDecl(decl_index);
3417 try module.linkerUpdateDecl(decl_index);
3418 return;
3419 }
3420
3421 // Instead of sending this decl to the linker, we actually will delete it
3422 // because we found out that it in fact was never referenced.
3423 module.deleteUnusedDecl(decl_index);
3424 return;3407 return;
3425 },3408 },
3426 }3409 }
src/InternPool.zig-5
...@@ -6581,7 +6581,6 @@ pub fn getFuncInstance(ip: *InternPool, gpa: Allocator, arg: GetFuncInstanceKey)...@@ -6581,7 +6581,6 @@ pub fn getFuncInstance(ip: *InternPool, gpa: Allocator, arg: GetFuncInstanceKey)
6581 generic_owner,6581 generic_owner,
6582 func_index,6582 func_index,
6583 func_extra_index,6583 func_extra_index,
6584 func_ty,
6585 arg.alignment,6584 arg.alignment,
6586 arg.section,6585 arg.section,
6587 );6586 );
...@@ -6711,7 +6710,6 @@ pub fn getFuncInstanceIes(...@@ -6711,7 +6710,6 @@ pub fn getFuncInstanceIes(
6711 generic_owner,6710 generic_owner,
6712 func_index,6711 func_index,
6713 func_extra_index,6712 func_extra_index,
6714 func_ty,
6715 arg.alignment,6713 arg.alignment,
6716 arg.section,6714 arg.section,
6717 );6715 );
...@@ -6723,7 +6721,6 @@ fn finishFuncInstance(...@@ -6723,7 +6721,6 @@ fn finishFuncInstance(
6723 generic_owner: Index,6721 generic_owner: Index,
6724 func_index: Index,6722 func_index: Index,
6725 func_extra_index: u32,6723 func_extra_index: u32,
6726 func_ty: Index,
6727 alignment: Alignment,6724 alignment: Alignment,
6728 section: OptionalNullTerminatedString,6725 section: OptionalNullTerminatedString,
6729) Allocator.Error!Index {6726) Allocator.Error!Index {
...@@ -6735,7 +6732,6 @@ fn finishFuncInstance(...@@ -6735,7 +6732,6 @@ fn finishFuncInstance(
6735 .src_line = fn_owner_decl.src_line,6732 .src_line = fn_owner_decl.src_line,
6736 .has_tv = true,6733 .has_tv = true,
6737 .owns_tv = true,6734 .owns_tv = true,
6738 .ty = @import("type.zig").Type.fromInterned(func_ty),
6739 .val = @import("Value.zig").fromInterned(func_index),6735 .val = @import("Value.zig").fromInterned(func_index),
6740 .alignment = alignment,6736 .alignment = alignment,
6741 .@"linksection" = section,6737 .@"linksection" = section,
...@@ -6744,7 +6740,6 @@ fn finishFuncInstance(...@@ -6744,7 +6740,6 @@ fn finishFuncInstance(
6744 .zir_decl_index = fn_owner_decl.zir_decl_index,6740 .zir_decl_index = fn_owner_decl.zir_decl_index,
6745 .is_pub = fn_owner_decl.is_pub,6741 .is_pub = fn_owner_decl.is_pub,
6746 .is_exported = fn_owner_decl.is_exported,6742 .is_exported = fn_owner_decl.is_exported,
6747 .alive = true,
6748 .kind = .anon,6743 .kind = .anon,
6749 });6744 });
6750 errdefer ip.destroyDecl(gpa, decl_index);6745 errdefer ip.destroyDecl(gpa, decl_index);
src/Module.zig+56-209
...@@ -22,7 +22,6 @@ const Compilation = @import("Compilation.zig");...@@ -22,7 +22,6 @@ const Compilation = @import("Compilation.zig");
22const Cache = std.Build.Cache;22const Cache = std.Build.Cache;
23const Value = @import("Value.zig");23const Value = @import("Value.zig");
24const Type = @import("type.zig").Type;24const Type = @import("type.zig").Type;
25const TypedValue = @import("TypedValue.zig");
26const Package = @import("Package.zig");25const Package = @import("Package.zig");
27const link = @import("link.zig");26const link = @import("link.zig");
28const Air = @import("Air.zig");27const Air = @import("Air.zig");
...@@ -330,9 +329,6 @@ const ValueArena = struct {...@@ -330,9 +329,6 @@ const ValueArena = struct {
330329
331pub const Decl = struct {330pub const Decl = struct {
332 name: InternPool.NullTerminatedString,331 name: InternPool.NullTerminatedString,
333 /// The most recent Type of the Decl after a successful semantic analysis.
334 /// Populated when `has_tv`.
335 ty: Type,
336 /// The most recent Value of the Decl after a successful semantic analysis.332 /// The most recent Value of the Decl after a successful semantic analysis.
337 /// Populated when `has_tv`.333 /// Populated when `has_tv`.
338 val: Value,334 val: Value,
...@@ -397,15 +393,6 @@ pub const Decl = struct {...@@ -397,15 +393,6 @@ pub const Decl = struct {
397 is_pub: bool,393 is_pub: bool,
398 /// Whether the corresponding AST decl has a `export` keyword.394 /// Whether the corresponding AST decl has a `export` keyword.
399 is_exported: bool,395 is_exported: bool,
400 /// Flag used by garbage collection to mark and sweep.
401 /// Decls which correspond to an AST node always have this field set to `true`.
402 /// Anonymous Decls are initialized with this field set to `false` and then it
403 /// is the responsibility of machine code backends to mark it `true` whenever
404 /// a `decl_ref` Value is encountered that points to this Decl.
405 /// When the `codegen_decl` job is encountered in the main work queue, if the
406 /// Decl is marked alive, then it sends the Decl to the linker. Otherwise it
407 /// deletes the Decl on the spot.
408 alive: bool,
409 /// If true `name` is already fully qualified.396 /// If true `name` is already fully qualified.
410 name_fully_qualified: bool = false,397 name_fully_qualified: bool = false,
411 /// What kind of a declaration is this.398 /// What kind of a declaration is this.
...@@ -438,14 +425,6 @@ pub const Decl = struct {...@@ -438,14 +425,6 @@ pub const Decl = struct {
438 return @as(i32, @bitCast(node_index)) - @as(i32, @bitCast(decl.src_node));425 return @as(i32, @bitCast(node_index)) - @as(i32, @bitCast(decl.src_node));
439 }426 }
440427
441 pub fn tokSrcLoc(decl: Decl, token_index: Ast.TokenIndex) LazySrcLoc {
442 return .{ .token_offset = token_index - decl.srcToken() };
443 }
444
445 pub fn nodeSrcLoc(decl: Decl, node_index: Ast.Node.Index) LazySrcLoc {
446 return LazySrcLoc.nodeOffset(decl.nodeIndexToRelative(node_index));
447 }
448
449 pub fn srcLoc(decl: Decl, zcu: *Zcu) SrcLoc {428 pub fn srcLoc(decl: Decl, zcu: *Zcu) SrcLoc {
450 return decl.nodeOffsetSrcLoc(0, zcu);429 return decl.nodeOffsetSrcLoc(0, zcu);
451 }430 }
...@@ -458,16 +437,6 @@ pub const Decl = struct {...@@ -458,16 +437,6 @@ pub const Decl = struct {
458 };437 };
459 }438 }
460439
461 pub fn srcToken(decl: Decl, zcu: *Zcu) Ast.TokenIndex {
462 const tree = &decl.getFileScope(zcu).tree;
463 return tree.firstToken(decl.src_node);
464 }
465
466 pub fn srcByteOffset(decl: Decl, zcu: *Zcu) u32 {
467 const tree = &decl.getFileScope(zcu).tree;
468 return tree.tokens.items(.start)[decl.srcToken()];
469 }
470
471 pub fn renderFullyQualifiedName(decl: Decl, zcu: *Zcu, writer: anytype) !void {440 pub fn renderFullyQualifiedName(decl: Decl, zcu: *Zcu, writer: anytype) !void {
472 if (decl.name_fully_qualified) {441 if (decl.name_fully_qualified) {
473 try writer.print("{}", .{decl.name.fmt(&zcu.intern_pool)});442 try writer.print("{}", .{decl.name.fmt(&zcu.intern_pool)});
...@@ -487,37 +456,16 @@ pub const Decl = struct {...@@ -487,37 +456,16 @@ pub const Decl = struct {
487 zcu.namespacePtr(decl.src_namespace).fullyQualifiedName(zcu, decl.name);456 zcu.namespacePtr(decl.src_namespace).fullyQualifiedName(zcu, decl.name);
488 }457 }
489458
490 pub fn typedValue(decl: Decl) error{AnalysisFail}!TypedValue {459 pub fn typeOf(decl: Decl, zcu: *const Zcu) Type {
491 if (!decl.has_tv) return error.AnalysisFail;
492 return TypedValue{ .ty = decl.ty, .val = decl.val };
493 }
494
495 pub fn internValue(decl: *Decl, zcu: *Zcu) Allocator.Error!InternPool.Index {
496 assert(decl.has_tv);460 assert(decl.has_tv);
497 const ip_index = try decl.val.intern(decl.ty, zcu);461 return decl.val.typeOf(zcu);
498 decl.val = Value.fromInterned(ip_index);
499 return ip_index;
500 }462 }
501463
502 pub fn isFunction(decl: Decl, zcu: *const Zcu) !bool {464 /// Small wrapper for Sema to use over direct access to the `val` field.
503 const tv = try decl.typedValue();465 /// If the value is not populated, instead returns `error.AnalysisFail`.
504 return tv.ty.zigTypeTag(zcu) == .Fn;466 pub fn valueOrFail(decl: Decl) error{AnalysisFail}!Value {
505 }467 if (!decl.has_tv) return error.AnalysisFail;
506468 return decl.val;
507 /// If the Decl owns its value and it is a struct, return it,
508 /// otherwise null.
509 pub fn getOwnedStruct(decl: Decl, zcu: *Zcu) ?InternPool.Key.StructType {
510 if (!decl.owns_tv) return null;
511 if (decl.val.ip_index == .none) return null;
512 return zcu.typeToStruct(decl.val.toType());
513 }
514
515 /// If the Decl owns its value and it is a union, return it,
516 /// otherwise null.
517 pub fn getOwnedUnion(decl: Decl, zcu: *Zcu) ?InternPool.LoadedUnionType {
518 if (!decl.owns_tv) return null;
519 if (decl.val.ip_index == .none) return null;
520 return zcu.typeToUnion(decl.val.toType());
521 }469 }
522470
523 pub fn getOwnedFunction(decl: Decl, zcu: *Zcu) ?InternPool.Key.Func {471 pub fn getOwnedFunction(decl: Decl, zcu: *Zcu) ?InternPool.Key.Func {
...@@ -590,7 +538,7 @@ pub const Decl = struct {...@@ -590,7 +538,7 @@ pub const Decl = struct {
590 @tagName(decl.analysis),538 @tagName(decl.analysis),
591 });539 });
592 if (decl.has_tv) {540 if (decl.has_tv) {
593 std.debug.print(" ty={} val={}", .{ decl.ty, decl.val });541 std.debug.print(" val={}", .{decl.val});
594 }542 }
595 std.debug.print("\n", .{});543 std.debug.print("\n", .{});
596 }544 }
...@@ -615,7 +563,7 @@ pub const Decl = struct {...@@ -615,7 +563,7 @@ pub const Decl = struct {
615 pub fn getAlignment(decl: Decl, zcu: *Zcu) Alignment {563 pub fn getAlignment(decl: Decl, zcu: *Zcu) Alignment {
616 assert(decl.has_tv);564 assert(decl.has_tv);
617 if (decl.alignment != .none) return decl.alignment;565 if (decl.alignment != .none) return decl.alignment;
618 return decl.ty.abiAlignment(zcu);566 return decl.typeOf(zcu).abiAlignment(zcu);
619 }567 }
620568
621 /// Upgrade a `LazySrcLoc` to a `SrcLoc` based on the `Decl` provided.569 /// Upgrade a `LazySrcLoc` to a `SrcLoc` based on the `Decl` provided.
...@@ -3525,10 +3473,8 @@ fn semaFile(mod: *Module, file: *File) SemaError!void {...@@ -3525,10 +3473,8 @@ fn semaFile(mod: *Module, file: *File) SemaError!void {
3525 new_decl.src_line = 0;3473 new_decl.src_line = 0;
3526 new_decl.is_pub = true;3474 new_decl.is_pub = true;
3527 new_decl.is_exported = false;3475 new_decl.is_exported = false;
3528 new_decl.ty = Type.type;
3529 new_decl.alignment = .none;3476 new_decl.alignment = .none;
3530 new_decl.@"linksection" = .none;3477 new_decl.@"linksection" = .none;
3531 new_decl.alive = true; // This Decl corresponds to a File and is therefore always alive.
3532 new_decl.analysis = .in_progress;3478 new_decl.analysis = .in_progress;
35333479
3534 if (file.status != .success_zir) {3480 if (file.status != .success_zir) {
...@@ -3594,7 +3540,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !SemaDeclResult {...@@ -3594,7 +3540,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !SemaDeclResult {
35943540
3595 const old_has_tv = decl.has_tv;3541 const old_has_tv = decl.has_tv;
3596 // The following values are ignored if `!old_has_tv`3542 // The following values are ignored if `!old_has_tv`
3597 const old_ty = decl.ty;3543 const old_ty = if (old_has_tv) decl.typeOf(mod) else undefined;
3598 const old_val = decl.val;3544 const old_val = decl.val;
3599 const old_align = decl.alignment;3545 const old_align = decl.alignment;
3600 const old_linksection = decl.@"linksection";3546 const old_linksection = decl.@"linksection";
...@@ -3698,25 +3644,25 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !SemaDeclResult {...@@ -3698,25 +3644,25 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !SemaDeclResult {
3698 const address_space_src: LazySrcLoc = .{ .node_offset_var_decl_addrspace = 0 };3644 const address_space_src: LazySrcLoc = .{ .node_offset_var_decl_addrspace = 0 };
3699 const ty_src: LazySrcLoc = .{ .node_offset_var_decl_ty = 0 };3645 const ty_src: LazySrcLoc = .{ .node_offset_var_decl_ty = 0 };
3700 const init_src: LazySrcLoc = .{ .node_offset_var_decl_init = 0 };3646 const init_src: LazySrcLoc = .{ .node_offset_var_decl_init = 0 };
3701 const decl_tv = try sema.resolveFinalDeclValue(&block_scope, init_src, result_ref);3647 const decl_val = try sema.resolveFinalDeclValue(&block_scope, init_src, result_ref);
3648 const decl_ty = decl_val.typeOf(mod);
37023649
3703 // Note this resolves the type of the Decl, not the value; if this Decl3650 // Note this resolves the type of the Decl, not the value; if this Decl
3704 // is a struct, for example, this resolves `type` (which needs no resolution),3651 // is a struct, for example, this resolves `type` (which needs no resolution),
3705 // not the struct itself.3652 // not the struct itself.
3706 try sema.resolveTypeLayout(decl_tv.ty);3653 try sema.resolveTypeLayout(decl_ty);
37073654
3708 if (decl.kind == .@"usingnamespace") {3655 if (decl.kind == .@"usingnamespace") {
3709 if (!decl_tv.ty.eql(Type.type, mod)) {3656 if (!decl_ty.eql(Type.type, mod)) {
3710 return sema.fail(&block_scope, ty_src, "expected type, found {}", .{3657 return sema.fail(&block_scope, ty_src, "expected type, found {}", .{
3711 decl_tv.ty.fmt(mod),3658 decl_ty.fmt(mod),
3712 });3659 });
3713 }3660 }
3714 const ty = decl_tv.val.toType();3661 const ty = decl_val.toType();
3715 if (ty.getNamespace(mod) == null) {3662 if (ty.getNamespace(mod) == null) {
3716 return sema.fail(&block_scope, ty_src, "type {} has no namespace", .{ty.fmt(mod)});3663 return sema.fail(&block_scope, ty_src, "type {} has no namespace", .{ty.fmt(mod)});
3717 }3664 }
37183665
3719 decl.ty = Type.fromInterned(InternPool.Index.type_type);
3720 decl.val = ty.toValue();3666 decl.val = ty.toValue();
3721 decl.alignment = .none;3667 decl.alignment = .none;
3722 decl.@"linksection" = .none;3668 decl.@"linksection" = .none;
...@@ -3734,10 +3680,10 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !SemaDeclResult {...@@ -3734,10 +3680,10 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !SemaDeclResult {
3734 var queue_linker_work = true;3680 var queue_linker_work = true;
3735 var is_func = false;3681 var is_func = false;
3736 var is_inline = false;3682 var is_inline = false;
3737 switch (decl_tv.val.toIntern()) {3683 switch (decl_val.toIntern()) {
3738 .generic_poison => unreachable,3684 .generic_poison => unreachable,
3739 .unreachable_value => unreachable,3685 .unreachable_value => unreachable,
3740 else => switch (ip.indexToKey(decl_tv.val.toIntern())) {3686 else => switch (ip.indexToKey(decl_val.toIntern())) {
3741 .variable => |variable| {3687 .variable => |variable| {
3742 decl.owns_tv = variable.decl == decl_index;3688 decl.owns_tv = variable.decl == decl_index;
3743 queue_linker_work = decl.owns_tv;3689 queue_linker_work = decl.owns_tv;
...@@ -3752,7 +3698,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !SemaDeclResult {...@@ -3752,7 +3698,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !SemaDeclResult {
3752 .func => |func| {3698 .func => |func| {
3753 decl.owns_tv = func.owner_decl == decl_index;3699 decl.owns_tv = func.owner_decl == decl_index;
3754 queue_linker_work = false;3700 queue_linker_work = false;
3755 is_inline = decl.owns_tv and decl_tv.ty.fnCallingConvention(mod) == .Inline;3701 is_inline = decl.owns_tv and decl_ty.fnCallingConvention(mod) == .Inline;
3756 is_func = decl.owns_tv;3702 is_func = decl.owns_tv;
3757 },3703 },
37583704
...@@ -3760,8 +3706,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !SemaDeclResult {...@@ -3760,8 +3706,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !SemaDeclResult {
3760 },3706 },
3761 }3707 }
37623708
3763 decl.ty = decl_tv.ty;3709 decl.val = decl_val;
3764 decl.val = Value.fromInterned((try decl_tv.val.intern(decl_tv.ty, mod)));
3765 // Function linksection, align, and addrspace were already set by Sema3710 // Function linksection, align, and addrspace were already set by Sema
3766 if (!is_func) {3711 if (!is_func) {
3767 decl.alignment = blk: {3712 decl.alignment = blk: {
...@@ -3784,7 +3729,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !SemaDeclResult {...@@ -3784,7 +3729,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !SemaDeclResult {
3784 break :blk section.toOptional();3729 break :blk section.toOptional();
3785 };3730 };
3786 decl.@"addrspace" = blk: {3731 decl.@"addrspace" = blk: {
3787 const addrspace_ctx: Sema.AddressSpaceContext = switch (ip.indexToKey(decl_tv.val.toIntern())) {3732 const addrspace_ctx: Sema.AddressSpaceContext = switch (ip.indexToKey(decl_val.toIntern())) {
3788 .variable => .variable,3733 .variable => .variable,
3789 .extern_func, .func => .function,3734 .extern_func, .func => .function,
3790 else => .constant,3735 else => .constant,
...@@ -3806,10 +3751,10 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !SemaDeclResult {...@@ -3806,10 +3751,10 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !SemaDeclResult {
3806 decl.analysis = .complete;3751 decl.analysis = .complete;
38073752
3808 const result: SemaDeclResult = if (old_has_tv) .{3753 const result: SemaDeclResult = if (old_has_tv) .{
3809 .invalidate_decl_val = !decl.ty.eql(old_ty, mod) or3754 .invalidate_decl_val = !decl_ty.eql(old_ty, mod) or
3810 !decl.val.eql(old_val, decl.ty, mod) or3755 !decl.val.eql(old_val, decl_ty, mod) or
3811 is_inline != old_is_inline,3756 is_inline != old_is_inline,
3812 .invalidate_decl_ref = !decl.ty.eql(old_ty, mod) or3757 .invalidate_decl_ref = !decl_ty.eql(old_ty, mod) or
3813 decl.alignment != old_align or3758 decl.alignment != old_align or
3814 decl.@"linksection" != old_linksection or3759 decl.@"linksection" != old_linksection or
3815 decl.@"addrspace" != old_addrspace or3760 decl.@"addrspace" != old_addrspace or
...@@ -3819,11 +3764,11 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !SemaDeclResult {...@@ -3819,11 +3764,11 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !SemaDeclResult {
3819 .invalidate_decl_ref = true,3764 .invalidate_decl_ref = true,
3820 };3765 };
38213766
3822 const has_runtime_bits = queue_linker_work and (is_func or try sema.typeHasRuntimeBits(decl.ty));3767 const has_runtime_bits = queue_linker_work and (is_func or try sema.typeHasRuntimeBits(decl_ty));
3823 if (has_runtime_bits) {3768 if (has_runtime_bits) {
3824 // Needed for codegen_decl which will call updateDecl and then the3769 // Needed for codegen_decl which will call updateDecl and then the
3825 // codegen backend wants full access to the Decl Type.3770 // codegen backend wants full access to the Decl Type.
3826 try sema.resolveTypeFully(decl.ty);3771 try sema.resolveTypeFully(decl_ty);
38273772
3828 try mod.comp.work_queue.writeItem(.{ .codegen_decl = decl_index });3773 try mod.comp.work_queue.writeItem(.{ .codegen_decl = decl_index });
38293774
...@@ -3850,7 +3795,7 @@ fn semaAnonOwnerDecl(zcu: *Zcu, decl_index: Decl.Index) !SemaDeclResult {...@@ -3850,7 +3795,7 @@ fn semaAnonOwnerDecl(zcu: *Zcu, decl_index: Decl.Index) !SemaDeclResult {
38503795
3851 log.debug("semaAnonOwnerDecl '{d}'", .{@intFromEnum(decl_index)});3796 log.debug("semaAnonOwnerDecl '{d}'", .{@intFromEnum(decl_index)});
38523797
3853 switch (decl.ty.zigTypeTag(zcu)) {3798 switch (decl.typeOf(zcu).zigTypeTag(zcu)) {
3854 .Fn => @panic("TODO: update fn instance"),3799 .Fn => @panic("TODO: update fn instance"),
3855 .Type => {},3800 .Type => {},
3856 else => unreachable,3801 else => unreachable,
...@@ -4380,7 +4325,6 @@ fn scanDecl(iter: *ScanDeclIter, decl_inst: Zir.Inst.Index) Allocator.Error!void...@@ -4380,7 +4325,6 @@ fn scanDecl(iter: *ScanDeclIter, decl_inst: Zir.Inst.Index) Allocator.Error!void
4380 const decl = zcu.declPtr(decl_index);4325 const decl = zcu.declPtr(decl_index);
4381 const was_exported = decl.is_exported;4326 const was_exported = decl.is_exported;
4382 assert(decl.kind == kind); // ZIR tracking should preserve this4327 assert(decl.kind == kind); // ZIR tracking should preserve this
4383 assert(decl.alive);
4384 decl.name = decl_name;4328 decl.name = decl_name;
4385 decl.src_node = decl_node;4329 decl.src_node = decl_node;
4386 decl.src_line = line;4330 decl.src_line = line;
...@@ -4397,7 +4341,6 @@ fn scanDecl(iter: *ScanDeclIter, decl_inst: Zir.Inst.Index) Allocator.Error!void...@@ -4397,7 +4341,6 @@ fn scanDecl(iter: *ScanDeclIter, decl_inst: Zir.Inst.Index) Allocator.Error!void
4397 new_decl.is_pub = declaration.flags.is_pub;4341 new_decl.is_pub = declaration.flags.is_pub;
4398 new_decl.is_exported = declaration.flags.is_export;4342 new_decl.is_exported = declaration.flags.is_export;
4399 new_decl.zir_decl_index = tracked_inst.toOptional();4343 new_decl.zir_decl_index = tracked_inst.toOptional();
4400 new_decl.alive = true; // This Decl corresponds to an AST node and is therefore always alive.
4401 break :decl_index .{ false, new_decl_index };4344 break :decl_index .{ false, new_decl_index };
4402 };4345 };
44034346
...@@ -4450,22 +4393,6 @@ fn scanDecl(iter: *ScanDeclIter, decl_inst: Zir.Inst.Index) Allocator.Error!void...@@ -4450,22 +4393,6 @@ fn scanDecl(iter: *ScanDeclIter, decl_inst: Zir.Inst.Index) Allocator.Error!void
4450 }4393 }
4451}4394}
44524395
4453/// This function is exclusively called for anonymous decls.
4454/// All resources referenced by anonymous decls are owned by InternPool
4455/// so there is no cleanup to do here.
4456pub fn deleteUnusedDecl(mod: *Module, decl_index: Decl.Index) void {
4457 const gpa = mod.gpa;
4458 const ip = &mod.intern_pool;
4459
4460 ip.destroyDecl(gpa, decl_index);
4461
4462 if (mod.emit_h) |mod_emit_h| {
4463 const decl_emit_h = mod_emit_h.declPtr(decl_index);
4464 decl_emit_h.fwd_decl.deinit(gpa);
4465 decl_emit_h.* = undefined;
4466 }
4467}
4468
4469/// Cancel the creation of an anon decl and delete any references to it.4396/// Cancel the creation of an anon decl and delete any references to it.
4470/// If other decls depend on this decl, they must be aborted first.4397/// If other decls depend on this decl, they must be aborted first.
4471pub fn abortAnonDecl(mod: *Module, decl_index: Decl.Index) void {4398pub fn abortAnonDecl(mod: *Module, decl_index: Decl.Index) void {
...@@ -4475,12 +4402,8 @@ pub fn abortAnonDecl(mod: *Module, decl_index: Decl.Index) void {...@@ -4475,12 +4402,8 @@ pub fn abortAnonDecl(mod: *Module, decl_index: Decl.Index) void {
44754402
4476/// Finalize the creation of an anon decl.4403/// Finalize the creation of an anon decl.
4477pub fn finalizeAnonDecl(mod: *Module, decl_index: Decl.Index) Allocator.Error!void {4404pub fn finalizeAnonDecl(mod: *Module, decl_index: Decl.Index) Allocator.Error!void {
4478 // The Decl starts off with alive=false and the codegen backend will set alive=true4405 if (mod.declPtr(decl_index).typeOf(mod).isFnOrHasRuntimeBits(mod)) {
4479 // if the Decl is referenced by an instruction or another constant. Otherwise,4406 try mod.comp.work_queue.writeItem(.{ .codegen_decl = decl_index });
4480 // the Decl will be garbage collected by the `codegen_decl` task instead of sent
4481 // to the linker.
4482 if (mod.declPtr(decl_index).ty.isFnOrHasRuntimeBits(mod)) {
4483 try mod.comp.anon_work_queue.writeItem(.{ .codegen_decl = decl_index });
4484 }4407 }
4485}4408}
44864409
...@@ -4563,7 +4486,7 @@ pub fn analyzeFnBody(mod: *Module, func_index: InternPool.Index, arena: Allocato...@@ -4563,7 +4486,7 @@ pub fn analyzeFnBody(mod: *Module, func_index: InternPool.Index, arena: Allocato
4563 // the runtime-known parameters only, not to be confused with the4486 // the runtime-known parameters only, not to be confused with the
4564 // generic_owner function type, which potentially has more parameters,4487 // generic_owner function type, which potentially has more parameters,
4565 // including comptime parameters.4488 // including comptime parameters.
4566 const fn_ty = decl.ty;4489 const fn_ty = decl.typeOf(mod);
4567 const fn_ty_info = mod.typeToFunc(fn_ty).?;4490 const fn_ty_info = mod.typeToFunc(fn_ty).?;
45684491
4569 var sema: Sema = .{4492 var sema: Sema = .{
...@@ -4812,7 +4735,6 @@ pub fn allocateNewDecl(...@@ -4812,7 +4735,6 @@ pub fn allocateNewDecl(
4812 .src_line = undefined,4735 .src_line = undefined,
4813 .has_tv = false,4736 .has_tv = false,
4814 .owns_tv = false,4737 .owns_tv = false,
4815 .ty = undefined,
4816 .val = undefined,4738 .val = undefined,
4817 .alignment = undefined,4739 .alignment = undefined,
4818 .@"linksection" = .none,4740 .@"linksection" = .none,
...@@ -4821,7 +4743,6 @@ pub fn allocateNewDecl(...@@ -4821,7 +4743,6 @@ pub fn allocateNewDecl(
4821 .zir_decl_index = .none,4743 .zir_decl_index = .none,
4822 .is_pub = false,4744 .is_pub = false,
4823 .is_exported = false,4745 .is_exported = false,
4824 .alive = false,
4825 .kind = .anon,4746 .kind = .anon,
4826 });4747 });
48274748
...@@ -4856,41 +4777,18 @@ pub fn errorSetBits(mod: *Module) u16 {...@@ -4856,41 +4777,18 @@ pub fn errorSetBits(mod: *Module) u16 {
4856 return std.math.log2_int_ceil(ErrorInt, mod.error_limit + 1); // +1 for no error4777 return std.math.log2_int_ceil(ErrorInt, mod.error_limit + 1); // +1 for no error
4857}4778}
48584779
4859pub fn createAnonymousDecl(mod: *Module, block: *Sema.Block, typed_value: TypedValue) !Decl.Index {
4860 const src_decl = mod.declPtr(block.src_decl);
4861 return mod.createAnonymousDeclFromDecl(src_decl, block.namespace, typed_value);
4862}
4863
4864pub fn createAnonymousDeclFromDecl(
4865 mod: *Module,
4866 src_decl: *Decl,
4867 namespace: Namespace.Index,
4868 tv: TypedValue,
4869) !Decl.Index {
4870 const new_decl_index = try mod.allocateNewDecl(namespace, src_decl.src_node);
4871 errdefer mod.destroyDecl(new_decl_index);
4872 const name = try mod.intern_pool.getOrPutStringFmt(mod.gpa, "{}__anon_{d}", .{
4873 src_decl.name.fmt(&mod.intern_pool), @intFromEnum(new_decl_index),
4874 });
4875 try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, tv, name);
4876 return new_decl_index;
4877}
4878
4879pub fn initNewAnonDecl(4780pub fn initNewAnonDecl(
4880 mod: *Module,4781 mod: *Module,
4881 new_decl_index: Decl.Index,4782 new_decl_index: Decl.Index,
4882 src_line: u32,4783 src_line: u32,
4883 typed_value: TypedValue,4784 val: Value,
4884 name: InternPool.NullTerminatedString,4785 name: InternPool.NullTerminatedString,
4885) Allocator.Error!void {4786) Allocator.Error!void {
4886 assert(typed_value.ty.toIntern() == mod.intern_pool.typeOf(typed_value.val.toIntern()));
4887
4888 const new_decl = mod.declPtr(new_decl_index);4787 const new_decl = mod.declPtr(new_decl_index);
48894788
4890 new_decl.name = name;4789 new_decl.name = name;
4891 new_decl.src_line = src_line;4790 new_decl.src_line = src_line;
4892 new_decl.ty = typed_value.ty;4791 new_decl.val = val;
4893 new_decl.val = typed_value.val;
4894 new_decl.alignment = .none;4792 new_decl.alignment = .none;
4895 new_decl.@"linksection" = .none;4793 new_decl.@"linksection" = .none;
4896 new_decl.has_tv = true;4794 new_decl.has_tv = true;
...@@ -5419,9 +5317,9 @@ pub fn populateTestFunctions(...@@ -5419,9 +5317,9 @@ pub fn populateTestFunctions(
5419 try mod.ensureDeclAnalyzed(decl_index);5317 try mod.ensureDeclAnalyzed(decl_index);
5420 }5318 }
5421 const decl = mod.declPtr(decl_index);5319 const decl = mod.declPtr(decl_index);
5422 const test_fn_ty = decl.ty.slicePtrFieldType(mod).childType(mod);5320 const test_fn_ty = decl.typeOf(mod).slicePtrFieldType(mod).childType(mod);
54235321
5424 const array_decl_index = d: {5322 const array_anon_decl: InternPool.Key.Ptr.Addr.AnonDecl = array: {
5425 // Add mod.test_functions to an array decl then make the test_functions5323 // Add mod.test_functions to an array decl then make the test_functions
5426 // decl reference it as a slice.5324 // decl reference it as a slice.
5427 const test_fn_vals = try gpa.alloc(InternPool.Index, mod.test_functions.count());5325 const test_fn_vals = try gpa.alloc(InternPool.Index, mod.test_functions.count());
...@@ -5431,21 +5329,20 @@ pub fn populateTestFunctions(...@@ -5431,21 +5329,20 @@ pub fn populateTestFunctions(
5431 const test_decl = mod.declPtr(test_decl_index);5329 const test_decl = mod.declPtr(test_decl_index);
5432 const test_decl_name = try gpa.dupe(u8, ip.stringToSlice(try test_decl.fullyQualifiedName(mod)));5330 const test_decl_name = try gpa.dupe(u8, ip.stringToSlice(try test_decl.fullyQualifiedName(mod)));
5433 defer gpa.free(test_decl_name);5331 defer gpa.free(test_decl_name);
5434 const test_name_decl_index = n: {5332 const test_name_anon_decl: InternPool.Key.Ptr.Addr.AnonDecl = n: {
5435 const test_name_decl_ty = try mod.arrayType(.{5333 const test_name_ty = try mod.arrayType(.{
5436 .len = test_decl_name.len,5334 .len = test_decl_name.len,
5437 .child = .u8_type,5335 .child = .u8_type,
5438 });5336 });
5439 const test_name_decl_index = try mod.createAnonymousDeclFromDecl(decl, decl.src_namespace, .{5337 const test_name_val = try mod.intern(.{ .aggregate = .{
5440 .ty = test_name_decl_ty,5338 .ty = test_name_ty.toIntern(),
5441 .val = Value.fromInterned((try mod.intern(.{ .aggregate = .{5339 .storage = .{ .bytes = test_decl_name },
5442 .ty = test_name_decl_ty.toIntern(),5340 } });
5443 .storage = .{ .bytes = test_decl_name },5341 break :n .{
5444 } }))),5342 .orig_ty = (try mod.singleConstPtrType(test_name_ty)).toIntern(),
5445 });5343 .val = test_name_val,
5446 break :n test_name_decl_index;5344 };
5447 };5345 };
5448 try mod.linkerUpdateDecl(test_name_decl_index);
54495346
5450 const test_fn_fields = .{5347 const test_fn_fields = .{
5451 // name5348 // name
...@@ -5453,7 +5350,7 @@ pub fn populateTestFunctions(...@@ -5453,7 +5350,7 @@ pub fn populateTestFunctions(
5453 .ty = .slice_const_u8_type,5350 .ty = .slice_const_u8_type,
5454 .ptr = try mod.intern(.{ .ptr = .{5351 .ptr = try mod.intern(.{ .ptr = .{
5455 .ty = .manyptr_const_u8_type,5352 .ty = .manyptr_const_u8_type,
5456 .addr = .{ .decl = test_name_decl_index },5353 .addr = .{ .anon_decl = test_name_anon_decl },
5457 } }),5354 } }),
5458 .len = try mod.intern(.{ .int = .{5355 .len = try mod.intern(.{ .int = .{
5459 .ty = .usize_type,5356 .ty = .usize_type,
...@@ -5463,7 +5360,7 @@ pub fn populateTestFunctions(...@@ -5463,7 +5360,7 @@ pub fn populateTestFunctions(
5463 // func5360 // func
5464 try mod.intern(.{ .ptr = .{5361 try mod.intern(.{ .ptr = .{
5465 .ty = try mod.intern(.{ .ptr_type = .{5362 .ty = try mod.intern(.{ .ptr_type = .{
5466 .child = test_decl.ty.toIntern(),5363 .child = test_decl.typeOf(mod).toIntern(),
5467 .flags = .{5364 .flags = .{
5468 .is_const = true,5365 .is_const = true,
5469 },5366 },
...@@ -5477,22 +5374,20 @@ pub fn populateTestFunctions(...@@ -5477,22 +5374,20 @@ pub fn populateTestFunctions(
5477 } });5374 } });
5478 }5375 }
54795376
5480 const array_decl_ty = try mod.arrayType(.{5377 const array_ty = try mod.arrayType(.{
5481 .len = test_fn_vals.len,5378 .len = test_fn_vals.len,
5482 .child = test_fn_ty.toIntern(),5379 .child = test_fn_ty.toIntern(),
5483 .sentinel = .none,5380 .sentinel = .none,
5484 });5381 });
5485 const array_decl_index = try mod.createAnonymousDeclFromDecl(decl, decl.src_namespace, .{5382 const array_val = try mod.intern(.{ .aggregate = .{
5486 .ty = array_decl_ty,5383 .ty = array_ty.toIntern(),
5487 .val = Value.fromInterned((try mod.intern(.{ .aggregate = .{5384 .storage = .{ .elems = test_fn_vals },
5488 .ty = array_decl_ty.toIntern(),5385 } });
5489 .storage = .{ .elems = test_fn_vals },5386 break :array .{
5490 } }))),5387 .orig_ty = (try mod.singleConstPtrType(array_ty)).toIntern(),
5491 });5388 .val = array_val,
54925389 };
5493 break :d array_decl_index;
5494 };5390 };
5495 try mod.linkerUpdateDecl(array_decl_index);
54965391
5497 {5392 {
5498 const new_ty = try mod.ptrType(.{5393 const new_ty = try mod.ptrType(.{
...@@ -5507,7 +5402,7 @@ pub fn populateTestFunctions(...@@ -5507,7 +5402,7 @@ pub fn populateTestFunctions(
5507 .ty = new_ty.toIntern(),5402 .ty = new_ty.toIntern(),
5508 .ptr = try mod.intern(.{ .ptr = .{5403 .ptr = try mod.intern(.{ .ptr = .{
5509 .ty = new_ty.slicePtrFieldType(mod).toIntern(),5404 .ty = new_ty.slicePtrFieldType(mod).toIntern(),
5510 .addr = .{ .decl = array_decl_index },5405 .addr = .{ .anon_decl = array_anon_decl },
5511 } }),5406 } }),
5512 .len = (try mod.intValue(Type.usize, mod.test_functions.count())).toIntern(),5407 .len = (try mod.intValue(Type.usize, mod.test_functions.count())).toIntern(),
5513 } });5408 } });
...@@ -5515,7 +5410,6 @@ pub fn populateTestFunctions(...@@ -5515,7 +5410,6 @@ pub fn populateTestFunctions(
55155410
5516 // Since we are replacing the Decl's value we must perform cleanup on the5411 // Since we are replacing the Decl's value we must perform cleanup on the
5517 // previous value.5412 // previous value.
5518 decl.ty = new_ty;
5519 decl.val = new_val;5413 decl.val = new_val;
5520 decl.has_tv = true;5414 decl.has_tv = true;
5521 }5415 }
...@@ -5590,53 +5484,6 @@ fn reportRetryableFileError(...@@ -5590,53 +5484,6 @@ fn reportRetryableFileError(
5590 gop.value_ptr.* = err_msg;5484 gop.value_ptr.* = err_msg;
5591}5485}
55925486
5593pub fn markReferencedDeclsAlive(mod: *Module, val: Value) Allocator.Error!void {
5594 switch (mod.intern_pool.indexToKey(val.toIntern())) {
5595 .variable => |variable| try mod.markDeclIndexAlive(variable.decl),
5596 .extern_func => |extern_func| try mod.markDeclIndexAlive(extern_func.decl),
5597 .func => |func| try mod.markDeclIndexAlive(func.owner_decl),
5598 .error_union => |error_union| switch (error_union.val) {
5599 .err_name => {},
5600 .payload => |payload| try mod.markReferencedDeclsAlive(Value.fromInterned(payload)),
5601 },
5602 .slice => |slice| {
5603 try mod.markReferencedDeclsAlive(Value.fromInterned(slice.ptr));
5604 try mod.markReferencedDeclsAlive(Value.fromInterned(slice.len));
5605 },
5606 .ptr => |ptr| switch (ptr.addr) {
5607 .decl => |decl| try mod.markDeclIndexAlive(decl),
5608 .anon_decl => {},
5609 .int, .comptime_field, .comptime_alloc => {},
5610 .eu_payload, .opt_payload => |parent| try mod.markReferencedDeclsAlive(Value.fromInterned(parent)),
5611 .elem, .field => |base_index| try mod.markReferencedDeclsAlive(Value.fromInterned(base_index.base)),
5612 },
5613 .opt => |opt| if (opt.val != .none) try mod.markReferencedDeclsAlive(Value.fromInterned(opt.val)),
5614 .aggregate => |aggregate| for (aggregate.storage.values()) |elem|
5615 try mod.markReferencedDeclsAlive(Value.fromInterned(elem)),
5616 .un => |un| {
5617 if (un.tag != .none) try mod.markReferencedDeclsAlive(Value.fromInterned(un.tag));
5618 try mod.markReferencedDeclsAlive(Value.fromInterned(un.val));
5619 },
5620 else => {},
5621 }
5622}
5623
5624pub fn markDeclAlive(mod: *Module, decl: *Decl) Allocator.Error!void {
5625 if (decl.alive) return;
5626 decl.alive = true;
5627
5628 _ = try decl.internValue(mod);
5629
5630 // This is the first time we are marking this Decl alive. We must
5631 // therefore recurse into its value and mark any Decl it references
5632 // as also alive, so that any Decl referenced does not get garbage collected.
5633 try mod.markReferencedDeclsAlive(decl.val);
5634}
5635
5636fn markDeclIndexAlive(mod: *Module, decl_index: Decl.Index) Allocator.Error!void {
5637 return mod.markDeclAlive(mod.declPtr(decl_index));
5638}
5639
5640pub fn addGlobalAssembly(mod: *Module, decl_index: Decl.Index, source: []const u8) !void {5487pub fn addGlobalAssembly(mod: *Module, decl_index: Decl.Index, source: []const u8) !void {
5641 const gop = try mod.global_assembly.getOrPut(mod.gpa, decl_index);5488 const gop = try mod.global_assembly.getOrPut(mod.gpa, decl_index);
5642 if (gop.found_existing) {5489 if (gop.found_existing) {
src/Sema.zig+559-754
...@@ -139,8 +139,7 @@ const MaybeComptimeAlloc = struct {...@@ -139,8 +139,7 @@ const MaybeComptimeAlloc = struct {
139};139};
140140
141const ComptimeAlloc = struct {141const ComptimeAlloc = struct {
142 ty: Type,142 val: MutableValue,
143 val: Value,
144 is_const: bool,143 is_const: bool,
145 /// `.none` indicates that the alignment is the natural alignment of `val`.144 /// `.none` indicates that the alignment is the natural alignment of `val`.
146 alignment: Alignment,145 alignment: Alignment,
...@@ -153,8 +152,7 @@ const ComptimeAlloc = struct {...@@ -153,8 +152,7 @@ const ComptimeAlloc = struct {
153fn newComptimeAlloc(sema: *Sema, block: *Block, ty: Type, alignment: Alignment) !ComptimeAllocIndex {152fn newComptimeAlloc(sema: *Sema, block: *Block, ty: Type, alignment: Alignment) !ComptimeAllocIndex {
154 const idx = sema.comptime_allocs.items.len;153 const idx = sema.comptime_allocs.items.len;
155 try sema.comptime_allocs.append(sema.gpa, .{154 try sema.comptime_allocs.append(sema.gpa, .{
156 .ty = ty,155 .val = .{ .interned = try sema.mod.intern(.{ .undef = ty.toIntern() }) },
157 .val = Value.fromInterned(try sema.mod.intern(.{ .undef = ty.toIntern() })),
158 .is_const = false,156 .is_const = false,
159 .alignment = alignment,157 .alignment = alignment,
160 .runtime_index = block.runtime_index,158 .runtime_index = block.runtime_index,
...@@ -175,8 +173,8 @@ const log = std.log.scoped(.sema);...@@ -175,8 +173,8 @@ const log = std.log.scoped(.sema);
175173
176const Sema = @This();174const Sema = @This();
177const Value = @import("Value.zig");175const Value = @import("Value.zig");
176const MutableValue = @import("mutable_value.zig").MutableValue;
178const Type = @import("type.zig").Type;177const Type = @import("type.zig").Type;
179const TypedValue = @import("TypedValue.zig");
180const Air = @import("Air.zig");178const Air = @import("Air.zig");
181const Zir = std.zig.Zir;179const Zir = std.zig.Zir;
182const Module = @import("Module.zig");180const Module = @import("Module.zig");
...@@ -1709,7 +1707,7 @@ fn analyzeBodyInner(...@@ -1709,7 +1707,7 @@ fn analyzeBodyInner(
1709 .needed_comptime_reason = "condition in comptime branch must be comptime-known",1707 .needed_comptime_reason = "condition in comptime branch must be comptime-known",
1710 .block_comptime_reason = block.comptime_reason,1708 .block_comptime_reason = block.comptime_reason,
1711 });1709 });
1712 const inline_body = if (cond.val.toBool()) then_body else else_body;1710 const inline_body = if (cond.toBool()) then_body else else_body;
17131711
1714 try sema.maybeErrorUnwrapCondbr(block, inline_body, extra.data.condition, cond_src);1712 try sema.maybeErrorUnwrapCondbr(block, inline_body, extra.data.condition, cond_src);
17151713
...@@ -1729,7 +1727,7 @@ fn analyzeBodyInner(...@@ -1729,7 +1727,7 @@ fn analyzeBodyInner(
1729 .needed_comptime_reason = "condition in comptime branch must be comptime-known",1727 .needed_comptime_reason = "condition in comptime branch must be comptime-known",
1730 .block_comptime_reason = block.comptime_reason,1728 .block_comptime_reason = block.comptime_reason,
1731 });1729 });
1732 const inline_body = if (cond.val.toBool()) then_body else else_body;1730 const inline_body = if (cond.toBool()) then_body else else_body;
17331731
1734 try sema.maybeErrorUnwrapCondbr(block, inline_body, extra.data.condition, cond_src);1732 try sema.maybeErrorUnwrapCondbr(block, inline_body, extra.data.condition, cond_src);
1735 const old_runtime_index = block.runtime_index;1733 const old_runtime_index = block.runtime_index;
...@@ -1882,10 +1880,10 @@ pub fn toConstString(...@@ -1882,10 +1880,10 @@ pub fn toConstString(
1882 air_inst: Air.Inst.Ref,1880 air_inst: Air.Inst.Ref,
1883 reason: NeededComptimeReason,1881 reason: NeededComptimeReason,
1884) ![]u8 {1882) ![]u8 {
1885 const wanted_type = Type.slice_const_u8;1883 const coerced_inst = try sema.coerce(block, Type.slice_const_u8, air_inst, src);
1886 const coerced_inst = try sema.coerce(block, wanted_type, air_inst, src);1884 const slice_val = try sema.resolveConstDefinedValue(block, src, coerced_inst, reason);
1887 const val = try sema.resolveConstDefinedValue(block, src, coerced_inst, reason);1885 const arr_val = try sema.derefSliceAsArray(block, src, slice_val, reason);
1888 return val.toAllocatedBytes(wanted_type, sema.arena, sema.mod);1886 return arr_val.toAllocatedBytes(arr_val.typeOf(sema.mod), sema.arena, sema.mod);
1889}1887}
18901888
1891pub fn resolveConstStringIntern(1889pub fn resolveConstStringIntern(
...@@ -2180,13 +2178,9 @@ fn resolveInstConst(...@@ -2180,13 +2178,9 @@ fn resolveInstConst(
2180 src: LazySrcLoc,2178 src: LazySrcLoc,
2181 zir_ref: Zir.Inst.Ref,2179 zir_ref: Zir.Inst.Ref,
2182 reason: NeededComptimeReason,2180 reason: NeededComptimeReason,
2183) CompileError!TypedValue {2181) CompileError!Value {
2184 const air_ref = try sema.resolveInst(zir_ref);2182 const air_ref = try sema.resolveInst(zir_ref);
2185 const val = try sema.resolveConstDefinedValue(block, src, air_ref, reason);2183 return sema.resolveConstDefinedValue(block, src, air_ref, reason);
2186 return .{
2187 .ty = sema.typeOf(air_ref),
2188 .val = val,
2189 };
2190}2184}
21912185
2192/// Value Tag may be `undef` or `variable`.2186/// Value Tag may be `undef` or `variable`.
...@@ -2195,7 +2189,7 @@ pub fn resolveFinalDeclValue(...@@ -2195,7 +2189,7 @@ pub fn resolveFinalDeclValue(
2195 block: *Block,2189 block: *Block,
2196 src: LazySrcLoc,2190 src: LazySrcLoc,
2197 air_ref: Air.Inst.Ref,2191 air_ref: Air.Inst.Ref,
2198) CompileError!TypedValue {2192) CompileError!Value {
2199 const val = try sema.resolveValueAllowVariables(air_ref) orelse {2193 const val = try sema.resolveValueAllowVariables(air_ref) orelse {
2200 return sema.failWithNeededComptime(block, src, .{2194 return sema.failWithNeededComptime(block, src, .{
2201 .needed_comptime_reason = "global variable initializer must be comptime-known",2195 .needed_comptime_reason = "global variable initializer must be comptime-known",
...@@ -2205,10 +2199,7 @@ pub fn resolveFinalDeclValue(...@@ -2205,10 +2199,7 @@ pub fn resolveFinalDeclValue(
2205 if (val.canMutateComptimeVarState(sema.mod)) {2199 if (val.canMutateComptimeVarState(sema.mod)) {
2206 return sema.fail(block, src, "global variable contains reference to comptime var", .{});2200 return sema.fail(block, src, "global variable contains reference to comptime var", .{});
2207 }2201 }
2208 return .{2202 return val;
2209 .ty = sema.typeOf(air_ref),
2210 .val = val,
2211 };
2212}2203}
22132204
2214fn failWithNeededComptime(sema: *Sema, block: *Block, src: LazySrcLoc, reason: NeededComptimeReason) CompileError {2205fn failWithNeededComptime(sema: *Sema, block: *Block, src: LazySrcLoc, reason: NeededComptimeReason) CompileError {
...@@ -2281,7 +2272,7 @@ fn failWithIntegerOverflow(sema: *Sema, block: *Block, src: LazySrcLoc, int_ty:...@@ -2281,7 +2272,7 @@ fn failWithIntegerOverflow(sema: *Sema, block: *Block, src: LazySrcLoc, int_ty:
2281 if (int_ty.zigTypeTag(mod) == .Vector) {2272 if (int_ty.zigTypeTag(mod) == .Vector) {
2282 const msg = msg: {2273 const msg = msg: {
2283 const msg = try sema.errMsg(block, src, "overflow of vector type '{}' with value '{}'", .{2274 const msg = try sema.errMsg(block, src, "overflow of vector type '{}' with value '{}'", .{
2284 int_ty.fmt(sema.mod), val.fmtValue(int_ty, sema.mod),2275 int_ty.fmt(sema.mod), val.fmtValue(sema.mod),
2285 });2276 });
2286 errdefer msg.destroy(sema.gpa);2277 errdefer msg.destroy(sema.gpa);
2287 try sema.errNote(block, src, msg, "when computing vector element at index '{d}'", .{vector_index});2278 try sema.errNote(block, src, msg, "when computing vector element at index '{d}'", .{vector_index});
...@@ -2290,7 +2281,7 @@ fn failWithIntegerOverflow(sema: *Sema, block: *Block, src: LazySrcLoc, int_ty:...@@ -2290,7 +2281,7 @@ fn failWithIntegerOverflow(sema: *Sema, block: *Block, src: LazySrcLoc, int_ty:
2290 return sema.failWithOwnedErrorMsg(block, msg);2281 return sema.failWithOwnedErrorMsg(block, msg);
2291 }2282 }
2292 return sema.fail(block, src, "overflow of integer type '{}' with value '{}'", .{2283 return sema.fail(block, src, "overflow of integer type '{}' with value '{}'", .{
2293 int_ty.fmt(sema.mod), val.fmtValue(int_ty, sema.mod),2284 int_ty.fmt(sema.mod), val.fmtValue(sema.mod),
2294 });2285 });
2295}2286}
22962287
...@@ -2826,10 +2817,14 @@ fn zirStructDecl(...@@ -2826,10 +2817,14 @@ fn zirStructDecl(
2826 });2817 });
2827 errdefer wip_ty.cancel(ip);2818 errdefer wip_ty.cancel(ip);
28282819
2829 const new_decl_index = try sema.createAnonymousDeclTypeNamed(block, src, .{2820 const new_decl_index = try sema.createAnonymousDeclTypeNamed(
2830 .ty = Type.type,2821 block,
2831 .val = Value.fromInterned(wip_ty.index),2822 src,
2832 }, small.name_strategy, "struct", inst);2823 Value.fromInterned(wip_ty.index),
2824 small.name_strategy,
2825 "struct",
2826 inst,
2827 );
2833 mod.declPtr(new_decl_index).owns_tv = true;2828 mod.declPtr(new_decl_index).owns_tv = true;
2834 errdefer mod.abortAnonDecl(new_decl_index);2829 errdefer mod.abortAnonDecl(new_decl_index);
28352830
...@@ -2862,7 +2857,7 @@ fn createAnonymousDeclTypeNamed(...@@ -2862,7 +2857,7 @@ fn createAnonymousDeclTypeNamed(
2862 sema: *Sema,2857 sema: *Sema,
2863 block: *Block,2858 block: *Block,
2864 src: LazySrcLoc,2859 src: LazySrcLoc,
2865 typed_value: TypedValue,2860 val: Value,
2866 name_strategy: Zir.Inst.NameStrategy,2861 name_strategy: Zir.Inst.NameStrategy,
2867 anon_prefix: []const u8,2862 anon_prefix: []const u8,
2868 inst: ?Zir.Inst.Index,2863 inst: ?Zir.Inst.Index,
...@@ -2888,12 +2883,12 @@ fn createAnonymousDeclTypeNamed(...@@ -2888,12 +2883,12 @@ fn createAnonymousDeclTypeNamed(
2888 const name = mod.intern_pool.getOrPutStringFmt(gpa, "{}__{s}_{d}", .{2883 const name = mod.intern_pool.getOrPutStringFmt(gpa, "{}__{s}_{d}", .{
2889 src_decl.name.fmt(&mod.intern_pool), anon_prefix, @intFromEnum(new_decl_index),2884 src_decl.name.fmt(&mod.intern_pool), anon_prefix, @intFromEnum(new_decl_index),
2890 }) catch unreachable;2885 }) catch unreachable;
2891 try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, typed_value, name);2886 try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, val, name);
2892 return new_decl_index;2887 return new_decl_index;
2893 },2888 },
2894 .parent => {2889 .parent => {
2895 const name = mod.declPtr(block.src_decl).name;2890 const name = mod.declPtr(block.src_decl).name;
2896 try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, typed_value, name);2891 try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, val, name);
2897 return new_decl_index;2892 return new_decl_index;
2898 },2893 },
2899 .func => {2894 .func => {
...@@ -2916,10 +2911,10 @@ fn createAnonymousDeclTypeNamed(...@@ -2916,10 +2911,10 @@ fn createAnonymousDeclTypeNamed(
2916 // function and the name doesn't matter since it will later2911 // function and the name doesn't matter since it will later
2917 // result in a compile error.2912 // result in a compile error.
2918 const arg_val = sema.resolveConstValue(block, .unneeded, arg, undefined) catch2913 const arg_val = sema.resolveConstValue(block, .unneeded, arg, undefined) catch
2919 return sema.createAnonymousDeclTypeNamed(block, src, typed_value, .anon, anon_prefix, null);2914 return sema.createAnonymousDeclTypeNamed(block, src, val, .anon, anon_prefix, null);
29202915
2921 if (arg_i != 0) try writer.writeByte(',');2916 if (arg_i != 0) try writer.writeByte(',');
2922 try writer.print("{}", .{arg_val.fmtValue(sema.typeOf(arg), sema.mod)});2917 try writer.print("{}", .{arg_val.fmtValue(sema.mod)});
29232918
2924 arg_i += 1;2919 arg_i += 1;
2925 continue;2920 continue;
...@@ -2929,7 +2924,7 @@ fn createAnonymousDeclTypeNamed(...@@ -2929,7 +2924,7 @@ fn createAnonymousDeclTypeNamed(
29292924
2930 try writer.writeByte(')');2925 try writer.writeByte(')');
2931 const name = try mod.intern_pool.getOrPutString(gpa, buf.items);2926 const name = try mod.intern_pool.getOrPutString(gpa, buf.items);
2932 try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, typed_value, name);2927 try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, val, name);
2933 return new_decl_index;2928 return new_decl_index;
2934 },2929 },
2935 .dbg_var => {2930 .dbg_var => {
...@@ -2944,12 +2939,12 @@ fn createAnonymousDeclTypeNamed(...@@ -2944,12 +2939,12 @@ fn createAnonymousDeclTypeNamed(
2944 src_decl.name.fmt(&mod.intern_pool), zir_data[i].str_op.getStr(sema.code),2939 src_decl.name.fmt(&mod.intern_pool), zir_data[i].str_op.getStr(sema.code),
2945 });2940 });
29462941
2947 try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, typed_value, name);2942 try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, val, name);
2948 return new_decl_index;2943 return new_decl_index;
2949 },2944 },
2950 else => {},2945 else => {},
2951 };2946 };
2952 return sema.createAnonymousDeclTypeNamed(block, src, typed_value, .anon, anon_prefix, null);2947 return sema.createAnonymousDeclTypeNamed(block, src, val, .anon, anon_prefix, null);
2953 },2948 },
2954 }2949 }
2955}2950}
...@@ -3049,10 +3044,14 @@ fn zirEnumDecl(...@@ -3049,10 +3044,14 @@ fn zirEnumDecl(
30493044
3050 errdefer if (!done) wip_ty.cancel(ip);3045 errdefer if (!done) wip_ty.cancel(ip);
30513046
3052 const new_decl_index = try sema.createAnonymousDeclTypeNamed(block, src, .{3047 const new_decl_index = try sema.createAnonymousDeclTypeNamed(
3053 .ty = Type.type,3048 block,
3054 .val = Value.fromInterned(wip_ty.index),3049 src,
3055 }, small.name_strategy, "enum", inst);3050 Value.fromInterned(wip_ty.index),
3051 small.name_strategy,
3052 "enum",
3053 inst,
3054 );
3056 const new_decl = mod.declPtr(new_decl_index);3055 const new_decl = mod.declPtr(new_decl_index);
3057 new_decl.owns_tv = true;3056 new_decl.owns_tv = true;
3058 errdefer if (!done) mod.abortAnonDecl(new_decl_index);3057 errdefer if (!done) mod.abortAnonDecl(new_decl_index);
...@@ -3187,7 +3186,7 @@ fn zirEnumDecl(...@@ -3187,7 +3186,7 @@ fn zirEnumDecl(
3187 }).lazy;3186 }).lazy;
3188 const other_field_src = mod.fieldSrcLoc(new_decl_index, .{ .index = conflict.prev_field_idx }).lazy;3187 const other_field_src = mod.fieldSrcLoc(new_decl_index, .{ .index = conflict.prev_field_idx }).lazy;
3189 const msg = msg: {3188 const msg = msg: {
3190 const msg = try sema.errMsg(block, value_src, "enum tag value {} already taken", .{last_tag_val.?.fmtValue(int_tag_ty, sema.mod)});3189 const msg = try sema.errMsg(block, value_src, "enum tag value {} already taken", .{last_tag_val.?.fmtValue(sema.mod)});
3191 errdefer msg.destroy(gpa);3190 errdefer msg.destroy(gpa);
3192 try sema.errNote(block, other_field_src, msg, "other occurrence here", .{});3191 try sema.errNote(block, other_field_src, msg, "other occurrence here", .{});
3193 break :msg msg;3192 break :msg msg;
...@@ -3207,7 +3206,7 @@ fn zirEnumDecl(...@@ -3207,7 +3206,7 @@ fn zirEnumDecl(
3207 const field_src = mod.fieldSrcLoc(new_decl_index, .{ .index = field_i }).lazy;3206 const field_src = mod.fieldSrcLoc(new_decl_index, .{ .index = field_i }).lazy;
3208 const other_field_src = mod.fieldSrcLoc(new_decl_index, .{ .index = conflict.prev_field_idx }).lazy;3207 const other_field_src = mod.fieldSrcLoc(new_decl_index, .{ .index = conflict.prev_field_idx }).lazy;
3209 const msg = msg: {3208 const msg = msg: {
3210 const msg = try sema.errMsg(block, field_src, "enum tag value {} already taken", .{last_tag_val.?.fmtValue(int_tag_ty, sema.mod)});3209 const msg = try sema.errMsg(block, field_src, "enum tag value {} already taken", .{last_tag_val.?.fmtValue(sema.mod)});
3211 errdefer msg.destroy(gpa);3210 errdefer msg.destroy(gpa);
3212 try sema.errNote(block, other_field_src, msg, "other occurrence here", .{});3211 try sema.errNote(block, other_field_src, msg, "other occurrence here", .{});
3213 break :msg msg;3212 break :msg msg;
...@@ -3229,7 +3228,7 @@ fn zirEnumDecl(...@@ -3229,7 +3228,7 @@ fn zirEnumDecl(
3229 .range = if (has_tag_value) .value else .name,3228 .range = if (has_tag_value) .value else .name,
3230 }).lazy;3229 }).lazy;
3231 const msg = try sema.errMsg(block, value_src, "enumeration value '{}' too large for type '{}'", .{3230 const msg = try sema.errMsg(block, value_src, "enumeration value '{}' too large for type '{}'", .{
3232 last_tag_val.?.fmtValue(int_tag_ty, mod), int_tag_ty.fmt(mod),3231 last_tag_val.?.fmtValue(mod), int_tag_ty.fmt(mod),
3233 });3232 });
3234 return sema.failWithOwnedErrorMsg(block, msg);3233 return sema.failWithOwnedErrorMsg(block, msg);
3235 }3234 }
...@@ -3316,10 +3315,14 @@ fn zirUnionDecl(...@@ -3316,10 +3315,14 @@ fn zirUnionDecl(
3316 });3315 });
3317 errdefer wip_ty.cancel(ip);3316 errdefer wip_ty.cancel(ip);
33183317
3319 const new_decl_index = try sema.createAnonymousDeclTypeNamed(block, src, .{3318 const new_decl_index = try sema.createAnonymousDeclTypeNamed(
3320 .ty = Type.type,3319 block,
3321 .val = Value.fromInterned(wip_ty.index),3320 src,
3322 }, small.name_strategy, "union", inst);3321 Value.fromInterned(wip_ty.index),
3322 small.name_strategy,
3323 "union",
3324 inst,
3325 );
3323 mod.declPtr(new_decl_index).owns_tv = true;3326 mod.declPtr(new_decl_index).owns_tv = true;
3324 errdefer mod.abortAnonDecl(new_decl_index);3327 errdefer mod.abortAnonDecl(new_decl_index);
33253328
...@@ -3400,10 +3403,14 @@ fn zirOpaqueDecl(...@@ -3400,10 +3403,14 @@ fn zirOpaqueDecl(
3400 };3403 };
3401 errdefer wip_ty.cancel(ip);3404 errdefer wip_ty.cancel(ip);
34023405
3403 const new_decl_index = try sema.createAnonymousDeclTypeNamed(block, src, .{3406 const new_decl_index = try sema.createAnonymousDeclTypeNamed(
3404 .ty = Type.type,3407 block,
3405 .val = Value.fromInterned(wip_ty.index),3408 src,
3406 }, small.name_strategy, "opaque", inst);3409 Value.fromInterned(wip_ty.index),
3410 small.name_strategy,
3411 "opaque",
3412 inst,
3413 );
3407 mod.declPtr(new_decl_index).owns_tv = true;3414 mod.declPtr(new_decl_index).owns_tv = true;
3408 errdefer mod.abortAnonDecl(new_decl_index);3415 errdefer mod.abortAnonDecl(new_decl_index);
34093416
...@@ -3463,10 +3470,14 @@ fn zirErrorSetDecl(...@@ -3463,10 +3470,14 @@ fn zirErrorSetDecl(
34633470
3464 const error_set_ty = try mod.errorSetFromUnsortedNames(names.keys());3471 const error_set_ty = try mod.errorSetFromUnsortedNames(names.keys());
34653472
3466 const new_decl_index = try sema.createAnonymousDeclTypeNamed(block, src, .{3473 const new_decl_index = try sema.createAnonymousDeclTypeNamed(
3467 .ty = Type.type,3474 block,
3468 .val = error_set_ty.toValue(),3475 src,
3469 }, name_strategy, "error", inst);3476 error_set_ty.toValue(),
3477 name_strategy,
3478 "error",
3479 inst,
3480 );
3470 const new_decl = mod.declPtr(new_decl_index);3481 const new_decl = mod.declPtr(new_decl_index);
3471 new_decl.owns_tv = true;3482 new_decl.owns_tv = true;
3472 errdefer mod.abortAnonDecl(new_decl_index);3483 errdefer mod.abortAnonDecl(new_decl_index);
...@@ -3762,10 +3773,10 @@ fn zirMakePtrConst(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro...@@ -3762,10 +3773,10 @@ fn zirMakePtrConst(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro
3762 if (!sema.isComptimeMutablePtr(ptr_val)) break :already_ct;3773 if (!sema.isComptimeMutablePtr(ptr_val)) break :already_ct;
3763 const alloc_index = mod.intern_pool.indexToKey(ptr_val.toIntern()).ptr.addr.comptime_alloc;3774 const alloc_index = mod.intern_pool.indexToKey(ptr_val.toIntern()).ptr.addr.comptime_alloc;
3764 const ct_alloc = sema.getComptimeAlloc(alloc_index);3775 const ct_alloc = sema.getComptimeAlloc(alloc_index);
3765 const interned = try ct_alloc.val.intern(ct_alloc.ty, mod);3776 const interned = try ct_alloc.val.intern(mod, sema.arena);
3766 if (Value.fromInterned(interned).canMutateComptimeVarState(mod)) {3777 if (Value.fromInterned(interned).canMutateComptimeVarState(mod)) {
3767 // Preserve the comptime alloc, just make the pointer const.3778 // Preserve the comptime alloc, just make the pointer const.
3768 ct_alloc.val = Value.fromInterned(interned);3779 ct_alloc.val = .{ .interned = interned };
3769 ct_alloc.is_const = true;3780 ct_alloc.is_const = true;
3770 return sema.makePtrConst(block, alloc);3781 return sema.makePtrConst(block, alloc);
3771 } else {3782 } else {
...@@ -4030,7 +4041,7 @@ fn finishResolveComptimeKnownAllocPtr(...@@ -4030,7 +4041,7 @@ fn finishResolveComptimeKnownAllocPtr(
4030 const alloc_index = existing_comptime_alloc orelse a: {4041 const alloc_index = existing_comptime_alloc orelse a: {
4031 const idx = try sema.newComptimeAlloc(block, alloc_ty.childType(zcu), alloc_ty.ptrAlignment(zcu));4042 const idx = try sema.newComptimeAlloc(block, alloc_ty.childType(zcu), alloc_ty.ptrAlignment(zcu));
4032 const alloc = sema.getComptimeAlloc(idx);4043 const alloc = sema.getComptimeAlloc(idx);
4033 alloc.val = Value.fromInterned(result_val);4044 alloc.val = .{ .interned = result_val };
4034 break :a idx;4045 break :a idx;
4035 };4046 };
4036 sema.getComptimeAlloc(alloc_index).is_const = true;4047 sema.getComptimeAlloc(alloc_index).is_const = true;
...@@ -4193,7 +4204,7 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com...@@ -4193,7 +4204,7 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com
4193 .anon_decl => |a| a.val,4204 .anon_decl => |a| a.val,
4194 .comptime_alloc => |i| val: {4205 .comptime_alloc => |i| val: {
4195 const alloc = sema.getComptimeAlloc(i);4206 const alloc = sema.getComptimeAlloc(i);
4196 break :val try alloc.val.intern(alloc.ty, mod);4207 break :val try alloc.val.intern(mod, sema.arena);
4197 },4208 },
4198 else => unreachable,4209 else => unreachable,
4199 };4210 };
...@@ -4370,10 +4381,10 @@ fn zirForLen(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air....@@ -4370,10 +4381,10 @@ fn zirForLen(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
4370 .input_index = len_idx,4381 .input_index = len_idx,
4371 } };4382 } };
4372 try sema.errNote(block, a_src, msg, "length {} here", .{4383 try sema.errNote(block, a_src, msg, "length {} here", .{
4373 v.fmtValue(Type.usize, sema.mod),4384 v.fmtValue(sema.mod),
4374 });4385 });
4375 try sema.errNote(block, arg_src, msg, "length {} here", .{4386 try sema.errNote(block, arg_src, msg, "length {} here", .{
4376 arg_val.fmtValue(Type.usize, sema.mod),4387 arg_val.fmtValue(sema.mod),
4377 });4388 });
4378 break :msg msg;4389 break :msg msg;
4379 };4390 };
...@@ -5597,7 +5608,7 @@ fn storeToInferredAllocComptime(...@@ -5597,7 +5608,7 @@ fn storeToInferredAllocComptime(
5597 } });5608 } });
5598 } else {5609 } else {
5599 const alloc_index = try sema.newComptimeAlloc(block, operand_ty, iac.alignment);5610 const alloc_index = try sema.newComptimeAlloc(block, operand_ty, iac.alignment);
5600 sema.getComptimeAlloc(alloc_index).val = operand_val;5611 sema.getComptimeAlloc(alloc_index).val = .{ .interned = operand_val.toIntern() };
5601 iac.ptr = try zcu.intern(.{ .ptr = .{5612 iac.ptr = try zcu.intern(.{ .ptr = .{
5602 .ty = alloc_ty.toIntern(),5613 .ty = alloc_ty.toIntern(),
5603 .addr = .{ .comptime_alloc = alloc_index },5614 .addr = .{ .comptime_alloc = alloc_index },
...@@ -5783,7 +5794,7 @@ fn zirCompileLog(...@@ -5783,7 +5794,7 @@ fn zirCompileLog(
5783 const arg_ty = sema.typeOf(arg);5794 const arg_ty = sema.typeOf(arg);
5784 if (try sema.resolveValueResolveLazy(arg)) |val| {5795 if (try sema.resolveValueResolveLazy(arg)) |val| {
5785 try writer.print("@as({}, {})", .{5796 try writer.print("@as({}, {})", .{
5786 arg_ty.fmt(mod), val.fmtValue(arg_ty, mod),5797 arg_ty.fmt(mod), val.fmtValue(mod),
5787 });5798 });
5788 } else {5799 } else {
5789 try writer.print("@as({}, [runtime value])", .{arg_ty.fmt(mod)});5800 try writer.print("@as({}, [runtime value])", .{arg_ty.fmt(mod)});
...@@ -6395,7 +6406,7 @@ fn zirExportValue(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -6395,7 +6406,7 @@ fn zirExportValue(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
6395 const options = try sema.resolveExportOptions(block, options_src, extra.options);6406 const options = try sema.resolveExportOptions(block, options_src, extra.options);
6396 if (options.linkage == .internal)6407 if (options.linkage == .internal)
6397 return;6408 return;
6398 if (operand.val.getFunction(mod)) |function| {6409 if (operand.getFunction(mod)) |function| {
6399 const decl_index = function.owner_decl;6410 const decl_index = function.owner_decl;
6400 return sema.analyzeExport(block, src, options, decl_index);6411 return sema.analyzeExport(block, src, options, decl_index);
6401 }6412 }
...@@ -6405,7 +6416,7 @@ fn zirExportValue(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -6405,7 +6416,7 @@ fn zirExportValue(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
6405 .src = src,6416 .src = src,
6406 .owner_decl = sema.owner_decl_index,6417 .owner_decl = sema.owner_decl_index,
6407 .src_decl = block.src_decl,6418 .src_decl = block.src_decl,
6408 .exported = .{ .value = operand.val.toIntern() },6419 .exported = .{ .value = operand.toIntern() },
6409 .status = .in_progress,6420 .status = .in_progress,
6410 });6421 });
6411}6422}
...@@ -6425,16 +6436,17 @@ pub fn analyzeExport(...@@ -6425,16 +6436,17 @@ pub fn analyzeExport(
64256436
6426 try mod.ensureDeclAnalyzed(exported_decl_index);6437 try mod.ensureDeclAnalyzed(exported_decl_index);
6427 const exported_decl = mod.declPtr(exported_decl_index);6438 const exported_decl = mod.declPtr(exported_decl_index);
6439 const export_ty = exported_decl.typeOf(mod);
64286440
6429 if (!try sema.validateExternType(exported_decl.ty, .other)) {6441 if (!try sema.validateExternType(export_ty, .other)) {
6430 const msg = msg: {6442 const msg = msg: {
6431 const msg = try sema.errMsg(block, src, "unable to export type '{}'", .{exported_decl.ty.fmt(mod)});6443 const msg = try sema.errMsg(block, src, "unable to export type '{}'", .{export_ty.fmt(mod)});
6432 errdefer msg.destroy(gpa);6444 errdefer msg.destroy(gpa);
64336445
6434 const src_decl = mod.declPtr(block.src_decl);6446 const src_decl = mod.declPtr(block.src_decl);
6435 try sema.explainWhyTypeIsNotExtern(msg, src_decl.toSrcLoc(src, mod), exported_decl.ty, .other);6447 try sema.explainWhyTypeIsNotExtern(msg, src_decl.toSrcLoc(src, mod), export_ty, .other);
64366448
6437 try sema.addDeclaredHereNote(msg, exported_decl.ty);6449 try sema.addDeclaredHereNote(msg, export_ty);
6438 break :msg msg;6450 break :msg msg;
6439 };6451 };
6440 return sema.failWithOwnedErrorMsg(block, msg);6452 return sema.failWithOwnedErrorMsg(block, msg);
...@@ -6445,8 +6457,6 @@ pub fn analyzeExport(...@@ -6445,8 +6457,6 @@ pub fn analyzeExport(
6445 return sema.fail(block, src, "export target cannot be extern", .{});6457 return sema.fail(block, src, "export target cannot be extern", .{});
6446 }6458 }
64476459
6448 // This decl is alive no matter what, since it's being exported
6449 try mod.markDeclAlive(exported_decl);
6450 try sema.maybeQueueFuncBodyAnalysis(exported_decl_index);6460 try sema.maybeQueueFuncBodyAnalysis(exported_decl_index);
64516461
6452 try addExport(mod, .{6462 try addExport(mod, .{
...@@ -6503,7 +6513,7 @@ fn zirSetAlignStack(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Inst...@@ -6503,7 +6513,7 @@ fn zirSetAlignStack(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Inst
6503 }6513 }
65046514
6505 const fn_owner_decl = mod.funcOwnerDeclPtr(sema.func_index);6515 const fn_owner_decl = mod.funcOwnerDeclPtr(sema.func_index);
6506 switch (fn_owner_decl.ty.fnCallingConvention(mod)) {6516 switch (fn_owner_decl.typeOf(mod).fnCallingConvention(mod)) {
6507 .Naked => return sema.fail(block, src, "@setAlignStack in naked function", .{}),6517 .Naked => return sema.fail(block, src, "@setAlignStack in naked function", .{}),
6508 .Inline => return sema.fail(block, src, "@setAlignStack in inline function", .{}),6518 .Inline => return sema.fail(block, src, "@setAlignStack in inline function", .{}),
6509 else => if (block.inlining != null) {6519 else => if (block.inlining != null) {
...@@ -7692,7 +7702,7 @@ fn analyzeCall(...@@ -7692,7 +7702,7 @@ fn analyzeCall(
7692 // comptime memory is mutated.7702 // comptime memory is mutated.
7693 const memoized_arg_values = try sema.arena.alloc(InternPool.Index, func_ty_info.param_types.len);7703 const memoized_arg_values = try sema.arena.alloc(InternPool.Index, func_ty_info.param_types.len);
76947704
7695 const owner_info = mod.typeToFunc(fn_owner_decl.ty).?;7705 const owner_info = mod.typeToFunc(fn_owner_decl.typeOf(mod)).?;
7696 const new_param_types = try sema.arena.alloc(InternPool.Index, owner_info.param_types.len);7706 const new_param_types = try sema.arena.alloc(InternPool.Index, owner_info.param_types.len);
7697 var new_fn_info: InternPool.GetFuncTypeKey = .{7707 var new_fn_info: InternPool.GetFuncTypeKey = .{
7698 .param_types = new_param_types,7708 .param_types = new_param_types,
...@@ -7835,7 +7845,7 @@ fn analyzeCall(...@@ -7835,7 +7845,7 @@ fn analyzeCall(
78357845
7836 if (is_comptime_call) {7846 if (is_comptime_call) {
7837 const result_val = try sema.resolveConstValue(block, .unneeded, result, undefined);7847 const result_val = try sema.resolveConstValue(block, .unneeded, result, undefined);
7838 const result_interned = try result_val.intern2(sema.fn_ret_ty, mod);7848 const result_interned = result_val.toIntern();
78397849
7840 // Transform ad-hoc inferred error set types into concrete error sets.7850 // Transform ad-hoc inferred error set types into concrete error sets.
7841 const result_transformed = try sema.resolveAdHocInferredErrorSet(block, call_src, result_interned);7851 const result_transformed = try sema.resolveAdHocInferredErrorSet(block, call_src, result_interned);
...@@ -7856,8 +7866,7 @@ fn analyzeCall(...@@ -7856,8 +7866,7 @@ fn analyzeCall(
7856 }7866 }
78577867
7858 if (try sema.resolveValue(result)) |result_val| {7868 if (try sema.resolveValue(result)) |result_val| {
7859 const result_interned = try result_val.intern2(sema.fn_ret_ty, mod);7869 const result_transformed = try sema.resolveAdHocInferredErrorSet(block, call_src, result_val.toIntern());
7860 const result_transformed = try sema.resolveAdHocInferredErrorSet(block, call_src, result_interned);
7861 break :res2 Air.internedToRef(result_transformed);7870 break :res2 Air.internedToRef(result_transformed);
7862 }7871 }
78637872
...@@ -7960,9 +7969,9 @@ fn handleTailCall(sema: *Sema, block: *Block, call_src: LazySrcLoc, func_ty: Typ...@@ -7960,9 +7969,9 @@ fn handleTailCall(sema: *Sema, block: *Block, call_src: LazySrcLoc, func_ty: Typ
7960 });7969 });
7961 }7970 }
7962 const func_decl = mod.funcOwnerDeclPtr(sema.owner_func_index);7971 const func_decl = mod.funcOwnerDeclPtr(sema.owner_func_index);
7963 if (!func_ty.eql(func_decl.ty, mod)) {7972 if (!func_ty.eql(func_decl.typeOf(mod), mod)) {
7964 return sema.fail(block, call_src, "unable to perform tail call: type of function being called '{}' does not match type of calling function '{}'", .{7973 return sema.fail(block, call_src, "unable to perform tail call: type of function being called '{}' does not match type of calling function '{}'", .{
7965 func_ty.fmt(mod), func_decl.ty.fmt(mod),7974 func_ty.fmt(mod), func_decl.typeOf(mod).fmt(mod),
7966 });7975 });
7967 }7976 }
7968 _ = try block.addUnOp(.ret, result);7977 _ = try block.addUnOp(.ret, result);
...@@ -8042,7 +8051,7 @@ fn analyzeInlineCallArg(...@@ -8042,7 +8051,7 @@ fn analyzeInlineCallArg(
8042 // when the hash function is called.8051 // when the hash function is called.
8043 const resolved_arg_val = try ics.caller().resolveLazyValue(arg_val);8052 const resolved_arg_val = try ics.caller().resolveLazyValue(arg_val);
8044 should_memoize.* = should_memoize.* and !resolved_arg_val.canMutateComptimeVarState(mod);8053 should_memoize.* = should_memoize.* and !resolved_arg_val.canMutateComptimeVarState(mod);
8045 memoized_arg_values[arg_i.*] = try resolved_arg_val.intern(Type.fromInterned(param_ty), mod);8054 memoized_arg_values[arg_i.*] = resolved_arg_val.toIntern();
8046 } else {8055 } else {
8047 ics.callee().inst_map.putAssumeCapacityNoClobber(inst, casted_arg);8056 ics.callee().inst_map.putAssumeCapacityNoClobber(inst, casted_arg);
8048 }8057 }
...@@ -8081,7 +8090,7 @@ fn analyzeInlineCallArg(...@@ -8081,7 +8090,7 @@ fn analyzeInlineCallArg(
8081 // when the hash function is called.8090 // when the hash function is called.
8082 const resolved_arg_val = try ics.caller().resolveLazyValue(arg_val);8091 const resolved_arg_val = try ics.caller().resolveLazyValue(arg_val);
8083 should_memoize.* = should_memoize.* and !resolved_arg_val.canMutateComptimeVarState(mod);8092 should_memoize.* = should_memoize.* and !resolved_arg_val.canMutateComptimeVarState(mod);
8084 memoized_arg_values[arg_i.*] = try resolved_arg_val.intern(ics.caller().typeOf(uncasted_arg), mod);8093 memoized_arg_values[arg_i.*] = resolved_arg_val.toIntern();
8085 } else {8094 } else {
8086 if (zir_tags[@intFromEnum(inst)] == .param_anytype_comptime) {8095 if (zir_tags[@intFromEnum(inst)] == .param_anytype_comptime) {
8087 _ = try ics.caller().resolveConstValue(arg_block, arg_src, uncasted_arg, .{8096 _ = try ics.caller().resolveConstValue(arg_block, arg_src, uncasted_arg, .{
...@@ -8871,7 +8880,7 @@ fn zirEnumFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -8871,7 +8880,7 @@ fn zirEnumFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
8871 return Air.internedToRef((try mod.getCoerced(int_val, dest_ty)).toIntern());8880 return Air.internedToRef((try mod.getCoerced(int_val, dest_ty)).toIntern());
8872 }8881 }
8873 return sema.fail(block, src, "int value '{}' out of range of non-exhaustive enum '{}'", .{8882 return sema.fail(block, src, "int value '{}' out of range of non-exhaustive enum '{}'", .{
8874 int_val.fmtValue(sema.typeOf(operand), mod), dest_ty.fmt(mod),8883 int_val.fmtValue(mod), dest_ty.fmt(mod),
8875 });8884 });
8876 }8885 }
8877 if (int_val.isUndef(mod)) {8886 if (int_val.isUndef(mod)) {
...@@ -8879,7 +8888,7 @@ fn zirEnumFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -8879,7 +8888,7 @@ fn zirEnumFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
8879 }8888 }
8880 if (!(try sema.enumHasInt(dest_ty, int_val))) {8889 if (!(try sema.enumHasInt(dest_ty, int_val))) {
8881 return sema.fail(block, src, "enum '{}' has no tag with value '{}'", .{8890 return sema.fail(block, src, "enum '{}' has no tag with value '{}'", .{
8882 dest_ty.fmt(mod), int_val.fmtValue(sema.typeOf(operand), mod),8891 dest_ty.fmt(mod), int_val.fmtValue(mod),
8883 });8892 });
8884 }8893 }
8885 return Air.internedToRef((try mod.getCoerced(int_val, dest_ty)).toIntern());8894 return Air.internedToRef((try mod.getCoerced(int_val, dest_ty)).toIntern());
...@@ -13925,7 +13934,7 @@ fn zirShl(...@@ -13925,7 +13934,7 @@ fn zirShl(
13925 const rhs_elem = try rhs_val.elemValue(mod, i);13934 const rhs_elem = try rhs_val.elemValue(mod, i);
13926 if (rhs_elem.compareHetero(.gte, bit_value, mod)) {13935 if (rhs_elem.compareHetero(.gte, bit_value, mod)) {
13927 return sema.fail(block, rhs_src, "shift amount '{}' at index '{d}' is too large for operand type '{}'", .{13936 return sema.fail(block, rhs_src, "shift amount '{}' at index '{d}' is too large for operand type '{}'", .{
13928 rhs_elem.fmtValue(scalar_ty, mod),13937 rhs_elem.fmtValue(mod),
13929 i,13938 i,
13930 scalar_ty.fmt(mod),13939 scalar_ty.fmt(mod),
13931 });13940 });
...@@ -13933,7 +13942,7 @@ fn zirShl(...@@ -13933,7 +13942,7 @@ fn zirShl(
13933 }13942 }
13934 } else if (rhs_val.compareHetero(.gte, bit_value, mod)) {13943 } else if (rhs_val.compareHetero(.gte, bit_value, mod)) {
13935 return sema.fail(block, rhs_src, "shift amount '{}' is too large for operand type '{}'", .{13944 return sema.fail(block, rhs_src, "shift amount '{}' is too large for operand type '{}'", .{
13936 rhs_val.fmtValue(scalar_ty, mod),13945 rhs_val.fmtValue(mod),
13937 scalar_ty.fmt(mod),13946 scalar_ty.fmt(mod),
13938 });13947 });
13939 }13948 }
...@@ -13944,14 +13953,14 @@ fn zirShl(...@@ -13944,14 +13953,14 @@ fn zirShl(
13944 const rhs_elem = try rhs_val.elemValue(mod, i);13953 const rhs_elem = try rhs_val.elemValue(mod, i);
13945 if (rhs_elem.compareHetero(.lt, try mod.intValue(scalar_rhs_ty, 0), mod)) {13954 if (rhs_elem.compareHetero(.lt, try mod.intValue(scalar_rhs_ty, 0), mod)) {
13946 return sema.fail(block, rhs_src, "shift by negative amount '{}' at index '{d}'", .{13955 return sema.fail(block, rhs_src, "shift by negative amount '{}' at index '{d}'", .{
13947 rhs_elem.fmtValue(scalar_ty, mod),13956 rhs_elem.fmtValue(mod),
13948 i,13957 i,
13949 });13958 });
13950 }13959 }
13951 }13960 }
13952 } else if (rhs_val.compareHetero(.lt, try mod.intValue(rhs_ty, 0), mod)) {13961 } else if (rhs_val.compareHetero(.lt, try mod.intValue(rhs_ty, 0), mod)) {
13953 return sema.fail(block, rhs_src, "shift by negative amount '{}'", .{13962 return sema.fail(block, rhs_src, "shift by negative amount '{}'", .{
13954 rhs_val.fmtValue(scalar_ty, mod),13963 rhs_val.fmtValue(mod),
13955 });13964 });
13956 }13965 }
13957 }13966 }
...@@ -14090,7 +14099,7 @@ fn zirShr(...@@ -14090,7 +14099,7 @@ fn zirShr(
14090 const rhs_elem = try rhs_val.elemValue(mod, i);14099 const rhs_elem = try rhs_val.elemValue(mod, i);
14091 if (rhs_elem.compareHetero(.gte, bit_value, mod)) {14100 if (rhs_elem.compareHetero(.gte, bit_value, mod)) {
14092 return sema.fail(block, rhs_src, "shift amount '{}' at index '{d}' is too large for operand type '{}'", .{14101 return sema.fail(block, rhs_src, "shift amount '{}' at index '{d}' is too large for operand type '{}'", .{
14093 rhs_elem.fmtValue(scalar_ty, mod),14102 rhs_elem.fmtValue(mod),
14094 i,14103 i,
14095 scalar_ty.fmt(mod),14104 scalar_ty.fmt(mod),
14096 });14105 });
...@@ -14098,7 +14107,7 @@ fn zirShr(...@@ -14098,7 +14107,7 @@ fn zirShr(
14098 }14107 }
14099 } else if (rhs_val.compareHetero(.gte, bit_value, mod)) {14108 } else if (rhs_val.compareHetero(.gte, bit_value, mod)) {
14100 return sema.fail(block, rhs_src, "shift amount '{}' is too large for operand type '{}'", .{14109 return sema.fail(block, rhs_src, "shift amount '{}' is too large for operand type '{}'", .{
14101 rhs_val.fmtValue(scalar_ty, mod),14110 rhs_val.fmtValue(mod),
14102 scalar_ty.fmt(mod),14111 scalar_ty.fmt(mod),
14103 });14112 });
14104 }14113 }
...@@ -14109,14 +14118,14 @@ fn zirShr(...@@ -14109,14 +14118,14 @@ fn zirShr(
14109 const rhs_elem = try rhs_val.elemValue(mod, i);14118 const rhs_elem = try rhs_val.elemValue(mod, i);
14110 if (rhs_elem.compareHetero(.lt, try mod.intValue(rhs_ty.childType(mod), 0), mod)) {14119 if (rhs_elem.compareHetero(.lt, try mod.intValue(rhs_ty.childType(mod), 0), mod)) {
14111 return sema.fail(block, rhs_src, "shift by negative amount '{}' at index '{d}'", .{14120 return sema.fail(block, rhs_src, "shift by negative amount '{}' at index '{d}'", .{
14112 rhs_elem.fmtValue(scalar_ty, mod),14121 rhs_elem.fmtValue(mod),
14113 i,14122 i,
14114 });14123 });
14115 }14124 }
14116 }14125 }
14117 } else if (rhs_val.compareHetero(.lt, try mod.intValue(rhs_ty, 0), mod)) {14126 } else if (rhs_val.compareHetero(.lt, try mod.intValue(rhs_ty, 0), mod)) {
14118 return sema.fail(block, rhs_src, "shift by negative amount '{}'", .{14127 return sema.fail(block, rhs_src, "shift by negative amount '{}'", .{
14119 rhs_val.fmtValue(scalar_ty, mod),14128 rhs_val.fmtValue(mod),
14120 });14129 });
14121 }14130 }
14122 if (maybe_lhs_val) |lhs_val| {14131 if (maybe_lhs_val) |lhs_val| {
...@@ -14270,7 +14279,7 @@ fn zirBitNot(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air....@@ -14270,7 +14279,7 @@ fn zirBitNot(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
14270 const elems = try sema.arena.alloc(InternPool.Index, vec_len);14279 const elems = try sema.arena.alloc(InternPool.Index, vec_len);
14271 for (elems, 0..) |*elem, i| {14280 for (elems, 0..) |*elem, i| {
14272 const elem_val = try val.elemValue(mod, i);14281 const elem_val = try val.elemValue(mod, i);
14273 elem.* = try (try elem_val.bitwiseNot(scalar_type, sema.arena, mod)).intern(scalar_type, mod);14282 elem.* = (try elem_val.bitwiseNot(scalar_type, sema.arena, mod)).toIntern();
14274 }14283 }
14275 return Air.internedToRef((try mod.intern(.{ .aggregate = .{14284 return Air.internedToRef((try mod.intern(.{ .aggregate = .{
14276 .ty = operand_type.toIntern(),14285 .ty = operand_type.toIntern(),
...@@ -14499,12 +14508,16 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -14499,12 +14508,16 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
14499 else => unreachable,14508 else => unreachable,
14500 }) |rhs_val| {14509 }) |rhs_val| {
14501 const lhs_sub_val = if (lhs_ty.isSinglePointer(mod))14510 const lhs_sub_val = if (lhs_ty.isSinglePointer(mod))
14502 (try sema.pointerDeref(block, lhs_src, lhs_val, lhs_ty)).?14511 try sema.pointerDeref(block, lhs_src, lhs_val, lhs_ty) orelse break :rs lhs_src
14512 else if (lhs_ty.isSlice(mod))
14513 try sema.maybeDerefSliceAsArray(block, lhs_src, lhs_val) orelse break :rs lhs_src
14503 else14514 else
14504 lhs_val;14515 lhs_val;
1450514516
14506 const rhs_sub_val = if (rhs_ty.isSinglePointer(mod))14517 const rhs_sub_val = if (rhs_ty.isSinglePointer(mod))
14507 (try sema.pointerDeref(block, rhs_src, rhs_val, rhs_ty)).?14518 try sema.pointerDeref(block, rhs_src, rhs_val, rhs_ty) orelse break :rs rhs_src
14519 else if (rhs_ty.isSlice(mod))
14520 try sema.maybeDerefSliceAsArray(block, rhs_src, rhs_val) orelse break :rs rhs_src
14508 else14521 else
14509 rhs_val;14522 rhs_val;
1451014523
...@@ -14521,7 +14534,7 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -14521,7 +14534,7 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
14521 } };14534 } };
14522 const coerced_elem_val_inst = try sema.coerce(block, resolved_elem_ty, elem_val_inst, operand_src);14535 const coerced_elem_val_inst = try sema.coerce(block, resolved_elem_ty, elem_val_inst, operand_src);
14523 const coerced_elem_val = try sema.resolveConstValue(block, operand_src, coerced_elem_val_inst, undefined);14536 const coerced_elem_val = try sema.resolveConstValue(block, operand_src, coerced_elem_val_inst, undefined);
14524 element_vals[elem_i] = try coerced_elem_val.intern(resolved_elem_ty, mod);14537 element_vals[elem_i] = coerced_elem_val.toIntern();
14525 }14538 }
14526 while (elem_i < result_len) : (elem_i += 1) {14539 while (elem_i < result_len) : (elem_i += 1) {
14527 const rhs_elem_i = elem_i - lhs_len;14540 const rhs_elem_i = elem_i - lhs_len;
...@@ -14534,7 +14547,7 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -14534,7 +14547,7 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
14534 } };14547 } };
14535 const coerced_elem_val_inst = try sema.coerce(block, resolved_elem_ty, elem_val_inst, operand_src);14548 const coerced_elem_val_inst = try sema.coerce(block, resolved_elem_ty, elem_val_inst, operand_src);
14536 const coerced_elem_val = try sema.resolveConstValue(block, operand_src, coerced_elem_val_inst, undefined);14549 const coerced_elem_val = try sema.resolveConstValue(block, operand_src, coerced_elem_val_inst, undefined);
14537 element_vals[elem_i] = try coerced_elem_val.intern(resolved_elem_ty, mod);14550 element_vals[elem_i] = coerced_elem_val.toIntern();
14538 }14551 }
14539 return sema.addConstantMaybeRef(try mod.intern(.{ .aggregate = .{14552 return sema.addConstantMaybeRef(try mod.intern(.{ .aggregate = .{
14540 .ty = result_ty.toIntern(),14553 .ty = result_ty.toIntern(),
...@@ -14624,10 +14637,7 @@ fn getArrayCatInfo(sema: *Sema, block: *Block, src: LazySrcLoc, operand: Air.Ins...@@ -14624,10 +14637,7 @@ fn getArrayCatInfo(sema: *Sema, block: *Block, src: LazySrcLoc, operand: Air.Ins
14624 .Pointer => {14637 .Pointer => {
14625 const ptr_info = operand_ty.ptrInfo(mod);14638 const ptr_info = operand_ty.ptrInfo(mod);
14626 switch (ptr_info.flags.size) {14639 switch (ptr_info.flags.size) {
14627 // TODO: in the Many case here this should only work if the type14640 .Slice => {
14628 // has a sentinel, and this code should compute the length based
14629 // on the sentinel value.
14630 .Slice, .Many => {
14631 const val = try sema.resolveConstDefinedValue(block, src, operand, .{14641 const val = try sema.resolveConstDefinedValue(block, src, operand, .{
14632 .needed_comptime_reason = "slice value being concatenated must be comptime-known",14642 .needed_comptime_reason = "slice value being concatenated must be comptime-known",
14633 });14643 });
...@@ -14637,7 +14647,7 @@ fn getArrayCatInfo(sema: *Sema, block: *Block, src: LazySrcLoc, operand: Air.Ins...@@ -14637,7 +14647,7 @@ fn getArrayCatInfo(sema: *Sema, block: *Block, src: LazySrcLoc, operand: Air.Ins
14637 .none => null,14647 .none => null,
14638 else => Value.fromInterned(ptr_info.sentinel),14648 else => Value.fromInterned(ptr_info.sentinel),
14639 },14649 },
14640 .len = val.sliceLen(mod),14650 .len = try val.sliceLen(sema),
14641 };14651 };
14642 },14652 },
14643 .One => {14653 .One => {
...@@ -14645,7 +14655,7 @@ fn getArrayCatInfo(sema: *Sema, block: *Block, src: LazySrcLoc, operand: Air.Ins...@@ -14645,7 +14655,7 @@ fn getArrayCatInfo(sema: *Sema, block: *Block, src: LazySrcLoc, operand: Air.Ins
14645 return Type.fromInterned(ptr_info.child).arrayInfo(mod);14655 return Type.fromInterned(ptr_info.child).arrayInfo(mod);
14646 }14656 }
14647 },14657 },
14648 .C => {},14658 .C, .Many => {},
14649 }14659 }
14650 },14660 },
14651 .Struct => {14661 .Struct => {
...@@ -14831,9 +14841,11 @@ fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -14831,9 +14841,11 @@ fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
14831 const ptr_addrspace = if (lhs_ty.zigTypeTag(mod) == .Pointer) lhs_ty.ptrAddressSpace(mod) else null;14841 const ptr_addrspace = if (lhs_ty.zigTypeTag(mod) == .Pointer) lhs_ty.ptrAddressSpace(mod) else null;
14832 const lhs_len = try sema.usizeCast(block, lhs_src, lhs_info.len);14842 const lhs_len = try sema.usizeCast(block, lhs_src, lhs_info.len);
1483314843
14834 if (try sema.resolveDefinedValue(block, lhs_src, lhs)) |lhs_val| {14844 if (try sema.resolveDefinedValue(block, lhs_src, lhs)) |lhs_val| ct: {
14835 const lhs_sub_val = if (lhs_ty.isSinglePointer(mod))14845 const lhs_sub_val = if (lhs_ty.isSinglePointer(mod))
14836 (try sema.pointerDeref(block, lhs_src, lhs_val, lhs_ty)).?14846 try sema.pointerDeref(block, lhs_src, lhs_val, lhs_ty) orelse break :ct
14847 else if (lhs_ty.isSlice(mod))
14848 try sema.maybeDerefSliceAsArray(block, lhs_src, lhs_val) orelse break :ct
14837 else14849 else
14838 lhs_val;14850 lhs_val;
1483914851
...@@ -14841,7 +14853,7 @@ fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -14841,7 +14853,7 @@ fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
14841 // Optimization for the common pattern of a single element repeated N times, such14853 // Optimization for the common pattern of a single element repeated N times, such
14842 // as zero-filling a byte array.14854 // as zero-filling a byte array.
14843 if (lhs_len == 1 and lhs_info.sentinel == null) {14855 if (lhs_len == 1 and lhs_info.sentinel == null) {
14844 const elem_val = (try lhs_sub_val.maybeElemValueFull(sema, mod, 0)).?;14856 const elem_val = try lhs_sub_val.elemValue(mod, 0);
14845 break :v try mod.intern(.{ .aggregate = .{14857 break :v try mod.intern(.{ .aggregate = .{
14846 .ty = result_ty.toIntern(),14858 .ty = result_ty.toIntern(),
14847 .storage = .{ .repeated_elem = elem_val.toIntern() },14859 .storage = .{ .repeated_elem = elem_val.toIntern() },
...@@ -14853,7 +14865,7 @@ fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -14853,7 +14865,7 @@ fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
14853 while (elem_i < result_len) {14865 while (elem_i < result_len) {
14854 var lhs_i: usize = 0;14866 var lhs_i: usize = 0;
14855 while (lhs_i < lhs_len) : (lhs_i += 1) {14867 while (lhs_i < lhs_len) : (lhs_i += 1) {
14856 const elem_val = (try lhs_sub_val.maybeElemValueFull(sema, mod, lhs_i)).?;14868 const elem_val = try lhs_sub_val.elemValue(mod, lhs_i);
14857 element_vals[elem_i] = elem_val.toIntern();14869 element_vals[elem_i] = elem_val.toIntern();
14858 elem_i += 1;14870 elem_i += 1;
14859 }14871 }
...@@ -15034,7 +15046,7 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins...@@ -15034,7 +15046,7 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
15034 block,15046 block,
15035 src,15047 src,
15036 "ambiguous coercion of division operands '{}' and '{}'; non-zero remainder '{}'",15048 "ambiguous coercion of division operands '{}' and '{}'; non-zero remainder '{}'",
15037 .{ lhs_ty.fmt(mod), rhs_ty.fmt(mod), rem.fmtValue(resolved_type, mod) },15049 .{ lhs_ty.fmt(mod), rhs_ty.fmt(mod), rem.fmtValue(mod) },
15038 );15050 );
15039 }15051 }
15040 }15052 }
...@@ -15813,7 +15825,7 @@ fn intRem(...@@ -15813,7 +15825,7 @@ fn intRem(
15813 for (result_data, 0..) |*scalar, i| {15825 for (result_data, 0..) |*scalar, i| {
15814 const lhs_elem = try lhs.elemValue(mod, i);15826 const lhs_elem = try lhs.elemValue(mod, i);
15815 const rhs_elem = try rhs.elemValue(mod, i);15827 const rhs_elem = try rhs.elemValue(mod, i);
15816 scalar.* = try (try sema.intRemScalar(lhs_elem, rhs_elem, scalar_ty)).intern(scalar_ty, mod);15828 scalar.* = (try sema.intRemScalar(lhs_elem, rhs_elem, scalar_ty)).toIntern();
15817 }15829 }
15818 return Value.fromInterned((try mod.intern(.{ .aggregate = .{15830 return Value.fromInterned((try mod.intern(.{ .aggregate = .{
15819 .ty = ty.toIntern(),15831 .ty = ty.toIntern(),
...@@ -17753,7 +17765,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -17753,7 +17765,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
17753 const info = ty.intInfo(mod);17765 const info = ty.intInfo(mod);
17754 const field_values = .{17766 const field_values = .{
17755 // signedness: Signedness,17767 // signedness: Signedness,
17756 try (try mod.enumValueFieldIndex(signedness_ty, @intFromEnum(info.signedness))).intern(signedness_ty, mod),17768 (try mod.enumValueFieldIndex(signedness_ty, @intFromEnum(info.signedness))).toIntern(),
17757 // bits: u16,17769 // bits: u16,
17758 (try mod.intValue(Type.u16, info.bits)).toIntern(),17770 (try mod.intValue(Type.u16, info.bits)).toIntern(),
17759 };17771 };
...@@ -17823,7 +17835,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -17823,7 +17835,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1782317835
17824 const field_values = .{17836 const field_values = .{
17825 // size: Size,17837 // size: Size,
17826 try (try mod.enumValueFieldIndex(ptr_size_ty, @intFromEnum(info.flags.size))).intern(ptr_size_ty, mod),17838 (try mod.enumValueFieldIndex(ptr_size_ty, @intFromEnum(info.flags.size))).toIntern(),
17827 // is_const: bool,17839 // is_const: bool,
17828 Value.makeBool(info.flags.is_const).toIntern(),17840 Value.makeBool(info.flags.is_const).toIntern(),
17829 // is_volatile: bool,17841 // is_volatile: bool,
...@@ -17831,7 +17843,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -17831,7 +17843,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
17831 // alignment: comptime_int,17843 // alignment: comptime_int,
17832 alignment.toIntern(),17844 alignment.toIntern(),
17833 // address_space: AddressSpace17845 // address_space: AddressSpace
17834 try (try mod.enumValueFieldIndex(addrspace_ty, @intFromEnum(info.flags.address_space))).intern(addrspace_ty, mod),17846 (try mod.enumValueFieldIndex(addrspace_ty, @intFromEnum(info.flags.address_space))).toIntern(),
17835 // child: type,17847 // child: type,
17836 info.child,17848 info.child,
17837 // is_allowzero: bool,17849 // is_allowzero: bool,
...@@ -19975,8 +19987,8 @@ fn unionInit(...@@ -19975,8 +19987,8 @@ fn unionInit(
19975 const tag_val = try mod.enumValueFieldIndex(tag_ty, field_index);19987 const tag_val = try mod.enumValueFieldIndex(tag_ty, field_index);
19976 return Air.internedToRef((try mod.intern(.{ .un = .{19988 return Air.internedToRef((try mod.intern(.{ .un = .{
19977 .ty = union_ty.toIntern(),19989 .ty = union_ty.toIntern(),
19978 .tag = try tag_val.intern(tag_ty, mod),19990 .tag = tag_val.toIntern(),
19979 .val = try init_val.intern(field_ty, mod),19991 .val = init_val.toIntern(),
19980 } })));19992 } })));
19981 }19993 }
1998219994
...@@ -20099,8 +20111,8 @@ fn zirStructInit(...@@ -20099,8 +20111,8 @@ fn zirStructInit(
20099 if (try sema.resolveValue(init_inst)) |val| {20111 if (try sema.resolveValue(init_inst)) |val| {
20100 const struct_val = Value.fromInterned((try mod.intern(.{ .un = .{20112 const struct_val = Value.fromInterned((try mod.intern(.{ .un = .{
20101 .ty = resolved_ty.toIntern(),20113 .ty = resolved_ty.toIntern(),
20102 .tag = try tag_val.intern(tag_ty, mod),20114 .tag = tag_val.toIntern(),
20103 .val = try val.intern(field_ty, mod),20115 .val = val.toIntern(),
20104 } })));20116 } })));
20105 const final_val_inst = try sema.coerce(block, result_ty, Air.internedToRef(struct_val.toIntern()), src);20117 const final_val_inst = try sema.coerce(block, result_ty, Air.internedToRef(struct_val.toIntern()), src);
20106 const final_val = (try sema.resolveValue(final_val_inst)).?;20118 const final_val = (try sema.resolveValue(final_val_inst)).?;
...@@ -20400,7 +20412,7 @@ fn structInitAnon(...@@ -20400,7 +20412,7 @@ fn structInitAnon(
20400 return sema.failWithOwnedErrorMsg(block, msg);20412 return sema.failWithOwnedErrorMsg(block, msg);
20401 }20413 }
20402 if (try sema.resolveValue(init)) |init_val| {20414 if (try sema.resolveValue(init)) |init_val| {
20403 field_val.* = try init_val.intern(Type.fromInterned(field_ty.*), mod);20415 field_val.* = init_val.toIntern();
20404 } else {20416 } else {
20405 field_val.* = .none;20417 field_val.* = .none;
20406 runtime_index = @intCast(i_usize);20418 runtime_index = @intCast(i_usize);
...@@ -20577,13 +20589,9 @@ fn zirArrayInit(...@@ -20577,13 +20589,9 @@ fn zirArrayInit(
2057720589
20578 const runtime_index = opt_runtime_index orelse {20590 const runtime_index = opt_runtime_index orelse {
20579 const elem_vals = try sema.arena.alloc(InternPool.Index, resolved_args.len);20591 const elem_vals = try sema.arena.alloc(InternPool.Index, resolved_args.len);
20580 for (elem_vals, resolved_args, 0..) |*val, arg, i| {20592 for (elem_vals, resolved_args) |*val, arg| {
20581 const elem_ty = if (is_tuple)
20582 array_ty.structFieldType(i, mod)
20583 else
20584 array_ty.elemType2(mod);
20585 // We checked that all args are comptime above.20593 // We checked that all args are comptime above.
20586 val.* = try ((sema.resolveValue(arg) catch unreachable).?).intern(elem_ty, mod);20594 val.* = (sema.resolveValue(arg) catch unreachable).?.toIntern();
20587 }20595 }
20588 const arr_val = try mod.intern(.{ .aggregate = .{20596 const arr_val = try mod.intern(.{ .aggregate = .{
20589 .ty = array_ty.toIntern(),20597 .ty = array_ty.toIntern(),
...@@ -20998,7 +21006,7 @@ fn maybeConstantUnaryMath(...@@ -20998,7 +21006,7 @@ fn maybeConstantUnaryMath(
20998 const elems = try sema.arena.alloc(InternPool.Index, vec_len);21006 const elems = try sema.arena.alloc(InternPool.Index, vec_len);
20999 for (elems, 0..) |*elem, i| {21007 for (elems, 0..) |*elem, i| {
21000 const elem_val = try val.elemValue(sema.mod, i);21008 const elem_val = try val.elemValue(sema.mod, i);
21001 elem.* = try (try eval(elem_val, scalar_ty, sema.arena, sema.mod)).intern(scalar_ty, mod);21009 elem.* = (try eval(elem_val, scalar_ty, sema.arena, sema.mod)).toIntern();
21002 }21010 }
21003 return Air.internedToRef((try mod.intern(.{ .aggregate = .{21011 return Air.internedToRef((try mod.intern(.{ .aggregate = .{
21004 .ty = result_ty.toIntern(),21012 .ty = result_ty.toIntern(),
...@@ -21086,7 +21094,7 @@ fn zirTagName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -21086,7 +21094,7 @@ fn zirTagName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
21086 const enum_decl = mod.declPtr(enum_decl_index);21094 const enum_decl = mod.declPtr(enum_decl_index);
21087 const msg = msg: {21095 const msg = msg: {
21088 const msg = try sema.errMsg(block, src, "no field with value '{}' in enum '{}'", .{21096 const msg = try sema.errMsg(block, src, "no field with value '{}' in enum '{}'", .{
21089 val.fmtValue(enum_ty, sema.mod), enum_decl.name.fmt(ip),21097 val.fmtValue(sema.mod), enum_decl.name.fmt(ip),
21090 });21098 });
21091 errdefer msg.destroy(sema.gpa);21099 errdefer msg.destroy(sema.gpa);
21092 try mod.errNoteNonLazy(enum_decl.srcLoc(mod), msg, "declared here", .{});21100 try mod.errNoteNonLazy(enum_decl.srcLoc(mod), msg, "declared here", .{});
...@@ -21129,7 +21137,9 @@ fn zirReify(...@@ -21129,7 +21137,9 @@ fn zirReify(
21129 .needed_comptime_reason = "operand to @Type must be comptime-known",21137 .needed_comptime_reason = "operand to @Type must be comptime-known",
21130 });21138 });
21131 const union_val = ip.indexToKey(val.toIntern()).un;21139 const union_val = ip.indexToKey(val.toIntern()).un;
21132 if (try sema.anyUndef(Value.fromInterned(union_val.val))) return sema.failWithUseOfUndef(block, src);21140 if (try sema.anyUndef(block, operand_src, Value.fromInterned(union_val.val))) {
21141 return sema.failWithUseOfUndef(block, operand_src);
21142 }
21133 const tag_index = type_info_ty.unionTagFieldIndex(Value.fromInterned(union_val.tag), mod).?;21143 const tag_index = type_info_ty.unionTagFieldIndex(Value.fromInterned(union_val.tag), mod).?;
21134 switch (@as(std.builtin.TypeId, @enumFromInt(tag_index))) {21144 switch (@as(std.builtin.TypeId, @enumFromInt(tag_index))) {
21135 .Type => return .type_type,21145 .Type => return .type_type,
...@@ -21370,11 +21380,15 @@ fn zirReify(...@@ -21370,11 +21380,15 @@ fn zirReify(
21370 const payload_val = Value.fromInterned(union_val.val).optionalValue(mod) orelse21380 const payload_val = Value.fromInterned(union_val.val).optionalValue(mod) orelse
21371 return Air.internedToRef(Type.anyerror.toIntern());21381 return Air.internedToRef(Type.anyerror.toIntern());
2137221382
21373 const len = try sema.usizeCast(block, src, payload_val.sliceLen(mod));21383 const names_val = try sema.derefSliceAsArray(block, src, payload_val, .{
21384 .needed_comptime_reason = "error set contents must be comptime-known",
21385 });
21386
21387 const len = try sema.usizeCast(block, src, names_val.typeOf(mod).arrayLen(mod));
21374 var names: InferredErrorSet.NameMap = .{};21388 var names: InferredErrorSet.NameMap = .{};
21375 try names.ensureUnusedCapacity(sema.arena, len);21389 try names.ensureUnusedCapacity(sema.arena, len);
21376 for (0..len) |i| {21390 for (0..len) |i| {
21377 const elem_val = (try payload_val.maybeElemValueFull(sema, mod, i)).?;21391 const elem_val = try names_val.elemValue(mod, i);
21378 const elem_struct_type = ip.loadStructType(ip.typeOf(elem_val.toIntern()));21392 const elem_struct_type = ip.loadStructType(ip.typeOf(elem_val.toIntern()));
21379 const name_val = try elem_val.fieldValue(mod, elem_struct_type.nameIndex(21393 const name_val = try elem_val.fieldValue(mod, elem_struct_type.nameIndex(
21380 ip,21394 ip,
...@@ -21422,7 +21436,7 @@ fn zirReify(...@@ -21422,7 +21436,7 @@ fn zirReify(
21422 const layout = mod.toEnum(std.builtin.Type.ContainerLayout, layout_val);21436 const layout = mod.toEnum(std.builtin.Type.ContainerLayout, layout_val);
2142321437
21424 // Decls21438 // Decls
21425 if (decls_val.sliceLen(mod) > 0) {21439 if (try decls_val.sliceLen(sema) > 0) {
21426 return sema.fail(block, src, "reified structs must have no decls", .{});21440 return sema.fail(block, src, "reified structs must have no decls", .{});
21427 }21441 }
2142821442
...@@ -21430,7 +21444,11 @@ fn zirReify(...@@ -21430,7 +21444,11 @@ fn zirReify(
21430 return sema.fail(block, src, "non-packed struct does not support backing integer type", .{});21444 return sema.fail(block, src, "non-packed struct does not support backing integer type", .{});
21431 }21445 }
2143221446
21433 return try sema.reifyStruct(block, inst, src, layout, backing_integer_val, fields_val, name_strategy, is_tuple_val.toBool());21447 const fields_arr = try sema.derefSliceAsArray(block, operand_src, fields_val, .{
21448 .needed_comptime_reason = "struct fields must be comptime-known",
21449 });
21450
21451 return try sema.reifyStruct(block, inst, src, layout, backing_integer_val, fields_arr, name_strategy, is_tuple_val.toBool());
21434 },21452 },
21435 .Enum => {21453 .Enum => {
21436 const struct_type = ip.loadStructType(ip.typeOf(union_val.val));21454 const struct_type = ip.loadStructType(ip.typeOf(union_val.val));
...@@ -21451,11 +21469,15 @@ fn zirReify(...@@ -21451,11 +21469,15 @@ fn zirReify(
21451 try ip.getOrPutString(gpa, "is_exhaustive"),21469 try ip.getOrPutString(gpa, "is_exhaustive"),
21452 ).?);21470 ).?);
2145321471
21454 if (decls_val.sliceLen(mod) > 0) {21472 if (try decls_val.sliceLen(sema) > 0) {
21455 return sema.fail(block, src, "reified enums must have no decls", .{});21473 return sema.fail(block, src, "reified enums must have no decls", .{});
21456 }21474 }
2145721475
21458 return sema.reifyEnum(block, inst, src, tag_type_val.toType(), is_exhaustive_val.toBool(), fields_val, name_strategy);21476 const fields_arr = try sema.derefSliceAsArray(block, operand_src, fields_val, .{
21477 .needed_comptime_reason = "enum fields must be comptime-known",
21478 });
21479
21480 return sema.reifyEnum(block, inst, src, tag_type_val.toType(), is_exhaustive_val.toBool(), fields_arr, name_strategy);
21459 },21481 },
21460 .Opaque => {21482 .Opaque => {
21461 const struct_type = ip.loadStructType(ip.typeOf(union_val.val));21483 const struct_type = ip.loadStructType(ip.typeOf(union_val.val));
...@@ -21465,7 +21487,7 @@ fn zirReify(...@@ -21465,7 +21487,7 @@ fn zirReify(
21465 ).?);21487 ).?);
2146621488
21467 // Decls21489 // Decls
21468 if (decls_val.sliceLen(mod) > 0) {21490 if (try decls_val.sliceLen(sema) > 0) {
21469 return sema.fail(block, src, "reified opaque must have no decls", .{});21491 return sema.fail(block, src, "reified opaque must have no decls", .{});
21470 }21492 }
2147121493
...@@ -21480,10 +21502,14 @@ fn zirReify(...@@ -21480,10 +21502,14 @@ fn zirReify(
21480 };21502 };
21481 errdefer wip_ty.cancel(ip);21503 errdefer wip_ty.cancel(ip);
2148221504
21483 const new_decl_index = try sema.createAnonymousDeclTypeNamed(block, src, .{21505 const new_decl_index = try sema.createAnonymousDeclTypeNamed(
21484 .ty = Type.type,21506 block,
21485 .val = Value.fromInterned(wip_ty.index),21507 src,
21486 }, name_strategy, "opaque", inst);21508 Value.fromInterned(wip_ty.index),
21509 name_strategy,
21510 "opaque",
21511 inst,
21512 );
21487 mod.declPtr(new_decl_index).owns_tv = true;21513 mod.declPtr(new_decl_index).owns_tv = true;
21488 errdefer mod.abortAnonDecl(new_decl_index);21514 errdefer mod.abortAnonDecl(new_decl_index);
2148921515
...@@ -21510,12 +21536,16 @@ fn zirReify(...@@ -21510,12 +21536,16 @@ fn zirReify(
21510 try ip.getOrPutString(gpa, "decls"),21536 try ip.getOrPutString(gpa, "decls"),
21511 ).?);21537 ).?);
2151221538
21513 if (decls_val.sliceLen(mod) > 0) {21539 if (try decls_val.sliceLen(sema) > 0) {
21514 return sema.fail(block, src, "reified unions must have no decls", .{});21540 return sema.fail(block, src, "reified unions must have no decls", .{});
21515 }21541 }
21516 const layout = mod.toEnum(std.builtin.Type.ContainerLayout, layout_val);21542 const layout = mod.toEnum(std.builtin.Type.ContainerLayout, layout_val);
2151721543
21518 return sema.reifyUnion(block, inst, src, layout, tag_type_val, fields_val, name_strategy);21544 const fields_arr = try sema.derefSliceAsArray(block, operand_src, fields_val, .{
21545 .needed_comptime_reason = "union fields must be comptime-known",
21546 });
21547
21548 return sema.reifyUnion(block, inst, src, layout, tag_type_val, fields_arr, name_strategy);
21519 },21549 },
21520 .Fn => {21550 .Fn => {
21521 const struct_type = ip.loadStructType(ip.typeOf(union_val.val));21551 const struct_type = ip.loadStructType(ip.typeOf(union_val.val));
...@@ -21535,7 +21565,7 @@ fn zirReify(...@@ -21535,7 +21565,7 @@ fn zirReify(
21535 ip,21565 ip,
21536 try ip.getOrPutString(gpa, "return_type"),21566 try ip.getOrPutString(gpa, "return_type"),
21537 ).?);21567 ).?);
21538 const params_val = try Value.fromInterned(union_val.val).fieldValue(mod, struct_type.nameIndex(21568 const params_slice_val = try Value.fromInterned(union_val.val).fieldValue(mod, struct_type.nameIndex(
21539 ip,21569 ip,
21540 try ip.getOrPutString(gpa, "params"),21570 try ip.getOrPutString(gpa, "params"),
21541 ).?);21571 ).?);
...@@ -21554,12 +21584,16 @@ fn zirReify(...@@ -21554,12 +21584,16 @@ fn zirReify(
21554 const return_type = return_type_val.optionalValue(mod) orelse21584 const return_type = return_type_val.optionalValue(mod) orelse
21555 return sema.fail(block, src, "Type.Fn.return_type must be non-null for @Type", .{});21585 return sema.fail(block, src, "Type.Fn.return_type must be non-null for @Type", .{});
2155621586
21557 const args_len = try sema.usizeCast(block, src, params_val.sliceLen(mod));21587 const params_val = try sema.derefSliceAsArray(block, operand_src, params_slice_val, .{
21588 .needed_comptime_reason = "function parameters must be comptime-known",
21589 });
21590
21591 const args_len = try sema.usizeCast(block, src, params_val.typeOf(mod).arrayLen(mod));
21558 const param_types = try sema.arena.alloc(InternPool.Index, args_len);21592 const param_types = try sema.arena.alloc(InternPool.Index, args_len);
2155921593
21560 var noalias_bits: u32 = 0;21594 var noalias_bits: u32 = 0;
21561 for (param_types, 0..) |*param_type, i| {21595 for (param_types, 0..) |*param_type, i| {
21562 const elem_val = (try params_val.maybeElemValueFull(sema, mod, i)).?;21596 const elem_val = try params_val.elemValue(mod, i);
21563 const elem_struct_type = ip.loadStructType(ip.typeOf(elem_val.toIntern()));21597 const elem_struct_type = ip.loadStructType(ip.typeOf(elem_val.toIntern()));
21564 const param_is_generic_val = try elem_val.fieldValue(mod, elem_struct_type.nameIndex(21598 const param_is_generic_val = try elem_val.fieldValue(mod, elem_struct_type.nameIndex(
21565 ip,21599 ip,
...@@ -21620,7 +21654,7 @@ fn reifyEnum(...@@ -21620,7 +21654,7 @@ fn reifyEnum(
2162021654
21621 // This logic must stay in sync with the structure of `std.builtin.Type.Enum` - search for `fieldValue`.21655 // This logic must stay in sync with the structure of `std.builtin.Type.Enum` - search for `fieldValue`.
2162221656
21623 const fields_len: u32 = @intCast(fields_val.sliceLen(mod));21657 const fields_len: u32 = @intCast(fields_val.typeOf(mod).arrayLen(mod));
2162421658
21625 // The validation work here is non-trivial, and it's possible the type already exists.21659 // The validation work here is non-trivial, and it's possible the type already exists.
21626 // So in this first pass, let's just construct a hash to optimize for this case. If the21660 // So in this first pass, let's just construct a hash to optimize for this case. If the
...@@ -21634,7 +21668,7 @@ fn reifyEnum(...@@ -21634,7 +21668,7 @@ fn reifyEnum(
21634 std.hash.autoHash(&hasher, fields_len);21668 std.hash.autoHash(&hasher, fields_len);
2163521669
21636 for (0..fields_len) |field_idx| {21670 for (0..fields_len) |field_idx| {
21637 const field_info = (try fields_val.maybeElemValueFull(sema, mod, field_idx)).?;21671 const field_info = try fields_val.elemValue(mod, field_idx);
2163821672
21639 const field_name_val = try field_info.fieldValue(mod, 0);21673 const field_name_val = try field_info.fieldValue(mod, 0);
21640 const field_value_val = try sema.resolveLazyValue(try field_info.fieldValue(mod, 1));21674 const field_value_val = try sema.resolveLazyValue(try field_info.fieldValue(mod, 1));
...@@ -21668,10 +21702,14 @@ fn reifyEnum(...@@ -21668,10 +21702,14 @@ fn reifyEnum(
21668 return sema.fail(block, src, "Type.Enum.tag_type must be an integer type", .{});21702 return sema.fail(block, src, "Type.Enum.tag_type must be an integer type", .{});
21669 }21703 }
2167021704
21671 const new_decl_index = try sema.createAnonymousDeclTypeNamed(block, src, .{21705 const new_decl_index = try sema.createAnonymousDeclTypeNamed(
21672 .ty = Type.type,21706 block,
21673 .val = Value.fromInterned(wip_ty.index),21707 src,
21674 }, name_strategy, "enum", inst);21708 Value.fromInterned(wip_ty.index),
21709 name_strategy,
21710 "enum",
21711 inst,
21712 );
21675 mod.declPtr(new_decl_index).owns_tv = true;21713 mod.declPtr(new_decl_index).owns_tv = true;
21676 errdefer mod.abortAnonDecl(new_decl_index);21714 errdefer mod.abortAnonDecl(new_decl_index);
2167721715
...@@ -21679,7 +21717,7 @@ fn reifyEnum(...@@ -21679,7 +21717,7 @@ fn reifyEnum(
21679 wip_ty.setTagTy(ip, tag_ty.toIntern());21717 wip_ty.setTagTy(ip, tag_ty.toIntern());
2168021718
21681 for (0..fields_len) |field_idx| {21719 for (0..fields_len) |field_idx| {
21682 const field_info = (try fields_val.maybeElemValueFull(sema, mod, field_idx)).?;21720 const field_info = try fields_val.elemValue(mod, field_idx);
2168321721
21684 const field_name_val = try field_info.fieldValue(mod, 0);21722 const field_name_val = try field_info.fieldValue(mod, 0);
21685 const field_value_val = try sema.resolveLazyValue(try field_info.fieldValue(mod, 1));21723 const field_value_val = try sema.resolveLazyValue(try field_info.fieldValue(mod, 1));
...@@ -21691,7 +21729,7 @@ fn reifyEnum(...@@ -21691,7 +21729,7 @@ fn reifyEnum(
21691 // TODO: better source location21729 // TODO: better source location
21692 return sema.fail(block, src, "field '{}' with enumeration value '{}' is too large for backing int type '{}'", .{21730 return sema.fail(block, src, "field '{}' with enumeration value '{}' is too large for backing int type '{}'", .{
21693 field_name.fmt(ip),21731 field_name.fmt(ip),
21694 field_value_val.fmtValue(Type.comptime_int, mod),21732 field_value_val.fmtValue(mod),
21695 tag_ty.fmt(mod),21733 tag_ty.fmt(mod),
21696 });21734 });
21697 }21735 }
...@@ -21707,7 +21745,7 @@ fn reifyEnum(...@@ -21707,7 +21745,7 @@ fn reifyEnum(
21707 break :msg msg;21745 break :msg msg;
21708 },21746 },
21709 .value => msg: {21747 .value => msg: {
21710 const msg = try sema.errMsg(block, src, "enum tag value {} already taken", .{field_value_val.fmtValue(Type.comptime_int, mod)});21748 const msg = try sema.errMsg(block, src, "enum tag value {} already taken", .{field_value_val.fmtValue(mod)});
21711 errdefer msg.destroy(gpa);21749 errdefer msg.destroy(gpa);
21712 _ = conflict.prev_field_idx; // TODO: this note is incorrect21750 _ = conflict.prev_field_idx; // TODO: this note is incorrect
21713 try sema.errNote(block, src, msg, "other enum tag value here", .{});21751 try sema.errNote(block, src, msg, "other enum tag value here", .{});
...@@ -21741,7 +21779,7 @@ fn reifyUnion(...@@ -21741,7 +21779,7 @@ fn reifyUnion(
2174121779
21742 // This logic must stay in sync with the structure of `std.builtin.Type.Union` - search for `fieldValue`.21780 // This logic must stay in sync with the structure of `std.builtin.Type.Union` - search for `fieldValue`.
2174321781
21744 const fields_len: u32 = @intCast(fields_val.sliceLen(mod));21782 const fields_len: u32 = @intCast(fields_val.typeOf(mod).arrayLen(mod));
2174521783
21746 // The validation work here is non-trivial, and it's possible the type already exists.21784 // The validation work here is non-trivial, and it's possible the type already exists.
21747 // So in this first pass, let's just construct a hash to optimize for this case. If the21785 // So in this first pass, let's just construct a hash to optimize for this case. If the
...@@ -21757,7 +21795,7 @@ fn reifyUnion(...@@ -21757,7 +21795,7 @@ fn reifyUnion(
21757 var any_aligns = false;21795 var any_aligns = false;
2175821796
21759 for (0..fields_len) |field_idx| {21797 for (0..fields_len) |field_idx| {
21760 const field_info = (try fields_val.maybeElemValueFull(sema, mod, field_idx)).?;21798 const field_info = try fields_val.elemValue(mod, field_idx);
2176121799
21762 const field_name_val = try field_info.fieldValue(mod, 0);21800 const field_name_val = try field_info.fieldValue(mod, 0);
21763 const field_type_val = try field_info.fieldValue(mod, 1);21801 const field_type_val = try field_info.fieldValue(mod, 1);
...@@ -21811,10 +21849,14 @@ fn reifyUnion(...@@ -21811,10 +21849,14 @@ fn reifyUnion(
21811 };21849 };
21812 errdefer wip_ty.cancel(ip);21850 errdefer wip_ty.cancel(ip);
2181321851
21814 const new_decl_index = try sema.createAnonymousDeclTypeNamed(block, src, .{21852 const new_decl_index = try sema.createAnonymousDeclTypeNamed(
21815 .ty = Type.type,21853 block,
21816 .val = Value.fromInterned(wip_ty.index),21854 src,
21817 }, name_strategy, "union", inst);21855 Value.fromInterned(wip_ty.index),
21856 name_strategy,
21857 "union",
21858 inst,
21859 );
21818 mod.declPtr(new_decl_index).owns_tv = true;21860 mod.declPtr(new_decl_index).owns_tv = true;
21819 errdefer mod.abortAnonDecl(new_decl_index);21861 errdefer mod.abortAnonDecl(new_decl_index);
2182021862
...@@ -21833,7 +21875,7 @@ fn reifyUnion(...@@ -21833,7 +21875,7 @@ fn reifyUnion(
21833 var seen_tags = try std.DynamicBitSetUnmanaged.initEmpty(sema.arena, tag_ty_fields_len);21875 var seen_tags = try std.DynamicBitSetUnmanaged.initEmpty(sema.arena, tag_ty_fields_len);
2183421876
21835 for (field_types, 0..) |*field_ty, field_idx| {21877 for (field_types, 0..) |*field_ty, field_idx| {
21836 const field_info = (try fields_val.maybeElemValueFull(sema, mod, field_idx)).?;21878 const field_info = try fields_val.elemValue(mod, field_idx);
2183721879
21838 const field_name_val = try field_info.fieldValue(mod, 0);21880 const field_name_val = try field_info.fieldValue(mod, 0);
21839 const field_type_val = try field_info.fieldValue(mod, 1);21881 const field_type_val = try field_info.fieldValue(mod, 1);
...@@ -21885,7 +21927,7 @@ fn reifyUnion(...@@ -21885,7 +21927,7 @@ fn reifyUnion(
21885 try field_names.ensureTotalCapacity(sema.arena, fields_len);21927 try field_names.ensureTotalCapacity(sema.arena, fields_len);
2188621928
21887 for (field_types, 0..) |*field_ty, field_idx| {21929 for (field_types, 0..) |*field_ty, field_idx| {
21888 const field_info = (try fields_val.maybeElemValueFull(sema, mod, field_idx)).?;21930 const field_info = try fields_val.elemValue(mod, field_idx);
2188921931
21890 const field_name_val = try field_info.fieldValue(mod, 0);21932 const field_name_val = try field_info.fieldValue(mod, 0);
21891 const field_type_val = try field_info.fieldValue(mod, 1);21933 const field_type_val = try field_info.fieldValue(mod, 1);
...@@ -21979,7 +22021,7 @@ fn reifyStruct(...@@ -21979,7 +22021,7 @@ fn reifyStruct(
2197922021
21980 // This logic must stay in sync with the structure of `std.builtin.Type.Struct` - search for `fieldValue`.22022 // This logic must stay in sync with the structure of `std.builtin.Type.Struct` - search for `fieldValue`.
2198122023
21982 const fields_len: u32 = @intCast(fields_val.sliceLen(mod));22024 const fields_len: u32 = @intCast(fields_val.typeOf(mod).arrayLen(mod));
2198322025
21984 // The validation work here is non-trivial, and it's possible the type already exists.22026 // The validation work here is non-trivial, and it's possible the type already exists.
21985 // So in this first pass, let's just construct a hash to optimize for this case. If the22027 // So in this first pass, let's just construct a hash to optimize for this case. If the
...@@ -21998,7 +22040,7 @@ fn reifyStruct(...@@ -21998,7 +22040,7 @@ fn reifyStruct(
21998 var any_aligned_fields = false;22040 var any_aligned_fields = false;
2199922041
22000 for (0..fields_len) |field_idx| {22042 for (0..fields_len) |field_idx| {
22001 const field_info = (try fields_val.maybeElemValueFull(sema, mod, field_idx)).?;22043 const field_info = try fields_val.elemValue(mod, field_idx);
2200222044
22003 const field_name_val = try field_info.fieldValue(mod, 0);22045 const field_name_val = try field_info.fieldValue(mod, 0);
22004 const field_type_val = try field_info.fieldValue(mod, 1);22046 const field_type_val = try field_info.fieldValue(mod, 1);
...@@ -22066,17 +22108,21 @@ fn reifyStruct(...@@ -22066,17 +22108,21 @@ fn reifyStruct(
22066 .auto => {},22108 .auto => {},
22067 };22109 };
2206822110
22069 const new_decl_index = try sema.createAnonymousDeclTypeNamed(block, src, .{22111 const new_decl_index = try sema.createAnonymousDeclTypeNamed(
22070 .ty = Type.type,22112 block,
22071 .val = Value.fromInterned(wip_ty.index),22113 src,
22072 }, name_strategy, "struct", inst);22114 Value.fromInterned(wip_ty.index),
22115 name_strategy,
22116 "struct",
22117 inst,
22118 );
22073 mod.declPtr(new_decl_index).owns_tv = true;22119 mod.declPtr(new_decl_index).owns_tv = true;
22074 errdefer mod.abortAnonDecl(new_decl_index);22120 errdefer mod.abortAnonDecl(new_decl_index);
2207522121
22076 const struct_type = ip.loadStructType(wip_ty.index);22122 const struct_type = ip.loadStructType(wip_ty.index);
2207722123
22078 for (0..fields_len) |field_idx| {22124 for (0..fields_len) |field_idx| {
22079 const field_info = (try fields_val.maybeElemValueFull(sema, mod, field_idx)).?;22125 const field_info = try fields_val.elemValue(mod, field_idx);
2208022126
22081 const field_name_val = try field_info.fieldValue(mod, 0);22127 const field_name_val = try field_info.fieldValue(mod, 0);
22082 const field_type_val = try field_info.fieldValue(mod, 1);22128 const field_type_val = try field_info.fieldValue(mod, 1);
...@@ -22837,12 +22883,12 @@ fn ptrCastFull(...@@ -22837,12 +22883,12 @@ fn ptrCastFull(
22837 return sema.failWithOwnedErrorMsg(block, msg: {22883 return sema.failWithOwnedErrorMsg(block, msg: {
22838 const msg = if (src_info.sentinel == .none) blk: {22884 const msg = if (src_info.sentinel == .none) blk: {
22839 break :blk try sema.errMsg(block, src, "destination pointer requires '{}' sentinel", .{22885 break :blk try sema.errMsg(block, src, "destination pointer requires '{}' sentinel", .{
22840 Value.fromInterned(dest_info.sentinel).fmtValue(Type.fromInterned(dest_info.child), mod),22886 Value.fromInterned(dest_info.sentinel).fmtValue(mod),
22841 });22887 });
22842 } else blk: {22888 } else blk: {
22843 break :blk try sema.errMsg(block, src, "pointer sentinel '{}' cannot coerce into pointer sentinel '{}'", .{22889 break :blk try sema.errMsg(block, src, "pointer sentinel '{}' cannot coerce into pointer sentinel '{}'", .{
22844 Value.fromInterned(src_info.sentinel).fmtValue(Type.fromInterned(src_info.child), mod),22890 Value.fromInterned(src_info.sentinel).fmtValue(mod),
22845 Value.fromInterned(dest_info.sentinel).fmtValue(Type.fromInterned(dest_info.child), mod),22891 Value.fromInterned(dest_info.sentinel).fmtValue(mod),
22846 });22892 });
22847 };22893 };
22848 errdefer msg.destroy(sema.gpa);22894 errdefer msg.destroy(sema.gpa);
...@@ -23216,7 +23262,8 @@ fn zirTruncate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -23216,7 +23262,8 @@ fn zirTruncate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
23216 const elems = try sema.arena.alloc(InternPool.Index, operand_ty.vectorLen(mod));23262 const elems = try sema.arena.alloc(InternPool.Index, operand_ty.vectorLen(mod));
23217 for (elems, 0..) |*elem, i| {23263 for (elems, 0..) |*elem, i| {
23218 const elem_val = try val.elemValue(mod, i);23264 const elem_val = try val.elemValue(mod, i);
23219 elem.* = try (try elem_val.intTrunc(operand_scalar_ty, sema.arena, dest_info.signedness, dest_info.bits, mod)).intern(dest_scalar_ty, mod);23265 const uncoerced_elem = try elem_val.intTrunc(operand_scalar_ty, sema.arena, dest_info.signedness, dest_info.bits, mod);
23266 elem.* = (try mod.getCoerced(uncoerced_elem, dest_scalar_ty)).toIntern();
23220 }23267 }
23221 return Air.internedToRef((try mod.intern(.{ .aggregate = .{23268 return Air.internedToRef((try mod.intern(.{ .aggregate = .{
23222 .ty = dest_ty.toIntern(),23269 .ty = dest_ty.toIntern(),
...@@ -23330,7 +23377,7 @@ fn zirByteSwap(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -23330,7 +23377,7 @@ fn zirByteSwap(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
23330 const elems = try sema.arena.alloc(InternPool.Index, vec_len);23377 const elems = try sema.arena.alloc(InternPool.Index, vec_len);
23331 for (elems, 0..) |*elem, i| {23378 for (elems, 0..) |*elem, i| {
23332 const elem_val = try val.elemValue(mod, i);23379 const elem_val = try val.elemValue(mod, i);
23333 elem.* = try (try elem_val.byteSwap(scalar_ty, mod, sema.arena)).intern(scalar_ty, mod);23380 elem.* = (try elem_val.byteSwap(scalar_ty, mod, sema.arena)).toIntern();
23334 }23381 }
23335 return Air.internedToRef((try mod.intern(.{ .aggregate = .{23382 return Air.internedToRef((try mod.intern(.{ .aggregate = .{
23336 .ty = operand_ty.toIntern(),23383 .ty = operand_ty.toIntern(),
...@@ -23378,7 +23425,7 @@ fn zirBitReverse(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!...@@ -23378,7 +23425,7 @@ fn zirBitReverse(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!
23378 const elems = try sema.arena.alloc(InternPool.Index, vec_len);23425 const elems = try sema.arena.alloc(InternPool.Index, vec_len);
23379 for (elems, 0..) |*elem, i| {23426 for (elems, 0..) |*elem, i| {
23380 const elem_val = try val.elemValue(mod, i);23427 const elem_val = try val.elemValue(mod, i);
23381 elem.* = try (try elem_val.bitReverse(scalar_ty, mod, sema.arena)).intern(scalar_ty, mod);23428 elem.* = (try elem_val.bitReverse(scalar_ty, mod, sema.arena)).toIntern();
23382 }23429 }
23383 return Air.internedToRef((try mod.intern(.{ .aggregate = .{23430 return Air.internedToRef((try mod.intern(.{ .aggregate = .{
23384 .ty = operand_ty.toIntern(),23431 .ty = operand_ty.toIntern(),
...@@ -23896,11 +23943,9 @@ fn resolveExportOptions(...@@ -23896,11 +23943,9 @@ fn resolveExportOptions(
23896 const visibility_src = sema.maybeOptionsSrc(block, src, "visibility");23943 const visibility_src = sema.maybeOptionsSrc(block, src, "visibility");
2389723944
23898 const name_operand = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, "name"), name_src);23945 const name_operand = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, "name"), name_src);
23899 const name_val = try sema.resolveConstDefinedValue(block, name_src, name_operand, .{23946 const name = try sema.toConstString(block, name_src, name_operand, .{
23900 .needed_comptime_reason = "name of exported value must be comptime-known",23947 .needed_comptime_reason = "name of exported value must be comptime-known",
23901 });23948 });
23902 const name_ty = Type.slice_const_u8;
23903 const name = try name_val.toAllocatedBytes(name_ty, sema.arena, mod);
2390423949
23905 const linkage_operand = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, "linkage"), linkage_src);23950 const linkage_operand = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, "linkage"), linkage_src);
23906 const linkage_val = try sema.resolveConstDefinedValue(block, linkage_src, linkage_operand, .{23951 const linkage_val = try sema.resolveConstDefinedValue(block, linkage_src, linkage_operand, .{
...@@ -23912,9 +23957,10 @@ fn resolveExportOptions(...@@ -23912,9 +23957,10 @@ fn resolveExportOptions(
23912 const section_opt_val = try sema.resolveConstDefinedValue(block, section_src, section_operand, .{23957 const section_opt_val = try sema.resolveConstDefinedValue(block, section_src, section_operand, .{
23913 .needed_comptime_reason = "linksection of exported value must be comptime-known",23958 .needed_comptime_reason = "linksection of exported value must be comptime-known",
23914 });23959 });
23915 const section_ty = Type.slice_const_u8;
23916 const section = if (section_opt_val.optionalValue(mod)) |section_val|23960 const section = if (section_opt_val.optionalValue(mod)) |section_val|
23917 try section_val.toAllocatedBytes(section_ty, sema.arena, mod)23961 try sema.toConstString(block, section_src, Air.internedToRef(section_val.toIntern()), .{
23962 .needed_comptime_reason = "linksection of exported value must be comptime-known",
23963 })
23918 else23964 else
23919 null;23965 null;
2392023966
...@@ -24311,7 +24357,7 @@ fn analyzeShuffle(...@@ -24311,7 +24357,7 @@ fn analyzeShuffle(
24311 }24357 }
24312 const int = mask_elem_val.toSignedInt(mod);24358 const int = mask_elem_val.toSignedInt(mod);
24313 const unsigned: u32 = @intCast(if (int >= 0) int else ~int);24359 const unsigned: u32 = @intCast(if (int >= 0) int else ~int);
24314 values[i] = try (try (if (int >= 0) a_val else b_val).elemValue(mod, unsigned)).intern(elem_ty, mod);24360 values[i] = (try (if (int >= 0) a_val else b_val).elemValue(mod, unsigned)).toIntern();
24315 }24361 }
24316 return Air.internedToRef((try mod.intern(.{ .aggregate = .{24362 return Air.internedToRef((try mod.intern(.{ .aggregate = .{
24317 .ty = res_ty.toIntern(),24363 .ty = res_ty.toIntern(),
...@@ -24417,7 +24463,7 @@ fn zirSelect(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) C...@@ -24417,7 +24463,7 @@ fn zirSelect(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) C
24417 for (elems, 0..) |*elem, i| {24463 for (elems, 0..) |*elem, i| {
24418 const pred_elem_val = try pred_val.elemValue(mod, i);24464 const pred_elem_val = try pred_val.elemValue(mod, i);
24419 const should_choose_a = pred_elem_val.toBool();24465 const should_choose_a = pred_elem_val.toBool();
24420 elem.* = try (try (if (should_choose_a) a_val else b_val).elemValue(mod, i)).intern(elem_ty, mod);24466 elem.* = (try (if (should_choose_a) a_val else b_val).elemValue(mod, i)).toIntern();
24421 }24467 }
2442224468
24423 return Air.internedToRef((try mod.intern(.{ .aggregate = .{24469 return Air.internedToRef((try mod.intern(.{ .aggregate = .{
...@@ -25239,10 +25285,10 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void...@@ -25239,10 +25285,10 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
25239 const msg = try sema.errMsg(block, src, "non-matching @memcpy lengths", .{});25285 const msg = try sema.errMsg(block, src, "non-matching @memcpy lengths", .{});
25240 errdefer msg.destroy(sema.gpa);25286 errdefer msg.destroy(sema.gpa);
25241 try sema.errNote(block, dest_src, msg, "length {} here", .{25287 try sema.errNote(block, dest_src, msg, "length {} here", .{
25242 dest_len_val.fmtValue(Type.usize, sema.mod),25288 dest_len_val.fmtValue(sema.mod),
25243 });25289 });
25244 try sema.errNote(block, src_src, msg, "length {} here", .{25290 try sema.errNote(block, src_src, msg, "length {} here", .{
25245 src_len_val.fmtValue(Type.usize, sema.mod),25291 src_len_val.fmtValue(sema.mod),
25246 });25292 });
25247 break :msg msg;25293 break :msg msg;
25248 };25294 };
...@@ -25777,7 +25823,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A...@@ -25777,7 +25823,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
25777 } else if (extra.data.bits.has_ret_ty_ref) blk: {25823 } else if (extra.data.bits.has_ret_ty_ref) blk: {
25778 const ret_ty_ref: Zir.Inst.Ref = @enumFromInt(sema.code.extra[extra_index]);25824 const ret_ty_ref: Zir.Inst.Ref = @enumFromInt(sema.code.extra[extra_index]);
25779 extra_index += 1;25825 extra_index += 1;
25780 const ret_ty_tv = sema.resolveInstConst(block, ret_src, ret_ty_ref, .{25826 const ret_ty_val = sema.resolveInstConst(block, ret_src, ret_ty_ref, .{
25781 .needed_comptime_reason = "return type must be comptime-known",25827 .needed_comptime_reason = "return type must be comptime-known",
25782 }) catch |err| switch (err) {25828 }) catch |err| switch (err) {
25783 error.GenericPoison => {25829 error.GenericPoison => {
...@@ -25785,8 +25831,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A...@@ -25785,8 +25831,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
25785 },25831 },
25786 else => |e| return e,25832 else => |e| return e,
25787 };25833 };
25788 const ty = ret_ty_tv.val.toType();25834 break :blk ret_ty_val.toType();
25789 break :blk ty;
25790 } else Type.void;25835 } else Type.void;
2579125836
25792 const noalias_bits: u32 = if (extra.data.bits.has_any_noalias) blk: {25837 const noalias_bits: u32 = if (extra.data.bits.has_any_noalias) blk: {
...@@ -26032,10 +26077,9 @@ fn resolveExternOptions(...@@ -26032,10 +26077,9 @@ fn resolveExternOptions(
26032 const thread_local_src = sema.maybeOptionsSrc(block, src, "thread_local");26077 const thread_local_src = sema.maybeOptionsSrc(block, src, "thread_local");
2603326078
26034 const name_ref = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, "name"), name_src);26079 const name_ref = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, "name"), name_src);
26035 const name_val = try sema.resolveConstDefinedValue(block, name_src, name_ref, .{26080 const name = try sema.toConstString(block, name_src, name_ref, .{
26036 .needed_comptime_reason = "name of the extern symbol must be comptime-known",26081 .needed_comptime_reason = "name of the extern symbol must be comptime-known",
26037 });26082 });
26038 const name = try name_val.toAllocatedBytes(Type.slice_const_u8, sema.arena, mod);
2603926083
26040 const library_name_inst = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, "library_name"), library_src);26084 const library_name_inst = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, "library_name"), library_src);
26041 const library_name_val = try sema.resolveConstDefinedValue(block, library_src, library_name_inst, .{26085 const library_name_val = try sema.resolveConstDefinedValue(block, library_src, library_name_inst, .{
...@@ -26054,7 +26098,9 @@ fn resolveExternOptions(...@@ -26054,7 +26098,9 @@ fn resolveExternOptions(
26054 });26098 });
2605526099
26056 const library_name = if (library_name_val.optionalValue(mod)) |library_name_payload| library_name: {26100 const library_name = if (library_name_val.optionalValue(mod)) |library_name_payload| library_name: {
26057 const library_name = try library_name_payload.toAllocatedBytes(Type.slice_const_u8, sema.arena, mod);26101 const library_name = try sema.toConstString(block, library_src, Air.internedToRef(library_name_payload.toIntern()), .{
26102 .needed_comptime_reason = "library in which extern symbol is must be comptime-known",
26103 });
26058 if (library_name.len == 0) {26104 if (library_name.len == 0) {
26059 return sema.fail(block, library_src, "library name cannot be empty", .{});26105 return sema.fail(block, library_src, "library name cannot be empty", .{});
26060 }26106 }
...@@ -26120,9 +26166,10 @@ fn zirBuiltinExtern(...@@ -26120,9 +26166,10 @@ fn zirBuiltinExtern(
26120 const new_decl_index = try mod.allocateNewDecl(sema.owner_decl.src_namespace, sema.owner_decl.src_node);26166 const new_decl_index = try mod.allocateNewDecl(sema.owner_decl.src_namespace, sema.owner_decl.src_node);
26121 errdefer mod.destroyDecl(new_decl_index);26167 errdefer mod.destroyDecl(new_decl_index);
26122 const new_decl = mod.declPtr(new_decl_index);26168 const new_decl = mod.declPtr(new_decl_index);
26123 try mod.initNewAnonDecl(new_decl_index, sema.owner_decl.src_line, .{26169 try mod.initNewAnonDecl(
26124 .ty = Type.fromInterned(ptr_info.child),26170 new_decl_index,
26125 .val = Value.fromInterned(26171 sema.owner_decl.src_line,
26172 Value.fromInterned(
26126 if (Type.fromInterned(ptr_info.child).zigTypeTag(mod) == .Fn)26173 if (Type.fromInterned(ptr_info.child).zigTypeTag(mod) == .Fn)
26127 try ip.getExternFunc(sema.gpa, .{26174 try ip.getExternFunc(sema.gpa, .{
26128 .ty = ptr_info.child,26175 .ty = ptr_info.child,
...@@ -26141,7 +26188,8 @@ fn zirBuiltinExtern(...@@ -26141,7 +26188,8 @@ fn zirBuiltinExtern(
26141 .is_weak_linkage = options.linkage == .weak,26188 .is_weak_linkage = options.linkage == .weak,
26142 } }),26189 } }),
26143 ),26190 ),
26144 }, options.name);26191 options.name,
26192 );
26145 new_decl.owns_tv = true;26193 new_decl.owns_tv = true;
26146 // Note that this will queue the anon decl for codegen, so that the backend can26194 // Note that this will queue the anon decl for codegen, so that the backend can
26147 // correctly handle the extern, including duplicate detection.26195 // correctly handle the extern, including duplicate detection.
...@@ -26641,13 +26689,12 @@ fn prepareSimplePanic(sema: *Sema, block: *Block) !void {...@@ -26641,13 +26689,12 @@ fn prepareSimplePanic(sema: *Sema, block: *Block) !void {
26641 // decl_index may be an alias; we must find the decl that actually26689 // decl_index may be an alias; we must find the decl that actually
26642 // owns the function.26690 // owns the function.
26643 try sema.ensureDeclAnalyzed(decl_index);26691 try sema.ensureDeclAnalyzed(decl_index);
26644 const tv = try mod.declPtr(decl_index).typedValue();26692 const fn_val = try mod.declPtr(decl_index).valueOrFail();
26645 try sema.declareDependency(.{ .decl_val = decl_index });26693 try sema.declareDependency(.{ .decl_val = decl_index });
26646 assert(tv.ty.zigTypeTag(mod) == .Fn);26694 assert(fn_val.typeOf(mod).zigTypeTag(mod) == .Fn);
26647 assert(try sema.fnHasRuntimeBits(tv.ty));26695 assert(try sema.fnHasRuntimeBits(fn_val.typeOf(mod)));
26648 const func_index = tv.val.toIntern();26696 try mod.ensureFuncBodyAnalysisQueued(fn_val.toIntern());
26649 try mod.ensureFuncBodyAnalysisQueued(func_index);26697 mod.panic_func_index = fn_val.toIntern();
26650 mod.panic_func_index = func_index;
26651 }26698 }
2665226699
26653 if (mod.null_stack_trace == .none) {26700 if (mod.null_stack_trace == .none) {
...@@ -27789,7 +27836,7 @@ fn structFieldPtrByIndex(...@@ -27789,7 +27836,7 @@ fn structFieldPtrByIndex(
27789 const val = try mod.intern(.{ .ptr = .{27836 const val = try mod.intern(.{ .ptr = .{
27790 .ty = ptr_field_ty.toIntern(),27837 .ty = ptr_field_ty.toIntern(),
27791 .addr = .{ .field = .{27838 .addr = .{ .field = .{
27792 .base = try struct_ptr_val.intern(struct_ptr_ty, mod),27839 .base = struct_ptr_val.toIntern(),
27793 .index = field_index,27840 .index = field_index,
27794 } },27841 } },
27795 } });27842 } });
...@@ -28568,7 +28615,7 @@ fn elemValSlice(...@@ -28568,7 +28615,7 @@ fn elemValSlice(
2856828615
28569 if (maybe_slice_val) |slice_val| {28616 if (maybe_slice_val) |slice_val| {
28570 runtime_src = elem_index_src;28617 runtime_src = elem_index_src;
28571 const slice_len = slice_val.sliceLen(mod);28618 const slice_len = try slice_val.sliceLen(sema);
28572 const slice_len_s = slice_len + @intFromBool(slice_sent);28619 const slice_len_s = slice_len + @intFromBool(slice_sent);
28573 if (slice_len_s == 0) {28620 if (slice_len_s == 0) {
28574 return sema.fail(block, slice_src, "indexing into empty slice is not allowed", .{});28621 return sema.fail(block, slice_src, "indexing into empty slice is not allowed", .{});
...@@ -28593,7 +28640,7 @@ fn elemValSlice(...@@ -28593,7 +28640,7 @@ fn elemValSlice(
28593 try sema.requireRuntimeBlock(block, src, runtime_src);28640 try sema.requireRuntimeBlock(block, src, runtime_src);
28594 if (oob_safety and block.wantSafety()) {28641 if (oob_safety and block.wantSafety()) {
28595 const len_inst = if (maybe_slice_val) |slice_val|28642 const len_inst = if (maybe_slice_val) |slice_val|
28596 try mod.intRef(Type.usize, slice_val.sliceLen(mod))28643 try mod.intRef(Type.usize, try slice_val.sliceLen(sema))
28597 else28644 else
28598 try block.addTyOp(.slice_len, Type.usize, slice);28645 try block.addTyOp(.slice_len, Type.usize, slice);
28599 const cmp_op: Air.Inst.Tag = if (slice_sent) .cmp_lte else .cmp_lt;28646 const cmp_op: Air.Inst.Tag = if (slice_sent) .cmp_lte else .cmp_lt;
...@@ -28630,7 +28677,7 @@ fn elemPtrSlice(...@@ -28630,7 +28677,7 @@ fn elemPtrSlice(
28630 if (slice_val.isUndef(mod)) {28677 if (slice_val.isUndef(mod)) {
28631 return mod.undefRef(elem_ptr_ty);28678 return mod.undefRef(elem_ptr_ty);
28632 }28679 }
28633 const slice_len = slice_val.sliceLen(mod);28680 const slice_len = try slice_val.sliceLen(sema);
28634 const slice_len_s = slice_len + @intFromBool(slice_sent);28681 const slice_len_s = slice_len + @intFromBool(slice_sent);
28635 if (slice_len_s == 0) {28682 if (slice_len_s == 0) {
28636 return sema.fail(block, slice_src, "indexing into empty slice is not allowed", .{});28683 return sema.fail(block, slice_src, "indexing into empty slice is not allowed", .{});
...@@ -28653,7 +28700,7 @@ fn elemPtrSlice(...@@ -28653,7 +28700,7 @@ fn elemPtrSlice(
28653 const len_inst = len: {28700 const len_inst = len: {
28654 if (maybe_undef_slice_val) |slice_val|28701 if (maybe_undef_slice_val) |slice_val|
28655 if (!slice_val.isUndef(mod))28702 if (!slice_val.isUndef(mod))
28656 break :len try mod.intRef(Type.usize, slice_val.sliceLen(mod));28703 break :len try mod.intRef(Type.usize, try slice_val.sliceLen(sema));
28657 break :len try block.addTyOp(.slice_len, Type.usize, slice);28704 break :len try block.addTyOp(.slice_len, Type.usize, slice);
28658 };28705 };
28659 const cmp_op: Air.Inst.Tag = if (slice_sent) .cmp_lte else .cmp_lt;28706 const cmp_op: Air.Inst.Tag = if (slice_sent) .cmp_lte else .cmp_lt;
...@@ -29115,7 +29162,7 @@ fn coerceExtra(...@@ -29115,7 +29162,7 @@ fn coerceExtra(
29115 // comptime-known integer to other number29162 // comptime-known integer to other number
29116 if (!(try sema.intFitsInType(val, dest_ty, null))) {29163 if (!(try sema.intFitsInType(val, dest_ty, null))) {
29117 if (!opts.report_err) return error.NotCoercible;29164 if (!opts.report_err) return error.NotCoercible;
29118 return sema.fail(block, inst_src, "type '{}' cannot represent integer value '{}'", .{ dest_ty.fmt(mod), val.fmtValue(inst_ty, mod) });29165 return sema.fail(block, inst_src, "type '{}' cannot represent integer value '{}'", .{ dest_ty.fmt(mod), val.fmtValue(mod) });
29119 }29166 }
29120 return switch (mod.intern_pool.indexToKey(val.toIntern())) {29167 return switch (mod.intern_pool.indexToKey(val.toIntern())) {
29121 .undef => try mod.undefRef(dest_ty),29168 .undef => try mod.undefRef(dest_ty),
...@@ -29160,7 +29207,7 @@ fn coerceExtra(...@@ -29160,7 +29207,7 @@ fn coerceExtra(
29160 block,29207 block,
29161 inst_src,29208 inst_src,
29162 "type '{}' cannot represent float value '{}'",29209 "type '{}' cannot represent float value '{}'",
29163 .{ dest_ty.fmt(mod), val.fmtValue(inst_ty, mod) },29210 .{ dest_ty.fmt(mod), val.fmtValue(mod) },
29164 );29211 );
29165 }29212 }
29166 return Air.internedToRef(result_val.toIntern());29213 return Air.internedToRef(result_val.toIntern());
...@@ -29531,11 +29578,11 @@ const InMemoryCoercionResult = union(enum) {...@@ -29531,11 +29578,11 @@ const InMemoryCoercionResult = union(enum) {
29531 .array_sentinel => |sentinel| {29578 .array_sentinel => |sentinel| {
29532 if (sentinel.actual.toIntern() != .unreachable_value) {29579 if (sentinel.actual.toIntern() != .unreachable_value) {
29533 try sema.errNote(block, src, msg, "array sentinel '{}' cannot cast into array sentinel '{}'", .{29580 try sema.errNote(block, src, msg, "array sentinel '{}' cannot cast into array sentinel '{}'", .{
29534 sentinel.actual.fmtValue(sentinel.ty, mod), sentinel.wanted.fmtValue(sentinel.ty, mod),29581 sentinel.actual.fmtValue(mod), sentinel.wanted.fmtValue(mod),
29535 });29582 });
29536 } else {29583 } else {
29537 try sema.errNote(block, src, msg, "destination array requires '{}' sentinel", .{29584 try sema.errNote(block, src, msg, "destination array requires '{}' sentinel", .{
29538 sentinel.wanted.fmtValue(sentinel.ty, mod),29585 sentinel.wanted.fmtValue(mod),
29539 });29586 });
29540 }29587 }
29541 break;29588 break;
...@@ -29657,11 +29704,11 @@ const InMemoryCoercionResult = union(enum) {...@@ -29657,11 +29704,11 @@ const InMemoryCoercionResult = union(enum) {
29657 .ptr_sentinel => |sentinel| {29704 .ptr_sentinel => |sentinel| {
29658 if (sentinel.actual.toIntern() != .unreachable_value) {29705 if (sentinel.actual.toIntern() != .unreachable_value) {
29659 try sema.errNote(block, src, msg, "pointer sentinel '{}' cannot cast into pointer sentinel '{}'", .{29706 try sema.errNote(block, src, msg, "pointer sentinel '{}' cannot cast into pointer sentinel '{}'", .{
29660 sentinel.actual.fmtValue(sentinel.ty, mod), sentinel.wanted.fmtValue(sentinel.ty, mod),29707 sentinel.actual.fmtValue(mod), sentinel.wanted.fmtValue(mod),
29661 });29708 });
29662 } else {29709 } else {
29663 try sema.errNote(block, src, msg, "destination pointer requires '{}' sentinel", .{29710 try sema.errNote(block, src, msg, "destination pointer requires '{}' sentinel", .{
29664 sentinel.wanted.fmtValue(sentinel.ty, mod),29711 sentinel.wanted.fmtValue(mod),
29665 });29712 });
29666 }29713 }
29667 break;29714 break;
...@@ -30654,21 +30701,22 @@ fn storePtrVal(...@@ -30654,21 +30701,22 @@ fn storePtrVal(
30654 .opv => {},30701 .opv => {},
30655 .direct => |val_ptr| {30702 .direct => |val_ptr| {
30656 if (mut_kit.root == .comptime_field) {30703 if (mut_kit.root == .comptime_field) {
30657 val_ptr.* = Value.fromInterned((try val_ptr.intern(operand_ty, mod)));30704 val_ptr.* = .{ .interned = try val_ptr.intern(mod, sema.arena) };
30658 if (!operand_val.eql(val_ptr.*, operand_ty, mod)) {30705 if (operand_val.toIntern() != val_ptr.interned) {
30659 // TODO use failWithInvalidComptimeFieldStore30706 // TODO use failWithInvalidComptimeFieldStore
30660 return sema.fail(block, src, "value stored in comptime field does not match the default value of the field", .{});30707 return sema.fail(block, src, "value stored in comptime field does not match the default value of the field", .{});
30661 }30708 }
30662 return;30709 return;
30663 }30710 }
30664 val_ptr.* = Value.fromInterned((try operand_val.intern(operand_ty, mod)));30711 val_ptr.* = .{ .interned = operand_val.toIntern() };
30665 },30712 },
30666 .reinterpret => |reinterpret| {30713 .reinterpret => |reinterpret| {
30667 try sema.resolveTypeLayout(mut_kit.ty);30714 try sema.resolveTypeLayout(mut_kit.ty);
30668 const abi_size = try sema.usizeCast(block, src, mut_kit.ty.abiSize(mod));30715 const abi_size = try sema.usizeCast(block, src, mut_kit.ty.abiSize(mod));
30669 const buffer = try sema.gpa.alloc(u8, abi_size);30716 const buffer = try sema.gpa.alloc(u8, abi_size);
30670 defer sema.gpa.free(buffer);30717 defer sema.gpa.free(buffer);
30671 reinterpret.val_ptr.*.writeToMemory(mut_kit.ty, mod, buffer) catch |err| switch (err) {30718 const interned_old = Value.fromInterned(try reinterpret.val_ptr.intern(mod, sema.arena));
30719 interned_old.writeToMemory(mut_kit.ty, mod, buffer) catch |err| switch (err) {
30672 error.OutOfMemory => return error.OutOfMemory,30720 error.OutOfMemory => return error.OutOfMemory,
30673 error.ReinterpretDeclRef => unreachable,30721 error.ReinterpretDeclRef => unreachable,
30674 error.IllDefinedMemoryLayout => unreachable, // Sema was supposed to emit a compile error already30722 error.IllDefinedMemoryLayout => unreachable, // Sema was supposed to emit a compile error already
...@@ -30692,7 +30740,7 @@ fn storePtrVal(...@@ -30692,7 +30740,7 @@ fn storePtrVal(
30692 error.IllDefinedMemoryLayout => unreachable,30740 error.IllDefinedMemoryLayout => unreachable,
30693 error.Unimplemented => return sema.fail(block, src, "TODO: implement readFromMemory for type '{}'", .{mut_kit.ty.fmt(mod)}),30741 error.Unimplemented => return sema.fail(block, src, "TODO: implement readFromMemory for type '{}'", .{mut_kit.ty.fmt(mod)}),
30694 };30742 };
30695 reinterpret.val_ptr.* = Value.fromInterned((try val.intern(mut_kit.ty, mod)));30743 reinterpret.val_ptr.* = .{ .interned = val.toIntern() };
30696 },30744 },
30697 .bad_decl_ty, .bad_ptr_ty => {30745 .bad_decl_ty, .bad_ptr_ty => {
30698 // TODO show the decl declaration site in a note and explain whether the decl30746 // TODO show the decl declaration site in a note and explain whether the decl
...@@ -30717,11 +30765,11 @@ const ComptimePtrMutationKit = struct {...@@ -30717,11 +30765,11 @@ const ComptimePtrMutationKit = struct {
30717 opv,30765 opv,
30718 /// The pointer type matches the actual comptime Value so a direct30766 /// The pointer type matches the actual comptime Value so a direct
30719 /// modification is possible.30767 /// modification is possible.
30720 direct: *Value,30768 direct: *MutableValue,
30721 /// The largest parent Value containing pointee and having a well-defined memory layout.30769 /// The largest parent Value containing pointee and having a well-defined memory layout.
30722 /// This is used for bitcasting, if direct dereferencing failed.30770 /// This is used for bitcasting, if direct dereferencing failed.
30723 reinterpret: struct {30771 reinterpret: struct {
30724 val_ptr: *Value,30772 val_ptr: *MutableValue,
30725 byte_offset: usize,30773 byte_offset: usize,
30726 /// If set, write the operand to packed memory30774 /// If set, write the operand to packed memory
30727 write_packed: bool = false,30775 write_packed: bool = false,
...@@ -30753,15 +30801,15 @@ fn beginComptimePtrMutation(...@@ -30753,15 +30801,15 @@ fn beginComptimePtrMutation(
30753 .decl, .anon_decl, .int => unreachable, // isComptimeMutablePtr has been checked already30801 .decl, .anon_decl, .int => unreachable, // isComptimeMutablePtr has been checked already
30754 .comptime_alloc => |alloc_index| {30802 .comptime_alloc => |alloc_index| {
30755 const alloc = sema.getComptimeAlloc(alloc_index);30803 const alloc = sema.getComptimeAlloc(alloc_index);
30756 return sema.beginComptimePtrMutationInner(block, src, alloc.ty, &alloc.val, ptr_elem_ty, .{ .alloc = alloc_index });30804 return sema.beginComptimePtrMutationInner(block, src, alloc.val.typeOf(mod), &alloc.val, ptr_elem_ty, .{ .alloc = alloc_index });
30757 },30805 },
30758 .comptime_field => |comptime_field| {30806 .comptime_field => |comptime_field| {
30759 const duped = try sema.arena.create(Value);30807 const duped = try sema.arena.create(MutableValue);
30760 duped.* = Value.fromInterned(comptime_field);30808 duped.* = .{ .interned = comptime_field };
30761 return sema.beginComptimePtrMutationInner(30809 return sema.beginComptimePtrMutationInner(
30762 block,30810 block,
30763 src,30811 src,
30764 Type.fromInterned(mod.intern_pool.typeOf(comptime_field)),30812 duped.typeOf(mod),
30765 duped,30813 duped,
30766 ptr_elem_ty,30814 ptr_elem_ty,
30767 .comptime_field,30815 .comptime_field,
...@@ -30774,36 +30822,28 @@ fn beginComptimePtrMutation(...@@ -30774,36 +30822,28 @@ fn beginComptimePtrMutation(
30774 .opv => unreachable,30822 .opv => unreachable,
30775 .direct => |val_ptr| {30823 .direct => |val_ptr| {
30776 const payload_ty = parent.ty.errorUnionPayload(mod);30824 const payload_ty = parent.ty.errorUnionPayload(mod);
30777 if (val_ptr.ip_index == .none and val_ptr.tag() == .eu_payload) {30825 try val_ptr.unintern(mod, sema.arena, false, false);
30778 return ComptimePtrMutationKit{30826 if (val_ptr.* == .interned) {
30779 .root = parent.root,
30780 .pointee = .{ .direct = &val_ptr.castTag(.eu_payload).?.data },
30781 .ty = payload_ty,
30782 };
30783 } else {
30784 // An error union has been initialized to undefined at comptime and now we30827 // An error union has been initialized to undefined at comptime and now we
30785 // are for the first time setting the payload. We must change the30828 // are for the first time setting the payload. We must change the
30786 // representation of the error union from `undef` to `opt_payload`.30829 // representation of the error union to `eu_payload`.
3078730830 const child = try sema.arena.create(MutableValue);
30788 const payload = try sema.arena.create(Value.Payload.SubValue);30831 child.* = .{ .interned = try mod.intern(.{ .undef = payload_ty.toIntern() }) };
30789 payload.* = .{30832 val_ptr.* = .{ .eu_payload = .{
30790 .base = .{ .tag = .eu_payload },30833 .ty = parent.ty.toIntern(),
30791 .data = Value.fromInterned((try mod.intern(.{ .undef = payload_ty.toIntern() }))),30834 .child = child,
30792 };30835 } };
30793
30794 val_ptr.* = Value.initPayload(&payload.base);
30795
30796 return ComptimePtrMutationKit{
30797 .root = parent.root,
30798 .pointee = .{ .direct = &payload.data },
30799 .ty = payload_ty,
30800 };
30801 }30836 }
30837 return .{
30838 .root = parent.root,
30839 .pointee = .{ .direct = val_ptr.eu_payload.child },
30840 .ty = payload_ty,
30841 };
30802 },30842 },
30803 .bad_decl_ty, .bad_ptr_ty => return parent,30843 .bad_decl_ty, .bad_ptr_ty => return parent,
30804 // Even though the parent value type has well-defined memory layout, our30844 // Even though the parent value type has well-defined memory layout, our
30805 // pointer type does not.30845 // pointer type does not.
30806 .reinterpret => return ComptimePtrMutationKit{30846 .reinterpret => return .{
30807 .root = parent.root,30847 .root = parent.root,
30808 .pointee = .bad_ptr_ty,30848 .pointee = .bad_ptr_ty,
30809 .ty = eu_ty,30849 .ty = eu_ty,
...@@ -30817,46 +30857,28 @@ fn beginComptimePtrMutation(...@@ -30817,46 +30857,28 @@ fn beginComptimePtrMutation(
30817 .opv => unreachable,30857 .opv => unreachable,
30818 .direct => |val_ptr| {30858 .direct => |val_ptr| {
30819 const payload_ty = parent.ty.optionalChild(mod);30859 const payload_ty = parent.ty.optionalChild(mod);
30820 switch (val_ptr.ip_index) {30860 try val_ptr.unintern(mod, sema.arena, false, false);
30821 .none => return ComptimePtrMutationKit{30861 if (val_ptr.* == .interned) {
30822 .root = parent.root,30862 // An optional has been initialized to undefined at comptime and now we
30823 .pointee = .{ .direct = &val_ptr.castTag(.opt_payload).?.data },30863 // are for the first time setting the payload. We must change the
30824 .ty = payload_ty,30864 // representation of the optional to `opt_payload`.
30825 },30865 const child = try sema.arena.create(MutableValue);
30826 else => {30866 child.* = .{ .interned = try mod.intern(.{ .undef = payload_ty.toIntern() }) };
30827 const payload_val = switch (mod.intern_pool.indexToKey(val_ptr.ip_index)) {30867 val_ptr.* = .{ .opt_payload = .{
30828 .undef => try mod.intern(.{ .undef = payload_ty.toIntern() }),30868 .ty = parent.ty.toIntern(),
30829 .opt => |opt| switch (opt.val) {30869 .child = child,
30830 .none => try mod.intern(.{ .undef = payload_ty.toIntern() }),30870 } };
30831 else => |payload| payload,
30832 },
30833 else => unreachable,
30834 };
30835
30836 // An optional has been initialized to undefined at comptime and now we
30837 // are for the first time setting the payload. We must change the
30838 // representation of the optional from `undef` to `opt_payload`.
30839
30840 const payload = try sema.arena.create(Value.Payload.SubValue);
30841 payload.* = .{
30842 .base = .{ .tag = .opt_payload },
30843 .data = Value.fromInterned(payload_val),
30844 };
30845
30846 val_ptr.* = Value.initPayload(&payload.base);
30847
30848 return ComptimePtrMutationKit{
30849 .root = parent.root,
30850 .pointee = .{ .direct = &payload.data },
30851 .ty = payload_ty,
30852 };
30853 },
30854 }30871 }
30872 return .{
30873 .root = parent.root,
30874 .pointee = .{ .direct = val_ptr.opt_payload.child },
30875 .ty = payload_ty,
30876 };
30855 },30877 },
30856 .bad_decl_ty, .bad_ptr_ty => return parent,30878 .bad_decl_ty, .bad_ptr_ty => return parent,
30857 // Even though the parent value type has well-defined memory layout, our30879 // Even though the parent value type has well-defined memory layout, our
30858 // pointer type does not.30880 // pointer type does not.
30859 .reinterpret => return ComptimePtrMutationKit{30881 .reinterpret => return .{
30860 .root = parent.root,30882 .root = parent.root,
30861 .pointee = .bad_ptr_ty,30883 .pointee = .bad_ptr_ty,
30862 .ty = opt_ty,30884 .ty = opt_ty,
...@@ -30915,106 +30937,28 @@ fn beginComptimePtrMutation(...@@ -30915,106 +30937,28 @@ fn beginComptimePtrMutation(
30915 };30937 };
30916 }30938 }
3091730939
30918 switch (val_ptr.ip_index) {30940 try val_ptr.unintern(mod, sema.arena, false, false);
30919 .none => switch (val_ptr.tag()) {30941
30920 .bytes => {30942 const aggregate = switch (val_ptr.*) {
30921 // An array is memory-optimized to store a slice of bytes, but we are about30943 .interned,
30922 // to modify an individual field and the representation has to change.30944 .bytes,
30923 // If we wanted to avoid this, there would need to be special detection30945 .repeated,
30924 // elsewhere to identify when writing a value to an array element that is stored30946 .eu_payload,
30925 // using the `bytes` tag, and handle it without making a call to this function.30947 .opt_payload,
30926 const arena = sema.arena;30948 .slice,
3092730949 .un,
30928 const bytes = val_ptr.castTag(.bytes).?.data;30950 => unreachable,
30929 const dest_len = parent.ty.arrayLenIncludingSentinel(mod);30951 .aggregate => |*a| a,
30930 // bytes.len may be one greater than dest_len because of the case when30952 };
30931 // assigning `[N:S]T` to `[N]T`. This is allowed; the sentinel is omitted.
30932 assert(bytes.len >= dest_len);
30933 const elems = try arena.alloc(Value, @intCast(dest_len));
30934 for (elems, 0..) |*elem, i| {
30935 elem.* = try mod.intValue(elem_ty, bytes[i]);
30936 }
30937
30938 val_ptr.* = try Value.Tag.aggregate.create(arena, elems);
30939
30940 return beginComptimePtrMutationInner(
30941 sema,
30942 block,
30943 src,
30944 elem_ty,
30945 &elems[@intCast(elem_ptr.index)],
30946 ptr_elem_ty,
30947 parent.root,
30948 );
30949 },
30950 .repeated => {
30951 // An array is memory-optimized to store only a single element value, and
30952 // that value is understood to be the same for the entire length of the array.
30953 // However, now we want to modify an individual field and so the
30954 // representation has to change. If we wanted to avoid this, there would
30955 // need to be special detection elsewhere to identify when writing a value to an
30956 // array element that is stored using the `repeated` tag, and handle it
30957 // without making a call to this function.
30958 const arena = sema.arena;
30959
30960 const repeated_val = try val_ptr.castTag(.repeated).?.data.intern(parent.ty.childType(mod), mod);
30961 const array_len_including_sentinel =
30962 try sema.usizeCast(block, src, parent.ty.arrayLenIncludingSentinel(mod));
30963 const elems = try arena.alloc(Value, array_len_including_sentinel);
30964 @memset(elems, Value.fromInterned(repeated_val));
30965
30966 val_ptr.* = try Value.Tag.aggregate.create(arena, elems);
30967
30968 return beginComptimePtrMutationInner(
30969 sema,
30970 block,
30971 src,
30972 elem_ty,
30973 &elems[@intCast(elem_ptr.index)],
30974 ptr_elem_ty,
30975 parent.root,
30976 );
30977 },
30978
30979 .aggregate => return beginComptimePtrMutationInner(
30980 sema,
30981 block,
30982 src,
30983 elem_ty,
30984 &val_ptr.castTag(.aggregate).?.data[@intCast(elem_ptr.index)],
30985 ptr_elem_ty,
30986 parent.root,
30987 ),
3098830953
30989 else => unreachable,30954 return sema.beginComptimePtrMutationInner(
30990 },30955 block,
30991 else => switch (mod.intern_pool.indexToKey(val_ptr.toIntern())) {30956 src,
30992 .undef => {30957 elem_ty,
30993 // An array has been initialized to undefined at comptime and now we30958 &aggregate.elems[@intCast(elem_ptr.index)],
30994 // are for the first time setting an element. We must change the representation30959 ptr_elem_ty,
30995 // of the array from `undef` to `array`.30960 parent.root,
30996 const arena = sema.arena;30961 );
30997
30998 const array_len_including_sentinel =
30999 try sema.usizeCast(block, src, parent.ty.arrayLenIncludingSentinel(mod));
31000 const elems = try arena.alloc(Value, array_len_including_sentinel);
31001 @memset(elems, Value.fromInterned((try mod.intern(.{ .undef = elem_ty.toIntern() }))));
31002
31003 val_ptr.* = try Value.Tag.aggregate.create(arena, elems);
31004
31005 return beginComptimePtrMutationInner(
31006 sema,
31007 block,
31008 src,
31009 elem_ty,
31010 &elems[@intCast(elem_ptr.index)],
31011 ptr_elem_ty,
31012 parent.root,
31013 );
31014 },
31015 else => unreachable,
31016 },
31017 }
31018 },30962 },
31019 else => {30963 else => {
31020 if (elem_ptr.index != 0) {30964 if (elem_ptr.index != 0) {
...@@ -31038,7 +30982,7 @@ fn beginComptimePtrMutation(...@@ -31038,7 +30982,7 @@ fn beginComptimePtrMutation(
31038 if (!base_elem_ty.hasWellDefinedLayout(mod)) {30982 if (!base_elem_ty.hasWellDefinedLayout(mod)) {
31039 // Even though the parent value type has well-defined memory layout, our30983 // Even though the parent value type has well-defined memory layout, our
31040 // pointer type does not.30984 // pointer type does not.
31041 return ComptimePtrMutationKit{30985 return .{
31042 .root = parent.root,30986 .root = parent.root,
31043 .pointee = .bad_ptr_ty,30987 .pointee = .bad_ptr_ty,
31044 .ty = base_elem_ty,30988 .ty = base_elem_ty,
...@@ -31048,7 +30992,7 @@ fn beginComptimePtrMutation(...@@ -31048,7 +30992,7 @@ fn beginComptimePtrMutation(
31048 const elem_abi_size_u64 = try sema.typeAbiSize(base_elem_ty);30992 const elem_abi_size_u64 = try sema.typeAbiSize(base_elem_ty);
31049 const elem_abi_size = try sema.usizeCast(block, src, elem_abi_size_u64);30993 const elem_abi_size = try sema.usizeCast(block, src, elem_abi_size_u64);
31050 const elem_idx = try sema.usizeCast(block, src, elem_ptr.index);30994 const elem_idx = try sema.usizeCast(block, src, elem_ptr.index);
31051 return ComptimePtrMutationKit{30995 return .{
31052 .root = parent.root,30996 .root = parent.root,
31053 .pointee = .{ .reinterpret = .{30997 .pointee = .{ .reinterpret = .{
31054 .val_ptr = reinterpret.val_ptr,30998 .val_ptr = reinterpret.val_ptr,
...@@ -31067,56 +31011,68 @@ fn beginComptimePtrMutation(...@@ -31067,56 +31011,68 @@ fn beginComptimePtrMutation(
31067 var parent = try sema.beginComptimePtrMutation(block, src, Value.fromInterned(field_ptr.base), base_child_ty);31011 var parent = try sema.beginComptimePtrMutation(block, src, Value.fromInterned(field_ptr.base), base_child_ty);
31068 switch (parent.pointee) {31012 switch (parent.pointee) {
31069 .opv => unreachable,31013 .opv => unreachable,
31070 .direct => |val_ptr| switch (val_ptr.ip_index) {31014 .direct => |val_ptr| {
31071 .empty_struct => {31015 try val_ptr.unintern(mod, sema.arena, false, false);
31072 const duped = try sema.arena.create(Value);31016 switch (val_ptr.*) {
31073 duped.* = val_ptr.*;31017 .interned,
31074 return beginComptimePtrMutationInner(31018 .eu_payload,
31075 sema,31019 .opt_payload,
31076 block,31020 .repeated,
31077 src,31021 .bytes,
31078 parent.ty.structFieldType(field_index, mod),31022 => unreachable,
31079 duped,31023 .aggregate => |*a| return sema.beginComptimePtrMutationInner(
31080 ptr_elem_ty,
31081 parent.root,
31082 );
31083 },
31084 .none => switch (val_ptr.tag()) {
31085 .aggregate => return beginComptimePtrMutationInner(
31086 sema,
31087 block,31024 block,
31088 src,31025 src,
31089 parent.ty.structFieldType(field_index, mod),31026 parent.ty.structFieldType(field_index, mod),
31090 &val_ptr.castTag(.aggregate).?.data[field_index],31027 &a.elems[field_index],
31091 ptr_elem_ty,31028 ptr_elem_ty,
31092 parent.root,31029 parent.root,
31093 ),31030 ),
31094 .repeated => {31031 .slice => |*s| switch (field_index) {
31095 const arena = sema.arena;31032 Value.slice_ptr_index => return sema.beginComptimePtrMutationInner(
31096
31097 const elems = try arena.alloc(Value, parent.ty.structFieldCount(mod));
31098 @memset(elems, val_ptr.castTag(.repeated).?.data);
31099 val_ptr.* = try Value.Tag.aggregate.create(arena, elems);
31100
31101 return beginComptimePtrMutationInner(
31102 sema,
31103 block,31033 block,
31104 src,31034 src,
31105 parent.ty.structFieldType(field_index, mod),31035 parent.ty.slicePtrFieldType(mod),
31106 &elems[field_index],31036 s.ptr,
31107 ptr_elem_ty,31037 ptr_elem_ty,
31108 parent.root,31038 parent.root,
31109 );31039 ),
31040 Value.slice_len_index => return sema.beginComptimePtrMutationInner(
31041 block,
31042 src,
31043 Type.usize,
31044 s.len,
31045 ptr_elem_ty,
31046 parent.root,
31047 ),
31048 else => unreachable,
31110 },31049 },
31111 .@"union" => {31050 .un => |*un| {
31112 const payload = &val_ptr.castTag(.@"union").?.data;
31113 const layout = base_child_ty.containerLayout(mod);31051 const layout = base_child_ty.containerLayout(mod);
3111431052
31115 const tag_type = base_child_ty.unionTagTypeHypothetical(mod);31053 const tag_type = base_child_ty.unionTagTypeHypothetical(mod);
31116 const hypothetical_tag = try mod.enumValueFieldIndex(tag_type, field_index);31054 const hypothetical_tag = try mod.enumValueFieldIndex(tag_type, field_index);
31117 if (layout == .auto or (payload.tag != null and hypothetical_tag.eql(payload.tag.?, tag_type, mod))) {31055 if (un.tag == .none and un.payload.* == .interned and un.payload.interned == .undef) {
31056 // A union has been initialized to undefined at comptime and now we
31057 // are for the first time setting the payload. We must change the
31058 // tag implicitly.
31059 const payload_ty = parent.ty.structFieldType(field_index, mod);
31060 un.tag = hypothetical_tag.toIntern();
31061 un.payload.* = .{ .interned = try mod.intern(.{ .undef = payload_ty.toIntern() }) };
31062 return beginComptimePtrMutationInner(
31063 sema,
31064 block,
31065 src,
31066 payload_ty,
31067 un.payload,
31068 ptr_elem_ty,
31069 parent.root,
31070 );
31071 }
31072
31073 if (layout == .auto or hypothetical_tag.toIntern() == un.tag) {
31118 // We need to set the active field of the union.31074 // We need to set the active field of the union.
31119 payload.tag = hypothetical_tag;31075 un.tag = hypothetical_tag.toIntern();
3112031076
31121 const field_ty = parent.ty.structFieldType(field_index, mod);31077 const field_ty = parent.ty.structFieldType(field_index, mod);
31122 return beginComptimePtrMutationInner(31078 return beginComptimePtrMutationInner(
...@@ -31124,7 +31080,7 @@ fn beginComptimePtrMutation(...@@ -31124,7 +31080,7 @@ fn beginComptimePtrMutation(
31124 block,31080 block,
31125 src,31081 src,
31126 field_ty,31082 field_ty,
31127 &payload.val,31083 un.payload,
31128 ptr_elem_ty,31084 ptr_elem_ty,
31129 parent.root,31085 parent.root,
31130 );31086 );
...@@ -31132,11 +31088,10 @@ fn beginComptimePtrMutation(...@@ -31132,11 +31088,10 @@ fn beginComptimePtrMutation(
31132 // Writing to a different field (a different or unknown tag is active) requires reinterpreting31088 // Writing to a different field (a different or unknown tag is active) requires reinterpreting
31133 // memory of the entire union, which requires knowing its abiSize.31089 // memory of the entire union, which requires knowing its abiSize.
31134 try sema.resolveTypeLayout(parent.ty);31090 try sema.resolveTypeLayout(parent.ty);
31135
31136 // This union value no longer has a well-defined tag type.31091 // This union value no longer has a well-defined tag type.
31137 // The reinterpretation will read it back out as .none.31092 // The reinterpretation will read it back out as .none.
31138 payload.val = try payload.val.unintern(sema.arena, mod);31093 try un.payload.unintern(mod, sema.arena, false, false);
31139 return ComptimePtrMutationKit{31094 return .{
31140 .root = parent.root,31095 .root = parent.root,
31141 .pointee = .{ .reinterpret = .{31096 .pointee = .{ .reinterpret = .{
31142 .val_ptr = val_ptr,31097 .val_ptr = val_ptr,
...@@ -31147,119 +31102,12 @@ fn beginComptimePtrMutation(...@@ -31147,119 +31102,12 @@ fn beginComptimePtrMutation(
31147 };31102 };
31148 }31103 }
31149 },31104 },
31150 .slice => switch (field_index) {31105 }
31151 Value.slice_ptr_index => return beginComptimePtrMutationInner(
31152 sema,
31153 block,
31154 src,
31155 parent.ty.slicePtrFieldType(mod),
31156 &val_ptr.castTag(.slice).?.data.ptr,
31157 ptr_elem_ty,
31158 parent.root,
31159 ),
31160
31161 Value.slice_len_index => return beginComptimePtrMutationInner(
31162 sema,
31163 block,
31164 src,
31165 Type.usize,
31166 &val_ptr.castTag(.slice).?.data.len,
31167 ptr_elem_ty,
31168 parent.root,
31169 ),
31170
31171 else => unreachable,
31172 },
31173 else => unreachable,
31174 },
31175 else => switch (mod.intern_pool.indexToKey(val_ptr.toIntern())) {
31176 .undef => {
31177 // A struct or union has been initialized to undefined at comptime and now we
31178 // are for the first time setting a field. We must change the representation
31179 // of the struct/union from `undef` to `struct`/`union`.
31180 const arena = sema.arena;
31181
31182 switch (parent.ty.zigTypeTag(mod)) {
31183 .Struct => {
31184 const fields = try arena.alloc(Value, parent.ty.structFieldCount(mod));
31185 for (fields, 0..) |*field, i| field.* = Value.fromInterned((try mod.intern(.{
31186 .undef = parent.ty.structFieldType(i, mod).toIntern(),
31187 })));
31188
31189 val_ptr.* = try Value.Tag.aggregate.create(arena, fields);
31190
31191 return beginComptimePtrMutationInner(
31192 sema,
31193 block,
31194 src,
31195 parent.ty.structFieldType(field_index, mod),
31196 &fields[field_index],
31197 ptr_elem_ty,
31198 parent.root,
31199 );
31200 },
31201 .Union => {
31202 const payload = try arena.create(Value.Payload.Union);
31203 const tag_ty = parent.ty.unionTagTypeHypothetical(mod);
31204 const payload_ty = parent.ty.structFieldType(field_index, mod);
31205 payload.* = .{ .data = .{
31206 .tag = try mod.enumValueFieldIndex(tag_ty, field_index),
31207 .val = Value.fromInterned((try mod.intern(.{ .undef = payload_ty.toIntern() }))),
31208 } };
31209
31210 val_ptr.* = Value.initPayload(&payload.base);
31211
31212 return beginComptimePtrMutationInner(
31213 sema,
31214 block,
31215 src,
31216 payload_ty,
31217 &payload.data.val,
31218 ptr_elem_ty,
31219 parent.root,
31220 );
31221 },
31222 .Pointer => {
31223 assert(parent.ty.isSlice(mod));
31224 const ptr_ty = parent.ty.slicePtrFieldType(mod);
31225 val_ptr.* = try Value.Tag.slice.create(arena, .{
31226 .ptr = Value.fromInterned((try mod.intern(.{ .undef = ptr_ty.toIntern() }))),
31227 .len = Value.fromInterned((try mod.intern(.{ .undef = .usize_type }))),
31228 });
31229
31230 switch (field_index) {
31231 Value.slice_ptr_index => return beginComptimePtrMutationInner(
31232 sema,
31233 block,
31234 src,
31235 ptr_ty,
31236 &val_ptr.castTag(.slice).?.data.ptr,
31237 ptr_elem_ty,
31238 parent.root,
31239 ),
31240 Value.slice_len_index => return beginComptimePtrMutationInner(
31241 sema,
31242 block,
31243 src,
31244 Type.usize,
31245 &val_ptr.castTag(.slice).?.data.len,
31246 ptr_elem_ty,
31247 parent.root,
31248 ),
31249
31250 else => unreachable,
31251 }
31252 },
31253 else => unreachable,
31254 }
31255 },
31256 else => unreachable,
31257 },
31258 },31106 },
31259 .reinterpret => |reinterpret| {31107 .reinterpret => |reinterpret| {
31260 const field_offset_u64 = base_child_ty.structFieldOffset(field_index, mod);31108 const field_offset_u64 = base_child_ty.structFieldOffset(field_index, mod);
31261 const field_offset = try sema.usizeCast(block, src, field_offset_u64);31109 const field_offset = try sema.usizeCast(block, src, field_offset_u64);
31262 return ComptimePtrMutationKit{31110 return .{
31263 .root = parent.root,31111 .root = parent.root,
31264 .pointee = .{ .reinterpret = .{31112 .pointee = .{ .reinterpret = .{
31265 .val_ptr = reinterpret.val_ptr,31113 .val_ptr = reinterpret.val_ptr,
...@@ -31279,7 +31127,7 @@ fn beginComptimePtrMutationInner(...@@ -31279,7 +31127,7 @@ fn beginComptimePtrMutationInner(
31279 block: *Block,31127 block: *Block,
31280 src: LazySrcLoc,31128 src: LazySrcLoc,
31281 decl_ty: Type,31129 decl_ty: Type,
31282 decl_val: *Value,31130 decl_val: *MutableValue,
31283 ptr_elem_ty: Type,31131 ptr_elem_ty: Type,
31284 root: ComptimePtrMutationKit.Root,31132 root: ComptimePtrMutationKit.Root,
31285) CompileError!ComptimePtrMutationKit {31133) CompileError!ComptimePtrMutationKit {
...@@ -31287,7 +31135,13 @@ fn beginComptimePtrMutationInner(...@@ -31287,7 +31135,13 @@ fn beginComptimePtrMutationInner(
31287 const target = mod.getTarget();31135 const target = mod.getTarget();
31288 const coerce_ok = (try sema.coerceInMemoryAllowed(block, ptr_elem_ty, decl_ty, true, target, src, src)) == .ok;31136 const coerce_ok = (try sema.coerceInMemoryAllowed(block, ptr_elem_ty, decl_ty, true, target, src, src)) == .ok;
3128931137
31290 decl_val.* = try decl_val.unintern(sema.arena, mod);31138 const old_decl_val = decl_val.*;
31139 try decl_val.unintern(mod, sema.arena, false, false);
31140 if (decl_val.* == .un and decl_val.un.tag == .none and decl_val.un.payload.* == .interned and decl_val.un.payload.interned == .undef) {
31141 // HACKHACK: undefined union - re-intern it for now
31142 // `unintern` probably should just leave these as is, but I'm leaving it until I rewrite comptime pointer access.
31143 decl_val.* = old_decl_val;
31144 }
3129131145
31292 if (coerce_ok) {31146 if (coerce_ok) {
31293 return ComptimePtrMutationKit{31147 return ComptimePtrMutationKit{
...@@ -31333,21 +31187,16 @@ fn beginComptimePtrMutationInner(...@@ -31333,21 +31187,16 @@ fn beginComptimePtrMutationInner(
31333 };31187 };
31334}31188}
3133531189
31336const TypedValueAndOffset = struct {
31337 tv: TypedValue,
31338 byte_offset: usize,
31339};
31340
31341const ComptimePtrLoadKit = struct {31190const ComptimePtrLoadKit = struct {
31342 /// The Value and Type corresponding to the pointee of the provided pointer.31191 /// The Value and Type corresponding to the pointee of the provided pointer.
31343 /// If a direct dereference is not possible, this is null.31192 /// If a direct dereference is not possible, this is null.
31344 pointee: ?TypedValue,31193 pointee: ?MutableValue,
31345 /// The largest parent Value containing `pointee` and having a well-defined memory layout.31194 /// The largest parent Value containing `pointee` and having a well-defined memory layout.
31346 /// This is used for bitcasting, if direct dereferencing failed (i.e. `pointee` is null).31195 /// This is used for bitcasting, if direct dereferencing failed (i.e. `pointee` is null).
31347 parent: ?TypedValueAndOffset,31196 parent: ?struct {
31348 /// Whether the `pointee` could be mutated by further31197 val: MutableValue,
31349 /// semantic analysis and a copy must be performed.31198 byte_offset: usize,
31350 is_mutable: bool,31199 },
31351 /// If the root decl could not be used as `parent`, this is the type that31200 /// If the root decl could not be used as `parent`, this is the type that
31352 /// caused that by not having a well-defined layout31201 /// caused that by not having a well-defined layout
31353 ty_without_well_defined_layout: ?Type,31202 ty_without_well_defined_layout: ?Type,
...@@ -31374,53 +31223,41 @@ fn beginComptimePtrLoad(...@@ -31374,53 +31223,41 @@ fn beginComptimePtrLoad(
31374 .ptr => |ptr| switch (ptr.addr) {31223 .ptr => |ptr| switch (ptr.addr) {
31375 .decl => |decl_index| blk: {31224 .decl => |decl_index| blk: {
31376 const decl = mod.declPtr(decl_index);31225 const decl = mod.declPtr(decl_index);
31377 const decl_tv = try decl.typedValue();
31378 try sema.declareDependency(.{ .decl_val = decl_index });31226 try sema.declareDependency(.{ .decl_val = decl_index });
31379 if (decl.val.getVariable(mod) != null) return error.RuntimeLoad;31227 if (decl.val.getVariable(mod) != null) return error.RuntimeLoad;
3138031228 const decl_val: MutableValue = .{ .interned = decl.val.toIntern() };
31381 const layout_defined = decl.ty.hasWellDefinedLayout(mod);31229 const layout_defined = decl.typeOf(mod).hasWellDefinedLayout(mod);
31382 break :blk ComptimePtrLoadKit{31230 break :blk ComptimePtrLoadKit{
31383 .parent = if (layout_defined) .{ .tv = decl_tv, .byte_offset = 0 } else null,31231 .parent = if (layout_defined) .{ .val = decl_val, .byte_offset = 0 } else null,
31384 .pointee = decl_tv,31232 .pointee = decl_val,
31385 .is_mutable = false,31233 .ty_without_well_defined_layout = if (!layout_defined) decl.typeOf(mod) else null,
31386 .ty_without_well_defined_layout = if (!layout_defined) decl.ty else null,
31387 };31234 };
31388 },31235 },
31389 .comptime_alloc => |alloc_index| kit: {31236 .comptime_alloc => |alloc_index| kit: {
31390 const alloc = sema.getComptimeAlloc(alloc_index);31237 const alloc = sema.getComptimeAlloc(alloc_index);
31391 const alloc_tv: TypedValue = .{31238 const alloc_ty = alloc.val.typeOf(mod);
31392 .ty = alloc.ty,31239 const layout_defined = alloc_ty.hasWellDefinedLayout(mod);
31393 .val = alloc.val,
31394 };
31395 const layout_defined = alloc.ty.hasWellDefinedLayout(mod);
31396 break :kit .{31240 break :kit .{
31397 .parent = if (layout_defined) .{ .tv = alloc_tv, .byte_offset = 0 } else null,31241 .parent = if (layout_defined) .{ .val = alloc.val, .byte_offset = 0 } else null,
31398 .pointee = alloc_tv,31242 .pointee = alloc.val,
31399 .is_mutable = true,31243 .ty_without_well_defined_layout = if (!layout_defined) alloc_ty else null,
31400 .ty_without_well_defined_layout = if (!layout_defined) alloc.ty else null,
31401 };31244 };
31402 },31245 },
31403 .anon_decl => |anon_decl| blk: {31246 .anon_decl => |anon_decl| blk: {
31404 const decl_val = anon_decl.val;31247 const decl_val = anon_decl.val;
31405 if (Value.fromInterned(decl_val).getVariable(mod) != null) return error.RuntimeLoad;31248 if (Value.fromInterned(decl_val).getVariable(mod) != null) return error.RuntimeLoad;
31406 const decl_ty = Type.fromInterned(ip.typeOf(decl_val));31249 const decl_ty = Type.fromInterned(ip.typeOf(decl_val));
31407 const decl_tv: TypedValue = .{ .ty = decl_ty, .val = Value.fromInterned(decl_val) };31250 const decl_mv: MutableValue = .{ .interned = decl_val };
31408 const layout_defined = decl_ty.hasWellDefinedLayout(mod);31251 const layout_defined = decl_ty.hasWellDefinedLayout(mod);
31409 break :blk ComptimePtrLoadKit{31252 break :blk ComptimePtrLoadKit{
31410 .parent = if (layout_defined) .{ .tv = decl_tv, .byte_offset = 0 } else null,31253 .parent = if (layout_defined) .{ .val = decl_mv, .byte_offset = 0 } else null,
31411 .pointee = decl_tv,31254 .pointee = decl_mv,
31412 .is_mutable = false,
31413 .ty_without_well_defined_layout = if (!layout_defined) decl_ty else null,31255 .ty_without_well_defined_layout = if (!layout_defined) decl_ty else null,
31414 };31256 };
31415 },31257 },
31416 .int => return error.RuntimeLoad,31258 .int => return error.RuntimeLoad,
31417 .eu_payload, .opt_payload => |container_ptr| blk: {31259 .eu_payload, .opt_payload => |container_ptr| blk: {
31418 const container_ty = Type.fromInterned(ip.typeOf(container_ptr)).childType(mod);31260 const container_ty = Type.fromInterned(ip.typeOf(container_ptr)).childType(mod);
31419 const payload_ty = switch (ptr.addr) {
31420 .eu_payload => container_ty.errorUnionPayload(mod),
31421 .opt_payload => container_ty.optionalChild(mod),
31422 else => unreachable,
31423 };
31424 var deref = try sema.beginComptimePtrLoad(block, src, Value.fromInterned(container_ptr), container_ty);31261 var deref = try sema.beginComptimePtrLoad(block, src, Value.fromInterned(container_ptr), container_ty);
3142531262
31426 // eu_payload and opt_payload never have a well-defined layout31263 // eu_payload and opt_payload never have a well-defined layout
...@@ -31429,15 +31266,14 @@ fn beginComptimePtrLoad(...@@ -31429,15 +31266,14 @@ fn beginComptimePtrLoad(
31429 deref.ty_without_well_defined_layout = container_ty;31266 deref.ty_without_well_defined_layout = container_ty;
31430 }31267 }
3143131268
31432 if (deref.pointee) |*tv| {31269 if (deref.pointee) |pointee| {
31270 const pointee_ty = pointee.typeOf(mod);
31433 const coerce_in_mem_ok =31271 const coerce_in_mem_ok =
31434 (try sema.coerceInMemoryAllowed(block, container_ty, tv.ty, false, target, src, src)) == .ok or31272 (try sema.coerceInMemoryAllowed(block, container_ty, pointee_ty, false, target, src, src)) == .ok or
31435 (try sema.coerceInMemoryAllowed(block, tv.ty, container_ty, false, target, src, src)) == .ok;31273 (try sema.coerceInMemoryAllowed(block, pointee_ty, container_ty, false, target, src, src)) == .ok;
31436 if (coerce_in_mem_ok) {31274 if (coerce_in_mem_ok) {
31437 const payload_val = switch (tv.val.ip_index) {31275 deref.pointee = switch (pointee) {
31438 .none => tv.val.cast(Value.Payload.SubValue).?.data,31276 .interned => |ip_index| .{ .interned = switch (ip.indexToKey(ip_index)) {
31439 .null_value => return sema.fail(block, src, "attempt to use null value", .{}),
31440 else => Value.fromInterned(switch (ip.indexToKey(tv.val.toIntern())) {
31441 .error_union => |error_union| switch (error_union.val) {31277 .error_union => |error_union| switch (error_union.val) {
31442 .err_name => |err_name| return sema.fail(31278 .err_name => |err_name| return sema.fail(
31443 block,31279 block,
...@@ -31452,23 +31288,20 @@ fn beginComptimePtrLoad(...@@ -31452,23 +31288,20 @@ fn beginComptimePtrLoad(
31452 else => |payload| payload,31288 else => |payload| payload,
31453 },31289 },
31454 else => unreachable,31290 else => unreachable,
31455 }),31291 } },
31292 .eu_payload, .opt_payload => |p| p.child.*,
31293 else => unreachable,
31456 };31294 };
31457 tv.* = TypedValue{ .ty = payload_ty, .val = payload_val };
31458 break :blk deref;31295 break :blk deref;
31459 }31296 }
31460 }31297 }
31461 deref.pointee = null;31298 deref.pointee = null;
31462 break :blk deref;31299 break :blk deref;
31463 },31300 },
31464 .comptime_field => |comptime_field| blk: {31301 .comptime_field => |field_val| .{
31465 const field_ty = Type.fromInterned(ip.typeOf(comptime_field));31302 .parent = null,
31466 break :blk ComptimePtrLoadKit{31303 .pointee = .{ .interned = field_val },
31467 .parent = null,31304 .ty_without_well_defined_layout = Type.fromInterned(ip.typeOf(field_val)),
31468 .pointee = .{ .ty = field_ty, .val = Value.fromInterned(comptime_field) },
31469 .is_mutable = false,
31470 .ty_without_well_defined_layout = field_ty,
31471 };
31472 },31305 },
31473 .elem => |elem_ptr| blk: {31306 .elem => |elem_ptr| blk: {
31474 const elem_ty = Type.fromInterned(ip.typeOf(elem_ptr.base)).elemType2(mod);31307 const elem_ty = Type.fromInterned(ip.typeOf(elem_ptr.base)).elemType2(mod);
...@@ -31501,30 +31334,37 @@ fn beginComptimePtrLoad(...@@ -31501,30 +31334,37 @@ fn beginComptimePtrLoad(
3150131334
31502 // If we're loading an elem that was derived from a different type31335 // If we're loading an elem that was derived from a different type
31503 // than the true type of the underlying decl, we cannot deref directly31336 // than the true type of the underlying decl, we cannot deref directly
31504 const ty_matches = if (deref.pointee != null and deref.pointee.?.ty.isArrayOrVector(mod)) x: {31337 const ty_matches = if (deref.pointee) |pointee| match: {
31505 const deref_elem_ty = deref.pointee.?.ty.childType(mod);31338 const ty = pointee.typeOf(mod);
31506 break :x (try sema.coerceInMemoryAllowed(block, deref_elem_ty, elem_ty, false, target, src, src)) == .ok or31339 if (!ty.isArrayOrVector(mod)) break :match false;
31507 (try sema.coerceInMemoryAllowed(block, elem_ty, deref_elem_ty, false, target, src, src)) == .ok;31340 const deref_elem_ty = ty.childType(mod);
31341 if ((try sema.coerceInMemoryAllowed(block, deref_elem_ty, elem_ty, false, target, src, src)) == .ok) break :match true;
31342 if ((try sema.coerceInMemoryAllowed(block, elem_ty, deref_elem_ty, false, target, src, src)) == .ok) break :match true;
31343 break :match false;
31508 } else false;31344 } else false;
31509 if (!ty_matches) {31345 if (!ty_matches) {
31510 deref.pointee = null;31346 deref.pointee = null;
31511 break :blk deref;31347 break :blk deref;
31512 }31348 }
3151331349
31514 var array_tv = deref.pointee.?;31350 var array_val = deref.pointee.?;
31515 const check_len = array_tv.ty.arrayLenIncludingSentinel(mod);31351 const check_len = array_val.typeOf(mod).arrayLenIncludingSentinel(mod);
31516 if (maybe_array_ty) |load_ty| {31352 if (maybe_array_ty) |load_ty| {
31517 // It's possible that we're loading a [N]T, in which case we'd like to slice31353 // It's possible that we're loading a [N]T, in which case we'd like to slice
31518 // the pointee array directly from our parent array.31354 // the pointee array directly from our parent array.
31519 if (load_ty.isArrayOrVector(mod) and load_ty.childType(mod).eql(elem_ty, mod)) {31355 if (load_ty.isArrayOrVector(mod) and load_ty.childType(mod).eql(elem_ty, mod)) {
31520 const len = try sema.usizeCast(block, src, load_ty.arrayLenIncludingSentinel(mod));31356 const len = try sema.usizeCast(block, src, load_ty.arrayLenIncludingSentinel(mod));
31521 const elem_idx = try sema.usizeCast(block, src, elem_ptr.index);31357 const elem_idx = try sema.usizeCast(block, src, elem_ptr.index);
31522 deref.pointee = if (elem_ptr.index + len <= check_len) TypedValue{31358 deref.pointee = if (elem_ptr.index + len <= check_len) switch (array_val) {
31523 .ty = try mod.arrayType(.{31359 .aggregate => |a| .{ .aggregate = .{
31524 .len = len,31360 .ty = (try mod.arrayType(.{ .len = len, .child = elem_ty.toIntern() })).toIntern(),
31525 .child = elem_ty.toIntern(),31361 .elems = a.elems[elem_idx..][0..len],
31526 }),31362 } },
31527 .val = try array_tv.val.sliceArray(sema, elem_idx, elem_idx + len),31363 else => .{
31364 .interned = (try (Value.fromInterned(
31365 try array_val.intern(mod, sema.arena),
31366 ).sliceArray(sema, elem_idx, elem_idx + len))).toIntern(),
31367 },
31528 } else null;31368 } else null;
31529 break :blk deref;31369 break :blk deref;
31530 }31370 }
...@@ -31535,18 +31375,12 @@ fn beginComptimePtrLoad(...@@ -31535,18 +31375,12 @@ fn beginComptimePtrLoad(
31535 break :blk deref;31375 break :blk deref;
31536 }31376 }
31537 if (elem_ptr.index == check_len - 1) {31377 if (elem_ptr.index == check_len - 1) {
31538 if (array_tv.ty.sentinel(mod)) |sent| {31378 if (array_val.typeOf(mod).sentinel(mod)) |sent| {
31539 deref.pointee = TypedValue{31379 deref.pointee = .{ .interned = sent.toIntern() };
31540 .ty = elem_ty,
31541 .val = sent,
31542 };
31543 break :blk deref;31380 break :blk deref;
31544 }31381 }
31545 }31382 }
31546 deref.pointee = TypedValue{31383 deref.pointee = try array_val.getElem(mod, @intCast(elem_ptr.index));
31547 .ty = elem_ty,
31548 .val = try array_tv.val.elemValue(mod, @intCast(elem_ptr.index)),
31549 };
31550 break :blk deref;31384 break :blk deref;
31551 },31385 },
31552 .field => |field_ptr| blk: {31386 .field => |field_ptr| blk: {
...@@ -31570,37 +31404,17 @@ fn beginComptimePtrLoad(...@@ -31570,37 +31404,17 @@ fn beginComptimePtrLoad(
31570 deref.ty_without_well_defined_layout = container_ty;31404 deref.ty_without_well_defined_layout = container_ty;
31571 }31405 }
3157231406
31573 const tv = deref.pointee orelse {31407 const pointee = deref.pointee orelse break :blk deref;
31574 deref.pointee = null;31408 const pointee_ty = pointee.typeOf(mod);
31575 break :blk deref;
31576 };
31577 const coerce_in_mem_ok =31409 const coerce_in_mem_ok =
31578 (try sema.coerceInMemoryAllowed(block, container_ty, tv.ty, false, target, src, src)) == .ok or31410 (try sema.coerceInMemoryAllowed(block, container_ty, pointee_ty, false, target, src, src)) == .ok or
31579 (try sema.coerceInMemoryAllowed(block, tv.ty, container_ty, false, target, src, src)) == .ok;31411 (try sema.coerceInMemoryAllowed(block, pointee_ty, container_ty, false, target, src, src)) == .ok;
31580 if (!coerce_in_mem_ok) {31412 if (!coerce_in_mem_ok) {
31581 deref.pointee = null;31413 deref.pointee = null;
31582 break :blk deref;31414 break :blk deref;
31583 }31415 }
3158431416
31585 if (container_ty.isSlice(mod)) {31417 deref.pointee = try pointee.getElem(mod, field_index);
31586 deref.pointee = switch (field_index) {
31587 Value.slice_ptr_index => TypedValue{
31588 .ty = container_ty.slicePtrFieldType(mod),
31589 .val = tv.val.slicePtr(mod),
31590 },
31591 Value.slice_len_index => TypedValue{
31592 .ty = Type.usize,
31593 .val = Value.fromInterned(ip.indexToKey(try tv.val.intern(tv.ty, mod)).slice.len),
31594 },
31595 else => unreachable,
31596 };
31597 } else {
31598 const field_ty = container_ty.structFieldType(field_index, mod);
31599 deref.pointee = TypedValue{
31600 .ty = field_ty,
31601 .val = try tv.val.fieldValue(mod, field_index),
31602 };
31603 }
31604 break :blk deref;31418 break :blk deref;
31605 },31419 },
31606 },31420 },
...@@ -31611,9 +31425,9 @@ fn beginComptimePtrLoad(...@@ -31611,9 +31425,9 @@ fn beginComptimePtrLoad(
31611 else => unreachable,31425 else => unreachable,
31612 };31426 };
3161331427
31614 if (deref.pointee) |tv| {31428 if (deref.pointee) |val| {
31615 if (deref.parent == null and tv.ty.hasWellDefinedLayout(mod)) {31429 if (deref.parent == null and val.typeOf(mod).hasWellDefinedLayout(mod)) {
31616 deref.parent = .{ .tv = tv, .byte_offset = 0 };31430 deref.parent = .{ .val = val, .byte_offset = 0 };
31617 }31431 }
31618 }31432 }
31619 return deref;31433 return deref;
...@@ -31760,16 +31574,11 @@ fn coerceArrayPtrToSlice(...@@ -31760,16 +31574,11 @@ fn coerceArrayPtrToSlice(
31760 if (try sema.resolveValue(inst)) |val| {31574 if (try sema.resolveValue(inst)) |val| {
31761 const ptr_array_ty = sema.typeOf(inst);31575 const ptr_array_ty = sema.typeOf(inst);
31762 const array_ty = ptr_array_ty.childType(mod);31576 const array_ty = ptr_array_ty.childType(mod);
31577 const slice_ptr_ty = dest_ty.slicePtrFieldType(mod);
31578 const slice_ptr = try mod.getCoerced(val, slice_ptr_ty);
31763 const slice_val = try mod.intern(.{ .slice = .{31579 const slice_val = try mod.intern(.{ .slice = .{
31764 .ty = dest_ty.toIntern(),31580 .ty = dest_ty.toIntern(),
31765 .ptr = try mod.intern(.{ .ptr = .{31581 .ptr = slice_ptr.toIntern(),
31766 .ty = dest_ty.slicePtrFieldType(mod).toIntern(),
31767 .addr = switch (mod.intern_pool.indexToKey(val.toIntern())) {
31768 .undef => .{ .int = try mod.intern(.{ .undef = .usize_type }) },
31769 .ptr => |ptr| ptr.addr,
31770 else => unreachable,
31771 },
31772 } }),
31773 .len = (try mod.intValue(Type.usize, array_ty.arrayLen(mod))).toIntern(),31582 .len = (try mod.intValue(Type.usize, array_ty.arrayLen(mod))).toIntern(),
31774 } });31583 } });
31775 return Air.internedToRef(slice_val);31584 return Air.internedToRef(slice_val);
...@@ -31844,7 +31653,7 @@ fn coerceCompatiblePtrs(...@@ -31844,7 +31653,7 @@ fn coerceCompatiblePtrs(
31844 }31653 }
31845 // The comptime Value representation is compatible with both types.31654 // The comptime Value representation is compatible with both types.
31846 return Air.internedToRef(31655 return Air.internedToRef(
31847 (try mod.getCoerced(Value.fromInterned((try val.intern(inst_ty, mod))), dest_ty)).toIntern(),31656 (try mod.getCoerced(val, dest_ty)).toIntern(),
31848 );31657 );
31849 }31658 }
31850 try sema.requireRuntimeBlock(block, inst_src, null);31659 try sema.requireRuntimeBlock(block, inst_src, null);
...@@ -31899,7 +31708,7 @@ fn coerceEnumToUnion(...@@ -31899,7 +31708,7 @@ fn coerceEnumToUnion(
31899 if (try sema.resolveDefinedValue(block, inst_src, enum_tag)) |val| {31708 if (try sema.resolveDefinedValue(block, inst_src, enum_tag)) |val| {
31900 const field_index = union_ty.unionTagFieldIndex(val, sema.mod) orelse {31709 const field_index = union_ty.unionTagFieldIndex(val, sema.mod) orelse {
31901 return sema.fail(block, inst_src, "union '{}' has no tag with value '{}'", .{31710 return sema.fail(block, inst_src, "union '{}' has no tag with value '{}'", .{
31902 union_ty.fmt(sema.mod), val.fmtValue(tag_ty, sema.mod),31711 union_ty.fmt(sema.mod), val.fmtValue(sema.mod),
31903 });31712 });
31904 };31713 };
3190531714
...@@ -32181,7 +31990,7 @@ fn coerceArrayLike(...@@ -32181,7 +31990,7 @@ fn coerceArrayLike(
32181 ref.* = coerced;31990 ref.* = coerced;
32182 if (runtime_src == null) {31991 if (runtime_src == null) {
32183 if (try sema.resolveValue(coerced)) |elem_val| {31992 if (try sema.resolveValue(coerced)) |elem_val| {
32184 val.* = try elem_val.intern(dest_elem_ty, mod);31993 val.* = elem_val.toIntern();
32185 } else {31994 } else {
32186 runtime_src = elem_src;31995 runtime_src = elem_src;
32187 }31996 }
...@@ -32246,7 +32055,7 @@ fn coerceTupleToArray(...@@ -32246,7 +32055,7 @@ fn coerceTupleToArray(
32246 ref.* = coerced;32055 ref.* = coerced;
32247 if (runtime_src == null) {32056 if (runtime_src == null) {
32248 if (try sema.resolveValue(coerced)) |elem_val| {32057 if (try sema.resolveValue(coerced)) |elem_val| {
32249 val.* = try elem_val.intern(dest_elem_ty, mod);32058 val.* = elem_val.toIntern();
32250 } else {32059 } else {
32251 runtime_src = elem_src;32060 runtime_src = elem_src;
32252 }32061 }
...@@ -32650,7 +32459,7 @@ fn optRefValue(sema: *Sema, opt_val: ?Value) !Value {...@@ -32650,7 +32459,7 @@ fn optRefValue(sema: *Sema, opt_val: ?Value) !Value {
32650 return Value.fromInterned((try mod.intern(.{ .opt = .{32459 return Value.fromInterned((try mod.intern(.{ .opt = .{
32651 .ty = (try mod.optionalType(ptr_anyopaque_ty.toIntern())).toIntern(),32460 .ty = (try mod.optionalType(ptr_anyopaque_ty.toIntern())).toIntern(),
32652 .val = if (opt_val) |val| (try mod.getCoerced(32461 .val = if (opt_val) |val| (try mod.getCoerced(
32653 Value.fromInterned((try sema.refValue(val.toIntern()))),32462 Value.fromInterned(try sema.refValue(val.toIntern())),
32654 ptr_anyopaque_ty,32463 ptr_anyopaque_ty,
32655 )).toIntern() else .none,32464 )).toIntern() else .none,
32656 } })));32465 } })));
...@@ -32668,8 +32477,8 @@ fn analyzeDeclRefInner(sema: *Sema, decl_index: InternPool.DeclIndex, analyze_fn...@@ -32668,8 +32477,8 @@ fn analyzeDeclRefInner(sema: *Sema, decl_index: InternPool.DeclIndex, analyze_fn
32668 const mod = sema.mod;32477 const mod = sema.mod;
32669 try sema.ensureDeclAnalyzed(decl_index);32478 try sema.ensureDeclAnalyzed(decl_index);
3267032479
32671 const decl_tv = try mod.declPtr(decl_index).typedValue();32480 const decl_val = try mod.declPtr(decl_index).valueOrFail();
32672 const owner_decl = mod.declPtr(switch (mod.intern_pool.indexToKey(decl_tv.val.toIntern())) {32481 const owner_decl = mod.declPtr(switch (mod.intern_pool.indexToKey(decl_val.toIntern())) {
32673 .variable => |variable| variable.decl,32482 .variable => |variable| variable.decl,
32674 .extern_func => |extern_func| extern_func.decl,32483 .extern_func => |extern_func| extern_func.decl,
32675 .func => |func| func.owner_decl,32484 .func => |func| func.owner_decl,
...@@ -32678,10 +32487,10 @@ fn analyzeDeclRefInner(sema: *Sema, decl_index: InternPool.DeclIndex, analyze_fn...@@ -32678,10 +32487,10 @@ fn analyzeDeclRefInner(sema: *Sema, decl_index: InternPool.DeclIndex, analyze_fn
32678 // TODO: if this is a `decl_ref` of a non-variable decl, only depend on decl type32487 // TODO: if this is a `decl_ref` of a non-variable decl, only depend on decl type
32679 try sema.declareDependency(.{ .decl_val = decl_index });32488 try sema.declareDependency(.{ .decl_val = decl_index });
32680 const ptr_ty = try sema.ptrType(.{32489 const ptr_ty = try sema.ptrType(.{
32681 .child = decl_tv.ty.toIntern(),32490 .child = decl_val.typeOf(mod).toIntern(),
32682 .flags = .{32491 .flags = .{
32683 .alignment = owner_decl.alignment,32492 .alignment = owner_decl.alignment,
32684 .is_const = if (decl_tv.val.getVariable(mod)) |variable| variable.is_const else true,32493 .is_const = if (decl_val.getVariable(mod)) |variable| variable.is_const else true,
32685 .address_space = owner_decl.@"addrspace",32494 .address_space = owner_decl.@"addrspace",
32686 },32495 },
32687 });32496 });
...@@ -32697,12 +32506,10 @@ fn analyzeDeclRefInner(sema: *Sema, decl_index: InternPool.DeclIndex, analyze_fn...@@ -32697,12 +32506,10 @@ fn analyzeDeclRefInner(sema: *Sema, decl_index: InternPool.DeclIndex, analyze_fn
32697fn maybeQueueFuncBodyAnalysis(sema: *Sema, decl_index: InternPool.DeclIndex) !void {32506fn maybeQueueFuncBodyAnalysis(sema: *Sema, decl_index: InternPool.DeclIndex) !void {
32698 const mod = sema.mod;32507 const mod = sema.mod;
32699 const decl = mod.declPtr(decl_index);32508 const decl = mod.declPtr(decl_index);
32700 const tv = try decl.typedValue();32509 const decl_val = try decl.valueOrFail();
32701 if (tv.ty.zigTypeTag(mod) != .Fn) return;32510 if (!mod.intern_pool.isFuncBody(decl_val.toIntern())) return;
32702 if (!try sema.fnHasRuntimeBits(tv.ty)) return;32511 if (!try sema.fnHasRuntimeBits(decl_val.typeOf(mod))) return;
32703 const func_index = tv.val.toIntern();32512 try mod.ensureFuncBodyAnalysisQueued(decl_val.toIntern());
32704 if (!mod.intern_pool.isFuncBody(func_index)) return; // undef or extern function
32705 try mod.ensureFuncBodyAnalysisQueued(func_index);
32706}32513}
3270732514
32708fn analyzeRef(32515fn analyzeRef(
...@@ -32839,7 +32646,7 @@ fn analyzeSliceLen(...@@ -32839,7 +32646,7 @@ fn analyzeSliceLen(
32839 if (slice_val.isUndef(mod)) {32646 if (slice_val.isUndef(mod)) {
32840 return mod.undefRef(Type.usize);32647 return mod.undefRef(Type.usize);
32841 }32648 }
32842 return mod.intRef(Type.usize, slice_val.sliceLen(sema.mod));32649 return mod.intRef(Type.usize, try slice_val.sliceLen(sema));
32843 }32650 }
32844 try sema.requireRuntimeBlock(block, src, null);32651 try sema.requireRuntimeBlock(block, src, null);
32845 return block.addTyOp(.slice_len, Type.usize, slice_inst);32652 return block.addTyOp(.slice_len, Type.usize, slice_inst);
...@@ -33121,8 +32928,8 @@ fn analyzeSlice(...@@ -33121,8 +32928,8 @@ fn analyzeSlice(
33121 msg,32928 msg,
33122 "expected '{}', found '{}'",32929 "expected '{}', found '{}'",
33123 .{32930 .{
33124 Value.zero_comptime_int.fmtValue(Type.comptime_int, mod),32931 Value.zero_comptime_int.fmtValue(mod),
33125 start_value.fmtValue(Type.comptime_int, mod),32932 start_value.fmtValue(mod),
33126 },32933 },
33127 );32934 );
33128 break :msg msg;32935 break :msg msg;
...@@ -33138,8 +32945,8 @@ fn analyzeSlice(...@@ -33138,8 +32945,8 @@ fn analyzeSlice(
33138 msg,32945 msg,
33139 "expected '{}', found '{}'",32946 "expected '{}', found '{}'",
33140 .{32947 .{
33141 Value.one_comptime_int.fmtValue(Type.comptime_int, mod),32948 Value.one_comptime_int.fmtValue(mod),
33142 end_value.fmtValue(Type.comptime_int, mod),32949 end_value.fmtValue(mod),
33143 },32950 },
33144 );32951 );
33145 break :msg msg;32952 break :msg msg;
...@@ -33152,7 +32959,7 @@ fn analyzeSlice(...@@ -33152,7 +32959,7 @@ fn analyzeSlice(
33152 block,32959 block,
33153 end_src,32960 end_src,
33154 "end index {} out of bounds for slice of single-item pointer",32961 "end index {} out of bounds for slice of single-item pointer",
33155 .{end_value.fmtValue(Type.comptime_int, mod)},32962 .{end_value.fmtValue(mod)},
33156 );32963 );
33157 }32964 }
33158 }32965 }
...@@ -33247,8 +33054,8 @@ fn analyzeSlice(...@@ -33247,8 +33054,8 @@ fn analyzeSlice(
33247 end_src,33054 end_src,
33248 "end index {} out of bounds for array of length {}{s}",33055 "end index {} out of bounds for array of length {}{s}",
33249 .{33056 .{
33250 end_val.fmtValue(Type.usize, mod),33057 end_val.fmtValue(mod),
33251 len_val.fmtValue(Type.usize, mod),33058 len_val.fmtValue(mod),
33252 sentinel_label,33059 sentinel_label,
33253 },33060 },
33254 );33061 );
...@@ -33278,7 +33085,7 @@ fn analyzeSlice(...@@ -33278,7 +33085,7 @@ fn analyzeSlice(
33278 return sema.fail(block, src, "slice of undefined", .{});33085 return sema.fail(block, src, "slice of undefined", .{});
33279 }33086 }
33280 const has_sentinel = slice_ty.sentinel(mod) != null;33087 const has_sentinel = slice_ty.sentinel(mod) != null;
33281 const slice_len = slice_val.sliceLen(mod);33088 const slice_len = try slice_val.sliceLen(sema);
33282 const len_plus_sent = slice_len + @intFromBool(has_sentinel);33089 const len_plus_sent = slice_len + @intFromBool(has_sentinel);
33283 const slice_len_val_with_sentinel = try mod.intValue(Type.usize, len_plus_sent);33090 const slice_len_val_with_sentinel = try mod.intValue(Type.usize, len_plus_sent);
33284 if (!(try sema.compareAll(end_val, .lte, slice_len_val_with_sentinel, Type.usize))) {33091 if (!(try sema.compareAll(end_val, .lte, slice_len_val_with_sentinel, Type.usize))) {
...@@ -33292,8 +33099,8 @@ fn analyzeSlice(...@@ -33292,8 +33099,8 @@ fn analyzeSlice(
33292 end_src,33099 end_src,
33293 "end index {} out of bounds for slice of length {d}{s}",33100 "end index {} out of bounds for slice of length {d}{s}",
33294 .{33101 .{
33295 end_val.fmtValue(Type.usize, mod),33102 end_val.fmtValue(mod),
33296 slice_val.sliceLen(mod),33103 try slice_val.sliceLen(sema),
33297 sentinel_label,33104 sentinel_label,
33298 },33105 },
33299 );33106 );
...@@ -33352,8 +33159,8 @@ fn analyzeSlice(...@@ -33352,8 +33159,8 @@ fn analyzeSlice(
33352 start_src,33159 start_src,
33353 "start index {} is larger than end index {}",33160 "start index {} is larger than end index {}",
33354 .{33161 .{
33355 start_val.fmtValue(Type.usize, mod),33162 start_val.fmtValue(mod),
33356 end_val.fmtValue(Type.usize, mod),33163 end_val.fmtValue(mod),
33357 },33164 },
33358 );33165 );
33359 }33166 }
...@@ -33391,8 +33198,8 @@ fn analyzeSlice(...@@ -33391,8 +33198,8 @@ fn analyzeSlice(
33391 const msg = try sema.errMsg(block, src, "value in memory does not match slice sentinel", .{});33198 const msg = try sema.errMsg(block, src, "value in memory does not match slice sentinel", .{});
33392 errdefer msg.destroy(sema.gpa);33199 errdefer msg.destroy(sema.gpa);
33393 try sema.errNote(block, src, msg, "expected '{}', found '{}'", .{33200 try sema.errNote(block, src, msg, "expected '{}', found '{}'", .{
33394 expected_sentinel.fmtValue(elem_ty, mod),33201 expected_sentinel.fmtValue(mod),
33395 actual_sentinel.fmtValue(elem_ty, mod),33202 actual_sentinel.fmtValue(mod),
33396 });33203 });
3339733204
33398 break :msg msg;33205 break :msg msg;
...@@ -33483,10 +33290,7 @@ fn analyzeSlice(...@@ -33483,10 +33290,7 @@ fn analyzeSlice(
33483 };33290 };
3348433291
33485 if (!new_ptr_val.isUndef(mod)) {33292 if (!new_ptr_val.isUndef(mod)) {
33486 return Air.internedToRef((try mod.getCoerced(33293 return Air.internedToRef((try mod.getCoerced(new_ptr_val, return_ty)).toIntern());
33487 Value.fromInterned((try new_ptr_val.intern(new_ptr_ty, mod))),
33488 return_ty,
33489 )).toIntern());
33490 }33294 }
3349133295
33492 // Special case: @as([]i32, undefined)[x..x]33296 // Special case: @as([]i32, undefined)[x..x]
...@@ -33525,7 +33329,7 @@ fn analyzeSlice(...@@ -33525,7 +33329,7 @@ fn analyzeSlice(
33525 if (try sema.resolveDefinedValue(block, src, ptr_or_slice)) |slice_val| {33329 if (try sema.resolveDefinedValue(block, src, ptr_or_slice)) |slice_val| {
33526 // we don't need to add one for sentinels because the33330 // we don't need to add one for sentinels because the
33527 // underlying value data includes the sentinel33331 // underlying value data includes the sentinel
33528 break :blk try mod.intRef(Type.usize, slice_val.sliceLen(mod));33332 break :blk try mod.intRef(Type.usize, try slice_val.sliceLen(sema));
33529 }33333 }
3353033334
33531 const slice_len_inst = try block.addTyOp(.slice_len, Type.usize, ptr_or_slice);33335 const slice_len_inst = try block.addTyOp(.slice_len, Type.usize, ptr_or_slice);
...@@ -33998,7 +33802,7 @@ fn wrapErrorUnionPayload(...@@ -33998,7 +33802,7 @@ fn wrapErrorUnionPayload(
33998 if (try sema.resolveValue(coerced)) |val| {33802 if (try sema.resolveValue(coerced)) |val| {
33999 return Air.internedToRef((try mod.intern(.{ .error_union = .{33803 return Air.internedToRef((try mod.intern(.{ .error_union = .{
34000 .ty = dest_ty.toIntern(),33804 .ty = dest_ty.toIntern(),
34001 .val = .{ .payload = try val.intern(dest_payload_ty, mod) },33805 .val = .{ .payload = val.toIntern() },
34002 } })));33806 } })));
34003 }33807 }
34004 try sema.requireRuntimeBlock(block, inst_src, null);33808 try sema.requireRuntimeBlock(block, inst_src, null);
...@@ -36611,7 +36415,7 @@ fn resolveInferredErrorSet(...@@ -36611,7 +36415,7 @@ fn resolveInferredErrorSet(
36611 // inferred error sets, each call gets an adhoc InferredErrorSet object, which36415 // inferred error sets, each call gets an adhoc InferredErrorSet object, which
36612 // has no corresponding function body.36416 // has no corresponding function body.
36613 const ies_func_owner_decl = mod.declPtr(func.owner_decl);36417 const ies_func_owner_decl = mod.declPtr(func.owner_decl);
36614 const ies_func_info = mod.typeToFunc(ies_func_owner_decl.ty).?;36418 const ies_func_info = mod.typeToFunc(ies_func_owner_decl.typeOf(mod)).?;
36615 // if ies declared by a inline function with generic return type, the return_type should be generic_poison,36419 // if ies declared by a inline function with generic return type, the return_type should be generic_poison,
36616 // because inline function does not create a new declaration, and the ies has been filled with analyzeCall,36420 // because inline function does not create a new declaration, and the ies has been filled with analyzeCall,
36617 // so here we can simply skip this case.36421 // so here we can simply skip this case.
...@@ -37174,15 +36978,14 @@ fn semaStructFieldInits(...@@ -37174,15 +36978,14 @@ fn semaStructFieldInits(
37174 });36978 });
37175 };36979 };
3717636980
37177 const field_init = try default_val.intern(field_ty, mod);36981 if (default_val.canMutateComptimeVarState(mod)) {
37178 if (Value.fromInterned(field_init).canMutateComptimeVarState(mod)) {
37179 const init_src = mod.fieldSrcLoc(decl_index, .{36982 const init_src = mod.fieldSrcLoc(decl_index, .{
37180 .index = field_i,36983 .index = field_i,
37181 .range = .value,36984 .range = .value,
37182 }).lazy;36985 }).lazy;
37183 return sema.fail(&block_scope, init_src, "field default value contains reference to comptime-mutable memory", .{});36986 return sema.fail(&block_scope, init_src, "field default value contains reference to comptime-mutable memory", .{});
37184 }36987 }
37185 struct_type.field_inits.get(ip)[field_i] = field_init;36988 struct_type.field_inits.get(ip)[field_i] = default_val.toIntern();
37186 }36989 }
37187 }36990 }
37188}36991}
...@@ -37410,7 +37213,7 @@ fn semaUnionFields(mod: *Module, arena: Allocator, union_type: InternPool.Loaded...@@ -37410,7 +37213,7 @@ fn semaUnionFields(mod: *Module, arena: Allocator, union_type: InternPool.Loaded
37410 const field_src = mod.fieldSrcLoc(union_type.decl, .{ .index = field_i }).lazy;37213 const field_src = mod.fieldSrcLoc(union_type.decl, .{ .index = field_i }).lazy;
37411 const other_field_src = mod.fieldSrcLoc(union_type.decl, .{ .index = gop.index }).lazy;37214 const other_field_src = mod.fieldSrcLoc(union_type.decl, .{ .index = gop.index }).lazy;
37412 const msg = msg: {37215 const msg = msg: {
37413 const msg = try sema.errMsg(&block_scope, field_src, "enum tag value {} already taken", .{enum_tag_val.fmtValue(int_tag_ty, mod)});37216 const msg = try sema.errMsg(&block_scope, field_src, "enum tag value {} already taken", .{enum_tag_val.fmtValue(mod)});
37414 errdefer msg.destroy(gpa);37217 errdefer msg.destroy(gpa);
37415 try sema.errNote(&block_scope, other_field_src, msg, "other occurrence here", .{});37218 try sema.errNote(&block_scope, other_field_src, msg, "other occurrence here", .{});
37416 break :msg msg;37219 break :msg msg;
...@@ -37607,10 +37410,12 @@ fn generateUnionTagTypeNumbered(...@@ -37607,10 +37410,12 @@ fn generateUnionTagTypeNumbered(
37607 errdefer mod.destroyDecl(new_decl_index);37410 errdefer mod.destroyDecl(new_decl_index);
37608 const fqn = try union_owner_decl.fullyQualifiedName(mod);37411 const fqn = try union_owner_decl.fullyQualifiedName(mod);
37609 const name = try ip.getOrPutStringFmt(gpa, "@typeInfo({}).Union.tag_type.?", .{fqn.fmt(ip)});37412 const name = try ip.getOrPutStringFmt(gpa, "@typeInfo({}).Union.tag_type.?", .{fqn.fmt(ip)});
37610 try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, .{37413 try mod.initNewAnonDecl(
37611 .ty = Type.noreturn,37414 new_decl_index,
37612 .val = Value.@"unreachable",37415 src_decl.src_line,
37613 }, name);37416 Value.@"unreachable",
37417 name,
37418 );
37614 errdefer mod.abortAnonDecl(new_decl_index);37419 errdefer mod.abortAnonDecl(new_decl_index);
3761537420
37616 const new_decl = mod.declPtr(new_decl_index);37421 const new_decl = mod.declPtr(new_decl_index);
...@@ -37629,7 +37434,6 @@ fn generateUnionTagTypeNumbered(...@@ -37629,7 +37434,6 @@ fn generateUnionTagTypeNumbered(
37629 .tag_mode = .explicit,37434 .tag_mode = .explicit,
37630 });37435 });
3763137436
37632 new_decl.ty = Type.type;
37633 new_decl.val = Value.fromInterned(enum_ty);37437 new_decl.val = Value.fromInterned(enum_ty);
3763437438
37635 try mod.finalizeAnonDecl(new_decl_index);37439 try mod.finalizeAnonDecl(new_decl_index);
...@@ -37652,10 +37456,12 @@ fn generateUnionTagTypeSimple(...@@ -37652,10 +37456,12 @@ fn generateUnionTagTypeSimple(
37652 const new_decl_index = try mod.allocateNewDecl(block.namespace, src_decl.src_node);37456 const new_decl_index = try mod.allocateNewDecl(block.namespace, src_decl.src_node);
37653 errdefer mod.destroyDecl(new_decl_index);37457 errdefer mod.destroyDecl(new_decl_index);
37654 const name = try ip.getOrPutStringFmt(gpa, "@typeInfo({}).Union.tag_type.?", .{fqn.fmt(ip)});37458 const name = try ip.getOrPutStringFmt(gpa, "@typeInfo({}).Union.tag_type.?", .{fqn.fmt(ip)});
37655 try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, .{37459 try mod.initNewAnonDecl(
37656 .ty = Type.noreturn,37460 new_decl_index,
37657 .val = Value.@"unreachable",37461 src_decl.src_line,
37658 }, name);37462 Value.@"unreachable",
37463 name,
37464 );
37659 mod.declPtr(new_decl_index).name_fully_qualified = true;37465 mod.declPtr(new_decl_index).name_fully_qualified = true;
37660 break :new_decl_index new_decl_index;37466 break :new_decl_index new_decl_index;
37661 };37467 };
...@@ -37675,7 +37481,6 @@ fn generateUnionTagTypeSimple(...@@ -37675,7 +37481,6 @@ fn generateUnionTagTypeSimple(
3767537481
37676 const new_decl = mod.declPtr(new_decl_index);37482 const new_decl = mod.declPtr(new_decl_index);
37677 new_decl.owns_tv = true;37483 new_decl.owns_tv = true;
37678 new_decl.ty = Type.type;
37679 new_decl.val = Value.fromInterned(enum_ty);37484 new_decl.val = Value.fromInterned(enum_ty);
3768037485
37681 try mod.finalizeAnonDecl(new_decl_index);37486 try mod.finalizeAnonDecl(new_decl_index);
...@@ -37991,7 +37796,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {...@@ -37991,7 +37796,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
37991 return sema.failWithOwnedErrorMsg(null, msg);37796 return sema.failWithOwnedErrorMsg(null, msg);
37992 }37797 }
37993 if (try sema.typeHasOnePossibleValue(field_ty)) |field_opv| {37798 if (try sema.typeHasOnePossibleValue(field_ty)) |field_opv| {
37994 field_val.* = try field_opv.intern(field_ty, mod);37799 field_val.* = field_opv.toIntern();
37995 } else return null;37800 } else return null;
37996 }37801 }
3799737802
...@@ -38290,17 +38095,18 @@ fn pointerDerefExtra(sema: *Sema, block: *Block, src: LazySrcLoc, ptr_val: Value...@@ -38290,17 +38095,18 @@ fn pointerDerefExtra(sema: *Sema, block: *Block, src: LazySrcLoc, ptr_val: Value
38290 else => |e| return e,38095 else => |e| return e,
38291 };38096 };
3829238097
38293 if (deref.pointee) |tv| {38098 if (deref.pointee) |pointee| {
38099 const uncoerced_val = Value.fromInterned(try pointee.intern(mod, sema.arena));
38100 const ty = Type.fromInterned(mod.intern_pool.typeOf(uncoerced_val.toIntern()));
38294 const coerce_in_mem_ok =38101 const coerce_in_mem_ok =
38295 (try sema.coerceInMemoryAllowed(block, load_ty, tv.ty, false, target, src, src)) == .ok or38102 (try sema.coerceInMemoryAllowed(block, load_ty, ty, false, target, src, src)) == .ok or
38296 (try sema.coerceInMemoryAllowed(block, tv.ty, load_ty, false, target, src, src)) == .ok;38103 (try sema.coerceInMemoryAllowed(block, ty, load_ty, false, target, src, src)) == .ok;
38297 if (coerce_in_mem_ok) {38104 if (coerce_in_mem_ok) {
38298 // We have a Value that lines up in virtual memory exactly with what we want to load,38105 // We have a Value that lines up in virtual memory exactly with what we want to load,
38299 // and it is in-memory coercible to load_ty. It may be returned without modifications.38106 // and it is in-memory coercible to load_ty. It may be returned without modifications.
38300 // Move mutable decl values to the InternPool and assert other decls are already in38107 // Move mutable decl values to the InternPool and assert other decls are already in
38301 // the InternPool.38108 // the InternPool.
38302 const uncoerced_val = if (deref.is_mutable) try tv.val.intern(tv.ty, mod) else tv.val.toIntern();38109 const coerced_val = try mod.getCoerced(uncoerced_val, load_ty);
38303 const coerced_val = try mod.getCoerced(Value.fromInterned(uncoerced_val), load_ty);
38304 return .{ .val = coerced_val };38110 return .{ .val = coerced_val };
38305 }38111 }
38306 }38112 }
...@@ -38314,21 +38120,35 @@ fn pointerDerefExtra(sema: *Sema, block: *Block, src: LazySrcLoc, ptr_val: Value...@@ -38314,21 +38120,35 @@ fn pointerDerefExtra(sema: *Sema, block: *Block, src: LazySrcLoc, ptr_val: Value
38314 const load_sz = try sema.typeAbiSize(load_ty);38120 const load_sz = try sema.typeAbiSize(load_ty);
3831538121
38316 // Try the smaller bit-cast first, since that's more efficient than using the larger `parent`38122 // Try the smaller bit-cast first, since that's more efficient than using the larger `parent`
38317 if (deref.pointee) |tv| if (load_sz <= try sema.typeAbiSize(tv.ty))38123 if (deref.pointee) |pointee| {
38318 return DerefResult{ .val = (try sema.bitCastVal(block, src, tv.val, tv.ty, load_ty, 0)) orelse return .runtime_load };38124 const val_ip_index = try pointee.intern(mod, sema.arena);
38125 const val = Value.fromInterned(val_ip_index);
38126 const ty = Type.fromInterned(mod.intern_pool.typeOf(val_ip_index));
38127 if (load_sz <= try sema.typeAbiSize(ty)) {
38128 return .{ .val = (try sema.bitCastVal(block, src, val, ty, load_ty, 0)) orelse return .runtime_load };
38129 }
38130 }
3831938131
38320 // If that fails, try to bit-cast from the largest parent value with a well-defined layout38132 // If that fails, try to bit-cast from the largest parent value with a well-defined layout
38321 if (deref.parent) |parent| if (load_sz + parent.byte_offset <= try sema.typeAbiSize(parent.tv.ty))38133 if (deref.parent) |parent| {
38322 return DerefResult{ .val = (try sema.bitCastVal(block, src, parent.tv.val, parent.tv.ty, load_ty, parent.byte_offset)) orelse return .runtime_load };38134 const parent_ip_index = try parent.val.intern(mod, sema.arena);
38135 const parent_val = Value.fromInterned(parent_ip_index);
38136 const parent_ty = Type.fromInterned(mod.intern_pool.typeOf(parent_ip_index));
38137 if (load_sz + parent.byte_offset <= try sema.typeAbiSize(parent_ty)) {
38138 return .{ .val = (try sema.bitCastVal(block, src, parent_val, parent_ty, load_ty, parent.byte_offset)) orelse return .runtime_load };
38139 }
38140 }
3832338141
38324 if (deref.ty_without_well_defined_layout) |bad_ty| {38142 if (deref.ty_without_well_defined_layout) |bad_ty| {
38325 // We got no parent for bit-casting, or the parent we got was too small. Either way, the problem38143 // We got no parent for bit-casting, or the parent we got was too small. Either way, the problem
38326 // is that some type we encountered when de-referencing does not have a well-defined layout.38144 // is that some type we encountered when de-referencing does not have a well-defined layout.
38327 return DerefResult{ .needed_well_defined = bad_ty };38145 return .{ .needed_well_defined = bad_ty };
38328 } else {38146 } else {
38329 // If all encountered types had well-defined layouts, the parent is the root decl and it just38147 // If all encountered types had well-defined layouts, the parent is the root decl and it just
38330 // wasn't big enough for the load.38148 // wasn't big enough for the load.
38331 return DerefResult{ .out_of_bounds = deref.parent.?.tv.ty };38149 const parent_ip_index = try deref.parent.?.val.intern(mod, sema.arena);
38150 const parent_ty = Type.fromInterned(mod.intern_pool.typeOf(parent_ip_index));
38151 return .{ .out_of_bounds = parent_ty };
38332 }38152 }
38333}38153}
3833438154
...@@ -38530,7 +38350,7 @@ fn intAddInner(sema: *Sema, lhs: Value, rhs: Value, ty: Type, overflow_idx: *usi...@@ -38530,7 +38350,7 @@ fn intAddInner(sema: *Sema, lhs: Value, rhs: Value, ty: Type, overflow_idx: *usi
38530 },38350 },
38531 else => |e| return e,38351 else => |e| return e,
38532 };38352 };
38533 scalar.* = try val.intern(scalar_ty, mod);38353 scalar.* = val.toIntern();
38534 }38354 }
38535 return Value.fromInterned((try mod.intern(.{ .aggregate = .{38355 return Value.fromInterned((try mod.intern(.{ .aggregate = .{
38536 .ty = ty.toIntern(),38356 .ty = ty.toIntern(),
...@@ -38620,7 +38440,7 @@ fn intSubInner(sema: *Sema, lhs: Value, rhs: Value, ty: Type, overflow_idx: *usi...@@ -38620,7 +38440,7 @@ fn intSubInner(sema: *Sema, lhs: Value, rhs: Value, ty: Type, overflow_idx: *usi
38620 },38440 },
38621 else => |e| return e,38441 else => |e| return e,
38622 };38442 };
38623 scalar.* = try val.intern(scalar_ty, mod);38443 scalar.* = val.toIntern();
38624 }38444 }
38625 return Value.fromInterned((try mod.intern(.{ .aggregate = .{38445 return Value.fromInterned((try mod.intern(.{ .aggregate = .{
38626 .ty = ty.toIntern(),38446 .ty = ty.toIntern(),
...@@ -38690,8 +38510,8 @@ fn intSubWithOverflow(...@@ -38690,8 +38510,8 @@ fn intSubWithOverflow(
38690 const lhs_elem = try lhs.elemValue(sema.mod, i);38510 const lhs_elem = try lhs.elemValue(sema.mod, i);
38691 const rhs_elem = try rhs.elemValue(sema.mod, i);38511 const rhs_elem = try rhs.elemValue(sema.mod, i);
38692 const of_math_result = try sema.intSubWithOverflowScalar(lhs_elem, rhs_elem, scalar_ty);38512 const of_math_result = try sema.intSubWithOverflowScalar(lhs_elem, rhs_elem, scalar_ty);
38693 of.* = try of_math_result.overflow_bit.intern(Type.u1, mod);38513 of.* = of_math_result.overflow_bit.toIntern();
38694 scalar.* = try of_math_result.wrapped_result.intern(scalar_ty, mod);38514 scalar.* = of_math_result.wrapped_result.toIntern();
38695 }38515 }
38696 return Value.OverflowArithmeticResult{38516 return Value.OverflowArithmeticResult{
38697 .overflow_bit = Value.fromInterned((try mod.intern(.{ .aggregate = .{38517 .overflow_bit = Value.fromInterned((try mod.intern(.{ .aggregate = .{
...@@ -38746,19 +38566,17 @@ fn intFromFloat(...@@ -38746,19 +38566,17 @@ fn intFromFloat(
38746) CompileError!Value {38566) CompileError!Value {
38747 const mod = sema.mod;38567 const mod = sema.mod;
38748 if (float_ty.zigTypeTag(mod) == .Vector) {38568 if (float_ty.zigTypeTag(mod) == .Vector) {
38749 const elem_ty = float_ty.scalarType(mod);
38750 const result_data = try sema.arena.alloc(InternPool.Index, float_ty.vectorLen(mod));38569 const result_data = try sema.arena.alloc(InternPool.Index, float_ty.vectorLen(mod));
38751 const scalar_ty = int_ty.scalarType(mod);
38752 for (result_data, 0..) |*scalar, i| {38570 for (result_data, 0..) |*scalar, i| {
38753 const elem_val = try val.elemValue(sema.mod, i);38571 const elem_val = try val.elemValue(sema.mod, i);
38754 scalar.* = try (try sema.intFromFloatScalar(block, src, elem_val, elem_ty, int_ty.scalarType(mod), mode)).intern(scalar_ty, mod);38572 scalar.* = (try sema.intFromFloatScalar(block, src, elem_val, int_ty.scalarType(mod), mode)).toIntern();
38755 }38573 }
38756 return Value.fromInterned((try mod.intern(.{ .aggregate = .{38574 return Value.fromInterned((try mod.intern(.{ .aggregate = .{
38757 .ty = int_ty.toIntern(),38575 .ty = int_ty.toIntern(),
38758 .storage = .{ .elems = result_data },38576 .storage = .{ .elems = result_data },
38759 } })));38577 } })));
38760 }38578 }
38761 return sema.intFromFloatScalar(block, src, val, float_ty, int_ty, mode);38579 return sema.intFromFloatScalar(block, src, val, int_ty, mode);
38762}38580}
3876338581
38764// float is expected to be finite and non-NaN38582// float is expected to be finite and non-NaN
...@@ -38791,7 +38609,6 @@ fn intFromFloatScalar(...@@ -38791,7 +38609,6 @@ fn intFromFloatScalar(
38791 block: *Block,38609 block: *Block,
38792 src: LazySrcLoc,38610 src: LazySrcLoc,
38793 val: Value,38611 val: Value,
38794 float_ty: Type,
38795 int_ty: Type,38612 int_ty: Type,
38796 mode: IntFromFloatMode,38613 mode: IntFromFloatMode,
38797) CompileError!Value {38614) CompileError!Value {
...@@ -38803,7 +38620,7 @@ fn intFromFloatScalar(...@@ -38803,7 +38620,7 @@ fn intFromFloatScalar(
38803 block,38620 block,
38804 src,38621 src,
38805 "fractional component prevents float value '{}' from coercion to type '{}'",38622 "fractional component prevents float value '{}' from coercion to type '{}'",
38806 .{ val.fmtValue(float_ty, mod), int_ty.fmt(mod) },38623 .{ val.fmtValue(mod), int_ty.fmt(mod) },
38807 );38624 );
3880838625
38809 const float = val.toFloat(f128, mod);38626 const float = val.toFloat(f128, mod);
...@@ -38825,7 +38642,7 @@ fn intFromFloatScalar(...@@ -38825,7 +38642,7 @@ fn intFromFloatScalar(
3882538642
38826 if (!(try sema.intFitsInType(cti_result, int_ty, null))) {38643 if (!(try sema.intFitsInType(cti_result, int_ty, null))) {
38827 return sema.fail(block, src, "float value '{}' cannot be stored in integer type '{}'", .{38644 return sema.fail(block, src, "float value '{}' cannot be stored in integer type '{}'", .{
38828 val.fmtValue(float_ty, sema.mod), int_ty.fmt(sema.mod),38645 val.fmtValue(sema.mod), int_ty.fmt(sema.mod),
38829 });38646 });
38830 }38647 }
38831 return mod.getCoerced(cti_result, int_ty);38648 return mod.getCoerced(cti_result, int_ty);
...@@ -38944,8 +38761,8 @@ fn intAddWithOverflow(...@@ -38944,8 +38761,8 @@ fn intAddWithOverflow(
38944 const lhs_elem = try lhs.elemValue(sema.mod, i);38761 const lhs_elem = try lhs.elemValue(sema.mod, i);
38945 const rhs_elem = try rhs.elemValue(sema.mod, i);38762 const rhs_elem = try rhs.elemValue(sema.mod, i);
38946 const of_math_result = try sema.intAddWithOverflowScalar(lhs_elem, rhs_elem, scalar_ty);38763 const of_math_result = try sema.intAddWithOverflowScalar(lhs_elem, rhs_elem, scalar_ty);
38947 of.* = try of_math_result.overflow_bit.intern(Type.u1, mod);38764 of.* = of_math_result.overflow_bit.toIntern();
38948 scalar.* = try of_math_result.wrapped_result.intern(scalar_ty, mod);38765 scalar.* = of_math_result.wrapped_result.toIntern();
38949 }38766 }
38950 return Value.OverflowArithmeticResult{38767 return Value.OverflowArithmeticResult{
38951 .overflow_bit = Value.fromInterned((try mod.intern(.{ .aggregate = .{38768 .overflow_bit = Value.fromInterned((try mod.intern(.{ .aggregate = .{
...@@ -39055,7 +38872,7 @@ fn compareVector(...@@ -39055,7 +38872,7 @@ fn compareVector(
39055 const lhs_elem = try lhs.elemValue(sema.mod, i);38872 const lhs_elem = try lhs.elemValue(sema.mod, i);
39056 const rhs_elem = try rhs.elemValue(sema.mod, i);38873 const rhs_elem = try rhs.elemValue(sema.mod, i);
39057 const res_bool = try sema.compareScalar(lhs_elem, op, rhs_elem, ty.scalarType(mod));38874 const res_bool = try sema.compareScalar(lhs_elem, op, rhs_elem, ty.scalarType(mod));
39058 scalar.* = try Value.makeBool(res_bool).intern(Type.bool, mod);38875 scalar.* = Value.makeBool(res_bool).toIntern();
39059 }38876 }
39060 return Value.fromInterned((try mod.intern(.{ .aggregate = .{38877 return Value.fromInterned((try mod.intern(.{ .aggregate = .{
39061 .ty = (try mod.vectorType(.{ .len = ty.vectorLen(mod), .child = .bool_type })).toIntern(),38878 .ty = (try mod.vectorType(.{ .len = ty.vectorLen(mod), .child = .bool_type })).toIntern(),
...@@ -39232,45 +39049,22 @@ fn validateRuntimeValue(sema: *Sema, block: *Block, val_src: LazySrcLoc, val: Ai...@@ -39232,45 +39049,22 @@ fn validateRuntimeValue(sema: *Sema, block: *Block, val_src: LazySrcLoc, val: Ai
39232}39049}
3923339050
39234/// Returns true if any value contained in `val` is undefined.39051/// Returns true if any value contained in `val` is undefined.
39235fn anyUndef(sema: *Sema, val: Value) !bool {39052fn anyUndef(sema: *Sema, block: *Block, src: LazySrcLoc, val: Value) !bool {
39236 const mod = sema.mod;39053 const mod = sema.mod;
39237 if (val.ip_index == .none) return switch (val.tag()) {39054 return switch (mod.intern_pool.indexToKey(val.toIntern())) {
39238 .eu_payload => try sema.anyUndef(val.castTag(.eu_payload).?.data),39055 .undef => true,
39239 .opt_payload => try sema.anyUndef(val.castTag(.opt_payload).?.data),39056 .simple_value => |v| v == .undefined,
39240 .repeated => try sema.anyUndef(val.castTag(.repeated).?.data),
39241 .slice => {39057 .slice => {
39242 const slice = val.castTag(.slice).?.data;39058 // If the slice contents are runtime-known, reification will fail later on with a
39243 for (0..@intCast(slice.len.toUnsignedInt(mod))) |idx| {39059 // specific error message.
39244 if (try sema.anyUndef((try slice.ptr.maybeElemValueFull(sema, mod, idx)).?)) return true;39060 const arr = try sema.maybeDerefSliceAsArray(block, src, val) orelse return false;
39245 }39061 return sema.anyUndef(block, src, arr);
39246 return false;39062 },
39247 },39063 .aggregate => |aggregate| for (0..aggregate.storage.values().len) |i| {
39248 .bytes => false,39064 const elem = mod.intern_pool.indexToKey(val.toIntern()).aggregate.storage.values()[i];
39249 .aggregate => for (val.castTag(.aggregate).?.data) |elem| {39065 if (try sema.anyUndef(block, src, Value.fromInterned(elem))) break true;
39250 if (try sema.anyUndef(elem)) break true;
39251 } else false,39066 } else false,
39252 .@"union" => {39067 else => false,
39253 const un = val.castTag(.@"union").?.data;
39254 if (un.tag) |t| {
39255 if (try sema.anyUndef(t)) return true;
39256 }
39257 return sema.anyUndef(un.val);
39258 },
39259 };
39260 return switch (val.toIntern()) {
39261 .undef => true,
39262 else => switch (mod.intern_pool.indexToKey(val.toIntern())) {
39263 .undef => true,
39264 .simple_value => |v| v == .undefined,
39265 .slice => |slice| for (0..@intCast(Value.fromInterned(slice.len).toUnsignedInt(mod))) |idx| {
39266 if (try sema.anyUndef((try val.maybeElemValueFull(sema, mod, idx)).?)) break true;
39267 } else false,
39268 .aggregate => |aggregate| for (0..aggregate.storage.values().len) |i| {
39269 const elem = mod.intern_pool.indexToKey(val.toIntern()).aggregate.storage.values()[i];
39270 if (try sema.anyUndef(Value.fromInterned(elem))) break true;
39271 } else false,
39272 else => false,
39273 },
39274 };39068 };
39275}39069}
3927639070
...@@ -39283,12 +39077,11 @@ fn sliceToIpString(...@@ -39283,12 +39077,11 @@ fn sliceToIpString(
39283 reason: NeededComptimeReason,39077 reason: NeededComptimeReason,
39284) CompileError!InternPool.NullTerminatedString {39078) CompileError!InternPool.NullTerminatedString {
39285 const zcu = sema.mod;39079 const zcu = sema.mod;
39286 const ip = &zcu.intern_pool;39080 const slice_ty = slice_val.typeOf(zcu);
39287 const slice_ty = Type.fromInterned(ip.typeOf(slice_val.toIntern()));
39288 assert(slice_ty.isSlice(zcu));39081 assert(slice_ty.isSlice(zcu));
39289 assert(slice_ty.childType(zcu).toIntern() == .u8_type);39082 assert(slice_ty.childType(zcu).toIntern() == .u8_type);
39290 const array_val = try sema.derefSliceAsArray(block, src, slice_val, reason);39083 const array_val = try sema.derefSliceAsArray(block, src, slice_val, reason);
39291 const array_ty = Type.fromInterned(ip.typeOf(array_val.toIntern()));39084 const array_ty = array_val.typeOf(zcu);
39292 return array_val.toIpString(array_ty, zcu);39085 return array_val.toIpString(array_ty, zcu);
39293}39086}
3929439087
...@@ -39302,9 +39095,23 @@ fn derefSliceAsArray(...@@ -39302,9 +39095,23 @@ fn derefSliceAsArray(
39302 slice_val: Value,39095 slice_val: Value,
39303 reason: NeededComptimeReason,39096 reason: NeededComptimeReason,
39304) CompileError!Value {39097) CompileError!Value {
39098 return try sema.maybeDerefSliceAsArray(block, src, slice_val) orelse {
39099 return sema.failWithNeededComptime(block, src, reason);
39100 };
39101}
39102
39103/// Given a slice value, attempts to dereference it into a comptime-known array.
39104/// Returns `null` if the contents of the slice are not comptime-known.
39105/// Asserts that `slice_val` is a slice.
39106fn maybeDerefSliceAsArray(
39107 sema: *Sema,
39108 block: *Block,
39109 src: LazySrcLoc,
39110 slice_val: Value,
39111) CompileError!?Value {
39305 const zcu = sema.mod;39112 const zcu = sema.mod;
39306 const ip = &zcu.intern_pool;39113 const ip = &zcu.intern_pool;
39307 assert(Type.fromInterned(ip.typeOf(slice_val.toIntern())).isSlice(zcu));39114 assert(slice_val.typeOf(zcu).isSlice(zcu));
39308 const slice = switch (ip.indexToKey(slice_val.toIntern())) {39115 const slice = switch (ip.indexToKey(slice_val.toIntern())) {
39309 .undef => return sema.failWithUseOfUndef(block, src),39116 .undef => return sema.failWithUseOfUndef(block, src),
39310 .slice => |slice| slice,39117 .slice => |slice| slice,
...@@ -39324,7 +39131,5 @@ fn derefSliceAsArray(...@@ -39324,7 +39131,5 @@ fn derefSliceAsArray(
39324 break :p p;39131 break :p p;
39325 });39132 });
39326 const casted_ptr = try zcu.getCoerced(Value.fromInterned(slice.ptr), ptr_ty);39133 const casted_ptr = try zcu.getCoerced(Value.fromInterned(slice.ptr), ptr_ty);
39327 return try sema.pointerDeref(block, src, casted_ptr, ptr_ty) orelse {39134 return sema.pointerDeref(block, src, casted_ptr, ptr_ty);
39328 return sema.failWithNeededComptime(block, src, reason);
39329 };
39330}39135}
src/TypedValue.zig deleted-528
...@@ -1,528 +0,0 @@
1const std = @import("std");
2const Type = @import("type.zig").Type;
3const Value = @import("Value.zig");
4const Module = @import("Module.zig");
5const Allocator = std.mem.Allocator;
6const TypedValue = @This();
7const Target = std.Target;
8
9ty: Type,
10val: Value,
11
12/// Memory management for TypedValue. The main purpose of this type
13/// is to be small and have a deinit() function to free associated resources.
14pub const Managed = struct {
15 /// If the tag value is less than Tag.no_payload_count, then no pointer
16 /// dereference is needed.
17 typed_value: TypedValue,
18 /// If this is `null` then there is no memory management needed.
19 arena: ?*std.heap.ArenaAllocator.State = null,
20
21 pub fn deinit(self: *Managed, allocator: Allocator) void {
22 if (self.arena) |a| a.promote(allocator).deinit();
23 self.* = undefined;
24 }
25};
26
27/// Assumes arena allocation. Does a recursive copy.
28pub fn copy(self: TypedValue, arena: Allocator) error{OutOfMemory}!TypedValue {
29 return TypedValue{
30 .ty = self.ty,
31 .val = try self.val.copy(arena),
32 };
33}
34
35pub fn eql(a: TypedValue, b: TypedValue, mod: *Module) bool {
36 if (a.ty.toIntern() != b.ty.toIntern()) return false;
37 return a.val.eql(b.val, a.ty, mod);
38}
39
40pub fn hash(tv: TypedValue, hasher: *std.hash.Wyhash, mod: *Module) void {
41 return tv.val.hash(tv.ty, hasher, mod);
42}
43
44pub fn intFromEnum(tv: TypedValue, mod: *Module) Allocator.Error!Value {
45 return tv.val.intFromEnum(tv.ty, mod);
46}
47
48const max_aggregate_items = 100;
49const max_string_len = 256;
50
51const FormatContext = struct {
52 tv: TypedValue,
53 mod: *Module,
54};
55
56pub fn format(
57 ctx: FormatContext,
58 comptime fmt: []const u8,
59 options: std.fmt.FormatOptions,
60 writer: anytype,
61) !void {
62 _ = options;
63 comptime std.debug.assert(fmt.len == 0);
64 return ctx.tv.print(writer, 3, ctx.mod) catch |err| switch (err) {
65 error.OutOfMemory => @panic("OOM"), // We're not allowed to return this from a format function
66 else => |e| return e,
67 };
68}
69
70/// Prints the Value according to the Type, not according to the Value Tag.
71pub fn print(
72 tv: TypedValue,
73 writer: anytype,
74 level: u8,
75 mod: *Module,
76) (@TypeOf(writer).Error || Allocator.Error)!void {
77 var val = tv.val;
78 var ty = tv.ty;
79 const ip = &mod.intern_pool;
80 while (true) switch (val.ip_index) {
81 .none => switch (val.tag()) {
82 .aggregate => return printAggregate(ty, val, writer, level, mod),
83 .@"union" => {
84 if (level == 0) {
85 return writer.writeAll(".{ ... }");
86 }
87 const payload = val.castTag(.@"union").?.data;
88 try writer.writeAll(".{ ");
89
90 if (payload.tag) |tag| {
91 try print(.{
92 .ty = Type.fromInterned(ip.loadUnionType(ty.toIntern()).enum_tag_ty),
93 .val = tag,
94 }, writer, level - 1, mod);
95 try writer.writeAll(" = ");
96 const field_ty = ty.unionFieldType(tag, mod).?;
97 try print(.{
98 .ty = field_ty,
99 .val = payload.val,
100 }, writer, level - 1, mod);
101 } else {
102 try writer.writeAll("(unknown tag) = ");
103 const backing_ty = try ty.unionBackingType(mod);
104 try print(.{
105 .ty = backing_ty,
106 .val = payload.val,
107 }, writer, level - 1, mod);
108 }
109
110 return writer.writeAll(" }");
111 },
112 .bytes => return writer.print("\"{}\"", .{std.zig.fmtEscapes(val.castTag(.bytes).?.data)}),
113 .repeated => {
114 if (level == 0) {
115 return writer.writeAll(".{ ... }");
116 }
117 var i: u32 = 0;
118 try writer.writeAll(".{ ");
119 const elem_tv = TypedValue{
120 .ty = ty.elemType2(mod),
121 .val = val.castTag(.repeated).?.data,
122 };
123 const len = ty.arrayLen(mod);
124 const max_len = @min(len, max_aggregate_items);
125 while (i < max_len) : (i += 1) {
126 if (i != 0) try writer.writeAll(", ");
127 try print(elem_tv, writer, level - 1, mod);
128 }
129 if (len > max_aggregate_items) {
130 try writer.writeAll(", ...");
131 }
132 return writer.writeAll(" }");
133 },
134 .slice => {
135 if (level == 0) {
136 return writer.writeAll(".{ ... }");
137 }
138 const payload = val.castTag(.slice).?.data;
139 const elem_ty = ty.elemType2(mod);
140 const len = payload.len.toUnsignedInt(mod);
141
142 if (elem_ty.eql(Type.u8, mod)) str: {
143 const max_len: usize = @min(len, max_string_len);
144 var buf: [max_string_len]u8 = undefined;
145
146 var i: u32 = 0;
147 while (i < max_len) : (i += 1) {
148 const maybe_elem_val = payload.ptr.maybeElemValue(mod, i) catch |err| switch (err) {
149 error.OutOfMemory => @panic("OOM"), // TODO: eliminate this panic
150 };
151 const elem_val = maybe_elem_val orelse return writer.writeAll(".{ (reinterpreted data) }");
152 if (elem_val.isUndef(mod)) break :str;
153 buf[i] = std.math.cast(u8, elem_val.toUnsignedInt(mod)) orelse break :str;
154 }
155
156 // TODO would be nice if this had a bit of unicode awareness.
157 const truncated = if (len > max_string_len) " (truncated)" else "";
158 return writer.print("\"{}{s}\"", .{ std.zig.fmtEscapes(buf[0..max_len]), truncated });
159 }
160
161 try writer.writeAll(".{ ");
162
163 const max_len = @min(len, max_aggregate_items);
164 var i: u32 = 0;
165 while (i < max_len) : (i += 1) {
166 if (i != 0) try writer.writeAll(", ");
167 const maybe_elem_val = payload.ptr.maybeElemValue(mod, i) catch |err| switch (err) {
168 error.OutOfMemory => @panic("OOM"), // TODO: eliminate this panic
169 };
170 const elem_val = maybe_elem_val orelse return writer.writeAll("(reinterpreted data) }");
171 try print(.{
172 .ty = elem_ty,
173 .val = elem_val,
174 }, writer, level - 1, mod);
175 }
176 if (len > max_aggregate_items) {
177 try writer.writeAll(", ...");
178 }
179 return writer.writeAll(" }");
180 },
181 .eu_payload => {
182 val = val.castTag(.eu_payload).?.data;
183 ty = ty.errorUnionPayload(mod);
184 },
185 .opt_payload => {
186 val = val.castTag(.opt_payload).?.data;
187 ty = ty.optionalChild(mod);
188 },
189 },
190 else => switch (ip.indexToKey(val.toIntern())) {
191 .int_type,
192 .ptr_type,
193 .array_type,
194 .vector_type,
195 .opt_type,
196 .anyframe_type,
197 .error_union_type,
198 .simple_type,
199 .struct_type,
200 .anon_struct_type,
201 .union_type,
202 .opaque_type,
203 .enum_type,
204 .func_type,
205 .error_set_type,
206 .inferred_error_set_type,
207 => return Type.print(val.toType(), writer, mod),
208 .undef => return writer.writeAll("undefined"),
209 .simple_value => |simple_value| switch (simple_value) {
210 .void => return writer.writeAll("{}"),
211 .empty_struct => return printAggregate(ty, val, writer, level, mod),
212 .generic_poison => return writer.writeAll("(generic poison)"),
213 else => return writer.writeAll(@tagName(simple_value)),
214 },
215 .variable => return writer.writeAll("(variable)"),
216 .extern_func => |extern_func| return writer.print("(extern function '{}')", .{
217 mod.declPtr(extern_func.decl).name.fmt(ip),
218 }),
219 .func => |func| return writer.print("(function '{}')", .{
220 mod.declPtr(func.owner_decl).name.fmt(ip),
221 }),
222 .int => |int| switch (int.storage) {
223 inline .u64, .i64, .big_int => |x| return writer.print("{}", .{x}),
224 .lazy_align => |lazy_ty| return writer.print("{d}", .{
225 Type.fromInterned(lazy_ty).abiAlignment(mod),
226 }),
227 .lazy_size => |lazy_ty| return writer.print("{d}", .{
228 Type.fromInterned(lazy_ty).abiSize(mod),
229 }),
230 },
231 .err => |err| return writer.print("error.{}", .{
232 err.name.fmt(ip),
233 }),
234 .error_union => |error_union| switch (error_union.val) {
235 .err_name => |err_name| return writer.print("error.{}", .{
236 err_name.fmt(ip),
237 }),
238 .payload => |payload| {
239 val = Value.fromInterned(payload);
240 ty = ty.errorUnionPayload(mod);
241 },
242 },
243 .enum_literal => |enum_literal| return writer.print(".{}", .{
244 enum_literal.fmt(ip),
245 }),
246 .enum_tag => |enum_tag| {
247 if (level == 0) {
248 return writer.writeAll("(enum)");
249 }
250 const enum_type = ip.loadEnumType(ty.toIntern());
251 if (enum_type.tagValueIndex(ip, val.toIntern())) |tag_index| {
252 try writer.print(".{i}", .{enum_type.names.get(ip)[tag_index].fmt(ip)});
253 return;
254 }
255 try writer.writeAll("@enumFromInt(");
256 try print(.{
257 .ty = Type.fromInterned(ip.typeOf(enum_tag.int)),
258 .val = Value.fromInterned(enum_tag.int),
259 }, writer, level - 1, mod);
260 try writer.writeAll(")");
261 return;
262 },
263 .empty_enum_value => return writer.writeAll("(empty enum value)"),
264 .float => |float| switch (float.storage) {
265 inline else => |x| return writer.print("{d}", .{@as(f64, @floatCast(x))}),
266 },
267 .slice => |slice| {
268 const ptr_ty = switch (ip.indexToKey(slice.ptr)) {
269 .ptr => |ptr| ty: {
270 if (ptr.addr == .int) return print(.{
271 .ty = Type.fromInterned(ptr.ty),
272 .val = Value.fromInterned(slice.ptr),
273 }, writer, level - 1, mod);
274 break :ty ip.indexToKey(ptr.ty).ptr_type;
275 },
276 .undef => |ptr_ty| ip.indexToKey(ptr_ty).ptr_type,
277 else => unreachable,
278 };
279 if (level == 0) {
280 return writer.writeAll(".{ ... }");
281 }
282 const elem_ty = Type.fromInterned(ptr_ty.child);
283 const len = Value.fromInterned(slice.len).toUnsignedInt(mod);
284 if (elem_ty.eql(Type.u8, mod)) str: {
285 const max_len = @min(len, max_string_len);
286 var buf: [max_string_len]u8 = undefined;
287 for (buf[0..max_len], 0..) |*c, i| {
288 const maybe_elem = try val.maybeElemValue(mod, i);
289 const elem = maybe_elem orelse return writer.writeAll(".{ (reinterpreted data) }");
290 if (elem.isUndef(mod)) break :str;
291 c.* = @as(u8, @intCast(elem.toUnsignedInt(mod)));
292 }
293 const truncated = if (len > max_string_len) " (truncated)" else "";
294 return writer.print("\"{}{s}\"", .{ std.zig.fmtEscapes(buf[0..max_len]), truncated });
295 }
296 try writer.writeAll(".{ ");
297 const max_len = @min(len, max_aggregate_items);
298 for (0..max_len) |i| {
299 if (i != 0) try writer.writeAll(", ");
300 const maybe_elem = try val.maybeElemValue(mod, i);
301 const elem = maybe_elem orelse return writer.writeAll("(reinterpreted data) }");
302 try print(.{
303 .ty = elem_ty,
304 .val = elem,
305 }, writer, level - 1, mod);
306 }
307 if (len > max_aggregate_items) {
308 try writer.writeAll(", ...");
309 }
310 return writer.writeAll(" }");
311 },
312 .ptr => |ptr| {
313 switch (ptr.addr) {
314 .decl => |decl_index| {
315 const decl = mod.declPtr(decl_index);
316 if (level == 0) return writer.print("(decl '{}')", .{decl.name.fmt(ip)});
317 return print(.{
318 .ty = decl.ty,
319 .val = decl.val,
320 }, writer, level - 1, mod);
321 },
322 .anon_decl => |anon_decl| {
323 const decl_val = anon_decl.val;
324 if (level == 0) return writer.print("(anon decl '{d}')", .{
325 @intFromEnum(decl_val),
326 });
327 return print(.{
328 .ty = Type.fromInterned(ip.typeOf(decl_val)),
329 .val = Value.fromInterned(decl_val),
330 }, writer, level - 1, mod);
331 },
332 .comptime_alloc => {
333 // TODO: we need a Sema to print this!
334 return writer.writeAll("(comptime alloc)");
335 },
336 .comptime_field => |field_val_ip| {
337 return print(.{
338 .ty = Type.fromInterned(ip.typeOf(field_val_ip)),
339 .val = Value.fromInterned(field_val_ip),
340 }, writer, level - 1, mod);
341 },
342 .int => |int_ip| {
343 try writer.writeAll("@ptrFromInt(");
344 try print(.{
345 .ty = Type.usize,
346 .val = Value.fromInterned(int_ip),
347 }, writer, level - 1, mod);
348 try writer.writeByte(')');
349 },
350 .eu_payload => |eu_ip| {
351 try writer.writeAll("(payload of ");
352 try print(.{
353 .ty = Type.fromInterned(ip.typeOf(eu_ip)),
354 .val = Value.fromInterned(eu_ip),
355 }, writer, level - 1, mod);
356 try writer.writeAll(")");
357 },
358 .opt_payload => |opt_ip| {
359 try print(.{
360 .ty = Type.fromInterned(ip.typeOf(opt_ip)),
361 .val = Value.fromInterned(opt_ip),
362 }, writer, level - 1, mod);
363 try writer.writeAll(".?");
364 },
365 .elem => |elem| {
366 if (level == 0) {
367 try writer.writeAll("(...)");
368 } else {
369 try print(.{
370 .ty = Type.fromInterned(ip.typeOf(elem.base)),
371 .val = Value.fromInterned(elem.base),
372 }, writer, level - 1, mod);
373 }
374 try writer.print("[{}]", .{elem.index});
375 },
376 .field => |field| {
377 const ptr_container_ty = Type.fromInterned(ip.typeOf(field.base));
378 if (level == 0) {
379 try writer.writeAll("(...)");
380 } else {
381 try print(.{
382 .ty = ptr_container_ty,
383 .val = Value.fromInterned(field.base),
384 }, writer, level - 1, mod);
385 }
386
387 const container_ty = ptr_container_ty.childType(mod);
388 switch (container_ty.zigTypeTag(mod)) {
389 .Struct => {
390 if (container_ty.structFieldName(@intCast(field.index), mod).unwrap()) |field_name| {
391 try writer.print(".{i}", .{field_name.fmt(ip)});
392 } else {
393 try writer.print("[{d}]", .{field.index});
394 }
395 },
396 .Union => {
397 const field_name = mod.typeToUnion(container_ty).?.loadTagType(ip).names.get(ip)[@intCast(field.index)];
398 try writer.print(".{i}", .{field_name.fmt(ip)});
399 },
400 .Pointer => {
401 std.debug.assert(container_ty.isSlice(mod));
402 try writer.writeAll(switch (field.index) {
403 Value.slice_ptr_index => ".ptr",
404 Value.slice_len_index => ".len",
405 else => unreachable,
406 });
407 },
408 else => unreachable,
409 }
410 },
411 }
412 return;
413 },
414 .opt => |opt| switch (opt.val) {
415 .none => return writer.writeAll("null"),
416 else => |payload| {
417 val = Value.fromInterned(payload);
418 ty = ty.optionalChild(mod);
419 },
420 },
421 .aggregate => |aggregate| switch (aggregate.storage) {
422 .bytes => |bytes| {
423 // Strip the 0 sentinel off of strings before printing
424 const zero_sent = blk: {
425 const sent = ty.sentinel(mod) orelse break :blk false;
426 break :blk sent.eql(Value.zero_u8, Type.u8, mod);
427 };
428 const str = if (zero_sent) bytes[0 .. bytes.len - 1] else bytes;
429 return writer.print("\"{}\"", .{std.zig.fmtEscapes(str)});
430 },
431 .elems, .repeated_elem => return printAggregate(ty, val, writer, level, mod),
432 },
433 .un => |un| {
434 try writer.writeAll(".{ ");
435 if (level > 0) {
436 if (un.tag != .none) {
437 try print(.{
438 .ty = ty.unionTagTypeHypothetical(mod),
439 .val = Value.fromInterned(un.tag),
440 }, writer, level - 1, mod);
441 try writer.writeAll(" = ");
442 const field_ty = ty.unionFieldType(Value.fromInterned(un.tag), mod).?;
443 try print(.{
444 .ty = field_ty,
445 .val = Value.fromInterned(un.val),
446 }, writer, level - 1, mod);
447 } else {
448 try writer.writeAll("(unknown tag) = ");
449 const backing_ty = try ty.unionBackingType(mod);
450 try print(.{
451 .ty = backing_ty,
452 .val = Value.fromInterned(un.val),
453 }, writer, level - 1, mod);
454 }
455 } else try writer.writeAll("...");
456 return writer.writeAll(" }");
457 },
458 .memoized_call => unreachable,
459 },
460 };
461}
462
463fn printAggregate(
464 ty: Type,
465 val: Value,
466 writer: anytype,
467 level: u8,
468 mod: *Module,
469) (@TypeOf(writer).Error || Allocator.Error)!void {
470 if (level == 0) {
471 return writer.writeAll(".{ ... }");
472 }
473 const ip = &mod.intern_pool;
474 if (ty.zigTypeTag(mod) == .Struct) {
475 try writer.writeAll(".{");
476 const max_len = @min(ty.structFieldCount(mod), max_aggregate_items);
477
478 for (0..max_len) |i| {
479 if (i != 0) try writer.writeAll(", ");
480
481 const field_name = ty.structFieldName(@intCast(i), mod);
482
483 if (field_name.unwrap()) |name| try writer.print(".{} = ", .{name.fmt(ip)});
484 try print(.{
485 .ty = ty.structFieldType(i, mod),
486 .val = try val.fieldValue(mod, i),
487 }, writer, level - 1, mod);
488 }
489 if (ty.structFieldCount(mod) > max_aggregate_items) {
490 try writer.writeAll(", ...");
491 }
492 return writer.writeAll("}");
493 } else {
494 const elem_ty = ty.elemType2(mod);
495 const len = ty.arrayLen(mod);
496
497 if (elem_ty.eql(Type.u8, mod)) str: {
498 const max_len: usize = @min(len, max_string_len);
499 var buf: [max_string_len]u8 = undefined;
500
501 var i: u32 = 0;
502 while (i < max_len) : (i += 1) {
503 const elem = try val.fieldValue(mod, i);
504 if (elem.isUndef(mod)) break :str;
505 buf[i] = std.math.cast(u8, elem.toUnsignedInt(mod)) orelse break :str;
506 }
507
508 const truncated = if (len > max_string_len) " (truncated)" else "";
509 return writer.print("\"{}{s}\"", .{ std.zig.fmtEscapes(buf[0..max_len]), truncated });
510 }
511
512 try writer.writeAll(".{ ");
513
514 const max_len = @min(len, max_aggregate_items);
515 var i: u32 = 0;
516 while (i < max_len) : (i += 1) {
517 if (i != 0) try writer.writeAll(", ");
518 try print(.{
519 .ty = elem_ty,
520 .val = try val.fieldValue(mod, i),
521 }, writer, level - 1, mod);
522 }
523 if (len > max_aggregate_items) {
524 try writer.writeAll(", ...");
525 }
526 return writer.writeAll(" }");
527 }
528}
src/Value.zig+174-647
...@@ -8,129 +8,13 @@ const Target = std.Target;...@@ -8,129 +8,13 @@ const Target = std.Target;
8const Allocator = std.mem.Allocator;8const Allocator = std.mem.Allocator;
9const Zcu = @import("Module.zig");9const Zcu = @import("Module.zig");
10const Module = Zcu;10const Module = Zcu;
11const TypedValue = @import("TypedValue.zig");
12const Sema = @import("Sema.zig");11const Sema = @import("Sema.zig");
13const InternPool = @import("InternPool.zig");12const InternPool = @import("InternPool.zig");
13const print_value = @import("print_value.zig");
14const Value = @This();14const Value = @This();
1515
16/// We are migrating towards using this for every Value object. However, many
17/// values are still represented the legacy way. This is indicated by using
18/// InternPool.Index.none.
19ip_index: InternPool.Index,16ip_index: InternPool.Index,
2017
21/// This is the raw data, with no bookkeeping, no memory awareness,
22/// no de-duplication, and no type system awareness.
23/// This union takes advantage of the fact that the first page of memory
24/// is unmapped, giving us 4096 possible enum tags that have no payload.
25legacy: extern union {
26 ptr_otherwise: *Payload,
27},
28
29// Keep in sync with tools/stage2_pretty_printers_common.py
30pub const Tag = enum(usize) {
31 // The first section of this enum are tags that require no payload.
32 // After this, the tag requires a payload.
33
34 /// When the type is error union:
35 /// * If the tag is `.@"error"`, the error union is an error.
36 /// * If the tag is `.eu_payload`, the error union is a payload.
37 /// * A nested error such as `anyerror!(anyerror!T)` in which the the outer error union
38 /// is non-error, but the inner error union is an error, is represented as
39 /// a tag of `.eu_payload`, with a sub-tag of `.@"error"`.
40 eu_payload,
41 /// When the type is optional:
42 /// * If the tag is `.null_value`, the optional is null.
43 /// * If the tag is `.opt_payload`, the optional is a payload.
44 /// * A nested optional such as `??T` in which the the outer optional
45 /// is non-null, but the inner optional is null, is represented as
46 /// a tag of `.opt_payload`, with a sub-tag of `.null_value`.
47 opt_payload,
48 /// Pointer and length as sub `Value` objects.
49 slice,
50 /// A slice of u8 whose memory is managed externally.
51 bytes,
52 /// This value is repeated some number of times. The amount of times to repeat
53 /// is stored externally.
54 repeated,
55 /// An instance of a struct, array, or vector.
56 /// Each element/field stored as a `Value`.
57 /// In the case of sentinel-terminated arrays, the sentinel value *is* stored,
58 /// so the slice length will be one more than the type's array length.
59 aggregate,
60 /// An instance of a union.
61 @"union",
62
63 pub fn Type(comptime t: Tag) type {
64 return switch (t) {
65 .eu_payload,
66 .opt_payload,
67 .repeated,
68 => Payload.SubValue,
69 .slice => Payload.Slice,
70 .bytes => Payload.Bytes,
71 .aggregate => Payload.Aggregate,
72 .@"union" => Payload.Union,
73 };
74 }
75
76 pub fn create(comptime t: Tag, ally: Allocator, data: Data(t)) error{OutOfMemory}!Value {
77 const ptr = try ally.create(t.Type());
78 ptr.* = .{
79 .base = .{ .tag = t },
80 .data = data,
81 };
82 return Value{
83 .ip_index = .none,
84 .legacy = .{ .ptr_otherwise = &ptr.base },
85 };
86 }
87
88 pub fn Data(comptime t: Tag) type {
89 return std.meta.fieldInfo(t.Type(), .data).type;
90 }
91};
92
93pub fn initPayload(payload: *Payload) Value {
94 return Value{
95 .ip_index = .none,
96 .legacy = .{ .ptr_otherwise = payload },
97 };
98}
99
100pub fn tag(self: Value) Tag {
101 assert(self.ip_index == .none);
102 return self.legacy.ptr_otherwise.tag;
103}
104
105/// Prefer `castTag` to this.
106pub fn cast(self: Value, comptime T: type) ?*T {
107 if (self.ip_index != .none) {
108 return null;
109 }
110 if (@hasField(T, "base_tag")) {
111 return self.castTag(T.base_tag);
112 }
113 inline for (@typeInfo(Tag).Enum.fields) |field| {
114 const t = @as(Tag, @enumFromInt(field.value));
115 if (self.legacy.ptr_otherwise.tag == t) {
116 if (T == t.Type()) {
117 return @fieldParentPtr(T, "base", self.legacy.ptr_otherwise);
118 }
119 return null;
120 }
121 }
122 unreachable;
123}
124
125pub fn castTag(self: Value, comptime t: Tag) ?*t.Type() {
126 if (self.ip_index != .none) return null;
127
128 if (self.legacy.ptr_otherwise.tag == t)
129 return @fieldParentPtr(t.Type(), "base", self.legacy.ptr_otherwise);
130
131 return null;
132}
133
134pub fn format(val: Value, comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void {18pub fn format(val: Value, comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void {
135 _ = val;19 _ = val;
136 _ = fmt;20 _ = fmt;
...@@ -148,42 +32,16 @@ pub fn dump(...@@ -148,42 +32,16 @@ pub fn dump(
148 out_stream: anytype,32 out_stream: anytype,
149) !void {33) !void {
150 comptime assert(fmt.len == 0);34 comptime assert(fmt.len == 0);
151 if (start_val.ip_index != .none) {35 try out_stream.print("(interned: {})", .{start_val.toIntern()});
152 try out_stream.print("(interned: {})", .{start_val.toIntern()});
153 return;
154 }
155 var val = start_val;
156 while (true) switch (val.tag()) {
157 .aggregate => {
158 return out_stream.writeAll("(aggregate)");
159 },
160 .@"union" => {
161 return out_stream.writeAll("(union value)");
162 },
163 .bytes => return out_stream.print("\"{}\"", .{std.zig.fmtEscapes(val.castTag(.bytes).?.data)}),
164 .repeated => {
165 try out_stream.writeAll("(repeated) ");
166 val = val.castTag(.repeated).?.data;
167 },
168 .eu_payload => {
169 try out_stream.writeAll("(eu_payload) ");
170 val = val.castTag(.repeated).?.data;
171 },
172 .opt_payload => {
173 try out_stream.writeAll("(opt_payload) ");
174 val = val.castTag(.repeated).?.data;
175 },
176 .slice => return out_stream.writeAll("(slice)"),
177 };
178}36}
17937
180pub fn fmtDebug(val: Value) std.fmt.Formatter(dump) {38pub fn fmtDebug(val: Value) std.fmt.Formatter(dump) {
181 return .{ .data = val };39 return .{ .data = val };
182}40}
18341
184pub fn fmtValue(val: Value, ty: Type, mod: *Module) std.fmt.Formatter(TypedValue.format) {42pub fn fmtValue(val: Value, mod: *Module) std.fmt.Formatter(print_value.format) {
185 return .{ .data = .{43 return .{ .data = .{
186 .tv = .{ .ty = ty, .val = val },44 .val = val,
187 .mod = mod,45 .mod = mod,
188 } };46 } };
189}47}
...@@ -252,162 +110,9 @@ fn arrayToIpString(val: Value, len_u64: u64, mod: *Module) !InternPool.NullTermi...@@ -252,162 +110,9 @@ fn arrayToIpString(val: Value, len_u64: u64, mod: *Module) !InternPool.NullTermi
252 return ip.getOrPutTrailingString(gpa, len);110 return ip.getOrPutTrailingString(gpa, len);
253}111}
254112
255pub fn intern2(val: Value, ty: Type, mod: *Module) Allocator.Error!InternPool.Index {
256 if (val.ip_index != .none) return val.ip_index;
257 return intern(val, ty, mod);
258}
259
260pub fn intern(val: Value, ty: Type, mod: *Module) Allocator.Error!InternPool.Index {
261 if (val.ip_index != .none) return (try mod.getCoerced(val, ty)).toIntern();
262 const ip = &mod.intern_pool;
263 switch (val.tag()) {
264 .eu_payload => {
265 const pl = val.castTag(.eu_payload).?.data;
266 return mod.intern(.{ .error_union = .{
267 .ty = ty.toIntern(),
268 .val = .{ .payload = try pl.intern(ty.errorUnionPayload(mod), mod) },
269 } });
270 },
271 .opt_payload => {
272 const pl = val.castTag(.opt_payload).?.data;
273 return mod.intern(.{ .opt = .{
274 .ty = ty.toIntern(),
275 .val = try pl.intern(ty.optionalChild(mod), mod),
276 } });
277 },
278 .slice => {
279 const pl = val.castTag(.slice).?.data;
280 return mod.intern(.{ .slice = .{
281 .ty = ty.toIntern(),
282 .len = try pl.len.intern(Type.usize, mod),
283 .ptr = try pl.ptr.intern(ty.slicePtrFieldType(mod), mod),
284 } });
285 },
286 .bytes => {
287 const pl = val.castTag(.bytes).?.data;
288 return mod.intern(.{ .aggregate = .{
289 .ty = ty.toIntern(),
290 .storage = .{ .bytes = pl },
291 } });
292 },
293 .repeated => {
294 const pl = val.castTag(.repeated).?.data;
295 return mod.intern(.{ .aggregate = .{
296 .ty = ty.toIntern(),
297 .storage = .{ .repeated_elem = try pl.intern(ty.childType(mod), mod) },
298 } });
299 },
300 .aggregate => {
301 const len = @as(usize, @intCast(ty.arrayLen(mod)));
302 const old_elems = val.castTag(.aggregate).?.data[0..len];
303 const new_elems = try mod.gpa.alloc(InternPool.Index, old_elems.len);
304 defer mod.gpa.free(new_elems);
305 const ty_key = ip.indexToKey(ty.toIntern());
306 for (new_elems, old_elems, 0..) |*new_elem, old_elem, field_i|
307 new_elem.* = try old_elem.intern(switch (ty_key) {
308 .struct_type => ty.structFieldType(field_i, mod),
309 .anon_struct_type => |info| Type.fromInterned(info.types.get(ip)[field_i]),
310 inline .array_type, .vector_type => |info| Type.fromInterned(info.child),
311 else => unreachable,
312 }, mod);
313 return mod.intern(.{ .aggregate = .{
314 .ty = ty.toIntern(),
315 .storage = .{ .elems = new_elems },
316 } });
317 },
318 .@"union" => {
319 const pl = val.castTag(.@"union").?.data;
320 if (pl.tag) |pl_tag| {
321 return mod.intern(.{ .un = .{
322 .ty = ty.toIntern(),
323 .tag = try pl_tag.intern(ty.unionTagTypeHypothetical(mod), mod),
324 .val = try pl.val.intern(ty.unionFieldType(pl_tag, mod).?, mod),
325 } });
326 } else {
327 return mod.intern(.{ .un = .{
328 .ty = ty.toIntern(),
329 .tag = .none,
330 .val = try pl.val.intern(try ty.unionBackingType(mod), mod),
331 } });
332 }
333 },
334 }
335}
336
337pub fn unintern(val: Value, arena: Allocator, mod: *Module) Allocator.Error!Value {
338 return if (val.ip_index == .none) val else switch (mod.intern_pool.indexToKey(val.toIntern())) {
339 .int_type,
340 .ptr_type,
341 .array_type,
342 .vector_type,
343 .opt_type,
344 .anyframe_type,
345 .error_union_type,
346 .simple_type,
347 .struct_type,
348 .anon_struct_type,
349 .union_type,
350 .opaque_type,
351 .enum_type,
352 .func_type,
353 .error_set_type,
354 .inferred_error_set_type,
355
356 .undef,
357 .simple_value,
358 .variable,
359 .extern_func,
360 .func,
361 .int,
362 .err,
363 .enum_literal,
364 .enum_tag,
365 .empty_enum_value,
366 .float,
367 .ptr,
368 => val,
369
370 .error_union => |error_union| switch (error_union.val) {
371 .err_name => val,
372 .payload => |payload| Tag.eu_payload.create(arena, Value.fromInterned(payload)),
373 },
374
375 .slice => |slice| Tag.slice.create(arena, .{
376 .ptr = Value.fromInterned(slice.ptr),
377 .len = Value.fromInterned(slice.len),
378 }),
379
380 .opt => |opt| switch (opt.val) {
381 .none => val,
382 else => |payload| Tag.opt_payload.create(arena, Value.fromInterned(payload)),
383 },
384
385 .aggregate => |aggregate| switch (aggregate.storage) {
386 .bytes => |bytes| Tag.bytes.create(arena, try arena.dupe(u8, bytes)),
387 .elems => |old_elems| {
388 const new_elems = try arena.alloc(Value, old_elems.len);
389 for (new_elems, old_elems) |*new_elem, old_elem| new_elem.* = Value.fromInterned(old_elem);
390 return Tag.aggregate.create(arena, new_elems);
391 },
392 .repeated_elem => |elem| Tag.repeated.create(arena, Value.fromInterned(elem)),
393 },
394
395 .un => |un| Tag.@"union".create(arena, .{
396 // toValue asserts that the value cannot be .none which is valid on unions.
397 .tag = if (un.tag == .none) null else Value.fromInterned(un.tag),
398 .val = Value.fromInterned(un.val),
399 }),
400
401 .memoized_call => unreachable,
402 };
403}
404
405pub fn fromInterned(i: InternPool.Index) Value {113pub fn fromInterned(i: InternPool.Index) Value {
406 assert(i != .none);114 assert(i != .none);
407 return .{115 return .{ .ip_index = i };
408 .ip_index = i,
409 .legacy = undefined,
410 };
411}116}
412117
413pub fn toIntern(val: Value) InternPool.Index {118pub fn toIntern(val: Value) InternPool.Index {
...@@ -492,24 +197,24 @@ pub fn isFuncBody(val: Value, mod: *Module) bool {...@@ -492,24 +197,24 @@ pub fn isFuncBody(val: Value, mod: *Module) bool {
492}197}
493198
494pub fn getFunction(val: Value, mod: *Module) ?InternPool.Key.Func {199pub fn getFunction(val: Value, mod: *Module) ?InternPool.Key.Func {
495 return if (val.ip_index != .none) switch (mod.intern_pool.indexToKey(val.toIntern())) {200 return switch (mod.intern_pool.indexToKey(val.toIntern())) {
496 .func => |x| x,201 .func => |x| x,
497 else => null,202 else => null,
498 } else null;203 };
499}204}
500205
501pub fn getExternFunc(val: Value, mod: *Module) ?InternPool.Key.ExternFunc {206pub fn getExternFunc(val: Value, mod: *Module) ?InternPool.Key.ExternFunc {
502 return if (val.ip_index != .none) switch (mod.intern_pool.indexToKey(val.toIntern())) {207 return switch (mod.intern_pool.indexToKey(val.toIntern())) {
503 .extern_func => |extern_func| extern_func,208 .extern_func => |extern_func| extern_func,
504 else => null,209 else => null,
505 } else null;210 };
506}211}
507212
508pub fn getVariable(val: Value, mod: *Module) ?InternPool.Key.Variable {213pub fn getVariable(val: Value, mod: *Module) ?InternPool.Key.Variable {
509 return if (val.ip_index != .none) switch (mod.intern_pool.indexToKey(val.toIntern())) {214 return switch (mod.intern_pool.indexToKey(val.toIntern())) {
510 .variable => |variable| variable,215 .variable => |variable| variable,
511 else => null,216 else => null,
512 } else null;217 };
513}218}
514219
515/// If the value fits in a u64, return it, otherwise null.220/// If the value fits in a u64, return it, otherwise null.
...@@ -544,12 +249,12 @@ pub fn getUnsignedIntAdvanced(val: Value, mod: *Module, opt_sema: ?*Sema) !?u64...@@ -544,12 +249,12 @@ pub fn getUnsignedIntAdvanced(val: Value, mod: *Module, opt_sema: ?*Sema) !?u64
544 .int => |int| Value.fromInterned(int).getUnsignedIntAdvanced(mod, opt_sema),249 .int => |int| Value.fromInterned(int).getUnsignedIntAdvanced(mod, opt_sema),
545 .elem => |elem| {250 .elem => |elem| {
546 const base_addr = (try Value.fromInterned(elem.base).getUnsignedIntAdvanced(mod, opt_sema)) orelse return null;251 const base_addr = (try Value.fromInterned(elem.base).getUnsignedIntAdvanced(mod, opt_sema)) orelse return null;
547 const elem_ty = Type.fromInterned(mod.intern_pool.typeOf(elem.base)).elemType2(mod);252 const elem_ty = Value.fromInterned(elem.base).typeOf(mod).elemType2(mod);
548 return base_addr + elem.index * elem_ty.abiSize(mod);253 return base_addr + elem.index * elem_ty.abiSize(mod);
549 },254 },
550 .field => |field| {255 .field => |field| {
551 const base_addr = (try Value.fromInterned(field.base).getUnsignedIntAdvanced(mod, opt_sema)) orelse return null;256 const base_addr = (try Value.fromInterned(field.base).getUnsignedIntAdvanced(mod, opt_sema)) orelse return null;
552 const struct_ty = Type.fromInterned(mod.intern_pool.typeOf(field.base)).childType(mod);257 const struct_ty = Value.fromInterned(field.base).typeOf(mod).childType(mod);
553 if (opt_sema) |sema| try sema.resolveTypeLayout(struct_ty);258 if (opt_sema) |sema| try sema.resolveTypeLayout(struct_ty);
554 return base_addr + struct_ty.structFieldOffset(@as(usize, @intCast(field.index)), mod);259 return base_addr + struct_ty.structFieldOffset(@as(usize, @intCast(field.index)), mod);
555 },260 },
...@@ -600,16 +305,16 @@ pub fn toBool(val: Value) bool {...@@ -600,16 +305,16 @@ pub fn toBool(val: Value) bool {
600 };305 };
601}306}
602307
603fn isDeclRef(val: Value, mod: *Module) bool {308fn ptrHasIntAddr(val: Value, mod: *Module) bool {
604 var check = val;309 var check = val;
605 while (true) switch (mod.intern_pool.indexToKey(check.toIntern())) {310 while (true) switch (mod.intern_pool.indexToKey(check.toIntern())) {
606 .ptr => |ptr| switch (ptr.addr) {311 .ptr => |ptr| switch (ptr.addr) {
607 .decl, .comptime_alloc, .comptime_field, .anon_decl => return true,312 .decl, .comptime_alloc, .comptime_field, .anon_decl => return false,
313 .int => return true,
608 .eu_payload, .opt_payload => |base| check = Value.fromInterned(base),314 .eu_payload, .opt_payload => |base| check = Value.fromInterned(base),
609 .elem, .field => |base_index| check = Value.fromInterned(base_index.base),315 .elem, .field => |base_index| check = Value.fromInterned(base_index.base),
610 .int => return false,
611 },316 },
612 else => return false,317 else => unreachable,
613 };318 };
614}319}
615320
...@@ -677,25 +382,14 @@ pub fn writeToMemory(val: Value, ty: Type, mod: *Module, buffer: []u8) error{...@@ -677,25 +382,14 @@ pub fn writeToMemory(val: Value, ty: Type, mod: *Module, buffer: []u8) error{
677 .auto => return error.IllDefinedMemoryLayout,382 .auto => return error.IllDefinedMemoryLayout,
678 .@"extern" => for (0..struct_type.field_types.len) |i| {383 .@"extern" => for (0..struct_type.field_types.len) |i| {
679 const off: usize = @intCast(ty.structFieldOffset(i, mod));384 const off: usize = @intCast(ty.structFieldOffset(i, mod));
680 const field_val = switch (val.ip_index) {385 const field_val = Value.fromInterned(switch (ip.indexToKey(val.toIntern()).aggregate.storage) {
681 .none => switch (val.tag()) {386 .bytes => |bytes| {
682 .bytes => {387 buffer[off] = bytes[i];
683 buffer[off] = val.castTag(.bytes).?.data[i];388 continue;
684 continue;
685 },
686 .aggregate => val.castTag(.aggregate).?.data[i],
687 .repeated => val.castTag(.repeated).?.data,
688 else => unreachable,
689 },389 },
690 else => Value.fromInterned(switch (ip.indexToKey(val.toIntern()).aggregate.storage) {390 .elems => |elems| elems[i],
691 .bytes => |bytes| {391 .repeated_elem => |elem| elem,
692 buffer[off] = bytes[i];392 });
693 continue;
694 },
695 .elems => |elems| elems[i],
696 .repeated_elem => |elem| elem,
697 }),
698 };
699 const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[i]);393 const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[i]);
700 try writeToMemory(field_val, field_ty, mod, buffer[off..]);394 try writeToMemory(field_val, field_ty, mod, buffer[off..]);
701 },395 },
...@@ -745,7 +439,7 @@ pub fn writeToMemory(val: Value, ty: Type, mod: *Module, buffer: []u8) error{...@@ -745,7 +439,7 @@ pub fn writeToMemory(val: Value, ty: Type, mod: *Module, buffer: []u8) error{
745 },439 },
746 .Pointer => {440 .Pointer => {
747 if (ty.isSlice(mod)) return error.IllDefinedMemoryLayout;441 if (ty.isSlice(mod)) return error.IllDefinedMemoryLayout;
748 if (val.isDeclRef(mod)) return error.ReinterpretDeclRef;442 if (!val.ptrHasIntAddr(mod)) return error.ReinterpretDeclRef;
749 return val.writeToMemory(Type.usize, mod, buffer);443 return val.writeToMemory(Type.usize, mod, buffer);
750 },444 },
751 .Optional => {445 .Optional => {
...@@ -842,19 +536,11 @@ pub fn writeToPackedMemory(...@@ -842,19 +536,11 @@ pub fn writeToPackedMemory(
842 assert(struct_type.layout == .@"packed");536 assert(struct_type.layout == .@"packed");
843 var bits: u16 = 0;537 var bits: u16 = 0;
844 for (0..struct_type.field_types.len) |i| {538 for (0..struct_type.field_types.len) |i| {
845 const field_val = switch (val.ip_index) {539 const field_val = Value.fromInterned(switch (ip.indexToKey(val.toIntern()).aggregate.storage) {
846 .none => switch (val.tag()) {540 .bytes => unreachable,
847 .bytes => unreachable,541 .elems => |elems| elems[i],
848 .aggregate => val.castTag(.aggregate).?.data[i],542 .repeated_elem => |elem| elem,
849 .repeated => val.castTag(.repeated).?.data,543 });
850 else => unreachable,
851 },
852 else => Value.fromInterned(switch (ip.indexToKey(val.toIntern()).aggregate.storage) {
853 .bytes => unreachable,
854 .elems => |elems| elems[i],
855 .repeated_elem => |elem| elem,
856 }),
857 };
858 const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[i]);544 const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[i]);
859 const field_bits: u16 = @intCast(field_ty.bitSize(mod));545 const field_bits: u16 = @intCast(field_ty.bitSize(mod));
860 try field_val.writeToPackedMemory(field_ty, mod, buffer, bit_offset + bits);546 try field_val.writeToPackedMemory(field_ty, mod, buffer, bit_offset + bits);
...@@ -880,7 +566,7 @@ pub fn writeToPackedMemory(...@@ -880,7 +566,7 @@ pub fn writeToPackedMemory(
880 },566 },
881 .Pointer => {567 .Pointer => {
882 assert(!ty.isSlice(mod)); // No well defined layout.568 assert(!ty.isSlice(mod)); // No well defined layout.
883 if (val.isDeclRef(mod)) return error.ReinterpretDeclRef;569 if (!val.ptrHasIntAddr(mod)) return error.ReinterpretDeclRef;
884 return val.writeToPackedMemory(Type.usize, mod, buffer, bit_offset);570 return val.writeToPackedMemory(Type.usize, mod, buffer, bit_offset);
885 },571 },
886 .Optional => {572 .Optional => {
...@@ -972,7 +658,7 @@ pub fn readFromMemory(...@@ -972,7 +658,7 @@ pub fn readFromMemory(
972 const elems = try arena.alloc(InternPool.Index, @as(usize, @intCast(ty.arrayLen(mod))));658 const elems = try arena.alloc(InternPool.Index, @as(usize, @intCast(ty.arrayLen(mod))));
973 var offset: usize = 0;659 var offset: usize = 0;
974 for (elems) |*elem| {660 for (elems) |*elem| {
975 elem.* = try (try readFromMemory(elem_ty, mod, buffer[offset..], arena)).intern(elem_ty, mod);661 elem.* = (try readFromMemory(elem_ty, mod, buffer[offset..], arena)).toIntern();
976 offset += @as(usize, @intCast(elem_size));662 offset += @as(usize, @intCast(elem_size));
977 }663 }
978 return Value.fromInterned((try mod.intern(.{ .aggregate = .{664 return Value.fromInterned((try mod.intern(.{ .aggregate = .{
...@@ -997,7 +683,7 @@ pub fn readFromMemory(...@@ -997,7 +683,7 @@ pub fn readFromMemory(
997 const field_ty = Type.fromInterned(field_types.get(ip)[i]);683 const field_ty = Type.fromInterned(field_types.get(ip)[i]);
998 const off: usize = @intCast(ty.structFieldOffset(i, mod));684 const off: usize = @intCast(ty.structFieldOffset(i, mod));
999 const sz: usize = @intCast(field_ty.abiSize(mod));685 const sz: usize = @intCast(field_ty.abiSize(mod));
1000 field_val.* = try (try readFromMemory(field_ty, mod, buffer[off..(off + sz)], arena)).intern(field_ty, mod);686 field_val.* = (try readFromMemory(field_ty, mod, buffer[off..(off + sz)], arena)).toIntern();
1001 }687 }
1002 return Value.fromInterned((try mod.intern(.{ .aggregate = .{688 return Value.fromInterned((try mod.intern(.{ .aggregate = .{
1003 .ty = ty.toIntern(),689 .ty = ty.toIntern(),
...@@ -1027,7 +713,7 @@ pub fn readFromMemory(...@@ -1027,7 +713,7 @@ pub fn readFromMemory(
1027 .@"extern" => {713 .@"extern" => {
1028 const union_size = ty.abiSize(mod);714 const union_size = ty.abiSize(mod);
1029 const array_ty = try mod.arrayType(.{ .len = union_size, .child = .u8_type });715 const array_ty = try mod.arrayType(.{ .len = union_size, .child = .u8_type });
1030 const val = try (try readFromMemory(array_ty, mod, buffer, arena)).intern(array_ty, mod);716 const val = (try readFromMemory(array_ty, mod, buffer, arena)).toIntern();
1031 return Value.fromInterned((try mod.intern(.{ .un = .{717 return Value.fromInterned((try mod.intern(.{ .un = .{
1032 .ty = ty.toIntern(),718 .ty = ty.toIntern(),
1033 .tag = .none,719 .tag = .none,
...@@ -1094,30 +780,19 @@ pub fn readFromPackedMemory(...@@ -1094,30 +780,19 @@ pub fn readFromPackedMemory(
1094 return Value.true;780 return Value.true;
1095 }781 }
1096 },782 },
1097 .Int, .Enum => |ty_tag| {783 .Int => {
1098 if (buffer.len == 0) return mod.intValue(ty, 0);784 if (buffer.len == 0) return mod.intValue(ty, 0);
1099 const int_info = ty.intInfo(mod);785 const int_info = ty.intInfo(mod);
1100 const bits = int_info.bits;786 const bits = int_info.bits;
1101 if (bits == 0) return mod.intValue(ty, 0);787 if (bits == 0) return mod.intValue(ty, 0);
1102788
1103 // Fast path for integers <= u64789 // Fast path for integers <= u64
1104 if (bits <= 64) {790 if (bits <= 64) switch (int_info.signedness) {
1105 const int_ty = switch (ty_tag) {791 // Use different backing types for unsigned vs signed to avoid the need to go via
1106 .Int => ty,792 // a larger type like `i128`.
1107 .Enum => ty.intTagType(mod),793 .unsigned => return mod.intValue(ty, std.mem.readVarPackedInt(u64, buffer, bit_offset, bits, endian, .unsigned)),
1108 else => unreachable,794 .signed => return mod.intValue(ty, std.mem.readVarPackedInt(i64, buffer, bit_offset, bits, endian, .signed)),
1109 };795 };
1110 return mod.getCoerced(switch (int_info.signedness) {
1111 .signed => return mod.intValue(
1112 int_ty,
1113 std.mem.readVarPackedInt(i64, buffer, bit_offset, bits, endian, .signed),
1114 ),
1115 .unsigned => return mod.intValue(
1116 int_ty,
1117 std.mem.readVarPackedInt(u64, buffer, bit_offset, bits, endian, .unsigned),
1118 ),
1119 }, ty);
1120 }
1121796
1122 // Slow path, we have to construct a big-int797 // Slow path, we have to construct a big-int
1123 const abi_size = @as(usize, @intCast(ty.abiSize(mod)));798 const abi_size = @as(usize, @intCast(ty.abiSize(mod)));
...@@ -1129,6 +804,11 @@ pub fn readFromPackedMemory(...@@ -1129,6 +804,11 @@ pub fn readFromPackedMemory(
1129 bigint.readPackedTwosComplement(buffer, bit_offset, bits, endian, int_info.signedness);804 bigint.readPackedTwosComplement(buffer, bit_offset, bits, endian, int_info.signedness);
1130 return mod.intValue_big(ty, bigint.toConst());805 return mod.intValue_big(ty, bigint.toConst());
1131 },806 },
807 .Enum => {
808 const int_ty = ty.intTagType(mod);
809 const int_val = try Value.readFromPackedMemory(int_ty, mod, buffer, bit_offset, arena);
810 return mod.getCoerced(int_val, ty);
811 },
1132 .Float => return Value.fromInterned((try mod.intern(.{ .float = .{812 .Float => return Value.fromInterned((try mod.intern(.{ .float = .{
1133 .ty = ty.toIntern(),813 .ty = ty.toIntern(),
1134 .storage = switch (ty.floatBits(target)) {814 .storage = switch (ty.floatBits(target)) {
...@@ -1149,7 +829,7 @@ pub fn readFromPackedMemory(...@@ -1149,7 +829,7 @@ pub fn readFromPackedMemory(
1149 for (elems, 0..) |_, i| {829 for (elems, 0..) |_, i| {
1150 // On big-endian systems, LLVM reverses the element order of vectors by default830 // On big-endian systems, LLVM reverses the element order of vectors by default
1151 const tgt_elem_i = if (endian == .big) elems.len - i - 1 else i;831 const tgt_elem_i = if (endian == .big) elems.len - i - 1 else i;
1152 elems[tgt_elem_i] = try (try readFromPackedMemory(elem_ty, mod, buffer, bit_offset + bits, arena)).intern(elem_ty, mod);832 elems[tgt_elem_i] = (try readFromPackedMemory(elem_ty, mod, buffer, bit_offset + bits, arena)).toIntern();
1153 bits += elem_bit_size;833 bits += elem_bit_size;
1154 }834 }
1155 return Value.fromInterned((try mod.intern(.{ .aggregate = .{835 return Value.fromInterned((try mod.intern(.{ .aggregate = .{
...@@ -1166,7 +846,7 @@ pub fn readFromPackedMemory(...@@ -1166,7 +846,7 @@ pub fn readFromPackedMemory(
1166 for (field_vals, 0..) |*field_val, i| {846 for (field_vals, 0..) |*field_val, i| {
1167 const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[i]);847 const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[i]);
1168 const field_bits: u16 = @intCast(field_ty.bitSize(mod));848 const field_bits: u16 = @intCast(field_ty.bitSize(mod));
1169 field_val.* = try (try readFromPackedMemory(field_ty, mod, buffer, bit_offset + bits, arena)).intern(field_ty, mod);849 field_val.* = (try readFromPackedMemory(field_ty, mod, buffer, bit_offset + bits, arena)).toIntern();
1170 bits += field_bits;850 bits += field_bits;
1171 }851 }
1172 return Value.fromInterned((try mod.intern(.{ .aggregate = .{852 return Value.fromInterned((try mod.intern(.{ .aggregate = .{
...@@ -1581,80 +1261,34 @@ pub fn slicePtr(val: Value, mod: *Module) Value {...@@ -1581,80 +1261,34 @@ pub fn slicePtr(val: Value, mod: *Module) Value {
1581 return Value.fromInterned(mod.intern_pool.slicePtr(val.toIntern()));1261 return Value.fromInterned(mod.intern_pool.slicePtr(val.toIntern()));
1582}1262}
15831263
1584pub fn sliceLen(val: Value, mod: *Module) u64 {1264/// Gets the `len` field of a slice value as a `u64`.
1585 const ip = &mod.intern_pool;1265/// Resolves the length using the provided `Sema` if necessary.
1586 return switch (ip.indexToKey(val.toIntern())) {1266pub fn sliceLen(val: Value, sema: *Sema) !u64 {
1587 .ptr => |ptr| switch (ip.indexToKey(switch (ptr.addr) {1267 return Value.fromInterned(sema.mod.intern_pool.sliceLen(val.toIntern())).toUnsignedIntAdvanced(sema);
1588 .decl => |decl| mod.declPtr(decl).ty.toIntern(),
1589 .comptime_alloc => @panic("TODO"),
1590 .anon_decl => |anon_decl| ip.typeOf(anon_decl.val),
1591 .comptime_field => |comptime_field| ip.typeOf(comptime_field),
1592 else => unreachable,
1593 })) {
1594 .array_type => |array_type| array_type.len,
1595 else => 1,
1596 },
1597 .slice => |slice| Value.fromInterned(slice.len).toUnsignedInt(mod),
1598 else => unreachable,
1599 };
1600}1268}
16011269
1602/// Asserts the value is a single-item pointer to an array, or an array,1270/// Asserts the value is an aggregate, and returns the element value at the given index.
1603/// or an unknown-length pointer, and returns the element value at the index.1271pub fn elemValue(val: Value, zcu: *Zcu, index: usize) Allocator.Error!Value {
1604pub fn elemValue(val: Value, mod: *Module, index: usize) Allocator.Error!Value {1272 const ip = &zcu.intern_pool;
1605 return (try val.maybeElemValue(mod, index)).?;1273 switch (zcu.intern_pool.indexToKey(val.toIntern())) {
1606}1274 .undef => |ty| {
16071275 return Value.fromInterned(try zcu.intern(.{ .undef = Type.fromInterned(ty).childType(zcu).toIntern() }));
1608/// Like `elemValue`, but returns `null` instead of asserting on failure.
1609pub fn maybeElemValue(val: Value, mod: *Module, index: usize) Allocator.Error!?Value {
1610 return val.maybeElemValueFull(null, mod, index);
1611}
1612
1613pub fn maybeElemValueFull(val: Value, sema: ?*Sema, mod: *Module, index: usize) Allocator.Error!?Value {
1614 return switch (val.ip_index) {
1615 .none => switch (val.tag()) {
1616 .bytes => try mod.intValue(Type.u8, val.castTag(.bytes).?.data[index]),
1617 .repeated => val.castTag(.repeated).?.data,
1618 .aggregate => val.castTag(.aggregate).?.data[index],
1619 .slice => val.castTag(.slice).?.data.ptr.maybeElemValueFull(sema, mod, index),
1620 else => null,
1621 },1276 },
1622 else => switch (mod.intern_pool.indexToKey(val.toIntern())) {1277 .aggregate => |aggregate| {
1623 .undef => |ty| Value.fromInterned((try mod.intern(.{1278 const len = ip.aggregateTypeLen(aggregate.ty);
1624 .undef = Type.fromInterned(ty).elemType2(mod).toIntern(),1279 if (index < len) return Value.fromInterned(switch (aggregate.storage) {
1625 }))),1280 .bytes => |bytes| try zcu.intern(.{ .int = .{
1626 .slice => |slice| return Value.fromInterned(slice.ptr).maybeElemValueFull(sema, mod, index),1281 .ty = .u8_type,
1627 .ptr => |ptr| switch (ptr.addr) {1282 .storage = .{ .u64 = bytes[index] },
1628 .decl => |decl| mod.declPtr(decl).val.maybeElemValueFull(sema, mod, index),1283 } }),
1629 .anon_decl => |anon_decl| Value.fromInterned(anon_decl.val).maybeElemValueFull(sema, mod, index),1284 .elems => |elems| elems[index],
1630 .comptime_alloc => |idx| if (sema) |s| s.getComptimeAlloc(idx).val.maybeElemValueFull(sema, mod, index) else null,1285 .repeated_elem => |elem| elem,
1631 .int, .eu_payload => null,1286 });
1632 .opt_payload => |base| Value.fromInterned(base).maybeElemValueFull(sema, mod, index),1287 assert(index == len);
1633 .comptime_field => |field_val| Value.fromInterned(field_val).maybeElemValueFull(sema, mod, index),1288 return Type.fromInterned(aggregate.ty).sentinel(zcu).?;
1634 .elem => |elem| Value.fromInterned(elem.base).maybeElemValueFull(sema, mod, index + @as(usize, @intCast(elem.index))),
1635 .field => |field| if (Value.fromInterned(field.base).pointerDecl(mod)) |decl_index| {
1636 const base_decl = mod.declPtr(decl_index);
1637 const field_val = try base_decl.val.fieldValue(mod, @as(usize, @intCast(field.index)));
1638 return field_val.maybeElemValueFull(sema, mod, index);
1639 } else null,
1640 },
1641 .opt => |opt| Value.fromInterned(opt.val).maybeElemValueFull(sema, mod, index),
1642 .aggregate => |aggregate| {
1643 const len = mod.intern_pool.aggregateTypeLen(aggregate.ty);
1644 if (index < len) return Value.fromInterned(switch (aggregate.storage) {
1645 .bytes => |bytes| try mod.intern(.{ .int = .{
1646 .ty = .u8_type,
1647 .storage = .{ .u64 = bytes[index] },
1648 } }),
1649 .elems => |elems| elems[index],
1650 .repeated_elem => |elem| elem,
1651 });
1652 assert(index == len);
1653 return Value.fromInterned(mod.intern_pool.indexToKey(aggregate.ty).array_type.sentinel);
1654 },
1655 else => null,
1656 },1289 },
1657 };1290 else => unreachable,
1291 }
1658}1292}
16591293
1660pub fn isLazyAlign(val: Value, mod: *Module) bool {1294pub fn isLazyAlign(val: Value, mod: *Module) bool {
...@@ -1686,83 +1320,48 @@ pub fn sliceArray(...@@ -1686,83 +1320,48 @@ pub fn sliceArray(
1686) error{OutOfMemory}!Value {1320) error{OutOfMemory}!Value {
1687 // TODO: write something like getCoercedInts to avoid needing to dupe1321 // TODO: write something like getCoercedInts to avoid needing to dupe
1688 const mod = sema.mod;1322 const mod = sema.mod;
1689 return switch (val.ip_index) {1323 const aggregate = mod.intern_pool.indexToKey(val.toIntern()).aggregate;
1690 .none => switch (val.tag()) {1324 return Value.fromInterned(try mod.intern(.{ .aggregate = .{
1691 .slice => val.castTag(.slice).?.data.ptr.sliceArray(sema, start, end),1325 .ty = switch (mod.intern_pool.indexToKey(mod.intern_pool.typeOf(val.toIntern()))) {
1692 .bytes => Tag.bytes.create(sema.arena, val.castTag(.bytes).?.data[start..end]),1326 .array_type => |array_type| try mod.arrayType(.{
1693 .repeated => val,1327 .len = @as(u32, @intCast(end - start)),
1694 .aggregate => Tag.aggregate.create(sema.arena, val.castTag(.aggregate).?.data[start..end]),1328 .child = array_type.child,
1695 else => unreachable,1329 .sentinel = if (end == array_type.len) array_type.sentinel else .none,
1696 },1330 }),
1697 else => switch (mod.intern_pool.indexToKey(val.toIntern())) {1331 .vector_type => |vector_type| try mod.vectorType(.{
1698 .ptr => |ptr| switch (ptr.addr) {1332 .len = @as(u32, @intCast(end - start)),
1699 .decl => |decl| try mod.declPtr(decl).val.sliceArray(sema, start, end),1333 .child = vector_type.child,
1700 .comptime_alloc => |idx| sema.getComptimeAlloc(idx).val.sliceArray(sema, start, end),1334 }),
1701 .comptime_field => |comptime_field| Value.fromInterned(comptime_field)
1702 .sliceArray(sema, start, end),
1703 .elem => |elem| Value.fromInterned(elem.base)
1704 .sliceArray(sema, start + @as(usize, @intCast(elem.index)), end + @as(usize, @intCast(elem.index))),
1705 else => unreachable,
1706 },
1707 .aggregate => |aggregate| Value.fromInterned((try mod.intern(.{ .aggregate = .{
1708 .ty = switch (mod.intern_pool.indexToKey(mod.intern_pool.typeOf(val.toIntern()))) {
1709 .array_type => |array_type| try mod.arrayType(.{
1710 .len = @as(u32, @intCast(end - start)),
1711 .child = array_type.child,
1712 .sentinel = if (end == array_type.len) array_type.sentinel else .none,
1713 }),
1714 .vector_type => |vector_type| try mod.vectorType(.{
1715 .len = @as(u32, @intCast(end - start)),
1716 .child = vector_type.child,
1717 }),
1718 else => unreachable,
1719 }.toIntern(),
1720 .storage = switch (aggregate.storage) {
1721 .bytes => .{ .bytes = try sema.arena.dupe(u8, mod.intern_pool.indexToKey(val.toIntern()).aggregate.storage.bytes[start..end]) },
1722 .elems => .{ .elems = try sema.arena.dupe(InternPool.Index, mod.intern_pool.indexToKey(val.toIntern()).aggregate.storage.elems[start..end]) },
1723 .repeated_elem => |elem| .{ .repeated_elem = elem },
1724 },
1725 } }))),
1726 else => unreachable,1335 else => unreachable,
1336 }.toIntern(),
1337 .storage = switch (aggregate.storage) {
1338 .bytes => .{ .bytes = try sema.arena.dupe(u8, mod.intern_pool.indexToKey(val.toIntern()).aggregate.storage.bytes[start..end]) },
1339 .elems => .{ .elems = try sema.arena.dupe(InternPool.Index, mod.intern_pool.indexToKey(val.toIntern()).aggregate.storage.elems[start..end]) },
1340 .repeated_elem => |elem| .{ .repeated_elem = elem },
1727 },1341 },
1728 };1342 } }));
1729}1343}
17301344
1731pub fn fieldValue(val: Value, mod: *Module, index: usize) !Value {1345pub fn fieldValue(val: Value, mod: *Module, index: usize) !Value {
1732 return switch (val.ip_index) {1346 return switch (mod.intern_pool.indexToKey(val.toIntern())) {
1733 .none => switch (val.tag()) {1347 .undef => |ty| Value.fromInterned((try mod.intern(.{
1734 .aggregate => {1348 .undef = Type.fromInterned(ty).structFieldType(index, mod).toIntern(),
1735 const field_values = val.castTag(.aggregate).?.data;1349 }))),
1736 return field_values[index];1350 .aggregate => |aggregate| Value.fromInterned(switch (aggregate.storage) {
1737 },1351 .bytes => |bytes| try mod.intern(.{ .int = .{
1738 .@"union" => {1352 .ty = .u8_type,
1739 const payload = val.castTag(.@"union").?.data;1353 .storage = .{ .u64 = bytes[index] },
1740 // TODO assert the tag is correct1354 } }),
1741 return payload.val;1355 .elems => |elems| elems[index],
1742 },1356 .repeated_elem => |elem| elem,
1743 else => unreachable,1357 }),
1744 },1358 // TODO assert the tag is correct
1745 else => switch (mod.intern_pool.indexToKey(val.toIntern())) {1359 .un => |un| Value.fromInterned(un.val),
1746 .undef => |ty| Value.fromInterned((try mod.intern(.{1360 else => unreachable,
1747 .undef = Type.fromInterned(ty).structFieldType(index, mod).toIntern(),
1748 }))),
1749 .aggregate => |aggregate| Value.fromInterned(switch (aggregate.storage) {
1750 .bytes => |bytes| try mod.intern(.{ .int = .{
1751 .ty = .u8_type,
1752 .storage = .{ .u64 = bytes[index] },
1753 } }),
1754 .elems => |elems| elems[index],
1755 .repeated_elem => |elem| elem,
1756 }),
1757 // TODO assert the tag is correct
1758 .un => |un| Value.fromInterned(un.val),
1759 else => unreachable,
1760 },
1761 };1361 };
1762}1362}
17631363
1764pub fn unionTag(val: Value, mod: *Module) ?Value {1364pub fn unionTag(val: Value, mod: *Module) ?Value {
1765 if (val.ip_index == .none) return val.castTag(.@"union").?.data.tag;
1766 return switch (mod.intern_pool.indexToKey(val.toIntern())) {1365 return switch (mod.intern_pool.indexToKey(val.toIntern())) {
1767 .undef, .enum_tag => val,1366 .undef, .enum_tag => val,
1768 .un => |un| if (un.tag != .none) Value.fromInterned(un.tag) else return null,1367 .un => |un| if (un.tag != .none) Value.fromInterned(un.tag) else return null,
...@@ -1771,7 +1370,6 @@ pub fn unionTag(val: Value, mod: *Module) ?Value {...@@ -1771,7 +1370,6 @@ pub fn unionTag(val: Value, mod: *Module) ?Value {
1771}1370}
17721371
1773pub fn unionValue(val: Value, mod: *Module) Value {1372pub fn unionValue(val: Value, mod: *Module) Value {
1774 if (val.ip_index == .none) return val.castTag(.@"union").?.data.val;
1775 return switch (mod.intern_pool.indexToKey(val.toIntern())) {1373 return switch (mod.intern_pool.indexToKey(val.toIntern())) {
1776 .un => |un| Value.fromInterned(un.val),1374 .un => |un| Value.fromInterned(un.val),
1777 else => unreachable,1375 else => unreachable,
...@@ -1792,7 +1390,7 @@ pub fn elemPtr(...@@ -1792,7 +1390,7 @@ pub fn elemPtr(
1792 };1390 };
1793 switch (mod.intern_pool.indexToKey(ptr_val.toIntern())) {1391 switch (mod.intern_pool.indexToKey(ptr_val.toIntern())) {
1794 .ptr => |ptr| switch (ptr.addr) {1392 .ptr => |ptr| switch (ptr.addr) {
1795 .elem => |elem| if (Type.fromInterned(mod.intern_pool.typeOf(elem.base)).elemType2(mod).eql(elem_ty, mod))1393 .elem => |elem| if (Value.fromInterned(elem.base).typeOf(mod).elemType2(mod).eql(elem_ty, mod))
1796 return Value.fromInterned((try mod.intern(.{ .ptr = .{1394 return Value.fromInterned((try mod.intern(.{ .ptr = .{
1797 .ty = elem_ptr_ty.toIntern(),1395 .ty = elem_ptr_ty.toIntern(),
1798 .addr = .{ .elem = .{1396 .addr = .{ .elem = .{
...@@ -1817,7 +1415,7 @@ pub fn elemPtr(...@@ -1817,7 +1415,7 @@ pub fn elemPtr(
1817}1415}
18181416
1819pub fn isUndef(val: Value, mod: *Module) bool {1417pub fn isUndef(val: Value, mod: *Module) bool {
1820 return val.ip_index != .none and mod.intern_pool.isUndef(val.toIntern());1418 return mod.intern_pool.isUndef(val.toIntern());
1821}1419}
18221420
1823/// TODO: check for cases such as array that is not marked undef but all the element1421/// TODO: check for cases such as array that is not marked undef but all the element
...@@ -1911,7 +1509,7 @@ pub fn floatFromIntAdvanced(val: Value, arena: Allocator, int_ty: Type, float_ty...@@ -1911,7 +1509,7 @@ pub fn floatFromIntAdvanced(val: Value, arena: Allocator, int_ty: Type, float_ty
1911 const scalar_ty = float_ty.scalarType(mod);1509 const scalar_ty = float_ty.scalarType(mod);
1912 for (result_data, 0..) |*scalar, i| {1510 for (result_data, 0..) |*scalar, i| {
1913 const elem_val = try val.elemValue(mod, i);1511 const elem_val = try val.elemValue(mod, i);
1914 scalar.* = try (try floatFromIntScalar(elem_val, scalar_ty, mod, opt_sema)).intern(scalar_ty, mod);1512 scalar.* = (try floatFromIntScalar(elem_val, scalar_ty, mod, opt_sema)).toIntern();
1915 }1513 }
1916 return Value.fromInterned((try mod.intern(.{ .aggregate = .{1514 return Value.fromInterned((try mod.intern(.{ .aggregate = .{
1917 .ty = float_ty.toIntern(),1515 .ty = float_ty.toIntern(),
...@@ -1989,7 +1587,7 @@ pub fn intAddSat(...@@ -1989,7 +1587,7 @@ pub fn intAddSat(
1989 for (result_data, 0..) |*scalar, i| {1587 for (result_data, 0..) |*scalar, i| {
1990 const lhs_elem = try lhs.elemValue(mod, i);1588 const lhs_elem = try lhs.elemValue(mod, i);
1991 const rhs_elem = try rhs.elemValue(mod, i);1589 const rhs_elem = try rhs.elemValue(mod, i);
1992 scalar.* = try (try intAddSatScalar(lhs_elem, rhs_elem, scalar_ty, arena, mod)).intern(scalar_ty, mod);1590 scalar.* = (try intAddSatScalar(lhs_elem, rhs_elem, scalar_ty, arena, mod)).toIntern();
1993 }1591 }
1994 return Value.fromInterned((try mod.intern(.{ .aggregate = .{1592 return Value.fromInterned((try mod.intern(.{ .aggregate = .{
1995 .ty = ty.toIntern(),1593 .ty = ty.toIntern(),
...@@ -2039,7 +1637,7 @@ pub fn intSubSat(...@@ -2039,7 +1637,7 @@ pub fn intSubSat(
2039 for (result_data, 0..) |*scalar, i| {1637 for (result_data, 0..) |*scalar, i| {
2040 const lhs_elem = try lhs.elemValue(mod, i);1638 const lhs_elem = try lhs.elemValue(mod, i);
2041 const rhs_elem = try rhs.elemValue(mod, i);1639 const rhs_elem = try rhs.elemValue(mod, i);
2042 scalar.* = try (try intSubSatScalar(lhs_elem, rhs_elem, scalar_ty, arena, mod)).intern(scalar_ty, mod);1640 scalar.* = (try intSubSatScalar(lhs_elem, rhs_elem, scalar_ty, arena, mod)).toIntern();
2043 }1641 }
2044 return Value.fromInterned((try mod.intern(.{ .aggregate = .{1642 return Value.fromInterned((try mod.intern(.{ .aggregate = .{
2045 .ty = ty.toIntern(),1643 .ty = ty.toIntern(),
...@@ -2091,8 +1689,8 @@ pub fn intMulWithOverflow(...@@ -2091,8 +1689,8 @@ pub fn intMulWithOverflow(
2091 const lhs_elem = try lhs.elemValue(mod, i);1689 const lhs_elem = try lhs.elemValue(mod, i);
2092 const rhs_elem = try rhs.elemValue(mod, i);1690 const rhs_elem = try rhs.elemValue(mod, i);
2093 const of_math_result = try intMulWithOverflowScalar(lhs_elem, rhs_elem, scalar_ty, arena, mod);1691 const of_math_result = try intMulWithOverflowScalar(lhs_elem, rhs_elem, scalar_ty, arena, mod);
2094 of.* = try of_math_result.overflow_bit.intern(Type.u1, mod);1692 of.* = of_math_result.overflow_bit.toIntern();
2095 scalar.* = try of_math_result.wrapped_result.intern(scalar_ty, mod);1693 scalar.* = of_math_result.wrapped_result.toIntern();
2096 }1694 }
2097 return OverflowArithmeticResult{1695 return OverflowArithmeticResult{
2098 .overflow_bit = Value.fromInterned((try mod.intern(.{ .aggregate = .{1696 .overflow_bit = Value.fromInterned((try mod.intern(.{ .aggregate = .{
...@@ -2157,7 +1755,7 @@ pub fn numberMulWrap(...@@ -2157,7 +1755,7 @@ pub fn numberMulWrap(
2157 for (result_data, 0..) |*scalar, i| {1755 for (result_data, 0..) |*scalar, i| {
2158 const lhs_elem = try lhs.elemValue(mod, i);1756 const lhs_elem = try lhs.elemValue(mod, i);
2159 const rhs_elem = try rhs.elemValue(mod, i);1757 const rhs_elem = try rhs.elemValue(mod, i);
2160 scalar.* = try (try numberMulWrapScalar(lhs_elem, rhs_elem, scalar_ty, arena, mod)).intern(scalar_ty, mod);1758 scalar.* = (try numberMulWrapScalar(lhs_elem, rhs_elem, scalar_ty, arena, mod)).toIntern();
2161 }1759 }
2162 return Value.fromInterned((try mod.intern(.{ .aggregate = .{1760 return Value.fromInterned((try mod.intern(.{ .aggregate = .{
2163 .ty = ty.toIntern(),1761 .ty = ty.toIntern(),
...@@ -2203,7 +1801,7 @@ pub fn intMulSat(...@@ -2203,7 +1801,7 @@ pub fn intMulSat(
2203 for (result_data, 0..) |*scalar, i| {1801 for (result_data, 0..) |*scalar, i| {
2204 const lhs_elem = try lhs.elemValue(mod, i);1802 const lhs_elem = try lhs.elemValue(mod, i);
2205 const rhs_elem = try rhs.elemValue(mod, i);1803 const rhs_elem = try rhs.elemValue(mod, i);
2206 scalar.* = try (try intMulSatScalar(lhs_elem, rhs_elem, scalar_ty, arena, mod)).intern(scalar_ty, mod);1804 scalar.* = (try intMulSatScalar(lhs_elem, rhs_elem, scalar_ty, arena, mod)).toIntern();
2207 }1805 }
2208 return Value.fromInterned((try mod.intern(.{ .aggregate = .{1806 return Value.fromInterned((try mod.intern(.{ .aggregate = .{
2209 .ty = ty.toIntern(),1807 .ty = ty.toIntern(),
...@@ -2279,7 +1877,7 @@ pub fn bitwiseNot(val: Value, ty: Type, arena: Allocator, mod: *Module) !Value {...@@ -2279,7 +1877,7 @@ pub fn bitwiseNot(val: Value, ty: Type, arena: Allocator, mod: *Module) !Value {
2279 const scalar_ty = ty.scalarType(mod);1877 const scalar_ty = ty.scalarType(mod);
2280 for (result_data, 0..) |*scalar, i| {1878 for (result_data, 0..) |*scalar, i| {
2281 const elem_val = try val.elemValue(mod, i);1879 const elem_val = try val.elemValue(mod, i);
2282 scalar.* = try (try bitwiseNotScalar(elem_val, scalar_ty, arena, mod)).intern(scalar_ty, mod);1880 scalar.* = (try bitwiseNotScalar(elem_val, scalar_ty, arena, mod)).toIntern();
2283 }1881 }
2284 return Value.fromInterned((try mod.intern(.{ .aggregate = .{1882 return Value.fromInterned((try mod.intern(.{ .aggregate = .{
2285 .ty = ty.toIntern(),1883 .ty = ty.toIntern(),
...@@ -2322,7 +1920,7 @@ pub fn bitwiseAnd(lhs: Value, rhs: Value, ty: Type, allocator: Allocator, mod: *...@@ -2322,7 +1920,7 @@ pub fn bitwiseAnd(lhs: Value, rhs: Value, ty: Type, allocator: Allocator, mod: *
2322 for (result_data, 0..) |*scalar, i| {1920 for (result_data, 0..) |*scalar, i| {
2323 const lhs_elem = try lhs.elemValue(mod, i);1921 const lhs_elem = try lhs.elemValue(mod, i);
2324 const rhs_elem = try rhs.elemValue(mod, i);1922 const rhs_elem = try rhs.elemValue(mod, i);
2325 scalar.* = try (try bitwiseAndScalar(lhs_elem, rhs_elem, scalar_ty, allocator, mod)).intern(scalar_ty, mod);1923 scalar.* = (try bitwiseAndScalar(lhs_elem, rhs_elem, scalar_ty, allocator, mod)).toIntern();
2326 }1924 }
2327 return Value.fromInterned((try mod.intern(.{ .aggregate = .{1925 return Value.fromInterned((try mod.intern(.{ .aggregate = .{
2328 .ty = ty.toIntern(),1926 .ty = ty.toIntern(),
...@@ -2361,7 +1959,7 @@ pub fn bitwiseNand(lhs: Value, rhs: Value, ty: Type, arena: Allocator, mod: *Mod...@@ -2361,7 +1959,7 @@ pub fn bitwiseNand(lhs: Value, rhs: Value, ty: Type, arena: Allocator, mod: *Mod
2361 for (result_data, 0..) |*scalar, i| {1959 for (result_data, 0..) |*scalar, i| {
2362 const lhs_elem = try lhs.elemValue(mod, i);1960 const lhs_elem = try lhs.elemValue(mod, i);
2363 const rhs_elem = try rhs.elemValue(mod, i);1961 const rhs_elem = try rhs.elemValue(mod, i);
2364 scalar.* = try (try bitwiseNandScalar(lhs_elem, rhs_elem, scalar_ty, arena, mod)).intern(scalar_ty, mod);1962 scalar.* = (try bitwiseNandScalar(lhs_elem, rhs_elem, scalar_ty, arena, mod)).toIntern();
2365 }1963 }
2366 return Value.fromInterned((try mod.intern(.{ .aggregate = .{1964 return Value.fromInterned((try mod.intern(.{ .aggregate = .{
2367 .ty = ty.toIntern(),1965 .ty = ty.toIntern(),
...@@ -2389,7 +1987,7 @@ pub fn bitwiseOr(lhs: Value, rhs: Value, ty: Type, allocator: Allocator, mod: *M...@@ -2389,7 +1987,7 @@ pub fn bitwiseOr(lhs: Value, rhs: Value, ty: Type, allocator: Allocator, mod: *M
2389 for (result_data, 0..) |*scalar, i| {1987 for (result_data, 0..) |*scalar, i| {
2390 const lhs_elem = try lhs.elemValue(mod, i);1988 const lhs_elem = try lhs.elemValue(mod, i);
2391 const rhs_elem = try rhs.elemValue(mod, i);1989 const rhs_elem = try rhs.elemValue(mod, i);
2392 scalar.* = try (try bitwiseOrScalar(lhs_elem, rhs_elem, scalar_ty, allocator, mod)).intern(scalar_ty, mod);1990 scalar.* = (try bitwiseOrScalar(lhs_elem, rhs_elem, scalar_ty, allocator, mod)).toIntern();
2393 }1991 }
2394 return Value.fromInterned((try mod.intern(.{ .aggregate = .{1992 return Value.fromInterned((try mod.intern(.{ .aggregate = .{
2395 .ty = ty.toIntern(),1993 .ty = ty.toIntern(),
...@@ -2427,7 +2025,7 @@ pub fn bitwiseXor(lhs: Value, rhs: Value, ty: Type, allocator: Allocator, mod: *...@@ -2427,7 +2025,7 @@ pub fn bitwiseXor(lhs: Value, rhs: Value, ty: Type, allocator: Allocator, mod: *
2427 for (result_data, 0..) |*scalar, i| {2025 for (result_data, 0..) |*scalar, i| {
2428 const lhs_elem = try lhs.elemValue(mod, i);2026 const lhs_elem = try lhs.elemValue(mod, i);
2429 const rhs_elem = try rhs.elemValue(mod, i);2027 const rhs_elem = try rhs.elemValue(mod, i);
2430 scalar.* = try (try bitwiseXorScalar(lhs_elem, rhs_elem, scalar_ty, allocator, mod)).intern(scalar_ty, mod);2028 scalar.* = (try bitwiseXorScalar(lhs_elem, rhs_elem, scalar_ty, allocator, mod)).toIntern();
2431 }2029 }
2432 return Value.fromInterned((try mod.intern(.{ .aggregate = .{2030 return Value.fromInterned((try mod.intern(.{ .aggregate = .{
2433 .ty = ty.toIntern(),2031 .ty = ty.toIntern(),
...@@ -2493,7 +2091,7 @@ fn intDivInner(lhs: Value, rhs: Value, ty: Type, overflow_idx: *usize, allocator...@@ -2493,7 +2091,7 @@ fn intDivInner(lhs: Value, rhs: Value, ty: Type, overflow_idx: *usize, allocator
2493 },2091 },
2494 else => |e| return e,2092 else => |e| return e,
2495 };2093 };
2496 scalar.* = try val.intern(scalar_ty, mod);2094 scalar.* = val.toIntern();
2497 }2095 }
2498 return Value.fromInterned((try mod.intern(.{ .aggregate = .{2096 return Value.fromInterned((try mod.intern(.{ .aggregate = .{
2499 .ty = ty.toIntern(),2097 .ty = ty.toIntern(),
...@@ -2541,7 +2139,7 @@ pub fn intDivFloor(lhs: Value, rhs: Value, ty: Type, allocator: Allocator, mod:...@@ -2541,7 +2139,7 @@ pub fn intDivFloor(lhs: Value, rhs: Value, ty: Type, allocator: Allocator, mod:
2541 for (result_data, 0..) |*scalar, i| {2139 for (result_data, 0..) |*scalar, i| {
2542 const lhs_elem = try lhs.elemValue(mod, i);2140 const lhs_elem = try lhs.elemValue(mod, i);
2543 const rhs_elem = try rhs.elemValue(mod, i);2141 const rhs_elem = try rhs.elemValue(mod, i);
2544 scalar.* = try (try intDivFloorScalar(lhs_elem, rhs_elem, scalar_ty, allocator, mod)).intern(scalar_ty, mod);2142 scalar.* = (try intDivFloorScalar(lhs_elem, rhs_elem, scalar_ty, allocator, mod)).toIntern();
2545 }2143 }
2546 return Value.fromInterned((try mod.intern(.{ .aggregate = .{2144 return Value.fromInterned((try mod.intern(.{ .aggregate = .{
2547 .ty = ty.toIntern(),2145 .ty = ty.toIntern(),
...@@ -2583,7 +2181,7 @@ pub fn intMod(lhs: Value, rhs: Value, ty: Type, allocator: Allocator, mod: *Modu...@@ -2583,7 +2181,7 @@ pub fn intMod(lhs: Value, rhs: Value, ty: Type, allocator: Allocator, mod: *Modu
2583 for (result_data, 0..) |*scalar, i| {2181 for (result_data, 0..) |*scalar, i| {
2584 const lhs_elem = try lhs.elemValue(mod, i);2182 const lhs_elem = try lhs.elemValue(mod, i);
2585 const rhs_elem = try rhs.elemValue(mod, i);2183 const rhs_elem = try rhs.elemValue(mod, i);
2586 scalar.* = try (try intModScalar(lhs_elem, rhs_elem, scalar_ty, allocator, mod)).intern(scalar_ty, mod);2184 scalar.* = (try intModScalar(lhs_elem, rhs_elem, scalar_ty, allocator, mod)).toIntern();
2587 }2185 }
2588 return Value.fromInterned((try mod.intern(.{ .aggregate = .{2186 return Value.fromInterned((try mod.intern(.{ .aggregate = .{
2589 .ty = ty.toIntern(),2187 .ty = ty.toIntern(),
...@@ -2620,7 +2218,6 @@ pub fn intModScalar(lhs: Value, rhs: Value, ty: Type, allocator: Allocator, mod:...@@ -2620,7 +2218,6 @@ pub fn intModScalar(lhs: Value, rhs: Value, ty: Type, allocator: Allocator, mod:
26202218
2621/// Returns true if the value is a floating point type and is NaN. Returns false otherwise.2219/// Returns true if the value is a floating point type and is NaN. Returns false otherwise.
2622pub fn isNan(val: Value, mod: *const Module) bool {2220pub fn isNan(val: Value, mod: *const Module) bool {
2623 if (val.ip_index == .none) return false;
2624 return switch (mod.intern_pool.indexToKey(val.toIntern())) {2221 return switch (mod.intern_pool.indexToKey(val.toIntern())) {
2625 .float => |float| switch (float.storage) {2222 .float => |float| switch (float.storage) {
2626 inline else => |x| std.math.isNan(x),2223 inline else => |x| std.math.isNan(x),
...@@ -2631,7 +2228,6 @@ pub fn isNan(val: Value, mod: *const Module) bool {...@@ -2631,7 +2228,6 @@ pub fn isNan(val: Value, mod: *const Module) bool {
26312228
2632/// Returns true if the value is a floating point type and is infinite. Returns false otherwise.2229/// Returns true if the value is a floating point type and is infinite. Returns false otherwise.
2633pub fn isInf(val: Value, mod: *const Module) bool {2230pub fn isInf(val: Value, mod: *const Module) bool {
2634 if (val.ip_index == .none) return false;
2635 return switch (mod.intern_pool.indexToKey(val.toIntern())) {2231 return switch (mod.intern_pool.indexToKey(val.toIntern())) {
2636 .float => |float| switch (float.storage) {2232 .float => |float| switch (float.storage) {
2637 inline else => |x| std.math.isInf(x),2233 inline else => |x| std.math.isInf(x),
...@@ -2641,7 +2237,6 @@ pub fn isInf(val: Value, mod: *const Module) bool {...@@ -2641,7 +2237,6 @@ pub fn isInf(val: Value, mod: *const Module) bool {
2641}2237}
26422238
2643pub fn isNegativeInf(val: Value, mod: *const Module) bool {2239pub fn isNegativeInf(val: Value, mod: *const Module) bool {
2644 if (val.ip_index == .none) return false;
2645 return switch (mod.intern_pool.indexToKey(val.toIntern())) {2240 return switch (mod.intern_pool.indexToKey(val.toIntern())) {
2646 .float => |float| switch (float.storage) {2241 .float => |float| switch (float.storage) {
2647 inline else => |x| std.math.isNegativeInf(x),2242 inline else => |x| std.math.isNegativeInf(x),
...@@ -2657,7 +2252,7 @@ pub fn floatRem(lhs: Value, rhs: Value, float_type: Type, arena: Allocator, mod:...@@ -2657,7 +2252,7 @@ pub fn floatRem(lhs: Value, rhs: Value, float_type: Type, arena: Allocator, mod:
2657 for (result_data, 0..) |*scalar, i| {2252 for (result_data, 0..) |*scalar, i| {
2658 const lhs_elem = try lhs.elemValue(mod, i);2253 const lhs_elem = try lhs.elemValue(mod, i);
2659 const rhs_elem = try rhs.elemValue(mod, i);2254 const rhs_elem = try rhs.elemValue(mod, i);
2660 scalar.* = try (try floatRemScalar(lhs_elem, rhs_elem, scalar_ty, mod)).intern(scalar_ty, mod);2255 scalar.* = (try floatRemScalar(lhs_elem, rhs_elem, scalar_ty, mod)).toIntern();
2661 }2256 }
2662 return Value.fromInterned((try mod.intern(.{ .aggregate = .{2257 return Value.fromInterned((try mod.intern(.{ .aggregate = .{
2663 .ty = float_type.toIntern(),2258 .ty = float_type.toIntern(),
...@@ -2690,7 +2285,7 @@ pub fn floatMod(lhs: Value, rhs: Value, float_type: Type, arena: Allocator, mod:...@@ -2690,7 +2285,7 @@ pub fn floatMod(lhs: Value, rhs: Value, float_type: Type, arena: Allocator, mod:
2690 for (result_data, 0..) |*scalar, i| {2285 for (result_data, 0..) |*scalar, i| {
2691 const lhs_elem = try lhs.elemValue(mod, i);2286 const lhs_elem = try lhs.elemValue(mod, i);
2692 const rhs_elem = try rhs.elemValue(mod, i);2287 const rhs_elem = try rhs.elemValue(mod, i);
2693 scalar.* = try (try floatModScalar(lhs_elem, rhs_elem, scalar_ty, mod)).intern(scalar_ty, mod);2288 scalar.* = (try floatModScalar(lhs_elem, rhs_elem, scalar_ty, mod)).toIntern();
2694 }2289 }
2695 return Value.fromInterned((try mod.intern(.{ .aggregate = .{2290 return Value.fromInterned((try mod.intern(.{ .aggregate = .{
2696 .ty = float_type.toIntern(),2291 .ty = float_type.toIntern(),
...@@ -2751,7 +2346,7 @@ fn intMulInner(lhs: Value, rhs: Value, ty: Type, overflow_idx: *usize, allocator...@@ -2751,7 +2346,7 @@ fn intMulInner(lhs: Value, rhs: Value, ty: Type, overflow_idx: *usize, allocator
2751 },2346 },
2752 else => |e| return e,2347 else => |e| return e,
2753 };2348 };
2754 scalar.* = try val.intern(scalar_ty, mod);2349 scalar.* = val.toIntern();
2755 }2350 }
2756 return Value.fromInterned((try mod.intern(.{ .aggregate = .{2351 return Value.fromInterned((try mod.intern(.{ .aggregate = .{
2757 .ty = ty.toIntern(),2352 .ty = ty.toIntern(),
...@@ -2793,7 +2388,7 @@ pub fn intTrunc(val: Value, ty: Type, allocator: Allocator, signedness: std.buil...@@ -2793,7 +2388,7 @@ pub fn intTrunc(val: Value, ty: Type, allocator: Allocator, signedness: std.buil
2793 const scalar_ty = ty.scalarType(mod);2388 const scalar_ty = ty.scalarType(mod);
2794 for (result_data, 0..) |*scalar, i| {2389 for (result_data, 0..) |*scalar, i| {
2795 const elem_val = try val.elemValue(mod, i);2390 const elem_val = try val.elemValue(mod, i);
2796 scalar.* = try (try intTruncScalar(elem_val, scalar_ty, allocator, signedness, bits, mod)).intern(scalar_ty, mod);2391 scalar.* = (try intTruncScalar(elem_val, scalar_ty, allocator, signedness, bits, mod)).toIntern();
2797 }2392 }
2798 return Value.fromInterned((try mod.intern(.{ .aggregate = .{2393 return Value.fromInterned((try mod.intern(.{ .aggregate = .{
2799 .ty = ty.toIntern(),2394 .ty = ty.toIntern(),
...@@ -2818,7 +2413,7 @@ pub fn intTruncBitsAsValue(...@@ -2818,7 +2413,7 @@ pub fn intTruncBitsAsValue(
2818 for (result_data, 0..) |*scalar, i| {2413 for (result_data, 0..) |*scalar, i| {
2819 const elem_val = try val.elemValue(mod, i);2414 const elem_val = try val.elemValue(mod, i);
2820 const bits_elem = try bits.elemValue(mod, i);2415 const bits_elem = try bits.elemValue(mod, i);
2821 scalar.* = try (try intTruncScalar(elem_val, scalar_ty, allocator, signedness, @as(u16, @intCast(bits_elem.toUnsignedInt(mod))), mod)).intern(scalar_ty, mod);2416 scalar.* = (try intTruncScalar(elem_val, scalar_ty, allocator, signedness, @as(u16, @intCast(bits_elem.toUnsignedInt(mod))), mod)).toIntern();
2822 }2417 }
2823 return Value.fromInterned((try mod.intern(.{ .aggregate = .{2418 return Value.fromInterned((try mod.intern(.{ .aggregate = .{
2824 .ty = ty.toIntern(),2419 .ty = ty.toIntern(),
...@@ -2858,7 +2453,7 @@ pub fn shl(lhs: Value, rhs: Value, ty: Type, allocator: Allocator, mod: *Module)...@@ -2858,7 +2453,7 @@ pub fn shl(lhs: Value, rhs: Value, ty: Type, allocator: Allocator, mod: *Module)
2858 for (result_data, 0..) |*scalar, i| {2453 for (result_data, 0..) |*scalar, i| {
2859 const lhs_elem = try lhs.elemValue(mod, i);2454 const lhs_elem = try lhs.elemValue(mod, i);
2860 const rhs_elem = try rhs.elemValue(mod, i);2455 const rhs_elem = try rhs.elemValue(mod, i);
2861 scalar.* = try (try shlScalar(lhs_elem, rhs_elem, scalar_ty, allocator, mod)).intern(scalar_ty, mod);2456 scalar.* = (try shlScalar(lhs_elem, rhs_elem, scalar_ty, allocator, mod)).toIntern();
2862 }2457 }
2863 return Value.fromInterned((try mod.intern(.{ .aggregate = .{2458 return Value.fromInterned((try mod.intern(.{ .aggregate = .{
2864 .ty = ty.toIntern(),2459 .ty = ty.toIntern(),
...@@ -2908,8 +2503,8 @@ pub fn shlWithOverflow(...@@ -2908,8 +2503,8 @@ pub fn shlWithOverflow(
2908 const lhs_elem = try lhs.elemValue(mod, i);2503 const lhs_elem = try lhs.elemValue(mod, i);
2909 const rhs_elem = try rhs.elemValue(mod, i);2504 const rhs_elem = try rhs.elemValue(mod, i);
2910 const of_math_result = try shlWithOverflowScalar(lhs_elem, rhs_elem, scalar_ty, allocator, mod);2505 const of_math_result = try shlWithOverflowScalar(lhs_elem, rhs_elem, scalar_ty, allocator, mod);
2911 of.* = try of_math_result.overflow_bit.intern(Type.u1, mod);2506 of.* = of_math_result.overflow_bit.toIntern();
2912 scalar.* = try of_math_result.wrapped_result.intern(scalar_ty, mod);2507 scalar.* = of_math_result.wrapped_result.toIntern();
2913 }2508 }
2914 return OverflowArithmeticResult{2509 return OverflowArithmeticResult{
2915 .overflow_bit = Value.fromInterned((try mod.intern(.{ .aggregate = .{2510 .overflow_bit = Value.fromInterned((try mod.intern(.{ .aggregate = .{
...@@ -2969,7 +2564,7 @@ pub fn shlSat(...@@ -2969,7 +2564,7 @@ pub fn shlSat(
2969 for (result_data, 0..) |*scalar, i| {2564 for (result_data, 0..) |*scalar, i| {
2970 const lhs_elem = try lhs.elemValue(mod, i);2565 const lhs_elem = try lhs.elemValue(mod, i);
2971 const rhs_elem = try rhs.elemValue(mod, i);2566 const rhs_elem = try rhs.elemValue(mod, i);
2972 scalar.* = try (try shlSatScalar(lhs_elem, rhs_elem, scalar_ty, arena, mod)).intern(scalar_ty, mod);2567 scalar.* = (try shlSatScalar(lhs_elem, rhs_elem, scalar_ty, arena, mod)).toIntern();
2973 }2568 }
2974 return Value.fromInterned((try mod.intern(.{ .aggregate = .{2569 return Value.fromInterned((try mod.intern(.{ .aggregate = .{
2975 .ty = ty.toIntern(),2570 .ty = ty.toIntern(),
...@@ -3019,7 +2614,7 @@ pub fn shlTrunc(...@@ -3019,7 +2614,7 @@ pub fn shlTrunc(
3019 for (result_data, 0..) |*scalar, i| {2614 for (result_data, 0..) |*scalar, i| {
3020 const lhs_elem = try lhs.elemValue(mod, i);2615 const lhs_elem = try lhs.elemValue(mod, i);
3021 const rhs_elem = try rhs.elemValue(mod, i);2616 const rhs_elem = try rhs.elemValue(mod, i);
3022 scalar.* = try (try shlTruncScalar(lhs_elem, rhs_elem, scalar_ty, arena, mod)).intern(scalar_ty, mod);2617 scalar.* = (try shlTruncScalar(lhs_elem, rhs_elem, scalar_ty, arena, mod)).toIntern();
3023 }2618 }
3024 return Value.fromInterned((try mod.intern(.{ .aggregate = .{2619 return Value.fromInterned((try mod.intern(.{ .aggregate = .{
3025 .ty = ty.toIntern(),2620 .ty = ty.toIntern(),
...@@ -3049,7 +2644,7 @@ pub fn shr(lhs: Value, rhs: Value, ty: Type, allocator: Allocator, mod: *Module)...@@ -3049,7 +2644,7 @@ pub fn shr(lhs: Value, rhs: Value, ty: Type, allocator: Allocator, mod: *Module)
3049 for (result_data, 0..) |*scalar, i| {2644 for (result_data, 0..) |*scalar, i| {
3050 const lhs_elem = try lhs.elemValue(mod, i);2645 const lhs_elem = try lhs.elemValue(mod, i);
3051 const rhs_elem = try rhs.elemValue(mod, i);2646 const rhs_elem = try rhs.elemValue(mod, i);
3052 scalar.* = try (try shrScalar(lhs_elem, rhs_elem, scalar_ty, allocator, mod)).intern(scalar_ty, mod);2647 scalar.* = (try shrScalar(lhs_elem, rhs_elem, scalar_ty, allocator, mod)).toIntern();
3053 }2648 }
3054 return Value.fromInterned((try mod.intern(.{ .aggregate = .{2649 return Value.fromInterned((try mod.intern(.{ .aggregate = .{
3055 .ty = ty.toIntern(),2650 .ty = ty.toIntern(),
...@@ -3101,7 +2696,7 @@ pub fn floatNeg(...@@ -3101,7 +2696,7 @@ pub fn floatNeg(
3101 const scalar_ty = float_type.scalarType(mod);2696 const scalar_ty = float_type.scalarType(mod);
3102 for (result_data, 0..) |*scalar, i| {2697 for (result_data, 0..) |*scalar, i| {
3103 const elem_val = try val.elemValue(mod, i);2698 const elem_val = try val.elemValue(mod, i);
3104 scalar.* = try (try floatNegScalar(elem_val, scalar_ty, mod)).intern(scalar_ty, mod);2699 scalar.* = (try floatNegScalar(elem_val, scalar_ty, mod)).toIntern();
3105 }2700 }
3106 return Value.fromInterned((try mod.intern(.{ .aggregate = .{2701 return Value.fromInterned((try mod.intern(.{ .aggregate = .{
3107 .ty = float_type.toIntern(),2702 .ty = float_type.toIntern(),
...@@ -3144,7 +2739,7 @@ pub fn floatAdd(...@@ -3144,7 +2739,7 @@ pub fn floatAdd(
3144 for (result_data, 0..) |*scalar, i| {2739 for (result_data, 0..) |*scalar, i| {
3145 const lhs_elem = try lhs.elemValue(mod, i);2740 const lhs_elem = try lhs.elemValue(mod, i);
3146 const rhs_elem = try rhs.elemValue(mod, i);2741 const rhs_elem = try rhs.elemValue(mod, i);
3147 scalar.* = try (try floatAddScalar(lhs_elem, rhs_elem, scalar_ty, mod)).intern(scalar_ty, mod);2742 scalar.* = (try floatAddScalar(lhs_elem, rhs_elem, scalar_ty, mod)).toIntern();
3148 }2743 }
3149 return Value.fromInterned((try mod.intern(.{ .aggregate = .{2744 return Value.fromInterned((try mod.intern(.{ .aggregate = .{
3150 .ty = float_type.toIntern(),2745 .ty = float_type.toIntern(),
...@@ -3188,7 +2783,7 @@ pub fn floatSub(...@@ -3188,7 +2783,7 @@ pub fn floatSub(
3188 for (result_data, 0..) |*scalar, i| {2783 for (result_data, 0..) |*scalar, i| {
3189 const lhs_elem = try lhs.elemValue(mod, i);2784 const lhs_elem = try lhs.elemValue(mod, i);
3190 const rhs_elem = try rhs.elemValue(mod, i);2785 const rhs_elem = try rhs.elemValue(mod, i);
3191 scalar.* = try (try floatSubScalar(lhs_elem, rhs_elem, scalar_ty, mod)).intern(scalar_ty, mod);2786 scalar.* = (try floatSubScalar(lhs_elem, rhs_elem, scalar_ty, mod)).toIntern();
3192 }2787 }
3193 return Value.fromInterned((try mod.intern(.{ .aggregate = .{2788 return Value.fromInterned((try mod.intern(.{ .aggregate = .{
3194 .ty = float_type.toIntern(),2789 .ty = float_type.toIntern(),
...@@ -3232,7 +2827,7 @@ pub fn floatDiv(...@@ -3232,7 +2827,7 @@ pub fn floatDiv(
3232 for (result_data, 0..) |*scalar, i| {2827 for (result_data, 0..) |*scalar, i| {
3233 const lhs_elem = try lhs.elemValue(mod, i);2828 const lhs_elem = try lhs.elemValue(mod, i);
3234 const rhs_elem = try rhs.elemValue(mod, i);2829 const rhs_elem = try rhs.elemValue(mod, i);
3235 scalar.* = try (try floatDivScalar(lhs_elem, rhs_elem, scalar_ty, mod)).intern(scalar_ty, mod);2830 scalar.* = (try floatDivScalar(lhs_elem, rhs_elem, scalar_ty, mod)).toIntern();
3236 }2831 }
3237 return Value.fromInterned((try mod.intern(.{ .aggregate = .{2832 return Value.fromInterned((try mod.intern(.{ .aggregate = .{
3238 .ty = float_type.toIntern(),2833 .ty = float_type.toIntern(),
...@@ -3276,7 +2871,7 @@ pub fn floatDivFloor(...@@ -3276,7 +2871,7 @@ pub fn floatDivFloor(
3276 for (result_data, 0..) |*scalar, i| {2871 for (result_data, 0..) |*scalar, i| {
3277 const lhs_elem = try lhs.elemValue(mod, i);2872 const lhs_elem = try lhs.elemValue(mod, i);
3278 const rhs_elem = try rhs.elemValue(mod, i);2873 const rhs_elem = try rhs.elemValue(mod, i);
3279 scalar.* = try (try floatDivFloorScalar(lhs_elem, rhs_elem, scalar_ty, mod)).intern(scalar_ty, mod);2874 scalar.* = (try floatDivFloorScalar(lhs_elem, rhs_elem, scalar_ty, mod)).toIntern();
3280 }2875 }
3281 return Value.fromInterned((try mod.intern(.{ .aggregate = .{2876 return Value.fromInterned((try mod.intern(.{ .aggregate = .{
3282 .ty = float_type.toIntern(),2877 .ty = float_type.toIntern(),
...@@ -3320,7 +2915,7 @@ pub fn floatDivTrunc(...@@ -3320,7 +2915,7 @@ pub fn floatDivTrunc(
3320 for (result_data, 0..) |*scalar, i| {2915 for (result_data, 0..) |*scalar, i| {
3321 const lhs_elem = try lhs.elemValue(mod, i);2916 const lhs_elem = try lhs.elemValue(mod, i);
3322 const rhs_elem = try rhs.elemValue(mod, i);2917 const rhs_elem = try rhs.elemValue(mod, i);
3323 scalar.* = try (try floatDivTruncScalar(lhs_elem, rhs_elem, scalar_ty, mod)).intern(scalar_ty, mod);2918 scalar.* = (try floatDivTruncScalar(lhs_elem, rhs_elem, scalar_ty, mod)).toIntern();
3324 }2919 }
3325 return Value.fromInterned((try mod.intern(.{ .aggregate = .{2920 return Value.fromInterned((try mod.intern(.{ .aggregate = .{
3326 .ty = float_type.toIntern(),2921 .ty = float_type.toIntern(),
...@@ -3364,7 +2959,7 @@ pub fn floatMul(...@@ -3364,7 +2959,7 @@ pub fn floatMul(
3364 for (result_data, 0..) |*scalar, i| {2959 for (result_data, 0..) |*scalar, i| {
3365 const lhs_elem = try lhs.elemValue(mod, i);2960 const lhs_elem = try lhs.elemValue(mod, i);
3366 const rhs_elem = try rhs.elemValue(mod, i);2961 const rhs_elem = try rhs.elemValue(mod, i);
3367 scalar.* = try (try floatMulScalar(lhs_elem, rhs_elem, scalar_ty, mod)).intern(scalar_ty, mod);2962 scalar.* = (try floatMulScalar(lhs_elem, rhs_elem, scalar_ty, mod)).toIntern();
3368 }2963 }
3369 return Value.fromInterned((try mod.intern(.{ .aggregate = .{2964 return Value.fromInterned((try mod.intern(.{ .aggregate = .{
3370 .ty = float_type.toIntern(),2965 .ty = float_type.toIntern(),
...@@ -3401,7 +2996,7 @@ pub fn sqrt(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Value...@@ -3401,7 +2996,7 @@ pub fn sqrt(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Value
3401 const scalar_ty = float_type.scalarType(mod);2996 const scalar_ty = float_type.scalarType(mod);
3402 for (result_data, 0..) |*scalar, i| {2997 for (result_data, 0..) |*scalar, i| {
3403 const elem_val = try val.elemValue(mod, i);2998 const elem_val = try val.elemValue(mod, i);
3404 scalar.* = try (try sqrtScalar(elem_val, scalar_ty, mod)).intern(scalar_ty, mod);2999 scalar.* = (try sqrtScalar(elem_val, scalar_ty, mod)).toIntern();
3405 }3000 }
3406 return Value.fromInterned((try mod.intern(.{ .aggregate = .{3001 return Value.fromInterned((try mod.intern(.{ .aggregate = .{
3407 .ty = float_type.toIntern(),3002 .ty = float_type.toIntern(),
...@@ -3433,7 +3028,7 @@ pub fn sin(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Value...@@ -3433,7 +3028,7 @@ pub fn sin(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Value
3433 const scalar_ty = float_type.scalarType(mod);3028 const scalar_ty = float_type.scalarType(mod);
3434 for (result_data, 0..) |*scalar, i| {3029 for (result_data, 0..) |*scalar, i| {
3435 const elem_val = try val.elemValue(mod, i);3030 const elem_val = try val.elemValue(mod, i);
3436 scalar.* = try (try sinScalar(elem_val, scalar_ty, mod)).intern(scalar_ty, mod);3031 scalar.* = (try sinScalar(elem_val, scalar_ty, mod)).toIntern();
3437 }3032 }
3438 return Value.fromInterned((try mod.intern(.{ .aggregate = .{3033 return Value.fromInterned((try mod.intern(.{ .aggregate = .{
3439 .ty = float_type.toIntern(),3034 .ty = float_type.toIntern(),
...@@ -3465,7 +3060,7 @@ pub fn cos(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Value...@@ -3465,7 +3060,7 @@ pub fn cos(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Value
3465 const scalar_ty = float_type.scalarType(mod);3060 const scalar_ty = float_type.scalarType(mod);
3466 for (result_data, 0..) |*scalar, i| {3061 for (result_data, 0..) |*scalar, i| {
3467 const elem_val = try val.elemValue(mod, i);3062 const elem_val = try val.elemValue(mod, i);
3468 scalar.* = try (try cosScalar(elem_val, scalar_ty, mod)).intern(scalar_ty, mod);3063 scalar.* = (try cosScalar(elem_val, scalar_ty, mod)).toIntern();
3469 }3064 }
3470 return Value.fromInterned((try mod.intern(.{ .aggregate = .{3065 return Value.fromInterned((try mod.intern(.{ .aggregate = .{
3471 .ty = float_type.toIntern(),3066 .ty = float_type.toIntern(),
...@@ -3497,7 +3092,7 @@ pub fn tan(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Value...@@ -3497,7 +3092,7 @@ pub fn tan(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Value
3497 const scalar_ty = float_type.scalarType(mod);3092 const scalar_ty = float_type.scalarType(mod);
3498 for (result_data, 0..) |*scalar, i| {3093 for (result_data, 0..) |*scalar, i| {
3499 const elem_val = try val.elemValue(mod, i);3094 const elem_val = try val.elemValue(mod, i);
3500 scalar.* = try (try tanScalar(elem_val, scalar_ty, mod)).intern(scalar_ty, mod);3095 scalar.* = (try tanScalar(elem_val, scalar_ty, mod)).toIntern();
3501 }3096 }
3502 return Value.fromInterned((try mod.intern(.{ .aggregate = .{3097 return Value.fromInterned((try mod.intern(.{ .aggregate = .{
3503 .ty = float_type.toIntern(),3098 .ty = float_type.toIntern(),
...@@ -3529,7 +3124,7 @@ pub fn exp(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Value...@@ -3529,7 +3124,7 @@ pub fn exp(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Value
3529 const scalar_ty = float_type.scalarType(mod);3124 const scalar_ty = float_type.scalarType(mod);
3530 for (result_data, 0..) |*scalar, i| {3125 for (result_data, 0..) |*scalar, i| {
3531 const elem_val = try val.elemValue(mod, i);3126 const elem_val = try val.elemValue(mod, i);
3532 scalar.* = try (try expScalar(elem_val, scalar_ty, mod)).intern(scalar_ty, mod);3127 scalar.* = (try expScalar(elem_val, scalar_ty, mod)).toIntern();
3533 }3128 }
3534 return Value.fromInterned((try mod.intern(.{ .aggregate = .{3129 return Value.fromInterned((try mod.intern(.{ .aggregate = .{
3535 .ty = float_type.toIntern(),3130 .ty = float_type.toIntern(),
...@@ -3561,7 +3156,7 @@ pub fn exp2(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Value...@@ -3561,7 +3156,7 @@ pub fn exp2(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Value
3561 const scalar_ty = float_type.scalarType(mod);3156 const scalar_ty = float_type.scalarType(mod);
3562 for (result_data, 0..) |*scalar, i| {3157 for (result_data, 0..) |*scalar, i| {
3563 const elem_val = try val.elemValue(mod, i);3158 const elem_val = try val.elemValue(mod, i);
3564 scalar.* = try (try exp2Scalar(elem_val, scalar_ty, mod)).intern(scalar_ty, mod);3159 scalar.* = (try exp2Scalar(elem_val, scalar_ty, mod)).toIntern();
3565 }3160 }
3566 return Value.fromInterned((try mod.intern(.{ .aggregate = .{3161 return Value.fromInterned((try mod.intern(.{ .aggregate = .{
3567 .ty = float_type.toIntern(),3162 .ty = float_type.toIntern(),
...@@ -3593,7 +3188,7 @@ pub fn log(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Value...@@ -3593,7 +3188,7 @@ pub fn log(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Value
3593 const scalar_ty = float_type.scalarType(mod);3188 const scalar_ty = float_type.scalarType(mod);
3594 for (result_data, 0..) |*scalar, i| {3189 for (result_data, 0..) |*scalar, i| {
3595 const elem_val = try val.elemValue(mod, i);3190 const elem_val = try val.elemValue(mod, i);
3596 scalar.* = try (try logScalar(elem_val, scalar_ty, mod)).intern(scalar_ty, mod);3191 scalar.* = (try logScalar(elem_val, scalar_ty, mod)).toIntern();
3597 }3192 }
3598 return Value.fromInterned((try mod.intern(.{ .aggregate = .{3193 return Value.fromInterned((try mod.intern(.{ .aggregate = .{
3599 .ty = float_type.toIntern(),3194 .ty = float_type.toIntern(),
...@@ -3625,7 +3220,7 @@ pub fn log2(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Value...@@ -3625,7 +3220,7 @@ pub fn log2(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Value
3625 const scalar_ty = float_type.scalarType(mod);3220 const scalar_ty = float_type.scalarType(mod);
3626 for (result_data, 0..) |*scalar, i| {3221 for (result_data, 0..) |*scalar, i| {
3627 const elem_val = try val.elemValue(mod, i);3222 const elem_val = try val.elemValue(mod, i);
3628 scalar.* = try (try log2Scalar(elem_val, scalar_ty, mod)).intern(scalar_ty, mod);3223 scalar.* = (try log2Scalar(elem_val, scalar_ty, mod)).toIntern();
3629 }3224 }
3630 return Value.fromInterned((try mod.intern(.{ .aggregate = .{3225 return Value.fromInterned((try mod.intern(.{ .aggregate = .{
3631 .ty = float_type.toIntern(),3226 .ty = float_type.toIntern(),
...@@ -3657,7 +3252,7 @@ pub fn log10(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Valu...@@ -3657,7 +3252,7 @@ pub fn log10(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Valu
3657 const scalar_ty = float_type.scalarType(mod);3252 const scalar_ty = float_type.scalarType(mod);
3658 for (result_data, 0..) |*scalar, i| {3253 for (result_data, 0..) |*scalar, i| {
3659 const elem_val = try val.elemValue(mod, i);3254 const elem_val = try val.elemValue(mod, i);
3660 scalar.* = try (try log10Scalar(elem_val, scalar_ty, mod)).intern(scalar_ty, mod);3255 scalar.* = (try log10Scalar(elem_val, scalar_ty, mod)).toIntern();
3661 }3256 }
3662 return Value.fromInterned((try mod.intern(.{ .aggregate = .{3257 return Value.fromInterned((try mod.intern(.{ .aggregate = .{
3663 .ty = float_type.toIntern(),3258 .ty = float_type.toIntern(),
...@@ -3689,7 +3284,7 @@ pub fn abs(val: Value, ty: Type, arena: Allocator, mod: *Module) !Value {...@@ -3689,7 +3284,7 @@ pub fn abs(val: Value, ty: Type, arena: Allocator, mod: *Module) !Value {
3689 const scalar_ty = ty.scalarType(mod);3284 const scalar_ty = ty.scalarType(mod);
3690 for (result_data, 0..) |*scalar, i| {3285 for (result_data, 0..) |*scalar, i| {
3691 const elem_val = try val.elemValue(mod, i);3286 const elem_val = try val.elemValue(mod, i);
3692 scalar.* = try (try absScalar(elem_val, scalar_ty, mod, arena)).intern(scalar_ty, mod);3287 scalar.* = (try absScalar(elem_val, scalar_ty, mod, arena)).toIntern();
3693 }3288 }
3694 return Value.fromInterned((try mod.intern(.{ .aggregate = .{3289 return Value.fromInterned((try mod.intern(.{ .aggregate = .{
3695 .ty = ty.toIntern(),3290 .ty = ty.toIntern(),
...@@ -3740,7 +3335,7 @@ pub fn floor(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Valu...@@ -3740,7 +3335,7 @@ pub fn floor(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Valu
3740 const scalar_ty = float_type.scalarType(mod);3335 const scalar_ty = float_type.scalarType(mod);
3741 for (result_data, 0..) |*scalar, i| {3336 for (result_data, 0..) |*scalar, i| {
3742 const elem_val = try val.elemValue(mod, i);3337 const elem_val = try val.elemValue(mod, i);
3743 scalar.* = try (try floorScalar(elem_val, scalar_ty, mod)).intern(scalar_ty, mod);3338 scalar.* = (try floorScalar(elem_val, scalar_ty, mod)).toIntern();
3744 }3339 }
3745 return Value.fromInterned((try mod.intern(.{ .aggregate = .{3340 return Value.fromInterned((try mod.intern(.{ .aggregate = .{
3746 .ty = float_type.toIntern(),3341 .ty = float_type.toIntern(),
...@@ -3772,7 +3367,7 @@ pub fn ceil(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Value...@@ -3772,7 +3367,7 @@ pub fn ceil(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Value
3772 const scalar_ty = float_type.scalarType(mod);3367 const scalar_ty = float_type.scalarType(mod);
3773 for (result_data, 0..) |*scalar, i| {3368 for (result_data, 0..) |*scalar, i| {
3774 const elem_val = try val.elemValue(mod, i);3369 const elem_val = try val.elemValue(mod, i);
3775 scalar.* = try (try ceilScalar(elem_val, scalar_ty, mod)).intern(scalar_ty, mod);3370 scalar.* = (try ceilScalar(elem_val, scalar_ty, mod)).toIntern();
3776 }3371 }
3777 return Value.fromInterned((try mod.intern(.{ .aggregate = .{3372 return Value.fromInterned((try mod.intern(.{ .aggregate = .{
3778 .ty = float_type.toIntern(),3373 .ty = float_type.toIntern(),
...@@ -3804,7 +3399,7 @@ pub fn round(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Valu...@@ -3804,7 +3399,7 @@ pub fn round(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Valu
3804 const scalar_ty = float_type.scalarType(mod);3399 const scalar_ty = float_type.scalarType(mod);
3805 for (result_data, 0..) |*scalar, i| {3400 for (result_data, 0..) |*scalar, i| {
3806 const elem_val = try val.elemValue(mod, i);3401 const elem_val = try val.elemValue(mod, i);
3807 scalar.* = try (try roundScalar(elem_val, scalar_ty, mod)).intern(scalar_ty, mod);3402 scalar.* = (try roundScalar(elem_val, scalar_ty, mod)).toIntern();
3808 }3403 }
3809 return Value.fromInterned((try mod.intern(.{ .aggregate = .{3404 return Value.fromInterned((try mod.intern(.{ .aggregate = .{
3810 .ty = float_type.toIntern(),3405 .ty = float_type.toIntern(),
...@@ -3836,7 +3431,7 @@ pub fn trunc(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Valu...@@ -3836,7 +3431,7 @@ pub fn trunc(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Valu
3836 const scalar_ty = float_type.scalarType(mod);3431 const scalar_ty = float_type.scalarType(mod);
3837 for (result_data, 0..) |*scalar, i| {3432 for (result_data, 0..) |*scalar, i| {
3838 const elem_val = try val.elemValue(mod, i);3433 const elem_val = try val.elemValue(mod, i);
3839 scalar.* = try (try truncScalar(elem_val, scalar_ty, mod)).intern(scalar_ty, mod);3434 scalar.* = (try truncScalar(elem_val, scalar_ty, mod)).toIntern();
3840 }3435 }
3841 return Value.fromInterned((try mod.intern(.{ .aggregate = .{3436 return Value.fromInterned((try mod.intern(.{ .aggregate = .{
3842 .ty = float_type.toIntern(),3437 .ty = float_type.toIntern(),
...@@ -3877,7 +3472,7 @@ pub fn mulAdd(...@@ -3877,7 +3472,7 @@ pub fn mulAdd(
3877 const mulend1_elem = try mulend1.elemValue(mod, i);3472 const mulend1_elem = try mulend1.elemValue(mod, i);
3878 const mulend2_elem = try mulend2.elemValue(mod, i);3473 const mulend2_elem = try mulend2.elemValue(mod, i);
3879 const addend_elem = try addend.elemValue(mod, i);3474 const addend_elem = try addend.elemValue(mod, i);
3880 scalar.* = try (try mulAddScalar(scalar_ty, mulend1_elem, mulend2_elem, addend_elem, mod)).intern(scalar_ty, mod);3475 scalar.* = (try mulAddScalar(scalar_ty, mulend1_elem, mulend2_elem, addend_elem, mod)).toIntern();
3881 }3476 }
3882 return Value.fromInterned((try mod.intern(.{ .aggregate = .{3477 return Value.fromInterned((try mod.intern(.{ .aggregate = .{
3883 .ty = float_type.toIntern(),3478 .ty = float_type.toIntern(),
...@@ -3939,6 +3534,10 @@ pub fn isGenericPoison(val: Value) bool {...@@ -3939,6 +3534,10 @@ pub fn isGenericPoison(val: Value) bool {
3939 return val.toIntern() == .generic_poison;3534 return val.toIntern() == .generic_poison;
3940}3535}
39413536
3537pub fn typeOf(val: Value, zcu: *const Zcu) Type {
3538 return Type.fromInterned(zcu.intern_pool.typeOf(val.toIntern()));
3539}
3540
3942/// For an integer (comptime or fixed-width) `val`, returns the comptime-known bounds of the value.3541/// For an integer (comptime or fixed-width) `val`, returns the comptime-known bounds of the value.
3943/// If `val` is not undef, the bounds are both `val`.3542/// If `val` is not undef, the bounds are both `val`.
3944/// If `val` is undef and has a fixed-width type, the bounds are the bounds of the type.3543/// If `val` is undef and has a fixed-width type, the bounds are the bounds of the type.
...@@ -3953,98 +3552,26 @@ pub fn intValueBounds(val: Value, mod: *Module) !?[2]Value {...@@ -3953,98 +3552,26 @@ pub fn intValueBounds(val: Value, mod: *Module) !?[2]Value {
3953 };3552 };
3954}3553}
39553554
3956/// This type is not copyable since it may contain pointers to its inner data.
3957pub const Payload = struct {
3958 tag: Tag,
3959
3960 pub const Slice = struct {
3961 base: Payload,
3962 data: struct {
3963 ptr: Value,
3964 len: Value,
3965 },
3966 };
3967
3968 pub const Bytes = struct {
3969 base: Payload,
3970 /// Includes the sentinel, if any.
3971 data: []const u8,
3972 };
3973
3974 pub const SubValue = struct {
3975 base: Payload,
3976 data: Value,
3977 };
3978
3979 pub const Aggregate = struct {
3980 base: Payload,
3981 /// Field values. The types are according to the struct or array type.
3982 /// The length is provided here so that copying a Value does not depend on the Type.
3983 data: []Value,
3984 };
3985
3986 pub const Union = struct {
3987 pub const base_tag = Tag.@"union";
3988
3989 base: Payload = .{ .tag = base_tag },
3990 data: Data,
3991
3992 pub const Data = struct {
3993 tag: ?Value,
3994 val: Value,
3995 };
3996 };
3997};
3998
3999pub const BigIntSpace = InternPool.Key.Int.Storage.BigIntSpace;3555pub const BigIntSpace = InternPool.Key.Int.Storage.BigIntSpace;
40003556
4001pub const zero_usize: Value = .{ .ip_index = .zero_usize, .legacy = undefined };3557pub const zero_usize: Value = .{ .ip_index = .zero_usize };
4002pub const zero_u8: Value = .{ .ip_index = .zero_u8, .legacy = undefined };3558pub const zero_u8: Value = .{ .ip_index = .zero_u8 };
4003pub const zero_comptime_int: Value = .{ .ip_index = .zero, .legacy = undefined };3559pub const zero_comptime_int: Value = .{ .ip_index = .zero };
4004pub const one_comptime_int: Value = .{ .ip_index = .one, .legacy = undefined };3560pub const one_comptime_int: Value = .{ .ip_index = .one };
4005pub const negative_one_comptime_int: Value = .{ .ip_index = .negative_one, .legacy = undefined };3561pub const negative_one_comptime_int: Value = .{ .ip_index = .negative_one };
4006pub const undef: Value = .{ .ip_index = .undef, .legacy = undefined };3562pub const undef: Value = .{ .ip_index = .undef };
4007pub const @"void": Value = .{ .ip_index = .void_value, .legacy = undefined };3563pub const @"void": Value = .{ .ip_index = .void_value };
4008pub const @"null": Value = .{ .ip_index = .null_value, .legacy = undefined };3564pub const @"null": Value = .{ .ip_index = .null_value };
4009pub const @"false": Value = .{ .ip_index = .bool_false, .legacy = undefined };3565pub const @"false": Value = .{ .ip_index = .bool_false };
4010pub const @"true": Value = .{ .ip_index = .bool_true, .legacy = undefined };3566pub const @"true": Value = .{ .ip_index = .bool_true };
4011pub const @"unreachable": Value = .{ .ip_index = .unreachable_value, .legacy = undefined };3567pub const @"unreachable": Value = .{ .ip_index = .unreachable_value };
40123568
4013pub const generic_poison: Value = .{ .ip_index = .generic_poison, .legacy = undefined };3569pub const generic_poison: Value = .{ .ip_index = .generic_poison };
4014pub const generic_poison_type: Value = .{ .ip_index = .generic_poison_type, .legacy = undefined };3570pub const generic_poison_type: Value = .{ .ip_index = .generic_poison_type };
4015pub const empty_struct: Value = .{ .ip_index = .empty_struct, .legacy = undefined };3571pub const empty_struct: Value = .{ .ip_index = .empty_struct };
40163572
4017pub fn makeBool(x: bool) Value {3573pub fn makeBool(x: bool) Value {
4018 return if (x) Value.true else Value.false;3574 return if (x) Value.true else Value.false;
4019}3575}
40203576
4021pub const RuntimeIndex = InternPool.RuntimeIndex;3577pub const RuntimeIndex = InternPool.RuntimeIndex;
4022
4023/// This function is used in the debugger pretty formatters in tools/ to fetch the
4024/// Tag to Payload mapping to facilitate fancy debug printing for this type.
4025fn dbHelper(self: *Value, tag_to_payload_map: *map: {
4026 const tags = @typeInfo(Tag).Enum.fields;
4027 var fields: [tags.len]std.builtin.Type.StructField = undefined;
4028 for (&fields, tags) |*field, t| field.* = .{
4029 .name = t.name ++ "",
4030 .type = *@field(Tag, t.name).Type(),
4031 .default_value = null,
4032 .is_comptime = false,
4033 .alignment = 0,
4034 };
4035 break :map @Type(.{ .Struct = .{
4036 .layout = .@"extern",
4037 .fields = &fields,
4038 .decls = &.{},
4039 .is_tuple = false,
4040 } });
4041}) void {
4042 _ = self;
4043 _ = tag_to_payload_map;
4044}
4045
4046comptime {
4047 if (!builtin.strip_debug_info) {
4048 _ = &dbHelper;
4049 }
4050}
src/arch/aarch64/CodeGen.zig+4-8
...@@ -10,7 +10,6 @@ const Emit = @import("Emit.zig");...@@ -10,7 +10,6 @@ const Emit = @import("Emit.zig");
10const Liveness = @import("../../Liveness.zig");10const Liveness = @import("../../Liveness.zig");
11const Type = @import("../../type.zig").Type;11const Type = @import("../../type.zig").Type;
12const Value = @import("../../Value.zig");12const Value = @import("../../Value.zig");
13const TypedValue = @import("../../TypedValue.zig");
14const link = @import("../../link.zig");13const link = @import("../../link.zig");
15const Module = @import("../../Module.zig");14const Module = @import("../../Module.zig");
16const InternPool = @import("../../InternPool.zig");15const InternPool = @import("../../InternPool.zig");
...@@ -342,7 +341,7 @@ pub fn generate(...@@ -342,7 +341,7 @@ pub fn generate(
342 const func = zcu.funcInfo(func_index);341 const func = zcu.funcInfo(func_index);
343 const fn_owner_decl = zcu.declPtr(func.owner_decl);342 const fn_owner_decl = zcu.declPtr(func.owner_decl);
344 assert(fn_owner_decl.has_tv);343 assert(fn_owner_decl.has_tv);
345 const fn_type = fn_owner_decl.ty;344 const fn_type = fn_owner_decl.typeOf(zcu);
346 const namespace = zcu.namespacePtr(fn_owner_decl.src_namespace);345 const namespace = zcu.namespacePtr(fn_owner_decl.src_namespace);
347 const target = &namespace.file_scope.mod.resolved_target.result;346 const target = &namespace.file_scope.mod.resolved_target.result;
348347
...@@ -6143,10 +6142,7 @@ fn resolveInst(self: *Self, inst: Air.Inst.Ref) InnerError!MCValue {...@@ -6143,10 +6142,7 @@ fn resolveInst(self: *Self, inst: Air.Inst.Ref) InnerError!MCValue {
6143 if (!inst_ty.hasRuntimeBitsIgnoreComptime(mod) and !inst_ty.isError(mod))6142 if (!inst_ty.hasRuntimeBitsIgnoreComptime(mod) and !inst_ty.isError(mod))
6144 return MCValue{ .none = {} };6143 return MCValue{ .none = {} };
61456144
6146 const inst_index = inst.toIndex() orelse return self.genTypedValue(.{6145 const inst_index = inst.toIndex() orelse return self.genTypedValue((try self.air.value(inst, mod)).?);
6147 .ty = inst_ty,
6148 .val = (try self.air.value(inst, mod)).?,
6149 });
61506146
6151 return self.getResolvedInstValue(inst_index);6147 return self.getResolvedInstValue(inst_index);
6152}6148}
...@@ -6163,11 +6159,11 @@ fn getResolvedInstValue(self: *Self, inst: Air.Inst.Index) MCValue {...@@ -6163,11 +6159,11 @@ fn getResolvedInstValue(self: *Self, inst: Air.Inst.Index) MCValue {
6163 }6159 }
6164}6160}
61656161
6166fn genTypedValue(self: *Self, arg_tv: TypedValue) InnerError!MCValue {6162fn genTypedValue(self: *Self, val: Value) InnerError!MCValue {
6167 const mcv: MCValue = switch (try codegen.genTypedValue(6163 const mcv: MCValue = switch (try codegen.genTypedValue(
6168 self.bin_file,6164 self.bin_file,
6169 self.src_loc,6165 self.src_loc,
6170 arg_tv,6166 val,
6171 self.owner_decl,6167 self.owner_decl,
6172 )) {6168 )) {
6173 .mcv => |mcv| switch (mcv) {6169 .mcv => |mcv| switch (mcv) {
src/arch/arm/CodeGen.zig+4-8
...@@ -10,7 +10,6 @@ const Emit = @import("Emit.zig");...@@ -10,7 +10,6 @@ const Emit = @import("Emit.zig");
10const Liveness = @import("../../Liveness.zig");10const Liveness = @import("../../Liveness.zig");
11const Type = @import("../../type.zig").Type;11const Type = @import("../../type.zig").Type;
12const Value = @import("../../Value.zig");12const Value = @import("../../Value.zig");
13const TypedValue = @import("../../TypedValue.zig");
14const link = @import("../../link.zig");13const link = @import("../../link.zig");
15const Module = @import("../../Module.zig");14const Module = @import("../../Module.zig");
16const InternPool = @import("../../InternPool.zig");15const InternPool = @import("../../InternPool.zig");
...@@ -349,7 +348,7 @@ pub fn generate(...@@ -349,7 +348,7 @@ pub fn generate(
349 const func = zcu.funcInfo(func_index);348 const func = zcu.funcInfo(func_index);
350 const fn_owner_decl = zcu.declPtr(func.owner_decl);349 const fn_owner_decl = zcu.declPtr(func.owner_decl);
351 assert(fn_owner_decl.has_tv);350 assert(fn_owner_decl.has_tv);
352 const fn_type = fn_owner_decl.ty;351 const fn_type = fn_owner_decl.typeOf(zcu);
353 const namespace = zcu.namespacePtr(fn_owner_decl.src_namespace);352 const namespace = zcu.namespacePtr(fn_owner_decl.src_namespace);
354 const target = &namespace.file_scope.mod.resolved_target.result;353 const target = &namespace.file_scope.mod.resolved_target.result;
355354
...@@ -6097,10 +6096,7 @@ fn resolveInst(self: *Self, inst: Air.Inst.Ref) InnerError!MCValue {...@@ -6097,10 +6096,7 @@ fn resolveInst(self: *Self, inst: Air.Inst.Ref) InnerError!MCValue {
6097 if (!inst_ty.hasRuntimeBitsIgnoreComptime(mod) and !inst_ty.isError(mod))6096 if (!inst_ty.hasRuntimeBitsIgnoreComptime(mod) and !inst_ty.isError(mod))
6098 return MCValue{ .none = {} };6097 return MCValue{ .none = {} };
60996098
6100 const inst_index = inst.toIndex() orelse return self.genTypedValue(.{6099 const inst_index = inst.toIndex() orelse return self.genTypedValue((try self.air.value(inst, mod)).?);
6101 .ty = inst_ty,
6102 .val = (try self.air.value(inst, mod)).?,
6103 });
61046100
6105 return self.getResolvedInstValue(inst_index);6101 return self.getResolvedInstValue(inst_index);
6106}6102}
...@@ -6117,12 +6113,12 @@ fn getResolvedInstValue(self: *Self, inst: Air.Inst.Index) MCValue {...@@ -6117,12 +6113,12 @@ fn getResolvedInstValue(self: *Self, inst: Air.Inst.Index) MCValue {
6117 }6113 }
6118}6114}
61196115
6120fn genTypedValue(self: *Self, arg_tv: TypedValue) InnerError!MCValue {6116fn genTypedValue(self: *Self, val: Value) InnerError!MCValue {
6121 const mod = self.bin_file.comp.module.?;6117 const mod = self.bin_file.comp.module.?;
6122 const mcv: MCValue = switch (try codegen.genTypedValue(6118 const mcv: MCValue = switch (try codegen.genTypedValue(
6123 self.bin_file,6119 self.bin_file,
6124 self.src_loc,6120 self.src_loc,
6125 arg_tv,6121 val,
6126 mod.funcOwnerDeclIndex(self.func_index),6122 mod.funcOwnerDeclIndex(self.func_index),
6127 )) {6123 )) {
6128 .mcv => |mcv| switch (mcv) {6124 .mcv => |mcv| switch (mcv) {
src/arch/riscv64/CodeGen.zig+4-8
...@@ -9,7 +9,6 @@ const Emit = @import("Emit.zig");...@@ -9,7 +9,6 @@ const Emit = @import("Emit.zig");
9const Liveness = @import("../../Liveness.zig");9const Liveness = @import("../../Liveness.zig");
10const Type = @import("../../type.zig").Type;10const Type = @import("../../type.zig").Type;
11const Value = @import("../../Value.zig");11const Value = @import("../../Value.zig");
12const TypedValue = @import("../../TypedValue.zig");
13const link = @import("../../link.zig");12const link = @import("../../link.zig");
14const Module = @import("../../Module.zig");13const Module = @import("../../Module.zig");
15const InternPool = @import("../../InternPool.zig");14const InternPool = @import("../../InternPool.zig");
...@@ -230,7 +229,7 @@ pub fn generate(...@@ -230,7 +229,7 @@ pub fn generate(
230 const func = zcu.funcInfo(func_index);229 const func = zcu.funcInfo(func_index);
231 const fn_owner_decl = zcu.declPtr(func.owner_decl);230 const fn_owner_decl = zcu.declPtr(func.owner_decl);
232 assert(fn_owner_decl.has_tv);231 assert(fn_owner_decl.has_tv);
233 const fn_type = fn_owner_decl.ty;232 const fn_type = fn_owner_decl.typeOf(zcu);
234 const namespace = zcu.namespacePtr(fn_owner_decl.src_namespace);233 const namespace = zcu.namespacePtr(fn_owner_decl.src_namespace);
235 const target = &namespace.file_scope.mod.resolved_target.result;234 const target = &namespace.file_scope.mod.resolved_target.result;
236235
...@@ -2552,10 +2551,7 @@ fn resolveInst(self: *Self, inst: Air.Inst.Ref) InnerError!MCValue {...@@ -2552,10 +2551,7 @@ fn resolveInst(self: *Self, inst: Air.Inst.Ref) InnerError!MCValue {
2552 if (!inst_ty.hasRuntimeBits(mod))2551 if (!inst_ty.hasRuntimeBits(mod))
2553 return MCValue{ .none = {} };2552 return MCValue{ .none = {} };
25542553
2555 const inst_index = inst.toIndex() orelse return self.genTypedValue(.{2554 const inst_index = inst.toIndex() orelse return self.genTypedValue((try self.air.value(inst, mod)).?);
2556 .ty = inst_ty,
2557 .val = (try self.air.value(inst, mod)).?,
2558 });
25592555
2560 return self.getResolvedInstValue(inst_index);2556 return self.getResolvedInstValue(inst_index);
2561}2557}
...@@ -2572,12 +2568,12 @@ fn getResolvedInstValue(self: *Self, inst: Air.Inst.Index) MCValue {...@@ -2572,12 +2568,12 @@ fn getResolvedInstValue(self: *Self, inst: Air.Inst.Index) MCValue {
2572 }2568 }
2573}2569}
25742570
2575fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue {2571fn genTypedValue(self: *Self, val: Value) InnerError!MCValue {
2576 const mod = self.bin_file.comp.module.?;2572 const mod = self.bin_file.comp.module.?;
2577 const mcv: MCValue = switch (try codegen.genTypedValue(2573 const mcv: MCValue = switch (try codegen.genTypedValue(
2578 self.bin_file,2574 self.bin_file,
2579 self.src_loc,2575 self.src_loc,
2580 typed_value,2576 val,
2581 mod.funcOwnerDeclIndex(self.func_index),2577 mod.funcOwnerDeclIndex(self.func_index),
2582 )) {2578 )) {
2583 .mcv => |mcv| switch (mcv) {2579 .mcv => |mcv| switch (mcv) {
src/arch/sparc64/CodeGen.zig+5-8
...@@ -12,7 +12,7 @@ const builtin = @import("builtin");...@@ -12,7 +12,7 @@ const builtin = @import("builtin");
12const link = @import("../../link.zig");12const link = @import("../../link.zig");
13const Module = @import("../../Module.zig");13const Module = @import("../../Module.zig");
14const InternPool = @import("../../InternPool.zig");14const InternPool = @import("../../InternPool.zig");
15const TypedValue = @import("../../TypedValue.zig");15const Value = @import("../../Value.zig");
16const ErrorMsg = Module.ErrorMsg;16const ErrorMsg = Module.ErrorMsg;
17const codegen = @import("../../codegen.zig");17const codegen = @import("../../codegen.zig");
18const Air = @import("../../Air.zig");18const Air = @import("../../Air.zig");
...@@ -273,7 +273,7 @@ pub fn generate(...@@ -273,7 +273,7 @@ pub fn generate(
273 const func = zcu.funcInfo(func_index);273 const func = zcu.funcInfo(func_index);
274 const fn_owner_decl = zcu.declPtr(func.owner_decl);274 const fn_owner_decl = zcu.declPtr(func.owner_decl);
275 assert(fn_owner_decl.has_tv);275 assert(fn_owner_decl.has_tv);
276 const fn_type = fn_owner_decl.ty;276 const fn_type = fn_owner_decl.typeOf(zcu);
277 const namespace = zcu.namespacePtr(fn_owner_decl.src_namespace);277 const namespace = zcu.namespacePtr(fn_owner_decl.src_namespace);
278 const target = &namespace.file_scope.mod.resolved_target.result;278 const target = &namespace.file_scope.mod.resolved_target.result;
279279
...@@ -4118,12 +4118,12 @@ fn genStoreASI(self: *Self, value_reg: Register, addr_reg: Register, off_reg: Re...@@ -4118,12 +4118,12 @@ fn genStoreASI(self: *Self, value_reg: Register, addr_reg: Register, off_reg: Re
4118 }4118 }
4119}4119}
41204120
4121fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue {4121fn genTypedValue(self: *Self, val: Value) InnerError!MCValue {
4122 const mod = self.bin_file.comp.module.?;4122 const mod = self.bin_file.comp.module.?;
4123 const mcv: MCValue = switch (try codegen.genTypedValue(4123 const mcv: MCValue = switch (try codegen.genTypedValue(
4124 self.bin_file,4124 self.bin_file,
4125 self.src_loc,4125 self.src_loc,
4126 typed_value,4126 val,
4127 mod.funcOwnerDeclIndex(self.func_index),4127 mod.funcOwnerDeclIndex(self.func_index),
4128 )) {4128 )) {
4129 .mcv => |mcv| switch (mcv) {4129 .mcv => |mcv| switch (mcv) {
...@@ -4546,10 +4546,7 @@ fn resolveInst(self: *Self, ref: Air.Inst.Ref) InnerError!MCValue {...@@ -4546,10 +4546,7 @@ fn resolveInst(self: *Self, ref: Air.Inst.Ref) InnerError!MCValue {
4546 return self.getResolvedInstValue(inst);4546 return self.getResolvedInstValue(inst);
4547 }4547 }
45484548
4549 return self.genTypedValue(.{4549 return self.genTypedValue((try self.air.value(ref, mod)).?);
4550 .ty = ty,
4551 .val = (try self.air.value(ref, mod)).?,
4552 });
4553}4550}
45544551
4555fn ret(self: *Self, mcv: MCValue) !void {4552fn ret(self: *Self, mcv: MCValue) !void {
src/arch/wasm/CodeGen.zig+25-30
...@@ -18,7 +18,6 @@ const Value = @import("../../Value.zig");...@@ -18,7 +18,6 @@ const Value = @import("../../Value.zig");
18const Compilation = @import("../../Compilation.zig");18const Compilation = @import("../../Compilation.zig");
19const LazySrcLoc = std.zig.LazySrcLoc;19const LazySrcLoc = std.zig.LazySrcLoc;
20const link = @import("../../link.zig");20const link = @import("../../link.zig");
21const TypedValue = @import("../../TypedValue.zig");
22const Air = @import("../../Air.zig");21const Air = @import("../../Air.zig");
23const Liveness = @import("../../Liveness.zig");22const Liveness = @import("../../Liveness.zig");
24const target_util = @import("../../target.zig");23const target_util = @import("../../target.zig");
...@@ -805,7 +804,7 @@ fn resolveInst(func: *CodeGen, ref: Air.Inst.Ref) InnerError!WValue {...@@ -805,7 +804,7 @@ fn resolveInst(func: *CodeGen, ref: Air.Inst.Ref) InnerError!WValue {
805 // In the other cases, we will simply lower the constant to a value that fits804 // In the other cases, we will simply lower the constant to a value that fits
806 // into a single local (such as a pointer, integer, bool, etc).805 // into a single local (such as a pointer, integer, bool, etc).
807 const result = if (isByRef(ty, mod)) blk: {806 const result = if (isByRef(ty, mod)) blk: {
808 const sym_index = try func.bin_file.lowerUnnamedConst(.{ .ty = ty, .val = val }, func.decl_index);807 const sym_index = try func.bin_file.lowerUnnamedConst(val, func.decl_index);
809 break :blk WValue{ .memory = sym_index };808 break :blk WValue{ .memory = sym_index };
810 } else try func.lowerConstant(val, ty);809 } else try func.lowerConstant(val, ty);
811810
...@@ -1243,12 +1242,12 @@ pub fn generate(...@@ -1243,12 +1242,12 @@ pub fn generate(
1243fn genFunc(func: *CodeGen) InnerError!void {1242fn genFunc(func: *CodeGen) InnerError!void {
1244 const mod = func.bin_file.base.comp.module.?;1243 const mod = func.bin_file.base.comp.module.?;
1245 const ip = &mod.intern_pool;1244 const ip = &mod.intern_pool;
1246 const fn_info = mod.typeToFunc(func.decl.ty).?;1245 const fn_info = mod.typeToFunc(func.decl.typeOf(mod)).?;
1247 var func_type = try genFunctype(func.gpa, fn_info.cc, fn_info.param_types.get(ip), Type.fromInterned(fn_info.return_type), mod);1246 var func_type = try genFunctype(func.gpa, fn_info.cc, fn_info.param_types.get(ip), Type.fromInterned(fn_info.return_type), mod);
1248 defer func_type.deinit(func.gpa);1247 defer func_type.deinit(func.gpa);
1249 _ = try func.bin_file.storeDeclType(func.decl_index, func_type);1248 _ = try func.bin_file.storeDeclType(func.decl_index, func_type);
12501249
1251 var cc_result = try func.resolveCallingConventionValues(func.decl.ty);1250 var cc_result = try func.resolveCallingConventionValues(func.decl.typeOf(mod));
1252 defer cc_result.deinit(func.gpa);1251 defer cc_result.deinit(func.gpa);
12531252
1254 func.args = cc_result.args;1253 func.args = cc_result.args;
...@@ -2087,7 +2086,7 @@ fn airRet(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -2087,7 +2086,7 @@ fn airRet(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
2087 const mod = func.bin_file.base.comp.module.?;2086 const mod = func.bin_file.base.comp.module.?;
2088 const un_op = func.air.instructions.items(.data)[@intFromEnum(inst)].un_op;2087 const un_op = func.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
2089 const operand = try func.resolveInst(un_op);2088 const operand = try func.resolveInst(un_op);
2090 const fn_info = mod.typeToFunc(func.decl.ty).?;2089 const fn_info = mod.typeToFunc(func.decl.typeOf(mod)).?;
2091 const ret_ty = Type.fromInterned(fn_info.return_type);2090 const ret_ty = Type.fromInterned(fn_info.return_type);
20922091
2093 // result must be stored in the stack and we return a pointer2092 // result must be stored in the stack and we return a pointer
...@@ -2135,7 +2134,7 @@ fn airRetPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -2135,7 +2134,7 @@ fn airRetPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
2135 break :result try func.allocStack(Type.usize); // create pointer to void2134 break :result try func.allocStack(Type.usize); // create pointer to void
2136 }2135 }
21372136
2138 const fn_info = mod.typeToFunc(func.decl.ty).?;2137 const fn_info = mod.typeToFunc(func.decl.typeOf(mod)).?;
2139 if (firstParamSRet(fn_info.cc, Type.fromInterned(fn_info.return_type), mod)) {2138 if (firstParamSRet(fn_info.cc, Type.fromInterned(fn_info.return_type), mod)) {
2140 break :result func.return_value;2139 break :result func.return_value;
2141 }2140 }
...@@ -2152,7 +2151,7 @@ fn airRetLoad(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -2152,7 +2151,7 @@ fn airRetLoad(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
2152 const operand = try func.resolveInst(un_op);2151 const operand = try func.resolveInst(un_op);
2153 const ret_ty = func.typeOf(un_op).childType(mod);2152 const ret_ty = func.typeOf(un_op).childType(mod);
21542153
2155 const fn_info = mod.typeToFunc(func.decl.ty).?;2154 const fn_info = mod.typeToFunc(func.decl.typeOf(mod)).?;
2156 if (!ret_ty.hasRuntimeBitsIgnoreComptime(mod)) {2155 if (!ret_ty.hasRuntimeBitsIgnoreComptime(mod)) {
2157 if (ret_ty.isError(mod)) {2156 if (ret_ty.isError(mod)) {
2158 try func.addImm32(0);2157 try func.addImm32(0);
...@@ -2193,7 +2192,7 @@ fn airCall(func: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif...@@ -2193,7 +2192,7 @@ fn airCall(func: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif
2193 break :blk function.owner_decl;2192 break :blk function.owner_decl;
2194 } else if (func_val.getExternFunc(mod)) |extern_func| {2193 } else if (func_val.getExternFunc(mod)) |extern_func| {
2195 const ext_decl = mod.declPtr(extern_func.decl);2194 const ext_decl = mod.declPtr(extern_func.decl);
2196 const ext_info = mod.typeToFunc(ext_decl.ty).?;2195 const ext_info = mod.typeToFunc(ext_decl.typeOf(mod)).?;
2197 var func_type = try genFunctype(func.gpa, ext_info.cc, ext_info.param_types.get(ip), Type.fromInterned(ext_info.return_type), mod);2196 var func_type = try genFunctype(func.gpa, ext_info.cc, ext_info.param_types.get(ip), Type.fromInterned(ext_info.return_type), mod);
2198 defer func_type.deinit(func.gpa);2197 defer func_type.deinit(func.gpa);
2199 const atom_index = try func.bin_file.getOrCreateAtomForDecl(extern_func.decl);2198 const atom_index = try func.bin_file.getOrCreateAtomForDecl(extern_func.decl);
...@@ -2216,7 +2215,7 @@ fn airCall(func: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif...@@ -2216,7 +2215,7 @@ fn airCall(func: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif
2216 },2215 },
2217 else => {},2216 else => {},
2218 }2217 }
2219 return func.fail("Expected a function, but instead found type '{}'", .{func_val.tag()});2218 return func.fail("Expected a function, but instead found '{s}'", .{@tagName(ip.indexToKey(func_val.toIntern()))});
2220 };2219 };
22212220
2222 const sret = if (first_param_sret) blk: {2221 const sret = if (first_param_sret) blk: {
...@@ -2530,7 +2529,7 @@ fn airArg(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -2530,7 +2529,7 @@ fn airArg(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
2530 const mod = func.bin_file.base.comp.module.?;2529 const mod = func.bin_file.base.comp.module.?;
2531 const arg_index = func.arg_index;2530 const arg_index = func.arg_index;
2532 const arg = func.args[arg_index];2531 const arg = func.args[arg_index];
2533 const cc = mod.typeToFunc(func.decl.ty).?.cc;2532 const cc = mod.typeToFunc(func.decl.typeOf(mod)).?.cc;
2534 const arg_ty = func.typeOfIndex(inst);2533 const arg_ty = func.typeOfIndex(inst);
2535 if (cc == .C) {2534 if (cc == .C) {
2536 const arg_classes = abi.classifyType(arg_ty, mod);2535 const arg_classes = abi.classifyType(arg_ty, mod);
...@@ -3119,11 +3118,7 @@ fn lowerParentPtr(func: *CodeGen, ptr_val: Value, offset: u32) InnerError!WValue...@@ -3119,11 +3118,7 @@ fn lowerParentPtr(func: *CodeGen, ptr_val: Value, offset: u32) InnerError!WValue
3119}3118}
31203119
3121fn lowerParentPtrDecl(func: *CodeGen, ptr_val: Value, decl_index: InternPool.DeclIndex, offset: u32) InnerError!WValue {3120fn lowerParentPtrDecl(func: *CodeGen, ptr_val: Value, decl_index: InternPool.DeclIndex, offset: u32) InnerError!WValue {
3122 const mod = func.bin_file.base.comp.module.?;3121 return func.lowerDeclRefValue(ptr_val, decl_index, offset);
3123 const decl = mod.declPtr(decl_index);
3124 try mod.markDeclAlive(decl);
3125 const ptr_ty = try mod.singleMutPtrType(decl.ty);
3126 return func.lowerDeclRefValue(.{ .ty = ptr_ty, .val = ptr_val }, decl_index, offset);
3127}3122}
31283123
3129fn lowerAnonDeclRef(3124fn lowerAnonDeclRef(
...@@ -3158,7 +3153,7 @@ fn lowerAnonDeclRef(...@@ -3158,7 +3153,7 @@ fn lowerAnonDeclRef(
3158 } else return WValue{ .memory_offset = .{ .pointer = target_sym_index, .offset = offset } };3153 } else return WValue{ .memory_offset = .{ .pointer = target_sym_index, .offset = offset } };
3159}3154}
31603155
3161fn lowerDeclRefValue(func: *CodeGen, tv: TypedValue, decl_index: InternPool.DeclIndex, offset: u32) InnerError!WValue {3156fn lowerDeclRefValue(func: *CodeGen, val: Value, decl_index: InternPool.DeclIndex, offset: u32) InnerError!WValue {
3162 const mod = func.bin_file.base.comp.module.?;3157 const mod = func.bin_file.base.comp.module.?;
31633158
3164 const decl = mod.declPtr(decl_index);3159 const decl = mod.declPtr(decl_index);
...@@ -3166,23 +3161,23 @@ fn lowerDeclRefValue(func: *CodeGen, tv: TypedValue, decl_index: InternPool.Decl...@@ -3166,23 +3161,23 @@ fn lowerDeclRefValue(func: *CodeGen, tv: TypedValue, decl_index: InternPool.Decl
3166 // want to lower the actual decl, rather than the alias itself.3161 // want to lower the actual decl, rather than the alias itself.
3167 if (decl.val.getFunction(mod)) |func_val| {3162 if (decl.val.getFunction(mod)) |func_val| {
3168 if (func_val.owner_decl != decl_index) {3163 if (func_val.owner_decl != decl_index) {
3169 return func.lowerDeclRefValue(tv, func_val.owner_decl, offset);3164 return func.lowerDeclRefValue(val, func_val.owner_decl, offset);
3170 }3165 }
3171 } else if (decl.val.getExternFunc(mod)) |func_val| {3166 } else if (decl.val.getExternFunc(mod)) |func_val| {
3172 if (func_val.decl != decl_index) {3167 if (func_val.decl != decl_index) {
3173 return func.lowerDeclRefValue(tv, func_val.decl, offset);3168 return func.lowerDeclRefValue(val, func_val.decl, offset);
3174 }3169 }
3175 }3170 }
3176 if (decl.ty.zigTypeTag(mod) != .Fn and !decl.ty.hasRuntimeBitsIgnoreComptime(mod)) {3171 const decl_ty = decl.typeOf(mod);
3172 if (decl_ty.zigTypeTag(mod) != .Fn and !decl_ty.hasRuntimeBitsIgnoreComptime(mod)) {
3177 return WValue{ .imm32 = 0xaaaaaaaa };3173 return WValue{ .imm32 = 0xaaaaaaaa };
3178 }3174 }
31793175
3180 try mod.markDeclAlive(decl);
3181 const atom_index = try func.bin_file.getOrCreateAtomForDecl(decl_index);3176 const atom_index = try func.bin_file.getOrCreateAtomForDecl(decl_index);
3182 const atom = func.bin_file.getAtom(atom_index);3177 const atom = func.bin_file.getAtom(atom_index);
31833178
3184 const target_sym_index = @intFromEnum(atom.sym_index);3179 const target_sym_index = @intFromEnum(atom.sym_index);
3185 if (decl.ty.zigTypeTag(mod) == .Fn) {3180 if (decl_ty.zigTypeTag(mod) == .Fn) {
3186 return WValue{ .function_index = target_sym_index };3181 return WValue{ .function_index = target_sym_index };
3187 } else if (offset == 0) {3182 } else if (offset == 0) {
3188 return WValue{ .memory = target_sym_index };3183 return WValue{ .memory = target_sym_index };
...@@ -3281,23 +3276,23 @@ fn lowerConstant(func: *CodeGen, val: Value, ty: Type) InnerError!WValue {...@@ -3281,23 +3276,23 @@ fn lowerConstant(func: *CodeGen, val: Value, ty: Type) InnerError!WValue {
3281 },3276 },
3282 .error_union => |error_union| {3277 .error_union => |error_union| {
3283 const err_int_ty = try mod.errorIntType();3278 const err_int_ty = try mod.errorIntType();
3284 const err_tv: TypedValue = switch (error_union.val) {3279 const err_ty, const err_val = switch (error_union.val) {
3285 .err_name => |err_name| .{3280 .err_name => |err_name| .{
3286 .ty = ty.errorUnionSet(mod),3281 ty.errorUnionSet(mod),
3287 .val = Value.fromInterned((try mod.intern(.{ .err = .{3282 Value.fromInterned((try mod.intern(.{ .err = .{
3288 .ty = ty.errorUnionSet(mod).toIntern(),3283 .ty = ty.errorUnionSet(mod).toIntern(),
3289 .name = err_name,3284 .name = err_name,
3290 } }))),3285 } }))),
3291 },3286 },
3292 .payload => .{3287 .payload => .{
3293 .ty = err_int_ty,3288 err_int_ty,
3294 .val = try mod.intValue(err_int_ty, 0),3289 try mod.intValue(err_int_ty, 0),
3295 },3290 },
3296 };3291 };
3297 const payload_type = ty.errorUnionPayload(mod);3292 const payload_type = ty.errorUnionPayload(mod);
3298 if (!payload_type.hasRuntimeBitsIgnoreComptime(mod)) {3293 if (!payload_type.hasRuntimeBitsIgnoreComptime(mod)) {
3299 // We use the error type directly as the type.3294 // We use the error type directly as the type.
3300 return func.lowerConstant(err_tv.val, err_tv.ty);3295 return func.lowerConstant(err_val, err_ty);
3301 }3296 }
33023297
3303 return func.fail("Wasm TODO: lowerConstant error union with non-zero-bit payload type", .{});3298 return func.fail("Wasm TODO: lowerConstant error union with non-zero-bit payload type", .{});
...@@ -3321,10 +3316,10 @@ fn lowerConstant(func: *CodeGen, val: Value, ty: Type) InnerError!WValue {...@@ -3321,10 +3316,10 @@ fn lowerConstant(func: *CodeGen, val: Value, ty: Type) InnerError!WValue {
3321 .elem, .field => |base_index| ptr = ip.indexToKey(base_index.base).ptr,3316 .elem, .field => |base_index| ptr = ip.indexToKey(base_index.base).ptr,
3322 .comptime_field, .comptime_alloc => unreachable,3317 .comptime_field, .comptime_alloc => unreachable,
3323 };3318 };
3324 return .{ .memory = try func.bin_file.lowerUnnamedConst(.{ .ty = ty, .val = val }, owner_decl) };3319 return .{ .memory = try func.bin_file.lowerUnnamedConst(val, owner_decl) };
3325 },3320 },
3326 .ptr => |ptr| switch (ptr.addr) {3321 .ptr => |ptr| switch (ptr.addr) {
3327 .decl => |decl| return func.lowerDeclRefValue(.{ .ty = ty, .val = val }, decl, 0),3322 .decl => |decl| return func.lowerDeclRefValue(val, decl, 0),
3328 .int => |int| return func.lowerConstant(Value.fromInterned(int), Type.fromInterned(ip.typeOf(int))),3323 .int => |int| return func.lowerConstant(Value.fromInterned(int), Type.fromInterned(ip.typeOf(int))),
3329 .opt_payload, .elem, .field => return func.lowerParentPtr(val, 0),3324 .opt_payload, .elem, .field => return func.lowerParentPtr(val, 0),
3330 .anon_decl => |ad| return func.lowerAnonDeclRef(ad, 0),3325 .anon_decl => |ad| return func.lowerAnonDeclRef(ad, 0),
...@@ -7286,7 +7281,7 @@ fn getTagNameFunction(func: *CodeGen, enum_ty: Type) InnerError!u32 {...@@ -7286,7 +7281,7 @@ fn getTagNameFunction(func: *CodeGen, enum_ty: Type) InnerError!u32 {
7286 .storage = .{ .bytes = tag_name },7281 .storage = .{ .bytes = tag_name },
7287 } });7282 } });
7288 const tag_sym_index = try func.bin_file.lowerUnnamedConst(7283 const tag_sym_index = try func.bin_file.lowerUnnamedConst(
7289 .{ .ty = name_ty, .val = Value.fromInterned(name_val) },7284 Value.fromInterned(name_val),
7290 enum_decl_index,7285 enum_decl_index,
7291 );7286 );
72927287
src/arch/x86_64/CodeGen.zig+42-72
...@@ -32,7 +32,6 @@ const InternPool = @import("../../InternPool.zig");...@@ -32,7 +32,6 @@ const InternPool = @import("../../InternPool.zig");
32const Alignment = InternPool.Alignment;32const Alignment = InternPool.Alignment;
33const Target = std.Target;33const Target = std.Target;
34const Type = @import("../../type.zig").Type;34const Type = @import("../../type.zig").Type;
35const TypedValue = @import("../../TypedValue.zig");
36const Value = @import("../../Value.zig");35const Value = @import("../../Value.zig");
37const Instruction = @import("encoder.zig").Instruction;36const Instruction = @import("encoder.zig").Instruction;
3837
...@@ -808,7 +807,7 @@ pub fn generate(...@@ -808,7 +807,7 @@ pub fn generate(
808 const func = zcu.funcInfo(func_index);807 const func = zcu.funcInfo(func_index);
809 const fn_owner_decl = zcu.declPtr(func.owner_decl);808 const fn_owner_decl = zcu.declPtr(func.owner_decl);
810 assert(fn_owner_decl.has_tv);809 assert(fn_owner_decl.has_tv);
811 const fn_type = fn_owner_decl.ty;810 const fn_type = fn_owner_decl.typeOf(zcu);
812 const namespace = zcu.namespacePtr(fn_owner_decl.src_namespace);811 const namespace = zcu.namespacePtr(fn_owner_decl.src_namespace);
813 const mod = namespace.file_scope.mod;812 const mod = namespace.file_scope.mod;
814813
...@@ -2250,7 +2249,7 @@ fn genLazy(self: *Self, lazy_sym: link.File.LazySymbol) InnerError!void {...@@ -2250,7 +2249,7 @@ fn genLazy(self: *Self, lazy_sym: link.File.LazySymbol) InnerError!void {
2250 for (exitlude_jump_relocs, 0..) |*exitlude_jump_reloc, tag_index| {2249 for (exitlude_jump_relocs, 0..) |*exitlude_jump_reloc, tag_index| {
2251 const tag_name_len = ip.stringToSlice(tag_names.get(ip)[tag_index]).len;2250 const tag_name_len = ip.stringToSlice(tag_names.get(ip)[tag_index]).len;
2252 const tag_val = try mod.enumValueFieldIndex(enum_ty, @intCast(tag_index));2251 const tag_val = try mod.enumValueFieldIndex(enum_ty, @intCast(tag_index));
2253 const tag_mcv = try self.genTypedValue(.{ .ty = enum_ty, .val = tag_val });2252 const tag_mcv = try self.genTypedValue(tag_val);
2254 try self.genBinOpMir(.{ ._, .cmp }, enum_ty, enum_mcv, tag_mcv);2253 try self.genBinOpMir(.{ ._, .cmp }, enum_ty, enum_mcv, tag_mcv);
2255 const skip_reloc = try self.asmJccReloc(.ne, undefined);2254 const skip_reloc = try self.asmJccReloc(.ne, undefined);
22562255
...@@ -3323,7 +3322,7 @@ fn airTrunc(self: *Self, inst: Air.Inst.Index) !void {...@@ -3323,7 +3322,7 @@ fn airTrunc(self: *Self, inst: Air.Inst.Index) !void {
3323 .storage = .{ .repeated_elem = mask_val.ip_index },3322 .storage = .{ .repeated_elem = mask_val.ip_index },
3324 } });3323 } });
33253324
3326 const splat_mcv = try self.genTypedValue(.{ .ty = splat_ty, .val = Value.fromInterned(splat_val) });3325 const splat_mcv = try self.genTypedValue(Value.fromInterned(splat_val));
3327 const splat_addr_mcv: MCValue = switch (splat_mcv) {3326 const splat_addr_mcv: MCValue = switch (splat_mcv) {
3328 .memory, .indirect, .load_frame => splat_mcv.address(),3327 .memory, .indirect, .load_frame => splat_mcv.address(),
3329 else => .{ .register = try self.copyToTmpRegister(Type.usize, splat_mcv.address()) },3328 else => .{ .register = try self.copyToTmpRegister(Type.usize, splat_mcv.address()) },
...@@ -4992,17 +4991,14 @@ fn airShlShrBinOp(self: *Self, inst: Air.Inst.Index) !void {...@@ -4992,17 +4991,14 @@ fn airShlShrBinOp(self: *Self, inst: Air.Inst.Index) !void {
4992 defer self.register_manager.unlockReg(shift_lock);4991 defer self.register_manager.unlockReg(shift_lock);
49934992
4994 const mask_ty = try mod.vectorType(.{ .len = 16, .child = .u8_type });4993 const mask_ty = try mod.vectorType(.{ .len = 16, .child = .u8_type });
4995 const mask_mcv = try self.genTypedValue(.{4994 const mask_mcv = try self.genTypedValue(Value.fromInterned(try mod.intern(.{ .aggregate = .{
4996 .ty = mask_ty,4995 .ty = mask_ty.toIntern(),
4997 .val = Value.fromInterned((try mod.intern(.{ .aggregate = .{4996 .storage = .{ .elems = &([1]InternPool.Index{
4998 .ty = mask_ty.toIntern(),4997 (try rhs_ty.childType(mod).maxIntScalar(mod, Type.u8)).toIntern(),
4999 .storage = .{ .elems = &([1]InternPool.Index{4998 } ++ [1]InternPool.Index{
5000 (try rhs_ty.childType(mod).maxIntScalar(mod, Type.u8)).toIntern(),4999 (try mod.intValue(Type.u8, 0)).toIntern(),
5001 } ++ [1]InternPool.Index{5000 } ** 15) },
5002 (try mod.intValue(Type.u8, 0)).toIntern(),5001 } })));
5003 } ** 15) },
5004 } }))),
5005 });
5006 const mask_addr_reg =5002 const mask_addr_reg =
5007 try self.copyToTmpRegister(Type.usize, mask_mcv.address());5003 try self.copyToTmpRegister(Type.usize, mask_mcv.address());
5008 const mask_addr_lock = self.register_manager.lockRegAssumeUnused(mask_addr_reg);5004 const mask_addr_lock = self.register_manager.lockRegAssumeUnused(mask_addr_reg);
...@@ -6860,11 +6856,11 @@ fn floatSign(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, ty: Type)...@@ -6860,11 +6856,11 @@ fn floatSign(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, ty: Type)
6860 .child = (try mod.intType(.signed, scalar_bits)).ip_index,6856 .child = (try mod.intType(.signed, scalar_bits)).ip_index,
6861 });6857 });
68626858
6863 const sign_mcv = try self.genTypedValue(.{ .ty = vec_ty, .val = switch (tag) {6859 const sign_mcv = try self.genTypedValue(switch (tag) {
6864 .neg => try vec_ty.minInt(mod, vec_ty),6860 .neg => try vec_ty.minInt(mod, vec_ty),
6865 .abs => try vec_ty.maxInt(mod, vec_ty),6861 .abs => try vec_ty.maxInt(mod, vec_ty),
6866 else => unreachable,6862 else => unreachable,
6867 } });6863 });
6868 const sign_mem: Memory = if (sign_mcv.isMemory())6864 const sign_mem: Memory = if (sign_mcv.isMemory())
6869 try sign_mcv.mem(self, Memory.Size.fromSize(abi_size))6865 try sign_mcv.mem(self, Memory.Size.fromSize(abi_size))
6870 else6866 else
...@@ -11130,10 +11126,7 @@ fn genBinOp(...@@ -11130,10 +11126,7 @@ fn genBinOp(
11130 .cmp_neq,11126 .cmp_neq,
11131 => {11127 => {
11132 const unsigned_ty = try lhs_ty.toUnsigned(mod);11128 const unsigned_ty = try lhs_ty.toUnsigned(mod);
11133 const not_mcv = try self.genTypedValue(.{11129 const not_mcv = try self.genTypedValue(try unsigned_ty.maxInt(mod, unsigned_ty));
11134 .ty = lhs_ty,
11135 .val = try unsigned_ty.maxInt(mod, unsigned_ty),
11136 });
11137 const not_mem: Memory = if (not_mcv.isMemory())11130 const not_mem: Memory = if (not_mcv.isMemory())
11138 try not_mcv.mem(self, Memory.Size.fromSize(abi_size))11131 try not_mcv.mem(self, Memory.Size.fromSize(abi_size))
11139 else11132 else
...@@ -12258,12 +12251,11 @@ fn genCall(self: *Self, info: union(enum) {...@@ -12258,12 +12251,11 @@ fn genCall(self: *Self, info: union(enum) {
12258 switch (switch (func_key) {12251 switch (switch (func_key) {
12259 else => func_key,12252 else => func_key,
12260 .ptr => |ptr| switch (ptr.addr) {12253 .ptr => |ptr| switch (ptr.addr) {
12261 .decl => |decl| mod.intern_pool.indexToKey(try mod.declPtr(decl).internValue(mod)),12254 .decl => |decl| mod.intern_pool.indexToKey(mod.declPtr(decl).val.toIntern()),
12262 else => func_key,12255 else => func_key,
12263 },12256 },
12264 }) {12257 }) {
12265 .func => |func| {12258 .func => |func| {
12266 try mod.markDeclAlive(mod.declPtr(func.owner_decl));
12267 if (self.bin_file.cast(link.File.Elf)) |elf_file| {12259 if (self.bin_file.cast(link.File.Elf)) |elf_file| {
12268 const sym_index = try elf_file.zigObjectPtr().?.getOrCreateMetadataForDecl(elf_file, func.owner_decl);12260 const sym_index = try elf_file.zigObjectPtr().?.getOrCreateMetadataForDecl(elf_file, func.owner_decl);
12269 const sym = elf_file.symbol(sym_index);12261 const sym = elf_file.symbol(sym_index);
...@@ -12323,7 +12315,6 @@ fn genCall(self: *Self, info: union(enum) {...@@ -12323,7 +12315,6 @@ fn genCall(self: *Self, info: union(enum) {
12323 },12315 },
12324 .extern_func => |extern_func| {12316 .extern_func => |extern_func| {
12325 const owner_decl = mod.declPtr(extern_func.decl);12317 const owner_decl = mod.declPtr(extern_func.decl);
12326 try mod.markDeclAlive(owner_decl);
12327 const lib_name = mod.intern_pool.stringToSliceUnwrap(extern_func.lib_name);12318 const lib_name = mod.intern_pool.stringToSliceUnwrap(extern_func.lib_name);
12328 const decl_name = mod.intern_pool.stringToSlice(owner_decl.name);12319 const decl_name = mod.intern_pool.stringToSlice(owner_decl.name);
12329 try self.genExternSymbolRef(.call, lib_name, decl_name);12320 try self.genExternSymbolRef(.call, lib_name, decl_name);
...@@ -14694,10 +14685,7 @@ fn genSetReg(...@@ -14694,10 +14685,7 @@ fn genSetReg(
14694 ),14685 ),
14695 else => unreachable,14686 else => unreachable,
14696 },14687 },
14697 .segment, .x87, .mmx, .sse => try self.genSetReg(dst_reg, ty, try self.genTypedValue(.{14688 .segment, .x87, .mmx, .sse => try self.genSetReg(dst_reg, ty, try self.genTypedValue(try mod.undefValue(ty)), opts),
14698 .ty = ty,
14699 .val = try mod.undefValue(ty),
14700 }), opts),
14701 },14689 },
14702 .eflags => |cc| try self.asmSetccRegister(cc, dst_reg.to8()),14690 .eflags => |cc| try self.asmSetccRegister(cc, dst_reg.to8()),
14703 .immediate => |imm| {14691 .immediate => |imm| {
...@@ -16895,13 +16883,10 @@ fn airSelect(self: *Self, inst: Air.Inst.Index) !void {...@@ -16895,13 +16883,10 @@ fn airSelect(self: *Self, inst: Air.Inst.Index) !void {
16895 .ty = mask_elem_ty.toIntern(),16883 .ty = mask_elem_ty.toIntern(),
16896 .storage = .{ .u64 = bit / elem_bits },16884 .storage = .{ .u64 = bit / elem_bits },
16897 } });16885 } });
16898 const mask_mcv = try self.genTypedValue(.{16886 const mask_mcv = try self.genTypedValue(Value.fromInterned(try mod.intern(.{ .aggregate = .{
16899 .ty = mask_ty,16887 .ty = mask_ty.toIntern(),
16900 .val = Value.fromInterned(try mod.intern(.{ .aggregate = .{16888 .storage = .{ .elems = mask_elems[0..vec_len] },
16901 .ty = mask_ty.toIntern(),16889 } })));
16902 .storage = .{ .elems = mask_elems[0..vec_len] },
16903 } })),
16904 });
16905 const mask_mem: Memory = .{16890 const mask_mem: Memory = .{
16906 .base = .{ .reg = try self.copyToTmpRegister(Type.usize, mask_mcv.address()) },16891 .base = .{ .reg = try self.copyToTmpRegister(Type.usize, mask_mcv.address()) },
16907 .mod = .{ .rm = .{ .size = self.memSize(ty) } },16892 .mod = .{ .rm = .{ .size = self.memSize(ty) } },
...@@ -16923,13 +16908,10 @@ fn airSelect(self: *Self, inst: Air.Inst.Index) !void {...@@ -16923,13 +16908,10 @@ fn airSelect(self: *Self, inst: Air.Inst.Index) !void {
16923 .ty = mask_elem_ty.toIntern(),16908 .ty = mask_elem_ty.toIntern(),
16924 .storage = .{ .u64 = @as(u32, 1) << @intCast(bit & (elem_bits - 1)) },16909 .storage = .{ .u64 = @as(u32, 1) << @intCast(bit & (elem_bits - 1)) },
16925 } });16910 } });
16926 const mask_mcv = try self.genTypedValue(.{16911 const mask_mcv = try self.genTypedValue(Value.fromInterned(try mod.intern(.{ .aggregate = .{
16927 .ty = mask_ty,16912 .ty = mask_ty.toIntern(),
16928 .val = Value.fromInterned(try mod.intern(.{ .aggregate = .{16913 .storage = .{ .elems = mask_elems[0..vec_len] },
16929 .ty = mask_ty.toIntern(),16914 } })));
16930 .storage = .{ .elems = mask_elems[0..vec_len] },
16931 } })),
16932 });
16933 const mask_mem: Memory = .{16915 const mask_mem: Memory = .{
16934 .base = .{ .reg = try self.copyToTmpRegister(Type.usize, mask_mcv.address()) },16916 .base = .{ .reg = try self.copyToTmpRegister(Type.usize, mask_mcv.address()) },
16935 .mod = .{ .rm = .{ .size = self.memSize(ty) } },16917 .mod = .{ .rm = .{ .size = self.memSize(ty) } },
...@@ -17660,13 +17642,10 @@ fn airShuffle(self: *Self, inst: Air.Inst.Index) !void {...@@ -17660,13 +17642,10 @@ fn airShuffle(self: *Self, inst: Air.Inst.Index) !void {
17660 else17642 else
17661 try select_mask_elem_ty.minIntScalar(mod, select_mask_elem_ty)).toIntern();17643 try select_mask_elem_ty.minIntScalar(mod, select_mask_elem_ty)).toIntern();
17662 }17644 }
17663 const select_mask_mcv = try self.genTypedValue(.{17645 const select_mask_mcv = try self.genTypedValue(Value.fromInterned(try mod.intern(.{ .aggregate = .{
17664 .ty = select_mask_ty,17646 .ty = select_mask_ty.toIntern(),
17665 .val = Value.fromInterned(try mod.intern(.{ .aggregate = .{17647 .storage = .{ .elems = select_mask_elems[0..mask_elems.len] },
17666 .ty = select_mask_ty.toIntern(),17648 } })));
17667 .storage = .{ .elems = select_mask_elems[0..mask_elems.len] },
17668 } })),
17669 });
1767017649
17671 if (self.hasFeature(.sse4_1)) {17650 if (self.hasFeature(.sse4_1)) {
17672 const mir_tag: Mir.Inst.FixedTag = .{17651 const mir_tag: Mir.Inst.FixedTag = .{
...@@ -17811,13 +17790,10 @@ fn airShuffle(self: *Self, inst: Air.Inst.Index) !void {...@@ -17811,13 +17790,10 @@ fn airShuffle(self: *Self, inst: Air.Inst.Index) !void {
17811 } });17790 } });
17812 }17791 }
17813 const lhs_mask_ty = try mod.vectorType(.{ .len = max_abi_size, .child = .u8_type });17792 const lhs_mask_ty = try mod.vectorType(.{ .len = max_abi_size, .child = .u8_type });
17814 const lhs_mask_mcv = try self.genTypedValue(.{17793 const lhs_mask_mcv = try self.genTypedValue(Value.fromInterned(try mod.intern(.{ .aggregate = .{
17815 .ty = lhs_mask_ty,17794 .ty = lhs_mask_ty.toIntern(),
17816 .val = Value.fromInterned(try mod.intern(.{ .aggregate = .{17795 .storage = .{ .elems = lhs_mask_elems[0..max_abi_size] },
17817 .ty = lhs_mask_ty.toIntern(),17796 } })));
17818 .storage = .{ .elems = lhs_mask_elems[0..max_abi_size] },
17819 } })),
17820 });
17821 const lhs_mask_mem: Memory = .{17797 const lhs_mask_mem: Memory = .{
17822 .base = .{ .reg = try self.copyToTmpRegister(Type.usize, lhs_mask_mcv.address()) },17798 .base = .{ .reg = try self.copyToTmpRegister(Type.usize, lhs_mask_mcv.address()) },
17823 .mod = .{ .rm = .{ .size = Memory.Size.fromSize(@max(max_abi_size, 16)) } },17799 .mod = .{ .rm = .{ .size = Memory.Size.fromSize(@max(max_abi_size, 16)) } },
...@@ -17848,13 +17824,10 @@ fn airShuffle(self: *Self, inst: Air.Inst.Index) !void {...@@ -17848,13 +17824,10 @@ fn airShuffle(self: *Self, inst: Air.Inst.Index) !void {
17848 } });17824 } });
17849 }17825 }
17850 const rhs_mask_ty = try mod.vectorType(.{ .len = max_abi_size, .child = .u8_type });17826 const rhs_mask_ty = try mod.vectorType(.{ .len = max_abi_size, .child = .u8_type });
17851 const rhs_mask_mcv = try self.genTypedValue(.{17827 const rhs_mask_mcv = try self.genTypedValue(Value.fromInterned(try mod.intern(.{ .aggregate = .{
17852 .ty = rhs_mask_ty,17828 .ty = rhs_mask_ty.toIntern(),
17853 .val = Value.fromInterned(try mod.intern(.{ .aggregate = .{17829 .storage = .{ .elems = rhs_mask_elems[0..max_abi_size] },
17854 .ty = rhs_mask_ty.toIntern(),17830 } })));
17855 .storage = .{ .elems = rhs_mask_elems[0..max_abi_size] },
17856 } })),
17857 });
17858 const rhs_mask_mem: Memory = .{17831 const rhs_mask_mem: Memory = .{
17859 .base = .{ .reg = try self.copyToTmpRegister(Type.usize, rhs_mask_mcv.address()) },17832 .base = .{ .reg = try self.copyToTmpRegister(Type.usize, rhs_mask_mcv.address()) },
17860 .mod = .{ .rm = .{ .size = Memory.Size.fromSize(@max(max_abi_size, 16)) } },17833 .mod = .{ .rm = .{ .size = Memory.Size.fromSize(@max(max_abi_size, 16)) } },
...@@ -17903,11 +17876,8 @@ fn airShuffle(self: *Self, inst: Air.Inst.Index) !void {...@@ -17903,11 +17876,8 @@ fn airShuffle(self: *Self, inst: Air.Inst.Index) !void {
1790317876
17904 break :result null;17877 break :result null;
17905 }) orelse return self.fail("TODO implement airShuffle from {} and {} to {} with {}", .{17878 }) orelse return self.fail("TODO implement airShuffle from {} and {} to {} with {}", .{
17906 lhs_ty.fmt(mod), rhs_ty.fmt(mod), dst_ty.fmt(mod),17879 lhs_ty.fmt(mod), rhs_ty.fmt(mod), dst_ty.fmt(mod),
17907 Value.fromInterned(extra.mask).fmtValue(17880 Value.fromInterned(extra.mask).fmtValue(mod),
17908 Type.fromInterned(mod.intern_pool.typeOf(extra.mask)),
17909 mod,
17910 ),
17911 });17881 });
17912 return self.finishAir(inst, result, .{ extra.a, extra.b, .none });17882 return self.finishAir(inst, result, .{ extra.a, extra.b, .none });
17913}17883}
...@@ -18140,7 +18110,7 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void {...@@ -18140,7 +18110,7 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void {
18140 .{ .frame = frame_index },18110 .{ .frame = frame_index },
18141 @intCast(elem_size * elements.len),18111 @intCast(elem_size * elements.len),
18142 elem_ty,18112 elem_ty,
18143 try self.genTypedValue(.{ .ty = elem_ty, .val = sentinel }),18113 try self.genTypedValue(sentinel),
18144 .{},18114 .{},
18145 );18115 );
18146 break :result .{ .load_frame = .{ .index = frame_index } };18116 break :result .{ .load_frame = .{ .index = frame_index } };
...@@ -18664,7 +18634,7 @@ fn resolveInst(self: *Self, ref: Air.Inst.Ref) InnerError!MCValue {...@@ -18664,7 +18634,7 @@ fn resolveInst(self: *Self, ref: Air.Inst.Ref) InnerError!MCValue {
18664 const ip_index = ref.toInterned().?;18634 const ip_index = ref.toInterned().?;
18665 const gop = try self.const_tracking.getOrPut(self.gpa, ip_index);18635 const gop = try self.const_tracking.getOrPut(self.gpa, ip_index);
18666 if (!gop.found_existing) gop.value_ptr.* = InstTracking.init(init: {18636 if (!gop.found_existing) gop.value_ptr.* = InstTracking.init(init: {
18667 const const_mcv = try self.genTypedValue(.{ .ty = ty, .val = Value.fromInterned(ip_index) });18637 const const_mcv = try self.genTypedValue(Value.fromInterned(ip_index));
18668 switch (const_mcv) {18638 switch (const_mcv) {
18669 .lea_tlv => |tlv_sym| switch (self.bin_file.tag) {18639 .lea_tlv => |tlv_sym| switch (self.bin_file.tag) {
18670 .elf, .macho => {18640 .elf, .macho => {
...@@ -18729,9 +18699,9 @@ fn limitImmediateType(self: *Self, operand: Air.Inst.Ref, comptime T: type) !MCV...@@ -18729,9 +18699,9 @@ fn limitImmediateType(self: *Self, operand: Air.Inst.Ref, comptime T: type) !MCV
18729 return mcv;18699 return mcv;
18730}18700}
1873118701
18732fn genTypedValue(self: *Self, arg_tv: TypedValue) InnerError!MCValue {18702fn genTypedValue(self: *Self, val: Value) InnerError!MCValue {
18733 const mod = self.bin_file.comp.module.?;18703 const mod = self.bin_file.comp.module.?;
18734 return switch (try codegen.genTypedValue(self.bin_file, self.src_loc, arg_tv, self.owner.getDecl(mod))) {18704 return switch (try codegen.genTypedValue(self.bin_file, self.src_loc, val, self.owner.getDecl(mod))) {
18735 .mcv => |mcv| switch (mcv) {18705 .mcv => |mcv| switch (mcv) {
18736 .none => .none,18706 .none => .none,
18737 .undef => .undef,18707 .undef => .undef,
src/codegen.zig+123-177
...@@ -19,7 +19,6 @@ const Liveness = @import("Liveness.zig");...@@ -19,7 +19,6 @@ const Liveness = @import("Liveness.zig");
19const Module = @import("Module.zig");19const Module = @import("Module.zig");
20const Target = std.Target;20const Target = std.Target;
21const Type = @import("type.zig").Type;21const Type = @import("type.zig").Type;
22const TypedValue = @import("TypedValue.zig");
23const Value = @import("Value.zig");22const Value = @import("Value.zig");
24const Zir = std.zig.Zir;23const Zir = std.zig.Zir;
25const Alignment = InternPool.Alignment;24const Alignment = InternPool.Alignment;
...@@ -171,7 +170,7 @@ pub fn generateLazySymbol(...@@ -171,7 +170,7 @@ pub fn generateLazySymbol(
171pub fn generateSymbol(170pub fn generateSymbol(
172 bin_file: *link.File,171 bin_file: *link.File,
173 src_loc: Module.SrcLoc,172 src_loc: Module.SrcLoc,
174 arg_tv: TypedValue,173 val: Value,
175 code: *std.ArrayList(u8),174 code: *std.ArrayList(u8),
176 debug_output: DebugInfoOutput,175 debug_output: DebugInfoOutput,
177 reloc_info: RelocInfo,176 reloc_info: RelocInfo,
...@@ -181,23 +180,20 @@ pub fn generateSymbol(...@@ -181,23 +180,20 @@ pub fn generateSymbol(
181180
182 const mod = bin_file.comp.module.?;181 const mod = bin_file.comp.module.?;
183 const ip = &mod.intern_pool;182 const ip = &mod.intern_pool;
184 const typed_value = arg_tv;183 const ty = val.typeOf(mod);
185184
186 const target = mod.getTarget();185 const target = mod.getTarget();
187 const endian = target.cpu.arch.endian();186 const endian = target.cpu.arch.endian();
188187
189 log.debug("generateSymbol: ty = {}, val = {}", .{188 log.debug("generateSymbol: val = {}", .{val.fmtValue(mod)});
190 typed_value.ty.fmt(mod),
191 typed_value.val.fmtValue(typed_value.ty, mod),
192 });
193189
194 if (typed_value.val.isUndefDeep(mod)) {190 if (val.isUndefDeep(mod)) {
195 const abi_size = math.cast(usize, typed_value.ty.abiSize(mod)) orelse return error.Overflow;191 const abi_size = math.cast(usize, ty.abiSize(mod)) orelse return error.Overflow;
196 try code.appendNTimes(0xaa, abi_size);192 try code.appendNTimes(0xaa, abi_size);
197 return .ok;193 return .ok;
198 }194 }
199195
200 switch (ip.indexToKey(typed_value.val.toIntern())) {196 switch (ip.indexToKey(val.toIntern())) {
201 .int_type,197 .int_type,
202 .ptr_type,198 .ptr_type,
203 .array_type,199 .array_type,
...@@ -238,17 +234,17 @@ pub fn generateSymbol(...@@ -238,17 +234,17 @@ pub fn generateSymbol(
238 .empty_enum_value,234 .empty_enum_value,
239 => unreachable, // non-runtime values235 => unreachable, // non-runtime values
240 .int => {236 .int => {
241 const abi_size = math.cast(usize, typed_value.ty.abiSize(mod)) orelse return error.Overflow;237 const abi_size = math.cast(usize, ty.abiSize(mod)) orelse return error.Overflow;
242 var space: Value.BigIntSpace = undefined;238 var space: Value.BigIntSpace = undefined;
243 const val = typed_value.val.toBigInt(&space, mod);239 const int_val = val.toBigInt(&space, mod);
244 val.writeTwosComplement(try code.addManyAsSlice(abi_size), endian);240 int_val.writeTwosComplement(try code.addManyAsSlice(abi_size), endian);
245 },241 },
246 .err => |err| {242 .err => |err| {
247 const int = try mod.getErrorValue(err.name);243 const int = try mod.getErrorValue(err.name);
248 try code.writer().writeInt(u16, @as(u16, @intCast(int)), endian);244 try code.writer().writeInt(u16, @as(u16, @intCast(int)), endian);
249 },245 },
250 .error_union => |error_union| {246 .error_union => |error_union| {
251 const payload_ty = typed_value.ty.errorUnionPayload(mod);247 const payload_ty = ty.errorUnionPayload(mod);
252 const err_val = switch (error_union.val) {248 const err_val = switch (error_union.val) {
253 .err_name => |err_name| @as(u16, @intCast(try mod.getErrorValue(err_name))),249 .err_name => |err_name| @as(u16, @intCast(try mod.getErrorValue(err_name))),
254 .payload => @as(u16, 0),250 .payload => @as(u16, 0),
...@@ -261,7 +257,7 @@ pub fn generateSymbol(...@@ -261,7 +257,7 @@ pub fn generateSymbol(
261257
262 const payload_align = payload_ty.abiAlignment(mod);258 const payload_align = payload_ty.abiAlignment(mod);
263 const error_align = Type.anyerror.abiAlignment(mod);259 const error_align = Type.anyerror.abiAlignment(mod);
264 const abi_align = typed_value.ty.abiAlignment(mod);260 const abi_align = ty.abiAlignment(mod);
265261
266 // error value first when its type is larger than the error union's payload262 // error value first when its type is larger than the error union's payload
267 if (error_align.order(payload_align) == .gt) {263 if (error_align.order(payload_align) == .gt) {
...@@ -271,13 +267,10 @@ pub fn generateSymbol(...@@ -271,13 +267,10 @@ pub fn generateSymbol(
271 // emit payload part of the error union267 // emit payload part of the error union
272 {268 {
273 const begin = code.items.len;269 const begin = code.items.len;
274 switch (try generateSymbol(bin_file, src_loc, .{270 switch (try generateSymbol(bin_file, src_loc, Value.fromInterned(switch (error_union.val) {
275 .ty = payload_ty,271 .err_name => try mod.intern(.{ .undef = payload_ty.toIntern() }),
276 .val = Value.fromInterned(switch (error_union.val) {272 .payload => |payload| payload,
277 .err_name => try mod.intern(.{ .undef = payload_ty.toIntern() }),273 }), code, debug_output, reloc_info)) {
278 .payload => |payload| payload,
279 }),
280 }, code, debug_output, reloc_info)) {
281 .ok => {},274 .ok => {},
282 .fail => |em| return .{ .fail = em },275 .fail => |em| return .{ .fail = em },
283 }276 }
...@@ -304,11 +297,8 @@ pub fn generateSymbol(...@@ -304,11 +297,8 @@ pub fn generateSymbol(
304 }297 }
305 },298 },
306 .enum_tag => |enum_tag| {299 .enum_tag => |enum_tag| {
307 const int_tag_ty = typed_value.ty.intTagType(mod);300 const int_tag_ty = ty.intTagType(mod);
308 switch (try generateSymbol(bin_file, src_loc, .{301 switch (try generateSymbol(bin_file, src_loc, try mod.getCoerced(Value.fromInterned(enum_tag.int), int_tag_ty), code, debug_output, reloc_info)) {
309 .ty = int_tag_ty,
310 .val = try mod.getCoerced(Value.fromInterned(enum_tag.int), int_tag_ty),
311 }, code, debug_output, reloc_info)) {
312 .ok => {},302 .ok => {},
313 .fail => |em| return .{ .fail = em },303 .fail => |em| return .{ .fail = em },
314 }304 }
...@@ -319,42 +309,33 @@ pub fn generateSymbol(...@@ -319,42 +309,33 @@ pub fn generateSymbol(
319 .f64 => |f64_val| writeFloat(f64, f64_val, target, endian, try code.addManyAsArray(8)),309 .f64 => |f64_val| writeFloat(f64, f64_val, target, endian, try code.addManyAsArray(8)),
320 .f80 => |f80_val| {310 .f80 => |f80_val| {
321 writeFloat(f80, f80_val, target, endian, try code.addManyAsArray(10));311 writeFloat(f80, f80_val, target, endian, try code.addManyAsArray(10));
322 const abi_size = math.cast(usize, typed_value.ty.abiSize(mod)) orelse return error.Overflow;312 const abi_size = math.cast(usize, ty.abiSize(mod)) orelse return error.Overflow;
323 try code.appendNTimes(0, abi_size - 10);313 try code.appendNTimes(0, abi_size - 10);
324 },314 },
325 .f128 => |f128_val| writeFloat(f128, f128_val, target, endian, try code.addManyAsArray(16)),315 .f128 => |f128_val| writeFloat(f128, f128_val, target, endian, try code.addManyAsArray(16)),
326 },316 },
327 .ptr => switch (try lowerParentPtr(bin_file, src_loc, typed_value.val.toIntern(), code, debug_output, reloc_info)) {317 .ptr => switch (try lowerParentPtr(bin_file, src_loc, val.toIntern(), code, debug_output, reloc_info)) {
328 .ok => {},318 .ok => {},
329 .fail => |em| return .{ .fail = em },319 .fail => |em| return .{ .fail = em },
330 },320 },
331 .slice => |slice| {321 .slice => |slice| {
332 switch (try generateSymbol(bin_file, src_loc, .{322 switch (try generateSymbol(bin_file, src_loc, Value.fromInterned(slice.ptr), code, debug_output, reloc_info)) {
333 .ty = typed_value.ty.slicePtrFieldType(mod),
334 .val = Value.fromInterned(slice.ptr),
335 }, code, debug_output, reloc_info)) {
336 .ok => {},323 .ok => {},
337 .fail => |em| return .{ .fail = em },324 .fail => |em| return .{ .fail = em },
338 }325 }
339 switch (try generateSymbol(bin_file, src_loc, .{326 switch (try generateSymbol(bin_file, src_loc, Value.fromInterned(slice.len), code, debug_output, reloc_info)) {
340 .ty = Type.usize,
341 .val = Value.fromInterned(slice.len),
342 }, code, debug_output, reloc_info)) {
343 .ok => {},327 .ok => {},
344 .fail => |em| return .{ .fail = em },328 .fail => |em| return .{ .fail = em },
345 }329 }
346 },330 },
347 .opt => {331 .opt => {
348 const payload_type = typed_value.ty.optionalChild(mod);332 const payload_type = ty.optionalChild(mod);
349 const payload_val = typed_value.val.optionalValue(mod);333 const payload_val = val.optionalValue(mod);
350 const abi_size = math.cast(usize, typed_value.ty.abiSize(mod)) orelse return error.Overflow;334 const abi_size = math.cast(usize, ty.abiSize(mod)) orelse return error.Overflow;
351335
352 if (typed_value.ty.optionalReprIsPayload(mod)) {336 if (ty.optionalReprIsPayload(mod)) {
353 if (payload_val) |value| {337 if (payload_val) |value| {
354 switch (try generateSymbol(bin_file, src_loc, .{338 switch (try generateSymbol(bin_file, src_loc, value, code, debug_output, reloc_info)) {
355 .ty = payload_type,
356 .val = value,
357 }, code, debug_output, reloc_info)) {
358 .ok => {},339 .ok => {},
359 .fail => |em| return Result{ .fail = em },340 .fail => |em| return Result{ .fail = em },
360 }341 }
...@@ -365,10 +346,7 @@ pub fn generateSymbol(...@@ -365,10 +346,7 @@ pub fn generateSymbol(
365 const padding = abi_size - (math.cast(usize, payload_type.abiSize(mod)) orelse return error.Overflow) - 1;346 const padding = abi_size - (math.cast(usize, payload_type.abiSize(mod)) orelse return error.Overflow) - 1;
366 if (payload_type.hasRuntimeBits(mod)) {347 if (payload_type.hasRuntimeBits(mod)) {
367 const value = payload_val orelse Value.fromInterned((try mod.intern(.{ .undef = payload_type.toIntern() })));348 const value = payload_val orelse Value.fromInterned((try mod.intern(.{ .undef = payload_type.toIntern() })));
368 switch (try generateSymbol(bin_file, src_loc, .{349 switch (try generateSymbol(bin_file, src_loc, value, code, debug_output, reloc_info)) {
369 .ty = payload_type,
370 .val = value,
371 }, code, debug_output, reloc_info)) {
372 .ok => {},350 .ok => {},
373 .fail => |em| return Result{ .fail = em },351 .fail => |em| return Result{ .fail = em },
374 }352 }
...@@ -377,7 +355,7 @@ pub fn generateSymbol(...@@ -377,7 +355,7 @@ pub fn generateSymbol(
377 try code.appendNTimes(0, padding);355 try code.appendNTimes(0, padding);
378 }356 }
379 },357 },
380 .aggregate => |aggregate| switch (ip.indexToKey(typed_value.ty.toIntern())) {358 .aggregate => |aggregate| switch (ip.indexToKey(ty.toIntern())) {
381 .array_type => |array_type| switch (aggregate.storage) {359 .array_type => |array_type| switch (aggregate.storage) {
382 .bytes => |bytes| try code.appendSlice(bytes),360 .bytes => |bytes| try code.appendSlice(bytes),
383 .elems, .repeated_elem => {361 .elems, .repeated_elem => {
...@@ -385,17 +363,14 @@ pub fn generateSymbol(...@@ -385,17 +363,14 @@ pub fn generateSymbol(
385 const len_including_sentinel =363 const len_including_sentinel =
386 array_type.len + @intFromBool(array_type.sentinel != .none);364 array_type.len + @intFromBool(array_type.sentinel != .none);
387 while (index < len_including_sentinel) : (index += 1) {365 while (index < len_including_sentinel) : (index += 1) {
388 switch (try generateSymbol(bin_file, src_loc, .{366 switch (try generateSymbol(bin_file, src_loc, Value.fromInterned(switch (aggregate.storage) {
389 .ty = Type.fromInterned(array_type.child),367 .bytes => unreachable,
390 .val = Value.fromInterned(switch (aggregate.storage) {368 .elems => |elems| elems[@as(usize, @intCast(index))],
391 .bytes => unreachable,369 .repeated_elem => |elem| if (index < array_type.len)
392 .elems => |elems| elems[@as(usize, @intCast(index))],370 elem
393 .repeated_elem => |elem| if (index < array_type.len)371 else
394 elem372 array_type.sentinel,
395 else373 }), code, debug_output, reloc_info)) {
396 array_type.sentinel,
397 }),
398 }, code, debug_output, reloc_info)) {
399 .ok => {},374 .ok => {},
400 .fail => |em| return .{ .fail = em },375 .fail => |em| return .{ .fail = em },
401 }376 }
...@@ -403,7 +378,7 @@ pub fn generateSymbol(...@@ -403,7 +378,7 @@ pub fn generateSymbol(
403 },378 },
404 },379 },
405 .vector_type => |vector_type| {380 .vector_type => |vector_type| {
406 const abi_size = math.cast(usize, typed_value.ty.abiSize(mod)) orelse381 const abi_size = math.cast(usize, ty.abiSize(mod)) orelse
407 return error.Overflow;382 return error.Overflow;
408 if (vector_type.child == .bool_type) {383 if (vector_type.child == .bool_type) {
409 const bytes = try code.addManyAsSlice(abi_size);384 const bytes = try code.addManyAsSlice(abi_size);
...@@ -449,16 +424,13 @@ pub fn generateSymbol(...@@ -449,16 +424,13 @@ pub fn generateSymbol(
449 .elems, .repeated_elem => {424 .elems, .repeated_elem => {
450 var index: u64 = 0;425 var index: u64 = 0;
451 while (index < vector_type.len) : (index += 1) {426 while (index < vector_type.len) : (index += 1) {
452 switch (try generateSymbol(bin_file, src_loc, .{427 switch (try generateSymbol(bin_file, src_loc, Value.fromInterned(switch (aggregate.storage) {
453 .ty = Type.fromInterned(vector_type.child),428 .bytes => unreachable,
454 .val = Value.fromInterned(switch (aggregate.storage) {429 .elems => |elems| elems[
455 .bytes => unreachable,430 math.cast(usize, index) orelse return error.Overflow
456 .elems => |elems| elems[431 ],
457 math.cast(usize, index) orelse return error.Overflow432 .repeated_elem => |elem| elem,
458 ],433 }), code, debug_output, reloc_info)) {
459 .repeated_elem => |elem| elem,
460 }),
461 }, code, debug_output, reloc_info)) {
462 .ok => {},434 .ok => {},
463 .fail => |em| return .{ .fail = em },435 .fail => |em| return .{ .fail = em },
464 }436 }
...@@ -491,17 +463,14 @@ pub fn generateSymbol(...@@ -491,17 +463,14 @@ pub fn generateSymbol(
491 .repeated_elem => |elem| elem,463 .repeated_elem => |elem| elem,
492 };464 };
493465
494 switch (try generateSymbol(bin_file, src_loc, .{466 switch (try generateSymbol(bin_file, src_loc, Value.fromInterned(field_val), code, debug_output, reloc_info)) {
495 .ty = Type.fromInterned(field_ty),
496 .val = Value.fromInterned(field_val),
497 }, code, debug_output, reloc_info)) {
498 .ok => {},467 .ok => {},
499 .fail => |em| return Result{ .fail = em },468 .fail => |em| return Result{ .fail = em },
500 }469 }
501 const unpadded_field_end = code.items.len - struct_begin;470 const unpadded_field_end = code.items.len - struct_begin;
502471
503 // Pad struct members if required472 // Pad struct members if required
504 const padded_field_end = typed_value.ty.structFieldOffset(index + 1, mod);473 const padded_field_end = ty.structFieldOffset(index + 1, mod);
505 const padding = math.cast(usize, padded_field_end - unpadded_field_end) orelse474 const padding = math.cast(usize, padded_field_end - unpadded_field_end) orelse
506 return error.Overflow;475 return error.Overflow;
507476
...@@ -511,10 +480,10 @@ pub fn generateSymbol(...@@ -511,10 +480,10 @@ pub fn generateSymbol(
511 }480 }
512 },481 },
513 .struct_type => {482 .struct_type => {
514 const struct_type = ip.loadStructType(typed_value.ty.toIntern());483 const struct_type = ip.loadStructType(ty.toIntern());
515 switch (struct_type.layout) {484 switch (struct_type.layout) {
516 .@"packed" => {485 .@"packed" => {
517 const abi_size = math.cast(usize, typed_value.ty.abiSize(mod)) orelse486 const abi_size = math.cast(usize, ty.abiSize(mod)) orelse
518 return error.Overflow;487 return error.Overflow;
519 const current_pos = code.items.len;488 const current_pos = code.items.len;
520 try code.resize(current_pos + abi_size);489 try code.resize(current_pos + abi_size);
...@@ -537,10 +506,7 @@ pub fn generateSymbol(...@@ -537,10 +506,7 @@ pub fn generateSymbol(
537 return error.Overflow;506 return error.Overflow;
538 var tmp_list = try std.ArrayList(u8).initCapacity(code.allocator, field_size);507 var tmp_list = try std.ArrayList(u8).initCapacity(code.allocator, field_size);
539 defer tmp_list.deinit();508 defer tmp_list.deinit();
540 switch (try generateSymbol(bin_file, src_loc, .{509 switch (try generateSymbol(bin_file, src_loc, Value.fromInterned(field_val), &tmp_list, debug_output, reloc_info)) {
541 .ty = Type.fromInterned(field_ty),
542 .val = Value.fromInterned(field_val),
543 }, &tmp_list, debug_output, reloc_info)) {
544 .ok => @memcpy(code.items[current_pos..][0..tmp_list.items.len], tmp_list.items),510 .ok => @memcpy(code.items[current_pos..][0..tmp_list.items.len], tmp_list.items),
545 .fail => |em| return Result{ .fail = em },511 .fail => |em| return Result{ .fail = em },
546 }512 }
...@@ -560,7 +526,7 @@ pub fn generateSymbol(...@@ -560,7 +526,7 @@ pub fn generateSymbol(
560 const field_ty = field_types[field_index];526 const field_ty = field_types[field_index];
561 if (!Type.fromInterned(field_ty).hasRuntimeBits(mod)) continue;527 if (!Type.fromInterned(field_ty).hasRuntimeBits(mod)) continue;
562528
563 const field_val = switch (ip.indexToKey(typed_value.val.toIntern()).aggregate.storage) {529 const field_val = switch (ip.indexToKey(val.toIntern()).aggregate.storage) {
564 .bytes => |bytes| try ip.get(mod.gpa, .{ .int = .{530 .bytes => |bytes| try ip.get(mod.gpa, .{ .int = .{
565 .ty = field_ty,531 .ty = field_ty,
566 .storage = .{ .u64 = bytes[field_index] },532 .storage = .{ .u64 = bytes[field_index] },
...@@ -575,10 +541,7 @@ pub fn generateSymbol(...@@ -575,10 +541,7 @@ pub fn generateSymbol(
575 ) orelse return error.Overflow;541 ) orelse return error.Overflow;
576 if (padding > 0) try code.appendNTimes(0, padding);542 if (padding > 0) try code.appendNTimes(0, padding);
577543
578 switch (try generateSymbol(bin_file, src_loc, .{544 switch (try generateSymbol(bin_file, src_loc, Value.fromInterned(field_val), code, debug_output, reloc_info)) {
579 .ty = Type.fromInterned(field_ty),
580 .val = Value.fromInterned(field_val),
581 }, code, debug_output, reloc_info)) {
582 .ok => {},545 .ok => {},
583 .fail => |em| return Result{ .fail = em },546 .fail => |em| return Result{ .fail = em },
584 }547 }
...@@ -599,37 +562,28 @@ pub fn generateSymbol(...@@ -599,37 +562,28 @@ pub fn generateSymbol(
599 else => unreachable,562 else => unreachable,
600 },563 },
601 .un => |un| {564 .un => |un| {
602 const layout = typed_value.ty.unionGetLayout(mod);565 const layout = ty.unionGetLayout(mod);
603566
604 if (layout.payload_size == 0) {567 if (layout.payload_size == 0) {
605 return generateSymbol(bin_file, src_loc, .{568 return generateSymbol(bin_file, src_loc, Value.fromInterned(un.tag), code, debug_output, reloc_info);
606 .ty = typed_value.ty.unionTagTypeSafety(mod).?,
607 .val = Value.fromInterned(un.tag),
608 }, code, debug_output, reloc_info);
609 }569 }
610570
611 // Check if we should store the tag first.571 // Check if we should store the tag first.
612 if (layout.tag_size > 0 and layout.tag_align.compare(.gte, layout.payload_align)) {572 if (layout.tag_size > 0 and layout.tag_align.compare(.gte, layout.payload_align)) {
613 switch (try generateSymbol(bin_file, src_loc, .{573 switch (try generateSymbol(bin_file, src_loc, Value.fromInterned(un.tag), code, debug_output, reloc_info)) {
614 .ty = typed_value.ty.unionTagTypeSafety(mod).?,
615 .val = Value.fromInterned(un.tag),
616 }, code, debug_output, reloc_info)) {
617 .ok => {},574 .ok => {},
618 .fail => |em| return Result{ .fail = em },575 .fail => |em| return Result{ .fail = em },
619 }576 }
620 }577 }
621578
622 const union_obj = mod.typeToUnion(typed_value.ty).?;579 const union_obj = mod.typeToUnion(ty).?;
623 if (un.tag != .none) {580 if (un.tag != .none) {
624 const field_index = typed_value.ty.unionTagFieldIndex(Value.fromInterned(un.tag), mod).?;581 const field_index = ty.unionTagFieldIndex(Value.fromInterned(un.tag), mod).?;
625 const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[field_index]);582 const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[field_index]);
626 if (!field_ty.hasRuntimeBits(mod)) {583 if (!field_ty.hasRuntimeBits(mod)) {
627 try code.appendNTimes(0xaa, math.cast(usize, layout.payload_size) orelse return error.Overflow);584 try code.appendNTimes(0xaa, math.cast(usize, layout.payload_size) orelse return error.Overflow);
628 } else {585 } else {
629 switch (try generateSymbol(bin_file, src_loc, .{586 switch (try generateSymbol(bin_file, src_loc, Value.fromInterned(un.val), code, debug_output, reloc_info)) {
630 .ty = field_ty,
631 .val = Value.fromInterned(un.val),
632 }, code, debug_output, reloc_info)) {
633 .ok => {},587 .ok => {},
634 .fail => |em| return Result{ .fail = em },588 .fail => |em| return Result{ .fail = em },
635 }589 }
...@@ -640,20 +594,14 @@ pub fn generateSymbol(...@@ -640,20 +594,14 @@ pub fn generateSymbol(
640 }594 }
641 }595 }
642 } else {596 } else {
643 switch (try generateSymbol(bin_file, src_loc, .{597 switch (try generateSymbol(bin_file, src_loc, Value.fromInterned(un.val), code, debug_output, reloc_info)) {
644 .ty = Type.fromInterned(ip.typeOf(un.val)),
645 .val = Value.fromInterned(un.val),
646 }, code, debug_output, reloc_info)) {
647 .ok => {},598 .ok => {},
648 .fail => |em| return Result{ .fail = em },599 .fail => |em| return Result{ .fail = em },
649 }600 }
650 }601 }
651602
652 if (layout.tag_size > 0 and layout.tag_align.compare(.lt, layout.payload_align)) {603 if (layout.tag_size > 0 and layout.tag_align.compare(.lt, layout.payload_align)) {
653 switch (try generateSymbol(bin_file, src_loc, .{604 switch (try generateSymbol(bin_file, src_loc, Value.fromInterned(un.tag), code, debug_output, reloc_info)) {
654 .ty = Type.fromInterned(union_obj.enum_tag_ty),
655 .val = Value.fromInterned(un.tag),
656 }, code, debug_output, reloc_info)) {
657 .ok => {},605 .ok => {},
658 .fail => |em| return Result{ .fail = em },606 .fail => |em| return Result{ .fail = em },
659 }607 }
...@@ -681,10 +629,7 @@ fn lowerParentPtr(...@@ -681,10 +629,7 @@ fn lowerParentPtr(
681 return switch (ptr.addr) {629 return switch (ptr.addr) {
682 .decl => |decl| try lowerDeclRef(bin_file, src_loc, decl, code, debug_output, reloc_info),630 .decl => |decl| try lowerDeclRef(bin_file, src_loc, decl, code, debug_output, reloc_info),
683 .anon_decl => |ad| try lowerAnonDeclRef(bin_file, src_loc, ad, code, debug_output, reloc_info),631 .anon_decl => |ad| try lowerAnonDeclRef(bin_file, src_loc, ad, code, debug_output, reloc_info),
684 .int => |int| try generateSymbol(bin_file, src_loc, .{632 .int => |int| try generateSymbol(bin_file, src_loc, Value.fromInterned(int), code, debug_output, reloc_info),
685 .ty = Type.usize,
686 .val = Value.fromInterned(int),
687 }, code, debug_output, reloc_info),
688 .eu_payload => |eu_payload| try lowerParentPtr(633 .eu_payload => |eu_payload| try lowerParentPtr(
689 bin_file,634 bin_file,
690 src_loc,635 src_loc,
...@@ -829,14 +774,12 @@ fn lowerDeclRef(...@@ -829,14 +774,12 @@ fn lowerDeclRef(
829 const target = namespace.file_scope.mod.resolved_target.result;774 const target = namespace.file_scope.mod.resolved_target.result;
830775
831 const ptr_width = target.ptrBitWidth();776 const ptr_width = target.ptrBitWidth();
832 const is_fn_body = decl.ty.zigTypeTag(zcu) == .Fn;777 const is_fn_body = decl.typeOf(zcu).zigTypeTag(zcu) == .Fn;
833 if (!is_fn_body and !decl.ty.hasRuntimeBits(zcu)) {778 if (!is_fn_body and !decl.typeOf(zcu).hasRuntimeBits(zcu)) {
834 try code.appendNTimes(0xaa, @divExact(ptr_width, 8));779 try code.appendNTimes(0xaa, @divExact(ptr_width, 8));
835 return Result.ok;780 return Result.ok;
836 }781 }
837782
838 try zcu.markDeclAlive(decl);
839
840 const vaddr = try lf.getDeclVAddr(decl_index, .{783 const vaddr = try lf.getDeclVAddr(decl_index, .{
841 .parent_atom_index = reloc_info.parent_atom_index,784 .parent_atom_index = reloc_info.parent_atom_index,
842 .offset = code.items.len,785 .offset = code.items.len,
...@@ -912,11 +855,12 @@ pub const GenResult = union(enum) {...@@ -912,11 +855,12 @@ pub const GenResult = union(enum) {
912fn genDeclRef(855fn genDeclRef(
913 lf: *link.File,856 lf: *link.File,
914 src_loc: Module.SrcLoc,857 src_loc: Module.SrcLoc,
915 tv: TypedValue,858 val: Value,
916 ptr_decl_index: InternPool.DeclIndex,859 ptr_decl_index: InternPool.DeclIndex,
917) CodeGenError!GenResult {860) CodeGenError!GenResult {
918 const zcu = lf.comp.module.?;861 const zcu = lf.comp.module.?;
919 log.debug("genDeclRef: ty = {}, val = {}", .{ tv.ty.fmt(zcu), tv.val.fmtValue(tv.ty, zcu) });862 const ty = val.typeOf(zcu);
863 log.debug("genDeclRef: val = {}", .{val.fmtValue(zcu)});
920864
921 const ptr_decl = zcu.declPtr(ptr_decl_index);865 const ptr_decl = zcu.declPtr(ptr_decl_index);
922 const namespace = zcu.namespacePtr(ptr_decl.src_namespace);866 const namespace = zcu.namespacePtr(ptr_decl.src_namespace);
...@@ -925,14 +869,14 @@ fn genDeclRef(...@@ -925,14 +869,14 @@ fn genDeclRef(
925 const ptr_bits = target.ptrBitWidth();869 const ptr_bits = target.ptrBitWidth();
926 const ptr_bytes: u64 = @divExact(ptr_bits, 8);870 const ptr_bytes: u64 = @divExact(ptr_bits, 8);
927871
928 const decl_index = switch (zcu.intern_pool.indexToKey(try ptr_decl.internValue(zcu))) {872 const decl_index = switch (zcu.intern_pool.indexToKey(ptr_decl.val.toIntern())) {
929 .func => |func| func.owner_decl,873 .func => |func| func.owner_decl,
930 .extern_func => |extern_func| extern_func.decl,874 .extern_func => |extern_func| extern_func.decl,
931 else => ptr_decl_index,875 else => ptr_decl_index,
932 };876 };
933 const decl = zcu.declPtr(decl_index);877 const decl = zcu.declPtr(decl_index);
934878
935 if (!decl.ty.isFnOrHasRuntimeBitsIgnoreComptime(zcu)) {879 if (!decl.typeOf(zcu).isFnOrHasRuntimeBitsIgnoreComptime(zcu)) {
936 const imm: u64 = switch (ptr_bytes) {880 const imm: u64 = switch (ptr_bytes) {
937 1 => 0xaa,881 1 => 0xaa,
938 2 => 0xaaaa,882 2 => 0xaaaa,
...@@ -947,22 +891,20 @@ fn genDeclRef(...@@ -947,22 +891,20 @@ fn genDeclRef(
947 const gpa = comp.gpa;891 const gpa = comp.gpa;
948892
949 // TODO this feels clunky. Perhaps we should check for it in `genTypedValue`?893 // TODO this feels clunky. Perhaps we should check for it in `genTypedValue`?
950 if (tv.ty.castPtrToFn(zcu)) |fn_ty| {894 if (ty.castPtrToFn(zcu)) |fn_ty| {
951 if (zcu.typeToFunc(fn_ty).?.is_generic) {895 if (zcu.typeToFunc(fn_ty).?.is_generic) {
952 return GenResult.mcv(.{ .immediate = fn_ty.abiAlignment(zcu).toByteUnitsOptional().? });896 return GenResult.mcv(.{ .immediate = fn_ty.abiAlignment(zcu).toByteUnitsOptional().? });
953 }897 }
954 } else if (tv.ty.zigTypeTag(zcu) == .Pointer) {898 } else if (ty.zigTypeTag(zcu) == .Pointer) {
955 const elem_ty = tv.ty.elemType2(zcu);899 const elem_ty = ty.elemType2(zcu);
956 if (!elem_ty.hasRuntimeBits(zcu)) {900 if (!elem_ty.hasRuntimeBits(zcu)) {
957 return GenResult.mcv(.{ .immediate = elem_ty.abiAlignment(zcu).toByteUnitsOptional().? });901 return GenResult.mcv(.{ .immediate = elem_ty.abiAlignment(zcu).toByteUnitsOptional().? });
958 }902 }
959 }903 }
960904
961 try zcu.markDeclAlive(decl);
962
963 const decl_namespace = zcu.namespacePtr(decl.src_namespace);905 const decl_namespace = zcu.namespacePtr(decl.src_namespace);
964 const single_threaded = decl_namespace.file_scope.mod.single_threaded;906 const single_threaded = decl_namespace.file_scope.mod.single_threaded;
965 const is_threadlocal = tv.val.isPtrToThreadLocal(zcu) and !single_threaded;907 const is_threadlocal = val.isPtrToThreadLocal(zcu) and !single_threaded;
966 const is_extern = decl.isExtern(zcu);908 const is_extern = decl.isExtern(zcu);
967909
968 if (lf.cast(link.File.Elf)) |elf_file| {910 if (lf.cast(link.File.Elf)) |elf_file| {
...@@ -1027,14 +969,14 @@ fn genDeclRef(...@@ -1027,14 +969,14 @@ fn genDeclRef(
1027fn genUnnamedConst(969fn genUnnamedConst(
1028 lf: *link.File,970 lf: *link.File,
1029 src_loc: Module.SrcLoc,971 src_loc: Module.SrcLoc,
1030 tv: TypedValue,972 val: Value,
1031 owner_decl_index: InternPool.DeclIndex,973 owner_decl_index: InternPool.DeclIndex,
1032) CodeGenError!GenResult {974) CodeGenError!GenResult {
1033 const zcu = lf.comp.module.?;975 const zcu = lf.comp.module.?;
1034 const gpa = lf.comp.gpa;976 const gpa = lf.comp.gpa;
1035 log.debug("genUnnamedConst: ty = {}, val = {}", .{ tv.ty.fmt(zcu), tv.val.fmtValue(tv.ty, zcu) });977 log.debug("genUnnamedConst: val = {}", .{val.fmtValue(zcu)});
1036978
1037 const local_sym_index = lf.lowerUnnamedConst(tv, owner_decl_index) catch |err| {979 const local_sym_index = lf.lowerUnnamedConst(val, owner_decl_index) catch |err| {
1038 return GenResult.fail(gpa, src_loc, "lowering unnamed constant failed: {s}", .{@errorName(err)});980 return GenResult.fail(gpa, src_loc, "lowering unnamed constant failed: {s}", .{@errorName(err)});
1039 };981 };
1040 switch (lf.tag) {982 switch (lf.tag) {
...@@ -1066,18 +1008,15 @@ fn genUnnamedConst(...@@ -1066,18 +1008,15 @@ fn genUnnamedConst(
1066pub fn genTypedValue(1008pub fn genTypedValue(
1067 lf: *link.File,1009 lf: *link.File,
1068 src_loc: Module.SrcLoc,1010 src_loc: Module.SrcLoc,
1069 arg_tv: TypedValue,1011 val: Value,
1070 owner_decl_index: InternPool.DeclIndex,1012 owner_decl_index: InternPool.DeclIndex,
1071) CodeGenError!GenResult {1013) CodeGenError!GenResult {
1072 const zcu = lf.comp.module.?;1014 const zcu = lf.comp.module.?;
1073 const typed_value = arg_tv;1015 const ty = val.typeOf(zcu);
10741016
1075 log.debug("genTypedValue: ty = {}, val = {}", .{1017 log.debug("genTypedValue: val = {}", .{val.fmtValue(zcu)});
1076 typed_value.ty.fmt(zcu),
1077 typed_value.val.fmtValue(typed_value.ty, zcu),
1078 });
10791018
1080 if (typed_value.val.isUndef(zcu))1019 if (val.isUndef(zcu))
1081 return GenResult.mcv(.undef);1020 return GenResult.mcv(.undef);
10821021
1083 const owner_decl = zcu.declPtr(owner_decl_index);1022 const owner_decl = zcu.declPtr(owner_decl_index);
...@@ -1085,85 +1024,92 @@ pub fn genTypedValue(...@@ -1085,85 +1024,92 @@ pub fn genTypedValue(
1085 const target = namespace.file_scope.mod.resolved_target.result;1024 const target = namespace.file_scope.mod.resolved_target.result;
1086 const ptr_bits = target.ptrBitWidth();1025 const ptr_bits = target.ptrBitWidth();
10871026
1088 if (!typed_value.ty.isSlice(zcu)) switch (zcu.intern_pool.indexToKey(typed_value.val.toIntern())) {1027 if (!ty.isSlice(zcu)) switch (zcu.intern_pool.indexToKey(val.toIntern())) {
1089 .ptr => |ptr| switch (ptr.addr) {1028 .ptr => |ptr| switch (ptr.addr) {
1090 .decl => |decl| return genDeclRef(lf, src_loc, typed_value, decl),1029 .decl => |decl| return genDeclRef(lf, src_loc, val, decl),
1091 else => {},1030 else => {},
1092 },1031 },
1093 else => {},1032 else => {},
1094 };1033 };
10951034
1096 switch (typed_value.ty.zigTypeTag(zcu)) {1035 switch (ty.zigTypeTag(zcu)) {
1097 .Void => return GenResult.mcv(.none),1036 .Void => return GenResult.mcv(.none),
1098 .Pointer => switch (typed_value.ty.ptrSize(zcu)) {1037 .Pointer => switch (ty.ptrSize(zcu)) {
1099 .Slice => {},1038 .Slice => {},
1100 else => switch (typed_value.val.toIntern()) {1039 else => switch (val.toIntern()) {
1101 .null_value => {1040 .null_value => {
1102 return GenResult.mcv(.{ .immediate = 0 });1041 return GenResult.mcv(.{ .immediate = 0 });
1103 },1042 },
1104 .none => {},1043 .none => {},
1105 else => switch (zcu.intern_pool.indexToKey(typed_value.val.toIntern())) {1044 else => switch (zcu.intern_pool.indexToKey(val.toIntern())) {
1106 .int => {1045 .int => {
1107 return GenResult.mcv(.{ .immediate = typed_value.val.toUnsignedInt(zcu) });1046 return GenResult.mcv(.{ .immediate = val.toUnsignedInt(zcu) });
1108 },1047 },
1109 else => {},1048 else => {},
1110 },1049 },
1111 },1050 },
1112 },1051 },
1113 .Int => {1052 .Int => {
1114 const info = typed_value.ty.intInfo(zcu);1053 const info = ty.intInfo(zcu);
1115 if (info.bits <= ptr_bits) {1054 if (info.bits <= ptr_bits) {
1116 const unsigned = switch (info.signedness) {1055 const unsigned = switch (info.signedness) {
1117 .signed => @as(u64, @bitCast(typed_value.val.toSignedInt(zcu))),1056 .signed => @as(u64, @bitCast(val.toSignedInt(zcu))),
1118 .unsigned => typed_value.val.toUnsignedInt(zcu),1057 .unsigned => val.toUnsignedInt(zcu),
1119 };1058 };
1120 return GenResult.mcv(.{ .immediate = unsigned });1059 return GenResult.mcv(.{ .immediate = unsigned });
1121 }1060 }
1122 },1061 },
1123 .Bool => {1062 .Bool => {
1124 return GenResult.mcv(.{ .immediate = @intFromBool(typed_value.val.toBool()) });1063 return GenResult.mcv(.{ .immediate = @intFromBool(val.toBool()) });
1125 },1064 },
1126 .Optional => {1065 .Optional => {
1127 if (typed_value.ty.isPtrLikeOptional(zcu)) {1066 if (ty.isPtrLikeOptional(zcu)) {
1128 return genTypedValue(lf, src_loc, .{1067 return genTypedValue(
1129 .ty = typed_value.ty.optionalChild(zcu),1068 lf,
1130 .val = typed_value.val.optionalValue(zcu) orelse return GenResult.mcv(.{ .immediate = 0 }),1069 src_loc,
1131 }, owner_decl_index);1070 val.optionalValue(zcu) orelse return GenResult.mcv(.{ .immediate = 0 }),
1132 } else if (typed_value.ty.abiSize(zcu) == 1) {1071 owner_decl_index,
1133 return GenResult.mcv(.{ .immediate = @intFromBool(!typed_value.val.isNull(zcu)) });1072 );
1073 } else if (ty.abiSize(zcu) == 1) {
1074 return GenResult.mcv(.{ .immediate = @intFromBool(!val.isNull(zcu)) });
1134 }1075 }
1135 },1076 },
1136 .Enum => {1077 .Enum => {
1137 const enum_tag = zcu.intern_pool.indexToKey(typed_value.val.toIntern()).enum_tag;1078 const enum_tag = zcu.intern_pool.indexToKey(val.toIntern()).enum_tag;
1138 const int_tag_ty = zcu.intern_pool.typeOf(enum_tag.int);1079 return genTypedValue(
1139 return genTypedValue(lf, src_loc, .{1080 lf,
1140 .ty = Type.fromInterned(int_tag_ty),1081 src_loc,
1141 .val = Value.fromInterned(enum_tag.int),1082 Value.fromInterned(enum_tag.int),
1142 }, owner_decl_index);1083 owner_decl_index,
1084 );
1143 },1085 },
1144 .ErrorSet => {1086 .ErrorSet => {
1145 const err_name = zcu.intern_pool.indexToKey(typed_value.val.toIntern()).err.name;1087 const err_name = zcu.intern_pool.indexToKey(val.toIntern()).err.name;
1146 const error_index = zcu.global_error_set.getIndex(err_name).?;1088 const error_index = zcu.global_error_set.getIndex(err_name).?;
1147 return GenResult.mcv(.{ .immediate = error_index });1089 return GenResult.mcv(.{ .immediate = error_index });
1148 },1090 },
1149 .ErrorUnion => {1091 .ErrorUnion => {
1150 const err_type = typed_value.ty.errorUnionSet(zcu);1092 const err_type = ty.errorUnionSet(zcu);
1151 const payload_type = typed_value.ty.errorUnionPayload(zcu);1093 const payload_type = ty.errorUnionPayload(zcu);
1152 if (!payload_type.hasRuntimeBitsIgnoreComptime(zcu)) {1094 if (!payload_type.hasRuntimeBitsIgnoreComptime(zcu)) {
1153 // We use the error type directly as the type.1095 // We use the error type directly as the type.
1154 const err_int_ty = try zcu.errorIntType();1096 const err_int_ty = try zcu.errorIntType();
1155 switch (zcu.intern_pool.indexToKey(typed_value.val.toIntern()).error_union.val) {1097 switch (zcu.intern_pool.indexToKey(val.toIntern()).error_union.val) {
1156 .err_name => |err_name| return genTypedValue(lf, src_loc, .{1098 .err_name => |err_name| return genTypedValue(
1157 .ty = err_type,1099 lf,
1158 .val = Value.fromInterned((try zcu.intern(.{ .err = .{1100 src_loc,
1101 Value.fromInterned(try zcu.intern(.{ .err = .{
1159 .ty = err_type.toIntern(),1102 .ty = err_type.toIntern(),
1160 .name = err_name,1103 .name = err_name,
1161 } }))),1104 } })),
1162 }, owner_decl_index),1105 owner_decl_index,
1163 .payload => return genTypedValue(lf, src_loc, .{1106 ),
1164 .ty = err_int_ty,1107 .payload => return genTypedValue(
1165 .val = try zcu.intValue(err_int_ty, 0),1108 lf,
1166 }, owner_decl_index),1109 src_loc,
1110 try zcu.intValue(err_int_ty, 0),
1111 owner_decl_index,
1112 ),
1167 }1113 }
1168 }1114 }
1169 },1115 },
...@@ -1180,7 +1126,7 @@ pub fn genTypedValue(...@@ -1180,7 +1126,7 @@ pub fn genTypedValue(
1180 else => {},1126 else => {},
1181 }1127 }
11821128
1183 return genUnnamedConst(lf, src_loc, typed_value, owner_decl_index);1129 return genUnnamedConst(lf, src_loc, val, owner_decl_index);
1184}1130}
11851131
1186pub fn errUnionPayloadOffset(payload_ty: Type, mod: *Module) u64 {1132pub fn errUnionPayloadOffset(payload_ty: Type, mod: *Module) u64 {
src/codegen/c.zig+37-44
...@@ -9,7 +9,6 @@ const Module = @import("../Module.zig");...@@ -9,7 +9,6 @@ const Module = @import("../Module.zig");
9const Compilation = @import("../Compilation.zig");9const Compilation = @import("../Compilation.zig");
10const Value = @import("../Value.zig");10const Value = @import("../Value.zig");
11const Type = @import("../type.zig").Type;11const Type = @import("../type.zig").Type;
12const TypedValue = @import("../TypedValue.zig");
13const C = link.File.C;12const C = link.File.C;
14const Decl = Module.Decl;13const Decl = Module.Decl;
15const trace = @import("../tracy.zig").trace;14const trace = @import("../tracy.zig").trace;
...@@ -657,7 +656,7 @@ pub const DeclGen = struct {...@@ -657,7 +656,7 @@ pub const DeclGen = struct {
657 assert(decl.has_tv);656 assert(decl.has_tv);
658657
659 // Render an undefined pointer if we have a pointer to a zero-bit or comptime type.658 // Render an undefined pointer if we have a pointer to a zero-bit or comptime type.
660 if (ty.isPtrAtRuntime(mod) and !decl.ty.isFnOrHasRuntimeBits(mod)) {659 if (ty.isPtrAtRuntime(mod) and !decl.typeOf(mod).isFnOrHasRuntimeBits(mod)) {
661 return dg.writeCValue(writer, .{ .undef = ty });660 return dg.writeCValue(writer, .{ .undef = ty });
662 }661 }
663662
...@@ -673,7 +672,7 @@ pub const DeclGen = struct {...@@ -673,7 +672,7 @@ pub const DeclGen = struct {
673 // them). The analysis until now should ensure that the C function672 // them). The analysis until now should ensure that the C function
674 // pointers are compatible. If they are not, then there is a bug673 // pointers are compatible. If they are not, then there is a bug
675 // somewhere and we should let the C compiler tell us about it.674 // somewhere and we should let the C compiler tell us about it.
676 const need_typecast = if (ty.castPtrToFn(mod)) |_| false else !ty.childType(mod).eql(decl.ty, mod);675 const need_typecast = if (ty.castPtrToFn(mod)) |_| false else !ty.childType(mod).eql(decl.typeOf(mod), mod);
677 if (need_typecast) {676 if (need_typecast) {
678 try writer.writeAll("((");677 try writer.writeAll("((");
679 try dg.renderType(writer, ty);678 try dg.renderType(writer, ty);
...@@ -1588,9 +1587,10 @@ pub const DeclGen = struct {...@@ -1588,9 +1587,10 @@ pub const DeclGen = struct {
1588 const ip = &mod.intern_pool;1587 const ip = &mod.intern_pool;
15891588
1590 const fn_decl = mod.declPtr(fn_decl_index);1589 const fn_decl = mod.declPtr(fn_decl_index);
1591 const fn_cty_idx = try dg.typeToIndex(fn_decl.ty, kind);1590 const fn_ty = fn_decl.typeOf(mod);
1591 const fn_cty_idx = try dg.typeToIndex(fn_ty, kind);
15921592
1593 const fn_info = mod.typeToFunc(fn_decl.ty).?;1593 const fn_info = mod.typeToFunc(fn_ty).?;
1594 if (fn_info.cc == .Naked) {1594 if (fn_info.cc == .Naked) {
1595 switch (kind) {1595 switch (kind) {
1596 .forward => try w.writeAll("zig_naked_decl "),1596 .forward => try w.writeAll("zig_naked_decl "),
...@@ -1876,9 +1876,9 @@ pub const DeclGen = struct {...@@ -1876,9 +1876,9 @@ pub const DeclGen = struct {
1876 try renderTypeSuffix(dg.pass, store.*, mod, w, cty_idx, .suffix, .{});1876 try renderTypeSuffix(dg.pass, store.*, mod, w, cty_idx, .suffix, .{});
1877 }1877 }
18781878
1879 fn declIsGlobal(dg: *DeclGen, tv: TypedValue) bool {1879 fn declIsGlobal(dg: *DeclGen, val: Value) bool {
1880 const mod = dg.module;1880 const mod = dg.module;
1881 return switch (mod.intern_pool.indexToKey(tv.val.ip_index)) {1881 return switch (mod.intern_pool.indexToKey(val.ip_index)) {
1882 .variable => |variable| mod.decl_exports.contains(variable.decl),1882 .variable => |variable| mod.decl_exports.contains(variable.decl),
1883 .extern_func => true,1883 .extern_func => true,
1884 .func => |func| mod.decl_exports.contains(func.owner_decl),1884 .func => |func| mod.decl_exports.contains(func.owner_decl),
...@@ -1971,7 +1971,7 @@ pub const DeclGen = struct {...@@ -1971,7 +1971,7 @@ pub const DeclGen = struct {
1971 ) !void {1971 ) !void {
1972 const decl = dg.module.declPtr(decl_index);1972 const decl = dg.module.declPtr(decl_index);
1973 const fwd = dg.fwdDeclWriter();1973 const fwd = dg.fwdDeclWriter();
1974 const is_global = variable.is_extern or dg.declIsGlobal(.{ .ty = decl.ty, .val = decl.val });1974 const is_global = variable.is_extern or dg.declIsGlobal(decl.val);
1975 try fwd.writeAll(if (is_global) "zig_extern " else "static ");1975 try fwd.writeAll(if (is_global) "zig_extern " else "static ");
1976 const maybe_exports = dg.module.decl_exports.get(decl_index);1976 const maybe_exports = dg.module.decl_exports.get(decl_index);
1977 const export_weak_linkage = if (maybe_exports) |exports|1977 const export_weak_linkage = if (maybe_exports) |exports|
...@@ -1982,7 +1982,7 @@ pub const DeclGen = struct {...@@ -1982,7 +1982,7 @@ pub const DeclGen = struct {
1982 if (variable.is_threadlocal) try fwd.writeAll("zig_threadlocal ");1982 if (variable.is_threadlocal) try fwd.writeAll("zig_threadlocal ");
1983 try dg.renderTypeAndName(1983 try dg.renderTypeAndName(
1984 fwd,1984 fwd,
1985 decl.ty,1985 decl.typeOf(dg.module),
1986 .{ .decl = decl_index },1986 .{ .decl = decl_index },
1987 CQualifiers.init(.{ .@"const" = variable.is_const }),1987 CQualifiers.init(.{ .@"const" = variable.is_const }),
1988 decl.alignment,1988 decl.alignment,
...@@ -2009,7 +2009,6 @@ pub const DeclGen = struct {...@@ -2009,7 +2009,6 @@ pub const DeclGen = struct {
2009 fn renderDeclName(dg: *DeclGen, writer: anytype, decl_index: InternPool.DeclIndex, export_index: u32) !void {2009 fn renderDeclName(dg: *DeclGen, writer: anytype, decl_index: InternPool.DeclIndex, export_index: u32) !void {
2010 const mod = dg.module;2010 const mod = dg.module;
2011 const decl = mod.declPtr(decl_index);2011 const decl = mod.declPtr(decl_index);
2012 try mod.markDeclAlive(decl);
20132012
2014 if (mod.decl_exports.get(decl_index)) |exports| {2013 if (mod.decl_exports.get(decl_index)) |exports| {
2015 try writer.print("{ }", .{2014 try writer.print("{ }", .{
...@@ -2656,13 +2655,12 @@ fn genExports(o: *Object) !void {...@@ -2656,13 +2655,12 @@ fn genExports(o: *Object) !void {
2656 .anon, .flush => return,2655 .anon, .flush => return,
2657 };2656 };
2658 const decl = mod.declPtr(decl_index);2657 const decl = mod.declPtr(decl_index);
2659 const tv: TypedValue = .{ .ty = decl.ty, .val = Value.fromInterned((try decl.internValue(mod))) };
2660 const fwd = o.dg.fwdDeclWriter();2658 const fwd = o.dg.fwdDeclWriter();
26612659
2662 const exports = mod.decl_exports.get(decl_index) orelse return;2660 const exports = mod.decl_exports.get(decl_index) orelse return;
2663 if (exports.items.len < 2) return;2661 if (exports.items.len < 2) return;
26642662
2665 const is_variable_const = switch (ip.indexToKey(tv.val.toIntern())) {2663 const is_variable_const = switch (ip.indexToKey(decl.val.toIntern())) {
2666 .func => return for (exports.items[1..], 1..) |@"export", i| {2664 .func => return for (exports.items[1..], 1..) |@"export", i| {
2667 try fwd.writeAll("zig_extern ");2665 try fwd.writeAll("zig_extern ");
2668 if (@"export".opts.linkage == .weak) try fwd.writeAll("zig_weak_linkage_fn ");2666 if (@"export".opts.linkage == .weak) try fwd.writeAll("zig_weak_linkage_fn ");
...@@ -2687,7 +2685,7 @@ fn genExports(o: *Object) !void {...@@ -2687,7 +2685,7 @@ fn genExports(o: *Object) !void {
2687 const export_name = ip.stringToSlice(@"export".opts.name);2685 const export_name = ip.stringToSlice(@"export".opts.name);
2688 try o.dg.renderTypeAndName(2686 try o.dg.renderTypeAndName(
2689 fwd,2687 fwd,
2690 decl.ty,2688 decl.typeOf(mod),
2691 .{ .identifier = export_name },2689 .{ .identifier = export_name },
2692 CQualifiers.init(.{ .@"const" = is_variable_const }),2690 CQualifiers.init(.{ .@"const" = is_variable_const }),
2693 decl.alignment,2691 decl.alignment,
...@@ -2769,7 +2767,7 @@ pub fn genLazyFn(o: *Object, lazy_fn: LazyFnMap.Entry) !void {...@@ -2769,7 +2767,7 @@ pub fn genLazyFn(o: *Object, lazy_fn: LazyFnMap.Entry) !void {
2769 },2767 },
2770 .never_tail, .never_inline => |fn_decl_index| {2768 .never_tail, .never_inline => |fn_decl_index| {
2771 const fn_decl = mod.declPtr(fn_decl_index);2769 const fn_decl = mod.declPtr(fn_decl_index);
2772 const fn_cty = try o.dg.typeToCType(fn_decl.ty, .complete);2770 const fn_cty = try o.dg.typeToCType(fn_decl.typeOf(mod), .complete);
2773 const fn_info = fn_cty.cast(CType.Payload.Function).?.data;2771 const fn_info = fn_cty.cast(CType.Payload.Function).?.data;
27742772
2775 const fwd_decl_writer = o.dg.fwdDeclWriter();2773 const fwd_decl_writer = o.dg.fwdDeclWriter();
...@@ -2805,15 +2803,11 @@ pub fn genFunc(f: *Function) !void {...@@ -2805,15 +2803,11 @@ pub fn genFunc(f: *Function) !void {
2805 const gpa = o.dg.gpa;2803 const gpa = o.dg.gpa;
2806 const decl_index = o.dg.pass.decl;2804 const decl_index = o.dg.pass.decl;
2807 const decl = mod.declPtr(decl_index);2805 const decl = mod.declPtr(decl_index);
2808 const tv: TypedValue = .{
2809 .ty = decl.ty,
2810 .val = decl.val,
2811 };
28122806
2813 o.code_header = std.ArrayList(u8).init(gpa);2807 o.code_header = std.ArrayList(u8).init(gpa);
2814 defer o.code_header.deinit();2808 defer o.code_header.deinit();
28152809
2816 const is_global = o.dg.declIsGlobal(tv);2810 const is_global = o.dg.declIsGlobal(decl.val);
2817 const fwd_decl_writer = o.dg.fwdDeclWriter();2811 const fwd_decl_writer = o.dg.fwdDeclWriter();
2818 try fwd_decl_writer.writeAll(if (is_global) "zig_extern " else "static ");2812 try fwd_decl_writer.writeAll(if (is_global) "zig_extern " else "static ");
28192813
...@@ -2893,22 +2887,23 @@ pub fn genDecl(o: *Object) !void {...@@ -2893,22 +2887,23 @@ pub fn genDecl(o: *Object) !void {
2893 const mod = o.dg.module;2887 const mod = o.dg.module;
2894 const decl_index = o.dg.pass.decl;2888 const decl_index = o.dg.pass.decl;
2895 const decl = mod.declPtr(decl_index);2889 const decl = mod.declPtr(decl_index);
2896 const tv: TypedValue = .{ .ty = decl.ty, .val = Value.fromInterned((try decl.internValue(mod))) };2890 const decl_val = decl.val;
2891 const decl_ty = decl_val.typeOf(mod);
28972892
2898 if (!tv.ty.isFnOrHasRuntimeBitsIgnoreComptime(mod)) return;2893 if (!decl_ty.isFnOrHasRuntimeBitsIgnoreComptime(mod)) return;
2899 if (tv.val.getExternFunc(mod)) |_| {2894 if (decl_val.getExternFunc(mod)) |_| {
2900 const fwd_decl_writer = o.dg.fwdDeclWriter();2895 const fwd_decl_writer = o.dg.fwdDeclWriter();
2901 try fwd_decl_writer.writeAll("zig_extern ");2896 try fwd_decl_writer.writeAll("zig_extern ");
2902 try o.dg.renderFunctionSignature(fwd_decl_writer, decl_index, .forward, .{ .export_index = 0 });2897 try o.dg.renderFunctionSignature(fwd_decl_writer, decl_index, .forward, .{ .export_index = 0 });
2903 try fwd_decl_writer.writeAll(";\n");2898 try fwd_decl_writer.writeAll(";\n");
2904 try genExports(o);2899 try genExports(o);
2905 } else if (tv.val.getVariable(mod)) |variable| {2900 } else if (decl_val.getVariable(mod)) |variable| {
2906 try o.dg.renderFwdDecl(decl_index, variable, .final);2901 try o.dg.renderFwdDecl(decl_index, variable, .final);
2907 try genExports(o);2902 try genExports(o);
29082903
2909 if (variable.is_extern) return;2904 if (variable.is_extern) return;
29102905
2911 const is_global = variable.is_extern or o.dg.declIsGlobal(tv);2906 const is_global = variable.is_extern or o.dg.declIsGlobal(decl_val);
2912 const w = o.writer();2907 const w = o.writer();
2913 if (!is_global) try w.writeAll("static ");2908 if (!is_global) try w.writeAll("static ");
2914 if (variable.is_weak_linkage) try w.writeAll("zig_weak_linkage ");2909 if (variable.is_weak_linkage) try w.writeAll("zig_weak_linkage ");
...@@ -2916,22 +2911,22 @@ pub fn genDecl(o: *Object) !void {...@@ -2916,22 +2911,22 @@ pub fn genDecl(o: *Object) !void {
2916 if (mod.intern_pool.stringToSliceUnwrap(decl.@"linksection")) |s|2911 if (mod.intern_pool.stringToSliceUnwrap(decl.@"linksection")) |s|
2917 try w.print("zig_linksection(\"{s}\", ", .{s});2912 try w.print("zig_linksection(\"{s}\", ", .{s});
2918 const decl_c_value = .{ .decl = decl_index };2913 const decl_c_value = .{ .decl = decl_index };
2919 try o.dg.renderTypeAndName(w, tv.ty, decl_c_value, .{}, decl.alignment, .complete);2914 try o.dg.renderTypeAndName(w, decl_ty, decl_c_value, .{}, decl.alignment, .complete);
2920 if (decl.@"linksection" != .none) try w.writeAll(", read, write)");2915 if (decl.@"linksection" != .none) try w.writeAll(", read, write)");
2921 try w.writeAll(" = ");2916 try w.writeAll(" = ");
2922 try o.dg.renderValue(w, tv.ty, Value.fromInterned(variable.init), .StaticInitializer);2917 try o.dg.renderValue(w, decl_ty, Value.fromInterned(variable.init), .StaticInitializer);
2923 try w.writeByte(';');2918 try w.writeByte(';');
2924 try o.indent_writer.insertNewline();2919 try o.indent_writer.insertNewline();
2925 } else {2920 } else {
2926 const is_global = o.dg.module.decl_exports.contains(decl_index);2921 const is_global = o.dg.module.decl_exports.contains(decl_index);
2927 const decl_c_value = .{ .decl = decl_index };2922 const decl_c_value = .{ .decl = decl_index };
2928 try genDeclValue(o, tv, is_global, decl_c_value, decl.alignment, decl.@"linksection");2923 try genDeclValue(o, decl_val, is_global, decl_c_value, decl.alignment, decl.@"linksection");
2929 }2924 }
2930}2925}
29312926
2932pub fn genDeclValue(2927pub fn genDeclValue(
2933 o: *Object,2928 o: *Object,
2934 tv: TypedValue,2929 val: Value,
2935 is_global: bool,2930 is_global: bool,
2936 decl_c_value: CValue,2931 decl_c_value: CValue,
2937 alignment: Alignment,2932 alignment: Alignment,
...@@ -2940,8 +2935,10 @@ pub fn genDeclValue(...@@ -2940,8 +2935,10 @@ pub fn genDeclValue(
2940 const mod = o.dg.module;2935 const mod = o.dg.module;
2941 const fwd_decl_writer = o.dg.fwdDeclWriter();2936 const fwd_decl_writer = o.dg.fwdDeclWriter();
29422937
2938 const ty = val.typeOf(mod);
2939
2943 try fwd_decl_writer.writeAll(if (is_global) "zig_extern " else "static ");2940 try fwd_decl_writer.writeAll(if (is_global) "zig_extern " else "static ");
2944 try o.dg.renderTypeAndName(fwd_decl_writer, tv.ty, decl_c_value, Const, alignment, .complete);2941 try o.dg.renderTypeAndName(fwd_decl_writer, ty, decl_c_value, Const, alignment, .complete);
2945 switch (o.dg.pass) {2942 switch (o.dg.pass) {
2946 .decl => |decl_index| {2943 .decl => |decl_index| {
2947 if (mod.decl_exports.get(decl_index)) |exports| {2944 if (mod.decl_exports.get(decl_index)) |exports| {
...@@ -2964,10 +2961,10 @@ pub fn genDeclValue(...@@ -2964,10 +2961,10 @@ pub fn genDeclValue(
29642961
2965 if (mod.intern_pool.stringToSliceUnwrap(link_section)) |s|2962 if (mod.intern_pool.stringToSliceUnwrap(link_section)) |s|
2966 try w.print("zig_linksection(\"{s}\", ", .{s});2963 try w.print("zig_linksection(\"{s}\", ", .{s});
2967 try o.dg.renderTypeAndName(w, tv.ty, decl_c_value, Const, alignment, .complete);2964 try o.dg.renderTypeAndName(w, ty, decl_c_value, Const, alignment, .complete);
2968 if (link_section != .none) try w.writeAll(", read)");2965 if (link_section != .none) try w.writeAll(", read)");
2969 try w.writeAll(" = ");2966 try w.writeAll(" = ");
2970 try o.dg.renderValue(w, tv.ty, tv.val, .StaticInitializer);2967 try o.dg.renderValue(w, ty, val, .StaticInitializer);
2971 try w.writeAll(";\n");2968 try w.writeAll(";\n");
2972}2969}
29732970
...@@ -2978,14 +2975,10 @@ pub fn genHeader(dg: *DeclGen) error{ AnalysisFail, OutOfMemory }!void {...@@ -2978,14 +2975,10 @@ pub fn genHeader(dg: *DeclGen) error{ AnalysisFail, OutOfMemory }!void {
2978 const mod = dg.module;2975 const mod = dg.module;
2979 const decl_index = dg.pass.decl;2976 const decl_index = dg.pass.decl;
2980 const decl = mod.declPtr(decl_index);2977 const decl = mod.declPtr(decl_index);
2981 const tv: TypedValue = .{
2982 .ty = decl.ty,
2983 .val = decl.val,
2984 };
2985 const writer = dg.fwdDeclWriter();2978 const writer = dg.fwdDeclWriter();
29862979
2987 switch (tv.ty.zigTypeTag(mod)) {2980 switch (decl.val.typeOf(mod).zigTypeTag(mod)) {
2988 .Fn => if (dg.declIsGlobal(tv)) {2981 .Fn => if (dg.declIsGlobal(decl.val)) {
2989 try writer.writeAll("zig_extern ");2982 try writer.writeAll("zig_extern ");
2990 try dg.renderFunctionSignature(writer, dg.pass.decl, .complete, .{ .export_index = 0 });2983 try dg.renderFunctionSignature(writer, dg.pass.decl, .complete, .{ .export_index = 0 });
2991 try dg.fwd_decl.appendSlice(";\n");2984 try dg.fwd_decl.appendSlice(";\n");
...@@ -5304,25 +5297,25 @@ fn airIsNull(...@@ -5304,25 +5297,25 @@ fn airIsNull(
5304 const err_int_ty = try mod.errorIntType();5297 const err_int_ty = try mod.errorIntType();
53055298
5306 const rhs = if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod))5299 const rhs = if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod))
5307 TypedValue{ .ty = Type.bool, .val = Value.true }5300 Value.true
5308 else if (optional_ty.isPtrLikeOptional(mod))5301 else if (optional_ty.isPtrLikeOptional(mod))
5309 // operand is a regular pointer, test `operand !=/== NULL`5302 // operand is a regular pointer, test `operand !=/== NULL`
5310 TypedValue{ .ty = optional_ty, .val = try mod.getCoerced(Value.null, optional_ty) }5303 try mod.getCoerced(Value.null, optional_ty)
5311 else if (payload_ty.zigTypeTag(mod) == .ErrorSet)5304 else if (payload_ty.zigTypeTag(mod) == .ErrorSet)
5312 TypedValue{ .ty = err_int_ty, .val = try mod.intValue(err_int_ty, 0) }5305 try mod.intValue(err_int_ty, 0)
5313 else if (payload_ty.isSlice(mod) and optional_ty.optionalReprIsPayload(mod)) rhs: {5306 else if (payload_ty.isSlice(mod) and optional_ty.optionalReprIsPayload(mod)) rhs: {
5314 try writer.writeAll(".ptr");5307 try writer.writeAll(".ptr");
5315 const slice_ptr_ty = payload_ty.slicePtrFieldType(mod);5308 const slice_ptr_ty = payload_ty.slicePtrFieldType(mod);
5316 const opt_slice_ptr_ty = try mod.optionalType(slice_ptr_ty.toIntern());5309 const opt_slice_ptr_ty = try mod.optionalType(slice_ptr_ty.toIntern());
5317 break :rhs TypedValue{ .ty = opt_slice_ptr_ty, .val = try mod.nullValue(opt_slice_ptr_ty) };5310 break :rhs try mod.nullValue(opt_slice_ptr_ty);
5318 } else rhs: {5311 } else rhs: {
5319 try writer.writeAll(".is_null");5312 try writer.writeAll(".is_null");
5320 break :rhs TypedValue{ .ty = Type.bool, .val = Value.true };5313 break :rhs Value.true;
5321 };5314 };
5322 try writer.writeByte(' ');5315 try writer.writeByte(' ');
5323 try writer.writeAll(operator);5316 try writer.writeAll(operator);
5324 try writer.writeByte(' ');5317 try writer.writeByte(' ');
5325 try f.object.dg.renderValue(writer, rhs.ty, rhs.val, .Other);5318 try f.object.dg.renderValue(writer, rhs.typeOf(mod), rhs, .Other);
5326 try writer.writeAll(";\n");5319 try writer.writeAll(";\n");
5327 return local;5320 return local;
5328}5321}
...@@ -7392,7 +7385,7 @@ fn airCVaStart(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -7392,7 +7385,7 @@ fn airCVaStart(f: *Function, inst: Air.Inst.Index) !CValue {
7392 const inst_ty = f.typeOfIndex(inst);7385 const inst_ty = f.typeOfIndex(inst);
7393 const decl_index = f.object.dg.pass.decl;7386 const decl_index = f.object.dg.pass.decl;
7394 const decl = mod.declPtr(decl_index);7387 const decl = mod.declPtr(decl_index);
7395 const fn_cty = try f.typeToCType(decl.ty, .complete);7388 const fn_cty = try f.typeToCType(decl.typeOf(mod), .complete);
7396 const param_len = fn_cty.castTag(.varargs_function).?.data.param_types.len;7389 const param_len = fn_cty.castTag(.varargs_function).?.data.param_types.len;
73977390
7398 const writer = f.object.writer();7391 const writer = f.object.writer();
src/codegen/llvm.zig+27-40
...@@ -18,7 +18,6 @@ const Module = @import("../Module.zig");...@@ -18,7 +18,6 @@ const Module = @import("../Module.zig");
18const Zcu = Module;18const Zcu = Module;
19const InternPool = @import("../InternPool.zig");19const InternPool = @import("../InternPool.zig");
20const Package = @import("../Package.zig");20const Package = @import("../Package.zig");
21const TypedValue = @import("../TypedValue.zig");
22const Air = @import("../Air.zig");21const Air = @import("../Air.zig");
23const Liveness = @import("../Liveness.zig");22const Liveness = @import("../Liveness.zig");
24const Value = @import("../Value.zig");23const Value = @import("../Value.zig");
...@@ -1384,7 +1383,7 @@ pub const Object = struct {...@@ -1384,7 +1383,7 @@ pub const Object = struct {
1384 const decl = zcu.declPtr(decl_index);1383 const decl = zcu.declPtr(decl_index);
1385 const namespace = zcu.namespacePtr(decl.src_namespace);1384 const namespace = zcu.namespacePtr(decl.src_namespace);
1386 const owner_mod = namespace.file_scope.mod;1385 const owner_mod = namespace.file_scope.mod;
1387 const fn_info = zcu.typeToFunc(decl.ty).?;1386 const fn_info = zcu.typeToFunc(decl.typeOf(zcu)).?;
1388 const target = zcu.getTarget();1387 const target = zcu.getTarget();
1389 const ip = &zcu.intern_pool;1388 const ip = &zcu.intern_pool;
13901389
...@@ -1659,7 +1658,7 @@ pub const Object = struct {...@@ -1659,7 +1658,7 @@ pub const Object = struct {
1659 const line_number = decl.src_line + 1;1658 const line_number = decl.src_line + 1;
1660 const is_internal_linkage = decl.val.getExternFunc(zcu) == null and1659 const is_internal_linkage = decl.val.getExternFunc(zcu) == null and
1661 !zcu.decl_exports.contains(decl_index);1660 !zcu.decl_exports.contains(decl_index);
1662 const debug_decl_type = try o.lowerDebugType(decl.ty);1661 const debug_decl_type = try o.lowerDebugType(decl.typeOf(zcu));
16631662
1664 const subprogram = try o.builder.debugSubprogram(1663 const subprogram = try o.builder.debugSubprogram(
1665 file,1664 file,
...@@ -1762,7 +1761,7 @@ pub const Object = struct {...@@ -1762,7 +1761,7 @@ pub const Object = struct {
1762 const decl_name = decl_name: {1761 const decl_name = decl_name: {
1763 const decl_name = mod.intern_pool.stringToSlice(decl.name);1762 const decl_name = mod.intern_pool.stringToSlice(decl.name);
17641763
1765 if (mod.getTarget().isWasm() and try decl.isFunction(mod)) {1764 if (mod.getTarget().isWasm() and decl.val.typeOf(mod).zigTypeTag(mod) == .Fn) {
1766 if (mod.intern_pool.stringToSliceUnwrap(decl.getOwnedExternFunc(mod).?.lib_name)) |lib_name| {1765 if (mod.intern_pool.stringToSliceUnwrap(decl.getOwnedExternFunc(mod).?.lib_name)) |lib_name| {
1767 if (!std.mem.eql(u8, lib_name, "c")) {1766 if (!std.mem.eql(u8, lib_name, "c")) {
1768 break :decl_name try self.builder.strtabStringFmt("{s}|{s}", .{ decl_name, lib_name });1767 break :decl_name try self.builder.strtabStringFmt("{s}|{s}", .{ decl_name, lib_name });
...@@ -2881,7 +2880,7 @@ pub const Object = struct {...@@ -2881,7 +2880,7 @@ pub const Object = struct {
2881 const decl = zcu.declPtr(decl_index);2880 const decl = zcu.declPtr(decl_index);
2882 const namespace = zcu.namespacePtr(decl.src_namespace);2881 const namespace = zcu.namespacePtr(decl.src_namespace);
2883 const owner_mod = namespace.file_scope.mod;2882 const owner_mod = namespace.file_scope.mod;
2884 const zig_fn_type = decl.ty;2883 const zig_fn_type = decl.typeOf(zcu);
2885 const gop = try o.decl_map.getOrPut(gpa, decl_index);2884 const gop = try o.decl_map.getOrPut(gpa, decl_index);
2886 if (gop.found_existing) return gop.value_ptr.ptr(&o.builder).kind.function;2885 if (gop.found_existing) return gop.value_ptr.ptr(&o.builder).kind.function;
28872886
...@@ -3112,7 +3111,7 @@ pub const Object = struct {...@@ -3112,7 +3111,7 @@ pub const Object = struct {
3112 try o.builder.strtabString(mod.intern_pool.stringToSlice(3111 try o.builder.strtabString(mod.intern_pool.stringToSlice(
3113 if (is_extern) decl.name else try decl.fullyQualifiedName(mod),3112 if (is_extern) decl.name else try decl.fullyQualifiedName(mod),
3114 )),3113 )),
3115 try o.lowerType(decl.ty),3114 try o.lowerType(decl.typeOf(mod)),
3116 toLlvmGlobalAddressSpace(decl.@"addrspace", mod.getTarget()),3115 toLlvmGlobalAddressSpace(decl.@"addrspace", mod.getTarget()),
3117 );3116 );
3118 gop.value_ptr.* = variable_index.ptrConst(&o.builder).global;3117 gop.value_ptr.* = variable_index.ptrConst(&o.builder).global;
...@@ -3722,15 +3721,11 @@ pub const Object = struct {...@@ -3722,15 +3721,11 @@ pub const Object = struct {
3722 => unreachable, // non-runtime values3721 => unreachable, // non-runtime values
3723 .extern_func => |extern_func| {3722 .extern_func => |extern_func| {
3724 const fn_decl_index = extern_func.decl;3723 const fn_decl_index = extern_func.decl;
3725 const fn_decl = mod.declPtr(fn_decl_index);
3726 try mod.markDeclAlive(fn_decl);
3727 const function_index = try o.resolveLlvmFunction(fn_decl_index);3724 const function_index = try o.resolveLlvmFunction(fn_decl_index);
3728 return function_index.ptrConst(&o.builder).global.toConst();3725 return function_index.ptrConst(&o.builder).global.toConst();
3729 },3726 },
3730 .func => |func| {3727 .func => |func| {
3731 const fn_decl_index = func.owner_decl;3728 const fn_decl_index = func.owner_decl;
3732 const fn_decl = mod.declPtr(fn_decl_index);
3733 try mod.markDeclAlive(fn_decl);
3734 const function_index = try o.resolveLlvmFunction(fn_decl_index);3729 const function_index = try o.resolveLlvmFunction(fn_decl_index);
3735 return function_index.ptrConst(&o.builder).global.toConst();3730 return function_index.ptrConst(&o.builder).global.toConst();
3736 },3731 },
...@@ -4262,8 +4257,7 @@ pub const Object = struct {...@@ -4262,8 +4257,7 @@ pub const Object = struct {
4262 fn lowerParentPtrDecl(o: *Object, decl_index: InternPool.DeclIndex) Allocator.Error!Builder.Constant {4257 fn lowerParentPtrDecl(o: *Object, decl_index: InternPool.DeclIndex) Allocator.Error!Builder.Constant {
4263 const mod = o.module;4258 const mod = o.module;
4264 const decl = mod.declPtr(decl_index);4259 const decl = mod.declPtr(decl_index);
4265 try mod.markDeclAlive(decl);4260 const ptr_ty = try mod.singleMutPtrType(decl.typeOf(mod));
4266 const ptr_ty = try mod.singleMutPtrType(decl.ty);
4267 return o.lowerDeclRefValue(ptr_ty, decl_index);4261 return o.lowerDeclRefValue(ptr_ty, decl_index);
4268 }4262 }
42694263
...@@ -4450,11 +4444,10 @@ pub const Object = struct {...@@ -4450,11 +4444,10 @@ pub const Object = struct {
4450 }4444 }
4451 }4445 }
44524446
4453 const is_fn_body = decl.ty.zigTypeTag(mod) == .Fn;4447 const decl_ty = decl.typeOf(mod);
4454 if ((!is_fn_body and !decl.ty.hasRuntimeBits(mod)) or4448 const is_fn_body = decl_ty.zigTypeTag(mod) == .Fn;
4455 (is_fn_body and mod.typeToFunc(decl.ty).?.is_generic)) return o.lowerPtrToVoid(ty);4449 if ((!is_fn_body and !decl_ty.hasRuntimeBits(mod)) or
44564450 (is_fn_body and mod.typeToFunc(decl_ty).?.is_generic)) return o.lowerPtrToVoid(ty);
4457 try mod.markDeclAlive(decl);
44584451
4459 const llvm_global = if (is_fn_body)4452 const llvm_global = if (is_fn_body)
4460 (try o.resolveLlvmFunction(decl_index)).ptrConst(&o.builder).global4453 (try o.resolveLlvmFunction(decl_index)).ptrConst(&o.builder).global
...@@ -4740,7 +4733,7 @@ pub const DeclGen = struct {...@@ -4740,7 +4733,7 @@ pub const DeclGen = struct {
4740 debug_file, // File4733 debug_file, // File
4741 debug_file, // Scope4734 debug_file, // Scope
4742 line_number,4735 line_number,
4743 try o.lowerDebugType(decl.ty),4736 try o.lowerDebugType(decl.typeOf(zcu)),
4744 variable_index,4737 variable_index,
4745 .{ .local = is_internal_linkage },4738 .{ .local = is_internal_linkage },
4746 );4739 );
...@@ -4829,19 +4822,17 @@ pub const FuncGen = struct {...@@ -4829,19 +4822,17 @@ pub const FuncGen = struct {
48294822
4830 const o = self.dg.object;4823 const o = self.dg.object;
4831 const mod = o.module;4824 const mod = o.module;
4832 const llvm_val = try self.resolveValue(.{4825 const llvm_val = try self.resolveValue((try self.air.value(inst, mod)).?);
4833 .ty = self.typeOf(inst),
4834 .val = (try self.air.value(inst, mod)).?,
4835 });
4836 gop.value_ptr.* = llvm_val.toValue();4826 gop.value_ptr.* = llvm_val.toValue();
4837 return llvm_val.toValue();4827 return llvm_val.toValue();
4838 }4828 }
48394829
4840 fn resolveValue(self: *FuncGen, tv: TypedValue) Error!Builder.Constant {4830 fn resolveValue(self: *FuncGen, val: Value) Error!Builder.Constant {
4841 const o = self.dg.object;4831 const o = self.dg.object;
4842 const mod = o.module;4832 const mod = o.module;
4843 const llvm_val = try o.lowerValue(tv.val.toIntern());4833 const ty = val.typeOf(mod);
4844 if (!isByRef(tv.ty, mod)) return llvm_val;4834 const llvm_val = try o.lowerValue(val.toIntern());
4835 if (!isByRef(ty, mod)) return llvm_val;
48454836
4846 // We have an LLVM value but we need to create a global constant and4837 // We have an LLVM value but we need to create a global constant and
4847 // set the value as its initializer, and then return a pointer to the global.4838 // set the value as its initializer, and then return a pointer to the global.
...@@ -4855,7 +4846,7 @@ pub const FuncGen = struct {...@@ -4855,7 +4846,7 @@ pub const FuncGen = struct {
4855 variable_index.setLinkage(.private, &o.builder);4846 variable_index.setLinkage(.private, &o.builder);
4856 variable_index.setMutability(.constant, &o.builder);4847 variable_index.setMutability(.constant, &o.builder);
4857 variable_index.setUnnamedAddr(.unnamed_addr, &o.builder);4848 variable_index.setUnnamedAddr(.unnamed_addr, &o.builder);
4858 variable_index.setAlignment(tv.ty.abiAlignment(mod).toLlvm(), &o.builder);4849 variable_index.setAlignment(ty.abiAlignment(mod).toLlvm(), &o.builder);
4859 return o.builder.convConst(4850 return o.builder.convConst(
4860 .unneeded,4851 .unneeded,
4861 variable_index.toConst(&o.builder),4852 variable_index.toConst(&o.builder),
...@@ -4867,11 +4858,10 @@ pub const FuncGen = struct {...@@ -4867,11 +4858,10 @@ pub const FuncGen = struct {
4867 const o = self.dg.object;4858 const o = self.dg.object;
4868 const mod = o.module;4859 const mod = o.module;
4869 if (o.null_opt_usize == .no_init) {4860 if (o.null_opt_usize == .no_init) {
4870 const ty = try mod.intern(.{ .opt_type = .usize_type });4861 o.null_opt_usize = try self.resolveValue(Value.fromInterned(try mod.intern(.{ .opt = .{
4871 o.null_opt_usize = try self.resolveValue(.{4862 .ty = try mod.intern(.{ .opt_type = .usize_type }),
4872 .ty = Type.fromInterned(ty),4863 .val = .none,
4873 .val = Value.fromInterned((try mod.intern(.{ .opt = .{ .ty = ty, .val = .none } }))),4864 } })));
4874 });
4875 }4865 }
4876 return o.null_opt_usize;4866 return o.null_opt_usize;
4877 }4867 }
...@@ -5530,8 +5520,8 @@ pub const FuncGen = struct {...@@ -5530,8 +5520,8 @@ pub const FuncGen = struct {
5530 const mod = o.module;5520 const mod = o.module;
5531 const msg_decl_index = mod.panic_messages[@intFromEnum(panic_id)].unwrap().?;5521 const msg_decl_index = mod.panic_messages[@intFromEnum(panic_id)].unwrap().?;
5532 const msg_decl = mod.declPtr(msg_decl_index);5522 const msg_decl = mod.declPtr(msg_decl_index);
5533 const msg_len = msg_decl.ty.childType(mod).arrayLen(mod);5523 const msg_len = msg_decl.typeOf(mod).childType(mod).arrayLen(mod);
5534 const msg_ptr = try o.lowerValue(try msg_decl.internValue(mod));5524 const msg_ptr = try o.lowerValue(msg_decl.val.toIntern());
5535 const null_opt_addr_global = try fg.resolveNullOptUsize();5525 const null_opt_addr_global = try fg.resolveNullOptUsize();
5536 const target = mod.getTarget();5526 const target = mod.getTarget();
5537 const llvm_usize = try o.lowerType(Type.usize);5527 const llvm_usize = try o.lowerType(Type.usize);
...@@ -5544,7 +5534,7 @@ pub const FuncGen = struct {...@@ -5544,7 +5534,7 @@ pub const FuncGen = struct {
5544 // )5534 // )
5545 const panic_func = mod.funcInfo(mod.panic_func_index);5535 const panic_func = mod.funcInfo(mod.panic_func_index);
5546 const panic_decl = mod.declPtr(panic_func.owner_decl);5536 const panic_decl = mod.declPtr(panic_func.owner_decl);
5547 const fn_info = mod.typeToFunc(panic_decl.ty).?;5537 const fn_info = mod.typeToFunc(panic_decl.typeOf(mod)).?;
5548 const panic_global = try o.resolveLlvmFunction(panic_func.owner_decl);5538 const panic_global = try o.resolveLlvmFunction(panic_func.owner_decl);
5549 _ = try fg.wip.call(5539 _ = try fg.wip.call(
5550 .normal,5540 .normal,
...@@ -5612,7 +5602,7 @@ pub const FuncGen = struct {...@@ -5612,7 +5602,7 @@ pub const FuncGen = struct {
5612 _ = try self.wip.retVoid();5602 _ = try self.wip.retVoid();
5613 return .none;5603 return .none;
5614 }5604 }
5615 const fn_info = mod.typeToFunc(self.dg.decl.ty).?;5605 const fn_info = mod.typeToFunc(self.dg.decl.typeOf(mod)).?;
5616 if (!ret_ty.hasRuntimeBitsIgnoreComptime(mod)) {5606 if (!ret_ty.hasRuntimeBitsIgnoreComptime(mod)) {
5617 if (Type.fromInterned(fn_info.return_type).isError(mod)) {5607 if (Type.fromInterned(fn_info.return_type).isError(mod)) {
5618 // Functions with an empty error set are emitted with an error code5608 // Functions with an empty error set are emitted with an error code
...@@ -5674,7 +5664,7 @@ pub const FuncGen = struct {...@@ -5674,7 +5664,7 @@ pub const FuncGen = struct {
5674 const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op;5664 const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
5675 const ptr_ty = self.typeOf(un_op);5665 const ptr_ty = self.typeOf(un_op);
5676 const ret_ty = ptr_ty.childType(mod);5666 const ret_ty = ptr_ty.childType(mod);
5677 const fn_info = mod.typeToFunc(self.dg.decl.ty).?;5667 const fn_info = mod.typeToFunc(self.dg.decl.typeOf(mod)).?;
5678 if (!ret_ty.hasRuntimeBitsIgnoreComptime(mod)) {5668 if (!ret_ty.hasRuntimeBitsIgnoreComptime(mod)) {
5679 if (Type.fromInterned(fn_info.return_type).isError(mod)) {5669 if (Type.fromInterned(fn_info.return_type).isError(mod)) {
5680 // Functions with an empty error set are emitted with an error code5670 // Functions with an empty error set are emitted with an error code
...@@ -10067,10 +10057,7 @@ pub const FuncGen = struct {...@@ -10067,10 +10057,7 @@ pub const FuncGen = struct {
10067 const elem_ptr = try self.wip.gep(.inbounds, llvm_result_ty, alloca_inst, &.{10057 const elem_ptr = try self.wip.gep(.inbounds, llvm_result_ty, alloca_inst, &.{
10068 usize_zero, try o.builder.intValue(llvm_usize, array_info.len),10058 usize_zero, try o.builder.intValue(llvm_usize, array_info.len),
10069 }, "");10059 }, "");
10070 const llvm_elem = try self.resolveValue(.{10060 const llvm_elem = try self.resolveValue(sent_val);
10071 .ty = array_info.elem_type,
10072 .val = sent_val,
10073 });
10074 try self.store(elem_ptr, elem_ptr_ty, llvm_elem.toValue(), .none);10061 try self.store(elem_ptr, elem_ptr_ty, llvm_elem.toValue(), .none);
10075 }10062 }
1007610063
src/codegen/spirv.zig+11-12
...@@ -255,7 +255,6 @@ pub const Object = struct {...@@ -255,7 +255,6 @@ pub const Object = struct {
255 pub fn resolveDecl(self: *Object, mod: *Module, decl_index: InternPool.DeclIndex) !SpvModule.Decl.Index {255 pub fn resolveDecl(self: *Object, mod: *Module, decl_index: InternPool.DeclIndex) !SpvModule.Decl.Index {
256 const decl = mod.declPtr(decl_index);256 const decl = mod.declPtr(decl_index);
257 assert(decl.has_tv); // TODO: Do we need to handle a situation where this is false?257 assert(decl.has_tv); // TODO: Do we need to handle a situation where this is false?
258 try mod.markDeclAlive(decl);
259258
260 const entry = try self.decl_link.getOrPut(self.gpa, decl_index);259 const entry = try self.decl_link.getOrPut(self.gpa, decl_index);
261 if (!entry.found_existing) {260 if (!entry.found_existing) {
...@@ -861,7 +860,7 @@ const DeclGen = struct {...@@ -861,7 +860,7 @@ const DeclGen = struct {
861860
862 const val = arg_val;861 const val = arg_val;
863862
864 log.debug("constant: ty = {}, val = {}", .{ ty.fmt(mod), val.fmtValue(ty, mod) });863 log.debug("constant: ty = {}, val = {}", .{ ty.fmt(mod), val.fmtValue(mod) });
865 if (val.isUndefDeep(mod)) {864 if (val.isUndefDeep(mod)) {
866 return self.spv.constUndef(result_ty_ref);865 return self.spv.constUndef(result_ty_ref);
867 }866 }
...@@ -1221,7 +1220,7 @@ const DeclGen = struct {...@@ -1221,7 +1220,7 @@ const DeclGen = struct {
1221 else => {},1220 else => {},
1222 }1221 }
12231222
1224 if (!decl.ty.isFnOrHasRuntimeBitsIgnoreComptime(mod)) {1223 if (!decl.typeOf(mod).isFnOrHasRuntimeBitsIgnoreComptime(mod)) {
1225 // Pointer to nothing - return undefined.1224 // Pointer to nothing - return undefined.
1226 return self.spv.constUndef(ty_ref);1225 return self.spv.constUndef(ty_ref);
1227 }1226 }
...@@ -1237,7 +1236,7 @@ const DeclGen = struct {...@@ -1237,7 +1236,7 @@ const DeclGen = struct {
1237 const final_storage_class = self.spvStorageClass(decl.@"addrspace");1236 const final_storage_class = self.spvStorageClass(decl.@"addrspace");
1238 try self.addFunctionDep(spv_decl_index, final_storage_class);1237 try self.addFunctionDep(spv_decl_index, final_storage_class);
12391238
1240 const decl_ptr_ty_ref = try self.ptrType(decl.ty, final_storage_class);1239 const decl_ptr_ty_ref = try self.ptrType(decl.typeOf(mod), final_storage_class);
12411240
1242 const ptr_id = switch (final_storage_class) {1241 const ptr_id = switch (final_storage_class) {
1243 .Generic => try self.castToGeneric(self.typeId(decl_ptr_ty_ref), decl_id),1242 .Generic => try self.castToGeneric(self.typeId(decl_ptr_ty_ref), decl_id),
...@@ -2044,11 +2043,11 @@ const DeclGen = struct {...@@ -2044,11 +2043,11 @@ const DeclGen = struct {
20442043
2045 switch (self.spv.declPtr(spv_decl_index).kind) {2044 switch (self.spv.declPtr(spv_decl_index).kind) {
2046 .func => {2045 .func => {
2047 assert(decl.ty.zigTypeTag(mod) == .Fn);2046 assert(decl.typeOf(mod).zigTypeTag(mod) == .Fn);
2048 const fn_info = mod.typeToFunc(decl.ty).?;2047 const fn_info = mod.typeToFunc(decl.typeOf(mod)).?;
2049 const return_ty_ref = try self.resolveFnReturnType(Type.fromInterned(fn_info.return_type));2048 const return_ty_ref = try self.resolveFnReturnType(Type.fromInterned(fn_info.return_type));
20502049
2051 const prototype_ty_ref = try self.resolveType(decl.ty, .direct);2050 const prototype_ty_ref = try self.resolveType(decl.typeOf(mod), .direct);
2052 try self.func.prologue.emit(self.spv.gpa, .OpFunction, .{2051 try self.func.prologue.emit(self.spv.gpa, .OpFunction, .{
2053 .id_result_type = self.typeId(return_ty_ref),2052 .id_result_type = self.typeId(return_ty_ref),
2054 .id_result = result_id,2053 .id_result = result_id,
...@@ -2121,7 +2120,7 @@ const DeclGen = struct {...@@ -2121,7 +2120,7 @@ const DeclGen = struct {
2121 const final_storage_class = self.spvStorageClass(decl.@"addrspace");2120 const final_storage_class = self.spvStorageClass(decl.@"addrspace");
2122 assert(final_storage_class != .Generic); // These should be instance globals2121 assert(final_storage_class != .Generic); // These should be instance globals
21232122
2124 const ptr_ty_ref = try self.ptrType(decl.ty, final_storage_class);2123 const ptr_ty_ref = try self.ptrType(decl.typeOf(mod), final_storage_class);
21252124
2126 try self.spv.sections.types_globals_constants.emit(self.spv.gpa, .OpVariable, .{2125 try self.spv.sections.types_globals_constants.emit(self.spv.gpa, .OpVariable, .{
2127 .id_result_type = self.typeId(ptr_ty_ref),2126 .id_result_type = self.typeId(ptr_ty_ref),
...@@ -2144,7 +2143,7 @@ const DeclGen = struct {...@@ -2144,7 +2143,7 @@ const DeclGen = struct {
21442143
2145 try self.spv.declareDeclDeps(spv_decl_index, &.{});2144 try self.spv.declareDeclDeps(spv_decl_index, &.{});
21462145
2147 const ptr_ty_ref = try self.ptrType(decl.ty, .Function);2146 const ptr_ty_ref = try self.ptrType(decl.typeOf(mod), .Function);
21482147
2149 if (maybe_init_val) |init_val| {2148 if (maybe_init_val) |init_val| {
2150 // TODO: Combine with resolveAnonDecl?2149 // TODO: Combine with resolveAnonDecl?
...@@ -2168,7 +2167,7 @@ const DeclGen = struct {...@@ -2168,7 +2167,7 @@ const DeclGen = struct {
2168 });2167 });
2169 self.current_block_label = root_block_id;2168 self.current_block_label = root_block_id;
21702169
2171 const val_id = try self.constant(decl.ty, init_val, .indirect);2170 const val_id = try self.constant(decl.typeOf(mod), init_val, .indirect);
2172 try self.func.body.emit(self.spv.gpa, .OpStore, .{2171 try self.func.body.emit(self.spv.gpa, .OpStore, .{
2173 .pointer = result_id,2172 .pointer = result_id,
2174 .object = val_id,2173 .object = val_id,
...@@ -4785,7 +4784,7 @@ const DeclGen = struct {...@@ -4785,7 +4784,7 @@ const DeclGen = struct {
4785 const mod = self.module;4784 const mod = self.module;
4786 if (!ret_ty.hasRuntimeBitsIgnoreComptime(mod)) {4785 if (!ret_ty.hasRuntimeBitsIgnoreComptime(mod)) {
4787 const decl = mod.declPtr(self.decl_index);4786 const decl = mod.declPtr(self.decl_index);
4788 const fn_info = mod.typeToFunc(decl.ty).?;4787 const fn_info = mod.typeToFunc(decl.typeOf(mod)).?;
4789 if (Type.fromInterned(fn_info.return_type).isError(mod)) {4788 if (Type.fromInterned(fn_info.return_type).isError(mod)) {
4790 // Functions with an empty error set are emitted with an error code4789 // Functions with an empty error set are emitted with an error code
4791 // return type and return zero so they can be function pointers coerced4790 // return type and return zero so they can be function pointers coerced
...@@ -4810,7 +4809,7 @@ const DeclGen = struct {...@@ -4810,7 +4809,7 @@ const DeclGen = struct {
48104809
4811 if (!ret_ty.hasRuntimeBitsIgnoreComptime(mod)) {4810 if (!ret_ty.hasRuntimeBitsIgnoreComptime(mod)) {
4812 const decl = mod.declPtr(self.decl_index);4811 const decl = mod.declPtr(self.decl_index);
4813 const fn_info = mod.typeToFunc(decl.ty).?;4812 const fn_info = mod.typeToFunc(decl.typeOf(mod)).?;
4814 if (Type.fromInterned(fn_info.return_type).isError(mod)) {4813 if (Type.fromInterned(fn_info.return_type).isError(mod)) {
4815 // Functions with an empty error set are emitted with an error code4814 // Functions with an empty error set are emitted with an error code
4816 // return type and return zero so they can be function pointers coerced4815 // return type and return zero so they can be function pointers coerced
src/link.zig+3-3
...@@ -17,7 +17,7 @@ const Liveness = @import("Liveness.zig");...@@ -17,7 +17,7 @@ const Liveness = @import("Liveness.zig");
17const Module = @import("Module.zig");17const Module = @import("Module.zig");
18const InternPool = @import("InternPool.zig");18const InternPool = @import("InternPool.zig");
19const Type = @import("type.zig").Type;19const Type = @import("type.zig").Type;
20const TypedValue = @import("TypedValue.zig");20const Value = @import("Value.zig");
21const LlvmObject = @import("codegen/llvm.zig").Object;21const LlvmObject = @import("codegen/llvm.zig").Object;
2222
23/// When adding a new field, remember to update `hashAddSystemLibs`.23/// When adding a new field, remember to update `hashAddSystemLibs`.
...@@ -376,14 +376,14 @@ pub const File = struct {...@@ -376,14 +376,14 @@ pub const File = struct {
376 /// Called from within the CodeGen to lower a local variable instantion as an unnamed376 /// Called from within the CodeGen to lower a local variable instantion as an unnamed
377 /// constant. Returns the symbol index of the lowered constant in the read-only section377 /// constant. Returns the symbol index of the lowered constant in the read-only section
378 /// of the final binary.378 /// of the final binary.
379 pub fn lowerUnnamedConst(base: *File, tv: TypedValue, decl_index: InternPool.DeclIndex) UpdateDeclError!u32 {379 pub fn lowerUnnamedConst(base: *File, val: Value, decl_index: InternPool.DeclIndex) UpdateDeclError!u32 {
380 if (build_options.only_c) @compileError("unreachable");380 if (build_options.only_c) @compileError("unreachable");
381 switch (base.tag) {381 switch (base.tag) {
382 .spirv => unreachable,382 .spirv => unreachable,
383 .c => unreachable,383 .c => unreachable,
384 .nvptx => unreachable,384 .nvptx => unreachable,
385 inline else => |t| {385 inline else => |t| {
386 return @fieldParentPtr(t.Type(), "base", base).lowerUnnamedConst(tv, decl_index);386 return @fieldParentPtr(t.Type(), "base", base).lowerUnnamedConst(val, decl_index);
387 },387 },
388 }388 }
389 }389 }
src/link/C.zig+2-6
...@@ -209,7 +209,7 @@ pub fn updateFunc(...@@ -209,7 +209,7 @@ pub fn updateFunc(
209 .module = module,209 .module = module,
210 .error_msg = null,210 .error_msg = null,
211 .pass = .{ .decl = decl_index },211 .pass = .{ .decl = decl_index },
212 .is_naked_fn = decl.ty.fnCallingConvention(module) == .Naked,212 .is_naked_fn = decl.typeOf(module).fnCallingConvention(module) == .Naked,
213 .fwd_decl = fwd_decl.toManaged(gpa),213 .fwd_decl = fwd_decl.toManaged(gpa),
214 .ctypes = ctypes.*,214 .ctypes = ctypes.*,
215 .anon_decl_deps = self.anon_decls,215 .anon_decl_deps = self.anon_decls,
...@@ -283,13 +283,9 @@ fn updateAnonDecl(self: *C, module: *Module, i: usize) !void {...@@ -283,13 +283,9 @@ fn updateAnonDecl(self: *C, module: *Module, i: usize) !void {
283 code.* = object.code.moveToUnmanaged();283 code.* = object.code.moveToUnmanaged();
284 }284 }
285285
286 const tv: @import("../TypedValue.zig") = .{
287 .ty = Type.fromInterned(module.intern_pool.typeOf(anon_decl)),
288 .val = Value.fromInterned(anon_decl),
289 };
290 const c_value: codegen.CValue = .{ .constant = anon_decl };286 const c_value: codegen.CValue = .{ .constant = anon_decl };
291 const alignment: Alignment = self.aligned_anon_decls.get(anon_decl) orelse .none;287 const alignment: Alignment = self.aligned_anon_decls.get(anon_decl) orelse .none;
292 codegen.genDeclValue(&object, tv, false, c_value, alignment, .none) catch |err| switch (err) {288 codegen.genDeclValue(&object, Value.fromInterned(anon_decl), false, c_value, alignment, .none) catch |err| switch (err) {
293 error.AnalysisFail => {289 error.AnalysisFail => {
294 @panic("TODO: C backend AnalysisFail on anonymous decl");290 @panic("TODO: C backend AnalysisFail on anonymous decl");
295 //try module.failed_decls.put(gpa, decl_index, object.dg.error_msg.?);291 //try module.failed_decls.put(gpa, decl_index, object.dg.error_msg.?);
src/link/Coff.zig+9-13
...@@ -1167,7 +1167,7 @@ pub fn updateFunc(self: *Coff, mod: *Module, func_index: InternPool.Index, air:...@@ -1167,7 +1167,7 @@ pub fn updateFunc(self: *Coff, mod: *Module, func_index: InternPool.Index, air:
1167 return self.updateExports(mod, .{ .decl_index = decl_index }, mod.getDeclExports(decl_index));1167 return self.updateExports(mod, .{ .decl_index = decl_index }, mod.getDeclExports(decl_index));
1168}1168}
11691169
1170pub fn lowerUnnamedConst(self: *Coff, tv: TypedValue, decl_index: InternPool.DeclIndex) !u32 {1170pub fn lowerUnnamedConst(self: *Coff, val: Value, decl_index: InternPool.DeclIndex) !u32 {
1171 const gpa = self.base.comp.gpa;1171 const gpa = self.base.comp.gpa;
1172 const mod = self.base.comp.module.?;1172 const mod = self.base.comp.module.?;
1173 const decl = mod.declPtr(decl_index);1173 const decl = mod.declPtr(decl_index);
...@@ -1180,7 +1180,8 @@ pub fn lowerUnnamedConst(self: *Coff, tv: TypedValue, decl_index: InternPool.Dec...@@ -1180,7 +1180,8 @@ pub fn lowerUnnamedConst(self: *Coff, tv: TypedValue, decl_index: InternPool.Dec
1180 const index = unnamed_consts.items.len;1180 const index = unnamed_consts.items.len;
1181 const sym_name = try std.fmt.allocPrint(gpa, "__unnamed_{s}_{d}", .{ decl_name, index });1181 const sym_name = try std.fmt.allocPrint(gpa, "__unnamed_{s}_{d}", .{ decl_name, index });
1182 defer gpa.free(sym_name);1182 defer gpa.free(sym_name);
1183 const atom_index = switch (try self.lowerConst(sym_name, tv, tv.ty.abiAlignment(mod), self.rdata_section_index.?, decl.srcLoc(mod))) {1183 const ty = val.typeOf(mod);
1184 const atom_index = switch (try self.lowerConst(sym_name, val, ty.abiAlignment(mod), self.rdata_section_index.?, decl.srcLoc(mod))) {
1184 .ok => |atom_index| atom_index,1185 .ok => |atom_index| atom_index,
1185 .fail => |em| {1186 .fail => |em| {
1186 decl.analysis = .codegen_failure;1187 decl.analysis = .codegen_failure;
...@@ -1198,7 +1199,7 @@ const LowerConstResult = union(enum) {...@@ -1198,7 +1199,7 @@ const LowerConstResult = union(enum) {
1198 fail: *Module.ErrorMsg,1199 fail: *Module.ErrorMsg,
1199};1200};
12001201
1201fn lowerConst(self: *Coff, name: []const u8, tv: TypedValue, required_alignment: InternPool.Alignment, sect_id: u16, src_loc: Module.SrcLoc) !LowerConstResult {1202fn lowerConst(self: *Coff, name: []const u8, val: Value, required_alignment: InternPool.Alignment, sect_id: u16, src_loc: Module.SrcLoc) !LowerConstResult {
1202 const gpa = self.base.comp.gpa;1203 const gpa = self.base.comp.gpa;
12031204
1204 var code_buffer = std.ArrayList(u8).init(gpa);1205 var code_buffer = std.ArrayList(u8).init(gpa);
...@@ -1209,7 +1210,7 @@ fn lowerConst(self: *Coff, name: []const u8, tv: TypedValue, required_alignment:...@@ -1209,7 +1210,7 @@ fn lowerConst(self: *Coff, name: []const u8, tv: TypedValue, required_alignment:
1209 try self.setSymbolName(sym, name);1210 try self.setSymbolName(sym, name);
1210 sym.section_number = @as(coff.SectionNumber, @enumFromInt(sect_id + 1));1211 sym.section_number = @as(coff.SectionNumber, @enumFromInt(sect_id + 1));
12111212
1212 const res = try codegen.generateSymbol(&self.base, src_loc, tv, &code_buffer, .none, .{1213 const res = try codegen.generateSymbol(&self.base, src_loc, val, &code_buffer, .none, .{
1213 .parent_atom_index = self.getAtom(atom_index).getSymbolIndex().?,1214 .parent_atom_index = self.getAtom(atom_index).getSymbolIndex().?,
1214 });1215 });
1215 const code = switch (res) {1216 const code = switch (res) {
...@@ -1271,10 +1272,7 @@ pub fn updateDecl(...@@ -1271,10 +1272,7 @@ pub fn updateDecl(
1271 defer code_buffer.deinit();1272 defer code_buffer.deinit();
12721273
1273 const decl_val = if (decl.val.getVariable(mod)) |variable| Value.fromInterned(variable.init) else decl.val;1274 const decl_val = if (decl.val.getVariable(mod)) |variable| Value.fromInterned(variable.init) else decl.val;
1274 const res = try codegen.generateSymbol(&self.base, decl.srcLoc(mod), .{1275 const res = try codegen.generateSymbol(&self.base, decl.srcLoc(mod), decl_val, &code_buffer, .none, .{
1275 .ty = decl.ty,
1276 .val = decl_val,
1277 }, &code_buffer, .none, .{
1278 .parent_atom_index = atom.getSymbolIndex().?,1276 .parent_atom_index = atom.getSymbolIndex().?,
1279 });1277 });
1280 const code = switch (res) {1278 const code = switch (res) {
...@@ -1399,8 +1397,8 @@ pub fn getOrCreateAtomForDecl(self: *Coff, decl_index: InternPool.DeclIndex) !At...@@ -1399,8 +1397,8 @@ pub fn getOrCreateAtomForDecl(self: *Coff, decl_index: InternPool.DeclIndex) !At
13991397
1400fn getDeclOutputSection(self: *Coff, decl_index: InternPool.DeclIndex) u16 {1398fn getDeclOutputSection(self: *Coff, decl_index: InternPool.DeclIndex) u16 {
1401 const decl = self.base.comp.module.?.declPtr(decl_index);1399 const decl = self.base.comp.module.?.declPtr(decl_index);
1402 const ty = decl.ty;
1403 const mod = self.base.comp.module.?;1400 const mod = self.base.comp.module.?;
1401 const ty = decl.typeOf(mod);
1404 const zig_ty = ty.zigTypeTag(mod);1402 const zig_ty = ty.zigTypeTag(mod);
1405 const val = decl.val;1403 const val = decl.val;
1406 const index: u16 = blk: {1404 const index: u16 = blk: {
...@@ -1535,7 +1533,7 @@ pub fn updateExports(...@@ -1535,7 +1533,7 @@ pub fn updateExports(
1535 .x86 => std.builtin.CallingConvention.Stdcall,1533 .x86 => std.builtin.CallingConvention.Stdcall,
1536 else => std.builtin.CallingConvention.C,1534 else => std.builtin.CallingConvention.C,
1537 };1535 };
1538 const decl_cc = exported_decl.ty.fnCallingConvention(mod);1536 const decl_cc = exported_decl.typeOf(mod).fnCallingConvention(mod);
1539 if (decl_cc == .C and ip.stringEqlSlice(exp.opts.name, "main") and1537 if (decl_cc == .C and ip.stringEqlSlice(exp.opts.name, "main") and
1540 comp.config.link_libc)1538 comp.config.link_libc)
1541 {1539 {
...@@ -1887,14 +1885,13 @@ pub fn lowerAnonDecl(...@@ -1887,14 +1885,13 @@ pub fn lowerAnonDecl(
1887 }1885 }
18881886
1889 const val = Value.fromInterned(decl_val);1887 const val = Value.fromInterned(decl_val);
1890 const tv = TypedValue{ .ty = ty, .val = val };
1891 var name_buf: [32]u8 = undefined;1888 var name_buf: [32]u8 = undefined;
1892 const name = std.fmt.bufPrint(&name_buf, "__anon_{d}", .{1889 const name = std.fmt.bufPrint(&name_buf, "__anon_{d}", .{
1893 @intFromEnum(decl_val),1890 @intFromEnum(decl_val),
1894 }) catch unreachable;1891 }) catch unreachable;
1895 const res = self.lowerConst(1892 const res = self.lowerConst(
1896 name,1893 name,
1897 tv,1894 val,
1898 decl_alignment,1895 decl_alignment,
1899 self.rdata_section_index.?,1896 self.rdata_section_index.?,
1900 src_loc,1897 src_loc,
...@@ -2754,7 +2751,6 @@ const TableSection = @import("table_section.zig").TableSection;...@@ -2754,7 +2751,6 @@ const TableSection = @import("table_section.zig").TableSection;
2754const StringTable = @import("StringTable.zig");2751const StringTable = @import("StringTable.zig");
2755const Type = @import("../type.zig").Type;2752const Type = @import("../type.zig").Type;
2756const Value = @import("../Value.zig");2753const Value = @import("../Value.zig");
2757const TypedValue = @import("../TypedValue.zig");
27582754
2759pub const base_tag: link.File.Tag = .coff;2755pub const base_tag: link.File.Tag = .coff;
27602756
src/link/Dwarf.zig+3-3
...@@ -1109,7 +1109,7 @@ pub fn initDeclState(self: *Dwarf, mod: *Module, decl_index: InternPool.DeclInde...@@ -1109,7 +1109,7 @@ pub fn initDeclState(self: *Dwarf, mod: *Module, decl_index: InternPool.DeclInde
11091109
1110 assert(decl.has_tv);1110 assert(decl.has_tv);
11111111
1112 switch (decl.ty.zigTypeTag(mod)) {1112 switch (decl.typeOf(mod).zigTypeTag(mod)) {
1113 .Fn => {1113 .Fn => {
1114 _ = try self.getOrCreateAtomForDecl(.src_fn, decl_index);1114 _ = try self.getOrCreateAtomForDecl(.src_fn, decl_index);
11151115
...@@ -1162,7 +1162,7 @@ pub fn initDeclState(self: *Dwarf, mod: *Module, decl_index: InternPool.DeclInde...@@ -1162,7 +1162,7 @@ pub fn initDeclState(self: *Dwarf, mod: *Module, decl_index: InternPool.DeclInde
1162 try dbg_info_buffer.ensureUnusedCapacity(1 + ptr_width_bytes + 4 + 4 +1162 try dbg_info_buffer.ensureUnusedCapacity(1 + ptr_width_bytes + 4 + 4 +
1163 (decl_name_slice.len + 1) + (decl_linkage_name_slice.len + 1));1163 (decl_name_slice.len + 1) + (decl_linkage_name_slice.len + 1));
11641164
1165 const fn_ret_type = decl.ty.fnReturnType(mod);1165 const fn_ret_type = decl.typeOf(mod).fnReturnType(mod);
1166 const fn_ret_has_bits = fn_ret_type.hasRuntimeBits(mod);1166 const fn_ret_has_bits = fn_ret_type.hasRuntimeBits(mod);
1167 dbg_info_buffer.appendAssumeCapacity(@intFromEnum(1167 dbg_info_buffer.appendAssumeCapacity(@intFromEnum(
1168 @as(AbbrevCode, if (fn_ret_has_bits) .subprogram else .subprogram_retvoid),1168 @as(AbbrevCode, if (fn_ret_has_bits) .subprogram else .subprogram_retvoid),
...@@ -1215,7 +1215,7 @@ pub fn commitDeclState(...@@ -1215,7 +1215,7 @@ pub fn commitDeclState(
1215 var dbg_info_buffer = &decl_state.dbg_info;1215 var dbg_info_buffer = &decl_state.dbg_info;
12161216
1217 assert(decl.has_tv);1217 assert(decl.has_tv);
1218 switch (decl.ty.zigTypeTag(zcu)) {1218 switch (decl.typeOf(zcu).zigTypeTag(zcu)) {
1219 .Fn => {1219 .Fn => {
1220 try decl_state.setInlineFunc(decl.val.toIntern());1220 try decl_state.setInlineFunc(decl.val.toIntern());
12211221
src/link/Elf.zig+3-3
...@@ -3039,8 +3039,8 @@ pub fn updateDecl(...@@ -3039,8 +3039,8 @@ pub fn updateDecl(
3039 return self.zigObjectPtr().?.updateDecl(self, mod, decl_index);3039 return self.zigObjectPtr().?.updateDecl(self, mod, decl_index);
3040}3040}
30413041
3042pub fn lowerUnnamedConst(self: *Elf, typed_value: TypedValue, decl_index: InternPool.DeclIndex) !u32 {3042pub fn lowerUnnamedConst(self: *Elf, val: Value, decl_index: InternPool.DeclIndex) !u32 {
3043 return self.zigObjectPtr().?.lowerUnnamedConst(self, typed_value, decl_index);3043 return self.zigObjectPtr().?.lowerUnnamedConst(self, val, decl_index);
3044}3044}
30453045
3046pub fn updateExports(3046pub fn updateExports(
...@@ -6260,7 +6260,7 @@ const SharedObject = @import("Elf/SharedObject.zig");...@@ -6260,7 +6260,7 @@ const SharedObject = @import("Elf/SharedObject.zig");
6260const Symbol = @import("Elf/Symbol.zig");6260const Symbol = @import("Elf/Symbol.zig");
6261const StringTable = @import("StringTable.zig");6261const StringTable = @import("StringTable.zig");
6262const Thunk = thunks.Thunk;6262const Thunk = thunks.Thunk;
6263const TypedValue = @import("../TypedValue.zig");6263const Value = @import("../Value.zig");
6264const VerneedSection = synthetic_sections.VerneedSection;6264const VerneedSection = synthetic_sections.VerneedSection;
6265const ZigGotSection = synthetic_sections.ZigGotSection;6265const ZigGotSection = synthetic_sections.ZigGotSection;
6266const ZigObject = @import("Elf/ZigObject.zig");6266const ZigObject = @import("Elf/ZigObject.zig");
src/link/Elf/ZigObject.zig+10-17
...@@ -702,7 +702,6 @@ pub fn lowerAnonDecl(...@@ -702,7 +702,6 @@ pub fn lowerAnonDecl(
702 }702 }
703703
704 const val = Value.fromInterned(decl_val);704 const val = Value.fromInterned(decl_val);
705 const tv = TypedValue{ .ty = ty, .val = val };
706 var name_buf: [32]u8 = undefined;705 var name_buf: [32]u8 = undefined;
707 const name = std.fmt.bufPrint(&name_buf, "__anon_{d}", .{706 const name = std.fmt.bufPrint(&name_buf, "__anon_{d}", .{
708 @intFromEnum(decl_val),707 @intFromEnum(decl_val),
...@@ -710,7 +709,7 @@ pub fn lowerAnonDecl(...@@ -710,7 +709,7 @@ pub fn lowerAnonDecl(
710 const res = self.lowerConst(709 const res = self.lowerConst(
711 elf_file,710 elf_file,
712 name,711 name,
713 tv,712 val,
714 decl_alignment,713 decl_alignment,
715 elf_file.zig_data_rel_ro_section_index.?,714 elf_file.zig_data_rel_ro_section_index.?,
716 src_loc,715 src_loc,
...@@ -846,7 +845,7 @@ fn getDeclShdrIndex(...@@ -846,7 +845,7 @@ fn getDeclShdrIndex(
846 _ = self;845 _ = self;
847 const mod = elf_file.base.comp.module.?;846 const mod = elf_file.base.comp.module.?;
848 const any_non_single_threaded = elf_file.base.comp.config.any_non_single_threaded;847 const any_non_single_threaded = elf_file.base.comp.config.any_non_single_threaded;
849 const shdr_index = switch (decl.ty.zigTypeTag(mod)) {848 const shdr_index = switch (decl.typeOf(mod).zigTypeTag(mod)) {
850 .Fn => elf_file.zig_text_section_index.?,849 .Fn => elf_file.zig_text_section_index.?,
851 else => blk: {850 else => blk: {
852 if (decl.getOwnedVariable(mod)) |variable| {851 if (decl.getOwnedVariable(mod)) |variable| {
...@@ -1157,19 +1156,13 @@ pub fn updateDecl(...@@ -1157,19 +1156,13 @@ pub fn updateDecl(
1157 // TODO implement .debug_info for global variables1156 // TODO implement .debug_info for global variables
1158 const decl_val = if (decl.val.getVariable(mod)) |variable| Value.fromInterned(variable.init) else decl.val;1157 const decl_val = if (decl.val.getVariable(mod)) |variable| Value.fromInterned(variable.init) else decl.val;
1159 const res = if (decl_state) |*ds|1158 const res = if (decl_state) |*ds|
1160 try codegen.generateSymbol(&elf_file.base, decl.srcLoc(mod), .{1159 try codegen.generateSymbol(&elf_file.base, decl.srcLoc(mod), decl_val, &code_buffer, .{
1161 .ty = decl.ty,
1162 .val = decl_val,
1163 }, &code_buffer, .{
1164 .dwarf = ds,1160 .dwarf = ds,
1165 }, .{1161 }, .{
1166 .parent_atom_index = sym_index,1162 .parent_atom_index = sym_index,
1167 })1163 })
1168 else1164 else
1169 try codegen.generateSymbol(&elf_file.base, decl.srcLoc(mod), .{1165 try codegen.generateSymbol(&elf_file.base, decl.srcLoc(mod), decl_val, &code_buffer, .none, .{
1170 .ty = decl.ty,
1171 .val = decl_val,
1172 }, &code_buffer, .none, .{
1173 .parent_atom_index = sym_index,1166 .parent_atom_index = sym_index,
1174 });1167 });
11751168
...@@ -1289,7 +1282,7 @@ fn updateLazySymbol(...@@ -1289,7 +1282,7 @@ fn updateLazySymbol(
1289pub fn lowerUnnamedConst(1282pub fn lowerUnnamedConst(
1290 self: *ZigObject,1283 self: *ZigObject,
1291 elf_file: *Elf,1284 elf_file: *Elf,
1292 typed_value: TypedValue,1285 val: Value,
1293 decl_index: InternPool.DeclIndex,1286 decl_index: InternPool.DeclIndex,
1294) !u32 {1287) !u32 {
1295 const gpa = elf_file.base.comp.gpa;1288 const gpa = elf_file.base.comp.gpa;
...@@ -1304,11 +1297,12 @@ pub fn lowerUnnamedConst(...@@ -1304,11 +1297,12 @@ pub fn lowerUnnamedConst(
1304 const index = unnamed_consts.items.len;1297 const index = unnamed_consts.items.len;
1305 const name = try std.fmt.allocPrint(gpa, "__unnamed_{s}_{d}", .{ decl_name, index });1298 const name = try std.fmt.allocPrint(gpa, "__unnamed_{s}_{d}", .{ decl_name, index });
1306 defer gpa.free(name);1299 defer gpa.free(name);
1300 const ty = val.typeOf(mod);
1307 const sym_index = switch (try self.lowerConst(1301 const sym_index = switch (try self.lowerConst(
1308 elf_file,1302 elf_file,
1309 name,1303 name,
1310 typed_value,1304 val,
1311 typed_value.ty.abiAlignment(mod),1305 ty.abiAlignment(mod),
1312 elf_file.zig_data_rel_ro_section_index.?,1306 elf_file.zig_data_rel_ro_section_index.?,
1313 decl.srcLoc(mod),1307 decl.srcLoc(mod),
1314 )) {1308 )) {
...@@ -1334,7 +1328,7 @@ fn lowerConst(...@@ -1334,7 +1328,7 @@ fn lowerConst(
1334 self: *ZigObject,1328 self: *ZigObject,
1335 elf_file: *Elf,1329 elf_file: *Elf,
1336 name: []const u8,1330 name: []const u8,
1337 tv: TypedValue,1331 val: Value,
1338 required_alignment: InternPool.Alignment,1332 required_alignment: InternPool.Alignment,
1339 output_section_index: u32,1333 output_section_index: u32,
1340 src_loc: Module.SrcLoc,1334 src_loc: Module.SrcLoc,
...@@ -1346,7 +1340,7 @@ fn lowerConst(...@@ -1346,7 +1340,7 @@ fn lowerConst(
13461340
1347 const sym_index = try self.addAtom(elf_file);1341 const sym_index = try self.addAtom(elf_file);
13481342
1349 const res = try codegen.generateSymbol(&elf_file.base, src_loc, tv, &code_buffer, .{1343 const res = try codegen.generateSymbol(&elf_file.base, src_loc, val, &code_buffer, .{
1350 .none = {},1344 .none = {},
1351 }, .{1345 }, .{
1352 .parent_atom_index = sym_index,1346 .parent_atom_index = sym_index,
...@@ -1657,5 +1651,4 @@ const Symbol = @import("Symbol.zig");...@@ -1657,5 +1651,4 @@ const Symbol = @import("Symbol.zig");
1657const StringTable = @import("../StringTable.zig");1651const StringTable = @import("../StringTable.zig");
1658const Type = @import("../../type.zig").Type;1652const Type = @import("../../type.zig").Type;
1659const Value = @import("../../Value.zig");1653const Value = @import("../../Value.zig");
1660const TypedValue = @import("../../TypedValue.zig");
1661const ZigObject = @This();1654const ZigObject = @This();
src/link/MachO.zig+3-3
...@@ -3127,8 +3127,8 @@ pub fn updateFunc(self: *MachO, mod: *Module, func_index: InternPool.Index, air:...@@ -3127,8 +3127,8 @@ pub fn updateFunc(self: *MachO, mod: *Module, func_index: InternPool.Index, air:
3127 return self.getZigObject().?.updateFunc(self, mod, func_index, air, liveness);3127 return self.getZigObject().?.updateFunc(self, mod, func_index, air, liveness);
3128}3128}
31293129
3130pub fn lowerUnnamedConst(self: *MachO, typed_value: TypedValue, decl_index: InternPool.DeclIndex) !u32 {3130pub fn lowerUnnamedConst(self: *MachO, val: Value, decl_index: InternPool.DeclIndex) !u32 {
3131 return self.getZigObject().?.lowerUnnamedConst(self, typed_value, decl_index);3131 return self.getZigObject().?.lowerUnnamedConst(self, val, decl_index);
3132}3132}
31333133
3134pub fn updateDecl(self: *MachO, mod: *Module, decl_index: InternPool.DeclIndex) !void {3134pub fn updateDecl(self: *MachO, mod: *Module, decl_index: InternPool.DeclIndex) !void {
...@@ -4689,7 +4689,7 @@ const StubsHelperSection = synthetic.StubsHelperSection;...@@ -4689,7 +4689,7 @@ const StubsHelperSection = synthetic.StubsHelperSection;
4689const Symbol = @import("MachO/Symbol.zig");4689const Symbol = @import("MachO/Symbol.zig");
4690const Thunk = thunks.Thunk;4690const Thunk = thunks.Thunk;
4691const TlvPtrSection = synthetic.TlvPtrSection;4691const TlvPtrSection = synthetic.TlvPtrSection;
4692const TypedValue = @import("../TypedValue.zig");4692const Value = @import("../Value.zig");
4693const UnwindInfo = @import("MachO/UnwindInfo.zig");4693const UnwindInfo = @import("MachO/UnwindInfo.zig");
4694const WeakBindSection = synthetic.WeakBindSection;4694const WeakBindSection = synthetic.WeakBindSection;
4695const ZigGotSection = synthetic.ZigGotSection;4695const ZigGotSection = synthetic.ZigGotSection;
src/link/MachO/ZigObject.zig+8-15
...@@ -567,8 +567,6 @@ pub fn lowerAnonDecl(...@@ -567,8 +567,6 @@ pub fn lowerAnonDecl(
567 return .ok;567 return .ok;
568 }568 }
569569
570 const val = Value.fromInterned(decl_val);
571 const tv = TypedValue{ .ty = ty, .val = val };
572 var name_buf: [32]u8 = undefined;570 var name_buf: [32]u8 = undefined;
573 const name = std.fmt.bufPrint(&name_buf, "__anon_{d}", .{571 const name = std.fmt.bufPrint(&name_buf, "__anon_{d}", .{
574 @intFromEnum(decl_val),572 @intFromEnum(decl_val),
...@@ -576,7 +574,7 @@ pub fn lowerAnonDecl(...@@ -576,7 +574,7 @@ pub fn lowerAnonDecl(
576 const res = self.lowerConst(574 const res = self.lowerConst(
577 macho_file,575 macho_file,
578 name,576 name,
579 tv,577 Value.fromInterned(decl_val),
580 decl_alignment,578 decl_alignment,
581 macho_file.zig_const_sect_index.?,579 macho_file.zig_const_sect_index.?,
582 src_loc,580 src_loc,
...@@ -738,11 +736,7 @@ pub fn updateDecl(...@@ -738,11 +736,7 @@ pub fn updateDecl(
738736
739 const decl_val = if (decl.val.getVariable(mod)) |variable| Value.fromInterned(variable.init) else decl.val;737 const decl_val = if (decl.val.getVariable(mod)) |variable| Value.fromInterned(variable.init) else decl.val;
740 const dio: codegen.DebugInfoOutput = if (decl_state) |*ds| .{ .dwarf = ds } else .none;738 const dio: codegen.DebugInfoOutput = if (decl_state) |*ds| .{ .dwarf = ds } else .none;
741 const res =739 const res = try codegen.generateSymbol(&macho_file.base, decl.srcLoc(mod), decl_val, &code_buffer, dio, .{
742 try codegen.generateSymbol(&macho_file.base, decl.srcLoc(mod), .{
743 .ty = decl.ty,
744 .val = decl_val,
745 }, &code_buffer, dio, .{
746 .parent_atom_index = sym_index,740 .parent_atom_index = sym_index,
747 });741 });
748742
...@@ -1021,7 +1015,7 @@ fn getDeclOutputSection(...@@ -1021,7 +1015,7 @@ fn getDeclOutputSection(
1021 _ = self;1015 _ = self;
1022 const mod = macho_file.base.comp.module.?;1016 const mod = macho_file.base.comp.module.?;
1023 const any_non_single_threaded = macho_file.base.comp.config.any_non_single_threaded;1017 const any_non_single_threaded = macho_file.base.comp.config.any_non_single_threaded;
1024 const sect_id: u8 = switch (decl.ty.zigTypeTag(mod)) {1018 const sect_id: u8 = switch (decl.typeOf(mod).zigTypeTag(mod)) {
1025 .Fn => macho_file.zig_text_sect_index.?,1019 .Fn => macho_file.zig_text_sect_index.?,
1026 else => blk: {1020 else => blk: {
1027 if (decl.getOwnedVariable(mod)) |variable| {1021 if (decl.getOwnedVariable(mod)) |variable| {
...@@ -1068,7 +1062,7 @@ fn getDeclOutputSection(...@@ -1068,7 +1062,7 @@ fn getDeclOutputSection(
1068pub fn lowerUnnamedConst(1062pub fn lowerUnnamedConst(
1069 self: *ZigObject,1063 self: *ZigObject,
1070 macho_file: *MachO,1064 macho_file: *MachO,
1071 typed_value: TypedValue,1065 val: Value,
1072 decl_index: InternPool.DeclIndex,1066 decl_index: InternPool.DeclIndex,
1073) !u32 {1067) !u32 {
1074 const gpa = macho_file.base.comp.gpa;1068 const gpa = macho_file.base.comp.gpa;
...@@ -1086,8 +1080,8 @@ pub fn lowerUnnamedConst(...@@ -1086,8 +1080,8 @@ pub fn lowerUnnamedConst(
1086 const sym_index = switch (try self.lowerConst(1080 const sym_index = switch (try self.lowerConst(
1087 macho_file,1081 macho_file,
1088 name,1082 name,
1089 typed_value,1083 val,
1090 typed_value.ty.abiAlignment(mod),1084 val.typeOf(mod).abiAlignment(mod),
1091 macho_file.zig_const_sect_index.?,1085 macho_file.zig_const_sect_index.?,
1092 decl.srcLoc(mod),1086 decl.srcLoc(mod),
1093 )) {1087 )) {
...@@ -1113,7 +1107,7 @@ fn lowerConst(...@@ -1113,7 +1107,7 @@ fn lowerConst(
1113 self: *ZigObject,1107 self: *ZigObject,
1114 macho_file: *MachO,1108 macho_file: *MachO,
1115 name: []const u8,1109 name: []const u8,
1116 tv: TypedValue,1110 val: Value,
1117 required_alignment: Atom.Alignment,1111 required_alignment: Atom.Alignment,
1118 output_section_index: u8,1112 output_section_index: u8,
1119 src_loc: Module.SrcLoc,1113 src_loc: Module.SrcLoc,
...@@ -1125,7 +1119,7 @@ fn lowerConst(...@@ -1125,7 +1119,7 @@ fn lowerConst(
11251119
1126 const sym_index = try self.addAtom(macho_file);1120 const sym_index = try self.addAtom(macho_file);
11271121
1128 const res = try codegen.generateSymbol(&macho_file.base, src_loc, tv, &code_buffer, .{1122 const res = try codegen.generateSymbol(&macho_file.base, src_loc, val, &code_buffer, .{
1129 .none = {},1123 .none = {},
1130 }, .{1124 }, .{
1131 .parent_atom_index = sym_index,1125 .parent_atom_index = sym_index,
...@@ -1580,5 +1574,4 @@ const Symbol = @import("Symbol.zig");...@@ -1580,5 +1574,4 @@ const Symbol = @import("Symbol.zig");
1580const StringTable = @import("../StringTable.zig");1574const StringTable = @import("../StringTable.zig");
1581const Type = @import("../../type.zig").Type;1575const Type = @import("../../type.zig").Type;
1582const Value = @import("../../Value.zig");1576const Value = @import("../../Value.zig");
1583const TypedValue = @import("../../TypedValue.zig");
1584const ZigObject = @This();1577const ZigObject = @This();
src/link/Plan9.zig+6-13
...@@ -15,7 +15,6 @@ const Air = @import("../Air.zig");...@@ -15,7 +15,6 @@ const Air = @import("../Air.zig");
15const Liveness = @import("../Liveness.zig");15const Liveness = @import("../Liveness.zig");
16const Type = @import("../type.zig").Type;16const Type = @import("../type.zig").Type;
17const Value = @import("../Value.zig");17const Value = @import("../Value.zig");
18const TypedValue = @import("../TypedValue.zig");
1918
20const std = @import("std");19const std = @import("std");
21const builtin = @import("builtin");20const builtin = @import("builtin");
...@@ -177,7 +176,7 @@ pub const Atom = struct {...@@ -177,7 +176,7 @@ pub const Atom = struct {
177 return if (self.code_ptr) |p| p[0..self.other.code_len] else blk: {176 return if (self.code_ptr) |p| p[0..self.other.code_len] else blk: {
178 const decl_index = self.other.decl_index;177 const decl_index = self.other.decl_index;
179 const decl = mod.declPtr(decl_index);178 const decl = mod.declPtr(decl_index);
180 if (decl.ty.zigTypeTag(mod) == .Fn) {179 if (decl.typeOf(mod).zigTypeTag(mod) == .Fn) {
181 const table = plan9.fn_decl_table.get(decl.getFileScope(mod)).?.functions;180 const table = plan9.fn_decl_table.get(decl.getFileScope(mod)).?.functions;
182 const output = table.get(decl_index).?;181 const output = table.get(decl_index).?;
183 break :blk output.code;182 break :blk output.code;
...@@ -463,7 +462,7 @@ pub fn updateFunc(self: *Plan9, mod: *Module, func_index: InternPool.Index, air:...@@ -463,7 +462,7 @@ pub fn updateFunc(self: *Plan9, mod: *Module, func_index: InternPool.Index, air:
463 return self.updateFinish(decl_index);462 return self.updateFinish(decl_index);
464}463}
465464
466pub fn lowerUnnamedConst(self: *Plan9, tv: TypedValue, decl_index: InternPool.DeclIndex) !u32 {465pub fn lowerUnnamedConst(self: *Plan9, val: Value, decl_index: InternPool.DeclIndex) !u32 {
467 const gpa = self.base.comp.gpa;466 const gpa = self.base.comp.gpa;
468 _ = try self.seeDecl(decl_index);467 _ = try self.seeDecl(decl_index);
469 var code_buffer = std.ArrayList(u8).init(gpa);468 var code_buffer = std.ArrayList(u8).init(gpa);
...@@ -500,7 +499,7 @@ pub fn lowerUnnamedConst(self: *Plan9, tv: TypedValue, decl_index: InternPool.De...@@ -500,7 +499,7 @@ pub fn lowerUnnamedConst(self: *Plan9, tv: TypedValue, decl_index: InternPool.De
500 };499 };
501 self.syms.items[info.sym_index.?] = sym;500 self.syms.items[info.sym_index.?] = sym;
502501
503 const res = try codegen.generateSymbol(&self.base, decl.srcLoc(mod), tv, &code_buffer, .{502 const res = try codegen.generateSymbol(&self.base, decl.srcLoc(mod), val, &code_buffer, .{
504 .none = {},503 .none = {},
505 }, .{504 }, .{
506 .parent_atom_index = new_atom_idx,505 .parent_atom_index = new_atom_idx,
...@@ -539,10 +538,7 @@ pub fn updateDecl(self: *Plan9, mod: *Module, decl_index: InternPool.DeclIndex)...@@ -539,10 +538,7 @@ pub fn updateDecl(self: *Plan9, mod: *Module, decl_index: InternPool.DeclIndex)
539 defer code_buffer.deinit();538 defer code_buffer.deinit();
540 const decl_val = if (decl.val.getVariable(mod)) |variable| Value.fromInterned(variable.init) else decl.val;539 const decl_val = if (decl.val.getVariable(mod)) |variable| Value.fromInterned(variable.init) else decl.val;
541 // TODO we need the symbol index for symbol in the table of locals for the containing atom540 // TODO we need the symbol index for symbol in the table of locals for the containing atom
542 const res = try codegen.generateSymbol(&self.base, decl.srcLoc(mod), .{541 const res = try codegen.generateSymbol(&self.base, decl.srcLoc(mod), decl_val, &code_buffer, .{ .none = {} }, .{
543 .ty = decl.ty,
544 .val = decl_val,
545 }, &code_buffer, .{ .none = {} }, .{
546 .parent_atom_index = @as(Atom.Index, @intCast(atom_idx)),542 .parent_atom_index = @as(Atom.Index, @intCast(atom_idx)),
547 });543 });
548 const code = switch (res) {544 const code = switch (res) {
...@@ -566,7 +562,7 @@ fn updateFinish(self: *Plan9, decl_index: InternPool.DeclIndex) !void {...@@ -566,7 +562,7 @@ fn updateFinish(self: *Plan9, decl_index: InternPool.DeclIndex) !void {
566 const gpa = self.base.comp.gpa;562 const gpa = self.base.comp.gpa;
567 const mod = self.base.comp.module.?;563 const mod = self.base.comp.module.?;
568 const decl = mod.declPtr(decl_index);564 const decl = mod.declPtr(decl_index);
569 const is_fn = (decl.ty.zigTypeTag(mod) == .Fn);565 const is_fn = (decl.typeOf(mod).zigTypeTag(mod) == .Fn);
570 const sym_t: aout.Sym.Type = if (is_fn) .t else .d;566 const sym_t: aout.Sym.Type = if (is_fn) .t else .d;
571567
572 const atom = self.getAtomPtr(self.decls.get(decl_index).?.index);568 const atom = self.getAtomPtr(self.decls.get(decl_index).?.index);
...@@ -1545,11 +1541,8 @@ pub fn lowerAnonDecl(...@@ -1545,11 +1541,8 @@ pub fn lowerAnonDecl(
1545 // ...1541 // ...
1546 const gpa = self.base.comp.gpa;1542 const gpa = self.base.comp.gpa;
1547 const gop = try self.anon_decls.getOrPut(gpa, decl_val);1543 const gop = try self.anon_decls.getOrPut(gpa, decl_val);
1548 const mod = self.base.comp.module.?;
1549 if (!gop.found_existing) {1544 if (!gop.found_existing) {
1550 const ty = Type.fromInterned(mod.intern_pool.typeOf(decl_val));
1551 const val = Value.fromInterned(decl_val);1545 const val = Value.fromInterned(decl_val);
1552 const tv = TypedValue{ .ty = ty, .val = val };
1553 const name = try std.fmt.allocPrint(gpa, "__anon_{d}", .{@intFromEnum(decl_val)});1546 const name = try std.fmt.allocPrint(gpa, "__anon_{d}", .{@intFromEnum(decl_val)});
15541547
1555 const index = try self.createAtom();1548 const index = try self.createAtom();
...@@ -1557,7 +1550,7 @@ pub fn lowerAnonDecl(...@@ -1557,7 +1550,7 @@ pub fn lowerAnonDecl(
1557 gop.value_ptr.* = index;1550 gop.value_ptr.* = index;
1558 // we need to free name latex1551 // we need to free name latex
1559 var code_buffer = std.ArrayList(u8).init(gpa);1552 var code_buffer = std.ArrayList(u8).init(gpa);
1560 const res = try codegen.generateSymbol(&self.base, src_loc, tv, &code_buffer, .{ .none = {} }, .{ .parent_atom_index = index });1553 const res = try codegen.generateSymbol(&self.base, src_loc, val, &code_buffer, .{ .none = {} }, .{ .parent_atom_index = index });
1561 const code = switch (res) {1554 const code = switch (res) {
1562 .ok => code_buffer.items,1555 .ok => code_buffer.items,
1563 .fail => |em| return .{ .fail = em },1556 .fail => |em| return .{ .fail = em },
src/link/SpirV.zig+1-1
...@@ -163,7 +163,7 @@ pub fn updateExports(...@@ -163,7 +163,7 @@ pub fn updateExports(
163 if (decl.val.isFuncBody(mod)) {163 if (decl.val.isFuncBody(mod)) {
164 const target = mod.getTarget();164 const target = mod.getTarget();
165 const spv_decl_index = try self.object.resolveDecl(mod, decl_index);165 const spv_decl_index = try self.object.resolveDecl(mod, decl_index);
166 const execution_model = switch (decl.ty.fnCallingConvention(mod)) {166 const execution_model = switch (decl.typeOf(mod).fnCallingConvention(mod)) {
167 .Vertex => spec.ExecutionModel.Vertex,167 .Vertex => spec.ExecutionModel.Vertex,
168 .Fragment => spec.ExecutionModel.Fragment,168 .Fragment => spec.ExecutionModel.Fragment,
169 .Kernel => spec.ExecutionModel.Kernel,169 .Kernel => spec.ExecutionModel.Kernel,
src/link/Wasm.zig+3-3
...@@ -32,7 +32,7 @@ const Module = @import("../Module.zig");...@@ -32,7 +32,7 @@ const Module = @import("../Module.zig");
32const Object = @import("Wasm/Object.zig");32const Object = @import("Wasm/Object.zig");
33const Symbol = @import("Wasm/Symbol.zig");33const Symbol = @import("Wasm/Symbol.zig");
34const Type = @import("../type.zig").Type;34const Type = @import("../type.zig").Type;
35const TypedValue = @import("../TypedValue.zig");35const Value = @import("../Value.zig");
36const ZigObject = @import("Wasm/ZigObject.zig");36const ZigObject = @import("Wasm/ZigObject.zig");
3737
38pub const Atom = @import("Wasm/Atom.zig");38pub const Atom = @import("Wasm/Atom.zig");
...@@ -1504,8 +1504,8 @@ fn getFunctionSignature(wasm: *const Wasm, loc: SymbolLoc) std.wasm.Type {...@@ -1504,8 +1504,8 @@ fn getFunctionSignature(wasm: *const Wasm, loc: SymbolLoc) std.wasm.Type {
1504/// Lowers a constant typed value to a local symbol and atom.1504/// Lowers a constant typed value to a local symbol and atom.
1505/// Returns the symbol index of the local1505/// Returns the symbol index of the local
1506/// The given `decl` is the parent decl whom owns the constant.1506/// The given `decl` is the parent decl whom owns the constant.
1507pub fn lowerUnnamedConst(wasm: *Wasm, tv: TypedValue, decl_index: InternPool.DeclIndex) !u32 {1507pub fn lowerUnnamedConst(wasm: *Wasm, val: Value, decl_index: InternPool.DeclIndex) !u32 {
1508 return wasm.zigObjectPtr().?.lowerUnnamedConst(wasm, tv, decl_index);1508 return wasm.zigObjectPtr().?.lowerUnnamedConst(wasm, val, decl_index);
1509}1509}
15101510
1511/// Returns the symbol index from a symbol of which its flag is set global,1511/// Returns the symbol index from a symbol of which its flag is set global,
src/link/Wasm/ZigObject.zig+14-16
...@@ -270,7 +270,7 @@ pub fn updateDecl(...@@ -270,7 +270,7 @@ pub fn updateDecl(
270 const res = try codegen.generateSymbol(270 const res = try codegen.generateSymbol(
271 &wasm_file.base,271 &wasm_file.base,
272 decl.srcLoc(mod),272 decl.srcLoc(mod),
273 .{ .ty = decl.ty, .val = val },273 val,
274 &code_writer,274 &code_writer,
275 .none,275 .none,
276 .{ .parent_atom_index = @intFromEnum(atom.sym_index) },276 .{ .parent_atom_index = @intFromEnum(atom.sym_index) },
...@@ -346,7 +346,7 @@ fn finishUpdateDecl(...@@ -346,7 +346,7 @@ fn finishUpdateDecl(
346 try atom.code.appendSlice(gpa, code);346 try atom.code.appendSlice(gpa, code);
347 atom.size = @intCast(code.len);347 atom.size = @intCast(code.len);
348348
349 switch (decl.ty.zigTypeTag(mod)) {349 switch (decl.typeOf(mod).zigTypeTag(mod)) {
350 .Fn => {350 .Fn => {
351 sym.index = try zig_object.appendFunction(gpa, .{ .type_index = zig_object.atom_types.get(atom_index).? });351 sym.index = try zig_object.appendFunction(gpa, .{ .type_index = zig_object.atom_types.get(atom_index).? });
352 sym.tag = .function;352 sym.tag = .function;
...@@ -444,15 +444,12 @@ pub fn lowerAnonDecl(...@@ -444,15 +444,12 @@ pub fn lowerAnonDecl(
444 const gpa = wasm_file.base.comp.gpa;444 const gpa = wasm_file.base.comp.gpa;
445 const gop = try zig_object.anon_decls.getOrPut(gpa, decl_val);445 const gop = try zig_object.anon_decls.getOrPut(gpa, decl_val);
446 if (!gop.found_existing) {446 if (!gop.found_existing) {
447 const mod = wasm_file.base.comp.module.?;
448 const ty = Type.fromInterned(mod.intern_pool.typeOf(decl_val));
449 const tv: TypedValue = .{ .ty = ty, .val = Value.fromInterned(decl_val) };
450 var name_buf: [32]u8 = undefined;447 var name_buf: [32]u8 = undefined;
451 const name = std.fmt.bufPrint(&name_buf, "__anon_{d}", .{448 const name = std.fmt.bufPrint(&name_buf, "__anon_{d}", .{
452 @intFromEnum(decl_val),449 @intFromEnum(decl_val),
453 }) catch unreachable;450 }) catch unreachable;
454451
455 switch (try zig_object.lowerConst(wasm_file, name, tv, src_loc)) {452 switch (try zig_object.lowerConst(wasm_file, name, Value.fromInterned(decl_val), src_loc)) {
456 .ok => |atom_index| zig_object.anon_decls.values()[gop.index] = atom_index,453 .ok => |atom_index| zig_object.anon_decls.values()[gop.index] = atom_index,
457 .fail => |em| return .{ .fail = em },454 .fail => |em| return .{ .fail = em },
458 }455 }
...@@ -472,10 +469,10 @@ pub fn lowerAnonDecl(...@@ -472,10 +469,10 @@ pub fn lowerAnonDecl(
472/// Lowers a constant typed value to a local symbol and atom.469/// Lowers a constant typed value to a local symbol and atom.
473/// Returns the symbol index of the local470/// Returns the symbol index of the local
474/// The given `decl` is the parent decl whom owns the constant.471/// The given `decl` is the parent decl whom owns the constant.
475pub fn lowerUnnamedConst(zig_object: *ZigObject, wasm_file: *Wasm, tv: TypedValue, decl_index: InternPool.DeclIndex) !u32 {472pub fn lowerUnnamedConst(zig_object: *ZigObject, wasm_file: *Wasm, val: Value, decl_index: InternPool.DeclIndex) !u32 {
476 const gpa = wasm_file.base.comp.gpa;473 const gpa = wasm_file.base.comp.gpa;
477 const mod = wasm_file.base.comp.module.?;474 const mod = wasm_file.base.comp.module.?;
478 std.debug.assert(tv.ty.zigTypeTag(mod) != .Fn); // cannot create local symbols for functions475 std.debug.assert(val.typeOf(mod).zigTypeTag(mod) != .Fn); // cannot create local symbols for functions
479 const decl = mod.declPtr(decl_index);476 const decl = mod.declPtr(decl_index);
480477
481 const parent_atom_index = try zig_object.getOrCreateAtomForDecl(wasm_file, decl_index);478 const parent_atom_index = try zig_object.getOrCreateAtomForDecl(wasm_file, decl_index);
...@@ -487,7 +484,7 @@ pub fn lowerUnnamedConst(zig_object: *ZigObject, wasm_file: *Wasm, tv: TypedValu...@@ -487,7 +484,7 @@ pub fn lowerUnnamedConst(zig_object: *ZigObject, wasm_file: *Wasm, tv: TypedValu
487 });484 });
488 defer gpa.free(name);485 defer gpa.free(name);
489486
490 switch (try zig_object.lowerConst(wasm_file, name, tv, decl.srcLoc(mod))) {487 switch (try zig_object.lowerConst(wasm_file, name, val, decl.srcLoc(mod))) {
491 .ok => |atom_index| {488 .ok => |atom_index| {
492 try wasm_file.getAtomPtr(parent_atom_index).locals.append(gpa, atom_index);489 try wasm_file.getAtomPtr(parent_atom_index).locals.append(gpa, atom_index);
493 return @intFromEnum(wasm_file.getAtom(atom_index).sym_index);490 return @intFromEnum(wasm_file.getAtom(atom_index).sym_index);
...@@ -505,10 +502,12 @@ const LowerConstResult = union(enum) {...@@ -505,10 +502,12 @@ const LowerConstResult = union(enum) {
505 fail: *Module.ErrorMsg,502 fail: *Module.ErrorMsg,
506};503};
507504
508fn lowerConst(zig_object: *ZigObject, wasm_file: *Wasm, name: []const u8, tv: TypedValue, src_loc: Module.SrcLoc) !LowerConstResult {505fn lowerConst(zig_object: *ZigObject, wasm_file: *Wasm, name: []const u8, val: Value, src_loc: Module.SrcLoc) !LowerConstResult {
509 const gpa = wasm_file.base.comp.gpa;506 const gpa = wasm_file.base.comp.gpa;
510 const mod = wasm_file.base.comp.module.?;507 const mod = wasm_file.base.comp.module.?;
511508
509 const ty = val.typeOf(mod);
510
512 // Create and initialize a new local symbol and atom511 // Create and initialize a new local symbol and atom
513 const sym_index = try zig_object.allocateSymbol(gpa);512 const sym_index = try zig_object.allocateSymbol(gpa);
514 const atom_index = try wasm_file.createAtom(sym_index, zig_object.index);513 const atom_index = try wasm_file.createAtom(sym_index, zig_object.index);
...@@ -517,7 +516,7 @@ fn lowerConst(zig_object: *ZigObject, wasm_file: *Wasm, name: []const u8, tv: Ty...@@ -517,7 +516,7 @@ fn lowerConst(zig_object: *ZigObject, wasm_file: *Wasm, name: []const u8, tv: Ty
517516
518 const code = code: {517 const code = code: {
519 const atom = wasm_file.getAtomPtr(atom_index);518 const atom = wasm_file.getAtomPtr(atom_index);
520 atom.alignment = tv.ty.abiAlignment(mod);519 atom.alignment = ty.abiAlignment(mod);
521 const segment_name = try std.mem.concat(gpa, u8, &.{ ".rodata.", name });520 const segment_name = try std.mem.concat(gpa, u8, &.{ ".rodata.", name });
522 errdefer gpa.free(segment_name);521 errdefer gpa.free(segment_name);
523 zig_object.symbol(sym_index).* = .{522 zig_object.symbol(sym_index).* = .{
...@@ -527,7 +526,7 @@ fn lowerConst(zig_object: *ZigObject, wasm_file: *Wasm, name: []const u8, tv: Ty...@@ -527,7 +526,7 @@ fn lowerConst(zig_object: *ZigObject, wasm_file: *Wasm, name: []const u8, tv: Ty
527 .index = try zig_object.createDataSegment(526 .index = try zig_object.createDataSegment(
528 gpa,527 gpa,
529 segment_name,528 segment_name,
530 tv.ty.abiAlignment(mod),529 ty.abiAlignment(mod),
531 ),530 ),
532 .virtual_address = undefined,531 .virtual_address = undefined,
533 };532 };
...@@ -535,7 +534,7 @@ fn lowerConst(zig_object: *ZigObject, wasm_file: *Wasm, name: []const u8, tv: Ty...@@ -535,7 +534,7 @@ fn lowerConst(zig_object: *ZigObject, wasm_file: *Wasm, name: []const u8, tv: Ty
535 const result = try codegen.generateSymbol(534 const result = try codegen.generateSymbol(
536 &wasm_file.base,535 &wasm_file.base,
537 src_loc,536 src_loc,
538 tv,537 val,
539 &value_bytes,538 &value_bytes,
540 .none,539 .none,
541 .{540 .{
...@@ -764,7 +763,7 @@ pub fn getDeclVAddr(...@@ -764,7 +763,7 @@ pub fn getDeclVAddr(
764 const atom_index = wasm_file.symbol_atom.get(.{ .file = zig_object.index, .index = @enumFromInt(reloc_info.parent_atom_index) }).?;763 const atom_index = wasm_file.symbol_atom.get(.{ .file = zig_object.index, .index = @enumFromInt(reloc_info.parent_atom_index) }).?;
765 const atom = wasm_file.getAtomPtr(atom_index);764 const atom = wasm_file.getAtomPtr(atom_index);
766 const is_wasm32 = target.cpu.arch == .wasm32;765 const is_wasm32 = target.cpu.arch == .wasm32;
767 if (decl.ty.zigTypeTag(mod) == .Fn) {766 if (decl.typeOf(mod).zigTypeTag(mod) == .Fn) {
768 std.debug.assert(reloc_info.addend == 0); // addend not allowed for function relocations767 std.debug.assert(reloc_info.addend == 0); // addend not allowed for function relocations
769 try atom.relocs.append(gpa, .{768 try atom.relocs.append(gpa, .{
770 .index = target_symbol_index,769 .index = target_symbol_index,
...@@ -964,7 +963,7 @@ pub fn freeDecl(zig_object: *ZigObject, wasm_file: *Wasm, decl_index: InternPool...@@ -964,7 +963,7 @@ pub fn freeDecl(zig_object: *ZigObject, wasm_file: *Wasm, decl_index: InternPool
964 if (sym.isGlobal()) {963 if (sym.isGlobal()) {
965 std.debug.assert(zig_object.global_syms.remove(atom.sym_index));964 std.debug.assert(zig_object.global_syms.remove(atom.sym_index));
966 }965 }
967 switch (decl.ty.zigTypeTag(mod)) {966 switch (decl.typeOf(mod).zigTypeTag(mod)) {
968 .Fn => {967 .Fn => {
969 zig_object.functions_free_list.append(gpa, sym.index) catch {};968 zig_object.functions_free_list.append(gpa, sym.index) catch {};
970 std.debug.assert(zig_object.atom_types.remove(atom_index));969 std.debug.assert(zig_object.atom_types.remove(atom_index));
...@@ -1242,7 +1241,6 @@ const Module = @import("../../Module.zig");...@@ -1242,7 +1241,6 @@ const Module = @import("../../Module.zig");
1242const StringTable = @import("../StringTable.zig");1241const StringTable = @import("../StringTable.zig");
1243const Symbol = @import("Symbol.zig");1242const Symbol = @import("Symbol.zig");
1244const Type = @import("../../type.zig").Type;1243const Type = @import("../../type.zig").Type;
1245const TypedValue = @import("../../TypedValue.zig");
1246const Value = @import("../../Value.zig");1244const Value = @import("../../Value.zig");
1247const Wasm = @import("../Wasm.zig");1245const Wasm = @import("../Wasm.zig");
1248const ZigObject = @This();1246const ZigObject = @This();
src/mutable_value.zig created+508
...@@ -0,0 +1,508 @@
1const std = @import("std");
2const assert = std.debug.assert;
3const Allocator = std.mem.Allocator;
4const Zcu = @import("Module.zig");
5const InternPool = @import("InternPool.zig");
6const Type = @import("type.zig").Type;
7const Value = @import("Value.zig");
8
9/// We use a tagged union here because while it wastes a few bytes for some tags, having a fixed
10/// size for the type makes the common `aggregate` representation more efficient.
11/// For aggregates, the sentinel value, if any, *is* stored.
12pub const MutableValue = union(enum) {
13 /// An interned value.
14 interned: InternPool.Index,
15 /// An error union value which is a payload (not an error).
16 eu_payload: SubValue,
17 /// An optional value which is a payload (not `null`).
18 opt_payload: SubValue,
19 /// An aggregate consisting of a single repeated value.
20 repeated: SubValue,
21 /// An aggregate of `u8` consisting of "plain" bytes (no lazy or undefined elements).
22 bytes: Bytes,
23 /// An aggregate with arbitrary sub-values.
24 aggregate: Aggregate,
25 /// A slice, containing a pointer and length.
26 slice: Slice,
27 /// An instance of a union.
28 un: Union,
29
30 pub const SubValue = struct {
31 ty: InternPool.Index,
32 child: *MutableValue,
33 };
34 pub const Bytes = struct {
35 ty: InternPool.Index,
36 data: []u8,
37 };
38 pub const Aggregate = struct {
39 ty: InternPool.Index,
40 elems: []MutableValue,
41 };
42 pub const Slice = struct {
43 ty: InternPool.Index,
44 /// Must have the appropriate many-ptr type.
45 /// TODO: we want this to be an `InternPool.Index`, but `Sema.beginComptimePtrMutation` doesn't support it.
46 ptr: *MutableValue,
47 /// Must be of type `usize`.
48 /// TODO: we want this to be an `InternPool.Index`, but `Sema.beginComptimePtrMutation` doesn't support it.
49 len: *MutableValue,
50 };
51 pub const Union = struct {
52 ty: InternPool.Index,
53 tag: InternPool.Index,
54 payload: *MutableValue,
55 };
56
57 pub fn intern(mv: MutableValue, zcu: *Zcu, arena: Allocator) Allocator.Error!InternPool.Index {
58 const ip = &zcu.intern_pool;
59 const gpa = zcu.gpa;
60 return switch (mv) {
61 .interned => |ip_index| ip_index,
62 .eu_payload => |sv| try ip.get(gpa, .{ .error_union = .{
63 .ty = sv.ty,
64 .val = .{ .payload = try sv.child.intern(zcu, arena) },
65 } }),
66 .opt_payload => |sv| try ip.get(gpa, .{ .opt = .{
67 .ty = sv.ty,
68 .val = try sv.child.intern(zcu, arena),
69 } }),
70 .repeated => |sv| try ip.get(gpa, .{ .aggregate = .{
71 .ty = sv.ty,
72 .storage = .{ .repeated_elem = try sv.child.intern(zcu, arena) },
73 } }),
74 .bytes => |b| try ip.get(gpa, .{ .aggregate = .{
75 .ty = b.ty,
76 .storage = .{ .bytes = b.data },
77 } }),
78 .aggregate => |a| {
79 const elems = try arena.alloc(InternPool.Index, a.elems.len);
80 for (a.elems, elems) |mut_elem, *interned_elem| {
81 interned_elem.* = try mut_elem.intern(zcu, arena);
82 }
83 return ip.get(gpa, .{ .aggregate = .{
84 .ty = a.ty,
85 .storage = .{ .elems = elems },
86 } });
87 },
88 .slice => |s| try ip.get(gpa, .{ .slice = .{
89 .ty = s.ty,
90 .ptr = try s.ptr.intern(zcu, arena),
91 .len = try s.len.intern(zcu, arena),
92 } }),
93 .un => |u| try ip.get(gpa, .{ .un = .{
94 .ty = u.ty,
95 .tag = u.tag,
96 .val = try u.payload.intern(zcu, arena),
97 } }),
98 };
99 }
100
101 /// Un-interns the top level of this `MutableValue`, if applicable.
102 /// * Non-error error unions use `eu_payload`
103 /// * Non-null optionals use `eu_payload
104 /// * Slices use `slice`
105 /// * Unions use `un`
106 /// * Aggregates use `repeated` or `bytes` or `aggregate`
107 /// If `!allow_bytes`, the `bytes` representation will not be used.
108 /// If `!allow_repeated`, the `repeated` representation will not be used.
109 pub fn unintern(
110 mv: *MutableValue,
111 zcu: *Zcu,
112 arena: Allocator,
113 allow_bytes: bool,
114 allow_repeated: bool,
115 ) Allocator.Error!void {
116 const ip = &zcu.intern_pool;
117 const gpa = zcu.gpa;
118 switch (mv.*) {
119 .interned => |ip_index| switch (ip.indexToKey(ip_index)) {
120 .opt => |opt| if (opt.val != .none) {
121 const mut_payload = try arena.create(MutableValue);
122 mut_payload.* = .{ .interned = opt.val };
123 mv.* = .{ .opt_payload = .{
124 .ty = opt.ty,
125 .child = mut_payload,
126 } };
127 },
128 .error_union => |eu| switch (eu.val) {
129 .err_name => {},
130 .payload => |payload| {
131 const mut_payload = try arena.create(MutableValue);
132 mut_payload.* = .{ .interned = payload };
133 mv.* = .{ .eu_payload = .{
134 .ty = eu.ty,
135 .child = mut_payload,
136 } };
137 },
138 },
139 .slice => |slice| {
140 const ptr = try arena.create(MutableValue);
141 const len = try arena.create(MutableValue);
142 ptr.* = .{ .interned = slice.ptr };
143 len.* = .{ .interned = slice.len };
144 mv.* = .{ .slice = .{
145 .ty = slice.ty,
146 .ptr = ptr,
147 .len = len,
148 } };
149 },
150 .un => |un| {
151 const payload = try arena.create(MutableValue);
152 payload.* = .{ .interned = un.val };
153 mv.* = .{ .un = .{
154 .ty = un.ty,
155 .tag = un.tag,
156 .payload = payload,
157 } };
158 },
159 .aggregate => |agg| switch (agg.storage) {
160 .bytes => |bytes| {
161 assert(bytes.len == ip.aggregateTypeLenIncludingSentinel(agg.ty));
162 assert(ip.childType(agg.ty) == .u8_type);
163 if (allow_bytes) {
164 const arena_bytes = try arena.alloc(u8, bytes.len);
165 @memcpy(arena_bytes, bytes);
166 mv.* = .{ .bytes = .{
167 .ty = agg.ty,
168 .data = arena_bytes,
169 } };
170 } else {
171 const mut_elems = try arena.alloc(MutableValue, bytes.len);
172 for (bytes, mut_elems) |b, *mut_elem| {
173 mut_elem.* = .{ .interned = try ip.get(gpa, .{ .int = .{
174 .ty = .u8_type,
175 .storage = .{ .u64 = b },
176 } }) };
177 }
178 mv.* = .{ .aggregate = .{
179 .ty = agg.ty,
180 .elems = mut_elems,
181 } };
182 }
183 },
184 .elems => |elems| {
185 assert(elems.len == ip.aggregateTypeLenIncludingSentinel(agg.ty));
186 const mut_elems = try arena.alloc(MutableValue, elems.len);
187 for (elems, mut_elems) |interned_elem, *mut_elem| {
188 mut_elem.* = .{ .interned = interned_elem };
189 }
190 mv.* = .{ .aggregate = .{
191 .ty = agg.ty,
192 .elems = mut_elems,
193 } };
194 },
195 .repeated_elem => |val| {
196 if (allow_repeated) {
197 const repeated_val = try arena.create(MutableValue);
198 repeated_val.* = .{ .interned = val };
199 mv.* = .{ .repeated = .{
200 .ty = agg.ty,
201 .child = repeated_val,
202 } };
203 } else {
204 const len = ip.aggregateTypeLenIncludingSentinel(agg.ty);
205 const mut_elems = try arena.alloc(MutableValue, @intCast(len));
206 @memset(mut_elems, .{ .interned = val });
207 mv.* = .{ .aggregate = .{
208 .ty = agg.ty,
209 .elems = mut_elems,
210 } };
211 }
212 },
213 },
214 .undef => |ty_ip| switch (Type.fromInterned(ty_ip).zigTypeTag(zcu)) {
215 .Struct, .Array, .Vector => |type_tag| {
216 const ty = Type.fromInterned(ty_ip);
217 const opt_sent = ty.sentinel(zcu);
218 if (type_tag == .Struct or opt_sent != null or !allow_repeated) {
219 const len_no_sent = ip.aggregateTypeLen(ty_ip);
220 const elems = try arena.alloc(MutableValue, @intCast(len_no_sent + @intFromBool(opt_sent != null)));
221 switch (type_tag) {
222 .Array, .Vector => {
223 const elem_ty = ip.childType(ty_ip);
224 const undef_elem = try ip.get(gpa, .{ .undef = elem_ty });
225 @memset(elems[0..@intCast(len_no_sent)], .{ .interned = undef_elem });
226 },
227 .Struct => for (elems[0..@intCast(len_no_sent)], 0..) |*mut_elem, i| {
228 const field_ty = ty.structFieldType(i, zcu).toIntern();
229 mut_elem.* = .{ .interned = try ip.get(gpa, .{ .undef = field_ty }) };
230 },
231 else => unreachable,
232 }
233 if (opt_sent) |s| elems[@intCast(len_no_sent)] = .{ .interned = s.toIntern() };
234 mv.* = .{ .aggregate = .{
235 .ty = ty_ip,
236 .elems = elems,
237 } };
238 } else {
239 const repeated_val = try arena.create(MutableValue);
240 repeated_val.* = .{
241 .interned = try ip.get(gpa, .{ .undef = ip.childType(ty_ip) }),
242 };
243 mv.* = .{ .repeated = .{
244 .ty = ty_ip,
245 .child = repeated_val,
246 } };
247 }
248 },
249 .Union => {
250 const payload = try arena.create(MutableValue);
251 // HACKHACK: this logic is silly, but Sema detects it and reverts the change where needed.
252 // See comment at the top of `Sema.beginComptimePtrMutationInner`.
253 payload.* = .{ .interned = .undef };
254 mv.* = .{ .un = .{
255 .ty = ty_ip,
256 .tag = .none,
257 .payload = payload,
258 } };
259 },
260 .Pointer => {
261 const ptr_ty = ip.indexToKey(ty_ip).ptr_type;
262 if (ptr_ty.flags.size != .Slice) return;
263 const ptr = try arena.create(MutableValue);
264 const len = try arena.create(MutableValue);
265 ptr.* = .{ .interned = try ip.get(gpa, .{ .undef = ip.slicePtrType(ty_ip) }) };
266 len.* = .{ .interned = try ip.get(gpa, .{ .undef = .usize_type }) };
267 mv.* = .{ .slice = .{
268 .ty = ty_ip,
269 .ptr = ptr,
270 .len = len,
271 } };
272 },
273 else => {},
274 },
275 else => {},
276 },
277 .bytes => |bytes| if (!allow_bytes) {
278 const elems = try arena.alloc(MutableValue, bytes.data.len);
279 for (bytes.data, elems) |byte, *interned_byte| {
280 interned_byte.* = .{ .interned = try ip.get(gpa, .{ .int = .{
281 .ty = .u8_type,
282 .storage = .{ .u64 = byte },
283 } }) };
284 }
285 mv.* = .{ .aggregate = .{
286 .ty = bytes.ty,
287 .elems = elems,
288 } };
289 },
290 else => {},
291 }
292 }
293
294 /// Get a pointer to the `MutableValue` associated with a field/element.
295 /// The returned pointer can be safety mutated through to modify the field value.
296 /// The returned pointer is valid until the representation of `mv` changes.
297 /// This function does *not* support accessing the ptr/len field of slices.
298 pub fn elem(
299 mv: *MutableValue,
300 zcu: *Zcu,
301 arena: Allocator,
302 field_idx: usize,
303 ) Allocator.Error!*MutableValue {
304 const ip = &zcu.intern_pool;
305 const gpa = zcu.gpa;
306 // Convert to the `aggregate` representation.
307 switch (mv) {
308 .eu_payload, .opt_payload, .slice, .un => unreachable,
309 .interned => {
310 try mv.unintern(zcu, arena, false, false);
311 },
312 .bytes => |bytes| {
313 const elems = try arena.alloc(MutableValue, bytes.data.len);
314 for (bytes.data, elems) |byte, interned_byte| {
315 interned_byte.* = try ip.get(gpa, .{ .int = .{
316 .ty = .u8_type,
317 .storage = .{ .u64 = byte },
318 } });
319 }
320 mv.* = .{ .aggregate = .{
321 .ty = bytes.ty,
322 .elems = elems,
323 } };
324 },
325 .repeated => |repeated| {
326 const len = ip.aggregateTypeLenIncludingSentinel(repeated.ty);
327 const elems = try arena.alloc(MutableValue, @intCast(len));
328 @memset(elems, repeated.child.*);
329 mv.* = .{ .aggregate = .{
330 .ty = repeated.ty,
331 .elems = elems,
332 } };
333 },
334 .aggregate => {},
335 }
336 return &mv.aggregate.elems[field_idx];
337 }
338
339 /// Modify a single field of a `MutableValue` which represents an aggregate or slice, leaving others
340 /// untouched. When an entire field must be modified, this should be used in preference to `elemPtr`
341 /// to allow for an optimal representation.
342 /// For slices, uses `Value.slice_ptr_index` and `Value.slice_len_index`.
343 pub fn setElem(
344 mv: *MutableValue,
345 zcu: *Zcu,
346 arena: Allocator,
347 field_idx: usize,
348 field_val: MutableValue,
349 ) Allocator.Error!void {
350 const ip = &zcu.intern_pool;
351 const is_trivial_int = field_val.isTrivialInt(zcu);
352 try mv.unintern(arena, is_trivial_int, true);
353 switch (mv) {
354 .interned,
355 .eu_payload,
356 .opt_payload,
357 .un,
358 => unreachable,
359 .slice => |*s| switch (field_idx) {
360 Value.slice_ptr_index => s.ptr = field_val,
361 Value.slice_len_index => s.len = field_val,
362 },
363 .bytes => |b| {
364 assert(is_trivial_int);
365 assert(field_val.typeOf() == Type.u8);
366 b.data[field_idx] = Value.fromInterned(field_val.interned).toUnsignedInt(zcu);
367 },
368 .repeated => |r| {
369 if (field_val.eqlTrivial(r.child.*)) return;
370 // We must switch to either the `aggregate` or the `bytes` representation.
371 const len_inc_sent = ip.aggregateTypeLenIncludingSentinel(r.ty);
372 if (ip.zigTypeTag(r.ty) != .Struct and
373 is_trivial_int and
374 Type.fromInterned(r.ty).childType(zcu) == .u8_type and
375 r.child.isTrivialInt(zcu))
376 {
377 // We can use the `bytes` representation.
378 const bytes = try arena.alloc(u8, @intCast(len_inc_sent));
379 const repeated_byte = Value.fromInterned(r.child.interned).getUnsignedInt(zcu);
380 @memset(bytes, repeated_byte);
381 bytes[field_idx] = Value.fromInterned(field_val.interned).getUnsignedInt(zcu);
382 mv.* = .{ .bytes = .{
383 .ty = r.ty,
384 .data = bytes,
385 } };
386 } else {
387 // We must use the `aggregate` representation.
388 const mut_elems = try arena.alloc(u8, @intCast(len_inc_sent));
389 @memset(mut_elems, r.child.*);
390 mut_elems[field_idx] = field_val;
391 mv.* = .{ .aggregate = .{
392 .ty = r.ty,
393 .elems = mut_elems,
394 } };
395 }
396 },
397 .aggregate => |a| {
398 a.elems[field_idx] = field_val;
399 const is_struct = ip.zigTypeTag(a.ty) == .Struct;
400 // Attempt to switch to a more efficient representation.
401 const is_repeated = for (a.elems) |e| {
402 if (!e.eqlTrivial(field_val)) break false;
403 } else true;
404 if (is_repeated) {
405 // Switch to `repeated` repr
406 const mut_repeated = try arena.create(MutableValue);
407 mut_repeated.* = field_val;
408 mv.* = .{ .repeated = .{
409 .ty = a.ty,
410 .child = mut_repeated,
411 } };
412 } else if (!is_struct and is_trivial_int and Type.fromInterned(a.ty).childType(zcu).toIntern() == .u8_type) {
413 // See if we can switch to `bytes` repr
414 for (a.elems) |e| {
415 switch (e) {
416 else => break,
417 .interned => |ip_index| switch (ip.indexToKey(ip_index)) {
418 else => break,
419 .int => |int| switch (int.storage) {
420 .u64, .i64, .big_int => {},
421 .lazy_align, .lazy_size => break,
422 },
423 },
424 }
425 } else {
426 const bytes = try arena.alloc(u8, a.elems.len);
427 for (a.elems, bytes) |elem_val, *b| {
428 b.* = Value.fromInterned(elem_val.interned).toUnsignedInt(zcu);
429 }
430 mv.* = .{ .bytes = .{
431 .ty = a.ty,
432 .data = bytes,
433 } };
434 }
435 }
436 },
437 }
438 }
439
440 /// Get the value of a single field of a `MutableValue` which represents an aggregate or slice.
441 /// For slices, uses `Value.slice_ptr_index` and `Value.slice_len_index`.
442 pub fn getElem(
443 mv: MutableValue,
444 zcu: *Zcu,
445 field_idx: usize,
446 ) Allocator.Error!MutableValue {
447 return switch (mv) {
448 .eu_payload,
449 .opt_payload,
450 => unreachable,
451 .interned => |ip_index| {
452 const ty = Type.fromInterned(zcu.intern_pool.typeOf(ip_index));
453 switch (ty.zigTypeTag(zcu)) {
454 .Array, .Vector => return .{ .interned = (try Value.fromInterned(ip_index).elemValue(zcu, field_idx)).toIntern() },
455 .Struct, .Union => return .{ .interned = (try Value.fromInterned(ip_index).fieldValue(zcu, field_idx)).toIntern() },
456 .Pointer => {
457 assert(ty.isSlice(zcu));
458 return switch (field_idx) {
459 Value.slice_ptr_index => .{ .interned = Value.fromInterned(ip_index).slicePtr(zcu).toIntern() },
460 Value.slice_len_index => .{ .interned = switch (zcu.intern_pool.indexToKey(ip_index)) {
461 .undef => try zcu.intern(.{ .undef = .usize_type }),
462 .slice => |s| s.len,
463 else => unreachable,
464 } },
465 else => unreachable,
466 };
467 },
468 else => unreachable,
469 }
470 },
471 .un => |un| {
472 // TODO assert the tag is correct
473 return un.payload.*;
474 },
475 .slice => |s| switch (field_idx) {
476 Value.slice_ptr_index => s.ptr.*,
477 Value.slice_len_index => s.len.*,
478 else => unreachable,
479 },
480 .bytes => |b| .{ .interned = try zcu.intern(.{ .int = .{
481 .ty = .u8_type,
482 .storage = .{ .u64 = b.data[field_idx] },
483 } }) },
484 .repeated => |r| r.child.*,
485 .aggregate => |a| a.elems[field_idx],
486 };
487 }
488
489 fn isTrivialInt(mv: MutableValue, zcu: *Zcu) bool {
490 return switch (mv) {
491 else => false,
492 .interned => |ip_index| switch (zcu.intern_pool.indexToKey(ip_index)) {
493 else => false,
494 .int => |int| switch (int.storage) {
495 .u64, .i64, .big_int => true,
496 .lazy_align, .lazy_size => false,
497 },
498 },
499 };
500 }
501
502 pub fn typeOf(mv: MutableValue, zcu: *Zcu) Type {
503 return switch (mv) {
504 .interned => |ip_index| Type.fromInterned(zcu.intern_pool.typeOf(ip_index)),
505 inline else => |x| Type.fromInterned(x.ty),
506 };
507 }
508};
src/print_air.zig+1-1
...@@ -951,7 +951,7 @@ const Writer = struct {...@@ -951,7 +951,7 @@ const Writer = struct {
951 const ty = Type.fromInterned(mod.intern_pool.indexToKey(ip_index).typeOf());951 const ty = Type.fromInterned(mod.intern_pool.indexToKey(ip_index).typeOf());
952 try s.print("<{}, {}>", .{952 try s.print("<{}, {}>", .{
953 ty.fmt(mod),953 ty.fmt(mod),
954 Value.fromInterned(ip_index).fmtValue(ty, mod),954 Value.fromInterned(ip_index).fmtValue(mod),
955 });955 });
956 } else {956 } else {
957 return w.writeInstIndex(s, operand.toIndex().?, dies);957 return w.writeInstIndex(s, operand.toIndex().?, dies);
src/print_value.zig created+354
...@@ -0,0 +1,354 @@
1//! This type exists only for legacy purposes, and will be removed in the future.
2//! It is a thin wrapper around a `Value` which also, redundantly, stores its `Type`.
3
4const std = @import("std");
5const Type = @import("type.zig").Type;
6const Value = @import("Value.zig");
7const Zcu = @import("Module.zig");
8const Module = Zcu;
9const Sema = @import("Sema.zig");
10const InternPool = @import("InternPool.zig");
11const Allocator = std.mem.Allocator;
12const Target = std.Target;
13
14const max_aggregate_items = 100;
15const max_string_len = 256;
16
17const FormatContext = struct {
18 val: Value,
19 mod: *Module,
20};
21
22pub fn format(
23 ctx: FormatContext,
24 comptime fmt: []const u8,
25 options: std.fmt.FormatOptions,
26 writer: anytype,
27) !void {
28 _ = options;
29 comptime std.debug.assert(fmt.len == 0);
30 return print(ctx.val, writer, 3, ctx.mod, null) catch |err| switch (err) {
31 error.OutOfMemory => @panic("OOM"), // We're not allowed to return this from a format function
32 error.ComptimeBreak, error.ComptimeReturn => unreachable,
33 error.AnalysisFail, error.NeededSourceLocation => unreachable, // TODO: re-evaluate when we actually pass `opt_sema`
34 else => |e| return e,
35 };
36}
37
38pub fn print(
39 val: Value,
40 writer: anytype,
41 level: u8,
42 mod: *Module,
43 /// If this `Sema` is provided, we will recurse through pointers where possible to provide friendly output.
44 opt_sema: ?*Sema,
45) (@TypeOf(writer).Error || Module.CompileError)!void {
46 const ip = &mod.intern_pool;
47 switch (ip.indexToKey(val.toIntern())) {
48 .int_type,
49 .ptr_type,
50 .array_type,
51 .vector_type,
52 .opt_type,
53 .anyframe_type,
54 .error_union_type,
55 .simple_type,
56 .struct_type,
57 .anon_struct_type,
58 .union_type,
59 .opaque_type,
60 .enum_type,
61 .func_type,
62 .error_set_type,
63 .inferred_error_set_type,
64 => try Type.print(val.toType(), writer, mod),
65 .undef => try writer.writeAll("undefined"),
66 .simple_value => |simple_value| switch (simple_value) {
67 .void => try writer.writeAll("{}"),
68 .empty_struct => try writer.writeAll(".{}"),
69 .generic_poison => try writer.writeAll("(generic poison)"),
70 else => try writer.writeAll(@tagName(simple_value)),
71 },
72 .variable => try writer.writeAll("(variable)"),
73 .extern_func => |extern_func| try writer.print("(extern function '{}')", .{
74 mod.declPtr(extern_func.decl).name.fmt(ip),
75 }),
76 .func => |func| try writer.print("(function '{}')", .{
77 mod.declPtr(func.owner_decl).name.fmt(ip),
78 }),
79 .int => |int| switch (int.storage) {
80 inline .u64, .i64, .big_int => |x| try writer.print("{}", .{x}),
81 .lazy_align => |ty| if (opt_sema) |sema| {
82 const a = (try Type.fromInterned(ty).abiAlignmentAdvanced(mod, .{ .sema = sema })).scalar;
83 try writer.print("{}", .{a.toByteUnits(0)});
84 } else try writer.print("@alignOf({})", .{Type.fromInterned(ty).fmt(mod)}),
85 .lazy_size => |ty| if (opt_sema) |sema| {
86 const s = (try Type.fromInterned(ty).abiSizeAdvanced(mod, .{ .sema = sema })).scalar;
87 try writer.print("{}", .{s});
88 } else try writer.print("@sizeOf({})", .{Type.fromInterned(ty).fmt(mod)}),
89 },
90 .err => |err| try writer.print("error.{}", .{
91 err.name.fmt(ip),
92 }),
93 .error_union => |error_union| switch (error_union.val) {
94 .err_name => |err_name| try writer.print("error.{}", .{
95 err_name.fmt(ip),
96 }),
97 .payload => |payload| try print(Value.fromInterned(payload), writer, level, mod, opt_sema),
98 },
99 .enum_literal => |enum_literal| try writer.print(".{}", .{
100 enum_literal.fmt(ip),
101 }),
102 .enum_tag => |enum_tag| {
103 const enum_type = ip.loadEnumType(val.typeOf(mod).toIntern());
104 if (enum_type.tagValueIndex(ip, val.toIntern())) |tag_index| {
105 return writer.print(".{i}", .{enum_type.names.get(ip)[tag_index].fmt(ip)});
106 }
107 if (level == 0) {
108 return writer.writeAll("@enumFromInt(...)");
109 }
110 try writer.writeAll("@enumFromInt(");
111 try print(Value.fromInterned(enum_tag.int), writer, level - 1, mod, opt_sema);
112 try writer.writeAll(")");
113 },
114 .empty_enum_value => try writer.writeAll("(empty enum value)"),
115 .float => |float| switch (float.storage) {
116 inline else => |x| try writer.print("{d}", .{@as(f64, @floatCast(x))}),
117 },
118 .slice => |slice| {
119 const print_contents = switch (ip.getBackingAddrTag(slice.ptr).?) {
120 .field, .elem, .eu_payload, .opt_payload => unreachable,
121 .anon_decl, .comptime_alloc, .comptime_field => true,
122 .decl, .int => false,
123 };
124 if (print_contents) {
125 // TODO: eventually we want to load the slice as an array with `opt_sema`, but that's
126 // currently not possible without e.g. triggering compile errors.
127 }
128 try printPtr(slice.ptr, writer, false, false, 0, level, mod, opt_sema);
129 try writer.writeAll("[0..");
130 if (level == 0) {
131 try writer.writeAll("(...)");
132 } else {
133 try print(Value.fromInterned(slice.len), writer, level - 1, mod, opt_sema);
134 }
135 try writer.writeAll("]");
136 },
137 .ptr => {
138 const print_contents = switch (ip.getBackingAddrTag(val.toIntern()).?) {
139 .field, .elem, .eu_payload, .opt_payload => unreachable,
140 .anon_decl, .comptime_alloc, .comptime_field => true,
141 .decl, .int => false,
142 };
143 if (print_contents) {
144 // TODO: eventually we want to load the pointer with `opt_sema`, but that's
145 // currently not possible without e.g. triggering compile errors.
146 }
147 try printPtr(val.toIntern(), writer, false, false, 0, level, mod, opt_sema);
148 },
149 .opt => |opt| switch (opt.val) {
150 .none => try writer.writeAll("null"),
151 else => |payload| try print(Value.fromInterned(payload), writer, level, mod, opt_sema),
152 },
153 .aggregate => |aggregate| try printAggregate(val, aggregate, writer, level, false, mod, opt_sema),
154 .un => |un| {
155 if (level == 0) {
156 try writer.writeAll(".{ ... }");
157 return;
158 }
159 if (un.tag == .none) {
160 const backing_ty = try val.typeOf(mod).unionBackingType(mod);
161 try writer.print("@bitCast(@as({}, ", .{backing_ty.fmt(mod)});
162 try print(Value.fromInterned(un.val), writer, level - 1, mod, opt_sema);
163 try writer.writeAll("))");
164 } else {
165 try writer.writeAll(".{ ");
166 try print(Value.fromInterned(un.tag), writer, level - 1, mod, opt_sema);
167 try writer.writeAll(" = ");
168 try print(Value.fromInterned(un.val), writer, level - 1, mod, opt_sema);
169 try writer.writeAll(" }");
170 }
171 },
172 .memoized_call => unreachable,
173 }
174}
175
176fn printAggregate(
177 val: Value,
178 aggregate: InternPool.Key.Aggregate,
179 writer: anytype,
180 level: u8,
181 is_ref: bool,
182 zcu: *Zcu,
183 opt_sema: ?*Sema,
184) (@TypeOf(writer).Error || Module.CompileError)!void {
185 if (level == 0) {
186 return writer.writeAll(".{ ... }");
187 }
188 const ip = &zcu.intern_pool;
189 const ty = Type.fromInterned(aggregate.ty);
190 switch (ty.zigTypeTag(zcu)) {
191 .Struct => if (!ty.isTuple(zcu)) {
192 if (is_ref) try writer.writeByte('&');
193 if (ty.structFieldCount(zcu) == 0) {
194 return writer.writeAll(".{}");
195 }
196 try writer.writeAll(".{ ");
197 const max_len = @min(ty.structFieldCount(zcu), max_aggregate_items);
198 for (0..max_len) |i| {
199 if (i != 0) try writer.writeAll(", ");
200 const field_name = ty.structFieldName(@intCast(i), zcu).unwrap().?;
201 try writer.print(".{i} = ", .{field_name.fmt(ip)});
202 try print(try val.fieldValue(zcu, i), writer, level - 1, zcu, opt_sema);
203 }
204 try writer.writeAll(" }");
205 return;
206 },
207 .Array => if (aggregate.storage == .bytes and aggregate.storage.bytes.len > 0) {
208 const skip_terminator = aggregate.storage.bytes[aggregate.storage.bytes.len - 1] == 0;
209 const bytes = if (skip_terminator) b: {
210 break :b aggregate.storage.bytes[0 .. aggregate.storage.bytes.len - 1];
211 } else aggregate.storage.bytes;
212 try writer.print("\"{}\"", .{std.zig.fmtEscapes(bytes)});
213 if (!is_ref) try writer.writeAll(".*");
214 return;
215 } else if (ty.arrayLen(zcu) == 0) {
216 if (is_ref) try writer.writeByte('&');
217 return writer.writeAll(".{}");
218 } else if (ty.arrayLen(zcu) == 1) one_byte_str: {
219 // The repr isn't `bytes`, but we might still be able to print this as a string
220 if (ty.childType(zcu).toIntern() != .u8_type) break :one_byte_str;
221 const elem_val = Value.fromInterned(aggregate.storage.values()[0]);
222 if (elem_val.isUndef(zcu)) break :one_byte_str;
223 const byte = elem_val.toUnsignedInt(zcu);
224 try writer.print("\"{}\"", .{std.zig.fmtEscapes(&.{@intCast(byte)})});
225 if (!is_ref) try writer.writeAll(".*");
226 return;
227 },
228 .Vector => if (ty.arrayLen(zcu) == 0) {
229 if (is_ref) try writer.writeByte('&');
230 return writer.writeAll(".{}");
231 },
232 else => unreachable,
233 }
234
235 const len = ty.arrayLen(zcu);
236
237 if (is_ref) try writer.writeByte('&');
238 try writer.writeAll(".{ ");
239
240 const max_len = @min(len, max_aggregate_items);
241 for (0..max_len) |i| {
242 if (i != 0) try writer.writeAll(", ");
243 try print(try val.fieldValue(zcu, i), writer, level - 1, zcu, opt_sema);
244 }
245 if (len > max_aggregate_items) {
246 try writer.writeAll(", ...");
247 }
248 return writer.writeAll(" }");
249}
250
251fn printPtr(
252 ptr_val: InternPool.Index,
253 writer: anytype,
254 force_type: bool,
255 force_addrof: bool,
256 leading_parens: u32,
257 level: u8,
258 zcu: *Zcu,
259 opt_sema: ?*Sema,
260) (@TypeOf(writer).Error || Module.CompileError)!void {
261 const ip = &zcu.intern_pool;
262 const ptr = switch (ip.indexToKey(ptr_val)) {
263 .undef => |ptr_ty| {
264 if (force_addrof) try writer.writeAll("&");
265 try writer.writeByteNTimes('(', leading_parens);
266 try writer.print("@as({}, undefined)", .{Type.fromInterned(ptr_ty).fmt(zcu)});
267 return;
268 },
269 .ptr => |ptr| ptr,
270 else => unreachable,
271 };
272 if (level == 0) {
273 return writer.writeAll("&...");
274 }
275 switch (ptr.addr) {
276 .int => |int| {
277 if (force_addrof) try writer.writeAll("&");
278 try writer.writeByteNTimes('(', leading_parens);
279 if (force_type) {
280 try writer.print("@as({}, @ptrFromInt(", .{Type.fromInterned(ptr.ty).fmt(zcu)});
281 try print(Value.fromInterned(int), writer, level - 1, zcu, opt_sema);
282 try writer.writeAll("))");
283 } else {
284 try writer.writeAll("@ptrFromInt(");
285 try print(Value.fromInterned(int), writer, level - 1, zcu, opt_sema);
286 try writer.writeAll(")");
287 }
288 },
289 .decl => |index| {
290 try writer.writeAll("&");
291 try zcu.declPtr(index).renderFullyQualifiedName(zcu, writer);
292 },
293 .comptime_alloc => try writer.writeAll("&(comptime alloc)"),
294 .anon_decl => |anon| switch (ip.indexToKey(anon.val)) {
295 .aggregate => |aggregate| try printAggregate(
296 Value.fromInterned(anon.val),
297 aggregate,
298 writer,
299 level - 1,
300 true,
301 zcu,
302 opt_sema,
303 ),
304 else => {
305 const ty = Type.fromInterned(ip.typeOf(anon.val));
306 try writer.print("&@as({}, ", .{ty.fmt(zcu)});
307 try print(Value.fromInterned(anon.val), writer, level - 1, zcu, opt_sema);
308 try writer.writeAll(")");
309 },
310 },
311 .comptime_field => |val| {
312 const ty = Type.fromInterned(ip.typeOf(val));
313 try writer.print("&@as({}, ", .{ty.fmt(zcu)});
314 try print(Value.fromInterned(val), writer, level - 1, zcu, opt_sema);
315 try writer.writeAll(")");
316 },
317 .eu_payload => |base| {
318 try printPtr(base, writer, true, true, leading_parens, level, zcu, opt_sema);
319 try writer.writeAll(".?");
320 },
321 .opt_payload => |base| {
322 try writer.writeAll("(");
323 try printPtr(base, writer, true, true, leading_parens + 1, level, zcu, opt_sema);
324 try writer.writeAll(" catch unreachable");
325 },
326 .elem => |elem| {
327 try printPtr(elem.base, writer, true, true, leading_parens, level, zcu, opt_sema);
328 try writer.print("[{d}]", .{elem.index});
329 },
330 .field => |field| {
331 try printPtr(field.base, writer, true, true, leading_parens, level, zcu, opt_sema);
332 const base_ty = Type.fromInterned(ip.typeOf(field.base)).childType(zcu);
333 switch (base_ty.zigTypeTag(zcu)) {
334 .Struct => if (base_ty.isTuple(zcu)) {
335 try writer.print("[{d}]", .{field.index});
336 } else {
337 const field_name = base_ty.structFieldName(@intCast(field.index), zcu).unwrap().?;
338 try writer.print(".{i}", .{field_name.fmt(ip)});
339 },
340 .Union => {
341 const tag_ty = base_ty.unionTagTypeHypothetical(zcu);
342 const field_name = tag_ty.enumFieldName(@intCast(field.index), zcu);
343 try writer.print(".{i}", .{field_name.fmt(ip)});
344 },
345 .Pointer => switch (field.index) {
346 Value.slice_ptr_index => try writer.writeAll(".ptr"),
347 Value.slice_len_index => try writer.writeAll(".len"),
348 else => unreachable,
349 },
350 else => unreachable,
351 }
352 },
353 }
354}
src/type.zig+5-6
...@@ -7,7 +7,6 @@ const Module = @import("Module.zig");...@@ -7,7 +7,6 @@ const Module = @import("Module.zig");
7const Zcu = Module;7const Zcu = Module;
8const log = std.log.scoped(.Type);8const log = std.log.scoped(.Type);
9const target_util = @import("target.zig");9const target_util = @import("target.zig");
10const TypedValue = @import("TypedValue.zig");
11const Sema = @import("Sema.zig");10const Sema = @import("Sema.zig");
12const InternPool = @import("InternPool.zig");11const InternPool = @import("InternPool.zig");
13const Alignment = InternPool.Alignment;12const Alignment = InternPool.Alignment;
...@@ -188,8 +187,8 @@ pub const Type = struct {...@@ -188,8 +187,8 @@ pub const Type = struct {
188187
189 if (info.sentinel != .none) switch (info.flags.size) {188 if (info.sentinel != .none) switch (info.flags.size) {
190 .One, .C => unreachable,189 .One, .C => unreachable,
191 .Many => try writer.print("[*:{}]", .{Value.fromInterned(info.sentinel).fmtValue(Type.fromInterned(info.child), mod)}),190 .Many => try writer.print("[*:{}]", .{Value.fromInterned(info.sentinel).fmtValue(mod)}),
192 .Slice => try writer.print("[:{}]", .{Value.fromInterned(info.sentinel).fmtValue(Type.fromInterned(info.child), mod)}),191 .Slice => try writer.print("[:{}]", .{Value.fromInterned(info.sentinel).fmtValue(mod)}),
193 } else switch (info.flags.size) {192 } else switch (info.flags.size) {
194 .One => try writer.writeAll("*"),193 .One => try writer.writeAll("*"),
195 .Many => try writer.writeAll("[*]"),194 .Many => try writer.writeAll("[*]"),
...@@ -235,7 +234,7 @@ pub const Type = struct {...@@ -235,7 +234,7 @@ pub const Type = struct {
235 } else {234 } else {
236 try writer.print("[{d}:{}]", .{235 try writer.print("[{d}:{}]", .{
237 array_type.len,236 array_type.len,
238 Value.fromInterned(array_type.sentinel).fmtValue(Type.fromInterned(array_type.child), mod),237 Value.fromInterned(array_type.sentinel).fmtValue(mod),
239 });238 });
240 try print(Type.fromInterned(array_type.child), writer, mod);239 try print(Type.fromInterned(array_type.child), writer, mod);
241 }240 }
...@@ -353,7 +352,7 @@ pub const Type = struct {...@@ -353,7 +352,7 @@ pub const Type = struct {
353 try print(Type.fromInterned(field_ty), writer, mod);352 try print(Type.fromInterned(field_ty), writer, mod);
354353
355 if (val != .none) {354 if (val != .none) {
356 try writer.print(" = {}", .{Value.fromInterned(val).fmtValue(Type.fromInterned(field_ty), mod)});355 try writer.print(" = {}", .{Value.fromInterned(val).fmtValue(mod)});
357 }356 }
358 }357 }
359 try writer.writeAll("}");358 try writer.writeAll("}");
...@@ -2481,7 +2480,7 @@ pub const Type = struct {...@@ -2481,7 +2480,7 @@ pub const Type = struct {
2481 }2480 }
2482 const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[i]);2481 const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[i]);
2483 if (try field_ty.onePossibleValue(mod)) |field_opv| {2482 if (try field_ty.onePossibleValue(mod)) |field_opv| {
2484 field_val.* = try field_opv.intern(field_ty, mod);2483 field_val.* = field_opv.toIntern();
2485 } else return null;2484 } else return null;
2486 }2485 }
24872486
test/behavior/basic.zig-25
...@@ -693,31 +693,6 @@ test "string concatenation" {...@@ -693,31 +693,6 @@ test "string concatenation" {
693 try expect(b[len] == 0);693 try expect(b[len] == 0);
694}694}
695695
696fn manyptrConcat(comptime s: [*:0]const u8) [*:0]const u8 {
697 return "very " ++ s;
698}
699
700test "comptime manyptr concatenation" {
701 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
702 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
703 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
704
705 const s = "epic";
706 const actual = manyptrConcat(s);
707 const expected = "very epic";
708
709 const len = mem.len(actual);
710 const len_with_null = len + 1;
711 {
712 var i: u32 = 0;
713 while (i < len_with_null) : (i += 1) {
714 try expect(actual[i] == expected[i]);
715 }
716 }
717 try expect(actual[len] == 0);
718 try expect(expected[len] == 0);
719}
720
721test "result location is optional inside error union" {696test "result location is optional inside error union" {
722 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO697 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
723 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO698 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
test/cases/compile_errors/compile_log.zig+1-1
...@@ -21,7 +21,7 @@ export fn baz() void {...@@ -21,7 +21,7 @@ export fn baz() void {
21//21//
22// Compile Log Output:22// Compile Log Output:
23// @as(*const [5:0]u8, "begin")23// @as(*const [5:0]u8, "begin")
24// @as(*const [1:0]u8, "a"), @as(i32, 12), @as(*const [1:0]u8, "b"), @as([]const u8, "hi")24// @as(*const [1:0]u8, "a"), @as(i32, 12), @as(*const [1:0]u8, "b"), @as([]const u8, "hi"[0..2])
25// @as(*const [3:0]u8, "end")25// @as(*const [3:0]u8, "end")
26// @as(comptime_int, 4)26// @as(comptime_int, 4)
27// @as(*const [5:0]u8, "begin")27// @as(*const [5:0]u8, "begin")
test/cases/compile_errors/compile_log_a_pointer_to_an_opaque_value.zig+1-1
...@@ -9,4 +9,4 @@ export fn entry() void {...@@ -9,4 +9,4 @@ export fn entry() void {
9// :2:5: error: found compile log statement9// :2:5: error: found compile log statement
10//10//
11// Compile Log Output:11// Compile Log Output:
12// @as(*const anyopaque, (function 'entry'))12// @as(*const anyopaque, &tmp.entry)
test/cases/compile_errors/reify_type_for_exhaustive_enum_with_undefined_tag_type.zig+1-1
...@@ -14,4 +14,4 @@ export fn entry() void {...@@ -14,4 +14,4 @@ export fn entry() void {
14// backend=stage214// backend=stage2
15// target=native15// target=native
16//16//
17// :1:13: error: use of undefined value here causes undefined behavior17// :1:20: error: use of undefined value here causes undefined behavior
test/cases/compile_errors/reify_type_union_payload_is_undefined.zig+1-1
...@@ -9,4 +9,4 @@ comptime {...@@ -9,4 +9,4 @@ comptime {
9// backend=stage29// backend=stage2
10// target=native10// target=native
11//11//
12// :1:13: error: use of undefined value here causes undefined behavior12// :1:20: error: use of undefined value here causes undefined behavior
test/cases/compile_errors/reify_type_with_undefined.zig+3-3
...@@ -28,6 +28,6 @@ comptime {...@@ -28,6 +28,6 @@ comptime {
28// backend=stage228// backend=stage2
29// target=native29// target=native
30//30//
31// :2:9: error: use of undefined value here causes undefined behavior31// :2:16: error: use of undefined value here causes undefined behavior
32// :5:9: error: use of undefined value here causes undefined behavior32// :5:16: error: use of undefined value here causes undefined behavior
33// :17:9: error: use of undefined value here causes undefined behavior33// :17:16: error: use of undefined value here causes undefined behavior
test/cases/comptime_aggregate_print.zig+2-2
...@@ -31,5 +31,5 @@ pub fn main() !void {}...@@ -31,5 +31,5 @@ pub fn main() !void {}
31// :20:5: error: found compile log statement31// :20:5: error: found compile log statement
32//32//
33// Compile Log Output:33// Compile Log Output:
34// @as([]i32, .{ (reinterpreted data) })34// @as([]i32, &(comptime alloc).buf[0..2])
35// @as([]i32, .{ (reinterpreted data) })35// @as([]i32, &(comptime alloc).buf[0..2])