| author | |
| committer | |
| log | fc2924080694d68945308d394751a2ec4841b3c0 |
| tree | c4b372662b0253de33483225d17a8a79c735ada5 |
| parent | 531cd177e89c1edfcd2e52f74f220eb186a25f78 |
| parent | 153e7d6235a7d74d0c02d51f84edc5c06ab7469d |
| signature |
compiler: split `Decl` into `Nav` and `Cau`49 files changed, 6455 insertions(+), 7288 deletions(-)
src/Compilation.zig+76-151| ... | ... | @@ -354,28 +354,25 @@ pub const RcIncludes = enum { |
| 354 | 354 | |
| 355 | 355 | const Job = union(enum) { |
| 356 | 356 | /// Write the constant value for a Decl to the output file. |
| 357 | codegen_decl: InternPool.DeclIndex, | |
| 357 | codegen_nav: InternPool.Nav.Index, | |
| 358 | 358 | /// Write the machine code for a function to the output file. |
| 359 | /// This will either be a non-generic `func_decl` or a `func_instance`. | |
| 360 | 359 | codegen_func: struct { |
| 360 | /// This will either be a non-generic `func_decl` or a `func_instance`. | |
| 361 | 361 | func: InternPool.Index, |
| 362 | 362 | /// This `Air` is owned by the `Job` and allocated with `gpa`. |
| 363 | 363 | /// It must be deinited when the job is processed. |
| 364 | 364 | air: Air, |
| 365 | 365 | }, |
| 366 | /// Render the .h file snippet for the Decl. | |
| 367 | emit_h_decl: InternPool.DeclIndex, | |
| 368 | /// The Decl needs to be analyzed and possibly export itself. | |
| 369 | /// It may have already be analyzed, or it may have been determined | |
| 370 | /// to be outdated; in this case perform semantic analysis again. | |
| 371 | analyze_decl: InternPool.DeclIndex, | |
| 366 | /// The `Cau` must be semantically analyzed (and possibly export itself). | |
| 367 | /// This may be its first time being analyzed, or it may be outdated. | |
| 368 | analyze_cau: InternPool.Cau.Index, | |
| 372 | 369 | /// Analyze the body of a runtime function. |
| 373 | 370 | /// After analysis, a `codegen_func` job will be queued. |
| 374 | 371 | /// These must be separate jobs to ensure any needed type resolution occurs *before* codegen. |
| 375 | 372 | analyze_func: InternPool.Index, |
| 376 | 373 | /// The source file containing the Decl has been updated, and so the |
| 377 | 374 | /// Decl may need its line number information updated in the debug info. |
| 378 | update_line_number: InternPool.DeclIndex, | |
| 375 | update_line_number: void, // TODO | |
| 379 | 376 | /// The main source file for the module needs to be analyzed. |
| 380 | 377 | analyze_mod: *Package.Module, |
| 381 | 378 | /// Fully resolve the given `struct` or `union` type. |
| ... | ... | @@ -419,7 +416,7 @@ const Job = union(enum) { |
| 419 | 416 | }; |
| 420 | 417 | |
| 421 | 418 | const CodegenJob = union(enum) { |
| 422 | decl: InternPool.DeclIndex, | |
| 419 | nav: InternPool.Nav.Index, | |
| 423 | 420 | func: struct { |
| 424 | 421 | func: InternPool.Index, |
| 425 | 422 | /// This `Air` is owned by the `Job` and allocated with `gpa`. |
| ... | ... | @@ -1445,12 +1442,6 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil |
| 1445 | 1442 | .path = try options.global_cache_directory.join(arena, &[_][]const u8{zir_sub_dir}), |
| 1446 | 1443 | }; |
| 1447 | 1444 | |
| 1448 | const emit_h: ?*Zcu.GlobalEmitH = if (options.emit_h) |loc| eh: { | |
| 1449 | const eh = try arena.create(Zcu.GlobalEmitH); | |
| 1450 | eh.* = .{ .loc = loc }; | |
| 1451 | break :eh eh; | |
| 1452 | } else null; | |
| 1453 | ||
| 1454 | 1445 | const std_mod = options.std_mod orelse try Package.Module.create(arena, .{ |
| 1455 | 1446 | .global_cache_directory = options.global_cache_directory, |
| 1456 | 1447 | .paths = .{ |
| ... | ... | @@ -1478,7 +1469,6 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil |
| 1478 | 1469 | .std_mod = std_mod, |
| 1479 | 1470 | .global_zir_cache = global_zir_cache, |
| 1480 | 1471 | .local_zir_cache = local_zir_cache, |
| 1481 | .emit_h = emit_h, | |
| 1482 | 1472 | .error_limit = error_limit, |
| 1483 | 1473 | .llvm_object = null, |
| 1484 | 1474 | }; |
| ... | ... | @@ -2581,7 +2571,7 @@ fn addNonIncrementalStuffToCacheManifest( |
| 2581 | 2571 | man.hash.addOptionalBytes(comp.test_name_prefix); |
| 2582 | 2572 | man.hash.add(comp.skip_linker_dependencies); |
| 2583 | 2573 | man.hash.add(comp.formatted_panics); |
| 2584 | man.hash.add(mod.emit_h != null); | |
| 2574 | //man.hash.add(mod.emit_h != null); | |
| 2585 | 2575 | man.hash.add(mod.error_limit); |
| 2586 | 2576 | } else { |
| 2587 | 2577 | cache_helpers.addModule(&man.hash, comp.root_mod); |
| ... | ... | @@ -2930,7 +2920,7 @@ const Header = extern struct { |
| 2930 | 2920 | intern_pool: extern struct { |
| 2931 | 2921 | thread_count: u32, |
| 2932 | 2922 | src_hash_deps_len: u32, |
| 2933 | decl_val_deps_len: u32, | |
| 2923 | nav_val_deps_len: u32, | |
| 2934 | 2924 | namespace_deps_len: u32, |
| 2935 | 2925 | namespace_name_deps_len: u32, |
| 2936 | 2926 | first_dependency_len: u32, |
| ... | ... | @@ -2972,7 +2962,7 @@ pub fn saveState(comp: *Compilation) !void { |
| 2972 | 2962 | .intern_pool = .{ |
| 2973 | 2963 | .thread_count = @intCast(ip.locals.len), |
| 2974 | 2964 | .src_hash_deps_len = @intCast(ip.src_hash_deps.count()), |
| 2975 | .decl_val_deps_len = @intCast(ip.decl_val_deps.count()), | |
| 2965 | .nav_val_deps_len = @intCast(ip.nav_val_deps.count()), | |
| 2976 | 2966 | .namespace_deps_len = @intCast(ip.namespace_deps.count()), |
| 2977 | 2967 | .namespace_name_deps_len = @intCast(ip.namespace_name_deps.count()), |
| 2978 | 2968 | .first_dependency_len = @intCast(ip.first_dependency.count()), |
| ... | ... | @@ -2999,8 +2989,8 @@ pub fn saveState(comp: *Compilation) !void { |
| 2999 | 2989 | |
| 3000 | 2990 | addBuf(&bufs, mem.sliceAsBytes(ip.src_hash_deps.keys())); |
| 3001 | 2991 | addBuf(&bufs, mem.sliceAsBytes(ip.src_hash_deps.values())); |
| 3002 | addBuf(&bufs, mem.sliceAsBytes(ip.decl_val_deps.keys())); | |
| 3003 | addBuf(&bufs, mem.sliceAsBytes(ip.decl_val_deps.values())); | |
| 2992 | addBuf(&bufs, mem.sliceAsBytes(ip.nav_val_deps.keys())); | |
| 2993 | addBuf(&bufs, mem.sliceAsBytes(ip.nav_val_deps.values())); | |
| 3004 | 2994 | addBuf(&bufs, mem.sliceAsBytes(ip.namespace_deps.keys())); |
| 3005 | 2995 | addBuf(&bufs, mem.sliceAsBytes(ip.namespace_deps.values())); |
| 3006 | 2996 | addBuf(&bufs, mem.sliceAsBytes(ip.namespace_name_deps.keys())); |
| ... | ... | @@ -3019,7 +3009,7 @@ pub fn saveState(comp: *Compilation) !void { |
| 3019 | 3009 | addBuf(&bufs, local.shared.strings.view().items(.@"0")[0..pt_header.intern_pool.string_bytes_len]); |
| 3020 | 3010 | addBuf(&bufs, mem.sliceAsBytes(local.shared.tracked_insts.view().items(.@"0")[0..pt_header.intern_pool.tracked_insts_len])); |
| 3021 | 3011 | addBuf(&bufs, mem.sliceAsBytes(local.shared.files.view().items(.bin_digest)[0..pt_header.intern_pool.files_len])); |
| 3022 | addBuf(&bufs, mem.sliceAsBytes(local.shared.files.view().items(.root_decl)[0..pt_header.intern_pool.files_len])); | |
| 3012 | addBuf(&bufs, mem.sliceAsBytes(local.shared.files.view().items(.root_type)[0..pt_header.intern_pool.files_len])); | |
| 3023 | 3013 | } |
| 3024 | 3014 | |
| 3025 | 3015 | //// TODO: compilation errors |
| ... | ... | @@ -3065,6 +3055,8 @@ pub fn totalErrorCount(comp: *Compilation) u32 { |
| 3065 | 3055 | } |
| 3066 | 3056 | |
| 3067 | 3057 | if (comp.module) |zcu| { |
| 3058 | const ip = &zcu.intern_pool; | |
| 3059 | ||
| 3068 | 3060 | total += zcu.failed_exports.count(); |
| 3069 | 3061 | total += zcu.failed_embed_files.count(); |
| 3070 | 3062 | |
| ... | ... | @@ -3084,25 +3076,18 @@ pub fn totalErrorCount(comp: *Compilation) u32 { |
| 3084 | 3076 | // When a parse error is introduced, we keep all the semantic analysis for |
| 3085 | 3077 | // the previous parse success, including compile errors, but we cannot |
| 3086 | 3078 | // emit them until the file succeeds parsing. |
| 3087 | for (zcu.failed_analysis.keys()) |key| { | |
| 3088 | const decl_index = switch (key.unwrap()) { | |
| 3089 | .decl => |d| d, | |
| 3090 | .func => |ip_index| zcu.funcInfo(ip_index).owner_decl, | |
| 3079 | for (zcu.failed_analysis.keys()) |anal_unit| { | |
| 3080 | const file_index = switch (anal_unit.unwrap()) { | |
| 3081 | .cau => |cau| zcu.namespacePtr(ip.getCau(cau).namespace).file_scope, | |
| 3082 | .func => |ip_index| zcu.funcInfo(ip_index).zir_body_inst.resolveFull(ip).file, | |
| 3091 | 3083 | }; |
| 3092 | if (zcu.declFileScope(decl_index).okToReportErrors()) { | |
| 3084 | if (zcu.fileByIndex(file_index).okToReportErrors()) { | |
| 3093 | 3085 | total += 1; |
| 3094 | if (zcu.cimport_errors.get(key)) |errors| { | |
| 3086 | if (zcu.cimport_errors.get(anal_unit)) |errors| { | |
| 3095 | 3087 | total += errors.errorMessageCount(); |
| 3096 | 3088 | } |
| 3097 | 3089 | } |
| 3098 | 3090 | } |
| 3099 | if (zcu.emit_h) |emit_h| { | |
| 3100 | for (emit_h.failed_decls.keys()) |key| { | |
| 3101 | if (zcu.declFileScope(key).okToReportErrors()) { | |
| 3102 | total += 1; | |
| 3103 | } | |
| 3104 | } | |
| 3105 | } | |
| 3106 | 3091 | |
| 3107 | 3092 | if (zcu.intern_pool.global_error_set.getNamesFromMainThread().len > zcu.error_limit) { |
| 3108 | 3093 | total += 1; |
| ... | ... | @@ -3169,6 +3154,8 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle { |
| 3169 | 3154 | }); |
| 3170 | 3155 | } |
| 3171 | 3156 | if (comp.module) |zcu| { |
| 3157 | const ip = &zcu.intern_pool; | |
| 3158 | ||
| 3172 | 3159 | var all_references = try zcu.resolveReferences(); |
| 3173 | 3160 | defer all_references.deinit(gpa); |
| 3174 | 3161 | |
| ... | ... | @@ -3219,14 +3206,14 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle { |
| 3219 | 3206 | if (err) |e| return e; |
| 3220 | 3207 | } |
| 3221 | 3208 | for (zcu.failed_analysis.keys(), zcu.failed_analysis.values()) |anal_unit, error_msg| { |
| 3222 | const decl_index = switch (anal_unit.unwrap()) { | |
| 3223 | .decl => |d| d, | |
| 3224 | .func => |ip_index| zcu.funcInfo(ip_index).owner_decl, | |
| 3209 | const file_index = switch (anal_unit.unwrap()) { | |
| 3210 | .cau => |cau| zcu.namespacePtr(ip.getCau(cau).namespace).file_scope, | |
| 3211 | .func => |ip_index| zcu.funcInfo(ip_index).zir_body_inst.resolveFull(ip).file, | |
| 3225 | 3212 | }; |
| 3226 | 3213 | |
| 3227 | // Skip errors for Decls within files that had a parse failure. | |
| 3214 | // Skip errors for AnalUnits within files that had a parse failure. | |
| 3228 | 3215 | // We'll try again once parsing succeeds. |
| 3229 | if (!zcu.declFileScope(decl_index).okToReportErrors()) continue; | |
| 3216 | if (!zcu.fileByIndex(file_index).okToReportErrors()) continue; | |
| 3230 | 3217 | |
| 3231 | 3218 | try addModuleErrorMsg(zcu, &bundle, error_msg.*, &all_references); |
| 3232 | 3219 | if (zcu.cimport_errors.get(anal_unit)) |errors| { |
| ... | ... | @@ -3250,15 +3237,6 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle { |
| 3250 | 3237 | } |
| 3251 | 3238 | } |
| 3252 | 3239 | } |
| 3253 | if (zcu.emit_h) |emit_h| { | |
| 3254 | for (emit_h.failed_decls.keys(), emit_h.failed_decls.values()) |decl_index, error_msg| { | |
| 3255 | // Skip errors for Decls within files that had a parse failure. | |
| 3256 | // We'll try again once parsing succeeds. | |
| 3257 | if (zcu.declFileScope(decl_index).okToReportErrors()) { | |
| 3258 | try addModuleErrorMsg(zcu, &bundle, error_msg.*, &all_references); | |
| 3259 | } | |
| 3260 | } | |
| 3261 | } | |
| 3262 | 3240 | for (zcu.failed_exports.values()) |value| { |
| 3263 | 3241 | try addModuleErrorMsg(zcu, &bundle, value.*, &all_references); |
| 3264 | 3242 | } |
| ... | ... | @@ -3437,11 +3415,15 @@ pub fn addModuleErrorMsg( |
| 3437 | 3415 | const loc = std.zig.findLineColumn(source.bytes, span.main); |
| 3438 | 3416 | const rt_file_path = try src.file_scope.fullPath(gpa); |
| 3439 | 3417 | const name = switch (ref.referencer.unwrap()) { |
| 3440 | .decl => |d| mod.declPtr(d).name, | |
| 3441 | .func => |f| mod.funcOwnerDeclPtr(f).name, | |
| 3418 | .cau => |cau| switch (ip.getCau(cau).owner.unwrap()) { | |
| 3419 | .nav => |nav| ip.getNav(nav).name.toSlice(ip), | |
| 3420 | .type => |ty| Type.fromInterned(ty).containerTypeName(ip).toSlice(ip), | |
| 3421 | .none => "comptime", | |
| 3422 | }, | |
| 3423 | .func => |f| ip.getNav(mod.funcInfo(f).owner_nav).name.toSlice(ip), | |
| 3442 | 3424 | }; |
| 3443 | 3425 | try ref_traces.append(gpa, .{ |
| 3444 | .decl_name = try eb.addString(name.toSlice(ip)), | |
| 3426 | .decl_name = try eb.addString(name), | |
| 3445 | 3427 | .src_loc = try eb.addSourceLocation(.{ |
| 3446 | 3428 | .src_path = try eb.addString(rt_file_path), |
| 3447 | 3429 | .span_start = span.start, |
| ... | ... | @@ -3617,10 +3599,10 @@ fn performAllTheWorkInner( |
| 3617 | 3599 | // Pre-load these things from our single-threaded context since they |
| 3618 | 3600 | // will be needed by the worker threads. |
| 3619 | 3601 | const path_digest = zcu.filePathDigest(file_index); |
| 3620 | const root_decl = zcu.fileRootDecl(file_index); | |
| 3602 | const old_root_type = zcu.fileRootType(file_index); | |
| 3621 | 3603 | const file = zcu.fileByIndex(file_index); |
| 3622 | 3604 | comp.thread_pool.spawnWgId(&astgen_wait_group, workerAstGenFile, .{ |
| 3623 | comp, file, file_index, path_digest, root_decl, zir_prog_node, &astgen_wait_group, .root, | |
| 3605 | comp, file, file_index, path_digest, old_root_type, zir_prog_node, &astgen_wait_group, .root, | |
| 3624 | 3606 | }); |
| 3625 | 3607 | } |
| 3626 | 3608 | } |
| ... | ... | @@ -3682,7 +3664,7 @@ fn performAllTheWorkInner( |
| 3682 | 3664 | // which we need to work on, and queue it if so. |
| 3683 | 3665 | if (try zcu.findOutdatedToAnalyze()) |outdated| { |
| 3684 | 3666 | switch (outdated.unwrap()) { |
| 3685 | .decl => |decl| try comp.queueJob(.{ .analyze_decl = decl }), | |
| 3667 | .cau => |cau| try comp.queueJob(.{ .analyze_cau = cau }), | |
| 3686 | 3668 | .func => |func| try comp.queueJob(.{ .analyze_func = func }), |
| 3687 | 3669 | } |
| 3688 | 3670 | continue; |
| ... | ... | @@ -3704,24 +3686,17 @@ pub fn queueJobs(comp: *Compilation, jobs: []const Job) !void { |
| 3704 | 3686 | |
| 3705 | 3687 | fn processOneJob(tid: usize, comp: *Compilation, job: Job, prog_node: std.Progress.Node) JobError!void { |
| 3706 | 3688 | switch (job) { |
| 3707 | .codegen_decl => |decl_index| { | |
| 3708 | const decl = comp.module.?.declPtr(decl_index); | |
| 3709 | ||
| 3710 | switch (decl.analysis) { | |
| 3711 | .unreferenced => unreachable, | |
| 3712 | .in_progress => unreachable, | |
| 3713 | ||
| 3714 | .file_failure, | |
| 3715 | .sema_failure, | |
| 3716 | .codegen_failure, | |
| 3717 | .dependency_failure, | |
| 3718 | => {}, | |
| 3719 | ||
| 3720 | .complete => { | |
| 3721 | assert(decl.has_tv); | |
| 3722 | try comp.queueCodegenJob(tid, .{ .decl = decl_index }); | |
| 3723 | }, | |
| 3689 | .codegen_nav => |nav_index| { | |
| 3690 | const zcu = comp.module.?; | |
| 3691 | const nav = zcu.intern_pool.getNav(nav_index); | |
| 3692 | if (nav.analysis_owner.unwrap()) |cau| { | |
| 3693 | const unit = InternPool.AnalUnit.wrap(.{ .cau = cau }); | |
| 3694 | if (zcu.failed_analysis.contains(unit) or zcu.transitive_failed_analysis.contains(unit)) { | |
| 3695 | return; | |
| 3696 | } | |
| 3724 | 3697 | } |
| 3698 | assert(nav.status == .resolved); | |
| 3699 | try comp.queueCodegenJob(tid, .{ .nav = nav_index }); | |
| 3725 | 3700 | }, |
| 3726 | 3701 | .codegen_func => |func| { |
| 3727 | 3702 | // This call takes ownership of `func.air`. |
| ... | ... | @@ -3740,82 +3715,30 @@ fn processOneJob(tid: usize, comp: *Compilation, job: Job, prog_node: std.Progre |
| 3740 | 3715 | error.AnalysisFail => return, |
| 3741 | 3716 | }; |
| 3742 | 3717 | }, |
| 3743 | .emit_h_decl => |decl_index| { | |
| 3744 | if (true) @panic("regressed compiler feature: emit-h should hook into updateExports, " ++ | |
| 3745 | "not decl analysis, which is too early to know about @export calls"); | |
| 3746 | ||
| 3718 | .analyze_cau => |cau_index| { | |
| 3747 | 3719 | const pt: Zcu.PerThread = .{ .zcu = comp.module.?, .tid = @enumFromInt(tid) }; |
| 3748 | const decl = pt.zcu.declPtr(decl_index); | |
| 3749 | ||
| 3750 | switch (decl.analysis) { | |
| 3751 | .unreferenced => unreachable, | |
| 3752 | .in_progress => unreachable, | |
| 3753 | ||
| 3754 | .file_failure, | |
| 3755 | .sema_failure, | |
| 3756 | .dependency_failure, | |
| 3757 | => return, | |
| 3758 | ||
| 3759 | // emit-h only requires semantic analysis of the Decl to be complete, | |
| 3760 | // it does not depend on machine code generation to succeed. | |
| 3761 | .codegen_failure, .complete => { | |
| 3762 | const named_frame = tracy.namedFrame("emit_h_decl"); | |
| 3763 | defer named_frame.end(); | |
| 3764 | ||
| 3765 | const gpa = comp.gpa; | |
| 3766 | const emit_h = pt.zcu.emit_h.?; | |
| 3767 | _ = try emit_h.decl_table.getOrPut(gpa, decl_index); | |
| 3768 | const decl_emit_h = emit_h.declPtr(decl_index); | |
| 3769 | const fwd_decl = &decl_emit_h.fwd_decl; | |
| 3770 | fwd_decl.shrinkRetainingCapacity(0); | |
| 3771 | var ctypes_arena = std.heap.ArenaAllocator.init(gpa); | |
| 3772 | defer ctypes_arena.deinit(); | |
| 3773 | ||
| 3774 | const file_scope = pt.zcu.namespacePtr(decl.src_namespace).fileScope(pt.zcu); | |
| 3775 | ||
| 3776 | var dg: c_codegen.DeclGen = .{ | |
| 3777 | .gpa = gpa, | |
| 3778 | .pt = pt, | |
| 3779 | .mod = file_scope.mod, | |
| 3780 | .error_msg = null, | |
| 3781 | .pass = .{ .decl = decl_index }, | |
| 3782 | .is_naked_fn = false, | |
| 3783 | .fwd_decl = fwd_decl.toManaged(gpa), | |
| 3784 | .ctype_pool = c_codegen.CType.Pool.empty, | |
| 3785 | .scratch = .{}, | |
| 3786 | .anon_decl_deps = .{}, | |
| 3787 | .aligned_anon_decls = .{}, | |
| 3788 | }; | |
| 3789 | defer { | |
| 3790 | fwd_decl.* = dg.fwd_decl.moveToUnmanaged(); | |
| 3791 | fwd_decl.shrinkAndFree(gpa, fwd_decl.items.len); | |
| 3792 | dg.ctype_pool.deinit(gpa); | |
| 3793 | dg.scratch.deinit(gpa); | |
| 3794 | } | |
| 3795 | try dg.ctype_pool.init(gpa); | |
| 3796 | ||
| 3797 | c_codegen.genHeader(&dg) catch |err| switch (err) { | |
| 3798 | error.AnalysisFail => { | |
| 3799 | try emit_h.failed_decls.put(gpa, decl_index, dg.error_msg.?); | |
| 3800 | return; | |
| 3801 | }, | |
| 3802 | else => |e| return e, | |
| 3803 | }; | |
| 3804 | }, | |
| 3805 | } | |
| 3806 | }, | |
| 3807 | .analyze_decl => |decl_index| { | |
| 3808 | const pt: Zcu.PerThread = .{ .zcu = comp.module.?, .tid = @enumFromInt(tid) }; | |
| 3809 | pt.ensureDeclAnalyzed(decl_index) catch |err| switch (err) { | |
| 3720 | pt.ensureCauAnalyzed(cau_index) catch |err| switch (err) { | |
| 3810 | 3721 | error.OutOfMemory => return error.OutOfMemory, |
| 3811 | 3722 | error.AnalysisFail => return, |
| 3812 | 3723 | }; |
| 3813 | const decl = pt.zcu.declPtr(decl_index); | |
| 3814 | if (decl.kind == .@"test" and comp.config.is_test) { | |
| 3724 | queue_test_analysis: { | |
| 3725 | if (!comp.config.is_test) break :queue_test_analysis; | |
| 3726 | ||
| 3727 | // Check if this is a test function. | |
| 3728 | const ip = &pt.zcu.intern_pool; | |
| 3729 | const cau = ip.getCau(cau_index); | |
| 3730 | const nav_index = switch (cau.owner.unwrap()) { | |
| 3731 | .none, .type => break :queue_test_analysis, | |
| 3732 | .nav => |nav| nav, | |
| 3733 | }; | |
| 3734 | if (!pt.zcu.test_functions.contains(nav_index)) { | |
| 3735 | break :queue_test_analysis; | |
| 3736 | } | |
| 3737 | ||
| 3815 | 3738 | // Tests are always emitted in test binaries. The decl_refs are created by |
| 3816 | 3739 | // Zcu.populateTestFunctions, but this will not queue body analysis, so do |
| 3817 | 3740 | // that now. |
| 3818 | try pt.zcu.ensureFuncBodyAnalysisQueued(decl.val.toIntern()); | |
| 3741 | try pt.zcu.ensureFuncBodyAnalysisQueued(ip.getNav(nav_index).status.resolved.val); | |
| 3819 | 3742 | } |
| 3820 | 3743 | }, |
| 3821 | 3744 | .resolve_type_fully => |ty| { |
| ... | ... | @@ -3832,6 +3755,8 @@ fn processOneJob(tid: usize, comp: *Compilation, job: Job, prog_node: std.Progre |
| 3832 | 3755 | const named_frame = tracy.namedFrame("update_line_number"); |
| 3833 | 3756 | defer named_frame.end(); |
| 3834 | 3757 | |
| 3758 | if (true) @panic("TODO: update_line_number"); | |
| 3759 | ||
| 3835 | 3760 | const gpa = comp.gpa; |
| 3836 | 3761 | const pt: Zcu.PerThread = .{ .zcu = comp.module.?, .tid = @enumFromInt(tid) }; |
| 3837 | 3762 | const decl = pt.zcu.declPtr(decl_index); |
| ... | ... | @@ -4054,12 +3979,12 @@ fn codegenThread(tid: usize, comp: *Compilation) void { |
| 4054 | 3979 | |
| 4055 | 3980 | fn processOneCodegenJob(tid: usize, comp: *Compilation, codegen_job: CodegenJob) JobError!void { |
| 4056 | 3981 | switch (codegen_job) { |
| 4057 | .decl => |decl_index| { | |
| 4058 | const named_frame = tracy.namedFrame("codegen_decl"); | |
| 3982 | .nav => |nav_index| { | |
| 3983 | const named_frame = tracy.namedFrame("codegen_nav"); | |
| 4059 | 3984 | defer named_frame.end(); |
| 4060 | 3985 | |
| 4061 | 3986 | const pt: Zcu.PerThread = .{ .zcu = comp.module.?, .tid = @enumFromInt(tid) }; |
| 4062 | try pt.linkerUpdateDecl(decl_index); | |
| 3987 | try pt.linkerUpdateNav(nav_index); | |
| 4063 | 3988 | }, |
| 4064 | 3989 | .func => |func| { |
| 4065 | 3990 | const named_frame = tracy.namedFrame("codegen_func"); |
| ... | ... | @@ -4366,7 +4291,7 @@ fn workerAstGenFile( |
| 4366 | 4291 | file: *Zcu.File, |
| 4367 | 4292 | file_index: Zcu.File.Index, |
| 4368 | 4293 | path_digest: Cache.BinDigest, |
| 4369 | root_decl: Zcu.Decl.OptionalIndex, | |
| 4294 | old_root_type: InternPool.Index, | |
| 4370 | 4295 | prog_node: std.Progress.Node, |
| 4371 | 4296 | wg: *WaitGroup, |
| 4372 | 4297 | src: Zcu.AstGenSrc, |
| ... | ... | @@ -4375,7 +4300,7 @@ fn workerAstGenFile( |
| 4375 | 4300 | defer child_prog_node.end(); |
| 4376 | 4301 | |
| 4377 | 4302 | const pt: Zcu.PerThread = .{ .zcu = comp.module.?, .tid = @enumFromInt(tid) }; |
| 4378 | pt.astGenFile(file, path_digest, root_decl) catch |err| switch (err) { | |
| 4303 | pt.astGenFile(file, path_digest, old_root_type) catch |err| switch (err) { | |
| 4379 | 4304 | error.AnalysisFail => return, |
| 4380 | 4305 | else => { |
| 4381 | 4306 | file.status = .retryable_failure; |
| ... | ... | @@ -4406,7 +4331,7 @@ fn workerAstGenFile( |
| 4406 | 4331 | // `@import("builtin")` is handled specially. |
| 4407 | 4332 | if (mem.eql(u8, import_path, "builtin")) continue; |
| 4408 | 4333 | |
| 4409 | const import_result, const imported_path_digest, const imported_root_decl = blk: { | |
| 4334 | const import_result, const imported_path_digest, const imported_root_type = blk: { | |
| 4410 | 4335 | comp.mutex.lock(); |
| 4411 | 4336 | defer comp.mutex.unlock(); |
| 4412 | 4337 | |
| ... | ... | @@ -4421,8 +4346,8 @@ fn workerAstGenFile( |
| 4421 | 4346 | comp.appendFileSystemInput(fsi, res.file.mod.root, res.file.sub_file_path) catch continue; |
| 4422 | 4347 | }; |
| 4423 | 4348 | const imported_path_digest = pt.zcu.filePathDigest(res.file_index); |
| 4424 | const imported_root_decl = pt.zcu.fileRootDecl(res.file_index); | |
| 4425 | break :blk .{ res, imported_path_digest, imported_root_decl }; | |
| 4349 | const imported_root_type = pt.zcu.fileRootType(res.file_index); | |
| 4350 | break :blk .{ res, imported_path_digest, imported_root_type }; | |
| 4426 | 4351 | }; |
| 4427 | 4352 | if (import_result.is_new) { |
| 4428 | 4353 | log.debug("AstGen of {s} has import '{s}'; queuing AstGen of {s}", .{ |
| ... | ... | @@ -4433,7 +4358,7 @@ fn workerAstGenFile( |
| 4433 | 4358 | .import_tok = item.data.token, |
| 4434 | 4359 | } }; |
| 4435 | 4360 | comp.thread_pool.spawnWgId(wg, workerAstGenFile, .{ |
| 4436 | comp, import_result.file, import_result.file_index, imported_path_digest, imported_root_decl, prog_node, wg, sub_src, | |
| 4361 | comp, import_result.file, import_result.file_index, imported_path_digest, imported_root_type, prog_node, wg, sub_src, | |
| 4437 | 4362 | }); |
| 4438 | 4363 | } |
| 4439 | 4364 | } |
src/InternPool.zig+964-523| ... | ... | @@ -24,12 +24,14 @@ tid_shift_32: if (single_threaded) u0 else std.math.Log2Int(u32) = if (single_th |
| 24 | 24 | /// These are also invalidated if tracking fails for this instruction. |
| 25 | 25 | /// Value is index into `dep_entries` of the first dependency on this hash. |
| 26 | 26 | src_hash_deps: std.AutoArrayHashMapUnmanaged(TrackedInst.Index, DepEntry.Index) = .{}, |
| 27 | /// Dependencies on the value of a Decl. | |
| 28 | /// Value is index into `dep_entries` of the first dependency on this Decl value. | |
| 29 | decl_val_deps: std.AutoArrayHashMapUnmanaged(DeclIndex, DepEntry.Index) = .{}, | |
| 30 | /// Dependencies on the IES of a runtime function. | |
| 31 | /// Value is index into `dep_entries` of the first dependency on this Decl value. | |
| 32 | func_ies_deps: std.AutoArrayHashMapUnmanaged(Index, DepEntry.Index) = .{}, | |
| 27 | /// Dependencies on the value of a Nav. | |
| 28 | /// Value is index into `dep_entries` of the first dependency on this Nav value. | |
| 29 | nav_val_deps: std.AutoArrayHashMapUnmanaged(Nav.Index, DepEntry.Index) = .{}, | |
| 30 | /// Dependencies on an interned value, either: | |
| 31 | /// * a runtime function (invalidated when its IES changes) | |
| 32 | /// * a container type requiring resolution (invalidated when the type must be recreated at a new index) | |
| 33 | /// Value is index into `dep_entries` of the first dependency on this interned value. | |
| 34 | interned_deps: std.AutoArrayHashMapUnmanaged(Index, DepEntry.Index) = .{}, | |
| 33 | 35 | /// Dependencies on the full set of names in a ZIR namespace. |
| 34 | 36 | /// Key refers to a `struct_decl`, `union_decl`, etc. |
| 35 | 37 | /// Value is index into `dep_entries` of the first dependency on this namespace. |
| ... | ... | @@ -210,25 +212,25 @@ pub fn trackZir( |
| 210 | 212 | } |
| 211 | 213 | |
| 212 | 214 | /// Analysis Unit. Represents a single entity which undergoes semantic analysis. |
| 213 | /// This is either a `Decl` (in future `Cau`) or a runtime function. | |
| 215 | /// This is either a `Cau` or a runtime function. | |
| 214 | 216 | /// The LSB is used as a tag bit. |
| 215 | 217 | /// This is the "source" of an incremental dependency edge. |
| 216 | 218 | pub const AnalUnit = packed struct(u32) { |
| 217 | kind: enum(u1) { decl, func }, | |
| 219 | kind: enum(u1) { cau, func }, | |
| 218 | 220 | index: u31, |
| 219 | 221 | pub const Unwrapped = union(enum) { |
| 220 | decl: DeclIndex, | |
| 222 | cau: Cau.Index, | |
| 221 | 223 | func: InternPool.Index, |
| 222 | 224 | }; |
| 223 | 225 | pub fn unwrap(as: AnalUnit) Unwrapped { |
| 224 | 226 | return switch (as.kind) { |
| 225 | .decl => .{ .decl = @enumFromInt(as.index) }, | |
| 227 | .cau => .{ .cau = @enumFromInt(as.index) }, | |
| 226 | 228 | .func => .{ .func = @enumFromInt(as.index) }, |
| 227 | 229 | }; |
| 228 | 230 | } |
| 229 | 231 | pub fn wrap(raw: Unwrapped) AnalUnit { |
| 230 | 232 | return switch (raw) { |
| 231 | .decl => |decl| .{ .kind = .decl, .index = @intCast(@intFromEnum(decl)) }, | |
| 233 | .cau => |cau| .{ .kind = .cau, .index = @intCast(@intFromEnum(cau)) }, | |
| 232 | 234 | .func => |func| .{ .kind = .func, .index = @intCast(@intFromEnum(func)) }, |
| 233 | 235 | }; |
| 234 | 236 | } |
| ... | ... | @@ -247,10 +249,275 @@ pub const AnalUnit = packed struct(u32) { |
| 247 | 249 | }; |
| 248 | 250 | }; |
| 249 | 251 | |
| 252 | /// Comptime Analysis Unit. This is the "subject" of semantic analysis where the root context is | |
| 253 | /// comptime; every `Sema` is owned by either a `Cau` or a runtime function (see `AnalUnit`). | |
| 254 | /// The state stored here is immutable. | |
| 255 | /// | |
| 256 | /// * Every ZIR `declaration` has a `Cau` (post-instantiation) to analyze the declaration body. | |
| 257 | /// * Every `struct`, `union`, and `enum` has a `Cau` for type resolution. | |
| 258 | /// | |
| 259 | /// The analysis status of a `Cau` is known only from state in `Zcu`. | |
| 260 | /// An entry in `Zcu.failed_analysis` indicates an analysis failure with associated error message. | |
| 261 | /// An entry in `Zcu.transitive_failed_analysis` indicates a transitive analysis failure. | |
| 262 | /// | |
| 263 | /// 12 bytes. | |
| 264 | pub const Cau = struct { | |
| 265 | /// The `declaration`, `struct_decl`, `enum_decl`, or `union_decl` instruction which this `Cau` analyzes. | |
| 266 | zir_index: TrackedInst.Index, | |
| 267 | /// The namespace which this `Cau` should be analyzed within. | |
| 268 | namespace: NamespaceIndex, | |
| 269 | /// This field essentially tells us what to do with the information resulting from | |
| 270 | /// semantic analysis. See `Owner.Unwrapped` for details. | |
| 271 | owner: Owner, | |
| 272 | ||
| 273 | /// See `Owner.Unwrapped` for details. In terms of representation, the `InternPool.Index` | |
| 274 | /// or `Nav.Index` is cast to a `u31` and stored in `index`. As a special case, if | |
| 275 | /// `@as(u32, @bitCast(owner)) == 0xFFFF_FFFF`, then the value is treated as `.none`. | |
| 276 | pub const Owner = packed struct(u32) { | |
| 277 | kind: enum(u1) { type, nav }, | |
| 278 | index: u31, | |
| 279 | ||
| 280 | pub const Unwrapped = union(enum) { | |
| 281 | /// This `Cau` exists in isolation. It is a global `comptime` declaration, or (TODO ANYTHING ELSE?). | |
| 282 | /// After semantic analysis completes, the result is discarded. | |
| 283 | none, | |
| 284 | /// This `Cau` is owned by the given type for type resolution. | |
| 285 | /// This is a `struct`, `union`, or `enum` type. | |
| 286 | type: InternPool.Index, | |
| 287 | /// This `Cau` is owned by the given `Nav` to resolve its value. | |
| 288 | /// When analyzing the `Cau`, the resulting value is stored as the value of this `Nav`. | |
| 289 | nav: Nav.Index, | |
| 290 | }; | |
| 291 | ||
| 292 | pub fn unwrap(owner: Owner) Unwrapped { | |
| 293 | if (@as(u32, @bitCast(owner)) == std.math.maxInt(u32)) { | |
| 294 | return .none; | |
| 295 | } | |
| 296 | return switch (owner.kind) { | |
| 297 | .type => .{ .type = @enumFromInt(owner.index) }, | |
| 298 | .nav => .{ .nav = @enumFromInt(owner.index) }, | |
| 299 | }; | |
| 300 | } | |
| 301 | ||
| 302 | fn wrap(raw: Unwrapped) Owner { | |
| 303 | return switch (raw) { | |
| 304 | .none => @bitCast(@as(u32, std.math.maxInt(u32))), | |
| 305 | .type => |ty| .{ .kind = .type, .index = @intCast(@intFromEnum(ty)) }, | |
| 306 | .nav => |nav| .{ .kind = .nav, .index = @intCast(@intFromEnum(nav)) }, | |
| 307 | }; | |
| 308 | } | |
| 309 | }; | |
| 310 | ||
| 311 | pub const Index = enum(u32) { | |
| 312 | _, | |
| 313 | pub const Optional = enum(u32) { | |
| 314 | none = std.math.maxInt(u32), | |
| 315 | _, | |
| 316 | pub fn unwrap(opt: Optional) ?Cau.Index { | |
| 317 | return switch (opt) { | |
| 318 | .none => null, | |
| 319 | _ => @enumFromInt(@intFromEnum(opt)), | |
| 320 | }; | |
| 321 | } | |
| 322 | }; | |
| 323 | pub fn toOptional(i: Cau.Index) Optional { | |
| 324 | return @enumFromInt(@intFromEnum(i)); | |
| 325 | } | |
| 326 | const Unwrapped = struct { | |
| 327 | tid: Zcu.PerThread.Id, | |
| 328 | index: u32, | |
| 329 | ||
| 330 | fn wrap(unwrapped: Unwrapped, ip: *const InternPool) Cau.Index { | |
| 331 | assert(@intFromEnum(unwrapped.tid) <= ip.getTidMask()); | |
| 332 | assert(unwrapped.index <= ip.getIndexMask(u31)); | |
| 333 | return @enumFromInt(@as(u32, @intFromEnum(unwrapped.tid)) << ip.tid_shift_31 | | |
| 334 | unwrapped.index); | |
| 335 | } | |
| 336 | }; | |
| 337 | fn unwrap(cau_index: Cau.Index, ip: *const InternPool) Unwrapped { | |
| 338 | return .{ | |
| 339 | .tid = @enumFromInt(@intFromEnum(cau_index) >> ip.tid_shift_31 & ip.getTidMask()), | |
| 340 | .index = @intFromEnum(cau_index) & ip.getIndexMask(u31), | |
| 341 | }; | |
| 342 | } | |
| 343 | }; | |
| 344 | }; | |
| 345 | ||
| 346 | /// Named Addressable Value. Represents a global value with a name and address. This name may be | |
| 347 | /// generated, and the type (and hence address) may be comptime-only. A `Nav` whose type has runtime | |
| 348 | /// bits is sent to the linker to be emitted to the binary. | |
| 349 | /// | |
| 350 | /// * Every ZIR `declaration` which is not a `comptime` declaration has a `Nav` (post-instantiation) | |
| 351 | /// which stores the declaration's resolved value. | |
| 352 | /// * Generic instances have a `Nav` corresponding to the instantiated function. | |
| 353 | /// * `@extern` calls create a `Nav` whose value is a `.@"extern"`. | |
| 354 | /// | |
| 355 | /// `Nav.Repr` is the in-memory representation. | |
| 356 | pub const Nav = struct { | |
| 357 | /// The unqualified name of this `Nav`. Namespace lookups use this name, and error messages may use it. | |
| 358 | /// Additionally, extern `Nav`s (i.e. those whose value is an `extern`) use this name. | |
| 359 | name: NullTerminatedString, | |
| 360 | /// The fully-qualified name of this `Nav`. | |
| 361 | fqn: NullTerminatedString, | |
| 362 | /// If the value of this `Nav` is resolved by semantic analysis, it is within this `Cau`. | |
| 363 | /// If this is `.none`, then `status == .resolved` always. | |
| 364 | analysis_owner: Cau.Index.Optional, | |
| 365 | /// TODO: this is a hack! If #20663 isn't accepted, let's figure out something a bit better. | |
| 366 | is_usingnamespace: bool, | |
| 367 | status: union(enum) { | |
| 368 | /// This `Nav` is pending semantic analysis through `analysis_owner`. | |
| 369 | unresolved, | |
| 370 | /// The value of this `Nav` is resolved. | |
| 371 | resolved: struct { | |
| 372 | val: InternPool.Index, | |
| 373 | alignment: Alignment, | |
| 374 | @"linksection": OptionalNullTerminatedString, | |
| 375 | @"addrspace": std.builtin.AddressSpace, | |
| 376 | }, | |
| 377 | }, | |
| 378 | ||
| 379 | /// Asserts that `status == .resolved`. | |
| 380 | pub fn typeOf(nav: Nav, ip: *const InternPool) InternPool.Index { | |
| 381 | return ip.typeOf(nav.status.resolved.val); | |
| 382 | } | |
| 383 | ||
| 384 | /// Asserts that `status == .resolved`. | |
| 385 | pub fn isExtern(nav: Nav, ip: *const InternPool) bool { | |
| 386 | return ip.indexToKey(nav.status.resolved.val) == .@"extern"; | |
| 387 | } | |
| 388 | ||
| 389 | /// Get the ZIR instruction corresponding to this `Nav`, used to resolve source locations. | |
| 390 | /// This is a `declaration`. | |
| 391 | pub fn srcInst(nav: Nav, ip: *const InternPool) TrackedInst.Index { | |
| 392 | if (nav.analysis_owner.unwrap()) |cau| { | |
| 393 | return ip.getCau(cau).zir_index; | |
| 394 | } | |
| 395 | // A `Nav` with no corresponding `Cau` always has a resolved value. | |
| 396 | return switch (ip.indexToKey(nav.status.resolved.val)) { | |
| 397 | .func => |func| { | |
| 398 | // Since there was no `analysis_owner`, this must be an instantiation. | |
| 399 | // Go up to the generic owner and consult *its* `analysis_owner`. | |
| 400 | const go_nav = ip.getNav(ip.indexToKey(func.generic_owner).func.owner_nav); | |
| 401 | const go_cau = ip.getCau(go_nav.analysis_owner.unwrap().?); | |
| 402 | return go_cau.zir_index; | |
| 403 | }, | |
| 404 | .@"extern" => |@"extern"| @"extern".zir_index, // extern / @extern | |
| 405 | else => unreachable, | |
| 406 | }; | |
| 407 | } | |
| 408 | ||
| 409 | pub const Index = enum(u32) { | |
| 410 | _, | |
| 411 | pub const Optional = enum(u32) { | |
| 412 | none = std.math.maxInt(u32), | |
| 413 | _, | |
| 414 | pub fn unwrap(opt: Optional) ?Nav.Index { | |
| 415 | return switch (opt) { | |
| 416 | .none => null, | |
| 417 | _ => @enumFromInt(@intFromEnum(opt)), | |
| 418 | }; | |
| 419 | } | |
| 420 | }; | |
| 421 | pub fn toOptional(i: Nav.Index) Optional { | |
| 422 | return @enumFromInt(@intFromEnum(i)); | |
| 423 | } | |
| 424 | const Unwrapped = struct { | |
| 425 | tid: Zcu.PerThread.Id, | |
| 426 | index: u32, | |
| 427 | ||
| 428 | fn wrap(unwrapped: Unwrapped, ip: *const InternPool) Nav.Index { | |
| 429 | assert(@intFromEnum(unwrapped.tid) <= ip.getTidMask()); | |
| 430 | assert(unwrapped.index <= ip.getIndexMask(u32)); | |
| 431 | return @enumFromInt(@as(u32, @intFromEnum(unwrapped.tid)) << ip.tid_shift_32 | | |
| 432 | unwrapped.index); | |
| 433 | } | |
| 434 | }; | |
| 435 | fn unwrap(nav_index: Nav.Index, ip: *const InternPool) Unwrapped { | |
| 436 | return .{ | |
| 437 | .tid = @enumFromInt(@intFromEnum(nav_index) >> ip.tid_shift_32 & ip.getTidMask()), | |
| 438 | .index = @intFromEnum(nav_index) & ip.getIndexMask(u32), | |
| 439 | }; | |
| 440 | } | |
| 441 | }; | |
| 442 | ||
| 443 | /// The compact in-memory representation of a `Nav`. | |
| 444 | /// 18 bytes. | |
| 445 | const Repr = struct { | |
| 446 | name: NullTerminatedString, | |
| 447 | fqn: NullTerminatedString, | |
| 448 | analysis_owner: Cau.Index.Optional, | |
| 449 | /// Populated only if `bits.status == .resolved`. | |
| 450 | val: InternPool.Index, | |
| 451 | /// Populated only if `bits.status == .resolved`. | |
| 452 | @"linksection": OptionalNullTerminatedString, | |
| 453 | bits: Bits, | |
| 454 | ||
| 455 | const Bits = packed struct(u16) { | |
| 456 | status: enum(u1) { unresolved, resolved }, | |
| 457 | /// Populated only if `bits.status == .resolved`. | |
| 458 | alignment: Alignment, | |
| 459 | /// Populated only if `bits.status == .resolved`. | |
| 460 | @"addrspace": std.builtin.AddressSpace, | |
| 461 | _: u3 = 0, | |
| 462 | is_usingnamespace: bool, | |
| 463 | }; | |
| 464 | ||
| 465 | fn unpack(repr: Repr) Nav { | |
| 466 | return .{ | |
| 467 | .name = repr.name, | |
| 468 | .fqn = repr.fqn, | |
| 469 | .analysis_owner = repr.analysis_owner, | |
| 470 | .is_usingnamespace = repr.bits.is_usingnamespace, | |
| 471 | .status = switch (repr.bits.status) { | |
| 472 | .unresolved => .unresolved, | |
| 473 | .resolved => .{ .resolved = .{ | |
| 474 | .val = repr.val, | |
| 475 | .alignment = repr.bits.alignment, | |
| 476 | .@"linksection" = repr.@"linksection", | |
| 477 | .@"addrspace" = repr.bits.@"addrspace", | |
| 478 | } }, | |
| 479 | }, | |
| 480 | }; | |
| 481 | } | |
| 482 | }; | |
| 483 | ||
| 484 | fn pack(nav: Nav) Repr { | |
| 485 | // Note that in the `unresolved` case, we do not mark fields as `undefined`, even though they should not be used. | |
| 486 | // This is to avoid writing undefined bytes to disk when serializing buffers. | |
| 487 | return .{ | |
| 488 | .name = nav.name, | |
| 489 | .fqn = nav.fqn, | |
| 490 | .analysis_owner = nav.analysis_owner, | |
| 491 | .val = switch (nav.status) { | |
| 492 | .unresolved => .none, | |
| 493 | .resolved => |r| r.val, | |
| 494 | }, | |
| 495 | .@"linksection" = switch (nav.status) { | |
| 496 | .unresolved => .none, | |
| 497 | .resolved => |r| r.@"linksection", | |
| 498 | }, | |
| 499 | .bits = switch (nav.status) { | |
| 500 | .unresolved => .{ | |
| 501 | .status = .unresolved, | |
| 502 | .alignment = .none, | |
| 503 | .@"addrspace" = .generic, | |
| 504 | .is_usingnamespace = nav.is_usingnamespace, | |
| 505 | }, | |
| 506 | .resolved => |r| .{ | |
| 507 | .status = .resolved, | |
| 508 | .alignment = r.alignment, | |
| 509 | .@"addrspace" = r.@"addrspace", | |
| 510 | .is_usingnamespace = nav.is_usingnamespace, | |
| 511 | }, | |
| 512 | }, | |
| 513 | }; | |
| 514 | } | |
| 515 | }; | |
| 516 | ||
| 250 | 517 | pub const Dependee = union(enum) { |
| 251 | 518 | src_hash: TrackedInst.Index, |
| 252 | decl_val: DeclIndex, | |
| 253 | func_ies: Index, | |
| 519 | nav_val: Nav.Index, | |
| 520 | interned: Index, | |
| 254 | 521 | namespace: TrackedInst.Index, |
| 255 | 522 | namespace_name: NamespaceNameKey, |
| 256 | 523 | }; |
| ... | ... | @@ -297,8 +564,8 @@ pub const DependencyIterator = struct { |
| 297 | 564 | pub fn dependencyIterator(ip: *const InternPool, dependee: Dependee) DependencyIterator { |
| 298 | 565 | const first_entry = switch (dependee) { |
| 299 | 566 | .src_hash => |x| ip.src_hash_deps.get(x), |
| 300 | .decl_val => |x| ip.decl_val_deps.get(x), | |
| 301 | .func_ies => |x| ip.func_ies_deps.get(x), | |
| 567 | .nav_val => |x| ip.nav_val_deps.get(x), | |
| 568 | .interned => |x| ip.interned_deps.get(x), | |
| 302 | 569 | .namespace => |x| ip.namespace_deps.get(x), |
| 303 | 570 | .namespace_name => |x| ip.namespace_name_deps.get(x), |
| 304 | 571 | } orelse return .{ |
| ... | ... | @@ -337,8 +604,8 @@ pub fn addDependency(ip: *InternPool, gpa: Allocator, depender: AnalUnit, depend |
| 337 | 604 | inline else => |dependee_payload, tag| new_index: { |
| 338 | 605 | const gop = try switch (tag) { |
| 339 | 606 | .src_hash => ip.src_hash_deps, |
| 340 | .decl_val => ip.decl_val_deps, | |
| 341 | .func_ies => ip.func_ies_deps, | |
| 607 | .nav_val => ip.nav_val_deps, | |
| 608 | .interned => ip.interned_deps, | |
| 342 | 609 | .namespace => ip.namespace_deps, |
| 343 | 610 | .namespace_name => ip.namespace_name_deps, |
| 344 | 611 | }.getOrPut(gpa, dependee_payload); |
| ... | ... | @@ -426,8 +693,9 @@ const Local = struct { |
| 426 | 693 | tracked_insts: ListMutate, |
| 427 | 694 | files: ListMutate, |
| 428 | 695 | maps: ListMutate, |
| 696 | caus: ListMutate, | |
| 697 | navs: ListMutate, | |
| 429 | 698 | |
| 430 | decls: BucketListMutate, | |
| 431 | 699 | namespaces: BucketListMutate, |
| 432 | 700 | } align(std.atomic.cache_line), |
| 433 | 701 | |
| ... | ... | @@ -439,8 +707,9 @@ const Local = struct { |
| 439 | 707 | tracked_insts: TrackedInsts, |
| 440 | 708 | files: List(File), |
| 441 | 709 | maps: Maps, |
| 710 | caus: Caus, | |
| 711 | navs: Navs, | |
| 442 | 712 | |
| 443 | decls: Decls, | |
| 444 | 713 | namespaces: Namespaces, |
| 445 | 714 | |
| 446 | 715 | pub fn getLimbs(shared: *const Local.Shared) Limbs { |
| ... | ... | @@ -461,15 +730,12 @@ const Local = struct { |
| 461 | 730 | const Strings = List(struct { u8 }); |
| 462 | 731 | const TrackedInsts = List(struct { TrackedInst }); |
| 463 | 732 | const Maps = List(struct { FieldMap }); |
| 464 | ||
| 465 | const decls_bucket_width = 8; | |
| 466 | const decls_bucket_mask = (1 << decls_bucket_width) - 1; | |
| 467 | const decl_next_free_field = "src_namespace"; | |
| 468 | const Decls = List(struct { *[1 << decls_bucket_width]Zcu.Decl }); | |
| 733 | const Caus = List(struct { Cau }); | |
| 734 | const Navs = List(Nav.Repr); | |
| 469 | 735 | |
| 470 | 736 | const namespaces_bucket_width = 8; |
| 471 | 737 | const namespaces_bucket_mask = (1 << namespaces_bucket_width) - 1; |
| 472 | const namespace_next_free_field = "decl_index"; | |
| 738 | const namespace_next_free_field = "owner_type"; | |
| 473 | 739 | const Namespaces = List(struct { *[1 << namespaces_bucket_width]Zcu.Namespace }); |
| 474 | 740 | |
| 475 | 741 | const ListMutate = struct { |
| ... | ... | @@ -810,8 +1076,6 @@ const Local = struct { |
| 810 | 1076 | /// |
| 811 | 1077 | /// Key is the hash of the path to this file, used to store |
| 812 | 1078 | /// `InternPool.TrackedInst`. |
| 813 | /// | |
| 814 | /// Value is the `Decl` of the struct that represents this `File`. | |
| 815 | 1079 | pub fn getMutableFiles(local: *Local, gpa: Allocator) List(File).Mutable { |
| 816 | 1080 | return .{ |
| 817 | 1081 | .gpa = gpa, |
| ... | ... | @@ -835,26 +1099,34 @@ const Local = struct { |
| 835 | 1099 | }; |
| 836 | 1100 | } |
| 837 | 1101 | |
| 838 | /// Rather than allocating Decl objects with an Allocator, we instead allocate | |
| 839 | /// them with this BucketList. This provides four advantages: | |
| 840 | /// * Stable memory so that one thread can access a Decl object while another | |
| 841 | /// thread allocates additional Decl objects from this list. | |
| 842 | /// * It allows us to use u32 indexes to reference Decl objects rather than | |
| 843 | /// pointers, saving memory in Type, Value, and dependency sets. | |
| 844 | /// * Using integers to reference Decl objects rather than pointers makes | |
| 845 | /// serialization trivial. | |
| 846 | /// * It provides a unique integer to be used for anonymous symbol names, avoiding | |
| 847 | /// multi-threaded contention on an atomic counter. | |
| 848 | pub fn getMutableDecls(local: *Local, gpa: Allocator) Decls.Mutable { | |
| 1102 | pub fn getMutableCaus(local: *Local, gpa: Allocator) Caus.Mutable { | |
| 1103 | return .{ | |
| 1104 | .gpa = gpa, | |
| 1105 | .arena = &local.mutate.arena, | |
| 1106 | .mutate = &local.mutate.caus, | |
| 1107 | .list = &local.shared.caus, | |
| 1108 | }; | |
| 1109 | } | |
| 1110 | ||
| 1111 | pub fn getMutableNavs(local: *Local, gpa: Allocator) Navs.Mutable { | |
| 849 | 1112 | return .{ |
| 850 | 1113 | .gpa = gpa, |
| 851 | 1114 | .arena = &local.mutate.arena, |
| 852 | .mutate = &local.mutate.decls.buckets_list, | |
| 853 | .list = &local.shared.decls, | |
| 1115 | .mutate = &local.mutate.navs, | |
| 1116 | .list = &local.shared.navs, | |
| 854 | 1117 | }; |
| 855 | 1118 | } |
| 856 | 1119 | |
| 857 | /// Same pattern as with `getMutableDecls`. | |
| 1120 | /// Rather than allocating Namespace objects with an Allocator, we instead allocate | |
| 1121 | /// them with this BucketList. This provides four advantages: | |
| 1122 | /// * Stable memory so that one thread can access a Namespace object while another | |
| 1123 | /// thread allocates additional Namespace objects from this list. | |
| 1124 | /// * It allows us to use u32 indexes to reference Namespace objects rather than | |
| 1125 | /// pointers, saving memory in types. | |
| 1126 | /// * Using integers to reference Namespace objects rather than pointers makes | |
| 1127 | /// serialization trivial. | |
| 1128 | /// * It provides a unique integer to be used for anonymous symbol names, avoiding | |
| 1129 | /// multi-threaded contention on an atomic counter. | |
| 858 | 1130 | pub fn getMutableNamespaces(local: *Local, gpa: Allocator) Namespaces.Mutable { |
| 859 | 1131 | return .{ |
| 860 | 1132 | .gpa = gpa, |
| ... | ... | @@ -1038,51 +1310,6 @@ pub const RuntimeIndex = enum(u32) { |
| 1038 | 1310 | |
| 1039 | 1311 | pub const ComptimeAllocIndex = enum(u32) { _ }; |
| 1040 | 1312 | |
| 1041 | pub const DeclIndex = enum(u32) { | |
| 1042 | _, | |
| 1043 | ||
| 1044 | const Unwrapped = struct { | |
| 1045 | tid: Zcu.PerThread.Id, | |
| 1046 | bucket_index: u32, | |
| 1047 | index: u32, | |
| 1048 | ||
| 1049 | fn wrap(unwrapped: Unwrapped, ip: *const InternPool) DeclIndex { | |
| 1050 | assert(@intFromEnum(unwrapped.tid) <= ip.getTidMask()); | |
| 1051 | assert(unwrapped.bucket_index <= ip.getIndexMask(u32) >> Local.decls_bucket_width); | |
| 1052 | assert(unwrapped.index <= Local.decls_bucket_mask); | |
| 1053 | return @enumFromInt(@as(u32, @intFromEnum(unwrapped.tid)) << ip.tid_shift_32 | | |
| 1054 | unwrapped.bucket_index << Local.decls_bucket_width | | |
| 1055 | unwrapped.index); | |
| 1056 | } | |
| 1057 | }; | |
| 1058 | fn unwrap(decl_index: DeclIndex, ip: *const InternPool) Unwrapped { | |
| 1059 | const index = @intFromEnum(decl_index) & ip.getIndexMask(u32); | |
| 1060 | return .{ | |
| 1061 | .tid = @enumFromInt(@intFromEnum(decl_index) >> ip.tid_shift_32 & ip.getTidMask()), | |
| 1062 | .bucket_index = index >> Local.decls_bucket_width, | |
| 1063 | .index = index & Local.decls_bucket_mask, | |
| 1064 | }; | |
| 1065 | } | |
| 1066 | ||
| 1067 | pub fn toOptional(i: DeclIndex) OptionalDeclIndex { | |
| 1068 | return @enumFromInt(@intFromEnum(i)); | |
| 1069 | } | |
| 1070 | }; | |
| 1071 | ||
| 1072 | pub const OptionalDeclIndex = enum(u32) { | |
| 1073 | none = std.math.maxInt(u32), | |
| 1074 | _, | |
| 1075 | ||
| 1076 | pub fn init(oi: ?DeclIndex) OptionalDeclIndex { | |
| 1077 | return @enumFromInt(@intFromEnum(oi orelse return .none)); | |
| 1078 | } | |
| 1079 | ||
| 1080 | pub fn unwrap(oi: OptionalDeclIndex) ?DeclIndex { | |
| 1081 | if (oi == .none) return null; | |
| 1082 | return @enumFromInt(@intFromEnum(oi)); | |
| 1083 | } | |
| 1084 | }; | |
| 1085 | ||
| 1086 | 1313 | pub const NamespaceIndex = enum(u32) { |
| 1087 | 1314 | _, |
| 1088 | 1315 | |
| ... | ... | @@ -1153,7 +1380,8 @@ pub const FileIndex = enum(u32) { |
| 1153 | 1380 | const File = struct { |
| 1154 | 1381 | bin_digest: Cache.BinDigest, |
| 1155 | 1382 | file: *Zcu.File, |
| 1156 | root_decl: OptionalDeclIndex, | |
| 1383 | /// `.none` means no type has been created yet. | |
| 1384 | root_type: InternPool.Index, | |
| 1157 | 1385 | }; |
| 1158 | 1386 | |
| 1159 | 1387 | /// An index into `strings`. |
| ... | ... | @@ -1332,26 +1560,26 @@ pub const OptionalNullTerminatedString = enum(u32) { |
| 1332 | 1560 | /// `Index` because we must differentiate between the following cases: |
| 1333 | 1561 | /// * runtime-known value (where we store the type) |
| 1334 | 1562 | /// * comptime-known value (where we store the value) |
| 1335 | /// * decl val (so that we can analyze the value lazily) | |
| 1336 | /// * decl ref (so that we can analyze the reference lazily) | |
| 1563 | /// * `Nav` val (so that we can analyze the value lazily) | |
| 1564 | /// * `Nav` ref (so that we can analyze the reference lazily) | |
| 1337 | 1565 | pub const CaptureValue = packed struct(u32) { |
| 1338 | tag: enum(u2) { @"comptime", runtime, decl_val, decl_ref }, | |
| 1566 | tag: enum(u2) { @"comptime", runtime, nav_val, nav_ref }, | |
| 1339 | 1567 | idx: u30, |
| 1340 | 1568 | |
| 1341 | 1569 | pub fn wrap(val: Unwrapped) CaptureValue { |
| 1342 | 1570 | return switch (val) { |
| 1343 | 1571 | .@"comptime" => |i| .{ .tag = .@"comptime", .idx = @intCast(@intFromEnum(i)) }, |
| 1344 | 1572 | .runtime => |i| .{ .tag = .runtime, .idx = @intCast(@intFromEnum(i)) }, |
| 1345 | .decl_val => |i| .{ .tag = .decl_val, .idx = @intCast(@intFromEnum(i)) }, | |
| 1346 | .decl_ref => |i| .{ .tag = .decl_ref, .idx = @intCast(@intFromEnum(i)) }, | |
| 1573 | .nav_val => |i| .{ .tag = .nav_val, .idx = @intCast(@intFromEnum(i)) }, | |
| 1574 | .nav_ref => |i| .{ .tag = .nav_ref, .idx = @intCast(@intFromEnum(i)) }, | |
| 1347 | 1575 | }; |
| 1348 | 1576 | } |
| 1349 | 1577 | pub fn unwrap(val: CaptureValue) Unwrapped { |
| 1350 | 1578 | return switch (val.tag) { |
| 1351 | 1579 | .@"comptime" => .{ .@"comptime" = @enumFromInt(val.idx) }, |
| 1352 | 1580 | .runtime => .{ .runtime = @enumFromInt(val.idx) }, |
| 1353 | .decl_val => .{ .decl_val = @enumFromInt(val.idx) }, | |
| 1354 | .decl_ref => .{ .decl_ref = @enumFromInt(val.idx) }, | |
| 1581 | .nav_val => .{ .nav_val = @enumFromInt(val.idx) }, | |
| 1582 | .nav_ref => .{ .nav_ref = @enumFromInt(val.idx) }, | |
| 1355 | 1583 | }; |
| 1356 | 1584 | } |
| 1357 | 1585 | |
| ... | ... | @@ -1360,8 +1588,8 @@ pub const CaptureValue = packed struct(u32) { |
| 1360 | 1588 | @"comptime": Index, |
| 1361 | 1589 | /// Index refers to the type. |
| 1362 | 1590 | runtime: Index, |
| 1363 | decl_val: DeclIndex, | |
| 1364 | decl_ref: DeclIndex, | |
| 1591 | nav_val: Nav.Index, | |
| 1592 | nav_ref: Nav.Index, | |
| 1365 | 1593 | }; |
| 1366 | 1594 | |
| 1367 | 1595 | pub const Slice = struct { |
| ... | ... | @@ -1410,7 +1638,7 @@ pub const Key = union(enum) { |
| 1410 | 1638 | undef: Index, |
| 1411 | 1639 | simple_value: SimpleValue, |
| 1412 | 1640 | variable: Variable, |
| 1413 | extern_func: ExternFunc, | |
| 1641 | @"extern": Extern, | |
| 1414 | 1642 | func: Func, |
| 1415 | 1643 | int: Key.Int, |
| 1416 | 1644 | err: Error, |
| ... | ... | @@ -1637,25 +1865,37 @@ pub const Key = union(enum) { |
| 1637 | 1865 | } |
| 1638 | 1866 | }; |
| 1639 | 1867 | |
| 1868 | /// A runtime variable defined in this `Zcu`. | |
| 1640 | 1869 | pub const Variable = struct { |
| 1641 | 1870 | ty: Index, |
| 1642 | 1871 | init: Index, |
| 1643 | decl: DeclIndex, | |
| 1872 | owner_nav: Nav.Index, | |
| 1644 | 1873 | lib_name: OptionalNullTerminatedString, |
| 1645 | is_extern: bool, | |
| 1646 | is_const: bool, | |
| 1647 | 1874 | is_threadlocal: bool, |
| 1648 | 1875 | is_weak_linkage: bool, |
| 1649 | 1876 | }; |
| 1650 | 1877 | |
| 1651 | pub const ExternFunc = struct { | |
| 1878 | pub const Extern = struct { | |
| 1879 | /// The name of the extern symbol. | |
| 1880 | name: NullTerminatedString, | |
| 1881 | /// The type of the extern symbol itself. | |
| 1882 | /// This may be `.anyopaque_type`, in which case the value may not be loaded. | |
| 1652 | 1883 | ty: Index, |
| 1653 | /// The Decl that corresponds to the function itself. | |
| 1654 | decl: DeclIndex, | |
| 1655 | 1884 | /// Library name if specified. |
| 1656 | 1885 | /// For example `extern "c" fn write(...) usize` would have 'c' as library name. |
| 1657 | 1886 | /// Index into the string table bytes. |
| 1658 | 1887 | lib_name: OptionalNullTerminatedString, |
| 1888 | is_const: bool, | |
| 1889 | is_threadlocal: bool, | |
| 1890 | is_weak_linkage: bool, | |
| 1891 | alignment: Alignment, | |
| 1892 | @"addrspace": std.builtin.AddressSpace, | |
| 1893 | /// The ZIR instruction which created this extern; used only for source locations. | |
| 1894 | /// This is a `declaration`. | |
| 1895 | zir_index: TrackedInst.Index, | |
| 1896 | /// The `Nav` corresponding to this extern symbol. | |
| 1897 | /// This is ignored by hashing and equality. | |
| 1898 | owner_nav: Nav.Index, | |
| 1659 | 1899 | }; |
| 1660 | 1900 | |
| 1661 | 1901 | pub const Func = struct { |
| ... | ... | @@ -1687,8 +1927,7 @@ pub const Key = union(enum) { |
| 1687 | 1927 | /// so that it can be mutated. |
| 1688 | 1928 | /// This will be 0 when the function is not a generic function instantiation. |
| 1689 | 1929 | branch_quota_extra_index: u32, |
| 1690 | /// The Decl that corresponds to the function itself. | |
| 1691 | owner_decl: DeclIndex, | |
| 1930 | owner_nav: Nav.Index, | |
| 1692 | 1931 | /// The ZIR instruction that is a function instruction. Use this to find |
| 1693 | 1932 | /// the body. We store this rather than the body directly so that when ZIR |
| 1694 | 1933 | /// is regenerated on update(), we can map this to the new corresponding |
| ... | ... | @@ -1861,14 +2100,14 @@ pub const Key = union(enum) { |
| 1861 | 2100 | pub const BaseAddr = union(enum) { |
| 1862 | 2101 | const Tag = @typeInfo(BaseAddr).Union.tag_type.?; |
| 1863 | 2102 | |
| 1864 | /// Points to the value of a single `Decl`, which may be constant or a `variable`. | |
| 1865 | decl: DeclIndex, | |
| 2103 | /// Points to the value of a single `Nav`, which may be constant or a `variable`. | |
| 2104 | nav: Nav.Index, | |
| 1866 | 2105 | |
| 1867 | 2106 | /// Points to the value of a single comptime alloc stored in `Sema`. |
| 1868 | 2107 | comptime_alloc: ComptimeAllocIndex, |
| 1869 | 2108 | |
| 1870 | 2109 | /// Points to a single unnamed constant value. |
| 1871 | anon_decl: AnonDecl, | |
| 2110 | uav: Uav, | |
| 1872 | 2111 | |
| 1873 | 2112 | /// Points to a comptime field of a struct. Index is the field's value. |
| 1874 | 2113 | /// |
| ... | ... | @@ -1923,15 +2162,11 @@ pub const Key = union(enum) { |
| 1923 | 2162 | /// the aggregate pointer. |
| 1924 | 2163 | arr_elem: BaseIndex, |
| 1925 | 2164 | |
| 1926 | pub const MutDecl = struct { | |
| 1927 | decl: DeclIndex, | |
| 1928 | runtime_index: RuntimeIndex, | |
| 1929 | }; | |
| 1930 | 2165 | pub const BaseIndex = struct { |
| 1931 | 2166 | base: Index, |
| 1932 | 2167 | index: u64, |
| 1933 | 2168 | }; |
| 1934 | pub const AnonDecl = extern struct { | |
| 2169 | pub const Uav = extern struct { | |
| 1935 | 2170 | val: Index, |
| 1936 | 2171 | /// Contains the canonical pointer type of the anonymous |
| 1937 | 2172 | /// declaration. This may equal `ty` of the `Ptr` or it may be |
| ... | ... | @@ -1944,10 +2179,10 @@ pub const Key = union(enum) { |
| 1944 | 2179 | if (@as(Key.Ptr.BaseAddr.Tag, a) != @as(Key.Ptr.BaseAddr.Tag, b)) return false; |
| 1945 | 2180 | |
| 1946 | 2181 | return switch (a) { |
| 1947 | .decl => |a_decl| a_decl == b.decl, | |
| 2182 | .nav => |a_nav| a_nav == b.nav, | |
| 1948 | 2183 | .comptime_alloc => |a_alloc| a_alloc == b.comptime_alloc, |
| 1949 | .anon_decl => |ad| ad.val == b.anon_decl.val and | |
| 1950 | ad.orig_ty == b.anon_decl.orig_ty, | |
| 2184 | .uav => |ad| ad.val == b.uav.val and | |
| 2185 | ad.orig_ty == b.uav.orig_ty, | |
| 1951 | 2186 | .int => true, |
| 1952 | 2187 | .eu_payload => |a_eu_payload| a_eu_payload == b.eu_payload, |
| 1953 | 2188 | .opt_payload => |a_opt_payload| a_opt_payload == b.opt_payload, |
| ... | ... | @@ -2048,7 +2283,7 @@ pub const Key = union(enum) { |
| 2048 | 2283 | .payload => |y| Hash.hash(seed + 1, asBytes(&x.ty) ++ asBytes(&y)), |
| 2049 | 2284 | }, |
| 2050 | 2285 | |
| 2051 | .variable => |variable| Hash.hash(seed, asBytes(&variable.decl)), | |
| 2286 | .variable => |variable| Hash.hash(seed, asBytes(&variable.owner_nav)), | |
| 2052 | 2287 | |
| 2053 | 2288 | .opaque_type, |
| 2054 | 2289 | .enum_type, |
| ... | ... | @@ -2125,9 +2360,9 @@ pub const Key = union(enum) { |
| 2125 | 2360 | const big_offset: i128 = ptr.byte_offset; |
| 2126 | 2361 | const common = asBytes(&ptr.ty) ++ asBytes(&big_offset); |
| 2127 | 2362 | return switch (ptr.base_addr) { |
| 2128 | inline .decl, | |
| 2363 | inline .nav, | |
| 2129 | 2364 | .comptime_alloc, |
| 2130 | .anon_decl, | |
| 2365 | .uav, | |
| 2131 | 2366 | .int, |
| 2132 | 2367 | .eu_payload, |
| 2133 | 2368 | .opt_payload, |
| ... | ... | @@ -2231,7 +2466,7 @@ pub const Key = union(enum) { |
| 2231 | 2466 | // function instances which have inferred error sets. |
| 2232 | 2467 | |
| 2233 | 2468 | if (func.generic_owner == .none and func.resolved_error_set_extra_index == 0) { |
| 2234 | const bytes = asBytes(&func.owner_decl) ++ asBytes(&func.ty) ++ | |
| 2469 | const bytes = asBytes(&func.owner_nav) ++ asBytes(&func.ty) ++ | |
| 2235 | 2470 | [1]u8{@intFromBool(func.uncoerced_ty == func.ty)}; |
| 2236 | 2471 | return Hash.hash(seed, bytes); |
| 2237 | 2472 | } |
| ... | ... | @@ -2250,7 +2485,11 @@ pub const Key = union(enum) { |
| 2250 | 2485 | return hasher.final(); |
| 2251 | 2486 | }, |
| 2252 | 2487 | |
| 2253 | .extern_func => |x| Hash.hash(seed, asBytes(&x.ty) ++ asBytes(&x.decl)), | |
| 2488 | .@"extern" => |e| Hash.hash(seed, asBytes(&e.name) ++ | |
| 2489 | asBytes(&e.ty) ++ asBytes(&e.lib_name) ++ | |
| 2490 | asBytes(&e.is_const) ++ asBytes(&e.is_threadlocal) ++ | |
| 2491 | asBytes(&e.is_weak_linkage) ++ asBytes(&e.alignment) ++ | |
| 2492 | asBytes(&e.@"addrspace") ++ asBytes(&e.zir_index)), | |
| 2254 | 2493 | }; |
| 2255 | 2494 | } |
| 2256 | 2495 | |
| ... | ... | @@ -2331,11 +2570,19 @@ pub const Key = union(enum) { |
| 2331 | 2570 | |
| 2332 | 2571 | .variable => |a_info| { |
| 2333 | 2572 | const b_info = b.variable; |
| 2334 | return a_info.decl == b_info.decl; | |
| 2573 | return a_info.owner_nav == b_info.owner_nav; | |
| 2335 | 2574 | }, |
| 2336 | .extern_func => |a_info| { | |
| 2337 | const b_info = b.extern_func; | |
| 2338 | return a_info.ty == b_info.ty and a_info.decl == b_info.decl; | |
| 2575 | .@"extern" => |a_info| { | |
| 2576 | const b_info = b.@"extern"; | |
| 2577 | return a_info.name == b_info.name and | |
| 2578 | a_info.ty == b_info.ty and | |
| 2579 | a_info.lib_name == b_info.lib_name and | |
| 2580 | a_info.is_const == b_info.is_const and | |
| 2581 | a_info.is_threadlocal == b_info.is_threadlocal and | |
| 2582 | a_info.is_weak_linkage == b_info.is_weak_linkage and | |
| 2583 | a_info.alignment == b_info.alignment and | |
| 2584 | a_info.@"addrspace" == b_info.@"addrspace" and | |
| 2585 | a_info.zir_index == b_info.zir_index; | |
| 2339 | 2586 | }, |
| 2340 | 2587 | .func => |a_info| { |
| 2341 | 2588 | const b_info = b.func; |
| ... | ... | @@ -2344,7 +2591,7 @@ pub const Key = union(enum) { |
| 2344 | 2591 | return false; |
| 2345 | 2592 | |
| 2346 | 2593 | if (a_info.generic_owner == .none) { |
| 2347 | if (a_info.owner_decl != b_info.owner_decl) | |
| 2594 | if (a_info.owner_nav != b_info.owner_nav) | |
| 2348 | 2595 | return false; |
| 2349 | 2596 | } else { |
| 2350 | 2597 | if (!std.mem.eql( |
| ... | ... | @@ -2594,7 +2841,7 @@ pub const Key = union(enum) { |
| 2594 | 2841 | .float, |
| 2595 | 2842 | .opt, |
| 2596 | 2843 | .variable, |
| 2597 | .extern_func, | |
| 2844 | .@"extern", | |
| 2598 | 2845 | .func, |
| 2599 | 2846 | .err, |
| 2600 | 2847 | .error_union, |
| ... | ... | @@ -2632,10 +2879,13 @@ pub const LoadedUnionType = struct { |
| 2632 | 2879 | tid: Zcu.PerThread.Id, |
| 2633 | 2880 | /// The index of the `Tag.TypeUnion` payload. |
| 2634 | 2881 | extra_index: u32, |
| 2635 | /// The Decl that corresponds to the union itself. | |
| 2636 | decl: DeclIndex, | |
| 2882 | // TODO: the non-fqn will be needed by the new dwarf structure | |
| 2883 | /// The name of this union type. | |
| 2884 | name: NullTerminatedString, | |
| 2885 | /// The `Cau` within which type resolution occurs. | |
| 2886 | cau: Cau.Index, | |
| 2637 | 2887 | /// Represents the declarations inside this union. |
| 2638 | namespace: OptionalNamespaceIndex, | |
| 2888 | namespace: NamespaceIndex, | |
| 2639 | 2889 | /// The enum tag type. |
| 2640 | 2890 | enum_tag_ty: Index, |
| 2641 | 2891 | /// List of field types in declaration order. |
| ... | ... | @@ -2949,7 +3199,8 @@ pub fn loadUnionType(ip: *const InternPool, index: Index) LoadedUnionType { |
| 2949 | 3199 | return .{ |
| 2950 | 3200 | .tid = unwrapped_index.tid, |
| 2951 | 3201 | .extra_index = data, |
| 2952 | .decl = type_union.data.decl, | |
| 3202 | .name = type_union.data.name, | |
| 3203 | .cau = type_union.data.cau, | |
| 2953 | 3204 | .namespace = type_union.data.namespace, |
| 2954 | 3205 | .enum_tag_ty = type_union.data.tag_ty, |
| 2955 | 3206 | .field_types = field_types, |
| ... | ... | @@ -2963,9 +3214,12 @@ pub const LoadedStructType = struct { |
| 2963 | 3214 | tid: Zcu.PerThread.Id, |
| 2964 | 3215 | /// The index of the `Tag.TypeStruct` or `Tag.TypeStructPacked` payload. |
| 2965 | 3216 | extra_index: u32, |
| 2966 | /// The struct's owner Decl. `none` when the struct is `@TypeOf(.{})`. | |
| 2967 | decl: OptionalDeclIndex, | |
| 2968 | /// `none` when the struct has no declarations. | |
| 3217 | // TODO: the non-fqn will be needed by the new dwarf structure | |
| 3218 | /// The name of this struct type. | |
| 3219 | name: NullTerminatedString, | |
| 3220 | /// The `Cau` within which type resolution occurs. `none` when the struct is `@TypeOf(.{})`. | |
| 3221 | cau: Cau.Index.Optional, | |
| 3222 | /// `none` when the struct is `@TypeOf(.{})`. | |
| 2969 | 3223 | namespace: OptionalNamespaceIndex, |
| 2970 | 3224 | /// Index of the `struct_decl` or `reify` ZIR instruction. |
| 2971 | 3225 | /// Only `none` when the struct is `@TypeOf(.{})`. |
| ... | ... | @@ -3563,7 +3817,8 @@ pub fn loadStructType(ip: *const InternPool, index: Index) LoadedStructType { |
| 3563 | 3817 | if (item.data == 0) return .{ |
| 3564 | 3818 | .tid = .main, |
| 3565 | 3819 | .extra_index = 0, |
| 3566 | .decl = .none, | |
| 3820 | .name = .empty, | |
| 3821 | .cau = .none, | |
| 3567 | 3822 | .namespace = .none, |
| 3568 | 3823 | .zir_index = .none, |
| 3569 | 3824 | .layout = .auto, |
| ... | ... | @@ -3577,7 +3832,9 @@ pub fn loadStructType(ip: *const InternPool, index: Index) LoadedStructType { |
| 3577 | 3832 | .names_map = .none, |
| 3578 | 3833 | .captures = CaptureValue.Slice.empty, |
| 3579 | 3834 | }; |
| 3580 | const decl: DeclIndex = @enumFromInt(extra_items[item.data + std.meta.fieldIndex(Tag.TypeStruct, "decl").?]); | |
| 3835 | const name: NullTerminatedString = @enumFromInt(extra_items[item.data + std.meta.fieldIndex(Tag.TypeStruct, "name").?]); | |
| 3836 | const cau: Cau.Index = @enumFromInt(extra_items[item.data + std.meta.fieldIndex(Tag.TypeStruct, "cau").?]); | |
| 3837 | const namespace: NamespaceIndex = @enumFromInt(extra_items[item.data + std.meta.fieldIndex(Tag.TypeStruct, "namespace").?]); | |
| 3581 | 3838 | const zir_index: TrackedInst.Index = @enumFromInt(extra_items[item.data + std.meta.fieldIndex(Tag.TypeStruct, "zir_index").?]); |
| 3582 | 3839 | const fields_len = extra_items[item.data + std.meta.fieldIndex(Tag.TypeStruct, "fields_len").?]; |
| 3583 | 3840 | const flags: Tag.TypeStruct.Flags = @bitCast(@atomicLoad(u32, &extra_items[item.data + std.meta.fieldIndex(Tag.TypeStruct, "flags").?], .unordered)); |
| ... | ... | @@ -3622,11 +3879,6 @@ pub fn loadStructType(ip: *const InternPool, index: Index) LoadedStructType { |
| 3622 | 3879 | extra_index += fields_len; |
| 3623 | 3880 | break :i inits; |
| 3624 | 3881 | } else Index.Slice.empty; |
| 3625 | const namespace: OptionalNamespaceIndex = if (flags.has_namespace) n: { | |
| 3626 | const n: NamespaceIndex = @enumFromInt(extra_list.view().items(.@"0")[extra_index]); | |
| 3627 | extra_index += 1; | |
| 3628 | break :n n.toOptional(); | |
| 3629 | } else .none; | |
| 3630 | 3882 | const aligns: Alignment.Slice = if (flags.any_aligned_fields) a: { |
| 3631 | 3883 | const a: Alignment.Slice = .{ |
| 3632 | 3884 | .tid = unwrapped_index.tid, |
| ... | ... | @@ -3667,8 +3919,9 @@ pub fn loadStructType(ip: *const InternPool, index: Index) LoadedStructType { |
| 3667 | 3919 | return .{ |
| 3668 | 3920 | .tid = unwrapped_index.tid, |
| 3669 | 3921 | .extra_index = item.data, |
| 3670 | .decl = decl.toOptional(), | |
| 3671 | .namespace = namespace, | |
| 3922 | .name = name, | |
| 3923 | .cau = cau.toOptional(), | |
| 3924 | .namespace = namespace.toOptional(), | |
| 3672 | 3925 | .zir_index = zir_index.toOptional(), |
| 3673 | 3926 | .layout = if (flags.is_extern) .@"extern" else .auto, |
| 3674 | 3927 | .field_names = names, |
| ... | ... | @@ -3683,10 +3936,11 @@ pub fn loadStructType(ip: *const InternPool, index: Index) LoadedStructType { |
| 3683 | 3936 | }; |
| 3684 | 3937 | }, |
| 3685 | 3938 | .type_struct_packed, .type_struct_packed_inits => { |
| 3686 | const decl: DeclIndex = @enumFromInt(extra_items[item.data + std.meta.fieldIndex(Tag.TypeStructPacked, "decl").?]); | |
| 3939 | const name: NullTerminatedString = @enumFromInt(extra_items[item.data + std.meta.fieldIndex(Tag.TypeStructPacked, "name").?]); | |
| 3940 | const cau: Cau.Index = @enumFromInt(extra_items[item.data + std.meta.fieldIndex(Tag.TypeStructPacked, "cau").?]); | |
| 3687 | 3941 | const zir_index: TrackedInst.Index = @enumFromInt(extra_items[item.data + std.meta.fieldIndex(Tag.TypeStructPacked, "zir_index").?]); |
| 3688 | 3942 | const fields_len = extra_items[item.data + std.meta.fieldIndex(Tag.TypeStructPacked, "fields_len").?]; |
| 3689 | const namespace: OptionalNamespaceIndex = @enumFromInt(extra_items[item.data + std.meta.fieldIndex(Tag.TypeStructPacked, "namespace").?]); | |
| 3943 | const namespace: NamespaceIndex = @enumFromInt(extra_items[item.data + std.meta.fieldIndex(Tag.TypeStructPacked, "namespace").?]); | |
| 3690 | 3944 | const names_map: MapIndex = @enumFromInt(extra_items[item.data + std.meta.fieldIndex(Tag.TypeStructPacked, "names_map").?]); |
| 3691 | 3945 | const flags: Tag.TypeStructPacked.Flags = @bitCast(@atomicLoad(u32, &extra_items[item.data + std.meta.fieldIndex(Tag.TypeStructPacked, "flags").?], .unordered)); |
| 3692 | 3946 | var extra_index = item.data + @as(u32, @typeInfo(Tag.TypeStructPacked).Struct.fields.len); |
| ... | ... | @@ -3729,8 +3983,9 @@ pub fn loadStructType(ip: *const InternPool, index: Index) LoadedStructType { |
| 3729 | 3983 | return .{ |
| 3730 | 3984 | .tid = unwrapped_index.tid, |
| 3731 | 3985 | .extra_index = item.data, |
| 3732 | .decl = decl.toOptional(), | |
| 3733 | .namespace = namespace, | |
| 3986 | .name = name, | |
| 3987 | .cau = cau.toOptional(), | |
| 3988 | .namespace = namespace.toOptional(), | |
| 3734 | 3989 | .zir_index = zir_index.toOptional(), |
| 3735 | 3990 | .layout = .@"packed", |
| 3736 | 3991 | .field_names = field_names, |
| ... | ... | @@ -3749,10 +4004,14 @@ pub fn loadStructType(ip: *const InternPool, index: Index) LoadedStructType { |
| 3749 | 4004 | } |
| 3750 | 4005 | |
| 3751 | 4006 | const LoadedEnumType = struct { |
| 3752 | /// The Decl that corresponds to the enum itself. | |
| 3753 | decl: DeclIndex, | |
| 4007 | // TODO: the non-fqn will be needed by the new dwarf structure | |
| 4008 | /// The name of this enum type. | |
| 4009 | name: NullTerminatedString, | |
| 4010 | /// The `Cau` within which type resolution occurs. | |
| 4011 | /// `null` if this is a generated tag type. | |
| 4012 | cau: Cau.Index.Optional, | |
| 3754 | 4013 | /// Represents the declarations inside this enum. |
| 3755 | namespace: OptionalNamespaceIndex, | |
| 4014 | namespace: NamespaceIndex, | |
| 3756 | 4015 | /// An integer type which is used for the numerical value of the enum. |
| 3757 | 4016 | /// This field is present regardless of whether the enum has an |
| 3758 | 4017 | /// explicitly provided tag type or auto-numbered. |
| ... | ... | @@ -3827,15 +4086,21 @@ pub fn loadEnumType(ip: *const InternPool, index: Index) LoadedEnumType { |
| 3827 | 4086 | .type_enum_auto => { |
| 3828 | 4087 | const extra = extraDataTrail(extra_list, EnumAuto, item.data); |
| 3829 | 4088 | var extra_index: u32 = @intCast(extra.end); |
| 3830 | if (extra.data.zir_index == .none) { | |
| 4089 | const cau: Cau.Index.Optional = if (extra.data.zir_index == .none) cau: { | |
| 3831 | 4090 | extra_index += 1; // owner_union |
| 3832 | } | |
| 4091 | break :cau .none; | |
| 4092 | } else cau: { | |
| 4093 | const cau: Cau.Index = @enumFromInt(extra_list.view().items(.@"0")[extra_index]); | |
| 4094 | extra_index += 1; // cau | |
| 4095 | break :cau cau.toOptional(); | |
| 4096 | }; | |
| 3833 | 4097 | const captures_len = if (extra.data.captures_len == std.math.maxInt(u32)) c: { |
| 3834 | 4098 | extra_index += 2; // type_hash: PackedU64 |
| 3835 | 4099 | break :c 0; |
| 3836 | 4100 | } else extra.data.captures_len; |
| 3837 | 4101 | return .{ |
| 3838 | .decl = extra.data.decl, | |
| 4102 | .name = extra.data.name, | |
| 4103 | .cau = cau, | |
| 3839 | 4104 | .namespace = extra.data.namespace, |
| 3840 | 4105 | .tag_ty = extra.data.int_tag_type, |
| 3841 | 4106 | .names = .{ |
| ... | ... | @@ -3861,15 +4126,21 @@ pub fn loadEnumType(ip: *const InternPool, index: Index) LoadedEnumType { |
| 3861 | 4126 | }; |
| 3862 | 4127 | const extra = extraDataTrail(extra_list, EnumExplicit, item.data); |
| 3863 | 4128 | var extra_index: u32 = @intCast(extra.end); |
| 3864 | if (extra.data.zir_index == .none) { | |
| 4129 | const cau: Cau.Index.Optional = if (extra.data.zir_index == .none) cau: { | |
| 3865 | 4130 | extra_index += 1; // owner_union |
| 3866 | } | |
| 4131 | break :cau .none; | |
| 4132 | } else cau: { | |
| 4133 | const cau: Cau.Index = @enumFromInt(extra_list.view().items(.@"0")[extra_index]); | |
| 4134 | extra_index += 1; // cau | |
| 4135 | break :cau cau.toOptional(); | |
| 4136 | }; | |
| 3867 | 4137 | const captures_len = if (extra.data.captures_len == std.math.maxInt(u32)) c: { |
| 3868 | 4138 | extra_index += 2; // type_hash: PackedU64 |
| 3869 | 4139 | break :c 0; |
| 3870 | 4140 | } else extra.data.captures_len; |
| 3871 | 4141 | return .{ |
| 3872 | .decl = extra.data.decl, | |
| 4142 | .name = extra.data.name, | |
| 4143 | .cau = cau, | |
| 3873 | 4144 | .namespace = extra.data.namespace, |
| 3874 | 4145 | .tag_ty = extra.data.int_tag_type, |
| 3875 | 4146 | .names = .{ |
| ... | ... | @@ -3896,10 +4167,11 @@ pub fn loadEnumType(ip: *const InternPool, index: Index) LoadedEnumType { |
| 3896 | 4167 | |
| 3897 | 4168 | /// Note that this type doubles as the payload for `Tag.type_opaque`. |
| 3898 | 4169 | pub const LoadedOpaqueType = struct { |
| 3899 | /// The opaque's owner Decl. | |
| 3900 | decl: DeclIndex, | |
| 3901 | 4170 | /// Contains the declarations inside this opaque. |
| 3902 | namespace: OptionalNamespaceIndex, | |
| 4171 | namespace: NamespaceIndex, | |
| 4172 | // TODO: the non-fqn will be needed by the new dwarf structure | |
| 4173 | /// The name of this opaque type. | |
| 4174 | name: NullTerminatedString, | |
| 3903 | 4175 | /// Index of the `opaque_decl` or `reify` instruction. |
| 3904 | 4176 | zir_index: TrackedInst.Index, |
| 3905 | 4177 | captures: CaptureValue.Slice, |
| ... | ... | @@ -3915,7 +4187,7 @@ pub fn loadOpaqueType(ip: *const InternPool, index: Index) LoadedOpaqueType { |
| 3915 | 4187 | else |
| 3916 | 4188 | extra.data.captures_len; |
| 3917 | 4189 | return .{ |
| 3918 | .decl = extra.data.decl, | |
| 4190 | .name = extra.data.name, | |
| 3919 | 4191 | .namespace = extra.data.namespace, |
| 3920 | 4192 | .zir_index = extra.data.zir_index, |
| 3921 | 4193 | .captures = .{ |
| ... | ... | @@ -4216,10 +4488,10 @@ pub const Index = enum(u32) { |
| 4216 | 4488 | |
| 4217 | 4489 | undef: DataIsIndex, |
| 4218 | 4490 | simple_value: void, |
| 4219 | ptr_decl: struct { data: *PtrDecl }, | |
| 4491 | ptr_nav: struct { data: *PtrNav }, | |
| 4220 | 4492 | ptr_comptime_alloc: struct { data: *PtrComptimeAlloc }, |
| 4221 | ptr_anon_decl: struct { data: *PtrAnonDecl }, | |
| 4222 | ptr_anon_decl_aligned: struct { data: *PtrAnonDeclAligned }, | |
| 4493 | ptr_uav: struct { data: *PtrUav }, | |
| 4494 | ptr_uav_aligned: struct { data: *PtrUavAligned }, | |
| 4223 | 4495 | ptr_comptime_field: struct { data: *PtrComptimeField }, |
| 4224 | 4496 | ptr_int: struct { data: *PtrInt }, |
| 4225 | 4497 | ptr_eu_payload: struct { data: *PtrBase }, |
| ... | ... | @@ -4255,7 +4527,7 @@ pub const Index = enum(u32) { |
| 4255 | 4527 | float_c_longdouble_f128: struct { data: *Float128 }, |
| 4256 | 4528 | float_comptime_float: struct { data: *Float128 }, |
| 4257 | 4529 | variable: struct { data: *Tag.Variable }, |
| 4258 | extern_func: struct { data: *Key.ExternFunc }, | |
| 4530 | @"extern": struct { data: *Tag.Extern }, | |
| 4259 | 4531 | func_decl: struct { |
| 4260 | 4532 | const @"data.analysis.inferred_error_set" = opaque {}; |
| 4261 | 4533 | data: *Tag.FuncDecl, |
| ... | ... | @@ -4669,23 +4941,23 @@ pub const Tag = enum(u8) { |
| 4669 | 4941 | /// A value that can be represented with only an enum tag. |
| 4670 | 4942 | /// data is SimpleValue enum value. |
| 4671 | 4943 | simple_value, |
| 4672 | /// A pointer to a decl. | |
| 4673 | /// data is extra index of `PtrDecl`, which contains the type and address. | |
| 4674 | ptr_decl, | |
| 4944 | /// A pointer to a `Nav`. | |
| 4945 | /// data is extra index of `PtrNav`, which contains the type and address. | |
| 4946 | ptr_nav, | |
| 4675 | 4947 | /// A pointer to a decl that can be mutated at comptime. |
| 4676 | 4948 | /// data is extra index of `PtrComptimeAlloc`, which contains the type and address. |
| 4677 | 4949 | ptr_comptime_alloc, |
| 4678 | /// A pointer to an anonymous decl. | |
| 4679 | /// data is extra index of `PtrAnonDecl`, which contains the pointer type and decl value. | |
| 4680 | /// The alignment of the anonymous decl is communicated via the pointer type. | |
| 4681 | ptr_anon_decl, | |
| 4682 | /// A pointer to an anonymous decl. | |
| 4683 | /// data is extra index of `PtrAnonDeclAligned`, which contains the pointer | |
| 4950 | /// A pointer to an anonymous addressable value. | |
| 4951 | /// data is extra index of `PtrUav`, which contains the pointer type and decl value. | |
| 4952 | /// The alignment of the uav is communicated via the pointer type. | |
| 4953 | ptr_uav, | |
| 4954 | /// A pointer to an unnamed addressable value. | |
| 4955 | /// data is extra index of `PtrUavAligned`, which contains the pointer | |
| 4684 | 4956 | /// type and decl value. |
| 4685 | 4957 | /// The original pointer type is also provided, which will be different than `ty`. |
| 4686 | /// This encoding is only used when a pointer to an anonymous decl is | |
| 4958 | /// This encoding is only used when a pointer to a Uav is | |
| 4687 | 4959 | /// coerced to a different pointer type with a different alignment. |
| 4688 | ptr_anon_decl_aligned, | |
| 4960 | ptr_uav_aligned, | |
| 4689 | 4961 | /// data is extra index of `PtrComptimeField`, which contains the pointer type and field value. |
| 4690 | 4962 | ptr_comptime_field, |
| 4691 | 4963 | /// A pointer with an integer value. |
| ... | ... | @@ -4800,9 +5072,10 @@ pub const Tag = enum(u8) { |
| 4800 | 5072 | /// A global variable. |
| 4801 | 5073 | /// data is extra index to Variable. |
| 4802 | 5074 | variable, |
| 4803 | /// An extern function. | |
| 4804 | /// data is extra index to ExternFunc. | |
| 4805 | extern_func, | |
| 5075 | /// An extern function or variable. | |
| 5076 | /// data is extra index to Extern. | |
| 5077 | /// Some parts of the key are stored in `owner_nav`. | |
| 5078 | @"extern", | |
| 4806 | 5079 | /// A non-extern function corresponding directly to the AST node from whence it originated. |
| 4807 | 5080 | /// data is extra index to `FuncDecl`. |
| 4808 | 5081 | /// Only the owner Decl is used for hashing and equality because the other |
| ... | ... | @@ -4843,7 +5116,6 @@ pub const Tag = enum(u8) { |
| 4843 | 5116 | const TypeValue = Key.TypeValue; |
| 4844 | 5117 | const Error = Key.Error; |
| 4845 | 5118 | const EnumTag = Key.EnumTag; |
| 4846 | const ExternFunc = Key.ExternFunc; | |
| 4847 | 5119 | const Union = Key.Union; |
| 4848 | 5120 | const TypePointer = Key.PtrType; |
| 4849 | 5121 | |
| ... | ... | @@ -4877,10 +5149,10 @@ pub const Tag = enum(u8) { |
| 4877 | 5149 | |
| 4878 | 5150 | .undef => unreachable, |
| 4879 | 5151 | .simple_value => unreachable, |
| 4880 | .ptr_decl => PtrDecl, | |
| 5152 | .ptr_nav => PtrNav, | |
| 4881 | 5153 | .ptr_comptime_alloc => PtrComptimeAlloc, |
| 4882 | .ptr_anon_decl => PtrAnonDecl, | |
| 4883 | .ptr_anon_decl_aligned => PtrAnonDeclAligned, | |
| 5154 | .ptr_uav => PtrUav, | |
| 5155 | .ptr_uav_aligned => PtrUavAligned, | |
| 4884 | 5156 | .ptr_comptime_field => PtrComptimeField, |
| 4885 | 5157 | .ptr_int => PtrInt, |
| 4886 | 5158 | .ptr_eu_payload => PtrBase, |
| ... | ... | @@ -4916,7 +5188,7 @@ pub const Tag = enum(u8) { |
| 4916 | 5188 | .float_c_longdouble_f128 => unreachable, |
| 4917 | 5189 | .float_comptime_float => unreachable, |
| 4918 | 5190 | .variable => Variable, |
| 4919 | .extern_func => ExternFunc, | |
| 5191 | .@"extern" => Extern, | |
| 4920 | 5192 | .func_decl => FuncDecl, |
| 4921 | 5193 | .func_instance => FuncInstance, |
| 4922 | 5194 | .func_coerced => FuncCoerced, |
| ... | ... | @@ -4933,21 +5205,29 @@ pub const Tag = enum(u8) { |
| 4933 | 5205 | ty: Index, |
| 4934 | 5206 | /// May be `none`. |
| 4935 | 5207 | init: Index, |
| 4936 | decl: DeclIndex, | |
| 5208 | owner_nav: Nav.Index, | |
| 4937 | 5209 | /// Library name if specified. |
| 4938 | 5210 | /// For example `extern "c" var stderrp = ...` would have 'c' as library name. |
| 4939 | 5211 | lib_name: OptionalNullTerminatedString, |
| 4940 | 5212 | flags: Flags, |
| 4941 | 5213 | |
| 4942 | 5214 | pub const Flags = packed struct(u32) { |
| 4943 | is_extern: bool, | |
| 4944 | 5215 | is_const: bool, |
| 4945 | 5216 | is_threadlocal: bool, |
| 4946 | 5217 | is_weak_linkage: bool, |
| 4947 | _: u28 = 0, | |
| 5218 | _: u29 = 0, | |
| 4948 | 5219 | }; |
| 4949 | 5220 | }; |
| 4950 | 5221 | |
| 5222 | pub const Extern = struct { | |
| 5223 | // name, alignment, addrspace come from `owner_nav`. | |
| 5224 | ty: Index, | |
| 5225 | lib_name: OptionalNullTerminatedString, | |
| 5226 | flags: Variable.Flags, | |
| 5227 | owner_nav: Nav.Index, | |
| 5228 | zir_index: TrackedInst.Index, | |
| 5229 | }; | |
| 5230 | ||
| 4951 | 5231 | /// Trailing: |
| 4952 | 5232 | /// 0. element: Index for each len |
| 4953 | 5233 | /// len is determined by the aggregate type. |
| ... | ... | @@ -4962,7 +5242,7 @@ pub const Tag = enum(u8) { |
| 4962 | 5242 | /// A `none` value marks that the inferred error set is not resolved yet. |
| 4963 | 5243 | pub const FuncDecl = struct { |
| 4964 | 5244 | analysis: FuncAnalysis, |
| 4965 | owner_decl: DeclIndex, | |
| 5245 | owner_nav: Nav.Index, | |
| 4966 | 5246 | ty: Index, |
| 4967 | 5247 | zir_body_inst: TrackedInst.Index, |
| 4968 | 5248 | lbrace_line: u32, |
| ... | ... | @@ -4979,7 +5259,7 @@ pub const Tag = enum(u8) { |
| 4979 | 5259 | pub const FuncInstance = struct { |
| 4980 | 5260 | analysis: FuncAnalysis, |
| 4981 | 5261 | // Needed by the linker for codegen. Not part of hashing or equality. |
| 4982 | owner_decl: DeclIndex, | |
| 5262 | owner_nav: Nav.Index, | |
| 4983 | 5263 | ty: Index, |
| 4984 | 5264 | branch_quota: u32, |
| 4985 | 5265 | /// Points to a `FuncDecl`. |
| ... | ... | @@ -5029,6 +5309,7 @@ pub const Tag = enum(u8) { |
| 5029 | 5309 | /// 3. field type: Index for each field; declaration order |
| 5030 | 5310 | /// 4. field align: Alignment for each field; declaration order |
| 5031 | 5311 | pub const TypeUnion = struct { |
| 5312 | name: NullTerminatedString, | |
| 5032 | 5313 | flags: Flags, |
| 5033 | 5314 | /// This could be provided through the tag type, but it is more convenient |
| 5034 | 5315 | /// to store it directly. This is also necessary for `dumpStatsFallible` to |
| ... | ... | @@ -5038,8 +5319,8 @@ pub const Tag = enum(u8) { |
| 5038 | 5319 | size: u32, |
| 5039 | 5320 | /// Only valid after .have_layout |
| 5040 | 5321 | padding: u32, |
| 5041 | decl: DeclIndex, | |
| 5042 | namespace: OptionalNamespaceIndex, | |
| 5322 | cau: Cau.Index, | |
| 5323 | namespace: NamespaceIndex, | |
| 5043 | 5324 | /// The enum that provides the list of field names and values. |
| 5044 | 5325 | tag_ty: Index, |
| 5045 | 5326 | zir_index: TrackedInst.Index, |
| ... | ... | @@ -5068,10 +5349,11 @@ pub const Tag = enum(u8) { |
| 5068 | 5349 | /// 4. name: NullTerminatedString for each fields_len |
| 5069 | 5350 | /// 5. init: Index for each fields_len // if tag is type_struct_packed_inits |
| 5070 | 5351 | pub const TypeStructPacked = struct { |
| 5071 | decl: DeclIndex, | |
| 5352 | name: NullTerminatedString, | |
| 5353 | cau: Cau.Index, | |
| 5072 | 5354 | zir_index: TrackedInst.Index, |
| 5073 | 5355 | fields_len: u32, |
| 5074 | namespace: OptionalNamespaceIndex, | |
| 5356 | namespace: NamespaceIndex, | |
| 5075 | 5357 | backing_int_ty: Index, |
| 5076 | 5358 | names_map: MapIndex, |
| 5077 | 5359 | flags: Flags, |
| ... | ... | @@ -5110,18 +5392,18 @@ pub const Tag = enum(u8) { |
| 5110 | 5392 | /// name: NullTerminatedString // for each field in declared order |
| 5111 | 5393 | /// 5. if any_default_inits: |
| 5112 | 5394 | /// init: Index // for each field in declared order |
| 5113 | /// 6. if has_namespace: | |
| 5114 | /// namespace: NamespaceIndex | |
| 5115 | /// 7. if any_aligned_fields: | |
| 5395 | /// 6. if any_aligned_fields: | |
| 5116 | 5396 | /// align: Alignment // for each field in declared order |
| 5117 | /// 8. if any_comptime_fields: | |
| 5397 | /// 7. if any_comptime_fields: | |
| 5118 | 5398 | /// field_is_comptime_bits: u32 // minimal number of u32s needed, LSB is field 0 |
| 5119 | /// 9. if not is_extern: | |
| 5399 | /// 8. if not is_extern: | |
| 5120 | 5400 | /// field_index: RuntimeOrder // for each field in runtime order |
| 5121 | /// 10. field_offset: u32 // for each field in declared order, undef until layout_resolved | |
| 5401 | /// 9. field_offset: u32 // for each field in declared order, undef until layout_resolved | |
| 5122 | 5402 | pub const TypeStruct = struct { |
| 5123 | decl: DeclIndex, | |
| 5403 | name: NullTerminatedString, | |
| 5404 | cau: Cau.Index, | |
| 5124 | 5405 | zir_index: TrackedInst.Index, |
| 5406 | namespace: NamespaceIndex, | |
| 5125 | 5407 | fields_len: u32, |
| 5126 | 5408 | flags: Flags, |
| 5127 | 5409 | size: u32, |
| ... | ... | @@ -5134,7 +5416,6 @@ pub const Tag = enum(u8) { |
| 5134 | 5416 | is_tuple: bool = false, |
| 5135 | 5417 | assumed_runtime_bits: bool = false, |
| 5136 | 5418 | assumed_pointer_aligned: bool = false, |
| 5137 | has_namespace: bool = false, | |
| 5138 | 5419 | any_comptime_fields: bool = false, |
| 5139 | 5420 | any_default_inits: bool = false, |
| 5140 | 5421 | any_aligned_fields: bool = false, |
| ... | ... | @@ -5157,17 +5438,16 @@ pub const Tag = enum(u8) { |
| 5157 | 5438 | // which `layout_resolved` does not ensure. |
| 5158 | 5439 | fully_resolved: bool = false, |
| 5159 | 5440 | is_reified: bool = false, |
| 5160 | _: u6 = 0, | |
| 5441 | _: u7 = 0, | |
| 5161 | 5442 | }; |
| 5162 | 5443 | }; |
| 5163 | 5444 | |
| 5164 | 5445 | /// Trailing: |
| 5165 | 5446 | /// 0. capture: CaptureValue // for each `captures_len` |
| 5166 | 5447 | pub const TypeOpaque = struct { |
| 5167 | /// The opaque's owner Decl. | |
| 5168 | decl: DeclIndex, | |
| 5448 | name: NullTerminatedString, | |
| 5169 | 5449 | /// Contains the declarations inside this opaque. |
| 5170 | namespace: OptionalNamespaceIndex, | |
| 5450 | namespace: NamespaceIndex, | |
| 5171 | 5451 | /// The index of the `opaque_decl` instruction. |
| 5172 | 5452 | zir_index: TrackedInst.Index, |
| 5173 | 5453 | /// `std.math.maxInt(u32)` indicates this type is reified. |
| ... | ... | @@ -5188,29 +5468,19 @@ pub const FuncAnalysis = packed struct(u32) { |
| 5188 | 5468 | inferred_error_set: bool, |
| 5189 | 5469 | disable_instrumentation: bool, |
| 5190 | 5470 | |
| 5191 | _: u13 = 0, | |
| 5471 | _: u19 = 0, | |
| 5192 | 5472 | |
| 5193 | pub const State = enum(u8) { | |
| 5194 | /// This function has not yet undergone analysis, because we have not | |
| 5195 | /// seen a potential runtime call. It may be analyzed in future. | |
| 5196 | none, | |
| 5197 | /// Analysis for this function has been queued, but not yet completed. | |
| 5473 | pub const State = enum(u2) { | |
| 5474 | /// The runtime function has never been referenced. | |
| 5475 | /// As such, it has never been analyzed, nor is it queued for analysis. | |
| 5476 | unreferenced, | |
| 5477 | /// The runtime function has been referenced, but has not yet been analyzed. | |
| 5478 | /// Its semantic analysis is queued. | |
| 5198 | 5479 | queued, |
| 5199 | /// This function intentionally only has ZIR generated because it is marked | |
| 5200 | /// inline, which means no runtime version of the function will be generated. | |
| 5201 | inline_only, | |
| 5202 | in_progress, | |
| 5203 | /// There will be a corresponding ErrorMsg in Zcu.failed_decls | |
| 5204 | sema_failure, | |
| 5205 | /// This function might be OK but it depends on another Decl which did not | |
| 5206 | /// successfully complete semantic analysis. | |
| 5207 | dependency_failure, | |
| 5208 | /// There will be a corresponding ErrorMsg in Zcu.failed_decls. | |
| 5209 | /// Indicates that semantic analysis succeeded, but code generation for | |
| 5210 | /// this function failed. | |
| 5211 | codegen_failure, | |
| 5212 | /// Semantic analysis and code generation of this function succeeded. | |
| 5213 | success, | |
| 5480 | /// The runtime function has been (or is currently being) semantically analyzed. | |
| 5481 | /// To know if analysis succeeded, consult `zcu.[transitive_]failed_analysis`. | |
| 5482 | /// To know if analysis is up-to-date, consult `zcu.[potentially_]outdated`. | |
| 5483 | analyzed, | |
| 5214 | 5484 | }; |
| 5215 | 5485 | }; |
| 5216 | 5486 | |
| ... | ... | @@ -5477,17 +5747,16 @@ pub const Array = struct { |
| 5477 | 5747 | |
| 5478 | 5748 | /// Trailing: |
| 5479 | 5749 | /// 0. owner_union: Index // if `zir_index == .none` |
| 5480 | /// 1. capture: CaptureValue // for each `captures_len` | |
| 5481 | /// 2. type_hash: PackedU64 // if reified (`captures_len == std.math.maxInt(u32)`) | |
| 5482 | /// 3. field name: NullTerminatedString for each fields_len; declaration order | |
| 5483 | /// 4. tag value: Index for each fields_len; declaration order | |
| 5750 | /// 1. cau: Cau.Index // if `zir_index != .none` | |
| 5751 | /// 2. capture: CaptureValue // for each `captures_len` | |
| 5752 | /// 3. type_hash: PackedU64 // if reified (`captures_len == std.math.maxInt(u32)`) | |
| 5753 | /// 4. field name: NullTerminatedString for each fields_len; declaration order | |
| 5754 | /// 5. tag value: Index for each fields_len; declaration order | |
| 5484 | 5755 | pub const EnumExplicit = struct { |
| 5485 | /// The Decl that corresponds to the enum itself. | |
| 5486 | decl: DeclIndex, | |
| 5756 | name: NullTerminatedString, | |
| 5487 | 5757 | /// `std.math.maxInt(u32)` indicates this type is reified. |
| 5488 | 5758 | captures_len: u32, |
| 5489 | /// This may be `none` if there are no declarations. | |
| 5490 | namespace: OptionalNamespaceIndex, | |
| 5759 | namespace: NamespaceIndex, | |
| 5491 | 5760 | /// An integer type which is used for the numerical value of the enum, which |
| 5492 | 5761 | /// has been explicitly provided by the enum declaration. |
| 5493 | 5762 | int_tag_type: Index, |
| ... | ... | @@ -5505,16 +5774,15 @@ pub const EnumExplicit = struct { |
| 5505 | 5774 | |
| 5506 | 5775 | /// Trailing: |
| 5507 | 5776 | /// 0. owner_union: Index // if `zir_index == .none` |
| 5508 | /// 1. capture: CaptureValue // for each `captures_len` | |
| 5509 | /// 2. type_hash: PackedU64 // if reified (`captures_len == std.math.maxInt(u32)`) | |
| 5510 | /// 3. field name: NullTerminatedString for each fields_len; declaration order | |
| 5777 | /// 1. cau: Cau.Index // if `zir_index != .none` | |
| 5778 | /// 2. capture: CaptureValue // for each `captures_len` | |
| 5779 | /// 3. type_hash: PackedU64 // if reified (`captures_len == std.math.maxInt(u32)`) | |
| 5780 | /// 4. field name: NullTerminatedString for each fields_len; declaration order | |
| 5511 | 5781 | pub const EnumAuto = struct { |
| 5512 | /// The Decl that corresponds to the enum itself. | |
| 5513 | decl: DeclIndex, | |
| 5782 | name: NullTerminatedString, | |
| 5514 | 5783 | /// `std.math.maxInt(u32)` indicates this type is reified. |
| 5515 | 5784 | captures_len: u32, |
| 5516 | /// This may be `none` if there are no declarations. | |
| 5517 | namespace: OptionalNamespaceIndex, | |
| 5785 | namespace: NamespaceIndex, | |
| 5518 | 5786 | /// An integer type which is used for the numerical value of the enum, which |
| 5519 | 5787 | /// was inferred by Zig based on the number of tags. |
| 5520 | 5788 | int_tag_type: Index, |
| ... | ... | @@ -5539,15 +5807,15 @@ pub const PackedU64 = packed struct(u64) { |
| 5539 | 5807 | } |
| 5540 | 5808 | }; |
| 5541 | 5809 | |
| 5542 | pub const PtrDecl = struct { | |
| 5810 | pub const PtrNav = struct { | |
| 5543 | 5811 | ty: Index, |
| 5544 | decl: DeclIndex, | |
| 5812 | nav: Nav.Index, | |
| 5545 | 5813 | byte_offset_a: u32, |
| 5546 | 5814 | byte_offset_b: u32, |
| 5547 | fn init(ty: Index, decl: DeclIndex, byte_offset: u64) @This() { | |
| 5815 | fn init(ty: Index, nav: Nav.Index, byte_offset: u64) @This() { | |
| 5548 | 5816 | return .{ |
| 5549 | 5817 | .ty = ty, |
| 5550 | .decl = decl, | |
| 5818 | .nav = nav, | |
| 5551 | 5819 | .byte_offset_a = @intCast(byte_offset >> 32), |
| 5552 | 5820 | .byte_offset_b = @truncate(byte_offset), |
| 5553 | 5821 | }; |
| ... | ... | @@ -5557,7 +5825,7 @@ pub const PtrDecl = struct { |
| 5557 | 5825 | } |
| 5558 | 5826 | }; |
| 5559 | 5827 | |
| 5560 | pub const PtrAnonDecl = struct { | |
| 5828 | pub const PtrUav = struct { | |
| 5561 | 5829 | ty: Index, |
| 5562 | 5830 | val: Index, |
| 5563 | 5831 | byte_offset_a: u32, |
| ... | ... | @@ -5575,7 +5843,7 @@ pub const PtrAnonDecl = struct { |
| 5575 | 5843 | } |
| 5576 | 5844 | }; |
| 5577 | 5845 | |
| 5578 | pub const PtrAnonDeclAligned = struct { | |
| 5846 | pub const PtrUavAligned = struct { | |
| 5579 | 5847 | ty: Index, |
| 5580 | 5848 | val: Index, |
| 5581 | 5849 | /// Must be nonequal to `ty`. Only the alignment from this value is important. |
| ... | ... | @@ -5805,8 +6073,9 @@ pub fn init(ip: *InternPool, gpa: Allocator, available_threads: usize) !void { |
| 5805 | 6073 | .tracked_insts = Local.TrackedInsts.empty, |
| 5806 | 6074 | .files = Local.List(File).empty, |
| 5807 | 6075 | .maps = Local.Maps.empty, |
| 6076 | .caus = Local.Caus.empty, | |
| 6077 | .navs = Local.Navs.empty, | |
| 5808 | 6078 | |
| 5809 | .decls = Local.Decls.empty, | |
| 5810 | 6079 | .namespaces = Local.Namespaces.empty, |
| 5811 | 6080 | }, |
| 5812 | 6081 | .mutate = .{ |
| ... | ... | @@ -5819,8 +6088,9 @@ pub fn init(ip: *InternPool, gpa: Allocator, available_threads: usize) !void { |
| 5819 | 6088 | .tracked_insts = Local.ListMutate.empty, |
| 5820 | 6089 | .files = Local.ListMutate.empty, |
| 5821 | 6090 | .maps = Local.ListMutate.empty, |
| 6091 | .caus = Local.ListMutate.empty, | |
| 6092 | .navs = Local.ListMutate.empty, | |
| 5822 | 6093 | |
| 5823 | .decls = Local.BucketListMutate.empty, | |
| 5824 | 6094 | .namespaces = Local.BucketListMutate.empty, |
| 5825 | 6095 | }, |
| 5826 | 6096 | }); |
| ... | ... | @@ -5878,8 +6148,8 @@ pub fn init(ip: *InternPool, gpa: Allocator, available_threads: usize) !void { |
| 5878 | 6148 | |
| 5879 | 6149 | pub fn deinit(ip: *InternPool, gpa: Allocator) void { |
| 5880 | 6150 | ip.src_hash_deps.deinit(gpa); |
| 5881 | ip.decl_val_deps.deinit(gpa); | |
| 5882 | ip.func_ies_deps.deinit(gpa); | |
| 6151 | ip.nav_val_deps.deinit(gpa); | |
| 6152 | ip.interned_deps.deinit(gpa); | |
| 5883 | 6153 | ip.namespace_deps.deinit(gpa); |
| 5884 | 6154 | ip.namespace_name_deps.deinit(gpa); |
| 5885 | 6155 | |
| ... | ... | @@ -5900,8 +6170,11 @@ pub fn deinit(ip: *InternPool, gpa: Allocator) void { |
| 5900 | 6170 | else |
| 5901 | 6171 | local.mutate.namespaces.last_bucket_len]) |*namespace| |
| 5902 | 6172 | { |
| 5903 | namespace.decls.deinit(gpa); | |
| 5904 | namespace.usingnamespace_set.deinit(gpa); | |
| 6173 | namespace.pub_decls.deinit(gpa); | |
| 6174 | namespace.priv_decls.deinit(gpa); | |
| 6175 | namespace.pub_usingnamespace.deinit(gpa); | |
| 6176 | namespace.priv_usingnamespace.deinit(gpa); | |
| 6177 | namespace.other_decls.deinit(gpa); | |
| 5905 | 6178 | } |
| 5906 | 6179 | }; |
| 5907 | 6180 | const maps = local.getMutableMaps(gpa); |
| ... | ... | @@ -6082,14 +6355,14 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key { |
| 6082 | 6355 | if (extra.data.captures_len == std.math.maxInt(u32)) { |
| 6083 | 6356 | break :ns .{ .reified = .{ |
| 6084 | 6357 | .zir_index = zir_index, |
| 6085 | .type_hash = extraData(extra_list, PackedU64, extra.end).get(), | |
| 6358 | .type_hash = extraData(extra_list, PackedU64, extra.end + 1).get(), | |
| 6086 | 6359 | } }; |
| 6087 | 6360 | } |
| 6088 | 6361 | break :ns .{ .declared = .{ |
| 6089 | 6362 | .zir_index = zir_index, |
| 6090 | 6363 | .captures = .{ .owned = .{ |
| 6091 | 6364 | .tid = unwrapped_index.tid, |
| 6092 | .start = extra.end, | |
| 6365 | .start = extra.end + 1, | |
| 6093 | 6366 | .len = extra.data.captures_len, |
| 6094 | 6367 | } }, |
| 6095 | 6368 | } }; |
| ... | ... | @@ -6106,14 +6379,14 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key { |
| 6106 | 6379 | if (extra.data.captures_len == std.math.maxInt(u32)) { |
| 6107 | 6380 | break :ns .{ .reified = .{ |
| 6108 | 6381 | .zir_index = zir_index, |
| 6109 | .type_hash = extraData(extra_list, PackedU64, extra.end).get(), | |
| 6382 | .type_hash = extraData(extra_list, PackedU64, extra.end + 1).get(), | |
| 6110 | 6383 | } }; |
| 6111 | 6384 | } |
| 6112 | 6385 | break :ns .{ .declared = .{ |
| 6113 | 6386 | .zir_index = zir_index, |
| 6114 | 6387 | .captures = .{ .owned = .{ |
| 6115 | 6388 | .tid = unwrapped_index.tid, |
| 6116 | .start = extra.end, | |
| 6389 | .start = extra.end + 1, | |
| 6117 | 6390 | .len = extra.data.captures_len, |
| 6118 | 6391 | } }, |
| 6119 | 6392 | } }; |
| ... | ... | @@ -6132,24 +6405,24 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key { |
| 6132 | 6405 | .val = extra.val, |
| 6133 | 6406 | } }; |
| 6134 | 6407 | }, |
| 6135 | .ptr_decl => { | |
| 6136 | const info = extraData(unwrapped_index.getExtra(ip), PtrDecl, data); | |
| 6137 | return .{ .ptr = .{ .ty = info.ty, .base_addr = .{ .decl = info.decl }, .byte_offset = info.byteOffset() } }; | |
| 6408 | .ptr_nav => { | |
| 6409 | const info = extraData(unwrapped_index.getExtra(ip), PtrNav, data); | |
| 6410 | return .{ .ptr = .{ .ty = info.ty, .base_addr = .{ .nav = info.nav }, .byte_offset = info.byteOffset() } }; | |
| 6138 | 6411 | }, |
| 6139 | 6412 | .ptr_comptime_alloc => { |
| 6140 | 6413 | const info = extraData(unwrapped_index.getExtra(ip), PtrComptimeAlloc, data); |
| 6141 | 6414 | return .{ .ptr = .{ .ty = info.ty, .base_addr = .{ .comptime_alloc = info.index }, .byte_offset = info.byteOffset() } }; |
| 6142 | 6415 | }, |
| 6143 | .ptr_anon_decl => { | |
| 6144 | const info = extraData(unwrapped_index.getExtra(ip), PtrAnonDecl, data); | |
| 6145 | return .{ .ptr = .{ .ty = info.ty, .base_addr = .{ .anon_decl = .{ | |
| 6416 | .ptr_uav => { | |
| 6417 | const info = extraData(unwrapped_index.getExtra(ip), PtrUav, data); | |
| 6418 | return .{ .ptr = .{ .ty = info.ty, .base_addr = .{ .uav = .{ | |
| 6146 | 6419 | .val = info.val, |
| 6147 | 6420 | .orig_ty = info.ty, |
| 6148 | 6421 | } }, .byte_offset = info.byteOffset() } }; |
| 6149 | 6422 | }, |
| 6150 | .ptr_anon_decl_aligned => { | |
| 6151 | const info = extraData(unwrapped_index.getExtra(ip), PtrAnonDeclAligned, data); | |
| 6152 | return .{ .ptr = .{ .ty = info.ty, .base_addr = .{ .anon_decl = .{ | |
| 6423 | .ptr_uav_aligned => { | |
| 6424 | const info = extraData(unwrapped_index.getExtra(ip), PtrUavAligned, data); | |
| 6425 | return .{ .ptr = .{ .ty = info.ty, .base_addr = .{ .uav = .{ | |
| 6153 | 6426 | .val = info.val, |
| 6154 | 6427 | .orig_ty = info.orig_ty, |
| 6155 | 6428 | } }, .byte_offset = info.byteOffset() } }; |
| ... | ... | @@ -6293,15 +6566,28 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key { |
| 6293 | 6566 | return .{ .variable = .{ |
| 6294 | 6567 | .ty = extra.ty, |
| 6295 | 6568 | .init = extra.init, |
| 6296 | .decl = extra.decl, | |
| 6569 | .owner_nav = extra.owner_nav, | |
| 6570 | .lib_name = extra.lib_name, | |
| 6571 | .is_threadlocal = extra.flags.is_threadlocal, | |
| 6572 | .is_weak_linkage = extra.flags.is_weak_linkage, | |
| 6573 | } }; | |
| 6574 | }, | |
| 6575 | .@"extern" => { | |
| 6576 | const extra = extraData(unwrapped_index.getExtra(ip), Tag.Extern, data); | |
| 6577 | const nav = ip.getNav(extra.owner_nav); | |
| 6578 | return .{ .@"extern" = .{ | |
| 6579 | .name = nav.name, | |
| 6580 | .ty = extra.ty, | |
| 6297 | 6581 | .lib_name = extra.lib_name, |
| 6298 | .is_extern = extra.flags.is_extern, | |
| 6299 | 6582 | .is_const = extra.flags.is_const, |
| 6300 | 6583 | .is_threadlocal = extra.flags.is_threadlocal, |
| 6301 | 6584 | .is_weak_linkage = extra.flags.is_weak_linkage, |
| 6585 | .alignment = nav.status.resolved.alignment, | |
| 6586 | .@"addrspace" = nav.status.resolved.@"addrspace", | |
| 6587 | .zir_index = extra.zir_index, | |
| 6588 | .owner_nav = extra.owner_nav, | |
| 6302 | 6589 | } }; |
| 6303 | 6590 | }, |
| 6304 | .extern_func => .{ .extern_func = extraData(unwrapped_index.getExtra(ip), Tag.ExternFunc, data) }, | |
| 6305 | 6591 | .func_instance => .{ .func = ip.extraFuncInstance(unwrapped_index.tid, unwrapped_index.getExtra(ip), data) }, |
| 6306 | 6592 | .func_decl => .{ .func = extraFuncDecl(unwrapped_index.tid, unwrapped_index.getExtra(ip), data) }, |
| 6307 | 6593 | .func_coerced => .{ .func = ip.extraFuncCoerced(unwrapped_index.getExtra(ip), data) }, |
| ... | ... | @@ -6513,7 +6799,7 @@ fn extraFuncDecl(tid: Zcu.PerThread.Id, extra: Local.Extra, extra_index: u32) Ke |
| 6513 | 6799 | .zir_body_inst_extra_index = extra_index + std.meta.fieldIndex(P, "zir_body_inst").?, |
| 6514 | 6800 | .resolved_error_set_extra_index = if (func_decl.data.analysis.inferred_error_set) func_decl.end else 0, |
| 6515 | 6801 | .branch_quota_extra_index = 0, |
| 6516 | .owner_decl = func_decl.data.owner_decl, | |
| 6802 | .owner_nav = func_decl.data.owner_nav, | |
| 6517 | 6803 | .zir_body_inst = func_decl.data.zir_body_inst, |
| 6518 | 6804 | .lbrace_line = func_decl.data.lbrace_line, |
| 6519 | 6805 | .rbrace_line = func_decl.data.rbrace_line, |
| ... | ... | @@ -6528,7 +6814,7 @@ fn extraFuncInstance(ip: *const InternPool, tid: Zcu.PerThread.Id, extra: Local. |
| 6528 | 6814 | const extra_items = extra.view().items(.@"0"); |
| 6529 | 6815 | const analysis_extra_index = extra_index + std.meta.fieldIndex(Tag.FuncInstance, "analysis").?; |
| 6530 | 6816 | const analysis: FuncAnalysis = @bitCast(@atomicLoad(u32, &extra_items[analysis_extra_index], .unordered)); |
| 6531 | const owner_decl: DeclIndex = @enumFromInt(extra_items[extra_index + std.meta.fieldIndex(Tag.FuncInstance, "owner_decl").?]); | |
| 6817 | const owner_nav: Nav.Index = @enumFromInt(extra_items[extra_index + std.meta.fieldIndex(Tag.FuncInstance, "owner_nav").?]); | |
| 6532 | 6818 | const ty: Index = @enumFromInt(extra_items[extra_index + std.meta.fieldIndex(Tag.FuncInstance, "ty").?]); |
| 6533 | 6819 | const generic_owner: Index = @enumFromInt(extra_items[extra_index + std.meta.fieldIndex(Tag.FuncInstance, "generic_owner").?]); |
| 6534 | 6820 | const func_decl = ip.funcDeclInfo(generic_owner); |
| ... | ... | @@ -6541,7 +6827,7 @@ fn extraFuncInstance(ip: *const InternPool, tid: Zcu.PerThread.Id, extra: Local. |
| 6541 | 6827 | .zir_body_inst_extra_index = func_decl.zir_body_inst_extra_index, |
| 6542 | 6828 | .resolved_error_set_extra_index = if (analysis.inferred_error_set) end_extra_index else 0, |
| 6543 | 6829 | .branch_quota_extra_index = extra_index + std.meta.fieldIndex(Tag.FuncInstance, "branch_quota").?, |
| 6544 | .owner_decl = owner_decl, | |
| 6830 | .owner_nav = owner_nav, | |
| 6545 | 6831 | .zir_body_inst = func_decl.zir_body_inst, |
| 6546 | 6832 | .lbrace_line = func_decl.lbrace_line, |
| 6547 | 6833 | .rbrace_line = func_decl.rbrace_line, |
| ... | ... | @@ -6905,7 +7191,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, tid: Zcu.PerThread.Id, key: Key) All |
| 6905 | 7191 | |
| 6906 | 7192 | .enum_type => unreachable, // use getEnumType() instead |
| 6907 | 7193 | .func_type => unreachable, // use getFuncType() instead |
| 6908 | .extern_func => unreachable, // use getExternFunc() instead | |
| 7194 | .@"extern" => unreachable, // use getExtern() instead | |
| 6909 | 7195 | .func => unreachable, // use getFuncInstance() or getFuncDecl() instead |
| 6910 | 7196 | |
| 6911 | 7197 | .variable => |variable| { |
| ... | ... | @@ -6916,11 +7202,10 @@ pub fn get(ip: *InternPool, gpa: Allocator, tid: Zcu.PerThread.Id, key: Key) All |
| 6916 | 7202 | .data = try addExtra(extra, Tag.Variable{ |
| 6917 | 7203 | .ty = variable.ty, |
| 6918 | 7204 | .init = variable.init, |
| 6919 | .decl = variable.decl, | |
| 7205 | .owner_nav = variable.owner_nav, | |
| 6920 | 7206 | .lib_name = variable.lib_name, |
| 6921 | 7207 | .flags = .{ |
| 6922 | .is_extern = variable.is_extern, | |
| 6923 | .is_const = variable.is_const, | |
| 7208 | .is_const = false, | |
| 6924 | 7209 | .is_threadlocal = variable.is_threadlocal, |
| 6925 | 7210 | .is_weak_linkage = variable.is_weak_linkage, |
| 6926 | 7211 | }, |
| ... | ... | @@ -6945,29 +7230,29 @@ pub fn get(ip: *InternPool, gpa: Allocator, tid: Zcu.PerThread.Id, key: Key) All |
| 6945 | 7230 | const ptr_type = ip.indexToKey(ptr.ty).ptr_type; |
| 6946 | 7231 | assert(ptr_type.flags.size != .Slice); |
| 6947 | 7232 | items.appendAssumeCapacity(switch (ptr.base_addr) { |
| 6948 | .decl => |decl| .{ | |
| 6949 | .tag = .ptr_decl, | |
| 6950 | .data = try addExtra(extra, PtrDecl.init(ptr.ty, decl, ptr.byte_offset)), | |
| 7233 | .nav => |nav| .{ | |
| 7234 | .tag = .ptr_nav, | |
| 7235 | .data = try addExtra(extra, PtrNav.init(ptr.ty, nav, ptr.byte_offset)), | |
| 6951 | 7236 | }, |
| 6952 | 7237 | .comptime_alloc => |alloc_index| .{ |
| 6953 | 7238 | .tag = .ptr_comptime_alloc, |
| 6954 | 7239 | .data = try addExtra(extra, PtrComptimeAlloc.init(ptr.ty, alloc_index, ptr.byte_offset)), |
| 6955 | 7240 | }, |
| 6956 | .anon_decl => |anon_decl| if (ptrsHaveSameAlignment(ip, ptr.ty, ptr_type, anon_decl.orig_ty)) item: { | |
| 6957 | if (ptr.ty != anon_decl.orig_ty) { | |
| 7241 | .uav => |uav| if (ptrsHaveSameAlignment(ip, ptr.ty, ptr_type, uav.orig_ty)) item: { | |
| 7242 | if (ptr.ty != uav.orig_ty) { | |
| 6958 | 7243 | gop.cancel(); |
| 6959 | 7244 | var new_key = key; |
| 6960 | new_key.ptr.base_addr.anon_decl.orig_ty = ptr.ty; | |
| 7245 | new_key.ptr.base_addr.uav.orig_ty = ptr.ty; | |
| 6961 | 7246 | gop = try ip.getOrPutKey(gpa, tid, new_key); |
| 6962 | 7247 | if (gop == .existing) return gop.existing; |
| 6963 | 7248 | } |
| 6964 | 7249 | break :item .{ |
| 6965 | .tag = .ptr_anon_decl, | |
| 6966 | .data = try addExtra(extra, PtrAnonDecl.init(ptr.ty, anon_decl.val, ptr.byte_offset)), | |
| 7250 | .tag = .ptr_uav, | |
| 7251 | .data = try addExtra(extra, PtrUav.init(ptr.ty, uav.val, ptr.byte_offset)), | |
| 6967 | 7252 | }; |
| 6968 | 7253 | } else .{ |
| 6969 | .tag = .ptr_anon_decl_aligned, | |
| 6970 | .data = try addExtra(extra, PtrAnonDeclAligned.init(ptr.ty, anon_decl.val, anon_decl.orig_ty, ptr.byte_offset)), | |
| 7254 | .tag = .ptr_uav_aligned, | |
| 7255 | .data = try addExtra(extra, PtrUavAligned.init(ptr.ty, uav.val, uav.orig_ty, ptr.byte_offset)), | |
| 6971 | 7256 | }, |
| 6972 | 7257 | .comptime_field => |field_val| item: { |
| 6973 | 7258 | assert(field_val != .none); |
| ... | ... | @@ -7561,7 +7846,6 @@ pub const UnionTypeInit = struct { |
| 7561 | 7846 | assumed_pointer_aligned: bool, |
| 7562 | 7847 | alignment: Alignment, |
| 7563 | 7848 | }, |
| 7564 | has_namespace: bool, | |
| 7565 | 7849 | fields_len: u32, |
| 7566 | 7850 | enum_tag_ty: Index, |
| 7567 | 7851 | /// May have length 0 which leaves the values unset until later. |
| ... | ... | @@ -7635,8 +7919,9 @@ pub fn getUnionType( |
| 7635 | 7919 | .fields_len = ini.fields_len, |
| 7636 | 7920 | .size = std.math.maxInt(u32), |
| 7637 | 7921 | .padding = std.math.maxInt(u32), |
| 7638 | .decl = undefined, // set by `finish` | |
| 7639 | .namespace = .none, // set by `finish` | |
| 7922 | .name = undefined, // set by `finish` | |
| 7923 | .cau = undefined, // set by `finish` | |
| 7924 | .namespace = undefined, // set by `finish` | |
| 7640 | 7925 | .tag_ty = ini.enum_tag_ty, |
| 7641 | 7926 | .zir_index = switch (ini.key) { |
| 7642 | 7927 | inline else => |x| x.zir_index, |
| ... | ... | @@ -7682,29 +7967,49 @@ pub fn getUnionType( |
| 7682 | 7967 | return .{ .wip = .{ |
| 7683 | 7968 | .tid = tid, |
| 7684 | 7969 | .index = gop.put(), |
| 7685 | .decl_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeUnion, "decl").?, | |
| 7686 | .namespace_extra_index = if (ini.has_namespace) | |
| 7687 | extra_index + std.meta.fieldIndex(Tag.TypeUnion, "namespace").? | |
| 7688 | else | |
| 7689 | null, | |
| 7970 | .type_name_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeUnion, "name").?, | |
| 7971 | .cau_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeUnion, "cau").?, | |
| 7972 | .namespace_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeUnion, "namespace").?, | |
| 7690 | 7973 | } }; |
| 7691 | 7974 | } |
| 7692 | 7975 | |
| 7693 | 7976 | pub const WipNamespaceType = struct { |
| 7694 | 7977 | tid: Zcu.PerThread.Id, |
| 7695 | 7978 | index: Index, |
| 7696 | decl_extra_index: u32, | |
| 7697 | namespace_extra_index: ?u32, | |
| 7698 | pub fn finish(wip: WipNamespaceType, ip: *InternPool, decl: DeclIndex, namespace: OptionalNamespaceIndex) Index { | |
| 7699 | const extra_items = ip.getLocalShared(wip.tid).extra.acquire().view().items(.@"0"); | |
| 7700 | extra_items[wip.decl_extra_index] = @intFromEnum(decl); | |
| 7701 | if (wip.namespace_extra_index) |i| { | |
| 7702 | extra_items[i] = @intFromEnum(namespace.unwrap().?); | |
| 7979 | type_name_extra_index: u32, | |
| 7980 | cau_extra_index: ?u32, | |
| 7981 | namespace_extra_index: u32, | |
| 7982 | ||
| 7983 | pub fn setName( | |
| 7984 | wip: WipNamespaceType, | |
| 7985 | ip: *InternPool, | |
| 7986 | type_name: NullTerminatedString, | |
| 7987 | ) void { | |
| 7988 | const extra = ip.getLocalShared(wip.tid).extra.acquire(); | |
| 7989 | const extra_items = extra.view().items(.@"0"); | |
| 7990 | extra_items[wip.type_name_extra_index] = @intFromEnum(type_name); | |
| 7991 | } | |
| 7992 | ||
| 7993 | pub fn finish( | |
| 7994 | wip: WipNamespaceType, | |
| 7995 | ip: *InternPool, | |
| 7996 | analysis_owner: Cau.Index.Optional, | |
| 7997 | namespace: NamespaceIndex, | |
| 7998 | ) Index { | |
| 7999 | const extra = ip.getLocalShared(wip.tid).extra.acquire(); | |
| 8000 | const extra_items = extra.view().items(.@"0"); | |
| 8001 | ||
| 8002 | if (wip.cau_extra_index) |i| { | |
| 8003 | extra_items[i] = @intFromEnum(analysis_owner.unwrap().?); | |
| 7703 | 8004 | } else { |
| 7704 | assert(namespace == .none); | |
| 8005 | assert(analysis_owner == .none); | |
| 7705 | 8006 | } |
| 8007 | ||
| 8008 | extra_items[wip.namespace_extra_index] = @intFromEnum(namespace); | |
| 8009 | ||
| 7706 | 8010 | return wip.index; |
| 7707 | 8011 | } |
| 8012 | ||
| 7708 | 8013 | pub fn cancel(wip: WipNamespaceType, ip: *InternPool, tid: Zcu.PerThread.Id) void { |
| 7709 | 8014 | ip.remove(tid, wip.index); |
| 7710 | 8015 | } |
| ... | ... | @@ -7725,7 +8030,6 @@ pub const StructTypeInit = struct { |
| 7725 | 8030 | any_default_inits: bool, |
| 7726 | 8031 | inits_resolved: bool, |
| 7727 | 8032 | any_aligned_fields: bool, |
| 7728 | has_namespace: bool, | |
| 7729 | 8033 | key: union(enum) { |
| 7730 | 8034 | declared: struct { |
| 7731 | 8035 | zir_index: TrackedInst.Index, |
| ... | ... | @@ -7784,10 +8088,11 @@ pub fn getStructType( |
| 7784 | 8088 | ini.fields_len + // names |
| 7785 | 8089 | ini.fields_len); // inits |
| 7786 | 8090 | const extra_index = addExtraAssumeCapacity(extra, Tag.TypeStructPacked{ |
| 7787 | .decl = undefined, // set by `finish` | |
| 8091 | .name = undefined, // set by `finish` | |
| 8092 | .cau = undefined, // set by `finish` | |
| 7788 | 8093 | .zir_index = zir_index, |
| 7789 | 8094 | .fields_len = ini.fields_len, |
| 7790 | .namespace = .none, | |
| 8095 | .namespace = undefined, // set by `finish` | |
| 7791 | 8096 | .backing_int_ty = .none, |
| 7792 | 8097 | .names_map = names_map, |
| 7793 | 8098 | .flags = .{ |
| ... | ... | @@ -7818,11 +8123,9 @@ pub fn getStructType( |
| 7818 | 8123 | return .{ .wip = .{ |
| 7819 | 8124 | .tid = tid, |
| 7820 | 8125 | .index = gop.put(), |
| 7821 | .decl_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeStructPacked, "decl").?, | |
| 7822 | .namespace_extra_index = if (ini.has_namespace) | |
| 7823 | extra_index + std.meta.fieldIndex(Tag.TypeStructPacked, "namespace").? | |
| 7824 | else | |
| 7825 | null, | |
| 8126 | .type_name_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeStructPacked, "name").?, | |
| 8127 | .cau_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeStructPacked, "cau").?, | |
| 8128 | .namespace_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeStructPacked, "namespace").?, | |
| 7826 | 8129 | } }; |
| 7827 | 8130 | }, |
| 7828 | 8131 | }; |
| ... | ... | @@ -7841,10 +8144,12 @@ pub fn getStructType( |
| 7841 | 8144 | // zig fmt: on |
| 7842 | 8145 | (ini.fields_len * 5) + // types, names, inits, runtime order, offsets |
| 7843 | 8146 | align_elements_len + comptime_elements_len + |
| 7844 | 2); // names_map + namespace | |
| 8147 | 1); // names_map | |
| 7845 | 8148 | const extra_index = addExtraAssumeCapacity(extra, Tag.TypeStruct{ |
| 7846 | .decl = undefined, // set by `finish` | |
| 8149 | .name = undefined, // set by `finish` | |
| 8150 | .cau = undefined, // set by `finish` | |
| 7847 | 8151 | .zir_index = zir_index, |
| 8152 | .namespace = undefined, // set by `finish` | |
| 7848 | 8153 | .fields_len = ini.fields_len, |
| 7849 | 8154 | .size = std.math.maxInt(u32), |
| 7850 | 8155 | .flags = .{ |
| ... | ... | @@ -7855,7 +8160,6 @@ pub fn getStructType( |
| 7855 | 8160 | .is_tuple = ini.is_tuple, |
| 7856 | 8161 | .assumed_runtime_bits = false, |
| 7857 | 8162 | .assumed_pointer_aligned = false, |
| 7858 | .has_namespace = ini.has_namespace, | |
| 7859 | 8163 | .any_comptime_fields = ini.any_comptime_fields, |
| 7860 | 8164 | .any_default_inits = ini.any_default_inits, |
| 7861 | 8165 | .any_aligned_fields = ini.any_aligned_fields, |
| ... | ... | @@ -7891,10 +8195,6 @@ pub fn getStructType( |
| 7891 | 8195 | if (ini.any_default_inits) { |
| 7892 | 8196 | extra.appendNTimesAssumeCapacity(.{@intFromEnum(Index.none)}, ini.fields_len); |
| 7893 | 8197 | } |
| 7894 | const namespace_extra_index: ?u32 = if (ini.has_namespace) i: { | |
| 7895 | extra.appendAssumeCapacity(undefined); // set by `finish` | |
| 7896 | break :i @intCast(extra.mutate.len - 1); | |
| 7897 | } else null; | |
| 7898 | 8198 | if (ini.any_aligned_fields) { |
| 7899 | 8199 | extra.appendNTimesAssumeCapacity(.{align_element}, align_elements_len); |
| 7900 | 8200 | } |
| ... | ... | @@ -7908,8 +8208,9 @@ pub fn getStructType( |
| 7908 | 8208 | return .{ .wip = .{ |
| 7909 | 8209 | .tid = tid, |
| 7910 | 8210 | .index = gop.put(), |
| 7911 | .decl_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeStruct, "decl").?, | |
| 7912 | .namespace_extra_index = namespace_extra_index, | |
| 8211 | .type_name_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeStruct, "name").?, | |
| 8212 | .cau_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeStruct, "cau").?, | |
| 8213 | .namespace_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeStruct, "namespace").?, | |
| 7913 | 8214 | } }; |
| 7914 | 8215 | } |
| 7915 | 8216 | |
| ... | ... | @@ -8047,34 +8348,71 @@ pub fn getFuncType( |
| 8047 | 8348 | return gop.put(); |
| 8048 | 8349 | } |
| 8049 | 8350 | |
| 8050 | pub fn getExternFunc( | |
| 8351 | /// Intern an `.@"extern"`, creating a corresponding owner `Nav` if necessary. | |
| 8352 | /// This will *not* queue the extern for codegen: see `Zcu.PerThread.getExtern` for a wrapper which does. | |
| 8353 | pub fn getExtern( | |
| 8051 | 8354 | ip: *InternPool, |
| 8052 | 8355 | gpa: Allocator, |
| 8053 | 8356 | tid: Zcu.PerThread.Id, |
| 8054 | key: Key.ExternFunc, | |
| 8055 | ) Allocator.Error!Index { | |
| 8056 | var gop = try ip.getOrPutKey(gpa, tid, .{ .extern_func = key }); | |
| 8357 | /// `key.owner_nav` is ignored. | |
| 8358 | key: Key.Extern, | |
| 8359 | ) Allocator.Error!struct { | |
| 8360 | index: Index, | |
| 8361 | /// Only set if the `Nav` was newly created. | |
| 8362 | new_nav: Nav.Index.Optional, | |
| 8363 | } { | |
| 8364 | var gop = try ip.getOrPutKey(gpa, tid, .{ .@"extern" = key }); | |
| 8057 | 8365 | defer gop.deinit(); |
| 8058 | if (gop == .existing) return gop.existing; | |
| 8366 | if (gop == .existing) return .{ | |
| 8367 | .index = gop.existing, | |
| 8368 | .new_nav = .none, | |
| 8369 | }; | |
| 8059 | 8370 | |
| 8060 | 8371 | const local = ip.getLocal(tid); |
| 8061 | 8372 | const items = local.getMutableItems(gpa); |
| 8062 | try items.ensureUnusedCapacity(1); | |
| 8063 | 8373 | const extra = local.getMutableExtra(gpa); |
| 8374 | try items.ensureUnusedCapacity(1); | |
| 8375 | try extra.ensureUnusedCapacity(@typeInfo(Tag.Extern).Struct.fields.len); | |
| 8376 | try local.getMutableNavs(gpa).ensureUnusedCapacity(1); | |
| 8064 | 8377 | |
| 8065 | const prev_extra_len = extra.mutate.len; | |
| 8066 | const extra_index = try addExtra(extra, @as(Tag.ExternFunc, key)); | |
| 8067 | errdefer extra.mutate.len = prev_extra_len; | |
| 8378 | // Predict the index the `@"extern" will live at, so we can construct the owner `Nav` before releasing the shard's mutex. | |
| 8379 | const extern_index = Index.Unwrapped.wrap(.{ | |
| 8380 | .tid = tid, | |
| 8381 | .index = items.mutate.len, | |
| 8382 | }, ip); | |
| 8383 | const owner_nav = ip.createNav(gpa, tid, .{ | |
| 8384 | .name = key.name, | |
| 8385 | .fqn = key.name, | |
| 8386 | .val = extern_index, | |
| 8387 | .alignment = key.alignment, | |
| 8388 | .@"linksection" = .none, | |
| 8389 | .@"addrspace" = key.@"addrspace", | |
| 8390 | }) catch unreachable; // capacity asserted above | |
| 8391 | const extra_index = addExtraAssumeCapacity(extra, Tag.Extern{ | |
| 8392 | .ty = key.ty, | |
| 8393 | .lib_name = key.lib_name, | |
| 8394 | .flags = .{ | |
| 8395 | .is_const = key.is_const, | |
| 8396 | .is_threadlocal = key.is_threadlocal, | |
| 8397 | .is_weak_linkage = key.is_weak_linkage, | |
| 8398 | }, | |
| 8399 | .zir_index = key.zir_index, | |
| 8400 | .owner_nav = owner_nav, | |
| 8401 | }); | |
| 8068 | 8402 | items.appendAssumeCapacity(.{ |
| 8069 | .tag = .extern_func, | |
| 8403 | .tag = .@"extern", | |
| 8070 | 8404 | .data = extra_index, |
| 8071 | 8405 | }); |
| 8072 | errdefer items.mutate.len -= 1; | |
| 8073 | return gop.put(); | |
| 8406 | assert(gop.put() == extern_index); | |
| 8407 | ||
| 8408 | return .{ | |
| 8409 | .index = extern_index, | |
| 8410 | .new_nav = owner_nav.toOptional(), | |
| 8411 | }; | |
| 8074 | 8412 | } |
| 8075 | 8413 | |
| 8076 | 8414 | pub const GetFuncDeclKey = struct { |
| 8077 | owner_decl: DeclIndex, | |
| 8415 | owner_nav: Nav.Index, | |
| 8078 | 8416 | ty: Index, |
| 8079 | 8417 | zir_body_inst: TrackedInst.Index, |
| 8080 | 8418 | lbrace_line: u32, |
| ... | ... | @@ -8105,7 +8443,7 @@ pub fn getFuncDecl( |
| 8105 | 8443 | |
| 8106 | 8444 | const func_decl_extra_index = addExtraAssumeCapacity(extra, Tag.FuncDecl{ |
| 8107 | 8445 | .analysis = .{ |
| 8108 | .state = if (key.cc == .Inline) .inline_only else .none, | |
| 8446 | .state = .unreferenced, | |
| 8109 | 8447 | .is_cold = false, |
| 8110 | 8448 | .is_noinline = key.is_noinline, |
| 8111 | 8449 | .calls_or_awaits_errorable_fn = false, |
| ... | ... | @@ -8113,7 +8451,7 @@ pub fn getFuncDecl( |
| 8113 | 8451 | .inferred_error_set = false, |
| 8114 | 8452 | .disable_instrumentation = false, |
| 8115 | 8453 | }, |
| 8116 | .owner_decl = key.owner_decl, | |
| 8454 | .owner_nav = key.owner_nav, | |
| 8117 | 8455 | .ty = key.ty, |
| 8118 | 8456 | .zir_body_inst = key.zir_body_inst, |
| 8119 | 8457 | .lbrace_line = key.lbrace_line, |
| ... | ... | @@ -8140,7 +8478,7 @@ pub fn getFuncDecl( |
| 8140 | 8478 | } |
| 8141 | 8479 | |
| 8142 | 8480 | pub const GetFuncDeclIesKey = struct { |
| 8143 | owner_decl: DeclIndex, | |
| 8481 | owner_nav: Nav.Index, | |
| 8144 | 8482 | param_types: []Index, |
| 8145 | 8483 | noalias_bits: u32, |
| 8146 | 8484 | comptime_bits: u32, |
| ... | ... | @@ -8209,7 +8547,7 @@ pub fn getFuncDeclIes( |
| 8209 | 8547 | |
| 8210 | 8548 | const func_decl_extra_index = addExtraAssumeCapacity(extra, Tag.FuncDecl{ |
| 8211 | 8549 | .analysis = .{ |
| 8212 | .state = if (key.cc == .Inline) .inline_only else .none, | |
| 8550 | .state = .unreferenced, | |
| 8213 | 8551 | .is_cold = false, |
| 8214 | 8552 | .is_noinline = key.is_noinline, |
| 8215 | 8553 | .calls_or_awaits_errorable_fn = false, |
| ... | ... | @@ -8217,7 +8555,7 @@ pub fn getFuncDeclIes( |
| 8217 | 8555 | .inferred_error_set = true, |
| 8218 | 8556 | .disable_instrumentation = false, |
| 8219 | 8557 | }, |
| 8220 | .owner_decl = key.owner_decl, | |
| 8558 | .owner_nav = key.owner_nav, | |
| 8221 | 8559 | .ty = func_ty, |
| 8222 | 8560 | .zir_body_inst = key.zir_body_inst, |
| 8223 | 8561 | .lbrace_line = key.lbrace_line, |
| ... | ... | @@ -8401,7 +8739,7 @@ pub fn getFuncInstance( |
| 8401 | 8739 | |
| 8402 | 8740 | const func_extra_index = addExtraAssumeCapacity(extra, Tag.FuncInstance{ |
| 8403 | 8741 | .analysis = .{ |
| 8404 | .state = if (arg.cc == .Inline) .inline_only else .none, | |
| 8742 | .state = .unreferenced, | |
| 8405 | 8743 | .is_cold = false, |
| 8406 | 8744 | .is_noinline = arg.is_noinline, |
| 8407 | 8745 | .calls_or_awaits_errorable_fn = false, |
| ... | ... | @@ -8409,9 +8747,9 @@ pub fn getFuncInstance( |
| 8409 | 8747 | .inferred_error_set = false, |
| 8410 | 8748 | .disable_instrumentation = false, |
| 8411 | 8749 | }, |
| 8412 | // This is populated after we create the Decl below. It is not read | |
| 8750 | // This is populated after we create the Nav below. It is not read | |
| 8413 | 8751 | // by equality or hashing functions. |
| 8414 | .owner_decl = undefined, | |
| 8752 | .owner_nav = undefined, | |
| 8415 | 8753 | .ty = func_ty, |
| 8416 | 8754 | .branch_quota = 0, |
| 8417 | 8755 | .generic_owner = generic_owner, |
| ... | ... | @@ -8501,7 +8839,7 @@ pub fn getFuncInstanceIes( |
| 8501 | 8839 | |
| 8502 | 8840 | const func_extra_index = addExtraAssumeCapacity(extra, Tag.FuncInstance{ |
| 8503 | 8841 | .analysis = .{ |
| 8504 | .state = if (arg.cc == .Inline) .inline_only else .none, | |
| 8842 | .state = .unreferenced, | |
| 8505 | 8843 | .is_cold = false, |
| 8506 | 8844 | .is_noinline = arg.is_noinline, |
| 8507 | 8845 | .calls_or_awaits_errorable_fn = false, |
| ... | ... | @@ -8509,9 +8847,9 @@ pub fn getFuncInstanceIes( |
| 8509 | 8847 | .inferred_error_set = true, |
| 8510 | 8848 | .disable_instrumentation = false, |
| 8511 | 8849 | }, |
| 8512 | // This is populated after we create the Decl below. It is not read | |
| 8850 | // This is populated after we create the Nav below. It is not read | |
| 8513 | 8851 | // by equality or hashing functions. |
| 8514 | .owner_decl = undefined, | |
| 8852 | .owner_nav = undefined, | |
| 8515 | 8853 | .ty = func_ty, |
| 8516 | 8854 | .branch_quota = 0, |
| 8517 | 8855 | .generic_owner = generic_owner, |
| ... | ... | @@ -8617,41 +8955,29 @@ fn finishFuncInstance( |
| 8617 | 8955 | alignment: Alignment, |
| 8618 | 8956 | section: OptionalNullTerminatedString, |
| 8619 | 8957 | ) Allocator.Error!void { |
| 8620 | const fn_owner_decl = ip.declPtr(ip.funcDeclOwner(generic_owner)); | |
| 8621 | const decl_index = try ip.createDecl(gpa, tid, .{ | |
| 8622 | .name = undefined, | |
| 8623 | .fqn = undefined, | |
| 8624 | .src_namespace = fn_owner_decl.src_namespace, | |
| 8625 | .has_tv = true, | |
| 8626 | .owns_tv = true, | |
| 8627 | .val = @import("Value.zig").fromInterned(func_index), | |
| 8958 | const fn_owner_nav = ip.getNav(ip.funcDeclInfo(generic_owner).owner_nav); | |
| 8959 | const fn_namespace = ip.getCau(fn_owner_nav.analysis_owner.unwrap().?).namespace; | |
| 8960 | ||
| 8961 | // TODO: improve this name | |
| 8962 | const nav_name = try ip.getOrPutStringFmt(gpa, tid, "{}__anon_{d}", .{ | |
| 8963 | fn_owner_nav.name.fmt(ip), @intFromEnum(func_index), | |
| 8964 | }, .no_embedded_nulls); | |
| 8965 | const nav_index = try ip.createNav(gpa, tid, .{ | |
| 8966 | .name = nav_name, | |
| 8967 | .fqn = try ip.namespacePtr(fn_namespace).internFullyQualifiedName(ip, gpa, tid, nav_name), | |
| 8968 | .val = func_index, | |
| 8628 | 8969 | .alignment = alignment, |
| 8629 | 8970 | .@"linksection" = section, |
| 8630 | .@"addrspace" = fn_owner_decl.@"addrspace", | |
| 8631 | .analysis = .complete, | |
| 8632 | .zir_decl_index = fn_owner_decl.zir_decl_index, | |
| 8633 | .is_pub = fn_owner_decl.is_pub, | |
| 8634 | .is_exported = fn_owner_decl.is_exported, | |
| 8635 | .kind = .anon, | |
| 8971 | .@"addrspace" = fn_owner_nav.status.resolved.@"addrspace", | |
| 8636 | 8972 | }); |
| 8637 | errdefer ip.destroyDecl(tid, decl_index); | |
| 8638 | 8973 | |
| 8639 | // Populate the owner_decl field which was left undefined until now. | |
| 8974 | // Populate the owner_nav field which was left undefined until now. | |
| 8640 | 8975 | extra.view().items(.@"0")[ |
| 8641 | func_extra_index + std.meta.fieldIndex(Tag.FuncInstance, "owner_decl").? | |
| 8642 | ] = @intFromEnum(decl_index); | |
| 8643 | ||
| 8644 | // TODO: improve this name | |
| 8645 | const decl = ip.declPtr(decl_index); | |
| 8646 | decl.name = try ip.getOrPutStringFmt(gpa, tid, "{}__anon_{d}", .{ | |
| 8647 | fn_owner_decl.name.fmt(ip), @intFromEnum(decl_index), | |
| 8648 | }, .no_embedded_nulls); | |
| 8649 | decl.fqn = try ip.namespacePtr(fn_owner_decl.src_namespace) | |
| 8650 | .internFullyQualifiedName(ip, gpa, tid, decl.name); | |
| 8976 | func_extra_index + std.meta.fieldIndex(Tag.FuncInstance, "owner_nav").? | |
| 8977 | ] = @intFromEnum(nav_index); | |
| 8651 | 8978 | } |
| 8652 | 8979 | |
| 8653 | 8980 | pub const EnumTypeInit = struct { |
| 8654 | has_namespace: bool, | |
| 8655 | 8981 | has_values: bool, |
| 8656 | 8982 | tag_mode: LoadedEnumType.TagMode, |
| 8657 | 8983 | fields_len: u32, |
| ... | ... | @@ -8671,27 +8997,35 @@ pub const WipEnumType = struct { |
| 8671 | 8997 | tid: Zcu.PerThread.Id, |
| 8672 | 8998 | index: Index, |
| 8673 | 8999 | tag_ty_index: u32, |
| 8674 | decl_index: u32, | |
| 8675 | namespace_index: ?u32, | |
| 9000 | type_name_extra_index: u32, | |
| 9001 | cau_extra_index: u32, | |
| 9002 | namespace_extra_index: u32, | |
| 8676 | 9003 | names_map: MapIndex, |
| 8677 | 9004 | names_start: u32, |
| 8678 | 9005 | values_map: OptionalMapIndex, |
| 8679 | 9006 | values_start: u32, |
| 8680 | 9007 | |
| 9008 | pub fn setName( | |
| 9009 | wip: WipEnumType, | |
| 9010 | ip: *InternPool, | |
| 9011 | type_name: NullTerminatedString, | |
| 9012 | ) void { | |
| 9013 | const extra = ip.getLocalShared(wip.tid).extra.acquire(); | |
| 9014 | const extra_items = extra.view().items(.@"0"); | |
| 9015 | extra_items[wip.type_name_extra_index] = @intFromEnum(type_name); | |
| 9016 | } | |
| 9017 | ||
| 8681 | 9018 | pub fn prepare( |
| 8682 | 9019 | wip: WipEnumType, |
| 8683 | 9020 | ip: *InternPool, |
| 8684 | decl: DeclIndex, | |
| 8685 | namespace: OptionalNamespaceIndex, | |
| 9021 | analysis_owner: Cau.Index, | |
| 9022 | namespace: NamespaceIndex, | |
| 8686 | 9023 | ) void { |
| 8687 | 9024 | const extra = ip.getLocalShared(wip.tid).extra.acquire(); |
| 8688 | 9025 | const extra_items = extra.view().items(.@"0"); |
| 8689 | extra_items[wip.decl_index] = @intFromEnum(decl); | |
| 8690 | if (wip.namespace_index) |i| { | |
| 8691 | extra_items[i] = @intFromEnum(namespace.unwrap().?); | |
| 8692 | } else { | |
| 8693 | assert(namespace == .none); | |
| 8694 | } | |
| 9026 | ||
| 9027 | extra_items[wip.cau_extra_index] = @intFromEnum(analysis_owner); | |
| 9028 | extra_items[wip.namespace_extra_index] = @intFromEnum(namespace); | |
| 8695 | 9029 | } |
| 8696 | 9030 | |
| 8697 | 9031 | pub fn setTagTy(wip: WipEnumType, ip: *InternPool, tag_ty: Index) void { |
| ... | ... | @@ -8780,15 +9114,16 @@ pub fn getEnumType( |
| 8780 | 9114 | .reified => 2, // type_hash: PackedU64 |
| 8781 | 9115 | } + |
| 8782 | 9116 | // zig fmt: on |
| 9117 | 1 + // cau | |
| 8783 | 9118 | ini.fields_len); // field types |
| 8784 | 9119 | |
| 8785 | 9120 | const extra_index = addExtraAssumeCapacity(extra, EnumAuto{ |
| 8786 | .decl = undefined, // set by `prepare` | |
| 9121 | .name = undefined, // set by `prepare` | |
| 8787 | 9122 | .captures_len = switch (ini.key) { |
| 8788 | 9123 | .declared => |d| @intCast(d.captures.len), |
| 8789 | 9124 | .reified => std.math.maxInt(u32), |
| 8790 | 9125 | }, |
| 8791 | .namespace = .none, | |
| 9126 | .namespace = undefined, // set by `prepare` | |
| 8792 | 9127 | .int_tag_type = .none, // set by `prepare` |
| 8793 | 9128 | .fields_len = ini.fields_len, |
| 8794 | 9129 | .names_map = names_map, |
| ... | ... | @@ -8800,6 +9135,8 @@ pub fn getEnumType( |
| 8800 | 9135 | .tag = .type_enum_auto, |
| 8801 | 9136 | .data = extra_index, |
| 8802 | 9137 | }); |
| 9138 | const cau_extra_index = extra.view().len; | |
| 9139 | extra.appendAssumeCapacity(undefined); // `cau` will be set by `finish` | |
| 8803 | 9140 | switch (ini.key) { |
| 8804 | 9141 | .declared => |d| extra.appendSliceAssumeCapacity(.{@ptrCast(d.captures)}), |
| 8805 | 9142 | .reified => |r| _ = addExtraAssumeCapacity(extra, PackedU64.init(r.type_hash)), |
| ... | ... | @@ -8810,8 +9147,9 @@ pub fn getEnumType( |
| 8810 | 9147 | .tid = tid, |
| 8811 | 9148 | .index = gop.put(), |
| 8812 | 9149 | .tag_ty_index = extra_index + std.meta.fieldIndex(EnumAuto, "int_tag_type").?, |
| 8813 | .decl_index = extra_index + std.meta.fieldIndex(EnumAuto, "decl").?, | |
| 8814 | .namespace_index = if (ini.has_namespace) extra_index + std.meta.fieldIndex(EnumAuto, "namespace").? else null, | |
| 9150 | .type_name_extra_index = extra_index + std.meta.fieldIndex(EnumAuto, "name").?, | |
| 9151 | .cau_extra_index = @intCast(cau_extra_index), | |
| 9152 | .namespace_extra_index = extra_index + std.meta.fieldIndex(EnumAuto, "namespace").?, | |
| 8815 | 9153 | .names_map = names_map, |
| 8816 | 9154 | .names_start = @intCast(names_start), |
| 8817 | 9155 | .values_map = .none, |
| ... | ... | @@ -8835,16 +9173,17 @@ pub fn getEnumType( |
| 8835 | 9173 | .reified => 2, // type_hash: PackedU64 |
| 8836 | 9174 | } + |
| 8837 | 9175 | // zig fmt: on |
| 9176 | 1 + // cau | |
| 8838 | 9177 | ini.fields_len + // field types |
| 8839 | 9178 | ini.fields_len * @intFromBool(ini.has_values)); // field values |
| 8840 | 9179 | |
| 8841 | 9180 | const extra_index = addExtraAssumeCapacity(extra, EnumExplicit{ |
| 8842 | .decl = undefined, // set by `prepare` | |
| 9181 | .name = undefined, // set by `prepare` | |
| 8843 | 9182 | .captures_len = switch (ini.key) { |
| 8844 | 9183 | .declared => |d| @intCast(d.captures.len), |
| 8845 | 9184 | .reified => std.math.maxInt(u32), |
| 8846 | 9185 | }, |
| 8847 | .namespace = .none, | |
| 9186 | .namespace = undefined, // set by `prepare` | |
| 8848 | 9187 | .int_tag_type = .none, // set by `prepare` |
| 8849 | 9188 | .fields_len = ini.fields_len, |
| 8850 | 9189 | .names_map = names_map, |
| ... | ... | @@ -8861,6 +9200,8 @@ pub fn getEnumType( |
| 8861 | 9200 | }, |
| 8862 | 9201 | .data = extra_index, |
| 8863 | 9202 | }); |
| 9203 | const cau_extra_index = extra.view().len; | |
| 9204 | extra.appendAssumeCapacity(undefined); // `cau` will be set by `finish` | |
| 8864 | 9205 | switch (ini.key) { |
| 8865 | 9206 | .declared => |d| extra.appendSliceAssumeCapacity(.{@ptrCast(d.captures)}), |
| 8866 | 9207 | .reified => |r| _ = addExtraAssumeCapacity(extra, PackedU64.init(r.type_hash)), |
| ... | ... | @@ -8874,9 +9215,10 @@ pub fn getEnumType( |
| 8874 | 9215 | return .{ .wip = .{ |
| 8875 | 9216 | .tid = tid, |
| 8876 | 9217 | .index = gop.put(), |
| 8877 | .tag_ty_index = extra_index + std.meta.fieldIndex(EnumAuto, "int_tag_type").?, | |
| 8878 | .decl_index = extra_index + std.meta.fieldIndex(EnumAuto, "decl").?, | |
| 8879 | .namespace_index = if (ini.has_namespace) extra_index + std.meta.fieldIndex(EnumAuto, "namespace").? else null, | |
| 9218 | .tag_ty_index = extra_index + std.meta.fieldIndex(EnumExplicit, "int_tag_type").?, | |
| 9219 | .type_name_extra_index = extra_index + std.meta.fieldIndex(EnumExplicit, "name").?, | |
| 9220 | .cau_extra_index = @intCast(cau_extra_index), | |
| 9221 | .namespace_extra_index = extra_index + std.meta.fieldIndex(EnumExplicit, "namespace").?, | |
| 8880 | 9222 | .names_map = names_map, |
| 8881 | 9223 | .names_start = @intCast(names_start), |
| 8882 | 9224 | .values_map = values_map, |
| ... | ... | @@ -8887,12 +9229,13 @@ pub fn getEnumType( |
| 8887 | 9229 | } |
| 8888 | 9230 | |
| 8889 | 9231 | const GeneratedTagEnumTypeInit = struct { |
| 8890 | decl: DeclIndex, | |
| 9232 | name: NullTerminatedString, | |
| 8891 | 9233 | owner_union_ty: Index, |
| 8892 | 9234 | tag_ty: Index, |
| 8893 | 9235 | names: []const NullTerminatedString, |
| 8894 | 9236 | values: []const Index, |
| 8895 | 9237 | tag_mode: LoadedEnumType.TagMode, |
| 9238 | parent_namespace: NamespaceIndex, | |
| 8896 | 9239 | }; |
| 8897 | 9240 | |
| 8898 | 9241 | /// Creates an enum type which was automatically-generated as the tag type of a |
| ... | ... | @@ -8919,6 +9262,18 @@ pub fn getGeneratedTagEnumType( |
| 8919 | 9262 | |
| 8920 | 9263 | const fields_len: u32 = @intCast(ini.names.len); |
| 8921 | 9264 | |
| 9265 | // Predict the index the enum will live at so we can construct the namespace before releasing the shard's mutex. | |
| 9266 | const enum_index = Index.Unwrapped.wrap(.{ | |
| 9267 | .tid = tid, | |
| 9268 | .index = items.mutate.len, | |
| 9269 | }, ip); | |
| 9270 | const namespace = try ip.createNamespace(gpa, tid, .{ | |
| 9271 | .parent = ini.parent_namespace.toOptional(), | |
| 9272 | .owner_type = enum_index, | |
| 9273 | .file_scope = ip.namespacePtr(ini.parent_namespace).file_scope, | |
| 9274 | }); | |
| 9275 | errdefer ip.destroyNamespace(tid, namespace); | |
| 9276 | ||
| 8922 | 9277 | const prev_extra_len = extra.mutate.len; |
| 8923 | 9278 | switch (ini.tag_mode) { |
| 8924 | 9279 | .auto => { |
| ... | ... | @@ -8928,9 +9283,9 @@ pub fn getGeneratedTagEnumType( |
| 8928 | 9283 | items.appendAssumeCapacity(.{ |
| 8929 | 9284 | .tag = .type_enum_auto, |
| 8930 | 9285 | .data = addExtraAssumeCapacity(extra, EnumAuto{ |
| 8931 | .decl = ini.decl, | |
| 9286 | .name = ini.name, | |
| 8932 | 9287 | .captures_len = 0, |
| 8933 | .namespace = .none, | |
| 9288 | .namespace = namespace, | |
| 8934 | 9289 | .int_tag_type = ini.tag_ty, |
| 8935 | 9290 | .fields_len = fields_len, |
| 8936 | 9291 | .names_map = names_map, |
| ... | ... | @@ -8961,9 +9316,9 @@ pub fn getGeneratedTagEnumType( |
| 8961 | 9316 | .auto => unreachable, |
| 8962 | 9317 | }, |
| 8963 | 9318 | .data = addExtraAssumeCapacity(extra, EnumExplicit{ |
| 8964 | .decl = ini.decl, | |
| 9319 | .name = ini.name, | |
| 8965 | 9320 | .captures_len = 0, |
| 8966 | .namespace = .none, | |
| 9321 | .namespace = namespace, | |
| 8967 | 9322 | .int_tag_type = ini.tag_ty, |
| 8968 | 9323 | .fields_len = fields_len, |
| 8969 | 9324 | .names_map = names_map, |
| ... | ... | @@ -8988,11 +9343,11 @@ pub fn getGeneratedTagEnumType( |
| 8988 | 9343 | .generated_tag = .{ .union_type = ini.owner_union_ty }, |
| 8989 | 9344 | } }); |
| 8990 | 9345 | defer gop.deinit(); |
| 8991 | return gop.put(); | |
| 9346 | assert(gop.put() == enum_index); | |
| 9347 | return enum_index; | |
| 8992 | 9348 | } |
| 8993 | 9349 | |
| 8994 | 9350 | pub const OpaqueTypeInit = struct { |
| 8995 | has_namespace: bool, | |
| 8996 | 9351 | key: union(enum) { |
| 8997 | 9352 | declared: struct { |
| 8998 | 9353 | zir_index: TrackedInst.Index, |
| ... | ... | @@ -9034,8 +9389,8 @@ pub fn getOpaqueType( |
| 9034 | 9389 | .reified => 0, |
| 9035 | 9390 | }); |
| 9036 | 9391 | const extra_index = addExtraAssumeCapacity(extra, Tag.TypeOpaque{ |
| 9037 | .decl = undefined, // set by `finish` | |
| 9038 | .namespace = .none, | |
| 9392 | .name = undefined, // set by `finish` | |
| 9393 | .namespace = undefined, // set by `finish` | |
| 9039 | 9394 | .zir_index = switch (ini.key) { |
| 9040 | 9395 | inline else => |x| x.zir_index, |
| 9041 | 9396 | }, |
| ... | ... | @@ -9052,15 +9407,15 @@ pub fn getOpaqueType( |
| 9052 | 9407 | .declared => |d| extra.appendSliceAssumeCapacity(.{@ptrCast(d.captures)}), |
| 9053 | 9408 | .reified => {}, |
| 9054 | 9409 | } |
| 9055 | return .{ .wip = .{ | |
| 9056 | .tid = tid, | |
| 9057 | .index = gop.put(), | |
| 9058 | .decl_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeOpaque, "decl").?, | |
| 9059 | .namespace_extra_index = if (ini.has_namespace) | |
| 9060 | extra_index + std.meta.fieldIndex(Tag.TypeOpaque, "namespace").? | |
| 9061 | else | |
| 9062 | null, | |
| 9063 | } }; | |
| 9410 | return .{ | |
| 9411 | .wip = .{ | |
| 9412 | .tid = tid, | |
| 9413 | .index = gop.put(), | |
| 9414 | .type_name_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeOpaque, "name").?, | |
| 9415 | .cau_extra_index = null, // opaques do not undergo type resolution | |
| 9416 | .namespace_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeOpaque, "namespace").?, | |
| 9417 | }, | |
| 9418 | }; | |
| 9064 | 9419 | } |
| 9065 | 9420 | |
| 9066 | 9421 | pub fn getIfExists(ip: *const InternPool, key: Key) ?Index { |
| ... | ... | @@ -9181,7 +9536,8 @@ fn addExtraAssumeCapacity(extra: Local.Extra.Mutable, item: anytype) u32 { |
| 9181 | 9536 | inline for (@typeInfo(@TypeOf(item)).Struct.fields) |field| { |
| 9182 | 9537 | extra.appendAssumeCapacity(.{switch (field.type) { |
| 9183 | 9538 | Index, |
| 9184 | DeclIndex, | |
| 9539 | Cau.Index, | |
| 9540 | Nav.Index, | |
| 9185 | 9541 | NamespaceIndex, |
| 9186 | 9542 | OptionalNamespaceIndex, |
| 9187 | 9543 | MapIndex, |
| ... | ... | @@ -9244,7 +9600,8 @@ fn extraDataTrail(extra: Local.Extra, comptime T: type, index: u32) struct { dat |
| 9244 | 9600 | const extra_item = extra_items[extra_index]; |
| 9245 | 9601 | @field(result, field.name) = switch (field.type) { |
| 9246 | 9602 | Index, |
| 9247 | DeclIndex, | |
| 9603 | Cau.Index, | |
| 9604 | Nav.Index, | |
| 9248 | 9605 | NamespaceIndex, |
| 9249 | 9606 | OptionalNamespaceIndex, |
| 9250 | 9607 | MapIndex, |
| ... | ... | @@ -9436,12 +9793,6 @@ pub fn getCoerced( |
| 9436 | 9793 | |
| 9437 | 9794 | switch (ip.indexToKey(val)) { |
| 9438 | 9795 | .undef => return ip.get(gpa, tid, .{ .undef = new_ty }), |
| 9439 | .extern_func => |extern_func| if (ip.isFunctionType(new_ty)) | |
| 9440 | return ip.getExternFunc(gpa, tid, .{ | |
| 9441 | .ty = new_ty, | |
| 9442 | .decl = extern_func.decl, | |
| 9443 | .lib_name = extern_func.lib_name, | |
| 9444 | }), | |
| 9445 | 9796 | .func => unreachable, |
| 9446 | 9797 | |
| 9447 | 9798 | .int => |int| switch (ip.indexToKey(new_ty)) { |
| ... | ... | @@ -9858,27 +10209,23 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void { |
| 9858 | 10209 | var items_len: usize = 0; |
| 9859 | 10210 | var extra_len: usize = 0; |
| 9860 | 10211 | var limbs_len: usize = 0; |
| 9861 | var decls_len: usize = 0; | |
| 9862 | 10212 | for (ip.locals) |*local| { |
| 9863 | 10213 | items_len += local.mutate.items.len; |
| 9864 | 10214 | extra_len += local.mutate.extra.len; |
| 9865 | 10215 | limbs_len += local.mutate.limbs.len; |
| 9866 | decls_len += local.mutate.decls.buckets_list.len; | |
| 9867 | 10216 | } |
| 9868 | 10217 | const items_size = (1 + 4) * items_len; |
| 9869 | 10218 | const extra_size = 4 * extra_len; |
| 9870 | 10219 | const limbs_size = 8 * limbs_len; |
| 9871 | const decls_size = @sizeOf(Zcu.Decl) * decls_len; | |
| 9872 | 10220 | |
| 9873 | 10221 | // TODO: map overhead size is not taken into account |
| 9874 | const total_size = @sizeOf(InternPool) + items_size + extra_size + limbs_size + decls_size; | |
| 10222 | const total_size = @sizeOf(InternPool) + items_size + extra_size + limbs_size; | |
| 9875 | 10223 | |
| 9876 | 10224 | std.debug.print( |
| 9877 | 10225 | \\InternPool size: {d} bytes |
| 9878 | 10226 | \\ {d} items: {d} bytes |
| 9879 | 10227 | \\ {d} extra: {d} bytes |
| 9880 | 10228 | \\ {d} limbs: {d} bytes |
| 9881 | \\ {d} decls: {d} bytes | |
| 9882 | 10229 | \\ |
| 9883 | 10230 | , .{ |
| 9884 | 10231 | total_size, |
| ... | ... | @@ -9888,8 +10235,6 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void { |
| 9888 | 10235 | extra_size, |
| 9889 | 10236 | limbs_len, |
| 9890 | 10237 | limbs_size, |
| 9891 | decls_len, | |
| 9892 | decls_size, | |
| 9893 | 10238 | }); |
| 9894 | 10239 | |
| 9895 | 10240 | const TagStats = struct { |
| ... | ... | @@ -9967,7 +10312,6 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void { |
| 9967 | 10312 | } |
| 9968 | 10313 | if (info.flags.any_default_inits) |
| 9969 | 10314 | ints += info.fields_len; // inits |
| 9970 | ints += @intFromBool(info.flags.has_namespace); // namespace | |
| 9971 | 10315 | if (info.flags.any_aligned_fields) |
| 9972 | 10316 | ints += (info.fields_len + 3) / 4; // aligns |
| 9973 | 10317 | if (info.flags.any_comptime_fields) |
| ... | ... | @@ -10034,10 +10378,10 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void { |
| 10034 | 10378 | .undef => 0, |
| 10035 | 10379 | .simple_type => 0, |
| 10036 | 10380 | .simple_value => 0, |
| 10037 | .ptr_decl => @sizeOf(PtrDecl), | |
| 10381 | .ptr_nav => @sizeOf(PtrNav), | |
| 10038 | 10382 | .ptr_comptime_alloc => @sizeOf(PtrComptimeAlloc), |
| 10039 | .ptr_anon_decl => @sizeOf(PtrAnonDecl), | |
| 10040 | .ptr_anon_decl_aligned => @sizeOf(PtrAnonDeclAligned), | |
| 10383 | .ptr_uav => @sizeOf(PtrUav), | |
| 10384 | .ptr_uav_aligned => @sizeOf(PtrUavAligned), | |
| 10041 | 10385 | .ptr_comptime_field => @sizeOf(PtrComptimeField), |
| 10042 | 10386 | .ptr_int => @sizeOf(PtrInt), |
| 10043 | 10387 | .ptr_eu_payload => @sizeOf(PtrBase), |
| ... | ... | @@ -10092,7 +10436,7 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void { |
| 10092 | 10436 | .float_c_longdouble_f128 => @sizeOf(Float128), |
| 10093 | 10437 | .float_comptime_float => @sizeOf(Float128), |
| 10094 | 10438 | .variable => @sizeOf(Tag.Variable), |
| 10095 | .extern_func => @sizeOf(Tag.ExternFunc), | |
| 10439 | .@"extern" => @sizeOf(Tag.Extern), | |
| 10096 | 10440 | .func_decl => @sizeOf(Tag.FuncDecl), |
| 10097 | 10441 | .func_instance => b: { |
| 10098 | 10442 | const info = extraData(extra_list, Tag.FuncInstance, data); |
| ... | ... | @@ -10171,10 +10515,10 @@ fn dumpAllFallible(ip: *const InternPool) anyerror!void { |
| 10171 | 10515 | .type_union, |
| 10172 | 10516 | .type_function, |
| 10173 | 10517 | .undef, |
| 10174 | .ptr_decl, | |
| 10518 | .ptr_nav, | |
| 10175 | 10519 | .ptr_comptime_alloc, |
| 10176 | .ptr_anon_decl, | |
| 10177 | .ptr_anon_decl_aligned, | |
| 10520 | .ptr_uav, | |
| 10521 | .ptr_uav_aligned, | |
| 10178 | 10522 | .ptr_comptime_field, |
| 10179 | 10523 | .ptr_int, |
| 10180 | 10524 | .ptr_eu_payload, |
| ... | ... | @@ -10212,7 +10556,7 @@ fn dumpAllFallible(ip: *const InternPool) anyerror!void { |
| 10212 | 10556 | .float_c_longdouble_f128, |
| 10213 | 10557 | .float_comptime_float, |
| 10214 | 10558 | .variable, |
| 10215 | .extern_func, | |
| 10559 | .@"extern", | |
| 10216 | 10560 | .func_decl, |
| 10217 | 10561 | .func_instance, |
| 10218 | 10562 | .func_coerced, |
| ... | ... | @@ -10275,13 +10619,13 @@ pub fn dumpGenericInstancesFallible(ip: *const InternPool, allocator: Allocator) |
| 10275 | 10619 | instances.sort(SortContext{ .values = instances.values() }); |
| 10276 | 10620 | var it = instances.iterator(); |
| 10277 | 10621 | while (it.next()) |entry| { |
| 10278 | const generic_fn_owner_decl = ip.declPtrConst(ip.funcDeclOwner(entry.key_ptr.*)); | |
| 10279 | try w.print("{} ({}): \n", .{ generic_fn_owner_decl.name.fmt(ip), entry.value_ptr.items.len }); | |
| 10622 | const generic_fn_owner_nav = ip.getNav(ip.funcDeclInfo(entry.key_ptr.*).owner_nav); | |
| 10623 | try w.print("{} ({}): \n", .{ generic_fn_owner_nav.name.fmt(ip), entry.value_ptr.items.len }); | |
| 10280 | 10624 | for (entry.value_ptr.items) |index| { |
| 10281 | 10625 | const unwrapped_index = index.unwrap(ip); |
| 10282 | 10626 | const func = ip.extraFuncInstance(unwrapped_index.tid, unwrapped_index.getExtra(ip), unwrapped_index.getData(ip)); |
| 10283 | const owner_decl = ip.declPtrConst(func.owner_decl); | |
| 10284 | try w.print(" {}: (", .{owner_decl.name.fmt(ip)}); | |
| 10627 | const owner_nav = ip.getNav(func.owner_nav); | |
| 10628 | try w.print(" {}: (", .{owner_nav.name.fmt(ip)}); | |
| 10285 | 10629 | for (func.comptime_args.get(ip)) |arg| { |
| 10286 | 10630 | if (arg != .none) { |
| 10287 | 10631 | const key = ip.indexToKey(arg); |
| ... | ... | @@ -10295,66 +10639,183 @@ pub fn dumpGenericInstancesFallible(ip: *const InternPool, allocator: Allocator) |
| 10295 | 10639 | try bw.flush(); |
| 10296 | 10640 | } |
| 10297 | 10641 | |
| 10298 | pub fn declPtr(ip: *InternPool, decl_index: DeclIndex) *Zcu.Decl { | |
| 10299 | return @constCast(ip.declPtrConst(decl_index)); | |
| 10642 | pub fn getCau(ip: *const InternPool, index: Cau.Index) Cau { | |
| 10643 | const unwrapped = index.unwrap(ip); | |
| 10644 | const caus = ip.getLocalShared(unwrapped.tid).caus.acquire(); | |
| 10645 | return caus.view().items(.@"0")[unwrapped.index]; | |
| 10300 | 10646 | } |
| 10301 | 10647 | |
| 10302 | pub fn declPtrConst(ip: *const InternPool, decl_index: DeclIndex) *const Zcu.Decl { | |
| 10303 | const unwrapped_decl_index = decl_index.unwrap(ip); | |
| 10304 | const decls = ip.getLocalShared(unwrapped_decl_index.tid).decls.acquire(); | |
| 10305 | const decls_bucket = decls.view().items(.@"0")[unwrapped_decl_index.bucket_index]; | |
| 10306 | return &decls_bucket[unwrapped_decl_index.index]; | |
| 10648 | pub fn getNav(ip: *const InternPool, index: Nav.Index) Nav { | |
| 10649 | const unwrapped = index.unwrap(ip); | |
| 10650 | const navs = ip.getLocalShared(unwrapped.tid).navs.acquire(); | |
| 10651 | return navs.view().get(unwrapped.index).unpack(); | |
| 10652 | } | |
| 10653 | ||
| 10654 | pub fn namespacePtr(ip: *InternPool, namespace_index: NamespaceIndex) *Zcu.Namespace { | |
| 10655 | const unwrapped_namespace_index = namespace_index.unwrap(ip); | |
| 10656 | const namespaces = ip.getLocalShared(unwrapped_namespace_index.tid).namespaces.acquire(); | |
| 10657 | const namespaces_bucket = namespaces.view().items(.@"0")[unwrapped_namespace_index.bucket_index]; | |
| 10658 | return &namespaces_bucket[unwrapped_namespace_index.index]; | |
| 10307 | 10659 | } |
| 10308 | 10660 | |
| 10309 | pub fn createDecl( | |
| 10661 | /// Create a `Cau` associated with the type at the given `InternPool.Index`. | |
| 10662 | pub fn createTypeCau( | |
| 10310 | 10663 | ip: *InternPool, |
| 10311 | 10664 | gpa: Allocator, |
| 10312 | 10665 | tid: Zcu.PerThread.Id, |
| 10313 | initialization: Zcu.Decl, | |
| 10314 | ) Allocator.Error!DeclIndex { | |
| 10315 | const local = ip.getLocal(tid); | |
| 10316 | const free_list_next = local.mutate.decls.free_list; | |
| 10317 | if (free_list_next != Local.BucketListMutate.free_list_sentinel) { | |
| 10318 | const reused_decl_index: DeclIndex = @enumFromInt(free_list_next); | |
| 10319 | const reused_decl = ip.declPtr(reused_decl_index); | |
| 10320 | local.mutate.decls.free_list = @intFromEnum(@field(reused_decl, Local.decl_next_free_field)); | |
| 10321 | reused_decl.* = initialization; | |
| 10322 | return reused_decl_index; | |
| 10323 | } | |
| 10324 | const decls = local.getMutableDecls(gpa); | |
| 10325 | if (local.mutate.decls.last_bucket_len == 0) { | |
| 10326 | try decls.ensureUnusedCapacity(1); | |
| 10327 | var arena = decls.arena.promote(decls.gpa); | |
| 10328 | defer decls.arena.* = arena.state; | |
| 10329 | decls.appendAssumeCapacity(.{try arena.allocator().create( | |
| 10330 | [1 << Local.decls_bucket_width]Zcu.Decl, | |
| 10331 | )}); | |
| 10332 | } | |
| 10333 | const unwrapped_decl_index: DeclIndex.Unwrapped = .{ | |
| 10666 | zir_index: TrackedInst.Index, | |
| 10667 | namespace: NamespaceIndex, | |
| 10668 | owner_type: InternPool.Index, | |
| 10669 | ) Allocator.Error!Cau.Index { | |
| 10670 | const caus = ip.getLocal(tid).getMutableCaus(gpa); | |
| 10671 | const index_unwrapped: Cau.Index.Unwrapped = .{ | |
| 10334 | 10672 | .tid = tid, |
| 10335 | .bucket_index = decls.mutate.len - 1, | |
| 10336 | .index = local.mutate.decls.last_bucket_len, | |
| 10673 | .index = caus.mutate.len, | |
| 10337 | 10674 | }; |
| 10338 | local.mutate.decls.last_bucket_len = | |
| 10339 | (unwrapped_decl_index.index + 1) & Local.namespaces_bucket_mask; | |
| 10340 | const decl_index = unwrapped_decl_index.wrap(ip); | |
| 10341 | ip.declPtr(decl_index).* = initialization; | |
| 10342 | return decl_index; | |
| 10675 | try caus.append(.{.{ | |
| 10676 | .zir_index = zir_index, | |
| 10677 | .namespace = namespace, | |
| 10678 | .owner = Cau.Owner.wrap(.{ .type = owner_type }), | |
| 10679 | }}); | |
| 10680 | return index_unwrapped.wrap(ip); | |
| 10343 | 10681 | } |
| 10344 | 10682 | |
| 10345 | pub fn destroyDecl(ip: *InternPool, tid: Zcu.PerThread.Id, decl_index: DeclIndex) void { | |
| 10346 | const local = ip.getLocal(tid); | |
| 10347 | const decl = ip.declPtr(decl_index); | |
| 10348 | decl.* = undefined; | |
| 10349 | @field(decl, Local.decl_next_free_field) = @enumFromInt(local.mutate.decls.free_list); | |
| 10350 | local.mutate.decls.free_list = @intFromEnum(decl_index); | |
| 10683 | /// Create a `Cau` for a `comptime` declaration. | |
| 10684 | pub fn createComptimeCau( | |
| 10685 | ip: *InternPool, | |
| 10686 | gpa: Allocator, | |
| 10687 | tid: Zcu.PerThread.Id, | |
| 10688 | zir_index: TrackedInst.Index, | |
| 10689 | namespace: NamespaceIndex, | |
| 10690 | ) Allocator.Error!Cau.Index { | |
| 10691 | const caus = ip.getLocal(tid).getMutableCaus(gpa); | |
| 10692 | const index_unwrapped: Cau.Index.Unwrapped = .{ | |
| 10693 | .tid = tid, | |
| 10694 | .index = caus.mutate.len, | |
| 10695 | }; | |
| 10696 | try caus.append(.{.{ | |
| 10697 | .zir_index = zir_index, | |
| 10698 | .namespace = namespace, | |
| 10699 | .owner = Cau.Owner.wrap(.none), | |
| 10700 | }}); | |
| 10701 | return index_unwrapped.wrap(ip); | |
| 10351 | 10702 | } |
| 10352 | 10703 | |
| 10353 | pub fn namespacePtr(ip: *InternPool, namespace_index: NamespaceIndex) *Zcu.Namespace { | |
| 10354 | const unwrapped_namespace_index = namespace_index.unwrap(ip); | |
| 10355 | const namespaces = ip.getLocalShared(unwrapped_namespace_index.tid).namespaces.acquire(); | |
| 10356 | const namespaces_bucket = namespaces.view().items(.@"0")[unwrapped_namespace_index.bucket_index]; | |
| 10357 | return &namespaces_bucket[unwrapped_namespace_index.index]; | |
| 10704 | /// Create a `Nav` not associated with any `Cau`. | |
| 10705 | /// Since there is no analysis owner, the `Nav`'s value must be known at creation time. | |
| 10706 | pub fn createNav( | |
| 10707 | ip: *InternPool, | |
| 10708 | gpa: Allocator, | |
| 10709 | tid: Zcu.PerThread.Id, | |
| 10710 | opts: struct { | |
| 10711 | name: NullTerminatedString, | |
| 10712 | fqn: NullTerminatedString, | |
| 10713 | val: InternPool.Index, | |
| 10714 | alignment: Alignment, | |
| 10715 | @"linksection": OptionalNullTerminatedString, | |
| 10716 | @"addrspace": std.builtin.AddressSpace, | |
| 10717 | }, | |
| 10718 | ) Allocator.Error!Nav.Index { | |
| 10719 | const navs = ip.getLocal(tid).getMutableNavs(gpa); | |
| 10720 | const index_unwrapped: Nav.Index.Unwrapped = .{ | |
| 10721 | .tid = tid, | |
| 10722 | .index = navs.mutate.len, | |
| 10723 | }; | |
| 10724 | try navs.append(Nav.pack(.{ | |
| 10725 | .name = opts.name, | |
| 10726 | .fqn = opts.fqn, | |
| 10727 | .analysis_owner = .none, | |
| 10728 | .status = .{ .resolved = .{ | |
| 10729 | .val = opts.val, | |
| 10730 | .alignment = opts.alignment, | |
| 10731 | .@"linksection" = opts.@"linksection", | |
| 10732 | .@"addrspace" = opts.@"addrspace", | |
| 10733 | } }, | |
| 10734 | .is_usingnamespace = false, | |
| 10735 | })); | |
| 10736 | return index_unwrapped.wrap(ip); | |
| 10737 | } | |
| 10738 | ||
| 10739 | /// Create a `Cau` and `Nav` which are paired. The value of the `Nav` is | |
| 10740 | /// determined by semantic analysis of the `Cau`. The value of the `Nav` | |
| 10741 | /// is initially unresolved. | |
| 10742 | pub fn createPairedCauNav( | |
| 10743 | ip: *InternPool, | |
| 10744 | gpa: Allocator, | |
| 10745 | tid: Zcu.PerThread.Id, | |
| 10746 | name: NullTerminatedString, | |
| 10747 | fqn: NullTerminatedString, | |
| 10748 | zir_index: TrackedInst.Index, | |
| 10749 | namespace: NamespaceIndex, | |
| 10750 | /// TODO: this is hacky! See `Nav.is_usingnamespace`. | |
| 10751 | is_usingnamespace: bool, | |
| 10752 | ) Allocator.Error!struct { Cau.Index, Nav.Index } { | |
| 10753 | const caus = ip.getLocal(tid).getMutableCaus(gpa); | |
| 10754 | const navs = ip.getLocal(tid).getMutableNavs(gpa); | |
| 10755 | ||
| 10756 | try caus.ensureUnusedCapacity(1); | |
| 10757 | try navs.ensureUnusedCapacity(1); | |
| 10758 | ||
| 10759 | const cau = Cau.Index.Unwrapped.wrap(.{ | |
| 10760 | .tid = tid, | |
| 10761 | .index = caus.mutate.len, | |
| 10762 | }, ip); | |
| 10763 | const nav = Nav.Index.Unwrapped.wrap(.{ | |
| 10764 | .tid = tid, | |
| 10765 | .index = navs.mutate.len, | |
| 10766 | }, ip); | |
| 10767 | ||
| 10768 | caus.appendAssumeCapacity(.{.{ | |
| 10769 | .zir_index = zir_index, | |
| 10770 | .namespace = namespace, | |
| 10771 | .owner = Cau.Owner.wrap(.{ .nav = nav }), | |
| 10772 | }}); | |
| 10773 | navs.appendAssumeCapacity(Nav.pack(.{ | |
| 10774 | .name = name, | |
| 10775 | .fqn = fqn, | |
| 10776 | .analysis_owner = cau.toOptional(), | |
| 10777 | .status = .unresolved, | |
| 10778 | .is_usingnamespace = is_usingnamespace, | |
| 10779 | })); | |
| 10780 | ||
| 10781 | return .{ cau, nav }; | |
| 10782 | } | |
| 10783 | ||
| 10784 | /// Resolve the value of a `Nav` with an analysis owner. | |
| 10785 | /// If its status is already `resolved`, the old value is discarded. | |
| 10786 | pub fn resolveNavValue( | |
| 10787 | ip: *InternPool, | |
| 10788 | nav: Nav.Index, | |
| 10789 | resolved: struct { | |
| 10790 | val: InternPool.Index, | |
| 10791 | alignment: Alignment, | |
| 10792 | @"linksection": OptionalNullTerminatedString, | |
| 10793 | @"addrspace": std.builtin.AddressSpace, | |
| 10794 | }, | |
| 10795 | ) void { | |
| 10796 | const unwrapped = nav.unwrap(ip); | |
| 10797 | ||
| 10798 | const local = ip.getLocal(unwrapped.tid); | |
| 10799 | local.mutate.extra.mutex.lock(); | |
| 10800 | defer local.mutate.extra.mutex.unlock(); | |
| 10801 | ||
| 10802 | const navs = local.shared.navs.view(); | |
| 10803 | ||
| 10804 | const nav_analysis_owners = navs.items(.analysis_owner); | |
| 10805 | const nav_vals = navs.items(.val); | |
| 10806 | const nav_linksections = navs.items(.@"linksection"); | |
| 10807 | const nav_bits = navs.items(.bits); | |
| 10808 | ||
| 10809 | assert(nav_analysis_owners[unwrapped.index] != .none); | |
| 10810 | ||
| 10811 | @atomicStore(InternPool.Index, &nav_vals[unwrapped.index], resolved.val, .release); | |
| 10812 | @atomicStore(OptionalNullTerminatedString, &nav_linksections[unwrapped.index], resolved.@"linksection", .release); | |
| 10813 | ||
| 10814 | var bits = nav_bits[unwrapped.index]; | |
| 10815 | bits.status = .resolved; | |
| 10816 | bits.alignment = resolved.alignment; | |
| 10817 | bits.@"addrspace" = resolved.@"addrspace"; | |
| 10818 | @atomicStore(Nav.Repr.Bits, &nav_bits[unwrapped.index], bits, .release); | |
| 10358 | 10819 | } |
| 10359 | 10820 | |
| 10360 | 10821 | pub fn createNamespace( |
| ... | ... | @@ -10404,7 +10865,7 @@ pub fn destroyNamespace( |
| 10404 | 10865 | namespace.* = .{ |
| 10405 | 10866 | .parent = undefined, |
| 10406 | 10867 | .file_scope = undefined, |
| 10407 | .decl_index = undefined, | |
| 10868 | .owner_type = undefined, | |
| 10408 | 10869 | }; |
| 10409 | 10870 | @field(namespace, Local.namespace_next_free_field) = |
| 10410 | 10871 | @enumFromInt(local.mutate.namespaces.free_list); |
| ... | ... | @@ -10750,10 +11211,10 @@ pub fn typeOf(ip: *const InternPool, index: Index) Index { |
| 10750 | 11211 | |
| 10751 | 11212 | .simple_type, .simple_value => unreachable, // handled via Index above |
| 10752 | 11213 | |
| 10753 | inline .ptr_decl, | |
| 11214 | inline .ptr_nav, | |
| 10754 | 11215 | .ptr_comptime_alloc, |
| 10755 | .ptr_anon_decl, | |
| 10756 | .ptr_anon_decl_aligned, | |
| 11216 | .ptr_uav, | |
| 11217 | .ptr_uav_aligned, | |
| 10757 | 11218 | .ptr_comptime_field, |
| 10758 | 11219 | .ptr_int, |
| 10759 | 11220 | .ptr_eu_payload, |
| ... | ... | @@ -10770,7 +11231,7 @@ pub fn typeOf(ip: *const InternPool, index: Index) Index { |
| 10770 | 11231 | .error_union_error, |
| 10771 | 11232 | .enum_tag, |
| 10772 | 11233 | .variable, |
| 10773 | .extern_func, | |
| 11234 | .@"extern", | |
| 10774 | 11235 | .func_decl, |
| 10775 | 11236 | .func_instance, |
| 10776 | 11237 | .func_coerced, |
| ... | ... | @@ -10892,14 +11353,14 @@ pub fn isVariable(ip: *const InternPool, val: Index) bool { |
| 10892 | 11353 | return val.unwrap(ip).getTag(ip) == .variable; |
| 10893 | 11354 | } |
| 10894 | 11355 | |
| 10895 | pub fn getBackingDecl(ip: *const InternPool, val: Index) OptionalDeclIndex { | |
| 11356 | pub fn getBackingNav(ip: *const InternPool, val: Index) Nav.Index.Optional { | |
| 10896 | 11357 | var base = val; |
| 10897 | 11358 | while (true) { |
| 10898 | 11359 | const unwrapped_base = base.unwrap(ip); |
| 10899 | 11360 | const base_item = unwrapped_base.getItem(ip); |
| 10900 | 11361 | switch (base_item.tag) { |
| 10901 | .ptr_decl => return @enumFromInt(unwrapped_base.getExtra(ip).view().items(.@"0")[ | |
| 10902 | base_item.data + std.meta.fieldIndex(PtrDecl, "decl").? | |
| 11362 | .ptr_nav => return @enumFromInt(unwrapped_base.getExtra(ip).view().items(.@"0")[ | |
| 11363 | base_item.data + std.meta.fieldIndex(PtrNav, "nav").? | |
| 10903 | 11364 | ]), |
| 10904 | 11365 | inline .ptr_eu_payload, |
| 10905 | 11366 | .ptr_opt_payload, |
| ... | ... | @@ -10922,11 +11383,11 @@ pub fn getBackingAddrTag(ip: *const InternPool, val: Index) ?Key.Ptr.BaseAddr.Ta |
| 10922 | 11383 | const unwrapped_base = base.unwrap(ip); |
| 10923 | 11384 | const base_item = unwrapped_base.getItem(ip); |
| 10924 | 11385 | switch (base_item.tag) { |
| 10925 | .ptr_decl => return .decl, | |
| 11386 | .ptr_nav => return .nav, | |
| 10926 | 11387 | .ptr_comptime_alloc => return .comptime_alloc, |
| 10927 | .ptr_anon_decl, | |
| 10928 | .ptr_anon_decl_aligned, | |
| 10929 | => return .anon_decl, | |
| 11388 | .ptr_uav, | |
| 11389 | .ptr_uav_aligned, | |
| 11390 | => return .uav, | |
| 10930 | 11391 | .ptr_comptime_field => return .comptime_field, |
| 10931 | 11392 | .ptr_int => return .int, |
| 10932 | 11393 | inline .ptr_eu_payload, |
| ... | ... | @@ -11098,10 +11559,10 @@ pub fn zigTypeTagOrPoison(ip: *const InternPool, index: Index) error{GenericPois |
| 11098 | 11559 | // values, not types |
| 11099 | 11560 | .undef, |
| 11100 | 11561 | .simple_value, |
| 11101 | .ptr_decl, | |
| 11562 | .ptr_nav, | |
| 11102 | 11563 | .ptr_comptime_alloc, |
| 11103 | .ptr_anon_decl, | |
| 11104 | .ptr_anon_decl_aligned, | |
| 11564 | .ptr_uav, | |
| 11565 | .ptr_uav_aligned, | |
| 11105 | 11566 | .ptr_comptime_field, |
| 11106 | 11567 | .ptr_int, |
| 11107 | 11568 | .ptr_eu_payload, |
| ... | ... | @@ -11137,7 +11598,7 @@ pub fn zigTypeTagOrPoison(ip: *const InternPool, index: Index) error{GenericPois |
| 11137 | 11598 | .float_c_longdouble_f128, |
| 11138 | 11599 | .float_comptime_float, |
| 11139 | 11600 | .variable, |
| 11140 | .extern_func, | |
| 11601 | .@"extern", | |
| 11141 | 11602 | .func_decl, |
| 11142 | 11603 | .func_instance, |
| 11143 | 11604 | .func_coerced, |
| ... | ... | @@ -11190,18 +11651,6 @@ pub fn funcAnalysisUnordered(ip: *const InternPool, func: Index) FuncAnalysis { |
| 11190 | 11651 | return @atomicLoad(FuncAnalysis, @constCast(ip).funcAnalysisPtr(func), .unordered); |
| 11191 | 11652 | } |
| 11192 | 11653 | |
| 11193 | pub fn funcSetAnalysisState(ip: *InternPool, func: Index, state: FuncAnalysis.State) void { | |
| 11194 | const unwrapped_func = func.unwrap(ip); | |
| 11195 | const extra_mutex = &ip.getLocal(unwrapped_func.tid).mutate.extra.mutex; | |
| 11196 | extra_mutex.lock(); | |
| 11197 | defer extra_mutex.unlock(); | |
| 11198 | ||
| 11199 | const analysis_ptr = ip.funcAnalysisPtr(func); | |
| 11200 | var analysis = analysis_ptr.*; | |
| 11201 | analysis.state = state; | |
| 11202 | @atomicStore(FuncAnalysis, analysis_ptr, analysis, .release); | |
| 11203 | } | |
| 11204 | ||
| 11205 | 11654 | pub fn funcMaxStackAlignment(ip: *InternPool, func: Index, new_stack_alignment: Alignment) void { |
| 11206 | 11655 | const unwrapped_func = func.unwrap(ip); |
| 11207 | 11656 | const extra_mutex = &ip.getLocal(unwrapped_func.tid).mutate.extra.mutex; |
| ... | ... | @@ -11349,10 +11798,6 @@ pub fn funcDeclInfo(ip: *const InternPool, index: Index) Key.Func { |
| 11349 | 11798 | return extraFuncDecl(unwrapped_index.tid, unwrapped_index.getExtra(ip), item.data); |
| 11350 | 11799 | } |
| 11351 | 11800 | |
| 11352 | pub fn funcDeclOwner(ip: *const InternPool, index: Index) DeclIndex { | |
| 11353 | return funcDeclInfo(ip, index).owner_decl; | |
| 11354 | } | |
| 11355 | ||
| 11356 | 11801 | pub fn funcTypeParamsLen(ip: *const InternPool, index: Index) u32 { |
| 11357 | 11802 | const unwrapped_index = index.unwrap(ip); |
| 11358 | 11803 | const extra_list = unwrapped_index.getExtra(ip); |
| ... | ... | @@ -11409,14 +11854,6 @@ pub fn anonStructFieldsLen(ip: *const InternPool, i: Index) u32 { |
| 11409 | 11854 | return @intCast(ip.indexToKey(i).anon_struct_type.types.len); |
| 11410 | 11855 | } |
| 11411 | 11856 | |
| 11412 | /// Asserts the type is a struct. | |
| 11413 | pub fn structDecl(ip: *const InternPool, i: Index) OptionalDeclIndex { | |
| 11414 | return switch (ip.indexToKey(i)) { | |
| 11415 | .struct_type => |t| t.decl, | |
| 11416 | else => unreachable, | |
| 11417 | }; | |
| 11418 | } | |
| 11419 | ||
| 11420 | 11857 | /// Returns the already-existing field with the same name, if any. |
| 11421 | 11858 | pub fn addFieldName( |
| 11422 | 11859 | ip: *InternPool, |
| ... | ... | @@ -11436,8 +11873,8 @@ pub fn addFieldName( |
| 11436 | 11873 | return null; |
| 11437 | 11874 | } |
| 11438 | 11875 | |
| 11439 | /// Used only by `get` for pointer values, and mainly intended to use `Tag.ptr_anon_decl` | |
| 11440 | /// encoding instead of `Tag.ptr_anon_decl_aligned` when possible. | |
| 11876 | /// Used only by `get` for pointer values, and mainly intended to use `Tag.ptr_uav` | |
| 11877 | /// encoding instead of `Tag.ptr_uav_aligned` when possible. | |
| 11441 | 11878 | fn ptrsHaveSameAlignment(ip: *InternPool, a_ty: Index, a_info: Key.PtrType, b_ty: Index) bool { |
| 11442 | 11879 | if (a_ty == b_ty) return true; |
| 11443 | 11880 | const b_info = ip.indexToKey(b_ty).ptr_type; |
| ... | ... | @@ -11607,3 +12044,7 @@ pub fn getErrorValue( |
| 11607 | 12044 | pub fn getErrorValueIfExists(ip: *const InternPool, name: NullTerminatedString) ?Zcu.ErrorInt { |
| 11608 | 12045 | return @intFromEnum(ip.global_error_set.getErrorValueIfExists(name) orelse return null); |
| 11609 | 12046 | } |
| 12047 | ||
| 12048 | pub fn isRemoved(ip: *const InternPool, ty: Index) bool { | |
| 12049 | return ty.unwrap(ip).getTag(ip) == .removed; | |
| 12050 | } |
src/Sema.zig+1054-1088| ... | ... | @@ -16,16 +16,14 @@ air_instructions: std.MultiArrayList(Air.Inst) = .{}, |
| 16 | 16 | air_extra: std.ArrayListUnmanaged(u32) = .{}, |
| 17 | 17 | /// Maps ZIR to AIR. |
| 18 | 18 | inst_map: InstMap = .{}, |
| 19 | /// When analyzing an inline function call, owner_decl is the Decl of the caller. | |
| 20 | owner_decl: *Decl, | |
| 21 | owner_decl_index: InternPool.DeclIndex, | |
| 22 | /// For an inline or comptime function call, this will be the root parent function | |
| 23 | /// which contains the callsite. Corresponds to `owner_decl`. | |
| 24 | /// This could be `none`, a `func_decl`, or a `func_instance`. | |
| 25 | owner_func_index: InternPool.Index, | |
| 19 | /// The "owner" of a `Sema` represents the root "thing" that is being analyzed. | |
| 20 | /// This does not change throughout the entire lifetime of a `Sema`. For instance, | |
| 21 | /// when analyzing a runtime function body, this is always `func` of that function, | |
| 22 | /// even if an inline/comptime function call is being analyzed. | |
| 23 | owner: AnalUnit, | |
| 26 | 24 | /// The function this ZIR code is the body of, according to the source code. |
| 27 | /// This starts out the same as `owner_func_index` and then diverges in the case of | |
| 28 | /// an inline or comptime function call. | |
| 25 | /// This starts out the same as `sema.owner.func` if applicable, and then diverges | |
| 26 | /// in the case of an inline or comptime function call. | |
| 29 | 27 | /// This could be `none`, a `func_decl`, or a `func_instance`. |
| 30 | 28 | func_index: InternPool.Index, |
| 31 | 29 | /// Whether the type of func_index has a calling convention of `.Naked`. |
| ... | ... | @@ -48,7 +46,6 @@ branch_count: u32 = 0, |
| 48 | 46 | /// Populated when returning `error.ComptimeBreak`. Used to communicate the |
| 49 | 47 | /// break instruction up the stack to find the corresponding Block. |
| 50 | 48 | comptime_break_inst: Zir.Inst.Index = undefined, |
| 51 | decl_val_table: std.AutoHashMapUnmanaged(InternPool.DeclIndex, Air.Inst.Ref) = .{}, | |
| 52 | 49 | /// When doing a generic function instantiation, this array collects a value |
| 53 | 50 | /// for each parameter of the generic owner. `none` for non-comptime parameters. |
| 54 | 51 | /// This is a separate array from `block.params` so that it can be passed |
| ... | ... | @@ -79,10 +76,6 @@ no_partial_func_ty: bool = false, |
| 79 | 76 | /// here so the values can be dropped without any cleanup. |
| 80 | 77 | unresolved_inferred_allocs: std.AutoArrayHashMapUnmanaged(Air.Inst.Index, InferredAlloc) = .{}, |
| 81 | 78 | |
| 82 | /// This is populated when `@setAlignStack` occurs so that if there is a duplicate | |
| 83 | /// one encountered, the conflicting source location can be shown. | |
| 84 | prev_stack_alignment_src: ?LazySrcLoc = null, | |
| 85 | ||
| 86 | 79 | /// While analyzing a type which has a special InternPool index, this is set to the index at which |
| 87 | 80 | /// the struct/enum/union type created should be placed. Otherwise, it is `.none`. |
| 88 | 81 | builtin_type_target_index: InternPool.Index = .none, |
| ... | ... | @@ -177,7 +170,6 @@ const trace = @import("tracy.zig").trace; |
| 177 | 170 | const Namespace = Module.Namespace; |
| 178 | 171 | const CompileError = Module.CompileError; |
| 179 | 172 | const SemaError = Module.SemaError; |
| 180 | const Decl = Module.Decl; | |
| 181 | 173 | const LazySrcLoc = Zcu.LazySrcLoc; |
| 182 | 174 | const RangeSet = @import("RangeSet.zig"); |
| 183 | 175 | const target_util = @import("target.zig"); |
| ... | ... | @@ -394,7 +386,7 @@ pub const Block = struct { |
| 394 | 386 | /// The name of the current "context" for naming namespace types. |
| 395 | 387 | /// The interpretation of this depends on the name strategy in ZIR, but the name |
| 396 | 388 | /// is always incorporated into the type name somehow. |
| 397 | /// See `Sema.createAnonymousDeclTypeNamed`. | |
| 389 | /// See `Sema.createTypeName`. | |
| 398 | 390 | type_name_ctx: InternPool.NullTerminatedString, |
| 399 | 391 | |
| 400 | 392 | /// Create a `LazySrcLoc` based on an `Offset` from the code being analyzed in this block. |
| ... | ... | @@ -440,8 +432,8 @@ pub const Block = struct { |
| 440 | 432 | try sema.errNote(ci.src, parent, prefix ++ "it is inside a @cImport", .{}); |
| 441 | 433 | }, |
| 442 | 434 | .comptime_ret_ty => |rt| { |
| 443 | const ret_ty_src: LazySrcLoc = if (try sema.funcDeclSrc(rt.func)) |fn_decl| .{ | |
| 444 | .base_node_inst = fn_decl.zir_decl_index.unwrap().?, | |
| 435 | const ret_ty_src: LazySrcLoc = if (try sema.funcDeclSrcInst(rt.func)) |fn_decl_inst| .{ | |
| 436 | .base_node_inst = fn_decl_inst, | |
| 445 | 437 | .offset = .{ .node_offset_fn_type_ret_ty = 0 }, |
| 446 | 438 | } else rt.func_src; |
| 447 | 439 | if (rt.return_ty.isGenericPoison()) { |
| ... | ... | @@ -871,7 +863,6 @@ pub fn deinit(sema: *Sema) void { |
| 871 | 863 | sema.air_instructions.deinit(gpa); |
| 872 | 864 | sema.air_extra.deinit(gpa); |
| 873 | 865 | sema.inst_map.deinit(gpa); |
| 874 | sema.decl_val_table.deinit(gpa); | |
| 875 | 866 | { |
| 876 | 867 | var it = sema.post_hoc_blocks.iterator(); |
| 877 | 868 | while (it.next()) |entry| { |
| ... | ... | @@ -2170,7 +2161,7 @@ fn resolveValueResolveLazy(sema: *Sema, inst: Air.Inst.Ref) CompileError!?Value |
| 2170 | 2161 | fn resolveValueIntable(sema: *Sema, inst: Air.Inst.Ref) CompileError!?Value { |
| 2171 | 2162 | const val = (try sema.resolveValue(inst)) orelse return null; |
| 2172 | 2163 | if (sema.pt.zcu.intern_pool.getBackingAddrTag(val.toIntern())) |addr| switch (addr) { |
| 2173 | .decl, .anon_decl, .comptime_alloc, .comptime_field => return null, | |
| 2164 | .nav, .uav, .comptime_alloc, .comptime_field => return null, | |
| 2174 | 2165 | .int => {}, |
| 2175 | 2166 | .eu_payload, .opt_payload, .arr_elem, .field => unreachable, |
| 2176 | 2167 | }; |
| ... | ... | @@ -2503,7 +2494,6 @@ pub fn failWithOwnedErrorMsg(sema: *Sema, block: ?*Block, err_msg: *Module.Error |
| 2503 | 2494 | @setCold(true); |
| 2504 | 2495 | const gpa = sema.gpa; |
| 2505 | 2496 | const mod = sema.pt.zcu; |
| 2506 | const ip = &mod.intern_pool; | |
| 2507 | 2497 | |
| 2508 | 2498 | if (build_options.enable_debug_extensions and mod.comp.debug_compile_errors) { |
| 2509 | 2499 | var all_references = mod.resolveReferences() catch @panic("out of memory"); |
| ... | ... | @@ -2531,10 +2521,10 @@ pub fn failWithOwnedErrorMsg(sema: *Sema, block: ?*Block, err_msg: *Module.Error |
| 2531 | 2521 | |
| 2532 | 2522 | const use_ref_trace = if (mod.comp.reference_trace) |n| n > 0 else mod.failed_analysis.count() == 0; |
| 2533 | 2523 | if (use_ref_trace) { |
| 2534 | err_msg.reference_trace_root = sema.ownerUnit().toOptional(); | |
| 2524 | err_msg.reference_trace_root = sema.owner.toOptional(); | |
| 2535 | 2525 | } |
| 2536 | 2526 | |
| 2537 | const gop = try mod.failed_analysis.getOrPut(gpa, sema.ownerUnit()); | |
| 2527 | const gop = try mod.failed_analysis.getOrPut(gpa, sema.owner); | |
| 2538 | 2528 | if (gop.found_existing) { |
| 2539 | 2529 | // If there are multiple errors for the same Decl, prefer the first one added. |
| 2540 | 2530 | sema.err = null; |
| ... | ... | @@ -2544,16 +2534,6 @@ pub fn failWithOwnedErrorMsg(sema: *Sema, block: ?*Block, err_msg: *Module.Error |
| 2544 | 2534 | gop.value_ptr.* = err_msg; |
| 2545 | 2535 | } |
| 2546 | 2536 | |
| 2547 | if (sema.owner_func_index != .none) { | |
| 2548 | ip.funcSetAnalysisState(sema.owner_func_index, .sema_failure); | |
| 2549 | } else { | |
| 2550 | sema.owner_decl.analysis = .sema_failure; | |
| 2551 | } | |
| 2552 | ||
| 2553 | if (sema.func_index != .none) { | |
| 2554 | ip.funcSetAnalysisState(sema.func_index, .sema_failure); | |
| 2555 | } | |
| 2556 | ||
| 2557 | 2537 | return error.AnalysisFail; |
| 2558 | 2538 | } |
| 2559 | 2539 | |
| ... | ... | @@ -2662,7 +2642,8 @@ fn getCaptures(sema: *Sema, block: *Block, type_src: LazySrcLoc, extra_index: us |
| 2662 | 2642 | const pt = sema.pt; |
| 2663 | 2643 | const zcu = pt.zcu; |
| 2664 | 2644 | const ip = &zcu.intern_pool; |
| 2665 | const parent_captures: InternPool.CaptureValue.Slice = zcu.namespacePtr(block.namespace).getType(zcu).getCaptures(zcu); | |
| 2645 | const parent_ty = Type.fromInterned(zcu.namespacePtr(block.namespace).owner_type); | |
| 2646 | const parent_captures: InternPool.CaptureValue.Slice = parent_ty.getCaptures(zcu); | |
| 2666 | 2647 | |
| 2667 | 2648 | const captures = try sema.arena.alloc(InternPool.CaptureValue, captures_len); |
| 2668 | 2649 | |
| ... | ... | @@ -2704,8 +2685,8 @@ fn getCaptures(sema: *Sema, block: *Block, type_src: LazySrcLoc, extra_index: us |
| 2704 | 2685 | sema.code.nullTerminatedString(str), |
| 2705 | 2686 | .no_embedded_nulls, |
| 2706 | 2687 | ); |
| 2707 | const decl = try sema.lookupIdentifier(block, LazySrcLoc.unneeded, decl_name); // TODO: could we need this src loc? | |
| 2708 | break :capture InternPool.CaptureValue.wrap(.{ .decl_val = decl }); | |
| 2688 | const nav = try sema.lookupIdentifier(block, LazySrcLoc.unneeded, decl_name); // TODO: could we need this src loc? | |
| 2689 | break :capture InternPool.CaptureValue.wrap(.{ .nav_val = nav }); | |
| 2709 | 2690 | }, |
| 2710 | 2691 | .decl_ref => |str| capture: { |
| 2711 | 2692 | const decl_name = try ip.getOrPutString( |
| ... | ... | @@ -2714,8 +2695,8 @@ fn getCaptures(sema: *Sema, block: *Block, type_src: LazySrcLoc, extra_index: us |
| 2714 | 2695 | sema.code.nullTerminatedString(str), |
| 2715 | 2696 | .no_embedded_nulls, |
| 2716 | 2697 | ); |
| 2717 | const decl = try sema.lookupIdentifier(block, LazySrcLoc.unneeded, decl_name); // TODO: could we need this src loc? | |
| 2718 | break :capture InternPool.CaptureValue.wrap(.{ .decl_ref = decl }); | |
| 2698 | const nav = try sema.lookupIdentifier(block, LazySrcLoc.unneeded, decl_name); // TODO: could we need this src loc? | |
| 2699 | break :capture InternPool.CaptureValue.wrap(.{ .nav_ref = nav }); | |
| 2719 | 2700 | }, |
| 2720 | 2701 | }; |
| 2721 | 2702 | } |
| ... | ... | @@ -2740,19 +2721,24 @@ fn wrapWipTy(sema: *Sema, wip_ty: anytype) @TypeOf(wip_ty) { |
| 2740 | 2721 | fn maybeRemoveOutdatedType(sema: *Sema, ty: InternPool.Index) !bool { |
| 2741 | 2722 | const pt = sema.pt; |
| 2742 | 2723 | const zcu = pt.zcu; |
| 2724 | const ip = &zcu.intern_pool; | |
| 2743 | 2725 | |
| 2744 | 2726 | if (!zcu.comp.incremental) return false; |
| 2745 | 2727 | |
| 2746 | const decl_index = Type.fromInterned(ty).getOwnerDecl(zcu); | |
| 2747 | const decl_as_depender = AnalUnit.wrap(.{ .decl = decl_index }); | |
| 2748 | const was_outdated = zcu.outdated.swapRemove(decl_as_depender) or | |
| 2749 | zcu.potentially_outdated.swapRemove(decl_as_depender); | |
| 2728 | const cau_index = switch (ip.indexToKey(ty)) { | |
| 2729 | .struct_type => ip.loadStructType(ty).cau.unwrap().?, | |
| 2730 | .union_type => ip.loadUnionType(ty).cau, | |
| 2731 | .enum_type => ip.loadEnumType(ty).cau.unwrap().?, | |
| 2732 | else => unreachable, | |
| 2733 | }; | |
| 2734 | const cau_unit = AnalUnit.wrap(.{ .cau = cau_index }); | |
| 2735 | const was_outdated = zcu.outdated.swapRemove(cau_unit) or | |
| 2736 | zcu.potentially_outdated.swapRemove(cau_unit); | |
| 2750 | 2737 | if (!was_outdated) return false; |
| 2751 | _ = zcu.outdated_ready.swapRemove(decl_as_depender); | |
| 2752 | zcu.intern_pool.removeDependenciesForDepender(zcu.gpa, AnalUnit.wrap(.{ .decl = decl_index })); | |
| 2738 | _ = zcu.outdated_ready.swapRemove(cau_unit); | |
| 2739 | zcu.intern_pool.removeDependenciesForDepender(zcu.gpa, cau_unit); | |
| 2753 | 2740 | zcu.intern_pool.remove(pt.tid, ty); |
| 2754 | zcu.declPtr(decl_index).analysis = .dependency_failure; | |
| 2755 | try zcu.markDependeeOutdated(.{ .decl_val = decl_index }); | |
| 2741 | try zcu.markDependeeOutdated(.{ .interned = ty }); | |
| 2756 | 2742 | return true; |
| 2757 | 2743 | } |
| 2758 | 2744 | |
| ... | ... | @@ -2816,7 +2802,6 @@ fn zirStructDecl( |
| 2816 | 2802 | .any_default_inits = small.any_default_inits, |
| 2817 | 2803 | .inits_resolved = false, |
| 2818 | 2804 | .any_aligned_fields = small.any_aligned_fields, |
| 2819 | .has_namespace = true or decls_len > 0, // TODO: see below | |
| 2820 | 2805 | .key = .{ .declared = .{ |
| 2821 | 2806 | .zir_index = tracked_inst, |
| 2822 | 2807 | .captures = captures, |
| ... | ... | @@ -2831,73 +2816,65 @@ fn zirStructDecl( |
| 2831 | 2816 | }); |
| 2832 | 2817 | errdefer wip_ty.cancel(ip, pt.tid); |
| 2833 | 2818 | |
| 2834 | const new_decl_index = try sema.createAnonymousDeclTypeNamed( | |
| 2819 | wip_ty.setName(ip, try sema.createTypeName( | |
| 2835 | 2820 | block, |
| 2836 | Value.fromInterned(wip_ty.index), | |
| 2837 | 2821 | small.name_strategy, |
| 2838 | 2822 | "struct", |
| 2839 | 2823 | inst, |
| 2840 | ); | |
| 2841 | mod.declPtr(new_decl_index).owns_tv = true; | |
| 2842 | errdefer pt.abortAnonDecl(new_decl_index); | |
| 2824 | wip_ty.index, | |
| 2825 | )); | |
| 2826 | ||
| 2827 | const new_namespace_index: InternPool.NamespaceIndex = try pt.createNamespace(.{ | |
| 2828 | .parent = block.namespace.toOptional(), | |
| 2829 | .owner_type = wip_ty.index, | |
| 2830 | .file_scope = block.getFileScopeIndex(mod), | |
| 2831 | }); | |
| 2832 | errdefer pt.destroyNamespace(new_namespace_index); | |
| 2833 | ||
| 2834 | const new_cau_index = try ip.createTypeCau(gpa, pt.tid, tracked_inst, new_namespace_index, wip_ty.index); | |
| 2843 | 2835 | |
| 2844 | 2836 | if (pt.zcu.comp.incremental) { |
| 2845 | 2837 | try ip.addDependency( |
| 2846 | 2838 | sema.gpa, |
| 2847 | AnalUnit.wrap(.{ .decl = new_decl_index }), | |
| 2848 | .{ .src_hash = try block.trackZir(inst) }, | |
| 2839 | AnalUnit.wrap(.{ .cau = new_cau_index }), | |
| 2840 | .{ .src_hash = tracked_inst }, | |
| 2849 | 2841 | ); |
| 2850 | 2842 | } |
| 2851 | 2843 | |
| 2852 | // TODO: if AstGen tells us `@This` was not used in the fields, we can elide the namespace. | |
| 2853 | const new_namespace_index: InternPool.OptionalNamespaceIndex = if (true or decls_len > 0) (try pt.createNamespace(.{ | |
| 2854 | .parent = block.namespace.toOptional(), | |
| 2855 | .decl_index = new_decl_index, | |
| 2856 | .file_scope = block.getFileScopeIndex(mod), | |
| 2857 | })).toOptional() else .none; | |
| 2858 | errdefer if (new_namespace_index.unwrap()) |ns| pt.destroyNamespace(ns); | |
| 2859 | ||
| 2860 | if (new_namespace_index.unwrap()) |ns| { | |
| 2861 | const decls = sema.code.bodySlice(extra_index, decls_len); | |
| 2862 | try pt.scanNamespace(ns, decls, mod.declPtr(new_decl_index)); | |
| 2863 | } | |
| 2844 | const decls = sema.code.bodySlice(extra_index, decls_len); | |
| 2845 | try pt.scanNamespace(new_namespace_index, decls); | |
| 2864 | 2846 | |
| 2865 | try pt.finalizeAnonDecl(new_decl_index); | |
| 2866 | 2847 | try mod.comp.queueJob(.{ .resolve_type_fully = wip_ty.index }); |
| 2867 | try sema.addReferenceEntry(src, AnalUnit.wrap(.{ .decl = new_decl_index })); | |
| 2868 | return Air.internedToRef(wip_ty.finish(ip, new_decl_index, new_namespace_index)); | |
| 2848 | try sema.addReferenceEntry(src, AnalUnit.wrap(.{ .cau = new_cau_index })); | |
| 2849 | try sema.declareDependency(.{ .interned = wip_ty.index }); | |
| 2850 | return Air.internedToRef(wip_ty.finish(ip, new_cau_index.toOptional(), new_namespace_index)); | |
| 2869 | 2851 | } |
| 2870 | 2852 | |
| 2871 | fn createAnonymousDeclTypeNamed( | |
| 2853 | fn createTypeName( | |
| 2872 | 2854 | sema: *Sema, |
| 2873 | 2855 | block: *Block, |
| 2874 | val: Value, | |
| 2875 | 2856 | name_strategy: Zir.Inst.NameStrategy, |
| 2876 | 2857 | anon_prefix: []const u8, |
| 2877 | 2858 | inst: ?Zir.Inst.Index, |
| 2878 | ) !InternPool.DeclIndex { | |
| 2859 | /// This is used purely to give the type a unique name in the `anon` case. | |
| 2860 | type_index: InternPool.Index, | |
| 2861 | ) !InternPool.NullTerminatedString { | |
| 2879 | 2862 | const pt = sema.pt; |
| 2880 | 2863 | const zcu = pt.zcu; |
| 2864 | const gpa = zcu.gpa; | |
| 2881 | 2865 | const ip = &zcu.intern_pool; |
| 2882 | const gpa = sema.gpa; | |
| 2883 | const namespace = block.namespace; | |
| 2884 | const new_decl_index = try pt.allocateNewDecl(namespace); | |
| 2885 | errdefer pt.destroyDecl(new_decl_index); | |
| 2886 | 2866 | |
| 2887 | 2867 | switch (name_strategy) { |
| 2888 | 2868 | .anon => {}, // handled after switch |
| 2889 | .parent => { | |
| 2890 | try pt.initNewAnonDecl(new_decl_index, val, block.type_name_ctx, .none); | |
| 2891 | return new_decl_index; | |
| 2892 | }, | |
| 2869 | .parent => return block.type_name_ctx, | |
| 2893 | 2870 | .func => func_strat: { |
| 2894 | 2871 | const fn_info = sema.code.getFnInfo(ip.funcZirBodyInst(sema.func_index).resolve(ip)); |
| 2895 | 2872 | const zir_tags = sema.code.instructions.items(.tag); |
| 2896 | 2873 | |
| 2897 | var buf = std.ArrayList(u8).init(gpa); | |
| 2898 | defer buf.deinit(); | |
| 2874 | var buf: std.ArrayListUnmanaged(u8) = .{}; | |
| 2875 | defer buf.deinit(gpa); | |
| 2899 | 2876 | |
| 2900 | const writer = buf.writer(); | |
| 2877 | const writer = buf.writer(gpa); | |
| 2901 | 2878 | try writer.print("{}(", .{block.type_name_ctx.fmt(ip)}); |
| 2902 | 2879 | |
| 2903 | 2880 | var arg_i: usize = 0; |
| ... | ... | @@ -2931,23 +2908,18 @@ fn createAnonymousDeclTypeNamed( |
| 2931 | 2908 | }; |
| 2932 | 2909 | |
| 2933 | 2910 | try writer.writeByte(')'); |
| 2934 | const name = try ip.getOrPutString(gpa, pt.tid, buf.items, .no_embedded_nulls); | |
| 2935 | try pt.initNewAnonDecl(new_decl_index, val, name, .none); | |
| 2936 | return new_decl_index; | |
| 2911 | return ip.getOrPutString(gpa, pt.tid, buf.items, .no_embedded_nulls); | |
| 2937 | 2912 | }, |
| 2938 | 2913 | .dbg_var => { |
| 2914 | // TODO: this logic is questionable. We ideally should be traversing the `Block` rather than relying on the order of AstGen instructions. | |
| 2939 | 2915 | const ref = inst.?.toRef(); |
| 2940 | 2916 | const zir_tags = sema.code.instructions.items(.tag); |
| 2941 | 2917 | const zir_data = sema.code.instructions.items(.data); |
| 2942 | 2918 | for (@intFromEnum(inst.?)..zir_tags.len) |i| switch (zir_tags[i]) { |
| 2943 | .dbg_var_ptr, .dbg_var_val => { | |
| 2944 | if (zir_data[i].str_op.operand != ref) continue; | |
| 2945 | ||
| 2946 | const name = try ip.getOrPutStringFmt(gpa, pt.tid, "{}.{s}", .{ | |
| 2919 | .dbg_var_ptr, .dbg_var_val => if (zir_data[i].str_op.operand == ref) { | |
| 2920 | return ip.getOrPutStringFmt(gpa, pt.tid, "{}.{s}", .{ | |
| 2947 | 2921 | block.type_name_ctx.fmt(ip), zir_data[i].str_op.getStr(sema.code), |
| 2948 | 2922 | }, .no_embedded_nulls); |
| 2949 | try pt.initNewAnonDecl(new_decl_index, val, name, .none); | |
| 2950 | return new_decl_index; | |
| 2951 | 2923 | }, |
| 2952 | 2924 | else => {}, |
| 2953 | 2925 | }; |
| ... | ... | @@ -2955,20 +2927,19 @@ fn createAnonymousDeclTypeNamed( |
| 2955 | 2927 | }, |
| 2956 | 2928 | } |
| 2957 | 2929 | |
| 2958 | // anon strat handling. | |
| 2930 | // anon strat handling | |
| 2959 | 2931 | |
| 2960 | 2932 | // It would be neat to have "struct:line:column" but this name has |
| 2961 | 2933 | // to survive incremental updates, where it may have been shifted down |
| 2962 | 2934 | // or up to a different line, but unchanged, and thus not unnecessarily |
| 2963 | 2935 | // semantically analyzed. |
| 2964 | // This name is also used as the key in the parent namespace so it cannot be | |
| 2965 | // renamed. | |
| 2936 | // TODO: that would be possible, by detecting line number changes and renaming | |
| 2937 | // types appropriately. However, `@typeName` becomes a problem then. If we remove | |
| 2938 | // that builtin from the language, we can consider this. | |
| 2966 | 2939 | |
| 2967 | const name = ip.getOrPutStringFmt(gpa, pt.tid, "{}__{s}_{d}", .{ | |
| 2968 | block.type_name_ctx.fmt(ip), anon_prefix, @intFromEnum(new_decl_index), | |
| 2969 | }, .no_embedded_nulls) catch unreachable; | |
| 2970 | try pt.initNewAnonDecl(new_decl_index, val, name, .none); | |
| 2971 | return new_decl_index; | |
| 2940 | return ip.getOrPutStringFmt(gpa, pt.tid, "{}__{s}_{d}", .{ | |
| 2941 | block.type_name_ctx.fmt(ip), anon_prefix, @intFromEnum(type_index), | |
| 2942 | }, .no_embedded_nulls); | |
| 2972 | 2943 | } |
| 2973 | 2944 | |
| 2974 | 2945 | fn zirEnumDecl( |
| ... | ... | @@ -3040,7 +3011,6 @@ fn zirEnumDecl( |
| 3040 | 3011 | } else false; |
| 3041 | 3012 | |
| 3042 | 3013 | const enum_init: InternPool.EnumTypeInit = .{ |
| 3043 | .has_namespace = true or decls_len > 0, // TODO: see below | |
| 3044 | 3014 | .has_values = any_values, |
| 3045 | 3015 | .tag_mode = if (small.nonexhaustive) |
| 3046 | 3016 | .nonexhaustive |
| ... | ... | @@ -3068,60 +3038,50 @@ fn zirEnumDecl( |
| 3068 | 3038 | |
| 3069 | 3039 | errdefer if (!done) wip_ty.cancel(ip, pt.tid); |
| 3070 | 3040 | |
| 3071 | const new_decl_index = try sema.createAnonymousDeclTypeNamed( | |
| 3041 | const type_name = try sema.createTypeName( | |
| 3072 | 3042 | block, |
| 3073 | Value.fromInterned(wip_ty.index), | |
| 3074 | 3043 | small.name_strategy, |
| 3075 | 3044 | "enum", |
| 3076 | 3045 | inst, |
| 3046 | wip_ty.index, | |
| 3077 | 3047 | ); |
| 3078 | const new_decl = mod.declPtr(new_decl_index); | |
| 3079 | new_decl.owns_tv = true; | |
| 3080 | errdefer if (!done) pt.abortAnonDecl(new_decl_index); | |
| 3048 | wip_ty.setName(ip, type_name); | |
| 3049 | ||
| 3050 | const new_namespace_index: InternPool.NamespaceIndex = try pt.createNamespace(.{ | |
| 3051 | .parent = block.namespace.toOptional(), | |
| 3052 | .owner_type = wip_ty.index, | |
| 3053 | .file_scope = block.getFileScopeIndex(mod), | |
| 3054 | }); | |
| 3055 | errdefer if (!done) pt.destroyNamespace(new_namespace_index); | |
| 3056 | ||
| 3057 | const new_cau_index = try ip.createTypeCau(gpa, pt.tid, tracked_inst, new_namespace_index, wip_ty.index); | |
| 3081 | 3058 | |
| 3082 | 3059 | if (pt.zcu.comp.incremental) { |
| 3083 | 3060 | try mod.intern_pool.addDependency( |
| 3084 | 3061 | gpa, |
| 3085 | AnalUnit.wrap(.{ .decl = new_decl_index }), | |
| 3062 | AnalUnit.wrap(.{ .cau = new_cau_index }), | |
| 3086 | 3063 | .{ .src_hash = try block.trackZir(inst) }, |
| 3087 | 3064 | ); |
| 3088 | 3065 | } |
| 3089 | 3066 | |
| 3090 | // TODO: if AstGen tells us `@This` was not used in the fields, we can elide the namespace. | |
| 3091 | const new_namespace_index: InternPool.OptionalNamespaceIndex = if (true or decls_len > 0) (try pt.createNamespace(.{ | |
| 3092 | .parent = block.namespace.toOptional(), | |
| 3093 | .decl_index = new_decl_index, | |
| 3094 | .file_scope = block.getFileScopeIndex(mod), | |
| 3095 | })).toOptional() else .none; | |
| 3096 | errdefer if (!done) if (new_namespace_index.unwrap()) |ns| pt.destroyNamespace(ns); | |
| 3067 | try pt.scanNamespace(new_namespace_index, decls); | |
| 3097 | 3068 | |
| 3098 | if (new_namespace_index.unwrap()) |ns| { | |
| 3099 | try pt.scanNamespace(ns, decls, new_decl); | |
| 3100 | } | |
| 3069 | try sema.addReferenceEntry(src, AnalUnit.wrap(.{ .cau = new_cau_index })); | |
| 3070 | try sema.declareDependency(.{ .interned = wip_ty.index }); | |
| 3101 | 3071 | |
| 3102 | 3072 | // We've finished the initial construction of this type, and are about to perform analysis. |
| 3103 | // Set the decl and namespace appropriately, and don't destroy anything on failure. | |
| 3104 | wip_ty.prepare(ip, new_decl_index, new_namespace_index); | |
| 3073 | // Set the Cau and namespace appropriately, and don't destroy anything on failure. | |
| 3074 | wip_ty.prepare(ip, new_cau_index, new_namespace_index); | |
| 3105 | 3075 | done = true; |
| 3106 | 3076 | |
| 3107 | 3077 | const int_tag_ty = ty: { |
| 3108 | 3078 | // We create a block for the field type instructions because they |
| 3109 | 3079 | // may need to reference Decls from inside the enum namespace. |
| 3110 | // Within the field type, default value, and alignment expressions, the "owner decl" | |
| 3111 | // should be the enum itself. | |
| 3080 | // Within the field type, default value, and alignment expressions, the owner should be the enum's `Cau`. | |
| 3112 | 3081 | |
| 3113 | const prev_owner_decl = sema.owner_decl; | |
| 3114 | const prev_owner_decl_index = sema.owner_decl_index; | |
| 3115 | sema.owner_decl = new_decl; | |
| 3116 | sema.owner_decl_index = new_decl_index; | |
| 3117 | defer { | |
| 3118 | sema.owner_decl = prev_owner_decl; | |
| 3119 | sema.owner_decl_index = prev_owner_decl_index; | |
| 3120 | } | |
| 3121 | ||
| 3122 | const prev_owner_func_index = sema.owner_func_index; | |
| 3123 | sema.owner_func_index = .none; | |
| 3124 | defer sema.owner_func_index = prev_owner_func_index; | |
| 3082 | const prev_owner = sema.owner; | |
| 3083 | sema.owner = AnalUnit.wrap(.{ .cau = new_cau_index }); | |
| 3084 | defer sema.owner = prev_owner; | |
| 3125 | 3085 | |
| 3126 | 3086 | const prev_func_index = sema.func_index; |
| 3127 | 3087 | sema.func_index = .none; |
| ... | ... | @@ -3130,12 +3090,12 @@ fn zirEnumDecl( |
| 3130 | 3090 | var enum_block: Block = .{ |
| 3131 | 3091 | .parent = null, |
| 3132 | 3092 | .sema = sema, |
| 3133 | .namespace = new_namespace_index.unwrap() orelse block.namespace, | |
| 3093 | .namespace = new_namespace_index, | |
| 3134 | 3094 | .instructions = .{}, |
| 3135 | 3095 | .inlining = null, |
| 3136 | 3096 | .is_comptime = true, |
| 3137 | 3097 | .src_base_inst = tracked_inst, |
| 3138 | .type_name_ctx = new_decl.name, | |
| 3098 | .type_name_ctx = type_name, | |
| 3139 | 3099 | }; |
| 3140 | 3100 | defer enum_block.instructions.deinit(sema.gpa); |
| 3141 | 3101 | |
| ... | ... | @@ -3253,7 +3213,6 @@ fn zirEnumDecl( |
| 3253 | 3213 | } |
| 3254 | 3214 | } |
| 3255 | 3215 | |
| 3256 | try pt.finalizeAnonDecl(new_decl_index); | |
| 3257 | 3216 | return Air.internedToRef(wip_ty.index); |
| 3258 | 3217 | } |
| 3259 | 3218 | |
| ... | ... | @@ -3317,7 +3276,6 @@ fn zirUnionDecl( |
| 3317 | 3276 | .assumed_pointer_aligned = false, |
| 3318 | 3277 | .alignment = .none, |
| 3319 | 3278 | }, |
| 3320 | .has_namespace = true or decls_len != 0, // TODO: see below | |
| 3321 | 3279 | .fields_len = fields_len, |
| 3322 | 3280 | .enum_tag_ty = .none, // set later |
| 3323 | 3281 | .field_types = &.{}, // set later |
| ... | ... | @@ -3336,41 +3294,38 @@ fn zirUnionDecl( |
| 3336 | 3294 | }); |
| 3337 | 3295 | errdefer wip_ty.cancel(ip, pt.tid); |
| 3338 | 3296 | |
| 3339 | const new_decl_index = try sema.createAnonymousDeclTypeNamed( | |
| 3297 | wip_ty.setName(ip, try sema.createTypeName( | |
| 3340 | 3298 | block, |
| 3341 | Value.fromInterned(wip_ty.index), | |
| 3342 | 3299 | small.name_strategy, |
| 3343 | 3300 | "union", |
| 3344 | 3301 | inst, |
| 3345 | ); | |
| 3346 | mod.declPtr(new_decl_index).owns_tv = true; | |
| 3347 | errdefer pt.abortAnonDecl(new_decl_index); | |
| 3302 | wip_ty.index, | |
| 3303 | )); | |
| 3304 | ||
| 3305 | const new_namespace_index: InternPool.NamespaceIndex = try pt.createNamespace(.{ | |
| 3306 | .parent = block.namespace.toOptional(), | |
| 3307 | .owner_type = wip_ty.index, | |
| 3308 | .file_scope = block.getFileScopeIndex(mod), | |
| 3309 | }); | |
| 3310 | errdefer pt.destroyNamespace(new_namespace_index); | |
| 3311 | ||
| 3312 | const new_cau_index = try ip.createTypeCau(gpa, pt.tid, tracked_inst, new_namespace_index, wip_ty.index); | |
| 3348 | 3313 | |
| 3349 | 3314 | if (pt.zcu.comp.incremental) { |
| 3350 | 3315 | try mod.intern_pool.addDependency( |
| 3351 | 3316 | gpa, |
| 3352 | AnalUnit.wrap(.{ .decl = new_decl_index }), | |
| 3317 | AnalUnit.wrap(.{ .cau = new_cau_index }), | |
| 3353 | 3318 | .{ .src_hash = try block.trackZir(inst) }, |
| 3354 | 3319 | ); |
| 3355 | 3320 | } |
| 3356 | 3321 | |
| 3357 | // TODO: if AstGen tells us `@This` was not used in the fields, we can elide the namespace. | |
| 3358 | const new_namespace_index: InternPool.OptionalNamespaceIndex = if (true or decls_len > 0) (try pt.createNamespace(.{ | |
| 3359 | .parent = block.namespace.toOptional(), | |
| 3360 | .decl_index = new_decl_index, | |
| 3361 | .file_scope = block.getFileScopeIndex(mod), | |
| 3362 | })).toOptional() else .none; | |
| 3363 | errdefer if (new_namespace_index.unwrap()) |ns| pt.destroyNamespace(ns); | |
| 3364 | ||
| 3365 | if (new_namespace_index.unwrap()) |ns| { | |
| 3366 | const decls = sema.code.bodySlice(extra_index, decls_len); | |
| 3367 | try pt.scanNamespace(ns, decls, mod.declPtr(new_decl_index)); | |
| 3368 | } | |
| 3322 | const decls = sema.code.bodySlice(extra_index, decls_len); | |
| 3323 | try pt.scanNamespace(new_namespace_index, decls); | |
| 3369 | 3324 | |
| 3370 | try pt.finalizeAnonDecl(new_decl_index); | |
| 3371 | 3325 | try mod.comp.queueJob(.{ .resolve_type_fully = wip_ty.index }); |
| 3372 | try sema.addReferenceEntry(src, AnalUnit.wrap(.{ .decl = new_decl_index })); | |
| 3373 | return Air.internedToRef(wip_ty.finish(ip, new_decl_index, new_namespace_index)); | |
| 3326 | try sema.addReferenceEntry(src, AnalUnit.wrap(.{ .cau = new_cau_index })); | |
| 3327 | try sema.declareDependency(.{ .interned = wip_ty.index }); | |
| 3328 | return Air.internedToRef(wip_ty.finish(ip, new_cau_index.toOptional(), new_namespace_index)); | |
| 3374 | 3329 | } |
| 3375 | 3330 | |
| 3376 | 3331 | fn zirOpaqueDecl( |
| ... | ... | @@ -3410,7 +3365,6 @@ fn zirOpaqueDecl( |
| 3410 | 3365 | extra_index += captures_len; |
| 3411 | 3366 | |
| 3412 | 3367 | const opaque_init: InternPool.OpaqueTypeInit = .{ |
| 3413 | .has_namespace = decls_len != 0, | |
| 3414 | 3368 | .key = .{ .declared = .{ |
| 3415 | 3369 | .zir_index = tracked_inst, |
| 3416 | 3370 | .captures = captures, |
| ... | ... | @@ -3418,47 +3372,31 @@ fn zirOpaqueDecl( |
| 3418 | 3372 | }; |
| 3419 | 3373 | // No `wrapWipTy` needed as no std.builtin types are opaque. |
| 3420 | 3374 | const wip_ty = switch (try ip.getOpaqueType(gpa, pt.tid, opaque_init)) { |
| 3421 | .existing => |ty| wip: { | |
| 3422 | if (!try sema.maybeRemoveOutdatedType(ty)) return Air.internedToRef(ty); | |
| 3423 | break :wip (try ip.getOpaqueType(gpa, pt.tid, opaque_init)).wip; | |
| 3424 | }, | |
| 3375 | // No `maybeRemoveOutdatedType` as opaque types are never outdated. | |
| 3376 | .existing => |ty| return Air.internedToRef(ty), | |
| 3425 | 3377 | .wip => |wip| wip, |
| 3426 | 3378 | }; |
| 3427 | 3379 | errdefer wip_ty.cancel(ip, pt.tid); |
| 3428 | 3380 | |
| 3429 | const new_decl_index = try sema.createAnonymousDeclTypeNamed( | |
| 3381 | wip_ty.setName(ip, try sema.createTypeName( | |
| 3430 | 3382 | block, |
| 3431 | Value.fromInterned(wip_ty.index), | |
| 3432 | 3383 | small.name_strategy, |
| 3433 | 3384 | "opaque", |
| 3434 | 3385 | inst, |
| 3435 | ); | |
| 3436 | mod.declPtr(new_decl_index).owns_tv = true; | |
| 3437 | errdefer pt.abortAnonDecl(new_decl_index); | |
| 3386 | wip_ty.index, | |
| 3387 | )); | |
| 3438 | 3388 | |
| 3439 | if (pt.zcu.comp.incremental) { | |
| 3440 | try ip.addDependency( | |
| 3441 | gpa, | |
| 3442 | AnalUnit.wrap(.{ .decl = new_decl_index }), | |
| 3443 | .{ .src_hash = try block.trackZir(inst) }, | |
| 3444 | ); | |
| 3445 | } | |
| 3446 | ||
| 3447 | const new_namespace_index: InternPool.OptionalNamespaceIndex = if (decls_len > 0) (try pt.createNamespace(.{ | |
| 3389 | const new_namespace_index: InternPool.NamespaceIndex = try pt.createNamespace(.{ | |
| 3448 | 3390 | .parent = block.namespace.toOptional(), |
| 3449 | .decl_index = new_decl_index, | |
| 3391 | .owner_type = wip_ty.index, | |
| 3450 | 3392 | .file_scope = block.getFileScopeIndex(mod), |
| 3451 | })).toOptional() else .none; | |
| 3452 | errdefer if (new_namespace_index.unwrap()) |ns| pt.destroyNamespace(ns); | |
| 3453 | ||
| 3454 | if (new_namespace_index.unwrap()) |ns| { | |
| 3455 | const decls = sema.code.bodySlice(extra_index, decls_len); | |
| 3456 | try pt.scanNamespace(ns, decls, mod.declPtr(new_decl_index)); | |
| 3457 | } | |
| 3393 | }); | |
| 3394 | errdefer pt.destroyNamespace(new_namespace_index); | |
| 3458 | 3395 | |
| 3459 | try pt.finalizeAnonDecl(new_decl_index); | |
| 3396 | const decls = sema.code.bodySlice(extra_index, decls_len); | |
| 3397 | try pt.scanNamespace(new_namespace_index, decls); | |
| 3460 | 3398 | |
| 3461 | return Air.internedToRef(wip_ty.finish(ip, new_decl_index, new_namespace_index)); | |
| 3399 | return Air.internedToRef(wip_ty.finish(ip, .none, new_namespace_index)); | |
| 3462 | 3400 | } |
| 3463 | 3401 | |
| 3464 | 3402 | fn zirErrorSetDecl( |
| ... | ... | @@ -3774,7 +3712,7 @@ fn zirMakePtrConst(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro |
| 3774 | 3712 | // might have already done our job and created an anon decl ref. |
| 3775 | 3713 | switch (mod.intern_pool.indexToKey(ptr_val.toIntern())) { |
| 3776 | 3714 | .ptr => |ptr| switch (ptr.base_addr) { |
| 3777 | .anon_decl => { | |
| 3715 | .uav => { | |
| 3778 | 3716 | // The comptime-ification was already done for us. |
| 3779 | 3717 | // Just make sure the pointer is const. |
| 3780 | 3718 | return sema.makePtrConst(block, alloc); |
| ... | ... | @@ -3799,7 +3737,7 @@ fn zirMakePtrConst(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro |
| 3799 | 3737 | // Promote the constant to an anon decl. |
| 3800 | 3738 | const new_mut_ptr = Air.internedToRef(try pt.intern(.{ .ptr = .{ |
| 3801 | 3739 | .ty = alloc_ty.toIntern(), |
| 3802 | .base_addr = .{ .anon_decl = .{ | |
| 3740 | .base_addr = .{ .uav = .{ | |
| 3803 | 3741 | .val = interned.toIntern(), |
| 3804 | 3742 | .orig_ty = alloc_ty.toIntern(), |
| 3805 | 3743 | } }, |
| ... | ... | @@ -4097,7 +4035,7 @@ fn finishResolveComptimeKnownAllocPtr( |
| 4097 | 4035 | } else { |
| 4098 | 4036 | return try pt.intern(.{ .ptr = .{ |
| 4099 | 4037 | .ty = alloc_ty.toIntern(), |
| 4100 | .base_addr = .{ .anon_decl = .{ | |
| 4038 | .base_addr = .{ .uav = .{ | |
| 4101 | 4039 | .orig_ty = alloc_ty.toIntern(), |
| 4102 | 4040 | .val = result_val, |
| 4103 | 4041 | } }, |
| ... | ... | @@ -4250,7 +4188,7 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com |
| 4250 | 4188 | } |
| 4251 | 4189 | |
| 4252 | 4190 | const val = switch (mod.intern_pool.indexToKey(resolved_ptr).ptr.base_addr) { |
| 4253 | .anon_decl => |a| a.val, | |
| 4191 | .uav => |a| a.val, | |
| 4254 | 4192 | .comptime_alloc => |i| val: { |
| 4255 | 4193 | const alloc = sema.getComptimeAlloc(i); |
| 4256 | 4194 | break :val (try alloc.val.intern(pt, sema.arena)).toIntern(); |
| ... | ... | @@ -5505,22 +5443,23 @@ fn failWithBadMemberAccess( |
| 5505 | 5443 | field_name: InternPool.NullTerminatedString, |
| 5506 | 5444 | ) CompileError { |
| 5507 | 5445 | const pt = sema.pt; |
| 5508 | const mod = pt.zcu; | |
| 5509 | const kw_name = switch (agg_ty.zigTypeTag(mod)) { | |
| 5446 | const zcu = pt.zcu; | |
| 5447 | const ip = &zcu.intern_pool; | |
| 5448 | const kw_name = switch (agg_ty.zigTypeTag(zcu)) { | |
| 5510 | 5449 | .Union => "union", |
| 5511 | 5450 | .Struct => "struct", |
| 5512 | 5451 | .Opaque => "opaque", |
| 5513 | 5452 | .Enum => "enum", |
| 5514 | 5453 | else => unreachable, |
| 5515 | 5454 | }; |
| 5516 | if (agg_ty.getOwnerDeclOrNull(mod)) |some| if (mod.declIsRoot(some)) { | |
| 5455 | if (agg_ty.typeDeclInst(zcu)) |inst| if (inst.resolve(ip) == .main_struct_inst) { | |
| 5517 | 5456 | return sema.fail(block, field_src, "root struct of file '{}' has no member named '{}'", .{ |
| 5518 | agg_ty.fmt(pt), field_name.fmt(&mod.intern_pool), | |
| 5457 | agg_ty.fmt(pt), field_name.fmt(ip), | |
| 5519 | 5458 | }); |
| 5520 | 5459 | }; |
| 5521 | 5460 | |
| 5522 | 5461 | return sema.fail(block, field_src, "{s} '{}' has no member named '{}'", .{ |
| 5523 | kw_name, agg_ty.fmt(pt), field_name.fmt(&mod.intern_pool), | |
| 5462 | kw_name, agg_ty.fmt(pt), field_name.fmt(ip), | |
| 5524 | 5463 | }); |
| 5525 | 5464 | } |
| 5526 | 5465 | |
| ... | ... | @@ -5535,13 +5474,12 @@ fn failWithBadStructFieldAccess( |
| 5535 | 5474 | const pt = sema.pt; |
| 5536 | 5475 | const zcu = pt.zcu; |
| 5537 | 5476 | const ip = &zcu.intern_pool; |
| 5538 | const decl = zcu.declPtr(struct_type.decl.unwrap().?); | |
| 5539 | 5477 | |
| 5540 | 5478 | const msg = msg: { |
| 5541 | 5479 | const msg = try sema.errMsg( |
| 5542 | 5480 | field_src, |
| 5543 | 5481 | "no field named '{}' in struct '{}'", |
| 5544 | .{ field_name.fmt(ip), decl.fqn.fmt(ip) }, | |
| 5482 | .{ field_name.fmt(ip), struct_type.name.fmt(ip) }, | |
| 5545 | 5483 | ); |
| 5546 | 5484 | errdefer msg.destroy(sema.gpa); |
| 5547 | 5485 | try sema.errNote(struct_ty.srcLoc(zcu), msg, "struct declared here", .{}); |
| ... | ... | @@ -5562,13 +5500,12 @@ fn failWithBadUnionFieldAccess( |
| 5562 | 5500 | const zcu = pt.zcu; |
| 5563 | 5501 | const ip = &zcu.intern_pool; |
| 5564 | 5502 | const gpa = sema.gpa; |
| 5565 | const decl = zcu.declPtr(union_obj.decl); | |
| 5566 | 5503 | |
| 5567 | 5504 | const msg = msg: { |
| 5568 | 5505 | const msg = try sema.errMsg( |
| 5569 | 5506 | field_src, |
| 5570 | 5507 | "no field named '{}' in union '{}'", |
| 5571 | .{ field_name.fmt(ip), decl.fqn.fmt(ip) }, | |
| 5508 | .{ field_name.fmt(ip), union_obj.name.fmt(ip) }, | |
| 5572 | 5509 | ); |
| 5573 | 5510 | errdefer msg.destroy(gpa); |
| 5574 | 5511 | try sema.errNote(union_ty.srcLoc(zcu), msg, "union declared here", .{}); |
| ... | ... | @@ -5659,7 +5596,7 @@ fn storeToInferredAllocComptime( |
| 5659 | 5596 | if (iac.is_const and !operand_val.canMutateComptimeVarState(zcu)) { |
| 5660 | 5597 | iac.ptr = try pt.intern(.{ .ptr = .{ |
| 5661 | 5598 | .ty = alloc_ty.toIntern(), |
| 5662 | .base_addr = .{ .anon_decl = .{ | |
| 5599 | .base_addr = .{ .uav = .{ | |
| 5663 | 5600 | .val = operand_val.toIntern(), |
| 5664 | 5601 | .orig_ty = alloc_ty.toIntern(), |
| 5665 | 5602 | } }, |
| ... | ... | @@ -5748,11 +5685,11 @@ fn addStrLit(sema: *Sema, string: InternPool.String, len: u64) CompileError!Air. |
| 5748 | 5685 | .ty = array_ty.toIntern(), |
| 5749 | 5686 | .storage = .{ .bytes = string }, |
| 5750 | 5687 | } }); |
| 5751 | return anonDeclRef(sema, val); | |
| 5688 | return sema.uavRef(val); | |
| 5752 | 5689 | } |
| 5753 | 5690 | |
| 5754 | fn anonDeclRef(sema: *Sema, val: InternPool.Index) CompileError!Air.Inst.Ref { | |
| 5755 | return Air.internedToRef(try refValue(sema, val)); | |
| 5691 | fn uavRef(sema: *Sema, val: InternPool.Index) CompileError!Air.Inst.Ref { | |
| 5692 | return Air.internedToRef(try sema.refValue(val)); | |
| 5756 | 5693 | } |
| 5757 | 5694 | |
| 5758 | 5695 | fn refValue(sema: *Sema, val: InternPool.Index) CompileError!InternPool.Index { |
| ... | ... | @@ -5767,7 +5704,7 @@ fn refValue(sema: *Sema, val: InternPool.Index) CompileError!InternPool.Index { |
| 5767 | 5704 | })).toIntern(); |
| 5768 | 5705 | return pt.intern(.{ .ptr = .{ |
| 5769 | 5706 | .ty = ptr_ty, |
| 5770 | .base_addr = .{ .anon_decl = .{ | |
| 5707 | .base_addr = .{ .uav = .{ | |
| 5771 | 5708 | .val = val, |
| 5772 | 5709 | .orig_ty = ptr_ty, |
| 5773 | 5710 | } }, |
| ... | ... | @@ -5866,7 +5803,7 @@ fn zirCompileLog( |
| 5866 | 5803 | } |
| 5867 | 5804 | try writer.print("\n", .{}); |
| 5868 | 5805 | |
| 5869 | const gop = try mod.compile_log_sources.getOrPut(sema.gpa, sema.ownerUnit()); | |
| 5806 | const gop = try mod.compile_log_sources.getOrPut(sema.gpa, sema.owner); | |
| 5870 | 5807 | if (!gop.found_existing) gop.value_ptr.* = .{ |
| 5871 | 5808 | .base_node_inst = block.src_base_inst, |
| 5872 | 5809 | .node_offset = src_node, |
| ... | ... | @@ -6021,7 +5958,7 @@ fn zirCImport(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileEr |
| 6021 | 5958 | if (!comp.config.link_libc) |
| 6022 | 5959 | try sema.errNote(src, msg, "libc headers not available; compilation does not link against libc", .{}); |
| 6023 | 5960 | |
| 6024 | const gop = try zcu.cimport_errors.getOrPut(gpa, sema.ownerUnit()); | |
| 5961 | const gop = try zcu.cimport_errors.getOrPut(gpa, sema.owner); | |
| 6025 | 5962 | if (!gop.found_existing) { |
| 6026 | 5963 | gop.value_ptr.* = c_import_res.errors; |
| 6027 | 5964 | c_import_res.errors = std.zig.ErrorBundle.empty; |
| ... | ... | @@ -6069,13 +6006,15 @@ fn zirCImport(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileEr |
| 6069 | 6006 | return sema.fail(&child_block, src, "C import failed: {s}", .{@errorName(err)}); |
| 6070 | 6007 | |
| 6071 | 6008 | const path_digest = zcu.filePathDigest(result.file_index); |
| 6072 | const root_decl = zcu.fileRootDecl(result.file_index); | |
| 6073 | pt.astGenFile(result.file, path_digest, root_decl) catch |err| | |
| 6009 | const old_root_type = zcu.fileRootType(result.file_index); | |
| 6010 | pt.astGenFile(result.file, path_digest, old_root_type) catch |err| | |
| 6074 | 6011 | return sema.fail(&child_block, src, "C import failed: {s}", .{@errorName(err)}); |
| 6075 | 6012 | |
| 6013 | // TODO: register some kind of dependency on the file. | |
| 6014 | // That way, if this returns `error.AnalysisFail`, we have the dependency banked ready to | |
| 6015 | // trigger re-analysis later. | |
| 6076 | 6016 | try pt.ensureFileAnalyzed(result.file_index); |
| 6077 | const file_root_decl_index = zcu.fileRootDecl(result.file_index).unwrap().?; | |
| 6078 | return sema.analyzeDeclVal(parent_block, src, file_root_decl_index); | |
| 6017 | return Air.internedToRef(zcu.fileRootType(result.file_index)); | |
| 6079 | 6018 | } |
| 6080 | 6019 | |
| 6081 | 6020 | fn zirSuspendBlock(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| ... | ... | @@ -6423,36 +6362,40 @@ fn zirExport(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void |
| 6423 | 6362 | defer tracy.end(); |
| 6424 | 6363 | |
| 6425 | 6364 | const pt = sema.pt; |
| 6426 | const mod = pt.zcu; | |
| 6365 | const zcu = pt.zcu; | |
| 6366 | const ip = &zcu.intern_pool; | |
| 6427 | 6367 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; |
| 6428 | 6368 | const extra = sema.code.extraData(Zir.Inst.Export, inst_data.payload_index).data; |
| 6429 | 6369 | const src = block.nodeOffset(inst_data.src_node); |
| 6430 | 6370 | const operand_src = block.builtinCallArgSrc(inst_data.src_node, 0); |
| 6431 | 6371 | const options_src = block.builtinCallArgSrc(inst_data.src_node, 1); |
| 6432 | const decl_name = try mod.intern_pool.getOrPutString( | |
| 6433 | mod.gpa, | |
| 6372 | const decl_name = try ip.getOrPutString( | |
| 6373 | zcu.gpa, | |
| 6434 | 6374 | pt.tid, |
| 6435 | 6375 | sema.code.nullTerminatedString(extra.decl_name), |
| 6436 | 6376 | .no_embedded_nulls, |
| 6437 | 6377 | ); |
| 6438 | const decl_index = if (extra.namespace != .none) index_blk: { | |
| 6378 | const nav_index = if (extra.namespace != .none) index_blk: { | |
| 6439 | 6379 | const container_ty = try sema.resolveType(block, operand_src, extra.namespace); |
| 6440 | const container_namespace = container_ty.getNamespaceIndex(mod); | |
| 6380 | const container_namespace = container_ty.getNamespaceIndex(zcu); | |
| 6441 | 6381 | |
| 6442 | const maybe_index = try sema.lookupInNamespace(block, operand_src, container_namespace, decl_name, false); | |
| 6443 | break :index_blk maybe_index orelse | |
| 6382 | const lookup = try sema.lookupInNamespace(block, operand_src, container_namespace, decl_name, false) orelse | |
| 6444 | 6383 | return sema.failWithBadMemberAccess(block, container_ty, operand_src, decl_name); |
| 6384 | ||
| 6385 | break :index_blk lookup.nav; | |
| 6445 | 6386 | } else try sema.lookupIdentifier(block, operand_src, decl_name); |
| 6446 | 6387 | const options = try sema.resolveExportOptions(block, options_src, extra.options); |
| 6447 | { | |
| 6448 | try sema.addReferenceEntry(src, AnalUnit.wrap(.{ .decl = decl_index })); | |
| 6449 | try sema.ensureDeclAnalyzed(decl_index); | |
| 6450 | const exported_decl = mod.declPtr(decl_index); | |
| 6451 | if (exported_decl.val.getFunction(mod)) |function| { | |
| 6452 | return sema.analyzeExport(block, src, options, function.owner_decl); | |
| 6453 | } | |
| 6454 | } | |
| 6455 | try sema.analyzeExport(block, src, options, decl_index); | |
| 6388 | ||
| 6389 | try sema.ensureNavResolved(src, nav_index); | |
| 6390 | ||
| 6391 | // Make sure to export the owner Nav if applicable. | |
| 6392 | const exported_nav = switch (ip.indexToKey(ip.getNav(nav_index).status.resolved.val)) { | |
| 6393 | .variable => |v| v.owner_nav, | |
| 6394 | .@"extern" => |e| e.owner_nav, | |
| 6395 | .func => |f| f.owner_nav, | |
| 6396 | else => nav_index, | |
| 6397 | }; | |
| 6398 | try sema.analyzeExport(block, src, options, exported_nav); | |
| 6456 | 6399 | } |
| 6457 | 6400 | |
| 6458 | 6401 | fn zirExportValue(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void { |
| ... | ... | @@ -6460,7 +6403,8 @@ fn zirExportValue(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 6460 | 6403 | defer tracy.end(); |
| 6461 | 6404 | |
| 6462 | 6405 | const pt = sema.pt; |
| 6463 | const mod = pt.zcu; | |
| 6406 | const zcu = pt.zcu; | |
| 6407 | const ip = &zcu.intern_pool; | |
| 6464 | 6408 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; |
| 6465 | 6409 | const extra = sema.code.extraData(Zir.Inst.ExportValue, inst_data.payload_index).data; |
| 6466 | 6410 | const src = block.nodeOffset(inst_data.src_node); |
| ... | ... | @@ -6472,17 +6416,24 @@ fn zirExportValue(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 6472 | 6416 | const options = try sema.resolveExportOptions(block, options_src, extra.options); |
| 6473 | 6417 | if (options.linkage == .internal) |
| 6474 | 6418 | return; |
| 6475 | if (operand.getFunction(mod)) |function| { | |
| 6476 | const decl_index = function.owner_decl; | |
| 6477 | return sema.analyzeExport(block, src, options, decl_index); | |
| 6478 | } | |
| 6479 | 6419 | |
| 6480 | try sema.exports.append(mod.gpa, .{ | |
| 6481 | .opts = options, | |
| 6482 | .src = src, | |
| 6483 | .exported = .{ .value = operand.toIntern() }, | |
| 6484 | .status = .in_progress, | |
| 6485 | }); | |
| 6420 | // If the value has an owner Nav, export that instead. | |
| 6421 | const maybe_owner_nav = switch (ip.indexToKey(operand.toIntern())) { | |
| 6422 | .variable => |v| v.owner_nav, | |
| 6423 | .@"extern" => |e| e.owner_nav, | |
| 6424 | .func => |f| f.owner_nav, | |
| 6425 | else => null, | |
| 6426 | }; | |
| 6427 | if (maybe_owner_nav) |owner_nav| { | |
| 6428 | return sema.analyzeExport(block, src, options, owner_nav); | |
| 6429 | } else { | |
| 6430 | try sema.exports.append(zcu.gpa, .{ | |
| 6431 | .opts = options, | |
| 6432 | .src = src, | |
| 6433 | .exported = .{ .uav = operand.toIntern() }, | |
| 6434 | .status = .in_progress, | |
| 6435 | }); | |
| 6436 | } | |
| 6486 | 6437 | } |
| 6487 | 6438 | |
| 6488 | 6439 | pub fn analyzeExport( |
| ... | ... | @@ -6490,22 +6441,22 @@ pub fn analyzeExport( |
| 6490 | 6441 | block: *Block, |
| 6491 | 6442 | src: LazySrcLoc, |
| 6492 | 6443 | options: Module.Export.Options, |
| 6493 | exported_decl_index: InternPool.DeclIndex, | |
| 6444 | exported_nav_index: InternPool.Nav.Index, | |
| 6494 | 6445 | ) !void { |
| 6495 | 6446 | const gpa = sema.gpa; |
| 6496 | 6447 | const pt = sema.pt; |
| 6497 | const mod = pt.zcu; | |
| 6448 | const zcu = pt.zcu; | |
| 6449 | const ip = &zcu.intern_pool; | |
| 6498 | 6450 | |
| 6499 | 6451 | if (options.linkage == .internal) |
| 6500 | 6452 | return; |
| 6501 | 6453 | |
| 6502 | try sema.addReferenceEntry(src, AnalUnit.wrap(.{ .decl = exported_decl_index })); | |
| 6503 | try sema.ensureDeclAnalyzed(exported_decl_index); | |
| 6504 | const exported_decl = mod.declPtr(exported_decl_index); | |
| 6505 | const export_ty = exported_decl.typeOf(mod); | |
| 6454 | try sema.ensureNavResolved(src, exported_nav_index); | |
| 6455 | const exported_nav = ip.getNav(exported_nav_index); | |
| 6456 | const export_ty = Type.fromInterned(exported_nav.typeOf(ip)); | |
| 6506 | 6457 | |
| 6507 | 6458 | if (!try sema.validateExternType(export_ty, .other)) { |
| 6508 | const msg = msg: { | |
| 6459 | return sema.failWithOwnedErrorMsg(block, msg: { | |
| 6509 | 6460 | const msg = try sema.errMsg(src, "unable to export type '{}'", .{export_ty.fmt(pt)}); |
| 6510 | 6461 | errdefer msg.destroy(gpa); |
| 6511 | 6462 | |
| ... | ... | @@ -6513,59 +6464,50 @@ pub fn analyzeExport( |
| 6513 | 6464 | |
| 6514 | 6465 | try sema.addDeclaredHereNote(msg, export_ty); |
| 6515 | 6466 | break :msg msg; |
| 6516 | }; | |
| 6517 | return sema.failWithOwnedErrorMsg(block, msg); | |
| 6467 | }); | |
| 6518 | 6468 | } |
| 6519 | 6469 | |
| 6520 | 6470 | // TODO: some backends might support re-exporting extern decls |
| 6521 | if (exported_decl.isExtern(mod)) { | |
| 6471 | if (exported_nav.isExtern(ip)) { | |
| 6522 | 6472 | return sema.fail(block, src, "export target cannot be extern", .{}); |
| 6523 | 6473 | } |
| 6524 | 6474 | |
| 6525 | try sema.maybeQueueFuncBodyAnalysis(src, exported_decl_index); | |
| 6475 | try sema.maybeQueueFuncBodyAnalysis(src, exported_nav_index); | |
| 6526 | 6476 | |
| 6527 | 6477 | try sema.exports.append(gpa, .{ |
| 6528 | 6478 | .opts = options, |
| 6529 | 6479 | .src = src, |
| 6530 | .exported = .{ .decl_index = exported_decl_index }, | |
| 6480 | .exported = .{ .nav = exported_nav_index }, | |
| 6531 | 6481 | .status = .in_progress, |
| 6532 | 6482 | }); |
| 6533 | 6483 | } |
| 6534 | 6484 | |
| 6535 | 6485 | fn zirSetAlignStack(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!void { |
| 6536 | 6486 | const pt = sema.pt; |
| 6537 | const mod = pt.zcu; | |
| 6487 | const zcu = pt.zcu; | |
| 6538 | 6488 | const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data; |
| 6539 | 6489 | const operand_src = block.builtinCallArgSrc(extra.node, 0); |
| 6540 | 6490 | const src = block.nodeOffset(extra.node); |
| 6541 | 6491 | const alignment = try sema.resolveAlign(block, operand_src, extra.operand); |
| 6492 | ||
| 6493 | const func = switch (sema.owner.unwrap()) { | |
| 6494 | .func => |func| func, | |
| 6495 | .cau => return sema.fail(block, src, "@setAlignStack outside of function scope", .{}), | |
| 6496 | }; | |
| 6497 | ||
| 6542 | 6498 | if (alignment.order(Alignment.fromNonzeroByteUnits(256)).compare(.gt)) { |
| 6543 | 6499 | return sema.fail(block, src, "attempt to @setAlignStack({d}); maximum is 256", .{ |
| 6544 | 6500 | alignment.toByteUnits().?, |
| 6545 | 6501 | }); |
| 6546 | 6502 | } |
| 6547 | 6503 | |
| 6548 | const fn_owner_decl = mod.funcOwnerDeclPtr(sema.func_index); | |
| 6549 | switch (fn_owner_decl.typeOf(mod).fnCallingConvention(mod)) { | |
| 6504 | switch (Value.fromInterned(func).typeOf(zcu).fnCallingConvention(zcu)) { | |
| 6550 | 6505 | .Naked => return sema.fail(block, src, "@setAlignStack in naked function", .{}), |
| 6551 | 6506 | .Inline => return sema.fail(block, src, "@setAlignStack in inline function", .{}), |
| 6552 | else => if (block.inlining != null) { | |
| 6553 | return sema.fail(block, src, "@setAlignStack in inline call", .{}); | |
| 6554 | }, | |
| 6555 | } | |
| 6556 | ||
| 6557 | if (sema.prev_stack_alignment_src) |prev_src| { | |
| 6558 | const msg = msg: { | |
| 6559 | const msg = try sema.errMsg(src, "multiple @setAlignStack in the same function body", .{}); | |
| 6560 | errdefer msg.destroy(sema.gpa); | |
| 6561 | try sema.errNote(prev_src, msg, "other instance here", .{}); | |
| 6562 | break :msg msg; | |
| 6563 | }; | |
| 6564 | return sema.failWithOwnedErrorMsg(block, msg); | |
| 6507 | else => {}, | |
| 6565 | 6508 | } |
| 6566 | sema.prev_stack_alignment_src = src; | |
| 6567 | 6509 | |
| 6568 | mod.intern_pool.funcMaxStackAlignment(sema.func_index, alignment); | |
| 6510 | zcu.intern_pool.funcMaxStackAlignment(sema.func_index, alignment); | |
| 6569 | 6511 | } |
| 6570 | 6512 | |
| 6571 | 6513 | fn zirSetCold(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!void { |
| ... | ... | @@ -6577,16 +6519,24 @@ fn zirSetCold(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) |
| 6577 | 6519 | const is_cold = try sema.resolveConstBool(block, operand_src, extra.operand, .{ |
| 6578 | 6520 | .needed_comptime_reason = "operand to @setCold must be comptime-known", |
| 6579 | 6521 | }); |
| 6580 | if (sema.func_index == .none) return; // does nothing outside a function | |
| 6581 | ip.funcSetCold(sema.func_index, is_cold); | |
| 6522 | // TODO: should `@setCold` apply to the parent in an inline call? | |
| 6523 | // See also #20642 and friends. | |
| 6524 | const func = switch (sema.owner.unwrap()) { | |
| 6525 | .func => |func| func, | |
| 6526 | .cau => return, // does nothing outside a function | |
| 6527 | }; | |
| 6528 | ip.funcSetCold(func, is_cold); | |
| 6582 | 6529 | } |
| 6583 | 6530 | |
| 6584 | 6531 | fn zirDisableInstrumentation(sema: *Sema) CompileError!void { |
| 6585 | 6532 | const pt = sema.pt; |
| 6586 | 6533 | const mod = pt.zcu; |
| 6587 | 6534 | const ip = &mod.intern_pool; |
| 6588 | if (sema.func_index == .none) return; // does nothing outside a function | |
| 6589 | ip.funcSetDisableInstrumentation(sema.func_index); | |
| 6535 | const func = switch (sema.owner.unwrap()) { | |
| 6536 | .func => |func| func, | |
| 6537 | .cau => return, // does nothing outside a function | |
| 6538 | }; | |
| 6539 | ip.funcSetDisableInstrumentation(func); | |
| 6590 | 6540 | } |
| 6591 | 6541 | |
| 6592 | 6542 | fn zirSetFloatMode(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!void { |
| ... | ... | @@ -6760,8 +6710,8 @@ fn zirDeclRef(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 6760 | 6710 | inst_data.get(sema.code), |
| 6761 | 6711 | .no_embedded_nulls, |
| 6762 | 6712 | ); |
| 6763 | const decl_index = try sema.lookupIdentifier(block, src, decl_name); | |
| 6764 | return sema.analyzeDeclRef(src, decl_index); | |
| 6713 | const nav_index = try sema.lookupIdentifier(block, src, decl_name); | |
| 6714 | return sema.analyzeNavRef(src, nav_index); | |
| 6765 | 6715 | } |
| 6766 | 6716 | |
| 6767 | 6717 | fn zirDeclVal(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| ... | ... | @@ -6775,17 +6725,18 @@ fn zirDeclVal(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 6775 | 6725 | inst_data.get(sema.code), |
| 6776 | 6726 | .no_embedded_nulls, |
| 6777 | 6727 | ); |
| 6778 | const decl = try sema.lookupIdentifier(block, src, decl_name); | |
| 6779 | return sema.analyzeDeclVal(block, src, decl); | |
| 6728 | const nav = try sema.lookupIdentifier(block, src, decl_name); | |
| 6729 | return sema.analyzeNavVal(block, src, nav); | |
| 6780 | 6730 | } |
| 6781 | 6731 | |
| 6782 | fn lookupIdentifier(sema: *Sema, block: *Block, src: LazySrcLoc, name: InternPool.NullTerminatedString) !InternPool.DeclIndex { | |
| 6732 | fn lookupIdentifier(sema: *Sema, block: *Block, src: LazySrcLoc, name: InternPool.NullTerminatedString) !InternPool.Nav.Index { | |
| 6783 | 6733 | const pt = sema.pt; |
| 6784 | 6734 | const mod = pt.zcu; |
| 6785 | 6735 | var namespace = block.namespace; |
| 6786 | 6736 | while (true) { |
| 6787 | if (try sema.lookupInNamespace(block, src, namespace.toOptional(), name, false)) |decl_index| { | |
| 6788 | return decl_index; | |
| 6737 | if (try sema.lookupInNamespace(block, src, namespace, name, false)) |lookup| { | |
| 6738 | assert(lookup.accessible); | |
| 6739 | return lookup.nav; | |
| 6789 | 6740 | } |
| 6790 | 6741 | namespace = mod.namespacePtr(namespace).parent.unwrap() orelse break; |
| 6791 | 6742 | } |
| ... | ... | @@ -6798,69 +6749,74 @@ fn lookupInNamespace( |
| 6798 | 6749 | sema: *Sema, |
| 6799 | 6750 | block: *Block, |
| 6800 | 6751 | src: LazySrcLoc, |
| 6801 | opt_namespace_index: InternPool.OptionalNamespaceIndex, | |
| 6752 | namespace_index: InternPool.NamespaceIndex, | |
| 6802 | 6753 | ident_name: InternPool.NullTerminatedString, |
| 6803 | 6754 | observe_usingnamespace: bool, |
| 6804 | ) CompileError!?InternPool.DeclIndex { | |
| 6755 | ) CompileError!?struct { | |
| 6756 | nav: InternPool.Nav.Index, | |
| 6757 | /// If `false`, the declaration is in a different file and is not `pub`. | |
| 6758 | /// We still return the declaration for better error reporting. | |
| 6759 | accessible: bool, | |
| 6760 | } { | |
| 6805 | 6761 | const pt = sema.pt; |
| 6806 | const mod = pt.zcu; | |
| 6762 | const zcu = pt.zcu; | |
| 6763 | const ip = &zcu.intern_pool; | |
| 6807 | 6764 | |
| 6808 | const namespace_index = opt_namespace_index.unwrap() orelse return null; | |
| 6809 | const namespace = mod.namespacePtr(namespace_index); | |
| 6810 | const namespace_decl = mod.declPtr(namespace.decl_index); | |
| 6811 | if (namespace_decl.analysis == .file_failure) { | |
| 6812 | return error.AnalysisFail; | |
| 6813 | } | |
| 6765 | const namespace = zcu.namespacePtr(namespace_index); | |
| 6814 | 6766 | |
| 6815 | if (observe_usingnamespace and namespace.usingnamespace_set.count() != 0) { | |
| 6816 | const src_file = mod.namespacePtr(block.namespace).file_scope; | |
| 6767 | const adapter: Zcu.Namespace.NameAdapter = .{ .zcu = zcu }; | |
| 6817 | 6768 | |
| 6769 | const src_file = zcu.namespacePtr(block.namespace).file_scope; | |
| 6770 | ||
| 6771 | if (observe_usingnamespace and (namespace.pub_usingnamespace.items.len != 0 or namespace.priv_usingnamespace.items.len != 0)) { | |
| 6818 | 6772 | const gpa = sema.gpa; |
| 6819 | var checked_namespaces: std.AutoArrayHashMapUnmanaged(*Namespace, bool) = .{}; | |
| 6773 | var checked_namespaces: std.AutoArrayHashMapUnmanaged(*Namespace, void) = .{}; | |
| 6820 | 6774 | defer checked_namespaces.deinit(gpa); |
| 6821 | 6775 | |
| 6822 | 6776 | // Keep track of name conflicts for error notes. |
| 6823 | var candidates: std.ArrayListUnmanaged(InternPool.DeclIndex) = .{}; | |
| 6777 | var candidates: std.ArrayListUnmanaged(InternPool.Nav.Index) = .{}; | |
| 6824 | 6778 | defer candidates.deinit(gpa); |
| 6825 | 6779 | |
| 6826 | try checked_namespaces.put(gpa, namespace, namespace.file_scope == src_file); | |
| 6780 | try checked_namespaces.put(gpa, namespace, {}); | |
| 6827 | 6781 | var check_i: usize = 0; |
| 6828 | 6782 | |
| 6829 | 6783 | while (check_i < checked_namespaces.count()) : (check_i += 1) { |
| 6830 | 6784 | const check_ns = checked_namespaces.keys()[check_i]; |
| 6831 | if (check_ns.decls.getKeyAdapted(ident_name, Module.DeclAdapter{ .zcu = mod })) |decl_index| { | |
| 6832 | // Skip decls which are not marked pub, which are in a different | |
| 6833 | // file than the `a.b`/`@hasDecl` syntax. | |
| 6834 | const decl = mod.declPtr(decl_index); | |
| 6835 | if (decl.is_pub or (src_file == decl.getFileScopeIndex(mod) and | |
| 6836 | checked_namespaces.values()[check_i])) | |
| 6837 | { | |
| 6838 | try candidates.append(gpa, decl_index); | |
| 6839 | } | |
| 6840 | } | |
| 6841 | var it = check_ns.usingnamespace_set.iterator(); | |
| 6842 | while (it.next()) |entry| { | |
| 6843 | const sub_usingnamespace_decl_index = entry.key_ptr.*; | |
| 6844 | // Skip the decl we're currently analysing. | |
| 6845 | if (sub_usingnamespace_decl_index == sema.owner_decl_index) continue; | |
| 6846 | const sub_usingnamespace_decl = mod.declPtr(sub_usingnamespace_decl_index); | |
| 6847 | const sub_is_pub = entry.value_ptr.*; | |
| 6848 | if (!sub_is_pub and src_file != sub_usingnamespace_decl.getFileScopeIndex(mod)) { | |
| 6849 | // Skip usingnamespace decls which are not marked pub, which are in | |
| 6850 | // a different file than the `a.b`/`@hasDecl` syntax. | |
| 6785 | const Pass = enum { @"pub", priv }; | |
| 6786 | for ([2]Pass{ .@"pub", .priv }) |pass| { | |
| 6787 | if (pass == .priv and src_file != check_ns.file_scope) { | |
| 6851 | 6788 | continue; |
| 6852 | 6789 | } |
| 6853 | try sema.ensureDeclAnalyzed(sub_usingnamespace_decl_index); | |
| 6854 | const ns_ty = sub_usingnamespace_decl.val.toType(); | |
| 6855 | const sub_ns = mod.namespacePtrUnwrap(ns_ty.getNamespaceIndex(mod)) orelse continue; | |
| 6856 | try checked_namespaces.put(gpa, sub_ns, src_file == sub_usingnamespace_decl.getFileScopeIndex(mod)); | |
| 6790 | ||
| 6791 | const decls, const usingnamespaces = switch (pass) { | |
| 6792 | .@"pub" => .{ &check_ns.pub_decls, &check_ns.pub_usingnamespace }, | |
| 6793 | .priv => .{ &check_ns.priv_decls, &check_ns.priv_usingnamespace }, | |
| 6794 | }; | |
| 6795 | ||
| 6796 | if (decls.getKeyAdapted(ident_name, adapter)) |nav_index| { | |
| 6797 | try candidates.append(gpa, nav_index); | |
| 6798 | } | |
| 6799 | ||
| 6800 | for (usingnamespaces.items) |sub_ns_nav| { | |
| 6801 | try sema.ensureNavResolved(src, sub_ns_nav); | |
| 6802 | const sub_ns_ty = Type.fromInterned(ip.getNav(sub_ns_nav).status.resolved.val); | |
| 6803 | const sub_ns = zcu.namespacePtr(sub_ns_ty.getNamespaceIndex(zcu)); | |
| 6804 | try checked_namespaces.put(gpa, sub_ns, {}); | |
| 6805 | } | |
| 6857 | 6806 | } |
| 6858 | 6807 | } |
| 6859 | 6808 | |
| 6860 | { | |
| 6809 | ignore_self: { | |
| 6810 | const skip_nav = switch (sema.owner.unwrap()) { | |
| 6811 | .func => break :ignore_self, | |
| 6812 | .cau => |cau| switch (ip.getCau(cau).owner.unwrap()) { | |
| 6813 | .none, .type => break :ignore_self, | |
| 6814 | .nav => |nav| nav, | |
| 6815 | }, | |
| 6816 | }; | |
| 6861 | 6817 | var i: usize = 0; |
| 6862 | 6818 | while (i < candidates.items.len) { |
| 6863 | if (candidates.items[i] == sema.owner_decl_index) { | |
| 6819 | if (candidates.items[i] == skip_nav) { | |
| 6864 | 6820 | _ = candidates.orderedRemove(i); |
| 6865 | 6821 | } else { |
| 6866 | 6822 | i += 1; |
| ... | ... | @@ -6870,48 +6826,50 @@ fn lookupInNamespace( |
| 6870 | 6826 | |
| 6871 | 6827 | switch (candidates.items.len) { |
| 6872 | 6828 | 0 => {}, |
| 6873 | 1 => { | |
| 6874 | const decl_index = candidates.items[0]; | |
| 6875 | return decl_index; | |
| 6876 | }, | |
| 6877 | else => { | |
| 6878 | const msg = msg: { | |
| 6879 | const msg = try sema.errMsg(src, "ambiguous reference", .{}); | |
| 6880 | errdefer msg.destroy(gpa); | |
| 6881 | for (candidates.items) |candidate_index| { | |
| 6882 | const candidate = mod.declPtr(candidate_index); | |
| 6883 | try sema.errNote(.{ | |
| 6884 | .base_node_inst = candidate.zir_decl_index.unwrap().?, | |
| 6885 | .offset = LazySrcLoc.Offset.nodeOffset(0), | |
| 6886 | }, msg, "declared here", .{}); | |
| 6887 | } | |
| 6888 | break :msg msg; | |
| 6889 | }; | |
| 6890 | return sema.failWithOwnedErrorMsg(block, msg); | |
| 6829 | 1 => return .{ | |
| 6830 | .nav = candidates.items[0], | |
| 6831 | .accessible = true, | |
| 6891 | 6832 | }, |
| 6833 | else => return sema.failWithOwnedErrorMsg(block, msg: { | |
| 6834 | const msg = try sema.errMsg(src, "ambiguous reference", .{}); | |
| 6835 | errdefer msg.destroy(gpa); | |
| 6836 | for (candidates.items) |candidate| { | |
| 6837 | try sema.errNote(zcu.navSrcLoc(candidate), msg, "declared here", .{}); | |
| 6838 | } | |
| 6839 | break :msg msg; | |
| 6840 | }), | |
| 6892 | 6841 | } |
| 6893 | } else if (namespace.decls.getKeyAdapted(ident_name, Module.DeclAdapter{ .zcu = mod })) |decl_index| { | |
| 6894 | return decl_index; | |
| 6842 | } else if (namespace.pub_decls.getKeyAdapted(ident_name, adapter)) |nav_index| { | |
| 6843 | return .{ | |
| 6844 | .nav = nav_index, | |
| 6845 | .accessible = true, | |
| 6846 | }; | |
| 6847 | } else if (namespace.priv_decls.getKeyAdapted(ident_name, adapter)) |nav_index| { | |
| 6848 | return .{ | |
| 6849 | .nav = nav_index, | |
| 6850 | .accessible = src_file == namespace.file_scope, | |
| 6851 | }; | |
| 6895 | 6852 | } |
| 6896 | 6853 | |
| 6897 | 6854 | return null; |
| 6898 | 6855 | } |
| 6899 | 6856 | |
| 6900 | fn funcDeclSrc(sema: *Sema, func_inst: Air.Inst.Ref) !?*Decl { | |
| 6857 | fn funcDeclSrcInst(sema: *Sema, func_inst: Air.Inst.Ref) !?InternPool.TrackedInst.Index { | |
| 6901 | 6858 | const pt = sema.pt; |
| 6902 | const mod = pt.zcu; | |
| 6903 | const func_val = (try sema.resolveValue(func_inst)) orelse return null; | |
| 6904 | if (func_val.isUndef(mod)) return null; | |
| 6905 | const owner_decl_index = switch (mod.intern_pool.indexToKey(func_val.toIntern())) { | |
| 6906 | .extern_func => |extern_func| extern_func.decl, | |
| 6907 | .func => |func| func.owner_decl, | |
| 6859 | const zcu = pt.zcu; | |
| 6860 | const ip = &zcu.intern_pool; | |
| 6861 | const func_val = try sema.resolveValue(func_inst) orelse return null; | |
| 6862 | if (func_val.isUndef(zcu)) return null; | |
| 6863 | const nav = switch (ip.indexToKey(func_val.toIntern())) { | |
| 6864 | .@"extern" => |e| e.owner_nav, | |
| 6865 | .func => |f| f.owner_nav, | |
| 6908 | 6866 | .ptr => |ptr| switch (ptr.base_addr) { |
| 6909 | .decl => |decl| if (ptr.byte_offset == 0) mod.declPtr(decl).val.getFunction(mod).?.owner_decl else return null, | |
| 6867 | .nav => |nav| if (ptr.byte_offset == 0) nav else return null, | |
| 6910 | 6868 | else => return null, |
| 6911 | 6869 | }, |
| 6912 | 6870 | else => return null, |
| 6913 | 6871 | }; |
| 6914 | return mod.declPtr(owner_decl_index); | |
| 6872 | return ip.getNav(nav).srcInst(ip); | |
| 6915 | 6873 | } |
| 6916 | 6874 | |
| 6917 | 6875 | pub fn analyzeSaveErrRetIndex(sema: *Sema, block: *Block) SemaError!Air.Inst.Ref { |
| ... | ... | @@ -7100,11 +7058,12 @@ fn zirCall( |
| 7100 | 7058 | const call_dbg_node: Zir.Inst.Index = @enumFromInt(@intFromEnum(inst) - 1); |
| 7101 | 7059 | const call_inst = try sema.analyzeCall(block, func, func_ty, callee_src, call_src, modifier, ensure_result_used, args_info, call_dbg_node, .call); |
| 7102 | 7060 | |
| 7103 | if (sema.owner_func_index == .none or | |
| 7104 | !mod.intern_pool.funcAnalysisUnordered(sema.owner_func_index).calls_or_awaits_errorable_fn) | |
| 7105 | { | |
| 7106 | // No errorable fn actually called; we have no error return trace | |
| 7107 | input_is_error = false; | |
| 7061 | switch (sema.owner.unwrap()) { | |
| 7062 | .cau => input_is_error = false, | |
| 7063 | .func => |owner_func| if (!mod.intern_pool.funcAnalysisUnordered(owner_func).calls_or_awaits_errorable_fn) { | |
| 7064 | // No errorable fn actually called; we have no error return trace | |
| 7065 | input_is_error = false; | |
| 7066 | }, | |
| 7108 | 7067 | } |
| 7109 | 7068 | |
| 7110 | 7069 | if (block.ownerModule().error_tracing and |
| ... | ... | @@ -7199,7 +7158,7 @@ fn checkCallArgumentCount( |
| 7199 | 7158 | return func_ty; |
| 7200 | 7159 | } |
| 7201 | 7160 | |
| 7202 | const maybe_decl = try sema.funcDeclSrc(func); | |
| 7161 | const maybe_func_inst = try sema.funcDeclSrcInst(func); | |
| 7203 | 7162 | const member_str = if (member_fn) "member function " else ""; |
| 7204 | 7163 | const variadic_str = if (func_ty_info.is_var_args) "at least " else ""; |
| 7205 | 7164 | const msg = msg: { |
| ... | ... | @@ -7215,9 +7174,9 @@ fn checkCallArgumentCount( |
| 7215 | 7174 | ); |
| 7216 | 7175 | errdefer msg.destroy(sema.gpa); |
| 7217 | 7176 | |
| 7218 | if (maybe_decl) |fn_decl| { | |
| 7177 | if (maybe_func_inst) |func_inst| { | |
| 7219 | 7178 | try sema.errNote(.{ |
| 7220 | .base_node_inst = fn_decl.zir_decl_index.unwrap().?, | |
| 7179 | .base_node_inst = func_inst, | |
| 7221 | 7180 | .offset = LazySrcLoc.Offset.nodeOffset(0), |
| 7222 | 7181 | }, msg, "function declared here", .{}); |
| 7223 | 7182 | } |
| ... | ... | @@ -7544,7 +7503,7 @@ fn analyzeCall( |
| 7544 | 7503 | if (func_val.isUndef(mod)) |
| 7545 | 7504 | return sema.failWithUseOfUndef(block, call_src); |
| 7546 | 7505 | if (cc == .Naked) { |
| 7547 | const maybe_decl = try sema.funcDeclSrc(func); | |
| 7506 | const maybe_func_inst = try sema.funcDeclSrcInst(func); | |
| 7548 | 7507 | const msg = msg: { |
| 7549 | 7508 | const msg = try sema.errMsg( |
| 7550 | 7509 | func_src, |
| ... | ... | @@ -7553,8 +7512,8 @@ fn analyzeCall( |
| 7553 | 7512 | ); |
| 7554 | 7513 | errdefer msg.destroy(sema.gpa); |
| 7555 | 7514 | |
| 7556 | if (maybe_decl) |fn_decl| try sema.errNote(.{ | |
| 7557 | .base_node_inst = fn_decl.zir_decl_index.unwrap().?, | |
| 7515 | if (maybe_func_inst) |func_inst| try sema.errNote(.{ | |
| 7516 | .base_node_inst = func_inst, | |
| 7558 | 7517 | .offset = LazySrcLoc.Offset.nodeOffset(0), |
| 7559 | 7518 | }, msg, "function declared here", .{}); |
| 7560 | 7519 | break :msg msg; |
| ... | ... | @@ -7654,33 +7613,32 @@ fn analyzeCall( |
| 7654 | 7613 | .block_comptime_reason = comptime_reason, |
| 7655 | 7614 | }); |
| 7656 | 7615 | const module_fn_index = switch (mod.intern_pool.indexToKey(func_val.toIntern())) { |
| 7657 | .extern_func => return sema.fail(block, call_src, "{s} call of extern function", .{ | |
| 7616 | .@"extern" => return sema.fail(block, call_src, "{s} call of extern function", .{ | |
| 7658 | 7617 | @as([]const u8, if (is_comptime_call) "comptime" else "inline"), |
| 7659 | 7618 | }), |
| 7660 | 7619 | .func => func_val.toIntern(), |
| 7661 | 7620 | .ptr => |ptr| blk: { |
| 7662 | 7621 | switch (ptr.base_addr) { |
| 7663 | .decl => |decl| if (ptr.byte_offset == 0) { | |
| 7664 | const func_val_ptr = mod.declPtr(decl).val.toIntern(); | |
| 7665 | const intern_index = mod.intern_pool.indexToKey(func_val_ptr); | |
| 7666 | if (intern_index == .extern_func or (intern_index == .variable and intern_index.variable.is_extern)) | |
| 7622 | .nav => |nav_index| if (ptr.byte_offset == 0) { | |
| 7623 | const nav = ip.getNav(nav_index); | |
| 7624 | if (nav.isExtern(ip)) | |
| 7667 | 7625 | return sema.fail(block, call_src, "{s} call of extern function pointer", .{ |
| 7668 | @as([]const u8, if (is_comptime_call) "comptime" else "inline"), | |
| 7626 | if (is_comptime_call) "comptime" else "inline", | |
| 7669 | 7627 | }); |
| 7670 | break :blk func_val_ptr; | |
| 7628 | break :blk nav.status.resolved.val; | |
| 7671 | 7629 | }, |
| 7672 | 7630 | else => {}, |
| 7673 | 7631 | } |
| 7674 | 7632 | assert(callee_ty.isPtrAtRuntime(mod)); |
| 7675 | 7633 | return sema.fail(block, call_src, "{s} call of function pointer", .{ |
| 7676 | @as([]const u8, if (is_comptime_call) "comptime" else "inline"), | |
| 7634 | if (is_comptime_call) "comptime" else "inline", | |
| 7677 | 7635 | }); |
| 7678 | 7636 | }, |
| 7679 | 7637 | else => unreachable, |
| 7680 | 7638 | }; |
| 7681 | 7639 | if (func_ty_info.is_var_args) { |
| 7682 | 7640 | return sema.fail(block, call_src, "{s} call of variadic function", .{ |
| 7683 | @as([]const u8, if (is_comptime_call) "comptime" else "inline"), | |
| 7641 | if (is_comptime_call) "comptime" else "inline", | |
| 7684 | 7642 | }); |
| 7685 | 7643 | } |
| 7686 | 7644 | |
| ... | ... | @@ -7712,7 +7670,12 @@ fn analyzeCall( |
| 7712 | 7670 | }; |
| 7713 | 7671 | |
| 7714 | 7672 | const module_fn = mod.funcInfo(module_fn_index); |
| 7715 | const fn_owner_decl = mod.declPtr(module_fn.owner_decl); | |
| 7673 | ||
| 7674 | // This is not a function instance, so the function's `Nav` has a | |
| 7675 | // `Cau` -- we don't need to check `generic_owner`. | |
| 7676 | const fn_nav = ip.getNav(module_fn.owner_nav); | |
| 7677 | const fn_cau_index = fn_nav.analysis_owner.unwrap().?; | |
| 7678 | const fn_cau = ip.getCau(fn_cau_index); | |
| 7716 | 7679 | |
| 7717 | 7680 | // We effectively want a child Sema here, but can't literally do that, because we need AIR |
| 7718 | 7681 | // to be shared. InlineCallSema is a wrapper which handles this for us. While `ics` is in |
| ... | ... | @@ -7720,7 +7683,7 @@ fn analyzeCall( |
| 7720 | 7683 | // whenever performing an operation where the difference matters. |
| 7721 | 7684 | var ics = InlineCallSema.init( |
| 7722 | 7685 | sema, |
| 7723 | fn_owner_decl.getFileScope(mod).zir, | |
| 7686 | mod.cauFileScope(fn_cau_index).zir, | |
| 7724 | 7687 | module_fn_index, |
| 7725 | 7688 | block.error_return_trace_index, |
| 7726 | 7689 | ); |
| ... | ... | @@ -7729,7 +7692,8 @@ fn analyzeCall( |
| 7729 | 7692 | var child_block: Block = .{ |
| 7730 | 7693 | .parent = null, |
| 7731 | 7694 | .sema = sema, |
| 7732 | .namespace = fn_owner_decl.src_namespace, | |
| 7695 | // The function body exists in the same namespace as the corresponding function declaration. | |
| 7696 | .namespace = fn_cau.namespace, | |
| 7733 | 7697 | .instructions = .{}, |
| 7734 | 7698 | .label = null, |
| 7735 | 7699 | .inlining = &inlining, |
| ... | ... | @@ -7740,8 +7704,8 @@ fn analyzeCall( |
| 7740 | 7704 | .runtime_cond = block.runtime_cond, |
| 7741 | 7705 | .runtime_loop = block.runtime_loop, |
| 7742 | 7706 | .runtime_index = block.runtime_index, |
| 7743 | .src_base_inst = fn_owner_decl.zir_decl_index.unwrap().?, | |
| 7744 | .type_name_ctx = fn_owner_decl.name, | |
| 7707 | .src_base_inst = fn_cau.zir_index, | |
| 7708 | .type_name_ctx = fn_nav.fqn, | |
| 7745 | 7709 | }; |
| 7746 | 7710 | |
| 7747 | 7711 | const merges = &child_block.inlining.?.merges; |
| ... | ... | @@ -7759,7 +7723,7 @@ fn analyzeCall( |
| 7759 | 7723 | // comptime memory is mutated. |
| 7760 | 7724 | const memoized_arg_values = try sema.arena.alloc(InternPool.Index, func_ty_info.param_types.len); |
| 7761 | 7725 | |
| 7762 | const owner_info = mod.typeToFunc(fn_owner_decl.typeOf(mod)).?; | |
| 7726 | const owner_info = mod.typeToFunc(Type.fromInterned(module_fn.ty)).?; | |
| 7763 | 7727 | const new_param_types = try sema.arena.alloc(InternPool.Index, owner_info.param_types.len); |
| 7764 | 7728 | var new_fn_info: InternPool.GetFuncTypeKey = .{ |
| 7765 | 7729 | .param_types = new_param_types, |
| ... | ... | @@ -7809,9 +7773,6 @@ fn analyzeCall( |
| 7809 | 7773 | _ = ics.callee(); |
| 7810 | 7774 | |
| 7811 | 7775 | if (!inlining.has_comptime_args) { |
| 7812 | if (module_fn.analysisUnordered(ip).state == .sema_failure) | |
| 7813 | return error.AnalysisFail; | |
| 7814 | ||
| 7815 | 7776 | var block_it = block; |
| 7816 | 7777 | while (block_it.inlining) |parent_inlining| { |
| 7817 | 7778 | if (!parent_inlining.has_comptime_args and parent_inlining.func == module_fn_index) { |
| ... | ... | @@ -7957,8 +7918,11 @@ fn analyzeCall( |
| 7957 | 7918 | |
| 7958 | 7919 | if (call_dbg_node) |some| try sema.zirDbgStmt(block, some); |
| 7959 | 7920 | |
| 7960 | if (sema.owner_func_index != .none and Type.fromInterned(func_ty_info.return_type).isError(mod)) { | |
| 7961 | ip.funcSetCallsOrAwaitsErrorableFn(sema.owner_func_index); | |
| 7921 | switch (sema.owner.unwrap()) { | |
| 7922 | .cau => {}, | |
| 7923 | .func => |owner_func| if (Type.fromInterned(func_ty_info.return_type).isError(mod)) { | |
| 7924 | ip.funcSetCallsOrAwaitsErrorableFn(owner_func); | |
| 7925 | }, | |
| 7962 | 7926 | } |
| 7963 | 7927 | |
| 7964 | 7928 | if (try sema.resolveValue(func)) |func_val| { |
| ... | ... | @@ -7994,7 +7958,7 @@ fn analyzeCall( |
| 7994 | 7958 | switch (mod.intern_pool.indexToKey(func_val.toIntern())) { |
| 7995 | 7959 | .func => break :skip_safety, |
| 7996 | 7960 | .ptr => |ptr| if (ptr.byte_offset == 0) switch (ptr.base_addr) { |
| 7997 | .decl => |decl| if (!mod.declPtr(decl).isExtern(mod)) break :skip_safety, | |
| 7961 | .nav => |nav| if (!ip.getNav(nav).isExtern(ip)) break :skip_safety, | |
| 7998 | 7962 | else => {}, |
| 7999 | 7963 | }, |
| 8000 | 7964 | else => {}, |
| ... | ... | @@ -8018,18 +7982,18 @@ fn analyzeCall( |
| 8018 | 7982 | |
| 8019 | 7983 | fn handleTailCall(sema: *Sema, block: *Block, call_src: LazySrcLoc, func_ty: Type, result: Air.Inst.Ref) !Air.Inst.Ref { |
| 8020 | 7984 | const pt = sema.pt; |
| 8021 | const mod = pt.zcu; | |
| 8022 | const target = mod.getTarget(); | |
| 8023 | const backend = mod.comp.getZigBackend(); | |
| 7985 | const zcu = pt.zcu; | |
| 7986 | const target = zcu.getTarget(); | |
| 7987 | const backend = zcu.comp.getZigBackend(); | |
| 8024 | 7988 | if (!target_util.supportsTailCall(target, backend)) { |
| 8025 | 7989 | return sema.fail(block, call_src, "unable to perform tail call: compiler backend '{s}' does not support tail calls on target architecture '{s}' with the selected CPU feature flags", .{ |
| 8026 | 7990 | @tagName(backend), @tagName(target.cpu.arch), |
| 8027 | 7991 | }); |
| 8028 | 7992 | } |
| 8029 | const func_decl = mod.funcOwnerDeclPtr(sema.owner_func_index); | |
| 8030 | if (!func_ty.eql(func_decl.typeOf(mod), mod)) { | |
| 7993 | const owner_func_ty = Type.fromInterned(zcu.funcInfo(sema.owner.unwrap().func).ty); | |
| 7994 | if (owner_func_ty.toIntern() != func_ty.toIntern()) { | |
| 8031 | 7995 | return sema.fail(block, call_src, "unable to perform tail call: type of function being called '{}' does not match type of calling function '{}'", .{ |
| 8032 | func_ty.fmt(pt), func_decl.typeOf(mod).fmt(pt), | |
| 7996 | func_ty.fmt(pt), owner_func_ty.fmt(pt), | |
| 8033 | 7997 | }); |
| 8034 | 7998 | } |
| 8035 | 7999 | _ = try block.addUnOp(.ret, result); |
| ... | ... | @@ -8191,7 +8155,7 @@ fn instantiateGenericCall( |
| 8191 | 8155 | }); |
| 8192 | 8156 | const generic_owner = switch (zcu.intern_pool.indexToKey(func_val.toIntern())) { |
| 8193 | 8157 | .func => func_val.toIntern(), |
| 8194 | .ptr => |ptr| zcu.declPtr(ptr.base_addr.decl).val.toIntern(), | |
| 8158 | .ptr => |ptr| ip.getNav(ptr.base_addr.nav).status.resolved.val, | |
| 8195 | 8159 | else => unreachable, |
| 8196 | 8160 | }; |
| 8197 | 8161 | const generic_owner_func = zcu.intern_pool.indexToKey(generic_owner).func; |
| ... | ... | @@ -8207,10 +8171,10 @@ fn instantiateGenericCall( |
| 8207 | 8171 | // The actual monomorphization happens via adding `func_instance` to |
| 8208 | 8172 | // `InternPool`. |
| 8209 | 8173 | |
| 8210 | const fn_owner_decl = zcu.declPtr(generic_owner_func.owner_decl); | |
| 8211 | const namespace_index = fn_owner_decl.src_namespace; | |
| 8212 | const namespace = zcu.namespacePtr(namespace_index); | |
| 8213 | const fn_zir = namespace.fileScope(zcu).zir; | |
| 8174 | // Since we are looking at the generic owner here, it has a `Cau`. | |
| 8175 | const fn_nav = ip.getNav(generic_owner_func.owner_nav); | |
| 8176 | const fn_cau = ip.getCau(fn_nav.analysis_owner.unwrap().?); | |
| 8177 | const fn_zir = zcu.namespacePtr(fn_cau.namespace).fileScope(zcu).zir; | |
| 8214 | 8178 | const fn_info = fn_zir.getFnInfo(generic_owner_func.zir_body_inst.resolve(ip)); |
| 8215 | 8179 | |
| 8216 | 8180 | const comptime_args = try sema.arena.alloc(InternPool.Index, args_info.count()); |
| ... | ... | @@ -8232,15 +8196,13 @@ fn instantiateGenericCall( |
| 8232 | 8196 | // We pass the generic callsite's owner decl here because whatever `Decl` |
| 8233 | 8197 | // dependencies are chased at this point should be attached to the |
| 8234 | 8198 | // callsite, not the `Decl` associated with the `func_instance`. |
| 8235 | .owner_decl = sema.owner_decl, | |
| 8236 | .owner_decl_index = sema.owner_decl_index, | |
| 8237 | .func_index = sema.owner_func_index, | |
| 8199 | .owner = sema.owner, | |
| 8200 | .func_index = sema.func_index, | |
| 8238 | 8201 | // This may not be known yet, since the calling convention could be generic, but there |
| 8239 | 8202 | // should be no illegal instructions encountered while creating the function anyway. |
| 8240 | 8203 | .func_is_naked = false, |
| 8241 | 8204 | .fn_ret_ty = Type.void, |
| 8242 | 8205 | .fn_ret_ty_ies = null, |
| 8243 | .owner_func_index = .none, | |
| 8244 | 8206 | .comptime_args = comptime_args, |
| 8245 | 8207 | .generic_owner = generic_owner, |
| 8246 | 8208 | .generic_call_src = call_src, |
| ... | ... | @@ -8253,12 +8215,12 @@ fn instantiateGenericCall( |
| 8253 | 8215 | var child_block: Block = .{ |
| 8254 | 8216 | .parent = null, |
| 8255 | 8217 | .sema = &child_sema, |
| 8256 | .namespace = namespace_index, | |
| 8218 | .namespace = fn_cau.namespace, | |
| 8257 | 8219 | .instructions = .{}, |
| 8258 | 8220 | .inlining = null, |
| 8259 | 8221 | .is_comptime = true, |
| 8260 | .src_base_inst = fn_owner_decl.zir_decl_index.unwrap().?, | |
| 8261 | .type_name_ctx = fn_owner_decl.name, | |
| 8222 | .src_base_inst = fn_cau.zir_index, | |
| 8223 | .type_name_ctx = fn_nav.fqn, | |
| 8262 | 8224 | }; |
| 8263 | 8225 | defer child_block.instructions.deinit(gpa); |
| 8264 | 8226 | |
| ... | ... | @@ -8421,10 +8383,11 @@ fn instantiateGenericCall( |
| 8421 | 8383 | |
| 8422 | 8384 | if (call_dbg_node) |some| try sema.zirDbgStmt(block, some); |
| 8423 | 8385 | |
| 8424 | if (sema.owner_func_index != .none and | |
| 8425 | Type.fromInterned(func_ty_info.return_type).isError(zcu)) | |
| 8426 | { | |
| 8427 | ip.funcSetCallsOrAwaitsErrorableFn(sema.owner_func_index); | |
| 8386 | switch (sema.owner.unwrap()) { | |
| 8387 | .cau => {}, | |
| 8388 | .func => |owner_func| if (Type.fromInterned(func_ty_info.return_type).isError(zcu)) { | |
| 8389 | ip.funcSetCallsOrAwaitsErrorableFn(owner_func); | |
| 8390 | }, | |
| 8428 | 8391 | } |
| 8429 | 8392 | |
| 8430 | 8393 | try sema.addReferenceEntry(call_src, AnalUnit.wrap(.{ .func = callee_index })); |
| ... | ... | @@ -9366,10 +9329,11 @@ fn zirFunc( |
| 9366 | 9329 | inferred_error_set: bool, |
| 9367 | 9330 | ) CompileError!Air.Inst.Ref { |
| 9368 | 9331 | const pt = sema.pt; |
| 9369 | const mod = pt.zcu; | |
| 9332 | const zcu = pt.zcu; | |
| 9333 | const ip = &zcu.intern_pool; | |
| 9370 | 9334 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; |
| 9371 | 9335 | const extra = sema.code.extraData(Zir.Inst.Func, inst_data.payload_index); |
| 9372 | const target = mod.getTarget(); | |
| 9336 | const target = zcu.getTarget(); | |
| 9373 | 9337 | const ret_ty_src = block.src(.{ .node_offset_fn_type_ret_ty = inst_data.src_node }); |
| 9374 | 9338 | |
| 9375 | 9339 | var extra_index = extra.end; |
| ... | ... | @@ -9410,11 +9374,17 @@ fn zirFunc( |
| 9410 | 9374 | // the callconv based on whether it is exported. Otherwise, the callconv defaults |
| 9411 | 9375 | // to `.Unspecified`. |
| 9412 | 9376 | const cc: std.builtin.CallingConvention = if (has_body) cc: { |
| 9413 | const fn_is_exported = if (sema.generic_owner != .none) exported: { | |
| 9414 | const generic_owner_fn = mod.funcInfo(sema.generic_owner); | |
| 9415 | const generic_owner_decl = mod.declPtr(generic_owner_fn.owner_decl); | |
| 9416 | break :exported generic_owner_decl.is_exported; | |
| 9417 | } else sema.owner_decl.is_exported; | |
| 9377 | const func_decl_cau = if (sema.generic_owner != .none) cau: { | |
| 9378 | const generic_owner_fn = zcu.funcInfo(sema.generic_owner); | |
| 9379 | // The generic owner definitely has a `Cau` for the corresponding function declaration. | |
| 9380 | const generic_owner_nav = ip.getNav(generic_owner_fn.owner_nav); | |
| 9381 | break :cau generic_owner_nav.analysis_owner.unwrap().?; | |
| 9382 | } else sema.owner.unwrap().cau; | |
| 9383 | const fn_is_exported = exported: { | |
| 9384 | const decl_inst = ip.getCau(func_decl_cau).zir_index.resolve(ip); | |
| 9385 | const zir_decl = sema.code.getDeclaration(decl_inst)[0]; | |
| 9386 | break :exported zir_decl.flags.is_export; | |
| 9387 | }; | |
| 9418 | 9388 | break :cc if (fn_is_exported) .C else .Unspecified; |
| 9419 | 9389 | } else .Unspecified; |
| 9420 | 9390 | |
| ... | ... | @@ -9613,10 +9583,10 @@ fn funcCommon( |
| 9613 | 9583 | is_noinline: bool, |
| 9614 | 9584 | ) CompileError!Air.Inst.Ref { |
| 9615 | 9585 | const pt = sema.pt; |
| 9616 | const mod = pt.zcu; | |
| 9586 | const zcu = pt.zcu; | |
| 9617 | 9587 | const gpa = sema.gpa; |
| 9618 | const target = mod.getTarget(); | |
| 9619 | const ip = &mod.intern_pool; | |
| 9588 | const target = zcu.getTarget(); | |
| 9589 | const ip = &zcu.intern_pool; | |
| 9620 | 9590 | const ret_ty_src = block.src(.{ .node_offset_fn_type_ret_ty = src_node_offset }); |
| 9621 | 9591 | const cc_src = block.src(.{ .node_offset_fn_type_cc = src_node_offset }); |
| 9622 | 9592 | const func_src = block.nodeOffset(src_node_offset); |
| ... | ... | @@ -9664,8 +9634,8 @@ fn funcCommon( |
| 9664 | 9634 | if (this_generic and !sema.no_partial_func_ty and !target_util.fnCallConvAllowsZigTypes(target, cc_resolved)) { |
| 9665 | 9635 | return sema.fail(block, param_src, "generic parameters not allowed in function with calling convention '{s}'", .{@tagName(cc_resolved)}); |
| 9666 | 9636 | } |
| 9667 | if (!param_ty.isValidParamType(mod)) { | |
| 9668 | const opaque_str = if (param_ty.zigTypeTag(mod) == .Opaque) "opaque " else ""; | |
| 9637 | if (!param_ty.isValidParamType(zcu)) { | |
| 9638 | const opaque_str = if (param_ty.zigTypeTag(zcu) == .Opaque) "opaque " else ""; | |
| 9669 | 9639 | return sema.fail(block, param_src, "parameter of {s}type '{}' not allowed", .{ |
| 9670 | 9640 | opaque_str, param_ty.fmt(pt), |
| 9671 | 9641 | }); |
| ... | ... | @@ -9699,7 +9669,7 @@ fn funcCommon( |
| 9699 | 9669 | return sema.failWithOwnedErrorMsg(block, msg); |
| 9700 | 9670 | } |
| 9701 | 9671 | if (is_source_decl and !this_generic and is_noalias and |
| 9702 | !(param_ty.zigTypeTag(mod) == .Pointer or param_ty.isPtrLikeOptional(mod))) | |
| 9672 | !(param_ty.zigTypeTag(zcu) == .Pointer or param_ty.isPtrLikeOptional(zcu))) | |
| 9703 | 9673 | { |
| 9704 | 9674 | return sema.fail(block, param_src, "non-pointer parameter declared noalias", .{}); |
| 9705 | 9675 | } |
| ... | ... | @@ -9707,7 +9677,7 @@ fn funcCommon( |
| 9707 | 9677 | .Interrupt => if (target.cpu.arch.isX86()) { |
| 9708 | 9678 | const err_code_size = target.ptrBitWidth(); |
| 9709 | 9679 | switch (i) { |
| 9710 | 0 => if (param_ty.zigTypeTag(mod) != .Pointer) return sema.fail(block, param_src, "first parameter of function with 'Interrupt' calling convention must be a pointer type", .{}), | |
| 9680 | 0 => if (param_ty.zigTypeTag(zcu) != .Pointer) return sema.fail(block, param_src, "first parameter of function with 'Interrupt' calling convention must be a pointer type", .{}), | |
| 9711 | 9681 | 1 => if (param_ty.bitSize(pt) != err_code_size) return sema.fail(block, param_src, "second parameter of function with 'Interrupt' calling convention must be a {d}-bit integer", .{err_code_size}), |
| 9712 | 9682 | else => return sema.fail(block, param_src, "'Interrupt' calling convention supports up to 2 parameters, found {d}", .{i + 1}), |
| 9713 | 9683 | } |
| ... | ... | @@ -9769,14 +9739,11 @@ fn funcCommon( |
| 9769 | 9739 | ); |
| 9770 | 9740 | } |
| 9771 | 9741 | |
| 9772 | // extern_func and func_decl functions take ownership of `sema.owner_decl`. | |
| 9773 | sema.owner_decl.@"linksection" = switch (section) { | |
| 9742 | const section_name: InternPool.OptionalNullTerminatedString = switch (section) { | |
| 9774 | 9743 | .generic => .none, |
| 9775 | 9744 | .default => .none, |
| 9776 | .explicit => |section_name| section_name.toOptional(), | |
| 9745 | .explicit => |name| name.toOptional(), | |
| 9777 | 9746 | }; |
| 9778 | sema.owner_decl.alignment = alignment orelse .none; | |
| 9779 | sema.owner_decl.@"addrspace" = address_space orelse .generic; | |
| 9780 | 9747 | |
| 9781 | 9748 | if (inferred_error_set) { |
| 9782 | 9749 | assert(!is_extern); |
| ... | ... | @@ -9784,7 +9751,7 @@ fn funcCommon( |
| 9784 | 9751 | if (!ret_poison) |
| 9785 | 9752 | try sema.validateErrorUnionPayloadType(block, bare_return_type, ret_ty_src); |
| 9786 | 9753 | const func_index = try ip.getFuncDeclIes(gpa, pt.tid, .{ |
| 9787 | .owner_decl = sema.owner_decl_index, | |
| 9754 | .owner_nav = sema.getOwnerCauNav(), | |
| 9788 | 9755 | |
| 9789 | 9756 | .param_types = param_types, |
| 9790 | 9757 | .noalias_bits = noalias_bits, |
| ... | ... | @@ -9804,6 +9771,13 @@ fn funcCommon( |
| 9804 | 9771 | .lbrace_column = @as(u16, @truncate(src_locs.columns)), |
| 9805 | 9772 | .rbrace_column = @as(u16, @truncate(src_locs.columns >> 16)), |
| 9806 | 9773 | }); |
| 9774 | // func_decl functions take ownership of the `Nav` of Sema'a owner `Cau`. | |
| 9775 | ip.resolveNavValue(sema.getOwnerCauNav(), .{ | |
| 9776 | .val = func_index, | |
| 9777 | .alignment = alignment orelse .none, | |
| 9778 | .@"linksection" = section_name, | |
| 9779 | .@"addrspace" = address_space orelse .generic, | |
| 9780 | }); | |
| 9807 | 9781 | return finishFunc( |
| 9808 | 9782 | sema, |
| 9809 | 9783 | block, |
| ... | ... | @@ -9846,11 +9820,20 @@ fn funcCommon( |
| 9846 | 9820 | if (opt_lib_name) |lib_name| try sema.handleExternLibName(block, block.src(.{ |
| 9847 | 9821 | .node_offset_lib_name = src_node_offset, |
| 9848 | 9822 | }), lib_name); |
| 9849 | const func_index = try ip.getExternFunc(gpa, pt.tid, .{ | |
| 9823 | const func_index = try pt.getExtern(.{ | |
| 9824 | .name = sema.getOwnerCauNavName(), | |
| 9850 | 9825 | .ty = func_ty, |
| 9851 | .decl = sema.owner_decl_index, | |
| 9852 | .lib_name = try mod.intern_pool.getOrPutStringOpt(gpa, pt.tid, opt_lib_name, .no_embedded_nulls), | |
| 9826 | .lib_name = try ip.getOrPutStringOpt(gpa, pt.tid, opt_lib_name, .no_embedded_nulls), | |
| 9827 | .is_const = true, | |
| 9828 | .is_threadlocal = false, | |
| 9829 | .is_weak_linkage = false, | |
| 9830 | .alignment = alignment orelse .none, | |
| 9831 | .@"addrspace" = address_space orelse .generic, | |
| 9832 | .zir_index = sema.getOwnerCauDeclInst(), // `declaration` instruction | |
| 9833 | .owner_nav = undefined, // ignored by `getExtern` | |
| 9853 | 9834 | }); |
| 9835 | // Note that unlike function declaration, extern functions don't touch the | |
| 9836 | // Sema's owner Cau's owner Nav. The alignment etc were passed above. | |
| 9854 | 9837 | return finishFunc( |
| 9855 | 9838 | sema, |
| 9856 | 9839 | block, |
| ... | ... | @@ -9872,7 +9855,7 @@ fn funcCommon( |
| 9872 | 9855 | |
| 9873 | 9856 | if (has_body) { |
| 9874 | 9857 | const func_index = try ip.getFuncDecl(gpa, pt.tid, .{ |
| 9875 | .owner_decl = sema.owner_decl_index, | |
| 9858 | .owner_nav = sema.getOwnerCauNav(), | |
| 9876 | 9859 | .ty = func_ty, |
| 9877 | 9860 | .cc = cc, |
| 9878 | 9861 | .is_noinline = is_noinline, |
| ... | ... | @@ -9882,6 +9865,13 @@ fn funcCommon( |
| 9882 | 9865 | .lbrace_column = @as(u16, @truncate(src_locs.columns)), |
| 9883 | 9866 | .rbrace_column = @as(u16, @truncate(src_locs.columns >> 16)), |
| 9884 | 9867 | }); |
| 9868 | // func_decl functions take ownership of the `Nav` of Sema'a owner `Cau`. | |
| 9869 | ip.resolveNavValue(sema.getOwnerCauNav(), .{ | |
| 9870 | .val = func_index, | |
| 9871 | .alignment = alignment orelse .none, | |
| 9872 | .@"linksection" = section_name, | |
| 9873 | .@"addrspace" = address_space orelse .generic, | |
| 9874 | }); | |
| 9885 | 9875 | return finishFunc( |
| 9886 | 9876 | sema, |
| 9887 | 9877 | block, |
| ... | ... | @@ -11179,7 +11169,7 @@ const SwitchProngAnalysis = struct { |
| 11179 | 11169 | return block.addStructFieldVal(spa.operand, field_index, field_ty); |
| 11180 | 11170 | } |
| 11181 | 11171 | } else if (capture_byref) { |
| 11182 | return anonDeclRef(sema, item_val.toIntern()); | |
| 11172 | return sema.uavRef(item_val.toIntern()); | |
| 11183 | 11173 | } else { |
| 11184 | 11174 | return inline_case_capture; |
| 11185 | 11175 | } |
| ... | ... | @@ -13946,10 +13936,9 @@ fn zirHasDecl(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 13946 | 13936 | } }); |
| 13947 | 13937 | } |
| 13948 | 13938 | |
| 13949 | const namespace = container_type.getNamespaceIndex(mod); | |
| 13950 | if (try sema.lookupInNamespace(block, src, namespace, decl_name, true)) |decl_index| { | |
| 13951 | const decl = mod.declPtr(decl_index); | |
| 13952 | if (decl.is_pub or decl.getFileScope(mod) == block.getFileScope(mod)) { | |
| 13939 | const namespace = container_type.getNamespace(mod).unwrap() orelse return .bool_false; | |
| 13940 | if (try sema.lookupInNamespace(block, src, namespace, decl_name, true)) |lookup| { | |
| 13941 | if (lookup.accessible) { | |
| 13953 | 13942 | return .bool_true; |
| 13954 | 13943 | } |
| 13955 | 13944 | } |
| ... | ... | @@ -13981,9 +13970,11 @@ fn zirImport(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. |
| 13981 | 13970 | return sema.fail(block, operand_src, "unable to open '{s}': {s}", .{ operand, @errorName(err) }); |
| 13982 | 13971 | }, |
| 13983 | 13972 | }; |
| 13973 | // TODO: register some kind of dependency on the file. | |
| 13974 | // That way, if this returns `error.AnalysisFail`, we have the dependency banked ready to | |
| 13975 | // trigger re-analysis later. | |
| 13984 | 13976 | try pt.ensureFileAnalyzed(result.file_index); |
| 13985 | const file_root_decl_index = zcu.fileRootDecl(result.file_index).unwrap().?; | |
| 13986 | return sema.analyzeDeclVal(block, operand_src, file_root_decl_index); | |
| 13977 | return Air.internedToRef(zcu.fileRootType(result.file_index)); | |
| 13987 | 13978 | } |
| 13988 | 13979 | |
| 13989 | 13980 | fn zirEmbedFile(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| ... | ... | @@ -16970,7 +16961,7 @@ fn analyzeArithmetic( |
| 16970 | 16961 | if (block.wantSafety() and want_safety and scalar_tag == .Int) { |
| 16971 | 16962 | if (mod.backendSupportsFeature(.safety_checked_instructions)) { |
| 16972 | 16963 | if (air_tag != air_tag_safe) { |
| 16973 | _ = try sema.preparePanicId(block, .integer_overflow); | |
| 16964 | _ = try sema.preparePanicId(block, src, .integer_overflow); | |
| 16974 | 16965 | } |
| 16975 | 16966 | return block.addBinOp(air_tag_safe, casted_lhs, casted_rhs); |
| 16976 | 16967 | } else { |
| ... | ... | @@ -17158,13 +17149,11 @@ fn zirAsm( |
| 17158 | 17149 | if (is_volatile) { |
| 17159 | 17150 | return sema.fail(block, src, "volatile keyword is redundant on module-level assembly", .{}); |
| 17160 | 17151 | } |
| 17161 | try mod.addGlobalAssembly(sema.owner_decl_index, asm_source); | |
| 17152 | try mod.addGlobalAssembly(sema.owner.unwrap().cau, asm_source); | |
| 17162 | 17153 | return .void_value; |
| 17163 | 17154 | } |
| 17164 | 17155 | |
| 17165 | if (block.is_comptime) { | |
| 17166 | try sema.requireRuntimeBlock(block, src, null); | |
| 17167 | } | |
| 17156 | try sema.requireRuntimeBlock(block, src, null); | |
| 17168 | 17157 | |
| 17169 | 17158 | var extra_i = extra.end; |
| 17170 | 17159 | var output_type_bits = extra.data.output_type_bits; |
| ... | ... | @@ -17646,18 +17635,17 @@ fn zirThis( |
| 17646 | 17635 | block: *Block, |
| 17647 | 17636 | extended: Zir.Inst.Extended.InstData, |
| 17648 | 17637 | ) CompileError!Air.Inst.Ref { |
| 17638 | _ = extended; | |
| 17649 | 17639 | const pt = sema.pt; |
| 17650 | const mod = pt.zcu; | |
| 17651 | const this_decl_index = mod.namespacePtr(block.namespace).decl_index; | |
| 17652 | const src = block.nodeOffset(@bitCast(extended.operand)); | |
| 17653 | return sema.analyzeDeclVal(block, src, this_decl_index); | |
| 17640 | const namespace = pt.zcu.namespacePtr(block.namespace); | |
| 17641 | return Air.internedToRef(namespace.owner_type); | |
| 17654 | 17642 | } |
| 17655 | 17643 | |
| 17656 | 17644 | fn zirClosureGet(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref { |
| 17657 | 17645 | const pt = sema.pt; |
| 17658 | 17646 | const mod = pt.zcu; |
| 17659 | 17647 | const ip = &mod.intern_pool; |
| 17660 | const captures = mod.namespacePtr(block.namespace).getType(mod).getCaptures(mod); | |
| 17648 | const captures = Type.fromInterned(mod.namespacePtr(block.namespace).owner_type).getCaptures(mod); | |
| 17661 | 17649 | |
| 17662 | 17650 | const src_node: i32 = @bitCast(extended.operand); |
| 17663 | 17651 | const src = block.nodeOffset(src_node); |
| ... | ... | @@ -17665,8 +17653,8 @@ fn zirClosureGet(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat |
| 17665 | 17653 | const capture_ty = switch (captures.get(ip)[extended.small].unwrap()) { |
| 17666 | 17654 | .@"comptime" => |index| return Air.internedToRef(index), |
| 17667 | 17655 | .runtime => |index| index, |
| 17668 | .decl_val => |decl_index| return sema.analyzeDeclVal(block, src, decl_index), | |
| 17669 | .decl_ref => |decl_index| return sema.analyzeDeclRef(src, decl_index), | |
| 17656 | .nav_val => |nav| return sema.analyzeNavVal(block, src, nav), | |
| 17657 | .nav_ref => |nav| return sema.analyzeNavRef(src, nav), | |
| 17670 | 17658 | }; |
| 17671 | 17659 | |
| 17672 | 17660 | // The comptime case is handled already above. Runtime case below. |
| ... | ... | @@ -17764,20 +17752,19 @@ fn zirBuiltinSrc( |
| 17764 | 17752 | block: *Block, |
| 17765 | 17753 | extended: Zir.Inst.Extended.InstData, |
| 17766 | 17754 | ) CompileError!Air.Inst.Ref { |
| 17767 | _ = block; | |
| 17768 | 17755 | const tracy = trace(@src()); |
| 17769 | 17756 | defer tracy.end(); |
| 17770 | 17757 | |
| 17771 | 17758 | const pt = sema.pt; |
| 17772 | 17759 | const zcu = pt.zcu; |
| 17773 | const extra = sema.code.extraData(Zir.Inst.Src, extended.operand).data; | |
| 17774 | const fn_owner_decl = zcu.funcOwnerDeclPtr(sema.func_index); | |
| 17775 | 17760 | const ip = &zcu.intern_pool; |
| 17761 | const extra = sema.code.extraData(Zir.Inst.Src, extended.operand).data; | |
| 17762 | const fn_name = ip.getNav(zcu.funcInfo(sema.func_index).owner_nav).name; | |
| 17776 | 17763 | const gpa = sema.gpa; |
| 17777 | const file_scope = fn_owner_decl.getFileScope(zcu); | |
| 17764 | const file_scope = block.getFileScope(zcu); | |
| 17778 | 17765 | |
| 17779 | 17766 | const func_name_val = v: { |
| 17780 | const func_name_len = fn_owner_decl.name.length(ip); | |
| 17767 | const func_name_len = fn_name.length(ip); | |
| 17781 | 17768 | const array_ty = try pt.intern(.{ .array_type = .{ |
| 17782 | 17769 | .len = func_name_len, |
| 17783 | 17770 | .sentinel = .zero_u8, |
| ... | ... | @@ -17787,11 +17774,11 @@ fn zirBuiltinSrc( |
| 17787 | 17774 | .ty = .slice_const_u8_sentinel_0_type, |
| 17788 | 17775 | .ptr = try pt.intern(.{ .ptr = .{ |
| 17789 | 17776 | .ty = .manyptr_const_u8_sentinel_0_type, |
| 17790 | .base_addr = .{ .anon_decl = .{ | |
| 17777 | .base_addr = .{ .uav = .{ | |
| 17791 | 17778 | .orig_ty = .slice_const_u8_sentinel_0_type, |
| 17792 | 17779 | .val = try pt.intern(.{ .aggregate = .{ |
| 17793 | 17780 | .ty = array_ty, |
| 17794 | .storage = .{ .bytes = fn_owner_decl.name.toString() }, | |
| 17781 | .storage = .{ .bytes = fn_name.toString() }, | |
| 17795 | 17782 | } }), |
| 17796 | 17783 | } }, |
| 17797 | 17784 | .byte_offset = 0, |
| ... | ... | @@ -17811,7 +17798,7 @@ fn zirBuiltinSrc( |
| 17811 | 17798 | .ty = .slice_const_u8_sentinel_0_type, |
| 17812 | 17799 | .ptr = try pt.intern(.{ .ptr = .{ |
| 17813 | 17800 | .ty = .manyptr_const_u8_sentinel_0_type, |
| 17814 | .base_addr = .{ .anon_decl = .{ | |
| 17801 | .base_addr = .{ .uav = .{ | |
| 17815 | 17802 | .orig_ty = .slice_const_u8_sentinel_0_type, |
| 17816 | 17803 | .val = try pt.intern(.{ .aggregate = .{ |
| 17817 | 17804 | .ty = array_ty, |
| ... | ... | @@ -17837,7 +17824,7 @@ fn zirBuiltinSrc( |
| 17837 | 17824 | .ty = .slice_const_u8_sentinel_0_type, |
| 17838 | 17825 | .ptr = try pt.intern(.{ .ptr = .{ |
| 17839 | 17826 | .ty = .manyptr_const_u8_sentinel_0_type, |
| 17840 | .base_addr = .{ .anon_decl = .{ | |
| 17827 | .base_addr = .{ .uav = .{ | |
| 17841 | 17828 | .orig_ty = .slice_const_u8_sentinel_0_type, |
| 17842 | 17829 | .val = try pt.intern(.{ .aggregate = .{ |
| 17843 | 17830 | .ty = array_ty, |
| ... | ... | @@ -17902,25 +17889,23 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 17902 | 17889 | .val = .void_value, |
| 17903 | 17890 | } }))), |
| 17904 | 17891 | .Fn => { |
| 17905 | const fn_info_decl_index = (try sema.namespaceLookup( | |
| 17892 | const fn_info_nav = try sema.namespaceLookup( | |
| 17906 | 17893 | block, |
| 17907 | 17894 | src, |
| 17908 | 17895 | type_info_ty.getNamespaceIndex(mod), |
| 17909 | 17896 | try ip.getOrPutString(gpa, pt.tid, "Fn", .no_embedded_nulls), |
| 17910 | )).?; | |
| 17911 | try sema.ensureDeclAnalyzed(fn_info_decl_index); | |
| 17912 | const fn_info_decl = mod.declPtr(fn_info_decl_index); | |
| 17913 | const fn_info_ty = fn_info_decl.val.toType(); | |
| 17897 | ) orelse @panic("std.builtin.Type is corrupt"); | |
| 17898 | try sema.ensureNavResolved(src, fn_info_nav); | |
| 17899 | const fn_info_ty = Type.fromInterned(ip.getNav(fn_info_nav).status.resolved.val); | |
| 17914 | 17900 | |
| 17915 | const param_info_decl_index = (try sema.namespaceLookup( | |
| 17901 | const param_info_nav = try sema.namespaceLookup( | |
| 17916 | 17902 | block, |
| 17917 | 17903 | src, |
| 17918 | 17904 | fn_info_ty.getNamespaceIndex(mod), |
| 17919 | 17905 | try ip.getOrPutString(gpa, pt.tid, "Param", .no_embedded_nulls), |
| 17920 | )).?; | |
| 17921 | try sema.ensureDeclAnalyzed(param_info_decl_index); | |
| 17922 | const param_info_decl = mod.declPtr(param_info_decl_index); | |
| 17923 | const param_info_ty = param_info_decl.val.toType(); | |
| 17906 | ) orelse @panic("std.builtin.Type is corrupt"); | |
| 17907 | try sema.ensureNavResolved(src, param_info_nav); | |
| 17908 | const param_info_ty = Type.fromInterned(ip.getNav(param_info_nav).status.resolved.val); | |
| 17924 | 17909 | |
| 17925 | 17910 | const func_ty_info = mod.typeToFunc(ty).?; |
| 17926 | 17911 | const param_vals = try sema.arena.alloc(InternPool.Index, func_ty_info.param_types.len); |
| ... | ... | @@ -17972,7 +17957,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 17972 | 17957 | .ty = slice_ty, |
| 17973 | 17958 | .ptr = try pt.intern(.{ .ptr = .{ |
| 17974 | 17959 | .ty = manyptr_ty, |
| 17975 | .base_addr = .{ .anon_decl = .{ | |
| 17960 | .base_addr = .{ .uav = .{ | |
| 17976 | 17961 | .orig_ty = manyptr_ty, |
| 17977 | 17962 | .val = new_decl_val, |
| 17978 | 17963 | } }, |
| ... | ... | @@ -18014,15 +17999,14 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 18014 | 17999 | } }))); |
| 18015 | 18000 | }, |
| 18016 | 18001 | .Int => { |
| 18017 | const int_info_decl_index = (try sema.namespaceLookup( | |
| 18002 | const int_info_nav = try sema.namespaceLookup( | |
| 18018 | 18003 | block, |
| 18019 | 18004 | src, |
| 18020 | 18005 | type_info_ty.getNamespaceIndex(mod), |
| 18021 | 18006 | try ip.getOrPutString(gpa, pt.tid, "Int", .no_embedded_nulls), |
| 18022 | )).?; | |
| 18023 | try sema.ensureDeclAnalyzed(int_info_decl_index); | |
| 18024 | const int_info_decl = mod.declPtr(int_info_decl_index); | |
| 18025 | const int_info_ty = int_info_decl.val.toType(); | |
| 18007 | ) orelse @panic("std.builtin.Type is corrupt"); | |
| 18008 | try sema.ensureNavResolved(src, int_info_nav); | |
| 18009 | const int_info_ty = Type.fromInterned(ip.getNav(int_info_nav).status.resolved.val); | |
| 18026 | 18010 | |
| 18027 | 18011 | const signedness_ty = try pt.getBuiltinType("Signedness"); |
| 18028 | 18012 | const info = ty.intInfo(mod); |
| ... | ... | @@ -18042,15 +18026,14 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 18042 | 18026 | } }))); |
| 18043 | 18027 | }, |
| 18044 | 18028 | .Float => { |
| 18045 | const float_info_decl_index = (try sema.namespaceLookup( | |
| 18029 | const float_info_nav = try sema.namespaceLookup( | |
| 18046 | 18030 | block, |
| 18047 | 18031 | src, |
| 18048 | 18032 | type_info_ty.getNamespaceIndex(mod), |
| 18049 | 18033 | try ip.getOrPutString(gpa, pt.tid, "Float", .no_embedded_nulls), |
| 18050 | )).?; | |
| 18051 | try sema.ensureDeclAnalyzed(float_info_decl_index); | |
| 18052 | const float_info_decl = mod.declPtr(float_info_decl_index); | |
| 18053 | const float_info_ty = float_info_decl.val.toType(); | |
| 18034 | ) orelse @panic("std.builtin.Type is corrupt"); | |
| 18035 | try sema.ensureNavResolved(src, float_info_nav); | |
| 18036 | const float_info_ty = Type.fromInterned(ip.getNav(float_info_nav).status.resolved.val); | |
| 18054 | 18037 | |
| 18055 | 18038 | const field_vals = .{ |
| 18056 | 18039 | // bits: u16, |
| ... | ... | @@ -18074,26 +18057,24 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 18074 | 18057 | |
| 18075 | 18058 | const addrspace_ty = try pt.getBuiltinType("AddressSpace"); |
| 18076 | 18059 | const pointer_ty = t: { |
| 18077 | const decl_index = (try sema.namespaceLookup( | |
| 18060 | const nav = try sema.namespaceLookup( | |
| 18078 | 18061 | block, |
| 18079 | 18062 | src, |
| 18080 | 18063 | (try pt.getBuiltinType("Type")).getNamespaceIndex(mod), |
| 18081 | 18064 | try ip.getOrPutString(gpa, pt.tid, "Pointer", .no_embedded_nulls), |
| 18082 | )).?; | |
| 18083 | try sema.ensureDeclAnalyzed(decl_index); | |
| 18084 | const decl = mod.declPtr(decl_index); | |
| 18085 | break :t decl.val.toType(); | |
| 18065 | ) orelse @panic("std.builtin.Type is corrupt"); | |
| 18066 | try sema.ensureNavResolved(src, nav); | |
| 18067 | break :t Type.fromInterned(ip.getNav(nav).status.resolved.val); | |
| 18086 | 18068 | }; |
| 18087 | 18069 | const ptr_size_ty = t: { |
| 18088 | const decl_index = (try sema.namespaceLookup( | |
| 18070 | const nav = try sema.namespaceLookup( | |
| 18089 | 18071 | block, |
| 18090 | 18072 | src, |
| 18091 | 18073 | pointer_ty.getNamespaceIndex(mod), |
| 18092 | 18074 | try ip.getOrPutString(gpa, pt.tid, "Size", .no_embedded_nulls), |
| 18093 | )).?; | |
| 18094 | try sema.ensureDeclAnalyzed(decl_index); | |
| 18095 | const decl = mod.declPtr(decl_index); | |
| 18096 | break :t decl.val.toType(); | |
| 18075 | ) orelse @panic("std.builtin.Type is corrupt"); | |
| 18076 | try sema.ensureNavResolved(src, nav); | |
| 18077 | break :t Type.fromInterned(ip.getNav(nav).status.resolved.val); | |
| 18097 | 18078 | }; |
| 18098 | 18079 | |
| 18099 | 18080 | const field_values = .{ |
| ... | ... | @@ -18128,15 +18109,14 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 18128 | 18109 | }, |
| 18129 | 18110 | .Array => { |
| 18130 | 18111 | const array_field_ty = t: { |
| 18131 | const array_field_ty_decl_index = (try sema.namespaceLookup( | |
| 18112 | const nav = try sema.namespaceLookup( | |
| 18132 | 18113 | block, |
| 18133 | 18114 | src, |
| 18134 | 18115 | type_info_ty.getNamespaceIndex(mod), |
| 18135 | 18116 | try ip.getOrPutString(gpa, pt.tid, "Array", .no_embedded_nulls), |
| 18136 | )).?; | |
| 18137 | try sema.ensureDeclAnalyzed(array_field_ty_decl_index); | |
| 18138 | const array_field_ty_decl = mod.declPtr(array_field_ty_decl_index); | |
| 18139 | break :t array_field_ty_decl.val.toType(); | |
| 18117 | ) orelse @panic("std.builtin.Type is corrupt"); | |
| 18118 | try sema.ensureNavResolved(src, nav); | |
| 18119 | break :t Type.fromInterned(ip.getNav(nav).status.resolved.val); | |
| 18140 | 18120 | }; |
| 18141 | 18121 | |
| 18142 | 18122 | const info = ty.arrayInfo(mod); |
| ... | ... | @@ -18159,15 +18139,14 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 18159 | 18139 | }, |
| 18160 | 18140 | .Vector => { |
| 18161 | 18141 | const vector_field_ty = t: { |
| 18162 | const vector_field_ty_decl_index = (try sema.namespaceLookup( | |
| 18142 | const nav = try sema.namespaceLookup( | |
| 18163 | 18143 | block, |
| 18164 | 18144 | src, |
| 18165 | 18145 | type_info_ty.getNamespaceIndex(mod), |
| 18166 | 18146 | try ip.getOrPutString(gpa, pt.tid, "Vector", .no_embedded_nulls), |
| 18167 | )).?; | |
| 18168 | try sema.ensureDeclAnalyzed(vector_field_ty_decl_index); | |
| 18169 | const vector_field_ty_decl = mod.declPtr(vector_field_ty_decl_index); | |
| 18170 | break :t vector_field_ty_decl.val.toType(); | |
| 18147 | ) orelse @panic("std.builtin.Type is corrupt"); | |
| 18148 | try sema.ensureNavResolved(src, nav); | |
| 18149 | break :t Type.fromInterned(ip.getNav(nav).status.resolved.val); | |
| 18171 | 18150 | }; |
| 18172 | 18151 | |
| 18173 | 18152 | const info = ty.arrayInfo(mod); |
| ... | ... | @@ -18188,15 +18167,14 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 18188 | 18167 | }, |
| 18189 | 18168 | .Optional => { |
| 18190 | 18169 | const optional_field_ty = t: { |
| 18191 | const optional_field_ty_decl_index = (try sema.namespaceLookup( | |
| 18170 | const nav = try sema.namespaceLookup( | |
| 18192 | 18171 | block, |
| 18193 | 18172 | src, |
| 18194 | 18173 | type_info_ty.getNamespaceIndex(mod), |
| 18195 | 18174 | try ip.getOrPutString(gpa, pt.tid, "Optional", .no_embedded_nulls), |
| 18196 | )).?; | |
| 18197 | try sema.ensureDeclAnalyzed(optional_field_ty_decl_index); | |
| 18198 | const optional_field_ty_decl = mod.declPtr(optional_field_ty_decl_index); | |
| 18199 | break :t optional_field_ty_decl.val.toType(); | |
| 18175 | ) orelse @panic("std.builtin.Type is corrupt"); | |
| 18176 | try sema.ensureNavResolved(src, nav); | |
| 18177 | break :t Type.fromInterned(ip.getNav(nav).status.resolved.val); | |
| 18200 | 18178 | }; |
| 18201 | 18179 | |
| 18202 | 18180 | const field_values = .{ |
| ... | ... | @@ -18215,15 +18193,14 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 18215 | 18193 | .ErrorSet => { |
| 18216 | 18194 | // Get the Error type |
| 18217 | 18195 | const error_field_ty = t: { |
| 18218 | const set_field_ty_decl_index = (try sema.namespaceLookup( | |
| 18196 | const nav = try sema.namespaceLookup( | |
| 18219 | 18197 | block, |
| 18220 | 18198 | src, |
| 18221 | 18199 | type_info_ty.getNamespaceIndex(mod), |
| 18222 | 18200 | try ip.getOrPutString(gpa, pt.tid, "Error", .no_embedded_nulls), |
| 18223 | )).?; | |
| 18224 | try sema.ensureDeclAnalyzed(set_field_ty_decl_index); | |
| 18225 | const set_field_ty_decl = mod.declPtr(set_field_ty_decl_index); | |
| 18226 | break :t set_field_ty_decl.val.toType(); | |
| 18201 | ) orelse @panic("std.builtin.Type is corrupt"); | |
| 18202 | try sema.ensureNavResolved(src, nav); | |
| 18203 | break :t Type.fromInterned(ip.getNav(nav).status.resolved.val); | |
| 18227 | 18204 | }; |
| 18228 | 18205 | |
| 18229 | 18206 | // Build our list of Error values |
| ... | ... | @@ -18251,7 +18228,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 18251 | 18228 | .ty = .slice_const_u8_sentinel_0_type, |
| 18252 | 18229 | .ptr = try pt.intern(.{ .ptr = .{ |
| 18253 | 18230 | .ty = .manyptr_const_u8_sentinel_0_type, |
| 18254 | .base_addr = .{ .anon_decl = .{ | |
| 18231 | .base_addr = .{ .uav = .{ | |
| 18255 | 18232 | .val = new_decl_val, |
| 18256 | 18233 | .orig_ty = .slice_const_u8_sentinel_0_type, |
| 18257 | 18234 | } }, |
| ... | ... | @@ -18298,7 +18275,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 18298 | 18275 | .ty = slice_errors_ty.toIntern(), |
| 18299 | 18276 | .ptr = try pt.intern(.{ .ptr = .{ |
| 18300 | 18277 | .ty = manyptr_errors_ty, |
| 18301 | .base_addr = .{ .anon_decl = .{ | |
| 18278 | .base_addr = .{ .uav = .{ | |
| 18302 | 18279 | .orig_ty = manyptr_errors_ty, |
| 18303 | 18280 | .val = new_decl_val, |
| 18304 | 18281 | } }, |
| ... | ... | @@ -18321,15 +18298,14 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 18321 | 18298 | }, |
| 18322 | 18299 | .ErrorUnion => { |
| 18323 | 18300 | const error_union_field_ty = t: { |
| 18324 | const error_union_field_ty_decl_index = (try sema.namespaceLookup( | |
| 18301 | const nav = try sema.namespaceLookup( | |
| 18325 | 18302 | block, |
| 18326 | 18303 | src, |
| 18327 | 18304 | type_info_ty.getNamespaceIndex(mod), |
| 18328 | 18305 | try ip.getOrPutString(gpa, pt.tid, "ErrorUnion", .no_embedded_nulls), |
| 18329 | )).?; | |
| 18330 | try sema.ensureDeclAnalyzed(error_union_field_ty_decl_index); | |
| 18331 | const error_union_field_ty_decl = mod.declPtr(error_union_field_ty_decl_index); | |
| 18332 | break :t error_union_field_ty_decl.val.toType(); | |
| 18306 | ) orelse @panic("std.builtin.Type is corrupt"); | |
| 18307 | try sema.ensureNavResolved(src, nav); | |
| 18308 | break :t Type.fromInterned(ip.getNav(nav).status.resolved.val); | |
| 18333 | 18309 | }; |
| 18334 | 18310 | |
| 18335 | 18311 | const field_values = .{ |
| ... | ... | @@ -18351,15 +18327,14 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 18351 | 18327 | const is_exhaustive = Value.makeBool(ip.loadEnumType(ty.toIntern()).tag_mode != .nonexhaustive); |
| 18352 | 18328 | |
| 18353 | 18329 | const enum_field_ty = t: { |
| 18354 | const enum_field_ty_decl_index = (try sema.namespaceLookup( | |
| 18330 | const nav = try sema.namespaceLookup( | |
| 18355 | 18331 | block, |
| 18356 | 18332 | src, |
| 18357 | 18333 | type_info_ty.getNamespaceIndex(mod), |
| 18358 | 18334 | try ip.getOrPutString(gpa, pt.tid, "EnumField", .no_embedded_nulls), |
| 18359 | )).?; | |
| 18360 | try sema.ensureDeclAnalyzed(enum_field_ty_decl_index); | |
| 18361 | const enum_field_ty_decl = mod.declPtr(enum_field_ty_decl_index); | |
| 18362 | break :t enum_field_ty_decl.val.toType(); | |
| 18335 | ) orelse @panic("std.builtin.Type is corrupt"); | |
| 18336 | try sema.ensureNavResolved(src, nav); | |
| 18337 | break :t Type.fromInterned(ip.getNav(nav).status.resolved.val); | |
| 18363 | 18338 | }; |
| 18364 | 18339 | |
| 18365 | 18340 | const enum_field_vals = try sema.arena.alloc(InternPool.Index, ip.loadEnumType(ty.toIntern()).names.len); |
| ... | ... | @@ -18392,7 +18367,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 18392 | 18367 | .ty = .slice_const_u8_sentinel_0_type, |
| 18393 | 18368 | .ptr = try pt.intern(.{ .ptr = .{ |
| 18394 | 18369 | .ty = .manyptr_const_u8_sentinel_0_type, |
| 18395 | .base_addr = .{ .anon_decl = .{ | |
| 18370 | .base_addr = .{ .uav = .{ | |
| 18396 | 18371 | .val = new_decl_val, |
| 18397 | 18372 | .orig_ty = .slice_const_u8_sentinel_0_type, |
| 18398 | 18373 | } }, |
| ... | ... | @@ -18435,7 +18410,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 18435 | 18410 | .ty = slice_ty, |
| 18436 | 18411 | .ptr = try pt.intern(.{ .ptr = .{ |
| 18437 | 18412 | .ty = manyptr_ty, |
| 18438 | .base_addr = .{ .anon_decl = .{ | |
| 18413 | .base_addr = .{ .uav = .{ | |
| 18439 | 18414 | .val = new_decl_val, |
| 18440 | 18415 | .orig_ty = manyptr_ty, |
| 18441 | 18416 | } }, |
| ... | ... | @@ -18445,18 +18420,17 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 18445 | 18420 | } }); |
| 18446 | 18421 | }; |
| 18447 | 18422 | |
| 18448 | const decls_val = try sema.typeInfoDecls(block, src, type_info_ty, ip.loadEnumType(ty.toIntern()).namespace); | |
| 18423 | const decls_val = try sema.typeInfoDecls(block, src, type_info_ty, ip.loadEnumType(ty.toIntern()).namespace.toOptional()); | |
| 18449 | 18424 | |
| 18450 | 18425 | const type_enum_ty = t: { |
| 18451 | const type_enum_ty_decl_index = (try sema.namespaceLookup( | |
| 18426 | const nav = try sema.namespaceLookup( | |
| 18452 | 18427 | block, |
| 18453 | 18428 | src, |
| 18454 | 18429 | type_info_ty.getNamespaceIndex(mod), |
| 18455 | 18430 | try ip.getOrPutString(gpa, pt.tid, "Enum", .no_embedded_nulls), |
| 18456 | )).?; | |
| 18457 | try sema.ensureDeclAnalyzed(type_enum_ty_decl_index); | |
| 18458 | const type_enum_ty_decl = mod.declPtr(type_enum_ty_decl_index); | |
| 18459 | break :t type_enum_ty_decl.val.toType(); | |
| 18431 | ) orelse @panic("std.builtin.Type is corrupt"); | |
| 18432 | try sema.ensureNavResolved(src, nav); | |
| 18433 | break :t Type.fromInterned(ip.getNav(nav).status.resolved.val); | |
| 18460 | 18434 | }; |
| 18461 | 18435 | |
| 18462 | 18436 | const field_values = .{ |
| ... | ... | @@ -18480,27 +18454,25 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 18480 | 18454 | }, |
| 18481 | 18455 | .Union => { |
| 18482 | 18456 | const type_union_ty = t: { |
| 18483 | const type_union_ty_decl_index = (try sema.namespaceLookup( | |
| 18457 | const nav = try sema.namespaceLookup( | |
| 18484 | 18458 | block, |
| 18485 | 18459 | src, |
| 18486 | 18460 | type_info_ty.getNamespaceIndex(mod), |
| 18487 | 18461 | try ip.getOrPutString(gpa, pt.tid, "Union", .no_embedded_nulls), |
| 18488 | )).?; | |
| 18489 | try sema.ensureDeclAnalyzed(type_union_ty_decl_index); | |
| 18490 | const type_union_ty_decl = mod.declPtr(type_union_ty_decl_index); | |
| 18491 | break :t type_union_ty_decl.val.toType(); | |
| 18462 | ) orelse @panic("std.builtin.Type is corrupt"); | |
| 18463 | try sema.ensureNavResolved(src, nav); | |
| 18464 | break :t Type.fromInterned(ip.getNav(nav).status.resolved.val); | |
| 18492 | 18465 | }; |
| 18493 | 18466 | |
| 18494 | 18467 | const union_field_ty = t: { |
| 18495 | const union_field_ty_decl_index = (try sema.namespaceLookup( | |
| 18468 | const nav = try sema.namespaceLookup( | |
| 18496 | 18469 | block, |
| 18497 | 18470 | src, |
| 18498 | 18471 | type_info_ty.getNamespaceIndex(mod), |
| 18499 | 18472 | try ip.getOrPutString(gpa, pt.tid, "UnionField", .no_embedded_nulls), |
| 18500 | )).?; | |
| 18501 | try sema.ensureDeclAnalyzed(union_field_ty_decl_index); | |
| 18502 | const union_field_ty_decl = mod.declPtr(union_field_ty_decl_index); | |
| 18503 | break :t union_field_ty_decl.val.toType(); | |
| 18473 | ) orelse @panic("std.builtin.Type is corrupt"); | |
| 18474 | try sema.ensureNavResolved(src, nav); | |
| 18475 | break :t Type.fromInterned(ip.getNav(nav).status.resolved.val); | |
| 18504 | 18476 | }; |
| 18505 | 18477 | |
| 18506 | 18478 | try ty.resolveLayout(pt); // Getting alignment requires type layout |
| ... | ... | @@ -18528,7 +18500,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 18528 | 18500 | .ty = .slice_const_u8_sentinel_0_type, |
| 18529 | 18501 | .ptr = try pt.intern(.{ .ptr = .{ |
| 18530 | 18502 | .ty = .manyptr_const_u8_sentinel_0_type, |
| 18531 | .base_addr = .{ .anon_decl = .{ | |
| 18503 | .base_addr = .{ .uav = .{ | |
| 18532 | 18504 | .val = new_decl_val, |
| 18533 | 18505 | .orig_ty = .slice_const_u8_sentinel_0_type, |
| 18534 | 18506 | } }, |
| ... | ... | @@ -18579,7 +18551,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 18579 | 18551 | .ty = slice_ty, |
| 18580 | 18552 | .ptr = try pt.intern(.{ .ptr = .{ |
| 18581 | 18553 | .ty = manyptr_ty, |
| 18582 | .base_addr = .{ .anon_decl = .{ | |
| 18554 | .base_addr = .{ .uav = .{ | |
| 18583 | 18555 | .orig_ty = manyptr_ty, |
| 18584 | 18556 | .val = new_decl_val, |
| 18585 | 18557 | } }, |
| ... | ... | @@ -18589,7 +18561,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 18589 | 18561 | } }); |
| 18590 | 18562 | }; |
| 18591 | 18563 | |
| 18592 | const decls_val = try sema.typeInfoDecls(block, src, type_info_ty, ty.getNamespaceIndex(mod)); | |
| 18564 | const decls_val = try sema.typeInfoDecls(block, src, type_info_ty, ty.getNamespaceIndex(mod).toOptional()); | |
| 18593 | 18565 | |
| 18594 | 18566 | const enum_tag_ty_val = try pt.intern(.{ .opt = .{ |
| 18595 | 18567 | .ty = (try pt.optionalType(.type_type)).toIntern(), |
| ... | ... | @@ -18597,15 +18569,14 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 18597 | 18569 | } }); |
| 18598 | 18570 | |
| 18599 | 18571 | const container_layout_ty = t: { |
| 18600 | const decl_index = (try sema.namespaceLookup( | |
| 18572 | const nav = try sema.namespaceLookup( | |
| 18601 | 18573 | block, |
| 18602 | 18574 | src, |
| 18603 | 18575 | (try pt.getBuiltinType("Type")).getNamespaceIndex(mod), |
| 18604 | 18576 | try ip.getOrPutString(gpa, pt.tid, "ContainerLayout", .no_embedded_nulls), |
| 18605 | )).?; | |
| 18606 | try sema.ensureDeclAnalyzed(decl_index); | |
| 18607 | const decl = mod.declPtr(decl_index); | |
| 18608 | break :t decl.val.toType(); | |
| 18577 | ) orelse @panic("std.builtin.Type is corrupt"); | |
| 18578 | try sema.ensureNavResolved(src, nav); | |
| 18579 | break :t Type.fromInterned(ip.getNav(nav).status.resolved.val); | |
| 18609 | 18580 | }; |
| 18610 | 18581 | |
| 18611 | 18582 | const field_values = .{ |
| ... | ... | @@ -18630,27 +18601,25 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 18630 | 18601 | }, |
| 18631 | 18602 | .Struct => { |
| 18632 | 18603 | const type_struct_ty = t: { |
| 18633 | const type_struct_ty_decl_index = (try sema.namespaceLookup( | |
| 18604 | const nav = try sema.namespaceLookup( | |
| 18634 | 18605 | block, |
| 18635 | 18606 | src, |
| 18636 | 18607 | type_info_ty.getNamespaceIndex(mod), |
| 18637 | 18608 | try ip.getOrPutString(gpa, pt.tid, "Struct", .no_embedded_nulls), |
| 18638 | )).?; | |
| 18639 | try sema.ensureDeclAnalyzed(type_struct_ty_decl_index); | |
| 18640 | const type_struct_ty_decl = mod.declPtr(type_struct_ty_decl_index); | |
| 18641 | break :t type_struct_ty_decl.val.toType(); | |
| 18609 | ) orelse @panic("std.builtin.Type is corrupt"); | |
| 18610 | try sema.ensureNavResolved(src, nav); | |
| 18611 | break :t Type.fromInterned(ip.getNav(nav).status.resolved.val); | |
| 18642 | 18612 | }; |
| 18643 | 18613 | |
| 18644 | 18614 | const struct_field_ty = t: { |
| 18645 | const struct_field_ty_decl_index = (try sema.namespaceLookup( | |
| 18615 | const nav = try sema.namespaceLookup( | |
| 18646 | 18616 | block, |
| 18647 | 18617 | src, |
| 18648 | 18618 | type_info_ty.getNamespaceIndex(mod), |
| 18649 | 18619 | try ip.getOrPutString(gpa, pt.tid, "StructField", .no_embedded_nulls), |
| 18650 | )).?; | |
| 18651 | try sema.ensureDeclAnalyzed(struct_field_ty_decl_index); | |
| 18652 | const struct_field_ty_decl = mod.declPtr(struct_field_ty_decl_index); | |
| 18653 | break :t struct_field_ty_decl.val.toType(); | |
| 18620 | ) orelse @panic("std.builtin.Type is corrupt"); | |
| 18621 | try sema.ensureNavResolved(src, nav); | |
| 18622 | break :t Type.fromInterned(ip.getNav(nav).status.resolved.val); | |
| 18654 | 18623 | }; |
| 18655 | 18624 | |
| 18656 | 18625 | try ty.resolveLayout(pt); // Getting alignment requires type layout |
| ... | ... | @@ -18683,7 +18652,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 18683 | 18652 | .ty = .slice_const_u8_sentinel_0_type, |
| 18684 | 18653 | .ptr = try pt.intern(.{ .ptr = .{ |
| 18685 | 18654 | .ty = .manyptr_const_u8_sentinel_0_type, |
| 18686 | .base_addr = .{ .anon_decl = .{ | |
| 18655 | .base_addr = .{ .uav = .{ | |
| 18687 | 18656 | .val = new_decl_val, |
| 18688 | 18657 | .orig_ty = .slice_const_u8_sentinel_0_type, |
| 18689 | 18658 | } }, |
| ... | ... | @@ -18747,7 +18716,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 18747 | 18716 | .ty = .slice_const_u8_sentinel_0_type, |
| 18748 | 18717 | .ptr = try pt.intern(.{ .ptr = .{ |
| 18749 | 18718 | .ty = .manyptr_const_u8_sentinel_0_type, |
| 18750 | .base_addr = .{ .anon_decl = .{ | |
| 18719 | .base_addr = .{ .uav = .{ | |
| 18751 | 18720 | .val = new_decl_val, |
| 18752 | 18721 | .orig_ty = .slice_const_u8_sentinel_0_type, |
| 18753 | 18722 | } }, |
| ... | ... | @@ -18809,7 +18778,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 18809 | 18778 | .ty = slice_ty, |
| 18810 | 18779 | .ptr = try pt.intern(.{ .ptr = .{ |
| 18811 | 18780 | .ty = manyptr_ty, |
| 18812 | .base_addr = .{ .anon_decl = .{ | |
| 18781 | .base_addr = .{ .uav = .{ | |
| 18813 | 18782 | .orig_ty = manyptr_ty, |
| 18814 | 18783 | .val = new_decl_val, |
| 18815 | 18784 | } }, |
| ... | ... | @@ -18819,7 +18788,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 18819 | 18788 | } }); |
| 18820 | 18789 | }; |
| 18821 | 18790 | |
| 18822 | const decls_val = try sema.typeInfoDecls(block, src, type_info_ty, ty.getNamespaceIndex(mod)); | |
| 18791 | const decls_val = try sema.typeInfoDecls(block, src, type_info_ty, ty.getNamespace(mod)); | |
| 18823 | 18792 | |
| 18824 | 18793 | const backing_integer_val = try pt.intern(.{ .opt = .{ |
| 18825 | 18794 | .ty = (try pt.optionalType(.type_type)).toIntern(), |
| ... | ... | @@ -18830,15 +18799,14 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 18830 | 18799 | } }); |
| 18831 | 18800 | |
| 18832 | 18801 | const container_layout_ty = t: { |
| 18833 | const decl_index = (try sema.namespaceLookup( | |
| 18802 | const nav = try sema.namespaceLookup( | |
| 18834 | 18803 | block, |
| 18835 | 18804 | src, |
| 18836 | 18805 | (try pt.getBuiltinType("Type")).getNamespaceIndex(mod), |
| 18837 | 18806 | try ip.getOrPutString(gpa, pt.tid, "ContainerLayout", .no_embedded_nulls), |
| 18838 | )).?; | |
| 18839 | try sema.ensureDeclAnalyzed(decl_index); | |
| 18840 | const decl = mod.declPtr(decl_index); | |
| 18841 | break :t decl.val.toType(); | |
| 18807 | ) orelse @panic("std.builtin.Type is corrupt"); | |
| 18808 | try sema.ensureNavResolved(src, nav); | |
| 18809 | break :t Type.fromInterned(ip.getNav(nav).status.resolved.val); | |
| 18842 | 18810 | }; |
| 18843 | 18811 | |
| 18844 | 18812 | const layout = ty.containerLayout(mod); |
| ... | ... | @@ -18866,19 +18834,18 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 18866 | 18834 | }, |
| 18867 | 18835 | .Opaque => { |
| 18868 | 18836 | const type_opaque_ty = t: { |
| 18869 | const type_opaque_ty_decl_index = (try sema.namespaceLookup( | |
| 18837 | const nav = try sema.namespaceLookup( | |
| 18870 | 18838 | block, |
| 18871 | 18839 | src, |
| 18872 | 18840 | type_info_ty.getNamespaceIndex(mod), |
| 18873 | 18841 | try ip.getOrPutString(gpa, pt.tid, "Opaque", .no_embedded_nulls), |
| 18874 | )).?; | |
| 18875 | try sema.ensureDeclAnalyzed(type_opaque_ty_decl_index); | |
| 18876 | const type_opaque_ty_decl = mod.declPtr(type_opaque_ty_decl_index); | |
| 18877 | break :t type_opaque_ty_decl.val.toType(); | |
| 18842 | ) orelse @panic("std.builtin.Type is corrupt"); | |
| 18843 | try sema.ensureNavResolved(src, nav); | |
| 18844 | break :t Type.fromInterned(ip.getNav(nav).status.resolved.val); | |
| 18878 | 18845 | }; |
| 18879 | 18846 | |
| 18880 | 18847 | try ty.resolveFields(pt); |
| 18881 | const decls_val = try sema.typeInfoDecls(block, src, type_info_ty, ty.getNamespaceIndex(mod)); | |
| 18848 | const decls_val = try sema.typeInfoDecls(block, src, type_info_ty, ty.getNamespace(mod)); | |
| 18882 | 18849 | |
| 18883 | 18850 | const field_values = .{ |
| 18884 | 18851 | // decls: []const Declaration, |
| ... | ... | @@ -18906,19 +18873,19 @@ fn typeInfoDecls( |
| 18906 | 18873 | opt_namespace: InternPool.OptionalNamespaceIndex, |
| 18907 | 18874 | ) CompileError!InternPool.Index { |
| 18908 | 18875 | const pt = sema.pt; |
| 18909 | const mod = pt.zcu; | |
| 18876 | const zcu = pt.zcu; | |
| 18877 | const ip = &zcu.intern_pool; | |
| 18910 | 18878 | const gpa = sema.gpa; |
| 18911 | 18879 | |
| 18912 | 18880 | const declaration_ty = t: { |
| 18913 | const declaration_ty_decl_index = (try sema.namespaceLookup( | |
| 18881 | const nav = try sema.namespaceLookup( | |
| 18914 | 18882 | block, |
| 18915 | 18883 | src, |
| 18916 | type_info_ty.getNamespaceIndex(mod), | |
| 18917 | try mod.intern_pool.getOrPutString(gpa, pt.tid, "Declaration", .no_embedded_nulls), | |
| 18918 | )).?; | |
| 18919 | try sema.ensureDeclAnalyzed(declaration_ty_decl_index); | |
| 18920 | const declaration_ty_decl = mod.declPtr(declaration_ty_decl_index); | |
| 18921 | break :t declaration_ty_decl.val.toType(); | |
| 18884 | type_info_ty.getNamespaceIndex(zcu), | |
| 18885 | try ip.getOrPutString(gpa, pt.tid, "Declaration", .no_embedded_nulls), | |
| 18886 | ) orelse @panic("std.builtin.Type is corrupt"); | |
| 18887 | try sema.ensureNavResolved(src, nav); | |
| 18888 | break :t Type.fromInterned(ip.getNav(nav).status.resolved.val); | |
| 18922 | 18889 | }; |
| 18923 | 18890 | |
| 18924 | 18891 | var decl_vals = std.ArrayList(InternPool.Index).init(gpa); |
| ... | ... | @@ -18927,7 +18894,7 @@ fn typeInfoDecls( |
| 18927 | 18894 | var seen_namespaces = std.AutoHashMap(*Namespace, void).init(gpa); |
| 18928 | 18895 | defer seen_namespaces.deinit(); |
| 18929 | 18896 | |
| 18930 | try sema.typeInfoNamespaceDecls(block, opt_namespace, declaration_ty, &decl_vals, &seen_namespaces); | |
| 18897 | try sema.typeInfoNamespaceDecls(block, src, opt_namespace, declaration_ty, &decl_vals, &seen_namespaces); | |
| 18931 | 18898 | |
| 18932 | 18899 | const array_decl_ty = try pt.arrayType(.{ |
| 18933 | 18900 | .len = decl_vals.items.len, |
| ... | ... | @@ -18944,12 +18911,12 @@ fn typeInfoDecls( |
| 18944 | 18911 | .is_const = true, |
| 18945 | 18912 | }, |
| 18946 | 18913 | })).toIntern(); |
| 18947 | const manyptr_ty = Type.fromInterned(slice_ty).slicePtrFieldType(mod).toIntern(); | |
| 18914 | const manyptr_ty = Type.fromInterned(slice_ty).slicePtrFieldType(zcu).toIntern(); | |
| 18948 | 18915 | return try pt.intern(.{ .slice = .{ |
| 18949 | 18916 | .ty = slice_ty, |
| 18950 | 18917 | .ptr = try pt.intern(.{ .ptr = .{ |
| 18951 | 18918 | .ty = manyptr_ty, |
| 18952 | .base_addr = .{ .anon_decl = .{ | |
| 18919 | .base_addr = .{ .uav = .{ | |
| 18953 | 18920 | .orig_ty = manyptr_ty, |
| 18954 | 18921 | .val = new_decl_val, |
| 18955 | 18922 | } }, |
| ... | ... | @@ -18962,59 +18929,54 @@ fn typeInfoDecls( |
| 18962 | 18929 | fn typeInfoNamespaceDecls( |
| 18963 | 18930 | sema: *Sema, |
| 18964 | 18931 | block: *Block, |
| 18932 | src: LazySrcLoc, | |
| 18965 | 18933 | opt_namespace_index: InternPool.OptionalNamespaceIndex, |
| 18966 | 18934 | declaration_ty: Type, |
| 18967 | 18935 | decl_vals: *std.ArrayList(InternPool.Index), |
| 18968 | 18936 | seen_namespaces: *std.AutoHashMap(*Namespace, void), |
| 18969 | 18937 | ) !void { |
| 18970 | 18938 | const pt = sema.pt; |
| 18971 | const mod = pt.zcu; | |
| 18972 | const ip = &mod.intern_pool; | |
| 18939 | const zcu = pt.zcu; | |
| 18940 | const ip = &zcu.intern_pool; | |
| 18973 | 18941 | |
| 18974 | 18942 | const namespace_index = opt_namespace_index.unwrap() orelse return; |
| 18975 | const namespace = mod.namespacePtr(namespace_index); | |
| 18943 | const namespace = zcu.namespacePtr(namespace_index); | |
| 18976 | 18944 | |
| 18977 | 18945 | const gop = try seen_namespaces.getOrPut(namespace); |
| 18978 | 18946 | if (gop.found_existing) return; |
| 18979 | 18947 | |
| 18980 | const decls = namespace.decls.keys(); | |
| 18981 | for (decls) |decl_index| { | |
| 18982 | const decl = mod.declPtr(decl_index); | |
| 18983 | if (!decl.is_pub) continue; | |
| 18984 | if (decl.kind == .@"usingnamespace") { | |
| 18985 | if (decl.analysis == .in_progress) continue; | |
| 18986 | try sema.ensureDeclAnalyzed(decl_index); | |
| 18987 | try sema.typeInfoNamespaceDecls(block, decl.val.toType().getNamespaceIndex(mod), declaration_ty, decl_vals, seen_namespaces); | |
| 18988 | continue; | |
| 18989 | } | |
| 18990 | if (decl.kind != .named) continue; | |
| 18991 | const name_val = v: { | |
| 18992 | const decl_name_len = decl.name.length(ip); | |
| 18993 | const new_decl_ty = try pt.arrayType(.{ | |
| 18994 | .len = decl_name_len, | |
| 18948 | for (namespace.pub_decls.keys()) |nav| { | |
| 18949 | const name = ip.getNav(nav).name; | |
| 18950 | const name_val = name_val: { | |
| 18951 | const name_len = name.length(ip); | |
| 18952 | const array_ty = try pt.arrayType(.{ | |
| 18953 | .len = name_len, | |
| 18995 | 18954 | .sentinel = .zero_u8, |
| 18996 | 18955 | .child = .u8_type, |
| 18997 | 18956 | }); |
| 18998 | const new_decl_val = try pt.intern(.{ .aggregate = .{ | |
| 18999 | .ty = new_decl_ty.toIntern(), | |
| 19000 | .storage = .{ .bytes = decl.name.toString() }, | |
| 19001 | } }); | |
| 19002 | break :v try pt.intern(.{ .slice = .{ | |
| 19003 | .ty = .slice_const_u8_sentinel_0_type, | |
| 19004 | .ptr = try pt.intern(.{ .ptr = .{ | |
| 19005 | .ty = .manyptr_const_u8_sentinel_0_type, | |
| 19006 | .base_addr = .{ .anon_decl = .{ | |
| 19007 | .orig_ty = .slice_const_u8_sentinel_0_type, | |
| 19008 | .val = new_decl_val, | |
| 19009 | } }, | |
| 19010 | .byte_offset = 0, | |
| 19011 | } }), | |
| 19012 | .len = (try pt.intValue(Type.usize, decl_name_len)).toIntern(), | |
| 18957 | const array_val = try pt.intern(.{ .aggregate = .{ | |
| 18958 | .ty = array_ty.toIntern(), | |
| 18959 | .storage = .{ .bytes = name.toString() }, | |
| 19013 | 18960 | } }); |
| 18961 | break :name_val try pt.intern(.{ | |
| 18962 | .slice = .{ | |
| 18963 | .ty = .slice_const_u8_sentinel_0_type, // [:0]const u8 | |
| 18964 | .ptr = try pt.intern(.{ | |
| 18965 | .ptr = .{ | |
| 18966 | .ty = .manyptr_const_u8_sentinel_0_type, // [*:0]const u8 | |
| 18967 | .base_addr = .{ .uav = .{ | |
| 18968 | .orig_ty = .slice_const_u8_sentinel_0_type, | |
| 18969 | .val = array_val, | |
| 18970 | } }, | |
| 18971 | .byte_offset = 0, | |
| 18972 | }, | |
| 18973 | }), | |
| 18974 | .len = (try pt.intValue(Type.usize, name_len)).toIntern(), | |
| 18975 | }, | |
| 18976 | }); | |
| 19014 | 18977 | }; |
| 19015 | ||
| 19016 | const fields = .{ | |
| 19017 | //name: [:0]const u8, | |
| 18978 | const fields = [_]InternPool.Index{ | |
| 18979 | // name: [:0]const u8, | |
| 19018 | 18980 | name_val, |
| 19019 | 18981 | }; |
| 19020 | 18982 | try decl_vals.append(try pt.intern(.{ .aggregate = .{ |
| ... | ... | @@ -19022,6 +18984,17 @@ fn typeInfoNamespaceDecls( |
| 19022 | 18984 | .storage = .{ .elems = &fields }, |
| 19023 | 18985 | } })); |
| 19024 | 18986 | } |
| 18987 | ||
| 18988 | for (namespace.pub_usingnamespace.items) |nav| { | |
| 18989 | if (ip.getNav(nav).analysis_owner.unwrap()) |cau| { | |
| 18990 | if (zcu.analysis_in_progress.contains(AnalUnit.wrap(.{ .cau = cau }))) { | |
| 18991 | continue; | |
| 18992 | } | |
| 18993 | } | |
| 18994 | try sema.ensureNavResolved(src, nav); | |
| 18995 | const namespace_ty = Type.fromInterned(ip.getNav(nav).status.resolved.val); | |
| 18996 | try sema.typeInfoNamespaceDecls(block, src, namespace_ty.getNamespaceIndex(zcu).toOptional(), declaration_ty, decl_vals, seen_namespaces); | |
| 18997 | } | |
| 19025 | 18998 | } |
| 19026 | 18999 | |
| 19027 | 19000 | fn zirTypeof(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| ... | ... | @@ -19906,7 +19879,7 @@ fn restoreErrRetIndex(sema: *Sema, start_block: *Block, src: LazySrcLoc, target_ |
| 19906 | 19879 | return; |
| 19907 | 19880 | } |
| 19908 | 19881 | |
| 19909 | if (!mod.intern_pool.funcAnalysisUnordered(sema.owner_func_index).calls_or_awaits_errorable_fn) return; | |
| 19882 | if (!mod.intern_pool.funcAnalysisUnordered(sema.owner.unwrap().func).calls_or_awaits_errorable_fn) return; | |
| 19910 | 19883 | if (!start_block.ownerModule().error_tracing) return; |
| 19911 | 19884 | |
| 19912 | 19885 | assert(saved_index != .none); // The .error_return_trace_index field was dropped somewhere |
| ... | ... | @@ -19928,7 +19901,7 @@ fn addToInferredErrorSet(sema: *Sema, uncasted_operand: Air.Inst.Ref) !void { |
| 19928 | 19901 | }, |
| 19929 | 19902 | else => if (ip.isInferredErrorSetType(err_set_ty)) { |
| 19930 | 19903 | const ies = sema.fn_ret_ty_ies.?; |
| 19931 | assert(ies.func == sema.func_index); | |
| 19904 | assert(ies.func == sema.owner.unwrap().func); | |
| 19932 | 19905 | try sema.addToInferredErrorSetPtr(ies, sema.typeOf(uncasted_operand)); |
| 19933 | 19906 | }, |
| 19934 | 19907 | } |
| ... | ... | @@ -20232,7 +20205,7 @@ fn zirStructInitEmptyResult(sema: *Sema, block: *Block, inst: Zir.Inst.Index, is |
| 20232 | 20205 | |
| 20233 | 20206 | if (is_byref) { |
| 20234 | 20207 | const init_val = (try sema.resolveValue(init_ref)).?; |
| 20235 | return anonDeclRef(sema, init_val.toIntern()); | |
| 20208 | return sema.uavRef(init_val.toIntern()); | |
| 20236 | 20209 | } else { |
| 20237 | 20210 | return init_ref; |
| 20238 | 20211 | } |
| ... | ... | @@ -21056,7 +21029,7 @@ fn arrayInitAnon( |
| 21056 | 21029 | } |
| 21057 | 21030 | |
| 21058 | 21031 | fn addConstantMaybeRef(sema: *Sema, val: InternPool.Index, is_ref: bool) !Air.Inst.Ref { |
| 21059 | return if (is_ref) anonDeclRef(sema, val) else Air.internedToRef(val); | |
| 21032 | return if (is_ref) sema.uavRef(val) else Air.internedToRef(val); | |
| 21060 | 21033 | } |
| 21061 | 21034 | |
| 21062 | 21035 | fn zirFieldTypeRef(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| ... | ... | @@ -21163,16 +21136,16 @@ fn getErrorReturnTrace(sema: *Sema, block: *Block) CompileError!Air.Inst.Ref { |
| 21163 | 21136 | const ptr_stack_trace_ty = try pt.singleMutPtrType(stack_trace_ty); |
| 21164 | 21137 | const opt_ptr_stack_trace_ty = try pt.optionalType(ptr_stack_trace_ty.toIntern()); |
| 21165 | 21138 | |
| 21166 | if (sema.owner_func_index != .none and | |
| 21167 | ip.funcAnalysisUnordered(sema.owner_func_index).calls_or_awaits_errorable_fn and | |
| 21168 | block.ownerModule().error_tracing) | |
| 21169 | { | |
| 21170 | return block.addTy(.err_return_trace, opt_ptr_stack_trace_ty); | |
| 21139 | switch (sema.owner.unwrap()) { | |
| 21140 | .func => |func| if (ip.funcAnalysisUnordered(func).calls_or_awaits_errorable_fn and block.ownerModule().error_tracing) { | |
| 21141 | return block.addTy(.err_return_trace, opt_ptr_stack_trace_ty); | |
| 21142 | }, | |
| 21143 | .cau => {}, | |
| 21171 | 21144 | } |
| 21172 | return Air.internedToRef((try pt.intern(.{ .opt = .{ | |
| 21145 | return Air.internedToRef(try pt.intern(.{ .opt = .{ | |
| 21173 | 21146 | .ty = opt_ptr_stack_trace_ty.toIntern(), |
| 21174 | 21147 | .val = .none, |
| 21175 | } }))); | |
| 21148 | } })); | |
| 21176 | 21149 | } |
| 21177 | 21150 | |
| 21178 | 21151 | fn zirFrame( |
| ... | ... | @@ -21369,24 +21342,24 @@ fn zirTagName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 21369 | 21342 | const operand = try sema.resolveInst(inst_data.operand); |
| 21370 | 21343 | const operand_ty = sema.typeOf(operand); |
| 21371 | 21344 | const pt = sema.pt; |
| 21372 | const mod = pt.zcu; | |
| 21373 | const ip = &mod.intern_pool; | |
| 21345 | const zcu = pt.zcu; | |
| 21346 | const ip = &zcu.intern_pool; | |
| 21374 | 21347 | |
| 21375 | 21348 | try operand_ty.resolveLayout(pt); |
| 21376 | const enum_ty = switch (operand_ty.zigTypeTag(mod)) { | |
| 21349 | const enum_ty = switch (operand_ty.zigTypeTag(zcu)) { | |
| 21377 | 21350 | .EnumLiteral => { |
| 21378 | 21351 | const val = try sema.resolveConstDefinedValue(block, LazySrcLoc.unneeded, operand, undefined); |
| 21379 | 21352 | const tag_name = ip.indexToKey(val.toIntern()).enum_literal; |
| 21380 | 21353 | return sema.addNullTerminatedStrLit(tag_name); |
| 21381 | 21354 | }, |
| 21382 | 21355 | .Enum => operand_ty, |
| 21383 | .Union => operand_ty.unionTagType(mod) orelse | |
| 21356 | .Union => operand_ty.unionTagType(zcu) orelse | |
| 21384 | 21357 | return sema.fail(block, src, "union '{}' is untagged", .{operand_ty.fmt(pt)}), |
| 21385 | 21358 | else => return sema.fail(block, operand_src, "expected enum or union; found '{}'", .{ |
| 21386 | 21359 | operand_ty.fmt(pt), |
| 21387 | 21360 | }), |
| 21388 | 21361 | }; |
| 21389 | if (enum_ty.enumFieldCount(mod) == 0) { | |
| 21362 | if (enum_ty.enumFieldCount(zcu) == 0) { | |
| 21390 | 21363 | // TODO I don't think this is the correct way to handle this but |
| 21391 | 21364 | // it prevents a crash. |
| 21392 | 21365 | // https://github.com/ziglang/zig/issues/15909 |
| ... | ... | @@ -21394,26 +21367,25 @@ fn zirTagName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 21394 | 21367 | enum_ty.fmt(pt), |
| 21395 | 21368 | }); |
| 21396 | 21369 | } |
| 21397 | const enum_decl_index = enum_ty.getOwnerDecl(mod); | |
| 21398 | 21370 | const casted_operand = try sema.coerce(block, enum_ty, operand, operand_src); |
| 21399 | 21371 | if (try sema.resolveDefinedValue(block, operand_src, casted_operand)) |val| { |
| 21400 | const field_index = enum_ty.enumTagFieldIndex(val, mod) orelse { | |
| 21372 | const field_index = enum_ty.enumTagFieldIndex(val, zcu) orelse { | |
| 21401 | 21373 | const msg = msg: { |
| 21402 | 21374 | const msg = try sema.errMsg(src, "no field with value '{}' in enum '{}'", .{ |
| 21403 | val.fmtValueSema(pt, sema), mod.declPtr(enum_decl_index).name.fmt(ip), | |
| 21375 | val.fmtValueSema(pt, sema), enum_ty.fmt(pt), | |
| 21404 | 21376 | }); |
| 21405 | 21377 | errdefer msg.destroy(sema.gpa); |
| 21406 | try sema.errNote(enum_ty.srcLoc(mod), msg, "declared here", .{}); | |
| 21378 | try sema.errNote(enum_ty.srcLoc(zcu), msg, "declared here", .{}); | |
| 21407 | 21379 | break :msg msg; |
| 21408 | 21380 | }; |
| 21409 | 21381 | return sema.failWithOwnedErrorMsg(block, msg); |
| 21410 | 21382 | }; |
| 21411 | 21383 | // TODO: write something like getCoercedInts to avoid needing to dupe |
| 21412 | const field_name = enum_ty.enumFieldName(field_index, mod); | |
| 21384 | const field_name = enum_ty.enumFieldName(field_index, zcu); | |
| 21413 | 21385 | return sema.addNullTerminatedStrLit(field_name); |
| 21414 | 21386 | } |
| 21415 | 21387 | try sema.requireRuntimeBlock(block, src, operand_src); |
| 21416 | if (block.wantSafety() and mod.backendSupportsFeature(.is_named_enum_value)) { | |
| 21388 | if (block.wantSafety() and zcu.backendSupportsFeature(.is_named_enum_value)) { | |
| 21417 | 21389 | const ok = try block.addUnOp(.is_named_enum_value, casted_operand); |
| 21418 | 21390 | try sema.addSafetyCheck(block, src, ok, .invalid_enum_value); |
| 21419 | 21391 | } |
| ... | ... | @@ -21810,7 +21782,6 @@ fn zirReify( |
| 21810 | 21782 | } |
| 21811 | 21783 | |
| 21812 | 21784 | const wip_ty = switch (try ip.getOpaqueType(gpa, pt.tid, .{ |
| 21813 | .has_namespace = false, | |
| 21814 | 21785 | .key = .{ .reified = .{ |
| 21815 | 21786 | .zir_index = try block.trackZir(inst), |
| 21816 | 21787 | } }, |
| ... | ... | @@ -21820,19 +21791,21 @@ fn zirReify( |
| 21820 | 21791 | }; |
| 21821 | 21792 | errdefer wip_ty.cancel(ip, pt.tid); |
| 21822 | 21793 | |
| 21823 | const new_decl_index = try sema.createAnonymousDeclTypeNamed( | |
| 21794 | wip_ty.setName(ip, try sema.createTypeName( | |
| 21824 | 21795 | block, |
| 21825 | Value.fromInterned(wip_ty.index), | |
| 21826 | 21796 | name_strategy, |
| 21827 | 21797 | "opaque", |
| 21828 | 21798 | inst, |
| 21829 | ); | |
| 21830 | mod.declPtr(new_decl_index).owns_tv = true; | |
| 21831 | errdefer pt.abortAnonDecl(new_decl_index); | |
| 21799 | wip_ty.index, | |
| 21800 | )); | |
| 21832 | 21801 | |
| 21833 | try pt.finalizeAnonDecl(new_decl_index); | |
| 21802 | const new_namespace_index = try pt.createNamespace(.{ | |
| 21803 | .parent = block.namespace.toOptional(), | |
| 21804 | .owner_type = wip_ty.index, | |
| 21805 | .file_scope = block.getFileScopeIndex(mod), | |
| 21806 | }); | |
| 21834 | 21807 | |
| 21835 | return Air.internedToRef(wip_ty.finish(ip, new_decl_index, .none)); | |
| 21808 | return Air.internedToRef(wip_ty.finish(ip, .none, new_namespace_index)); | |
| 21836 | 21809 | }, |
| 21837 | 21810 | .Union => { |
| 21838 | 21811 | const struct_type = ip.loadStructType(ip.typeOf(union_val.val)); |
| ... | ... | @@ -22001,13 +21974,14 @@ fn reifyEnum( |
| 22001 | 21974 | }); |
| 22002 | 21975 | } |
| 22003 | 21976 | |
| 21977 | const tracked_inst = try block.trackZir(inst); | |
| 21978 | ||
| 22004 | 21979 | const wip_ty = switch (try ip.getEnumType(gpa, pt.tid, .{ |
| 22005 | .has_namespace = false, | |
| 22006 | 21980 | .has_values = true, |
| 22007 | 21981 | .tag_mode = if (is_exhaustive) .explicit else .nonexhaustive, |
| 22008 | 21982 | .fields_len = fields_len, |
| 22009 | 21983 | .key = .{ .reified = .{ |
| 22010 | .zir_index = try block.trackZir(inst), | |
| 21984 | .zir_index = tracked_inst, | |
| 22011 | 21985 | .type_hash = hasher.final(), |
| 22012 | 21986 | } }, |
| 22013 | 21987 | })) { |
| ... | ... | @@ -22020,17 +21994,23 @@ fn reifyEnum( |
| 22020 | 21994 | return sema.fail(block, src, "Type.Enum.tag_type must be an integer type", .{}); |
| 22021 | 21995 | } |
| 22022 | 21996 | |
| 22023 | const new_decl_index = try sema.createAnonymousDeclTypeNamed( | |
| 21997 | wip_ty.setName(ip, try sema.createTypeName( | |
| 22024 | 21998 | block, |
| 22025 | Value.fromInterned(wip_ty.index), | |
| 22026 | 21999 | name_strategy, |
| 22027 | 22000 | "enum", |
| 22028 | 22001 | inst, |
| 22029 | ); | |
| 22030 | mod.declPtr(new_decl_index).owns_tv = true; | |
| 22031 | errdefer pt.abortAnonDecl(new_decl_index); | |
| 22002 | wip_ty.index, | |
| 22003 | )); | |
| 22032 | 22004 | |
| 22033 | wip_ty.prepare(ip, new_decl_index, .none); | |
| 22005 | const new_namespace_index = try pt.createNamespace(.{ | |
| 22006 | .parent = block.namespace.toOptional(), | |
| 22007 | .owner_type = wip_ty.index, | |
| 22008 | .file_scope = block.getFileScopeIndex(mod), | |
| 22009 | }); | |
| 22010 | ||
| 22011 | const new_cau_index = try ip.createTypeCau(gpa, pt.tid, tracked_inst, new_namespace_index, wip_ty.index); | |
| 22012 | ||
| 22013 | wip_ty.prepare(ip, new_cau_index, new_namespace_index); | |
| 22034 | 22014 | wip_ty.setTagTy(ip, tag_ty.toIntern()); |
| 22035 | 22015 | |
| 22036 | 22016 | for (0..fields_len) |field_idx| { |
| ... | ... | @@ -22076,7 +22056,6 @@ fn reifyEnum( |
| 22076 | 22056 | return sema.fail(block, src, "non-exhaustive enum specified every value", .{}); |
| 22077 | 22057 | } |
| 22078 | 22058 | |
| 22079 | try pt.finalizeAnonDecl(new_decl_index); | |
| 22080 | 22059 | return Air.internedToRef(wip_ty.index); |
| 22081 | 22060 | } |
| 22082 | 22061 | |
| ... | ... | @@ -22134,6 +22113,8 @@ fn reifyUnion( |
| 22134 | 22113 | } |
| 22135 | 22114 | } |
| 22136 | 22115 | |
| 22116 | const tracked_inst = try block.trackZir(inst); | |
| 22117 | ||
| 22137 | 22118 | const wip_ty = switch (try ip.getUnionType(gpa, pt.tid, .{ |
| 22138 | 22119 | .flags = .{ |
| 22139 | 22120 | .layout = layout, |
| ... | ... | @@ -22152,13 +22133,12 @@ fn reifyUnion( |
| 22152 | 22133 | .assumed_pointer_aligned = false, |
| 22153 | 22134 | .alignment = .none, |
| 22154 | 22135 | }, |
| 22155 | .has_namespace = false, | |
| 22156 | 22136 | .fields_len = fields_len, |
| 22157 | 22137 | .enum_tag_ty = .none, // set later because not yet validated |
| 22158 | 22138 | .field_types = &.{}, // set later |
| 22159 | 22139 | .field_aligns = &.{}, // set later |
| 22160 | 22140 | .key = .{ .reified = .{ |
| 22161 | .zir_index = try block.trackZir(inst), | |
| 22141 | .zir_index = tracked_inst, | |
| 22162 | 22142 | .type_hash = hasher.final(), |
| 22163 | 22143 | } }, |
| 22164 | 22144 | })) { |
| ... | ... | @@ -22167,15 +22147,14 @@ fn reifyUnion( |
| 22167 | 22147 | }; |
| 22168 | 22148 | errdefer wip_ty.cancel(ip, pt.tid); |
| 22169 | 22149 | |
| 22170 | const new_decl_index = try sema.createAnonymousDeclTypeNamed( | |
| 22150 | const type_name = try sema.createTypeName( | |
| 22171 | 22151 | block, |
| 22172 | Value.fromInterned(wip_ty.index), | |
| 22173 | 22152 | name_strategy, |
| 22174 | 22153 | "union", |
| 22175 | 22154 | inst, |
| 22155 | wip_ty.index, | |
| 22176 | 22156 | ); |
| 22177 | mod.declPtr(new_decl_index).owns_tv = true; | |
| 22178 | errdefer pt.abortAnonDecl(new_decl_index); | |
| 22157 | wip_ty.setName(ip, type_name); | |
| 22179 | 22158 | |
| 22180 | 22159 | const field_types = try sema.arena.alloc(InternPool.Index, fields_len); |
| 22181 | 22160 | const field_aligns = if (any_aligns) try sema.arena.alloc(InternPool.Alignment, fields_len) else undefined; |
| ... | ... | @@ -22268,7 +22247,7 @@ fn reifyUnion( |
| 22268 | 22247 | } |
| 22269 | 22248 | } |
| 22270 | 22249 | |
| 22271 | const enum_tag_ty = try sema.generateUnionTagTypeSimple(block, field_names.keys(), mod.declPtr(new_decl_index)); | |
| 22250 | const enum_tag_ty = try sema.generateUnionTagTypeSimple(block, field_names.keys(), wip_ty.index, type_name); | |
| 22272 | 22251 | break :tag_ty .{ enum_tag_ty, false }; |
| 22273 | 22252 | }; |
| 22274 | 22253 | errdefer if (!has_explicit_tag) ip.remove(pt.tid, enum_tag_ty); // remove generated tag type on error |
| ... | ... | @@ -22315,10 +22294,17 @@ fn reifyUnion( |
| 22315 | 22294 | loaded_union.setTagType(ip, enum_tag_ty); |
| 22316 | 22295 | loaded_union.setStatus(ip, .have_field_types); |
| 22317 | 22296 | |
| 22318 | try pt.finalizeAnonDecl(new_decl_index); | |
| 22297 | const new_namespace_index = try pt.createNamespace(.{ | |
| 22298 | .parent = block.namespace.toOptional(), | |
| 22299 | .owner_type = wip_ty.index, | |
| 22300 | .file_scope = block.getFileScopeIndex(mod), | |
| 22301 | }); | |
| 22302 | ||
| 22303 | const new_cau_index = try ip.createTypeCau(gpa, pt.tid, tracked_inst, new_namespace_index, wip_ty.index); | |
| 22304 | ||
| 22319 | 22305 | try mod.comp.queueJob(.{ .resolve_type_fully = wip_ty.index }); |
| 22320 | try sema.addReferenceEntry(src, AnalUnit.wrap(.{ .decl = new_decl_index })); | |
| 22321 | return Air.internedToRef(wip_ty.finish(ip, new_decl_index, .none)); | |
| 22306 | try sema.addReferenceEntry(src, AnalUnit.wrap(.{ .cau = new_cau_index })); | |
| 22307 | return Air.internedToRef(wip_ty.finish(ip, new_cau_index.toOptional(), new_namespace_index)); | |
| 22322 | 22308 | } |
| 22323 | 22309 | |
| 22324 | 22310 | fn reifyStruct( |
| ... | ... | @@ -22399,6 +22385,8 @@ fn reifyStruct( |
| 22399 | 22385 | } |
| 22400 | 22386 | } |
| 22401 | 22387 | |
| 22388 | const tracked_inst = try block.trackZir(inst); | |
| 22389 | ||
| 22402 | 22390 | const wip_ty = switch (try ip.getStructType(gpa, pt.tid, .{ |
| 22403 | 22391 | .layout = layout, |
| 22404 | 22392 | .fields_len = fields_len, |
| ... | ... | @@ -22409,9 +22397,8 @@ fn reifyStruct( |
| 22409 | 22397 | .any_default_inits = any_default_inits, |
| 22410 | 22398 | .any_aligned_fields = any_aligned_fields, |
| 22411 | 22399 | .inits_resolved = true, |
| 22412 | .has_namespace = false, | |
| 22413 | 22400 | .key = .{ .reified = .{ |
| 22414 | .zir_index = try block.trackZir(inst), | |
| 22401 | .zir_index = tracked_inst, | |
| 22415 | 22402 | .type_hash = hasher.final(), |
| 22416 | 22403 | } }, |
| 22417 | 22404 | })) { |
| ... | ... | @@ -22426,15 +22413,13 @@ fn reifyStruct( |
| 22426 | 22413 | .auto => {}, |
| 22427 | 22414 | }; |
| 22428 | 22415 | |
| 22429 | const new_decl_index = try sema.createAnonymousDeclTypeNamed( | |
| 22416 | wip_ty.setName(ip, try sema.createTypeName( | |
| 22430 | 22417 | block, |
| 22431 | Value.fromInterned(wip_ty.index), | |
| 22432 | 22418 | name_strategy, |
| 22433 | 22419 | "struct", |
| 22434 | 22420 | inst, |
| 22435 | ); | |
| 22436 | mod.declPtr(new_decl_index).owns_tv = true; | |
| 22437 | errdefer pt.abortAnonDecl(new_decl_index); | |
| 22421 | wip_ty.index, | |
| 22422 | )); | |
| 22438 | 22423 | |
| 22439 | 22424 | const struct_type = ip.loadStructType(wip_ty.index); |
| 22440 | 22425 | |
| ... | ... | @@ -22582,10 +22567,17 @@ fn reifyStruct( |
| 22582 | 22567 | } |
| 22583 | 22568 | } |
| 22584 | 22569 | |
| 22585 | try pt.finalizeAnonDecl(new_decl_index); | |
| 22570 | const new_namespace_index = try pt.createNamespace(.{ | |
| 22571 | .parent = block.namespace.toOptional(), | |
| 22572 | .owner_type = wip_ty.index, | |
| 22573 | .file_scope = block.getFileScopeIndex(mod), | |
| 22574 | }); | |
| 22575 | ||
| 22576 | const new_cau_index = try ip.createTypeCau(gpa, pt.tid, tracked_inst, new_namespace_index, wip_ty.index); | |
| 22577 | ||
| 22586 | 22578 | try mod.comp.queueJob(.{ .resolve_type_fully = wip_ty.index }); |
| 22587 | try sema.addReferenceEntry(src, AnalUnit.wrap(.{ .decl = new_decl_index })); | |
| 22588 | return Air.internedToRef(wip_ty.finish(ip, new_decl_index, .none)); | |
| 22579 | try sema.addReferenceEntry(src, AnalUnit.wrap(.{ .cau = new_cau_index })); | |
| 22580 | return Air.internedToRef(wip_ty.finish(ip, new_cau_index.toOptional(), new_namespace_index)); | |
| 22589 | 22581 | } |
| 22590 | 22582 | |
| 22591 | 22583 | fn resolveVaListRef(sema: *Sema, block: *Block, src: LazySrcLoc, zir_ref: Zir.Inst.Ref) CompileError!Air.Inst.Ref { |
| ... | ... | @@ -26028,7 +26020,8 @@ fn zirVarExtended( |
| 26028 | 26020 | extended: Zir.Inst.Extended.InstData, |
| 26029 | 26021 | ) CompileError!Air.Inst.Ref { |
| 26030 | 26022 | const pt = sema.pt; |
| 26031 | const mod = pt.zcu; | |
| 26023 | const zcu = pt.zcu; | |
| 26024 | const ip = &zcu.intern_pool; | |
| 26032 | 26025 | const extra = sema.code.extraData(Zir.Inst.ExtendedVar, extended.operand); |
| 26033 | 26026 | const ty_src = block.src(.{ .node_offset_var_decl_ty = 0 }); |
| 26034 | 26027 | const init_src = block.src(.{ .node_offset_var_decl_init = 0 }); |
| ... | ... | @@ -26075,16 +26068,62 @@ fn zirVarExtended( |
| 26075 | 26068 | |
| 26076 | 26069 | try sema.validateVarType(block, ty_src, var_ty, small.is_extern); |
| 26077 | 26070 | |
| 26078 | return Air.internedToRef((try pt.intern(.{ .variable = .{ | |
| 26071 | if (small.is_extern) { | |
| 26072 | // We need to resolve the alignment and addrspace early. | |
| 26073 | // Keep in sync with logic in `Zcu.PerThread.semaCau`. | |
| 26074 | const align_src = block.src(.{ .node_offset_var_decl_align = 0 }); | |
| 26075 | const addrspace_src = block.src(.{ .node_offset_var_decl_addrspace = 0 }); | |
| 26076 | ||
| 26077 | const decl_inst, const decl_bodies = decl: { | |
| 26078 | const decl_inst = sema.getOwnerCauDeclInst().resolve(ip); | |
| 26079 | const zir_decl, const extra_end = sema.code.getDeclaration(decl_inst); | |
| 26080 | break :decl .{ decl_inst, zir_decl.getBodies(extra_end, sema.code) }; | |
| 26081 | }; | |
| 26082 | ||
| 26083 | const alignment: InternPool.Alignment = a: { | |
| 26084 | const align_body = decl_bodies.align_body orelse break :a .none; | |
| 26085 | const align_ref = try sema.resolveInlineBody(block, align_body, decl_inst); | |
| 26086 | break :a try sema.analyzeAsAlign(block, align_src, align_ref); | |
| 26087 | }; | |
| 26088 | ||
| 26089 | const @"addrspace": std.builtin.AddressSpace = as: { | |
| 26090 | const addrspace_ctx: Sema.AddressSpaceContext = switch (ip.indexToKey(var_ty.toIntern())) { | |
| 26091 | .func_type => .function, | |
| 26092 | else => .variable, | |
| 26093 | }; | |
| 26094 | const target = zcu.getTarget(); | |
| 26095 | const addrspace_body = decl_bodies.addrspace_body orelse break :as switch (addrspace_ctx) { | |
| 26096 | .function => target_util.defaultAddressSpace(target, .function), | |
| 26097 | .variable => target_util.defaultAddressSpace(target, .global_mutable), | |
| 26098 | .constant => target_util.defaultAddressSpace(target, .global_constant), | |
| 26099 | else => unreachable, | |
| 26100 | }; | |
| 26101 | const addrspace_ref = try sema.resolveInlineBody(block, addrspace_body, decl_inst); | |
| 26102 | break :as try sema.analyzeAsAddressSpace(block, addrspace_src, addrspace_ref, addrspace_ctx); | |
| 26103 | }; | |
| 26104 | ||
| 26105 | return Air.internedToRef(try pt.getExtern(.{ | |
| 26106 | .name = sema.getOwnerCauNavName(), | |
| 26107 | .ty = var_ty.toIntern(), | |
| 26108 | .lib_name = try ip.getOrPutStringOpt(sema.gpa, pt.tid, lib_name, .no_embedded_nulls), | |
| 26109 | .is_const = small.is_const, | |
| 26110 | .is_threadlocal = small.is_threadlocal, | |
| 26111 | .is_weak_linkage = false, | |
| 26112 | .alignment = alignment, | |
| 26113 | .@"addrspace" = @"addrspace", | |
| 26114 | .zir_index = sema.getOwnerCauDeclInst(), // `declaration` instruction | |
| 26115 | .owner_nav = undefined, // ignored by `getExtern` | |
| 26116 | })); | |
| 26117 | } | |
| 26118 | assert(!small.is_const); // non-const non-extern variable is not legal | |
| 26119 | return Air.internedToRef(try pt.intern(.{ .variable = .{ | |
| 26079 | 26120 | .ty = var_ty.toIntern(), |
| 26080 | 26121 | .init = init_val, |
| 26081 | .decl = sema.owner_decl_index, | |
| 26082 | .lib_name = try mod.intern_pool.getOrPutStringOpt(sema.gpa, pt.tid, lib_name, .no_embedded_nulls), | |
| 26083 | .is_extern = small.is_extern, | |
| 26084 | .is_const = small.is_const, | |
| 26122 | .owner_nav = sema.getOwnerCauNav(), | |
| 26123 | .lib_name = try ip.getOrPutStringOpt(sema.gpa, pt.tid, lib_name, .no_embedded_nulls), | |
| 26085 | 26124 | .is_threadlocal = small.is_threadlocal, |
| 26086 | 26125 | .is_weak_linkage = false, |
| 26087 | } }))); | |
| 26126 | } })); | |
| 26088 | 26127 | } |
| 26089 | 26128 | |
| 26090 | 26129 | fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| ... | ... | @@ -26255,10 +26294,23 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A |
| 26255 | 26294 | else => |e| return e, |
| 26256 | 26295 | }; |
| 26257 | 26296 | break :blk mod.toEnum(std.builtin.CallingConvention, cc_val); |
| 26258 | } else if (sema.owner_decl.is_exported and has_body) | |
| 26259 | .C | |
| 26260 | else | |
| 26261 | .Unspecified; | |
| 26297 | } else cc: { | |
| 26298 | if (has_body) { | |
| 26299 | const decl_inst = if (sema.generic_owner != .none) decl_inst: { | |
| 26300 | // Generic instance -- use the original function declaration to | |
| 26301 | // look for the `export` syntax. | |
| 26302 | const nav = mod.intern_pool.getNav(mod.funcInfo(sema.generic_owner).owner_nav); | |
| 26303 | const cau = mod.intern_pool.getCau(nav.analysis_owner.unwrap().?); | |
| 26304 | break :decl_inst cau.zir_index; | |
| 26305 | } else sema.getOwnerCauDeclInst(); // not an instantiation so we're analyzing a function declaration Cau | |
| 26306 | ||
| 26307 | const zir_decl = sema.code.getDeclaration(decl_inst.resolve(&mod.intern_pool))[0]; | |
| 26308 | if (zir_decl.flags.is_export) { | |
| 26309 | break :cc .C; | |
| 26310 | } | |
| 26311 | } | |
| 26312 | break :cc .Unspecified; | |
| 26313 | }; | |
| 26262 | 26314 | |
| 26263 | 26315 | const ret_ty: Type = if (extra.data.bits.has_ret_ty_body) blk: { |
| 26264 | 26316 | const body_len = sema.code.extra[extra_index]; |
| ... | ... | @@ -26600,42 +26652,32 @@ fn zirBuiltinExtern( |
| 26600 | 26652 | |
| 26601 | 26653 | const options = try sema.resolveExternOptions(block, options_src, extra.rhs); |
| 26602 | 26654 | |
| 26655 | // TODO: error for threadlocal functions, non-const functions, etc | |
| 26656 | ||
| 26603 | 26657 | if (options.linkage == .weak and !ty.ptrAllowsZero(mod)) { |
| 26604 | 26658 | ty = try pt.optionalType(ty.toIntern()); |
| 26605 | 26659 | } |
| 26606 | 26660 | const ptr_info = ty.ptrInfo(mod); |
| 26607 | 26661 | |
| 26608 | const new_decl_index = try pt.allocateNewDecl(sema.owner_decl.src_namespace); | |
| 26609 | errdefer pt.destroyDecl(new_decl_index); | |
| 26610 | const new_decl = mod.declPtr(new_decl_index); | |
| 26611 | try pt.initNewAnonDecl( | |
| 26612 | new_decl_index, | |
| 26613 | Value.fromInterned( | |
| 26614 | if (Type.fromInterned(ptr_info.child).zigTypeTag(mod) == .Fn) | |
| 26615 | try ip.getExternFunc(sema.gpa, pt.tid, .{ | |
| 26616 | .ty = ptr_info.child, | |
| 26617 | .decl = new_decl_index, | |
| 26618 | .lib_name = options.library_name, | |
| 26619 | }) | |
| 26620 | else | |
| 26621 | try pt.intern(.{ .variable = .{ | |
| 26622 | .ty = ptr_info.child, | |
| 26623 | .init = .none, | |
| 26624 | .decl = new_decl_index, | |
| 26625 | .lib_name = options.library_name, | |
| 26626 | .is_extern = true, | |
| 26627 | .is_const = ptr_info.flags.is_const, | |
| 26628 | .is_threadlocal = options.is_thread_local, | |
| 26629 | .is_weak_linkage = options.linkage == .weak, | |
| 26630 | } }), | |
| 26631 | ), | |
| 26632 | options.name, | |
| 26633 | .none, | |
| 26634 | ); | |
| 26635 | new_decl.owns_tv = true; | |
| 26636 | // Note that this will queue the anon decl for codegen, so that the backend can | |
| 26637 | // correctly handle the extern, including duplicate detection. | |
| 26638 | try pt.finalizeAnonDecl(new_decl_index); | |
| 26662 | const extern_val = try pt.getExtern(.{ | |
| 26663 | .name = options.name, | |
| 26664 | .ty = ptr_info.child, | |
| 26665 | .lib_name = options.library_name, | |
| 26666 | .is_const = ptr_info.flags.is_const, | |
| 26667 | .is_threadlocal = options.is_thread_local, | |
| 26668 | .is_weak_linkage = options.linkage == .weak, | |
| 26669 | .alignment = ptr_info.flags.alignment, | |
| 26670 | .@"addrspace" = ptr_info.flags.address_space, | |
| 26671 | // This instruction is just for source locations. | |
| 26672 | // `builtin_extern` doesn't provide enough information, and isn't currently tracked. | |
| 26673 | // So, for now, just use our containing `declaration`. | |
| 26674 | .zir_index = switch (sema.owner.unwrap()) { | |
| 26675 | .cau => sema.getOwnerCauDeclInst(), | |
| 26676 | .func => sema.getOwnerFuncDeclInst(), | |
| 26677 | }, | |
| 26678 | .owner_nav = undefined, // ignored by `getExtern` | |
| 26679 | }); | |
| 26680 | const extern_nav = ip.indexToKey(extern_val).@"extern".owner_nav; | |
| 26639 | 26681 | |
| 26640 | 26682 | return Air.internedToRef((try pt.getCoerced(Value.fromInterned(try pt.intern(.{ .ptr = .{ |
| 26641 | 26683 | .ty = switch (ip.indexToKey(ty.toIntern())) { |
| ... | ... | @@ -26643,7 +26685,7 @@ fn zirBuiltinExtern( |
| 26643 | 26685 | .opt_type => |child_type| child_type, |
| 26644 | 26686 | else => unreachable, |
| 26645 | 26687 | }, |
| 26646 | .base_addr = .{ .decl = new_decl_index }, | |
| 26688 | .base_addr = .{ .nav = extern_nav }, | |
| 26647 | 26689 | .byte_offset = 0, |
| 26648 | 26690 | } })), ty)).toIntern()); |
| 26649 | 26691 | } |
| ... | ... | @@ -27129,17 +27171,15 @@ fn explainWhyTypeIsNotPacked( |
| 27129 | 27171 | } |
| 27130 | 27172 | } |
| 27131 | 27173 | |
| 27132 | fn prepareSimplePanic(sema: *Sema) !void { | |
| 27174 | fn prepareSimplePanic(sema: *Sema, block: *Block, src: LazySrcLoc) !void { | |
| 27133 | 27175 | const pt = sema.pt; |
| 27134 | 27176 | const mod = pt.zcu; |
| 27135 | 27177 | |
| 27136 | 27178 | if (mod.panic_func_index == .none) { |
| 27137 | const decl_index = (try pt.getBuiltinDecl("panic")); | |
| 27138 | // decl_index may be an alias; we must find the decl that actually | |
| 27139 | // owns the function. | |
| 27140 | try sema.ensureDeclAnalyzed(decl_index); | |
| 27141 | const fn_val = try mod.declPtr(decl_index).valueOrFail(); | |
| 27142 | try sema.declareDependency(.{ .decl_val = decl_index }); | |
| 27179 | const fn_ref = try sema.analyzeNavVal(block, src, try pt.getBuiltinNav("panic")); | |
| 27180 | const fn_val = try sema.resolveConstValue(block, src, fn_ref, .{ | |
| 27181 | .needed_comptime_reason = "panic handler must be comptime-known", | |
| 27182 | }); | |
| 27143 | 27183 | assert(fn_val.typeOf(mod).zigTypeTag(mod) == .Fn); |
| 27144 | 27184 | assert(try sema.fnHasRuntimeBits(fn_val.typeOf(mod))); |
| 27145 | 27185 | try mod.ensureFuncBodyAnalysisQueued(fn_val.toIntern()); |
| ... | ... | @@ -27167,16 +27207,16 @@ fn prepareSimplePanic(sema: *Sema) !void { |
| 27167 | 27207 | /// Backends depend on panic decls being available when lowering safety-checked |
| 27168 | 27208 | /// instructions. This function ensures the panic function will be available to |
| 27169 | 27209 | /// be called during that time. |
| 27170 | fn preparePanicId(sema: *Sema, block: *Block, panic_id: Module.PanicId) !InternPool.DeclIndex { | |
| 27210 | fn preparePanicId(sema: *Sema, block: *Block, src: LazySrcLoc, panic_id: Module.PanicId) !InternPool.Nav.Index { | |
| 27171 | 27211 | const pt = sema.pt; |
| 27172 | 27212 | const mod = pt.zcu; |
| 27173 | 27213 | const gpa = sema.gpa; |
| 27174 | 27214 | if (mod.panic_messages[@intFromEnum(panic_id)].unwrap()) |x| return x; |
| 27175 | 27215 | |
| 27176 | try sema.prepareSimplePanic(); | |
| 27216 | try sema.prepareSimplePanic(block, src); | |
| 27177 | 27217 | |
| 27178 | 27218 | const panic_messages_ty = try pt.getBuiltinType("panic_messages"); |
| 27179 | const msg_decl_index = (sema.namespaceLookup( | |
| 27219 | const msg_nav_index = (sema.namespaceLookup( | |
| 27180 | 27220 | block, |
| 27181 | 27221 | LazySrcLoc.unneeded, |
| 27182 | 27222 | panic_messages_ty.getNamespaceIndex(mod), |
| ... | ... | @@ -27186,9 +27226,9 @@ fn preparePanicId(sema: *Sema, block: *Block, panic_id: Module.PanicId) !InternP |
| 27186 | 27226 | error.GenericPoison, error.ComptimeReturn, error.ComptimeBreak => unreachable, |
| 27187 | 27227 | error.OutOfMemory => |e| return e, |
| 27188 | 27228 | }).?; |
| 27189 | try sema.ensureDeclAnalyzed(msg_decl_index); | |
| 27190 | mod.panic_messages[@intFromEnum(panic_id)] = msg_decl_index.toOptional(); | |
| 27191 | return msg_decl_index; | |
| 27229 | try sema.ensureNavResolved(src, msg_nav_index); | |
| 27230 | mod.panic_messages[@intFromEnum(panic_id)] = msg_nav_index.toOptional(); | |
| 27231 | return msg_nav_index; | |
| 27192 | 27232 | } |
| 27193 | 27233 | |
| 27194 | 27234 | fn addSafetyCheck( |
| ... | ... | @@ -27282,10 +27322,10 @@ fn panicWithMsg(sema: *Sema, block: *Block, src: LazySrcLoc, msg_inst: Air.Inst. |
| 27282 | 27322 | return; |
| 27283 | 27323 | } |
| 27284 | 27324 | |
| 27285 | try sema.prepareSimplePanic(); | |
| 27325 | try sema.prepareSimplePanic(block, src); | |
| 27286 | 27326 | |
| 27287 | 27327 | const panic_func = mod.funcInfo(mod.panic_func_index); |
| 27288 | const panic_fn = try sema.analyzeDeclVal(block, src, panic_func.owner_decl); | |
| 27328 | const panic_fn = try sema.analyzeNavVal(block, src, panic_func.owner_nav); | |
| 27289 | 27329 | const null_stack_trace = Air.internedToRef(mod.null_stack_trace); |
| 27290 | 27330 | |
| 27291 | 27331 | const opt_usize_ty = try pt.optionalType(.usize_type); |
| ... | ... | @@ -27455,8 +27495,8 @@ fn safetyCheckFormatted( |
| 27455 | 27495 | } |
| 27456 | 27496 | |
| 27457 | 27497 | fn safetyPanic(sema: *Sema, block: *Block, src: LazySrcLoc, panic_id: Module.PanicId) CompileError!void { |
| 27458 | const msg_decl_index = try sema.preparePanicId(block, panic_id); | |
| 27459 | const msg_inst = try sema.analyzeDeclVal(block, src, msg_decl_index); | |
| 27498 | const msg_nav_index = try sema.preparePanicId(block, src, panic_id); | |
| 27499 | const msg_inst = try sema.analyzeNavVal(block, src, msg_nav_index); | |
| 27460 | 27500 | try sema.panicWithMsg(block, src, msg_inst, .@"safety check"); |
| 27461 | 27501 | } |
| 27462 | 27502 | |
| ... | ... | @@ -27628,21 +27668,21 @@ fn fieldVal( |
| 27628 | 27668 | return Air.internedToRef(enum_val.toIntern()); |
| 27629 | 27669 | }, |
| 27630 | 27670 | .Struct, .Opaque => { |
| 27631 | if (try sema.namespaceLookupVal(block, src, child_type.getNamespaceIndex(mod), field_name)) |inst| { | |
| 27632 | return inst; | |
| 27671 | switch (child_type.toIntern()) { | |
| 27672 | .empty_struct_type, .anyopaque_type => {}, // no namespace | |
| 27673 | else => if (try sema.namespaceLookupVal(block, src, child_type.getNamespaceIndex(mod), field_name)) |inst| { | |
| 27674 | return inst; | |
| 27675 | }, | |
| 27633 | 27676 | } |
| 27634 | 27677 | return sema.failWithBadMemberAccess(block, child_type, src, field_name); |
| 27635 | 27678 | }, |
| 27636 | else => { | |
| 27637 | const msg = msg: { | |
| 27638 | const msg = try sema.errMsg(src, "type '{}' has no members", .{child_type.fmt(pt)}); | |
| 27639 | errdefer msg.destroy(sema.gpa); | |
| 27640 | if (child_type.isSlice(mod)) try sema.errNote(src, msg, "slice values have 'len' and 'ptr' members", .{}); | |
| 27641 | if (child_type.zigTypeTag(mod) == .Array) try sema.errNote(src, msg, "array values have 'len' member", .{}); | |
| 27642 | break :msg msg; | |
| 27643 | }; | |
| 27644 | return sema.failWithOwnedErrorMsg(block, msg); | |
| 27645 | }, | |
| 27679 | else => return sema.failWithOwnedErrorMsg(block, msg: { | |
| 27680 | const msg = try sema.errMsg(src, "type '{}' has no members", .{child_type.fmt(pt)}); | |
| 27681 | errdefer msg.destroy(sema.gpa); | |
| 27682 | if (child_type.isSlice(mod)) try sema.errNote(src, msg, "slice values have 'len' and 'ptr' members", .{}); | |
| 27683 | if (child_type.zigTypeTag(mod) == .Array) try sema.errNote(src, msg, "array values have 'len' member", .{}); | |
| 27684 | break :msg msg; | |
| 27685 | }), | |
| 27646 | 27686 | } |
| 27647 | 27687 | }, |
| 27648 | 27688 | .Struct => if (is_pointer_to) { |
| ... | ... | @@ -27700,7 +27740,7 @@ fn fieldPtr( |
| 27700 | 27740 | .Array => { |
| 27701 | 27741 | if (field_name.eqlSlice("len", ip)) { |
| 27702 | 27742 | const int_val = try pt.intValue(Type.usize, inner_ty.arrayLen(mod)); |
| 27703 | return anonDeclRef(sema, int_val.toIntern()); | |
| 27743 | return uavRef(sema, int_val.toIntern()); | |
| 27704 | 27744 | } else if (field_name.eqlSlice("ptr", ip) and is_pointer_to) { |
| 27705 | 27745 | const ptr_info = object_ty.ptrInfo(mod); |
| 27706 | 27746 | const new_ptr_ty = try pt.ptrTypeSema(.{ |
| ... | ... | @@ -27839,7 +27879,7 @@ fn fieldPtr( |
| 27839 | 27879 | child_type |
| 27840 | 27880 | else |
| 27841 | 27881 | try pt.singleErrorSetType(field_name); |
| 27842 | return anonDeclRef(sema, try pt.intern(.{ .err = .{ | |
| 27882 | return uavRef(sema, try pt.intern(.{ .err = .{ | |
| 27843 | 27883 | .ty = error_set_type.toIntern(), |
| 27844 | 27884 | .name = field_name, |
| 27845 | 27885 | } })); |
| ... | ... | @@ -27853,7 +27893,7 @@ fn fieldPtr( |
| 27853 | 27893 | if (enum_ty.enumFieldIndex(field_name, mod)) |field_index| { |
| 27854 | 27894 | const field_index_u32: u32 = @intCast(field_index); |
| 27855 | 27895 | const idx_val = try pt.enumValueFieldIndex(enum_ty, field_index_u32); |
| 27856 | return anonDeclRef(sema, idx_val.toIntern()); | |
| 27896 | return uavRef(sema, idx_val.toIntern()); | |
| 27857 | 27897 | } |
| 27858 | 27898 | } |
| 27859 | 27899 | return sema.failWithBadMemberAccess(block, child_type, field_name_src, field_name); |
| ... | ... | @@ -27867,7 +27907,7 @@ fn fieldPtr( |
| 27867 | 27907 | }; |
| 27868 | 27908 | const field_index_u32: u32 = @intCast(field_index); |
| 27869 | 27909 | const idx_val = try pt.enumValueFieldIndex(child_type, field_index_u32); |
| 27870 | return anonDeclRef(sema, idx_val.toIntern()); | |
| 27910 | return uavRef(sema, idx_val.toIntern()); | |
| 27871 | 27911 | }, |
| 27872 | 27912 | .Struct, .Opaque => { |
| 27873 | 27913 | if (try sema.namespaceLookupRef(block, src, child_type.getNamespaceIndex(mod), field_name)) |inst| { |
| ... | ... | @@ -27923,18 +27963,18 @@ fn fieldCallBind( |
| 27923 | 27963 | // in `fieldVal`. This function takes a pointer and returns a pointer. |
| 27924 | 27964 | |
| 27925 | 27965 | const pt = sema.pt; |
| 27926 | const mod = pt.zcu; | |
| 27927 | const ip = &mod.intern_pool; | |
| 27966 | const zcu = pt.zcu; | |
| 27967 | const ip = &zcu.intern_pool; | |
| 27928 | 27968 | const raw_ptr_src = src; // TODO better source location |
| 27929 | 27969 | const raw_ptr_ty = sema.typeOf(raw_ptr); |
| 27930 | const inner_ty = if (raw_ptr_ty.zigTypeTag(mod) == .Pointer and (raw_ptr_ty.ptrSize(mod) == .One or raw_ptr_ty.ptrSize(mod) == .C)) | |
| 27931 | raw_ptr_ty.childType(mod) | |
| 27970 | const inner_ty = if (raw_ptr_ty.zigTypeTag(zcu) == .Pointer and (raw_ptr_ty.ptrSize(zcu) == .One or raw_ptr_ty.ptrSize(zcu) == .C)) | |
| 27971 | raw_ptr_ty.childType(zcu) | |
| 27932 | 27972 | else |
| 27933 | 27973 | return sema.fail(block, raw_ptr_src, "expected single pointer, found '{}'", .{raw_ptr_ty.fmt(pt)}); |
| 27934 | 27974 | |
| 27935 | 27975 | // Optionally dereference a second pointer to get the concrete type. |
| 27936 | const is_double_ptr = inner_ty.zigTypeTag(mod) == .Pointer and inner_ty.ptrSize(mod) == .One; | |
| 27937 | const concrete_ty = if (is_double_ptr) inner_ty.childType(mod) else inner_ty; | |
| 27976 | const is_double_ptr = inner_ty.zigTypeTag(zcu) == .Pointer and inner_ty.ptrSize(zcu) == .One; | |
| 27977 | const concrete_ty = if (is_double_ptr) inner_ty.childType(zcu) else inner_ty; | |
| 27938 | 27978 | const ptr_ty = if (is_double_ptr) inner_ty else raw_ptr_ty; |
| 27939 | 27979 | const object_ptr = if (is_double_ptr) |
| 27940 | 27980 | try sema.analyzeLoad(block, src, raw_ptr, src) |
| ... | ... | @@ -27942,36 +27982,36 @@ fn fieldCallBind( |
| 27942 | 27982 | raw_ptr; |
| 27943 | 27983 | |
| 27944 | 27984 | find_field: { |
| 27945 | switch (concrete_ty.zigTypeTag(mod)) { | |
| 27985 | switch (concrete_ty.zigTypeTag(zcu)) { | |
| 27946 | 27986 | .Struct => { |
| 27947 | 27987 | try concrete_ty.resolveFields(pt); |
| 27948 | if (mod.typeToStruct(concrete_ty)) |struct_type| { | |
| 27988 | if (zcu.typeToStruct(concrete_ty)) |struct_type| { | |
| 27949 | 27989 | const field_index = struct_type.nameIndex(ip, field_name) orelse |
| 27950 | 27990 | break :find_field; |
| 27951 | 27991 | const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[field_index]); |
| 27952 | 27992 | |
| 27953 | 27993 | return sema.finishFieldCallBind(block, src, ptr_ty, field_ty, field_index, object_ptr); |
| 27954 | } else if (concrete_ty.isTuple(mod)) { | |
| 27994 | } else if (concrete_ty.isTuple(zcu)) { | |
| 27955 | 27995 | if (field_name.eqlSlice("len", ip)) { |
| 27956 | return .{ .direct = try pt.intRef(Type.usize, concrete_ty.structFieldCount(mod)) }; | |
| 27996 | return .{ .direct = try pt.intRef(Type.usize, concrete_ty.structFieldCount(zcu)) }; | |
| 27957 | 27997 | } |
| 27958 | 27998 | if (field_name.toUnsigned(ip)) |field_index| { |
| 27959 | if (field_index >= concrete_ty.structFieldCount(mod)) break :find_field; | |
| 27960 | return sema.finishFieldCallBind(block, src, ptr_ty, concrete_ty.structFieldType(field_index, mod), field_index, object_ptr); | |
| 27999 | if (field_index >= concrete_ty.structFieldCount(zcu)) break :find_field; | |
| 28000 | return sema.finishFieldCallBind(block, src, ptr_ty, concrete_ty.structFieldType(field_index, zcu), field_index, object_ptr); | |
| 27961 | 28001 | } |
| 27962 | 28002 | } else { |
| 27963 | const max = concrete_ty.structFieldCount(mod); | |
| 28003 | const max = concrete_ty.structFieldCount(zcu); | |
| 27964 | 28004 | for (0..max) |i_usize| { |
| 27965 | 28005 | const i: u32 = @intCast(i_usize); |
| 27966 | if (field_name == concrete_ty.structFieldName(i, mod).unwrap().?) { | |
| 27967 | return sema.finishFieldCallBind(block, src, ptr_ty, concrete_ty.structFieldType(i, mod), i, object_ptr); | |
| 28006 | if (field_name == concrete_ty.structFieldName(i, zcu).unwrap().?) { | |
| 28007 | return sema.finishFieldCallBind(block, src, ptr_ty, concrete_ty.structFieldType(i, zcu), i, object_ptr); | |
| 27968 | 28008 | } |
| 27969 | 28009 | } |
| 27970 | 28010 | } |
| 27971 | 28011 | }, |
| 27972 | 28012 | .Union => { |
| 27973 | 28013 | try concrete_ty.resolveFields(pt); |
| 27974 | const union_obj = mod.typeToUnion(concrete_ty).?; | |
| 28014 | const union_obj = zcu.typeToUnion(concrete_ty).?; | |
| 27975 | 28015 | _ = union_obj.loadTagType(ip).nameIndex(ip, field_name) orelse break :find_field; |
| 27976 | 28016 | const field_ptr = try unionFieldPtr(sema, block, src, object_ptr, field_name, field_name_src, concrete_ty, false); |
| 27977 | 28017 | return .{ .direct = try sema.analyzeLoad(block, src, field_ptr, src) }; |
| ... | ... | @@ -27985,23 +28025,23 @@ fn fieldCallBind( |
| 27985 | 28025 | } |
| 27986 | 28026 | |
| 27987 | 28027 | // If we get here, we need to look for a decl in the struct type instead. |
| 27988 | const found_decl = found_decl: { | |
| 27989 | const namespace = concrete_ty.getNamespace(mod) orelse | |
| 27990 | break :found_decl null; | |
| 27991 | const decl_idx = (try sema.namespaceLookup(block, src, namespace, field_name)) orelse | |
| 27992 | break :found_decl null; | |
| 28028 | const found_nav = found_nav: { | |
| 28029 | const namespace = concrete_ty.getNamespace(zcu).unwrap() orelse | |
| 28030 | break :found_nav null; | |
| 28031 | const nav_index = try sema.namespaceLookup(block, src, namespace, field_name) orelse | |
| 28032 | break :found_nav null; | |
| 27993 | 28033 | |
| 27994 | const decl_val = try sema.analyzeDeclVal(block, src, decl_idx); | |
| 28034 | const decl_val = try sema.analyzeNavVal(block, src, nav_index); | |
| 27995 | 28035 | const decl_type = sema.typeOf(decl_val); |
| 27996 | if (mod.typeToFunc(decl_type)) |func_type| f: { | |
| 28036 | if (zcu.typeToFunc(decl_type)) |func_type| f: { | |
| 27997 | 28037 | if (func_type.param_types.len == 0) break :f; |
| 27998 | 28038 | |
| 27999 | 28039 | const first_param_type = Type.fromInterned(func_type.param_types.get(ip)[0]); |
| 28000 | 28040 | if (first_param_type.isGenericPoison() or |
| 28001 | (first_param_type.zigTypeTag(mod) == .Pointer and | |
| 28002 | (first_param_type.ptrSize(mod) == .One or | |
| 28003 | first_param_type.ptrSize(mod) == .C) and | |
| 28004 | first_param_type.childType(mod).eql(concrete_ty, mod))) | |
| 28041 | (first_param_type.zigTypeTag(zcu) == .Pointer and | |
| 28042 | (first_param_type.ptrSize(zcu) == .One or | |
| 28043 | first_param_type.ptrSize(zcu) == .C) and | |
| 28044 | first_param_type.childType(zcu).eql(concrete_ty, zcu))) | |
| 28005 | 28045 | { |
| 28006 | 28046 | // Note that if the param type is generic poison, we know that it must |
| 28007 | 28047 | // specifically be `anytype` since it's the first parameter, meaning we |
| ... | ... | @@ -28012,31 +28052,31 @@ fn fieldCallBind( |
| 28012 | 28052 | .func_inst = decl_val, |
| 28013 | 28053 | .arg0_inst = object_ptr, |
| 28014 | 28054 | } }; |
| 28015 | } else if (first_param_type.eql(concrete_ty, mod)) { | |
| 28055 | } else if (first_param_type.eql(concrete_ty, zcu)) { | |
| 28016 | 28056 | const deref = try sema.analyzeLoad(block, src, object_ptr, src); |
| 28017 | 28057 | return .{ .method = .{ |
| 28018 | 28058 | .func_inst = decl_val, |
| 28019 | 28059 | .arg0_inst = deref, |
| 28020 | 28060 | } }; |
| 28021 | } else if (first_param_type.zigTypeTag(mod) == .Optional) { | |
| 28022 | const child = first_param_type.optionalChild(mod); | |
| 28023 | if (child.eql(concrete_ty, mod)) { | |
| 28061 | } else if (first_param_type.zigTypeTag(zcu) == .Optional) { | |
| 28062 | const child = first_param_type.optionalChild(zcu); | |
| 28063 | if (child.eql(concrete_ty, zcu)) { | |
| 28024 | 28064 | const deref = try sema.analyzeLoad(block, src, object_ptr, src); |
| 28025 | 28065 | return .{ .method = .{ |
| 28026 | 28066 | .func_inst = decl_val, |
| 28027 | 28067 | .arg0_inst = deref, |
| 28028 | 28068 | } }; |
| 28029 | } else if (child.zigTypeTag(mod) == .Pointer and | |
| 28030 | child.ptrSize(mod) == .One and | |
| 28031 | child.childType(mod).eql(concrete_ty, mod)) | |
| 28069 | } else if (child.zigTypeTag(zcu) == .Pointer and | |
| 28070 | child.ptrSize(zcu) == .One and | |
| 28071 | child.childType(zcu).eql(concrete_ty, zcu)) | |
| 28032 | 28072 | { |
| 28033 | 28073 | return .{ .method = .{ |
| 28034 | 28074 | .func_inst = decl_val, |
| 28035 | 28075 | .arg0_inst = object_ptr, |
| 28036 | 28076 | } }; |
| 28037 | 28077 | } |
| 28038 | } else if (first_param_type.zigTypeTag(mod) == .ErrorUnion and | |
| 28039 | first_param_type.errorUnionPayload(mod).eql(concrete_ty, mod)) | |
| 28078 | } else if (first_param_type.zigTypeTag(zcu) == .ErrorUnion and | |
| 28079 | first_param_type.errorUnionPayload(zcu).eql(concrete_ty, zcu)) | |
| 28040 | 28080 | { |
| 28041 | 28081 | const deref = try sema.analyzeLoad(block, src, object_ptr, src); |
| 28042 | 28082 | return .{ .method = .{ |
| ... | ... | @@ -28045,7 +28085,7 @@ fn fieldCallBind( |
| 28045 | 28085 | } }; |
| 28046 | 28086 | } |
| 28047 | 28087 | } |
| 28048 | break :found_decl decl_idx; | |
| 28088 | break :found_nav nav_index; | |
| 28049 | 28089 | }; |
| 28050 | 28090 | |
| 28051 | 28091 | const msg = msg: { |
| ... | ... | @@ -28055,14 +28095,15 @@ fn fieldCallBind( |
| 28055 | 28095 | }); |
| 28056 | 28096 | errdefer msg.destroy(sema.gpa); |
| 28057 | 28097 | try sema.addDeclaredHereNote(msg, concrete_ty); |
| 28058 | if (found_decl) |decl_idx| { | |
| 28059 | const decl = mod.declPtr(decl_idx); | |
| 28060 | try sema.errNote(.{ | |
| 28061 | .base_node_inst = decl.zir_decl_index.unwrap().?, | |
| 28062 | .offset = LazySrcLoc.Offset.nodeOffset(0), | |
| 28063 | }, msg, "'{}' is not a member function", .{field_name.fmt(ip)}); | |
| 28098 | if (found_nav) |nav_index| { | |
| 28099 | try sema.errNote( | |
| 28100 | zcu.navSrcLoc(nav_index), | |
| 28101 | msg, | |
| 28102 | "'{}' is not a member function", | |
| 28103 | .{field_name.fmt(ip)}, | |
| 28104 | ); | |
| 28064 | 28105 | } |
| 28065 | if (concrete_ty.zigTypeTag(mod) == .ErrorUnion) { | |
| 28106 | if (concrete_ty.zigTypeTag(zcu) == .ErrorUnion) { | |
| 28066 | 28107 | try sema.errNote(src, msg, "consider using 'try', 'catch', or 'if'", .{}); |
| 28067 | 28108 | } |
| 28068 | 28109 | if (is_double_ptr) { |
| ... | ... | @@ -28117,29 +28158,24 @@ fn namespaceLookup( |
| 28117 | 28158 | sema: *Sema, |
| 28118 | 28159 | block: *Block, |
| 28119 | 28160 | src: LazySrcLoc, |
| 28120 | opt_namespace: InternPool.OptionalNamespaceIndex, | |
| 28161 | namespace: InternPool.NamespaceIndex, | |
| 28121 | 28162 | decl_name: InternPool.NullTerminatedString, |
| 28122 | ) CompileError!?InternPool.DeclIndex { | |
| 28163 | ) CompileError!?InternPool.Nav.Index { | |
| 28123 | 28164 | const pt = sema.pt; |
| 28124 | const mod = pt.zcu; | |
| 28165 | const zcu = pt.zcu; | |
| 28125 | 28166 | const gpa = sema.gpa; |
| 28126 | if (try sema.lookupInNamespace(block, src, opt_namespace, decl_name, true)) |decl_index| { | |
| 28127 | const decl = mod.declPtr(decl_index); | |
| 28128 | if (!decl.is_pub and decl.getFileScope(mod) != block.getFileScope(mod)) { | |
| 28129 | const msg = msg: { | |
| 28167 | if (try sema.lookupInNamespace(block, src, namespace, decl_name, true)) |lookup| { | |
| 28168 | if (!lookup.accessible) { | |
| 28169 | return sema.failWithOwnedErrorMsg(block, msg: { | |
| 28130 | 28170 | const msg = try sema.errMsg(src, "'{}' is not marked 'pub'", .{ |
| 28131 | decl_name.fmt(&mod.intern_pool), | |
| 28171 | decl_name.fmt(&zcu.intern_pool), | |
| 28132 | 28172 | }); |
| 28133 | 28173 | errdefer msg.destroy(gpa); |
| 28134 | try sema.errNote(.{ | |
| 28135 | .base_node_inst = decl.zir_decl_index.unwrap().?, | |
| 28136 | .offset = LazySrcLoc.Offset.nodeOffset(0), | |
| 28137 | }, msg, "declared here", .{}); | |
| 28174 | try sema.errNote(zcu.navSrcLoc(lookup.nav), msg, "declared here", .{}); | |
| 28138 | 28175 | break :msg msg; |
| 28139 | }; | |
| 28140 | return sema.failWithOwnedErrorMsg(block, msg); | |
| 28176 | }); | |
| 28141 | 28177 | } |
| 28142 | return decl_index; | |
| 28178 | return lookup.nav; | |
| 28143 | 28179 | } |
| 28144 | 28180 | return null; |
| 28145 | 28181 | } |
| ... | ... | @@ -28148,22 +28184,22 @@ fn namespaceLookupRef( |
| 28148 | 28184 | sema: *Sema, |
| 28149 | 28185 | block: *Block, |
| 28150 | 28186 | src: LazySrcLoc, |
| 28151 | opt_namespace: InternPool.OptionalNamespaceIndex, | |
| 28187 | namespace: InternPool.NamespaceIndex, | |
| 28152 | 28188 | decl_name: InternPool.NullTerminatedString, |
| 28153 | 28189 | ) CompileError!?Air.Inst.Ref { |
| 28154 | const decl = (try sema.namespaceLookup(block, src, opt_namespace, decl_name)) orelse return null; | |
| 28155 | return try sema.analyzeDeclRef(src, decl); | |
| 28190 | const nav = try sema.namespaceLookup(block, src, namespace, decl_name) orelse return null; | |
| 28191 | return try sema.analyzeNavRef(src, nav); | |
| 28156 | 28192 | } |
| 28157 | 28193 | |
| 28158 | 28194 | fn namespaceLookupVal( |
| 28159 | 28195 | sema: *Sema, |
| 28160 | 28196 | block: *Block, |
| 28161 | 28197 | src: LazySrcLoc, |
| 28162 | opt_namespace: InternPool.OptionalNamespaceIndex, | |
| 28198 | namespace: InternPool.NamespaceIndex, | |
| 28163 | 28199 | decl_name: InternPool.NullTerminatedString, |
| 28164 | 28200 | ) CompileError!?Air.Inst.Ref { |
| 28165 | const decl = (try sema.namespaceLookup(block, src, opt_namespace, decl_name)) orelse return null; | |
| 28166 | return try sema.analyzeDeclVal(block, src, decl); | |
| 28201 | const nav = try sema.namespaceLookup(block, src, namespace, decl_name) orelse return null; | |
| 28202 | return try sema.analyzeNavVal(block, src, nav); | |
| 28167 | 28203 | } |
| 28168 | 28204 | |
| 28169 | 28205 | fn structFieldPtr( |
| ... | ... | @@ -29200,9 +29236,9 @@ const CoerceOpts = struct { |
| 29200 | 29236 | |
| 29201 | 29237 | fn get(info: @This(), sema: *Sema) !?LazySrcLoc { |
| 29202 | 29238 | if (info.func_inst == .none) return null; |
| 29203 | const fn_decl = try sema.funcDeclSrc(info.func_inst) orelse return null; | |
| 29239 | const func_inst = try sema.funcDeclSrcInst(info.func_inst) orelse return null; | |
| 29204 | 29240 | return .{ |
| 29205 | .base_node_inst = fn_decl.zir_decl_index.unwrap().?, | |
| 29241 | .base_node_inst = func_inst, | |
| 29206 | 29242 | .offset = .{ .fn_proto_param_type = .{ |
| 29207 | 29243 | .fn_proto_node_offset = 0, |
| 29208 | 29244 | .param_index = info.param_i, |
| ... | ... | @@ -29303,8 +29339,12 @@ fn coerceExtra( |
| 29303 | 29339 | // Function body to function pointer. |
| 29304 | 29340 | if (inst_ty.zigTypeTag(zcu) == .Fn) { |
| 29305 | 29341 | const fn_val = try sema.resolveConstDefinedValue(block, LazySrcLoc.unneeded, inst, undefined); |
| 29306 | const fn_decl = fn_val.pointerDecl(zcu).?; | |
| 29307 | const inst_as_ptr = try sema.analyzeDeclRef(inst_src, fn_decl); | |
| 29342 | const fn_nav = switch (zcu.intern_pool.indexToKey(fn_val.toIntern())) { | |
| 29343 | .func => |f| f.owner_nav, | |
| 29344 | .@"extern" => |e| e.owner_nav, | |
| 29345 | else => unreachable, | |
| 29346 | }; | |
| 29347 | const inst_as_ptr = try sema.analyzeNavRef(inst_src, fn_nav); | |
| 29308 | 29348 | return sema.coerce(block, dest_ty, inst_as_ptr, inst_src); |
| 29309 | 29349 | } |
| 29310 | 29350 | |
| ... | ... | @@ -29846,7 +29886,7 @@ fn coerceExtra( |
| 29846 | 29886 | errdefer msg.destroy(sema.gpa); |
| 29847 | 29887 | |
| 29848 | 29888 | const ret_ty_src: LazySrcLoc = .{ |
| 29849 | .base_node_inst = zcu.funcOwnerDeclPtr(sema.func_index).zir_decl_index.unwrap().?, | |
| 29889 | .base_node_inst = sema.getOwnerFuncDeclInst(), | |
| 29850 | 29890 | .offset = .{ .node_offset_fn_type_ret_ty = 0 }, |
| 29851 | 29891 | }; |
| 29852 | 29892 | try sema.errNote(ret_ty_src, msg, "'noreturn' declared here", .{}); |
| ... | ... | @@ -29879,10 +29919,10 @@ fn coerceExtra( |
| 29879 | 29919 | |
| 29880 | 29920 | // Add notes about function return type |
| 29881 | 29921 | if (opts.is_ret and |
| 29882 | zcu.test_functions.get(zcu.funcOwnerDeclIndex(sema.func_index)) == null) | |
| 29922 | !zcu.test_functions.contains(zcu.funcInfo(sema.owner.unwrap().func).owner_nav)) | |
| 29883 | 29923 | { |
| 29884 | 29924 | const ret_ty_src: LazySrcLoc = .{ |
| 29885 | .base_node_inst = zcu.funcOwnerDeclPtr(sema.func_index).zir_decl_index.unwrap().?, | |
| 29925 | .base_node_inst = sema.getOwnerFuncDeclInst(), | |
| 29886 | 29926 | .offset = .{ .node_offset_fn_type_ret_ty = 0 }, |
| 29887 | 29927 | }; |
| 29888 | 29928 | if (inst_ty.isError(zcu) and !dest_ty.isError(zcu)) { |
| ... | ... | @@ -30885,9 +30925,9 @@ fn coerceVarArgParam( |
| 30885 | 30925 | if (block.is_typeof) return inst; |
| 30886 | 30926 | |
| 30887 | 30927 | const pt = sema.pt; |
| 30888 | const mod = pt.zcu; | |
| 30928 | const zcu = pt.zcu; | |
| 30889 | 30929 | const uncasted_ty = sema.typeOf(inst); |
| 30890 | const coerced = switch (uncasted_ty.zigTypeTag(mod)) { | |
| 30930 | const coerced = switch (uncasted_ty.zigTypeTag(zcu)) { | |
| 30891 | 30931 | // TODO consider casting to c_int/f64 if they fit |
| 30892 | 30932 | .ComptimeInt, .ComptimeFloat => return sema.fail( |
| 30893 | 30933 | block, |
| ... | ... | @@ -30897,12 +30937,12 @@ fn coerceVarArgParam( |
| 30897 | 30937 | ), |
| 30898 | 30938 | .Fn => fn_ptr: { |
| 30899 | 30939 | const fn_val = try sema.resolveConstDefinedValue(block, LazySrcLoc.unneeded, inst, undefined); |
| 30900 | const fn_decl = fn_val.pointerDecl(mod).?; | |
| 30901 | break :fn_ptr try sema.analyzeDeclRef(inst_src, fn_decl); | |
| 30940 | const fn_nav = zcu.funcInfo(fn_val.toIntern()).owner_nav; | |
| 30941 | break :fn_ptr try sema.analyzeNavRef(inst_src, fn_nav); | |
| 30902 | 30942 | }, |
| 30903 | 30943 | .Array => return sema.fail(block, inst_src, "arrays must be passed by reference to variadic function", .{}), |
| 30904 | 30944 | .Float => float: { |
| 30905 | const target = mod.getTarget(); | |
| 30945 | const target = zcu.getTarget(); | |
| 30906 | 30946 | const double_bits = target.c_type_bit_size(.double); |
| 30907 | 30947 | const inst_bits = uncasted_ty.floatBits(target); |
| 30908 | 30948 | if (inst_bits >= double_bits) break :float inst; |
| ... | ... | @@ -30912,10 +30952,10 @@ fn coerceVarArgParam( |
| 30912 | 30952 | else => unreachable, |
| 30913 | 30953 | } |
| 30914 | 30954 | }, |
| 30915 | else => if (uncasted_ty.isAbiInt(mod)) int: { | |
| 30955 | else => if (uncasted_ty.isAbiInt(zcu)) int: { | |
| 30916 | 30956 | if (!try sema.validateExternType(uncasted_ty, .param_ty)) break :int inst; |
| 30917 | const target = mod.getTarget(); | |
| 30918 | const uncasted_info = uncasted_ty.intInfo(mod); | |
| 30957 | const target = zcu.getTarget(); | |
| 30958 | const uncasted_info = uncasted_ty.intInfo(zcu); | |
| 30919 | 30959 | if (uncasted_info.bits <= target.c_type_bit_size(switch (uncasted_info.signedness) { |
| 30920 | 30960 | .signed => .int, |
| 30921 | 30961 | .unsigned => .uint, |
| ... | ... | @@ -32117,23 +32157,14 @@ fn coerceTupleToTuple( |
| 32117 | 32157 | } }))); |
| 32118 | 32158 | } |
| 32119 | 32159 | |
| 32120 | fn analyzeDeclVal( | |
| 32160 | fn analyzeNavVal( | |
| 32121 | 32161 | sema: *Sema, |
| 32122 | 32162 | block: *Block, |
| 32123 | 32163 | src: LazySrcLoc, |
| 32124 | decl_index: InternPool.DeclIndex, | |
| 32164 | nav_index: InternPool.Nav.Index, | |
| 32125 | 32165 | ) CompileError!Air.Inst.Ref { |
| 32126 | if (sema.decl_val_table.get(decl_index)) |result| { | |
| 32127 | return result; | |
| 32128 | } | |
| 32129 | const decl_ref = try sema.analyzeDeclRefInner(src, decl_index, false); | |
| 32130 | const result = try sema.analyzeLoad(block, src, decl_ref, src); | |
| 32131 | if (result.toInterned() != null) { | |
| 32132 | if (!block.is_typeof) { | |
| 32133 | try sema.decl_val_table.put(sema.gpa, decl_index, result); | |
| 32134 | } | |
| 32135 | } | |
| 32136 | return result; | |
| 32166 | const ref = try sema.analyzeNavRefInner(src, nav_index, false); | |
| 32167 | return sema.analyzeLoad(block, src, ref, src); | |
| 32137 | 32168 | } |
| 32138 | 32169 | |
| 32139 | 32170 | fn addReferenceEntry( |
| ... | ... | @@ -32148,44 +32179,37 @@ fn addReferenceEntry( |
| 32148 | 32179 | // TODO: we need to figure out how to model inline calls here. |
| 32149 | 32180 | // They aren't references in the analysis sense, but ought to show up in the reference trace! |
| 32150 | 32181 | // Would representing inline calls in the reference table cause excessive memory usage? |
| 32151 | try zcu.addUnitReference(sema.ownerUnit(), referenced_unit, src); | |
| 32182 | try zcu.addUnitReference(sema.owner, referenced_unit, src); | |
| 32152 | 32183 | } |
| 32153 | 32184 | |
| 32154 | pub fn ensureDeclAnalyzed(sema: *Sema, decl_index: InternPool.DeclIndex) CompileError!void { | |
| 32185 | pub fn ensureNavResolved(sema: *Sema, src: LazySrcLoc, nav_index: InternPool.Nav.Index) CompileError!void { | |
| 32155 | 32186 | const pt = sema.pt; |
| 32156 | const mod = pt.zcu; | |
| 32157 | const ip = &mod.intern_pool; | |
| 32158 | const decl = mod.declPtr(decl_index); | |
| 32159 | if (decl.analysis == .in_progress) { | |
| 32160 | const msg = try sema.errMsg(.{ | |
| 32161 | .base_node_inst = decl.zir_decl_index.unwrap().?, | |
| 32162 | .offset = LazySrcLoc.Offset.nodeOffset(0), | |
| 32163 | }, "dependency loop detected", .{}); | |
| 32164 | return sema.failWithOwnedErrorMsg(null, msg); | |
| 32165 | } | |
| 32187 | const zcu = pt.zcu; | |
| 32188 | const ip = &zcu.intern_pool; | |
| 32166 | 32189 | |
| 32167 | pt.ensureDeclAnalyzed(decl_index) catch |err| { | |
| 32168 | if (sema.owner_func_index != .none) { | |
| 32169 | ip.funcSetAnalysisState(sema.owner_func_index, .dependency_failure); | |
| 32170 | } else { | |
| 32171 | sema.owner_decl.analysis = .dependency_failure; | |
| 32172 | } | |
| 32173 | return err; | |
| 32174 | }; | |
| 32175 | } | |
| 32190 | const nav = ip.getNav(nav_index); | |
| 32176 | 32191 | |
| 32177 | fn ensureFuncBodyAnalyzed(sema: *Sema, func: InternPool.Index) CompileError!void { | |
| 32178 | const pt = sema.pt; | |
| 32179 | const mod = pt.zcu; | |
| 32180 | const ip = &mod.intern_pool; | |
| 32181 | pt.ensureFuncBodyAnalyzed(func) catch |err| { | |
| 32182 | if (sema.owner_func_index != .none) { | |
| 32183 | ip.funcSetAnalysisState(sema.owner_func_index, .dependency_failure); | |
| 32184 | } else { | |
| 32185 | sema.owner_decl.analysis = .dependency_failure; | |
| 32186 | } | |
| 32187 | return err; | |
| 32192 | const cau_index = nav.analysis_owner.unwrap() orelse { | |
| 32193 | assert(nav.status == .resolved); | |
| 32194 | return; | |
| 32188 | 32195 | }; |
| 32196 | ||
| 32197 | // Note that even if `nav.status == .resolved`, we must still trigger `ensureCauAnalyzed` | |
| 32198 | // to make sure the value is up-to-date on incremental updates. | |
| 32199 | ||
| 32200 | assert(ip.getCau(cau_index).owner.unwrap().nav == nav_index); | |
| 32201 | ||
| 32202 | const anal_unit = AnalUnit.wrap(.{ .cau = cau_index }); | |
| 32203 | try sema.addReferenceEntry(src, anal_unit); | |
| 32204 | ||
| 32205 | if (zcu.analysis_in_progress.contains(anal_unit)) { | |
| 32206 | return sema.failWithOwnedErrorMsg(null, try sema.errMsg(.{ | |
| 32207 | .base_node_inst = ip.getCau(cau_index).zir_index, | |
| 32208 | .offset = LazySrcLoc.Offset.nodeOffset(0), | |
| 32209 | }, "dependency loop detected", .{})); | |
| 32210 | } | |
| 32211 | ||
| 32212 | return pt.ensureCauAnalyzed(cau_index); | |
| 32189 | 32213 | } |
| 32190 | 32214 | |
| 32191 | 32215 | fn optRefValue(sema: *Sema, opt_val: ?Value) !Value { |
| ... | ... | @@ -32200,55 +32224,57 @@ fn optRefValue(sema: *Sema, opt_val: ?Value) !Value { |
| 32200 | 32224 | } })); |
| 32201 | 32225 | } |
| 32202 | 32226 | |
| 32203 | fn analyzeDeclRef(sema: *Sema, src: LazySrcLoc, decl_index: InternPool.DeclIndex) CompileError!Air.Inst.Ref { | |
| 32204 | return sema.analyzeDeclRefInner(src, decl_index, true); | |
| 32227 | fn analyzeNavRef(sema: *Sema, src: LazySrcLoc, nav_index: InternPool.Nav.Index) CompileError!Air.Inst.Ref { | |
| 32228 | return sema.analyzeNavRefInner(src, nav_index, true); | |
| 32205 | 32229 | } |
| 32206 | 32230 | |
| 32207 | /// Analyze a reference to the decl at the given index. Ensures the underlying decl is analyzed, but | |
| 32231 | /// Analyze a reference to the `Nav` at the given index. Ensures the underlying `Nav` is analyzed, but | |
| 32208 | 32232 | /// only triggers analysis for function bodies if `analyze_fn_body` is true. If it's possible for a |
| 32209 | /// decl_ref to end up in runtime code, the function body must be analyzed: `analyzeDeclRef` wraps | |
| 32233 | /// decl_ref to end up in runtime code, the function body must be analyzed: `analyzeNavRef` wraps | |
| 32210 | 32234 | /// this function with `analyze_fn_body` set to true. |
| 32211 | fn analyzeDeclRefInner(sema: *Sema, src: LazySrcLoc, decl_index: InternPool.DeclIndex, analyze_fn_body: bool) CompileError!Air.Inst.Ref { | |
| 32235 | fn analyzeNavRefInner(sema: *Sema, src: LazySrcLoc, orig_nav_index: InternPool.Nav.Index, analyze_fn_body: bool) CompileError!Air.Inst.Ref { | |
| 32212 | 32236 | const pt = sema.pt; |
| 32213 | const mod = pt.zcu; | |
| 32214 | try sema.addReferenceEntry(src, AnalUnit.wrap(.{ .decl = decl_index })); | |
| 32215 | try sema.ensureDeclAnalyzed(decl_index); | |
| 32237 | const zcu = pt.zcu; | |
| 32238 | const ip = &zcu.intern_pool; | |
| 32216 | 32239 | |
| 32217 | const decl_val = try mod.declPtr(decl_index).valueOrFail(); | |
| 32218 | const owner_decl = mod.declPtr(switch (mod.intern_pool.indexToKey(decl_val.toIntern())) { | |
| 32219 | .variable => |variable| variable.decl, | |
| 32220 | .extern_func => |extern_func| extern_func.decl, | |
| 32221 | .func => |func| func.owner_decl, | |
| 32222 | else => decl_index, | |
| 32223 | }); | |
| 32224 | // TODO: if this is a `decl_ref` of a non-variable decl, only depend on decl type | |
| 32225 | try sema.declareDependency(.{ .decl_val = decl_index }); | |
| 32240 | // TODO: if this is a `decl_ref` of a non-variable Nav, only depend on Nav type | |
| 32241 | try sema.declareDependency(.{ .nav_val = orig_nav_index }); | |
| 32242 | try sema.ensureNavResolved(src, orig_nav_index); | |
| 32243 | ||
| 32244 | const nav_val = zcu.navValue(orig_nav_index); | |
| 32245 | const nav_index, const is_const = switch (ip.indexToKey(nav_val.toIntern())) { | |
| 32246 | .variable => |v| .{ v.owner_nav, false }, | |
| 32247 | .func => |f| .{ f.owner_nav, true }, | |
| 32248 | .@"extern" => |e| .{ e.owner_nav, e.is_const }, | |
| 32249 | else => .{ orig_nav_index, true }, | |
| 32250 | }; | |
| 32251 | const nav_info = ip.getNav(nav_index).status.resolved; | |
| 32226 | 32252 | const ptr_ty = try pt.ptrTypeSema(.{ |
| 32227 | .child = decl_val.typeOf(mod).toIntern(), | |
| 32253 | .child = nav_val.typeOf(zcu).toIntern(), | |
| 32228 | 32254 | .flags = .{ |
| 32229 | .alignment = owner_decl.alignment, | |
| 32230 | .is_const = if (decl_val.getVariable(mod)) |variable| variable.is_const else true, | |
| 32231 | .address_space = owner_decl.@"addrspace", | |
| 32255 | .alignment = nav_info.alignment, | |
| 32256 | .is_const = is_const, | |
| 32257 | .address_space = nav_info.@"addrspace", | |
| 32232 | 32258 | }, |
| 32233 | 32259 | }); |
| 32234 | 32260 | if (analyze_fn_body) { |
| 32235 | try sema.maybeQueueFuncBodyAnalysis(src, decl_index); | |
| 32261 | try sema.maybeQueueFuncBodyAnalysis(src, nav_index); | |
| 32236 | 32262 | } |
| 32237 | 32263 | return Air.internedToRef((try pt.intern(.{ .ptr = .{ |
| 32238 | 32264 | .ty = ptr_ty.toIntern(), |
| 32239 | .base_addr = .{ .decl = decl_index }, | |
| 32265 | .base_addr = .{ .nav = nav_index }, | |
| 32240 | 32266 | .byte_offset = 0, |
| 32241 | 32267 | } }))); |
| 32242 | 32268 | } |
| 32243 | 32269 | |
| 32244 | fn maybeQueueFuncBodyAnalysis(sema: *Sema, src: LazySrcLoc, decl_index: InternPool.DeclIndex) !void { | |
| 32245 | const mod = sema.pt.zcu; | |
| 32246 | const decl = mod.declPtr(decl_index); | |
| 32247 | const decl_val = try decl.valueOrFail(); | |
| 32248 | if (!mod.intern_pool.isFuncBody(decl_val.toIntern())) return; | |
| 32249 | if (!try sema.fnHasRuntimeBits(decl_val.typeOf(mod))) return; | |
| 32250 | try sema.addReferenceEntry(src, AnalUnit.wrap(.{ .func = decl_val.toIntern() })); | |
| 32251 | try mod.ensureFuncBodyAnalysisQueued(decl_val.toIntern()); | |
| 32270 | fn maybeQueueFuncBodyAnalysis(sema: *Sema, src: LazySrcLoc, nav_index: InternPool.Nav.Index) !void { | |
| 32271 | const zcu = sema.pt.zcu; | |
| 32272 | const ip = &zcu.intern_pool; | |
| 32273 | const nav_val = zcu.navValue(nav_index); | |
| 32274 | if (!ip.isFuncBody(nav_val.toIntern())) return; | |
| 32275 | if (!try sema.fnHasRuntimeBits(nav_val.typeOf(zcu))) return; | |
| 32276 | try sema.addReferenceEntry(src, AnalUnit.wrap(.{ .func = nav_val.toIntern() })); | |
| 32277 | try zcu.ensureFuncBodyAnalysisQueued(nav_val.toIntern()); | |
| 32252 | 32278 | } |
| 32253 | 32279 | |
| 32254 | 32280 | fn analyzeRef( |
| ... | ... | @@ -32263,9 +32289,9 @@ fn analyzeRef( |
| 32263 | 32289 | |
| 32264 | 32290 | if (try sema.resolveValue(operand)) |val| { |
| 32265 | 32291 | switch (mod.intern_pool.indexToKey(val.toIntern())) { |
| 32266 | .extern_func => |extern_func| return sema.analyzeDeclRef(src, extern_func.decl), | |
| 32267 | .func => |func| return sema.analyzeDeclRef(src, func.owner_decl), | |
| 32268 | else => return anonDeclRef(sema, val.toIntern()), | |
| 32292 | .@"extern" => |e| return sema.analyzeNavRef(src, e.owner_nav), | |
| 32293 | .func => |f| return sema.analyzeNavRef(src, f.owner_nav), | |
| 32294 | else => return uavRef(sema, val.toIntern()), | |
| 32269 | 32295 | } |
| 32270 | 32296 | } |
| 32271 | 32297 | |
| ... | ... | @@ -35198,7 +35224,7 @@ pub fn resolveStructAlignment( |
| 35198 | 35224 | const ip = &mod.intern_pool; |
| 35199 | 35225 | const target = mod.getTarget(); |
| 35200 | 35226 | |
| 35201 | assert(sema.ownerUnit().unwrap().decl == struct_type.decl.unwrap().?); | |
| 35227 | assert(sema.owner.unwrap().cau == struct_type.cau.unwrap().?); | |
| 35202 | 35228 | |
| 35203 | 35229 | assert(struct_type.layout != .@"packed"); |
| 35204 | 35230 | assert(struct_type.flagsUnordered(ip).alignment == .none); |
| ... | ... | @@ -35242,7 +35268,7 @@ pub fn resolveStructLayout(sema: *Sema, ty: Type) SemaError!void { |
| 35242 | 35268 | const ip = &zcu.intern_pool; |
| 35243 | 35269 | const struct_type = zcu.typeToStruct(ty) orelse return; |
| 35244 | 35270 | |
| 35245 | assert(sema.ownerUnit().unwrap().decl == struct_type.decl.unwrap().?); | |
| 35271 | assert(sema.owner.unwrap().cau == struct_type.cau.unwrap().?); | |
| 35246 | 35272 | |
| 35247 | 35273 | if (struct_type.haveLayout(ip)) |
| 35248 | 35274 | return; |
| ... | ... | @@ -35384,8 +35410,7 @@ fn semaBackingIntType(pt: Zcu.PerThread, struct_type: InternPool.LoadedStructTyp |
| 35384 | 35410 | const gpa = zcu.gpa; |
| 35385 | 35411 | const ip = &zcu.intern_pool; |
| 35386 | 35412 | |
| 35387 | const decl_index = struct_type.decl.unwrap().?; | |
| 35388 | const decl = zcu.declPtr(decl_index); | |
| 35413 | const cau_index = struct_type.cau.unwrap().?; | |
| 35389 | 35414 | |
| 35390 | 35415 | const zir = zcu.namespacePtr(struct_type.namespace.unwrap().?).fileScope(zcu).zir; |
| 35391 | 35416 | |
| ... | ... | @@ -35400,13 +35425,11 @@ fn semaBackingIntType(pt: Zcu.PerThread, struct_type: InternPool.LoadedStructTyp |
| 35400 | 35425 | .gpa = gpa, |
| 35401 | 35426 | .arena = analysis_arena.allocator(), |
| 35402 | 35427 | .code = zir, |
| 35403 | .owner_decl = decl, | |
| 35404 | .owner_decl_index = decl_index, | |
| 35428 | .owner = AnalUnit.wrap(.{ .cau = cau_index }), | |
| 35405 | 35429 | .func_index = .none, |
| 35406 | 35430 | .func_is_naked = false, |
| 35407 | 35431 | .fn_ret_ty = Type.void, |
| 35408 | 35432 | .fn_ret_ty_ies = null, |
| 35409 | .owner_func_index = .none, | |
| 35410 | 35433 | .comptime_err_ret_trace = &comptime_err_ret_trace, |
| 35411 | 35434 | }; |
| 35412 | 35435 | defer sema.deinit(); |
| ... | ... | @@ -35414,12 +35437,12 @@ fn semaBackingIntType(pt: Zcu.PerThread, struct_type: InternPool.LoadedStructTyp |
| 35414 | 35437 | var block: Block = .{ |
| 35415 | 35438 | .parent = null, |
| 35416 | 35439 | .sema = &sema, |
| 35417 | .namespace = struct_type.namespace.unwrap() orelse decl.src_namespace, | |
| 35440 | .namespace = ip.getCau(cau_index).namespace, | |
| 35418 | 35441 | .instructions = .{}, |
| 35419 | 35442 | .inlining = null, |
| 35420 | 35443 | .is_comptime = true, |
| 35421 | 35444 | .src_base_inst = struct_type.zir_index.unwrap().?, |
| 35422 | .type_name_ctx = decl.name, | |
| 35445 | .type_name_ctx = struct_type.name, | |
| 35423 | 35446 | }; |
| 35424 | 35447 | defer assert(block.instructions.items.len == 0); |
| 35425 | 35448 | |
| ... | ... | @@ -35544,7 +35567,7 @@ pub fn resolveUnionAlignment( |
| 35544 | 35567 | const ip = &zcu.intern_pool; |
| 35545 | 35568 | const target = zcu.getTarget(); |
| 35546 | 35569 | |
| 35547 | assert(sema.ownerUnit().unwrap().decl == union_type.decl); | |
| 35570 | assert(sema.owner.unwrap().cau == union_type.cau); | |
| 35548 | 35571 | |
| 35549 | 35572 | assert(!union_type.haveLayout(ip)); |
| 35550 | 35573 | |
| ... | ... | @@ -35584,7 +35607,7 @@ pub fn resolveUnionLayout(sema: *Sema, ty: Type) SemaError!void { |
| 35584 | 35607 | // Load again, since the tag type might have changed due to resolution. |
| 35585 | 35608 | const union_type = ip.loadUnionType(ty.ip_index); |
| 35586 | 35609 | |
| 35587 | assert(sema.ownerUnit().unwrap().decl == union_type.decl); | |
| 35610 | assert(sema.owner.unwrap().cau == union_type.cau); | |
| 35588 | 35611 | |
| 35589 | 35612 | const old_flags = union_type.flagsUnordered(ip); |
| 35590 | 35613 | switch (old_flags.status) { |
| ... | ... | @@ -35697,7 +35720,7 @@ pub fn resolveStructFully(sema: *Sema, ty: Type) SemaError!void { |
| 35697 | 35720 | const ip = &mod.intern_pool; |
| 35698 | 35721 | const struct_type = mod.typeToStruct(ty).?; |
| 35699 | 35722 | |
| 35700 | assert(sema.ownerUnit().unwrap().decl == struct_type.decl.unwrap().?); | |
| 35723 | assert(sema.owner.unwrap().cau == struct_type.cau.unwrap().?); | |
| 35701 | 35724 | |
| 35702 | 35725 | if (struct_type.setFullyResolved(ip)) return; |
| 35703 | 35726 | errdefer struct_type.clearFullyResolved(ip); |
| ... | ... | @@ -35720,7 +35743,7 @@ pub fn resolveUnionFully(sema: *Sema, ty: Type) SemaError!void { |
| 35720 | 35743 | const ip = &mod.intern_pool; |
| 35721 | 35744 | const union_obj = mod.typeToUnion(ty).?; |
| 35722 | 35745 | |
| 35723 | assert(sema.ownerUnit().unwrap().decl == union_obj.decl); | |
| 35746 | assert(sema.owner.unwrap().cau == union_obj.cau); | |
| 35724 | 35747 | |
| 35725 | 35748 | switch (union_obj.flagsUnordered(ip).status) { |
| 35726 | 35749 | .none, .have_field_types, .field_types_wip, .layout_wip, .have_layout => {}, |
| ... | ... | @@ -35754,21 +35777,8 @@ pub fn resolveTypeFieldsStruct( |
| 35754 | 35777 | const pt = sema.pt; |
| 35755 | 35778 | const zcu = pt.zcu; |
| 35756 | 35779 | const ip = &zcu.intern_pool; |
| 35757 | // If there is no owner decl it means the struct has no fields. | |
| 35758 | const owner_decl = struct_type.decl.unwrap() orelse return; | |
| 35759 | 35780 | |
| 35760 | assert(sema.ownerUnit().unwrap().decl == owner_decl); | |
| 35761 | ||
| 35762 | switch (zcu.declPtr(owner_decl).analysis) { | |
| 35763 | .file_failure, | |
| 35764 | .dependency_failure, | |
| 35765 | .sema_failure, | |
| 35766 | => { | |
| 35767 | sema.owner_decl.analysis = .dependency_failure; | |
| 35768 | return error.AnalysisFail; | |
| 35769 | }, | |
| 35770 | else => {}, | |
| 35771 | } | |
| 35781 | assert(sema.owner.unwrap().cau == struct_type.cau.unwrap().?); | |
| 35772 | 35782 | |
| 35773 | 35783 | if (struct_type.haveFieldTypes(ip)) return; |
| 35774 | 35784 | |
| ... | ... | @@ -35783,13 +35793,7 @@ pub fn resolveTypeFieldsStruct( |
| 35783 | 35793 | defer struct_type.clearFieldTypesWip(ip); |
| 35784 | 35794 | |
| 35785 | 35795 | semaStructFields(pt, sema.arena, struct_type) catch |err| switch (err) { |
| 35786 | error.AnalysisFail => { | |
| 35787 | if (zcu.declPtr(owner_decl).analysis == .complete) { | |
| 35788 | zcu.declPtr(owner_decl).analysis = .dependency_failure; | |
| 35789 | } | |
| 35790 | return error.AnalysisFail; | |
| 35791 | }, | |
| 35792 | error.OutOfMemory => return error.OutOfMemory, | |
| 35796 | error.AnalysisFail, error.OutOfMemory => |e| return e, | |
| 35793 | 35797 | error.ComptimeBreak, error.ComptimeReturn, error.GenericPoison => unreachable, |
| 35794 | 35798 | }; |
| 35795 | 35799 | } |
| ... | ... | @@ -35799,9 +35803,8 @@ pub fn resolveStructFieldInits(sema: *Sema, ty: Type) SemaError!void { |
| 35799 | 35803 | const zcu = pt.zcu; |
| 35800 | 35804 | const ip = &zcu.intern_pool; |
| 35801 | 35805 | const struct_type = zcu.typeToStruct(ty) orelse return; |
| 35802 | const owner_decl = struct_type.decl.unwrap() orelse return; | |
| 35803 | 35806 | |
| 35804 | assert(sema.ownerUnit().unwrap().decl == owner_decl); | |
| 35807 | assert(sema.owner.unwrap().cau == struct_type.cau.unwrap().?); | |
| 35805 | 35808 | |
| 35806 | 35809 | // Inits can start as resolved |
| 35807 | 35810 | if (struct_type.haveFieldInits(ip)) return; |
| ... | ... | @@ -35819,13 +35822,7 @@ pub fn resolveStructFieldInits(sema: *Sema, ty: Type) SemaError!void { |
| 35819 | 35822 | defer struct_type.clearInitsWip(ip); |
| 35820 | 35823 | |
| 35821 | 35824 | semaStructFieldInits(pt, sema.arena, struct_type) catch |err| switch (err) { |
| 35822 | error.AnalysisFail => { | |
| 35823 | if (zcu.declPtr(owner_decl).analysis == .complete) { | |
| 35824 | zcu.declPtr(owner_decl).analysis = .dependency_failure; | |
| 35825 | } | |
| 35826 | return error.AnalysisFail; | |
| 35827 | }, | |
| 35828 | error.OutOfMemory => return error.OutOfMemory, | |
| 35825 | error.AnalysisFail, error.OutOfMemory => |e| return e, | |
| 35829 | 35826 | error.ComptimeBreak, error.ComptimeReturn, error.GenericPoison => unreachable, |
| 35830 | 35827 | }; |
| 35831 | 35828 | struct_type.setHaveFieldInits(ip); |
| ... | ... | @@ -35835,20 +35832,9 @@ pub fn resolveTypeFieldsUnion(sema: *Sema, ty: Type, union_type: InternPool.Load |
| 35835 | 35832 | const pt = sema.pt; |
| 35836 | 35833 | const zcu = pt.zcu; |
| 35837 | 35834 | const ip = &zcu.intern_pool; |
| 35838 | const owner_decl = zcu.declPtr(union_type.decl); | |
| 35839 | 35835 | |
| 35840 | assert(sema.ownerUnit().unwrap().decl == union_type.decl); | |
| 35836 | assert(sema.owner.unwrap().cau == union_type.cau); | |
| 35841 | 35837 | |
| 35842 | switch (owner_decl.analysis) { | |
| 35843 | .file_failure, | |
| 35844 | .dependency_failure, | |
| 35845 | .sema_failure, | |
| 35846 | => { | |
| 35847 | sema.owner_decl.analysis = .dependency_failure; | |
| 35848 | return error.AnalysisFail; | |
| 35849 | }, | |
| 35850 | else => {}, | |
| 35851 | } | |
| 35852 | 35838 | switch (union_type.flagsUnordered(ip).status) { |
| 35853 | 35839 | .none => {}, |
| 35854 | 35840 | .field_types_wip => { |
| ... | ... | @@ -35869,14 +35855,8 @@ pub fn resolveTypeFieldsUnion(sema: *Sema, ty: Type, union_type: InternPool.Load |
| 35869 | 35855 | |
| 35870 | 35856 | union_type.setStatus(ip, .field_types_wip); |
| 35871 | 35857 | errdefer union_type.setStatus(ip, .none); |
| 35872 | semaUnionFields(pt, sema.arena, union_type) catch |err| switch (err) { | |
| 35873 | error.AnalysisFail => { | |
| 35874 | if (owner_decl.analysis == .complete) { | |
| 35875 | owner_decl.analysis = .dependency_failure; | |
| 35876 | } | |
| 35877 | return error.AnalysisFail; | |
| 35878 | }, | |
| 35879 | error.OutOfMemory => return error.OutOfMemory, | |
| 35858 | semaUnionFields(pt, sema.arena, ty.toIntern(), union_type) catch |err| switch (err) { | |
| 35859 | error.AnalysisFail, error.OutOfMemory => |e| return e, | |
| 35880 | 35860 | error.ComptimeBreak, error.ComptimeReturn, error.GenericPoison => unreachable, |
| 35881 | 35861 | }; |
| 35882 | 35862 | union_type.setStatus(ip, .have_field_types); |
| ... | ... | @@ -35891,28 +35871,28 @@ fn resolveInferredErrorSet( |
| 35891 | 35871 | ies_index: InternPool.Index, |
| 35892 | 35872 | ) CompileError!InternPool.Index { |
| 35893 | 35873 | const pt = sema.pt; |
| 35894 | const mod = pt.zcu; | |
| 35895 | const ip = &mod.intern_pool; | |
| 35874 | const zcu = pt.zcu; | |
| 35875 | const ip = &zcu.intern_pool; | |
| 35896 | 35876 | const func_index = ip.iesFuncIndex(ies_index); |
| 35897 | const func = mod.funcInfo(func_index); | |
| 35877 | const func = zcu.funcInfo(func_index); | |
| 35898 | 35878 | |
| 35899 | try sema.declareDependency(.{ .func_ies = func_index }); | |
| 35879 | try sema.declareDependency(.{ .interned = func_index }); // resolved IES | |
| 35900 | 35880 | |
| 35901 | 35881 | // TODO: during an incremental update this might not be `.none`, but the |
| 35902 | 35882 | // function might be out-of-date! |
| 35903 | 35883 | const resolved_ty = func.resolvedErrorSetUnordered(ip); |
| 35904 | 35884 | if (resolved_ty != .none) return resolved_ty; |
| 35905 | 35885 | |
| 35906 | if (func.analysisUnordered(ip).state == .in_progress) | |
| 35886 | if (zcu.analysis_in_progress.contains(AnalUnit.wrap(.{ .func = func_index }))) { | |
| 35907 | 35887 | return sema.fail(block, src, "unable to resolve inferred error set", .{}); |
| 35888 | } | |
| 35908 | 35889 | |
| 35909 | 35890 | // In order to ensure that all dependencies are properly added to the set, |
| 35910 | 35891 | // we need to ensure the function body is analyzed of the inferred error |
| 35911 | 35892 | // set. However, in the case of comptime/inline function calls with |
| 35912 | 35893 | // inferred error sets, each call gets an adhoc InferredErrorSet object, which |
| 35913 | 35894 | // has no corresponding function body. |
| 35914 | const ies_func_owner_decl = mod.declPtr(func.owner_decl); | |
| 35915 | const ies_func_info = mod.typeToFunc(ies_func_owner_decl.typeOf(mod)).?; | |
| 35895 | const ies_func_info = zcu.typeToFunc(Type.fromInterned(func.ty)).?; | |
| 35916 | 35896 | // if ies declared by a inline function with generic return type, the return_type should be generic_poison, |
| 35917 | 35897 | // because inline function does not create a new declaration, and the ies has been filled with analyzeCall, |
| 35918 | 35898 | // so here we can simply skip this case. |
| ... | ... | @@ -35920,22 +35900,17 @@ fn resolveInferredErrorSet( |
| 35920 | 35900 | assert(ies_func_info.cc == .Inline); |
| 35921 | 35901 | } else if (ip.errorUnionSet(ies_func_info.return_type) == ies_index) { |
| 35922 | 35902 | if (ies_func_info.is_generic) { |
| 35923 | const msg = msg: { | |
| 35903 | return sema.failWithOwnedErrorMsg(block, msg: { | |
| 35924 | 35904 | const msg = try sema.errMsg(src, "unable to resolve inferred error set of generic function", .{}); |
| 35925 | 35905 | errdefer msg.destroy(sema.gpa); |
| 35926 | ||
| 35927 | try sema.errNote(.{ | |
| 35928 | .base_node_inst = ies_func_owner_decl.zir_decl_index.unwrap().?, | |
| 35929 | .offset = LazySrcLoc.Offset.nodeOffset(0), | |
| 35930 | }, msg, "generic function declared here", .{}); | |
| 35906 | try sema.errNote(zcu.navSrcLoc(func.owner_nav), msg, "generic function declared here", .{}); | |
| 35931 | 35907 | break :msg msg; |
| 35932 | }; | |
| 35933 | return sema.failWithOwnedErrorMsg(block, msg); | |
| 35908 | }); | |
| 35934 | 35909 | } |
| 35935 | 35910 | // In this case we are dealing with the actual InferredErrorSet object that |
| 35936 | 35911 | // corresponds to the function, not one created to track an inline/comptime call. |
| 35937 | 35912 | try sema.addReferenceEntry(src, AnalUnit.wrap(.{ .func = func_index })); |
| 35938 | try sema.ensureFuncBodyAnalyzed(func_index); | |
| 35913 | try pt.ensureFuncBodyAnalyzed(func_index); | |
| 35939 | 35914 | } |
| 35940 | 35915 | |
| 35941 | 35916 | // This will now have been resolved by the logic at the end of `Module.analyzeFnBody` |
| ... | ... | @@ -36092,9 +36067,8 @@ fn semaStructFields( |
| 36092 | 36067 | const zcu = pt.zcu; |
| 36093 | 36068 | const gpa = zcu.gpa; |
| 36094 | 36069 | const ip = &zcu.intern_pool; |
| 36095 | const decl_index = struct_type.decl.unwrap() orelse return; | |
| 36096 | const decl = zcu.declPtr(decl_index); | |
| 36097 | const namespace_index = struct_type.namespace.unwrap() orelse decl.src_namespace; | |
| 36070 | const cau_index = struct_type.cau.unwrap().?; | |
| 36071 | const namespace_index = ip.getCau(cau_index).namespace; | |
| 36098 | 36072 | const zir = zcu.namespacePtr(namespace_index).fileScope(zcu).zir; |
| 36099 | 36073 | const zir_index = struct_type.zir_index.unwrap().?.resolve(ip); |
| 36100 | 36074 | |
| ... | ... | @@ -36119,13 +36093,11 @@ fn semaStructFields( |
| 36119 | 36093 | .gpa = gpa, |
| 36120 | 36094 | .arena = arena, |
| 36121 | 36095 | .code = zir, |
| 36122 | .owner_decl = decl, | |
| 36123 | .owner_decl_index = decl_index, | |
| 36096 | .owner = AnalUnit.wrap(.{ .cau = cau_index }), | |
| 36124 | 36097 | .func_index = .none, |
| 36125 | 36098 | .func_is_naked = false, |
| 36126 | 36099 | .fn_ret_ty = Type.void, |
| 36127 | 36100 | .fn_ret_ty_ies = null, |
| 36128 | .owner_func_index = .none, | |
| 36129 | 36101 | .comptime_err_ret_trace = &comptime_err_ret_trace, |
| 36130 | 36102 | }; |
| 36131 | 36103 | defer sema.deinit(); |
| ... | ... | @@ -36138,7 +36110,7 @@ fn semaStructFields( |
| 36138 | 36110 | .inlining = null, |
| 36139 | 36111 | .is_comptime = true, |
| 36140 | 36112 | .src_base_inst = struct_type.zir_index.unwrap().?, |
| 36141 | .type_name_ctx = decl.name, | |
| 36113 | .type_name_ctx = struct_type.name, | |
| 36142 | 36114 | }; |
| 36143 | 36115 | defer assert(block_scope.instructions.items.len == 0); |
| 36144 | 36116 | |
| ... | ... | @@ -36318,9 +36290,8 @@ fn semaStructFieldInits( |
| 36318 | 36290 | |
| 36319 | 36291 | assert(!struct_type.haveFieldInits(ip)); |
| 36320 | 36292 | |
| 36321 | const decl_index = struct_type.decl.unwrap() orelse return; | |
| 36322 | const decl = zcu.declPtr(decl_index); | |
| 36323 | const namespace_index = struct_type.namespace.unwrap() orelse decl.src_namespace; | |
| 36293 | const cau_index = struct_type.cau.unwrap().?; | |
| 36294 | const namespace_index = ip.getCau(cau_index).namespace; | |
| 36324 | 36295 | const zir = zcu.namespacePtr(namespace_index).fileScope(zcu).zir; |
| 36325 | 36296 | const zir_index = struct_type.zir_index.unwrap().?.resolve(ip); |
| 36326 | 36297 | const fields_len, const small, var extra_index = structZirInfo(zir, zir_index); |
| ... | ... | @@ -36333,13 +36304,11 @@ fn semaStructFieldInits( |
| 36333 | 36304 | .gpa = gpa, |
| 36334 | 36305 | .arena = arena, |
| 36335 | 36306 | .code = zir, |
| 36336 | .owner_decl = decl, | |
| 36337 | .owner_decl_index = decl_index, | |
| 36307 | .owner = AnalUnit.wrap(.{ .cau = cau_index }), | |
| 36338 | 36308 | .func_index = .none, |
| 36339 | 36309 | .func_is_naked = false, |
| 36340 | 36310 | .fn_ret_ty = Type.void, |
| 36341 | 36311 | .fn_ret_ty_ies = null, |
| 36342 | .owner_func_index = .none, | |
| 36343 | 36312 | .comptime_err_ret_trace = &comptime_err_ret_trace, |
| 36344 | 36313 | }; |
| 36345 | 36314 | defer sema.deinit(); |
| ... | ... | @@ -36352,7 +36321,7 @@ fn semaStructFieldInits( |
| 36352 | 36321 | .inlining = null, |
| 36353 | 36322 | .is_comptime = true, |
| 36354 | 36323 | .src_base_inst = struct_type.zir_index.unwrap().?, |
| 36355 | .type_name_ctx = decl.name, | |
| 36324 | .type_name_ctx = struct_type.name, | |
| 36356 | 36325 | }; |
| 36357 | 36326 | defer assert(block_scope.instructions.items.len == 0); |
| 36358 | 36327 | |
| ... | ... | @@ -36449,15 +36418,15 @@ fn semaStructFieldInits( |
| 36449 | 36418 | try sema.flushExports(); |
| 36450 | 36419 | } |
| 36451 | 36420 | |
| 36452 | fn semaUnionFields(pt: Zcu.PerThread, arena: Allocator, union_type: InternPool.LoadedUnionType) CompileError!void { | |
| 36421 | fn semaUnionFields(pt: Zcu.PerThread, arena: Allocator, union_ty: InternPool.Index, union_type: InternPool.LoadedUnionType) CompileError!void { | |
| 36453 | 36422 | const tracy = trace(@src()); |
| 36454 | 36423 | defer tracy.end(); |
| 36455 | 36424 | |
| 36456 | 36425 | const zcu = pt.zcu; |
| 36457 | 36426 | const gpa = zcu.gpa; |
| 36458 | 36427 | const ip = &zcu.intern_pool; |
| 36459 | const decl_index = union_type.decl; | |
| 36460 | const zir = zcu.namespacePtr(union_type.namespace.unwrap().?).fileScope(zcu).zir; | |
| 36428 | const cau_index = union_type.cau; | |
| 36429 | const zir = zcu.namespacePtr(union_type.namespace).fileScope(zcu).zir; | |
| 36461 | 36430 | const zir_index = union_type.zir_index.resolve(ip); |
| 36462 | 36431 | const extended = zir.instructions.items(.data)[@intFromEnum(zir_index)].extended; |
| 36463 | 36432 | assert(extended.opcode == .union_decl); |
| ... | ... | @@ -36501,8 +36470,6 @@ fn semaUnionFields(pt: Zcu.PerThread, arena: Allocator, union_type: InternPool.L |
| 36501 | 36470 | const body = zir.bodySlice(extra_index, body_len); |
| 36502 | 36471 | extra_index += body.len; |
| 36503 | 36472 | |
| 36504 | const decl = zcu.declPtr(decl_index); | |
| 36505 | ||
| 36506 | 36473 | var comptime_err_ret_trace = std.ArrayList(LazySrcLoc).init(gpa); |
| 36507 | 36474 | defer comptime_err_ret_trace.deinit(); |
| 36508 | 36475 | |
| ... | ... | @@ -36511,13 +36478,11 @@ fn semaUnionFields(pt: Zcu.PerThread, arena: Allocator, union_type: InternPool.L |
| 36511 | 36478 | .gpa = gpa, |
| 36512 | 36479 | .arena = arena, |
| 36513 | 36480 | .code = zir, |
| 36514 | .owner_decl = decl, | |
| 36515 | .owner_decl_index = decl_index, | |
| 36481 | .owner = AnalUnit.wrap(.{ .cau = cau_index }), | |
| 36516 | 36482 | .func_index = .none, |
| 36517 | 36483 | .func_is_naked = false, |
| 36518 | 36484 | .fn_ret_ty = Type.void, |
| 36519 | 36485 | .fn_ret_ty_ies = null, |
| 36520 | .owner_func_index = .none, | |
| 36521 | 36486 | .comptime_err_ret_trace = &comptime_err_ret_trace, |
| 36522 | 36487 | }; |
| 36523 | 36488 | defer sema.deinit(); |
| ... | ... | @@ -36525,12 +36490,12 @@ fn semaUnionFields(pt: Zcu.PerThread, arena: Allocator, union_type: InternPool.L |
| 36525 | 36490 | var block_scope: Block = .{ |
| 36526 | 36491 | .parent = null, |
| 36527 | 36492 | .sema = &sema, |
| 36528 | .namespace = union_type.namespace.unwrap().?, | |
| 36493 | .namespace = union_type.namespace, | |
| 36529 | 36494 | .instructions = .{}, |
| 36530 | 36495 | .inlining = null, |
| 36531 | 36496 | .is_comptime = true, |
| 36532 | 36497 | .src_base_inst = union_type.zir_index, |
| 36533 | .type_name_ctx = decl.name, | |
| 36498 | .type_name_ctx = union_type.name, | |
| 36534 | 36499 | }; |
| 36535 | 36500 | defer assert(block_scope.instructions.items.len == 0); |
| 36536 | 36501 | |
| ... | ... | @@ -36817,10 +36782,10 @@ fn semaUnionFields(pt: Zcu.PerThread, arena: Allocator, union_type: InternPool.L |
| 36817 | 36782 | return sema.failWithOwnedErrorMsg(&block_scope, msg); |
| 36818 | 36783 | } |
| 36819 | 36784 | } else if (enum_field_vals.count() > 0) { |
| 36820 | const enum_ty = try sema.generateUnionTagTypeNumbered(&block_scope, enum_field_names, enum_field_vals.keys(), zcu.declPtr(union_type.decl)); | |
| 36785 | const enum_ty = try sema.generateUnionTagTypeNumbered(&block_scope, enum_field_names, enum_field_vals.keys(), union_ty, union_type.name); | |
| 36821 | 36786 | union_type.setTagType(ip, enum_ty); |
| 36822 | 36787 | } else { |
| 36823 | const enum_ty = try sema.generateUnionTagTypeSimple(&block_scope, enum_field_names, zcu.declPtr(union_type.decl)); | |
| 36788 | const enum_ty = try sema.generateUnionTagTypeSimple(&block_scope, enum_field_names, union_ty, union_type.name); | |
| 36824 | 36789 | union_type.setTagType(ip, enum_ty); |
| 36825 | 36790 | } |
| 36826 | 36791 | |
| ... | ... | @@ -36839,36 +36804,25 @@ fn generateUnionTagTypeNumbered( |
| 36839 | 36804 | block: *Block, |
| 36840 | 36805 | enum_field_names: []const InternPool.NullTerminatedString, |
| 36841 | 36806 | enum_field_vals: []const InternPool.Index, |
| 36842 | union_owner_decl: *Module.Decl, | |
| 36807 | union_type: InternPool.Index, | |
| 36808 | union_name: InternPool.NullTerminatedString, | |
| 36843 | 36809 | ) !InternPool.Index { |
| 36844 | 36810 | const pt = sema.pt; |
| 36845 | 36811 | const mod = pt.zcu; |
| 36846 | 36812 | const gpa = sema.gpa; |
| 36847 | 36813 | const ip = &mod.intern_pool; |
| 36848 | 36814 | |
| 36849 | const new_decl_index = try pt.allocateNewDecl(block.namespace); | |
| 36850 | errdefer pt.destroyDecl(new_decl_index); | |
| 36851 | 36815 | const name = try ip.getOrPutStringFmt( |
| 36852 | 36816 | gpa, |
| 36853 | 36817 | pt.tid, |
| 36854 | 36818 | "@typeInfo({}).Union.tag_type.?", |
| 36855 | .{union_owner_decl.fqn.fmt(ip)}, | |
| 36819 | .{union_name.fmt(ip)}, | |
| 36856 | 36820 | .no_embedded_nulls, |
| 36857 | 36821 | ); |
| 36858 | try pt.initNewAnonDecl( | |
| 36859 | new_decl_index, | |
| 36860 | Value.@"unreachable", | |
| 36861 | name, | |
| 36862 | name.toOptional(), | |
| 36863 | ); | |
| 36864 | errdefer pt.abortAnonDecl(new_decl_index); | |
| 36865 | ||
| 36866 | const new_decl = mod.declPtr(new_decl_index); | |
| 36867 | new_decl.owns_tv = true; | |
| 36868 | 36822 | |
| 36869 | 36823 | const enum_ty = try ip.getGeneratedTagEnumType(gpa, pt.tid, .{ |
| 36870 | .decl = new_decl_index, | |
| 36871 | .owner_union_ty = union_owner_decl.val.toIntern(), | |
| 36824 | .name = name, | |
| 36825 | .owner_union_ty = union_type, | |
| 36872 | 36826 | .tag_ty = if (enum_field_vals.len == 0) |
| 36873 | 36827 | (try pt.intType(.unsigned, 0)).toIntern() |
| 36874 | 36828 | else |
| ... | ... | @@ -36876,11 +36830,9 @@ fn generateUnionTagTypeNumbered( |
| 36876 | 36830 | .names = enum_field_names, |
| 36877 | 36831 | .values = enum_field_vals, |
| 36878 | 36832 | .tag_mode = .explicit, |
| 36833 | .parent_namespace = block.namespace, | |
| 36879 | 36834 | }); |
| 36880 | 36835 | |
| 36881 | new_decl.val = Value.fromInterned(enum_ty); | |
| 36882 | ||
| 36883 | try pt.finalizeAnonDecl(new_decl_index); | |
| 36884 | 36836 | return enum_ty; |
| 36885 | 36837 | } |
| 36886 | 36838 | |
| ... | ... | @@ -36888,36 +36840,25 @@ fn generateUnionTagTypeSimple( |
| 36888 | 36840 | sema: *Sema, |
| 36889 | 36841 | block: *Block, |
| 36890 | 36842 | enum_field_names: []const InternPool.NullTerminatedString, |
| 36891 | union_owner_decl: *Module.Decl, | |
| 36843 | union_type: InternPool.Index, | |
| 36844 | union_name: InternPool.NullTerminatedString, | |
| 36892 | 36845 | ) !InternPool.Index { |
| 36893 | 36846 | const pt = sema.pt; |
| 36894 | 36847 | const mod = pt.zcu; |
| 36895 | 36848 | const ip = &mod.intern_pool; |
| 36896 | 36849 | const gpa = sema.gpa; |
| 36897 | 36850 | |
| 36898 | const new_decl_index = new_decl_index: { | |
| 36899 | const new_decl_index = try pt.allocateNewDecl(block.namespace); | |
| 36900 | errdefer pt.destroyDecl(new_decl_index); | |
| 36901 | const name = try ip.getOrPutStringFmt( | |
| 36902 | gpa, | |
| 36903 | pt.tid, | |
| 36904 | "@typeInfo({}).Union.tag_type.?", | |
| 36905 | .{union_owner_decl.fqn.fmt(ip)}, | |
| 36906 | .no_embedded_nulls, | |
| 36907 | ); | |
| 36908 | try pt.initNewAnonDecl( | |
| 36909 | new_decl_index, | |
| 36910 | Value.@"unreachable", | |
| 36911 | name, | |
| 36912 | name.toOptional(), | |
| 36913 | ); | |
| 36914 | break :new_decl_index new_decl_index; | |
| 36915 | }; | |
| 36916 | errdefer pt.abortAnonDecl(new_decl_index); | |
| 36851 | const name = try ip.getOrPutStringFmt( | |
| 36852 | gpa, | |
| 36853 | pt.tid, | |
| 36854 | "@typeInfo({}).Union.tag_type.?", | |
| 36855 | .{union_name.fmt(ip)}, | |
| 36856 | .no_embedded_nulls, | |
| 36857 | ); | |
| 36917 | 36858 | |
| 36918 | 36859 | const enum_ty = try ip.getGeneratedTagEnumType(gpa, pt.tid, .{ |
| 36919 | .decl = new_decl_index, | |
| 36920 | .owner_union_ty = union_owner_decl.val.toIntern(), | |
| 36860 | .name = name, | |
| 36861 | .owner_union_ty = union_type, | |
| 36921 | 36862 | .tag_ty = if (enum_field_names.len == 0) |
| 36922 | 36863 | (try pt.intType(.unsigned, 0)).toIntern() |
| 36923 | 36864 | else |
| ... | ... | @@ -36925,13 +36866,9 @@ fn generateUnionTagTypeSimple( |
| 36925 | 36866 | .names = enum_field_names, |
| 36926 | 36867 | .values = &.{}, |
| 36927 | 36868 | .tag_mode = .auto, |
| 36869 | .parent_namespace = block.namespace, | |
| 36928 | 36870 | }); |
| 36929 | 36871 | |
| 36930 | const new_decl = mod.declPtr(new_decl_index); | |
| 36931 | new_decl.owns_tv = true; | |
| 36932 | new_decl.val = Value.fromInterned(enum_ty); | |
| 36933 | ||
| 36934 | try pt.finalizeAnonDecl(new_decl_index); | |
| 36935 | 36872 | return enum_ty; |
| 36936 | 36873 | } |
| 36937 | 36874 | |
| ... | ... | @@ -37057,9 +36994,9 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value { |
| 37057 | 36994 | // values, not types |
| 37058 | 36995 | .undef, |
| 37059 | 36996 | .simple_value, |
| 37060 | .ptr_decl, | |
| 37061 | .ptr_anon_decl, | |
| 37062 | .ptr_anon_decl_aligned, | |
| 36997 | .ptr_nav, | |
| 36998 | .ptr_uav, | |
| 36999 | .ptr_uav_aligned, | |
| 37063 | 37000 | .ptr_comptime_alloc, |
| 37064 | 37001 | .ptr_comptime_field, |
| 37065 | 37002 | .ptr_int, |
| ... | ... | @@ -37096,7 +37033,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value { |
| 37096 | 37033 | .float_c_longdouble_f128, |
| 37097 | 37034 | .float_comptime_float, |
| 37098 | 37035 | .variable, |
| 37099 | .extern_func, | |
| 37036 | .@"extern", | |
| 37100 | 37037 | .func_decl, |
| 37101 | 37038 | .func_instance, |
| 37102 | 37039 | .func_coerced, |
| ... | ... | @@ -37965,7 +37902,7 @@ fn intFitsInType( |
| 37965 | 37902 | .zero_usize, .zero_u8 => return true, |
| 37966 | 37903 | else => switch (mod.intern_pool.indexToKey(val.toIntern())) { |
| 37967 | 37904 | .undef => return true, |
| 37968 | .variable, .extern_func, .func, .ptr => { | |
| 37905 | .variable, .@"extern", .func, .ptr => { | |
| 37969 | 37906 | const target = mod.getTarget(); |
| 37970 | 37907 | const ptr_bits = target.ptrBitWidth(); |
| 37971 | 37908 | return switch (info.signedness) { |
| ... | ... | @@ -38240,24 +38177,24 @@ pub fn declareDependency(sema: *Sema, dependee: InternPool.Dependee) !void { |
| 38240 | 38177 | // of a type and they use `@This()`. This dependency would be unnecessary, and in fact would |
| 38241 | 38178 | // just result in over-analysis since `Zcu.findOutdatedToAnalyze` would never be able to resolve |
| 38242 | 38179 | // the loop. |
| 38243 | if (sema.owner_func_index == .none and dependee == .decl_val and dependee.decl_val == sema.owner_decl_index) { | |
| 38244 | return; | |
| 38180 | switch (sema.owner.unwrap()) { | |
| 38181 | .cau => |cau| switch (dependee) { | |
| 38182 | .nav_val => |nav| if (zcu.intern_pool.getNav(nav).analysis_owner == cau.toOptional()) { | |
| 38183 | return; | |
| 38184 | }, | |
| 38185 | else => {}, | |
| 38186 | }, | |
| 38187 | .func => {}, | |
| 38245 | 38188 | } |
| 38246 | 38189 | |
| 38247 | const depender = AnalUnit.wrap( | |
| 38248 | if (sema.owner_func_index != .none) | |
| 38249 | .{ .func = sema.owner_func_index } | |
| 38250 | else | |
| 38251 | .{ .decl = sema.owner_decl_index }, | |
| 38252 | ); | |
| 38253 | try zcu.intern_pool.addDependency(sema.gpa, depender, dependee); | |
| 38190 | try zcu.intern_pool.addDependency(sema.gpa, sema.owner, dependee); | |
| 38254 | 38191 | } |
| 38255 | 38192 | |
| 38256 | 38193 | fn isComptimeMutablePtr(sema: *Sema, val: Value) bool { |
| 38257 | 38194 | return switch (sema.pt.zcu.intern_pool.indexToKey(val.toIntern())) { |
| 38258 | 38195 | .slice => |slice| sema.isComptimeMutablePtr(Value.fromInterned(slice.ptr)), |
| 38259 | 38196 | .ptr => |ptr| switch (ptr.base_addr) { |
| 38260 | .anon_decl, .decl, .int => false, | |
| 38197 | .uav, .nav, .int => false, | |
| 38261 | 38198 | .comptime_field => true, |
| 38262 | 38199 | .comptime_alloc => |alloc_index| !sema.getComptimeAlloc(alloc_index).is_const, |
| 38263 | 38200 | .eu_payload, .opt_payload => |base| sema.isComptimeMutablePtr(Value.fromInterned(base)), |
| ... | ... | @@ -38388,19 +38325,17 @@ pub fn flushExports(sema: *Sema) !void { |
| 38388 | 38325 | const zcu = sema.pt.zcu; |
| 38389 | 38326 | const gpa = zcu.gpa; |
| 38390 | 38327 | |
| 38391 | const unit = sema.ownerUnit(); | |
| 38392 | ||
| 38393 | 38328 | // There may be existing exports. For instance, a struct may export |
| 38394 | 38329 | // things during both field type resolution and field default resolution. |
| 38395 | 38330 | // |
| 38396 | 38331 | // So, pick up and delete any existing exports. This strategy performs |
| 38397 | 38332 | // redundant work, but that's okay, because this case is exceedingly rare. |
| 38398 | if (zcu.single_exports.get(unit)) |export_idx| { | |
| 38333 | if (zcu.single_exports.get(sema.owner)) |export_idx| { | |
| 38399 | 38334 | try sema.exports.append(gpa, zcu.all_exports.items[export_idx]); |
| 38400 | } else if (zcu.multi_exports.get(unit)) |info| { | |
| 38335 | } else if (zcu.multi_exports.get(sema.owner)) |info| { | |
| 38401 | 38336 | try sema.exports.appendSlice(gpa, zcu.all_exports.items[info.index..][0..info.len]); |
| 38402 | 38337 | } |
| 38403 | zcu.deleteUnitExports(unit); | |
| 38338 | zcu.deleteUnitExports(sema.owner); | |
| 38404 | 38339 | |
| 38405 | 38340 | // `sema.exports` is completed; store the data into the `Zcu`. |
| 38406 | 38341 | if (sema.exports.items.len == 1) { |
| ... | ... | @@ -38410,24 +38345,55 @@ pub fn flushExports(sema: *Sema) !void { |
| 38410 | 38345 | break :idx zcu.all_exports.items.len - 1; |
| 38411 | 38346 | }; |
| 38412 | 38347 | zcu.all_exports.items[export_idx] = sema.exports.items[0]; |
| 38413 | zcu.single_exports.putAssumeCapacityNoClobber(unit, @intCast(export_idx)); | |
| 38348 | zcu.single_exports.putAssumeCapacityNoClobber(sema.owner, @intCast(export_idx)); | |
| 38414 | 38349 | } else { |
| 38415 | 38350 | try zcu.multi_exports.ensureUnusedCapacity(gpa, 1); |
| 38416 | 38351 | const exports_base = zcu.all_exports.items.len; |
| 38417 | 38352 | try zcu.all_exports.appendSlice(gpa, sema.exports.items); |
| 38418 | zcu.multi_exports.putAssumeCapacityNoClobber(unit, .{ | |
| 38353 | zcu.multi_exports.putAssumeCapacityNoClobber(sema.owner, .{ | |
| 38419 | 38354 | .index = @intCast(exports_base), |
| 38420 | 38355 | .len = @intCast(sema.exports.items.len), |
| 38421 | 38356 | }); |
| 38422 | 38357 | } |
| 38423 | 38358 | } |
| 38424 | 38359 | |
| 38425 | pub fn ownerUnit(sema: Sema) AnalUnit { | |
| 38426 | if (sema.owner_func_index != .none) { | |
| 38427 | return AnalUnit.wrap(.{ .func = sema.owner_func_index }); | |
| 38428 | } else { | |
| 38429 | return AnalUnit.wrap(.{ .decl = sema.owner_decl_index }); | |
| 38430 | } | |
| 38360 | /// Given that this `Sema` is owned by the `Cau` of a `declaration`, fetches | |
| 38361 | /// the corresponding `Nav`. | |
| 38362 | fn getOwnerCauNav(sema: *Sema) InternPool.Nav.Index { | |
| 38363 | const cau = sema.owner.unwrap().cau; | |
| 38364 | return sema.pt.zcu.intern_pool.getCau(cau).owner.unwrap().nav; | |
| 38365 | } | |
| 38366 | ||
| 38367 | /// Given that this `Sema` is owned by the `Cau` of a `declaration`, fetches | |
| 38368 | /// the declaration name from its corresponding `Nav`. | |
| 38369 | fn getOwnerCauNavName(sema: *Sema) InternPool.NullTerminatedString { | |
| 38370 | const nav = sema.getOwnerCauNav(); | |
| 38371 | return sema.pt.zcu.intern_pool.getNav(nav).name; | |
| 38372 | } | |
| 38373 | ||
| 38374 | /// Given that this `Sema` is owned by the `Cau` of a `declaration`, fetches | |
| 38375 | /// the `TrackedInst` corresponding to this `declaration` instruction. | |
| 38376 | fn getOwnerCauDeclInst(sema: *Sema) InternPool.TrackedInst.Index { | |
| 38377 | const ip = &sema.pt.zcu.intern_pool; | |
| 38378 | const cau = ip.getCau(sema.owner.unwrap().cau); | |
| 38379 | assert(cau.owner.unwrap() == .nav); | |
| 38380 | return cau.zir_index; | |
| 38381 | } | |
| 38382 | ||
| 38383 | /// Given that this `Sema` is owned by a runtime function, fetches the | |
| 38384 | /// `TrackedInst` corresponding to its `declaration` instruction. | |
| 38385 | fn getOwnerFuncDeclInst(sema: *Sema) InternPool.TrackedInst.Index { | |
| 38386 | const zcu = sema.pt.zcu; | |
| 38387 | const ip = &zcu.intern_pool; | |
| 38388 | const func = sema.owner.unwrap().func; | |
| 38389 | const func_info = zcu.funcInfo(func); | |
| 38390 | const cau = if (func_info.generic_owner == .none) cau: { | |
| 38391 | break :cau ip.getNav(func_info.owner_nav).analysis_owner.unwrap().?; | |
| 38392 | } else cau: { | |
| 38393 | const generic_owner = zcu.funcInfo(func_info.generic_owner); | |
| 38394 | break :cau ip.getNav(generic_owner.owner_nav).analysis_owner.unwrap().?; | |
| 38395 | }; | |
| 38396 | return ip.getCau(cau).zir_index; | |
| 38431 | 38397 | } |
| 38432 | 38398 | |
| 38433 | 38399 | pub const bitCastVal = @import("Sema/bitcast.zig").bitCast; |
src/Sema/bitcast.zig+1-1| ... | ... | @@ -254,7 +254,7 @@ const UnpackValueBits = struct { |
| 254 | 254 | .error_set_type, |
| 255 | 255 | .inferred_error_set_type, |
| 256 | 256 | .variable, |
| 257 | .extern_func, | |
| 257 | .@"extern", | |
| 258 | 258 | .func, |
| 259 | 259 | .err, |
| 260 | 260 | .error_union, |
src/Sema/comptime_ptr_access.zig+16-8| ... | ... | @@ -217,15 +217,23 @@ fn loadComptimePtrInner( |
| 217 | 217 | }; |
| 218 | 218 | |
| 219 | 219 | const base_val: MutableValue = switch (ptr.base_addr) { |
| 220 | .decl => |decl_index| val: { | |
| 221 | try sema.declareDependency(.{ .decl_val = decl_index }); | |
| 222 | try sema.ensureDeclAnalyzed(decl_index); | |
| 223 | const decl = zcu.declPtr(decl_index); | |
| 224 | if (decl.val.getVariable(zcu) != null) return .runtime_load; | |
| 225 | break :val .{ .interned = decl.val.toIntern() }; | |
| 220 | .nav => |nav| val: { | |
| 221 | try sema.declareDependency(.{ .nav_val = nav }); | |
| 222 | try sema.ensureNavResolved(src, nav); | |
| 223 | const val = ip.getNav(nav).status.resolved.val; | |
| 224 | switch (ip.indexToKey(val)) { | |
| 225 | .variable => return .runtime_load, | |
| 226 | // We let `.@"extern"` through here if it's a function. | |
| 227 | // This allows you to alias `extern fn`s. | |
| 228 | .@"extern" => |e| if (Type.fromInterned(e.ty).zigTypeTag(zcu) == .Fn) | |
| 229 | break :val .{ .interned = val } | |
| 230 | else | |
| 231 | return .runtime_load, | |
| 232 | else => break :val .{ .interned = val }, | |
| 233 | } | |
| 226 | 234 | }, |
| 227 | 235 | .comptime_alloc => |alloc_index| sema.getComptimeAlloc(alloc_index).val, |
| 228 | .anon_decl => |anon_decl| .{ .interned = anon_decl.val }, | |
| 236 | .uav => |uav| .{ .interned = uav.val }, | |
| 229 | 237 | .comptime_field => |val| .{ .interned = val }, |
| 230 | 238 | .int => return .runtime_load, |
| 231 | 239 | .eu_payload => |base_ptr_ip| val: { |
| ... | ... | @@ -580,7 +588,7 @@ fn prepareComptimePtrStore( |
| 580 | 588 | |
| 581 | 589 | // `base_strat` will not be an error case. |
| 582 | 590 | const base_strat: ComptimeStoreStrategy = switch (ptr.base_addr) { |
| 583 | .decl, .anon_decl, .int => return .runtime_store, | |
| 591 | .nav, .uav, .int => return .runtime_store, | |
| 584 | 592 | .comptime_field => return .comptime_field, |
| 585 | 593 | .comptime_alloc => |alloc_index| .{ .direct = .{ |
| 586 | 594 | .alloc = alloc_index, |
src/Type.zig+102-90| ... | ... | @@ -268,9 +268,9 @@ pub fn print(ty: Type, writer: anytype, pt: Zcu.PerThread) @TypeOf(writer).Error |
| 268 | 268 | return; |
| 269 | 269 | }, |
| 270 | 270 | .inferred_error_set_type => |func_index| { |
| 271 | const owner_decl = mod.funcOwnerDeclPtr(func_index); | |
| 271 | const func_nav = ip.getNav(mod.funcInfo(func_index).owner_nav); | |
| 272 | 272 | try writer.print("@typeInfo(@typeInfo(@TypeOf({})).Fn.return_type.?).ErrorUnion.error_set", .{ |
| 273 | owner_decl.fqn.fmt(ip), | |
| 273 | func_nav.fqn.fmt(ip), | |
| 274 | 274 | }); |
| 275 | 275 | }, |
| 276 | 276 | .error_set_type => |error_set_type| { |
| ... | ... | @@ -331,15 +331,11 @@ pub fn print(ty: Type, writer: anytype, pt: Zcu.PerThread) @TypeOf(writer).Error |
| 331 | 331 | .generic_poison => unreachable, |
| 332 | 332 | }, |
| 333 | 333 | .struct_type => { |
| 334 | const struct_type = ip.loadStructType(ty.toIntern()); | |
| 335 | if (struct_type.decl.unwrap()) |decl_index| { | |
| 336 | const decl = mod.declPtr(decl_index); | |
| 337 | try writer.print("{}", .{decl.fqn.fmt(ip)}); | |
| 338 | } else if (ip.loadStructType(ty.toIntern()).namespace.unwrap()) |namespace_index| { | |
| 339 | const namespace = mod.namespacePtr(namespace_index); | |
| 340 | try namespace.renderFullyQualifiedName(ip, .empty, writer); | |
| 341 | } else { | |
| 334 | const name = ip.loadStructType(ty.toIntern()).name; | |
| 335 | if (name == .empty) { | |
| 342 | 336 | try writer.writeAll("@TypeOf(.{})"); |
| 337 | } else { | |
| 338 | try writer.print("{}", .{name.fmt(ip)}); | |
| 343 | 339 | } |
| 344 | 340 | }, |
| 345 | 341 | .anon_struct_type => |anon_struct| { |
| ... | ... | @@ -366,16 +362,16 @@ pub fn print(ty: Type, writer: anytype, pt: Zcu.PerThread) @TypeOf(writer).Error |
| 366 | 362 | }, |
| 367 | 363 | |
| 368 | 364 | .union_type => { |
| 369 | const decl = mod.declPtr(ip.loadUnionType(ty.toIntern()).decl); | |
| 370 | try writer.print("{}", .{decl.fqn.fmt(ip)}); | |
| 365 | const name = ip.loadUnionType(ty.toIntern()).name; | |
| 366 | try writer.print("{}", .{name.fmt(ip)}); | |
| 371 | 367 | }, |
| 372 | 368 | .opaque_type => { |
| 373 | const decl = mod.declPtr(ip.loadOpaqueType(ty.toIntern()).decl); | |
| 374 | try writer.print("{}", .{decl.fqn.fmt(ip)}); | |
| 369 | const name = ip.loadOpaqueType(ty.toIntern()).name; | |
| 370 | try writer.print("{}", .{name.fmt(ip)}); | |
| 375 | 371 | }, |
| 376 | 372 | .enum_type => { |
| 377 | const decl = mod.declPtr(ip.loadEnumType(ty.toIntern()).decl); | |
| 378 | try writer.print("{}", .{decl.fqn.fmt(ip)}); | |
| 373 | const name = ip.loadEnumType(ty.toIntern()).name; | |
| 374 | try writer.print("{}", .{name.fmt(ip)}); | |
| 379 | 375 | }, |
| 380 | 376 | .func_type => |fn_info| { |
| 381 | 377 | if (fn_info.is_noinline) { |
| ... | ... | @@ -427,7 +423,7 @@ pub fn print(ty: Type, writer: anytype, pt: Zcu.PerThread) @TypeOf(writer).Error |
| 427 | 423 | .undef, |
| 428 | 424 | .simple_value, |
| 429 | 425 | .variable, |
| 430 | .extern_func, | |
| 426 | .@"extern", | |
| 431 | 427 | .func, |
| 432 | 428 | .int, |
| 433 | 429 | .err, |
| ... | ... | @@ -645,7 +641,7 @@ pub fn hasRuntimeBitsAdvanced( |
| 645 | 641 | .undef, |
| 646 | 642 | .simple_value, |
| 647 | 643 | .variable, |
| 648 | .extern_func, | |
| 644 | .@"extern", | |
| 649 | 645 | .func, |
| 650 | 646 | .int, |
| 651 | 647 | .err, |
| ... | ... | @@ -757,7 +753,7 @@ pub fn hasWellDefinedLayout(ty: Type, mod: *Module) bool { |
| 757 | 753 | .undef, |
| 758 | 754 | .simple_value, |
| 759 | 755 | .variable, |
| 760 | .extern_func, | |
| 756 | .@"extern", | |
| 761 | 757 | .func, |
| 762 | 758 | .int, |
| 763 | 759 | .err, |
| ... | ... | @@ -1108,7 +1104,7 @@ pub fn abiAlignmentAdvanced( |
| 1108 | 1104 | .undef, |
| 1109 | 1105 | .simple_value, |
| 1110 | 1106 | .variable, |
| 1111 | .extern_func, | |
| 1107 | .@"extern", | |
| 1112 | 1108 | .func, |
| 1113 | 1109 | .int, |
| 1114 | 1110 | .err, |
| ... | ... | @@ -1483,7 +1479,7 @@ pub fn abiSizeAdvanced( |
| 1483 | 1479 | .undef, |
| 1484 | 1480 | .simple_value, |
| 1485 | 1481 | .variable, |
| 1486 | .extern_func, | |
| 1482 | .@"extern", | |
| 1487 | 1483 | .func, |
| 1488 | 1484 | .int, |
| 1489 | 1485 | .err, |
| ... | ... | @@ -1813,7 +1809,7 @@ pub fn bitSizeAdvanced( |
| 1813 | 1809 | .undef, |
| 1814 | 1810 | .simple_value, |
| 1815 | 1811 | .variable, |
| 1816 | .extern_func, | |
| 1812 | .@"extern", | |
| 1817 | 1813 | .func, |
| 1818 | 1814 | .int, |
| 1819 | 1815 | .err, |
| ... | ... | @@ -2351,7 +2347,7 @@ pub fn intInfo(starting_ty: Type, mod: *Module) InternPool.Key.IntType { |
| 2351 | 2347 | .undef, |
| 2352 | 2348 | .simple_value, |
| 2353 | 2349 | .variable, |
| 2354 | .extern_func, | |
| 2350 | .@"extern", | |
| 2355 | 2351 | .func, |
| 2356 | 2352 | .int, |
| 2357 | 2353 | .err, |
| ... | ... | @@ -2700,7 +2696,7 @@ pub fn onePossibleValue(starting_type: Type, pt: Zcu.PerThread) !?Value { |
| 2700 | 2696 | .undef, |
| 2701 | 2697 | .simple_value, |
| 2702 | 2698 | .variable, |
| 2703 | .extern_func, | |
| 2699 | .@"extern", | |
| 2704 | 2700 | .func, |
| 2705 | 2701 | .int, |
| 2706 | 2702 | .err, |
| ... | ... | @@ -2899,7 +2895,7 @@ pub fn comptimeOnlyAdvanced(ty: Type, pt: Zcu.PerThread, comptime strat: Resolve |
| 2899 | 2895 | .undef, |
| 2900 | 2896 | .simple_value, |
| 2901 | 2897 | .variable, |
| 2902 | .extern_func, | |
| 2898 | .@"extern", | |
| 2903 | 2899 | .func, |
| 2904 | 2900 | .int, |
| 2905 | 2901 | .err, |
| ... | ... | @@ -2972,41 +2968,27 @@ pub fn indexableHasLen(ty: Type, mod: *Module) bool { |
| 2972 | 2968 | } |
| 2973 | 2969 | |
| 2974 | 2970 | /// Asserts that the type can have a namespace. |
| 2975 | pub fn getNamespaceIndex(ty: Type, zcu: *Zcu) InternPool.OptionalNamespaceIndex { | |
| 2976 | return ty.getNamespace(zcu).?; | |
| 2971 | pub fn getNamespaceIndex(ty: Type, zcu: *Zcu) InternPool.NamespaceIndex { | |
| 2972 | return ty.getNamespace(zcu).unwrap().?; | |
| 2977 | 2973 | } |
| 2978 | 2974 | |
| 2979 | 2975 | /// Returns null if the type has no namespace. |
| 2980 | pub fn getNamespace(ty: Type, zcu: *Zcu) ?InternPool.OptionalNamespaceIndex { | |
| 2976 | pub fn getNamespace(ty: Type, zcu: *Zcu) InternPool.OptionalNamespaceIndex { | |
| 2981 | 2977 | const ip = &zcu.intern_pool; |
| 2982 | 2978 | return switch (ip.indexToKey(ty.toIntern())) { |
| 2983 | .opaque_type => ip.loadOpaqueType(ty.toIntern()).namespace, | |
| 2979 | .opaque_type => ip.loadOpaqueType(ty.toIntern()).namespace.toOptional(), | |
| 2984 | 2980 | .struct_type => ip.loadStructType(ty.toIntern()).namespace, |
| 2985 | .union_type => ip.loadUnionType(ty.toIntern()).namespace, | |
| 2986 | .enum_type => ip.loadEnumType(ty.toIntern()).namespace, | |
| 2987 | ||
| 2988 | .anon_struct_type => .none, | |
| 2989 | .simple_type => |s| switch (s) { | |
| 2990 | .anyopaque, | |
| 2991 | .atomic_order, | |
| 2992 | .atomic_rmw_op, | |
| 2993 | .calling_convention, | |
| 2994 | .address_space, | |
| 2995 | .float_mode, | |
| 2996 | .reduce_op, | |
| 2997 | .call_modifier, | |
| 2998 | .prefetch_options, | |
| 2999 | .export_options, | |
| 3000 | .extern_options, | |
| 3001 | .type_info, | |
| 3002 | => .none, | |
| 3003 | else => null, | |
| 3004 | }, | |
| 3005 | ||
| 3006 | else => null, | |
| 2981 | .union_type => ip.loadUnionType(ty.toIntern()).namespace.toOptional(), | |
| 2982 | .enum_type => ip.loadEnumType(ty.toIntern()).namespace.toOptional(), | |
| 2983 | else => .none, | |
| 3007 | 2984 | }; |
| 3008 | 2985 | } |
| 3009 | 2986 | |
| 2987 | // TODO: new dwarf structure will also need the enclosing code block for types created in imperative scopes | |
| 2988 | pub fn getParentNamespace(ty: Type, zcu: *Zcu) InternPool.OptionalNamespaceIndex { | |
| 2989 | return zcu.namespacePtr(ty.getNamespace(zcu).unwrap() orelse return .none).parent; | |
| 2990 | } | |
| 2991 | ||
| 3010 | 2992 | // Works for vectors and vectors of integers. |
| 3011 | 2993 | pub fn minInt(ty: Type, pt: Zcu.PerThread, dest_ty: Type) !Value { |
| 3012 | 2994 | const mod = pt.zcu; |
| ... | ... | @@ -3321,21 +3303,6 @@ pub fn structFieldOffset(ty: Type, index: usize, pt: Zcu.PerThread) u64 { |
| 3321 | 3303 | } |
| 3322 | 3304 | } |
| 3323 | 3305 | |
| 3324 | pub fn getOwnerDecl(ty: Type, mod: *Module) InternPool.DeclIndex { | |
| 3325 | return ty.getOwnerDeclOrNull(mod) orelse unreachable; | |
| 3326 | } | |
| 3327 | ||
| 3328 | pub fn getOwnerDeclOrNull(ty: Type, mod: *Module) ?InternPool.DeclIndex { | |
| 3329 | const ip = &mod.intern_pool; | |
| 3330 | return switch (ip.indexToKey(ty.toIntern())) { | |
| 3331 | .struct_type => ip.loadStructType(ty.toIntern()).decl.unwrap(), | |
| 3332 | .union_type => ip.loadUnionType(ty.toIntern()).decl, | |
| 3333 | .opaque_type => ip.loadOpaqueType(ty.toIntern()).decl, | |
| 3334 | .enum_type => ip.loadEnumType(ty.toIntern()).decl, | |
| 3335 | else => null, | |
| 3336 | }; | |
| 3337 | } | |
| 3338 | ||
| 3339 | 3306 | pub fn srcLocOrNull(ty: Type, zcu: *Zcu) ?Module.LazySrcLoc { |
| 3340 | 3307 | const ip = &zcu.intern_pool; |
| 3341 | 3308 | return .{ |
| ... | ... | @@ -3366,7 +3333,7 @@ pub fn isTuple(ty: Type, mod: *Module) bool { |
| 3366 | 3333 | .struct_type => { |
| 3367 | 3334 | const struct_type = ip.loadStructType(ty.toIntern()); |
| 3368 | 3335 | if (struct_type.layout == .@"packed") return false; |
| 3369 | if (struct_type.decl == .none) return false; | |
| 3336 | if (struct_type.cau == .none) return false; | |
| 3370 | 3337 | return struct_type.flagsUnordered(ip).is_tuple; |
| 3371 | 3338 | }, |
| 3372 | 3339 | .anon_struct_type => |anon_struct| anon_struct.names.len == 0, |
| ... | ... | @@ -3388,7 +3355,7 @@ pub fn isTupleOrAnonStruct(ty: Type, mod: *Module) bool { |
| 3388 | 3355 | .struct_type => { |
| 3389 | 3356 | const struct_type = ip.loadStructType(ty.toIntern()); |
| 3390 | 3357 | if (struct_type.layout == .@"packed") return false; |
| 3391 | if (struct_type.decl == .none) return false; | |
| 3358 | if (struct_type.cau == .none) return false; | |
| 3392 | 3359 | return struct_type.flagsUnordered(ip).is_tuple; |
| 3393 | 3360 | }, |
| 3394 | 3361 | .anon_struct_type => true, |
| ... | ... | @@ -3444,6 +3411,21 @@ pub fn typeDeclInst(ty: Type, zcu: *const Zcu) ?InternPool.TrackedInst.Index { |
| 3444 | 3411 | }; |
| 3445 | 3412 | } |
| 3446 | 3413 | |
| 3414 | pub fn typeDeclInstAllowGeneratedTag(ty: Type, zcu: *const Zcu) ?InternPool.TrackedInst.Index { | |
| 3415 | const ip = &zcu.intern_pool; | |
| 3416 | return switch (ip.indexToKey(ty.toIntern())) { | |
| 3417 | .struct_type => ip.loadStructType(ty.toIntern()).zir_index.unwrap(), | |
| 3418 | .union_type => ip.loadUnionType(ty.toIntern()).zir_index, | |
| 3419 | .enum_type => |e| switch (e) { | |
| 3420 | .declared, .reified => ip.loadEnumType(ty.toIntern()).zir_index.unwrap().?, | |
| 3421 | .generated_tag => |gt| ip.loadUnionType(gt.union_type).zir_index, | |
| 3422 | .empty_struct => unreachable, | |
| 3423 | }, | |
| 3424 | .opaque_type => ip.loadOpaqueType(ty.toIntern()).zir_index, | |
| 3425 | else => null, | |
| 3426 | }; | |
| 3427 | } | |
| 3428 | ||
| 3447 | 3429 | pub fn typeDeclSrcLine(ty: Type, zcu: *Zcu) ?u32 { |
| 3448 | 3430 | const ip = &zcu.intern_pool; |
| 3449 | 3431 | const tracked = switch (ip.indexToKey(ty.toIntern())) { |
| ... | ... | @@ -3471,7 +3453,7 @@ pub fn typeDeclSrcLine(ty: Type, zcu: *Zcu) ?u32 { |
| 3471 | 3453 | }; |
| 3472 | 3454 | } |
| 3473 | 3455 | |
| 3474 | /// Given a namespace type, returns its list of caotured values. | |
| 3456 | /// Given a namespace type, returns its list of captured values. | |
| 3475 | 3457 | pub fn getCaptures(ty: Type, zcu: *const Zcu) InternPool.CaptureValue.Slice { |
| 3476 | 3458 | const ip = &zcu.intern_pool; |
| 3477 | 3459 | return switch (ip.indexToKey(ty.toIntern())) { |
| ... | ... | @@ -3773,7 +3755,11 @@ fn resolveStructInner( |
| 3773 | 3755 | const gpa = zcu.gpa; |
| 3774 | 3756 | |
| 3775 | 3757 | const struct_obj = zcu.typeToStruct(ty).?; |
| 3776 | const owner_decl_index = struct_obj.decl.unwrap() orelse return; | |
| 3758 | const owner = InternPool.AnalUnit.wrap(.{ .cau = struct_obj.cau.unwrap() orelse return }); | |
| 3759 | ||
| 3760 | if (zcu.failed_analysis.contains(owner) or zcu.transitive_failed_analysis.contains(owner)) { | |
| 3761 | return error.AnalysisFail; | |
| 3762 | } | |
| 3777 | 3763 | |
| 3778 | 3764 | var analysis_arena = std.heap.ArenaAllocator.init(gpa); |
| 3779 | 3765 | defer analysis_arena.deinit(); |
| ... | ... | @@ -3786,24 +3772,30 @@ fn resolveStructInner( |
| 3786 | 3772 | .gpa = gpa, |
| 3787 | 3773 | .arena = analysis_arena.allocator(), |
| 3788 | 3774 | .code = undefined, // This ZIR will not be used. |
| 3789 | .owner_decl = zcu.declPtr(owner_decl_index), | |
| 3790 | .owner_decl_index = owner_decl_index, | |
| 3775 | .owner = owner, | |
| 3791 | 3776 | .func_index = .none, |
| 3792 | 3777 | .func_is_naked = false, |
| 3793 | 3778 | .fn_ret_ty = Type.void, |
| 3794 | 3779 | .fn_ret_ty_ies = null, |
| 3795 | .owner_func_index = .none, | |
| 3796 | 3780 | .comptime_err_ret_trace = &comptime_err_ret_trace, |
| 3797 | 3781 | }; |
| 3798 | 3782 | defer sema.deinit(); |
| 3799 | 3783 | |
| 3800 | switch (resolution) { | |
| 3801 | .fields => return sema.resolveTypeFieldsStruct(ty.toIntern(), struct_obj), | |
| 3802 | .inits => return sema.resolveStructFieldInits(ty), | |
| 3803 | .alignment => return sema.resolveStructAlignment(ty.toIntern(), struct_obj), | |
| 3804 | .layout => return sema.resolveStructLayout(ty), | |
| 3805 | .full => return sema.resolveStructFully(ty), | |
| 3806 | } | |
| 3784 | (switch (resolution) { | |
| 3785 | .fields => sema.resolveTypeFieldsStruct(ty.toIntern(), struct_obj), | |
| 3786 | .inits => sema.resolveStructFieldInits(ty), | |
| 3787 | .alignment => sema.resolveStructAlignment(ty.toIntern(), struct_obj), | |
| 3788 | .layout => sema.resolveStructLayout(ty), | |
| 3789 | .full => sema.resolveStructFully(ty), | |
| 3790 | }) catch |err| switch (err) { | |
| 3791 | error.AnalysisFail => { | |
| 3792 | if (!zcu.failed_analysis.contains(owner)) { | |
| 3793 | try zcu.transitive_failed_analysis.put(gpa, owner, {}); | |
| 3794 | } | |
| 3795 | return error.AnalysisFail; | |
| 3796 | }, | |
| 3797 | error.OutOfMemory => |e| return e, | |
| 3798 | }; | |
| 3807 | 3799 | } |
| 3808 | 3800 | |
| 3809 | 3801 | /// `ty` must be a union. |
| ... | ... | @@ -3816,7 +3808,11 @@ fn resolveUnionInner( |
| 3816 | 3808 | const gpa = zcu.gpa; |
| 3817 | 3809 | |
| 3818 | 3810 | const union_obj = zcu.typeToUnion(ty).?; |
| 3819 | const owner_decl_index = union_obj.decl; | |
| 3811 | const owner = InternPool.AnalUnit.wrap(.{ .cau = union_obj.cau }); | |
| 3812 | ||
| 3813 | if (zcu.failed_analysis.contains(owner) or zcu.transitive_failed_analysis.contains(owner)) { | |
| 3814 | return error.AnalysisFail; | |
| 3815 | } | |
| 3820 | 3816 | |
| 3821 | 3817 | var analysis_arena = std.heap.ArenaAllocator.init(gpa); |
| 3822 | 3818 | defer analysis_arena.deinit(); |
| ... | ... | @@ -3829,23 +3825,29 @@ fn resolveUnionInner( |
| 3829 | 3825 | .gpa = gpa, |
| 3830 | 3826 | .arena = analysis_arena.allocator(), |
| 3831 | 3827 | .code = undefined, // This ZIR will not be used. |
| 3832 | .owner_decl = zcu.declPtr(owner_decl_index), | |
| 3833 | .owner_decl_index = owner_decl_index, | |
| 3828 | .owner = owner, | |
| 3834 | 3829 | .func_index = .none, |
| 3835 | 3830 | .func_is_naked = false, |
| 3836 | 3831 | .fn_ret_ty = Type.void, |
| 3837 | 3832 | .fn_ret_ty_ies = null, |
| 3838 | .owner_func_index = .none, | |
| 3839 | 3833 | .comptime_err_ret_trace = &comptime_err_ret_trace, |
| 3840 | 3834 | }; |
| 3841 | 3835 | defer sema.deinit(); |
| 3842 | 3836 | |
| 3843 | switch (resolution) { | |
| 3844 | .fields => return sema.resolveTypeFieldsUnion(ty, union_obj), | |
| 3845 | .alignment => return sema.resolveUnionAlignment(ty, union_obj), | |
| 3846 | .layout => return sema.resolveUnionLayout(ty), | |
| 3847 | .full => return sema.resolveUnionFully(ty), | |
| 3848 | } | |
| 3837 | (switch (resolution) { | |
| 3838 | .fields => sema.resolveTypeFieldsUnion(ty, union_obj), | |
| 3839 | .alignment => sema.resolveUnionAlignment(ty, union_obj), | |
| 3840 | .layout => sema.resolveUnionLayout(ty), | |
| 3841 | .full => sema.resolveUnionFully(ty), | |
| 3842 | }) catch |err| switch (err) { | |
| 3843 | error.AnalysisFail => { | |
| 3844 | if (!zcu.failed_analysis.contains(owner)) { | |
| 3845 | try zcu.transitive_failed_analysis.put(gpa, owner, {}); | |
| 3846 | } | |
| 3847 | return error.AnalysisFail; | |
| 3848 | }, | |
| 3849 | error.OutOfMemory => |e| return e, | |
| 3850 | }; | |
| 3849 | 3851 | } |
| 3850 | 3852 | |
| 3851 | 3853 | /// Fully resolves a simple type. This is usually a nop, but for builtin types with |
| ... | ... | @@ -3945,6 +3947,16 @@ pub fn elemPtrType(ptr_ty: Type, offset: ?usize, pt: Zcu.PerThread) !Type { |
| 3945 | 3947 | }); |
| 3946 | 3948 | } |
| 3947 | 3949 | |
| 3950 | pub fn containerTypeName(ty: Type, ip: *const InternPool) InternPool.NullTerminatedString { | |
| 3951 | return switch (ip.indexToKey(ty.toIntern())) { | |
| 3952 | .struct_type => ip.loadStructType(ty.toIntern()).name, | |
| 3953 | .union_type => ip.loadUnionType(ty.toIntern()).name, | |
| 3954 | .enum_type => ip.loadEnumType(ty.toIntern()).name, | |
| 3955 | .opaque_type => ip.loadOpaqueType(ty.toIntern()).name, | |
| 3956 | else => unreachable, | |
| 3957 | }; | |
| 3958 | } | |
| 3959 | ||
| 3948 | 3960 | pub const @"u1": Type = .{ .ip_index = .u1_type }; |
| 3949 | 3961 | pub const @"u8": Type = .{ .ip_index = .u8_type }; |
| 3950 | 3962 | pub const @"u16": Type = .{ .ip_index = .u16_type }; |
src/Value.zig+37-48| ... | ... | @@ -227,13 +227,6 @@ pub fn getFunction(val: Value, mod: *Module) ?InternPool.Key.Func { |
| 227 | 227 | }; |
| 228 | 228 | } |
| 229 | 229 | |
| 230 | pub fn getExternFunc(val: Value, mod: *Module) ?InternPool.Key.ExternFunc { | |
| 231 | return switch (mod.intern_pool.indexToKey(val.toIntern())) { | |
| 232 | .extern_func => |extern_func| extern_func, | |
| 233 | else => null, | |
| 234 | }; | |
| 235 | } | |
| 236 | ||
| 237 | 230 | pub fn getVariable(val: Value, mod: *Module) ?InternPool.Key.Variable { |
| 238 | 231 | return switch (mod.intern_pool.indexToKey(val.toIntern())) { |
| 239 | 232 | .variable => |variable| variable, |
| ... | ... | @@ -319,17 +312,8 @@ pub fn toBool(val: Value) bool { |
| 319 | 312 | }; |
| 320 | 313 | } |
| 321 | 314 | |
| 322 | fn ptrHasIntAddr(val: Value, mod: *Module) bool { | |
| 323 | var check = val; | |
| 324 | while (true) switch (mod.intern_pool.indexToKey(check.toIntern())) { | |
| 325 | .ptr => |ptr| switch (ptr.base_addr) { | |
| 326 | .decl, .comptime_alloc, .comptime_field, .anon_decl => return false, | |
| 327 | .int => return true, | |
| 328 | .eu_payload, .opt_payload => |base| check = Value.fromInterned(base), | |
| 329 | .arr_elem, .field => |base_index| check = Value.fromInterned(base_index.base), | |
| 330 | }, | |
| 331 | else => unreachable, | |
| 332 | }; | |
| 315 | fn ptrHasIntAddr(val: Value, zcu: *Zcu) bool { | |
| 316 | return zcu.intern_pool.getBackingAddrTag(val.toIntern()).? == .int; | |
| 333 | 317 | } |
| 334 | 318 | |
| 335 | 319 | /// Write a Value's contents to `buffer`. |
| ... | ... | @@ -1058,7 +1042,7 @@ pub fn orderAgainstZeroAdvanced( |
| 1058 | 1042 | .bool_true => .gt, |
| 1059 | 1043 | else => switch (pt.zcu.intern_pool.indexToKey(lhs.toIntern())) { |
| 1060 | 1044 | .ptr => |ptr| if (ptr.byte_offset > 0) .gt else switch (ptr.base_addr) { |
| 1061 | .decl, .comptime_alloc, .comptime_field => .gt, | |
| 1045 | .nav, .comptime_alloc, .comptime_field => .gt, | |
| 1062 | 1046 | .int => .eq, |
| 1063 | 1047 | else => unreachable, |
| 1064 | 1048 | }, |
| ... | ... | @@ -1130,11 +1114,11 @@ pub fn compareHeteroAdvanced( |
| 1130 | 1114 | pt: Zcu.PerThread, |
| 1131 | 1115 | comptime strat: ResolveStrat, |
| 1132 | 1116 | ) !bool { |
| 1133 | if (lhs.pointerDecl(pt.zcu)) |lhs_decl| { | |
| 1134 | if (rhs.pointerDecl(pt.zcu)) |rhs_decl| { | |
| 1117 | if (lhs.pointerNav(pt.zcu)) |lhs_nav| { | |
| 1118 | if (rhs.pointerNav(pt.zcu)) |rhs_nav| { | |
| 1135 | 1119 | switch (op) { |
| 1136 | .eq => return lhs_decl == rhs_decl, | |
| 1137 | .neq => return lhs_decl != rhs_decl, | |
| 1120 | .eq => return lhs_nav == rhs_nav, | |
| 1121 | .neq => return lhs_nav != rhs_nav, | |
| 1138 | 1122 | else => {}, |
| 1139 | 1123 | } |
| 1140 | 1124 | } else { |
| ... | ... | @@ -1144,7 +1128,7 @@ pub fn compareHeteroAdvanced( |
| 1144 | 1128 | else => {}, |
| 1145 | 1129 | } |
| 1146 | 1130 | } |
| 1147 | } else if (rhs.pointerDecl(pt.zcu)) |_| { | |
| 1131 | } else if (rhs.pointerNav(pt.zcu)) |_| { | |
| 1148 | 1132 | switch (op) { |
| 1149 | 1133 | .eq => return false, |
| 1150 | 1134 | .neq => return true, |
| ... | ... | @@ -1252,12 +1236,12 @@ pub fn canMutateComptimeVarState(val: Value, zcu: *Zcu) bool { |
| 1252 | 1236 | .payload => |payload| Value.fromInterned(payload).canMutateComptimeVarState(zcu), |
| 1253 | 1237 | }, |
| 1254 | 1238 | .ptr => |ptr| switch (ptr.base_addr) { |
| 1255 | .decl => false, // The value of a Decl can never reference a comptime alloc. | |
| 1239 | .nav => false, // The value of a Nav can never reference a comptime alloc. | |
| 1256 | 1240 | .int => false, |
| 1257 | 1241 | .comptime_alloc => true, // A comptime alloc is either mutable or references comptime-mutable memory. |
| 1258 | 1242 | .comptime_field => true, // Comptime field pointers are comptime-mutable, albeit only to the "correct" value. |
| 1259 | 1243 | .eu_payload, .opt_payload => |base| Value.fromInterned(base).canMutateComptimeVarState(zcu), |
| 1260 | .anon_decl => |anon_decl| Value.fromInterned(anon_decl.val).canMutateComptimeVarState(zcu), | |
| 1244 | .uav => |uav| Value.fromInterned(uav.val).canMutateComptimeVarState(zcu), | |
| 1261 | 1245 | .arr_elem, .field => |base_index| Value.fromInterned(base_index.base).canMutateComptimeVarState(zcu), |
| 1262 | 1246 | }, |
| 1263 | 1247 | .slice => |slice| return Value.fromInterned(slice.ptr).canMutateComptimeVarState(zcu), |
| ... | ... | @@ -1273,16 +1257,17 @@ pub fn canMutateComptimeVarState(val: Value, zcu: *Zcu) bool { |
| 1273 | 1257 | }; |
| 1274 | 1258 | } |
| 1275 | 1259 | |
| 1276 | /// Gets the decl referenced by this pointer. If the pointer does not point | |
| 1277 | /// to a decl, or if it points to some part of a decl (like field_ptr or element_ptr), | |
| 1278 | /// this function returns null. | |
| 1279 | pub fn pointerDecl(val: Value, mod: *Module) ?InternPool.DeclIndex { | |
| 1260 | /// Gets the `Nav` referenced by this pointer. If the pointer does not point | |
| 1261 | /// to a `Nav`, or if it points to some part of one (like a field or element), | |
| 1262 | /// returns null. | |
| 1263 | pub fn pointerNav(val: Value, mod: *Module) ?InternPool.Nav.Index { | |
| 1280 | 1264 | return switch (mod.intern_pool.indexToKey(val.toIntern())) { |
| 1281 | .variable => |variable| variable.decl, | |
| 1282 | .extern_func => |extern_func| extern_func.decl, | |
| 1283 | .func => |func| func.owner_decl, | |
| 1265 | // TODO: these 3 cases are weird; these aren't pointer values! | |
| 1266 | .variable => |v| v.owner_nav, | |
| 1267 | .@"extern" => |e| e.owner_nav, | |
| 1268 | .func => |func| func.owner_nav, | |
| 1284 | 1269 | .ptr => |ptr| if (ptr.byte_offset == 0) switch (ptr.base_addr) { |
| 1285 | .decl => |decl| decl, | |
| 1270 | .nav => |nav| nav, | |
| 1286 | 1271 | else => null, |
| 1287 | 1272 | } else null, |
| 1288 | 1273 | else => null, |
| ... | ... | @@ -1341,10 +1326,14 @@ pub fn isLazySize(val: Value, mod: *Module) bool { |
| 1341 | 1326 | }; |
| 1342 | 1327 | } |
| 1343 | 1328 | |
| 1344 | pub fn isPtrToThreadLocal(val: Value, mod: *Module) bool { | |
| 1345 | const backing_decl = mod.intern_pool.getBackingDecl(val.toIntern()).unwrap() orelse return false; | |
| 1346 | const variable = mod.declPtr(backing_decl).getOwnedVariable(mod) orelse return false; | |
| 1347 | return variable.is_threadlocal; | |
| 1329 | pub fn isPtrToThreadLocal(val: Value, zcu: *Zcu) bool { | |
| 1330 | const ip = &zcu.intern_pool; | |
| 1331 | const nav = ip.getBackingNav(val.toIntern()).unwrap() orelse return false; | |
| 1332 | return switch (ip.indexToKey(ip.getNav(nav).status.resolved.val)) { | |
| 1333 | .@"extern" => |e| e.is_threadlocal, | |
| 1334 | .variable => |v| v.is_threadlocal, | |
| 1335 | else => false, | |
| 1336 | }; | |
| 1348 | 1337 | } |
| 1349 | 1338 | |
| 1350 | 1339 | // Asserts that the provided start/end are in-bounds. |
| ... | ... | @@ -4031,8 +4020,8 @@ pub const PointerDeriveStep = union(enum) { |
| 4031 | 4020 | addr: u64, |
| 4032 | 4021 | ptr_ty: Type, |
| 4033 | 4022 | }, |
| 4034 | decl_ptr: InternPool.DeclIndex, | |
| 4035 | anon_decl_ptr: InternPool.Key.Ptr.BaseAddr.AnonDecl, | |
| 4023 | nav_ptr: InternPool.Nav.Index, | |
| 4024 | uav_ptr: InternPool.Key.Ptr.BaseAddr.Uav, | |
| 4036 | 4025 | comptime_alloc_ptr: struct { |
| 4037 | 4026 | val: Value, |
| 4038 | 4027 | ptr_ty: Type, |
| ... | ... | @@ -4069,8 +4058,8 @@ pub const PointerDeriveStep = union(enum) { |
| 4069 | 4058 | pub fn ptrType(step: PointerDeriveStep, pt: Zcu.PerThread) !Type { |
| 4070 | 4059 | return switch (step) { |
| 4071 | 4060 | .int => |int| int.ptr_ty, |
| 4072 | .decl_ptr => |decl| try pt.zcu.declPtr(decl).declPtrType(pt), | |
| 4073 | .anon_decl_ptr => |ad| Type.fromInterned(ad.orig_ty), | |
| 4061 | .nav_ptr => |nav| try pt.navPtrType(nav), | |
| 4062 | .uav_ptr => |uav| Type.fromInterned(uav.orig_ty), | |
| 4074 | 4063 | .comptime_alloc_ptr => |info| info.ptr_ty, |
| 4075 | 4064 | .comptime_field_ptr => |val| try pt.singleConstPtrType(val.typeOf(pt.zcu)), |
| 4076 | 4065 | .offset_and_cast => |oac| oac.new_ptr_ty, |
| ... | ... | @@ -4098,17 +4087,17 @@ pub fn pointerDerivationAdvanced(ptr_val: Value, arena: Allocator, pt: Zcu.PerTh |
| 4098 | 4087 | .addr = ptr.byte_offset, |
| 4099 | 4088 | .ptr_ty = Type.fromInterned(ptr.ty), |
| 4100 | 4089 | } }, |
| 4101 | .decl => |decl| .{ .decl_ptr = decl }, | |
| 4102 | .anon_decl => |ad| base: { | |
| 4090 | .nav => |nav| .{ .nav_ptr = nav }, | |
| 4091 | .uav => |uav| base: { | |
| 4103 | 4092 | // A slight tweak: `orig_ty` here is sometimes not `const`, but it ought to be. |
| 4104 | 4093 | // TODO: fix this in the sites interning anon decls! |
| 4105 | 4094 | const const_ty = try pt.ptrType(info: { |
| 4106 | var info = Type.fromInterned(ad.orig_ty).ptrInfo(zcu); | |
| 4095 | var info = Type.fromInterned(uav.orig_ty).ptrInfo(zcu); | |
| 4107 | 4096 | info.flags.is_const = true; |
| 4108 | 4097 | break :info info; |
| 4109 | 4098 | }); |
| 4110 | break :base .{ .anon_decl_ptr = .{ | |
| 4111 | .val = ad.val, | |
| 4099 | break :base .{ .uav_ptr = .{ | |
| 4100 | .val = uav.val, | |
| 4112 | 4101 | .orig_ty = const_ty.toIntern(), |
| 4113 | 4102 | } }; |
| 4114 | 4103 | }, |
| ... | ... | @@ -4357,7 +4346,7 @@ pub fn resolveLazy(val: Value, arena: Allocator, pt: Zcu.PerThread) Zcu.SemaErro |
| 4357 | 4346 | }, |
| 4358 | 4347 | .ptr => |ptr| { |
| 4359 | 4348 | switch (ptr.base_addr) { |
| 4360 | .decl, .comptime_alloc, .anon_decl, .int => return val, | |
| 4349 | .nav, .comptime_alloc, .uav, .int => return val, | |
| 4361 | 4350 | .comptime_field => |field_val| { |
| 4362 | 4351 | const resolved_field_val = (try Value.fromInterned(field_val).resolveLazy(arena, pt)).toIntern(); |
| 4363 | 4352 | return if (resolved_field_val == field_val) |
src/Zcu.zig+143-521| ... | ... | @@ -118,8 +118,15 @@ embed_table: std.StringArrayHashMapUnmanaged(*EmbedFile) = .{}, |
| 118 | 118 | /// is not yet implemented. |
| 119 | 119 | intern_pool: InternPool = .{}, |
| 120 | 120 | |
| 121 | analysis_in_progress: std.AutoArrayHashMapUnmanaged(AnalUnit, void) = .{}, | |
| 121 | 122 | /// The ErrorMsg memory is owned by the `AnalUnit`, using Module's general purpose allocator. |
| 122 | 123 | failed_analysis: std.AutoArrayHashMapUnmanaged(AnalUnit, *ErrorMsg) = .{}, |
| 124 | /// This `AnalUnit` failed semantic analysis because it required analysis of another `AnalUnit` which itself failed. | |
| 125 | transitive_failed_analysis: std.AutoArrayHashMapUnmanaged(AnalUnit, void) = .{}, | |
| 126 | /// This `Nav` succeeded analysis, but failed codegen. | |
| 127 | /// This may be a simple "value" `Nav`, or it may be a function. | |
| 128 | /// The ErrorMsg memory is owned by the `AnalUnit`, using Module's general purpose allocator. | |
| 129 | failed_codegen: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, *ErrorMsg) = .{}, | |
| 123 | 130 | /// Keep track of one `@compileLog` callsite per `AnalUnit`. |
| 124 | 131 | /// The value is the source location of the `@compileLog` call, convertible to a `LazySrcLoc`. |
| 125 | 132 | compile_log_sources: std.AutoArrayHashMapUnmanaged(AnalUnit, extern struct { |
| ... | ... | @@ -155,12 +162,12 @@ outdated: std.AutoArrayHashMapUnmanaged(AnalUnit, u32) = .{}, |
| 155 | 162 | /// Such `AnalUnit`s are ready for immediate re-analysis. |
| 156 | 163 | /// See `findOutdatedToAnalyze` for details. |
| 157 | 164 | outdated_ready: std.AutoArrayHashMapUnmanaged(AnalUnit, void) = .{}, |
| 158 | /// This contains a set of Decls which may not be in `outdated`, but are the | |
| 159 | /// root Decls of files which have updated source and thus must be re-analyzed. | |
| 160 | /// If such a Decl is only in this set, the struct type index may be preserved | |
| 161 | /// (only the namespace might change). If such a Decl is also `outdated`, the | |
| 162 | /// struct type index must be recreated. | |
| 163 | outdated_file_root: std.AutoArrayHashMapUnmanaged(Decl.Index, void) = .{}, | |
| 165 | /// This contains a set of struct types whose corresponding `Cau` may not be in | |
| 166 | /// `outdated`, but are the root types of files which have updated source and | |
| 167 | /// thus must be re-analyzed. If such a type is only in this set, the struct type | |
| 168 | /// index may be preserved (only the namespace might change). If its owned `Cau` | |
| 169 | /// is also outdated, the struct type index must be recreated. | |
| 170 | outdated_file_root: std.AutoArrayHashMapUnmanaged(InternPool.Index, void) = .{}, | |
| 164 | 171 | /// This contains a list of AnalUnit whose analysis or codegen failed, but the |
| 165 | 172 | /// failure was something like running out of disk space, and trying again may |
| 166 | 173 | /// succeed. On the next update, we will flush this list, marking all members of |
| ... | ... | @@ -179,12 +186,9 @@ stage1_flags: packed struct { |
| 179 | 186 | |
| 180 | 187 | compile_log_text: std.ArrayListUnmanaged(u8) = .{}, |
| 181 | 188 | |
| 182 | emit_h: ?*GlobalEmitH, | |
| 183 | ||
| 184 | test_functions: std.AutoArrayHashMapUnmanaged(Decl.Index, void) = .{}, | |
| 189 | test_functions: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, void) = .{}, | |
| 185 | 190 | |
| 186 | /// TODO: the key here will be a `Cau.Index`. | |
| 187 | global_assembly: std.AutoArrayHashMapUnmanaged(Decl.Index, []u8) = .{}, | |
| 191 | global_assembly: std.AutoArrayHashMapUnmanaged(InternPool.Cau.Index, []u8) = .{}, | |
| 188 | 192 | |
| 189 | 193 | /// Key is the `AnalUnit` *performing* the reference. This representation allows |
| 190 | 194 | /// incremental updates to quickly delete references caused by a specific `AnalUnit`. |
| ... | ... | @@ -196,7 +200,7 @@ all_references: std.ArrayListUnmanaged(Reference) = .{}, |
| 196 | 200 | /// Freelist of indices in `all_references`. |
| 197 | 201 | free_references: std.ArrayListUnmanaged(u32) = .{}, |
| 198 | 202 | |
| 199 | panic_messages: [PanicId.len]Decl.OptionalIndex = .{.none} ** PanicId.len, | |
| 203 | panic_messages: [PanicId.len]InternPool.Nav.Index.Optional = .{.none} ** PanicId.len, | |
| 200 | 204 | /// The panic function body. |
| 201 | 205 | panic_func_index: InternPool.Index = .none, |
| 202 | 206 | null_stack_trace: InternPool.Index = .none, |
| ... | ... | @@ -250,45 +254,25 @@ pub const CImportError = struct { |
| 250 | 254 | } |
| 251 | 255 | }; |
| 252 | 256 | |
| 253 | /// A `Module` has zero or one of these depending on whether `-femit-h` is enabled. | |
| 254 | pub const GlobalEmitH = struct { | |
| 255 | /// Where to put the output. | |
| 256 | loc: Compilation.EmitLoc, | |
| 257 | /// When emit_h is non-null, each Decl gets one more compile error slot for | |
| 258 | /// emit-h failing for that Decl. This table is also how we tell if a Decl has | |
| 259 | /// failed emit-h or succeeded. | |
| 260 | failed_decls: std.AutoArrayHashMapUnmanaged(Decl.Index, *ErrorMsg) = .{}, | |
| 261 | /// Tracks all decls in order to iterate over them and emit .h code for them. | |
| 262 | decl_table: std.AutoArrayHashMapUnmanaged(Decl.Index, void) = .{}, | |
| 263 | /// Similar to the allocated_decls field of Module, this is where `EmitH` objects | |
| 264 | /// are allocated. There will be exactly one EmitH object per Decl object, with | |
| 265 | /// identical indexes. | |
| 266 | allocated_emit_h: std.SegmentedList(EmitH, 0) = .{}, | |
| 267 | ||
| 268 | pub fn declPtr(global_emit_h: *GlobalEmitH, decl_index: Decl.Index) *EmitH { | |
| 269 | return global_emit_h.allocated_emit_h.at(@intFromEnum(decl_index)); | |
| 270 | } | |
| 271 | }; | |
| 272 | ||
| 273 | 257 | pub const ErrorInt = u32; |
| 274 | 258 | |
| 275 | 259 | pub const Exported = union(enum) { |
| 276 | /// The Decl being exported. Note this is *not* the Decl performing the export. | |
| 277 | decl_index: Decl.Index, | |
| 260 | /// The Nav being exported. Note this is *not* the Nav corresponding to the AnalUnit performing the export. | |
| 261 | nav: InternPool.Nav.Index, | |
| 278 | 262 | /// Constant value being exported. |
| 279 | value: InternPool.Index, | |
| 263 | uav: InternPool.Index, | |
| 280 | 264 | |
| 281 | 265 | pub fn getValue(exported: Exported, zcu: *Zcu) Value { |
| 282 | 266 | return switch (exported) { |
| 283 | .decl_index => |decl_index| zcu.declPtr(decl_index).val, | |
| 284 | .value => |value| Value.fromInterned(value), | |
| 267 | .nav => |nav| zcu.navValue(nav), | |
| 268 | .uav => |uav| Value.fromInterned(uav), | |
| 285 | 269 | }; |
| 286 | 270 | } |
| 287 | 271 | |
| 288 | 272 | pub fn getAlign(exported: Exported, zcu: *Zcu) Alignment { |
| 289 | 273 | return switch (exported) { |
| 290 | .decl_index => |decl_index| zcu.declPtr(decl_index).alignment, | |
| 291 | .value => .none, | |
| 274 | .nav => |nav| zcu.intern_pool.getNav(nav).status.resolved.alignment, | |
| 275 | .uav => .none, | |
| 292 | 276 | }; |
| 293 | 277 | } |
| 294 | 278 | }; |
| ... | ... | @@ -324,302 +308,54 @@ pub const Reference = struct { |
| 324 | 308 | src: LazySrcLoc, |
| 325 | 309 | }; |
| 326 | 310 | |
| 327 | pub const Decl = struct { | |
| 328 | /// Equal to `fqn` if already fully qualified. | |
| 329 | name: InternPool.NullTerminatedString, | |
| 330 | /// Fully qualified name. | |
| 331 | fqn: InternPool.NullTerminatedString, | |
| 332 | /// The most recent Value of the Decl after a successful semantic analysis. | |
| 333 | /// Populated when `has_tv`. | |
| 334 | val: Value, | |
| 335 | /// Populated when `has_tv`. | |
| 336 | @"linksection": InternPool.OptionalNullTerminatedString, | |
| 337 | /// Populated when `has_tv`. | |
| 338 | alignment: Alignment, | |
| 339 | /// Populated when `has_tv`. | |
| 340 | @"addrspace": std.builtin.AddressSpace, | |
| 341 | /// The direct parent namespace of the Decl. In the case of the Decl | |
| 342 | /// corresponding to a file, this is the namespace of the struct, since | |
| 343 | /// there is no parent. | |
| 344 | src_namespace: Namespace.Index, | |
| 345 | ||
| 346 | /// Index of the ZIR `declaration` instruction from which this `Decl` was created. | |
| 347 | /// For the root `Decl` of a `File` and legacy anonymous decls, this is `.none`. | |
| 348 | zir_decl_index: InternPool.TrackedInst.Index.Optional, | |
| 349 | ||
| 350 | /// Represents the "shallow" analysis status. For example, for decls that are functions, | |
| 351 | /// the function type is analyzed with this set to `in_progress`, however, the semantic | |
| 352 | /// analysis of the function body is performed with this value set to `success`. Functions | |
| 353 | /// have their own analysis status field. | |
| 354 | analysis: enum { | |
| 355 | /// This Decl corresponds to an AST Node that has not been referenced yet, and therefore | |
| 356 | /// because of Zig's lazy declaration analysis, it will remain unanalyzed until referenced. | |
| 357 | unreferenced, | |
| 358 | /// Semantic analysis for this Decl is running right now. | |
| 359 | /// This state detects dependency loops. | |
| 360 | in_progress, | |
| 361 | /// The file corresponding to this Decl had a parse error or ZIR error. | |
| 362 | /// There will be a corresponding ErrorMsg in Zcu.failed_files. | |
| 363 | file_failure, | |
| 364 | /// This Decl might be OK but it depends on another one which did not | |
| 365 | /// successfully complete semantic analysis. | |
| 366 | dependency_failure, | |
| 367 | /// Semantic analysis failure. | |
| 368 | /// There will be a corresponding ErrorMsg in Zcu.failed_analysis. | |
| 369 | sema_failure, | |
| 370 | /// There will be a corresponding ErrorMsg in Zcu.failed_analysis. | |
| 371 | codegen_failure, | |
| 372 | /// Sematic analysis and constant value codegen of this Decl has | |
| 373 | /// succeeded. However, the Decl may be outdated due to an in-progress | |
| 374 | /// update. Note that for a function, this does not mean codegen of the | |
| 375 | /// function body succeded: that state is indicated by the function's | |
| 376 | /// `analysis` field. | |
| 377 | complete, | |
| 378 | }, | |
| 379 | /// Whether `typed_value`, `align`, `linksection` and `addrspace` are populated. | |
| 380 | has_tv: bool, | |
| 381 | /// If `true` it means the `Decl` is the resource owner of the type/value associated | |
| 382 | /// with it. That means when `Decl` is destroyed, the cleanup code should additionally | |
| 383 | /// check if the value owns a `Namespace`, and destroy that too. | |
| 384 | owns_tv: bool, | |
| 385 | /// Whether the corresponding AST decl has a `pub` keyword. | |
| 386 | is_pub: bool, | |
| 387 | /// Whether the corresponding AST decl has a `export` keyword. | |
| 388 | is_exported: bool, | |
| 389 | /// What kind of a declaration is this. | |
| 390 | kind: Kind, | |
| 391 | ||
| 392 | pub const Kind = enum { | |
| 393 | @"usingnamespace", | |
| 394 | @"test", | |
| 395 | @"comptime", | |
| 396 | named, | |
| 397 | anon, | |
| 398 | }; | |
| 399 | ||
| 400 | pub const Index = InternPool.DeclIndex; | |
| 401 | pub const OptionalIndex = InternPool.OptionalDeclIndex; | |
| 402 | ||
| 403 | pub fn zirBodies(decl: Decl, zcu: *Zcu) Zir.Inst.Declaration.Bodies { | |
| 404 | const zir = decl.getFileScope(zcu).zir; | |
| 405 | const zir_index = decl.zir_decl_index.unwrap().?.resolve(&zcu.intern_pool); | |
| 406 | const declaration = zir.instructions.items(.data)[@intFromEnum(zir_index)].declaration; | |
| 407 | const extra = zir.extraData(Zir.Inst.Declaration, declaration.payload_index); | |
| 408 | return extra.data.getBodies(@intCast(extra.end), zir); | |
| 409 | } | |
| 410 | ||
| 411 | pub fn typeOf(decl: Decl, zcu: *const Zcu) Type { | |
| 412 | assert(decl.has_tv); | |
| 413 | return decl.val.typeOf(zcu); | |
| 414 | } | |
| 415 | ||
| 416 | /// Small wrapper for Sema to use over direct access to the `val` field. | |
| 417 | /// If the value is not populated, instead returns `error.AnalysisFail`. | |
| 418 | pub fn valueOrFail(decl: Decl) error{AnalysisFail}!Value { | |
| 419 | if (!decl.has_tv) return error.AnalysisFail; | |
| 420 | return decl.val; | |
| 421 | } | |
| 422 | ||
| 423 | pub fn getOwnedFunction(decl: Decl, zcu: *Zcu) ?InternPool.Key.Func { | |
| 424 | const i = decl.getOwnedFunctionIndex(); | |
| 425 | if (i == .none) return null; | |
| 426 | return switch (zcu.intern_pool.indexToKey(i)) { | |
| 427 | .func => |func| func, | |
| 428 | else => null, | |
| 429 | }; | |
| 430 | } | |
| 431 | ||
| 432 | /// This returns an InternPool.Index even when the value is not a function. | |
| 433 | pub fn getOwnedFunctionIndex(decl: Decl) InternPool.Index { | |
| 434 | return if (decl.owns_tv) decl.val.toIntern() else .none; | |
| 435 | } | |
| 436 | ||
| 437 | /// If the Decl owns its value and it is an extern function, returns it, | |
| 438 | /// otherwise null. | |
| 439 | pub fn getOwnedExternFunc(decl: Decl, zcu: *Zcu) ?InternPool.Key.ExternFunc { | |
| 440 | return if (decl.owns_tv) decl.val.getExternFunc(zcu) else null; | |
| 441 | } | |
| 442 | ||
| 443 | /// If the Decl owns its value and it is a variable, returns it, | |
| 444 | /// otherwise null. | |
| 445 | pub fn getOwnedVariable(decl: Decl, zcu: *Zcu) ?InternPool.Key.Variable { | |
| 446 | return if (decl.owns_tv) decl.val.getVariable(zcu) else null; | |
| 447 | } | |
| 448 | ||
| 449 | /// Gets the namespace that this Decl creates by being a struct, union, | |
| 450 | /// enum, or opaque. | |
| 451 | pub fn getInnerNamespaceIndex(decl: Decl, zcu: *Zcu) Namespace.OptionalIndex { | |
| 452 | if (!decl.has_tv) return .none; | |
| 453 | const ip = &zcu.intern_pool; | |
| 454 | return switch (decl.val.ip_index) { | |
| 455 | .empty_struct_type => .none, | |
| 456 | .none => .none, | |
| 457 | else => switch (ip.indexToKey(decl.val.toIntern())) { | |
| 458 | .opaque_type => ip.loadOpaqueType(decl.val.toIntern()).namespace, | |
| 459 | .struct_type => ip.loadStructType(decl.val.toIntern()).namespace, | |
| 460 | .union_type => ip.loadUnionType(decl.val.toIntern()).namespace, | |
| 461 | .enum_type => ip.loadEnumType(decl.val.toIntern()).namespace, | |
| 462 | else => .none, | |
| 463 | }, | |
| 464 | }; | |
| 465 | } | |
| 466 | ||
| 467 | /// Like `getInnerNamespaceIndex`, but only returns it if the Decl is the owner. | |
| 468 | pub fn getOwnedInnerNamespaceIndex(decl: Decl, zcu: *Zcu) Namespace.OptionalIndex { | |
| 469 | if (!decl.owns_tv) return .none; | |
| 470 | return decl.getInnerNamespaceIndex(zcu); | |
| 471 | } | |
| 472 | ||
| 473 | /// Same as `getOwnedInnerNamespaceIndex` but additionally obtains the pointer. | |
| 474 | pub fn getOwnedInnerNamespace(decl: Decl, zcu: *Zcu) ?*Namespace { | |
| 475 | return zcu.namespacePtrUnwrap(decl.getOwnedInnerNamespaceIndex(zcu)); | |
| 476 | } | |
| 477 | ||
| 478 | /// Same as `getInnerNamespaceIndex` but additionally obtains the pointer. | |
| 479 | pub fn getInnerNamespace(decl: Decl, zcu: *Zcu) ?*Namespace { | |
| 480 | return zcu.namespacePtrUnwrap(decl.getInnerNamespaceIndex(zcu)); | |
| 481 | } | |
| 482 | ||
| 483 | pub fn getFileScope(decl: Decl, zcu: *Zcu) *File { | |
| 484 | return zcu.fileByIndex(getFileScopeIndex(decl, zcu)); | |
| 485 | } | |
| 486 | ||
| 487 | pub fn getFileScopeIndex(decl: Decl, zcu: *Zcu) File.Index { | |
| 488 | return zcu.namespacePtr(decl.src_namespace).file_scope; | |
| 489 | } | |
| 490 | ||
| 491 | pub fn getExternDecl(decl: Decl, zcu: *Zcu) OptionalIndex { | |
| 492 | assert(decl.has_tv); | |
| 493 | return switch (zcu.intern_pool.indexToKey(decl.val.toIntern())) { | |
| 494 | .variable => |variable| if (variable.is_extern) variable.decl.toOptional() else .none, | |
| 495 | .extern_func => |extern_func| extern_func.decl.toOptional(), | |
| 496 | else => .none, | |
| 497 | }; | |
| 498 | } | |
| 499 | ||
| 500 | pub fn isExtern(decl: Decl, zcu: *Zcu) bool { | |
| 501 | return decl.getExternDecl(zcu) != .none; | |
| 502 | } | |
| 503 | ||
| 504 | pub fn getAlignment(decl: Decl, pt: Zcu.PerThread) Alignment { | |
| 505 | assert(decl.has_tv); | |
| 506 | if (decl.alignment != .none) return decl.alignment; | |
| 507 | return decl.typeOf(pt.zcu).abiAlignment(pt); | |
| 508 | } | |
| 509 | ||
| 510 | pub fn declPtrType(decl: Decl, pt: Zcu.PerThread) !Type { | |
| 511 | assert(decl.has_tv); | |
| 512 | const decl_ty = decl.typeOf(pt.zcu); | |
| 513 | return pt.ptrType(.{ | |
| 514 | .child = decl_ty.toIntern(), | |
| 515 | .flags = .{ | |
| 516 | .alignment = if (decl.alignment == decl_ty.abiAlignment(pt)) | |
| 517 | .none | |
| 518 | else | |
| 519 | decl.alignment, | |
| 520 | .address_space = decl.@"addrspace", | |
| 521 | .is_const = decl.getOwnedVariable(pt.zcu) == null, | |
| 522 | }, | |
| 523 | }); | |
| 524 | } | |
| 525 | ||
| 526 | /// Returns the source location of this `Decl`. | |
| 527 | /// Asserts that this `Decl` corresponds to what will in future be a `Nav` (Named | |
| 528 | /// Addressable Value): a source-level declaration or generic instantiation. | |
| 529 | pub fn navSrcLoc(decl: Decl, zcu: *Zcu) LazySrcLoc { | |
| 530 | return .{ | |
| 531 | .base_node_inst = decl.zir_decl_index.unwrap() orelse inst: { | |
| 532 | // generic instantiation | |
| 533 | assert(decl.has_tv); | |
| 534 | assert(decl.owns_tv); | |
| 535 | const owner = zcu.funcInfo(decl.val.toIntern()).generic_owner; | |
| 536 | const generic_owner_decl = zcu.declPtr(zcu.funcInfo(owner).owner_decl); | |
| 537 | break :inst generic_owner_decl.zir_decl_index.unwrap().?; | |
| 538 | }, | |
| 539 | .offset = LazySrcLoc.Offset.nodeOffset(0), | |
| 540 | }; | |
| 541 | } | |
| 542 | ||
| 543 | pub fn navSrcLine(decl: Decl, zcu: *Zcu) u32 { | |
| 544 | const ip = &zcu.intern_pool; | |
| 545 | const tracked = decl.zir_decl_index.unwrap() orelse inst: { | |
| 546 | // generic instantiation | |
| 547 | assert(decl.has_tv); | |
| 548 | assert(decl.owns_tv); | |
| 549 | const generic_owner_func = switch (ip.indexToKey(decl.val.toIntern())) { | |
| 550 | .func => |func| func.generic_owner, | |
| 551 | else => return 0, // TODO: this is probably a `variable` or something; figure this out when we finish sorting out `Decl`. | |
| 552 | }; | |
| 553 | const generic_owner_decl = zcu.declPtr(zcu.funcInfo(generic_owner_func).owner_decl); | |
| 554 | break :inst generic_owner_decl.zir_decl_index.unwrap().?; | |
| 555 | }; | |
| 556 | const info = tracked.resolveFull(ip); | |
| 557 | const file = zcu.fileByIndex(info.file); | |
| 558 | assert(file.zir_loaded); | |
| 559 | const zir = file.zir; | |
| 560 | const inst = zir.instructions.get(@intFromEnum(info.inst)); | |
| 561 | assert(inst.tag == .declaration); | |
| 562 | return zir.extraData(Zir.Inst.Declaration, inst.data.declaration.payload_index).data.src_line; | |
| 563 | } | |
| 564 | ||
| 565 | pub fn typeSrcLine(decl: Decl, zcu: *Zcu) u32 { | |
| 566 | assert(decl.has_tv); | |
| 567 | assert(decl.owns_tv); | |
| 568 | return decl.val.toType().typeDeclSrcLine(zcu).?; | |
| 569 | } | |
| 570 | }; | |
| 571 | ||
| 572 | /// This state is attached to every Decl when Module emit_h is non-null. | |
| 573 | pub const EmitH = struct { | |
| 574 | fwd_decl: std.ArrayListUnmanaged(u8) = .{}, | |
| 575 | }; | |
| 576 | ||
| 577 | pub const DeclAdapter = struct { | |
| 578 | zcu: *Zcu, | |
| 579 | ||
| 580 | pub fn hash(self: @This(), s: InternPool.NullTerminatedString) u32 { | |
| 581 | _ = self; | |
| 582 | return std.hash.uint32(@intFromEnum(s)); | |
| 583 | } | |
| 584 | ||
| 585 | pub fn eql(self: @This(), a: InternPool.NullTerminatedString, b_decl_index: Decl.Index, b_index: usize) bool { | |
| 586 | _ = b_index; | |
| 587 | return a == self.zcu.declPtr(b_decl_index).name; | |
| 588 | } | |
| 589 | }; | |
| 590 | ||
| 591 | 311 | /// The container that structs, enums, unions, and opaques have. |
| 592 | 312 | pub const Namespace = struct { |
| 593 | 313 | parent: OptionalIndex, |
| 594 | 314 | file_scope: File.Index, |
| 595 | 315 | /// Will be a struct, enum, union, or opaque. |
| 596 | decl_index: Decl.Index, | |
| 597 | /// Direct children of the namespace. | |
| 598 | /// Declaration order is preserved via entry order. | |
| 599 | /// These are only declarations named directly by the AST; anonymous | |
| 600 | /// declarations are not stored here. | |
| 601 | decls: std.ArrayHashMapUnmanaged(Decl.Index, void, DeclContext, true) = .{}, | |
| 602 | /// Key is usingnamespace Decl itself. To find the namespace being included, | |
| 603 | /// the Decl Value has to be resolved as a Type which has a Namespace. | |
| 604 | /// Value is whether the usingnamespace decl is marked `pub`. | |
| 605 | usingnamespace_set: std.AutoHashMapUnmanaged(Decl.Index, bool) = .{}, | |
| 316 | owner_type: InternPool.Index, | |
| 317 | /// Members of the namespace which are marked `pub`. | |
| 318 | pub_decls: std.ArrayHashMapUnmanaged(InternPool.Nav.Index, void, NavNameContext, true) = .{}, | |
| 319 | /// Members of the namespace which are *not* marked `pub`. | |
| 320 | priv_decls: std.ArrayHashMapUnmanaged(InternPool.Nav.Index, void, NavNameContext, true) = .{}, | |
| 321 | /// All `usingnamespace` declarations in this namespace which are marked `pub`. | |
| 322 | pub_usingnamespace: std.ArrayListUnmanaged(InternPool.Nav.Index) = .{}, | |
| 323 | /// All `usingnamespace` declarations in this namespace which are *not* marked `pub`. | |
| 324 | priv_usingnamespace: std.ArrayListUnmanaged(InternPool.Nav.Index) = .{}, | |
| 325 | /// All `comptime` and `test` declarations in this namespace. We store these purely so that | |
| 326 | /// incremental compilation can re-use the existing `Cau`s when a namespace changes. | |
| 327 | other_decls: std.ArrayListUnmanaged(InternPool.Cau.Index) = .{}, | |
| 606 | 328 | |
| 607 | 329 | pub const Index = InternPool.NamespaceIndex; |
| 608 | 330 | pub const OptionalIndex = InternPool.OptionalNamespaceIndex; |
| 609 | 331 | |
| 610 | const DeclContext = struct { | |
| 332 | const NavNameContext = struct { | |
| 611 | 333 | zcu: *Zcu, |
| 612 | 334 | |
| 613 | pub fn hash(ctx: @This(), decl_index: Decl.Index) u32 { | |
| 614 | const decl = ctx.zcu.declPtr(decl_index); | |
| 615 | return std.hash.uint32(@intFromEnum(decl.name)); | |
| 335 | pub fn hash(ctx: NavNameContext, nav: InternPool.Nav.Index) u32 { | |
| 336 | const name = ctx.zcu.intern_pool.getNav(nav).name; | |
| 337 | return std.hash.uint32(@intFromEnum(name)); | |
| 616 | 338 | } |
| 617 | 339 | |
| 618 | pub fn eql(ctx: @This(), a_decl_index: Decl.Index, b_decl_index: Decl.Index, b_index: usize) bool { | |
| 340 | pub fn eql(ctx: NavNameContext, a_nav: InternPool.Nav.Index, b_nav: InternPool.Nav.Index, b_index: usize) bool { | |
| 619 | 341 | _ = b_index; |
| 620 | const a_decl = ctx.zcu.declPtr(a_decl_index); | |
| 621 | const b_decl = ctx.zcu.declPtr(b_decl_index); | |
| 622 | return a_decl.name == b_decl.name; | |
| 342 | const a_name = ctx.zcu.intern_pool.getNav(a_nav).name; | |
| 343 | const b_name = ctx.zcu.intern_pool.getNav(b_nav).name; | |
| 344 | return a_name == b_name; | |
| 345 | } | |
| 346 | }; | |
| 347 | ||
| 348 | pub const NameAdapter = struct { | |
| 349 | zcu: *Zcu, | |
| 350 | ||
| 351 | pub fn hash(ctx: NameAdapter, s: InternPool.NullTerminatedString) u32 { | |
| 352 | _ = ctx; | |
| 353 | return std.hash.uint32(@intFromEnum(s)); | |
| 354 | } | |
| 355 | ||
| 356 | pub fn eql(ctx: NameAdapter, a: InternPool.NullTerminatedString, b_nav: InternPool.Nav.Index, b_index: usize) bool { | |
| 357 | _ = b_index; | |
| 358 | return a == ctx.zcu.intern_pool.getNav(b_nav).name; | |
| 623 | 359 | } |
| 624 | 360 | }; |
| 625 | 361 | |
| ... | ... | @@ -631,25 +367,6 @@ pub const Namespace = struct { |
| 631 | 367 | return ip.filePtr(ns.file_scope); |
| 632 | 368 | } |
| 633 | 369 | |
| 634 | // This renders e.g. "std.fs.Dir.OpenOptions" | |
| 635 | pub fn renderFullyQualifiedName( | |
| 636 | ns: Namespace, | |
| 637 | ip: *InternPool, | |
| 638 | name: InternPool.NullTerminatedString, | |
| 639 | writer: anytype, | |
| 640 | ) @TypeOf(writer).Error!void { | |
| 641 | if (ns.parent.unwrap()) |parent| { | |
| 642 | try ip.namespacePtr(parent).renderFullyQualifiedName( | |
| 643 | ip, | |
| 644 | ip.declPtr(ns.decl_index).name, | |
| 645 | writer, | |
| 646 | ); | |
| 647 | } else { | |
| 648 | try ns.fileScopeIp(ip).renderFullyQualifiedName(writer); | |
| 649 | } | |
| 650 | if (name != .empty) try writer.print(".{}", .{name.fmt(ip)}); | |
| 651 | } | |
| 652 | ||
| 653 | 370 | /// This renders e.g. "std/fs.zig:Dir.OpenOptions" |
| 654 | 371 | pub fn renderFullyQualifiedDebugName( |
| 655 | 372 | ns: Namespace, |
| ... | ... | @@ -678,44 +395,9 @@ pub const Namespace = struct { |
| 678 | 395 | tid: Zcu.PerThread.Id, |
| 679 | 396 | name: InternPool.NullTerminatedString, |
| 680 | 397 | ) !InternPool.NullTerminatedString { |
| 681 | const strings = ip.getLocal(tid).getMutableStrings(gpa); | |
| 682 | // Protects reads of interned strings from being reallocated during the call to | |
| 683 | // renderFullyQualifiedName. | |
| 684 | const slice = try strings.addManyAsSlice(count: { | |
| 685 | var count: usize = name.length(ip) + 1; | |
| 686 | var cur_ns = &ns; | |
| 687 | while (true) { | |
| 688 | const decl = ip.declPtr(cur_ns.decl_index); | |
| 689 | cur_ns = ip.namespacePtr(cur_ns.parent.unwrap() orelse { | |
| 690 | count += ns.fileScopeIp(ip).fullyQualifiedNameLen(); | |
| 691 | break :count count; | |
| 692 | }); | |
| 693 | count += decl.name.length(ip) + 1; | |
| 694 | } | |
| 695 | }); | |
| 696 | var fbs = std.io.fixedBufferStream(slice[0]); | |
| 697 | ns.renderFullyQualifiedName(ip, name, fbs.writer()) catch unreachable; | |
| 698 | assert(fbs.pos == slice[0].len); | |
| 699 | ||
| 700 | // Sanitize the name for nvptx which is more restrictive. | |
| 701 | // TODO This should be handled by the backend, not the frontend. Have a | |
| 702 | // look at how the C backend does it for inspiration. | |
| 703 | // FIXME This has bitrotted and is no longer able to be implemented here. | |
| 704 | //const cpu_arch = zcu.root_mod.resolved_target.result.cpu.arch; | |
| 705 | //if (cpu_arch.isNvptx()) { | |
| 706 | // for (slice[0]) |*byte| switch (byte.*) { | |
| 707 | // '{', '}', '*', '[', ']', '(', ')', ',', ' ', '\'' => byte.* = '_', | |
| 708 | // else => {}, | |
| 709 | // }; | |
| 710 | //} | |
| 711 | ||
| 712 | return ip.getOrPutTrailingString(gpa, tid, @intCast(slice[0].len), .no_embedded_nulls); | |
| 713 | } | |
| 714 | ||
| 715 | pub fn getType(ns: Namespace, zcu: *Zcu) Type { | |
| 716 | const decl = zcu.declPtr(ns.decl_index); | |
| 717 | assert(decl.has_tv); | |
| 718 | return decl.val.toType(); | |
| 398 | const ns_name = Type.fromInterned(ns.owner_type).containerTypeName(ip); | |
| 399 | if (name == .empty) return ns_name; | |
| 400 | return ip.getOrPutStringFmt(gpa, tid, "{}.{}", .{ ns_name.fmt(ip), name.fmt(ip) }, .no_embedded_nulls); | |
| 719 | 401 | } |
| 720 | 402 | }; |
| 721 | 403 | |
| ... | ... | @@ -2428,16 +2110,13 @@ pub fn deinit(zcu: *Zcu) void { |
| 2428 | 2110 | for (zcu.failed_analysis.values()) |value| { |
| 2429 | 2111 | value.destroy(gpa); |
| 2430 | 2112 | } |
| 2431 | zcu.failed_analysis.deinit(gpa); | |
| 2432 | ||
| 2433 | if (zcu.emit_h) |emit_h| { | |
| 2434 | for (emit_h.failed_decls.values()) |value| { | |
| 2435 | value.destroy(gpa); | |
| 2436 | } | |
| 2437 | emit_h.failed_decls.deinit(gpa); | |
| 2438 | emit_h.decl_table.deinit(gpa); | |
| 2439 | emit_h.allocated_emit_h.deinit(gpa); | |
| 2113 | for (zcu.failed_codegen.values()) |value| { | |
| 2114 | value.destroy(gpa); | |
| 2440 | 2115 | } |
| 2116 | zcu.analysis_in_progress.deinit(gpa); | |
| 2117 | zcu.failed_analysis.deinit(gpa); | |
| 2118 | zcu.transitive_failed_analysis.deinit(gpa); | |
| 2119 | zcu.failed_codegen.deinit(gpa); | |
| 2441 | 2120 | |
| 2442 | 2121 | for (zcu.failed_files.values()) |value| { |
| 2443 | 2122 | if (value) |msg| msg.destroy(gpa); |
| ... | ... | @@ -2486,26 +2165,14 @@ pub fn deinit(zcu: *Zcu) void { |
| 2486 | 2165 | zcu.intern_pool.deinit(gpa); |
| 2487 | 2166 | } |
| 2488 | 2167 | |
| 2489 | pub fn declPtr(mod: *Zcu, index: Decl.Index) *Decl { | |
| 2490 | return mod.intern_pool.declPtr(index); | |
| 2491 | } | |
| 2492 | ||
| 2493 | pub fn namespacePtr(mod: *Zcu, index: Namespace.Index) *Namespace { | |
| 2494 | return mod.intern_pool.namespacePtr(index); | |
| 2168 | pub fn namespacePtr(zcu: *Zcu, index: Namespace.Index) *Namespace { | |
| 2169 | return zcu.intern_pool.namespacePtr(index); | |
| 2495 | 2170 | } |
| 2496 | 2171 | |
| 2497 | 2172 | pub fn namespacePtrUnwrap(mod: *Zcu, index: Namespace.OptionalIndex) ?*Namespace { |
| 2498 | 2173 | return mod.namespacePtr(index.unwrap() orelse return null); |
| 2499 | 2174 | } |
| 2500 | 2175 | |
| 2501 | /// Returns true if and only if the Decl is the top level struct associated with a File. | |
| 2502 | pub fn declIsRoot(mod: *Zcu, decl_index: Decl.Index) bool { | |
| 2503 | const decl = mod.declPtr(decl_index); | |
| 2504 | const namespace = mod.namespacePtr(decl.src_namespace); | |
| 2505 | if (namespace.parent != .none) return false; | |
| 2506 | return decl_index == namespace.decl_index; | |
| 2507 | } | |
| 2508 | ||
| 2509 | 2176 | // TODO https://github.com/ziglang/zig/issues/8643 |
| 2510 | 2177 | pub const data_has_safety_tag = @sizeOf(Zir.Inst.Data) != 8; |
| 2511 | 2178 | pub const HackDataLayout = extern struct { |
| ... | ... | @@ -2642,8 +2309,12 @@ pub fn markPoDependeeUpToDate(zcu: *Zcu, dependee: InternPool.Dependee) !void { |
| 2642 | 2309 | // If this is a Decl, we must recursively mark dependencies on its tyval |
| 2643 | 2310 | // as no longer PO. |
| 2644 | 2311 | switch (depender.unwrap()) { |
| 2645 | .decl => |decl_index| try zcu.markPoDependeeUpToDate(.{ .decl_val = decl_index }), | |
| 2646 | .func => |func_index| try zcu.markPoDependeeUpToDate(.{ .func_ies = func_index }), | |
| 2312 | .cau => |cau| switch (zcu.intern_pool.getCau(cau).owner.unwrap()) { | |
| 2313 | .nav => |nav| try zcu.markPoDependeeUpToDate(.{ .nav_val = nav }), | |
| 2314 | .type => |ty| try zcu.markPoDependeeUpToDate(.{ .interned = ty }), | |
| 2315 | .none => {}, | |
| 2316 | }, | |
| 2317 | .func => |func| try zcu.markPoDependeeUpToDate(.{ .interned = func }), | |
| 2647 | 2318 | } |
| 2648 | 2319 | } |
| 2649 | 2320 | } |
| ... | ... | @@ -2651,9 +2322,13 @@ pub fn markPoDependeeUpToDate(zcu: *Zcu, dependee: InternPool.Dependee) !void { |
| 2651 | 2322 | /// Given a AnalUnit which is newly outdated or PO, mark all AnalUnits which may |
| 2652 | 2323 | /// in turn be PO, due to a dependency on the original AnalUnit's tyval or IES. |
| 2653 | 2324 | fn markTransitiveDependersPotentiallyOutdated(zcu: *Zcu, maybe_outdated: AnalUnit) !void { |
| 2654 | var it = zcu.intern_pool.dependencyIterator(switch (maybe_outdated.unwrap()) { | |
| 2655 | .decl => |decl_index| .{ .decl_val = decl_index }, // TODO: also `decl_ref` deps when introduced | |
| 2656 | .func => |func_index| .{ .func_ies = func_index }, | |
| 2325 | const ip = &zcu.intern_pool; | |
| 2326 | var it = ip.dependencyIterator(switch (maybe_outdated.unwrap()) { | |
| 2327 | .cau => |cau| switch (ip.getCau(cau).owner.unwrap()) { | |
| 2328 | .nav => |nav| .{ .nav_val = nav }, // TODO: also `nav_ref` deps when introduced | |
| 2329 | .none, .type => return, // analysis of this `Cau` can't outdate any dependencies | |
| 2330 | }, | |
| 2331 | .func => |func_index| .{ .interned = func_index }, // IES | |
| 2657 | 2332 | }); |
| 2658 | 2333 | |
| 2659 | 2334 | while (it.next()) |po| { |
| ... | ... | @@ -2680,6 +2355,8 @@ fn markTransitiveDependersPotentiallyOutdated(zcu: *Zcu, maybe_outdated: AnalUni |
| 2680 | 2355 | pub fn findOutdatedToAnalyze(zcu: *Zcu) Allocator.Error!?AnalUnit { |
| 2681 | 2356 | if (!zcu.comp.incremental) return null; |
| 2682 | 2357 | |
| 2358 | if (true) @panic("TODO: findOutdatedToAnalyze"); | |
| 2359 | ||
| 2683 | 2360 | if (zcu.outdated.count() == 0 and zcu.potentially_outdated.count() == 0) { |
| 2684 | 2361 | log.debug("findOutdatedToAnalyze: no outdated depender", .{}); |
| 2685 | 2362 | return null; |
| ... | ... | @@ -2742,6 +2419,8 @@ pub fn findOutdatedToAnalyze(zcu: *Zcu) Allocator.Error!?AnalUnit { |
| 2742 | 2419 | zcu.potentially_outdated.count(), |
| 2743 | 2420 | }); |
| 2744 | 2421 | |
| 2422 | const Decl = {}; | |
| 2423 | ||
| 2745 | 2424 | var chosen_decl_idx: ?Decl.Index = null; |
| 2746 | 2425 | var chosen_decl_dependers: u32 = undefined; |
| 2747 | 2426 | |
| ... | ... | @@ -2939,65 +2618,20 @@ pub fn mapOldZirToNew( |
| 2939 | 2618 | /// analyzed, and for ensuring it can exist at runtime (see |
| 2940 | 2619 | /// `sema.fnHasRuntimeBits`). This function does *not* guarantee that the body |
| 2941 | 2620 | /// will be analyzed when it returns: for that, see `ensureFuncBodyAnalyzed`. |
| 2942 | pub fn ensureFuncBodyAnalysisQueued(mod: *Zcu, func_index: InternPool.Index) !void { | |
| 2943 | const ip = &mod.intern_pool; | |
| 2944 | const func = mod.funcInfo(func_index); | |
| 2945 | const decl_index = func.owner_decl; | |
| 2946 | const decl = mod.declPtr(decl_index); | |
| 2947 | ||
| 2948 | switch (decl.analysis) { | |
| 2949 | .unreferenced => unreachable, | |
| 2950 | .in_progress => unreachable, | |
| 2951 | ||
| 2952 | .file_failure, | |
| 2953 | .sema_failure, | |
| 2954 | .codegen_failure, | |
| 2955 | .dependency_failure, | |
| 2956 | // Analysis of the function Decl itself failed, but we've already | |
| 2957 | // emitted an error for that. The callee doesn't need the function to be | |
| 2958 | // analyzed right now, so its analysis can safely continue. | |
| 2959 | => return, | |
| 2960 | ||
| 2961 | .complete => {}, | |
| 2962 | } | |
| 2963 | ||
| 2964 | assert(decl.has_tv); | |
| 2965 | ||
| 2966 | const func_as_depender = AnalUnit.wrap(.{ .func = func_index }); | |
| 2967 | const is_outdated = mod.outdated.contains(func_as_depender) or | |
| 2968 | mod.potentially_outdated.contains(func_as_depender); | |
| 2621 | pub fn ensureFuncBodyAnalysisQueued(zcu: *Zcu, func_index: InternPool.Index) !void { | |
| 2622 | const ip = &zcu.intern_pool; | |
| 2623 | const func = zcu.funcInfo(func_index); | |
| 2969 | 2624 | |
| 2970 | 2625 | switch (func.analysisUnordered(ip).state) { |
| 2971 | .none => {}, | |
| 2972 | .queued => return, | |
| 2973 | // As above, we don't need to forward errors here. | |
| 2974 | .sema_failure, | |
| 2975 | .dependency_failure, | |
| 2976 | .codegen_failure, | |
| 2977 | .success, | |
| 2978 | => if (!is_outdated) return, | |
| 2979 | .in_progress => return, | |
| 2980 | .inline_only => unreachable, // don't queue work for this | |
| 2981 | } | |
| 2982 | ||
| 2983 | // Decl itself is safely analyzed, and body analysis is not yet queued | |
| 2984 | ||
| 2985 | try mod.comp.queueJob(.{ .analyze_func = func_index }); | |
| 2986 | if (mod.emit_h != null) { | |
| 2987 | // TODO: we ideally only want to do this if the function's type changed | |
| 2988 | // since the last update | |
| 2989 | try mod.comp.queueJob(.{ .emit_h_decl = decl_index }); | |
| 2626 | .unreferenced => {}, // We're the first reference! | |
| 2627 | .queued => return, // Analysis is already queued. | |
| 2628 | .analyzed => return, // Analysis is complete; if it's out-of-date, it'll be re-analyzed later this update. | |
| 2990 | 2629 | } |
| 2630 | ||
| 2631 | try zcu.comp.queueJob(.{ .analyze_func = func_index }); | |
| 2991 | 2632 | func.setAnalysisState(ip, .queued); |
| 2992 | 2633 | } |
| 2993 | 2634 | |
| 2994 | pub const SemaDeclResult = packed struct { | |
| 2995 | /// Whether the value of a `decl_val` of this Decl changed. | |
| 2996 | invalidate_decl_val: bool, | |
| 2997 | /// Whether the type of a `decl_ref` of this Decl changed. | |
| 2998 | invalidate_decl_ref: bool, | |
| 2999 | }; | |
| 3000 | ||
| 3001 | 2635 | pub const ImportFileResult = struct { |
| 3002 | 2636 | file: *File, |
| 3003 | 2637 | file_index: File.Index, |
| ... | ... | @@ -3171,14 +2805,15 @@ pub fn handleUpdateExports( |
| 3171 | 2805 | }; |
| 3172 | 2806 | } |
| 3173 | 2807 | |
| 3174 | pub fn addGlobalAssembly(mod: *Zcu, decl_index: Decl.Index, source: []const u8) !void { | |
| 3175 | const gop = try mod.global_assembly.getOrPut(mod.gpa, decl_index); | |
| 2808 | pub fn addGlobalAssembly(zcu: *Zcu, cau: InternPool.Cau.Index, source: []const u8) !void { | |
| 2809 | const gpa = zcu.gpa; | |
| 2810 | const gop = try zcu.global_assembly.getOrPut(gpa, cau); | |
| 3176 | 2811 | if (gop.found_existing) { |
| 3177 | const new_value = try std.fmt.allocPrint(mod.gpa, "{s}\n{s}", .{ gop.value_ptr.*, source }); | |
| 3178 | mod.gpa.free(gop.value_ptr.*); | |
| 2812 | const new_value = try std.fmt.allocPrint(gpa, "{s}\n{s}", .{ gop.value_ptr.*, source }); | |
| 2813 | gpa.free(gop.value_ptr.*); | |
| 3179 | 2814 | gop.value_ptr.* = new_value; |
| 3180 | 2815 | } else { |
| 3181 | gop.value_ptr.* = try mod.gpa.dupe(u8, source); | |
| 2816 | gop.value_ptr.* = try gpa.dupe(u8, source); | |
| 3182 | 2817 | } |
| 3183 | 2818 | } |
| 3184 | 2819 | |
| ... | ... | @@ -3315,10 +2950,6 @@ pub fn atomicPtrAlignment( |
| 3315 | 2950 | return error.BadType; |
| 3316 | 2951 | } |
| 3317 | 2952 | |
| 3318 | pub fn declFileScope(mod: *Zcu, decl_index: Decl.Index) *File { | |
| 3319 | return mod.declPtr(decl_index).getFileScope(mod); | |
| 3320 | } | |
| 3321 | ||
| 3322 | 2953 | /// Returns null in the following cases: |
| 3323 | 2954 | /// * `@TypeOf(.{})` |
| 3324 | 2955 | /// * A struct which has no fields (`struct {}`). |
| ... | ... | @@ -3352,16 +2983,8 @@ pub fn typeToFunc(mod: *Zcu, ty: Type) ?InternPool.Key.FuncType { |
| 3352 | 2983 | return mod.intern_pool.indexToFuncType(ty.toIntern()); |
| 3353 | 2984 | } |
| 3354 | 2985 | |
| 3355 | pub fn funcOwnerDeclPtr(mod: *Zcu, func_index: InternPool.Index) *Decl { | |
| 3356 | return mod.declPtr(mod.funcOwnerDeclIndex(func_index)); | |
| 3357 | } | |
| 3358 | ||
| 3359 | pub fn funcOwnerDeclIndex(mod: *Zcu, func_index: InternPool.Index) Decl.Index { | |
| 3360 | return mod.funcInfo(func_index).owner_decl; | |
| 3361 | } | |
| 3362 | ||
| 3363 | pub fn iesFuncIndex(mod: *const Zcu, ies_index: InternPool.Index) InternPool.Index { | |
| 3364 | return mod.intern_pool.iesFuncIndex(ies_index); | |
| 2986 | pub fn iesFuncIndex(zcu: *const Zcu, ies_index: InternPool.Index) InternPool.Index { | |
| 2987 | return zcu.intern_pool.iesFuncIndex(ies_index); | |
| 3365 | 2988 | } |
| 3366 | 2989 | |
| 3367 | 2990 | pub fn funcInfo(mod: *Zcu, func_index: InternPool.Index) InternPool.Key.Func { |
| ... | ... | @@ -3372,44 +2995,6 @@ pub fn toEnum(mod: *Zcu, comptime E: type, val: Value) E { |
| 3372 | 2995 | return mod.intern_pool.toEnum(E, val.toIntern()); |
| 3373 | 2996 | } |
| 3374 | 2997 | |
| 3375 | pub fn isAnytypeParam(mod: *Zcu, func: InternPool.Index, index: u32) bool { | |
| 3376 | const file = mod.declPtr(func.owner_decl).getFileScope(mod); | |
| 3377 | ||
| 3378 | const tags = file.zir.instructions.items(.tag); | |
| 3379 | ||
| 3380 | const param_body = file.zir.getParamBody(func.zir_body_inst); | |
| 3381 | const param = param_body[index]; | |
| 3382 | ||
| 3383 | return switch (tags[param]) { | |
| 3384 | .param, .param_comptime => false, | |
| 3385 | .param_anytype, .param_anytype_comptime => true, | |
| 3386 | else => unreachable, | |
| 3387 | }; | |
| 3388 | } | |
| 3389 | ||
| 3390 | pub fn getParamName(mod: *Zcu, func_index: InternPool.Index, index: u32) [:0]const u8 { | |
| 3391 | const func = mod.funcInfo(func_index); | |
| 3392 | const file = mod.declPtr(func.owner_decl).getFileScope(mod); | |
| 3393 | ||
| 3394 | const tags = file.zir.instructions.items(.tag); | |
| 3395 | const data = file.zir.instructions.items(.data); | |
| 3396 | ||
| 3397 | const param_body = file.zir.getParamBody(func.zir_body_inst.resolve(&mod.intern_pool)); | |
| 3398 | const param = param_body[index]; | |
| 3399 | ||
| 3400 | return switch (tags[@intFromEnum(param)]) { | |
| 3401 | .param, .param_comptime => blk: { | |
| 3402 | const extra = file.zir.extraData(Zir.Inst.Param, data[@intFromEnum(param)].pl_tok.payload_index); | |
| 3403 | break :blk file.zir.nullTerminatedString(extra.data.name); | |
| 3404 | }, | |
| 3405 | .param_anytype, .param_anytype_comptime => blk: { | |
| 3406 | const param_data = data[@intFromEnum(param)].str_tok; | |
| 3407 | break :blk param_data.get(file.zir); | |
| 3408 | }, | |
| 3409 | else => unreachable, | |
| 3410 | }; | |
| 3411 | } | |
| 3412 | ||
| 3413 | 2998 | pub const UnionLayout = struct { |
| 3414 | 2999 | abi_size: u64, |
| 3415 | 3000 | abi_align: Alignment, |
| ... | ... | @@ -3468,19 +3053,20 @@ pub fn fileByIndex(zcu: *Zcu, file_index: File.Index) *File { |
| 3468 | 3053 | return zcu.intern_pool.filePtr(file_index); |
| 3469 | 3054 | } |
| 3470 | 3055 | |
| 3471 | /// Returns the `Decl` of the struct that represents this `File`. | |
| 3472 | pub fn fileRootDecl(zcu: *const Zcu, file_index: File.Index) Decl.OptionalIndex { | |
| 3056 | /// Returns the struct that represents this `File`. | |
| 3057 | /// If the struct has not been created, returns `.none`. | |
| 3058 | pub fn fileRootType(zcu: *const Zcu, file_index: File.Index) InternPool.Index { | |
| 3473 | 3059 | const ip = &zcu.intern_pool; |
| 3474 | 3060 | const file_index_unwrapped = file_index.unwrap(ip); |
| 3475 | 3061 | const files = ip.getLocalShared(file_index_unwrapped.tid).files.acquire(); |
| 3476 | return files.view().items(.root_decl)[file_index_unwrapped.index]; | |
| 3062 | return files.view().items(.root_type)[file_index_unwrapped.index]; | |
| 3477 | 3063 | } |
| 3478 | 3064 | |
| 3479 | pub fn setFileRootDecl(zcu: *Zcu, file_index: File.Index, root_decl: Decl.OptionalIndex) void { | |
| 3065 | pub fn setFileRootType(zcu: *Zcu, file_index: File.Index, root_type: InternPool.Index) void { | |
| 3480 | 3066 | const ip = &zcu.intern_pool; |
| 3481 | 3067 | const file_index_unwrapped = file_index.unwrap(ip); |
| 3482 | 3068 | const files = ip.getLocalShared(file_index_unwrapped.tid).files.acquire(); |
| 3483 | files.view().items(.root_decl)[file_index_unwrapped.index] = root_decl; | |
| 3069 | files.view().items(.root_type)[file_index_unwrapped.index] = root_type; | |
| 3484 | 3070 | } |
| 3485 | 3071 | |
| 3486 | 3072 | pub fn filePathDigest(zcu: *const Zcu, file_index: File.Index) Cache.BinDigest { |
| ... | ... | @@ -3489,3 +3075,39 @@ pub fn filePathDigest(zcu: *const Zcu, file_index: File.Index) Cache.BinDigest { |
| 3489 | 3075 | const files = ip.getLocalShared(file_index_unwrapped.tid).files.acquire(); |
| 3490 | 3076 | return files.view().items(.bin_digest)[file_index_unwrapped.index]; |
| 3491 | 3077 | } |
| 3078 | ||
| 3079 | pub fn navSrcLoc(zcu: *const Zcu, nav_index: InternPool.Nav.Index) LazySrcLoc { | |
| 3080 | const ip = &zcu.intern_pool; | |
| 3081 | return .{ | |
| 3082 | .base_node_inst = ip.getNav(nav_index).srcInst(ip), | |
| 3083 | .offset = LazySrcLoc.Offset.nodeOffset(0), | |
| 3084 | }; | |
| 3085 | } | |
| 3086 | ||
| 3087 | pub fn navSrcLine(zcu: *Zcu, nav_index: InternPool.Nav.Index) u32 { | |
| 3088 | const ip = &zcu.intern_pool; | |
| 3089 | const inst_info = ip.getNav(nav_index).srcInst(ip).resolveFull(ip); | |
| 3090 | const zir = zcu.fileByIndex(inst_info.file).zir; | |
| 3091 | const inst = zir.instructions.get(@intFromEnum(inst_info.inst)); | |
| 3092 | assert(inst.tag == .declaration); | |
| 3093 | return zir.extraData(Zir.Inst.Declaration, inst.data.declaration.payload_index).data.src_line; | |
| 3094 | } | |
| 3095 | ||
| 3096 | pub fn navValue(zcu: *const Zcu, nav_index: InternPool.Nav.Index) Value { | |
| 3097 | return Value.fromInterned(zcu.intern_pool.getNav(nav_index).status.resolved.val); | |
| 3098 | } | |
| 3099 | ||
| 3100 | pub fn navFileScopeIndex(zcu: *Zcu, nav: InternPool.Nav.Index) File.Index { | |
| 3101 | const ip = &zcu.intern_pool; | |
| 3102 | return ip.getNav(nav).srcInst(ip).resolveFull(ip).file; | |
| 3103 | } | |
| 3104 | ||
| 3105 | pub fn navFileScope(zcu: *Zcu, nav: InternPool.Nav.Index) *File { | |
| 3106 | return zcu.fileByIndex(zcu.navFileScopeIndex(nav)); | |
| 3107 | } | |
| 3108 | ||
| 3109 | pub fn cauFileScope(zcu: *Zcu, cau: InternPool.Cau.Index) *File { | |
| 3110 | const ip = &zcu.intern_pool; | |
| 3111 | const file_index = ip.getCau(cau).zir_index.resolveFull(ip).file; | |
| 3112 | return zcu.fileByIndex(file_index); | |
| 3113 | } |
src/Zcu/PerThread.zig+834-844| ... | ... | @@ -6,26 +6,6 @@ tid: Id, |
| 6 | 6 | pub const IdBacking = u7; |
| 7 | 7 | pub const Id = if (InternPool.single_threaded) enum { main } else enum(IdBacking) { main, _ }; |
| 8 | 8 | |
| 9 | pub fn destroyDecl(pt: Zcu.PerThread, decl_index: Zcu.Decl.Index) void { | |
| 10 | const zcu = pt.zcu; | |
| 11 | const gpa = zcu.gpa; | |
| 12 | ||
| 13 | { | |
| 14 | _ = zcu.test_functions.swapRemove(decl_index); | |
| 15 | if (zcu.global_assembly.fetchSwapRemove(decl_index)) |kv| { | |
| 16 | gpa.free(kv.value); | |
| 17 | } | |
| 18 | } | |
| 19 | ||
| 20 | pt.zcu.intern_pool.destroyDecl(pt.tid, decl_index); | |
| 21 | ||
| 22 | if (zcu.emit_h) |zcu_emit_h| { | |
| 23 | const decl_emit_h = zcu_emit_h.declPtr(decl_index); | |
| 24 | decl_emit_h.fwd_decl.deinit(gpa); | |
| 25 | decl_emit_h.* = undefined; | |
| 26 | } | |
| 27 | } | |
| 28 | ||
| 29 | 9 | fn deinitFile(pt: Zcu.PerThread, file_index: Zcu.File.Index) void { |
| 30 | 10 | const zcu = pt.zcu; |
| 31 | 11 | const gpa = zcu.gpa; |
| ... | ... | @@ -40,9 +20,6 @@ fn deinitFile(pt: Zcu.PerThread, file_index: Zcu.File.Index) void { |
| 40 | 20 | file.unload(gpa); |
| 41 | 21 | } |
| 42 | 22 | file.references.deinit(gpa); |
| 43 | if (zcu.fileRootDecl(file_index).unwrap()) |root_decl| { | |
| 44 | pt.zcu.intern_pool.destroyDecl(pt.tid, root_decl); | |
| 45 | } | |
| 46 | 23 | if (file.prev_zir) |prev_zir| { |
| 47 | 24 | prev_zir.deinit(gpa); |
| 48 | 25 | gpa.destroy(prev_zir); |
| ... | ... | @@ -62,7 +39,7 @@ pub fn astGenFile( |
| 62 | 39 | pt: Zcu.PerThread, |
| 63 | 40 | file: *Zcu.File, |
| 64 | 41 | path_digest: Cache.BinDigest, |
| 65 | opt_root_decl: Zcu.Decl.OptionalIndex, | |
| 42 | old_root_type: InternPool.Index, | |
| 66 | 43 | ) !void { |
| 67 | 44 | dev.check(.ast_gen); |
| 68 | 45 | assert(!file.mod.isBuiltin()); |
| ... | ... | @@ -323,13 +300,13 @@ pub fn astGenFile( |
| 323 | 300 | return error.AnalysisFail; |
| 324 | 301 | } |
| 325 | 302 | |
| 326 | if (opt_root_decl.unwrap()) |root_decl| { | |
| 303 | if (old_root_type != .none) { | |
| 327 | 304 | // The root of this file must be re-analyzed, since the file has changed. |
| 328 | 305 | comp.mutex.lock(); |
| 329 | 306 | defer comp.mutex.unlock(); |
| 330 | 307 | |
| 331 | log.debug("outdated root Decl: {}", .{root_decl}); | |
| 332 | try zcu.outdated_file_root.put(gpa, root_decl, {}); | |
| 308 | log.debug("outdated file root type: {}", .{old_root_type}); | |
| 309 | try zcu.outdated_file_root.put(gpa, old_root_type, {}); | |
| 333 | 310 | } |
| 334 | 311 | } |
| 335 | 312 | |
| ... | ... | @@ -491,137 +468,171 @@ pub fn updateZirRefs(pt: Zcu.PerThread) Allocator.Error!void { |
| 491 | 468 | } |
| 492 | 469 | } |
| 493 | 470 | |
| 494 | /// Like `ensureDeclAnalyzed`, but the Decl is a file's root Decl. | |
| 471 | /// Ensures that `zcu.fileRootType` on this `file_index` gives an up-to-date answer. | |
| 472 | /// Returns `error.AnalysisFail` if the file has an error. | |
| 495 | 473 | pub fn ensureFileAnalyzed(pt: Zcu.PerThread, file_index: Zcu.File.Index) Zcu.SemaError!void { |
| 496 | if (pt.zcu.fileRootDecl(file_index).unwrap()) |existing_root| { | |
| 497 | return pt.ensureDeclAnalyzed(existing_root); | |
| 474 | const file_root_type = pt.zcu.fileRootType(file_index); | |
| 475 | if (file_root_type != .none) { | |
| 476 | const file_root_type_cau = pt.zcu.intern_pool.loadStructType(file_root_type).cau.unwrap().?; | |
| 477 | return pt.ensureCauAnalyzed(file_root_type_cau); | |
| 498 | 478 | } else { |
| 499 | 479 | return pt.semaFile(file_index); |
| 500 | 480 | } |
| 501 | 481 | } |
| 502 | 482 | |
| 503 | /// This ensures that the Decl will have an up-to-date Type and Value populated. | |
| 504 | /// However the resolution status of the Type may not be fully resolved. | |
| 505 | /// For example an inferred error set is not resolved until after `analyzeFnBody`. | |
| 506 | /// is called. | |
| 507 | pub fn ensureDeclAnalyzed(pt: Zcu.PerThread, decl_index: Zcu.Decl.Index) Zcu.SemaError!void { | |
| 508 | dev.check(.sema); | |
| 509 | ||
| 483 | /// This ensures that the state of the `Cau`, and of its corresponding `Nav` or type, | |
| 484 | /// is fully up-to-date. Note that the type of the `Nav` may not be fully resolved. | |
| 485 | /// Returns `error.AnalysisFail` if the `Cau` has an error. | |
| 486 | pub fn ensureCauAnalyzed(pt: Zcu.PerThread, cau_index: InternPool.Cau.Index) Zcu.SemaError!void { | |
| 510 | 487 | const tracy = trace(@src()); |
| 511 | 488 | defer tracy.end(); |
| 512 | 489 | |
| 513 | const mod = pt.zcu; | |
| 514 | const ip = &mod.intern_pool; | |
| 515 | const decl = mod.declPtr(decl_index); | |
| 490 | const zcu = pt.zcu; | |
| 491 | const gpa = zcu.gpa; | |
| 492 | const ip = &zcu.intern_pool; | |
| 516 | 493 | |
| 517 | log.debug("ensureDeclAnalyzed '{d}' (name '{}')", .{ | |
| 518 | @intFromEnum(decl_index), | |
| 519 | decl.name.fmt(ip), | |
| 520 | }); | |
| 494 | const anal_unit = InternPool.AnalUnit.wrap(.{ .cau = cau_index }); | |
| 495 | const cau = ip.getCau(cau_index); | |
| 496 | const inst_info = cau.zir_index.resolveFull(ip); | |
| 497 | ||
| 498 | log.debug("ensureCauAnalyzed {d}", .{@intFromEnum(cau_index)}); | |
| 499 | ||
| 500 | assert(!zcu.analysis_in_progress.contains(anal_unit)); | |
| 521 | 501 | |
| 522 | // Determine whether or not this Decl is outdated, i.e. requires re-analysis | |
| 523 | // even if `complete`. If a Decl is PO, we pessismistically assume that it | |
| 524 | // *does* require re-analysis, to ensure that the Decl is definitely | |
| 502 | // Determine whether or not this Cau is outdated, i.e. requires re-analysis | |
| 503 | // even if `complete`. If a Cau is PO, we pessismistically assume that it | |
| 504 | // *does* require re-analysis, to ensure that the Cau is definitely | |
| 525 | 505 | // up-to-date when this function returns. |
| 526 | 506 | |
| 527 | 507 | // If analysis occurs in a poor order, this could result in over-analysis. |
| 528 | 508 | // We do our best to avoid this by the other dependency logic in this file |
| 529 | // which tries to limit re-analysis to Decls whose previously listed | |
| 509 | // which tries to limit re-analysis to Caus whose previously listed | |
| 530 | 510 | // dependencies are all up-to-date. |
| 531 | 511 | |
| 532 | const decl_as_depender = InternPool.AnalUnit.wrap(.{ .decl = decl_index }); | |
| 533 | const decl_was_outdated = mod.outdated.swapRemove(decl_as_depender) or | |
| 534 | mod.potentially_outdated.swapRemove(decl_as_depender); | |
| 512 | const cau_outdated = zcu.outdated.swapRemove(anal_unit) or | |
| 513 | zcu.potentially_outdated.swapRemove(anal_unit); | |
| 514 | ||
| 515 | if (cau_outdated) { | |
| 516 | _ = zcu.outdated_ready.swapRemove(anal_unit); | |
| 517 | } | |
| 518 | ||
| 519 | // TODO: this only works if namespace lookups in Sema trigger `ensureCauAnalyzed`, because | |
| 520 | // `outdated_file_root` information is not "viral", so we need that a namespace lookup first | |
| 521 | // handles the case where the file root is not an outdated *type* but does have an outdated | |
| 522 | // *namespace*. A more logically simple alternative may be for a file's root struct to register | |
| 523 | // a dependency on the file's entire source code (hash). Alternatively, we could make sure that | |
| 524 | // these are always handled first in an update. Actually, that's probably the best option. | |
| 525 | // For my own benefit, here's how a namespace update for a normal (non-file-root) type works: | |
| 526 | // `const S = struct { ... };` | |
| 527 | // We are adding or removing a declaration within this `struct`. | |
| 528 | // * `S` registers a dependency on `.{ .src_hash = (declaration of S) }` | |
| 529 | // * Any change to the `struct` body -- including changing a declaration -- invalidates this | |
| 530 | // * `S` is re-analyzed, but notes: | |
| 531 | // * there is an existing struct instance (at this `TrackedInst` with these captures) | |
| 532 | // * the struct's `Cau` is up-to-date (because nothing about the fields changed) | |
| 533 | // * so, it uses the same `struct` | |
| 534 | // * but this doesn't stop it from updating the namespace! | |
| 535 | // * we basically do `scanDecls`, updating the namespace as needed | |
| 536 | // * TODO: optimize this to make sure we only do it once a generation i guess? | |
| 537 | // * so everyone lived happily ever after | |
| 538 | const file_root_outdated = switch (cau.owner.unwrap()) { | |
| 539 | .type => |ty| zcu.outdated_file_root.swapRemove(ty), | |
| 540 | .nav, .none => false, | |
| 541 | }; | |
| 535 | 542 | |
| 536 | if (decl_was_outdated) { | |
| 537 | _ = mod.outdated_ready.swapRemove(decl_as_depender); | |
| 543 | if (zcu.fileByIndex(inst_info.file).status != .success_zir) { | |
| 544 | return error.AnalysisFail; | |
| 538 | 545 | } |
| 539 | 546 | |
| 540 | const was_outdated = mod.outdated_file_root.swapRemove(decl_index) or decl_was_outdated; | |
| 541 | ||
| 542 | switch (decl.analysis) { | |
| 543 | .in_progress => unreachable, | |
| 544 | ||
| 545 | .file_failure => return error.AnalysisFail, | |
| 546 | ||
| 547 | .sema_failure, | |
| 548 | .dependency_failure, | |
| 549 | .codegen_failure, | |
| 550 | => if (!was_outdated) return error.AnalysisFail, | |
| 551 | ||
| 552 | .complete => if (!was_outdated) return, | |
| 553 | ||
| 554 | .unreferenced => {}, | |
| 547 | if (!cau_outdated and !file_root_outdated) { | |
| 548 | // We can trust the current information about this `Cau`. | |
| 549 | if (zcu.failed_analysis.contains(anal_unit) or zcu.transitive_failed_analysis.contains(anal_unit)) { | |
| 550 | return error.AnalysisFail; | |
| 551 | } | |
| 552 | // If it wasn't failed and wasn't marked outdated, then either... | |
| 553 | // * it is a type and is up-to-date, or | |
| 554 | // * it is a `comptime` decl and is up-to-date, or | |
| 555 | // * it is another decl and is EITHER up-to-date OR never-referenced (so unresolved) | |
| 556 | // We just need to check for that last case. | |
| 557 | switch (cau.owner.unwrap()) { | |
| 558 | .type, .none => return, | |
| 559 | .nav => |nav| if (ip.getNav(nav).status == .resolved) return, | |
| 560 | } | |
| 555 | 561 | } |
| 556 | 562 | |
| 557 | if (was_outdated) { | |
| 558 | dev.check(.incremental); | |
| 559 | // The exports this Decl performs will be re-discovered, so we remove them here | |
| 563 | // `cau_outdated` can be true in the initial update for `comptime` declarations, | |
| 564 | // so this isn't a `dev.check`. | |
| 565 | if (cau_outdated and dev.env.supports(.incremental)) { | |
| 566 | // The exports this `Cau` performs will be re-discovered, so we remove them here | |
| 560 | 567 | // prior to re-analysis. |
| 561 | mod.deleteUnitExports(decl_as_depender); | |
| 562 | mod.deleteUnitReferences(decl_as_depender); | |
| 568 | zcu.deleteUnitExports(anal_unit); | |
| 569 | zcu.deleteUnitReferences(anal_unit); | |
| 563 | 570 | } |
| 564 | 571 | |
| 565 | const sema_result: Zcu.SemaDeclResult = blk: { | |
| 566 | if (decl.zir_decl_index == .none and !mod.declIsRoot(decl_index)) { | |
| 567 | // Anonymous decl. We don't semantically analyze these. | |
| 568 | break :blk .{ | |
| 569 | .invalidate_decl_val = false, | |
| 570 | .invalidate_decl_ref = false, | |
| 571 | }; | |
| 572 | } | |
| 573 | ||
| 574 | if (mod.declIsRoot(decl_index)) { | |
| 575 | const changed = try pt.semaFileUpdate(decl.getFileScopeIndex(mod), decl_was_outdated); | |
| 576 | break :blk .{ | |
| 572 | const sema_result: SemaCauResult = res: { | |
| 573 | if (inst_info.inst == .main_struct_inst) { | |
| 574 | const changed = try pt.semaFileUpdate(inst_info.file, cau_outdated); | |
| 575 | break :res .{ | |
| 577 | 576 | .invalidate_decl_val = changed, |
| 578 | 577 | .invalidate_decl_ref = changed, |
| 579 | 578 | }; |
| 580 | 579 | } |
| 581 | 580 | |
| 582 | const decl_prog_node = mod.sema_prog_node.start(decl.fqn.toSlice(ip), 0); | |
| 581 | const decl_prog_node = zcu.sema_prog_node.start(switch (cau.owner.unwrap()) { | |
| 582 | .nav => |nav| ip.getNav(nav).fqn.toSlice(ip), | |
| 583 | .type => |ty| Type.fromInterned(ty).containerTypeName(ip).toSlice(ip), | |
| 584 | .none => "comptime", | |
| 585 | }, 0); | |
| 583 | 586 | defer decl_prog_node.end(); |
| 584 | 587 | |
| 585 | break :blk pt.semaDecl(decl_index) catch |err| switch (err) { | |
| 588 | break :res pt.semaCau(cau_index) catch |err| switch (err) { | |
| 586 | 589 | error.AnalysisFail => { |
| 587 | if (decl.analysis == .in_progress) { | |
| 588 | // If this decl caused the compile error, the analysis field would | |
| 589 | // be changed to indicate it was this Decl's fault. Because this | |
| 590 | // did not happen, we infer here that it was a dependency failure. | |
| 591 | decl.analysis = .dependency_failure; | |
| 590 | if (!zcu.failed_analysis.contains(anal_unit)) { | |
| 591 | // If this `Cau` caused the error, it would have an entry in `failed_analysis`. | |
| 592 | // Since it does not, this must be a transitive failure. | |
| 593 | try zcu.transitive_failed_analysis.put(gpa, anal_unit, {}); | |
| 592 | 594 | } |
| 593 | 595 | return error.AnalysisFail; |
| 594 | 596 | }, |
| 595 | 597 | error.GenericPoison => unreachable, |
| 596 | else => |e| { | |
| 597 | decl.analysis = .sema_failure; | |
| 598 | try mod.failed_analysis.ensureUnusedCapacity(mod.gpa, 1); | |
| 599 | try mod.retryable_failures.append(mod.gpa, InternPool.AnalUnit.wrap(.{ .decl = decl_index })); | |
| 600 | mod.failed_analysis.putAssumeCapacityNoClobber(InternPool.AnalUnit.wrap(.{ .decl = decl_index }), try Zcu.ErrorMsg.create( | |
| 601 | mod.gpa, | |
| 602 | decl.navSrcLoc(mod), | |
| 603 | "unable to analyze: {s}", | |
| 604 | .{@errorName(e)}, | |
| 598 | error.ComptimeBreak => unreachable, | |
| 599 | error.ComptimeReturn => unreachable, | |
| 600 | error.OutOfMemory => { | |
| 601 | try zcu.failed_analysis.ensureUnusedCapacity(gpa, 1); | |
| 602 | try zcu.retryable_failures.append(gpa, anal_unit); | |
| 603 | zcu.failed_analysis.putAssumeCapacityNoClobber(anal_unit, try Zcu.ErrorMsg.create( | |
| 604 | gpa, | |
| 605 | .{ .base_node_inst = cau.zir_index, .offset = Zcu.LazySrcLoc.Offset.nodeOffset(0) }, | |
| 606 | "unable to analyze: OutOfMemory", | |
| 607 | .{}, | |
| 605 | 608 | )); |
| 606 | 609 | return error.AnalysisFail; |
| 607 | 610 | }, |
| 608 | 611 | }; |
| 609 | 612 | }; |
| 610 | 613 | |
| 614 | if (!cau_outdated) { | |
| 615 | // We definitely don't need to do any dependency tracking, so our work is done. | |
| 616 | return; | |
| 617 | } | |
| 618 | ||
| 611 | 619 | // TODO: we do not yet have separate dependencies for decl values vs types. |
| 612 | if (decl_was_outdated) { | |
| 613 | if (sema_result.invalidate_decl_val or sema_result.invalidate_decl_ref) { | |
| 614 | log.debug("Decl tv invalidated ('{d}')", .{@intFromEnum(decl_index)}); | |
| 615 | // This dependency was marked as PO, meaning dependees were waiting | |
| 616 | // on its analysis result, and it has turned out to be outdated. | |
| 617 | // Update dependees accordingly. | |
| 618 | try mod.markDependeeOutdated(.{ .decl_val = decl_index }); | |
| 619 | } else { | |
| 620 | log.debug("Decl tv up-to-date ('{d}')", .{@intFromEnum(decl_index)}); | |
| 621 | // This dependency was previously PO, but turned out to be up-to-date. | |
| 622 | // We do not need to queue successive analysis. | |
| 623 | try mod.markPoDependeeUpToDate(.{ .decl_val = decl_index }); | |
| 624 | } | |
| 620 | const invalidate = sema_result.invalidate_decl_val or sema_result.invalidate_decl_ref; | |
| 621 | const dependee: InternPool.Dependee = switch (cau.owner.unwrap()) { | |
| 622 | .none => return, // there are no dependencies on a `comptime` decl! | |
| 623 | .nav => |nav_index| .{ .nav_val = nav_index }, | |
| 624 | .type => |ty| .{ .interned = ty }, | |
| 625 | }; | |
| 626 | ||
| 627 | if (invalidate) { | |
| 628 | // This dependency was marked as PO, meaning dependees were waiting | |
| 629 | // on its analysis result, and it has turned out to be outdated. | |
| 630 | // Update dependees accordingly. | |
| 631 | try zcu.markDependeeOutdated(dependee); | |
| 632 | } else { | |
| 633 | // This dependency was previously PO, but turned out to be up-to-date. | |
| 634 | // We do not need to queue successive analysis. | |
| 635 | try zcu.markPoDependeeUpToDate(dependee); | |
| 625 | 636 | } |
| 626 | 637 | } |
| 627 | 638 | |
| ... | ... | @@ -636,28 +647,32 @@ pub fn ensureFuncBodyAnalyzed(pt: Zcu.PerThread, maybe_coerced_func_index: Inter |
| 636 | 647 | const ip = &zcu.intern_pool; |
| 637 | 648 | |
| 638 | 649 | // We only care about the uncoerced function. |
| 639 | // We need to do this for the "orphaned function" check below to be valid. | |
| 640 | 650 | const func_index = ip.unwrapCoercedFunc(maybe_coerced_func_index); |
| 641 | 651 | |
| 642 | 652 | const func = zcu.funcInfo(maybe_coerced_func_index); |
| 643 | const decl_index = func.owner_decl; | |
| 644 | const decl = zcu.declPtr(decl_index); | |
| 645 | 653 | |
| 646 | log.debug("ensureFuncBodyAnalyzed '{d}' (instance of '{}')", .{ | |
| 647 | @intFromEnum(func_index), | |
| 648 | decl.name.fmt(ip), | |
| 649 | }); | |
| 654 | log.debug("ensureFuncBodyAnalyzed {d}", .{@intFromEnum(func_index)}); | |
| 650 | 655 | |
| 651 | // First, our owner decl must be up-to-date. This will always be the case | |
| 652 | // during the first update, but may not on successive updates if we happen | |
| 653 | // to get analyzed before our parent decl. | |
| 654 | try pt.ensureDeclAnalyzed(decl_index); | |
| 656 | // Here's an interesting question: is this function actually valid? | |
| 657 | // Maybe the signature changed, so we'll end up creating a whole different `func` | |
| 658 | // in the InternPool, and this one is a waste of time to analyze. Worse, we'd be | |
| 659 | // analyzing new ZIR with old data, and get bogus errors. They would be unused, | |
| 660 | // but they would still hang around internally! So, let's detect this case. | |
| 661 | // For function decls, we must ensure the declaration's `Cau` is up-to-date, and | |
| 662 | // check if `func_index` was removed by that update. | |
| 663 | // For function instances, we do that process on the generic owner. | |
| 655 | 664 | |
| 656 | // On an update, it's possible this function changed such that our owner | |
| 657 | // decl now refers to a different function, making this one orphaned. If | |
| 658 | // that's the case, we should remove this function from the binary. | |
| 659 | if (decl.val.ip_index != func_index) { | |
| 660 | try zcu.markDependeeOutdated(.{ .func_ies = func_index }); | |
| 665 | try pt.ensureCauAnalyzed(cau: { | |
| 666 | const func_nav = if (func.generic_owner == .none) | |
| 667 | func.owner_nav | |
| 668 | else | |
| 669 | zcu.funcInfo(func.generic_owner).owner_nav; | |
| 670 | ||
| 671 | break :cau ip.getNav(func_nav).analysis_owner.unwrap().?; | |
| 672 | }); | |
| 673 | ||
| 674 | if (ip.isRemoved(func_index) or (func.generic_owner != .none and ip.isRemoved(func.generic_owner))) { | |
| 675 | try zcu.markDependeeOutdated(.{ .interned = func_index }); // IES | |
| 661 | 676 | ip.removeDependenciesForDepender(gpa, InternPool.AnalUnit.wrap(.{ .func = func_index })); |
| 662 | 677 | ip.remove(pt.tid, func_index); |
| 663 | 678 | @panic("TODO: remove orphaned function from binary"); |
| ... | ... | @@ -670,58 +685,40 @@ pub fn ensureFuncBodyAnalyzed(pt: Zcu.PerThread, maybe_coerced_func_index: Inter |
| 670 | 685 | else |
| 671 | 686 | .none; |
| 672 | 687 | |
| 673 | switch (decl.analysis) { | |
| 674 | .unreferenced => unreachable, | |
| 675 | .in_progress => unreachable, | |
| 676 | ||
| 677 | .codegen_failure => unreachable, // functions do not perform constant value generation | |
| 688 | const anal_unit = InternPool.AnalUnit.wrap(.{ .func = func_index }); | |
| 689 | const func_outdated = zcu.outdated.swapRemove(anal_unit) or | |
| 690 | zcu.potentially_outdated.swapRemove(anal_unit); | |
| 678 | 691 | |
| 679 | .file_failure, | |
| 680 | .sema_failure, | |
| 681 | .dependency_failure, | |
| 682 | => return error.AnalysisFail, | |
| 683 | ||
| 684 | .complete => {}, | |
| 685 | } | |
| 686 | ||
| 687 | const func_as_depender = InternPool.AnalUnit.wrap(.{ .func = func_index }); | |
| 688 | const was_outdated = zcu.outdated.swapRemove(func_as_depender) or | |
| 689 | zcu.potentially_outdated.swapRemove(func_as_depender); | |
| 690 | ||
| 691 | if (was_outdated) { | |
| 692 | if (func_outdated) { | |
| 692 | 693 | dev.check(.incremental); |
| 693 | _ = zcu.outdated_ready.swapRemove(func_as_depender); | |
| 694 | zcu.deleteUnitExports(func_as_depender); | |
| 695 | zcu.deleteUnitReferences(func_as_depender); | |
| 694 | _ = zcu.outdated_ready.swapRemove(anal_unit); | |
| 695 | zcu.deleteUnitExports(anal_unit); | |
| 696 | zcu.deleteUnitReferences(anal_unit); | |
| 696 | 697 | } |
| 697 | 698 | |
| 698 | switch (func.analysisUnordered(ip).state) { | |
| 699 | .success => if (!was_outdated) return, | |
| 700 | .sema_failure, | |
| 701 | .dependency_failure, | |
| 702 | .codegen_failure, | |
| 703 | => if (!was_outdated) return error.AnalysisFail, | |
| 704 | .none, .queued => {}, | |
| 705 | .in_progress => unreachable, | |
| 706 | .inline_only => unreachable, // don't queue work for this | |
| 699 | if (!func_outdated) { | |
| 700 | // We can trust the current information about this function. | |
| 701 | if (zcu.failed_analysis.contains(anal_unit) or zcu.transitive_failed_analysis.contains(anal_unit)) { | |
| 702 | return error.AnalysisFail; | |
| 703 | } | |
| 704 | switch (func.analysisUnordered(ip).state) { | |
| 705 | .unreferenced => {}, // this is the first reference | |
| 706 | .queued => {}, // we're waiting on first-time analysis | |
| 707 | .analyzed => return, // up-to-date | |
| 708 | } | |
| 707 | 709 | } |
| 708 | 710 | |
| 709 | 711 | log.debug("analyze and generate fn body '{d}'; reason='{s}'", .{ |
| 710 | 712 | @intFromEnum(func_index), |
| 711 | if (was_outdated) "outdated" else "never analyzed", | |
| 713 | if (func_outdated) "outdated" else "never analyzed", | |
| 712 | 714 | }); |
| 713 | 715 | |
| 714 | var tmp_arena = std.heap.ArenaAllocator.init(gpa); | |
| 715 | defer tmp_arena.deinit(); | |
| 716 | const sema_arena = tmp_arena.allocator(); | |
| 717 | ||
| 718 | var air = pt.analyzeFnBody(func_index, sema_arena) catch |err| switch (err) { | |
| 716 | var air = pt.analyzeFnBody(func_index) catch |err| switch (err) { | |
| 719 | 717 | error.AnalysisFail => { |
| 720 | if (func.analysisUnordered(ip).state == .in_progress) { | |
| 721 | // If this decl caused the compile error, the analysis field would | |
| 722 | // be changed to indicate it was this Decl's fault. Because this | |
| 723 | // did not happen, we infer here that it was a dependency failure. | |
| 724 | func.setAnalysisState(ip, .dependency_failure); | |
| 718 | if (!zcu.failed_analysis.contains(anal_unit)) { | |
| 719 | // If this function caused the error, it would have an entry in `failed_analysis`. | |
| 720 | // Since it does not, this must be a transitive failure. | |
| 721 | try zcu.transitive_failed_analysis.put(gpa, anal_unit, {}); | |
| 725 | 722 | } |
| 726 | 723 | return error.AnalysisFail; |
| 727 | 724 | }, |
| ... | ... | @@ -729,18 +726,14 @@ pub fn ensureFuncBodyAnalyzed(pt: Zcu.PerThread, maybe_coerced_func_index: Inter |
| 729 | 726 | }; |
| 730 | 727 | errdefer air.deinit(gpa); |
| 731 | 728 | |
| 732 | const invalidate_ies_deps = i: { | |
| 733 | if (!was_outdated) break :i false; | |
| 734 | if (!func.analysisUnordered(ip).inferred_error_set) break :i true; | |
| 735 | const new_resolved_ies = func.resolvedErrorSetUnordered(ip); | |
| 736 | break :i new_resolved_ies != old_resolved_ies; | |
| 737 | }; | |
| 738 | if (invalidate_ies_deps) { | |
| 739 | log.debug("func IES invalidated ('{d}')", .{@intFromEnum(func_index)}); | |
| 740 | try zcu.markDependeeOutdated(.{ .func_ies = func_index }); | |
| 741 | } else if (was_outdated) { | |
| 742 | log.debug("func IES up-to-date ('{d}')", .{@intFromEnum(func_index)}); | |
| 743 | try zcu.markPoDependeeUpToDate(.{ .func_ies = func_index }); | |
| 729 | if (func_outdated) { | |
| 730 | if (!func.analysisUnordered(ip).inferred_error_set or func.resolvedErrorSetUnordered(ip) != old_resolved_ies) { | |
| 731 | log.debug("func IES invalidated ('{d}')", .{@intFromEnum(func_index)}); | |
| 732 | try zcu.markDependeeOutdated(.{ .interned = func_index }); | |
| 733 | } else { | |
| 734 | log.debug("func IES up-to-date ('{d}')", .{@intFromEnum(func_index)}); | |
| 735 | try zcu.markPoDependeeUpToDate(.{ .interned = func_index }); | |
| 736 | } | |
| 744 | 737 | } |
| 745 | 738 | |
| 746 | 739 | const comp = zcu.comp; |
| ... | ... | @@ -773,16 +766,16 @@ pub fn linkerUpdateFunc(pt: Zcu.PerThread, func_index: InternPool.Index, air: Ai |
| 773 | 766 | } |
| 774 | 767 | |
| 775 | 768 | const func = zcu.funcInfo(func_index); |
| 776 | const decl_index = func.owner_decl; | |
| 777 | const decl = zcu.declPtr(decl_index); | |
| 769 | const nav_index = func.owner_nav; | |
| 770 | const nav = ip.getNav(nav_index); | |
| 778 | 771 | |
| 779 | 772 | var liveness = try Liveness.analyze(gpa, air, ip); |
| 780 | 773 | defer liveness.deinit(gpa); |
| 781 | 774 | |
| 782 | 775 | if (build_options.enable_debug_extensions and comp.verbose_air) { |
| 783 | std.debug.print("# Begin Function AIR: {}:\n", .{decl.fqn.fmt(ip)}); | |
| 776 | std.debug.print("# Begin Function AIR: {}:\n", .{nav.fqn.fmt(ip)}); | |
| 784 | 777 | @import("../print_air.zig").dump(pt, air, liveness); |
| 785 | std.debug.print("# End Function AIR: {}\n\n", .{decl.fqn.fmt(ip)}); | |
| 778 | std.debug.print("# End Function AIR: {}\n\n", .{nav.fqn.fmt(ip)}); | |
| 786 | 779 | } |
| 787 | 780 | |
| 788 | 781 | if (std.debug.runtime_safety) { |
| ... | ... | @@ -797,23 +790,18 @@ pub fn linkerUpdateFunc(pt: Zcu.PerThread, func_index: InternPool.Index, air: Ai |
| 797 | 790 | verify.verify() catch |err| switch (err) { |
| 798 | 791 | error.OutOfMemory => return error.OutOfMemory, |
| 799 | 792 | else => { |
| 800 | try zcu.failed_analysis.ensureUnusedCapacity(gpa, 1); | |
| 801 | zcu.failed_analysis.putAssumeCapacityNoClobber( | |
| 802 | InternPool.AnalUnit.wrap(.{ .func = func_index }), | |
| 803 | try Zcu.ErrorMsg.create( | |
| 804 | gpa, | |
| 805 | decl.navSrcLoc(zcu), | |
| 806 | "invalid liveness: {s}", | |
| 807 | .{@errorName(err)}, | |
| 808 | ), | |
| 809 | ); | |
| 810 | func.setAnalysisState(ip, .codegen_failure); | |
| 793 | try zcu.failed_codegen.putNoClobber(gpa, nav_index, try Zcu.ErrorMsg.create( | |
| 794 | gpa, | |
| 795 | zcu.navSrcLoc(nav_index), | |
| 796 | "invalid liveness: {s}", | |
| 797 | .{@errorName(err)}, | |
| 798 | )); | |
| 811 | 799 | return; |
| 812 | 800 | }, |
| 813 | 801 | }; |
| 814 | 802 | } |
| 815 | 803 | |
| 816 | const codegen_prog_node = zcu.codegen_prog_node.start(decl.fqn.toSlice(ip), 0); | |
| 804 | const codegen_prog_node = zcu.codegen_prog_node.start(nav.fqn.toSlice(ip), 0); | |
| 817 | 805 | defer codegen_prog_node.end(); |
| 818 | 806 | |
| 819 | 807 | if (!air.typesFullyResolved(zcu)) { |
| ... | ... | @@ -821,22 +809,21 @@ pub fn linkerUpdateFunc(pt: Zcu.PerThread, func_index: InternPool.Index, air: Ai |
| 821 | 809 | // Correcting this failure will involve changing a type this function |
| 822 | 810 | // depends on, hence triggering re-analysis of this function, so this |
| 823 | 811 | // interacts correctly with incremental compilation. |
| 824 | func.setAnalysisState(ip, .codegen_failure); | |
| 812 | // TODO: do we need to mark this failure anywhere? I don't think so, since compilation | |
| 813 | // will fail due to the type error anyway. | |
| 825 | 814 | } else if (comp.bin_file) |lf| { |
| 826 | 815 | lf.updateFunc(pt, func_index, air, liveness) catch |err| switch (err) { |
| 827 | 816 | error.OutOfMemory => return error.OutOfMemory, |
| 828 | 817 | error.AnalysisFail => { |
| 829 | func.setAnalysisState(ip, .codegen_failure); | |
| 818 | assert(zcu.failed_codegen.contains(nav_index)); | |
| 830 | 819 | }, |
| 831 | 820 | else => { |
| 832 | try zcu.failed_analysis.ensureUnusedCapacity(gpa, 1); | |
| 833 | zcu.failed_analysis.putAssumeCapacityNoClobber(InternPool.AnalUnit.wrap(.{ .func = func_index }), try Zcu.ErrorMsg.create( | |
| 821 | try zcu.failed_codegen.putNoClobber(gpa, nav_index, try Zcu.ErrorMsg.create( | |
| 834 | 822 | gpa, |
| 835 | decl.navSrcLoc(zcu), | |
| 823 | zcu.navSrcLoc(nav_index), | |
| 836 | 824 | "unable to codegen: {s}", |
| 837 | 825 | .{@errorName(err)}, |
| 838 | 826 | )); |
| 839 | func.setAnalysisState(ip, .codegen_failure); | |
| 840 | 827 | try zcu.retryable_failures.append(zcu.gpa, InternPool.AnalUnit.wrap(.{ .func = func_index })); |
| 841 | 828 | }, |
| 842 | 829 | }; |
| ... | ... | @@ -851,17 +838,16 @@ pub fn linkerUpdateFunc(pt: Zcu.PerThread, func_index: InternPool.Index, air: Ai |
| 851 | 838 | pub fn semaPkg(pt: Zcu.PerThread, pkg: *Module) !void { |
| 852 | 839 | dev.check(.sema); |
| 853 | 840 | const import_file_result = try pt.importPkg(pkg); |
| 854 | const root_decl_index = pt.zcu.fileRootDecl(import_file_result.file_index); | |
| 855 | if (root_decl_index == .none) { | |
| 841 | const root_type = pt.zcu.fileRootType(import_file_result.file_index); | |
| 842 | if (root_type == .none) { | |
| 856 | 843 | return pt.semaFile(import_file_result.file_index); |
| 857 | 844 | } |
| 858 | 845 | } |
| 859 | 846 | |
| 860 | fn getFileRootStruct( | |
| 847 | fn createFileRootStruct( | |
| 861 | 848 | pt: Zcu.PerThread, |
| 862 | decl_index: Zcu.Decl.Index, | |
| 863 | namespace_index: Zcu.Namespace.Index, | |
| 864 | 849 | file_index: Zcu.File.Index, |
| 850 | namespace_index: Zcu.Namespace.Index, | |
| 865 | 851 | ) Allocator.Error!InternPool.Index { |
| 866 | 852 | const zcu = pt.zcu; |
| 867 | 853 | const gpa = zcu.gpa; |
| ... | ... | @@ -901,7 +887,6 @@ fn getFileRootStruct( |
| 901 | 887 | .any_default_inits = small.any_default_inits, |
| 902 | 888 | .inits_resolved = false, |
| 903 | 889 | .any_aligned_fields = small.any_aligned_fields, |
| 904 | .has_namespace = true, | |
| 905 | 890 | .key = .{ .declared = .{ |
| 906 | 891 | .zir_index = tracked_inst, |
| 907 | 892 | .captures = &.{}, |
| ... | ... | @@ -912,34 +897,37 @@ fn getFileRootStruct( |
| 912 | 897 | }; |
| 913 | 898 | errdefer wip_ty.cancel(ip, pt.tid); |
| 914 | 899 | |
| 900 | wip_ty.setName(ip, try file.internFullyQualifiedName(pt)); | |
| 901 | ip.namespacePtr(namespace_index).owner_type = wip_ty.index; | |
| 902 | const new_cau_index = try ip.createTypeCau(gpa, pt.tid, tracked_inst, namespace_index, wip_ty.index); | |
| 903 | ||
| 915 | 904 | if (zcu.comp.incremental) { |
| 916 | 905 | try ip.addDependency( |
| 917 | 906 | gpa, |
| 918 | InternPool.AnalUnit.wrap(.{ .decl = decl_index }), | |
| 907 | InternPool.AnalUnit.wrap(.{ .cau = new_cau_index }), | |
| 919 | 908 | .{ .src_hash = tracked_inst }, |
| 920 | 909 | ); |
| 921 | 910 | } |
| 922 | 911 | |
| 923 | const decl = zcu.declPtr(decl_index); | |
| 924 | decl.val = Value.fromInterned(wip_ty.index); | |
| 925 | decl.has_tv = true; | |
| 926 | decl.owns_tv = true; | |
| 927 | decl.analysis = .complete; | |
| 928 | ||
| 929 | try pt.scanNamespace(namespace_index, decls, decl); | |
| 912 | try pt.scanNamespace(namespace_index, decls); | |
| 930 | 913 | try zcu.comp.queueJob(.{ .resolve_type_fully = wip_ty.index }); |
| 931 | return wip_ty.finish(ip, decl_index, namespace_index.toOptional()); | |
| 914 | zcu.setFileRootType(file_index, wip_ty.index); | |
| 915 | return wip_ty.finish(ip, new_cau_index.toOptional(), namespace_index); | |
| 932 | 916 | } |
| 933 | 917 | |
| 934 | /// Re-analyze the root Decl of a file on an incremental update. | |
| 918 | /// Re-analyze the root type of a file on an incremental update. | |
| 935 | 919 | /// If `type_outdated`, the struct type itself is considered outdated and is |
| 936 | 920 | /// reconstructed at a new InternPool index. Otherwise, the namespace is just |
| 937 | 921 | /// re-analyzed. Returns whether the decl's tyval was invalidated. |
| 922 | /// Returns `error.AnalysisFail` if the file has an error. | |
| 938 | 923 | fn semaFileUpdate(pt: Zcu.PerThread, file_index: Zcu.File.Index, type_outdated: bool) Zcu.SemaError!bool { |
| 939 | 924 | const zcu = pt.zcu; |
| 940 | 925 | const ip = &zcu.intern_pool; |
| 941 | 926 | const file = zcu.fileByIndex(file_index); |
| 942 | const decl = zcu.declPtr(zcu.fileRootDecl(file_index).unwrap().?); | |
| 927 | const file_root_type = zcu.fileRootType(file_index); | |
| 928 | const namespace_index = Type.fromInterned(file_root_type).getNamespaceIndex(zcu); | |
| 929 | ||
| 930 | assert(file_root_type != .none); | |
| 943 | 931 | |
| 944 | 932 | log.debug("semaFileUpdate mod={s} sub_file_path={s} type_outdated={}", .{ |
| 945 | 933 | file.mod.fully_qualified_name, |
| ... | ... | @@ -948,33 +936,18 @@ fn semaFileUpdate(pt: Zcu.PerThread, file_index: Zcu.File.Index, type_outdated: |
| 948 | 936 | }); |
| 949 | 937 | |
| 950 | 938 | if (file.status != .success_zir) { |
| 951 | if (decl.analysis == .file_failure) { | |
| 952 | return false; | |
| 953 | } else { | |
| 954 | decl.analysis = .file_failure; | |
| 955 | return true; | |
| 956 | } | |
| 957 | } | |
| 958 | ||
| 959 | if (decl.analysis == .file_failure) { | |
| 960 | // No struct type currently exists. Create one! | |
| 961 | const root_decl = zcu.fileRootDecl(file_index); | |
| 962 | _ = try pt.getFileRootStruct(root_decl.unwrap().?, decl.src_namespace, file_index); | |
| 963 | return true; | |
| 939 | return error.AnalysisFail; | |
| 964 | 940 | } |
| 965 | 941 | |
| 966 | assert(decl.has_tv); | |
| 967 | assert(decl.owns_tv); | |
| 968 | ||
| 969 | 942 | if (type_outdated) { |
| 970 | // Invalidate the existing type, reusing the decl and namespace. | |
| 971 | const file_root_decl = zcu.fileRootDecl(file_index).unwrap().?; | |
| 972 | ip.removeDependenciesForDepender(zcu.gpa, InternPool.AnalUnit.wrap(.{ | |
| 973 | .decl = file_root_decl, | |
| 974 | })); | |
| 975 | ip.remove(pt.tid, decl.val.toIntern()); | |
| 976 | decl.val = undefined; | |
| 977 | _ = try pt.getFileRootStruct(file_root_decl, decl.src_namespace, file_index); | |
| 943 | // Invalidate the existing type, reusing its namespace. | |
| 944 | const file_root_type_cau = ip.loadStructType(file_root_type).cau.unwrap().?; | |
| 945 | ip.removeDependenciesForDepender( | |
| 946 | zcu.gpa, | |
| 947 | InternPool.AnalUnit.wrap(.{ .cau = file_root_type_cau }), | |
| 948 | ); | |
| 949 | ip.remove(pt.tid, file_root_type); | |
| 950 | _ = try pt.createFileRootStruct(file_index, namespace_index); | |
| 978 | 951 | return true; |
| 979 | 952 | } |
| 980 | 953 | |
| ... | ... | @@ -994,7 +967,7 @@ fn semaFileUpdate(pt: Zcu.PerThread, file_index: Zcu.File.Index, type_outdated: |
| 994 | 967 | const decls = file.zir.bodySlice(extra_index, decls_len); |
| 995 | 968 | |
| 996 | 969 | if (!type_outdated) { |
| 997 | try pt.scanNamespace(decl.src_namespace, decls, decl); | |
| 970 | try pt.scanNamespace(namespace_index, decls); | |
| 998 | 971 | } |
| 999 | 972 | |
| 1000 | 973 | return false; |
| ... | ... | @@ -1009,43 +982,19 @@ fn semaFile(pt: Zcu.PerThread, file_index: Zcu.File.Index) Zcu.SemaError!void { |
| 1009 | 982 | const zcu = pt.zcu; |
| 1010 | 983 | const gpa = zcu.gpa; |
| 1011 | 984 | const file = zcu.fileByIndex(file_index); |
| 1012 | assert(zcu.fileRootDecl(file_index) == .none); | |
| 1013 | log.debug("semaFile zcu={s} sub_file_path={s}", .{ | |
| 1014 | file.mod.fully_qualified_name, file.sub_file_path, | |
| 1015 | }); | |
| 1016 | ||
| 1017 | // Because these three things each reference each other, `undefined` | |
| 1018 | // placeholders are used before being set after the struct type gains an | |
| 1019 | // InternPool index. | |
| 1020 | const new_namespace_index = try pt.createNamespace(.{ | |
| 1021 | .parent = .none, | |
| 1022 | .decl_index = undefined, | |
| 1023 | .file_scope = file_index, | |
| 1024 | }); | |
| 1025 | errdefer pt.destroyNamespace(new_namespace_index); | |
| 1026 | ||
| 1027 | const new_decl_index = try pt.allocateNewDecl(new_namespace_index); | |
| 1028 | const new_decl = zcu.declPtr(new_decl_index); | |
| 1029 | errdefer @panic("TODO error handling"); | |
| 1030 | ||
| 1031 | zcu.setFileRootDecl(file_index, new_decl_index.toOptional()); | |
| 1032 | zcu.namespacePtr(new_namespace_index).decl_index = new_decl_index; | |
| 1033 | ||
| 1034 | new_decl.fqn = try file.internFullyQualifiedName(pt); | |
| 1035 | new_decl.name = new_decl.fqn; | |
| 1036 | new_decl.is_pub = true; | |
| 1037 | new_decl.is_exported = false; | |
| 1038 | new_decl.alignment = .none; | |
| 1039 | new_decl.@"linksection" = .none; | |
| 1040 | new_decl.analysis = .in_progress; | |
| 985 | assert(zcu.fileRootType(file_index) == .none); | |
| 1041 | 986 | |
| 1042 | 987 | if (file.status != .success_zir) { |
| 1043 | new_decl.analysis = .file_failure; | |
| 1044 | return; | |
| 988 | return error.AnalysisFail; | |
| 1045 | 989 | } |
| 1046 | 990 | assert(file.zir_loaded); |
| 1047 | 991 | |
| 1048 | const struct_ty = try pt.getFileRootStruct(new_decl_index, new_namespace_index, file_index); | |
| 992 | const new_namespace_index = try pt.createNamespace(.{ | |
| 993 | .parent = .none, | |
| 994 | .owner_type = undefined, // set in `createFileRootStruct` | |
| 995 | .file_scope = file_index, | |
| 996 | }); | |
| 997 | const struct_ty = try pt.createFileRootStruct(file_index, new_namespace_index); | |
| 1049 | 998 | errdefer zcu.intern_pool.remove(pt.tid, struct_ty); |
| 1050 | 999 | |
| 1051 | 1000 | switch (zcu.comp.cache_use) { |
| ... | ... | @@ -1067,98 +1016,121 @@ fn semaFile(pt: Zcu.PerThread, file_index: Zcu.File.Index) Zcu.SemaError!void { |
| 1067 | 1016 | |
| 1068 | 1017 | whole.cache_manifest_mutex.lock(); |
| 1069 | 1018 | defer whole.cache_manifest_mutex.unlock(); |
| 1070 | try man.addFilePostContents(resolved_path, source.bytes, source.stat); | |
| 1019 | man.addFilePostContents(resolved_path, source.bytes, source.stat) catch |err| switch (err) { | |
| 1020 | error.OutOfMemory => |e| return e, | |
| 1021 | else => { | |
| 1022 | try pt.reportRetryableFileError(file_index, "unable to update cache: {s}", .{@errorName(err)}); | |
| 1023 | return error.AnalysisFail; | |
| 1024 | }, | |
| 1025 | }; | |
| 1071 | 1026 | }, |
| 1072 | 1027 | .incremental => {}, |
| 1073 | 1028 | } |
| 1074 | 1029 | } |
| 1075 | 1030 | |
| 1076 | fn semaDecl(pt: Zcu.PerThread, decl_index: Zcu.Decl.Index) !Zcu.SemaDeclResult { | |
| 1077 | const tracy = trace(@src()); | |
| 1078 | defer tracy.end(); | |
| 1031 | const SemaCauResult = packed struct { | |
| 1032 | /// Whether the value of a `decl_val` of the corresponding Nav changed. | |
| 1033 | invalidate_decl_val: bool, | |
| 1034 | /// Whether the type of a `decl_ref` of the corresponding Nav changed. | |
| 1035 | invalidate_decl_ref: bool, | |
| 1036 | }; | |
| 1079 | 1037 | |
| 1038 | /// Performs semantic analysis on the given `Cau`, storing results to its owner `Nav` if needed. | |
| 1039 | /// If analysis fails, returns `error.AnalysisFail`, storing an error in `zcu.failed_analysis` unless | |
| 1040 | /// the error is transitive. | |
| 1041 | /// On success, returns information about whether the `Nav` value changed. | |
| 1042 | fn semaCau(pt: Zcu.PerThread, cau_index: InternPool.Cau.Index) !SemaCauResult { | |
| 1080 | 1043 | const zcu = pt.zcu; |
| 1081 | const decl = zcu.declPtr(decl_index); | |
| 1044 | const gpa = zcu.gpa; | |
| 1082 | 1045 | const ip = &zcu.intern_pool; |
| 1083 | 1046 | |
| 1084 | if (decl.getFileScope(zcu).status != .success_zir) { | |
| 1085 | return error.AnalysisFail; | |
| 1086 | } | |
| 1047 | const anal_unit = InternPool.AnalUnit.wrap(.{ .cau = cau_index }); | |
| 1087 | 1048 | |
| 1088 | assert(!zcu.declIsRoot(decl_index)); | |
| 1049 | const cau = ip.getCau(cau_index); | |
| 1050 | const inst_info = cau.zir_index.resolveFull(ip); | |
| 1051 | const file = zcu.fileByIndex(inst_info.file); | |
| 1052 | const zir = file.zir; | |
| 1089 | 1053 | |
| 1090 | if (decl.zir_decl_index == .none and decl.owns_tv) { | |
| 1091 | // We are re-analyzing an anonymous owner Decl (for a function or a namespace type). | |
| 1092 | return pt.semaAnonOwnerDecl(decl_index); | |
| 1054 | if (file.status != .success_zir) { | |
| 1055 | return error.AnalysisFail; | |
| 1093 | 1056 | } |
| 1094 | 1057 | |
| 1095 | log.debug("semaDecl '{d}'", .{@intFromEnum(decl_index)}); | |
| 1096 | log.debug("decl name '{}'", .{decl.fqn.fmt(ip)}); | |
| 1097 | defer log.debug("finish decl name '{}'", .{decl.fqn.fmt(ip)}); | |
| 1058 | // We are about to re-analyze this `Cau`; drop its depenndencies. | |
| 1059 | zcu.intern_pool.removeDependenciesForDepender(gpa, anal_unit); | |
| 1098 | 1060 | |
| 1099 | const old_has_tv = decl.has_tv; | |
| 1100 | // The following values are ignored if `!old_has_tv` | |
| 1101 | const old_ty = if (old_has_tv) decl.typeOf(zcu) else undefined; | |
| 1102 | const old_val = decl.val; | |
| 1103 | const old_align = decl.alignment; | |
| 1104 | const old_linksection = decl.@"linksection"; | |
| 1105 | const old_addrspace = decl.@"addrspace"; | |
| 1106 | const old_is_inline = if (decl.getOwnedFunction(zcu)) |prev_func| | |
| 1107 | prev_func.analysisUnordered(ip).state == .inline_only | |
| 1108 | else | |
| 1109 | false; | |
| 1110 | ||
| 1111 | const decl_inst = decl.zir_decl_index.unwrap().?.resolve(ip); | |
| 1061 | const builtin_type_target_index: InternPool.Index = switch (cau.owner.unwrap()) { | |
| 1062 | .none => ip_index: { | |
| 1063 | // `comptime` decl -- we will re-analyze its body. | |
| 1064 | // This declaration has no value so is definitely not a std.builtin type. | |
| 1065 | break :ip_index .none; | |
| 1066 | }, | |
| 1067 | .type => |ty| { | |
| 1068 | // This is an incremental update, and this type is being re-analyzed because it is outdated. | |
| 1069 | // The type must be recreated at a new `InternPool.Index`. | |
| 1070 | // Remove it from the InternPool and mark it outdated so that creation sites are re-analyzed. | |
| 1071 | ip.remove(pt.tid, ty); | |
| 1072 | return .{ | |
| 1073 | .invalidate_decl_val = true, | |
| 1074 | .invalidate_decl_ref = true, | |
| 1075 | }; | |
| 1076 | }, | |
| 1077 | .nav => |nav| ip_index: { | |
| 1078 | // Other decl -- we will re-analyze its value. | |
| 1079 | // This might be a type in `builtin.zig` -- check. | |
| 1080 | if (file.mod != zcu.std_mod) break :ip_index .none; | |
| 1081 | // We're in the std module. | |
| 1082 | const nav_name = ip.getNav(nav).name; | |
| 1083 | const std_file_imported = try pt.importPkg(zcu.std_mod); | |
| 1084 | const std_type = Type.fromInterned(zcu.fileRootType(std_file_imported.file_index)); | |
| 1085 | const std_namespace = zcu.namespacePtr(std_type.getNamespace(zcu).unwrap().?); | |
| 1086 | const builtin_str = try ip.getOrPutString(gpa, pt.tid, "builtin", .no_embedded_nulls); | |
| 1087 | const builtin_nav = ip.getNav(std_namespace.pub_decls.getKeyAdapted(builtin_str, Zcu.Namespace.NameAdapter{ .zcu = zcu }) orelse break :ip_index .none); | |
| 1088 | const builtin_namespace = switch (builtin_nav.status) { | |
| 1089 | .unresolved => break :ip_index .none, | |
| 1090 | .resolved => |r| Type.fromInterned(r.val).getNamespace(zcu).unwrap().?, | |
| 1091 | }; | |
| 1092 | if (cau.namespace != builtin_namespace) break :ip_index .none; | |
| 1093 | // We're in builtin.zig. This could be a builtin we need to add to a specific InternPool index. | |
| 1094 | for ([_][]const u8{ | |
| 1095 | "AtomicOrder", | |
| 1096 | "AtomicRmwOp", | |
| 1097 | "CallingConvention", | |
| 1098 | "AddressSpace", | |
| 1099 | "FloatMode", | |
| 1100 | "ReduceOp", | |
| 1101 | "CallModifier", | |
| 1102 | "PrefetchOptions", | |
| 1103 | "ExportOptions", | |
| 1104 | "ExternOptions", | |
| 1105 | "Type", | |
| 1106 | }, [_]InternPool.Index{ | |
| 1107 | .atomic_order_type, | |
| 1108 | .atomic_rmw_op_type, | |
| 1109 | .calling_convention_type, | |
| 1110 | .address_space_type, | |
| 1111 | .float_mode_type, | |
| 1112 | .reduce_op_type, | |
| 1113 | .call_modifier_type, | |
| 1114 | .prefetch_options_type, | |
| 1115 | .export_options_type, | |
| 1116 | .extern_options_type, | |
| 1117 | .type_info_type, | |
| 1118 | }) |type_name, type_ip| { | |
| 1119 | if (nav_name.eqlSlice(type_name, ip)) break :ip_index type_ip; | |
| 1120 | } | |
| 1121 | break :ip_index .none; | |
| 1122 | }, | |
| 1123 | }; | |
| 1112 | 1124 | |
| 1113 | const gpa = zcu.gpa; | |
| 1114 | const zir = decl.getFileScope(zcu).zir; | |
| 1115 | ||
| 1116 | const builtin_type_target_index: InternPool.Index = ip_index: { | |
| 1117 | const std_mod = zcu.std_mod; | |
| 1118 | if (decl.getFileScope(zcu).mod != std_mod) break :ip_index .none; | |
| 1119 | // We're in the std module. | |
| 1120 | const std_file_imported = try pt.importPkg(std_mod); | |
| 1121 | const std_file_root_decl_index = zcu.fileRootDecl(std_file_imported.file_index); | |
| 1122 | const std_decl = zcu.declPtr(std_file_root_decl_index.unwrap().?); | |
| 1123 | const std_namespace = std_decl.getInnerNamespace(zcu).?; | |
| 1124 | const builtin_str = try ip.getOrPutString(gpa, pt.tid, "builtin", .no_embedded_nulls); | |
| 1125 | const builtin_decl = zcu.declPtr(std_namespace.decls.getKeyAdapted(builtin_str, Zcu.DeclAdapter{ .zcu = zcu }) orelse break :ip_index .none); | |
| 1126 | const builtin_namespace = builtin_decl.getInnerNamespaceIndex(zcu).unwrap() orelse break :ip_index .none; | |
| 1127 | if (decl.src_namespace != builtin_namespace) break :ip_index .none; | |
| 1128 | // We're in builtin.zig. This could be a builtin we need to add to a specific InternPool index. | |
| 1129 | for ([_][]const u8{ | |
| 1130 | "AtomicOrder", | |
| 1131 | "AtomicRmwOp", | |
| 1132 | "CallingConvention", | |
| 1133 | "AddressSpace", | |
| 1134 | "FloatMode", | |
| 1135 | "ReduceOp", | |
| 1136 | "CallModifier", | |
| 1137 | "PrefetchOptions", | |
| 1138 | "ExportOptions", | |
| 1139 | "ExternOptions", | |
| 1140 | "Type", | |
| 1141 | }, [_]InternPool.Index{ | |
| 1142 | .atomic_order_type, | |
| 1143 | .atomic_rmw_op_type, | |
| 1144 | .calling_convention_type, | |
| 1145 | .address_space_type, | |
| 1146 | .float_mode_type, | |
| 1147 | .reduce_op_type, | |
| 1148 | .call_modifier_type, | |
| 1149 | .prefetch_options_type, | |
| 1150 | .export_options_type, | |
| 1151 | .extern_options_type, | |
| 1152 | .type_info_type, | |
| 1153 | }) |type_name, type_ip| { | |
| 1154 | if (decl.name.eqlSlice(type_name, ip)) break :ip_index type_ip; | |
| 1155 | } | |
| 1156 | break :ip_index .none; | |
| 1125 | const is_usingnamespace = switch (cau.owner.unwrap()) { | |
| 1126 | .nav => |nav| ip.getNav(nav).is_usingnamespace, | |
| 1127 | .none, .type => false, | |
| 1157 | 1128 | }; |
| 1158 | 1129 | |
| 1159 | zcu.intern_pool.removeDependenciesForDepender(gpa, InternPool.AnalUnit.wrap(.{ .decl = decl_index })); | |
| 1130 | log.debug("semaCau '{d}'", .{@intFromEnum(cau_index)}); | |
| 1160 | 1131 | |
| 1161 | decl.analysis = .in_progress; | |
| 1132 | try zcu.analysis_in_progress.put(gpa, anal_unit, {}); | |
| 1133 | errdefer _ = zcu.analysis_in_progress.swapRemove(anal_unit); | |
| 1162 | 1134 | |
| 1163 | 1135 | var analysis_arena = std.heap.ArenaAllocator.init(gpa); |
| 1164 | 1136 | defer analysis_arena.deinit(); |
| ... | ... | @@ -1171,224 +1143,216 @@ fn semaDecl(pt: Zcu.PerThread, decl_index: Zcu.Decl.Index) !Zcu.SemaDeclResult { |
| 1171 | 1143 | .gpa = gpa, |
| 1172 | 1144 | .arena = analysis_arena.allocator(), |
| 1173 | 1145 | .code = zir, |
| 1174 | .owner_decl = decl, | |
| 1175 | .owner_decl_index = decl_index, | |
| 1146 | .owner = anal_unit, | |
| 1176 | 1147 | .func_index = .none, |
| 1177 | 1148 | .func_is_naked = false, |
| 1178 | 1149 | .fn_ret_ty = Type.void, |
| 1179 | 1150 | .fn_ret_ty_ies = null, |
| 1180 | .owner_func_index = .none, | |
| 1181 | 1151 | .comptime_err_ret_trace = &comptime_err_ret_trace, |
| 1182 | 1152 | .builtin_type_target_index = builtin_type_target_index, |
| 1183 | 1153 | }; |
| 1184 | 1154 | defer sema.deinit(); |
| 1185 | 1155 | |
| 1186 | // Every Decl (other than file root Decls, which do not have a ZIR index) has a dependency on its own source. | |
| 1187 | try sema.declareDependency(.{ .src_hash = try ip.trackZir(gpa, pt.tid, .{ | |
| 1188 | .file = decl.getFileScopeIndex(zcu), | |
| 1189 | .inst = decl_inst, | |
| 1190 | }) }); | |
| 1156 | // Every `Cau` has a dependency on the source of its own ZIR instruction. | |
| 1157 | try sema.declareDependency(.{ .src_hash = cau.zir_index }); | |
| 1191 | 1158 | |
| 1192 | var block_scope: Sema.Block = .{ | |
| 1159 | var block: Sema.Block = .{ | |
| 1193 | 1160 | .parent = null, |
| 1194 | 1161 | .sema = &sema, |
| 1195 | .namespace = decl.src_namespace, | |
| 1162 | .namespace = cau.namespace, | |
| 1196 | 1163 | .instructions = .{}, |
| 1197 | 1164 | .inlining = null, |
| 1198 | 1165 | .is_comptime = true, |
| 1199 | .src_base_inst = decl.zir_decl_index.unwrap().?, | |
| 1200 | .type_name_ctx = decl.name, | |
| 1166 | .src_base_inst = cau.zir_index, | |
| 1167 | .type_name_ctx = switch (cau.owner.unwrap()) { | |
| 1168 | .nav => |nav| ip.getNav(nav).fqn, | |
| 1169 | .type => |ty| Type.fromInterned(ty).containerTypeName(ip), | |
| 1170 | .none => try ip.getOrPutStringFmt(gpa, pt.tid, "{}.comptime", .{ | |
| 1171 | Type.fromInterned(zcu.namespacePtr(cau.namespace).owner_type).containerTypeName(ip).fmt(ip), | |
| 1172 | }, .no_embedded_nulls), | |
| 1173 | }, | |
| 1174 | }; | |
| 1175 | defer block.instructions.deinit(gpa); | |
| 1176 | ||
| 1177 | const zir_decl: Zir.Inst.Declaration, const decl_bodies: Zir.Inst.Declaration.Bodies = decl: { | |
| 1178 | const decl, const extra_end = zir.getDeclaration(inst_info.inst); | |
| 1179 | break :decl .{ decl, decl.getBodies(extra_end, zir) }; | |
| 1180 | }; | |
| 1181 | ||
| 1182 | // We have to fetch this state before resolving the body because of the `nav_already_populated` | |
| 1183 | // case below. We might change the language in future so that align/linksection/etc for functions | |
| 1184 | // work in a way more in line with other declarations, in which case that logic will go away. | |
| 1185 | const old_nav_info = switch (cau.owner.unwrap()) { | |
| 1186 | .none, .type => undefined, // we'll never use `old_nav_info` | |
| 1187 | .nav => |nav| ip.getNav(nav), | |
| 1201 | 1188 | }; |
| 1202 | defer block_scope.instructions.deinit(gpa); | |
| 1203 | 1189 | |
| 1204 | const decl_bodies = decl.zirBodies(zcu); | |
| 1190 | const result_ref = try sema.resolveInlineBody(&block, decl_bodies.value_body, inst_info.inst); | |
| 1205 | 1191 | |
| 1206 | const result_ref = try sema.resolveInlineBody(&block_scope, decl_bodies.value_body, decl_inst); | |
| 1207 | // We'll do some other bits with the Sema. Clear the type target index just | |
| 1208 | // in case they analyze any type. | |
| 1192 | const nav_index = switch (cau.owner.unwrap()) { | |
| 1193 | .none => { | |
| 1194 | // This is a `comptime` decl, so we are done -- the side effects are all we care about. | |
| 1195 | // Just make sure to `flushExports`. | |
| 1196 | try sema.flushExports(); | |
| 1197 | assert(zcu.analysis_in_progress.swapRemove(anal_unit)); | |
| 1198 | return .{ | |
| 1199 | .invalidate_decl_val = false, | |
| 1200 | .invalidate_decl_ref = false, | |
| 1201 | }; | |
| 1202 | }, | |
| 1203 | .nav => |nav| nav, // We will resolve this `Nav` below. | |
| 1204 | .type => unreachable, // Handled at top of function. | |
| 1205 | }; | |
| 1206 | ||
| 1207 | // We'll do more work with the Sema. Clear the target type index just in case we analyze any type. | |
| 1209 | 1208 | sema.builtin_type_target_index = .none; |
| 1210 | const align_src = block_scope.src(.{ .node_offset_var_decl_align = 0 }); | |
| 1211 | const section_src = block_scope.src(.{ .node_offset_var_decl_section = 0 }); | |
| 1212 | const address_space_src = block_scope.src(.{ .node_offset_var_decl_addrspace = 0 }); | |
| 1213 | const ty_src = block_scope.src(.{ .node_offset_var_decl_ty = 0 }); | |
| 1214 | const init_src = block_scope.src(.{ .node_offset_var_decl_init = 0 }); | |
| 1215 | const decl_val = try sema.resolveFinalDeclValue(&block_scope, init_src, result_ref); | |
| 1209 | ||
| 1210 | const align_src = block.src(.{ .node_offset_var_decl_align = 0 }); | |
| 1211 | const section_src = block.src(.{ .node_offset_var_decl_section = 0 }); | |
| 1212 | const addrspace_src = block.src(.{ .node_offset_var_decl_addrspace = 0 }); | |
| 1213 | const ty_src = block.src(.{ .node_offset_var_decl_ty = 0 }); | |
| 1214 | const init_src = block.src(.{ .node_offset_var_decl_init = 0 }); | |
| 1215 | ||
| 1216 | const decl_val = try sema.resolveFinalDeclValue(&block, init_src, result_ref); | |
| 1216 | 1217 | const decl_ty = decl_val.typeOf(zcu); |
| 1217 | 1218 | |
| 1218 | // Note this resolves the type of the Decl, not the value; if this Decl | |
| 1219 | // is a struct, for example, this resolves `type` (which needs no resolution), | |
| 1220 | // not the struct itself. | |
| 1219 | switch (decl_val.toIntern()) { | |
| 1220 | .generic_poison => unreachable, // assertion failure | |
| 1221 | .unreachable_value => unreachable, // assertion failure | |
| 1222 | else => {}, | |
| 1223 | } | |
| 1224 | ||
| 1225 | // This resolves the type of the resolved value, not that value itself. If `decl_val` is a struct type, | |
| 1226 | // this resolves the type `type` (which needs no resolution), not the struct itself. | |
| 1221 | 1227 | try decl_ty.resolveLayout(pt); |
| 1222 | 1228 | |
| 1223 | if (decl.kind == .@"usingnamespace") { | |
| 1224 | if (!decl_ty.eql(Type.type, zcu)) { | |
| 1225 | return sema.fail(&block_scope, ty_src, "expected type, found {}", .{decl_ty.fmt(pt)}); | |
| 1229 | // TODO: this is jank. If #20663 is rejected, let's think about how to better model `usingnamespace`. | |
| 1230 | if (is_usingnamespace) { | |
| 1231 | if (decl_ty.toIntern() != .type_type) { | |
| 1232 | return sema.fail(&block, ty_src, "expected type, found {}", .{decl_ty.fmt(pt)}); | |
| 1226 | 1233 | } |
| 1227 | const ty = decl_val.toType(); | |
| 1228 | if (ty.getNamespace(zcu) == null) { | |
| 1229 | return sema.fail(&block_scope, ty_src, "type {} has no namespace", .{ty.fmt(pt)}); | |
| 1234 | if (decl_val.toType().getNamespace(zcu) == .none) { | |
| 1235 | return sema.fail(&block, ty_src, "type {} has no namespace", .{decl_val.toType().fmt(pt)}); | |
| 1230 | 1236 | } |
| 1231 | ||
| 1232 | decl.val = ty.toValue(); | |
| 1233 | decl.alignment = .none; | |
| 1234 | decl.@"linksection" = .none; | |
| 1235 | decl.has_tv = true; | |
| 1236 | decl.owns_tv = false; | |
| 1237 | decl.analysis = .complete; | |
| 1238 | ||
| 1239 | // TODO: usingnamespace cannot currently participate in incremental compilation | |
| 1237 | ip.resolveNavValue(nav_index, .{ | |
| 1238 | .val = decl_val.toIntern(), | |
| 1239 | .alignment = .none, | |
| 1240 | .@"linksection" = .none, | |
| 1241 | .@"addrspace" = .generic, | |
| 1242 | }); | |
| 1243 | // TODO: usingnamespace cannot participate in incremental compilation | |
| 1244 | assert(zcu.analysis_in_progress.swapRemove(anal_unit)); | |
| 1240 | 1245 | return .{ |
| 1241 | 1246 | .invalidate_decl_val = true, |
| 1242 | 1247 | .invalidate_decl_ref = true, |
| 1243 | 1248 | }; |
| 1244 | 1249 | } |
| 1245 | 1250 | |
| 1246 | var queue_linker_work = true; | |
| 1247 | var is_func = false; | |
| 1248 | var is_inline = false; | |
| 1249 | switch (decl_val.toIntern()) { | |
| 1250 | .generic_poison => unreachable, | |
| 1251 | .unreachable_value => unreachable, | |
| 1252 | else => switch (ip.indexToKey(decl_val.toIntern())) { | |
| 1253 | .variable => |variable| { | |
| 1254 | decl.owns_tv = variable.decl == decl_index; | |
| 1255 | queue_linker_work = decl.owns_tv; | |
| 1256 | }, | |
| 1257 | ||
| 1258 | .extern_func => |extern_func| { | |
| 1259 | decl.owns_tv = extern_func.decl == decl_index; | |
| 1260 | queue_linker_work = decl.owns_tv; | |
| 1261 | is_func = decl.owns_tv; | |
| 1262 | }, | |
| 1263 | ||
| 1264 | .func => |func| { | |
| 1265 | decl.owns_tv = func.owner_decl == decl_index; | |
| 1266 | queue_linker_work = false; | |
| 1267 | is_inline = decl.owns_tv and decl_ty.fnCallingConvention(zcu) == .Inline; | |
| 1268 | is_func = decl.owns_tv; | |
| 1269 | }, | |
| 1270 | ||
| 1271 | else => {}, | |
| 1272 | }, | |
| 1273 | } | |
| 1251 | const nav_already_populated, const queue_linker_work = switch (ip.indexToKey(decl_val.toIntern())) { | |
| 1252 | .func => |f| .{ f.owner_nav == nav_index, false }, | |
| 1253 | .variable => |v| .{ false, v.owner_nav == nav_index }, | |
| 1254 | .@"extern" => .{ false, false }, | |
| 1255 | else => .{ false, true }, | |
| 1256 | }; | |
| 1274 | 1257 | |
| 1275 | decl.val = decl_val; | |
| 1276 | // Function linksection, align, and addrspace were already set by Sema | |
| 1277 | if (!is_func) { | |
| 1278 | decl.alignment = blk: { | |
| 1279 | const align_body = decl_bodies.align_body orelse break :blk .none; | |
| 1280 | const align_ref = try sema.resolveInlineBody(&block_scope, align_body, decl_inst); | |
| 1281 | break :blk try sema.analyzeAsAlign(&block_scope, align_src, align_ref); | |
| 1258 | if (nav_already_populated) { | |
| 1259 | // This is a function declaration. | |
| 1260 | // Logic in `Sema.funcCommon` has already populated the `Nav` for us. | |
| 1261 | assert(ip.getNav(nav_index).status.resolved.val == decl_val.toIntern()); | |
| 1262 | } else { | |
| 1263 | // Keep in sync with logic in `Sema.zirVarExtended`. | |
| 1264 | const alignment: InternPool.Alignment = a: { | |
| 1265 | const align_body = decl_bodies.align_body orelse break :a .none; | |
| 1266 | const align_ref = try sema.resolveInlineBody(&block, align_body, inst_info.inst); | |
| 1267 | break :a try sema.analyzeAsAlign(&block, align_src, align_ref); | |
| 1282 | 1268 | }; |
| 1283 | decl.@"linksection" = blk: { | |
| 1284 | const linksection_body = decl_bodies.linksection_body orelse break :blk .none; | |
| 1285 | const linksection_ref = try sema.resolveInlineBody(&block_scope, linksection_body, decl_inst); | |
| 1286 | const bytes = try sema.toConstString(&block_scope, section_src, linksection_ref, .{ | |
| 1269 | ||
| 1270 | const @"linksection": InternPool.OptionalNullTerminatedString = ls: { | |
| 1271 | const linksection_body = decl_bodies.linksection_body orelse break :ls .none; | |
| 1272 | const linksection_ref = try sema.resolveInlineBody(&block, linksection_body, inst_info.inst); | |
| 1273 | const bytes = try sema.toConstString(&block, section_src, linksection_ref, .{ | |
| 1287 | 1274 | .needed_comptime_reason = "linksection must be comptime-known", |
| 1288 | 1275 | }); |
| 1289 | 1276 | if (std.mem.indexOfScalar(u8, bytes, 0) != null) { |
| 1290 | return sema.fail(&block_scope, section_src, "linksection cannot contain null bytes", .{}); | |
| 1277 | return sema.fail(&block, section_src, "linksection cannot contain null bytes", .{}); | |
| 1291 | 1278 | } else if (bytes.len == 0) { |
| 1292 | return sema.fail(&block_scope, section_src, "linksection cannot be empty", .{}); | |
| 1279 | return sema.fail(&block, section_src, "linksection cannot be empty", .{}); | |
| 1293 | 1280 | } |
| 1294 | break :blk try ip.getOrPutStringOpt(gpa, pt.tid, bytes, .no_embedded_nulls); | |
| 1281 | break :ls try ip.getOrPutStringOpt(gpa, pt.tid, bytes, .no_embedded_nulls); | |
| 1295 | 1282 | }; |
| 1296 | decl.@"addrspace" = blk: { | |
| 1283 | ||
| 1284 | const @"addrspace": std.builtin.AddressSpace = as: { | |
| 1297 | 1285 | const addrspace_ctx: Sema.AddressSpaceContext = switch (ip.indexToKey(decl_val.toIntern())) { |
| 1286 | .func => .function, | |
| 1298 | 1287 | .variable => .variable, |
| 1299 | .extern_func, .func => .function, | |
| 1288 | .@"extern" => |e| if (ip.indexToKey(e.ty) == .func_type) | |
| 1289 | .function | |
| 1290 | else | |
| 1291 | .variable, | |
| 1300 | 1292 | else => .constant, |
| 1301 | 1293 | }; |
| 1302 | ||
| 1303 | 1294 | const target = zcu.getTarget(); |
| 1304 | ||
| 1305 | const addrspace_body = decl_bodies.addrspace_body orelse break :blk switch (addrspace_ctx) { | |
| 1295 | const addrspace_body = decl_bodies.addrspace_body orelse break :as switch (addrspace_ctx) { | |
| 1306 | 1296 | .function => target_util.defaultAddressSpace(target, .function), |
| 1307 | 1297 | .variable => target_util.defaultAddressSpace(target, .global_mutable), |
| 1308 | 1298 | .constant => target_util.defaultAddressSpace(target, .global_constant), |
| 1309 | 1299 | else => unreachable, |
| 1310 | 1300 | }; |
| 1311 | const addrspace_ref = try sema.resolveInlineBody(&block_scope, addrspace_body, decl_inst); | |
| 1312 | break :blk try sema.analyzeAsAddressSpace(&block_scope, address_space_src, addrspace_ref, addrspace_ctx); | |
| 1301 | const addrspace_ref = try sema.resolveInlineBody(&block, addrspace_body, inst_info.inst); | |
| 1302 | break :as try sema.analyzeAsAddressSpace(&block, addrspace_src, addrspace_ref, addrspace_ctx); | |
| 1313 | 1303 | }; |
| 1314 | } | |
| 1315 | decl.has_tv = true; | |
| 1316 | decl.analysis = .complete; | |
| 1317 | ||
| 1318 | const result: Zcu.SemaDeclResult = if (old_has_tv) .{ | |
| 1319 | .invalidate_decl_val = !decl_ty.eql(old_ty, zcu) or | |
| 1320 | !decl.val.eql(old_val, decl_ty, zcu) or | |
| 1321 | is_inline != old_is_inline, | |
| 1322 | .invalidate_decl_ref = !decl_ty.eql(old_ty, zcu) or | |
| 1323 | decl.alignment != old_align or | |
| 1324 | decl.@"linksection" != old_linksection or | |
| 1325 | decl.@"addrspace" != old_addrspace or | |
| 1326 | is_inline != old_is_inline, | |
| 1327 | } else .{ | |
| 1328 | .invalidate_decl_val = true, | |
| 1329 | .invalidate_decl_ref = true, | |
| 1330 | }; | |
| 1331 | ||
| 1332 | const has_runtime_bits = queue_linker_work and (is_func or try sema.typeHasRuntimeBits(decl_ty)); | |
| 1333 | if (has_runtime_bits) { | |
| 1334 | // Needed for codegen_decl which will call updateDecl and then the | |
| 1335 | // codegen backend wants full access to the Decl Type. | |
| 1336 | try decl_ty.resolveFully(pt); | |
| 1337 | ||
| 1338 | try zcu.comp.queueJob(.{ .codegen_decl = decl_index }); | |
| 1339 | 1304 | |
| 1340 | if (result.invalidate_decl_ref and zcu.emit_h != null) { | |
| 1341 | try zcu.comp.queueJob(.{ .emit_h_decl = decl_index }); | |
| 1342 | } | |
| 1305 | ip.resolveNavValue(nav_index, .{ | |
| 1306 | .val = decl_val.toIntern(), | |
| 1307 | .alignment = alignment, | |
| 1308 | .@"linksection" = @"linksection", | |
| 1309 | .@"addrspace" = @"addrspace", | |
| 1310 | }); | |
| 1343 | 1311 | } |
| 1344 | 1312 | |
| 1345 | if (decl.is_exported) { | |
| 1346 | const export_src = block_scope.src(.{ .token_offset = @intFromBool(decl.is_pub) }); | |
| 1347 | if (is_inline) return sema.fail(&block_scope, export_src, "export of inline function", .{}); | |
| 1348 | // The scope needs to have the decl in it. | |
| 1349 | try sema.analyzeExport(&block_scope, export_src, .{ .name = decl.name }, decl_index); | |
| 1313 | // Mark the `Cau` as completed before evaluating the export! | |
| 1314 | assert(zcu.analysis_in_progress.swapRemove(anal_unit)); | |
| 1315 | ||
| 1316 | if (zir_decl.flags.is_export) { | |
| 1317 | const export_src = block.src(.{ .token_offset = @intFromBool(zir_decl.flags.is_pub) }); | |
| 1318 | const name_slice = zir.nullTerminatedString(zir_decl.name.toString(zir).?); | |
| 1319 | const name_ip = try ip.getOrPutString(gpa, pt.tid, name_slice, .no_embedded_nulls); | |
| 1320 | try sema.analyzeExport(&block, export_src, .{ .name = name_ip }, nav_index); | |
| 1350 | 1321 | } |
| 1351 | 1322 | |
| 1352 | 1323 | try sema.flushExports(); |
| 1353 | 1324 | |
| 1354 | return result; | |
| 1355 | } | |
| 1356 | ||
| 1357 | pub fn semaAnonOwnerDecl(pt: Zcu.PerThread, decl_index: Zcu.Decl.Index) !Zcu.SemaDeclResult { | |
| 1358 | const zcu = pt.zcu; | |
| 1359 | const decl = zcu.declPtr(decl_index); | |
| 1325 | queue_codegen: { | |
| 1326 | if (!queue_linker_work) break :queue_codegen; | |
| 1360 | 1327 | |
| 1361 | assert(decl.has_tv); | |
| 1362 | assert(decl.owns_tv); | |
| 1328 | // Needed for codegen_nav which will call updateDecl and then the | |
| 1329 | // codegen backend wants full access to the Decl Type. | |
| 1330 | // We also need this for the `isFnOrHasRuntimeBits` check below. | |
| 1331 | // TODO: we could make the language more lenient by deferring this work | |
| 1332 | // to the `codegen_nav` job. | |
| 1333 | try decl_ty.resolveFully(pt); | |
| 1363 | 1334 | |
| 1364 | log.debug("semaAnonOwnerDecl '{d}'", .{@intFromEnum(decl_index)}); | |
| 1335 | if (!decl_ty.isFnOrHasRuntimeBits(pt)) break :queue_codegen; | |
| 1365 | 1336 | |
| 1366 | switch (decl.typeOf(zcu).zigTypeTag(zcu)) { | |
| 1367 | .Fn => @panic("TODO: update fn instance"), | |
| 1368 | .Type => {}, | |
| 1369 | else => unreachable, | |
| 1337 | try zcu.comp.queueJob(.{ .codegen_nav = nav_index }); | |
| 1370 | 1338 | } |
| 1371 | 1339 | |
| 1372 | // We are the owner Decl of a type, and we were marked as outdated. That means the *structure* | |
| 1373 | // of this type changed; not just its namespace. Therefore, we need a new InternPool index. | |
| 1374 | // | |
| 1375 | // However, as soon as we make that, the context that created us will require re-analysis anyway | |
| 1376 | // (as it depends on this Decl's value), meaning the `struct_decl` (or equivalent) instruction | |
| 1377 | // will be analyzed again. Since Sema already needs to be able to reconstruct types like this, | |
| 1378 | // why should we bother implementing it here too when the Sema logic will be hit right after? | |
| 1379 | // | |
| 1380 | // So instead, let's just mark this Decl as failed - so that any remaining Decls which genuinely | |
| 1381 | // reference it (via `@This`) end up silently erroring too - and we'll let Sema make a new type | |
| 1382 | // with a new Decl. | |
| 1383 | // | |
| 1384 | // Yes, this does mean that any type owner Decl has a constant value for its entire lifetime. | |
| 1385 | zcu.intern_pool.removeDependenciesForDepender(zcu.gpa, InternPool.AnalUnit.wrap(.{ .decl = decl_index })); | |
| 1386 | zcu.intern_pool.remove(pt.tid, decl.val.toIntern()); | |
| 1387 | decl.analysis = .dependency_failure; | |
| 1388 | return .{ | |
| 1389 | .invalidate_decl_val = true, | |
| 1390 | .invalidate_decl_ref = true, | |
| 1391 | }; | |
| 1340 | switch (old_nav_info.status) { | |
| 1341 | .unresolved => return .{ | |
| 1342 | .invalidate_decl_val = true, | |
| 1343 | .invalidate_decl_ref = true, | |
| 1344 | }, | |
| 1345 | .resolved => |old| { | |
| 1346 | const new = ip.getNav(nav_index).status.resolved; | |
| 1347 | return .{ | |
| 1348 | .invalidate_decl_val = new.val != old.val, | |
| 1349 | .invalidate_decl_ref = ip.typeOf(new.val) != ip.typeOf(old.val) or | |
| 1350 | new.alignment != old.alignment or | |
| 1351 | new.@"linksection" != old.@"linksection" or | |
| 1352 | new.@"addrspace" != old.@"addrspace", | |
| 1353 | }; | |
| 1354 | }, | |
| 1355 | } | |
| 1392 | 1356 | } |
| 1393 | 1357 | |
| 1394 | 1358 | pub fn importPkg(pt: Zcu.PerThread, mod: *Module) !Zcu.ImportFileResult { |
| ... | ... | @@ -1426,7 +1390,7 @@ pub fn importPkg(pt: Zcu.PerThread, mod: *Module) !Zcu.ImportFileResult { |
| 1426 | 1390 | const file_index = try ip.createFile(gpa, pt.tid, .{ |
| 1427 | 1391 | .bin_digest = path_digest, |
| 1428 | 1392 | .file = builtin_file, |
| 1429 | .root_decl = .none, | |
| 1393 | .root_type = .none, | |
| 1430 | 1394 | }); |
| 1431 | 1395 | keep_resolved_path = true; // It's now owned by import_table. |
| 1432 | 1396 | gop.value_ptr.* = file_index; |
| ... | ... | @@ -1453,7 +1417,7 @@ pub fn importPkg(pt: Zcu.PerThread, mod: *Module) !Zcu.ImportFileResult { |
| 1453 | 1417 | const new_file_index = try ip.createFile(gpa, pt.tid, .{ |
| 1454 | 1418 | .bin_digest = path_digest, |
| 1455 | 1419 | .file = new_file, |
| 1456 | .root_decl = .none, | |
| 1420 | .root_type = .none, | |
| 1457 | 1421 | }); |
| 1458 | 1422 | keep_resolved_path = true; // It's now owned by import_table. |
| 1459 | 1423 | gop.value_ptr.* = new_file_index; |
| ... | ... | @@ -1563,7 +1527,7 @@ pub fn importFile( |
| 1563 | 1527 | const new_file_index = try ip.createFile(gpa, pt.tid, .{ |
| 1564 | 1528 | .bin_digest = path_digest, |
| 1565 | 1529 | .file = new_file, |
| 1566 | .root_decl = .none, | |
| 1530 | .root_type = .none, | |
| 1567 | 1531 | }); |
| 1568 | 1532 | keep_resolved_path = true; // It's now owned by import_table. |
| 1569 | 1533 | gop.value_ptr.* = new_file_index; |
| ... | ... | @@ -1726,7 +1690,7 @@ fn newEmbedFile( |
| 1726 | 1690 | })).toIntern(); |
| 1727 | 1691 | const ptr_val = try pt.intern(.{ .ptr = .{ |
| 1728 | 1692 | .ty = ptr_ty, |
| 1729 | .base_addr = .{ .anon_decl = .{ | |
| 1693 | .base_addr = .{ .uav = .{ | |
| 1730 | 1694 | .val = array_val, |
| 1731 | 1695 | .orig_ty = ptr_ty, |
| 1732 | 1696 | } }, |
| ... | ... | @@ -1748,39 +1712,70 @@ pub fn scanNamespace( |
| 1748 | 1712 | pt: Zcu.PerThread, |
| 1749 | 1713 | namespace_index: Zcu.Namespace.Index, |
| 1750 | 1714 | decls: []const Zir.Inst.Index, |
| 1751 | parent_decl: *Zcu.Decl, | |
| 1752 | 1715 | ) Allocator.Error!void { |
| 1753 | 1716 | const tracy = trace(@src()); |
| 1754 | 1717 | defer tracy.end(); |
| 1755 | 1718 | |
| 1756 | 1719 | const zcu = pt.zcu; |
| 1720 | const ip = &zcu.intern_pool; | |
| 1757 | 1721 | const gpa = zcu.gpa; |
| 1758 | 1722 | const namespace = zcu.namespacePtr(namespace_index); |
| 1759 | 1723 | |
| 1760 | 1724 | // For incremental updates, `scanDecl` wants to look up existing decls by their ZIR index rather |
| 1761 | 1725 | // than their name. We'll build an efficient mapping now, then discard the current `decls`. |
| 1762 | var existing_by_inst: std.AutoHashMapUnmanaged(InternPool.TrackedInst.Index, Zcu.Decl.Index) = .{}; | |
| 1726 | // We map to the `Cau`, since not every declaration has a `Nav`. | |
| 1727 | var existing_by_inst: std.AutoHashMapUnmanaged(InternPool.TrackedInst.Index, InternPool.Cau.Index) = .{}; | |
| 1763 | 1728 | defer existing_by_inst.deinit(gpa); |
| 1764 | 1729 | |
| 1765 | try existing_by_inst.ensureTotalCapacity(gpa, @intCast(namespace.decls.count())); | |
| 1766 | ||
| 1767 | for (namespace.decls.keys()) |decl_index| { | |
| 1768 | const decl = zcu.declPtr(decl_index); | |
| 1769 | existing_by_inst.putAssumeCapacityNoClobber(decl.zir_decl_index.unwrap().?, decl_index); | |
| 1730 | try existing_by_inst.ensureTotalCapacity(gpa, @intCast( | |
| 1731 | namespace.pub_decls.count() + namespace.priv_decls.count() + | |
| 1732 | namespace.pub_usingnamespace.items.len + namespace.priv_usingnamespace.items.len + | |
| 1733 | namespace.other_decls.items.len, | |
| 1734 | )); | |
| 1735 | ||
| 1736 | for (namespace.pub_decls.keys()) |nav| { | |
| 1737 | const cau_index = ip.getNav(nav).analysis_owner.unwrap().?; | |
| 1738 | const zir_index = ip.getCau(cau_index).zir_index; | |
| 1739 | existing_by_inst.putAssumeCapacityNoClobber(zir_index, cau_index); | |
| 1740 | } | |
| 1741 | for (namespace.priv_decls.keys()) |nav| { | |
| 1742 | const cau_index = ip.getNav(nav).analysis_owner.unwrap().?; | |
| 1743 | const zir_index = ip.getCau(cau_index).zir_index; | |
| 1744 | existing_by_inst.putAssumeCapacityNoClobber(zir_index, cau_index); | |
| 1745 | } | |
| 1746 | for (namespace.pub_usingnamespace.items) |nav| { | |
| 1747 | const cau_index = ip.getNav(nav).analysis_owner.unwrap().?; | |
| 1748 | const zir_index = ip.getCau(cau_index).zir_index; | |
| 1749 | existing_by_inst.putAssumeCapacityNoClobber(zir_index, cau_index); | |
| 1750 | } | |
| 1751 | for (namespace.priv_usingnamespace.items) |nav| { | |
| 1752 | const cau_index = ip.getNav(nav).analysis_owner.unwrap().?; | |
| 1753 | const zir_index = ip.getCau(cau_index).zir_index; | |
| 1754 | existing_by_inst.putAssumeCapacityNoClobber(zir_index, cau_index); | |
| 1755 | } | |
| 1756 | for (namespace.other_decls.items) |cau_index| { | |
| 1757 | const cau = ip.getCau(cau_index); | |
| 1758 | existing_by_inst.putAssumeCapacityNoClobber(cau.zir_index, cau_index); | |
| 1759 | // If this is a test, it'll be re-added to `test_functions` later on | |
| 1760 | // if still alive. Remove it for now. | |
| 1761 | switch (cau.owner.unwrap()) { | |
| 1762 | .none, .type => {}, | |
| 1763 | .nav => |nav| _ = zcu.test_functions.swapRemove(nav), | |
| 1764 | } | |
| 1770 | 1765 | } |
| 1771 | 1766 | |
| 1772 | 1767 | var seen_decls: std.AutoHashMapUnmanaged(InternPool.NullTerminatedString, void) = .{}; |
| 1773 | 1768 | defer seen_decls.deinit(gpa); |
| 1774 | 1769 | |
| 1775 | namespace.decls.clearRetainingCapacity(); | |
| 1776 | try namespace.decls.ensureTotalCapacity(gpa, decls.len); | |
| 1777 | ||
| 1778 | namespace.usingnamespace_set.clearRetainingCapacity(); | |
| 1770 | namespace.pub_decls.clearRetainingCapacity(); | |
| 1771 | namespace.priv_decls.clearRetainingCapacity(); | |
| 1772 | namespace.pub_usingnamespace.clearRetainingCapacity(); | |
| 1773 | namespace.priv_usingnamespace.clearRetainingCapacity(); | |
| 1774 | namespace.other_decls.clearRetainingCapacity(); | |
| 1779 | 1775 | |
| 1780 | 1776 | var scan_decl_iter: ScanDeclIter = .{ |
| 1781 | 1777 | .pt = pt, |
| 1782 | 1778 | .namespace_index = namespace_index, |
| 1783 | .parent_decl = parent_decl, | |
| 1784 | 1779 | .seen_decls = &seen_decls, |
| 1785 | 1780 | .existing_by_inst = &existing_by_inst, |
| 1786 | 1781 | .pass = .named, |
| ... | ... | @@ -1792,34 +1787,17 @@ pub fn scanNamespace( |
| 1792 | 1787 | for (decls) |decl_inst| { |
| 1793 | 1788 | try scan_decl_iter.scanDecl(decl_inst); |
| 1794 | 1789 | } |
| 1795 | ||
| 1796 | if (seen_decls.count() != namespace.decls.count()) { | |
| 1797 | // Do a pass over the namespace contents and remove any decls from the last update | |
| 1798 | // which were removed in this one. | |
| 1799 | var i: usize = 0; | |
| 1800 | while (i < namespace.decls.count()) { | |
| 1801 | const decl_index = namespace.decls.keys()[i]; | |
| 1802 | const decl = zcu.declPtr(decl_index); | |
| 1803 | if (!seen_decls.contains(decl.name)) { | |
| 1804 | // We must preserve namespace ordering for @typeInfo. | |
| 1805 | namespace.decls.orderedRemoveAt(i); | |
| 1806 | i -= 1; | |
| 1807 | } | |
| 1808 | } | |
| 1809 | } | |
| 1810 | 1790 | } |
| 1811 | 1791 | |
| 1812 | 1792 | const ScanDeclIter = struct { |
| 1813 | 1793 | pt: Zcu.PerThread, |
| 1814 | 1794 | namespace_index: Zcu.Namespace.Index, |
| 1815 | parent_decl: *Zcu.Decl, | |
| 1816 | 1795 | seen_decls: *std.AutoHashMapUnmanaged(InternPool.NullTerminatedString, void), |
| 1817 | existing_by_inst: *const std.AutoHashMapUnmanaged(InternPool.TrackedInst.Index, Zcu.Decl.Index), | |
| 1796 | existing_by_inst: *const std.AutoHashMapUnmanaged(InternPool.TrackedInst.Index, InternPool.Cau.Index), | |
| 1818 | 1797 | /// Decl scanning is run in two passes, so that we can detect when a generated |
| 1819 | 1798 | /// name would clash with an explicit name and use a different one. |
| 1820 | 1799 | pass: enum { named, unnamed }, |
| 1821 | 1800 | usingnamespace_index: usize = 0, |
| 1822 | comptime_index: usize = 0, | |
| 1823 | 1801 | unnamed_test_index: usize = 0, |
| 1824 | 1802 | |
| 1825 | 1803 | fn avoidNameConflict(iter: *ScanDeclIter, comptime fmt: []const u8, args: anytype) !InternPool.NullTerminatedString { |
| ... | ... | @@ -1843,37 +1821,35 @@ const ScanDeclIter = struct { |
| 1843 | 1821 | |
| 1844 | 1822 | const pt = iter.pt; |
| 1845 | 1823 | const zcu = pt.zcu; |
| 1824 | const comp = zcu.comp; | |
| 1846 | 1825 | const namespace_index = iter.namespace_index; |
| 1847 | 1826 | const namespace = zcu.namespacePtr(namespace_index); |
| 1848 | 1827 | const gpa = zcu.gpa; |
| 1849 | const zir = namespace.fileScope(zcu).zir; | |
| 1828 | const file = namespace.fileScope(zcu); | |
| 1829 | const zir = file.zir; | |
| 1850 | 1830 | const ip = &zcu.intern_pool; |
| 1851 | 1831 | |
| 1852 | 1832 | const inst_data = zir.instructions.items(.data)[@intFromEnum(decl_inst)].declaration; |
| 1853 | 1833 | const extra = zir.extraData(Zir.Inst.Declaration, inst_data.payload_index); |
| 1854 | 1834 | const declaration = extra.data; |
| 1855 | 1835 | |
| 1856 | // Every Decl needs a name. | |
| 1857 | const decl_name: InternPool.NullTerminatedString, const kind: Zcu.Decl.Kind, const is_named_test: bool = switch (declaration.name) { | |
| 1836 | const Kind = enum { @"comptime", @"usingnamespace", @"test", named }; | |
| 1837 | ||
| 1838 | const maybe_name: InternPool.OptionalNullTerminatedString, const kind: Kind, const is_named_test: bool = switch (declaration.name) { | |
| 1858 | 1839 | .@"comptime" => info: { |
| 1859 | 1840 | if (iter.pass != .unnamed) return; |
| 1860 | const i = iter.comptime_index; | |
| 1861 | iter.comptime_index += 1; | |
| 1862 | 1841 | break :info .{ |
| 1863 | try iter.avoidNameConflict("comptime_{d}", .{i}), | |
| 1842 | .none, | |
| 1864 | 1843 | .@"comptime", |
| 1865 | 1844 | false, |
| 1866 | 1845 | }; |
| 1867 | 1846 | }, |
| 1868 | 1847 | .@"usingnamespace" => info: { |
| 1869 | // TODO: this isn't right! These should be considered unnamed. Name conflicts can happen here. | |
| 1870 | // The problem is, we need to preserve the decl ordering for `@typeInfo`. | |
| 1871 | // I'm not bothering to fix this now, since some upcoming changes will change this code significantly anyway. | |
| 1872 | if (iter.pass != .named) return; | |
| 1848 | if (iter.pass != .unnamed) return; | |
| 1873 | 1849 | const i = iter.usingnamespace_index; |
| 1874 | 1850 | iter.usingnamespace_index += 1; |
| 1875 | 1851 | break :info .{ |
| 1876 | try iter.avoidNameConflict("usingnamespace_{d}", .{i}), | |
| 1852 | (try iter.avoidNameConflict("usingnamespace_{d}", .{i})).toOptional(), | |
| 1877 | 1853 | .@"usingnamespace", |
| 1878 | 1854 | false, |
| 1879 | 1855 | }; |
| ... | ... | @@ -1883,7 +1859,7 @@ const ScanDeclIter = struct { |
| 1883 | 1859 | const i = iter.unnamed_test_index; |
| 1884 | 1860 | iter.unnamed_test_index += 1; |
| 1885 | 1861 | break :info .{ |
| 1886 | try iter.avoidNameConflict("test_{d}", .{i}), | |
| 1862 | (try iter.avoidNameConflict("test_{d}", .{i})).toOptional(), | |
| 1887 | 1863 | .@"test", |
| 1888 | 1864 | false, |
| 1889 | 1865 | }; |
| ... | ... | @@ -1894,7 +1870,7 @@ const ScanDeclIter = struct { |
| 1894 | 1870 | assert(declaration.flags.has_doc_comment); |
| 1895 | 1871 | const name = zir.nullTerminatedString(@enumFromInt(zir.extra[extra.end])); |
| 1896 | 1872 | break :info .{ |
| 1897 | try iter.avoidNameConflict("decltest.{s}", .{name}), | |
| 1873 | (try iter.avoidNameConflict("decltest.{s}", .{name})).toOptional(), | |
| 1898 | 1874 | .@"test", |
| 1899 | 1875 | true, |
| 1900 | 1876 | }; |
| ... | ... | @@ -1903,7 +1879,7 @@ const ScanDeclIter = struct { |
| 1903 | 1879 | // We consider these to be unnamed since the decl name can be adjusted to avoid conflicts if necessary. |
| 1904 | 1880 | if (iter.pass != .unnamed) return; |
| 1905 | 1881 | break :info .{ |
| 1906 | try iter.avoidNameConflict("test.{s}", .{zir.nullTerminatedString(declaration.name.toString(zir).?)}), | |
| 1882 | (try iter.avoidNameConflict("test.{s}", .{zir.nullTerminatedString(declaration.name.toString(zir).?)})).toOptional(), | |
| 1907 | 1883 | .@"test", |
| 1908 | 1884 | true, |
| 1909 | 1885 | }; |
| ... | ... | @@ -1917,132 +1893,144 @@ const ScanDeclIter = struct { |
| 1917 | 1893 | ); |
| 1918 | 1894 | try iter.seen_decls.putNoClobber(gpa, name, {}); |
| 1919 | 1895 | break :info .{ |
| 1920 | name, | |
| 1896 | name.toOptional(), | |
| 1921 | 1897 | .named, |
| 1922 | 1898 | false, |
| 1923 | 1899 | }; |
| 1924 | 1900 | }, |
| 1925 | 1901 | }; |
| 1926 | 1902 | |
| 1927 | switch (kind) { | |
| 1928 | .@"usingnamespace" => try namespace.usingnamespace_set.ensureUnusedCapacity(gpa, 1), | |
| 1929 | .@"test" => try zcu.test_functions.ensureUnusedCapacity(gpa, 1), | |
| 1930 | else => {}, | |
| 1931 | } | |
| 1932 | ||
| 1933 | const parent_file_scope_index = iter.parent_decl.getFileScopeIndex(zcu); | |
| 1934 | 1903 | const tracked_inst = try ip.trackZir(gpa, pt.tid, .{ |
| 1935 | .file = parent_file_scope_index, | |
| 1904 | .file = namespace.file_scope, | |
| 1936 | 1905 | .inst = decl_inst, |
| 1937 | 1906 | }); |
| 1938 | 1907 | |
| 1939 | // We create a Decl for it regardless of analysis status. | |
| 1940 | ||
| 1941 | const prev_exported, const decl_index = if (iter.existing_by_inst.get(tracked_inst)) |decl_index| decl_index: { | |
| 1942 | // We need only update this existing Decl. | |
| 1943 | const decl = zcu.declPtr(decl_index); | |
| 1944 | const was_exported = decl.is_exported; | |
| 1945 | assert(decl.kind == kind); // ZIR tracking should preserve this | |
| 1946 | decl.name = decl_name; | |
| 1947 | decl.fqn = try namespace.internFullyQualifiedName(ip, gpa, pt.tid, decl_name); | |
| 1948 | decl.is_pub = declaration.flags.is_pub; | |
| 1949 | decl.is_exported = declaration.flags.is_export; | |
| 1950 | break :decl_index .{ was_exported, decl_index }; | |
| 1951 | } else decl_index: { | |
| 1952 | // Create and set up a new Decl. | |
| 1953 | const new_decl_index = try pt.allocateNewDecl(namespace_index); | |
| 1954 | const new_decl = zcu.declPtr(new_decl_index); | |
| 1955 | new_decl.kind = kind; | |
| 1956 | new_decl.name = decl_name; | |
| 1957 | new_decl.fqn = try namespace.internFullyQualifiedName(ip, gpa, pt.tid, decl_name); | |
| 1958 | new_decl.is_pub = declaration.flags.is_pub; | |
| 1959 | new_decl.is_exported = declaration.flags.is_export; | |
| 1960 | new_decl.zir_decl_index = tracked_inst.toOptional(); | |
| 1961 | break :decl_index .{ false, new_decl_index }; | |
| 1962 | }; | |
| 1963 | ||
| 1964 | const decl = zcu.declPtr(decl_index); | |
| 1965 | ||
| 1966 | namespace.decls.putAssumeCapacityNoClobberContext(decl_index, {}, .{ .zcu = zcu }); | |
| 1908 | const existing_cau = iter.existing_by_inst.get(tracked_inst); | |
| 1909 | ||
| 1910 | const cau, const want_analysis = switch (kind) { | |
| 1911 | .@"comptime" => cau: { | |
| 1912 | const cau = existing_cau orelse try ip.createComptimeCau(gpa, pt.tid, tracked_inst, namespace_index); | |
| 1913 | ||
| 1914 | // For a `comptime` declaration, whether to re-analyze is based solely on whether the | |
| 1915 | // `Cau` is outdated. So, add this one to `outdated` and `outdated_ready` if not already. | |
| 1916 | const unit = InternPool.AnalUnit.wrap(.{ .cau = cau }); | |
| 1917 | if (zcu.potentially_outdated.fetchSwapRemove(unit)) |kv| { | |
| 1918 | try zcu.outdated.ensureUnusedCapacity(gpa, 1); | |
| 1919 | try zcu.outdated_ready.ensureUnusedCapacity(gpa, 1); | |
| 1920 | zcu.outdated.putAssumeCapacityNoClobber(unit, kv.value); | |
| 1921 | if (kv.value == 0) { // no PO deps | |
| 1922 | zcu.outdated_ready.putAssumeCapacityNoClobber(unit, {}); | |
| 1923 | } | |
| 1924 | } else if (!zcu.outdated.contains(unit)) { | |
| 1925 | try zcu.outdated.ensureUnusedCapacity(gpa, 1); | |
| 1926 | try zcu.outdated_ready.ensureUnusedCapacity(gpa, 1); | |
| 1927 | zcu.outdated.putAssumeCapacityNoClobber(unit, 0); | |
| 1928 | zcu.outdated_ready.putAssumeCapacityNoClobber(unit, {}); | |
| 1929 | } | |
| 1967 | 1930 | |
| 1968 | const comp = zcu.comp; | |
| 1969 | const decl_mod = namespace.fileScope(zcu).mod; | |
| 1970 | const want_analysis = declaration.flags.is_export or switch (kind) { | |
| 1971 | .anon => unreachable, | |
| 1972 | .@"comptime" => true, | |
| 1973 | .@"usingnamespace" => a: { | |
| 1974 | namespace.usingnamespace_set.putAssumeCapacityNoClobber(decl_index, declaration.flags.is_pub); | |
| 1975 | break :a true; | |
| 1931 | break :cau .{ cau, true }; | |
| 1976 | 1932 | }, |
| 1977 | .named => false, | |
| 1978 | .@"test" => a: { | |
| 1979 | if (!comp.config.is_test) break :a false; | |
| 1980 | if (decl_mod != zcu.main_mod) break :a false; | |
| 1981 | if (is_named_test and comp.test_filters.len > 0) { | |
| 1982 | const decl_fqn = decl.fqn.toSlice(ip); | |
| 1983 | for (comp.test_filters) |test_filter| { | |
| 1984 | if (std.mem.indexOf(u8, decl_fqn, test_filter)) |_| break; | |
| 1985 | } else break :a false; | |
| 1986 | } | |
| 1987 | zcu.test_functions.putAssumeCapacity(decl_index, {}); // may clobber on incremental update | |
| 1988 | break :a true; | |
| 1933 | else => cau: { | |
| 1934 | const name = maybe_name.unwrap().?; | |
| 1935 | const fqn = try namespace.internFullyQualifiedName(ip, gpa, pt.tid, name); | |
| 1936 | const cau, const nav = if (existing_cau) |cau_index| cau_nav: { | |
| 1937 | const nav_index = ip.getCau(cau_index).owner.unwrap().nav; | |
| 1938 | const nav = ip.getNav(nav_index); | |
| 1939 | assert(nav.name == name); | |
| 1940 | assert(nav.fqn == fqn); | |
| 1941 | break :cau_nav .{ cau_index, nav_index }; | |
| 1942 | } else try ip.createPairedCauNav(gpa, pt.tid, name, fqn, tracked_inst, namespace_index, kind == .@"usingnamespace"); | |
| 1943 | const want_analysis = switch (kind) { | |
| 1944 | .@"comptime" => unreachable, | |
| 1945 | .@"usingnamespace" => a: { | |
| 1946 | if (declaration.flags.is_pub) { | |
| 1947 | try namespace.pub_usingnamespace.append(gpa, nav); | |
| 1948 | } else { | |
| 1949 | try namespace.priv_usingnamespace.append(gpa, nav); | |
| 1950 | } | |
| 1951 | break :a true; | |
| 1952 | }, | |
| 1953 | .@"test" => a: { | |
| 1954 | try namespace.other_decls.append(gpa, cau); | |
| 1955 | // TODO: incremental compilation! | |
| 1956 | // * remove from `test_functions` if no longer matching filter | |
| 1957 | // * add to `test_functions` if newly passing filter | |
| 1958 | // This logic is unaware of incremental: we'll end up with duplicates. | |
| 1959 | // Perhaps we should add all test indiscriminately and filter at the end of the update. | |
| 1960 | if (!comp.config.is_test) break :a false; | |
| 1961 | if (file.mod != zcu.main_mod) break :a false; | |
| 1962 | if (is_named_test and comp.test_filters.len > 0) { | |
| 1963 | const fqn_slice = fqn.toSlice(ip); | |
| 1964 | for (comp.test_filters) |test_filter| { | |
| 1965 | if (std.mem.indexOf(u8, fqn_slice, test_filter) != null) break; | |
| 1966 | } else break :a false; | |
| 1967 | } | |
| 1968 | try zcu.test_functions.put(gpa, nav, {}); | |
| 1969 | break :a true; | |
| 1970 | }, | |
| 1971 | .named => a: { | |
| 1972 | if (declaration.flags.is_pub) { | |
| 1973 | try namespace.pub_decls.putContext(gpa, nav, {}, .{ .zcu = zcu }); | |
| 1974 | } else { | |
| 1975 | try namespace.priv_decls.putContext(gpa, nav, {}, .{ .zcu = zcu }); | |
| 1976 | } | |
| 1977 | break :a false; | |
| 1978 | }, | |
| 1979 | }; | |
| 1980 | break :cau .{ cau, want_analysis }; | |
| 1989 | 1981 | }, |
| 1990 | 1982 | }; |
| 1991 | 1983 | |
| 1992 | if (want_analysis) { | |
| 1993 | // We will not queue analysis if the decl has been analyzed on a previous update and | |
| 1994 | // `is_export` is unchanged. In this case, the incremental update mechanism will handle | |
| 1995 | // re-analysis for us if necessary. | |
| 1996 | if (prev_exported != declaration.flags.is_export or decl.analysis == .unreferenced) { | |
| 1997 | log.debug("scanDecl queue analyze_decl file='{s}' decl_name='{}' decl_index={d}", .{ | |
| 1998 | namespace.fileScope(zcu).sub_file_path, decl_name.fmt(ip), decl_index, | |
| 1999 | }); | |
| 2000 | try comp.queueJob(.{ .analyze_decl = decl_index }); | |
| 2001 | } | |
| 1984 | if (want_analysis or declaration.flags.is_export) { | |
| 1985 | log.debug( | |
| 1986 | "scanDecl queue analyze_cau file='{s}' cau_index={d}", | |
| 1987 | .{ namespace.fileScope(zcu).sub_file_path, cau }, | |
| 1988 | ); | |
| 1989 | try comp.queueJob(.{ .analyze_cau = cau }); | |
| 2002 | 1990 | } |
| 2003 | 1991 | |
| 2004 | if (decl.getOwnedFunction(zcu) != null) { | |
| 2005 | // TODO this logic is insufficient; namespaces we don't re-scan may still require | |
| 2006 | // updated line numbers. Look into this! | |
| 2007 | // TODO Look into detecting when this would be unnecessary by storing enough state | |
| 2008 | // in `Decl` to notice that the line number did not change. | |
| 2009 | try comp.queueJob(.{ .update_line_number = decl_index }); | |
| 2010 | } | |
| 1992 | // TODO: we used to do line number updates here, but this is an inappropriate place for this logic to live. | |
| 2011 | 1993 | } |
| 2012 | 1994 | }; |
| 2013 | 1995 | |
| 2014 | /// Cancel the creation of an anon decl and delete any references to it. | |
| 2015 | /// If other decls depend on this decl, they must be aborted first. | |
| 2016 | pub fn abortAnonDecl(pt: Zcu.PerThread, decl_index: Zcu.Decl.Index) void { | |
| 2017 | assert(!pt.zcu.declIsRoot(decl_index)); | |
| 2018 | pt.destroyDecl(decl_index); | |
| 2019 | } | |
| 2020 | ||
| 2021 | /// Finalize the creation of an anon decl. | |
| 2022 | pub fn finalizeAnonDecl(pt: Zcu.PerThread, decl_index: Zcu.Decl.Index) Allocator.Error!void { | |
| 2023 | if (pt.zcu.declPtr(decl_index).typeOf(pt.zcu).isFnOrHasRuntimeBits(pt)) { | |
| 2024 | try pt.zcu.comp.queueJob(.{ .codegen_decl = decl_index }); | |
| 2025 | } | |
| 2026 | } | |
| 2027 | ||
| 2028 | pub fn analyzeFnBody(pt: Zcu.PerThread, func_index: InternPool.Index, arena: Allocator) Zcu.SemaError!Air { | |
| 1996 | fn analyzeFnBody(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.SemaError!Air { | |
| 2029 | 1997 | const tracy = trace(@src()); |
| 2030 | 1998 | defer tracy.end(); |
| 2031 | 1999 | |
| 2032 | const mod = pt.zcu; | |
| 2033 | const gpa = mod.gpa; | |
| 2034 | const ip = &mod.intern_pool; | |
| 2035 | const func = mod.funcInfo(func_index); | |
| 2036 | const decl_index = func.owner_decl; | |
| 2037 | const decl = mod.declPtr(decl_index); | |
| 2000 | const zcu = pt.zcu; | |
| 2001 | const gpa = zcu.gpa; | |
| 2002 | const ip = &zcu.intern_pool; | |
| 2003 | ||
| 2004 | const anal_unit = InternPool.AnalUnit.wrap(.{ .func = func_index }); | |
| 2005 | const func = zcu.funcInfo(func_index); | |
| 2006 | const inst_info = func.zir_body_inst.resolveFull(ip); | |
| 2007 | const file = zcu.fileByIndex(inst_info.file); | |
| 2008 | const zir = file.zir; | |
| 2009 | ||
| 2010 | try zcu.analysis_in_progress.put(gpa, anal_unit, {}); | |
| 2011 | errdefer _ = zcu.analysis_in_progress.swapRemove(anal_unit); | |
| 2012 | ||
| 2013 | func.setAnalysisState(ip, .analyzed); | |
| 2014 | ||
| 2015 | // This is the `Cau` corresponding to the `declaration` instruction which the function or its generic owner originates from. | |
| 2016 | const decl_cau = ip.getCau(cau: { | |
| 2017 | const orig_nav = if (func.generic_owner == .none) | |
| 2018 | func.owner_nav | |
| 2019 | else | |
| 2020 | zcu.funcInfo(func.generic_owner).owner_nav; | |
| 2021 | ||
| 2022 | break :cau ip.getNav(orig_nav).analysis_owner.unwrap().?; | |
| 2023 | }); | |
| 2038 | 2024 | |
| 2039 | log.debug("func name '{}'", .{decl.fqn.fmt(ip)}); | |
| 2040 | defer log.debug("finish func name '{}'", .{decl.fqn.fmt(ip)}); | |
| 2025 | const func_nav = ip.getNav(func.owner_nav); | |
| 2041 | 2026 | |
| 2042 | const decl_prog_node = mod.sema_prog_node.start(decl.fqn.toSlice(ip), 0); | |
| 2027 | const decl_prog_node = zcu.sema_prog_node.start(func_nav.fqn.toSlice(ip), 0); | |
| 2043 | 2028 | defer decl_prog_node.end(); |
| 2044 | 2029 | |
| 2045 | mod.intern_pool.removeDependenciesForDepender(gpa, InternPool.AnalUnit.wrap(.{ .func = func_index })); | |
| 2030 | zcu.intern_pool.removeDependenciesForDepender(gpa, anal_unit); | |
| 2031 | ||
| 2032 | var analysis_arena = std.heap.ArenaAllocator.init(gpa); | |
| 2033 | defer analysis_arena.deinit(); | |
| 2046 | 2034 | |
| 2047 | 2035 | var comptime_err_ret_trace = std.ArrayList(Zcu.LazySrcLoc).init(gpa); |
| 2048 | 2036 | defer comptime_err_ret_trace.deinit(); |
| ... | ... | @@ -2052,21 +2040,19 @@ pub fn analyzeFnBody(pt: Zcu.PerThread, func_index: InternPool.Index, arena: All |
| 2052 | 2040 | // the runtime-known parameters only, not to be confused with the |
| 2053 | 2041 | // generic_owner function type, which potentially has more parameters, |
| 2054 | 2042 | // including comptime parameters. |
| 2055 | const fn_ty = decl.typeOf(mod); | |
| 2056 | const fn_ty_info = mod.typeToFunc(fn_ty).?; | |
| 2043 | const fn_ty = Type.fromInterned(func.ty); | |
| 2044 | const fn_ty_info = zcu.typeToFunc(fn_ty).?; | |
| 2057 | 2045 | |
| 2058 | 2046 | var sema: Sema = .{ |
| 2059 | 2047 | .pt = pt, |
| 2060 | 2048 | .gpa = gpa, |
| 2061 | .arena = arena, | |
| 2062 | .code = decl.getFileScope(mod).zir, | |
| 2063 | .owner_decl = decl, | |
| 2064 | .owner_decl_index = decl_index, | |
| 2049 | .arena = analysis_arena.allocator(), | |
| 2050 | .code = zir, | |
| 2051 | .owner = anal_unit, | |
| 2065 | 2052 | .func_index = func_index, |
| 2066 | 2053 | .func_is_naked = fn_ty_info.cc == .Naked, |
| 2067 | 2054 | .fn_ret_ty = Type.fromInterned(fn_ty_info.return_type), |
| 2068 | 2055 | .fn_ret_ty_ies = null, |
| 2069 | .owner_func_index = func_index, | |
| 2070 | 2056 | .branch_quota = @max(func.branchQuotaUnordered(ip), Sema.default_branch_quota), |
| 2071 | 2057 | .comptime_err_ret_trace = &comptime_err_ret_trace, |
| 2072 | 2058 | }; |
| ... | ... | @@ -2074,11 +2060,11 @@ pub fn analyzeFnBody(pt: Zcu.PerThread, func_index: InternPool.Index, arena: All |
| 2074 | 2060 | |
| 2075 | 2061 | // Every runtime function has a dependency on the source of the Decl it originates from. |
| 2076 | 2062 | // It also depends on the value of its owner Decl. |
| 2077 | try sema.declareDependency(.{ .src_hash = decl.zir_decl_index.unwrap().? }); | |
| 2078 | try sema.declareDependency(.{ .decl_val = decl_index }); | |
| 2063 | try sema.declareDependency(.{ .src_hash = decl_cau.zir_index }); | |
| 2064 | try sema.declareDependency(.{ .nav_val = func.owner_nav }); | |
| 2079 | 2065 | |
| 2080 | 2066 | if (func.analysisUnordered(ip).inferred_error_set) { |
| 2081 | const ies = try arena.create(Sema.InferredErrorSet); | |
| 2067 | const ies = try analysis_arena.allocator().create(Sema.InferredErrorSet); | |
| 2082 | 2068 | ies.* = .{ .func = func_index }; |
| 2083 | 2069 | sema.fn_ret_ty_ies = ies; |
| 2084 | 2070 | } |
| ... | ... | @@ -2094,19 +2080,12 @@ pub fn analyzeFnBody(pt: Zcu.PerThread, func_index: InternPool.Index, arena: All |
| 2094 | 2080 | var inner_block: Sema.Block = .{ |
| 2095 | 2081 | .parent = null, |
| 2096 | 2082 | .sema = &sema, |
| 2097 | .namespace = decl.src_namespace, | |
| 2083 | .namespace = decl_cau.namespace, | |
| 2098 | 2084 | .instructions = .{}, |
| 2099 | 2085 | .inlining = null, |
| 2100 | 2086 | .is_comptime = false, |
| 2101 | .src_base_inst = inst: { | |
| 2102 | const owner_info = if (func.generic_owner == .none) | |
| 2103 | func | |
| 2104 | else | |
| 2105 | mod.funcInfo(func.generic_owner); | |
| 2106 | const orig_decl = mod.declPtr(owner_info.owner_decl); | |
| 2107 | break :inst orig_decl.zir_decl_index.unwrap().?; | |
| 2108 | }, | |
| 2109 | .type_name_ctx = decl.name, | |
| 2087 | .src_base_inst = decl_cau.zir_index, | |
| 2088 | .type_name_ctx = func_nav.fqn, | |
| 2110 | 2089 | }; |
| 2111 | 2090 | defer inner_block.instructions.deinit(gpa); |
| 2112 | 2091 | |
| ... | ... | @@ -2144,10 +2123,10 @@ pub fn analyzeFnBody(pt: Zcu.PerThread, func_index: InternPool.Index, arena: All |
| 2144 | 2123 | const gop = sema.inst_map.getOrPutAssumeCapacity(inst); |
| 2145 | 2124 | if (gop.found_existing) continue; // provided above by comptime arg |
| 2146 | 2125 | |
| 2147 | const inst_info = sema.code.instructions.get(@intFromEnum(inst)); | |
| 2148 | const param_name: Zir.NullTerminatedString = switch (inst_info.tag) { | |
| 2149 | .param_anytype => inst_info.data.str_tok.start, | |
| 2150 | .param => sema.code.extraData(Zir.Inst.Param, inst_info.data.pl_tok.payload_index).data.name, | |
| 2126 | const param_inst_info = sema.code.instructions.get(@intFromEnum(inst)); | |
| 2127 | const param_name: Zir.NullTerminatedString = switch (param_inst_info.tag) { | |
| 2128 | .param_anytype => param_inst_info.data.str_tok.start, | |
| 2129 | .param => sema.code.extraData(Zir.Inst.Param, param_inst_info.data.pl_tok.payload_index).data.name, | |
| 2151 | 2130 | else => unreachable, |
| 2152 | 2131 | }; |
| 2153 | 2132 | |
| ... | ... | @@ -2179,8 +2158,6 @@ pub fn analyzeFnBody(pt: Zcu.PerThread, func_index: InternPool.Index, arena: All |
| 2179 | 2158 | }); |
| 2180 | 2159 | } |
| 2181 | 2160 | |
| 2182 | func.setAnalysisState(ip, .in_progress); | |
| 2183 | ||
| 2184 | 2161 | const last_arg_index = inner_block.instructions.items.len; |
| 2185 | 2162 | |
| 2186 | 2163 | // Save the error trace as our first action in the function. |
| ... | ... | @@ -2190,9 +2167,8 @@ pub fn analyzeFnBody(pt: Zcu.PerThread, func_index: InternPool.Index, arena: All |
| 2190 | 2167 | inner_block.error_return_trace_index = error_return_trace_index; |
| 2191 | 2168 | |
| 2192 | 2169 | sema.analyzeFnBody(&inner_block, fn_info.body) catch |err| switch (err) { |
| 2193 | // TODO make these unreachable instead of @panic | |
| 2194 | error.GenericPoison => @panic("zig compiler bug: GenericPoison"), | |
| 2195 | error.ComptimeReturn => @panic("zig compiler bug: ComptimeReturn"), | |
| 2170 | error.GenericPoison => unreachable, | |
| 2171 | error.ComptimeReturn => unreachable, | |
| 2196 | 2172 | else => |e| return e, |
| 2197 | 2173 | }; |
| 2198 | 2174 | |
| ... | ... | @@ -2207,14 +2183,13 @@ pub fn analyzeFnBody(pt: Zcu.PerThread, func_index: InternPool.Index, arena: All |
| 2207 | 2183 | |
| 2208 | 2184 | // If we don't get an error return trace from a caller, create our own. |
| 2209 | 2185 | if (func.analysisUnordered(ip).calls_or_awaits_errorable_fn and |
| 2210 | mod.comp.config.any_error_tracing and | |
| 2211 | !sema.fn_ret_ty.isError(mod)) | |
| 2186 | zcu.comp.config.any_error_tracing and | |
| 2187 | !sema.fn_ret_ty.isError(zcu)) | |
| 2212 | 2188 | { |
| 2213 | 2189 | sema.setupErrorReturnTrace(&inner_block, last_arg_index) catch |err| switch (err) { |
| 2214 | // TODO make these unreachable instead of @panic | |
| 2215 | error.GenericPoison => @panic("zig compiler bug: GenericPoison"), | |
| 2216 | error.ComptimeReturn => @panic("zig compiler bug: ComptimeReturn"), | |
| 2217 | error.ComptimeBreak => @panic("zig compiler bug: ComptimeBreak"), | |
| 2190 | error.GenericPoison => unreachable, | |
| 2191 | error.ComptimeReturn => unreachable, | |
| 2192 | error.ComptimeBreak => unreachable, | |
| 2218 | 2193 | else => |e| return e, |
| 2219 | 2194 | }; |
| 2220 | 2195 | } |
| ... | ... | @@ -2239,35 +2214,25 @@ pub fn analyzeFnBody(pt: Zcu.PerThread, func_index: InternPool.Index, arena: All |
| 2239 | 2214 | error.GenericPoison => unreachable, |
| 2240 | 2215 | error.ComptimeReturn => unreachable, |
| 2241 | 2216 | error.ComptimeBreak => unreachable, |
| 2242 | error.AnalysisFail => { | |
| 2243 | // In this case our function depends on a type that had a compile error. | |
| 2244 | // We should not try to lower this function. | |
| 2245 | decl.analysis = .dependency_failure; | |
| 2246 | return error.AnalysisFail; | |
| 2247 | }, | |
| 2248 | 2217 | else => |e| return e, |
| 2249 | 2218 | }; |
| 2250 | 2219 | assert(ies.resolved != .none); |
| 2251 | 2220 | ip.funcSetIesResolved(func_index, ies.resolved); |
| 2252 | 2221 | } |
| 2253 | 2222 | |
| 2254 | func.setAnalysisState(ip, .success); | |
| 2223 | assert(zcu.analysis_in_progress.swapRemove(anal_unit)); | |
| 2255 | 2224 | |
| 2256 | 2225 | // Finally we must resolve the return type and parameter types so that backends |
| 2257 | 2226 | // have full access to type information. |
| 2258 | 2227 | // Crucially, this happens *after* we set the function state to success above, |
| 2259 | 2228 | // so that dependencies on the function body will now be satisfied rather than |
| 2260 | 2229 | // result in circular dependency errors. |
| 2230 | // TODO: this can go away once we fix backends having to resolve `StackTrace`. | |
| 2231 | // The codegen timing guarantees that the parameter types will be populated. | |
| 2261 | 2232 | sema.resolveFnTypes(fn_ty) catch |err| switch (err) { |
| 2262 | 2233 | error.GenericPoison => unreachable, |
| 2263 | 2234 | error.ComptimeReturn => unreachable, |
| 2264 | 2235 | error.ComptimeBreak => unreachable, |
| 2265 | error.AnalysisFail => { | |
| 2266 | // In this case our function depends on a type that had a compile error. | |
| 2267 | // We should not try to lower this function. | |
| 2268 | decl.analysis = .dependency_failure; | |
| 2269 | return error.AnalysisFail; | |
| 2270 | }, | |
| 2271 | 2236 | else => |e| return e, |
| 2272 | 2237 | }; |
| 2273 | 2238 | |
| ... | ... | @@ -2287,36 +2252,6 @@ pub fn destroyNamespace(pt: Zcu.PerThread, namespace_index: Zcu.Namespace.Index) |
| 2287 | 2252 | return pt.zcu.intern_pool.destroyNamespace(pt.tid, namespace_index); |
| 2288 | 2253 | } |
| 2289 | 2254 | |
| 2290 | pub fn allocateNewDecl(pt: Zcu.PerThread, namespace: Zcu.Namespace.Index) !Zcu.Decl.Index { | |
| 2291 | const zcu = pt.zcu; | |
| 2292 | const gpa = zcu.gpa; | |
| 2293 | const decl_index = try zcu.intern_pool.createDecl(gpa, pt.tid, .{ | |
| 2294 | .name = undefined, | |
| 2295 | .fqn = undefined, | |
| 2296 | .src_namespace = namespace, | |
| 2297 | .has_tv = false, | |
| 2298 | .owns_tv = false, | |
| 2299 | .val = undefined, | |
| 2300 | .alignment = undefined, | |
| 2301 | .@"linksection" = .none, | |
| 2302 | .@"addrspace" = .generic, | |
| 2303 | .analysis = .unreferenced, | |
| 2304 | .zir_decl_index = .none, | |
| 2305 | .is_pub = false, | |
| 2306 | .is_exported = false, | |
| 2307 | .kind = .anon, | |
| 2308 | }); | |
| 2309 | ||
| 2310 | if (zcu.emit_h) |zcu_emit_h| { | |
| 2311 | if (@intFromEnum(decl_index) >= zcu_emit_h.allocated_emit_h.len) { | |
| 2312 | try zcu_emit_h.allocated_emit_h.append(gpa, .{}); | |
| 2313 | assert(@intFromEnum(decl_index) == zcu_emit_h.allocated_emit_h.len); | |
| 2314 | } | |
| 2315 | } | |
| 2316 | ||
| 2317 | return decl_index; | |
| 2318 | } | |
| 2319 | ||
| 2320 | 2255 | pub fn getErrorValue( |
| 2321 | 2256 | pt: Zcu.PerThread, |
| 2322 | 2257 | name: InternPool.NullTerminatedString, |
| ... | ... | @@ -2328,25 +2263,6 @@ pub fn getErrorValueFromSlice(pt: Zcu.PerThread, name: []const u8) Allocator.Err |
| 2328 | 2263 | return pt.getErrorValue(try pt.zcu.intern_pool.getOrPutString(pt.zcu.gpa, name)); |
| 2329 | 2264 | } |
| 2330 | 2265 | |
| 2331 | pub fn initNewAnonDecl( | |
| 2332 | pt: Zcu.PerThread, | |
| 2333 | new_decl_index: Zcu.Decl.Index, | |
| 2334 | val: Value, | |
| 2335 | name: InternPool.NullTerminatedString, | |
| 2336 | fqn: InternPool.OptionalNullTerminatedString, | |
| 2337 | ) Allocator.Error!void { | |
| 2338 | const new_decl = pt.zcu.declPtr(new_decl_index); | |
| 2339 | ||
| 2340 | new_decl.name = name; | |
| 2341 | new_decl.fqn = fqn.unwrap() orelse try pt.zcu.namespacePtr(new_decl.src_namespace) | |
| 2342 | .internFullyQualifiedName(&pt.zcu.intern_pool, pt.zcu.gpa, pt.tid, name); | |
| 2343 | new_decl.val = val; | |
| 2344 | new_decl.alignment = .none; | |
| 2345 | new_decl.@"linksection" = .none; | |
| 2346 | new_decl.has_tv = true; | |
| 2347 | new_decl.analysis = .complete; | |
| 2348 | } | |
| 2349 | ||
| 2350 | 2266 | fn lockAndClearFileCompileError(pt: Zcu.PerThread, file: *Zcu.File) void { |
| 2351 | 2267 | switch (file.status) { |
| 2352 | 2268 | .success_zir, .retryable_failure => {}, |
| ... | ... | @@ -2367,35 +2283,35 @@ pub fn processExports(pt: Zcu.PerThread) !void { |
| 2367 | 2283 | const zcu = pt.zcu; |
| 2368 | 2284 | const gpa = zcu.gpa; |
| 2369 | 2285 | |
| 2370 | // First, construct a mapping of every exported value and Decl to the indices of all its different exports. | |
| 2371 | var decl_exports: std.AutoArrayHashMapUnmanaged(Zcu.Decl.Index, std.ArrayListUnmanaged(u32)) = .{}; | |
| 2372 | var value_exports: std.AutoArrayHashMapUnmanaged(InternPool.Index, std.ArrayListUnmanaged(u32)) = .{}; | |
| 2286 | // First, construct a mapping of every exported value and Nav to the indices of all its different exports. | |
| 2287 | var nav_exports: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, std.ArrayListUnmanaged(u32)) = .{}; | |
| 2288 | var uav_exports: std.AutoArrayHashMapUnmanaged(InternPool.Index, std.ArrayListUnmanaged(u32)) = .{}; | |
| 2373 | 2289 | defer { |
| 2374 | for (decl_exports.values()) |*exports| { | |
| 2290 | for (nav_exports.values()) |*exports| { | |
| 2375 | 2291 | exports.deinit(gpa); |
| 2376 | 2292 | } |
| 2377 | decl_exports.deinit(gpa); | |
| 2378 | for (value_exports.values()) |*exports| { | |
| 2293 | nav_exports.deinit(gpa); | |
| 2294 | for (uav_exports.values()) |*exports| { | |
| 2379 | 2295 | exports.deinit(gpa); |
| 2380 | 2296 | } |
| 2381 | value_exports.deinit(gpa); | |
| 2297 | uav_exports.deinit(gpa); | |
| 2382 | 2298 | } |
| 2383 | 2299 | |
| 2384 | 2300 | // We note as a heuristic: |
| 2385 | 2301 | // * It is rare to export a value. |
| 2386 | // * It is rare for one Decl to be exported multiple times. | |
| 2302 | // * It is rare for one Nav to be exported multiple times. | |
| 2387 | 2303 | // So, this ensureTotalCapacity serves as a reasonable (albeit very approximate) optimization. |
| 2388 | try decl_exports.ensureTotalCapacity(gpa, zcu.single_exports.count() + zcu.multi_exports.count()); | |
| 2304 | try nav_exports.ensureTotalCapacity(gpa, zcu.single_exports.count() + zcu.multi_exports.count()); | |
| 2389 | 2305 | |
| 2390 | 2306 | for (zcu.single_exports.values()) |export_idx| { |
| 2391 | 2307 | const exp = zcu.all_exports.items[export_idx]; |
| 2392 | 2308 | const value_ptr, const found_existing = switch (exp.exported) { |
| 2393 | .decl_index => |i| gop: { | |
| 2394 | const gop = try decl_exports.getOrPut(gpa, i); | |
| 2309 | .nav => |nav| gop: { | |
| 2310 | const gop = try nav_exports.getOrPut(gpa, nav); | |
| 2395 | 2311 | break :gop .{ gop.value_ptr, gop.found_existing }; |
| 2396 | 2312 | }, |
| 2397 | .value => |i| gop: { | |
| 2398 | const gop = try value_exports.getOrPut(gpa, i); | |
| 2313 | .uav => |uav| gop: { | |
| 2314 | const gop = try uav_exports.getOrPut(gpa, uav); | |
| 2399 | 2315 | break :gop .{ gop.value_ptr, gop.found_existing }; |
| 2400 | 2316 | }, |
| 2401 | 2317 | }; |
| ... | ... | @@ -2406,12 +2322,12 @@ pub fn processExports(pt: Zcu.PerThread) !void { |
| 2406 | 2322 | for (zcu.multi_exports.values()) |info| { |
| 2407 | 2323 | for (zcu.all_exports.items[info.index..][0..info.len], info.index..) |exp, export_idx| { |
| 2408 | 2324 | const value_ptr, const found_existing = switch (exp.exported) { |
| 2409 | .decl_index => |i| gop: { | |
| 2410 | const gop = try decl_exports.getOrPut(gpa, i); | |
| 2325 | .nav => |nav| gop: { | |
| 2326 | const gop = try nav_exports.getOrPut(gpa, nav); | |
| 2411 | 2327 | break :gop .{ gop.value_ptr, gop.found_existing }; |
| 2412 | 2328 | }, |
| 2413 | .value => |i| gop: { | |
| 2414 | const gop = try value_exports.getOrPut(gpa, i); | |
| 2329 | .uav => |uav| gop: { | |
| 2330 | const gop = try uav_exports.getOrPut(gpa, uav); | |
| 2415 | 2331 | break :gop .{ gop.value_ptr, gop.found_existing }; |
| 2416 | 2332 | }, |
| 2417 | 2333 | }; |
| ... | ... | @@ -2424,13 +2340,13 @@ pub fn processExports(pt: Zcu.PerThread) !void { |
| 2424 | 2340 | var symbol_exports: SymbolExports = .{}; |
| 2425 | 2341 | defer symbol_exports.deinit(gpa); |
| 2426 | 2342 | |
| 2427 | for (decl_exports.keys(), decl_exports.values()) |exported_decl, exports_list| { | |
| 2428 | const exported: Zcu.Exported = .{ .decl_index = exported_decl }; | |
| 2343 | for (nav_exports.keys(), nav_exports.values()) |exported_nav, exports_list| { | |
| 2344 | const exported: Zcu.Exported = .{ .nav = exported_nav }; | |
| 2429 | 2345 | try pt.processExportsInner(&symbol_exports, exported, exports_list.items); |
| 2430 | 2346 | } |
| 2431 | 2347 | |
| 2432 | for (value_exports.keys(), value_exports.values()) |exported_value, exports_list| { | |
| 2433 | const exported: Zcu.Exported = .{ .value = exported_value }; | |
| 2348 | for (uav_exports.keys(), uav_exports.values()) |exported_uav, exports_list| { | |
| 2349 | const exported: Zcu.Exported = .{ .uav = exported_uav }; | |
| 2434 | 2350 | try pt.processExportsInner(&symbol_exports, exported, exports_list.items); |
| 2435 | 2351 | } |
| 2436 | 2352 | } |
| ... | ... | @@ -2467,20 +2383,31 @@ fn processExportsInner( |
| 2467 | 2383 | } |
| 2468 | 2384 | |
| 2469 | 2385 | switch (exported) { |
| 2470 | .decl_index => |idx| if (failed: { | |
| 2471 | const decl = zcu.declPtr(idx); | |
| 2472 | if (decl.analysis != .complete) break :failed true; | |
| 2473 | // Check if has owned function | |
| 2474 | if (!decl.owns_tv) break :failed false; | |
| 2475 | if (decl.typeOf(zcu).zigTypeTag(zcu) != .Fn) break :failed false; | |
| 2476 | // Check if owned function failed | |
| 2477 | break :failed zcu.funcInfo(decl.val.toIntern()).analysisUnordered(ip).state != .success; | |
| 2386 | .nav => |nav_index| if (failed: { | |
| 2387 | const nav = ip.getNav(nav_index); | |
| 2388 | if (zcu.failed_codegen.contains(nav_index)) break :failed true; | |
| 2389 | if (nav.analysis_owner.unwrap()) |cau| { | |
| 2390 | const cau_unit = InternPool.AnalUnit.wrap(.{ .cau = cau }); | |
| 2391 | if (zcu.failed_analysis.contains(cau_unit)) break :failed true; | |
| 2392 | if (zcu.transitive_failed_analysis.contains(cau_unit)) break :failed true; | |
| 2393 | } | |
| 2394 | const val = switch (nav.status) { | |
| 2395 | .unresolved => break :failed true, | |
| 2396 | .resolved => |r| Value.fromInterned(r.val), | |
| 2397 | }; | |
| 2398 | // If the value is a function, we also need to check if that function succeeded analysis. | |
| 2399 | if (val.typeOf(zcu).zigTypeTag(zcu) == .Fn) { | |
| 2400 | const func_unit = InternPool.AnalUnit.wrap(.{ .func = val.toIntern() }); | |
| 2401 | if (zcu.failed_analysis.contains(func_unit)) break :failed true; | |
| 2402 | if (zcu.transitive_failed_analysis.contains(func_unit)) break :failed true; | |
| 2403 | } | |
| 2404 | break :failed false; | |
| 2478 | 2405 | }) { |
| 2479 | 2406 | // This `Decl` is failed, so was never sent to codegen. |
| 2480 | 2407 | // TODO: we should probably tell the backend to delete any old exports of this `Decl`? |
| 2481 | 2408 | return; |
| 2482 | 2409 | }, |
| 2483 | .value => {}, | |
| 2410 | .uav => {}, | |
| 2484 | 2411 | } |
| 2485 | 2412 | |
| 2486 | 2413 | if (zcu.comp.bin_file) |lf| { |
| ... | ... | @@ -2499,46 +2426,49 @@ pub fn populateTestFunctions( |
| 2499 | 2426 | const ip = &zcu.intern_pool; |
| 2500 | 2427 | const builtin_mod = zcu.root_mod.getBuiltinDependency(); |
| 2501 | 2428 | const builtin_file_index = (pt.importPkg(builtin_mod) catch unreachable).file_index; |
| 2502 | const root_decl_index = zcu.fileRootDecl(builtin_file_index); | |
| 2503 | const root_decl = zcu.declPtr(root_decl_index.unwrap().?); | |
| 2504 | const builtin_namespace = zcu.namespacePtr(root_decl.src_namespace); | |
| 2505 | const test_functions_str = try ip.getOrPutString(gpa, pt.tid, "test_functions", .no_embedded_nulls); | |
| 2506 | const decl_index = builtin_namespace.decls.getKeyAdapted( | |
| 2507 | test_functions_str, | |
| 2508 | Zcu.DeclAdapter{ .zcu = zcu }, | |
| 2429 | pt.ensureFileAnalyzed(builtin_file_index) catch |err| switch (err) { | |
| 2430 | error.AnalysisFail => unreachable, // builtin module is generated so cannot be corrupt | |
| 2431 | error.OutOfMemory => |e| return e, | |
| 2432 | }; | |
| 2433 | const builtin_root_type = Type.fromInterned(zcu.fileRootType(builtin_file_index)); | |
| 2434 | const builtin_namespace = builtin_root_type.getNamespace(zcu).unwrap().?; | |
| 2435 | const nav_index = zcu.namespacePtr(builtin_namespace).pub_decls.getKeyAdapted( | |
| 2436 | try ip.getOrPutString(gpa, pt.tid, "test_functions", .no_embedded_nulls), | |
| 2437 | Zcu.Namespace.NameAdapter{ .zcu = zcu }, | |
| 2509 | 2438 | ).?; |
| 2510 | 2439 | { |
| 2511 | // We have to call `ensureDeclAnalyzed` here in case `builtin.test_functions` | |
| 2440 | // We have to call `ensureCauAnalyzed` here in case `builtin.test_functions` | |
| 2512 | 2441 | // was not referenced by start code. |
| 2513 | 2442 | zcu.sema_prog_node = main_progress_node.start("Semantic Analysis", 0); |
| 2514 | 2443 | defer { |
| 2515 | 2444 | zcu.sema_prog_node.end(); |
| 2516 | 2445 | zcu.sema_prog_node = std.Progress.Node.none; |
| 2517 | 2446 | } |
| 2518 | try pt.ensureDeclAnalyzed(decl_index); | |
| 2447 | const cau_index = ip.getNav(nav_index).analysis_owner.unwrap().?; | |
| 2448 | try pt.ensureCauAnalyzed(cau_index); | |
| 2519 | 2449 | } |
| 2520 | 2450 | |
| 2521 | const decl = zcu.declPtr(decl_index); | |
| 2522 | const test_fn_ty = decl.typeOf(zcu).slicePtrFieldType(zcu).childType(zcu); | |
| 2451 | const test_fns_val = zcu.navValue(nav_index); | |
| 2452 | const test_fn_ty = test_fns_val.typeOf(zcu).slicePtrFieldType(zcu).childType(zcu); | |
| 2523 | 2453 | |
| 2524 | const array_anon_decl: InternPool.Key.Ptr.BaseAddr.AnonDecl = array: { | |
| 2454 | const array_anon_decl: InternPool.Key.Ptr.BaseAddr.Uav = array: { | |
| 2525 | 2455 | // Add zcu.test_functions to an array decl then make the test_functions |
| 2526 | 2456 | // decl reference it as a slice. |
| 2527 | 2457 | const test_fn_vals = try gpa.alloc(InternPool.Index, zcu.test_functions.count()); |
| 2528 | 2458 | defer gpa.free(test_fn_vals); |
| 2529 | 2459 | |
| 2530 | for (test_fn_vals, zcu.test_functions.keys()) |*test_fn_val, test_decl_index| { | |
| 2531 | const test_decl = zcu.declPtr(test_decl_index); | |
| 2532 | const test_decl_name = test_decl.fqn; | |
| 2533 | const test_decl_name_len = test_decl_name.length(ip); | |
| 2534 | const test_name_anon_decl: InternPool.Key.Ptr.BaseAddr.AnonDecl = n: { | |
| 2460 | for (test_fn_vals, zcu.test_functions.keys()) |*test_fn_val, test_nav_index| { | |
| 2461 | const test_nav = ip.getNav(test_nav_index); | |
| 2462 | const test_nav_name = test_nav.fqn; | |
| 2463 | const test_nav_name_len = test_nav_name.length(ip); | |
| 2464 | const test_name_anon_decl: InternPool.Key.Ptr.BaseAddr.Uav = n: { | |
| 2535 | 2465 | const test_name_ty = try pt.arrayType(.{ |
| 2536 | .len = test_decl_name_len, | |
| 2466 | .len = test_nav_name_len, | |
| 2537 | 2467 | .child = .u8_type, |
| 2538 | 2468 | }); |
| 2539 | 2469 | const test_name_val = try pt.intern(.{ .aggregate = .{ |
| 2540 | 2470 | .ty = test_name_ty.toIntern(), |
| 2541 | .storage = .{ .bytes = test_decl_name.toString() }, | |
| 2471 | .storage = .{ .bytes = test_nav_name.toString() }, | |
| 2542 | 2472 | } }); |
| 2543 | 2473 | break :n .{ |
| 2544 | 2474 | .orig_ty = (try pt.singleConstPtrType(test_name_ty)).toIntern(), |
| ... | ... | @@ -2552,23 +2482,18 @@ pub fn populateTestFunctions( |
| 2552 | 2482 | .ty = .slice_const_u8_type, |
| 2553 | 2483 | .ptr = try pt.intern(.{ .ptr = .{ |
| 2554 | 2484 | .ty = .manyptr_const_u8_type, |
| 2555 | .base_addr = .{ .anon_decl = test_name_anon_decl }, | |
| 2485 | .base_addr = .{ .uav = test_name_anon_decl }, | |
| 2556 | 2486 | .byte_offset = 0, |
| 2557 | 2487 | } }), |
| 2558 | 2488 | .len = try pt.intern(.{ .int = .{ |
| 2559 | 2489 | .ty = .usize_type, |
| 2560 | .storage = .{ .u64 = test_decl_name_len }, | |
| 2490 | .storage = .{ .u64 = test_nav_name_len }, | |
| 2561 | 2491 | } }), |
| 2562 | 2492 | } }), |
| 2563 | 2493 | // func |
| 2564 | 2494 | try pt.intern(.{ .ptr = .{ |
| 2565 | .ty = try pt.intern(.{ .ptr_type = .{ | |
| 2566 | .child = test_decl.typeOf(zcu).toIntern(), | |
| 2567 | .flags = .{ | |
| 2568 | .is_const = true, | |
| 2569 | }, | |
| 2570 | } }), | |
| 2571 | .base_addr = .{ .decl = test_decl_index }, | |
| 2495 | .ty = (try pt.navPtrType(test_nav_index)).toIntern(), | |
| 2496 | .base_addr = .{ .nav = test_nav_index }, | |
| 2572 | 2497 | .byte_offset = 0, |
| 2573 | 2498 | } }), |
| 2574 | 2499 | }; |
| ... | ... | @@ -2601,22 +2526,16 @@ pub fn populateTestFunctions( |
| 2601 | 2526 | .size = .Slice, |
| 2602 | 2527 | }, |
| 2603 | 2528 | }); |
| 2604 | const new_val = decl.val; | |
| 2605 | 2529 | const new_init = try pt.intern(.{ .slice = .{ |
| 2606 | 2530 | .ty = new_ty.toIntern(), |
| 2607 | 2531 | .ptr = try pt.intern(.{ .ptr = .{ |
| 2608 | 2532 | .ty = new_ty.slicePtrFieldType(zcu).toIntern(), |
| 2609 | .base_addr = .{ .anon_decl = array_anon_decl }, | |
| 2533 | .base_addr = .{ .uav = array_anon_decl }, | |
| 2610 | 2534 | .byte_offset = 0, |
| 2611 | 2535 | } }), |
| 2612 | 2536 | .len = (try pt.intValue(Type.usize, zcu.test_functions.count())).toIntern(), |
| 2613 | 2537 | } }); |
| 2614 | ip.mutateVarInit(decl.val.toIntern(), new_init); | |
| 2615 | ||
| 2616 | // Since we are replacing the Decl's value we must perform cleanup on the | |
| 2617 | // previous value. | |
| 2618 | decl.val = new_val; | |
| 2619 | decl.has_tv = true; | |
| 2538 | ip.mutateVarInit(test_fns_val.toIntern(), new_init); | |
| 2620 | 2539 | } |
| 2621 | 2540 | { |
| 2622 | 2541 | zcu.codegen_prog_node = main_progress_node.start("Code Generation", 0); |
| ... | ... | @@ -2625,40 +2544,45 @@ pub fn populateTestFunctions( |
| 2625 | 2544 | zcu.codegen_prog_node = std.Progress.Node.none; |
| 2626 | 2545 | } |
| 2627 | 2546 | |
| 2628 | try pt.linkerUpdateDecl(decl_index); | |
| 2547 | try pt.linkerUpdateNav(nav_index); | |
| 2629 | 2548 | } |
| 2630 | 2549 | } |
| 2631 | 2550 | |
| 2632 | pub fn linkerUpdateDecl(pt: Zcu.PerThread, decl_index: Zcu.Decl.Index) !void { | |
| 2551 | pub fn linkerUpdateNav(pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) !void { | |
| 2633 | 2552 | const zcu = pt.zcu; |
| 2634 | 2553 | const comp = zcu.comp; |
| 2635 | 2554 | |
| 2636 | const decl = zcu.declPtr(decl_index); | |
| 2637 | ||
| 2638 | const codegen_prog_node = zcu.codegen_prog_node.start(decl.fqn.toSlice(&zcu.intern_pool), 0); | |
| 2555 | const nav = zcu.intern_pool.getNav(nav_index); | |
| 2556 | const codegen_prog_node = zcu.codegen_prog_node.start(nav.fqn.toSlice(&zcu.intern_pool), 0); | |
| 2639 | 2557 | defer codegen_prog_node.end(); |
| 2640 | 2558 | |
| 2641 | 2559 | if (comp.bin_file) |lf| { |
| 2642 | lf.updateDecl(pt, decl_index) catch |err| switch (err) { | |
| 2560 | lf.updateNav(pt, nav_index) catch |err| switch (err) { | |
| 2643 | 2561 | error.OutOfMemory => return error.OutOfMemory, |
| 2644 | 2562 | error.AnalysisFail => { |
| 2645 | decl.analysis = .codegen_failure; | |
| 2563 | assert(zcu.failed_codegen.contains(nav_index)); | |
| 2646 | 2564 | }, |
| 2647 | 2565 | else => { |
| 2648 | 2566 | const gpa = zcu.gpa; |
| 2649 | try zcu.failed_analysis.ensureUnusedCapacity(gpa, 1); | |
| 2650 | zcu.failed_analysis.putAssumeCapacityNoClobber(InternPool.AnalUnit.wrap(.{ .decl = decl_index }), try Zcu.ErrorMsg.create( | |
| 2567 | try zcu.failed_codegen.ensureUnusedCapacity(gpa, 1); | |
| 2568 | zcu.failed_codegen.putAssumeCapacityNoClobber(nav_index, try Zcu.ErrorMsg.create( | |
| 2651 | 2569 | gpa, |
| 2652 | decl.navSrcLoc(zcu), | |
| 2570 | zcu.navSrcLoc(nav_index), | |
| 2653 | 2571 | "unable to codegen: {s}", |
| 2654 | 2572 | .{@errorName(err)}, |
| 2655 | 2573 | )); |
| 2656 | decl.analysis = .codegen_failure; | |
| 2657 | try zcu.retryable_failures.append(zcu.gpa, InternPool.AnalUnit.wrap(.{ .decl = decl_index })); | |
| 2574 | if (nav.analysis_owner.unwrap()) |cau| { | |
| 2575 | try zcu.retryable_failures.append(zcu.gpa, InternPool.AnalUnit.wrap(.{ .cau = cau })); | |
| 2576 | } else { | |
| 2577 | // TODO: we don't have a way to indicate that this failure is retryable! | |
| 2578 | // Since these are really rare, we could as a cop-out retry the whole build next update. | |
| 2579 | // But perhaps we can do better... | |
| 2580 | @panic("TODO: retryable failure codegenning non-declaration Nav"); | |
| 2581 | } | |
| 2658 | 2582 | }, |
| 2659 | 2583 | }; |
| 2660 | 2584 | } else if (zcu.llvm_object) |llvm_object| { |
| 2661 | llvm_object.updateDecl(pt, decl_index) catch |err| switch (err) { | |
| 2585 | llvm_object.updateNav(pt, nav_index) catch |err| switch (err) { | |
| 2662 | 2586 | error.OutOfMemory => return error.OutOfMemory, |
| 2663 | 2587 | }; |
| 2664 | 2588 | } |
| ... | ... | @@ -2750,9 +2674,30 @@ pub fn intern(pt: Zcu.PerThread, key: InternPool.Key) Allocator.Error!InternPool |
| 2750 | 2674 | return pt.zcu.intern_pool.get(pt.zcu.gpa, pt.tid, key); |
| 2751 | 2675 | } |
| 2752 | 2676 | |
| 2753 | /// Shortcut for calling `intern_pool.getCoerced`. | |
| 2677 | /// Essentially a shortcut for calling `intern_pool.getCoerced`. | |
| 2678 | /// However, this function also allows coercing `extern`s. The `InternPool` function can't do | |
| 2679 | /// this because it requires potentially pushing to the job queue. | |
| 2754 | 2680 | pub fn getCoerced(pt: Zcu.PerThread, val: Value, new_ty: Type) Allocator.Error!Value { |
| 2755 | return Value.fromInterned(try pt.zcu.intern_pool.getCoerced(pt.zcu.gpa, pt.tid, val.toIntern(), new_ty.toIntern())); | |
| 2681 | const ip = &pt.zcu.intern_pool; | |
| 2682 | switch (ip.indexToKey(val.toIntern())) { | |
| 2683 | .@"extern" => |e| { | |
| 2684 | const coerced = try pt.getExtern(.{ | |
| 2685 | .name = e.name, | |
| 2686 | .ty = new_ty.toIntern(), | |
| 2687 | .lib_name = e.lib_name, | |
| 2688 | .is_const = e.is_const, | |
| 2689 | .is_threadlocal = e.is_threadlocal, | |
| 2690 | .is_weak_linkage = e.is_weak_linkage, | |
| 2691 | .alignment = e.alignment, | |
| 2692 | .@"addrspace" = e.@"addrspace", | |
| 2693 | .zir_index = e.zir_index, | |
| 2694 | .owner_nav = undefined, // ignored by `getExtern`. | |
| 2695 | }); | |
| 2696 | return Value.fromInterned(coerced); | |
| 2697 | }, | |
| 2698 | else => {}, | |
| 2699 | } | |
| 2700 | return Value.fromInterned(try ip.getCoerced(pt.zcu.gpa, pt.tid, val.toIntern(), new_ty.toIntern())); | |
| 2756 | 2701 | } |
| 2757 | 2702 | |
| 2758 | 2703 | pub fn intType(pt: Zcu.PerThread, signedness: std.builtin.Signedness, bits: u16) Allocator.Error!Type { |
| ... | ... | @@ -3237,24 +3182,28 @@ pub fn structPackedFieldBitOffset( |
| 3237 | 3182 | } |
| 3238 | 3183 | |
| 3239 | 3184 | pub fn getBuiltin(pt: Zcu.PerThread, name: []const u8) Allocator.Error!Air.Inst.Ref { |
| 3240 | const decl_index = try pt.getBuiltinDecl(name); | |
| 3241 | pt.ensureDeclAnalyzed(decl_index) catch @panic("std.builtin is corrupt"); | |
| 3242 | return Air.internedToRef(pt.zcu.declPtr(decl_index).val.toIntern()); | |
| 3185 | const zcu = pt.zcu; | |
| 3186 | const ip = &zcu.intern_pool; | |
| 3187 | const nav = try pt.getBuiltinNav(name); | |
| 3188 | pt.ensureCauAnalyzed(ip.getNav(nav).analysis_owner.unwrap().?) catch @panic("std.builtin is corrupt"); | |
| 3189 | return Air.internedToRef(ip.getNav(nav).status.resolved.val); | |
| 3243 | 3190 | } |
| 3244 | 3191 | |
| 3245 | pub fn getBuiltinDecl(pt: Zcu.PerThread, name: []const u8) Allocator.Error!InternPool.DeclIndex { | |
| 3192 | pub fn getBuiltinNav(pt: Zcu.PerThread, name: []const u8) Allocator.Error!InternPool.Nav.Index { | |
| 3246 | 3193 | const zcu = pt.zcu; |
| 3247 | 3194 | const gpa = zcu.gpa; |
| 3248 | 3195 | const ip = &zcu.intern_pool; |
| 3249 | 3196 | const std_file_imported = pt.importPkg(zcu.std_mod) catch @panic("failed to import lib/std.zig"); |
| 3250 | const std_file_root_decl = zcu.fileRootDecl(std_file_imported.file_index).unwrap().?; | |
| 3251 | const std_namespace = zcu.declPtr(std_file_root_decl).getOwnedInnerNamespace(zcu).?; | |
| 3197 | const std_type = Type.fromInterned(zcu.fileRootType(std_file_imported.file_index)); | |
| 3198 | const std_namespace = zcu.namespacePtr(std_type.getNamespace(zcu).unwrap().?); | |
| 3252 | 3199 | const builtin_str = try ip.getOrPutString(gpa, pt.tid, "builtin", .no_embedded_nulls); |
| 3253 | const builtin_decl = std_namespace.decls.getKeyAdapted(builtin_str, Zcu.DeclAdapter{ .zcu = zcu }) orelse @panic("lib/std.zig is corrupt and missing 'builtin'"); | |
| 3254 | pt.ensureDeclAnalyzed(builtin_decl) catch @panic("std.builtin is corrupt"); | |
| 3255 | const builtin_namespace = zcu.declPtr(builtin_decl).getInnerNamespace(zcu) orelse @panic("std.builtin is corrupt"); | |
| 3200 | const builtin_nav = std_namespace.pub_decls.getKeyAdapted(builtin_str, Zcu.Namespace.NameAdapter{ .zcu = zcu }) orelse | |
| 3201 | @panic("lib/std.zig is corrupt and missing 'builtin'"); | |
| 3202 | pt.ensureCauAnalyzed(ip.getNav(builtin_nav).analysis_owner.unwrap().?) catch @panic("std.builtin is corrupt"); | |
| 3203 | const builtin_type = Type.fromInterned(ip.getNav(builtin_nav).status.resolved.val); | |
| 3204 | const builtin_namespace = zcu.namespacePtr(builtin_type.getNamespace(zcu).unwrap() orelse @panic("std.builtin is corrupt")); | |
| 3256 | 3205 | const name_str = try ip.getOrPutString(gpa, pt.tid, name, .no_embedded_nulls); |
| 3257 | return builtin_namespace.decls.getKeyAdapted(name_str, Zcu.DeclAdapter{ .zcu = zcu }) orelse @panic("lib/std/builtin.zig is corrupt"); | |
| 3206 | return builtin_namespace.pub_decls.getKeyAdapted(name_str, Zcu.Namespace.NameAdapter{ .zcu = zcu }) orelse @panic("lib/std/builtin.zig is corrupt"); | |
| 3258 | 3207 | } |
| 3259 | 3208 | |
| 3260 | 3209 | pub fn getBuiltinType(pt: Zcu.PerThread, name: []const u8) Allocator.Error!Type { |
| ... | ... | @@ -3264,6 +3213,47 @@ pub fn getBuiltinType(pt: Zcu.PerThread, name: []const u8) Allocator.Error!Type |
| 3264 | 3213 | return ty; |
| 3265 | 3214 | } |
| 3266 | 3215 | |
| 3216 | pub fn navPtrType(pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) Allocator.Error!Type { | |
| 3217 | const zcu = pt.zcu; | |
| 3218 | const ip = &zcu.intern_pool; | |
| 3219 | const r = ip.getNav(nav_index).status.resolved; | |
| 3220 | const ty = Value.fromInterned(r.val).typeOf(zcu); | |
| 3221 | return pt.ptrType(.{ | |
| 3222 | .child = ty.toIntern(), | |
| 3223 | .flags = .{ | |
| 3224 | .alignment = if (r.alignment == ty.abiAlignment(pt)) | |
| 3225 | .none | |
| 3226 | else | |
| 3227 | r.alignment, | |
| 3228 | .address_space = r.@"addrspace", | |
| 3229 | .is_const = switch (ip.indexToKey(r.val)) { | |
| 3230 | .variable => false, | |
| 3231 | .@"extern" => |e| e.is_const, | |
| 3232 | else => true, | |
| 3233 | }, | |
| 3234 | }, | |
| 3235 | }); | |
| 3236 | } | |
| 3237 | ||
| 3238 | /// Intern an `.@"extern"`, creating a corresponding owner `Nav` if necessary. | |
| 3239 | /// If necessary, the new `Nav` is queued for codegen. | |
| 3240 | /// `key.owner_nav` is ignored and may be `undefined`. | |
| 3241 | pub fn getExtern(pt: Zcu.PerThread, key: InternPool.Key.Extern) Allocator.Error!InternPool.Index { | |
| 3242 | const result = try pt.zcu.intern_pool.getExtern(pt.zcu.gpa, pt.tid, key); | |
| 3243 | if (result.new_nav.unwrap()) |nav| { | |
| 3244 | try pt.zcu.comp.queueJob(.{ .codegen_nav = nav }); | |
| 3245 | } | |
| 3246 | return result.index; | |
| 3247 | } | |
| 3248 | ||
| 3249 | // TODO: this shouldn't need a `PerThread`! Fix the signature of `Type.abiAlignment`. | |
| 3250 | pub fn navAlignment(pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) InternPool.Alignment { | |
| 3251 | const zcu = pt.zcu; | |
| 3252 | const r = zcu.intern_pool.getNav(nav_index).status.resolved; | |
| 3253 | if (r.alignment != .none) return r.alignment; | |
| 3254 | return Value.fromInterned(r.val).typeOf(zcu).abiAlignment(pt); | |
| 3255 | } | |
| 3256 | ||
| 3267 | 3257 | const Air = @import("../Air.zig"); |
| 3268 | 3258 | const Allocator = std.mem.Allocator; |
| 3269 | 3259 | const assert = std.debug.assert; |
src/arch/aarch64/CodeGen.zig+40-41| ... | ... | @@ -52,7 +52,7 @@ bin_file: *link.File, |
| 52 | 52 | debug_output: DebugInfoOutput, |
| 53 | 53 | target: *const std.Target, |
| 54 | 54 | func_index: InternPool.Index, |
| 55 | owner_decl: InternPool.DeclIndex, | |
| 55 | owner_nav: InternPool.Nav.Index, | |
| 56 | 56 | err_msg: ?*ErrorMsg, |
| 57 | 57 | args: []MCValue, |
| 58 | 58 | ret_mcv: MCValue, |
| ... | ... | @@ -184,7 +184,7 @@ const DbgInfoReloc = struct { |
| 184 | 184 | fn genArgDbgInfo(reloc: DbgInfoReloc, function: Self) error{OutOfMemory}!void { |
| 185 | 185 | switch (function.debug_output) { |
| 186 | 186 | .dwarf => |dw| { |
| 187 | const loc: link.File.Dwarf.DeclState.DbgInfoLoc = switch (reloc.mcv) { | |
| 187 | const loc: link.File.Dwarf.NavState.DbgInfoLoc = switch (reloc.mcv) { | |
| 188 | 188 | .register => |reg| .{ .register = reg.dwarfLocOp() }, |
| 189 | 189 | .stack_offset, |
| 190 | 190 | .stack_argument_offset, |
| ... | ... | @@ -202,7 +202,7 @@ const DbgInfoReloc = struct { |
| 202 | 202 | else => unreachable, // not a possible argument |
| 203 | 203 | |
| 204 | 204 | }; |
| 205 | try dw.genArgDbgInfo(reloc.name, reloc.ty, function.owner_decl, loc); | |
| 205 | try dw.genArgDbgInfo(reloc.name, reloc.ty, function.owner_nav, loc); | |
| 206 | 206 | }, |
| 207 | 207 | .plan9 => {}, |
| 208 | 208 | .none => {}, |
| ... | ... | @@ -218,7 +218,7 @@ const DbgInfoReloc = struct { |
| 218 | 218 | |
| 219 | 219 | switch (function.debug_output) { |
| 220 | 220 | .dwarf => |dw| { |
| 221 | const loc: link.File.Dwarf.DeclState.DbgInfoLoc = switch (reloc.mcv) { | |
| 221 | const loc: link.File.Dwarf.NavState.DbgInfoLoc = switch (reloc.mcv) { | |
| 222 | 222 | .register => |reg| .{ .register = reg.dwarfLocOp() }, |
| 223 | 223 | .ptr_stack_offset, |
| 224 | 224 | .stack_offset, |
| ... | ... | @@ -248,7 +248,7 @@ const DbgInfoReloc = struct { |
| 248 | 248 | break :blk .nop; |
| 249 | 249 | }, |
| 250 | 250 | }; |
| 251 | try dw.genVarDbgInfo(reloc.name, reloc.ty, function.owner_decl, is_ptr, loc); | |
| 251 | try dw.genVarDbgInfo(reloc.name, reloc.ty, function.owner_nav, is_ptr, loc); | |
| 252 | 252 | }, |
| 253 | 253 | .plan9 => {}, |
| 254 | 254 | .none => {}, |
| ... | ... | @@ -341,11 +341,9 @@ pub fn generate( |
| 341 | 341 | const zcu = pt.zcu; |
| 342 | 342 | const gpa = zcu.gpa; |
| 343 | 343 | const func = zcu.funcInfo(func_index); |
| 344 | const fn_owner_decl = zcu.declPtr(func.owner_decl); | |
| 345 | assert(fn_owner_decl.has_tv); | |
| 346 | const fn_type = fn_owner_decl.typeOf(zcu); | |
| 347 | const namespace = zcu.namespacePtr(fn_owner_decl.src_namespace); | |
| 348 | const target = &namespace.fileScope(zcu).mod.resolved_target.result; | |
| 344 | const fn_type = Type.fromInterned(func.ty); | |
| 345 | const file_scope = zcu.navFileScope(func.owner_nav); | |
| 346 | const target = &file_scope.mod.resolved_target.result; | |
| 349 | 347 | |
| 350 | 348 | var branch_stack = std.ArrayList(Branch).init(gpa); |
| 351 | 349 | defer { |
| ... | ... | @@ -364,7 +362,7 @@ pub fn generate( |
| 364 | 362 | .target = target, |
| 365 | 363 | .bin_file = lf, |
| 366 | 364 | .func_index = func_index, |
| 367 | .owner_decl = func.owner_decl, | |
| 365 | .owner_nav = func.owner_nav, | |
| 368 | 366 | .err_msg = null, |
| 369 | 367 | .args = undefined, // populated after `resolveCallingConventionValues` |
| 370 | 368 | .ret_mcv = undefined, // populated after `resolveCallingConventionValues` |
| ... | ... | @@ -4053,8 +4051,8 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type |
| 4053 | 4051 | @panic("TODO store"); |
| 4054 | 4052 | }, |
| 4055 | 4053 | .coff => blk: { |
| 4056 | const coff_file = self.bin_file.cast(link.File.Coff).?; | |
| 4057 | const atom = try coff_file.getOrCreateAtomForDecl(self.owner_decl); | |
| 4054 | const coff_file = self.bin_file.cast(.coff).?; | |
| 4055 | const atom = try coff_file.getOrCreateAtomForNav(self.owner_nav); | |
| 4058 | 4056 | break :blk coff_file.getAtom(atom).getSymbolIndex().?; |
| 4059 | 4057 | }, |
| 4060 | 4058 | else => unreachable, // unsupported target format |
| ... | ... | @@ -4289,6 +4287,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier |
| 4289 | 4287 | const ty = self.typeOf(callee); |
| 4290 | 4288 | const pt = self.pt; |
| 4291 | 4289 | const mod = pt.zcu; |
| 4290 | const ip = &mod.intern_pool; | |
| 4292 | 4291 | |
| 4293 | 4292 | const fn_ty = switch (ty.zigTypeTag(mod)) { |
| 4294 | 4293 | .Fn => ty, |
| ... | ... | @@ -4351,19 +4350,19 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier |
| 4351 | 4350 | |
| 4352 | 4351 | // Due to incremental compilation, how function calls are generated depends |
| 4353 | 4352 | // on linking. |
| 4354 | if (try self.air.value(callee, pt)) |func_value| { | |
| 4355 | if (func_value.getFunction(mod)) |func| { | |
| 4356 | if (self.bin_file.cast(link.File.Elf)) |elf_file| { | |
| 4353 | if (try self.air.value(callee, pt)) |func_value| switch (ip.indexToKey(func_value.toIntern())) { | |
| 4354 | .func => |func| { | |
| 4355 | if (self.bin_file.cast(.elf)) |elf_file| { | |
| 4357 | 4356 | const zo = elf_file.zigObjectPtr().?; |
| 4358 | const sym_index = try zo.getOrCreateMetadataForDecl(elf_file, func.owner_decl); | |
| 4357 | const sym_index = try zo.getOrCreateMetadataForNav(elf_file, func.owner_nav); | |
| 4359 | 4358 | const sym = zo.symbol(sym_index); |
| 4360 | 4359 | _ = try sym.getOrCreateZigGotEntry(sym_index, elf_file); |
| 4361 | 4360 | const got_addr = @as(u32, @intCast(sym.zigGotAddress(elf_file))); |
| 4362 | 4361 | try self.genSetReg(Type.usize, .x30, .{ .memory = got_addr }); |
| 4363 | } else if (self.bin_file.cast(link.File.MachO)) |macho_file| { | |
| 4362 | } else if (self.bin_file.cast(.macho)) |macho_file| { | |
| 4364 | 4363 | _ = macho_file; |
| 4365 | 4364 | @panic("TODO airCall"); |
| 4366 | // const atom = try macho_file.getOrCreateAtomForDecl(func.owner_decl); | |
| 4365 | // const atom = try macho_file.getOrCreateAtomForNav(func.owner_nav); | |
| 4367 | 4366 | // const sym_index = macho_file.getAtom(atom).getSymbolIndex().?; |
| 4368 | 4367 | // try self.genSetReg(Type.u64, .x30, .{ |
| 4369 | 4368 | // .linker_load = .{ |
| ... | ... | @@ -4371,8 +4370,8 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier |
| 4371 | 4370 | // .sym_index = sym_index, |
| 4372 | 4371 | // }, |
| 4373 | 4372 | // }); |
| 4374 | } else if (self.bin_file.cast(link.File.Coff)) |coff_file| { | |
| 4375 | const atom = try coff_file.getOrCreateAtomForDecl(func.owner_decl); | |
| 4373 | } else if (self.bin_file.cast(.coff)) |coff_file| { | |
| 4374 | const atom = try coff_file.getOrCreateAtomForNav(func.owner_nav); | |
| 4376 | 4375 | const sym_index = coff_file.getAtom(atom).getSymbolIndex().?; |
| 4377 | 4376 | try self.genSetReg(Type.u64, .x30, .{ |
| 4378 | 4377 | .linker_load = .{ |
| ... | ... | @@ -4380,8 +4379,8 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier |
| 4380 | 4379 | .sym_index = sym_index, |
| 4381 | 4380 | }, |
| 4382 | 4381 | }); |
| 4383 | } else if (self.bin_file.cast(link.File.Plan9)) |p9| { | |
| 4384 | const atom_index = try p9.seeDecl(func.owner_decl); | |
| 4382 | } else if (self.bin_file.cast(.plan9)) |p9| { | |
| 4383 | const atom_index = try p9.seeNav(pt, func.owner_nav); | |
| 4385 | 4384 | const atom = p9.getAtom(atom_index); |
| 4386 | 4385 | try self.genSetReg(Type.usize, .x30, .{ .memory = atom.getOffsetTableAddress(p9) }); |
| 4387 | 4386 | } else unreachable; |
| ... | ... | @@ -4390,14 +4389,15 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier |
| 4390 | 4389 | .tag = .blr, |
| 4391 | 4390 | .data = .{ .reg = .x30 }, |
| 4392 | 4391 | }); |
| 4393 | } else if (func_value.getExternFunc(mod)) |extern_func| { | |
| 4394 | const decl_name = mod.declPtr(extern_func.decl).name.toSlice(&mod.intern_pool); | |
| 4395 | const lib_name = extern_func.lib_name.toSlice(&mod.intern_pool); | |
| 4396 | if (self.bin_file.cast(link.File.MachO)) |macho_file| { | |
| 4392 | }, | |
| 4393 | .@"extern" => |@"extern"| { | |
| 4394 | const nav_name = ip.getNav(@"extern".owner_nav).name.toSlice(ip); | |
| 4395 | const lib_name = @"extern".lib_name.toSlice(ip); | |
| 4396 | if (self.bin_file.cast(.macho)) |macho_file| { | |
| 4397 | 4397 | _ = macho_file; |
| 4398 | 4398 | @panic("TODO airCall"); |
| 4399 | // const sym_index = try macho_file.getGlobalSymbol(decl_name, lib_name); | |
| 4400 | // const atom = try macho_file.getOrCreateAtomForDecl(self.owner_decl); | |
| 4399 | // const sym_index = try macho_file.getGlobalSymbol(nav_name, lib_name); | |
| 4400 | // const atom = try macho_file.getOrCreateAtomForNav(self.owner_nav); | |
| 4401 | 4401 | // const atom_index = macho_file.getAtom(atom).getSymbolIndex().?; |
| 4402 | 4402 | // _ = try self.addInst(.{ |
| 4403 | 4403 | // .tag = .call_extern, |
| ... | ... | @@ -4408,8 +4408,8 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier |
| 4408 | 4408 | // }, |
| 4409 | 4409 | // }, |
| 4410 | 4410 | // }); |
| 4411 | } else if (self.bin_file.cast(link.File.Coff)) |coff_file| { | |
| 4412 | const sym_index = try coff_file.getGlobalSymbol(decl_name, lib_name); | |
| 4411 | } else if (self.bin_file.cast(.coff)) |coff_file| { | |
| 4412 | const sym_index = try coff_file.getGlobalSymbol(nav_name, lib_name); | |
| 4413 | 4413 | try self.genSetReg(Type.u64, .x30, .{ |
| 4414 | 4414 | .linker_load = .{ |
| 4415 | 4415 | .type = .import, |
| ... | ... | @@ -4423,9 +4423,8 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier |
| 4423 | 4423 | } else { |
| 4424 | 4424 | return self.fail("TODO implement calling extern functions", .{}); |
| 4425 | 4425 | } |
| 4426 | } else { | |
| 4427 | return self.fail("TODO implement calling bitcasted functions", .{}); | |
| 4428 | } | |
| 4426 | }, | |
| 4427 | else => return self.fail("TODO implement calling bitcasted functions", .{}), | |
| 4429 | 4428 | } else { |
| 4430 | 4429 | assert(ty.zigTypeTag(mod) == .Pointer); |
| 4431 | 4430 | const mcv = try self.resolveInst(callee); |
| ... | ... | @@ -5594,8 +5593,8 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro |
| 5594 | 5593 | @panic("TODO genSetStack"); |
| 5595 | 5594 | }, |
| 5596 | 5595 | .coff => blk: { |
| 5597 | const coff_file = self.bin_file.cast(link.File.Coff).?; | |
| 5598 | const atom = try coff_file.getOrCreateAtomForDecl(self.owner_decl); | |
| 5596 | const coff_file = self.bin_file.cast(.coff).?; | |
| 5597 | const atom = try coff_file.getOrCreateAtomForNav(self.owner_nav); | |
| 5599 | 5598 | break :blk coff_file.getAtom(atom).getSymbolIndex().?; |
| 5600 | 5599 | }, |
| 5601 | 5600 | else => unreachable, // unsupported target format |
| ... | ... | @@ -5717,8 +5716,8 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void |
| 5717 | 5716 | // break :blk macho_file.getAtom(atom).getSymbolIndex().?; |
| 5718 | 5717 | }, |
| 5719 | 5718 | .coff => blk: { |
| 5720 | const coff_file = self.bin_file.cast(link.File.Coff).?; | |
| 5721 | const atom = try coff_file.getOrCreateAtomForDecl(self.owner_decl); | |
| 5719 | const coff_file = self.bin_file.cast(.coff).?; | |
| 5720 | const atom = try coff_file.getOrCreateAtomForNav(self.owner_nav); | |
| 5722 | 5721 | break :blk coff_file.getAtom(atom).getSymbolIndex().?; |
| 5723 | 5722 | }, |
| 5724 | 5723 | else => unreachable, // unsupported target format |
| ... | ... | @@ -5915,8 +5914,8 @@ fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) I |
| 5915 | 5914 | // break :blk macho_file.getAtom(atom).getSymbolIndex().?; |
| 5916 | 5915 | }, |
| 5917 | 5916 | .coff => blk: { |
| 5918 | const coff_file = self.bin_file.cast(link.File.Coff).?; | |
| 5919 | const atom = try coff_file.getOrCreateAtomForDecl(self.owner_decl); | |
| 5917 | const coff_file = self.bin_file.cast(.coff).?; | |
| 5918 | const atom = try coff_file.getOrCreateAtomForNav(self.owner_nav); | |
| 5920 | 5919 | break :blk coff_file.getAtom(atom).getSymbolIndex().?; |
| 5921 | 5920 | }, |
| 5922 | 5921 | else => unreachable, // unsupported target format |
| ... | ... | @@ -6226,7 +6225,7 @@ fn genTypedValue(self: *Self, val: Value) InnerError!MCValue { |
| 6226 | 6225 | self.pt, |
| 6227 | 6226 | self.src_loc, |
| 6228 | 6227 | val, |
| 6229 | self.owner_decl, | |
| 6228 | self.target.*, | |
| 6230 | 6229 | )) { |
| 6231 | 6230 | .mcv => |mcv| switch (mcv) { |
| 6232 | 6231 | .none => .none, |
src/arch/aarch64/Emit.zig+4-4| ... | ... | @@ -687,7 +687,7 @@ fn mirCallExtern(emit: *Emit, inst: Mir.Inst.Index) !void { |
| 687 | 687 | }; |
| 688 | 688 | _ = offset; |
| 689 | 689 | |
| 690 | if (emit.bin_file.cast(link.File.MachO)) |macho_file| { | |
| 690 | if (emit.bin_file.cast(.macho)) |macho_file| { | |
| 691 | 691 | _ = macho_file; |
| 692 | 692 | @panic("TODO mirCallExtern"); |
| 693 | 693 | // // Add relocation to the decl. |
| ... | ... | @@ -701,7 +701,7 @@ fn mirCallExtern(emit: *Emit, inst: Mir.Inst.Index) !void { |
| 701 | 701 | // .pcrel = true, |
| 702 | 702 | // .length = 2, |
| 703 | 703 | // }); |
| 704 | } else if (emit.bin_file.cast(link.File.Coff)) |_| { | |
| 704 | } else if (emit.bin_file.cast(.coff)) |_| { | |
| 705 | 705 | unreachable; // Calling imports is handled via `.load_memory_import` |
| 706 | 706 | } else { |
| 707 | 707 | return emit.fail("Implement call_extern for linking backends != {{ COFF, MachO }}", .{}); |
| ... | ... | @@ -903,7 +903,7 @@ fn mirLoadMemoryPie(emit: *Emit, inst: Mir.Inst.Index) !void { |
| 903 | 903 | else => unreachable, |
| 904 | 904 | } |
| 905 | 905 | |
| 906 | if (emit.bin_file.cast(link.File.MachO)) |macho_file| { | |
| 906 | if (emit.bin_file.cast(.macho)) |macho_file| { | |
| 907 | 907 | _ = macho_file; |
| 908 | 908 | @panic("TODO mirLoadMemoryPie"); |
| 909 | 909 | // const Atom = link.File.MachO.Atom; |
| ... | ... | @@ -932,7 +932,7 @@ fn mirLoadMemoryPie(emit: *Emit, inst: Mir.Inst.Index) !void { |
| 932 | 932 | // else => unreachable, |
| 933 | 933 | // }, |
| 934 | 934 | // } }); |
| 935 | } else if (emit.bin_file.cast(link.File.Coff)) |coff_file| { | |
| 935 | } else if (emit.bin_file.cast(.coff)) |coff_file| { | |
| 936 | 936 | const atom_index = coff_file.getAtomIndexForSymbol(.{ .sym_index = data.atom_index, .file = null }).?; |
| 937 | 937 | const target = switch (tag) { |
| 938 | 938 | .load_memory_got, |
src/arch/arm/CodeGen.zig+21-20| ... | ... | @@ -262,7 +262,7 @@ const DbgInfoReloc = struct { |
| 262 | 262 | fn genArgDbgInfo(reloc: DbgInfoReloc, function: Self) error{OutOfMemory}!void { |
| 263 | 263 | switch (function.debug_output) { |
| 264 | 264 | .dwarf => |dw| { |
| 265 | const loc: link.File.Dwarf.DeclState.DbgInfoLoc = switch (reloc.mcv) { | |
| 265 | const loc: link.File.Dwarf.NavState.DbgInfoLoc = switch (reloc.mcv) { | |
| 266 | 266 | .register => |reg| .{ .register = reg.dwarfLocOp() }, |
| 267 | 267 | .stack_offset, |
| 268 | 268 | .stack_argument_offset, |
| ... | ... | @@ -280,7 +280,7 @@ const DbgInfoReloc = struct { |
| 280 | 280 | else => unreachable, // not a possible argument |
| 281 | 281 | }; |
| 282 | 282 | |
| 283 | try dw.genArgDbgInfo(reloc.name, reloc.ty, function.pt.zcu.funcOwnerDeclIndex(function.func_index), loc); | |
| 283 | try dw.genArgDbgInfo(reloc.name, reloc.ty, function.pt.zcu.funcInfo(function.func_index).owner_nav, loc); | |
| 284 | 284 | }, |
| 285 | 285 | .plan9 => {}, |
| 286 | 286 | .none => {}, |
| ... | ... | @@ -296,7 +296,7 @@ const DbgInfoReloc = struct { |
| 296 | 296 | |
| 297 | 297 | switch (function.debug_output) { |
| 298 | 298 | .dwarf => |dw| { |
| 299 | const loc: link.File.Dwarf.DeclState.DbgInfoLoc = switch (reloc.mcv) { | |
| 299 | const loc: link.File.Dwarf.NavState.DbgInfoLoc = switch (reloc.mcv) { | |
| 300 | 300 | .register => |reg| .{ .register = reg.dwarfLocOp() }, |
| 301 | 301 | .ptr_stack_offset, |
| 302 | 302 | .stack_offset, |
| ... | ... | @@ -323,7 +323,7 @@ const DbgInfoReloc = struct { |
| 323 | 323 | break :blk .nop; |
| 324 | 324 | }, |
| 325 | 325 | }; |
| 326 | try dw.genVarDbgInfo(reloc.name, reloc.ty, function.pt.zcu.funcOwnerDeclIndex(function.func_index), is_ptr, loc); | |
| 326 | try dw.genVarDbgInfo(reloc.name, reloc.ty, function.pt.zcu.funcInfo(function.func_index).owner_nav, is_ptr, loc); | |
| 327 | 327 | }, |
| 328 | 328 | .plan9 => {}, |
| 329 | 329 | .none => {}, |
| ... | ... | @@ -346,11 +346,9 @@ pub fn generate( |
| 346 | 346 | const zcu = pt.zcu; |
| 347 | 347 | const gpa = zcu.gpa; |
| 348 | 348 | const func = zcu.funcInfo(func_index); |
| 349 | const fn_owner_decl = zcu.declPtr(func.owner_decl); | |
| 350 | assert(fn_owner_decl.has_tv); | |
| 351 | const fn_type = fn_owner_decl.typeOf(zcu); | |
| 352 | const namespace = zcu.namespacePtr(fn_owner_decl.src_namespace); | |
| 353 | const target = &namespace.fileScope(zcu).mod.resolved_target.result; | |
| 349 | const func_ty = Type.fromInterned(func.ty); | |
| 350 | const file_scope = zcu.navFileScope(func.owner_nav); | |
| 351 | const target = &file_scope.mod.resolved_target.result; | |
| 354 | 352 | |
| 355 | 353 | var branch_stack = std.ArrayList(Branch).init(gpa); |
| 356 | 354 | defer { |
| ... | ... | @@ -372,7 +370,7 @@ pub fn generate( |
| 372 | 370 | .err_msg = null, |
| 373 | 371 | .args = undefined, // populated after `resolveCallingConventionValues` |
| 374 | 372 | .ret_mcv = undefined, // populated after `resolveCallingConventionValues` |
| 375 | .fn_type = fn_type, | |
| 373 | .fn_type = func_ty, | |
| 376 | 374 | .arg_index = 0, |
| 377 | 375 | .branch_stack = &branch_stack, |
| 378 | 376 | .src_loc = src_loc, |
| ... | ... | @@ -385,7 +383,7 @@ pub fn generate( |
| 385 | 383 | defer function.exitlude_jump_relocs.deinit(gpa); |
| 386 | 384 | defer function.dbg_info_relocs.deinit(gpa); |
| 387 | 385 | |
| 388 | var call_info = function.resolveCallingConventionValues(fn_type) catch |err| switch (err) { | |
| 386 | var call_info = function.resolveCallingConventionValues(func_ty) catch |err| switch (err) { | |
| 389 | 387 | error.CodegenFail => return Result{ .fail = function.err_msg.? }, |
| 390 | 388 | error.OutOfRegisters => return Result{ |
| 391 | 389 | .fail = try ErrorMsg.create(gpa, src_loc, "CodeGen ran out of registers. This is a bug in the Zig compiler.", .{}), |
| ... | ... | @@ -4264,6 +4262,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier |
| 4264 | 4262 | const ty = self.typeOf(callee); |
| 4265 | 4263 | const pt = self.pt; |
| 4266 | 4264 | const mod = pt.zcu; |
| 4265 | const ip = &mod.intern_pool; | |
| 4267 | 4266 | |
| 4268 | 4267 | const fn_ty = switch (ty.zigTypeTag(mod)) { |
| 4269 | 4268 | .Fn => ty, |
| ... | ... | @@ -4333,16 +4332,16 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier |
| 4333 | 4332 | |
| 4334 | 4333 | // Due to incremental compilation, how function calls are generated depends |
| 4335 | 4334 | // on linking. |
| 4336 | if (try self.air.value(callee, pt)) |func_value| { | |
| 4337 | if (func_value.getFunction(mod)) |func| { | |
| 4338 | if (self.bin_file.cast(link.File.Elf)) |elf_file| { | |
| 4335 | if (try self.air.value(callee, pt)) |func_value| switch (ip.indexToKey(func_value.toIntern())) { | |
| 4336 | .func => |func| { | |
| 4337 | if (self.bin_file.cast(.elf)) |elf_file| { | |
| 4339 | 4338 | const zo = elf_file.zigObjectPtr().?; |
| 4340 | const sym_index = try zo.getOrCreateMetadataForDecl(elf_file, func.owner_decl); | |
| 4339 | const sym_index = try zo.getOrCreateMetadataForNav(elf_file, func.owner_nav); | |
| 4341 | 4340 | const sym = zo.symbol(sym_index); |
| 4342 | 4341 | _ = try sym.getOrCreateZigGotEntry(sym_index, elf_file); |
| 4343 | 4342 | const got_addr: u32 = @intCast(sym.zigGotAddress(elf_file)); |
| 4344 | 4343 | try self.genSetReg(Type.usize, .lr, .{ .memory = got_addr }); |
| 4345 | } else if (self.bin_file.cast(link.File.MachO)) |_| { | |
| 4344 | } else if (self.bin_file.cast(.macho)) |_| { | |
| 4346 | 4345 | unreachable; // unsupported architecture for MachO |
| 4347 | 4346 | } else { |
| 4348 | 4347 | return self.fail("TODO implement call on {s} for {s}", .{ |
| ... | ... | @@ -4350,11 +4349,13 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier |
| 4350 | 4349 | @tagName(self.target.cpu.arch), |
| 4351 | 4350 | }); |
| 4352 | 4351 | } |
| 4353 | } else if (func_value.getExternFunc(mod)) |_| { | |
| 4352 | }, | |
| 4353 | .@"extern" => { | |
| 4354 | 4354 | return self.fail("TODO implement calling extern functions", .{}); |
| 4355 | } else { | |
| 4355 | }, | |
| 4356 | else => { | |
| 4356 | 4357 | return self.fail("TODO implement calling bitcasted functions", .{}); |
| 4357 | } | |
| 4358 | }, | |
| 4358 | 4359 | } else { |
| 4359 | 4360 | assert(ty.zigTypeTag(mod) == .Pointer); |
| 4360 | 4361 | const mcv = try self.resolveInst(callee); |
| ... | ... | @@ -6178,7 +6179,7 @@ fn genTypedValue(self: *Self, val: Value) InnerError!MCValue { |
| 6178 | 6179 | pt, |
| 6179 | 6180 | self.src_loc, |
| 6180 | 6181 | val, |
| 6181 | pt.zcu.funcOwnerDeclIndex(self.func_index), | |
| 6182 | self.target.*, | |
| 6182 | 6183 | )) { |
| 6183 | 6184 | .mcv => |mcv| switch (mcv) { |
| 6184 | 6185 | .none => .none, |
src/arch/riscv64/CodeGen.zig+40-77| ... | ... | @@ -118,26 +118,18 @@ const RegisterOffset = struct { reg: Register, off: i32 = 0 }; |
| 118 | 118 | pub const FrameAddr = struct { index: FrameIndex, off: i32 = 0 }; |
| 119 | 119 | |
| 120 | 120 | const Owner = union(enum) { |
| 121 | func_index: InternPool.Index, | |
| 121 | nav_index: InternPool.Nav.Index, | |
| 122 | 122 | lazy_sym: link.File.LazySymbol, |
| 123 | 123 | |
| 124 | fn getDecl(owner: Owner, zcu: *Zcu) InternPool.DeclIndex { | |
| 125 | return switch (owner) { | |
| 126 | .func_index => |func_index| zcu.funcOwnerDeclIndex(func_index), | |
| 127 | .lazy_sym => |lazy_sym| lazy_sym.ty.getOwnerDecl(zcu), | |
| 128 | }; | |
| 129 | } | |
| 130 | ||
| 131 | 124 | fn getSymbolIndex(owner: Owner, func: *Func) !u32 { |
| 132 | 125 | const pt = func.pt; |
| 133 | 126 | switch (owner) { |
| 134 | .func_index => |func_index| { | |
| 135 | const decl_index = func.pt.zcu.funcOwnerDeclIndex(func_index); | |
| 136 | const elf_file = func.bin_file.cast(link.File.Elf).?; | |
| 137 | return elf_file.zigObjectPtr().?.getOrCreateMetadataForDecl(elf_file, decl_index); | |
| 127 | .nav_index => |nav_index| { | |
| 128 | const elf_file = func.bin_file.cast(.elf).?; | |
| 129 | return elf_file.zigObjectPtr().?.getOrCreateMetadataForNav(elf_file, nav_index); | |
| 138 | 130 | }, |
| 139 | 131 | .lazy_sym => |lazy_sym| { |
| 140 | const elf_file = func.bin_file.cast(link.File.Elf).?; | |
| 132 | const elf_file = func.bin_file.cast(.elf).?; | |
| 141 | 133 | return elf_file.zigObjectPtr().?.getOrCreateMetadataForLazySymbol(elf_file, pt, lazy_sym) catch |err| |
| 142 | 134 | func.fail("{s} creating lazy symbol", .{@errorName(err)}); |
| 143 | 135 | }, |
| ... | ... | @@ -767,12 +759,8 @@ pub fn generate( |
| 767 | 759 | const gpa = zcu.gpa; |
| 768 | 760 | const ip = &zcu.intern_pool; |
| 769 | 761 | const func = zcu.funcInfo(func_index); |
| 770 | const fn_owner_decl = zcu.declPtr(func.owner_decl); | |
| 771 | assert(fn_owner_decl.has_tv); | |
| 772 | const fn_type = fn_owner_decl.typeOf(zcu); | |
| 773 | const namespace = zcu.namespacePtr(fn_owner_decl.src_namespace); | |
| 774 | const target = &namespace.fileScope(zcu).mod.resolved_target.result; | |
| 775 | const mod = namespace.fileScope(zcu).mod; | |
| 762 | const fn_type = Type.fromInterned(func.ty); | |
| 763 | const mod = zcu.navFileScope(func.owner_nav).mod; | |
| 776 | 764 | |
| 777 | 765 | var branch_stack = std.ArrayList(Branch).init(gpa); |
| 778 | 766 | defer { |
| ... | ... | @@ -789,9 +777,9 @@ pub fn generate( |
| 789 | 777 | .mod = mod, |
| 790 | 778 | .bin_file = bin_file, |
| 791 | 779 | .liveness = liveness, |
| 792 | .target = target, | |
| 780 | .target = &mod.resolved_target.result, | |
| 793 | 781 | .debug_output = debug_output, |
| 794 | .owner = .{ .func_index = func_index }, | |
| 782 | .owner = .{ .nav_index = func.owner_nav }, | |
| 795 | 783 | .err_msg = null, |
| 796 | 784 | .args = undefined, // populated after `resolveCallingConventionValues` |
| 797 | 785 | .ret_mcv = undefined, // populated after `resolveCallingConventionValues` |
| ... | ... | @@ -818,7 +806,7 @@ pub fn generate( |
| 818 | 806 | function.mir_instructions.deinit(gpa); |
| 819 | 807 | } |
| 820 | 808 | |
| 821 | wip_mir_log.debug("{}:", .{function.fmtDecl(func.owner_decl)}); | |
| 809 | wip_mir_log.debug("{}:", .{fmtNav(func.owner_nav, ip)}); | |
| 822 | 810 | |
| 823 | 811 | try function.frame_allocs.resize(gpa, FrameIndex.named_count); |
| 824 | 812 | function.frame_allocs.set( |
| ... | ... | @@ -1074,22 +1062,22 @@ fn fmtWipMir(func: *Func, inst: Mir.Inst.Index) std.fmt.Formatter(formatWipMir) |
| 1074 | 1062 | return .{ .data = .{ .func = func, .inst = inst } }; |
| 1075 | 1063 | } |
| 1076 | 1064 | |
| 1077 | const FormatDeclData = struct { | |
| 1078 | zcu: *Zcu, | |
| 1079 | decl_index: InternPool.DeclIndex, | |
| 1065 | const FormatNavData = struct { | |
| 1066 | ip: *const InternPool, | |
| 1067 | nav_index: InternPool.Nav.Index, | |
| 1080 | 1068 | }; |
| 1081 | fn formatDecl( | |
| 1082 | data: FormatDeclData, | |
| 1069 | fn formatNav( | |
| 1070 | data: FormatNavData, | |
| 1083 | 1071 | comptime _: []const u8, |
| 1084 | 1072 | _: std.fmt.FormatOptions, |
| 1085 | 1073 | writer: anytype, |
| 1086 | 1074 | ) @TypeOf(writer).Error!void { |
| 1087 | try writer.print("{}", .{data.zcu.declPtr(data.decl_index).fqn.fmt(&data.zcu.intern_pool)}); | |
| 1075 | try writer.print("{}", .{data.ip.getNav(data.nav_index).fqn.fmt(data.ip)}); | |
| 1088 | 1076 | } |
| 1089 | fn fmtDecl(func: *Func, decl_index: InternPool.DeclIndex) std.fmt.Formatter(formatDecl) { | |
| 1077 | fn fmtNav(nav_index: InternPool.Nav.Index, ip: *const InternPool) std.fmt.Formatter(formatNav) { | |
| 1090 | 1078 | return .{ .data = .{ |
| 1091 | .zcu = func.pt.zcu, | |
| 1092 | .decl_index = decl_index, | |
| 1079 | .ip = ip, | |
| 1080 | .nav_index = nav_index, | |
| 1093 | 1081 | } }; |
| 1094 | 1082 | } |
| 1095 | 1083 | |
| ... | ... | @@ -1393,9 +1381,9 @@ fn genLazy(func: *Func, lazy_sym: link.File.LazySymbol) InnerError!void { |
| 1393 | 1381 | const pt = func.pt; |
| 1394 | 1382 | const mod = pt.zcu; |
| 1395 | 1383 | const ip = &mod.intern_pool; |
| 1396 | switch (lazy_sym.ty.zigTypeTag(mod)) { | |
| 1384 | switch (Type.fromInterned(lazy_sym.ty).zigTypeTag(mod)) { | |
| 1397 | 1385 | .Enum => { |
| 1398 | const enum_ty = lazy_sym.ty; | |
| 1386 | const enum_ty = Type.fromInterned(lazy_sym.ty); | |
| 1399 | 1387 | wip_mir_log.debug("{}.@tagName:", .{enum_ty.fmt(pt)}); |
| 1400 | 1388 | |
| 1401 | 1389 | const param_regs = abi.Registers.Integer.function_arg_regs; |
| ... | ... | @@ -1408,11 +1396,11 @@ fn genLazy(func: *Func, lazy_sym: link.File.LazySymbol) InnerError!void { |
| 1408 | 1396 | const data_reg, const data_lock = try func.allocReg(.int); |
| 1409 | 1397 | defer func.register_manager.unlockReg(data_lock); |
| 1410 | 1398 | |
| 1411 | const elf_file = func.bin_file.cast(link.File.Elf).?; | |
| 1399 | const elf_file = func.bin_file.cast(.elf).?; | |
| 1412 | 1400 | const zo = elf_file.zigObjectPtr().?; |
| 1413 | 1401 | const sym_index = zo.getOrCreateMetadataForLazySymbol(elf_file, pt, .{ |
| 1414 | 1402 | .kind = .const_data, |
| 1415 | .ty = enum_ty, | |
| 1403 | .ty = enum_ty.toIntern(), | |
| 1416 | 1404 | }) catch |err| |
| 1417 | 1405 | return func.fail("{s} creating lazy symbol", .{@errorName(err)}); |
| 1418 | 1406 | |
| ... | ... | @@ -1479,7 +1467,7 @@ fn genLazy(func: *Func, lazy_sym: link.File.LazySymbol) InnerError!void { |
| 1479 | 1467 | }, |
| 1480 | 1468 | else => return func.fail( |
| 1481 | 1469 | "TODO implement {s} for {}", |
| 1482 | .{ @tagName(lazy_sym.kind), lazy_sym.ty.fmt(pt) }, | |
| 1470 | .{ @tagName(lazy_sym.kind), Type.fromInterned(lazy_sym.ty).fmt(pt) }, | |
| 1483 | 1471 | ), |
| 1484 | 1472 | } |
| 1485 | 1473 | } |
| ... | ... | @@ -4682,17 +4670,14 @@ fn airFieldParentPtr(func: *Func, inst: Air.Inst.Index) !void { |
| 4682 | 4670 | } |
| 4683 | 4671 | |
| 4684 | 4672 | fn genArgDbgInfo(func: Func, inst: Air.Inst.Index, mcv: MCValue) !void { |
| 4685 | const pt = func.pt; | |
| 4686 | const zcu = pt.zcu; | |
| 4687 | 4673 | const arg = func.air.instructions.items(.data)[@intFromEnum(inst)].arg; |
| 4688 | 4674 | const ty = arg.ty.toType(); |
| 4689 | const owner_decl = func.owner.getDecl(zcu); | |
| 4690 | 4675 | if (arg.name == .none) return; |
| 4691 | 4676 | const name = func.air.nullTerminatedString(@intFromEnum(arg.name)); |
| 4692 | 4677 | |
| 4693 | 4678 | switch (func.debug_output) { |
| 4694 | 4679 | .dwarf => |dw| switch (mcv) { |
| 4695 | .register => |reg| try dw.genArgDbgInfo(name, ty, owner_decl, .{ | |
| 4680 | .register => |reg| try dw.genArgDbgInfo(name, ty, func.owner.nav_index, .{ | |
| 4696 | 4681 | .register = reg.dwarfLocOp(), |
| 4697 | 4682 | }), |
| 4698 | 4683 | .load_frame => {}, |
| ... | ... | @@ -4940,14 +4925,14 @@ fn genCall( |
| 4940 | 4925 | switch (switch (func_key) { |
| 4941 | 4926 | else => func_key, |
| 4942 | 4927 | .ptr => |ptr| if (ptr.byte_offset == 0) switch (ptr.base_addr) { |
| 4943 | .decl => |decl| zcu.intern_pool.indexToKey(zcu.declPtr(decl).val.toIntern()), | |
| 4928 | .nav => |nav| zcu.intern_pool.indexToKey(zcu.navValue(nav).toIntern()), | |
| 4944 | 4929 | else => func_key, |
| 4945 | 4930 | } else func_key, |
| 4946 | 4931 | }) { |
| 4947 | 4932 | .func => |func_val| { |
| 4948 | if (func.bin_file.cast(link.File.Elf)) |elf_file| { | |
| 4933 | if (func.bin_file.cast(.elf)) |elf_file| { | |
| 4949 | 4934 | const zo = elf_file.zigObjectPtr().?; |
| 4950 | const sym_index = try zo.getOrCreateMetadataForDecl(elf_file, func_val.owner_decl); | |
| 4935 | const sym_index = try zo.getOrCreateMetadataForNav(elf_file, func_val.owner_nav); | |
| 4951 | 4936 | |
| 4952 | 4937 | if (func.mod.pic) { |
| 4953 | 4938 | return func.fail("TODO: genCall pic", .{}); |
| ... | ... | @@ -4964,19 +4949,18 @@ fn genCall( |
| 4964 | 4949 | } |
| 4965 | 4950 | } else unreachable; // not a valid riscv64 format |
| 4966 | 4951 | }, |
| 4967 | .extern_func => |extern_func| { | |
| 4968 | const owner_decl = zcu.declPtr(extern_func.decl); | |
| 4969 | const lib_name = extern_func.lib_name.toSlice(&zcu.intern_pool); | |
| 4970 | const decl_name = owner_decl.name.toSlice(&zcu.intern_pool); | |
| 4952 | .@"extern" => |@"extern"| { | |
| 4953 | const lib_name = @"extern".lib_name.toSlice(&zcu.intern_pool); | |
| 4954 | const name = @"extern".name.toSlice(&zcu.intern_pool); | |
| 4971 | 4955 | const atom_index = try func.owner.getSymbolIndex(func); |
| 4972 | 4956 | |
| 4973 | const elf_file = func.bin_file.cast(link.File.Elf).?; | |
| 4957 | const elf_file = func.bin_file.cast(.elf).?; | |
| 4974 | 4958 | _ = try func.addInst(.{ |
| 4975 | 4959 | .tag = .pseudo_extern_fn_reloc, |
| 4976 | 4960 | .data = .{ .reloc = .{ |
| 4977 | 4961 | .register = .ra, |
| 4978 | 4962 | .atom_index = atom_index, |
| 4979 | .sym_index = try elf_file.getGlobalSymbol(decl_name, lib_name), | |
| 4963 | .sym_index = try elf_file.getGlobalSymbol(name, lib_name), | |
| 4980 | 4964 | } }, |
| 4981 | 4965 | }); |
| 4982 | 4966 | }, |
| ... | ... | @@ -5213,8 +5197,6 @@ fn genVarDbgInfo( |
| 5213 | 5197 | mcv: MCValue, |
| 5214 | 5198 | name: [:0]const u8, |
| 5215 | 5199 | ) !void { |
| 5216 | const pt = func.pt; | |
| 5217 | const zcu = pt.zcu; | |
| 5218 | 5200 | const is_ptr = switch (tag) { |
| 5219 | 5201 | .dbg_var_ptr => true, |
| 5220 | 5202 | .dbg_var_val => false, |
| ... | ... | @@ -5223,7 +5205,7 @@ fn genVarDbgInfo( |
| 5223 | 5205 | |
| 5224 | 5206 | switch (func.debug_output) { |
| 5225 | 5207 | .dwarf => |dw| { |
| 5226 | const loc: link.File.Dwarf.DeclState.DbgInfoLoc = switch (mcv) { | |
| 5208 | const loc: link.File.Dwarf.NavState.DbgInfoLoc = switch (mcv) { | |
| 5227 | 5209 | .register => |reg| .{ .register = reg.dwarfLocOp() }, |
| 5228 | 5210 | .memory => |address| .{ .memory = address }, |
| 5229 | 5211 | .load_symbol => |sym_off| loc: { |
| ... | ... | @@ -5238,7 +5220,7 @@ fn genVarDbgInfo( |
| 5238 | 5220 | break :blk .nop; |
| 5239 | 5221 | }, |
| 5240 | 5222 | }; |
| 5241 | try dw.genVarDbgInfo(name, ty, func.owner.getDecl(zcu), is_ptr, loc); | |
| 5223 | try dw.genVarDbgInfo(name, ty, func.owner.nav_index, is_ptr, loc); | |
| 5242 | 5224 | }, |
| 5243 | 5225 | .plan9 => {}, |
| 5244 | 5226 | .none => {}, |
| ... | ... | @@ -7804,7 +7786,6 @@ fn airMemcpy(func: *Func, inst: Air.Inst.Index) !void { |
| 7804 | 7786 | |
| 7805 | 7787 | fn airTagName(func: *Func, inst: Air.Inst.Index) !void { |
| 7806 | 7788 | const pt = func.pt; |
| 7807 | const zcu = pt.zcu; | |
| 7808 | 7789 | |
| 7809 | 7790 | const un_op = func.air.instructions.items(.data)[@intFromEnum(inst)].un_op; |
| 7810 | 7791 | const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else result: { |
| ... | ... | @@ -7820,7 +7801,7 @@ fn airTagName(func: *Func, inst: Air.Inst.Index) !void { |
| 7820 | 7801 | const operand = try func.resolveInst(un_op); |
| 7821 | 7802 | try func.genSetReg(enum_ty, param_regs[1], operand); |
| 7822 | 7803 | |
| 7823 | const lazy_sym = link.File.LazySymbol.initDecl(.code, enum_ty.getOwnerDecl(zcu), zcu); | |
| 7804 | const lazy_sym: link.File.LazySymbol = .{ .kind = .code, .ty = enum_ty.toIntern() }; | |
| 7824 | 7805 | const elf_file = func.bin_file.cast(link.File.Elf).?; |
| 7825 | 7806 | const zo = elf_file.zigObjectPtr().?; |
| 7826 | 7807 | const sym_index = zo.getOrCreateMetadataForLazySymbol(elf_file, pt, lazy_sym) catch |err| |
| ... | ... | @@ -8033,32 +8014,14 @@ fn getResolvedInstValue(func: *Func, inst: Air.Inst.Index) *InstTracking { |
| 8033 | 8014 | |
| 8034 | 8015 | fn genTypedValue(func: *Func, val: Value) InnerError!MCValue { |
| 8035 | 8016 | const pt = func.pt; |
| 8036 | const zcu = pt.zcu; | |
| 8037 | const gpa = func.gpa; | |
| 8038 | 8017 | |
| 8039 | const owner_decl_index = func.owner.getDecl(zcu); | |
| 8040 | 8018 | const lf = func.bin_file; |
| 8041 | 8019 | const src_loc = func.src_loc; |
| 8042 | 8020 | |
| 8043 | if (val.isUndef(pt.zcu)) { | |
| 8044 | const local_sym_index = lf.lowerUnnamedConst(pt, val, owner_decl_index) catch |err| { | |
| 8045 | const msg = try ErrorMsg.create(gpa, src_loc, "lowering unnamed undefined constant failed: {s}", .{@errorName(err)}); | |
| 8046 | func.err_msg = msg; | |
| 8047 | return error.CodegenFail; | |
| 8048 | }; | |
| 8049 | switch (lf.tag) { | |
| 8050 | .elf => return MCValue{ .undef = local_sym_index }, | |
| 8051 | else => unreachable, | |
| 8052 | } | |
| 8053 | } | |
| 8054 | ||
| 8055 | const result = try codegen.genTypedValue( | |
| 8056 | lf, | |
| 8057 | pt, | |
| 8058 | src_loc, | |
| 8059 | val, | |
| 8060 | owner_decl_index, | |
| 8061 | ); | |
| 8021 | const result = if (val.isUndef(pt.zcu)) | |
| 8022 | try lf.lowerUav(pt, val.toIntern(), .none, src_loc) | |
| 8023 | else | |
| 8024 | try codegen.genTypedValue(lf, pt, src_loc, val, func.target.*); | |
| 8062 | 8025 | const mcv: MCValue = switch (result) { |
| 8063 | 8026 | .mcv => |mcv| switch (mcv) { |
| 8064 | 8027 | .none => .none, |
src/arch/riscv64/Emit.zig+3-3| ... | ... | @@ -49,7 +49,7 @@ pub fn emitMir(emit: *Emit) Error!void { |
| 49 | 49 | .Lib => emit.lower.link_mode == .static, |
| 50 | 50 | }; |
| 51 | 51 | |
| 52 | const elf_file = emit.bin_file.cast(link.File.Elf).?; | |
| 52 | const elf_file = emit.bin_file.cast(.elf).?; | |
| 53 | 53 | const zo = elf_file.zigObjectPtr().?; |
| 54 | 54 | |
| 55 | 55 | const atom_ptr = zo.symbol(symbol.atom_index).atom(elf_file).?; |
| ... | ... | @@ -81,7 +81,7 @@ pub fn emitMir(emit: *Emit) Error!void { |
| 81 | 81 | }); |
| 82 | 82 | }, |
| 83 | 83 | .load_tlv_reloc => |symbol| { |
| 84 | const elf_file = emit.bin_file.cast(link.File.Elf).?; | |
| 84 | const elf_file = emit.bin_file.cast(.elf).?; | |
| 85 | 85 | const zo = elf_file.zigObjectPtr().?; |
| 86 | 86 | |
| 87 | 87 | const atom_ptr = zo.symbol(symbol.atom_index).atom(elf_file).?; |
| ... | ... | @@ -107,7 +107,7 @@ pub fn emitMir(emit: *Emit) Error!void { |
| 107 | 107 | }); |
| 108 | 108 | }, |
| 109 | 109 | .call_extern_fn_reloc => |symbol| { |
| 110 | const elf_file = emit.bin_file.cast(link.File.Elf).?; | |
| 110 | const elf_file = emit.bin_file.cast(.elf).?; | |
| 111 | 111 | const zo = elf_file.zigObjectPtr().?; |
| 112 | 112 | const atom_ptr = zo.symbol(symbol.atom_index).atom(elf_file).?; |
| 113 | 113 |
src/arch/sparc64/CodeGen.zig+43-48| ... | ... | @@ -273,11 +273,9 @@ pub fn generate( |
| 273 | 273 | const zcu = pt.zcu; |
| 274 | 274 | const gpa = zcu.gpa; |
| 275 | 275 | const func = zcu.funcInfo(func_index); |
| 276 | const fn_owner_decl = zcu.declPtr(func.owner_decl); | |
| 277 | assert(fn_owner_decl.has_tv); | |
| 278 | const fn_type = fn_owner_decl.typeOf(zcu); | |
| 279 | const namespace = zcu.namespacePtr(fn_owner_decl.src_namespace); | |
| 280 | const target = &namespace.fileScope(zcu).mod.resolved_target.result; | |
| 276 | const func_ty = Type.fromInterned(func.ty); | |
| 277 | const file_scope = zcu.navFileScope(func.owner_nav); | |
| 278 | const target = &file_scope.mod.resolved_target.result; | |
| 281 | 279 | |
| 282 | 280 | var branch_stack = std.ArrayList(Branch).init(gpa); |
| 283 | 281 | defer { |
| ... | ... | @@ -300,7 +298,7 @@ pub fn generate( |
| 300 | 298 | .err_msg = null, |
| 301 | 299 | .args = undefined, // populated after `resolveCallingConventionValues` |
| 302 | 300 | .ret_mcv = undefined, // populated after `resolveCallingConventionValues` |
| 303 | .fn_type = fn_type, | |
| 301 | .fn_type = func_ty, | |
| 304 | 302 | .arg_index = 0, |
| 305 | 303 | .branch_stack = &branch_stack, |
| 306 | 304 | .src_loc = src_loc, |
| ... | ... | @@ -312,7 +310,7 @@ pub fn generate( |
| 312 | 310 | defer function.blocks.deinit(gpa); |
| 313 | 311 | defer function.exitlude_jump_relocs.deinit(gpa); |
| 314 | 312 | |
| 315 | var call_info = function.resolveCallingConventionValues(fn_type, .callee) catch |err| switch (err) { | |
| 313 | var call_info = function.resolveCallingConventionValues(func_ty, .callee) catch |err| switch (err) { | |
| 316 | 314 | error.CodegenFail => return Result{ .fail = function.err_msg.? }, |
| 317 | 315 | error.OutOfRegisters => return Result{ |
| 318 | 316 | .fail = try ErrorMsg.create(gpa, src_loc, "CodeGen ran out of registers. This is a bug in the Zig compiler.", .{}), |
| ... | ... | @@ -1306,6 +1304,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier |
| 1306 | 1304 | const ty = self.typeOf(callee); |
| 1307 | 1305 | const pt = self.pt; |
| 1308 | 1306 | const mod = pt.zcu; |
| 1307 | const ip = &mod.intern_pool; | |
| 1309 | 1308 | const fn_ty = switch (ty.zigTypeTag(mod)) { |
| 1310 | 1309 | .Fn => ty, |
| 1311 | 1310 | .Pointer => ty.childType(mod), |
| ... | ... | @@ -1349,46 +1348,42 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier |
| 1349 | 1348 | |
| 1350 | 1349 | // Due to incremental compilation, how function calls are generated depends |
| 1351 | 1350 | // on linking. |
| 1352 | if (try self.air.value(callee, pt)) |func_value| { | |
| 1353 | if (self.bin_file.tag == link.File.Elf.base_tag) { | |
| 1354 | switch (mod.intern_pool.indexToKey(func_value.ip_index)) { | |
| 1355 | .func => |func| { | |
| 1356 | const got_addr = if (self.bin_file.cast(link.File.Elf)) |elf_file| blk: { | |
| 1357 | const zo = elf_file.zigObjectPtr().?; | |
| 1358 | const sym_index = try zo.getOrCreateMetadataForDecl(elf_file, func.owner_decl); | |
| 1359 | const sym = zo.symbol(sym_index); | |
| 1360 | _ = try sym.getOrCreateZigGotEntry(sym_index, elf_file); | |
| 1361 | break :blk @as(u32, @intCast(sym.zigGotAddress(elf_file))); | |
| 1362 | } else unreachable; | |
| 1363 | ||
| 1364 | try self.genSetReg(Type.usize, .o7, .{ .memory = got_addr }); | |
| 1365 | ||
| 1366 | _ = try self.addInst(.{ | |
| 1367 | .tag = .jmpl, | |
| 1368 | .data = .{ | |
| 1369 | .arithmetic_3op = .{ | |
| 1370 | .is_imm = false, | |
| 1371 | .rd = .o7, | |
| 1372 | .rs1 = .o7, | |
| 1373 | .rs2_or_imm = .{ .rs2 = .g0 }, | |
| 1374 | }, | |
| 1375 | }, | |
| 1376 | }); | |
| 1351 | if (try self.air.value(callee, pt)) |func_value| switch (ip.indexToKey(func_value.toIntern())) { | |
| 1352 | .func => |func| { | |
| 1353 | const got_addr = if (self.bin_file.cast(.elf)) |elf_file| blk: { | |
| 1354 | const zo = elf_file.zigObjectPtr().?; | |
| 1355 | const sym_index = try zo.getOrCreateMetadataForNav(elf_file, func.owner_nav); | |
| 1356 | const sym = zo.symbol(sym_index); | |
| 1357 | _ = try sym.getOrCreateZigGotEntry(sym_index, elf_file); | |
| 1358 | break :blk @as(u32, @intCast(sym.zigGotAddress(elf_file))); | |
| 1359 | } else @panic("TODO SPARCv9 currently does not support non-ELF binaries"); | |
| 1360 | ||
| 1361 | try self.genSetReg(Type.usize, .o7, .{ .memory = got_addr }); | |
| 1377 | 1362 | |
| 1378 | // TODO Find a way to fill this delay slot | |
| 1379 | _ = try self.addInst(.{ | |
| 1380 | .tag = .nop, | |
| 1381 | .data = .{ .nop = {} }, | |
| 1382 | }); | |
| 1383 | }, | |
| 1384 | .extern_func => { | |
| 1385 | return self.fail("TODO implement calling extern functions", .{}); | |
| 1386 | }, | |
| 1387 | else => { | |
| 1388 | return self.fail("TODO implement calling bitcasted functions", .{}); | |
| 1363 | _ = try self.addInst(.{ | |
| 1364 | .tag = .jmpl, | |
| 1365 | .data = .{ | |
| 1366 | .arithmetic_3op = .{ | |
| 1367 | .is_imm = false, | |
| 1368 | .rd = .o7, | |
| 1369 | .rs1 = .o7, | |
| 1370 | .rs2_or_imm = .{ .rs2 = .g0 }, | |
| 1371 | }, | |
| 1389 | 1372 | }, |
| 1390 | } | |
| 1391 | } else @panic("TODO SPARCv9 currently does not support non-ELF binaries"); | |
| 1373 | }); | |
| 1374 | ||
| 1375 | // TODO Find a way to fill this delay slot | |
| 1376 | _ = try self.addInst(.{ | |
| 1377 | .tag = .nop, | |
| 1378 | .data = .{ .nop = {} }, | |
| 1379 | }); | |
| 1380 | }, | |
| 1381 | .@"extern" => { | |
| 1382 | return self.fail("TODO implement calling extern functions", .{}); | |
| 1383 | }, | |
| 1384 | else => { | |
| 1385 | return self.fail("TODO implement calling bitcasted functions", .{}); | |
| 1386 | }, | |
| 1392 | 1387 | } else { |
| 1393 | 1388 | assert(ty.zigTypeTag(mod) == .Pointer); |
| 1394 | 1389 | const mcv = try self.resolveInst(callee); |
| ... | ... | @@ -3614,13 +3609,13 @@ fn genArgDbgInfo(self: Self, inst: Air.Inst.Index, mcv: MCValue) !void { |
| 3614 | 3609 | const mod = pt.zcu; |
| 3615 | 3610 | const arg = self.air.instructions.items(.data)[@intFromEnum(inst)].arg; |
| 3616 | 3611 | const ty = arg.ty.toType(); |
| 3617 | const owner_decl = mod.funcOwnerDeclIndex(self.func_index); | |
| 3612 | const owner_nav = mod.funcInfo(self.func_index).owner_nav; | |
| 3618 | 3613 | if (arg.name == .none) return; |
| 3619 | 3614 | const name = self.air.nullTerminatedString(@intFromEnum(arg.name)); |
| 3620 | 3615 | |
| 3621 | 3616 | switch (self.debug_output) { |
| 3622 | 3617 | .dwarf => |dw| switch (mcv) { |
| 3623 | .register => |reg| try dw.genArgDbgInfo(name, ty, owner_decl, .{ | |
| 3618 | .register => |reg| try dw.genArgDbgInfo(name, ty, owner_nav, .{ | |
| 3624 | 3619 | .register = reg.dwarfLocOp(), |
| 3625 | 3620 | }), |
| 3626 | 3621 | else => {}, |
| ... | ... | @@ -4153,7 +4148,7 @@ fn genTypedValue(self: *Self, val: Value) InnerError!MCValue { |
| 4153 | 4148 | pt, |
| 4154 | 4149 | self.src_loc, |
| 4155 | 4150 | val, |
| 4156 | pt.zcu.funcOwnerDeclIndex(self.func_index), | |
| 4151 | self.target.*, | |
| 4157 | 4152 | )) { |
| 4158 | 4153 | .mcv => |mcv| switch (mcv) { |
| 4159 | 4154 | .none => .none, |
src/arch/wasm/CodeGen.zig+194-197| ... | ... | @@ -640,8 +640,8 @@ const CodeGen = @This(); |
| 640 | 640 | |
| 641 | 641 | /// Reference to the function declaration the code |
| 642 | 642 | /// section belongs to |
| 643 | decl: *Decl, | |
| 644 | decl_index: InternPool.DeclIndex, | |
| 643 | owner_nav: InternPool.Nav.Index, | |
| 644 | src_loc: Zcu.LazySrcLoc, | |
| 645 | 645 | /// Current block depth. Used to calculate the relative difference between a break |
| 646 | 646 | /// and block |
| 647 | 647 | block_depth: u32 = 0, |
| ... | ... | @@ -681,7 +681,7 @@ locals: std.ArrayListUnmanaged(u8), |
| 681 | 681 | /// are enabled also. |
| 682 | 682 | simd_immediates: std.ArrayListUnmanaged([16]u8) = .{}, |
| 683 | 683 | /// The Target we're emitting (used to call intInfo) |
| 684 | target: std.Target, | |
| 684 | target: *const std.Target, | |
| 685 | 685 | /// Represents the wasm binary file that is being linked. |
| 686 | 686 | bin_file: *link.File.Wasm, |
| 687 | 687 | pt: Zcu.PerThread, |
| ... | ... | @@ -765,8 +765,7 @@ pub fn deinit(func: *CodeGen) void { |
| 765 | 765 | |
| 766 | 766 | /// Sets `err_msg` on `CodeGen` and returns `error.CodegenFail` which is caught in link/Wasm.zig |
| 767 | 767 | fn fail(func: *CodeGen, comptime fmt: []const u8, args: anytype) InnerError { |
| 768 | const src_loc = func.decl.navSrcLoc(func.pt.zcu); | |
| 769 | func.err_msg = try Zcu.ErrorMsg.create(func.gpa, src_loc, fmt, args); | |
| 768 | func.err_msg = try Zcu.ErrorMsg.create(func.gpa, func.src_loc, fmt, args); | |
| 770 | 769 | return error.CodegenFail; |
| 771 | 770 | } |
| 772 | 771 | |
| ... | ... | @@ -803,8 +802,14 @@ fn resolveInst(func: *CodeGen, ref: Air.Inst.Ref) InnerError!WValue { |
| 803 | 802 | // |
| 804 | 803 | // In the other cases, we will simply lower the constant to a value that fits |
| 805 | 804 | // into a single local (such as a pointer, integer, bool, etc). |
| 806 | const result: WValue = if (isByRef(ty, pt)) | |
| 807 | .{ .memory = try func.bin_file.lowerUnnamedConst(pt, val, func.decl_index) } | |
| 805 | const result: WValue = if (isByRef(ty, pt, func.target.*)) | |
| 806 | switch (try func.bin_file.lowerUav(pt, val.toIntern(), .none, func.src_loc)) { | |
| 807 | .mcv => |mcv| .{ .memory = mcv.load_symbol }, | |
| 808 | .fail => |err_msg| { | |
| 809 | func.err_msg = err_msg; | |
| 810 | return error.CodegenFail; | |
| 811 | }, | |
| 812 | } | |
| 808 | 813 | else |
| 809 | 814 | try func.lowerConstant(val, ty); |
| 810 | 815 | |
| ... | ... | @@ -995,9 +1000,8 @@ fn addExtraAssumeCapacity(func: *CodeGen, extra: anytype) error{OutOfMemory}!u32 |
| 995 | 1000 | } |
| 996 | 1001 | |
| 997 | 1002 | /// Using a given `Type`, returns the corresponding valtype for .auto callconv |
| 998 | fn typeToValtype(ty: Type, pt: Zcu.PerThread) wasm.Valtype { | |
| 1003 | fn typeToValtype(ty: Type, pt: Zcu.PerThread, target: std.Target) wasm.Valtype { | |
| 999 | 1004 | const mod = pt.zcu; |
| 1000 | const target = mod.getTarget(); | |
| 1001 | 1005 | const ip = &mod.intern_pool; |
| 1002 | 1006 | return switch (ty.zigTypeTag(mod)) { |
| 1003 | 1007 | .Float => switch (ty.floatBits(target)) { |
| ... | ... | @@ -1015,19 +1019,19 @@ fn typeToValtype(ty: Type, pt: Zcu.PerThread) wasm.Valtype { |
| 1015 | 1019 | .Struct => blk: { |
| 1016 | 1020 | if (pt.zcu.typeToPackedStruct(ty)) |packed_struct| { |
| 1017 | 1021 | const backing_int_ty = Type.fromInterned(packed_struct.backingIntTypeUnordered(ip)); |
| 1018 | break :blk typeToValtype(backing_int_ty, pt); | |
| 1022 | break :blk typeToValtype(backing_int_ty, pt, target); | |
| 1019 | 1023 | } else { |
| 1020 | 1024 | break :blk .i32; |
| 1021 | 1025 | } |
| 1022 | 1026 | }, |
| 1023 | .Vector => switch (determineSimdStoreStrategy(ty, pt)) { | |
| 1027 | .Vector => switch (determineSimdStoreStrategy(ty, pt, target)) { | |
| 1024 | 1028 | .direct => .v128, |
| 1025 | 1029 | .unrolled => .i32, |
| 1026 | 1030 | }, |
| 1027 | 1031 | .Union => switch (ty.containerLayout(pt.zcu)) { |
| 1028 | 1032 | .@"packed" => blk: { |
| 1029 | 1033 | const int_ty = pt.intType(.unsigned, @as(u16, @intCast(ty.bitSize(pt)))) catch @panic("out of memory"); |
| 1030 | break :blk typeToValtype(int_ty, pt); | |
| 1034 | break :blk typeToValtype(int_ty, pt, target); | |
| 1031 | 1035 | }, |
| 1032 | 1036 | else => .i32, |
| 1033 | 1037 | }, |
| ... | ... | @@ -1036,17 +1040,17 @@ fn typeToValtype(ty: Type, pt: Zcu.PerThread) wasm.Valtype { |
| 1036 | 1040 | } |
| 1037 | 1041 | |
| 1038 | 1042 | /// Using a given `Type`, returns the byte representation of its wasm value type |
| 1039 | fn genValtype(ty: Type, pt: Zcu.PerThread) u8 { | |
| 1040 | return wasm.valtype(typeToValtype(ty, pt)); | |
| 1043 | fn genValtype(ty: Type, pt: Zcu.PerThread, target: std.Target) u8 { | |
| 1044 | return wasm.valtype(typeToValtype(ty, pt, target)); | |
| 1041 | 1045 | } |
| 1042 | 1046 | |
| 1043 | 1047 | /// Using a given `Type`, returns the corresponding wasm value type |
| 1044 | 1048 | /// Differently from `genValtype` this also allows `void` to create a block |
| 1045 | 1049 | /// with no return type |
| 1046 | fn genBlockType(ty: Type, pt: Zcu.PerThread) u8 { | |
| 1050 | fn genBlockType(ty: Type, pt: Zcu.PerThread, target: std.Target) u8 { | |
| 1047 | 1051 | return switch (ty.ip_index) { |
| 1048 | 1052 | .void_type, .noreturn_type => wasm.block_empty, |
| 1049 | else => genValtype(ty, pt), | |
| 1053 | else => genValtype(ty, pt, target), | |
| 1050 | 1054 | }; |
| 1051 | 1055 | } |
| 1052 | 1056 | |
| ... | ... | @@ -1108,7 +1112,7 @@ fn getResolvedInst(func: *CodeGen, ref: Air.Inst.Ref) *WValue { |
| 1108 | 1112 | /// Returns a corresponding `Wvalue` with `local` as active tag |
| 1109 | 1113 | fn allocLocal(func: *CodeGen, ty: Type) InnerError!WValue { |
| 1110 | 1114 | const pt = func.pt; |
| 1111 | const valtype = typeToValtype(ty, pt); | |
| 1115 | const valtype = typeToValtype(ty, pt, func.target.*); | |
| 1112 | 1116 | const index_or_null = switch (valtype) { |
| 1113 | 1117 | .i32 => func.free_locals_i32.popOrNull(), |
| 1114 | 1118 | .i64 => func.free_locals_i64.popOrNull(), |
| ... | ... | @@ -1128,7 +1132,7 @@ fn allocLocal(func: *CodeGen, ty: Type) InnerError!WValue { |
| 1128 | 1132 | /// to use a zero-initialized local. |
| 1129 | 1133 | fn ensureAllocLocal(func: *CodeGen, ty: Type) InnerError!WValue { |
| 1130 | 1134 | const pt = func.pt; |
| 1131 | try func.locals.append(func.gpa, genValtype(ty, pt)); | |
| 1135 | try func.locals.append(func.gpa, genValtype(ty, pt, func.target.*)); | |
| 1132 | 1136 | const initial_index = func.local_index; |
| 1133 | 1137 | func.local_index += 1; |
| 1134 | 1138 | return .{ .local = .{ .value = initial_index, .references = 1 } }; |
| ... | ... | @@ -1142,6 +1146,7 @@ fn genFunctype( |
| 1142 | 1146 | params: []const InternPool.Index, |
| 1143 | 1147 | return_type: Type, |
| 1144 | 1148 | pt: Zcu.PerThread, |
| 1149 | target: std.Target, | |
| 1145 | 1150 | ) !wasm.Type { |
| 1146 | 1151 | const mod = pt.zcu; |
| 1147 | 1152 | var temp_params = std.ArrayList(wasm.Valtype).init(gpa); |
| ... | ... | @@ -1149,16 +1154,16 @@ fn genFunctype( |
| 1149 | 1154 | var returns = std.ArrayList(wasm.Valtype).init(gpa); |
| 1150 | 1155 | defer returns.deinit(); |
| 1151 | 1156 | |
| 1152 | if (firstParamSRet(cc, return_type, pt)) { | |
| 1157 | if (firstParamSRet(cc, return_type, pt, target)) { | |
| 1153 | 1158 | try temp_params.append(.i32); // memory address is always a 32-bit handle |
| 1154 | 1159 | } else if (return_type.hasRuntimeBitsIgnoreComptime(pt)) { |
| 1155 | 1160 | if (cc == .C) { |
| 1156 | 1161 | const res_classes = abi.classifyType(return_type, pt); |
| 1157 | 1162 | assert(res_classes[0] == .direct and res_classes[1] == .none); |
| 1158 | 1163 | const scalar_type = abi.scalarType(return_type, pt); |
| 1159 | try returns.append(typeToValtype(scalar_type, pt)); | |
| 1164 | try returns.append(typeToValtype(scalar_type, pt, target)); | |
| 1160 | 1165 | } else { |
| 1161 | try returns.append(typeToValtype(return_type, pt)); | |
| 1166 | try returns.append(typeToValtype(return_type, pt, target)); | |
| 1162 | 1167 | } |
| 1163 | 1168 | } else if (return_type.isError(mod)) { |
| 1164 | 1169 | try returns.append(.i32); |
| ... | ... | @@ -1175,9 +1180,9 @@ fn genFunctype( |
| 1175 | 1180 | if (param_classes[1] == .none) { |
| 1176 | 1181 | if (param_classes[0] == .direct) { |
| 1177 | 1182 | const scalar_type = abi.scalarType(param_type, pt); |
| 1178 | try temp_params.append(typeToValtype(scalar_type, pt)); | |
| 1183 | try temp_params.append(typeToValtype(scalar_type, pt, target)); | |
| 1179 | 1184 | } else { |
| 1180 | try temp_params.append(typeToValtype(param_type, pt)); | |
| 1185 | try temp_params.append(typeToValtype(param_type, pt, target)); | |
| 1181 | 1186 | } |
| 1182 | 1187 | } else { |
| 1183 | 1188 | // i128/f128 |
| ... | ... | @@ -1185,7 +1190,7 @@ fn genFunctype( |
| 1185 | 1190 | try temp_params.append(.i64); |
| 1186 | 1191 | } |
| 1187 | 1192 | }, |
| 1188 | else => try temp_params.append(typeToValtype(param_type, pt)), | |
| 1193 | else => try temp_params.append(typeToValtype(param_type, pt, target)), | |
| 1189 | 1194 | } |
| 1190 | 1195 | } |
| 1191 | 1196 | |
| ... | ... | @@ -1205,25 +1210,23 @@ pub fn generate( |
| 1205 | 1210 | code: *std.ArrayList(u8), |
| 1206 | 1211 | debug_output: codegen.DebugInfoOutput, |
| 1207 | 1212 | ) codegen.CodeGenError!codegen.Result { |
| 1208 | _ = src_loc; | |
| 1209 | 1213 | const zcu = pt.zcu; |
| 1210 | 1214 | const gpa = zcu.gpa; |
| 1211 | 1215 | const func = zcu.funcInfo(func_index); |
| 1212 | const decl = zcu.declPtr(func.owner_decl); | |
| 1213 | const namespace = zcu.namespacePtr(decl.src_namespace); | |
| 1214 | const target = namespace.fileScope(zcu).mod.resolved_target.result; | |
| 1216 | const file_scope = zcu.navFileScope(func.owner_nav); | |
| 1217 | const target = &file_scope.mod.resolved_target.result; | |
| 1215 | 1218 | var code_gen: CodeGen = .{ |
| 1216 | 1219 | .gpa = gpa, |
| 1217 | 1220 | .pt = pt, |
| 1218 | 1221 | .air = air, |
| 1219 | 1222 | .liveness = liveness, |
| 1220 | 1223 | .code = code, |
| 1221 | .decl_index = func.owner_decl, | |
| 1222 | .decl = decl, | |
| 1224 | .owner_nav = func.owner_nav, | |
| 1225 | .src_loc = src_loc, | |
| 1223 | 1226 | .err_msg = undefined, |
| 1224 | 1227 | .locals = .{}, |
| 1225 | 1228 | .target = target, |
| 1226 | .bin_file = bin_file.cast(link.File.Wasm).?, | |
| 1229 | .bin_file = bin_file.cast(.wasm).?, | |
| 1227 | 1230 | .debug_output = debug_output, |
| 1228 | 1231 | .func_index = func_index, |
| 1229 | 1232 | }; |
| ... | ... | @@ -1241,12 +1244,13 @@ fn genFunc(func: *CodeGen) InnerError!void { |
| 1241 | 1244 | const pt = func.pt; |
| 1242 | 1245 | const mod = pt.zcu; |
| 1243 | 1246 | const ip = &mod.intern_pool; |
| 1244 | const fn_info = mod.typeToFunc(func.decl.typeOf(mod)).?; | |
| 1245 | var func_type = try genFunctype(func.gpa, fn_info.cc, fn_info.param_types.get(ip), Type.fromInterned(fn_info.return_type), pt); | |
| 1247 | const fn_ty = mod.navValue(func.owner_nav).typeOf(mod); | |
| 1248 | const fn_info = mod.typeToFunc(fn_ty).?; | |
| 1249 | var func_type = try genFunctype(func.gpa, fn_info.cc, fn_info.param_types.get(ip), Type.fromInterned(fn_info.return_type), pt, func.target.*); | |
| 1246 | 1250 | defer func_type.deinit(func.gpa); |
| 1247 | _ = try func.bin_file.storeDeclType(func.decl_index, func_type); | |
| 1251 | _ = try func.bin_file.storeNavType(func.owner_nav, func_type); | |
| 1248 | 1252 | |
| 1249 | var cc_result = try func.resolveCallingConventionValues(func.decl.typeOf(mod)); | |
| 1253 | var cc_result = try func.resolveCallingConventionValues(fn_ty); | |
| 1250 | 1254 | defer cc_result.deinit(func.gpa); |
| 1251 | 1255 | |
| 1252 | 1256 | func.args = cc_result.args; |
| ... | ... | @@ -1324,7 +1328,7 @@ fn genFunc(func: *CodeGen) InnerError!void { |
| 1324 | 1328 | .bin_file = func.bin_file, |
| 1325 | 1329 | .code = func.code, |
| 1326 | 1330 | .locals = func.locals.items, |
| 1327 | .decl_index = func.decl_index, | |
| 1331 | .owner_nav = func.owner_nav, | |
| 1328 | 1332 | .dbg_output = func.debug_output, |
| 1329 | 1333 | .prev_di_line = 0, |
| 1330 | 1334 | .prev_di_column = 0, |
| ... | ... | @@ -1367,7 +1371,7 @@ fn resolveCallingConventionValues(func: *CodeGen, fn_ty: Type) InnerError!CallWV |
| 1367 | 1371 | |
| 1368 | 1372 | // Check if we store the result as a pointer to the stack rather than |
| 1369 | 1373 | // by value |
| 1370 | if (firstParamSRet(fn_info.cc, Type.fromInterned(fn_info.return_type), pt)) { | |
| 1374 | if (firstParamSRet(fn_info.cc, Type.fromInterned(fn_info.return_type), pt, func.target.*)) { | |
| 1371 | 1375 | // the sret arg will be passed as first argument, therefore we |
| 1372 | 1376 | // set the `return_value` before allocating locals for regular args. |
| 1373 | 1377 | result.return_value = .{ .local = .{ .value = func.local_index, .references = 1 } }; |
| ... | ... | @@ -1401,9 +1405,9 @@ fn resolveCallingConventionValues(func: *CodeGen, fn_ty: Type) InnerError!CallWV |
| 1401 | 1405 | return result; |
| 1402 | 1406 | } |
| 1403 | 1407 | |
| 1404 | fn firstParamSRet(cc: std.builtin.CallingConvention, return_type: Type, pt: Zcu.PerThread) bool { | |
| 1408 | fn firstParamSRet(cc: std.builtin.CallingConvention, return_type: Type, pt: Zcu.PerThread, target: std.Target) bool { | |
| 1405 | 1409 | switch (cc) { |
| 1406 | .Unspecified, .Inline => return isByRef(return_type, pt), | |
| 1410 | .Unspecified, .Inline => return isByRef(return_type, pt, target), | |
| 1407 | 1411 | .C => { |
| 1408 | 1412 | const ty_classes = abi.classifyType(return_type, pt); |
| 1409 | 1413 | if (ty_classes[0] == .indirect) return true; |
| ... | ... | @@ -1711,10 +1715,9 @@ fn arch(func: *const CodeGen) std.Target.Cpu.Arch { |
| 1711 | 1715 | |
| 1712 | 1716 | /// For a given `Type`, will return true when the type will be passed |
| 1713 | 1717 | /// by reference, rather than by value |
| 1714 | fn isByRef(ty: Type, pt: Zcu.PerThread) bool { | |
| 1718 | fn isByRef(ty: Type, pt: Zcu.PerThread, target: std.Target) bool { | |
| 1715 | 1719 | const mod = pt.zcu; |
| 1716 | 1720 | const ip = &mod.intern_pool; |
| 1717 | const target = mod.getTarget(); | |
| 1718 | 1721 | switch (ty.zigTypeTag(mod)) { |
| 1719 | 1722 | .Type, |
| 1720 | 1723 | .ComptimeInt, |
| ... | ... | @@ -1746,11 +1749,11 @@ fn isByRef(ty: Type, pt: Zcu.PerThread) bool { |
| 1746 | 1749 | }, |
| 1747 | 1750 | .Struct => { |
| 1748 | 1751 | if (mod.typeToPackedStruct(ty)) |packed_struct| { |
| 1749 | return isByRef(Type.fromInterned(packed_struct.backingIntTypeUnordered(ip)), pt); | |
| 1752 | return isByRef(Type.fromInterned(packed_struct.backingIntTypeUnordered(ip)), pt, target); | |
| 1750 | 1753 | } |
| 1751 | 1754 | return ty.hasRuntimeBitsIgnoreComptime(pt); |
| 1752 | 1755 | }, |
| 1753 | .Vector => return determineSimdStoreStrategy(ty, pt) == .unrolled, | |
| 1756 | .Vector => return determineSimdStoreStrategy(ty, pt, target) == .unrolled, | |
| 1754 | 1757 | .Int => return ty.intInfo(mod).bits > 64, |
| 1755 | 1758 | .Enum => return ty.intInfo(mod).bits > 64, |
| 1756 | 1759 | .Float => return ty.floatBits(target) > 64, |
| ... | ... | @@ -1784,11 +1787,10 @@ const SimdStoreStrategy = enum { |
| 1784 | 1787 | /// This means when a given type is 128 bits and either the simd128 or relaxed-simd |
| 1785 | 1788 | /// features are enabled, the function will return `.direct`. This would allow to store |
| 1786 | 1789 | /// it using a instruction, rather than an unrolled version. |
| 1787 | fn determineSimdStoreStrategy(ty: Type, pt: Zcu.PerThread) SimdStoreStrategy { | |
| 1790 | fn determineSimdStoreStrategy(ty: Type, pt: Zcu.PerThread, target: std.Target) SimdStoreStrategy { | |
| 1788 | 1791 | std.debug.assert(ty.zigTypeTag(pt.zcu) == .Vector); |
| 1789 | 1792 | if (ty.bitSize(pt) != 128) return .unrolled; |
| 1790 | 1793 | const hasFeature = std.Target.wasm.featureSetHas; |
| 1791 | const target = pt.zcu.getTarget(); | |
| 1792 | 1794 | const features = target.cpu.features; |
| 1793 | 1795 | if (hasFeature(features, .relaxed_simd) or hasFeature(features, .simd128)) { |
| 1794 | 1796 | return .direct; |
| ... | ... | @@ -2091,7 +2093,7 @@ fn airRet(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 2091 | 2093 | const mod = pt.zcu; |
| 2092 | 2094 | const un_op = func.air.instructions.items(.data)[@intFromEnum(inst)].un_op; |
| 2093 | 2095 | const operand = try func.resolveInst(un_op); |
| 2094 | const fn_info = mod.typeToFunc(func.decl.typeOf(mod)).?; | |
| 2096 | const fn_info = mod.typeToFunc(mod.navValue(func.owner_nav).typeOf(mod)).?; | |
| 2095 | 2097 | const ret_ty = Type.fromInterned(fn_info.return_type); |
| 2096 | 2098 | |
| 2097 | 2099 | // result must be stored in the stack and we return a pointer |
| ... | ... | @@ -2108,7 +2110,7 @@ fn airRet(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 2108 | 2110 | .op = .load, |
| 2109 | 2111 | .width = @as(u8, @intCast(scalar_type.abiSize(pt) * 8)), |
| 2110 | 2112 | .signedness = if (scalar_type.isSignedInt(mod)) .signed else .unsigned, |
| 2111 | .valtype1 = typeToValtype(scalar_type, pt), | |
| 2113 | .valtype1 = typeToValtype(scalar_type, pt, func.target.*), | |
| 2112 | 2114 | }); |
| 2113 | 2115 | try func.addMemArg(Mir.Inst.Tag.fromOpcode(opcode), .{ |
| 2114 | 2116 | .offset = operand.offset(), |
| ... | ... | @@ -2140,8 +2142,8 @@ fn airRetPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 2140 | 2142 | break :result try func.allocStack(Type.usize); // create pointer to void |
| 2141 | 2143 | } |
| 2142 | 2144 | |
| 2143 | const fn_info = mod.typeToFunc(func.decl.typeOf(mod)).?; | |
| 2144 | if (firstParamSRet(fn_info.cc, Type.fromInterned(fn_info.return_type), pt)) { | |
| 2145 | const fn_info = mod.typeToFunc(mod.navValue(func.owner_nav).typeOf(mod)).?; | |
| 2146 | if (firstParamSRet(fn_info.cc, Type.fromInterned(fn_info.return_type), pt, func.target.*)) { | |
| 2145 | 2147 | break :result func.return_value; |
| 2146 | 2148 | } |
| 2147 | 2149 | |
| ... | ... | @@ -2158,12 +2160,12 @@ fn airRetLoad(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 2158 | 2160 | const operand = try func.resolveInst(un_op); |
| 2159 | 2161 | const ret_ty = func.typeOf(un_op).childType(mod); |
| 2160 | 2162 | |
| 2161 | const fn_info = mod.typeToFunc(func.decl.typeOf(mod)).?; | |
| 2163 | const fn_info = mod.typeToFunc(mod.navValue(func.owner_nav).typeOf(mod)).?; | |
| 2162 | 2164 | if (!ret_ty.hasRuntimeBitsIgnoreComptime(pt)) { |
| 2163 | 2165 | if (ret_ty.isError(mod)) { |
| 2164 | 2166 | try func.addImm32(0); |
| 2165 | 2167 | } |
| 2166 | } else if (!firstParamSRet(fn_info.cc, Type.fromInterned(fn_info.return_type), pt)) { | |
| 2168 | } else if (!firstParamSRet(fn_info.cc, Type.fromInterned(fn_info.return_type), pt, func.target.*)) { | |
| 2167 | 2169 | // leave on the stack |
| 2168 | 2170 | _ = try func.load(operand, ret_ty, 0); |
| 2169 | 2171 | } |
| ... | ... | @@ -2190,34 +2192,43 @@ fn airCall(func: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif |
| 2190 | 2192 | }; |
| 2191 | 2193 | const ret_ty = fn_ty.fnReturnType(mod); |
| 2192 | 2194 | const fn_info = mod.typeToFunc(fn_ty).?; |
| 2193 | const first_param_sret = firstParamSRet(fn_info.cc, Type.fromInterned(fn_info.return_type), pt); | |
| 2195 | const first_param_sret = firstParamSRet(fn_info.cc, Type.fromInterned(fn_info.return_type), pt, func.target.*); | |
| 2194 | 2196 | |
| 2195 | const callee: ?InternPool.DeclIndex = blk: { | |
| 2197 | const callee: ?InternPool.Nav.Index = blk: { | |
| 2196 | 2198 | const func_val = (try func.air.value(pl_op.operand, pt)) orelse break :blk null; |
| 2197 | 2199 | |
| 2198 | if (func_val.getFunction(mod)) |function| { | |
| 2199 | _ = try func.bin_file.getOrCreateAtomForDecl(pt, function.owner_decl); | |
| 2200 | break :blk function.owner_decl; | |
| 2201 | } else if (func_val.getExternFunc(mod)) |extern_func| { | |
| 2202 | const ext_decl = mod.declPtr(extern_func.decl); | |
| 2203 | const ext_info = mod.typeToFunc(ext_decl.typeOf(mod)).?; | |
| 2204 | var func_type = try genFunctype(func.gpa, ext_info.cc, ext_info.param_types.get(ip), Type.fromInterned(ext_info.return_type), pt); | |
| 2205 | defer func_type.deinit(func.gpa); | |
| 2206 | const atom_index = try func.bin_file.getOrCreateAtomForDecl(pt, extern_func.decl); | |
| 2207 | const atom = func.bin_file.getAtomPtr(atom_index); | |
| 2208 | const type_index = try func.bin_file.storeDeclType(extern_func.decl, func_type); | |
| 2209 | try func.bin_file.addOrUpdateImport( | |
| 2210 | ext_decl.name.toSlice(&mod.intern_pool), | |
| 2211 | atom.sym_index, | |
| 2212 | ext_decl.getOwnedExternFunc(mod).?.lib_name.toSlice(&mod.intern_pool), | |
| 2213 | type_index, | |
| 2214 | ); | |
| 2215 | break :blk extern_func.decl; | |
| 2216 | } else switch (mod.intern_pool.indexToKey(func_val.ip_index)) { | |
| 2200 | switch (ip.indexToKey(func_val.toIntern())) { | |
| 2201 | .func => |function| { | |
| 2202 | _ = try func.bin_file.getOrCreateAtomForNav(pt, function.owner_nav); | |
| 2203 | break :blk function.owner_nav; | |
| 2204 | }, | |
| 2205 | .@"extern" => |@"extern"| { | |
| 2206 | const ext_nav = ip.getNav(@"extern".owner_nav); | |
| 2207 | const ext_info = mod.typeToFunc(Type.fromInterned(@"extern".ty)).?; | |
| 2208 | var func_type = try genFunctype( | |
| 2209 | func.gpa, | |
| 2210 | ext_info.cc, | |
| 2211 | ext_info.param_types.get(ip), | |
| 2212 | Type.fromInterned(ext_info.return_type), | |
| 2213 | pt, | |
| 2214 | func.target.*, | |
| 2215 | ); | |
| 2216 | defer func_type.deinit(func.gpa); | |
| 2217 | const atom_index = try func.bin_file.getOrCreateAtomForNav(pt, @"extern".owner_nav); | |
| 2218 | const atom = func.bin_file.getAtomPtr(atom_index); | |
| 2219 | const type_index = try func.bin_file.storeNavType(@"extern".owner_nav, func_type); | |
| 2220 | try func.bin_file.addOrUpdateImport( | |
| 2221 | ext_nav.name.toSlice(ip), | |
| 2222 | atom.sym_index, | |
| 2223 | @"extern".lib_name.toSlice(ip), | |
| 2224 | type_index, | |
| 2225 | ); | |
| 2226 | break :blk @"extern".owner_nav; | |
| 2227 | }, | |
| 2217 | 2228 | .ptr => |ptr| if (ptr.byte_offset == 0) switch (ptr.base_addr) { |
| 2218 | .decl => |decl| { | |
| 2219 | _ = try func.bin_file.getOrCreateAtomForDecl(pt, decl); | |
| 2220 | break :blk decl; | |
| 2229 | .nav => |nav| { | |
| 2230 | _ = try func.bin_file.getOrCreateAtomForNav(pt, nav); | |
| 2231 | break :blk nav; | |
| 2221 | 2232 | }, |
| 2222 | 2233 | else => {}, |
| 2223 | 2234 | }, |
| ... | ... | @@ -2242,7 +2253,7 @@ fn airCall(func: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif |
| 2242 | 2253 | } |
| 2243 | 2254 | |
| 2244 | 2255 | if (callee) |direct| { |
| 2245 | const atom_index = func.bin_file.zigObjectPtr().?.decls_map.get(direct).?.atom; | |
| 2256 | const atom_index = func.bin_file.zigObjectPtr().?.navs.get(direct).?.atom; | |
| 2246 | 2257 | try func.addLabel(.call, @intFromEnum(func.bin_file.getAtom(atom_index).sym_index)); |
| 2247 | 2258 | } else { |
| 2248 | 2259 | // in this case we call a function pointer |
| ... | ... | @@ -2251,7 +2262,7 @@ fn airCall(func: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif |
| 2251 | 2262 | const operand = try func.resolveInst(pl_op.operand); |
| 2252 | 2263 | try func.emitWValue(operand); |
| 2253 | 2264 | |
| 2254 | var fn_type = try genFunctype(func.gpa, fn_info.cc, fn_info.param_types.get(ip), Type.fromInterned(fn_info.return_type), pt); | |
| 2265 | var fn_type = try genFunctype(func.gpa, fn_info.cc, fn_info.param_types.get(ip), Type.fromInterned(fn_info.return_type), pt, func.target.*); | |
| 2255 | 2266 | defer fn_type.deinit(func.gpa); |
| 2256 | 2267 | |
| 2257 | 2268 | const fn_type_index = try func.bin_file.zigObjectPtr().?.putOrGetFuncType(func.gpa, fn_type); |
| ... | ... | @@ -2315,7 +2326,7 @@ fn airStore(func: *CodeGen, inst: Air.Inst.Index, safety: bool) InnerError!void |
| 2315 | 2326 | // load the value, and then shift+or the rhs into the result location. |
| 2316 | 2327 | const int_elem_ty = try pt.intType(.unsigned, ptr_info.packed_offset.host_size * 8); |
| 2317 | 2328 | |
| 2318 | if (isByRef(int_elem_ty, pt)) { | |
| 2329 | if (isByRef(int_elem_ty, pt, func.target.*)) { | |
| 2319 | 2330 | return func.fail("TODO: airStore for pointers to bitfields with backing type larger than 64bits", .{}); |
| 2320 | 2331 | } |
| 2321 | 2332 | |
| ... | ... | @@ -2381,11 +2392,11 @@ fn store(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerE |
| 2381 | 2392 | const len = @as(u32, @intCast(abi_size)); |
| 2382 | 2393 | return func.memcpy(lhs, rhs, .{ .imm32 = len }); |
| 2383 | 2394 | }, |
| 2384 | .Struct, .Array, .Union => if (isByRef(ty, pt)) { | |
| 2395 | .Struct, .Array, .Union => if (isByRef(ty, pt, func.target.*)) { | |
| 2385 | 2396 | const len = @as(u32, @intCast(abi_size)); |
| 2386 | 2397 | return func.memcpy(lhs, rhs, .{ .imm32 = len }); |
| 2387 | 2398 | }, |
| 2388 | .Vector => switch (determineSimdStoreStrategy(ty, pt)) { | |
| 2399 | .Vector => switch (determineSimdStoreStrategy(ty, pt, func.target.*)) { | |
| 2389 | 2400 | .unrolled => { |
| 2390 | 2401 | const len: u32 = @intCast(abi_size); |
| 2391 | 2402 | return func.memcpy(lhs, rhs, .{ .imm32 = len }); |
| ... | ... | @@ -2443,7 +2454,7 @@ fn store(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerE |
| 2443 | 2454 | // into lhs, so we calculate that and emit that instead |
| 2444 | 2455 | try func.lowerToStack(rhs); |
| 2445 | 2456 | |
| 2446 | const valtype = typeToValtype(ty, pt); | |
| 2457 | const valtype = typeToValtype(ty, pt, func.target.*); | |
| 2447 | 2458 | const opcode = buildOpcode(.{ |
| 2448 | 2459 | .valtype1 = valtype, |
| 2449 | 2460 | .width = @as(u8, @intCast(abi_size * 8)), |
| ... | ... | @@ -2472,7 +2483,7 @@ fn airLoad(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 2472 | 2483 | if (!ty.hasRuntimeBitsIgnoreComptime(pt)) return func.finishAir(inst, .none, &.{ty_op.operand}); |
| 2473 | 2484 | |
| 2474 | 2485 | const result = result: { |
| 2475 | if (isByRef(ty, pt)) { | |
| 2486 | if (isByRef(ty, pt, func.target.*)) { | |
| 2476 | 2487 | const new_local = try func.allocStack(ty); |
| 2477 | 2488 | try func.store(new_local, operand, ty, 0); |
| 2478 | 2489 | break :result new_local; |
| ... | ... | @@ -2522,7 +2533,7 @@ fn load(func: *CodeGen, operand: WValue, ty: Type, offset: u32) InnerError!WValu |
| 2522 | 2533 | |
| 2523 | 2534 | const abi_size: u8 = @intCast(ty.abiSize(pt)); |
| 2524 | 2535 | const opcode = buildOpcode(.{ |
| 2525 | .valtype1 = typeToValtype(ty, pt), | |
| 2536 | .valtype1 = typeToValtype(ty, pt, func.target.*), | |
| 2526 | 2537 | .width = abi_size * 8, |
| 2527 | 2538 | .op = .load, |
| 2528 | 2539 | .signedness = if (ty.isSignedInt(mod)) .signed else .unsigned, |
| ... | ... | @@ -2544,7 +2555,7 @@ fn airArg(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 2544 | 2555 | const mod = pt.zcu; |
| 2545 | 2556 | const arg_index = func.arg_index; |
| 2546 | 2557 | const arg = func.args[arg_index]; |
| 2547 | const cc = mod.typeToFunc(func.decl.typeOf(mod)).?.cc; | |
| 2558 | const cc = mod.typeToFunc(mod.navValue(func.owner_nav).typeOf(mod)).?.cc; | |
| 2548 | 2559 | const arg_ty = func.typeOfIndex(inst); |
| 2549 | 2560 | if (cc == .C) { |
| 2550 | 2561 | const arg_classes = abi.classifyType(arg_ty, pt); |
| ... | ... | @@ -2577,7 +2588,7 @@ fn airArg(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 2577 | 2588 | const name_nts = func.air.instructions.items(.data)[@intFromEnum(inst)].arg.name; |
| 2578 | 2589 | if (name_nts != .none) { |
| 2579 | 2590 | const name = func.air.nullTerminatedString(@intFromEnum(name_nts)); |
| 2580 | try dwarf.genArgDbgInfo(name, arg_ty, mod.funcOwnerDeclIndex(func.func_index), .{ | |
| 2591 | try dwarf.genArgDbgInfo(name, arg_ty, func.owner_nav, .{ | |
| 2581 | 2592 | .wasm_local = arg.local.value, |
| 2582 | 2593 | }); |
| 2583 | 2594 | } |
| ... | ... | @@ -2631,7 +2642,7 @@ fn binOp(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, op: Op) InnerError! |
| 2631 | 2642 | return func.floatOp(float_op, ty, &.{ lhs, rhs }); |
| 2632 | 2643 | } |
| 2633 | 2644 | |
| 2634 | if (isByRef(ty, pt)) { | |
| 2645 | if (isByRef(ty, pt, func.target.*)) { | |
| 2635 | 2646 | if (ty.zigTypeTag(mod) == .Int) { |
| 2636 | 2647 | return func.binOpBigInt(lhs, rhs, ty, op); |
| 2637 | 2648 | } else { |
| ... | ... | @@ -2644,7 +2655,7 @@ fn binOp(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, op: Op) InnerError! |
| 2644 | 2655 | |
| 2645 | 2656 | const opcode: wasm.Opcode = buildOpcode(.{ |
| 2646 | 2657 | .op = op, |
| 2647 | .valtype1 = typeToValtype(ty, pt), | |
| 2658 | .valtype1 = typeToValtype(ty, pt, func.target.*), | |
| 2648 | 2659 | .signedness = if (ty.isSignedInt(mod)) .signed else .unsigned, |
| 2649 | 2660 | }); |
| 2650 | 2661 | try func.emitWValue(lhs); |
| ... | ... | @@ -2896,7 +2907,7 @@ fn floatOp(func: *CodeGen, float_op: FloatOp, ty: Type, args: []const WValue) In |
| 2896 | 2907 | return func.fail("TODO: Implement floatOps for vectors", .{}); |
| 2897 | 2908 | } |
| 2898 | 2909 | |
| 2899 | const float_bits = ty.floatBits(func.target); | |
| 2910 | const float_bits = ty.floatBits(func.target.*); | |
| 2900 | 2911 | |
| 2901 | 2912 | if (float_op == .neg) { |
| 2902 | 2913 | return func.floatNeg(ty, args[0]); |
| ... | ... | @@ -2907,7 +2918,7 @@ fn floatOp(func: *CodeGen, float_op: FloatOp, ty: Type, args: []const WValue) In |
| 2907 | 2918 | for (args) |operand| { |
| 2908 | 2919 | try func.emitWValue(operand); |
| 2909 | 2920 | } |
| 2910 | const opcode = buildOpcode(.{ .op = op, .valtype1 = typeToValtype(ty, pt) }); | |
| 2921 | const opcode = buildOpcode(.{ .op = op, .valtype1 = typeToValtype(ty, pt, func.target.*) }); | |
| 2911 | 2922 | try func.addTag(Mir.Inst.Tag.fromOpcode(opcode)); |
| 2912 | 2923 | return .stack; |
| 2913 | 2924 | } |
| ... | ... | @@ -2955,7 +2966,7 @@ fn floatOp(func: *CodeGen, float_op: FloatOp, ty: Type, args: []const WValue) In |
| 2955 | 2966 | |
| 2956 | 2967 | /// NOTE: The result value remains on top of the stack. |
| 2957 | 2968 | fn floatNeg(func: *CodeGen, ty: Type, arg: WValue) InnerError!WValue { |
| 2958 | const float_bits = ty.floatBits(func.target); | |
| 2969 | const float_bits = ty.floatBits(func.target.*); | |
| 2959 | 2970 | switch (float_bits) { |
| 2960 | 2971 | 16 => { |
| 2961 | 2972 | try func.emitWValue(arg); |
| ... | ... | @@ -3115,8 +3126,8 @@ fn lowerPtr(func: *CodeGen, ptr_val: InternPool.Index, prev_offset: u64) InnerEr |
| 3115 | 3126 | const ptr = zcu.intern_pool.indexToKey(ptr_val).ptr; |
| 3116 | 3127 | const offset: u64 = prev_offset + ptr.byte_offset; |
| 3117 | 3128 | return switch (ptr.base_addr) { |
| 3118 | .decl => |decl| return func.lowerDeclRefValue(decl, @intCast(offset)), | |
| 3119 | .anon_decl => |ad| return func.lowerAnonDeclRef(ad, @intCast(offset)), | |
| 3129 | .nav => |nav| return func.lowerNavRef(nav, @intCast(offset)), | |
| 3130 | .uav => |uav| return func.lowerUavRef(uav, @intCast(offset)), | |
| 3120 | 3131 | .int => return func.lowerConstant(try pt.intValue(Type.usize, offset), Type.usize), |
| 3121 | 3132 | .eu_payload => return func.fail("Wasm TODO: lower error union payload pointer", .{}), |
| 3122 | 3133 | .opt_payload => |opt_ptr| return func.lowerPtr(opt_ptr, offset), |
| ... | ... | @@ -3128,7 +3139,7 @@ fn lowerPtr(func: *CodeGen, ptr_val: InternPool.Index, prev_offset: u64) InnerEr |
| 3128 | 3139 | assert(base_ty.isSlice(zcu)); |
| 3129 | 3140 | break :off switch (field.index) { |
| 3130 | 3141 | Value.slice_ptr_index => 0, |
| 3131 | Value.slice_len_index => @divExact(zcu.getTarget().ptrBitWidth(), 8), | |
| 3142 | Value.slice_len_index => @divExact(func.target.ptrBitWidth(), 8), | |
| 3132 | 3143 | else => unreachable, |
| 3133 | 3144 | }; |
| 3134 | 3145 | }, |
| ... | ... | @@ -3160,32 +3171,29 @@ fn lowerPtr(func: *CodeGen, ptr_val: InternPool.Index, prev_offset: u64) InnerEr |
| 3160 | 3171 | }; |
| 3161 | 3172 | } |
| 3162 | 3173 | |
| 3163 | fn lowerAnonDeclRef( | |
| 3174 | fn lowerUavRef( | |
| 3164 | 3175 | func: *CodeGen, |
| 3165 | anon_decl: InternPool.Key.Ptr.BaseAddr.AnonDecl, | |
| 3176 | uav: InternPool.Key.Ptr.BaseAddr.Uav, | |
| 3166 | 3177 | offset: u32, |
| 3167 | 3178 | ) InnerError!WValue { |
| 3168 | 3179 | const pt = func.pt; |
| 3169 | 3180 | const mod = pt.zcu; |
| 3170 | const decl_val = anon_decl.val; | |
| 3171 | const ty = Type.fromInterned(mod.intern_pool.typeOf(decl_val)); | |
| 3181 | const ty = Type.fromInterned(mod.intern_pool.typeOf(uav.val)); | |
| 3172 | 3182 | |
| 3173 | 3183 | const is_fn_body = ty.zigTypeTag(mod) == .Fn; |
| 3174 | 3184 | if (!is_fn_body and !ty.hasRuntimeBitsIgnoreComptime(pt)) { |
| 3175 | 3185 | return .{ .imm32 = 0xaaaaaaaa }; |
| 3176 | 3186 | } |
| 3177 | 3187 | |
| 3178 | const decl_align = mod.intern_pool.indexToKey(anon_decl.orig_ty).ptr_type.flags.alignment; | |
| 3179 | const res = try func.bin_file.lowerAnonDecl(pt, decl_val, decl_align, func.decl.navSrcLoc(mod)); | |
| 3180 | switch (res) { | |
| 3181 | .ok => {}, | |
| 3182 | .fail => |em| { | |
| 3183 | func.err_msg = em; | |
| 3188 | const decl_align = mod.intern_pool.indexToKey(uav.orig_ty).ptr_type.flags.alignment; | |
| 3189 | const res = try func.bin_file.lowerUav(pt, uav.val, decl_align, func.src_loc); | |
| 3190 | const target_sym_index = switch (res) { | |
| 3191 | .mcv => |mcv| mcv.load_symbol, | |
| 3192 | .fail => |err_msg| { | |
| 3193 | func.err_msg = err_msg; | |
| 3184 | 3194 | return error.CodegenFail; |
| 3185 | 3195 | }, |
| 3186 | } | |
| 3187 | const target_atom_index = func.bin_file.zigObjectPtr().?.anon_decls.get(decl_val).?; | |
| 3188 | const target_sym_index = @intFromEnum(func.bin_file.getAtom(target_atom_index).sym_index); | |
| 3196 | }; | |
| 3189 | 3197 | if (is_fn_body) { |
| 3190 | 3198 | return .{ .function_index = target_sym_index }; |
| 3191 | 3199 | } else if (offset == 0) { |
| ... | ... | @@ -3193,32 +3201,29 @@ fn lowerAnonDeclRef( |
| 3193 | 3201 | } else return .{ .memory_offset = .{ .pointer = target_sym_index, .offset = offset } }; |
| 3194 | 3202 | } |
| 3195 | 3203 | |
| 3196 | fn lowerDeclRefValue(func: *CodeGen, decl_index: InternPool.DeclIndex, offset: u32) InnerError!WValue { | |
| 3204 | fn lowerNavRef(func: *CodeGen, nav_index: InternPool.Nav.Index, offset: u32) InnerError!WValue { | |
| 3197 | 3205 | const pt = func.pt; |
| 3198 | 3206 | const mod = pt.zcu; |
| 3207 | const ip = &mod.intern_pool; | |
| 3199 | 3208 | |
| 3200 | const decl = mod.declPtr(decl_index); | |
| 3201 | 3209 | // check if decl is an alias to a function, in which case we |
| 3202 | 3210 | // want to lower the actual decl, rather than the alias itself. |
| 3203 | if (decl.val.getFunction(mod)) |func_val| { | |
| 3204 | if (func_val.owner_decl != decl_index) { | |
| 3205 | return func.lowerDeclRefValue(func_val.owner_decl, offset); | |
| 3206 | } | |
| 3207 | } else if (decl.val.getExternFunc(mod)) |func_val| { | |
| 3208 | if (func_val.decl != decl_index) { | |
| 3209 | return func.lowerDeclRefValue(func_val.decl, offset); | |
| 3210 | } | |
| 3211 | } | |
| 3212 | const decl_ty = decl.typeOf(mod); | |
| 3213 | if (decl_ty.zigTypeTag(mod) != .Fn and !decl_ty.hasRuntimeBitsIgnoreComptime(pt)) { | |
| 3211 | const owner_nav = switch (ip.indexToKey(mod.navValue(nav_index).toIntern())) { | |
| 3212 | .func => |function| function.owner_nav, | |
| 3213 | .variable => |variable| variable.owner_nav, | |
| 3214 | .@"extern" => |@"extern"| @"extern".owner_nav, | |
| 3215 | else => nav_index, | |
| 3216 | }; | |
| 3217 | const nav_ty = ip.getNav(owner_nav).typeOf(ip); | |
| 3218 | if (!ip.isFunctionType(nav_ty) and !Type.fromInterned(nav_ty).hasRuntimeBitsIgnoreComptime(pt)) { | |
| 3214 | 3219 | return .{ .imm32 = 0xaaaaaaaa }; |
| 3215 | 3220 | } |
| 3216 | 3221 | |
| 3217 | const atom_index = try func.bin_file.getOrCreateAtomForDecl(pt, decl_index); | |
| 3222 | const atom_index = try func.bin_file.getOrCreateAtomForNav(pt, nav_index); | |
| 3218 | 3223 | const atom = func.bin_file.getAtom(atom_index); |
| 3219 | 3224 | |
| 3220 | 3225 | const target_sym_index = @intFromEnum(atom.sym_index); |
| 3221 | if (decl_ty.zigTypeTag(mod) == .Fn) { | |
| 3226 | if (ip.isFunctionType(nav_ty)) { | |
| 3222 | 3227 | return .{ .function_index = target_sym_index }; |
| 3223 | 3228 | } else if (offset == 0) { |
| 3224 | 3229 | return .{ .memory = target_sym_index }; |
| ... | ... | @@ -3229,7 +3234,7 @@ fn lowerDeclRefValue(func: *CodeGen, decl_index: InternPool.DeclIndex, offset: u |
| 3229 | 3234 | fn lowerConstant(func: *CodeGen, val: Value, ty: Type) InnerError!WValue { |
| 3230 | 3235 | const pt = func.pt; |
| 3231 | 3236 | const mod = pt.zcu; |
| 3232 | assert(!isByRef(ty, pt)); | |
| 3237 | assert(!isByRef(ty, pt, func.target.*)); | |
| 3233 | 3238 | const ip = &mod.intern_pool; |
| 3234 | 3239 | if (val.isUndefDeep(mod)) return func.emitUndefined(ty); |
| 3235 | 3240 | |
| ... | ... | @@ -3268,7 +3273,7 @@ fn lowerConstant(func: *CodeGen, val: Value, ty: Type) InnerError!WValue { |
| 3268 | 3273 | } }, |
| 3269 | 3274 | }, |
| 3270 | 3275 | .variable, |
| 3271 | .extern_func, | |
| 3276 | .@"extern", | |
| 3272 | 3277 | .func, |
| 3273 | 3278 | .enum_literal, |
| 3274 | 3279 | .empty_enum_value, |
| ... | ... | @@ -3325,16 +3330,12 @@ fn lowerConstant(func: *CodeGen, val: Value, ty: Type) InnerError!WValue { |
| 3325 | 3330 | .f64 => |f64_val| return .{ .float64 = f64_val }, |
| 3326 | 3331 | else => unreachable, |
| 3327 | 3332 | }, |
| 3328 | .slice => |slice| { | |
| 3329 | var ptr = ip.indexToKey(slice.ptr).ptr; | |
| 3330 | const owner_decl = while (true) switch (ptr.base_addr) { | |
| 3331 | .decl => |decl| break decl, | |
| 3332 | .int, .anon_decl => return func.fail("Wasm TODO: lower slice where ptr is not owned by decl", .{}), | |
| 3333 | .opt_payload, .eu_payload => |base| ptr = ip.indexToKey(base).ptr, | |
| 3334 | .field => |base_index| ptr = ip.indexToKey(base_index.base).ptr, | |
| 3335 | .arr_elem, .comptime_field, .comptime_alloc => unreachable, | |
| 3336 | }; | |
| 3337 | return .{ .memory = try func.bin_file.lowerUnnamedConst(pt, val, owner_decl) }; | |
| 3333 | .slice => switch (try func.bin_file.lowerUav(pt, val.toIntern(), .none, func.src_loc)) { | |
| 3334 | .mcv => |mcv| return .{ .memory = mcv.load_symbol }, | |
| 3335 | .fail => |err_msg| { | |
| 3336 | func.err_msg = err_msg; | |
| 3337 | return error.CodegenFail; | |
| 3338 | }, | |
| 3338 | 3339 | }, |
| 3339 | 3340 | .ptr => return func.lowerPtr(val.toIntern(), 0), |
| 3340 | 3341 | .opt => if (ty.optionalReprIsPayload(mod)) { |
| ... | ... | @@ -3350,7 +3351,7 @@ fn lowerConstant(func: *CodeGen, val: Value, ty: Type) InnerError!WValue { |
| 3350 | 3351 | .aggregate => switch (ip.indexToKey(ty.ip_index)) { |
| 3351 | 3352 | .array_type => return func.fail("Wasm TODO: LowerConstant for {}", .{ty.fmt(pt)}), |
| 3352 | 3353 | .vector_type => { |
| 3353 | assert(determineSimdStoreStrategy(ty, pt) == .direct); | |
| 3354 | assert(determineSimdStoreStrategy(ty, pt, func.target.*) == .direct); | |
| 3354 | 3355 | var buf: [16]u8 = undefined; |
| 3355 | 3356 | val.writeToMemory(ty, pt, &buf) catch unreachable; |
| 3356 | 3357 | return func.storeSimdImmd(buf); |
| ... | ... | @@ -3405,7 +3406,7 @@ fn emitUndefined(func: *CodeGen, ty: Type) InnerError!WValue { |
| 3405 | 3406 | 33...64 => return .{ .imm64 = 0xaaaaaaaaaaaaaaaa }, |
| 3406 | 3407 | else => unreachable, |
| 3407 | 3408 | }, |
| 3408 | .Float => switch (ty.floatBits(func.target)) { | |
| 3409 | .Float => switch (ty.floatBits(func.target.*)) { | |
| 3409 | 3410 | 16 => return .{ .imm32 = 0xaaaaaaaa }, |
| 3410 | 3411 | 32 => return .{ .float32 = @as(f32, @bitCast(@as(u32, 0xaaaaaaaa))) }, |
| 3411 | 3412 | 64 => return .{ .float64 = @as(f64, @bitCast(@as(u64, 0xaaaaaaaaaaaaaaaa))) }, |
| ... | ... | @@ -3480,11 +3481,11 @@ fn airBlock(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 3480 | 3481 | |
| 3481 | 3482 | fn lowerBlock(func: *CodeGen, inst: Air.Inst.Index, block_ty: Type, body: []const Air.Inst.Index) InnerError!void { |
| 3482 | 3483 | const pt = func.pt; |
| 3483 | const wasm_block_ty = genBlockType(block_ty, pt); | |
| 3484 | const wasm_block_ty = genBlockType(block_ty, pt, func.target.*); | |
| 3484 | 3485 | |
| 3485 | 3486 | // if wasm_block_ty is non-empty, we create a register to store the temporary value |
| 3486 | 3487 | const block_result: WValue = if (wasm_block_ty != wasm.block_empty) blk: { |
| 3487 | const ty: Type = if (isByRef(block_ty, pt)) Type.u32 else block_ty; | |
| 3488 | const ty: Type = if (isByRef(block_ty, pt, func.target.*)) Type.u32 else block_ty; | |
| 3488 | 3489 | break :blk try func.ensureAllocLocal(ty); // make sure it's a clean local as it may never get overwritten |
| 3489 | 3490 | } else .none; |
| 3490 | 3491 | |
| ... | ... | @@ -3608,7 +3609,7 @@ fn cmp(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, op: std.math.CompareO |
| 3608 | 3609 | } |
| 3609 | 3610 | } else if (ty.isAnyFloat()) { |
| 3610 | 3611 | return func.cmpFloat(ty, lhs, rhs, op); |
| 3611 | } else if (isByRef(ty, pt)) { | |
| 3612 | } else if (isByRef(ty, pt, func.target.*)) { | |
| 3612 | 3613 | return func.cmpBigInt(lhs, rhs, ty, op); |
| 3613 | 3614 | } |
| 3614 | 3615 | |
| ... | ... | @@ -3626,7 +3627,7 @@ fn cmp(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, op: std.math.CompareO |
| 3626 | 3627 | try func.lowerToStack(rhs); |
| 3627 | 3628 | |
| 3628 | 3629 | const opcode: wasm.Opcode = buildOpcode(.{ |
| 3629 | .valtype1 = typeToValtype(ty, pt), | |
| 3630 | .valtype1 = typeToValtype(ty, pt, func.target.*), | |
| 3630 | 3631 | .op = switch (op) { |
| 3631 | 3632 | .lt => .lt, |
| 3632 | 3633 | .lte => .le, |
| ... | ... | @@ -3645,7 +3646,7 @@ fn cmp(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, op: std.math.CompareO |
| 3645 | 3646 | /// Compares two floats. |
| 3646 | 3647 | /// NOTE: Leaves the result of the comparison on top of the stack. |
| 3647 | 3648 | fn cmpFloat(func: *CodeGen, ty: Type, lhs: WValue, rhs: WValue, cmp_op: std.math.CompareOperator) InnerError!WValue { |
| 3648 | const float_bits = ty.floatBits(func.target); | |
| 3649 | const float_bits = ty.floatBits(func.target.*); | |
| 3649 | 3650 | |
| 3650 | 3651 | const op: Op = switch (cmp_op) { |
| 3651 | 3652 | .lt => .lt, |
| ... | ... | @@ -3829,7 +3830,7 @@ fn airBitcast(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 3829 | 3830 | break :result try func.bitcast(wanted_ty, given_ty, operand); |
| 3830 | 3831 | } |
| 3831 | 3832 | |
| 3832 | if (isByRef(given_ty, pt) and !isByRef(wanted_ty, pt)) { | |
| 3833 | if (isByRef(given_ty, pt, func.target.*) and !isByRef(wanted_ty, pt, func.target.*)) { | |
| 3833 | 3834 | const loaded_memory = try func.load(operand, wanted_ty, 0); |
| 3834 | 3835 | if (needs_wrapping) { |
| 3835 | 3836 | break :result try func.wrapOperand(loaded_memory, wanted_ty); |
| ... | ... | @@ -3837,7 +3838,7 @@ fn airBitcast(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 3837 | 3838 | break :result loaded_memory; |
| 3838 | 3839 | } |
| 3839 | 3840 | } |
| 3840 | if (!isByRef(given_ty, pt) and isByRef(wanted_ty, pt)) { | |
| 3841 | if (!isByRef(given_ty, pt, func.target.*) and isByRef(wanted_ty, pt, func.target.*)) { | |
| 3841 | 3842 | const stack_memory = try func.allocStack(wanted_ty); |
| 3842 | 3843 | try func.store(stack_memory, operand, given_ty, 0); |
| 3843 | 3844 | if (needs_wrapping) { |
| ... | ... | @@ -3867,8 +3868,8 @@ fn bitcast(func: *CodeGen, wanted_ty: Type, given_ty: Type, operand: WValue) Inn |
| 3867 | 3868 | |
| 3868 | 3869 | const opcode = buildOpcode(.{ |
| 3869 | 3870 | .op = .reinterpret, |
| 3870 | .valtype1 = typeToValtype(wanted_ty, pt), | |
| 3871 | .valtype2 = typeToValtype(given_ty, pt), | |
| 3871 | .valtype1 = typeToValtype(wanted_ty, pt, func.target.*), | |
| 3872 | .valtype2 = typeToValtype(given_ty, pt, func.target.*), | |
| 3872 | 3873 | }); |
| 3873 | 3874 | try func.emitWValue(operand); |
| 3874 | 3875 | try func.addTag(Mir.Inst.Tag.fromOpcode(opcode)); |
| ... | ... | @@ -3990,8 +3991,8 @@ fn airStructFieldVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 3990 | 3991 | break :result try func.trunc(shifted_value, field_ty, backing_ty); |
| 3991 | 3992 | }, |
| 3992 | 3993 | .Union => result: { |
| 3993 | if (isByRef(struct_ty, pt)) { | |
| 3994 | if (!isByRef(field_ty, pt)) { | |
| 3994 | if (isByRef(struct_ty, pt, func.target.*)) { | |
| 3995 | if (!isByRef(field_ty, pt, func.target.*)) { | |
| 3995 | 3996 | break :result try func.load(operand, field_ty, 0); |
| 3996 | 3997 | } else { |
| 3997 | 3998 | const new_stack_val = try func.allocStack(field_ty); |
| ... | ... | @@ -4017,7 +4018,7 @@ fn airStructFieldVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 4017 | 4018 | const offset = std.math.cast(u32, struct_ty.structFieldOffset(field_index, pt)) orelse { |
| 4018 | 4019 | return func.fail("Field type '{}' too big to fit into stack frame", .{field_ty.fmt(pt)}); |
| 4019 | 4020 | }; |
| 4020 | if (isByRef(field_ty, pt)) { | |
| 4021 | if (isByRef(field_ty, pt, func.target.*)) { | |
| 4021 | 4022 | switch (operand) { |
| 4022 | 4023 | .stack_offset => |stack_offset| { |
| 4023 | 4024 | break :result .{ .stack_offset = .{ .value = stack_offset.value + offset, .references = 1 } }; |
| ... | ... | @@ -4163,7 +4164,7 @@ fn airSwitchBr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 4163 | 4164 | const val = try func.lowerConstant(case.values[0].value, target_ty); |
| 4164 | 4165 | try func.emitWValue(val); |
| 4165 | 4166 | const opcode = buildOpcode(.{ |
| 4166 | .valtype1 = typeToValtype(target_ty, pt), | |
| 4167 | .valtype1 = typeToValtype(target_ty, pt, func.target.*), | |
| 4167 | 4168 | .op = .ne, // not equal, because we want to jump out of this block if it does not match the condition. |
| 4168 | 4169 | .signedness = signedness, |
| 4169 | 4170 | }); |
| ... | ... | @@ -4177,7 +4178,7 @@ fn airSwitchBr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 4177 | 4178 | const val = try func.lowerConstant(value.value, target_ty); |
| 4178 | 4179 | try func.emitWValue(val); |
| 4179 | 4180 | const opcode = buildOpcode(.{ |
| 4180 | .valtype1 = typeToValtype(target_ty, pt), | |
| 4181 | .valtype1 = typeToValtype(target_ty, pt, func.target.*), | |
| 4181 | 4182 | .op = .eq, |
| 4182 | 4183 | .signedness = signedness, |
| 4183 | 4184 | }); |
| ... | ... | @@ -4265,7 +4266,7 @@ fn airUnwrapErrUnionPayload(func: *CodeGen, inst: Air.Inst.Index, op_is_ptr: boo |
| 4265 | 4266 | } |
| 4266 | 4267 | |
| 4267 | 4268 | const pl_offset = @as(u32, @intCast(errUnionPayloadOffset(payload_ty, pt))); |
| 4268 | if (op_is_ptr or isByRef(payload_ty, pt)) { | |
| 4269 | if (op_is_ptr or isByRef(payload_ty, pt, func.target.*)) { | |
| 4269 | 4270 | break :result try func.buildPointerOffset(operand, pl_offset, .new); |
| 4270 | 4271 | } |
| 4271 | 4272 | |
| ... | ... | @@ -4492,7 +4493,7 @@ fn airOptionalPayload(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 4492 | 4493 | const operand = try func.resolveInst(ty_op.operand); |
| 4493 | 4494 | if (opt_ty.optionalReprIsPayload(mod)) break :result func.reuseOperand(ty_op.operand, operand); |
| 4494 | 4495 | |
| 4495 | if (isByRef(payload_ty, pt)) { | |
| 4496 | if (isByRef(payload_ty, pt, func.target.*)) { | |
| 4496 | 4497 | break :result try func.buildPointerOffset(operand, 0, .new); |
| 4497 | 4498 | } |
| 4498 | 4499 | |
| ... | ... | @@ -4626,7 +4627,7 @@ fn airSliceElemVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 4626 | 4627 | try func.addTag(.i32_mul); |
| 4627 | 4628 | try func.addTag(.i32_add); |
| 4628 | 4629 | |
| 4629 | const elem_result = if (isByRef(elem_ty, pt)) | |
| 4630 | const elem_result = if (isByRef(elem_ty, pt, func.target.*)) | |
| 4630 | 4631 | .stack |
| 4631 | 4632 | else |
| 4632 | 4633 | try func.load(.stack, elem_ty, 0); |
| ... | ... | @@ -4784,7 +4785,7 @@ fn airPtrElemVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 4784 | 4785 | try func.addTag(.i32_mul); |
| 4785 | 4786 | try func.addTag(.i32_add); |
| 4786 | 4787 | |
| 4787 | const elem_result = if (isByRef(elem_ty, pt)) | |
| 4788 | const elem_result = if (isByRef(elem_ty, pt, func.target.*)) | |
| 4788 | 4789 | .stack |
| 4789 | 4790 | else |
| 4790 | 4791 | try func.load(.stack, elem_ty, 0); |
| ... | ... | @@ -4835,7 +4836,7 @@ fn airPtrBinOp(func: *CodeGen, inst: Air.Inst.Index, op: Op) InnerError!void { |
| 4835 | 4836 | else => ptr_ty.childType(mod), |
| 4836 | 4837 | }; |
| 4837 | 4838 | |
| 4838 | const valtype = typeToValtype(Type.usize, pt); | |
| 4839 | const valtype = typeToValtype(Type.usize, pt, func.target.*); | |
| 4839 | 4840 | const mul_opcode = buildOpcode(.{ .valtype1 = valtype, .op = .mul }); |
| 4840 | 4841 | const bin_opcode = buildOpcode(.{ .valtype1 = valtype, .op = op }); |
| 4841 | 4842 | |
| ... | ... | @@ -4982,7 +4983,7 @@ fn airArrayElemVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 4982 | 4983 | const elem_ty = array_ty.childType(mod); |
| 4983 | 4984 | const elem_size = elem_ty.abiSize(pt); |
| 4984 | 4985 | |
| 4985 | if (isByRef(array_ty, pt)) { | |
| 4986 | if (isByRef(array_ty, pt, func.target.*)) { | |
| 4986 | 4987 | try func.lowerToStack(array); |
| 4987 | 4988 | try func.emitWValue(index); |
| 4988 | 4989 | try func.addImm32(@intCast(elem_size)); |
| ... | ... | @@ -5025,7 +5026,7 @@ fn airArrayElemVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 5025 | 5026 | } |
| 5026 | 5027 | } |
| 5027 | 5028 | |
| 5028 | const elem_result = if (isByRef(elem_ty, pt)) | |
| 5029 | const elem_result = if (isByRef(elem_ty, pt, func.target.*)) | |
| 5029 | 5030 | .stack |
| 5030 | 5031 | else |
| 5031 | 5032 | try func.load(.stack, elem_ty, 0); |
| ... | ... | @@ -5040,7 +5041,7 @@ fn airIntFromFloat(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 5040 | 5041 | |
| 5041 | 5042 | const operand = try func.resolveInst(ty_op.operand); |
| 5042 | 5043 | const op_ty = func.typeOf(ty_op.operand); |
| 5043 | const op_bits = op_ty.floatBits(func.target); | |
| 5044 | const op_bits = op_ty.floatBits(func.target.*); | |
| 5044 | 5045 | |
| 5045 | 5046 | const dest_ty = func.typeOfIndex(inst); |
| 5046 | 5047 | const dest_info = dest_ty.intInfo(mod); |
| ... | ... | @@ -5069,8 +5070,8 @@ fn airIntFromFloat(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 5069 | 5070 | try func.emitWValue(operand); |
| 5070 | 5071 | const op = buildOpcode(.{ |
| 5071 | 5072 | .op = .trunc, |
| 5072 | .valtype1 = typeToValtype(dest_ty, pt), | |
| 5073 | .valtype2 = typeToValtype(op_ty, pt), | |
| 5073 | .valtype1 = typeToValtype(dest_ty, pt, func.target.*), | |
| 5074 | .valtype2 = typeToValtype(op_ty, pt, func.target.*), | |
| 5074 | 5075 | .signedness = dest_info.signedness, |
| 5075 | 5076 | }); |
| 5076 | 5077 | try func.addTag(Mir.Inst.Tag.fromOpcode(op)); |
| ... | ... | @@ -5088,7 +5089,7 @@ fn airFloatFromInt(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 5088 | 5089 | const op_info = op_ty.intInfo(mod); |
| 5089 | 5090 | |
| 5090 | 5091 | const dest_ty = func.typeOfIndex(inst); |
| 5091 | const dest_bits = dest_ty.floatBits(func.target); | |
| 5092 | const dest_bits = dest_ty.floatBits(func.target.*); | |
| 5092 | 5093 | |
| 5093 | 5094 | if (op_info.bits > 128) { |
| 5094 | 5095 | return func.fail("TODO: floatFromInt for integers/floats with bitsize {d} bits", .{op_info.bits}); |
| ... | ... | @@ -5114,8 +5115,8 @@ fn airFloatFromInt(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 5114 | 5115 | try func.emitWValue(operand); |
| 5115 | 5116 | const op = buildOpcode(.{ |
| 5116 | 5117 | .op = .convert, |
| 5117 | .valtype1 = typeToValtype(dest_ty, pt), | |
| 5118 | .valtype2 = typeToValtype(op_ty, pt), | |
| 5118 | .valtype1 = typeToValtype(dest_ty, pt, func.target.*), | |
| 5119 | .valtype2 = typeToValtype(op_ty, pt, func.target.*), | |
| 5119 | 5120 | .signedness = op_info.signedness, |
| 5120 | 5121 | }); |
| 5121 | 5122 | try func.addTag(Mir.Inst.Tag.fromOpcode(op)); |
| ... | ... | @@ -5131,7 +5132,7 @@ fn airSplat(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 5131 | 5132 | const ty = func.typeOfIndex(inst); |
| 5132 | 5133 | const elem_ty = ty.childType(mod); |
| 5133 | 5134 | |
| 5134 | if (determineSimdStoreStrategy(ty, pt) == .direct) blk: { | |
| 5135 | if (determineSimdStoreStrategy(ty, pt, func.target.*) == .direct) blk: { | |
| 5135 | 5136 | switch (operand) { |
| 5136 | 5137 | // when the operand lives in the linear memory section, we can directly |
| 5137 | 5138 | // load and splat the value at once. Meaning we do not first have to load |
| ... | ... | @@ -5215,7 +5216,7 @@ fn airShuffle(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 5215 | 5216 | const elem_size = child_ty.abiSize(pt); |
| 5216 | 5217 | |
| 5217 | 5218 | // TODO: One of them could be by ref; handle in loop |
| 5218 | if (isByRef(func.typeOf(extra.a), pt) or isByRef(inst_ty, pt)) { | |
| 5219 | if (isByRef(func.typeOf(extra.a), pt, func.target.*) or isByRef(inst_ty, pt, func.target.*)) { | |
| 5219 | 5220 | const result = try func.allocStack(inst_ty); |
| 5220 | 5221 | |
| 5221 | 5222 | for (0..mask_len) |index| { |
| ... | ... | @@ -5291,7 +5292,7 @@ fn airAggregateInit(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 5291 | 5292 | // When the element type is by reference, we must copy the entire |
| 5292 | 5293 | // value. It is therefore safer to move the offset pointer and store |
| 5293 | 5294 | // each value individually, instead of using store offsets. |
| 5294 | if (isByRef(elem_ty, pt)) { | |
| 5295 | if (isByRef(elem_ty, pt, func.target.*)) { | |
| 5295 | 5296 | // copy stack pointer into a temporary local, which is |
| 5296 | 5297 | // moved for each element to store each value in the right position. |
| 5297 | 5298 | const offset = try func.buildPointerOffset(result, 0, .new); |
| ... | ... | @@ -5321,7 +5322,7 @@ fn airAggregateInit(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 5321 | 5322 | }, |
| 5322 | 5323 | .Struct => switch (result_ty.containerLayout(mod)) { |
| 5323 | 5324 | .@"packed" => { |
| 5324 | if (isByRef(result_ty, pt)) { | |
| 5325 | if (isByRef(result_ty, pt, func.target.*)) { | |
| 5325 | 5326 | return func.fail("TODO: airAggregateInit for packed structs larger than 64 bits", .{}); |
| 5326 | 5327 | } |
| 5327 | 5328 | const packed_struct = mod.typeToPackedStruct(result_ty).?; |
| ... | ... | @@ -5424,15 +5425,15 @@ fn airUnionInit(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 5424 | 5425 | if (layout.tag_size == 0) { |
| 5425 | 5426 | break :result .none; |
| 5426 | 5427 | } |
| 5427 | assert(!isByRef(union_ty, pt)); | |
| 5428 | assert(!isByRef(union_ty, pt, func.target.*)); | |
| 5428 | 5429 | break :result tag_int; |
| 5429 | 5430 | } |
| 5430 | 5431 | |
| 5431 | if (isByRef(union_ty, pt)) { | |
| 5432 | if (isByRef(union_ty, pt, func.target.*)) { | |
| 5432 | 5433 | const result_ptr = try func.allocStack(union_ty); |
| 5433 | 5434 | const payload = try func.resolveInst(extra.init); |
| 5434 | 5435 | if (layout.tag_align.compare(.gte, layout.payload_align)) { |
| 5435 | if (isByRef(field_ty, pt)) { | |
| 5436 | if (isByRef(field_ty, pt, func.target.*)) { | |
| 5436 | 5437 | const payload_ptr = try func.buildPointerOffset(result_ptr, layout.tag_size, .new); |
| 5437 | 5438 | try func.store(payload_ptr, payload, field_ty, 0); |
| 5438 | 5439 | } else { |
| ... | ... | @@ -5513,7 +5514,7 @@ fn cmpOptionals(func: *CodeGen, lhs: WValue, rhs: WValue, operand_ty: Type, op: |
| 5513 | 5514 | |
| 5514 | 5515 | _ = try func.load(lhs, payload_ty, 0); |
| 5515 | 5516 | _ = try func.load(rhs, payload_ty, 0); |
| 5516 | const opcode = buildOpcode(.{ .op = .ne, .valtype1 = typeToValtype(payload_ty, pt) }); | |
| 5517 | const opcode = buildOpcode(.{ .op = .ne, .valtype1 = typeToValtype(payload_ty, pt, func.target.*) }); | |
| 5517 | 5518 | try func.addTag(Mir.Inst.Tag.fromOpcode(opcode)); |
| 5518 | 5519 | try func.addLabel(.br_if, 0); |
| 5519 | 5520 | |
| ... | ... | @@ -5630,8 +5631,8 @@ fn airFpext(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 5630 | 5631 | /// Extends a float from a given `Type` to a larger wanted `Type` |
| 5631 | 5632 | /// NOTE: Leaves the result on the stack |
| 5632 | 5633 | fn fpext(func: *CodeGen, operand: WValue, given: Type, wanted: Type) InnerError!WValue { |
| 5633 | const given_bits = given.floatBits(func.target); | |
| 5634 | const wanted_bits = wanted.floatBits(func.target); | |
| 5634 | const given_bits = given.floatBits(func.target.*); | |
| 5635 | const wanted_bits = wanted.floatBits(func.target.*); | |
| 5635 | 5636 | |
| 5636 | 5637 | if (wanted_bits == 64 and given_bits == 32) { |
| 5637 | 5638 | try func.emitWValue(operand); |
| ... | ... | @@ -5674,8 +5675,8 @@ fn airFptrunc(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 5674 | 5675 | /// Truncates a float from a given `Type` to its wanted `Type` |
| 5675 | 5676 | /// NOTE: The result value remains on the stack |
| 5676 | 5677 | fn fptrunc(func: *CodeGen, operand: WValue, given: Type, wanted: Type) InnerError!WValue { |
| 5677 | const given_bits = given.floatBits(func.target); | |
| 5678 | const wanted_bits = wanted.floatBits(func.target); | |
| 5678 | const given_bits = given.floatBits(func.target.*); | |
| 5679 | const wanted_bits = wanted.floatBits(func.target.*); | |
| 5679 | 5680 | |
| 5680 | 5681 | if (wanted_bits == 32 and given_bits == 64) { |
| 5681 | 5682 | try func.emitWValue(operand); |
| ... | ... | @@ -6247,7 +6248,6 @@ fn airMaxMin(func: *CodeGen, inst: Air.Inst.Index, op: Op) InnerError!void { |
| 6247 | 6248 | assert(op == .max or op == .min); |
| 6248 | 6249 | const pt = func.pt; |
| 6249 | 6250 | const mod = pt.zcu; |
| 6250 | const target = mod.getTarget(); | |
| 6251 | 6251 | const bin_op = func.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| 6252 | 6252 | |
| 6253 | 6253 | const ty = func.typeOfIndex(inst); |
| ... | ... | @@ -6264,7 +6264,7 @@ fn airMaxMin(func: *CodeGen, inst: Air.Inst.Index, op: Op) InnerError!void { |
| 6264 | 6264 | |
| 6265 | 6265 | if (ty.zigTypeTag(mod) == .Float) { |
| 6266 | 6266 | var fn_name_buf: [64]u8 = undefined; |
| 6267 | const float_bits = ty.floatBits(target); | |
| 6267 | const float_bits = ty.floatBits(func.target.*); | |
| 6268 | 6268 | const fn_name = std.fmt.bufPrint(&fn_name_buf, "{s}f{s}{s}", .{ |
| 6269 | 6269 | target_util.libcFloatPrefix(float_bits), |
| 6270 | 6270 | @tagName(op), |
| ... | ... | @@ -6300,7 +6300,7 @@ fn airMulAdd(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 6300 | 6300 | const lhs = try func.resolveInst(bin_op.lhs); |
| 6301 | 6301 | const rhs = try func.resolveInst(bin_op.rhs); |
| 6302 | 6302 | |
| 6303 | const result = if (ty.floatBits(func.target) == 16) fl_result: { | |
| 6303 | const result = if (ty.floatBits(func.target.*) == 16) fl_result: { | |
| 6304 | 6304 | const rhs_ext = try func.fpext(rhs, ty, Type.f32); |
| 6305 | 6305 | const lhs_ext = try func.fpext(lhs, ty, Type.f32); |
| 6306 | 6306 | const addend_ext = try func.fpext(addend, ty, Type.f32); |
| ... | ... | @@ -6457,8 +6457,6 @@ fn airDbgInlineBlock(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 6457 | 6457 | fn airDbgVar(func: *CodeGen, inst: Air.Inst.Index, is_ptr: bool) InnerError!void { |
| 6458 | 6458 | if (func.debug_output != .dwarf) return func.finishAir(inst, .none, &.{}); |
| 6459 | 6459 | |
| 6460 | const pt = func.pt; | |
| 6461 | const mod = pt.zcu; | |
| 6462 | 6460 | const pl_op = func.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; |
| 6463 | 6461 | const ty = func.typeOf(pl_op.operand); |
| 6464 | 6462 | const operand = try func.resolveInst(pl_op.operand); |
| ... | ... | @@ -6468,14 +6466,14 @@ fn airDbgVar(func: *CodeGen, inst: Air.Inst.Index, is_ptr: bool) InnerError!void |
| 6468 | 6466 | const name = func.air.nullTerminatedString(pl_op.payload); |
| 6469 | 6467 | log.debug(" var name = ({s})", .{name}); |
| 6470 | 6468 | |
| 6471 | const loc: link.File.Dwarf.DeclState.DbgInfoLoc = switch (operand) { | |
| 6469 | const loc: link.File.Dwarf.NavState.DbgInfoLoc = switch (operand) { | |
| 6472 | 6470 | .local => |local| .{ .wasm_local = local.value }, |
| 6473 | 6471 | else => blk: { |
| 6474 | 6472 | log.debug("TODO generate debug info for {}", .{operand}); |
| 6475 | 6473 | break :blk .nop; |
| 6476 | 6474 | }, |
| 6477 | 6475 | }; |
| 6478 | try func.debug_output.dwarf.genVarDbgInfo(name, ty, mod.funcOwnerDeclIndex(func.func_index), is_ptr, loc); | |
| 6476 | try func.debug_output.dwarf.genVarDbgInfo(name, ty, func.owner_nav, is_ptr, loc); | |
| 6479 | 6477 | |
| 6480 | 6478 | return func.finishAir(inst, .none, &.{}); |
| 6481 | 6479 | } |
| ... | ... | @@ -6552,7 +6550,7 @@ fn lowerTry( |
| 6552 | 6550 | } |
| 6553 | 6551 | |
| 6554 | 6552 | const pl_offset: u32 = @intCast(errUnionPayloadOffset(pl_ty, pt)); |
| 6555 | if (isByRef(pl_ty, pt)) { | |
| 6553 | if (isByRef(pl_ty, pt, func.target.*)) { | |
| 6556 | 6554 | return buildPointerOffset(func, err_union, pl_offset, .new); |
| 6557 | 6555 | } |
| 6558 | 6556 | const payload = try func.load(err_union, pl_ty, pl_offset); |
| ... | ... | @@ -6712,7 +6710,7 @@ fn airDivFloor(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 6712 | 6710 | _ = try func.wrapOperand(.stack, ty); |
| 6713 | 6711 | } |
| 6714 | 6712 | } else { |
| 6715 | const float_bits = ty.floatBits(func.target); | |
| 6713 | const float_bits = ty.floatBits(func.target.*); | |
| 6716 | 6714 | if (float_bits > 64) { |
| 6717 | 6715 | return func.fail("TODO: `@divFloor` for floats with bitsize: {d}", .{float_bits}); |
| 6718 | 6716 | } |
| ... | ... | @@ -7126,12 +7124,12 @@ fn callIntrinsic( |
| 7126 | 7124 | // Always pass over C-ABI |
| 7127 | 7125 | const pt = func.pt; |
| 7128 | 7126 | const mod = pt.zcu; |
| 7129 | var func_type = try genFunctype(func.gpa, .C, param_types, return_type, pt); | |
| 7127 | var func_type = try genFunctype(func.gpa, .C, param_types, return_type, pt, func.target.*); | |
| 7130 | 7128 | defer func_type.deinit(func.gpa); |
| 7131 | 7129 | const func_type_index = try func.bin_file.zigObjectPtr().?.putOrGetFuncType(func.gpa, func_type); |
| 7132 | 7130 | try func.bin_file.addOrUpdateImport(name, symbol_index, null, func_type_index); |
| 7133 | 7131 | |
| 7134 | const want_sret_param = firstParamSRet(.C, return_type, pt); | |
| 7132 | const want_sret_param = firstParamSRet(.C, return_type, pt, func.target.*); | |
| 7135 | 7133 | // if we want return as first param, we allocate a pointer to stack, |
| 7136 | 7134 | // and emit it as our first argument |
| 7137 | 7135 | const sret = if (want_sret_param) blk: { |
| ... | ... | @@ -7181,14 +7179,12 @@ fn getTagNameFunction(func: *CodeGen, enum_ty: Type) InnerError!u32 { |
| 7181 | 7179 | const pt = func.pt; |
| 7182 | 7180 | const mod = pt.zcu; |
| 7183 | 7181 | const ip = &mod.intern_pool; |
| 7184 | const enum_decl_index = enum_ty.getOwnerDecl(mod); | |
| 7185 | 7182 | |
| 7186 | 7183 | var arena_allocator = std.heap.ArenaAllocator.init(func.gpa); |
| 7187 | 7184 | defer arena_allocator.deinit(); |
| 7188 | 7185 | const arena = arena_allocator.allocator(); |
| 7189 | 7186 | |
| 7190 | const decl = mod.declPtr(enum_decl_index); | |
| 7191 | const func_name = try std.fmt.allocPrintZ(arena, "__zig_tag_name_{}", .{decl.fqn.fmt(ip)}); | |
| 7187 | const func_name = try std.fmt.allocPrintZ(arena, "__zig_tag_name_{}", .{ip.loadEnumType(enum_ty.toIntern()).name.fmt(ip)}); | |
| 7192 | 7188 | |
| 7193 | 7189 | // check if we already generated code for this. |
| 7194 | 7190 | if (func.bin_file.findGlobalSymbol(func_name)) |loc| { |
| ... | ... | @@ -7232,11 +7228,13 @@ fn getTagNameFunction(func: *CodeGen, enum_ty: Type) InnerError!u32 { |
| 7232 | 7228 | .ty = name_ty.toIntern(), |
| 7233 | 7229 | .storage = .{ .bytes = tag_name.toString() }, |
| 7234 | 7230 | } }); |
| 7235 | const tag_sym_index = try func.bin_file.lowerUnnamedConst( | |
| 7236 | pt, | |
| 7237 | Value.fromInterned(name_val), | |
| 7238 | enum_decl_index, | |
| 7239 | ); | |
| 7231 | const tag_sym_index = switch (try func.bin_file.lowerUav(pt, name_val, .none, func.src_loc)) { | |
| 7232 | .mcv => |mcv| mcv.load_symbol, | |
| 7233 | .fail => |err_msg| { | |
| 7234 | func.err_msg = err_msg; | |
| 7235 | return error.CodegenFail; | |
| 7236 | }, | |
| 7237 | }; | |
| 7240 | 7238 | |
| 7241 | 7239 | // block for this if case |
| 7242 | 7240 | try writer.writeByte(std.wasm.opcode(.block)); |
| ... | ... | @@ -7333,7 +7331,7 @@ fn getTagNameFunction(func: *CodeGen, enum_ty: Type) InnerError!u32 { |
| 7333 | 7331 | try writer.writeByte(std.wasm.opcode(.end)); |
| 7334 | 7332 | |
| 7335 | 7333 | const slice_ty = Type.slice_const_u8_sentinel_0; |
| 7336 | const func_type = try genFunctype(arena, .Unspecified, &.{int_tag_ty.ip_index}, slice_ty, pt); | |
| 7334 | const func_type = try genFunctype(arena, .Unspecified, &.{int_tag_ty.ip_index}, slice_ty, pt, func.target.*); | |
| 7337 | 7335 | const sym_index = try func.bin_file.createFunction(func_name, func_type, &body_list, &relocs); |
| 7338 | 7336 | return @intFromEnum(sym_index); |
| 7339 | 7337 | } |
| ... | ... | @@ -7477,7 +7475,7 @@ fn airCmpxchg(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 7477 | 7475 | break :val ptr_val; |
| 7478 | 7476 | }; |
| 7479 | 7477 | |
| 7480 | const result = if (isByRef(result_ty, pt)) val: { | |
| 7478 | const result = if (isByRef(result_ty, pt, func.target.*)) val: { | |
| 7481 | 7479 | try func.emitWValue(cmp_result); |
| 7482 | 7480 | try func.addImm32(~@as(u32, 0)); |
| 7483 | 7481 | try func.addTag(.i32_xor); |
| ... | ... | @@ -7706,8 +7704,7 @@ fn airFence(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 7706 | 7704 | // Only when the atomic feature is enabled, and we're not building |
| 7707 | 7705 | // for a single-threaded build, can we emit the `fence` instruction. |
| 7708 | 7706 | // In all other cases, we emit no instructions for a fence. |
| 7709 | const func_namespace = zcu.namespacePtr(func.decl.src_namespace); | |
| 7710 | const single_threaded = func_namespace.fileScope(zcu).mod.single_threaded; | |
| 7707 | const single_threaded = zcu.navFileScope(func.owner_nav).mod.single_threaded; | |
| 7711 | 7708 | if (func.useAtomicFeature() and !single_threaded) { |
| 7712 | 7709 | try func.addAtomicTag(.atomic_fence); |
| 7713 | 7710 | } |
src/arch/wasm/Emit.zig+7-7| ... | ... | @@ -22,7 +22,7 @@ code: *std.ArrayList(u8), |
| 22 | 22 | /// List of allocated locals. |
| 23 | 23 | locals: []const u8, |
| 24 | 24 | /// The declaration that code is being generated for. |
| 25 | decl_index: InternPool.DeclIndex, | |
| 25 | owner_nav: InternPool.Nav.Index, | |
| 26 | 26 | |
| 27 | 27 | // Debug information |
| 28 | 28 | /// Holds the debug information for this emission |
| ... | ... | @@ -257,7 +257,7 @@ fn fail(emit: *Emit, comptime format: []const u8, args: anytype) InnerError { |
| 257 | 257 | const comp = emit.bin_file.base.comp; |
| 258 | 258 | const zcu = comp.module.?; |
| 259 | 259 | const gpa = comp.gpa; |
| 260 | emit.error_msg = try Zcu.ErrorMsg.create(gpa, zcu.declPtr(emit.decl_index).navSrcLoc(zcu), format, args); | |
| 260 | emit.error_msg = try Zcu.ErrorMsg.create(gpa, zcu.navSrcLoc(emit.owner_nav), format, args); | |
| 261 | 261 | return error.EmitFail; |
| 262 | 262 | } |
| 263 | 263 | |
| ... | ... | @@ -310,7 +310,7 @@ fn emitGlobal(emit: *Emit, tag: Mir.Inst.Tag, inst: Mir.Inst.Index) !void { |
| 310 | 310 | const global_offset = emit.offset(); |
| 311 | 311 | try emit.code.appendSlice(&buf); |
| 312 | 312 | |
| 313 | const atom_index = emit.bin_file.zigObjectPtr().?.decls_map.get(emit.decl_index).?.atom; | |
| 313 | const atom_index = emit.bin_file.zigObjectPtr().?.navs.get(emit.owner_nav).?.atom; | |
| 314 | 314 | const atom = emit.bin_file.getAtomPtr(atom_index); |
| 315 | 315 | try atom.relocs.append(gpa, .{ |
| 316 | 316 | .index = label, |
| ... | ... | @@ -370,7 +370,7 @@ fn emitCall(emit: *Emit, inst: Mir.Inst.Index) !void { |
| 370 | 370 | try emit.code.appendSlice(&buf); |
| 371 | 371 | |
| 372 | 372 | if (label != 0) { |
| 373 | const atom_index = emit.bin_file.zigObjectPtr().?.decls_map.get(emit.decl_index).?.atom; | |
| 373 | const atom_index = emit.bin_file.zigObjectPtr().?.navs.get(emit.owner_nav).?.atom; | |
| 374 | 374 | const atom = emit.bin_file.getAtomPtr(atom_index); |
| 375 | 375 | try atom.relocs.append(gpa, .{ |
| 376 | 376 | .offset = call_offset, |
| ... | ... | @@ -390,7 +390,7 @@ fn emitCallIndirect(emit: *Emit, inst: Mir.Inst.Index) !void { |
| 390 | 390 | leb128.writeUnsignedFixed(5, &buf, type_index); |
| 391 | 391 | try emit.code.appendSlice(&buf); |
| 392 | 392 | if (type_index != 0) { |
| 393 | const atom_index = emit.bin_file.zigObjectPtr().?.decls_map.get(emit.decl_index).?.atom; | |
| 393 | const atom_index = emit.bin_file.zigObjectPtr().?.navs.get(emit.owner_nav).?.atom; | |
| 394 | 394 | const atom = emit.bin_file.getAtomPtr(atom_index); |
| 395 | 395 | try atom.relocs.append(emit.bin_file.base.comp.gpa, .{ |
| 396 | 396 | .offset = call_offset, |
| ... | ... | @@ -412,7 +412,7 @@ fn emitFunctionIndex(emit: *Emit, inst: Mir.Inst.Index) !void { |
| 412 | 412 | try emit.code.appendSlice(&buf); |
| 413 | 413 | |
| 414 | 414 | if (symbol_index != 0) { |
| 415 | const atom_index = emit.bin_file.zigObjectPtr().?.decls_map.get(emit.decl_index).?.atom; | |
| 415 | const atom_index = emit.bin_file.zigObjectPtr().?.navs.get(emit.owner_nav).?.atom; | |
| 416 | 416 | const atom = emit.bin_file.getAtomPtr(atom_index); |
| 417 | 417 | try atom.relocs.append(gpa, .{ |
| 418 | 418 | .offset = index_offset, |
| ... | ... | @@ -443,7 +443,7 @@ fn emitMemAddress(emit: *Emit, inst: Mir.Inst.Index) !void { |
| 443 | 443 | } |
| 444 | 444 | |
| 445 | 445 | if (mem.pointer != 0) { |
| 446 | const atom_index = emit.bin_file.zigObjectPtr().?.decls_map.get(emit.decl_index).?.atom; | |
| 446 | const atom_index = emit.bin_file.zigObjectPtr().?.navs.get(emit.owner_nav).?.atom; | |
| 447 | 447 | const atom = emit.bin_file.getAtomPtr(atom_index); |
| 448 | 448 | try atom.relocs.append(gpa, .{ |
| 449 | 449 | .offset = mem_offset, |
src/arch/x86_64/CodeGen.zig+84-109| ... | ... | @@ -116,48 +116,36 @@ const RegisterOffset = struct { reg: Register, off: i32 = 0 }; |
| 116 | 116 | const SymbolOffset = struct { sym: u32, off: i32 = 0 }; |
| 117 | 117 | |
| 118 | 118 | const Owner = union(enum) { |
| 119 | func_index: InternPool.Index, | |
| 119 | nav_index: InternPool.Nav.Index, | |
| 120 | 120 | lazy_sym: link.File.LazySymbol, |
| 121 | 121 | |
| 122 | fn getDecl(owner: Owner, zcu: *Zcu) InternPool.DeclIndex { | |
| 123 | return switch (owner) { | |
| 124 | .func_index => |func_index| zcu.funcOwnerDeclIndex(func_index), | |
| 125 | .lazy_sym => |lazy_sym| lazy_sym.ty.getOwnerDecl(zcu), | |
| 126 | }; | |
| 127 | } | |
| 128 | ||
| 129 | 122 | fn getSymbolIndex(owner: Owner, ctx: *Self) !u32 { |
| 130 | 123 | const pt = ctx.pt; |
| 131 | 124 | switch (owner) { |
| 132 | .func_index => |func_index| { | |
| 133 | const decl_index = ctx.pt.zcu.funcOwnerDeclIndex(func_index); | |
| 134 | if (ctx.bin_file.cast(link.File.Elf)) |elf_file| { | |
| 135 | return elf_file.zigObjectPtr().?.getOrCreateMetadataForDecl(elf_file, decl_index); | |
| 136 | } else if (ctx.bin_file.cast(link.File.MachO)) |macho_file| { | |
| 137 | return macho_file.getZigObject().?.getOrCreateMetadataForDecl(macho_file, decl_index); | |
| 138 | } else if (ctx.bin_file.cast(link.File.Coff)) |coff_file| { | |
| 139 | const atom = try coff_file.getOrCreateAtomForDecl(decl_index); | |
| 140 | return coff_file.getAtom(atom).getSymbolIndex().?; | |
| 141 | } else if (ctx.bin_file.cast(link.File.Plan9)) |p9_file| { | |
| 142 | return p9_file.seeDecl(decl_index); | |
| 143 | } else unreachable; | |
| 144 | }, | |
| 145 | .lazy_sym => |lazy_sym| { | |
| 146 | if (ctx.bin_file.cast(link.File.Elf)) |elf_file| { | |
| 147 | return elf_file.zigObjectPtr().?.getOrCreateMetadataForLazySymbol(elf_file, pt, lazy_sym) catch |err| | |
| 148 | ctx.fail("{s} creating lazy symbol", .{@errorName(err)}); | |
| 149 | } else if (ctx.bin_file.cast(link.File.MachO)) |macho_file| { | |
| 150 | return macho_file.getZigObject().?.getOrCreateMetadataForLazySymbol(macho_file, pt, lazy_sym) catch |err| | |
| 151 | ctx.fail("{s} creating lazy symbol", .{@errorName(err)}); | |
| 152 | } else if (ctx.bin_file.cast(link.File.Coff)) |coff_file| { | |
| 153 | const atom = coff_file.getOrCreateAtomForLazySymbol(pt, lazy_sym) catch |err| | |
| 154 | return ctx.fail("{s} creating lazy symbol", .{@errorName(err)}); | |
| 155 | return coff_file.getAtom(atom).getSymbolIndex().?; | |
| 156 | } else if (ctx.bin_file.cast(link.File.Plan9)) |p9_file| { | |
| 157 | return p9_file.getOrCreateAtomForLazySymbol(pt, lazy_sym) catch |err| | |
| 158 | return ctx.fail("{s} creating lazy symbol", .{@errorName(err)}); | |
| 159 | } else unreachable; | |
| 160 | }, | |
| 125 | .nav_index => |nav_index| if (ctx.bin_file.cast(.elf)) |elf_file| { | |
| 126 | return elf_file.zigObjectPtr().?.getOrCreateMetadataForNav(elf_file, nav_index); | |
| 127 | } else if (ctx.bin_file.cast(.macho)) |macho_file| { | |
| 128 | return macho_file.getZigObject().?.getOrCreateMetadataForNav(macho_file, nav_index); | |
| 129 | } else if (ctx.bin_file.cast(.coff)) |coff_file| { | |
| 130 | const atom = try coff_file.getOrCreateAtomForNav(nav_index); | |
| 131 | return coff_file.getAtom(atom).getSymbolIndex().?; | |
| 132 | } else if (ctx.bin_file.cast(.plan9)) |p9_file| { | |
| 133 | return p9_file.seeNav(pt, nav_index); | |
| 134 | } else unreachable, | |
| 135 | .lazy_sym => |lazy_sym| if (ctx.bin_file.cast(.elf)) |elf_file| { | |
| 136 | return elf_file.zigObjectPtr().?.getOrCreateMetadataForLazySymbol(elf_file, pt, lazy_sym) catch |err| | |
| 137 | ctx.fail("{s} creating lazy symbol", .{@errorName(err)}); | |
| 138 | } else if (ctx.bin_file.cast(.macho)) |macho_file| { | |
| 139 | return macho_file.getZigObject().?.getOrCreateMetadataForLazySymbol(macho_file, pt, lazy_sym) catch |err| | |
| 140 | ctx.fail("{s} creating lazy symbol", .{@errorName(err)}); | |
| 141 | } else if (ctx.bin_file.cast(.coff)) |coff_file| { | |
| 142 | const atom = coff_file.getOrCreateAtomForLazySymbol(pt, lazy_sym) catch |err| | |
| 143 | return ctx.fail("{s} creating lazy symbol", .{@errorName(err)}); | |
| 144 | return coff_file.getAtom(atom).getSymbolIndex().?; | |
| 145 | } else if (ctx.bin_file.cast(.plan9)) |p9_file| { | |
| 146 | return p9_file.getOrCreateAtomForLazySymbol(pt, lazy_sym) catch |err| | |
| 147 | return ctx.fail("{s} creating lazy symbol", .{@errorName(err)}); | |
| 148 | } else unreachable, | |
| 161 | 149 | } |
| 162 | 150 | } |
| 163 | 151 | }; |
| ... | ... | @@ -803,14 +791,12 @@ pub fn generate( |
| 803 | 791 | debug_output: DebugInfoOutput, |
| 804 | 792 | ) CodeGenError!Result { |
| 805 | 793 | const zcu = pt.zcu; |
| 806 | const gpa = zcu.gpa; | |
| 807 | 794 | const comp = zcu.comp; |
| 795 | const gpa = zcu.gpa; | |
| 796 | const ip = &zcu.intern_pool; | |
| 808 | 797 | const func = zcu.funcInfo(func_index); |
| 809 | const fn_owner_decl = zcu.declPtr(func.owner_decl); | |
| 810 | assert(fn_owner_decl.has_tv); | |
| 811 | const fn_type = fn_owner_decl.typeOf(zcu); | |
| 812 | const namespace = zcu.namespacePtr(fn_owner_decl.src_namespace); | |
| 813 | const mod = namespace.fileScope(zcu).mod; | |
| 798 | const fn_type = Type.fromInterned(func.ty); | |
| 799 | const mod = zcu.navFileScope(func.owner_nav).mod; | |
| 814 | 800 | |
| 815 | 801 | var function: Self = .{ |
| 816 | 802 | .gpa = gpa, |
| ... | ... | @@ -821,7 +807,7 @@ pub fn generate( |
| 821 | 807 | .mod = mod, |
| 822 | 808 | .bin_file = bin_file, |
| 823 | 809 | .debug_output = debug_output, |
| 824 | .owner = .{ .func_index = func_index }, | |
| 810 | .owner = .{ .nav_index = func.owner_nav }, | |
| 825 | 811 | .inline_func = func_index, |
| 826 | 812 | .err_msg = null, |
| 827 | 813 | .args = undefined, // populated after `resolveCallingConventionValues` |
| ... | ... | @@ -847,9 +833,7 @@ pub fn generate( |
| 847 | 833 | function.mir_extra.deinit(gpa); |
| 848 | 834 | } |
| 849 | 835 | |
| 850 | wip_mir_log.debug("{}:", .{function.fmtDecl(func.owner_decl)}); | |
| 851 | ||
| 852 | const ip = &zcu.intern_pool; | |
| 836 | wip_mir_log.debug("{}:", .{fmtNav(func.owner_nav, ip)}); | |
| 853 | 837 | |
| 854 | 838 | try function.frame_allocs.resize(gpa, FrameIndex.named_count); |
| 855 | 839 | function.frame_allocs.set( |
| ... | ... | @@ -1067,22 +1051,22 @@ pub fn generateLazy( |
| 1067 | 1051 | } |
| 1068 | 1052 | } |
| 1069 | 1053 | |
| 1070 | const FormatDeclData = struct { | |
| 1071 | zcu: *Zcu, | |
| 1072 | decl_index: InternPool.DeclIndex, | |
| 1054 | const FormatNavData = struct { | |
| 1055 | ip: *const InternPool, | |
| 1056 | nav_index: InternPool.Nav.Index, | |
| 1073 | 1057 | }; |
| 1074 | fn formatDecl( | |
| 1075 | data: FormatDeclData, | |
| 1058 | fn formatNav( | |
| 1059 | data: FormatNavData, | |
| 1076 | 1060 | comptime _: []const u8, |
| 1077 | 1061 | _: std.fmt.FormatOptions, |
| 1078 | 1062 | writer: anytype, |
| 1079 | 1063 | ) @TypeOf(writer).Error!void { |
| 1080 | try writer.print("{}", .{data.zcu.declPtr(data.decl_index).fqn.fmt(&data.zcu.intern_pool)}); | |
| 1064 | try writer.print("{}", .{data.ip.getNav(data.nav_index).fqn.fmt(data.ip)}); | |
| 1081 | 1065 | } |
| 1082 | fn fmtDecl(self: *Self, decl_index: InternPool.DeclIndex) std.fmt.Formatter(formatDecl) { | |
| 1066 | fn fmtNav(nav_index: InternPool.Nav.Index, ip: *const InternPool) std.fmt.Formatter(formatNav) { | |
| 1083 | 1067 | return .{ .data = .{ |
| 1084 | .zcu = self.pt.zcu, | |
| 1085 | .decl_index = decl_index, | |
| 1068 | .ip = ip, | |
| 1069 | .nav_index = nav_index, | |
| 1086 | 1070 | } }; |
| 1087 | 1071 | } |
| 1088 | 1072 | |
| ... | ... | @@ -2230,9 +2214,9 @@ fn genLazy(self: *Self, lazy_sym: link.File.LazySymbol) InnerError!void { |
| 2230 | 2214 | const pt = self.pt; |
| 2231 | 2215 | const mod = pt.zcu; |
| 2232 | 2216 | const ip = &mod.intern_pool; |
| 2233 | switch (lazy_sym.ty.zigTypeTag(mod)) { | |
| 2217 | switch (Type.fromInterned(lazy_sym.ty).zigTypeTag(mod)) { | |
| 2234 | 2218 | .Enum => { |
| 2235 | const enum_ty = lazy_sym.ty; | |
| 2219 | const enum_ty = Type.fromInterned(lazy_sym.ty); | |
| 2236 | 2220 | wip_mir_log.debug("{}.@tagName:", .{enum_ty.fmt(pt)}); |
| 2237 | 2221 | |
| 2238 | 2222 | const resolved_cc = abi.resolveCallingConvention(.Unspecified, self.target.*); |
| ... | ... | @@ -2249,7 +2233,7 @@ fn genLazy(self: *Self, lazy_sym: link.File.LazySymbol) InnerError!void { |
| 2249 | 2233 | const data_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp); |
| 2250 | 2234 | const data_lock = self.register_manager.lockRegAssumeUnused(data_reg); |
| 2251 | 2235 | defer self.register_manager.unlockReg(data_lock); |
| 2252 | try self.genLazySymbolRef(.lea, data_reg, .{ .kind = .const_data, .ty = enum_ty }); | |
| 2236 | try self.genLazySymbolRef(.lea, data_reg, .{ .kind = .const_data, .ty = enum_ty.toIntern() }); | |
| 2253 | 2237 | |
| 2254 | 2238 | var data_off: i32 = 0; |
| 2255 | 2239 | const tag_names = enum_ty.enumFields(mod); |
| ... | ... | @@ -2288,7 +2272,7 @@ fn genLazy(self: *Self, lazy_sym: link.File.LazySymbol) InnerError!void { |
| 2288 | 2272 | }, |
| 2289 | 2273 | else => return self.fail( |
| 2290 | 2274 | "TODO implement {s} for {}", |
| 2291 | .{ @tagName(lazy_sym.kind), lazy_sym.ty.fmt(pt) }, | |
| 2275 | .{ @tagName(lazy_sym.kind), Type.fromInterned(lazy_sym.ty).fmt(pt) }, | |
| 2292 | 2276 | ), |
| 2293 | 2277 | } |
| 2294 | 2278 | } |
| ... | ... | @@ -11932,11 +11916,9 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void { |
| 11932 | 11916 | } |
| 11933 | 11917 | |
| 11934 | 11918 | fn genArgDbgInfo(self: Self, ty: Type, name: [:0]const u8, mcv: MCValue) !void { |
| 11935 | const pt = self.pt; | |
| 11936 | const mod = pt.zcu; | |
| 11937 | 11919 | switch (self.debug_output) { |
| 11938 | 11920 | .dwarf => |dw| { |
| 11939 | const loc: link.File.Dwarf.DeclState.DbgInfoLoc = switch (mcv) { | |
| 11921 | const loc: link.File.Dwarf.NavState.DbgInfoLoc = switch (mcv) { | |
| 11940 | 11922 | .register => |reg| .{ .register = reg.dwarfNum() }, |
| 11941 | 11923 | .register_pair => |regs| .{ .register_pair = .{ |
| 11942 | 11924 | regs[0].dwarfNum(), regs[1].dwarfNum(), |
| ... | ... | @@ -11955,7 +11937,7 @@ fn genArgDbgInfo(self: Self, ty: Type, name: [:0]const u8, mcv: MCValue) !void { |
| 11955 | 11937 | // TODO: this might need adjusting like the linkers do. |
| 11956 | 11938 | // Instead of flattening the owner and passing Decl.Index here we may |
| 11957 | 11939 | // want to special case LazySymbol in DWARF linker too. |
| 11958 | try dw.genArgDbgInfo(name, ty, self.owner.getDecl(mod), loc); | |
| 11940 | try dw.genArgDbgInfo(name, ty, self.owner.nav_index, loc); | |
| 11959 | 11941 | }, |
| 11960 | 11942 | .plan9 => {}, |
| 11961 | 11943 | .none => {}, |
| ... | ... | @@ -11969,8 +11951,6 @@ fn genVarDbgInfo( |
| 11969 | 11951 | mcv: MCValue, |
| 11970 | 11952 | name: [:0]const u8, |
| 11971 | 11953 | ) !void { |
| 11972 | const pt = self.pt; | |
| 11973 | const mod = pt.zcu; | |
| 11974 | 11954 | const is_ptr = switch (tag) { |
| 11975 | 11955 | .dbg_var_ptr => true, |
| 11976 | 11956 | .dbg_var_val => false, |
| ... | ... | @@ -11979,7 +11959,7 @@ fn genVarDbgInfo( |
| 11979 | 11959 | |
| 11980 | 11960 | switch (self.debug_output) { |
| 11981 | 11961 | .dwarf => |dw| { |
| 11982 | const loc: link.File.Dwarf.DeclState.DbgInfoLoc = switch (mcv) { | |
| 11962 | const loc: link.File.Dwarf.NavState.DbgInfoLoc = switch (mcv) { | |
| 11983 | 11963 | .register => |reg| .{ .register = reg.dwarfNum() }, |
| 11984 | 11964 | // TODO use a frame index |
| 11985 | 11965 | .load_frame, .lea_frame => return, |
| ... | ... | @@ -12007,7 +11987,7 @@ fn genVarDbgInfo( |
| 12007 | 11987 | // TODO: this might need adjusting like the linkers do. |
| 12008 | 11988 | // Instead of flattening the owner and passing Decl.Index here we may |
| 12009 | 11989 | // want to special case LazySymbol in DWARF linker too. |
| 12010 | try dw.genVarDbgInfo(name, ty, self.owner.getDecl(mod), is_ptr, loc); | |
| 11990 | try dw.genVarDbgInfo(name, ty, self.owner.nav_index, is_ptr, loc); | |
| 12011 | 11991 | }, |
| 12012 | 11992 | .plan9 => {}, |
| 12013 | 11993 | .none => {}, |
| ... | ... | @@ -12090,14 +12070,15 @@ fn genCall(self: *Self, info: union(enum) { |
| 12090 | 12070 | }, |
| 12091 | 12071 | }, arg_types: []const Type, args: []const MCValue) !MCValue { |
| 12092 | 12072 | const pt = self.pt; |
| 12093 | const mod = pt.zcu; | |
| 12073 | const zcu = pt.zcu; | |
| 12074 | const ip = &zcu.intern_pool; | |
| 12094 | 12075 | |
| 12095 | 12076 | const fn_ty = switch (info) { |
| 12096 | 12077 | .air => |callee| fn_info: { |
| 12097 | 12078 | const callee_ty = self.typeOf(callee); |
| 12098 | break :fn_info switch (callee_ty.zigTypeTag(mod)) { | |
| 12079 | break :fn_info switch (callee_ty.zigTypeTag(zcu)) { | |
| 12099 | 12080 | .Fn => callee_ty, |
| 12100 | .Pointer => callee_ty.childType(mod), | |
| 12081 | .Pointer => callee_ty.childType(zcu), | |
| 12101 | 12082 | else => unreachable, |
| 12102 | 12083 | }; |
| 12103 | 12084 | }, |
| ... | ... | @@ -12107,7 +12088,7 @@ fn genCall(self: *Self, info: union(enum) { |
| 12107 | 12088 | .cc = .C, |
| 12108 | 12089 | }), |
| 12109 | 12090 | }; |
| 12110 | const fn_info = mod.typeToFunc(fn_ty).?; | |
| 12091 | const fn_info = zcu.typeToFunc(fn_ty).?; | |
| 12111 | 12092 | const resolved_cc = abi.resolveCallingConvention(fn_info.cc, self.target.*); |
| 12112 | 12093 | |
| 12113 | 12094 | const ExpectedContents = extern struct { |
| ... | ... | @@ -12225,7 +12206,7 @@ fn genCall(self: *Self, info: union(enum) { |
| 12225 | 12206 | try self.asmRegisterImmediate( |
| 12226 | 12207 | .{ ._, .cmp }, |
| 12227 | 12208 | index_reg.to32(), |
| 12228 | Immediate.u(arg_ty.vectorLen(mod)), | |
| 12209 | Immediate.u(arg_ty.vectorLen(zcu)), | |
| 12229 | 12210 | ); |
| 12230 | 12211 | _ = try self.asmJccReloc(.b, loop); |
| 12231 | 12212 | |
| ... | ... | @@ -12317,18 +12298,18 @@ fn genCall(self: *Self, info: union(enum) { |
| 12317 | 12298 | // on linking. |
| 12318 | 12299 | switch (info) { |
| 12319 | 12300 | .air => |callee| if (try self.air.value(callee, pt)) |func_value| { |
| 12320 | const func_key = mod.intern_pool.indexToKey(func_value.ip_index); | |
| 12301 | const func_key = ip.indexToKey(func_value.ip_index); | |
| 12321 | 12302 | switch (switch (func_key) { |
| 12322 | 12303 | else => func_key, |
| 12323 | 12304 | .ptr => |ptr| if (ptr.byte_offset == 0) switch (ptr.base_addr) { |
| 12324 | .decl => |decl| mod.intern_pool.indexToKey(mod.declPtr(decl).val.toIntern()), | |
| 12305 | .nav => |nav| ip.indexToKey(zcu.navValue(nav).toIntern()), | |
| 12325 | 12306 | else => func_key, |
| 12326 | 12307 | } else func_key, |
| 12327 | 12308 | }) { |
| 12328 | 12309 | .func => |func| { |
| 12329 | if (self.bin_file.cast(link.File.Elf)) |elf_file| { | |
| 12310 | if (self.bin_file.cast(.elf)) |elf_file| { | |
| 12330 | 12311 | const zo = elf_file.zigObjectPtr().?; |
| 12331 | const sym_index = try zo.getOrCreateMetadataForDecl(elf_file, func.owner_decl); | |
| 12312 | const sym_index = try zo.getOrCreateMetadataForNav(elf_file, func.owner_nav); | |
| 12332 | 12313 | if (self.mod.pic) { |
| 12333 | 12314 | const callee_reg: Register = switch (resolved_cc) { |
| 12334 | 12315 | .SysV => callee: { |
| ... | ... | @@ -12356,14 +12337,14 @@ fn genCall(self: *Self, info: union(enum) { |
| 12356 | 12337 | } }, |
| 12357 | 12338 | .mod = .{ .rm = .{ .size = .qword } }, |
| 12358 | 12339 | }); |
| 12359 | } else if (self.bin_file.cast(link.File.Coff)) |coff_file| { | |
| 12360 | const atom = try coff_file.getOrCreateAtomForDecl(func.owner_decl); | |
| 12340 | } else if (self.bin_file.cast(.coff)) |coff_file| { | |
| 12341 | const atom = try coff_file.getOrCreateAtomForNav(func.owner_nav); | |
| 12361 | 12342 | const sym_index = coff_file.getAtom(atom).getSymbolIndex().?; |
| 12362 | 12343 | try self.genSetReg(.rax, Type.usize, .{ .lea_got = sym_index }, .{}); |
| 12363 | 12344 | try self.asmRegister(.{ ._, .call }, .rax); |
| 12364 | } else if (self.bin_file.cast(link.File.MachO)) |macho_file| { | |
| 12345 | } else if (self.bin_file.cast(.macho)) |macho_file| { | |
| 12365 | 12346 | const zo = macho_file.getZigObject().?; |
| 12366 | const sym_index = try zo.getOrCreateMetadataForDecl(macho_file, func.owner_decl); | |
| 12347 | const sym_index = try zo.getOrCreateMetadataForNav(macho_file, func.owner_nav); | |
| 12367 | 12348 | const sym = zo.symbols.items[sym_index]; |
| 12368 | 12349 | try self.genSetReg( |
| 12369 | 12350 | .rax, |
| ... | ... | @@ -12372,8 +12353,8 @@ fn genCall(self: *Self, info: union(enum) { |
| 12372 | 12353 | .{}, |
| 12373 | 12354 | ); |
| 12374 | 12355 | try self.asmRegister(.{ ._, .call }, .rax); |
| 12375 | } else if (self.bin_file.cast(link.File.Plan9)) |p9| { | |
| 12376 | const atom_index = try p9.seeDecl(func.owner_decl); | |
| 12356 | } else if (self.bin_file.cast(.plan9)) |p9| { | |
| 12357 | const atom_index = try p9.seeNav(pt, func.owner_nav); | |
| 12377 | 12358 | const atom = p9.getAtom(atom_index); |
| 12378 | 12359 | try self.asmMemory(.{ ._, .call }, .{ |
| 12379 | 12360 | .base = .{ .reg = .ds }, |
| ... | ... | @@ -12384,16 +12365,15 @@ fn genCall(self: *Self, info: union(enum) { |
| 12384 | 12365 | }); |
| 12385 | 12366 | } else unreachable; |
| 12386 | 12367 | }, |
| 12387 | .extern_func => |extern_func| { | |
| 12388 | const owner_decl = mod.declPtr(extern_func.decl); | |
| 12389 | const lib_name = extern_func.lib_name.toSlice(&mod.intern_pool); | |
| 12390 | const decl_name = owner_decl.name.toSlice(&mod.intern_pool); | |
| 12391 | try self.genExternSymbolRef(.call, lib_name, decl_name); | |
| 12392 | }, | |
| 12368 | .@"extern" => |@"extern"| try self.genExternSymbolRef( | |
| 12369 | .call, | |
| 12370 | @"extern".lib_name.toSlice(ip), | |
| 12371 | @"extern".name.toSlice(ip), | |
| 12372 | ), | |
| 12393 | 12373 | else => return self.fail("TODO implement calling bitcasted functions", .{}), |
| 12394 | 12374 | } |
| 12395 | 12375 | } else { |
| 12396 | assert(self.typeOf(callee).zigTypeTag(mod) == .Pointer); | |
| 12376 | assert(self.typeOf(callee).zigTypeTag(zcu) == .Pointer); | |
| 12397 | 12377 | try self.genSetReg(.rax, Type.usize, .{ .air_ref = callee }, .{}); |
| 12398 | 12378 | try self.asmRegister(.{ ._, .call }, .rax); |
| 12399 | 12379 | }, |
| ... | ... | @@ -12919,13 +12899,13 @@ fn airCmpVector(self: *Self, inst: Air.Inst.Index) !void { |
| 12919 | 12899 | |
| 12920 | 12900 | fn airCmpLtErrorsLen(self: *Self, inst: Air.Inst.Index) !void { |
| 12921 | 12901 | const pt = self.pt; |
| 12922 | const mod = pt.zcu; | |
| 12923 | 12902 | const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op; |
| 12924 | 12903 | |
| 12925 | 12904 | const addr_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp); |
| 12926 | 12905 | const addr_lock = self.register_manager.lockRegAssumeUnused(addr_reg); |
| 12927 | 12906 | defer self.register_manager.unlockReg(addr_lock); |
| 12928 | try self.genLazySymbolRef(.lea, addr_reg, link.File.LazySymbol.initDecl(.const_data, null, mod)); | |
| 12907 | const anyerror_lazy_sym: link.File.LazySymbol = .{ .kind = .const_data, .ty = .anyerror_type }; | |
| 12908 | try self.genLazySymbolRef(.lea, addr_reg, anyerror_lazy_sym); | |
| 12929 | 12909 | |
| 12930 | 12910 | try self.spillEflagsIfOccupied(); |
| 12931 | 12911 | |
| ... | ... | @@ -15273,7 +15253,7 @@ fn genExternSymbolRef( |
| 15273 | 15253 | callee: []const u8, |
| 15274 | 15254 | ) InnerError!void { |
| 15275 | 15255 | const atom_index = try self.owner.getSymbolIndex(self); |
| 15276 | if (self.bin_file.cast(link.File.Elf)) |elf_file| { | |
| 15256 | if (self.bin_file.cast(.elf)) |elf_file| { | |
| 15277 | 15257 | _ = try self.addInst(.{ |
| 15278 | 15258 | .tag = tag, |
| 15279 | 15259 | .ops = .extern_fn_reloc, |
| ... | ... | @@ -15282,7 +15262,7 @@ fn genExternSymbolRef( |
| 15282 | 15262 | .sym_index = try elf_file.getGlobalSymbol(callee, lib), |
| 15283 | 15263 | } }, |
| 15284 | 15264 | }); |
| 15285 | } else if (self.bin_file.cast(link.File.Coff)) |coff_file| { | |
| 15265 | } else if (self.bin_file.cast(.coff)) |coff_file| { | |
| 15286 | 15266 | const global_index = try coff_file.getGlobalSymbol(callee, lib); |
| 15287 | 15267 | _ = try self.addInst(.{ |
| 15288 | 15268 | .tag = .mov, |
| ... | ... | @@ -15300,7 +15280,7 @@ fn genExternSymbolRef( |
| 15300 | 15280 | .call => try self.asmRegister(.{ ._, .call }, .rax), |
| 15301 | 15281 | else => unreachable, |
| 15302 | 15282 | } |
| 15303 | } else if (self.bin_file.cast(link.File.MachO)) |macho_file| { | |
| 15283 | } else if (self.bin_file.cast(.macho)) |macho_file| { | |
| 15304 | 15284 | _ = try self.addInst(.{ |
| 15305 | 15285 | .tag = .call, |
| 15306 | 15286 | .ops = .extern_fn_reloc, |
| ... | ... | @@ -15319,7 +15299,7 @@ fn genLazySymbolRef( |
| 15319 | 15299 | lazy_sym: link.File.LazySymbol, |
| 15320 | 15300 | ) InnerError!void { |
| 15321 | 15301 | const pt = self.pt; |
| 15322 | if (self.bin_file.cast(link.File.Elf)) |elf_file| { | |
| 15302 | if (self.bin_file.cast(.elf)) |elf_file| { | |
| 15323 | 15303 | const zo = elf_file.zigObjectPtr().?; |
| 15324 | 15304 | const sym_index = zo.getOrCreateMetadataForLazySymbol(elf_file, pt, lazy_sym) catch |err| |
| 15325 | 15305 | return self.fail("{s} creating lazy symbol", .{@errorName(err)}); |
| ... | ... | @@ -15355,7 +15335,7 @@ fn genLazySymbolRef( |
| 15355 | 15335 | else => unreachable, |
| 15356 | 15336 | } |
| 15357 | 15337 | } |
| 15358 | } else if (self.bin_file.cast(link.File.Plan9)) |p9_file| { | |
| 15338 | } else if (self.bin_file.cast(.plan9)) |p9_file| { | |
| 15359 | 15339 | const atom_index = p9_file.getOrCreateAtomForLazySymbol(pt, lazy_sym) catch |err| |
| 15360 | 15340 | return self.fail("{s} creating lazy symbol", .{@errorName(err)}); |
| 15361 | 15341 | var atom = p9_file.getAtom(atom_index); |
| ... | ... | @@ -15382,7 +15362,7 @@ fn genLazySymbolRef( |
| 15382 | 15362 | ), |
| 15383 | 15363 | else => unreachable, |
| 15384 | 15364 | } |
| 15385 | } else if (self.bin_file.cast(link.File.Coff)) |coff_file| { | |
| 15365 | } else if (self.bin_file.cast(.coff)) |coff_file| { | |
| 15386 | 15366 | const atom_index = coff_file.getOrCreateAtomForLazySymbol(pt, lazy_sym) catch |err| |
| 15387 | 15367 | return self.fail("{s} creating lazy symbol", .{@errorName(err)}); |
| 15388 | 15368 | const sym_index = coff_file.getAtom(atom_index).getSymbolIndex().?; |
| ... | ... | @@ -15396,7 +15376,7 @@ fn genLazySymbolRef( |
| 15396 | 15376 | .call => try self.asmRegister(.{ ._, .call }, reg), |
| 15397 | 15377 | else => unreachable, |
| 15398 | 15378 | } |
| 15399 | } else if (self.bin_file.cast(link.File.MachO)) |macho_file| { | |
| 15379 | } else if (self.bin_file.cast(.macho)) |macho_file| { | |
| 15400 | 15380 | const zo = macho_file.getZigObject().?; |
| 15401 | 15381 | const sym_index = zo.getOrCreateMetadataForLazySymbol(macho_file, pt, lazy_sym) catch |err| |
| 15402 | 15382 | return self.fail("{s} creating lazy symbol", .{@errorName(err)}); |
| ... | ... | @@ -16361,7 +16341,6 @@ fn airMemcpy(self: *Self, inst: Air.Inst.Index) !void { |
| 16361 | 16341 | |
| 16362 | 16342 | fn airTagName(self: *Self, inst: Air.Inst.Index) !void { |
| 16363 | 16343 | const pt = self.pt; |
| 16364 | const mod = pt.zcu; | |
| 16365 | 16344 | const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op; |
| 16366 | 16345 | const inst_ty = self.typeOfIndex(inst); |
| 16367 | 16346 | const enum_ty = self.typeOf(un_op); |
| ... | ... | @@ -16393,18 +16372,13 @@ fn airTagName(self: *Self, inst: Air.Inst.Index) !void { |
| 16393 | 16372 | const operand = try self.resolveInst(un_op); |
| 16394 | 16373 | try self.genSetReg(param_regs[1], enum_ty, operand, .{}); |
| 16395 | 16374 | |
| 16396 | try self.genLazySymbolRef( | |
| 16397 | .call, | |
| 16398 | .rax, | |
| 16399 | link.File.LazySymbol.initDecl(.code, enum_ty.getOwnerDecl(mod), mod), | |
| 16400 | ); | |
| 16375 | const enum_lazy_sym: link.File.LazySymbol = .{ .kind = .code, .ty = enum_ty.toIntern() }; | |
| 16376 | try self.genLazySymbolRef(.call, .rax, enum_lazy_sym); | |
| 16401 | 16377 | |
| 16402 | 16378 | return self.finishAir(inst, dst_mcv, .{ un_op, .none, .none }); |
| 16403 | 16379 | } |
| 16404 | 16380 | |
| 16405 | 16381 | fn airErrorName(self: *Self, inst: Air.Inst.Index) !void { |
| 16406 | const pt = self.pt; | |
| 16407 | const mod = pt.zcu; | |
| 16408 | 16382 | const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op; |
| 16409 | 16383 | |
| 16410 | 16384 | const err_ty = self.typeOf(un_op); |
| ... | ... | @@ -16416,7 +16390,8 @@ fn airErrorName(self: *Self, inst: Air.Inst.Index) !void { |
| 16416 | 16390 | const addr_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp); |
| 16417 | 16391 | const addr_lock = self.register_manager.lockRegAssumeUnused(addr_reg); |
| 16418 | 16392 | defer self.register_manager.unlockReg(addr_lock); |
| 16419 | try self.genLazySymbolRef(.lea, addr_reg, link.File.LazySymbol.initDecl(.const_data, null, mod)); | |
| 16393 | const anyerror_lazy_sym: link.File.LazySymbol = .{ .kind = .const_data, .ty = .anyerror_type }; | |
| 16394 | try self.genLazySymbolRef(.lea, addr_reg, anyerror_lazy_sym); | |
| 16420 | 16395 | |
| 16421 | 16396 | const start_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp); |
| 16422 | 16397 | const start_lock = self.register_manager.lockRegAssumeUnused(start_reg); |
| ... | ... | @@ -18808,7 +18783,7 @@ fn limitImmediateType(self: *Self, operand: Air.Inst.Ref, comptime T: type) !MCV |
| 18808 | 18783 | |
| 18809 | 18784 | fn genTypedValue(self: *Self, val: Value) InnerError!MCValue { |
| 18810 | 18785 | const pt = self.pt; |
| 18811 | return switch (try codegen.genTypedValue(self.bin_file, pt, self.src_loc, val, self.owner.getDecl(pt.zcu))) { | |
| 18786 | return switch (try codegen.genTypedValue(self.bin_file, pt, self.src_loc, val, self.target.*)) { | |
| 18812 | 18787 | .mcv => |mcv| switch (mcv) { |
| 18813 | 18788 | .none => .none, |
| 18814 | 18789 | .undef => .undef, |
src/arch/x86_64/Emit.zig+11-11| ... | ... | @@ -40,7 +40,7 @@ pub fn emitMir(emit: *Emit) Error!void { |
| 40 | 40 | .offset = end_offset - 4, |
| 41 | 41 | .length = @intCast(end_offset - start_offset), |
| 42 | 42 | }), |
| 43 | .linker_extern_fn => |symbol| if (emit.lower.bin_file.cast(link.File.Elf)) |elf_file| { | |
| 43 | .linker_extern_fn => |symbol| if (emit.lower.bin_file.cast(.elf)) |elf_file| { | |
| 44 | 44 | // Add relocation to the decl. |
| 45 | 45 | const zo = elf_file.zigObjectPtr().?; |
| 46 | 46 | const atom_ptr = zo.symbol(symbol.atom_index).atom(elf_file).?; |
| ... | ... | @@ -50,7 +50,7 @@ pub fn emitMir(emit: *Emit) Error!void { |
| 50 | 50 | .r_info = (@as(u64, @intCast(symbol.sym_index)) << 32) | r_type, |
| 51 | 51 | .r_addend = -4, |
| 52 | 52 | }); |
| 53 | } else if (emit.lower.bin_file.cast(link.File.MachO)) |macho_file| { | |
| 53 | } else if (emit.lower.bin_file.cast(.macho)) |macho_file| { | |
| 54 | 54 | // Add relocation to the decl. |
| 55 | 55 | const zo = macho_file.getZigObject().?; |
| 56 | 56 | const atom = zo.symbols.items[symbol.atom_index].getAtom(macho_file).?; |
| ... | ... | @@ -67,7 +67,7 @@ pub fn emitMir(emit: *Emit) Error!void { |
| 67 | 67 | .symbolnum = @intCast(symbol.sym_index), |
| 68 | 68 | }, |
| 69 | 69 | }); |
| 70 | } else if (emit.lower.bin_file.cast(link.File.Coff)) |coff_file| { | |
| 70 | } else if (emit.lower.bin_file.cast(.coff)) |coff_file| { | |
| 71 | 71 | // Add relocation to the decl. |
| 72 | 72 | const atom_index = coff_file.getAtomIndexForSymbol( |
| 73 | 73 | .{ .sym_index = symbol.atom_index, .file = null }, |
| ... | ... | @@ -88,7 +88,7 @@ pub fn emitMir(emit: *Emit) Error!void { |
| 88 | 88 | @tagName(emit.lower.bin_file.tag), |
| 89 | 89 | }), |
| 90 | 90 | .linker_tlsld => |data| { |
| 91 | const elf_file = emit.lower.bin_file.cast(link.File.Elf).?; | |
| 91 | const elf_file = emit.lower.bin_file.cast(.elf).?; | |
| 92 | 92 | const zo = elf_file.zigObjectPtr().?; |
| 93 | 93 | const atom = zo.symbol(data.atom_index).atom(elf_file).?; |
| 94 | 94 | const r_type = @intFromEnum(std.elf.R_X86_64.TLSLD); |
| ... | ... | @@ -99,7 +99,7 @@ pub fn emitMir(emit: *Emit) Error!void { |
| 99 | 99 | }); |
| 100 | 100 | }, |
| 101 | 101 | .linker_dtpoff => |data| { |
| 102 | const elf_file = emit.lower.bin_file.cast(link.File.Elf).?; | |
| 102 | const elf_file = emit.lower.bin_file.cast(.elf).?; | |
| 103 | 103 | const zo = elf_file.zigObjectPtr().?; |
| 104 | 104 | const atom = zo.symbol(data.atom_index).atom(elf_file).?; |
| 105 | 105 | const r_type = @intFromEnum(std.elf.R_X86_64.DTPOFF32); |
| ... | ... | @@ -109,7 +109,7 @@ pub fn emitMir(emit: *Emit) Error!void { |
| 109 | 109 | .r_addend = 0, |
| 110 | 110 | }); |
| 111 | 111 | }, |
| 112 | .linker_reloc => |data| if (emit.lower.bin_file.cast(link.File.Elf)) |elf_file| { | |
| 112 | .linker_reloc => |data| if (emit.lower.bin_file.cast(.elf)) |elf_file| { | |
| 113 | 113 | const is_obj_or_static_lib = switch (emit.lower.output_mode) { |
| 114 | 114 | .Exe => false, |
| 115 | 115 | .Obj => true, |
| ... | ... | @@ -157,7 +157,7 @@ pub fn emitMir(emit: *Emit) Error!void { |
| 157 | 157 | }); |
| 158 | 158 | } |
| 159 | 159 | } |
| 160 | } else if (emit.lower.bin_file.cast(link.File.MachO)) |macho_file| { | |
| 160 | } else if (emit.lower.bin_file.cast(.macho)) |macho_file| { | |
| 161 | 161 | const is_obj_or_static_lib = switch (emit.lower.output_mode) { |
| 162 | 162 | .Exe => false, |
| 163 | 163 | .Obj => true, |
| ... | ... | @@ -196,11 +196,11 @@ pub fn emitMir(emit: *Emit) Error!void { |
| 196 | 196 | .linker_got, |
| 197 | 197 | .linker_direct, |
| 198 | 198 | .linker_import, |
| 199 | => |symbol| if (emit.lower.bin_file.cast(link.File.Elf)) |_| { | |
| 199 | => |symbol| if (emit.lower.bin_file.cast(.elf)) |_| { | |
| 200 | 200 | unreachable; |
| 201 | } else if (emit.lower.bin_file.cast(link.File.MachO)) |_| { | |
| 201 | } else if (emit.lower.bin_file.cast(.macho)) |_| { | |
| 202 | 202 | unreachable; |
| 203 | } else if (emit.lower.bin_file.cast(link.File.Coff)) |coff_file| { | |
| 203 | } else if (emit.lower.bin_file.cast(.coff)) |coff_file| { | |
| 204 | 204 | const atom_index = coff_file.getAtomIndexForSymbol(.{ |
| 205 | 205 | .sym_index = symbol.atom_index, |
| 206 | 206 | .file = null, |
| ... | ... | @@ -222,7 +222,7 @@ pub fn emitMir(emit: *Emit) Error!void { |
| 222 | 222 | .pcrel = true, |
| 223 | 223 | .length = 2, |
| 224 | 224 | }); |
| 225 | } else if (emit.lower.bin_file.cast(link.File.Plan9)) |p9_file| { | |
| 225 | } else if (emit.lower.bin_file.cast(.plan9)) |p9_file| { | |
| 226 | 226 | const atom_index = symbol.atom_index; |
| 227 | 227 | try p9_file.addReloc(atom_index, .{ // TODO we may need to add a .type field to the relocs if they are .linker_got instead of just .linker_direct |
| 228 | 228 | .target = symbol.sym_index, // we set sym_index to just be the atom index |
src/arch/x86_64/Lower.zig+2-2| ... | ... | @@ -348,7 +348,7 @@ fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand) |
| 348 | 348 | assert(mem_op.sib.disp == 0); |
| 349 | 349 | assert(mem_op.sib.scale_index.scale == 0); |
| 350 | 350 | |
| 351 | if (lower.bin_file.cast(link.File.Elf)) |elf_file| { | |
| 351 | if (lower.bin_file.cast(.elf)) |elf_file| { | |
| 352 | 352 | const zo = elf_file.zigObjectPtr().?; |
| 353 | 353 | const elf_sym = zo.symbol(sym.sym_index); |
| 354 | 354 | |
| ... | ... | @@ -424,7 +424,7 @@ fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand) |
| 424 | 424 | }, |
| 425 | 425 | else => unreachable, |
| 426 | 426 | }; |
| 427 | } else if (lower.bin_file.cast(link.File.MachO)) |macho_file| { | |
| 427 | } else if (lower.bin_file.cast(.macho)) |macho_file| { | |
| 428 | 428 | const zo = macho_file.getZigObject().?; |
| 429 | 429 | const macho_sym = zo.symbols.items[sym.sym_index]; |
| 430 | 430 |
src/codegen.zig+71-132| ... | ... | @@ -17,7 +17,7 @@ const ErrorMsg = Zcu.ErrorMsg; |
| 17 | 17 | const InternPool = @import("InternPool.zig"); |
| 18 | 18 | const Liveness = @import("Liveness.zig"); |
| 19 | 19 | const Zcu = @import("Zcu.zig"); |
| 20 | const Target = std.Target; | |
| 20 | ||
| 21 | 21 | const Type = @import("Type.zig"); |
| 22 | 22 | const Value = @import("Value.zig"); |
| 23 | 23 | const Zir = std.zig.Zir; |
| ... | ... | @@ -26,7 +26,7 @@ const dev = @import("dev.zig"); |
| 26 | 26 | |
| 27 | 27 | pub const Result = union(enum) { |
| 28 | 28 | /// The `code` parameter passed to `generateSymbol` has the value ok. |
| 29 | ok: void, | |
| 29 | ok, | |
| 30 | 30 | |
| 31 | 31 | /// There was a codegen error. |
| 32 | 32 | fail: *ErrorMsg, |
| ... | ... | @@ -39,7 +39,7 @@ pub const CodeGenError = error{ |
| 39 | 39 | }; |
| 40 | 40 | |
| 41 | 41 | pub const DebugInfoOutput = union(enum) { |
| 42 | dwarf: *link.File.Dwarf.DeclState, | |
| 42 | dwarf: *link.File.Dwarf.NavState, | |
| 43 | 43 | plan9: *link.File.Plan9.DebugInfoOutput, |
| 44 | 44 | none, |
| 45 | 45 | }; |
| ... | ... | @@ -73,9 +73,7 @@ pub fn generateFunction( |
| 73 | 73 | ) CodeGenError!Result { |
| 74 | 74 | const zcu = pt.zcu; |
| 75 | 75 | const func = zcu.funcInfo(func_index); |
| 76 | const decl = zcu.declPtr(func.owner_decl); | |
| 77 | const namespace = zcu.namespacePtr(decl.src_namespace); | |
| 78 | const target = namespace.fileScope(zcu).mod.resolved_target.result; | |
| 76 | const target = zcu.navFileScope(func.owner_nav).mod.resolved_target.result; | |
| 79 | 77 | switch (target_util.zigBackend(target, false)) { |
| 80 | 78 | else => unreachable, |
| 81 | 79 | inline .stage2_aarch64, |
| ... | ... | @@ -100,10 +98,8 @@ pub fn generateLazyFunction( |
| 100 | 98 | debug_output: DebugInfoOutput, |
| 101 | 99 | ) CodeGenError!Result { |
| 102 | 100 | const zcu = pt.zcu; |
| 103 | const decl_index = lazy_sym.ty.getOwnerDecl(zcu); | |
| 104 | const decl = zcu.declPtr(decl_index); | |
| 105 | const namespace = zcu.namespacePtr(decl.src_namespace); | |
| 106 | const target = namespace.fileScope(zcu).mod.resolved_target.result; | |
| 101 | const file = Type.fromInterned(lazy_sym.ty).typeDeclInstAllowGeneratedTag(zcu).?.resolveFull(&zcu.intern_pool).file; | |
| 102 | const target = zcu.fileByIndex(file).mod.resolved_target.result; | |
| 107 | 103 | switch (target_util.zigBackend(target, false)) { |
| 108 | 104 | else => unreachable, |
| 109 | 105 | inline .stage2_x86_64, |
| ... | ... | @@ -115,7 +111,7 @@ pub fn generateLazyFunction( |
| 115 | 111 | } |
| 116 | 112 | } |
| 117 | 113 | |
| 118 | fn writeFloat(comptime F: type, f: F, target: Target, endian: std.builtin.Endian, code: []u8) void { | |
| 114 | fn writeFloat(comptime F: type, f: F, target: std.Target, endian: std.builtin.Endian, code: []u8) void { | |
| 119 | 115 | _ = target; |
| 120 | 116 | const bits = @typeInfo(F).Float.bits; |
| 121 | 117 | const Int = @Type(.{ .Int = .{ .signedness = .unsigned, .bits = bits } }); |
| ... | ... | @@ -147,7 +143,7 @@ pub fn generateLazySymbol( |
| 147 | 143 | |
| 148 | 144 | log.debug("generateLazySymbol: kind = {s}, ty = {}", .{ |
| 149 | 145 | @tagName(lazy_sym.kind), |
| 150 | lazy_sym.ty.fmt(pt), | |
| 146 | Type.fromInterned(lazy_sym.ty).fmt(pt), | |
| 151 | 147 | }); |
| 152 | 148 | |
| 153 | 149 | if (lazy_sym.kind == .code) { |
| ... | ... | @@ -155,7 +151,7 @@ pub fn generateLazySymbol( |
| 155 | 151 | return generateLazyFunction(bin_file, pt, src_loc, lazy_sym, code, debug_output); |
| 156 | 152 | } |
| 157 | 153 | |
| 158 | if (lazy_sym.ty.isAnyError(pt.zcu)) { | |
| 154 | if (lazy_sym.ty == .anyerror_type) { | |
| 159 | 155 | alignment.* = .@"4"; |
| 160 | 156 | const err_names = ip.global_error_set.getNamesFromMainThread(); |
| 161 | 157 | mem.writeInt(u32, try code.addManyAsArray(4), @intCast(err_names.len), endian); |
| ... | ... | @@ -171,9 +167,10 @@ pub fn generateLazySymbol( |
| 171 | 167 | } |
| 172 | 168 | mem.writeInt(u32, code.items[offset..][0..4], @intCast(code.items.len), endian); |
| 173 | 169 | return Result.ok; |
| 174 | } else if (lazy_sym.ty.zigTypeTag(pt.zcu) == .Enum) { | |
| 170 | } else if (Type.fromInterned(lazy_sym.ty).zigTypeTag(pt.zcu) == .Enum) { | |
| 175 | 171 | alignment.* = .@"1"; |
| 176 | const tag_names = lazy_sym.ty.enumFields(pt.zcu); | |
| 172 | const enum_ty = Type.fromInterned(lazy_sym.ty); | |
| 173 | const tag_names = enum_ty.enumFields(pt.zcu); | |
| 177 | 174 | for (0..tag_names.len) |tag_index| { |
| 178 | 175 | const tag_name = tag_names.get(ip)[tag_index].toSlice(ip); |
| 179 | 176 | try code.ensureUnusedCapacity(tag_name.len + 1); |
| ... | ... | @@ -185,7 +182,7 @@ pub fn generateLazySymbol( |
| 185 | 182 | gpa, |
| 186 | 183 | src_loc, |
| 187 | 184 | "TODO implement generateLazySymbol for {s} {}", |
| 188 | .{ @tagName(lazy_sym.kind), lazy_sym.ty.fmt(pt) }, | |
| 185 | .{ @tagName(lazy_sym.kind), Type.fromInterned(lazy_sym.ty).fmt(pt) }, | |
| 189 | 186 | ) }; |
| 190 | 187 | } |
| 191 | 188 | |
| ... | ... | @@ -251,7 +248,7 @@ pub fn generateSymbol( |
| 251 | 248 | }), |
| 252 | 249 | }, |
| 253 | 250 | .variable, |
| 254 | .extern_func, | |
| 251 | .@"extern", | |
| 255 | 252 | .func, |
| 256 | 253 | .enum_literal, |
| 257 | 254 | .empty_enum_value, |
| ... | ... | @@ -651,8 +648,8 @@ fn lowerPtr( |
| 651 | 648 | const ptr = zcu.intern_pool.indexToKey(ptr_val).ptr; |
| 652 | 649 | const offset: u64 = prev_offset + ptr.byte_offset; |
| 653 | 650 | return switch (ptr.base_addr) { |
| 654 | .decl => |decl| try lowerDeclRef(bin_file, pt, src_loc, decl, code, debug_output, reloc_info, offset), | |
| 655 | .anon_decl => |ad| try lowerAnonDeclRef(bin_file, pt, src_loc, ad, code, debug_output, reloc_info, offset), | |
| 651 | .nav => |nav| try lowerNavRef(bin_file, pt, src_loc, nav, code, debug_output, reloc_info, offset), | |
| 652 | .uav => |uav| try lowerUavRef(bin_file, pt, src_loc, uav, code, debug_output, reloc_info, offset), | |
| 656 | 653 | .int => try generateSymbol(bin_file, pt, src_loc, try pt.intValue(Type.usize, offset), code, debug_output, reloc_info), |
| 657 | 654 | .eu_payload => |eu_ptr| try lowerPtr( |
| 658 | 655 | bin_file, |
| ... | ... | @@ -705,11 +702,11 @@ const RelocInfo = struct { |
| 705 | 702 | parent_atom_index: u32, |
| 706 | 703 | }; |
| 707 | 704 | |
| 708 | fn lowerAnonDeclRef( | |
| 705 | fn lowerUavRef( | |
| 709 | 706 | lf: *link.File, |
| 710 | 707 | pt: Zcu.PerThread, |
| 711 | 708 | src_loc: Zcu.LazySrcLoc, |
| 712 | anon_decl: InternPool.Key.Ptr.BaseAddr.AnonDecl, | |
| 709 | uav: InternPool.Key.Ptr.BaseAddr.Uav, | |
| 713 | 710 | code: *std.ArrayList(u8), |
| 714 | 711 | debug_output: DebugInfoOutput, |
| 715 | 712 | reloc_info: RelocInfo, |
| ... | ... | @@ -720,23 +717,23 @@ fn lowerAnonDeclRef( |
| 720 | 717 | const target = lf.comp.root_mod.resolved_target.result; |
| 721 | 718 | |
| 722 | 719 | const ptr_width_bytes = @divExact(target.ptrBitWidth(), 8); |
| 723 | const decl_val = anon_decl.val; | |
| 724 | const decl_ty = Type.fromInterned(ip.typeOf(decl_val)); | |
| 725 | log.debug("lowerAnonDecl: ty = {}", .{decl_ty.fmt(pt)}); | |
| 726 | const is_fn_body = decl_ty.zigTypeTag(pt.zcu) == .Fn; | |
| 727 | if (!is_fn_body and !decl_ty.hasRuntimeBits(pt)) { | |
| 720 | const uav_val = uav.val; | |
| 721 | const uav_ty = Type.fromInterned(ip.typeOf(uav_val)); | |
| 722 | log.debug("lowerUavRef: ty = {}", .{uav_ty.fmt(pt)}); | |
| 723 | const is_fn_body = uav_ty.zigTypeTag(pt.zcu) == .Fn; | |
| 724 | if (!is_fn_body and !uav_ty.hasRuntimeBits(pt)) { | |
| 728 | 725 | try code.appendNTimes(0xaa, ptr_width_bytes); |
| 729 | 726 | return Result.ok; |
| 730 | 727 | } |
| 731 | 728 | |
| 732 | const decl_align = ip.indexToKey(anon_decl.orig_ty).ptr_type.flags.alignment; | |
| 733 | const res = try lf.lowerAnonDecl(pt, decl_val, decl_align, src_loc); | |
| 729 | const uav_align = ip.indexToKey(uav.orig_ty).ptr_type.flags.alignment; | |
| 730 | const res = try lf.lowerUav(pt, uav_val, uav_align, src_loc); | |
| 734 | 731 | switch (res) { |
| 735 | .ok => {}, | |
| 732 | .mcv => {}, | |
| 736 | 733 | .fail => |em| return .{ .fail = em }, |
| 737 | 734 | } |
| 738 | 735 | |
| 739 | const vaddr = try lf.getAnonDeclVAddr(decl_val, .{ | |
| 736 | const vaddr = try lf.getUavVAddr(uav_val, .{ | |
| 740 | 737 | .parent_atom_index = reloc_info.parent_atom_index, |
| 741 | 738 | .offset = code.items.len, |
| 742 | 739 | .addend = @intCast(offset), |
| ... | ... | @@ -752,11 +749,11 @@ fn lowerAnonDeclRef( |
| 752 | 749 | return Result.ok; |
| 753 | 750 | } |
| 754 | 751 | |
| 755 | fn lowerDeclRef( | |
| 752 | fn lowerNavRef( | |
| 756 | 753 | lf: *link.File, |
| 757 | 754 | pt: Zcu.PerThread, |
| 758 | 755 | src_loc: Zcu.LazySrcLoc, |
| 759 | decl_index: InternPool.DeclIndex, | |
| 756 | nav_index: InternPool.Nav.Index, | |
| 760 | 757 | code: *std.ArrayList(u8), |
| 761 | 758 | debug_output: DebugInfoOutput, |
| 762 | 759 | reloc_info: RelocInfo, |
| ... | ... | @@ -765,18 +762,18 @@ fn lowerDeclRef( |
| 765 | 762 | _ = src_loc; |
| 766 | 763 | _ = debug_output; |
| 767 | 764 | const zcu = pt.zcu; |
| 768 | const decl = zcu.declPtr(decl_index); | |
| 769 | const namespace = zcu.namespacePtr(decl.src_namespace); | |
| 770 | const target = namespace.fileScope(zcu).mod.resolved_target.result; | |
| 765 | const ip = &zcu.intern_pool; | |
| 766 | const target = zcu.navFileScope(nav_index).mod.resolved_target.result; | |
| 771 | 767 | |
| 772 | 768 | const ptr_width = target.ptrBitWidth(); |
| 773 | const is_fn_body = decl.typeOf(zcu).zigTypeTag(zcu) == .Fn; | |
| 774 | if (!is_fn_body and !decl.typeOf(zcu).hasRuntimeBits(pt)) { | |
| 769 | const nav_ty = Type.fromInterned(ip.getNav(nav_index).typeOf(ip)); | |
| 770 | const is_fn_body = nav_ty.zigTypeTag(zcu) == .Fn; | |
| 771 | if (!is_fn_body and !nav_ty.hasRuntimeBits(pt)) { | |
| 775 | 772 | try code.appendNTimes(0xaa, @divExact(ptr_width, 8)); |
| 776 | 773 | return Result.ok; |
| 777 | 774 | } |
| 778 | 775 | |
| 779 | const vaddr = try lf.getDeclVAddr(pt, decl_index, .{ | |
| 776 | const vaddr = try lf.getNavVAddr(pt, nav_index, .{ | |
| 780 | 777 | .parent_atom_index = reloc_info.parent_atom_index, |
| 781 | 778 | .offset = code.items.len, |
| 782 | 779 | .addend = @intCast(offset), |
| ... | ... | @@ -848,34 +845,21 @@ pub const GenResult = union(enum) { |
| 848 | 845 | } |
| 849 | 846 | }; |
| 850 | 847 | |
| 851 | fn genDeclRef( | |
| 848 | fn genNavRef( | |
| 852 | 849 | lf: *link.File, |
| 853 | 850 | pt: Zcu.PerThread, |
| 854 | 851 | src_loc: Zcu.LazySrcLoc, |
| 855 | 852 | val: Value, |
| 856 | ptr_decl_index: InternPool.DeclIndex, | |
| 853 | ref_nav_index: InternPool.Nav.Index, | |
| 854 | target: std.Target, | |
| 857 | 855 | ) CodeGenError!GenResult { |
| 858 | 856 | const zcu = pt.zcu; |
| 859 | 857 | const ip = &zcu.intern_pool; |
| 860 | 858 | const ty = val.typeOf(zcu); |
| 861 | log.debug("genDeclRef: val = {}", .{val.fmtValue(pt)}); | |
| 862 | ||
| 863 | const ptr_decl = zcu.declPtr(ptr_decl_index); | |
| 864 | const namespace = zcu.namespacePtr(ptr_decl.src_namespace); | |
| 865 | const target = namespace.fileScope(zcu).mod.resolved_target.result; | |
| 866 | ||
| 867 | const ptr_bits = target.ptrBitWidth(); | |
| 868 | const ptr_bytes: u64 = @divExact(ptr_bits, 8); | |
| 869 | ||
| 870 | const decl_index = switch (ip.indexToKey(ptr_decl.val.toIntern())) { | |
| 871 | .func => |func| func.owner_decl, | |
| 872 | .extern_func => |extern_func| extern_func.decl, | |
| 873 | else => ptr_decl_index, | |
| 874 | }; | |
| 875 | const decl = zcu.declPtr(decl_index); | |
| 859 | log.debug("genNavRef: val = {}", .{val.fmtValue(pt)}); | |
| 876 | 860 | |
| 877 | if (!decl.typeOf(zcu).isFnOrHasRuntimeBitsIgnoreComptime(pt)) { | |
| 878 | const imm: u64 = switch (ptr_bytes) { | |
| 861 | if (!ty.isFnOrHasRuntimeBitsIgnoreComptime(pt)) { | |
| 862 | const imm: u64 = switch (@divExact(target.ptrBitWidth(), 8)) { | |
| 879 | 863 | 1 => 0xaa, |
| 880 | 864 | 2 => 0xaaaa, |
| 881 | 865 | 4 => 0xaaaaaaaa, |
| ... | ... | @@ -900,96 +884,56 @@ fn genDeclRef( |
| 900 | 884 | } |
| 901 | 885 | } |
| 902 | 886 | |
| 903 | const decl_namespace = zcu.namespacePtr(decl.src_namespace); | |
| 904 | const single_threaded = decl_namespace.fileScope(zcu).mod.single_threaded; | |
| 905 | const is_threadlocal = val.isPtrToThreadLocal(zcu) and !single_threaded; | |
| 906 | const is_extern = decl.isExtern(zcu); | |
| 907 | ||
| 908 | if (lf.cast(link.File.Elf)) |elf_file| { | |
| 887 | const nav_index, const is_extern, const lib_name, const is_threadlocal = switch (ip.indexToKey(zcu.navValue(ref_nav_index).toIntern())) { | |
| 888 | .func => |func| .{ func.owner_nav, false, .none, false }, | |
| 889 | .variable => |variable| .{ variable.owner_nav, false, variable.lib_name, variable.is_threadlocal }, | |
| 890 | .@"extern" => |@"extern"| .{ @"extern".owner_nav, true, @"extern".lib_name, @"extern".is_threadlocal }, | |
| 891 | else => .{ ref_nav_index, false, .none, false }, | |
| 892 | }; | |
| 893 | const single_threaded = zcu.navFileScope(nav_index).mod.single_threaded; | |
| 894 | const name = ip.getNav(nav_index).name; | |
| 895 | if (lf.cast(.elf)) |elf_file| { | |
| 909 | 896 | const zo = elf_file.zigObjectPtr().?; |
| 910 | 897 | if (is_extern) { |
| 911 | const name = decl.name.toSlice(ip); | |
| 912 | 898 | // TODO audit this |
| 913 | const lib_name = if (decl.getOwnedVariable(zcu)) |ov| ov.lib_name.toSlice(ip) else null; | |
| 914 | const sym_index = try elf_file.getGlobalSymbol(name, lib_name); | |
| 899 | const sym_index = try elf_file.getGlobalSymbol(name.toSlice(ip), lib_name.toSlice(ip)); | |
| 915 | 900 | zo.symbol(sym_index).flags.needs_got = true; |
| 916 | 901 | return GenResult.mcv(.{ .load_symbol = sym_index }); |
| 917 | 902 | } |
| 918 | const sym_index = try zo.getOrCreateMetadataForDecl(elf_file, decl_index); | |
| 919 | if (is_threadlocal) { | |
| 903 | const sym_index = try zo.getOrCreateMetadataForNav(elf_file, nav_index); | |
| 904 | if (!single_threaded and is_threadlocal) { | |
| 920 | 905 | return GenResult.mcv(.{ .load_tlv = sym_index }); |
| 921 | 906 | } |
| 922 | 907 | return GenResult.mcv(.{ .load_symbol = sym_index }); |
| 923 | } else if (lf.cast(link.File.MachO)) |macho_file| { | |
| 908 | } else if (lf.cast(.macho)) |macho_file| { | |
| 924 | 909 | const zo = macho_file.getZigObject().?; |
| 925 | 910 | if (is_extern) { |
| 926 | const name = decl.name.toSlice(ip); | |
| 927 | const lib_name = if (decl.getOwnedVariable(zcu)) |ov| ov.lib_name.toSlice(ip) else null; | |
| 928 | const sym_index = try macho_file.getGlobalSymbol(name, lib_name); | |
| 911 | const sym_index = try macho_file.getGlobalSymbol(name.toSlice(ip), lib_name.toSlice(ip)); | |
| 929 | 912 | zo.symbols.items[sym_index].setSectionFlags(.{ .needs_got = true }); |
| 930 | 913 | return GenResult.mcv(.{ .load_symbol = sym_index }); |
| 931 | 914 | } |
| 932 | const sym_index = try zo.getOrCreateMetadataForDecl(macho_file, decl_index); | |
| 915 | const sym_index = try zo.getOrCreateMetadataForNav(macho_file, nav_index); | |
| 933 | 916 | const sym = zo.symbols.items[sym_index]; |
| 934 | if (is_threadlocal) { | |
| 917 | if (!single_threaded and is_threadlocal) { | |
| 935 | 918 | return GenResult.mcv(.{ .load_tlv = sym.nlist_idx }); |
| 936 | 919 | } |
| 937 | 920 | return GenResult.mcv(.{ .load_symbol = sym.nlist_idx }); |
| 938 | } else if (lf.cast(link.File.Coff)) |coff_file| { | |
| 921 | } else if (lf.cast(.coff)) |coff_file| { | |
| 939 | 922 | if (is_extern) { |
| 940 | const name = decl.name.toSlice(ip); | |
| 941 | 923 | // TODO audit this |
| 942 | const lib_name = if (decl.getOwnedVariable(zcu)) |ov| ov.lib_name.toSlice(ip) else null; | |
| 943 | const global_index = try coff_file.getGlobalSymbol(name, lib_name); | |
| 924 | const global_index = try coff_file.getGlobalSymbol(name.toSlice(ip), lib_name.toSlice(ip)); | |
| 944 | 925 | try coff_file.need_got_table.put(gpa, global_index, {}); // needs GOT |
| 945 | 926 | return GenResult.mcv(.{ .load_got = link.File.Coff.global_symbol_bit | global_index }); |
| 946 | 927 | } |
| 947 | const atom_index = try coff_file.getOrCreateAtomForDecl(decl_index); | |
| 928 | const atom_index = try coff_file.getOrCreateAtomForNav(nav_index); | |
| 948 | 929 | const sym_index = coff_file.getAtom(atom_index).getSymbolIndex().?; |
| 949 | 930 | return GenResult.mcv(.{ .load_got = sym_index }); |
| 950 | } else if (lf.cast(link.File.Plan9)) |p9| { | |
| 951 | const atom_index = try p9.seeDecl(decl_index); | |
| 931 | } else if (lf.cast(.plan9)) |p9| { | |
| 932 | const atom_index = try p9.seeNav(pt, nav_index); | |
| 952 | 933 | const atom = p9.getAtom(atom_index); |
| 953 | 934 | return GenResult.mcv(.{ .memory = atom.getOffsetTableAddress(p9) }); |
| 954 | 935 | } else { |
| 955 | return GenResult.fail(gpa, src_loc, "TODO genDeclRef for target {}", .{target}); | |
| 956 | } | |
| 957 | } | |
| 958 | ||
| 959 | fn genUnnamedConst( | |
| 960 | lf: *link.File, | |
| 961 | pt: Zcu.PerThread, | |
| 962 | src_loc: Zcu.LazySrcLoc, | |
| 963 | val: Value, | |
| 964 | owner_decl_index: InternPool.DeclIndex, | |
| 965 | ) CodeGenError!GenResult { | |
| 966 | const gpa = lf.comp.gpa; | |
| 967 | log.debug("genUnnamedConst: val = {}", .{val.fmtValue(pt)}); | |
| 968 | ||
| 969 | const local_sym_index = lf.lowerUnnamedConst(pt, val, owner_decl_index) catch |err| { | |
| 970 | return GenResult.fail(gpa, src_loc, "lowering unnamed constant failed: {s}", .{@errorName(err)}); | |
| 971 | }; | |
| 972 | switch (lf.tag) { | |
| 973 | .elf => { | |
| 974 | return GenResult.mcv(.{ .load_symbol = local_sym_index }); | |
| 975 | }, | |
| 976 | .macho => { | |
| 977 | const macho_file = lf.cast(link.File.MachO).?; | |
| 978 | const local = macho_file.getZigObject().?.symbols.items[local_sym_index]; | |
| 979 | return GenResult.mcv(.{ .load_symbol = local.nlist_idx }); | |
| 980 | }, | |
| 981 | .coff => { | |
| 982 | return GenResult.mcv(.{ .load_direct = local_sym_index }); | |
| 983 | }, | |
| 984 | .plan9 => { | |
| 985 | const atom_index = local_sym_index; // plan9 returns the atom_index | |
| 986 | return GenResult.mcv(.{ .load_direct = atom_index }); | |
| 987 | }, | |
| 988 | ||
| 989 | .c => return GenResult.fail(gpa, src_loc, "TODO genUnnamedConst for -ofmt=c", .{}), | |
| 990 | .wasm => return GenResult.fail(gpa, src_loc, "TODO genUnnamedConst for wasm", .{}), | |
| 991 | .spirv => return GenResult.fail(gpa, src_loc, "TODO genUnnamedConst for spirv", .{}), | |
| 992 | .nvptx => return GenResult.fail(gpa, src_loc, "TODO genUnnamedConst for nvptx", .{}), | |
| 936 | return GenResult.fail(gpa, src_loc, "TODO genNavRef for target {}", .{target}); | |
| 993 | 937 | } |
| 994 | 938 | } |
| 995 | 939 | |
| ... | ... | @@ -998,7 +942,7 @@ pub fn genTypedValue( |
| 998 | 942 | pt: Zcu.PerThread, |
| 999 | 943 | src_loc: Zcu.LazySrcLoc, |
| 1000 | 944 | val: Value, |
| 1001 | owner_decl_index: InternPool.DeclIndex, | |
| 945 | target: std.Target, | |
| 1002 | 946 | ) CodeGenError!GenResult { |
| 1003 | 947 | const zcu = pt.zcu; |
| 1004 | 948 | const ip = &zcu.intern_pool; |
| ... | ... | @@ -1010,14 +954,9 @@ pub fn genTypedValue( |
| 1010 | 954 | return GenResult.mcv(.undef); |
| 1011 | 955 | } |
| 1012 | 956 | |
| 1013 | const owner_decl = zcu.declPtr(owner_decl_index); | |
| 1014 | const namespace = zcu.namespacePtr(owner_decl.src_namespace); | |
| 1015 | const target = namespace.fileScope(zcu).mod.resolved_target.result; | |
| 1016 | const ptr_bits = target.ptrBitWidth(); | |
| 1017 | ||
| 1018 | 957 | if (!ty.isSlice(zcu)) switch (ip.indexToKey(val.toIntern())) { |
| 1019 | 958 | .ptr => |ptr| if (ptr.byte_offset == 0) switch (ptr.base_addr) { |
| 1020 | .decl => |decl| return genDeclRef(lf, pt, src_loc, val, decl), | |
| 959 | .nav => |nav| return genNavRef(lf, pt, src_loc, val, nav, target), | |
| 1021 | 960 | else => {}, |
| 1022 | 961 | }, |
| 1023 | 962 | else => {}, |
| ... | ... | @@ -1042,7 +981,7 @@ pub fn genTypedValue( |
| 1042 | 981 | }, |
| 1043 | 982 | .Int => { |
| 1044 | 983 | const info = ty.intInfo(zcu); |
| 1045 | if (info.bits <= ptr_bits) { | |
| 984 | if (info.bits <= target.ptrBitWidth()) { | |
| 1046 | 985 | const unsigned: u64 = switch (info.signedness) { |
| 1047 | 986 | .signed => @bitCast(val.toSignedInt(pt)), |
| 1048 | 987 | .unsigned => val.toUnsignedInt(pt), |
| ... | ... | @@ -1060,7 +999,7 @@ pub fn genTypedValue( |
| 1060 | 999 | pt, |
| 1061 | 1000 | src_loc, |
| 1062 | 1001 | val.optionalValue(zcu) orelse return GenResult.mcv(.{ .immediate = 0 }), |
| 1063 | owner_decl_index, | |
| 1002 | target, | |
| 1064 | 1003 | ); |
| 1065 | 1004 | } else if (ty.abiSize(pt) == 1) { |
| 1066 | 1005 | return GenResult.mcv(.{ .immediate = @intFromBool(!val.isNull(zcu)) }); |
| ... | ... | @@ -1073,7 +1012,7 @@ pub fn genTypedValue( |
| 1073 | 1012 | pt, |
| 1074 | 1013 | src_loc, |
| 1075 | 1014 | Value.fromInterned(enum_tag.int), |
| 1076 | owner_decl_index, | |
| 1015 | target, | |
| 1077 | 1016 | ); |
| 1078 | 1017 | }, |
| 1079 | 1018 | .ErrorSet => { |
| ... | ... | @@ -1096,14 +1035,14 @@ pub fn genTypedValue( |
| 1096 | 1035 | .ty = err_type.toIntern(), |
| 1097 | 1036 | .name = err_name, |
| 1098 | 1037 | } })), |
| 1099 | owner_decl_index, | |
| 1038 | target, | |
| 1100 | 1039 | ), |
| 1101 | 1040 | .payload => return genTypedValue( |
| 1102 | 1041 | lf, |
| 1103 | 1042 | pt, |
| 1104 | 1043 | src_loc, |
| 1105 | 1044 | try pt.intValue(err_int_ty, 0), |
| 1106 | owner_decl_index, | |
| 1045 | target, | |
| 1107 | 1046 | ), |
| 1108 | 1047 | } |
| 1109 | 1048 | } |
| ... | ... | @@ -1121,7 +1060,7 @@ pub fn genTypedValue( |
| 1121 | 1060 | else => {}, |
| 1122 | 1061 | } |
| 1123 | 1062 | |
| 1124 | return genUnnamedConst(lf, pt, src_loc, val, owner_decl_index); | |
| 1063 | return lf.lowerUav(pt, val.toIntern(), .none, src_loc); | |
| 1125 | 1064 | } |
| 1126 | 1065 | |
| 1127 | 1066 | pub fn errUnionPayloadOffset(payload_ty: Type, pt: Zcu.PerThread) u64 { |
src/codegen/c.zig+251-229| ... | ... | @@ -38,8 +38,8 @@ pub const CValue = union(enum) { |
| 38 | 38 | /// Index into a tuple's fields |
| 39 | 39 | field: usize, |
| 40 | 40 | /// By-value |
| 41 | decl: InternPool.DeclIndex, | |
| 42 | decl_ref: InternPool.DeclIndex, | |
| 41 | nav: InternPool.Nav.Index, | |
| 42 | nav_ref: InternPool.Nav.Index, | |
| 43 | 43 | /// An undefined value (cannot be dereferenced) |
| 44 | 44 | undef: Type, |
| 45 | 45 | /// Rendered as an identifier (using fmtIdent) |
| ... | ... | @@ -58,19 +58,12 @@ const BlockData = struct { |
| 58 | 58 | pub const CValueMap = std.AutoHashMap(Air.Inst.Ref, CValue); |
| 59 | 59 | |
| 60 | 60 | pub const LazyFnKey = union(enum) { |
| 61 | tag_name: InternPool.DeclIndex, | |
| 62 | never_tail: InternPool.DeclIndex, | |
| 63 | never_inline: InternPool.DeclIndex, | |
| 61 | tag_name: InternPool.Index, | |
| 62 | never_tail: InternPool.Nav.Index, | |
| 63 | never_inline: InternPool.Nav.Index, | |
| 64 | 64 | }; |
| 65 | 65 | pub const LazyFnValue = struct { |
| 66 | 66 | fn_name: CType.Pool.String, |
| 67 | data: Data, | |
| 68 | ||
| 69 | const Data = union { | |
| 70 | tag_name: Type, | |
| 71 | never_tail: void, | |
| 72 | never_inline: void, | |
| 73 | }; | |
| 74 | 67 | }; |
| 75 | 68 | pub const LazyFnMap = std.AutoArrayHashMapUnmanaged(LazyFnKey, LazyFnValue); |
| 76 | 69 | |
| ... | ... | @@ -498,10 +491,11 @@ pub const Function = struct { |
| 498 | 491 | return f.object.dg.fmtIntLiteral(val, .Other); |
| 499 | 492 | } |
| 500 | 493 | |
| 501 | fn getLazyFnName(f: *Function, key: LazyFnKey, data: LazyFnValue.Data) ![]const u8 { | |
| 494 | fn getLazyFnName(f: *Function, key: LazyFnKey) ![]const u8 { | |
| 502 | 495 | const gpa = f.object.dg.gpa; |
| 503 | 496 | const pt = f.object.dg.pt; |
| 504 | 497 | const zcu = pt.zcu; |
| 498 | const ip = &zcu.intern_pool; | |
| 505 | 499 | const ctype_pool = &f.object.dg.ctype_pool; |
| 506 | 500 | |
| 507 | 501 | const gop = try f.lazy_fns.getOrPut(gpa, key); |
| ... | ... | @@ -511,19 +505,19 @@ pub const Function = struct { |
| 511 | 505 | gop.value_ptr.* = .{ |
| 512 | 506 | .fn_name = switch (key) { |
| 513 | 507 | .tag_name, |
| 508 | => |enum_ty| try ctype_pool.fmt(gpa, "zig_{s}_{}__{d}", .{ | |
| 509 | @tagName(key), | |
| 510 | fmtIdent(ip.loadEnumType(enum_ty).name.toSlice(ip)), | |
| 511 | @intFromEnum(enum_ty), | |
| 512 | }), | |
| 514 | 513 | .never_tail, |
| 515 | 514 | .never_inline, |
| 516 | => |owner_decl| try ctype_pool.fmt(gpa, "zig_{s}_{}__{d}", .{ | |
| 515 | => |owner_nav| try ctype_pool.fmt(gpa, "zig_{s}_{}__{d}", .{ | |
| 517 | 516 | @tagName(key), |
| 518 | fmtIdent(zcu.declPtr(owner_decl).name.toSlice(&zcu.intern_pool)), | |
| 519 | @intFromEnum(owner_decl), | |
| 517 | fmtIdent(ip.getNav(owner_nav).name.toSlice(ip)), | |
| 518 | @intFromEnum(owner_nav), | |
| 520 | 519 | }), |
| 521 | 520 | }, |
| 522 | .data = switch (key) { | |
| 523 | .tag_name => .{ .tag_name = data.tag_name }, | |
| 524 | .never_tail => .{ .never_tail = data.never_tail }, | |
| 525 | .never_inline => .{ .never_inline = data.never_inline }, | |
| 526 | }, | |
| 527 | 521 | }; |
| 528 | 522 | } |
| 529 | 523 | return gop.value_ptr.fn_name.toSlice(ctype_pool).?; |
| ... | ... | @@ -618,12 +612,12 @@ pub const DeclGen = struct { |
| 618 | 612 | scratch: std.ArrayListUnmanaged(u32), |
| 619 | 613 | /// Keeps track of anonymous decls that need to be rendered before this |
| 620 | 614 | /// (named) Decl in the output C code. |
| 621 | anon_decl_deps: std.AutoArrayHashMapUnmanaged(InternPool.Index, C.DeclBlock), | |
| 622 | aligned_anon_decls: std.AutoArrayHashMapUnmanaged(InternPool.Index, Alignment), | |
| 615 | uav_deps: std.AutoArrayHashMapUnmanaged(InternPool.Index, C.AvBlock), | |
| 616 | aligned_uavs: std.AutoArrayHashMapUnmanaged(InternPool.Index, Alignment), | |
| 623 | 617 | |
| 624 | 618 | pub const Pass = union(enum) { |
| 625 | decl: InternPool.DeclIndex, | |
| 626 | anon: InternPool.Index, | |
| 619 | nav: InternPool.Nav.Index, | |
| 620 | uav: InternPool.Index, | |
| 627 | 621 | flush, |
| 628 | 622 | }; |
| 629 | 623 | |
| ... | ... | @@ -634,39 +628,37 @@ pub const DeclGen = struct { |
| 634 | 628 | fn fail(dg: *DeclGen, comptime format: []const u8, args: anytype) error{ AnalysisFail, OutOfMemory } { |
| 635 | 629 | @setCold(true); |
| 636 | 630 | const zcu = dg.pt.zcu; |
| 637 | const decl_index = dg.pass.decl; | |
| 638 | const decl = zcu.declPtr(decl_index); | |
| 639 | const src_loc = decl.navSrcLoc(zcu); | |
| 631 | const src_loc = zcu.navSrcLoc(dg.pass.nav); | |
| 640 | 632 | dg.error_msg = try Zcu.ErrorMsg.create(dg.gpa, src_loc, format, args); |
| 641 | 633 | return error.AnalysisFail; |
| 642 | 634 | } |
| 643 | 635 | |
| 644 | fn renderAnonDeclValue( | |
| 636 | fn renderUav( | |
| 645 | 637 | dg: *DeclGen, |
| 646 | 638 | writer: anytype, |
| 647 | anon_decl: InternPool.Key.Ptr.BaseAddr.AnonDecl, | |
| 639 | uav: InternPool.Key.Ptr.BaseAddr.Uav, | |
| 648 | 640 | location: ValueRenderLocation, |
| 649 | 641 | ) error{ OutOfMemory, AnalysisFail }!void { |
| 650 | 642 | const pt = dg.pt; |
| 651 | 643 | const zcu = pt.zcu; |
| 652 | 644 | const ip = &zcu.intern_pool; |
| 653 | 645 | const ctype_pool = &dg.ctype_pool; |
| 654 | const decl_val = Value.fromInterned(anon_decl.val); | |
| 655 | const decl_ty = decl_val.typeOf(zcu); | |
| 646 | const uav_val = Value.fromInterned(uav.val); | |
| 647 | const uav_ty = uav_val.typeOf(zcu); | |
| 656 | 648 | |
| 657 | 649 | // Render an undefined pointer if we have a pointer to a zero-bit or comptime type. |
| 658 | const ptr_ty = Type.fromInterned(anon_decl.orig_ty); | |
| 659 | if (ptr_ty.isPtrAtRuntime(zcu) and !decl_ty.isFnOrHasRuntimeBits(pt)) { | |
| 650 | const ptr_ty = Type.fromInterned(uav.orig_ty); | |
| 651 | if (ptr_ty.isPtrAtRuntime(zcu) and !uav_ty.isFnOrHasRuntimeBits(pt)) { | |
| 660 | 652 | return dg.writeCValue(writer, .{ .undef = ptr_ty }); |
| 661 | 653 | } |
| 662 | 654 | |
| 663 | 655 | // Chase function values in order to be able to reference the original function. |
| 664 | if (decl_val.getFunction(zcu)) |func| | |
| 665 | return dg.renderDeclValue(writer, func.owner_decl, location); | |
| 666 | if (decl_val.getExternFunc(zcu)) |extern_func| | |
| 667 | return dg.renderDeclValue(writer, extern_func.decl, location); | |
| 668 | ||
| 669 | assert(decl_val.getVariable(zcu) == null); | |
| 656 | switch (ip.indexToKey(uav.val)) { | |
| 657 | .variable => unreachable, | |
| 658 | .func => |func| return dg.renderNav(writer, func.owner_nav, location), | |
| 659 | .@"extern" => |@"extern"| return dg.renderNav(writer, @"extern".owner_nav, location), | |
| 660 | else => {}, | |
| 661 | } | |
| 670 | 662 | |
| 671 | 663 | // We shouldn't cast C function pointers as this is UB (when you call |
| 672 | 664 | // them). The analysis until now should ensure that the C function |
| ... | ... | @@ -674,22 +666,22 @@ pub const DeclGen = struct { |
| 674 | 666 | // somewhere and we should let the C compiler tell us about it. |
| 675 | 667 | const ptr_ctype = try dg.ctypeFromType(ptr_ty, .complete); |
| 676 | 668 | const elem_ctype = ptr_ctype.info(ctype_pool).pointer.elem_ctype; |
| 677 | const decl_ctype = try dg.ctypeFromType(decl_ty, .complete); | |
| 678 | const need_cast = !elem_ctype.eql(decl_ctype) and | |
| 679 | (elem_ctype.info(ctype_pool) != .function or decl_ctype.info(ctype_pool) != .function); | |
| 669 | const uav_ctype = try dg.ctypeFromType(uav_ty, .complete); | |
| 670 | const need_cast = !elem_ctype.eql(uav_ctype) and | |
| 671 | (elem_ctype.info(ctype_pool) != .function or uav_ctype.info(ctype_pool) != .function); | |
| 680 | 672 | if (need_cast) { |
| 681 | 673 | try writer.writeAll("(("); |
| 682 | 674 | try dg.renderCType(writer, ptr_ctype); |
| 683 | 675 | try writer.writeByte(')'); |
| 684 | 676 | } |
| 685 | 677 | try writer.writeByte('&'); |
| 686 | try renderAnonDeclName(writer, decl_val); | |
| 678 | try renderUavName(writer, uav_val); | |
| 687 | 679 | if (need_cast) try writer.writeByte(')'); |
| 688 | 680 | |
| 689 | 681 | // Indicate that the anon decl should be rendered to the output so that |
| 690 | 682 | // our reference above is not undefined. |
| 691 | const ptr_type = ip.indexToKey(anon_decl.orig_ty).ptr_type; | |
| 692 | const gop = try dg.anon_decl_deps.getOrPut(dg.gpa, anon_decl.val); | |
| 683 | const ptr_type = ip.indexToKey(uav.orig_ty).ptr_type; | |
| 684 | const gop = try dg.uav_deps.getOrPut(dg.gpa, uav.val); | |
| 693 | 685 | if (!gop.found_existing) gop.value_ptr.* = .{}; |
| 694 | 686 | |
| 695 | 687 | // Only insert an alignment entry if the alignment is greater than ABI |
| ... | ... | @@ -698,7 +690,7 @@ pub const DeclGen = struct { |
| 698 | 690 | if (explicit_alignment != .none) { |
| 699 | 691 | const abi_alignment = Type.fromInterned(ptr_type.child).abiAlignment(pt); |
| 700 | 692 | if (explicit_alignment.order(abi_alignment).compare(.gt)) { |
| 701 | const aligned_gop = try dg.aligned_anon_decls.getOrPut(dg.gpa, anon_decl.val); | |
| 693 | const aligned_gop = try dg.aligned_uavs.getOrPut(dg.gpa, uav.val); | |
| 702 | 694 | aligned_gop.value_ptr.* = if (aligned_gop.found_existing) |
| 703 | 695 | aligned_gop.value_ptr.maxStrict(explicit_alignment) |
| 704 | 696 | else |
| ... | ... | @@ -707,47 +699,49 @@ pub const DeclGen = struct { |
| 707 | 699 | } |
| 708 | 700 | } |
| 709 | 701 | |
| 710 | fn renderDeclValue( | |
| 702 | fn renderNav( | |
| 711 | 703 | dg: *DeclGen, |
| 712 | 704 | writer: anytype, |
| 713 | decl_index: InternPool.DeclIndex, | |
| 705 | nav_index: InternPool.Nav.Index, | |
| 714 | 706 | location: ValueRenderLocation, |
| 715 | 707 | ) error{ OutOfMemory, AnalysisFail }!void { |
| 708 | _ = location; | |
| 716 | 709 | const pt = dg.pt; |
| 717 | 710 | const zcu = pt.zcu; |
| 711 | const ip = &zcu.intern_pool; | |
| 718 | 712 | const ctype_pool = &dg.ctype_pool; |
| 719 | const decl = zcu.declPtr(decl_index); | |
| 720 | assert(decl.has_tv); | |
| 713 | ||
| 714 | // Chase function values in order to be able to reference the original function. | |
| 715 | const owner_nav = switch (ip.indexToKey(zcu.navValue(nav_index).toIntern())) { | |
| 716 | .variable => |variable| variable.owner_nav, | |
| 717 | .func => |func| func.owner_nav, | |
| 718 | .@"extern" => |@"extern"| @"extern".owner_nav, | |
| 719 | else => nav_index, | |
| 720 | }; | |
| 721 | 721 | |
| 722 | 722 | // Render an undefined pointer if we have a pointer to a zero-bit or comptime type. |
| 723 | const decl_ty = decl.typeOf(zcu); | |
| 724 | const ptr_ty = try decl.declPtrType(pt); | |
| 725 | if (!decl_ty.isFnOrHasRuntimeBits(pt)) { | |
| 723 | const nav_ty = Type.fromInterned(ip.getNav(owner_nav).typeOf(ip)); | |
| 724 | const ptr_ty = try pt.navPtrType(owner_nav); | |
| 725 | if (!nav_ty.isFnOrHasRuntimeBits(pt)) { | |
| 726 | 726 | return dg.writeCValue(writer, .{ .undef = ptr_ty }); |
| 727 | 727 | } |
| 728 | 728 | |
| 729 | // Chase function values in order to be able to reference the original function. | |
| 730 | if (decl.val.getFunction(zcu)) |func| if (func.owner_decl != decl_index) | |
| 731 | return dg.renderDeclValue(writer, func.owner_decl, location); | |
| 732 | if (decl.val.getExternFunc(zcu)) |extern_func| if (extern_func.decl != decl_index) | |
| 733 | return dg.renderDeclValue(writer, extern_func.decl, location); | |
| 734 | ||
| 735 | 729 | // We shouldn't cast C function pointers as this is UB (when you call |
| 736 | 730 | // them). The analysis until now should ensure that the C function |
| 737 | 731 | // pointers are compatible. If they are not, then there is a bug |
| 738 | 732 | // somewhere and we should let the C compiler tell us about it. |
| 739 | 733 | const ctype = try dg.ctypeFromType(ptr_ty, .complete); |
| 740 | 734 | const elem_ctype = ctype.info(ctype_pool).pointer.elem_ctype; |
| 741 | const decl_ctype = try dg.ctypeFromType(decl_ty, .complete); | |
| 742 | const need_cast = !elem_ctype.eql(decl_ctype) and | |
| 743 | (elem_ctype.info(ctype_pool) != .function or decl_ctype.info(ctype_pool) != .function); | |
| 735 | const nav_ctype = try dg.ctypeFromType(nav_ty, .complete); | |
| 736 | const need_cast = !elem_ctype.eql(nav_ctype) and | |
| 737 | (elem_ctype.info(ctype_pool) != .function or nav_ctype.info(ctype_pool) != .function); | |
| 744 | 738 | if (need_cast) { |
| 745 | 739 | try writer.writeAll("(("); |
| 746 | 740 | try dg.renderCType(writer, ctype); |
| 747 | 741 | try writer.writeByte(')'); |
| 748 | 742 | } |
| 749 | 743 | try writer.writeByte('&'); |
| 750 | try dg.renderDeclName(writer, decl_index); | |
| 744 | try dg.renderNavName(writer, owner_nav); | |
| 751 | 745 | if (need_cast) try writer.writeByte(')'); |
| 752 | 746 | } |
| 753 | 747 | |
| ... | ... | @@ -769,8 +763,8 @@ pub const DeclGen = struct { |
| 769 | 763 | try writer.print("){x}", .{try dg.fmtIntLiteral(addr_val, .Other)}); |
| 770 | 764 | }, |
| 771 | 765 | |
| 772 | .decl_ptr => |decl| try dg.renderDeclValue(writer, decl, location), | |
| 773 | .anon_decl_ptr => |ad| try dg.renderAnonDeclValue(writer, ad, location), | |
| 766 | .nav_ptr => |nav| try dg.renderNav(writer, nav, location), | |
| 767 | .uav_ptr => |uav| try dg.renderUav(writer, uav, location), | |
| 774 | 768 | |
| 775 | 769 | inline .eu_payload_ptr, .opt_payload_ptr => |info| { |
| 776 | 770 | try writer.writeAll("&("); |
| ... | ... | @@ -918,7 +912,7 @@ pub const DeclGen = struct { |
| 918 | 912 | .true => try writer.writeAll("true"), |
| 919 | 913 | }, |
| 920 | 914 | .variable, |
| 921 | .extern_func, | |
| 915 | .@"extern", | |
| 922 | 916 | .func, |
| 923 | 917 | .enum_literal, |
| 924 | 918 | .empty_enum_value, |
| ... | ... | @@ -1743,7 +1737,7 @@ pub const DeclGen = struct { |
| 1743 | 1737 | .undef, |
| 1744 | 1738 | .simple_value, |
| 1745 | 1739 | .variable, |
| 1746 | .extern_func, | |
| 1740 | .@"extern", | |
| 1747 | 1741 | .func, |
| 1748 | 1742 | .int, |
| 1749 | 1743 | .err, |
| ... | ... | @@ -1758,7 +1752,7 @@ pub const DeclGen = struct { |
| 1758 | 1752 | .aggregate, |
| 1759 | 1753 | .un, |
| 1760 | 1754 | .memoized_call, |
| 1761 | => unreachable, | |
| 1755 | => unreachable, // values, not types | |
| 1762 | 1756 | }, |
| 1763 | 1757 | } |
| 1764 | 1758 | } |
| ... | ... | @@ -1770,7 +1764,7 @@ pub const DeclGen = struct { |
| 1770 | 1764 | fn_align: InternPool.Alignment, |
| 1771 | 1765 | kind: CType.Kind, |
| 1772 | 1766 | name: union(enum) { |
| 1773 | decl: InternPool.DeclIndex, | |
| 1767 | nav: InternPool.Nav.Index, | |
| 1774 | 1768 | fmt_ctype_pool_string: std.fmt.Formatter(formatCTypePoolString), |
| 1775 | 1769 | @"export": struct { |
| 1776 | 1770 | main_name: InternPool.NullTerminatedString, |
| ... | ... | @@ -1805,7 +1799,7 @@ pub const DeclGen = struct { |
| 1805 | 1799 | |
| 1806 | 1800 | try w.print("{}", .{trailing}); |
| 1807 | 1801 | switch (name) { |
| 1808 | .decl => |decl_index| try dg.renderDeclName(w, decl_index), | |
| 1802 | .nav => |nav| try dg.renderNavName(w, nav), | |
| 1809 | 1803 | .fmt_ctype_pool_string => |fmt| try w.print("{ }", .{fmt}), |
| 1810 | 1804 | .@"export" => |@"export"| try w.print("{ }", .{fmtIdent(@"export".extern_name.toSlice(ip))}), |
| 1811 | 1805 | } |
| ... | ... | @@ -1828,7 +1822,7 @@ pub const DeclGen = struct { |
| 1828 | 1822 | .forward => { |
| 1829 | 1823 | if (fn_align.toByteUnits()) |a| try w.print(" zig_align_fn({})", .{a}); |
| 1830 | 1824 | switch (name) { |
| 1831 | .decl, .fmt_ctype_pool_string => {}, | |
| 1825 | .nav, .fmt_ctype_pool_string => {}, | |
| 1832 | 1826 | .@"export" => |@"export"| { |
| 1833 | 1827 | const extern_name = @"export".extern_name.toSlice(ip); |
| 1834 | 1828 | const is_mangled = isMangledIdent(extern_name, true); |
| ... | ... | @@ -2069,8 +2063,8 @@ pub const DeclGen = struct { |
| 2069 | 2063 | fn writeName(dg: *DeclGen, w: anytype, c_value: CValue) !void { |
| 2070 | 2064 | switch (c_value) { |
| 2071 | 2065 | .new_local, .local => |i| try w.print("t{d}", .{i}), |
| 2072 | .constant => |val| try renderAnonDeclName(w, val), | |
| 2073 | .decl => |decl| try dg.renderDeclName(w, decl), | |
| 2066 | .constant => |uav| try renderUavName(w, uav), | |
| 2067 | .nav => |nav| try dg.renderNavName(w, nav), | |
| 2074 | 2068 | .identifier => |ident| try w.print("{ }", .{fmtIdent(ident)}), |
| 2075 | 2069 | else => unreachable, |
| 2076 | 2070 | } |
| ... | ... | @@ -2079,13 +2073,13 @@ pub const DeclGen = struct { |
| 2079 | 2073 | fn writeCValue(dg: *DeclGen, w: anytype, c_value: CValue) !void { |
| 2080 | 2074 | switch (c_value) { |
| 2081 | 2075 | .none, .new_local, .local, .local_ref => unreachable, |
| 2082 | .constant => |val| try renderAnonDeclName(w, val), | |
| 2076 | .constant => |uav| try renderUavName(w, uav), | |
| 2083 | 2077 | .arg, .arg_array => unreachable, |
| 2084 | 2078 | .field => |i| try w.print("f{d}", .{i}), |
| 2085 | .decl => |decl| try dg.renderDeclName(w, decl), | |
| 2086 | .decl_ref => |decl| { | |
| 2079 | .nav => |nav| try dg.renderNavName(w, nav), | |
| 2080 | .nav_ref => |nav| { | |
| 2087 | 2081 | try w.writeByte('&'); |
| 2088 | try dg.renderDeclName(w, decl); | |
| 2082 | try dg.renderNavName(w, nav); | |
| 2089 | 2083 | }, |
| 2090 | 2084 | .undef => |ty| try dg.renderUndefValue(w, ty, .Other), |
| 2091 | 2085 | .identifier => |ident| try w.print("{ }", .{fmtIdent(ident)}), |
| ... | ... | @@ -2111,12 +2105,12 @@ pub const DeclGen = struct { |
| 2111 | 2105 | .ctype_pool_string, |
| 2112 | 2106 | => unreachable, |
| 2113 | 2107 | .field => |i| try w.print("f{d}", .{i}), |
| 2114 | .decl => |decl| { | |
| 2108 | .nav => |nav| { | |
| 2115 | 2109 | try w.writeAll("(*"); |
| 2116 | try dg.renderDeclName(w, decl); | |
| 2110 | try dg.renderNavName(w, nav); | |
| 2117 | 2111 | try w.writeByte(')'); |
| 2118 | 2112 | }, |
| 2119 | .decl_ref => |decl| try dg.renderDeclName(w, decl), | |
| 2113 | .nav_ref => |nav| try dg.renderNavName(w, nav), | |
| 2120 | 2114 | .undef => unreachable, |
| 2121 | 2115 | .identifier => |ident| try w.print("(*{ })", .{fmtIdent(ident)}), |
| 2122 | 2116 | .payload_identifier => |ident| try w.print("(*{ }.{ })", .{ |
| ... | ... | @@ -2150,11 +2144,11 @@ pub const DeclGen = struct { |
| 2150 | 2144 | .arg_array, |
| 2151 | 2145 | .ctype_pool_string, |
| 2152 | 2146 | => unreachable, |
| 2153 | .decl, .identifier, .payload_identifier => { | |
| 2147 | .nav, .identifier, .payload_identifier => { | |
| 2154 | 2148 | try dg.writeCValue(writer, c_value); |
| 2155 | 2149 | try writer.writeAll("->"); |
| 2156 | 2150 | }, |
| 2157 | .decl_ref => { | |
| 2151 | .nav_ref => { | |
| 2158 | 2152 | try dg.writeCValueDeref(writer, c_value); |
| 2159 | 2153 | try writer.writeByte('.'); |
| 2160 | 2154 | }, |
| ... | ... | @@ -2164,46 +2158,53 @@ pub const DeclGen = struct { |
| 2164 | 2158 | |
| 2165 | 2159 | fn renderFwdDecl( |
| 2166 | 2160 | dg: *DeclGen, |
| 2167 | decl_index: InternPool.DeclIndex, | |
| 2168 | variable: InternPool.Key.Variable, | |
| 2161 | nav_index: InternPool.Nav.Index, | |
| 2162 | flags: struct { | |
| 2163 | is_extern: bool, | |
| 2164 | is_const: bool, | |
| 2165 | is_threadlocal: bool, | |
| 2166 | is_weak_linkage: bool, | |
| 2167 | }, | |
| 2169 | 2168 | ) !void { |
| 2170 | 2169 | const zcu = dg.pt.zcu; |
| 2171 | const decl = zcu.declPtr(decl_index); | |
| 2170 | const ip = &zcu.intern_pool; | |
| 2171 | const nav = ip.getNav(nav_index); | |
| 2172 | 2172 | const fwd = dg.fwdDeclWriter(); |
| 2173 | try fwd.writeAll(if (variable.is_extern) "zig_extern " else "static "); | |
| 2174 | if (variable.is_weak_linkage) try fwd.writeAll("zig_weak_linkage "); | |
| 2175 | if (variable.is_threadlocal and !dg.mod.single_threaded) try fwd.writeAll("zig_threadlocal "); | |
| 2173 | try fwd.writeAll(if (flags.is_extern) "zig_extern " else "static "); | |
| 2174 | if (flags.is_weak_linkage) try fwd.writeAll("zig_weak_linkage "); | |
| 2175 | if (flags.is_threadlocal and !dg.mod.single_threaded) try fwd.writeAll("zig_threadlocal "); | |
| 2176 | 2176 | try dg.renderTypeAndName( |
| 2177 | 2177 | fwd, |
| 2178 | decl.typeOf(zcu), | |
| 2179 | .{ .decl = decl_index }, | |
| 2180 | CQualifiers.init(.{ .@"const" = variable.is_const }), | |
| 2181 | decl.alignment, | |
| 2178 | Type.fromInterned(nav.typeOf(ip)), | |
| 2179 | .{ .nav = nav_index }, | |
| 2180 | CQualifiers.init(.{ .@"const" = flags.is_const }), | |
| 2181 | nav.status.resolved.alignment, | |
| 2182 | 2182 | .complete, |
| 2183 | 2183 | ); |
| 2184 | 2184 | try fwd.writeAll(";\n"); |
| 2185 | 2185 | } |
| 2186 | 2186 | |
| 2187 | fn renderDeclName(dg: *DeclGen, writer: anytype, decl_index: InternPool.DeclIndex) !void { | |
| 2187 | fn renderNavName(dg: *DeclGen, writer: anytype, nav_index: InternPool.Nav.Index) !void { | |
| 2188 | 2188 | const zcu = dg.pt.zcu; |
| 2189 | 2189 | const ip = &zcu.intern_pool; |
| 2190 | const decl = zcu.declPtr(decl_index); | |
| 2191 | ||
| 2192 | if (decl.getExternDecl(zcu).unwrap()) |extern_decl_index| try writer.print("{ }", .{ | |
| 2193 | fmtIdent(zcu.declPtr(extern_decl_index).name.toSlice(ip)), | |
| 2194 | }) else { | |
| 2195 | // MSVC has a limit of 4095 character token length limit, and fmtIdent can (worst case), | |
| 2196 | // expand to 3x the length of its input, but let's cut it off at a much shorter limit. | |
| 2197 | const fqn_slice = decl.fqn.toSlice(ip); | |
| 2198 | try writer.print("{}__{d}", .{ | |
| 2199 | fmtIdent(fqn_slice[0..@min(fqn_slice.len, 100)]), | |
| 2200 | @intFromEnum(decl_index), | |
| 2201 | }); | |
| 2190 | switch (ip.indexToKey(zcu.navValue(nav_index).toIntern())) { | |
| 2191 | .@"extern" => |@"extern"| try writer.print("{ }", .{ | |
| 2192 | fmtIdent(ip.getNav(@"extern".owner_nav).name.toSlice(ip)), | |
| 2193 | }), | |
| 2194 | else => { | |
| 2195 | // MSVC has a limit of 4095 character token length limit, and fmtIdent can (worst case), | |
| 2196 | // expand to 3x the length of its input, but let's cut it off at a much shorter limit. | |
| 2197 | const fqn_slice = ip.getNav(nav_index).fqn.toSlice(ip); | |
| 2198 | try writer.print("{}__{d}", .{ | |
| 2199 | fmtIdent(fqn_slice[0..@min(fqn_slice.len, 100)]), | |
| 2200 | @intFromEnum(nav_index), | |
| 2201 | }); | |
| 2202 | }, | |
| 2202 | 2203 | } |
| 2203 | 2204 | } |
| 2204 | 2205 | |
| 2205 | fn renderAnonDeclName(writer: anytype, anon_decl_val: Value) !void { | |
| 2206 | try writer.print("__anon_{d}", .{@intFromEnum(anon_decl_val.toIntern())}); | |
| 2206 | fn renderUavName(writer: anytype, uav: Value) !void { | |
| 2207 | try writer.print("__anon_{d}", .{@intFromEnum(uav.toIntern())}); | |
| 2207 | 2208 | } |
| 2208 | 2209 | |
| 2209 | 2210 | fn renderTypeForBuiltinFnName(dg: *DeclGen, writer: anytype, ty: Type) !void { |
| ... | ... | @@ -2301,12 +2302,13 @@ fn renderFwdDeclTypeName( |
| 2301 | 2302 | fwd_decl: CType.Info.FwdDecl, |
| 2302 | 2303 | attributes: []const u8, |
| 2303 | 2304 | ) !void { |
| 2305 | const ip = &zcu.intern_pool; | |
| 2304 | 2306 | try w.print("{s} {s}", .{ @tagName(fwd_decl.tag), attributes }); |
| 2305 | 2307 | switch (fwd_decl.name) { |
| 2306 | 2308 | .anon => try w.print("anon__lazy_{d}", .{@intFromEnum(ctype.index)}), |
| 2307 | .owner_decl => |owner_decl| try w.print("{}__{d}", .{ | |
| 2308 | fmtIdent(zcu.declPtr(owner_decl).name.toSlice(&zcu.intern_pool)), | |
| 2309 | @intFromEnum(owner_decl), | |
| 2309 | .index => |index| try w.print("{}__{d}", .{ | |
| 2310 | fmtIdent(Type.fromInterned(index).containerTypeName(ip).toSlice(&zcu.intern_pool)), | |
| 2311 | @intFromEnum(index), | |
| 2310 | 2312 | }), |
| 2311 | 2313 | } |
| 2312 | 2314 | } |
| ... | ... | @@ -2340,11 +2342,11 @@ fn renderTypePrefix( |
| 2340 | 2342 | }, |
| 2341 | 2343 | |
| 2342 | 2344 | .aligned => switch (pass) { |
| 2343 | .decl => |decl_index| try w.print("decl__{d}_{d}", .{ | |
| 2344 | @intFromEnum(decl_index), @intFromEnum(ctype.index), | |
| 2345 | .nav => |nav| try w.print("nav__{d}_{d}", .{ | |
| 2346 | @intFromEnum(nav), @intFromEnum(ctype.index), | |
| 2345 | 2347 | }), |
| 2346 | .anon => |anon_decl| try w.print("anon__{d}_{d}", .{ | |
| 2347 | @intFromEnum(anon_decl), @intFromEnum(ctype.index), | |
| 2348 | .uav => |uav| try w.print("uav__{d}_{d}", .{ | |
| 2349 | @intFromEnum(uav), @intFromEnum(ctype.index), | |
| 2348 | 2350 | }), |
| 2349 | 2351 | .flush => try renderAlignedTypeName(w, ctype), |
| 2350 | 2352 | }, |
| ... | ... | @@ -2370,15 +2372,15 @@ fn renderTypePrefix( |
| 2370 | 2372 | |
| 2371 | 2373 | .fwd_decl => |fwd_decl_info| switch (fwd_decl_info.name) { |
| 2372 | 2374 | .anon => switch (pass) { |
| 2373 | .decl => |decl_index| try w.print("decl__{d}_{d}", .{ | |
| 2374 | @intFromEnum(decl_index), @intFromEnum(ctype.index), | |
| 2375 | .nav => |nav| try w.print("nav__{d}_{d}", .{ | |
| 2376 | @intFromEnum(nav), @intFromEnum(ctype.index), | |
| 2375 | 2377 | }), |
| 2376 | .anon => |anon_decl| try w.print("anon__{d}_{d}", .{ | |
| 2377 | @intFromEnum(anon_decl), @intFromEnum(ctype.index), | |
| 2378 | .uav => |uav| try w.print("uav__{d}_{d}", .{ | |
| 2379 | @intFromEnum(uav), @intFromEnum(ctype.index), | |
| 2378 | 2380 | }), |
| 2379 | 2381 | .flush => try renderFwdDeclTypeName(zcu, w, ctype, fwd_decl_info, ""), |
| 2380 | 2382 | }, |
| 2381 | .owner_decl => try renderFwdDeclTypeName(zcu, w, ctype, fwd_decl_info, ""), | |
| 2383 | .index => try renderFwdDeclTypeName(zcu, w, ctype, fwd_decl_info, ""), | |
| 2382 | 2384 | }, |
| 2383 | 2385 | |
| 2384 | 2386 | .aggregate => |aggregate_info| switch (aggregate_info.name) { |
| ... | ... | @@ -2557,7 +2559,7 @@ pub fn genTypeDecl( |
| 2557 | 2559 | try writer.writeAll(";\n"); |
| 2558 | 2560 | } |
| 2559 | 2561 | switch (pass) { |
| 2560 | .decl, .anon => { | |
| 2562 | .nav, .uav => { | |
| 2561 | 2563 | try writer.writeAll("typedef "); |
| 2562 | 2564 | _ = try renderTypePrefix(.flush, global_ctype_pool, zcu, writer, global_ctype, .suffix, .{}); |
| 2563 | 2565 | try writer.writeByte(' '); |
| ... | ... | @@ -2569,7 +2571,7 @@ pub fn genTypeDecl( |
| 2569 | 2571 | }, |
| 2570 | 2572 | .fwd_decl => |fwd_decl_info| switch (fwd_decl_info.name) { |
| 2571 | 2573 | .anon => switch (pass) { |
| 2572 | .decl, .anon => { | |
| 2574 | .nav, .uav => { | |
| 2573 | 2575 | try writer.writeAll("typedef "); |
| 2574 | 2576 | _ = try renderTypePrefix(.flush, global_ctype_pool, zcu, writer, global_ctype, .suffix, .{}); |
| 2575 | 2577 | try writer.writeByte(' '); |
| ... | ... | @@ -2578,13 +2580,14 @@ pub fn genTypeDecl( |
| 2578 | 2580 | }, |
| 2579 | 2581 | .flush => {}, |
| 2580 | 2582 | }, |
| 2581 | .owner_decl => |owner_decl_index| if (!found_existing) { | |
| 2583 | .index => |index| if (!found_existing) { | |
| 2584 | const ip = &zcu.intern_pool; | |
| 2585 | const ty = Type.fromInterned(index); | |
| 2582 | 2586 | _ = try renderTypePrefix(.flush, global_ctype_pool, zcu, writer, global_ctype, .suffix, .{}); |
| 2583 | 2587 | try writer.writeByte(';'); |
| 2584 | const owner_decl = zcu.declPtr(owner_decl_index); | |
| 2585 | const owner_mod = zcu.namespacePtr(owner_decl.src_namespace).fileScope(zcu).mod; | |
| 2586 | if (!owner_mod.strip) try writer.print(" /* {} */", .{ | |
| 2587 | owner_decl.fqn.fmt(&zcu.intern_pool), | |
| 2588 | const file_scope = ty.typeDeclInstAllowGeneratedTag(zcu).?.resolveFull(ip).file; | |
| 2589 | if (!zcu.fileByIndex(file_scope).mod.strip) try writer.print(" /* {} */", .{ | |
| 2590 | ty.containerTypeName(ip).fmt(ip), | |
| 2588 | 2591 | }); |
| 2589 | 2592 | try writer.writeByte('\n'); |
| 2590 | 2593 | }, |
| ... | ... | @@ -2709,9 +2712,8 @@ pub fn genLazyFn(o: *Object, lazy_ctype_pool: *const CType.Pool, lazy_fn: LazyFn |
| 2709 | 2712 | const key = lazy_fn.key_ptr.*; |
| 2710 | 2713 | const val = lazy_fn.value_ptr; |
| 2711 | 2714 | switch (key) { |
| 2712 | .tag_name => { | |
| 2713 | const enum_ty = val.data.tag_name; | |
| 2714 | ||
| 2715 | .tag_name => |enum_ty_ip| { | |
| 2716 | const enum_ty = Type.fromInterned(enum_ty_ip); | |
| 2715 | 2717 | const name_slice_ty = Type.slice_const_u8_sentinel_0; |
| 2716 | 2718 | |
| 2717 | 2719 | try w.writeAll("static "); |
| ... | ... | @@ -2756,25 +2758,25 @@ pub fn genLazyFn(o: *Object, lazy_ctype_pool: *const CType.Pool, lazy_fn: LazyFn |
| 2756 | 2758 | _ = try airBreakpoint(w); |
| 2757 | 2759 | try w.writeAll("}\n"); |
| 2758 | 2760 | }, |
| 2759 | .never_tail, .never_inline => |fn_decl_index| { | |
| 2760 | const fn_decl = zcu.declPtr(fn_decl_index); | |
| 2761 | const fn_ctype = try o.dg.ctypeFromType(fn_decl.typeOf(zcu), .complete); | |
| 2761 | .never_tail, .never_inline => |fn_nav_index| { | |
| 2762 | const fn_val = zcu.navValue(fn_nav_index); | |
| 2763 | const fn_ctype = try o.dg.ctypeFromType(fn_val.typeOf(zcu), .complete); | |
| 2762 | 2764 | const fn_info = fn_ctype.info(ctype_pool).function; |
| 2763 | 2765 | const fn_name = fmtCTypePoolString(val.fn_name, lazy_ctype_pool); |
| 2764 | 2766 | |
| 2765 | 2767 | const fwd = o.dg.fwdDeclWriter(); |
| 2766 | 2768 | try fwd.print("static zig_{s} ", .{@tagName(key)}); |
| 2767 | try o.dg.renderFunctionSignature(fwd, fn_decl.val, fn_decl.alignment, .forward, .{ | |
| 2769 | try o.dg.renderFunctionSignature(fwd, fn_val, ip.getNav(fn_nav_index).status.resolved.alignment, .forward, .{ | |
| 2768 | 2770 | .fmt_ctype_pool_string = fn_name, |
| 2769 | 2771 | }); |
| 2770 | 2772 | try fwd.writeAll(";\n"); |
| 2771 | 2773 | |
| 2772 | 2774 | try w.print("zig_{s} ", .{@tagName(key)}); |
| 2773 | try o.dg.renderFunctionSignature(w, fn_decl.val, .none, .complete, .{ | |
| 2775 | try o.dg.renderFunctionSignature(w, fn_val, .none, .complete, .{ | |
| 2774 | 2776 | .fmt_ctype_pool_string = fn_name, |
| 2775 | 2777 | }); |
| 2776 | 2778 | try w.writeAll(" {\n return "); |
| 2777 | try o.dg.renderDeclName(w, fn_decl_index); | |
| 2779 | try o.dg.renderNavName(w, fn_nav_index); | |
| 2778 | 2780 | try w.writeByte('('); |
| 2779 | 2781 | for (0..fn_info.param_ctypes.len) |arg| { |
| 2780 | 2782 | if (arg > 0) try w.writeAll(", "); |
| ... | ... | @@ -2791,9 +2793,11 @@ pub fn genFunc(f: *Function) !void { |
| 2791 | 2793 | |
| 2792 | 2794 | const o = &f.object; |
| 2793 | 2795 | const zcu = o.dg.pt.zcu; |
| 2796 | const ip = &zcu.intern_pool; | |
| 2794 | 2797 | const gpa = o.dg.gpa; |
| 2795 | const decl_index = o.dg.pass.decl; | |
| 2796 | const decl = zcu.declPtr(decl_index); | |
| 2798 | const nav_index = o.dg.pass.nav; | |
| 2799 | const nav_val = zcu.navValue(nav_index); | |
| 2800 | const nav = ip.getNav(nav_index); | |
| 2797 | 2801 | |
| 2798 | 2802 | o.code_header = std.ArrayList(u8).init(gpa); |
| 2799 | 2803 | defer o.code_header.deinit(); |
| ... | ... | @@ -2802,21 +2806,21 @@ pub fn genFunc(f: *Function) !void { |
| 2802 | 2806 | try fwd.writeAll("static "); |
| 2803 | 2807 | try o.dg.renderFunctionSignature( |
| 2804 | 2808 | fwd, |
| 2805 | decl.val, | |
| 2806 | decl.alignment, | |
| 2809 | nav_val, | |
| 2810 | nav.status.resolved.alignment, | |
| 2807 | 2811 | .forward, |
| 2808 | .{ .decl = decl_index }, | |
| 2812 | .{ .nav = nav_index }, | |
| 2809 | 2813 | ); |
| 2810 | 2814 | try fwd.writeAll(";\n"); |
| 2811 | 2815 | |
| 2812 | if (decl.@"linksection".toSlice(&zcu.intern_pool)) |s| | |
| 2816 | if (nav.status.resolved.@"linksection".toSlice(ip)) |s| | |
| 2813 | 2817 | try o.writer().print("zig_linksection_fn({s}) ", .{fmtStringLiteral(s, null)}); |
| 2814 | 2818 | try o.dg.renderFunctionSignature( |
| 2815 | 2819 | o.writer(), |
| 2816 | decl.val, | |
| 2820 | nav_val, | |
| 2817 | 2821 | .none, |
| 2818 | 2822 | .complete, |
| 2819 | .{ .decl = decl_index }, | |
| 2823 | .{ .nav = nav_index }, | |
| 2820 | 2824 | ); |
| 2821 | 2825 | try o.writer().writeByte(' '); |
| 2822 | 2826 | |
| ... | ... | @@ -2883,44 +2887,66 @@ pub fn genDecl(o: *Object) !void { |
| 2883 | 2887 | |
| 2884 | 2888 | const pt = o.dg.pt; |
| 2885 | 2889 | const zcu = pt.zcu; |
| 2886 | const decl_index = o.dg.pass.decl; | |
| 2887 | const decl = zcu.declPtr(decl_index); | |
| 2888 | const decl_ty = decl.typeOf(zcu); | |
| 2890 | const ip = &zcu.intern_pool; | |
| 2891 | const nav = ip.getNav(o.dg.pass.nav); | |
| 2892 | const nav_ty = Type.fromInterned(nav.typeOf(ip)); | |
| 2893 | ||
| 2894 | if (!nav_ty.isFnOrHasRuntimeBitsIgnoreComptime(pt)) return; | |
| 2895 | switch (ip.indexToKey(nav.status.resolved.val)) { | |
| 2896 | .@"extern" => |@"extern"| { | |
| 2897 | if (!ip.isFunctionType(nav_ty.toIntern())) return o.dg.renderFwdDecl(o.dg.pass.nav, .{ | |
| 2898 | .is_extern = true, | |
| 2899 | .is_const = @"extern".is_const, | |
| 2900 | .is_threadlocal = @"extern".is_threadlocal, | |
| 2901 | .is_weak_linkage = @"extern".is_weak_linkage, | |
| 2902 | }); | |
| 2889 | 2903 | |
| 2890 | if (!decl_ty.isFnOrHasRuntimeBitsIgnoreComptime(pt)) return; | |
| 2891 | if (decl.val.getExternFunc(zcu)) |_| { | |
| 2892 | const fwd = o.dg.fwdDeclWriter(); | |
| 2893 | try fwd.writeAll("zig_extern "); | |
| 2894 | try o.dg.renderFunctionSignature( | |
| 2895 | fwd, | |
| 2896 | decl.val, | |
| 2897 | decl.alignment, | |
| 2898 | .forward, | |
| 2899 | .{ .@"export" = .{ | |
| 2900 | .main_name = decl.name, | |
| 2901 | .extern_name = decl.name, | |
| 2902 | } }, | |
| 2903 | ); | |
| 2904 | try fwd.writeAll(";\n"); | |
| 2905 | } else if (decl.val.getVariable(zcu)) |variable| { | |
| 2906 | try o.dg.renderFwdDecl(decl_index, variable); | |
| 2907 | ||
| 2908 | if (variable.is_extern) return; | |
| 2909 | ||
| 2910 | const w = o.writer(); | |
| 2911 | if (variable.is_weak_linkage) try w.writeAll("zig_weak_linkage "); | |
| 2912 | if (variable.is_threadlocal and !o.dg.mod.single_threaded) try w.writeAll("zig_threadlocal "); | |
| 2913 | if (decl.@"linksection".toSlice(&zcu.intern_pool)) |s| | |
| 2914 | try w.print("zig_linksection({s}) ", .{fmtStringLiteral(s, null)}); | |
| 2915 | const decl_c_value = .{ .decl = decl_index }; | |
| 2916 | try o.dg.renderTypeAndName(w, decl_ty, decl_c_value, .{}, decl.alignment, .complete); | |
| 2917 | try w.writeAll(" = "); | |
| 2918 | try o.dg.renderValue(w, Value.fromInterned(variable.init), .StaticInitializer); | |
| 2919 | try w.writeByte(';'); | |
| 2920 | try o.indent_writer.insertNewline(); | |
| 2921 | } else { | |
| 2922 | const decl_c_value = .{ .decl = decl_index }; | |
| 2923 | try genDeclValue(o, decl.val, decl_c_value, decl.alignment, decl.@"linksection"); | |
| 2904 | const fwd = o.dg.fwdDeclWriter(); | |
| 2905 | try fwd.writeAll("zig_extern "); | |
| 2906 | try o.dg.renderFunctionSignature( | |
| 2907 | fwd, | |
| 2908 | Value.fromInterned(nav.status.resolved.val), | |
| 2909 | nav.status.resolved.alignment, | |
| 2910 | .forward, | |
| 2911 | .{ .@"export" = .{ | |
| 2912 | .main_name = nav.name, | |
| 2913 | .extern_name = nav.name, | |
| 2914 | } }, | |
| 2915 | ); | |
| 2916 | try fwd.writeAll(";\n"); | |
| 2917 | }, | |
| 2918 | .variable => |variable| { | |
| 2919 | try o.dg.renderFwdDecl(o.dg.pass.nav, .{ | |
| 2920 | .is_extern = false, | |
| 2921 | .is_const = false, | |
| 2922 | .is_threadlocal = variable.is_threadlocal, | |
| 2923 | .is_weak_linkage = variable.is_weak_linkage, | |
| 2924 | }); | |
| 2925 | const w = o.writer(); | |
| 2926 | if (variable.is_weak_linkage) try w.writeAll("zig_weak_linkage "); | |
| 2927 | if (variable.is_threadlocal and !o.dg.mod.single_threaded) try w.writeAll("zig_threadlocal "); | |
| 2928 | if (nav.status.resolved.@"linksection".toSlice(&zcu.intern_pool)) |s| | |
| 2929 | try w.print("zig_linksection({s}) ", .{fmtStringLiteral(s, null)}); | |
| 2930 | try o.dg.renderTypeAndName( | |
| 2931 | w, | |
| 2932 | nav_ty, | |
| 2933 | .{ .nav = o.dg.pass.nav }, | |
| 2934 | .{}, | |
| 2935 | nav.status.resolved.alignment, | |
| 2936 | .complete, | |
| 2937 | ); | |
| 2938 | try w.writeAll(" = "); | |
| 2939 | try o.dg.renderValue(w, Value.fromInterned(variable.init), .StaticInitializer); | |
| 2940 | try w.writeByte(';'); | |
| 2941 | try o.indent_writer.insertNewline(); | |
| 2942 | }, | |
| 2943 | else => try genDeclValue( | |
| 2944 | o, | |
| 2945 | Value.fromInterned(nav.status.resolved.val), | |
| 2946 | .{ .nav = o.dg.pass.nav }, | |
| 2947 | nav.status.resolved.alignment, | |
| 2948 | nav.status.resolved.@"linksection", | |
| 2949 | ), | |
| 2924 | 2950 | } |
| 2925 | 2951 | } |
| 2926 | 2952 | |
| ... | ... | @@ -2956,31 +2982,34 @@ pub fn genExports(dg: *DeclGen, exported: Zcu.Exported, export_indices: []const |
| 2956 | 2982 | const main_name = zcu.all_exports.items[export_indices[0]].opts.name; |
| 2957 | 2983 | try fwd.writeAll("#define "); |
| 2958 | 2984 | switch (exported) { |
| 2959 | .decl_index => |decl_index| try dg.renderDeclName(fwd, decl_index), | |
| 2960 | .value => |value| try DeclGen.renderAnonDeclName(fwd, Value.fromInterned(value)), | |
| 2985 | .nav => |nav| try dg.renderNavName(fwd, nav), | |
| 2986 | .uav => |uav| try DeclGen.renderUavName(fwd, Value.fromInterned(uav)), | |
| 2961 | 2987 | } |
| 2962 | 2988 | try fwd.writeByte(' '); |
| 2963 | 2989 | try fwd.print("{ }", .{fmtIdent(main_name.toSlice(ip))}); |
| 2964 | 2990 | try fwd.writeByte('\n'); |
| 2965 | 2991 | |
| 2966 | const is_const = switch (ip.indexToKey(exported.getValue(zcu).toIntern())) { | |
| 2967 | .func, .extern_func => return for (export_indices) |export_index| { | |
| 2968 | const @"export" = &zcu.all_exports.items[export_index]; | |
| 2969 | try fwd.writeAll("zig_extern "); | |
| 2970 | if (@"export".opts.linkage == .weak) try fwd.writeAll("zig_weak_linkage_fn "); | |
| 2971 | try dg.renderFunctionSignature( | |
| 2972 | fwd, | |
| 2973 | exported.getValue(zcu), | |
| 2974 | exported.getAlign(zcu), | |
| 2975 | .forward, | |
| 2976 | .{ .@"export" = .{ | |
| 2977 | .main_name = main_name, | |
| 2978 | .extern_name = @"export".opts.name, | |
| 2979 | } }, | |
| 2980 | ); | |
| 2981 | try fwd.writeAll(";\n"); | |
| 2982 | }, | |
| 2983 | .variable => |variable| variable.is_const, | |
| 2992 | const exported_val = exported.getValue(zcu); | |
| 2993 | if (ip.isFunctionType(exported_val.typeOf(zcu).toIntern())) return for (export_indices) |export_index| { | |
| 2994 | const @"export" = &zcu.all_exports.items[export_index]; | |
| 2995 | try fwd.writeAll("zig_extern "); | |
| 2996 | if (@"export".opts.linkage == .weak) try fwd.writeAll("zig_weak_linkage_fn "); | |
| 2997 | try dg.renderFunctionSignature( | |
| 2998 | fwd, | |
| 2999 | exported.getValue(zcu), | |
| 3000 | exported.getAlign(zcu), | |
| 3001 | .forward, | |
| 3002 | .{ .@"export" = .{ | |
| 3003 | .main_name = main_name, | |
| 3004 | .extern_name = @"export".opts.name, | |
| 3005 | } }, | |
| 3006 | ); | |
| 3007 | try fwd.writeAll(";\n"); | |
| 3008 | }; | |
| 3009 | const is_const = switch (ip.indexToKey(exported_val.toIntern())) { | |
| 3010 | .func => unreachable, | |
| 3011 | .@"extern" => |@"extern"| @"extern".is_const, | |
| 3012 | .variable => false, | |
| 2984 | 3013 | else => true, |
| 2985 | 3014 | }; |
| 2986 | 3015 | for (export_indices) |export_index| { |
| ... | ... | @@ -4474,24 +4503,19 @@ fn airCall( |
| 4474 | 4503 | |
| 4475 | 4504 | callee: { |
| 4476 | 4505 | known: { |
| 4477 | const fn_decl = fn_decl: { | |
| 4478 | const callee_val = (try f.air.value(pl_op.operand, pt)) orelse break :known; | |
| 4479 | break :fn_decl switch (zcu.intern_pool.indexToKey(callee_val.toIntern())) { | |
| 4480 | .extern_func => |extern_func| extern_func.decl, | |
| 4481 | .func => |func| func.owner_decl, | |
| 4482 | .ptr => |ptr| if (ptr.byte_offset == 0) switch (ptr.base_addr) { | |
| 4483 | .decl => |decl| decl, | |
| 4484 | else => break :known, | |
| 4485 | } else break :known, | |
| 4506 | const callee_val = (try f.air.value(pl_op.operand, pt)) orelse break :known; | |
| 4507 | const fn_nav = switch (zcu.intern_pool.indexToKey(callee_val.toIntern())) { | |
| 4508 | .@"extern" => |@"extern"| @"extern".owner_nav, | |
| 4509 | .func => |func| func.owner_nav, | |
| 4510 | .ptr => |ptr| if (ptr.byte_offset == 0) switch (ptr.base_addr) { | |
| 4511 | .nav => |nav| nav, | |
| 4486 | 4512 | else => break :known, |
| 4487 | }; | |
| 4513 | } else break :known, | |
| 4514 | else => break :known, | |
| 4488 | 4515 | }; |
| 4489 | 4516 | switch (modifier) { |
| 4490 | .auto, .always_tail => try f.object.dg.renderDeclName(writer, fn_decl), | |
| 4491 | inline .never_tail, .never_inline => |m| try writer.writeAll(try f.getLazyFnName( | |
| 4492 | @unionInit(LazyFnKey, @tagName(m), fn_decl), | |
| 4493 | @unionInit(LazyFnValue.Data, @tagName(m), {}), | |
| 4494 | )), | |
| 4517 | .auto, .always_tail => try f.object.dg.renderNavName(writer, fn_nav), | |
| 4518 | inline .never_tail, .never_inline => |m| try writer.writeAll(try f.getLazyFnName(@unionInit(LazyFnKey, @tagName(m), fn_nav))), | |
| 4495 | 4519 | else => unreachable, |
| 4496 | 4520 | } |
| 4497 | 4521 | break :callee; |
| ... | ... | @@ -4554,11 +4578,12 @@ fn airDbgStmt(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4554 | 4578 | fn airDbgInlineBlock(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4555 | 4579 | const pt = f.object.dg.pt; |
| 4556 | 4580 | const zcu = pt.zcu; |
| 4581 | const ip = &zcu.intern_pool; | |
| 4557 | 4582 | const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; |
| 4558 | 4583 | const extra = f.air.extraData(Air.DbgInlineBlock, ty_pl.payload); |
| 4559 | const owner_decl = zcu.funcOwnerDeclPtr(extra.data.func); | |
| 4584 | const owner_nav = ip.getNav(zcu.funcInfo(extra.data.func).owner_nav); | |
| 4560 | 4585 | const writer = f.object.writer(); |
| 4561 | try writer.print("/* inline:{} */\n", .{owner_decl.fqn.fmt(&zcu.intern_pool)}); | |
| 4586 | try writer.print("/* inline:{} */\n", .{owner_nav.fqn.fmt(&zcu.intern_pool)}); | |
| 4562 | 4587 | return lowerBlock(f, inst, @ptrCast(f.air.extra[extra.end..][0..extra.data.body_len])); |
| 4563 | 4588 | } |
| 4564 | 4589 | |
| ... | ... | @@ -5059,7 +5084,7 @@ fn asmInputNeedsLocal(f: *Function, constraint: []const u8, value: CValue) bool |
| 5059 | 5084 | else => switch (value) { |
| 5060 | 5085 | .constant => |val| switch (dg.pt.zcu.intern_pool.indexToKey(val.toIntern())) { |
| 5061 | 5086 | .ptr => |ptr| if (ptr.byte_offset == 0) switch (ptr.base_addr) { |
| 5062 | .decl => false, | |
| 5087 | .nav => false, | |
| 5063 | 5088 | else => true, |
| 5064 | 5089 | } else true, |
| 5065 | 5090 | else => true, |
| ... | ... | @@ -6841,8 +6866,6 @@ fn airGetUnionTag(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6841 | 6866 | } |
| 6842 | 6867 | |
| 6843 | 6868 | fn airTagName(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6844 | const pt = f.object.dg.pt; | |
| 6845 | const zcu = pt.zcu; | |
| 6846 | 6869 | const un_op = f.air.instructions.items(.data)[@intFromEnum(inst)].un_op; |
| 6847 | 6870 | |
| 6848 | 6871 | const inst_ty = f.typeOfIndex(inst); |
| ... | ... | @@ -6854,7 +6877,7 @@ fn airTagName(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6854 | 6877 | const local = try f.allocLocal(inst, inst_ty); |
| 6855 | 6878 | try f.writeCValue(writer, local, .Other); |
| 6856 | 6879 | try writer.print(" = {s}(", .{ |
| 6857 | try f.getLazyFnName(.{ .tag_name = enum_ty.getOwnerDecl(zcu) }, .{ .tag_name = enum_ty }), | |
| 6880 | try f.getLazyFnName(.{ .tag_name = enum_ty.toIntern() }), | |
| 6858 | 6881 | }); |
| 6859 | 6882 | try f.writeCValue(writer, operand, .Other); |
| 6860 | 6883 | try writer.writeAll(");\n"); |
| ... | ... | @@ -7390,18 +7413,17 @@ fn airCVaStart(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7390 | 7413 | const pt = f.object.dg.pt; |
| 7391 | 7414 | const zcu = pt.zcu; |
| 7392 | 7415 | const inst_ty = f.typeOfIndex(inst); |
| 7393 | const decl_index = f.object.dg.pass.decl; | |
| 7394 | const decl = zcu.declPtr(decl_index); | |
| 7395 | const function_ctype = try f.ctypeFromType(decl.typeOf(zcu), .complete); | |
| 7396 | const params_len = function_ctype.info(&f.object.dg.ctype_pool).function.param_ctypes.len; | |
| 7416 | const function_ty = zcu.navValue(f.object.dg.pass.nav).typeOf(zcu); | |
| 7417 | const function_info = (try f.ctypeFromType(function_ty, .complete)).info(&f.object.dg.ctype_pool).function; | |
| 7418 | assert(function_info.varargs); | |
| 7397 | 7419 | |
| 7398 | 7420 | const writer = f.object.writer(); |
| 7399 | 7421 | const local = try f.allocLocal(inst, inst_ty); |
| 7400 | 7422 | try writer.writeAll("va_start(*(va_list *)&"); |
| 7401 | 7423 | try f.writeCValue(writer, local, .Other); |
| 7402 | if (params_len > 0) { | |
| 7424 | if (function_info.param_ctypes.len > 0) { | |
| 7403 | 7425 | try writer.writeAll(", "); |
| 7404 | try f.writeCValue(writer, .{ .arg = params_len - 1 }, .FunctionArgument); | |
| 7426 | try f.writeCValue(writer, .{ .arg = function_info.param_ctypes.len - 1 }, .FunctionArgument); | |
| 7405 | 7427 | } |
| 7406 | 7428 | try writer.writeAll(");\n"); |
| 7407 | 7429 | return local; |
| ... | ... | @@ -7941,7 +7963,7 @@ const Materialize = struct { |
| 7941 | 7963 | |
| 7942 | 7964 | pub fn start(f: *Function, inst: Air.Inst.Index, ty: Type, value: CValue) !Materialize { |
| 7943 | 7965 | return .{ .local = switch (value) { |
| 7944 | .local_ref, .constant, .decl_ref, .undef => try f.moveCValue(inst, ty, value), | |
| 7966 | .local_ref, .constant, .nav_ref, .undef => try f.moveCValue(inst, ty, value), | |
| 7945 | 7967 | .new_local => |local| .{ .local = local }, |
| 7946 | 7968 | else => value, |
| 7947 | 7969 | } }; |
src/codegen/c/Type.zig+36-37| ... | ... | @@ -449,18 +449,18 @@ pub fn info(ctype: CType, pool: *const Pool) Info { |
| 449 | 449 | }, |
| 450 | 450 | .fwd_decl_struct => return .{ .fwd_decl = .{ |
| 451 | 451 | .tag = .@"struct", |
| 452 | .name = .{ .owner_decl = @enumFromInt(item.data) }, | |
| 452 | .name = .{ .index = @enumFromInt(item.data) }, | |
| 453 | 453 | } }, |
| 454 | 454 | .fwd_decl_union => return .{ .fwd_decl = .{ |
| 455 | 455 | .tag = .@"union", |
| 456 | .name = .{ .owner_decl = @enumFromInt(item.data) }, | |
| 456 | .name = .{ .index = @enumFromInt(item.data) }, | |
| 457 | 457 | } }, |
| 458 | 458 | .aggregate_struct_anon => { |
| 459 | 459 | const extra_trail = pool.getExtraTrail(Pool.AggregateAnon, item.data); |
| 460 | 460 | return .{ .aggregate = .{ |
| 461 | 461 | .tag = .@"struct", |
| 462 | 462 | .name = .{ .anon = .{ |
| 463 | .owner_decl = extra_trail.extra.owner_decl, | |
| 463 | .index = extra_trail.extra.index, | |
| 464 | 464 | .id = extra_trail.extra.id, |
| 465 | 465 | } }, |
| 466 | 466 | .fields = .{ |
| ... | ... | @@ -474,7 +474,7 @@ pub fn info(ctype: CType, pool: *const Pool) Info { |
| 474 | 474 | return .{ .aggregate = .{ |
| 475 | 475 | .tag = .@"union", |
| 476 | 476 | .name = .{ .anon = .{ |
| 477 | .owner_decl = extra_trail.extra.owner_decl, | |
| 477 | .index = extra_trail.extra.index, | |
| 478 | 478 | .id = extra_trail.extra.id, |
| 479 | 479 | } }, |
| 480 | 480 | .fields = .{ |
| ... | ... | @@ -489,7 +489,7 @@ pub fn info(ctype: CType, pool: *const Pool) Info { |
| 489 | 489 | .tag = .@"struct", |
| 490 | 490 | .@"packed" = true, |
| 491 | 491 | .name = .{ .anon = .{ |
| 492 | .owner_decl = extra_trail.extra.owner_decl, | |
| 492 | .index = extra_trail.extra.index, | |
| 493 | 493 | .id = extra_trail.extra.id, |
| 494 | 494 | } }, |
| 495 | 495 | .fields = .{ |
| ... | ... | @@ -504,7 +504,7 @@ pub fn info(ctype: CType, pool: *const Pool) Info { |
| 504 | 504 | .tag = .@"union", |
| 505 | 505 | .@"packed" = true, |
| 506 | 506 | .name = .{ .anon = .{ |
| 507 | .owner_decl = extra_trail.extra.owner_decl, | |
| 507 | .index = extra_trail.extra.index, | |
| 508 | 508 | .id = extra_trail.extra.id, |
| 509 | 509 | } }, |
| 510 | 510 | .fields = .{ |
| ... | ... | @@ -834,7 +834,7 @@ pub const Info = union(enum) { |
| 834 | 834 | tag: AggregateTag, |
| 835 | 835 | name: union(enum) { |
| 836 | 836 | anon: Field.Slice, |
| 837 | owner_decl: DeclIndex, | |
| 837 | index: InternPool.Index, | |
| 838 | 838 | }, |
| 839 | 839 | }; |
| 840 | 840 | |
| ... | ... | @@ -843,7 +843,7 @@ pub const Info = union(enum) { |
| 843 | 843 | @"packed": bool = false, |
| 844 | 844 | name: union(enum) { |
| 845 | 845 | anon: struct { |
| 846 | owner_decl: DeclIndex, | |
| 846 | index: InternPool.Index, | |
| 847 | 847 | id: u32, |
| 848 | 848 | }, |
| 849 | 849 | fwd_decl: CType, |
| ... | ... | @@ -885,14 +885,14 @@ pub const Info = union(enum) { |
| 885 | 885 | rhs_pool, |
| 886 | 886 | pool_adapter, |
| 887 | 887 | ), |
| 888 | .owner_decl => |lhs_owner_decl| rhs_info.fwd_decl.name == .owner_decl and | |
| 889 | lhs_owner_decl == rhs_info.fwd_decl.name.owner_decl, | |
| 888 | .index => |lhs_index| rhs_info.fwd_decl.name == .index and | |
| 889 | lhs_index == rhs_info.fwd_decl.name.index, | |
| 890 | 890 | }, |
| 891 | 891 | .aggregate => |lhs_aggregate_info| lhs_aggregate_info.tag == rhs_info.aggregate.tag and |
| 892 | 892 | lhs_aggregate_info.@"packed" == rhs_info.aggregate.@"packed" and |
| 893 | 893 | switch (lhs_aggregate_info.name) { |
| 894 | 894 | .anon => |lhs_anon| rhs_info.aggregate.name == .anon and |
| 895 | lhs_anon.owner_decl == rhs_info.aggregate.name.anon.owner_decl and | |
| 895 | lhs_anon.index == rhs_info.aggregate.name.anon.index and | |
| 896 | 896 | lhs_anon.id == rhs_info.aggregate.name.anon.id, |
| 897 | 897 | .fwd_decl => |lhs_fwd_decl| rhs_info.aggregate.name == .fwd_decl and |
| 898 | 898 | pool_adapter.eql(lhs_fwd_decl, rhs_info.aggregate.name.fwd_decl), |
| ... | ... | @@ -1105,7 +1105,7 @@ pub const Pool = struct { |
| 1105 | 1105 | tag: Info.AggregateTag, |
| 1106 | 1106 | name: union(enum) { |
| 1107 | 1107 | anon: []const Info.Field, |
| 1108 | owner_decl: DeclIndex, | |
| 1108 | index: InternPool.Index, | |
| 1109 | 1109 | }, |
| 1110 | 1110 | }, |
| 1111 | 1111 | ) !CType { |
| ... | ... | @@ -1145,13 +1145,13 @@ pub const Pool = struct { |
| 1145 | 1145 | .@"enum" => unreachable, |
| 1146 | 1146 | }, extra_index); |
| 1147 | 1147 | }, |
| 1148 | .owner_decl => |owner_decl| { | |
| 1149 | hasher.update(owner_decl); | |
| 1148 | .index => |index| { | |
| 1149 | hasher.update(index); | |
| 1150 | 1150 | return pool.tagData(allocator, hasher, switch (fwd_decl_info.tag) { |
| 1151 | 1151 | .@"struct" => .fwd_decl_struct, |
| 1152 | 1152 | .@"union" => .fwd_decl_union, |
| 1153 | 1153 | .@"enum" => unreachable, |
| 1154 | }, @intFromEnum(owner_decl)); | |
| 1154 | }, @intFromEnum(index)); | |
| 1155 | 1155 | }, |
| 1156 | 1156 | } |
| 1157 | 1157 | } |
| ... | ... | @@ -1164,7 +1164,7 @@ pub const Pool = struct { |
| 1164 | 1164 | @"packed": bool = false, |
| 1165 | 1165 | name: union(enum) { |
| 1166 | 1166 | anon: struct { |
| 1167 | owner_decl: DeclIndex, | |
| 1167 | index: InternPool.Index, | |
| 1168 | 1168 | id: u32, |
| 1169 | 1169 | }, |
| 1170 | 1170 | fwd_decl: CType, |
| ... | ... | @@ -1176,7 +1176,7 @@ pub const Pool = struct { |
| 1176 | 1176 | switch (aggregate_info.name) { |
| 1177 | 1177 | .anon => |anon| { |
| 1178 | 1178 | const extra: AggregateAnon = .{ |
| 1179 | .owner_decl = anon.owner_decl, | |
| 1179 | .index = anon.index, | |
| 1180 | 1180 | .id = anon.id, |
| 1181 | 1181 | .fields_len = @intCast(aggregate_info.fields.len), |
| 1182 | 1182 | }; |
| ... | ... | @@ -1683,7 +1683,7 @@ pub const Pool = struct { |
| 1683 | 1683 | .auto, .@"extern" => { |
| 1684 | 1684 | const fwd_decl = try pool.getFwdDecl(allocator, .{ |
| 1685 | 1685 | .tag = .@"struct", |
| 1686 | .name = .{ .owner_decl = loaded_struct.decl.unwrap().? }, | |
| 1686 | .name = .{ .index = ip_index }, | |
| 1687 | 1687 | }); |
| 1688 | 1688 | if (kind.isForward()) return if (ty.hasRuntimeBitsIgnoreComptime(pt)) |
| 1689 | 1689 | fwd_decl |
| ... | ... | @@ -1822,7 +1822,7 @@ pub const Pool = struct { |
| 1822 | 1822 | const has_tag = loaded_union.hasTag(ip); |
| 1823 | 1823 | const fwd_decl = try pool.getFwdDecl(allocator, .{ |
| 1824 | 1824 | .tag = if (has_tag) .@"struct" else .@"union", |
| 1825 | .name = .{ .owner_decl = loaded_union.decl }, | |
| 1825 | .name = .{ .index = ip_index }, | |
| 1826 | 1826 | }); |
| 1827 | 1827 | if (kind.isForward()) return if (ty.hasRuntimeBitsIgnoreComptime(pt)) |
| 1828 | 1828 | fwd_decl |
| ... | ... | @@ -1837,7 +1837,7 @@ pub const Pool = struct { |
| 1837 | 1837 | ); |
| 1838 | 1838 | var hasher = Hasher.init; |
| 1839 | 1839 | var tag: Pool.Tag = .aggregate_union; |
| 1840 | var payload_align: Alignment = .@"1"; | |
| 1840 | var payload_align: InternPool.Alignment = .@"1"; | |
| 1841 | 1841 | for (0..loaded_union.field_types.len) |field_index| { |
| 1842 | 1842 | const field_type = Type.fromInterned( |
| 1843 | 1843 | loaded_union.field_types.get(ip)[field_index], |
| ... | ... | @@ -1915,7 +1915,7 @@ pub const Pool = struct { |
| 1915 | 1915 | &hasher, |
| 1916 | 1916 | AggregateAnon, |
| 1917 | 1917 | .{ |
| 1918 | .owner_decl = loaded_union.decl, | |
| 1918 | .index = ip_index, | |
| 1919 | 1919 | .id = 0, |
| 1920 | 1920 | .fields_len = fields_len, |
| 1921 | 1921 | }, |
| ... | ... | @@ -2017,7 +2017,7 @@ pub const Pool = struct { |
| 2017 | 2017 | .undef, |
| 2018 | 2018 | .simple_value, |
| 2019 | 2019 | .variable, |
| 2020 | .extern_func, | |
| 2020 | .@"extern", | |
| 2021 | 2021 | .func, |
| 2022 | 2022 | .int, |
| 2023 | 2023 | .err, |
| ... | ... | @@ -2032,7 +2032,7 @@ pub const Pool = struct { |
| 2032 | 2032 | .aggregate, |
| 2033 | 2033 | .un, |
| 2034 | 2034 | .memoized_call, |
| 2035 | => unreachable, | |
| 2035 | => unreachable, // values, not types | |
| 2036 | 2036 | }, |
| 2037 | 2037 | } |
| 2038 | 2038 | } |
| ... | ... | @@ -2123,9 +2123,9 @@ pub const Pool = struct { |
| 2123 | 2123 | }); |
| 2124 | 2124 | } |
| 2125 | 2125 | }, |
| 2126 | .owner_decl => |owner_decl| pool.items.appendAssumeCapacity(.{ | |
| 2126 | .index => |index| pool.items.appendAssumeCapacity(.{ | |
| 2127 | 2127 | .tag = tag, |
| 2128 | .data = @intFromEnum(owner_decl), | |
| 2128 | .data = @intFromEnum(index), | |
| 2129 | 2129 | }), |
| 2130 | 2130 | }, |
| 2131 | 2131 | .aggregate => |aggregate_info| { |
| ... | ... | @@ -2133,7 +2133,7 @@ pub const Pool = struct { |
| 2133 | 2133 | .tag = tag, |
| 2134 | 2134 | .data = switch (aggregate_info.name) { |
| 2135 | 2135 | .anon => |anon| try pool.addExtra(allocator, AggregateAnon, .{ |
| 2136 | .owner_decl = anon.owner_decl, | |
| 2136 | .index = anon.index, | |
| 2137 | 2137 | .id = anon.id, |
| 2138 | 2138 | .fields_len = aggregate_info.fields.len, |
| 2139 | 2139 | }, aggregate_info.fields.len * @typeInfo(Field).Struct.fields.len), |
| ... | ... | @@ -2221,7 +2221,7 @@ pub const Pool = struct { |
| 2221 | 2221 | Pool.Tag => @compileError("pass tag to final"), |
| 2222 | 2222 | CType, CType.Index => @compileError("hash ctype.hash(pool) instead"), |
| 2223 | 2223 | String, String.Index => @compileError("hash string.slice(pool) instead"), |
| 2224 | u32, DeclIndex, Aligned.Flags => hasher.impl.update(std.mem.asBytes(&data)), | |
| 2224 | u32, InternPool.Index, Aligned.Flags => hasher.impl.update(std.mem.asBytes(&data)), | |
| 2225 | 2225 | []const u8 => hasher.impl.update(data), |
| 2226 | 2226 | else => @compileError("unhandled type: " ++ @typeName(@TypeOf(data))), |
| 2227 | 2227 | } |
| ... | ... | @@ -2426,7 +2426,7 @@ pub const Pool = struct { |
| 2426 | 2426 | }; |
| 2427 | 2427 | |
| 2428 | 2428 | const AggregateAnon = struct { |
| 2429 | owner_decl: DeclIndex, | |
| 2429 | index: InternPool.Index, | |
| 2430 | 2430 | id: u32, |
| 2431 | 2431 | fields_len: u32, |
| 2432 | 2432 | }; |
| ... | ... | @@ -2467,7 +2467,7 @@ pub const Pool = struct { |
| 2467 | 2467 | const value = @field(extra, field.name); |
| 2468 | 2468 | array.appendAssumeCapacity(switch (field.type) { |
| 2469 | 2469 | u32 => value, |
| 2470 | CType.Index, String.Index, DeclIndex => @intFromEnum(value), | |
| 2470 | CType.Index, String.Index, InternPool.Index => @intFromEnum(value), | |
| 2471 | 2471 | Aligned.Flags => @bitCast(value), |
| 2472 | 2472 | else => @compileError("bad field type: " ++ field.name ++ ": " ++ |
| 2473 | 2473 | @typeName(field.type)), |
| ... | ... | @@ -2530,7 +2530,7 @@ pub const Pool = struct { |
| 2530 | 2530 | inline for (fields, pool.extra.items[extra_index..][0..fields.len]) |field, value| |
| 2531 | 2531 | @field(extra, field.name) = switch (field.type) { |
| 2532 | 2532 | u32 => value, |
| 2533 | CType.Index, String.Index, DeclIndex => @enumFromInt(value), | |
| 2533 | CType.Index, String.Index, InternPool.Index => @enumFromInt(value), | |
| 2534 | 2534 | Aligned.Flags => @bitCast(value), |
| 2535 | 2535 | else => @compileError("bad field type: " ++ field.name ++ ": " ++ @typeName(field.type)), |
| 2536 | 2536 | }; |
| ... | ... | @@ -2546,8 +2546,8 @@ pub const Pool = struct { |
| 2546 | 2546 | }; |
| 2547 | 2547 | |
| 2548 | 2548 | pub const AlignAs = packed struct { |
| 2549 | @"align": Alignment, | |
| 2550 | abi: Alignment, | |
| 2549 | @"align": InternPool.Alignment, | |
| 2550 | abi: InternPool.Alignment, | |
| 2551 | 2551 | |
| 2552 | 2552 | pub fn fromAlignment(alignas: AlignAs) AlignAs { |
| 2553 | 2553 | assert(alignas.abi != .none); |
| ... | ... | @@ -2556,14 +2556,14 @@ pub const AlignAs = packed struct { |
| 2556 | 2556 | .abi = alignas.abi, |
| 2557 | 2557 | }; |
| 2558 | 2558 | } |
| 2559 | pub fn fromAbiAlignment(abi: Alignment) AlignAs { | |
| 2559 | pub fn fromAbiAlignment(abi: InternPool.Alignment) AlignAs { | |
| 2560 | 2560 | assert(abi != .none); |
| 2561 | 2561 | return .{ .@"align" = abi, .abi = abi }; |
| 2562 | 2562 | } |
| 2563 | 2563 | pub fn fromByteUnits(@"align": u64, abi: u64) AlignAs { |
| 2564 | 2564 | return fromAlignment(.{ |
| 2565 | .@"align" = Alignment.fromByteUnits(@"align"), | |
| 2566 | .abi = Alignment.fromNonzeroByteUnits(abi), | |
| 2565 | .@"align" = InternPool.Alignment.fromByteUnits(@"align"), | |
| 2566 | .abi = InternPool.Alignment.fromNonzeroByteUnits(abi), | |
| 2567 | 2567 | }); |
| 2568 | 2568 | } |
| 2569 | 2569 | |
| ... | ... | @@ -2578,11 +2578,10 @@ pub const AlignAs = packed struct { |
| 2578 | 2578 | } |
| 2579 | 2579 | }; |
| 2580 | 2580 | |
| 2581 | const Alignment = @import("../../InternPool.zig").Alignment; | |
| 2582 | 2581 | const assert = std.debug.assert; |
| 2583 | 2582 | const CType = @This(); |
| 2583 | const InternPool = @import("../../InternPool.zig"); | |
| 2584 | 2584 | const Module = @import("../../Package/Module.zig"); |
| 2585 | 2585 | const std = @import("std"); |
| 2586 | 2586 | const Type = @import("../../Type.zig"); |
| 2587 | 2587 | const Zcu = @import("../../Zcu.zig"); |
| 2588 | const DeclIndex = @import("../../InternPool.zig").DeclIndex; |
src/codegen/llvm.zig+410-440| ... | ... | @@ -776,7 +776,7 @@ pub const Object = struct { |
| 776 | 776 | debug_enums: std.ArrayListUnmanaged(Builder.Metadata), |
| 777 | 777 | debug_globals: std.ArrayListUnmanaged(Builder.Metadata), |
| 778 | 778 | |
| 779 | debug_file_map: std.AutoHashMapUnmanaged(*const Zcu.File, Builder.Metadata), | |
| 779 | debug_file_map: std.AutoHashMapUnmanaged(Zcu.File.Index, Builder.Metadata), | |
| 780 | 780 | debug_type_map: std.AutoHashMapUnmanaged(Type, Builder.Metadata), |
| 781 | 781 | |
| 782 | 782 | debug_unresolved_namespace_scopes: std.AutoArrayHashMapUnmanaged(InternPool.NamespaceIndex, Builder.Metadata), |
| ... | ... | @@ -790,11 +790,13 @@ pub const Object = struct { |
| 790 | 790 | /// version of the name and incorrectly get function not found in the llvm module. |
| 791 | 791 | /// * it works for functions not all globals. |
| 792 | 792 | /// Therefore, this table keeps track of the mapping. |
| 793 | decl_map: std.AutoHashMapUnmanaged(InternPool.DeclIndex, Builder.Global.Index), | |
| 793 | nav_map: std.AutoHashMapUnmanaged(InternPool.Nav.Index, Builder.Global.Index), | |
| 794 | 794 | /// Same deal as `decl_map` but for anonymous declarations, which are always global constants. |
| 795 | anon_decl_map: std.AutoHashMapUnmanaged(InternPool.Index, Builder.Global.Index), | |
| 796 | /// Serves the same purpose as `decl_map` but only used for the `is_named_enum_value` instruction. | |
| 797 | named_enum_map: std.AutoHashMapUnmanaged(InternPool.DeclIndex, Builder.Function.Index), | |
| 795 | uav_map: std.AutoHashMapUnmanaged(InternPool.Index, Builder.Global.Index), | |
| 796 | /// Maps enum types to their corresponding LLVM functions for implementing the `tag_name` instruction. | |
| 797 | enum_tag_name_map: std.AutoHashMapUnmanaged(InternPool.Index, Builder.Global.Index), | |
| 798 | /// Serves the same purpose as `enum_tag_name_map` but for the `is_named_enum_value` instruction. | |
| 799 | named_enum_map: std.AutoHashMapUnmanaged(InternPool.Index, Builder.Function.Index), | |
| 798 | 800 | /// Maps Zig types to LLVM types. The table memory is backed by the GPA of |
| 799 | 801 | /// the compiler. |
| 800 | 802 | /// TODO when InternPool garbage collection is implemented, this map needs |
| ... | ... | @@ -963,8 +965,9 @@ pub const Object = struct { |
| 963 | 965 | .debug_type_map = .{}, |
| 964 | 966 | .debug_unresolved_namespace_scopes = .{}, |
| 965 | 967 | .target = target, |
| 966 | .decl_map = .{}, | |
| 967 | .anon_decl_map = .{}, | |
| 968 | .nav_map = .{}, | |
| 969 | .uav_map = .{}, | |
| 970 | .enum_tag_name_map = .{}, | |
| 968 | 971 | .named_enum_map = .{}, |
| 969 | 972 | .type_map = .{}, |
| 970 | 973 | .error_name_table = .none, |
| ... | ... | @@ -981,8 +984,9 @@ pub const Object = struct { |
| 981 | 984 | self.debug_file_map.deinit(gpa); |
| 982 | 985 | self.debug_type_map.deinit(gpa); |
| 983 | 986 | self.debug_unresolved_namespace_scopes.deinit(gpa); |
| 984 | self.decl_map.deinit(gpa); | |
| 985 | self.anon_decl_map.deinit(gpa); | |
| 987 | self.nav_map.deinit(gpa); | |
| 988 | self.uav_map.deinit(gpa); | |
| 989 | self.enum_tag_name_map.deinit(gpa); | |
| 986 | 990 | self.named_enum_map.deinit(gpa); |
| 987 | 991 | self.type_map.deinit(gpa); |
| 988 | 992 | self.builder.deinit(); |
| ... | ... | @@ -1108,7 +1112,7 @@ pub const Object = struct { |
| 1108 | 1112 | const fwd_ref = self.debug_unresolved_namespace_scopes.values()[i]; |
| 1109 | 1113 | |
| 1110 | 1114 | const namespace = zcu.namespacePtr(namespace_index); |
| 1111 | const debug_type = try self.lowerDebugType(namespace.getType(zcu)); | |
| 1115 | const debug_type = try self.lowerDebugType(Type.fromInterned(namespace.owner_type)); | |
| 1112 | 1116 | |
| 1113 | 1117 | self.builder.debugForwardReferenceSetType(fwd_ref, debug_type); |
| 1114 | 1118 | } |
| ... | ... | @@ -1328,24 +1332,22 @@ pub const Object = struct { |
| 1328 | 1332 | assert(std.meta.eql(pt, o.pt)); |
| 1329 | 1333 | const zcu = pt.zcu; |
| 1330 | 1334 | const comp = zcu.comp; |
| 1335 | const ip = &zcu.intern_pool; | |
| 1331 | 1336 | const func = zcu.funcInfo(func_index); |
| 1332 | const decl_index = func.owner_decl; | |
| 1333 | const decl = zcu.declPtr(decl_index); | |
| 1334 | const namespace = zcu.namespacePtr(decl.src_namespace); | |
| 1335 | const file_scope = namespace.fileScope(zcu); | |
| 1336 | const owner_mod = file_scope.mod; | |
| 1337 | const fn_info = zcu.typeToFunc(decl.typeOf(zcu)).?; | |
| 1337 | const nav = ip.getNav(func.owner_nav); | |
| 1338 | const file_scope = zcu.navFileScopeIndex(func.owner_nav); | |
| 1339 | const owner_mod = zcu.fileByIndex(file_scope).mod; | |
| 1340 | const fn_ty = Type.fromInterned(func.ty); | |
| 1341 | const fn_info = zcu.typeToFunc(fn_ty).?; | |
| 1338 | 1342 | const target = owner_mod.resolved_target.result; |
| 1339 | const ip = &zcu.intern_pool; | |
| 1340 | 1343 | |
| 1341 | var dg: DeclGen = .{ | |
| 1344 | var ng: NavGen = .{ | |
| 1342 | 1345 | .object = o, |
| 1343 | .decl_index = decl_index, | |
| 1344 | .decl = decl, | |
| 1346 | .nav_index = func.owner_nav, | |
| 1345 | 1347 | .err_msg = null, |
| 1346 | 1348 | }; |
| 1347 | 1349 | |
| 1348 | const function_index = try o.resolveLlvmFunction(decl_index); | |
| 1350 | const function_index = try o.resolveLlvmFunction(func.owner_nav); | |
| 1349 | 1351 | |
| 1350 | 1352 | var attributes = try function_index.ptrConst(&o.builder).attributes.toWip(&o.builder); |
| 1351 | 1353 | defer attributes.deinit(&o.builder); |
| ... | ... | @@ -1409,7 +1411,7 @@ pub const Object = struct { |
| 1409 | 1411 | } }, &o.builder); |
| 1410 | 1412 | } |
| 1411 | 1413 | |
| 1412 | if (decl.@"linksection".toSlice(ip)) |section| | |
| 1414 | if (nav.status.resolved.@"linksection".toSlice(ip)) |section| | |
| 1413 | 1415 | function_index.setSection(try o.builder.string(section), &o.builder); |
| 1414 | 1416 | |
| 1415 | 1417 | var deinit_wip = true; |
| ... | ... | @@ -1422,7 +1424,7 @@ pub const Object = struct { |
| 1422 | 1424 | |
| 1423 | 1425 | var llvm_arg_i: u32 = 0; |
| 1424 | 1426 | |
| 1425 | // This gets the LLVM values from the function and stores them in `dg.args`. | |
| 1427 | // This gets the LLVM values from the function and stores them in `ng.args`. | |
| 1426 | 1428 | const sret = firstParamSRet(fn_info, pt, target); |
| 1427 | 1429 | const ret_ptr: Builder.Value = if (sret) param: { |
| 1428 | 1430 | const param = wip.arg(llvm_arg_i); |
| ... | ... | @@ -1622,13 +1624,13 @@ pub const Object = struct { |
| 1622 | 1624 | const file, const subprogram = if (!wip.strip) debug_info: { |
| 1623 | 1625 | const file = try o.getDebugFile(file_scope); |
| 1624 | 1626 | |
| 1625 | const line_number = decl.navSrcLine(zcu) + 1; | |
| 1626 | const is_internal_linkage = decl.val.getExternFunc(zcu) == null; | |
| 1627 | const debug_decl_type = try o.lowerDebugType(decl.typeOf(zcu)); | |
| 1627 | const line_number = zcu.navSrcLine(func.owner_nav) + 1; | |
| 1628 | const is_internal_linkage = ip.indexToKey(nav.status.resolved.val) != .@"extern"; | |
| 1629 | const debug_decl_type = try o.lowerDebugType(fn_ty); | |
| 1628 | 1630 | |
| 1629 | 1631 | const subprogram = try o.builder.debugSubprogram( |
| 1630 | 1632 | file, |
| 1631 | try o.builder.metadataString(decl.name.toSlice(ip)), | |
| 1633 | try o.builder.metadataString(nav.name.toSlice(ip)), | |
| 1632 | 1634 | try o.builder.metadataStringFromStrtabString(function_index.name(&o.builder)), |
| 1633 | 1635 | line_number, |
| 1634 | 1636 | line_number + func.lbrace_line, |
| ... | ... | @@ -1654,7 +1656,7 @@ pub const Object = struct { |
| 1654 | 1656 | .gpa = gpa, |
| 1655 | 1657 | .air = air, |
| 1656 | 1658 | .liveness = liveness, |
| 1657 | .dg = &dg, | |
| 1659 | .ng = &ng, | |
| 1658 | 1660 | .wip = wip, |
| 1659 | 1661 | .is_naked = fn_info.cc == .Naked, |
| 1660 | 1662 | .ret_ptr = ret_ptr, |
| ... | ... | @@ -1665,7 +1667,7 @@ pub const Object = struct { |
| 1665 | 1667 | .sync_scope = if (owner_mod.single_threaded) .singlethread else .system, |
| 1666 | 1668 | .file = file, |
| 1667 | 1669 | .scope = subprogram, |
| 1668 | .base_line = dg.decl.navSrcLine(zcu), | |
| 1670 | .base_line = zcu.navSrcLine(func.owner_nav), | |
| 1669 | 1671 | .prev_dbg_line = 0, |
| 1670 | 1672 | .prev_dbg_column = 0, |
| 1671 | 1673 | .err_ret_trace = err_ret_trace, |
| ... | ... | @@ -1675,9 +1677,8 @@ pub const Object = struct { |
| 1675 | 1677 | |
| 1676 | 1678 | fg.genBody(air.getMainBody()) catch |err| switch (err) { |
| 1677 | 1679 | error.CodegenFail => { |
| 1678 | decl.analysis = .codegen_failure; | |
| 1679 | try zcu.failed_analysis.put(zcu.gpa, InternPool.AnalUnit.wrap(.{ .decl = decl_index }), dg.err_msg.?); | |
| 1680 | dg.err_msg = null; | |
| 1680 | try zcu.failed_codegen.put(zcu.gpa, func.owner_nav, ng.err_msg.?); | |
| 1681 | ng.err_msg = null; | |
| 1681 | 1682 | return; |
| 1682 | 1683 | }, |
| 1683 | 1684 | else => |e| return e, |
| ... | ... | @@ -1686,20 +1687,17 @@ pub const Object = struct { |
| 1686 | 1687 | try fg.wip.finish(); |
| 1687 | 1688 | } |
| 1688 | 1689 | |
| 1689 | pub fn updateDecl(self: *Object, pt: Zcu.PerThread, decl_index: InternPool.DeclIndex) !void { | |
| 1690 | pub fn updateNav(self: *Object, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) !void { | |
| 1690 | 1691 | assert(std.meta.eql(pt, self.pt)); |
| 1691 | const decl = pt.zcu.declPtr(decl_index); | |
| 1692 | var dg: DeclGen = .{ | |
| 1692 | var ng: NavGen = .{ | |
| 1693 | 1693 | .object = self, |
| 1694 | .decl = decl, | |
| 1695 | .decl_index = decl_index, | |
| 1694 | .nav_index = nav_index, | |
| 1696 | 1695 | .err_msg = null, |
| 1697 | 1696 | }; |
| 1698 | dg.genDecl() catch |err| switch (err) { | |
| 1697 | ng.genDecl() catch |err| switch (err) { | |
| 1699 | 1698 | error.CodegenFail => { |
| 1700 | decl.analysis = .codegen_failure; | |
| 1701 | try pt.zcu.failed_analysis.put(pt.zcu.gpa, InternPool.AnalUnit.wrap(.{ .decl = decl_index }), dg.err_msg.?); | |
| 1702 | dg.err_msg = null; | |
| 1699 | try pt.zcu.failed_codegen.put(pt.zcu.gpa, nav_index, ng.err_msg.?); | |
| 1700 | ng.err_msg = null; | |
| 1703 | 1701 | return; |
| 1704 | 1702 | }, |
| 1705 | 1703 | else => |e| return e, |
| ... | ... | @@ -1714,19 +1712,18 @@ pub const Object = struct { |
| 1714 | 1712 | ) link.File.UpdateExportsError!void { |
| 1715 | 1713 | assert(std.meta.eql(pt, self.pt)); |
| 1716 | 1714 | const zcu = pt.zcu; |
| 1717 | const decl_index = switch (exported) { | |
| 1718 | .decl_index => |i| i, | |
| 1719 | .value => |val| return updateExportedValue(self, zcu, val, export_indices), | |
| 1715 | const nav_index = switch (exported) { | |
| 1716 | .nav => |nav| nav, | |
| 1717 | .uav => |uav| return updateExportedValue(self, zcu, uav, export_indices), | |
| 1720 | 1718 | }; |
| 1721 | 1719 | const ip = &zcu.intern_pool; |
| 1722 | const global_index = self.decl_map.get(decl_index).?; | |
| 1723 | const decl = zcu.declPtr(decl_index); | |
| 1720 | const global_index = self.nav_map.get(nav_index).?; | |
| 1724 | 1721 | const comp = zcu.comp; |
| 1725 | 1722 | |
| 1726 | 1723 | if (export_indices.len != 0) { |
| 1727 | 1724 | return updateExportedGlobal(self, zcu, global_index, export_indices); |
| 1728 | 1725 | } else { |
| 1729 | const fqn = try self.builder.strtabString(decl.fqn.toSlice(ip)); | |
| 1726 | const fqn = try self.builder.strtabString(ip.getNav(nav_index).fqn.toSlice(ip)); | |
| 1730 | 1727 | try global_index.rename(fqn, &self.builder); |
| 1731 | 1728 | global_index.setLinkage(.internal, &self.builder); |
| 1732 | 1729 | if (comp.config.dll_export_fns) |
| ... | ... | @@ -1745,7 +1742,7 @@ pub const Object = struct { |
| 1745 | 1742 | const ip = &mod.intern_pool; |
| 1746 | 1743 | const main_exp_name = try o.builder.strtabString(mod.all_exports.items[export_indices[0]].opts.name.toSlice(ip)); |
| 1747 | 1744 | const global_index = i: { |
| 1748 | const gop = try o.anon_decl_map.getOrPut(gpa, exported_value); | |
| 1745 | const gop = try o.uav_map.getOrPut(gpa, exported_value); | |
| 1749 | 1746 | if (gop.found_existing) { |
| 1750 | 1747 | const global_index = gop.value_ptr.*; |
| 1751 | 1748 | try global_index.rename(main_exp_name, &o.builder); |
| ... | ... | @@ -1868,11 +1865,12 @@ pub const Object = struct { |
| 1868 | 1865 | global.delete(&self.builder); |
| 1869 | 1866 | } |
| 1870 | 1867 | |
| 1871 | fn getDebugFile(o: *Object, file: *const Zcu.File) Allocator.Error!Builder.Metadata { | |
| 1868 | fn getDebugFile(o: *Object, file_index: Zcu.File.Index) Allocator.Error!Builder.Metadata { | |
| 1872 | 1869 | const gpa = o.gpa; |
| 1873 | const gop = try o.debug_file_map.getOrPut(gpa, file); | |
| 1874 | errdefer assert(o.debug_file_map.remove(file)); | |
| 1870 | const gop = try o.debug_file_map.getOrPut(gpa, file_index); | |
| 1871 | errdefer assert(o.debug_file_map.remove(file_index)); | |
| 1875 | 1872 | if (gop.found_existing) return gop.value_ptr.*; |
| 1873 | const file = o.pt.zcu.fileByIndex(file_index); | |
| 1876 | 1874 | gop.value_ptr.* = try o.builder.debugFile( |
| 1877 | 1875 | try o.builder.metadataString(std.fs.path.basename(file.sub_file_path)), |
| 1878 | 1876 | dir_path: { |
| ... | ... | @@ -1930,17 +1928,13 @@ pub const Object = struct { |
| 1930 | 1928 | return debug_int_type; |
| 1931 | 1929 | }, |
| 1932 | 1930 | .Enum => { |
| 1933 | const owner_decl_index = ty.getOwnerDecl(zcu); | |
| 1934 | const owner_decl = zcu.declPtr(owner_decl_index); | |
| 1935 | ||
| 1936 | 1931 | if (!ty.hasRuntimeBitsIgnoreComptime(pt)) { |
| 1937 | const debug_enum_type = try o.makeEmptyNamespaceDebugType(owner_decl_index); | |
| 1932 | const debug_enum_type = try o.makeEmptyNamespaceDebugType(ty); | |
| 1938 | 1933 | try o.debug_type_map.put(gpa, ty, debug_enum_type); |
| 1939 | 1934 | return debug_enum_type; |
| 1940 | 1935 | } |
| 1941 | 1936 | |
| 1942 | 1937 | const enum_type = ip.loadEnumType(ty.toIntern()); |
| 1943 | ||
| 1944 | 1938 | const enumerators = try gpa.alloc(Builder.Metadata, enum_type.names.len); |
| 1945 | 1939 | defer gpa.free(enumerators); |
| 1946 | 1940 | |
| ... | ... | @@ -1963,9 +1957,11 @@ pub const Object = struct { |
| 1963 | 1957 | ); |
| 1964 | 1958 | } |
| 1965 | 1959 | |
| 1966 | const file_scope = zcu.namespacePtr(owner_decl.src_namespace).fileScope(zcu); | |
| 1967 | const file = try o.getDebugFile(file_scope); | |
| 1968 | const scope = try o.namespaceToDebugScope(owner_decl.src_namespace); | |
| 1960 | const file = try o.getDebugFile(ty.typeDeclInstAllowGeneratedTag(zcu).?.resolveFull(ip).file); | |
| 1961 | const scope = if (ty.getParentNamespace(zcu).unwrap()) |parent_namespace| | |
| 1962 | try o.namespaceToDebugScope(parent_namespace) | |
| 1963 | else | |
| 1964 | file; | |
| 1969 | 1965 | |
| 1970 | 1966 | const name = try o.allocTypeName(ty); |
| 1971 | 1967 | defer gpa.free(name); |
| ... | ... | @@ -1974,7 +1970,7 @@ pub const Object = struct { |
| 1974 | 1970 | try o.builder.metadataString(name), |
| 1975 | 1971 | file, |
| 1976 | 1972 | scope, |
| 1977 | owner_decl.typeSrcLine(zcu) + 1, // Line | |
| 1973 | ty.typeDeclSrcLine(zcu).? + 1, // Line | |
| 1978 | 1974 | try o.lowerDebugType(int_ty), |
| 1979 | 1975 | ty.abiSize(pt) * 8, |
| 1980 | 1976 | (ty.abiAlignment(pt).toByteUnits() orelse 0) * 8, |
| ... | ... | @@ -2138,14 +2134,18 @@ pub const Object = struct { |
| 2138 | 2134 | |
| 2139 | 2135 | const name = try o.allocTypeName(ty); |
| 2140 | 2136 | defer gpa.free(name); |
| 2141 | const owner_decl_index = ty.getOwnerDecl(zcu); | |
| 2142 | const owner_decl = zcu.declPtr(owner_decl_index); | |
| 2143 | const file_scope = zcu.namespacePtr(owner_decl.src_namespace).fileScope(zcu); | |
| 2137 | ||
| 2138 | const file = try o.getDebugFile(ty.typeDeclInstAllowGeneratedTag(zcu).?.resolveFull(ip).file); | |
| 2139 | const scope = if (ty.getParentNamespace(zcu).unwrap()) |parent_namespace| | |
| 2140 | try o.namespaceToDebugScope(parent_namespace) | |
| 2141 | else | |
| 2142 | file; | |
| 2143 | ||
| 2144 | 2144 | const debug_opaque_type = try o.builder.debugStructType( |
| 2145 | 2145 | try o.builder.metadataString(name), |
| 2146 | try o.getDebugFile(file_scope), | |
| 2147 | try o.namespaceToDebugScope(owner_decl.src_namespace), | |
| 2148 | owner_decl.typeSrcLine(zcu) + 1, // Line | |
| 2146 | file, | |
| 2147 | scope, | |
| 2148 | ty.typeDeclSrcLine(zcu).? + 1, // Line | |
| 2149 | 2149 | .none, // Underlying type |
| 2150 | 2150 | 0, // Size |
| 2151 | 2151 | 0, // Align |
| ... | ... | @@ -2460,8 +2460,7 @@ pub const Object = struct { |
| 2460 | 2460 | // into. Therefore we can satisfy this by making an empty namespace, |
| 2461 | 2461 | // rather than changing the frontend to unnecessarily resolve the |
| 2462 | 2462 | // struct field types. |
| 2463 | const owner_decl_index = ty.getOwnerDecl(zcu); | |
| 2464 | const debug_struct_type = try o.makeEmptyNamespaceDebugType(owner_decl_index); | |
| 2463 | const debug_struct_type = try o.makeEmptyNamespaceDebugType(ty); | |
| 2465 | 2464 | try o.debug_type_map.put(gpa, ty, debug_struct_type); |
| 2466 | 2465 | return debug_struct_type; |
| 2467 | 2466 | } |
| ... | ... | @@ -2470,8 +2469,7 @@ pub const Object = struct { |
| 2470 | 2469 | } |
| 2471 | 2470 | |
| 2472 | 2471 | if (!ty.hasRuntimeBitsIgnoreComptime(pt)) { |
| 2473 | const owner_decl_index = ty.getOwnerDecl(zcu); | |
| 2474 | const debug_struct_type = try o.makeEmptyNamespaceDebugType(owner_decl_index); | |
| 2472 | const debug_struct_type = try o.makeEmptyNamespaceDebugType(ty); | |
| 2475 | 2473 | try o.debug_type_map.put(gpa, ty, debug_struct_type); |
| 2476 | 2474 | return debug_struct_type; |
| 2477 | 2475 | } |
| ... | ... | @@ -2536,8 +2534,6 @@ pub const Object = struct { |
| 2536 | 2534 | return debug_struct_type; |
| 2537 | 2535 | }, |
| 2538 | 2536 | .Union => { |
| 2539 | const owner_decl_index = ty.getOwnerDecl(zcu); | |
| 2540 | ||
| 2541 | 2537 | const name = try o.allocTypeName(ty); |
| 2542 | 2538 | defer gpa.free(name); |
| 2543 | 2539 | |
| ... | ... | @@ -2546,7 +2542,7 @@ pub const Object = struct { |
| 2546 | 2542 | !ty.hasRuntimeBitsIgnoreComptime(pt) or |
| 2547 | 2543 | !union_type.haveLayout(ip)) |
| 2548 | 2544 | { |
| 2549 | const debug_union_type = try o.makeEmptyNamespaceDebugType(owner_decl_index); | |
| 2545 | const debug_union_type = try o.makeEmptyNamespaceDebugType(ty); | |
| 2550 | 2546 | try o.debug_type_map.put(gpa, ty, debug_union_type); |
| 2551 | 2547 | return debug_union_type; |
| 2552 | 2548 | } |
| ... | ... | @@ -2762,8 +2758,7 @@ pub const Object = struct { |
| 2762 | 2758 | fn namespaceToDebugScope(o: *Object, namespace_index: InternPool.NamespaceIndex) !Builder.Metadata { |
| 2763 | 2759 | const zcu = o.pt.zcu; |
| 2764 | 2760 | const namespace = zcu.namespacePtr(namespace_index); |
| 2765 | const file_scope = namespace.fileScope(zcu); | |
| 2766 | if (namespace.parent == .none) return try o.getDebugFile(file_scope); | |
| 2761 | if (namespace.parent == .none) return try o.getDebugFile(namespace.file_scope); | |
| 2767 | 2762 | |
| 2768 | 2763 | const gop = try o.debug_unresolved_namespace_scopes.getOrPut(o.gpa, namespace_index); |
| 2769 | 2764 | |
| ... | ... | @@ -2772,15 +2767,19 @@ pub const Object = struct { |
| 2772 | 2767 | return gop.value_ptr.*; |
| 2773 | 2768 | } |
| 2774 | 2769 | |
| 2775 | fn makeEmptyNamespaceDebugType(o: *Object, decl_index: InternPool.DeclIndex) !Builder.Metadata { | |
| 2770 | fn makeEmptyNamespaceDebugType(o: *Object, ty: Type) !Builder.Metadata { | |
| 2776 | 2771 | const zcu = o.pt.zcu; |
| 2777 | const decl = zcu.declPtr(decl_index); | |
| 2778 | const file_scope = zcu.namespacePtr(decl.src_namespace).fileScope(zcu); | |
| 2772 | const ip = &zcu.intern_pool; | |
| 2773 | const file = try o.getDebugFile(ty.typeDeclInstAllowGeneratedTag(zcu).?.resolveFull(ip).file); | |
| 2774 | const scope = if (ty.getParentNamespace(zcu).unwrap()) |parent_namespace| | |
| 2775 | try o.namespaceToDebugScope(parent_namespace) | |
| 2776 | else | |
| 2777 | file; | |
| 2779 | 2778 | return o.builder.debugStructType( |
| 2780 | try o.builder.metadataString(decl.name.toSlice(&zcu.intern_pool)), // TODO use fully qualified name | |
| 2781 | try o.getDebugFile(file_scope), | |
| 2782 | try o.namespaceToDebugScope(decl.src_namespace), | |
| 2783 | decl.typeSrcLine(zcu) + 1, | |
| 2779 | try o.builder.metadataString(ty.containerTypeName(ip).toSlice(ip)), // TODO use fully qualified name | |
| 2780 | file, | |
| 2781 | scope, | |
| 2782 | ty.typeDeclSrcLine(zcu).? + 1, | |
| 2784 | 2783 | .none, |
| 2785 | 2784 | 0, |
| 2786 | 2785 | 0, |
| ... | ... | @@ -2791,25 +2790,24 @@ pub const Object = struct { |
| 2791 | 2790 | fn getStackTraceType(o: *Object) Allocator.Error!Type { |
| 2792 | 2791 | const pt = o.pt; |
| 2793 | 2792 | const zcu = pt.zcu; |
| 2793 | const ip = &zcu.intern_pool; | |
| 2794 | 2794 | |
| 2795 | 2795 | const std_mod = zcu.std_mod; |
| 2796 | 2796 | const std_file_imported = pt.importPkg(std_mod) catch unreachable; |
| 2797 | 2797 | |
| 2798 | const builtin_str = try zcu.intern_pool.getOrPutString(zcu.gpa, pt.tid, "builtin", .no_embedded_nulls); | |
| 2799 | const std_file_root_decl = zcu.fileRootDecl(std_file_imported.file_index); | |
| 2800 | const std_namespace = zcu.namespacePtr(zcu.declPtr(std_file_root_decl.unwrap().?).src_namespace); | |
| 2801 | const builtin_decl = std_namespace.decls.getKeyAdapted(builtin_str, Zcu.DeclAdapter{ .zcu = zcu }).?; | |
| 2798 | const builtin_str = try ip.getOrPutString(zcu.gpa, pt.tid, "builtin", .no_embedded_nulls); | |
| 2799 | const std_file_root_type = Type.fromInterned(zcu.fileRootType(std_file_imported.file_index)); | |
| 2800 | const std_namespace = ip.namespacePtr(std_file_root_type.getNamespaceIndex(zcu)); | |
| 2801 | const builtin_nav = std_namespace.pub_decls.getKeyAdapted(builtin_str, Zcu.Namespace.NameAdapter{ .zcu = zcu }).?; | |
| 2802 | 2802 | |
| 2803 | const stack_trace_str = try zcu.intern_pool.getOrPutString(zcu.gpa, pt.tid, "StackTrace", .no_embedded_nulls); | |
| 2803 | const stack_trace_str = try ip.getOrPutString(zcu.gpa, pt.tid, "StackTrace", .no_embedded_nulls); | |
| 2804 | 2804 | // buffer is only used for int_type, `builtin` is a struct. |
| 2805 | const builtin_ty = zcu.declPtr(builtin_decl).val.toType(); | |
| 2806 | const builtin_namespace = zcu.namespacePtrUnwrap(builtin_ty.getNamespaceIndex(zcu)).?; | |
| 2807 | const stack_trace_decl_index = builtin_namespace.decls.getKeyAdapted(stack_trace_str, Zcu.DeclAdapter{ .zcu = zcu }).?; | |
| 2808 | const stack_trace_decl = zcu.declPtr(stack_trace_decl_index); | |
| 2805 | const builtin_ty = zcu.navValue(builtin_nav).toType(); | |
| 2806 | const builtin_namespace = zcu.namespacePtr(builtin_ty.getNamespaceIndex(zcu)); | |
| 2807 | const stack_trace_nav = builtin_namespace.pub_decls.getKeyAdapted(stack_trace_str, Zcu.Namespace.NameAdapter{ .zcu = zcu }).?; | |
| 2809 | 2808 | |
| 2810 | 2809 | // Sema should have ensured that StackTrace was analyzed. |
| 2811 | assert(stack_trace_decl.has_tv); | |
| 2812 | return stack_trace_decl.val.toType(); | |
| 2810 | return zcu.navValue(stack_trace_nav).toType(); | |
| 2813 | 2811 | } |
| 2814 | 2812 | |
| 2815 | 2813 | fn allocTypeName(o: *Object, ty: Type) Allocator.Error![:0]const u8 { |
| ... | ... | @@ -2824,29 +2822,33 @@ pub const Object = struct { |
| 2824 | 2822 | /// completed, so if any attributes rely on that, they must be done in updateFunc, not here. |
| 2825 | 2823 | fn resolveLlvmFunction( |
| 2826 | 2824 | o: *Object, |
| 2827 | decl_index: InternPool.DeclIndex, | |
| 2825 | nav_index: InternPool.Nav.Index, | |
| 2828 | 2826 | ) Allocator.Error!Builder.Function.Index { |
| 2829 | 2827 | const pt = o.pt; |
| 2830 | 2828 | const zcu = pt.zcu; |
| 2831 | 2829 | const ip = &zcu.intern_pool; |
| 2832 | 2830 | const gpa = o.gpa; |
| 2833 | const decl = zcu.declPtr(decl_index); | |
| 2834 | const namespace = zcu.namespacePtr(decl.src_namespace); | |
| 2835 | const owner_mod = namespace.fileScope(zcu).mod; | |
| 2836 | const zig_fn_type = decl.typeOf(zcu); | |
| 2837 | const gop = try o.decl_map.getOrPut(gpa, decl_index); | |
| 2831 | const nav = ip.getNav(nav_index); | |
| 2832 | const owner_mod = zcu.navFileScope(nav_index).mod; | |
| 2833 | const resolved = nav.status.resolved; | |
| 2834 | const val = Value.fromInterned(resolved.val); | |
| 2835 | const ty = val.typeOf(zcu); | |
| 2836 | const gop = try o.nav_map.getOrPut(gpa, nav_index); | |
| 2838 | 2837 | if (gop.found_existing) return gop.value_ptr.ptr(&o.builder).kind.function; |
| 2839 | 2838 | |
| 2840 | assert(decl.has_tv); | |
| 2841 | const fn_info = zcu.typeToFunc(zig_fn_type).?; | |
| 2839 | const fn_info = zcu.typeToFunc(ty).?; | |
| 2842 | 2840 | const target = owner_mod.resolved_target.result; |
| 2843 | 2841 | const sret = firstParamSRet(fn_info, pt, target); |
| 2844 | 2842 | |
| 2845 | const is_extern = decl.isExtern(zcu); | |
| 2843 | const is_extern, const lib_name = switch (ip.indexToKey(val.toIntern())) { | |
| 2844 | .variable => |variable| .{ false, variable.lib_name }, | |
| 2845 | .@"extern" => |@"extern"| .{ true, @"extern".lib_name }, | |
| 2846 | else => .{ false, .none }, | |
| 2847 | }; | |
| 2846 | 2848 | const function_index = try o.builder.addFunction( |
| 2847 | try o.lowerType(zig_fn_type), | |
| 2848 | try o.builder.strtabString((if (is_extern) decl.name else decl.fqn).toSlice(ip)), | |
| 2849 | toLlvmAddressSpace(decl.@"addrspace", target), | |
| 2849 | try o.lowerType(ty), | |
| 2850 | try o.builder.strtabString((if (is_extern) nav.name else nav.fqn).toSlice(ip)), | |
| 2851 | toLlvmAddressSpace(resolved.@"addrspace", target), | |
| 2850 | 2852 | ); |
| 2851 | 2853 | gop.value_ptr.* = function_index.ptrConst(&o.builder).global; |
| 2852 | 2854 | |
| ... | ... | @@ -2860,12 +2862,12 @@ pub const Object = struct { |
| 2860 | 2862 | if (target.isWasm()) { |
| 2861 | 2863 | try attributes.addFnAttr(.{ .string = .{ |
| 2862 | 2864 | .kind = try o.builder.string("wasm-import-name"), |
| 2863 | .value = try o.builder.string(decl.name.toSlice(ip)), | |
| 2865 | .value = try o.builder.string(nav.name.toSlice(ip)), | |
| 2864 | 2866 | } }, &o.builder); |
| 2865 | if (decl.getOwnedExternFunc(zcu).?.lib_name.toSlice(ip)) |lib_name| { | |
| 2866 | if (!std.mem.eql(u8, lib_name, "c")) try attributes.addFnAttr(.{ .string = .{ | |
| 2867 | if (lib_name.toSlice(ip)) |lib_name_slice| { | |
| 2868 | if (!std.mem.eql(u8, lib_name_slice, "c")) try attributes.addFnAttr(.{ .string = .{ | |
| 2867 | 2869 | .kind = try o.builder.string("wasm-import-module"), |
| 2868 | .value = try o.builder.string(lib_name), | |
| 2870 | .value = try o.builder.string(lib_name_slice), | |
| 2869 | 2871 | } }, &o.builder); |
| 2870 | 2872 | } |
| 2871 | 2873 | } |
| ... | ... | @@ -2901,8 +2903,8 @@ pub const Object = struct { |
| 2901 | 2903 | else => function_index.setCallConv(toLlvmCallConv(fn_info.cc, target), &o.builder), |
| 2902 | 2904 | } |
| 2903 | 2905 | |
| 2904 | if (decl.alignment != .none) | |
| 2905 | function_index.setAlignment(decl.alignment.toLlvm(), &o.builder); | |
| 2906 | if (resolved.alignment != .none) | |
| 2907 | function_index.setAlignment(resolved.alignment.toLlvm(), &o.builder); | |
| 2906 | 2908 | |
| 2907 | 2909 | // Function attributes that are independent of analysis results of the function body. |
| 2908 | 2910 | try o.addCommonFnAttributes(&attributes, owner_mod); |
| ... | ... | @@ -3006,15 +3008,15 @@ pub const Object = struct { |
| 3006 | 3008 | } |
| 3007 | 3009 | } |
| 3008 | 3010 | |
| 3009 | fn resolveGlobalAnonDecl( | |
| 3011 | fn resolveGlobalUav( | |
| 3010 | 3012 | o: *Object, |
| 3011 | decl_val: InternPool.Index, | |
| 3013 | uav: InternPool.Index, | |
| 3012 | 3014 | llvm_addr_space: Builder.AddrSpace, |
| 3013 | 3015 | alignment: InternPool.Alignment, |
| 3014 | 3016 | ) Error!Builder.Variable.Index { |
| 3015 | 3017 | assert(alignment != .none); |
| 3016 | 3018 | // TODO: Add address space to the anon_decl_map |
| 3017 | const gop = try o.anon_decl_map.getOrPut(o.gpa, decl_val); | |
| 3019 | const gop = try o.uav_map.getOrPut(o.gpa, uav); | |
| 3018 | 3020 | if (gop.found_existing) { |
| 3019 | 3021 | // Keep the greater of the two alignments. |
| 3020 | 3022 | const variable_index = gop.value_ptr.ptr(&o.builder).kind.variable; |
| ... | ... | @@ -3023,19 +3025,19 @@ pub const Object = struct { |
| 3023 | 3025 | variable_index.setAlignment(max_alignment.toLlvm(), &o.builder); |
| 3024 | 3026 | return variable_index; |
| 3025 | 3027 | } |
| 3026 | errdefer assert(o.anon_decl_map.remove(decl_val)); | |
| 3028 | errdefer assert(o.uav_map.remove(uav)); | |
| 3027 | 3029 | |
| 3028 | 3030 | const mod = o.pt.zcu; |
| 3029 | const decl_ty = mod.intern_pool.typeOf(decl_val); | |
| 3031 | const decl_ty = mod.intern_pool.typeOf(uav); | |
| 3030 | 3032 | |
| 3031 | 3033 | const variable_index = try o.builder.addVariable( |
| 3032 | try o.builder.strtabStringFmt("__anon_{d}", .{@intFromEnum(decl_val)}), | |
| 3034 | try o.builder.strtabStringFmt("__anon_{d}", .{@intFromEnum(uav)}), | |
| 3033 | 3035 | try o.lowerType(Type.fromInterned(decl_ty)), |
| 3034 | 3036 | llvm_addr_space, |
| 3035 | 3037 | ); |
| 3036 | 3038 | gop.value_ptr.* = variable_index.ptrConst(&o.builder).global; |
| 3037 | 3039 | |
| 3038 | try variable_index.setInitializer(try o.lowerValue(decl_val), &o.builder); | |
| 3040 | try variable_index.setInitializer(try o.lowerValue(uav), &o.builder); | |
| 3039 | 3041 | variable_index.setLinkage(.internal, &o.builder); |
| 3040 | 3042 | variable_index.setMutability(.constant, &o.builder); |
| 3041 | 3043 | variable_index.setUnnamedAddr(.unnamed_addr, &o.builder); |
| ... | ... | @@ -3043,24 +3045,29 @@ pub const Object = struct { |
| 3043 | 3045 | return variable_index; |
| 3044 | 3046 | } |
| 3045 | 3047 | |
| 3046 | fn resolveGlobalDecl( | |
| 3048 | fn resolveGlobalNav( | |
| 3047 | 3049 | o: *Object, |
| 3048 | decl_index: InternPool.DeclIndex, | |
| 3050 | nav_index: InternPool.Nav.Index, | |
| 3049 | 3051 | ) Allocator.Error!Builder.Variable.Index { |
| 3050 | const gop = try o.decl_map.getOrPut(o.gpa, decl_index); | |
| 3052 | const gop = try o.nav_map.getOrPut(o.gpa, nav_index); | |
| 3051 | 3053 | if (gop.found_existing) return gop.value_ptr.ptr(&o.builder).kind.variable; |
| 3052 | errdefer assert(o.decl_map.remove(decl_index)); | |
| 3054 | errdefer assert(o.nav_map.remove(nav_index)); | |
| 3053 | 3055 | |
| 3054 | 3056 | const pt = o.pt; |
| 3055 | 3057 | const zcu = pt.zcu; |
| 3056 | 3058 | const ip = &zcu.intern_pool; |
| 3057 | const decl = zcu.declPtr(decl_index); | |
| 3058 | const is_extern = decl.isExtern(zcu); | |
| 3059 | const nav = ip.getNav(nav_index); | |
| 3060 | const resolved = nav.status.resolved; | |
| 3061 | const is_extern, const is_threadlocal, const is_weak_linkage = switch (ip.indexToKey(resolved.val)) { | |
| 3062 | .variable => |variable| .{ false, variable.is_threadlocal, variable.is_weak_linkage }, | |
| 3063 | .@"extern" => |@"extern"| .{ true, @"extern".is_threadlocal, @"extern".is_weak_linkage }, | |
| 3064 | else => .{ false, false, false }, | |
| 3065 | }; | |
| 3059 | 3066 | |
| 3060 | 3067 | const variable_index = try o.builder.addVariable( |
| 3061 | try o.builder.strtabString((if (is_extern) decl.name else decl.fqn).toSlice(ip)), | |
| 3062 | try o.lowerType(decl.typeOf(zcu)), | |
| 3063 | toLlvmGlobalAddressSpace(decl.@"addrspace", zcu.getTarget()), | |
| 3068 | try o.builder.strtabString((if (is_extern) nav.name else nav.fqn).toSlice(ip)), | |
| 3069 | try o.lowerType(Type.fromInterned(nav.typeOf(ip))), | |
| 3070 | toLlvmGlobalAddressSpace(resolved.@"addrspace", zcu.getTarget()), | |
| 3064 | 3071 | ); |
| 3065 | 3072 | gop.value_ptr.* = variable_index.ptrConst(&o.builder).global; |
| 3066 | 3073 | |
| ... | ... | @@ -3068,15 +3075,9 @@ pub const Object = struct { |
| 3068 | 3075 | if (is_extern) { |
| 3069 | 3076 | variable_index.setLinkage(.external, &o.builder); |
| 3070 | 3077 | variable_index.setUnnamedAddr(.default, &o.builder); |
| 3071 | if (decl.val.getVariable(zcu)) |decl_var| { | |
| 3072 | const decl_namespace = zcu.namespacePtr(decl.src_namespace); | |
| 3073 | const single_threaded = decl_namespace.fileScope(zcu).mod.single_threaded; | |
| 3074 | variable_index.setThreadLocal( | |
| 3075 | if (decl_var.is_threadlocal and !single_threaded) .generaldynamic else .default, | |
| 3076 | &o.builder, | |
| 3077 | ); | |
| 3078 | if (decl_var.is_weak_linkage) variable_index.setLinkage(.extern_weak, &o.builder); | |
| 3079 | } | |
| 3078 | if (is_threadlocal and !zcu.navFileScope(nav_index).mod.single_threaded) | |
| 3079 | variable_index.setThreadLocal(.generaldynamic, &o.builder); | |
| 3080 | if (is_weak_linkage) variable_index.setLinkage(.extern_weak, &o.builder); | |
| 3080 | 3081 | } else { |
| 3081 | 3082 | variable_index.setLinkage(.internal, &o.builder); |
| 3082 | 3083 | variable_index.setUnnamedAddr(.unnamed_addr, &o.builder); |
| ... | ... | @@ -3286,8 +3287,6 @@ pub const Object = struct { |
| 3286 | 3287 | return int_ty; |
| 3287 | 3288 | } |
| 3288 | 3289 | |
| 3289 | const decl = mod.declPtr(struct_type.decl.unwrap().?); | |
| 3290 | ||
| 3291 | 3290 | var llvm_field_types = std.ArrayListUnmanaged(Builder.Type){}; |
| 3292 | 3291 | defer llvm_field_types.deinit(o.gpa); |
| 3293 | 3292 | // Although we can estimate how much capacity to add, these cannot be |
| ... | ... | @@ -3351,7 +3350,7 @@ pub const Object = struct { |
| 3351 | 3350 | ); |
| 3352 | 3351 | } |
| 3353 | 3352 | |
| 3354 | const ty = try o.builder.opaqueType(try o.builder.string(decl.fqn.toSlice(ip))); | |
| 3353 | const ty = try o.builder.opaqueType(try o.builder.string(t.containerTypeName(ip).toSlice(ip))); | |
| 3355 | 3354 | try o.type_map.put(o.gpa, t.toIntern(), ty); |
| 3356 | 3355 | |
| 3357 | 3356 | o.builder.namedTypeSetBody( |
| ... | ... | @@ -3440,8 +3439,6 @@ pub const Object = struct { |
| 3440 | 3439 | return enum_tag_ty; |
| 3441 | 3440 | } |
| 3442 | 3441 | |
| 3443 | const decl = mod.declPtr(union_obj.decl); | |
| 3444 | ||
| 3445 | 3442 | const aligned_field_ty = Type.fromInterned(union_obj.field_types.get(ip)[layout.most_aligned_field]); |
| 3446 | 3443 | const aligned_field_llvm_ty = try o.lowerType(aligned_field_ty); |
| 3447 | 3444 | |
| ... | ... | @@ -3460,7 +3457,7 @@ pub const Object = struct { |
| 3460 | 3457 | }; |
| 3461 | 3458 | |
| 3462 | 3459 | if (layout.tag_size == 0) { |
| 3463 | const ty = try o.builder.opaqueType(try o.builder.string(decl.fqn.toSlice(ip))); | |
| 3460 | const ty = try o.builder.opaqueType(try o.builder.string(t.containerTypeName(ip).toSlice(ip))); | |
| 3464 | 3461 | try o.type_map.put(o.gpa, t.toIntern(), ty); |
| 3465 | 3462 | |
| 3466 | 3463 | o.builder.namedTypeSetBody( |
| ... | ... | @@ -3488,7 +3485,7 @@ pub const Object = struct { |
| 3488 | 3485 | llvm_fields_len += 1; |
| 3489 | 3486 | } |
| 3490 | 3487 | |
| 3491 | const ty = try o.builder.opaqueType(try o.builder.string(decl.fqn.toSlice(ip))); | |
| 3488 | const ty = try o.builder.opaqueType(try o.builder.string(t.containerTypeName(ip).toSlice(ip))); | |
| 3492 | 3489 | try o.type_map.put(o.gpa, t.toIntern(), ty); |
| 3493 | 3490 | |
| 3494 | 3491 | o.builder.namedTypeSetBody( |
| ... | ... | @@ -3500,8 +3497,7 @@ pub const Object = struct { |
| 3500 | 3497 | .opaque_type => { |
| 3501 | 3498 | const gop = try o.type_map.getOrPut(o.gpa, t.toIntern()); |
| 3502 | 3499 | if (!gop.found_existing) { |
| 3503 | const decl = mod.declPtr(ip.loadOpaqueType(t.toIntern()).decl); | |
| 3504 | gop.value_ptr.* = try o.builder.opaqueType(try o.builder.string(decl.fqn.toSlice(ip))); | |
| 3500 | gop.value_ptr.* = try o.builder.opaqueType(try o.builder.string(t.containerTypeName(ip).toSlice(ip))); | |
| 3505 | 3501 | } |
| 3506 | 3502 | return gop.value_ptr.*; |
| 3507 | 3503 | }, |
| ... | ... | @@ -3512,7 +3508,7 @@ pub const Object = struct { |
| 3512 | 3508 | .undef, |
| 3513 | 3509 | .simple_value, |
| 3514 | 3510 | .variable, |
| 3515 | .extern_func, | |
| 3511 | .@"extern", | |
| 3516 | 3512 | .func, |
| 3517 | 3513 | .int, |
| 3518 | 3514 | .err, |
| ... | ... | @@ -3632,15 +3628,13 @@ pub const Object = struct { |
| 3632 | 3628 | |
| 3633 | 3629 | const ty = Type.fromInterned(val_key.typeOf()); |
| 3634 | 3630 | switch (val_key) { |
| 3635 | .extern_func => |extern_func| { | |
| 3636 | const fn_decl_index = extern_func.decl; | |
| 3637 | const function_index = try o.resolveLlvmFunction(fn_decl_index); | |
| 3631 | .@"extern" => |@"extern"| { | |
| 3632 | const function_index = try o.resolveLlvmFunction(@"extern".owner_nav); | |
| 3638 | 3633 | const ptr = function_index.ptrConst(&o.builder).global.toConst(); |
| 3639 | 3634 | return o.builder.convConst(ptr, llvm_int_ty); |
| 3640 | 3635 | }, |
| 3641 | 3636 | .func => |func| { |
| 3642 | const fn_decl_index = func.owner_decl; | |
| 3643 | const function_index = try o.resolveLlvmFunction(fn_decl_index); | |
| 3637 | const function_index = try o.resolveLlvmFunction(func.owner_nav); | |
| 3644 | 3638 | const ptr = function_index.ptrConst(&o.builder).global.toConst(); |
| 3645 | 3639 | return o.builder.convConst(ptr, llvm_int_ty); |
| 3646 | 3640 | }, |
| ... | ... | @@ -3783,14 +3777,12 @@ pub const Object = struct { |
| 3783 | 3777 | .enum_literal, |
| 3784 | 3778 | .empty_enum_value, |
| 3785 | 3779 | => unreachable, // non-runtime values |
| 3786 | .extern_func => |extern_func| { | |
| 3787 | const fn_decl_index = extern_func.decl; | |
| 3788 | const function_index = try o.resolveLlvmFunction(fn_decl_index); | |
| 3780 | .@"extern" => |@"extern"| { | |
| 3781 | const function_index = try o.resolveLlvmFunction(@"extern".owner_nav); | |
| 3789 | 3782 | return function_index.ptrConst(&o.builder).global.toConst(); |
| 3790 | 3783 | }, |
| 3791 | 3784 | .func => |func| { |
| 3792 | const fn_decl_index = func.owner_decl; | |
| 3793 | const function_index = try o.resolveLlvmFunction(fn_decl_index); | |
| 3785 | const function_index = try o.resolveLlvmFunction(func.owner_nav); | |
| 3794 | 3786 | return function_index.ptrConst(&o.builder).global.toConst(); |
| 3795 | 3787 | }, |
| 3796 | 3788 | .int => { |
| ... | ... | @@ -4284,14 +4276,14 @@ pub const Object = struct { |
| 4284 | 4276 | const ptr = zcu.intern_pool.indexToKey(ptr_val).ptr; |
| 4285 | 4277 | const offset: u64 = prev_offset + ptr.byte_offset; |
| 4286 | 4278 | return switch (ptr.base_addr) { |
| 4287 | .decl => |decl| { | |
| 4288 | const base_ptr = try o.lowerDeclRefValue(decl); | |
| 4279 | .nav => |nav| { | |
| 4280 | const base_ptr = try o.lowerNavRefValue(nav); | |
| 4289 | 4281 | return o.builder.gepConst(.inbounds, .i8, base_ptr, null, &.{ |
| 4290 | 4282 | try o.builder.intConst(.i64, offset), |
| 4291 | 4283 | }); |
| 4292 | 4284 | }, |
| 4293 | .anon_decl => |ad| { | |
| 4294 | const base_ptr = try o.lowerAnonDeclRef(ad); | |
| 4285 | .uav => |uav| { | |
| 4286 | const base_ptr = try o.lowerUavRef(uav); | |
| 4295 | 4287 | return o.builder.gepConst(.inbounds, .i8, base_ptr, null, &.{ |
| 4296 | 4288 | try o.builder.intConst(.i64, offset), |
| 4297 | 4289 | }); |
| ... | ... | @@ -4332,39 +4324,37 @@ pub const Object = struct { |
| 4332 | 4324 | }; |
| 4333 | 4325 | } |
| 4334 | 4326 | |
| 4335 | /// This logic is very similar to `lowerDeclRefValue` but for anonymous declarations. | |
| 4327 | /// This logic is very similar to `lowerNavRefValue` but for anonymous declarations. | |
| 4336 | 4328 | /// Maybe the logic could be unified. |
| 4337 | fn lowerAnonDeclRef( | |
| 4329 | fn lowerUavRef( | |
| 4338 | 4330 | o: *Object, |
| 4339 | anon_decl: InternPool.Key.Ptr.BaseAddr.AnonDecl, | |
| 4331 | uav: InternPool.Key.Ptr.BaseAddr.Uav, | |
| 4340 | 4332 | ) Error!Builder.Constant { |
| 4341 | 4333 | const pt = o.pt; |
| 4342 | 4334 | const mod = pt.zcu; |
| 4343 | 4335 | const ip = &mod.intern_pool; |
| 4344 | const decl_val = anon_decl.val; | |
| 4345 | const decl_ty = Type.fromInterned(ip.typeOf(decl_val)); | |
| 4336 | const uav_val = uav.val; | |
| 4337 | const uav_ty = Type.fromInterned(ip.typeOf(uav_val)); | |
| 4346 | 4338 | const target = mod.getTarget(); |
| 4347 | 4339 | |
| 4348 | if (Value.fromInterned(decl_val).getFunction(mod)) |func| { | |
| 4349 | _ = func; | |
| 4350 | @panic("TODO"); | |
| 4351 | } else if (Value.fromInterned(decl_val).getExternFunc(mod)) |func| { | |
| 4352 | _ = func; | |
| 4353 | @panic("TODO"); | |
| 4340 | switch (ip.indexToKey(uav_val)) { | |
| 4341 | .func => @panic("TODO"), | |
| 4342 | .@"extern" => @panic("TODO"), | |
| 4343 | else => {}, | |
| 4354 | 4344 | } |
| 4355 | 4345 | |
| 4356 | const ptr_ty = Type.fromInterned(anon_decl.orig_ty); | |
| 4346 | const ptr_ty = Type.fromInterned(uav.orig_ty); | |
| 4357 | 4347 | |
| 4358 | const is_fn_body = decl_ty.zigTypeTag(mod) == .Fn; | |
| 4359 | if ((!is_fn_body and !decl_ty.hasRuntimeBits(pt)) or | |
| 4360 | (is_fn_body and mod.typeToFunc(decl_ty).?.is_generic)) return o.lowerPtrToVoid(ptr_ty); | |
| 4348 | const is_fn_body = uav_ty.zigTypeTag(mod) == .Fn; | |
| 4349 | if ((!is_fn_body and !uav_ty.hasRuntimeBits(pt)) or | |
| 4350 | (is_fn_body and mod.typeToFunc(uav_ty).?.is_generic)) return o.lowerPtrToVoid(ptr_ty); | |
| 4361 | 4351 | |
| 4362 | 4352 | if (is_fn_body) |
| 4363 | 4353 | @panic("TODO"); |
| 4364 | 4354 | |
| 4365 | 4355 | const llvm_addr_space = toLlvmAddressSpace(ptr_ty.ptrAddressSpace(mod), target); |
| 4366 | 4356 | const alignment = ptr_ty.ptrAlignment(pt); |
| 4367 | const llvm_global = (try o.resolveGlobalAnonDecl(decl_val, llvm_addr_space, alignment)).ptrConst(&o.builder).global; | |
| 4357 | const llvm_global = (try o.resolveGlobalUav(uav.val, llvm_addr_space, alignment)).ptrConst(&o.builder).global; | |
| 4368 | 4358 | |
| 4369 | 4359 | const llvm_val = try o.builder.convConst( |
| 4370 | 4360 | llvm_global.toConst(), |
| ... | ... | @@ -4374,44 +4364,41 @@ pub const Object = struct { |
| 4374 | 4364 | return o.builder.convConst(llvm_val, try o.lowerType(ptr_ty)); |
| 4375 | 4365 | } |
| 4376 | 4366 | |
| 4377 | fn lowerDeclRefValue(o: *Object, decl_index: InternPool.DeclIndex) Allocator.Error!Builder.Constant { | |
| 4367 | fn lowerNavRefValue(o: *Object, nav_index: InternPool.Nav.Index) Allocator.Error!Builder.Constant { | |
| 4378 | 4368 | const pt = o.pt; |
| 4379 | const mod = pt.zcu; | |
| 4369 | const zcu = pt.zcu; | |
| 4370 | const ip = &zcu.intern_pool; | |
| 4380 | 4371 | |
| 4381 | 4372 | // In the case of something like: |
| 4382 | 4373 | // fn foo() void {} |
| 4383 | 4374 | // const bar = foo; |
| 4384 | 4375 | // ... &bar; |
| 4385 | 4376 | // `bar` is just an alias and we actually want to lower a reference to `foo`. |
| 4386 | const decl = mod.declPtr(decl_index); | |
| 4387 | if (decl.val.getFunction(mod)) |func| { | |
| 4388 | if (func.owner_decl != decl_index) { | |
| 4389 | return o.lowerDeclRefValue(func.owner_decl); | |
| 4390 | } | |
| 4391 | } else if (decl.val.getExternFunc(mod)) |func| { | |
| 4392 | if (func.decl != decl_index) { | |
| 4393 | return o.lowerDeclRefValue(func.decl); | |
| 4394 | } | |
| 4395 | } | |
| 4377 | const owner_nav_index = switch (ip.indexToKey(zcu.navValue(nav_index).toIntern())) { | |
| 4378 | .func => |func| func.owner_nav, | |
| 4379 | .@"extern" => |@"extern"| @"extern".owner_nav, | |
| 4380 | else => nav_index, | |
| 4381 | }; | |
| 4382 | const owner_nav = ip.getNav(owner_nav_index); | |
| 4396 | 4383 | |
| 4397 | const decl_ty = decl.typeOf(mod); | |
| 4398 | const ptr_ty = try decl.declPtrType(pt); | |
| 4384 | const nav_ty = Type.fromInterned(owner_nav.typeOf(ip)); | |
| 4385 | const ptr_ty = try pt.navPtrType(owner_nav_index); | |
| 4399 | 4386 | |
| 4400 | const is_fn_body = decl_ty.zigTypeTag(mod) == .Fn; | |
| 4401 | if ((!is_fn_body and !decl_ty.hasRuntimeBits(pt)) or | |
| 4402 | (is_fn_body and mod.typeToFunc(decl_ty).?.is_generic)) | |
| 4387 | const is_fn_body = nav_ty.zigTypeTag(zcu) == .Fn; | |
| 4388 | if ((!is_fn_body and !nav_ty.hasRuntimeBits(pt)) or | |
| 4389 | (is_fn_body and zcu.typeToFunc(nav_ty).?.is_generic)) | |
| 4403 | 4390 | { |
| 4404 | 4391 | return o.lowerPtrToVoid(ptr_ty); |
| 4405 | 4392 | } |
| 4406 | 4393 | |
| 4407 | 4394 | const llvm_global = if (is_fn_body) |
| 4408 | (try o.resolveLlvmFunction(decl_index)).ptrConst(&o.builder).global | |
| 4395 | (try o.resolveLlvmFunction(owner_nav_index)).ptrConst(&o.builder).global | |
| 4409 | 4396 | else |
| 4410 | (try o.resolveGlobalDecl(decl_index)).ptrConst(&o.builder).global; | |
| 4397 | (try o.resolveGlobalNav(owner_nav_index)).ptrConst(&o.builder).global; | |
| 4411 | 4398 | |
| 4412 | 4399 | const llvm_val = try o.builder.convConst( |
| 4413 | 4400 | llvm_global.toConst(), |
| 4414 | try o.builder.ptrType(toLlvmAddressSpace(decl.@"addrspace", mod.getTarget())), | |
| 4401 | try o.builder.ptrType(toLlvmAddressSpace(owner_nav.status.resolved.@"addrspace", zcu.getTarget())), | |
| 4415 | 4402 | ); |
| 4416 | 4403 | |
| 4417 | 4404 | return o.builder.convConst(llvm_val, try o.lowerType(ptr_ty)); |
| ... | ... | @@ -4553,18 +4540,16 @@ pub const Object = struct { |
| 4553 | 4540 | const ip = &zcu.intern_pool; |
| 4554 | 4541 | const enum_type = ip.loadEnumType(enum_ty.toIntern()); |
| 4555 | 4542 | |
| 4556 | // TODO: detect when the type changes and re-emit this function. | |
| 4557 | const gop = try o.decl_map.getOrPut(o.gpa, enum_type.decl); | |
| 4543 | const gop = try o.enum_tag_name_map.getOrPut(o.gpa, enum_ty.toIntern()); | |
| 4558 | 4544 | if (gop.found_existing) return gop.value_ptr.ptrConst(&o.builder).kind.function; |
| 4559 | errdefer assert(o.decl_map.remove(enum_type.decl)); | |
| 4545 | errdefer assert(o.enum_tag_name_map.remove(enum_ty.toIntern())); | |
| 4560 | 4546 | |
| 4561 | 4547 | const usize_ty = try o.lowerType(Type.usize); |
| 4562 | 4548 | const ret_ty = try o.lowerType(Type.slice_const_u8_sentinel_0); |
| 4563 | const decl = zcu.declPtr(enum_type.decl); | |
| 4564 | 4549 | const target = zcu.root_mod.resolved_target.result; |
| 4565 | 4550 | const function_index = try o.builder.addFunction( |
| 4566 | 4551 | try o.builder.fnType(ret_ty, &.{try o.lowerType(Type.fromInterned(enum_type.tag_ty))}, .normal), |
| 4567 | try o.builder.strtabStringFmt("__zig_tag_name_{}", .{decl.fqn.fmt(ip)}), | |
| 4552 | try o.builder.strtabStringFmt("__zig_tag_name_{}", .{enum_type.name.fmt(ip)}), | |
| 4568 | 4553 | toLlvmAddressSpace(.generic, target), |
| 4569 | 4554 | ); |
| 4570 | 4555 | |
| ... | ... | @@ -4624,86 +4609,73 @@ pub const Object = struct { |
| 4624 | 4609 | } |
| 4625 | 4610 | }; |
| 4626 | 4611 | |
| 4627 | pub const DeclGen = struct { | |
| 4612 | pub const NavGen = struct { | |
| 4628 | 4613 | object: *Object, |
| 4629 | decl: *Zcu.Decl, | |
| 4630 | decl_index: InternPool.DeclIndex, | |
| 4614 | nav_index: InternPool.Nav.Index, | |
| 4631 | 4615 | err_msg: ?*Zcu.ErrorMsg, |
| 4632 | 4616 | |
| 4633 | fn ownerModule(dg: DeclGen) *Package.Module { | |
| 4634 | const o = dg.object; | |
| 4635 | const zcu = o.pt.zcu; | |
| 4636 | const namespace = zcu.namespacePtr(dg.decl.src_namespace); | |
| 4637 | const file_scope = namespace.fileScope(zcu); | |
| 4638 | return file_scope.mod; | |
| 4617 | fn ownerModule(ng: NavGen) *Package.Module { | |
| 4618 | return ng.object.pt.zcu.navFileScope(ng.nav_index).mod; | |
| 4639 | 4619 | } |
| 4640 | 4620 | |
| 4641 | fn todo(dg: *DeclGen, comptime format: []const u8, args: anytype) Error { | |
| 4621 | fn todo(ng: *NavGen, comptime format: []const u8, args: anytype) Error { | |
| 4642 | 4622 | @setCold(true); |
| 4643 | assert(dg.err_msg == null); | |
| 4644 | const o = dg.object; | |
| 4623 | assert(ng.err_msg == null); | |
| 4624 | const o = ng.object; | |
| 4645 | 4625 | const gpa = o.gpa; |
| 4646 | const src_loc = dg.decl.navSrcLoc(o.pt.zcu); | |
| 4647 | dg.err_msg = try Zcu.ErrorMsg.create(gpa, src_loc, "TODO (LLVM): " ++ format, args); | |
| 4626 | const src_loc = o.pt.zcu.navSrcLoc(ng.nav_index); | |
| 4627 | ng.err_msg = try Zcu.ErrorMsg.create(gpa, src_loc, "TODO (LLVM): " ++ format, args); | |
| 4648 | 4628 | return error.CodegenFail; |
| 4649 | 4629 | } |
| 4650 | 4630 | |
| 4651 | fn genDecl(dg: *DeclGen) !void { | |
| 4652 | const o = dg.object; | |
| 4631 | fn genDecl(ng: *NavGen) !void { | |
| 4632 | const o = ng.object; | |
| 4653 | 4633 | const pt = o.pt; |
| 4654 | 4634 | const zcu = pt.zcu; |
| 4655 | 4635 | const ip = &zcu.intern_pool; |
| 4656 | const decl = dg.decl; | |
| 4657 | const decl_index = dg.decl_index; | |
| 4658 | assert(decl.has_tv); | |
| 4636 | const nav_index = ng.nav_index; | |
| 4637 | const nav = ip.getNav(nav_index); | |
| 4638 | const resolved = nav.status.resolved; | |
| 4639 | ||
| 4640 | const is_extern, const lib_name, const is_threadlocal, const is_weak_linkage, const is_const, const init_val, const owner_nav = switch (ip.indexToKey(resolved.val)) { | |
| 4641 | .variable => |variable| .{ false, variable.lib_name, variable.is_threadlocal, variable.is_weak_linkage, false, variable.init, variable.owner_nav }, | |
| 4642 | .@"extern" => |@"extern"| .{ true, @"extern".lib_name, @"extern".is_threadlocal, @"extern".is_weak_linkage, @"extern".is_const, .none, @"extern".owner_nav }, | |
| 4643 | else => .{ false, .none, false, false, true, resolved.val, nav_index }, | |
| 4644 | }; | |
| 4645 | const ty = Type.fromInterned(nav.typeOf(ip)); | |
| 4659 | 4646 | |
| 4660 | if (decl.val.getExternFunc(zcu)) |extern_func| { | |
| 4661 | _ = try o.resolveLlvmFunction(extern_func.decl); | |
| 4647 | if (is_extern and ip.isFunctionType(ty.toIntern())) { | |
| 4648 | _ = try o.resolveLlvmFunction(owner_nav); | |
| 4662 | 4649 | } else { |
| 4663 | const variable_index = try o.resolveGlobalDecl(decl_index); | |
| 4664 | variable_index.setAlignment( | |
| 4665 | decl.getAlignment(pt).toLlvm(), | |
| 4666 | &o.builder, | |
| 4667 | ); | |
| 4668 | if (decl.@"linksection".toSlice(ip)) |section| | |
| 4650 | const variable_index = try o.resolveGlobalNav(nav_index); | |
| 4651 | variable_index.setAlignment(pt.navAlignment(nav_index).toLlvm(), &o.builder); | |
| 4652 | if (resolved.@"linksection".toSlice(ip)) |section| | |
| 4669 | 4653 | variable_index.setSection(try o.builder.string(section), &o.builder); |
| 4670 | assert(decl.has_tv); | |
| 4671 | const init_val = if (decl.val.getVariable(zcu)) |decl_var| decl_var.init else init_val: { | |
| 4672 | variable_index.setMutability(.constant, &o.builder); | |
| 4673 | break :init_val decl.val.toIntern(); | |
| 4674 | }; | |
| 4654 | if (is_const) variable_index.setMutability(.constant, &o.builder); | |
| 4675 | 4655 | try variable_index.setInitializer(switch (init_val) { |
| 4676 | 4656 | .none => .no_init, |
| 4677 | 4657 | else => try o.lowerValue(init_val), |
| 4678 | 4658 | }, &o.builder); |
| 4679 | 4659 | |
| 4680 | if (decl.val.getVariable(zcu)) |decl_var| { | |
| 4681 | const decl_namespace = zcu.namespacePtr(decl.src_namespace); | |
| 4682 | const single_threaded = decl_namespace.fileScope(zcu).mod.single_threaded; | |
| 4683 | variable_index.setThreadLocal( | |
| 4684 | if (decl_var.is_threadlocal and !single_threaded) .generaldynamic else .default, | |
| 4685 | &o.builder, | |
| 4686 | ); | |
| 4687 | } | |
| 4688 | ||
| 4689 | const line_number = decl.navSrcLine(zcu) + 1; | |
| 4660 | const file_scope = zcu.navFileScopeIndex(nav_index); | |
| 4661 | const mod = zcu.fileByIndex(file_scope).mod; | |
| 4662 | if (is_threadlocal and !mod.single_threaded) | |
| 4663 | variable_index.setThreadLocal(.generaldynamic, &o.builder); | |
| 4690 | 4664 | |
| 4691 | const namespace = zcu.namespacePtr(decl.src_namespace); | |
| 4692 | const file_scope = namespace.fileScope(zcu); | |
| 4693 | const owner_mod = file_scope.mod; | |
| 4665 | const line_number = zcu.navSrcLine(nav_index) + 1; | |
| 4694 | 4666 | |
| 4695 | if (!owner_mod.strip) { | |
| 4667 | if (!mod.strip) { | |
| 4696 | 4668 | const debug_file = try o.getDebugFile(file_scope); |
| 4697 | 4669 | |
| 4698 | 4670 | const debug_global_var = try o.builder.debugGlobalVar( |
| 4699 | try o.builder.metadataString(decl.name.toSlice(ip)), // Name | |
| 4671 | try o.builder.metadataString(nav.name.toSlice(ip)), // Name | |
| 4700 | 4672 | try o.builder.metadataStringFromStrtabString(variable_index.name(&o.builder)), // Linkage name |
| 4701 | 4673 | debug_file, // File |
| 4702 | 4674 | debug_file, // Scope |
| 4703 | 4675 | line_number, |
| 4704 | try o.lowerDebugType(decl.typeOf(zcu)), | |
| 4676 | try o.lowerDebugType(ty), | |
| 4705 | 4677 | variable_index, |
| 4706 | .{ .local = !decl.isExtern(zcu) }, | |
| 4678 | .{ .local = !is_extern }, | |
| 4707 | 4679 | ); |
| 4708 | 4680 | |
| 4709 | 4681 | const debug_expression = try o.builder.debugExpression(&.{}); |
| ... | ... | @@ -4718,18 +4690,18 @@ pub const DeclGen = struct { |
| 4718 | 4690 | } |
| 4719 | 4691 | } |
| 4720 | 4692 | |
| 4721 | if (decl.isExtern(zcu)) { | |
| 4722 | const global_index = o.decl_map.get(decl_index).?; | |
| 4693 | if (is_extern) { | |
| 4694 | const global_index = o.nav_map.get(nav_index).?; | |
| 4723 | 4695 | |
| 4724 | 4696 | const decl_name = decl_name: { |
| 4725 | if (zcu.getTarget().isWasm() and decl.typeOf(zcu).zigTypeTag(zcu) == .Fn) { | |
| 4726 | if (decl.getOwnedExternFunc(zcu).?.lib_name.toSlice(ip)) |lib_name| { | |
| 4727 | if (!std.mem.eql(u8, lib_name, "c")) { | |
| 4728 | break :decl_name try o.builder.strtabStringFmt("{}|{s}", .{ decl.name.fmt(ip), lib_name }); | |
| 4697 | if (zcu.getTarget().isWasm() and ty.zigTypeTag(zcu) == .Fn) { | |
| 4698 | if (lib_name.toSlice(ip)) |lib_name_slice| { | |
| 4699 | if (!std.mem.eql(u8, lib_name_slice, "c")) { | |
| 4700 | break :decl_name try o.builder.strtabStringFmt("{}|{s}", .{ nav.name.fmt(ip), lib_name_slice }); | |
| 4729 | 4701 | } |
| 4730 | 4702 | } |
| 4731 | 4703 | } |
| 4732 | break :decl_name try o.builder.strtabString(decl.name.toSlice(ip)); | |
| 4704 | break :decl_name try o.builder.strtabString(nav.name.toSlice(ip)); | |
| 4733 | 4705 | }; |
| 4734 | 4706 | |
| 4735 | 4707 | if (o.builder.getGlobal(decl_name)) |other_global| { |
| ... | ... | @@ -4746,16 +4718,14 @@ pub const DeclGen = struct { |
| 4746 | 4718 | if (zcu.comp.config.dll_export_fns) |
| 4747 | 4719 | global_index.setDllStorageClass(.default, &o.builder); |
| 4748 | 4720 | |
| 4749 | if (decl.val.getVariable(zcu)) |decl_var| { | |
| 4750 | if (decl_var.is_weak_linkage) global_index.setLinkage(.extern_weak, &o.builder); | |
| 4751 | } | |
| 4721 | if (is_weak_linkage) global_index.setLinkage(.extern_weak, &o.builder); | |
| 4752 | 4722 | } |
| 4753 | 4723 | } |
| 4754 | 4724 | }; |
| 4755 | 4725 | |
| 4756 | 4726 | pub const FuncGen = struct { |
| 4757 | 4727 | gpa: Allocator, |
| 4758 | dg: *DeclGen, | |
| 4728 | ng: *NavGen, | |
| 4759 | 4729 | air: Air, |
| 4760 | 4730 | liveness: Liveness, |
| 4761 | 4731 | wip: Builder.WipFunction, |
| ... | ... | @@ -4815,7 +4785,7 @@ pub const FuncGen = struct { |
| 4815 | 4785 | |
| 4816 | 4786 | fn todo(self: *FuncGen, comptime format: []const u8, args: anytype) Error { |
| 4817 | 4787 | @setCold(true); |
| 4818 | return self.dg.todo(format, args); | |
| 4788 | return self.ng.todo(format, args); | |
| 4819 | 4789 | } |
| 4820 | 4790 | |
| 4821 | 4791 | fn resolveInst(self: *FuncGen, inst: Air.Inst.Ref) !Builder.Value { |
| ... | ... | @@ -4823,13 +4793,13 @@ pub const FuncGen = struct { |
| 4823 | 4793 | const gop = try self.func_inst_table.getOrPut(gpa, inst); |
| 4824 | 4794 | if (gop.found_existing) return gop.value_ptr.*; |
| 4825 | 4795 | |
| 4826 | const llvm_val = try self.resolveValue((try self.air.value(inst, self.dg.object.pt)).?); | |
| 4796 | const llvm_val = try self.resolveValue((try self.air.value(inst, self.ng.object.pt)).?); | |
| 4827 | 4797 | gop.value_ptr.* = llvm_val.toValue(); |
| 4828 | 4798 | return llvm_val.toValue(); |
| 4829 | 4799 | } |
| 4830 | 4800 | |
| 4831 | 4801 | fn resolveValue(self: *FuncGen, val: Value) Error!Builder.Constant { |
| 4832 | const o = self.dg.object; | |
| 4802 | const o = self.ng.object; | |
| 4833 | 4803 | const pt = o.pt; |
| 4834 | 4804 | const ty = val.typeOf(pt.zcu); |
| 4835 | 4805 | const llvm_val = try o.lowerValue(val.toIntern()); |
| ... | ... | @@ -4855,7 +4825,7 @@ pub const FuncGen = struct { |
| 4855 | 4825 | } |
| 4856 | 4826 | |
| 4857 | 4827 | fn resolveNullOptUsize(self: *FuncGen) Error!Builder.Constant { |
| 4858 | const o = self.dg.object; | |
| 4828 | const o = self.ng.object; | |
| 4859 | 4829 | const pt = o.pt; |
| 4860 | 4830 | if (o.null_opt_usize == .no_init) { |
| 4861 | 4831 | o.null_opt_usize = try self.resolveValue(Value.fromInterned(try pt.intern(.{ .opt = .{ |
| ... | ... | @@ -4867,7 +4837,7 @@ pub const FuncGen = struct { |
| 4867 | 4837 | } |
| 4868 | 4838 | |
| 4869 | 4839 | fn genBody(self: *FuncGen, body: []const Air.Inst.Index) Error!void { |
| 4870 | const o = self.dg.object; | |
| 4840 | const o = self.ng.object; | |
| 4871 | 4841 | const mod = o.pt.zcu; |
| 4872 | 4842 | const ip = &mod.intern_pool; |
| 4873 | 4843 | const air_tags = self.air.instructions.items(.tag); |
| ... | ... | @@ -5132,20 +5102,19 @@ pub const FuncGen = struct { |
| 5132 | 5102 | defer self.scope = old_scope; |
| 5133 | 5103 | |
| 5134 | 5104 | if (maybe_inline_func) |inline_func| { |
| 5135 | const o = self.dg.object; | |
| 5105 | const o = self.ng.object; | |
| 5136 | 5106 | const pt = o.pt; |
| 5137 | 5107 | const zcu = pt.zcu; |
| 5108 | const ip = &zcu.intern_pool; | |
| 5138 | 5109 | |
| 5139 | 5110 | const func = zcu.funcInfo(inline_func); |
| 5140 | const decl_index = func.owner_decl; | |
| 5141 | const decl = zcu.declPtr(decl_index); | |
| 5142 | const namespace = zcu.namespacePtr(decl.src_namespace); | |
| 5143 | const file_scope = namespace.fileScope(zcu); | |
| 5144 | const owner_mod = file_scope.mod; | |
| 5111 | const nav = ip.getNav(func.owner_nav); | |
| 5112 | const file_scope = zcu.navFileScopeIndex(func.owner_nav); | |
| 5113 | const mod = zcu.fileByIndex(file_scope).mod; | |
| 5145 | 5114 | |
| 5146 | 5115 | self.file = try o.getDebugFile(file_scope); |
| 5147 | 5116 | |
| 5148 | const line_number = decl.navSrcLine(zcu) + 1; | |
| 5117 | const line_number = zcu.navSrcLine(func.owner_nav) + 1; | |
| 5149 | 5118 | self.inlined = self.wip.debug_location; |
| 5150 | 5119 | |
| 5151 | 5120 | const fn_ty = try pt.funcType(.{ |
| ... | ... | @@ -5155,15 +5124,15 @@ pub const FuncGen = struct { |
| 5155 | 5124 | |
| 5156 | 5125 | self.scope = try o.builder.debugSubprogram( |
| 5157 | 5126 | self.file, |
| 5158 | try o.builder.metadataString(decl.name.toSlice(&zcu.intern_pool)), | |
| 5159 | try o.builder.metadataString(decl.fqn.toSlice(&zcu.intern_pool)), | |
| 5127 | try o.builder.metadataString(nav.name.toSlice(&zcu.intern_pool)), | |
| 5128 | try o.builder.metadataString(nav.fqn.toSlice(&zcu.intern_pool)), | |
| 5160 | 5129 | line_number, |
| 5161 | 5130 | line_number + func.lbrace_line, |
| 5162 | 5131 | try o.lowerDebugType(fn_ty), |
| 5163 | 5132 | .{ |
| 5164 | 5133 | .di_flags = .{ .StaticMember = true }, |
| 5165 | 5134 | .sp_flags = .{ |
| 5166 | .Optimized = owner_mod.optimize_mode != .Debug, | |
| 5135 | .Optimized = mod.optimize_mode != .Debug, | |
| 5167 | 5136 | .Definition = true, |
| 5168 | 5137 | .LocalToUnit = true, // TODO: we can't know this at this point, since the function could be exported later! |
| 5169 | 5138 | }, |
| ... | ... | @@ -5171,7 +5140,7 @@ pub const FuncGen = struct { |
| 5171 | 5140 | o.debug_compile_unit, |
| 5172 | 5141 | ); |
| 5173 | 5142 | |
| 5174 | self.base_line = decl.navSrcLine(zcu); | |
| 5143 | self.base_line = zcu.navSrcLine(func.owner_nav); | |
| 5175 | 5144 | const inlined_at_location = try self.wip.debug_location.toMetadata(&o.builder); |
| 5176 | 5145 | self.wip.debug_location = .{ |
| 5177 | 5146 | .location = .{ |
| ... | ... | @@ -5183,7 +5152,7 @@ pub const FuncGen = struct { |
| 5183 | 5152 | }; |
| 5184 | 5153 | } |
| 5185 | 5154 | |
| 5186 | self.scope = try self.dg.object.builder.debugLexicalBlock( | |
| 5155 | self.scope = try self.ng.object.builder.debugLexicalBlock( | |
| 5187 | 5156 | self.scope, |
| 5188 | 5157 | self.file, |
| 5189 | 5158 | self.prev_dbg_line, |
| ... | ... | @@ -5214,7 +5183,7 @@ pub const FuncGen = struct { |
| 5214 | 5183 | const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; |
| 5215 | 5184 | const extra = self.air.extraData(Air.Call, pl_op.payload); |
| 5216 | 5185 | const args: []const Air.Inst.Ref = @ptrCast(self.air.extra[extra.end..][0..extra.data.args_len]); |
| 5217 | const o = self.dg.object; | |
| 5186 | const o = self.ng.object; | |
| 5218 | 5187 | const pt = o.pt; |
| 5219 | 5188 | const mod = pt.zcu; |
| 5220 | 5189 | const ip = &mod.intern_pool; |
| ... | ... | @@ -5515,14 +5484,15 @@ pub const FuncGen = struct { |
| 5515 | 5484 | } |
| 5516 | 5485 | |
| 5517 | 5486 | fn buildSimplePanic(fg: *FuncGen, panic_id: Zcu.PanicId) !void { |
| 5518 | const o = fg.dg.object; | |
| 5519 | const mod = o.pt.zcu; | |
| 5520 | const msg_decl_index = mod.panic_messages[@intFromEnum(panic_id)].unwrap().?; | |
| 5521 | const msg_decl = mod.declPtr(msg_decl_index); | |
| 5522 | const msg_len = msg_decl.typeOf(mod).childType(mod).arrayLen(mod); | |
| 5523 | const msg_ptr = try o.lowerValue(msg_decl.val.toIntern()); | |
| 5487 | const o = fg.ng.object; | |
| 5488 | const zcu = o.pt.zcu; | |
| 5489 | const ip = &zcu.intern_pool; | |
| 5490 | const msg_nav_index = zcu.panic_messages[@intFromEnum(panic_id)].unwrap().?; | |
| 5491 | const msg_nav = ip.getNav(msg_nav_index); | |
| 5492 | const msg_len = Type.fromInterned(msg_nav.typeOf(ip)).childType(zcu).arrayLen(zcu); | |
| 5493 | const msg_ptr = try o.lowerValue(msg_nav.status.resolved.val); | |
| 5524 | 5494 | const null_opt_addr_global = try fg.resolveNullOptUsize(); |
| 5525 | const target = mod.getTarget(); | |
| 5495 | const target = zcu.getTarget(); | |
| 5526 | 5496 | const llvm_usize = try o.lowerType(Type.usize); |
| 5527 | 5497 | // example: |
| 5528 | 5498 | // call fastcc void @test2.panic( |
| ... | ... | @@ -5531,10 +5501,10 @@ pub const FuncGen = struct { |
| 5531 | 5501 | // ptr null, ; stack trace |
| 5532 | 5502 | // ptr @2, ; addr (null ?usize) |
| 5533 | 5503 | // ) |
| 5534 | const panic_func = mod.funcInfo(mod.panic_func_index); | |
| 5535 | const panic_decl = mod.declPtr(panic_func.owner_decl); | |
| 5536 | const fn_info = mod.typeToFunc(panic_decl.typeOf(mod)).?; | |
| 5537 | const panic_global = try o.resolveLlvmFunction(panic_func.owner_decl); | |
| 5504 | const panic_func = zcu.funcInfo(zcu.panic_func_index); | |
| 5505 | const panic_nav = ip.getNav(panic_func.owner_nav); | |
| 5506 | const fn_info = zcu.typeToFunc(Type.fromInterned(panic_nav.typeOf(ip))).?; | |
| 5507 | const panic_global = try o.resolveLlvmFunction(panic_func.owner_nav); | |
| 5538 | 5508 | _ = try fg.wip.call( |
| 5539 | 5509 | .normal, |
| 5540 | 5510 | toLlvmCallConv(fn_info.cc, target), |
| ... | ... | @@ -5553,9 +5523,10 @@ pub const FuncGen = struct { |
| 5553 | 5523 | } |
| 5554 | 5524 | |
| 5555 | 5525 | fn airRet(self: *FuncGen, inst: Air.Inst.Index, safety: bool) !Builder.Value { |
| 5556 | const o = self.dg.object; | |
| 5526 | const o = self.ng.object; | |
| 5557 | 5527 | const pt = o.pt; |
| 5558 | 5528 | const mod = pt.zcu; |
| 5529 | const ip = &mod.intern_pool; | |
| 5559 | 5530 | const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op; |
| 5560 | 5531 | const ret_ty = self.typeOf(un_op); |
| 5561 | 5532 | |
| ... | ... | @@ -5581,7 +5552,7 @@ pub const FuncGen = struct { |
| 5581 | 5552 | len, |
| 5582 | 5553 | if (ptr_ty.isVolatilePtr(mod)) .@"volatile" else .normal, |
| 5583 | 5554 | ); |
| 5584 | const owner_mod = self.dg.ownerModule(); | |
| 5555 | const owner_mod = self.ng.ownerModule(); | |
| 5585 | 5556 | if (owner_mod.valgrind) { |
| 5586 | 5557 | try self.valgrindMarkUndef(self.ret_ptr, len); |
| 5587 | 5558 | } |
| ... | ... | @@ -5602,7 +5573,7 @@ pub const FuncGen = struct { |
| 5602 | 5573 | _ = try self.wip.retVoid(); |
| 5603 | 5574 | return .none; |
| 5604 | 5575 | } |
| 5605 | const fn_info = mod.typeToFunc(self.dg.decl.typeOf(mod)).?; | |
| 5576 | const fn_info = mod.typeToFunc(Type.fromInterned(ip.getNav(self.ng.nav_index).typeOf(ip))).?; | |
| 5606 | 5577 | if (!ret_ty.hasRuntimeBitsIgnoreComptime(pt)) { |
| 5607 | 5578 | if (Type.fromInterned(fn_info.return_type).isError(mod)) { |
| 5608 | 5579 | // Functions with an empty error set are emitted with an error code |
| ... | ... | @@ -5631,7 +5602,7 @@ pub const FuncGen = struct { |
| 5631 | 5602 | len, |
| 5632 | 5603 | .normal, |
| 5633 | 5604 | ); |
| 5634 | const owner_mod = self.dg.ownerModule(); | |
| 5605 | const owner_mod = self.ng.ownerModule(); | |
| 5635 | 5606 | if (owner_mod.valgrind) { |
| 5636 | 5607 | try self.valgrindMarkUndef(rp, len); |
| 5637 | 5608 | } |
| ... | ... | @@ -5659,13 +5630,14 @@ pub const FuncGen = struct { |
| 5659 | 5630 | } |
| 5660 | 5631 | |
| 5661 | 5632 | fn airRetLoad(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { |
| 5662 | const o = self.dg.object; | |
| 5633 | const o = self.ng.object; | |
| 5663 | 5634 | const pt = o.pt; |
| 5664 | 5635 | const mod = pt.zcu; |
| 5636 | const ip = &mod.intern_pool; | |
| 5665 | 5637 | const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op; |
| 5666 | 5638 | const ptr_ty = self.typeOf(un_op); |
| 5667 | 5639 | const ret_ty = ptr_ty.childType(mod); |
| 5668 | const fn_info = mod.typeToFunc(self.dg.decl.typeOf(mod)).?; | |
| 5640 | const fn_info = mod.typeToFunc(Type.fromInterned(ip.getNav(self.ng.nav_index).typeOf(ip))).?; | |
| 5669 | 5641 | if (!ret_ty.hasRuntimeBitsIgnoreComptime(pt)) { |
| 5670 | 5642 | if (Type.fromInterned(fn_info.return_type).isError(mod)) { |
| 5671 | 5643 | // Functions with an empty error set are emitted with an error code |
| ... | ... | @@ -5689,7 +5661,7 @@ pub const FuncGen = struct { |
| 5689 | 5661 | } |
| 5690 | 5662 | |
| 5691 | 5663 | fn airCVaArg(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { |
| 5692 | const o = self.dg.object; | |
| 5664 | const o = self.ng.object; | |
| 5693 | 5665 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 5694 | 5666 | const list = try self.resolveInst(ty_op.operand); |
| 5695 | 5667 | const arg_ty = ty_op.ty.toType(); |
| ... | ... | @@ -5699,7 +5671,7 @@ pub const FuncGen = struct { |
| 5699 | 5671 | } |
| 5700 | 5672 | |
| 5701 | 5673 | fn airCVaCopy(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { |
| 5702 | const o = self.dg.object; | |
| 5674 | const o = self.ng.object; | |
| 5703 | 5675 | const pt = o.pt; |
| 5704 | 5676 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 5705 | 5677 | const src_list = try self.resolveInst(ty_op.operand); |
| ... | ... | @@ -5725,7 +5697,7 @@ pub const FuncGen = struct { |
| 5725 | 5697 | } |
| 5726 | 5698 | |
| 5727 | 5699 | fn airCVaStart(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { |
| 5728 | const o = self.dg.object; | |
| 5700 | const o = self.ng.object; | |
| 5729 | 5701 | const pt = o.pt; |
| 5730 | 5702 | const va_list_ty = self.typeOfIndex(inst); |
| 5731 | 5703 | const llvm_va_list_ty = try o.lowerType(va_list_ty); |
| ... | ... | @@ -5767,7 +5739,7 @@ pub const FuncGen = struct { |
| 5767 | 5739 | } |
| 5768 | 5740 | |
| 5769 | 5741 | fn airCmpLtErrorsLen(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { |
| 5770 | const o = self.dg.object; | |
| 5742 | const o = self.ng.object; | |
| 5771 | 5743 | const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op; |
| 5772 | 5744 | const operand = try self.resolveInst(un_op); |
| 5773 | 5745 | const llvm_fn = try o.getCmpLtErrorsLenFunction(); |
| ... | ... | @@ -5790,7 +5762,7 @@ pub const FuncGen = struct { |
| 5790 | 5762 | lhs: Builder.Value, |
| 5791 | 5763 | rhs: Builder.Value, |
| 5792 | 5764 | ) Allocator.Error!Builder.Value { |
| 5793 | const o = self.dg.object; | |
| 5765 | const o = self.ng.object; | |
| 5794 | 5766 | const pt = o.pt; |
| 5795 | 5767 | const mod = pt.zcu; |
| 5796 | 5768 | const scalar_ty = operand_ty.scalarType(mod); |
| ... | ... | @@ -5897,7 +5869,7 @@ pub const FuncGen = struct { |
| 5897 | 5869 | maybe_inline_func: ?InternPool.Index, |
| 5898 | 5870 | body: []const Air.Inst.Index, |
| 5899 | 5871 | ) !Builder.Value { |
| 5900 | const o = self.dg.object; | |
| 5872 | const o = self.ng.object; | |
| 5901 | 5873 | const pt = o.pt; |
| 5902 | 5874 | const mod = pt.zcu; |
| 5903 | 5875 | const inst_ty = self.typeOfIndex(inst); |
| ... | ... | @@ -5948,7 +5920,7 @@ pub const FuncGen = struct { |
| 5948 | 5920 | } |
| 5949 | 5921 | |
| 5950 | 5922 | fn airBr(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { |
| 5951 | const o = self.dg.object; | |
| 5923 | const o = self.ng.object; | |
| 5952 | 5924 | const pt = o.pt; |
| 5953 | 5925 | const branch = self.air.instructions.items(.data)[@intFromEnum(inst)].br; |
| 5954 | 5926 | const block = self.blocks.get(branch.block_inst).?; |
| ... | ... | @@ -5988,7 +5960,7 @@ pub const FuncGen = struct { |
| 5988 | 5960 | } |
| 5989 | 5961 | |
| 5990 | 5962 | fn airTry(self: *FuncGen, body_tail: []const Air.Inst.Index) !Builder.Value { |
| 5991 | const o = self.dg.object; | |
| 5963 | const o = self.ng.object; | |
| 5992 | 5964 | const pt = o.pt; |
| 5993 | 5965 | const inst = body_tail[0]; |
| 5994 | 5966 | const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; |
| ... | ... | @@ -6003,7 +5975,7 @@ pub const FuncGen = struct { |
| 6003 | 5975 | } |
| 6004 | 5976 | |
| 6005 | 5977 | fn airTryPtr(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { |
| 6006 | const o = self.dg.object; | |
| 5978 | const o = self.ng.object; | |
| 6007 | 5979 | const mod = o.pt.zcu; |
| 6008 | 5980 | const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; |
| 6009 | 5981 | const extra = self.air.extraData(Air.TryPtr, ty_pl.payload); |
| ... | ... | @@ -6023,7 +5995,7 @@ pub const FuncGen = struct { |
| 6023 | 5995 | can_elide_load: bool, |
| 6024 | 5996 | is_unused: bool, |
| 6025 | 5997 | ) !Builder.Value { |
| 6026 | const o = fg.dg.object; | |
| 5998 | const o = fg.ng.object; | |
| 6027 | 5999 | const pt = o.pt; |
| 6028 | 6000 | const mod = pt.zcu; |
| 6029 | 6001 | const payload_ty = err_union_ty.errorUnionPayload(mod); |
| ... | ... | @@ -6088,7 +6060,7 @@ pub const FuncGen = struct { |
| 6088 | 6060 | } |
| 6089 | 6061 | |
| 6090 | 6062 | fn airSwitchBr(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { |
| 6091 | const o = self.dg.object; | |
| 6063 | const o = self.ng.object; | |
| 6092 | 6064 | const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; |
| 6093 | 6065 | const cond = try self.resolveInst(pl_op.operand); |
| 6094 | 6066 | const switch_br = self.air.extraData(Air.SwitchBr, pl_op.payload); |
| ... | ... | @@ -6152,7 +6124,7 @@ pub const FuncGen = struct { |
| 6152 | 6124 | } |
| 6153 | 6125 | |
| 6154 | 6126 | fn airLoop(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { |
| 6155 | const o = self.dg.object; | |
| 6127 | const o = self.ng.object; | |
| 6156 | 6128 | const mod = o.pt.zcu; |
| 6157 | 6129 | const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; |
| 6158 | 6130 | const loop = self.air.extraData(Air.Block, ty_pl.payload); |
| ... | ... | @@ -6176,7 +6148,7 @@ pub const FuncGen = struct { |
| 6176 | 6148 | } |
| 6177 | 6149 | |
| 6178 | 6150 | fn airArrayToSlice(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { |
| 6179 | const o = self.dg.object; | |
| 6151 | const o = self.ng.object; | |
| 6180 | 6152 | const pt = o.pt; |
| 6181 | 6153 | const mod = pt.zcu; |
| 6182 | 6154 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| ... | ... | @@ -6195,7 +6167,7 @@ pub const FuncGen = struct { |
| 6195 | 6167 | } |
| 6196 | 6168 | |
| 6197 | 6169 | fn airFloatFromInt(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { |
| 6198 | const o = self.dg.object; | |
| 6170 | const o = self.ng.object; | |
| 6199 | 6171 | const pt = o.pt; |
| 6200 | 6172 | const mod = pt.zcu; |
| 6201 | 6173 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| ... | ... | @@ -6280,7 +6252,7 @@ pub const FuncGen = struct { |
| 6280 | 6252 | ) !Builder.Value { |
| 6281 | 6253 | _ = fast; |
| 6282 | 6254 | |
| 6283 | const o = self.dg.object; | |
| 6255 | const o = self.ng.object; | |
| 6284 | 6256 | const pt = o.pt; |
| 6285 | 6257 | const mod = pt.zcu; |
| 6286 | 6258 | const target = mod.getTarget(); |
| ... | ... | @@ -6342,13 +6314,13 @@ pub const FuncGen = struct { |
| 6342 | 6314 | } |
| 6343 | 6315 | |
| 6344 | 6316 | fn sliceOrArrayPtr(fg: *FuncGen, ptr: Builder.Value, ty: Type) Allocator.Error!Builder.Value { |
| 6345 | const o = fg.dg.object; | |
| 6317 | const o = fg.ng.object; | |
| 6346 | 6318 | const mod = o.pt.zcu; |
| 6347 | 6319 | return if (ty.isSlice(mod)) fg.wip.extractValue(ptr, &.{0}, "") else ptr; |
| 6348 | 6320 | } |
| 6349 | 6321 | |
| 6350 | 6322 | fn sliceOrArrayLenInBytes(fg: *FuncGen, ptr: Builder.Value, ty: Type) Allocator.Error!Builder.Value { |
| 6351 | const o = fg.dg.object; | |
| 6323 | const o = fg.ng.object; | |
| 6352 | 6324 | const pt = o.pt; |
| 6353 | 6325 | const mod = pt.zcu; |
| 6354 | 6326 | const llvm_usize = try o.lowerType(Type.usize); |
| ... | ... | @@ -6378,7 +6350,7 @@ pub const FuncGen = struct { |
| 6378 | 6350 | } |
| 6379 | 6351 | |
| 6380 | 6352 | fn airPtrSliceFieldPtr(self: *FuncGen, inst: Air.Inst.Index, index: c_uint) !Builder.Value { |
| 6381 | const o = self.dg.object; | |
| 6353 | const o = self.ng.object; | |
| 6382 | 6354 | const mod = o.pt.zcu; |
| 6383 | 6355 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 6384 | 6356 | const slice_ptr = try self.resolveInst(ty_op.operand); |
| ... | ... | @@ -6389,7 +6361,7 @@ pub const FuncGen = struct { |
| 6389 | 6361 | } |
| 6390 | 6362 | |
| 6391 | 6363 | fn airSliceElemVal(self: *FuncGen, body_tail: []const Air.Inst.Index) !Builder.Value { |
| 6392 | const o = self.dg.object; | |
| 6364 | const o = self.ng.object; | |
| 6393 | 6365 | const pt = o.pt; |
| 6394 | 6366 | const mod = pt.zcu; |
| 6395 | 6367 | const inst = body_tail[0]; |
| ... | ... | @@ -6413,7 +6385,7 @@ pub const FuncGen = struct { |
| 6413 | 6385 | } |
| 6414 | 6386 | |
| 6415 | 6387 | fn airSliceElemPtr(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { |
| 6416 | const o = self.dg.object; | |
| 6388 | const o = self.ng.object; | |
| 6417 | 6389 | const mod = o.pt.zcu; |
| 6418 | 6390 | const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; |
| 6419 | 6391 | const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data; |
| ... | ... | @@ -6427,7 +6399,7 @@ pub const FuncGen = struct { |
| 6427 | 6399 | } |
| 6428 | 6400 | |
| 6429 | 6401 | fn airArrayElemVal(self: *FuncGen, body_tail: []const Air.Inst.Index) !Builder.Value { |
| 6430 | const o = self.dg.object; | |
| 6402 | const o = self.ng.object; | |
| 6431 | 6403 | const pt = o.pt; |
| 6432 | 6404 | const mod = pt.zcu; |
| 6433 | 6405 | const inst = body_tail[0]; |
| ... | ... | @@ -6460,7 +6432,7 @@ pub const FuncGen = struct { |
| 6460 | 6432 | } |
| 6461 | 6433 | |
| 6462 | 6434 | fn airPtrElemVal(self: *FuncGen, body_tail: []const Air.Inst.Index) !Builder.Value { |
| 6463 | const o = self.dg.object; | |
| 6435 | const o = self.ng.object; | |
| 6464 | 6436 | const pt = o.pt; |
| 6465 | 6437 | const mod = pt.zcu; |
| 6466 | 6438 | const inst = body_tail[0]; |
| ... | ... | @@ -6486,7 +6458,7 @@ pub const FuncGen = struct { |
| 6486 | 6458 | } |
| 6487 | 6459 | |
| 6488 | 6460 | fn airPtrElemPtr(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { |
| 6489 | const o = self.dg.object; | |
| 6461 | const o = self.ng.object; | |
| 6490 | 6462 | const pt = o.pt; |
| 6491 | 6463 | const mod = pt.zcu; |
| 6492 | 6464 | const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; |
| ... | ... | @@ -6529,7 +6501,7 @@ pub const FuncGen = struct { |
| 6529 | 6501 | } |
| 6530 | 6502 | |
| 6531 | 6503 | fn airStructFieldVal(self: *FuncGen, body_tail: []const Air.Inst.Index) !Builder.Value { |
| 6532 | const o = self.dg.object; | |
| 6504 | const o = self.ng.object; | |
| 6533 | 6505 | const pt = o.pt; |
| 6534 | 6506 | const mod = pt.zcu; |
| 6535 | 6507 | const inst = body_tail[0]; |
| ... | ... | @@ -6635,7 +6607,7 @@ pub const FuncGen = struct { |
| 6635 | 6607 | } |
| 6636 | 6608 | |
| 6637 | 6609 | fn airFieldParentPtr(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { |
| 6638 | const o = self.dg.object; | |
| 6610 | const o = self.ng.object; | |
| 6639 | 6611 | const pt = o.pt; |
| 6640 | 6612 | const mod = pt.zcu; |
| 6641 | 6613 | const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; |
| ... | ... | @@ -6697,7 +6669,7 @@ pub const FuncGen = struct { |
| 6697 | 6669 | } |
| 6698 | 6670 | |
| 6699 | 6671 | fn airDbgVarPtr(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { |
| 6700 | const o = self.dg.object; | |
| 6672 | const o = self.ng.object; | |
| 6701 | 6673 | const mod = o.pt.zcu; |
| 6702 | 6674 | const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; |
| 6703 | 6675 | const operand = try self.resolveInst(pl_op.operand); |
| ... | ... | @@ -6729,7 +6701,7 @@ pub const FuncGen = struct { |
| 6729 | 6701 | } |
| 6730 | 6702 | |
| 6731 | 6703 | fn airDbgVarVal(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { |
| 6732 | const o = self.dg.object; | |
| 6704 | const o = self.ng.object; | |
| 6733 | 6705 | const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; |
| 6734 | 6706 | const operand = try self.resolveInst(pl_op.operand); |
| 6735 | 6707 | const operand_ty = self.typeOf(pl_op.operand); |
| ... | ... | @@ -6746,7 +6718,7 @@ pub const FuncGen = struct { |
| 6746 | 6718 | ); |
| 6747 | 6719 | |
| 6748 | 6720 | const pt = o.pt; |
| 6749 | const owner_mod = self.dg.ownerModule(); | |
| 6721 | const owner_mod = self.ng.ownerModule(); | |
| 6750 | 6722 | if (isByRef(operand_ty, pt)) { |
| 6751 | 6723 | _ = try self.wip.callIntrinsic( |
| 6752 | 6724 | .normal, |
| ... | ... | @@ -6800,7 +6772,7 @@ pub const FuncGen = struct { |
| 6800 | 6772 | // We don't have such an assembler implemented yet though. For now, |
| 6801 | 6773 | // this implementation feeds the inline assembly code directly to LLVM. |
| 6802 | 6774 | |
| 6803 | const o = self.dg.object; | |
| 6775 | const o = self.ng.object; | |
| 6804 | 6776 | const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; |
| 6805 | 6777 | const extra = self.air.extraData(Air.Asm, ty_pl.payload); |
| 6806 | 6778 | const is_volatile = @as(u1, @truncate(extra.data.flags >> 31)) != 0; |
| ... | ... | @@ -7181,7 +7153,7 @@ pub const FuncGen = struct { |
| 7181 | 7153 | operand_is_ptr: bool, |
| 7182 | 7154 | cond: Builder.IntegerCondition, |
| 7183 | 7155 | ) !Builder.Value { |
| 7184 | const o = self.dg.object; | |
| 7156 | const o = self.ng.object; | |
| 7185 | 7157 | const pt = o.pt; |
| 7186 | 7158 | const mod = pt.zcu; |
| 7187 | 7159 | const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op; |
| ... | ... | @@ -7226,7 +7198,7 @@ pub const FuncGen = struct { |
| 7226 | 7198 | cond: Builder.IntegerCondition, |
| 7227 | 7199 | operand_is_ptr: bool, |
| 7228 | 7200 | ) !Builder.Value { |
| 7229 | const o = self.dg.object; | |
| 7201 | const o = self.ng.object; | |
| 7230 | 7202 | const pt = o.pt; |
| 7231 | 7203 | const mod = pt.zcu; |
| 7232 | 7204 | const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op; |
| ... | ... | @@ -7266,7 +7238,7 @@ pub const FuncGen = struct { |
| 7266 | 7238 | } |
| 7267 | 7239 | |
| 7268 | 7240 | fn airOptionalPayloadPtr(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { |
| 7269 | const o = self.dg.object; | |
| 7241 | const o = self.ng.object; | |
| 7270 | 7242 | const pt = o.pt; |
| 7271 | 7243 | const mod = pt.zcu; |
| 7272 | 7244 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| ... | ... | @@ -7288,7 +7260,7 @@ pub const FuncGen = struct { |
| 7288 | 7260 | fn airOptionalPayloadPtrSet(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { |
| 7289 | 7261 | comptime assert(optional_layout_version == 3); |
| 7290 | 7262 | |
| 7291 | const o = self.dg.object; | |
| 7263 | const o = self.ng.object; | |
| 7292 | 7264 | const pt = o.pt; |
| 7293 | 7265 | const mod = pt.zcu; |
| 7294 | 7266 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| ... | ... | @@ -7320,7 +7292,7 @@ pub const FuncGen = struct { |
| 7320 | 7292 | } |
| 7321 | 7293 | |
| 7322 | 7294 | fn airOptionalPayload(self: *FuncGen, body_tail: []const Air.Inst.Index) !Builder.Value { |
| 7323 | const o = self.dg.object; | |
| 7295 | const o = self.ng.object; | |
| 7324 | 7296 | const pt = o.pt; |
| 7325 | 7297 | const mod = pt.zcu; |
| 7326 | 7298 | const inst = body_tail[0]; |
| ... | ... | @@ -7345,7 +7317,7 @@ pub const FuncGen = struct { |
| 7345 | 7317 | body_tail: []const Air.Inst.Index, |
| 7346 | 7318 | operand_is_ptr: bool, |
| 7347 | 7319 | ) !Builder.Value { |
| 7348 | const o = self.dg.object; | |
| 7320 | const o = self.ng.object; | |
| 7349 | 7321 | const pt = o.pt; |
| 7350 | 7322 | const mod = pt.zcu; |
| 7351 | 7323 | const inst = body_tail[0]; |
| ... | ... | @@ -7381,7 +7353,7 @@ pub const FuncGen = struct { |
| 7381 | 7353 | inst: Air.Inst.Index, |
| 7382 | 7354 | operand_is_ptr: bool, |
| 7383 | 7355 | ) !Builder.Value { |
| 7384 | const o = self.dg.object; | |
| 7356 | const o = self.ng.object; | |
| 7385 | 7357 | const pt = o.pt; |
| 7386 | 7358 | const mod = pt.zcu; |
| 7387 | 7359 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| ... | ... | @@ -7415,7 +7387,7 @@ pub const FuncGen = struct { |
| 7415 | 7387 | } |
| 7416 | 7388 | |
| 7417 | 7389 | fn airErrUnionPayloadPtrSet(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { |
| 7418 | const o = self.dg.object; | |
| 7390 | const o = self.ng.object; | |
| 7419 | 7391 | const pt = o.pt; |
| 7420 | 7392 | const mod = pt.zcu; |
| 7421 | 7393 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| ... | ... | @@ -7456,7 +7428,7 @@ pub const FuncGen = struct { |
| 7456 | 7428 | } |
| 7457 | 7429 | |
| 7458 | 7430 | fn airSaveErrReturnTraceIndex(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { |
| 7459 | const o = self.dg.object; | |
| 7431 | const o = self.ng.object; | |
| 7460 | 7432 | const pt = o.pt; |
| 7461 | 7433 | const mod = pt.zcu; |
| 7462 | 7434 | |
| ... | ... | @@ -7502,7 +7474,7 @@ pub const FuncGen = struct { |
| 7502 | 7474 | } |
| 7503 | 7475 | |
| 7504 | 7476 | fn airWrapOptional(self: *FuncGen, body_tail: []const Air.Inst.Index) !Builder.Value { |
| 7505 | const o = self.dg.object; | |
| 7477 | const o = self.ng.object; | |
| 7506 | 7478 | const pt = o.pt; |
| 7507 | 7479 | const mod = pt.zcu; |
| 7508 | 7480 | const inst = body_tail[0]; |
| ... | ... | @@ -7536,7 +7508,7 @@ pub const FuncGen = struct { |
| 7536 | 7508 | } |
| 7537 | 7509 | |
| 7538 | 7510 | fn airWrapErrUnionPayload(self: *FuncGen, body_tail: []const Air.Inst.Index) !Builder.Value { |
| 7539 | const o = self.dg.object; | |
| 7511 | const o = self.ng.object; | |
| 7540 | 7512 | const pt = o.pt; |
| 7541 | 7513 | const inst = body_tail[0]; |
| 7542 | 7514 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| ... | ... | @@ -7577,7 +7549,7 @@ pub const FuncGen = struct { |
| 7577 | 7549 | } |
| 7578 | 7550 | |
| 7579 | 7551 | fn airWrapErrUnionErr(self: *FuncGen, body_tail: []const Air.Inst.Index) !Builder.Value { |
| 7580 | const o = self.dg.object; | |
| 7552 | const o = self.ng.object; | |
| 7581 | 7553 | const pt = o.pt; |
| 7582 | 7554 | const mod = pt.zcu; |
| 7583 | 7555 | const inst = body_tail[0]; |
| ... | ... | @@ -7618,7 +7590,7 @@ pub const FuncGen = struct { |
| 7618 | 7590 | } |
| 7619 | 7591 | |
| 7620 | 7592 | fn airWasmMemorySize(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { |
| 7621 | const o = self.dg.object; | |
| 7593 | const o = self.ng.object; | |
| 7622 | 7594 | const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; |
| 7623 | 7595 | const index = pl_op.payload; |
| 7624 | 7596 | const llvm_usize = try o.lowerType(Type.usize); |
| ... | ... | @@ -7628,7 +7600,7 @@ pub const FuncGen = struct { |
| 7628 | 7600 | } |
| 7629 | 7601 | |
| 7630 | 7602 | fn airWasmMemoryGrow(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { |
| 7631 | const o = self.dg.object; | |
| 7603 | const o = self.ng.object; | |
| 7632 | 7604 | const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; |
| 7633 | 7605 | const index = pl_op.payload; |
| 7634 | 7606 | const llvm_isize = try o.lowerType(Type.isize); |
| ... | ... | @@ -7638,7 +7610,7 @@ pub const FuncGen = struct { |
| 7638 | 7610 | } |
| 7639 | 7611 | |
| 7640 | 7612 | fn airVectorStoreElem(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { |
| 7641 | const o = self.dg.object; | |
| 7613 | const o = self.ng.object; | |
| 7642 | 7614 | const pt = o.pt; |
| 7643 | 7615 | const mod = pt.zcu; |
| 7644 | 7616 | const data = self.air.instructions.items(.data)[@intFromEnum(inst)].vector_store_elem; |
| ... | ... | @@ -7661,7 +7633,7 @@ pub const FuncGen = struct { |
| 7661 | 7633 | } |
| 7662 | 7634 | |
| 7663 | 7635 | fn airMin(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { |
| 7664 | const o = self.dg.object; | |
| 7636 | const o = self.ng.object; | |
| 7665 | 7637 | const mod = o.pt.zcu; |
| 7666 | 7638 | const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| 7667 | 7639 | const lhs = try self.resolveInst(bin_op.lhs); |
| ... | ... | @@ -7681,7 +7653,7 @@ pub const FuncGen = struct { |
| 7681 | 7653 | } |
| 7682 | 7654 | |
| 7683 | 7655 | fn airMax(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { |
| 7684 | const o = self.dg.object; | |
| 7656 | const o = self.ng.object; | |
| 7685 | 7657 | const mod = o.pt.zcu; |
| 7686 | 7658 | const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| 7687 | 7659 | const lhs = try self.resolveInst(bin_op.lhs); |
| ... | ... | @@ -7701,7 +7673,7 @@ pub const FuncGen = struct { |
| 7701 | 7673 | } |
| 7702 | 7674 | |
| 7703 | 7675 | fn airSlice(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { |
| 7704 | const o = self.dg.object; | |
| 7676 | const o = self.ng.object; | |
| 7705 | 7677 | const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; |
| 7706 | 7678 | const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data; |
| 7707 | 7679 | const ptr = try self.resolveInst(bin_op.lhs); |
| ... | ... | @@ -7711,7 +7683,7 @@ pub const FuncGen = struct { |
| 7711 | 7683 | } |
| 7712 | 7684 | |
| 7713 | 7685 | fn airAdd(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) !Builder.Value { |
| 7714 | const o = self.dg.object; | |
| 7686 | const o = self.ng.object; | |
| 7715 | 7687 | const mod = o.pt.zcu; |
| 7716 | 7688 | const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| 7717 | 7689 | const lhs = try self.resolveInst(bin_op.lhs); |
| ... | ... | @@ -7729,7 +7701,7 @@ pub const FuncGen = struct { |
| 7729 | 7701 | signed_intrinsic: Builder.Intrinsic, |
| 7730 | 7702 | unsigned_intrinsic: Builder.Intrinsic, |
| 7731 | 7703 | ) !Builder.Value { |
| 7732 | const o = fg.dg.object; | |
| 7704 | const o = fg.ng.object; | |
| 7733 | 7705 | const mod = o.pt.zcu; |
| 7734 | 7706 | |
| 7735 | 7707 | const bin_op = fg.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| ... | ... | @@ -7777,7 +7749,7 @@ pub const FuncGen = struct { |
| 7777 | 7749 | } |
| 7778 | 7750 | |
| 7779 | 7751 | fn airAddSat(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { |
| 7780 | const o = self.dg.object; | |
| 7752 | const o = self.ng.object; | |
| 7781 | 7753 | const mod = o.pt.zcu; |
| 7782 | 7754 | const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| 7783 | 7755 | const lhs = try self.resolveInst(bin_op.lhs); |
| ... | ... | @@ -7797,7 +7769,7 @@ pub const FuncGen = struct { |
| 7797 | 7769 | } |
| 7798 | 7770 | |
| 7799 | 7771 | fn airSub(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) !Builder.Value { |
| 7800 | const o = self.dg.object; | |
| 7772 | const o = self.ng.object; | |
| 7801 | 7773 | const mod = o.pt.zcu; |
| 7802 | 7774 | const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| 7803 | 7775 | const lhs = try self.resolveInst(bin_op.lhs); |
| ... | ... | @@ -7818,7 +7790,7 @@ pub const FuncGen = struct { |
| 7818 | 7790 | } |
| 7819 | 7791 | |
| 7820 | 7792 | fn airSubSat(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { |
| 7821 | const o = self.dg.object; | |
| 7793 | const o = self.ng.object; | |
| 7822 | 7794 | const mod = o.pt.zcu; |
| 7823 | 7795 | const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| 7824 | 7796 | const lhs = try self.resolveInst(bin_op.lhs); |
| ... | ... | @@ -7838,7 +7810,7 @@ pub const FuncGen = struct { |
| 7838 | 7810 | } |
| 7839 | 7811 | |
| 7840 | 7812 | fn airMul(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) !Builder.Value { |
| 7841 | const o = self.dg.object; | |
| 7813 | const o = self.ng.object; | |
| 7842 | 7814 | const mod = o.pt.zcu; |
| 7843 | 7815 | const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| 7844 | 7816 | const lhs = try self.resolveInst(bin_op.lhs); |
| ... | ... | @@ -7859,7 +7831,7 @@ pub const FuncGen = struct { |
| 7859 | 7831 | } |
| 7860 | 7832 | |
| 7861 | 7833 | fn airMulSat(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { |
| 7862 | const o = self.dg.object; | |
| 7834 | const o = self.ng.object; | |
| 7863 | 7835 | const mod = o.pt.zcu; |
| 7864 | 7836 | const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| 7865 | 7837 | const lhs = try self.resolveInst(bin_op.lhs); |
| ... | ... | @@ -7888,7 +7860,7 @@ pub const FuncGen = struct { |
| 7888 | 7860 | } |
| 7889 | 7861 | |
| 7890 | 7862 | fn airDivTrunc(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) !Builder.Value { |
| 7891 | const o = self.dg.object; | |
| 7863 | const o = self.ng.object; | |
| 7892 | 7864 | const mod = o.pt.zcu; |
| 7893 | 7865 | const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| 7894 | 7866 | const lhs = try self.resolveInst(bin_op.lhs); |
| ... | ... | @@ -7904,7 +7876,7 @@ pub const FuncGen = struct { |
| 7904 | 7876 | } |
| 7905 | 7877 | |
| 7906 | 7878 | fn airDivFloor(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) !Builder.Value { |
| 7907 | const o = self.dg.object; | |
| 7879 | const o = self.ng.object; | |
| 7908 | 7880 | const mod = o.pt.zcu; |
| 7909 | 7881 | const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| 7910 | 7882 | const lhs = try self.resolveInst(bin_op.lhs); |
| ... | ... | @@ -7936,7 +7908,7 @@ pub const FuncGen = struct { |
| 7936 | 7908 | } |
| 7937 | 7909 | |
| 7938 | 7910 | fn airDivExact(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) !Builder.Value { |
| 7939 | const o = self.dg.object; | |
| 7911 | const o = self.ng.object; | |
| 7940 | 7912 | const mod = o.pt.zcu; |
| 7941 | 7913 | const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| 7942 | 7914 | const lhs = try self.resolveInst(bin_op.lhs); |
| ... | ... | @@ -7954,7 +7926,7 @@ pub const FuncGen = struct { |
| 7954 | 7926 | } |
| 7955 | 7927 | |
| 7956 | 7928 | fn airRem(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) !Builder.Value { |
| 7957 | const o = self.dg.object; | |
| 7929 | const o = self.ng.object; | |
| 7958 | 7930 | const mod = o.pt.zcu; |
| 7959 | 7931 | const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| 7960 | 7932 | const lhs = try self.resolveInst(bin_op.lhs); |
| ... | ... | @@ -7971,7 +7943,7 @@ pub const FuncGen = struct { |
| 7971 | 7943 | } |
| 7972 | 7944 | |
| 7973 | 7945 | fn airMod(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) !Builder.Value { |
| 7974 | const o = self.dg.object; | |
| 7946 | const o = self.ng.object; | |
| 7975 | 7947 | const mod = o.pt.zcu; |
| 7976 | 7948 | const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| 7977 | 7949 | const lhs = try self.resolveInst(bin_op.lhs); |
| ... | ... | @@ -8007,7 +7979,7 @@ pub const FuncGen = struct { |
| 8007 | 7979 | } |
| 8008 | 7980 | |
| 8009 | 7981 | fn airPtrAdd(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { |
| 8010 | const o = self.dg.object; | |
| 7982 | const o = self.ng.object; | |
| 8011 | 7983 | const mod = o.pt.zcu; |
| 8012 | 7984 | const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; |
| 8013 | 7985 | const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data; |
| ... | ... | @@ -8029,7 +8001,7 @@ pub const FuncGen = struct { |
| 8029 | 8001 | } |
| 8030 | 8002 | |
| 8031 | 8003 | fn airPtrSub(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { |
| 8032 | const o = self.dg.object; | |
| 8004 | const o = self.ng.object; | |
| 8033 | 8005 | const mod = o.pt.zcu; |
| 8034 | 8006 | const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; |
| 8035 | 8007 | const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data; |
| ... | ... | @@ -8057,7 +8029,7 @@ pub const FuncGen = struct { |
| 8057 | 8029 | signed_intrinsic: Builder.Intrinsic, |
| 8058 | 8030 | unsigned_intrinsic: Builder.Intrinsic, |
| 8059 | 8031 | ) !Builder.Value { |
| 8060 | const o = self.dg.object; | |
| 8032 | const o = self.ng.object; | |
| 8061 | 8033 | const pt = o.pt; |
| 8062 | 8034 | const mod = pt.zcu; |
| 8063 | 8035 | const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; |
| ... | ... | @@ -8111,7 +8083,7 @@ pub const FuncGen = struct { |
| 8111 | 8083 | result_vector: Builder.Value, |
| 8112 | 8084 | vector_len: usize, |
| 8113 | 8085 | ) !Builder.Value { |
| 8114 | const o = self.dg.object; | |
| 8086 | const o = self.ng.object; | |
| 8115 | 8087 | assert(args_vectors.len <= 3); |
| 8116 | 8088 | |
| 8117 | 8089 | var i: usize = 0; |
| ... | ... | @@ -8143,7 +8115,7 @@ pub const FuncGen = struct { |
| 8143 | 8115 | param_types: []const Builder.Type, |
| 8144 | 8116 | return_type: Builder.Type, |
| 8145 | 8117 | ) Allocator.Error!Builder.Function.Index { |
| 8146 | const o = self.dg.object; | |
| 8118 | const o = self.ng.object; | |
| 8147 | 8119 | if (o.builder.getGlobal(fn_name)) |global| return switch (global.ptrConst(&o.builder).kind) { |
| 8148 | 8120 | .alias => |alias| alias.getAliasee(&o.builder).ptrConst(&o.builder).kind.function, |
| 8149 | 8121 | .function => |function| function, |
| ... | ... | @@ -8165,7 +8137,7 @@ pub const FuncGen = struct { |
| 8165 | 8137 | ty: Type, |
| 8166 | 8138 | params: [2]Builder.Value, |
| 8167 | 8139 | ) !Builder.Value { |
| 8168 | const o = self.dg.object; | |
| 8140 | const o = self.ng.object; | |
| 8169 | 8141 | const mod = o.pt.zcu; |
| 8170 | 8142 | const target = mod.getTarget(); |
| 8171 | 8143 | const scalar_ty = ty.scalarType(mod); |
| ... | ... | @@ -8271,7 +8243,7 @@ pub const FuncGen = struct { |
| 8271 | 8243 | comptime params_len: usize, |
| 8272 | 8244 | params: [params_len]Builder.Value, |
| 8273 | 8245 | ) !Builder.Value { |
| 8274 | const o = self.dg.object; | |
| 8246 | const o = self.ng.object; | |
| 8275 | 8247 | const mod = o.pt.zcu; |
| 8276 | 8248 | const target = mod.getTarget(); |
| 8277 | 8249 | const scalar_ty = ty.scalarType(mod); |
| ... | ... | @@ -8412,7 +8384,7 @@ pub const FuncGen = struct { |
| 8412 | 8384 | } |
| 8413 | 8385 | |
| 8414 | 8386 | fn airShlWithOverflow(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { |
| 8415 | const o = self.dg.object; | |
| 8387 | const o = self.ng.object; | |
| 8416 | 8388 | const pt = o.pt; |
| 8417 | 8389 | const mod = pt.zcu; |
| 8418 | 8390 | const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; |
| ... | ... | @@ -8483,7 +8455,7 @@ pub const FuncGen = struct { |
| 8483 | 8455 | } |
| 8484 | 8456 | |
| 8485 | 8457 | fn airShlExact(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { |
| 8486 | const o = self.dg.object; | |
| 8458 | const o = self.ng.object; | |
| 8487 | 8459 | const mod = o.pt.zcu; |
| 8488 | 8460 | const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| 8489 | 8461 | |
| ... | ... | @@ -8501,7 +8473,7 @@ pub const FuncGen = struct { |
| 8501 | 8473 | } |
| 8502 | 8474 | |
| 8503 | 8475 | fn airShl(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { |
| 8504 | const o = self.dg.object; | |
| 8476 | const o = self.ng.object; | |
| 8505 | 8477 | const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| 8506 | 8478 | |
| 8507 | 8479 | const lhs = try self.resolveInst(bin_op.lhs); |
| ... | ... | @@ -8514,7 +8486,7 @@ pub const FuncGen = struct { |
| 8514 | 8486 | } |
| 8515 | 8487 | |
| 8516 | 8488 | fn airShlSat(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { |
| 8517 | const o = self.dg.object; | |
| 8489 | const o = self.ng.object; | |
| 8518 | 8490 | const pt = o.pt; |
| 8519 | 8491 | const mod = pt.zcu; |
| 8520 | 8492 | const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| ... | ... | @@ -8557,7 +8529,7 @@ pub const FuncGen = struct { |
| 8557 | 8529 | } |
| 8558 | 8530 | |
| 8559 | 8531 | fn airShr(self: *FuncGen, inst: Air.Inst.Index, is_exact: bool) !Builder.Value { |
| 8560 | const o = self.dg.object; | |
| 8532 | const o = self.ng.object; | |
| 8561 | 8533 | const mod = o.pt.zcu; |
| 8562 | 8534 | const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| 8563 | 8535 | |
| ... | ... | @@ -8576,7 +8548,7 @@ pub const FuncGen = struct { |
| 8576 | 8548 | } |
| 8577 | 8549 | |
| 8578 | 8550 | fn airAbs(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { |
| 8579 | const o = self.dg.object; | |
| 8551 | const o = self.ng.object; | |
| 8580 | 8552 | const mod = o.pt.zcu; |
| 8581 | 8553 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 8582 | 8554 | const operand = try self.resolveInst(ty_op.operand); |
| ... | ... | @@ -8598,7 +8570,7 @@ pub const FuncGen = struct { |
| 8598 | 8570 | } |
| 8599 | 8571 | |
| 8600 | 8572 | fn airIntCast(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { |
| 8601 | const o = self.dg.object; | |
| 8573 | const o = self.ng.object; | |
| 8602 | 8574 | const mod = o.pt.zcu; |
| 8603 | 8575 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 8604 | 8576 | const dest_ty = self.typeOfIndex(inst); |
| ... | ... | @@ -8614,7 +8586,7 @@ pub const FuncGen = struct { |
| 8614 | 8586 | } |
| 8615 | 8587 | |
| 8616 | 8588 | fn airTrunc(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { |
| 8617 | const o = self.dg.object; | |
| 8589 | const o = self.ng.object; | |
| 8618 | 8590 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 8619 | 8591 | const operand = try self.resolveInst(ty_op.operand); |
| 8620 | 8592 | const dest_llvm_ty = try o.lowerType(self.typeOfIndex(inst)); |
| ... | ... | @@ -8622,7 +8594,7 @@ pub const FuncGen = struct { |
| 8622 | 8594 | } |
| 8623 | 8595 | |
| 8624 | 8596 | fn airFptrunc(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { |
| 8625 | const o = self.dg.object; | |
| 8597 | const o = self.ng.object; | |
| 8626 | 8598 | const mod = o.pt.zcu; |
| 8627 | 8599 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 8628 | 8600 | const operand = try self.resolveInst(ty_op.operand); |
| ... | ... | @@ -8656,7 +8628,7 @@ pub const FuncGen = struct { |
| 8656 | 8628 | } |
| 8657 | 8629 | |
| 8658 | 8630 | fn airFpext(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { |
| 8659 | const o = self.dg.object; | |
| 8631 | const o = self.ng.object; | |
| 8660 | 8632 | const mod = o.pt.zcu; |
| 8661 | 8633 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 8662 | 8634 | const operand = try self.resolveInst(ty_op.operand); |
| ... | ... | @@ -8696,7 +8668,7 @@ pub const FuncGen = struct { |
| 8696 | 8668 | } |
| 8697 | 8669 | |
| 8698 | 8670 | fn airIntFromPtr(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { |
| 8699 | const o = self.dg.object; | |
| 8671 | const o = self.ng.object; | |
| 8700 | 8672 | const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op; |
| 8701 | 8673 | const operand = try self.resolveInst(un_op); |
| 8702 | 8674 | const ptr_ty = self.typeOf(un_op); |
| ... | ... | @@ -8714,7 +8686,7 @@ pub const FuncGen = struct { |
| 8714 | 8686 | } |
| 8715 | 8687 | |
| 8716 | 8688 | fn bitCast(self: *FuncGen, operand: Builder.Value, operand_ty: Type, inst_ty: Type) !Builder.Value { |
| 8717 | const o = self.dg.object; | |
| 8689 | const o = self.ng.object; | |
| 8718 | 8690 | const pt = o.pt; |
| 8719 | 8691 | const mod = pt.zcu; |
| 8720 | 8692 | const operand_is_ref = isByRef(operand_ty, pt); |
| ... | ... | @@ -8739,7 +8711,7 @@ pub const FuncGen = struct { |
| 8739 | 8711 | if (operand_ty.zigTypeTag(mod) == .Vector and inst_ty.zigTypeTag(mod) == .Array) { |
| 8740 | 8712 | const elem_ty = operand_ty.childType(mod); |
| 8741 | 8713 | if (!result_is_ref) { |
| 8742 | return self.dg.todo("implement bitcast vector to non-ref array", .{}); | |
| 8714 | return self.ng.todo("implement bitcast vector to non-ref array", .{}); | |
| 8743 | 8715 | } |
| 8744 | 8716 | const alignment = inst_ty.abiAlignment(pt).toLlvm(); |
| 8745 | 8717 | const array_ptr = try self.buildAllocaWorkaround(inst_ty, alignment); |
| ... | ... | @@ -8766,7 +8738,7 @@ pub const FuncGen = struct { |
| 8766 | 8738 | } else if (operand_ty.zigTypeTag(mod) == .Array and inst_ty.zigTypeTag(mod) == .Vector) { |
| 8767 | 8739 | const elem_ty = operand_ty.childType(mod); |
| 8768 | 8740 | const llvm_vector_ty = try o.lowerType(inst_ty); |
| 8769 | if (!operand_is_ref) return self.dg.todo("implement bitcast non-ref array to vector", .{}); | |
| 8741 | if (!operand_is_ref) return self.ng.todo("implement bitcast non-ref array to vector", .{}); | |
| 8770 | 8742 | |
| 8771 | 8743 | const bitcast_ok = elem_ty.bitSize(pt) == elem_ty.abiSize(pt) * 8; |
| 8772 | 8744 | if (bitcast_ok) { |
| ... | ... | @@ -8831,9 +8803,9 @@ pub const FuncGen = struct { |
| 8831 | 8803 | } |
| 8832 | 8804 | |
| 8833 | 8805 | fn airArg(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { |
| 8834 | const o = self.dg.object; | |
| 8806 | const o = self.ng.object; | |
| 8835 | 8807 | const pt = o.pt; |
| 8836 | const mod = pt.zcu; | |
| 8808 | const zcu = pt.zcu; | |
| 8837 | 8809 | const arg_val = self.args[self.arg_index]; |
| 8838 | 8810 | self.arg_index += 1; |
| 8839 | 8811 | |
| ... | ... | @@ -8846,9 +8818,8 @@ pub const FuncGen = struct { |
| 8846 | 8818 | const name = self.air.instructions.items(.data)[@intFromEnum(inst)].arg.name; |
| 8847 | 8819 | if (name == .none) return arg_val; |
| 8848 | 8820 | |
| 8849 | const func_index = self.dg.decl.getOwnedFunctionIndex(); | |
| 8850 | const func = mod.funcInfo(func_index); | |
| 8851 | const lbrace_line = mod.declPtr(func.owner_decl).navSrcLine(mod) + func.lbrace_line + 1; | |
| 8821 | const func = zcu.funcInfo(zcu.navValue(self.ng.nav_index).toIntern()); | |
| 8822 | const lbrace_line = zcu.navSrcLine(func.owner_nav) + func.lbrace_line + 1; | |
| 8852 | 8823 | const lbrace_col = func.lbrace_column + 1; |
| 8853 | 8824 | |
| 8854 | 8825 | const debug_parameter = try o.builder.debugParameter( |
| ... | ... | @@ -8870,7 +8841,7 @@ pub const FuncGen = struct { |
| 8870 | 8841 | }, |
| 8871 | 8842 | }; |
| 8872 | 8843 | |
| 8873 | const owner_mod = self.dg.ownerModule(); | |
| 8844 | const mod = self.ng.ownerModule(); | |
| 8874 | 8845 | if (isByRef(inst_ty, pt)) { |
| 8875 | 8846 | _ = try self.wip.callIntrinsic( |
| 8876 | 8847 | .normal, |
| ... | ... | @@ -8884,7 +8855,7 @@ pub const FuncGen = struct { |
| 8884 | 8855 | }, |
| 8885 | 8856 | "", |
| 8886 | 8857 | ); |
| 8887 | } else if (owner_mod.optimize_mode == .Debug) { | |
| 8858 | } else if (mod.optimize_mode == .Debug) { | |
| 8888 | 8859 | const alignment = inst_ty.abiAlignment(pt).toLlvm(); |
| 8889 | 8860 | const alloca = try self.buildAlloca(arg_val.typeOfWip(&self.wip), alignment); |
| 8890 | 8861 | _ = try self.wip.store(.normal, arg_val, alloca, alignment); |
| ... | ... | @@ -8920,7 +8891,7 @@ pub const FuncGen = struct { |
| 8920 | 8891 | } |
| 8921 | 8892 | |
| 8922 | 8893 | fn airAlloc(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { |
| 8923 | const o = self.dg.object; | |
| 8894 | const o = self.ng.object; | |
| 8924 | 8895 | const pt = o.pt; |
| 8925 | 8896 | const mod = pt.zcu; |
| 8926 | 8897 | const ptr_ty = self.typeOfIndex(inst); |
| ... | ... | @@ -8934,7 +8905,7 @@ pub const FuncGen = struct { |
| 8934 | 8905 | } |
| 8935 | 8906 | |
| 8936 | 8907 | fn airRetPtr(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { |
| 8937 | const o = self.dg.object; | |
| 8908 | const o = self.ng.object; | |
| 8938 | 8909 | const pt = o.pt; |
| 8939 | 8910 | const mod = pt.zcu; |
| 8940 | 8911 | const ptr_ty = self.typeOfIndex(inst); |
| ... | ... | @@ -8954,7 +8925,7 @@ pub const FuncGen = struct { |
| 8954 | 8925 | llvm_ty: Builder.Type, |
| 8955 | 8926 | alignment: Builder.Alignment, |
| 8956 | 8927 | ) Allocator.Error!Builder.Value { |
| 8957 | const target = self.dg.object.pt.zcu.getTarget(); | |
| 8928 | const target = self.ng.object.pt.zcu.getTarget(); | |
| 8958 | 8929 | return buildAllocaInner(&self.wip, llvm_ty, alignment, target); |
| 8959 | 8930 | } |
| 8960 | 8931 | |
| ... | ... | @@ -8964,12 +8935,12 @@ pub const FuncGen = struct { |
| 8964 | 8935 | ty: Type, |
| 8965 | 8936 | alignment: Builder.Alignment, |
| 8966 | 8937 | ) Allocator.Error!Builder.Value { |
| 8967 | const o = self.dg.object; | |
| 8938 | const o = self.ng.object; | |
| 8968 | 8939 | return self.buildAlloca(try o.builder.arrayType(ty.abiSize(o.pt), .i8), alignment); |
| 8969 | 8940 | } |
| 8970 | 8941 | |
| 8971 | 8942 | fn airStore(self: *FuncGen, inst: Air.Inst.Index, safety: bool) !Builder.Value { |
| 8972 | const o = self.dg.object; | |
| 8943 | const o = self.ng.object; | |
| 8973 | 8944 | const pt = o.pt; |
| 8974 | 8945 | const mod = pt.zcu; |
| 8975 | 8946 | const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| ... | ... | @@ -8979,7 +8950,7 @@ pub const FuncGen = struct { |
| 8979 | 8950 | |
| 8980 | 8951 | const val_is_undef = if (try self.air.value(bin_op.rhs, pt)) |val| val.isUndefDeep(mod) else false; |
| 8981 | 8952 | if (val_is_undef) { |
| 8982 | const owner_mod = self.dg.ownerModule(); | |
| 8953 | const owner_mod = self.ng.ownerModule(); | |
| 8983 | 8954 | |
| 8984 | 8955 | // Even if safety is disabled, we still emit a memset to undefined since it conveys |
| 8985 | 8956 | // extra information to LLVM, and LLVM will optimize it out. Safety makes the difference |
| ... | ... | @@ -9029,7 +9000,7 @@ pub const FuncGen = struct { |
| 9029 | 9000 | /// |
| 9030 | 9001 | /// The first instruction of `body_tail` is the one whose copy we want to elide. |
| 9031 | 9002 | fn canElideLoad(fg: *FuncGen, body_tail: []const Air.Inst.Index) bool { |
| 9032 | const o = fg.dg.object; | |
| 9003 | const o = fg.ng.object; | |
| 9033 | 9004 | const mod = o.pt.zcu; |
| 9034 | 9005 | const ip = &mod.intern_pool; |
| 9035 | 9006 | for (body_tail[1..]) |body_inst| { |
| ... | ... | @@ -9045,7 +9016,7 @@ pub const FuncGen = struct { |
| 9045 | 9016 | } |
| 9046 | 9017 | |
| 9047 | 9018 | fn airLoad(fg: *FuncGen, body_tail: []const Air.Inst.Index) !Builder.Value { |
| 9048 | const o = fg.dg.object; | |
| 9019 | const o = fg.ng.object; | |
| 9049 | 9020 | const pt = o.pt; |
| 9050 | 9021 | const mod = pt.zcu; |
| 9051 | 9022 | const inst = body_tail[0]; |
| ... | ... | @@ -9077,7 +9048,7 @@ pub const FuncGen = struct { |
| 9077 | 9048 | |
| 9078 | 9049 | fn airRetAddr(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { |
| 9079 | 9050 | _ = inst; |
| 9080 | const o = self.dg.object; | |
| 9051 | const o = self.ng.object; | |
| 9081 | 9052 | const llvm_usize = try o.lowerType(Type.usize); |
| 9082 | 9053 | if (!target_util.supportsReturnAddress(o.pt.zcu.getTarget())) { |
| 9083 | 9054 | // https://github.com/ziglang/zig/issues/11946 |
| ... | ... | @@ -9089,7 +9060,7 @@ pub const FuncGen = struct { |
| 9089 | 9060 | |
| 9090 | 9061 | fn airFrameAddress(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { |
| 9091 | 9062 | _ = inst; |
| 9092 | const o = self.dg.object; | |
| 9063 | const o = self.ng.object; | |
| 9093 | 9064 | const result = try self.wip.callIntrinsic(.normal, .none, .frameaddress, &.{.ptr}, &.{.@"0"}, ""); |
| 9094 | 9065 | return self.wip.cast(.ptrtoint, result, try o.lowerType(Type.usize), ""); |
| 9095 | 9066 | } |
| ... | ... | @@ -9106,7 +9077,7 @@ pub const FuncGen = struct { |
| 9106 | 9077 | inst: Air.Inst.Index, |
| 9107 | 9078 | kind: Builder.Function.Instruction.CmpXchg.Kind, |
| 9108 | 9079 | ) !Builder.Value { |
| 9109 | const o = self.dg.object; | |
| 9080 | const o = self.ng.object; | |
| 9110 | 9081 | const pt = o.pt; |
| 9111 | 9082 | const mod = pt.zcu; |
| 9112 | 9083 | const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; |
| ... | ... | @@ -9157,7 +9128,7 @@ pub const FuncGen = struct { |
| 9157 | 9128 | } |
| 9158 | 9129 | |
| 9159 | 9130 | fn airAtomicRmw(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { |
| 9160 | const o = self.dg.object; | |
| 9131 | const o = self.ng.object; | |
| 9161 | 9132 | const pt = o.pt; |
| 9162 | 9133 | const mod = pt.zcu; |
| 9163 | 9134 | const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; |
| ... | ... | @@ -9221,7 +9192,7 @@ pub const FuncGen = struct { |
| 9221 | 9192 | } |
| 9222 | 9193 | |
| 9223 | 9194 | fn airAtomicLoad(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { |
| 9224 | const o = self.dg.object; | |
| 9195 | const o = self.ng.object; | |
| 9225 | 9196 | const pt = o.pt; |
| 9226 | 9197 | const mod = pt.zcu; |
| 9227 | 9198 | const atomic_load = self.air.instructions.items(.data)[@intFromEnum(inst)].atomic_load; |
| ... | ... | @@ -9269,7 +9240,7 @@ pub const FuncGen = struct { |
| 9269 | 9240 | inst: Air.Inst.Index, |
| 9270 | 9241 | ordering: Builder.AtomicOrdering, |
| 9271 | 9242 | ) !Builder.Value { |
| 9272 | const o = self.dg.object; | |
| 9243 | const o = self.ng.object; | |
| 9273 | 9244 | const pt = o.pt; |
| 9274 | 9245 | const mod = pt.zcu; |
| 9275 | 9246 | const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| ... | ... | @@ -9294,7 +9265,7 @@ pub const FuncGen = struct { |
| 9294 | 9265 | } |
| 9295 | 9266 | |
| 9296 | 9267 | fn airMemset(self: *FuncGen, inst: Air.Inst.Index, safety: bool) !Builder.Value { |
| 9297 | const o = self.dg.object; | |
| 9268 | const o = self.ng.object; | |
| 9298 | 9269 | const pt = o.pt; |
| 9299 | 9270 | const mod = pt.zcu; |
| 9300 | 9271 | const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| ... | ... | @@ -9329,7 +9300,7 @@ pub const FuncGen = struct { |
| 9329 | 9300 | } else { |
| 9330 | 9301 | _ = try self.wip.callMemSet(dest_ptr, dest_ptr_align, fill_byte, len, access_kind); |
| 9331 | 9302 | } |
| 9332 | const owner_mod = self.dg.ownerModule(); | |
| 9303 | const owner_mod = self.ng.ownerModule(); | |
| 9333 | 9304 | if (safety and owner_mod.valgrind) { |
| 9334 | 9305 | try self.valgrindMarkUndef(dest_ptr, len); |
| 9335 | 9306 | } |
| ... | ... | @@ -9435,7 +9406,7 @@ pub const FuncGen = struct { |
| 9435 | 9406 | dest_ptr_align: Builder.Alignment, |
| 9436 | 9407 | access_kind: Builder.MemoryAccessKind, |
| 9437 | 9408 | ) !void { |
| 9438 | const o = self.dg.object; | |
| 9409 | const o = self.ng.object; | |
| 9439 | 9410 | const usize_zero = try o.builder.intValue(try o.lowerType(Type.usize), 0); |
| 9440 | 9411 | const cond = try self.cmp(.normal, .neq, Type.usize, len, usize_zero); |
| 9441 | 9412 | const memset_block = try self.wip.block(1, "MemsetTrapSkip"); |
| ... | ... | @@ -9448,7 +9419,7 @@ pub const FuncGen = struct { |
| 9448 | 9419 | } |
| 9449 | 9420 | |
| 9450 | 9421 | fn airMemcpy(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { |
| 9451 | const o = self.dg.object; | |
| 9422 | const o = self.ng.object; | |
| 9452 | 9423 | const pt = o.pt; |
| 9453 | 9424 | const mod = pt.zcu; |
| 9454 | 9425 | const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| ... | ... | @@ -9502,7 +9473,7 @@ pub const FuncGen = struct { |
| 9502 | 9473 | } |
| 9503 | 9474 | |
| 9504 | 9475 | fn airSetUnionTag(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { |
| 9505 | const o = self.dg.object; | |
| 9476 | const o = self.ng.object; | |
| 9506 | 9477 | const pt = o.pt; |
| 9507 | 9478 | const mod = pt.zcu; |
| 9508 | 9479 | const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| ... | ... | @@ -9524,7 +9495,7 @@ pub const FuncGen = struct { |
| 9524 | 9495 | } |
| 9525 | 9496 | |
| 9526 | 9497 | fn airGetUnionTag(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { |
| 9527 | const o = self.dg.object; | |
| 9498 | const o = self.ng.object; | |
| 9528 | 9499 | const pt = o.pt; |
| 9529 | 9500 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 9530 | 9501 | const un_ty = self.typeOf(ty_op.operand); |
| ... | ... | @@ -9563,7 +9534,7 @@ pub const FuncGen = struct { |
| 9563 | 9534 | } |
| 9564 | 9535 | |
| 9565 | 9536 | fn airClzCtz(self: *FuncGen, inst: Air.Inst.Index, intrinsic: Builder.Intrinsic) !Builder.Value { |
| 9566 | const o = self.dg.object; | |
| 9537 | const o = self.ng.object; | |
| 9567 | 9538 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 9568 | 9539 | const inst_ty = self.typeOfIndex(inst); |
| 9569 | 9540 | const operand_ty = self.typeOf(ty_op.operand); |
| ... | ... | @@ -9581,7 +9552,7 @@ pub const FuncGen = struct { |
| 9581 | 9552 | } |
| 9582 | 9553 | |
| 9583 | 9554 | fn airBitOp(self: *FuncGen, inst: Air.Inst.Index, intrinsic: Builder.Intrinsic) !Builder.Value { |
| 9584 | const o = self.dg.object; | |
| 9555 | const o = self.ng.object; | |
| 9585 | 9556 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 9586 | 9557 | const inst_ty = self.typeOfIndex(inst); |
| 9587 | 9558 | const operand_ty = self.typeOf(ty_op.operand); |
| ... | ... | @@ -9599,7 +9570,7 @@ pub const FuncGen = struct { |
| 9599 | 9570 | } |
| 9600 | 9571 | |
| 9601 | 9572 | fn airByteSwap(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { |
| 9602 | const o = self.dg.object; | |
| 9573 | const o = self.ng.object; | |
| 9603 | 9574 | const mod = o.pt.zcu; |
| 9604 | 9575 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 9605 | 9576 | const operand_ty = self.typeOf(ty_op.operand); |
| ... | ... | @@ -9633,7 +9604,7 @@ pub const FuncGen = struct { |
| 9633 | 9604 | } |
| 9634 | 9605 | |
| 9635 | 9606 | fn airErrorSetHasValue(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { |
| 9636 | const o = self.dg.object; | |
| 9607 | const o = self.ng.object; | |
| 9637 | 9608 | const mod = o.pt.zcu; |
| 9638 | 9609 | const ip = &mod.intern_pool; |
| 9639 | 9610 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| ... | ... | @@ -9665,7 +9636,7 @@ pub const FuncGen = struct { |
| 9665 | 9636 | } |
| 9666 | 9637 | |
| 9667 | 9638 | fn airIsNamedEnumValue(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { |
| 9668 | const o = self.dg.object; | |
| 9639 | const o = self.ng.object; | |
| 9669 | 9640 | const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op; |
| 9670 | 9641 | const operand = try self.resolveInst(un_op); |
| 9671 | 9642 | const enum_ty = self.typeOf(un_op); |
| ... | ... | @@ -9683,22 +9654,21 @@ pub const FuncGen = struct { |
| 9683 | 9654 | } |
| 9684 | 9655 | |
| 9685 | 9656 | fn getIsNamedEnumValueFunction(self: *FuncGen, enum_ty: Type) !Builder.Function.Index { |
| 9686 | const o = self.dg.object; | |
| 9657 | const o = self.ng.object; | |
| 9687 | 9658 | const pt = o.pt; |
| 9688 | 9659 | const zcu = pt.zcu; |
| 9689 | 9660 | const ip = &zcu.intern_pool; |
| 9690 | 9661 | const enum_type = ip.loadEnumType(enum_ty.toIntern()); |
| 9691 | 9662 | |
| 9692 | 9663 | // TODO: detect when the type changes and re-emit this function. |
| 9693 | const gop = try o.named_enum_map.getOrPut(o.gpa, enum_type.decl); | |
| 9664 | const gop = try o.named_enum_map.getOrPut(o.gpa, enum_ty.toIntern()); | |
| 9694 | 9665 | if (gop.found_existing) return gop.value_ptr.*; |
| 9695 | errdefer assert(o.named_enum_map.remove(enum_type.decl)); | |
| 9666 | errdefer assert(o.named_enum_map.remove(enum_ty.toIntern())); | |
| 9696 | 9667 | |
| 9697 | const decl = zcu.declPtr(enum_type.decl); | |
| 9698 | 9668 | const target = zcu.root_mod.resolved_target.result; |
| 9699 | 9669 | const function_index = try o.builder.addFunction( |
| 9700 | 9670 | try o.builder.fnType(.i1, &.{try o.lowerType(Type.fromInterned(enum_type.tag_ty))}, .normal), |
| 9701 | try o.builder.strtabStringFmt("__zig_is_named_enum_value_{}", .{decl.fqn.fmt(ip)}), | |
| 9671 | try o.builder.strtabStringFmt("__zig_is_named_enum_value_{}", .{enum_type.name.fmt(ip)}), | |
| 9702 | 9672 | toLlvmAddressSpace(.generic, target), |
| 9703 | 9673 | ); |
| 9704 | 9674 | |
| ... | ... | @@ -9741,7 +9711,7 @@ pub const FuncGen = struct { |
| 9741 | 9711 | } |
| 9742 | 9712 | |
| 9743 | 9713 | fn airTagName(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { |
| 9744 | const o = self.dg.object; | |
| 9714 | const o = self.ng.object; | |
| 9745 | 9715 | const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op; |
| 9746 | 9716 | const operand = try self.resolveInst(un_op); |
| 9747 | 9717 | const enum_ty = self.typeOf(un_op); |
| ... | ... | @@ -9759,7 +9729,7 @@ pub const FuncGen = struct { |
| 9759 | 9729 | } |
| 9760 | 9730 | |
| 9761 | 9731 | fn airErrorName(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { |
| 9762 | const o = self.dg.object; | |
| 9732 | const o = self.ng.object; | |
| 9763 | 9733 | const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op; |
| 9764 | 9734 | const operand = try self.resolveInst(un_op); |
| 9765 | 9735 | const slice_ty = self.typeOfIndex(inst); |
| ... | ... | @@ -9774,7 +9744,7 @@ pub const FuncGen = struct { |
| 9774 | 9744 | } |
| 9775 | 9745 | |
| 9776 | 9746 | fn airSplat(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { |
| 9777 | const o = self.dg.object; | |
| 9747 | const o = self.ng.object; | |
| 9778 | 9748 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 9779 | 9749 | const scalar = try self.resolveInst(ty_op.operand); |
| 9780 | 9750 | const vector_ty = self.typeOfIndex(inst); |
| ... | ... | @@ -9792,7 +9762,7 @@ pub const FuncGen = struct { |
| 9792 | 9762 | } |
| 9793 | 9763 | |
| 9794 | 9764 | fn airShuffle(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { |
| 9795 | const o = self.dg.object; | |
| 9765 | const o = self.ng.object; | |
| 9796 | 9766 | const pt = o.pt; |
| 9797 | 9767 | const mod = pt.zcu; |
| 9798 | 9768 | const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; |
| ... | ... | @@ -9848,7 +9818,7 @@ pub const FuncGen = struct { |
| 9848 | 9818 | vector_len: usize, |
| 9849 | 9819 | accum_init: Builder.Value, |
| 9850 | 9820 | ) !Builder.Value { |
| 9851 | const o = self.dg.object; | |
| 9821 | const o = self.ng.object; | |
| 9852 | 9822 | const usize_ty = try o.lowerType(Type.usize); |
| 9853 | 9823 | const llvm_vector_len = try o.builder.intValue(usize_ty, vector_len); |
| 9854 | 9824 | const llvm_result_ty = accum_init.typeOfWip(&self.wip); |
| ... | ... | @@ -9902,7 +9872,7 @@ pub const FuncGen = struct { |
| 9902 | 9872 | } |
| 9903 | 9873 | |
| 9904 | 9874 | fn airReduce(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) !Builder.Value { |
| 9905 | const o = self.dg.object; | |
| 9875 | const o = self.ng.object; | |
| 9906 | 9876 | const mod = o.pt.zcu; |
| 9907 | 9877 | const target = mod.getTarget(); |
| 9908 | 9878 | |
| ... | ... | @@ -10012,7 +9982,7 @@ pub const FuncGen = struct { |
| 10012 | 9982 | } |
| 10013 | 9983 | |
| 10014 | 9984 | fn airAggregateInit(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { |
| 10015 | const o = self.dg.object; | |
| 9985 | const o = self.ng.object; | |
| 10016 | 9986 | const pt = o.pt; |
| 10017 | 9987 | const mod = pt.zcu; |
| 10018 | 9988 | const ip = &mod.intern_pool; |
| ... | ... | @@ -10133,7 +10103,7 @@ pub const FuncGen = struct { |
| 10133 | 10103 | } |
| 10134 | 10104 | |
| 10135 | 10105 | fn airUnionInit(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { |
| 10136 | const o = self.dg.object; | |
| 10106 | const o = self.ng.object; | |
| 10137 | 10107 | const pt = o.pt; |
| 10138 | 10108 | const mod = pt.zcu; |
| 10139 | 10109 | const ip = &mod.intern_pool; |
| ... | ... | @@ -10256,7 +10226,7 @@ pub const FuncGen = struct { |
| 10256 | 10226 | } |
| 10257 | 10227 | |
| 10258 | 10228 | fn airPrefetch(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { |
| 10259 | const o = self.dg.object; | |
| 10229 | const o = self.ng.object; | |
| 10260 | 10230 | const prefetch = self.air.instructions.items(.data)[@intFromEnum(inst)].prefetch; |
| 10261 | 10231 | |
| 10262 | 10232 | comptime assert(@intFromEnum(std.builtin.PrefetchOptions.Rw.read) == 0); |
| ... | ... | @@ -10306,7 +10276,7 @@ pub const FuncGen = struct { |
| 10306 | 10276 | } |
| 10307 | 10277 | |
| 10308 | 10278 | fn airAddrSpaceCast(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { |
| 10309 | const o = self.dg.object; | |
| 10279 | const o = self.ng.object; | |
| 10310 | 10280 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 10311 | 10281 | const inst_ty = self.typeOfIndex(inst); |
| 10312 | 10282 | const operand = try self.resolveInst(ty_op.operand); |
| ... | ... | @@ -10324,12 +10294,12 @@ pub const FuncGen = struct { |
| 10324 | 10294 | 0 => @field(Builder.Intrinsic, basename ++ ".x"), |
| 10325 | 10295 | 1 => @field(Builder.Intrinsic, basename ++ ".y"), |
| 10326 | 10296 | 2 => @field(Builder.Intrinsic, basename ++ ".z"), |
| 10327 | else => return self.dg.object.builder.intValue(.i32, default), | |
| 10297 | else => return self.ng.object.builder.intValue(.i32, default), | |
| 10328 | 10298 | }, &.{}, &.{}, ""); |
| 10329 | 10299 | } |
| 10330 | 10300 | |
| 10331 | 10301 | fn airWorkItemId(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { |
| 10332 | const o = self.dg.object; | |
| 10302 | const o = self.ng.object; | |
| 10333 | 10303 | const target = o.pt.zcu.getTarget(); |
| 10334 | 10304 | assert(target.cpu.arch == .amdgcn); // TODO is to port this function to other GPU architectures |
| 10335 | 10305 | |
| ... | ... | @@ -10339,7 +10309,7 @@ pub const FuncGen = struct { |
| 10339 | 10309 | } |
| 10340 | 10310 | |
| 10341 | 10311 | fn airWorkGroupSize(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { |
| 10342 | const o = self.dg.object; | |
| 10312 | const o = self.ng.object; | |
| 10343 | 10313 | const target = o.pt.zcu.getTarget(); |
| 10344 | 10314 | assert(target.cpu.arch == .amdgcn); // TODO is to port this function to other GPU architectures |
| 10345 | 10315 | |
| ... | ... | @@ -10362,7 +10332,7 @@ pub const FuncGen = struct { |
| 10362 | 10332 | } |
| 10363 | 10333 | |
| 10364 | 10334 | fn airWorkGroupId(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { |
| 10365 | const o = self.dg.object; | |
| 10335 | const o = self.ng.object; | |
| 10366 | 10336 | const target = o.pt.zcu.getTarget(); |
| 10367 | 10337 | assert(target.cpu.arch == .amdgcn); // TODO is to port this function to other GPU architectures |
| 10368 | 10338 | |
| ... | ... | @@ -10372,7 +10342,7 @@ pub const FuncGen = struct { |
| 10372 | 10342 | } |
| 10373 | 10343 | |
| 10374 | 10344 | fn getErrorNameTable(self: *FuncGen) Allocator.Error!Builder.Variable.Index { |
| 10375 | const o = self.dg.object; | |
| 10345 | const o = self.ng.object; | |
| 10376 | 10346 | const pt = o.pt; |
| 10377 | 10347 | |
| 10378 | 10348 | const table = o.error_name_table; |
| ... | ... | @@ -10401,7 +10371,7 @@ pub const FuncGen = struct { |
| 10401 | 10371 | opt_handle: Builder.Value, |
| 10402 | 10372 | is_by_ref: bool, |
| 10403 | 10373 | ) Allocator.Error!Builder.Value { |
| 10404 | const o = self.dg.object; | |
| 10374 | const o = self.ng.object; | |
| 10405 | 10375 | const field = b: { |
| 10406 | 10376 | if (is_by_ref) { |
| 10407 | 10377 | const field_ptr = try self.wip.gepStruct(opt_llvm_ty, opt_handle, 1, ""); |
| ... | ... | @@ -10422,7 +10392,7 @@ pub const FuncGen = struct { |
| 10422 | 10392 | opt_ty: Type, |
| 10423 | 10393 | can_elide_load: bool, |
| 10424 | 10394 | ) !Builder.Value { |
| 10425 | const o = fg.dg.object; | |
| 10395 | const o = fg.ng.object; | |
| 10426 | 10396 | const pt = o.pt; |
| 10427 | 10397 | const mod = pt.zcu; |
| 10428 | 10398 | const payload_ty = opt_ty.optionalChild(mod); |
| ... | ... | @@ -10451,7 +10421,7 @@ pub const FuncGen = struct { |
| 10451 | 10421 | payload: Builder.Value, |
| 10452 | 10422 | non_null_bit: Builder.Value, |
| 10453 | 10423 | ) !Builder.Value { |
| 10454 | const o = self.dg.object; | |
| 10424 | const o = self.ng.object; | |
| 10455 | 10425 | const pt = o.pt; |
| 10456 | 10426 | const optional_llvm_ty = try o.lowerType(optional_ty); |
| 10457 | 10427 | const non_null_field = try self.wip.cast(.zext, non_null_bit, .i8, ""); |
| ... | ... | @@ -10483,7 +10453,7 @@ pub const FuncGen = struct { |
| 10483 | 10453 | struct_ptr_ty: Type, |
| 10484 | 10454 | field_index: u32, |
| 10485 | 10455 | ) !Builder.Value { |
| 10486 | const o = self.dg.object; | |
| 10456 | const o = self.ng.object; | |
| 10487 | 10457 | const pt = o.pt; |
| 10488 | 10458 | const mod = pt.zcu; |
| 10489 | 10459 | const struct_ty = struct_ptr_ty.childType(mod); |
| ... | ... | @@ -10552,7 +10522,7 @@ pub const FuncGen = struct { |
| 10552 | 10522 | // "When loading a value of a type like i20 with a size that is not an integral number of bytes, the result is undefined if the value was not originally written using a store of the same type. " |
| 10553 | 10523 | // => so load the byte aligned value and trunc the unwanted bits. |
| 10554 | 10524 | |
| 10555 | const o = fg.dg.object; | |
| 10525 | const o = fg.ng.object; | |
| 10556 | 10526 | const pt = o.pt; |
| 10557 | 10527 | const mod = pt.zcu; |
| 10558 | 10528 | const payload_llvm_ty = try o.lowerType(payload_ty); |
| ... | ... | @@ -10599,7 +10569,7 @@ pub const FuncGen = struct { |
| 10599 | 10569 | ptr_alignment: Builder.Alignment, |
| 10600 | 10570 | access_kind: Builder.MemoryAccessKind, |
| 10601 | 10571 | ) !Builder.Value { |
| 10602 | const o = fg.dg.object; | |
| 10572 | const o = fg.ng.object; | |
| 10603 | 10573 | const pt = o.pt; |
| 10604 | 10574 | //const pointee_llvm_ty = try o.lowerType(pointee_type); |
| 10605 | 10575 | const result_align = InternPool.Alignment.fromLlvm(ptr_alignment).max(pointee_type.abiAlignment(pt)).toLlvm(); |
| ... | ... | @@ -10620,7 +10590,7 @@ pub const FuncGen = struct { |
| 10620 | 10590 | /// alloca and copies the value into it, then returns the alloca instruction. |
| 10621 | 10591 | /// For isByRef=false types, it creates a load instruction and returns it. |
| 10622 | 10592 | fn load(self: *FuncGen, ptr: Builder.Value, ptr_ty: Type) !Builder.Value { |
| 10623 | const o = self.dg.object; | |
| 10593 | const o = self.ng.object; | |
| 10624 | 10594 | const pt = o.pt; |
| 10625 | 10595 | const mod = pt.zcu; |
| 10626 | 10596 | const info = ptr_ty.ptrInfo(mod); |
| ... | ... | @@ -10693,7 +10663,7 @@ pub const FuncGen = struct { |
| 10693 | 10663 | elem: Builder.Value, |
| 10694 | 10664 | ordering: Builder.AtomicOrdering, |
| 10695 | 10665 | ) !void { |
| 10696 | const o = self.dg.object; | |
| 10666 | const o = self.ng.object; | |
| 10697 | 10667 | const pt = o.pt; |
| 10698 | 10668 | const mod = pt.zcu; |
| 10699 | 10669 | const info = ptr_ty.ptrInfo(mod); |
| ... | ... | @@ -10784,7 +10754,7 @@ pub const FuncGen = struct { |
| 10784 | 10754 | |
| 10785 | 10755 | fn valgrindMarkUndef(fg: *FuncGen, ptr: Builder.Value, len: Builder.Value) Allocator.Error!void { |
| 10786 | 10756 | const VG_USERREQ__MAKE_MEM_UNDEFINED = 1296236545; |
| 10787 | const o = fg.dg.object; | |
| 10757 | const o = fg.ng.object; | |
| 10788 | 10758 | const usize_ty = try o.lowerType(Type.usize); |
| 10789 | 10759 | const zero = try o.builder.intValue(usize_ty, 0); |
| 10790 | 10760 | const req = try o.builder.intValue(usize_ty, VG_USERREQ__MAKE_MEM_UNDEFINED); |
| ... | ... | @@ -10802,7 +10772,7 @@ pub const FuncGen = struct { |
| 10802 | 10772 | a4: Builder.Value, |
| 10803 | 10773 | a5: Builder.Value, |
| 10804 | 10774 | ) Allocator.Error!Builder.Value { |
| 10805 | const o = fg.dg.object; | |
| 10775 | const o = fg.ng.object; | |
| 10806 | 10776 | const pt = o.pt; |
| 10807 | 10777 | const mod = pt.zcu; |
| 10808 | 10778 | const target = mod.getTarget(); |
| ... | ... | @@ -10869,13 +10839,13 @@ pub const FuncGen = struct { |
| 10869 | 10839 | } |
| 10870 | 10840 | |
| 10871 | 10841 | fn typeOf(fg: *FuncGen, inst: Air.Inst.Ref) Type { |
| 10872 | const o = fg.dg.object; | |
| 10842 | const o = fg.ng.object; | |
| 10873 | 10843 | const mod = o.pt.zcu; |
| 10874 | 10844 | return fg.air.typeOf(inst, &mod.intern_pool); |
| 10875 | 10845 | } |
| 10876 | 10846 | |
| 10877 | 10847 | fn typeOfIndex(fg: *FuncGen, inst: Air.Inst.Index) Type { |
| 10878 | const o = fg.dg.object; | |
| 10848 | const o = fg.ng.object; | |
| 10879 | 10849 | const mod = o.pt.zcu; |
| 10880 | 10850 | return fg.air.typeOfIndex(inst, &mod.intern_pool); |
| 10881 | 10851 | } |
src/codegen/spirv.zig+287-299| ... | ... | @@ -31,9 +31,9 @@ const InstMap = std.AutoHashMapUnmanaged(Air.Inst.Index, IdRef); |
| 31 | 31 | |
| 32 | 32 | pub const zig_call_abi_ver = 3; |
| 33 | 33 | |
| 34 | const InternMap = std.AutoHashMapUnmanaged(struct { InternPool.Index, DeclGen.Repr }, IdResult); | |
| 34 | const InternMap = std.AutoHashMapUnmanaged(struct { InternPool.Index, NavGen.Repr }, IdResult); | |
| 35 | 35 | const PtrTypeMap = std.AutoHashMapUnmanaged( |
| 36 | struct { InternPool.Index, StorageClass, DeclGen.Repr }, | |
| 36 | struct { InternPool.Index, StorageClass, NavGen.Repr }, | |
| 37 | 37 | struct { ty_id: IdRef, fwd_emitted: bool }, |
| 38 | 38 | ); |
| 39 | 39 | |
| ... | ... | @@ -142,7 +142,7 @@ const ControlFlow = union(enum) { |
| 142 | 142 | }; |
| 143 | 143 | |
| 144 | 144 | /// This structure holds information that is relevant to the entire compilation, |
| 145 | /// in contrast to `DeclGen`, which only holds relevant information about a | |
| 145 | /// in contrast to `NavGen`, which only holds relevant information about a | |
| 146 | 146 | /// single decl. |
| 147 | 147 | pub const Object = struct { |
| 148 | 148 | /// A general-purpose allocator that can be used for any allocation for this Object. |
| ... | ... | @@ -153,10 +153,10 @@ pub const Object = struct { |
| 153 | 153 | |
| 154 | 154 | /// The Zig module that this object file is generated for. |
| 155 | 155 | /// A map of Zig decl indices to SPIR-V decl indices. |
| 156 | decl_link: std.AutoHashMapUnmanaged(InternPool.DeclIndex, SpvModule.Decl.Index) = .{}, | |
| 156 | nav_link: std.AutoHashMapUnmanaged(InternPool.Nav.Index, SpvModule.Decl.Index) = .{}, | |
| 157 | 157 | |
| 158 | 158 | /// A map of Zig InternPool indices for anonymous decls to SPIR-V decl indices. |
| 159 | anon_decl_link: std.AutoHashMapUnmanaged(struct { InternPool.Index, StorageClass }, SpvModule.Decl.Index) = .{}, | |
| 159 | uav_link: std.AutoHashMapUnmanaged(struct { InternPool.Index, StorageClass }, SpvModule.Decl.Index) = .{}, | |
| 160 | 160 | |
| 161 | 161 | /// A map that maps AIR intern pool indices to SPIR-V result-ids. |
| 162 | 162 | intern_map: InternMap = .{}, |
| ... | ... | @@ -178,31 +178,29 @@ pub const Object = struct { |
| 178 | 178 | |
| 179 | 179 | pub fn deinit(self: *Object) void { |
| 180 | 180 | self.spv.deinit(); |
| 181 | self.decl_link.deinit(self.gpa); | |
| 182 | self.anon_decl_link.deinit(self.gpa); | |
| 181 | self.nav_link.deinit(self.gpa); | |
| 182 | self.uav_link.deinit(self.gpa); | |
| 183 | 183 | self.intern_map.deinit(self.gpa); |
| 184 | 184 | self.ptr_types.deinit(self.gpa); |
| 185 | 185 | } |
| 186 | 186 | |
| 187 | fn genDecl( | |
| 187 | fn genNav( | |
| 188 | 188 | self: *Object, |
| 189 | 189 | pt: Zcu.PerThread, |
| 190 | decl_index: InternPool.DeclIndex, | |
| 190 | nav_index: InternPool.Nav.Index, | |
| 191 | 191 | air: Air, |
| 192 | 192 | liveness: Liveness, |
| 193 | 193 | ) !void { |
| 194 | 194 | const zcu = pt.zcu; |
| 195 | 195 | const gpa = zcu.gpa; |
| 196 | const decl = zcu.declPtr(decl_index); | |
| 197 | const namespace = zcu.namespacePtr(decl.src_namespace); | |
| 198 | const structured_cfg = namespace.fileScope(zcu).mod.structured_cfg; | |
| 196 | const structured_cfg = zcu.navFileScope(nav_index).mod.structured_cfg; | |
| 199 | 197 | |
| 200 | var decl_gen = DeclGen{ | |
| 198 | var nav_gen = NavGen{ | |
| 201 | 199 | .gpa = gpa, |
| 202 | 200 | .object = self, |
| 203 | 201 | .pt = pt, |
| 204 | 202 | .spv = &self.spv, |
| 205 | .decl_index = decl_index, | |
| 203 | .owner_nav = nav_index, | |
| 206 | 204 | .air = air, |
| 207 | 205 | .liveness = liveness, |
| 208 | 206 | .intern_map = &self.intern_map, |
| ... | ... | @@ -212,18 +210,18 @@ pub const Object = struct { |
| 212 | 210 | false => .{ .unstructured = .{} }, |
| 213 | 211 | }, |
| 214 | 212 | .current_block_label = undefined, |
| 215 | .base_line = decl.navSrcLine(zcu), | |
| 213 | .base_line = zcu.navSrcLine(nav_index), | |
| 216 | 214 | }; |
| 217 | defer decl_gen.deinit(); | |
| 215 | defer nav_gen.deinit(); | |
| 218 | 216 | |
| 219 | decl_gen.genDecl() catch |err| switch (err) { | |
| 217 | nav_gen.genNav() catch |err| switch (err) { | |
| 220 | 218 | error.CodegenFail => { |
| 221 | try zcu.failed_analysis.put(gpa, InternPool.AnalUnit.wrap(.{ .decl = decl_index }), decl_gen.error_msg.?); | |
| 219 | try zcu.failed_codegen.put(gpa, nav_index, nav_gen.error_msg.?); | |
| 222 | 220 | }, |
| 223 | 221 | else => |other| { |
| 224 | 222 | // There might be an error that happened *after* self.error_msg |
| 225 | 223 | // was already allocated, so be sure to free it. |
| 226 | if (decl_gen.error_msg) |error_msg| { | |
| 224 | if (nav_gen.error_msg) |error_msg| { | |
| 227 | 225 | error_msg.deinit(gpa); |
| 228 | 226 | } |
| 229 | 227 | |
| ... | ... | @@ -239,31 +237,30 @@ pub const Object = struct { |
| 239 | 237 | air: Air, |
| 240 | 238 | liveness: Liveness, |
| 241 | 239 | ) !void { |
| 242 | const decl_index = pt.zcu.funcInfo(func_index).owner_decl; | |
| 240 | const nav = pt.zcu.funcInfo(func_index).owner_nav; | |
| 243 | 241 | // TODO: Separate types for generating decls and functions? |
| 244 | try self.genDecl(pt, decl_index, air, liveness); | |
| 242 | try self.genNav(pt, nav, air, liveness); | |
| 245 | 243 | } |
| 246 | 244 | |
| 247 | pub fn updateDecl( | |
| 245 | pub fn updateNav( | |
| 248 | 246 | self: *Object, |
| 249 | 247 | pt: Zcu.PerThread, |
| 250 | decl_index: InternPool.DeclIndex, | |
| 248 | nav: InternPool.Nav.Index, | |
| 251 | 249 | ) !void { |
| 252 | try self.genDecl(pt, decl_index, undefined, undefined); | |
| 250 | try self.genNav(pt, nav, undefined, undefined); | |
| 253 | 251 | } |
| 254 | 252 | |
| 255 | /// Fetch or allocate a result id for decl index. This function also marks the decl as alive. | |
| 256 | /// Note: Function does not actually generate the decl, it just allocates an index. | |
| 257 | pub fn resolveDecl(self: *Object, zcu: *Zcu, decl_index: InternPool.DeclIndex) !SpvModule.Decl.Index { | |
| 258 | const decl = zcu.declPtr(decl_index); | |
| 259 | assert(decl.has_tv); // TODO: Do we need to handle a situation where this is false? | |
| 260 | ||
| 261 | const entry = try self.decl_link.getOrPut(self.gpa, decl_index); | |
| 253 | /// Fetch or allocate a result id for nav index. This function also marks the nav as alive. | |
| 254 | /// Note: Function does not actually generate the nav, it just allocates an index. | |
| 255 | pub fn resolveNav(self: *Object, zcu: *Zcu, nav_index: InternPool.Nav.Index) !SpvModule.Decl.Index { | |
| 256 | const ip = &zcu.intern_pool; | |
| 257 | const entry = try self.nav_link.getOrPut(self.gpa, nav_index); | |
| 262 | 258 | if (!entry.found_existing) { |
| 259 | const nav = ip.getNav(nav_index); | |
| 263 | 260 | // TODO: Extern fn? |
| 264 | const kind: SpvModule.Decl.Kind = if (decl.val.isFuncBody(zcu)) | |
| 261 | const kind: SpvModule.Decl.Kind = if (ip.isFunctionType(nav.typeOf(ip))) | |
| 265 | 262 | .func |
| 266 | else switch (decl.@"addrspace") { | |
| 263 | else switch (nav.status.resolved.@"addrspace") { | |
| 267 | 264 | .generic => .invocation_global, |
| 268 | 265 | else => .global, |
| 269 | 266 | }; |
| ... | ... | @@ -276,8 +273,8 @@ pub const Object = struct { |
| 276 | 273 | }; |
| 277 | 274 | |
| 278 | 275 | /// This structure is used to compile a declaration, and contains all relevant meta-information to deal with that. |
| 279 | const DeclGen = struct { | |
| 280 | /// A general-purpose allocator that can be used for any allocations for this DeclGen. | |
| 276 | const NavGen = struct { | |
| 277 | /// A general-purpose allocator that can be used for any allocations for this NavGen. | |
| 281 | 278 | gpa: Allocator, |
| 282 | 279 | |
| 283 | 280 | /// The object that this decl is generated into. |
| ... | ... | @@ -291,7 +288,7 @@ const DeclGen = struct { |
| 291 | 288 | spv: *SpvModule, |
| 292 | 289 | |
| 293 | 290 | /// The decl we are currently generating code for. |
| 294 | decl_index: InternPool.DeclIndex, | |
| 291 | owner_nav: InternPool.Nav.Index, | |
| 295 | 292 | |
| 296 | 293 | /// The intermediate code of the declaration we are currently generating. Note: If |
| 297 | 294 | /// the declaration is not a function, this value will be undefined! |
| ... | ... | @@ -399,8 +396,8 @@ const DeclGen = struct { |
| 399 | 396 | indirect, |
| 400 | 397 | }; |
| 401 | 398 | |
| 402 | /// Free resources owned by the DeclGen. | |
| 403 | pub fn deinit(self: *DeclGen) void { | |
| 399 | /// Free resources owned by the NavGen. | |
| 400 | pub fn deinit(self: *NavGen) void { | |
| 404 | 401 | self.args.deinit(self.gpa); |
| 405 | 402 | self.inst_results.deinit(self.gpa); |
| 406 | 403 | self.control_flow.deinit(self.gpa); |
| ... | ... | @@ -408,26 +405,26 @@ const DeclGen = struct { |
| 408 | 405 | } |
| 409 | 406 | |
| 410 | 407 | /// Return the target which we are currently compiling for. |
| 411 | pub fn getTarget(self: *DeclGen) std.Target { | |
| 408 | pub fn getTarget(self: *NavGen) std.Target { | |
| 412 | 409 | return self.pt.zcu.getTarget(); |
| 413 | 410 | } |
| 414 | 411 | |
| 415 | pub fn fail(self: *DeclGen, comptime format: []const u8, args: anytype) Error { | |
| 412 | pub fn fail(self: *NavGen, comptime format: []const u8, args: anytype) Error { | |
| 416 | 413 | @setCold(true); |
| 417 | 414 | const zcu = self.pt.zcu; |
| 418 | const src_loc = zcu.declPtr(self.decl_index).navSrcLoc(zcu); | |
| 415 | const src_loc = zcu.navSrcLoc(self.owner_nav); | |
| 419 | 416 | assert(self.error_msg == null); |
| 420 | 417 | self.error_msg = try Zcu.ErrorMsg.create(zcu.gpa, src_loc, format, args); |
| 421 | 418 | return error.CodegenFail; |
| 422 | 419 | } |
| 423 | 420 | |
| 424 | pub fn todo(self: *DeclGen, comptime format: []const u8, args: anytype) Error { | |
| 421 | pub fn todo(self: *NavGen, comptime format: []const u8, args: anytype) Error { | |
| 425 | 422 | return self.fail("TODO (SPIR-V): " ++ format, args); |
| 426 | 423 | } |
| 427 | 424 | |
| 428 | 425 | /// This imports the "default" extended instruction set for the target |
| 429 | 426 | /// For OpenCL, OpenCL.std.100. For Vulkan, GLSL.std.450. |
| 430 | fn importExtendedSet(self: *DeclGen) !IdResult { | |
| 427 | fn importExtendedSet(self: *NavGen) !IdResult { | |
| 431 | 428 | const target = self.getTarget(); |
| 432 | 429 | return switch (target.os.tag) { |
| 433 | 430 | .opencl => try self.spv.importInstructionSet(.@"OpenCL.std"), |
| ... | ... | @@ -437,18 +434,18 @@ const DeclGen = struct { |
| 437 | 434 | } |
| 438 | 435 | |
| 439 | 436 | /// Fetch the result-id for a previously generated instruction or constant. |
| 440 | fn resolve(self: *DeclGen, inst: Air.Inst.Ref) !IdRef { | |
| 437 | fn resolve(self: *NavGen, inst: Air.Inst.Ref) !IdRef { | |
| 441 | 438 | const pt = self.pt; |
| 442 | 439 | const mod = pt.zcu; |
| 443 | 440 | if (try self.air.value(inst, pt)) |val| { |
| 444 | 441 | const ty = self.typeOf(inst); |
| 445 | 442 | if (ty.zigTypeTag(mod) == .Fn) { |
| 446 | const fn_decl_index = switch (mod.intern_pool.indexToKey(val.ip_index)) { | |
| 447 | .extern_func => |extern_func| extern_func.decl, | |
| 448 | .func => |func| func.owner_decl, | |
| 443 | const fn_nav = switch (mod.intern_pool.indexToKey(val.ip_index)) { | |
| 444 | .@"extern" => |@"extern"| @"extern".owner_nav, | |
| 445 | .func => |func| func.owner_nav, | |
| 449 | 446 | else => unreachable, |
| 450 | 447 | }; |
| 451 | const spv_decl_index = try self.object.resolveDecl(mod, fn_decl_index); | |
| 448 | const spv_decl_index = try self.object.resolveNav(mod, fn_nav); | |
| 452 | 449 | try self.func.decl_deps.put(self.spv.gpa, spv_decl_index, {}); |
| 453 | 450 | return self.spv.declPtr(spv_decl_index).result_id; |
| 454 | 451 | } |
| ... | ... | @@ -459,7 +456,7 @@ const DeclGen = struct { |
| 459 | 456 | return self.inst_results.get(index).?; // Assertion means instruction does not dominate usage. |
| 460 | 457 | } |
| 461 | 458 | |
| 462 | fn resolveAnonDecl(self: *DeclGen, val: InternPool.Index) !IdRef { | |
| 459 | fn resolveUav(self: *NavGen, val: InternPool.Index) !IdRef { | |
| 463 | 460 | // TODO: This cannot be a function at this point, but it should probably be handled anyway. |
| 464 | 461 | |
| 465 | 462 | const mod = self.pt.zcu; |
| ... | ... | @@ -467,7 +464,7 @@ const DeclGen = struct { |
| 467 | 464 | const decl_ptr_ty_id = try self.ptrType(ty, .Generic); |
| 468 | 465 | |
| 469 | 466 | const spv_decl_index = blk: { |
| 470 | const entry = try self.object.anon_decl_link.getOrPut(self.object.gpa, .{ val, .Function }); | |
| 467 | const entry = try self.object.uav_link.getOrPut(self.object.gpa, .{ val, .Function }); | |
| 471 | 468 | if (entry.found_existing) { |
| 472 | 469 | try self.addFunctionDep(entry.value_ptr.*, .Function); |
| 473 | 470 | |
| ... | ... | @@ -540,7 +537,7 @@ const DeclGen = struct { |
| 540 | 537 | return try self.castToGeneric(decl_ptr_ty_id, result_id); |
| 541 | 538 | } |
| 542 | 539 | |
| 543 | fn addFunctionDep(self: *DeclGen, decl_index: SpvModule.Decl.Index, storage_class: StorageClass) !void { | |
| 540 | fn addFunctionDep(self: *NavGen, decl_index: SpvModule.Decl.Index, storage_class: StorageClass) !void { | |
| 544 | 541 | const target = self.getTarget(); |
| 545 | 542 | if (target.os.tag == .vulkan) { |
| 546 | 543 | // Shader entry point dependencies must be variables with Input or Output storage class |
| ... | ... | @@ -555,7 +552,7 @@ const DeclGen = struct { |
| 555 | 552 | } |
| 556 | 553 | } |
| 557 | 554 | |
| 558 | fn castToGeneric(self: *DeclGen, type_id: IdRef, ptr_id: IdRef) !IdRef { | |
| 555 | fn castToGeneric(self: *NavGen, type_id: IdRef, ptr_id: IdRef) !IdRef { | |
| 559 | 556 | const target = self.getTarget(); |
| 560 | 557 | |
| 561 | 558 | if (target.os.tag == .vulkan) { |
| ... | ... | @@ -575,7 +572,7 @@ const DeclGen = struct { |
| 575 | 572 | /// block we are currently generating. |
| 576 | 573 | /// Note that there is no such thing as nested blocks like in ZIR or AIR, so we don't need to |
| 577 | 574 | /// keep track of the previous block. |
| 578 | fn beginSpvBlock(self: *DeclGen, label: IdResult) !void { | |
| 575 | fn beginSpvBlock(self: *NavGen, label: IdResult) !void { | |
| 579 | 576 | try self.func.body.emit(self.spv.gpa, .OpLabel, .{ .id_result = label }); |
| 580 | 577 | self.current_block_label = label; |
| 581 | 578 | } |
| ... | ... | @@ -590,7 +587,7 @@ const DeclGen = struct { |
| 590 | 587 | /// TODO: The extension SPV_INTEL_arbitrary_precision_integers allows any integer size (at least up to 32 bits). |
| 591 | 588 | /// TODO: This probably needs an ABI-version as well (especially in combination with SPV_INTEL_arbitrary_precision_integers). |
| 592 | 589 | /// TODO: Should the result of this function be cached? |
| 593 | fn backingIntBits(self: *DeclGen, bits: u16) ?u16 { | |
| 590 | fn backingIntBits(self: *NavGen, bits: u16) ?u16 { | |
| 594 | 591 | const target = self.getTarget(); |
| 595 | 592 | |
| 596 | 593 | // The backend will never be asked to compiler a 0-bit integer, so we won't have to handle those in this function. |
| ... | ... | @@ -625,7 +622,7 @@ const DeclGen = struct { |
| 625 | 622 | /// In theory that could also be used, but since the spec says that it only guarantees support up to 32-bit ints there |
| 626 | 623 | /// is no way of knowing whether those are actually supported. |
| 627 | 624 | /// TODO: Maybe this should be cached? |
| 628 | fn largestSupportedIntBits(self: *DeclGen) u16 { | |
| 625 | fn largestSupportedIntBits(self: *NavGen) u16 { | |
| 629 | 626 | const target = self.getTarget(); |
| 630 | 627 | return if (Target.spirv.featureSetHas(target.cpu.features, .Int64)) |
| 631 | 628 | 64 |
| ... | ... | @@ -636,12 +633,12 @@ const DeclGen = struct { |
| 636 | 633 | /// Checks whether the type is "composite int", an integer consisting of multiple native integers. These are represented by |
| 637 | 634 | /// arrays of largestSupportedIntBits(). |
| 638 | 635 | /// Asserts `ty` is an integer. |
| 639 | fn isCompositeInt(self: *DeclGen, ty: Type) bool { | |
| 636 | fn isCompositeInt(self: *NavGen, ty: Type) bool { | |
| 640 | 637 | return self.backingIntBits(ty) == null; |
| 641 | 638 | } |
| 642 | 639 | |
| 643 | 640 | /// Checks whether the type can be directly translated to SPIR-V vectors |
| 644 | fn isSpvVector(self: *DeclGen, ty: Type) bool { | |
| 641 | fn isSpvVector(self: *NavGen, ty: Type) bool { | |
| 645 | 642 | const mod = self.pt.zcu; |
| 646 | 643 | const target = self.getTarget(); |
| 647 | 644 | if (ty.zigTypeTag(mod) != .Vector) return false; |
| ... | ... | @@ -667,7 +664,7 @@ const DeclGen = struct { |
| 667 | 664 | return is_scalar and (spirv_len or opencl_len); |
| 668 | 665 | } |
| 669 | 666 | |
| 670 | fn arithmeticTypeInfo(self: *DeclGen, ty: Type) ArithmeticTypeInfo { | |
| 667 | fn arithmeticTypeInfo(self: *NavGen, ty: Type) ArithmeticTypeInfo { | |
| 671 | 668 | const mod = self.pt.zcu; |
| 672 | 669 | const target = self.getTarget(); |
| 673 | 670 | var scalar_ty = ty.scalarType(mod); |
| ... | ... | @@ -715,7 +712,7 @@ const DeclGen = struct { |
| 715 | 712 | } |
| 716 | 713 | |
| 717 | 714 | /// Emits a bool constant in a particular representation. |
| 718 | fn constBool(self: *DeclGen, value: bool, repr: Repr) !IdRef { | |
| 715 | fn constBool(self: *NavGen, value: bool, repr: Repr) !IdRef { | |
| 719 | 716 | // TODO: Cache? |
| 720 | 717 | |
| 721 | 718 | const section = &self.spv.sections.types_globals_constants; |
| ... | ... | @@ -742,7 +739,7 @@ const DeclGen = struct { |
| 742 | 739 | /// Emits an integer constant. |
| 743 | 740 | /// This function, unlike SpvModule.constInt, takes care to bitcast |
| 744 | 741 | /// the value to an unsigned int first for Kernels. |
| 745 | fn constInt(self: *DeclGen, ty: Type, value: anytype, repr: Repr) !IdRef { | |
| 742 | fn constInt(self: *NavGen, ty: Type, value: anytype, repr: Repr) !IdRef { | |
| 746 | 743 | // TODO: Cache? |
| 747 | 744 | const mod = self.pt.zcu; |
| 748 | 745 | const scalar_ty = ty.scalarType(mod); |
| ... | ... | @@ -809,7 +806,7 @@ const DeclGen = struct { |
| 809 | 806 | /// ty must be a struct type. |
| 810 | 807 | /// Constituents should be in `indirect` representation (as the elements of a struct should be). |
| 811 | 808 | /// Result is in `direct` representation. |
| 812 | fn constructStruct(self: *DeclGen, ty: Type, types: []const Type, constituents: []const IdRef) !IdRef { | |
| 809 | fn constructStruct(self: *NavGen, ty: Type, types: []const Type, constituents: []const IdRef) !IdRef { | |
| 813 | 810 | assert(types.len == constituents.len); |
| 814 | 811 | |
| 815 | 812 | const result_id = self.spv.allocId(); |
| ... | ... | @@ -823,7 +820,7 @@ const DeclGen = struct { |
| 823 | 820 | |
| 824 | 821 | /// Construct a vector at runtime. |
| 825 | 822 | /// ty must be an vector type. |
| 826 | fn constructVector(self: *DeclGen, ty: Type, constituents: []const IdRef) !IdRef { | |
| 823 | fn constructVector(self: *NavGen, ty: Type, constituents: []const IdRef) !IdRef { | |
| 827 | 824 | const mod = self.pt.zcu; |
| 828 | 825 | assert(ty.vectorLen(mod) == constituents.len); |
| 829 | 826 | |
| ... | ... | @@ -847,7 +844,7 @@ const DeclGen = struct { |
| 847 | 844 | |
| 848 | 845 | /// Construct a vector at runtime with all lanes set to the same value. |
| 849 | 846 | /// ty must be an vector type. |
| 850 | fn constructVectorSplat(self: *DeclGen, ty: Type, constituent: IdRef) !IdRef { | |
| 847 | fn constructVectorSplat(self: *NavGen, ty: Type, constituent: IdRef) !IdRef { | |
| 851 | 848 | const mod = self.pt.zcu; |
| 852 | 849 | const n = ty.vectorLen(mod); |
| 853 | 850 | |
| ... | ... | @@ -862,7 +859,7 @@ const DeclGen = struct { |
| 862 | 859 | /// ty must be an array type. |
| 863 | 860 | /// Constituents should be in `indirect` representation (as the elements of an array should be). |
| 864 | 861 | /// Result is in `direct` representation. |
| 865 | fn constructArray(self: *DeclGen, ty: Type, constituents: []const IdRef) !IdRef { | |
| 862 | fn constructArray(self: *NavGen, ty: Type, constituents: []const IdRef) !IdRef { | |
| 866 | 863 | const result_id = self.spv.allocId(); |
| 867 | 864 | try self.func.body.emit(self.spv.gpa, .OpCompositeConstruct, .{ |
| 868 | 865 | .id_result_type = try self.resolveType(ty, .direct), |
| ... | ... | @@ -878,7 +875,7 @@ const DeclGen = struct { |
| 878 | 875 | /// is done by emitting a sequence of instructions that initialize the value. |
| 879 | 876 | // |
| 880 | 877 | /// This function should only be called during function code generation. |
| 881 | fn constant(self: *DeclGen, ty: Type, val: Value, repr: Repr) !IdRef { | |
| 878 | fn constant(self: *NavGen, ty: Type, val: Value, repr: Repr) !IdRef { | |
| 882 | 879 | // Note: Using intern_map can only be used with constants that DO NOT generate any runtime code!! |
| 883 | 880 | // Ideally that should be all constants in the future, or it should be cleaned up somehow. For |
| 884 | 881 | // now, only use the intern_map on case-by-case basis by breaking to :cache. |
| ... | ... | @@ -922,7 +919,7 @@ const DeclGen = struct { |
| 922 | 919 | .undef => unreachable, // handled above |
| 923 | 920 | |
| 924 | 921 | .variable, |
| 925 | .extern_func, | |
| 922 | .@"extern", | |
| 926 | 923 | .func, |
| 927 | 924 | .enum_literal, |
| 928 | 925 | .empty_enum_value, |
| ... | ... | @@ -1142,7 +1139,7 @@ const DeclGen = struct { |
| 1142 | 1139 | return cacheable_id; |
| 1143 | 1140 | } |
| 1144 | 1141 | |
| 1145 | fn constantPtr(self: *DeclGen, ptr_val: Value) Error!IdRef { | |
| 1142 | fn constantPtr(self: *NavGen, ptr_val: Value) Error!IdRef { | |
| 1146 | 1143 | // TODO: Caching?? |
| 1147 | 1144 | |
| 1148 | 1145 | const pt = self.pt; |
| ... | ... | @@ -1160,7 +1157,7 @@ const DeclGen = struct { |
| 1160 | 1157 | return self.derivePtr(derivation); |
| 1161 | 1158 | } |
| 1162 | 1159 | |
| 1163 | fn derivePtr(self: *DeclGen, derivation: Value.PointerDeriveStep) Error!IdRef { | |
| 1160 | fn derivePtr(self: *NavGen, derivation: Value.PointerDeriveStep) Error!IdRef { | |
| 1164 | 1161 | const pt = self.pt; |
| 1165 | 1162 | const zcu = pt.zcu; |
| 1166 | 1163 | switch (derivation) { |
| ... | ... | @@ -1178,13 +1175,13 @@ const DeclGen = struct { |
| 1178 | 1175 | }); |
| 1179 | 1176 | return result_ptr_id; |
| 1180 | 1177 | }, |
| 1181 | .decl_ptr => |decl| { | |
| 1182 | const result_ptr_ty = try zcu.declPtr(decl).declPtrType(pt); | |
| 1183 | return self.constantDeclRef(result_ptr_ty, decl); | |
| 1178 | .nav_ptr => |nav| { | |
| 1179 | const result_ptr_ty = try pt.navPtrType(nav); | |
| 1180 | return self.constantNavRef(result_ptr_ty, nav); | |
| 1184 | 1181 | }, |
| 1185 | .anon_decl_ptr => |ad| { | |
| 1186 | const result_ptr_ty = Type.fromInterned(ad.orig_ty); | |
| 1187 | return self.constantAnonDeclRef(result_ptr_ty, ad); | |
| 1182 | .uav_ptr => |uav| { | |
| 1183 | const result_ptr_ty = Type.fromInterned(uav.orig_ty); | |
| 1184 | return self.constantUavRef(result_ptr_ty, uav); | |
| 1188 | 1185 | }, |
| 1189 | 1186 | .eu_payload_ptr => @panic("TODO"), |
| 1190 | 1187 | .opt_payload_ptr => @panic("TODO"), |
| ... | ... | @@ -1227,10 +1224,10 @@ const DeclGen = struct { |
| 1227 | 1224 | } |
| 1228 | 1225 | } |
| 1229 | 1226 | |
| 1230 | fn constantAnonDeclRef( | |
| 1231 | self: *DeclGen, | |
| 1227 | fn constantUavRef( | |
| 1228 | self: *NavGen, | |
| 1232 | 1229 | ty: Type, |
| 1233 | anon_decl: InternPool.Key.Ptr.BaseAddr.AnonDecl, | |
| 1230 | uav: InternPool.Key.Ptr.BaseAddr.Uav, | |
| 1234 | 1231 | ) !IdRef { |
| 1235 | 1232 | // TODO: Merge this function with constantDeclRef. |
| 1236 | 1233 | |
| ... | ... | @@ -1238,31 +1235,24 @@ const DeclGen = struct { |
| 1238 | 1235 | const mod = pt.zcu; |
| 1239 | 1236 | const ip = &mod.intern_pool; |
| 1240 | 1237 | const ty_id = try self.resolveType(ty, .direct); |
| 1241 | const decl_val = anon_decl.val; | |
| 1242 | const decl_ty = Type.fromInterned(ip.typeOf(decl_val)); | |
| 1238 | const uav_ty = Type.fromInterned(ip.typeOf(uav.val)); | |
| 1243 | 1239 | |
| 1244 | if (Value.fromInterned(decl_val).getFunction(mod)) |func| { | |
| 1245 | _ = func; | |
| 1246 | unreachable; // TODO | |
| 1247 | } else if (Value.fromInterned(decl_val).getExternFunc(mod)) |func| { | |
| 1248 | _ = func; | |
| 1249 | unreachable; | |
| 1240 | switch (ip.indexToKey(uav.val)) { | |
| 1241 | .func => unreachable, // TODO | |
| 1242 | .@"extern" => assert(!ip.isFunctionType(uav_ty.toIntern())), | |
| 1243 | else => {}, | |
| 1250 | 1244 | } |
| 1251 | 1245 | |
| 1252 | 1246 | // const is_fn_body = decl_ty.zigTypeTag(mod) == .Fn; |
| 1253 | if (!decl_ty.isFnOrHasRuntimeBitsIgnoreComptime(pt)) { | |
| 1254 | // Pointer to nothing - return undefoined | |
| 1247 | if (!uav_ty.isFnOrHasRuntimeBitsIgnoreComptime(pt)) { | |
| 1248 | // Pointer to nothing - return undefined | |
| 1255 | 1249 | return self.spv.constUndef(ty_id); |
| 1256 | 1250 | } |
| 1257 | 1251 | |
| 1258 | if (decl_ty.zigTypeTag(mod) == .Fn) { | |
| 1259 | unreachable; // TODO | |
| 1260 | } | |
| 1261 | ||
| 1262 | // Anon decl refs are always generic. | |
| 1252 | // Uav refs are always generic. | |
| 1263 | 1253 | assert(ty.ptrAddressSpace(mod) == .generic); |
| 1264 | const decl_ptr_ty_id = try self.ptrType(decl_ty, .Generic); | |
| 1265 | const ptr_id = try self.resolveAnonDecl(decl_val); | |
| 1254 | const decl_ptr_ty_id = try self.ptrType(uav_ty, .Generic); | |
| 1255 | const ptr_id = try self.resolveUav(uav.val); | |
| 1266 | 1256 | |
| 1267 | 1257 | if (decl_ptr_ty_id != ty_id) { |
| 1268 | 1258 | // Differing pointer types, insert a cast. |
| ... | ... | @@ -1278,28 +1268,31 @@ const DeclGen = struct { |
| 1278 | 1268 | } |
| 1279 | 1269 | } |
| 1280 | 1270 | |
| 1281 | fn constantDeclRef(self: *DeclGen, ty: Type, decl_index: InternPool.DeclIndex) !IdRef { | |
| 1271 | fn constantNavRef(self: *NavGen, ty: Type, nav_index: InternPool.Nav.Index) !IdRef { | |
| 1282 | 1272 | const pt = self.pt; |
| 1283 | 1273 | const mod = pt.zcu; |
| 1274 | const ip = &mod.intern_pool; | |
| 1284 | 1275 | const ty_id = try self.resolveType(ty, .direct); |
| 1285 | const decl = mod.declPtr(decl_index); | |
| 1276 | const nav = ip.getNav(nav_index); | |
| 1277 | const nav_val = mod.navValue(nav_index); | |
| 1278 | const nav_ty = nav_val.typeOf(mod); | |
| 1286 | 1279 | |
| 1287 | switch (mod.intern_pool.indexToKey(decl.val.ip_index)) { | |
| 1280 | switch (ip.indexToKey(nav_val.toIntern())) { | |
| 1288 | 1281 | .func => { |
| 1289 | 1282 | // TODO: Properly lower function pointers. For now we are going to hack around it and |
| 1290 | 1283 | // just generate an empty pointer. Function pointers are represented by a pointer to usize. |
| 1291 | 1284 | return try self.spv.constUndef(ty_id); |
| 1292 | 1285 | }, |
| 1293 | .extern_func => unreachable, // TODO | |
| 1286 | .@"extern" => assert(!ip.isFunctionType(nav_ty.toIntern())), // TODO | |
| 1294 | 1287 | else => {}, |
| 1295 | 1288 | } |
| 1296 | 1289 | |
| 1297 | if (!decl.typeOf(mod).isFnOrHasRuntimeBitsIgnoreComptime(pt)) { | |
| 1290 | if (!nav_ty.isFnOrHasRuntimeBitsIgnoreComptime(pt)) { | |
| 1298 | 1291 | // Pointer to nothing - return undefined. |
| 1299 | 1292 | return self.spv.constUndef(ty_id); |
| 1300 | 1293 | } |
| 1301 | 1294 | |
| 1302 | const spv_decl_index = try self.object.resolveDecl(mod, decl_index); | |
| 1295 | const spv_decl_index = try self.object.resolveNav(mod, nav_index); | |
| 1303 | 1296 | const spv_decl = self.spv.declPtr(spv_decl_index); |
| 1304 | 1297 | |
| 1305 | 1298 | const decl_id = switch (spv_decl.kind) { |
| ... | ... | @@ -1307,10 +1300,10 @@ const DeclGen = struct { |
| 1307 | 1300 | .global, .invocation_global => spv_decl.result_id, |
| 1308 | 1301 | }; |
| 1309 | 1302 | |
| 1310 | const final_storage_class = self.spvStorageClass(decl.@"addrspace"); | |
| 1303 | const final_storage_class = self.spvStorageClass(nav.status.resolved.@"addrspace"); | |
| 1311 | 1304 | try self.addFunctionDep(spv_decl_index, final_storage_class); |
| 1312 | 1305 | |
| 1313 | const decl_ptr_ty_id = try self.ptrType(decl.typeOf(mod), final_storage_class); | |
| 1306 | const decl_ptr_ty_id = try self.ptrType(nav_ty, final_storage_class); | |
| 1314 | 1307 | |
| 1315 | 1308 | const ptr_id = switch (final_storage_class) { |
| 1316 | 1309 | .Generic => try self.castToGeneric(decl_ptr_ty_id, decl_id), |
| ... | ... | @@ -1332,7 +1325,7 @@ const DeclGen = struct { |
| 1332 | 1325 | } |
| 1333 | 1326 | |
| 1334 | 1327 | // Turn a Zig type's name into a cache reference. |
| 1335 | fn resolveTypeName(self: *DeclGen, ty: Type) ![]const u8 { | |
| 1328 | fn resolveTypeName(self: *NavGen, ty: Type) ![]const u8 { | |
| 1336 | 1329 | var name = std.ArrayList(u8).init(self.gpa); |
| 1337 | 1330 | defer name.deinit(); |
| 1338 | 1331 | try ty.print(name.writer(), self.pt); |
| ... | ... | @@ -1343,7 +1336,7 @@ const DeclGen = struct { |
| 1343 | 1336 | /// The integer type that is returned by this function is the type that is used to perform |
| 1344 | 1337 | /// actual operations (as well as store) a Zig type of a particular number of bits. To create |
| 1345 | 1338 | /// a type with an exact size, use SpvModule.intType. |
| 1346 | fn intType(self: *DeclGen, signedness: std.builtin.Signedness, bits: u16) !IdRef { | |
| 1339 | fn intType(self: *NavGen, signedness: std.builtin.Signedness, bits: u16) !IdRef { | |
| 1347 | 1340 | const backing_bits = self.backingIntBits(bits) orelse { |
| 1348 | 1341 | // TODO: Integers too big for any native type are represented as "composite integers": |
| 1349 | 1342 | // An array of largestSupportedIntBits. |
| ... | ... | @@ -1358,7 +1351,7 @@ const DeclGen = struct { |
| 1358 | 1351 | return self.spv.intType(.unsigned, backing_bits); |
| 1359 | 1352 | } |
| 1360 | 1353 | |
| 1361 | fn arrayType(self: *DeclGen, len: u32, child_ty: IdRef) !IdRef { | |
| 1354 | fn arrayType(self: *NavGen, len: u32, child_ty: IdRef) !IdRef { | |
| 1362 | 1355 | // TODO: Cache?? |
| 1363 | 1356 | const len_id = try self.constInt(Type.u32, len, .direct); |
| 1364 | 1357 | const result_id = self.spv.allocId(); |
| ... | ... | @@ -1371,11 +1364,11 @@ const DeclGen = struct { |
| 1371 | 1364 | return result_id; |
| 1372 | 1365 | } |
| 1373 | 1366 | |
| 1374 | fn ptrType(self: *DeclGen, child_ty: Type, storage_class: StorageClass) !IdRef { | |
| 1367 | fn ptrType(self: *NavGen, child_ty: Type, storage_class: StorageClass) !IdRef { | |
| 1375 | 1368 | return try self.ptrType2(child_ty, storage_class, .indirect); |
| 1376 | 1369 | } |
| 1377 | 1370 | |
| 1378 | fn ptrType2(self: *DeclGen, child_ty: Type, storage_class: StorageClass, child_repr: Repr) !IdRef { | |
| 1371 | fn ptrType2(self: *NavGen, child_ty: Type, storage_class: StorageClass, child_repr: Repr) !IdRef { | |
| 1379 | 1372 | const key = .{ child_ty.toIntern(), storage_class, child_repr }; |
| 1380 | 1373 | const entry = try self.ptr_types.getOrPut(self.gpa, key); |
| 1381 | 1374 | if (entry.found_existing) { |
| ... | ... | @@ -1407,7 +1400,7 @@ const DeclGen = struct { |
| 1407 | 1400 | return result_id; |
| 1408 | 1401 | } |
| 1409 | 1402 | |
| 1410 | fn functionType(self: *DeclGen, return_ty: Type, param_types: []const Type) !IdRef { | |
| 1403 | fn functionType(self: *NavGen, return_ty: Type, param_types: []const Type) !IdRef { | |
| 1411 | 1404 | // TODO: Cache?? |
| 1412 | 1405 | |
| 1413 | 1406 | const param_ids = try self.gpa.alloc(IdRef, param_types.len); |
| ... | ... | @@ -1427,7 +1420,7 @@ const DeclGen = struct { |
| 1427 | 1420 | return ty_id; |
| 1428 | 1421 | } |
| 1429 | 1422 | |
| 1430 | fn zigScalarOrVectorTypeLike(self: *DeclGen, new_ty: Type, base_ty: Type) !Type { | |
| 1423 | fn zigScalarOrVectorTypeLike(self: *NavGen, new_ty: Type, base_ty: Type) !Type { | |
| 1431 | 1424 | const pt = self.pt; |
| 1432 | 1425 | const new_scalar_ty = new_ty.scalarType(pt.zcu); |
| 1433 | 1426 | if (!base_ty.isVector(pt.zcu)) { |
| ... | ... | @@ -1458,7 +1451,7 @@ const DeclGen = struct { |
| 1458 | 1451 | /// padding: [padding_size]u8, |
| 1459 | 1452 | /// } |
| 1460 | 1453 | /// If any of the fields' size is 0, it will be omitted. |
| 1461 | fn resolveUnionType(self: *DeclGen, ty: Type) !IdRef { | |
| 1454 | fn resolveUnionType(self: *NavGen, ty: Type) !IdRef { | |
| 1462 | 1455 | const mod = self.pt.zcu; |
| 1463 | 1456 | const ip = &mod.intern_pool; |
| 1464 | 1457 | const union_obj = mod.typeToUnion(ty).?; |
| ... | ... | @@ -1509,7 +1502,7 @@ const DeclGen = struct { |
| 1509 | 1502 | return result_id; |
| 1510 | 1503 | } |
| 1511 | 1504 | |
| 1512 | fn resolveFnReturnType(self: *DeclGen, ret_ty: Type) !IdRef { | |
| 1505 | fn resolveFnReturnType(self: *NavGen, ret_ty: Type) !IdRef { | |
| 1513 | 1506 | const pt = self.pt; |
| 1514 | 1507 | if (!ret_ty.hasRuntimeBitsIgnoreComptime(pt)) { |
| 1515 | 1508 | // If the return type is an error set or an error union, then we make this |
| ... | ... | @@ -1526,7 +1519,7 @@ const DeclGen = struct { |
| 1526 | 1519 | } |
| 1527 | 1520 | |
| 1528 | 1521 | /// Turn a Zig type into a SPIR-V Type, and return a reference to it. |
| 1529 | fn resolveType(self: *DeclGen, ty: Type, repr: Repr) Error!IdRef { | |
| 1522 | fn resolveType(self: *NavGen, ty: Type, repr: Repr) Error!IdRef { | |
| 1530 | 1523 | if (self.intern_map.get(.{ ty.toIntern(), repr })) |id| { |
| 1531 | 1524 | return id; |
| 1532 | 1525 | } |
| ... | ... | @@ -1536,7 +1529,7 @@ const DeclGen = struct { |
| 1536 | 1529 | return id; |
| 1537 | 1530 | } |
| 1538 | 1531 | |
| 1539 | fn resolveTypeInner(self: *DeclGen, ty: Type, repr: Repr) Error!IdRef { | |
| 1532 | fn resolveTypeInner(self: *NavGen, ty: Type, repr: Repr) Error!IdRef { | |
| 1540 | 1533 | const pt = self.pt; |
| 1541 | 1534 | const mod = pt.zcu; |
| 1542 | 1535 | const ip = &mod.intern_pool; |
| ... | ... | @@ -1839,7 +1832,7 @@ const DeclGen = struct { |
| 1839 | 1832 | } |
| 1840 | 1833 | } |
| 1841 | 1834 | |
| 1842 | fn spvStorageClass(self: *DeclGen, as: std.builtin.AddressSpace) StorageClass { | |
| 1835 | fn spvStorageClass(self: *NavGen, as: std.builtin.AddressSpace) StorageClass { | |
| 1843 | 1836 | const target = self.getTarget(); |
| 1844 | 1837 | return switch (as) { |
| 1845 | 1838 | .generic => switch (target.os.tag) { |
| ... | ... | @@ -1882,7 +1875,7 @@ const DeclGen = struct { |
| 1882 | 1875 | } |
| 1883 | 1876 | }; |
| 1884 | 1877 | |
| 1885 | fn errorUnionLayout(self: *DeclGen, payload_ty: Type) ErrorUnionLayout { | |
| 1878 | fn errorUnionLayout(self: *NavGen, payload_ty: Type) ErrorUnionLayout { | |
| 1886 | 1879 | const pt = self.pt; |
| 1887 | 1880 | |
| 1888 | 1881 | const error_align = Type.anyerror.abiAlignment(pt); |
| ... | ... | @@ -1913,7 +1906,7 @@ const DeclGen = struct { |
| 1913 | 1906 | total_fields: u32, |
| 1914 | 1907 | }; |
| 1915 | 1908 | |
| 1916 | fn unionLayout(self: *DeclGen, ty: Type) UnionLayout { | |
| 1909 | fn unionLayout(self: *NavGen, ty: Type) UnionLayout { | |
| 1917 | 1910 | const pt = self.pt; |
| 1918 | 1911 | const mod = pt.zcu; |
| 1919 | 1912 | const ip = &mod.intern_pool; |
| ... | ... | @@ -2004,25 +1997,25 @@ const DeclGen = struct { |
| 2004 | 1997 | return .{ .ty = ty, .value = .{ .singleton = singleton } }; |
| 2005 | 1998 | } |
| 2006 | 1999 | |
| 2007 | fn materialize(self: Temporary, dg: *DeclGen) !IdResult { | |
| 2008 | const mod = dg.pt.zcu; | |
| 2000 | fn materialize(self: Temporary, ng: *NavGen) !IdResult { | |
| 2001 | const mod = ng.pt.zcu; | |
| 2009 | 2002 | switch (self.value) { |
| 2010 | 2003 | .singleton => |id| return id, |
| 2011 | 2004 | .exploded_vector => |range| { |
| 2012 | 2005 | assert(self.ty.isVector(mod)); |
| 2013 | 2006 | assert(self.ty.vectorLen(mod) == range.len); |
| 2014 | const consituents = try dg.gpa.alloc(IdRef, range.len); | |
| 2015 | defer dg.gpa.free(consituents); | |
| 2007 | const consituents = try ng.gpa.alloc(IdRef, range.len); | |
| 2008 | defer ng.gpa.free(consituents); | |
| 2016 | 2009 | for (consituents, 0..range.len) |*id, i| { |
| 2017 | 2010 | id.* = range.at(i); |
| 2018 | 2011 | } |
| 2019 | return dg.constructVector(self.ty, consituents); | |
| 2012 | return ng.constructVector(self.ty, consituents); | |
| 2020 | 2013 | }, |
| 2021 | 2014 | } |
| 2022 | 2015 | } |
| 2023 | 2016 | |
| 2024 | fn vectorization(self: Temporary, dg: *DeclGen) Vectorization { | |
| 2025 | return Vectorization.fromType(self.ty, dg); | |
| 2017 | fn vectorization(self: Temporary, ng: *NavGen) Vectorization { | |
| 2018 | return Vectorization.fromType(self.ty, ng); | |
| 2026 | 2019 | } |
| 2027 | 2020 | |
| 2028 | 2021 | fn pun(self: Temporary, new_ty: Type) Temporary { |
| ... | ... | @@ -2034,8 +2027,8 @@ const DeclGen = struct { |
| 2034 | 2027 | |
| 2035 | 2028 | /// 'Explode' a temporary into separate elements. This turns a vector |
| 2036 | 2029 | /// into a bag of elements. |
| 2037 | fn explode(self: Temporary, dg: *DeclGen) !IdRange { | |
| 2038 | const mod = dg.pt.zcu; | |
| 2030 | fn explode(self: Temporary, ng: *NavGen) !IdRange { | |
| 2031 | const mod = ng.pt.zcu; | |
| 2039 | 2032 | |
| 2040 | 2033 | // If the value is a scalar, then this is a no-op. |
| 2041 | 2034 | if (!self.ty.isVector(mod)) { |
| ... | ... | @@ -2045,9 +2038,9 @@ const DeclGen = struct { |
| 2045 | 2038 | }; |
| 2046 | 2039 | } |
| 2047 | 2040 | |
| 2048 | const ty_id = try dg.resolveType(self.ty.scalarType(mod), .direct); | |
| 2041 | const ty_id = try ng.resolveType(self.ty.scalarType(mod), .direct); | |
| 2049 | 2042 | const n = self.ty.vectorLen(mod); |
| 2050 | const results = dg.spv.allocIds(n); | |
| 2043 | const results = ng.spv.allocIds(n); | |
| 2051 | 2044 | |
| 2052 | 2045 | const id = switch (self.value) { |
| 2053 | 2046 | .singleton => |id| id, |
| ... | ... | @@ -2056,7 +2049,7 @@ const DeclGen = struct { |
| 2056 | 2049 | |
| 2057 | 2050 | for (0..n) |i| { |
| 2058 | 2051 | const indexes = [_]u32{@intCast(i)}; |
| 2059 | try dg.func.body.emit(dg.spv.gpa, .OpCompositeExtract, .{ | |
| 2052 | try ng.func.body.emit(ng.spv.gpa, .OpCompositeExtract, .{ | |
| 2060 | 2053 | .id_result_type = ty_id, |
| 2061 | 2054 | .id_result = results.at(i), |
| 2062 | 2055 | .composite = id, |
| ... | ... | @@ -2069,7 +2062,7 @@ const DeclGen = struct { |
| 2069 | 2062 | }; |
| 2070 | 2063 | |
| 2071 | 2064 | /// Initialize a `Temporary` from an AIR value. |
| 2072 | fn temporary(self: *DeclGen, inst: Air.Inst.Ref) !Temporary { | |
| 2065 | fn temporary(self: *NavGen, inst: Air.Inst.Ref) !Temporary { | |
| 2073 | 2066 | return .{ |
| 2074 | 2067 | .ty = self.typeOf(inst), |
| 2075 | 2068 | .value = .{ .singleton = try self.resolve(inst) }, |
| ... | ... | @@ -2093,11 +2086,11 @@ const DeclGen = struct { |
| 2093 | 2086 | /// Derive a vectorization from a particular type. This usually |
| 2094 | 2087 | /// only checks the size, but the source-of-truth is implemented |
| 2095 | 2088 | /// by `isSpvVector()`. |
| 2096 | fn fromType(ty: Type, dg: *DeclGen) Vectorization { | |
| 2097 | const mod = dg.pt.zcu; | |
| 2089 | fn fromType(ty: Type, ng: *NavGen) Vectorization { | |
| 2090 | const mod = ng.pt.zcu; | |
| 2098 | 2091 | if (!ty.isVector(mod)) { |
| 2099 | 2092 | return .scalar; |
| 2100 | } else if (dg.isSpvVector(ty)) { | |
| 2093 | } else if (ng.isSpvVector(ty)) { | |
| 2101 | 2094 | return .{ .spv_vectorized = ty.vectorLen(mod) }; |
| 2102 | 2095 | } else { |
| 2103 | 2096 | return .{ .unrolled = ty.vectorLen(mod) }; |
| ... | ... | @@ -2169,8 +2162,8 @@ const DeclGen = struct { |
| 2169 | 2162 | |
| 2170 | 2163 | /// Turns `ty` into the result-type of an individual vector operation. |
| 2171 | 2164 | /// `ty` may be a scalar or vector, it doesn't matter. |
| 2172 | fn operationType(self: Vectorization, dg: *DeclGen, ty: Type) !Type { | |
| 2173 | const pt = dg.pt; | |
| 2165 | fn operationType(self: Vectorization, ng: *NavGen, ty: Type) !Type { | |
| 2166 | const pt = ng.pt; | |
| 2174 | 2167 | const scalar_ty = ty.scalarType(pt.zcu); |
| 2175 | 2168 | return switch (self) { |
| 2176 | 2169 | .scalar, .unrolled => scalar_ty, |
| ... | ... | @@ -2183,8 +2176,8 @@ const DeclGen = struct { |
| 2183 | 2176 | |
| 2184 | 2177 | /// Turns `ty` into the result-type of the entire operation. |
| 2185 | 2178 | /// `ty` may be a scalar or vector, it doesn't matter. |
| 2186 | fn resultType(self: Vectorization, dg: *DeclGen, ty: Type) !Type { | |
| 2187 | const pt = dg.pt; | |
| 2179 | fn resultType(self: Vectorization, ng: *NavGen, ty: Type) !Type { | |
| 2180 | const pt = ng.pt; | |
| 2188 | 2181 | const scalar_ty = ty.scalarType(pt.zcu); |
| 2189 | 2182 | return switch (self) { |
| 2190 | 2183 | .scalar => scalar_ty, |
| ... | ... | @@ -2198,10 +2191,10 @@ const DeclGen = struct { |
| 2198 | 2191 | /// Before a temporary can be used, some setup may need to be one. This function implements |
| 2199 | 2192 | /// this setup, and returns a new type that holds the relevant information on how to access |
| 2200 | 2193 | /// elements of the input. |
| 2201 | fn prepare(self: Vectorization, dg: *DeclGen, tmp: Temporary) !PreparedOperand { | |
| 2202 | const pt = dg.pt; | |
| 2194 | fn prepare(self: Vectorization, ng: *NavGen, tmp: Temporary) !PreparedOperand { | |
| 2195 | const pt = ng.pt; | |
| 2203 | 2196 | const is_vector = tmp.ty.isVector(pt.zcu); |
| 2204 | const is_spv_vector = dg.isSpvVector(tmp.ty); | |
| 2197 | const is_spv_vector = ng.isSpvVector(tmp.ty); | |
| 2205 | 2198 | const value: PreparedOperand.Value = switch (tmp.value) { |
| 2206 | 2199 | .singleton => |id| switch (self) { |
| 2207 | 2200 | .scalar => blk: { |
| ... | ... | @@ -2220,7 +2213,7 @@ const DeclGen = struct { |
| 2220 | 2213 | .child = tmp.ty.toIntern(), |
| 2221 | 2214 | }); |
| 2222 | 2215 | |
| 2223 | const vector = try dg.constructVectorSplat(vector_ty, id); | |
| 2216 | const vector = try ng.constructVectorSplat(vector_ty, id); | |
| 2224 | 2217 | return .{ |
| 2225 | 2218 | .ty = vector_ty, |
| 2226 | 2219 | .value = .{ .spv_vectorwise = vector }, |
| ... | ... | @@ -2228,7 +2221,7 @@ const DeclGen = struct { |
| 2228 | 2221 | }, |
| 2229 | 2222 | .unrolled => blk: { |
| 2230 | 2223 | if (is_vector) { |
| 2231 | break :blk .{ .vector_exploded = try tmp.explode(dg) }; | |
| 2224 | break :blk .{ .vector_exploded = try tmp.explode(ng) }; | |
| 2232 | 2225 | } else { |
| 2233 | 2226 | break :blk .{ .scalar_broadcast = id }; |
| 2234 | 2227 | } |
| ... | ... | @@ -2243,7 +2236,7 @@ const DeclGen = struct { |
| 2243 | 2236 | // a type that cannot do that. |
| 2244 | 2237 | assert(is_spv_vector); |
| 2245 | 2238 | assert(range.len == n); |
| 2246 | const vec = try tmp.materialize(dg); | |
| 2239 | const vec = try tmp.materialize(ng); | |
| 2247 | 2240 | break :blk .{ .spv_vectorwise = vec }; |
| 2248 | 2241 | }, |
| 2249 | 2242 | .unrolled => |n| blk: { |
| ... | ... | @@ -2324,7 +2317,7 @@ const DeclGen = struct { |
| 2324 | 2317 | /// - A `Vectorization` instance |
| 2325 | 2318 | /// - A Type, in which case the vectorization is computed via `Vectorization.fromType`. |
| 2326 | 2319 | /// - A Temporary, in which case the vectorization is computed via `Temporary.vectorization`. |
| 2327 | fn vectorization(self: *DeclGen, args: anytype) Vectorization { | |
| 2320 | fn vectorization(self: *NavGen, args: anytype) Vectorization { | |
| 2328 | 2321 | var v: Vectorization = undefined; |
| 2329 | 2322 | assert(args.len >= 1); |
| 2330 | 2323 | inline for (args, 0..) |arg, i| { |
| ... | ... | @@ -2345,7 +2338,7 @@ const DeclGen = struct { |
| 2345 | 2338 | |
| 2346 | 2339 | /// This function builds an OpSConvert of OpUConvert depending on the |
| 2347 | 2340 | /// signedness of the types. |
| 2348 | fn buildIntConvert(self: *DeclGen, dst_ty: Type, src: Temporary) !Temporary { | |
| 2341 | fn buildIntConvert(self: *NavGen, dst_ty: Type, src: Temporary) !Temporary { | |
| 2349 | 2342 | const mod = self.pt.zcu; |
| 2350 | 2343 | |
| 2351 | 2344 | const dst_ty_id = try self.resolveType(dst_ty.scalarType(mod), .direct); |
| ... | ... | @@ -2384,7 +2377,7 @@ const DeclGen = struct { |
| 2384 | 2377 | return v.finalize(result_ty, results); |
| 2385 | 2378 | } |
| 2386 | 2379 | |
| 2387 | fn buildFma(self: *DeclGen, a: Temporary, b: Temporary, c: Temporary) !Temporary { | |
| 2380 | fn buildFma(self: *NavGen, a: Temporary, b: Temporary, c: Temporary) !Temporary { | |
| 2388 | 2381 | const target = self.getTarget(); |
| 2389 | 2382 | |
| 2390 | 2383 | const v = self.vectorization(.{ a, b, c }); |
| ... | ... | @@ -2424,7 +2417,7 @@ const DeclGen = struct { |
| 2424 | 2417 | return v.finalize(result_ty, results); |
| 2425 | 2418 | } |
| 2426 | 2419 | |
| 2427 | fn buildSelect(self: *DeclGen, condition: Temporary, lhs: Temporary, rhs: Temporary) !Temporary { | |
| 2420 | fn buildSelect(self: *NavGen, condition: Temporary, lhs: Temporary, rhs: Temporary) !Temporary { | |
| 2428 | 2421 | const mod = self.pt.zcu; |
| 2429 | 2422 | |
| 2430 | 2423 | const v = self.vectorization(.{ condition, lhs, rhs }); |
| ... | ... | @@ -2475,7 +2468,7 @@ const DeclGen = struct { |
| 2475 | 2468 | f_oge, |
| 2476 | 2469 | }; |
| 2477 | 2470 | |
| 2478 | fn buildCmp(self: *DeclGen, pred: CmpPredicate, lhs: Temporary, rhs: Temporary) !Temporary { | |
| 2471 | fn buildCmp(self: *NavGen, pred: CmpPredicate, lhs: Temporary, rhs: Temporary) !Temporary { | |
| 2479 | 2472 | const v = self.vectorization(.{ lhs, rhs }); |
| 2480 | 2473 | const ops = v.operations(); |
| 2481 | 2474 | const results = self.spv.allocIds(ops); |
| ... | ... | @@ -2543,7 +2536,7 @@ const DeclGen = struct { |
| 2543 | 2536 | log10, |
| 2544 | 2537 | }; |
| 2545 | 2538 | |
| 2546 | fn buildUnary(self: *DeclGen, op: UnaryOp, operand: Temporary) !Temporary { | |
| 2539 | fn buildUnary(self: *NavGen, op: UnaryOp, operand: Temporary) !Temporary { | |
| 2547 | 2540 | const target = self.getTarget(); |
| 2548 | 2541 | const v = blk: { |
| 2549 | 2542 | const v = self.vectorization(.{operand}); |
| ... | ... | @@ -2673,7 +2666,7 @@ const DeclGen = struct { |
| 2673 | 2666 | l_or, |
| 2674 | 2667 | }; |
| 2675 | 2668 | |
| 2676 | fn buildBinary(self: *DeclGen, op: BinaryOp, lhs: Temporary, rhs: Temporary) !Temporary { | |
| 2669 | fn buildBinary(self: *NavGen, op: BinaryOp, lhs: Temporary, rhs: Temporary) !Temporary { | |
| 2677 | 2670 | const target = self.getTarget(); |
| 2678 | 2671 | |
| 2679 | 2672 | const v = self.vectorization(.{ lhs, rhs }); |
| ... | ... | @@ -2762,7 +2755,7 @@ const DeclGen = struct { |
| 2762 | 2755 | /// This function builds an extended multiplication, either OpSMulExtended or OpUMulExtended on Vulkan, |
| 2763 | 2756 | /// or OpIMul and s_mul_hi or u_mul_hi on OpenCL. |
| 2764 | 2757 | fn buildWideMul( |
| 2765 | self: *DeclGen, | |
| 2758 | self: *NavGen, | |
| 2766 | 2759 | op: enum { |
| 2767 | 2760 | s_mul_extended, |
| 2768 | 2761 | u_mul_extended, |
| ... | ... | @@ -2893,7 +2886,7 @@ const DeclGen = struct { |
| 2893 | 2886 | /// OpFunctionEnd |
| 2894 | 2887 | /// TODO is to also write out the error as a function call parameter, and to somehow fetch |
| 2895 | 2888 | /// the name of an error in the text executor. |
| 2896 | fn generateTestEntryPoint(self: *DeclGen, name: []const u8, spv_test_decl_index: SpvModule.Decl.Index) !void { | |
| 2889 | fn generateTestEntryPoint(self: *NavGen, name: []const u8, spv_test_decl_index: SpvModule.Decl.Index) !void { | |
| 2897 | 2890 | const anyerror_ty_id = try self.resolveType(Type.anyerror, .direct); |
| 2898 | 2891 | const ptr_anyerror_ty = try self.pt.ptrType(.{ |
| 2899 | 2892 | .child = Type.anyerror.toIntern(), |
| ... | ... | @@ -2946,21 +2939,22 @@ const DeclGen = struct { |
| 2946 | 2939 | try self.spv.declareEntryPoint(spv_decl_index, test_name, .Kernel); |
| 2947 | 2940 | } |
| 2948 | 2941 | |
| 2949 | fn genDecl(self: *DeclGen) !void { | |
| 2942 | fn genNav(self: *NavGen) !void { | |
| 2950 | 2943 | const pt = self.pt; |
| 2951 | 2944 | const mod = pt.zcu; |
| 2952 | 2945 | const ip = &mod.intern_pool; |
| 2953 | const decl = mod.declPtr(self.decl_index); | |
| 2954 | const spv_decl_index = try self.object.resolveDecl(mod, self.decl_index); | |
| 2946 | const spv_decl_index = try self.object.resolveNav(mod, self.owner_nav); | |
| 2955 | 2947 | const result_id = self.spv.declPtr(spv_decl_index).result_id; |
| 2956 | 2948 | |
| 2949 | const nav = ip.getNav(self.owner_nav); | |
| 2950 | const val = mod.navValue(self.owner_nav); | |
| 2951 | const ty = val.typeOf(mod); | |
| 2957 | 2952 | switch (self.spv.declPtr(spv_decl_index).kind) { |
| 2958 | 2953 | .func => { |
| 2959 | assert(decl.typeOf(mod).zigTypeTag(mod) == .Fn); | |
| 2960 | const fn_info = mod.typeToFunc(decl.typeOf(mod)).?; | |
| 2954 | const fn_info = mod.typeToFunc(ty).?; | |
| 2961 | 2955 | const return_ty_id = try self.resolveFnReturnType(Type.fromInterned(fn_info.return_type)); |
| 2962 | 2956 | |
| 2963 | const prototype_ty_id = try self.resolveType(decl.typeOf(mod), .direct); | |
| 2957 | const prototype_ty_id = try self.resolveType(ty, .direct); | |
| 2964 | 2958 | try self.func.prologue.emit(self.spv.gpa, .OpFunction, .{ |
| 2965 | 2959 | .id_result_type = return_ty_id, |
| 2966 | 2960 | .id_result = result_id, |
| ... | ... | @@ -3012,27 +3006,26 @@ const DeclGen = struct { |
| 3012 | 3006 | // Append the actual code into the functions section. |
| 3013 | 3007 | try self.spv.addFunction(spv_decl_index, self.func); |
| 3014 | 3008 | |
| 3015 | try self.spv.debugName(result_id, decl.fqn.toSlice(ip)); | |
| 3009 | try self.spv.debugName(result_id, nav.fqn.toSlice(ip)); | |
| 3016 | 3010 | |
| 3017 | 3011 | // Temporarily generate a test kernel declaration if this is a test function. |
| 3018 | if (self.pt.zcu.test_functions.contains(self.decl_index)) { | |
| 3019 | try self.generateTestEntryPoint(decl.fqn.toSlice(ip), spv_decl_index); | |
| 3012 | if (self.pt.zcu.test_functions.contains(self.owner_nav)) { | |
| 3013 | try self.generateTestEntryPoint(nav.fqn.toSlice(ip), spv_decl_index); | |
| 3020 | 3014 | } |
| 3021 | 3015 | }, |
| 3022 | 3016 | .global => { |
| 3023 | const maybe_init_val: ?Value = blk: { | |
| 3024 | if (decl.val.getVariable(mod)) |payload| { | |
| 3025 | if (payload.is_extern) break :blk null; | |
| 3026 | break :blk Value.fromInterned(payload.init); | |
| 3027 | } | |
| 3028 | break :blk decl.val; | |
| 3017 | const maybe_init_val: ?Value = switch (ip.indexToKey(val.toIntern())) { | |
| 3018 | .func => unreachable, | |
| 3019 | .variable => |variable| Value.fromInterned(variable.init), | |
| 3020 | .@"extern" => null, | |
| 3021 | else => val, | |
| 3029 | 3022 | }; |
| 3030 | 3023 | assert(maybe_init_val == null); // TODO |
| 3031 | 3024 | |
| 3032 | const final_storage_class = self.spvStorageClass(decl.@"addrspace"); | |
| 3025 | const final_storage_class = self.spvStorageClass(nav.status.resolved.@"addrspace"); | |
| 3033 | 3026 | assert(final_storage_class != .Generic); // These should be instance globals |
| 3034 | 3027 | |
| 3035 | const ptr_ty_id = try self.ptrType(decl.typeOf(mod), final_storage_class); | |
| 3028 | const ptr_ty_id = try self.ptrType(ty, final_storage_class); | |
| 3036 | 3029 | |
| 3037 | 3030 | try self.spv.sections.types_globals_constants.emit(self.spv.gpa, .OpVariable, .{ |
| 3038 | 3031 | .id_result_type = ptr_ty_id, |
| ... | ... | @@ -3040,21 +3033,20 @@ const DeclGen = struct { |
| 3040 | 3033 | .storage_class = final_storage_class, |
| 3041 | 3034 | }); |
| 3042 | 3035 | |
| 3043 | try self.spv.debugName(result_id, decl.fqn.toSlice(ip)); | |
| 3036 | try self.spv.debugName(result_id, nav.fqn.toSlice(ip)); | |
| 3044 | 3037 | try self.spv.declareDeclDeps(spv_decl_index, &.{}); |
| 3045 | 3038 | }, |
| 3046 | 3039 | .invocation_global => { |
| 3047 | const maybe_init_val: ?Value = blk: { | |
| 3048 | if (decl.val.getVariable(mod)) |payload| { | |
| 3049 | if (payload.is_extern) break :blk null; | |
| 3050 | break :blk Value.fromInterned(payload.init); | |
| 3051 | } | |
| 3052 | break :blk decl.val; | |
| 3040 | const maybe_init_val: ?Value = switch (ip.indexToKey(val.toIntern())) { | |
| 3041 | .func => unreachable, | |
| 3042 | .variable => |variable| Value.fromInterned(variable.init), | |
| 3043 | .@"extern" => null, | |
| 3044 | else => val, | |
| 3053 | 3045 | }; |
| 3054 | 3046 | |
| 3055 | 3047 | try self.spv.declareDeclDeps(spv_decl_index, &.{}); |
| 3056 | 3048 | |
| 3057 | const ptr_ty_id = try self.ptrType(decl.typeOf(mod), .Function); | |
| 3049 | const ptr_ty_id = try self.ptrType(ty, .Function); | |
| 3058 | 3050 | |
| 3059 | 3051 | if (maybe_init_val) |init_val| { |
| 3060 | 3052 | // TODO: Combine with resolveAnonDecl? |
| ... | ... | @@ -3074,7 +3066,7 @@ const DeclGen = struct { |
| 3074 | 3066 | }); |
| 3075 | 3067 | self.current_block_label = root_block_id; |
| 3076 | 3068 | |
| 3077 | const val_id = try self.constant(decl.typeOf(mod), init_val, .indirect); | |
| 3069 | const val_id = try self.constant(ty, init_val, .indirect); | |
| 3078 | 3070 | try self.func.body.emit(self.spv.gpa, .OpStore, .{ |
| 3079 | 3071 | .pointer = result_id, |
| 3080 | 3072 | .object = val_id, |
| ... | ... | @@ -3084,7 +3076,7 @@ const DeclGen = struct { |
| 3084 | 3076 | try self.func.body.emit(self.spv.gpa, .OpFunctionEnd, {}); |
| 3085 | 3077 | try self.spv.addFunction(spv_decl_index, self.func); |
| 3086 | 3078 | |
| 3087 | try self.spv.debugNameFmt(initializer_id, "initializer of {}", .{decl.fqn.fmt(ip)}); | |
| 3079 | try self.spv.debugNameFmt(initializer_id, "initializer of {}", .{nav.fqn.fmt(ip)}); | |
| 3088 | 3080 | |
| 3089 | 3081 | try self.spv.sections.types_globals_constants.emit(self.spv.gpa, .OpExtInst, .{ |
| 3090 | 3082 | .id_result_type = ptr_ty_id, |
| ... | ... | @@ -3106,11 +3098,11 @@ const DeclGen = struct { |
| 3106 | 3098 | } |
| 3107 | 3099 | } |
| 3108 | 3100 | |
| 3109 | fn intFromBool(self: *DeclGen, value: Temporary) !Temporary { | |
| 3101 | fn intFromBool(self: *NavGen, value: Temporary) !Temporary { | |
| 3110 | 3102 | return try self.intFromBool2(value, Type.u1); |
| 3111 | 3103 | } |
| 3112 | 3104 | |
| 3113 | fn intFromBool2(self: *DeclGen, value: Temporary, result_ty: Type) !Temporary { | |
| 3105 | fn intFromBool2(self: *NavGen, value: Temporary, result_ty: Type) !Temporary { | |
| 3114 | 3106 | const zero_id = try self.constInt(result_ty, 0, .direct); |
| 3115 | 3107 | const one_id = try self.constInt(result_ty, 1, .direct); |
| 3116 | 3108 | |
| ... | ... | @@ -3123,7 +3115,7 @@ const DeclGen = struct { |
| 3123 | 3115 | |
| 3124 | 3116 | /// Convert representation from indirect (in memory) to direct (in 'register') |
| 3125 | 3117 | /// This converts the argument type from resolveType(ty, .indirect) to resolveType(ty, .direct). |
| 3126 | fn convertToDirect(self: *DeclGen, ty: Type, operand_id: IdRef) !IdRef { | |
| 3118 | fn convertToDirect(self: *NavGen, ty: Type, operand_id: IdRef) !IdRef { | |
| 3127 | 3119 | const mod = self.pt.zcu; |
| 3128 | 3120 | switch (ty.scalarType(mod).zigTypeTag(mod)) { |
| 3129 | 3121 | .Bool => { |
| ... | ... | @@ -3149,7 +3141,7 @@ const DeclGen = struct { |
| 3149 | 3141 | |
| 3150 | 3142 | /// Convert representation from direct (in 'register) to direct (in memory) |
| 3151 | 3143 | /// This converts the argument type from resolveType(ty, .direct) to resolveType(ty, .indirect). |
| 3152 | fn convertToIndirect(self: *DeclGen, ty: Type, operand_id: IdRef) !IdRef { | |
| 3144 | fn convertToIndirect(self: *NavGen, ty: Type, operand_id: IdRef) !IdRef { | |
| 3153 | 3145 | const mod = self.pt.zcu; |
| 3154 | 3146 | switch (ty.scalarType(mod).zigTypeTag(mod)) { |
| 3155 | 3147 | .Bool => { |
| ... | ... | @@ -3160,7 +3152,7 @@ const DeclGen = struct { |
| 3160 | 3152 | } |
| 3161 | 3153 | } |
| 3162 | 3154 | |
| 3163 | fn extractField(self: *DeclGen, result_ty: Type, object: IdRef, field: u32) !IdRef { | |
| 3155 | fn extractField(self: *NavGen, result_ty: Type, object: IdRef, field: u32) !IdRef { | |
| 3164 | 3156 | const result_ty_id = try self.resolveType(result_ty, .indirect); |
| 3165 | 3157 | const result_id = self.spv.allocId(); |
| 3166 | 3158 | const indexes = [_]u32{field}; |
| ... | ... | @@ -3174,7 +3166,7 @@ const DeclGen = struct { |
| 3174 | 3166 | return try self.convertToDirect(result_ty, result_id); |
| 3175 | 3167 | } |
| 3176 | 3168 | |
| 3177 | fn extractVectorComponent(self: *DeclGen, result_ty: Type, vector_id: IdRef, field: u32) !IdRef { | |
| 3169 | fn extractVectorComponent(self: *NavGen, result_ty: Type, vector_id: IdRef, field: u32) !IdRef { | |
| 3178 | 3170 | // Whether this is an OpTypeVector or OpTypeArray, we need to emit the same instruction regardless. |
| 3179 | 3171 | const result_ty_id = try self.resolveType(result_ty, .direct); |
| 3180 | 3172 | const result_id = self.spv.allocId(); |
| ... | ... | @@ -3193,7 +3185,7 @@ const DeclGen = struct { |
| 3193 | 3185 | is_volatile: bool = false, |
| 3194 | 3186 | }; |
| 3195 | 3187 | |
| 3196 | fn load(self: *DeclGen, value_ty: Type, ptr_id: IdRef, options: MemoryOptions) !IdRef { | |
| 3188 | fn load(self: *NavGen, value_ty: Type, ptr_id: IdRef, options: MemoryOptions) !IdRef { | |
| 3197 | 3189 | const indirect_value_ty_id = try self.resolveType(value_ty, .indirect); |
| 3198 | 3190 | const result_id = self.spv.allocId(); |
| 3199 | 3191 | const access = spec.MemoryAccess.Extended{ |
| ... | ... | @@ -3208,7 +3200,7 @@ const DeclGen = struct { |
| 3208 | 3200 | return try self.convertToDirect(value_ty, result_id); |
| 3209 | 3201 | } |
| 3210 | 3202 | |
| 3211 | fn store(self: *DeclGen, value_ty: Type, ptr_id: IdRef, value_id: IdRef, options: MemoryOptions) !void { | |
| 3203 | fn store(self: *NavGen, value_ty: Type, ptr_id: IdRef, value_id: IdRef, options: MemoryOptions) !void { | |
| 3212 | 3204 | const indirect_value_id = try self.convertToIndirect(value_ty, value_id); |
| 3213 | 3205 | const access = spec.MemoryAccess.Extended{ |
| 3214 | 3206 | .Volatile = options.is_volatile, |
| ... | ... | @@ -3220,13 +3212,13 @@ const DeclGen = struct { |
| 3220 | 3212 | }); |
| 3221 | 3213 | } |
| 3222 | 3214 | |
| 3223 | fn genBody(self: *DeclGen, body: []const Air.Inst.Index) Error!void { | |
| 3215 | fn genBody(self: *NavGen, body: []const Air.Inst.Index) Error!void { | |
| 3224 | 3216 | for (body) |inst| { |
| 3225 | 3217 | try self.genInst(inst); |
| 3226 | 3218 | } |
| 3227 | 3219 | } |
| 3228 | 3220 | |
| 3229 | fn genInst(self: *DeclGen, inst: Air.Inst.Index) !void { | |
| 3221 | fn genInst(self: *NavGen, inst: Air.Inst.Index) !void { | |
| 3230 | 3222 | const mod = self.pt.zcu; |
| 3231 | 3223 | const ip = &mod.intern_pool; |
| 3232 | 3224 | if (self.liveness.isUnused(inst) and !self.air.mustLower(inst, ip)) |
| ... | ... | @@ -3397,7 +3389,7 @@ const DeclGen = struct { |
| 3397 | 3389 | try self.inst_results.putNoClobber(self.gpa, inst, result_id); |
| 3398 | 3390 | } |
| 3399 | 3391 | |
| 3400 | fn airBinOpSimple(self: *DeclGen, inst: Air.Inst.Index, op: BinaryOp) !?IdRef { | |
| 3392 | fn airBinOpSimple(self: *NavGen, inst: Air.Inst.Index, op: BinaryOp) !?IdRef { | |
| 3401 | 3393 | const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| 3402 | 3394 | const lhs = try self.temporary(bin_op.lhs); |
| 3403 | 3395 | const rhs = try self.temporary(bin_op.rhs); |
| ... | ... | @@ -3406,7 +3398,7 @@ const DeclGen = struct { |
| 3406 | 3398 | return try result.materialize(self); |
| 3407 | 3399 | } |
| 3408 | 3400 | |
| 3409 | fn airShift(self: *DeclGen, inst: Air.Inst.Index, unsigned: BinaryOp, signed: BinaryOp) !?IdRef { | |
| 3401 | fn airShift(self: *NavGen, inst: Air.Inst.Index, unsigned: BinaryOp, signed: BinaryOp) !?IdRef { | |
| 3410 | 3402 | const mod = self.pt.zcu; |
| 3411 | 3403 | const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| 3412 | 3404 | |
| ... | ... | @@ -3441,7 +3433,7 @@ const DeclGen = struct { |
| 3441 | 3433 | |
| 3442 | 3434 | const MinMax = enum { min, max }; |
| 3443 | 3435 | |
| 3444 | fn airMinMax(self: *DeclGen, inst: Air.Inst.Index, op: MinMax) !?IdRef { | |
| 3436 | fn airMinMax(self: *NavGen, inst: Air.Inst.Index, op: MinMax) !?IdRef { | |
| 3445 | 3437 | const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| 3446 | 3438 | |
| 3447 | 3439 | const lhs = try self.temporary(bin_op.lhs); |
| ... | ... | @@ -3451,7 +3443,7 @@ const DeclGen = struct { |
| 3451 | 3443 | return try result.materialize(self); |
| 3452 | 3444 | } |
| 3453 | 3445 | |
| 3454 | fn minMax(self: *DeclGen, lhs: Temporary, rhs: Temporary, op: MinMax) !Temporary { | |
| 3446 | fn minMax(self: *NavGen, lhs: Temporary, rhs: Temporary, op: MinMax) !Temporary { | |
| 3455 | 3447 | const info = self.arithmeticTypeInfo(lhs.ty); |
| 3456 | 3448 | |
| 3457 | 3449 | const binop: BinaryOp = switch (info.class) { |
| ... | ... | @@ -3484,7 +3476,7 @@ const DeclGen = struct { |
| 3484 | 3476 | /// - Signed integers are also sign extended if they are negative. |
| 3485 | 3477 | /// All other values are returned unmodified (this makes strange integer |
| 3486 | 3478 | /// wrapping easier to use in generic operations). |
| 3487 | fn normalize(self: *DeclGen, value: Temporary, info: ArithmeticTypeInfo) !Temporary { | |
| 3479 | fn normalize(self: *NavGen, value: Temporary, info: ArithmeticTypeInfo) !Temporary { | |
| 3488 | 3480 | const mod = self.pt.zcu; |
| 3489 | 3481 | const ty = value.ty; |
| 3490 | 3482 | switch (info.class) { |
| ... | ... | @@ -3507,7 +3499,7 @@ const DeclGen = struct { |
| 3507 | 3499 | } |
| 3508 | 3500 | } |
| 3509 | 3501 | |
| 3510 | fn airDivFloor(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { | |
| 3502 | fn airDivFloor(self: *NavGen, inst: Air.Inst.Index) !?IdRef { | |
| 3511 | 3503 | const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| 3512 | 3504 | |
| 3513 | 3505 | const lhs = try self.temporary(bin_op.lhs); |
| ... | ... | @@ -3564,7 +3556,7 @@ const DeclGen = struct { |
| 3564 | 3556 | } |
| 3565 | 3557 | } |
| 3566 | 3558 | |
| 3567 | fn airDivTrunc(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { | |
| 3559 | fn airDivTrunc(self: *NavGen, inst: Air.Inst.Index) !?IdRef { | |
| 3568 | 3560 | const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| 3569 | 3561 | |
| 3570 | 3562 | const lhs = try self.temporary(bin_op.lhs); |
| ... | ... | @@ -3592,7 +3584,7 @@ const DeclGen = struct { |
| 3592 | 3584 | } |
| 3593 | 3585 | } |
| 3594 | 3586 | |
| 3595 | fn airUnOpSimple(self: *DeclGen, inst: Air.Inst.Index, op: UnaryOp) !?IdRef { | |
| 3587 | fn airUnOpSimple(self: *NavGen, inst: Air.Inst.Index, op: UnaryOp) !?IdRef { | |
| 3596 | 3588 | const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op; |
| 3597 | 3589 | const operand = try self.temporary(un_op); |
| 3598 | 3590 | const result = try self.buildUnary(op, operand); |
| ... | ... | @@ -3600,7 +3592,7 @@ const DeclGen = struct { |
| 3600 | 3592 | } |
| 3601 | 3593 | |
| 3602 | 3594 | fn airArithOp( |
| 3603 | self: *DeclGen, | |
| 3595 | self: *NavGen, | |
| 3604 | 3596 | inst: Air.Inst.Index, |
| 3605 | 3597 | comptime fop: BinaryOp, |
| 3606 | 3598 | comptime sop: BinaryOp, |
| ... | ... | @@ -3626,7 +3618,7 @@ const DeclGen = struct { |
| 3626 | 3618 | return try result.materialize(self); |
| 3627 | 3619 | } |
| 3628 | 3620 | |
| 3629 | fn airAbs(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { | |
| 3621 | fn airAbs(self: *NavGen, inst: Air.Inst.Index) !?IdRef { | |
| 3630 | 3622 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 3631 | 3623 | const operand = try self.temporary(ty_op.operand); |
| 3632 | 3624 | // Note: operand_ty may be signed, while ty is always unsigned! |
| ... | ... | @@ -3635,7 +3627,7 @@ const DeclGen = struct { |
| 3635 | 3627 | return try result.materialize(self); |
| 3636 | 3628 | } |
| 3637 | 3629 | |
| 3638 | fn abs(self: *DeclGen, result_ty: Type, value: Temporary) !Temporary { | |
| 3630 | fn abs(self: *NavGen, result_ty: Type, value: Temporary) !Temporary { | |
| 3639 | 3631 | const target = self.getTarget(); |
| 3640 | 3632 | const operand_info = self.arithmeticTypeInfo(value.ty); |
| 3641 | 3633 | |
| ... | ... | @@ -3658,7 +3650,7 @@ const DeclGen = struct { |
| 3658 | 3650 | } |
| 3659 | 3651 | |
| 3660 | 3652 | fn airAddSubOverflow( |
| 3661 | self: *DeclGen, | |
| 3653 | self: *NavGen, | |
| 3662 | 3654 | inst: Air.Inst.Index, |
| 3663 | 3655 | comptime add: BinaryOp, |
| 3664 | 3656 | comptime ucmp: CmpPredicate, |
| ... | ... | @@ -3724,7 +3716,7 @@ const DeclGen = struct { |
| 3724 | 3716 | ); |
| 3725 | 3717 | } |
| 3726 | 3718 | |
| 3727 | fn airMulOverflow(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { | |
| 3719 | fn airMulOverflow(self: *NavGen, inst: Air.Inst.Index) !?IdRef { | |
| 3728 | 3720 | const target = self.getTarget(); |
| 3729 | 3721 | const pt = self.pt; |
| 3730 | 3722 | |
| ... | ... | @@ -3904,7 +3896,7 @@ const DeclGen = struct { |
| 3904 | 3896 | ); |
| 3905 | 3897 | } |
| 3906 | 3898 | |
| 3907 | fn airShlOverflow(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { | |
| 3899 | fn airShlOverflow(self: *NavGen, inst: Air.Inst.Index) !?IdRef { | |
| 3908 | 3900 | const mod = self.pt.zcu; |
| 3909 | 3901 | |
| 3910 | 3902 | const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; |
| ... | ... | @@ -3944,7 +3936,7 @@ const DeclGen = struct { |
| 3944 | 3936 | ); |
| 3945 | 3937 | } |
| 3946 | 3938 | |
| 3947 | fn airMulAdd(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { | |
| 3939 | fn airMulAdd(self: *NavGen, inst: Air.Inst.Index) !?IdRef { | |
| 3948 | 3940 | const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; |
| 3949 | 3941 | const extra = self.air.extraData(Air.Bin, pl_op.payload).data; |
| 3950 | 3942 | |
| ... | ... | @@ -3960,7 +3952,7 @@ const DeclGen = struct { |
| 3960 | 3952 | return try result.materialize(self); |
| 3961 | 3953 | } |
| 3962 | 3954 | |
| 3963 | fn airClzCtz(self: *DeclGen, inst: Air.Inst.Index, op: UnaryOp) !?IdRef { | |
| 3955 | fn airClzCtz(self: *NavGen, inst: Air.Inst.Index, op: UnaryOp) !?IdRef { | |
| 3964 | 3956 | if (self.liveness.isUnused(inst)) return null; |
| 3965 | 3957 | |
| 3966 | 3958 | const mod = self.pt.zcu; |
| ... | ... | @@ -3991,7 +3983,7 @@ const DeclGen = struct { |
| 3991 | 3983 | return try result.materialize(self); |
| 3992 | 3984 | } |
| 3993 | 3985 | |
| 3994 | fn airSelect(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { | |
| 3986 | fn airSelect(self: *NavGen, inst: Air.Inst.Index) !?IdRef { | |
| 3995 | 3987 | const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; |
| 3996 | 3988 | const extra = self.air.extraData(Air.Bin, pl_op.payload).data; |
| 3997 | 3989 | const pred = try self.temporary(pl_op.operand); |
| ... | ... | @@ -4002,7 +3994,7 @@ const DeclGen = struct { |
| 4002 | 3994 | return try result.materialize(self); |
| 4003 | 3995 | } |
| 4004 | 3996 | |
| 4005 | fn airSplat(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { | |
| 3997 | fn airSplat(self: *NavGen, inst: Air.Inst.Index) !?IdRef { | |
| 4006 | 3998 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 4007 | 3999 | |
| 4008 | 4000 | const operand_id = try self.resolve(ty_op.operand); |
| ... | ... | @@ -4011,7 +4003,7 @@ const DeclGen = struct { |
| 4011 | 4003 | return try self.constructVectorSplat(result_ty, operand_id); |
| 4012 | 4004 | } |
| 4013 | 4005 | |
| 4014 | fn airReduce(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { | |
| 4006 | fn airReduce(self: *NavGen, inst: Air.Inst.Index) !?IdRef { | |
| 4015 | 4007 | const mod = self.pt.zcu; |
| 4016 | 4008 | const reduce = self.air.instructions.items(.data)[@intFromEnum(inst)].reduce; |
| 4017 | 4009 | const operand = try self.resolve(reduce.operand); |
| ... | ... | @@ -4086,7 +4078,7 @@ const DeclGen = struct { |
| 4086 | 4078 | return result_id; |
| 4087 | 4079 | } |
| 4088 | 4080 | |
| 4089 | fn airShuffle(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { | |
| 4081 | fn airShuffle(self: *NavGen, inst: Air.Inst.Index) !?IdRef { | |
| 4090 | 4082 | const pt = self.pt; |
| 4091 | 4083 | const mod = pt.zcu; |
| 4092 | 4084 | const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; |
| ... | ... | @@ -4163,7 +4155,7 @@ const DeclGen = struct { |
| 4163 | 4155 | return try self.constructVector(result_ty, components); |
| 4164 | 4156 | } |
| 4165 | 4157 | |
| 4166 | fn indicesToIds(self: *DeclGen, indices: []const u32) ![]IdRef { | |
| 4158 | fn indicesToIds(self: *NavGen, indices: []const u32) ![]IdRef { | |
| 4167 | 4159 | const ids = try self.gpa.alloc(IdRef, indices.len); |
| 4168 | 4160 | errdefer self.gpa.free(ids); |
| 4169 | 4161 | for (indices, ids) |index, *id| { |
| ... | ... | @@ -4174,7 +4166,7 @@ const DeclGen = struct { |
| 4174 | 4166 | } |
| 4175 | 4167 | |
| 4176 | 4168 | fn accessChainId( |
| 4177 | self: *DeclGen, | |
| 4169 | self: *NavGen, | |
| 4178 | 4170 | result_ty_id: IdRef, |
| 4179 | 4171 | base: IdRef, |
| 4180 | 4172 | indices: []const IdRef, |
| ... | ... | @@ -4194,7 +4186,7 @@ const DeclGen = struct { |
| 4194 | 4186 | /// same as that of the base pointer, or that of a dereferenced base pointer. AccessChain |
| 4195 | 4187 | /// is the latter and PtrAccessChain is the former. |
| 4196 | 4188 | fn accessChain( |
| 4197 | self: *DeclGen, | |
| 4189 | self: *NavGen, | |
| 4198 | 4190 | result_ty_id: IdRef, |
| 4199 | 4191 | base: IdRef, |
| 4200 | 4192 | indices: []const u32, |
| ... | ... | @@ -4205,7 +4197,7 @@ const DeclGen = struct { |
| 4205 | 4197 | } |
| 4206 | 4198 | |
| 4207 | 4199 | fn ptrAccessChain( |
| 4208 | self: *DeclGen, | |
| 4200 | self: *NavGen, | |
| 4209 | 4201 | result_ty_id: IdRef, |
| 4210 | 4202 | base: IdRef, |
| 4211 | 4203 | element: IdRef, |
| ... | ... | @@ -4225,7 +4217,7 @@ const DeclGen = struct { |
| 4225 | 4217 | return result_id; |
| 4226 | 4218 | } |
| 4227 | 4219 | |
| 4228 | fn ptrAdd(self: *DeclGen, result_ty: Type, ptr_ty: Type, ptr_id: IdRef, offset_id: IdRef) !IdRef { | |
| 4220 | fn ptrAdd(self: *NavGen, result_ty: Type, ptr_ty: Type, ptr_id: IdRef, offset_id: IdRef) !IdRef { | |
| 4229 | 4221 | const mod = self.pt.zcu; |
| 4230 | 4222 | const result_ty_id = try self.resolveType(result_ty, .direct); |
| 4231 | 4223 | |
| ... | ... | @@ -4246,7 +4238,7 @@ const DeclGen = struct { |
| 4246 | 4238 | } |
| 4247 | 4239 | } |
| 4248 | 4240 | |
| 4249 | fn airPtrAdd(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { | |
| 4241 | fn airPtrAdd(self: *NavGen, inst: Air.Inst.Index) !?IdRef { | |
| 4250 | 4242 | const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; |
| 4251 | 4243 | const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data; |
| 4252 | 4244 | const ptr_id = try self.resolve(bin_op.lhs); |
| ... | ... | @@ -4257,7 +4249,7 @@ const DeclGen = struct { |
| 4257 | 4249 | return try self.ptrAdd(result_ty, ptr_ty, ptr_id, offset_id); |
| 4258 | 4250 | } |
| 4259 | 4251 | |
| 4260 | fn airPtrSub(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { | |
| 4252 | fn airPtrSub(self: *NavGen, inst: Air.Inst.Index) !?IdRef { | |
| 4261 | 4253 | const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; |
| 4262 | 4254 | const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data; |
| 4263 | 4255 | const ptr_id = try self.resolve(bin_op.lhs); |
| ... | ... | @@ -4277,7 +4269,7 @@ const DeclGen = struct { |
| 4277 | 4269 | } |
| 4278 | 4270 | |
| 4279 | 4271 | fn cmp( |
| 4280 | self: *DeclGen, | |
| 4272 | self: *NavGen, | |
| 4281 | 4273 | op: std.math.CompareOperator, |
| 4282 | 4274 | lhs: Temporary, |
| 4283 | 4275 | rhs: Temporary, |
| ... | ... | @@ -4443,7 +4435,7 @@ const DeclGen = struct { |
| 4443 | 4435 | } |
| 4444 | 4436 | |
| 4445 | 4437 | fn airCmp( |
| 4446 | self: *DeclGen, | |
| 4438 | self: *NavGen, | |
| 4447 | 4439 | inst: Air.Inst.Index, |
| 4448 | 4440 | comptime op: std.math.CompareOperator, |
| 4449 | 4441 | ) !?IdRef { |
| ... | ... | @@ -4455,7 +4447,7 @@ const DeclGen = struct { |
| 4455 | 4447 | return try result.materialize(self); |
| 4456 | 4448 | } |
| 4457 | 4449 | |
| 4458 | fn airVectorCmp(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { | |
| 4450 | fn airVectorCmp(self: *NavGen, inst: Air.Inst.Index) !?IdRef { | |
| 4459 | 4451 | const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; |
| 4460 | 4452 | const vec_cmp = self.air.extraData(Air.VectorCmp, ty_pl.payload).data; |
| 4461 | 4453 | const lhs = try self.temporary(vec_cmp.lhs); |
| ... | ... | @@ -4468,7 +4460,7 @@ const DeclGen = struct { |
| 4468 | 4460 | |
| 4469 | 4461 | /// Bitcast one type to another. Note: both types, input, output are expected in **direct** representation. |
| 4470 | 4462 | fn bitCast( |
| 4471 | self: *DeclGen, | |
| 4463 | self: *NavGen, | |
| 4472 | 4464 | dst_ty: Type, |
| 4473 | 4465 | src_ty: Type, |
| 4474 | 4466 | src_id: IdRef, |
| ... | ... | @@ -4536,7 +4528,7 @@ const DeclGen = struct { |
| 4536 | 4528 | return result_id; |
| 4537 | 4529 | } |
| 4538 | 4530 | |
| 4539 | fn airBitCast(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { | |
| 4531 | fn airBitCast(self: *NavGen, inst: Air.Inst.Index) !?IdRef { | |
| 4540 | 4532 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 4541 | 4533 | const operand_id = try self.resolve(ty_op.operand); |
| 4542 | 4534 | const operand_ty = self.typeOf(ty_op.operand); |
| ... | ... | @@ -4544,7 +4536,7 @@ const DeclGen = struct { |
| 4544 | 4536 | return try self.bitCast(result_ty, operand_ty, operand_id); |
| 4545 | 4537 | } |
| 4546 | 4538 | |
| 4547 | fn airIntCast(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { | |
| 4539 | fn airIntCast(self: *NavGen, inst: Air.Inst.Index) !?IdRef { | |
| 4548 | 4540 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 4549 | 4541 | const src = try self.temporary(ty_op.operand); |
| 4550 | 4542 | const dst_ty = self.typeOfIndex(inst); |
| ... | ... | @@ -4570,7 +4562,7 @@ const DeclGen = struct { |
| 4570 | 4562 | return try result.materialize(self); |
| 4571 | 4563 | } |
| 4572 | 4564 | |
| 4573 | fn intFromPtr(self: *DeclGen, operand_id: IdRef) !IdRef { | |
| 4565 | fn intFromPtr(self: *NavGen, operand_id: IdRef) !IdRef { | |
| 4574 | 4566 | const result_type_id = try self.resolveType(Type.usize, .direct); |
| 4575 | 4567 | const result_id = self.spv.allocId(); |
| 4576 | 4568 | try self.func.body.emit(self.spv.gpa, .OpConvertPtrToU, .{ |
| ... | ... | @@ -4581,13 +4573,13 @@ const DeclGen = struct { |
| 4581 | 4573 | return result_id; |
| 4582 | 4574 | } |
| 4583 | 4575 | |
| 4584 | fn airIntFromPtr(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { | |
| 4576 | fn airIntFromPtr(self: *NavGen, inst: Air.Inst.Index) !?IdRef { | |
| 4585 | 4577 | const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op; |
| 4586 | 4578 | const operand_id = try self.resolve(un_op); |
| 4587 | 4579 | return try self.intFromPtr(operand_id); |
| 4588 | 4580 | } |
| 4589 | 4581 | |
| 4590 | fn airFloatFromInt(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { | |
| 4582 | fn airFloatFromInt(self: *NavGen, inst: Air.Inst.Index) !?IdRef { | |
| 4591 | 4583 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 4592 | 4584 | const operand_ty = self.typeOf(ty_op.operand); |
| 4593 | 4585 | const operand_id = try self.resolve(ty_op.operand); |
| ... | ... | @@ -4595,7 +4587,7 @@ const DeclGen = struct { |
| 4595 | 4587 | return try self.floatFromInt(result_ty, operand_ty, operand_id); |
| 4596 | 4588 | } |
| 4597 | 4589 | |
| 4598 | fn floatFromInt(self: *DeclGen, result_ty: Type, operand_ty: Type, operand_id: IdRef) !IdRef { | |
| 4590 | fn floatFromInt(self: *NavGen, result_ty: Type, operand_ty: Type, operand_id: IdRef) !IdRef { | |
| 4599 | 4591 | const operand_info = self.arithmeticTypeInfo(operand_ty); |
| 4600 | 4592 | const result_id = self.spv.allocId(); |
| 4601 | 4593 | const result_ty_id = try self.resolveType(result_ty, .direct); |
| ... | ... | @@ -4614,14 +4606,14 @@ const DeclGen = struct { |
| 4614 | 4606 | return result_id; |
| 4615 | 4607 | } |
| 4616 | 4608 | |
| 4617 | fn airIntFromFloat(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { | |
| 4609 | fn airIntFromFloat(self: *NavGen, inst: Air.Inst.Index) !?IdRef { | |
| 4618 | 4610 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 4619 | 4611 | const operand_id = try self.resolve(ty_op.operand); |
| 4620 | 4612 | const result_ty = self.typeOfIndex(inst); |
| 4621 | 4613 | return try self.intFromFloat(result_ty, operand_id); |
| 4622 | 4614 | } |
| 4623 | 4615 | |
| 4624 | fn intFromFloat(self: *DeclGen, result_ty: Type, operand_id: IdRef) !IdRef { | |
| 4616 | fn intFromFloat(self: *NavGen, result_ty: Type, operand_id: IdRef) !IdRef { | |
| 4625 | 4617 | const result_info = self.arithmeticTypeInfo(result_ty); |
| 4626 | 4618 | const result_ty_id = try self.resolveType(result_ty, .direct); |
| 4627 | 4619 | const result_id = self.spv.allocId(); |
| ... | ... | @@ -4640,14 +4632,14 @@ const DeclGen = struct { |
| 4640 | 4632 | return result_id; |
| 4641 | 4633 | } |
| 4642 | 4634 | |
| 4643 | fn airIntFromBool(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { | |
| 4635 | fn airIntFromBool(self: *NavGen, inst: Air.Inst.Index) !?IdRef { | |
| 4644 | 4636 | const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op; |
| 4645 | 4637 | const operand = try self.temporary(un_op); |
| 4646 | 4638 | const result = try self.intFromBool(operand); |
| 4647 | 4639 | return try result.materialize(self); |
| 4648 | 4640 | } |
| 4649 | 4641 | |
| 4650 | fn airFloatCast(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { | |
| 4642 | fn airFloatCast(self: *NavGen, inst: Air.Inst.Index) !?IdRef { | |
| 4651 | 4643 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 4652 | 4644 | const operand_id = try self.resolve(ty_op.operand); |
| 4653 | 4645 | const dest_ty = self.typeOfIndex(inst); |
| ... | ... | @@ -4662,7 +4654,7 @@ const DeclGen = struct { |
| 4662 | 4654 | return result_id; |
| 4663 | 4655 | } |
| 4664 | 4656 | |
| 4665 | fn airNot(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { | |
| 4657 | fn airNot(self: *NavGen, inst: Air.Inst.Index) !?IdRef { | |
| 4666 | 4658 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 4667 | 4659 | const operand = try self.temporary(ty_op.operand); |
| 4668 | 4660 | const result_ty = self.typeOfIndex(inst); |
| ... | ... | @@ -4681,7 +4673,7 @@ const DeclGen = struct { |
| 4681 | 4673 | return try result.materialize(self); |
| 4682 | 4674 | } |
| 4683 | 4675 | |
| 4684 | fn airArrayToSlice(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { | |
| 4676 | fn airArrayToSlice(self: *NavGen, inst: Air.Inst.Index) !?IdRef { | |
| 4685 | 4677 | const pt = self.pt; |
| 4686 | 4678 | const mod = pt.zcu; |
| 4687 | 4679 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| ... | ... | @@ -4709,7 +4701,7 @@ const DeclGen = struct { |
| 4709 | 4701 | ); |
| 4710 | 4702 | } |
| 4711 | 4703 | |
| 4712 | fn airSlice(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { | |
| 4704 | fn airSlice(self: *NavGen, inst: Air.Inst.Index) !?IdRef { | |
| 4713 | 4705 | const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; |
| 4714 | 4706 | const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data; |
| 4715 | 4707 | const ptr_id = try self.resolve(bin_op.lhs); |
| ... | ... | @@ -4726,7 +4718,7 @@ const DeclGen = struct { |
| 4726 | 4718 | ); |
| 4727 | 4719 | } |
| 4728 | 4720 | |
| 4729 | fn airAggregateInit(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { | |
| 4721 | fn airAggregateInit(self: *NavGen, inst: Air.Inst.Index) !?IdRef { | |
| 4730 | 4722 | const pt = self.pt; |
| 4731 | 4723 | const mod = pt.zcu; |
| 4732 | 4724 | const ip = &mod.intern_pool; |
| ... | ... | @@ -4816,7 +4808,7 @@ const DeclGen = struct { |
| 4816 | 4808 | } |
| 4817 | 4809 | } |
| 4818 | 4810 | |
| 4819 | fn sliceOrArrayLen(self: *DeclGen, operand_id: IdRef, ty: Type) !IdRef { | |
| 4811 | fn sliceOrArrayLen(self: *NavGen, operand_id: IdRef, ty: Type) !IdRef { | |
| 4820 | 4812 | const pt = self.pt; |
| 4821 | 4813 | const mod = pt.zcu; |
| 4822 | 4814 | switch (ty.ptrSize(mod)) { |
| ... | ... | @@ -4832,7 +4824,7 @@ const DeclGen = struct { |
| 4832 | 4824 | } |
| 4833 | 4825 | } |
| 4834 | 4826 | |
| 4835 | fn sliceOrArrayPtr(self: *DeclGen, operand_id: IdRef, ty: Type) !IdRef { | |
| 4827 | fn sliceOrArrayPtr(self: *NavGen, operand_id: IdRef, ty: Type) !IdRef { | |
| 4836 | 4828 | const mod = self.pt.zcu; |
| 4837 | 4829 | if (ty.isSlice(mod)) { |
| 4838 | 4830 | const ptr_ty = ty.slicePtrFieldType(mod); |
| ... | ... | @@ -4841,7 +4833,7 @@ const DeclGen = struct { |
| 4841 | 4833 | return operand_id; |
| 4842 | 4834 | } |
| 4843 | 4835 | |
| 4844 | fn airMemcpy(self: *DeclGen, inst: Air.Inst.Index) !void { | |
| 4836 | fn airMemcpy(self: *NavGen, inst: Air.Inst.Index) !void { | |
| 4845 | 4837 | const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| 4846 | 4838 | const dest_slice = try self.resolve(bin_op.lhs); |
| 4847 | 4839 | const src_slice = try self.resolve(bin_op.rhs); |
| ... | ... | @@ -4857,14 +4849,14 @@ const DeclGen = struct { |
| 4857 | 4849 | }); |
| 4858 | 4850 | } |
| 4859 | 4851 | |
| 4860 | fn airSliceField(self: *DeclGen, inst: Air.Inst.Index, field: u32) !?IdRef { | |
| 4852 | fn airSliceField(self: *NavGen, inst: Air.Inst.Index, field: u32) !?IdRef { | |
| 4861 | 4853 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 4862 | 4854 | const field_ty = self.typeOfIndex(inst); |
| 4863 | 4855 | const operand_id = try self.resolve(ty_op.operand); |
| 4864 | 4856 | return try self.extractField(field_ty, operand_id, field); |
| 4865 | 4857 | } |
| 4866 | 4858 | |
| 4867 | fn airSliceElemPtr(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { | |
| 4859 | fn airSliceElemPtr(self: *NavGen, inst: Air.Inst.Index) !?IdRef { | |
| 4868 | 4860 | const mod = self.pt.zcu; |
| 4869 | 4861 | const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; |
| 4870 | 4862 | const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data; |
| ... | ... | @@ -4881,7 +4873,7 @@ const DeclGen = struct { |
| 4881 | 4873 | return try self.ptrAccessChain(ptr_ty_id, slice_ptr, index_id, &.{}); |
| 4882 | 4874 | } |
| 4883 | 4875 | |
| 4884 | fn airSliceElemVal(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { | |
| 4876 | fn airSliceElemVal(self: *NavGen, inst: Air.Inst.Index) !?IdRef { | |
| 4885 | 4877 | const mod = self.pt.zcu; |
| 4886 | 4878 | const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| 4887 | 4879 | const slice_ty = self.typeOf(bin_op.lhs); |
| ... | ... | @@ -4898,7 +4890,7 @@ const DeclGen = struct { |
| 4898 | 4890 | return try self.load(slice_ty.childType(mod), elem_ptr, .{ .is_volatile = slice_ty.isVolatilePtr(mod) }); |
| 4899 | 4891 | } |
| 4900 | 4892 | |
| 4901 | fn ptrElemPtr(self: *DeclGen, ptr_ty: Type, ptr_id: IdRef, index_id: IdRef) !IdRef { | |
| 4893 | fn ptrElemPtr(self: *NavGen, ptr_ty: Type, ptr_id: IdRef, index_id: IdRef) !IdRef { | |
| 4902 | 4894 | const mod = self.pt.zcu; |
| 4903 | 4895 | // Construct new pointer type for the resulting pointer |
| 4904 | 4896 | const elem_ty = ptr_ty.elemType2(mod); // use elemType() so that we get T for *[N]T. |
| ... | ... | @@ -4913,7 +4905,7 @@ const DeclGen = struct { |
| 4913 | 4905 | } |
| 4914 | 4906 | } |
| 4915 | 4907 | |
| 4916 | fn airPtrElemPtr(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { | |
| 4908 | fn airPtrElemPtr(self: *NavGen, inst: Air.Inst.Index) !?IdRef { | |
| 4917 | 4909 | const pt = self.pt; |
| 4918 | 4910 | const mod = pt.zcu; |
| 4919 | 4911 | const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; |
| ... | ... | @@ -4931,7 +4923,7 @@ const DeclGen = struct { |
| 4931 | 4923 | return try self.ptrElemPtr(src_ptr_ty, ptr_id, index_id); |
| 4932 | 4924 | } |
| 4933 | 4925 | |
| 4934 | fn airArrayElemVal(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { | |
| 4926 | fn airArrayElemVal(self: *NavGen, inst: Air.Inst.Index) !?IdRef { | |
| 4935 | 4927 | const mod = self.pt.zcu; |
| 4936 | 4928 | const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| 4937 | 4929 | const array_ty = self.typeOf(bin_op.lhs); |
| ... | ... | @@ -4992,7 +4984,7 @@ const DeclGen = struct { |
| 4992 | 4984 | return try self.convertToDirect(elem_ty, result_id); |
| 4993 | 4985 | } |
| 4994 | 4986 | |
| 4995 | fn airPtrElemVal(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { | |
| 4987 | fn airPtrElemVal(self: *NavGen, inst: Air.Inst.Index) !?IdRef { | |
| 4996 | 4988 | const mod = self.pt.zcu; |
| 4997 | 4989 | const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| 4998 | 4990 | const ptr_ty = self.typeOf(bin_op.lhs); |
| ... | ... | @@ -5003,7 +4995,7 @@ const DeclGen = struct { |
| 5003 | 4995 | return try self.load(elem_ty, elem_ptr_id, .{ .is_volatile = ptr_ty.isVolatilePtr(mod) }); |
| 5004 | 4996 | } |
| 5005 | 4997 | |
| 5006 | fn airVectorStoreElem(self: *DeclGen, inst: Air.Inst.Index) !void { | |
| 4998 | fn airVectorStoreElem(self: *NavGen, inst: Air.Inst.Index) !void { | |
| 5007 | 4999 | const mod = self.pt.zcu; |
| 5008 | 5000 | const data = self.air.instructions.items(.data)[@intFromEnum(inst)].vector_store_elem; |
| 5009 | 5001 | const extra = self.air.extraData(Air.Bin, data.payload).data; |
| ... | ... | @@ -5025,7 +5017,7 @@ const DeclGen = struct { |
| 5025 | 5017 | }); |
| 5026 | 5018 | } |
| 5027 | 5019 | |
| 5028 | fn airSetUnionTag(self: *DeclGen, inst: Air.Inst.Index) !void { | |
| 5020 | fn airSetUnionTag(self: *NavGen, inst: Air.Inst.Index) !void { | |
| 5029 | 5021 | const mod = self.pt.zcu; |
| 5030 | 5022 | const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| 5031 | 5023 | const un_ptr_ty = self.typeOf(bin_op.lhs); |
| ... | ... | @@ -5048,7 +5040,7 @@ const DeclGen = struct { |
| 5048 | 5040 | } |
| 5049 | 5041 | } |
| 5050 | 5042 | |
| 5051 | fn airGetUnionTag(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { | |
| 5043 | fn airGetUnionTag(self: *NavGen, inst: Air.Inst.Index) !?IdRef { | |
| 5052 | 5044 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 5053 | 5045 | const un_ty = self.typeOf(ty_op.operand); |
| 5054 | 5046 | |
| ... | ... | @@ -5064,7 +5056,7 @@ const DeclGen = struct { |
| 5064 | 5056 | } |
| 5065 | 5057 | |
| 5066 | 5058 | fn unionInit( |
| 5067 | self: *DeclGen, | |
| 5059 | self: *NavGen, | |
| 5068 | 5060 | ty: Type, |
| 5069 | 5061 | active_field: u32, |
| 5070 | 5062 | payload: ?IdRef, |
| ... | ... | @@ -5129,7 +5121,7 @@ const DeclGen = struct { |
| 5129 | 5121 | return try self.load(ty, tmp_id, .{}); |
| 5130 | 5122 | } |
| 5131 | 5123 | |
| 5132 | fn airUnionInit(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { | |
| 5124 | fn airUnionInit(self: *NavGen, inst: Air.Inst.Index) !?IdRef { | |
| 5133 | 5125 | const pt = self.pt; |
| 5134 | 5126 | const mod = pt.zcu; |
| 5135 | 5127 | const ip = &mod.intern_pool; |
| ... | ... | @@ -5146,7 +5138,7 @@ const DeclGen = struct { |
| 5146 | 5138 | return try self.unionInit(ty, extra.field_index, payload); |
| 5147 | 5139 | } |
| 5148 | 5140 | |
| 5149 | fn airStructFieldVal(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { | |
| 5141 | fn airStructFieldVal(self: *NavGen, inst: Air.Inst.Index) !?IdRef { | |
| 5150 | 5142 | const pt = self.pt; |
| 5151 | 5143 | const mod = pt.zcu; |
| 5152 | 5144 | const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; |
| ... | ... | @@ -5191,7 +5183,7 @@ const DeclGen = struct { |
| 5191 | 5183 | } |
| 5192 | 5184 | } |
| 5193 | 5185 | |
| 5194 | fn airFieldParentPtr(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { | |
| 5186 | fn airFieldParentPtr(self: *NavGen, inst: Air.Inst.Index) !?IdRef { | |
| 5195 | 5187 | const pt = self.pt; |
| 5196 | 5188 | const mod = pt.zcu; |
| 5197 | 5189 | const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; |
| ... | ... | @@ -5225,7 +5217,7 @@ const DeclGen = struct { |
| 5225 | 5217 | } |
| 5226 | 5218 | |
| 5227 | 5219 | fn structFieldPtr( |
| 5228 | self: *DeclGen, | |
| 5220 | self: *NavGen, | |
| 5229 | 5221 | result_ptr_ty: Type, |
| 5230 | 5222 | object_ptr_ty: Type, |
| 5231 | 5223 | object_ptr: IdRef, |
| ... | ... | @@ -5273,7 +5265,7 @@ const DeclGen = struct { |
| 5273 | 5265 | } |
| 5274 | 5266 | } |
| 5275 | 5267 | |
| 5276 | fn airStructFieldPtrIndex(self: *DeclGen, inst: Air.Inst.Index, field_index: u32) !?IdRef { | |
| 5268 | fn airStructFieldPtrIndex(self: *NavGen, inst: Air.Inst.Index, field_index: u32) !?IdRef { | |
| 5277 | 5269 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 5278 | 5270 | const struct_ptr = try self.resolve(ty_op.operand); |
| 5279 | 5271 | const struct_ptr_ty = self.typeOf(ty_op.operand); |
| ... | ... | @@ -5294,7 +5286,7 @@ const DeclGen = struct { |
| 5294 | 5286 | // which is in the Generic address space. The variable is actually |
| 5295 | 5287 | // placed in the Function address space. |
| 5296 | 5288 | fn alloc( |
| 5297 | self: *DeclGen, | |
| 5289 | self: *NavGen, | |
| 5298 | 5290 | ty: Type, |
| 5299 | 5291 | options: AllocOptions, |
| 5300 | 5292 | ) !IdRef { |
| ... | ... | @@ -5326,7 +5318,7 @@ const DeclGen = struct { |
| 5326 | 5318 | } |
| 5327 | 5319 | } |
| 5328 | 5320 | |
| 5329 | fn airAlloc(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { | |
| 5321 | fn airAlloc(self: *NavGen, inst: Air.Inst.Index) !?IdRef { | |
| 5330 | 5322 | const mod = self.pt.zcu; |
| 5331 | 5323 | const ptr_ty = self.typeOfIndex(inst); |
| 5332 | 5324 | assert(ptr_ty.ptrAddressSpace(mod) == .generic); |
| ... | ... | @@ -5334,7 +5326,7 @@ const DeclGen = struct { |
| 5334 | 5326 | return try self.alloc(child_ty, .{}); |
| 5335 | 5327 | } |
| 5336 | 5328 | |
| 5337 | fn airArg(self: *DeclGen) IdRef { | |
| 5329 | fn airArg(self: *NavGen) IdRef { | |
| 5338 | 5330 | defer self.next_arg_index += 1; |
| 5339 | 5331 | return self.args.items[self.next_arg_index]; |
| 5340 | 5332 | } |
| ... | ... | @@ -5343,7 +5335,7 @@ const DeclGen = struct { |
| 5343 | 5335 | /// block to jump to. This function emits instructions, so it should be emitted |
| 5344 | 5336 | /// inside the merge block of the block. |
| 5345 | 5337 | /// This function should only be called with structured control flow generation. |
| 5346 | fn structuredNextBlock(self: *DeclGen, incoming: []const ControlFlow.Structured.Block.Incoming) !IdRef { | |
| 5338 | fn structuredNextBlock(self: *NavGen, incoming: []const ControlFlow.Structured.Block.Incoming) !IdRef { | |
| 5347 | 5339 | assert(self.control_flow == .structured); |
| 5348 | 5340 | |
| 5349 | 5341 | const result_id = self.spv.allocId(); |
| ... | ... | @@ -5362,7 +5354,7 @@ const DeclGen = struct { |
| 5362 | 5354 | /// Jumps to the block with the target block-id. This function must only be called when |
| 5363 | 5355 | /// terminating a body, there should be no instructions after it. |
| 5364 | 5356 | /// This function should only be called with structured control flow generation. |
| 5365 | fn structuredBreak(self: *DeclGen, target_block: IdRef) !void { | |
| 5357 | fn structuredBreak(self: *NavGen, target_block: IdRef) !void { | |
| 5366 | 5358 | assert(self.control_flow == .structured); |
| 5367 | 5359 | |
| 5368 | 5360 | const sblock = self.control_flow.structured.block_stack.getLast(); |
| ... | ... | @@ -5393,7 +5385,7 @@ const DeclGen = struct { |
| 5393 | 5385 | /// should still be emitted to the block that should follow this structured body. |
| 5394 | 5386 | /// This function should only be called with structured control flow generation. |
| 5395 | 5387 | fn genStructuredBody( |
| 5396 | self: *DeclGen, | |
| 5388 | self: *NavGen, | |
| 5397 | 5389 | /// This parameter defines the method that this structured body is exited with. |
| 5398 | 5390 | block_merge_type: union(enum) { |
| 5399 | 5391 | /// Using selection; early exits from this body are surrounded with |
| ... | ... | @@ -5487,13 +5479,13 @@ const DeclGen = struct { |
| 5487 | 5479 | } |
| 5488 | 5480 | } |
| 5489 | 5481 | |
| 5490 | fn airBlock(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { | |
| 5482 | fn airBlock(self: *NavGen, inst: Air.Inst.Index) !?IdRef { | |
| 5491 | 5483 | const inst_datas = self.air.instructions.items(.data); |
| 5492 | 5484 | const extra = self.air.extraData(Air.Block, inst_datas[@intFromEnum(inst)].ty_pl.payload); |
| 5493 | 5485 | return self.lowerBlock(inst, @ptrCast(self.air.extra[extra.end..][0..extra.data.body_len])); |
| 5494 | 5486 | } |
| 5495 | 5487 | |
| 5496 | fn lowerBlock(self: *DeclGen, inst: Air.Inst.Index, body: []const Air.Inst.Index) !?IdRef { | |
| 5488 | fn lowerBlock(self: *NavGen, inst: Air.Inst.Index, body: []const Air.Inst.Index) !?IdRef { | |
| 5497 | 5489 | // In AIR, a block doesn't really define an entry point like a block, but |
| 5498 | 5490 | // more like a scope that breaks can jump out of and "return" a value from. |
| 5499 | 5491 | // This cannot be directly modelled in SPIR-V, so in a block instruction, |
| ... | ... | @@ -5633,7 +5625,7 @@ const DeclGen = struct { |
| 5633 | 5625 | return null; |
| 5634 | 5626 | } |
| 5635 | 5627 | |
| 5636 | fn airBr(self: *DeclGen, inst: Air.Inst.Index) !void { | |
| 5628 | fn airBr(self: *NavGen, inst: Air.Inst.Index) !void { | |
| 5637 | 5629 | const pt = self.pt; |
| 5638 | 5630 | const br = self.air.instructions.items(.data)[@intFromEnum(inst)].br; |
| 5639 | 5631 | const operand_ty = self.typeOf(br.operand); |
| ... | ... | @@ -5670,7 +5662,7 @@ const DeclGen = struct { |
| 5670 | 5662 | } |
| 5671 | 5663 | } |
| 5672 | 5664 | |
| 5673 | fn airCondBr(self: *DeclGen, inst: Air.Inst.Index) !void { | |
| 5665 | fn airCondBr(self: *NavGen, inst: Air.Inst.Index) !void { | |
| 5674 | 5666 | const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; |
| 5675 | 5667 | const cond_br = self.air.extraData(Air.CondBr, pl_op.payload); |
| 5676 | 5668 | const then_body: []const Air.Inst.Index = @ptrCast(self.air.extra[cond_br.end..][0..cond_br.data.then_body_len]); |
| ... | ... | @@ -5730,7 +5722,7 @@ const DeclGen = struct { |
| 5730 | 5722 | } |
| 5731 | 5723 | } |
| 5732 | 5724 | |
| 5733 | fn airLoop(self: *DeclGen, inst: Air.Inst.Index) !void { | |
| 5725 | fn airLoop(self: *NavGen, inst: Air.Inst.Index) !void { | |
| 5734 | 5726 | const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; |
| 5735 | 5727 | const loop = self.air.extraData(Air.Block, ty_pl.payload); |
| 5736 | 5728 | const body: []const Air.Inst.Index = @ptrCast(self.air.extra[loop.end..][0..loop.data.body_len]); |
| ... | ... | @@ -5777,7 +5769,7 @@ const DeclGen = struct { |
| 5777 | 5769 | } |
| 5778 | 5770 | } |
| 5779 | 5771 | |
| 5780 | fn airLoad(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { | |
| 5772 | fn airLoad(self: *NavGen, inst: Air.Inst.Index) !?IdRef { | |
| 5781 | 5773 | const mod = self.pt.zcu; |
| 5782 | 5774 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 5783 | 5775 | const ptr_ty = self.typeOf(ty_op.operand); |
| ... | ... | @@ -5788,7 +5780,7 @@ const DeclGen = struct { |
| 5788 | 5780 | return try self.load(elem_ty, operand, .{ .is_volatile = ptr_ty.isVolatilePtr(mod) }); |
| 5789 | 5781 | } |
| 5790 | 5782 | |
| 5791 | fn airStore(self: *DeclGen, inst: Air.Inst.Index) !void { | |
| 5783 | fn airStore(self: *NavGen, inst: Air.Inst.Index) !void { | |
| 5792 | 5784 | const mod = self.pt.zcu; |
| 5793 | 5785 | const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| 5794 | 5786 | const ptr_ty = self.typeOf(bin_op.lhs); |
| ... | ... | @@ -5799,14 +5791,13 @@ const DeclGen = struct { |
| 5799 | 5791 | try self.store(elem_ty, ptr, value, .{ .is_volatile = ptr_ty.isVolatilePtr(mod) }); |
| 5800 | 5792 | } |
| 5801 | 5793 | |
| 5802 | fn airRet(self: *DeclGen, inst: Air.Inst.Index) !void { | |
| 5794 | fn airRet(self: *NavGen, inst: Air.Inst.Index) !void { | |
| 5803 | 5795 | const pt = self.pt; |
| 5804 | 5796 | const mod = pt.zcu; |
| 5805 | 5797 | const operand = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op; |
| 5806 | 5798 | const ret_ty = self.typeOf(operand); |
| 5807 | 5799 | if (!ret_ty.hasRuntimeBitsIgnoreComptime(pt)) { |
| 5808 | const decl = mod.declPtr(self.decl_index); | |
| 5809 | const fn_info = mod.typeToFunc(decl.typeOf(mod)).?; | |
| 5800 | const fn_info = mod.typeToFunc(mod.navValue(self.owner_nav).typeOf(mod)).?; | |
| 5810 | 5801 | if (Type.fromInterned(fn_info.return_type).isError(mod)) { |
| 5811 | 5802 | // Functions with an empty error set are emitted with an error code |
| 5812 | 5803 | // return type and return zero so they can be function pointers coerced |
| ... | ... | @@ -5822,7 +5813,7 @@ const DeclGen = struct { |
| 5822 | 5813 | try self.func.body.emit(self.spv.gpa, .OpReturnValue, .{ .value = operand_id }); |
| 5823 | 5814 | } |
| 5824 | 5815 | |
| 5825 | fn airRetLoad(self: *DeclGen, inst: Air.Inst.Index) !void { | |
| 5816 | fn airRetLoad(self: *NavGen, inst: Air.Inst.Index) !void { | |
| 5826 | 5817 | const pt = self.pt; |
| 5827 | 5818 | const mod = pt.zcu; |
| 5828 | 5819 | const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op; |
| ... | ... | @@ -5830,8 +5821,7 @@ const DeclGen = struct { |
| 5830 | 5821 | const ret_ty = ptr_ty.childType(mod); |
| 5831 | 5822 | |
| 5832 | 5823 | if (!ret_ty.hasRuntimeBitsIgnoreComptime(pt)) { |
| 5833 | const decl = mod.declPtr(self.decl_index); | |
| 5834 | const fn_info = mod.typeToFunc(decl.typeOf(mod)).?; | |
| 5824 | const fn_info = mod.typeToFunc(mod.navValue(self.owner_nav).typeOf(mod)).?; | |
| 5835 | 5825 | if (Type.fromInterned(fn_info.return_type).isError(mod)) { |
| 5836 | 5826 | // Functions with an empty error set are emitted with an error code |
| 5837 | 5827 | // return type and return zero so they can be function pointers coerced |
| ... | ... | @@ -5850,7 +5840,7 @@ const DeclGen = struct { |
| 5850 | 5840 | }); |
| 5851 | 5841 | } |
| 5852 | 5842 | |
| 5853 | fn airTry(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { | |
| 5843 | fn airTry(self: *NavGen, inst: Air.Inst.Index) !?IdRef { | |
| 5854 | 5844 | const mod = self.pt.zcu; |
| 5855 | 5845 | const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; |
| 5856 | 5846 | const err_union_id = try self.resolve(pl_op.operand); |
| ... | ... | @@ -5920,7 +5910,7 @@ const DeclGen = struct { |
| 5920 | 5910 | return try self.extractField(payload_ty, err_union_id, eu_layout.payloadFieldIndex()); |
| 5921 | 5911 | } |
| 5922 | 5912 | |
| 5923 | fn airErrUnionErr(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { | |
| 5913 | fn airErrUnionErr(self: *NavGen, inst: Air.Inst.Index) !?IdRef { | |
| 5924 | 5914 | const mod = self.pt.zcu; |
| 5925 | 5915 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 5926 | 5916 | const operand_id = try self.resolve(ty_op.operand); |
| ... | ... | @@ -5943,7 +5933,7 @@ const DeclGen = struct { |
| 5943 | 5933 | return try self.extractField(Type.anyerror, operand_id, eu_layout.errorFieldIndex()); |
| 5944 | 5934 | } |
| 5945 | 5935 | |
| 5946 | fn airErrUnionPayload(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { | |
| 5936 | fn airErrUnionPayload(self: *NavGen, inst: Air.Inst.Index) !?IdRef { | |
| 5947 | 5937 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 5948 | 5938 | const operand_id = try self.resolve(ty_op.operand); |
| 5949 | 5939 | const payload_ty = self.typeOfIndex(inst); |
| ... | ... | @@ -5956,7 +5946,7 @@ const DeclGen = struct { |
| 5956 | 5946 | return try self.extractField(payload_ty, operand_id, eu_layout.payloadFieldIndex()); |
| 5957 | 5947 | } |
| 5958 | 5948 | |
| 5959 | fn airWrapErrUnionErr(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { | |
| 5949 | fn airWrapErrUnionErr(self: *NavGen, inst: Air.Inst.Index) !?IdRef { | |
| 5960 | 5950 | const mod = self.pt.zcu; |
| 5961 | 5951 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 5962 | 5952 | const err_union_ty = self.typeOfIndex(inst); |
| ... | ... | @@ -5981,7 +5971,7 @@ const DeclGen = struct { |
| 5981 | 5971 | return try self.constructStruct(err_union_ty, &types, &members); |
| 5982 | 5972 | } |
| 5983 | 5973 | |
| 5984 | fn airWrapErrUnionPayload(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { | |
| 5974 | fn airWrapErrUnionPayload(self: *NavGen, inst: Air.Inst.Index) !?IdRef { | |
| 5985 | 5975 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 5986 | 5976 | const err_union_ty = self.typeOfIndex(inst); |
| 5987 | 5977 | const operand_id = try self.resolve(ty_op.operand); |
| ... | ... | @@ -6003,7 +5993,7 @@ const DeclGen = struct { |
| 6003 | 5993 | return try self.constructStruct(err_union_ty, &types, &members); |
| 6004 | 5994 | } |
| 6005 | 5995 | |
| 6006 | fn airIsNull(self: *DeclGen, inst: Air.Inst.Index, is_pointer: bool, pred: enum { is_null, is_non_null }) !?IdRef { | |
| 5996 | fn airIsNull(self: *NavGen, inst: Air.Inst.Index, is_pointer: bool, pred: enum { is_null, is_non_null }) !?IdRef { | |
| 6007 | 5997 | const pt = self.pt; |
| 6008 | 5998 | const mod = pt.zcu; |
| 6009 | 5999 | const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op; |
| ... | ... | @@ -6080,7 +6070,7 @@ const DeclGen = struct { |
| 6080 | 6070 | }; |
| 6081 | 6071 | } |
| 6082 | 6072 | |
| 6083 | fn airIsErr(self: *DeclGen, inst: Air.Inst.Index, pred: enum { is_err, is_non_err }) !?IdRef { | |
| 6073 | fn airIsErr(self: *NavGen, inst: Air.Inst.Index, pred: enum { is_err, is_non_err }) !?IdRef { | |
| 6084 | 6074 | const mod = self.pt.zcu; |
| 6085 | 6075 | const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op; |
| 6086 | 6076 | const operand_id = try self.resolve(un_op); |
| ... | ... | @@ -6113,7 +6103,7 @@ const DeclGen = struct { |
| 6113 | 6103 | return result_id; |
| 6114 | 6104 | } |
| 6115 | 6105 | |
| 6116 | fn airUnwrapOptional(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { | |
| 6106 | fn airUnwrapOptional(self: *NavGen, inst: Air.Inst.Index) !?IdRef { | |
| 6117 | 6107 | const pt = self.pt; |
| 6118 | 6108 | const mod = pt.zcu; |
| 6119 | 6109 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| ... | ... | @@ -6130,7 +6120,7 @@ const DeclGen = struct { |
| 6130 | 6120 | return try self.extractField(payload_ty, operand_id, 0); |
| 6131 | 6121 | } |
| 6132 | 6122 | |
| 6133 | fn airUnwrapOptionalPtr(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { | |
| 6123 | fn airUnwrapOptionalPtr(self: *NavGen, inst: Air.Inst.Index) !?IdRef { | |
| 6134 | 6124 | const pt = self.pt; |
| 6135 | 6125 | const mod = pt.zcu; |
| 6136 | 6126 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| ... | ... | @@ -6155,7 +6145,7 @@ const DeclGen = struct { |
| 6155 | 6145 | return try self.accessChain(result_ty_id, operand_id, &.{0}); |
| 6156 | 6146 | } |
| 6157 | 6147 | |
| 6158 | fn airWrapOptional(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { | |
| 6148 | fn airWrapOptional(self: *NavGen, inst: Air.Inst.Index) !?IdRef { | |
| 6159 | 6149 | const pt = self.pt; |
| 6160 | 6150 | const mod = pt.zcu; |
| 6161 | 6151 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| ... | ... | @@ -6178,7 +6168,7 @@ const DeclGen = struct { |
| 6178 | 6168 | return try self.constructStruct(optional_ty, &types, &members); |
| 6179 | 6169 | } |
| 6180 | 6170 | |
| 6181 | fn airSwitchBr(self: *DeclGen, inst: Air.Inst.Index) !void { | |
| 6171 | fn airSwitchBr(self: *NavGen, inst: Air.Inst.Index) !void { | |
| 6182 | 6172 | const pt = self.pt; |
| 6183 | 6173 | const mod = pt.zcu; |
| 6184 | 6174 | const target = self.getTarget(); |
| ... | ... | @@ -6347,16 +6337,15 @@ const DeclGen = struct { |
| 6347 | 6337 | } |
| 6348 | 6338 | } |
| 6349 | 6339 | |
| 6350 | fn airUnreach(self: *DeclGen) !void { | |
| 6340 | fn airUnreach(self: *NavGen) !void { | |
| 6351 | 6341 | try self.func.body.emit(self.spv.gpa, .OpUnreachable, {}); |
| 6352 | 6342 | } |
| 6353 | 6343 | |
| 6354 | fn airDbgStmt(self: *DeclGen, inst: Air.Inst.Index) !void { | |
| 6344 | fn airDbgStmt(self: *NavGen, inst: Air.Inst.Index) !void { | |
| 6355 | 6345 | const pt = self.pt; |
| 6356 | 6346 | const mod = pt.zcu; |
| 6357 | 6347 | const dbg_stmt = self.air.instructions.items(.data)[@intFromEnum(inst)].dbg_stmt; |
| 6358 | const decl = mod.declPtr(self.decl_index); | |
| 6359 | const path = decl.getFileScope(mod).sub_file_path; | |
| 6348 | const path = mod.navFileScope(self.owner_nav).sub_file_path; | |
| 6360 | 6349 | try self.func.body.emit(self.spv.gpa, .OpLine, .{ |
| 6361 | 6350 | .file = try self.spv.resolveString(path), |
| 6362 | 6351 | .line = self.base_line + dbg_stmt.line + 1, |
| ... | ... | @@ -6364,25 +6353,24 @@ const DeclGen = struct { |
| 6364 | 6353 | }); |
| 6365 | 6354 | } |
| 6366 | 6355 | |
| 6367 | fn airDbgInlineBlock(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { | |
| 6356 | fn airDbgInlineBlock(self: *NavGen, inst: Air.Inst.Index) !?IdRef { | |
| 6368 | 6357 | const mod = self.pt.zcu; |
| 6369 | 6358 | const inst_datas = self.air.instructions.items(.data); |
| 6370 | 6359 | const extra = self.air.extraData(Air.DbgInlineBlock, inst_datas[@intFromEnum(inst)].ty_pl.payload); |
| 6371 | const decl = mod.funcOwnerDeclPtr(extra.data.func); | |
| 6372 | 6360 | const old_base_line = self.base_line; |
| 6373 | 6361 | defer self.base_line = old_base_line; |
| 6374 | self.base_line = decl.navSrcLine(mod); | |
| 6362 | self.base_line = mod.navSrcLine(mod.funcInfo(extra.data.func).owner_nav); | |
| 6375 | 6363 | return self.lowerBlock(inst, @ptrCast(self.air.extra[extra.end..][0..extra.data.body_len])); |
| 6376 | 6364 | } |
| 6377 | 6365 | |
| 6378 | fn airDbgVar(self: *DeclGen, inst: Air.Inst.Index) !void { | |
| 6366 | fn airDbgVar(self: *NavGen, inst: Air.Inst.Index) !void { | |
| 6379 | 6367 | const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; |
| 6380 | 6368 | const target_id = try self.resolve(pl_op.operand); |
| 6381 | 6369 | const name = self.air.nullTerminatedString(pl_op.payload); |
| 6382 | 6370 | try self.spv.debugName(target_id, name); |
| 6383 | 6371 | } |
| 6384 | 6372 | |
| 6385 | fn airAssembly(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { | |
| 6373 | fn airAssembly(self: *NavGen, inst: Air.Inst.Index) !?IdRef { | |
| 6386 | 6374 | const mod = self.pt.zcu; |
| 6387 | 6375 | const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; |
| 6388 | 6376 | const extra = self.air.extraData(Air.Asm, ty_pl.payload); |
| ... | ... | @@ -6465,7 +6453,7 @@ const DeclGen = struct { |
| 6465 | 6453 | // TODO: Translate proper error locations. |
| 6466 | 6454 | assert(as.errors.items.len != 0); |
| 6467 | 6455 | assert(self.error_msg == null); |
| 6468 | const src_loc = mod.declPtr(self.decl_index).navSrcLoc(mod); | |
| 6456 | const src_loc = mod.navSrcLoc(self.owner_nav); | |
| 6469 | 6457 | self.error_msg = try Zcu.ErrorMsg.create(mod.gpa, src_loc, "failed to assemble SPIR-V inline assembly", .{}); |
| 6470 | 6458 | const notes = try mod.gpa.alloc(Zcu.ErrorMsg, as.errors.items.len); |
| 6471 | 6459 | |
| ... | ... | @@ -6511,7 +6499,7 @@ const DeclGen = struct { |
| 6511 | 6499 | return null; |
| 6512 | 6500 | } |
| 6513 | 6501 | |
| 6514 | fn airCall(self: *DeclGen, inst: Air.Inst.Index, modifier: std.builtin.CallModifier) !?IdRef { | |
| 6502 | fn airCall(self: *NavGen, inst: Air.Inst.Index, modifier: std.builtin.CallModifier) !?IdRef { | |
| 6515 | 6503 | _ = modifier; |
| 6516 | 6504 | |
| 6517 | 6505 | const pt = self.pt; |
| ... | ... | @@ -6566,7 +6554,7 @@ const DeclGen = struct { |
| 6566 | 6554 | return result_id; |
| 6567 | 6555 | } |
| 6568 | 6556 | |
| 6569 | fn builtin3D(self: *DeclGen, result_ty: Type, builtin: spec.BuiltIn, dimension: u32, out_of_range_value: anytype) !IdRef { | |
| 6557 | fn builtin3D(self: *NavGen, result_ty: Type, builtin: spec.BuiltIn, dimension: u32, out_of_range_value: anytype) !IdRef { | |
| 6570 | 6558 | if (dimension >= 3) { |
| 6571 | 6559 | return try self.constInt(result_ty, out_of_range_value, .direct); |
| 6572 | 6560 | } |
| ... | ... | @@ -6582,7 +6570,7 @@ const DeclGen = struct { |
| 6582 | 6570 | return try self.extractVectorComponent(result_ty, vec, dimension); |
| 6583 | 6571 | } |
| 6584 | 6572 | |
| 6585 | fn airWorkItemId(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { | |
| 6573 | fn airWorkItemId(self: *NavGen, inst: Air.Inst.Index) !?IdRef { | |
| 6586 | 6574 | if (self.liveness.isUnused(inst)) return null; |
| 6587 | 6575 | const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; |
| 6588 | 6576 | const dimension = pl_op.payload; |
| ... | ... | @@ -6593,7 +6581,7 @@ const DeclGen = struct { |
| 6593 | 6581 | return try result.materialize(self); |
| 6594 | 6582 | } |
| 6595 | 6583 | |
| 6596 | fn airWorkGroupSize(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { | |
| 6584 | fn airWorkGroupSize(self: *NavGen, inst: Air.Inst.Index) !?IdRef { | |
| 6597 | 6585 | if (self.liveness.isUnused(inst)) return null; |
| 6598 | 6586 | const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; |
| 6599 | 6587 | const dimension = pl_op.payload; |
| ... | ... | @@ -6604,7 +6592,7 @@ const DeclGen = struct { |
| 6604 | 6592 | return try result.materialize(self); |
| 6605 | 6593 | } |
| 6606 | 6594 | |
| 6607 | fn airWorkGroupId(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { | |
| 6595 | fn airWorkGroupId(self: *NavGen, inst: Air.Inst.Index) !?IdRef { | |
| 6608 | 6596 | if (self.liveness.isUnused(inst)) return null; |
| 6609 | 6597 | const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; |
| 6610 | 6598 | const dimension = pl_op.payload; |
| ... | ... | @@ -6615,12 +6603,12 @@ const DeclGen = struct { |
| 6615 | 6603 | return try result.materialize(self); |
| 6616 | 6604 | } |
| 6617 | 6605 | |
| 6618 | fn typeOf(self: *DeclGen, inst: Air.Inst.Ref) Type { | |
| 6606 | fn typeOf(self: *NavGen, inst: Air.Inst.Ref) Type { | |
| 6619 | 6607 | const mod = self.pt.zcu; |
| 6620 | 6608 | return self.air.typeOf(inst, &mod.intern_pool); |
| 6621 | 6609 | } |
| 6622 | 6610 | |
| 6623 | fn typeOfIndex(self: *DeclGen, inst: Air.Inst.Index) Type { | |
| 6611 | fn typeOfIndex(self: *NavGen, inst: Air.Inst.Index) Type { | |
| 6624 | 6612 | const mod = self.pt.zcu; |
| 6625 | 6613 | return self.air.typeOfIndex(inst, &mod.intern_pool); |
| 6626 | 6614 | } |
src/link.zig+31-57| ... | ... | @@ -216,8 +216,8 @@ pub const File = struct { |
| 216 | 216 | } |
| 217 | 217 | } |
| 218 | 218 | |
| 219 | pub fn cast(base: *File, comptime T: type) ?*T { | |
| 220 | return if (base.tag == T.base_tag) @fieldParentPtr("base", base) else null; | |
| 219 | pub fn cast(base: *File, comptime tag: Tag) if (dev.env.supports(tag.devFeature())) ?*tag.Type() else ?noreturn { | |
| 220 | return if (dev.env.supports(tag.devFeature()) and base.tag == tag) @fieldParentPtr("base", base) else null; | |
| 221 | 221 | } |
| 222 | 222 | |
| 223 | 223 | pub fn makeWritable(base: *File) !void { |
| ... | ... | @@ -231,7 +231,7 @@ pub const File = struct { |
| 231 | 231 | const emit = base.emit; |
| 232 | 232 | if (base.child_pid) |pid| { |
| 233 | 233 | if (builtin.os.tag == .windows) { |
| 234 | base.cast(Coff).?.ptraceAttach(pid) catch |err| { | |
| 234 | base.cast(.coff).?.ptraceAttach(pid) catch |err| { | |
| 235 | 235 | log.warn("attaching failed with error: {s}", .{@errorName(err)}); |
| 236 | 236 | }; |
| 237 | 237 | } else { |
| ... | ... | @@ -249,7 +249,7 @@ pub const File = struct { |
| 249 | 249 | .linux => std.posix.ptrace(std.os.linux.PTRACE.ATTACH, pid, 0, 0) catch |err| { |
| 250 | 250 | log.warn("ptrace failure: {s}", .{@errorName(err)}); |
| 251 | 251 | }, |
| 252 | .macos => base.cast(MachO).?.ptraceAttach(pid) catch |err| { | |
| 252 | .macos => base.cast(.macho).?.ptraceAttach(pid) catch |err| { | |
| 253 | 253 | log.warn("attaching failed with error: {s}", .{@errorName(err)}); |
| 254 | 254 | }, |
| 255 | 255 | .windows => unreachable, |
| ... | ... | @@ -317,10 +317,10 @@ pub const File = struct { |
| 317 | 317 | |
| 318 | 318 | if (base.child_pid) |pid| { |
| 319 | 319 | switch (builtin.os.tag) { |
| 320 | .macos => base.cast(MachO).?.ptraceDetach(pid) catch |err| { | |
| 320 | .macos => base.cast(.macho).?.ptraceDetach(pid) catch |err| { | |
| 321 | 321 | log.warn("detaching failed with error: {s}", .{@errorName(err)}); |
| 322 | 322 | }, |
| 323 | .windows => base.cast(Coff).?.ptraceDetach(pid), | |
| 323 | .windows => base.cast(.coff).?.ptraceDetach(pid), | |
| 324 | 324 | else => return error.HotSwapUnavailableOnHostOperatingSystem, |
| 325 | 325 | } |
| 326 | 326 | } |
| ... | ... | @@ -329,7 +329,7 @@ pub const File = struct { |
| 329 | 329 | } |
| 330 | 330 | } |
| 331 | 331 | |
| 332 | pub const UpdateDeclError = error{ | |
| 332 | pub const UpdateNavError = error{ | |
| 333 | 333 | OutOfMemory, |
| 334 | 334 | Overflow, |
| 335 | 335 | Underflow, |
| ... | ... | @@ -367,27 +367,12 @@ pub const File = struct { |
| 367 | 367 | HotSwapUnavailableOnHostOperatingSystem, |
| 368 | 368 | }; |
| 369 | 369 | |
| 370 | /// Called from within the CodeGen to lower a local variable instantion as an unnamed | |
| 371 | /// constant. Returns the symbol index of the lowered constant in the read-only section | |
| 372 | /// of the final binary. | |
| 373 | pub fn lowerUnnamedConst(base: *File, pt: Zcu.PerThread, val: Value, decl_index: InternPool.DeclIndex) UpdateDeclError!u32 { | |
| 374 | switch (base.tag) { | |
| 375 | .spirv => unreachable, | |
| 376 | .c => unreachable, | |
| 377 | .nvptx => unreachable, | |
| 378 | inline else => |tag| { | |
| 379 | dev.check(tag.devFeature()); | |
| 380 | return @as(*tag.Type(), @fieldParentPtr("base", base)).lowerUnnamedConst(pt, val, decl_index); | |
| 381 | }, | |
| 382 | } | |
| 383 | } | |
| 384 | ||
| 385 | 370 | /// Called from within CodeGen to retrieve the symbol index of a global symbol. |
| 386 | 371 | /// If no symbol exists yet with this name, a new undefined global symbol will |
| 387 | 372 | /// be created. This symbol may get resolved once all relocatables are (re-)linked. |
| 388 | 373 | /// Optionally, it is possible to specify where to expect the symbol defined if it |
| 389 | 374 | /// is an import. |
| 390 | pub fn getGlobalSymbol(base: *File, name: []const u8, lib_name: ?[]const u8) UpdateDeclError!u32 { | |
| 375 | pub fn getGlobalSymbol(base: *File, name: []const u8, lib_name: ?[]const u8) UpdateNavError!u32 { | |
| 391 | 376 | log.debug("getGlobalSymbol '{s}' (expected in '{?s}')", .{ name, lib_name }); |
| 392 | 377 | switch (base.tag) { |
| 393 | 378 | .plan9 => unreachable, |
| ... | ... | @@ -401,14 +386,14 @@ pub const File = struct { |
| 401 | 386 | } |
| 402 | 387 | } |
| 403 | 388 | |
| 404 | /// May be called before or after updateExports for any given Decl. | |
| 405 | pub fn updateDecl(base: *File, pt: Zcu.PerThread, decl_index: InternPool.DeclIndex) UpdateDeclError!void { | |
| 406 | const decl = pt.zcu.declPtr(decl_index); | |
| 407 | assert(decl.has_tv); | |
| 389 | /// May be called before or after updateExports for any given Nav. | |
| 390 | pub fn updateNav(base: *File, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) UpdateNavError!void { | |
| 391 | const nav = pt.zcu.intern_pool.getNav(nav_index); | |
| 392 | assert(nav.status == .resolved); | |
| 408 | 393 | switch (base.tag) { |
| 409 | 394 | inline else => |tag| { |
| 410 | 395 | dev.check(tag.devFeature()); |
| 411 | return @as(*tag.Type(), @fieldParentPtr("base", base)).updateDecl(pt, decl_index); | |
| 396 | return @as(*tag.Type(), @fieldParentPtr("base", base)).updateNav(pt, nav_index); | |
| 412 | 397 | }, |
| 413 | 398 | } |
| 414 | 399 | } |
| ... | ... | @@ -420,7 +405,7 @@ pub const File = struct { |
| 420 | 405 | func_index: InternPool.Index, |
| 421 | 406 | air: Air, |
| 422 | 407 | liveness: Liveness, |
| 423 | ) UpdateDeclError!void { | |
| 408 | ) UpdateNavError!void { | |
| 424 | 409 | switch (base.tag) { |
| 425 | 410 | inline else => |tag| { |
| 426 | 411 | dev.check(tag.devFeature()); |
| ... | ... | @@ -429,14 +414,16 @@ pub const File = struct { |
| 429 | 414 | } |
| 430 | 415 | } |
| 431 | 416 | |
| 432 | pub fn updateDeclLineNumber(base: *File, pt: Zcu.PerThread, decl_index: InternPool.DeclIndex) UpdateDeclError!void { | |
| 433 | const decl = pt.zcu.declPtr(decl_index); | |
| 434 | assert(decl.has_tv); | |
| 417 | pub fn updateNavLineNumber( | |
| 418 | base: *File, | |
| 419 | pt: Zcu.PerThread, | |
| 420 | nav_index: InternPool.Nav.Index, | |
| 421 | ) UpdateNavError!void { | |
| 435 | 422 | switch (base.tag) { |
| 436 | 423 | .spirv, .nvptx => {}, |
| 437 | 424 | inline else => |tag| { |
| 438 | 425 | dev.check(tag.devFeature()); |
| 439 | return @as(*tag.Type(), @fieldParentPtr("base", base)).updateDeclLineNumber(pt, decl_index); | |
| 426 | return @as(*tag.Type(), @fieldParentPtr("base", base)).updateNavineNumber(pt, nav_index); | |
| 440 | 427 | }, |
| 441 | 428 | } |
| 442 | 429 | } |
| ... | ... | @@ -675,52 +662,50 @@ pub const File = struct { |
| 675 | 662 | addend: u32, |
| 676 | 663 | }; |
| 677 | 664 | |
| 678 | /// Get allocated `Decl`'s address in virtual memory. | |
| 665 | /// Get allocated `Nav`'s address in virtual memory. | |
| 679 | 666 | /// The linker is passed information about the containing atom, `parent_atom_index`, and offset within it's |
| 680 | 667 | /// memory buffer, `offset`, so that it can make a note of potential relocation sites, should the |
| 681 | /// `Decl`'s address was not yet resolved, or the containing atom gets moved in virtual memory. | |
| 682 | /// May be called before or after updateFunc/updateDecl therefore it is up to the linker to allocate | |
| 668 | /// `Nav`'s address was not yet resolved, or the containing atom gets moved in virtual memory. | |
| 669 | /// May be called before or after updateFunc/updateNav therefore it is up to the linker to allocate | |
| 683 | 670 | /// the block/atom. |
| 684 | pub fn getDeclVAddr(base: *File, pt: Zcu.PerThread, decl_index: InternPool.DeclIndex, reloc_info: RelocInfo) !u64 { | |
| 671 | pub fn getNavVAddr(base: *File, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index, reloc_info: RelocInfo) !u64 { | |
| 685 | 672 | switch (base.tag) { |
| 686 | 673 | .c => unreachable, |
| 687 | 674 | .spirv => unreachable, |
| 688 | 675 | .nvptx => unreachable, |
| 689 | 676 | inline else => |tag| { |
| 690 | 677 | dev.check(tag.devFeature()); |
| 691 | return @as(*tag.Type(), @fieldParentPtr("base", base)).getDeclVAddr(pt, decl_index, reloc_info); | |
| 678 | return @as(*tag.Type(), @fieldParentPtr("base", base)).getNavVAddr(pt, nav_index, reloc_info); | |
| 692 | 679 | }, |
| 693 | 680 | } |
| 694 | 681 | } |
| 695 | 682 | |
| 696 | pub const LowerResult = @import("codegen.zig").Result; | |
| 697 | ||
| 698 | pub fn lowerAnonDecl( | |
| 683 | pub fn lowerUav( | |
| 699 | 684 | base: *File, |
| 700 | 685 | pt: Zcu.PerThread, |
| 701 | 686 | decl_val: InternPool.Index, |
| 702 | 687 | decl_align: InternPool.Alignment, |
| 703 | 688 | src_loc: Zcu.LazySrcLoc, |
| 704 | ) !LowerResult { | |
| 689 | ) !@import("codegen.zig").GenResult { | |
| 705 | 690 | switch (base.tag) { |
| 706 | 691 | .c => unreachable, |
| 707 | 692 | .spirv => unreachable, |
| 708 | 693 | .nvptx => unreachable, |
| 709 | 694 | inline else => |tag| { |
| 710 | 695 | dev.check(tag.devFeature()); |
| 711 | return @as(*tag.Type(), @fieldParentPtr("base", base)).lowerAnonDecl(pt, decl_val, decl_align, src_loc); | |
| 696 | return @as(*tag.Type(), @fieldParentPtr("base", base)).lowerUav(pt, decl_val, decl_align, src_loc); | |
| 712 | 697 | }, |
| 713 | 698 | } |
| 714 | 699 | } |
| 715 | 700 | |
| 716 | pub fn getAnonDeclVAddr(base: *File, decl_val: InternPool.Index, reloc_info: RelocInfo) !u64 { | |
| 701 | pub fn getUavVAddr(base: *File, decl_val: InternPool.Index, reloc_info: RelocInfo) !u64 { | |
| 717 | 702 | switch (base.tag) { |
| 718 | 703 | .c => unreachable, |
| 719 | 704 | .spirv => unreachable, |
| 720 | 705 | .nvptx => unreachable, |
| 721 | 706 | inline else => |tag| { |
| 722 | 707 | dev.check(tag.devFeature()); |
| 723 | return @as(*tag.Type(), @fieldParentPtr("base", base)).getAnonDeclVAddr(decl_val, reloc_info); | |
| 708 | return @as(*tag.Type(), @fieldParentPtr("base", base)).getUavVAddr(decl_val, reloc_info); | |
| 724 | 709 | }, |
| 725 | 710 | } |
| 726 | 711 | } |
| ... | ... | @@ -964,18 +949,7 @@ pub const File = struct { |
| 964 | 949 | pub const Kind = enum { code, const_data }; |
| 965 | 950 | |
| 966 | 951 | kind: Kind, |
| 967 | ty: Type, | |
| 968 | ||
| 969 | pub fn initDecl(kind: Kind, decl: ?InternPool.DeclIndex, mod: *Zcu) LazySymbol { | |
| 970 | return .{ .kind = kind, .ty = if (decl) |decl_index| | |
| 971 | mod.declPtr(decl_index).val.toType() | |
| 972 | else | |
| 973 | Type.anyerror }; | |
| 974 | } | |
| 975 | ||
| 976 | pub fn getDecl(self: LazySymbol, mod: *Zcu) InternPool.OptionalDeclIndex { | |
| 977 | return InternPool.OptionalDeclIndex.init(self.ty.getOwnerDeclOrNull(mod)); | |
| 978 | } | |
| 952 | ty: InternPool.Index, | |
| 979 | 953 | }; |
| 980 | 954 | |
| 981 | 955 | pub fn effectiveOutputMode( |
src/link/C.zig+112-130| ... | ... | @@ -19,28 +19,27 @@ const Value = @import("../Value.zig"); |
| 19 | 19 | const Air = @import("../Air.zig"); |
| 20 | 20 | const Liveness = @import("../Liveness.zig"); |
| 21 | 21 | |
| 22 | pub const base_tag: link.File.Tag = .c; | |
| 23 | 22 | pub const zig_h = "#include \"zig.h\"\n"; |
| 24 | 23 | |
| 25 | 24 | base: link.File, |
| 26 | 25 | /// This linker backend does not try to incrementally link output C source code. |
| 27 | 26 | /// Instead, it tracks all declarations in this table, and iterates over it |
| 28 | 27 | /// in the flush function, stitching pre-rendered pieces of C code together. |
| 29 | decl_table: std.AutoArrayHashMapUnmanaged(InternPool.DeclIndex, DeclBlock) = .{}, | |
| 28 | navs: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, AvBlock) = .{}, | |
| 30 | 29 | /// All the string bytes of rendered C code, all squished into one array. |
| 31 | 30 | /// While in progress, a separate buffer is used, and then when finished, the |
| 32 | 31 | /// buffer is copied into this one. |
| 33 | 32 | string_bytes: std.ArrayListUnmanaged(u8) = .{}, |
| 34 | 33 | /// Tracks all the anonymous decls that are used by all the decls so they can |
| 35 | 34 | /// be rendered during flush(). |
| 36 | anon_decls: std.AutoArrayHashMapUnmanaged(InternPool.Index, DeclBlock) = .{}, | |
| 37 | /// Sparse set of anon decls that are overaligned. Underaligned anon decls are | |
| 35 | uavs: std.AutoArrayHashMapUnmanaged(InternPool.Index, AvBlock) = .{}, | |
| 36 | /// Sparse set of uavs that are overaligned. Underaligned anon decls are | |
| 38 | 37 | /// lowered the same as ABI-aligned anon decls. The keys here are a subset of |
| 39 | /// the keys of `anon_decls`. | |
| 40 | aligned_anon_decls: std.AutoArrayHashMapUnmanaged(InternPool.Index, Alignment) = .{}, | |
| 38 | /// the keys of `uavs`. | |
| 39 | aligned_uavs: std.AutoArrayHashMapUnmanaged(InternPool.Index, Alignment) = .{}, | |
| 41 | 40 | |
| 42 | exported_decls: std.AutoArrayHashMapUnmanaged(InternPool.DeclIndex, ExportedBlock) = .{}, | |
| 43 | exported_values: std.AutoArrayHashMapUnmanaged(InternPool.Index, ExportedBlock) = .{}, | |
| 41 | exported_navs: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, ExportedBlock) = .{}, | |
| 42 | exported_uavs: std.AutoArrayHashMapUnmanaged(InternPool.Index, ExportedBlock) = .{}, | |
| 44 | 43 | |
| 45 | 44 | /// Optimization, `updateDecl` reuses this buffer rather than creating a new |
| 46 | 45 | /// one with every call. |
| ... | ... | @@ -67,7 +66,7 @@ const String = extern struct { |
| 67 | 66 | }; |
| 68 | 67 | |
| 69 | 68 | /// Per-declaration data. |
| 70 | pub const DeclBlock = struct { | |
| 69 | pub const AvBlock = struct { | |
| 71 | 70 | code: String = String.empty, |
| 72 | 71 | fwd_decl: String = String.empty, |
| 73 | 72 | /// Each `Decl` stores a set of used `CType`s. In `flush()`, we iterate |
| ... | ... | @@ -76,10 +75,10 @@ pub const DeclBlock = struct { |
| 76 | 75 | /// May contain string references to ctype_pool |
| 77 | 76 | lazy_fns: codegen.LazyFnMap = .{}, |
| 78 | 77 | |
| 79 | fn deinit(db: *DeclBlock, gpa: Allocator) void { | |
| 80 | db.lazy_fns.deinit(gpa); | |
| 81 | db.ctype_pool.deinit(gpa); | |
| 82 | db.* = undefined; | |
| 78 | fn deinit(ab: *AvBlock, gpa: Allocator) void { | |
| 79 | ab.lazy_fns.deinit(gpa); | |
| 80 | ab.ctype_pool.deinit(gpa); | |
| 81 | ab.* = undefined; | |
| 83 | 82 | } |
| 84 | 83 | }; |
| 85 | 84 | |
| ... | ... | @@ -158,16 +157,16 @@ pub fn createEmpty( |
| 158 | 157 | pub fn deinit(self: *C) void { |
| 159 | 158 | const gpa = self.base.comp.gpa; |
| 160 | 159 | |
| 161 | for (self.decl_table.values()) |*db| { | |
| 160 | for (self.navs.values()) |*db| { | |
| 162 | 161 | db.deinit(gpa); |
| 163 | 162 | } |
| 164 | self.decl_table.deinit(gpa); | |
| 163 | self.navs.deinit(gpa); | |
| 165 | 164 | |
| 166 | for (self.anon_decls.values()) |*db| { | |
| 165 | for (self.uavs.values()) |*db| { | |
| 167 | 166 | db.deinit(gpa); |
| 168 | 167 | } |
| 169 | self.anon_decls.deinit(gpa); | |
| 170 | self.aligned_anon_decls.deinit(gpa); | |
| 168 | self.uavs.deinit(gpa); | |
| 169 | self.aligned_uavs.deinit(gpa); | |
| 171 | 170 | |
| 172 | 171 | self.string_bytes.deinit(gpa); |
| 173 | 172 | self.fwd_decl_buf.deinit(gpa); |
| ... | ... | @@ -194,9 +193,7 @@ pub fn updateFunc( |
| 194 | 193 | const zcu = pt.zcu; |
| 195 | 194 | const gpa = zcu.gpa; |
| 196 | 195 | const func = zcu.funcInfo(func_index); |
| 197 | const decl_index = func.owner_decl; | |
| 198 | const decl = zcu.declPtr(decl_index); | |
| 199 | const gop = try self.decl_table.getOrPut(gpa, decl_index); | |
| 196 | const gop = try self.navs.getOrPut(gpa, func.owner_nav); | |
| 200 | 197 | if (!gop.found_existing) gop.value_ptr.* = .{}; |
| 201 | 198 | const ctype_pool = &gop.value_ptr.ctype_pool; |
| 202 | 199 | const lazy_fns = &gop.value_ptr.lazy_fns; |
| ... | ... | @@ -208,8 +205,6 @@ pub fn updateFunc( |
| 208 | 205 | fwd_decl.clearRetainingCapacity(); |
| 209 | 206 | code.clearRetainingCapacity(); |
| 210 | 207 | |
| 211 | const file_scope = zcu.namespacePtr(decl.src_namespace).fileScope(zcu); | |
| 212 | ||
| 213 | 208 | var function: codegen.Function = .{ |
| 214 | 209 | .value_map = codegen.CValueMap.init(gpa), |
| 215 | 210 | .air = air, |
| ... | ... | @@ -219,15 +214,15 @@ pub fn updateFunc( |
| 219 | 214 | .dg = .{ |
| 220 | 215 | .gpa = gpa, |
| 221 | 216 | .pt = pt, |
| 222 | .mod = file_scope.mod, | |
| 217 | .mod = zcu.navFileScope(func.owner_nav).mod, | |
| 223 | 218 | .error_msg = null, |
| 224 | .pass = .{ .decl = decl_index }, | |
| 225 | .is_naked_fn = decl.typeOf(zcu).fnCallingConvention(zcu) == .Naked, | |
| 219 | .pass = .{ .nav = func.owner_nav }, | |
| 220 | .is_naked_fn = zcu.navValue(func.owner_nav).typeOf(zcu).fnCallingConvention(zcu) == .Naked, | |
| 226 | 221 | .fwd_decl = fwd_decl.toManaged(gpa), |
| 227 | 222 | .ctype_pool = ctype_pool.*, |
| 228 | 223 | .scratch = .{}, |
| 229 | .anon_decl_deps = self.anon_decls, | |
| 230 | .aligned_anon_decls = self.aligned_anon_decls, | |
| 224 | .uav_deps = self.uavs, | |
| 225 | .aligned_uavs = self.aligned_uavs, | |
| 231 | 226 | }, |
| 232 | 227 | .code = code.toManaged(gpa), |
| 233 | 228 | .indent_writer = undefined, // set later so we can get a pointer to object.code |
| ... | ... | @@ -236,8 +231,8 @@ pub fn updateFunc( |
| 236 | 231 | }; |
| 237 | 232 | function.object.indent_writer = .{ .underlying_writer = function.object.code.writer() }; |
| 238 | 233 | defer { |
| 239 | self.anon_decls = function.object.dg.anon_decl_deps; | |
| 240 | self.aligned_anon_decls = function.object.dg.aligned_anon_decls; | |
| 234 | self.uavs = function.object.dg.uav_deps; | |
| 235 | self.aligned_uavs = function.object.dg.aligned_uavs; | |
| 241 | 236 | fwd_decl.* = function.object.dg.fwd_decl.moveToUnmanaged(); |
| 242 | 237 | ctype_pool.* = function.object.dg.ctype_pool.move(); |
| 243 | 238 | ctype_pool.freeUnusedCapacity(gpa); |
| ... | ... | @@ -248,13 +243,10 @@ pub fn updateFunc( |
| 248 | 243 | function.deinit(); |
| 249 | 244 | } |
| 250 | 245 | |
| 251 | try zcu.failed_analysis.ensureUnusedCapacity(gpa, 1); | |
| 246 | try zcu.failed_codegen.ensureUnusedCapacity(gpa, 1); | |
| 252 | 247 | codegen.genFunc(&function) catch |err| switch (err) { |
| 253 | 248 | error.AnalysisFail => { |
| 254 | zcu.failed_analysis.putAssumeCapacityNoClobber( | |
| 255 | InternPool.AnalUnit.wrap(.{ .decl = decl_index }), | |
| 256 | function.object.dg.error_msg.?, | |
| 257 | ); | |
| 249 | zcu.failed_codegen.putAssumeCapacityNoClobber(func.owner_nav, function.object.dg.error_msg.?); | |
| 258 | 250 | return; |
| 259 | 251 | }, |
| 260 | 252 | else => |e| return e, |
| ... | ... | @@ -263,9 +255,9 @@ pub fn updateFunc( |
| 263 | 255 | gop.value_ptr.code = try self.addString(function.object.code.items); |
| 264 | 256 | } |
| 265 | 257 | |
| 266 | fn updateAnonDecl(self: *C, pt: Zcu.PerThread, i: usize) !void { | |
| 258 | fn updateUav(self: *C, pt: Zcu.PerThread, i: usize) !void { | |
| 267 | 259 | const gpa = self.base.comp.gpa; |
| 268 | const anon_decl = self.anon_decls.keys()[i]; | |
| 260 | const uav = self.uavs.keys()[i]; | |
| 269 | 261 | |
| 270 | 262 | const fwd_decl = &self.fwd_decl_buf; |
| 271 | 263 | const code = &self.code_buf; |
| ... | ... | @@ -278,21 +270,21 @@ fn updateAnonDecl(self: *C, pt: Zcu.PerThread, i: usize) !void { |
| 278 | 270 | .pt = pt, |
| 279 | 271 | .mod = pt.zcu.root_mod, |
| 280 | 272 | .error_msg = null, |
| 281 | .pass = .{ .anon = anon_decl }, | |
| 273 | .pass = .{ .uav = uav }, | |
| 282 | 274 | .is_naked_fn = false, |
| 283 | 275 | .fwd_decl = fwd_decl.toManaged(gpa), |
| 284 | 276 | .ctype_pool = codegen.CType.Pool.empty, |
| 285 | 277 | .scratch = .{}, |
| 286 | .anon_decl_deps = self.anon_decls, | |
| 287 | .aligned_anon_decls = self.aligned_anon_decls, | |
| 278 | .uav_deps = self.uavs, | |
| 279 | .aligned_uavs = self.aligned_uavs, | |
| 288 | 280 | }, |
| 289 | 281 | .code = code.toManaged(gpa), |
| 290 | 282 | .indent_writer = undefined, // set later so we can get a pointer to object.code |
| 291 | 283 | }; |
| 292 | 284 | object.indent_writer = .{ .underlying_writer = object.code.writer() }; |
| 293 | 285 | defer { |
| 294 | self.anon_decls = object.dg.anon_decl_deps; | |
| 295 | self.aligned_anon_decls = object.dg.aligned_anon_decls; | |
| 286 | self.uavs = object.dg.uav_deps; | |
| 287 | self.aligned_uavs = object.dg.aligned_uavs; | |
| 296 | 288 | fwd_decl.* = object.dg.fwd_decl.moveToUnmanaged(); |
| 297 | 289 | object.dg.ctype_pool.deinit(object.dg.gpa); |
| 298 | 290 | object.dg.scratch.deinit(gpa); |
| ... | ... | @@ -300,8 +292,8 @@ fn updateAnonDecl(self: *C, pt: Zcu.PerThread, i: usize) !void { |
| 300 | 292 | } |
| 301 | 293 | try object.dg.ctype_pool.init(gpa); |
| 302 | 294 | |
| 303 | const c_value: codegen.CValue = .{ .constant = Value.fromInterned(anon_decl) }; | |
| 304 | const alignment: Alignment = self.aligned_anon_decls.get(anon_decl) orelse .none; | |
| 295 | const c_value: codegen.CValue = .{ .constant = Value.fromInterned(uav) }; | |
| 296 | const alignment: Alignment = self.aligned_uavs.get(uav) orelse .none; | |
| 305 | 297 | codegen.genDeclValue(&object, c_value.constant, c_value, alignment, .none) catch |err| switch (err) { |
| 306 | 298 | error.AnalysisFail => { |
| 307 | 299 | @panic("TODO: C backend AnalysisFail on anonymous decl"); |
| ... | ... | @@ -312,23 +304,22 @@ fn updateAnonDecl(self: *C, pt: Zcu.PerThread, i: usize) !void { |
| 312 | 304 | }; |
| 313 | 305 | |
| 314 | 306 | object.dg.ctype_pool.freeUnusedCapacity(gpa); |
| 315 | object.dg.anon_decl_deps.values()[i] = .{ | |
| 307 | object.dg.uav_deps.values()[i] = .{ | |
| 316 | 308 | .code = try self.addString(object.code.items), |
| 317 | 309 | .fwd_decl = try self.addString(object.dg.fwd_decl.items), |
| 318 | 310 | .ctype_pool = object.dg.ctype_pool.move(), |
| 319 | 311 | }; |
| 320 | 312 | } |
| 321 | 313 | |
| 322 | pub fn updateDecl(self: *C, pt: Zcu.PerThread, decl_index: InternPool.DeclIndex) !void { | |
| 314 | pub fn updateNav(self: *C, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) !void { | |
| 323 | 315 | const tracy = trace(@src()); |
| 324 | 316 | defer tracy.end(); |
| 325 | 317 | |
| 326 | 318 | const gpa = self.base.comp.gpa; |
| 327 | 319 | |
| 328 | 320 | const zcu = pt.zcu; |
| 329 | const decl = zcu.declPtr(decl_index); | |
| 330 | const gop = try self.decl_table.getOrPut(gpa, decl_index); | |
| 331 | errdefer _ = self.decl_table.pop(); | |
| 321 | const gop = try self.navs.getOrPut(gpa, nav_index); | |
| 322 | errdefer _ = self.navs.pop(); | |
| 332 | 323 | if (!gop.found_existing) gop.value_ptr.* = .{}; |
| 333 | 324 | const ctype_pool = &gop.value_ptr.ctype_pool; |
| 334 | 325 | const fwd_decl = &self.fwd_decl_buf; |
| ... | ... | @@ -338,29 +329,27 @@ pub fn updateDecl(self: *C, pt: Zcu.PerThread, decl_index: InternPool.DeclIndex) |
| 338 | 329 | fwd_decl.clearRetainingCapacity(); |
| 339 | 330 | code.clearRetainingCapacity(); |
| 340 | 331 | |
| 341 | const file_scope = zcu.namespacePtr(decl.src_namespace).fileScope(zcu); | |
| 342 | ||
| 343 | 332 | var object: codegen.Object = .{ |
| 344 | 333 | .dg = .{ |
| 345 | 334 | .gpa = gpa, |
| 346 | 335 | .pt = pt, |
| 347 | .mod = file_scope.mod, | |
| 336 | .mod = zcu.navFileScope(nav_index).mod, | |
| 348 | 337 | .error_msg = null, |
| 349 | .pass = .{ .decl = decl_index }, | |
| 338 | .pass = .{ .nav = nav_index }, | |
| 350 | 339 | .is_naked_fn = false, |
| 351 | 340 | .fwd_decl = fwd_decl.toManaged(gpa), |
| 352 | 341 | .ctype_pool = ctype_pool.*, |
| 353 | 342 | .scratch = .{}, |
| 354 | .anon_decl_deps = self.anon_decls, | |
| 355 | .aligned_anon_decls = self.aligned_anon_decls, | |
| 343 | .uav_deps = self.uavs, | |
| 344 | .aligned_uavs = self.aligned_uavs, | |
| 356 | 345 | }, |
| 357 | 346 | .code = code.toManaged(gpa), |
| 358 | 347 | .indent_writer = undefined, // set later so we can get a pointer to object.code |
| 359 | 348 | }; |
| 360 | 349 | object.indent_writer = .{ .underlying_writer = object.code.writer() }; |
| 361 | 350 | defer { |
| 362 | self.anon_decls = object.dg.anon_decl_deps; | |
| 363 | self.aligned_anon_decls = object.dg.aligned_anon_decls; | |
| 351 | self.uavs = object.dg.uav_deps; | |
| 352 | self.aligned_uavs = object.dg.aligned_uavs; | |
| 364 | 353 | fwd_decl.* = object.dg.fwd_decl.moveToUnmanaged(); |
| 365 | 354 | ctype_pool.* = object.dg.ctype_pool.move(); |
| 366 | 355 | ctype_pool.freeUnusedCapacity(gpa); |
| ... | ... | @@ -368,13 +357,10 @@ pub fn updateDecl(self: *C, pt: Zcu.PerThread, decl_index: InternPool.DeclIndex) |
| 368 | 357 | code.* = object.code.moveToUnmanaged(); |
| 369 | 358 | } |
| 370 | 359 | |
| 371 | try zcu.failed_analysis.ensureUnusedCapacity(gpa, 1); | |
| 360 | try zcu.failed_codegen.ensureUnusedCapacity(gpa, 1); | |
| 372 | 361 | codegen.genDecl(&object) catch |err| switch (err) { |
| 373 | 362 | error.AnalysisFail => { |
| 374 | zcu.failed_analysis.putAssumeCapacityNoClobber( | |
| 375 | InternPool.AnalUnit.wrap(.{ .decl = decl_index }), | |
| 376 | object.dg.error_msg.?, | |
| 377 | ); | |
| 363 | zcu.failed_codegen.putAssumeCapacityNoClobber(nav_index, object.dg.error_msg.?); | |
| 378 | 364 | return; |
| 379 | 365 | }, |
| 380 | 366 | else => |e| return e, |
| ... | ... | @@ -383,12 +369,12 @@ pub fn updateDecl(self: *C, pt: Zcu.PerThread, decl_index: InternPool.DeclIndex) |
| 383 | 369 | gop.value_ptr.fwd_decl = try self.addString(object.dg.fwd_decl.items); |
| 384 | 370 | } |
| 385 | 371 | |
| 386 | pub fn updateDeclLineNumber(self: *C, pt: Zcu.PerThread, decl_index: InternPool.DeclIndex) !void { | |
| 372 | pub fn updateNavLineNumber(self: *C, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) !void { | |
| 387 | 373 | // The C backend does not have the ability to fix line numbers without re-generating |
| 388 | 374 | // the entire Decl. |
| 389 | 375 | _ = self; |
| 390 | 376 | _ = pt; |
| 391 | _ = decl_index; | |
| 377 | _ = nav_index; | |
| 392 | 378 | } |
| 393 | 379 | |
| 394 | 380 | pub fn flush(self: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) !void { |
| ... | ... | @@ -422,12 +408,13 @@ pub fn flushModule(self: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: |
| 422 | 408 | const comp = self.base.comp; |
| 423 | 409 | const gpa = comp.gpa; |
| 424 | 410 | const zcu = self.base.comp.module.?; |
| 411 | const ip = &zcu.intern_pool; | |
| 425 | 412 | const pt: Zcu.PerThread = .{ .zcu = zcu, .tid = tid }; |
| 426 | 413 | |
| 427 | 414 | { |
| 428 | 415 | var i: usize = 0; |
| 429 | while (i < self.anon_decls.count()) : (i += 1) { | |
| 430 | try updateAnonDecl(self, pt, i); | |
| 416 | while (i < self.uavs.count()) : (i += 1) { | |
| 417 | try self.updateUav(pt, i); | |
| 431 | 418 | } |
| 432 | 419 | } |
| 433 | 420 | |
| ... | ... | @@ -484,30 +471,28 @@ pub fn flushModule(self: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: |
| 484 | 471 | } |
| 485 | 472 | } |
| 486 | 473 | |
| 487 | for (self.anon_decls.keys(), self.anon_decls.values()) |value, *decl_block| try self.flushDeclBlock( | |
| 474 | for (self.uavs.keys(), self.uavs.values()) |uav, *av_block| try self.flushAvBlock( | |
| 488 | 475 | pt, |
| 489 | 476 | zcu.root_mod, |
| 490 | 477 | &f, |
| 491 | decl_block, | |
| 492 | self.exported_values.getPtr(value), | |
| 478 | av_block, | |
| 479 | self.exported_uavs.getPtr(uav), | |
| 493 | 480 | export_names, |
| 494 | 481 | .none, |
| 495 | 482 | ); |
| 496 | 483 | |
| 497 | for (self.decl_table.keys(), self.decl_table.values()) |decl_index, *decl_block| { | |
| 498 | const decl = zcu.declPtr(decl_index); | |
| 499 | const extern_name = if (decl.isExtern(zcu)) decl.name.toOptional() else .none; | |
| 500 | const mod = zcu.namespacePtr(decl.src_namespace).fileScope(zcu).mod; | |
| 501 | try self.flushDeclBlock( | |
| 502 | pt, | |
| 503 | mod, | |
| 504 | &f, | |
| 505 | decl_block, | |
| 506 | self.exported_decls.getPtr(decl_index), | |
| 507 | export_names, | |
| 508 | extern_name, | |
| 509 | ); | |
| 510 | } | |
| 484 | for (self.navs.keys(), self.navs.values()) |nav, *av_block| try self.flushAvBlock( | |
| 485 | pt, | |
| 486 | zcu.navFileScope(nav).mod, | |
| 487 | &f, | |
| 488 | av_block, | |
| 489 | self.exported_navs.getPtr(nav), | |
| 490 | export_names, | |
| 491 | if (ip.indexToKey(zcu.navValue(nav).toIntern()) == .@"extern") | |
| 492 | ip.getNav(nav).name.toOptional() | |
| 493 | else | |
| 494 | .none, | |
| 495 | ); | |
| 511 | 496 | } |
| 512 | 497 | |
| 513 | 498 | { |
| ... | ... | @@ -516,12 +501,12 @@ pub fn flushModule(self: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: |
| 516 | 501 | try f.ctype_pool.init(gpa); |
| 517 | 502 | try self.flushCTypes(zcu, &f, .flush, &f.lazy_ctype_pool); |
| 518 | 503 | |
| 519 | for (self.anon_decls.keys(), self.anon_decls.values()) |anon_decl, decl_block| { | |
| 520 | try self.flushCTypes(zcu, &f, .{ .anon = anon_decl }, &decl_block.ctype_pool); | |
| 504 | for (self.uavs.keys(), self.uavs.values()) |uav, av_block| { | |
| 505 | try self.flushCTypes(zcu, &f, .{ .uav = uav }, &av_block.ctype_pool); | |
| 521 | 506 | } |
| 522 | 507 | |
| 523 | for (self.decl_table.keys(), self.decl_table.values()) |decl_index, decl_block| { | |
| 524 | try self.flushCTypes(zcu, &f, .{ .decl = decl_index }, &decl_block.ctype_pool); | |
| 508 | for (self.navs.keys(), self.navs.values()) |nav, av_block| { | |
| 509 | try self.flushCTypes(zcu, &f, .{ .nav = nav }, &av_block.ctype_pool); | |
| 525 | 510 | } |
| 526 | 511 | } |
| 527 | 512 | |
| ... | ... | @@ -539,26 +524,21 @@ pub fn flushModule(self: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: |
| 539 | 524 | f.file_size += lazy_fwd_decl_len; |
| 540 | 525 | |
| 541 | 526 | // Now the code. |
| 542 | try f.all_buffers.ensureUnusedCapacity(gpa, 1 + (self.anon_decls.count() + self.decl_table.count()) * 2); | |
| 527 | try f.all_buffers.ensureUnusedCapacity(gpa, 1 + (self.uavs.count() + self.navs.count()) * 2); | |
| 543 | 528 | f.appendBufAssumeCapacity(self.lazy_code_buf.items); |
| 544 | for (self.anon_decls.keys(), self.anon_decls.values()) |anon_decl, decl_block| f.appendCodeAssumeCapacity( | |
| 545 | if (self.exported_values.contains(anon_decl)) | |
| 546 | .default | |
| 547 | else switch (zcu.intern_pool.indexToKey(anon_decl)) { | |
| 548 | .extern_func => .zig_extern, | |
| 549 | .variable => |variable| if (variable.is_extern) .zig_extern else .static, | |
| 529 | for (self.uavs.keys(), self.uavs.values()) |uav, av_block| f.appendCodeAssumeCapacity( | |
| 530 | if (self.exported_uavs.contains(uav)) .default else switch (ip.indexToKey(uav)) { | |
| 531 | .@"extern" => .zig_extern, | |
| 550 | 532 | else => .static, |
| 551 | 533 | }, |
| 552 | self.getString(decl_block.code), | |
| 534 | self.getString(av_block.code), | |
| 553 | 535 | ); |
| 554 | for (self.decl_table.keys(), self.decl_table.values()) |decl_index, decl_block| f.appendCodeAssumeCapacity( | |
| 555 | if (self.exported_decls.contains(decl_index)) | |
| 556 | .default | |
| 557 | else if (zcu.declPtr(decl_index).isExtern(zcu)) | |
| 558 | .zig_extern | |
| 559 | else | |
| 560 | .static, | |
| 561 | self.getString(decl_block.code), | |
| 536 | for (self.navs.keys(), self.navs.values()) |nav, av_block| f.appendCodeAssumeCapacity( | |
| 537 | if (self.exported_navs.contains(nav)) .default else switch (ip.indexToKey(zcu.navValue(nav).toIntern())) { | |
| 538 | .@"extern" => .zig_extern, | |
| 539 | else => .static, | |
| 540 | }, | |
| 541 | self.getString(av_block.code), | |
| 562 | 542 | ); |
| 563 | 543 | |
| 564 | 544 | const file = self.base.file.?; |
| ... | ... | @@ -689,16 +669,16 @@ fn flushErrDecls(self: *C, pt: Zcu.PerThread, ctype_pool: *codegen.CType.Pool) F |
| 689 | 669 | .fwd_decl = fwd_decl.toManaged(gpa), |
| 690 | 670 | .ctype_pool = ctype_pool.*, |
| 691 | 671 | .scratch = .{}, |
| 692 | .anon_decl_deps = self.anon_decls, | |
| 693 | .aligned_anon_decls = self.aligned_anon_decls, | |
| 672 | .uav_deps = self.uavs, | |
| 673 | .aligned_uavs = self.aligned_uavs, | |
| 694 | 674 | }, |
| 695 | 675 | .code = code.toManaged(gpa), |
| 696 | 676 | .indent_writer = undefined, // set later so we can get a pointer to object.code |
| 697 | 677 | }; |
| 698 | 678 | object.indent_writer = .{ .underlying_writer = object.code.writer() }; |
| 699 | 679 | defer { |
| 700 | self.anon_decls = object.dg.anon_decl_deps; | |
| 701 | self.aligned_anon_decls = object.dg.aligned_anon_decls; | |
| 680 | self.uavs = object.dg.uav_deps; | |
| 681 | self.aligned_uavs = object.dg.aligned_uavs; | |
| 702 | 682 | fwd_decl.* = object.dg.fwd_decl.moveToUnmanaged(); |
| 703 | 683 | ctype_pool.* = object.dg.ctype_pool.move(); |
| 704 | 684 | ctype_pool.freeUnusedCapacity(gpa); |
| ... | ... | @@ -736,8 +716,8 @@ fn flushLazyFn( |
| 736 | 716 | .fwd_decl = fwd_decl.toManaged(gpa), |
| 737 | 717 | .ctype_pool = ctype_pool.*, |
| 738 | 718 | .scratch = .{}, |
| 739 | .anon_decl_deps = .{}, | |
| 740 | .aligned_anon_decls = .{}, | |
| 719 | .uav_deps = .{}, | |
| 720 | .aligned_uavs = .{}, | |
| 741 | 721 | }, |
| 742 | 722 | .code = code.toManaged(gpa), |
| 743 | 723 | .indent_writer = undefined, // set later so we can get a pointer to object.code |
| ... | ... | @@ -746,8 +726,8 @@ fn flushLazyFn( |
| 746 | 726 | defer { |
| 747 | 727 | // If this assert trips just handle the anon_decl_deps the same as |
| 748 | 728 | // `updateFunc()` does. |
| 749 | assert(object.dg.anon_decl_deps.count() == 0); | |
| 750 | assert(object.dg.aligned_anon_decls.count() == 0); | |
| 729 | assert(object.dg.uav_deps.count() == 0); | |
| 730 | assert(object.dg.aligned_uavs.count() == 0); | |
| 751 | 731 | fwd_decl.* = object.dg.fwd_decl.moveToUnmanaged(); |
| 752 | 732 | ctype_pool.* = object.dg.ctype_pool.move(); |
| 753 | 733 | ctype_pool.freeUnusedCapacity(gpa); |
| ... | ... | @@ -781,31 +761,33 @@ fn flushLazyFns( |
| 781 | 761 | } |
| 782 | 762 | } |
| 783 | 763 | |
| 784 | fn flushDeclBlock( | |
| 764 | fn flushAvBlock( | |
| 785 | 765 | self: *C, |
| 786 | 766 | pt: Zcu.PerThread, |
| 787 | 767 | mod: *Module, |
| 788 | 768 | f: *Flush, |
| 789 | decl_block: *const DeclBlock, | |
| 769 | av_block: *const AvBlock, | |
| 790 | 770 | exported_block: ?*const ExportedBlock, |
| 791 | 771 | export_names: std.AutoHashMapUnmanaged(InternPool.NullTerminatedString, void), |
| 792 | 772 | extern_name: InternPool.OptionalNullTerminatedString, |
| 793 | 773 | ) FlushDeclError!void { |
| 794 | 774 | const gpa = self.base.comp.gpa; |
| 795 | try self.flushLazyFns(pt, mod, f, &decl_block.ctype_pool, decl_block.lazy_fns); | |
| 775 | try self.flushLazyFns(pt, mod, f, &av_block.ctype_pool, av_block.lazy_fns); | |
| 796 | 776 | try f.all_buffers.ensureUnusedCapacity(gpa, 1); |
| 797 | 777 | // avoid emitting extern decls that are already exported |
| 798 | 778 | if (extern_name.unwrap()) |name| if (export_names.contains(name)) return; |
| 799 | 779 | f.appendBufAssumeCapacity(self.getString(if (exported_block) |exported| |
| 800 | 780 | exported.fwd_decl |
| 801 | 781 | else |
| 802 | decl_block.fwd_decl)); | |
| 782 | av_block.fwd_decl)); | |
| 803 | 783 | } |
| 804 | 784 | |
| 805 | 785 | pub fn flushEmitH(zcu: *Zcu) !void { |
| 806 | 786 | const tracy = trace(@src()); |
| 807 | 787 | defer tracy.end(); |
| 808 | 788 | |
| 789 | if (true) return; // emit-h is regressed | |
| 790 | ||
| 809 | 791 | const emit_h = zcu.emit_h orelse return; |
| 810 | 792 | |
| 811 | 793 | // We collect a list of buffers to write, and write them all at once with pwritev 😎 |
| ... | ... | @@ -854,17 +836,17 @@ pub fn updateExports( |
| 854 | 836 | const zcu = pt.zcu; |
| 855 | 837 | const gpa = zcu.gpa; |
| 856 | 838 | const mod, const pass: codegen.DeclGen.Pass, const decl_block, const exported_block = switch (exported) { |
| 857 | .decl_index => |decl_index| .{ | |
| 858 | zcu.namespacePtr(zcu.declPtr(decl_index).src_namespace).fileScope(zcu).mod, | |
| 859 | .{ .decl = decl_index }, | |
| 860 | self.decl_table.getPtr(decl_index).?, | |
| 861 | (try self.exported_decls.getOrPut(gpa, decl_index)).value_ptr, | |
| 839 | .nav => |nav| .{ | |
| 840 | zcu.navFileScope(nav).mod, | |
| 841 | .{ .nav = nav }, | |
| 842 | self.navs.getPtr(nav).?, | |
| 843 | (try self.exported_navs.getOrPut(gpa, nav)).value_ptr, | |
| 862 | 844 | }, |
| 863 | .value => |value| .{ | |
| 845 | .uav => |uav| .{ | |
| 864 | 846 | zcu.root_mod, |
| 865 | .{ .anon = value }, | |
| 866 | self.anon_decls.getPtr(value).?, | |
| 867 | (try self.exported_values.getOrPut(gpa, value)).value_ptr, | |
| 847 | .{ .uav = uav }, | |
| 848 | self.uavs.getPtr(uav).?, | |
| 849 | (try self.exported_uavs.getOrPut(gpa, uav)).value_ptr, | |
| 868 | 850 | }, |
| 869 | 851 | }; |
| 870 | 852 | const ctype_pool = &decl_block.ctype_pool; |
| ... | ... | @@ -880,12 +862,12 @@ pub fn updateExports( |
| 880 | 862 | .fwd_decl = fwd_decl.toManaged(gpa), |
| 881 | 863 | .ctype_pool = decl_block.ctype_pool, |
| 882 | 864 | .scratch = .{}, |
| 883 | .anon_decl_deps = .{}, | |
| 884 | .aligned_anon_decls = .{}, | |
| 865 | .uav_deps = .{}, | |
| 866 | .aligned_uavs = .{}, | |
| 885 | 867 | }; |
| 886 | 868 | defer { |
| 887 | assert(dg.anon_decl_deps.count() == 0); | |
| 888 | assert(dg.aligned_anon_decls.count() == 0); | |
| 869 | assert(dg.uav_deps.count() == 0); | |
| 870 | assert(dg.aligned_uavs.count() == 0); | |
| 889 | 871 | fwd_decl.* = dg.fwd_decl.moveToUnmanaged(); |
| 890 | 872 | ctype_pool.* = dg.ctype_pool.move(); |
| 891 | 873 | ctype_pool.freeUnusedCapacity(gpa); |
| ... | ... | @@ -901,7 +883,7 @@ pub fn deleteExport( |
| 901 | 883 | _: InternPool.NullTerminatedString, |
| 902 | 884 | ) void { |
| 903 | 885 | switch (exported) { |
| 904 | .decl_index => |decl_index| _ = self.exported_decls.swapRemove(decl_index), | |
| 905 | .value => |value| _ = self.exported_values.swapRemove(value), | |
| 886 | .nav => |nav| _ = self.exported_navs.swapRemove(nav), | |
| 887 | .uav => |uav| _ = self.exported_uavs.swapRemove(uav), | |
| 906 | 888 | } |
| 907 | 889 | } |
src/link/Coff.zig+177-223| ... | ... | @@ -65,8 +65,8 @@ imports_count_dirty: bool = true, |
| 65 | 65 | /// Table of tracked LazySymbols. |
| 66 | 66 | lazy_syms: LazySymbolTable = .{}, |
| 67 | 67 | |
| 68 | /// Table of tracked Decls. | |
| 69 | decls: DeclTable = .{}, | |
| 68 | /// Table of tracked `Nav`s. | |
| 69 | navs: NavTable = .{}, | |
| 70 | 70 | |
| 71 | 71 | /// List of atoms that are either synthetic or map directly to the Zig source program. |
| 72 | 72 | atoms: std.ArrayListUnmanaged(Atom) = .{}, |
| ... | ... | @@ -74,27 +74,7 @@ atoms: std.ArrayListUnmanaged(Atom) = .{}, |
| 74 | 74 | /// Table of atoms indexed by the symbol index. |
| 75 | 75 | atom_by_index_table: std.AutoHashMapUnmanaged(u32, Atom.Index) = .{}, |
| 76 | 76 | |
| 77 | /// Table of unnamed constants associated with a parent `Decl`. | |
| 78 | /// We store them here so that we can free the constants whenever the `Decl` | |
| 79 | /// needs updating or is freed. | |
| 80 | /// | |
| 81 | /// For example, | |
| 82 | /// | |
| 83 | /// ```zig | |
| 84 | /// const Foo = struct{ | |
| 85 | /// a: u8, | |
| 86 | /// }; | |
| 87 | /// | |
| 88 | /// pub fn main() void { | |
| 89 | /// var foo = Foo{ .a = 1 }; | |
| 90 | /// _ = foo; | |
| 91 | /// } | |
| 92 | /// ``` | |
| 93 | /// | |
| 94 | /// value assigned to label `foo` is an unnamed constant belonging/associated | |
| 95 | /// with `Decl` `main`, and lives as long as that `Decl`. | |
| 96 | unnamed_const_atoms: UnnamedConstTable = .{}, | |
| 97 | anon_decls: AnonDeclTable = .{}, | |
| 77 | uavs: UavTable = .{}, | |
| 98 | 78 | |
| 99 | 79 | /// A table of relocations indexed by the owning them `Atom`. |
| 100 | 80 | /// Note that once we refactor `Atom`'s lifetime and ownership rules, |
| ... | ... | @@ -120,11 +100,10 @@ const HotUpdateState = struct { |
| 120 | 100 | loaded_base_address: ?std.os.windows.HMODULE = null, |
| 121 | 101 | }; |
| 122 | 102 | |
| 123 | const DeclTable = std.AutoArrayHashMapUnmanaged(InternPool.DeclIndex, DeclMetadata); | |
| 124 | const AnonDeclTable = std.AutoHashMapUnmanaged(InternPool.Index, DeclMetadata); | |
| 103 | const NavTable = std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, AvMetadata); | |
| 104 | const UavTable = std.AutoHashMapUnmanaged(InternPool.Index, AvMetadata); | |
| 125 | 105 | const RelocTable = std.AutoArrayHashMapUnmanaged(Atom.Index, std.ArrayListUnmanaged(Relocation)); |
| 126 | 106 | const BaseRelocationTable = std.AutoArrayHashMapUnmanaged(Atom.Index, std.ArrayListUnmanaged(u32)); |
| 127 | const UnnamedConstTable = std.AutoArrayHashMapUnmanaged(InternPool.DeclIndex, std.ArrayListUnmanaged(Atom.Index)); | |
| 128 | 107 | |
| 129 | 108 | const default_file_alignment: u16 = 0x200; |
| 130 | 109 | const default_size_of_stack_reserve: u32 = 0x1000000; |
| ... | ... | @@ -155,7 +134,7 @@ const Section = struct { |
| 155 | 134 | free_list: std.ArrayListUnmanaged(Atom.Index) = .{}, |
| 156 | 135 | }; |
| 157 | 136 | |
| 158 | const LazySymbolTable = std.AutoArrayHashMapUnmanaged(InternPool.OptionalDeclIndex, LazySymbolMetadata); | |
| 137 | const LazySymbolTable = std.AutoArrayHashMapUnmanaged(InternPool.Index, LazySymbolMetadata); | |
| 159 | 138 | |
| 160 | 139 | const LazySymbolMetadata = struct { |
| 161 | 140 | const State = enum { unused, pending_flush, flushed }; |
| ... | ... | @@ -165,17 +144,17 @@ const LazySymbolMetadata = struct { |
| 165 | 144 | rdata_state: State = .unused, |
| 166 | 145 | }; |
| 167 | 146 | |
| 168 | const DeclMetadata = struct { | |
| 147 | const AvMetadata = struct { | |
| 169 | 148 | atom: Atom.Index, |
| 170 | 149 | section: u16, |
| 171 | 150 | /// A list of all exports aliases of this Decl. |
| 172 | 151 | exports: std.ArrayListUnmanaged(u32) = .{}, |
| 173 | 152 | |
| 174 | fn deinit(m: *DeclMetadata, allocator: Allocator) void { | |
| 153 | fn deinit(m: *AvMetadata, allocator: Allocator) void { | |
| 175 | 154 | m.exports.deinit(allocator); |
| 176 | 155 | } |
| 177 | 156 | |
| 178 | fn getExport(m: DeclMetadata, coff_file: *const Coff, name: []const u8) ?u32 { | |
| 157 | fn getExport(m: AvMetadata, coff_file: *const Coff, name: []const u8) ?u32 { | |
| 179 | 158 | for (m.exports.items) |exp| { |
| 180 | 159 | if (mem.eql(u8, name, coff_file.getSymbolName(.{ |
| 181 | 160 | .sym_index = exp, |
| ... | ... | @@ -185,7 +164,7 @@ const DeclMetadata = struct { |
| 185 | 164 | return null; |
| 186 | 165 | } |
| 187 | 166 | |
| 188 | fn getExportPtr(m: *DeclMetadata, coff_file: *Coff, name: []const u8) ?*u32 { | |
| 167 | fn getExportPtr(m: *AvMetadata, coff_file: *Coff, name: []const u8) ?*u32 { | |
| 189 | 168 | for (m.exports.items) |*exp| { |
| 190 | 169 | if (mem.eql(u8, name, coff_file.getSymbolName(.{ |
| 191 | 170 | .sym_index = exp.*, |
| ... | ... | @@ -486,24 +465,19 @@ pub fn deinit(self: *Coff) void { |
| 486 | 465 | |
| 487 | 466 | self.lazy_syms.deinit(gpa); |
| 488 | 467 | |
| 489 | for (self.decls.values()) |*metadata| { | |
| 468 | for (self.navs.values()) |*metadata| { | |
| 490 | 469 | metadata.deinit(gpa); |
| 491 | 470 | } |
| 492 | self.decls.deinit(gpa); | |
| 471 | self.navs.deinit(gpa); | |
| 493 | 472 | |
| 494 | 473 | self.atom_by_index_table.deinit(gpa); |
| 495 | 474 | |
| 496 | for (self.unnamed_const_atoms.values()) |*atoms| { | |
| 497 | atoms.deinit(gpa); | |
| 498 | } | |
| 499 | self.unnamed_const_atoms.deinit(gpa); | |
| 500 | ||
| 501 | 475 | { |
| 502 | var it = self.anon_decls.iterator(); | |
| 476 | var it = self.uavs.iterator(); | |
| 503 | 477 | while (it.next()) |entry| { |
| 504 | 478 | entry.value_ptr.exports.deinit(gpa); |
| 505 | 479 | } |
| 506 | self.anon_decls.deinit(gpa); | |
| 480 | self.uavs.deinit(gpa); | |
| 507 | 481 | } |
| 508 | 482 | |
| 509 | 483 | for (self.relocs.values()) |*relocs| { |
| ... | ... | @@ -1132,23 +1106,20 @@ pub fn updateFunc(self: *Coff, pt: Zcu.PerThread, func_index: InternPool.Index, |
| 1132 | 1106 | const tracy = trace(@src()); |
| 1133 | 1107 | defer tracy.end(); |
| 1134 | 1108 | |
| 1135 | const mod = pt.zcu; | |
| 1136 | const func = mod.funcInfo(func_index); | |
| 1137 | const decl_index = func.owner_decl; | |
| 1138 | const decl = mod.declPtr(decl_index); | |
| 1109 | const zcu = pt.zcu; | |
| 1110 | const gpa = zcu.gpa; | |
| 1111 | const func = zcu.funcInfo(func_index); | |
| 1139 | 1112 | |
| 1140 | const atom_index = try self.getOrCreateAtomForDecl(decl_index); | |
| 1141 | self.freeUnnamedConsts(decl_index); | |
| 1113 | const atom_index = try self.getOrCreateAtomForNav(func.owner_nav); | |
| 1142 | 1114 | Atom.freeRelocations(self, atom_index); |
| 1143 | 1115 | |
| 1144 | const gpa = self.base.comp.gpa; | |
| 1145 | 1116 | var code_buffer = std.ArrayList(u8).init(gpa); |
| 1146 | 1117 | defer code_buffer.deinit(); |
| 1147 | 1118 | |
| 1148 | 1119 | const res = try codegen.generateFunction( |
| 1149 | 1120 | &self.base, |
| 1150 | 1121 | pt, |
| 1151 | decl.navSrcLoc(mod), | |
| 1122 | zcu.navSrcLoc(func.owner_nav), | |
| 1152 | 1123 | func_index, |
| 1153 | 1124 | air, |
| 1154 | 1125 | liveness, |
| ... | ... | @@ -1158,45 +1129,16 @@ pub fn updateFunc(self: *Coff, pt: Zcu.PerThread, func_index: InternPool.Index, |
| 1158 | 1129 | const code = switch (res) { |
| 1159 | 1130 | .ok => code_buffer.items, |
| 1160 | 1131 | .fail => |em| { |
| 1161 | func.setAnalysisState(&mod.intern_pool, .codegen_failure); | |
| 1162 | try mod.failed_analysis.put(mod.gpa, AnalUnit.wrap(.{ .decl = decl_index }), em); | |
| 1132 | try zcu.failed_codegen.put(zcu.gpa, func.owner_nav, em); | |
| 1163 | 1133 | return; |
| 1164 | 1134 | }, |
| 1165 | 1135 | }; |
| 1166 | 1136 | |
| 1167 | try self.updateDeclCode(pt, decl_index, code, .FUNCTION); | |
| 1137 | try self.updateNavCode(pt, func.owner_nav, code, .FUNCTION); | |
| 1168 | 1138 | |
| 1169 | 1139 | // Exports will be updated by `Zcu.processExports` after the update. |
| 1170 | 1140 | } |
| 1171 | 1141 | |
| 1172 | pub fn lowerUnnamedConst(self: *Coff, pt: Zcu.PerThread, val: Value, decl_index: InternPool.DeclIndex) !u32 { | |
| 1173 | const mod = pt.zcu; | |
| 1174 | const gpa = mod.gpa; | |
| 1175 | const decl = mod.declPtr(decl_index); | |
| 1176 | const gop = try self.unnamed_const_atoms.getOrPut(gpa, decl_index); | |
| 1177 | if (!gop.found_existing) { | |
| 1178 | gop.value_ptr.* = .{}; | |
| 1179 | } | |
| 1180 | const unnamed_consts = gop.value_ptr; | |
| 1181 | const index = unnamed_consts.items.len; | |
| 1182 | const sym_name = try std.fmt.allocPrint(gpa, "__unnamed_{}_{d}", .{ | |
| 1183 | decl.fqn.fmt(&mod.intern_pool), index, | |
| 1184 | }); | |
| 1185 | defer gpa.free(sym_name); | |
| 1186 | const ty = val.typeOf(mod); | |
| 1187 | const atom_index = switch (try self.lowerConst(pt, sym_name, val, ty.abiAlignment(pt), self.rdata_section_index.?, decl.navSrcLoc(mod))) { | |
| 1188 | .ok => |atom_index| atom_index, | |
| 1189 | .fail => |em| { | |
| 1190 | decl.analysis = .codegen_failure; | |
| 1191 | try mod.failed_analysis.put(mod.gpa, AnalUnit.wrap(.{ .decl = decl_index }), em); | |
| 1192 | log.err("{s}", .{em.msg}); | |
| 1193 | return error.CodegenFail; | |
| 1194 | }, | |
| 1195 | }; | |
| 1196 | try unnamed_consts.append(gpa, atom_index); | |
| 1197 | return self.getAtom(atom_index).getSymbolIndex().?; | |
| 1198 | } | |
| 1199 | ||
| 1200 | 1142 | const LowerConstResult = union(enum) { |
| 1201 | 1143 | ok: Atom.Index, |
| 1202 | 1144 | fail: *Module.ErrorMsg, |
| ... | ... | @@ -1246,57 +1188,62 @@ fn lowerConst( |
| 1246 | 1188 | return .{ .ok = atom_index }; |
| 1247 | 1189 | } |
| 1248 | 1190 | |
| 1249 | pub fn updateDecl( | |
| 1191 | pub fn updateNav( | |
| 1250 | 1192 | self: *Coff, |
| 1251 | 1193 | pt: Zcu.PerThread, |
| 1252 | decl_index: InternPool.DeclIndex, | |
| 1253 | ) link.File.UpdateDeclError!void { | |
| 1254 | const mod = pt.zcu; | |
| 1194 | nav_index: InternPool.Nav.Index, | |
| 1195 | ) link.File.UpdateNavError!void { | |
| 1255 | 1196 | if (build_options.skip_non_native and builtin.object_format != .coff) { |
| 1256 | 1197 | @panic("Attempted to compile for object format that was disabled by build configuration"); |
| 1257 | 1198 | } |
| 1258 | if (self.llvm_object) |llvm_object| return llvm_object.updateDecl(pt, decl_index); | |
| 1199 | if (self.llvm_object) |llvm_object| return llvm_object.updateNav(pt, nav_index); | |
| 1259 | 1200 | const tracy = trace(@src()); |
| 1260 | 1201 | defer tracy.end(); |
| 1261 | 1202 | |
| 1262 | const decl = mod.declPtr(decl_index); | |
| 1263 | ||
| 1264 | if (decl.val.getExternFunc(mod)) |_| { | |
| 1265 | return; | |
| 1266 | } | |
| 1267 | ||
| 1268 | const gpa = self.base.comp.gpa; | |
| 1269 | if (decl.isExtern(mod)) { | |
| 1270 | // TODO make this part of getGlobalSymbol | |
| 1271 | const variable = decl.getOwnedVariable(mod).?; | |
| 1272 | const name = decl.name.toSlice(&mod.intern_pool); | |
| 1273 | const lib_name = variable.lib_name.toSlice(&mod.intern_pool); | |
| 1274 | const global_index = try self.getGlobalSymbol(name, lib_name); | |
| 1275 | try self.need_got_table.put(gpa, global_index, {}); | |
| 1276 | return; | |
| 1277 | } | |
| 1203 | const zcu = pt.zcu; | |
| 1204 | const gpa = zcu.gpa; | |
| 1205 | const ip = &zcu.intern_pool; | |
| 1206 | const nav = ip.getNav(nav_index); | |
| 1207 | ||
| 1208 | const init_val = switch (ip.indexToKey(nav.status.resolved.val)) { | |
| 1209 | .variable => |variable| variable.init, | |
| 1210 | .@"extern" => |@"extern"| { | |
| 1211 | if (ip.isFunctionType(nav.typeOf(ip))) return; | |
| 1212 | // TODO make this part of getGlobalSymbol | |
| 1213 | const name = nav.name.toSlice(ip); | |
| 1214 | const lib_name = @"extern".lib_name.toSlice(ip); | |
| 1215 | const global_index = try self.getGlobalSymbol(name, lib_name); | |
| 1216 | try self.need_got_table.put(gpa, global_index, {}); | |
| 1217 | return; | |
| 1218 | }, | |
| 1219 | else => nav.status.resolved.val, | |
| 1220 | }; | |
| 1278 | 1221 | |
| 1279 | const atom_index = try self.getOrCreateAtomForDecl(decl_index); | |
| 1222 | const atom_index = try self.getOrCreateAtomForNav(nav_index); | |
| 1280 | 1223 | Atom.freeRelocations(self, atom_index); |
| 1281 | 1224 | const atom = self.getAtom(atom_index); |
| 1282 | 1225 | |
| 1283 | 1226 | var code_buffer = std.ArrayList(u8).init(gpa); |
| 1284 | 1227 | defer code_buffer.deinit(); |
| 1285 | 1228 | |
| 1286 | const decl_val = if (decl.val.getVariable(mod)) |variable| Value.fromInterned(variable.init) else decl.val; | |
| 1287 | const res = try codegen.generateSymbol(&self.base, pt, decl.navSrcLoc(mod), decl_val, &code_buffer, .none, .{ | |
| 1288 | .parent_atom_index = atom.getSymbolIndex().?, | |
| 1289 | }); | |
| 1229 | const res = try codegen.generateSymbol( | |
| 1230 | &self.base, | |
| 1231 | pt, | |
| 1232 | zcu.navSrcLoc(nav_index), | |
| 1233 | Value.fromInterned(init_val), | |
| 1234 | &code_buffer, | |
| 1235 | .none, | |
| 1236 | .{ .parent_atom_index = atom.getSymbolIndex().? }, | |
| 1237 | ); | |
| 1290 | 1238 | const code = switch (res) { |
| 1291 | 1239 | .ok => code_buffer.items, |
| 1292 | 1240 | .fail => |em| { |
| 1293 | decl.analysis = .codegen_failure; | |
| 1294 | try mod.failed_analysis.put(mod.gpa, AnalUnit.wrap(.{ .decl = decl_index }), em); | |
| 1241 | try zcu.failed_codegen.put(gpa, nav_index, em); | |
| 1295 | 1242 | return; |
| 1296 | 1243 | }, |
| 1297 | 1244 | }; |
| 1298 | 1245 | |
| 1299 | try self.updateDeclCode(pt, decl_index, code, .NULL); | |
| 1246 | try self.updateNavCode(pt, nav_index, code, .NULL); | |
| 1300 | 1247 | |
| 1301 | 1248 | // Exports will be updated by `Zcu.processExports` after the update. |
| 1302 | 1249 | } |
| ... | ... | @@ -1317,14 +1264,14 @@ fn updateLazySymbolAtom( |
| 1317 | 1264 | |
| 1318 | 1265 | const name = try std.fmt.allocPrint(gpa, "__lazy_{s}_{}", .{ |
| 1319 | 1266 | @tagName(sym.kind), |
| 1320 | sym.ty.fmt(pt), | |
| 1267 | Type.fromInterned(sym.ty).fmt(pt), | |
| 1321 | 1268 | }); |
| 1322 | 1269 | defer gpa.free(name); |
| 1323 | 1270 | |
| 1324 | 1271 | const atom = self.getAtomPtr(atom_index); |
| 1325 | 1272 | const local_sym_index = atom.getSymbolIndex().?; |
| 1326 | 1273 | |
| 1327 | const src = sym.ty.srcLocOrNull(mod) orelse Module.LazySrcLoc.unneeded; | |
| 1274 | const src = Type.fromInterned(sym.ty).srcLocOrNull(mod) orelse Module.LazySrcLoc.unneeded; | |
| 1328 | 1275 | const res = try codegen.generateLazySymbol( |
| 1329 | 1276 | &self.base, |
| 1330 | 1277 | pt, |
| ... | ... | @@ -1362,52 +1309,55 @@ fn updateLazySymbolAtom( |
| 1362 | 1309 | try self.writeAtom(atom_index, code); |
| 1363 | 1310 | } |
| 1364 | 1311 | |
| 1365 | pub fn getOrCreateAtomForLazySymbol(self: *Coff, pt: Zcu.PerThread, sym: link.File.LazySymbol) !Atom.Index { | |
| 1366 | const gpa = self.base.comp.gpa; | |
| 1367 | const mod = self.base.comp.module.?; | |
| 1368 | const gop = try self.lazy_syms.getOrPut(gpa, sym.getDecl(mod)); | |
| 1312 | pub fn getOrCreateAtomForLazySymbol( | |
| 1313 | self: *Coff, | |
| 1314 | pt: Zcu.PerThread, | |
| 1315 | lazy_sym: link.File.LazySymbol, | |
| 1316 | ) !Atom.Index { | |
| 1317 | const gop = try self.lazy_syms.getOrPut(pt.zcu.gpa, lazy_sym.ty); | |
| 1369 | 1318 | errdefer _ = if (!gop.found_existing) self.lazy_syms.pop(); |
| 1370 | 1319 | if (!gop.found_existing) gop.value_ptr.* = .{}; |
| 1371 | const metadata: struct { atom: *Atom.Index, state: *LazySymbolMetadata.State } = switch (sym.kind) { | |
| 1372 | .code => .{ .atom = &gop.value_ptr.text_atom, .state = &gop.value_ptr.text_state }, | |
| 1373 | .const_data => .{ .atom = &gop.value_ptr.rdata_atom, .state = &gop.value_ptr.rdata_state }, | |
| 1320 | const atom_ptr, const state_ptr = switch (lazy_sym.kind) { | |
| 1321 | .code => .{ &gop.value_ptr.text_atom, &gop.value_ptr.text_state }, | |
| 1322 | .const_data => .{ &gop.value_ptr.rdata_atom, &gop.value_ptr.rdata_state }, | |
| 1374 | 1323 | }; |
| 1375 | switch (metadata.state.*) { | |
| 1376 | .unused => metadata.atom.* = try self.createAtom(), | |
| 1377 | .pending_flush => return metadata.atom.*, | |
| 1324 | switch (state_ptr.*) { | |
| 1325 | .unused => atom_ptr.* = try self.createAtom(), | |
| 1326 | .pending_flush => return atom_ptr.*, | |
| 1378 | 1327 | .flushed => {}, |
| 1379 | 1328 | } |
| 1380 | metadata.state.* = .pending_flush; | |
| 1381 | const atom = metadata.atom.*; | |
| 1329 | state_ptr.* = .pending_flush; | |
| 1330 | const atom = atom_ptr.*; | |
| 1382 | 1331 | // anyerror needs to be deferred until flushModule |
| 1383 | if (sym.getDecl(mod) != .none) try self.updateLazySymbolAtom(pt, sym, atom, switch (sym.kind) { | |
| 1332 | if (lazy_sym.ty != .anyerror_type) try self.updateLazySymbolAtom(pt, lazy_sym, atom, switch (lazy_sym.kind) { | |
| 1384 | 1333 | .code => self.text_section_index.?, |
| 1385 | 1334 | .const_data => self.rdata_section_index.?, |
| 1386 | 1335 | }); |
| 1387 | 1336 | return atom; |
| 1388 | 1337 | } |
| 1389 | 1338 | |
| 1390 | pub fn getOrCreateAtomForDecl(self: *Coff, decl_index: InternPool.DeclIndex) !Atom.Index { | |
| 1339 | pub fn getOrCreateAtomForNav(self: *Coff, nav_index: InternPool.Nav.Index) !Atom.Index { | |
| 1391 | 1340 | const gpa = self.base.comp.gpa; |
| 1392 | const gop = try self.decls.getOrPut(gpa, decl_index); | |
| 1341 | const gop = try self.navs.getOrPut(gpa, nav_index); | |
| 1393 | 1342 | if (!gop.found_existing) { |
| 1394 | 1343 | gop.value_ptr.* = .{ |
| 1395 | 1344 | .atom = try self.createAtom(), |
| 1396 | .section = self.getDeclOutputSection(decl_index), | |
| 1345 | .section = self.getNavOutputSection(nav_index), | |
| 1397 | 1346 | .exports = .{}, |
| 1398 | 1347 | }; |
| 1399 | 1348 | } |
| 1400 | 1349 | return gop.value_ptr.atom; |
| 1401 | 1350 | } |
| 1402 | 1351 | |
| 1403 | fn getDeclOutputSection(self: *Coff, decl_index: InternPool.DeclIndex) u16 { | |
| 1404 | const decl = self.base.comp.module.?.declPtr(decl_index); | |
| 1405 | const mod = self.base.comp.module.?; | |
| 1406 | const ty = decl.typeOf(mod); | |
| 1407 | const zig_ty = ty.zigTypeTag(mod); | |
| 1408 | const val = decl.val; | |
| 1352 | fn getNavOutputSection(self: *Coff, nav_index: InternPool.Nav.Index) u16 { | |
| 1353 | const zcu = self.base.comp.module.?; | |
| 1354 | const ip = &zcu.intern_pool; | |
| 1355 | const nav = ip.getNav(nav_index); | |
| 1356 | const ty = Type.fromInterned(nav.typeOf(ip)); | |
| 1357 | const zig_ty = ty.zigTypeTag(zcu); | |
| 1358 | const val = Value.fromInterned(nav.status.resolved.val); | |
| 1409 | 1359 | const index: u16 = blk: { |
| 1410 | if (val.isUndefDeep(mod)) { | |
| 1360 | if (val.isUndefDeep(zcu)) { | |
| 1411 | 1361 | // TODO in release-fast and release-small, we should put undef in .bss |
| 1412 | 1362 | break :blk self.data_section_index.?; |
| 1413 | 1363 | } |
| ... | ... | @@ -1416,7 +1366,7 @@ fn getDeclOutputSection(self: *Coff, decl_index: InternPool.DeclIndex) u16 { |
| 1416 | 1366 | // TODO: what if this is a function pointer? |
| 1417 | 1367 | .Fn => break :blk self.text_section_index.?, |
| 1418 | 1368 | else => { |
| 1419 | if (val.getVariable(mod)) |_| { | |
| 1369 | if (val.getVariable(zcu)) |_| { | |
| 1420 | 1370 | break :blk self.data_section_index.?; |
| 1421 | 1371 | } |
| 1422 | 1372 | break :blk self.rdata_section_index.?; |
| ... | ... | @@ -1426,31 +1376,41 @@ fn getDeclOutputSection(self: *Coff, decl_index: InternPool.DeclIndex) u16 { |
| 1426 | 1376 | return index; |
| 1427 | 1377 | } |
| 1428 | 1378 | |
| 1429 | fn updateDeclCode(self: *Coff, pt: Zcu.PerThread, decl_index: InternPool.DeclIndex, code: []u8, complex_type: coff.ComplexType) !void { | |
| 1430 | const mod = pt.zcu; | |
| 1431 | const decl = mod.declPtr(decl_index); | |
| 1379 | fn updateNavCode( | |
| 1380 | self: *Coff, | |
| 1381 | pt: Zcu.PerThread, | |
| 1382 | nav_index: InternPool.Nav.Index, | |
| 1383 | code: []u8, | |
| 1384 | complex_type: coff.ComplexType, | |
| 1385 | ) !void { | |
| 1386 | const zcu = pt.zcu; | |
| 1387 | const ip = &zcu.intern_pool; | |
| 1388 | const nav = ip.getNav(nav_index); | |
| 1432 | 1389 | |
| 1433 | log.debug("updateDeclCode {}{*}", .{ decl.fqn.fmt(&mod.intern_pool), decl }); | |
| 1434 | const required_alignment: u32 = @intCast(decl.getAlignment(pt).toByteUnits() orelse 0); | |
| 1390 | log.debug("updateNavCode {} 0x{x}", .{ nav.fqn.fmt(ip), nav_index }); | |
| 1435 | 1391 | |
| 1436 | const decl_metadata = self.decls.get(decl_index).?; | |
| 1437 | const atom_index = decl_metadata.atom; | |
| 1392 | const required_alignment = pt.navAlignment(nav_index).max( | |
| 1393 | target_util.minFunctionAlignment(zcu.navFileScope(nav_index).mod.resolved_target.result), | |
| 1394 | ); | |
| 1395 | ||
| 1396 | const nav_metadata = self.navs.get(nav_index).?; | |
| 1397 | const atom_index = nav_metadata.atom; | |
| 1438 | 1398 | const atom = self.getAtom(atom_index); |
| 1439 | 1399 | const sym_index = atom.getSymbolIndex().?; |
| 1440 | const sect_index = decl_metadata.section; | |
| 1400 | const sect_index = nav_metadata.section; | |
| 1441 | 1401 | const code_len = @as(u32, @intCast(code.len)); |
| 1442 | 1402 | |
| 1443 | 1403 | if (atom.size != 0) { |
| 1444 | 1404 | const sym = atom.getSymbolPtr(self); |
| 1445 | try self.setSymbolName(sym, decl.fqn.toSlice(&mod.intern_pool)); | |
| 1405 | try self.setSymbolName(sym, nav.fqn.toSlice(ip)); | |
| 1446 | 1406 | sym.section_number = @as(coff.SectionNumber, @enumFromInt(sect_index + 1)); |
| 1447 | 1407 | sym.type = .{ .complex_type = complex_type, .base_type = .NULL }; |
| 1448 | 1408 | |
| 1449 | 1409 | const capacity = atom.capacity(self); |
| 1450 | const need_realloc = code.len > capacity or !mem.isAlignedGeneric(u64, sym.value, required_alignment); | |
| 1410 | const need_realloc = code.len > capacity or !required_alignment.check(sym.value); | |
| 1451 | 1411 | if (need_realloc) { |
| 1452 | const vaddr = try self.growAtom(atom_index, code_len, required_alignment); | |
| 1453 | log.debug("growing {} from 0x{x} to 0x{x}", .{ decl.fqn.fmt(&mod.intern_pool), sym.value, vaddr }); | |
| 1412 | const vaddr = try self.growAtom(atom_index, code_len, @intCast(required_alignment.toByteUnits() orelse 0)); | |
| 1413 | log.debug("growing {} from 0x{x} to 0x{x}", .{ nav.fqn.fmt(ip), sym.value, vaddr }); | |
| 1454 | 1414 | log.debug(" (required alignment 0x{x}", .{required_alignment}); |
| 1455 | 1415 | |
| 1456 | 1416 | if (vaddr != sym.value) { |
| ... | ... | @@ -1466,13 +1426,13 @@ fn updateDeclCode(self: *Coff, pt: Zcu.PerThread, decl_index: InternPool.DeclInd |
| 1466 | 1426 | self.getAtomPtr(atom_index).size = code_len; |
| 1467 | 1427 | } else { |
| 1468 | 1428 | const sym = atom.getSymbolPtr(self); |
| 1469 | try self.setSymbolName(sym, decl.fqn.toSlice(&mod.intern_pool)); | |
| 1429 | try self.setSymbolName(sym, nav.fqn.toSlice(ip)); | |
| 1470 | 1430 | sym.section_number = @as(coff.SectionNumber, @enumFromInt(sect_index + 1)); |
| 1471 | 1431 | sym.type = .{ .complex_type = complex_type, .base_type = .NULL }; |
| 1472 | 1432 | |
| 1473 | const vaddr = try self.allocateAtom(atom_index, code_len, required_alignment); | |
| 1433 | const vaddr = try self.allocateAtom(atom_index, code_len, @intCast(required_alignment.toByteUnits() orelse 0)); | |
| 1474 | 1434 | errdefer self.freeAtom(atom_index); |
| 1475 | log.debug("allocated atom for {} at 0x{x}", .{ decl.fqn.fmt(&mod.intern_pool), vaddr }); | |
| 1435 | log.debug("allocated atom for {} at 0x{x}", .{ nav.fqn.fmt(ip), vaddr }); | |
| 1476 | 1436 | self.getAtomPtr(atom_index).size = code_len; |
| 1477 | 1437 | sym.value = vaddr; |
| 1478 | 1438 | |
| ... | ... | @@ -1482,28 +1442,15 @@ fn updateDeclCode(self: *Coff, pt: Zcu.PerThread, decl_index: InternPool.DeclInd |
| 1482 | 1442 | try self.writeAtom(atom_index, code); |
| 1483 | 1443 | } |
| 1484 | 1444 | |
| 1485 | fn freeUnnamedConsts(self: *Coff, decl_index: InternPool.DeclIndex) void { | |
| 1486 | const gpa = self.base.comp.gpa; | |
| 1487 | const unnamed_consts = self.unnamed_const_atoms.getPtr(decl_index) orelse return; | |
| 1488 | for (unnamed_consts.items) |atom_index| { | |
| 1489 | self.freeAtom(atom_index); | |
| 1490 | } | |
| 1491 | unnamed_consts.clearAndFree(gpa); | |
| 1492 | } | |
| 1493 | ||
| 1494 | pub fn freeDecl(self: *Coff, decl_index: InternPool.DeclIndex) void { | |
| 1495 | if (self.llvm_object) |llvm_object| return llvm_object.freeDecl(decl_index); | |
| 1445 | pub fn freeNav(self: *Coff, nav_index: InternPool.NavIndex) void { | |
| 1446 | if (self.llvm_object) |llvm_object| return llvm_object.freeNav(nav_index); | |
| 1496 | 1447 | |
| 1497 | 1448 | const gpa = self.base.comp.gpa; |
| 1498 | const mod = self.base.comp.module.?; | |
| 1499 | const decl = mod.declPtr(decl_index); | |
| 1449 | log.debug("freeDecl 0x{x}", .{nav_index}); | |
| 1500 | 1450 | |
| 1501 | log.debug("freeDecl {*}", .{decl}); | |
| 1502 | ||
| 1503 | if (self.decls.fetchOrderedRemove(decl_index)) |const_kv| { | |
| 1451 | if (self.decls.fetchOrderedRemove(nav_index)) |const_kv| { | |
| 1504 | 1452 | var kv = const_kv; |
| 1505 | 1453 | self.freeAtom(kv.value.atom); |
| 1506 | self.freeUnnamedConsts(decl_index); | |
| 1507 | 1454 | kv.value.exports.deinit(gpa); |
| 1508 | 1455 | } |
| 1509 | 1456 | } |
| ... | ... | @@ -1528,20 +1475,21 @@ pub fn updateExports( |
| 1528 | 1475 | // detect the default subsystem. |
| 1529 | 1476 | for (export_indices) |export_idx| { |
| 1530 | 1477 | const exp = mod.all_exports.items[export_idx]; |
| 1531 | const exported_decl_index = switch (exp.exported) { | |
| 1532 | .decl_index => |i| i, | |
| 1533 | .value => continue, | |
| 1478 | const exported_nav_index = switch (exp.exported) { | |
| 1479 | .nav => |nav| nav, | |
| 1480 | .uav => continue, | |
| 1534 | 1481 | }; |
| 1535 | const exported_decl = mod.declPtr(exported_decl_index); | |
| 1536 | if (exported_decl.getOwnedFunction(mod) == null) continue; | |
| 1537 | const winapi_cc = switch (target.cpu.arch) { | |
| 1538 | .x86 => std.builtin.CallingConvention.Stdcall, | |
| 1539 | else => std.builtin.CallingConvention.C, | |
| 1482 | const exported_nav = ip.getNav(exported_nav_index); | |
| 1483 | const exported_ty = exported_nav.typeOf(ip); | |
| 1484 | if (!ip.isFunctionType(exported_ty)) continue; | |
| 1485 | const winapi_cc: std.builtin.CallingConvention = switch (target.cpu.arch) { | |
| 1486 | .x86 => .Stdcall, | |
| 1487 | else => .C, | |
| 1540 | 1488 | }; |
| 1541 | const decl_cc = exported_decl.typeOf(mod).fnCallingConvention(mod); | |
| 1542 | if (decl_cc == .C and exp.opts.name.eqlSlice("main", ip) and comp.config.link_libc) { | |
| 1489 | const exported_cc = Type.fromInterned(exported_ty).fnCallingConvention(mod); | |
| 1490 | if (exported_cc == .C and exp.opts.name.eqlSlice("main", ip) and comp.config.link_libc) { | |
| 1543 | 1491 | mod.stage1_flags.have_c_main = true; |
| 1544 | } else if (decl_cc == winapi_cc and target.os.tag == .windows) { | |
| 1492 | } else if (exported_cc == winapi_cc and target.os.tag == .windows) { | |
| 1545 | 1493 | if (exp.opts.name.eqlSlice("WinMain", ip)) { |
| 1546 | 1494 | mod.stage1_flags.have_winmain = true; |
| 1547 | 1495 | } else if (exp.opts.name.eqlSlice("wWinMain", ip)) { |
| ... | ... | @@ -1562,15 +1510,15 @@ pub fn updateExports( |
| 1562 | 1510 | const gpa = comp.gpa; |
| 1563 | 1511 | |
| 1564 | 1512 | const metadata = switch (exported) { |
| 1565 | .decl_index => |decl_index| blk: { | |
| 1566 | _ = try self.getOrCreateAtomForDecl(decl_index); | |
| 1567 | break :blk self.decls.getPtr(decl_index).?; | |
| 1513 | .nav => |nav| blk: { | |
| 1514 | _ = try self.getOrCreateAtomForNav(nav); | |
| 1515 | break :blk self.navs.getPtr(nav).?; | |
| 1568 | 1516 | }, |
| 1569 | .value => |value| self.anon_decls.getPtr(value) orelse blk: { | |
| 1517 | .uav => |uav| self.uavs.getPtr(uav) orelse blk: { | |
| 1570 | 1518 | const first_exp = mod.all_exports.items[export_indices[0]]; |
| 1571 | const res = try self.lowerAnonDecl(pt, value, .none, first_exp.src); | |
| 1519 | const res = try self.lowerUav(pt, uav, .none, first_exp.src); | |
| 1572 | 1520 | switch (res) { |
| 1573 | .ok => {}, | |
| 1521 | .mcv => {}, | |
| 1574 | 1522 | .fail => |em| { |
| 1575 | 1523 | // TODO maybe it's enough to return an error here and let Module.processExportsInner |
| 1576 | 1524 | // handle the error? |
| ... | ... | @@ -1579,7 +1527,7 @@ pub fn updateExports( |
| 1579 | 1527 | return; |
| 1580 | 1528 | }, |
| 1581 | 1529 | } |
| 1582 | break :blk self.anon_decls.getPtr(value).?; | |
| 1530 | break :blk self.uavs.getPtr(uav).?; | |
| 1583 | 1531 | }, |
| 1584 | 1532 | }; |
| 1585 | 1533 | const atom_index = metadata.atom; |
| ... | ... | @@ -1654,9 +1602,9 @@ pub fn deleteExport( |
| 1654 | 1602 | ) void { |
| 1655 | 1603 | if (self.llvm_object) |_| return; |
| 1656 | 1604 | const metadata = switch (exported) { |
| 1657 | .decl_index => |decl_index| self.decls.getPtr(decl_index) orelse return, | |
| 1658 | .value => |value| self.anon_decls.getPtr(value) orelse return, | |
| 1659 | }; | |
| 1605 | .nav => |nav| self.navs.getPtr(nav), | |
| 1606 | .uav => |uav| self.uavs.getPtr(uav), | |
| 1607 | } orelse return; | |
| 1660 | 1608 | const mod = self.base.comp.module.?; |
| 1661 | 1609 | const name_slice = name.toSlice(&mod.intern_pool); |
| 1662 | 1610 | const sym_index = metadata.getExportPtr(self, name_slice) orelse return; |
| ... | ... | @@ -1748,7 +1696,7 @@ pub fn flushModule(self: *Coff, arena: Allocator, tid: Zcu.PerThread.Id, prog_no |
| 1748 | 1696 | // anyerror needs to wait for everything to be flushed. |
| 1749 | 1697 | if (metadata.text_state != .unused) self.updateLazySymbolAtom( |
| 1750 | 1698 | pt, |
| 1751 | link.File.LazySymbol.initDecl(.code, null, pt.zcu), | |
| 1699 | .{ .kind = .code, .ty = .anyerror_type }, | |
| 1752 | 1700 | metadata.text_atom, |
| 1753 | 1701 | self.text_section_index.?, |
| 1754 | 1702 | ) catch |err| return switch (err) { |
| ... | ... | @@ -1757,7 +1705,7 @@ pub fn flushModule(self: *Coff, arena: Allocator, tid: Zcu.PerThread.Id, prog_no |
| 1757 | 1705 | }; |
| 1758 | 1706 | if (metadata.rdata_state != .unused) self.updateLazySymbolAtom( |
| 1759 | 1707 | pt, |
| 1760 | link.File.LazySymbol.initDecl(.const_data, null, pt.zcu), | |
| 1708 | .{ .kind = .const_data, .ty = .anyerror_type }, | |
| 1761 | 1709 | metadata.rdata_atom, |
| 1762 | 1710 | self.rdata_section_index.?, |
| 1763 | 1711 | ) catch |err| return switch (err) { |
| ... | ... | @@ -1856,22 +1804,20 @@ pub fn flushModule(self: *Coff, arena: Allocator, tid: Zcu.PerThread.Id, prog_no |
| 1856 | 1804 | assert(!self.imports_count_dirty); |
| 1857 | 1805 | } |
| 1858 | 1806 | |
| 1859 | pub fn getDeclVAddr(self: *Coff, pt: Zcu.PerThread, decl_index: InternPool.DeclIndex, reloc_info: link.File.RelocInfo) !u64 { | |
| 1807 | pub fn getNavVAddr( | |
| 1808 | self: *Coff, | |
| 1809 | pt: Zcu.PerThread, | |
| 1810 | nav_index: InternPool.Nav.Index, | |
| 1811 | reloc_info: link.File.RelocInfo, | |
| 1812 | ) !u64 { | |
| 1860 | 1813 | assert(self.llvm_object == null); |
| 1861 | 1814 | const zcu = pt.zcu; |
| 1862 | 1815 | const ip = &zcu.intern_pool; |
| 1863 | const decl = zcu.declPtr(decl_index); | |
| 1864 | log.debug("getDeclVAddr {}({d})", .{ decl.fqn.fmt(ip), decl_index }); | |
| 1865 | const sym_index = if (decl.isExtern(zcu)) blk: { | |
| 1866 | const name = decl.name.toSlice(ip); | |
| 1867 | const lib_name = if (decl.getOwnedExternFunc(zcu)) |ext_fn| | |
| 1868 | ext_fn.lib_name.toSlice(ip) | |
| 1869 | else | |
| 1870 | decl.getOwnedVariable(zcu).?.lib_name.toSlice(ip); | |
| 1871 | break :blk try self.getGlobalSymbol(name, lib_name); | |
| 1872 | } else blk: { | |
| 1873 | const this_atom_index = try self.getOrCreateAtomForDecl(decl_index); | |
| 1874 | break :blk self.getAtom(this_atom_index).getSymbolIndex().?; | |
| 1816 | const nav = ip.getNav(nav_index); | |
| 1817 | log.debug("getNavVAddr {}({d})", .{ nav.fqn.fmt(ip), nav_index }); | |
| 1818 | const sym_index = switch (ip.indexToKey(nav.status.resolved.val)) { | |
| 1819 | .@"extern" => |@"extern"| try self.getGlobalSymbol(nav.name.toSlice(ip), @"extern".lib_name.toSlice(ip)), | |
| 1820 | else => self.getAtom(try self.getOrCreateAtomForNav(nav_index)).getSymbolIndex().?, | |
| 1875 | 1821 | }; |
| 1876 | 1822 | const atom_index = self.getAtomIndexForSymbol(.{ .sym_index = reloc_info.parent_atom_index, .file = null }).?; |
| 1877 | 1823 | const target = SymbolWithLoc{ .sym_index = sym_index, .file = null }; |
| ... | ... | @@ -1888,36 +1834,36 @@ pub fn getDeclVAddr(self: *Coff, pt: Zcu.PerThread, decl_index: InternPool.DeclI |
| 1888 | 1834 | return 0; |
| 1889 | 1835 | } |
| 1890 | 1836 | |
| 1891 | pub fn lowerAnonDecl( | |
| 1837 | pub fn lowerUav( | |
| 1892 | 1838 | self: *Coff, |
| 1893 | 1839 | pt: Zcu.PerThread, |
| 1894 | decl_val: InternPool.Index, | |
| 1840 | uav: InternPool.Index, | |
| 1895 | 1841 | explicit_alignment: InternPool.Alignment, |
| 1896 | 1842 | src_loc: Module.LazySrcLoc, |
| 1897 | ) !codegen.Result { | |
| 1898 | const gpa = self.base.comp.gpa; | |
| 1899 | const mod = self.base.comp.module.?; | |
| 1900 | const ty = Type.fromInterned(mod.intern_pool.typeOf(decl_val)); | |
| 1901 | const decl_alignment = switch (explicit_alignment) { | |
| 1902 | .none => ty.abiAlignment(pt), | |
| 1843 | ) !codegen.GenResult { | |
| 1844 | const zcu = pt.zcu; | |
| 1845 | const gpa = zcu.gpa; | |
| 1846 | const val = Value.fromInterned(uav); | |
| 1847 | const uav_alignment = switch (explicit_alignment) { | |
| 1848 | .none => val.typeOf(zcu).abiAlignment(pt), | |
| 1903 | 1849 | else => explicit_alignment, |
| 1904 | 1850 | }; |
| 1905 | if (self.anon_decls.get(decl_val)) |metadata| { | |
| 1906 | const existing_addr = self.getAtom(metadata.atom).getSymbol(self).value; | |
| 1907 | if (decl_alignment.check(existing_addr)) | |
| 1908 | return .ok; | |
| 1851 | if (self.uavs.get(uav)) |metadata| { | |
| 1852 | const atom = self.getAtom(metadata.atom); | |
| 1853 | const existing_addr = atom.getSymbol(self).value; | |
| 1854 | if (uav_alignment.check(existing_addr)) | |
| 1855 | return .{ .mcv = .{ .load_direct = atom.getSymbolIndex().? } }; | |
| 1909 | 1856 | } |
| 1910 | 1857 | |
| 1911 | const val = Value.fromInterned(decl_val); | |
| 1912 | 1858 | var name_buf: [32]u8 = undefined; |
| 1913 | 1859 | const name = std.fmt.bufPrint(&name_buf, "__anon_{d}", .{ |
| 1914 | @intFromEnum(decl_val), | |
| 1860 | @intFromEnum(uav), | |
| 1915 | 1861 | }) catch unreachable; |
| 1916 | 1862 | const res = self.lowerConst( |
| 1917 | 1863 | pt, |
| 1918 | 1864 | name, |
| 1919 | 1865 | val, |
| 1920 | decl_alignment, | |
| 1866 | uav_alignment, | |
| 1921 | 1867 | self.rdata_section_index.?, |
| 1922 | 1868 | src_loc, |
| 1923 | 1869 | ) catch |err| switch (err) { |
| ... | ... | @@ -1933,14 +1879,23 @@ pub fn lowerAnonDecl( |
| 1933 | 1879 | .ok => |atom_index| atom_index, |
| 1934 | 1880 | .fail => |em| return .{ .fail = em }, |
| 1935 | 1881 | }; |
| 1936 | try self.anon_decls.put(gpa, decl_val, .{ .atom = atom_index, .section = self.rdata_section_index.? }); | |
| 1937 | return .ok; | |
| 1882 | try self.uavs.put(gpa, uav, .{ | |
| 1883 | .atom = atom_index, | |
| 1884 | .section = self.rdata_section_index.?, | |
| 1885 | }); | |
| 1886 | return .{ .mcv = .{ | |
| 1887 | .load_direct = self.getAtom(atom_index).getSymbolIndex().?, | |
| 1888 | } }; | |
| 1938 | 1889 | } |
| 1939 | 1890 | |
| 1940 | pub fn getAnonDeclVAddr(self: *Coff, decl_val: InternPool.Index, reloc_info: link.File.RelocInfo) !u64 { | |
| 1891 | pub fn getUavVAddr( | |
| 1892 | self: *Coff, | |
| 1893 | uav: InternPool.Index, | |
| 1894 | reloc_info: link.File.RelocInfo, | |
| 1895 | ) !u64 { | |
| 1941 | 1896 | assert(self.llvm_object == null); |
| 1942 | 1897 | |
| 1943 | const this_atom_index = self.anon_decls.get(decl_val).?.atom; | |
| 1898 | const this_atom_index = self.uavs.get(uav).?.atom; | |
| 1944 | 1899 | const sym_index = self.getAtom(this_atom_index).getSymbolIndex().?; |
| 1945 | 1900 | const atom_index = self.getAtomIndexForSymbol(.{ .sym_index = reloc_info.parent_atom_index, .file = null }).?; |
| 1946 | 1901 | const target = SymbolWithLoc{ .sym_index = sym_index, .file = null }; |
| ... | ... | @@ -2760,6 +2715,7 @@ const Allocator = std.mem.Allocator; |
| 2760 | 2715 | const codegen = @import("../codegen.zig"); |
| 2761 | 2716 | const link = @import("../link.zig"); |
| 2762 | 2717 | const lld = @import("Coff/lld.zig"); |
| 2718 | const target_util = @import("../target.zig"); | |
| 2763 | 2719 | const trace = @import("../tracy.zig").trace; |
| 2764 | 2720 | |
| 2765 | 2721 | const Air = @import("../Air.zig"); |
| ... | ... | @@ -2781,6 +2737,4 @@ const Value = @import("../Value.zig"); |
| 2781 | 2737 | const AnalUnit = InternPool.AnalUnit; |
| 2782 | 2738 | const dev = @import("../dev.zig"); |
| 2783 | 2739 | |
| 2784 | pub const base_tag: link.File.Tag = .coff; | |
| 2785 | ||
| 2786 | 2740 | const msdos_stub = @embedFile("msdos-stub.bin"); |
src/link/Dwarf.zig+475-564| ... | ... | @@ -9,7 +9,7 @@ src_fn_free_list: std.AutoHashMapUnmanaged(Atom.Index, void) = .{}, |
| 9 | 9 | src_fn_first_index: ?Atom.Index = null, |
| 10 | 10 | src_fn_last_index: ?Atom.Index = null, |
| 11 | 11 | src_fns: std.ArrayListUnmanaged(Atom) = .{}, |
| 12 | src_fn_decls: AtomTable = .{}, | |
| 12 | src_fn_navs: AtomTable = .{}, | |
| 13 | 13 | |
| 14 | 14 | /// A list of `Atom`s whose corresponding .debug_info tags have surplus capacity. |
| 15 | 15 | /// This is the same concept as `text_block_free_list`; see those doc comments. |
| ... | ... | @@ -17,7 +17,7 @@ di_atom_free_list: std.AutoHashMapUnmanaged(Atom.Index, void) = .{}, |
| 17 | 17 | di_atom_first_index: ?Atom.Index = null, |
| 18 | 18 | di_atom_last_index: ?Atom.Index = null, |
| 19 | 19 | di_atoms: std.ArrayListUnmanaged(Atom) = .{}, |
| 20 | di_atom_decls: AtomTable = .{}, | |
| 20 | di_atom_navs: AtomTable = .{}, | |
| 21 | 21 | |
| 22 | 22 | dbg_line_header: DbgLineHeader, |
| 23 | 23 | |
| ... | ... | @@ -27,7 +27,7 @@ abbrev_table_offset: ?u64 = null, |
| 27 | 27 | /// Table of debug symbol names. |
| 28 | 28 | strtab: StringTable = .{}, |
| 29 | 29 | |
| 30 | /// Quick lookup array of all defined source files referenced by at least one Decl. | |
| 30 | /// Quick lookup array of all defined source files referenced by at least one Nav. | |
| 31 | 31 | /// They will end up in the DWARF debug_line header as two lists: |
| 32 | 32 | /// * []include_directory |
| 33 | 33 | /// * []file_names |
| ... | ... | @@ -35,13 +35,13 @@ di_files: std.AutoArrayHashMapUnmanaged(*const Zcu.File, void) = .{}, |
| 35 | 35 | |
| 36 | 36 | global_abbrev_relocs: std.ArrayListUnmanaged(AbbrevRelocation) = .{}, |
| 37 | 37 | |
| 38 | const AtomTable = std.AutoHashMapUnmanaged(InternPool.DeclIndex, Atom.Index); | |
| 38 | const AtomTable = std.AutoHashMapUnmanaged(InternPool.Nav.Index, Atom.Index); | |
| 39 | 39 | |
| 40 | 40 | const Atom = struct { |
| 41 | /// Offset into .debug_info pointing to the tag for this Decl, or | |
| 41 | /// Offset into .debug_info pointing to the tag for this Nav, or | |
| 42 | 42 | /// offset from the beginning of the Debug Line Program header that contains this function. |
| 43 | 43 | off: u32, |
| 44 | /// Size of the .debug_info tag for this Decl, not including padding, or | |
| 44 | /// Size of the .debug_info tag for this Nav, not including padding, or | |
| 45 | 45 | /// size of the line number program component belonging to this function, not |
| 46 | 46 | /// including padding. |
| 47 | 47 | len: u32, |
| ... | ... | @@ -61,14 +61,14 @@ const DbgLineHeader = struct { |
| 61 | 61 | opcode_base: u8, |
| 62 | 62 | }; |
| 63 | 63 | |
| 64 | /// Represents state of the analysed Decl. | |
| 65 | /// Includes Decl's abbrev table of type Types, matching arena | |
| 64 | /// Represents state of the analysed Nav. | |
| 65 | /// Includes Nav's abbrev table of type Types, matching arena | |
| 66 | 66 | /// and a set of relocations that will be resolved once this |
| 67 | /// Decl's inner Atom is assigned an offset within the DWARF section. | |
| 68 | pub const DeclState = struct { | |
| 67 | /// Nav's inner Atom is assigned an offset within the DWARF section. | |
| 68 | pub const NavState = struct { | |
| 69 | 69 | dwarf: *Dwarf, |
| 70 | 70 | pt: Zcu.PerThread, |
| 71 | di_atom_decls: *const AtomTable, | |
| 71 | di_atom_navs: *const AtomTable, | |
| 72 | 72 | dbg_line_func: InternPool.Index, |
| 73 | 73 | dbg_line: std.ArrayList(u8), |
| 74 | 74 | dbg_info: std.ArrayList(u8), |
| ... | ... | @@ -78,20 +78,20 @@ pub const DeclState = struct { |
| 78 | 78 | abbrev_relocs: std.ArrayListUnmanaged(AbbrevRelocation), |
| 79 | 79 | exprloc_relocs: std.ArrayListUnmanaged(ExprlocRelocation), |
| 80 | 80 | |
| 81 | pub fn deinit(self: *DeclState) void { | |
| 82 | const gpa = self.dwarf.allocator; | |
| 83 | self.dbg_line.deinit(); | |
| 84 | self.dbg_info.deinit(); | |
| 85 | self.abbrev_type_arena.deinit(); | |
| 86 | self.abbrev_table.deinit(gpa); | |
| 87 | self.abbrev_resolver.deinit(gpa); | |
| 88 | self.abbrev_relocs.deinit(gpa); | |
| 89 | self.exprloc_relocs.deinit(gpa); | |
| 81 | pub fn deinit(ns: *NavState) void { | |
| 82 | const gpa = ns.dwarf.allocator; | |
| 83 | ns.dbg_line.deinit(); | |
| 84 | ns.dbg_info.deinit(); | |
| 85 | ns.abbrev_type_arena.deinit(); | |
| 86 | ns.abbrev_table.deinit(gpa); | |
| 87 | ns.abbrev_resolver.deinit(gpa); | |
| 88 | ns.abbrev_relocs.deinit(gpa); | |
| 89 | ns.exprloc_relocs.deinit(gpa); | |
| 90 | 90 | } |
| 91 | 91 | |
| 92 | 92 | /// Adds local type relocation of the form: @offset => @this + addend |
| 93 | 93 | /// @this signifies the offset within the .debug_abbrev section of the containing atom. |
| 94 | fn addTypeRelocLocal(self: *DeclState, atom_index: Atom.Index, offset: u32, addend: u32) !void { | |
| 94 | fn addTypeRelocLocal(self: *NavState, atom_index: Atom.Index, offset: u32, addend: u32) !void { | |
| 95 | 95 | log.debug("{x}: @this + {x}", .{ offset, addend }); |
| 96 | 96 | try self.abbrev_relocs.append(self.dwarf.allocator, .{ |
| 97 | 97 | .target = null, |
| ... | ... | @@ -104,7 +104,7 @@ pub const DeclState = struct { |
| 104 | 104 | /// Adds global type relocation of the form: @offset => @symbol + 0 |
| 105 | 105 | /// @symbol signifies a type abbreviation posititioned somewhere in the .debug_abbrev section |
| 106 | 106 | /// which we use as our target of the relocation. |
| 107 | fn addTypeRelocGlobal(self: *DeclState, atom_index: Atom.Index, ty: Type, offset: u32) !void { | |
| 107 | fn addTypeRelocGlobal(self: *NavState, atom_index: Atom.Index, ty: Type, offset: u32) !void { | |
| 108 | 108 | const gpa = self.dwarf.allocator; |
| 109 | 109 | const resolv = self.abbrev_resolver.get(ty.toIntern()) orelse blk: { |
| 110 | 110 | const sym_index: u32 = @intCast(self.abbrev_table.items.len); |
| ... | ... | @@ -127,7 +127,7 @@ pub const DeclState = struct { |
| 127 | 127 | } |
| 128 | 128 | |
| 129 | 129 | fn addDbgInfoType( |
| 130 | self: *DeclState, | |
| 130 | self: *NavState, | |
| 131 | 131 | pt: Zcu.PerThread, |
| 132 | 132 | atom_index: Atom.Index, |
| 133 | 133 | ty: Type, |
| ... | ... | @@ -550,15 +550,15 @@ pub const DeclState = struct { |
| 550 | 550 | }; |
| 551 | 551 | |
| 552 | 552 | pub fn genArgDbgInfo( |
| 553 | self: *DeclState, | |
| 553 | self: *NavState, | |
| 554 | 554 | name: [:0]const u8, |
| 555 | 555 | ty: Type, |
| 556 | owner_decl: InternPool.DeclIndex, | |
| 556 | owner_nav: InternPool.Nav.Index, | |
| 557 | 557 | loc: DbgInfoLoc, |
| 558 | 558 | ) error{OutOfMemory}!void { |
| 559 | 559 | const pt = self.pt; |
| 560 | 560 | const dbg_info = &self.dbg_info; |
| 561 | const atom_index = self.di_atom_decls.get(owner_decl).?; | |
| 561 | const atom_index = self.di_atom_navs.get(owner_nav).?; | |
| 562 | 562 | const name_with_null = name.ptr[0 .. name.len + 1]; |
| 563 | 563 | |
| 564 | 564 | switch (loc) { |
| ... | ... | @@ -639,6 +639,7 @@ pub const DeclState = struct { |
| 639 | 639 | leb128.writeIleb128(dbg_info.writer(), info.offset) catch unreachable; |
| 640 | 640 | }, |
| 641 | 641 | .wasm_local => |value| { |
| 642 | @import("../dev.zig").check(.wasm_linker); | |
| 642 | 643 | const leb_size = link.File.Wasm.getUleb128Size(value); |
| 643 | 644 | try dbg_info.ensureUnusedCapacity(3 + leb_size); |
| 644 | 645 | // wasm locations are encoded as follow: |
| ... | ... | @@ -665,15 +666,15 @@ pub const DeclState = struct { |
| 665 | 666 | } |
| 666 | 667 | |
| 667 | 668 | pub fn genVarDbgInfo( |
| 668 | self: *DeclState, | |
| 669 | self: *NavState, | |
| 669 | 670 | name: [:0]const u8, |
| 670 | 671 | ty: Type, |
| 671 | owner_decl: InternPool.DeclIndex, | |
| 672 | owner_nav: InternPool.Nav.Index, | |
| 672 | 673 | is_ptr: bool, |
| 673 | 674 | loc: DbgInfoLoc, |
| 674 | 675 | ) error{OutOfMemory}!void { |
| 675 | 676 | const dbg_info = &self.dbg_info; |
| 676 | const atom_index = self.di_atom_decls.get(owner_decl).?; | |
| 677 | const atom_index = self.di_atom_navs.get(owner_nav).?; | |
| 677 | 678 | const name_with_null = name.ptr[0 .. name.len + 1]; |
| 678 | 679 | try dbg_info.append(@intFromEnum(AbbrevCode.variable)); |
| 679 | 680 | const gpa = self.dwarf.allocator; |
| ... | ... | @@ -881,7 +882,7 @@ pub const DeclState = struct { |
| 881 | 882 | } |
| 882 | 883 | |
| 883 | 884 | pub fn advancePCAndLine( |
| 884 | self: *DeclState, | |
| 885 | self: *NavState, | |
| 885 | 886 | delta_line: i33, |
| 886 | 887 | delta_pc: u64, |
| 887 | 888 | ) error{OutOfMemory}!void { |
| ... | ... | @@ -921,21 +922,21 @@ pub const DeclState = struct { |
| 921 | 922 | } |
| 922 | 923 | } |
| 923 | 924 | |
| 924 | pub fn setColumn(self: *DeclState, column: u32) error{OutOfMemory}!void { | |
| 925 | pub fn setColumn(self: *NavState, column: u32) error{OutOfMemory}!void { | |
| 925 | 926 | try self.dbg_line.ensureUnusedCapacity(1 + 5); |
| 926 | 927 | self.dbg_line.appendAssumeCapacity(DW.LNS.set_column); |
| 927 | 928 | leb128.writeUleb128(self.dbg_line.writer(), column + 1) catch unreachable; |
| 928 | 929 | } |
| 929 | 930 | |
| 930 | pub fn setPrologueEnd(self: *DeclState) error{OutOfMemory}!void { | |
| 931 | pub fn setPrologueEnd(self: *NavState) error{OutOfMemory}!void { | |
| 931 | 932 | try self.dbg_line.append(DW.LNS.set_prologue_end); |
| 932 | 933 | } |
| 933 | 934 | |
| 934 | pub fn setEpilogueBegin(self: *DeclState) error{OutOfMemory}!void { | |
| 935 | pub fn setEpilogueBegin(self: *NavState) error{OutOfMemory}!void { | |
| 935 | 936 | try self.dbg_line.append(DW.LNS.set_epilogue_begin); |
| 936 | 937 | } |
| 937 | 938 | |
| 938 | pub fn setInlineFunc(self: *DeclState, func: InternPool.Index) error{OutOfMemory}!void { | |
| 939 | pub fn setInlineFunc(self: *NavState, func: InternPool.Index) error{OutOfMemory}!void { | |
| 939 | 940 | const zcu = self.pt.zcu; |
| 940 | 941 | if (self.dbg_line_func == func) return; |
| 941 | 942 | |
| ... | ... | @@ -944,15 +945,15 @@ pub const DeclState = struct { |
| 944 | 945 | const old_func_info = zcu.funcInfo(self.dbg_line_func); |
| 945 | 946 | const new_func_info = zcu.funcInfo(func); |
| 946 | 947 | |
| 947 | const old_file = try self.dwarf.addDIFile(zcu, old_func_info.owner_decl); | |
| 948 | const new_file = try self.dwarf.addDIFile(zcu, new_func_info.owner_decl); | |
| 948 | const old_file = try self.dwarf.addDIFile(zcu, old_func_info.owner_nav); | |
| 949 | const new_file = try self.dwarf.addDIFile(zcu, new_func_info.owner_nav); | |
| 949 | 950 | if (old_file != new_file) { |
| 950 | 951 | self.dbg_line.appendAssumeCapacity(DW.LNS.set_file); |
| 951 | 952 | leb128.writeUnsignedFixed(4, self.dbg_line.addManyAsArrayAssumeCapacity(4), new_file); |
| 952 | 953 | } |
| 953 | 954 | |
| 954 | const old_src_line: i33 = zcu.declPtr(old_func_info.owner_decl).navSrcLine(zcu); | |
| 955 | const new_src_line: i33 = zcu.declPtr(new_func_info.owner_decl).navSrcLine(zcu); | |
| 955 | const old_src_line: i33 = zcu.navSrcLine(old_func_info.owner_nav); | |
| 956 | const new_src_line: i33 = zcu.navSrcLine(new_func_info.owner_nav); | |
| 956 | 957 | if (new_src_line != old_src_line) { |
| 957 | 958 | self.dbg_line.appendAssumeCapacity(DW.LNS.advance_line); |
| 958 | 959 | leb128.writeSignedFixed(5, self.dbg_line.addManyAsArrayAssumeCapacity(5), new_src_line - old_src_line); |
| ... | ... | @@ -1064,31 +1065,31 @@ pub fn deinit(self: *Dwarf) void { |
| 1064 | 1065 | |
| 1065 | 1066 | self.src_fn_free_list.deinit(gpa); |
| 1066 | 1067 | self.src_fns.deinit(gpa); |
| 1067 | self.src_fn_decls.deinit(gpa); | |
| 1068 | self.src_fn_navs.deinit(gpa); | |
| 1068 | 1069 | |
| 1069 | 1070 | self.di_atom_free_list.deinit(gpa); |
| 1070 | 1071 | self.di_atoms.deinit(gpa); |
| 1071 | self.di_atom_decls.deinit(gpa); | |
| 1072 | self.di_atom_navs.deinit(gpa); | |
| 1072 | 1073 | |
| 1073 | 1074 | self.strtab.deinit(gpa); |
| 1074 | 1075 | self.di_files.deinit(gpa); |
| 1075 | 1076 | self.global_abbrev_relocs.deinit(gpa); |
| 1076 | 1077 | } |
| 1077 | 1078 | |
| 1078 | /// Initializes Decl's state and its matching output buffers. | |
| 1079 | /// Call this before `commitDeclState`. | |
| 1080 | pub fn initDeclState(self: *Dwarf, pt: Zcu.PerThread, decl_index: InternPool.DeclIndex) !DeclState { | |
| 1079 | /// Initializes Nav's state and its matching output buffers. | |
| 1080 | /// Call this before `commitNavState`. | |
| 1081 | pub fn initNavState(self: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) !NavState { | |
| 1081 | 1082 | const tracy = trace(@src()); |
| 1082 | 1083 | defer tracy.end(); |
| 1083 | 1084 | |
| 1084 | const decl = pt.zcu.declPtr(decl_index); | |
| 1085 | log.debug("initDeclState {}{*}", .{ decl.fqn.fmt(&pt.zcu.intern_pool), decl }); | |
| 1085 | const nav = pt.zcu.intern_pool.getNav(nav_index); | |
| 1086 | log.debug("initNavState {}", .{nav.fqn.fmt(&pt.zcu.intern_pool)}); | |
| 1086 | 1087 | |
| 1087 | 1088 | const gpa = self.allocator; |
| 1088 | var decl_state: DeclState = .{ | |
| 1089 | var nav_state: NavState = .{ | |
| 1089 | 1090 | .dwarf = self, |
| 1090 | 1091 | .pt = pt, |
| 1091 | .di_atom_decls = &self.di_atom_decls, | |
| 1092 | .di_atom_navs = &self.di_atom_navs, | |
| 1092 | 1093 | .dbg_line_func = undefined, |
| 1093 | 1094 | .dbg_line = std.ArrayList(u8).init(gpa), |
| 1094 | 1095 | .dbg_info = std.ArrayList(u8).init(gpa), |
| ... | ... | @@ -1098,30 +1099,30 @@ pub fn initDeclState(self: *Dwarf, pt: Zcu.PerThread, decl_index: InternPool.Dec |
| 1098 | 1099 | .abbrev_relocs = .{}, |
| 1099 | 1100 | .exprloc_relocs = .{}, |
| 1100 | 1101 | }; |
| 1101 | errdefer decl_state.deinit(); | |
| 1102 | const dbg_line_buffer = &decl_state.dbg_line; | |
| 1103 | const dbg_info_buffer = &decl_state.dbg_info; | |
| 1102 | errdefer nav_state.deinit(); | |
| 1103 | const dbg_line_buffer = &nav_state.dbg_line; | |
| 1104 | const dbg_info_buffer = &nav_state.dbg_info; | |
| 1104 | 1105 | |
| 1105 | const di_atom_index = try self.getOrCreateAtomForDecl(.di_atom, decl_index); | |
| 1106 | const di_atom_index = try self.getOrCreateAtomForNav(.di_atom, nav_index); | |
| 1106 | 1107 | |
| 1107 | assert(decl.has_tv); | |
| 1108 | const nav_val = Value.fromInterned(nav.status.resolved.val); | |
| 1108 | 1109 | |
| 1109 | switch (decl.typeOf(pt.zcu).zigTypeTag(pt.zcu)) { | |
| 1110 | switch (nav_val.typeOf(pt.zcu).zigTypeTag(pt.zcu)) { | |
| 1110 | 1111 | .Fn => { |
| 1111 | _ = try self.getOrCreateAtomForDecl(.src_fn, decl_index); | |
| 1112 | _ = try self.getOrCreateAtomForNav(.src_fn, nav_index); | |
| 1112 | 1113 | |
| 1113 | 1114 | // For functions we need to add a prologue to the debug line program. |
| 1114 | 1115 | const ptr_width_bytes = self.ptrWidthBytes(); |
| 1115 | 1116 | try dbg_line_buffer.ensureTotalCapacity((3 + ptr_width_bytes) + (1 + 4) + (1 + 4) + (1 + 5) + 1); |
| 1116 | 1117 | |
| 1117 | decl_state.dbg_line_func = decl.val.toIntern(); | |
| 1118 | const func = decl.val.getFunction(pt.zcu).?; | |
| 1119 | log.debug("decl.src_line={d}, func.lbrace_line={d}, func.rbrace_line={d}", .{ | |
| 1120 | decl.navSrcLine(pt.zcu), | |
| 1118 | nav_state.dbg_line_func = nav_val.toIntern(); | |
| 1119 | const func = nav_val.getFunction(pt.zcu).?; | |
| 1120 | log.debug("src_line={d}, func.lbrace_line={d}, func.rbrace_line={d}", .{ | |
| 1121 | pt.zcu.navSrcLine(nav_index), | |
| 1121 | 1122 | func.lbrace_line, |
| 1122 | 1123 | func.rbrace_line, |
| 1123 | 1124 | }); |
| 1124 | const line: u28 = @intCast(decl.navSrcLine(pt.zcu) + func.lbrace_line); | |
| 1125 | const line: u28 = @intCast(pt.zcu.navSrcLine(nav_index) + func.lbrace_line); | |
| 1125 | 1126 | |
| 1126 | 1127 | dbg_line_buffer.appendSliceAssumeCapacity(&.{ |
| 1127 | 1128 | DW.LNS.extended_op, |
| ... | ... | @@ -1143,7 +1144,7 @@ pub fn initDeclState(self: *Dwarf, pt: Zcu.PerThread, decl_index: InternPool.Dec |
| 1143 | 1144 | assert(self.getRelocDbgFileIndex() == dbg_line_buffer.items.len); |
| 1144 | 1145 | // Once we support more than one source file, this will have the ability to be more |
| 1145 | 1146 | // than one possible value. |
| 1146 | const file_index = try self.addDIFile(pt.zcu, decl_index); | |
| 1147 | const file_index = try self.addDIFile(pt.zcu, nav_index); | |
| 1147 | 1148 | leb128.writeUnsignedFixed(4, dbg_line_buffer.addManyAsArrayAssumeCapacity(4), file_index); |
| 1148 | 1149 | |
| 1149 | 1150 | dbg_line_buffer.appendAssumeCapacity(DW.LNS.set_column); |
| ... | ... | @@ -1154,12 +1155,12 @@ pub fn initDeclState(self: *Dwarf, pt: Zcu.PerThread, decl_index: InternPool.Dec |
| 1154 | 1155 | dbg_line_buffer.appendAssumeCapacity(DW.LNS.copy); |
| 1155 | 1156 | |
| 1156 | 1157 | // .debug_info subprogram |
| 1157 | const decl_name_slice = decl.name.toSlice(&pt.zcu.intern_pool); | |
| 1158 | const decl_linkage_name_slice = decl.fqn.toSlice(&pt.zcu.intern_pool); | |
| 1158 | const nav_name_slice = nav.name.toSlice(&pt.zcu.intern_pool); | |
| 1159 | const nav_linkage_name_slice = nav.fqn.toSlice(&pt.zcu.intern_pool); | |
| 1159 | 1160 | try dbg_info_buffer.ensureUnusedCapacity(1 + ptr_width_bytes + 4 + 4 + |
| 1160 | (decl_name_slice.len + 1) + (decl_linkage_name_slice.len + 1)); | |
| 1161 | (nav_name_slice.len + 1) + (nav_linkage_name_slice.len + 1)); | |
| 1161 | 1162 | |
| 1162 | const fn_ret_type = decl.typeOf(pt.zcu).fnReturnType(pt.zcu); | |
| 1163 | const fn_ret_type = nav_val.typeOf(pt.zcu).fnReturnType(pt.zcu); | |
| 1163 | 1164 | const fn_ret_has_bits = fn_ret_type.hasRuntimeBits(pt); |
| 1164 | 1165 | dbg_info_buffer.appendAssumeCapacity(@intFromEnum( |
| 1165 | 1166 | @as(AbbrevCode, if (fn_ret_has_bits) .subprogram else .subprogram_retvoid), |
| ... | ... | @@ -1172,14 +1173,14 @@ pub fn initDeclState(self: *Dwarf, pt: Zcu.PerThread, decl_index: InternPool.Dec |
| 1172 | 1173 | assert(self.getRelocDbgInfoSubprogramHighPC() == dbg_info_buffer.items.len); |
| 1173 | 1174 | dbg_info_buffer.appendNTimesAssumeCapacity(0, 4); // DW.AT.high_pc, DW.FORM.data4 |
| 1174 | 1175 | if (fn_ret_has_bits) { |
| 1175 | try decl_state.addTypeRelocGlobal(di_atom_index, fn_ret_type, @intCast(dbg_info_buffer.items.len)); | |
| 1176 | try nav_state.addTypeRelocGlobal(di_atom_index, fn_ret_type, @intCast(dbg_info_buffer.items.len)); | |
| 1176 | 1177 | dbg_info_buffer.appendNTimesAssumeCapacity(0, 4); // DW.AT.type, DW.FORM.ref4 |
| 1177 | 1178 | } |
| 1178 | 1179 | dbg_info_buffer.appendSliceAssumeCapacity( |
| 1179 | decl_name_slice[0 .. decl_name_slice.len + 1], | |
| 1180 | nav_name_slice[0 .. nav_name_slice.len + 1], | |
| 1180 | 1181 | ); // DW.AT.name, DW.FORM.string |
| 1181 | 1182 | dbg_info_buffer.appendSliceAssumeCapacity( |
| 1182 | decl_linkage_name_slice[0 .. decl_linkage_name_slice.len + 1], | |
| 1183 | nav_linkage_name_slice[0 .. nav_linkage_name_slice.len + 1], | |
| 1183 | 1184 | ); // DW.AT.linkage_name, DW.FORM.string |
| 1184 | 1185 | }, |
| 1185 | 1186 | else => { |
| ... | ... | @@ -1187,37 +1188,36 @@ pub fn initDeclState(self: *Dwarf, pt: Zcu.PerThread, decl_index: InternPool.Dec |
| 1187 | 1188 | }, |
| 1188 | 1189 | } |
| 1189 | 1190 | |
| 1190 | return decl_state; | |
| 1191 | return nav_state; | |
| 1191 | 1192 | } |
| 1192 | 1193 | |
| 1193 | pub fn commitDeclState( | |
| 1194 | pub fn commitNavState( | |
| 1194 | 1195 | self: *Dwarf, |
| 1195 | 1196 | pt: Zcu.PerThread, |
| 1196 | decl_index: InternPool.DeclIndex, | |
| 1197 | nav_index: InternPool.Nav.Index, | |
| 1197 | 1198 | sym_addr: u64, |
| 1198 | 1199 | sym_size: u64, |
| 1199 | decl_state: *DeclState, | |
| 1200 | nav_state: *NavState, | |
| 1200 | 1201 | ) !void { |
| 1201 | 1202 | const tracy = trace(@src()); |
| 1202 | 1203 | defer tracy.end(); |
| 1203 | 1204 | |
| 1204 | 1205 | const gpa = self.allocator; |
| 1205 | 1206 | const zcu = pt.zcu; |
| 1206 | const decl = zcu.declPtr(decl_index); | |
| 1207 | 1207 | const ip = &zcu.intern_pool; |
| 1208 | const namespace = zcu.namespacePtr(decl.src_namespace); | |
| 1209 | const target = namespace.fileScope(zcu).mod.resolved_target.result; | |
| 1208 | const nav = ip.getNav(nav_index); | |
| 1209 | const target = zcu.navFileScope(nav_index).mod.resolved_target.result; | |
| 1210 | 1210 | const target_endian = target.cpu.arch.endian(); |
| 1211 | 1211 | |
| 1212 | var dbg_line_buffer = &decl_state.dbg_line; | |
| 1213 | var dbg_info_buffer = &decl_state.dbg_info; | |
| 1212 | var dbg_line_buffer = &nav_state.dbg_line; | |
| 1213 | var dbg_info_buffer = &nav_state.dbg_info; | |
| 1214 | 1214 | |
| 1215 | assert(decl.has_tv); | |
| 1216 | switch (decl.typeOf(zcu).zigTypeTag(zcu)) { | |
| 1215 | const nav_val = Value.fromInterned(nav.status.resolved.val); | |
| 1216 | switch (nav_val.typeOf(zcu).zigTypeTag(zcu)) { | |
| 1217 | 1217 | .Fn => { |
| 1218 | try decl_state.setInlineFunc(decl.val.toIntern()); | |
| 1218 | try nav_state.setInlineFunc(nav_val.toIntern()); | |
| 1219 | 1219 | |
| 1220 | // Since the Decl is a function, we need to update the .debug_line program. | |
| 1220 | // Since the Nav is a function, we need to update the .debug_line program. | |
| 1221 | 1221 | // Perform the relocations based on vaddr. |
| 1222 | 1222 | switch (self.ptr_width) { |
| 1223 | 1223 | .p32 => { |
| ... | ... | @@ -1254,10 +1254,10 @@ pub fn commitDeclState( |
| 1254 | 1254 | |
| 1255 | 1255 | // Now we have the full contents and may allocate a region to store it. |
| 1256 | 1256 | |
| 1257 | // This logic is nearly identical to the logic below in `updateDeclDebugInfo` for | |
| 1257 | // This logic is nearly identical to the logic below in `updateNavDebugInfo` for | |
| 1258 | 1258 | // `TextBlock` and the .debug_info. If you are editing this logic, you |
| 1259 | 1259 | // probably need to edit that logic too. |
| 1260 | const src_fn_index = self.src_fn_decls.get(decl_index).?; | |
| 1260 | const src_fn_index = self.src_fn_navs.get(nav_index).?; | |
| 1261 | 1261 | const src_fn = self.getAtomPtr(.src_fn, src_fn_index); |
| 1262 | 1262 | src_fn.len = @intCast(dbg_line_buffer.items.len); |
| 1263 | 1263 | |
| ... | ... | @@ -1275,33 +1275,26 @@ pub fn commitDeclState( |
| 1275 | 1275 | next.prev_index = src_fn.prev_index; |
| 1276 | 1276 | src_fn.next_index = null; |
| 1277 | 1277 | // Populate where it used to be with NOPs. |
| 1278 | switch (self.bin_file.tag) { | |
| 1279 | .elf => { | |
| 1280 | const elf_file = self.bin_file.cast(File.Elf).?; | |
| 1281 | const debug_line_sect = &elf_file.shdrs.items[elf_file.debug_line_section_index.?]; | |
| 1282 | const file_pos = debug_line_sect.sh_offset + src_fn.off; | |
| 1283 | try pwriteDbgLineNops(elf_file.base.file.?, file_pos, 0, &[0]u8{}, src_fn.len); | |
| 1284 | }, | |
| 1285 | .macho => { | |
| 1286 | const macho_file = self.bin_file.cast(File.MachO).?; | |
| 1287 | if (macho_file.base.isRelocatable()) { | |
| 1288 | const debug_line_sect = &macho_file.sections.items(.header)[macho_file.debug_line_sect_index.?]; | |
| 1289 | const file_pos = debug_line_sect.offset + src_fn.off; | |
| 1290 | try pwriteDbgLineNops(macho_file.base.file.?, file_pos, 0, &[0]u8{}, src_fn.len); | |
| 1291 | } else { | |
| 1292 | const d_sym = macho_file.getDebugSymbols().?; | |
| 1293 | const debug_line_sect = d_sym.getSectionPtr(d_sym.debug_line_section_index.?); | |
| 1294 | const file_pos = debug_line_sect.offset + src_fn.off; | |
| 1295 | try pwriteDbgLineNops(d_sym.file, file_pos, 0, &[0]u8{}, src_fn.len); | |
| 1296 | } | |
| 1297 | }, | |
| 1298 | .wasm => { | |
| 1299 | // const wasm_file = self.bin_file.cast(File.Wasm).?; | |
| 1300 | // const debug_line = wasm_file.getAtomPtr(wasm_file.debug_line_atom.?).code; | |
| 1301 | // writeDbgLineNopsBuffered(debug_line.items, src_fn.off, 0, &.{}, src_fn.len); | |
| 1302 | }, | |
| 1303 | else => unreachable, | |
| 1304 | } | |
| 1278 | if (self.bin_file.cast(.elf)) |elf_file| { | |
| 1279 | const debug_line_sect = &elf_file.shdrs.items[elf_file.debug_line_section_index.?]; | |
| 1280 | const file_pos = debug_line_sect.sh_offset + src_fn.off; | |
| 1281 | try pwriteDbgLineNops(elf_file.base.file.?, file_pos, 0, &[0]u8{}, src_fn.len); | |
| 1282 | } else if (self.bin_file.cast(.macho)) |macho_file| { | |
| 1283 | if (macho_file.base.isRelocatable()) { | |
| 1284 | const debug_line_sect = &macho_file.sections.items(.header)[macho_file.debug_line_sect_index.?]; | |
| 1285 | const file_pos = debug_line_sect.offset + src_fn.off; | |
| 1286 | try pwriteDbgLineNops(macho_file.base.file.?, file_pos, 0, &[0]u8{}, src_fn.len); | |
| 1287 | } else { | |
| 1288 | const d_sym = macho_file.getDebugSymbols().?; | |
| 1289 | const debug_line_sect = d_sym.getSectionPtr(d_sym.debug_line_section_index.?); | |
| 1290 | const file_pos = debug_line_sect.offset + src_fn.off; | |
| 1291 | try pwriteDbgLineNops(d_sym.file, file_pos, 0, &[0]u8{}, src_fn.len); | |
| 1292 | } | |
| 1293 | } else if (self.bin_file.cast(.wasm)) |wasm_file| { | |
| 1294 | _ = wasm_file; | |
| 1295 | // const debug_line = wasm_file.getAtomPtr(wasm_file.debug_line_atom.?).code; | |
| 1296 | // writeDbgLineNopsBuffered(debug_line.items, src_fn.off, 0, &.{}, src_fn.len); | |
| 1297 | } else unreachable; | |
| 1305 | 1298 | // TODO Look at the free list before appending at the end. |
| 1306 | 1299 | src_fn.prev_index = last_index; |
| 1307 | 1300 | const last = self.getAtomPtr(.src_fn, last_index); |
| ... | ... | @@ -1342,76 +1335,67 @@ pub fn commitDeclState( |
| 1342 | 1335 | |
| 1343 | 1336 | // We only have support for one compilation unit so far, so the offsets are directly |
| 1344 | 1337 | // from the .debug_line section. |
| 1345 | switch (self.bin_file.tag) { | |
| 1346 | .elf => { | |
| 1347 | const elf_file = self.bin_file.cast(File.Elf).?; | |
| 1348 | const shdr_index = elf_file.debug_line_section_index.?; | |
| 1349 | try elf_file.growNonAllocSection(shdr_index, needed_size, 1, true); | |
| 1350 | const debug_line_sect = elf_file.shdrs.items[shdr_index]; | |
| 1351 | const file_pos = debug_line_sect.sh_offset + src_fn.off; | |
| 1338 | if (self.bin_file.cast(.elf)) |elf_file| { | |
| 1339 | const shdr_index = elf_file.debug_line_section_index.?; | |
| 1340 | try elf_file.growNonAllocSection(shdr_index, needed_size, 1, true); | |
| 1341 | const debug_line_sect = elf_file.shdrs.items[shdr_index]; | |
| 1342 | const file_pos = debug_line_sect.sh_offset + src_fn.off; | |
| 1343 | try pwriteDbgLineNops( | |
| 1344 | elf_file.base.file.?, | |
| 1345 | file_pos, | |
| 1346 | prev_padding_size, | |
| 1347 | dbg_line_buffer.items, | |
| 1348 | next_padding_size, | |
| 1349 | ); | |
| 1350 | } else if (self.bin_file.cast(.macho)) |macho_file| { | |
| 1351 | if (macho_file.base.isRelocatable()) { | |
| 1352 | const sect_index = macho_file.debug_line_sect_index.?; | |
| 1353 | try macho_file.growSection(sect_index, needed_size); | |
| 1354 | const sect = macho_file.sections.items(.header)[sect_index]; | |
| 1355 | const file_pos = sect.offset + src_fn.off; | |
| 1352 | 1356 | try pwriteDbgLineNops( |
| 1353 | elf_file.base.file.?, | |
| 1357 | macho_file.base.file.?, | |
| 1354 | 1358 | file_pos, |
| 1355 | 1359 | prev_padding_size, |
| 1356 | 1360 | dbg_line_buffer.items, |
| 1357 | 1361 | next_padding_size, |
| 1358 | 1362 | ); |
| 1359 | }, | |
| 1360 | ||
| 1361 | .macho => { | |
| 1362 | const macho_file = self.bin_file.cast(File.MachO).?; | |
| 1363 | if (macho_file.base.isRelocatable()) { | |
| 1364 | const sect_index = macho_file.debug_line_sect_index.?; | |
| 1365 | try macho_file.growSection(sect_index, needed_size); | |
| 1366 | const sect = macho_file.sections.items(.header)[sect_index]; | |
| 1367 | const file_pos = sect.offset + src_fn.off; | |
| 1368 | try pwriteDbgLineNops( | |
| 1369 | macho_file.base.file.?, | |
| 1370 | file_pos, | |
| 1371 | prev_padding_size, | |
| 1372 | dbg_line_buffer.items, | |
| 1373 | next_padding_size, | |
| 1374 | ); | |
| 1375 | } else { | |
| 1376 | const d_sym = macho_file.getDebugSymbols().?; | |
| 1377 | const sect_index = d_sym.debug_line_section_index.?; | |
| 1378 | try d_sym.growSection(sect_index, needed_size, true, macho_file); | |
| 1379 | const sect = d_sym.getSection(sect_index); | |
| 1380 | const file_pos = sect.offset + src_fn.off; | |
| 1381 | try pwriteDbgLineNops( | |
| 1382 | d_sym.file, | |
| 1383 | file_pos, | |
| 1384 | prev_padding_size, | |
| 1385 | dbg_line_buffer.items, | |
| 1386 | next_padding_size, | |
| 1387 | ); | |
| 1388 | } | |
| 1389 | }, | |
| 1390 | ||
| 1391 | .wasm => { | |
| 1392 | // const wasm_file = self.bin_file.cast(File.Wasm).?; | |
| 1393 | // const atom = wasm_file.getAtomPtr(wasm_file.debug_line_atom.?); | |
| 1394 | // const debug_line = &atom.code; | |
| 1395 | // const segment_size = debug_line.items.len; | |
| 1396 | // if (needed_size != segment_size) { | |
| 1397 | // log.debug(" needed size does not equal allocated size: {d}", .{needed_size}); | |
| 1398 | // if (needed_size > segment_size) { | |
| 1399 | // log.debug(" allocating {d} bytes for 'debug line' information", .{needed_size - segment_size}); | |
| 1400 | // try debug_line.resize(self.allocator, needed_size); | |
| 1401 | // @memset(debug_line.items[segment_size..], 0); | |
| 1402 | // } | |
| 1403 | // debug_line.items.len = needed_size; | |
| 1404 | // } | |
| 1405 | // writeDbgLineNopsBuffered( | |
| 1406 | // debug_line.items, | |
| 1407 | // src_fn.off, | |
| 1408 | // prev_padding_size, | |
| 1409 | // dbg_line_buffer.items, | |
| 1410 | // next_padding_size, | |
| 1411 | // ); | |
| 1412 | }, | |
| 1413 | else => unreachable, | |
| 1414 | } | |
| 1363 | } else { | |
| 1364 | const d_sym = macho_file.getDebugSymbols().?; | |
| 1365 | const sect_index = d_sym.debug_line_section_index.?; | |
| 1366 | try d_sym.growSection(sect_index, needed_size, true, macho_file); | |
| 1367 | const sect = d_sym.getSection(sect_index); | |
| 1368 | const file_pos = sect.offset + src_fn.off; | |
| 1369 | try pwriteDbgLineNops( | |
| 1370 | d_sym.file, | |
| 1371 | file_pos, | |
| 1372 | prev_padding_size, | |
| 1373 | dbg_line_buffer.items, | |
| 1374 | next_padding_size, | |
| 1375 | ); | |
| 1376 | } | |
| 1377 | } else if (self.bin_file.cast(.wasm)) |wasm_file| { | |
| 1378 | _ = wasm_file; | |
| 1379 | // const atom = wasm_file.getAtomPtr(wasm_file.debug_line_atom.?); | |
| 1380 | // const debug_line = &atom.code; | |
| 1381 | // const segment_size = debug_line.items.len; | |
| 1382 | // if (needed_size != segment_size) { | |
| 1383 | // log.debug(" needed size does not equal allocated size: {d}", .{needed_size}); | |
| 1384 | // if (needed_size > segment_size) { | |
| 1385 | // log.debug(" allocating {d} bytes for 'debug line' information", .{needed_size - segment_size}); | |
| 1386 | // try debug_line.resize(self.allocator, needed_size); | |
| 1387 | // @memset(debug_line.items[segment_size..], 0); | |
| 1388 | // } | |
| 1389 | // debug_line.items.len = needed_size; | |
| 1390 | // } | |
| 1391 | // writeDbgLineNopsBuffered( | |
| 1392 | // debug_line.items, | |
| 1393 | // src_fn.off, | |
| 1394 | // prev_padding_size, | |
| 1395 | // dbg_line_buffer.items, | |
| 1396 | // next_padding_size, | |
| 1397 | // ); | |
| 1398 | } else unreachable; | |
| 1415 | 1399 | |
| 1416 | 1400 | // .debug_info - End the TAG.subprogram children. |
| 1417 | 1401 | try dbg_info_buffer.append(0); |
| ... | ... | @@ -1422,27 +1406,27 @@ pub fn commitDeclState( |
| 1422 | 1406 | if (dbg_info_buffer.items.len == 0) |
| 1423 | 1407 | return; |
| 1424 | 1408 | |
| 1425 | const di_atom_index = self.di_atom_decls.get(decl_index).?; | |
| 1426 | if (decl_state.abbrev_table.items.len > 0) { | |
| 1427 | // Now we emit the .debug_info types of the Decl. These will count towards the size of | |
| 1409 | const di_atom_index = self.di_atom_navs.get(nav_index).?; | |
| 1410 | if (nav_state.abbrev_table.items.len > 0) { | |
| 1411 | // Now we emit the .debug_info types of the Nav. These will count towards the size of | |
| 1428 | 1412 | // the buffer, so we have to do it before computing the offset, and we can't perform the actual |
| 1429 | 1413 | // relocations yet. |
| 1430 | 1414 | var sym_index: usize = 0; |
| 1431 | while (sym_index < decl_state.abbrev_table.items.len) : (sym_index += 1) { | |
| 1432 | const symbol = &decl_state.abbrev_table.items[sym_index]; | |
| 1415 | while (sym_index < nav_state.abbrev_table.items.len) : (sym_index += 1) { | |
| 1416 | const symbol = &nav_state.abbrev_table.items[sym_index]; | |
| 1433 | 1417 | const ty = symbol.type; |
| 1434 | 1418 | if (ip.isErrorSetType(ty.toIntern())) continue; |
| 1435 | 1419 | |
| 1436 | 1420 | symbol.offset = @intCast(dbg_info_buffer.items.len); |
| 1437 | try decl_state.addDbgInfoType(pt, di_atom_index, ty); | |
| 1421 | try nav_state.addDbgInfoType(pt, di_atom_index, ty); | |
| 1438 | 1422 | } |
| 1439 | 1423 | } |
| 1440 | 1424 | |
| 1441 | try self.updateDeclDebugInfoAllocation(di_atom_index, @intCast(dbg_info_buffer.items.len)); | |
| 1425 | try self.updateNavDebugInfoAllocation(di_atom_index, @intCast(dbg_info_buffer.items.len)); | |
| 1442 | 1426 | |
| 1443 | while (decl_state.abbrev_relocs.popOrNull()) |reloc| { | |
| 1427 | while (nav_state.abbrev_relocs.popOrNull()) |reloc| { | |
| 1444 | 1428 | if (reloc.target) |reloc_target| { |
| 1445 | const symbol = decl_state.abbrev_table.items[reloc_target]; | |
| 1429 | const symbol = nav_state.abbrev_table.items[reloc_target]; | |
| 1446 | 1430 | const ty = symbol.type; |
| 1447 | 1431 | if (ip.isErrorSetType(ty.toIntern())) { |
| 1448 | 1432 | log.debug("resolving %{d} deferred until flush", .{reloc_target}); |
| ... | ... | @@ -1479,38 +1463,35 @@ pub fn commitDeclState( |
| 1479 | 1463 | } |
| 1480 | 1464 | } |
| 1481 | 1465 | |
| 1482 | while (decl_state.exprloc_relocs.popOrNull()) |reloc| { | |
| 1483 | switch (self.bin_file.tag) { | |
| 1484 | .macho => { | |
| 1485 | const macho_file = self.bin_file.cast(File.MachO).?; | |
| 1486 | if (macho_file.base.isRelocatable()) { | |
| 1487 | // TODO | |
| 1488 | } else { | |
| 1489 | const d_sym = macho_file.getDebugSymbols().?; | |
| 1490 | try d_sym.relocs.append(d_sym.allocator, .{ | |
| 1491 | .type = switch (reloc.type) { | |
| 1492 | .direct_load => .direct_load, | |
| 1493 | .got_load => .got_load, | |
| 1494 | }, | |
| 1495 | .target = reloc.target, | |
| 1496 | .offset = reloc.offset + self.getAtom(.di_atom, di_atom_index).off, | |
| 1497 | .addend = 0, | |
| 1498 | }); | |
| 1499 | } | |
| 1500 | }, | |
| 1501 | .elf => {}, // TODO | |
| 1502 | else => unreachable, | |
| 1503 | } | |
| 1466 | while (nav_state.exprloc_relocs.popOrNull()) |reloc| { | |
| 1467 | if (self.bin_file.cast(.elf)) |elf_file| { | |
| 1468 | _ = elf_file; // TODO | |
| 1469 | } else if (self.bin_file.cast(.macho)) |macho_file| { | |
| 1470 | if (macho_file.base.isRelocatable()) { | |
| 1471 | // TODO | |
| 1472 | } else { | |
| 1473 | const d_sym = macho_file.getDebugSymbols().?; | |
| 1474 | try d_sym.relocs.append(d_sym.allocator, .{ | |
| 1475 | .type = switch (reloc.type) { | |
| 1476 | .direct_load => .direct_load, | |
| 1477 | .got_load => .got_load, | |
| 1478 | }, | |
| 1479 | .target = reloc.target, | |
| 1480 | .offset = reloc.offset + self.getAtom(.di_atom, di_atom_index).off, | |
| 1481 | .addend = 0, | |
| 1482 | }); | |
| 1483 | } | |
| 1484 | } else unreachable; | |
| 1504 | 1485 | } |
| 1505 | 1486 | |
| 1506 | try self.writeDeclDebugInfo(di_atom_index, dbg_info_buffer.items); | |
| 1487 | try self.writeNavDebugInfo(di_atom_index, dbg_info_buffer.items); | |
| 1507 | 1488 | } |
| 1508 | 1489 | |
| 1509 | fn updateDeclDebugInfoAllocation(self: *Dwarf, atom_index: Atom.Index, len: u32) !void { | |
| 1490 | fn updateNavDebugInfoAllocation(self: *Dwarf, atom_index: Atom.Index, len: u32) !void { | |
| 1510 | 1491 | const tracy = trace(@src()); |
| 1511 | 1492 | defer tracy.end(); |
| 1512 | 1493 | |
| 1513 | // This logic is nearly identical to the logic above in `updateDecl` for | |
| 1494 | // This logic is nearly identical to the logic above in `updateNav` for | |
| 1514 | 1495 | // `SrcFn` and the line number programs. If you are editing this logic, you |
| 1515 | 1496 | // probably need to edit that logic too. |
| 1516 | 1497 | const gpa = self.allocator; |
| ... | ... | @@ -1521,7 +1502,7 @@ fn updateDeclDebugInfoAllocation(self: *Dwarf, atom_index: Atom.Index, len: u32) |
| 1521 | 1502 | if (atom_index == last_index) break :blk; |
| 1522 | 1503 | if (atom.next_index) |next_index| { |
| 1523 | 1504 | const next = self.getAtomPtr(.di_atom, next_index); |
| 1524 | // Update existing Decl - non-last item. | |
| 1505 | // Update existing Nav - non-last item. | |
| 1525 | 1506 | if (atom.off + atom.len + min_nop_size > next.off) { |
| 1526 | 1507 | // It grew too big, so we move it to a new location. |
| 1527 | 1508 | if (atom.prev_index) |prev_index| { |
| ... | ... | @@ -1531,34 +1512,27 @@ fn updateDeclDebugInfoAllocation(self: *Dwarf, atom_index: Atom.Index, len: u32) |
| 1531 | 1512 | next.prev_index = atom.prev_index; |
| 1532 | 1513 | atom.next_index = null; |
| 1533 | 1514 | // Populate where it used to be with NOPs. |
| 1534 | switch (self.bin_file.tag) { | |
| 1535 | .elf => { | |
| 1536 | const elf_file = self.bin_file.cast(File.Elf).?; | |
| 1537 | const debug_info_sect = &elf_file.shdrs.items[elf_file.debug_info_section_index.?]; | |
| 1538 | const file_pos = debug_info_sect.sh_offset + atom.off; | |
| 1539 | try pwriteDbgInfoNops(elf_file.base.file.?, file_pos, 0, &[0]u8{}, atom.len, false); | |
| 1540 | }, | |
| 1541 | .macho => { | |
| 1542 | const macho_file = self.bin_file.cast(File.MachO).?; | |
| 1543 | if (macho_file.base.isRelocatable()) { | |
| 1544 | const debug_info_sect = macho_file.sections.items(.header)[macho_file.debug_info_sect_index.?]; | |
| 1545 | const file_pos = debug_info_sect.offset + atom.off; | |
| 1546 | try pwriteDbgInfoNops(macho_file.base.file.?, file_pos, 0, &[0]u8{}, atom.len, false); | |
| 1547 | } else { | |
| 1548 | const d_sym = macho_file.getDebugSymbols().?; | |
| 1549 | const debug_info_sect = d_sym.getSectionPtr(d_sym.debug_info_section_index.?); | |
| 1550 | const file_pos = debug_info_sect.offset + atom.off; | |
| 1551 | try pwriteDbgInfoNops(d_sym.file, file_pos, 0, &[0]u8{}, atom.len, false); | |
| 1552 | } | |
| 1553 | }, | |
| 1554 | .wasm => { | |
| 1555 | // const wasm_file = self.bin_file.cast(File.Wasm).?; | |
| 1556 | // const debug_info_index = wasm_file.debug_info_atom.?; | |
| 1557 | // const debug_info = &wasm_file.getAtomPtr(debug_info_index).code; | |
| 1558 | // try writeDbgInfoNopsToArrayList(gpa, debug_info, atom.off, 0, &.{0}, atom.len, false); | |
| 1559 | }, | |
| 1560 | else => unreachable, | |
| 1561 | } | |
| 1515 | if (self.bin_file.cast(.elf)) |elf_file| { | |
| 1516 | const debug_info_sect = &elf_file.shdrs.items[elf_file.debug_info_section_index.?]; | |
| 1517 | const file_pos = debug_info_sect.sh_offset + atom.off; | |
| 1518 | try pwriteDbgInfoNops(elf_file.base.file.?, file_pos, 0, &[0]u8{}, atom.len, false); | |
| 1519 | } else if (self.bin_file.cast(.macho)) |macho_file| { | |
| 1520 | if (macho_file.base.isRelocatable()) { | |
| 1521 | const debug_info_sect = macho_file.sections.items(.header)[macho_file.debug_info_sect_index.?]; | |
| 1522 | const file_pos = debug_info_sect.offset + atom.off; | |
| 1523 | try pwriteDbgInfoNops(macho_file.base.file.?, file_pos, 0, &[0]u8{}, atom.len, false); | |
| 1524 | } else { | |
| 1525 | const d_sym = macho_file.getDebugSymbols().?; | |
| 1526 | const debug_info_sect = d_sym.getSectionPtr(d_sym.debug_info_section_index.?); | |
| 1527 | const file_pos = debug_info_sect.offset + atom.off; | |
| 1528 | try pwriteDbgInfoNops(d_sym.file, file_pos, 0, &[0]u8{}, atom.len, false); | |
| 1529 | } | |
| 1530 | } else if (self.bin_file.cast(.wasm)) |wasm_file| { | |
| 1531 | _ = wasm_file; | |
| 1532 | // const debug_info_index = wasm_file.debug_info_atom.?; | |
| 1533 | // const debug_info = &wasm_file.getAtomPtr(debug_info_index).code; | |
| 1534 | // try writeDbgInfoNopsToArrayList(gpa, debug_info, atom.off, 0, &.{0}, atom.len, false); | |
| 1535 | } else unreachable; | |
| 1562 | 1536 | // TODO Look at the free list before appending at the end. |
| 1563 | 1537 | atom.prev_index = last_index; |
| 1564 | 1538 | const last = self.getAtomPtr(.di_atom, last_index); |
| ... | ... | @@ -1568,7 +1542,7 @@ fn updateDeclDebugInfoAllocation(self: *Dwarf, atom_index: Atom.Index, len: u32) |
| 1568 | 1542 | atom.off = last.off + padToIdeal(last.len); |
| 1569 | 1543 | } |
| 1570 | 1544 | } else if (atom.prev_index == null) { |
| 1571 | // Append new Decl. | |
| 1545 | // Append new Nav. | |
| 1572 | 1546 | // TODO Look at the free list before appending at the end. |
| 1573 | 1547 | atom.prev_index = last_index; |
| 1574 | 1548 | const last = self.getAtomPtr(.di_atom, last_index); |
| ... | ... | @@ -1578,7 +1552,7 @@ fn updateDeclDebugInfoAllocation(self: *Dwarf, atom_index: Atom.Index, len: u32) |
| 1578 | 1552 | atom.off = last.off + padToIdeal(last.len); |
| 1579 | 1553 | } |
| 1580 | 1554 | } else { |
| 1581 | // This is the first Decl of the .debug_info | |
| 1555 | // This is the first Nav of the .debug_info | |
| 1582 | 1556 | self.di_atom_first_index = atom_index; |
| 1583 | 1557 | self.di_atom_last_index = atom_index; |
| 1584 | 1558 | |
| ... | ... | @@ -1586,19 +1560,19 @@ fn updateDeclDebugInfoAllocation(self: *Dwarf, atom_index: Atom.Index, len: u32) |
| 1586 | 1560 | } |
| 1587 | 1561 | } |
| 1588 | 1562 | |
| 1589 | fn writeDeclDebugInfo(self: *Dwarf, atom_index: Atom.Index, dbg_info_buf: []const u8) !void { | |
| 1563 | fn writeNavDebugInfo(self: *Dwarf, atom_index: Atom.Index, dbg_info_buf: []const u8) !void { | |
| 1590 | 1564 | const tracy = trace(@src()); |
| 1591 | 1565 | defer tracy.end(); |
| 1592 | 1566 | |
| 1593 | // This logic is nearly identical to the logic above in `updateDecl` for | |
| 1567 | // This logic is nearly identical to the logic above in `updateNav` for | |
| 1594 | 1568 | // `SrcFn` and the line number programs. If you are editing this logic, you |
| 1595 | 1569 | // probably need to edit that logic too. |
| 1596 | 1570 | |
| 1597 | 1571 | const atom = self.getAtom(.di_atom, atom_index); |
| 1598 | const last_decl_index = self.di_atom_last_index.?; | |
| 1599 | const last_decl = self.getAtom(.di_atom, last_decl_index); | |
| 1600 | // +1 for a trailing zero to end the children of the decl tag. | |
| 1601 | const needed_size = last_decl.off + last_decl.len + 1; | |
| 1572 | const last_nav_index = self.di_atom_last_index.?; | |
| 1573 | const last_nav = self.getAtom(.di_atom, last_nav_index); | |
| 1574 | // +1 for a trailing zero to end the children of the nav tag. | |
| 1575 | const needed_size = last_nav.off + last_nav.len + 1; | |
| 1602 | 1576 | const prev_padding_size: u32 = if (atom.prev_index) |prev_index| blk: { |
| 1603 | 1577 | const prev = self.getAtom(.di_atom, prev_index); |
| 1604 | 1578 | break :blk atom.off - (prev.off + prev.len); |
| ... | ... | @@ -1608,107 +1582,99 @@ fn writeDeclDebugInfo(self: *Dwarf, atom_index: Atom.Index, dbg_info_buf: []cons |
| 1608 | 1582 | break :blk next.off - (atom.off + atom.len); |
| 1609 | 1583 | } else 0; |
| 1610 | 1584 | |
| 1611 | // To end the children of the decl tag. | |
| 1585 | // To end the children of the nav tag. | |
| 1612 | 1586 | const trailing_zero = atom.next_index == null; |
| 1613 | 1587 | |
| 1614 | 1588 | // We only have support for one compilation unit so far, so the offsets are directly |
| 1615 | 1589 | // from the .debug_info section. |
| 1616 | switch (self.bin_file.tag) { | |
| 1617 | .elf => { | |
| 1618 | const elf_file = self.bin_file.cast(File.Elf).?; | |
| 1619 | const shdr_index = elf_file.debug_info_section_index.?; | |
| 1620 | try elf_file.growNonAllocSection(shdr_index, needed_size, 1, true); | |
| 1621 | const debug_info_sect = &elf_file.shdrs.items[shdr_index]; | |
| 1622 | const file_pos = debug_info_sect.sh_offset + atom.off; | |
| 1590 | if (self.bin_file.cast(.elf)) |elf_file| { | |
| 1591 | const shdr_index = elf_file.debug_info_section_index.?; | |
| 1592 | try elf_file.growNonAllocSection(shdr_index, needed_size, 1, true); | |
| 1593 | const debug_info_sect = &elf_file.shdrs.items[shdr_index]; | |
| 1594 | const file_pos = debug_info_sect.sh_offset + atom.off; | |
| 1595 | try pwriteDbgInfoNops( | |
| 1596 | elf_file.base.file.?, | |
| 1597 | file_pos, | |
| 1598 | prev_padding_size, | |
| 1599 | dbg_info_buf, | |
| 1600 | next_padding_size, | |
| 1601 | trailing_zero, | |
| 1602 | ); | |
| 1603 | } else if (self.bin_file.cast(.macho)) |macho_file| { | |
| 1604 | if (macho_file.base.isRelocatable()) { | |
| 1605 | const sect_index = macho_file.debug_info_sect_index.?; | |
| 1606 | try macho_file.growSection(sect_index, needed_size); | |
| 1607 | const sect = macho_file.sections.items(.header)[sect_index]; | |
| 1608 | const file_pos = sect.offset + atom.off; | |
| 1623 | 1609 | try pwriteDbgInfoNops( |
| 1624 | elf_file.base.file.?, | |
| 1610 | macho_file.base.file.?, | |
| 1625 | 1611 | file_pos, |
| 1626 | 1612 | prev_padding_size, |
| 1627 | 1613 | dbg_info_buf, |
| 1628 | 1614 | next_padding_size, |
| 1629 | 1615 | trailing_zero, |
| 1630 | 1616 | ); |
| 1631 | }, | |
| 1632 | ||
| 1633 | .macho => { | |
| 1634 | const macho_file = self.bin_file.cast(File.MachO).?; | |
| 1635 | if (macho_file.base.isRelocatable()) { | |
| 1636 | const sect_index = macho_file.debug_info_sect_index.?; | |
| 1637 | try macho_file.growSection(sect_index, needed_size); | |
| 1638 | const sect = macho_file.sections.items(.header)[sect_index]; | |
| 1639 | const file_pos = sect.offset + atom.off; | |
| 1640 | try pwriteDbgInfoNops( | |
| 1641 | macho_file.base.file.?, | |
| 1642 | file_pos, | |
| 1643 | prev_padding_size, | |
| 1644 | dbg_info_buf, | |
| 1645 | next_padding_size, | |
| 1646 | trailing_zero, | |
| 1647 | ); | |
| 1648 | } else { | |
| 1649 | const d_sym = macho_file.getDebugSymbols().?; | |
| 1650 | const sect_index = d_sym.debug_info_section_index.?; | |
| 1651 | try d_sym.growSection(sect_index, needed_size, true, macho_file); | |
| 1652 | const sect = d_sym.getSection(sect_index); | |
| 1653 | const file_pos = sect.offset + atom.off; | |
| 1654 | try pwriteDbgInfoNops( | |
| 1655 | d_sym.file, | |
| 1656 | file_pos, | |
| 1657 | prev_padding_size, | |
| 1658 | dbg_info_buf, | |
| 1659 | next_padding_size, | |
| 1660 | trailing_zero, | |
| 1661 | ); | |
| 1662 | } | |
| 1663 | }, | |
| 1664 | ||
| 1665 | .wasm => { | |
| 1666 | // const wasm_file = self.bin_file.cast(File.Wasm).?; | |
| 1667 | // const info_atom = wasm_file.debug_info_atom.?; | |
| 1668 | // const debug_info = &wasm_file.getAtomPtr(info_atom).code; | |
| 1669 | // const segment_size = debug_info.items.len; | |
| 1670 | // if (needed_size != segment_size) { | |
| 1671 | // log.debug(" needed size does not equal allocated size: {d}", .{needed_size}); | |
| 1672 | // if (needed_size > segment_size) { | |
| 1673 | // log.debug(" allocating {d} bytes for 'debug info' information", .{needed_size - segment_size}); | |
| 1674 | // try debug_info.resize(self.allocator, needed_size); | |
| 1675 | // @memset(debug_info.items[segment_size..], 0); | |
| 1676 | // } | |
| 1677 | // debug_info.items.len = needed_size; | |
| 1678 | // } | |
| 1679 | // log.debug(" writeDbgInfoNopsToArrayList debug_info_len={d} offset={d} content_len={d} next_padding_size={d}", .{ | |
| 1680 | // debug_info.items.len, atom.off, dbg_info_buf.len, next_padding_size, | |
| 1681 | // }); | |
| 1682 | // try writeDbgInfoNopsToArrayList( | |
| 1683 | // gpa, | |
| 1684 | // debug_info, | |
| 1685 | // atom.off, | |
| 1686 | // prev_padding_size, | |
| 1687 | // dbg_info_buf, | |
| 1688 | // next_padding_size, | |
| 1689 | // trailing_zero, | |
| 1690 | // ); | |
| 1691 | }, | |
| 1692 | else => unreachable, | |
| 1693 | } | |
| 1617 | } else { | |
| 1618 | const d_sym = macho_file.getDebugSymbols().?; | |
| 1619 | const sect_index = d_sym.debug_info_section_index.?; | |
| 1620 | try d_sym.growSection(sect_index, needed_size, true, macho_file); | |
| 1621 | const sect = d_sym.getSection(sect_index); | |
| 1622 | const file_pos = sect.offset + atom.off; | |
| 1623 | try pwriteDbgInfoNops( | |
| 1624 | d_sym.file, | |
| 1625 | file_pos, | |
| 1626 | prev_padding_size, | |
| 1627 | dbg_info_buf, | |
| 1628 | next_padding_size, | |
| 1629 | trailing_zero, | |
| 1630 | ); | |
| 1631 | } | |
| 1632 | } else if (self.bin_file.cast(.wasm)) |wasm_file| { | |
| 1633 | _ = wasm_file; | |
| 1634 | // const info_atom = wasm_file.debug_info_atom.?; | |
| 1635 | // const debug_info = &wasm_file.getAtomPtr(info_atom).code; | |
| 1636 | // const segment_size = debug_info.items.len; | |
| 1637 | // if (needed_size != segment_size) { | |
| 1638 | // log.debug(" needed size does not equal allocated size: {d}", .{needed_size}); | |
| 1639 | // if (needed_size > segment_size) { | |
| 1640 | // log.debug(" allocating {d} bytes for 'debug info' information", .{needed_size - segment_size}); | |
| 1641 | // try debug_info.resize(self.allocator, needed_size); | |
| 1642 | // @memset(debug_info.items[segment_size..], 0); | |
| 1643 | // } | |
| 1644 | // debug_info.items.len = needed_size; | |
| 1645 | // } | |
| 1646 | // log.debug(" writeDbgInfoNopsToArrayList debug_info_len={d} offset={d} content_len={d} next_padding_size={d}", .{ | |
| 1647 | // debug_info.items.len, atom.off, dbg_info_buf.len, next_padding_size, | |
| 1648 | // }); | |
| 1649 | // try writeDbgInfoNopsToArrayList( | |
| 1650 | // gpa, | |
| 1651 | // debug_info, | |
| 1652 | // atom.off, | |
| 1653 | // prev_padding_size, | |
| 1654 | // dbg_info_buf, | |
| 1655 | // next_padding_size, | |
| 1656 | // trailing_zero, | |
| 1657 | // ); | |
| 1658 | } else unreachable; | |
| 1694 | 1659 | } |
| 1695 | 1660 | |
| 1696 | pub fn updateDeclLineNumber(self: *Dwarf, zcu: *Zcu, decl_index: InternPool.DeclIndex) !void { | |
| 1661 | pub fn updateNavLineNumber(self: *Dwarf, zcu: *Zcu, nav_index: InternPool.Nav.Index) !void { | |
| 1697 | 1662 | const tracy = trace(@src()); |
| 1698 | 1663 | defer tracy.end(); |
| 1699 | 1664 | |
| 1700 | const atom_index = try self.getOrCreateAtomForDecl(.src_fn, decl_index); | |
| 1665 | const atom_index = try self.getOrCreateAtomForNav(.src_fn, nav_index); | |
| 1701 | 1666 | const atom = self.getAtom(.src_fn, atom_index); |
| 1702 | 1667 | if (atom.len == 0) return; |
| 1703 | 1668 | |
| 1704 | const decl = zcu.declPtr(decl_index); | |
| 1705 | const func = decl.val.getFunction(zcu).?; | |
| 1706 | log.debug("decl.src_line={d}, func.lbrace_line={d}, func.rbrace_line={d}", .{ | |
| 1707 | decl.navSrcLine(zcu), | |
| 1669 | const nav = zcu.intern_pool.getNav(nav_index); | |
| 1670 | const nav_val = Value.fromInterned(nav.status.resolved.val); | |
| 1671 | const func = nav_val.getFunction(zcu).?; | |
| 1672 | log.debug("src_line={d}, func.lbrace_line={d}, func.rbrace_line={d}", .{ | |
| 1673 | zcu.navSrcLine(nav_index), | |
| 1708 | 1674 | func.lbrace_line, |
| 1709 | 1675 | func.rbrace_line, |
| 1710 | 1676 | }); |
| 1711 | const line: u28 = @intCast(decl.navSrcLine(zcu) + func.lbrace_line); | |
| 1677 | const line: u28 = @intCast(zcu.navSrcLine(nav_index) + func.lbrace_line); | |
| 1712 | 1678 | var data: [4]u8 = undefined; |
| 1713 | 1679 | leb128.writeUnsignedFixed(4, &data, line); |
| 1714 | 1680 | |
| ... | ... | @@ -1742,11 +1708,11 @@ pub fn updateDeclLineNumber(self: *Dwarf, zcu: *Zcu, decl_index: InternPool.Decl |
| 1742 | 1708 | } |
| 1743 | 1709 | } |
| 1744 | 1710 | |
| 1745 | pub fn freeDecl(self: *Dwarf, decl_index: InternPool.DeclIndex) void { | |
| 1711 | pub fn freeNav(self: *Dwarf, nav_index: InternPool.Nav.Index) void { | |
| 1746 | 1712 | const gpa = self.allocator; |
| 1747 | 1713 | |
| 1748 | 1714 | // Free SrcFn atom |
| 1749 | if (self.src_fn_decls.fetchRemove(decl_index)) |kv| { | |
| 1715 | if (self.src_fn_navs.fetchRemove(nav_index)) |kv| { | |
| 1750 | 1716 | const src_fn_index = kv.value; |
| 1751 | 1717 | const src_fn = self.getAtom(.src_fn, src_fn_index); |
| 1752 | 1718 | _ = self.src_fn_free_list.remove(src_fn_index); |
| ... | ... | @@ -1773,7 +1739,7 @@ pub fn freeDecl(self: *Dwarf, decl_index: InternPool.DeclIndex) void { |
| 1773 | 1739 | } |
| 1774 | 1740 | |
| 1775 | 1741 | // Free DI atom |
| 1776 | if (self.di_atom_decls.fetchRemove(decl_index)) |kv| { | |
| 1742 | if (self.di_atom_navs.fetchRemove(nav_index)) |kv| { | |
| 1777 | 1743 | const di_atom_index = kv.value; |
| 1778 | 1744 | const di_atom = self.getAtomPtr(.di_atom, di_atom_index); |
| 1779 | 1745 | |
| ... | ... | @@ -1930,40 +1896,33 @@ pub fn writeDbgAbbrev(self: *Dwarf) !void { |
| 1930 | 1896 | self.abbrev_table_offset = abbrev_offset; |
| 1931 | 1897 | |
| 1932 | 1898 | const needed_size = abbrev_buf.len; |
| 1933 | switch (self.bin_file.tag) { | |
| 1934 | .elf => { | |
| 1935 | const elf_file = self.bin_file.cast(File.Elf).?; | |
| 1936 | const shdr_index = elf_file.debug_abbrev_section_index.?; | |
| 1937 | try elf_file.growNonAllocSection(shdr_index, needed_size, 1, false); | |
| 1938 | const debug_abbrev_sect = &elf_file.shdrs.items[shdr_index]; | |
| 1939 | const file_pos = debug_abbrev_sect.sh_offset + abbrev_offset; | |
| 1940 | try elf_file.base.file.?.pwriteAll(&abbrev_buf, file_pos); | |
| 1941 | }, | |
| 1942 | .macho => { | |
| 1943 | const macho_file = self.bin_file.cast(File.MachO).?; | |
| 1944 | if (macho_file.base.isRelocatable()) { | |
| 1945 | const sect_index = macho_file.debug_abbrev_sect_index.?; | |
| 1946 | try macho_file.growSection(sect_index, needed_size); | |
| 1947 | const sect = macho_file.sections.items(.header)[sect_index]; | |
| 1948 | const file_pos = sect.offset + abbrev_offset; | |
| 1949 | try macho_file.base.file.?.pwriteAll(&abbrev_buf, file_pos); | |
| 1950 | } else { | |
| 1951 | const d_sym = macho_file.getDebugSymbols().?; | |
| 1952 | const sect_index = d_sym.debug_abbrev_section_index.?; | |
| 1953 | try d_sym.growSection(sect_index, needed_size, false, macho_file); | |
| 1954 | const sect = d_sym.getSection(sect_index); | |
| 1955 | const file_pos = sect.offset + abbrev_offset; | |
| 1956 | try d_sym.file.pwriteAll(&abbrev_buf, file_pos); | |
| 1957 | } | |
| 1958 | }, | |
| 1959 | .wasm => { | |
| 1960 | // const wasm_file = self.bin_file.cast(File.Wasm).?; | |
| 1961 | // const debug_abbrev = &wasm_file.getAtomPtr(wasm_file.debug_abbrev_atom.?).code; | |
| 1962 | // try debug_abbrev.resize(gpa, needed_size); | |
| 1963 | // debug_abbrev.items[0..abbrev_buf.len].* = abbrev_buf; | |
| 1964 | }, | |
| 1965 | else => unreachable, | |
| 1966 | } | |
| 1899 | if (self.bin_file.cast(.elf)) |elf_file| { | |
| 1900 | const shdr_index = elf_file.debug_abbrev_section_index.?; | |
| 1901 | try elf_file.growNonAllocSection(shdr_index, needed_size, 1, false); | |
| 1902 | const debug_abbrev_sect = &elf_file.shdrs.items[shdr_index]; | |
| 1903 | const file_pos = debug_abbrev_sect.sh_offset + abbrev_offset; | |
| 1904 | try elf_file.base.file.?.pwriteAll(&abbrev_buf, file_pos); | |
| 1905 | } else if (self.bin_file.cast(.macho)) |macho_file| { | |
| 1906 | if (macho_file.base.isRelocatable()) { | |
| 1907 | const sect_index = macho_file.debug_abbrev_sect_index.?; | |
| 1908 | try macho_file.growSection(sect_index, needed_size); | |
| 1909 | const sect = macho_file.sections.items(.header)[sect_index]; | |
| 1910 | const file_pos = sect.offset + abbrev_offset; | |
| 1911 | try macho_file.base.file.?.pwriteAll(&abbrev_buf, file_pos); | |
| 1912 | } else { | |
| 1913 | const d_sym = macho_file.getDebugSymbols().?; | |
| 1914 | const sect_index = d_sym.debug_abbrev_section_index.?; | |
| 1915 | try d_sym.growSection(sect_index, needed_size, false, macho_file); | |
| 1916 | const sect = d_sym.getSection(sect_index); | |
| 1917 | const file_pos = sect.offset + abbrev_offset; | |
| 1918 | try d_sym.file.pwriteAll(&abbrev_buf, file_pos); | |
| 1919 | } | |
| 1920 | } else if (self.bin_file.cast(.wasm)) |wasm_file| { | |
| 1921 | _ = wasm_file; | |
| 1922 | // const debug_abbrev = &wasm_file.getAtomPtr(wasm_file.debug_abbrev_atom.?).code; | |
| 1923 | // try debug_abbrev.resize(gpa, needed_size); | |
| 1924 | // debug_abbrev.items[0..abbrev_buf.len].* = abbrev_buf; | |
| 1925 | } else unreachable; | |
| 1967 | 1926 | } |
| 1968 | 1927 | |
| 1969 | 1928 | fn dbgInfoHeaderBytes(self: *Dwarf) usize { |
| ... | ... | @@ -2027,37 +1986,30 @@ pub fn writeDbgInfoHeader(self: *Dwarf, zcu: *Zcu, low_pc: u64, high_pc: u64) !v |
| 2027 | 1986 | mem.writeInt(u16, di_buf.addManyAsArrayAssumeCapacity(2), DW.LANG.C99, target_endian); |
| 2028 | 1987 | |
| 2029 | 1988 | if (di_buf.items.len > first_dbg_info_off) { |
| 2030 | // Move the first N decls to the end to make more padding for the header. | |
| 1989 | // Move the first N navs to the end to make more padding for the header. | |
| 2031 | 1990 | @panic("TODO: handle .debug_info header exceeding its padding"); |
| 2032 | 1991 | } |
| 2033 | 1992 | const jmp_amt = first_dbg_info_off - di_buf.items.len; |
| 2034 | switch (self.bin_file.tag) { | |
| 2035 | .elf => { | |
| 2036 | const elf_file = self.bin_file.cast(File.Elf).?; | |
| 2037 | const debug_info_sect = &elf_file.shdrs.items[elf_file.debug_info_section_index.?]; | |
| 2038 | const file_pos = debug_info_sect.sh_offset; | |
| 2039 | try pwriteDbgInfoNops(elf_file.base.file.?, file_pos, 0, di_buf.items, jmp_amt, false); | |
| 2040 | }, | |
| 2041 | .macho => { | |
| 2042 | const macho_file = self.bin_file.cast(File.MachO).?; | |
| 2043 | if (macho_file.base.isRelocatable()) { | |
| 2044 | const debug_info_sect = macho_file.sections.items(.header)[macho_file.debug_info_sect_index.?]; | |
| 2045 | const file_pos = debug_info_sect.offset; | |
| 2046 | try pwriteDbgInfoNops(macho_file.base.file.?, file_pos, 0, di_buf.items, jmp_amt, false); | |
| 2047 | } else { | |
| 2048 | const d_sym = macho_file.getDebugSymbols().?; | |
| 2049 | const debug_info_sect = d_sym.getSection(d_sym.debug_info_section_index.?); | |
| 2050 | const file_pos = debug_info_sect.offset; | |
| 2051 | try pwriteDbgInfoNops(d_sym.file, file_pos, 0, di_buf.items, jmp_amt, false); | |
| 2052 | } | |
| 2053 | }, | |
| 2054 | .wasm => { | |
| 2055 | // const wasm_file = self.bin_file.cast(File.Wasm).?; | |
| 2056 | // const debug_info = &wasm_file.getAtomPtr(wasm_file.debug_info_atom.?).code; | |
| 2057 | // try writeDbgInfoNopsToArrayList(self.allocator, debug_info, 0, 0, di_buf.items, jmp_amt, false); | |
| 2058 | }, | |
| 2059 | else => unreachable, | |
| 2060 | } | |
| 1993 | if (self.bin_file.cast(.elf)) |elf_file| { | |
| 1994 | const debug_info_sect = &elf_file.shdrs.items[elf_file.debug_info_section_index.?]; | |
| 1995 | const file_pos = debug_info_sect.sh_offset; | |
| 1996 | try pwriteDbgInfoNops(elf_file.base.file.?, file_pos, 0, di_buf.items, jmp_amt, false); | |
| 1997 | } else if (self.bin_file.cast(.macho)) |macho_file| { | |
| 1998 | if (macho_file.base.isRelocatable()) { | |
| 1999 | const debug_info_sect = macho_file.sections.items(.header)[macho_file.debug_info_sect_index.?]; | |
| 2000 | const file_pos = debug_info_sect.offset; | |
| 2001 | try pwriteDbgInfoNops(macho_file.base.file.?, file_pos, 0, di_buf.items, jmp_amt, false); | |
| 2002 | } else { | |
| 2003 | const d_sym = macho_file.getDebugSymbols().?; | |
| 2004 | const debug_info_sect = d_sym.getSection(d_sym.debug_info_section_index.?); | |
| 2005 | const file_pos = debug_info_sect.offset; | |
| 2006 | try pwriteDbgInfoNops(d_sym.file, file_pos, 0, di_buf.items, jmp_amt, false); | |
| 2007 | } | |
| 2008 | } else if (self.bin_file.cast(.wasm)) |wasm_file| { | |
| 2009 | _ = wasm_file; | |
| 2010 | // const debug_info = &wasm_file.getAtomPtr(wasm_file.debug_info_atom.?).code; | |
| 2011 | // try writeDbgInfoNopsToArrayList(self.allocator, debug_info, 0, 0, di_buf.items, jmp_amt, false); | |
| 2012 | } else unreachable; | |
| 2061 | 2013 | } |
| 2062 | 2014 | |
| 2063 | 2015 | fn resolveCompilationDir(zcu: *Zcu, buffer: *[std.fs.max_path_bytes]u8) []const u8 { |
| ... | ... | @@ -2360,40 +2312,33 @@ pub fn writeDbgAranges(self: *Dwarf, addr: u64, size: u64) !void { |
| 2360 | 2312 | } |
| 2361 | 2313 | |
| 2362 | 2314 | const needed_size: u32 = @intCast(di_buf.items.len); |
| 2363 | switch (self.bin_file.tag) { | |
| 2364 | .elf => { | |
| 2365 | const elf_file = self.bin_file.cast(File.Elf).?; | |
| 2366 | const shdr_index = elf_file.debug_aranges_section_index.?; | |
| 2367 | try elf_file.growNonAllocSection(shdr_index, needed_size, 16, false); | |
| 2368 | const debug_aranges_sect = &elf_file.shdrs.items[shdr_index]; | |
| 2369 | const file_pos = debug_aranges_sect.sh_offset; | |
| 2370 | try elf_file.base.file.?.pwriteAll(di_buf.items, file_pos); | |
| 2371 | }, | |
| 2372 | .macho => { | |
| 2373 | const macho_file = self.bin_file.cast(File.MachO).?; | |
| 2374 | if (macho_file.base.isRelocatable()) { | |
| 2375 | const sect_index = macho_file.debug_aranges_sect_index.?; | |
| 2376 | try macho_file.growSection(sect_index, needed_size); | |
| 2377 | const sect = macho_file.sections.items(.header)[sect_index]; | |
| 2378 | const file_pos = sect.offset; | |
| 2379 | try macho_file.base.file.?.pwriteAll(di_buf.items, file_pos); | |
| 2380 | } else { | |
| 2381 | const d_sym = macho_file.getDebugSymbols().?; | |
| 2382 | const sect_index = d_sym.debug_aranges_section_index.?; | |
| 2383 | try d_sym.growSection(sect_index, needed_size, false, macho_file); | |
| 2384 | const sect = d_sym.getSection(sect_index); | |
| 2385 | const file_pos = sect.offset; | |
| 2386 | try d_sym.file.pwriteAll(di_buf.items, file_pos); | |
| 2387 | } | |
| 2388 | }, | |
| 2389 | .wasm => { | |
| 2390 | // const wasm_file = self.bin_file.cast(File.Wasm).?; | |
| 2391 | // const debug_ranges = &wasm_file.getAtomPtr(wasm_file.debug_ranges_atom.?).code; | |
| 2392 | // try debug_ranges.resize(gpa, needed_size); | |
| 2393 | // @memcpy(debug_ranges.items[0..di_buf.items.len], di_buf.items); | |
| 2394 | }, | |
| 2395 | else => unreachable, | |
| 2396 | } | |
| 2315 | if (self.bin_file.cast(.elf)) |elf_file| { | |
| 2316 | const shdr_index = elf_file.debug_aranges_section_index.?; | |
| 2317 | try elf_file.growNonAllocSection(shdr_index, needed_size, 16, false); | |
| 2318 | const debug_aranges_sect = &elf_file.shdrs.items[shdr_index]; | |
| 2319 | const file_pos = debug_aranges_sect.sh_offset; | |
| 2320 | try elf_file.base.file.?.pwriteAll(di_buf.items, file_pos); | |
| 2321 | } else if (self.bin_file.cast(.macho)) |macho_file| { | |
| 2322 | if (macho_file.base.isRelocatable()) { | |
| 2323 | const sect_index = macho_file.debug_aranges_sect_index.?; | |
| 2324 | try macho_file.growSection(sect_index, needed_size); | |
| 2325 | const sect = macho_file.sections.items(.header)[sect_index]; | |
| 2326 | const file_pos = sect.offset; | |
| 2327 | try macho_file.base.file.?.pwriteAll(di_buf.items, file_pos); | |
| 2328 | } else { | |
| 2329 | const d_sym = macho_file.getDebugSymbols().?; | |
| 2330 | const sect_index = d_sym.debug_aranges_section_index.?; | |
| 2331 | try d_sym.growSection(sect_index, needed_size, false, macho_file); | |
| 2332 | const sect = d_sym.getSection(sect_index); | |
| 2333 | const file_pos = sect.offset; | |
| 2334 | try d_sym.file.pwriteAll(di_buf.items, file_pos); | |
| 2335 | } | |
| 2336 | } else if (self.bin_file.cast(.wasm)) |wasm_file| { | |
| 2337 | _ = wasm_file; | |
| 2338 | // const debug_ranges = &wasm_file.getAtomPtr(wasm_file.debug_ranges_atom.?).code; | |
| 2339 | // try debug_ranges.resize(gpa, needed_size); | |
| 2340 | // @memcpy(debug_ranges.items[0..di_buf.items.len], di_buf.items); | |
| 2341 | } else unreachable; | |
| 2397 | 2342 | } |
| 2398 | 2343 | |
| 2399 | 2344 | pub fn writeDbgLineHeader(self: *Dwarf) !void { |
| ... | ... | @@ -2502,60 +2447,52 @@ pub fn writeDbgLineHeader(self: *Dwarf) !void { |
| 2502 | 2447 | |
| 2503 | 2448 | var src_fn_index = first_fn_index; |
| 2504 | 2449 | |
| 2505 | var buffer = try gpa.alloc(u8, last_fn.off + last_fn.len - first_fn.off); | |
| 2450 | const buffer = try gpa.alloc(u8, last_fn.off + last_fn.len - first_fn.off); | |
| 2506 | 2451 | defer gpa.free(buffer); |
| 2507 | 2452 | |
| 2508 | switch (self.bin_file.tag) { | |
| 2509 | .elf => { | |
| 2510 | const elf_file = self.bin_file.cast(File.Elf).?; | |
| 2511 | const shdr_index = elf_file.debug_line_section_index.?; | |
| 2512 | const needed_size = elf_file.shdrs.items[shdr_index].sh_size + delta; | |
| 2513 | try elf_file.growNonAllocSection(shdr_index, needed_size, 1, true); | |
| 2514 | const file_pos = elf_file.shdrs.items[shdr_index].sh_offset + first_fn.off; | |
| 2453 | if (self.bin_file.cast(.elf)) |elf_file| { | |
| 2454 | const shdr_index = elf_file.debug_line_section_index.?; | |
| 2455 | const needed_size = elf_file.shdrs.items[shdr_index].sh_size + delta; | |
| 2456 | try elf_file.growNonAllocSection(shdr_index, needed_size, 1, true); | |
| 2457 | const file_pos = elf_file.shdrs.items[shdr_index].sh_offset + first_fn.off; | |
| 2515 | 2458 | |
| 2516 | const amt = try elf_file.base.file.?.preadAll(buffer, file_pos); | |
| 2517 | if (amt != buffer.len) return error.InputOutput; | |
| 2459 | const amt = try elf_file.base.file.?.preadAll(buffer, file_pos); | |
| 2460 | if (amt != buffer.len) return error.InputOutput; | |
| 2518 | 2461 | |
| 2519 | try elf_file.base.file.?.pwriteAll(buffer, file_pos + delta); | |
| 2520 | }, | |
| 2521 | .macho => { | |
| 2522 | const macho_file = self.bin_file.cast(File.MachO).?; | |
| 2523 | if (macho_file.base.isRelocatable()) { | |
| 2524 | const sect_index = macho_file.debug_line_sect_index.?; | |
| 2525 | const needed_size: u32 = @intCast(macho_file.sections.items(.header)[sect_index].size + delta); | |
| 2526 | try macho_file.growSection(sect_index, needed_size); | |
| 2527 | const file_pos = macho_file.sections.items(.header)[sect_index].offset + first_fn.off; | |
| 2462 | try elf_file.base.file.?.pwriteAll(buffer, file_pos + delta); | |
| 2463 | } else if (self.bin_file.cast(.macho)) |macho_file| { | |
| 2464 | if (macho_file.base.isRelocatable()) { | |
| 2465 | const sect_index = macho_file.debug_line_sect_index.?; | |
| 2466 | const needed_size: u32 = @intCast(macho_file.sections.items(.header)[sect_index].size + delta); | |
| 2467 | try macho_file.growSection(sect_index, needed_size); | |
| 2468 | const file_pos = macho_file.sections.items(.header)[sect_index].offset + first_fn.off; | |
| 2528 | 2469 | |
| 2529 | const amt = try macho_file.base.file.?.preadAll(buffer, file_pos); | |
| 2530 | if (amt != buffer.len) return error.InputOutput; | |
| 2470 | const amt = try macho_file.base.file.?.preadAll(buffer, file_pos); | |
| 2471 | if (amt != buffer.len) return error.InputOutput; | |
| 2531 | 2472 | |
| 2532 | try macho_file.base.file.?.pwriteAll(buffer, file_pos + delta); | |
| 2533 | } else { | |
| 2534 | const d_sym = macho_file.getDebugSymbols().?; | |
| 2535 | const sect_index = d_sym.debug_line_section_index.?; | |
| 2536 | const needed_size: u32 = @intCast(d_sym.getSection(sect_index).size + delta); | |
| 2537 | try d_sym.growSection(sect_index, needed_size, true, macho_file); | |
| 2538 | const file_pos = d_sym.getSection(sect_index).offset + first_fn.off; | |
| 2473 | try macho_file.base.file.?.pwriteAll(buffer, file_pos + delta); | |
| 2474 | } else { | |
| 2475 | const d_sym = macho_file.getDebugSymbols().?; | |
| 2476 | const sect_index = d_sym.debug_line_section_index.?; | |
| 2477 | const needed_size: u32 = @intCast(d_sym.getSection(sect_index).size + delta); | |
| 2478 | try d_sym.growSection(sect_index, needed_size, true, macho_file); | |
| 2479 | const file_pos = d_sym.getSection(sect_index).offset + first_fn.off; | |
| 2539 | 2480 | |
| 2540 | const amt = try d_sym.file.preadAll(buffer, file_pos); | |
| 2541 | if (amt != buffer.len) return error.InputOutput; | |
| 2481 | const amt = try d_sym.file.preadAll(buffer, file_pos); | |
| 2482 | if (amt != buffer.len) return error.InputOutput; | |
| 2542 | 2483 | |
| 2543 | try d_sym.file.pwriteAll(buffer, file_pos + delta); | |
| 2544 | } | |
| 2545 | }, | |
| 2546 | .wasm => { | |
| 2547 | _ = &buffer; | |
| 2548 | // const wasm_file = self.bin_file.cast(File.Wasm).?; | |
| 2549 | // const debug_line = &wasm_file.getAtomPtr(wasm_file.debug_line_atom.?).code; | |
| 2550 | // { | |
| 2551 | // const src = debug_line.items[first_fn.off..]; | |
| 2552 | // @memcpy(buffer[0..src.len], src); | |
| 2553 | // } | |
| 2554 | // try debug_line.resize(self.allocator, debug_line.items.len + delta); | |
| 2555 | // @memcpy(debug_line.items[first_fn.off + delta ..][0..buffer.len], buffer); | |
| 2556 | }, | |
| 2557 | else => unreachable, | |
| 2558 | } | |
| 2484 | try d_sym.file.pwriteAll(buffer, file_pos + delta); | |
| 2485 | } | |
| 2486 | } else if (self.bin_file.cast(.wasm)) |wasm_file| { | |
| 2487 | _ = wasm_file; | |
| 2488 | // const debug_line = &wasm_file.getAtomPtr(wasm_file.debug_line_atom.?).code; | |
| 2489 | // { | |
| 2490 | // const src = debug_line.items[first_fn.off..]; | |
| 2491 | // @memcpy(buffer[0..src.len], src); | |
| 2492 | // } | |
| 2493 | // try debug_line.resize(self.allocator, debug_line.items.len + delta); | |
| 2494 | // @memcpy(debug_line.items[first_fn.off + delta ..][0..buffer.len], buffer); | |
| 2495 | } else unreachable; | |
| 2559 | 2496 | |
| 2560 | 2497 | while (true) { |
| 2561 | 2498 | const src_fn = self.getAtomPtr(.src_fn, src_fn_index); |
| ... | ... | @@ -2580,33 +2517,26 @@ pub fn writeDbgLineHeader(self: *Dwarf) !void { |
| 2580 | 2517 | |
| 2581 | 2518 | // We use NOPs because consumers empirically do not respect the header length field. |
| 2582 | 2519 | const jmp_amt = self.getDebugLineProgramOff().? - di_buf.items.len; |
| 2583 | switch (self.bin_file.tag) { | |
| 2584 | .elf => { | |
| 2585 | const elf_file = self.bin_file.cast(File.Elf).?; | |
| 2586 | const debug_line_sect = &elf_file.shdrs.items[elf_file.debug_line_section_index.?]; | |
| 2587 | const file_pos = debug_line_sect.sh_offset; | |
| 2588 | try pwriteDbgLineNops(elf_file.base.file.?, file_pos, 0, di_buf.items, jmp_amt); | |
| 2589 | }, | |
| 2590 | .macho => { | |
| 2591 | const macho_file = self.bin_file.cast(File.MachO).?; | |
| 2592 | if (macho_file.base.isRelocatable()) { | |
| 2593 | const debug_line_sect = macho_file.sections.items(.header)[macho_file.debug_line_sect_index.?]; | |
| 2594 | const file_pos = debug_line_sect.offset; | |
| 2595 | try pwriteDbgLineNops(macho_file.base.file.?, file_pos, 0, di_buf.items, jmp_amt); | |
| 2596 | } else { | |
| 2597 | const d_sym = macho_file.getDebugSymbols().?; | |
| 2598 | const debug_line_sect = d_sym.getSection(d_sym.debug_line_section_index.?); | |
| 2599 | const file_pos = debug_line_sect.offset; | |
| 2600 | try pwriteDbgLineNops(d_sym.file, file_pos, 0, di_buf.items, jmp_amt); | |
| 2601 | } | |
| 2602 | }, | |
| 2603 | .wasm => { | |
| 2604 | // const wasm_file = self.bin_file.cast(File.Wasm).?; | |
| 2605 | // const debug_line = &wasm_file.getAtomPtr(wasm_file.debug_line_atom.?).code; | |
| 2606 | // writeDbgLineNopsBuffered(debug_line.items, 0, 0, di_buf.items, jmp_amt); | |
| 2607 | }, | |
| 2608 | else => unreachable, | |
| 2609 | } | |
| 2520 | if (self.bin_file.cast(.elf)) |elf_file| { | |
| 2521 | const debug_line_sect = &elf_file.shdrs.items[elf_file.debug_line_section_index.?]; | |
| 2522 | const file_pos = debug_line_sect.sh_offset; | |
| 2523 | try pwriteDbgLineNops(elf_file.base.file.?, file_pos, 0, di_buf.items, jmp_amt); | |
| 2524 | } else if (self.bin_file.cast(.macho)) |macho_file| { | |
| 2525 | if (macho_file.base.isRelocatable()) { | |
| 2526 | const debug_line_sect = macho_file.sections.items(.header)[macho_file.debug_line_sect_index.?]; | |
| 2527 | const file_pos = debug_line_sect.offset; | |
| 2528 | try pwriteDbgLineNops(macho_file.base.file.?, file_pos, 0, di_buf.items, jmp_amt); | |
| 2529 | } else { | |
| 2530 | const d_sym = macho_file.getDebugSymbols().?; | |
| 2531 | const debug_line_sect = d_sym.getSection(d_sym.debug_line_section_index.?); | |
| 2532 | const file_pos = debug_line_sect.offset; | |
| 2533 | try pwriteDbgLineNops(d_sym.file, file_pos, 0, di_buf.items, jmp_amt); | |
| 2534 | } | |
| 2535 | } else if (self.bin_file.cast(.wasm)) |wasm_file| { | |
| 2536 | _ = wasm_file; | |
| 2537 | // const debug_line = &wasm_file.getAtomPtr(wasm_file.debug_line_atom.?).code; | |
| 2538 | // writeDbgLineNopsBuffered(debug_line.items, 0, 0, di_buf.items, jmp_amt); | |
| 2539 | } else unreachable; | |
| 2610 | 2540 | } |
| 2611 | 2541 | |
| 2612 | 2542 | fn getDebugInfoOff(self: Dwarf) ?u32 { |
| ... | ... | @@ -2704,85 +2634,66 @@ pub fn flushModule(self: *Dwarf, pt: Zcu.PerThread) !void { |
| 2704 | 2634 | ); |
| 2705 | 2635 | |
| 2706 | 2636 | const di_atom_index = try self.createAtom(.di_atom); |
| 2707 | log.debug("updateDeclDebugInfoAllocation in flushModule", .{}); | |
| 2708 | try self.updateDeclDebugInfoAllocation(di_atom_index, @intCast(dbg_info_buffer.items.len)); | |
| 2709 | log.debug("writeDeclDebugInfo in flushModule", .{}); | |
| 2710 | try self.writeDeclDebugInfo(di_atom_index, dbg_info_buffer.items); | |
| 2711 | ||
| 2712 | const file_pos = switch (self.bin_file.tag) { | |
| 2713 | .elf => pos: { | |
| 2714 | const elf_file = self.bin_file.cast(File.Elf).?; | |
| 2715 | const debug_info_sect = &elf_file.shdrs.items[elf_file.debug_info_section_index.?]; | |
| 2716 | break :pos debug_info_sect.sh_offset; | |
| 2717 | }, | |
| 2718 | .macho => pos: { | |
| 2719 | const macho_file = self.bin_file.cast(File.MachO).?; | |
| 2720 | if (macho_file.base.isRelocatable()) { | |
| 2721 | const debug_info_sect = &macho_file.sections.items(.header)[macho_file.debug_info_sect_index.?]; | |
| 2722 | break :pos debug_info_sect.offset; | |
| 2723 | } else { | |
| 2724 | const d_sym = macho_file.getDebugSymbols().?; | |
| 2725 | const debug_info_sect = d_sym.getSectionPtr(d_sym.debug_info_section_index.?); | |
| 2726 | break :pos debug_info_sect.offset; | |
| 2727 | } | |
| 2728 | }, | |
| 2637 | log.debug("updateNavDebugInfoAllocation in flushModule", .{}); | |
| 2638 | try self.updateNavDebugInfoAllocation(di_atom_index, @intCast(dbg_info_buffer.items.len)); | |
| 2639 | log.debug("writeNavDebugInfo in flushModule", .{}); | |
| 2640 | try self.writeNavDebugInfo(di_atom_index, dbg_info_buffer.items); | |
| 2641 | ||
| 2642 | const file_pos = if (self.bin_file.cast(.elf)) |elf_file| pos: { | |
| 2643 | const debug_info_sect = &elf_file.shdrs.items[elf_file.debug_info_section_index.?]; | |
| 2644 | break :pos debug_info_sect.sh_offset; | |
| 2645 | } else if (self.bin_file.cast(.macho)) |macho_file| pos: { | |
| 2646 | if (macho_file.base.isRelocatable()) { | |
| 2647 | const debug_info_sect = &macho_file.sections.items(.header)[macho_file.debug_info_sect_index.?]; | |
| 2648 | break :pos debug_info_sect.offset; | |
| 2649 | } else { | |
| 2650 | const d_sym = macho_file.getDebugSymbols().?; | |
| 2651 | const debug_info_sect = d_sym.getSectionPtr(d_sym.debug_info_section_index.?); | |
| 2652 | break :pos debug_info_sect.offset; | |
| 2653 | } | |
| 2654 | } else if (self.bin_file.cast(.wasm)) |_| | |
| 2729 | 2655 | // for wasm, the offset is always 0 as we write to memory first |
| 2730 | .wasm => 0, | |
| 2731 | else => unreachable, | |
| 2732 | }; | |
| 2656 | 0 | |
| 2657 | else | |
| 2658 | unreachable; | |
| 2733 | 2659 | |
| 2734 | 2660 | var buf: [@sizeOf(u32)]u8 = undefined; |
| 2735 | 2661 | mem.writeInt(u32, &buf, self.getAtom(.di_atom, di_atom_index).off, target.cpu.arch.endian()); |
| 2736 | 2662 | |
| 2737 | 2663 | while (self.global_abbrev_relocs.popOrNull()) |reloc| { |
| 2738 | 2664 | const atom = self.getAtom(.di_atom, reloc.atom_index); |
| 2739 | switch (self.bin_file.tag) { | |
| 2740 | .elf => { | |
| 2741 | const elf_file = self.bin_file.cast(File.Elf).?; | |
| 2742 | try elf_file.base.file.?.pwriteAll(&buf, file_pos + atom.off + reloc.offset); | |
| 2743 | }, | |
| 2744 | .macho => { | |
| 2745 | const macho_file = self.bin_file.cast(File.MachO).?; | |
| 2746 | if (macho_file.base.isRelocatable()) { | |
| 2747 | try macho_file.base.file.?.pwriteAll(&buf, file_pos + atom.off + reloc.offset); | |
| 2748 | } else { | |
| 2749 | const d_sym = macho_file.getDebugSymbols().?; | |
| 2750 | try d_sym.file.pwriteAll(&buf, file_pos + atom.off + reloc.offset); | |
| 2751 | } | |
| 2752 | }, | |
| 2753 | .wasm => { | |
| 2754 | // const wasm_file = self.bin_file.cast(File.Wasm).?; | |
| 2755 | // const debug_info = wasm_file.getAtomPtr(wasm_file.debug_info_atom.?).code; | |
| 2756 | // debug_info.items[atom.off + reloc.offset ..][0..buf.len].* = buf; | |
| 2757 | }, | |
| 2758 | else => unreachable, | |
| 2759 | } | |
| 2665 | if (self.bin_file.cast(.elf)) |elf_file| { | |
| 2666 | try elf_file.base.file.?.pwriteAll(&buf, file_pos + atom.off + reloc.offset); | |
| 2667 | } else if (self.bin_file.cast(.macho)) |macho_file| { | |
| 2668 | if (macho_file.base.isRelocatable()) { | |
| 2669 | try macho_file.base.file.?.pwriteAll(&buf, file_pos + atom.off + reloc.offset); | |
| 2670 | } else { | |
| 2671 | const d_sym = macho_file.getDebugSymbols().?; | |
| 2672 | try d_sym.file.pwriteAll(&buf, file_pos + atom.off + reloc.offset); | |
| 2673 | } | |
| 2674 | } else if (self.bin_file.cast(.wasm)) |wasm_file| { | |
| 2675 | _ = wasm_file; | |
| 2676 | // const debug_info = wasm_file.getAtomPtr(wasm_file.debug_info_atom.?).code; | |
| 2677 | // debug_info.items[atom.off + reloc.offset ..][0..buf.len].* = buf; | |
| 2678 | } else unreachable; | |
| 2760 | 2679 | } |
| 2761 | 2680 | } |
| 2762 | 2681 | } |
| 2763 | 2682 | |
| 2764 | fn addDIFile(self: *Dwarf, zcu: *Zcu, decl_index: InternPool.DeclIndex) !u28 { | |
| 2765 | const decl = zcu.declPtr(decl_index); | |
| 2766 | const file_scope = decl.getFileScope(zcu); | |
| 2683 | fn addDIFile(self: *Dwarf, zcu: *Zcu, nav_index: InternPool.Nav.Index) !u28 { | |
| 2684 | const file_scope = zcu.navFileScope(nav_index); | |
| 2767 | 2685 | const gop = try self.di_files.getOrPut(self.allocator, file_scope); |
| 2768 | 2686 | if (!gop.found_existing) { |
| 2769 | switch (self.bin_file.tag) { | |
| 2770 | .elf => { | |
| 2771 | const elf_file = self.bin_file.cast(File.Elf).?; | |
| 2772 | elf_file.markDirty(elf_file.debug_line_section_index.?); | |
| 2773 | }, | |
| 2774 | .macho => { | |
| 2775 | const macho_file = self.bin_file.cast(File.MachO).?; | |
| 2776 | if (macho_file.base.isRelocatable()) { | |
| 2777 | macho_file.markDirty(macho_file.debug_line_sect_index.?); | |
| 2778 | } else { | |
| 2779 | const d_sym = macho_file.getDebugSymbols().?; | |
| 2780 | d_sym.markDirty(d_sym.debug_line_section_index.?, macho_file); | |
| 2781 | } | |
| 2782 | }, | |
| 2783 | .wasm => {}, | |
| 2784 | else => unreachable, | |
| 2785 | } | |
| 2687 | if (self.bin_file.cast(.elf)) |elf_file| { | |
| 2688 | elf_file.markDirty(elf_file.debug_line_section_index.?); | |
| 2689 | } else if (self.bin_file.cast(.macho)) |macho_file| { | |
| 2690 | if (macho_file.base.isRelocatable()) { | |
| 2691 | macho_file.markDirty(macho_file.debug_line_sect_index.?); | |
| 2692 | } else { | |
| 2693 | const d_sym = macho_file.getDebugSymbols().?; | |
| 2694 | d_sym.markDirty(d_sym.debug_line_section_index.?, macho_file); | |
| 2695 | } | |
| 2696 | } else if (self.bin_file.cast(.wasm)) |_| {} else unreachable; | |
| 2786 | 2697 | } |
| 2787 | 2698 | return @intCast(gop.index + 1); |
| 2788 | 2699 | } |
| ... | ... | @@ -2909,17 +2820,17 @@ fn createAtom(self: *Dwarf, comptime kind: Kind) !Atom.Index { |
| 2909 | 2820 | return index; |
| 2910 | 2821 | } |
| 2911 | 2822 | |
| 2912 | fn getOrCreateAtomForDecl(self: *Dwarf, comptime kind: Kind, decl_index: InternPool.DeclIndex) !Atom.Index { | |
| 2823 | fn getOrCreateAtomForNav(self: *Dwarf, comptime kind: Kind, nav_index: InternPool.Nav.Index) !Atom.Index { | |
| 2913 | 2824 | switch (kind) { |
| 2914 | 2825 | .src_fn => { |
| 2915 | const gop = try self.src_fn_decls.getOrPut(self.allocator, decl_index); | |
| 2826 | const gop = try self.src_fn_navs.getOrPut(self.allocator, nav_index); | |
| 2916 | 2827 | if (!gop.found_existing) { |
| 2917 | 2828 | gop.value_ptr.* = try self.createAtom(kind); |
| 2918 | 2829 | } |
| 2919 | 2830 | return gop.value_ptr.*; |
| 2920 | 2831 | }, |
| 2921 | 2832 | .di_atom => { |
| 2922 | const gop = try self.di_atom_decls.getOrPut(self.allocator, decl_index); | |
| 2833 | const gop = try self.di_atom_navs.getOrPut(self.allocator, nav_index); | |
| 2923 | 2834 | if (!gop.found_existing) { |
| 2924 | 2835 | gop.value_ptr.* = try self.createAtom(kind); |
| 2925 | 2836 | } |
src/link/Elf.zig+18-22| ... | ... | @@ -478,24 +478,24 @@ pub fn deinit(self: *Elf) void { |
| 478 | 478 | self.comdat_group_sections.deinit(gpa); |
| 479 | 479 | } |
| 480 | 480 | |
| 481 | pub fn getDeclVAddr(self: *Elf, pt: Zcu.PerThread, decl_index: InternPool.DeclIndex, reloc_info: link.File.RelocInfo) !u64 { | |
| 481 | pub fn getNavVAddr(self: *Elf, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index, reloc_info: link.File.RelocInfo) !u64 { | |
| 482 | 482 | assert(self.llvm_object == null); |
| 483 | return self.zigObjectPtr().?.getDeclVAddr(self, pt, decl_index, reloc_info); | |
| 483 | return self.zigObjectPtr().?.getNavVAddr(self, pt, nav_index, reloc_info); | |
| 484 | 484 | } |
| 485 | 485 | |
| 486 | pub fn lowerAnonDecl( | |
| 486 | pub fn lowerUav( | |
| 487 | 487 | self: *Elf, |
| 488 | 488 | pt: Zcu.PerThread, |
| 489 | decl_val: InternPool.Index, | |
| 489 | uav: InternPool.Index, | |
| 490 | 490 | explicit_alignment: InternPool.Alignment, |
| 491 | 491 | src_loc: Zcu.LazySrcLoc, |
| 492 | ) !codegen.Result { | |
| 493 | return self.zigObjectPtr().?.lowerAnonDecl(self, pt, decl_val, explicit_alignment, src_loc); | |
| 492 | ) !codegen.GenResult { | |
| 493 | return self.zigObjectPtr().?.lowerUav(self, pt, uav, explicit_alignment, src_loc); | |
| 494 | 494 | } |
| 495 | 495 | |
| 496 | pub fn getAnonDeclVAddr(self: *Elf, decl_val: InternPool.Index, reloc_info: link.File.RelocInfo) !u64 { | |
| 496 | pub fn getUavVAddr(self: *Elf, uav: InternPool.Index, reloc_info: link.File.RelocInfo) !u64 { | |
| 497 | 497 | assert(self.llvm_object == null); |
| 498 | return self.zigObjectPtr().?.getAnonDeclVAddr(self, decl_val, reloc_info); | |
| 498 | return self.zigObjectPtr().?.getUavVAddr(self, uav, reloc_info); | |
| 499 | 499 | } |
| 500 | 500 | |
| 501 | 501 | /// Returns end pos of collision, if any. |
| ... | ... | @@ -2913,9 +2913,9 @@ pub fn writeElfHeader(self: *Elf) !void { |
| 2913 | 2913 | try self.base.file.?.pwriteAll(hdr_buf[0..index], 0); |
| 2914 | 2914 | } |
| 2915 | 2915 | |
| 2916 | pub fn freeDecl(self: *Elf, decl_index: InternPool.DeclIndex) void { | |
| 2917 | if (self.llvm_object) |llvm_object| return llvm_object.freeDecl(decl_index); | |
| 2918 | return self.zigObjectPtr().?.freeDecl(self, decl_index); | |
| 2916 | pub fn freeNav(self: *Elf, nav: InternPool.Nav.Index) void { | |
| 2917 | if (self.llvm_object) |llvm_object| return llvm_object.freeNav(nav); | |
| 2918 | return self.zigObjectPtr().?.freeNav(self, nav); | |
| 2919 | 2919 | } |
| 2920 | 2920 | |
| 2921 | 2921 | pub fn updateFunc(self: *Elf, pt: Zcu.PerThread, func_index: InternPool.Index, air: Air, liveness: Liveness) !void { |
| ... | ... | @@ -2926,20 +2926,16 @@ pub fn updateFunc(self: *Elf, pt: Zcu.PerThread, func_index: InternPool.Index, a |
| 2926 | 2926 | return self.zigObjectPtr().?.updateFunc(self, pt, func_index, air, liveness); |
| 2927 | 2927 | } |
| 2928 | 2928 | |
| 2929 | pub fn updateDecl( | |
| 2929 | pub fn updateNav( | |
| 2930 | 2930 | self: *Elf, |
| 2931 | 2931 | pt: Zcu.PerThread, |
| 2932 | decl_index: InternPool.DeclIndex, | |
| 2933 | ) link.File.UpdateDeclError!void { | |
| 2932 | nav: InternPool.Nav.Index, | |
| 2933 | ) link.File.UpdateNavError!void { | |
| 2934 | 2934 | if (build_options.skip_non_native and builtin.object_format != .elf) { |
| 2935 | 2935 | @panic("Attempted to compile for object format that was disabled by build configuration"); |
| 2936 | 2936 | } |
| 2937 | if (self.llvm_object) |llvm_object| return llvm_object.updateDecl(pt, decl_index); | |
| 2938 | return self.zigObjectPtr().?.updateDecl(self, pt, decl_index); | |
| 2939 | } | |
| 2940 | ||
| 2941 | pub fn lowerUnnamedConst(self: *Elf, pt: Zcu.PerThread, val: Value, decl_index: InternPool.DeclIndex) !u32 { | |
| 2942 | return self.zigObjectPtr().?.lowerUnnamedConst(self, pt, val, decl_index); | |
| 2937 | if (self.llvm_object) |llvm_object| return llvm_object.updateNav(pt, nav); | |
| 2938 | return self.zigObjectPtr().?.updateNav(self, pt, nav); | |
| 2943 | 2939 | } |
| 2944 | 2940 | |
| 2945 | 2941 | pub fn updateExports( |
| ... | ... | @@ -2955,9 +2951,9 @@ pub fn updateExports( |
| 2955 | 2951 | return self.zigObjectPtr().?.updateExports(self, pt, exported, export_indices); |
| 2956 | 2952 | } |
| 2957 | 2953 | |
| 2958 | pub fn updateDeclLineNumber(self: *Elf, pt: Zcu.PerThread, decl_index: InternPool.DeclIndex) !void { | |
| 2954 | pub fn updateNavLineNumber(self: *Elf, pt: Zcu.PerThread, nav: InternPool.Nav.Index) !void { | |
| 2959 | 2955 | if (self.llvm_object) |_| return; |
| 2960 | return self.zigObjectPtr().?.updateDeclLineNumber(pt, decl_index); | |
| 2956 | return self.zigObjectPtr().?.updateNavLineNumber(pt, nav); | |
| 2961 | 2957 | } |
| 2962 | 2958 | |
| 2963 | 2959 | pub fn deleteExport( |
src/link/Elf/ZigObject.zig+223-322| ... | ... | @@ -32,35 +32,14 @@ dwarf: ?Dwarf = null, |
| 32 | 32 | /// Table of tracked LazySymbols. |
| 33 | 33 | lazy_syms: LazySymbolTable = .{}, |
| 34 | 34 | |
| 35 | /// Table of tracked Decls. | |
| 36 | decls: DeclTable = .{}, | |
| 35 | /// Table of tracked `Nav`s. | |
| 36 | navs: NavTable = .{}, | |
| 37 | 37 | |
| 38 | 38 | /// TLS variables indexed by Atom.Index. |
| 39 | 39 | tls_variables: TlsTable = .{}, |
| 40 | 40 | |
| 41 | /// Table of unnamed constants associated with a parent `Decl`. | |
| 42 | /// We store them here so that we can free the constants whenever the `Decl` | |
| 43 | /// needs updating or is freed. | |
| 44 | /// | |
| 45 | /// For example, | |
| 46 | /// | |
| 47 | /// ```zig | |
| 48 | /// const Foo = struct{ | |
| 49 | /// a: u8, | |
| 50 | /// }; | |
| 51 | /// | |
| 52 | /// pub fn main() void { | |
| 53 | /// var foo = Foo{ .a = 1 }; | |
| 54 | /// _ = foo; | |
| 55 | /// } | |
| 56 | /// ``` | |
| 57 | /// | |
| 58 | /// value assigned to label `foo` is an unnamed constant belonging/associated | |
| 59 | /// with `Decl` `main`, and lives as long as that `Decl`. | |
| 60 | unnamed_consts: UnnamedConstTable = .{}, | |
| 61 | ||
| 62 | /// Table of tracked AnonDecls. | |
| 63 | anon_decls: AnonDeclTable = .{}, | |
| 41 | /// Table of tracked `Uav`s. | |
| 42 | uavs: UavTable = .{}, | |
| 64 | 43 | |
| 65 | 44 | debug_strtab_dirty: bool = false, |
| 66 | 45 | debug_abbrev_section_dirty: bool = false, |
| ... | ... | @@ -124,29 +103,21 @@ pub fn deinit(self: *ZigObject, allocator: Allocator) void { |
| 124 | 103 | self.relocs.deinit(allocator); |
| 125 | 104 | |
| 126 | 105 | { |
| 127 | var it = self.decls.iterator(); | |
| 106 | var it = self.navs.iterator(); | |
| 128 | 107 | while (it.next()) |entry| { |
| 129 | 108 | entry.value_ptr.exports.deinit(allocator); |
| 130 | 109 | } |
| 131 | self.decls.deinit(allocator); | |
| 110 | self.navs.deinit(allocator); | |
| 132 | 111 | } |
| 133 | 112 | |
| 134 | 113 | self.lazy_syms.deinit(allocator); |
| 135 | 114 | |
| 136 | 115 | { |
| 137 | var it = self.unnamed_consts.valueIterator(); | |
| 138 | while (it.next()) |syms| { | |
| 139 | syms.deinit(allocator); | |
| 140 | } | |
| 141 | self.unnamed_consts.deinit(allocator); | |
| 142 | } | |
| 143 | ||
| 144 | { | |
| 145 | var it = self.anon_decls.iterator(); | |
| 116 | var it = self.uavs.iterator(); | |
| 146 | 117 | while (it.next()) |entry| { |
| 147 | 118 | entry.value_ptr.exports.deinit(allocator); |
| 148 | 119 | } |
| 149 | self.anon_decls.deinit(allocator); | |
| 120 | self.uavs.deinit(allocator); | |
| 150 | 121 | } |
| 151 | 122 | |
| 152 | 123 | for (self.tls_variables.values()) |*tlv| { |
| ... | ... | @@ -161,7 +132,7 @@ pub fn deinit(self: *ZigObject, allocator: Allocator) void { |
| 161 | 132 | |
| 162 | 133 | pub fn flushModule(self: *ZigObject, elf_file: *Elf, tid: Zcu.PerThread.Id) !void { |
| 163 | 134 | // Handle any lazy symbols that were emitted by incremental compilation. |
| 164 | if (self.lazy_syms.getPtr(.none)) |metadata| { | |
| 135 | if (self.lazy_syms.getPtr(.anyerror_type)) |metadata| { | |
| 165 | 136 | const pt: Zcu.PerThread = .{ .zcu = elf_file.base.comp.module.?, .tid = tid }; |
| 166 | 137 | |
| 167 | 138 | // Most lazy symbols can be updated on first use, but |
| ... | ... | @@ -169,7 +140,7 @@ pub fn flushModule(self: *ZigObject, elf_file: *Elf, tid: Zcu.PerThread.Id) !voi |
| 169 | 140 | if (metadata.text_state != .unused) self.updateLazySymbol( |
| 170 | 141 | elf_file, |
| 171 | 142 | pt, |
| 172 | link.File.LazySymbol.initDecl(.code, null, pt.zcu), | |
| 143 | .{ .kind = .code, .ty = .anyerror_type }, | |
| 173 | 144 | metadata.text_symbol_index, |
| 174 | 145 | ) catch |err| return switch (err) { |
| 175 | 146 | error.CodegenFail => error.FlushFailure, |
| ... | ... | @@ -178,7 +149,7 @@ pub fn flushModule(self: *ZigObject, elf_file: *Elf, tid: Zcu.PerThread.Id) !voi |
| 178 | 149 | if (metadata.rodata_state != .unused) self.updateLazySymbol( |
| 179 | 150 | elf_file, |
| 180 | 151 | pt, |
| 181 | link.File.LazySymbol.initDecl(.const_data, null, pt.zcu), | |
| 152 | .{ .kind = .const_data, .ty = .anyerror_type }, | |
| 182 | 153 | metadata.rodata_symbol_index, |
| 183 | 154 | ) catch |err| return switch (err) { |
| 184 | 155 | error.CodegenFail => error.FlushFailure, |
| ... | ... | @@ -661,25 +632,25 @@ pub fn codeAlloc(self: *ZigObject, elf_file: *Elf, atom_index: Atom.Index) ![]u8 |
| 661 | 632 | return code; |
| 662 | 633 | } |
| 663 | 634 | |
| 664 | pub fn getDeclVAddr( | |
| 635 | pub fn getNavVAddr( | |
| 665 | 636 | self: *ZigObject, |
| 666 | 637 | elf_file: *Elf, |
| 667 | 638 | pt: Zcu.PerThread, |
| 668 | decl_index: InternPool.DeclIndex, | |
| 639 | nav_index: InternPool.Nav.Index, | |
| 669 | 640 | reloc_info: link.File.RelocInfo, |
| 670 | 641 | ) !u64 { |
| 671 | 642 | const zcu = pt.zcu; |
| 672 | 643 | const ip = &zcu.intern_pool; |
| 673 | const decl = zcu.declPtr(decl_index); | |
| 674 | log.debug("getDeclVAddr {}({d})", .{ decl.fqn.fmt(ip), decl_index }); | |
| 675 | const this_sym_index = if (decl.isExtern(zcu)) blk: { | |
| 676 | const name = decl.name.toSlice(ip); | |
| 677 | const lib_name = if (decl.getOwnedExternFunc(zcu)) |ext_fn| | |
| 678 | ext_fn.lib_name.toSlice(ip) | |
| 679 | else | |
| 680 | decl.getOwnedVariable(zcu).?.lib_name.toSlice(ip); | |
| 681 | break :blk try self.getGlobalSymbol(elf_file, name, lib_name); | |
| 682 | } else try self.getOrCreateMetadataForDecl(elf_file, decl_index); | |
| 644 | const nav = ip.getNav(nav_index); | |
| 645 | log.debug("getNavVAddr {}({d})", .{ nav.fqn.fmt(ip), nav_index }); | |
| 646 | const this_sym_index = switch (ip.indexToKey(nav.status.resolved.val)) { | |
| 647 | .@"extern" => |@"extern"| try self.getGlobalSymbol( | |
| 648 | elf_file, | |
| 649 | nav.name.toSlice(ip), | |
| 650 | @"extern".lib_name.toSlice(ip), | |
| 651 | ), | |
| 652 | else => try self.getOrCreateMetadataForNav(elf_file, nav_index), | |
| 653 | }; | |
| 683 | 654 | const this_sym = self.symbol(this_sym_index); |
| 684 | 655 | const vaddr = this_sym.address(.{}, elf_file); |
| 685 | 656 | const parent_atom = self.symbol(reloc_info.parent_atom_index).atom(elf_file).?; |
| ... | ... | @@ -692,13 +663,13 @@ pub fn getDeclVAddr( |
| 692 | 663 | return @intCast(vaddr); |
| 693 | 664 | } |
| 694 | 665 | |
| 695 | pub fn getAnonDeclVAddr( | |
| 666 | pub fn getUavVAddr( | |
| 696 | 667 | self: *ZigObject, |
| 697 | 668 | elf_file: *Elf, |
| 698 | decl_val: InternPool.Index, | |
| 669 | uav: InternPool.Index, | |
| 699 | 670 | reloc_info: link.File.RelocInfo, |
| 700 | 671 | ) !u64 { |
| 701 | const sym_index = self.anon_decls.get(decl_val).?.symbol_index; | |
| 672 | const sym_index = self.uavs.get(uav).?.symbol_index; | |
| 702 | 673 | const sym = self.symbol(sym_index); |
| 703 | 674 | const vaddr = sym.address(.{}, elf_file); |
| 704 | 675 | const parent_atom = self.symbol(reloc_info.parent_atom_index).atom(elf_file).?; |
| ... | ... | @@ -711,43 +682,43 @@ pub fn getAnonDeclVAddr( |
| 711 | 682 | return @intCast(vaddr); |
| 712 | 683 | } |
| 713 | 684 | |
| 714 | pub fn lowerAnonDecl( | |
| 685 | pub fn lowerUav( | |
| 715 | 686 | self: *ZigObject, |
| 716 | 687 | elf_file: *Elf, |
| 717 | 688 | pt: Zcu.PerThread, |
| 718 | decl_val: InternPool.Index, | |
| 689 | uav: InternPool.Index, | |
| 719 | 690 | explicit_alignment: InternPool.Alignment, |
| 720 | src_loc: Module.LazySrcLoc, | |
| 721 | ) !codegen.Result { | |
| 722 | const gpa = elf_file.base.comp.gpa; | |
| 723 | const mod = elf_file.base.comp.module.?; | |
| 724 | const ty = Type.fromInterned(mod.intern_pool.typeOf(decl_val)); | |
| 725 | const decl_alignment = switch (explicit_alignment) { | |
| 726 | .none => ty.abiAlignment(pt), | |
| 691 | src_loc: Zcu.LazySrcLoc, | |
| 692 | ) !codegen.GenResult { | |
| 693 | const zcu = pt.zcu; | |
| 694 | const gpa = zcu.gpa; | |
| 695 | const val = Value.fromInterned(uav); | |
| 696 | const uav_alignment = switch (explicit_alignment) { | |
| 697 | .none => val.typeOf(zcu).abiAlignment(pt), | |
| 727 | 698 | else => explicit_alignment, |
| 728 | 699 | }; |
| 729 | if (self.anon_decls.get(decl_val)) |metadata| { | |
| 730 | const existing_alignment = self.symbol(metadata.symbol_index).atom(elf_file).?.alignment; | |
| 731 | if (decl_alignment.order(existing_alignment).compare(.lte)) | |
| 732 | return .ok; | |
| 700 | if (self.uavs.get(uav)) |metadata| { | |
| 701 | const sym = self.symbol(metadata.symbol_index); | |
| 702 | const existing_alignment = sym.atom(elf_file).?.alignment; | |
| 703 | if (uav_alignment.order(existing_alignment).compare(.lte)) | |
| 704 | return .{ .mcv = .{ .load_symbol = metadata.symbol_index } }; | |
| 733 | 705 | } |
| 734 | 706 | |
| 735 | const val = Value.fromInterned(decl_val); | |
| 736 | 707 | var name_buf: [32]u8 = undefined; |
| 737 | 708 | const name = std.fmt.bufPrint(&name_buf, "__anon_{d}", .{ |
| 738 | @intFromEnum(decl_val), | |
| 709 | @intFromEnum(uav), | |
| 739 | 710 | }) catch unreachable; |
| 740 | 711 | const res = self.lowerConst( |
| 741 | 712 | elf_file, |
| 742 | 713 | pt, |
| 743 | 714 | name, |
| 744 | 715 | val, |
| 745 | decl_alignment, | |
| 716 | uav_alignment, | |
| 746 | 717 | elf_file.zig_data_rel_ro_section_index.?, |
| 747 | 718 | src_loc, |
| 748 | 719 | ) catch |err| switch (err) { |
| 749 | 720 | error.OutOfMemory => return error.OutOfMemory, |
| 750 | else => |e| return .{ .fail = try Module.ErrorMsg.create( | |
| 721 | else => |e| return .{ .fail = try Zcu.ErrorMsg.create( | |
| 751 | 722 | gpa, |
| 752 | 723 | src_loc, |
| 753 | 724 | "unable to lower constant value: {s}", |
| ... | ... | @@ -758,8 +729,8 @@ pub fn lowerAnonDecl( |
| 758 | 729 | .ok => |sym_index| sym_index, |
| 759 | 730 | .fail => |em| return .{ .fail = em }, |
| 760 | 731 | }; |
| 761 | try self.anon_decls.put(gpa, decl_val, .{ .symbol_index = sym_index }); | |
| 762 | return .ok; | |
| 732 | try self.uavs.put(gpa, uav, .{ .symbol_index = sym_index }); | |
| 733 | return .{ .mcv = .{ .load_symbol = sym_index } }; | |
| 763 | 734 | } |
| 764 | 735 | |
| 765 | 736 | pub fn getOrCreateMetadataForLazySymbol( |
| ... | ... | @@ -768,51 +739,32 @@ pub fn getOrCreateMetadataForLazySymbol( |
| 768 | 739 | pt: Zcu.PerThread, |
| 769 | 740 | lazy_sym: link.File.LazySymbol, |
| 770 | 741 | ) !Symbol.Index { |
| 771 | const mod = pt.zcu; | |
| 772 | const gpa = mod.gpa; | |
| 773 | const gop = try self.lazy_syms.getOrPut(gpa, lazy_sym.getDecl(mod)); | |
| 742 | const gop = try self.lazy_syms.getOrPut(pt.zcu.gpa, lazy_sym.ty); | |
| 774 | 743 | errdefer _ = if (!gop.found_existing) self.lazy_syms.pop(); |
| 775 | 744 | if (!gop.found_existing) gop.value_ptr.* = .{}; |
| 776 | const metadata: struct { | |
| 777 | symbol_index: *Symbol.Index, | |
| 778 | state: *LazySymbolMetadata.State, | |
| 779 | } = switch (lazy_sym.kind) { | |
| 780 | .code => .{ | |
| 781 | .symbol_index = &gop.value_ptr.text_symbol_index, | |
| 782 | .state = &gop.value_ptr.text_state, | |
| 783 | }, | |
| 784 | .const_data => .{ | |
| 785 | .symbol_index = &gop.value_ptr.rodata_symbol_index, | |
| 786 | .state = &gop.value_ptr.rodata_state, | |
| 787 | }, | |
| 745 | const symbol_index_ptr, const state_ptr = switch (lazy_sym.kind) { | |
| 746 | .code => .{ &gop.value_ptr.text_symbol_index, &gop.value_ptr.text_state }, | |
| 747 | .const_data => .{ &gop.value_ptr.rodata_symbol_index, &gop.value_ptr.rodata_state }, | |
| 788 | 748 | }; |
| 789 | switch (metadata.state.*) { | |
| 749 | switch (state_ptr.*) { | |
| 790 | 750 | .unused => { |
| 751 | const gpa = elf_file.base.comp.gpa; | |
| 791 | 752 | const symbol_index = try self.newSymbolWithAtom(gpa, 0); |
| 792 | 753 | const sym = self.symbol(symbol_index); |
| 793 | 754 | sym.flags.needs_zig_got = true; |
| 794 | metadata.symbol_index.* = symbol_index; | |
| 755 | symbol_index_ptr.* = symbol_index; | |
| 795 | 756 | }, |
| 796 | .pending_flush => return metadata.symbol_index.*, | |
| 757 | .pending_flush => return symbol_index_ptr.*, | |
| 797 | 758 | .flushed => {}, |
| 798 | 759 | } |
| 799 | metadata.state.* = .pending_flush; | |
| 800 | const symbol_index = metadata.symbol_index.*; | |
| 760 | state_ptr.* = .pending_flush; | |
| 761 | const symbol_index = symbol_index_ptr.*; | |
| 801 | 762 | // anyerror needs to be deferred until flushModule |
| 802 | if (lazy_sym.getDecl(mod) != .none) try self.updateLazySymbol(elf_file, pt, lazy_sym, symbol_index); | |
| 763 | if (lazy_sym.ty != .anyerror_type) try self.updateLazySymbol(elf_file, pt, lazy_sym, symbol_index); | |
| 803 | 764 | return symbol_index; |
| 804 | 765 | } |
| 805 | 766 | |
| 806 | fn freeUnnamedConsts(self: *ZigObject, elf_file: *Elf, decl_index: InternPool.DeclIndex) void { | |
| 807 | const gpa = elf_file.base.comp.gpa; | |
| 808 | const unnamed_consts = self.unnamed_consts.getPtr(decl_index) orelse return; | |
| 809 | for (unnamed_consts.items) |sym_index| { | |
| 810 | self.freeDeclMetadata(elf_file, sym_index); | |
| 811 | } | |
| 812 | unnamed_consts.clearAndFree(gpa); | |
| 813 | } | |
| 814 | ||
| 815 | fn freeDeclMetadata(self: *ZigObject, elf_file: *Elf, sym_index: Symbol.Index) void { | |
| 767 | fn freeNavMetadata(self: *ZigObject, elf_file: *Elf, sym_index: Symbol.Index) void { | |
| 816 | 768 | const sym = self.symbol(sym_index); |
| 817 | 769 | sym.atom(elf_file).?.free(elf_file); |
| 818 | 770 | log.debug("adding %{d} to local symbols free list", .{sym_index}); |
| ... | ... | @@ -820,38 +772,37 @@ fn freeDeclMetadata(self: *ZigObject, elf_file: *Elf, sym_index: Symbol.Index) v |
| 820 | 772 | // TODO free GOT entry here |
| 821 | 773 | } |
| 822 | 774 | |
| 823 | pub fn freeDecl(self: *ZigObject, elf_file: *Elf, decl_index: InternPool.DeclIndex) void { | |
| 775 | pub fn freeNav(self: *ZigObject, elf_file: *Elf, nav_index: InternPool.Nav.Index) void { | |
| 824 | 776 | const gpa = elf_file.base.comp.gpa; |
| 825 | 777 | |
| 826 | log.debug("freeDecl ({d})", .{decl_index}); | |
| 778 | log.debug("freeNav ({d})", .{nav_index}); | |
| 827 | 779 | |
| 828 | if (self.decls.fetchRemove(decl_index)) |const_kv| { | |
| 780 | if (self.navs.fetchRemove(nav_index)) |const_kv| { | |
| 829 | 781 | var kv = const_kv; |
| 830 | 782 | const sym_index = kv.value.symbol_index; |
| 831 | self.freeDeclMetadata(elf_file, sym_index); | |
| 832 | self.freeUnnamedConsts(elf_file, decl_index); | |
| 783 | self.freeNavMetadata(elf_file, sym_index); | |
| 833 | 784 | kv.value.exports.deinit(gpa); |
| 834 | 785 | } |
| 835 | 786 | |
| 836 | 787 | if (self.dwarf) |*dw| { |
| 837 | dw.freeDecl(decl_index); | |
| 788 | dw.freeNav(nav_index); | |
| 838 | 789 | } |
| 839 | 790 | } |
| 840 | 791 | |
| 841 | pub fn getOrCreateMetadataForDecl( | |
| 792 | pub fn getOrCreateMetadataForNav( | |
| 842 | 793 | self: *ZigObject, |
| 843 | 794 | elf_file: *Elf, |
| 844 | decl_index: InternPool.DeclIndex, | |
| 795 | nav_index: InternPool.Nav.Index, | |
| 845 | 796 | ) !Symbol.Index { |
| 846 | 797 | const gpa = elf_file.base.comp.gpa; |
| 847 | const gop = try self.decls.getOrPut(gpa, decl_index); | |
| 798 | const gop = try self.navs.getOrPut(gpa, nav_index); | |
| 848 | 799 | if (!gop.found_existing) { |
| 849 | 800 | const any_non_single_threaded = elf_file.base.comp.config.any_non_single_threaded; |
| 850 | 801 | const symbol_index = try self.newSymbolWithAtom(gpa, 0); |
| 851 | const mod = elf_file.base.comp.module.?; | |
| 852 | const decl = mod.declPtr(decl_index); | |
| 802 | const zcu = elf_file.base.comp.module.?; | |
| 803 | const nav_val = Value.fromInterned(zcu.intern_pool.getNav(nav_index).status.resolved.val); | |
| 853 | 804 | const sym = self.symbol(symbol_index); |
| 854 | if (decl.getOwnedVariable(mod)) |variable| { | |
| 805 | if (nav_val.getVariable(zcu)) |variable| { | |
| 855 | 806 | if (variable.is_threadlocal and any_non_single_threaded) { |
| 856 | 807 | sym.flags.is_tls = true; |
| 857 | 808 | } |
| ... | ... | @@ -864,89 +815,81 @@ pub fn getOrCreateMetadataForDecl( |
| 864 | 815 | return gop.value_ptr.symbol_index; |
| 865 | 816 | } |
| 866 | 817 | |
| 867 | fn getDeclShdrIndex( | |
| 818 | fn getNavShdrIndex( | |
| 868 | 819 | self: *ZigObject, |
| 869 | 820 | elf_file: *Elf, |
| 870 | decl: *const Module.Decl, | |
| 821 | zcu: *Zcu, | |
| 822 | nav_index: InternPool.Nav.Index, | |
| 871 | 823 | code: []const u8, |
| 872 | 824 | ) error{OutOfMemory}!u32 { |
| 873 | 825 | _ = self; |
| 874 | const mod = elf_file.base.comp.module.?; | |
| 826 | const ip = &zcu.intern_pool; | |
| 875 | 827 | const any_non_single_threaded = elf_file.base.comp.config.any_non_single_threaded; |
| 876 | const shdr_index = switch (decl.typeOf(mod).zigTypeTag(mod)) { | |
| 877 | .Fn => elf_file.zig_text_section_index.?, | |
| 878 | else => blk: { | |
| 879 | if (decl.getOwnedVariable(mod)) |variable| { | |
| 880 | if (variable.is_threadlocal and any_non_single_threaded) { | |
| 881 | const is_all_zeroes = for (code) |byte| { | |
| 882 | if (byte != 0) break false; | |
| 883 | } else true; | |
| 884 | if (is_all_zeroes) break :blk elf_file.sectionByName(".tbss") orelse try elf_file.addSection(.{ | |
| 885 | .type = elf.SHT_NOBITS, | |
| 886 | .flags = elf.SHF_ALLOC | elf.SHF_WRITE | elf.SHF_TLS, | |
| 887 | .name = try elf_file.insertShString(".tbss"), | |
| 888 | .offset = std.math.maxInt(u64), | |
| 889 | }); | |
| 890 | ||
| 891 | break :blk elf_file.sectionByName(".tdata") orelse try elf_file.addSection(.{ | |
| 892 | .type = elf.SHT_PROGBITS, | |
| 893 | .flags = elf.SHF_ALLOC | elf.SHF_WRITE | elf.SHF_TLS, | |
| 894 | .name = try elf_file.insertShString(".tdata"), | |
| 895 | .offset = std.math.maxInt(u64), | |
| 896 | }); | |
| 897 | } | |
| 898 | if (variable.is_const) break :blk elf_file.zig_data_rel_ro_section_index.?; | |
| 899 | if (Value.fromInterned(variable.init).isUndefDeep(mod)) { | |
| 900 | // TODO: get the optimize_mode from the Module that owns the decl instead | |
| 901 | // of using the root module here. | |
| 902 | break :blk switch (elf_file.base.comp.root_mod.optimize_mode) { | |
| 903 | .Debug, .ReleaseSafe => elf_file.zig_data_section_index.?, | |
| 904 | .ReleaseFast, .ReleaseSmall => elf_file.zig_bss_section_index.?, | |
| 905 | }; | |
| 906 | } | |
| 907 | // TODO I blatantly copied the logic from the Wasm linker, but is there a less | |
| 908 | // intrusive check for all zeroes than this? | |
| 909 | const is_all_zeroes = for (code) |byte| { | |
| 910 | if (byte != 0) break false; | |
| 911 | } else true; | |
| 912 | if (is_all_zeroes) break :blk elf_file.zig_bss_section_index.?; | |
| 913 | break :blk elf_file.zig_data_section_index.?; | |
| 914 | } | |
| 915 | break :blk elf_file.zig_data_rel_ro_section_index.?; | |
| 916 | }, | |
| 828 | const nav_val = zcu.navValue(nav_index); | |
| 829 | if (ip.isFunctionType(nav_val.typeOf(zcu).toIntern())) return elf_file.zig_text_section_index.?; | |
| 830 | const is_const, const is_threadlocal, const nav_init = switch (ip.indexToKey(nav_val.toIntern())) { | |
| 831 | .variable => |variable| .{ false, variable.is_threadlocal, variable.init }, | |
| 832 | .@"extern" => |@"extern"| .{ @"extern".is_const, @"extern".is_threadlocal, .none }, | |
| 833 | else => .{ true, false, nav_val.toIntern() }, | |
| 917 | 834 | }; |
| 918 | return shdr_index; | |
| 835 | if (any_non_single_threaded and is_threadlocal) { | |
| 836 | for (code) |byte| { | |
| 837 | if (byte != 0) break; | |
| 838 | } else return elf_file.sectionByName(".tbss") orelse try elf_file.addSection(.{ | |
| 839 | .type = elf.SHT_NOBITS, | |
| 840 | .flags = elf.SHF_ALLOC | elf.SHF_WRITE | elf.SHF_TLS, | |
| 841 | .name = try elf_file.insertShString(".tbss"), | |
| 842 | .offset = std.math.maxInt(u64), | |
| 843 | }); | |
| 844 | return elf_file.sectionByName(".tdata") orelse try elf_file.addSection(.{ | |
| 845 | .type = elf.SHT_PROGBITS, | |
| 846 | .flags = elf.SHF_ALLOC | elf.SHF_WRITE | elf.SHF_TLS, | |
| 847 | .name = try elf_file.insertShString(".tdata"), | |
| 848 | .offset = std.math.maxInt(u64), | |
| 849 | }); | |
| 850 | } | |
| 851 | if (is_const) return elf_file.zig_data_rel_ro_section_index.?; | |
| 852 | if (nav_init != .none and Value.fromInterned(nav_init).isUndefDeep(zcu)) | |
| 853 | return switch (zcu.navFileScope(nav_index).mod.optimize_mode) { | |
| 854 | .Debug, .ReleaseSafe => elf_file.zig_data_section_index.?, | |
| 855 | .ReleaseFast, .ReleaseSmall => elf_file.zig_bss_section_index.?, | |
| 856 | }; | |
| 857 | for (code) |byte| { | |
| 858 | if (byte != 0) break; | |
| 859 | } else return elf_file.zig_bss_section_index.?; | |
| 860 | return elf_file.zig_data_section_index.?; | |
| 919 | 861 | } |
| 920 | 862 | |
| 921 | fn updateDeclCode( | |
| 863 | fn updateNavCode( | |
| 922 | 864 | self: *ZigObject, |
| 923 | 865 | elf_file: *Elf, |
| 924 | 866 | pt: Zcu.PerThread, |
| 925 | decl_index: InternPool.DeclIndex, | |
| 867 | nav_index: InternPool.Nav.Index, | |
| 926 | 868 | sym_index: Symbol.Index, |
| 927 | 869 | shdr_index: u32, |
| 928 | 870 | code: []const u8, |
| 929 | 871 | stt_bits: u8, |
| 930 | 872 | ) !void { |
| 931 | const gpa = elf_file.base.comp.gpa; | |
| 932 | const mod = pt.zcu; | |
| 933 | const ip = &mod.intern_pool; | |
| 934 | const decl = mod.declPtr(decl_index); | |
| 873 | const zcu = pt.zcu; | |
| 874 | const gpa = zcu.gpa; | |
| 875 | const ip = &zcu.intern_pool; | |
| 876 | const nav = ip.getNav(nav_index); | |
| 935 | 877 | |
| 936 | log.debug("updateDeclCode {}({d})", .{ decl.fqn.fmt(ip), decl_index }); | |
| 878 | log.debug("updateNavCode {}({d})", .{ nav.fqn.fmt(ip), nav_index }); | |
| 937 | 879 | |
| 938 | const required_alignment = decl.getAlignment(pt).max( | |
| 939 | target_util.minFunctionAlignment(mod.getTarget()), | |
| 880 | const required_alignment = pt.navAlignment(nav_index).max( | |
| 881 | target_util.minFunctionAlignment(zcu.navFileScope(nav_index).mod.resolved_target.result), | |
| 940 | 882 | ); |
| 941 | 883 | |
| 942 | 884 | const sym = self.symbol(sym_index); |
| 943 | 885 | const esym = &self.symtab.items(.elf_sym)[sym.esym_index]; |
| 944 | 886 | const atom_ptr = sym.atom(elf_file).?; |
| 945 | const name_offset = try self.strtab.insert(gpa, decl.fqn.toSlice(ip)); | |
| 887 | const name_offset = try self.strtab.insert(gpa, nav.fqn.toSlice(ip)); | |
| 946 | 888 | |
| 947 | 889 | atom_ptr.alive = true; |
| 948 | 890 | atom_ptr.name_offset = name_offset; |
| 949 | 891 | atom_ptr.output_section_index = shdr_index; |
| 892 | ||
| 950 | 893 | sym.name_offset = name_offset; |
| 951 | 894 | esym.st_name = name_offset; |
| 952 | 895 | esym.st_info |= stt_bits; |
| ... | ... | @@ -962,7 +905,7 @@ fn updateDeclCode( |
| 962 | 905 | const need_realloc = code.len > capacity or !required_alignment.check(@intCast(atom_ptr.value)); |
| 963 | 906 | if (need_realloc) { |
| 964 | 907 | try atom_ptr.grow(elf_file); |
| 965 | log.debug("growing {} from 0x{x} to 0x{x}", .{ decl.fqn.fmt(ip), old_vaddr, atom_ptr.value }); | |
| 908 | log.debug("growing {} from 0x{x} to 0x{x}", .{ nav.fqn.fmt(ip), old_vaddr, atom_ptr.value }); | |
| 966 | 909 | if (old_vaddr != atom_ptr.value) { |
| 967 | 910 | sym.value = 0; |
| 968 | 911 | esym.st_value = 0; |
| ... | ... | @@ -979,7 +922,7 @@ fn updateDeclCode( |
| 979 | 922 | } |
| 980 | 923 | } else { |
| 981 | 924 | try atom_ptr.allocate(elf_file); |
| 982 | errdefer self.freeDeclMetadata(elf_file, sym_index); | |
| 925 | errdefer self.freeNavMetadata(elf_file, sym_index); | |
| 983 | 926 | |
| 984 | 927 | sym.value = 0; |
| 985 | 928 | sym.flags.needs_zig_got = true; |
| ... | ... | @@ -1023,24 +966,24 @@ fn updateTlv( |
| 1023 | 966 | self: *ZigObject, |
| 1024 | 967 | elf_file: *Elf, |
| 1025 | 968 | pt: Zcu.PerThread, |
| 1026 | decl_index: InternPool.DeclIndex, | |
| 969 | nav_index: InternPool.Nav.Index, | |
| 1027 | 970 | sym_index: Symbol.Index, |
| 1028 | 971 | shndx: u32, |
| 1029 | 972 | code: []const u8, |
| 1030 | 973 | ) !void { |
| 1031 | const mod = pt.zcu; | |
| 1032 | const ip = &mod.intern_pool; | |
| 1033 | const gpa = mod.gpa; | |
| 1034 | const decl = mod.declPtr(decl_index); | |
| 974 | const zcu = pt.zcu; | |
| 975 | const ip = &zcu.intern_pool; | |
| 976 | const gpa = zcu.gpa; | |
| 977 | const nav = ip.getNav(nav_index); | |
| 1035 | 978 | |
| 1036 | log.debug("updateTlv {}({d})", .{ decl.fqn.fmt(ip), decl_index }); | |
| 979 | log.debug("updateTlv {}({d})", .{ nav.fqn.fmt(ip), nav_index }); | |
| 1037 | 980 | |
| 1038 | const required_alignment = decl.getAlignment(pt); | |
| 981 | const required_alignment = pt.navAlignment(nav_index); | |
| 1039 | 982 | |
| 1040 | 983 | const sym = self.symbol(sym_index); |
| 1041 | 984 | const esym = &self.symtab.items(.elf_sym)[sym.esym_index]; |
| 1042 | 985 | const atom_ptr = sym.atom(elf_file).?; |
| 1043 | const name_offset = try self.strtab.insert(gpa, decl.fqn.toSlice(ip)); | |
| 986 | const name_offset = try self.strtab.insert(gpa, nav.fqn.toSlice(ip)); | |
| 1044 | 987 | |
| 1045 | 988 | sym.value = 0; |
| 1046 | 989 | sym.name_offset = name_offset; |
| ... | ... | @@ -1049,6 +992,7 @@ fn updateTlv( |
| 1049 | 992 | atom_ptr.alive = true; |
| 1050 | 993 | atom_ptr.name_offset = name_offset; |
| 1051 | 994 | |
| 995 | sym.name_offset = name_offset; | |
| 1052 | 996 | esym.st_value = 0; |
| 1053 | 997 | esym.st_name = name_offset; |
| 1054 | 998 | esym.st_info = elf.STT_TLS; |
| ... | ... | @@ -1086,53 +1030,49 @@ pub fn updateFunc( |
| 1086 | 1030 | const tracy = trace(@src()); |
| 1087 | 1031 | defer tracy.end(); |
| 1088 | 1032 | |
| 1089 | const mod = pt.zcu; | |
| 1090 | const ip = &mod.intern_pool; | |
| 1033 | const zcu = pt.zcu; | |
| 1034 | const ip = &zcu.intern_pool; | |
| 1091 | 1035 | const gpa = elf_file.base.comp.gpa; |
| 1092 | const func = mod.funcInfo(func_index); | |
| 1093 | const decl_index = func.owner_decl; | |
| 1094 | const decl = mod.declPtr(decl_index); | |
| 1036 | const func = zcu.funcInfo(func_index); | |
| 1095 | 1037 | |
| 1096 | log.debug("updateFunc {}({d})", .{ decl.fqn.fmt(ip), decl_index }); | |
| 1038 | log.debug("updateFunc {}({d})", .{ ip.getNav(func.owner_nav).fqn.fmt(ip), func.owner_nav }); | |
| 1097 | 1039 | |
| 1098 | const sym_index = try self.getOrCreateMetadataForDecl(elf_file, decl_index); | |
| 1099 | self.freeUnnamedConsts(elf_file, decl_index); | |
| 1040 | const sym_index = try self.getOrCreateMetadataForNav(elf_file, func.owner_nav); | |
| 1100 | 1041 | self.symbol(sym_index).atom(elf_file).?.freeRelocs(elf_file); |
| 1101 | 1042 | |
| 1102 | 1043 | var code_buffer = std.ArrayList(u8).init(gpa); |
| 1103 | 1044 | defer code_buffer.deinit(); |
| 1104 | 1045 | |
| 1105 | var decl_state: ?Dwarf.DeclState = if (self.dwarf) |*dw| try dw.initDeclState(pt, decl_index) else null; | |
| 1106 | defer if (decl_state) |*ds| ds.deinit(); | |
| 1046 | var dwarf_state = if (self.dwarf) |*dw| try dw.initNavState(pt, func.owner_nav) else null; | |
| 1047 | defer if (dwarf_state) |*ds| ds.deinit(); | |
| 1107 | 1048 | |
| 1108 | 1049 | const res = try codegen.generateFunction( |
| 1109 | 1050 | &elf_file.base, |
| 1110 | 1051 | pt, |
| 1111 | decl.navSrcLoc(mod), | |
| 1052 | zcu.navSrcLoc(func.owner_nav), | |
| 1112 | 1053 | func_index, |
| 1113 | 1054 | air, |
| 1114 | 1055 | liveness, |
| 1115 | 1056 | &code_buffer, |
| 1116 | if (decl_state) |*ds| .{ .dwarf = ds } else .none, | |
| 1057 | if (dwarf_state) |*ds| .{ .dwarf = ds } else .none, | |
| 1117 | 1058 | ); |
| 1118 | 1059 | |
| 1119 | 1060 | const code = switch (res) { |
| 1120 | 1061 | .ok => code_buffer.items, |
| 1121 | 1062 | .fail => |em| { |
| 1122 | func.setAnalysisState(&mod.intern_pool, .codegen_failure); | |
| 1123 | try mod.failed_analysis.put(mod.gpa, AnalUnit.wrap(.{ .decl = decl_index }), em); | |
| 1063 | try zcu.failed_codegen.put(gpa, func.owner_nav, em); | |
| 1124 | 1064 | return; |
| 1125 | 1065 | }, |
| 1126 | 1066 | }; |
| 1127 | 1067 | |
| 1128 | const shndx = try self.getDeclShdrIndex(elf_file, decl, code); | |
| 1129 | try self.updateDeclCode(elf_file, pt, decl_index, sym_index, shndx, code, elf.STT_FUNC); | |
| 1068 | const shndx = try self.getNavShdrIndex(elf_file, zcu, func.owner_nav, code); | |
| 1069 | try self.updateNavCode(elf_file, pt, func.owner_nav, sym_index, shndx, code, elf.STT_FUNC); | |
| 1130 | 1070 | |
| 1131 | if (decl_state) |*ds| { | |
| 1071 | if (dwarf_state) |*ds| { | |
| 1132 | 1072 | const sym = self.symbol(sym_index); |
| 1133 | try self.dwarf.?.commitDeclState( | |
| 1073 | try self.dwarf.?.commitNavState( | |
| 1134 | 1074 | pt, |
| 1135 | decl_index, | |
| 1075 | func.owner_nav, | |
| 1136 | 1076 | @intCast(sym.address(.{}, elf_file)), |
| 1137 | 1077 | sym.atom(elf_file).?.size, |
| 1138 | 1078 | ds, |
| ... | ... | @@ -1142,78 +1082,80 @@ pub fn updateFunc( |
| 1142 | 1082 | // Exports will be updated by `Zcu.processExports` after the update. |
| 1143 | 1083 | } |
| 1144 | 1084 | |
| 1145 | pub fn updateDecl( | |
| 1085 | pub fn updateNav( | |
| 1146 | 1086 | self: *ZigObject, |
| 1147 | 1087 | elf_file: *Elf, |
| 1148 | 1088 | pt: Zcu.PerThread, |
| 1149 | decl_index: InternPool.DeclIndex, | |
| 1150 | ) link.File.UpdateDeclError!void { | |
| 1089 | nav_index: InternPool.Nav.Index, | |
| 1090 | ) link.File.UpdateNavError!void { | |
| 1151 | 1091 | const tracy = trace(@src()); |
| 1152 | 1092 | defer tracy.end(); |
| 1153 | 1093 | |
| 1154 | const mod = pt.zcu; | |
| 1155 | const ip = &mod.intern_pool; | |
| 1156 | const decl = mod.declPtr(decl_index); | |
| 1157 | ||
| 1158 | log.debug("updateDecl {}({d})", .{ decl.fqn.fmt(ip), decl_index }); | |
| 1159 | ||
| 1160 | if (decl.val.getExternFunc(mod)) |_| return; | |
| 1161 | if (decl.isExtern(mod)) { | |
| 1162 | // Extern variable gets a .got entry only. | |
| 1163 | const variable = decl.getOwnedVariable(mod).?; | |
| 1164 | const name = decl.name.toSlice(&mod.intern_pool); | |
| 1165 | const lib_name = variable.lib_name.toSlice(&mod.intern_pool); | |
| 1166 | const sym_index = try self.getGlobalSymbol(elf_file, name, lib_name); | |
| 1167 | self.symbol(sym_index).flags.needs_got = true; | |
| 1168 | return; | |
| 1169 | } | |
| 1094 | const zcu = pt.zcu; | |
| 1095 | const ip = &zcu.intern_pool; | |
| 1096 | const nav = ip.getNav(nav_index); | |
| 1097 | ||
| 1098 | log.debug("updateNav {}({d})", .{ nav.fqn.fmt(ip), nav_index }); | |
| 1099 | ||
| 1100 | const nav_val = zcu.navValue(nav_index); | |
| 1101 | const nav_init = switch (ip.indexToKey(nav_val.toIntern())) { | |
| 1102 | .variable => |variable| Value.fromInterned(variable.init), | |
| 1103 | .@"extern" => |@"extern"| { | |
| 1104 | if (ip.isFunctionType(@"extern".ty)) return; | |
| 1105 | // Extern variable gets a .got entry only. | |
| 1106 | const sym_index = try self.getGlobalSymbol( | |
| 1107 | elf_file, | |
| 1108 | nav.name.toSlice(ip), | |
| 1109 | @"extern".lib_name.toSlice(ip), | |
| 1110 | ); | |
| 1111 | self.symbol(sym_index).flags.needs_got = true; | |
| 1112 | return; | |
| 1113 | }, | |
| 1114 | else => nav_val, | |
| 1115 | }; | |
| 1170 | 1116 | |
| 1171 | const sym_index = try self.getOrCreateMetadataForDecl(elf_file, decl_index); | |
| 1117 | const sym_index = try self.getOrCreateMetadataForNav(elf_file, nav_index); | |
| 1172 | 1118 | self.symbol(sym_index).atom(elf_file).?.freeRelocs(elf_file); |
| 1173 | 1119 | |
| 1174 | const gpa = elf_file.base.comp.gpa; | |
| 1175 | var code_buffer = std.ArrayList(u8).init(gpa); | |
| 1120 | var code_buffer = std.ArrayList(u8).init(zcu.gpa); | |
| 1176 | 1121 | defer code_buffer.deinit(); |
| 1177 | 1122 | |
| 1178 | var decl_state: ?Dwarf.DeclState = if (self.dwarf) |*dw| try dw.initDeclState(pt, decl_index) else null; | |
| 1179 | defer if (decl_state) |*ds| ds.deinit(); | |
| 1123 | var nav_state: ?Dwarf.NavState = if (self.dwarf) |*dw| try dw.initNavState(pt, nav_index) else null; | |
| 1124 | defer if (nav_state) |*ns| ns.deinit(); | |
| 1180 | 1125 | |
| 1181 | 1126 | // TODO implement .debug_info for global variables |
| 1182 | const decl_val = if (decl.val.getVariable(mod)) |variable| Value.fromInterned(variable.init) else decl.val; | |
| 1183 | const res = if (decl_state) |*ds| | |
| 1184 | try codegen.generateSymbol(&elf_file.base, pt, decl.navSrcLoc(mod), decl_val, &code_buffer, .{ | |
| 1185 | .dwarf = ds, | |
| 1186 | }, .{ | |
| 1187 | .parent_atom_index = sym_index, | |
| 1188 | }) | |
| 1189 | else | |
| 1190 | try codegen.generateSymbol(&elf_file.base, pt, decl.navSrcLoc(mod), decl_val, &code_buffer, .none, .{ | |
| 1191 | .parent_atom_index = sym_index, | |
| 1192 | }); | |
| 1127 | const res = try codegen.generateSymbol( | |
| 1128 | &elf_file.base, | |
| 1129 | pt, | |
| 1130 | zcu.navSrcLoc(nav_index), | |
| 1131 | nav_init, | |
| 1132 | &code_buffer, | |
| 1133 | if (nav_state) |*ns| .{ .dwarf = ns } else .none, | |
| 1134 | .{ .parent_atom_index = sym_index }, | |
| 1135 | ); | |
| 1193 | 1136 | |
| 1194 | 1137 | const code = switch (res) { |
| 1195 | 1138 | .ok => code_buffer.items, |
| 1196 | 1139 | .fail => |em| { |
| 1197 | decl.analysis = .codegen_failure; | |
| 1198 | try mod.failed_analysis.put(mod.gpa, AnalUnit.wrap(.{ .decl = decl_index }), em); | |
| 1140 | try zcu.failed_codegen.put(zcu.gpa, nav_index, em); | |
| 1199 | 1141 | return; |
| 1200 | 1142 | }, |
| 1201 | 1143 | }; |
| 1202 | 1144 | |
| 1203 | const shndx = try self.getDeclShdrIndex(elf_file, decl, code); | |
| 1145 | const shndx = try self.getNavShdrIndex(elf_file, zcu, nav_index, code); | |
| 1204 | 1146 | if (elf_file.shdrs.items[shndx].sh_flags & elf.SHF_TLS != 0) |
| 1205 | try self.updateTlv(elf_file, pt, decl_index, sym_index, shndx, code) | |
| 1147 | try self.updateTlv(elf_file, pt, nav_index, sym_index, shndx, code) | |
| 1206 | 1148 | else |
| 1207 | try self.updateDeclCode(elf_file, pt, decl_index, sym_index, shndx, code, elf.STT_OBJECT); | |
| 1149 | try self.updateNavCode(elf_file, pt, nav_index, sym_index, shndx, code, elf.STT_OBJECT); | |
| 1208 | 1150 | |
| 1209 | if (decl_state) |*ds| { | |
| 1151 | if (nav_state) |*ns| { | |
| 1210 | 1152 | const sym = self.symbol(sym_index); |
| 1211 | try self.dwarf.?.commitDeclState( | |
| 1153 | try self.dwarf.?.commitNavState( | |
| 1212 | 1154 | pt, |
| 1213 | decl_index, | |
| 1155 | nav_index, | |
| 1214 | 1156 | @intCast(sym.address(.{}, elf_file)), |
| 1215 | 1157 | sym.atom(elf_file).?.size, |
| 1216 | ds, | |
| 1158 | ns, | |
| 1217 | 1159 | ); |
| 1218 | 1160 | } |
| 1219 | 1161 | |
| ... | ... | @@ -1237,13 +1179,13 @@ fn updateLazySymbol( |
| 1237 | 1179 | const name_str_index = blk: { |
| 1238 | 1180 | const name = try std.fmt.allocPrint(gpa, "__lazy_{s}_{}", .{ |
| 1239 | 1181 | @tagName(sym.kind), |
| 1240 | sym.ty.fmt(pt), | |
| 1182 | Type.fromInterned(sym.ty).fmt(pt), | |
| 1241 | 1183 | }); |
| 1242 | 1184 | defer gpa.free(name); |
| 1243 | 1185 | break :blk try self.strtab.insert(gpa, name); |
| 1244 | 1186 | }; |
| 1245 | 1187 | |
| 1246 | const src = sym.ty.srcLocOrNull(mod) orelse Module.LazySrcLoc.unneeded; | |
| 1188 | const src = Type.fromInterned(sym.ty).srcLocOrNull(mod) orelse Zcu.LazySrcLoc.unneeded; | |
| 1247 | 1189 | const res = try codegen.generateLazySymbol( |
| 1248 | 1190 | &elf_file.base, |
| 1249 | 1191 | pt, |
| ... | ... | @@ -1280,7 +1222,7 @@ fn updateLazySymbol( |
| 1280 | 1222 | atom_ptr.output_section_index = output_section_index; |
| 1281 | 1223 | |
| 1282 | 1224 | try atom_ptr.allocate(elf_file); |
| 1283 | errdefer self.freeDeclMetadata(elf_file, symbol_index); | |
| 1225 | errdefer self.freeNavMetadata(elf_file, symbol_index); | |
| 1284 | 1226 | |
| 1285 | 1227 | local_sym.value = 0; |
| 1286 | 1228 | local_sym.flags.needs_zig_got = true; |
| ... | ... | @@ -1296,49 +1238,9 @@ fn updateLazySymbol( |
| 1296 | 1238 | try elf_file.base.file.?.pwriteAll(code, file_offset); |
| 1297 | 1239 | } |
| 1298 | 1240 | |
| 1299 | pub fn lowerUnnamedConst( | |
| 1300 | self: *ZigObject, | |
| 1301 | elf_file: *Elf, | |
| 1302 | pt: Zcu.PerThread, | |
| 1303 | val: Value, | |
| 1304 | decl_index: InternPool.DeclIndex, | |
| 1305 | ) !u32 { | |
| 1306 | const gpa = elf_file.base.comp.gpa; | |
| 1307 | const mod = elf_file.base.comp.module.?; | |
| 1308 | const gop = try self.unnamed_consts.getOrPut(gpa, decl_index); | |
| 1309 | if (!gop.found_existing) { | |
| 1310 | gop.value_ptr.* = .{}; | |
| 1311 | } | |
| 1312 | const unnamed_consts = gop.value_ptr; | |
| 1313 | const decl = mod.declPtr(decl_index); | |
| 1314 | const index = unnamed_consts.items.len; | |
| 1315 | const name = try std.fmt.allocPrint(gpa, "__unnamed_{}_{d}", .{ decl.fqn.fmt(&mod.intern_pool), index }); | |
| 1316 | defer gpa.free(name); | |
| 1317 | const ty = val.typeOf(mod); | |
| 1318 | const sym_index = switch (try self.lowerConst( | |
| 1319 | elf_file, | |
| 1320 | pt, | |
| 1321 | name, | |
| 1322 | val, | |
| 1323 | ty.abiAlignment(pt), | |
| 1324 | elf_file.zig_data_rel_ro_section_index.?, | |
| 1325 | decl.navSrcLoc(mod), | |
| 1326 | )) { | |
| 1327 | .ok => |sym_index| sym_index, | |
| 1328 | .fail => |em| { | |
| 1329 | decl.analysis = .codegen_failure; | |
| 1330 | try mod.failed_analysis.put(mod.gpa, AnalUnit.wrap(.{ .decl = decl_index }), em); | |
| 1331 | log.err("{s}", .{em.msg}); | |
| 1332 | return error.CodegenFail; | |
| 1333 | }, | |
| 1334 | }; | |
| 1335 | try unnamed_consts.append(gpa, sym_index); | |
| 1336 | return sym_index; | |
| 1337 | } | |
| 1338 | ||
| 1339 | 1241 | const LowerConstResult = union(enum) { |
| 1340 | 1242 | ok: Symbol.Index, |
| 1341 | fail: *Module.ErrorMsg, | |
| 1243 | fail: *Zcu.ErrorMsg, | |
| 1342 | 1244 | }; |
| 1343 | 1245 | |
| 1344 | 1246 | fn lowerConst( |
| ... | ... | @@ -1349,7 +1251,7 @@ fn lowerConst( |
| 1349 | 1251 | val: Value, |
| 1350 | 1252 | required_alignment: InternPool.Alignment, |
| 1351 | 1253 | output_section_index: u32, |
| 1352 | src_loc: Module.LazySrcLoc, | |
| 1254 | src_loc: Zcu.LazySrcLoc, | |
| 1353 | 1255 | ) !LowerConstResult { |
| 1354 | 1256 | const gpa = pt.zcu.gpa; |
| 1355 | 1257 | |
| ... | ... | @@ -1384,7 +1286,8 @@ fn lowerConst( |
| 1384 | 1286 | atom_ptr.output_section_index = output_section_index; |
| 1385 | 1287 | |
| 1386 | 1288 | try atom_ptr.allocate(elf_file); |
| 1387 | errdefer self.freeDeclMetadata(elf_file, sym_index); | |
| 1289 | // TODO rename and re-audit this method | |
| 1290 | errdefer self.freeNavMetadata(elf_file, sym_index); | |
| 1388 | 1291 | |
| 1389 | 1292 | const shdr = elf_file.shdrs.items[output_section_index]; |
| 1390 | 1293 | const file_offset = shdr.sh_offset + @as(u64, @intCast(atom_ptr.value)); |
| ... | ... | @@ -1397,7 +1300,7 @@ pub fn updateExports( |
| 1397 | 1300 | self: *ZigObject, |
| 1398 | 1301 | elf_file: *Elf, |
| 1399 | 1302 | pt: Zcu.PerThread, |
| 1400 | exported: Module.Exported, | |
| 1303 | exported: Zcu.Exported, | |
| 1401 | 1304 | export_indices: []const u32, |
| 1402 | 1305 | ) link.File.UpdateExportsError!void { |
| 1403 | 1306 | const tracy = trace(@src()); |
| ... | ... | @@ -1406,24 +1309,24 @@ pub fn updateExports( |
| 1406 | 1309 | const mod = pt.zcu; |
| 1407 | 1310 | const gpa = elf_file.base.comp.gpa; |
| 1408 | 1311 | const metadata = switch (exported) { |
| 1409 | .decl_index => |decl_index| blk: { | |
| 1410 | _ = try self.getOrCreateMetadataForDecl(elf_file, decl_index); | |
| 1411 | break :blk self.decls.getPtr(decl_index).?; | |
| 1312 | .nav => |nav| blk: { | |
| 1313 | _ = try self.getOrCreateMetadataForNav(elf_file, nav); | |
| 1314 | break :blk self.navs.getPtr(nav).?; | |
| 1412 | 1315 | }, |
| 1413 | .value => |value| self.anon_decls.getPtr(value) orelse blk: { | |
| 1316 | .uav => |uav| self.uavs.getPtr(uav) orelse blk: { | |
| 1414 | 1317 | const first_exp = mod.all_exports.items[export_indices[0]]; |
| 1415 | const res = try self.lowerAnonDecl(elf_file, pt, value, .none, first_exp.src); | |
| 1318 | const res = try self.lowerUav(elf_file, pt, uav, .none, first_exp.src); | |
| 1416 | 1319 | switch (res) { |
| 1417 | .ok => {}, | |
| 1320 | .mcv => {}, | |
| 1418 | 1321 | .fail => |em| { |
| 1419 | // TODO maybe it's enough to return an error here and let Module.processExportsInner | |
| 1322 | // TODO maybe it's enough to return an error here and let Zcu.processExportsInner | |
| 1420 | 1323 | // handle the error? |
| 1421 | 1324 | try mod.failed_exports.ensureUnusedCapacity(mod.gpa, 1); |
| 1422 | 1325 | mod.failed_exports.putAssumeCapacityNoClobber(export_indices[0], em); |
| 1423 | 1326 | return; |
| 1424 | 1327 | }, |
| 1425 | 1328 | } |
| 1426 | break :blk self.anon_decls.getPtr(value).?; | |
| 1329 | break :blk self.uavs.getPtr(uav).?; | |
| 1427 | 1330 | }, |
| 1428 | 1331 | }; |
| 1429 | 1332 | const sym_index = metadata.symbol_index; |
| ... | ... | @@ -1436,7 +1339,7 @@ pub fn updateExports( |
| 1436 | 1339 | if (exp.opts.section.unwrap()) |section_name| { |
| 1437 | 1340 | if (!section_name.eqlSlice(".text", &mod.intern_pool)) { |
| 1438 | 1341 | try mod.failed_exports.ensureUnusedCapacity(mod.gpa, 1); |
| 1439 | mod.failed_exports.putAssumeCapacityNoClobber(export_idx, try Module.ErrorMsg.create( | |
| 1342 | mod.failed_exports.putAssumeCapacityNoClobber(export_idx, try Zcu.ErrorMsg.create( | |
| 1440 | 1343 | gpa, |
| 1441 | 1344 | exp.src, |
| 1442 | 1345 | "Unimplemented: ExportOptions.section", |
| ... | ... | @@ -1451,7 +1354,7 @@ pub fn updateExports( |
| 1451 | 1354 | .weak => elf.STB_WEAK, |
| 1452 | 1355 | .link_once => { |
| 1453 | 1356 | try mod.failed_exports.ensureUnusedCapacity(mod.gpa, 1); |
| 1454 | mod.failed_exports.putAssumeCapacityNoClobber(export_idx, try Module.ErrorMsg.create( | |
| 1357 | mod.failed_exports.putAssumeCapacityNoClobber(export_idx, try Zcu.ErrorMsg.create( | |
| 1455 | 1358 | gpa, |
| 1456 | 1359 | exp.src, |
| 1457 | 1360 | "Unimplemented: GlobalLinkage.LinkOnce", |
| ... | ... | @@ -1487,21 +1390,22 @@ pub fn updateExports( |
| 1487 | 1390 | } |
| 1488 | 1391 | } |
| 1489 | 1392 | |
| 1490 | /// Must be called only after a successful call to `updateDecl`. | |
| 1491 | pub fn updateDeclLineNumber( | |
| 1393 | /// Must be called only after a successful call to `updateNav`. | |
| 1394 | pub fn updateNavLineNumber( | |
| 1492 | 1395 | self: *ZigObject, |
| 1493 | 1396 | pt: Zcu.PerThread, |
| 1494 | decl_index: InternPool.DeclIndex, | |
| 1397 | nav_index: InternPool.Nav.Index, | |
| 1495 | 1398 | ) !void { |
| 1496 | 1399 | const tracy = trace(@src()); |
| 1497 | 1400 | defer tracy.end(); |
| 1498 | 1401 | |
| 1499 | const decl = pt.zcu.declPtr(decl_index); | |
| 1402 | const ip = &pt.zcu.intern_pool; | |
| 1403 | const nav = ip.getNav(nav_index); | |
| 1500 | 1404 | |
| 1501 | log.debug("updateDeclLineNumber {}({d})", .{ decl.fqn.fmt(&pt.zcu.intern_pool), decl_index }); | |
| 1405 | log.debug("updateNavLineNumber {}({d})", .{ nav.fqn.fmt(ip), nav_index }); | |
| 1502 | 1406 | |
| 1503 | 1407 | if (self.dwarf) |*dw| { |
| 1504 | try dw.updateDeclLineNumber(pt.zcu, decl_index); | |
| 1408 | try dw.updateNavLineNumber(pt.zcu, nav_index); | |
| 1505 | 1409 | } |
| 1506 | 1410 | } |
| 1507 | 1411 | |
| ... | ... | @@ -1512,9 +1416,9 @@ pub fn deleteExport( |
| 1512 | 1416 | name: InternPool.NullTerminatedString, |
| 1513 | 1417 | ) void { |
| 1514 | 1418 | const metadata = switch (exported) { |
| 1515 | .decl_index => |decl_index| self.decls.getPtr(decl_index) orelse return, | |
| 1516 | .value => |value| self.anon_decls.getPtr(value) orelse return, | |
| 1517 | }; | |
| 1419 | .nav => |nav| self.navs.getPtr(nav), | |
| 1420 | .uav => |uav| self.uavs.getPtr(uav), | |
| 1421 | } orelse return; | |
| 1518 | 1422 | const mod = elf_file.base.comp.module.?; |
| 1519 | 1423 | const exp_name = name.toSlice(&mod.intern_pool); |
| 1520 | 1424 | const esym_index = metadata.@"export"(self, exp_name) orelse return; |
| ... | ... | @@ -1754,14 +1658,14 @@ const LazySymbolMetadata = struct { |
| 1754 | 1658 | rodata_state: State = .unused, |
| 1755 | 1659 | }; |
| 1756 | 1660 | |
| 1757 | const DeclMetadata = struct { | |
| 1661 | const AvMetadata = struct { | |
| 1758 | 1662 | symbol_index: Symbol.Index, |
| 1759 | /// A list of all exports aliases of this Decl. | |
| 1663 | /// A list of all exports aliases of this Av. | |
| 1760 | 1664 | exports: std.ArrayListUnmanaged(Symbol.Index) = .{}, |
| 1761 | 1665 | |
| 1762 | fn @"export"(m: DeclMetadata, zo: *ZigObject, name: []const u8) ?*u32 { | |
| 1666 | fn @"export"(m: AvMetadata, zig_object: *ZigObject, name: []const u8) ?*u32 { | |
| 1763 | 1667 | for (m.exports.items) |*exp| { |
| 1764 | const exp_name = zo.getString(zo.symbol(exp.*).name_offset); | |
| 1668 | const exp_name = zig_object.getString(zig_object.symbol(exp.*).name_offset); | |
| 1765 | 1669 | if (mem.eql(u8, name, exp_name)) return exp; |
| 1766 | 1670 | } |
| 1767 | 1671 | return null; |
| ... | ... | @@ -1778,10 +1682,9 @@ const TlsVariable = struct { |
| 1778 | 1682 | }; |
| 1779 | 1683 | |
| 1780 | 1684 | const AtomList = std.ArrayListUnmanaged(Atom.Index); |
| 1781 | const UnnamedConstTable = std.AutoHashMapUnmanaged(InternPool.DeclIndex, std.ArrayListUnmanaged(Symbol.Index)); | |
| 1782 | const DeclTable = std.AutoHashMapUnmanaged(InternPool.DeclIndex, DeclMetadata); | |
| 1783 | const AnonDeclTable = std.AutoHashMapUnmanaged(InternPool.Index, DeclMetadata); | |
| 1784 | const LazySymbolTable = std.AutoArrayHashMapUnmanaged(InternPool.OptionalDeclIndex, LazySymbolMetadata); | |
| 1685 | const NavTable = std.AutoHashMapUnmanaged(InternPool.Nav.Index, AvMetadata); | |
| 1686 | const UavTable = std.AutoHashMapUnmanaged(InternPool.Index, AvMetadata); | |
| 1687 | const LazySymbolTable = std.AutoArrayHashMapUnmanaged(InternPool.Index, LazySymbolMetadata); | |
| 1785 | 1688 | const TlsTable = std.AutoArrayHashMapUnmanaged(Atom.Index, TlsVariable); |
| 1786 | 1689 | |
| 1787 | 1690 | const assert = std.debug.assert; |
| ... | ... | @@ -1792,8 +1695,8 @@ const link = @import("../../link.zig"); |
| 1792 | 1695 | const log = std.log.scoped(.link); |
| 1793 | 1696 | const mem = std.mem; |
| 1794 | 1697 | const relocation = @import("relocation.zig"); |
| 1795 | const trace = @import("../../tracy.zig").trace; | |
| 1796 | 1698 | const target_util = @import("../../target.zig"); |
| 1699 | const trace = @import("../../tracy.zig").trace; | |
| 1797 | 1700 | const std = @import("std"); |
| 1798 | 1701 | |
| 1799 | 1702 | const Air = @import("../../Air.zig"); |
| ... | ... | @@ -1806,8 +1709,6 @@ const File = @import("file.zig").File; |
| 1806 | 1709 | const InternPool = @import("../../InternPool.zig"); |
| 1807 | 1710 | const Liveness = @import("../../Liveness.zig"); |
| 1808 | 1711 | const Zcu = @import("../../Zcu.zig"); |
| 1809 | /// Deprecated. | |
| 1810 | const Module = Zcu; | |
| 1811 | 1712 | const Object = @import("Object.zig"); |
| 1812 | 1713 | const Symbol = @import("Symbol.zig"); |
| 1813 | 1714 | const StringTable = @import("../StringTable.zig"); |
src/link/MachO.zig+16-22| ... | ... | @@ -2998,21 +2998,17 @@ pub fn updateFunc(self: *MachO, pt: Zcu.PerThread, func_index: InternPool.Index, |
| 2998 | 2998 | return self.getZigObject().?.updateFunc(self, pt, func_index, air, liveness); |
| 2999 | 2999 | } |
| 3000 | 3000 | |
| 3001 | pub fn lowerUnnamedConst(self: *MachO, pt: Zcu.PerThread, val: Value, decl_index: InternPool.DeclIndex) !u32 { | |
| 3002 | return self.getZigObject().?.lowerUnnamedConst(self, pt, val, decl_index); | |
| 3003 | } | |
| 3004 | ||
| 3005 | pub fn updateDecl(self: *MachO, pt: Zcu.PerThread, decl_index: InternPool.DeclIndex) !void { | |
| 3001 | pub fn updateNav(self: *MachO, pt: Zcu.PerThread, nav: InternPool.Nav.Index) !void { | |
| 3006 | 3002 | if (build_options.skip_non_native and builtin.object_format != .macho) { |
| 3007 | 3003 | @panic("Attempted to compile for object format that was disabled by build configuration"); |
| 3008 | 3004 | } |
| 3009 | if (self.llvm_object) |llvm_object| return llvm_object.updateDecl(pt, decl_index); | |
| 3010 | return self.getZigObject().?.updateDecl(self, pt, decl_index); | |
| 3005 | if (self.llvm_object) |llvm_object| return llvm_object.updateNav(pt, nav); | |
| 3006 | return self.getZigObject().?.updateNav(self, pt, nav); | |
| 3011 | 3007 | } |
| 3012 | 3008 | |
| 3013 | pub fn updateDeclLineNumber(self: *MachO, pt: Zcu.PerThread, decl_index: InternPool.DeclIndex) !void { | |
| 3009 | pub fn updateNavLineNumber(self: *MachO, pt: Zcu.PerThread, nav: InternPool.NavIndex) !void { | |
| 3014 | 3010 | if (self.llvm_object) |_| return; |
| 3015 | return self.getZigObject().?.updateDeclLineNumber(pt, decl_index); | |
| 3011 | return self.getZigObject().?.updateNavLineNumber(pt, nav); | |
| 3016 | 3012 | } |
| 3017 | 3013 | |
| 3018 | 3014 | pub fn updateExports( |
| ... | ... | @@ -3037,29 +3033,29 @@ pub fn deleteExport( |
| 3037 | 3033 | return self.getZigObject().?.deleteExport(self, exported, name); |
| 3038 | 3034 | } |
| 3039 | 3035 | |
| 3040 | pub fn freeDecl(self: *MachO, decl_index: InternPool.DeclIndex) void { | |
| 3041 | if (self.llvm_object) |llvm_object| return llvm_object.freeDecl(decl_index); | |
| 3042 | return self.getZigObject().?.freeDecl(decl_index); | |
| 3036 | pub fn freeNav(self: *MachO, nav: InternPool.Nav.Index) void { | |
| 3037 | if (self.llvm_object) |llvm_object| return llvm_object.freeNav(nav); | |
| 3038 | return self.getZigObject().?.freeNav(nav); | |
| 3043 | 3039 | } |
| 3044 | 3040 | |
| 3045 | pub fn getDeclVAddr(self: *MachO, pt: Zcu.PerThread, decl_index: InternPool.DeclIndex, reloc_info: link.File.RelocInfo) !u64 { | |
| 3041 | pub fn getNavVAddr(self: *MachO, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index, reloc_info: link.File.RelocInfo) !u64 { | |
| 3046 | 3042 | assert(self.llvm_object == null); |
| 3047 | return self.getZigObject().?.getDeclVAddr(self, pt, decl_index, reloc_info); | |
| 3043 | return self.getZigObject().?.getNavVAddr(self, pt, nav_index, reloc_info); | |
| 3048 | 3044 | } |
| 3049 | 3045 | |
| 3050 | pub fn lowerAnonDecl( | |
| 3046 | pub fn lowerUav( | |
| 3051 | 3047 | self: *MachO, |
| 3052 | 3048 | pt: Zcu.PerThread, |
| 3053 | decl_val: InternPool.Index, | |
| 3049 | uav: InternPool.Index, | |
| 3054 | 3050 | explicit_alignment: InternPool.Alignment, |
| 3055 | 3051 | src_loc: Module.LazySrcLoc, |
| 3056 | ) !codegen.Result { | |
| 3057 | return self.getZigObject().?.lowerAnonDecl(self, pt, decl_val, explicit_alignment, src_loc); | |
| 3052 | ) !codegen.GenResult { | |
| 3053 | return self.getZigObject().?.lowerUav(self, pt, uav, explicit_alignment, src_loc); | |
| 3058 | 3054 | } |
| 3059 | 3055 | |
| 3060 | pub fn getAnonDeclVAddr(self: *MachO, decl_val: InternPool.Index, reloc_info: link.File.RelocInfo) !u64 { | |
| 3056 | pub fn getUavVAddr(self: *MachO, uav: InternPool.Index, reloc_info: link.File.RelocInfo) !u64 { | |
| 3061 | 3057 | assert(self.llvm_object == null); |
| 3062 | return self.getZigObject().?.getAnonDeclVAddr(self, decl_val, reloc_info); | |
| 3058 | return self.getZigObject().?.getUavVAddr(self, uav, reloc_info); | |
| 3063 | 3059 | } |
| 3064 | 3060 | |
| 3065 | 3061 | pub fn getGlobalSymbol(self: *MachO, name: []const u8, lib_name: ?[]const u8) !u32 { |
| ... | ... | @@ -4051,8 +4047,6 @@ const is_hot_update_compatible = switch (builtin.target.os.tag) { |
| 4051 | 4047 | |
| 4052 | 4048 | const default_entry_symbol_name = "_main"; |
| 4053 | 4049 | |
| 4054 | pub const base_tag: link.File.Tag = link.File.Tag.macho; | |
| 4055 | ||
| 4056 | 4050 | const Section = struct { |
| 4057 | 4051 | header: macho.section_64, |
| 4058 | 4052 | segment_id: u8, |
src/link/MachO/Atom.zig+20| ... | ... | @@ -992,6 +992,8 @@ pub fn writeRelocs(self: Atom, macho_file: *MachO, code: []u8, buffer: []macho.r |
| 992 | 992 | const tracy = trace(@src()); |
| 993 | 993 | defer tracy.end(); |
| 994 | 994 | |
| 995 | relocs_log.debug("{x}: {s}", .{ self.getAddress(macho_file), self.getName(macho_file) }); | |
| 996 | ||
| 995 | 997 | const cpu_arch = macho_file.getTarget().cpu.arch; |
| 996 | 998 | const relocs = self.getRelocs(macho_file); |
| 997 | 999 | |
| ... | ... | @@ -1015,6 +1017,24 @@ pub fn writeRelocs(self: Atom, macho_file: *MachO, code: []u8, buffer: []macho.r |
| 1015 | 1017 | addend += target; |
| 1016 | 1018 | } |
| 1017 | 1019 | |
| 1020 | switch (rel.tag) { | |
| 1021 | .local => relocs_log.debug(" {}: [{x} => {d}({s},{s})] + {x}", .{ | |
| 1022 | rel.fmtPretty(cpu_arch), | |
| 1023 | r_address, | |
| 1024 | r_symbolnum, | |
| 1025 | macho_file.sections.items(.header)[r_symbolnum - 1].segName(), | |
| 1026 | macho_file.sections.items(.header)[r_symbolnum - 1].sectName(), | |
| 1027 | addend, | |
| 1028 | }), | |
| 1029 | .@"extern" => relocs_log.debug(" {}: [{x} => {d}({s})] + {x}", .{ | |
| 1030 | rel.fmtPretty(cpu_arch), | |
| 1031 | r_address, | |
| 1032 | r_symbolnum, | |
| 1033 | rel.getTargetSymbol(self, macho_file).getName(macho_file), | |
| 1034 | addend, | |
| 1035 | }), | |
| 1036 | } | |
| 1037 | ||
| 1018 | 1038 | switch (cpu_arch) { |
| 1019 | 1039 | .aarch64 => { |
| 1020 | 1040 | if (rel.type == .unsigned) switch (rel.meta.length) { |
src/link/MachO/ZigObject.zig+225-329| ... | ... | @@ -19,32 +19,11 @@ atoms_extra: std.ArrayListUnmanaged(u32) = .{}, |
| 19 | 19 | /// Table of tracked LazySymbols. |
| 20 | 20 | lazy_syms: LazySymbolTable = .{}, |
| 21 | 21 | |
| 22 | /// Table of tracked Decls. | |
| 23 | decls: DeclTable = .{}, | |
| 24 | ||
| 25 | /// Table of unnamed constants associated with a parent `Decl`. | |
| 26 | /// We store them here so that we can free the constants whenever the `Decl` | |
| 27 | /// needs updating or is freed. | |
| 28 | /// | |
| 29 | /// For example, | |
| 30 | /// | |
| 31 | /// ```zig | |
| 32 | /// const Foo = struct{ | |
| 33 | /// a: u8, | |
| 34 | /// }; | |
| 35 | /// | |
| 36 | /// pub fn main() void { | |
| 37 | /// var foo = Foo{ .a = 1 }; | |
| 38 | /// _ = foo; | |
| 39 | /// } | |
| 40 | /// ``` | |
| 41 | /// | |
| 42 | /// value assigned to label `foo` is an unnamed constant belonging/associated | |
| 43 | /// with `Decl` `main`, and lives as long as that `Decl`. | |
| 44 | unnamed_consts: UnnamedConstTable = .{}, | |
| 45 | ||
| 46 | /// Table of tracked AnonDecls. | |
| 47 | anon_decls: AnonDeclTable = .{}, | |
| 22 | /// Table of tracked Navs. | |
| 23 | navs: NavTable = .{}, | |
| 24 | ||
| 25 | /// Table of tracked Uavs. | |
| 26 | uavs: UavTable = .{}, | |
| 48 | 27 | |
| 49 | 28 | /// TLV initializers indexed by Atom.Index. |
| 50 | 29 | tlv_initializers: TlvInitializerTable = .{}, |
| ... | ... | @@ -100,31 +79,17 @@ pub fn deinit(self: *ZigObject, allocator: Allocator) void { |
| 100 | 79 | self.atoms_indexes.deinit(allocator); |
| 101 | 80 | self.atoms_extra.deinit(allocator); |
| 102 | 81 | |
| 103 | { | |
| 104 | var it = self.decls.iterator(); | |
| 105 | while (it.next()) |entry| { | |
| 106 | entry.value_ptr.exports.deinit(allocator); | |
| 107 | } | |
| 108 | self.decls.deinit(allocator); | |
| 82 | for (self.navs.values()) |*meta| { | |
| 83 | meta.exports.deinit(allocator); | |
| 109 | 84 | } |
| 85 | self.navs.deinit(allocator); | |
| 110 | 86 | |
| 111 | 87 | self.lazy_syms.deinit(allocator); |
| 112 | 88 | |
| 113 | { | |
| 114 | var it = self.unnamed_consts.valueIterator(); | |
| 115 | while (it.next()) |syms| { | |
| 116 | syms.deinit(allocator); | |
| 117 | } | |
| 118 | self.unnamed_consts.deinit(allocator); | |
| 119 | } | |
| 120 | ||
| 121 | { | |
| 122 | var it = self.anon_decls.iterator(); | |
| 123 | while (it.next()) |entry| { | |
| 124 | entry.value_ptr.exports.deinit(allocator); | |
| 125 | } | |
| 126 | self.anon_decls.deinit(allocator); | |
| 89 | for (self.uavs.values()) |*meta| { | |
| 90 | meta.exports.deinit(allocator); | |
| 127 | 91 | } |
| 92 | self.uavs.deinit(allocator); | |
| 128 | 93 | |
| 129 | 94 | for (self.relocs.items) |*list| { |
| 130 | 95 | list.deinit(allocator); |
| ... | ... | @@ -601,7 +566,7 @@ pub fn getInputSection(self: ZigObject, atom: Atom, macho_file: *MachO) macho.se |
| 601 | 566 | |
| 602 | 567 | pub fn flushModule(self: *ZigObject, macho_file: *MachO, tid: Zcu.PerThread.Id) !void { |
| 603 | 568 | // Handle any lazy symbols that were emitted by incremental compilation. |
| 604 | if (self.lazy_syms.getPtr(.none)) |metadata| { | |
| 569 | if (self.lazy_syms.getPtr(.anyerror_type)) |metadata| { | |
| 605 | 570 | const pt: Zcu.PerThread = .{ .zcu = macho_file.base.comp.module.?, .tid = tid }; |
| 606 | 571 | |
| 607 | 572 | // Most lazy symbols can be updated on first use, but |
| ... | ... | @@ -609,7 +574,7 @@ pub fn flushModule(self: *ZigObject, macho_file: *MachO, tid: Zcu.PerThread.Id) |
| 609 | 574 | if (metadata.text_state != .unused) self.updateLazySymbol( |
| 610 | 575 | macho_file, |
| 611 | 576 | pt, |
| 612 | link.File.LazySymbol.initDecl(.code, null, pt.zcu), | |
| 577 | .{ .kind = .code, .ty = .anyerror_type }, | |
| 613 | 578 | metadata.text_symbol_index, |
| 614 | 579 | ) catch |err| return switch (err) { |
| 615 | 580 | error.CodegenFail => error.FlushFailure, |
| ... | ... | @@ -618,7 +583,7 @@ pub fn flushModule(self: *ZigObject, macho_file: *MachO, tid: Zcu.PerThread.Id) |
| 618 | 583 | if (metadata.const_state != .unused) self.updateLazySymbol( |
| 619 | 584 | macho_file, |
| 620 | 585 | pt, |
| 621 | link.File.LazySymbol.initDecl(.const_data, null, pt.zcu), | |
| 586 | .{ .kind = .const_data, .ty = .anyerror_type }, | |
| 622 | 587 | metadata.const_symbol_index, |
| 623 | 588 | ) catch |err| return switch (err) { |
| 624 | 589 | error.CodegenFail => error.FlushFailure, |
| ... | ... | @@ -691,25 +656,25 @@ pub fn flushModule(self: *ZigObject, macho_file: *MachO, tid: Zcu.PerThread.Id) |
| 691 | 656 | assert(!self.debug_strtab_dirty); |
| 692 | 657 | } |
| 693 | 658 | |
| 694 | pub fn getDeclVAddr( | |
| 659 | pub fn getNavVAddr( | |
| 695 | 660 | self: *ZigObject, |
| 696 | 661 | macho_file: *MachO, |
| 697 | 662 | pt: Zcu.PerThread, |
| 698 | decl_index: InternPool.DeclIndex, | |
| 663 | nav_index: InternPool.Nav.Index, | |
| 699 | 664 | reloc_info: link.File.RelocInfo, |
| 700 | 665 | ) !u64 { |
| 701 | 666 | const zcu = pt.zcu; |
| 702 | 667 | const ip = &zcu.intern_pool; |
| 703 | const decl = zcu.declPtr(decl_index); | |
| 704 | log.debug("getDeclVAddr {}({d})", .{ decl.fqn.fmt(ip), decl_index }); | |
| 705 | const sym_index = if (decl.isExtern(zcu)) blk: { | |
| 706 | const name = decl.name.toSlice(ip); | |
| 707 | const lib_name = if (decl.getOwnedExternFunc(zcu)) |ext_fn| | |
| 708 | ext_fn.lib_name.toSlice(ip) | |
| 709 | else | |
| 710 | decl.getOwnedVariable(zcu).?.lib_name.toSlice(ip); | |
| 711 | break :blk try self.getGlobalSymbol(macho_file, name, lib_name); | |
| 712 | } else try self.getOrCreateMetadataForDecl(macho_file, decl_index); | |
| 668 | const nav = ip.getNav(nav_index); | |
| 669 | log.debug("getNavVAddr {}({d})", .{ nav.fqn.fmt(ip), nav_index }); | |
| 670 | const sym_index = switch (ip.indexToKey(nav.status.resolved.val)) { | |
| 671 | .@"extern" => |@"extern"| try self.getGlobalSymbol( | |
| 672 | macho_file, | |
| 673 | nav.name.toSlice(ip), | |
| 674 | @"extern".lib_name.toSlice(ip), | |
| 675 | ), | |
| 676 | else => try self.getOrCreateMetadataForNav(macho_file, nav_index), | |
| 677 | }; | |
| 713 | 678 | const sym = self.symbols.items[sym_index]; |
| 714 | 679 | const vaddr = sym.getAddress(.{}, macho_file); |
| 715 | 680 | const parent_atom = self.symbols.items[reloc_info.parent_atom_index].getAtom(macho_file).?; |
| ... | ... | @@ -729,13 +694,13 @@ pub fn getDeclVAddr( |
| 729 | 694 | return vaddr; |
| 730 | 695 | } |
| 731 | 696 | |
| 732 | pub fn getAnonDeclVAddr( | |
| 697 | pub fn getUavVAddr( | |
| 733 | 698 | self: *ZigObject, |
| 734 | 699 | macho_file: *MachO, |
| 735 | decl_val: InternPool.Index, | |
| 700 | uav: InternPool.Index, | |
| 736 | 701 | reloc_info: link.File.RelocInfo, |
| 737 | 702 | ) !u64 { |
| 738 | const sym_index = self.anon_decls.get(decl_val).?.symbol_index; | |
| 703 | const sym_index = self.uavs.get(uav).?.symbol_index; | |
| 739 | 704 | const sym = self.symbols.items[sym_index]; |
| 740 | 705 | const vaddr = sym.getAddress(.{}, macho_file); |
| 741 | 706 | const parent_atom = self.symbols.items[reloc_info.parent_atom_index].getAtom(macho_file).?; |
| ... | ... | @@ -755,42 +720,43 @@ pub fn getAnonDeclVAddr( |
| 755 | 720 | return vaddr; |
| 756 | 721 | } |
| 757 | 722 | |
| 758 | pub fn lowerAnonDecl( | |
| 723 | pub fn lowerUav( | |
| 759 | 724 | self: *ZigObject, |
| 760 | 725 | macho_file: *MachO, |
| 761 | 726 | pt: Zcu.PerThread, |
| 762 | decl_val: InternPool.Index, | |
| 727 | uav: InternPool.Index, | |
| 763 | 728 | explicit_alignment: Atom.Alignment, |
| 764 | src_loc: Module.LazySrcLoc, | |
| 765 | ) !codegen.Result { | |
| 766 | const gpa = macho_file.base.comp.gpa; | |
| 767 | const mod = macho_file.base.comp.module.?; | |
| 768 | const ty = Type.fromInterned(mod.intern_pool.typeOf(decl_val)); | |
| 769 | const decl_alignment = switch (explicit_alignment) { | |
| 770 | .none => ty.abiAlignment(pt), | |
| 729 | src_loc: Zcu.LazySrcLoc, | |
| 730 | ) !codegen.GenResult { | |
| 731 | const zcu = pt.zcu; | |
| 732 | const gpa = zcu.gpa; | |
| 733 | const val = Value.fromInterned(uav); | |
| 734 | const uav_alignment = switch (explicit_alignment) { | |
| 735 | .none => val.typeOf(zcu).abiAlignment(pt), | |
| 771 | 736 | else => explicit_alignment, |
| 772 | 737 | }; |
| 773 | if (self.anon_decls.get(decl_val)) |metadata| { | |
| 774 | const existing_alignment = self.symbols.items[metadata.symbol_index].getAtom(macho_file).?.alignment; | |
| 775 | if (decl_alignment.order(existing_alignment).compare(.lte)) | |
| 776 | return .ok; | |
| 738 | if (self.uavs.get(uav)) |metadata| { | |
| 739 | const sym = self.symbols.items[metadata.symbol_index]; | |
| 740 | const existing_alignment = sym.getAtom(macho_file).?.alignment; | |
| 741 | if (uav_alignment.order(existing_alignment).compare(.lte)) | |
| 742 | return .{ .mcv = .{ .load_symbol = sym.nlist_idx } }; | |
| 777 | 743 | } |
| 778 | 744 | |
| 779 | 745 | var name_buf: [32]u8 = undefined; |
| 780 | 746 | const name = std.fmt.bufPrint(&name_buf, "__anon_{d}", .{ |
| 781 | @intFromEnum(decl_val), | |
| 747 | @intFromEnum(uav), | |
| 782 | 748 | }) catch unreachable; |
| 783 | 749 | const res = self.lowerConst( |
| 784 | 750 | macho_file, |
| 785 | 751 | pt, |
| 786 | 752 | name, |
| 787 | Value.fromInterned(decl_val), | |
| 788 | decl_alignment, | |
| 753 | val, | |
| 754 | uav_alignment, | |
| 789 | 755 | macho_file.zig_const_sect_index.?, |
| 790 | 756 | src_loc, |
| 791 | 757 | ) catch |err| switch (err) { |
| 792 | 758 | error.OutOfMemory => return error.OutOfMemory, |
| 793 | else => |e| return .{ .fail = try Module.ErrorMsg.create( | |
| 759 | else => |e| return .{ .fail = try Zcu.ErrorMsg.create( | |
| 794 | 760 | gpa, |
| 795 | 761 | src_loc, |
| 796 | 762 | "unable to lower constant value: {s}", |
| ... | ... | @@ -801,20 +767,13 @@ pub fn lowerAnonDecl( |
| 801 | 767 | .ok => |sym_index| sym_index, |
| 802 | 768 | .fail => |em| return .{ .fail = em }, |
| 803 | 769 | }; |
| 804 | try self.anon_decls.put(gpa, decl_val, .{ .symbol_index = sym_index }); | |
| 805 | return .ok; | |
| 806 | } | |
| 807 | ||
| 808 | fn freeUnnamedConsts(self: *ZigObject, macho_file: *MachO, decl_index: InternPool.DeclIndex) void { | |
| 809 | const gpa = macho_file.base.comp.gpa; | |
| 810 | const unnamed_consts = self.unnamed_consts.getPtr(decl_index) orelse return; | |
| 811 | for (unnamed_consts.items) |sym_index| { | |
| 812 | self.freeDeclMetadata(macho_file, sym_index); | |
| 813 | } | |
| 814 | unnamed_consts.clearAndFree(gpa); | |
| 770 | try self.uavs.put(gpa, uav, .{ .symbol_index = sym_index }); | |
| 771 | return .{ .mcv = .{ | |
| 772 | .load_symbol = self.symbols.items[sym_index].nlist_idx, | |
| 773 | } }; | |
| 815 | 774 | } |
| 816 | 775 | |
| 817 | fn freeDeclMetadata(self: *ZigObject, macho_file: *MachO, sym_index: Symbol.Index) void { | |
| 776 | fn freeNavMetadata(self: *ZigObject, macho_file: *MachO, sym_index: Symbol.Index) void { | |
| 818 | 777 | const sym = self.symbols.items[sym_index]; |
| 819 | 778 | sym.getAtom(macho_file).?.free(macho_file); |
| 820 | 779 | log.debug("adding %{d} to local symbols free list", .{sym_index}); |
| ... | ... | @@ -822,18 +781,14 @@ fn freeDeclMetadata(self: *ZigObject, macho_file: *MachO, sym_index: Symbol.Inde |
| 822 | 781 | // TODO free GOT entry here |
| 823 | 782 | } |
| 824 | 783 | |
| 825 | pub fn freeDecl(self: *ZigObject, macho_file: *MachO, decl_index: InternPool.DeclIndex) void { | |
| 784 | pub fn freeNav(self: *ZigObject, macho_file: *MachO, nav_index: InternPool.Nav.Index) void { | |
| 826 | 785 | const gpa = macho_file.base.comp.gpa; |
| 827 | const mod = macho_file.base.comp.module.?; | |
| 828 | const decl = mod.declPtr(decl_index); | |
| 786 | log.debug("freeNav 0x{x}", .{nav_index}); | |
| 829 | 787 | |
| 830 | log.debug("freeDecl {*}", .{decl}); | |
| 831 | ||
| 832 | if (self.decls.fetchRemove(decl_index)) |const_kv| { | |
| 788 | if (self.navs.fetchRemove(nav_index)) |const_kv| { | |
| 833 | 789 | var kv = const_kv; |
| 834 | 790 | const sym_index = kv.value.symbol_index; |
| 835 | self.freeDeclMetadata(macho_file, sym_index); | |
| 836 | self.freeUnnamedConsts(macho_file, decl_index); | |
| 791 | self.freeNavMetadata(macho_file, sym_index); | |
| 837 | 792 | kv.value.exports.deinit(gpa); |
| 838 | 793 | } |
| 839 | 794 | |
| ... | ... | @@ -851,51 +806,46 @@ pub fn updateFunc( |
| 851 | 806 | const tracy = trace(@src()); |
| 852 | 807 | defer tracy.end(); |
| 853 | 808 | |
| 854 | const mod = pt.zcu; | |
| 855 | const gpa = mod.gpa; | |
| 856 | const func = mod.funcInfo(func_index); | |
| 857 | const decl_index = func.owner_decl; | |
| 858 | const decl = mod.declPtr(decl_index); | |
| 809 | const zcu = pt.zcu; | |
| 810 | const gpa = zcu.gpa; | |
| 811 | const func = zcu.funcInfo(func_index); | |
| 859 | 812 | |
| 860 | const sym_index = try self.getOrCreateMetadataForDecl(macho_file, decl_index); | |
| 861 | self.freeUnnamedConsts(macho_file, decl_index); | |
| 813 | const sym_index = try self.getOrCreateMetadataForNav(macho_file, func.owner_nav); | |
| 862 | 814 | self.symbols.items[sym_index].getAtom(macho_file).?.freeRelocs(macho_file); |
| 863 | 815 | |
| 864 | 816 | var code_buffer = std.ArrayList(u8).init(gpa); |
| 865 | 817 | defer code_buffer.deinit(); |
| 866 | 818 | |
| 867 | var decl_state: ?Dwarf.DeclState = if (self.dwarf) |*dw| try dw.initDeclState(pt, decl_index) else null; | |
| 868 | defer if (decl_state) |*ds| ds.deinit(); | |
| 819 | var dwarf_state = if (self.dwarf) |*dw| try dw.initNavState(pt, func.owner_nav) else null; | |
| 820 | defer if (dwarf_state) |*ds| ds.deinit(); | |
| 869 | 821 | |
| 870 | const dio: codegen.DebugInfoOutput = if (decl_state) |*ds| .{ .dwarf = ds } else .none; | |
| 871 | 822 | const res = try codegen.generateFunction( |
| 872 | 823 | &macho_file.base, |
| 873 | 824 | pt, |
| 874 | decl.navSrcLoc(mod), | |
| 825 | zcu.navSrcLoc(func.owner_nav), | |
| 875 | 826 | func_index, |
| 876 | 827 | air, |
| 877 | 828 | liveness, |
| 878 | 829 | &code_buffer, |
| 879 | dio, | |
| 830 | if (dwarf_state) |*ds| .{ .dwarf = ds } else .none, | |
| 880 | 831 | ); |
| 881 | 832 | |
| 882 | 833 | const code = switch (res) { |
| 883 | 834 | .ok => code_buffer.items, |
| 884 | 835 | .fail => |em| { |
| 885 | func.setAnalysisState(&mod.intern_pool, .codegen_failure); | |
| 886 | try mod.failed_analysis.put(mod.gpa, AnalUnit.wrap(.{ .decl = decl_index }), em); | |
| 836 | try zcu.failed_codegen.put(gpa, func.owner_nav, em); | |
| 887 | 837 | return; |
| 888 | 838 | }, |
| 889 | 839 | }; |
| 890 | 840 | |
| 891 | const sect_index = try self.getDeclOutputSection(macho_file, decl, code); | |
| 892 | try self.updateDeclCode(macho_file, pt, decl_index, sym_index, sect_index, code); | |
| 841 | const sect_index = try self.getNavOutputSection(macho_file, zcu, func.owner_nav, code); | |
| 842 | try self.updateNavCode(macho_file, pt, func.owner_nav, sym_index, sect_index, code); | |
| 893 | 843 | |
| 894 | if (decl_state) |*ds| { | |
| 844 | if (dwarf_state) |*ds| { | |
| 895 | 845 | const sym = self.symbols.items[sym_index]; |
| 896 | try self.dwarf.?.commitDeclState( | |
| 846 | try self.dwarf.?.commitNavState( | |
| 897 | 847 | pt, |
| 898 | decl_index, | |
| 848 | func.owner_nav, | |
| 899 | 849 | sym.getAddress(.{}, macho_file), |
| 900 | 850 | sym.getAtom(macho_file).?.size, |
| 901 | 851 | ds, |
| ... | ... | @@ -905,96 +855,98 @@ pub fn updateFunc( |
| 905 | 855 | // Exports will be updated by `Zcu.processExports` after the update. |
| 906 | 856 | } |
| 907 | 857 | |
| 908 | pub fn updateDecl( | |
| 858 | pub fn updateNav( | |
| 909 | 859 | self: *ZigObject, |
| 910 | 860 | macho_file: *MachO, |
| 911 | 861 | pt: Zcu.PerThread, |
| 912 | decl_index: InternPool.DeclIndex, | |
| 913 | ) link.File.UpdateDeclError!void { | |
| 862 | nav_index: InternPool.Nav.Index, | |
| 863 | ) link.File.UpdateNavError!void { | |
| 914 | 864 | const tracy = trace(@src()); |
| 915 | 865 | defer tracy.end(); |
| 916 | 866 | |
| 917 | const mod = pt.zcu; | |
| 918 | const decl = mod.declPtr(decl_index); | |
| 919 | ||
| 920 | if (decl.val.getExternFunc(mod)) |_| { | |
| 921 | return; | |
| 922 | } | |
| 923 | ||
| 924 | if (decl.isExtern(mod)) { | |
| 925 | // Extern variable gets a __got entry only | |
| 926 | const variable = decl.getOwnedVariable(mod).?; | |
| 927 | const name = decl.name.toSlice(&mod.intern_pool); | |
| 928 | const lib_name = variable.lib_name.toSlice(&mod.intern_pool); | |
| 929 | const index = try self.getGlobalSymbol(macho_file, name, lib_name); | |
| 930 | const sym = &self.symbols.items[index]; | |
| 931 | sym.setSectionFlags(.{ .needs_got = true }); | |
| 932 | return; | |
| 933 | } | |
| 867 | const zcu = pt.zcu; | |
| 868 | const ip = &zcu.intern_pool; | |
| 869 | const nav_val = zcu.navValue(nav_index); | |
| 870 | const nav_init = switch (ip.indexToKey(nav_val.toIntern())) { | |
| 871 | .variable => |variable| Value.fromInterned(variable.init), | |
| 872 | .@"extern" => |@"extern"| { | |
| 873 | if (ip.isFunctionType(@"extern".ty)) return; | |
| 874 | // Extern variable gets a __got entry only | |
| 875 | const name = @"extern".name.toSlice(ip); | |
| 876 | const lib_name = @"extern".lib_name.toSlice(ip); | |
| 877 | const index = try self.getGlobalSymbol(macho_file, name, lib_name); | |
| 878 | const sym = &self.symbols.items[index]; | |
| 879 | sym.setSectionFlags(.{ .needs_got = true }); | |
| 880 | return; | |
| 881 | }, | |
| 882 | else => nav_val, | |
| 883 | }; | |
| 934 | 884 | |
| 935 | const sym_index = try self.getOrCreateMetadataForDecl(macho_file, decl_index); | |
| 885 | const sym_index = try self.getOrCreateMetadataForNav(macho_file, nav_index); | |
| 936 | 886 | self.symbols.items[sym_index].getAtom(macho_file).?.freeRelocs(macho_file); |
| 937 | 887 | |
| 938 | const gpa = macho_file.base.comp.gpa; | |
| 939 | var code_buffer = std.ArrayList(u8).init(gpa); | |
| 888 | var code_buffer = std.ArrayList(u8).init(zcu.gpa); | |
| 940 | 889 | defer code_buffer.deinit(); |
| 941 | 890 | |
| 942 | var decl_state: ?Dwarf.DeclState = if (self.dwarf) |*dw| try dw.initDeclState(pt, decl_index) else null; | |
| 943 | defer if (decl_state) |*ds| ds.deinit(); | |
| 891 | var nav_state: ?Dwarf.NavState = if (self.dwarf) |*dw| try dw.initNavState(pt, nav_index) else null; | |
| 892 | defer if (nav_state) |*ns| ns.deinit(); | |
| 944 | 893 | |
| 945 | const decl_val = if (decl.val.getVariable(mod)) |variable| Value.fromInterned(variable.init) else decl.val; | |
| 946 | const dio: codegen.DebugInfoOutput = if (decl_state) |*ds| .{ .dwarf = ds } else .none; | |
| 947 | const res = try codegen.generateSymbol(&macho_file.base, pt, decl.navSrcLoc(mod), decl_val, &code_buffer, dio, .{ | |
| 948 | .parent_atom_index = sym_index, | |
| 949 | }); | |
| 894 | const res = try codegen.generateSymbol( | |
| 895 | &macho_file.base, | |
| 896 | pt, | |
| 897 | zcu.navSrcLoc(nav_index), | |
| 898 | nav_init, | |
| 899 | &code_buffer, | |
| 900 | if (nav_state) |*ns| .{ .dwarf = ns } else .none, | |
| 901 | .{ .parent_atom_index = sym_index }, | |
| 902 | ); | |
| 950 | 903 | |
| 951 | 904 | const code = switch (res) { |
| 952 | 905 | .ok => code_buffer.items, |
| 953 | 906 | .fail => |em| { |
| 954 | decl.analysis = .codegen_failure; | |
| 955 | try mod.failed_analysis.put(mod.gpa, AnalUnit.wrap(.{ .decl = decl_index }), em); | |
| 907 | try zcu.failed_codegen.put(zcu.gpa, nav_index, em); | |
| 956 | 908 | return; |
| 957 | 909 | }, |
| 958 | 910 | }; |
| 959 | if (isThreadlocal(macho_file, decl_index)) { | |
| 960 | const sect_index = try self.getDeclOutputSection(macho_file, decl, code); | |
| 961 | try self.updateTlv(macho_file, pt, decl_index, sym_index, sect_index, code); | |
| 962 | } else { | |
| 963 | const sect_index = try self.getDeclOutputSection(macho_file, decl, code); | |
| 964 | try self.updateDeclCode(macho_file, pt, decl_index, sym_index, sect_index, code); | |
| 965 | } | |
| 911 | const sect_index = try self.getNavOutputSection(macho_file, zcu, nav_index, code); | |
| 912 | if (isThreadlocal(macho_file, nav_index)) | |
| 913 | try self.updateTlv(macho_file, pt, nav_index, sym_index, sect_index, code) | |
| 914 | else | |
| 915 | try self.updateNavCode(macho_file, pt, nav_index, sym_index, sect_index, code); | |
| 966 | 916 | |
| 967 | if (decl_state) |*ds| { | |
| 917 | if (nav_state) |*ns| { | |
| 968 | 918 | const sym = self.symbols.items[sym_index]; |
| 969 | try self.dwarf.?.commitDeclState( | |
| 919 | try self.dwarf.?.commitNavState( | |
| 970 | 920 | pt, |
| 971 | decl_index, | |
| 921 | nav_index, | |
| 972 | 922 | sym.getAddress(.{}, macho_file), |
| 973 | 923 | sym.getAtom(macho_file).?.size, |
| 974 | ds, | |
| 924 | ns, | |
| 975 | 925 | ); |
| 976 | 926 | } |
| 977 | 927 | |
| 978 | 928 | // Exports will be updated by `Zcu.processExports` after the update. |
| 979 | 929 | } |
| 980 | 930 | |
| 981 | fn updateDeclCode( | |
| 931 | fn updateNavCode( | |
| 982 | 932 | self: *ZigObject, |
| 983 | 933 | macho_file: *MachO, |
| 984 | 934 | pt: Zcu.PerThread, |
| 985 | decl_index: InternPool.DeclIndex, | |
| 935 | nav_index: InternPool.Nav.Index, | |
| 986 | 936 | sym_index: Symbol.Index, |
| 987 | 937 | sect_index: u8, |
| 988 | 938 | code: []const u8, |
| 989 | 939 | ) !void { |
| 990 | const gpa = macho_file.base.comp.gpa; | |
| 991 | const mod = pt.zcu; | |
| 992 | const ip = &mod.intern_pool; | |
| 993 | const decl = mod.declPtr(decl_index); | |
| 940 | const zcu = pt.zcu; | |
| 941 | const gpa = zcu.gpa; | |
| 942 | const ip = &zcu.intern_pool; | |
| 943 | const nav = ip.getNav(nav_index); | |
| 994 | 944 | |
| 995 | log.debug("updateDeclCode {}{*}", .{ decl.fqn.fmt(ip), decl }); | |
| 945 | log.debug("updateNavCode {} 0x{x}", .{ nav.fqn.fmt(ip), nav_index }); | |
| 996 | 946 | |
| 997 | const required_alignment = decl.getAlignment(pt); | |
| 947 | const required_alignment = pt.navAlignment(nav_index).max( | |
| 948 | target_util.minFunctionAlignment(zcu.navFileScope(nav_index).mod.resolved_target.result), | |
| 949 | ); | |
| 998 | 950 | |
| 999 | 951 | const sect = &macho_file.sections.items(.header)[sect_index]; |
| 1000 | 952 | const sym = &self.symbols.items[sym_index]; |
| ... | ... | @@ -1004,7 +956,7 @@ fn updateDeclCode( |
| 1004 | 956 | sym.out_n_sect = sect_index; |
| 1005 | 957 | atom.out_n_sect = sect_index; |
| 1006 | 958 | |
| 1007 | const sym_name = try std.fmt.allocPrintZ(gpa, "_{s}", .{decl.fqn.toSlice(ip)}); | |
| 959 | const sym_name = try std.fmt.allocPrintZ(gpa, "_{s}", .{nav.fqn.toSlice(ip)}); | |
| 1008 | 960 | defer gpa.free(sym_name); |
| 1009 | 961 | sym.name = try self.addString(gpa, sym_name); |
| 1010 | 962 | atom.setAlive(true); |
| ... | ... | @@ -1025,7 +977,7 @@ fn updateDeclCode( |
| 1025 | 977 | |
| 1026 | 978 | if (need_realloc) { |
| 1027 | 979 | try atom.grow(macho_file); |
| 1028 | log.debug("growing {} from 0x{x} to 0x{x}", .{ decl.fqn.fmt(ip), old_vaddr, atom.value }); | |
| 980 | log.debug("growing {} from 0x{x} to 0x{x}", .{ nav.fqn.fmt(ip), old_vaddr, atom.value }); | |
| 1029 | 981 | if (old_vaddr != atom.value) { |
| 1030 | 982 | sym.value = 0; |
| 1031 | 983 | nlist.n_value = 0; |
| ... | ... | @@ -1045,7 +997,7 @@ fn updateDeclCode( |
| 1045 | 997 | } |
| 1046 | 998 | } else { |
| 1047 | 999 | try atom.allocate(macho_file); |
| 1048 | errdefer self.freeDeclMetadata(macho_file, sym_index); | |
| 1000 | errdefer self.freeNavMetadata(macho_file, sym_index); | |
| 1049 | 1001 | |
| 1050 | 1002 | sym.value = 0; |
| 1051 | 1003 | sym.setSectionFlags(.{ .needs_zig_got = true }); |
| ... | ... | @@ -1070,27 +1022,27 @@ fn updateTlv( |
| 1070 | 1022 | self: *ZigObject, |
| 1071 | 1023 | macho_file: *MachO, |
| 1072 | 1024 | pt: Zcu.PerThread, |
| 1073 | decl_index: InternPool.DeclIndex, | |
| 1025 | nav_index: InternPool.Nav.Index, | |
| 1074 | 1026 | sym_index: Symbol.Index, |
| 1075 | 1027 | sect_index: u8, |
| 1076 | 1028 | code: []const u8, |
| 1077 | 1029 | ) !void { |
| 1078 | 1030 | const ip = &pt.zcu.intern_pool; |
| 1079 | const decl = pt.zcu.declPtr(decl_index); | |
| 1031 | const nav = ip.getNav(nav_index); | |
| 1080 | 1032 | |
| 1081 | log.debug("updateTlv {} ({*})", .{ decl.fqn.fmt(&pt.zcu.intern_pool), decl }); | |
| 1033 | log.debug("updateTlv {} (0x{x})", .{ nav.fqn.fmt(ip), nav_index }); | |
| 1082 | 1034 | |
| 1083 | 1035 | // 1. Lower TLV initializer |
| 1084 | 1036 | const init_sym_index = try self.createTlvInitializer( |
| 1085 | 1037 | macho_file, |
| 1086 | decl.fqn.toSlice(ip), | |
| 1087 | decl.getAlignment(pt), | |
| 1038 | nav.fqn.toSlice(ip), | |
| 1039 | pt.navAlignment(nav_index), | |
| 1088 | 1040 | sect_index, |
| 1089 | 1041 | code, |
| 1090 | 1042 | ); |
| 1091 | 1043 | |
| 1092 | 1044 | // 2. Create TLV descriptor |
| 1093 | try self.createTlvDescriptor(macho_file, sym_index, init_sym_index, decl.fqn.toSlice(ip)); | |
| 1045 | try self.createTlvDescriptor(macho_file, sym_index, init_sym_index, nav.fqn.toSlice(ip)); | |
| 1094 | 1046 | } |
| 1095 | 1047 | |
| 1096 | 1048 | fn createTlvInitializer( |
| ... | ... | @@ -1197,102 +1149,52 @@ fn createTlvDescriptor( |
| 1197 | 1149 | }); |
| 1198 | 1150 | } |
| 1199 | 1151 | |
| 1200 | fn getDeclOutputSection( | |
| 1152 | fn getNavOutputSection( | |
| 1201 | 1153 | self: *ZigObject, |
| 1202 | 1154 | macho_file: *MachO, |
| 1203 | decl: *const Module.Decl, | |
| 1155 | zcu: *Zcu, | |
| 1156 | nav_index: InternPool.Nav.Index, | |
| 1204 | 1157 | code: []const u8, |
| 1205 | 1158 | ) error{OutOfMemory}!u8 { |
| 1206 | 1159 | _ = self; |
| 1207 | const mod = macho_file.base.comp.module.?; | |
| 1160 | const ip = &zcu.intern_pool; | |
| 1208 | 1161 | const any_non_single_threaded = macho_file.base.comp.config.any_non_single_threaded; |
| 1209 | const sect_id: u8 = switch (decl.typeOf(mod).zigTypeTag(mod)) { | |
| 1210 | .Fn => macho_file.zig_text_sect_index.?, | |
| 1211 | else => blk: { | |
| 1212 | if (decl.getOwnedVariable(mod)) |variable| { | |
| 1213 | if (variable.is_threadlocal and any_non_single_threaded) { | |
| 1214 | const is_all_zeroes = for (code) |byte| { | |
| 1215 | if (byte != 0) break false; | |
| 1216 | } else true; | |
| 1217 | if (is_all_zeroes) break :blk macho_file.getSectionByName("__DATA", "__thread_bss") orelse try macho_file.addSection( | |
| 1218 | "__DATA", | |
| 1219 | "__thread_bss", | |
| 1220 | .{ .flags = macho.S_THREAD_LOCAL_ZEROFILL }, | |
| 1221 | ); | |
| 1222 | break :blk macho_file.getSectionByName("__DATA", "__thread_data") orelse try macho_file.addSection( | |
| 1223 | "__DATA", | |
| 1224 | "__thread_data", | |
| 1225 | .{ .flags = macho.S_THREAD_LOCAL_REGULAR }, | |
| 1226 | ); | |
| 1227 | } | |
| 1228 | ||
| 1229 | if (variable.is_const) break :blk macho_file.zig_const_sect_index.?; | |
| 1230 | if (Value.fromInterned(variable.init).isUndefDeep(mod)) { | |
| 1231 | // TODO: get the optimize_mode from the Module that owns the decl instead | |
| 1232 | // of using the root module here. | |
| 1233 | break :blk switch (macho_file.base.comp.root_mod.optimize_mode) { | |
| 1234 | .Debug, .ReleaseSafe => macho_file.zig_data_sect_index.?, | |
| 1235 | .ReleaseFast, .ReleaseSmall => macho_file.zig_bss_sect_index.?, | |
| 1236 | }; | |
| 1237 | } | |
| 1238 | ||
| 1239 | // TODO I blatantly copied the logic from the Wasm linker, but is there a less | |
| 1240 | // intrusive check for all zeroes than this? | |
| 1241 | const is_all_zeroes = for (code) |byte| { | |
| 1242 | if (byte != 0) break false; | |
| 1243 | } else true; | |
| 1244 | if (is_all_zeroes) break :blk macho_file.zig_bss_sect_index.?; | |
| 1245 | break :blk macho_file.zig_data_sect_index.?; | |
| 1246 | } | |
| 1247 | break :blk macho_file.zig_const_sect_index.?; | |
| 1248 | }, | |
| 1162 | const nav_val = zcu.navValue(nav_index); | |
| 1163 | if (ip.isFunctionType(nav_val.typeOf(zcu).toIntern())) return macho_file.zig_text_sect_index.?; | |
| 1164 | const is_const, const is_threadlocal, const nav_init = switch (ip.indexToKey(nav_val.toIntern())) { | |
| 1165 | .variable => |variable| .{ false, variable.is_threadlocal, variable.init }, | |
| 1166 | .@"extern" => |@"extern"| .{ @"extern".is_const, @"extern".is_threadlocal, .none }, | |
| 1167 | else => .{ true, false, nav_val.toIntern() }, | |
| 1249 | 1168 | }; |
| 1250 | return sect_id; | |
| 1251 | } | |
| 1252 | ||
| 1253 | pub fn lowerUnnamedConst( | |
| 1254 | self: *ZigObject, | |
| 1255 | macho_file: *MachO, | |
| 1256 | pt: Zcu.PerThread, | |
| 1257 | val: Value, | |
| 1258 | decl_index: InternPool.DeclIndex, | |
| 1259 | ) !u32 { | |
| 1260 | const mod = pt.zcu; | |
| 1261 | const gpa = mod.gpa; | |
| 1262 | const gop = try self.unnamed_consts.getOrPut(gpa, decl_index); | |
| 1263 | if (!gop.found_existing) { | |
| 1264 | gop.value_ptr.* = .{}; | |
| 1169 | if (any_non_single_threaded and is_threadlocal) { | |
| 1170 | for (code) |byte| { | |
| 1171 | if (byte != 0) break; | |
| 1172 | } else return macho_file.getSectionByName("__DATA", "__thread_bss") orelse try macho_file.addSection( | |
| 1173 | "__DATA", | |
| 1174 | "__thread_bss", | |
| 1175 | .{ .flags = macho.S_THREAD_LOCAL_ZEROFILL }, | |
| 1176 | ); | |
| 1177 | return macho_file.getSectionByName("__DATA", "__thread_data") orelse try macho_file.addSection( | |
| 1178 | "__DATA", | |
| 1179 | "__thread_data", | |
| 1180 | .{ .flags = macho.S_THREAD_LOCAL_REGULAR }, | |
| 1181 | ); | |
| 1265 | 1182 | } |
| 1266 | const unnamed_consts = gop.value_ptr; | |
| 1267 | const decl = mod.declPtr(decl_index); | |
| 1268 | const index = unnamed_consts.items.len; | |
| 1269 | const name = try std.fmt.allocPrint(gpa, "__unnamed_{}_{d}", .{ decl.fqn.fmt(&mod.intern_pool), index }); | |
| 1270 | defer gpa.free(name); | |
| 1271 | const sym_index = switch (try self.lowerConst( | |
| 1272 | macho_file, | |
| 1273 | pt, | |
| 1274 | name, | |
| 1275 | val, | |
| 1276 | val.typeOf(mod).abiAlignment(pt), | |
| 1277 | macho_file.zig_const_sect_index.?, | |
| 1278 | decl.navSrcLoc(mod), | |
| 1279 | )) { | |
| 1280 | .ok => |sym_index| sym_index, | |
| 1281 | .fail => |em| { | |
| 1282 | decl.analysis = .codegen_failure; | |
| 1283 | try mod.failed_analysis.put(mod.gpa, AnalUnit.wrap(.{ .decl = decl_index }), em); | |
| 1284 | log.err("{s}", .{em.msg}); | |
| 1285 | return error.CodegenFail; | |
| 1286 | }, | |
| 1287 | }; | |
| 1288 | const sym = self.symbols.items[sym_index]; | |
| 1289 | try unnamed_consts.append(gpa, sym.atom_ref.index); | |
| 1290 | return sym_index; | |
| 1183 | if (is_const) return macho_file.zig_const_sect_index.?; | |
| 1184 | if (nav_init != .none and Value.fromInterned(nav_init).isUndefDeep(zcu)) | |
| 1185 | return switch (zcu.navFileScope(nav_index).mod.optimize_mode) { | |
| 1186 | .Debug, .ReleaseSafe => macho_file.zig_data_sect_index.?, | |
| 1187 | .ReleaseFast, .ReleaseSmall => macho_file.zig_bss_sect_index.?, | |
| 1188 | }; | |
| 1189 | for (code) |byte| { | |
| 1190 | if (byte != 0) break; | |
| 1191 | } else return macho_file.zig_bss_sect_index.?; | |
| 1192 | return macho_file.zig_data_sect_index.?; | |
| 1291 | 1193 | } |
| 1292 | 1194 | |
| 1293 | 1195 | const LowerConstResult = union(enum) { |
| 1294 | 1196 | ok: Symbol.Index, |
| 1295 | fail: *Module.ErrorMsg, | |
| 1197 | fail: *Zcu.ErrorMsg, | |
| 1296 | 1198 | }; |
| 1297 | 1199 | |
| 1298 | 1200 | fn lowerConst( |
| ... | ... | @@ -1303,7 +1205,7 @@ fn lowerConst( |
| 1303 | 1205 | val: Value, |
| 1304 | 1206 | required_alignment: Atom.Alignment, |
| 1305 | 1207 | output_section_index: u8, |
| 1306 | src_loc: Module.LazySrcLoc, | |
| 1208 | src_loc: Zcu.LazySrcLoc, | |
| 1307 | 1209 | ) !LowerConstResult { |
| 1308 | 1210 | const gpa = macho_file.base.comp.gpa; |
| 1309 | 1211 | |
| ... | ... | @@ -1338,7 +1240,7 @@ fn lowerConst( |
| 1338 | 1240 | |
| 1339 | 1241 | try atom.allocate(macho_file); |
| 1340 | 1242 | // TODO rename and re-audit this method |
| 1341 | errdefer self.freeDeclMetadata(macho_file, sym_index); | |
| 1243 | errdefer self.freeNavMetadata(macho_file, sym_index); | |
| 1342 | 1244 | |
| 1343 | 1245 | const sect = macho_file.sections.items(.header)[output_section_index]; |
| 1344 | 1246 | const file_offset = sect.offset + atom.value; |
| ... | ... | @@ -1351,7 +1253,7 @@ pub fn updateExports( |
| 1351 | 1253 | self: *ZigObject, |
| 1352 | 1254 | macho_file: *MachO, |
| 1353 | 1255 | pt: Zcu.PerThread, |
| 1354 | exported: Module.Exported, | |
| 1256 | exported: Zcu.Exported, | |
| 1355 | 1257 | export_indices: []const u32, |
| 1356 | 1258 | ) link.File.UpdateExportsError!void { |
| 1357 | 1259 | const tracy = trace(@src()); |
| ... | ... | @@ -1360,24 +1262,24 @@ pub fn updateExports( |
| 1360 | 1262 | const mod = pt.zcu; |
| 1361 | 1263 | const gpa = macho_file.base.comp.gpa; |
| 1362 | 1264 | const metadata = switch (exported) { |
| 1363 | .decl_index => |decl_index| blk: { | |
| 1364 | _ = try self.getOrCreateMetadataForDecl(macho_file, decl_index); | |
| 1365 | break :blk self.decls.getPtr(decl_index).?; | |
| 1265 | .nav => |nav| blk: { | |
| 1266 | _ = try self.getOrCreateMetadataForNav(macho_file, nav); | |
| 1267 | break :blk self.navs.getPtr(nav).?; | |
| 1366 | 1268 | }, |
| 1367 | .value => |value| self.anon_decls.getPtr(value) orelse blk: { | |
| 1269 | .uav => |uav| self.uavs.getPtr(uav) orelse blk: { | |
| 1368 | 1270 | const first_exp = mod.all_exports.items[export_indices[0]]; |
| 1369 | const res = try self.lowerAnonDecl(macho_file, pt, value, .none, first_exp.src); | |
| 1271 | const res = try self.lowerUav(macho_file, pt, uav, .none, first_exp.src); | |
| 1370 | 1272 | switch (res) { |
| 1371 | .ok => {}, | |
| 1273 | .mcv => {}, | |
| 1372 | 1274 | .fail => |em| { |
| 1373 | // TODO maybe it's enough to return an error here and let Module.processExportsInner | |
| 1275 | // TODO maybe it's enough to return an error here and let Zcu.processExportsInner | |
| 1374 | 1276 | // handle the error? |
| 1375 | 1277 | try mod.failed_exports.ensureUnusedCapacity(mod.gpa, 1); |
| 1376 | 1278 | mod.failed_exports.putAssumeCapacityNoClobber(export_indices[0], em); |
| 1377 | 1279 | return; |
| 1378 | 1280 | }, |
| 1379 | 1281 | } |
| 1380 | break :blk self.anon_decls.getPtr(value).?; | |
| 1282 | break :blk self.uavs.getPtr(uav).?; | |
| 1381 | 1283 | }, |
| 1382 | 1284 | }; |
| 1383 | 1285 | const sym_index = metadata.symbol_index; |
| ... | ... | @@ -1389,7 +1291,7 @@ pub fn updateExports( |
| 1389 | 1291 | if (exp.opts.section.unwrap()) |section_name| { |
| 1390 | 1292 | if (!section_name.eqlSlice("__text", &mod.intern_pool)) { |
| 1391 | 1293 | try mod.failed_exports.ensureUnusedCapacity(mod.gpa, 1); |
| 1392 | mod.failed_exports.putAssumeCapacityNoClobber(export_idx, try Module.ErrorMsg.create( | |
| 1294 | mod.failed_exports.putAssumeCapacityNoClobber(export_idx, try Zcu.ErrorMsg.create( | |
| 1393 | 1295 | gpa, |
| 1394 | 1296 | exp.src, |
| 1395 | 1297 | "Unimplemented: ExportOptions.section", |
| ... | ... | @@ -1399,7 +1301,7 @@ pub fn updateExports( |
| 1399 | 1301 | } |
| 1400 | 1302 | } |
| 1401 | 1303 | if (exp.opts.linkage == .link_once) { |
| 1402 | try mod.failed_exports.putNoClobber(mod.gpa, export_idx, try Module.ErrorMsg.create( | |
| 1304 | try mod.failed_exports.putNoClobber(mod.gpa, export_idx, try Zcu.ErrorMsg.create( | |
| 1403 | 1305 | gpa, |
| 1404 | 1306 | exp.src, |
| 1405 | 1307 | "Unimplemented: GlobalLinkage.link_once", |
| ... | ... | @@ -1454,8 +1356,8 @@ fn updateLazySymbol( |
| 1454 | 1356 | lazy_sym: link.File.LazySymbol, |
| 1455 | 1357 | symbol_index: Symbol.Index, |
| 1456 | 1358 | ) !void { |
| 1457 | const gpa = macho_file.base.comp.gpa; | |
| 1458 | const mod = macho_file.base.comp.module.?; | |
| 1359 | const zcu = pt.zcu; | |
| 1360 | const gpa = zcu.gpa; | |
| 1459 | 1361 | |
| 1460 | 1362 | var required_alignment: Atom.Alignment = .none; |
| 1461 | 1363 | var code_buffer = std.ArrayList(u8).init(gpa); |
| ... | ... | @@ -1464,13 +1366,13 @@ fn updateLazySymbol( |
| 1464 | 1366 | const name_str = blk: { |
| 1465 | 1367 | const name = try std.fmt.allocPrint(gpa, "__lazy_{s}_{}", .{ |
| 1466 | 1368 | @tagName(lazy_sym.kind), |
| 1467 | lazy_sym.ty.fmt(pt), | |
| 1369 | Type.fromInterned(lazy_sym.ty).fmt(pt), | |
| 1468 | 1370 | }); |
| 1469 | 1371 | defer gpa.free(name); |
| 1470 | 1372 | break :blk try self.addString(gpa, name); |
| 1471 | 1373 | }; |
| 1472 | 1374 | |
| 1473 | const src = lazy_sym.ty.srcLocOrNull(mod) orelse Module.LazySrcLoc.unneeded; | |
| 1375 | const src = Type.fromInterned(lazy_sym.ty).srcLocOrNull(zcu) orelse Zcu.LazySrcLoc.unneeded; | |
| 1474 | 1376 | const res = try codegen.generateLazySymbol( |
| 1475 | 1377 | &macho_file.base, |
| 1476 | 1378 | pt, |
| ... | ... | @@ -1511,7 +1413,7 @@ fn updateLazySymbol( |
| 1511 | 1413 | atom.out_n_sect = output_section_index; |
| 1512 | 1414 | |
| 1513 | 1415 | try atom.allocate(macho_file); |
| 1514 | errdefer self.freeDeclMetadata(macho_file, symbol_index); | |
| 1416 | errdefer self.freeNavMetadata(macho_file, symbol_index); | |
| 1515 | 1417 | |
| 1516 | 1418 | sym.value = 0; |
| 1517 | 1419 | sym.setSectionFlags(.{ .needs_zig_got = true }); |
| ... | ... | @@ -1527,10 +1429,14 @@ fn updateLazySymbol( |
| 1527 | 1429 | try macho_file.base.file.?.pwriteAll(code, file_offset); |
| 1528 | 1430 | } |
| 1529 | 1431 | |
| 1530 | /// Must be called only after a successful call to `updateDecl`. | |
| 1531 | pub fn updateDeclLineNumber(self: *ZigObject, pt: Zcu.PerThread, decl_index: InternPool.DeclIndex) !void { | |
| 1432 | /// Must be called only after a successful call to `updateNav`. | |
| 1433 | pub fn updateNavLineNumber( | |
| 1434 | self: *ZigObject, | |
| 1435 | pt: Zcu.PerThread, | |
| 1436 | nav_index: InternPool.Nav.Index, | |
| 1437 | ) !void { | |
| 1532 | 1438 | if (self.dwarf) |*dw| { |
| 1533 | try dw.updateDeclLineNumber(pt.zcu, decl_index); | |
| 1439 | try dw.updateNavLineNumber(pt.zcu, nav_index); | |
| 1534 | 1440 | } |
| 1535 | 1441 | } |
| 1536 | 1442 | |
| ... | ... | @@ -1543,9 +1449,9 @@ pub fn deleteExport( |
| 1543 | 1449 | const mod = macho_file.base.comp.module.?; |
| 1544 | 1450 | |
| 1545 | 1451 | const metadata = switch (exported) { |
| 1546 | .decl_index => |decl_index| self.decls.getPtr(decl_index) orelse return, | |
| 1547 | .value => |value| self.anon_decls.getPtr(value) orelse return, | |
| 1548 | }; | |
| 1452 | .nav => |nav| self.navs.getPtr(nav), | |
| 1453 | .uav => |uav| self.uavs.getPtr(uav), | |
| 1454 | } orelse return; | |
| 1549 | 1455 | const nlist_index = metadata.@"export"(self, name.toSlice(&mod.intern_pool)) orelse return; |
| 1550 | 1456 | |
| 1551 | 1457 | log.debug("deleting export '{}'", .{name.fmt(&mod.intern_pool)}); |
| ... | ... | @@ -1577,17 +1483,17 @@ pub fn getGlobalSymbol(self: *ZigObject, macho_file: *MachO, name: []const u8, l |
| 1577 | 1483 | return lookup_gop.value_ptr.*; |
| 1578 | 1484 | } |
| 1579 | 1485 | |
| 1580 | pub fn getOrCreateMetadataForDecl( | |
| 1486 | pub fn getOrCreateMetadataForNav( | |
| 1581 | 1487 | self: *ZigObject, |
| 1582 | 1488 | macho_file: *MachO, |
| 1583 | decl_index: InternPool.DeclIndex, | |
| 1489 | nav_index: InternPool.Nav.Index, | |
| 1584 | 1490 | ) !Symbol.Index { |
| 1585 | 1491 | const gpa = macho_file.base.comp.gpa; |
| 1586 | const gop = try self.decls.getOrPut(gpa, decl_index); | |
| 1492 | const gop = try self.navs.getOrPut(gpa, nav_index); | |
| 1587 | 1493 | if (!gop.found_existing) { |
| 1588 | 1494 | const sym_index = try self.newSymbolWithAtom(gpa, .{}, macho_file); |
| 1589 | 1495 | const sym = &self.symbols.items[sym_index]; |
| 1590 | if (isThreadlocal(macho_file, decl_index)) { | |
| 1496 | if (isThreadlocal(macho_file, nav_index)) { | |
| 1591 | 1497 | sym.flags.tlv = true; |
| 1592 | 1498 | } else { |
| 1593 | 1499 | sym.setSectionFlags(.{ .needs_zig_got = true }); |
| ... | ... | @@ -1603,47 +1509,39 @@ pub fn getOrCreateMetadataForLazySymbol( |
| 1603 | 1509 | pt: Zcu.PerThread, |
| 1604 | 1510 | lazy_sym: link.File.LazySymbol, |
| 1605 | 1511 | ) !Symbol.Index { |
| 1606 | const mod = pt.zcu; | |
| 1607 | const gpa = mod.gpa; | |
| 1608 | const gop = try self.lazy_syms.getOrPut(gpa, lazy_sym.getDecl(mod)); | |
| 1512 | const gop = try self.lazy_syms.getOrPut(pt.zcu.gpa, lazy_sym.ty); | |
| 1609 | 1513 | errdefer _ = if (!gop.found_existing) self.lazy_syms.pop(); |
| 1610 | 1514 | if (!gop.found_existing) gop.value_ptr.* = .{}; |
| 1611 | const metadata: struct { | |
| 1612 | symbol_index: *Symbol.Index, | |
| 1613 | state: *LazySymbolMetadata.State, | |
| 1614 | } = switch (lazy_sym.kind) { | |
| 1615 | .code => .{ | |
| 1616 | .symbol_index = &gop.value_ptr.text_symbol_index, | |
| 1617 | .state = &gop.value_ptr.text_state, | |
| 1618 | }, | |
| 1619 | .const_data => .{ | |
| 1620 | .symbol_index = &gop.value_ptr.const_symbol_index, | |
| 1621 | .state = &gop.value_ptr.const_state, | |
| 1622 | }, | |
| 1515 | const symbol_index_ptr, const state_ptr = switch (lazy_sym.kind) { | |
| 1516 | .code => .{ &gop.value_ptr.text_symbol_index, &gop.value_ptr.text_state }, | |
| 1517 | .const_data => .{ &gop.value_ptr.const_symbol_index, &gop.value_ptr.const_state }, | |
| 1623 | 1518 | }; |
| 1624 | switch (metadata.state.*) { | |
| 1519 | switch (state_ptr.*) { | |
| 1625 | 1520 | .unused => { |
| 1626 | const symbol_index = try self.newSymbolWithAtom(gpa, .{}, macho_file); | |
| 1521 | const symbol_index = try self.newSymbolWithAtom(pt.zcu.gpa, .{}, macho_file); | |
| 1627 | 1522 | const sym = &self.symbols.items[symbol_index]; |
| 1628 | 1523 | sym.setSectionFlags(.{ .needs_zig_got = true }); |
| 1629 | metadata.symbol_index.* = symbol_index; | |
| 1524 | symbol_index_ptr.* = symbol_index; | |
| 1630 | 1525 | }, |
| 1631 | .pending_flush => return metadata.symbol_index.*, | |
| 1526 | .pending_flush => return symbol_index_ptr.*, | |
| 1632 | 1527 | .flushed => {}, |
| 1633 | 1528 | } |
| 1634 | metadata.state.* = .pending_flush; | |
| 1635 | const symbol_index = metadata.symbol_index.*; | |
| 1529 | state_ptr.* = .pending_flush; | |
| 1530 | const symbol_index = symbol_index_ptr.*; | |
| 1636 | 1531 | // anyerror needs to be deferred until flushModule |
| 1637 | if (lazy_sym.getDecl(mod) != .none) try self.updateLazySymbol(macho_file, pt, lazy_sym, symbol_index); | |
| 1532 | if (lazy_sym.ty != .anyerror_type) try self.updateLazySymbol(macho_file, pt, lazy_sym, symbol_index); | |
| 1638 | 1533 | return symbol_index; |
| 1639 | 1534 | } |
| 1640 | 1535 | |
| 1641 | fn isThreadlocal(macho_file: *MachO, decl_index: InternPool.DeclIndex) bool { | |
| 1642 | const any_non_single_threaded = macho_file.base.comp.config.any_non_single_threaded; | |
| 1643 | const zcu = macho_file.base.comp.module.?; | |
| 1644 | const decl = zcu.declPtr(decl_index); | |
| 1645 | const variable = decl.getOwnedVariable(zcu) orelse return false; | |
| 1646 | return variable.is_threadlocal and any_non_single_threaded; | |
| 1536 | fn isThreadlocal(macho_file: *MachO, nav_index: InternPool.Nav.Index) bool { | |
| 1537 | if (!macho_file.base.comp.config.any_non_single_threaded) | |
| 1538 | return false; | |
| 1539 | const ip = &macho_file.base.comp.module.?.intern_pool; | |
| 1540 | return switch (ip.indexToKey(ip.getNav(nav_index).status.resolved.val)) { | |
| 1541 | .variable => |variable| variable.is_threadlocal, | |
| 1542 | .@"extern" => |@"extern"| @"extern".is_threadlocal, | |
| 1543 | else => false, | |
| 1544 | }; | |
| 1647 | 1545 | } |
| 1648 | 1546 | |
| 1649 | 1547 | fn addAtom(self: *ZigObject, allocator: Allocator) !Atom.Index { |
| ... | ... | @@ -1848,12 +1746,12 @@ fn formatAtoms( |
| 1848 | 1746 | } |
| 1849 | 1747 | } |
| 1850 | 1748 | |
| 1851 | const DeclMetadata = struct { | |
| 1749 | const AvMetadata = struct { | |
| 1852 | 1750 | symbol_index: Symbol.Index, |
| 1853 | /// A list of all exports aliases of this Decl. | |
| 1751 | /// A list of all exports aliases of this Av. | |
| 1854 | 1752 | exports: std.ArrayListUnmanaged(Symbol.Index) = .{}, |
| 1855 | 1753 | |
| 1856 | fn @"export"(m: DeclMetadata, zig_object: *ZigObject, name: []const u8) ?*u32 { | |
| 1754 | fn @"export"(m: AvMetadata, zig_object: *ZigObject, name: []const u8) ?*u32 { | |
| 1857 | 1755 | for (m.exports.items) |*exp| { |
| 1858 | 1756 | const nlist = zig_object.symtab.items(.nlist)[exp.*]; |
| 1859 | 1757 | const exp_name = zig_object.strtab.getAssumeExists(nlist.n_strx); |
| ... | ... | @@ -1880,10 +1778,9 @@ const TlvInitializer = struct { |
| 1880 | 1778 | } |
| 1881 | 1779 | }; |
| 1882 | 1780 | |
| 1883 | const DeclTable = std.AutoHashMapUnmanaged(InternPool.DeclIndex, DeclMetadata); | |
| 1884 | const UnnamedConstTable = std.AutoHashMapUnmanaged(InternPool.DeclIndex, std.ArrayListUnmanaged(Symbol.Index)); | |
| 1885 | const AnonDeclTable = std.AutoHashMapUnmanaged(InternPool.Index, DeclMetadata); | |
| 1886 | const LazySymbolTable = std.AutoArrayHashMapUnmanaged(InternPool.OptionalDeclIndex, LazySymbolMetadata); | |
| 1781 | const NavTable = std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, AvMetadata); | |
| 1782 | const UavTable = std.AutoArrayHashMapUnmanaged(InternPool.Index, AvMetadata); | |
| 1783 | const LazySymbolTable = std.AutoArrayHashMapUnmanaged(InternPool.Index, LazySymbolMetadata); | |
| 1887 | 1784 | const RelocationTable = std.ArrayListUnmanaged(std.ArrayListUnmanaged(Relocation)); |
| 1888 | 1785 | const TlvInitializerTable = std.AutoArrayHashMapUnmanaged(Atom.Index, TlvInitializer); |
| 1889 | 1786 | |
| ... | ... | @@ -1894,6 +1791,7 @@ const link = @import("../../link.zig"); |
| 1894 | 1791 | const log = std.log.scoped(.link); |
| 1895 | 1792 | const macho = std.macho; |
| 1896 | 1793 | const mem = std.mem; |
| 1794 | const target_util = @import("../../target.zig"); | |
| 1897 | 1795 | const trace = @import("../../tracy.zig").trace; |
| 1898 | 1796 | const std = @import("std"); |
| 1899 | 1797 | |
| ... | ... | @@ -1908,8 +1806,6 @@ const Liveness = @import("../../Liveness.zig"); |
| 1908 | 1806 | const MachO = @import("../MachO.zig"); |
| 1909 | 1807 | const Nlist = Object.Nlist; |
| 1910 | 1808 | const Zcu = @import("../../Zcu.zig"); |
| 1911 | /// Deprecated. | |
| 1912 | const Module = Zcu; | |
| 1913 | 1809 | const Object = @import("Object.zig"); |
| 1914 | 1810 | const Relocation = @import("Relocation.zig"); |
| 1915 | 1811 | const Symbol = @import("Symbol.zig"); |
src/link/NvPtx.zig+2-2| ... | ... | @@ -86,8 +86,8 @@ pub fn updateFunc(self: *NvPtx, pt: Zcu.PerThread, func_index: InternPool.Index, |
| 86 | 86 | try self.llvm_object.updateFunc(pt, func_index, air, liveness); |
| 87 | 87 | } |
| 88 | 88 | |
| 89 | pub fn updateDecl(self: *NvPtx, pt: Zcu.PerThread, decl_index: InternPool.DeclIndex) !void { | |
| 90 | return self.llvm_object.updateDecl(pt, decl_index); | |
| 89 | pub fn updateNav(self: *NvPtx, pt: Zcu.PerThread, nav: InternPool.Nav.Index) !void { | |
| 90 | return self.llvm_object.updateNav(pt, nav); | |
| 91 | 91 | } |
| 92 | 92 | |
| 93 | 93 | pub fn updateExports( |
src/link/Plan9.zig+191-336| ... | ... | @@ -24,8 +24,6 @@ const Allocator = std.mem.Allocator; |
| 24 | 24 | const log = std.log.scoped(.link); |
| 25 | 25 | const assert = std.debug.assert; |
| 26 | 26 | |
| 27 | pub const base_tag = .plan9; | |
| 28 | ||
| 29 | 27 | base: link.File, |
| 30 | 28 | sixtyfour_bit: bool, |
| 31 | 29 | bases: Bases, |
| ... | ... | @@ -53,40 +51,19 @@ path_arena: std.heap.ArenaAllocator, |
| 53 | 51 | /// The debugger looks for the first file (aout.Sym.Type.z) preceeding the text symbol |
| 54 | 52 | /// of the function to know what file it came from. |
| 55 | 53 | /// If we group the decls by file, it makes it really easy to do this (put the symbol in the correct place) |
| 56 | fn_decl_table: std.AutoArrayHashMapUnmanaged( | |
| 57 | *Zcu.File, | |
| 58 | struct { sym_index: u32, functions: std.AutoArrayHashMapUnmanaged(InternPool.DeclIndex, FnDeclOutput) = .{} }, | |
| 54 | fn_nav_table: std.AutoArrayHashMapUnmanaged( | |
| 55 | Zcu.File.Index, | |
| 56 | struct { sym_index: u32, functions: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, FnNavOutput) = .{} }, | |
| 59 | 57 | ) = .{}, |
| 60 | 58 | /// the code is modified when relocated, so that is why it is mutable |
| 61 | data_decl_table: std.AutoArrayHashMapUnmanaged(InternPool.DeclIndex, []u8) = .{}, | |
| 59 | data_nav_table: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, []u8) = .{}, | |
| 62 | 60 | /// When `updateExports` is called, we store the export indices here, to be used |
| 63 | 61 | /// during flush. |
| 64 | decl_exports: std.AutoArrayHashMapUnmanaged(InternPool.DeclIndex, []u32) = .{}, | |
| 65 | ||
| 66 | /// Table of unnamed constants associated with a parent `Decl`. | |
| 67 | /// We store them here so that we can free the constants whenever the `Decl` | |
| 68 | /// needs updating or is freed. | |
| 69 | /// | |
| 70 | /// For example, | |
| 71 | /// | |
| 72 | /// ```zig | |
| 73 | /// const Foo = struct{ | |
| 74 | /// a: u8, | |
| 75 | /// }; | |
| 76 | /// | |
| 77 | /// pub fn main() void { | |
| 78 | /// var foo = Foo{ .a = 1 }; | |
| 79 | /// _ = foo; | |
| 80 | /// } | |
| 81 | /// ``` | |
| 82 | /// | |
| 83 | /// value assigned to label `foo` is an unnamed constant belonging/associated | |
| 84 | /// with `Decl` `main`, and lives as long as that `Decl`. | |
| 85 | unnamed_const_atoms: UnnamedConstTable = .{}, | |
| 62 | nav_exports: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, []u32) = .{}, | |
| 86 | 63 | |
| 87 | 64 | lazy_syms: LazySymbolTable = .{}, |
| 88 | 65 | |
| 89 | anon_decls: std.AutoHashMapUnmanaged(InternPool.Index, Atom.Index) = .{}, | |
| 66 | uavs: std.AutoHashMapUnmanaged(InternPool.Index, Atom.Index) = .{}, | |
| 90 | 67 | |
| 91 | 68 | relocs: std.AutoHashMapUnmanaged(Atom.Index, std.ArrayListUnmanaged(Reloc)) = .{}, |
| 92 | 69 | hdr: aout.ExecHdr = undefined, |
| ... | ... | @@ -104,7 +81,7 @@ got_index_free_list: std.ArrayListUnmanaged(usize) = .{}, |
| 104 | 81 | syms_index_free_list: std.ArrayListUnmanaged(usize) = .{}, |
| 105 | 82 | |
| 106 | 83 | atoms: std.ArrayListUnmanaged(Atom) = .{}, |
| 107 | decls: std.AutoHashMapUnmanaged(InternPool.DeclIndex, DeclMetadata) = .{}, | |
| 84 | navs: std.AutoHashMapUnmanaged(InternPool.Nav.Index, NavMetadata) = .{}, | |
| 108 | 85 | |
| 109 | 86 | /// Indices of the three "special" symbols into atoms |
| 110 | 87 | etext_edata_end_atom_indices: [3]?Atom.Index = .{ null, null, null }, |
| ... | ... | @@ -131,9 +108,7 @@ const Bases = struct { |
| 131 | 108 | data: u64, |
| 132 | 109 | }; |
| 133 | 110 | |
| 134 | const UnnamedConstTable = std.AutoHashMapUnmanaged(InternPool.DeclIndex, std.ArrayListUnmanaged(Atom.Index)); | |
| 135 | ||
| 136 | const LazySymbolTable = std.AutoArrayHashMapUnmanaged(InternPool.OptionalDeclIndex, LazySymbolMetadata); | |
| 111 | const LazySymbolTable = std.AutoArrayHashMapUnmanaged(InternPool.Index, LazySymbolMetadata); | |
| 137 | 112 | |
| 138 | 113 | const LazySymbolMetadata = struct { |
| 139 | 114 | const State = enum { unused, pending_flush, flushed }; |
| ... | ... | @@ -161,7 +136,7 @@ pub const Atom = struct { |
| 161 | 136 | /// offset into got |
| 162 | 137 | got_index: ?usize, |
| 163 | 138 | /// We include the code here to be use in relocs |
| 164 | /// In the case of unnamed_const_atoms and lazy_syms, this atom owns the code. | |
| 139 | /// In the case of lazy_syms, this atom owns the code. | |
| 165 | 140 | /// But, in the case of function and data decls, they own the code and this field |
| 166 | 141 | /// is just a pointer for convience. |
| 167 | 142 | code: CodePtr, |
| ... | ... | @@ -170,22 +145,23 @@ pub const Atom = struct { |
| 170 | 145 | code_ptr: ?[*]u8, |
| 171 | 146 | other: union { |
| 172 | 147 | code_len: usize, |
| 173 | decl_index: InternPool.DeclIndex, | |
| 148 | nav_index: InternPool.Nav.Index, | |
| 174 | 149 | }, |
| 175 | 150 | fn fromSlice(slice: []u8) CodePtr { |
| 176 | 151 | return .{ .code_ptr = slice.ptr, .other = .{ .code_len = slice.len } }; |
| 177 | 152 | } |
| 178 | 153 | fn getCode(self: CodePtr, plan9: *const Plan9) []u8 { |
| 179 | const mod = plan9.base.comp.module.?; | |
| 154 | const zcu = plan9.base.comp.module.?; | |
| 155 | const ip = &zcu.intern_pool; | |
| 180 | 156 | return if (self.code_ptr) |p| p[0..self.other.code_len] else blk: { |
| 181 | const decl_index = self.other.decl_index; | |
| 182 | const decl = mod.declPtr(decl_index); | |
| 183 | if (decl.typeOf(mod).zigTypeTag(mod) == .Fn) { | |
| 184 | const table = plan9.fn_decl_table.get(decl.getFileScope(mod)).?.functions; | |
| 185 | const output = table.get(decl_index).?; | |
| 157 | const nav_index = self.other.nav_index; | |
| 158 | const nav = ip.getNav(nav_index); | |
| 159 | if (ip.isFunctionType(nav.typeOf(ip))) { | |
| 160 | const table = plan9.fn_nav_table.get(zcu.navFileScopeIndex(nav_index)).?.functions; | |
| 161 | const output = table.get(nav_index).?; | |
| 186 | 162 | break :blk output.code; |
| 187 | 163 | } else { |
| 188 | break :blk plan9.data_decl_table.get(decl_index).?; | |
| 164 | break :blk plan9.data_nav_table.get(nav_index).?; | |
| 189 | 165 | } |
| 190 | 166 | }; |
| 191 | 167 | } |
| ... | ... | @@ -241,11 +217,11 @@ pub const DebugInfoOutput = struct { |
| 241 | 217 | pc_quanta: u8, |
| 242 | 218 | }; |
| 243 | 219 | |
| 244 | const DeclMetadata = struct { | |
| 220 | const NavMetadata = struct { | |
| 245 | 221 | index: Atom.Index, |
| 246 | 222 | exports: std.ArrayListUnmanaged(usize) = .{}, |
| 247 | 223 | |
| 248 | fn getExport(m: DeclMetadata, p9: *const Plan9, name: []const u8) ?usize { | |
| 224 | fn getExport(m: NavMetadata, p9: *const Plan9, name: []const u8) ?usize { | |
| 249 | 225 | for (m.exports.items) |exp| { |
| 250 | 226 | const sym = p9.syms.items[exp]; |
| 251 | 227 | if (mem.eql(u8, name, sym.name)) return exp; |
| ... | ... | @@ -254,7 +230,7 @@ const DeclMetadata = struct { |
| 254 | 230 | } |
| 255 | 231 | }; |
| 256 | 232 | |
| 257 | const FnDeclOutput = struct { | |
| 233 | const FnNavOutput = struct { | |
| 258 | 234 | /// this code is modified when relocated so it is mutable |
| 259 | 235 | code: []u8, |
| 260 | 236 | /// this might have to be modified in the linker, so thats why its mutable |
| ... | ... | @@ -338,18 +314,18 @@ pub fn createEmpty( |
| 338 | 314 | return self; |
| 339 | 315 | } |
| 340 | 316 | |
| 341 | fn putFn(self: *Plan9, decl_index: InternPool.DeclIndex, out: FnDeclOutput) !void { | |
| 317 | fn putFn(self: *Plan9, nav_index: InternPool.Nav.Index, out: FnNavOutput) !void { | |
| 342 | 318 | const gpa = self.base.comp.gpa; |
| 343 | 319 | const mod = self.base.comp.module.?; |
| 344 | const decl = mod.declPtr(decl_index); | |
| 345 | const fn_map_res = try self.fn_decl_table.getOrPut(gpa, decl.getFileScope(mod)); | |
| 320 | const file_scope = mod.navFileScopeIndex(nav_index); | |
| 321 | const fn_map_res = try self.fn_nav_table.getOrPut(gpa, file_scope); | |
| 346 | 322 | if (fn_map_res.found_existing) { |
| 347 | if (try fn_map_res.value_ptr.functions.fetchPut(gpa, decl_index, out)) |old_entry| { | |
| 323 | if (try fn_map_res.value_ptr.functions.fetchPut(gpa, nav_index, out)) |old_entry| { | |
| 348 | 324 | gpa.free(old_entry.value.code); |
| 349 | 325 | gpa.free(old_entry.value.lineinfo); |
| 350 | 326 | } |
| 351 | 327 | } else { |
| 352 | const file = decl.getFileScope(mod); | |
| 328 | const file = mod.fileByIndex(file_scope); | |
| 353 | 329 | const arena = self.path_arena.allocator(); |
| 354 | 330 | // each file gets a symbol |
| 355 | 331 | fn_map_res.value_ptr.* = .{ |
| ... | ... | @@ -359,7 +335,7 @@ fn putFn(self: *Plan9, decl_index: InternPool.DeclIndex, out: FnDeclOutput) !voi |
| 359 | 335 | break :blk @as(u32, @intCast(self.syms.items.len - 1)); |
| 360 | 336 | }, |
| 361 | 337 | }; |
| 362 | try fn_map_res.value_ptr.functions.put(gpa, decl_index, out); | |
| 338 | try fn_map_res.value_ptr.functions.put(gpa, nav_index, out); | |
| 363 | 339 | |
| 364 | 340 | var a = std.ArrayList(u8).init(arena); |
| 365 | 341 | errdefer a.deinit(); |
| ... | ... | @@ -418,11 +394,8 @@ pub fn updateFunc(self: *Plan9, pt: Zcu.PerThread, func_index: InternPool.Index, |
| 418 | 394 | const gpa = mod.gpa; |
| 419 | 395 | const target = self.base.comp.root_mod.resolved_target.result; |
| 420 | 396 | const func = mod.funcInfo(func_index); |
| 421 | const decl_index = func.owner_decl; | |
| 422 | const decl = mod.declPtr(decl_index); | |
| 423 | self.freeUnnamedConsts(decl_index); | |
| 424 | 397 | |
| 425 | const atom_idx = try self.seeDecl(decl_index); | |
| 398 | const atom_idx = try self.seeNav(pt, func.owner_nav); | |
| 426 | 399 | |
| 427 | 400 | var code_buffer = std.ArrayList(u8).init(gpa); |
| 428 | 401 | defer code_buffer.deinit(); |
| ... | ... | @@ -439,7 +412,7 @@ pub fn updateFunc(self: *Plan9, pt: Zcu.PerThread, func_index: InternPool.Index, |
| 439 | 412 | const res = try codegen.generateFunction( |
| 440 | 413 | &self.base, |
| 441 | 414 | pt, |
| 442 | decl.navSrcLoc(mod), | |
| 415 | mod.navSrcLoc(func.owner_nav), | |
| 443 | 416 | func_index, |
| 444 | 417 | air, |
| 445 | 418 | liveness, |
| ... | ... | @@ -449,128 +422,72 @@ pub fn updateFunc(self: *Plan9, pt: Zcu.PerThread, func_index: InternPool.Index, |
| 449 | 422 | const code = switch (res) { |
| 450 | 423 | .ok => try code_buffer.toOwnedSlice(), |
| 451 | 424 | .fail => |em| { |
| 452 | func.setAnalysisState(&mod.intern_pool, .codegen_failure); | |
| 453 | try mod.failed_analysis.put(mod.gpa, AnalUnit.wrap(.{ .decl = decl_index }), em); | |
| 425 | try mod.failed_codegen.put(gpa, func.owner_nav, em); | |
| 454 | 426 | return; |
| 455 | 427 | }, |
| 456 | 428 | }; |
| 457 | 429 | self.getAtomPtr(atom_idx).code = .{ |
| 458 | 430 | .code_ptr = null, |
| 459 | .other = .{ .decl_index = decl_index }, | |
| 431 | .other = .{ .nav_index = func.owner_nav }, | |
| 460 | 432 | }; |
| 461 | const out: FnDeclOutput = .{ | |
| 433 | const out: FnNavOutput = .{ | |
| 462 | 434 | .code = code, |
| 463 | 435 | .lineinfo = try dbg_info_output.dbg_line.toOwnedSlice(), |
| 464 | 436 | .start_line = dbg_info_output.start_line.?, |
| 465 | 437 | .end_line = dbg_info_output.end_line, |
| 466 | 438 | }; |
| 467 | try self.putFn(decl_index, out); | |
| 468 | return self.updateFinish(decl_index); | |
| 439 | try self.putFn(func.owner_nav, out); | |
| 440 | return self.updateFinish(pt, func.owner_nav); | |
| 469 | 441 | } |
| 470 | 442 | |
| 471 | pub fn lowerUnnamedConst(self: *Plan9, pt: Zcu.PerThread, val: Value, decl_index: InternPool.DeclIndex) !u32 { | |
| 472 | const mod = pt.zcu; | |
| 473 | const gpa = mod.gpa; | |
| 474 | _ = try self.seeDecl(decl_index); | |
| 475 | var code_buffer = std.ArrayList(u8).init(gpa); | |
| 476 | defer code_buffer.deinit(); | |
| 477 | ||
| 478 | const decl = mod.declPtr(decl_index); | |
| 479 | ||
| 480 | const gop = try self.unnamed_const_atoms.getOrPut(gpa, decl_index); | |
| 481 | if (!gop.found_existing) { | |
| 482 | gop.value_ptr.* = .{}; | |
| 483 | } | |
| 484 | const unnamed_consts = gop.value_ptr; | |
| 485 | ||
| 486 | const index = unnamed_consts.items.len; | |
| 487 | // name is freed when the unnamed const is freed | |
| 488 | const name = try std.fmt.allocPrint(gpa, "__unnamed_{}_{d}", .{ decl.fqn.fmt(&mod.intern_pool), index }); | |
| 489 | ||
| 490 | const sym_index = try self.allocateSymbolIndex(); | |
| 491 | const new_atom_idx = try self.createAtom(); | |
| 492 | const info: Atom = .{ | |
| 493 | .type = .d, | |
| 494 | .offset = null, | |
| 495 | .sym_index = sym_index, | |
| 496 | .got_index = self.allocateGotIndex(), | |
| 497 | .code = undefined, // filled in later | |
| 498 | }; | |
| 499 | const sym: aout.Sym = .{ | |
| 500 | .value = undefined, | |
| 501 | .type = info.type, | |
| 502 | .name = name, | |
| 503 | }; | |
| 504 | self.syms.items[info.sym_index.?] = sym; | |
| 505 | ||
| 506 | const res = try codegen.generateSymbol(&self.base, pt, decl.navSrcLoc(mod), val, &code_buffer, .{ | |
| 507 | .none = {}, | |
| 508 | }, .{ | |
| 509 | .parent_atom_index = new_atom_idx, | |
| 510 | }); | |
| 511 | const code = switch (res) { | |
| 512 | .ok => code_buffer.items, | |
| 513 | .fail => |em| { | |
| 514 | decl.analysis = .codegen_failure; | |
| 515 | try mod.failed_analysis.put(mod.gpa, AnalUnit.wrap(.{ .decl = decl_index }), em); | |
| 516 | log.err("{s}", .{em.msg}); | |
| 517 | return error.CodegenFail; | |
| 443 | pub fn updateNav(self: *Plan9, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) !void { | |
| 444 | const zcu = pt.zcu; | |
| 445 | const gpa = zcu.gpa; | |
| 446 | const ip = &zcu.intern_pool; | |
| 447 | const nav = ip.getNav(nav_index); | |
| 448 | const nav_val = zcu.navValue(nav_index); | |
| 449 | const nav_init = switch (ip.indexToKey(nav_val.toIntern())) { | |
| 450 | .variable => |variable| Value.fromInterned(variable.init), | |
| 451 | .@"extern" => { | |
| 452 | log.debug("found extern decl: {}", .{nav.name.fmt(ip)}); | |
| 453 | return; | |
| 518 | 454 | }, |
| 455 | else => nav_val, | |
| 519 | 456 | }; |
| 520 | // duped_code is freed when the unnamed const is freed | |
| 521 | const duped_code = try gpa.dupe(u8, code); | |
| 522 | errdefer gpa.free(duped_code); | |
| 523 | const new_atom = self.getAtomPtr(new_atom_idx); | |
| 524 | new_atom.* = info; | |
| 525 | new_atom.code = .{ .code_ptr = duped_code.ptr, .other = .{ .code_len = duped_code.len } }; | |
| 526 | try unnamed_consts.append(gpa, new_atom_idx); | |
| 527 | // we return the new_atom_idx to codegen | |
| 528 | return new_atom_idx; | |
| 529 | } | |
| 530 | ||
| 531 | pub fn updateDecl(self: *Plan9, pt: Zcu.PerThread, decl_index: InternPool.DeclIndex) !void { | |
| 532 | const gpa = self.base.comp.gpa; | |
| 533 | const mod = pt.zcu; | |
| 534 | const decl = mod.declPtr(decl_index); | |
| 535 | ||
| 536 | if (decl.isExtern(mod)) { | |
| 537 | log.debug("found extern decl: {}", .{decl.name.fmt(&mod.intern_pool)}); | |
| 538 | return; | |
| 539 | } | |
| 540 | const atom_idx = try self.seeDecl(decl_index); | |
| 457 | const atom_idx = try self.seeNav(pt, nav_index); | |
| 541 | 458 | |
| 542 | 459 | var code_buffer = std.ArrayList(u8).init(gpa); |
| 543 | 460 | defer code_buffer.deinit(); |
| 544 | const decl_val = if (decl.val.getVariable(mod)) |variable| Value.fromInterned(variable.init) else decl.val; | |
| 545 | 461 | // TODO we need the symbol index for symbol in the table of locals for the containing atom |
| 546 | const res = try codegen.generateSymbol(&self.base, pt, decl.navSrcLoc(mod), decl_val, &code_buffer, .{ .none = {} }, .{ | |
| 547 | .parent_atom_index = @as(Atom.Index, @intCast(atom_idx)), | |
| 462 | const res = try codegen.generateSymbol(&self.base, pt, zcu.navSrcLoc(nav_index), nav_init, &code_buffer, .none, .{ | |
| 463 | .parent_atom_index = @intCast(atom_idx), | |
| 548 | 464 | }); |
| 549 | 465 | const code = switch (res) { |
| 550 | 466 | .ok => code_buffer.items, |
| 551 | 467 | .fail => |em| { |
| 552 | decl.analysis = .codegen_failure; | |
| 553 | try mod.failed_analysis.put(mod.gpa, AnalUnit.wrap(.{ .decl = decl_index }), em); | |
| 468 | try zcu.failed_codegen.put(gpa, nav_index, em); | |
| 554 | 469 | return; |
| 555 | 470 | }, |
| 556 | 471 | }; |
| 557 | try self.data_decl_table.ensureUnusedCapacity(gpa, 1); | |
| 472 | try self.data_nav_table.ensureUnusedCapacity(gpa, 1); | |
| 558 | 473 | const duped_code = try gpa.dupe(u8, code); |
| 559 | self.getAtomPtr(self.decls.get(decl_index).?.index).code = .{ .code_ptr = null, .other = .{ .decl_index = decl_index } }; | |
| 560 | if (self.data_decl_table.fetchPutAssumeCapacity(decl_index, duped_code)) |old_entry| { | |
| 474 | self.getAtomPtr(self.navs.get(nav_index).?.index).code = .{ .code_ptr = null, .other = .{ .nav_index = nav_index } }; | |
| 475 | if (self.data_nav_table.fetchPutAssumeCapacity(nav_index, duped_code)) |old_entry| { | |
| 561 | 476 | gpa.free(old_entry.value); |
| 562 | 477 | } |
| 563 | return self.updateFinish(decl_index); | |
| 478 | return self.updateFinish(pt, nav_index); | |
| 564 | 479 | } |
| 480 | ||
| 565 | 481 | /// called at the end of update{Decl,Func} |
| 566 | fn updateFinish(self: *Plan9, decl_index: InternPool.DeclIndex) !void { | |
| 567 | const gpa = self.base.comp.gpa; | |
| 568 | const mod = self.base.comp.module.?; | |
| 569 | const decl = mod.declPtr(decl_index); | |
| 570 | const is_fn = (decl.typeOf(mod).zigTypeTag(mod) == .Fn); | |
| 482 | fn updateFinish(self: *Plan9, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) !void { | |
| 483 | const zcu = pt.zcu; | |
| 484 | const gpa = zcu.gpa; | |
| 485 | const ip = &zcu.intern_pool; | |
| 486 | const nav = ip.getNav(nav_index); | |
| 487 | const is_fn = ip.isFunctionType(nav.typeOf(ip)); | |
| 571 | 488 | const sym_t: aout.Sym.Type = if (is_fn) .t else .d; |
| 572 | 489 | |
| 573 | const atom = self.getAtomPtr(self.decls.get(decl_index).?.index); | |
| 490 | const atom = self.getAtomPtr(self.navs.get(nav_index).?.index); | |
| 574 | 491 | // write the internal linker metadata |
| 575 | 492 | atom.type = sym_t; |
| 576 | 493 | // write the symbol |
| ... | ... | @@ -578,7 +495,7 @@ fn updateFinish(self: *Plan9, decl_index: InternPool.DeclIndex) !void { |
| 578 | 495 | const sym: aout.Sym = .{ |
| 579 | 496 | .value = undefined, // the value of stuff gets filled in in flushModule |
| 580 | 497 | .type = atom.type, |
| 581 | .name = try gpa.dupe(u8, decl.name.toSlice(&mod.intern_pool)), | |
| 498 | .name = try gpa.dupe(u8, nav.name.toSlice(ip)), | |
| 582 | 499 | }; |
| 583 | 500 | |
| 584 | 501 | if (atom.sym_index) |s| { |
| ... | ... | @@ -643,29 +560,24 @@ fn externCount(self: *Plan9) usize { |
| 643 | 560 | } |
| 644 | 561 | return extern_atom_count; |
| 645 | 562 | } |
| 646 | // counts decls, unnamed consts, and lazy syms | |
| 563 | // counts decls, and lazy syms | |
| 647 | 564 | fn atomCount(self: *Plan9) usize { |
| 648 | var fn_decl_count: usize = 0; | |
| 649 | var itf_files = self.fn_decl_table.iterator(); | |
| 565 | var fn_nav_count: usize = 0; | |
| 566 | var itf_files = self.fn_nav_table.iterator(); | |
| 650 | 567 | while (itf_files.next()) |ent| { |
| 651 | 568 | // get the submap |
| 652 | 569 | var submap = ent.value_ptr.functions; |
| 653 | fn_decl_count += submap.count(); | |
| 654 | } | |
| 655 | const data_decl_count = self.data_decl_table.count(); | |
| 656 | var unnamed_const_count: usize = 0; | |
| 657 | var it_unc = self.unnamed_const_atoms.iterator(); | |
| 658 | while (it_unc.next()) |unnamed_consts| { | |
| 659 | unnamed_const_count += unnamed_consts.value_ptr.items.len; | |
| 570 | fn_nav_count += submap.count(); | |
| 660 | 571 | } |
| 572 | const data_nav_count = self.data_nav_table.count(); | |
| 661 | 573 | var lazy_atom_count: usize = 0; |
| 662 | 574 | var it_lazy = self.lazy_syms.iterator(); |
| 663 | 575 | while (it_lazy.next()) |kv| { |
| 664 | 576 | lazy_atom_count += kv.value_ptr.numberOfAtoms(); |
| 665 | 577 | } |
| 666 | const anon_atom_count = self.anon_decls.count(); | |
| 578 | const uav_atom_count = self.uavs.count(); | |
| 667 | 579 | const extern_atom_count = self.externCount(); |
| 668 | return data_decl_count + fn_decl_count + unnamed_const_count + lazy_atom_count + extern_atom_count + anon_atom_count; | |
| 580 | return data_nav_count + fn_nav_count + lazy_atom_count + extern_atom_count + uav_atom_count; | |
| 669 | 581 | } |
| 670 | 582 | |
| 671 | 583 | pub fn flushModule(self: *Plan9, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) link.File.FlushError!void { |
| ... | ... | @@ -700,7 +612,7 @@ pub fn flushModule(self: *Plan9, arena: Allocator, tid: Zcu.PerThread.Id, prog_n |
| 700 | 612 | // anyerror needs to wait for everything to be flushed. |
| 701 | 613 | if (metadata.text_state != .unused) self.updateLazySymbolAtom( |
| 702 | 614 | pt, |
| 703 | File.LazySymbol.initDecl(.code, null, pt.zcu), | |
| 615 | .{ .kind = .code, .ty = .anyerror_type }, | |
| 704 | 616 | metadata.text_atom, |
| 705 | 617 | ) catch |err| return switch (err) { |
| 706 | 618 | error.CodegenFail => error.FlushFailure, |
| ... | ... | @@ -708,7 +620,7 @@ pub fn flushModule(self: *Plan9, arena: Allocator, tid: Zcu.PerThread.Id, prog_n |
| 708 | 620 | }; |
| 709 | 621 | if (metadata.rodata_state != .unused) self.updateLazySymbolAtom( |
| 710 | 622 | pt, |
| 711 | File.LazySymbol.initDecl(.const_data, null, pt.zcu), | |
| 623 | .{ .kind = .const_data, .ty = .anyerror_type }, | |
| 712 | 624 | metadata.rodata_atom, |
| 713 | 625 | ) catch |err| return switch (err) { |
| 714 | 626 | error.CodegenFail => error.FlushFailure, |
| ... | ... | @@ -734,7 +646,7 @@ pub fn flushModule(self: *Plan9, arena: Allocator, tid: Zcu.PerThread.Id, prog_n |
| 734 | 646 | |
| 735 | 647 | var hdr_buf: [40]u8 = undefined; |
| 736 | 648 | // account for the fat header |
| 737 | const hdr_size = if (self.sixtyfour_bit) @as(usize, 40) else 32; | |
| 649 | const hdr_size: usize = if (self.sixtyfour_bit) 40 else 32; | |
| 738 | 650 | const hdr_slice: []u8 = hdr_buf[0..hdr_size]; |
| 739 | 651 | var foff = hdr_size; |
| 740 | 652 | iovecs[0] = .{ .base = hdr_slice.ptr, .len = hdr_slice.len }; |
| ... | ... | @@ -746,13 +658,13 @@ pub fn flushModule(self: *Plan9, arena: Allocator, tid: Zcu.PerThread.Id, prog_n |
| 746 | 658 | // text |
| 747 | 659 | { |
| 748 | 660 | var linecount: i64 = -1; |
| 749 | var it_file = self.fn_decl_table.iterator(); | |
| 661 | var it_file = self.fn_nav_table.iterator(); | |
| 750 | 662 | while (it_file.next()) |fentry| { |
| 751 | 663 | var it = fentry.value_ptr.functions.iterator(); |
| 752 | 664 | while (it.next()) |entry| { |
| 753 | const decl_index = entry.key_ptr.*; | |
| 754 | const decl = pt.zcu.declPtr(decl_index); | |
| 755 | const atom = self.getAtomPtr(self.decls.get(decl_index).?.index); | |
| 665 | const nav_index = entry.key_ptr.*; | |
| 666 | const nav = pt.zcu.intern_pool.getNav(nav_index); | |
| 667 | const atom = self.getAtomPtr(self.navs.get(nav_index).?.index); | |
| 756 | 668 | const out = entry.value_ptr.*; |
| 757 | 669 | { |
| 758 | 670 | // connect the previous decl to the next |
| ... | ... | @@ -771,15 +683,15 @@ pub fn flushModule(self: *Plan9, arena: Allocator, tid: Zcu.PerThread.Id, prog_n |
| 771 | 683 | const off = self.getAddr(text_i, .t); |
| 772 | 684 | text_i += out.code.len; |
| 773 | 685 | atom.offset = off; |
| 774 | log.debug("write text decl {*} ({}), lines {d} to {d}.;__GOT+0x{x} vaddr: 0x{x}", .{ decl, decl.name.fmt(&pt.zcu.intern_pool), out.start_line + 1, out.end_line, atom.got_index.? * 8, off }); | |
| 686 | log.debug("write text nav 0x{x} ({}), lines {d} to {d}.;__GOT+0x{x} vaddr: 0x{x}", .{ nav_index, nav.name.fmt(&pt.zcu.intern_pool), out.start_line + 1, out.end_line, atom.got_index.? * 8, off }); | |
| 775 | 687 | if (!self.sixtyfour_bit) { |
| 776 | mem.writeInt(u32, got_table[atom.got_index.? * 4 ..][0..4], @as(u32, @intCast(off)), target.cpu.arch.endian()); | |
| 688 | mem.writeInt(u32, got_table[atom.got_index.? * 4 ..][0..4], @intCast(off), target.cpu.arch.endian()); | |
| 777 | 689 | } else { |
| 778 | 690 | mem.writeInt(u64, got_table[atom.got_index.? * 8 ..][0..8], off, target.cpu.arch.endian()); |
| 779 | 691 | } |
| 780 | 692 | self.syms.items[atom.sym_index.?].value = off; |
| 781 | if (self.decl_exports.get(decl_index)) |export_indices| { | |
| 782 | try self.addDeclExports(pt.zcu, decl_index, export_indices); | |
| 693 | if (self.nav_exports.get(nav_index)) |export_indices| { | |
| 694 | try self.addNavExports(pt.zcu, nav_index, export_indices); | |
| 783 | 695 | } |
| 784 | 696 | } |
| 785 | 697 | } |
| ... | ... | @@ -826,10 +738,10 @@ pub fn flushModule(self: *Plan9, arena: Allocator, tid: Zcu.PerThread.Id, prog_n |
| 826 | 738 | // data |
| 827 | 739 | var data_i: u64 = got_size; |
| 828 | 740 | { |
| 829 | var it = self.data_decl_table.iterator(); | |
| 741 | var it = self.data_nav_table.iterator(); | |
| 830 | 742 | while (it.next()) |entry| { |
| 831 | const decl_index = entry.key_ptr.*; | |
| 832 | const atom = self.getAtomPtr(self.decls.get(decl_index).?.index); | |
| 743 | const nav_index = entry.key_ptr.*; | |
| 744 | const atom = self.getAtomPtr(self.navs.get(nav_index).?.index); | |
| 833 | 745 | const code = entry.value_ptr.*; |
| 834 | 746 | |
| 835 | 747 | foff += code.len; |
| ... | ... | @@ -844,35 +756,13 @@ pub fn flushModule(self: *Plan9, arena: Allocator, tid: Zcu.PerThread.Id, prog_n |
| 844 | 756 | mem.writeInt(u64, got_table[atom.got_index.? * 8 ..][0..8], off, target.cpu.arch.endian()); |
| 845 | 757 | } |
| 846 | 758 | self.syms.items[atom.sym_index.?].value = off; |
| 847 | if (self.decl_exports.get(decl_index)) |export_indices| { | |
| 848 | try self.addDeclExports(pt.zcu, decl_index, export_indices); | |
| 759 | if (self.nav_exports.get(nav_index)) |export_indices| { | |
| 760 | try self.addNavExports(pt.zcu, nav_index, export_indices); | |
| 849 | 761 | } |
| 850 | 762 | } |
| 851 | // write the unnamed constants after the other data decls | |
| 852 | var it_unc = self.unnamed_const_atoms.iterator(); | |
| 853 | while (it_unc.next()) |unnamed_consts| { | |
| 854 | for (unnamed_consts.value_ptr.items) |atom_idx| { | |
| 855 | const atom = self.getAtomPtr(atom_idx); | |
| 856 | const code = atom.code.getOwnedCode().?; // unnamed consts must own their code | |
| 857 | log.debug("write unnamed const: ({s})", .{self.syms.items[atom.sym_index.?].name}); | |
| 858 | foff += code.len; | |
| 859 | iovecs[iovecs_i] = .{ .base = code.ptr, .len = code.len }; | |
| 860 | iovecs_i += 1; | |
| 861 | const off = self.getAddr(data_i, .d); | |
| 862 | data_i += code.len; | |
| 863 | atom.offset = off; | |
| 864 | if (!self.sixtyfour_bit) { | |
| 865 | mem.writeInt(u32, got_table[atom.got_index.? * 4 ..][0..4], @as(u32, @intCast(off)), target.cpu.arch.endian()); | |
| 866 | } else { | |
| 867 | mem.writeInt(u64, got_table[atom.got_index.? * 8 ..][0..8], off, target.cpu.arch.endian()); | |
| 868 | } | |
| 869 | self.syms.items[atom.sym_index.?].value = off; | |
| 870 | } | |
| 871 | } | |
| 872 | // the anon decls | |
| 873 | 763 | { |
| 874 | var it_anon = self.anon_decls.iterator(); | |
| 875 | while (it_anon.next()) |kv| { | |
| 764 | var it_uav = self.uavs.iterator(); | |
| 765 | while (it_uav.next()) |kv| { | |
| 876 | 766 | const atom = self.getAtomPtr(kv.value_ptr.*); |
| 877 | 767 | const code = atom.code.getOwnedCode().?; |
| 878 | 768 | log.debug("write anon decl: {s}", .{self.syms.items[atom.sym_index.?].name}); |
| ... | ... | @@ -1011,14 +901,14 @@ pub fn flushModule(self: *Plan9, arena: Allocator, tid: Zcu.PerThread.Id, prog_n |
| 1011 | 901 | // write it all! |
| 1012 | 902 | try file.pwritevAll(iovecs, 0); |
| 1013 | 903 | } |
| 1014 | fn addDeclExports( | |
| 904 | fn addNavExports( | |
| 1015 | 905 | self: *Plan9, |
| 1016 | 906 | mod: *Zcu, |
| 1017 | decl_index: InternPool.DeclIndex, | |
| 907 | nav_index: InternPool.Nav.Index, | |
| 1018 | 908 | export_indices: []const u32, |
| 1019 | 909 | ) !void { |
| 1020 | 910 | const gpa = self.base.comp.gpa; |
| 1021 | const metadata = self.decls.getPtr(decl_index).?; | |
| 911 | const metadata = self.navs.getPtr(nav_index).?; | |
| 1022 | 912 | const atom = self.getAtom(metadata.index); |
| 1023 | 913 | |
| 1024 | 914 | for (export_indices) |export_idx| { |
| ... | ... | @@ -1031,7 +921,7 @@ fn addDeclExports( |
| 1031 | 921 | { |
| 1032 | 922 | try mod.failed_exports.put(mod.gpa, export_idx, try Zcu.ErrorMsg.create( |
| 1033 | 923 | gpa, |
| 1034 | mod.declPtr(decl_index).navSrcLoc(mod), | |
| 924 | mod.navSrcLoc(nav_index), | |
| 1035 | 925 | "plan9 does not support extra sections", |
| 1036 | 926 | .{}, |
| 1037 | 927 | )); |
| ... | ... | @@ -1090,7 +980,6 @@ pub fn freeDecl(self: *Plan9, decl_index: InternPool.DeclIndex) void { |
| 1090 | 980 | } |
| 1091 | 981 | kv.value.exports.deinit(gpa); |
| 1092 | 982 | } |
| 1093 | self.freeUnnamedConsts(decl_index); | |
| 1094 | 983 | { |
| 1095 | 984 | const atom_index = self.decls.get(decl_index).?.index; |
| 1096 | 985 | const relocs = self.relocs.getPtr(atom_index) orelse return; |
| ... | ... | @@ -1098,18 +987,6 @@ pub fn freeDecl(self: *Plan9, decl_index: InternPool.DeclIndex) void { |
| 1098 | 987 | assert(self.relocs.remove(atom_index)); |
| 1099 | 988 | } |
| 1100 | 989 | } |
| 1101 | fn freeUnnamedConsts(self: *Plan9, decl_index: InternPool.DeclIndex) void { | |
| 1102 | const gpa = self.base.comp.gpa; | |
| 1103 | const unnamed_consts = self.unnamed_const_atoms.getPtr(decl_index) orelse return; | |
| 1104 | for (unnamed_consts.items) |atom_idx| { | |
| 1105 | const atom = self.getAtom(atom_idx); | |
| 1106 | gpa.free(self.syms.items[atom.sym_index.?].name); | |
| 1107 | self.syms.items[atom.sym_index.?] = aout.Sym.undefined_symbol; | |
| 1108 | self.syms_index_free_list.append(gpa, atom.sym_index.?) catch {}; | |
| 1109 | } | |
| 1110 | unnamed_consts.clearAndFree(gpa); | |
| 1111 | } | |
| 1112 | ||
| 1113 | 990 | fn createAtom(self: *Plan9) !Atom.Index { |
| 1114 | 991 | const gpa = self.base.comp.gpa; |
| 1115 | 992 | const index = @as(Atom.Index, @intCast(self.atoms.items.len)); |
| ... | ... | @@ -1124,9 +1001,11 @@ fn createAtom(self: *Plan9) !Atom.Index { |
| 1124 | 1001 | return index; |
| 1125 | 1002 | } |
| 1126 | 1003 | |
| 1127 | pub fn seeDecl(self: *Plan9, decl_index: InternPool.DeclIndex) !Atom.Index { | |
| 1128 | const gpa = self.base.comp.gpa; | |
| 1129 | const gop = try self.decls.getOrPut(gpa, decl_index); | |
| 1004 | pub fn seeNav(self: *Plan9, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) !Atom.Index { | |
| 1005 | const zcu = pt.zcu; | |
| 1006 | const ip = &zcu.intern_pool; | |
| 1007 | const gpa = zcu.gpa; | |
| 1008 | const gop = try self.navs.getOrPut(gpa, nav_index); | |
| 1130 | 1009 | if (!gop.found_existing) { |
| 1131 | 1010 | const index = try self.createAtom(); |
| 1132 | 1011 | self.getAtomPtr(index).got_index = self.allocateGotIndex(); |
| ... | ... | @@ -1137,23 +1016,22 @@ pub fn seeDecl(self: *Plan9, decl_index: InternPool.DeclIndex) !Atom.Index { |
| 1137 | 1016 | } |
| 1138 | 1017 | const atom_idx = gop.value_ptr.index; |
| 1139 | 1018 | // handle externs here because they might not get updateDecl called on them |
| 1140 | const mod = self.base.comp.module.?; | |
| 1141 | const decl = mod.declPtr(decl_index); | |
| 1142 | if (decl.isExtern(mod)) { | |
| 1019 | const nav = ip.getNav(nav_index); | |
| 1020 | if (ip.indexToKey(nav.status.resolved.val) == .@"extern") { | |
| 1143 | 1021 | // this is a "phantom atom" - it is never actually written to disk, just convenient for us to store stuff about externs |
| 1144 | if (decl.name.eqlSlice("etext", &mod.intern_pool)) { | |
| 1022 | if (nav.name.eqlSlice("etext", ip)) { | |
| 1145 | 1023 | self.etext_edata_end_atom_indices[0] = atom_idx; |
| 1146 | } else if (decl.name.eqlSlice("edata", &mod.intern_pool)) { | |
| 1024 | } else if (nav.name.eqlSlice("edata", ip)) { | |
| 1147 | 1025 | self.etext_edata_end_atom_indices[1] = atom_idx; |
| 1148 | } else if (decl.name.eqlSlice("end", &mod.intern_pool)) { | |
| 1026 | } else if (nav.name.eqlSlice("end", ip)) { | |
| 1149 | 1027 | self.etext_edata_end_atom_indices[2] = atom_idx; |
| 1150 | 1028 | } |
| 1151 | try self.updateFinish(decl_index); | |
| 1152 | log.debug("seeDecl(extern) for {} (got_addr=0x{x})", .{ | |
| 1153 | decl.name.fmt(&mod.intern_pool), | |
| 1029 | try self.updateFinish(pt, nav_index); | |
| 1030 | log.debug("seeNav(extern) for {} (got_addr=0x{x})", .{ | |
| 1031 | nav.name.fmt(ip), | |
| 1154 | 1032 | self.getAtom(atom_idx).getOffsetTableAddress(self), |
| 1155 | 1033 | }); |
| 1156 | } else log.debug("seeDecl for {}", .{decl.name.fmt(&mod.intern_pool)}); | |
| 1034 | } else log.debug("seeNav for {}", .{nav.name.fmt(ip)}); | |
| 1157 | 1035 | return atom_idx; |
| 1158 | 1036 | } |
| 1159 | 1037 | |
| ... | ... | @@ -1165,45 +1043,41 @@ pub fn updateExports( |
| 1165 | 1043 | ) !void { |
| 1166 | 1044 | const gpa = self.base.comp.gpa; |
| 1167 | 1045 | switch (exported) { |
| 1168 | .value => @panic("TODO: plan9 updateExports handling values"), | |
| 1169 | .decl_index => |decl_index| { | |
| 1170 | _ = try self.seeDecl(decl_index); | |
| 1171 | if (self.decl_exports.fetchSwapRemove(decl_index)) |kv| { | |
| 1046 | .uav => @panic("TODO: plan9 updateExports handling values"), | |
| 1047 | .nav => |nav| { | |
| 1048 | _ = try self.seeNav(pt, nav); | |
| 1049 | if (self.nav_exports.fetchSwapRemove(nav)) |kv| { | |
| 1172 | 1050 | gpa.free(kv.value); |
| 1173 | 1051 | } |
| 1174 | try self.decl_exports.ensureUnusedCapacity(gpa, 1); | |
| 1052 | try self.nav_exports.ensureUnusedCapacity(gpa, 1); | |
| 1175 | 1053 | const duped_indices = try gpa.dupe(u32, export_indices); |
| 1176 | self.decl_exports.putAssumeCapacityNoClobber(decl_index, duped_indices); | |
| 1054 | self.nav_exports.putAssumeCapacityNoClobber(nav, duped_indices); | |
| 1177 | 1055 | }, |
| 1178 | 1056 | } |
| 1179 | 1057 | // all proper work is done in flush |
| 1180 | _ = pt; | |
| 1181 | 1058 | } |
| 1182 | 1059 | |
| 1183 | pub fn getOrCreateAtomForLazySymbol(self: *Plan9, pt: Zcu.PerThread, sym: File.LazySymbol) !Atom.Index { | |
| 1184 | const gpa = pt.zcu.gpa; | |
| 1185 | const gop = try self.lazy_syms.getOrPut(gpa, sym.getDecl(self.base.comp.module.?)); | |
| 1060 | pub fn getOrCreateAtomForLazySymbol(self: *Plan9, pt: Zcu.PerThread, lazy_sym: File.LazySymbol) !Atom.Index { | |
| 1061 | const gop = try self.lazy_syms.getOrPut(pt.zcu.gpa, lazy_sym.ty); | |
| 1186 | 1062 | errdefer _ = if (!gop.found_existing) self.lazy_syms.pop(); |
| 1187 | 1063 | |
| 1188 | 1064 | if (!gop.found_existing) gop.value_ptr.* = .{}; |
| 1189 | 1065 | |
| 1190 | const metadata: struct { atom: *Atom.Index, state: *LazySymbolMetadata.State } = switch (sym.kind) { | |
| 1191 | .code => .{ .atom = &gop.value_ptr.text_atom, .state = &gop.value_ptr.text_state }, | |
| 1192 | .const_data => .{ .atom = &gop.value_ptr.rodata_atom, .state = &gop.value_ptr.rodata_state }, | |
| 1066 | const atom_ptr, const state_ptr = switch (lazy_sym.kind) { | |
| 1067 | .code => .{ &gop.value_ptr.text_atom, &gop.value_ptr.text_state }, | |
| 1068 | .const_data => .{ &gop.value_ptr.rodata_atom, &gop.value_ptr.rodata_state }, | |
| 1193 | 1069 | }; |
| 1194 | switch (metadata.state.*) { | |
| 1195 | .unused => metadata.atom.* = try self.createAtom(), | |
| 1196 | .pending_flush => return metadata.atom.*, | |
| 1070 | switch (state_ptr.*) { | |
| 1071 | .unused => atom_ptr.* = try self.createAtom(), | |
| 1072 | .pending_flush => return atom_ptr.*, | |
| 1197 | 1073 | .flushed => {}, |
| 1198 | 1074 | } |
| 1199 | metadata.state.* = .pending_flush; | |
| 1200 | const atom = metadata.atom.*; | |
| 1075 | state_ptr.* = .pending_flush; | |
| 1076 | const atom = atom_ptr.*; | |
| 1201 | 1077 | _ = try self.getAtomPtr(atom).getOrCreateSymbolTableEntry(self); |
| 1202 | 1078 | _ = self.getAtomPtr(atom).getOrCreateOffsetTableEntry(self); |
| 1203 | 1079 | // anyerror needs to be deferred until flushModule |
| 1204 | if (sym.getDecl(self.base.comp.module.?) != .none) { | |
| 1205 | try self.updateLazySymbolAtom(pt, sym, atom); | |
| 1206 | } | |
| 1080 | if (lazy_sym.ty != .anyerror_type) try self.updateLazySymbolAtom(pt, lazy_sym, atom); | |
| 1207 | 1081 | return atom; |
| 1208 | 1082 | } |
| 1209 | 1083 | |
| ... | ... | @@ -1217,7 +1091,7 @@ fn updateLazySymbolAtom(self: *Plan9, pt: Zcu.PerThread, sym: File.LazySymbol, a |
| 1217 | 1091 | // create the symbol for the name |
| 1218 | 1092 | const name = try std.fmt.allocPrint(gpa, "__lazy_{s}_{}", .{ |
| 1219 | 1093 | @tagName(sym.kind), |
| 1220 | sym.ty.fmt(pt), | |
| 1094 | Type.fromInterned(sym.ty).fmt(pt), | |
| 1221 | 1095 | }); |
| 1222 | 1096 | |
| 1223 | 1097 | const symbol: aout.Sym = .{ |
| ... | ... | @@ -1228,7 +1102,7 @@ fn updateLazySymbolAtom(self: *Plan9, pt: Zcu.PerThread, sym: File.LazySymbol, a |
| 1228 | 1102 | self.syms.items[self.getAtomPtr(atom_index).sym_index.?] = symbol; |
| 1229 | 1103 | |
| 1230 | 1104 | // generate the code |
| 1231 | const src = sym.ty.srcLocOrNull(pt.zcu) orelse Zcu.LazySrcLoc.unneeded; | |
| 1105 | const src = Type.fromInterned(sym.ty).srcLocOrNull(pt.zcu) orelse Zcu.LazySrcLoc.unneeded; | |
| 1232 | 1106 | const res = try codegen.generateLazySymbol( |
| 1233 | 1107 | &self.base, |
| 1234 | 1108 | pt, |
| ... | ... | @@ -1264,12 +1138,6 @@ pub fn deinit(self: *Plan9) void { |
| 1264 | 1138 | } |
| 1265 | 1139 | self.relocs.deinit(gpa); |
| 1266 | 1140 | } |
| 1267 | // free the unnamed consts | |
| 1268 | var it_unc = self.unnamed_const_atoms.iterator(); | |
| 1269 | while (it_unc.next()) |kv| { | |
| 1270 | self.freeUnnamedConsts(kv.key_ptr.*); | |
| 1271 | } | |
| 1272 | self.unnamed_const_atoms.deinit(gpa); | |
| 1273 | 1141 | var it_lzc = self.lazy_syms.iterator(); |
| 1274 | 1142 | while (it_lzc.next()) |kv| { |
| 1275 | 1143 | if (kv.value_ptr.text_state != .unused) |
| ... | ... | @@ -1278,7 +1146,7 @@ pub fn deinit(self: *Plan9) void { |
| 1278 | 1146 | gpa.free(self.syms.items[self.getAtom(kv.value_ptr.rodata_atom).sym_index.?].name); |
| 1279 | 1147 | } |
| 1280 | 1148 | self.lazy_syms.deinit(gpa); |
| 1281 | var itf_files = self.fn_decl_table.iterator(); | |
| 1149 | var itf_files = self.fn_nav_table.iterator(); | |
| 1282 | 1150 | while (itf_files.next()) |ent| { |
| 1283 | 1151 | // get the submap |
| 1284 | 1152 | var submap = ent.value_ptr.functions; |
| ... | ... | @@ -1289,21 +1157,21 @@ pub fn deinit(self: *Plan9) void { |
| 1289 | 1157 | gpa.free(entry.value_ptr.lineinfo); |
| 1290 | 1158 | } |
| 1291 | 1159 | } |
| 1292 | self.fn_decl_table.deinit(gpa); | |
| 1293 | var itd = self.data_decl_table.iterator(); | |
| 1160 | self.fn_nav_table.deinit(gpa); | |
| 1161 | var itd = self.data_nav_table.iterator(); | |
| 1294 | 1162 | while (itd.next()) |entry| { |
| 1295 | 1163 | gpa.free(entry.value_ptr.*); |
| 1296 | 1164 | } |
| 1297 | var it_anon = self.anon_decls.iterator(); | |
| 1298 | while (it_anon.next()) |entry| { | |
| 1165 | var it_uav = self.uavs.iterator(); | |
| 1166 | while (it_uav.next()) |entry| { | |
| 1299 | 1167 | const sym_index = self.getAtom(entry.value_ptr.*).sym_index.?; |
| 1300 | 1168 | gpa.free(self.syms.items[sym_index].name); |
| 1301 | 1169 | } |
| 1302 | self.data_decl_table.deinit(gpa); | |
| 1303 | for (self.decl_exports.values()) |export_indices| { | |
| 1170 | self.data_nav_table.deinit(gpa); | |
| 1171 | for (self.nav_exports.values()) |export_indices| { | |
| 1304 | 1172 | gpa.free(export_indices); |
| 1305 | 1173 | } |
| 1306 | self.decl_exports.deinit(gpa); | |
| 1174 | self.nav_exports.deinit(gpa); | |
| 1307 | 1175 | self.syms.deinit(gpa); |
| 1308 | 1176 | self.got_index_free_list.deinit(gpa); |
| 1309 | 1177 | self.syms_index_free_list.deinit(gpa); |
| ... | ... | @@ -1317,11 +1185,11 @@ pub fn deinit(self: *Plan9) void { |
| 1317 | 1185 | self.atoms.deinit(gpa); |
| 1318 | 1186 | |
| 1319 | 1187 | { |
| 1320 | var it = self.decls.iterator(); | |
| 1188 | var it = self.navs.iterator(); | |
| 1321 | 1189 | while (it.next()) |entry| { |
| 1322 | 1190 | entry.value_ptr.exports.deinit(gpa); |
| 1323 | 1191 | } |
| 1324 | self.decls.deinit(gpa); | |
| 1192 | self.navs.deinit(gpa); | |
| 1325 | 1193 | } |
| 1326 | 1194 | } |
| 1327 | 1195 | |
| ... | ... | @@ -1402,17 +1270,17 @@ pub fn writeSyms(self: *Plan9, buf: *std.ArrayList(u8)) !void { |
| 1402 | 1270 | |
| 1403 | 1271 | // write the data symbols |
| 1404 | 1272 | { |
| 1405 | var it = self.data_decl_table.iterator(); | |
| 1273 | var it = self.data_nav_table.iterator(); | |
| 1406 | 1274 | while (it.next()) |entry| { |
| 1407 | const decl_index = entry.key_ptr.*; | |
| 1408 | const decl_metadata = self.decls.get(decl_index).?; | |
| 1409 | const atom = self.getAtom(decl_metadata.index); | |
| 1275 | const nav_index = entry.key_ptr.*; | |
| 1276 | const nav_metadata = self.navs.get(nav_index).?; | |
| 1277 | const atom = self.getAtom(nav_metadata.index); | |
| 1410 | 1278 | const sym = self.syms.items[atom.sym_index.?]; |
| 1411 | 1279 | try self.writeSym(writer, sym); |
| 1412 | if (self.decl_exports.get(decl_index)) |export_indices| { | |
| 1280 | if (self.nav_exports.get(nav_index)) |export_indices| { | |
| 1413 | 1281 | for (export_indices) |export_idx| { |
| 1414 | 1282 | const exp = mod.all_exports.items[export_idx]; |
| 1415 | if (decl_metadata.getExport(self, exp.opts.name.toSlice(ip))) |exp_i| { | |
| 1283 | if (nav_metadata.getExport(self, exp.opts.name.toSlice(ip))) |exp_i| { | |
| 1416 | 1284 | try self.writeSym(writer, self.syms.items[exp_i]); |
| 1417 | 1285 | } |
| 1418 | 1286 | } |
| ... | ... | @@ -1429,22 +1297,11 @@ pub fn writeSyms(self: *Plan9, buf: *std.ArrayList(u8)) !void { |
| 1429 | 1297 | try self.writeSym(writer, sym); |
| 1430 | 1298 | } |
| 1431 | 1299 | } |
| 1432 | // unnamed consts | |
| 1433 | { | |
| 1434 | var it = self.unnamed_const_atoms.iterator(); | |
| 1435 | while (it.next()) |kv| { | |
| 1436 | const consts = kv.value_ptr; | |
| 1437 | for (consts.items) |atom_index| { | |
| 1438 | const sym = self.syms.items[self.getAtom(atom_index).sym_index.?]; | |
| 1439 | try self.writeSym(writer, sym); | |
| 1440 | } | |
| 1441 | } | |
| 1442 | } | |
| 1443 | 1300 | // text symbols are the hardest: |
| 1444 | 1301 | // the file of a text symbol is the .z symbol before it |
| 1445 | 1302 | // so we have to write everything in the right order |
| 1446 | 1303 | { |
| 1447 | var it_file = self.fn_decl_table.iterator(); | |
| 1304 | var it_file = self.fn_nav_table.iterator(); | |
| 1448 | 1305 | while (it_file.next()) |fentry| { |
| 1449 | 1306 | var symidx_and_submap = fentry.value_ptr; |
| 1450 | 1307 | // write the z symbols |
| ... | ... | @@ -1454,15 +1311,15 @@ pub fn writeSyms(self: *Plan9, buf: *std.ArrayList(u8)) !void { |
| 1454 | 1311 | // write all the decls come from the file of the z symbol |
| 1455 | 1312 | var submap_it = symidx_and_submap.functions.iterator(); |
| 1456 | 1313 | while (submap_it.next()) |entry| { |
| 1457 | const decl_index = entry.key_ptr.*; | |
| 1458 | const decl_metadata = self.decls.get(decl_index).?; | |
| 1459 | const atom = self.getAtom(decl_metadata.index); | |
| 1314 | const nav_index = entry.key_ptr.*; | |
| 1315 | const nav_metadata = self.navs.get(nav_index).?; | |
| 1316 | const atom = self.getAtom(nav_metadata.index); | |
| 1460 | 1317 | const sym = self.syms.items[atom.sym_index.?]; |
| 1461 | 1318 | try self.writeSym(writer, sym); |
| 1462 | if (self.decl_exports.get(decl_index)) |export_indices| { | |
| 1319 | if (self.nav_exports.get(nav_index)) |export_indices| { | |
| 1463 | 1320 | for (export_indices) |export_idx| { |
| 1464 | 1321 | const exp = mod.all_exports.items[export_idx]; |
| 1465 | if (decl_metadata.getExport(self, exp.opts.name.toSlice(ip))) |exp_i| { | |
| 1322 | if (nav_metadata.getExport(self, exp.opts.name.toSlice(ip))) |exp_i| { | |
| 1466 | 1323 | const s = self.syms.items[exp_i]; |
| 1467 | 1324 | if (mem.eql(u8, s.name, "_start")) |
| 1468 | 1325 | self.entry_val = s.value; |
| ... | ... | @@ -1500,31 +1357,31 @@ pub fn updateDeclLineNumber(self: *Plan9, pt: Zcu.PerThread, decl_index: InternP |
| 1500 | 1357 | _ = decl_index; |
| 1501 | 1358 | } |
| 1502 | 1359 | |
| 1503 | pub fn getDeclVAddr( | |
| 1360 | pub fn getNavVAddr( | |
| 1504 | 1361 | self: *Plan9, |
| 1505 | 1362 | pt: Zcu.PerThread, |
| 1506 | decl_index: InternPool.DeclIndex, | |
| 1363 | nav_index: InternPool.Nav.Index, | |
| 1507 | 1364 | reloc_info: link.File.RelocInfo, |
| 1508 | 1365 | ) !u64 { |
| 1509 | 1366 | const ip = &pt.zcu.intern_pool; |
| 1510 | const decl = pt.zcu.declPtr(decl_index); | |
| 1511 | log.debug("getDeclVAddr for {}", .{decl.name.fmt(ip)}); | |
| 1512 | if (decl.isExtern(pt.zcu)) { | |
| 1513 | if (decl.name.eqlSlice("etext", ip)) { | |
| 1367 | const nav = ip.getNav(nav_index); | |
| 1368 | log.debug("getDeclVAddr for {}", .{nav.name.fmt(ip)}); | |
| 1369 | if (ip.indexToKey(nav.status.resolved.val) == .@"extern") { | |
| 1370 | if (nav.name.eqlSlice("etext", ip)) { | |
| 1514 | 1371 | try self.addReloc(reloc_info.parent_atom_index, .{ |
| 1515 | 1372 | .target = undefined, |
| 1516 | 1373 | .offset = reloc_info.offset, |
| 1517 | 1374 | .addend = reloc_info.addend, |
| 1518 | 1375 | .type = .special_etext, |
| 1519 | 1376 | }); |
| 1520 | } else if (decl.name.eqlSlice("edata", ip)) { | |
| 1377 | } else if (nav.name.eqlSlice("edata", ip)) { | |
| 1521 | 1378 | try self.addReloc(reloc_info.parent_atom_index, .{ |
| 1522 | 1379 | .target = undefined, |
| 1523 | 1380 | .offset = reloc_info.offset, |
| 1524 | 1381 | .addend = reloc_info.addend, |
| 1525 | 1382 | .type = .special_edata, |
| 1526 | 1383 | }); |
| 1527 | } else if (decl.name.eqlSlice("end", ip)) { | |
| 1384 | } else if (nav.name.eqlSlice("end", ip)) { | |
| 1528 | 1385 | try self.addReloc(reloc_info.parent_atom_index, .{ |
| 1529 | 1386 | .target = undefined, |
| 1530 | 1387 | .offset = reloc_info.offset, |
| ... | ... | @@ -1536,7 +1393,7 @@ pub fn getDeclVAddr( |
| 1536 | 1393 | return undefined; |
| 1537 | 1394 | } |
| 1538 | 1395 | // otherwise, we just add a relocation |
| 1539 | const atom_index = try self.seeDecl(decl_index); | |
| 1396 | const atom_index = try self.seeNav(pt, nav_index); | |
| 1540 | 1397 | // the parent_atom_index in this case is just the decl_index of the parent |
| 1541 | 1398 | try self.addReloc(reloc_info.parent_atom_index, .{ |
| 1542 | 1399 | .target = atom_index, |
| ... | ... | @@ -1546,15 +1403,14 @@ pub fn getDeclVAddr( |
| 1546 | 1403 | return undefined; |
| 1547 | 1404 | } |
| 1548 | 1405 | |
| 1549 | pub fn lowerAnonDecl( | |
| 1406 | pub fn lowerUav( | |
| 1550 | 1407 | self: *Plan9, |
| 1551 | 1408 | pt: Zcu.PerThread, |
| 1552 | decl_val: InternPool.Index, | |
| 1409 | uav: InternPool.Index, | |
| 1553 | 1410 | explicit_alignment: InternPool.Alignment, |
| 1554 | 1411 | src_loc: Zcu.LazySrcLoc, |
| 1555 | ) !codegen.Result { | |
| 1412 | ) !codegen.GenResult { | |
| 1556 | 1413 | _ = explicit_alignment; |
| 1557 | // This is basically the same as lowerUnnamedConst. | |
| 1558 | 1414 | // example: |
| 1559 | 1415 | // const ty = mod.intern_pool.typeOf(decl_val).toType(); |
| 1560 | 1416 | // const val = decl_val.toValue(); |
| ... | ... | @@ -1564,41 +1420,40 @@ pub fn lowerAnonDecl( |
| 1564 | 1420 | // to put it in some location. |
| 1565 | 1421 | // ... |
| 1566 | 1422 | const gpa = self.base.comp.gpa; |
| 1567 | const gop = try self.anon_decls.getOrPut(gpa, decl_val); | |
| 1568 | if (!gop.found_existing) { | |
| 1569 | const val = Value.fromInterned(decl_val); | |
| 1570 | const name = try std.fmt.allocPrint(gpa, "__anon_{d}", .{@intFromEnum(decl_val)}); | |
| 1571 | ||
| 1572 | const index = try self.createAtom(); | |
| 1573 | const got_index = self.allocateGotIndex(); | |
| 1574 | gop.value_ptr.* = index; | |
| 1575 | // we need to free name latex | |
| 1576 | var code_buffer = std.ArrayList(u8).init(gpa); | |
| 1577 | const res = try codegen.generateSymbol(&self.base, pt, src_loc, val, &code_buffer, .{ .none = {} }, .{ .parent_atom_index = index }); | |
| 1578 | const code = switch (res) { | |
| 1579 | .ok => code_buffer.items, | |
| 1580 | .fail => |em| return .{ .fail = em }, | |
| 1581 | }; | |
| 1582 | const atom_ptr = self.getAtomPtr(index); | |
| 1583 | atom_ptr.* = .{ | |
| 1584 | .type = .d, | |
| 1585 | .offset = undefined, | |
| 1586 | .sym_index = null, | |
| 1587 | .got_index = got_index, | |
| 1588 | .code = Atom.CodePtr.fromSlice(code), | |
| 1589 | }; | |
| 1590 | _ = try atom_ptr.getOrCreateSymbolTableEntry(self); | |
| 1591 | self.syms.items[atom_ptr.sym_index.?] = .{ | |
| 1592 | .type = .d, | |
| 1593 | .value = undefined, | |
| 1594 | .name = name, | |
| 1595 | }; | |
| 1596 | } | |
| 1597 | return .ok; | |
| 1423 | const gop = try self.uavs.getOrPut(gpa, uav); | |
| 1424 | if (gop.found_existing) return .{ .mcv = .{ .load_direct = gop.value_ptr.* } }; | |
| 1425 | const val = Value.fromInterned(uav); | |
| 1426 | const name = try std.fmt.allocPrint(gpa, "__anon_{d}", .{@intFromEnum(uav)}); | |
| 1427 | ||
| 1428 | const index = try self.createAtom(); | |
| 1429 | const got_index = self.allocateGotIndex(); | |
| 1430 | gop.value_ptr.* = index; | |
| 1431 | // we need to free name latex | |
| 1432 | var code_buffer = std.ArrayList(u8).init(gpa); | |
| 1433 | const res = try codegen.generateSymbol(&self.base, pt, src_loc, val, &code_buffer, .{ .none = {} }, .{ .parent_atom_index = index }); | |
| 1434 | const code = switch (res) { | |
| 1435 | .ok => code_buffer.items, | |
| 1436 | .fail => |em| return .{ .fail = em }, | |
| 1437 | }; | |
| 1438 | const atom_ptr = self.getAtomPtr(index); | |
| 1439 | atom_ptr.* = .{ | |
| 1440 | .type = .d, | |
| 1441 | .offset = undefined, | |
| 1442 | .sym_index = null, | |
| 1443 | .got_index = got_index, | |
| 1444 | .code = Atom.CodePtr.fromSlice(code), | |
| 1445 | }; | |
| 1446 | _ = try atom_ptr.getOrCreateSymbolTableEntry(self); | |
| 1447 | self.syms.items[atom_ptr.sym_index.?] = .{ | |
| 1448 | .type = .d, | |
| 1449 | .value = undefined, | |
| 1450 | .name = name, | |
| 1451 | }; | |
| 1452 | return .{ .mcv = .{ .load_direct = index } }; | |
| 1598 | 1453 | } |
| 1599 | 1454 | |
| 1600 | pub fn getAnonDeclVAddr(self: *Plan9, decl_val: InternPool.Index, reloc_info: link.File.RelocInfo) !u64 { | |
| 1601 | const atom_index = self.anon_decls.get(decl_val).?; | |
| 1455 | pub fn getUavVAddr(self: *Plan9, uav: InternPool.Index, reloc_info: link.File.RelocInfo) !u64 { | |
| 1456 | const atom_index = self.uavs.get(uav).?; | |
| 1602 | 1457 | try self.addReloc(reloc_info.parent_atom_index, .{ |
| 1603 | 1458 | .target = atom_index, |
| 1604 | 1459 | .offset = reloc_info.offset, |
src/link/SpirV.zig+20-20| ... | ... | @@ -36,6 +36,7 @@ const trace = @import("../tracy.zig").trace; |
| 36 | 36 | const build_options = @import("build_options"); |
| 37 | 37 | const Air = @import("../Air.zig"); |
| 38 | 38 | const Liveness = @import("../Liveness.zig"); |
| 39 | const Type = @import("../Type.zig"); | |
| 39 | 40 | const Value = @import("../Value.zig"); |
| 40 | 41 | |
| 41 | 42 | const SpvModule = @import("../codegen/spirv/Module.zig"); |
| ... | ... | @@ -50,8 +51,6 @@ base: link.File, |
| 50 | 51 | |
| 51 | 52 | object: codegen.Object, |
| 52 | 53 | |
| 53 | pub const base_tag: link.File.Tag = .spirv; | |
| 54 | ||
| 55 | 54 | pub fn createEmpty( |
| 56 | 55 | arena: Allocator, |
| 57 | 56 | comp: *Compilation, |
| ... | ... | @@ -128,22 +127,22 @@ pub fn updateFunc(self: *SpirV, pt: Zcu.PerThread, func_index: InternPool.Index, |
| 128 | 127 | @panic("Attempted to compile for architecture that was disabled by build configuration"); |
| 129 | 128 | } |
| 130 | 129 | |
| 130 | const ip = &pt.zcu.intern_pool; | |
| 131 | 131 | const func = pt.zcu.funcInfo(func_index); |
| 132 | const decl = pt.zcu.declPtr(func.owner_decl); | |
| 133 | log.debug("lowering function {}", .{decl.name.fmt(&pt.zcu.intern_pool)}); | |
| 132 | log.debug("lowering function {}", .{ip.getNav(func.owner_nav).name.fmt(ip)}); | |
| 134 | 133 | |
| 135 | 134 | try self.object.updateFunc(pt, func_index, air, liveness); |
| 136 | 135 | } |
| 137 | 136 | |
| 138 | pub fn updateDecl(self: *SpirV, pt: Zcu.PerThread, decl_index: InternPool.DeclIndex) !void { | |
| 137 | pub fn updateNav(self: *SpirV, pt: Zcu.PerThread, nav: InternPool.Nav.Index) !void { | |
| 139 | 138 | if (build_options.skip_non_native) { |
| 140 | 139 | @panic("Attempted to compile for architecture that was disabled by build configuration"); |
| 141 | 140 | } |
| 142 | 141 | |
| 143 | const decl = pt.zcu.declPtr(decl_index); | |
| 144 | log.debug("lowering declaration {}", .{decl.name.fmt(&pt.zcu.intern_pool)}); | |
| 142 | const ip = &pt.zcu.intern_pool; | |
| 143 | log.debug("lowering declaration {}", .{ip.getNav(nav).name.fmt(ip)}); | |
| 145 | 144 | |
| 146 | try self.object.updateDecl(pt, decl_index); | |
| 145 | try self.object.updateNav(pt, nav); | |
| 147 | 146 | } |
| 148 | 147 | |
| 149 | 148 | pub fn updateExports( |
| ... | ... | @@ -152,19 +151,20 @@ pub fn updateExports( |
| 152 | 151 | exported: Zcu.Exported, |
| 153 | 152 | export_indices: []const u32, |
| 154 | 153 | ) !void { |
| 155 | const mod = pt.zcu; | |
| 156 | const decl_index = switch (exported) { | |
| 157 | .decl_index => |i| i, | |
| 158 | .value => |val| { | |
| 159 | _ = val; | |
| 154 | const zcu = pt.zcu; | |
| 155 | const ip = &zcu.intern_pool; | |
| 156 | const nav_index = switch (exported) { | |
| 157 | .nav => |nav| nav, | |
| 158 | .uav => |uav| { | |
| 159 | _ = uav; | |
| 160 | 160 | @panic("TODO: implement SpirV linker code for exporting a constant value"); |
| 161 | 161 | }, |
| 162 | 162 | }; |
| 163 | const decl = mod.declPtr(decl_index); | |
| 164 | if (decl.val.isFuncBody(mod)) { | |
| 165 | const target = mod.getTarget(); | |
| 166 | const spv_decl_index = try self.object.resolveDecl(mod, decl_index); | |
| 167 | const execution_model = switch (decl.typeOf(mod).fnCallingConvention(mod)) { | |
| 163 | const nav_ty = ip.getNav(nav_index).typeOf(ip); | |
| 164 | if (ip.isFunctionType(nav_ty)) { | |
| 165 | const target = zcu.getTarget(); | |
| 166 | const spv_decl_index = try self.object.resolveNav(zcu, nav_index); | |
| 167 | const execution_model = switch (Type.fromInterned(nav_ty).fnCallingConvention(zcu)) { | |
| 168 | 168 | .Vertex => spec.ExecutionModel.Vertex, |
| 169 | 169 | .Fragment => spec.ExecutionModel.Fragment, |
| 170 | 170 | .Kernel => spec.ExecutionModel.Kernel, |
| ... | ... | @@ -177,10 +177,10 @@ pub fn updateExports( |
| 177 | 177 | (is_vulkan and (execution_model == .Fragment or execution_model == .Vertex))) |
| 178 | 178 | { |
| 179 | 179 | for (export_indices) |export_idx| { |
| 180 | const exp = mod.all_exports.items[export_idx]; | |
| 180 | const exp = zcu.all_exports.items[export_idx]; | |
| 181 | 181 | try self.object.spv.declareEntryPoint( |
| 182 | 182 | spv_decl_index, |
| 183 | exp.opts.name.toSlice(&mod.intern_pool), | |
| 183 | exp.opts.name.toSlice(ip), | |
| 184 | 184 | execution_model, |
| 185 | 185 | ); |
| 186 | 186 | } |
src/link/Wasm.zig+21-30| ... | ... | @@ -39,8 +39,6 @@ const ZigObject = @import("Wasm/ZigObject.zig"); |
| 39 | 39 | pub const Atom = @import("Wasm/Atom.zig"); |
| 40 | 40 | pub const Relocation = types.Relocation; |
| 41 | 41 | |
| 42 | pub const base_tag: link.File.Tag = .wasm; | |
| 43 | ||
| 44 | 42 | base: link.File, |
| 45 | 43 | /// Symbol name of the entry function to export |
| 46 | 44 | entry_name: ?[]const u8, |
| ... | ... | @@ -1451,19 +1449,19 @@ pub fn updateFunc(wasm: *Wasm, pt: Zcu.PerThread, func_index: InternPool.Index, |
| 1451 | 1449 | try wasm.zigObjectPtr().?.updateFunc(wasm, pt, func_index, air, liveness); |
| 1452 | 1450 | } |
| 1453 | 1451 | |
| 1454 | // Generate code for the Decl, storing it in memory to be later written to | |
| 1452 | // Generate code for the "Nav", storing it in memory to be later written to | |
| 1455 | 1453 | // the file on flush(). |
| 1456 | pub fn updateDecl(wasm: *Wasm, pt: Zcu.PerThread, decl_index: InternPool.DeclIndex) !void { | |
| 1454 | pub fn updateNav(wasm: *Wasm, pt: Zcu.PerThread, nav: InternPool.Nav.Index) !void { | |
| 1457 | 1455 | if (build_options.skip_non_native and builtin.object_format != .wasm) { |
| 1458 | 1456 | @panic("Attempted to compile for object format that was disabled by build configuration"); |
| 1459 | 1457 | } |
| 1460 | if (wasm.llvm_object) |llvm_object| return llvm_object.updateDecl(pt, decl_index); | |
| 1461 | try wasm.zigObjectPtr().?.updateDecl(wasm, pt, decl_index); | |
| 1458 | if (wasm.llvm_object) |llvm_object| return llvm_object.updateNav(pt, nav); | |
| 1459 | try wasm.zigObjectPtr().?.updateNav(wasm, pt, nav); | |
| 1462 | 1460 | } |
| 1463 | 1461 | |
| 1464 | pub fn updateDeclLineNumber(wasm: *Wasm, pt: Zcu.PerThread, decl_index: InternPool.DeclIndex) !void { | |
| 1462 | pub fn updateNavLineNumber(wasm: *Wasm, pt: Zcu.PerThread, nav: InternPool.Nav.Index) !void { | |
| 1465 | 1463 | if (wasm.llvm_object) |_| return; |
| 1466 | try wasm.zigObjectPtr().?.updateDeclLineNumber(pt, decl_index); | |
| 1464 | try wasm.zigObjectPtr().?.updateNavLineNumber(pt, nav); | |
| 1467 | 1465 | } |
| 1468 | 1466 | |
| 1469 | 1467 | /// From a given symbol location, returns its `wasm.GlobalType`. |
| ... | ... | @@ -1505,13 +1503,6 @@ fn getFunctionSignature(wasm: *const Wasm, loc: SymbolLoc) std.wasm.Type { |
| 1505 | 1503 | return wasm.func_types.items[wasm.functions.get(.{ .file = loc.file, .index = symbol.index }).?.func.type_index]; |
| 1506 | 1504 | } |
| 1507 | 1505 | |
| 1508 | /// Lowers a constant typed value to a local symbol and atom. | |
| 1509 | /// Returns the symbol index of the local | |
| 1510 | /// The given `decl` is the parent decl whom owns the constant. | |
| 1511 | pub fn lowerUnnamedConst(wasm: *Wasm, pt: Zcu.PerThread, val: Value, decl_index: InternPool.DeclIndex) !u32 { | |
| 1512 | return wasm.zigObjectPtr().?.lowerUnnamedConst(wasm, pt, val, decl_index); | |
| 1513 | } | |
| 1514 | ||
| 1515 | 1506 | /// Returns the symbol index from a symbol of which its flag is set global, |
| 1516 | 1507 | /// such as an exported or imported symbol. |
| 1517 | 1508 | /// If the symbol does not yet exist, creates a new one symbol instead |
| ... | ... | @@ -1521,29 +1512,29 @@ pub fn getGlobalSymbol(wasm: *Wasm, name: []const u8, lib_name: ?[]const u8) !Sy |
| 1521 | 1512 | return wasm.zigObjectPtr().?.getGlobalSymbol(wasm.base.comp.gpa, name); |
| 1522 | 1513 | } |
| 1523 | 1514 | |
| 1524 | /// For a given decl, find the given symbol index's atom, and create a relocation for the type. | |
| 1515 | /// For a given `Nav`, find the given symbol index's atom, and create a relocation for the type. | |
| 1525 | 1516 | /// Returns the given pointer address |
| 1526 | pub fn getDeclVAddr( | |
| 1517 | pub fn getNavVAddr( | |
| 1527 | 1518 | wasm: *Wasm, |
| 1528 | 1519 | pt: Zcu.PerThread, |
| 1529 | decl_index: InternPool.DeclIndex, | |
| 1520 | nav: InternPool.Nav.Index, | |
| 1530 | 1521 | reloc_info: link.File.RelocInfo, |
| 1531 | 1522 | ) !u64 { |
| 1532 | return wasm.zigObjectPtr().?.getDeclVAddr(wasm, pt, decl_index, reloc_info); | |
| 1523 | return wasm.zigObjectPtr().?.getNavVAddr(wasm, pt, nav, reloc_info); | |
| 1533 | 1524 | } |
| 1534 | 1525 | |
| 1535 | pub fn lowerAnonDecl( | |
| 1526 | pub fn lowerUav( | |
| 1536 | 1527 | wasm: *Wasm, |
| 1537 | 1528 | pt: Zcu.PerThread, |
| 1538 | decl_val: InternPool.Index, | |
| 1529 | uav: InternPool.Index, | |
| 1539 | 1530 | explicit_alignment: Alignment, |
| 1540 | 1531 | src_loc: Zcu.LazySrcLoc, |
| 1541 | ) !codegen.Result { | |
| 1542 | return wasm.zigObjectPtr().?.lowerAnonDecl(wasm, pt, decl_val, explicit_alignment, src_loc); | |
| 1532 | ) !codegen.GenResult { | |
| 1533 | return wasm.zigObjectPtr().?.lowerUav(wasm, pt, uav, explicit_alignment, src_loc); | |
| 1543 | 1534 | } |
| 1544 | 1535 | |
| 1545 | pub fn getAnonDeclVAddr(wasm: *Wasm, decl_val: InternPool.Index, reloc_info: link.File.RelocInfo) !u64 { | |
| 1546 | return wasm.zigObjectPtr().?.getAnonDeclVAddr(wasm, decl_val, reloc_info); | |
| 1536 | pub fn getUavVAddr(wasm: *Wasm, uav: InternPool.Index, reloc_info: link.File.RelocInfo) !u64 { | |
| 1537 | return wasm.zigObjectPtr().?.getUavVAddr(wasm, uav, reloc_info); | |
| 1547 | 1538 | } |
| 1548 | 1539 | |
| 1549 | 1540 | pub fn deleteExport( |
| ... | ... | @@ -4018,11 +4009,11 @@ pub fn putOrGetFuncType(wasm: *Wasm, func_type: std.wasm.Type) !u32 { |
| 4018 | 4009 | return index; |
| 4019 | 4010 | } |
| 4020 | 4011 | |
| 4021 | /// For the given `decl_index`, stores the corresponding type representing the function signature. | |
| 4012 | /// For the given `nav`, stores the corresponding type representing the function signature. | |
| 4022 | 4013 | /// Asserts declaration has an associated `Atom`. |
| 4023 | 4014 | /// Returns the index into the list of types. |
| 4024 | pub fn storeDeclType(wasm: *Wasm, decl_index: InternPool.DeclIndex, func_type: std.wasm.Type) !u32 { | |
| 4025 | return wasm.zigObjectPtr().?.storeDeclType(wasm.base.comp.gpa, decl_index, func_type); | |
| 4015 | pub fn storeNavType(wasm: *Wasm, nav: InternPool.Nav.Index, func_type: std.wasm.Type) !u32 { | |
| 4016 | return wasm.zigObjectPtr().?.storeDeclType(wasm.base.comp.gpa, nav, func_type); | |
| 4026 | 4017 | } |
| 4027 | 4018 | |
| 4028 | 4019 | /// Returns the symbol index of the error name table. |
| ... | ... | @@ -4036,8 +4027,8 @@ pub fn getErrorTableSymbol(wasm_file: *Wasm, pt: Zcu.PerThread) !u32 { |
| 4036 | 4027 | /// For a given `InternPool.DeclIndex` returns its corresponding `Atom.Index`. |
| 4037 | 4028 | /// When the index was not found, a new `Atom` will be created, and its index will be returned. |
| 4038 | 4029 | /// The newly created Atom is empty with default fields as specified by `Atom.empty`. |
| 4039 | pub fn getOrCreateAtomForDecl(wasm_file: *Wasm, pt: Zcu.PerThread, decl_index: InternPool.DeclIndex) !Atom.Index { | |
| 4040 | return wasm_file.zigObjectPtr().?.getOrCreateAtomForDecl(wasm_file, pt, decl_index); | |
| 4030 | pub fn getOrCreateAtomForNav(wasm_file: *Wasm, pt: Zcu.PerThread, nav: InternPool.Nav.Index) !Atom.Index { | |
| 4031 | return wasm_file.zigObjectPtr().?.getOrCreateAtomForNav(wasm_file, pt, nav); | |
| 4041 | 4032 | } |
| 4042 | 4033 | |
| 4043 | 4034 | /// Verifies all resolved symbols and checks whether itself needs to be marked alive, |
src/link/Wasm/ZigObject.zig+174-223| ... | ... | @@ -6,9 +6,9 @@ |
| 6 | 6 | path: []const u8, |
| 7 | 7 | /// Index within the list of relocatable objects of the linker driver. |
| 8 | 8 | index: File.Index, |
| 9 | /// Map of all `Decl` that are currently alive. | |
| 10 | /// Each index maps to the corresponding `DeclInfo`. | |
| 11 | decls_map: std.AutoHashMapUnmanaged(InternPool.DeclIndex, DeclInfo) = .{}, | |
| 9 | /// Map of all `Nav` that are currently alive. | |
| 10 | /// Each index maps to the corresponding `NavInfo`. | |
| 11 | navs: std.AutoHashMapUnmanaged(InternPool.Nav.Index, NavInfo) = .{}, | |
| 12 | 12 | /// List of function type signatures for this Zig module. |
| 13 | 13 | func_types: std.ArrayListUnmanaged(std.wasm.Type) = .{}, |
| 14 | 14 | /// List of `std.wasm.Func`. Each entry contains the function signature, |
| ... | ... | @@ -36,7 +36,7 @@ segment_free_list: std.ArrayListUnmanaged(u32) = .{}, |
| 36 | 36 | /// File encapsulated string table, used to deduplicate strings within the generated file. |
| 37 | 37 | string_table: StringTable = .{}, |
| 38 | 38 | /// Map for storing anonymous declarations. Each anonymous decl maps to its Atom's index. |
| 39 | anon_decls: std.AutoArrayHashMapUnmanaged(InternPool.Index, Atom.Index) = .{}, | |
| 39 | uavs: std.AutoArrayHashMapUnmanaged(InternPool.Index, Atom.Index) = .{}, | |
| 40 | 40 | /// List of atom indexes of functions that are generated by the backend. |
| 41 | 41 | synthetic_functions: std.ArrayListUnmanaged(Atom.Index) = .{}, |
| 42 | 42 | /// Represents the symbol index of the error name table |
| ... | ... | @@ -86,12 +86,12 @@ debug_str_index: ?u32 = null, |
| 86 | 86 | /// The index of the segment representing the custom '.debug_pubtypes' section. |
| 87 | 87 | debug_abbrev_index: ?u32 = null, |
| 88 | 88 | |
| 89 | const DeclInfo = struct { | |
| 89 | const NavInfo = struct { | |
| 90 | 90 | atom: Atom.Index = .null, |
| 91 | 91 | exports: std.ArrayListUnmanaged(Symbol.Index) = .{}, |
| 92 | 92 | |
| 93 | fn @"export"(di: DeclInfo, zig_object: *const ZigObject, name: []const u8) ?Symbol.Index { | |
| 94 | for (di.exports.items) |sym_index| { | |
| 93 | fn @"export"(ni: NavInfo, zig_object: *const ZigObject, name: []const u8) ?Symbol.Index { | |
| 94 | for (ni.exports.items) |sym_index| { | |
| 95 | 95 | const sym_name_index = zig_object.symbol(sym_index).name; |
| 96 | 96 | const sym_name = zig_object.string_table.getAssumeExists(sym_name_index); |
| 97 | 97 | if (std.mem.eql(u8, name, sym_name)) { |
| ... | ... | @@ -101,14 +101,14 @@ const DeclInfo = struct { |
| 101 | 101 | return null; |
| 102 | 102 | } |
| 103 | 103 | |
| 104 | fn appendExport(di: *DeclInfo, gpa: std.mem.Allocator, sym_index: Symbol.Index) !void { | |
| 105 | return di.exports.append(gpa, sym_index); | |
| 104 | fn appendExport(ni: *NavInfo, gpa: std.mem.Allocator, sym_index: Symbol.Index) !void { | |
| 105 | return ni.exports.append(gpa, sym_index); | |
| 106 | 106 | } |
| 107 | 107 | |
| 108 | fn deleteExport(di: *DeclInfo, sym_index: Symbol.Index) void { | |
| 109 | for (di.exports.items, 0..) |idx, index| { | |
| 108 | fn deleteExport(ni: *NavInfo, sym_index: Symbol.Index) void { | |
| 109 | for (ni.exports.items, 0..) |idx, index| { | |
| 110 | 110 | if (idx == sym_index) { |
| 111 | _ = di.exports.swapRemove(index); | |
| 111 | _ = ni.exports.swapRemove(index); | |
| 112 | 112 | return; |
| 113 | 113 | } |
| 114 | 114 | } |
| ... | ... | @@ -155,19 +155,19 @@ pub fn deinit(zig_object: *ZigObject, wasm_file: *Wasm) void { |
| 155 | 155 | } |
| 156 | 156 | |
| 157 | 157 | { |
| 158 | var it = zig_object.decls_map.valueIterator(); | |
| 159 | while (it.next()) |decl_info| { | |
| 160 | const atom = wasm_file.getAtomPtr(decl_info.atom); | |
| 158 | var it = zig_object.navs.valueIterator(); | |
| 159 | while (it.next()) |nav_info| { | |
| 160 | const atom = wasm_file.getAtomPtr(nav_info.atom); | |
| 161 | 161 | for (atom.locals.items) |local_index| { |
| 162 | 162 | const local_atom = wasm_file.getAtomPtr(local_index); |
| 163 | 163 | local_atom.deinit(gpa); |
| 164 | 164 | } |
| 165 | 165 | atom.deinit(gpa); |
| 166 | decl_info.exports.deinit(gpa); | |
| 166 | nav_info.exports.deinit(gpa); | |
| 167 | 167 | } |
| 168 | 168 | } |
| 169 | 169 | { |
| 170 | for (zig_object.anon_decls.values()) |atom_index| { | |
| 170 | for (zig_object.uavs.values()) |atom_index| { | |
| 171 | 171 | const atom = wasm_file.getAtomPtr(atom_index); |
| 172 | 172 | for (atom.locals.items) |local_index| { |
| 173 | 173 | const local_atom = wasm_file.getAtomPtr(local_index); |
| ... | ... | @@ -201,8 +201,8 @@ pub fn deinit(zig_object: *ZigObject, wasm_file: *Wasm) void { |
| 201 | 201 | zig_object.atom_types.deinit(gpa); |
| 202 | 202 | zig_object.functions.deinit(gpa); |
| 203 | 203 | zig_object.imports.deinit(gpa); |
| 204 | zig_object.decls_map.deinit(gpa); | |
| 205 | zig_object.anon_decls.deinit(gpa); | |
| 204 | zig_object.navs.deinit(gpa); | |
| 205 | zig_object.uavs.deinit(gpa); | |
| 206 | 206 | zig_object.symbols.deinit(gpa); |
| 207 | 207 | zig_object.symbols_free_list.deinit(gpa); |
| 208 | 208 | zig_object.segment_info.deinit(gpa); |
| ... | ... | @@ -236,34 +236,35 @@ pub fn allocateSymbol(zig_object: *ZigObject, gpa: std.mem.Allocator) !Symbol.In |
| 236 | 236 | return index; |
| 237 | 237 | } |
| 238 | 238 | |
| 239 | // Generate code for the Decl, storing it in memory to be later written to | |
| 239 | // Generate code for the `Nav`, storing it in memory to be later written to | |
| 240 | 240 | // the file on flush(). |
| 241 | pub fn updateDecl( | |
| 241 | pub fn updateNav( | |
| 242 | 242 | zig_object: *ZigObject, |
| 243 | 243 | wasm_file: *Wasm, |
| 244 | 244 | pt: Zcu.PerThread, |
| 245 | decl_index: InternPool.DeclIndex, | |
| 245 | nav_index: InternPool.Nav.Index, | |
| 246 | 246 | ) !void { |
| 247 | const mod = pt.zcu; | |
| 248 | const decl = mod.declPtr(decl_index); | |
| 249 | if (decl.val.getFunction(mod)) |_| { | |
| 250 | return; | |
| 251 | } else if (decl.val.getExternFunc(mod)) |_| { | |
| 252 | return; | |
| 253 | } | |
| 247 | const zcu = pt.zcu; | |
| 248 | const ip = &zcu.intern_pool; | |
| 249 | const nav = ip.getNav(nav_index); | |
| 250 | ||
| 251 | const is_extern, const lib_name, const nav_init = switch (ip.indexToKey(nav.status.resolved.val)) { | |
| 252 | .variable => |variable| .{ false, variable.lib_name, variable.init }, | |
| 253 | .func => return, | |
| 254 | .@"extern" => |@"extern"| if (ip.isFunctionType(nav.typeOf(ip))) | |
| 255 | return | |
| 256 | else | |
| 257 | .{ true, @"extern".lib_name, nav.status.resolved.val }, | |
| 258 | else => .{ false, .none, nav.status.resolved.val }, | |
| 259 | }; | |
| 254 | 260 | |
| 255 | 261 | const gpa = wasm_file.base.comp.gpa; |
| 256 | const atom_index = try zig_object.getOrCreateAtomForDecl(wasm_file, pt, decl_index); | |
| 262 | const atom_index = try zig_object.getOrCreateAtomForNav(wasm_file, pt, nav_index); | |
| 257 | 263 | const atom = wasm_file.getAtomPtr(atom_index); |
| 258 | 264 | atom.clear(); |
| 259 | 265 | |
| 260 | if (decl.isExtern(mod)) { | |
| 261 | const variable = decl.getOwnedVariable(mod).?; | |
| 262 | const name = decl.name.toSlice(&mod.intern_pool); | |
| 263 | const lib_name = variable.lib_name.toSlice(&mod.intern_pool); | |
| 264 | return zig_object.addOrUpdateImport(wasm_file, name, atom.sym_index, lib_name, null); | |
| 265 | } | |
| 266 | const val = if (decl.val.getVariable(mod)) |variable| Value.fromInterned(variable.init) else decl.val; | |
| 266 | if (is_extern) | |
| 267 | return zig_object.addOrUpdateImport(wasm_file, nav.name.toSlice(ip), atom.sym_index, lib_name.toSlice(ip), null); | |
| 267 | 268 | |
| 268 | 269 | var code_writer = std.ArrayList(u8).init(gpa); |
| 269 | 270 | defer code_writer.deinit(); |
| ... | ... | @@ -271,8 +272,8 @@ pub fn updateDecl( |
| 271 | 272 | const res = try codegen.generateSymbol( |
| 272 | 273 | &wasm_file.base, |
| 273 | 274 | pt, |
| 274 | decl.navSrcLoc(mod), | |
| 275 | val, | |
| 275 | zcu.navSrcLoc(nav_index), | |
| 276 | Value.fromInterned(nav_init), | |
| 276 | 277 | &code_writer, |
| 277 | 278 | .none, |
| 278 | 279 | .{ .parent_atom_index = @intFromEnum(atom.sym_index) }, |
| ... | ... | @@ -281,13 +282,12 @@ pub fn updateDecl( |
| 281 | 282 | const code = switch (res) { |
| 282 | 283 | .ok => code_writer.items, |
| 283 | 284 | .fail => |em| { |
| 284 | decl.analysis = .codegen_failure; | |
| 285 | try mod.failed_analysis.put(mod.gpa, AnalUnit.wrap(.{ .decl = decl_index }), em); | |
| 285 | try zcu.failed_codegen.put(zcu.gpa, nav_index, em); | |
| 286 | 286 | return; |
| 287 | 287 | }, |
| 288 | 288 | }; |
| 289 | 289 | |
| 290 | return zig_object.finishUpdateDecl(wasm_file, pt, decl_index, code); | |
| 290 | return zig_object.finishUpdateNav(wasm_file, pt, nav_index, code); | |
| 291 | 291 | } |
| 292 | 292 | |
| 293 | 293 | pub fn updateFunc( |
| ... | ... | @@ -298,11 +298,10 @@ pub fn updateFunc( |
| 298 | 298 | air: Air, |
| 299 | 299 | liveness: Liveness, |
| 300 | 300 | ) !void { |
| 301 | const gpa = wasm_file.base.comp.gpa; | |
| 301 | const zcu = pt.zcu; | |
| 302 | const gpa = zcu.gpa; | |
| 302 | 303 | const func = pt.zcu.funcInfo(func_index); |
| 303 | const decl_index = func.owner_decl; | |
| 304 | const decl = pt.zcu.declPtr(decl_index); | |
| 305 | const atom_index = try zig_object.getOrCreateAtomForDecl(wasm_file, pt, decl_index); | |
| 304 | const atom_index = try zig_object.getOrCreateAtomForNav(wasm_file, pt, func.owner_nav); | |
| 306 | 305 | const atom = wasm_file.getAtomPtr(atom_index); |
| 307 | 306 | atom.clear(); |
| 308 | 307 | |
| ... | ... | @@ -311,7 +310,7 @@ pub fn updateFunc( |
| 311 | 310 | const result = try codegen.generateFunction( |
| 312 | 311 | &wasm_file.base, |
| 313 | 312 | pt, |
| 314 | decl.navSrcLoc(pt.zcu), | |
| 313 | zcu.navSrcLoc(func.owner_nav), | |
| 315 | 314 | func_index, |
| 316 | 315 | air, |
| 317 | 316 | liveness, |
| ... | ... | @@ -322,79 +321,75 @@ pub fn updateFunc( |
| 322 | 321 | const code = switch (result) { |
| 323 | 322 | .ok => code_writer.items, |
| 324 | 323 | .fail => |em| { |
| 325 | decl.analysis = .codegen_failure; | |
| 326 | try pt.zcu.failed_analysis.put(gpa, AnalUnit.wrap(.{ .decl = decl_index }), em); | |
| 324 | try pt.zcu.failed_codegen.put(gpa, func.owner_nav, em); | |
| 327 | 325 | return; |
| 328 | 326 | }, |
| 329 | 327 | }; |
| 330 | 328 | |
| 331 | return zig_object.finishUpdateDecl(wasm_file, pt, decl_index, code); | |
| 329 | return zig_object.finishUpdateNav(wasm_file, pt, func.owner_nav, code); | |
| 332 | 330 | } |
| 333 | 331 | |
| 334 | fn finishUpdateDecl( | |
| 332 | fn finishUpdateNav( | |
| 335 | 333 | zig_object: *ZigObject, |
| 336 | 334 | wasm_file: *Wasm, |
| 337 | 335 | pt: Zcu.PerThread, |
| 338 | decl_index: InternPool.DeclIndex, | |
| 336 | nav_index: InternPool.Nav.Index, | |
| 339 | 337 | code: []const u8, |
| 340 | 338 | ) !void { |
| 341 | 339 | const zcu = pt.zcu; |
| 342 | 340 | const ip = &zcu.intern_pool; |
| 343 | 341 | const gpa = zcu.gpa; |
| 344 | const decl = zcu.declPtr(decl_index); | |
| 345 | const decl_info = zig_object.decls_map.get(decl_index).?; | |
| 346 | const atom_index = decl_info.atom; | |
| 342 | const nav = ip.getNav(nav_index); | |
| 343 | const nav_val = zcu.navValue(nav_index); | |
| 344 | const nav_info = zig_object.navs.get(nav_index).?; | |
| 345 | const atom_index = nav_info.atom; | |
| 347 | 346 | const atom = wasm_file.getAtomPtr(atom_index); |
| 348 | 347 | const sym = zig_object.symbol(atom.sym_index); |
| 349 | sym.name = try zig_object.string_table.insert(gpa, decl.fqn.toSlice(ip)); | |
| 348 | sym.name = try zig_object.string_table.insert(gpa, nav.fqn.toSlice(ip)); | |
| 350 | 349 | try atom.code.appendSlice(gpa, code); |
| 351 | 350 | atom.size = @intCast(code.len); |
| 352 | 351 | |
| 353 | switch (decl.typeOf(zcu).zigTypeTag(zcu)) { | |
| 354 | .Fn => { | |
| 355 | sym.index = try zig_object.appendFunction(gpa, .{ .type_index = zig_object.atom_types.get(atom_index).? }); | |
| 356 | sym.tag = .function; | |
| 357 | }, | |
| 358 | else => { | |
| 359 | const segment_name: []const u8 = if (decl.getOwnedVariable(zcu)) |variable| name: { | |
| 360 | if (variable.is_const) { | |
| 361 | break :name ".rodata."; | |
| 362 | } else if (Value.fromInterned(variable.init).isUndefDeep(zcu)) { | |
| 363 | const decl_namespace = zcu.namespacePtr(decl.src_namespace); | |
| 364 | const optimize_mode = decl_namespace.fileScope(zcu).mod.optimize_mode; | |
| 365 | const is_initialized = switch (optimize_mode) { | |
| 366 | .Debug, .ReleaseSafe => true, | |
| 367 | .ReleaseFast, .ReleaseSmall => false, | |
| 368 | }; | |
| 369 | if (is_initialized) { | |
| 370 | break :name ".data."; | |
| 371 | } | |
| 372 | break :name ".bss."; | |
| 373 | } | |
| 374 | // when the decl is all zeroes, we store the atom in the bss segment, | |
| 375 | // in all other cases it will be in the data segment. | |
| 376 | for (atom.code.items) |byte| { | |
| 377 | if (byte != 0) break :name ".data."; | |
| 378 | } | |
| 379 | break :name ".bss."; | |
| 380 | } else ".rodata."; | |
| 381 | if ((wasm_file.base.isObject() or wasm_file.base.comp.config.import_memory) and | |
| 382 | std.mem.startsWith(u8, segment_name, ".bss")) | |
| 383 | { | |
| 384 | @memset(atom.code.items, 0); | |
| 352 | if (ip.isFunctionType(nav.typeOf(ip))) { | |
| 353 | sym.index = try zig_object.appendFunction(gpa, .{ .type_index = zig_object.atom_types.get(atom_index).? }); | |
| 354 | sym.tag = .function; | |
| 355 | } else { | |
| 356 | const is_const, const nav_init = switch (ip.indexToKey(nav_val.toIntern())) { | |
| 357 | .variable => |variable| .{ false, variable.init }, | |
| 358 | .@"extern" => |@"extern"| .{ @"extern".is_const, .none }, | |
| 359 | else => .{ true, nav_val.toIntern() }, | |
| 360 | }; | |
| 361 | const segment_name = name: { | |
| 362 | if (is_const) break :name ".rodata."; | |
| 363 | ||
| 364 | if (nav_init != .none and Value.fromInterned(nav_init).isUndefDeep(zcu)) { | |
| 365 | break :name switch (zcu.navFileScope(nav_index).mod.optimize_mode) { | |
| 366 | .Debug, .ReleaseSafe => ".data.", | |
| 367 | .ReleaseFast, .ReleaseSmall => ".bss.", | |
| 368 | }; | |
| 385 | 369 | } |
| 386 | // Will be freed upon freeing of decl or after cleanup of Wasm binary. | |
| 387 | const full_segment_name = try std.mem.concat(gpa, u8, &.{ | |
| 388 | segment_name, | |
| 389 | decl.fqn.toSlice(ip), | |
| 390 | }); | |
| 391 | errdefer gpa.free(full_segment_name); | |
| 392 | sym.tag = .data; | |
| 393 | sym.index = try zig_object.createDataSegment(gpa, full_segment_name, decl.alignment); | |
| 394 | }, | |
| 370 | // when the decl is all zeroes, we store the atom in the bss segment, | |
| 371 | // in all other cases it will be in the data segment. | |
| 372 | for (atom.code.items) |byte| { | |
| 373 | if (byte != 0) break :name ".data."; | |
| 374 | } | |
| 375 | break :name ".bss."; | |
| 376 | }; | |
| 377 | if ((wasm_file.base.isObject() or wasm_file.base.comp.config.import_memory) and | |
| 378 | std.mem.startsWith(u8, segment_name, ".bss")) | |
| 379 | { | |
| 380 | @memset(atom.code.items, 0); | |
| 381 | } | |
| 382 | // Will be freed upon freeing of decl or after cleanup of Wasm binary. | |
| 383 | const full_segment_name = try std.mem.concat(gpa, u8, &.{ | |
| 384 | segment_name, | |
| 385 | nav.fqn.toSlice(ip), | |
| 386 | }); | |
| 387 | errdefer gpa.free(full_segment_name); | |
| 388 | sym.tag = .data; | |
| 389 | sym.index = try zig_object.createDataSegment(gpa, full_segment_name, pt.navAlignment(nav_index)); | |
| 395 | 390 | } |
| 396 | 391 | if (code.len == 0) return; |
| 397 | atom.alignment = decl.getAlignment(pt); | |
| 392 | atom.alignment = pt.navAlignment(nav_index); | |
| 398 | 393 | } |
| 399 | 394 | |
| 400 | 395 | /// Creates and initializes a new segment in the 'Data' section. |
| ... | ... | @@ -420,50 +415,51 @@ fn createDataSegment( |
| 420 | 415 | return segment_index; |
| 421 | 416 | } |
| 422 | 417 | |
| 423 | /// For a given `InternPool.DeclIndex` returns its corresponding `Atom.Index`. | |
| 418 | /// For a given `InternPool.Nav.Index` returns its corresponding `Atom.Index`. | |
| 424 | 419 | /// When the index was not found, a new `Atom` will be created, and its index will be returned. |
| 425 | 420 | /// The newly created Atom is empty with default fields as specified by `Atom.empty`. |
| 426 | pub fn getOrCreateAtomForDecl( | |
| 421 | pub fn getOrCreateAtomForNav( | |
| 427 | 422 | zig_object: *ZigObject, |
| 428 | 423 | wasm_file: *Wasm, |
| 429 | 424 | pt: Zcu.PerThread, |
| 430 | decl_index: InternPool.DeclIndex, | |
| 425 | nav_index: InternPool.Nav.Index, | |
| 431 | 426 | ) !Atom.Index { |
| 427 | const ip = &pt.zcu.intern_pool; | |
| 432 | 428 | const gpa = pt.zcu.gpa; |
| 433 | const gop = try zig_object.decls_map.getOrPut(gpa, decl_index); | |
| 429 | const gop = try zig_object.navs.getOrPut(gpa, nav_index); | |
| 434 | 430 | if (!gop.found_existing) { |
| 435 | 431 | const sym_index = try zig_object.allocateSymbol(gpa); |
| 436 | 432 | gop.value_ptr.* = .{ .atom = try wasm_file.createAtom(sym_index, zig_object.index) }; |
| 437 | const decl = pt.zcu.declPtr(decl_index); | |
| 433 | const nav = ip.getNav(nav_index); | |
| 438 | 434 | const sym = zig_object.symbol(sym_index); |
| 439 | sym.name = try zig_object.string_table.insert(gpa, decl.fqn.toSlice(&pt.zcu.intern_pool)); | |
| 435 | sym.name = try zig_object.string_table.insert(gpa, nav.fqn.toSlice(ip)); | |
| 440 | 436 | } |
| 441 | 437 | return gop.value_ptr.atom; |
| 442 | 438 | } |
| 443 | 439 | |
| 444 | pub fn lowerAnonDecl( | |
| 440 | pub fn lowerUav( | |
| 445 | 441 | zig_object: *ZigObject, |
| 446 | 442 | wasm_file: *Wasm, |
| 447 | 443 | pt: Zcu.PerThread, |
| 448 | decl_val: InternPool.Index, | |
| 444 | uav: InternPool.Index, | |
| 449 | 445 | explicit_alignment: InternPool.Alignment, |
| 450 | 446 | src_loc: Zcu.LazySrcLoc, |
| 451 | ) !codegen.Result { | |
| 447 | ) !codegen.GenResult { | |
| 452 | 448 | const gpa = wasm_file.base.comp.gpa; |
| 453 | const gop = try zig_object.anon_decls.getOrPut(gpa, decl_val); | |
| 449 | const gop = try zig_object.uavs.getOrPut(gpa, uav); | |
| 454 | 450 | if (!gop.found_existing) { |
| 455 | 451 | var name_buf: [32]u8 = undefined; |
| 456 | 452 | const name = std.fmt.bufPrint(&name_buf, "__anon_{d}", .{ |
| 457 | @intFromEnum(decl_val), | |
| 453 | @intFromEnum(uav), | |
| 458 | 454 | }) catch unreachable; |
| 459 | 455 | |
| 460 | switch (try zig_object.lowerConst(wasm_file, pt, name, Value.fromInterned(decl_val), src_loc)) { | |
| 461 | .ok => |atom_index| zig_object.anon_decls.values()[gop.index] = atom_index, | |
| 456 | switch (try zig_object.lowerConst(wasm_file, pt, name, Value.fromInterned(uav), src_loc)) { | |
| 457 | .ok => |atom_index| zig_object.uavs.values()[gop.index] = atom_index, | |
| 462 | 458 | .fail => |em| return .{ .fail = em }, |
| 463 | 459 | } |
| 464 | 460 | } |
| 465 | 461 | |
| 466 | const atom = wasm_file.getAtomPtr(zig_object.anon_decls.values()[gop.index]); | |
| 462 | const atom = wasm_file.getAtomPtr(zig_object.uavs.values()[gop.index]); | |
| 467 | 463 | atom.alignment = switch (atom.alignment) { |
| 468 | 464 | .none => explicit_alignment, |
| 469 | 465 | else => switch (explicit_alignment) { |
| ... | ... | @@ -471,53 +467,7 @@ pub fn lowerAnonDecl( |
| 471 | 467 | else => atom.alignment.maxStrict(explicit_alignment), |
| 472 | 468 | }, |
| 473 | 469 | }; |
| 474 | return .ok; | |
| 475 | } | |
| 476 | ||
| 477 | /// Lowers a constant typed value to a local symbol and atom. | |
| 478 | /// Returns the symbol index of the local | |
| 479 | /// The given `decl` is the parent decl whom owns the constant. | |
| 480 | pub fn lowerUnnamedConst( | |
| 481 | zig_object: *ZigObject, | |
| 482 | wasm_file: *Wasm, | |
| 483 | pt: Zcu.PerThread, | |
| 484 | val: Value, | |
| 485 | decl_index: InternPool.DeclIndex, | |
| 486 | ) !u32 { | |
| 487 | const mod = pt.zcu; | |
| 488 | const gpa = mod.gpa; | |
| 489 | std.debug.assert(val.typeOf(mod).zigTypeTag(mod) != .Fn); // cannot create local symbols for functions | |
| 490 | const decl = mod.declPtr(decl_index); | |
| 491 | ||
| 492 | const parent_atom_index = try zig_object.getOrCreateAtomForDecl(wasm_file, pt, decl_index); | |
| 493 | const parent_atom = wasm_file.getAtom(parent_atom_index); | |
| 494 | const local_index = parent_atom.locals.items.len; | |
| 495 | const name = try std.fmt.allocPrintZ(gpa, "__unnamed_{}_{d}", .{ | |
| 496 | decl.fqn.fmt(&mod.intern_pool), local_index, | |
| 497 | }); | |
| 498 | defer gpa.free(name); | |
| 499 | ||
| 500 | // We want to lower the source location of `decl`. However, when generating | |
| 501 | // lazy functions (for e.g. `@tagName`), `decl` may correspond to a type | |
| 502 | // rather than a `Nav`! | |
| 503 | // The future split of `Decl` into `Nav` and `Cau` may require rethinking this | |
| 504 | // logic. For now, just get the source location conditionally as needed. | |
| 505 | const decl_src = if (decl.typeOf(mod).toIntern() == .type_type) | |
| 506 | decl.val.toType().srcLoc(mod) | |
| 507 | else | |
| 508 | decl.navSrcLoc(mod); | |
| 509 | ||
| 510 | switch (try zig_object.lowerConst(wasm_file, pt, name, val, decl_src)) { | |
| 511 | .ok => |atom_index| { | |
| 512 | try wasm_file.getAtomPtr(parent_atom_index).locals.append(gpa, atom_index); | |
| 513 | return @intFromEnum(wasm_file.getAtom(atom_index).sym_index); | |
| 514 | }, | |
| 515 | .fail => |em| { | |
| 516 | decl.analysis = .codegen_failure; | |
| 517 | try mod.failed_analysis.put(mod.gpa, AnalUnit.wrap(.{ .decl = decl_index }), em); | |
| 518 | return error.CodegenFail; | |
| 519 | }, | |
| 520 | } | |
| 470 | return .{ .mcv = .{ .load_symbol = @intFromEnum(atom.sym_index) } }; | |
| 521 | 471 | } |
| 522 | 472 | |
| 523 | 473 | const LowerConstResult = union(enum) { |
| ... | ... | @@ -782,36 +732,38 @@ pub fn getGlobalSymbol(zig_object: *ZigObject, gpa: std.mem.Allocator, name: []c |
| 782 | 732 | |
| 783 | 733 | /// For a given decl, find the given symbol index's atom, and create a relocation for the type. |
| 784 | 734 | /// Returns the given pointer address |
| 785 | pub fn getDeclVAddr( | |
| 735 | pub fn getNavVAddr( | |
| 786 | 736 | zig_object: *ZigObject, |
| 787 | 737 | wasm_file: *Wasm, |
| 788 | 738 | pt: Zcu.PerThread, |
| 789 | decl_index: InternPool.DeclIndex, | |
| 739 | nav_index: InternPool.Nav.Index, | |
| 790 | 740 | reloc_info: link.File.RelocInfo, |
| 791 | 741 | ) !u64 { |
| 792 | const target = wasm_file.base.comp.root_mod.resolved_target.result; | |
| 793 | 742 | const zcu = pt.zcu; |
| 794 | 743 | const ip = &zcu.intern_pool; |
| 795 | 744 | const gpa = zcu.gpa; |
| 796 | const decl = zcu.declPtr(decl_index); | |
| 745 | const nav = ip.getNav(nav_index); | |
| 746 | const target = &zcu.navFileScope(nav_index).mod.resolved_target.result; | |
| 797 | 747 | |
| 798 | const target_atom_index = try zig_object.getOrCreateAtomForDecl(wasm_file, pt, decl_index); | |
| 748 | const target_atom_index = try zig_object.getOrCreateAtomForNav(wasm_file, pt, nav_index); | |
| 799 | 749 | const target_atom = wasm_file.getAtom(target_atom_index); |
| 800 | 750 | const target_symbol_index = @intFromEnum(target_atom.sym_index); |
| 801 | if (decl.isExtern(zcu)) { | |
| 802 | const name = decl.name.toSlice(ip); | |
| 803 | const lib_name = if (decl.getOwnedExternFunc(zcu)) |ext_fn| | |
| 804 | ext_fn.lib_name.toSlice(ip) | |
| 805 | else | |
| 806 | decl.getOwnedVariable(zcu).?.lib_name.toSlice(ip); | |
| 807 | try zig_object.addOrUpdateImport(wasm_file, name, target_atom.sym_index, lib_name, null); | |
| 751 | switch (ip.indexToKey(nav.status.resolved.val)) { | |
| 752 | .@"extern" => |@"extern"| try zig_object.addOrUpdateImport( | |
| 753 | wasm_file, | |
| 754 | nav.name.toSlice(ip), | |
| 755 | target_atom.sym_index, | |
| 756 | @"extern".lib_name.toSlice(ip), | |
| 757 | null, | |
| 758 | ), | |
| 759 | else => {}, | |
| 808 | 760 | } |
| 809 | 761 | |
| 810 | 762 | std.debug.assert(reloc_info.parent_atom_index != 0); |
| 811 | 763 | const atom_index = wasm_file.symbol_atom.get(.{ .file = zig_object.index, .index = @enumFromInt(reloc_info.parent_atom_index) }).?; |
| 812 | 764 | const atom = wasm_file.getAtomPtr(atom_index); |
| 813 | 765 | const is_wasm32 = target.cpu.arch == .wasm32; |
| 814 | if (decl.typeOf(pt.zcu).zigTypeTag(pt.zcu) == .Fn) { | |
| 766 | if (ip.isFunctionType(ip.getNav(nav_index).typeOf(ip))) { | |
| 815 | 767 | std.debug.assert(reloc_info.addend == 0); // addend not allowed for function relocations |
| 816 | 768 | try atom.relocs.append(gpa, .{ |
| 817 | 769 | .index = target_symbol_index, |
| ... | ... | @@ -834,22 +786,22 @@ pub fn getDeclVAddr( |
| 834 | 786 | return target_symbol_index; |
| 835 | 787 | } |
| 836 | 788 | |
| 837 | pub fn getAnonDeclVAddr( | |
| 789 | pub fn getUavVAddr( | |
| 838 | 790 | zig_object: *ZigObject, |
| 839 | 791 | wasm_file: *Wasm, |
| 840 | decl_val: InternPool.Index, | |
| 792 | uav: InternPool.Index, | |
| 841 | 793 | reloc_info: link.File.RelocInfo, |
| 842 | 794 | ) !u64 { |
| 843 | 795 | const gpa = wasm_file.base.comp.gpa; |
| 844 | 796 | const target = wasm_file.base.comp.root_mod.resolved_target.result; |
| 845 | const atom_index = zig_object.anon_decls.get(decl_val).?; | |
| 797 | const atom_index = zig_object.uavs.get(uav).?; | |
| 846 | 798 | const target_symbol_index = @intFromEnum(wasm_file.getAtom(atom_index).sym_index); |
| 847 | 799 | |
| 848 | 800 | const parent_atom_index = wasm_file.symbol_atom.get(.{ .file = zig_object.index, .index = @enumFromInt(reloc_info.parent_atom_index) }).?; |
| 849 | 801 | const parent_atom = wasm_file.getAtomPtr(parent_atom_index); |
| 850 | 802 | const is_wasm32 = target.cpu.arch == .wasm32; |
| 851 | 803 | const mod = wasm_file.base.comp.module.?; |
| 852 | const ty = Type.fromInterned(mod.intern_pool.typeOf(decl_val)); | |
| 804 | const ty = Type.fromInterned(mod.intern_pool.typeOf(uav)); | |
| 853 | 805 | if (ty.zigTypeTag(mod) == .Fn) { |
| 854 | 806 | std.debug.assert(reloc_info.addend == 0); // addend not allowed for function relocations |
| 855 | 807 | try parent_atom.relocs.append(gpa, .{ |
| ... | ... | @@ -880,14 +832,14 @@ pub fn deleteExport( |
| 880 | 832 | name: InternPool.NullTerminatedString, |
| 881 | 833 | ) void { |
| 882 | 834 | const mod = wasm_file.base.comp.module.?; |
| 883 | const decl_index = switch (exported) { | |
| 884 | .decl_index => |decl_index| decl_index, | |
| 885 | .value => @panic("TODO: implement Wasm linker code for exporting a constant value"), | |
| 835 | const nav_index = switch (exported) { | |
| 836 | .nav => |nav_index| nav_index, | |
| 837 | .uav => @panic("TODO: implement Wasm linker code for exporting a constant value"), | |
| 886 | 838 | }; |
| 887 | const decl_info = zig_object.decls_map.getPtr(decl_index) orelse return; | |
| 888 | if (decl_info.@"export"(zig_object, name.toSlice(&mod.intern_pool))) |sym_index| { | |
| 839 | const nav_info = zig_object.navs.getPtr(nav_index) orelse return; | |
| 840 | if (nav_info.@"export"(zig_object, name.toSlice(&mod.intern_pool))) |sym_index| { | |
| 889 | 841 | const sym = zig_object.symbol(sym_index); |
| 890 | decl_info.deleteExport(sym_index); | |
| 842 | nav_info.deleteExport(sym_index); | |
| 891 | 843 | std.debug.assert(zig_object.global_syms.remove(sym.name)); |
| 892 | 844 | std.debug.assert(wasm_file.symbol_atom.remove(.{ .file = zig_object.index, .index = sym_index })); |
| 893 | 845 | zig_object.symbols_free_list.append(wasm_file.base.comp.gpa, sym_index) catch {}; |
| ... | ... | @@ -902,38 +854,39 @@ pub fn updateExports( |
| 902 | 854 | exported: Zcu.Exported, |
| 903 | 855 | export_indices: []const u32, |
| 904 | 856 | ) !void { |
| 905 | const mod = pt.zcu; | |
| 906 | const decl_index = switch (exported) { | |
| 907 | .decl_index => |i| i, | |
| 908 | .value => |val| { | |
| 909 | _ = val; | |
| 857 | const zcu = pt.zcu; | |
| 858 | const ip = &zcu.intern_pool; | |
| 859 | const nav_index = switch (exported) { | |
| 860 | .nav => |nav| nav, | |
| 861 | .uav => |uav| { | |
| 862 | _ = uav; | |
| 910 | 863 | @panic("TODO: implement Wasm linker code for exporting a constant value"); |
| 911 | 864 | }, |
| 912 | 865 | }; |
| 913 | const decl = mod.declPtr(decl_index); | |
| 914 | const atom_index = try zig_object.getOrCreateAtomForDecl(wasm_file, pt, decl_index); | |
| 915 | const decl_info = zig_object.decls_map.getPtr(decl_index).?; | |
| 866 | const nav = ip.getNav(nav_index); | |
| 867 | const atom_index = try zig_object.getOrCreateAtomForNav(wasm_file, pt, nav_index); | |
| 868 | const nav_info = zig_object.navs.getPtr(nav_index).?; | |
| 916 | 869 | const atom = wasm_file.getAtom(atom_index); |
| 917 | 870 | const atom_sym = atom.symbolLoc().getSymbol(wasm_file).*; |
| 918 | const gpa = mod.gpa; | |
| 919 | log.debug("Updating exports for decl '{}'", .{decl.name.fmt(&mod.intern_pool)}); | |
| 871 | const gpa = zcu.gpa; | |
| 872 | log.debug("Updating exports for decl '{}'", .{nav.name.fmt(ip)}); | |
| 920 | 873 | |
| 921 | 874 | for (export_indices) |export_idx| { |
| 922 | const exp = mod.all_exports.items[export_idx]; | |
| 923 | if (exp.opts.section.toSlice(&mod.intern_pool)) |section| { | |
| 924 | try mod.failed_exports.putNoClobber(gpa, export_idx, try Zcu.ErrorMsg.create( | |
| 875 | const exp = zcu.all_exports.items[export_idx]; | |
| 876 | if (exp.opts.section.toSlice(ip)) |section| { | |
| 877 | try zcu.failed_exports.putNoClobber(gpa, export_idx, try Zcu.ErrorMsg.create( | |
| 925 | 878 | gpa, |
| 926 | decl.navSrcLoc(mod), | |
| 879 | zcu.navSrcLoc(nav_index), | |
| 927 | 880 | "Unimplemented: ExportOptions.section '{s}'", |
| 928 | 881 | .{section}, |
| 929 | 882 | )); |
| 930 | 883 | continue; |
| 931 | 884 | } |
| 932 | 885 | |
| 933 | const export_string = exp.opts.name.toSlice(&mod.intern_pool); | |
| 934 | const sym_index = if (decl_info.@"export"(zig_object, export_string)) |idx| idx else index: { | |
| 886 | const export_string = exp.opts.name.toSlice(ip); | |
| 887 | const sym_index = if (nav_info.@"export"(zig_object, export_string)) |idx| idx else index: { | |
| 935 | 888 | const sym_index = try zig_object.allocateSymbol(gpa); |
| 936 | try decl_info.appendExport(gpa, sym_index); | |
| 889 | try nav_info.appendExport(gpa, sym_index); | |
| 937 | 890 | break :index sym_index; |
| 938 | 891 | }; |
| 939 | 892 | |
| ... | ... | @@ -954,9 +907,9 @@ pub fn updateExports( |
| 954 | 907 | }, |
| 955 | 908 | .strong => {}, // symbols are strong by default |
| 956 | 909 | .link_once => { |
| 957 | try mod.failed_exports.putNoClobber(gpa, export_idx, try Zcu.ErrorMsg.create( | |
| 910 | try zcu.failed_exports.putNoClobber(gpa, export_idx, try Zcu.ErrorMsg.create( | |
| 958 | 911 | gpa, |
| 959 | decl.navSrcLoc(mod), | |
| 912 | zcu.navSrcLoc(nav_index), | |
| 960 | 913 | "Unimplemented: LinkOnce", |
| 961 | 914 | .{}, |
| 962 | 915 | )); |
| ... | ... | @@ -972,21 +925,21 @@ pub fn updateExports( |
| 972 | 925 | } |
| 973 | 926 | } |
| 974 | 927 | |
| 975 | pub fn freeDecl(zig_object: *ZigObject, wasm_file: *Wasm, decl_index: InternPool.DeclIndex) void { | |
| 928 | pub fn freeNav(zig_object: *ZigObject, wasm_file: *Wasm, nav_index: InternPool.Nav.Index) void { | |
| 976 | 929 | const gpa = wasm_file.base.comp.gpa; |
| 977 | 930 | const mod = wasm_file.base.comp.module.?; |
| 978 | const decl = mod.declPtr(decl_index); | |
| 979 | const decl_info = zig_object.decls_map.getPtr(decl_index).?; | |
| 980 | const atom_index = decl_info.atom; | |
| 931 | const ip = &mod.intern_pool; | |
| 932 | const nav_info = zig_object.navs.getPtr(nav_index).?; | |
| 933 | const atom_index = nav_info.atom; | |
| 981 | 934 | const atom = wasm_file.getAtomPtr(atom_index); |
| 982 | 935 | zig_object.symbols_free_list.append(gpa, atom.sym_index) catch {}; |
| 983 | for (decl_info.exports.items) |exp_sym_index| { | |
| 936 | for (nav_info.exports.items) |exp_sym_index| { | |
| 984 | 937 | const exp_sym = zig_object.symbol(exp_sym_index); |
| 985 | 938 | exp_sym.tag = .dead; |
| 986 | 939 | zig_object.symbols_free_list.append(exp_sym_index) catch {}; |
| 987 | 940 | } |
| 988 | decl_info.exports.deinit(gpa); | |
| 989 | std.debug.assert(zig_object.decls_map.remove(decl_index)); | |
| 941 | nav_info.exports.deinit(gpa); | |
| 942 | std.debug.assert(zig_object.navs.remove(nav_index)); | |
| 990 | 943 | const sym = &zig_object.symbols.items[atom.sym_index]; |
| 991 | 944 | for (atom.locals.items) |local_atom_index| { |
| 992 | 945 | const local_atom = wasm_file.getAtom(local_atom_index); |
| ... | ... | @@ -1000,7 +953,8 @@ pub fn freeDecl(zig_object: *ZigObject, wasm_file: *Wasm, decl_index: InternPool |
| 1000 | 953 | segment.name = &.{}; // Ensure no accidental double free |
| 1001 | 954 | } |
| 1002 | 955 | |
| 1003 | if (decl.isExtern(mod)) { | |
| 956 | const nav_val = mod.navValue(nav_index).toIntern(); | |
| 957 | if (ip.indexToKey(nav_val) == .@"extern") { | |
| 1004 | 958 | std.debug.assert(zig_object.imports.remove(atom.sym_index)); |
| 1005 | 959 | } |
| 1006 | 960 | std.debug.assert(wasm_file.symbol_atom.remove(atom.symbolLoc())); |
| ... | ... | @@ -1014,17 +968,14 @@ pub fn freeDecl(zig_object: *ZigObject, wasm_file: *Wasm, decl_index: InternPool |
| 1014 | 968 | if (sym.isGlobal()) { |
| 1015 | 969 | std.debug.assert(zig_object.global_syms.remove(atom.sym_index)); |
| 1016 | 970 | } |
| 1017 | switch (decl.typeOf(mod).zigTypeTag(mod)) { | |
| 1018 | .Fn => { | |
| 1019 | zig_object.functions_free_list.append(gpa, sym.index) catch {}; | |
| 1020 | std.debug.assert(zig_object.atom_types.remove(atom_index)); | |
| 1021 | }, | |
| 1022 | else => { | |
| 1023 | zig_object.segment_free_list.append(gpa, sym.index) catch {}; | |
| 1024 | const segment = &zig_object.segment_info.items[sym.index]; | |
| 1025 | gpa.free(segment.name); | |
| 1026 | segment.name = &.{}; // Prevent accidental double free | |
| 1027 | }, | |
| 971 | if (ip.isFunctionType(ip.typeOf(nav_val))) { | |
| 972 | zig_object.functions_free_list.append(gpa, sym.index) catch {}; | |
| 973 | std.debug.assert(zig_object.atom_types.remove(atom_index)); | |
| 974 | } else { | |
| 975 | zig_object.segment_free_list.append(gpa, sym.index) catch {}; | |
| 976 | const segment = &zig_object.segment_info.items[sym.index]; | |
| 977 | gpa.free(segment.name); | |
| 978 | segment.name = &.{}; // Prevent accidental double free | |
| 1028 | 979 | } |
| 1029 | 980 | } |
| 1030 | 981 | |
| ... | ... | @@ -1182,10 +1133,10 @@ fn allocateDebugAtoms(zig_object: *ZigObject) !void { |
| 1182 | 1133 | /// For the given `decl_index`, stores the corresponding type representing the function signature. |
| 1183 | 1134 | /// Asserts declaration has an associated `Atom`. |
| 1184 | 1135 | /// Returns the index into the list of types. |
| 1185 | pub fn storeDeclType(zig_object: *ZigObject, gpa: std.mem.Allocator, decl_index: InternPool.DeclIndex, func_type: std.wasm.Type) !u32 { | |
| 1186 | const decl_info = zig_object.decls_map.get(decl_index).?; | |
| 1136 | pub fn storeDeclType(zig_object: *ZigObject, gpa: std.mem.Allocator, nav_index: InternPool.Nav.Index, func_type: std.wasm.Type) !u32 { | |
| 1137 | const nav_info = zig_object.navs.get(nav_index).?; | |
| 1187 | 1138 | const index = try zig_object.putOrGetFuncType(gpa, func_type); |
| 1188 | try zig_object.atom_types.put(gpa, decl_info.atom, index); | |
| 1139 | try zig_object.atom_types.put(gpa, nav_info.atom, index); | |
| 1189 | 1140 | return index; |
| 1190 | 1141 | } |
| 1191 | 1142 |
src/print_air.zig+1-1| ... | ... | @@ -675,7 +675,7 @@ const Writer = struct { |
| 675 | 675 | } |
| 676 | 676 | } |
| 677 | 677 | const asm_source = std.mem.sliceAsBytes(w.air.extra[extra_i..])[0..extra.data.source_len]; |
| 678 | try s.print(", \"{s}\"", .{asm_source}); | |
| 678 | try s.print(", \"{}\"", .{std.zig.fmtEscapes(asm_source)}); | |
| 679 | 679 | } |
| 680 | 680 | |
| 681 | 681 | fn writeDbgStmt(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { |
src/print_value.zig+14-18| ... | ... | @@ -90,12 +90,8 @@ pub fn print( |
| 90 | 90 | else => try writer.writeAll(@tagName(simple_value)), |
| 91 | 91 | }, |
| 92 | 92 | .variable => try writer.writeAll("(variable)"), |
| 93 | .extern_func => |extern_func| try writer.print("(extern function '{}')", .{ | |
| 94 | mod.declPtr(extern_func.decl).name.fmt(ip), | |
| 95 | }), | |
| 96 | .func => |func| try writer.print("(function '{}')", .{ | |
| 97 | mod.declPtr(func.owner_decl).name.fmt(ip), | |
| 98 | }), | |
| 93 | .@"extern" => |e| try writer.print("(extern '{}')", .{e.name.fmt(ip)}), | |
| 94 | .func => |func| try writer.print("(function '{}')", .{ip.getNav(func.owner_nav).name.fmt(ip)}), | |
| 99 | 95 | .int => |int| switch (int.storage) { |
| 100 | 96 | inline .u64, .i64, .big_int => |x| try writer.print("{}", .{x}), |
| 101 | 97 | .lazy_align => |ty| if (have_sema) { |
| ... | ... | @@ -138,8 +134,8 @@ pub fn print( |
| 138 | 134 | .slice => |slice| { |
| 139 | 135 | const print_contents = switch (ip.getBackingAddrTag(slice.ptr).?) { |
| 140 | 136 | .field, .arr_elem, .eu_payload, .opt_payload => unreachable, |
| 141 | .anon_decl, .comptime_alloc, .comptime_field => true, | |
| 142 | .decl, .int => false, | |
| 137 | .uav, .comptime_alloc, .comptime_field => true, | |
| 138 | .nav, .int => false, | |
| 143 | 139 | }; |
| 144 | 140 | if (print_contents) { |
| 145 | 141 | // TODO: eventually we want to load the slice as an array with `sema`, but that's |
| ... | ... | @@ -157,8 +153,8 @@ pub fn print( |
| 157 | 153 | .ptr => { |
| 158 | 154 | const print_contents = switch (ip.getBackingAddrTag(val.toIntern()).?) { |
| 159 | 155 | .field, .arr_elem, .eu_payload, .opt_payload => unreachable, |
| 160 | .anon_decl, .comptime_alloc, .comptime_field => true, | |
| 161 | .decl, .int => false, | |
| 156 | .uav, .comptime_alloc, .comptime_field => true, | |
| 157 | .nav, .int => false, | |
| 162 | 158 | }; |
| 163 | 159 | if (print_contents) { |
| 164 | 160 | // TODO: eventually we want to load the pointer with `sema`, but that's |
| ... | ... | @@ -294,11 +290,11 @@ fn printPtr( |
| 294 | 290 | else => unreachable, |
| 295 | 291 | }; |
| 296 | 292 | |
| 297 | if (ptr.base_addr == .anon_decl) { | |
| 293 | if (ptr.base_addr == .uav) { | |
| 298 | 294 | // If the value is an aggregate, we can potentially print it more nicely. |
| 299 | switch (pt.zcu.intern_pool.indexToKey(ptr.base_addr.anon_decl.val)) { | |
| 295 | switch (pt.zcu.intern_pool.indexToKey(ptr.base_addr.uav.val)) { | |
| 300 | 296 | .aggregate => |agg| return printAggregate( |
| 301 | Value.fromInterned(ptr.base_addr.anon_decl.val), | |
| 297 | Value.fromInterned(ptr.base_addr.uav.val), | |
| 302 | 298 | agg, |
| 303 | 299 | true, |
| 304 | 300 | writer, |
| ... | ... | @@ -333,13 +329,13 @@ fn printPtrDerivation( |
| 333 | 329 | int.ptr_ty.fmt(pt), |
| 334 | 330 | int.addr, |
| 335 | 331 | }), |
| 336 | .decl_ptr => |decl_index| { | |
| 337 | try writer.print("{}", .{zcu.declPtr(decl_index).fqn.fmt(ip)}); | |
| 332 | .nav_ptr => |nav| { | |
| 333 | try writer.print("{}", .{ip.getNav(nav).fqn.fmt(ip)}); | |
| 338 | 334 | }, |
| 339 | .anon_decl_ptr => |anon| { | |
| 340 | const ty = Value.fromInterned(anon.val).typeOf(zcu); | |
| 335 | .uav_ptr => |uav| { | |
| 336 | const ty = Value.fromInterned(uav.val).typeOf(zcu); | |
| 341 | 337 | try writer.print("@as({}, ", .{ty.fmt(pt)}); |
| 342 | try print(Value.fromInterned(anon.val), writer, level - 1, pt, have_sema, sema); | |
| 338 | try print(Value.fromInterned(uav.val), writer, level - 1, pt, have_sema, sema); | |
| 343 | 339 | try writer.writeByte(')'); |
| 344 | 340 | }, |
| 345 | 341 | .comptime_alloc_ptr => |info| { |
test/behavior/type_info.zig+3-3| ... | ... | @@ -605,9 +605,9 @@ test "@typeInfo decls and usingnamespace" { |
| 605 | 605 | }; |
| 606 | 606 | const decls = @typeInfo(B).Struct.decls; |
| 607 | 607 | try expect(decls.len == 3); |
| 608 | try expectEqualStrings(decls[0].name, "x"); | |
| 609 | try expectEqualStrings(decls[1].name, "y"); | |
| 610 | try expectEqualStrings(decls[2].name, "z"); | |
| 608 | try expectEqualStrings(decls[0].name, "z"); | |
| 609 | try expectEqualStrings(decls[1].name, "x"); | |
| 610 | try expectEqualStrings(decls[2].name, "y"); | |
| 611 | 611 | } |
| 612 | 612 | |
| 613 | 613 | test "@typeInfo decls ignore dependency loops" { |
test/behavior/usingnamespace.zig-4| ... | ... | @@ -90,10 +90,6 @@ test { |
| 90 | 90 | try expect(a.x == AA.c().expected); |
| 91 | 91 | } |
| 92 | 92 | |
| 93 | comptime { | |
| 94 | _ = @import("usingnamespace/file_1.zig"); | |
| 95 | } | |
| 96 | ||
| 97 | 93 | const Bar = struct { |
| 98 | 94 | usingnamespace Mixin; |
| 99 | 95 | }; |
test/behavior/usingnamespace/file_0.zig deleted-1| ... | ... | @@ -1 +0,0 @@ |
| 1 | pub const A = 123; |
test/behavior/usingnamespace/file_1.zig deleted-12| ... | ... | @@ -1,12 +0,0 @@ |
| 1 | const std = @import("std"); | |
| 2 | const expect = std.testing.expect; | |
| 3 | const imports = @import("imports.zig"); | |
| 4 | const builtin = @import("builtin"); | |
| 5 | ||
| 6 | const A = 456; | |
| 7 | ||
| 8 | test { | |
| 9 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | |
| 10 | ||
| 11 | try expect(imports.A == 123); | |
| 12 | } |
test/behavior/usingnamespace/imports.zig deleted-5| ... | ... | @@ -1,5 +0,0 @@ |
| 1 | const file_0 = @import("file_0.zig"); | |
| 2 | const file_1 = @import("file_1.zig"); | |
| 3 | ||
| 4 | pub usingnamespace file_0; | |
| 5 | pub usingnamespace file_1; |
test/cases/compile_errors/setAlignStack_in_inline_function.zig deleted-22| ... | ... | @@ -1,22 +0,0 @@ |
| 1 | export fn entry() void { | |
| 2 | foo(); | |
| 3 | } | |
| 4 | inline fn foo() void { | |
| 5 | @setAlignStack(16); | |
| 6 | } | |
| 7 | ||
| 8 | export fn entry1() void { | |
| 9 | comptime bar(); | |
| 10 | } | |
| 11 | fn bar() void { | |
| 12 | @setAlignStack(16); | |
| 13 | } | |
| 14 | ||
| 15 | // error | |
| 16 | // backend=stage2 | |
| 17 | // target=native | |
| 18 | // | |
| 19 | // :5:5: error: @setAlignStack in inline function | |
| 20 | // :2:8: note: called from here | |
| 21 | // :12:5: error: @setAlignStack in inline call | |
| 22 | // :9:17: note: called from here |
test/cases/compile_errors/setAlignStack_set_twice.zig deleted-11| ... | ... | @@ -1,11 +0,0 @@ |
| 1 | export fn entry() void { | |
| 2 | @setAlignStack(16); | |
| 3 | @setAlignStack(16); | |
| 4 | } | |
| 5 | ||
| 6 | // error | |
| 7 | // backend=stage2 | |
| 8 | // target=native | |
| 9 | // | |
| 10 | // :3:5: error: multiple @setAlignStack in the same function body | |
| 11 | // :2:5: note: other instance here |
test/cases/compile_errors/tagName_on_invalid_value_of_non-exhaustive_enum.zig+1-1| ... | ... | @@ -8,5 +8,5 @@ test "enum" { |
| 8 | 8 | // target=native |
| 9 | 9 | // is_test=true |
| 10 | 10 | // |
| 11 | // :3:9: error: no field with value '@enumFromInt(5)' in enum 'test.enum.E' | |
| 11 | // :3:9: error: no field with value '@enumFromInt(5)' in enum 'tmp.test.enum.E' | |
| 12 | 12 | // :2:15: note: declared here |