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,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.
1 * reimplement semaDecl4 * reimplement semaDecl
2 * use a hash map for instructions because the array is too big5 * 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
4 * keep track of file dependencies/dependants10 * keep track of file dependencies/dependants
5 * unload files from memory when a dependency is dropped11 * unload files from memory when a dependency is dropped
...@@ -101,39 +107,6 @@ fn astgenAndSemaDecl(mod: *Module, decl: *Decl) !bool {...@@ -101,39 +107,6 @@ fn astgenAndSemaDecl(mod: *Module, decl: *Decl) !bool {
101 .aligned_var_decl => return mod.astgenAndSemaVarDecl(decl, tree.*, tree.alignedVarDecl(decl_node)),107 .aligned_var_decl => return mod.astgenAndSemaVarDecl(decl, tree.*, tree.alignedVarDecl(decl_node)),
102108
103 .@"comptime" => {109 .@"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;
137 },110 },
138 .@"usingnamespace" => {111 .@"usingnamespace" => {
139 decl.analysis = .in_progress;112 decl.analysis = .in_progress;
...@@ -424,3 +397,78 @@ pub fn analyzeNamespace(...@@ -424,3 +397,78 @@ pub fn analyzeNamespace(
424 };397 };
425}398}
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...@@ -1890,7 +1890,8 @@ pub fn performAllTheWork(self: *Compilation) error{ TimerUnsupported, OutOfMemor
1890 if (build_options.omit_stage2)1890 if (build_options.omit_stage2)
1891 @panic("sadly stage2 is omitted from this build to save memory on the CI server");1891 @panic("sadly stage2 is omitted from this build to save memory on the CI server");
1892 const module = self.bin_file.options.module.?;1892 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| {
1894 const func = payload.data;1895 const func = payload.data;
1895 switch (func.state) {1896 switch (func.state) {
1896 .queued => module.analyzeFnBody(decl, func) catch |err| switch (err) {1897 .queued => module.analyzeFnBody(decl, func) catch |err| switch (err) {
...@@ -1907,8 +1908,8 @@ pub fn performAllTheWork(self: *Compilation) error{ TimerUnsupported, OutOfMemor...@@ -1907,8 +1908,8 @@ pub fn performAllTheWork(self: *Compilation) error{ TimerUnsupported, OutOfMemor
1907 }1908 }
1908 // Here we tack on additional allocations to the Decl's arena. The allocations1909 // Here we tack on additional allocations to the Decl's arena. The allocations
1909 // are lifetime annotations in the ZIR.1910 // are lifetime annotations in the ZIR.
1910 var decl_arena = decl.typed_value.most_recent.arena.?.promote(module.gpa);1911 var decl_arena = decl.value_arena.?.promote(module.gpa);
1911 defer decl.typed_value.most_recent.arena.?.* = decl_arena.state;1912 defer decl.value_arena.?.* = decl_arena.state;
1912 log.debug("analyze liveness of {s}", .{decl.name});1913 log.debug("analyze liveness of {s}", .{decl.name});
1913 try liveness.analyze(module.gpa, &decl_arena.allocator, func.body);1914 try liveness.analyze(module.gpa, &decl_arena.allocator, func.body);
19141915
...@@ -1918,9 +1919,9 @@ pub fn performAllTheWork(self: *Compilation) error{ TimerUnsupported, OutOfMemor...@@ -1918,9 +1919,9 @@ pub fn performAllTheWork(self: *Compilation) error{ TimerUnsupported, OutOfMemor
1918 }1919 }
19191920
1920 log.debug("calling updateDecl on '{s}', type={}", .{1921 log.debug("calling updateDecl on '{s}', type={}", .{
1921 decl.name, decl.typed_value.most_recent.typed_value.ty,1922 decl.name, decl.ty,
1922 });1923 });
1923 assert(decl.typed_value.most_recent.typed_value.ty.hasCodeGenBits());1924 assert(decl.ty.hasCodeGenBits());
19241925
1925 self.bin_file.updateDecl(module, decl) catch |err| switch (err) {1926 self.bin_file.updateDecl(module, decl) catch |err| switch (err) {
1926 error.OutOfMemory => return error.OutOfMemory,1927 error.OutOfMemory => return error.OutOfMemory,
...@@ -1960,7 +1961,6 @@ pub fn performAllTheWork(self: *Compilation) error{ TimerUnsupported, OutOfMemor...@@ -1960,7 +1961,6 @@ pub fn performAllTheWork(self: *Compilation) error{ TimerUnsupported, OutOfMemor
1960 const module = self.bin_file.options.module.?;1961 const module = self.bin_file.options.module.?;
1961 const emit_h = module.emit_h.?;1962 const emit_h = module.emit_h.?;
1962 _ = try emit_h.decl_table.getOrPut(module.gpa, decl);1963 _ = try emit_h.decl_table.getOrPut(module.gpa, decl);
1963 const tv = decl.typed_value.most_recent.typed_value;
1964 const decl_emit_h = decl.getEmitH(module);1964 const decl_emit_h = decl.getEmitH(module);
1965 const fwd_decl = &decl_emit_h.fwd_decl;1965 const fwd_decl = &decl_emit_h.fwd_decl;
1966 fwd_decl.shrinkRetainingCapacity(0);1966 fwd_decl.shrinkRetainingCapacity(0);
src/Module.zig+190-135
...@@ -154,17 +154,29 @@ pub const DeclPlusEmitH = struct {...@@ -154,17 +154,29 @@ pub const DeclPlusEmitH = struct {
154};154};
155155
156pub const Decl = struct {156pub const Decl = struct {
157 /// This name is relative to the containing namespace of the decl. It uses157 /// This name is relative to the containing namespace of the decl.
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.
161 /// All Decls have names, even values that are not bound to a zig namespace.158 /// All Decls have names, even values that are not bound to a zig namespace.
162 /// This is necessary for mapping them to an address in the output file.159 /// 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.
164 name: [*:0]const u8,164 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,
165 /// The direct parent namespace of the Decl.178 /// The direct parent namespace of the Decl.
166 /// Reference to externally owned memory.179 /// Reference to externally owned memory.
167 /// This is `null` for the Decl that represents a `File`.
168 namespace: *Scope.Namespace,180 namespace: *Scope.Namespace,
169181
170 /// An integer that can be checked against the corresponding incrementing182 /// An integer that can be checked against the corresponding incrementing
...@@ -174,12 +186,11 @@ pub const Decl = struct {...@@ -174,12 +186,11 @@ pub const Decl = struct {
174 /// The AST node index of this declaration.186 /// The AST node index of this declaration.
175 /// Must be recomputed when the corresponding source file is modified.187 /// Must be recomputed when the corresponding source file is modified.
176 src_node: ast.Node.Index,188 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 },
183 /// Represents the "shallow" analysis status. For example, for decls that are functions,194 /// Represents the "shallow" analysis status. For example, for decls that are functions,
184 /// the function type is analyzed with this set to `in_progress`, however, the semantic195 /// the function type is analyzed with this set to `in_progress`, however, the semantic
185 /// analysis of the function body is performed with this value set to `success`. Functions196 /// analysis of the function body is performed with this value set to `success`. Functions
...@@ -214,11 +225,15 @@ pub const Decl = struct {...@@ -214,11 +225,15 @@ pub const Decl = struct {
214 /// to require re-analysis.225 /// to require re-analysis.
215 outdated,226 outdated,
216 },227 },
228 /// Whether `typed_value`, `align_val`, and `linksection_val` are populated.
229 has_tv: bool,
217 /// This flag is set when this Decl is added to `Module.deletion_set`, and cleared230 /// This flag is set when this Decl is added to `Module.deletion_set`, and cleared
218 /// when removed.231 /// when removed.
219 deletion_flag: bool,232 deletion_flag: bool,
220 /// Whether the corresponding AST decl has a `pub` keyword.233 /// Whether the corresponding AST decl has a `pub` keyword.
221 is_pub: bool,234 is_pub: bool,
235 /// Whether the corresponding AST decl has a `export` keyword.
236 is_exported: bool,
222237
223 /// Represents the position of the code in the output file.238 /// Represents the position of the code in the output file.
224 /// This is populated regardless of semantic analysis and code generation.239 /// This is populated regardless of semantic analysis and code generation.
...@@ -231,6 +246,9 @@ pub const Decl = struct {...@@ -231,6 +246,9 @@ pub const Decl = struct {
231 /// to save on memory usage.246 /// to save on memory usage.
232 fn_link: link.File.LinkFn,247 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.
234 contents_hash: std.zig.SrcHash,252 contents_hash: std.zig.SrcHash,
235253
236 /// The shallow set of other decls whose typed_value could possibly change if this Decl's254 /// The shallow set of other decls whose typed_value could possibly change if this Decl's
...@@ -247,12 +265,12 @@ pub const Decl = struct {...@@ -247,12 +265,12 @@ pub const Decl = struct {
247 pub fn destroy(decl: *Decl, module: *Module) void {265 pub fn destroy(decl: *Decl, module: *Module) void {
248 const gpa = module.gpa;266 const gpa = module.gpa;
249 gpa.free(mem.spanZ(decl.name));267 gpa.free(mem.spanZ(decl.name));
250 if (decl.typedValueManaged()) |tvm| {268 if (decl.has_tv) {
251 if (tvm.typed_value.val.castTag(.function)) |payload| {269 if (decl.val.castTag(.function)) |payload| {
252 const func = payload.data;270 const func = payload.data;
253 func.deinit(gpa);271 func.deinit(gpa);
254 }272 }
255 tvm.deinit(gpa);273 if (decl.value_arena) |a| a.promote(gpa).deinit();
256 }274 }
257 decl.dependants.deinit(gpa);275 decl.dependants.deinit(gpa);
258 decl.dependencies.deinit(gpa);276 decl.dependencies.deinit(gpa);
...@@ -311,9 +329,12 @@ pub const Decl = struct {...@@ -311,9 +329,12 @@ pub const Decl = struct {
311 return buffer.toOwnedSlice();329 return buffer.toOwnedSlice();
312 }330 }
313331
314 pub fn typedValue(decl: *Decl) error{AnalysisFail}!TypedValue {332 pub fn typedValue(decl: Decl) error{AnalysisFail}!TypedValue {
315 const tvm = decl.typedValueManaged() orelse return error.AnalysisFail;333 if (!decl.has_tv) return error.AnalysisFail;
316 return tvm.typed_value;334 return TypedValue{
335 .ty = decl.ty,
336 .val = decl.val,
337 };
317 }338 }
318339
319 pub fn value(decl: *Decl) error{AnalysisFail}!Value {340 pub fn value(decl: *Decl) error{AnalysisFail}!Value {
...@@ -334,19 +355,12 @@ pub const Decl = struct {...@@ -334,19 +355,12 @@ pub const Decl = struct {
334 mem.spanZ(decl.name),355 mem.spanZ(decl.name),
335 @tagName(decl.analysis),356 @tagName(decl.analysis),
336 });357 });
337 if (decl.typedValueManaged()) |tvm| {358 if (decl.has_tv) {
338 std.debug.print(" ty={} val={}", .{ tvm.typed_value.ty, tvm.typed_value.val });359 std.debug.print(" ty={} val={}", .{ decl.ty, decl.val });
339 }360 }
340 std.debug.print("\n", .{});361 std.debug.print("\n", .{});
341 }362 }
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
350 pub fn getFileScope(decl: Decl) *Scope.File {364 pub fn getFileScope(decl: Decl) *Scope.File {
351 return decl.namespace.file_scope;365 return decl.namespace.file_scope;
352 }366 }
...@@ -475,16 +489,6 @@ pub const EnumFull = struct {...@@ -475,16 +489,6 @@ pub const EnumFull = struct {
475/// the `Decl` only, with a `Value` tag of `extern_fn`.489/// the `Decl` only, with a `Value` tag of `extern_fn`.
476pub const Fn = struct {490pub const Fn = struct {
477 owner_decl: *Decl,491 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,
488 /// undefined unless analysis state is `success`.492 /// undefined unless analysis state is `success`.
489 body: ir.Body,493 body: ir.Body,
490 state: Analysis,494 state: Analysis,
...@@ -508,9 +512,7 @@ pub const Fn = struct {...@@ -508,9 +512,7 @@ pub const Fn = struct {
508 ir.dumpFn(mod, func);512 ir.dumpFn(mod, func);
509 }513 }
510514
511 pub fn deinit(func: *Fn, gpa: *Allocator) void {515 pub fn deinit(func: *Fn, gpa: *Allocator) void {}
512 func.zir.deinit(gpa);
513 }
514};516};
515517
516pub const Var = struct {518pub const Var = struct {
...@@ -3111,7 +3113,7 @@ pub fn ensureDeclAnalyzed(mod: *Module, decl: *Decl) InnerError!void {...@@ -3111,7 +3113,7 @@ pub fn ensureDeclAnalyzed(mod: *Module, decl: *Decl) InnerError!void {
3111 if (subsequent_analysis) {3113 if (subsequent_analysis) {
3112 // We may need to chase the dependants and re-analyze them.3114 // We may need to chase the dependants and re-analyze them.
3113 // However, if the decl is a function, and the type is the same, we do not need to.3115 // 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) {
3115 for (decl.dependants.items()) |entry| {3117 for (decl.dependants.items()) |entry| {
3116 const dep = entry.key;3118 const dep = entry.key;
3117 switch (dep.analysis) {3119 switch (dep.analysis) {
...@@ -3162,13 +3164,20 @@ pub fn semaFile(mod: *Module, file: *Scope.File) InnerError!void {...@@ -3162,13 +3164,20 @@ pub fn semaFile(mod: *Module, file: *Scope.File) InnerError!void {
3162 .namespace = &tmp_namespace,3164 .namespace = &tmp_namespace,
3163 .generation = mod.generation,3165 .generation = mod.generation,
3164 .src_node = 0, // the root AST node for the file3166 .src_node = 0, // the root AST node for the file
3165 .typed_value = .never_succeeded,
3166 .analysis = .in_progress,3167 .analysis = .in_progress,
3167 .deletion_flag = false,3168 .deletion_flag = false,
3168 .is_pub = true,3169 .is_pub = true,
3170 .is_exported = false,
3169 .link = undefined, // don't try to codegen this3171 .link = undefined, // don't try to codegen this
3170 .fn_link = undefined, // not a function3172 .fn_link = undefined, // not a function
3171 .contents_hash = undefined, // top-level struct has no contents hash3173 .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,
3172 };3181 };
3173 defer top_decl.dependencies.deinit(gpa);3182 defer top_decl.dependencies.deinit(gpa);
31743183
...@@ -3223,7 +3232,56 @@ fn semaDecl(mod: *Module, decl: *Decl) !bool {...@@ -3223,7 +3232,56 @@ fn semaDecl(mod: *Module, decl: *Decl) !bool {
3223 const tracy = trace(@src());3232 const tracy = trace(@src());
3224 defer tracy.end();3233 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;
3227}3285}
32283286
3229/// Returns the depender's index of the dependee.3287/// Returns the depender's index of the dependee.
...@@ -3489,6 +3547,7 @@ fn scanDecl(...@@ -3489,6 +3547,7 @@ fn scanDecl(
34893547
3490 const gpa = mod.gpa;3548 const gpa = mod.gpa;
3491 const zir = namespace.file_scope.zir;3549 const zir = namespace.file_scope.zir;
3550
3492 const decl_block_inst_data = zir.instructions.items(.data)[decl_index].pl_node;3551 const decl_block_inst_data = zir.instructions.items(.data)[decl_index].pl_node;
3493 const decl_node = parent_decl.relativeToNodeIndex(decl_block_inst_data.src_node);3552 const decl_node = parent_decl.relativeToNodeIndex(decl_block_inst_data.src_node);
34943553
...@@ -3504,13 +3563,9 @@ fn scanDecl(...@@ -3504,13 +3563,9 @@ fn scanDecl(
3504 const decl_key = decl_name orelse &contents_hash;3563 const decl_key = decl_name orelse &contents_hash;
3505 const gop = try namespace.decls.getOrPut(gpa, decl_key);3564 const gop = try namespace.decls.getOrPut(gpa, decl_key);
3506 if (!gop.found_existing) {3565 if (!gop.found_existing) {
3507 if (align_inst != .none) {3566 const new_decl = try mod.allocateNewDecl(namespace, decl_node);
3508 return mod.fail(&namespace.base, .{ .node_abs = decl_node }, "TODO: implement decls with align()", .{});3567 new_decl.contents_hash = contents_hash;
3509 }3568 new_decl.name = try gpa.dupeZ(u8, decl_key);
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);
3514 // Update the key reference to the longer-lived memory.3569 // Update the key reference to the longer-lived memory.
3515 gop.entry.key = &new_decl.contents_hash;3570 gop.entry.key = &new_decl.contents_hash;
3516 gop.entry.value = new_decl;3571 gop.entry.value = new_decl;
...@@ -3524,7 +3579,11 @@ fn scanDecl(...@@ -3524,7 +3579,11 @@ fn scanDecl(
3524 if (want_analysis) {3579 if (want_analysis) {
3525 mod.comp.work_queue.writeItemAssumeCapacity(.{ .analyze_decl = new_decl });3580 mod.comp.work_queue.writeItemAssumeCapacity(.{ .analyze_decl = new_decl });
3526 }3581 }
3582 new_decl.is_exported = is_exported;
3527 new_decl.is_pub = is_pub;3583 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;
3528 return;3587 return;
3529 }3588 }
3530 const decl = gop.entry.value;3589 const decl = gop.entry.value;
...@@ -3532,6 +3591,11 @@ fn scanDecl(...@@ -3532,6 +3591,11 @@ fn scanDecl(
3532 // have been re-ordered.3591 // have been re-ordered.
3533 const prev_src_node = decl.src_node;3592 const prev_src_node = decl.src_node;
3534 decl.src_node = decl_node;3593 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;
3535 if (deleted_decls.swapRemove(decl) == null) {3599 if (deleted_decls.swapRemove(decl) == null) {
3536 if (true) {3600 if (true) {
3537 @panic("TODO I think this code path is unreachable; should be caught by AstGen.");3601 @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 {...@@ -3681,64 +3745,70 @@ pub fn analyzeFnBody(mod: *Module, decl: *Decl, func: *Fn) !void {
3681 defer tracy.end();3745 defer tracy.end();
36823746
3683 // Use the Decl's arena for function memory.3747 // Use the Decl's arena for function memory.
3684 var arena = decl.typed_value.most_recent.arena.?.promote(mod.gpa);3748 var arena = decl.value_arena.?.promote(mod.gpa);
3685 defer decl.typed_value.most_recent.arena.?.* = arena.state;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;
3688 const param_inst_list = try mod.gpa.alloc(*ir.Inst, fn_ty.fnParamLen());3752 const param_inst_list = try mod.gpa.alloc(*ir.Inst, fn_ty.fnParamLen());
3689 defer mod.gpa.free(param_inst_list);3753 defer mod.gpa.free(param_inst_list);
36903754
3691 for (param_inst_list) |*param_inst, param_index| {3755 var f = false;
3692 const param_type = fn_ty.fnParamType(param_index);3756 if (f) {
3693 const name = func.zir.nullTerminatedString(func.zir.extra[param_index]);3757 return error.AnalysisFail;
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;
3704 }3758 }
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 = .{3776 //var sema: Sema = .{
3707 .mod = mod,3777 // .mod = mod,
3708 .gpa = mod.gpa,3778 // .gpa = mod.gpa,
3709 .arena = &arena.allocator,3779 // .arena = &arena.allocator,
3710 .code = func.zir,3780 // .code = func.zir,
3711 .inst_map = try mod.gpa.alloc(*ir.Inst, func.zir.instructions.len),3781 // .inst_map = try mod.gpa.alloc(*ir.Inst, func.zir.instructions.len),
3712 .owner_decl = decl,3782 // .owner_decl = decl,
3713 .namespace = decl.namespace,3783 // .namespace = decl.namespace,
3714 .func = func,3784 // .func = func,
3715 .owner_func = func,3785 // .owner_func = func,
3716 .param_inst_list = param_inst_list,3786 // .param_inst_list = param_inst_list,
3717 };3787 //};
3718 defer mod.gpa.free(sema.inst_map);3788 //defer mod.gpa.free(sema.inst_map);
37193789
3720 var inner_block: Scope.Block = .{3790 //var inner_block: Scope.Block = .{
3721 .parent = null,3791 // .parent = null,
3722 .sema = &sema,3792 // .sema = &sema,
3723 .src_decl = decl,3793 // .src_decl = decl,
3724 .instructions = .{},3794 // .instructions = .{},
3725 .inlining = null,3795 // .inlining = null,
3726 .is_comptime = false,3796 // .is_comptime = false,
3727 };3797 //};
3728 defer inner_block.instructions.deinit(mod.gpa);3798 //defer inner_block.instructions.deinit(mod.gpa);
37293799
3730 // AIR currently requires the arg parameters to be the first N instructions3800 //// AIR currently requires the arg parameters to be the first N instructions
3731 try inner_block.instructions.appendSlice(mod.gpa, param_inst_list);3801 //try inner_block.instructions.appendSlice(mod.gpa, param_inst_list);
37323802
3733 func.state = .in_progress;3803 //func.state = .in_progress;
3734 log.debug("set {s} to in_progress", .{decl.name});3804 //log.debug("set {s} to in_progress", .{decl.name});
37353805
3736 _ = try sema.root(&inner_block);3806 //_ = try sema.root(&inner_block);
37373807
3738 const instructions = try arena.allocator.dupe(*ir.Inst, inner_block.instructions.items);3808 //const instructions = try arena.allocator.dupe(*ir.Inst, inner_block.instructions.items);
3739 func.state = .success;3809 //func.state = .success;
3740 func.body = .{ .instructions = instructions };3810 //func.body = .{ .instructions = instructions };
3741 log.debug("set {s} to success", .{decl.name});3811 //log.debug("set {s} to success", .{decl.name});
3742}3812}
37433813
3744fn markOutdatedDecl(mod: *Module, decl: *Decl) !void {3814fn markOutdatedDecl(mod: *Module, decl: *Decl) !void {
...@@ -3756,12 +3826,7 @@ fn markOutdatedDecl(mod: *Module, decl: *Decl) !void {...@@ -3756,12 +3826,7 @@ fn markOutdatedDecl(mod: *Module, decl: *Decl) !void {
3756 decl.analysis = .outdated;3826 decl.analysis = .outdated;
3757}3827}
37583828
3759fn allocateNewDecl(3829fn allocateNewDecl(mod: *Module, namespace: *Scope.Namespace, src_node: ast.Node.Index) !*Decl {
3760 mod: *Module,
3761 namespace: *Scope.Namespace,
3762 src_node: ast.Node.Index,
3763 contents_hash: std.zig.SrcHash,
3764) !*Decl {
3765 // If we have emit-h then we must allocate a bigger structure to store the emit-h state.3830 // If we have emit-h then we must allocate a bigger structure to store the emit-h state.
3766 const new_decl: *Decl = if (mod.emit_h != null) blk: {3831 const new_decl: *Decl = if (mod.emit_h != null) blk: {
3767 const parent_struct = try mod.gpa.create(DeclPlusEmitH);3832 const parent_struct = try mod.gpa.create(DeclPlusEmitH);
...@@ -3776,10 +3841,15 @@ fn allocateNewDecl(...@@ -3776,10 +3841,15 @@ fn allocateNewDecl(
3776 .name = "",3841 .name = "",
3777 .namespace = namespace,3842 .namespace = namespace,
3778 .src_node = src_node,3843 .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,
3780 .analysis = .unreferenced,3849 .analysis = .unreferenced,
3781 .deletion_flag = false,3850 .deletion_flag = false,
3782 .contents_hash = contents_hash,3851 .contents_hash = undefined,
3852 .zir_block_index = undefined,
3783 .link = switch (mod.comp.bin_file.tag) {3853 .link = switch (mod.comp.bin_file.tag) {
3784 .coff => .{ .coff = link.File.Coff.TextBlock.empty },3854 .coff => .{ .coff = link.File.Coff.TextBlock.empty },
3785 .elf => .{ .elf = link.File.Elf.TextBlock.empty },3855 .elf => .{ .elf = link.File.Elf.TextBlock.empty },
...@@ -3798,23 +3868,11 @@ fn allocateNewDecl(...@@ -3798,23 +3868,11 @@ fn allocateNewDecl(
3798 },3868 },
3799 .generation = 0,3869 .generation = 0,
3800 .is_pub = false,3870 .is_pub = false,
3871 .is_exported = false,
3801 };3872 };
3802 return new_decl;3873 return new_decl;
3803}3874}
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
3818/// Get error value for error tag `name`.3876/// Get error value for error tag `name`.
3819pub fn getErrorValue(mod: *Module, name: []const u8) !std.StringHashMapUnmanaged(ErrorInt).Entry {3877pub fn getErrorValue(mod: *Module, name: []const u8) !std.StringHashMapUnmanaged(ErrorInt).Entry {
3820 const gop = try mod.global_error_set.getOrPut(mod.gpa, name);3878 const gop = try mod.global_error_set.getOrPut(mod.gpa, name);
...@@ -3837,10 +3895,9 @@ pub fn analyzeExport(...@@ -3837,10 +3895,9 @@ pub fn analyzeExport(
3837 exported_decl: *Decl,3895 exported_decl: *Decl,
3838) !void {3896) !void {
3839 try mod.ensureDeclAnalyzed(exported_decl);3897 try mod.ensureDeclAnalyzed(exported_decl);
3840 const typed_value = exported_decl.typed_value.most_recent.typed_value;3898 switch (exported_decl.ty.zigTypeTag()) {
3841 switch (typed_value.ty.zigTypeTag()) {
3842 .Fn => {},3899 .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}),
3844 }3901 }
38453902
3846 try mod.decl_exports.ensureCapacity(mod.gpa, mod.decl_exports.items().len + 1);3903 try mod.decl_exports.ensureCapacity(mod.gpa, mod.decl_exports.items().len + 1);
...@@ -4017,20 +4074,18 @@ pub fn createAnonymousDecl(...@@ -4017,20 +4074,18 @@ pub fn createAnonymousDecl(
4017) !*Decl {4074) !*Decl {
4018 const name_index = mod.getNextAnonNameIndex();4075 const name_index = mod.getNextAnonNameIndex();
4019 const scope_decl = scope.ownerDecl().?;4076 const scope_decl = scope.ownerDecl().?;
4020 const name = try std.fmt.allocPrint(mod.gpa, "{s}__anon_{d}", .{ scope_decl.name, name_index });4077 const name = try std.fmt.allocPrintZ(mod.gpa, "{s}__anon_{d}", .{ scope_decl.name, name_index });
4021 defer mod.gpa.free(name);4078 errdefer mod.gpa.free(name);
4022 const namespace = scope_decl.namespace;4079 const namespace = scope_decl.namespace;
4023 const src_hash: std.zig.SrcHash = undefined;4080 const new_decl = try mod.allocateNewDecl(namespace, scope_decl.src_node);
4024 const new_decl = try mod.createNewDecl(namespace, name, scope_decl.src_node, src_hash);4081 new_decl.name = name;
4082
4025 const decl_arena_state = try decl_arena.allocator.create(std.heap.ArenaAllocator.State);4083 const decl_arena_state = try decl_arena.allocator.create(std.heap.ArenaAllocator.State);
40264084
4027 decl_arena_state.* = decl_arena.state;4085 decl_arena_state.* = decl_arena.state;
4028 new_decl.typed_value = .{4086 new_decl.ty = typed_value.ty;
4029 .most_recent = .{4087 new_decl.val = typed_value.val;
4030 .typed_value = typed_value,4088 new_decl.has_tv = true;
4031 .arena = decl_arena_state,
4032 },
4033 };
4034 new_decl.analysis = .complete;4089 new_decl.analysis = .complete;
4035 new_decl.generation = mod.generation;4090 new_decl.generation = mod.generation;
40364091
src/Sema.zig+6-25
...@@ -64,28 +64,6 @@ const LazySrcLoc = Module.LazySrcLoc;...@@ -64,28 +64,6 @@ const LazySrcLoc = Module.LazySrcLoc;
64const RangeSet = @import("RangeSet.zig");64const RangeSet = @import("RangeSet.zig");
65const AstGen = @import("AstGen.zig");65const 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
89/// Returns only the result from the body that is specified.67/// Returns only the result from the body that is specified.
90/// Only appropriate to call when it is determined at comptime that this body68/// Only appropriate to call when it is determined at comptime that this body
91/// has no peers.69/// has no peers.
...@@ -997,7 +975,7 @@ fn zirRetPtr(...@@ -997,7 +975,7 @@ fn zirRetPtr(
997975
998 const src: LazySrcLoc = .{ .node_offset = @bitCast(i32, extended.operand) };976 const src: LazySrcLoc = .{ .node_offset = @bitCast(i32, extended.operand) };
999 try sema.requireFunctionBlock(block, src);977 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;
1001 const ret_type = fn_ty.fnReturnType();979 const ret_type = fn_ty.fnReturnType();
1002 const ptr_type = try sema.mod.simplePtrType(sema.arena, ret_type, true, .One);980 const ptr_type = try sema.mod.simplePtrType(sema.arena, ret_type, true, .One);
1003 return block.addNoOp(src, ptr_type, .alloc);981 return block.addNoOp(src, ptr_type, .alloc);
...@@ -1022,7 +1000,7 @@ fn zirRetType(...@@ -1022,7 +1000,7 @@ fn zirRetType(
10221000
1023 const src: LazySrcLoc = .{ .node_offset = @bitCast(i32, extended.operand) };1001 const src: LazySrcLoc = .{ .node_offset = @bitCast(i32, extended.operand) };
1024 try sema.requireFunctionBlock(block, src);1002 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;
1026 const ret_type = fn_ty.fnReturnType();1004 const ret_type = fn_ty.fnReturnType();
1027 return sema.mod.constType(sema.arena, src, ret_type);1005 return sema.mod.constType(sema.arena, src, ret_type);
1028}1006}
...@@ -2022,6 +2000,9 @@ fn analyzeCall(...@@ -2022,6 +2000,9 @@ fn analyzeCall(
2022 .block_inst = block_inst,2000 .block_inst = block_inst,
2023 },2001 },
2024 };2002 };
2003 if (true) {
2004 @panic("TODO reimplement inline fn call after whole-file astgen");
2005 }
2025 var inline_sema: Sema = .{2006 var inline_sema: Sema = .{
2026 .mod = sema.mod,2007 .mod = sema.mod,
2027 .gpa = sema.mod.gpa,2008 .gpa = sema.mod.gpa,
...@@ -4949,7 +4930,7 @@ fn analyzeRet(...@@ -4949,7 +4930,7 @@ fn analyzeRet(
49494930
4950 if (need_coercion) {4931 if (need_coercion) {
4951 if (sema.func) |func| {4932 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;
4953 const fn_ret_ty = fn_ty.fnReturnType();4934 const fn_ret_ty = fn_ty.fnReturnType();
4954 const casted_operand = try sema.coerce(block, fn_ret_ty, operand, src);4935 const casted_operand = try sema.coerce(block, fn_ret_ty, operand, src);
4955 if (fn_ret_ty.zigTypeTag() == .Void)4936 if (fn_ret_ty.zigTypeTag() == .Void)
src/codegen.zig+4-2
...@@ -400,7 +400,8 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -400,7 +400,8 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
400400
401 const module_fn = typed_value.val.castTag(.function).?.data;401 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
405 var branch_stack = std.ArrayList(Branch).init(bin_file.allocator);406 var branch_stack = std.ArrayList(Branch).init(bin_file.allocator);
406 defer {407 defer {
...@@ -1925,7 +1926,8 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -1925,7 +1926,8 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
1925 else1926 else
1926 unreachable;1927 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();
1929 // First, push the return address, then jump; if noreturn, don't bother with the first step1931 // First, push the return address, then jump; if noreturn, don't bother with the first step
1930 // TODO: implement packed struct -> u16 at comptime and move the bitcast here1932 // TODO: implement packed struct -> u16 at comptime and move the bitcast here
1931 var instr = Instruction{ .condition = .always, .input0 = .immediate, .input1 = .zero, .modify_flags = false, .output = .jump, .command = .load16 };1933 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 {...@@ -190,8 +190,8 @@ pub const DeclGen = struct {
190 const decl = val.castTag(.decl_ref).?.data;190 const decl = val.castTag(.decl_ref).?.data;
191191
192 // Determine if we must pointer cast.192 // Determine if we must pointer cast.
193 const decl_tv = decl.typed_value.most_recent.typed_value;193 assert(decl.has_tv);
194 if (t.eql(decl_tv.ty)) {194 if (t.eql(decl.ty)) {
195 try writer.print("&{s}", .{decl.name});195 try writer.print("&{s}", .{decl.name});
196 } else {196 } else {
197 try writer.writeAll("(");197 try writer.writeAll("(");
...@@ -326,12 +326,11 @@ pub const DeclGen = struct {...@@ -326,12 +326,11 @@ pub const DeclGen = struct {
326 if (!is_global) {326 if (!is_global) {
327 try w.writeAll("static ");327 try w.writeAll("static ");
328 }328 }
329 const tv = dg.decl.typed_value.most_recent.typed_value;329 try dg.renderType(w, dg.decl.ty.fnReturnType());
330 try dg.renderType(w, tv.ty.fnReturnType());
331 const decl_name = mem.span(dg.decl.name);330 const decl_name = mem.span(dg.decl.name);
332 try w.print(" {s}(", .{decl_name});331 try w.print(" {s}(", .{decl_name});
333 const param_len = tv.ty.fnParamLen();332 const param_len = dg.decl.ty.fnParamLen();
334 const is_var_args = tv.ty.fnIsVarArgs();333 const is_var_args = dg.decl.ty.fnIsVarArgs();
335 if (param_len == 0 and !is_var_args)334 if (param_len == 0 and !is_var_args)
336 try w.writeAll("void")335 try w.writeAll("void")
337 else {336 else {
...@@ -340,7 +339,7 @@ pub const DeclGen = struct {...@@ -340,7 +339,7 @@ pub const DeclGen = struct {
340 if (index > 0) {339 if (index > 0) {
341 try w.writeAll(", ");340 try w.writeAll(", ");
342 }341 }
343 try dg.renderType(w, tv.ty.fnParamType(index));342 try dg.renderType(w, dg.decl.ty.fnParamType(index));
344 try w.print(" a{d}", .{index});343 try w.print(" a{d}", .{index});
345 }344 }
346 }345 }
...@@ -545,8 +544,10 @@ pub fn genDecl(o: *Object) !void {...@@ -545,8 +544,10 @@ pub fn genDecl(o: *Object) !void {
545 const tracy = trace(@src());544 const tracy = trace(@src());
546 defer tracy.end();545 defer tracy.end();
547546
548 const tv = o.dg.decl.typed_value.most_recent.typed_value;547 const tv: TypedValue = .{
549548 .ty = o.dg.decl.ty,
549 .val = o.dg.decl.val,
550 };
550 if (tv.val.castTag(.function)) |func_payload| {551 if (tv.val.castTag(.function)) |func_payload| {
551 const is_global = o.dg.functionIsGlobal(tv);552 const is_global = o.dg.functionIsGlobal(tv);
552 const fwd_decl_writer = o.dg.fwd_decl.writer();553 const fwd_decl_writer = o.dg.fwd_decl.writer();
...@@ -589,7 +590,10 @@ pub fn genHeader(dg: *DeclGen) error{ AnalysisFail, OutOfMemory }!void {...@@ -589,7 +590,10 @@ pub fn genHeader(dg: *DeclGen) error{ AnalysisFail, OutOfMemory }!void {
589 const tracy = trace(@src());590 const tracy = trace(@src());
590 defer tracy.end();591 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 };
593 const writer = dg.fwd_decl.writer();597 const writer = dg.fwd_decl.writer();
594598
595 switch (tv.ty.zigTypeTag()) {599 switch (tv.ty.zigTypeTag()) {
...@@ -842,7 +846,7 @@ fn genCall(o: *Object, inst: *Inst.Call) !CValue {...@@ -842,7 +846,7 @@ fn genCall(o: *Object, inst: *Inst.Call) !CValue {
842 else846 else
843 unreachable;847 unreachable;
844848
845 const fn_ty = fn_decl.typed_value.most_recent.typed_value.ty;849 const fn_ty = fn_decl.ty;
846 const ret_ty = fn_ty.fnReturnType();850 const ret_ty = fn_ty.fnReturnType();
847 const unused_result = inst.base.isUnused();851 const unused_result = inst.base.isUnused();
848 var result_local: CValue = .none;852 var result_local: CValue = .none;
src/codegen/llvm.zig+12-10
...@@ -325,17 +325,17 @@ pub const DeclGen = struct {...@@ -325,17 +325,17 @@ pub const DeclGen = struct {
325325
326 fn genDecl(self: *DeclGen) !void {326 fn genDecl(self: *DeclGen) !void {
327 const decl = self.decl;327 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| {
333 const func = func_payload.data;333 const func = func_payload.data;
334334
335 const llvm_func = try self.resolveLLVMFunction(func.owner_decl);335 const llvm_func = try self.resolveLLVMFunction(func.owner_decl);
336336
337 // This gets the LLVM values from the function and stores them in `self.args`.337 // 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();
339 var args = try self.gpa.alloc(*const llvm.Value, fn_param_len);339 var args = try self.gpa.alloc(*const llvm.Value, fn_param_len);
340340
341 for (args) |*arg, i| {341 for (args) |*arg, i| {
...@@ -368,7 +368,7 @@ pub const DeclGen = struct {...@@ -368,7 +368,7 @@ pub const DeclGen = struct {
368 defer fg.deinit();368 defer fg.deinit();
369369
370 try fg.genBody(func.body);370 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| {
372 _ = try self.resolveLLVMFunction(extern_fn.data);372 _ = try self.resolveLLVMFunction(extern_fn.data);
373 } else {373 } else {
374 _ = try self.resolveGlobalDecl(decl);374 _ = try self.resolveGlobalDecl(decl);
...@@ -380,7 +380,8 @@ pub const DeclGen = struct {...@@ -380,7 +380,8 @@ pub const DeclGen = struct {
380 // TODO: do we want to store this in our own datastructure?380 // TODO: do we want to store this in our own datastructure?
381 if (self.llvmModule().getNamedFunction(func.name)) |llvm_fn| return llvm_fn;381 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;
384 const return_type = zig_fn_type.fnReturnType();385 const return_type = zig_fn_type.fnReturnType();
385386
386 const fn_param_len = zig_fn_type.fnParamLen();387 const fn_param_len = zig_fn_type.fnParamLen();
...@@ -415,11 +416,11 @@ pub const DeclGen = struct {...@@ -415,11 +416,11 @@ pub const DeclGen = struct {
415 // TODO: do we want to store this in our own datastructure?416 // TODO: do we want to store this in our own datastructure?
416 if (self.llvmModule().getNamedGlobal(decl.name)) |val| return val;417 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
420 // TODO: remove this redundant `getLLVMType`, it is also called in `genTypedValue`.421 // TODO: remove this redundant `getLLVMType`, it is also called in `genTypedValue`.
421 const llvm_type = try self.getLLVMType(typed_value.ty);422 const llvm_type = try self.getLLVMType(decl.ty);
422 const val = try self.genTypedValue(typed_value, null);423 const val = try self.genTypedValue(.{ .ty = decl.ty, .val = decl.val }, null);
423 const global = self.llvmModule().addGlobal(llvm_type, decl.name);424 const global = self.llvmModule().addGlobal(llvm_type, decl.name);
424 llvm.setInitializer(global, val);425 llvm.setInitializer(global, val);
425426
...@@ -688,7 +689,8 @@ pub const FuncGen = struct {...@@ -688,7 +689,8 @@ pub const FuncGen = struct {
688 else689 else
689 unreachable;690 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;
692 const llvm_fn = try self.dg.resolveLLVMFunction(fn_decl);694 const llvm_fn = try self.dg.resolveLLVMFunction(fn_decl);
693695
694 const num_args = inst.args.len;696 const num_args = inst.args.len;
src/codegen/wasm.zig+2-1
...@@ -591,7 +591,8 @@ pub const Context = struct {...@@ -591,7 +591,8 @@ pub const Context = struct {
591 }591 }
592592
593 fn genFunctype(self: *Context) InnerError!void {593 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;
595 const writer = self.func_type_data.writer();596 const writer = self.func_type_data.writer();
596597
597 try writer.writeByte(wasm.function_type);598 try writer.writeByte(wasm.function_type);
src/link.zig+3
...@@ -300,6 +300,7 @@ pub const File = struct {...@@ -300,6 +300,7 @@ pub const File = struct {
300 /// May be called before or after updateDeclExports but must be called300 /// May be called before or after updateDeclExports but must be called
301 /// after allocateDeclIndexes for any given Decl.301 /// after allocateDeclIndexes for any given Decl.
302 pub fn updateDecl(base: *File, module: *Module, decl: *Module.Decl) !void {302 pub fn updateDecl(base: *File, module: *Module, decl: *Module.Decl) !void {
303 assert(decl.has_tv);
303 switch (base.tag) {304 switch (base.tag) {
304 .coff => return @fieldParentPtr(Coff, "base", base).updateDecl(module, decl),305 .coff => return @fieldParentPtr(Coff, "base", base).updateDecl(module, decl),
305 .elf => return @fieldParentPtr(Elf, "base", base).updateDecl(module, decl),306 .elf => return @fieldParentPtr(Elf, "base", base).updateDecl(module, decl),
...@@ -311,6 +312,7 @@ pub const File = struct {...@@ -311,6 +312,7 @@ pub const File = struct {
311 }312 }
312313
313 pub fn updateDeclLineNumber(base: *File, module: *Module, decl: *Module.Decl) !void {314 pub fn updateDeclLineNumber(base: *File, module: *Module, decl: *Module.Decl) !void {
315 assert(decl.has_tv);
314 switch (base.tag) {316 switch (base.tag) {
315 .coff => return @fieldParentPtr(Coff, "base", base).updateDeclLineNumber(module, decl),317 .coff => return @fieldParentPtr(Coff, "base", base).updateDeclLineNumber(module, decl),
316 .elf => return @fieldParentPtr(Elf, "base", base).updateDeclLineNumber(module, decl),318 .elf => return @fieldParentPtr(Elf, "base", base).updateDeclLineNumber(module, decl),
...@@ -461,6 +463,7 @@ pub const File = struct {...@@ -461,6 +463,7 @@ pub const File = struct {
461 decl: *Module.Decl,463 decl: *Module.Decl,
462 exports: []const *Module.Export,464 exports: []const *Module.Export,
463 ) !void {465 ) !void {
466 assert(decl.has_tv);
464 switch (base.tag) {467 switch (base.tag) {
465 .coff => return @fieldParentPtr(Coff, "base", base).updateDeclExports(module, decl, exports),468 .coff => return @fieldParentPtr(Coff, "base", base).updateDeclExports(module, decl, exports),
466 .elf => return @fieldParentPtr(Elf, "base", base).updateDeclExports(module, decl, exports),469 .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 {...@@ -206,34 +206,30 @@ pub fn flushModule(self: *C, comp: *Compilation) !void {
206 // generate, rather than querying here, be faster?206 // generate, rather than querying here, be faster?
207 for (self.decl_table.items()) |kv| {207 for (self.decl_table.items()) |kv| {
208 const decl = kv.key;208 const decl = kv.key;
209 switch (decl.typed_value) {209 if (!decl.has_tv) continue;
210 .most_recent => |tvm| {210 const buf = buf: {
211 const buf = buf: {211 if (decl.val.castTag(.function)) |_| {
212 if (tvm.typed_value.val.castTag(.function)) |_| {212 var it = decl.fn_link.c.typedefs.iterator();
213 var it = decl.fn_link.c.typedefs.iterator();213 while (it.next()) |new| {
214 while (it.next()) |new| {214 if (typedefs.get(new.key)) |previous| {
215 if (typedefs.get(new.key)) |previous| {215 try err_typedef_writer.print("typedef {s} {s};\n", .{ previous, new.value.name });
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;
225 } else {216 } 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);
227 }220 }
228 };221 }
229 all_buffers.appendAssumeCapacity(.{222 fn_count += 1;
230 .iov_base = buf.ptr,223 break :buf decl.fn_link.c.fwd_decl.items;
231 .iov_len = buf.len,224 } else {
232 });225 break :buf decl.link.c.code.items;
233 file_size += buf.len;226 }
234 },227 };
235 .never_succeeded => continue,228 all_buffers.appendAssumeCapacity(.{
236 }229 .iov_base = buf.ptr,
230 .iov_len = buf.len,
231 });
232 file_size += buf.len;
237 }233 }
238234
239 err_typedef_item.* = .{235 err_typedef_item.* = .{
...@@ -246,18 +242,14 @@ pub fn flushModule(self: *C, comp: *Compilation) !void {...@@ -246,18 +242,14 @@ pub fn flushModule(self: *C, comp: *Compilation) !void {
246 try all_buffers.ensureCapacity(all_buffers.items.len + fn_count);242 try all_buffers.ensureCapacity(all_buffers.items.len + fn_count);
247 for (self.decl_table.items()) |kv| {243 for (self.decl_table.items()) |kv| {
248 const decl = kv.key;244 const decl = kv.key;
249 switch (decl.typed_value) {245 if (!decl.has_tv) continue;
250 .most_recent => |tvm| {246 if (decl.val.castTag(.function)) |_| {
251 if (tvm.typed_value.val.castTag(.function)) |_| {247 const buf = decl.link.c.code.items;
252 const buf = decl.link.c.code.items;248 all_buffers.appendAssumeCapacity(.{
253 all_buffers.appendAssumeCapacity(.{249 .iov_base = buf.ptr,
254 .iov_base = buf.ptr,250 .iov_len = buf.len,
255 .iov_len = buf.len,251 });
256 });252 file_size += buf.len;
257 file_size += buf.len;
258 }
259 },
260 .never_succeeded => continue,
261 }253 }
262 }254 }
263255
src/link/Coff.zig+6-4
...@@ -662,15 +662,17 @@ pub fn updateDecl(self: *Coff, module: *Module, decl: *Module.Decl) !void {...@@ -662,15 +662,17 @@ pub fn updateDecl(self: *Coff, module: *Module, decl: *Module.Decl) !void {
662 if (build_options.have_llvm)662 if (build_options.have_llvm)
663 if (self.llvm_object) |llvm_object| return try llvm_object.updateDecl(module, decl);663 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;665 if (decl.val.tag() == .extern_fn) {
666 if (typed_value.val.tag() == .extern_fn) {
667 return; // TODO Should we do more when front-end analyzed extern decl?666 return; // TODO Should we do more when front-end analyzed extern decl?
668 }667 }
669668
670 var code_buffer = std.ArrayList(u8).init(self.base.allocator);669 var code_buffer = std.ArrayList(u8).init(self.base.allocator);
671 defer code_buffer.deinit();670 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);
674 const code = switch (res) {676 const code = switch (res) {
675 .externally_managed => |x| x,677 .externally_managed => |x| x,
676 .appended => code_buffer.items,678 .appended => code_buffer.items,
...@@ -681,7 +683,7 @@ pub fn updateDecl(self: *Coff, module: *Module, decl: *Module.Decl) !void {...@@ -681,7 +683,7 @@ pub fn updateDecl(self: *Coff, module: *Module, decl: *Module.Decl) !void {
681 },683 },
682 };684 };
683685
684 const required_alignment = typed_value.ty.abiAlignment(self.base.options.target);686 const required_alignment = decl.ty.abiAlignment(self.base.options.target);
685 const curr_size = decl.link.coff.size;687 const curr_size = decl.link.coff.size;
686 if (curr_size != 0) {688 if (curr_size != 0) {
687 const capacity = decl.link.coff.capacity();689 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 {...@@ -2191,8 +2191,7 @@ pub fn updateDecl(self: *Elf, module: *Module, decl: *Module.Decl) !void {
2191 if (build_options.have_llvm)2191 if (build_options.have_llvm)
2192 if (self.llvm_object) |llvm_object| return try llvm_object.updateDecl(module, decl);2192 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;2194 if (decl.val.tag() == .extern_fn) {
2195 if (typed_value.val.tag() == .extern_fn) {
2196 return; // TODO Should we do more when front-end analyzed extern decl?2195 return; // TODO Should we do more when front-end analyzed extern decl?
2197 }2196 }
21982197
...@@ -2214,7 +2213,7 @@ pub fn updateDecl(self: *Elf, module: *Module, decl: *Module.Decl) !void {...@@ -2214,7 +2213,7 @@ pub fn updateDecl(self: *Elf, module: *Module, decl: *Module.Decl) !void {
2214 dbg_info_type_relocs.deinit(self.base.allocator);2213 dbg_info_type_relocs.deinit(self.base.allocator);
2215 }2214 }
22162215
2217 const is_fn: bool = switch (typed_value.ty.zigTypeTag()) {2216 const is_fn: bool = switch (decl.ty.zigTypeTag()) {
2218 .Fn => true,2217 .Fn => true,
2219 else => false,2218 else => false,
2220 };2219 };
...@@ -2270,7 +2269,7 @@ pub fn updateDecl(self: *Elf, module: *Module, decl: *Module.Decl) !void {...@@ -2270,7 +2269,7 @@ pub fn updateDecl(self: *Elf, module: *Module, decl: *Module.Decl) !void {
2270 const decl_name_with_null = decl.name[0 .. mem.lenZ(decl.name) + 1];2269 const decl_name_with_null = decl.name[0 .. mem.lenZ(decl.name) + 1];
2271 try dbg_info_buffer.ensureCapacity(dbg_info_buffer.items.len + 25 + decl_name_with_null.len);2270 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();
2274 const fn_ret_has_bits = fn_ret_type.hasCodeGenBits();2273 const fn_ret_has_bits = fn_ret_type.hasCodeGenBits();
2275 if (fn_ret_has_bits) {2274 if (fn_ret_has_bits) {
2276 dbg_info_buffer.appendAssumeCapacity(abbrev_subprogram);2275 dbg_info_buffer.appendAssumeCapacity(abbrev_subprogram);
...@@ -2299,7 +2298,10 @@ pub fn updateDecl(self: *Elf, module: *Module, decl: *Module.Decl) !void {...@@ -2299,7 +2298,10 @@ pub fn updateDecl(self: *Elf, module: *Module, decl: *Module.Decl) !void {
2299 } else {2298 } else {
2300 // TODO implement .debug_info for global variables2299 // TODO implement .debug_info for global variables
2301 }2300 }
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, .{
2303 .dwarf = .{2305 .dwarf = .{
2304 .dbg_line = &dbg_line_buffer,2306 .dbg_line = &dbg_line_buffer,
2305 .dbg_info = &dbg_info_buffer,2307 .dbg_info = &dbg_info_buffer,
...@@ -2316,7 +2318,7 @@ pub fn updateDecl(self: *Elf, module: *Module, decl: *Module.Decl) !void {...@@ -2316,7 +2318,7 @@ pub fn updateDecl(self: *Elf, module: *Module, decl: *Module.Decl) !void {
2316 },2318 },
2317 };2319 };
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
2321 const stt_bits: u8 = if (is_fn) elf.STT_FUNC else elf.STT_OBJECT;2323 const stt_bits: u8 = if (is_fn) elf.STT_FUNC else elf.STT_OBJECT;
23222324
...@@ -2678,7 +2680,6 @@ pub fn updateDeclExports(...@@ -2678,7 +2680,6 @@ pub fn updateDeclExports(
2678 defer tracy.end();2680 defer tracy.end();
26792681
2680 try self.global_symbols.ensureCapacity(self.base.allocator, self.global_symbols.items.len + exports.len);2682 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;
2682 if (decl.link.elf.local_sym_index == 0) return;2683 if (decl.link.elf.local_sym_index == 0) return;
2683 const decl_sym = self.local_symbols.items[decl.link.elf.local_sym_index];2684 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 {...@@ -1138,8 +1138,7 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void {
1138 const tracy = trace(@src());1138 const tracy = trace(@src());
1139 defer tracy.end();1139 defer tracy.end();
11401140
1141 const typed_value = decl.typed_value.most_recent.typed_value;1141 if (decl.val.tag() == .extern_fn) {
1142 if (typed_value.val.tag() == .extern_fn) {
1143 return; // TODO Should we do more when front-end analyzed extern decl?1142 return; // TODO Should we do more when front-end analyzed extern decl?
1144 }1143 }
11451144
...@@ -1160,7 +1159,10 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void {...@@ -1160,7 +1159,10 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void {
1160 }1159 }
11611160
1162 const res = if (debug_buffers) |*dbg|1161 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, .{
1164 .dwarf = .{1166 .dwarf = .{
1165 .dbg_line = &dbg.dbg_line_buffer,1167 .dbg_line = &dbg.dbg_line_buffer,
1166 .dbg_info = &dbg.dbg_info_buffer,1168 .dbg_info = &dbg.dbg_info_buffer,
...@@ -1168,7 +1170,10 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void {...@@ -1168,7 +1170,10 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void {
1168 },1170 },
1169 })1171 })
1170 else1172 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
1173 const code = switch (res) {1178 const code = switch (res) {
1174 .externally_managed => |x| x,1179 .externally_managed => |x| x,
...@@ -1184,7 +1189,7 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void {...@@ -1184,7 +1189,7 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void {
1184 },1189 },
1185 };1190 };
11861191
1187 const required_alignment = typed_value.ty.abiAlignment(self.base.options.target);1192 const required_alignment = decl.ty.abiAlignment(self.base.options.target);
1188 assert(decl.link.macho.local_sym_index != 0); // Caller forgot to call allocateDeclIndexes()1193 assert(decl.link.macho.local_sym_index != 0); // Caller forgot to call allocateDeclIndexes()
1189 const symbol = &self.locals.items[decl.link.macho.local_sym_index];1194 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(...@@ -946,8 +946,8 @@ pub fn initDeclDebugBuffers(
946 var dbg_info_buffer = std.ArrayList(u8).init(allocator);946 var dbg_info_buffer = std.ArrayList(u8).init(allocator);
947 var dbg_info_type_relocs: link.File.DbgInfoTypeRelocsTable = .{};947 var dbg_info_type_relocs: link.File.DbgInfoTypeRelocsTable = .{};
948948
949 const typed_value = decl.typed_value.most_recent.typed_value;949 assert(decl.has_tv);
950 switch (typed_value.ty.zigTypeTag()) {950 switch (decl.ty.zigTypeTag()) {
951 .Fn => {951 .Fn => {
952 // For functions we need to add a prologue to the debug line program.952 // For functions we need to add a prologue to the debug line program.
953 try dbg_line_buffer.ensureCapacity(26);953 try dbg_line_buffer.ensureCapacity(26);
...@@ -999,7 +999,7 @@ pub fn initDeclDebugBuffers(...@@ -999,7 +999,7 @@ pub fn initDeclDebugBuffers(
999 const decl_name_with_null = decl.name[0 .. mem.lenZ(decl.name) + 1];999 const decl_name_with_null = decl.name[0 .. mem.lenZ(decl.name) + 1];
1000 try dbg_info_buffer.ensureCapacity(dbg_info_buffer.items.len + 27 + decl_name_with_null.len);1000 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();
1003 const fn_ret_has_bits = fn_ret_type.hasCodeGenBits();1003 const fn_ret_has_bits = fn_ret_type.hasCodeGenBits();
1004 if (fn_ret_has_bits) {1004 if (fn_ret_has_bits) {
1005 dbg_info_buffer.appendAssumeCapacity(abbrev_subprogram);1005 dbg_info_buffer.appendAssumeCapacity(abbrev_subprogram);
...@@ -1058,8 +1058,8 @@ pub fn commitDeclDebugInfo(...@@ -1058,8 +1058,8 @@ pub fn commitDeclDebugInfo(
1058 const symbol = self.base.locals.items[decl.link.macho.local_sym_index];1058 const symbol = self.base.locals.items[decl.link.macho.local_sym_index];
1059 const text_block = &decl.link.macho;1059 const text_block = &decl.link.macho;
1060 // If the Decl is a function, we need to update the __debug_line program.1060 // 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;1061 assert(decl.has_tv);
1062 switch (typed_value.ty.zigTypeTag()) {1062 switch (decl.ty.zigTypeTag()) {
1063 .Fn => {1063 .Fn => {
1064 // Perform the relocations based on vaddr.1064 // Perform the relocations based on vaddr.
1065 {1065 {
src/link/SpirV.zig+3-7
...@@ -179,13 +179,9 @@ pub fn flushModule(self: *SpirV, comp: *Compilation) !void {...@@ -179,13 +179,9 @@ pub fn flushModule(self: *SpirV, comp: *Compilation) !void {
179179
180 for (self.decl_table.items()) |entry| {180 for (self.decl_table.items()) |entry| {
181 const decl = entry.key;181 const decl = entry.key;
182 switch (decl.typed_value) {182 if (!decl.has_tv) continue;
183 .most_recent => |tvm| {183 const fn_data = &decl.fn_link.spirv;
184 const fn_data = &decl.fn_link.spirv;184 all_buffers.appendAssumeCapacity(wordsToIovConst(fn_data.code.items));
185 all_buffers.appendAssumeCapacity(wordsToIovConst(fn_data.code.items));
186 },
187 .never_succeeded => continue,
188 }
189 }185 }
190186
191 var file_size: u64 = 0;187 var file_size: u64 = 0;
src/link/Wasm.zig+7-9
...@@ -175,9 +175,8 @@ pub fn allocateDeclIndexes(self: *Wasm, decl: *Module.Decl) !void {...@@ -175,9 +175,8 @@ pub fn allocateDeclIndexes(self: *Wasm, decl: *Module.Decl) !void {
175175
176 self.offset_table.items[block.offset_index] = 0;176 self.offset_table.items[block.offset_index] = 0;
177177
178 const typed_value = decl.typed_value.most_recent.typed_value;178 if (decl.ty.zigTypeTag() == .Fn) {
179 if (typed_value.ty.zigTypeTag() == .Fn) {179 switch (decl.val.tag()) {
180 switch (typed_value.val.tag()) {
181 // dependent on function type, appends it to the correct list180 // dependent on function type, appends it to the correct list
182 .function => try self.funcs.append(self.base.allocator, decl),181 .function => try self.funcs.append(self.base.allocator, decl),
183 .extern_fn => try self.ext_funcs.append(self.base.allocator, decl),182 .extern_fn => try self.ext_funcs.append(self.base.allocator, decl),
...@@ -191,7 +190,6 @@ pub fn allocateDeclIndexes(self: *Wasm, decl: *Module.Decl) !void {...@@ -191,7 +190,6 @@ pub fn allocateDeclIndexes(self: *Wasm, decl: *Module.Decl) !void {
191pub fn updateDecl(self: *Wasm, module: *Module, decl: *Module.Decl) !void {190pub fn updateDecl(self: *Wasm, module: *Module, decl: *Module.Decl) !void {
192 std.debug.assert(decl.link.wasm.init); // Must call allocateDeclIndexes()191 std.debug.assert(decl.link.wasm.init); // Must call allocateDeclIndexes()
193192
194 const typed_value = decl.typed_value.most_recent.typed_value;
195 const fn_data = &decl.fn_link.wasm;193 const fn_data = &decl.fn_link.wasm;
196 fn_data.functype.items.len = 0;194 fn_data.functype.items.len = 0;
197 fn_data.code.items.len = 0;195 fn_data.code.items.len = 0;
...@@ -210,7 +208,7 @@ pub fn updateDecl(self: *Wasm, module: *Module, decl: *Module.Decl) !void {...@@ -210,7 +208,7 @@ pub fn updateDecl(self: *Wasm, module: *Module, decl: *Module.Decl) !void {
210 defer context.deinit();208 defer context.deinit();
211209
212 // generate the 'code' section for the function declaration210 // 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) {
214 error.CodegenFail => {212 error.CodegenFail => {
215 decl.analysis = .codegen_failure;213 decl.analysis = .codegen_failure;
216 try module.failed_decls.put(module.gpa, decl, context.err_msg);214 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 {...@@ -228,7 +226,7 @@ pub fn updateDecl(self: *Wasm, module: *Module, decl: *Module.Decl) !void {
228 fn_data.functype = context.func_type_data.toUnmanaged();226 fn_data.functype = context.func_type_data.toUnmanaged();
229227
230 const block = &decl.link.wasm;228 const block = &decl.link.wasm;
231 if (typed_value.ty.zigTypeTag() == .Fn) {229 if (decl.ty.zigTypeTag() == .Fn) {
232 // as locals are patched afterwards, the offsets of funcidx's are off,230 // as locals are patched afterwards, the offsets of funcidx's are off,
233 // here we update them to correct them231 // here we update them to correct them
234 for (fn_data.idx_refs.items) |*func| {232 for (fn_data.idx_refs.items) |*func| {
...@@ -262,7 +260,7 @@ pub fn updateDeclExports(...@@ -262,7 +260,7 @@ pub fn updateDeclExports(
262260
263pub fn freeDecl(self: *Wasm, decl: *Module.Decl) void {261pub fn freeDecl(self: *Wasm, decl: *Module.Decl) void {
264 if (self.getFuncidx(decl)) |func_idx| {262 if (self.getFuncidx(decl)) |func_idx| {
265 switch (decl.typed_value.most_recent.typed_value.val.tag()) {263 switch (decl.val.tag()) {
266 .function => _ = self.funcs.swapRemove(func_idx),264 .function => _ = self.funcs.swapRemove(func_idx),
267 .extern_fn => _ = self.ext_funcs.swapRemove(func_idx),265 .extern_fn => _ = self.ext_funcs.swapRemove(func_idx),
268 else => unreachable,266 else => unreachable,
...@@ -429,7 +427,7 @@ pub fn flushModule(self: *Wasm, comp: *Compilation) !void {...@@ -429,7 +427,7 @@ pub fn flushModule(self: *Wasm, comp: *Compilation) !void {
429 try leb.writeULEB128(writer, @intCast(u32, exprt.options.name.len));427 try leb.writeULEB128(writer, @intCast(u32, exprt.options.name.len));
430 try writer.writeAll(exprt.options.name);428 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()) {
433 .Fn => {431 .Fn => {
434 // Type of the export432 // Type of the export
435 try writer.writeByte(wasm.externalKind(.function));433 try writer.writeByte(wasm.externalKind(.function));
...@@ -802,7 +800,7 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation) !void {...@@ -802,7 +800,7 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation) !void {
802/// TODO: we could maintain a hash map to potentially make this simpler800/// TODO: we could maintain a hash map to potentially make this simpler
803fn getFuncidx(self: Wasm, decl: *Module.Decl) ?u32 {801fn getFuncidx(self: Wasm, decl: *Module.Decl) ?u32 {
804 var offset: u32 = 0;802 var offset: u32 = 0;
805 const slice = switch (decl.typed_value.most_recent.typed_value.val.tag()) {803 const slice = switch (decl.val.tag()) {
806 .function => blk: {804 .function => blk: {
807 // when the target is a regular function, we have to calculate805 // when the target is a regular function, we have to calculate
808 // the offset of where the index starts806 // the offset of where the index starts