authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-04-27 18:36:12-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-04-28 16:57:01-07:00
logf86469bc5eea2b7bd95222d00a11bd287bfdfedf
treec34ef71820e4c7b962a631f2b9cdecdff3f5aa79
parentfa6bb4b662155e4d6a61cc551b5d02a2a7d5d144

stage2: semaDecl properly analyzes the decl block

Also flattened out Decl TypedValue fields into ty, val, has_tv and add relevant fields to Decl for alignment and link section.

16 files changed, 388 insertions(+), 298 deletions(-)

BRANCH_TODO+81-33
......@@ -1,5 +1,11 @@
1 * namespace decls table can't reference ZIR memory because it can get modified on updates
2 - change it for astgen worker to compare old and new ZIR, updating existing
3 namespaces & decls, and creating a changelist.
14 * reimplement semaDecl
25 * use a hash map for instructions because the array is too big
6 - no, actually modify the Zir.Inst.Ref strategy so that each decl gets
7 their indexes starting at 0 so that we can use an array to store Sema
8 results rather than a map.
39
410 * keep track of file dependencies/dependants
511 * unload files from memory when a dependency is dropped
......@@ -101,39 +107,6 @@ fn astgenAndSemaDecl(mod: *Module, decl: *Decl) !bool {
101107 .aligned_var_decl => return mod.astgenAndSemaVarDecl(decl, tree.*, tree.alignedVarDecl(decl_node)),
102108
103109 .@"comptime" => {
104 decl.analysis = .in_progress;
105
106 // A comptime decl does not store any value so we can just deinit this arena after analysis is done.
107 var analysis_arena = std.heap.ArenaAllocator.init(mod.gpa);
108 defer analysis_arena.deinit();
109
110 var sema: Sema = .{
111 .mod = mod,
112 .gpa = mod.gpa,
113 .arena = &analysis_arena.allocator,
114 .code = code,
115 .inst_map = try analysis_arena.allocator.alloc(*ir.Inst, code.instructions.len),
116 .owner_decl = decl,
117 .namespace = decl.namespace,
118 .func = null,
119 .owner_func = null,
120 .param_inst_list = &.{},
121 };
122 var block_scope: Scope.Block = .{
123 .parent = null,
124 .sema = &sema,
125 .src_decl = decl,
126 .instructions = .{},
127 .inlining = null,
128 .is_comptime = true,
129 };
130 defer block_scope.instructions.deinit(mod.gpa);
131
132 _ = try sema.root(&block_scope);
133
134 decl.analysis = .complete;
135 decl.generation = mod.generation;
136 return true;
137110 },
138111 .@"usingnamespace" => {
139112 decl.analysis = .in_progress;
......@@ -424,3 +397,78 @@ pub fn analyzeNamespace(
424397 };
425398}
426399
400 if (align_inst != .none) {
401 return mod.fail(&namespace.base, .{ .node_abs = decl_node }, "TODO: implement decls with align()", .{});
402 }
403 if (section_inst != .none) {
404 return mod.fail(&namespace.base, .{ .node_abs = decl_node }, "TODO: implement decls with linksection()", .{});
405 }
406
407
408/// Trailing:
409/// 0. `EmitH` if `module.emit_h != null`.
410/// 1. A per-Decl link object. Represents the position of the code in the output file.
411/// This is populated regardless of semantic analysis and code generation.
412/// Depending on the target, will be one of:
413/// * Elf.TextBlock
414/// * Coff.TextBlock
415/// * MachO.TextBlock
416/// * C.DeclBlock
417/// * Wasm.DeclBlock
418/// * void
419/// 2. If it is a function, a per-Decl link function object. Represents the
420/// function in the linked output file, if the `Decl` is a function.
421/// This is stored here and not in `Fn` because `Decl` survives across updates but
422/// `Fn` does not. Depending on the target, will be one of:
423/// * Elf.SrcFn
424/// * Coff.SrcFn
425/// * MachO.SrcFn
426/// * C.FnBlock
427/// * Wasm.FnData
428/// * SpirV.FnData
429 /// This name is relative to the containing namespace of the decl.
430 /// The memory is owned by the containing File ZIR.
431 pub fn getName(decl: Decl) ?[:0]const u8 {
432 const zir = decl.namespace.file_scope.zir;
433 const name_index = zir.extra[decl.zir_decl_index + 4];
434 if (name_index <= 1) return null;
435 return zir.nullTerminatedString(name_index);
436 }
437
438
439 extra_index += @boolToInt(has_align);
440 extra_index += @boolToInt(has_section);
441
442 /// Contains un-analyzed ZIR instructions generated from Zig source AST.
443 /// Even after we finish analysis, the ZIR is kept in memory, so that
444 /// comptime and inline function calls can happen.
445 /// Parameter names are stored here so that they may be referenced for debug info,
446 /// without having source code bytes loaded into memory.
447 /// The number of parameters is determined by referring to the type.
448 /// The first N elements of `extra` are indexes into `string_bytes` to
449 /// a null-terminated string.
450 /// This memory is managed with gpa, must be freed when the function is freed.
451 zir: Zir,
452
453pub fn root(sema: *Sema, root_block: *Scope.Block) !Zir.Inst.Index {
454 const inst_data = sema.code.instructions.items(.data)[0].pl_node;
455 const extra = sema.code.extraData(Zir.Inst.Block, inst_data.payload_index);
456 const root_body = sema.code.extra[extra.end..][0..extra.data.body_len];
457 return sema.analyzeBody(root_block, root_body);
458}
459
460pub fn rootAsRef(sema: *Sema, root_block: *Scope.Block) !Zir.Inst.Ref {
461 const break_inst = try sema.root(root_block);
462 return sema.code.instructions.items(.data)[break_inst].@"break".operand;
463}
464
465/// Assumes that `root_block` ends with `break_inline`.
466pub fn rootAsType(sema: *Sema, root_block: *Scope.Block) !Type {
467 assert(root_block.is_comptime);
468 const zir_inst_ref = try sema.rootAsRef(root_block);
469 // Source location is unneeded because resolveConstValue must have already
470 // been successfully called when coercing the value to a type, from the
471 // result location.
472 return sema.resolveType(root_block, .unneeded, zir_inst_ref);
473}
474
src/Compilation.zig+6-6
......@@ -1890,7 +1890,8 @@ pub fn performAllTheWork(self: *Compilation) error{ TimerUnsupported, OutOfMemor
18901890 if (build_options.omit_stage2)
18911891 @panic("sadly stage2 is omitted from this build to save memory on the CI server");
18921892 const module = self.bin_file.options.module.?;
1893 if (decl.typed_value.most_recent.typed_value.val.castTag(.function)) |payload| {
1893 assert(decl.has_tv);
1894 if (decl.val.castTag(.function)) |payload| {
18941895 const func = payload.data;
18951896 switch (func.state) {
18961897 .queued => module.analyzeFnBody(decl, func) catch |err| switch (err) {
......@@ -1907,8 +1908,8 @@ pub fn performAllTheWork(self: *Compilation) error{ TimerUnsupported, OutOfMemor
19071908 }
19081909 // Here we tack on additional allocations to the Decl's arena. The allocations
19091910 // are lifetime annotations in the ZIR.
1910 var decl_arena = decl.typed_value.most_recent.arena.?.promote(module.gpa);
1911 defer decl.typed_value.most_recent.arena.?.* = decl_arena.state;
1911 var decl_arena = decl.value_arena.?.promote(module.gpa);
1912 defer decl.value_arena.?.* = decl_arena.state;
19121913 log.debug("analyze liveness of {s}", .{decl.name});
19131914 try liveness.analyze(module.gpa, &decl_arena.allocator, func.body);
19141915
......@@ -1918,9 +1919,9 @@ pub fn performAllTheWork(self: *Compilation) error{ TimerUnsupported, OutOfMemor
19181919 }
19191920
19201921 log.debug("calling updateDecl on '{s}', type={}", .{
1921 decl.name, decl.typed_value.most_recent.typed_value.ty,
1922 decl.name, decl.ty,
19221923 });
1923 assert(decl.typed_value.most_recent.typed_value.ty.hasCodeGenBits());
1924 assert(decl.ty.hasCodeGenBits());
19241925
19251926 self.bin_file.updateDecl(module, decl) catch |err| switch (err) {
19261927 error.OutOfMemory => return error.OutOfMemory,
......@@ -1960,7 +1961,6 @@ pub fn performAllTheWork(self: *Compilation) error{ TimerUnsupported, OutOfMemor
19601961 const module = self.bin_file.options.module.?;
19611962 const emit_h = module.emit_h.?;
19621963 _ = try emit_h.decl_table.getOrPut(module.gpa, decl);
1963 const tv = decl.typed_value.most_recent.typed_value;
19641964 const decl_emit_h = decl.getEmitH(module);
19651965 const fwd_decl = &decl_emit_h.fwd_decl;
19661966 fwd_decl.shrinkRetainingCapacity(0);
src/Module.zig+190-135
......@@ -154,17 +154,29 @@ pub const DeclPlusEmitH = struct {
154154};
155155
156156pub const Decl = struct {
157 /// This name is relative to the containing namespace of the decl. It uses
158 /// null-termination to save bytes, since there can be a lot of decls in a
159 /// compilation. The null byte is not allowed in symbol names, because
160 /// executable file formats use null-terminated strings for symbol names.
157 /// This name is relative to the containing namespace of the decl.
161158 /// All Decls have names, even values that are not bound to a zig namespace.
162159 /// This is necessary for mapping them to an address in the output file.
163 /// Memory owned by this decl, using Module's allocator.
160 /// Memory is owned by this decl, using Module's allocator.
161 /// Note that this cannot be changed to reference ZIR memory because when
162 /// ZIR updates, it would change the Decl name, but we still need the previous
163 /// name to delete the Decl from the hash maps it has been inserted into.
164164 name: [*:0]const u8,
165 /// The most recent Type of the Decl after a successful semantic analysis.
166 /// Populated when `has_tv`.
167 ty: Type,
168 /// The most recent Value of the Decl after a successful semantic analysis.
169 /// Populated when `has_tv`.
170 val: Value,
171 /// Populated when `has_tv`.
172 align_val: Value,
173 /// Populated when `has_tv`.
174 linksection_val: Value,
175 /// The memory for ty, val, align_val, linksection_val.
176 /// If this is `null` then there is no memory management needed.
177 value_arena: ?*std.heap.ArenaAllocator.State = null,
165178 /// The direct parent namespace of the Decl.
166179 /// Reference to externally owned memory.
167 /// This is `null` for the Decl that represents a `File`.
168180 namespace: *Scope.Namespace,
169181
170182 /// An integer that can be checked against the corresponding incrementing
......@@ -174,12 +186,11 @@ pub const Decl = struct {
174186 /// The AST node index of this declaration.
175187 /// Must be recomputed when the corresponding source file is modified.
176188 src_node: ast.Node.Index,
189 /// Index to ZIR `extra` array to the block of ZIR code that encodes the Decl expression.
190 zir_block_index: Zir.Inst.Index,
191 zir_align_ref: Zir.Inst.Ref = .none,
192 zir_linksection_ref: Zir.Inst.Ref = .none,
177193
178 /// The most recent value of the Decl after a successful semantic analysis.
179 typed_value: union(enum) {
180 never_succeeded: void,
181 most_recent: TypedValue.Managed,
182 },
183194 /// Represents the "shallow" analysis status. For example, for decls that are functions,
184195 /// the function type is analyzed with this set to `in_progress`, however, the semantic
185196 /// analysis of the function body is performed with this value set to `success`. Functions
......@@ -214,11 +225,15 @@ pub const Decl = struct {
214225 /// to require re-analysis.
215226 outdated,
216227 },
228 /// Whether `typed_value`, `align_val`, and `linksection_val` are populated.
229 has_tv: bool,
217230 /// This flag is set when this Decl is added to `Module.deletion_set`, and cleared
218231 /// when removed.
219232 deletion_flag: bool,
220233 /// Whether the corresponding AST decl has a `pub` keyword.
221234 is_pub: bool,
235 /// Whether the corresponding AST decl has a `export` keyword.
236 is_exported: bool,
222237
223238 /// Represents the position of the code in the output file.
224239 /// This is populated regardless of semantic analysis and code generation.
......@@ -231,6 +246,9 @@ pub const Decl = struct {
231246 /// to save on memory usage.
232247 fn_link: link.File.LinkFn,
233248
249 /// This is stored separately in addition to being available via `zir_decl_index`
250 /// because when the underlying ZIR code is updated, this field is used to find
251 /// out if anything changed.
234252 contents_hash: std.zig.SrcHash,
235253
236254 /// The shallow set of other decls whose typed_value could possibly change if this Decl's
......@@ -247,12 +265,12 @@ pub const Decl = struct {
247265 pub fn destroy(decl: *Decl, module: *Module) void {
248266 const gpa = module.gpa;
249267 gpa.free(mem.spanZ(decl.name));
250 if (decl.typedValueManaged()) |tvm| {
251 if (tvm.typed_value.val.castTag(.function)) |payload| {
268 if (decl.has_tv) {
269 if (decl.val.castTag(.function)) |payload| {
252270 const func = payload.data;
253271 func.deinit(gpa);
254272 }
255 tvm.deinit(gpa);
273 if (decl.value_arena) |a| a.promote(gpa).deinit();
256274 }
257275 decl.dependants.deinit(gpa);
258276 decl.dependencies.deinit(gpa);
......@@ -311,9 +329,12 @@ pub const Decl = struct {
311329 return buffer.toOwnedSlice();
312330 }
313331
314 pub fn typedValue(decl: *Decl) error{AnalysisFail}!TypedValue {
315 const tvm = decl.typedValueManaged() orelse return error.AnalysisFail;
316 return tvm.typed_value;
332 pub fn typedValue(decl: Decl) error{AnalysisFail}!TypedValue {
333 if (!decl.has_tv) return error.AnalysisFail;
334 return TypedValue{
335 .ty = decl.ty,
336 .val = decl.val,
337 };
317338 }
318339
319340 pub fn value(decl: *Decl) error{AnalysisFail}!Value {
......@@ -334,19 +355,12 @@ pub const Decl = struct {
334355 mem.spanZ(decl.name),
335356 @tagName(decl.analysis),
336357 });
337 if (decl.typedValueManaged()) |tvm| {
338 std.debug.print(" ty={} val={}", .{ tvm.typed_value.ty, tvm.typed_value.val });
358 if (decl.has_tv) {
359 std.debug.print(" ty={} val={}", .{ decl.ty, decl.val });
339360 }
340361 std.debug.print("\n", .{});
341362 }
342363
343 pub fn typedValueManaged(decl: *Decl) ?*TypedValue.Managed {
344 switch (decl.typed_value) {
345 .most_recent => |*x| return x,
346 .never_succeeded => return null,
347 }
348 }
349
350364 pub fn getFileScope(decl: Decl) *Scope.File {
351365 return decl.namespace.file_scope;
352366 }
......@@ -475,16 +489,6 @@ pub const EnumFull = struct {
475489/// the `Decl` only, with a `Value` tag of `extern_fn`.
476490pub const Fn = struct {
477491 owner_decl: *Decl,
478 /// Contains un-analyzed ZIR instructions generated from Zig source AST.
479 /// Even after we finish analysis, the ZIR is kept in memory, so that
480 /// comptime and inline function calls can happen.
481 /// Parameter names are stored here so that they may be referenced for debug info,
482 /// without having source code bytes loaded into memory.
483 /// The number of parameters is determined by referring to the type.
484 /// The first N elements of `extra` are indexes into `string_bytes` to
485 /// a null-terminated string.
486 /// This memory is managed with gpa, must be freed when the function is freed.
487 zir: Zir,
488492 /// undefined unless analysis state is `success`.
489493 body: ir.Body,
490494 state: Analysis,
......@@ -508,9 +512,7 @@ pub const Fn = struct {
508512 ir.dumpFn(mod, func);
509513 }
510514
511 pub fn deinit(func: *Fn, gpa: *Allocator) void {
512 func.zir.deinit(gpa);
513 }
515 pub fn deinit(func: *Fn, gpa: *Allocator) void {}
514516};
515517
516518pub const Var = struct {
......@@ -3111,7 +3113,7 @@ pub fn ensureDeclAnalyzed(mod: *Module, decl: *Decl) InnerError!void {
31113113 if (subsequent_analysis) {
31123114 // We may need to chase the dependants and re-analyze them.
31133115 // However, if the decl is a function, and the type is the same, we do not need to.
3114 if (type_changed or decl.typed_value.most_recent.typed_value.val.tag() != .function) {
3116 if (type_changed or decl.ty.zigTypeTag() != .Fn) {
31153117 for (decl.dependants.items()) |entry| {
31163118 const dep = entry.key;
31173119 switch (dep.analysis) {
......@@ -3162,13 +3164,20 @@ pub fn semaFile(mod: *Module, file: *Scope.File) InnerError!void {
31623164 .namespace = &tmp_namespace,
31633165 .generation = mod.generation,
31643166 .src_node = 0, // the root AST node for the file
3165 .typed_value = .never_succeeded,
31663167 .analysis = .in_progress,
31673168 .deletion_flag = false,
31683169 .is_pub = true,
3170 .is_exported = false,
31693171 .link = undefined, // don't try to codegen this
31703172 .fn_link = undefined, // not a function
31713173 .contents_hash = undefined, // top-level struct has no contents hash
3174 .zir_block_index = undefined,
3175
3176 .has_tv = false,
3177 .ty = undefined,
3178 .val = undefined,
3179 .align_val = undefined,
3180 .linksection_val = undefined,
31723181 };
31733182 defer top_decl.dependencies.deinit(gpa);
31743183
......@@ -3223,7 +3232,56 @@ fn semaDecl(mod: *Module, decl: *Decl) !bool {
32233232 const tracy = trace(@src());
32243233 defer tracy.end();
32253234
3226 @panic("TODO implement semaDecl");
3235 const gpa = mod.gpa;
3236
3237 decl.analysis = .in_progress;
3238
3239 var analysis_arena = std.heap.ArenaAllocator.init(gpa);
3240 defer analysis_arena.deinit();
3241
3242 const zir = decl.namespace.file_scope.zir;
3243
3244 var sema: Sema = .{
3245 .mod = mod,
3246 .gpa = gpa,
3247 .arena = &analysis_arena.allocator,
3248 .code = zir,
3249 .inst_map = try analysis_arena.allocator.alloc(*ir.Inst, zir.instructions.len),
3250 .owner_decl = decl,
3251 .namespace = decl.namespace,
3252 .func = null,
3253 .owner_func = null,
3254 .param_inst_list = &.{},
3255 };
3256 var block_scope: Scope.Block = .{
3257 .parent = null,
3258 .sema = &sema,
3259 .src_decl = decl,
3260 .instructions = .{},
3261 .inlining = null,
3262 .is_comptime = true,
3263 };
3264 defer block_scope.instructions.deinit(gpa);
3265
3266 const inst_data = zir.instructions.items(.data)[decl.zir_block_index].pl_node;
3267 const extra = zir.extraData(Zir.Inst.Block, inst_data.payload_index);
3268 const body = zir.extra[extra.end..][0..extra.data.body_len];
3269 const break_index = try sema.analyzeBody(&block_scope, body);
3270
3271 if (decl.zir_align_ref != .none) {
3272 @panic("TODO implement decl align");
3273 }
3274 if (decl.zir_linksection_ref != .none) {
3275 @panic("TODO implement decl linksection");
3276 }
3277
3278 decl.analysis = .complete;
3279 decl.generation = mod.generation;
3280
3281 // TODO inspect the type and return a proper type_changed result
3282 @breakpoint();
3283
3284 return true;
32273285}
32283286
32293287/// Returns the depender's index of the dependee.
......@@ -3489,6 +3547,7 @@ fn scanDecl(
34893547
34903548 const gpa = mod.gpa;
34913549 const zir = namespace.file_scope.zir;
3550
34923551 const decl_block_inst_data = zir.instructions.items(.data)[decl_index].pl_node;
34933552 const decl_node = parent_decl.relativeToNodeIndex(decl_block_inst_data.src_node);
34943553
......@@ -3504,13 +3563,9 @@ fn scanDecl(
35043563 const decl_key = decl_name orelse &contents_hash;
35053564 const gop = try namespace.decls.getOrPut(gpa, decl_key);
35063565 if (!gop.found_existing) {
3507 if (align_inst != .none) {
3508 return mod.fail(&namespace.base, .{ .node_abs = decl_node }, "TODO: implement decls with align()", .{});
3509 }
3510 if (section_inst != .none) {
3511 return mod.fail(&namespace.base, .{ .node_abs = decl_node }, "TODO: implement decls with linksection()", .{});
3512 }
3513 const new_decl = try mod.createNewDecl(namespace, decl_key, decl_node, contents_hash);
3566 const new_decl = try mod.allocateNewDecl(namespace, decl_node);
3567 new_decl.contents_hash = contents_hash;
3568 new_decl.name = try gpa.dupeZ(u8, decl_key);
35143569 // Update the key reference to the longer-lived memory.
35153570 gop.entry.key = &new_decl.contents_hash;
35163571 gop.entry.value = new_decl;
......@@ -3524,7 +3579,11 @@ fn scanDecl(
35243579 if (want_analysis) {
35253580 mod.comp.work_queue.writeItemAssumeCapacity(.{ .analyze_decl = new_decl });
35263581 }
3582 new_decl.is_exported = is_exported;
35273583 new_decl.is_pub = is_pub;
3584 new_decl.zir_block_index = decl_index;
3585 new_decl.zir_align_ref = align_inst;
3586 new_decl.zir_linksection_ref = section_inst;
35283587 return;
35293588 }
35303589 const decl = gop.entry.value;
......@@ -3532,6 +3591,11 @@ fn scanDecl(
35323591 // have been re-ordered.
35333592 const prev_src_node = decl.src_node;
35343593 decl.src_node = decl_node;
3594 decl.is_pub = is_pub;
3595 decl.is_exported = is_exported;
3596 decl.zir_block_index = decl_index;
3597 decl.zir_align_ref = align_inst;
3598 decl.zir_linksection_ref = section_inst;
35353599 if (deleted_decls.swapRemove(decl) == null) {
35363600 if (true) {
35373601 @panic("TODO I think this code path is unreachable; should be caught by AstGen.");
......@@ -3681,64 +3745,70 @@ pub fn analyzeFnBody(mod: *Module, decl: *Decl, func: *Fn) !void {
36813745 defer tracy.end();
36823746
36833747 // Use the Decl's arena for function memory.
3684 var arena = decl.typed_value.most_recent.arena.?.promote(mod.gpa);
3685 defer decl.typed_value.most_recent.arena.?.* = arena.state;
3748 var arena = decl.value_arena.?.promote(mod.gpa);
3749 defer decl.value_arena.?.* = arena.state;
36863750
3687 const fn_ty = decl.typed_value.most_recent.typed_value.ty;
3751 const fn_ty = decl.ty;
36883752 const param_inst_list = try mod.gpa.alloc(*ir.Inst, fn_ty.fnParamLen());
36893753 defer mod.gpa.free(param_inst_list);
36903754
3691 for (param_inst_list) |*param_inst, param_index| {
3692 const param_type = fn_ty.fnParamType(param_index);
3693 const name = func.zir.nullTerminatedString(func.zir.extra[param_index]);
3694 const arg_inst = try arena.allocator.create(ir.Inst.Arg);
3695 arg_inst.* = .{
3696 .base = .{
3697 .tag = .arg,
3698 .ty = param_type,
3699 .src = .unneeded,
3700 },
3701 .name = name,
3702 };
3703 param_inst.* = &arg_inst.base;
3755 var f = false;
3756 if (f) {
3757 return error.AnalysisFail;
37043758 }
3759 @panic("TODO reimplement analyzeFnBody now that ZIR is whole-file");
3760
3761 //for (param_inst_list) |*param_inst, param_index| {
3762 // const param_type = fn_ty.fnParamType(param_index);
3763 // const name = func.zir.nullTerminatedString(func.zir.extra[param_index]);
3764 // const arg_inst = try arena.allocator.create(ir.Inst.Arg);
3765 // arg_inst.* = .{
3766 // .base = .{
3767 // .tag = .arg,
3768 // .ty = param_type,
3769 // .src = .unneeded,
3770 // },
3771 // .name = name,
3772 // };
3773 // param_inst.* = &arg_inst.base;
3774 //}
37053775
3706 var sema: Sema = .{
3707 .mod = mod,
3708 .gpa = mod.gpa,
3709 .arena = &arena.allocator,
3710 .code = func.zir,
3711 .inst_map = try mod.gpa.alloc(*ir.Inst, func.zir.instructions.len),
3712 .owner_decl = decl,
3713 .namespace = decl.namespace,
3714 .func = func,
3715 .owner_func = func,
3716 .param_inst_list = param_inst_list,
3717 };
3718 defer mod.gpa.free(sema.inst_map);
3719
3720 var inner_block: Scope.Block = .{
3721 .parent = null,
3722 .sema = &sema,
3723 .src_decl = decl,
3724 .instructions = .{},
3725 .inlining = null,
3726 .is_comptime = false,
3727 };
3728 defer inner_block.instructions.deinit(mod.gpa);
3729
3730 // AIR currently requires the arg parameters to be the first N instructions
3731 try inner_block.instructions.appendSlice(mod.gpa, param_inst_list);
3732
3733 func.state = .in_progress;
3734 log.debug("set {s} to in_progress", .{decl.name});
3735
3736 _ = try sema.root(&inner_block);
3737
3738 const instructions = try arena.allocator.dupe(*ir.Inst, inner_block.instructions.items);
3739 func.state = .success;
3740 func.body = .{ .instructions = instructions };
3741 log.debug("set {s} to success", .{decl.name});
3776 //var sema: Sema = .{
3777 // .mod = mod,
3778 // .gpa = mod.gpa,
3779 // .arena = &arena.allocator,
3780 // .code = func.zir,
3781 // .inst_map = try mod.gpa.alloc(*ir.Inst, func.zir.instructions.len),
3782 // .owner_decl = decl,
3783 // .namespace = decl.namespace,
3784 // .func = func,
3785 // .owner_func = func,
3786 // .param_inst_list = param_inst_list,
3787 //};
3788 //defer mod.gpa.free(sema.inst_map);
3789
3790 //var inner_block: Scope.Block = .{
3791 // .parent = null,
3792 // .sema = &sema,
3793 // .src_decl = decl,
3794 // .instructions = .{},
3795 // .inlining = null,
3796 // .is_comptime = false,
3797 //};
3798 //defer inner_block.instructions.deinit(mod.gpa);
3799
3800 //// AIR currently requires the arg parameters to be the first N instructions
3801 //try inner_block.instructions.appendSlice(mod.gpa, param_inst_list);
3802
3803 //func.state = .in_progress;
3804 //log.debug("set {s} to in_progress", .{decl.name});
3805
3806 //_ = try sema.root(&inner_block);
3807
3808 //const instructions = try arena.allocator.dupe(*ir.Inst, inner_block.instructions.items);
3809 //func.state = .success;
3810 //func.body = .{ .instructions = instructions };
3811 //log.debug("set {s} to success", .{decl.name});
37423812}
37433813
37443814fn markOutdatedDecl(mod: *Module, decl: *Decl) !void {
......@@ -3756,12 +3826,7 @@ fn markOutdatedDecl(mod: *Module, decl: *Decl) !void {
37563826 decl.analysis = .outdated;
37573827}
37583828
3759fn allocateNewDecl(
3760 mod: *Module,
3761 namespace: *Scope.Namespace,
3762 src_node: ast.Node.Index,
3763 contents_hash: std.zig.SrcHash,
3764) !*Decl {
3829fn allocateNewDecl(mod: *Module, namespace: *Scope.Namespace, src_node: ast.Node.Index) !*Decl {
37653830 // If we have emit-h then we must allocate a bigger structure to store the emit-h state.
37663831 const new_decl: *Decl = if (mod.emit_h != null) blk: {
37673832 const parent_struct = try mod.gpa.create(DeclPlusEmitH);
......@@ -3776,10 +3841,15 @@ fn allocateNewDecl(
37763841 .name = "",
37773842 .namespace = namespace,
37783843 .src_node = src_node,
3779 .typed_value = .{ .never_succeeded = {} },
3844 .has_tv = false,
3845 .ty = undefined,
3846 .val = undefined,
3847 .align_val = undefined,
3848 .linksection_val = undefined,
37803849 .analysis = .unreferenced,
37813850 .deletion_flag = false,
3782 .contents_hash = contents_hash,
3851 .contents_hash = undefined,
3852 .zir_block_index = undefined,
37833853 .link = switch (mod.comp.bin_file.tag) {
37843854 .coff => .{ .coff = link.File.Coff.TextBlock.empty },
37853855 .elf => .{ .elf = link.File.Elf.TextBlock.empty },
......@@ -3798,23 +3868,11 @@ fn allocateNewDecl(
37983868 },
37993869 .generation = 0,
38003870 .is_pub = false,
3871 .is_exported = false,
38013872 };
38023873 return new_decl;
38033874}
38043875
3805fn createNewDecl(
3806 mod: *Module,
3807 namespace: *Scope.Namespace,
3808 decl_name: []const u8,
3809 src_node: ast.Node.Index,
3810 contents_hash: std.zig.SrcHash,
3811) !*Decl {
3812 const new_decl = try mod.allocateNewDecl(namespace, src_node, contents_hash);
3813 errdefer mod.gpa.destroy(new_decl);
3814 new_decl.name = try mem.dupeZ(mod.gpa, u8, decl_name);
3815 return new_decl;
3816}
3817
38183876/// Get error value for error tag `name`.
38193877pub fn getErrorValue(mod: *Module, name: []const u8) !std.StringHashMapUnmanaged(ErrorInt).Entry {
38203878 const gop = try mod.global_error_set.getOrPut(mod.gpa, name);
......@@ -3837,10 +3895,9 @@ pub fn analyzeExport(
38373895 exported_decl: *Decl,
38383896) !void {
38393897 try mod.ensureDeclAnalyzed(exported_decl);
3840 const typed_value = exported_decl.typed_value.most_recent.typed_value;
3841 switch (typed_value.ty.zigTypeTag()) {
3898 switch (exported_decl.ty.zigTypeTag()) {
38423899 .Fn => {},
3843 else => return mod.fail(scope, src, "unable to export type '{}'", .{typed_value.ty}),
3900 else => return mod.fail(scope, src, "unable to export type '{}'", .{exported_decl.ty}),
38443901 }
38453902
38463903 try mod.decl_exports.ensureCapacity(mod.gpa, mod.decl_exports.items().len + 1);
......@@ -4017,20 +4074,18 @@ pub fn createAnonymousDecl(
40174074) !*Decl {
40184075 const name_index = mod.getNextAnonNameIndex();
40194076 const scope_decl = scope.ownerDecl().?;
4020 const name = try std.fmt.allocPrint(mod.gpa, "{s}__anon_{d}", .{ scope_decl.name, name_index });
4021 defer mod.gpa.free(name);
4077 const name = try std.fmt.allocPrintZ(mod.gpa, "{s}__anon_{d}", .{ scope_decl.name, name_index });
4078 errdefer mod.gpa.free(name);
40224079 const namespace = scope_decl.namespace;
4023 const src_hash: std.zig.SrcHash = undefined;
4024 const new_decl = try mod.createNewDecl(namespace, name, scope_decl.src_node, src_hash);
4080 const new_decl = try mod.allocateNewDecl(namespace, scope_decl.src_node);
4081 new_decl.name = name;
4082
40254083 const decl_arena_state = try decl_arena.allocator.create(std.heap.ArenaAllocator.State);
40264084
40274085 decl_arena_state.* = decl_arena.state;
4028 new_decl.typed_value = .{
4029 .most_recent = .{
4030 .typed_value = typed_value,
4031 .arena = decl_arena_state,
4032 },
4033 };
4086 new_decl.ty = typed_value.ty;
4087 new_decl.val = typed_value.val;
4088 new_decl.has_tv = true;
40344089 new_decl.analysis = .complete;
40354090 new_decl.generation = mod.generation;
40364091
src/Sema.zig+6-25
......@@ -64,28 +64,6 @@ const LazySrcLoc = Module.LazySrcLoc;
6464const RangeSet = @import("RangeSet.zig");
6565const AstGen = @import("AstGen.zig");
6666
67pub fn root(sema: *Sema, root_block: *Scope.Block) !Zir.Inst.Index {
68 const inst_data = sema.code.instructions.items(.data)[0].pl_node;
69 const extra = sema.code.extraData(Zir.Inst.Block, inst_data.payload_index);
70 const root_body = sema.code.extra[extra.end..][0..extra.data.body_len];
71 return sema.analyzeBody(root_block, root_body);
72}
73
74pub fn rootAsRef(sema: *Sema, root_block: *Scope.Block) !Zir.Inst.Ref {
75 const break_inst = try sema.root(root_block);
76 return sema.code.instructions.items(.data)[break_inst].@"break".operand;
77}
78
79/// Assumes that `root_block` ends with `break_inline`.
80pub fn rootAsType(sema: *Sema, root_block: *Scope.Block) !Type {
81 assert(root_block.is_comptime);
82 const zir_inst_ref = try sema.rootAsRef(root_block);
83 // Source location is unneeded because resolveConstValue must have already
84 // been successfully called when coercing the value to a type, from the
85 // result location.
86 return sema.resolveType(root_block, .unneeded, zir_inst_ref);
87}
88
8967/// Returns only the result from the body that is specified.
9068/// Only appropriate to call when it is determined at comptime that this body
9169/// has no peers.
......@@ -997,7 +975,7 @@ fn zirRetPtr(
997975
998976 const src: LazySrcLoc = .{ .node_offset = @bitCast(i32, extended.operand) };
999977 try sema.requireFunctionBlock(block, src);
1000 const fn_ty = sema.func.?.owner_decl.typed_value.most_recent.typed_value.ty;
978 const fn_ty = sema.func.?.owner_decl.ty;
1001979 const ret_type = fn_ty.fnReturnType();
1002980 const ptr_type = try sema.mod.simplePtrType(sema.arena, ret_type, true, .One);
1003981 return block.addNoOp(src, ptr_type, .alloc);
......@@ -1022,7 +1000,7 @@ fn zirRetType(
10221000
10231001 const src: LazySrcLoc = .{ .node_offset = @bitCast(i32, extended.operand) };
10241002 try sema.requireFunctionBlock(block, src);
1025 const fn_ty = sema.func.?.owner_decl.typed_value.most_recent.typed_value.ty;
1003 const fn_ty = sema.func.?.owner_decl.ty;
10261004 const ret_type = fn_ty.fnReturnType();
10271005 return sema.mod.constType(sema.arena, src, ret_type);
10281006}
......@@ -2022,6 +2000,9 @@ fn analyzeCall(
20222000 .block_inst = block_inst,
20232001 },
20242002 };
2003 if (true) {
2004 @panic("TODO reimplement inline fn call after whole-file astgen");
2005 }
20252006 var inline_sema: Sema = .{
20262007 .mod = sema.mod,
20272008 .gpa = sema.mod.gpa,
......@@ -4949,7 +4930,7 @@ fn analyzeRet(
49494930
49504931 if (need_coercion) {
49514932 if (sema.func) |func| {
4952 const fn_ty = func.owner_decl.typed_value.most_recent.typed_value.ty;
4933 const fn_ty = func.owner_decl.ty;
49534934 const fn_ret_ty = fn_ty.fnReturnType();
49544935 const casted_operand = try sema.coerce(block, fn_ret_ty, operand, src);
49554936 if (fn_ret_ty.zigTypeTag() == .Void)
src/codegen.zig+4-2
......@@ -400,7 +400,8 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
400400
401401 const module_fn = typed_value.val.castTag(.function).?.data;
402402
403 const fn_type = module_fn.owner_decl.typed_value.most_recent.typed_value.ty;
403 assert(module_fn.owner_decl.has_tv);
404 const fn_type = module_fn.owner_decl.ty;
404405
405406 var branch_stack = std.ArrayList(Branch).init(bin_file.allocator);
406407 defer {
......@@ -1925,7 +1926,8 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
19251926 else
19261927 unreachable;
19271928
1928 const return_type = func.owner_decl.typed_value.most_recent.typed_value.ty.fnReturnType();
1929 assert(func.owner_decl.has_tv);
1930 const return_type = func.owner_decl.ty.fnReturnType();
19291931 // First, push the return address, then jump; if noreturn, don't bother with the first step
19301932 // TODO: implement packed struct -> u16 at comptime and move the bitcast here
19311933 var instr = Instruction{ .condition = .always, .input0 = .immediate, .input1 = .zero, .modify_flags = false, .output = .jump, .command = .load16 };
src/codegen/c.zig+15-11
......@@ -190,8 +190,8 @@ pub const DeclGen = struct {
190190 const decl = val.castTag(.decl_ref).?.data;
191191
192192 // Determine if we must pointer cast.
193 const decl_tv = decl.typed_value.most_recent.typed_value;
194 if (t.eql(decl_tv.ty)) {
193 assert(decl.has_tv);
194 if (t.eql(decl.ty)) {
195195 try writer.print("&{s}", .{decl.name});
196196 } else {
197197 try writer.writeAll("(");
......@@ -326,12 +326,11 @@ pub const DeclGen = struct {
326326 if (!is_global) {
327327 try w.writeAll("static ");
328328 }
329 const tv = dg.decl.typed_value.most_recent.typed_value;
330 try dg.renderType(w, tv.ty.fnReturnType());
329 try dg.renderType(w, dg.decl.ty.fnReturnType());
331330 const decl_name = mem.span(dg.decl.name);
332331 try w.print(" {s}(", .{decl_name});
333 const param_len = tv.ty.fnParamLen();
334 const is_var_args = tv.ty.fnIsVarArgs();
332 const param_len = dg.decl.ty.fnParamLen();
333 const is_var_args = dg.decl.ty.fnIsVarArgs();
335334 if (param_len == 0 and !is_var_args)
336335 try w.writeAll("void")
337336 else {
......@@ -340,7 +339,7 @@ pub const DeclGen = struct {
340339 if (index > 0) {
341340 try w.writeAll(", ");
342341 }
343 try dg.renderType(w, tv.ty.fnParamType(index));
342 try dg.renderType(w, dg.decl.ty.fnParamType(index));
344343 try w.print(" a{d}", .{index});
345344 }
346345 }
......@@ -545,8 +544,10 @@ pub fn genDecl(o: *Object) !void {
545544 const tracy = trace(@src());
546545 defer tracy.end();
547546
548 const tv = o.dg.decl.typed_value.most_recent.typed_value;
549
547 const tv: TypedValue = .{
548 .ty = o.dg.decl.ty,
549 .val = o.dg.decl.val,
550 };
550551 if (tv.val.castTag(.function)) |func_payload| {
551552 const is_global = o.dg.functionIsGlobal(tv);
552553 const fwd_decl_writer = o.dg.fwd_decl.writer();
......@@ -589,7 +590,10 @@ pub fn genHeader(dg: *DeclGen) error{ AnalysisFail, OutOfMemory }!void {
589590 const tracy = trace(@src());
590591 defer tracy.end();
591592
592 const tv = dg.decl.typed_value.most_recent.typed_value;
593 const tv: TypedValue = .{
594 .ty = dg.decl.ty,
595 .val = dg.decl.val,
596 };
593597 const writer = dg.fwd_decl.writer();
594598
595599 switch (tv.ty.zigTypeTag()) {
......@@ -842,7 +846,7 @@ fn genCall(o: *Object, inst: *Inst.Call) !CValue {
842846 else
843847 unreachable;
844848
845 const fn_ty = fn_decl.typed_value.most_recent.typed_value.ty;
849 const fn_ty = fn_decl.ty;
846850 const ret_ty = fn_ty.fnReturnType();
847851 const unused_result = inst.base.isUnused();
848852 var result_local: CValue = .none;
src/codegen/llvm.zig+12-10
......@@ -325,17 +325,17 @@ pub const DeclGen = struct {
325325
326326 fn genDecl(self: *DeclGen) !void {
327327 const decl = self.decl;
328 const typed_value = decl.typed_value.most_recent.typed_value;
328 assert(decl.has_tv);
329329
330 log.debug("gen: {s} type: {}, value: {}", .{ decl.name, typed_value.ty, typed_value.val });
330 log.debug("gen: {s} type: {}, value: {}", .{ decl.name, decl.ty, decl.val });
331331
332 if (typed_value.val.castTag(.function)) |func_payload| {
332 if (decl.val.castTag(.function)) |func_payload| {
333333 const func = func_payload.data;
334334
335335 const llvm_func = try self.resolveLLVMFunction(func.owner_decl);
336336
337337 // This gets the LLVM values from the function and stores them in `self.args`.
338 const fn_param_len = func.owner_decl.typed_value.most_recent.typed_value.ty.fnParamLen();
338 const fn_param_len = func.owner_decl.ty.fnParamLen();
339339 var args = try self.gpa.alloc(*const llvm.Value, fn_param_len);
340340
341341 for (args) |*arg, i| {
......@@ -368,7 +368,7 @@ pub const DeclGen = struct {
368368 defer fg.deinit();
369369
370370 try fg.genBody(func.body);
371 } else if (typed_value.val.castTag(.extern_fn)) |extern_fn| {
371 } else if (decl.val.castTag(.extern_fn)) |extern_fn| {
372372 _ = try self.resolveLLVMFunction(extern_fn.data);
373373 } else {
374374 _ = try self.resolveGlobalDecl(decl);
......@@ -380,7 +380,8 @@ pub const DeclGen = struct {
380380 // TODO: do we want to store this in our own datastructure?
381381 if (self.llvmModule().getNamedFunction(func.name)) |llvm_fn| return llvm_fn;
382382
383 const zig_fn_type = func.typed_value.most_recent.typed_value.ty;
383 assert(func.has_tv);
384 const zig_fn_type = func.ty;
384385 const return_type = zig_fn_type.fnReturnType();
385386
386387 const fn_param_len = zig_fn_type.fnParamLen();
......@@ -415,11 +416,11 @@ pub const DeclGen = struct {
415416 // TODO: do we want to store this in our own datastructure?
416417 if (self.llvmModule().getNamedGlobal(decl.name)) |val| return val;
417418
418 const typed_value = decl.typed_value.most_recent.typed_value;
419 assert(decl.has_tv);
419420
420421 // TODO: remove this redundant `getLLVMType`, it is also called in `genTypedValue`.
421 const llvm_type = try self.getLLVMType(typed_value.ty);
422 const val = try self.genTypedValue(typed_value, null);
422 const llvm_type = try self.getLLVMType(decl.ty);
423 const val = try self.genTypedValue(.{ .ty = decl.ty, .val = decl.val }, null);
423424 const global = self.llvmModule().addGlobal(llvm_type, decl.name);
424425 llvm.setInitializer(global, val);
425426
......@@ -688,7 +689,8 @@ pub const FuncGen = struct {
688689 else
689690 unreachable;
690691
691 const zig_fn_type = fn_decl.typed_value.most_recent.typed_value.ty;
692 assert(fn_decl.has_tv);
693 const zig_fn_type = fn_decl.ty;
692694 const llvm_fn = try self.dg.resolveLLVMFunction(fn_decl);
693695
694696 const num_args = inst.args.len;
src/codegen/wasm.zig+2-1
......@@ -591,7 +591,8 @@ pub const Context = struct {
591591 }
592592
593593 fn genFunctype(self: *Context) InnerError!void {
594 const ty = self.decl.typed_value.most_recent.typed_value.ty;
594 assert(self.decl.has_tv);
595 const ty = self.decl.ty;
595596 const writer = self.func_type_data.writer();
596597
597598 try writer.writeByte(wasm.function_type);
src/link.zig+3
......@@ -300,6 +300,7 @@ pub const File = struct {
300300 /// May be called before or after updateDeclExports but must be called
301301 /// after allocateDeclIndexes for any given Decl.
302302 pub fn updateDecl(base: *File, module: *Module, decl: *Module.Decl) !void {
303 assert(decl.has_tv);
303304 switch (base.tag) {
304305 .coff => return @fieldParentPtr(Coff, "base", base).updateDecl(module, decl),
305306 .elf => return @fieldParentPtr(Elf, "base", base).updateDecl(module, decl),
......@@ -311,6 +312,7 @@ pub const File = struct {
311312 }
312313
313314 pub fn updateDeclLineNumber(base: *File, module: *Module, decl: *Module.Decl) !void {
315 assert(decl.has_tv);
314316 switch (base.tag) {
315317 .coff => return @fieldParentPtr(Coff, "base", base).updateDeclLineNumber(module, decl),
316318 .elf => return @fieldParentPtr(Elf, "base", base).updateDeclLineNumber(module, decl),
......@@ -461,6 +463,7 @@ pub const File = struct {
461463 decl: *Module.Decl,
462464 exports: []const *Module.Export,
463465 ) !void {
466 assert(decl.has_tv);
464467 switch (base.tag) {
465468 .coff => return @fieldParentPtr(Coff, "base", base).updateDeclExports(module, decl, exports),
466469 .elf => return @fieldParentPtr(Elf, "base", base).updateDeclExports(module, decl, exports),
src/link/C.zig+30-38
......@@ -206,34 +206,30 @@ pub fn flushModule(self: *C, comp: *Compilation) !void {
206206 // generate, rather than querying here, be faster?
207207 for (self.decl_table.items()) |kv| {
208208 const decl = kv.key;
209 switch (decl.typed_value) {
210 .most_recent => |tvm| {
211 const buf = buf: {
212 if (tvm.typed_value.val.castTag(.function)) |_| {
213 var it = decl.fn_link.c.typedefs.iterator();
214 while (it.next()) |new| {
215 if (typedefs.get(new.key)) |previous| {
216 try err_typedef_writer.print("typedef {s} {s};\n", .{ previous, new.value.name });
217 } else {
218 try typedefs.ensureCapacity(typedefs.capacity() + 1);
219 try err_typedef_writer.writeAll(new.value.rendered);
220 typedefs.putAssumeCapacityNoClobber(new.key, new.value.name);
221 }
222 }
223 fn_count += 1;
224 break :buf decl.fn_link.c.fwd_decl.items;
209 if (!decl.has_tv) continue;
210 const buf = buf: {
211 if (decl.val.castTag(.function)) |_| {
212 var it = decl.fn_link.c.typedefs.iterator();
213 while (it.next()) |new| {
214 if (typedefs.get(new.key)) |previous| {
215 try err_typedef_writer.print("typedef {s} {s};\n", .{ previous, new.value.name });
225216 } else {
226 break :buf decl.link.c.code.items;
217 try typedefs.ensureCapacity(typedefs.capacity() + 1);
218 try err_typedef_writer.writeAll(new.value.rendered);
219 typedefs.putAssumeCapacityNoClobber(new.key, new.value.name);
227220 }
228 };
229 all_buffers.appendAssumeCapacity(.{
230 .iov_base = buf.ptr,
231 .iov_len = buf.len,
232 });
233 file_size += buf.len;
234 },
235 .never_succeeded => continue,
236 }
221 }
222 fn_count += 1;
223 break :buf decl.fn_link.c.fwd_decl.items;
224 } else {
225 break :buf decl.link.c.code.items;
226 }
227 };
228 all_buffers.appendAssumeCapacity(.{
229 .iov_base = buf.ptr,
230 .iov_len = buf.len,
231 });
232 file_size += buf.len;
237233 }
238234
239235 err_typedef_item.* = .{
......@@ -246,18 +242,14 @@ pub fn flushModule(self: *C, comp: *Compilation) !void {
246242 try all_buffers.ensureCapacity(all_buffers.items.len + fn_count);
247243 for (self.decl_table.items()) |kv| {
248244 const decl = kv.key;
249 switch (decl.typed_value) {
250 .most_recent => |tvm| {
251 if (tvm.typed_value.val.castTag(.function)) |_| {
252 const buf = decl.link.c.code.items;
253 all_buffers.appendAssumeCapacity(.{
254 .iov_base = buf.ptr,
255 .iov_len = buf.len,
256 });
257 file_size += buf.len;
258 }
259 },
260 .never_succeeded => continue,
245 if (!decl.has_tv) continue;
246 if (decl.val.castTag(.function)) |_| {
247 const buf = decl.link.c.code.items;
248 all_buffers.appendAssumeCapacity(.{
249 .iov_base = buf.ptr,
250 .iov_len = buf.len,
251 });
252 file_size += buf.len;
261253 }
262254 }
263255
src/link/Coff.zig+6-4
......@@ -662,15 +662,17 @@ pub fn updateDecl(self: *Coff, module: *Module, decl: *Module.Decl) !void {
662662 if (build_options.have_llvm)
663663 if (self.llvm_object) |llvm_object| return try llvm_object.updateDecl(module, decl);
664664
665 const typed_value = decl.typed_value.most_recent.typed_value;
666 if (typed_value.val.tag() == .extern_fn) {
665 if (decl.val.tag() == .extern_fn) {
667666 return; // TODO Should we do more when front-end analyzed extern decl?
668667 }
669668
670669 var code_buffer = std.ArrayList(u8).init(self.base.allocator);
671670 defer code_buffer.deinit();
672671
673 const res = try codegen.generateSymbol(&self.base, decl.srcLoc(), typed_value, &code_buffer, .none);
672 const res = try codegen.generateSymbol(&self.base, decl.srcLoc(), .{
673 .ty = decl.ty,
674 .val = decl.val,
675 }, &code_buffer, .none);
674676 const code = switch (res) {
675677 .externally_managed => |x| x,
676678 .appended => code_buffer.items,
......@@ -681,7 +683,7 @@ pub fn updateDecl(self: *Coff, module: *Module, decl: *Module.Decl) !void {
681683 },
682684 };
683685
684 const required_alignment = typed_value.ty.abiAlignment(self.base.options.target);
686 const required_alignment = decl.ty.abiAlignment(self.base.options.target);
685687 const curr_size = decl.link.coff.size;
686688 if (curr_size != 0) {
687689 const capacity = decl.link.coff.capacity();
src/link/Elf.zig+8-7
......@@ -2191,8 +2191,7 @@ pub fn updateDecl(self: *Elf, module: *Module, decl: *Module.Decl) !void {
21912191 if (build_options.have_llvm)
21922192 if (self.llvm_object) |llvm_object| return try llvm_object.updateDecl(module, decl);
21932193
2194 const typed_value = decl.typed_value.most_recent.typed_value;
2195 if (typed_value.val.tag() == .extern_fn) {
2194 if (decl.val.tag() == .extern_fn) {
21962195 return; // TODO Should we do more when front-end analyzed extern decl?
21972196 }
21982197
......@@ -2214,7 +2213,7 @@ pub fn updateDecl(self: *Elf, module: *Module, decl: *Module.Decl) !void {
22142213 dbg_info_type_relocs.deinit(self.base.allocator);
22152214 }
22162215
2217 const is_fn: bool = switch (typed_value.ty.zigTypeTag()) {
2216 const is_fn: bool = switch (decl.ty.zigTypeTag()) {
22182217 .Fn => true,
22192218 else => false,
22202219 };
......@@ -2270,7 +2269,7 @@ pub fn updateDecl(self: *Elf, module: *Module, decl: *Module.Decl) !void {
22702269 const decl_name_with_null = decl.name[0 .. mem.lenZ(decl.name) + 1];
22712270 try dbg_info_buffer.ensureCapacity(dbg_info_buffer.items.len + 25 + decl_name_with_null.len);
22722271
2273 const fn_ret_type = typed_value.ty.fnReturnType();
2272 const fn_ret_type = decl.ty.fnReturnType();
22742273 const fn_ret_has_bits = fn_ret_type.hasCodeGenBits();
22752274 if (fn_ret_has_bits) {
22762275 dbg_info_buffer.appendAssumeCapacity(abbrev_subprogram);
......@@ -2299,7 +2298,10 @@ pub fn updateDecl(self: *Elf, module: *Module, decl: *Module.Decl) !void {
22992298 } else {
23002299 // TODO implement .debug_info for global variables
23012300 }
2302 const res = try codegen.generateSymbol(&self.base, decl.srcLoc(), typed_value, &code_buffer, .{
2301 const res = try codegen.generateSymbol(&self.base, decl.srcLoc(), .{
2302 .ty = decl.ty,
2303 .val = decl.val,
2304 }, &code_buffer, .{
23032305 .dwarf = .{
23042306 .dbg_line = &dbg_line_buffer,
23052307 .dbg_info = &dbg_info_buffer,
......@@ -2316,7 +2318,7 @@ pub fn updateDecl(self: *Elf, module: *Module, decl: *Module.Decl) !void {
23162318 },
23172319 };
23182320
2319 const required_alignment = typed_value.ty.abiAlignment(self.base.options.target);
2321 const required_alignment = decl.ty.abiAlignment(self.base.options.target);
23202322
23212323 const stt_bits: u8 = if (is_fn) elf.STT_FUNC else elf.STT_OBJECT;
23222324
......@@ -2678,7 +2680,6 @@ pub fn updateDeclExports(
26782680 defer tracy.end();
26792681
26802682 try self.global_symbols.ensureCapacity(self.base.allocator, self.global_symbols.items.len + exports.len);
2681 const typed_value = decl.typed_value.most_recent.typed_value;
26822683 if (decl.link.elf.local_sym_index == 0) return;
26832684 const decl_sym = self.local_symbols.items[decl.link.elf.local_sym_index];
26842685
src/link/MachO.zig+10-5
......@@ -1138,8 +1138,7 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void {
11381138 const tracy = trace(@src());
11391139 defer tracy.end();
11401140
1141 const typed_value = decl.typed_value.most_recent.typed_value;
1142 if (typed_value.val.tag() == .extern_fn) {
1141 if (decl.val.tag() == .extern_fn) {
11431142 return; // TODO Should we do more when front-end analyzed extern decl?
11441143 }
11451144
......@@ -1160,7 +1159,10 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void {
11601159 }
11611160
11621161 const res = if (debug_buffers) |*dbg|
1163 try codegen.generateSymbol(&self.base, decl.srcLoc(), typed_value, &code_buffer, .{
1162 try codegen.generateSymbol(&self.base, decl.srcLoc(), .{
1163 .ty = decl.ty,
1164 .val = decl.val,
1165 }, &code_buffer, .{
11641166 .dwarf = .{
11651167 .dbg_line = &dbg.dbg_line_buffer,
11661168 .dbg_info = &dbg.dbg_info_buffer,
......@@ -1168,7 +1170,10 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void {
11681170 },
11691171 })
11701172 else
1171 try codegen.generateSymbol(&self.base, decl.srcLoc(), typed_value, &code_buffer, .none);
1173 try codegen.generateSymbol(&self.base, decl.srcLoc(), .{
1174 .ty = decl.ty,
1175 .val = decl.val,
1176 }, &code_buffer, .none);
11721177
11731178 const code = switch (res) {
11741179 .externally_managed => |x| x,
......@@ -1184,7 +1189,7 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void {
11841189 },
11851190 };
11861191
1187 const required_alignment = typed_value.ty.abiAlignment(self.base.options.target);
1192 const required_alignment = decl.ty.abiAlignment(self.base.options.target);
11881193 assert(decl.link.macho.local_sym_index != 0); // Caller forgot to call allocateDeclIndexes()
11891194 const symbol = &self.locals.items[decl.link.macho.local_sym_index];
11901195
src/link/MachO/DebugSymbols.zig+5-5
......@@ -946,8 +946,8 @@ pub fn initDeclDebugBuffers(
946946 var dbg_info_buffer = std.ArrayList(u8).init(allocator);
947947 var dbg_info_type_relocs: link.File.DbgInfoTypeRelocsTable = .{};
948948
949 const typed_value = decl.typed_value.most_recent.typed_value;
950 switch (typed_value.ty.zigTypeTag()) {
949 assert(decl.has_tv);
950 switch (decl.ty.zigTypeTag()) {
951951 .Fn => {
952952 // For functions we need to add a prologue to the debug line program.
953953 try dbg_line_buffer.ensureCapacity(26);
......@@ -999,7 +999,7 @@ pub fn initDeclDebugBuffers(
999999 const decl_name_with_null = decl.name[0 .. mem.lenZ(decl.name) + 1];
10001000 try dbg_info_buffer.ensureCapacity(dbg_info_buffer.items.len + 27 + decl_name_with_null.len);
10011001
1002 const fn_ret_type = typed_value.ty.fnReturnType();
1002 const fn_ret_type = decl.ty.fnReturnType();
10031003 const fn_ret_has_bits = fn_ret_type.hasCodeGenBits();
10041004 if (fn_ret_has_bits) {
10051005 dbg_info_buffer.appendAssumeCapacity(abbrev_subprogram);
......@@ -1058,8 +1058,8 @@ pub fn commitDeclDebugInfo(
10581058 const symbol = self.base.locals.items[decl.link.macho.local_sym_index];
10591059 const text_block = &decl.link.macho;
10601060 // If the Decl is a function, we need to update the __debug_line program.
1061 const typed_value = decl.typed_value.most_recent.typed_value;
1062 switch (typed_value.ty.zigTypeTag()) {
1061 assert(decl.has_tv);
1062 switch (decl.ty.zigTypeTag()) {
10631063 .Fn => {
10641064 // Perform the relocations based on vaddr.
10651065 {
src/link/SpirV.zig+3-7
......@@ -179,13 +179,9 @@ pub fn flushModule(self: *SpirV, comp: *Compilation) !void {
179179
180180 for (self.decl_table.items()) |entry| {
181181 const decl = entry.key;
182 switch (decl.typed_value) {
183 .most_recent => |tvm| {
184 const fn_data = &decl.fn_link.spirv;
185 all_buffers.appendAssumeCapacity(wordsToIovConst(fn_data.code.items));
186 },
187 .never_succeeded => continue,
188 }
182 if (!decl.has_tv) continue;
183 const fn_data = &decl.fn_link.spirv;
184 all_buffers.appendAssumeCapacity(wordsToIovConst(fn_data.code.items));
189185 }
190186
191187 var file_size: u64 = 0;
src/link/Wasm.zig+7-9
......@@ -175,9 +175,8 @@ pub fn allocateDeclIndexes(self: *Wasm, decl: *Module.Decl) !void {
175175
176176 self.offset_table.items[block.offset_index] = 0;
177177
178 const typed_value = decl.typed_value.most_recent.typed_value;
179 if (typed_value.ty.zigTypeTag() == .Fn) {
180 switch (typed_value.val.tag()) {
178 if (decl.ty.zigTypeTag() == .Fn) {
179 switch (decl.val.tag()) {
181180 // dependent on function type, appends it to the correct list
182181 .function => try self.funcs.append(self.base.allocator, decl),
183182 .extern_fn => try self.ext_funcs.append(self.base.allocator, decl),
......@@ -191,7 +190,6 @@ pub fn allocateDeclIndexes(self: *Wasm, decl: *Module.Decl) !void {
191190pub fn updateDecl(self: *Wasm, module: *Module, decl: *Module.Decl) !void {
192191 std.debug.assert(decl.link.wasm.init); // Must call allocateDeclIndexes()
193192
194 const typed_value = decl.typed_value.most_recent.typed_value;
195193 const fn_data = &decl.fn_link.wasm;
196194 fn_data.functype.items.len = 0;
197195 fn_data.code.items.len = 0;
......@@ -210,7 +208,7 @@ pub fn updateDecl(self: *Wasm, module: *Module, decl: *Module.Decl) !void {
210208 defer context.deinit();
211209
212210 // generate the 'code' section for the function declaration
213 const result = context.gen(typed_value) catch |err| switch (err) {
211 const result = context.gen(.{ .ty = decl.ty, .val = decl.val }) catch |err| switch (err) {
214212 error.CodegenFail => {
215213 decl.analysis = .codegen_failure;
216214 try module.failed_decls.put(module.gpa, decl, context.err_msg);
......@@ -228,7 +226,7 @@ pub fn updateDecl(self: *Wasm, module: *Module, decl: *Module.Decl) !void {
228226 fn_data.functype = context.func_type_data.toUnmanaged();
229227
230228 const block = &decl.link.wasm;
231 if (typed_value.ty.zigTypeTag() == .Fn) {
229 if (decl.ty.zigTypeTag() == .Fn) {
232230 // as locals are patched afterwards, the offsets of funcidx's are off,
233231 // here we update them to correct them
234232 for (fn_data.idx_refs.items) |*func| {
......@@ -262,7 +260,7 @@ pub fn updateDeclExports(
262260
263261pub fn freeDecl(self: *Wasm, decl: *Module.Decl) void {
264262 if (self.getFuncidx(decl)) |func_idx| {
265 switch (decl.typed_value.most_recent.typed_value.val.tag()) {
263 switch (decl.val.tag()) {
266264 .function => _ = self.funcs.swapRemove(func_idx),
267265 .extern_fn => _ = self.ext_funcs.swapRemove(func_idx),
268266 else => unreachable,
......@@ -429,7 +427,7 @@ pub fn flushModule(self: *Wasm, comp: *Compilation) !void {
429427 try leb.writeULEB128(writer, @intCast(u32, exprt.options.name.len));
430428 try writer.writeAll(exprt.options.name);
431429
432 switch (exprt.exported_decl.typed_value.most_recent.typed_value.ty.zigTypeTag()) {
430 switch (exprt.exported_decl.ty.zigTypeTag()) {
433431 .Fn => {
434432 // Type of the export
435433 try writer.writeByte(wasm.externalKind(.function));
......@@ -802,7 +800,7 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation) !void {
802800/// TODO: we could maintain a hash map to potentially make this simpler
803801fn getFuncidx(self: Wasm, decl: *Module.Decl) ?u32 {
804802 var offset: u32 = 0;
805 const slice = switch (decl.typed_value.most_recent.typed_value.val.tag()) {
803 const slice = switch (decl.val.tag()) {
806804 .function => blk: {
807805 // when the target is a regular function, we have to calculate
808806 // the offset of where the index starts