| author | |
| committer | |
| log | 5140f2726ae6e09381d9d44a72626dfe319f068b |
| tree | b2163e1439be4858c8e11b7d210ab91e262ab761 |
| parent | 341857e5cd4fd4453cf9c7d1a6679feb66710d84 |
| parent | 513254956525f8f970e972f6973ab4df0b19d06a |
| signature |
Follow-up to #1941440 files changed, 2016 insertions(+), 2706 deletions(-)
CMakeLists.txt+2-1| ... | ... | @@ -526,7 +526,6 @@ set(ZIG_STAGE2_SOURCES |
| 526 | 526 | "${CMAKE_SOURCE_DIR}/src/Package/Fetch.zig" |
| 527 | 527 | "${CMAKE_SOURCE_DIR}/src/RangeSet.zig" |
| 528 | 528 | "${CMAKE_SOURCE_DIR}/src/Sema.zig" |
| 529 | "${CMAKE_SOURCE_DIR}/src/TypedValue.zig" | |
| 530 | 529 | "${CMAKE_SOURCE_DIR}/src/Value.zig" |
| 531 | 530 | "${CMAKE_SOURCE_DIR}/src/arch/aarch64/CodeGen.zig" |
| 532 | 531 | "${CMAKE_SOURCE_DIR}/src/arch/aarch64/Emit.zig" |
| ... | ... | @@ -634,9 +633,11 @@ set(ZIG_STAGE2_SOURCES |
| 634 | 633 | "${CMAKE_SOURCE_DIR}/src/main.zig" |
| 635 | 634 | "${CMAKE_SOURCE_DIR}/src/mingw.zig" |
| 636 | 635 | "${CMAKE_SOURCE_DIR}/src/musl.zig" |
| 636 | "${CMAKE_SOURCE_DIR}/src/mutable_value.zig" | |
| 637 | 637 | "${CMAKE_SOURCE_DIR}/src/print_air.zig" |
| 638 | 638 | "${CMAKE_SOURCE_DIR}/src/print_env.zig" |
| 639 | 639 | "${CMAKE_SOURCE_DIR}/src/print_targets.zig" |
| 640 | "${CMAKE_SOURCE_DIR}/src/print_value.zig" | |
| 640 | 641 | "${CMAKE_SOURCE_DIR}/src/print_zir.zig" |
| 641 | 642 | "${CMAKE_SOURCE_DIR}/src/register_manager.zig" |
| 642 | 643 | "${CMAKE_SOURCE_DIR}/src/target.zig" |
src/Compilation.zig+1-18| ... | ... | @@ -102,7 +102,6 @@ link_errors: std.ArrayListUnmanaged(link.File.ErrorMsg) = .{}, |
| 102 | 102 | lld_errors: std.ArrayListUnmanaged(LldError) = .{}, |
| 103 | 103 | |
| 104 | 104 | work_queue: std.fifo.LinearFifo(Job, .Dynamic), |
| 105 | anon_work_queue: std.fifo.LinearFifo(Job, .Dynamic), | |
| 106 | 105 | |
| 107 | 106 | /// These jobs are to invoke the Clang compiler to create an object file, which |
| 108 | 107 | /// gets linked with the Compilation. |
| ... | ... | @@ -1417,7 +1416,6 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil |
| 1417 | 1416 | .emit_llvm_ir = options.emit_llvm_ir, |
| 1418 | 1417 | .emit_llvm_bc = options.emit_llvm_bc, |
| 1419 | 1418 | .work_queue = std.fifo.LinearFifo(Job, .Dynamic).init(gpa), |
| 1420 | .anon_work_queue = std.fifo.LinearFifo(Job, .Dynamic).init(gpa), | |
| 1421 | 1419 | .c_object_work_queue = std.fifo.LinearFifo(*CObject, .Dynamic).init(gpa), |
| 1422 | 1420 | .win32_resource_work_queue = if (build_options.only_core_functionality) {} else std.fifo.LinearFifo(*Win32Resource, .Dynamic).init(gpa), |
| 1423 | 1421 | .astgen_work_queue = std.fifo.LinearFifo(*Module.File, .Dynamic).init(gpa), |
| ... | ... | @@ -1840,7 +1838,6 @@ pub fn destroy(comp: *Compilation) void { |
| 1840 | 1838 | if (comp.module) |zcu| zcu.deinit(); |
| 1841 | 1839 | comp.cache_use.deinit(); |
| 1842 | 1840 | comp.work_queue.deinit(); |
| 1843 | comp.anon_work_queue.deinit(); | |
| 1844 | 1841 | comp.c_object_work_queue.deinit(); |
| 1845 | 1842 | if (!build_options.only_core_functionality) { |
| 1846 | 1843 | comp.win32_resource_work_queue.deinit(); |
| ... | ... | @@ -3354,18 +3351,11 @@ pub fn performAllTheWork( |
| 3354 | 3351 | mod.sema_prog_node = undefined; |
| 3355 | 3352 | }; |
| 3356 | 3353 | |
| 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 | 3354 | while (true) { |
| 3361 | 3355 | if (comp.work_queue.readItem()) |work_item| { |
| 3362 | 3356 | try processOneJob(comp, work_item, main_progress_node); |
| 3363 | 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 | 3359 | if (comp.module) |zcu| { |
| 3370 | 3360 | // If there's no work queued, check if there's anything outdated |
| 3371 | 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 | 3403 | |
| 3414 | 3404 | assert(decl.has_tv); |
| 3415 | 3405 | |
| 3416 | if (decl.alive) { | |
| 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); | |
| 3406 | try module.linkerUpdateDecl(decl_index); | |
| 3424 | 3407 | return; |
| 3425 | 3408 | }, |
| 3426 | 3409 | } |
src/InternPool.zig-5| ... | ... | @@ -6581,7 +6581,6 @@ pub fn getFuncInstance(ip: *InternPool, gpa: Allocator, arg: GetFuncInstanceKey) |
| 6581 | 6581 | generic_owner, |
| 6582 | 6582 | func_index, |
| 6583 | 6583 | func_extra_index, |
| 6584 | func_ty, | |
| 6585 | 6584 | arg.alignment, |
| 6586 | 6585 | arg.section, |
| 6587 | 6586 | ); |
| ... | ... | @@ -6711,7 +6710,6 @@ pub fn getFuncInstanceIes( |
| 6711 | 6710 | generic_owner, |
| 6712 | 6711 | func_index, |
| 6713 | 6712 | func_extra_index, |
| 6714 | func_ty, | |
| 6715 | 6713 | arg.alignment, |
| 6716 | 6714 | arg.section, |
| 6717 | 6715 | ); |
| ... | ... | @@ -6723,7 +6721,6 @@ fn finishFuncInstance( |
| 6723 | 6721 | generic_owner: Index, |
| 6724 | 6722 | func_index: Index, |
| 6725 | 6723 | func_extra_index: u32, |
| 6726 | func_ty: Index, | |
| 6727 | 6724 | alignment: Alignment, |
| 6728 | 6725 | section: OptionalNullTerminatedString, |
| 6729 | 6726 | ) Allocator.Error!Index { |
| ... | ... | @@ -6735,7 +6732,6 @@ fn finishFuncInstance( |
| 6735 | 6732 | .src_line = fn_owner_decl.src_line, |
| 6736 | 6733 | .has_tv = true, |
| 6737 | 6734 | .owns_tv = true, |
| 6738 | .ty = @import("type.zig").Type.fromInterned(func_ty), | |
| 6739 | 6735 | .val = @import("Value.zig").fromInterned(func_index), |
| 6740 | 6736 | .alignment = alignment, |
| 6741 | 6737 | .@"linksection" = section, |
| ... | ... | @@ -6744,7 +6740,6 @@ fn finishFuncInstance( |
| 6744 | 6740 | .zir_decl_index = fn_owner_decl.zir_decl_index, |
| 6745 | 6741 | .is_pub = fn_owner_decl.is_pub, |
| 6746 | 6742 | .is_exported = fn_owner_decl.is_exported, |
| 6747 | .alive = true, | |
| 6748 | 6743 | .kind = .anon, |
| 6749 | 6744 | }); |
| 6750 | 6745 | errdefer ip.destroyDecl(gpa, decl_index); |
src/Module.zig+56-209| ... | ... | @@ -22,7 +22,6 @@ const Compilation = @import("Compilation.zig"); |
| 22 | 22 | const Cache = std.Build.Cache; |
| 23 | 23 | const Value = @import("Value.zig"); |
| 24 | 24 | const Type = @import("type.zig").Type; |
| 25 | const TypedValue = @import("TypedValue.zig"); | |
| 26 | 25 | const Package = @import("Package.zig"); |
| 27 | 26 | const link = @import("link.zig"); |
| 28 | 27 | const Air = @import("Air.zig"); |
| ... | ... | @@ -330,9 +329,6 @@ const ValueArena = struct { |
| 330 | 329 | |
| 331 | 330 | pub const Decl = struct { |
| 332 | 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 | 332 | /// The most recent Value of the Decl after a successful semantic analysis. |
| 337 | 333 | /// Populated when `has_tv`. |
| 338 | 334 | val: Value, |
| ... | ... | @@ -397,15 +393,6 @@ pub const Decl = struct { |
| 397 | 393 | is_pub: bool, |
| 398 | 394 | /// Whether the corresponding AST decl has a `export` keyword. |
| 399 | 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 | 396 | /// If true `name` is already fully qualified. |
| 410 | 397 | name_fully_qualified: bool = false, |
| 411 | 398 | /// What kind of a declaration is this. |
| ... | ... | @@ -438,14 +425,6 @@ pub const Decl = struct { |
| 438 | 425 | return @as(i32, @bitCast(node_index)) - @as(i32, @bitCast(decl.src_node)); |
| 439 | 426 | } |
| 440 | 427 | |
| 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 | 428 | pub fn srcLoc(decl: Decl, zcu: *Zcu) SrcLoc { |
| 450 | 429 | return decl.nodeOffsetSrcLoc(0, zcu); |
| 451 | 430 | } |
| ... | ... | @@ -458,16 +437,6 @@ pub const Decl = struct { |
| 458 | 437 | }; |
| 459 | 438 | } |
| 460 | 439 | |
| 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 | 440 | pub fn renderFullyQualifiedName(decl: Decl, zcu: *Zcu, writer: anytype) !void { |
| 472 | 441 | if (decl.name_fully_qualified) { |
| 473 | 442 | try writer.print("{}", .{decl.name.fmt(&zcu.intern_pool)}); |
| ... | ... | @@ -487,37 +456,16 @@ pub const Decl = struct { |
| 487 | 456 | zcu.namespacePtr(decl.src_namespace).fullyQualifiedName(zcu, decl.name); |
| 488 | 457 | } |
| 489 | 458 | |
| 490 | pub fn typedValue(decl: Decl) error{AnalysisFail}!TypedValue { | |
| 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 { | |
| 459 | pub fn typeOf(decl: Decl, zcu: *const Zcu) Type { | |
| 496 | 460 | assert(decl.has_tv); |
| 497 | const ip_index = try decl.val.intern(decl.ty, zcu); | |
| 498 | decl.val = Value.fromInterned(ip_index); | |
| 499 | return ip_index; | |
| 461 | return decl.val.typeOf(zcu); | |
| 500 | 462 | } |
| 501 | 463 | |
| 502 | pub fn isFunction(decl: Decl, zcu: *const Zcu) !bool { | |
| 503 | const tv = try decl.typedValue(); | |
| 504 | return tv.ty.zigTypeTag(zcu) == .Fn; | |
| 505 | } | |
| 506 | ||
| 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()); | |
| 464 | /// Small wrapper for Sema to use over direct access to the `val` field. | |
| 465 | /// If the value is not populated, instead returns `error.AnalysisFail`. | |
| 466 | pub fn valueOrFail(decl: Decl) error{AnalysisFail}!Value { | |
| 467 | if (!decl.has_tv) return error.AnalysisFail; | |
| 468 | return decl.val; | |
| 521 | 469 | } |
| 522 | 470 | |
| 523 | 471 | pub fn getOwnedFunction(decl: Decl, zcu: *Zcu) ?InternPool.Key.Func { |
| ... | ... | @@ -590,7 +538,7 @@ pub const Decl = struct { |
| 590 | 538 | @tagName(decl.analysis), |
| 591 | 539 | }); |
| 592 | 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 | 543 | std.debug.print("\n", .{}); |
| 596 | 544 | } |
| ... | ... | @@ -615,7 +563,7 @@ pub const Decl = struct { |
| 615 | 563 | pub fn getAlignment(decl: Decl, zcu: *Zcu) Alignment { |
| 616 | 564 | assert(decl.has_tv); |
| 617 | 565 | if (decl.alignment != .none) return decl.alignment; |
| 618 | return decl.ty.abiAlignment(zcu); | |
| 566 | return decl.typeOf(zcu).abiAlignment(zcu); | |
| 619 | 567 | } |
| 620 | 568 | |
| 621 | 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 | 3473 | new_decl.src_line = 0; |
| 3526 | 3474 | new_decl.is_pub = true; |
| 3527 | 3475 | new_decl.is_exported = false; |
| 3528 | new_decl.ty = Type.type; | |
| 3529 | 3476 | new_decl.alignment = .none; |
| 3530 | 3477 | new_decl.@"linksection" = .none; |
| 3531 | new_decl.alive = true; // This Decl corresponds to a File and is therefore always alive. | |
| 3532 | 3478 | new_decl.analysis = .in_progress; |
| 3533 | 3479 | |
| 3534 | 3480 | if (file.status != .success_zir) { |
| ... | ... | @@ -3594,7 +3540,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !SemaDeclResult { |
| 3594 | 3540 | |
| 3595 | 3541 | const old_has_tv = decl.has_tv; |
| 3596 | 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 | 3544 | const old_val = decl.val; |
| 3599 | 3545 | const old_align = decl.alignment; |
| 3600 | 3546 | const old_linksection = decl.@"linksection"; |
| ... | ... | @@ -3698,25 +3644,25 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !SemaDeclResult { |
| 3698 | 3644 | const address_space_src: LazySrcLoc = .{ .node_offset_var_decl_addrspace = 0 }; |
| 3699 | 3645 | const ty_src: LazySrcLoc = .{ .node_offset_var_decl_ty = 0 }; |
| 3700 | 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); | |
| 3702 | 3649 | |
| 3703 | 3650 | // Note this resolves the type of the Decl, not the value; if this Decl |
| 3704 | 3651 | // is a struct, for example, this resolves `type` (which needs no resolution), |
| 3705 | 3652 | // not the struct itself. |
| 3706 | try sema.resolveTypeLayout(decl_tv.ty); | |
| 3653 | try sema.resolveTypeLayout(decl_ty); | |
| 3707 | 3654 | |
| 3708 | 3655 | if (decl.kind == .@"usingnamespace") { |
| 3709 | if (!decl_tv.ty.eql(Type.type, mod)) { | |
| 3656 | if (!decl_ty.eql(Type.type, mod)) { | |
| 3710 | 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 | 3662 | if (ty.getNamespace(mod) == null) { |
| 3716 | 3663 | return sema.fail(&block_scope, ty_src, "type {} has no namespace", .{ty.fmt(mod)}); |
| 3717 | 3664 | } |
| 3718 | 3665 | |
| 3719 | decl.ty = Type.fromInterned(InternPool.Index.type_type); | |
| 3720 | 3666 | decl.val = ty.toValue(); |
| 3721 | 3667 | decl.alignment = .none; |
| 3722 | 3668 | decl.@"linksection" = .none; |
| ... | ... | @@ -3734,10 +3680,10 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !SemaDeclResult { |
| 3734 | 3680 | var queue_linker_work = true; |
| 3735 | 3681 | var is_func = false; |
| 3736 | 3682 | var is_inline = false; |
| 3737 | switch (decl_tv.val.toIntern()) { | |
| 3683 | switch (decl_val.toIntern()) { | |
| 3738 | 3684 | .generic_poison => unreachable, |
| 3739 | 3685 | .unreachable_value => unreachable, |
| 3740 | else => switch (ip.indexToKey(decl_tv.val.toIntern())) { | |
| 3686 | else => switch (ip.indexToKey(decl_val.toIntern())) { | |
| 3741 | 3687 | .variable => |variable| { |
| 3742 | 3688 | decl.owns_tv = variable.decl == decl_index; |
| 3743 | 3689 | queue_linker_work = decl.owns_tv; |
| ... | ... | @@ -3752,7 +3698,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !SemaDeclResult { |
| 3752 | 3698 | .func => |func| { |
| 3753 | 3699 | decl.owns_tv = func.owner_decl == decl_index; |
| 3754 | 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 | 3702 | is_func = decl.owns_tv; |
| 3757 | 3703 | }, |
| 3758 | 3704 | |
| ... | ... | @@ -3760,8 +3706,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !SemaDeclResult { |
| 3760 | 3706 | }, |
| 3761 | 3707 | } |
| 3762 | 3708 | |
| 3763 | decl.ty = decl_tv.ty; | |
| 3764 | decl.val = Value.fromInterned((try decl_tv.val.intern(decl_tv.ty, mod))); | |
| 3709 | decl.val = decl_val; | |
| 3765 | 3710 | // Function linksection, align, and addrspace were already set by Sema |
| 3766 | 3711 | if (!is_func) { |
| 3767 | 3712 | decl.alignment = blk: { |
| ... | ... | @@ -3784,7 +3729,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !SemaDeclResult { |
| 3784 | 3729 | break :blk section.toOptional(); |
| 3785 | 3730 | }; |
| 3786 | 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 | 3733 | .variable => .variable, |
| 3789 | 3734 | .extern_func, .func => .function, |
| 3790 | 3735 | else => .constant, |
| ... | ... | @@ -3806,10 +3751,10 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !SemaDeclResult { |
| 3806 | 3751 | decl.analysis = .complete; |
| 3807 | 3752 | |
| 3808 | 3753 | const result: SemaDeclResult = if (old_has_tv) .{ |
| 3809 | .invalidate_decl_val = !decl.ty.eql(old_ty, mod) or | |
| 3810 | !decl.val.eql(old_val, decl.ty, mod) or | |
| 3754 | .invalidate_decl_val = !decl_ty.eql(old_ty, mod) or | |
| 3755 | !decl.val.eql(old_val, decl_ty, mod) or | |
| 3811 | 3756 | is_inline != old_is_inline, |
| 3812 | .invalidate_decl_ref = !decl.ty.eql(old_ty, mod) or | |
| 3757 | .invalidate_decl_ref = !decl_ty.eql(old_ty, mod) or | |
| 3813 | 3758 | decl.alignment != old_align or |
| 3814 | 3759 | decl.@"linksection" != old_linksection or |
| 3815 | 3760 | decl.@"addrspace" != old_addrspace or |
| ... | ... | @@ -3819,11 +3764,11 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !SemaDeclResult { |
| 3819 | 3764 | .invalidate_decl_ref = true, |
| 3820 | 3765 | }; |
| 3821 | 3766 | |
| 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 | 3768 | if (has_runtime_bits) { |
| 3824 | 3769 | // Needed for codegen_decl which will call updateDecl and then the |
| 3825 | 3770 | // codegen backend wants full access to the Decl Type. |
| 3826 | try sema.resolveTypeFully(decl.ty); | |
| 3771 | try sema.resolveTypeFully(decl_ty); | |
| 3827 | 3772 | |
| 3828 | 3773 | try mod.comp.work_queue.writeItem(.{ .codegen_decl = decl_index }); |
| 3829 | 3774 | |
| ... | ... | @@ -3850,7 +3795,7 @@ fn semaAnonOwnerDecl(zcu: *Zcu, decl_index: Decl.Index) !SemaDeclResult { |
| 3850 | 3795 | |
| 3851 | 3796 | log.debug("semaAnonOwnerDecl '{d}'", .{@intFromEnum(decl_index)}); |
| 3852 | 3797 | |
| 3853 | switch (decl.ty.zigTypeTag(zcu)) { | |
| 3798 | switch (decl.typeOf(zcu).zigTypeTag(zcu)) { | |
| 3854 | 3799 | .Fn => @panic("TODO: update fn instance"), |
| 3855 | 3800 | .Type => {}, |
| 3856 | 3801 | else => unreachable, |
| ... | ... | @@ -4380,7 +4325,6 @@ fn scanDecl(iter: *ScanDeclIter, decl_inst: Zir.Inst.Index) Allocator.Error!void |
| 4380 | 4325 | const decl = zcu.declPtr(decl_index); |
| 4381 | 4326 | const was_exported = decl.is_exported; |
| 4382 | 4327 | assert(decl.kind == kind); // ZIR tracking should preserve this |
| 4383 | assert(decl.alive); | |
| 4384 | 4328 | decl.name = decl_name; |
| 4385 | 4329 | decl.src_node = decl_node; |
| 4386 | 4330 | decl.src_line = line; |
| ... | ... | @@ -4397,7 +4341,6 @@ fn scanDecl(iter: *ScanDeclIter, decl_inst: Zir.Inst.Index) Allocator.Error!void |
| 4397 | 4341 | new_decl.is_pub = declaration.flags.is_pub; |
| 4398 | 4342 | new_decl.is_exported = declaration.flags.is_export; |
| 4399 | 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 | 4344 | break :decl_index .{ false, new_decl_index }; |
| 4402 | 4345 | }; |
| 4403 | 4346 | |
| ... | ... | @@ -4450,22 +4393,6 @@ fn scanDecl(iter: *ScanDeclIter, decl_inst: Zir.Inst.Index) Allocator.Error!void |
| 4450 | 4393 | } |
| 4451 | 4394 | } |
| 4452 | 4395 | |
| 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. | |
| 4456 | pub 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 | 4396 | /// Cancel the creation of an anon decl and delete any references to it. |
| 4470 | 4397 | /// If other decls depend on this decl, they must be aborted first. |
| 4471 | 4398 | pub fn abortAnonDecl(mod: *Module, decl_index: Decl.Index) void { |
| ... | ... | @@ -4475,12 +4402,8 @@ pub fn abortAnonDecl(mod: *Module, decl_index: Decl.Index) void { |
| 4475 | 4402 | |
| 4476 | 4403 | /// Finalize the creation of an anon decl. |
| 4477 | 4404 | pub 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=true | |
| 4479 | // if the Decl is referenced by an instruction or another constant. Otherwise, | |
| 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 }); | |
| 4405 | if (mod.declPtr(decl_index).typeOf(mod).isFnOrHasRuntimeBits(mod)) { | |
| 4406 | try mod.comp.work_queue.writeItem(.{ .codegen_decl = decl_index }); | |
| 4484 | 4407 | } |
| 4485 | 4408 | } |
| 4486 | 4409 | |
| ... | ... | @@ -4563,7 +4486,7 @@ pub fn analyzeFnBody(mod: *Module, func_index: InternPool.Index, arena: Allocato |
| 4563 | 4486 | // the runtime-known parameters only, not to be confused with the |
| 4564 | 4487 | // generic_owner function type, which potentially has more parameters, |
| 4565 | 4488 | // including comptime parameters. |
| 4566 | const fn_ty = decl.ty; | |
| 4489 | const fn_ty = decl.typeOf(mod); | |
| 4567 | 4490 | const fn_ty_info = mod.typeToFunc(fn_ty).?; |
| 4568 | 4491 | |
| 4569 | 4492 | var sema: Sema = .{ |
| ... | ... | @@ -4812,7 +4735,6 @@ pub fn allocateNewDecl( |
| 4812 | 4735 | .src_line = undefined, |
| 4813 | 4736 | .has_tv = false, |
| 4814 | 4737 | .owns_tv = false, |
| 4815 | .ty = undefined, | |
| 4816 | 4738 | .val = undefined, |
| 4817 | 4739 | .alignment = undefined, |
| 4818 | 4740 | .@"linksection" = .none, |
| ... | ... | @@ -4821,7 +4743,6 @@ pub fn allocateNewDecl( |
| 4821 | 4743 | .zir_decl_index = .none, |
| 4822 | 4744 | .is_pub = false, |
| 4823 | 4745 | .is_exported = false, |
| 4824 | .alive = false, | |
| 4825 | 4746 | .kind = .anon, |
| 4826 | 4747 | }); |
| 4827 | 4748 | |
| ... | ... | @@ -4856,41 +4777,18 @@ pub fn errorSetBits(mod: *Module) u16 { |
| 4856 | 4777 | return std.math.log2_int_ceil(ErrorInt, mod.error_limit + 1); // +1 for no error |
| 4857 | 4778 | } |
| 4858 | 4779 | |
| 4859 | pub 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 | ||
| 4864 | pub 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 | ||
| 4879 | 4780 | pub fn initNewAnonDecl( |
| 4880 | 4781 | mod: *Module, |
| 4881 | 4782 | new_decl_index: Decl.Index, |
| 4882 | 4783 | src_line: u32, |
| 4883 | typed_value: TypedValue, | |
| 4784 | val: Value, | |
| 4884 | 4785 | name: InternPool.NullTerminatedString, |
| 4885 | 4786 | ) Allocator.Error!void { |
| 4886 | assert(typed_value.ty.toIntern() == mod.intern_pool.typeOf(typed_value.val.toIntern())); | |
| 4887 | ||
| 4888 | 4787 | const new_decl = mod.declPtr(new_decl_index); |
| 4889 | 4788 | |
| 4890 | 4789 | new_decl.name = name; |
| 4891 | 4790 | new_decl.src_line = src_line; |
| 4892 | new_decl.ty = typed_value.ty; | |
| 4893 | new_decl.val = typed_value.val; | |
| 4791 | new_decl.val = val; | |
| 4894 | 4792 | new_decl.alignment = .none; |
| 4895 | 4793 | new_decl.@"linksection" = .none; |
| 4896 | 4794 | new_decl.has_tv = true; |
| ... | ... | @@ -5419,9 +5317,9 @@ pub fn populateTestFunctions( |
| 5419 | 5317 | try mod.ensureDeclAnalyzed(decl_index); |
| 5420 | 5318 | } |
| 5421 | 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); | |
| 5423 | 5321 | |
| 5424 | const array_decl_index = d: { | |
| 5322 | const array_anon_decl: InternPool.Key.Ptr.Addr.AnonDecl = array: { | |
| 5425 | 5323 | // Add mod.test_functions to an array decl then make the test_functions |
| 5426 | 5324 | // decl reference it as a slice. |
| 5427 | 5325 | const test_fn_vals = try gpa.alloc(InternPool.Index, mod.test_functions.count()); |
| ... | ... | @@ -5431,21 +5329,20 @@ pub fn populateTestFunctions( |
| 5431 | 5329 | const test_decl = mod.declPtr(test_decl_index); |
| 5432 | 5330 | const test_decl_name = try gpa.dupe(u8, ip.stringToSlice(try test_decl.fullyQualifiedName(mod))); |
| 5433 | 5331 | defer gpa.free(test_decl_name); |
| 5434 | const test_name_decl_index = n: { | |
| 5435 | const test_name_decl_ty = try mod.arrayType(.{ | |
| 5332 | const test_name_anon_decl: InternPool.Key.Ptr.Addr.AnonDecl = n: { | |
| 5333 | const test_name_ty = try mod.arrayType(.{ | |
| 5436 | 5334 | .len = test_decl_name.len, |
| 5437 | 5335 | .child = .u8_type, |
| 5438 | 5336 | }); |
| 5439 | const test_name_decl_index = try mod.createAnonymousDeclFromDecl(decl, decl.src_namespace, .{ | |
| 5440 | .ty = test_name_decl_ty, | |
| 5441 | .val = Value.fromInterned((try mod.intern(.{ .aggregate = .{ | |
| 5442 | .ty = test_name_decl_ty.toIntern(), | |
| 5443 | .storage = .{ .bytes = test_decl_name }, | |
| 5444 | } }))), | |
| 5445 | }); | |
| 5446 | break :n test_name_decl_index; | |
| 5337 | const test_name_val = try mod.intern(.{ .aggregate = .{ | |
| 5338 | .ty = test_name_ty.toIntern(), | |
| 5339 | .storage = .{ .bytes = test_decl_name }, | |
| 5340 | } }); | |
| 5341 | break :n .{ | |
| 5342 | .orig_ty = (try mod.singleConstPtrType(test_name_ty)).toIntern(), | |
| 5343 | .val = test_name_val, | |
| 5344 | }; | |
| 5447 | 5345 | }; |
| 5448 | try mod.linkerUpdateDecl(test_name_decl_index); | |
| 5449 | 5346 | |
| 5450 | 5347 | const test_fn_fields = .{ |
| 5451 | 5348 | // name |
| ... | ... | @@ -5453,7 +5350,7 @@ pub fn populateTestFunctions( |
| 5453 | 5350 | .ty = .slice_const_u8_type, |
| 5454 | 5351 | .ptr = try mod.intern(.{ .ptr = .{ |
| 5455 | 5352 | .ty = .manyptr_const_u8_type, |
| 5456 | .addr = .{ .decl = test_name_decl_index }, | |
| 5353 | .addr = .{ .anon_decl = test_name_anon_decl }, | |
| 5457 | 5354 | } }), |
| 5458 | 5355 | .len = try mod.intern(.{ .int = .{ |
| 5459 | 5356 | .ty = .usize_type, |
| ... | ... | @@ -5463,7 +5360,7 @@ pub fn populateTestFunctions( |
| 5463 | 5360 | // func |
| 5464 | 5361 | try mod.intern(.{ .ptr = .{ |
| 5465 | 5362 | .ty = try mod.intern(.{ .ptr_type = .{ |
| 5466 | .child = test_decl.ty.toIntern(), | |
| 5363 | .child = test_decl.typeOf(mod).toIntern(), | |
| 5467 | 5364 | .flags = .{ |
| 5468 | 5365 | .is_const = true, |
| 5469 | 5366 | }, |
| ... | ... | @@ -5477,22 +5374,20 @@ pub fn populateTestFunctions( |
| 5477 | 5374 | } }); |
| 5478 | 5375 | } |
| 5479 | 5376 | |
| 5480 | const array_decl_ty = try mod.arrayType(.{ | |
| 5377 | const array_ty = try mod.arrayType(.{ | |
| 5481 | 5378 | .len = test_fn_vals.len, |
| 5482 | 5379 | .child = test_fn_ty.toIntern(), |
| 5483 | 5380 | .sentinel = .none, |
| 5484 | 5381 | }); |
| 5485 | const array_decl_index = try mod.createAnonymousDeclFromDecl(decl, decl.src_namespace, .{ | |
| 5486 | .ty = array_decl_ty, | |
| 5487 | .val = Value.fromInterned((try mod.intern(.{ .aggregate = .{ | |
| 5488 | .ty = array_decl_ty.toIntern(), | |
| 5489 | .storage = .{ .elems = test_fn_vals }, | |
| 5490 | } }))), | |
| 5491 | }); | |
| 5492 | ||
| 5493 | break :d array_decl_index; | |
| 5382 | const array_val = try mod.intern(.{ .aggregate = .{ | |
| 5383 | .ty = array_ty.toIntern(), | |
| 5384 | .storage = .{ .elems = test_fn_vals }, | |
| 5385 | } }); | |
| 5386 | break :array .{ | |
| 5387 | .orig_ty = (try mod.singleConstPtrType(array_ty)).toIntern(), | |
| 5388 | .val = array_val, | |
| 5389 | }; | |
| 5494 | 5390 | }; |
| 5495 | try mod.linkerUpdateDecl(array_decl_index); | |
| 5496 | 5391 | |
| 5497 | 5392 | { |
| 5498 | 5393 | const new_ty = try mod.ptrType(.{ |
| ... | ... | @@ -5507,7 +5402,7 @@ pub fn populateTestFunctions( |
| 5507 | 5402 | .ty = new_ty.toIntern(), |
| 5508 | 5403 | .ptr = try mod.intern(.{ .ptr = .{ |
| 5509 | 5404 | .ty = new_ty.slicePtrFieldType(mod).toIntern(), |
| 5510 | .addr = .{ .decl = array_decl_index }, | |
| 5405 | .addr = .{ .anon_decl = array_anon_decl }, | |
| 5511 | 5406 | } }), |
| 5512 | 5407 | .len = (try mod.intValue(Type.usize, mod.test_functions.count())).toIntern(), |
| 5513 | 5408 | } }); |
| ... | ... | @@ -5515,7 +5410,6 @@ pub fn populateTestFunctions( |
| 5515 | 5410 | |
| 5516 | 5411 | // Since we are replacing the Decl's value we must perform cleanup on the |
| 5517 | 5412 | // previous value. |
| 5518 | decl.ty = new_ty; | |
| 5519 | 5413 | decl.val = new_val; |
| 5520 | 5414 | decl.has_tv = true; |
| 5521 | 5415 | } |
| ... | ... | @@ -5590,53 +5484,6 @@ fn reportRetryableFileError( |
| 5590 | 5484 | gop.value_ptr.* = err_msg; |
| 5591 | 5485 | } |
| 5592 | 5486 | |
| 5593 | pub 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 | ||
| 5624 | pub 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 | ||
| 5636 | fn markDeclIndexAlive(mod: *Module, decl_index: Decl.Index) Allocator.Error!void { | |
| 5637 | return mod.markDeclAlive(mod.declPtr(decl_index)); | |
| 5638 | } | |
| 5639 | ||
| 5640 | 5487 | pub fn addGlobalAssembly(mod: *Module, decl_index: Decl.Index, source: []const u8) !void { |
| 5641 | 5488 | const gop = try mod.global_assembly.getOrPut(mod.gpa, decl_index); |
| 5642 | 5489 | if (gop.found_existing) { |
src/Sema.zig+559-754| ... | ... | @@ -139,8 +139,7 @@ const MaybeComptimeAlloc = struct { |
| 139 | 139 | }; |
| 140 | 140 | |
| 141 | 141 | const ComptimeAlloc = struct { |
| 142 | ty: Type, | |
| 143 | val: Value, | |
| 142 | val: MutableValue, | |
| 144 | 143 | is_const: bool, |
| 145 | 144 | /// `.none` indicates that the alignment is the natural alignment of `val`. |
| 146 | 145 | alignment: Alignment, |
| ... | ... | @@ -153,8 +152,7 @@ const ComptimeAlloc = struct { |
| 153 | 152 | fn newComptimeAlloc(sema: *Sema, block: *Block, ty: Type, alignment: Alignment) !ComptimeAllocIndex { |
| 154 | 153 | const idx = sema.comptime_allocs.items.len; |
| 155 | 154 | try sema.comptime_allocs.append(sema.gpa, .{ |
| 156 | .ty = ty, | |
| 157 | .val = Value.fromInterned(try sema.mod.intern(.{ .undef = ty.toIntern() })), | |
| 155 | .val = .{ .interned = try sema.mod.intern(.{ .undef = ty.toIntern() }) }, | |
| 158 | 156 | .is_const = false, |
| 159 | 157 | .alignment = alignment, |
| 160 | 158 | .runtime_index = block.runtime_index, |
| ... | ... | @@ -175,8 +173,8 @@ const log = std.log.scoped(.sema); |
| 175 | 173 | |
| 176 | 174 | const Sema = @This(); |
| 177 | 175 | const Value = @import("Value.zig"); |
| 176 | const MutableValue = @import("mutable_value.zig").MutableValue; | |
| 178 | 177 | const Type = @import("type.zig").Type; |
| 179 | const TypedValue = @import("TypedValue.zig"); | |
| 180 | 178 | const Air = @import("Air.zig"); |
| 181 | 179 | const Zir = std.zig.Zir; |
| 182 | 180 | const Module = @import("Module.zig"); |
| ... | ... | @@ -1709,7 +1707,7 @@ fn analyzeBodyInner( |
| 1709 | 1707 | .needed_comptime_reason = "condition in comptime branch must be comptime-known", |
| 1710 | 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; | |
| 1713 | 1711 | |
| 1714 | 1712 | try sema.maybeErrorUnwrapCondbr(block, inline_body, extra.data.condition, cond_src); |
| 1715 | 1713 | |
| ... | ... | @@ -1729,7 +1727,7 @@ fn analyzeBodyInner( |
| 1729 | 1727 | .needed_comptime_reason = "condition in comptime branch must be comptime-known", |
| 1730 | 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; | |
| 1733 | 1731 | |
| 1734 | 1732 | try sema.maybeErrorUnwrapCondbr(block, inline_body, extra.data.condition, cond_src); |
| 1735 | 1733 | const old_runtime_index = block.runtime_index; |
| ... | ... | @@ -1882,10 +1880,10 @@ pub fn toConstString( |
| 1882 | 1880 | air_inst: Air.Inst.Ref, |
| 1883 | 1881 | reason: NeededComptimeReason, |
| 1884 | 1882 | ) ![]u8 { |
| 1885 | const wanted_type = Type.slice_const_u8; | |
| 1886 | const coerced_inst = try sema.coerce(block, wanted_type, air_inst, src); | |
| 1887 | const val = try sema.resolveConstDefinedValue(block, src, coerced_inst, reason); | |
| 1888 | return val.toAllocatedBytes(wanted_type, sema.arena, sema.mod); | |
| 1883 | const coerced_inst = try sema.coerce(block, Type.slice_const_u8, air_inst, src); | |
| 1884 | const slice_val = try sema.resolveConstDefinedValue(block, src, coerced_inst, reason); | |
| 1885 | const arr_val = try sema.derefSliceAsArray(block, src, slice_val, reason); | |
| 1886 | return arr_val.toAllocatedBytes(arr_val.typeOf(sema.mod), sema.arena, sema.mod); | |
| 1889 | 1887 | } |
| 1890 | 1888 | |
| 1891 | 1889 | pub fn resolveConstStringIntern( |
| ... | ... | @@ -2180,13 +2178,9 @@ fn resolveInstConst( |
| 2180 | 2178 | src: LazySrcLoc, |
| 2181 | 2179 | zir_ref: Zir.Inst.Ref, |
| 2182 | 2180 | reason: NeededComptimeReason, |
| 2183 | ) CompileError!TypedValue { | |
| 2181 | ) CompileError!Value { | |
| 2184 | 2182 | const air_ref = try sema.resolveInst(zir_ref); |
| 2185 | const val = try sema.resolveConstDefinedValue(block, src, air_ref, reason); | |
| 2186 | return .{ | |
| 2187 | .ty = sema.typeOf(air_ref), | |
| 2188 | .val = val, | |
| 2189 | }; | |
| 2183 | return sema.resolveConstDefinedValue(block, src, air_ref, reason); | |
| 2190 | 2184 | } |
| 2191 | 2185 | |
| 2192 | 2186 | /// Value Tag may be `undef` or `variable`. |
| ... | ... | @@ -2195,7 +2189,7 @@ pub fn resolveFinalDeclValue( |
| 2195 | 2189 | block: *Block, |
| 2196 | 2190 | src: LazySrcLoc, |
| 2197 | 2191 | air_ref: Air.Inst.Ref, |
| 2198 | ) CompileError!TypedValue { | |
| 2192 | ) CompileError!Value { | |
| 2199 | 2193 | const val = try sema.resolveValueAllowVariables(air_ref) orelse { |
| 2200 | 2194 | return sema.failWithNeededComptime(block, src, .{ |
| 2201 | 2195 | .needed_comptime_reason = "global variable initializer must be comptime-known", |
| ... | ... | @@ -2205,10 +2199,7 @@ pub fn resolveFinalDeclValue( |
| 2205 | 2199 | if (val.canMutateComptimeVarState(sema.mod)) { |
| 2206 | 2200 | return sema.fail(block, src, "global variable contains reference to comptime var", .{}); |
| 2207 | 2201 | } |
| 2208 | return .{ | |
| 2209 | .ty = sema.typeOf(air_ref), | |
| 2210 | .val = val, | |
| 2211 | }; | |
| 2202 | return val; | |
| 2212 | 2203 | } |
| 2213 | 2204 | |
| 2214 | 2205 | fn 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 | 2272 | if (int_ty.zigTypeTag(mod) == .Vector) { |
| 2282 | 2273 | const msg = msg: { |
| 2283 | 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 | 2277 | errdefer msg.destroy(sema.gpa); |
| 2287 | 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 | 2281 | return sema.failWithOwnedErrorMsg(block, msg); |
| 2291 | 2282 | } |
| 2292 | 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 | } |
| 2296 | 2287 | |
| ... | ... | @@ -2826,10 +2817,14 @@ fn zirStructDecl( |
| 2826 | 2817 | }); |
| 2827 | 2818 | errdefer wip_ty.cancel(ip); |
| 2828 | 2819 | |
| 2829 | const new_decl_index = try sema.createAnonymousDeclTypeNamed(block, src, .{ | |
| 2830 | .ty = Type.type, | |
| 2831 | .val = Value.fromInterned(wip_ty.index), | |
| 2832 | }, small.name_strategy, "struct", inst); | |
| 2820 | const new_decl_index = try sema.createAnonymousDeclTypeNamed( | |
| 2821 | block, | |
| 2822 | src, | |
| 2823 | Value.fromInterned(wip_ty.index), | |
| 2824 | small.name_strategy, | |
| 2825 | "struct", | |
| 2826 | inst, | |
| 2827 | ); | |
| 2833 | 2828 | mod.declPtr(new_decl_index).owns_tv = true; |
| 2834 | 2829 | errdefer mod.abortAnonDecl(new_decl_index); |
| 2835 | 2830 | |
| ... | ... | @@ -2862,7 +2857,7 @@ fn createAnonymousDeclTypeNamed( |
| 2862 | 2857 | sema: *Sema, |
| 2863 | 2858 | block: *Block, |
| 2864 | 2859 | src: LazySrcLoc, |
| 2865 | typed_value: TypedValue, | |
| 2860 | val: Value, | |
| 2866 | 2861 | name_strategy: Zir.Inst.NameStrategy, |
| 2867 | 2862 | anon_prefix: []const u8, |
| 2868 | 2863 | inst: ?Zir.Inst.Index, |
| ... | ... | @@ -2888,12 +2883,12 @@ fn createAnonymousDeclTypeNamed( |
| 2888 | 2883 | const name = mod.intern_pool.getOrPutStringFmt(gpa, "{}__{s}_{d}", .{ |
| 2889 | 2884 | src_decl.name.fmt(&mod.intern_pool), anon_prefix, @intFromEnum(new_decl_index), |
| 2890 | 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 | 2887 | return new_decl_index; |
| 2893 | 2888 | }, |
| 2894 | 2889 | .parent => { |
| 2895 | 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 | 2892 | return new_decl_index; |
| 2898 | 2893 | }, |
| 2899 | 2894 | .func => { |
| ... | ... | @@ -2916,10 +2911,10 @@ fn createAnonymousDeclTypeNamed( |
| 2916 | 2911 | // function and the name doesn't matter since it will later |
| 2917 | 2912 | // result in a compile error. |
| 2918 | 2913 | 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); | |
| 2920 | 2915 | |
| 2921 | 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)}); | |
| 2923 | 2918 | |
| 2924 | 2919 | arg_i += 1; |
| 2925 | 2920 | continue; |
| ... | ... | @@ -2929,7 +2924,7 @@ fn createAnonymousDeclTypeNamed( |
| 2929 | 2924 | |
| 2930 | 2925 | try writer.writeByte(')'); |
| 2931 | 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 | 2928 | return new_decl_index; |
| 2934 | 2929 | }, |
| 2935 | 2930 | .dbg_var => { |
| ... | ... | @@ -2944,12 +2939,12 @@ fn createAnonymousDeclTypeNamed( |
| 2944 | 2939 | src_decl.name.fmt(&mod.intern_pool), zir_data[i].str_op.getStr(sema.code), |
| 2945 | 2940 | }); |
| 2946 | 2941 | |
| 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 | 2943 | return new_decl_index; |
| 2949 | 2944 | }, |
| 2950 | 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 | 3044 | |
| 3050 | 3045 | errdefer if (!done) wip_ty.cancel(ip); |
| 3051 | 3046 | |
| 3052 | const new_decl_index = try sema.createAnonymousDeclTypeNamed(block, src, .{ | |
| 3053 | .ty = Type.type, | |
| 3054 | .val = Value.fromInterned(wip_ty.index), | |
| 3055 | }, small.name_strategy, "enum", inst); | |
| 3047 | const new_decl_index = try sema.createAnonymousDeclTypeNamed( | |
| 3048 | block, | |
| 3049 | src, | |
| 3050 | Value.fromInterned(wip_ty.index), | |
| 3051 | small.name_strategy, | |
| 3052 | "enum", | |
| 3053 | inst, | |
| 3054 | ); | |
| 3056 | 3055 | const new_decl = mod.declPtr(new_decl_index); |
| 3057 | 3056 | new_decl.owns_tv = true; |
| 3058 | 3057 | errdefer if (!done) mod.abortAnonDecl(new_decl_index); |
| ... | ... | @@ -3187,7 +3186,7 @@ fn zirEnumDecl( |
| 3187 | 3186 | }).lazy; |
| 3188 | 3187 | const other_field_src = mod.fieldSrcLoc(new_decl_index, .{ .index = conflict.prev_field_idx }).lazy; |
| 3189 | 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 | 3190 | errdefer msg.destroy(gpa); |
| 3192 | 3191 | try sema.errNote(block, other_field_src, msg, "other occurrence here", .{}); |
| 3193 | 3192 | break :msg msg; |
| ... | ... | @@ -3207,7 +3206,7 @@ fn zirEnumDecl( |
| 3207 | 3206 | const field_src = mod.fieldSrcLoc(new_decl_index, .{ .index = field_i }).lazy; |
| 3208 | 3207 | const other_field_src = mod.fieldSrcLoc(new_decl_index, .{ .index = conflict.prev_field_idx }).lazy; |
| 3209 | 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 | 3210 | errdefer msg.destroy(gpa); |
| 3212 | 3211 | try sema.errNote(block, other_field_src, msg, "other occurrence here", .{}); |
| 3213 | 3212 | break :msg msg; |
| ... | ... | @@ -3229,7 +3228,7 @@ fn zirEnumDecl( |
| 3229 | 3228 | .range = if (has_tag_value) .value else .name, |
| 3230 | 3229 | }).lazy; |
| 3231 | 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 | 3233 | return sema.failWithOwnedErrorMsg(block, msg); |
| 3235 | 3234 | } |
| ... | ... | @@ -3316,10 +3315,14 @@ fn zirUnionDecl( |
| 3316 | 3315 | }); |
| 3317 | 3316 | errdefer wip_ty.cancel(ip); |
| 3318 | 3317 | |
| 3319 | const new_decl_index = try sema.createAnonymousDeclTypeNamed(block, src, .{ | |
| 3320 | .ty = Type.type, | |
| 3321 | .val = Value.fromInterned(wip_ty.index), | |
| 3322 | }, small.name_strategy, "union", inst); | |
| 3318 | const new_decl_index = try sema.createAnonymousDeclTypeNamed( | |
| 3319 | block, | |
| 3320 | src, | |
| 3321 | Value.fromInterned(wip_ty.index), | |
| 3322 | small.name_strategy, | |
| 3323 | "union", | |
| 3324 | inst, | |
| 3325 | ); | |
| 3323 | 3326 | mod.declPtr(new_decl_index).owns_tv = true; |
| 3324 | 3327 | errdefer mod.abortAnonDecl(new_decl_index); |
| 3325 | 3328 | |
| ... | ... | @@ -3400,10 +3403,14 @@ fn zirOpaqueDecl( |
| 3400 | 3403 | }; |
| 3401 | 3404 | errdefer wip_ty.cancel(ip); |
| 3402 | 3405 | |
| 3403 | const new_decl_index = try sema.createAnonymousDeclTypeNamed(block, src, .{ | |
| 3404 | .ty = Type.type, | |
| 3405 | .val = Value.fromInterned(wip_ty.index), | |
| 3406 | }, small.name_strategy, "opaque", inst); | |
| 3406 | const new_decl_index = try sema.createAnonymousDeclTypeNamed( | |
| 3407 | block, | |
| 3408 | src, | |
| 3409 | Value.fromInterned(wip_ty.index), | |
| 3410 | small.name_strategy, | |
| 3411 | "opaque", | |
| 3412 | inst, | |
| 3413 | ); | |
| 3407 | 3414 | mod.declPtr(new_decl_index).owns_tv = true; |
| 3408 | 3415 | errdefer mod.abortAnonDecl(new_decl_index); |
| 3409 | 3416 | |
| ... | ... | @@ -3463,10 +3470,14 @@ fn zirErrorSetDecl( |
| 3463 | 3470 | |
| 3464 | 3471 | const error_set_ty = try mod.errorSetFromUnsortedNames(names.keys()); |
| 3465 | 3472 | |
| 3466 | const new_decl_index = try sema.createAnonymousDeclTypeNamed(block, src, .{ | |
| 3467 | .ty = Type.type, | |
| 3468 | .val = error_set_ty.toValue(), | |
| 3469 | }, name_strategy, "error", inst); | |
| 3473 | const new_decl_index = try sema.createAnonymousDeclTypeNamed( | |
| 3474 | block, | |
| 3475 | src, | |
| 3476 | error_set_ty.toValue(), | |
| 3477 | name_strategy, | |
| 3478 | "error", | |
| 3479 | inst, | |
| 3480 | ); | |
| 3470 | 3481 | const new_decl = mod.declPtr(new_decl_index); |
| 3471 | 3482 | new_decl.owns_tv = true; |
| 3472 | 3483 | errdefer mod.abortAnonDecl(new_decl_index); |
| ... | ... | @@ -3762,10 +3773,10 @@ fn zirMakePtrConst(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro |
| 3762 | 3773 | if (!sema.isComptimeMutablePtr(ptr_val)) break :already_ct; |
| 3763 | 3774 | const alloc_index = mod.intern_pool.indexToKey(ptr_val.toIntern()).ptr.addr.comptime_alloc; |
| 3764 | 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 | 3777 | if (Value.fromInterned(interned).canMutateComptimeVarState(mod)) { |
| 3767 | 3778 | // Preserve the comptime alloc, just make the pointer const. |
| 3768 | ct_alloc.val = Value.fromInterned(interned); | |
| 3779 | ct_alloc.val = .{ .interned = interned }; | |
| 3769 | 3780 | ct_alloc.is_const = true; |
| 3770 | 3781 | return sema.makePtrConst(block, alloc); |
| 3771 | 3782 | } else { |
| ... | ... | @@ -4030,7 +4041,7 @@ fn finishResolveComptimeKnownAllocPtr( |
| 4030 | 4041 | const alloc_index = existing_comptime_alloc orelse a: { |
| 4031 | 4042 | const idx = try sema.newComptimeAlloc(block, alloc_ty.childType(zcu), alloc_ty.ptrAlignment(zcu)); |
| 4032 | 4043 | const alloc = sema.getComptimeAlloc(idx); |
| 4033 | alloc.val = Value.fromInterned(result_val); | |
| 4044 | alloc.val = .{ .interned = result_val }; | |
| 4034 | 4045 | break :a idx; |
| 4035 | 4046 | }; |
| 4036 | 4047 | sema.getComptimeAlloc(alloc_index).is_const = true; |
| ... | ... | @@ -4193,7 +4204,7 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com |
| 4193 | 4204 | .anon_decl => |a| a.val, |
| 4194 | 4205 | .comptime_alloc => |i| val: { |
| 4195 | 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 | 4209 | else => unreachable, |
| 4199 | 4210 | }; |
| ... | ... | @@ -4370,10 +4381,10 @@ fn zirForLen(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. |
| 4370 | 4381 | .input_index = len_idx, |
| 4371 | 4382 | } }; |
| 4372 | 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 | 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 | 4389 | break :msg msg; |
| 4379 | 4390 | }; |
| ... | ... | @@ -5597,7 +5608,7 @@ fn storeToInferredAllocComptime( |
| 5597 | 5608 | } }); |
| 5598 | 5609 | } else { |
| 5599 | 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 | 5612 | iac.ptr = try zcu.intern(.{ .ptr = .{ |
| 5602 | 5613 | .ty = alloc_ty.toIntern(), |
| 5603 | 5614 | .addr = .{ .comptime_alloc = alloc_index }, |
| ... | ... | @@ -5783,7 +5794,7 @@ fn zirCompileLog( |
| 5783 | 5794 | const arg_ty = sema.typeOf(arg); |
| 5784 | 5795 | if (try sema.resolveValueResolveLazy(arg)) |val| { |
| 5785 | 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 | 5799 | } else { |
| 5789 | 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 | 6406 | const options = try sema.resolveExportOptions(block, options_src, extra.options); |
| 6396 | 6407 | if (options.linkage == .internal) |
| 6397 | 6408 | return; |
| 6398 | if (operand.val.getFunction(mod)) |function| { | |
| 6409 | if (operand.getFunction(mod)) |function| { | |
| 6399 | 6410 | const decl_index = function.owner_decl; |
| 6400 | 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 | 6416 | .src = src, |
| 6406 | 6417 | .owner_decl = sema.owner_decl_index, |
| 6407 | 6418 | .src_decl = block.src_decl, |
| 6408 | .exported = .{ .value = operand.val.toIntern() }, | |
| 6419 | .exported = .{ .value = operand.toIntern() }, | |
| 6409 | 6420 | .status = .in_progress, |
| 6410 | 6421 | }); |
| 6411 | 6422 | } |
| ... | ... | @@ -6425,16 +6436,17 @@ pub fn analyzeExport( |
| 6425 | 6436 | |
| 6426 | 6437 | try mod.ensureDeclAnalyzed(exported_decl_index); |
| 6427 | 6438 | const exported_decl = mod.declPtr(exported_decl_index); |
| 6439 | const export_ty = exported_decl.typeOf(mod); | |
| 6428 | 6440 | |
| 6429 | if (!try sema.validateExternType(exported_decl.ty, .other)) { | |
| 6441 | if (!try sema.validateExternType(export_ty, .other)) { | |
| 6430 | 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 | 6444 | errdefer msg.destroy(gpa); |
| 6433 | 6445 | |
| 6434 | 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); | |
| 6436 | 6448 | |
| 6437 | try sema.addDeclaredHereNote(msg, exported_decl.ty); | |
| 6449 | try sema.addDeclaredHereNote(msg, export_ty); | |
| 6438 | 6450 | break :msg msg; |
| 6439 | 6451 | }; |
| 6440 | 6452 | return sema.failWithOwnedErrorMsg(block, msg); |
| ... | ... | @@ -6445,8 +6457,6 @@ pub fn analyzeExport( |
| 6445 | 6457 | return sema.fail(block, src, "export target cannot be extern", .{}); |
| 6446 | 6458 | } |
| 6447 | 6459 | |
| 6448 | // This decl is alive no matter what, since it's being exported | |
| 6449 | try mod.markDeclAlive(exported_decl); | |
| 6450 | 6460 | try sema.maybeQueueFuncBodyAnalysis(exported_decl_index); |
| 6451 | 6461 | |
| 6452 | 6462 | try addExport(mod, .{ |
| ... | ... | @@ -6503,7 +6513,7 @@ fn zirSetAlignStack(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Inst |
| 6503 | 6513 | } |
| 6504 | 6514 | |
| 6505 | 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 | 6517 | .Naked => return sema.fail(block, src, "@setAlignStack in naked function", .{}), |
| 6508 | 6518 | .Inline => return sema.fail(block, src, "@setAlignStack in inline function", .{}), |
| 6509 | 6519 | else => if (block.inlining != null) { |
| ... | ... | @@ -7692,7 +7702,7 @@ fn analyzeCall( |
| 7692 | 7702 | // comptime memory is mutated. |
| 7693 | 7703 | const memoized_arg_values = try sema.arena.alloc(InternPool.Index, func_ty_info.param_types.len); |
| 7694 | 7704 | |
| 7695 | const owner_info = mod.typeToFunc(fn_owner_decl.ty).?; | |
| 7705 | const owner_info = mod.typeToFunc(fn_owner_decl.typeOf(mod)).?; | |
| 7696 | 7706 | const new_param_types = try sema.arena.alloc(InternPool.Index, owner_info.param_types.len); |
| 7697 | 7707 | var new_fn_info: InternPool.GetFuncTypeKey = .{ |
| 7698 | 7708 | .param_types = new_param_types, |
| ... | ... | @@ -7835,7 +7845,7 @@ fn analyzeCall( |
| 7835 | 7845 | |
| 7836 | 7846 | if (is_comptime_call) { |
| 7837 | 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(); | |
| 7839 | 7849 | |
| 7840 | 7850 | // Transform ad-hoc inferred error set types into concrete error sets. |
| 7841 | 7851 | const result_transformed = try sema.resolveAdHocInferredErrorSet(block, call_src, result_interned); |
| ... | ... | @@ -7856,8 +7866,7 @@ fn analyzeCall( |
| 7856 | 7866 | } |
| 7857 | 7867 | |
| 7858 | 7868 | if (try sema.resolveValue(result)) |result_val| { |
| 7859 | const result_interned = try result_val.intern2(sema.fn_ret_ty, mod); | |
| 7860 | const result_transformed = try sema.resolveAdHocInferredErrorSet(block, call_src, result_interned); | |
| 7869 | const result_transformed = try sema.resolveAdHocInferredErrorSet(block, call_src, result_val.toIntern()); | |
| 7861 | 7870 | break :res2 Air.internedToRef(result_transformed); |
| 7862 | 7871 | } |
| 7863 | 7872 | |
| ... | ... | @@ -7960,9 +7969,9 @@ fn handleTailCall(sema: *Sema, block: *Block, call_src: LazySrcLoc, func_ty: Typ |
| 7960 | 7969 | }); |
| 7961 | 7970 | } |
| 7962 | 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 | 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 | 7977 | _ = try block.addUnOp(.ret, result); |
| ... | ... | @@ -8042,7 +8051,7 @@ fn analyzeInlineCallArg( |
| 8042 | 8051 | // when the hash function is called. |
| 8043 | 8052 | const resolved_arg_val = try ics.caller().resolveLazyValue(arg_val); |
| 8044 | 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 | 8055 | } else { |
| 8047 | 8056 | ics.callee().inst_map.putAssumeCapacityNoClobber(inst, casted_arg); |
| 8048 | 8057 | } |
| ... | ... | @@ -8081,7 +8090,7 @@ fn analyzeInlineCallArg( |
| 8081 | 8090 | // when the hash function is called. |
| 8082 | 8091 | const resolved_arg_val = try ics.caller().resolveLazyValue(arg_val); |
| 8083 | 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 | 8094 | } else { |
| 8086 | 8095 | if (zir_tags[@intFromEnum(inst)] == .param_anytype_comptime) { |
| 8087 | 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 | 8880 | return Air.internedToRef((try mod.getCoerced(int_val, dest_ty)).toIntern()); |
| 8872 | 8881 | } |
| 8873 | 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 | 8886 | if (int_val.isUndef(mod)) { |
| ... | ... | @@ -8879,7 +8888,7 @@ fn zirEnumFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 8879 | 8888 | } |
| 8880 | 8889 | if (!(try sema.enumHasInt(dest_ty, int_val))) { |
| 8881 | 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 | 8894 | return Air.internedToRef((try mod.getCoerced(int_val, dest_ty)).toIntern()); |
| ... | ... | @@ -13925,7 +13934,7 @@ fn zirShl( |
| 13925 | 13934 | const rhs_elem = try rhs_val.elemValue(mod, i); |
| 13926 | 13935 | if (rhs_elem.compareHetero(.gte, bit_value, mod)) { |
| 13927 | 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 | 13938 | i, |
| 13930 | 13939 | scalar_ty.fmt(mod), |
| 13931 | 13940 | }); |
| ... | ... | @@ -13933,7 +13942,7 @@ fn zirShl( |
| 13933 | 13942 | } |
| 13934 | 13943 | } else if (rhs_val.compareHetero(.gte, bit_value, mod)) { |
| 13935 | 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 | 13946 | scalar_ty.fmt(mod), |
| 13938 | 13947 | }); |
| 13939 | 13948 | } |
| ... | ... | @@ -13944,14 +13953,14 @@ fn zirShl( |
| 13944 | 13953 | const rhs_elem = try rhs_val.elemValue(mod, i); |
| 13945 | 13954 | if (rhs_elem.compareHetero(.lt, try mod.intValue(scalar_rhs_ty, 0), mod)) { |
| 13946 | 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 | 13957 | i, |
| 13949 | 13958 | }); |
| 13950 | 13959 | } |
| 13951 | 13960 | } |
| 13952 | 13961 | } else if (rhs_val.compareHetero(.lt, try mod.intValue(rhs_ty, 0), mod)) { |
| 13953 | 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 | 14099 | const rhs_elem = try rhs_val.elemValue(mod, i); |
| 14091 | 14100 | if (rhs_elem.compareHetero(.gte, bit_value, mod)) { |
| 14092 | 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 | 14103 | i, |
| 14095 | 14104 | scalar_ty.fmt(mod), |
| 14096 | 14105 | }); |
| ... | ... | @@ -14098,7 +14107,7 @@ fn zirShr( |
| 14098 | 14107 | } |
| 14099 | 14108 | } else if (rhs_val.compareHetero(.gte, bit_value, mod)) { |
| 14100 | 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 | 14111 | scalar_ty.fmt(mod), |
| 14103 | 14112 | }); |
| 14104 | 14113 | } |
| ... | ... | @@ -14109,14 +14118,14 @@ fn zirShr( |
| 14109 | 14118 | const rhs_elem = try rhs_val.elemValue(mod, i); |
| 14110 | 14119 | if (rhs_elem.compareHetero(.lt, try mod.intValue(rhs_ty.childType(mod), 0), mod)) { |
| 14111 | 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 | 14122 | i, |
| 14114 | 14123 | }); |
| 14115 | 14124 | } |
| 14116 | 14125 | } |
| 14117 | 14126 | } else if (rhs_val.compareHetero(.lt, try mod.intValue(rhs_ty, 0), mod)) { |
| 14118 | 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 | 14131 | if (maybe_lhs_val) |lhs_val| { |
| ... | ... | @@ -14270,7 +14279,7 @@ fn zirBitNot(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. |
| 14270 | 14279 | const elems = try sema.arena.alloc(InternPool.Index, vec_len); |
| 14271 | 14280 | for (elems, 0..) |*elem, i| { |
| 14272 | 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 | 14284 | return Air.internedToRef((try mod.intern(.{ .aggregate = .{ |
| 14276 | 14285 | .ty = operand_type.toIntern(), |
| ... | ... | @@ -14499,12 +14508,16 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 14499 | 14508 | else => unreachable, |
| 14500 | 14509 | }) |rhs_val| { |
| 14501 | 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 | 14514 | else |
| 14504 | 14515 | lhs_val; |
| 14505 | 14516 | |
| 14506 | 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 | 14521 | else |
| 14509 | 14522 | rhs_val; |
| 14510 | 14523 | |
| ... | ... | @@ -14521,7 +14534,7 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 14521 | 14534 | } }; |
| 14522 | 14535 | const coerced_elem_val_inst = try sema.coerce(block, resolved_elem_ty, elem_val_inst, operand_src); |
| 14523 | 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 | 14539 | while (elem_i < result_len) : (elem_i += 1) { |
| 14527 | 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 | 14547 | } }; |
| 14535 | 14548 | const coerced_elem_val_inst = try sema.coerce(block, resolved_elem_ty, elem_val_inst, operand_src); |
| 14536 | 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 | 14552 | return sema.addConstantMaybeRef(try mod.intern(.{ .aggregate = .{ |
| 14540 | 14553 | .ty = result_ty.toIntern(), |
| ... | ... | @@ -14624,10 +14637,7 @@ fn getArrayCatInfo(sema: *Sema, block: *Block, src: LazySrcLoc, operand: Air.Ins |
| 14624 | 14637 | .Pointer => { |
| 14625 | 14638 | const ptr_info = operand_ty.ptrInfo(mod); |
| 14626 | 14639 | switch (ptr_info.flags.size) { |
| 14627 | // TODO: in the Many case here this should only work if the type | |
| 14628 | // has a sentinel, and this code should compute the length based | |
| 14629 | // on the sentinel value. | |
| 14630 | .Slice, .Many => { | |
| 14640 | .Slice => { | |
| 14631 | 14641 | const val = try sema.resolveConstDefinedValue(block, src, operand, .{ |
| 14632 | 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 | 14647 | .none => null, |
| 14638 | 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 | 14653 | .One => { |
| ... | ... | @@ -14645,7 +14655,7 @@ fn getArrayCatInfo(sema: *Sema, block: *Block, src: LazySrcLoc, operand: Air.Ins |
| 14645 | 14655 | return Type.fromInterned(ptr_info.child).arrayInfo(mod); |
| 14646 | 14656 | } |
| 14647 | 14657 | }, |
| 14648 | .C => {}, | |
| 14658 | .C, .Many => {}, | |
| 14649 | 14659 | } |
| 14650 | 14660 | }, |
| 14651 | 14661 | .Struct => { |
| ... | ... | @@ -14831,9 +14841,11 @@ fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 14831 | 14841 | const ptr_addrspace = if (lhs_ty.zigTypeTag(mod) == .Pointer) lhs_ty.ptrAddressSpace(mod) else null; |
| 14832 | 14842 | const lhs_len = try sema.usizeCast(block, lhs_src, lhs_info.len); |
| 14833 | 14843 | |
| 14834 | if (try sema.resolveDefinedValue(block, lhs_src, lhs)) |lhs_val| { | |
| 14844 | if (try sema.resolveDefinedValue(block, lhs_src, lhs)) |lhs_val| ct: { | |
| 14835 | 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 | 14849 | else |
| 14838 | 14850 | lhs_val; |
| 14839 | 14851 | |
| ... | ... | @@ -14841,7 +14853,7 @@ fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 14841 | 14853 | // Optimization for the common pattern of a single element repeated N times, such |
| 14842 | 14854 | // as zero-filling a byte array. |
| 14843 | 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 | 14857 | break :v try mod.intern(.{ .aggregate = .{ |
| 14846 | 14858 | .ty = result_ty.toIntern(), |
| 14847 | 14859 | .storage = .{ .repeated_elem = elem_val.toIntern() }, |
| ... | ... | @@ -14853,7 +14865,7 @@ fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 14853 | 14865 | while (elem_i < result_len) { |
| 14854 | 14866 | var lhs_i: usize = 0; |
| 14855 | 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 | 14869 | element_vals[elem_i] = elem_val.toIntern(); |
| 14858 | 14870 | elem_i += 1; |
| 14859 | 14871 | } |
| ... | ... | @@ -15034,7 +15046,7 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins |
| 15034 | 15046 | block, |
| 15035 | 15047 | src, |
| 15036 | 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 | 15825 | for (result_data, 0..) |*scalar, i| { |
| 15814 | 15826 | const lhs_elem = try lhs.elemValue(mod, i); |
| 15815 | 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 | 15830 | return Value.fromInterned((try mod.intern(.{ .aggregate = .{ |
| 15819 | 15831 | .ty = ty.toIntern(), |
| ... | ... | @@ -17753,7 +17765,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 17753 | 17765 | const info = ty.intInfo(mod); |
| 17754 | 17766 | const field_values = .{ |
| 17755 | 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 | 17769 | // bits: u16, |
| 17758 | 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 | 17835 | |
| 17824 | 17836 | const field_values = .{ |
| 17825 | 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 | 17839 | // is_const: bool, |
| 17828 | 17840 | Value.makeBool(info.flags.is_const).toIntern(), |
| 17829 | 17841 | // is_volatile: bool, |
| ... | ... | @@ -17831,7 +17843,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 17831 | 17843 | // alignment: comptime_int, |
| 17832 | 17844 | alignment.toIntern(), |
| 17833 | 17845 | // 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 | 17847 | // child: type, |
| 17836 | 17848 | info.child, |
| 17837 | 17849 | // is_allowzero: bool, |
| ... | ... | @@ -19975,8 +19987,8 @@ fn unionInit( |
| 19975 | 19987 | const tag_val = try mod.enumValueFieldIndex(tag_ty, field_index); |
| 19976 | 19988 | return Air.internedToRef((try mod.intern(.{ .un = .{ |
| 19977 | 19989 | .ty = union_ty.toIntern(), |
| 19978 | .tag = try tag_val.intern(tag_ty, mod), | |
| 19979 | .val = try init_val.intern(field_ty, mod), | |
| 19990 | .tag = tag_val.toIntern(), | |
| 19991 | .val = init_val.toIntern(), | |
| 19980 | 19992 | } }))); |
| 19981 | 19993 | } |
| 19982 | 19994 | |
| ... | ... | @@ -20099,8 +20111,8 @@ fn zirStructInit( |
| 20099 | 20111 | if (try sema.resolveValue(init_inst)) |val| { |
| 20100 | 20112 | const struct_val = Value.fromInterned((try mod.intern(.{ .un = .{ |
| 20101 | 20113 | .ty = resolved_ty.toIntern(), |
| 20102 | .tag = try tag_val.intern(tag_ty, mod), | |
| 20103 | .val = try val.intern(field_ty, mod), | |
| 20114 | .tag = tag_val.toIntern(), | |
| 20115 | .val = val.toIntern(), | |
| 20104 | 20116 | } }))); |
| 20105 | 20117 | const final_val_inst = try sema.coerce(block, result_ty, Air.internedToRef(struct_val.toIntern()), src); |
| 20106 | 20118 | const final_val = (try sema.resolveValue(final_val_inst)).?; |
| ... | ... | @@ -20400,7 +20412,7 @@ fn structInitAnon( |
| 20400 | 20412 | return sema.failWithOwnedErrorMsg(block, msg); |
| 20401 | 20413 | } |
| 20402 | 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 | 20416 | } else { |
| 20405 | 20417 | field_val.* = .none; |
| 20406 | 20418 | runtime_index = @intCast(i_usize); |
| ... | ... | @@ -20577,13 +20589,9 @@ fn zirArrayInit( |
| 20577 | 20589 | |
| 20578 | 20590 | const runtime_index = opt_runtime_index orelse { |
| 20579 | 20591 | const elem_vals = try sema.arena.alloc(InternPool.Index, resolved_args.len); |
| 20580 | for (elem_vals, resolved_args, 0..) |*val, arg, i| { | |
| 20581 | const elem_ty = if (is_tuple) | |
| 20582 | array_ty.structFieldType(i, mod) | |
| 20583 | else | |
| 20584 | array_ty.elemType2(mod); | |
| 20592 | for (elem_vals, resolved_args) |*val, arg| { | |
| 20585 | 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 | 20596 | const arr_val = try mod.intern(.{ .aggregate = .{ |
| 20589 | 20597 | .ty = array_ty.toIntern(), |
| ... | ... | @@ -20998,7 +21006,7 @@ fn maybeConstantUnaryMath( |
| 20998 | 21006 | const elems = try sema.arena.alloc(InternPool.Index, vec_len); |
| 20999 | 21007 | for (elems, 0..) |*elem, i| { |
| 21000 | 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 | 21011 | return Air.internedToRef((try mod.intern(.{ .aggregate = .{ |
| 21004 | 21012 | .ty = result_ty.toIntern(), |
| ... | ... | @@ -21086,7 +21094,7 @@ fn zirTagName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 21086 | 21094 | const enum_decl = mod.declPtr(enum_decl_index); |
| 21087 | 21095 | const msg = msg: { |
| 21088 | 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 | 21099 | errdefer msg.destroy(sema.gpa); |
| 21092 | 21100 | try mod.errNoteNonLazy(enum_decl.srcLoc(mod), msg, "declared here", .{}); |
| ... | ... | @@ -21129,7 +21137,9 @@ fn zirReify( |
| 21129 | 21137 | .needed_comptime_reason = "operand to @Type must be comptime-known", |
| 21130 | 21138 | }); |
| 21131 | 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 | 21143 | const tag_index = type_info_ty.unionTagFieldIndex(Value.fromInterned(union_val.tag), mod).?; |
| 21134 | 21144 | switch (@as(std.builtin.TypeId, @enumFromInt(tag_index))) { |
| 21135 | 21145 | .Type => return .type_type, |
| ... | ... | @@ -21370,11 +21380,15 @@ fn zirReify( |
| 21370 | 21380 | const payload_val = Value.fromInterned(union_val.val).optionalValue(mod) orelse |
| 21371 | 21381 | return Air.internedToRef(Type.anyerror.toIntern()); |
| 21372 | 21382 | |
| 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 | 21388 | var names: InferredErrorSet.NameMap = .{}; |
| 21375 | 21389 | try names.ensureUnusedCapacity(sema.arena, len); |
| 21376 | 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 | 21392 | const elem_struct_type = ip.loadStructType(ip.typeOf(elem_val.toIntern())); |
| 21379 | 21393 | const name_val = try elem_val.fieldValue(mod, elem_struct_type.nameIndex( |
| 21380 | 21394 | ip, |
| ... | ... | @@ -21422,7 +21436,7 @@ fn zirReify( |
| 21422 | 21436 | const layout = mod.toEnum(std.builtin.Type.ContainerLayout, layout_val); |
| 21423 | 21437 | |
| 21424 | 21438 | // Decls |
| 21425 | if (decls_val.sliceLen(mod) > 0) { | |
| 21439 | if (try decls_val.sliceLen(sema) > 0) { | |
| 21426 | 21440 | return sema.fail(block, src, "reified structs must have no decls", .{}); |
| 21427 | 21441 | } |
| 21428 | 21442 | |
| ... | ... | @@ -21430,7 +21444,11 @@ fn zirReify( |
| 21430 | 21444 | return sema.fail(block, src, "non-packed struct does not support backing integer type", .{}); |
| 21431 | 21445 | } |
| 21432 | 21446 | |
| 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 | 21453 | .Enum => { |
| 21436 | 21454 | const struct_type = ip.loadStructType(ip.typeOf(union_val.val)); |
| ... | ... | @@ -21451,11 +21469,15 @@ fn zirReify( |
| 21451 | 21469 | try ip.getOrPutString(gpa, "is_exhaustive"), |
| 21452 | 21470 | ).?); |
| 21453 | 21471 | |
| 21454 | if (decls_val.sliceLen(mod) > 0) { | |
| 21472 | if (try decls_val.sliceLen(sema) > 0) { | |
| 21455 | 21473 | return sema.fail(block, src, "reified enums must have no decls", .{}); |
| 21456 | 21474 | } |
| 21457 | 21475 | |
| 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 | 21482 | .Opaque => { |
| 21461 | 21483 | const struct_type = ip.loadStructType(ip.typeOf(union_val.val)); |
| ... | ... | @@ -21465,7 +21487,7 @@ fn zirReify( |
| 21465 | 21487 | ).?); |
| 21466 | 21488 | |
| 21467 | 21489 | // Decls |
| 21468 | if (decls_val.sliceLen(mod) > 0) { | |
| 21490 | if (try decls_val.sliceLen(sema) > 0) { | |
| 21469 | 21491 | return sema.fail(block, src, "reified opaque must have no decls", .{}); |
| 21470 | 21492 | } |
| 21471 | 21493 | |
| ... | ... | @@ -21480,10 +21502,14 @@ fn zirReify( |
| 21480 | 21502 | }; |
| 21481 | 21503 | errdefer wip_ty.cancel(ip); |
| 21482 | 21504 | |
| 21483 | const new_decl_index = try sema.createAnonymousDeclTypeNamed(block, src, .{ | |
| 21484 | .ty = Type.type, | |
| 21485 | .val = Value.fromInterned(wip_ty.index), | |
| 21486 | }, name_strategy, "opaque", inst); | |
| 21505 | const new_decl_index = try sema.createAnonymousDeclTypeNamed( | |
| 21506 | block, | |
| 21507 | src, | |
| 21508 | Value.fromInterned(wip_ty.index), | |
| 21509 | name_strategy, | |
| 21510 | "opaque", | |
| 21511 | inst, | |
| 21512 | ); | |
| 21487 | 21513 | mod.declPtr(new_decl_index).owns_tv = true; |
| 21488 | 21514 | errdefer mod.abortAnonDecl(new_decl_index); |
| 21489 | 21515 | |
| ... | ... | @@ -21510,12 +21536,16 @@ fn zirReify( |
| 21510 | 21536 | try ip.getOrPutString(gpa, "decls"), |
| 21511 | 21537 | ).?); |
| 21512 | 21538 | |
| 21513 | if (decls_val.sliceLen(mod) > 0) { | |
| 21539 | if (try decls_val.sliceLen(sema) > 0) { | |
| 21514 | 21540 | return sema.fail(block, src, "reified unions must have no decls", .{}); |
| 21515 | 21541 | } |
| 21516 | 21542 | const layout = mod.toEnum(std.builtin.Type.ContainerLayout, layout_val); |
| 21517 | 21543 | |
| 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 | 21550 | .Fn => { |
| 21521 | 21551 | const struct_type = ip.loadStructType(ip.typeOf(union_val.val)); |
| ... | ... | @@ -21535,7 +21565,7 @@ fn zirReify( |
| 21535 | 21565 | ip, |
| 21536 | 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 | 21569 | ip, |
| 21540 | 21570 | try ip.getOrPutString(gpa, "params"), |
| 21541 | 21571 | ).?); |
| ... | ... | @@ -21554,12 +21584,16 @@ fn zirReify( |
| 21554 | 21584 | const return_type = return_type_val.optionalValue(mod) orelse |
| 21555 | 21585 | return sema.fail(block, src, "Type.Fn.return_type must be non-null for @Type", .{}); |
| 21556 | 21586 | |
| 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 | 21592 | const param_types = try sema.arena.alloc(InternPool.Index, args_len); |
| 21559 | 21593 | |
| 21560 | 21594 | var noalias_bits: u32 = 0; |
| 21561 | 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 | 21597 | const elem_struct_type = ip.loadStructType(ip.typeOf(elem_val.toIntern())); |
| 21564 | 21598 | const param_is_generic_val = try elem_val.fieldValue(mod, elem_struct_type.nameIndex( |
| 21565 | 21599 | ip, |
| ... | ... | @@ -21620,7 +21654,7 @@ fn reifyEnum( |
| 21620 | 21654 | |
| 21621 | 21655 | // This logic must stay in sync with the structure of `std.builtin.Type.Enum` - search for `fieldValue`. |
| 21622 | 21656 | |
| 21623 | const fields_len: u32 = @intCast(fields_val.sliceLen(mod)); | |
| 21657 | const fields_len: u32 = @intCast(fields_val.typeOf(mod).arrayLen(mod)); | |
| 21624 | 21658 | |
| 21625 | 21659 | // The validation work here is non-trivial, and it's possible the type already exists. |
| 21626 | 21660 | // 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 | 21668 | std.hash.autoHash(&hasher, fields_len); |
| 21635 | 21669 | |
| 21636 | 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); | |
| 21638 | 21672 | |
| 21639 | 21673 | const field_name_val = try field_info.fieldValue(mod, 0); |
| 21640 | 21674 | const field_value_val = try sema.resolveLazyValue(try field_info.fieldValue(mod, 1)); |
| ... | ... | @@ -21668,10 +21702,14 @@ fn reifyEnum( |
| 21668 | 21702 | return sema.fail(block, src, "Type.Enum.tag_type must be an integer type", .{}); |
| 21669 | 21703 | } |
| 21670 | 21704 | |
| 21671 | const new_decl_index = try sema.createAnonymousDeclTypeNamed(block, src, .{ | |
| 21672 | .ty = Type.type, | |
| 21673 | .val = Value.fromInterned(wip_ty.index), | |
| 21674 | }, name_strategy, "enum", inst); | |
| 21705 | const new_decl_index = try sema.createAnonymousDeclTypeNamed( | |
| 21706 | block, | |
| 21707 | src, | |
| 21708 | Value.fromInterned(wip_ty.index), | |
| 21709 | name_strategy, | |
| 21710 | "enum", | |
| 21711 | inst, | |
| 21712 | ); | |
| 21675 | 21713 | mod.declPtr(new_decl_index).owns_tv = true; |
| 21676 | 21714 | errdefer mod.abortAnonDecl(new_decl_index); |
| 21677 | 21715 | |
| ... | ... | @@ -21679,7 +21717,7 @@ fn reifyEnum( |
| 21679 | 21717 | wip_ty.setTagTy(ip, tag_ty.toIntern()); |
| 21680 | 21718 | |
| 21681 | 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); | |
| 21683 | 21721 | |
| 21684 | 21722 | const field_name_val = try field_info.fieldValue(mod, 0); |
| 21685 | 21723 | const field_value_val = try sema.resolveLazyValue(try field_info.fieldValue(mod, 1)); |
| ... | ... | @@ -21691,7 +21729,7 @@ fn reifyEnum( |
| 21691 | 21729 | // TODO: better source location |
| 21692 | 21730 | return sema.fail(block, src, "field '{}' with enumeration value '{}' is too large for backing int type '{}'", .{ |
| 21693 | 21731 | field_name.fmt(ip), |
| 21694 | field_value_val.fmtValue(Type.comptime_int, mod), | |
| 21732 | field_value_val.fmtValue(mod), | |
| 21695 | 21733 | tag_ty.fmt(mod), |
| 21696 | 21734 | }); |
| 21697 | 21735 | } |
| ... | ... | @@ -21707,7 +21745,7 @@ fn reifyEnum( |
| 21707 | 21745 | break :msg msg; |
| 21708 | 21746 | }, |
| 21709 | 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 | 21749 | errdefer msg.destroy(gpa); |
| 21712 | 21750 | _ = conflict.prev_field_idx; // TODO: this note is incorrect |
| 21713 | 21751 | try sema.errNote(block, src, msg, "other enum tag value here", .{}); |
| ... | ... | @@ -21741,7 +21779,7 @@ fn reifyUnion( |
| 21741 | 21779 | |
| 21742 | 21780 | // This logic must stay in sync with the structure of `std.builtin.Type.Union` - search for `fieldValue`. |
| 21743 | 21781 | |
| 21744 | const fields_len: u32 = @intCast(fields_val.sliceLen(mod)); | |
| 21782 | const fields_len: u32 = @intCast(fields_val.typeOf(mod).arrayLen(mod)); | |
| 21745 | 21783 | |
| 21746 | 21784 | // The validation work here is non-trivial, and it's possible the type already exists. |
| 21747 | 21785 | // 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 | 21795 | var any_aligns = false; |
| 21758 | 21796 | |
| 21759 | 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); | |
| 21761 | 21799 | |
| 21762 | 21800 | const field_name_val = try field_info.fieldValue(mod, 0); |
| 21763 | 21801 | const field_type_val = try field_info.fieldValue(mod, 1); |
| ... | ... | @@ -21811,10 +21849,14 @@ fn reifyUnion( |
| 21811 | 21849 | }; |
| 21812 | 21850 | errdefer wip_ty.cancel(ip); |
| 21813 | 21851 | |
| 21814 | const new_decl_index = try sema.createAnonymousDeclTypeNamed(block, src, .{ | |
| 21815 | .ty = Type.type, | |
| 21816 | .val = Value.fromInterned(wip_ty.index), | |
| 21817 | }, name_strategy, "union", inst); | |
| 21852 | const new_decl_index = try sema.createAnonymousDeclTypeNamed( | |
| 21853 | block, | |
| 21854 | src, | |
| 21855 | Value.fromInterned(wip_ty.index), | |
| 21856 | name_strategy, | |
| 21857 | "union", | |
| 21858 | inst, | |
| 21859 | ); | |
| 21818 | 21860 | mod.declPtr(new_decl_index).owns_tv = true; |
| 21819 | 21861 | errdefer mod.abortAnonDecl(new_decl_index); |
| 21820 | 21862 | |
| ... | ... | @@ -21833,7 +21875,7 @@ fn reifyUnion( |
| 21833 | 21875 | var seen_tags = try std.DynamicBitSetUnmanaged.initEmpty(sema.arena, tag_ty_fields_len); |
| 21834 | 21876 | |
| 21835 | 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); | |
| 21837 | 21879 | |
| 21838 | 21880 | const field_name_val = try field_info.fieldValue(mod, 0); |
| 21839 | 21881 | const field_type_val = try field_info.fieldValue(mod, 1); |
| ... | ... | @@ -21885,7 +21927,7 @@ fn reifyUnion( |
| 21885 | 21927 | try field_names.ensureTotalCapacity(sema.arena, fields_len); |
| 21886 | 21928 | |
| 21887 | 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); | |
| 21889 | 21931 | |
| 21890 | 21932 | const field_name_val = try field_info.fieldValue(mod, 0); |
| 21891 | 21933 | const field_type_val = try field_info.fieldValue(mod, 1); |
| ... | ... | @@ -21979,7 +22021,7 @@ fn reifyStruct( |
| 21979 | 22021 | |
| 21980 | 22022 | // This logic must stay in sync with the structure of `std.builtin.Type.Struct` - search for `fieldValue`. |
| 21981 | 22023 | |
| 21982 | const fields_len: u32 = @intCast(fields_val.sliceLen(mod)); | |
| 22024 | const fields_len: u32 = @intCast(fields_val.typeOf(mod).arrayLen(mod)); | |
| 21983 | 22025 | |
| 21984 | 22026 | // The validation work here is non-trivial, and it's possible the type already exists. |
| 21985 | 22027 | // 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 | 22040 | var any_aligned_fields = false; |
| 21999 | 22041 | |
| 22000 | 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); | |
| 22002 | 22044 | |
| 22003 | 22045 | const field_name_val = try field_info.fieldValue(mod, 0); |
| 22004 | 22046 | const field_type_val = try field_info.fieldValue(mod, 1); |
| ... | ... | @@ -22066,17 +22108,21 @@ fn reifyStruct( |
| 22066 | 22108 | .auto => {}, |
| 22067 | 22109 | }; |
| 22068 | 22110 | |
| 22069 | const new_decl_index = try sema.createAnonymousDeclTypeNamed(block, src, .{ | |
| 22070 | .ty = Type.type, | |
| 22071 | .val = Value.fromInterned(wip_ty.index), | |
| 22072 | }, name_strategy, "struct", inst); | |
| 22111 | const new_decl_index = try sema.createAnonymousDeclTypeNamed( | |
| 22112 | block, | |
| 22113 | src, | |
| 22114 | Value.fromInterned(wip_ty.index), | |
| 22115 | name_strategy, | |
| 22116 | "struct", | |
| 22117 | inst, | |
| 22118 | ); | |
| 22073 | 22119 | mod.declPtr(new_decl_index).owns_tv = true; |
| 22074 | 22120 | errdefer mod.abortAnonDecl(new_decl_index); |
| 22075 | 22121 | |
| 22076 | 22122 | const struct_type = ip.loadStructType(wip_ty.index); |
| 22077 | 22123 | |
| 22078 | 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); | |
| 22080 | 22126 | |
| 22081 | 22127 | const field_name_val = try field_info.fieldValue(mod, 0); |
| 22082 | 22128 | const field_type_val = try field_info.fieldValue(mod, 1); |
| ... | ... | @@ -22837,12 +22883,12 @@ fn ptrCastFull( |
| 22837 | 22883 | return sema.failWithOwnedErrorMsg(block, msg: { |
| 22838 | 22884 | const msg = if (src_info.sentinel == .none) blk: { |
| 22839 | 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 | 22888 | } else blk: { |
| 22843 | 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), | |
| 22845 | Value.fromInterned(dest_info.sentinel).fmtValue(Type.fromInterned(dest_info.child), mod), | |
| 22890 | Value.fromInterned(src_info.sentinel).fmtValue(mod), | |
| 22891 | Value.fromInterned(dest_info.sentinel).fmtValue(mod), | |
| 22846 | 22892 | }); |
| 22847 | 22893 | }; |
| 22848 | 22894 | errdefer msg.destroy(sema.gpa); |
| ... | ... | @@ -23216,7 +23262,8 @@ fn zirTruncate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 23216 | 23262 | const elems = try sema.arena.alloc(InternPool.Index, operand_ty.vectorLen(mod)); |
| 23217 | 23263 | for (elems, 0..) |*elem, i| { |
| 23218 | 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 | 23268 | return Air.internedToRef((try mod.intern(.{ .aggregate = .{ |
| 23222 | 23269 | .ty = dest_ty.toIntern(), |
| ... | ... | @@ -23330,7 +23377,7 @@ fn zirByteSwap(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 23330 | 23377 | const elems = try sema.arena.alloc(InternPool.Index, vec_len); |
| 23331 | 23378 | for (elems, 0..) |*elem, i| { |
| 23332 | 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 | 23382 | return Air.internedToRef((try mod.intern(.{ .aggregate = .{ |
| 23336 | 23383 | .ty = operand_ty.toIntern(), |
| ... | ... | @@ -23378,7 +23425,7 @@ fn zirBitReverse(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! |
| 23378 | 23425 | const elems = try sema.arena.alloc(InternPool.Index, vec_len); |
| 23379 | 23426 | for (elems, 0..) |*elem, i| { |
| 23380 | 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 | 23430 | return Air.internedToRef((try mod.intern(.{ .aggregate = .{ |
| 23384 | 23431 | .ty = operand_ty.toIntern(), |
| ... | ... | @@ -23896,11 +23943,9 @@ fn resolveExportOptions( |
| 23896 | 23943 | const visibility_src = sema.maybeOptionsSrc(block, src, "visibility"); |
| 23897 | 23944 | |
| 23898 | 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 | 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); | |
| 23904 | 23949 | |
| 23905 | 23950 | const linkage_operand = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, "linkage"), linkage_src); |
| 23906 | 23951 | const linkage_val = try sema.resolveConstDefinedValue(block, linkage_src, linkage_operand, .{ |
| ... | ... | @@ -23912,9 +23957,10 @@ fn resolveExportOptions( |
| 23912 | 23957 | const section_opt_val = try sema.resolveConstDefinedValue(block, section_src, section_operand, .{ |
| 23913 | 23958 | .needed_comptime_reason = "linksection of exported value must be comptime-known", |
| 23914 | 23959 | }); |
| 23915 | const section_ty = Type.slice_const_u8; | |
| 23916 | 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 | 23964 | else |
| 23919 | 23965 | null; |
| 23920 | 23966 | |
| ... | ... | @@ -24311,7 +24357,7 @@ fn analyzeShuffle( |
| 24311 | 24357 | } |
| 24312 | 24358 | const int = mask_elem_val.toSignedInt(mod); |
| 24313 | 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 | 24362 | return Air.internedToRef((try mod.intern(.{ .aggregate = .{ |
| 24317 | 24363 | .ty = res_ty.toIntern(), |
| ... | ... | @@ -24417,7 +24463,7 @@ fn zirSelect(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) C |
| 24417 | 24463 | for (elems, 0..) |*elem, i| { |
| 24418 | 24464 | const pred_elem_val = try pred_val.elemValue(mod, i); |
| 24419 | 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 | } |
| 24422 | 24468 | |
| 24423 | 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 | 25285 | const msg = try sema.errMsg(block, src, "non-matching @memcpy lengths", .{}); |
| 25240 | 25286 | errdefer msg.destroy(sema.gpa); |
| 25241 | 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 | 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 | 25293 | break :msg msg; |
| 25248 | 25294 | }; |
| ... | ... | @@ -25777,7 +25823,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A |
| 25777 | 25823 | } else if (extra.data.bits.has_ret_ty_ref) blk: { |
| 25778 | 25824 | const ret_ty_ref: Zir.Inst.Ref = @enumFromInt(sema.code.extra[extra_index]); |
| 25779 | 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 | 25827 | .needed_comptime_reason = "return type must be comptime-known", |
| 25782 | 25828 | }) catch |err| switch (err) { |
| 25783 | 25829 | error.GenericPoison => { |
| ... | ... | @@ -25785,8 +25831,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A |
| 25785 | 25831 | }, |
| 25786 | 25832 | else => |e| return e, |
| 25787 | 25833 | }; |
| 25788 | const ty = ret_ty_tv.val.toType(); | |
| 25789 | break :blk ty; | |
| 25834 | break :blk ret_ty_val.toType(); | |
| 25790 | 25835 | } else Type.void; |
| 25791 | 25836 | |
| 25792 | 25837 | const noalias_bits: u32 = if (extra.data.bits.has_any_noalias) blk: { |
| ... | ... | @@ -26032,10 +26077,9 @@ fn resolveExternOptions( |
| 26032 | 26077 | const thread_local_src = sema.maybeOptionsSrc(block, src, "thread_local"); |
| 26033 | 26078 | |
| 26034 | 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 | 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); | |
| 26039 | 26083 | |
| 26040 | 26084 | const library_name_inst = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, "library_name"), library_src); |
| 26041 | 26085 | const library_name_val = try sema.resolveConstDefinedValue(block, library_src, library_name_inst, .{ |
| ... | ... | @@ -26054,7 +26098,9 @@ fn resolveExternOptions( |
| 26054 | 26098 | }); |
| 26055 | 26099 | |
| 26056 | 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 | 26104 | if (library_name.len == 0) { |
| 26059 | 26105 | return sema.fail(block, library_src, "library name cannot be empty", .{}); |
| 26060 | 26106 | } |
| ... | ... | @@ -26120,9 +26166,10 @@ fn zirBuiltinExtern( |
| 26120 | 26166 | const new_decl_index = try mod.allocateNewDecl(sema.owner_decl.src_namespace, sema.owner_decl.src_node); |
| 26121 | 26167 | errdefer mod.destroyDecl(new_decl_index); |
| 26122 | 26168 | const new_decl = mod.declPtr(new_decl_index); |
| 26123 | try mod.initNewAnonDecl(new_decl_index, sema.owner_decl.src_line, .{ | |
| 26124 | .ty = Type.fromInterned(ptr_info.child), | |
| 26125 | .val = Value.fromInterned( | |
| 26169 | try mod.initNewAnonDecl( | |
| 26170 | new_decl_index, | |
| 26171 | sema.owner_decl.src_line, | |
| 26172 | Value.fromInterned( | |
| 26126 | 26173 | if (Type.fromInterned(ptr_info.child).zigTypeTag(mod) == .Fn) |
| 26127 | 26174 | try ip.getExternFunc(sema.gpa, .{ |
| 26128 | 26175 | .ty = ptr_info.child, |
| ... | ... | @@ -26141,7 +26188,8 @@ fn zirBuiltinExtern( |
| 26141 | 26188 | .is_weak_linkage = options.linkage == .weak, |
| 26142 | 26189 | } }), |
| 26143 | 26190 | ), |
| 26144 | }, options.name); | |
| 26191 | options.name, | |
| 26192 | ); | |
| 26145 | 26193 | new_decl.owns_tv = true; |
| 26146 | 26194 | // Note that this will queue the anon decl for codegen, so that the backend can |
| 26147 | 26195 | // correctly handle the extern, including duplicate detection. |
| ... | ... | @@ -26641,13 +26689,12 @@ fn prepareSimplePanic(sema: *Sema, block: *Block) !void { |
| 26641 | 26689 | // decl_index may be an alias; we must find the decl that actually |
| 26642 | 26690 | // owns the function. |
| 26643 | 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 | 26693 | try sema.declareDependency(.{ .decl_val = decl_index }); |
| 26646 | assert(tv.ty.zigTypeTag(mod) == .Fn); | |
| 26647 | assert(try sema.fnHasRuntimeBits(tv.ty)); | |
| 26648 | const func_index = tv.val.toIntern(); | |
| 26649 | try mod.ensureFuncBodyAnalysisQueued(func_index); | |
| 26650 | mod.panic_func_index = func_index; | |
| 26694 | assert(fn_val.typeOf(mod).zigTypeTag(mod) == .Fn); | |
| 26695 | assert(try sema.fnHasRuntimeBits(fn_val.typeOf(mod))); | |
| 26696 | try mod.ensureFuncBodyAnalysisQueued(fn_val.toIntern()); | |
| 26697 | mod.panic_func_index = fn_val.toIntern(); | |
| 26651 | 26698 | } |
| 26652 | 26699 | |
| 26653 | 26700 | if (mod.null_stack_trace == .none) { |
| ... | ... | @@ -27789,7 +27836,7 @@ fn structFieldPtrByIndex( |
| 27789 | 27836 | const val = try mod.intern(.{ .ptr = .{ |
| 27790 | 27837 | .ty = ptr_field_ty.toIntern(), |
| 27791 | 27838 | .addr = .{ .field = .{ |
| 27792 | .base = try struct_ptr_val.intern(struct_ptr_ty, mod), | |
| 27839 | .base = struct_ptr_val.toIntern(), | |
| 27793 | 27840 | .index = field_index, |
| 27794 | 27841 | } }, |
| 27795 | 27842 | } }); |
| ... | ... | @@ -28568,7 +28615,7 @@ fn elemValSlice( |
| 28568 | 28615 | |
| 28569 | 28616 | if (maybe_slice_val) |slice_val| { |
| 28570 | 28617 | runtime_src = elem_index_src; |
| 28571 | const slice_len = slice_val.sliceLen(mod); | |
| 28618 | const slice_len = try slice_val.sliceLen(sema); | |
| 28572 | 28619 | const slice_len_s = slice_len + @intFromBool(slice_sent); |
| 28573 | 28620 | if (slice_len_s == 0) { |
| 28574 | 28621 | return sema.fail(block, slice_src, "indexing into empty slice is not allowed", .{}); |
| ... | ... | @@ -28593,7 +28640,7 @@ fn elemValSlice( |
| 28593 | 28640 | try sema.requireRuntimeBlock(block, src, runtime_src); |
| 28594 | 28641 | if (oob_safety and block.wantSafety()) { |
| 28595 | 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 | 28644 | else |
| 28598 | 28645 | try block.addTyOp(.slice_len, Type.usize, slice); |
| 28599 | 28646 | const cmp_op: Air.Inst.Tag = if (slice_sent) .cmp_lte else .cmp_lt; |
| ... | ... | @@ -28630,7 +28677,7 @@ fn elemPtrSlice( |
| 28630 | 28677 | if (slice_val.isUndef(mod)) { |
| 28631 | 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 | 28681 | const slice_len_s = slice_len + @intFromBool(slice_sent); |
| 28635 | 28682 | if (slice_len_s == 0) { |
| 28636 | 28683 | return sema.fail(block, slice_src, "indexing into empty slice is not allowed", .{}); |
| ... | ... | @@ -28653,7 +28700,7 @@ fn elemPtrSlice( |
| 28653 | 28700 | const len_inst = len: { |
| 28654 | 28701 | if (maybe_undef_slice_val) |slice_val| |
| 28655 | 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 | 28704 | break :len try block.addTyOp(.slice_len, Type.usize, slice); |
| 28658 | 28705 | }; |
| 28659 | 28706 | const cmp_op: Air.Inst.Tag = if (slice_sent) .cmp_lte else .cmp_lt; |
| ... | ... | @@ -29115,7 +29162,7 @@ fn coerceExtra( |
| 29115 | 29162 | // comptime-known integer to other number |
| 29116 | 29163 | if (!(try sema.intFitsInType(val, dest_ty, null))) { |
| 29117 | 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 | 29167 | return switch (mod.intern_pool.indexToKey(val.toIntern())) { |
| 29121 | 29168 | .undef => try mod.undefRef(dest_ty), |
| ... | ... | @@ -29160,7 +29207,7 @@ fn coerceExtra( |
| 29160 | 29207 | block, |
| 29161 | 29208 | inst_src, |
| 29162 | 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 | 29213 | return Air.internedToRef(result_val.toIntern()); |
| ... | ... | @@ -29531,11 +29578,11 @@ const InMemoryCoercionResult = union(enum) { |
| 29531 | 29578 | .array_sentinel => |sentinel| { |
| 29532 | 29579 | if (sentinel.actual.toIntern() != .unreachable_value) { |
| 29533 | 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 | 29583 | } else { |
| 29537 | 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 | 29588 | break; |
| ... | ... | @@ -29657,11 +29704,11 @@ const InMemoryCoercionResult = union(enum) { |
| 29657 | 29704 | .ptr_sentinel => |sentinel| { |
| 29658 | 29705 | if (sentinel.actual.toIntern() != .unreachable_value) { |
| 29659 | 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 | 29709 | } else { |
| 29663 | 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 | 29714 | break; |
| ... | ... | @@ -30654,21 +30701,22 @@ fn storePtrVal( |
| 30654 | 30701 | .opv => {}, |
| 30655 | 30702 | .direct => |val_ptr| { |
| 30656 | 30703 | if (mut_kit.root == .comptime_field) { |
| 30657 | val_ptr.* = Value.fromInterned((try val_ptr.intern(operand_ty, mod))); | |
| 30658 | if (!operand_val.eql(val_ptr.*, operand_ty, mod)) { | |
| 30704 | val_ptr.* = .{ .interned = try val_ptr.intern(mod, sema.arena) }; | |
| 30705 | if (operand_val.toIntern() != val_ptr.interned) { | |
| 30659 | 30706 | // TODO use failWithInvalidComptimeFieldStore |
| 30660 | 30707 | return sema.fail(block, src, "value stored in comptime field does not match the default value of the field", .{}); |
| 30661 | 30708 | } |
| 30662 | 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 | 30713 | .reinterpret => |reinterpret| { |
| 30667 | 30714 | try sema.resolveTypeLayout(mut_kit.ty); |
| 30668 | 30715 | const abi_size = try sema.usizeCast(block, src, mut_kit.ty.abiSize(mod)); |
| 30669 | 30716 | const buffer = try sema.gpa.alloc(u8, abi_size); |
| 30670 | 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 | 30720 | error.OutOfMemory => return error.OutOfMemory, |
| 30673 | 30721 | error.ReinterpretDeclRef => unreachable, |
| 30674 | 30722 | error.IllDefinedMemoryLayout => unreachable, // Sema was supposed to emit a compile error already |
| ... | ... | @@ -30692,7 +30740,7 @@ fn storePtrVal( |
| 30692 | 30740 | error.IllDefinedMemoryLayout => unreachable, |
| 30693 | 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 | 30745 | .bad_decl_ty, .bad_ptr_ty => { |
| 30698 | 30746 | // TODO show the decl declaration site in a note and explain whether the decl |
| ... | ... | @@ -30717,11 +30765,11 @@ const ComptimePtrMutationKit = struct { |
| 30717 | 30765 | opv, |
| 30718 | 30766 | /// The pointer type matches the actual comptime Value so a direct |
| 30719 | 30767 | /// modification is possible. |
| 30720 | direct: *Value, | |
| 30768 | direct: *MutableValue, | |
| 30721 | 30769 | /// The largest parent Value containing pointee and having a well-defined memory layout. |
| 30722 | 30770 | /// This is used for bitcasting, if direct dereferencing failed. |
| 30723 | 30771 | reinterpret: struct { |
| 30724 | val_ptr: *Value, | |
| 30772 | val_ptr: *MutableValue, | |
| 30725 | 30773 | byte_offset: usize, |
| 30726 | 30774 | /// If set, write the operand to packed memory |
| 30727 | 30775 | write_packed: bool = false, |
| ... | ... | @@ -30753,15 +30801,15 @@ fn beginComptimePtrMutation( |
| 30753 | 30801 | .decl, .anon_decl, .int => unreachable, // isComptimeMutablePtr has been checked already |
| 30754 | 30802 | .comptime_alloc => |alloc_index| { |
| 30755 | 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 | 30806 | .comptime_field => |comptime_field| { |
| 30759 | const duped = try sema.arena.create(Value); | |
| 30760 | duped.* = Value.fromInterned(comptime_field); | |
| 30807 | const duped = try sema.arena.create(MutableValue); | |
| 30808 | duped.* = .{ .interned = comptime_field }; | |
| 30761 | 30809 | return sema.beginComptimePtrMutationInner( |
| 30762 | 30810 | block, |
| 30763 | 30811 | src, |
| 30764 | Type.fromInterned(mod.intern_pool.typeOf(comptime_field)), | |
| 30812 | duped.typeOf(mod), | |
| 30765 | 30813 | duped, |
| 30766 | 30814 | ptr_elem_ty, |
| 30767 | 30815 | .comptime_field, |
| ... | ... | @@ -30774,36 +30822,28 @@ fn beginComptimePtrMutation( |
| 30774 | 30822 | .opv => unreachable, |
| 30775 | 30823 | .direct => |val_ptr| { |
| 30776 | 30824 | const payload_ty = parent.ty.errorUnionPayload(mod); |
| 30777 | if (val_ptr.ip_index == .none and val_ptr.tag() == .eu_payload) { | |
| 30778 | return ComptimePtrMutationKit{ | |
| 30779 | .root = parent.root, | |
| 30780 | .pointee = .{ .direct = &val_ptr.castTag(.eu_payload).?.data }, | |
| 30781 | .ty = payload_ty, | |
| 30782 | }; | |
| 30783 | } else { | |
| 30825 | try val_ptr.unintern(mod, sema.arena, false, false); | |
| 30826 | if (val_ptr.* == .interned) { | |
| 30784 | 30827 | // An error union has been initialized to undefined at comptime and now we |
| 30785 | 30828 | // are for the first time setting the payload. We must change the |
| 30786 | // representation of the error union from `undef` to `opt_payload`. | |
| 30787 | ||
| 30788 | const payload = try sema.arena.create(Value.Payload.SubValue); | |
| 30789 | payload.* = .{ | |
| 30790 | .base = .{ .tag = .eu_payload }, | |
| 30791 | .data = Value.fromInterned((try mod.intern(.{ .undef = payload_ty.toIntern() }))), | |
| 30792 | }; | |
| 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 | }; | |
| 30829 | // representation of the error union to `eu_payload`. | |
| 30830 | const child = try sema.arena.create(MutableValue); | |
| 30831 | child.* = .{ .interned = try mod.intern(.{ .undef = payload_ty.toIntern() }) }; | |
| 30832 | val_ptr.* = .{ .eu_payload = .{ | |
| 30833 | .ty = parent.ty.toIntern(), | |
| 30834 | .child = child, | |
| 30835 | } }; | |
| 30801 | 30836 | } |
| 30837 | return .{ | |
| 30838 | .root = parent.root, | |
| 30839 | .pointee = .{ .direct = val_ptr.eu_payload.child }, | |
| 30840 | .ty = payload_ty, | |
| 30841 | }; | |
| 30802 | 30842 | }, |
| 30803 | 30843 | .bad_decl_ty, .bad_ptr_ty => return parent, |
| 30804 | 30844 | // Even though the parent value type has well-defined memory layout, our |
| 30805 | 30845 | // pointer type does not. |
| 30806 | .reinterpret => return ComptimePtrMutationKit{ | |
| 30846 | .reinterpret => return .{ | |
| 30807 | 30847 | .root = parent.root, |
| 30808 | 30848 | .pointee = .bad_ptr_ty, |
| 30809 | 30849 | .ty = eu_ty, |
| ... | ... | @@ -30817,46 +30857,28 @@ fn beginComptimePtrMutation( |
| 30817 | 30857 | .opv => unreachable, |
| 30818 | 30858 | .direct => |val_ptr| { |
| 30819 | 30859 | const payload_ty = parent.ty.optionalChild(mod); |
| 30820 | switch (val_ptr.ip_index) { | |
| 30821 | .none => return ComptimePtrMutationKit{ | |
| 30822 | .root = parent.root, | |
| 30823 | .pointee = .{ .direct = &val_ptr.castTag(.opt_payload).?.data }, | |
| 30824 | .ty = payload_ty, | |
| 30825 | }, | |
| 30826 | else => { | |
| 30827 | const payload_val = switch (mod.intern_pool.indexToKey(val_ptr.ip_index)) { | |
| 30828 | .undef => try mod.intern(.{ .undef = payload_ty.toIntern() }), | |
| 30829 | .opt => |opt| switch (opt.val) { | |
| 30830 | .none => try mod.intern(.{ .undef = payload_ty.toIntern() }), | |
| 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 | }, | |
| 30860 | try val_ptr.unintern(mod, sema.arena, false, false); | |
| 30861 | if (val_ptr.* == .interned) { | |
| 30862 | // An optional has been initialized to undefined at comptime and now we | |
| 30863 | // are for the first time setting the payload. We must change the | |
| 30864 | // representation of the optional to `opt_payload`. | |
| 30865 | const child = try sema.arena.create(MutableValue); | |
| 30866 | child.* = .{ .interned = try mod.intern(.{ .undef = payload_ty.toIntern() }) }; | |
| 30867 | val_ptr.* = .{ .opt_payload = .{ | |
| 30868 | .ty = parent.ty.toIntern(), | |
| 30869 | .child = child, | |
| 30870 | } }; | |
| 30854 | 30871 | } |
| 30872 | return .{ | |
| 30873 | .root = parent.root, | |
| 30874 | .pointee = .{ .direct = val_ptr.opt_payload.child }, | |
| 30875 | .ty = payload_ty, | |
| 30876 | }; | |
| 30855 | 30877 | }, |
| 30856 | 30878 | .bad_decl_ty, .bad_ptr_ty => return parent, |
| 30857 | 30879 | // Even though the parent value type has well-defined memory layout, our |
| 30858 | 30880 | // pointer type does not. |
| 30859 | .reinterpret => return ComptimePtrMutationKit{ | |
| 30881 | .reinterpret => return .{ | |
| 30860 | 30882 | .root = parent.root, |
| 30861 | 30883 | .pointee = .bad_ptr_ty, |
| 30862 | 30884 | .ty = opt_ty, |
| ... | ... | @@ -30915,106 +30937,28 @@ fn beginComptimePtrMutation( |
| 30915 | 30937 | }; |
| 30916 | 30938 | } |
| 30917 | 30939 | |
| 30918 | switch (val_ptr.ip_index) { | |
| 30919 | .none => switch (val_ptr.tag()) { | |
| 30920 | .bytes => { | |
| 30921 | // An array is memory-optimized to store a slice of bytes, but we are about | |
| 30922 | // to modify an individual field and the representation has to change. | |
| 30923 | // If we wanted to avoid this, there would need to be special detection | |
| 30924 | // elsewhere to identify when writing a value to an array element that is stored | |
| 30925 | // using the `bytes` tag, and handle it without making a call to this function. | |
| 30926 | const arena = sema.arena; | |
| 30927 | ||
| 30928 | const bytes = val_ptr.castTag(.bytes).?.data; | |
| 30929 | const dest_len = parent.ty.arrayLenIncludingSentinel(mod); | |
| 30930 | // bytes.len may be one greater than dest_len because of the case when | |
| 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 | ), | |
| 30940 | try val_ptr.unintern(mod, sema.arena, false, false); | |
| 30941 | ||
| 30942 | const aggregate = switch (val_ptr.*) { | |
| 30943 | .interned, | |
| 30944 | .bytes, | |
| 30945 | .repeated, | |
| 30946 | .eu_payload, | |
| 30947 | .opt_payload, | |
| 30948 | .slice, | |
| 30949 | .un, | |
| 30950 | => unreachable, | |
| 30951 | .aggregate => |*a| a, | |
| 30952 | }; | |
| 30988 | 30953 | |
| 30989 | else => unreachable, | |
| 30990 | }, | |
| 30991 | else => switch (mod.intern_pool.indexToKey(val_ptr.toIntern())) { | |
| 30992 | .undef => { | |
| 30993 | // An array has been initialized to undefined at comptime and now we | |
| 30994 | // are for the first time setting an element. We must change the representation | |
| 30995 | // of the array from `undef` to `array`. | |
| 30996 | const arena = sema.arena; | |
| 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 | } | |
| 30954 | return sema.beginComptimePtrMutationInner( | |
| 30955 | block, | |
| 30956 | src, | |
| 30957 | elem_ty, | |
| 30958 | &aggregate.elems[@intCast(elem_ptr.index)], | |
| 30959 | ptr_elem_ty, | |
| 30960 | parent.root, | |
| 30961 | ); | |
| 31018 | 30962 | }, |
| 31019 | 30963 | else => { |
| 31020 | 30964 | if (elem_ptr.index != 0) { |
| ... | ... | @@ -31038,7 +30982,7 @@ fn beginComptimePtrMutation( |
| 31038 | 30982 | if (!base_elem_ty.hasWellDefinedLayout(mod)) { |
| 31039 | 30983 | // Even though the parent value type has well-defined memory layout, our |
| 31040 | 30984 | // pointer type does not. |
| 31041 | return ComptimePtrMutationKit{ | |
| 30985 | return .{ | |
| 31042 | 30986 | .root = parent.root, |
| 31043 | 30987 | .pointee = .bad_ptr_ty, |
| 31044 | 30988 | .ty = base_elem_ty, |
| ... | ... | @@ -31048,7 +30992,7 @@ fn beginComptimePtrMutation( |
| 31048 | 30992 | const elem_abi_size_u64 = try sema.typeAbiSize(base_elem_ty); |
| 31049 | 30993 | const elem_abi_size = try sema.usizeCast(block, src, elem_abi_size_u64); |
| 31050 | 30994 | const elem_idx = try sema.usizeCast(block, src, elem_ptr.index); |
| 31051 | return ComptimePtrMutationKit{ | |
| 30995 | return .{ | |
| 31052 | 30996 | .root = parent.root, |
| 31053 | 30997 | .pointee = .{ .reinterpret = .{ |
| 31054 | 30998 | .val_ptr = reinterpret.val_ptr, |
| ... | ... | @@ -31067,56 +31011,68 @@ fn beginComptimePtrMutation( |
| 31067 | 31011 | var parent = try sema.beginComptimePtrMutation(block, src, Value.fromInterned(field_ptr.base), base_child_ty); |
| 31068 | 31012 | switch (parent.pointee) { |
| 31069 | 31013 | .opv => unreachable, |
| 31070 | .direct => |val_ptr| switch (val_ptr.ip_index) { | |
| 31071 | .empty_struct => { | |
| 31072 | const duped = try sema.arena.create(Value); | |
| 31073 | duped.* = val_ptr.*; | |
| 31074 | return beginComptimePtrMutationInner( | |
| 31075 | sema, | |
| 31076 | block, | |
| 31077 | src, | |
| 31078 | parent.ty.structFieldType(field_index, mod), | |
| 31079 | duped, | |
| 31080 | ptr_elem_ty, | |
| 31081 | parent.root, | |
| 31082 | ); | |
| 31083 | }, | |
| 31084 | .none => switch (val_ptr.tag()) { | |
| 31085 | .aggregate => return beginComptimePtrMutationInner( | |
| 31086 | sema, | |
| 31014 | .direct => |val_ptr| { | |
| 31015 | try val_ptr.unintern(mod, sema.arena, false, false); | |
| 31016 | switch (val_ptr.*) { | |
| 31017 | .interned, | |
| 31018 | .eu_payload, | |
| 31019 | .opt_payload, | |
| 31020 | .repeated, | |
| 31021 | .bytes, | |
| 31022 | => unreachable, | |
| 31023 | .aggregate => |*a| return sema.beginComptimePtrMutationInner( | |
| 31087 | 31024 | block, |
| 31088 | 31025 | src, |
| 31089 | 31026 | parent.ty.structFieldType(field_index, mod), |
| 31090 | &val_ptr.castTag(.aggregate).?.data[field_index], | |
| 31027 | &a.elems[field_index], | |
| 31091 | 31028 | ptr_elem_ty, |
| 31092 | 31029 | parent.root, |
| 31093 | 31030 | ), |
| 31094 | .repeated => { | |
| 31095 | const arena = sema.arena; | |
| 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, | |
| 31031 | .slice => |*s| switch (field_index) { | |
| 31032 | Value.slice_ptr_index => return sema.beginComptimePtrMutationInner( | |
| 31103 | 31033 | block, |
| 31104 | 31034 | src, |
| 31105 | parent.ty.structFieldType(field_index, mod), | |
| 31106 | &elems[field_index], | |
| 31035 | parent.ty.slicePtrFieldType(mod), | |
| 31036 | s.ptr, | |
| 31107 | 31037 | ptr_elem_ty, |
| 31108 | 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" => { | |
| 31112 | const payload = &val_ptr.castTag(.@"union").?.data; | |
| 31050 | .un => |*un| { | |
| 31113 | 31051 | const layout = base_child_ty.containerLayout(mod); |
| 31114 | 31052 | |
| 31115 | 31053 | const tag_type = base_child_ty.unionTagTypeHypothetical(mod); |
| 31116 | 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 | 31074 | // We need to set the active field of the union. |
| 31119 | payload.tag = hypothetical_tag; | |
| 31075 | un.tag = hypothetical_tag.toIntern(); | |
| 31120 | 31076 | |
| 31121 | 31077 | const field_ty = parent.ty.structFieldType(field_index, mod); |
| 31122 | 31078 | return beginComptimePtrMutationInner( |
| ... | ... | @@ -31124,7 +31080,7 @@ fn beginComptimePtrMutation( |
| 31124 | 31080 | block, |
| 31125 | 31081 | src, |
| 31126 | 31082 | field_ty, |
| 31127 | &payload.val, | |
| 31083 | un.payload, | |
| 31128 | 31084 | ptr_elem_ty, |
| 31129 | 31085 | parent.root, |
| 31130 | 31086 | ); |
| ... | ... | @@ -31132,11 +31088,10 @@ fn beginComptimePtrMutation( |
| 31132 | 31088 | // Writing to a different field (a different or unknown tag is active) requires reinterpreting |
| 31133 | 31089 | // memory of the entire union, which requires knowing its abiSize. |
| 31134 | 31090 | try sema.resolveTypeLayout(parent.ty); |
| 31135 | ||
| 31136 | 31091 | // This union value no longer has a well-defined tag type. |
| 31137 | 31092 | // The reinterpretation will read it back out as .none. |
| 31138 | payload.val = try payload.val.unintern(sema.arena, mod); | |
| 31139 | return ComptimePtrMutationKit{ | |
| 31093 | try un.payload.unintern(mod, sema.arena, false, false); | |
| 31094 | return .{ | |
| 31140 | 31095 | .root = parent.root, |
| 31141 | 31096 | .pointee = .{ .reinterpret = .{ |
| 31142 | 31097 | .val_ptr = val_ptr, |
| ... | ... | @@ -31147,119 +31102,12 @@ fn beginComptimePtrMutation( |
| 31147 | 31102 | }; |
| 31148 | 31103 | } |
| 31149 | 31104 | }, |
| 31150 | .slice => switch (field_index) { | |
| 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 | }, | |
| 31105 | } | |
| 31258 | 31106 | }, |
| 31259 | 31107 | .reinterpret => |reinterpret| { |
| 31260 | 31108 | const field_offset_u64 = base_child_ty.structFieldOffset(field_index, mod); |
| 31261 | 31109 | const field_offset = try sema.usizeCast(block, src, field_offset_u64); |
| 31262 | return ComptimePtrMutationKit{ | |
| 31110 | return .{ | |
| 31263 | 31111 | .root = parent.root, |
| 31264 | 31112 | .pointee = .{ .reinterpret = .{ |
| 31265 | 31113 | .val_ptr = reinterpret.val_ptr, |
| ... | ... | @@ -31279,7 +31127,7 @@ fn beginComptimePtrMutationInner( |
| 31279 | 31127 | block: *Block, |
| 31280 | 31128 | src: LazySrcLoc, |
| 31281 | 31129 | decl_ty: Type, |
| 31282 | decl_val: *Value, | |
| 31130 | decl_val: *MutableValue, | |
| 31283 | 31131 | ptr_elem_ty: Type, |
| 31284 | 31132 | root: ComptimePtrMutationKit.Root, |
| 31285 | 31133 | ) CompileError!ComptimePtrMutationKit { |
| ... | ... | @@ -31287,7 +31135,13 @@ fn beginComptimePtrMutationInner( |
| 31287 | 31135 | const target = mod.getTarget(); |
| 31288 | 31136 | const coerce_ok = (try sema.coerceInMemoryAllowed(block, ptr_elem_ty, decl_ty, true, target, src, src)) == .ok; |
| 31289 | 31137 | |
| 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 | } | |
| 31291 | 31145 | |
| 31292 | 31146 | if (coerce_ok) { |
| 31293 | 31147 | return ComptimePtrMutationKit{ |
| ... | ... | @@ -31333,21 +31187,16 @@ fn beginComptimePtrMutationInner( |
| 31333 | 31187 | }; |
| 31334 | 31188 | } |
| 31335 | 31189 | |
| 31336 | const TypedValueAndOffset = struct { | |
| 31337 | tv: TypedValue, | |
| 31338 | byte_offset: usize, | |
| 31339 | }; | |
| 31340 | ||
| 31341 | 31190 | const ComptimePtrLoadKit = struct { |
| 31342 | 31191 | /// The Value and Type corresponding to the pointee of the provided pointer. |
| 31343 | 31192 | /// If a direct dereference is not possible, this is null. |
| 31344 | pointee: ?TypedValue, | |
| 31193 | pointee: ?MutableValue, | |
| 31345 | 31194 | /// The largest parent Value containing `pointee` and having a well-defined memory layout. |
| 31346 | 31195 | /// This is used for bitcasting, if direct dereferencing failed (i.e. `pointee` is null). |
| 31347 | parent: ?TypedValueAndOffset, | |
| 31348 | /// Whether the `pointee` could be mutated by further | |
| 31349 | /// semantic analysis and a copy must be performed. | |
| 31350 | is_mutable: bool, | |
| 31196 | parent: ?struct { | |
| 31197 | val: MutableValue, | |
| 31198 | byte_offset: usize, | |
| 31199 | }, | |
| 31351 | 31200 | /// If the root decl could not be used as `parent`, this is the type that |
| 31352 | 31201 | /// caused that by not having a well-defined layout |
| 31353 | 31202 | ty_without_well_defined_layout: ?Type, |
| ... | ... | @@ -31374,53 +31223,41 @@ fn beginComptimePtrLoad( |
| 31374 | 31223 | .ptr => |ptr| switch (ptr.addr) { |
| 31375 | 31224 | .decl => |decl_index| blk: { |
| 31376 | 31225 | const decl = mod.declPtr(decl_index); |
| 31377 | const decl_tv = try decl.typedValue(); | |
| 31378 | 31226 | try sema.declareDependency(.{ .decl_val = decl_index }); |
| 31379 | 31227 | if (decl.val.getVariable(mod) != null) return error.RuntimeLoad; |
| 31380 | ||
| 31381 | const layout_defined = decl.ty.hasWellDefinedLayout(mod); | |
| 31228 | const decl_val: MutableValue = .{ .interned = decl.val.toIntern() }; | |
| 31229 | const layout_defined = decl.typeOf(mod).hasWellDefinedLayout(mod); | |
| 31382 | 31230 | break :blk ComptimePtrLoadKit{ |
| 31383 | .parent = if (layout_defined) .{ .tv = decl_tv, .byte_offset = 0 } else null, | |
| 31384 | .pointee = decl_tv, | |
| 31385 | .is_mutable = false, | |
| 31386 | .ty_without_well_defined_layout = if (!layout_defined) decl.ty else null, | |
| 31231 | .parent = if (layout_defined) .{ .val = decl_val, .byte_offset = 0 } else null, | |
| 31232 | .pointee = decl_val, | |
| 31233 | .ty_without_well_defined_layout = if (!layout_defined) decl.typeOf(mod) else null, | |
| 31387 | 31234 | }; |
| 31388 | 31235 | }, |
| 31389 | 31236 | .comptime_alloc => |alloc_index| kit: { |
| 31390 | 31237 | const alloc = sema.getComptimeAlloc(alloc_index); |
| 31391 | const alloc_tv: TypedValue = .{ | |
| 31392 | .ty = alloc.ty, | |
| 31393 | .val = alloc.val, | |
| 31394 | }; | |
| 31395 | const layout_defined = alloc.ty.hasWellDefinedLayout(mod); | |
| 31238 | const alloc_ty = alloc.val.typeOf(mod); | |
| 31239 | const layout_defined = alloc_ty.hasWellDefinedLayout(mod); | |
| 31396 | 31240 | break :kit .{ |
| 31397 | .parent = if (layout_defined) .{ .tv = alloc_tv, .byte_offset = 0 } else null, | |
| 31398 | .pointee = alloc_tv, | |
| 31399 | .is_mutable = true, | |
| 31400 | .ty_without_well_defined_layout = if (!layout_defined) alloc.ty else null, | |
| 31241 | .parent = if (layout_defined) .{ .val = alloc.val, .byte_offset = 0 } else null, | |
| 31242 | .pointee = alloc.val, | |
| 31243 | .ty_without_well_defined_layout = if (!layout_defined) alloc_ty else null, | |
| 31401 | 31244 | }; |
| 31402 | 31245 | }, |
| 31403 | 31246 | .anon_decl => |anon_decl| blk: { |
| 31404 | 31247 | const decl_val = anon_decl.val; |
| 31405 | 31248 | if (Value.fromInterned(decl_val).getVariable(mod) != null) return error.RuntimeLoad; |
| 31406 | 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 | 31251 | const layout_defined = decl_ty.hasWellDefinedLayout(mod); |
| 31409 | 31252 | break :blk ComptimePtrLoadKit{ |
| 31410 | .parent = if (layout_defined) .{ .tv = decl_tv, .byte_offset = 0 } else null, | |
| 31411 | .pointee = decl_tv, | |
| 31412 | .is_mutable = false, | |
| 31253 | .parent = if (layout_defined) .{ .val = decl_mv, .byte_offset = 0 } else null, | |
| 31254 | .pointee = decl_mv, | |
| 31413 | 31255 | .ty_without_well_defined_layout = if (!layout_defined) decl_ty else null, |
| 31414 | 31256 | }; |
| 31415 | 31257 | }, |
| 31416 | 31258 | .int => return error.RuntimeLoad, |
| 31417 | 31259 | .eu_payload, .opt_payload => |container_ptr| blk: { |
| 31418 | 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 | 31261 | var deref = try sema.beginComptimePtrLoad(block, src, Value.fromInterned(container_ptr), container_ty); |
| 31425 | 31262 | |
| 31426 | 31263 | // eu_payload and opt_payload never have a well-defined layout |
| ... | ... | @@ -31429,15 +31266,14 @@ fn beginComptimePtrLoad( |
| 31429 | 31266 | deref.ty_without_well_defined_layout = container_ty; |
| 31430 | 31267 | } |
| 31431 | 31268 | |
| 31432 | if (deref.pointee) |*tv| { | |
| 31269 | if (deref.pointee) |pointee| { | |
| 31270 | const pointee_ty = pointee.typeOf(mod); | |
| 31433 | 31271 | const coerce_in_mem_ok = |
| 31434 | (try sema.coerceInMemoryAllowed(block, container_ty, tv.ty, false, target, src, src)) == .ok or | |
| 31435 | (try sema.coerceInMemoryAllowed(block, tv.ty, container_ty, false, target, src, src)) == .ok; | |
| 31272 | (try sema.coerceInMemoryAllowed(block, container_ty, pointee_ty, false, target, src, src)) == .ok or | |
| 31273 | (try sema.coerceInMemoryAllowed(block, pointee_ty, container_ty, false, target, src, src)) == .ok; | |
| 31436 | 31274 | if (coerce_in_mem_ok) { |
| 31437 | const payload_val = switch (tv.val.ip_index) { | |
| 31438 | .none => tv.val.cast(Value.Payload.SubValue).?.data, | |
| 31439 | .null_value => return sema.fail(block, src, "attempt to use null value", .{}), | |
| 31440 | else => Value.fromInterned(switch (ip.indexToKey(tv.val.toIntern())) { | |
| 31275 | deref.pointee = switch (pointee) { | |
| 31276 | .interned => |ip_index| .{ .interned = switch (ip.indexToKey(ip_index)) { | |
| 31441 | 31277 | .error_union => |error_union| switch (error_union.val) { |
| 31442 | 31278 | .err_name => |err_name| return sema.fail( |
| 31443 | 31279 | block, |
| ... | ... | @@ -31452,23 +31288,20 @@ fn beginComptimePtrLoad( |
| 31452 | 31288 | else => |payload| payload, |
| 31453 | 31289 | }, |
| 31454 | 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 | 31295 | break :blk deref; |
| 31459 | 31296 | } |
| 31460 | 31297 | } |
| 31461 | 31298 | deref.pointee = null; |
| 31462 | 31299 | break :blk deref; |
| 31463 | 31300 | }, |
| 31464 | .comptime_field => |comptime_field| blk: { | |
| 31465 | const field_ty = Type.fromInterned(ip.typeOf(comptime_field)); | |
| 31466 | break :blk ComptimePtrLoadKit{ | |
| 31467 | .parent = null, | |
| 31468 | .pointee = .{ .ty = field_ty, .val = Value.fromInterned(comptime_field) }, | |
| 31469 | .is_mutable = false, | |
| 31470 | .ty_without_well_defined_layout = field_ty, | |
| 31471 | }; | |
| 31301 | .comptime_field => |field_val| .{ | |
| 31302 | .parent = null, | |
| 31303 | .pointee = .{ .interned = field_val }, | |
| 31304 | .ty_without_well_defined_layout = Type.fromInterned(ip.typeOf(field_val)), | |
| 31472 | 31305 | }, |
| 31473 | 31306 | .elem => |elem_ptr| blk: { |
| 31474 | 31307 | const elem_ty = Type.fromInterned(ip.typeOf(elem_ptr.base)).elemType2(mod); |
| ... | ... | @@ -31501,30 +31334,37 @@ fn beginComptimePtrLoad( |
| 31501 | 31334 | |
| 31502 | 31335 | // If we're loading an elem that was derived from a different type |
| 31503 | 31336 | // 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: { | |
| 31505 | const deref_elem_ty = deref.pointee.?.ty.childType(mod); | |
| 31506 | break :x (try sema.coerceInMemoryAllowed(block, deref_elem_ty, elem_ty, false, target, src, src)) == .ok or | |
| 31507 | (try sema.coerceInMemoryAllowed(block, elem_ty, deref_elem_ty, false, target, src, src)) == .ok; | |
| 31337 | const ty_matches = if (deref.pointee) |pointee| match: { | |
| 31338 | const ty = pointee.typeOf(mod); | |
| 31339 | if (!ty.isArrayOrVector(mod)) break :match false; | |
| 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 | 31344 | } else false; |
| 31509 | 31345 | if (!ty_matches) { |
| 31510 | 31346 | deref.pointee = null; |
| 31511 | 31347 | break :blk deref; |
| 31512 | 31348 | } |
| 31513 | 31349 | |
| 31514 | var array_tv = deref.pointee.?; | |
| 31515 | const check_len = array_tv.ty.arrayLenIncludingSentinel(mod); | |
| 31350 | var array_val = deref.pointee.?; | |
| 31351 | const check_len = array_val.typeOf(mod).arrayLenIncludingSentinel(mod); | |
| 31516 | 31352 | if (maybe_array_ty) |load_ty| { |
| 31517 | 31353 | // It's possible that we're loading a [N]T, in which case we'd like to slice |
| 31518 | 31354 | // the pointee array directly from our parent array. |
| 31519 | 31355 | if (load_ty.isArrayOrVector(mod) and load_ty.childType(mod).eql(elem_ty, mod)) { |
| 31520 | 31356 | const len = try sema.usizeCast(block, src, load_ty.arrayLenIncludingSentinel(mod)); |
| 31521 | 31357 | const elem_idx = try sema.usizeCast(block, src, elem_ptr.index); |
| 31522 | deref.pointee = if (elem_ptr.index + len <= check_len) TypedValue{ | |
| 31523 | .ty = try mod.arrayType(.{ | |
| 31524 | .len = len, | |
| 31525 | .child = elem_ty.toIntern(), | |
| 31526 | }), | |
| 31527 | .val = try array_tv.val.sliceArray(sema, elem_idx, elem_idx + len), | |
| 31358 | deref.pointee = if (elem_ptr.index + len <= check_len) switch (array_val) { | |
| 31359 | .aggregate => |a| .{ .aggregate = .{ | |
| 31360 | .ty = (try mod.arrayType(.{ .len = len, .child = elem_ty.toIntern() })).toIntern(), | |
| 31361 | .elems = a.elems[elem_idx..][0..len], | |
| 31362 | } }, | |
| 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 | 31368 | } else null; |
| 31529 | 31369 | break :blk deref; |
| 31530 | 31370 | } |
| ... | ... | @@ -31535,18 +31375,12 @@ fn beginComptimePtrLoad( |
| 31535 | 31375 | break :blk deref; |
| 31536 | 31376 | } |
| 31537 | 31377 | if (elem_ptr.index == check_len - 1) { |
| 31538 | if (array_tv.ty.sentinel(mod)) |sent| { | |
| 31539 | deref.pointee = TypedValue{ | |
| 31540 | .ty = elem_ty, | |
| 31541 | .val = sent, | |
| 31542 | }; | |
| 31378 | if (array_val.typeOf(mod).sentinel(mod)) |sent| { | |
| 31379 | deref.pointee = .{ .interned = sent.toIntern() }; | |
| 31543 | 31380 | break :blk deref; |
| 31544 | 31381 | } |
| 31545 | 31382 | } |
| 31546 | deref.pointee = TypedValue{ | |
| 31547 | .ty = elem_ty, | |
| 31548 | .val = try array_tv.val.elemValue(mod, @intCast(elem_ptr.index)), | |
| 31549 | }; | |
| 31383 | deref.pointee = try array_val.getElem(mod, @intCast(elem_ptr.index)); | |
| 31550 | 31384 | break :blk deref; |
| 31551 | 31385 | }, |
| 31552 | 31386 | .field => |field_ptr| blk: { |
| ... | ... | @@ -31570,37 +31404,17 @@ fn beginComptimePtrLoad( |
| 31570 | 31404 | deref.ty_without_well_defined_layout = container_ty; |
| 31571 | 31405 | } |
| 31572 | 31406 | |
| 31573 | const tv = deref.pointee orelse { | |
| 31574 | deref.pointee = null; | |
| 31575 | break :blk deref; | |
| 31576 | }; | |
| 31407 | const pointee = deref.pointee orelse break :blk deref; | |
| 31408 | const pointee_ty = pointee.typeOf(mod); | |
| 31577 | 31409 | const coerce_in_mem_ok = |
| 31578 | (try sema.coerceInMemoryAllowed(block, container_ty, tv.ty, false, target, src, src)) == .ok or | |
| 31579 | (try sema.coerceInMemoryAllowed(block, tv.ty, container_ty, false, target, src, src)) == .ok; | |
| 31410 | (try sema.coerceInMemoryAllowed(block, container_ty, pointee_ty, false, target, src, src)) == .ok or | |
| 31411 | (try sema.coerceInMemoryAllowed(block, pointee_ty, container_ty, false, target, src, src)) == .ok; | |
| 31580 | 31412 | if (!coerce_in_mem_ok) { |
| 31581 | 31413 | deref.pointee = null; |
| 31582 | 31414 | break :blk deref; |
| 31583 | 31415 | } |
| 31584 | 31416 | |
| 31585 | if (container_ty.isSlice(mod)) { | |
| 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 | } | |
| 31417 | deref.pointee = try pointee.getElem(mod, field_index); | |
| 31604 | 31418 | break :blk deref; |
| 31605 | 31419 | }, |
| 31606 | 31420 | }, |
| ... | ... | @@ -31611,9 +31425,9 @@ fn beginComptimePtrLoad( |
| 31611 | 31425 | else => unreachable, |
| 31612 | 31426 | }; |
| 31613 | 31427 | |
| 31614 | if (deref.pointee) |tv| { | |
| 31615 | if (deref.parent == null and tv.ty.hasWellDefinedLayout(mod)) { | |
| 31616 | deref.parent = .{ .tv = tv, .byte_offset = 0 }; | |
| 31428 | if (deref.pointee) |val| { | |
| 31429 | if (deref.parent == null and val.typeOf(mod).hasWellDefinedLayout(mod)) { | |
| 31430 | deref.parent = .{ .val = val, .byte_offset = 0 }; | |
| 31617 | 31431 | } |
| 31618 | 31432 | } |
| 31619 | 31433 | return deref; |
| ... | ... | @@ -31760,16 +31574,11 @@ fn coerceArrayPtrToSlice( |
| 31760 | 31574 | if (try sema.resolveValue(inst)) |val| { |
| 31761 | 31575 | const ptr_array_ty = sema.typeOf(inst); |
| 31762 | 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 | 31579 | const slice_val = try mod.intern(.{ .slice = .{ |
| 31764 | 31580 | .ty = dest_ty.toIntern(), |
| 31765 | .ptr = try mod.intern(.{ .ptr = .{ | |
| 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 | } }), | |
| 31581 | .ptr = slice_ptr.toIntern(), | |
| 31773 | 31582 | .len = (try mod.intValue(Type.usize, array_ty.arrayLen(mod))).toIntern(), |
| 31774 | 31583 | } }); |
| 31775 | 31584 | return Air.internedToRef(slice_val); |
| ... | ... | @@ -31844,7 +31653,7 @@ fn coerceCompatiblePtrs( |
| 31844 | 31653 | } |
| 31845 | 31654 | // The comptime Value representation is compatible with both types. |
| 31846 | 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 | 31659 | try sema.requireRuntimeBlock(block, inst_src, null); |
| ... | ... | @@ -31899,7 +31708,7 @@ fn coerceEnumToUnion( |
| 31899 | 31708 | if (try sema.resolveDefinedValue(block, inst_src, enum_tag)) |val| { |
| 31900 | 31709 | const field_index = union_ty.unionTagFieldIndex(val, sema.mod) orelse { |
| 31901 | 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 | }; |
| 31905 | 31714 | |
| ... | ... | @@ -32181,7 +31990,7 @@ fn coerceArrayLike( |
| 32181 | 31990 | ref.* = coerced; |
| 32182 | 31991 | if (runtime_src == null) { |
| 32183 | 31992 | if (try sema.resolveValue(coerced)) |elem_val| { |
| 32184 | val.* = try elem_val.intern(dest_elem_ty, mod); | |
| 31993 | val.* = elem_val.toIntern(); | |
| 32185 | 31994 | } else { |
| 32186 | 31995 | runtime_src = elem_src; |
| 32187 | 31996 | } |
| ... | ... | @@ -32246,7 +32055,7 @@ fn coerceTupleToArray( |
| 32246 | 32055 | ref.* = coerced; |
| 32247 | 32056 | if (runtime_src == null) { |
| 32248 | 32057 | if (try sema.resolveValue(coerced)) |elem_val| { |
| 32249 | val.* = try elem_val.intern(dest_elem_ty, mod); | |
| 32058 | val.* = elem_val.toIntern(); | |
| 32250 | 32059 | } else { |
| 32251 | 32060 | runtime_src = elem_src; |
| 32252 | 32061 | } |
| ... | ... | @@ -32650,7 +32459,7 @@ fn optRefValue(sema: *Sema, opt_val: ?Value) !Value { |
| 32650 | 32459 | return Value.fromInterned((try mod.intern(.{ .opt = .{ |
| 32651 | 32460 | .ty = (try mod.optionalType(ptr_anyopaque_ty.toIntern())).toIntern(), |
| 32652 | 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 | 32463 | ptr_anyopaque_ty, |
| 32655 | 32464 | )).toIntern() else .none, |
| 32656 | 32465 | } }))); |
| ... | ... | @@ -32668,8 +32477,8 @@ fn analyzeDeclRefInner(sema: *Sema, decl_index: InternPool.DeclIndex, analyze_fn |
| 32668 | 32477 | const mod = sema.mod; |
| 32669 | 32478 | try sema.ensureDeclAnalyzed(decl_index); |
| 32670 | 32479 | |
| 32671 | const decl_tv = try mod.declPtr(decl_index).typedValue(); | |
| 32672 | const owner_decl = mod.declPtr(switch (mod.intern_pool.indexToKey(decl_tv.val.toIntern())) { | |
| 32480 | const decl_val = try mod.declPtr(decl_index).valueOrFail(); | |
| 32481 | const owner_decl = mod.declPtr(switch (mod.intern_pool.indexToKey(decl_val.toIntern())) { | |
| 32673 | 32482 | .variable => |variable| variable.decl, |
| 32674 | 32483 | .extern_func => |extern_func| extern_func.decl, |
| 32675 | 32484 | .func => |func| func.owner_decl, |
| ... | ... | @@ -32678,10 +32487,10 @@ fn analyzeDeclRefInner(sema: *Sema, decl_index: InternPool.DeclIndex, analyze_fn |
| 32678 | 32487 | // TODO: if this is a `decl_ref` of a non-variable decl, only depend on decl type |
| 32679 | 32488 | try sema.declareDependency(.{ .decl_val = decl_index }); |
| 32680 | 32489 | const ptr_ty = try sema.ptrType(.{ |
| 32681 | .child = decl_tv.ty.toIntern(), | |
| 32490 | .child = decl_val.typeOf(mod).toIntern(), | |
| 32682 | 32491 | .flags = .{ |
| 32683 | 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 | 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 | 32506 | fn maybeQueueFuncBodyAnalysis(sema: *Sema, decl_index: InternPool.DeclIndex) !void { |
| 32698 | 32507 | const mod = sema.mod; |
| 32699 | 32508 | const decl = mod.declPtr(decl_index); |
| 32700 | const tv = try decl.typedValue(); | |
| 32701 | if (tv.ty.zigTypeTag(mod) != .Fn) return; | |
| 32702 | if (!try sema.fnHasRuntimeBits(tv.ty)) return; | |
| 32703 | const func_index = tv.val.toIntern(); | |
| 32704 | if (!mod.intern_pool.isFuncBody(func_index)) return; // undef or extern function | |
| 32705 | try mod.ensureFuncBodyAnalysisQueued(func_index); | |
| 32509 | const decl_val = try decl.valueOrFail(); | |
| 32510 | if (!mod.intern_pool.isFuncBody(decl_val.toIntern())) return; | |
| 32511 | if (!try sema.fnHasRuntimeBits(decl_val.typeOf(mod))) return; | |
| 32512 | try mod.ensureFuncBodyAnalysisQueued(decl_val.toIntern()); | |
| 32706 | 32513 | } |
| 32707 | 32514 | |
| 32708 | 32515 | fn analyzeRef( |
| ... | ... | @@ -32839,7 +32646,7 @@ fn analyzeSliceLen( |
| 32839 | 32646 | if (slice_val.isUndef(mod)) { |
| 32840 | 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 | 32651 | try sema.requireRuntimeBlock(block, src, null); |
| 32845 | 32652 | return block.addTyOp(.slice_len, Type.usize, slice_inst); |
| ... | ... | @@ -33121,8 +32928,8 @@ fn analyzeSlice( |
| 33121 | 32928 | msg, |
| 33122 | 32929 | "expected '{}', found '{}'", |
| 33123 | 32930 | .{ |
| 33124 | Value.zero_comptime_int.fmtValue(Type.comptime_int, mod), | |
| 33125 | start_value.fmtValue(Type.comptime_int, mod), | |
| 32931 | Value.zero_comptime_int.fmtValue(mod), | |
| 32932 | start_value.fmtValue(mod), | |
| 33126 | 32933 | }, |
| 33127 | 32934 | ); |
| 33128 | 32935 | break :msg msg; |
| ... | ... | @@ -33138,8 +32945,8 @@ fn analyzeSlice( |
| 33138 | 32945 | msg, |
| 33139 | 32946 | "expected '{}', found '{}'", |
| 33140 | 32947 | .{ |
| 33141 | Value.one_comptime_int.fmtValue(Type.comptime_int, mod), | |
| 33142 | end_value.fmtValue(Type.comptime_int, mod), | |
| 32948 | Value.one_comptime_int.fmtValue(mod), | |
| 32949 | end_value.fmtValue(mod), | |
| 33143 | 32950 | }, |
| 33144 | 32951 | ); |
| 33145 | 32952 | break :msg msg; |
| ... | ... | @@ -33152,7 +32959,7 @@ fn analyzeSlice( |
| 33152 | 32959 | block, |
| 33153 | 32960 | end_src, |
| 33154 | 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 | 33054 | end_src, |
| 33248 | 33055 | "end index {} out of bounds for array of length {}{s}", |
| 33249 | 33056 | .{ |
| 33250 | end_val.fmtValue(Type.usize, mod), | |
| 33251 | len_val.fmtValue(Type.usize, mod), | |
| 33057 | end_val.fmtValue(mod), | |
| 33058 | len_val.fmtValue(mod), | |
| 33252 | 33059 | sentinel_label, |
| 33253 | 33060 | }, |
| 33254 | 33061 | ); |
| ... | ... | @@ -33278,7 +33085,7 @@ fn analyzeSlice( |
| 33278 | 33085 | return sema.fail(block, src, "slice of undefined", .{}); |
| 33279 | 33086 | } |
| 33280 | 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 | 33089 | const len_plus_sent = slice_len + @intFromBool(has_sentinel); |
| 33283 | 33090 | const slice_len_val_with_sentinel = try mod.intValue(Type.usize, len_plus_sent); |
| 33284 | 33091 | if (!(try sema.compareAll(end_val, .lte, slice_len_val_with_sentinel, Type.usize))) { |
| ... | ... | @@ -33292,8 +33099,8 @@ fn analyzeSlice( |
| 33292 | 33099 | end_src, |
| 33293 | 33100 | "end index {} out of bounds for slice of length {d}{s}", |
| 33294 | 33101 | .{ |
| 33295 | end_val.fmtValue(Type.usize, mod), | |
| 33296 | slice_val.sliceLen(mod), | |
| 33102 | end_val.fmtValue(mod), | |
| 33103 | try slice_val.sliceLen(sema), | |
| 33297 | 33104 | sentinel_label, |
| 33298 | 33105 | }, |
| 33299 | 33106 | ); |
| ... | ... | @@ -33352,8 +33159,8 @@ fn analyzeSlice( |
| 33352 | 33159 | start_src, |
| 33353 | 33160 | "start index {} is larger than end index {}", |
| 33354 | 33161 | .{ |
| 33355 | start_val.fmtValue(Type.usize, mod), | |
| 33356 | end_val.fmtValue(Type.usize, mod), | |
| 33162 | start_val.fmtValue(mod), | |
| 33163 | end_val.fmtValue(mod), | |
| 33357 | 33164 | }, |
| 33358 | 33165 | ); |
| 33359 | 33166 | } |
| ... | ... | @@ -33391,8 +33198,8 @@ fn analyzeSlice( |
| 33391 | 33198 | const msg = try sema.errMsg(block, src, "value in memory does not match slice sentinel", .{}); |
| 33392 | 33199 | errdefer msg.destroy(sema.gpa); |
| 33393 | 33200 | try sema.errNote(block, src, msg, "expected '{}', found '{}'", .{ |
| 33394 | expected_sentinel.fmtValue(elem_ty, mod), | |
| 33395 | actual_sentinel.fmtValue(elem_ty, mod), | |
| 33201 | expected_sentinel.fmtValue(mod), | |
| 33202 | actual_sentinel.fmtValue(mod), | |
| 33396 | 33203 | }); |
| 33397 | 33204 | |
| 33398 | 33205 | break :msg msg; |
| ... | ... | @@ -33483,10 +33290,7 @@ fn analyzeSlice( |
| 33483 | 33290 | }; |
| 33484 | 33291 | |
| 33485 | 33292 | if (!new_ptr_val.isUndef(mod)) { |
| 33486 | return Air.internedToRef((try mod.getCoerced( | |
| 33487 | Value.fromInterned((try new_ptr_val.intern(new_ptr_ty, mod))), | |
| 33488 | return_ty, | |
| 33489 | )).toIntern()); | |
| 33293 | return Air.internedToRef((try mod.getCoerced(new_ptr_val, return_ty)).toIntern()); | |
| 33490 | 33294 | } |
| 33491 | 33295 | |
| 33492 | 33296 | // Special case: @as([]i32, undefined)[x..x] |
| ... | ... | @@ -33525,7 +33329,7 @@ fn analyzeSlice( |
| 33525 | 33329 | if (try sema.resolveDefinedValue(block, src, ptr_or_slice)) |slice_val| { |
| 33526 | 33330 | // we don't need to add one for sentinels because the |
| 33527 | 33331 | // 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 | } |
| 33530 | 33334 | |
| 33531 | 33335 | const slice_len_inst = try block.addTyOp(.slice_len, Type.usize, ptr_or_slice); |
| ... | ... | @@ -33998,7 +33802,7 @@ fn wrapErrorUnionPayload( |
| 33998 | 33802 | if (try sema.resolveValue(coerced)) |val| { |
| 33999 | 33803 | return Air.internedToRef((try mod.intern(.{ .error_union = .{ |
| 34000 | 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 | 33808 | try sema.requireRuntimeBlock(block, inst_src, null); |
| ... | ... | @@ -36611,7 +36415,7 @@ fn resolveInferredErrorSet( |
| 36611 | 36415 | // inferred error sets, each call gets an adhoc InferredErrorSet object, which |
| 36612 | 36416 | // has no corresponding function body. |
| 36613 | 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 | 36419 | // if ies declared by a inline function with generic return type, the return_type should be generic_poison, |
| 36616 | 36420 | // because inline function does not create a new declaration, and the ies has been filled with analyzeCall, |
| 36617 | 36421 | // so here we can simply skip this case. |
| ... | ... | @@ -37174,15 +36978,14 @@ fn semaStructFieldInits( |
| 37174 | 36978 | }); |
| 37175 | 36979 | }; |
| 37176 | 36980 | |
| 37177 | const field_init = try default_val.intern(field_ty, mod); | |
| 37178 | if (Value.fromInterned(field_init).canMutateComptimeVarState(mod)) { | |
| 36981 | if (default_val.canMutateComptimeVarState(mod)) { | |
| 37179 | 36982 | const init_src = mod.fieldSrcLoc(decl_index, .{ |
| 37180 | 36983 | .index = field_i, |
| 37181 | 36984 | .range = .value, |
| 37182 | 36985 | }).lazy; |
| 37183 | 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 | 37213 | const field_src = mod.fieldSrcLoc(union_type.decl, .{ .index = field_i }).lazy; |
| 37411 | 37214 | const other_field_src = mod.fieldSrcLoc(union_type.decl, .{ .index = gop.index }).lazy; |
| 37412 | 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 | 37217 | errdefer msg.destroy(gpa); |
| 37415 | 37218 | try sema.errNote(&block_scope, other_field_src, msg, "other occurrence here", .{}); |
| 37416 | 37219 | break :msg msg; |
| ... | ... | @@ -37607,10 +37410,12 @@ fn generateUnionTagTypeNumbered( |
| 37607 | 37410 | errdefer mod.destroyDecl(new_decl_index); |
| 37608 | 37411 | const fqn = try union_owner_decl.fullyQualifiedName(mod); |
| 37609 | 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, .{ | |
| 37611 | .ty = Type.noreturn, | |
| 37612 | .val = Value.@"unreachable", | |
| 37613 | }, name); | |
| 37413 | try mod.initNewAnonDecl( | |
| 37414 | new_decl_index, | |
| 37415 | src_decl.src_line, | |
| 37416 | Value.@"unreachable", | |
| 37417 | name, | |
| 37418 | ); | |
| 37614 | 37419 | errdefer mod.abortAnonDecl(new_decl_index); |
| 37615 | 37420 | |
| 37616 | 37421 | const new_decl = mod.declPtr(new_decl_index); |
| ... | ... | @@ -37629,7 +37434,6 @@ fn generateUnionTagTypeNumbered( |
| 37629 | 37434 | .tag_mode = .explicit, |
| 37630 | 37435 | }); |
| 37631 | 37436 | |
| 37632 | new_decl.ty = Type.type; | |
| 37633 | 37437 | new_decl.val = Value.fromInterned(enum_ty); |
| 37634 | 37438 | |
| 37635 | 37439 | try mod.finalizeAnonDecl(new_decl_index); |
| ... | ... | @@ -37652,10 +37456,12 @@ fn generateUnionTagTypeSimple( |
| 37652 | 37456 | const new_decl_index = try mod.allocateNewDecl(block.namespace, src_decl.src_node); |
| 37653 | 37457 | errdefer mod.destroyDecl(new_decl_index); |
| 37654 | 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, .{ | |
| 37656 | .ty = Type.noreturn, | |
| 37657 | .val = Value.@"unreachable", | |
| 37658 | }, name); | |
| 37459 | try mod.initNewAnonDecl( | |
| 37460 | new_decl_index, | |
| 37461 | src_decl.src_line, | |
| 37462 | Value.@"unreachable", | |
| 37463 | name, | |
| 37464 | ); | |
| 37659 | 37465 | mod.declPtr(new_decl_index).name_fully_qualified = true; |
| 37660 | 37466 | break :new_decl_index new_decl_index; |
| 37661 | 37467 | }; |
| ... | ... | @@ -37675,7 +37481,6 @@ fn generateUnionTagTypeSimple( |
| 37675 | 37481 | |
| 37676 | 37482 | const new_decl = mod.declPtr(new_decl_index); |
| 37677 | 37483 | new_decl.owns_tv = true; |
| 37678 | new_decl.ty = Type.type; | |
| 37679 | 37484 | new_decl.val = Value.fromInterned(enum_ty); |
| 37680 | 37485 | |
| 37681 | 37486 | try mod.finalizeAnonDecl(new_decl_index); |
| ... | ... | @@ -37991,7 +37796,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value { |
| 37991 | 37796 | return sema.failWithOwnedErrorMsg(null, msg); |
| 37992 | 37797 | } |
| 37993 | 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 | 37800 | } else return null; |
| 37996 | 37801 | } |
| 37997 | 37802 | |
| ... | ... | @@ -38290,17 +38095,18 @@ fn pointerDerefExtra(sema: *Sema, block: *Block, src: LazySrcLoc, ptr_val: Value |
| 38290 | 38095 | else => |e| return e, |
| 38291 | 38096 | }; |
| 38292 | 38097 | |
| 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 | 38101 | const coerce_in_mem_ok = |
| 38295 | (try sema.coerceInMemoryAllowed(block, load_ty, tv.ty, false, target, src, src)) == .ok or | |
| 38296 | (try sema.coerceInMemoryAllowed(block, tv.ty, load_ty, false, target, src, src)) == .ok; | |
| 38102 | (try sema.coerceInMemoryAllowed(block, load_ty, ty, false, target, src, src)) == .ok or | |
| 38103 | (try sema.coerceInMemoryAllowed(block, ty, load_ty, false, target, src, src)) == .ok; | |
| 38297 | 38104 | if (coerce_in_mem_ok) { |
| 38298 | 38105 | // We have a Value that lines up in virtual memory exactly with what we want to load, |
| 38299 | 38106 | // and it is in-memory coercible to load_ty. It may be returned without modifications. |
| 38300 | 38107 | // Move mutable decl values to the InternPool and assert other decls are already in |
| 38301 | 38108 | // the InternPool. |
| 38302 | const uncoerced_val = if (deref.is_mutable) try tv.val.intern(tv.ty, mod) else tv.val.toIntern(); | |
| 38303 | const coerced_val = try mod.getCoerced(Value.fromInterned(uncoerced_val), load_ty); | |
| 38109 | const coerced_val = try mod.getCoerced(uncoerced_val, load_ty); | |
| 38304 | 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 | 38120 | const load_sz = try sema.typeAbiSize(load_ty); |
| 38315 | 38121 | |
| 38316 | 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)) | |
| 38318 | return DerefResult{ .val = (try sema.bitCastVal(block, src, tv.val, tv.ty, load_ty, 0)) orelse return .runtime_load }; | |
| 38123 | if (deref.pointee) |pointee| { | |
| 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 | } | |
| 38319 | 38131 | |
| 38320 | 38132 | // 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)) | |
| 38322 | return DerefResult{ .val = (try sema.bitCastVal(block, src, parent.tv.val, parent.tv.ty, load_ty, parent.byte_offset)) orelse return .runtime_load }; | |
| 38133 | if (deref.parent) |parent| { | |
| 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 | } | |
| 38323 | 38141 | |
| 38324 | 38142 | if (deref.ty_without_well_defined_layout) |bad_ty| { |
| 38325 | 38143 | // We got no parent for bit-casting, or the parent we got was too small. Either way, the problem |
| 38326 | 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 | 38146 | } else { |
| 38329 | 38147 | // If all encountered types had well-defined layouts, the parent is the root decl and it just |
| 38330 | 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 | } |
| 38334 | 38154 | |
| ... | ... | @@ -38530,7 +38350,7 @@ fn intAddInner(sema: *Sema, lhs: Value, rhs: Value, ty: Type, overflow_idx: *usi |
| 38530 | 38350 | }, |
| 38531 | 38351 | else => |e| return e, |
| 38532 | 38352 | }; |
| 38533 | scalar.* = try val.intern(scalar_ty, mod); | |
| 38353 | scalar.* = val.toIntern(); | |
| 38534 | 38354 | } |
| 38535 | 38355 | return Value.fromInterned((try mod.intern(.{ .aggregate = .{ |
| 38536 | 38356 | .ty = ty.toIntern(), |
| ... | ... | @@ -38620,7 +38440,7 @@ fn intSubInner(sema: *Sema, lhs: Value, rhs: Value, ty: Type, overflow_idx: *usi |
| 38620 | 38440 | }, |
| 38621 | 38441 | else => |e| return e, |
| 38622 | 38442 | }; |
| 38623 | scalar.* = try val.intern(scalar_ty, mod); | |
| 38443 | scalar.* = val.toIntern(); | |
| 38624 | 38444 | } |
| 38625 | 38445 | return Value.fromInterned((try mod.intern(.{ .aggregate = .{ |
| 38626 | 38446 | .ty = ty.toIntern(), |
| ... | ... | @@ -38690,8 +38510,8 @@ fn intSubWithOverflow( |
| 38690 | 38510 | const lhs_elem = try lhs.elemValue(sema.mod, i); |
| 38691 | 38511 | const rhs_elem = try rhs.elemValue(sema.mod, i); |
| 38692 | 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); | |
| 38694 | scalar.* = try of_math_result.wrapped_result.intern(scalar_ty, mod); | |
| 38513 | of.* = of_math_result.overflow_bit.toIntern(); | |
| 38514 | scalar.* = of_math_result.wrapped_result.toIntern(); | |
| 38695 | 38515 | } |
| 38696 | 38516 | return Value.OverflowArithmeticResult{ |
| 38697 | 38517 | .overflow_bit = Value.fromInterned((try mod.intern(.{ .aggregate = .{ |
| ... | ... | @@ -38746,19 +38566,17 @@ fn intFromFloat( |
| 38746 | 38566 | ) CompileError!Value { |
| 38747 | 38567 | const mod = sema.mod; |
| 38748 | 38568 | if (float_ty.zigTypeTag(mod) == .Vector) { |
| 38749 | const elem_ty = float_ty.scalarType(mod); | |
| 38750 | 38569 | const result_data = try sema.arena.alloc(InternPool.Index, float_ty.vectorLen(mod)); |
| 38751 | const scalar_ty = int_ty.scalarType(mod); | |
| 38752 | 38570 | for (result_data, 0..) |*scalar, i| { |
| 38753 | 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 | 38574 | return Value.fromInterned((try mod.intern(.{ .aggregate = .{ |
| 38757 | 38575 | .ty = int_ty.toIntern(), |
| 38758 | 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 | } |
| 38763 | 38581 | |
| 38764 | 38582 | // float is expected to be finite and non-NaN |
| ... | ... | @@ -38791,7 +38609,6 @@ fn intFromFloatScalar( |
| 38791 | 38609 | block: *Block, |
| 38792 | 38610 | src: LazySrcLoc, |
| 38793 | 38611 | val: Value, |
| 38794 | float_ty: Type, | |
| 38795 | 38612 | int_ty: Type, |
| 38796 | 38613 | mode: IntFromFloatMode, |
| 38797 | 38614 | ) CompileError!Value { |
| ... | ... | @@ -38803,7 +38620,7 @@ fn intFromFloatScalar( |
| 38803 | 38620 | block, |
| 38804 | 38621 | src, |
| 38805 | 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 | ); |
| 38808 | 38625 | |
| 38809 | 38626 | const float = val.toFloat(f128, mod); |
| ... | ... | @@ -38825,7 +38642,7 @@ fn intFromFloatScalar( |
| 38825 | 38642 | |
| 38826 | 38643 | if (!(try sema.intFitsInType(cti_result, int_ty, null))) { |
| 38827 | 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 | 38648 | return mod.getCoerced(cti_result, int_ty); |
| ... | ... | @@ -38944,8 +38761,8 @@ fn intAddWithOverflow( |
| 38944 | 38761 | const lhs_elem = try lhs.elemValue(sema.mod, i); |
| 38945 | 38762 | const rhs_elem = try rhs.elemValue(sema.mod, i); |
| 38946 | 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); | |
| 38948 | scalar.* = try of_math_result.wrapped_result.intern(scalar_ty, mod); | |
| 38764 | of.* = of_math_result.overflow_bit.toIntern(); | |
| 38765 | scalar.* = of_math_result.wrapped_result.toIntern(); | |
| 38949 | 38766 | } |
| 38950 | 38767 | return Value.OverflowArithmeticResult{ |
| 38951 | 38768 | .overflow_bit = Value.fromInterned((try mod.intern(.{ .aggregate = .{ |
| ... | ... | @@ -39055,7 +38872,7 @@ fn compareVector( |
| 39055 | 38872 | const lhs_elem = try lhs.elemValue(sema.mod, i); |
| 39056 | 38873 | const rhs_elem = try rhs.elemValue(sema.mod, i); |
| 39057 | 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 | 38877 | return Value.fromInterned((try mod.intern(.{ .aggregate = .{ |
| 39061 | 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 | 39049 | } |
| 39233 | 39050 | |
| 39234 | 39051 | /// Returns true if any value contained in `val` is undefined. |
| 39235 | fn anyUndef(sema: *Sema, val: Value) !bool { | |
| 39052 | fn anyUndef(sema: *Sema, block: *Block, src: LazySrcLoc, val: Value) !bool { | |
| 39236 | 39053 | const mod = sema.mod; |
| 39237 | if (val.ip_index == .none) return switch (val.tag()) { | |
| 39238 | .eu_payload => try sema.anyUndef(val.castTag(.eu_payload).?.data), | |
| 39239 | .opt_payload => try sema.anyUndef(val.castTag(.opt_payload).?.data), | |
| 39240 | .repeated => try sema.anyUndef(val.castTag(.repeated).?.data), | |
| 39054 | return switch (mod.intern_pool.indexToKey(val.toIntern())) { | |
| 39055 | .undef => true, | |
| 39056 | .simple_value => |v| v == .undefined, | |
| 39241 | 39057 | .slice => { |
| 39242 | const slice = val.castTag(.slice).?.data; | |
| 39243 | for (0..@intCast(slice.len.toUnsignedInt(mod))) |idx| { | |
| 39244 | if (try sema.anyUndef((try slice.ptr.maybeElemValueFull(sema, mod, idx)).?)) return true; | |
| 39245 | } | |
| 39246 | return false; | |
| 39247 | }, | |
| 39248 | .bytes => false, | |
| 39249 | .aggregate => for (val.castTag(.aggregate).?.data) |elem| { | |
| 39250 | if (try sema.anyUndef(elem)) break true; | |
| 39058 | // If the slice contents are runtime-known, reification will fail later on with a | |
| 39059 | // specific error message. | |
| 39060 | const arr = try sema.maybeDerefSliceAsArray(block, src, val) orelse return false; | |
| 39061 | return sema.anyUndef(block, src, arr); | |
| 39062 | }, | |
| 39063 | .aggregate => |aggregate| for (0..aggregate.storage.values().len) |i| { | |
| 39064 | const elem = mod.intern_pool.indexToKey(val.toIntern()).aggregate.storage.values()[i]; | |
| 39065 | if (try sema.anyUndef(block, src, Value.fromInterned(elem))) break true; | |
| 39251 | 39066 | } else false, |
| 39252 | .@"union" => { | |
| 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 | }, | |
| 39067 | else => false, | |
| 39274 | 39068 | }; |
| 39275 | 39069 | } |
| 39276 | 39070 | |
| ... | ... | @@ -39283,12 +39077,11 @@ fn sliceToIpString( |
| 39283 | 39077 | reason: NeededComptimeReason, |
| 39284 | 39078 | ) CompileError!InternPool.NullTerminatedString { |
| 39285 | 39079 | const zcu = sema.mod; |
| 39286 | const ip = &zcu.intern_pool; | |
| 39287 | const slice_ty = Type.fromInterned(ip.typeOf(slice_val.toIntern())); | |
| 39080 | const slice_ty = slice_val.typeOf(zcu); | |
| 39288 | 39081 | assert(slice_ty.isSlice(zcu)); |
| 39289 | 39082 | assert(slice_ty.childType(zcu).toIntern() == .u8_type); |
| 39290 | 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 | 39085 | return array_val.toIpString(array_ty, zcu); |
| 39293 | 39086 | } |
| 39294 | 39087 | |
| ... | ... | @@ -39302,9 +39095,23 @@ fn derefSliceAsArray( |
| 39302 | 39095 | slice_val: Value, |
| 39303 | 39096 | reason: NeededComptimeReason, |
| 39304 | 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. | |
| 39106 | fn maybeDerefSliceAsArray( | |
| 39107 | sema: *Sema, | |
| 39108 | block: *Block, | |
| 39109 | src: LazySrcLoc, | |
| 39110 | slice_val: Value, | |
| 39111 | ) CompileError!?Value { | |
| 39305 | 39112 | const zcu = sema.mod; |
| 39306 | 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 | 39115 | const slice = switch (ip.indexToKey(slice_val.toIntern())) { |
| 39309 | 39116 | .undef => return sema.failWithUseOfUndef(block, src), |
| 39310 | 39117 | .slice => |slice| slice, |
| ... | ... | @@ -39324,7 +39131,5 @@ fn derefSliceAsArray( |
| 39324 | 39131 | break :p p; |
| 39325 | 39132 | }); |
| 39326 | 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 { | |
| 39328 | return sema.failWithNeededComptime(block, src, reason); | |
| 39329 | }; | |
| 39134 | return sema.pointerDeref(block, src, casted_ptr, ptr_ty); | |
| 39330 | 39135 | } |
src/TypedValue.zig deleted-528| ... | ... | @@ -1,528 +0,0 @@ |
| 1 | const std = @import("std"); | |
| 2 | const Type = @import("type.zig").Type; | |
| 3 | const Value = @import("Value.zig"); | |
| 4 | const Module = @import("Module.zig"); | |
| 5 | const Allocator = std.mem.Allocator; | |
| 6 | const TypedValue = @This(); | |
| 7 | const Target = std.Target; | |
| 8 | ||
| 9 | ty: Type, | |
| 10 | val: 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. | |
| 14 | pub 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. | |
| 28 | pub 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 | ||
| 35 | pub 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 | ||
| 40 | pub fn hash(tv: TypedValue, hasher: *std.hash.Wyhash, mod: *Module) void { | |
| 41 | return tv.val.hash(tv.ty, hasher, mod); | |
| 42 | } | |
| 43 | ||
| 44 | pub fn intFromEnum(tv: TypedValue, mod: *Module) Allocator.Error!Value { | |
| 45 | return tv.val.intFromEnum(tv.ty, mod); | |
| 46 | } | |
| 47 | ||
| 48 | const max_aggregate_items = 100; | |
| 49 | const max_string_len = 256; | |
| 50 | ||
| 51 | const FormatContext = struct { | |
| 52 | tv: TypedValue, | |
| 53 | mod: *Module, | |
| 54 | }; | |
| 55 | ||
| 56 | pub 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. | |
| 71 | pub 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 | ||
| 463 | fn 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 | 8 | const Allocator = std.mem.Allocator; |
| 9 | 9 | const Zcu = @import("Module.zig"); |
| 10 | 10 | const Module = Zcu; |
| 11 | const TypedValue = @import("TypedValue.zig"); | |
| 12 | 11 | const Sema = @import("Sema.zig"); |
| 13 | 12 | const InternPool = @import("InternPool.zig"); |
| 13 | const print_value = @import("print_value.zig"); | |
| 14 | 14 | const Value = @This(); |
| 15 | 15 | |
| 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. | |
| 19 | 16 | ip_index: InternPool.Index, |
| 20 | 17 | |
| 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. | |
| 25 | legacy: extern union { | |
| 26 | ptr_otherwise: *Payload, | |
| 27 | }, | |
| 28 | ||
| 29 | // Keep in sync with tools/stage2_pretty_printers_common.py | |
| 30 | pub 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 | ||
| 93 | pub fn initPayload(payload: *Payload) Value { | |
| 94 | return Value{ | |
| 95 | .ip_index = .none, | |
| 96 | .legacy = .{ .ptr_otherwise = payload }, | |
| 97 | }; | |
| 98 | } | |
| 99 | ||
| 100 | pub 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. | |
| 106 | pub 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 | ||
| 125 | pub 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 | ||
| 134 | 18 | pub fn format(val: Value, comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void { |
| 135 | 19 | _ = val; |
| 136 | 20 | _ = fmt; |
| ... | ... | @@ -148,42 +32,16 @@ pub fn dump( |
| 148 | 32 | out_stream: anytype, |
| 149 | 33 | ) !void { |
| 150 | 34 | comptime assert(fmt.len == 0); |
| 151 | if (start_val.ip_index != .none) { | |
| 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 | }; | |
| 35 | try out_stream.print("(interned: {})", .{start_val.toIntern()}); | |
| 178 | 36 | } |
| 179 | 37 | |
| 180 | 38 | pub fn fmtDebug(val: Value) std.fmt.Formatter(dump) { |
| 181 | 39 | return .{ .data = val }; |
| 182 | 40 | } |
| 183 | 41 | |
| 184 | pub fn fmtValue(val: Value, ty: Type, mod: *Module) std.fmt.Formatter(TypedValue.format) { | |
| 42 | pub fn fmtValue(val: Value, mod: *Module) std.fmt.Formatter(print_value.format) { | |
| 185 | 43 | return .{ .data = .{ |
| 186 | .tv = .{ .ty = ty, .val = val }, | |
| 44 | .val = val, | |
| 187 | 45 | .mod = mod, |
| 188 | 46 | } }; |
| 189 | 47 | } |
| ... | ... | @@ -252,162 +110,9 @@ fn arrayToIpString(val: Value, len_u64: u64, mod: *Module) !InternPool.NullTermi |
| 252 | 110 | return ip.getOrPutTrailingString(gpa, len); |
| 253 | 111 | } |
| 254 | 112 | |
| 255 | pub 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 | ||
| 260 | pub 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 | ||
| 337 | pub 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 | ||
| 405 | 113 | pub fn fromInterned(i: InternPool.Index) Value { |
| 406 | 114 | assert(i != .none); |
| 407 | return .{ | |
| 408 | .ip_index = i, | |
| 409 | .legacy = undefined, | |
| 410 | }; | |
| 115 | return .{ .ip_index = i }; | |
| 411 | 116 | } |
| 412 | 117 | |
| 413 | 118 | pub fn toIntern(val: Value) InternPool.Index { |
| ... | ... | @@ -492,24 +197,24 @@ pub fn isFuncBody(val: Value, mod: *Module) bool { |
| 492 | 197 | } |
| 493 | 198 | |
| 494 | 199 | pub 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 | 201 | .func => |x| x, |
| 497 | 202 | else => null, |
| 498 | } else null; | |
| 203 | }; | |
| 499 | 204 | } |
| 500 | 205 | |
| 501 | 206 | pub 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 | 208 | .extern_func => |extern_func| extern_func, |
| 504 | 209 | else => null, |
| 505 | } else null; | |
| 210 | }; | |
| 506 | 211 | } |
| 507 | 212 | |
| 508 | 213 | pub 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 | 215 | .variable => |variable| variable, |
| 511 | 216 | else => null, |
| 512 | } else null; | |
| 217 | }; | |
| 513 | 218 | } |
| 514 | 219 | |
| 515 | 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 | 249 | .int => |int| Value.fromInterned(int).getUnsignedIntAdvanced(mod, opt_sema), |
| 545 | 250 | .elem => |elem| { |
| 546 | 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 | 253 | return base_addr + elem.index * elem_ty.abiSize(mod); |
| 549 | 254 | }, |
| 550 | 255 | .field => |field| { |
| 551 | 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 | 258 | if (opt_sema) |sema| try sema.resolveTypeLayout(struct_ty); |
| 554 | 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 | 305 | }; |
| 601 | 306 | } |
| 602 | 307 | |
| 603 | fn isDeclRef(val: Value, mod: *Module) bool { | |
| 308 | fn ptrHasIntAddr(val: Value, mod: *Module) bool { | |
| 604 | 309 | var check = val; |
| 605 | 310 | while (true) switch (mod.intern_pool.indexToKey(check.toIntern())) { |
| 606 | 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 | 314 | .eu_payload, .opt_payload => |base| check = Value.fromInterned(base), |
| 609 | 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 | } |
| 615 | 320 | |
| ... | ... | @@ -677,25 +382,14 @@ pub fn writeToMemory(val: Value, ty: Type, mod: *Module, buffer: []u8) error{ |
| 677 | 382 | .auto => return error.IllDefinedMemoryLayout, |
| 678 | 383 | .@"extern" => for (0..struct_type.field_types.len) |i| { |
| 679 | 384 | const off: usize = @intCast(ty.structFieldOffset(i, mod)); |
| 680 | const field_val = switch (val.ip_index) { | |
| 681 | .none => switch (val.tag()) { | |
| 682 | .bytes => { | |
| 683 | buffer[off] = val.castTag(.bytes).?.data[i]; | |
| 684 | continue; | |
| 685 | }, | |
| 686 | .aggregate => val.castTag(.aggregate).?.data[i], | |
| 687 | .repeated => val.castTag(.repeated).?.data, | |
| 688 | else => unreachable, | |
| 385 | const field_val = Value.fromInterned(switch (ip.indexToKey(val.toIntern()).aggregate.storage) { | |
| 386 | .bytes => |bytes| { | |
| 387 | buffer[off] = bytes[i]; | |
| 388 | continue; | |
| 689 | 389 | }, |
| 690 | else => Value.fromInterned(switch (ip.indexToKey(val.toIntern()).aggregate.storage) { | |
| 691 | .bytes => |bytes| { | |
| 692 | buffer[off] = bytes[i]; | |
| 693 | continue; | |
| 694 | }, | |
| 695 | .elems => |elems| elems[i], | |
| 696 | .repeated_elem => |elem| elem, | |
| 697 | }), | |
| 698 | }; | |
| 390 | .elems => |elems| elems[i], | |
| 391 | .repeated_elem => |elem| elem, | |
| 392 | }); | |
| 699 | 393 | const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[i]); |
| 700 | 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 | 439 | }, |
| 746 | 440 | .Pointer => { |
| 747 | 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 | 443 | return val.writeToMemory(Type.usize, mod, buffer); |
| 750 | 444 | }, |
| 751 | 445 | .Optional => { |
| ... | ... | @@ -842,19 +536,11 @@ pub fn writeToPackedMemory( |
| 842 | 536 | assert(struct_type.layout == .@"packed"); |
| 843 | 537 | var bits: u16 = 0; |
| 844 | 538 | for (0..struct_type.field_types.len) |i| { |
| 845 | const field_val = switch (val.ip_index) { | |
| 846 | .none => switch (val.tag()) { | |
| 847 | .bytes => unreachable, | |
| 848 | .aggregate => val.castTag(.aggregate).?.data[i], | |
| 849 | .repeated => val.castTag(.repeated).?.data, | |
| 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 | }; | |
| 539 | const field_val = Value.fromInterned(switch (ip.indexToKey(val.toIntern()).aggregate.storage) { | |
| 540 | .bytes => unreachable, | |
| 541 | .elems => |elems| elems[i], | |
| 542 | .repeated_elem => |elem| elem, | |
| 543 | }); | |
| 858 | 544 | const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[i]); |
| 859 | 545 | const field_bits: u16 = @intCast(field_ty.bitSize(mod)); |
| 860 | 546 | try field_val.writeToPackedMemory(field_ty, mod, buffer, bit_offset + bits); |
| ... | ... | @@ -880,7 +566,7 @@ pub fn writeToPackedMemory( |
| 880 | 566 | }, |
| 881 | 567 | .Pointer => { |
| 882 | 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 | 570 | return val.writeToPackedMemory(Type.usize, mod, buffer, bit_offset); |
| 885 | 571 | }, |
| 886 | 572 | .Optional => { |
| ... | ... | @@ -972,7 +658,7 @@ pub fn readFromMemory( |
| 972 | 658 | const elems = try arena.alloc(InternPool.Index, @as(usize, @intCast(ty.arrayLen(mod)))); |
| 973 | 659 | var offset: usize = 0; |
| 974 | 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 | 662 | offset += @as(usize, @intCast(elem_size)); |
| 977 | 663 | } |
| 978 | 664 | return Value.fromInterned((try mod.intern(.{ .aggregate = .{ |
| ... | ... | @@ -997,7 +683,7 @@ pub fn readFromMemory( |
| 997 | 683 | const field_ty = Type.fromInterned(field_types.get(ip)[i]); |
| 998 | 684 | const off: usize = @intCast(ty.structFieldOffset(i, mod)); |
| 999 | 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 | 688 | return Value.fromInterned((try mod.intern(.{ .aggregate = .{ |
| 1003 | 689 | .ty = ty.toIntern(), |
| ... | ... | @@ -1027,7 +713,7 @@ pub fn readFromMemory( |
| 1027 | 713 | .@"extern" => { |
| 1028 | 714 | const union_size = ty.abiSize(mod); |
| 1029 | 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 | 717 | return Value.fromInterned((try mod.intern(.{ .un = .{ |
| 1032 | 718 | .ty = ty.toIntern(), |
| 1033 | 719 | .tag = .none, |
| ... | ... | @@ -1094,30 +780,19 @@ pub fn readFromPackedMemory( |
| 1094 | 780 | return Value.true; |
| 1095 | 781 | } |
| 1096 | 782 | }, |
| 1097 | .Int, .Enum => |ty_tag| { | |
| 783 | .Int => { | |
| 1098 | 784 | if (buffer.len == 0) return mod.intValue(ty, 0); |
| 1099 | 785 | const int_info = ty.intInfo(mod); |
| 1100 | 786 | const bits = int_info.bits; |
| 1101 | 787 | if (bits == 0) return mod.intValue(ty, 0); |
| 1102 | 788 | |
| 1103 | 789 | // Fast path for integers <= u64 |
| 1104 | if (bits <= 64) { | |
| 1105 | const int_ty = switch (ty_tag) { | |
| 1106 | .Int => ty, | |
| 1107 | .Enum => ty.intTagType(mod), | |
| 1108 | else => unreachable, | |
| 1109 | }; | |
| 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 | } | |
| 790 | if (bits <= 64) switch (int_info.signedness) { | |
| 791 | // Use different backing types for unsigned vs signed to avoid the need to go via | |
| 792 | // a larger type like `i128`. | |
| 793 | .unsigned => return mod.intValue(ty, std.mem.readVarPackedInt(u64, buffer, bit_offset, bits, endian, .unsigned)), | |
| 794 | .signed => return mod.intValue(ty, std.mem.readVarPackedInt(i64, buffer, bit_offset, bits, endian, .signed)), | |
| 795 | }; | |
| 1121 | 796 | |
| 1122 | 797 | // Slow path, we have to construct a big-int |
| 1123 | 798 | const abi_size = @as(usize, @intCast(ty.abiSize(mod))); |
| ... | ... | @@ -1129,6 +804,11 @@ pub fn readFromPackedMemory( |
| 1129 | 804 | bigint.readPackedTwosComplement(buffer, bit_offset, bits, endian, int_info.signedness); |
| 1130 | 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 | 812 | .Float => return Value.fromInterned((try mod.intern(.{ .float = .{ |
| 1133 | 813 | .ty = ty.toIntern(), |
| 1134 | 814 | .storage = switch (ty.floatBits(target)) { |
| ... | ... | @@ -1149,7 +829,7 @@ pub fn readFromPackedMemory( |
| 1149 | 829 | for (elems, 0..) |_, i| { |
| 1150 | 830 | // On big-endian systems, LLVM reverses the element order of vectors by default |
| 1151 | 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 | 833 | bits += elem_bit_size; |
| 1154 | 834 | } |
| 1155 | 835 | return Value.fromInterned((try mod.intern(.{ .aggregate = .{ |
| ... | ... | @@ -1166,7 +846,7 @@ pub fn readFromPackedMemory( |
| 1166 | 846 | for (field_vals, 0..) |*field_val, i| { |
| 1167 | 847 | const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[i]); |
| 1168 | 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 | 850 | bits += field_bits; |
| 1171 | 851 | } |
| 1172 | 852 | return Value.fromInterned((try mod.intern(.{ .aggregate = .{ |
| ... | ... | @@ -1581,80 +1261,34 @@ pub fn slicePtr(val: Value, mod: *Module) Value { |
| 1581 | 1261 | return Value.fromInterned(mod.intern_pool.slicePtr(val.toIntern())); |
| 1582 | 1262 | } |
| 1583 | 1263 | |
| 1584 | pub fn sliceLen(val: Value, mod: *Module) u64 { | |
| 1585 | const ip = &mod.intern_pool; | |
| 1586 | return switch (ip.indexToKey(val.toIntern())) { | |
| 1587 | .ptr => |ptr| switch (ip.indexToKey(switch (ptr.addr) { | |
| 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 | }; | |
| 1264 | /// Gets the `len` field of a slice value as a `u64`. | |
| 1265 | /// Resolves the length using the provided `Sema` if necessary. | |
| 1266 | pub fn sliceLen(val: Value, sema: *Sema) !u64 { | |
| 1267 | return Value.fromInterned(sema.mod.intern_pool.sliceLen(val.toIntern())).toUnsignedIntAdvanced(sema); | |
| 1600 | 1268 | } |
| 1601 | 1269 | |
| 1602 | /// Asserts the value is a single-item pointer to an array, or an array, | |
| 1603 | /// or an unknown-length pointer, and returns the element value at the index. | |
| 1604 | pub fn elemValue(val: Value, mod: *Module, index: usize) Allocator.Error!Value { | |
| 1605 | return (try val.maybeElemValue(mod, index)).?; | |
| 1606 | } | |
| 1607 | ||
| 1608 | /// Like `elemValue`, but returns `null` instead of asserting on failure. | |
| 1609 | pub fn maybeElemValue(val: Value, mod: *Module, index: usize) Allocator.Error!?Value { | |
| 1610 | return val.maybeElemValueFull(null, mod, index); | |
| 1611 | } | |
| 1612 | ||
| 1613 | pub 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, | |
| 1270 | /// Asserts the value is an aggregate, and returns the element value at the given index. | |
| 1271 | pub fn elemValue(val: Value, zcu: *Zcu, index: usize) Allocator.Error!Value { | |
| 1272 | const ip = &zcu.intern_pool; | |
| 1273 | switch (zcu.intern_pool.indexToKey(val.toIntern())) { | |
| 1274 | .undef => |ty| { | |
| 1275 | return Value.fromInterned(try zcu.intern(.{ .undef = Type.fromInterned(ty).childType(zcu).toIntern() })); | |
| 1621 | 1276 | }, |
| 1622 | else => switch (mod.intern_pool.indexToKey(val.toIntern())) { | |
| 1623 | .undef => |ty| Value.fromInterned((try mod.intern(.{ | |
| 1624 | .undef = Type.fromInterned(ty).elemType2(mod).toIntern(), | |
| 1625 | }))), | |
| 1626 | .slice => |slice| return Value.fromInterned(slice.ptr).maybeElemValueFull(sema, mod, index), | |
| 1627 | .ptr => |ptr| switch (ptr.addr) { | |
| 1628 | .decl => |decl| mod.declPtr(decl).val.maybeElemValueFull(sema, mod, index), | |
| 1629 | .anon_decl => |anon_decl| Value.fromInterned(anon_decl.val).maybeElemValueFull(sema, mod, index), | |
| 1630 | .comptime_alloc => |idx| if (sema) |s| s.getComptimeAlloc(idx).val.maybeElemValueFull(sema, mod, index) else null, | |
| 1631 | .int, .eu_payload => null, | |
| 1632 | .opt_payload => |base| Value.fromInterned(base).maybeElemValueFull(sema, mod, index), | |
| 1633 | .comptime_field => |field_val| Value.fromInterned(field_val).maybeElemValueFull(sema, mod, index), | |
| 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, | |
| 1277 | .aggregate => |aggregate| { | |
| 1278 | const len = ip.aggregateTypeLen(aggregate.ty); | |
| 1279 | if (index < len) return Value.fromInterned(switch (aggregate.storage) { | |
| 1280 | .bytes => |bytes| try zcu.intern(.{ .int = .{ | |
| 1281 | .ty = .u8_type, | |
| 1282 | .storage = .{ .u64 = bytes[index] }, | |
| 1283 | } }), | |
| 1284 | .elems => |elems| elems[index], | |
| 1285 | .repeated_elem => |elem| elem, | |
| 1286 | }); | |
| 1287 | assert(index == len); | |
| 1288 | return Type.fromInterned(aggregate.ty).sentinel(zcu).?; | |
| 1656 | 1289 | }, |
| 1657 | }; | |
| 1290 | else => unreachable, | |
| 1291 | } | |
| 1658 | 1292 | } |
| 1659 | 1293 | |
| 1660 | 1294 | pub fn isLazyAlign(val: Value, mod: *Module) bool { |
| ... | ... | @@ -1686,83 +1320,48 @@ pub fn sliceArray( |
| 1686 | 1320 | ) error{OutOfMemory}!Value { |
| 1687 | 1321 | // TODO: write something like getCoercedInts to avoid needing to dupe |
| 1688 | 1322 | const mod = sema.mod; |
| 1689 | return switch (val.ip_index) { | |
| 1690 | .none => switch (val.tag()) { | |
| 1691 | .slice => val.castTag(.slice).?.data.ptr.sliceArray(sema, start, end), | |
| 1692 | .bytes => Tag.bytes.create(sema.arena, val.castTag(.bytes).?.data[start..end]), | |
| 1693 | .repeated => val, | |
| 1694 | .aggregate => Tag.aggregate.create(sema.arena, val.castTag(.aggregate).?.data[start..end]), | |
| 1695 | else => unreachable, | |
| 1696 | }, | |
| 1697 | else => switch (mod.intern_pool.indexToKey(val.toIntern())) { | |
| 1698 | .ptr => |ptr| switch (ptr.addr) { | |
| 1699 | .decl => |decl| try mod.declPtr(decl).val.sliceArray(sema, start, end), | |
| 1700 | .comptime_alloc => |idx| sema.getComptimeAlloc(idx).val.sliceArray(sema, start, end), | |
| 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 | } }))), | |
| 1323 | const aggregate = mod.intern_pool.indexToKey(val.toIntern()).aggregate; | |
| 1324 | return Value.fromInterned(try mod.intern(.{ .aggregate = .{ | |
| 1325 | .ty = switch (mod.intern_pool.indexToKey(mod.intern_pool.typeOf(val.toIntern()))) { | |
| 1326 | .array_type => |array_type| try mod.arrayType(.{ | |
| 1327 | .len = @as(u32, @intCast(end - start)), | |
| 1328 | .child = array_type.child, | |
| 1329 | .sentinel = if (end == array_type.len) array_type.sentinel else .none, | |
| 1330 | }), | |
| 1331 | .vector_type => |vector_type| try mod.vectorType(.{ | |
| 1332 | .len = @as(u32, @intCast(end - start)), | |
| 1333 | .child = vector_type.child, | |
| 1334 | }), | |
| 1726 | 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 | } |
| 1730 | 1344 | |
| 1731 | 1345 | pub fn fieldValue(val: Value, mod: *Module, index: usize) !Value { |
| 1732 | return switch (val.ip_index) { | |
| 1733 | .none => switch (val.tag()) { | |
| 1734 | .aggregate => { | |
| 1735 | const field_values = val.castTag(.aggregate).?.data; | |
| 1736 | return field_values[index]; | |
| 1737 | }, | |
| 1738 | .@"union" => { | |
| 1739 | const payload = val.castTag(.@"union").?.data; | |
| 1740 | // TODO assert the tag is correct | |
| 1741 | return payload.val; | |
| 1742 | }, | |
| 1743 | else => unreachable, | |
| 1744 | }, | |
| 1745 | else => switch (mod.intern_pool.indexToKey(val.toIntern())) { | |
| 1746 | .undef => |ty| Value.fromInterned((try mod.intern(.{ | |
| 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 | }, | |
| 1346 | return switch (mod.intern_pool.indexToKey(val.toIntern())) { | |
| 1347 | .undef => |ty| Value.fromInterned((try mod.intern(.{ | |
| 1348 | .undef = Type.fromInterned(ty).structFieldType(index, mod).toIntern(), | |
| 1349 | }))), | |
| 1350 | .aggregate => |aggregate| Value.fromInterned(switch (aggregate.storage) { | |
| 1351 | .bytes => |bytes| try mod.intern(.{ .int = .{ | |
| 1352 | .ty = .u8_type, | |
| 1353 | .storage = .{ .u64 = bytes[index] }, | |
| 1354 | } }), | |
| 1355 | .elems => |elems| elems[index], | |
| 1356 | .repeated_elem => |elem| elem, | |
| 1357 | }), | |
| 1358 | // TODO assert the tag is correct | |
| 1359 | .un => |un| Value.fromInterned(un.val), | |
| 1360 | else => unreachable, | |
| 1761 | 1361 | }; |
| 1762 | 1362 | } |
| 1763 | 1363 | |
| 1764 | 1364 | pub fn unionTag(val: Value, mod: *Module) ?Value { |
| 1765 | if (val.ip_index == .none) return val.castTag(.@"union").?.data.tag; | |
| 1766 | 1365 | return switch (mod.intern_pool.indexToKey(val.toIntern())) { |
| 1767 | 1366 | .undef, .enum_tag => val, |
| 1768 | 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 | 1370 | } |
| 1772 | 1371 | |
| 1773 | 1372 | pub fn unionValue(val: Value, mod: *Module) Value { |
| 1774 | if (val.ip_index == .none) return val.castTag(.@"union").?.data.val; | |
| 1775 | 1373 | return switch (mod.intern_pool.indexToKey(val.toIntern())) { |
| 1776 | 1374 | .un => |un| Value.fromInterned(un.val), |
| 1777 | 1375 | else => unreachable, |
| ... | ... | @@ -1792,7 +1390,7 @@ pub fn elemPtr( |
| 1792 | 1390 | }; |
| 1793 | 1391 | switch (mod.intern_pool.indexToKey(ptr_val.toIntern())) { |
| 1794 | 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 | 1394 | return Value.fromInterned((try mod.intern(.{ .ptr = .{ |
| 1797 | 1395 | .ty = elem_ptr_ty.toIntern(), |
| 1798 | 1396 | .addr = .{ .elem = .{ |
| ... | ... | @@ -1817,7 +1415,7 @@ pub fn elemPtr( |
| 1817 | 1415 | } |
| 1818 | 1416 | |
| 1819 | 1417 | pub 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 | } |
| 1822 | 1420 | |
| 1823 | 1421 | /// 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 | 1509 | const scalar_ty = float_ty.scalarType(mod); |
| 1912 | 1510 | for (result_data, 0..) |*scalar, i| { |
| 1913 | 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 | 1514 | return Value.fromInterned((try mod.intern(.{ .aggregate = .{ |
| 1917 | 1515 | .ty = float_ty.toIntern(), |
| ... | ... | @@ -1989,7 +1587,7 @@ pub fn intAddSat( |
| 1989 | 1587 | for (result_data, 0..) |*scalar, i| { |
| 1990 | 1588 | const lhs_elem = try lhs.elemValue(mod, i); |
| 1991 | 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 | 1592 | return Value.fromInterned((try mod.intern(.{ .aggregate = .{ |
| 1995 | 1593 | .ty = ty.toIntern(), |
| ... | ... | @@ -2039,7 +1637,7 @@ pub fn intSubSat( |
| 2039 | 1637 | for (result_data, 0..) |*scalar, i| { |
| 2040 | 1638 | const lhs_elem = try lhs.elemValue(mod, i); |
| 2041 | 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 | 1642 | return Value.fromInterned((try mod.intern(.{ .aggregate = .{ |
| 2045 | 1643 | .ty = ty.toIntern(), |
| ... | ... | @@ -2091,8 +1689,8 @@ pub fn intMulWithOverflow( |
| 2091 | 1689 | const lhs_elem = try lhs.elemValue(mod, i); |
| 2092 | 1690 | const rhs_elem = try rhs.elemValue(mod, i); |
| 2093 | 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); | |
| 2095 | scalar.* = try of_math_result.wrapped_result.intern(scalar_ty, mod); | |
| 1692 | of.* = of_math_result.overflow_bit.toIntern(); | |
| 1693 | scalar.* = of_math_result.wrapped_result.toIntern(); | |
| 2096 | 1694 | } |
| 2097 | 1695 | return OverflowArithmeticResult{ |
| 2098 | 1696 | .overflow_bit = Value.fromInterned((try mod.intern(.{ .aggregate = .{ |
| ... | ... | @@ -2157,7 +1755,7 @@ pub fn numberMulWrap( |
| 2157 | 1755 | for (result_data, 0..) |*scalar, i| { |
| 2158 | 1756 | const lhs_elem = try lhs.elemValue(mod, i); |
| 2159 | 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 | 1760 | return Value.fromInterned((try mod.intern(.{ .aggregate = .{ |
| 2163 | 1761 | .ty = ty.toIntern(), |
| ... | ... | @@ -2203,7 +1801,7 @@ pub fn intMulSat( |
| 2203 | 1801 | for (result_data, 0..) |*scalar, i| { |
| 2204 | 1802 | const lhs_elem = try lhs.elemValue(mod, i); |
| 2205 | 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 | 1806 | return Value.fromInterned((try mod.intern(.{ .aggregate = .{ |
| 2209 | 1807 | .ty = ty.toIntern(), |
| ... | ... | @@ -2279,7 +1877,7 @@ pub fn bitwiseNot(val: Value, ty: Type, arena: Allocator, mod: *Module) !Value { |
| 2279 | 1877 | const scalar_ty = ty.scalarType(mod); |
| 2280 | 1878 | for (result_data, 0..) |*scalar, i| { |
| 2281 | 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 | 1882 | return Value.fromInterned((try mod.intern(.{ .aggregate = .{ |
| 2285 | 1883 | .ty = ty.toIntern(), |
| ... | ... | @@ -2322,7 +1920,7 @@ pub fn bitwiseAnd(lhs: Value, rhs: Value, ty: Type, allocator: Allocator, mod: * |
| 2322 | 1920 | for (result_data, 0..) |*scalar, i| { |
| 2323 | 1921 | const lhs_elem = try lhs.elemValue(mod, i); |
| 2324 | 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 | 1925 | return Value.fromInterned((try mod.intern(.{ .aggregate = .{ |
| 2328 | 1926 | .ty = ty.toIntern(), |
| ... | ... | @@ -2361,7 +1959,7 @@ pub fn bitwiseNand(lhs: Value, rhs: Value, ty: Type, arena: Allocator, mod: *Mod |
| 2361 | 1959 | for (result_data, 0..) |*scalar, i| { |
| 2362 | 1960 | const lhs_elem = try lhs.elemValue(mod, i); |
| 2363 | 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 | 1964 | return Value.fromInterned((try mod.intern(.{ .aggregate = .{ |
| 2367 | 1965 | .ty = ty.toIntern(), |
| ... | ... | @@ -2389,7 +1987,7 @@ pub fn bitwiseOr(lhs: Value, rhs: Value, ty: Type, allocator: Allocator, mod: *M |
| 2389 | 1987 | for (result_data, 0..) |*scalar, i| { |
| 2390 | 1988 | const lhs_elem = try lhs.elemValue(mod, i); |
| 2391 | 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 | 1992 | return Value.fromInterned((try mod.intern(.{ .aggregate = .{ |
| 2395 | 1993 | .ty = ty.toIntern(), |
| ... | ... | @@ -2427,7 +2025,7 @@ pub fn bitwiseXor(lhs: Value, rhs: Value, ty: Type, allocator: Allocator, mod: * |
| 2427 | 2025 | for (result_data, 0..) |*scalar, i| { |
| 2428 | 2026 | const lhs_elem = try lhs.elemValue(mod, i); |
| 2429 | 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 | 2030 | return Value.fromInterned((try mod.intern(.{ .aggregate = .{ |
| 2433 | 2031 | .ty = ty.toIntern(), |
| ... | ... | @@ -2493,7 +2091,7 @@ fn intDivInner(lhs: Value, rhs: Value, ty: Type, overflow_idx: *usize, allocator |
| 2493 | 2091 | }, |
| 2494 | 2092 | else => |e| return e, |
| 2495 | 2093 | }; |
| 2496 | scalar.* = try val.intern(scalar_ty, mod); | |
| 2094 | scalar.* = val.toIntern(); | |
| 2497 | 2095 | } |
| 2498 | 2096 | return Value.fromInterned((try mod.intern(.{ .aggregate = .{ |
| 2499 | 2097 | .ty = ty.toIntern(), |
| ... | ... | @@ -2541,7 +2139,7 @@ pub fn intDivFloor(lhs: Value, rhs: Value, ty: Type, allocator: Allocator, mod: |
| 2541 | 2139 | for (result_data, 0..) |*scalar, i| { |
| 2542 | 2140 | const lhs_elem = try lhs.elemValue(mod, i); |
| 2543 | 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 | 2144 | return Value.fromInterned((try mod.intern(.{ .aggregate = .{ |
| 2547 | 2145 | .ty = ty.toIntern(), |
| ... | ... | @@ -2583,7 +2181,7 @@ pub fn intMod(lhs: Value, rhs: Value, ty: Type, allocator: Allocator, mod: *Modu |
| 2583 | 2181 | for (result_data, 0..) |*scalar, i| { |
| 2584 | 2182 | const lhs_elem = try lhs.elemValue(mod, i); |
| 2585 | 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 | 2186 | return Value.fromInterned((try mod.intern(.{ .aggregate = .{ |
| 2589 | 2187 | .ty = ty.toIntern(), |
| ... | ... | @@ -2620,7 +2218,6 @@ pub fn intModScalar(lhs: Value, rhs: Value, ty: Type, allocator: Allocator, mod: |
| 2620 | 2218 | |
| 2621 | 2219 | /// Returns true if the value is a floating point type and is NaN. Returns false otherwise. |
| 2622 | 2220 | pub fn isNan(val: Value, mod: *const Module) bool { |
| 2623 | if (val.ip_index == .none) return false; | |
| 2624 | 2221 | return switch (mod.intern_pool.indexToKey(val.toIntern())) { |
| 2625 | 2222 | .float => |float| switch (float.storage) { |
| 2626 | 2223 | inline else => |x| std.math.isNan(x), |
| ... | ... | @@ -2631,7 +2228,6 @@ pub fn isNan(val: Value, mod: *const Module) bool { |
| 2631 | 2228 | |
| 2632 | 2229 | /// Returns true if the value is a floating point type and is infinite. Returns false otherwise. |
| 2633 | 2230 | pub fn isInf(val: Value, mod: *const Module) bool { |
| 2634 | if (val.ip_index == .none) return false; | |
| 2635 | 2231 | return switch (mod.intern_pool.indexToKey(val.toIntern())) { |
| 2636 | 2232 | .float => |float| switch (float.storage) { |
| 2637 | 2233 | inline else => |x| std.math.isInf(x), |
| ... | ... | @@ -2641,7 +2237,6 @@ pub fn isInf(val: Value, mod: *const Module) bool { |
| 2641 | 2237 | } |
| 2642 | 2238 | |
| 2643 | 2239 | pub fn isNegativeInf(val: Value, mod: *const Module) bool { |
| 2644 | if (val.ip_index == .none) return false; | |
| 2645 | 2240 | return switch (mod.intern_pool.indexToKey(val.toIntern())) { |
| 2646 | 2241 | .float => |float| switch (float.storage) { |
| 2647 | 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 | 2252 | for (result_data, 0..) |*scalar, i| { |
| 2658 | 2253 | const lhs_elem = try lhs.elemValue(mod, i); |
| 2659 | 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 | 2257 | return Value.fromInterned((try mod.intern(.{ .aggregate = .{ |
| 2663 | 2258 | .ty = float_type.toIntern(), |
| ... | ... | @@ -2690,7 +2285,7 @@ pub fn floatMod(lhs: Value, rhs: Value, float_type: Type, arena: Allocator, mod: |
| 2690 | 2285 | for (result_data, 0..) |*scalar, i| { |
| 2691 | 2286 | const lhs_elem = try lhs.elemValue(mod, i); |
| 2692 | 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 | 2290 | return Value.fromInterned((try mod.intern(.{ .aggregate = .{ |
| 2696 | 2291 | .ty = float_type.toIntern(), |
| ... | ... | @@ -2751,7 +2346,7 @@ fn intMulInner(lhs: Value, rhs: Value, ty: Type, overflow_idx: *usize, allocator |
| 2751 | 2346 | }, |
| 2752 | 2347 | else => |e| return e, |
| 2753 | 2348 | }; |
| 2754 | scalar.* = try val.intern(scalar_ty, mod); | |
| 2349 | scalar.* = val.toIntern(); | |
| 2755 | 2350 | } |
| 2756 | 2351 | return Value.fromInterned((try mod.intern(.{ .aggregate = .{ |
| 2757 | 2352 | .ty = ty.toIntern(), |
| ... | ... | @@ -2793,7 +2388,7 @@ pub fn intTrunc(val: Value, ty: Type, allocator: Allocator, signedness: std.buil |
| 2793 | 2388 | const scalar_ty = ty.scalarType(mod); |
| 2794 | 2389 | for (result_data, 0..) |*scalar, i| { |
| 2795 | 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 | 2393 | return Value.fromInterned((try mod.intern(.{ .aggregate = .{ |
| 2799 | 2394 | .ty = ty.toIntern(), |
| ... | ... | @@ -2818,7 +2413,7 @@ pub fn intTruncBitsAsValue( |
| 2818 | 2413 | for (result_data, 0..) |*scalar, i| { |
| 2819 | 2414 | const elem_val = try val.elemValue(mod, i); |
| 2820 | 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 | 2418 | return Value.fromInterned((try mod.intern(.{ .aggregate = .{ |
| 2824 | 2419 | .ty = ty.toIntern(), |
| ... | ... | @@ -2858,7 +2453,7 @@ pub fn shl(lhs: Value, rhs: Value, ty: Type, allocator: Allocator, mod: *Module) |
| 2858 | 2453 | for (result_data, 0..) |*scalar, i| { |
| 2859 | 2454 | const lhs_elem = try lhs.elemValue(mod, i); |
| 2860 | 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 | 2458 | return Value.fromInterned((try mod.intern(.{ .aggregate = .{ |
| 2864 | 2459 | .ty = ty.toIntern(), |
| ... | ... | @@ -2908,8 +2503,8 @@ pub fn shlWithOverflow( |
| 2908 | 2503 | const lhs_elem = try lhs.elemValue(mod, i); |
| 2909 | 2504 | const rhs_elem = try rhs.elemValue(mod, i); |
| 2910 | 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); | |
| 2912 | scalar.* = try of_math_result.wrapped_result.intern(scalar_ty, mod); | |
| 2506 | of.* = of_math_result.overflow_bit.toIntern(); | |
| 2507 | scalar.* = of_math_result.wrapped_result.toIntern(); | |
| 2913 | 2508 | } |
| 2914 | 2509 | return OverflowArithmeticResult{ |
| 2915 | 2510 | .overflow_bit = Value.fromInterned((try mod.intern(.{ .aggregate = .{ |
| ... | ... | @@ -2969,7 +2564,7 @@ pub fn shlSat( |
| 2969 | 2564 | for (result_data, 0..) |*scalar, i| { |
| 2970 | 2565 | const lhs_elem = try lhs.elemValue(mod, i); |
| 2971 | 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 | 2569 | return Value.fromInterned((try mod.intern(.{ .aggregate = .{ |
| 2975 | 2570 | .ty = ty.toIntern(), |
| ... | ... | @@ -3019,7 +2614,7 @@ pub fn shlTrunc( |
| 3019 | 2614 | for (result_data, 0..) |*scalar, i| { |
| 3020 | 2615 | const lhs_elem = try lhs.elemValue(mod, i); |
| 3021 | 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 | 2619 | return Value.fromInterned((try mod.intern(.{ .aggregate = .{ |
| 3025 | 2620 | .ty = ty.toIntern(), |
| ... | ... | @@ -3049,7 +2644,7 @@ pub fn shr(lhs: Value, rhs: Value, ty: Type, allocator: Allocator, mod: *Module) |
| 3049 | 2644 | for (result_data, 0..) |*scalar, i| { |
| 3050 | 2645 | const lhs_elem = try lhs.elemValue(mod, i); |
| 3051 | 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 | 2649 | return Value.fromInterned((try mod.intern(.{ .aggregate = .{ |
| 3055 | 2650 | .ty = ty.toIntern(), |
| ... | ... | @@ -3101,7 +2696,7 @@ pub fn floatNeg( |
| 3101 | 2696 | const scalar_ty = float_type.scalarType(mod); |
| 3102 | 2697 | for (result_data, 0..) |*scalar, i| { |
| 3103 | 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 | 2701 | return Value.fromInterned((try mod.intern(.{ .aggregate = .{ |
| 3107 | 2702 | .ty = float_type.toIntern(), |
| ... | ... | @@ -3144,7 +2739,7 @@ pub fn floatAdd( |
| 3144 | 2739 | for (result_data, 0..) |*scalar, i| { |
| 3145 | 2740 | const lhs_elem = try lhs.elemValue(mod, i); |
| 3146 | 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 | 2744 | return Value.fromInterned((try mod.intern(.{ .aggregate = .{ |
| 3150 | 2745 | .ty = float_type.toIntern(), |
| ... | ... | @@ -3188,7 +2783,7 @@ pub fn floatSub( |
| 3188 | 2783 | for (result_data, 0..) |*scalar, i| { |
| 3189 | 2784 | const lhs_elem = try lhs.elemValue(mod, i); |
| 3190 | 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 | 2788 | return Value.fromInterned((try mod.intern(.{ .aggregate = .{ |
| 3194 | 2789 | .ty = float_type.toIntern(), |
| ... | ... | @@ -3232,7 +2827,7 @@ pub fn floatDiv( |
| 3232 | 2827 | for (result_data, 0..) |*scalar, i| { |
| 3233 | 2828 | const lhs_elem = try lhs.elemValue(mod, i); |
| 3234 | 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 | 2832 | return Value.fromInterned((try mod.intern(.{ .aggregate = .{ |
| 3238 | 2833 | .ty = float_type.toIntern(), |
| ... | ... | @@ -3276,7 +2871,7 @@ pub fn floatDivFloor( |
| 3276 | 2871 | for (result_data, 0..) |*scalar, i| { |
| 3277 | 2872 | const lhs_elem = try lhs.elemValue(mod, i); |
| 3278 | 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 | 2876 | return Value.fromInterned((try mod.intern(.{ .aggregate = .{ |
| 3282 | 2877 | .ty = float_type.toIntern(), |
| ... | ... | @@ -3320,7 +2915,7 @@ pub fn floatDivTrunc( |
| 3320 | 2915 | for (result_data, 0..) |*scalar, i| { |
| 3321 | 2916 | const lhs_elem = try lhs.elemValue(mod, i); |
| 3322 | 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 | 2920 | return Value.fromInterned((try mod.intern(.{ .aggregate = .{ |
| 3326 | 2921 | .ty = float_type.toIntern(), |
| ... | ... | @@ -3364,7 +2959,7 @@ pub fn floatMul( |
| 3364 | 2959 | for (result_data, 0..) |*scalar, i| { |
| 3365 | 2960 | const lhs_elem = try lhs.elemValue(mod, i); |
| 3366 | 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 | 2964 | return Value.fromInterned((try mod.intern(.{ .aggregate = .{ |
| 3370 | 2965 | .ty = float_type.toIntern(), |
| ... | ... | @@ -3401,7 +2996,7 @@ pub fn sqrt(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Value |
| 3401 | 2996 | const scalar_ty = float_type.scalarType(mod); |
| 3402 | 2997 | for (result_data, 0..) |*scalar, i| { |
| 3403 | 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 | 3001 | return Value.fromInterned((try mod.intern(.{ .aggregate = .{ |
| 3407 | 3002 | .ty = float_type.toIntern(), |
| ... | ... | @@ -3433,7 +3028,7 @@ pub fn sin(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Value |
| 3433 | 3028 | const scalar_ty = float_type.scalarType(mod); |
| 3434 | 3029 | for (result_data, 0..) |*scalar, i| { |
| 3435 | 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 | 3033 | return Value.fromInterned((try mod.intern(.{ .aggregate = .{ |
| 3439 | 3034 | .ty = float_type.toIntern(), |
| ... | ... | @@ -3465,7 +3060,7 @@ pub fn cos(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Value |
| 3465 | 3060 | const scalar_ty = float_type.scalarType(mod); |
| 3466 | 3061 | for (result_data, 0..) |*scalar, i| { |
| 3467 | 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 | 3065 | return Value.fromInterned((try mod.intern(.{ .aggregate = .{ |
| 3471 | 3066 | .ty = float_type.toIntern(), |
| ... | ... | @@ -3497,7 +3092,7 @@ pub fn tan(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Value |
| 3497 | 3092 | const scalar_ty = float_type.scalarType(mod); |
| 3498 | 3093 | for (result_data, 0..) |*scalar, i| { |
| 3499 | 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 | 3097 | return Value.fromInterned((try mod.intern(.{ .aggregate = .{ |
| 3503 | 3098 | .ty = float_type.toIntern(), |
| ... | ... | @@ -3529,7 +3124,7 @@ pub fn exp(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Value |
| 3529 | 3124 | const scalar_ty = float_type.scalarType(mod); |
| 3530 | 3125 | for (result_data, 0..) |*scalar, i| { |
| 3531 | 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 | 3129 | return Value.fromInterned((try mod.intern(.{ .aggregate = .{ |
| 3535 | 3130 | .ty = float_type.toIntern(), |
| ... | ... | @@ -3561,7 +3156,7 @@ pub fn exp2(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Value |
| 3561 | 3156 | const scalar_ty = float_type.scalarType(mod); |
| 3562 | 3157 | for (result_data, 0..) |*scalar, i| { |
| 3563 | 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 | 3161 | return Value.fromInterned((try mod.intern(.{ .aggregate = .{ |
| 3567 | 3162 | .ty = float_type.toIntern(), |
| ... | ... | @@ -3593,7 +3188,7 @@ pub fn log(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Value |
| 3593 | 3188 | const scalar_ty = float_type.scalarType(mod); |
| 3594 | 3189 | for (result_data, 0..) |*scalar, i| { |
| 3595 | 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 | 3193 | return Value.fromInterned((try mod.intern(.{ .aggregate = .{ |
| 3599 | 3194 | .ty = float_type.toIntern(), |
| ... | ... | @@ -3625,7 +3220,7 @@ pub fn log2(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Value |
| 3625 | 3220 | const scalar_ty = float_type.scalarType(mod); |
| 3626 | 3221 | for (result_data, 0..) |*scalar, i| { |
| 3627 | 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 | 3225 | return Value.fromInterned((try mod.intern(.{ .aggregate = .{ |
| 3631 | 3226 | .ty = float_type.toIntern(), |
| ... | ... | @@ -3657,7 +3252,7 @@ pub fn log10(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Valu |
| 3657 | 3252 | const scalar_ty = float_type.scalarType(mod); |
| 3658 | 3253 | for (result_data, 0..) |*scalar, i| { |
| 3659 | 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 | 3257 | return Value.fromInterned((try mod.intern(.{ .aggregate = .{ |
| 3663 | 3258 | .ty = float_type.toIntern(), |
| ... | ... | @@ -3689,7 +3284,7 @@ pub fn abs(val: Value, ty: Type, arena: Allocator, mod: *Module) !Value { |
| 3689 | 3284 | const scalar_ty = ty.scalarType(mod); |
| 3690 | 3285 | for (result_data, 0..) |*scalar, i| { |
| 3691 | 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 | 3289 | return Value.fromInterned((try mod.intern(.{ .aggregate = .{ |
| 3695 | 3290 | .ty = ty.toIntern(), |
| ... | ... | @@ -3740,7 +3335,7 @@ pub fn floor(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Valu |
| 3740 | 3335 | const scalar_ty = float_type.scalarType(mod); |
| 3741 | 3336 | for (result_data, 0..) |*scalar, i| { |
| 3742 | 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 | 3340 | return Value.fromInterned((try mod.intern(.{ .aggregate = .{ |
| 3746 | 3341 | .ty = float_type.toIntern(), |
| ... | ... | @@ -3772,7 +3367,7 @@ pub fn ceil(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Value |
| 3772 | 3367 | const scalar_ty = float_type.scalarType(mod); |
| 3773 | 3368 | for (result_data, 0..) |*scalar, i| { |
| 3774 | 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 | 3372 | return Value.fromInterned((try mod.intern(.{ .aggregate = .{ |
| 3778 | 3373 | .ty = float_type.toIntern(), |
| ... | ... | @@ -3804,7 +3399,7 @@ pub fn round(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Valu |
| 3804 | 3399 | const scalar_ty = float_type.scalarType(mod); |
| 3805 | 3400 | for (result_data, 0..) |*scalar, i| { |
| 3806 | 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 | 3404 | return Value.fromInterned((try mod.intern(.{ .aggregate = .{ |
| 3810 | 3405 | .ty = float_type.toIntern(), |
| ... | ... | @@ -3836,7 +3431,7 @@ pub fn trunc(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Valu |
| 3836 | 3431 | const scalar_ty = float_type.scalarType(mod); |
| 3837 | 3432 | for (result_data, 0..) |*scalar, i| { |
| 3838 | 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 | 3436 | return Value.fromInterned((try mod.intern(.{ .aggregate = .{ |
| 3842 | 3437 | .ty = float_type.toIntern(), |
| ... | ... | @@ -3877,7 +3472,7 @@ pub fn mulAdd( |
| 3877 | 3472 | const mulend1_elem = try mulend1.elemValue(mod, i); |
| 3878 | 3473 | const mulend2_elem = try mulend2.elemValue(mod, i); |
| 3879 | 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 | 3477 | return Value.fromInterned((try mod.intern(.{ .aggregate = .{ |
| 3883 | 3478 | .ty = float_type.toIntern(), |
| ... | ... | @@ -3939,6 +3534,10 @@ pub fn isGenericPoison(val: Value) bool { |
| 3939 | 3534 | return val.toIntern() == .generic_poison; |
| 3940 | 3535 | } |
| 3941 | 3536 | |
| 3537 | pub fn typeOf(val: Value, zcu: *const Zcu) Type { | |
| 3538 | return Type.fromInterned(zcu.intern_pool.typeOf(val.toIntern())); | |
| 3539 | } | |
| 3540 | ||
| 3942 | 3541 | /// For an integer (comptime or fixed-width) `val`, returns the comptime-known bounds of the value. |
| 3943 | 3542 | /// If `val` is not undef, the bounds are both `val`. |
| 3944 | 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 | 3552 | }; |
| 3954 | 3553 | } |
| 3955 | 3554 | |
| 3956 | /// This type is not copyable since it may contain pointers to its inner data. | |
| 3957 | pub 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 | ||
| 3999 | 3555 | pub const BigIntSpace = InternPool.Key.Int.Storage.BigIntSpace; |
| 4000 | 3556 | |
| 4001 | pub const zero_usize: Value = .{ .ip_index = .zero_usize, .legacy = undefined }; | |
| 4002 | pub const zero_u8: Value = .{ .ip_index = .zero_u8, .legacy = undefined }; | |
| 4003 | pub const zero_comptime_int: Value = .{ .ip_index = .zero, .legacy = undefined }; | |
| 4004 | pub const one_comptime_int: Value = .{ .ip_index = .one, .legacy = undefined }; | |
| 4005 | pub const negative_one_comptime_int: Value = .{ .ip_index = .negative_one, .legacy = undefined }; | |
| 4006 | pub const undef: Value = .{ .ip_index = .undef, .legacy = undefined }; | |
| 4007 | pub const @"void": Value = .{ .ip_index = .void_value, .legacy = undefined }; | |
| 4008 | pub const @"null": Value = .{ .ip_index = .null_value, .legacy = undefined }; | |
| 4009 | pub const @"false": Value = .{ .ip_index = .bool_false, .legacy = undefined }; | |
| 4010 | pub const @"true": Value = .{ .ip_index = .bool_true, .legacy = undefined }; | |
| 4011 | pub const @"unreachable": Value = .{ .ip_index = .unreachable_value, .legacy = undefined }; | |
| 4012 | ||
| 4013 | pub const generic_poison: Value = .{ .ip_index = .generic_poison, .legacy = undefined }; | |
| 4014 | pub const generic_poison_type: Value = .{ .ip_index = .generic_poison_type, .legacy = undefined }; | |
| 4015 | pub const empty_struct: Value = .{ .ip_index = .empty_struct, .legacy = undefined }; | |
| 3557 | pub const zero_usize: Value = .{ .ip_index = .zero_usize }; | |
| 3558 | pub const zero_u8: Value = .{ .ip_index = .zero_u8 }; | |
| 3559 | pub const zero_comptime_int: Value = .{ .ip_index = .zero }; | |
| 3560 | pub const one_comptime_int: Value = .{ .ip_index = .one }; | |
| 3561 | pub const negative_one_comptime_int: Value = .{ .ip_index = .negative_one }; | |
| 3562 | pub const undef: Value = .{ .ip_index = .undef }; | |
| 3563 | pub const @"void": Value = .{ .ip_index = .void_value }; | |
| 3564 | pub const @"null": Value = .{ .ip_index = .null_value }; | |
| 3565 | pub const @"false": Value = .{ .ip_index = .bool_false }; | |
| 3566 | pub const @"true": Value = .{ .ip_index = .bool_true }; | |
| 3567 | pub const @"unreachable": Value = .{ .ip_index = .unreachable_value }; | |
| 3568 | ||
| 3569 | pub const generic_poison: Value = .{ .ip_index = .generic_poison }; | |
| 3570 | pub const generic_poison_type: Value = .{ .ip_index = .generic_poison_type }; | |
| 3571 | pub const empty_struct: Value = .{ .ip_index = .empty_struct }; | |
| 4016 | 3572 | |
| 4017 | 3573 | pub fn makeBool(x: bool) Value { |
| 4018 | 3574 | return if (x) Value.true else Value.false; |
| 4019 | 3575 | } |
| 4020 | 3576 | |
| 4021 | 3577 | pub 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. | |
| 4025 | fn 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 | ||
| 4046 | comptime { | |
| 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 | 10 | const Liveness = @import("../../Liveness.zig"); |
| 11 | 11 | const Type = @import("../../type.zig").Type; |
| 12 | 12 | const Value = @import("../../Value.zig"); |
| 13 | const TypedValue = @import("../../TypedValue.zig"); | |
| 14 | 13 | const link = @import("../../link.zig"); |
| 15 | 14 | const Module = @import("../../Module.zig"); |
| 16 | 15 | const InternPool = @import("../../InternPool.zig"); |
| ... | ... | @@ -342,7 +341,7 @@ pub fn generate( |
| 342 | 341 | const func = zcu.funcInfo(func_index); |
| 343 | 342 | const fn_owner_decl = zcu.declPtr(func.owner_decl); |
| 344 | 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 | 345 | const namespace = zcu.namespacePtr(fn_owner_decl.src_namespace); |
| 347 | 346 | const target = &namespace.file_scope.mod.resolved_target.result; |
| 348 | 347 | |
| ... | ... | @@ -6143,10 +6142,7 @@ fn resolveInst(self: *Self, inst: Air.Inst.Ref) InnerError!MCValue { |
| 6143 | 6142 | if (!inst_ty.hasRuntimeBitsIgnoreComptime(mod) and !inst_ty.isError(mod)) |
| 6144 | 6143 | return MCValue{ .none = {} }; |
| 6145 | 6144 | |
| 6146 | const inst_index = inst.toIndex() orelse return self.genTypedValue(.{ | |
| 6147 | .ty = inst_ty, | |
| 6148 | .val = (try self.air.value(inst, mod)).?, | |
| 6149 | }); | |
| 6145 | const inst_index = inst.toIndex() orelse return self.genTypedValue((try self.air.value(inst, mod)).?); | |
| 6150 | 6146 | |
| 6151 | 6147 | return self.getResolvedInstValue(inst_index); |
| 6152 | 6148 | } |
| ... | ... | @@ -6163,11 +6159,11 @@ fn getResolvedInstValue(self: *Self, inst: Air.Inst.Index) MCValue { |
| 6163 | 6159 | } |
| 6164 | 6160 | } |
| 6165 | 6161 | |
| 6166 | fn genTypedValue(self: *Self, arg_tv: TypedValue) InnerError!MCValue { | |
| 6162 | fn genTypedValue(self: *Self, val: Value) InnerError!MCValue { | |
| 6167 | 6163 | const mcv: MCValue = switch (try codegen.genTypedValue( |
| 6168 | 6164 | self.bin_file, |
| 6169 | 6165 | self.src_loc, |
| 6170 | arg_tv, | |
| 6166 | val, | |
| 6171 | 6167 | self.owner_decl, |
| 6172 | 6168 | )) { |
| 6173 | 6169 | .mcv => |mcv| switch (mcv) { |
src/arch/arm/CodeGen.zig+4-8| ... | ... | @@ -10,7 +10,6 @@ const Emit = @import("Emit.zig"); |
| 10 | 10 | const Liveness = @import("../../Liveness.zig"); |
| 11 | 11 | const Type = @import("../../type.zig").Type; |
| 12 | 12 | const Value = @import("../../Value.zig"); |
| 13 | const TypedValue = @import("../../TypedValue.zig"); | |
| 14 | 13 | const link = @import("../../link.zig"); |
| 15 | 14 | const Module = @import("../../Module.zig"); |
| 16 | 15 | const InternPool = @import("../../InternPool.zig"); |
| ... | ... | @@ -349,7 +348,7 @@ pub fn generate( |
| 349 | 348 | const func = zcu.funcInfo(func_index); |
| 350 | 349 | const fn_owner_decl = zcu.declPtr(func.owner_decl); |
| 351 | 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 | 352 | const namespace = zcu.namespacePtr(fn_owner_decl.src_namespace); |
| 354 | 353 | const target = &namespace.file_scope.mod.resolved_target.result; |
| 355 | 354 | |
| ... | ... | @@ -6097,10 +6096,7 @@ fn resolveInst(self: *Self, inst: Air.Inst.Ref) InnerError!MCValue { |
| 6097 | 6096 | if (!inst_ty.hasRuntimeBitsIgnoreComptime(mod) and !inst_ty.isError(mod)) |
| 6098 | 6097 | return MCValue{ .none = {} }; |
| 6099 | 6098 | |
| 6100 | const inst_index = inst.toIndex() orelse return self.genTypedValue(.{ | |
| 6101 | .ty = inst_ty, | |
| 6102 | .val = (try self.air.value(inst, mod)).?, | |
| 6103 | }); | |
| 6099 | const inst_index = inst.toIndex() orelse return self.genTypedValue((try self.air.value(inst, mod)).?); | |
| 6104 | 6100 | |
| 6105 | 6101 | return self.getResolvedInstValue(inst_index); |
| 6106 | 6102 | } |
| ... | ... | @@ -6117,12 +6113,12 @@ fn getResolvedInstValue(self: *Self, inst: Air.Inst.Index) MCValue { |
| 6117 | 6113 | } |
| 6118 | 6114 | } |
| 6119 | 6115 | |
| 6120 | fn genTypedValue(self: *Self, arg_tv: TypedValue) InnerError!MCValue { | |
| 6116 | fn genTypedValue(self: *Self, val: Value) InnerError!MCValue { | |
| 6121 | 6117 | const mod = self.bin_file.comp.module.?; |
| 6122 | 6118 | const mcv: MCValue = switch (try codegen.genTypedValue( |
| 6123 | 6119 | self.bin_file, |
| 6124 | 6120 | self.src_loc, |
| 6125 | arg_tv, | |
| 6121 | val, | |
| 6126 | 6122 | mod.funcOwnerDeclIndex(self.func_index), |
| 6127 | 6123 | )) { |
| 6128 | 6124 | .mcv => |mcv| switch (mcv) { |
src/arch/riscv64/CodeGen.zig+4-8| ... | ... | @@ -9,7 +9,6 @@ const Emit = @import("Emit.zig"); |
| 9 | 9 | const Liveness = @import("../../Liveness.zig"); |
| 10 | 10 | const Type = @import("../../type.zig").Type; |
| 11 | 11 | const Value = @import("../../Value.zig"); |
| 12 | const TypedValue = @import("../../TypedValue.zig"); | |
| 13 | 12 | const link = @import("../../link.zig"); |
| 14 | 13 | const Module = @import("../../Module.zig"); |
| 15 | 14 | const InternPool = @import("../../InternPool.zig"); |
| ... | ... | @@ -230,7 +229,7 @@ pub fn generate( |
| 230 | 229 | const func = zcu.funcInfo(func_index); |
| 231 | 230 | const fn_owner_decl = zcu.declPtr(func.owner_decl); |
| 232 | 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 | 233 | const namespace = zcu.namespacePtr(fn_owner_decl.src_namespace); |
| 235 | 234 | const target = &namespace.file_scope.mod.resolved_target.result; |
| 236 | 235 | |
| ... | ... | @@ -2552,10 +2551,7 @@ fn resolveInst(self: *Self, inst: Air.Inst.Ref) InnerError!MCValue { |
| 2552 | 2551 | if (!inst_ty.hasRuntimeBits(mod)) |
| 2553 | 2552 | return MCValue{ .none = {} }; |
| 2554 | 2553 | |
| 2555 | const inst_index = inst.toIndex() orelse return self.genTypedValue(.{ | |
| 2556 | .ty = inst_ty, | |
| 2557 | .val = (try self.air.value(inst, mod)).?, | |
| 2558 | }); | |
| 2554 | const inst_index = inst.toIndex() orelse return self.genTypedValue((try self.air.value(inst, mod)).?); | |
| 2559 | 2555 | |
| 2560 | 2556 | return self.getResolvedInstValue(inst_index); |
| 2561 | 2557 | } |
| ... | ... | @@ -2572,12 +2568,12 @@ fn getResolvedInstValue(self: *Self, inst: Air.Inst.Index) MCValue { |
| 2572 | 2568 | } |
| 2573 | 2569 | } |
| 2574 | 2570 | |
| 2575 | fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue { | |
| 2571 | fn genTypedValue(self: *Self, val: Value) InnerError!MCValue { | |
| 2576 | 2572 | const mod = self.bin_file.comp.module.?; |
| 2577 | 2573 | const mcv: MCValue = switch (try codegen.genTypedValue( |
| 2578 | 2574 | self.bin_file, |
| 2579 | 2575 | self.src_loc, |
| 2580 | typed_value, | |
| 2576 | val, | |
| 2581 | 2577 | mod.funcOwnerDeclIndex(self.func_index), |
| 2582 | 2578 | )) { |
| 2583 | 2579 | .mcv => |mcv| switch (mcv) { |
src/arch/sparc64/CodeGen.zig+5-8| ... | ... | @@ -12,7 +12,7 @@ const builtin = @import("builtin"); |
| 12 | 12 | const link = @import("../../link.zig"); |
| 13 | 13 | const Module = @import("../../Module.zig"); |
| 14 | 14 | const InternPool = @import("../../InternPool.zig"); |
| 15 | const TypedValue = @import("../../TypedValue.zig"); | |
| 15 | const Value = @import("../../Value.zig"); | |
| 16 | 16 | const ErrorMsg = Module.ErrorMsg; |
| 17 | 17 | const codegen = @import("../../codegen.zig"); |
| 18 | 18 | const Air = @import("../../Air.zig"); |
| ... | ... | @@ -273,7 +273,7 @@ pub fn generate( |
| 273 | 273 | const func = zcu.funcInfo(func_index); |
| 274 | 274 | const fn_owner_decl = zcu.declPtr(func.owner_decl); |
| 275 | 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 | 277 | const namespace = zcu.namespacePtr(fn_owner_decl.src_namespace); |
| 278 | 278 | const target = &namespace.file_scope.mod.resolved_target.result; |
| 279 | 279 | |
| ... | ... | @@ -4118,12 +4118,12 @@ fn genStoreASI(self: *Self, value_reg: Register, addr_reg: Register, off_reg: Re |
| 4118 | 4118 | } |
| 4119 | 4119 | } |
| 4120 | 4120 | |
| 4121 | fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue { | |
| 4121 | fn genTypedValue(self: *Self, val: Value) InnerError!MCValue { | |
| 4122 | 4122 | const mod = self.bin_file.comp.module.?; |
| 4123 | 4123 | const mcv: MCValue = switch (try codegen.genTypedValue( |
| 4124 | 4124 | self.bin_file, |
| 4125 | 4125 | self.src_loc, |
| 4126 | typed_value, | |
| 4126 | val, | |
| 4127 | 4127 | mod.funcOwnerDeclIndex(self.func_index), |
| 4128 | 4128 | )) { |
| 4129 | 4129 | .mcv => |mcv| switch (mcv) { |
| ... | ... | @@ -4546,10 +4546,7 @@ fn resolveInst(self: *Self, ref: Air.Inst.Ref) InnerError!MCValue { |
| 4546 | 4546 | return self.getResolvedInstValue(inst); |
| 4547 | 4547 | } |
| 4548 | 4548 | |
| 4549 | return self.genTypedValue(.{ | |
| 4550 | .ty = ty, | |
| 4551 | .val = (try self.air.value(ref, mod)).?, | |
| 4552 | }); | |
| 4549 | return self.genTypedValue((try self.air.value(ref, mod)).?); | |
| 4553 | 4550 | } |
| 4554 | 4551 | |
| 4555 | 4552 | fn ret(self: *Self, mcv: MCValue) !void { |
src/arch/wasm/CodeGen.zig+25-30| ... | ... | @@ -18,7 +18,6 @@ const Value = @import("../../Value.zig"); |
| 18 | 18 | const Compilation = @import("../../Compilation.zig"); |
| 19 | 19 | const LazySrcLoc = std.zig.LazySrcLoc; |
| 20 | 20 | const link = @import("../../link.zig"); |
| 21 | const TypedValue = @import("../../TypedValue.zig"); | |
| 22 | 21 | const Air = @import("../../Air.zig"); |
| 23 | 22 | const Liveness = @import("../../Liveness.zig"); |
| 24 | 23 | const target_util = @import("../../target.zig"); |
| ... | ... | @@ -805,7 +804,7 @@ fn resolveInst(func: *CodeGen, ref: Air.Inst.Ref) InnerError!WValue { |
| 805 | 804 | // In the other cases, we will simply lower the constant to a value that fits |
| 806 | 805 | // into a single local (such as a pointer, integer, bool, etc). |
| 807 | 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 | 808 | break :blk WValue{ .memory = sym_index }; |
| 810 | 809 | } else try func.lowerConstant(val, ty); |
| 811 | 810 | |
| ... | ... | @@ -1243,12 +1242,12 @@ pub fn generate( |
| 1243 | 1242 | fn genFunc(func: *CodeGen) InnerError!void { |
| 1244 | 1243 | const mod = func.bin_file.base.comp.module.?; |
| 1245 | 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 | 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 | 1247 | defer func_type.deinit(func.gpa); |
| 1249 | 1248 | _ = try func.bin_file.storeDeclType(func.decl_index, func_type); |
| 1250 | 1249 | |
| 1251 | var cc_result = try func.resolveCallingConventionValues(func.decl.ty); | |
| 1250 | var cc_result = try func.resolveCallingConventionValues(func.decl.typeOf(mod)); | |
| 1252 | 1251 | defer cc_result.deinit(func.gpa); |
| 1253 | 1252 | |
| 1254 | 1253 | func.args = cc_result.args; |
| ... | ... | @@ -2087,7 +2086,7 @@ fn airRet(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 2087 | 2086 | const mod = func.bin_file.base.comp.module.?; |
| 2088 | 2087 | const un_op = func.air.instructions.items(.data)[@intFromEnum(inst)].un_op; |
| 2089 | 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 | 2090 | const ret_ty = Type.fromInterned(fn_info.return_type); |
| 2092 | 2091 | |
| 2093 | 2092 | // 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 | 2134 | break :result try func.allocStack(Type.usize); // create pointer to void |
| 2136 | 2135 | } |
| 2137 | 2136 | |
| 2138 | const fn_info = mod.typeToFunc(func.decl.ty).?; | |
| 2137 | const fn_info = mod.typeToFunc(func.decl.typeOf(mod)).?; | |
| 2139 | 2138 | if (firstParamSRet(fn_info.cc, Type.fromInterned(fn_info.return_type), mod)) { |
| 2140 | 2139 | break :result func.return_value; |
| 2141 | 2140 | } |
| ... | ... | @@ -2152,7 +2151,7 @@ fn airRetLoad(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 2152 | 2151 | const operand = try func.resolveInst(un_op); |
| 2153 | 2152 | const ret_ty = func.typeOf(un_op).childType(mod); |
| 2154 | 2153 | |
| 2155 | const fn_info = mod.typeToFunc(func.decl.ty).?; | |
| 2154 | const fn_info = mod.typeToFunc(func.decl.typeOf(mod)).?; | |
| 2156 | 2155 | if (!ret_ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 2157 | 2156 | if (ret_ty.isError(mod)) { |
| 2158 | 2157 | try func.addImm32(0); |
| ... | ... | @@ -2193,7 +2192,7 @@ fn airCall(func: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif |
| 2193 | 2192 | break :blk function.owner_decl; |
| 2194 | 2193 | } else if (func_val.getExternFunc(mod)) |extern_func| { |
| 2195 | 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 | 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 | 2197 | defer func_type.deinit(func.gpa); |
| 2199 | 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 | 2215 | }, |
| 2217 | 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 | }; |
| 2221 | 2220 | |
| 2222 | 2221 | const sret = if (first_param_sret) blk: { |
| ... | ... | @@ -2530,7 +2529,7 @@ fn airArg(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 2530 | 2529 | const mod = func.bin_file.base.comp.module.?; |
| 2531 | 2530 | const arg_index = func.arg_index; |
| 2532 | 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 | 2533 | const arg_ty = func.typeOfIndex(inst); |
| 2535 | 2534 | if (cc == .C) { |
| 2536 | 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 | 3118 | } |
| 3120 | 3119 | |
| 3121 | 3120 | fn lowerParentPtrDecl(func: *CodeGen, ptr_val: Value, decl_index: InternPool.DeclIndex, offset: u32) InnerError!WValue { |
| 3122 | const mod = func.bin_file.base.comp.module.?; | |
| 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); | |
| 3121 | return func.lowerDeclRefValue(ptr_val, decl_index, offset); | |
| 3127 | 3122 | } |
| 3128 | 3123 | |
| 3129 | 3124 | fn lowerAnonDeclRef( |
| ... | ... | @@ -3158,7 +3153,7 @@ fn lowerAnonDeclRef( |
| 3158 | 3153 | } else return WValue{ .memory_offset = .{ .pointer = target_sym_index, .offset = offset } }; |
| 3159 | 3154 | } |
| 3160 | 3155 | |
| 3161 | fn lowerDeclRefValue(func: *CodeGen, tv: TypedValue, decl_index: InternPool.DeclIndex, offset: u32) InnerError!WValue { | |
| 3156 | fn lowerDeclRefValue(func: *CodeGen, val: Value, decl_index: InternPool.DeclIndex, offset: u32) InnerError!WValue { | |
| 3162 | 3157 | const mod = func.bin_file.base.comp.module.?; |
| 3163 | 3158 | |
| 3164 | 3159 | const decl = mod.declPtr(decl_index); |
| ... | ... | @@ -3166,23 +3161,23 @@ fn lowerDeclRefValue(func: *CodeGen, tv: TypedValue, decl_index: InternPool.Decl |
| 3166 | 3161 | // want to lower the actual decl, rather than the alias itself. |
| 3167 | 3162 | if (decl.val.getFunction(mod)) |func_val| { |
| 3168 | 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 | 3166 | } else if (decl.val.getExternFunc(mod)) |func_val| { |
| 3172 | 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 | 3173 | return WValue{ .imm32 = 0xaaaaaaaa }; |
| 3178 | 3174 | } |
| 3179 | 3175 | |
| 3180 | try mod.markDeclAlive(decl); | |
| 3181 | 3176 | const atom_index = try func.bin_file.getOrCreateAtomForDecl(decl_index); |
| 3182 | 3177 | const atom = func.bin_file.getAtom(atom_index); |
| 3183 | 3178 | |
| 3184 | 3179 | const target_sym_index = @intFromEnum(atom.sym_index); |
| 3185 | if (decl.ty.zigTypeTag(mod) == .Fn) { | |
| 3180 | if (decl_ty.zigTypeTag(mod) == .Fn) { | |
| 3186 | 3181 | return WValue{ .function_index = target_sym_index }; |
| 3187 | 3182 | } else if (offset == 0) { |
| 3188 | 3183 | return WValue{ .memory = target_sym_index }; |
| ... | ... | @@ -3281,23 +3276,23 @@ fn lowerConstant(func: *CodeGen, val: Value, ty: Type) InnerError!WValue { |
| 3281 | 3276 | }, |
| 3282 | 3277 | .error_union => |error_union| { |
| 3283 | 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 | 3280 | .err_name => |err_name| .{ |
| 3286 | .ty = ty.errorUnionSet(mod), | |
| 3287 | .val = Value.fromInterned((try mod.intern(.{ .err = .{ | |
| 3281 | ty.errorUnionSet(mod), | |
| 3282 | Value.fromInterned((try mod.intern(.{ .err = .{ | |
| 3288 | 3283 | .ty = ty.errorUnionSet(mod).toIntern(), |
| 3289 | 3284 | .name = err_name, |
| 3290 | 3285 | } }))), |
| 3291 | 3286 | }, |
| 3292 | 3287 | .payload => .{ |
| 3293 | .ty = err_int_ty, | |
| 3294 | .val = try mod.intValue(err_int_ty, 0), | |
| 3288 | err_int_ty, | |
| 3289 | try mod.intValue(err_int_ty, 0), | |
| 3295 | 3290 | }, |
| 3296 | 3291 | }; |
| 3297 | 3292 | const payload_type = ty.errorUnionPayload(mod); |
| 3298 | 3293 | if (!payload_type.hasRuntimeBitsIgnoreComptime(mod)) { |
| 3299 | 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 | } |
| 3302 | 3297 | |
| 3303 | 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 | 3316 | .elem, .field => |base_index| ptr = ip.indexToKey(base_index.base).ptr, |
| 3322 | 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 | 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 | 3323 | .int => |int| return func.lowerConstant(Value.fromInterned(int), Type.fromInterned(ip.typeOf(int))), |
| 3329 | 3324 | .opt_payload, .elem, .field => return func.lowerParentPtr(val, 0), |
| 3330 | 3325 | .anon_decl => |ad| return func.lowerAnonDeclRef(ad, 0), |
| ... | ... | @@ -7286,7 +7281,7 @@ fn getTagNameFunction(func: *CodeGen, enum_ty: Type) InnerError!u32 { |
| 7286 | 7281 | .storage = .{ .bytes = tag_name }, |
| 7287 | 7282 | } }); |
| 7288 | 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 | 7285 | enum_decl_index, |
| 7291 | 7286 | ); |
| 7292 | 7287 |
src/arch/x86_64/CodeGen.zig+42-72| ... | ... | @@ -32,7 +32,6 @@ const InternPool = @import("../../InternPool.zig"); |
| 32 | 32 | const Alignment = InternPool.Alignment; |
| 33 | 33 | const Target = std.Target; |
| 34 | 34 | const Type = @import("../../type.zig").Type; |
| 35 | const TypedValue = @import("../../TypedValue.zig"); | |
| 36 | 35 | const Value = @import("../../Value.zig"); |
| 37 | 36 | const Instruction = @import("encoder.zig").Instruction; |
| 38 | 37 | |
| ... | ... | @@ -808,7 +807,7 @@ pub fn generate( |
| 808 | 807 | const func = zcu.funcInfo(func_index); |
| 809 | 808 | const fn_owner_decl = zcu.declPtr(func.owner_decl); |
| 810 | 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 | 811 | const namespace = zcu.namespacePtr(fn_owner_decl.src_namespace); |
| 813 | 812 | const mod = namespace.file_scope.mod; |
| 814 | 813 | |
| ... | ... | @@ -2250,7 +2249,7 @@ fn genLazy(self: *Self, lazy_sym: link.File.LazySymbol) InnerError!void { |
| 2250 | 2249 | for (exitlude_jump_relocs, 0..) |*exitlude_jump_reloc, tag_index| { |
| 2251 | 2250 | const tag_name_len = ip.stringToSlice(tag_names.get(ip)[tag_index]).len; |
| 2252 | 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 | 2253 | try self.genBinOpMir(.{ ._, .cmp }, enum_ty, enum_mcv, tag_mcv); |
| 2255 | 2254 | const skip_reloc = try self.asmJccReloc(.ne, undefined); |
| 2256 | 2255 | |
| ... | ... | @@ -3323,7 +3322,7 @@ fn airTrunc(self: *Self, inst: Air.Inst.Index) !void { |
| 3323 | 3322 | .storage = .{ .repeated_elem = mask_val.ip_index }, |
| 3324 | 3323 | } }); |
| 3325 | 3324 | |
| 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 | 3326 | const splat_addr_mcv: MCValue = switch (splat_mcv) { |
| 3328 | 3327 | .memory, .indirect, .load_frame => splat_mcv.address(), |
| 3329 | 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 | 4991 | defer self.register_manager.unlockReg(shift_lock); |
| 4993 | 4992 | |
| 4994 | 4993 | const mask_ty = try mod.vectorType(.{ .len = 16, .child = .u8_type }); |
| 4995 | const mask_mcv = try self.genTypedValue(.{ | |
| 4996 | .ty = mask_ty, | |
| 4997 | .val = Value.fromInterned((try mod.intern(.{ .aggregate = .{ | |
| 4998 | .ty = mask_ty.toIntern(), | |
| 4999 | .storage = .{ .elems = &([1]InternPool.Index{ | |
| 5000 | (try rhs_ty.childType(mod).maxIntScalar(mod, Type.u8)).toIntern(), | |
| 5001 | } ++ [1]InternPool.Index{ | |
| 5002 | (try mod.intValue(Type.u8, 0)).toIntern(), | |
| 5003 | } ** 15) }, | |
| 5004 | } }))), | |
| 5005 | }); | |
| 4994 | const mask_mcv = try self.genTypedValue(Value.fromInterned(try mod.intern(.{ .aggregate = .{ | |
| 4995 | .ty = mask_ty.toIntern(), | |
| 4996 | .storage = .{ .elems = &([1]InternPool.Index{ | |
| 4997 | (try rhs_ty.childType(mod).maxIntScalar(mod, Type.u8)).toIntern(), | |
| 4998 | } ++ [1]InternPool.Index{ | |
| 4999 | (try mod.intValue(Type.u8, 0)).toIntern(), | |
| 5000 | } ** 15) }, | |
| 5001 | } }))); | |
| 5006 | 5002 | const mask_addr_reg = |
| 5007 | 5003 | try self.copyToTmpRegister(Type.usize, mask_mcv.address()); |
| 5008 | 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 | 6856 | .child = (try mod.intType(.signed, scalar_bits)).ip_index, |
| 6861 | 6857 | }); |
| 6862 | 6858 | |
| 6863 | const sign_mcv = try self.genTypedValue(.{ .ty = vec_ty, .val = switch (tag) { | |
| 6859 | const sign_mcv = try self.genTypedValue(switch (tag) { | |
| 6864 | 6860 | .neg => try vec_ty.minInt(mod, vec_ty), |
| 6865 | 6861 | .abs => try vec_ty.maxInt(mod, vec_ty), |
| 6866 | 6862 | else => unreachable, |
| 6867 | } }); | |
| 6863 | }); | |
| 6868 | 6864 | const sign_mem: Memory = if (sign_mcv.isMemory()) |
| 6869 | 6865 | try sign_mcv.mem(self, Memory.Size.fromSize(abi_size)) |
| 6870 | 6866 | else |
| ... | ... | @@ -11130,10 +11126,7 @@ fn genBinOp( |
| 11130 | 11126 | .cmp_neq, |
| 11131 | 11127 | => { |
| 11132 | 11128 | const unsigned_ty = try lhs_ty.toUnsigned(mod); |
| 11133 | const not_mcv = try self.genTypedValue(.{ | |
| 11134 | .ty = lhs_ty, | |
| 11135 | .val = try unsigned_ty.maxInt(mod, unsigned_ty), | |
| 11136 | }); | |
| 11129 | const not_mcv = try self.genTypedValue(try unsigned_ty.maxInt(mod, unsigned_ty)); | |
| 11137 | 11130 | const not_mem: Memory = if (not_mcv.isMemory()) |
| 11138 | 11131 | try not_mcv.mem(self, Memory.Size.fromSize(abi_size)) |
| 11139 | 11132 | else |
| ... | ... | @@ -12258,12 +12251,11 @@ fn genCall(self: *Self, info: union(enum) { |
| 12258 | 12251 | switch (switch (func_key) { |
| 12259 | 12252 | else => func_key, |
| 12260 | 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 | 12255 | else => func_key, |
| 12263 | 12256 | }, |
| 12264 | 12257 | }) { |
| 12265 | 12258 | .func => |func| { |
| 12266 | try mod.markDeclAlive(mod.declPtr(func.owner_decl)); | |
| 12267 | 12259 | if (self.bin_file.cast(link.File.Elf)) |elf_file| { |
| 12268 | 12260 | const sym_index = try elf_file.zigObjectPtr().?.getOrCreateMetadataForDecl(elf_file, func.owner_decl); |
| 12269 | 12261 | const sym = elf_file.symbol(sym_index); |
| ... | ... | @@ -12323,7 +12315,6 @@ fn genCall(self: *Self, info: union(enum) { |
| 12323 | 12315 | }, |
| 12324 | 12316 | .extern_func => |extern_func| { |
| 12325 | 12317 | const owner_decl = mod.declPtr(extern_func.decl); |
| 12326 | try mod.markDeclAlive(owner_decl); | |
| 12327 | 12318 | const lib_name = mod.intern_pool.stringToSliceUnwrap(extern_func.lib_name); |
| 12328 | 12319 | const decl_name = mod.intern_pool.stringToSlice(owner_decl.name); |
| 12329 | 12320 | try self.genExternSymbolRef(.call, lib_name, decl_name); |
| ... | ... | @@ -14694,10 +14685,7 @@ fn genSetReg( |
| 14694 | 14685 | ), |
| 14695 | 14686 | else => unreachable, |
| 14696 | 14687 | }, |
| 14697 | .segment, .x87, .mmx, .sse => try self.genSetReg(dst_reg, ty, try self.genTypedValue(.{ | |
| 14698 | .ty = ty, | |
| 14699 | .val = try mod.undefValue(ty), | |
| 14700 | }), opts), | |
| 14688 | .segment, .x87, .mmx, .sse => try self.genSetReg(dst_reg, ty, try self.genTypedValue(try mod.undefValue(ty)), opts), | |
| 14701 | 14689 | }, |
| 14702 | 14690 | .eflags => |cc| try self.asmSetccRegister(cc, dst_reg.to8()), |
| 14703 | 14691 | .immediate => |imm| { |
| ... | ... | @@ -16895,13 +16883,10 @@ fn airSelect(self: *Self, inst: Air.Inst.Index) !void { |
| 16895 | 16883 | .ty = mask_elem_ty.toIntern(), |
| 16896 | 16884 | .storage = .{ .u64 = bit / elem_bits }, |
| 16897 | 16885 | } }); |
| 16898 | const mask_mcv = try self.genTypedValue(.{ | |
| 16899 | .ty = mask_ty, | |
| 16900 | .val = Value.fromInterned(try mod.intern(.{ .aggregate = .{ | |
| 16901 | .ty = mask_ty.toIntern(), | |
| 16902 | .storage = .{ .elems = mask_elems[0..vec_len] }, | |
| 16903 | } })), | |
| 16904 | }); | |
| 16886 | const mask_mcv = try self.genTypedValue(Value.fromInterned(try mod.intern(.{ .aggregate = .{ | |
| 16887 | .ty = mask_ty.toIntern(), | |
| 16888 | .storage = .{ .elems = mask_elems[0..vec_len] }, | |
| 16889 | } }))); | |
| 16905 | 16890 | const mask_mem: Memory = .{ |
| 16906 | 16891 | .base = .{ .reg = try self.copyToTmpRegister(Type.usize, mask_mcv.address()) }, |
| 16907 | 16892 | .mod = .{ .rm = .{ .size = self.memSize(ty) } }, |
| ... | ... | @@ -16923,13 +16908,10 @@ fn airSelect(self: *Self, inst: Air.Inst.Index) !void { |
| 16923 | 16908 | .ty = mask_elem_ty.toIntern(), |
| 16924 | 16909 | .storage = .{ .u64 = @as(u32, 1) << @intCast(bit & (elem_bits - 1)) }, |
| 16925 | 16910 | } }); |
| 16926 | const mask_mcv = try self.genTypedValue(.{ | |
| 16927 | .ty = mask_ty, | |
| 16928 | .val = Value.fromInterned(try mod.intern(.{ .aggregate = .{ | |
| 16929 | .ty = mask_ty.toIntern(), | |
| 16930 | .storage = .{ .elems = mask_elems[0..vec_len] }, | |
| 16931 | } })), | |
| 16932 | }); | |
| 16911 | const mask_mcv = try self.genTypedValue(Value.fromInterned(try mod.intern(.{ .aggregate = .{ | |
| 16912 | .ty = mask_ty.toIntern(), | |
| 16913 | .storage = .{ .elems = mask_elems[0..vec_len] }, | |
| 16914 | } }))); | |
| 16933 | 16915 | const mask_mem: Memory = .{ |
| 16934 | 16916 | .base = .{ .reg = try self.copyToTmpRegister(Type.usize, mask_mcv.address()) }, |
| 16935 | 16917 | .mod = .{ .rm = .{ .size = self.memSize(ty) } }, |
| ... | ... | @@ -17660,13 +17642,10 @@ fn airShuffle(self: *Self, inst: Air.Inst.Index) !void { |
| 17660 | 17642 | else |
| 17661 | 17643 | try select_mask_elem_ty.minIntScalar(mod, select_mask_elem_ty)).toIntern(); |
| 17662 | 17644 | } |
| 17663 | const select_mask_mcv = try self.genTypedValue(.{ | |
| 17664 | .ty = select_mask_ty, | |
| 17665 | .val = Value.fromInterned(try mod.intern(.{ .aggregate = .{ | |
| 17666 | .ty = select_mask_ty.toIntern(), | |
| 17667 | .storage = .{ .elems = select_mask_elems[0..mask_elems.len] }, | |
| 17668 | } })), | |
| 17669 | }); | |
| 17645 | const select_mask_mcv = try self.genTypedValue(Value.fromInterned(try mod.intern(.{ .aggregate = .{ | |
| 17646 | .ty = select_mask_ty.toIntern(), | |
| 17647 | .storage = .{ .elems = select_mask_elems[0..mask_elems.len] }, | |
| 17648 | } }))); | |
| 17670 | 17649 | |
| 17671 | 17650 | if (self.hasFeature(.sse4_1)) { |
| 17672 | 17651 | const mir_tag: Mir.Inst.FixedTag = .{ |
| ... | ... | @@ -17811,13 +17790,10 @@ fn airShuffle(self: *Self, inst: Air.Inst.Index) !void { |
| 17811 | 17790 | } }); |
| 17812 | 17791 | } |
| 17813 | 17792 | const lhs_mask_ty = try mod.vectorType(.{ .len = max_abi_size, .child = .u8_type }); |
| 17814 | const lhs_mask_mcv = try self.genTypedValue(.{ | |
| 17815 | .ty = lhs_mask_ty, | |
| 17816 | .val = Value.fromInterned(try mod.intern(.{ .aggregate = .{ | |
| 17817 | .ty = lhs_mask_ty.toIntern(), | |
| 17818 | .storage = .{ .elems = lhs_mask_elems[0..max_abi_size] }, | |
| 17819 | } })), | |
| 17820 | }); | |
| 17793 | const lhs_mask_mcv = try self.genTypedValue(Value.fromInterned(try mod.intern(.{ .aggregate = .{ | |
| 17794 | .ty = lhs_mask_ty.toIntern(), | |
| 17795 | .storage = .{ .elems = lhs_mask_elems[0..max_abi_size] }, | |
| 17796 | } }))); | |
| 17821 | 17797 | const lhs_mask_mem: Memory = .{ |
| 17822 | 17798 | .base = .{ .reg = try self.copyToTmpRegister(Type.usize, lhs_mask_mcv.address()) }, |
| 17823 | 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 | 17824 | } }); |
| 17849 | 17825 | } |
| 17850 | 17826 | const rhs_mask_ty = try mod.vectorType(.{ .len = max_abi_size, .child = .u8_type }); |
| 17851 | const rhs_mask_mcv = try self.genTypedValue(.{ | |
| 17852 | .ty = rhs_mask_ty, | |
| 17853 | .val = Value.fromInterned(try mod.intern(.{ .aggregate = .{ | |
| 17854 | .ty = rhs_mask_ty.toIntern(), | |
| 17855 | .storage = .{ .elems = rhs_mask_elems[0..max_abi_size] }, | |
| 17856 | } })), | |
| 17857 | }); | |
| 17827 | const rhs_mask_mcv = try self.genTypedValue(Value.fromInterned(try mod.intern(.{ .aggregate = .{ | |
| 17828 | .ty = rhs_mask_ty.toIntern(), | |
| 17829 | .storage = .{ .elems = rhs_mask_elems[0..max_abi_size] }, | |
| 17830 | } }))); | |
| 17858 | 17831 | const rhs_mask_mem: Memory = .{ |
| 17859 | 17832 | .base = .{ .reg = try self.copyToTmpRegister(Type.usize, rhs_mask_mcv.address()) }, |
| 17860 | 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 | 17876 | |
| 17904 | 17877 | break :result null; |
| 17905 | 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), | |
| 17907 | Value.fromInterned(extra.mask).fmtValue( | |
| 17908 | Type.fromInterned(mod.intern_pool.typeOf(extra.mask)), | |
| 17909 | mod, | |
| 17910 | ), | |
| 17879 | lhs_ty.fmt(mod), rhs_ty.fmt(mod), dst_ty.fmt(mod), | |
| 17880 | Value.fromInterned(extra.mask).fmtValue(mod), | |
| 17911 | 17881 | }); |
| 17912 | 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 | 18110 | .{ .frame = frame_index }, |
| 18141 | 18111 | @intCast(elem_size * elements.len), |
| 18142 | 18112 | elem_ty, |
| 18143 | try self.genTypedValue(.{ .ty = elem_ty, .val = sentinel }), | |
| 18113 | try self.genTypedValue(sentinel), | |
| 18144 | 18114 | .{}, |
| 18145 | 18115 | ); |
| 18146 | 18116 | break :result .{ .load_frame = .{ .index = frame_index } }; |
| ... | ... | @@ -18664,7 +18634,7 @@ fn resolveInst(self: *Self, ref: Air.Inst.Ref) InnerError!MCValue { |
| 18664 | 18634 | const ip_index = ref.toInterned().?; |
| 18665 | 18635 | const gop = try self.const_tracking.getOrPut(self.gpa, ip_index); |
| 18666 | 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 | 18638 | switch (const_mcv) { |
| 18669 | 18639 | .lea_tlv => |tlv_sym| switch (self.bin_file.tag) { |
| 18670 | 18640 | .elf, .macho => { |
| ... | ... | @@ -18729,9 +18699,9 @@ fn limitImmediateType(self: *Self, operand: Air.Inst.Ref, comptime T: type) !MCV |
| 18729 | 18699 | return mcv; |
| 18730 | 18700 | } |
| 18731 | 18701 | |
| 18732 | fn genTypedValue(self: *Self, arg_tv: TypedValue) InnerError!MCValue { | |
| 18702 | fn genTypedValue(self: *Self, val: Value) InnerError!MCValue { | |
| 18733 | 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 | 18705 | .mcv => |mcv| switch (mcv) { |
| 18736 | 18706 | .none => .none, |
| 18737 | 18707 | .undef => .undef, |
src/codegen.zig+123-177| ... | ... | @@ -19,7 +19,6 @@ const Liveness = @import("Liveness.zig"); |
| 19 | 19 | const Module = @import("Module.zig"); |
| 20 | 20 | const Target = std.Target; |
| 21 | 21 | const Type = @import("type.zig").Type; |
| 22 | const TypedValue = @import("TypedValue.zig"); | |
| 23 | 22 | const Value = @import("Value.zig"); |
| 24 | 23 | const Zir = std.zig.Zir; |
| 25 | 24 | const Alignment = InternPool.Alignment; |
| ... | ... | @@ -171,7 +170,7 @@ pub fn generateLazySymbol( |
| 171 | 170 | pub fn generateSymbol( |
| 172 | 171 | bin_file: *link.File, |
| 173 | 172 | src_loc: Module.SrcLoc, |
| 174 | arg_tv: TypedValue, | |
| 173 | val: Value, | |
| 175 | 174 | code: *std.ArrayList(u8), |
| 176 | 175 | debug_output: DebugInfoOutput, |
| 177 | 176 | reloc_info: RelocInfo, |
| ... | ... | @@ -181,23 +180,20 @@ pub fn generateSymbol( |
| 181 | 180 | |
| 182 | 181 | const mod = bin_file.comp.module.?; |
| 183 | 182 | const ip = &mod.intern_pool; |
| 184 | const typed_value = arg_tv; | |
| 183 | const ty = val.typeOf(mod); | |
| 185 | 184 | |
| 186 | 185 | const target = mod.getTarget(); |
| 187 | 186 | const endian = target.cpu.arch.endian(); |
| 188 | 187 | |
| 189 | log.debug("generateSymbol: ty = {}, val = {}", .{ | |
| 190 | typed_value.ty.fmt(mod), | |
| 191 | typed_value.val.fmtValue(typed_value.ty, mod), | |
| 192 | }); | |
| 188 | log.debug("generateSymbol: val = {}", .{val.fmtValue(mod)}); | |
| 193 | 189 | |
| 194 | if (typed_value.val.isUndefDeep(mod)) { | |
| 195 | const abi_size = math.cast(usize, typed_value.ty.abiSize(mod)) orelse return error.Overflow; | |
| 190 | if (val.isUndefDeep(mod)) { | |
| 191 | const abi_size = math.cast(usize, ty.abiSize(mod)) orelse return error.Overflow; | |
| 196 | 192 | try code.appendNTimes(0xaa, abi_size); |
| 197 | 193 | return .ok; |
| 198 | 194 | } |
| 199 | 195 | |
| 200 | switch (ip.indexToKey(typed_value.val.toIntern())) { | |
| 196 | switch (ip.indexToKey(val.toIntern())) { | |
| 201 | 197 | .int_type, |
| 202 | 198 | .ptr_type, |
| 203 | 199 | .array_type, |
| ... | ... | @@ -238,17 +234,17 @@ pub fn generateSymbol( |
| 238 | 234 | .empty_enum_value, |
| 239 | 235 | => unreachable, // non-runtime values |
| 240 | 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 | 238 | var space: Value.BigIntSpace = undefined; |
| 243 | const val = typed_value.val.toBigInt(&space, mod); | |
| 244 | val.writeTwosComplement(try code.addManyAsSlice(abi_size), endian); | |
| 239 | const int_val = val.toBigInt(&space, mod); | |
| 240 | int_val.writeTwosComplement(try code.addManyAsSlice(abi_size), endian); | |
| 245 | 241 | }, |
| 246 | 242 | .err => |err| { |
| 247 | 243 | const int = try mod.getErrorValue(err.name); |
| 248 | 244 | try code.writer().writeInt(u16, @as(u16, @intCast(int)), endian); |
| 249 | 245 | }, |
| 250 | 246 | .error_union => |error_union| { |
| 251 | const payload_ty = typed_value.ty.errorUnionPayload(mod); | |
| 247 | const payload_ty = ty.errorUnionPayload(mod); | |
| 252 | 248 | const err_val = switch (error_union.val) { |
| 253 | 249 | .err_name => |err_name| @as(u16, @intCast(try mod.getErrorValue(err_name))), |
| 254 | 250 | .payload => @as(u16, 0), |
| ... | ... | @@ -261,7 +257,7 @@ pub fn generateSymbol( |
| 261 | 257 | |
| 262 | 258 | const payload_align = payload_ty.abiAlignment(mod); |
| 263 | 259 | const error_align = Type.anyerror.abiAlignment(mod); |
| 264 | const abi_align = typed_value.ty.abiAlignment(mod); | |
| 260 | const abi_align = ty.abiAlignment(mod); | |
| 265 | 261 | |
| 266 | 262 | // error value first when its type is larger than the error union's payload |
| 267 | 263 | if (error_align.order(payload_align) == .gt) { |
| ... | ... | @@ -271,13 +267,10 @@ pub fn generateSymbol( |
| 271 | 267 | // emit payload part of the error union |
| 272 | 268 | { |
| 273 | 269 | const begin = code.items.len; |
| 274 | switch (try generateSymbol(bin_file, src_loc, .{ | |
| 275 | .ty = payload_ty, | |
| 276 | .val = Value.fromInterned(switch (error_union.val) { | |
| 277 | .err_name => try mod.intern(.{ .undef = payload_ty.toIntern() }), | |
| 278 | .payload => |payload| payload, | |
| 279 | }), | |
| 280 | }, code, debug_output, reloc_info)) { | |
| 270 | switch (try generateSymbol(bin_file, src_loc, Value.fromInterned(switch (error_union.val) { | |
| 271 | .err_name => try mod.intern(.{ .undef = payload_ty.toIntern() }), | |
| 272 | .payload => |payload| payload, | |
| 273 | }), code, debug_output, reloc_info)) { | |
| 281 | 274 | .ok => {}, |
| 282 | 275 | .fail => |em| return .{ .fail = em }, |
| 283 | 276 | } |
| ... | ... | @@ -304,11 +297,8 @@ pub fn generateSymbol( |
| 304 | 297 | } |
| 305 | 298 | }, |
| 306 | 299 | .enum_tag => |enum_tag| { |
| 307 | const int_tag_ty = typed_value.ty.intTagType(mod); | |
| 308 | switch (try generateSymbol(bin_file, src_loc, .{ | |
| 309 | .ty = int_tag_ty, | |
| 310 | .val = try mod.getCoerced(Value.fromInterned(enum_tag.int), int_tag_ty), | |
| 311 | }, code, debug_output, reloc_info)) { | |
| 300 | const int_tag_ty = ty.intTagType(mod); | |
| 301 | switch (try generateSymbol(bin_file, src_loc, try mod.getCoerced(Value.fromInterned(enum_tag.int), int_tag_ty), code, debug_output, reloc_info)) { | |
| 312 | 302 | .ok => {}, |
| 313 | 303 | .fail => |em| return .{ .fail = em }, |
| 314 | 304 | } |
| ... | ... | @@ -319,42 +309,33 @@ pub fn generateSymbol( |
| 319 | 309 | .f64 => |f64_val| writeFloat(f64, f64_val, target, endian, try code.addManyAsArray(8)), |
| 320 | 310 | .f80 => |f80_val| { |
| 321 | 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 | 313 | try code.appendNTimes(0, abi_size - 10); |
| 324 | 314 | }, |
| 325 | 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 | 318 | .ok => {}, |
| 329 | 319 | .fail => |em| return .{ .fail = em }, |
| 330 | 320 | }, |
| 331 | 321 | .slice => |slice| { |
| 332 | switch (try generateSymbol(bin_file, src_loc, .{ | |
| 333 | .ty = typed_value.ty.slicePtrFieldType(mod), | |
| 334 | .val = Value.fromInterned(slice.ptr), | |
| 335 | }, code, debug_output, reloc_info)) { | |
| 322 | switch (try generateSymbol(bin_file, src_loc, Value.fromInterned(slice.ptr), code, debug_output, reloc_info)) { | |
| 336 | 323 | .ok => {}, |
| 337 | 324 | .fail => |em| return .{ .fail = em }, |
| 338 | 325 | } |
| 339 | switch (try generateSymbol(bin_file, src_loc, .{ | |
| 340 | .ty = Type.usize, | |
| 341 | .val = Value.fromInterned(slice.len), | |
| 342 | }, code, debug_output, reloc_info)) { | |
| 326 | switch (try generateSymbol(bin_file, src_loc, Value.fromInterned(slice.len), code, debug_output, reloc_info)) { | |
| 343 | 327 | .ok => {}, |
| 344 | 328 | .fail => |em| return .{ .fail = em }, |
| 345 | 329 | } |
| 346 | 330 | }, |
| 347 | 331 | .opt => { |
| 348 | const payload_type = typed_value.ty.optionalChild(mod); | |
| 349 | const payload_val = typed_value.val.optionalValue(mod); | |
| 350 | const abi_size = math.cast(usize, typed_value.ty.abiSize(mod)) orelse return error.Overflow; | |
| 332 | const payload_type = ty.optionalChild(mod); | |
| 333 | const payload_val = val.optionalValue(mod); | |
| 334 | const abi_size = math.cast(usize, ty.abiSize(mod)) orelse return error.Overflow; | |
| 351 | 335 | |
| 352 | if (typed_value.ty.optionalReprIsPayload(mod)) { | |
| 336 | if (ty.optionalReprIsPayload(mod)) { | |
| 353 | 337 | if (payload_val) |value| { |
| 354 | switch (try generateSymbol(bin_file, src_loc, .{ | |
| 355 | .ty = payload_type, | |
| 356 | .val = value, | |
| 357 | }, code, debug_output, reloc_info)) { | |
| 338 | switch (try generateSymbol(bin_file, src_loc, value, code, debug_output, reloc_info)) { | |
| 358 | 339 | .ok => {}, |
| 359 | 340 | .fail => |em| return Result{ .fail = em }, |
| 360 | 341 | } |
| ... | ... | @@ -365,10 +346,7 @@ pub fn generateSymbol( |
| 365 | 346 | const padding = abi_size - (math.cast(usize, payload_type.abiSize(mod)) orelse return error.Overflow) - 1; |
| 366 | 347 | if (payload_type.hasRuntimeBits(mod)) { |
| 367 | 348 | const value = payload_val orelse Value.fromInterned((try mod.intern(.{ .undef = payload_type.toIntern() }))); |
| 368 | switch (try generateSymbol(bin_file, src_loc, .{ | |
| 369 | .ty = payload_type, | |
| 370 | .val = value, | |
| 371 | }, code, debug_output, reloc_info)) { | |
| 349 | switch (try generateSymbol(bin_file, src_loc, value, code, debug_output, reloc_info)) { | |
| 372 | 350 | .ok => {}, |
| 373 | 351 | .fail => |em| return Result{ .fail = em }, |
| 374 | 352 | } |
| ... | ... | @@ -377,7 +355,7 @@ pub fn generateSymbol( |
| 377 | 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 | 359 | .array_type => |array_type| switch (aggregate.storage) { |
| 382 | 360 | .bytes => |bytes| try code.appendSlice(bytes), |
| 383 | 361 | .elems, .repeated_elem => { |
| ... | ... | @@ -385,17 +363,14 @@ pub fn generateSymbol( |
| 385 | 363 | const len_including_sentinel = |
| 386 | 364 | array_type.len + @intFromBool(array_type.sentinel != .none); |
| 387 | 365 | while (index < len_including_sentinel) : (index += 1) { |
| 388 | switch (try generateSymbol(bin_file, src_loc, .{ | |
| 389 | .ty = Type.fromInterned(array_type.child), | |
| 390 | .val = Value.fromInterned(switch (aggregate.storage) { | |
| 391 | .bytes => unreachable, | |
| 392 | .elems => |elems| elems[@as(usize, @intCast(index))], | |
| 393 | .repeated_elem => |elem| if (index < array_type.len) | |
| 394 | elem | |
| 395 | else | |
| 396 | array_type.sentinel, | |
| 397 | }), | |
| 398 | }, code, debug_output, reloc_info)) { | |
| 366 | switch (try generateSymbol(bin_file, src_loc, Value.fromInterned(switch (aggregate.storage) { | |
| 367 | .bytes => unreachable, | |
| 368 | .elems => |elems| elems[@as(usize, @intCast(index))], | |
| 369 | .repeated_elem => |elem| if (index < array_type.len) | |
| 370 | elem | |
| 371 | else | |
| 372 | array_type.sentinel, | |
| 373 | }), code, debug_output, reloc_info)) { | |
| 399 | 374 | .ok => {}, |
| 400 | 375 | .fail => |em| return .{ .fail = em }, |
| 401 | 376 | } |
| ... | ... | @@ -403,7 +378,7 @@ pub fn generateSymbol( |
| 403 | 378 | }, |
| 404 | 379 | }, |
| 405 | 380 | .vector_type => |vector_type| { |
| 406 | const abi_size = math.cast(usize, typed_value.ty.abiSize(mod)) orelse | |
| 381 | const abi_size = math.cast(usize, ty.abiSize(mod)) orelse | |
| 407 | 382 | return error.Overflow; |
| 408 | 383 | if (vector_type.child == .bool_type) { |
| 409 | 384 | const bytes = try code.addManyAsSlice(abi_size); |
| ... | ... | @@ -449,16 +424,13 @@ pub fn generateSymbol( |
| 449 | 424 | .elems, .repeated_elem => { |
| 450 | 425 | var index: u64 = 0; |
| 451 | 426 | while (index < vector_type.len) : (index += 1) { |
| 452 | switch (try generateSymbol(bin_file, src_loc, .{ | |
| 453 | .ty = Type.fromInterned(vector_type.child), | |
| 454 | .val = Value.fromInterned(switch (aggregate.storage) { | |
| 455 | .bytes => unreachable, | |
| 456 | .elems => |elems| elems[ | |
| 457 | math.cast(usize, index) orelse return error.Overflow | |
| 458 | ], | |
| 459 | .repeated_elem => |elem| elem, | |
| 460 | }), | |
| 461 | }, code, debug_output, reloc_info)) { | |
| 427 | switch (try generateSymbol(bin_file, src_loc, Value.fromInterned(switch (aggregate.storage) { | |
| 428 | .bytes => unreachable, | |
| 429 | .elems => |elems| elems[ | |
| 430 | math.cast(usize, index) orelse return error.Overflow | |
| 431 | ], | |
| 432 | .repeated_elem => |elem| elem, | |
| 433 | }), code, debug_output, reloc_info)) { | |
| 462 | 434 | .ok => {}, |
| 463 | 435 | .fail => |em| return .{ .fail = em }, |
| 464 | 436 | } |
| ... | ... | @@ -491,17 +463,14 @@ pub fn generateSymbol( |
| 491 | 463 | .repeated_elem => |elem| elem, |
| 492 | 464 | }; |
| 493 | 465 | |
| 494 | switch (try generateSymbol(bin_file, src_loc, .{ | |
| 495 | .ty = Type.fromInterned(field_ty), | |
| 496 | .val = Value.fromInterned(field_val), | |
| 497 | }, code, debug_output, reloc_info)) { | |
| 466 | switch (try generateSymbol(bin_file, src_loc, Value.fromInterned(field_val), code, debug_output, reloc_info)) { | |
| 498 | 467 | .ok => {}, |
| 499 | 468 | .fail => |em| return Result{ .fail = em }, |
| 500 | 469 | } |
| 501 | 470 | const unpadded_field_end = code.items.len - struct_begin; |
| 502 | 471 | |
| 503 | 472 | // 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 | 474 | const padding = math.cast(usize, padded_field_end - unpadded_field_end) orelse |
| 506 | 475 | return error.Overflow; |
| 507 | 476 | |
| ... | ... | @@ -511,10 +480,10 @@ pub fn generateSymbol( |
| 511 | 480 | } |
| 512 | 481 | }, |
| 513 | 482 | .struct_type => { |
| 514 | const struct_type = ip.loadStructType(typed_value.ty.toIntern()); | |
| 483 | const struct_type = ip.loadStructType(ty.toIntern()); | |
| 515 | 484 | switch (struct_type.layout) { |
| 516 | 485 | .@"packed" => { |
| 517 | const abi_size = math.cast(usize, typed_value.ty.abiSize(mod)) orelse | |
| 486 | const abi_size = math.cast(usize, ty.abiSize(mod)) orelse | |
| 518 | 487 | return error.Overflow; |
| 519 | 488 | const current_pos = code.items.len; |
| 520 | 489 | try code.resize(current_pos + abi_size); |
| ... | ... | @@ -537,10 +506,7 @@ pub fn generateSymbol( |
| 537 | 506 | return error.Overflow; |
| 538 | 507 | var tmp_list = try std.ArrayList(u8).initCapacity(code.allocator, field_size); |
| 539 | 508 | defer tmp_list.deinit(); |
| 540 | switch (try generateSymbol(bin_file, src_loc, .{ | |
| 541 | .ty = Type.fromInterned(field_ty), | |
| 542 | .val = Value.fromInterned(field_val), | |
| 543 | }, &tmp_list, debug_output, reloc_info)) { | |
| 509 | switch (try generateSymbol(bin_file, src_loc, Value.fromInterned(field_val), &tmp_list, debug_output, reloc_info)) { | |
| 544 | 510 | .ok => @memcpy(code.items[current_pos..][0..tmp_list.items.len], tmp_list.items), |
| 545 | 511 | .fail => |em| return Result{ .fail = em }, |
| 546 | 512 | } |
| ... | ... | @@ -560,7 +526,7 @@ pub fn generateSymbol( |
| 560 | 526 | const field_ty = field_types[field_index]; |
| 561 | 527 | if (!Type.fromInterned(field_ty).hasRuntimeBits(mod)) continue; |
| 562 | 528 | |
| 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 | 530 | .bytes => |bytes| try ip.get(mod.gpa, .{ .int = .{ |
| 565 | 531 | .ty = field_ty, |
| 566 | 532 | .storage = .{ .u64 = bytes[field_index] }, |
| ... | ... | @@ -575,10 +541,7 @@ pub fn generateSymbol( |
| 575 | 541 | ) orelse return error.Overflow; |
| 576 | 542 | if (padding > 0) try code.appendNTimes(0, padding); |
| 577 | 543 | |
| 578 | switch (try generateSymbol(bin_file, src_loc, .{ | |
| 579 | .ty = Type.fromInterned(field_ty), | |
| 580 | .val = Value.fromInterned(field_val), | |
| 581 | }, code, debug_output, reloc_info)) { | |
| 544 | switch (try generateSymbol(bin_file, src_loc, Value.fromInterned(field_val), code, debug_output, reloc_info)) { | |
| 582 | 545 | .ok => {}, |
| 583 | 546 | .fail => |em| return Result{ .fail = em }, |
| 584 | 547 | } |
| ... | ... | @@ -599,37 +562,28 @@ pub fn generateSymbol( |
| 599 | 562 | else => unreachable, |
| 600 | 563 | }, |
| 601 | 564 | .un => |un| { |
| 602 | const layout = typed_value.ty.unionGetLayout(mod); | |
| 565 | const layout = ty.unionGetLayout(mod); | |
| 603 | 566 | |
| 604 | 567 | if (layout.payload_size == 0) { |
| 605 | return generateSymbol(bin_file, src_loc, .{ | |
| 606 | .ty = typed_value.ty.unionTagTypeSafety(mod).?, | |
| 607 | .val = Value.fromInterned(un.tag), | |
| 608 | }, code, debug_output, reloc_info); | |
| 568 | return generateSymbol(bin_file, src_loc, Value.fromInterned(un.tag), code, debug_output, reloc_info); | |
| 609 | 569 | } |
| 610 | 570 | |
| 611 | 571 | // Check if we should store the tag first. |
| 612 | 572 | if (layout.tag_size > 0 and layout.tag_align.compare(.gte, layout.payload_align)) { |
| 613 | switch (try generateSymbol(bin_file, src_loc, .{ | |
| 614 | .ty = typed_value.ty.unionTagTypeSafety(mod).?, | |
| 615 | .val = Value.fromInterned(un.tag), | |
| 616 | }, code, debug_output, reloc_info)) { | |
| 573 | switch (try generateSymbol(bin_file, src_loc, Value.fromInterned(un.tag), code, debug_output, reloc_info)) { | |
| 617 | 574 | .ok => {}, |
| 618 | 575 | .fail => |em| return Result{ .fail = em }, |
| 619 | 576 | } |
| 620 | 577 | } |
| 621 | 578 | |
| 622 | const union_obj = mod.typeToUnion(typed_value.ty).?; | |
| 579 | const union_obj = mod.typeToUnion(ty).?; | |
| 623 | 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 | 582 | const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[field_index]); |
| 626 | 583 | if (!field_ty.hasRuntimeBits(mod)) { |
| 627 | 584 | try code.appendNTimes(0xaa, math.cast(usize, layout.payload_size) orelse return error.Overflow); |
| 628 | 585 | } else { |
| 629 | switch (try generateSymbol(bin_file, src_loc, .{ | |
| 630 | .ty = field_ty, | |
| 631 | .val = Value.fromInterned(un.val), | |
| 632 | }, code, debug_output, reloc_info)) { | |
| 586 | switch (try generateSymbol(bin_file, src_loc, Value.fromInterned(un.val), code, debug_output, reloc_info)) { | |
| 633 | 587 | .ok => {}, |
| 634 | 588 | .fail => |em| return Result{ .fail = em }, |
| 635 | 589 | } |
| ... | ... | @@ -640,20 +594,14 @@ pub fn generateSymbol( |
| 640 | 594 | } |
| 641 | 595 | } |
| 642 | 596 | } else { |
| 643 | switch (try generateSymbol(bin_file, src_loc, .{ | |
| 644 | .ty = Type.fromInterned(ip.typeOf(un.val)), | |
| 645 | .val = Value.fromInterned(un.val), | |
| 646 | }, code, debug_output, reloc_info)) { | |
| 597 | switch (try generateSymbol(bin_file, src_loc, Value.fromInterned(un.val), code, debug_output, reloc_info)) { | |
| 647 | 598 | .ok => {}, |
| 648 | 599 | .fail => |em| return Result{ .fail = em }, |
| 649 | 600 | } |
| 650 | 601 | } |
| 651 | 602 | |
| 652 | 603 | if (layout.tag_size > 0 and layout.tag_align.compare(.lt, layout.payload_align)) { |
| 653 | switch (try generateSymbol(bin_file, src_loc, .{ | |
| 654 | .ty = Type.fromInterned(union_obj.enum_tag_ty), | |
| 655 | .val = Value.fromInterned(un.tag), | |
| 656 | }, code, debug_output, reloc_info)) { | |
| 604 | switch (try generateSymbol(bin_file, src_loc, Value.fromInterned(un.tag), code, debug_output, reloc_info)) { | |
| 657 | 605 | .ok => {}, |
| 658 | 606 | .fail => |em| return Result{ .fail = em }, |
| 659 | 607 | } |
| ... | ... | @@ -681,10 +629,7 @@ fn lowerParentPtr( |
| 681 | 629 | return switch (ptr.addr) { |
| 682 | 630 | .decl => |decl| try lowerDeclRef(bin_file, src_loc, decl, code, debug_output, reloc_info), |
| 683 | 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, .{ | |
| 685 | .ty = Type.usize, | |
| 686 | .val = Value.fromInterned(int), | |
| 687 | }, code, debug_output, reloc_info), | |
| 632 | .int => |int| try generateSymbol(bin_file, src_loc, Value.fromInterned(int), code, debug_output, reloc_info), | |
| 688 | 633 | .eu_payload => |eu_payload| try lowerParentPtr( |
| 689 | 634 | bin_file, |
| 690 | 635 | src_loc, |
| ... | ... | @@ -829,14 +774,12 @@ fn lowerDeclRef( |
| 829 | 774 | const target = namespace.file_scope.mod.resolved_target.result; |
| 830 | 775 | |
| 831 | 776 | const ptr_width = target.ptrBitWidth(); |
| 832 | const is_fn_body = decl.ty.zigTypeTag(zcu) == .Fn; | |
| 833 | if (!is_fn_body and !decl.ty.hasRuntimeBits(zcu)) { | |
| 777 | const is_fn_body = decl.typeOf(zcu).zigTypeTag(zcu) == .Fn; | |
| 778 | if (!is_fn_body and !decl.typeOf(zcu).hasRuntimeBits(zcu)) { | |
| 834 | 779 | try code.appendNTimes(0xaa, @divExact(ptr_width, 8)); |
| 835 | 780 | return Result.ok; |
| 836 | 781 | } |
| 837 | 782 | |
| 838 | try zcu.markDeclAlive(decl); | |
| 839 | ||
| 840 | 783 | const vaddr = try lf.getDeclVAddr(decl_index, .{ |
| 841 | 784 | .parent_atom_index = reloc_info.parent_atom_index, |
| 842 | 785 | .offset = code.items.len, |
| ... | ... | @@ -912,11 +855,12 @@ pub const GenResult = union(enum) { |
| 912 | 855 | fn genDeclRef( |
| 913 | 856 | lf: *link.File, |
| 914 | 857 | src_loc: Module.SrcLoc, |
| 915 | tv: TypedValue, | |
| 858 | val: Value, | |
| 916 | 859 | ptr_decl_index: InternPool.DeclIndex, |
| 917 | 860 | ) CodeGenError!GenResult { |
| 918 | 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)}); | |
| 920 | 864 | |
| 921 | 865 | const ptr_decl = zcu.declPtr(ptr_decl_index); |
| 922 | 866 | const namespace = zcu.namespacePtr(ptr_decl.src_namespace); |
| ... | ... | @@ -925,14 +869,14 @@ fn genDeclRef( |
| 925 | 869 | const ptr_bits = target.ptrBitWidth(); |
| 926 | 870 | const ptr_bytes: u64 = @divExact(ptr_bits, 8); |
| 927 | 871 | |
| 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 | 873 | .func => |func| func.owner_decl, |
| 930 | 874 | .extern_func => |extern_func| extern_func.decl, |
| 931 | 875 | else => ptr_decl_index, |
| 932 | 876 | }; |
| 933 | 877 | const decl = zcu.declPtr(decl_index); |
| 934 | 878 | |
| 935 | if (!decl.ty.isFnOrHasRuntimeBitsIgnoreComptime(zcu)) { | |
| 879 | if (!decl.typeOf(zcu).isFnOrHasRuntimeBitsIgnoreComptime(zcu)) { | |
| 936 | 880 | const imm: u64 = switch (ptr_bytes) { |
| 937 | 881 | 1 => 0xaa, |
| 938 | 882 | 2 => 0xaaaa, |
| ... | ... | @@ -947,22 +891,20 @@ fn genDeclRef( |
| 947 | 891 | const gpa = comp.gpa; |
| 948 | 892 | |
| 949 | 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 | 895 | if (zcu.typeToFunc(fn_ty).?.is_generic) { |
| 952 | 896 | return GenResult.mcv(.{ .immediate = fn_ty.abiAlignment(zcu).toByteUnitsOptional().? }); |
| 953 | 897 | } |
| 954 | } else if (tv.ty.zigTypeTag(zcu) == .Pointer) { | |
| 955 | const elem_ty = tv.ty.elemType2(zcu); | |
| 898 | } else if (ty.zigTypeTag(zcu) == .Pointer) { | |
| 899 | const elem_ty = ty.elemType2(zcu); | |
| 956 | 900 | if (!elem_ty.hasRuntimeBits(zcu)) { |
| 957 | 901 | return GenResult.mcv(.{ .immediate = elem_ty.abiAlignment(zcu).toByteUnitsOptional().? }); |
| 958 | 902 | } |
| 959 | 903 | } |
| 960 | 904 | |
| 961 | try zcu.markDeclAlive(decl); | |
| 962 | ||
| 963 | 905 | const decl_namespace = zcu.namespacePtr(decl.src_namespace); |
| 964 | 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 | 908 | const is_extern = decl.isExtern(zcu); |
| 967 | 909 | |
| 968 | 910 | if (lf.cast(link.File.Elf)) |elf_file| { |
| ... | ... | @@ -1027,14 +969,14 @@ fn genDeclRef( |
| 1027 | 969 | fn genUnnamedConst( |
| 1028 | 970 | lf: *link.File, |
| 1029 | 971 | src_loc: Module.SrcLoc, |
| 1030 | tv: TypedValue, | |
| 972 | val: Value, | |
| 1031 | 973 | owner_decl_index: InternPool.DeclIndex, |
| 1032 | 974 | ) CodeGenError!GenResult { |
| 1033 | 975 | const zcu = lf.comp.module.?; |
| 1034 | 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)}); | |
| 1036 | 978 | |
| 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 | 980 | return GenResult.fail(gpa, src_loc, "lowering unnamed constant failed: {s}", .{@errorName(err)}); |
| 1039 | 981 | }; |
| 1040 | 982 | switch (lf.tag) { |
| ... | ... | @@ -1066,18 +1008,15 @@ fn genUnnamedConst( |
| 1066 | 1008 | pub fn genTypedValue( |
| 1067 | 1009 | lf: *link.File, |
| 1068 | 1010 | src_loc: Module.SrcLoc, |
| 1069 | arg_tv: TypedValue, | |
| 1011 | val: Value, | |
| 1070 | 1012 | owner_decl_index: InternPool.DeclIndex, |
| 1071 | 1013 | ) CodeGenError!GenResult { |
| 1072 | 1014 | const zcu = lf.comp.module.?; |
| 1073 | const typed_value = arg_tv; | |
| 1015 | const ty = val.typeOf(zcu); | |
| 1074 | 1016 | |
| 1075 | log.debug("genTypedValue: ty = {}, val = {}", .{ | |
| 1076 | typed_value.ty.fmt(zcu), | |
| 1077 | typed_value.val.fmtValue(typed_value.ty, zcu), | |
| 1078 | }); | |
| 1017 | log.debug("genTypedValue: val = {}", .{val.fmtValue(zcu)}); | |
| 1079 | 1018 | |
| 1080 | if (typed_value.val.isUndef(zcu)) | |
| 1019 | if (val.isUndef(zcu)) | |
| 1081 | 1020 | return GenResult.mcv(.undef); |
| 1082 | 1021 | |
| 1083 | 1022 | const owner_decl = zcu.declPtr(owner_decl_index); |
| ... | ... | @@ -1085,85 +1024,92 @@ pub fn genTypedValue( |
| 1085 | 1024 | const target = namespace.file_scope.mod.resolved_target.result; |
| 1086 | 1025 | const ptr_bits = target.ptrBitWidth(); |
| 1087 | 1026 | |
| 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 | 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 | 1030 | else => {}, |
| 1092 | 1031 | }, |
| 1093 | 1032 | else => {}, |
| 1094 | 1033 | }; |
| 1095 | 1034 | |
| 1096 | switch (typed_value.ty.zigTypeTag(zcu)) { | |
| 1035 | switch (ty.zigTypeTag(zcu)) { | |
| 1097 | 1036 | .Void => return GenResult.mcv(.none), |
| 1098 | .Pointer => switch (typed_value.ty.ptrSize(zcu)) { | |
| 1037 | .Pointer => switch (ty.ptrSize(zcu)) { | |
| 1099 | 1038 | .Slice => {}, |
| 1100 | else => switch (typed_value.val.toIntern()) { | |
| 1039 | else => switch (val.toIntern()) { | |
| 1101 | 1040 | .null_value => { |
| 1102 | 1041 | return GenResult.mcv(.{ .immediate = 0 }); |
| 1103 | 1042 | }, |
| 1104 | 1043 | .none => {}, |
| 1105 | else => switch (zcu.intern_pool.indexToKey(typed_value.val.toIntern())) { | |
| 1044 | else => switch (zcu.intern_pool.indexToKey(val.toIntern())) { | |
| 1106 | 1045 | .int => { |
| 1107 | return GenResult.mcv(.{ .immediate = typed_value.val.toUnsignedInt(zcu) }); | |
| 1046 | return GenResult.mcv(.{ .immediate = val.toUnsignedInt(zcu) }); | |
| 1108 | 1047 | }, |
| 1109 | 1048 | else => {}, |
| 1110 | 1049 | }, |
| 1111 | 1050 | }, |
| 1112 | 1051 | }, |
| 1113 | 1052 | .Int => { |
| 1114 | const info = typed_value.ty.intInfo(zcu); | |
| 1053 | const info = ty.intInfo(zcu); | |
| 1115 | 1054 | if (info.bits <= ptr_bits) { |
| 1116 | 1055 | const unsigned = switch (info.signedness) { |
| 1117 | .signed => @as(u64, @bitCast(typed_value.val.toSignedInt(zcu))), | |
| 1118 | .unsigned => typed_value.val.toUnsignedInt(zcu), | |
| 1056 | .signed => @as(u64, @bitCast(val.toSignedInt(zcu))), | |
| 1057 | .unsigned => val.toUnsignedInt(zcu), | |
| 1119 | 1058 | }; |
| 1120 | 1059 | return GenResult.mcv(.{ .immediate = unsigned }); |
| 1121 | 1060 | } |
| 1122 | 1061 | }, |
| 1123 | 1062 | .Bool => { |
| 1124 | return GenResult.mcv(.{ .immediate = @intFromBool(typed_value.val.toBool()) }); | |
| 1063 | return GenResult.mcv(.{ .immediate = @intFromBool(val.toBool()) }); | |
| 1125 | 1064 | }, |
| 1126 | 1065 | .Optional => { |
| 1127 | if (typed_value.ty.isPtrLikeOptional(zcu)) { | |
| 1128 | return genTypedValue(lf, src_loc, .{ | |
| 1129 | .ty = typed_value.ty.optionalChild(zcu), | |
| 1130 | .val = typed_value.val.optionalValue(zcu) orelse return GenResult.mcv(.{ .immediate = 0 }), | |
| 1131 | }, owner_decl_index); | |
| 1132 | } else if (typed_value.ty.abiSize(zcu) == 1) { | |
| 1133 | return GenResult.mcv(.{ .immediate = @intFromBool(!typed_value.val.isNull(zcu)) }); | |
| 1066 | if (ty.isPtrLikeOptional(zcu)) { | |
| 1067 | return genTypedValue( | |
| 1068 | lf, | |
| 1069 | src_loc, | |
| 1070 | val.optionalValue(zcu) orelse return GenResult.mcv(.{ .immediate = 0 }), | |
| 1071 | owner_decl_index, | |
| 1072 | ); | |
| 1073 | } else if (ty.abiSize(zcu) == 1) { | |
| 1074 | return GenResult.mcv(.{ .immediate = @intFromBool(!val.isNull(zcu)) }); | |
| 1134 | 1075 | } |
| 1135 | 1076 | }, |
| 1136 | 1077 | .Enum => { |
| 1137 | const enum_tag = zcu.intern_pool.indexToKey(typed_value.val.toIntern()).enum_tag; | |
| 1138 | const int_tag_ty = zcu.intern_pool.typeOf(enum_tag.int); | |
| 1139 | return genTypedValue(lf, src_loc, .{ | |
| 1140 | .ty = Type.fromInterned(int_tag_ty), | |
| 1141 | .val = Value.fromInterned(enum_tag.int), | |
| 1142 | }, owner_decl_index); | |
| 1078 | const enum_tag = zcu.intern_pool.indexToKey(val.toIntern()).enum_tag; | |
| 1079 | return genTypedValue( | |
| 1080 | lf, | |
| 1081 | src_loc, | |
| 1082 | Value.fromInterned(enum_tag.int), | |
| 1083 | owner_decl_index, | |
| 1084 | ); | |
| 1143 | 1085 | }, |
| 1144 | 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 | 1088 | const error_index = zcu.global_error_set.getIndex(err_name).?; |
| 1147 | 1089 | return GenResult.mcv(.{ .immediate = error_index }); |
| 1148 | 1090 | }, |
| 1149 | 1091 | .ErrorUnion => { |
| 1150 | const err_type = typed_value.ty.errorUnionSet(zcu); | |
| 1151 | const payload_type = typed_value.ty.errorUnionPayload(zcu); | |
| 1092 | const err_type = ty.errorUnionSet(zcu); | |
| 1093 | const payload_type = ty.errorUnionPayload(zcu); | |
| 1152 | 1094 | if (!payload_type.hasRuntimeBitsIgnoreComptime(zcu)) { |
| 1153 | 1095 | // We use the error type directly as the type. |
| 1154 | 1096 | const err_int_ty = try zcu.errorIntType(); |
| 1155 | switch (zcu.intern_pool.indexToKey(typed_value.val.toIntern()).error_union.val) { | |
| 1156 | .err_name => |err_name| return genTypedValue(lf, src_loc, .{ | |
| 1157 | .ty = err_type, | |
| 1158 | .val = Value.fromInterned((try zcu.intern(.{ .err = .{ | |
| 1097 | switch (zcu.intern_pool.indexToKey(val.toIntern()).error_union.val) { | |
| 1098 | .err_name => |err_name| return genTypedValue( | |
| 1099 | lf, | |
| 1100 | src_loc, | |
| 1101 | Value.fromInterned(try zcu.intern(.{ .err = .{ | |
| 1159 | 1102 | .ty = err_type.toIntern(), |
| 1160 | 1103 | .name = err_name, |
| 1161 | } }))), | |
| 1162 | }, owner_decl_index), | |
| 1163 | .payload => return genTypedValue(lf, src_loc, .{ | |
| 1164 | .ty = err_int_ty, | |
| 1165 | .val = try zcu.intValue(err_int_ty, 0), | |
| 1166 | }, owner_decl_index), | |
| 1104 | } })), | |
| 1105 | owner_decl_index, | |
| 1106 | ), | |
| 1107 | .payload => return genTypedValue( | |
| 1108 | lf, | |
| 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 | 1126 | else => {}, |
| 1181 | 1127 | } |
| 1182 | 1128 | |
| 1183 | return genUnnamedConst(lf, src_loc, typed_value, owner_decl_index); | |
| 1129 | return genUnnamedConst(lf, src_loc, val, owner_decl_index); | |
| 1184 | 1130 | } |
| 1185 | 1131 | |
| 1186 | 1132 | pub fn errUnionPayloadOffset(payload_ty: Type, mod: *Module) u64 { |
src/codegen/c.zig+37-44| ... | ... | @@ -9,7 +9,6 @@ const Module = @import("../Module.zig"); |
| 9 | 9 | const Compilation = @import("../Compilation.zig"); |
| 10 | 10 | const Value = @import("../Value.zig"); |
| 11 | 11 | const Type = @import("../type.zig").Type; |
| 12 | const TypedValue = @import("../TypedValue.zig"); | |
| 13 | 12 | const C = link.File.C; |
| 14 | 13 | const Decl = Module.Decl; |
| 15 | 14 | const trace = @import("../tracy.zig").trace; |
| ... | ... | @@ -657,7 +656,7 @@ pub const DeclGen = struct { |
| 657 | 656 | assert(decl.has_tv); |
| 658 | 657 | |
| 659 | 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 | 660 | return dg.writeCValue(writer, .{ .undef = ty }); |
| 662 | 661 | } |
| 663 | 662 | |
| ... | ... | @@ -673,7 +672,7 @@ pub const DeclGen = struct { |
| 673 | 672 | // them). The analysis until now should ensure that the C function |
| 674 | 673 | // pointers are compatible. If they are not, then there is a bug |
| 675 | 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 | 676 | if (need_typecast) { |
| 678 | 677 | try writer.writeAll("(("); |
| 679 | 678 | try dg.renderType(writer, ty); |
| ... | ... | @@ -1588,9 +1587,10 @@ pub const DeclGen = struct { |
| 1588 | 1587 | const ip = &mod.intern_pool; |
| 1589 | 1588 | |
| 1590 | 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); | |
| 1592 | 1592 | |
| 1593 | const fn_info = mod.typeToFunc(fn_decl.ty).?; | |
| 1593 | const fn_info = mod.typeToFunc(fn_ty).?; | |
| 1594 | 1594 | if (fn_info.cc == .Naked) { |
| 1595 | 1595 | switch (kind) { |
| 1596 | 1596 | .forward => try w.writeAll("zig_naked_decl "), |
| ... | ... | @@ -1876,9 +1876,9 @@ pub const DeclGen = struct { |
| 1876 | 1876 | try renderTypeSuffix(dg.pass, store.*, mod, w, cty_idx, .suffix, .{}); |
| 1877 | 1877 | } |
| 1878 | 1878 | |
| 1879 | fn declIsGlobal(dg: *DeclGen, tv: TypedValue) bool { | |
| 1879 | fn declIsGlobal(dg: *DeclGen, val: Value) bool { | |
| 1880 | 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 | 1882 | .variable => |variable| mod.decl_exports.contains(variable.decl), |
| 1883 | 1883 | .extern_func => true, |
| 1884 | 1884 | .func => |func| mod.decl_exports.contains(func.owner_decl), |
| ... | ... | @@ -1971,7 +1971,7 @@ pub const DeclGen = struct { |
| 1971 | 1971 | ) !void { |
| 1972 | 1972 | const decl = dg.module.declPtr(decl_index); |
| 1973 | 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 | 1975 | try fwd.writeAll(if (is_global) "zig_extern " else "static "); |
| 1976 | 1976 | const maybe_exports = dg.module.decl_exports.get(decl_index); |
| 1977 | 1977 | const export_weak_linkage = if (maybe_exports) |exports| |
| ... | ... | @@ -1982,7 +1982,7 @@ pub const DeclGen = struct { |
| 1982 | 1982 | if (variable.is_threadlocal) try fwd.writeAll("zig_threadlocal "); |
| 1983 | 1983 | try dg.renderTypeAndName( |
| 1984 | 1984 | fwd, |
| 1985 | decl.ty, | |
| 1985 | decl.typeOf(dg.module), | |
| 1986 | 1986 | .{ .decl = decl_index }, |
| 1987 | 1987 | CQualifiers.init(.{ .@"const" = variable.is_const }), |
| 1988 | 1988 | decl.alignment, |
| ... | ... | @@ -2009,7 +2009,6 @@ pub const DeclGen = struct { |
| 2009 | 2009 | fn renderDeclName(dg: *DeclGen, writer: anytype, decl_index: InternPool.DeclIndex, export_index: u32) !void { |
| 2010 | 2010 | const mod = dg.module; |
| 2011 | 2011 | const decl = mod.declPtr(decl_index); |
| 2012 | try mod.markDeclAlive(decl); | |
| 2013 | 2012 | |
| 2014 | 2013 | if (mod.decl_exports.get(decl_index)) |exports| { |
| 2015 | 2014 | try writer.print("{ }", .{ |
| ... | ... | @@ -2656,13 +2655,12 @@ fn genExports(o: *Object) !void { |
| 2656 | 2655 | .anon, .flush => return, |
| 2657 | 2656 | }; |
| 2658 | 2657 | const decl = mod.declPtr(decl_index); |
| 2659 | const tv: TypedValue = .{ .ty = decl.ty, .val = Value.fromInterned((try decl.internValue(mod))) }; | |
| 2660 | 2658 | const fwd = o.dg.fwdDeclWriter(); |
| 2661 | 2659 | |
| 2662 | 2660 | const exports = mod.decl_exports.get(decl_index) orelse return; |
| 2663 | 2661 | if (exports.items.len < 2) return; |
| 2664 | 2662 | |
| 2665 | const is_variable_const = switch (ip.indexToKey(tv.val.toIntern())) { | |
| 2663 | const is_variable_const = switch (ip.indexToKey(decl.val.toIntern())) { | |
| 2666 | 2664 | .func => return for (exports.items[1..], 1..) |@"export", i| { |
| 2667 | 2665 | try fwd.writeAll("zig_extern "); |
| 2668 | 2666 | if (@"export".opts.linkage == .weak) try fwd.writeAll("zig_weak_linkage_fn "); |
| ... | ... | @@ -2687,7 +2685,7 @@ fn genExports(o: *Object) !void { |
| 2687 | 2685 | const export_name = ip.stringToSlice(@"export".opts.name); |
| 2688 | 2686 | try o.dg.renderTypeAndName( |
| 2689 | 2687 | fwd, |
| 2690 | decl.ty, | |
| 2688 | decl.typeOf(mod), | |
| 2691 | 2689 | .{ .identifier = export_name }, |
| 2692 | 2690 | CQualifiers.init(.{ .@"const" = is_variable_const }), |
| 2693 | 2691 | decl.alignment, |
| ... | ... | @@ -2769,7 +2767,7 @@ pub fn genLazyFn(o: *Object, lazy_fn: LazyFnMap.Entry) !void { |
| 2769 | 2767 | }, |
| 2770 | 2768 | .never_tail, .never_inline => |fn_decl_index| { |
| 2771 | 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 | 2771 | const fn_info = fn_cty.cast(CType.Payload.Function).?.data; |
| 2774 | 2772 | |
| 2775 | 2773 | const fwd_decl_writer = o.dg.fwdDeclWriter(); |
| ... | ... | @@ -2805,15 +2803,11 @@ pub fn genFunc(f: *Function) !void { |
| 2805 | 2803 | const gpa = o.dg.gpa; |
| 2806 | 2804 | const decl_index = o.dg.pass.decl; |
| 2807 | 2805 | const decl = mod.declPtr(decl_index); |
| 2808 | const tv: TypedValue = .{ | |
| 2809 | .ty = decl.ty, | |
| 2810 | .val = decl.val, | |
| 2811 | }; | |
| 2812 | 2806 | |
| 2813 | 2807 | o.code_header = std.ArrayList(u8).init(gpa); |
| 2814 | 2808 | defer o.code_header.deinit(); |
| 2815 | 2809 | |
| 2816 | const is_global = o.dg.declIsGlobal(tv); | |
| 2810 | const is_global = o.dg.declIsGlobal(decl.val); | |
| 2817 | 2811 | const fwd_decl_writer = o.dg.fwdDeclWriter(); |
| 2818 | 2812 | try fwd_decl_writer.writeAll(if (is_global) "zig_extern " else "static "); |
| 2819 | 2813 | |
| ... | ... | @@ -2893,22 +2887,23 @@ pub fn genDecl(o: *Object) !void { |
| 2893 | 2887 | const mod = o.dg.module; |
| 2894 | 2888 | const decl_index = o.dg.pass.decl; |
| 2895 | 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); | |
| 2897 | 2892 | |
| 2898 | if (!tv.ty.isFnOrHasRuntimeBitsIgnoreComptime(mod)) return; | |
| 2899 | if (tv.val.getExternFunc(mod)) |_| { | |
| 2893 | if (!decl_ty.isFnOrHasRuntimeBitsIgnoreComptime(mod)) return; | |
| 2894 | if (decl_val.getExternFunc(mod)) |_| { | |
| 2900 | 2895 | const fwd_decl_writer = o.dg.fwdDeclWriter(); |
| 2901 | 2896 | try fwd_decl_writer.writeAll("zig_extern "); |
| 2902 | 2897 | try o.dg.renderFunctionSignature(fwd_decl_writer, decl_index, .forward, .{ .export_index = 0 }); |
| 2903 | 2898 | try fwd_decl_writer.writeAll(";\n"); |
| 2904 | 2899 | try genExports(o); |
| 2905 | } else if (tv.val.getVariable(mod)) |variable| { | |
| 2900 | } else if (decl_val.getVariable(mod)) |variable| { | |
| 2906 | 2901 | try o.dg.renderFwdDecl(decl_index, variable, .final); |
| 2907 | 2902 | try genExports(o); |
| 2908 | 2903 | |
| 2909 | 2904 | if (variable.is_extern) return; |
| 2910 | 2905 | |
| 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 | 2907 | const w = o.writer(); |
| 2913 | 2908 | if (!is_global) try w.writeAll("static "); |
| 2914 | 2909 | if (variable.is_weak_linkage) try w.writeAll("zig_weak_linkage "); |
| ... | ... | @@ -2916,22 +2911,22 @@ pub fn genDecl(o: *Object) !void { |
| 2916 | 2911 | if (mod.intern_pool.stringToSliceUnwrap(decl.@"linksection")) |s| |
| 2917 | 2912 | try w.print("zig_linksection(\"{s}\", ", .{s}); |
| 2918 | 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 | 2915 | if (decl.@"linksection" != .none) try w.writeAll(", read, write)"); |
| 2921 | 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 | 2918 | try w.writeByte(';'); |
| 2924 | 2919 | try o.indent_writer.insertNewline(); |
| 2925 | 2920 | } else { |
| 2926 | 2921 | const is_global = o.dg.module.decl_exports.contains(decl_index); |
| 2927 | 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 | } |
| 2931 | 2926 | |
| 2932 | 2927 | pub fn genDeclValue( |
| 2933 | 2928 | o: *Object, |
| 2934 | tv: TypedValue, | |
| 2929 | val: Value, | |
| 2935 | 2930 | is_global: bool, |
| 2936 | 2931 | decl_c_value: CValue, |
| 2937 | 2932 | alignment: Alignment, |
| ... | ... | @@ -2940,8 +2935,10 @@ pub fn genDeclValue( |
| 2940 | 2935 | const mod = o.dg.module; |
| 2941 | 2936 | const fwd_decl_writer = o.dg.fwdDeclWriter(); |
| 2942 | 2937 | |
| 2938 | const ty = val.typeOf(mod); | |
| 2939 | ||
| 2943 | 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 | 2942 | switch (o.dg.pass) { |
| 2946 | 2943 | .decl => |decl_index| { |
| 2947 | 2944 | if (mod.decl_exports.get(decl_index)) |exports| { |
| ... | ... | @@ -2964,10 +2961,10 @@ pub fn genDeclValue( |
| 2964 | 2961 | |
| 2965 | 2962 | if (mod.intern_pool.stringToSliceUnwrap(link_section)) |s| |
| 2966 | 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 | 2965 | if (link_section != .none) try w.writeAll(", read)"); |
| 2969 | 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 | 2968 | try w.writeAll(";\n"); |
| 2972 | 2969 | } |
| 2973 | 2970 | |
| ... | ... | @@ -2978,14 +2975,10 @@ pub fn genHeader(dg: *DeclGen) error{ AnalysisFail, OutOfMemory }!void { |
| 2978 | 2975 | const mod = dg.module; |
| 2979 | 2976 | const decl_index = dg.pass.decl; |
| 2980 | 2977 | const decl = mod.declPtr(decl_index); |
| 2981 | const tv: TypedValue = .{ | |
| 2982 | .ty = decl.ty, | |
| 2983 | .val = decl.val, | |
| 2984 | }; | |
| 2985 | 2978 | const writer = dg.fwdDeclWriter(); |
| 2986 | 2979 | |
| 2987 | switch (tv.ty.zigTypeTag(mod)) { | |
| 2988 | .Fn => if (dg.declIsGlobal(tv)) { | |
| 2980 | switch (decl.val.typeOf(mod).zigTypeTag(mod)) { | |
| 2981 | .Fn => if (dg.declIsGlobal(decl.val)) { | |
| 2989 | 2982 | try writer.writeAll("zig_extern "); |
| 2990 | 2983 | try dg.renderFunctionSignature(writer, dg.pass.decl, .complete, .{ .export_index = 0 }); |
| 2991 | 2984 | try dg.fwd_decl.appendSlice(";\n"); |
| ... | ... | @@ -5304,25 +5297,25 @@ fn airIsNull( |
| 5304 | 5297 | const err_int_ty = try mod.errorIntType(); |
| 5305 | 5298 | |
| 5306 | 5299 | const rhs = if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) |
| 5307 | TypedValue{ .ty = Type.bool, .val = Value.true } | |
| 5300 | Value.true | |
| 5308 | 5301 | else if (optional_ty.isPtrLikeOptional(mod)) |
| 5309 | 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 | 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 | 5306 | else if (payload_ty.isSlice(mod) and optional_ty.optionalReprIsPayload(mod)) rhs: { |
| 5314 | 5307 | try writer.writeAll(".ptr"); |
| 5315 | 5308 | const slice_ptr_ty = payload_ty.slicePtrFieldType(mod); |
| 5316 | 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 | 5311 | } else rhs: { |
| 5319 | 5312 | try writer.writeAll(".is_null"); |
| 5320 | break :rhs TypedValue{ .ty = Type.bool, .val = Value.true }; | |
| 5313 | break :rhs Value.true; | |
| 5321 | 5314 | }; |
| 5322 | 5315 | try writer.writeByte(' '); |
| 5323 | 5316 | try writer.writeAll(operator); |
| 5324 | 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 | 5319 | try writer.writeAll(";\n"); |
| 5327 | 5320 | return local; |
| 5328 | 5321 | } |
| ... | ... | @@ -7392,7 +7385,7 @@ fn airCVaStart(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7392 | 7385 | const inst_ty = f.typeOfIndex(inst); |
| 7393 | 7386 | const decl_index = f.object.dg.pass.decl; |
| 7394 | 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 | 7389 | const param_len = fn_cty.castTag(.varargs_function).?.data.param_types.len; |
| 7397 | 7390 | |
| 7398 | 7391 | const writer = f.object.writer(); |
src/codegen/llvm.zig+27-40| ... | ... | @@ -18,7 +18,6 @@ const Module = @import("../Module.zig"); |
| 18 | 18 | const Zcu = Module; |
| 19 | 19 | const InternPool = @import("../InternPool.zig"); |
| 20 | 20 | const Package = @import("../Package.zig"); |
| 21 | const TypedValue = @import("../TypedValue.zig"); | |
| 22 | 21 | const Air = @import("../Air.zig"); |
| 23 | 22 | const Liveness = @import("../Liveness.zig"); |
| 24 | 23 | const Value = @import("../Value.zig"); |
| ... | ... | @@ -1384,7 +1383,7 @@ pub const Object = struct { |
| 1384 | 1383 | const decl = zcu.declPtr(decl_index); |
| 1385 | 1384 | const namespace = zcu.namespacePtr(decl.src_namespace); |
| 1386 | 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 | 1387 | const target = zcu.getTarget(); |
| 1389 | 1388 | const ip = &zcu.intern_pool; |
| 1390 | 1389 | |
| ... | ... | @@ -1659,7 +1658,7 @@ pub const Object = struct { |
| 1659 | 1658 | const line_number = decl.src_line + 1; |
| 1660 | 1659 | const is_internal_linkage = decl.val.getExternFunc(zcu) == null and |
| 1661 | 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)); | |
| 1663 | 1662 | |
| 1664 | 1663 | const subprogram = try o.builder.debugSubprogram( |
| 1665 | 1664 | file, |
| ... | ... | @@ -1762,7 +1761,7 @@ pub const Object = struct { |
| 1762 | 1761 | const decl_name = decl_name: { |
| 1763 | 1762 | const decl_name = mod.intern_pool.stringToSlice(decl.name); |
| 1764 | 1763 | |
| 1765 | if (mod.getTarget().isWasm() and try decl.isFunction(mod)) { | |
| 1764 | if (mod.getTarget().isWasm() and decl.val.typeOf(mod).zigTypeTag(mod) == .Fn) { | |
| 1766 | 1765 | if (mod.intern_pool.stringToSliceUnwrap(decl.getOwnedExternFunc(mod).?.lib_name)) |lib_name| { |
| 1767 | 1766 | if (!std.mem.eql(u8, lib_name, "c")) { |
| 1768 | 1767 | break :decl_name try self.builder.strtabStringFmt("{s}|{s}", .{ decl_name, lib_name }); |
| ... | ... | @@ -2881,7 +2880,7 @@ pub const Object = struct { |
| 2881 | 2880 | const decl = zcu.declPtr(decl_index); |
| 2882 | 2881 | const namespace = zcu.namespacePtr(decl.src_namespace); |
| 2883 | 2882 | const owner_mod = namespace.file_scope.mod; |
| 2884 | const zig_fn_type = decl.ty; | |
| 2883 | const zig_fn_type = decl.typeOf(zcu); | |
| 2885 | 2884 | const gop = try o.decl_map.getOrPut(gpa, decl_index); |
| 2886 | 2885 | if (gop.found_existing) return gop.value_ptr.ptr(&o.builder).kind.function; |
| 2887 | 2886 | |
| ... | ... | @@ -3112,7 +3111,7 @@ pub const Object = struct { |
| 3112 | 3111 | try o.builder.strtabString(mod.intern_pool.stringToSlice( |
| 3113 | 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 | 3115 | toLlvmGlobalAddressSpace(decl.@"addrspace", mod.getTarget()), |
| 3117 | 3116 | ); |
| 3118 | 3117 | gop.value_ptr.* = variable_index.ptrConst(&o.builder).global; |
| ... | ... | @@ -3722,15 +3721,11 @@ pub const Object = struct { |
| 3722 | 3721 | => unreachable, // non-runtime values |
| 3723 | 3722 | .extern_func => |extern_func| { |
| 3724 | 3723 | const fn_decl_index = extern_func.decl; |
| 3725 | const fn_decl = mod.declPtr(fn_decl_index); | |
| 3726 | try mod.markDeclAlive(fn_decl); | |
| 3727 | 3724 | const function_index = try o.resolveLlvmFunction(fn_decl_index); |
| 3728 | 3725 | return function_index.ptrConst(&o.builder).global.toConst(); |
| 3729 | 3726 | }, |
| 3730 | 3727 | .func => |func| { |
| 3731 | 3728 | const fn_decl_index = func.owner_decl; |
| 3732 | const fn_decl = mod.declPtr(fn_decl_index); | |
| 3733 | try mod.markDeclAlive(fn_decl); | |
| 3734 | 3729 | const function_index = try o.resolveLlvmFunction(fn_decl_index); |
| 3735 | 3730 | return function_index.ptrConst(&o.builder).global.toConst(); |
| 3736 | 3731 | }, |
| ... | ... | @@ -4262,8 +4257,7 @@ pub const Object = struct { |
| 4262 | 4257 | fn lowerParentPtrDecl(o: *Object, decl_index: InternPool.DeclIndex) Allocator.Error!Builder.Constant { |
| 4263 | 4258 | const mod = o.module; |
| 4264 | 4259 | const decl = mod.declPtr(decl_index); |
| 4265 | try mod.markDeclAlive(decl); | |
| 4266 | const ptr_ty = try mod.singleMutPtrType(decl.ty); | |
| 4260 | const ptr_ty = try mod.singleMutPtrType(decl.typeOf(mod)); | |
| 4267 | 4261 | return o.lowerDeclRefValue(ptr_ty, decl_index); |
| 4268 | 4262 | } |
| 4269 | 4263 | |
| ... | ... | @@ -4450,11 +4444,10 @@ pub const Object = struct { |
| 4450 | 4444 | } |
| 4451 | 4445 | } |
| 4452 | 4446 | |
| 4453 | const is_fn_body = decl.ty.zigTypeTag(mod) == .Fn; | |
| 4454 | if ((!is_fn_body and !decl.ty.hasRuntimeBits(mod)) or | |
| 4455 | (is_fn_body and mod.typeToFunc(decl.ty).?.is_generic)) return o.lowerPtrToVoid(ty); | |
| 4456 | ||
| 4457 | try mod.markDeclAlive(decl); | |
| 4447 | const decl_ty = decl.typeOf(mod); | |
| 4448 | const is_fn_body = decl_ty.zigTypeTag(mod) == .Fn; | |
| 4449 | if ((!is_fn_body and !decl_ty.hasRuntimeBits(mod)) or | |
| 4450 | (is_fn_body and mod.typeToFunc(decl_ty).?.is_generic)) return o.lowerPtrToVoid(ty); | |
| 4458 | 4451 | |
| 4459 | 4452 | const llvm_global = if (is_fn_body) |
| 4460 | 4453 | (try o.resolveLlvmFunction(decl_index)).ptrConst(&o.builder).global |
| ... | ... | @@ -4740,7 +4733,7 @@ pub const DeclGen = struct { |
| 4740 | 4733 | debug_file, // File |
| 4741 | 4734 | debug_file, // Scope |
| 4742 | 4735 | line_number, |
| 4743 | try o.lowerDebugType(decl.ty), | |
| 4736 | try o.lowerDebugType(decl.typeOf(zcu)), | |
| 4744 | 4737 | variable_index, |
| 4745 | 4738 | .{ .local = is_internal_linkage }, |
| 4746 | 4739 | ); |
| ... | ... | @@ -4829,19 +4822,17 @@ pub const FuncGen = struct { |
| 4829 | 4822 | |
| 4830 | 4823 | const o = self.dg.object; |
| 4831 | 4824 | const mod = o.module; |
| 4832 | const llvm_val = try self.resolveValue(.{ | |
| 4833 | .ty = self.typeOf(inst), | |
| 4834 | .val = (try self.air.value(inst, mod)).?, | |
| 4835 | }); | |
| 4825 | const llvm_val = try self.resolveValue((try self.air.value(inst, mod)).?); | |
| 4836 | 4826 | gop.value_ptr.* = llvm_val.toValue(); |
| 4837 | 4827 | return llvm_val.toValue(); |
| 4838 | 4828 | } |
| 4839 | 4829 | |
| 4840 | fn resolveValue(self: *FuncGen, tv: TypedValue) Error!Builder.Constant { | |
| 4830 | fn resolveValue(self: *FuncGen, val: Value) Error!Builder.Constant { | |
| 4841 | 4831 | const o = self.dg.object; |
| 4842 | 4832 | const mod = o.module; |
| 4843 | const llvm_val = try o.lowerValue(tv.val.toIntern()); | |
| 4844 | if (!isByRef(tv.ty, mod)) return llvm_val; | |
| 4833 | const ty = val.typeOf(mod); | |
| 4834 | const llvm_val = try o.lowerValue(val.toIntern()); | |
| 4835 | if (!isByRef(ty, mod)) return llvm_val; | |
| 4845 | 4836 | |
| 4846 | 4837 | // We have an LLVM value but we need to create a global constant and |
| 4847 | 4838 | // set the value as its initializer, and then return a pointer to the global. |
| ... | ... | @@ -4855,7 +4846,7 @@ pub const FuncGen = struct { |
| 4855 | 4846 | variable_index.setLinkage(.private, &o.builder); |
| 4856 | 4847 | variable_index.setMutability(.constant, &o.builder); |
| 4857 | 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 | 4850 | return o.builder.convConst( |
| 4860 | 4851 | .unneeded, |
| 4861 | 4852 | variable_index.toConst(&o.builder), |
| ... | ... | @@ -4867,11 +4858,10 @@ pub const FuncGen = struct { |
| 4867 | 4858 | const o = self.dg.object; |
| 4868 | 4859 | const mod = o.module; |
| 4869 | 4860 | if (o.null_opt_usize == .no_init) { |
| 4870 | const ty = try mod.intern(.{ .opt_type = .usize_type }); | |
| 4871 | o.null_opt_usize = try self.resolveValue(.{ | |
| 4872 | .ty = Type.fromInterned(ty), | |
| 4873 | .val = Value.fromInterned((try mod.intern(.{ .opt = .{ .ty = ty, .val = .none } }))), | |
| 4874 | }); | |
| 4861 | o.null_opt_usize = try self.resolveValue(Value.fromInterned(try mod.intern(.{ .opt = .{ | |
| 4862 | .ty = try mod.intern(.{ .opt_type = .usize_type }), | |
| 4863 | .val = .none, | |
| 4864 | } }))); | |
| 4875 | 4865 | } |
| 4876 | 4866 | return o.null_opt_usize; |
| 4877 | 4867 | } |
| ... | ... | @@ -5530,8 +5520,8 @@ pub const FuncGen = struct { |
| 5530 | 5520 | const mod = o.module; |
| 5531 | 5521 | const msg_decl_index = mod.panic_messages[@intFromEnum(panic_id)].unwrap().?; |
| 5532 | 5522 | const msg_decl = mod.declPtr(msg_decl_index); |
| 5533 | const msg_len = msg_decl.ty.childType(mod).arrayLen(mod); | |
| 5534 | const msg_ptr = try o.lowerValue(try msg_decl.internValue(mod)); | |
| 5523 | const msg_len = msg_decl.typeOf(mod).childType(mod).arrayLen(mod); | |
| 5524 | const msg_ptr = try o.lowerValue(msg_decl.val.toIntern()); | |
| 5535 | 5525 | const null_opt_addr_global = try fg.resolveNullOptUsize(); |
| 5536 | 5526 | const target = mod.getTarget(); |
| 5537 | 5527 | const llvm_usize = try o.lowerType(Type.usize); |
| ... | ... | @@ -5544,7 +5534,7 @@ pub const FuncGen = struct { |
| 5544 | 5534 | // ) |
| 5545 | 5535 | const panic_func = mod.funcInfo(mod.panic_func_index); |
| 5546 | 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 | 5538 | const panic_global = try o.resolveLlvmFunction(panic_func.owner_decl); |
| 5549 | 5539 | _ = try fg.wip.call( |
| 5550 | 5540 | .normal, |
| ... | ... | @@ -5612,7 +5602,7 @@ pub const FuncGen = struct { |
| 5612 | 5602 | _ = try self.wip.retVoid(); |
| 5613 | 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 | 5606 | if (!ret_ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 5617 | 5607 | if (Type.fromInterned(fn_info.return_type).isError(mod)) { |
| 5618 | 5608 | // Functions with an empty error set are emitted with an error code |
| ... | ... | @@ -5674,7 +5664,7 @@ pub const FuncGen = struct { |
| 5674 | 5664 | const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op; |
| 5675 | 5665 | const ptr_ty = self.typeOf(un_op); |
| 5676 | 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 | 5668 | if (!ret_ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 5679 | 5669 | if (Type.fromInterned(fn_info.return_type).isError(mod)) { |
| 5680 | 5670 | // Functions with an empty error set are emitted with an error code |
| ... | ... | @@ -10067,10 +10057,7 @@ pub const FuncGen = struct { |
| 10067 | 10057 | const elem_ptr = try self.wip.gep(.inbounds, llvm_result_ty, alloca_inst, &.{ |
| 10068 | 10058 | usize_zero, try o.builder.intValue(llvm_usize, array_info.len), |
| 10069 | 10059 | }, ""); |
| 10070 | const llvm_elem = try self.resolveValue(.{ | |
| 10071 | .ty = array_info.elem_type, | |
| 10072 | .val = sent_val, | |
| 10073 | }); | |
| 10060 | const llvm_elem = try self.resolveValue(sent_val); | |
| 10074 | 10061 | try self.store(elem_ptr, elem_ptr_ty, llvm_elem.toValue(), .none); |
| 10075 | 10062 | } |
| 10076 | 10063 |
src/codegen/spirv.zig+11-12| ... | ... | @@ -255,7 +255,6 @@ pub const Object = struct { |
| 255 | 255 | pub fn resolveDecl(self: *Object, mod: *Module, decl_index: InternPool.DeclIndex) !SpvModule.Decl.Index { |
| 256 | 256 | const decl = mod.declPtr(decl_index); |
| 257 | 257 | assert(decl.has_tv); // TODO: Do we need to handle a situation where this is false? |
| 258 | try mod.markDeclAlive(decl); | |
| 259 | 258 | |
| 260 | 259 | const entry = try self.decl_link.getOrPut(self.gpa, decl_index); |
| 261 | 260 | if (!entry.found_existing) { |
| ... | ... | @@ -861,7 +860,7 @@ const DeclGen = struct { |
| 861 | 860 | |
| 862 | 861 | const val = arg_val; |
| 863 | 862 | |
| 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 | 864 | if (val.isUndefDeep(mod)) { |
| 866 | 865 | return self.spv.constUndef(result_ty_ref); |
| 867 | 866 | } |
| ... | ... | @@ -1221,7 +1220,7 @@ const DeclGen = struct { |
| 1221 | 1220 | else => {}, |
| 1222 | 1221 | } |
| 1223 | 1222 | |
| 1224 | if (!decl.ty.isFnOrHasRuntimeBitsIgnoreComptime(mod)) { | |
| 1223 | if (!decl.typeOf(mod).isFnOrHasRuntimeBitsIgnoreComptime(mod)) { | |
| 1225 | 1224 | // Pointer to nothing - return undefined. |
| 1226 | 1225 | return self.spv.constUndef(ty_ref); |
| 1227 | 1226 | } |
| ... | ... | @@ -1237,7 +1236,7 @@ const DeclGen = struct { |
| 1237 | 1236 | const final_storage_class = self.spvStorageClass(decl.@"addrspace"); |
| 1238 | 1237 | try self.addFunctionDep(spv_decl_index, final_storage_class); |
| 1239 | 1238 | |
| 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); | |
| 1241 | 1240 | |
| 1242 | 1241 | const ptr_id = switch (final_storage_class) { |
| 1243 | 1242 | .Generic => try self.castToGeneric(self.typeId(decl_ptr_ty_ref), decl_id), |
| ... | ... | @@ -2044,11 +2043,11 @@ const DeclGen = struct { |
| 2044 | 2043 | |
| 2045 | 2044 | switch (self.spv.declPtr(spv_decl_index).kind) { |
| 2046 | 2045 | .func => { |
| 2047 | assert(decl.ty.zigTypeTag(mod) == .Fn); | |
| 2048 | const fn_info = mod.typeToFunc(decl.ty).?; | |
| 2046 | assert(decl.typeOf(mod).zigTypeTag(mod) == .Fn); | |
| 2047 | const fn_info = mod.typeToFunc(decl.typeOf(mod)).?; | |
| 2049 | 2048 | const return_ty_ref = try self.resolveFnReturnType(Type.fromInterned(fn_info.return_type)); |
| 2050 | 2049 | |
| 2051 | const prototype_ty_ref = try self.resolveType(decl.ty, .direct); | |
| 2050 | const prototype_ty_ref = try self.resolveType(decl.typeOf(mod), .direct); | |
| 2052 | 2051 | try self.func.prologue.emit(self.spv.gpa, .OpFunction, .{ |
| 2053 | 2052 | .id_result_type = self.typeId(return_ty_ref), |
| 2054 | 2053 | .id_result = result_id, |
| ... | ... | @@ -2121,7 +2120,7 @@ const DeclGen = struct { |
| 2121 | 2120 | const final_storage_class = self.spvStorageClass(decl.@"addrspace"); |
| 2122 | 2121 | assert(final_storage_class != .Generic); // These should be instance globals |
| 2123 | 2122 | |
| 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); | |
| 2125 | 2124 | |
| 2126 | 2125 | try self.spv.sections.types_globals_constants.emit(self.spv.gpa, .OpVariable, .{ |
| 2127 | 2126 | .id_result_type = self.typeId(ptr_ty_ref), |
| ... | ... | @@ -2144,7 +2143,7 @@ const DeclGen = struct { |
| 2144 | 2143 | |
| 2145 | 2144 | try self.spv.declareDeclDeps(spv_decl_index, &.{}); |
| 2146 | 2145 | |
| 2147 | const ptr_ty_ref = try self.ptrType(decl.ty, .Function); | |
| 2146 | const ptr_ty_ref = try self.ptrType(decl.typeOf(mod), .Function); | |
| 2148 | 2147 | |
| 2149 | 2148 | if (maybe_init_val) |init_val| { |
| 2150 | 2149 | // TODO: Combine with resolveAnonDecl? |
| ... | ... | @@ -2168,7 +2167,7 @@ const DeclGen = struct { |
| 2168 | 2167 | }); |
| 2169 | 2168 | self.current_block_label = root_block_id; |
| 2170 | 2169 | |
| 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 | 2171 | try self.func.body.emit(self.spv.gpa, .OpStore, .{ |
| 2173 | 2172 | .pointer = result_id, |
| 2174 | 2173 | .object = val_id, |
| ... | ... | @@ -4785,7 +4784,7 @@ const DeclGen = struct { |
| 4785 | 4784 | const mod = self.module; |
| 4786 | 4785 | if (!ret_ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 4787 | 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 | 4788 | if (Type.fromInterned(fn_info.return_type).isError(mod)) { |
| 4790 | 4789 | // Functions with an empty error set are emitted with an error code |
| 4791 | 4790 | // return type and return zero so they can be function pointers coerced |
| ... | ... | @@ -4810,7 +4809,7 @@ const DeclGen = struct { |
| 4810 | 4809 | |
| 4811 | 4810 | if (!ret_ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 4812 | 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 | 4813 | if (Type.fromInterned(fn_info.return_type).isError(mod)) { |
| 4815 | 4814 | // Functions with an empty error set are emitted with an error code |
| 4816 | 4815 | // 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 | 17 | const Module = @import("Module.zig"); |
| 18 | 18 | const InternPool = @import("InternPool.zig"); |
| 19 | 19 | const Type = @import("type.zig").Type; |
| 20 | const TypedValue = @import("TypedValue.zig"); | |
| 20 | const Value = @import("Value.zig"); | |
| 21 | 21 | const LlvmObject = @import("codegen/llvm.zig").Object; |
| 22 | 22 | |
| 23 | 23 | /// When adding a new field, remember to update `hashAddSystemLibs`. |
| ... | ... | @@ -376,14 +376,14 @@ pub const File = struct { |
| 376 | 376 | /// Called from within the CodeGen to lower a local variable instantion as an unnamed |
| 377 | 377 | /// constant. Returns the symbol index of the lowered constant in the read-only section |
| 378 | 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 | 380 | if (build_options.only_c) @compileError("unreachable"); |
| 381 | 381 | switch (base.tag) { |
| 382 | 382 | .spirv => unreachable, |
| 383 | 383 | .c => unreachable, |
| 384 | 384 | .nvptx => unreachable, |
| 385 | 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 | 209 | .module = module, |
| 210 | 210 | .error_msg = null, |
| 211 | 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 | 213 | .fwd_decl = fwd_decl.toManaged(gpa), |
| 214 | 214 | .ctypes = ctypes.*, |
| 215 | 215 | .anon_decl_deps = self.anon_decls, |
| ... | ... | @@ -283,13 +283,9 @@ fn updateAnonDecl(self: *C, module: *Module, i: usize) !void { |
| 283 | 283 | code.* = object.code.moveToUnmanaged(); |
| 284 | 284 | } |
| 285 | 285 | |
| 286 | const tv: @import("../TypedValue.zig") = .{ | |
| 287 | .ty = Type.fromInterned(module.intern_pool.typeOf(anon_decl)), | |
| 288 | .val = Value.fromInterned(anon_decl), | |
| 289 | }; | |
| 290 | 286 | const c_value: codegen.CValue = .{ .constant = anon_decl }; |
| 291 | 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 | 289 | error.AnalysisFail => { |
| 294 | 290 | @panic("TODO: C backend AnalysisFail on anonymous decl"); |
| 295 | 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 | 1167 | return self.updateExports(mod, .{ .decl_index = decl_index }, mod.getDeclExports(decl_index)); |
| 1168 | 1168 | } |
| 1169 | 1169 | |
| 1170 | pub fn lowerUnnamedConst(self: *Coff, tv: TypedValue, decl_index: InternPool.DeclIndex) !u32 { | |
| 1170 | pub fn lowerUnnamedConst(self: *Coff, val: Value, decl_index: InternPool.DeclIndex) !u32 { | |
| 1171 | 1171 | const gpa = self.base.comp.gpa; |
| 1172 | 1172 | const mod = self.base.comp.module.?; |
| 1173 | 1173 | const decl = mod.declPtr(decl_index); |
| ... | ... | @@ -1180,7 +1180,8 @@ pub fn lowerUnnamedConst(self: *Coff, tv: TypedValue, decl_index: InternPool.Dec |
| 1180 | 1180 | const index = unnamed_consts.items.len; |
| 1181 | 1181 | const sym_name = try std.fmt.allocPrint(gpa, "__unnamed_{s}_{d}", .{ decl_name, index }); |
| 1182 | 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 | 1185 | .ok => |atom_index| atom_index, |
| 1185 | 1186 | .fail => |em| { |
| 1186 | 1187 | decl.analysis = .codegen_failure; |
| ... | ... | @@ -1198,7 +1199,7 @@ const LowerConstResult = union(enum) { |
| 1198 | 1199 | fail: *Module.ErrorMsg, |
| 1199 | 1200 | }; |
| 1200 | 1201 | |
| 1201 | fn lowerConst(self: *Coff, name: []const u8, tv: TypedValue, required_alignment: InternPool.Alignment, sect_id: u16, src_loc: Module.SrcLoc) !LowerConstResult { | |
| 1202 | fn lowerConst(self: *Coff, name: []const u8, val: Value, required_alignment: InternPool.Alignment, sect_id: u16, src_loc: Module.SrcLoc) !LowerConstResult { | |
| 1202 | 1203 | const gpa = self.base.comp.gpa; |
| 1203 | 1204 | |
| 1204 | 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 | 1210 | try self.setSymbolName(sym, name); |
| 1210 | 1211 | sym.section_number = @as(coff.SectionNumber, @enumFromInt(sect_id + 1)); |
| 1211 | 1212 | |
| 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 | 1214 | .parent_atom_index = self.getAtom(atom_index).getSymbolIndex().?, |
| 1214 | 1215 | }); |
| 1215 | 1216 | const code = switch (res) { |
| ... | ... | @@ -1271,10 +1272,7 @@ pub fn updateDecl( |
| 1271 | 1272 | defer code_buffer.deinit(); |
| 1272 | 1273 | |
| 1273 | 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 | .ty = decl.ty, | |
| 1276 | .val = decl_val, | |
| 1277 | }, &code_buffer, .none, .{ | |
| 1275 | const res = try codegen.generateSymbol(&self.base, decl.srcLoc(mod), decl_val, &code_buffer, .none, .{ | |
| 1278 | 1276 | .parent_atom_index = atom.getSymbolIndex().?, |
| 1279 | 1277 | }); |
| 1280 | 1278 | const code = switch (res) { |
| ... | ... | @@ -1399,8 +1397,8 @@ pub fn getOrCreateAtomForDecl(self: *Coff, decl_index: InternPool.DeclIndex) !At |
| 1399 | 1397 | |
| 1400 | 1398 | fn getDeclOutputSection(self: *Coff, decl_index: InternPool.DeclIndex) u16 { |
| 1401 | 1399 | const decl = self.base.comp.module.?.declPtr(decl_index); |
| 1402 | const ty = decl.ty; | |
| 1403 | 1400 | const mod = self.base.comp.module.?; |
| 1401 | const ty = decl.typeOf(mod); | |
| 1404 | 1402 | const zig_ty = ty.zigTypeTag(mod); |
| 1405 | 1403 | const val = decl.val; |
| 1406 | 1404 | const index: u16 = blk: { |
| ... | ... | @@ -1535,7 +1533,7 @@ pub fn updateExports( |
| 1535 | 1533 | .x86 => std.builtin.CallingConvention.Stdcall, |
| 1536 | 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 | 1537 | if (decl_cc == .C and ip.stringEqlSlice(exp.opts.name, "main") and |
| 1540 | 1538 | comp.config.link_libc) |
| 1541 | 1539 | { |
| ... | ... | @@ -1887,14 +1885,13 @@ pub fn lowerAnonDecl( |
| 1887 | 1885 | } |
| 1888 | 1886 | |
| 1889 | 1887 | const val = Value.fromInterned(decl_val); |
| 1890 | const tv = TypedValue{ .ty = ty, .val = val }; | |
| 1891 | 1888 | var name_buf: [32]u8 = undefined; |
| 1892 | 1889 | const name = std.fmt.bufPrint(&name_buf, "__anon_{d}", .{ |
| 1893 | 1890 | @intFromEnum(decl_val), |
| 1894 | 1891 | }) catch unreachable; |
| 1895 | 1892 | const res = self.lowerConst( |
| 1896 | 1893 | name, |
| 1897 | tv, | |
| 1894 | val, | |
| 1898 | 1895 | decl_alignment, |
| 1899 | 1896 | self.rdata_section_index.?, |
| 1900 | 1897 | src_loc, |
| ... | ... | @@ -2754,7 +2751,6 @@ const TableSection = @import("table_section.zig").TableSection; |
| 2754 | 2751 | const StringTable = @import("StringTable.zig"); |
| 2755 | 2752 | const Type = @import("../type.zig").Type; |
| 2756 | 2753 | const Value = @import("../Value.zig"); |
| 2757 | const TypedValue = @import("../TypedValue.zig"); | |
| 2758 | 2754 | |
| 2759 | 2755 | pub const base_tag: link.File.Tag = .coff; |
| 2760 | 2756 |
src/link/Dwarf.zig+3-3| ... | ... | @@ -1109,7 +1109,7 @@ pub fn initDeclState(self: *Dwarf, mod: *Module, decl_index: InternPool.DeclInde |
| 1109 | 1109 | |
| 1110 | 1110 | assert(decl.has_tv); |
| 1111 | 1111 | |
| 1112 | switch (decl.ty.zigTypeTag(mod)) { | |
| 1112 | switch (decl.typeOf(mod).zigTypeTag(mod)) { | |
| 1113 | 1113 | .Fn => { |
| 1114 | 1114 | _ = try self.getOrCreateAtomForDecl(.src_fn, decl_index); |
| 1115 | 1115 | |
| ... | ... | @@ -1162,7 +1162,7 @@ pub fn initDeclState(self: *Dwarf, mod: *Module, decl_index: InternPool.DeclInde |
| 1162 | 1162 | try dbg_info_buffer.ensureUnusedCapacity(1 + ptr_width_bytes + 4 + 4 + |
| 1163 | 1163 | (decl_name_slice.len + 1) + (decl_linkage_name_slice.len + 1)); |
| 1164 | 1164 | |
| 1165 | const fn_ret_type = decl.ty.fnReturnType(mod); | |
| 1165 | const fn_ret_type = decl.typeOf(mod).fnReturnType(mod); | |
| 1166 | 1166 | const fn_ret_has_bits = fn_ret_type.hasRuntimeBits(mod); |
| 1167 | 1167 | dbg_info_buffer.appendAssumeCapacity(@intFromEnum( |
| 1168 | 1168 | @as(AbbrevCode, if (fn_ret_has_bits) .subprogram else .subprogram_retvoid), |
| ... | ... | @@ -1215,7 +1215,7 @@ pub fn commitDeclState( |
| 1215 | 1215 | var dbg_info_buffer = &decl_state.dbg_info; |
| 1216 | 1216 | |
| 1217 | 1217 | assert(decl.has_tv); |
| 1218 | switch (decl.ty.zigTypeTag(zcu)) { | |
| 1218 | switch (decl.typeOf(zcu).zigTypeTag(zcu)) { | |
| 1219 | 1219 | .Fn => { |
| 1220 | 1220 | try decl_state.setInlineFunc(decl.val.toIntern()); |
| 1221 | 1221 |
src/link/Elf.zig+3-3| ... | ... | @@ -3039,8 +3039,8 @@ pub fn updateDecl( |
| 3039 | 3039 | return self.zigObjectPtr().?.updateDecl(self, mod, decl_index); |
| 3040 | 3040 | } |
| 3041 | 3041 | |
| 3042 | pub fn lowerUnnamedConst(self: *Elf, typed_value: TypedValue, decl_index: InternPool.DeclIndex) !u32 { | |
| 3043 | return self.zigObjectPtr().?.lowerUnnamedConst(self, typed_value, decl_index); | |
| 3042 | pub fn lowerUnnamedConst(self: *Elf, val: Value, decl_index: InternPool.DeclIndex) !u32 { | |
| 3043 | return self.zigObjectPtr().?.lowerUnnamedConst(self, val, decl_index); | |
| 3044 | 3044 | } |
| 3045 | 3045 | |
| 3046 | 3046 | pub fn updateExports( |
| ... | ... | @@ -6260,7 +6260,7 @@ const SharedObject = @import("Elf/SharedObject.zig"); |
| 6260 | 6260 | const Symbol = @import("Elf/Symbol.zig"); |
| 6261 | 6261 | const StringTable = @import("StringTable.zig"); |
| 6262 | 6262 | const Thunk = thunks.Thunk; |
| 6263 | const TypedValue = @import("../TypedValue.zig"); | |
| 6263 | const Value = @import("../Value.zig"); | |
| 6264 | 6264 | const VerneedSection = synthetic_sections.VerneedSection; |
| 6265 | 6265 | const ZigGotSection = synthetic_sections.ZigGotSection; |
| 6266 | 6266 | const ZigObject = @import("Elf/ZigObject.zig"); |
src/link/Elf/ZigObject.zig+10-17| ... | ... | @@ -702,7 +702,6 @@ pub fn lowerAnonDecl( |
| 702 | 702 | } |
| 703 | 703 | |
| 704 | 704 | const val = Value.fromInterned(decl_val); |
| 705 | const tv = TypedValue{ .ty = ty, .val = val }; | |
| 706 | 705 | var name_buf: [32]u8 = undefined; |
| 707 | 706 | const name = std.fmt.bufPrint(&name_buf, "__anon_{d}", .{ |
| 708 | 707 | @intFromEnum(decl_val), |
| ... | ... | @@ -710,7 +709,7 @@ pub fn lowerAnonDecl( |
| 710 | 709 | const res = self.lowerConst( |
| 711 | 710 | elf_file, |
| 712 | 711 | name, |
| 713 | tv, | |
| 712 | val, | |
| 714 | 713 | decl_alignment, |
| 715 | 714 | elf_file.zig_data_rel_ro_section_index.?, |
| 716 | 715 | src_loc, |
| ... | ... | @@ -846,7 +845,7 @@ fn getDeclShdrIndex( |
| 846 | 845 | _ = self; |
| 847 | 846 | const mod = elf_file.base.comp.module.?; |
| 848 | 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 | 849 | .Fn => elf_file.zig_text_section_index.?, |
| 851 | 850 | else => blk: { |
| 852 | 851 | if (decl.getOwnedVariable(mod)) |variable| { |
| ... | ... | @@ -1157,19 +1156,13 @@ pub fn updateDecl( |
| 1157 | 1156 | // TODO implement .debug_info for global variables |
| 1158 | 1157 | const decl_val = if (decl.val.getVariable(mod)) |variable| Value.fromInterned(variable.init) else decl.val; |
| 1159 | 1158 | const res = if (decl_state) |*ds| |
| 1160 | try codegen.generateSymbol(&elf_file.base, decl.srcLoc(mod), .{ | |
| 1161 | .ty = decl.ty, | |
| 1162 | .val = decl_val, | |
| 1163 | }, &code_buffer, .{ | |
| 1159 | try codegen.generateSymbol(&elf_file.base, decl.srcLoc(mod), decl_val, &code_buffer, .{ | |
| 1164 | 1160 | .dwarf = ds, |
| 1165 | 1161 | }, .{ |
| 1166 | 1162 | .parent_atom_index = sym_index, |
| 1167 | 1163 | }) |
| 1168 | 1164 | else |
| 1169 | try codegen.generateSymbol(&elf_file.base, decl.srcLoc(mod), .{ | |
| 1170 | .ty = decl.ty, | |
| 1171 | .val = decl_val, | |
| 1172 | }, &code_buffer, .none, .{ | |
| 1165 | try codegen.generateSymbol(&elf_file.base, decl.srcLoc(mod), decl_val, &code_buffer, .none, .{ | |
| 1173 | 1166 | .parent_atom_index = sym_index, |
| 1174 | 1167 | }); |
| 1175 | 1168 | |
| ... | ... | @@ -1289,7 +1282,7 @@ fn updateLazySymbol( |
| 1289 | 1282 | pub fn lowerUnnamedConst( |
| 1290 | 1283 | self: *ZigObject, |
| 1291 | 1284 | elf_file: *Elf, |
| 1292 | typed_value: TypedValue, | |
| 1285 | val: Value, | |
| 1293 | 1286 | decl_index: InternPool.DeclIndex, |
| 1294 | 1287 | ) !u32 { |
| 1295 | 1288 | const gpa = elf_file.base.comp.gpa; |
| ... | ... | @@ -1304,11 +1297,12 @@ pub fn lowerUnnamedConst( |
| 1304 | 1297 | const index = unnamed_consts.items.len; |
| 1305 | 1298 | const name = try std.fmt.allocPrint(gpa, "__unnamed_{s}_{d}", .{ decl_name, index }); |
| 1306 | 1299 | defer gpa.free(name); |
| 1300 | const ty = val.typeOf(mod); | |
| 1307 | 1301 | const sym_index = switch (try self.lowerConst( |
| 1308 | 1302 | elf_file, |
| 1309 | 1303 | name, |
| 1310 | typed_value, | |
| 1311 | typed_value.ty.abiAlignment(mod), | |
| 1304 | val, | |
| 1305 | ty.abiAlignment(mod), | |
| 1312 | 1306 | elf_file.zig_data_rel_ro_section_index.?, |
| 1313 | 1307 | decl.srcLoc(mod), |
| 1314 | 1308 | )) { |
| ... | ... | @@ -1334,7 +1328,7 @@ fn lowerConst( |
| 1334 | 1328 | self: *ZigObject, |
| 1335 | 1329 | elf_file: *Elf, |
| 1336 | 1330 | name: []const u8, |
| 1337 | tv: TypedValue, | |
| 1331 | val: Value, | |
| 1338 | 1332 | required_alignment: InternPool.Alignment, |
| 1339 | 1333 | output_section_index: u32, |
| 1340 | 1334 | src_loc: Module.SrcLoc, |
| ... | ... | @@ -1346,7 +1340,7 @@ fn lowerConst( |
| 1346 | 1340 | |
| 1347 | 1341 | const sym_index = try self.addAtom(elf_file); |
| 1348 | 1342 | |
| 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 | 1344 | .none = {}, |
| 1351 | 1345 | }, .{ |
| 1352 | 1346 | .parent_atom_index = sym_index, |
| ... | ... | @@ -1657,5 +1651,4 @@ const Symbol = @import("Symbol.zig"); |
| 1657 | 1651 | const StringTable = @import("../StringTable.zig"); |
| 1658 | 1652 | const Type = @import("../../type.zig").Type; |
| 1659 | 1653 | const Value = @import("../../Value.zig"); |
| 1660 | const TypedValue = @import("../../TypedValue.zig"); | |
| 1661 | 1654 | const 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 | 3127 | return self.getZigObject().?.updateFunc(self, mod, func_index, air, liveness); |
| 3128 | 3128 | } |
| 3129 | 3129 | |
| 3130 | pub fn lowerUnnamedConst(self: *MachO, typed_value: TypedValue, decl_index: InternPool.DeclIndex) !u32 { | |
| 3131 | return self.getZigObject().?.lowerUnnamedConst(self, typed_value, decl_index); | |
| 3130 | pub fn lowerUnnamedConst(self: *MachO, val: Value, decl_index: InternPool.DeclIndex) !u32 { | |
| 3131 | return self.getZigObject().?.lowerUnnamedConst(self, val, decl_index); | |
| 3132 | 3132 | } |
| 3133 | 3133 | |
| 3134 | 3134 | pub fn updateDecl(self: *MachO, mod: *Module, decl_index: InternPool.DeclIndex) !void { |
| ... | ... | @@ -4689,7 +4689,7 @@ const StubsHelperSection = synthetic.StubsHelperSection; |
| 4689 | 4689 | const Symbol = @import("MachO/Symbol.zig"); |
| 4690 | 4690 | const Thunk = thunks.Thunk; |
| 4691 | 4691 | const TlvPtrSection = synthetic.TlvPtrSection; |
| 4692 | const TypedValue = @import("../TypedValue.zig"); | |
| 4692 | const Value = @import("../Value.zig"); | |
| 4693 | 4693 | const UnwindInfo = @import("MachO/UnwindInfo.zig"); |
| 4694 | 4694 | const WeakBindSection = synthetic.WeakBindSection; |
| 4695 | 4695 | const ZigGotSection = synthetic.ZigGotSection; |
src/link/MachO/ZigObject.zig+8-15| ... | ... | @@ -567,8 +567,6 @@ pub fn lowerAnonDecl( |
| 567 | 567 | return .ok; |
| 568 | 568 | } |
| 569 | 569 | |
| 570 | const val = Value.fromInterned(decl_val); | |
| 571 | const tv = TypedValue{ .ty = ty, .val = val }; | |
| 572 | 570 | var name_buf: [32]u8 = undefined; |
| 573 | 571 | const name = std.fmt.bufPrint(&name_buf, "__anon_{d}", .{ |
| 574 | 572 | @intFromEnum(decl_val), |
| ... | ... | @@ -576,7 +574,7 @@ pub fn lowerAnonDecl( |
| 576 | 574 | const res = self.lowerConst( |
| 577 | 575 | macho_file, |
| 578 | 576 | name, |
| 579 | tv, | |
| 577 | Value.fromInterned(decl_val), | |
| 580 | 578 | decl_alignment, |
| 581 | 579 | macho_file.zig_const_sect_index.?, |
| 582 | 580 | src_loc, |
| ... | ... | @@ -738,11 +736,7 @@ pub fn updateDecl( |
| 738 | 736 | |
| 739 | 737 | const decl_val = if (decl.val.getVariable(mod)) |variable| Value.fromInterned(variable.init) else decl.val; |
| 740 | 738 | const dio: codegen.DebugInfoOutput = if (decl_state) |*ds| .{ .dwarf = ds } else .none; |
| 741 | const res = | |
| 742 | try codegen.generateSymbol(&macho_file.base, decl.srcLoc(mod), .{ | |
| 743 | .ty = decl.ty, | |
| 744 | .val = decl_val, | |
| 745 | }, &code_buffer, dio, .{ | |
| 739 | const res = try codegen.generateSymbol(&macho_file.base, decl.srcLoc(mod), decl_val, &code_buffer, dio, .{ | |
| 746 | 740 | .parent_atom_index = sym_index, |
| 747 | 741 | }); |
| 748 | 742 | |
| ... | ... | @@ -1021,7 +1015,7 @@ fn getDeclOutputSection( |
| 1021 | 1015 | _ = self; |
| 1022 | 1016 | const mod = macho_file.base.comp.module.?; |
| 1023 | 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 | 1019 | .Fn => macho_file.zig_text_sect_index.?, |
| 1026 | 1020 | else => blk: { |
| 1027 | 1021 | if (decl.getOwnedVariable(mod)) |variable| { |
| ... | ... | @@ -1068,7 +1062,7 @@ fn getDeclOutputSection( |
| 1068 | 1062 | pub fn lowerUnnamedConst( |
| 1069 | 1063 | self: *ZigObject, |
| 1070 | 1064 | macho_file: *MachO, |
| 1071 | typed_value: TypedValue, | |
| 1065 | val: Value, | |
| 1072 | 1066 | decl_index: InternPool.DeclIndex, |
| 1073 | 1067 | ) !u32 { |
| 1074 | 1068 | const gpa = macho_file.base.comp.gpa; |
| ... | ... | @@ -1086,8 +1080,8 @@ pub fn lowerUnnamedConst( |
| 1086 | 1080 | const sym_index = switch (try self.lowerConst( |
| 1087 | 1081 | macho_file, |
| 1088 | 1082 | name, |
| 1089 | typed_value, | |
| 1090 | typed_value.ty.abiAlignment(mod), | |
| 1083 | val, | |
| 1084 | val.typeOf(mod).abiAlignment(mod), | |
| 1091 | 1085 | macho_file.zig_const_sect_index.?, |
| 1092 | 1086 | decl.srcLoc(mod), |
| 1093 | 1087 | )) { |
| ... | ... | @@ -1113,7 +1107,7 @@ fn lowerConst( |
| 1113 | 1107 | self: *ZigObject, |
| 1114 | 1108 | macho_file: *MachO, |
| 1115 | 1109 | name: []const u8, |
| 1116 | tv: TypedValue, | |
| 1110 | val: Value, | |
| 1117 | 1111 | required_alignment: Atom.Alignment, |
| 1118 | 1112 | output_section_index: u8, |
| 1119 | 1113 | src_loc: Module.SrcLoc, |
| ... | ... | @@ -1125,7 +1119,7 @@ fn lowerConst( |
| 1125 | 1119 | |
| 1126 | 1120 | const sym_index = try self.addAtom(macho_file); |
| 1127 | 1121 | |
| 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 | 1123 | .none = {}, |
| 1130 | 1124 | }, .{ |
| 1131 | 1125 | .parent_atom_index = sym_index, |
| ... | ... | @@ -1580,5 +1574,4 @@ const Symbol = @import("Symbol.zig"); |
| 1580 | 1574 | const StringTable = @import("../StringTable.zig"); |
| 1581 | 1575 | const Type = @import("../../type.zig").Type; |
| 1582 | 1576 | const Value = @import("../../Value.zig"); |
| 1583 | const TypedValue = @import("../../TypedValue.zig"); | |
| 1584 | 1577 | const ZigObject = @This(); |
src/link/Plan9.zig+6-13| ... | ... | @@ -15,7 +15,6 @@ const Air = @import("../Air.zig"); |
| 15 | 15 | const Liveness = @import("../Liveness.zig"); |
| 16 | 16 | const Type = @import("../type.zig").Type; |
| 17 | 17 | const Value = @import("../Value.zig"); |
| 18 | const TypedValue = @import("../TypedValue.zig"); | |
| 19 | 18 | |
| 20 | 19 | const std = @import("std"); |
| 21 | 20 | const builtin = @import("builtin"); |
| ... | ... | @@ -177,7 +176,7 @@ pub const Atom = struct { |
| 177 | 176 | return if (self.code_ptr) |p| p[0..self.other.code_len] else blk: { |
| 178 | 177 | const decl_index = self.other.decl_index; |
| 179 | 178 | const decl = mod.declPtr(decl_index); |
| 180 | if (decl.ty.zigTypeTag(mod) == .Fn) { | |
| 179 | if (decl.typeOf(mod).zigTypeTag(mod) == .Fn) { | |
| 181 | 180 | const table = plan9.fn_decl_table.get(decl.getFileScope(mod)).?.functions; |
| 182 | 181 | const output = table.get(decl_index).?; |
| 183 | 182 | break :blk output.code; |
| ... | ... | @@ -463,7 +462,7 @@ pub fn updateFunc(self: *Plan9, mod: *Module, func_index: InternPool.Index, air: |
| 463 | 462 | return self.updateFinish(decl_index); |
| 464 | 463 | } |
| 465 | 464 | |
| 466 | pub fn lowerUnnamedConst(self: *Plan9, tv: TypedValue, decl_index: InternPool.DeclIndex) !u32 { | |
| 465 | pub fn lowerUnnamedConst(self: *Plan9, val: Value, decl_index: InternPool.DeclIndex) !u32 { | |
| 467 | 466 | const gpa = self.base.comp.gpa; |
| 468 | 467 | _ = try self.seeDecl(decl_index); |
| 469 | 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 | 499 | }; |
| 501 | 500 | self.syms.items[info.sym_index.?] = sym; |
| 502 | 501 | |
| 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 | 503 | .none = {}, |
| 505 | 504 | }, .{ |
| 506 | 505 | .parent_atom_index = new_atom_idx, |
| ... | ... | @@ -539,10 +538,7 @@ pub fn updateDecl(self: *Plan9, mod: *Module, decl_index: InternPool.DeclIndex) |
| 539 | 538 | defer code_buffer.deinit(); |
| 540 | 539 | const decl_val = if (decl.val.getVariable(mod)) |variable| Value.fromInterned(variable.init) else decl.val; |
| 541 | 540 | // 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), .{ | |
| 543 | .ty = decl.ty, | |
| 544 | .val = decl_val, | |
| 545 | }, &code_buffer, .{ .none = {} }, .{ | |
| 541 | const res = try codegen.generateSymbol(&self.base, decl.srcLoc(mod), decl_val, &code_buffer, .{ .none = {} }, .{ | |
| 546 | 542 | .parent_atom_index = @as(Atom.Index, @intCast(atom_idx)), |
| 547 | 543 | }); |
| 548 | 544 | const code = switch (res) { |
| ... | ... | @@ -566,7 +562,7 @@ fn updateFinish(self: *Plan9, decl_index: InternPool.DeclIndex) !void { |
| 566 | 562 | const gpa = self.base.comp.gpa; |
| 567 | 563 | const mod = self.base.comp.module.?; |
| 568 | 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 | 566 | const sym_t: aout.Sym.Type = if (is_fn) .t else .d; |
| 571 | 567 | |
| 572 | 568 | const atom = self.getAtomPtr(self.decls.get(decl_index).?.index); |
| ... | ... | @@ -1545,11 +1541,8 @@ pub fn lowerAnonDecl( |
| 1545 | 1541 | // ... |
| 1546 | 1542 | const gpa = self.base.comp.gpa; |
| 1547 | 1543 | const gop = try self.anon_decls.getOrPut(gpa, decl_val); |
| 1548 | const mod = self.base.comp.module.?; | |
| 1549 | 1544 | if (!gop.found_existing) { |
| 1550 | const ty = Type.fromInterned(mod.intern_pool.typeOf(decl_val)); | |
| 1551 | 1545 | const val = Value.fromInterned(decl_val); |
| 1552 | const tv = TypedValue{ .ty = ty, .val = val }; | |
| 1553 | 1546 | const name = try std.fmt.allocPrint(gpa, "__anon_{d}", .{@intFromEnum(decl_val)}); |
| 1554 | 1547 | |
| 1555 | 1548 | const index = try self.createAtom(); |
| ... | ... | @@ -1557,7 +1550,7 @@ pub fn lowerAnonDecl( |
| 1557 | 1550 | gop.value_ptr.* = index; |
| 1558 | 1551 | // we need to free name latex |
| 1559 | 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 | 1554 | const code = switch (res) { |
| 1562 | 1555 | .ok => code_buffer.items, |
| 1563 | 1556 | .fail => |em| return .{ .fail = em }, |
src/link/SpirV.zig+1-1| ... | ... | @@ -163,7 +163,7 @@ pub fn updateExports( |
| 163 | 163 | if (decl.val.isFuncBody(mod)) { |
| 164 | 164 | const target = mod.getTarget(); |
| 165 | 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 | 167 | .Vertex => spec.ExecutionModel.Vertex, |
| 168 | 168 | .Fragment => spec.ExecutionModel.Fragment, |
| 169 | 169 | .Kernel => spec.ExecutionModel.Kernel, |
src/link/Wasm.zig+3-3| ... | ... | @@ -32,7 +32,7 @@ const Module = @import("../Module.zig"); |
| 32 | 32 | const Object = @import("Wasm/Object.zig"); |
| 33 | 33 | const Symbol = @import("Wasm/Symbol.zig"); |
| 34 | 34 | const Type = @import("../type.zig").Type; |
| 35 | const TypedValue = @import("../TypedValue.zig"); | |
| 35 | const Value = @import("../Value.zig"); | |
| 36 | 36 | const ZigObject = @import("Wasm/ZigObject.zig"); |
| 37 | 37 | |
| 38 | 38 | pub const Atom = @import("Wasm/Atom.zig"); |
| ... | ... | @@ -1504,8 +1504,8 @@ fn getFunctionSignature(wasm: *const Wasm, loc: SymbolLoc) std.wasm.Type { |
| 1504 | 1504 | /// Lowers a constant typed value to a local symbol and atom. |
| 1505 | 1505 | /// Returns the symbol index of the local |
| 1506 | 1506 | /// The given `decl` is the parent decl whom owns the constant. |
| 1507 | pub fn lowerUnnamedConst(wasm: *Wasm, tv: TypedValue, decl_index: InternPool.DeclIndex) !u32 { | |
| 1508 | return wasm.zigObjectPtr().?.lowerUnnamedConst(wasm, tv, decl_index); | |
| 1507 | pub fn lowerUnnamedConst(wasm: *Wasm, val: Value, decl_index: InternPool.DeclIndex) !u32 { | |
| 1508 | return wasm.zigObjectPtr().?.lowerUnnamedConst(wasm, val, decl_index); | |
| 1509 | 1509 | } |
| 1510 | 1510 | |
| 1511 | 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 | 270 | const res = try codegen.generateSymbol( |
| 271 | 271 | &wasm_file.base, |
| 272 | 272 | decl.srcLoc(mod), |
| 273 | .{ .ty = decl.ty, .val = val }, | |
| 273 | val, | |
| 274 | 274 | &code_writer, |
| 275 | 275 | .none, |
| 276 | 276 | .{ .parent_atom_index = @intFromEnum(atom.sym_index) }, |
| ... | ... | @@ -346,7 +346,7 @@ fn finishUpdateDecl( |
| 346 | 346 | try atom.code.appendSlice(gpa, code); |
| 347 | 347 | atom.size = @intCast(code.len); |
| 348 | 348 | |
| 349 | switch (decl.ty.zigTypeTag(mod)) { | |
| 349 | switch (decl.typeOf(mod).zigTypeTag(mod)) { | |
| 350 | 350 | .Fn => { |
| 351 | 351 | sym.index = try zig_object.appendFunction(gpa, .{ .type_index = zig_object.atom_types.get(atom_index).? }); |
| 352 | 352 | sym.tag = .function; |
| ... | ... | @@ -444,15 +444,12 @@ pub fn lowerAnonDecl( |
| 444 | 444 | const gpa = wasm_file.base.comp.gpa; |
| 445 | 445 | const gop = try zig_object.anon_decls.getOrPut(gpa, decl_val); |
| 446 | 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 | 447 | var name_buf: [32]u8 = undefined; |
| 451 | 448 | const name = std.fmt.bufPrint(&name_buf, "__anon_{d}", .{ |
| 452 | 449 | @intFromEnum(decl_val), |
| 453 | 450 | }) catch unreachable; |
| 454 | 451 | |
| 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 | 453 | .ok => |atom_index| zig_object.anon_decls.values()[gop.index] = atom_index, |
| 457 | 454 | .fail => |em| return .{ .fail = em }, |
| 458 | 455 | } |
| ... | ... | @@ -472,10 +469,10 @@ pub fn lowerAnonDecl( |
| 472 | 469 | /// Lowers a constant typed value to a local symbol and atom. |
| 473 | 470 | /// Returns the symbol index of the local |
| 474 | 471 | /// The given `decl` is the parent decl whom owns the constant. |
| 475 | pub fn lowerUnnamedConst(zig_object: *ZigObject, wasm_file: *Wasm, tv: TypedValue, decl_index: InternPool.DeclIndex) !u32 { | |
| 472 | pub fn lowerUnnamedConst(zig_object: *ZigObject, wasm_file: *Wasm, val: Value, decl_index: InternPool.DeclIndex) !u32 { | |
| 476 | 473 | const gpa = wasm_file.base.comp.gpa; |
| 477 | 474 | const mod = wasm_file.base.comp.module.?; |
| 478 | std.debug.assert(tv.ty.zigTypeTag(mod) != .Fn); // cannot create local symbols for functions | |
| 475 | std.debug.assert(val.typeOf(mod).zigTypeTag(mod) != .Fn); // cannot create local symbols for functions | |
| 479 | 476 | const decl = mod.declPtr(decl_index); |
| 480 | 477 | |
| 481 | 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 | 484 | }); |
| 488 | 485 | defer gpa.free(name); |
| 489 | 486 | |
| 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 | 488 | .ok => |atom_index| { |
| 492 | 489 | try wasm_file.getAtomPtr(parent_atom_index).locals.append(gpa, atom_index); |
| 493 | 490 | return @intFromEnum(wasm_file.getAtom(atom_index).sym_index); |
| ... | ... | @@ -505,10 +502,12 @@ const LowerConstResult = union(enum) { |
| 505 | 502 | fail: *Module.ErrorMsg, |
| 506 | 503 | }; |
| 507 | 504 | |
| 508 | fn lowerConst(zig_object: *ZigObject, wasm_file: *Wasm, name: []const u8, tv: TypedValue, src_loc: Module.SrcLoc) !LowerConstResult { | |
| 505 | fn lowerConst(zig_object: *ZigObject, wasm_file: *Wasm, name: []const u8, val: Value, src_loc: Module.SrcLoc) !LowerConstResult { | |
| 509 | 506 | const gpa = wasm_file.base.comp.gpa; |
| 510 | 507 | const mod = wasm_file.base.comp.module.?; |
| 511 | 508 | |
| 509 | const ty = val.typeOf(mod); | |
| 510 | ||
| 512 | 511 | // Create and initialize a new local symbol and atom |
| 513 | 512 | const sym_index = try zig_object.allocateSymbol(gpa); |
| 514 | 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 | 516 | |
| 518 | 517 | const code = code: { |
| 519 | 518 | const atom = wasm_file.getAtomPtr(atom_index); |
| 520 | atom.alignment = tv.ty.abiAlignment(mod); | |
| 519 | atom.alignment = ty.abiAlignment(mod); | |
| 521 | 520 | const segment_name = try std.mem.concat(gpa, u8, &.{ ".rodata.", name }); |
| 522 | 521 | errdefer gpa.free(segment_name); |
| 523 | 522 | zig_object.symbol(sym_index).* = .{ |
| ... | ... | @@ -527,7 +526,7 @@ fn lowerConst(zig_object: *ZigObject, wasm_file: *Wasm, name: []const u8, tv: Ty |
| 527 | 526 | .index = try zig_object.createDataSegment( |
| 528 | 527 | gpa, |
| 529 | 528 | segment_name, |
| 530 | tv.ty.abiAlignment(mod), | |
| 529 | ty.abiAlignment(mod), | |
| 531 | 530 | ), |
| 532 | 531 | .virtual_address = undefined, |
| 533 | 532 | }; |
| ... | ... | @@ -535,7 +534,7 @@ fn lowerConst(zig_object: *ZigObject, wasm_file: *Wasm, name: []const u8, tv: Ty |
| 535 | 534 | const result = try codegen.generateSymbol( |
| 536 | 535 | &wasm_file.base, |
| 537 | 536 | src_loc, |
| 538 | tv, | |
| 537 | val, | |
| 539 | 538 | &value_bytes, |
| 540 | 539 | .none, |
| 541 | 540 | .{ |
| ... | ... | @@ -764,7 +763,7 @@ pub fn getDeclVAddr( |
| 764 | 763 | const atom_index = wasm_file.symbol_atom.get(.{ .file = zig_object.index, .index = @enumFromInt(reloc_info.parent_atom_index) }).?; |
| 765 | 764 | const atom = wasm_file.getAtomPtr(atom_index); |
| 766 | 765 | const is_wasm32 = target.cpu.arch == .wasm32; |
| 767 | if (decl.ty.zigTypeTag(mod) == .Fn) { | |
| 766 | if (decl.typeOf(mod).zigTypeTag(mod) == .Fn) { | |
| 768 | 767 | std.debug.assert(reloc_info.addend == 0); // addend not allowed for function relocations |
| 769 | 768 | try atom.relocs.append(gpa, .{ |
| 770 | 769 | .index = target_symbol_index, |
| ... | ... | @@ -964,7 +963,7 @@ pub fn freeDecl(zig_object: *ZigObject, wasm_file: *Wasm, decl_index: InternPool |
| 964 | 963 | if (sym.isGlobal()) { |
| 965 | 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 | 967 | .Fn => { |
| 969 | 968 | zig_object.functions_free_list.append(gpa, sym.index) catch {}; |
| 970 | 969 | std.debug.assert(zig_object.atom_types.remove(atom_index)); |
| ... | ... | @@ -1242,7 +1241,6 @@ const Module = @import("../../Module.zig"); |
| 1242 | 1241 | const StringTable = @import("../StringTable.zig"); |
| 1243 | 1242 | const Symbol = @import("Symbol.zig"); |
| 1244 | 1243 | const Type = @import("../../type.zig").Type; |
| 1245 | const TypedValue = @import("../../TypedValue.zig"); | |
| 1246 | 1244 | const Value = @import("../../Value.zig"); |
| 1247 | 1245 | const Wasm = @import("../Wasm.zig"); |
| 1248 | 1246 | const ZigObject = @This(); |
src/mutable_value.zig created+508| ... | ... | @@ -0,0 +1,508 @@ |
| 1 | const std = @import("std"); | |
| 2 | const assert = std.debug.assert; | |
| 3 | const Allocator = std.mem.Allocator; | |
| 4 | const Zcu = @import("Module.zig"); | |
| 5 | const InternPool = @import("InternPool.zig"); | |
| 6 | const Type = @import("type.zig").Type; | |
| 7 | const 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. | |
| 12 | pub 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 | 951 | const ty = Type.fromInterned(mod.intern_pool.indexToKey(ip_index).typeOf()); |
| 952 | 952 | try s.print("<{}, {}>", .{ |
| 953 | 953 | ty.fmt(mod), |
| 954 | Value.fromInterned(ip_index).fmtValue(ty, mod), | |
| 954 | Value.fromInterned(ip_index).fmtValue(mod), | |
| 955 | 955 | }); |
| 956 | 956 | } else { |
| 957 | 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 | ||
| 4 | const std = @import("std"); | |
| 5 | const Type = @import("type.zig").Type; | |
| 6 | const Value = @import("Value.zig"); | |
| 7 | const Zcu = @import("Module.zig"); | |
| 8 | const Module = Zcu; | |
| 9 | const Sema = @import("Sema.zig"); | |
| 10 | const InternPool = @import("InternPool.zig"); | |
| 11 | const Allocator = std.mem.Allocator; | |
| 12 | const Target = std.Target; | |
| 13 | ||
| 14 | const max_aggregate_items = 100; | |
| 15 | const max_string_len = 256; | |
| 16 | ||
| 17 | const FormatContext = struct { | |
| 18 | val: Value, | |
| 19 | mod: *Module, | |
| 20 | }; | |
| 21 | ||
| 22 | pub 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 | ||
| 38 | pub 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 | ||
| 176 | fn 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 | ||
| 251 | fn 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 | const Zcu = Module; |
| 8 | 8 | const log = std.log.scoped(.Type); |
| 9 | 9 | const target_util = @import("target.zig"); |
| 10 | const TypedValue = @import("TypedValue.zig"); | |
| 11 | 10 | const Sema = @import("Sema.zig"); |
| 12 | 11 | const InternPool = @import("InternPool.zig"); |
| 13 | 12 | const Alignment = InternPool.Alignment; |
| ... | ... | @@ -188,8 +187,8 @@ pub const Type = struct { |
| 188 | 187 | |
| 189 | 188 | if (info.sentinel != .none) switch (info.flags.size) { |
| 190 | 189 | .One, .C => unreachable, |
| 191 | .Many => try writer.print("[*:{}]", .{Value.fromInterned(info.sentinel).fmtValue(Type.fromInterned(info.child), mod)}), | |
| 192 | .Slice => try writer.print("[:{}]", .{Value.fromInterned(info.sentinel).fmtValue(Type.fromInterned(info.child), mod)}), | |
| 190 | .Many => try writer.print("[*:{}]", .{Value.fromInterned(info.sentinel).fmtValue(mod)}), | |
| 191 | .Slice => try writer.print("[:{}]", .{Value.fromInterned(info.sentinel).fmtValue(mod)}), | |
| 193 | 192 | } else switch (info.flags.size) { |
| 194 | 193 | .One => try writer.writeAll("*"), |
| 195 | 194 | .Many => try writer.writeAll("[*]"), |
| ... | ... | @@ -235,7 +234,7 @@ pub const Type = struct { |
| 235 | 234 | } else { |
| 236 | 235 | try writer.print("[{d}:{}]", .{ |
| 237 | 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 | 239 | try print(Type.fromInterned(array_type.child), writer, mod); |
| 241 | 240 | } |
| ... | ... | @@ -353,7 +352,7 @@ pub const Type = struct { |
| 353 | 352 | try print(Type.fromInterned(field_ty), writer, mod); |
| 354 | 353 | |
| 355 | 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 | 358 | try writer.writeAll("}"); |
| ... | ... | @@ -2481,7 +2480,7 @@ pub const Type = struct { |
| 2481 | 2480 | } |
| 2482 | 2481 | const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[i]); |
| 2483 | 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 | 2484 | } else return null; |
| 2486 | 2485 | } |
| 2487 | 2486 |
test/behavior/basic.zig-25| ... | ... | @@ -693,31 +693,6 @@ test "string concatenation" { |
| 693 | 693 | try expect(b[len] == 0); |
| 694 | 694 | } |
| 695 | 695 | |
| 696 | fn manyptrConcat(comptime s: [*:0]const u8) [*:0]const u8 { | |
| 697 | return "very " ++ s; | |
| 698 | } | |
| 699 | ||
| 700 | test "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 | ||
| 721 | 696 | test "result location is optional inside error union" { |
| 722 | 697 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 723 | 698 | 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 | 21 | // |
| 22 | 22 | // Compile Log Output: |
| 23 | 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 | 25 | // @as(*const [3:0]u8, "end") |
| 26 | 26 | // @as(comptime_int, 4) |
| 27 | 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 | 9 | // :2:5: error: found compile log statement |
| 10 | 10 | // |
| 11 | 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 | 14 | // backend=stage2 |
| 15 | 15 | // target=native |
| 16 | 16 | // |
| 17 | // :1:13: error: use of undefined value here causes undefined behavior | |
| 17 | // :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 | 9 | // backend=stage2 |
| 10 | 10 | // target=native |
| 11 | 11 | // |
| 12 | // :1:13: error: use of undefined value here causes undefined behavior | |
| 12 | // :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 | 28 | // backend=stage2 |
| 29 | 29 | // target=native |
| 30 | 30 | // |
| 31 | // :2:9: error: use of undefined value here causes undefined behavior | |
| 32 | // :5:9: error: use of undefined value here causes undefined behavior | |
| 33 | // :17:9: error: use of undefined value here causes undefined behavior | |
| 31 | // :2:16: error: use of undefined value here causes undefined behavior | |
| 32 | // :5:16: error: use of undefined value here causes undefined behavior | |
| 33 | // :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 | 31 | // :20:5: error: found compile log statement |
| 32 | 32 | // |
| 33 | 33 | // Compile Log Output: |
| 34 | // @as([]i32, .{ (reinterpreted data) }) | |
| 35 | // @as([]i32, .{ (reinterpreted data) }) | |
| 34 | // @as([]i32, &(comptime alloc).buf[0..2]) | |
| 35 | // @as([]i32, &(comptime alloc).buf[0..2]) |