authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-06-17 04:29:54-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-06-18 17:12:56-04:00
log7e58c56ca72099f6e71752289be7165947bfaa04
treed4b5def4b5fd17caba14e88f5bdc3673449e8fdd
parentb4eac0414a01b1096e8dd7e89455db88f19789cf

self-hosted: implement Decl lookup

* Take advantage of coercing anonymous struct literals to struct types. * Reworks Module to favor Zig source as the primary use case. Breaks ZIR compilation, which will have to be restored in a future commit. * Decl uses src_index rather then src, pointing to an AST Decl node index, or ZIR Module Decl index, rather than a byte offset. * ZIR instructions have an `analyzed_inst` field instead of Module having a hash table. * Module.Fn loses the `fn_type` field since it is redundant with its `owner_decl` `TypedValue` type. * Implement Type and Value copying. A ZIR Const instruction's TypedValue is copied to the Decl arena during analysis, which allows freeing the ZIR text instructions post-analysis. * Don't flush the ELF file if there are compilation errors. * Function return types allow arbitrarily complex expressions. * AST->ZIR for function calls and return statements.

10 files changed, 867 insertions(+), 430 deletions(-)

lib/std/zig/ast.zig+2
...@@ -2260,6 +2260,8 @@ pub const Node = struct {...@@ -2260,6 +2260,8 @@ pub const Node = struct {
2260 }2260 }
2261 };2261 };
22622262
2263 /// TODO break this into separate Break, Continue, Return AST Nodes to save memory.
2264 /// Could be further broken into LabeledBreak, LabeledContinue, and ReturnVoid to save even more.
2263 pub const ControlFlowExpression = struct {2265 pub const ControlFlowExpression = struct {
2264 base: Node = Node{ .id = .ControlFlowExpression },2266 base: Node = Node{ .id = .ControlFlowExpression },
2265 ltoken: TokenIndex,2267 ltoken: TokenIndex,
src-self-hosted/Module.zig+543-407
...@@ -37,10 +37,10 @@ decl_exports: std.AutoHashMap(*Decl, []*Export),...@@ -37,10 +37,10 @@ decl_exports: std.AutoHashMap(*Decl, []*Export),
37/// This table owns the Export memory.37/// This table owns the Export memory.
38export_owners: std.AutoHashMap(*Decl, []*Export),38export_owners: std.AutoHashMap(*Decl, []*Export),
39/// Maps fully qualified namespaced names to the Decl struct for them.39/// Maps fully qualified namespaced names to the Decl struct for them.
40decl_table: std.AutoHashMap(Decl.Hash, *Decl),40decl_table: std.AutoHashMap(Scope.NameHash, *Decl),
4141
42optimize_mode: std.builtin.Mode,42optimize_mode: std.builtin.Mode,
43link_error_flags: link.ElfFile.ErrorFlags = link.ElfFile.ErrorFlags{},43link_error_flags: link.ElfFile.ErrorFlags = .{},
4444
45work_queue: std.fifo.LinearFifo(WorkItem, .Dynamic),45work_queue: std.fifo.LinearFifo(WorkItem, .Dynamic),
4646
...@@ -64,20 +64,15 @@ generation: u32 = 0,...@@ -64,20 +64,15 @@ generation: u32 = 0,
6464
65/// Candidates for deletion. After a semantic analysis update completes, this list65/// Candidates for deletion. After a semantic analysis update completes, this list
66/// contains Decls that need to be deleted if they end up having no references to them.66/// contains Decls that need to be deleted if they end up having no references to them.
67deletion_set: std.ArrayListUnmanaged(*Decl) = std.ArrayListUnmanaged(*Decl){},67deletion_set: std.ArrayListUnmanaged(*Decl) = .{},
6868
69const WorkItem = union(enum) {69const WorkItem = union(enum) {
70 /// Write the machine code for a Decl to the output file.70 /// Write the machine code for a Decl to the output file.
71 codegen_decl: *Decl,71 codegen_decl: *Decl,
72 /// Decl has been determined to be outdated; perform semantic analysis again.72 /// Decl has been determined to be outdated; perform semantic analysis again.
73 re_analyze_decl: *Decl,73 re_analyze_decl: *Decl,
74 /// This AST node needs to be converted to a Decl and then semantically analyzed.74 /// The Decl needs to be analyzed and possibly export itself.
75 ast_gen_decl: AstGenDecl,75 analyze_decl: *Decl,
76
77 const AstGenDecl = struct {
78 ast_node: *ast.Node,
79 scope: *Scope,
80 };
81};76};
8277
83pub const Export = struct {78pub const Export = struct {
...@@ -111,9 +106,9 @@ pub const Decl = struct {...@@ -111,9 +106,9 @@ pub const Decl = struct {
111 /// The direct parent container of the Decl. This is either a `Scope.File` or `Scope.ZIRModule`.106 /// The direct parent container of the Decl. This is either a `Scope.File` or `Scope.ZIRModule`.
112 /// Reference to externally owned memory.107 /// Reference to externally owned memory.
113 scope: *Scope,108 scope: *Scope,
114 /// Byte offset into the source file that contains this declaration.109 /// The AST Node decl index or ZIR Inst index that contains this declaration.
115 /// This is the base offset that src offsets within this Decl are relative to.110 /// Must be recomputed when the corresponding source file is modified.
116 src: usize,111 src_index: usize,
117 /// The most recent value of the Decl after a successful semantic analysis.112 /// The most recent value of the Decl after a successful semantic analysis.
118 typed_value: union(enum) {113 typed_value: union(enum) {
119 never_succeeded: void,114 never_succeeded: void,
...@@ -124,6 +119,9 @@ pub const Decl = struct {...@@ -124,6 +119,9 @@ pub const Decl = struct {
124 /// analysis of the function body is performed with this value set to `success`. Functions119 /// analysis of the function body is performed with this value set to `success`. Functions
125 /// have their own analysis status field.120 /// have their own analysis status field.
126 analysis: enum {121 analysis: enum {
122 /// This Decl corresponds to an AST Node that has not been referenced yet, and therefore
123 /// because of Zig's lazy declaration analysis, it will remain unanalyzed until referenced.
124 unreferenced,
127 /// Semantic analysis for this Decl is running right now. This state detects dependency loops.125 /// Semantic analysis for this Decl is running right now. This state detects dependency loops.
128 in_progress,126 in_progress,
129 /// This Decl might be OK but it depends on another one which did not successfully complete127 /// This Decl might be OK but it depends on another one which did not successfully complete
...@@ -133,6 +131,10 @@ pub const Decl = struct {...@@ -133,6 +131,10 @@ pub const Decl = struct {
133 /// There will be a corresponding ErrorMsg in Module.failed_decls.131 /// There will be a corresponding ErrorMsg in Module.failed_decls.
134 sema_failure,132 sema_failure,
135 /// There will be a corresponding ErrorMsg in Module.failed_decls.133 /// There will be a corresponding ErrorMsg in Module.failed_decls.
134 /// This indicates the failure was something like running out of disk space,
135 /// and attempting semantic analysis again may succeed.
136 sema_failure_retryable,
137 /// There will be a corresponding ErrorMsg in Module.failed_decls.
136 codegen_failure,138 codegen_failure,
137 /// There will be a corresponding ErrorMsg in Module.failed_decls.139 /// There will be a corresponding ErrorMsg in Module.failed_decls.
138 /// This indicates the failure was something like running out of disk space,140 /// This indicates the failure was something like running out of disk space,
...@@ -158,7 +160,7 @@ pub const Decl = struct {...@@ -158,7 +160,7 @@ pub const Decl = struct {
158 /// This is populated regardless of semantic analysis and code generation.160 /// This is populated regardless of semantic analysis and code generation.
159 link: link.ElfFile.TextBlock = link.ElfFile.TextBlock.empty,161 link: link.ElfFile.TextBlock = link.ElfFile.TextBlock.empty,
160162
161 contents_hash: Hash,163 contents_hash: std.zig.SrcHash,
162164
163 /// The shallow set of other decls whose typed_value could possibly change if this Decl's165 /// The shallow set of other decls whose typed_value could possibly change if this Decl's
164 /// typed_value is modified.166 /// typed_value is modified.
...@@ -177,19 +179,28 @@ pub const Decl = struct {...@@ -177,19 +179,28 @@ pub const Decl = struct {
177 allocator.destroy(self);179 allocator.destroy(self);
178 }180 }
179181
180 pub const Hash = [16]u8;182 pub fn src(self: Decl) usize {
181183 switch (self.scope.tag) {
182 pub fn hashSimpleName(name: []const u8) Hash {184 .file => {
183 return std.zig.hashSrc(name);185 const file = @fieldParentPtr(Scope.File, "base", self.scope);
186 const tree = file.contents.tree;
187 const decl_node = tree.root_node.decls()[self.src_index];
188 return tree.token_locs[decl_node.firstToken()].start;
189 },
190 .zir_module => {
191 const zir_module = @fieldParentPtr(Scope.ZIRModule, "base", self.scope);
192 const module = zir_module.contents.module;
193 const decl_inst = module.decls[self.src_index];
194 return decl_inst.src;
195 },
196 .block => unreachable,
197 .gen_zir => unreachable,
198 .decl => unreachable,
199 }
184 }200 }
185201
186 /// Must generate unique bytes with no collisions with other decls.202 pub fn fullyQualifiedNameHash(self: Decl) Scope.NameHash {
187 /// The point of hashing here is only to limit the number of bytes of203 return self.scope.fullyQualifiedNameHash(mem.spanZ(self.name));
188 /// the unique identifier to a fixed size (16 bytes).
189 pub fn fullyQualifiedNameHash(self: Decl) Hash {
190 // Right now we only have ZIRModule as the source. So this is simply the
191 // relative name of the decl.
192 return hashSimpleName(mem.spanZ(self.name));
193 }204 }
194205
195 pub fn typedValue(self: *Decl) error{AnalysisFail}!TypedValue {206 pub fn typedValue(self: *Decl) error{AnalysisFail}!TypedValue {
...@@ -247,11 +258,9 @@ pub const Decl = struct {...@@ -247,11 +258,9 @@ pub const Decl = struct {
247/// Fn struct memory is owned by the Decl's TypedValue.Managed arena allocator.258/// Fn struct memory is owned by the Decl's TypedValue.Managed arena allocator.
248pub const Fn = struct {259pub const Fn = struct {
249 /// This memory owned by the Decl's TypedValue.Managed arena allocator.260 /// This memory owned by the Decl's TypedValue.Managed arena allocator.
250 fn_type: Type,
251 analysis: union(enum) {261 analysis: union(enum) {
252 /// The value is the source instruction.262 queued: *ZIR,
253 queued: *zir.Inst.Fn,263 in_progress,
254 in_progress: *Analysis,
255 /// There will be a corresponding ErrorMsg in Module.failed_decls264 /// There will be a corresponding ErrorMsg in Module.failed_decls
256 sema_failure,265 sema_failure,
257 /// This Fn might be OK but it depends on another Decl which did not successfully complete266 /// This Fn might be OK but it depends on another Decl which did not successfully complete
...@@ -265,16 +274,20 @@ pub const Fn = struct {...@@ -265,16 +274,20 @@ pub const Fn = struct {
265 /// of Fn analysis.274 /// of Fn analysis.
266 pub const Analysis = struct {275 pub const Analysis = struct {
267 inner_block: Scope.Block,276 inner_block: Scope.Block,
268 /// TODO Performance optimization idea: instead of this inst_table,277 };
269 /// use a field in the zir.Inst instead to track corresponding instructions278
270 inst_table: std.AutoHashMap(*zir.Inst, *Inst),279 /// Contains un-analyzed ZIR instructions generated from Zig source AST.
271 needed_inst_capacity: usize,280 pub const ZIR = struct {
281 body: zir.Module.Body,
282 arena: std.heap.ArenaAllocator.State,
272 };283 };
273};284};
274285
275pub const Scope = struct {286pub const Scope = struct {
276 tag: Tag,287 tag: Tag,
277288
289 pub const NameHash = [16]u8;
290
278 pub fn cast(base: *Scope, comptime T: type) ?*T {291 pub fn cast(base: *Scope, comptime T: type) ?*T {
279 if (base.tag != T.base_tag)292 if (base.tag != T.base_tag)
280 return null;293 return null;
...@@ -288,6 +301,7 @@ pub const Scope = struct {...@@ -288,6 +301,7 @@ pub const Scope = struct {
288 switch (self.tag) {301 switch (self.tag) {
289 .block => return self.cast(Block).?.arena,302 .block => return self.cast(Block).?.arena,
290 .decl => return &self.cast(DeclAnalysis).?.arena.allocator,303 .decl => return &self.cast(DeclAnalysis).?.arena.allocator,
304 .gen_zir => return &self.cast(GenZIR).?.arena.allocator,
291 .zir_module => return &self.cast(ZIRModule).?.contents.module.arena.allocator,305 .zir_module => return &self.cast(ZIRModule).?.contents.module.arena.allocator,
292 .file => unreachable,306 .file => unreachable,
293 }307 }
...@@ -298,6 +312,7 @@ pub const Scope = struct {...@@ -298,6 +312,7 @@ pub const Scope = struct {
298 pub fn decl(self: *Scope) ?*Decl {312 pub fn decl(self: *Scope) ?*Decl {
299 return switch (self.tag) {313 return switch (self.tag) {
300 .block => self.cast(Block).?.decl,314 .block => self.cast(Block).?.decl,
315 .gen_zir => self.cast(GenZIR).?.decl,
301 .decl => self.cast(DeclAnalysis).?.decl,316 .decl => self.cast(DeclAnalysis).?.decl,
302 .zir_module => null,317 .zir_module => null,
303 .file => null,318 .file => null,
...@@ -309,11 +324,25 @@ pub const Scope = struct {...@@ -309,11 +324,25 @@ pub const Scope = struct {
309 pub fn namespace(self: *Scope) *Scope {324 pub fn namespace(self: *Scope) *Scope {
310 switch (self.tag) {325 switch (self.tag) {
311 .block => return self.cast(Block).?.decl.scope,326 .block => return self.cast(Block).?.decl.scope,
327 .gen_zir => return self.cast(GenZIR).?.decl.scope,
312 .decl => return self.cast(DeclAnalysis).?.decl.scope,328 .decl => return self.cast(DeclAnalysis).?.decl.scope,
313 .zir_module, .file => return self,329 .zir_module, .file => return self,
314 }330 }
315 }331 }
316332
333 /// Must generate unique bytes with no collisions with other decls.
334 /// The point of hashing here is only to limit the number of bytes of
335 /// the unique identifier to a fixed size (16 bytes).
336 pub fn fullyQualifiedNameHash(self: *Scope, name: []const u8) NameHash {
337 switch (self.tag) {
338 .block => unreachable,
339 .gen_zir => unreachable,
340 .decl => unreachable,
341 .zir_module => return self.cast(ZIRModule).?.fullyQualifiedNameHash(name),
342 .file => return self.cast(File).?.fullyQualifiedNameHash(name),
343 }
344 }
345
317 /// Asserts the scope is a child of a File and has an AST tree and returns the tree.346 /// Asserts the scope is a child of a File and has an AST tree and returns the tree.
318 pub fn tree(self: *Scope) *ast.Tree {347 pub fn tree(self: *Scope) *ast.Tree {
319 switch (self.tag) {348 switch (self.tag) {
...@@ -321,6 +350,7 @@ pub const Scope = struct {...@@ -321,6 +350,7 @@ pub const Scope = struct {
321 .zir_module => unreachable,350 .zir_module => unreachable,
322 .decl => return self.cast(DeclAnalysis).?.decl.scope.cast(File).?.contents.tree,351 .decl => return self.cast(DeclAnalysis).?.decl.scope.cast(File).?.contents.tree,
323 .block => return self.cast(Block).?.decl.scope.cast(File).?.contents.tree,352 .block => return self.cast(Block).?.decl.scope.cast(File).?.contents.tree,
353 .gen_zir => return self.cast(GenZIR).?.decl.scope.cast(File).?.contents.tree,
324 }354 }
325 }355 }
326356
...@@ -343,6 +373,7 @@ pub const Scope = struct {...@@ -343,6 +373,7 @@ pub const Scope = struct {
343 .file => return @fieldParentPtr(File, "base", base).sub_file_path,373 .file => return @fieldParentPtr(File, "base", base).sub_file_path,
344 .zir_module => return @fieldParentPtr(ZIRModule, "base", base).sub_file_path,374 .zir_module => return @fieldParentPtr(ZIRModule, "base", base).sub_file_path,
345 .block => unreachable,375 .block => unreachable,
376 .gen_zir => unreachable,
346 .decl => unreachable,377 .decl => unreachable,
347 }378 }
348 }379 }
...@@ -352,6 +383,7 @@ pub const Scope = struct {...@@ -352,6 +383,7 @@ pub const Scope = struct {
352 .file => return @fieldParentPtr(File, "base", base).unload(allocator),383 .file => return @fieldParentPtr(File, "base", base).unload(allocator),
353 .zir_module => return @fieldParentPtr(ZIRModule, "base", base).unload(allocator),384 .zir_module => return @fieldParentPtr(ZIRModule, "base", base).unload(allocator),
354 .block => unreachable,385 .block => unreachable,
386 .gen_zir => unreachable,
355 .decl => unreachable,387 .decl => unreachable,
356 }388 }
357 }389 }
...@@ -360,6 +392,7 @@ pub const Scope = struct {...@@ -360,6 +392,7 @@ pub const Scope = struct {
360 switch (base.tag) {392 switch (base.tag) {
361 .file => return @fieldParentPtr(File, "base", base).getSource(module),393 .file => return @fieldParentPtr(File, "base", base).getSource(module),
362 .zir_module => return @fieldParentPtr(ZIRModule, "base", base).getSource(module),394 .zir_module => return @fieldParentPtr(ZIRModule, "base", base).getSource(module),
395 .gen_zir => unreachable,
363 .block => unreachable,396 .block => unreachable,
364 .decl => unreachable,397 .decl => unreachable,
365 }398 }
...@@ -379,6 +412,7 @@ pub const Scope = struct {...@@ -379,6 +412,7 @@ pub const Scope = struct {
379 allocator.destroy(scope_zir_module);412 allocator.destroy(scope_zir_module);
380 },413 },
381 .block => unreachable,414 .block => unreachable,
415 .gen_zir => unreachable,
382 .decl => unreachable,416 .decl => unreachable,
383 }417 }
384 }418 }
...@@ -390,6 +424,7 @@ pub const Scope = struct {...@@ -390,6 +424,7 @@ pub const Scope = struct {
390 file,424 file,
391 block,425 block,
392 decl,426 decl,
427 gen_zir,
393 };428 };
394429
395 pub const File = struct {430 pub const File = struct {
...@@ -461,6 +496,11 @@ pub const Scope = struct {...@@ -461,6 +496,11 @@ pub const Scope = struct {
461 .bytes => |bytes| return bytes,496 .bytes => |bytes| return bytes,
462 }497 }
463 }498 }
499
500 pub fn fullyQualifiedNameHash(self: *File, name: []const u8) NameHash {
501 // We don't have struct scopes yet so this is currently just a simple name hash.
502 return std.zig.hashSrc(name);
503 }
464 };504 };
465505
466 pub const ZIRModule = struct {506 pub const ZIRModule = struct {
...@@ -541,6 +581,11 @@ pub const Scope = struct {...@@ -541,6 +581,11 @@ pub const Scope = struct {
541 .bytes => |bytes| return bytes,581 .bytes => |bytes| return bytes,
542 }582 }
543 }583 }
584
585 pub fn fullyQualifiedNameHash(self: *ZIRModule, name: []const u8) NameHash {
586 // ZIR modules only have 1 file with all decls global in the same namespace.
587 return std.zig.hashSrc(name);
588 }
544 };589 };
545590
546 /// This is a temporary structure, references to it are valid only591 /// This is a temporary structure, references to it are valid only
...@@ -548,7 +593,7 @@ pub const Scope = struct {...@@ -548,7 +593,7 @@ pub const Scope = struct {
548 pub const Block = struct {593 pub const Block = struct {
549 pub const base_tag: Tag = .block;594 pub const base_tag: Tag = .block;
550 base: Scope = Scope{ .tag = base_tag },595 base: Scope = Scope{ .tag = base_tag },
551 func: *Fn,596 func: ?*Fn,
552 decl: *Decl,597 decl: *Decl,
553 instructions: ArrayListUnmanaged(*Inst),598 instructions: ArrayListUnmanaged(*Inst),
554 /// Points to the arena allocator of DeclAnalysis599 /// Points to the arena allocator of DeclAnalysis
...@@ -563,6 +608,16 @@ pub const Scope = struct {...@@ -563,6 +608,16 @@ pub const Scope = struct {
563 decl: *Decl,608 decl: *Decl,
564 arena: std.heap.ArenaAllocator,609 arena: std.heap.ArenaAllocator,
565 };610 };
611
612 /// This is a temporary structure, references to it are valid only
613 /// during semantic analysis of the decl.
614 pub const GenZIR = struct {
615 pub const base_tag: Tag = .gen_zir;
616 base: Scope = Scope{ .tag = base_tag },
617 decl: *Decl,
618 arena: std.heap.ArenaAllocator,
619 instructions: std.ArrayList(*zir.Inst),
620 };
566};621};
567622
568pub const Body = struct {623pub const Body = struct {
...@@ -656,7 +711,7 @@ pub fn init(gpa: *Allocator, options: InitOptions) !Module {...@@ -656,7 +711,7 @@ pub fn init(gpa: *Allocator, options: InitOptions) !Module {
656 .bin_file_path = options.bin_file_path,711 .bin_file_path = options.bin_file_path,
657 .bin_file = bin_file,712 .bin_file = bin_file,
658 .optimize_mode = options.optimize_mode,713 .optimize_mode = options.optimize_mode,
659 .decl_table = std.AutoHashMap(Decl.Hash, *Decl).init(gpa),714 .decl_table = std.AutoHashMap(Scope.NameHash, *Decl).init(gpa),
660 .decl_exports = std.AutoHashMap(*Decl, []*Export).init(gpa),715 .decl_exports = std.AutoHashMap(*Decl, []*Export).init(gpa),
661 .export_owners = std.AutoHashMap(*Decl, []*Export).init(gpa),716 .export_owners = std.AutoHashMap(*Decl, []*Export).init(gpa),
662 .failed_decls = std.AutoHashMap(*Decl, *ErrorMsg).init(gpa),717 .failed_decls = std.AutoHashMap(*Decl, *ErrorMsg).init(gpa),
...@@ -765,14 +820,14 @@ pub fn update(self: *Module) !void {...@@ -765,14 +820,14 @@ pub fn update(self: *Module) !void {
765 try self.deleteDecl(decl);820 try self.deleteDecl(decl);
766 }821 }
767822
823 self.link_error_flags = self.bin_file.error_flags;
824
768 // If there are any errors, we anticipate the source files being loaded825 // If there are any errors, we anticipate the source files being loaded
769 // to report error messages. Otherwise we unload all source files to save memory.826 // to report error messages. Otherwise we unload all source files to save memory.
770 if (self.totalErrorCount() == 0) {827 if (self.totalErrorCount() == 0) {
771 self.root_scope.unload(self.allocator);828 self.root_scope.unload(self.allocator);
829 try self.bin_file.flush();
772 }830 }
773
774 try self.bin_file.flush();
775 self.link_error_flags = self.bin_file.error_flags;
776}831}
777832
778/// Having the file open for writing is problematic as far as executing the833/// Having the file open for writing is problematic as far as executing the
...@@ -852,12 +907,14 @@ const InnerError = error{ OutOfMemory, AnalysisFail };...@@ -852,12 +907,14 @@ const InnerError = error{ OutOfMemory, AnalysisFail };
852pub fn performAllTheWork(self: *Module) error{OutOfMemory}!void {907pub fn performAllTheWork(self: *Module) error{OutOfMemory}!void {
853 while (self.work_queue.readItem()) |work_item| switch (work_item) {908 while (self.work_queue.readItem()) |work_item| switch (work_item) {
854 .codegen_decl => |decl| switch (decl.analysis) {909 .codegen_decl => |decl| switch (decl.analysis) {
910 .unreferenced => unreachable,
855 .in_progress => unreachable,911 .in_progress => unreachable,
856 .outdated => unreachable,912 .outdated => unreachable,
857913
858 .sema_failure,914 .sema_failure,
859 .codegen_failure,915 .codegen_failure,
860 .dependency_failure,916 .dependency_failure,
917 .sema_failure_retryable,
861 => continue,918 => continue,
862919
863 .complete, .codegen_failure_retryable => {920 .complete, .codegen_failure_retryable => {
...@@ -865,12 +922,10 @@ pub fn performAllTheWork(self: *Module) error{OutOfMemory}!void {...@@ -865,12 +922,10 @@ pub fn performAllTheWork(self: *Module) error{OutOfMemory}!void {
865 switch (payload.func.analysis) {922 switch (payload.func.analysis) {
866 .queued => self.analyzeFnBody(decl, payload.func) catch |err| switch (err) {923 .queued => self.analyzeFnBody(decl, payload.func) catch |err| switch (err) {
867 error.AnalysisFail => {924 error.AnalysisFail => {
868 if (payload.func.analysis == .queued) {925 assert(payload.func.analysis != .in_progress);
869 payload.func.analysis = .dependency_failure;
870 }
871 continue;926 continue;
872 },927 },
873 else => |e| return e,928 error.OutOfMemory => return error.OutOfMemory,
874 },929 },
875 .in_progress => unreachable,930 .in_progress => unreachable,
876 .sema_failure, .dependency_failure => continue,931 .sema_failure, .dependency_failure => continue,
...@@ -889,7 +944,7 @@ pub fn performAllTheWork(self: *Module) error{OutOfMemory}!void {...@@ -889,7 +944,7 @@ pub fn performAllTheWork(self: *Module) error{OutOfMemory}!void {
889 try self.failed_decls.ensureCapacity(self.failed_decls.size + 1);944 try self.failed_decls.ensureCapacity(self.failed_decls.size + 1);
890 self.failed_decls.putAssumeCapacityNoClobber(decl, try ErrorMsg.create(945 self.failed_decls.putAssumeCapacityNoClobber(decl, try ErrorMsg.create(
891 self.allocator,946 self.allocator,
892 decl.src,947 decl.src(),
893 "unable to codegen: {}",948 "unable to codegen: {}",
894 .{@errorName(err)},949 .{@errorName(err)},
895 ));950 ));
...@@ -899,6 +954,7 @@ pub fn performAllTheWork(self: *Module) error{OutOfMemory}!void {...@@ -899,6 +954,7 @@ pub fn performAllTheWork(self: *Module) error{OutOfMemory}!void {
899 },954 },
900 },955 },
901 .re_analyze_decl => |decl| switch (decl.analysis) {956 .re_analyze_decl => |decl| switch (decl.analysis) {
957 .unreferenced => unreachable,
902 .in_progress => unreachable,958 .in_progress => unreachable,
903959
904 .sema_failure,960 .sema_failure,
...@@ -906,6 +962,7 @@ pub fn performAllTheWork(self: *Module) error{OutOfMemory}!void {...@@ -906,6 +962,7 @@ pub fn performAllTheWork(self: *Module) error{OutOfMemory}!void {
906 .dependency_failure,962 .dependency_failure,
907 .complete,963 .complete,
908 .codegen_failure_retryable,964 .codegen_failure_retryable,
965 .sema_failure_retryable,
909 => continue,966 => continue,
910967
911 .outdated => {968 .outdated => {
...@@ -918,7 +975,7 @@ pub fn performAllTheWork(self: *Module) error{OutOfMemory}!void {...@@ -918,7 +975,7 @@ pub fn performAllTheWork(self: *Module) error{OutOfMemory}!void {
918 try self.failed_decls.ensureCapacity(self.failed_decls.size + 1);975 try self.failed_decls.ensureCapacity(self.failed_decls.size + 1);
919 self.failed_decls.putAssumeCapacityNoClobber(decl, try ErrorMsg.create(976 self.failed_decls.putAssumeCapacityNoClobber(decl, try ErrorMsg.create(
920 self.allocator,977 self.allocator,
921 decl.src,978 decl.src(),
922 "unable to load source file '{}': {}",979 "unable to load source file '{}': {}",
923 .{ zir_scope.sub_file_path, @errorName(err) },980 .{ zir_scope.sub_file_path, @errorName(err) },
924 ));981 ));
...@@ -929,7 +986,8 @@ pub fn performAllTheWork(self: *Module) error{OutOfMemory}!void {...@@ -929,7 +986,8 @@ pub fn performAllTheWork(self: *Module) error{OutOfMemory}!void {
929 const decl_name = mem.spanZ(decl.name);986 const decl_name = mem.spanZ(decl.name);
930 // We already detected deletions, so we know this will be found.987 // We already detected deletions, so we know this will be found.
931 const src_decl = zir_module.findDecl(decl_name).?;988 const src_decl = zir_module.findDecl(decl_name).?;
932 self.reAnalyzeDecl(decl, src_decl) catch |err| switch (err) {989 decl.src_index = src_decl.index;
990 self.reAnalyzeDecl(decl, src_decl.decl) catch |err| switch (err) {
933 error.OutOfMemory => return error.OutOfMemory,991 error.OutOfMemory => return error.OutOfMemory,
934 error.AnalysisFail => continue,992 error.AnalysisFail => continue,
935 };993 };
...@@ -938,8 +996,8 @@ pub fn performAllTheWork(self: *Module) error{OutOfMemory}!void {...@@ -938,8 +996,8 @@ pub fn performAllTheWork(self: *Module) error{OutOfMemory}!void {
938 }996 }
939 },997 },
940 },998 },
941 .ast_gen_decl => |item| {999 .analyze_decl => |decl| {
942 self.astGenDecl(item.scope, item.ast_node) catch |err| switch (err) {1000 self.ensureDeclAnalyzed(decl) catch |err| switch (err) {
943 error.OutOfMemory => return error.OutOfMemory,1001 error.OutOfMemory => return error.OutOfMemory,
944 error.AnalysisFail => continue,1002 error.AnalysisFail => continue,
945 };1003 };
...@@ -947,51 +1005,83 @@ pub fn performAllTheWork(self: *Module) error{OutOfMemory}!void {...@@ -947,51 +1005,83 @@ pub fn performAllTheWork(self: *Module) error{OutOfMemory}!void {
947 };1005 };
948}1006}
9491007
950fn astGenDecl(self: *Module, parent_scope: *Scope, ast_node: *ast.Node) !void {1008fn ensureDeclAnalyzed(self: *Module, decl: *Decl) InnerError!void {
1009 switch (decl.analysis) {
1010 .in_progress => unreachable,
1011 .outdated => unreachable,
1012
1013 .sema_failure,
1014 .sema_failure_retryable,
1015 .codegen_failure,
1016 .dependency_failure,
1017 .codegen_failure_retryable,
1018 => return error.AnalysisFail,
1019
1020 .complete => return,
1021
1022 .unreferenced => {
1023 self.astGenAndAnalyzeDecl(decl) catch |err| switch (err) {
1024 error.OutOfMemory => return error.OutOfMemory,
1025 error.AnalysisFail => return error.AnalysisFail,
1026 else => {
1027 try self.failed_decls.ensureCapacity(self.failed_decls.size + 1);
1028 self.failed_decls.putAssumeCapacityNoClobber(decl, try ErrorMsg.create(
1029 self.allocator,
1030 decl.src(),
1031 "unable to analyze: {}",
1032 .{@errorName(err)},
1033 ));
1034 decl.analysis = .sema_failure_retryable;
1035 return error.AnalysisFail;
1036 },
1037 };
1038 },
1039 }
1040}
1041
1042fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !void {
1043 const file_scope = decl.scope.cast(Scope.File).?;
1044 const tree = try self.getAstTree(file_scope);
1045 const ast_node = tree.root_node.decls()[decl.src_index];
951 switch (ast_node.id) {1046 switch (ast_node.id) {
952 .FnProto => {1047 .FnProto => {
953 const fn_proto = @fieldParentPtr(ast.Node.FnProto, "base", ast_node);1048 const fn_proto = @fieldParentPtr(ast.Node.FnProto, "base", ast_node);
9541049
955 const name_tok = fn_proto.name_token orelse1050 decl.analysis = .in_progress;
956 return self.failTok(parent_scope, fn_proto.fn_token, "missing function name", .{});1051
957 const tree = parent_scope.tree();1052 // This arena allocator's memory is discarded at the end of this function. It is used
958 const name_loc = tree.token_locs[name_tok];1053 // to determine the type of the function, and hence the type of the decl, which is needed
959 const name = tree.tokenSliceLoc(name_loc);1054 // to complete the Decl analysis.
960 const name_hash = Decl.hashSimpleName(name);1055 var fn_type_scope: Scope.GenZIR = .{
961 const contents_hash = std.zig.hashSrc(tree.getNodeSource(ast_node));1056 .decl = decl,
962 const new_decl = try self.createNewDecl(parent_scope, name, name_loc.start, name_hash, contents_hash);
963
964 // This DeclAnalysis scope's arena memory is discarded after the ZIR generation
965 // pass completes, and semantic analysis of it completes.
966 var gen_scope: Scope.DeclAnalysis = .{
967 .decl = new_decl,
968 .arena = std.heap.ArenaAllocator.init(self.allocator),1057 .arena = std.heap.ArenaAllocator.init(self.allocator),
1058 .instructions = std.ArrayList(*zir.Inst).init(self.allocator),
969 };1059 };
970 // TODO free this memory1060 defer fn_type_scope.arena.deinit();
971 //defer gen_scope.arena.deinit();1061 defer fn_type_scope.instructions.deinit();
9721062
973 const body_node = fn_proto.body_node orelse1063 const body_node = fn_proto.body_node orelse
974 return self.failTok(&gen_scope.base, fn_proto.fn_token, "TODO implement extern functions", .{});1064 return self.failTok(&fn_type_scope.base, fn_proto.fn_token, "TODO implement extern functions", .{});
975 if (fn_proto.params_len != 0) {1065 if (fn_proto.params_len != 0) {
976 return self.failTok(1066 return self.failTok(
977 &gen_scope.base,1067 &fn_type_scope.base,
978 fn_proto.params()[0].name_token.?,1068 fn_proto.params()[0].name_token.?,
979 "TODO implement function parameters",1069 "TODO implement function parameters",
980 .{},1070 .{},
981 );1071 );
982 }1072 }
983 if (fn_proto.lib_name) |lib_name| {1073 if (fn_proto.lib_name) |lib_name| {
984 return self.failNode(&gen_scope.base, lib_name, "TODO implement function library name", .{});1074 return self.failNode(&fn_type_scope.base, lib_name, "TODO implement function library name", .{});
985 }1075 }
986 if (fn_proto.align_expr) |align_expr| {1076 if (fn_proto.align_expr) |align_expr| {
987 return self.failNode(&gen_scope.base, align_expr, "TODO implement function align expression", .{});1077 return self.failNode(&fn_type_scope.base, align_expr, "TODO implement function align expression", .{});
988 }1078 }
989 if (fn_proto.section_expr) |sect_expr| {1079 if (fn_proto.section_expr) |sect_expr| {
990 return self.failNode(&gen_scope.base, sect_expr, "TODO implement function section expression", .{});1080 return self.failNode(&fn_type_scope.base, sect_expr, "TODO implement function section expression", .{});
991 }1081 }
992 if (fn_proto.callconv_expr) |callconv_expr| {1082 if (fn_proto.callconv_expr) |callconv_expr| {
993 return self.failNode(1083 return self.failNode(
994 &gen_scope.base,1084 &fn_type_scope.base,
995 callconv_expr,1085 callconv_expr,
996 "TODO implement function calling convention expression",1086 "TODO implement function calling convention expression",
997 .{},1087 .{},
...@@ -999,82 +1089,94 @@ fn astGenDecl(self: *Module, parent_scope: *Scope, ast_node: *ast.Node) !void {...@@ -999,82 +1089,94 @@ fn astGenDecl(self: *Module, parent_scope: *Scope, ast_node: *ast.Node) !void {
999 }1089 }
1000 const return_type_expr = switch (fn_proto.return_type) {1090 const return_type_expr = switch (fn_proto.return_type) {
1001 .Explicit => |node| node,1091 .Explicit => |node| node,
1002 .InferErrorSet => |node| return self.failNode(&gen_scope.base, node, "TODO implement inferred error sets", .{}),1092 .InferErrorSet => |node| return self.failNode(&fn_type_scope.base, node, "TODO implement inferred error sets", .{}),
1003 .Invalid => |tok| return self.failTok(&gen_scope.base, tok, "unable to parse return type", .{}),1093 .Invalid => |tok| return self.failTok(&fn_type_scope.base, tok, "unable to parse return type", .{}),
1004 };1094 };
10051095
1006 const return_type_inst = try self.astGenExpr(&gen_scope.base, return_type_expr);1096 const return_type_inst = try self.astGenExpr(&fn_type_scope.base, return_type_expr);
1007 const body_block = body_node.cast(ast.Node.Block).?;1097 const fn_src = tree.token_locs[fn_proto.fn_token].start;
1008 const body = try self.astGenBlock(&gen_scope.base, body_block);1098 const fn_type_inst = try self.addZIRInst(&fn_type_scope.base, fn_src, zir.Inst.FnType, .{
1009 const fn_type_inst = try gen_scope.arena.allocator.create(zir.Inst.FnType);1099 .return_type = return_type_inst,
1010 fn_type_inst.* = .{1100 .param_types = &[0]*zir.Inst{},
1011 .base = .{1101 }, .{});
1012 .tag = zir.Inst.FnType.base_tag,1102 _ = try self.addZIRInst(&fn_type_scope.base, fn_src, zir.Inst.Return, .{ .operand = fn_type_inst }, .{});
1013 .name = "",1103
1014 .src = name_loc.start,1104 // We need the memory for the Type to go into the arena for the Decl
1015 },1105 var decl_arena = std.heap.ArenaAllocator.init(self.allocator);
1016 .positionals = .{1106 errdefer decl_arena.deinit();
1017 .return_type = return_type_inst,1107 const decl_arena_state = try decl_arena.allocator.create(std.heap.ArenaAllocator.State);
1018 .param_types = &[0]*zir.Inst{},1108
1019 },1109 var block_scope: Scope.Block = .{
1020 .kw_args = .{},1110 .func = null,
1111 .decl = decl,
1112 .instructions = .{},
1113 .arena = &decl_arena.allocator,
1021 };1114 };
1022 const fn_inst = try gen_scope.arena.allocator.create(zir.Inst.Fn);1115 defer block_scope.instructions.deinit(self.allocator);
1023 fn_inst.* = .{1116
1024 .base = .{1117 const fn_type = try self.analyzeBodyValueAsType(&block_scope, .{
1025 .tag = zir.Inst.Fn.base_tag,1118 .instructions = fn_type_scope.instructions.items,
1026 .name = name,1119 });
1027 .src = name_loc.start,1120 const new_func = try decl_arena.allocator.create(Fn);
1028 .contents_hash = contents_hash,1121 const fn_payload = try decl_arena.allocator.create(Value.Payload.Function);
1029 },1122
1030 .positionals = .{1123 const fn_zir = blk: {
1031 .fn_type = &fn_type_inst.base,1124 // This scope's arena memory is discarded after the ZIR generation
1032 .body = body,1125 // pass completes, and semantic analysis of it completes.
1126 var gen_scope: Scope.GenZIR = .{
1127 .decl = decl,
1128 .arena = std.heap.ArenaAllocator.init(self.allocator),
1129 .instructions = std.ArrayList(*zir.Inst).init(self.allocator),
1130 };
1131 errdefer gen_scope.arena.deinit();
1132 defer gen_scope.instructions.deinit();
1133
1134 const body_block = body_node.cast(ast.Node.Block).?;
1135
1136 try self.astGenBlock(&gen_scope.base, body_block);
1137
1138 const fn_zir = try gen_scope.arena.allocator.create(Fn.ZIR);
1139 fn_zir.* = .{
1140 .body = .{
1141 .instructions = try gen_scope.arena.allocator.dupe(*zir.Inst, gen_scope.instructions.items),
1142 },
1143 .arena = gen_scope.arena.state,
1144 };
1145 break :blk fn_zir;
1146 };
1147
1148 new_func.* = .{
1149 .analysis = .{ .queued = fn_zir },
1150 .owner_decl = decl,
1151 };
1152 fn_payload.* = .{ .func = new_func };
1153
1154 decl_arena_state.* = decl_arena.state;
1155 decl.typed_value = .{
1156 .most_recent = .{
1157 .typed_value = .{
1158 .ty = fn_type,
1159 .val = Value.initPayload(&fn_payload.base),
1160 },
1161 .arena = decl_arena_state,
1033 },1162 },
1034 .kw_args = .{},
1035 };1163 };
1036 try self.analyzeNewDecl(new_decl, &fn_inst.base);1164 decl.analysis = .complete;
1165 decl.generation = self.generation;
1166
1167 // We don't fully codegen the decl until later, but we do need to reserve a global
1168 // offset table index for it. This allows us to codegen decls out of dependency order,
1169 // increasing how many computations can be done in parallel.
1170 try self.bin_file.allocateDeclIndexes(decl);
1171 try self.work_queue.writeItem(.{ .codegen_decl = decl });
10371172
1038 if (fn_proto.extern_export_inline_token) |maybe_export_token| {1173 if (fn_proto.extern_export_inline_token) |maybe_export_token| {
1039 if (tree.token_ids[maybe_export_token] == .Keyword_export) {1174 if (tree.token_ids[maybe_export_token] == .Keyword_export) {
1040 var str_inst = zir.Inst.Str{1175 const export_src = tree.token_locs[maybe_export_token].start;
1041 .base = .{1176 const name_loc = tree.token_locs[fn_proto.name_token.?];
1042 .tag = zir.Inst.Str.base_tag,1177 const name = tree.tokenSliceLoc(name_loc);
1043 .name = "",1178 // The scope needs to have the decl in it.
1044 .src = name_loc.start,1179 try self.analyzeExport(&block_scope.base, export_src, name, decl);
1045 },
1046 .positionals = .{
1047 .bytes = name,
1048 },
1049 .kw_args = .{},
1050 };
1051 var ref_inst = zir.Inst.Ref{
1052 .base = .{
1053 .tag = zir.Inst.Ref.base_tag,
1054 .name = "",
1055 .src = name_loc.start,
1056 },
1057 .positionals = .{
1058 .operand = &str_inst.base,
1059 },
1060 .kw_args = .{},
1061 };
1062 var export_inst = zir.Inst.Export{
1063 .base = .{
1064 .tag = zir.Inst.Export.base_tag,
1065 .name = "",
1066 .src = name_loc.start,
1067 .contents_hash = contents_hash,
1068 },
1069 .positionals = .{
1070 .symbol_name = &ref_inst.base,
1071 .value = &fn_inst.base,
1072 },
1073 .kw_args = .{},
1074 };
1075 // Here we analyze the export using the arena that expires at the end of this
1076 // function call.
1077 try self.analyzeExport(&gen_scope.base, &export_inst);
1078 }1180 }
1079 }1181 }
1080 },1182 },
...@@ -1085,6 +1187,19 @@ fn astGenDecl(self: *Module, parent_scope: *Scope, ast_node: *ast.Node) !void {...@@ -1085,6 +1187,19 @@ fn astGenDecl(self: *Module, parent_scope: *Scope, ast_node: *ast.Node) !void {
1085 }1187 }
1086}1188}
10871189
1190fn analyzeBodyValueAsType(self: *Module, block_scope: *Scope.Block, body: zir.Module.Body) !Type {
1191 try self.analyzeBody(&block_scope.base, body);
1192 for (block_scope.instructions.items) |inst| {
1193 if (inst.cast(Inst.Ret)) |ret| {
1194 const val = try self.resolveConstValue(&block_scope.base, ret.args.operand);
1195 return val.toType();
1196 } else {
1197 return self.fail(&block_scope.base, inst.src, "unable to resolve comptime value", .{});
1198 }
1199 }
1200 unreachable;
1201}
1202
1088fn astGenExpr(self: *Module, scope: *Scope, ast_node: *ast.Node) InnerError!*zir.Inst {1203fn astGenExpr(self: *Module, scope: *Scope, ast_node: *ast.Node) InnerError!*zir.Inst {
1089 switch (ast_node.id) {1204 switch (ast_node.id) {
1090 .Identifier => return self.astGenIdent(scope, @fieldParentPtr(ast.Node.Identifier, "base", ast_node)),1205 .Identifier => return self.astGenIdent(scope, @fieldParentPtr(ast.Node.Identifier, "base", ast_node)),
...@@ -1092,11 +1207,33 @@ fn astGenExpr(self: *Module, scope: *Scope, ast_node: *ast.Node) InnerError!*zir...@@ -1092,11 +1207,33 @@ fn astGenExpr(self: *Module, scope: *Scope, ast_node: *ast.Node) InnerError!*zir
1092 .StringLiteral => return self.astGenStringLiteral(scope, @fieldParentPtr(ast.Node.StringLiteral, "base", ast_node)),1207 .StringLiteral => return self.astGenStringLiteral(scope, @fieldParentPtr(ast.Node.StringLiteral, "base", ast_node)),
1093 .IntegerLiteral => return self.astGenIntegerLiteral(scope, @fieldParentPtr(ast.Node.IntegerLiteral, "base", ast_node)),1208 .IntegerLiteral => return self.astGenIntegerLiteral(scope, @fieldParentPtr(ast.Node.IntegerLiteral, "base", ast_node)),
1094 .BuiltinCall => return self.astGenBuiltinCall(scope, @fieldParentPtr(ast.Node.BuiltinCall, "base", ast_node)),1209 .BuiltinCall => return self.astGenBuiltinCall(scope, @fieldParentPtr(ast.Node.BuiltinCall, "base", ast_node)),
1210 .Call => return self.astGenCall(scope, @fieldParentPtr(ast.Node.Call, "base", ast_node)),
1095 .Unreachable => return self.astGenUnreachable(scope, @fieldParentPtr(ast.Node.Unreachable, "base", ast_node)),1211 .Unreachable => return self.astGenUnreachable(scope, @fieldParentPtr(ast.Node.Unreachable, "base", ast_node)),
1212 .ControlFlowExpression => return self.astGenControlFlowExpression(scope, @fieldParentPtr(ast.Node.ControlFlowExpression, "base", ast_node)),
1096 else => return self.failNode(scope, ast_node, "TODO implement astGenExpr for {}", .{@tagName(ast_node.id)}),1213 else => return self.failNode(scope, ast_node, "TODO implement astGenExpr for {}", .{@tagName(ast_node.id)}),
1097 }1214 }
1098}1215}
10991216
1217fn astGenControlFlowExpression(
1218 self: *Module,
1219 scope: *Scope,
1220 cfe: *ast.Node.ControlFlowExpression,
1221) InnerError!*zir.Inst {
1222 switch (cfe.kind) {
1223 .Break => return self.failNode(scope, &cfe.base, "TODO implement astGenExpr for Break", .{}),
1224 .Continue => return self.failNode(scope, &cfe.base, "TODO implement astGenExpr for Continue", .{}),
1225 .Return => {},
1226 }
1227 const tree = scope.tree();
1228 const src = tree.token_locs[cfe.ltoken].start;
1229 if (cfe.rhs) |rhs_node| {
1230 const operand = try self.astGenExpr(scope, rhs_node);
1231 return self.addZIRInst(scope, src, zir.Inst.Return, .{ .operand = operand }, .{});
1232 } else {
1233 return self.addZIRInst(scope, src, zir.Inst.ReturnVoid, .{}, .{});
1234 }
1235}
1236
1100fn astGenIdent(self: *Module, scope: *Scope, ident: *ast.Node.Identifier) InnerError!*zir.Inst {1237fn astGenIdent(self: *Module, scope: *Scope, ident: *ast.Node.Identifier) InnerError!*zir.Inst {
1101 const tree = scope.tree();1238 const tree = scope.tree();
1102 const ident_name = tree.tokenSlice(ident.token);1239 const ident_name = tree.tokenSlice(ident.token);
...@@ -1105,19 +1242,8 @@ fn astGenIdent(self: *Module, scope: *Scope, ident: *ast.Node.Identifier) InnerE...@@ -1105,19 +1242,8 @@ fn astGenIdent(self: *Module, scope: *Scope, ident: *ast.Node.Identifier) InnerE
1105 }1242 }
11061243
1107 if (getSimplePrimitiveValue(ident_name)) |typed_value| {1244 if (getSimplePrimitiveValue(ident_name)) |typed_value| {
1108 const const_inst = try scope.arena().create(zir.Inst.Const);1245 const src = tree.token_locs[ident.token].start;
1109 const_inst.* = .{1246 return self.addZIRInstConst(scope, src, typed_value);
1110 .base = .{
1111 .tag = zir.Inst.Const.base_tag,
1112 .name = "",
1113 .src = tree.token_locs[ident.token].start,
1114 },
1115 .positionals = .{
1116 .typed_value = typed_value,
1117 },
1118 .kw_args = .{},
1119 };
1120 return &const_inst.base;
1121 }1247 }
11221248
1123 if (ident_name.len >= 2) integer: {1249 if (ident_name.len >= 2) integer: {
...@@ -1137,7 +1263,15 @@ fn astGenIdent(self: *Module, scope: *Scope, ident: *ast.Node.Identifier) InnerE...@@ -1137,7 +1263,15 @@ fn astGenIdent(self: *Module, scope: *Scope, ident: *ast.Node.Identifier) InnerE
1137 }1263 }
1138 }1264 }
11391265
1140 return self.failNode(scope, &ident.base, "TODO implement identifier lookup", .{});1266 // Decl lookup
1267 const namespace = scope.namespace();
1268 const name_hash = namespace.fullyQualifiedNameHash(ident_name);
1269 if (self.decl_table.getValue(name_hash)) |decl| {
1270 const src = tree.token_locs[ident.token].start;
1271 return try self.addZIRInst(scope, src, zir.Inst.DeclValInModule, .{ .decl = decl }, .{});
1272 }
1273
1274 return self.failNode(scope, &ident.base, "TODO implement local variable identifier lookup", .{});
1141}1275}
11421276
1143fn astGenStringLiteral(self: *Module, scope: *Scope, str_lit: *ast.Node.StringLiteral) InnerError!*zir.Inst {1277fn astGenStringLiteral(self: *Module, scope: *Scope, str_lit: *ast.Node.StringLiteral) InnerError!*zir.Inst {
...@@ -1155,31 +1289,9 @@ fn astGenStringLiteral(self: *Module, scope: *Scope, str_lit: *ast.Node.StringLi...@@ -1155,31 +1289,9 @@ fn astGenStringLiteral(self: *Module, scope: *Scope, str_lit: *ast.Node.StringLi
1155 else => |e| return e,1289 else => |e| return e,
1156 };1290 };
11571291
1158 var str_inst = try arena.create(zir.Inst.Str);1292 const src = tree.token_locs[str_lit.token].start;
1159 str_inst.* = .{1293 const str_inst = try self.addZIRInst(scope, src, zir.Inst.Str, .{ .bytes = bytes }, .{});
1160 .base = .{1294 return self.addZIRInst(scope, src, zir.Inst.Ref, .{ .operand = str_inst }, .{});
1161 .tag = zir.Inst.Str.base_tag,
1162 .name = "",
1163 .src = tree.token_locs[str_lit.token].start,
1164 },
1165 .positionals = .{
1166 .bytes = bytes,
1167 },
1168 .kw_args = .{},
1169 };
1170 var ref_inst = try arena.create(zir.Inst.Ref);
1171 ref_inst.* = .{
1172 .base = .{
1173 .tag = zir.Inst.Ref.base_tag,
1174 .name = "",
1175 .src = tree.token_locs[str_lit.token].start,
1176 },
1177 .positionals = .{
1178 .operand = &str_inst.base,
1179 },
1180 .kw_args = .{},
1181 };
1182 return &ref_inst.base;
1183}1295}
11841296
1185fn astGenIntegerLiteral(self: *Module, scope: *Scope, int_lit: *ast.Node.IntegerLiteral) InnerError!*zir.Inst {1297fn astGenIntegerLiteral(self: *Module, scope: *Scope, int_lit: *ast.Node.IntegerLiteral) InnerError!*zir.Inst {
...@@ -1195,48 +1307,25 @@ fn astGenIntegerLiteral(self: *Module, scope: *Scope, int_lit: *ast.Node.Integer...@@ -1195,48 +1307,25 @@ fn astGenIntegerLiteral(self: *Module, scope: *Scope, int_lit: *ast.Node.Integer
1195 return self.failTok(scope, int_lit.token, "TODO implement 0b int prefix", .{});1307 return self.failTok(scope, int_lit.token, "TODO implement 0b int prefix", .{});
1196 }1308 }
1197 if (std.fmt.parseInt(u64, bytes, 10)) |small_int| {1309 if (std.fmt.parseInt(u64, bytes, 10)) |small_int| {
1198 var int_payload = try arena.create(Value.Payload.Int_u64);1310 const int_payload = try arena.create(Value.Payload.Int_u64);
1199 int_payload.* = .{1311 int_payload.* = .{ .int = small_int };
1200 .int = small_int,1312 const src = tree.token_locs[int_lit.token].start;
1201 };1313 return self.addZIRInstConst(scope, src, .{
1202 var const_inst = try arena.create(zir.Inst.Const);1314 .ty = Type.initTag(.comptime_int),
1203 const_inst.* = .{1315 .val = Value.initPayload(&int_payload.base),
1204 .base = .{1316 });
1205 .tag = zir.Inst.Const.base_tag,
1206 .name = "",
1207 .src = tree.token_locs[int_lit.token].start,
1208 },
1209 .positionals = .{
1210 .typed_value = .{
1211 .ty = Type.initTag(.comptime_int),
1212 .val = Value.initPayload(&int_payload.base),
1213 },
1214 },
1215 .kw_args = .{},
1216 };
1217 return &const_inst.base;
1218 } else |err| {1317 } else |err| {
1219 return self.failTok(scope, int_lit.token, "TODO implement int literals that don't fit in a u64", .{});1318 return self.failTok(scope, int_lit.token, "TODO implement int literals that don't fit in a u64", .{});
1220 }1319 }
1221}1320}
12221321
1223fn astGenBlock(self: *Module, scope: *Scope, block_node: *ast.Node.Block) !zir.Module.Body {1322fn astGenBlock(self: *Module, scope: *Scope, block_node: *ast.Node.Block) !void {
1224 if (block_node.label) |label| {1323 if (block_node.label) |label| {
1225 return self.failTok(scope, label, "TODO implement labeled blocks", .{});1324 return self.failTok(scope, label, "TODO implement labeled blocks", .{});
1226 }1325 }
1227 const arena = scope.arena();
1228 var instructions = std.ArrayList(*zir.Inst).init(arena);
1229
1230 try instructions.ensureCapacity(block_node.statements_len);
1231
1232 for (block_node.statements()) |statement| {1326 for (block_node.statements()) |statement| {
1233 const inst = try self.astGenExpr(scope, statement);1327 _ = try self.astGenExpr(scope, statement);
1234 instructions.appendAssumeCapacity(inst);
1235 }1328 }
1236
1237 return zir.Module.Body{
1238 .instructions = instructions.items,
1239 };
1240}1329}
12411330
1242fn astGenAsm(self: *Module, scope: *Scope, asm_node: *ast.Node.Asm) InnerError!*zir.Inst {1331fn astGenAsm(self: *Module, scope: *Scope, asm_node: *ast.Node.Asm) InnerError!*zir.Inst {
...@@ -1255,84 +1344,59 @@ fn astGenAsm(self: *Module, scope: *Scope, asm_node: *ast.Node.Asm) InnerError!*...@@ -1255,84 +1344,59 @@ fn astGenAsm(self: *Module, scope: *Scope, asm_node: *ast.Node.Asm) InnerError!*
1255 args[i] = try self.astGenExpr(scope, input.expr);1344 args[i] = try self.astGenExpr(scope, input.expr);
1256 }1345 }
12571346
1258 const return_type = try arena.create(zir.Inst.Const);1347 const src = tree.token_locs[asm_node.asm_token].start;
1259 return_type.* = .{1348 const return_type = try self.addZIRInstConst(scope, src, .{
1260 .base = .{1349 .ty = Type.initTag(.type),
1261 .tag = zir.Inst.Const.base_tag,1350 .val = Value.initTag(.void_type),
1262 .name = "",1351 });
1263 .src = tree.token_locs[asm_node.asm_token].start,1352 const asm_inst = try self.addZIRInst(scope, src, zir.Inst.Asm, .{
1264 },1353 .asm_source = try self.astGenExpr(scope, asm_node.template),
1265 .positionals = .{1354 .return_type = return_type,
1266 .typed_value = .{1355 }, .{
1267 .ty = Type.initTag(.type),1356 .@"volatile" = asm_node.volatile_token != null,
1268 .val = Value.initTag(.void_type),1357 //.clobbers = TODO handle clobbers
1269 },1358 .inputs = inputs,
1270 },1359 .args = args,
1271 .kw_args = .{},1360 });
1272 };1361 return asm_inst;
1273
1274 const asm_inst = try arena.create(zir.Inst.Asm);
1275 asm_inst.* = .{
1276 .base = .{
1277 .tag = zir.Inst.Asm.base_tag,
1278 .name = "",
1279 .src = tree.token_locs[asm_node.asm_token].start,
1280 },
1281 .positionals = .{
1282 .asm_source = try self.astGenExpr(scope, asm_node.template),
1283 .return_type = &return_type.base,
1284 },
1285 .kw_args = .{
1286 .@"volatile" = asm_node.volatile_token != null,
1287 //.clobbers = TODO handle clobbers
1288 .inputs = inputs,
1289 .args = args,
1290 },
1291 };
1292 return &asm_inst.base;
1293}1362}
12941363
1295fn astGenBuiltinCall(self: *Module, scope: *Scope, call: *ast.Node.BuiltinCall) InnerError!*zir.Inst {1364fn astGenBuiltinCall(self: *Module, scope: *Scope, call: *ast.Node.BuiltinCall) InnerError!*zir.Inst {
1296 const tree = scope.tree();1365 const tree = scope.tree();
1297 const builtin_name = tree.tokenSlice(call.builtin_token);1366 const builtin_name = tree.tokenSlice(call.builtin_token);
1298 const arena = scope.arena();
12991367
1300 if (mem.eql(u8, builtin_name, "@ptrToInt")) {1368 if (mem.eql(u8, builtin_name, "@ptrToInt")) {
1301 if (call.params_len != 1) {1369 if (call.params_len != 1) {
1302 return self.failTok(scope, call.builtin_token, "expected 1 parameter, found {}", .{call.params_len});1370 return self.failTok(scope, call.builtin_token, "expected 1 parameter, found {}", .{call.params_len});
1303 }1371 }
1304 const ptrtoint = try arena.create(zir.Inst.PtrToInt);1372 const src = tree.token_locs[call.builtin_token].start;
1305 ptrtoint.* = .{1373 return self.addZIRInst(scope, src, zir.Inst.PtrToInt, .{
1306 .base = .{1374 .ptr = try self.astGenExpr(scope, call.params()[0]),
1307 .tag = zir.Inst.PtrToInt.base_tag,1375 }, .{});
1308 .name = "",
1309 .src = tree.token_locs[call.builtin_token].start,
1310 },
1311 .positionals = .{
1312 .ptr = try self.astGenExpr(scope, call.params()[0]),
1313 },
1314 .kw_args = .{},
1315 };
1316 return &ptrtoint.base;
1317 } else {1376 } else {
1318 return self.failTok(scope, call.builtin_token, "TODO implement builtin call for '{}'", .{builtin_name});1377 return self.failTok(scope, call.builtin_token, "TODO implement builtin call for '{}'", .{builtin_name});
1319 }1378 }
1320}1379}
13211380
1381fn astGenCall(self: *Module, scope: *Scope, call: *ast.Node.Call) InnerError!*zir.Inst {
1382 const tree = scope.tree();
1383
1384 if (call.params_len != 0) {
1385 return self.failNode(scope, &call.base, "TODO implement fn calls with parameters", .{});
1386 }
1387 const lhs = try self.astGenExpr(scope, call.lhs);
1388
1389 const src = tree.token_locs[call.lhs.firstToken()].start;
1390 return self.addZIRInst(scope, src, zir.Inst.Call, .{
1391 .func = lhs,
1392 .args = &[0]*zir.Inst{},
1393 }, .{});
1394}
1395
1322fn astGenUnreachable(self: *Module, scope: *Scope, unreach_node: *ast.Node.Unreachable) InnerError!*zir.Inst {1396fn astGenUnreachable(self: *Module, scope: *Scope, unreach_node: *ast.Node.Unreachable) InnerError!*zir.Inst {
1323 const tree = scope.tree();1397 const tree = scope.tree();
1324 const arena = scope.arena();1398 const src = tree.token_locs[unreach_node.token].start;
1325 const unreach = try arena.create(zir.Inst.Unreachable);1399 return self.addZIRInst(scope, src, zir.Inst.Unreachable, .{}, .{});
1326 unreach.* = .{
1327 .base = .{
1328 .tag = zir.Inst.Unreachable.base_tag,
1329 .name = "",
1330 .src = tree.token_locs[unreach_node.token].start,
1331 },
1332 .positionals = .{},
1333 .kw_args = .{},
1334 };
1335 return &unreach.base;
1336}1400}
13371401
1338fn getSimplePrimitiveValue(name: []const u8) ?TypedValue {1402fn getSimplePrimitiveValue(name: []const u8) ?TypedValue {
...@@ -1501,19 +1565,23 @@ fn analyzeRootSrcFile(self: *Module, root_scope: *Scope.File) !void {...@@ -1501,19 +1565,23 @@ fn analyzeRootSrcFile(self: *Module, root_scope: *Scope.File) !void {
15011565
1502 try self.work_queue.ensureUnusedCapacity(decls.len);1566 try self.work_queue.ensureUnusedCapacity(decls.len);
15031567
1504 for (decls) |decl| {1568 for (decls) |src_decl, decl_i| {
1505 if (decl.cast(ast.Node.FnProto)) |proto_decl| {1569 if (src_decl.cast(ast.Node.FnProto)) |fn_proto| {
1506 if (proto_decl.extern_export_inline_token) |maybe_export_token| {1570 // We will create a Decl for it regardless of analysis status.
1571 const name_tok = fn_proto.name_token orelse
1572 @panic("TODO handle missing function name in the parser");
1573 const name_loc = tree.token_locs[name_tok];
1574 const name = tree.tokenSliceLoc(name_loc);
1575 const name_hash = root_scope.fullyQualifiedNameHash(name);
1576 const contents_hash = std.zig.hashSrc(tree.getNodeSource(src_decl));
1577 const new_decl = try self.createNewDecl(&root_scope.base, name, decl_i, name_hash, contents_hash);
1578 if (fn_proto.extern_export_inline_token) |maybe_export_token| {
1507 if (tree.token_ids[maybe_export_token] == .Keyword_export) {1579 if (tree.token_ids[maybe_export_token] == .Keyword_export) {
1508 self.work_queue.writeItemAssumeCapacity(.{1580 self.work_queue.writeItemAssumeCapacity(.{ .analyze_decl = new_decl });
1509 .ast_gen_decl = .{
1510 .ast_node = decl,
1511 .scope = &root_scope.base,
1512 },
1513 });
1514 }1581 }
1515 }1582 }
1516 }1583 }
1584 // TODO also look for global variable declarations
1517 // TODO also look for comptime blocks and exported globals1585 // TODO also look for comptime blocks and exported globals
1518 }1586 }
1519 },1587 },
...@@ -1567,7 +1635,7 @@ fn analyzeRootZIRModule(self: *Module, root_scope: *Scope.ZIRModule) !void {...@@ -1567,7 +1635,7 @@ fn analyzeRootZIRModule(self: *Module, root_scope: *Scope.ZIRModule) !void {
1567 }1635 }
15681636
1569 for (src_module.decls) |src_decl| {1637 for (src_module.decls) |src_decl| {
1570 const name_hash = Decl.hashSimpleName(src_decl.name);1638 const name_hash = root_scope.fullyQualifiedNameHash(src_decl.name);
1571 if (self.decl_table.get(name_hash)) |kv| {1639 if (self.decl_table.get(name_hash)) |kv| {
1572 const decl = kv.value;1640 const decl = kv.value;
1573 deleted_decls.removeAssertDiscard(decl);1641 deleted_decls.removeAssertDiscard(decl);
...@@ -1664,36 +1732,33 @@ fn analyzeFnBody(self: *Module, decl: *Decl, func: *Fn) !void {...@@ -1664,36 +1732,33 @@ fn analyzeFnBody(self: *Module, decl: *Decl, func: *Fn) !void {
1664 // Use the Decl's arena for function memory.1732 // Use the Decl's arena for function memory.
1665 var arena = decl.typed_value.most_recent.arena.?.promote(self.allocator);1733 var arena = decl.typed_value.most_recent.arena.?.promote(self.allocator);
1666 defer decl.typed_value.most_recent.arena.?.* = arena.state;1734 defer decl.typed_value.most_recent.arena.?.* = arena.state;
1667 var analysis: Fn.Analysis = .{1735 var inner_block: Scope.Block = .{
1668 .inner_block = .{1736 .func = func,
1669 .func = func,1737 .decl = decl,
1670 .decl = decl,1738 .instructions = .{},
1671 .instructions = .{},1739 .arena = &arena.allocator,
1672 .arena = &arena.allocator,
1673 },
1674 .needed_inst_capacity = 0,
1675 .inst_table = std.AutoHashMap(*zir.Inst, *Inst).init(self.allocator),
1676 };1740 };
1677 defer analysis.inner_block.instructions.deinit(self.allocator);1741 defer inner_block.instructions.deinit(self.allocator);
1678 defer analysis.inst_table.deinit();
16791742
1680 const fn_inst = func.analysis.queued;1743 const fn_zir = func.analysis.queued;
1681 func.analysis = .{ .in_progress = &analysis };1744 defer fn_zir.arena.promote(self.allocator).deinit();
1745 func.analysis = .{ .in_progress = {} };
1746 std.debug.warn("set {} to in_progress\n", .{decl.name});
16821747
1683 try self.analyzeBody(&analysis.inner_block.base, fn_inst.positionals.body);1748 try self.analyzeBody(&inner_block.base, fn_zir.body);
16841749
1685 func.analysis = .{1750 const instructions = try arena.allocator.dupe(*Inst, inner_block.instructions.items);
1686 .success = .{1751 func.analysis = .{ .success = .{ .instructions = instructions } };
1687 .instructions = try arena.allocator.dupe(*Inst, analysis.inner_block.instructions.items),1752 std.debug.warn("set {} to success\n", .{decl.name});
1688 },
1689 };
1690}1753}
16911754
1692fn reAnalyzeDecl(self: *Module, decl: *Decl, old_inst: *zir.Inst) InnerError!void {1755fn reAnalyzeDecl(self: *Module, decl: *Decl, old_inst: *zir.Inst) InnerError!void {
1693 switch (decl.analysis) {1756 switch (decl.analysis) {
1757 .unreferenced => unreachable,
1694 .in_progress => unreachable,1758 .in_progress => unreachable,
1695 .dependency_failure,1759 .dependency_failure,
1696 .sema_failure,1760 .sema_failure,
1761 .sema_failure_retryable,
1697 .codegen_failure,1762 .codegen_failure,
1698 .codegen_failure_retryable,1763 .codegen_failure_retryable,
1699 .complete,1764 .complete,
...@@ -1702,7 +1767,6 @@ fn reAnalyzeDecl(self: *Module, decl: *Decl, old_inst: *zir.Inst) InnerError!voi...@@ -1702,7 +1767,6 @@ fn reAnalyzeDecl(self: *Module, decl: *Decl, old_inst: *zir.Inst) InnerError!voi
1702 .outdated => {}, // Decl re-analysis1767 .outdated => {}, // Decl re-analysis
1703 }1768 }
1704 //std.debug.warn("re-analyzing {}\n", .{decl.name});1769 //std.debug.warn("re-analyzing {}\n", .{decl.name});
1705 decl.src = old_inst.src;
17061770
1707 // The exports this Decl performs will be re-discovered, so we remove them here1771 // The exports this Decl performs will be re-discovered, so we remove them here
1708 // prior to re-analysis.1772 // prior to re-analysis.
...@@ -1771,11 +1835,13 @@ fn reAnalyzeDecl(self: *Module, decl: *Decl, old_inst: *zir.Inst) InnerError!voi...@@ -1771,11 +1835,13 @@ fn reAnalyzeDecl(self: *Module, decl: *Decl, old_inst: *zir.Inst) InnerError!voi
1771 if (type_changed or typed_value.val.tag() != .function) {1835 if (type_changed or typed_value.val.tag() != .function) {
1772 for (decl.dependants.items) |dep| {1836 for (decl.dependants.items) |dep| {
1773 switch (dep.analysis) {1837 switch (dep.analysis) {
1838 .unreferenced => unreachable,
1774 .in_progress => unreachable,1839 .in_progress => unreachable,
1775 .outdated => continue, // already queued for update1840 .outdated => continue, // already queued for update
17761841
1777 .dependency_failure,1842 .dependency_failure,
1778 .sema_failure,1843 .sema_failure,
1844 .sema_failure_retryable,
1779 .codegen_failure,1845 .codegen_failure,
1780 .codegen_failure_retryable,1846 .codegen_failure_retryable,
1781 .complete,1847 .complete,
...@@ -1799,16 +1865,16 @@ fn markOutdatedDecl(self: *Module, decl: *Decl) !void {...@@ -1799,16 +1865,16 @@ fn markOutdatedDecl(self: *Module, decl: *Decl) !void {
1799fn allocateNewDecl(1865fn allocateNewDecl(
1800 self: *Module,1866 self: *Module,
1801 scope: *Scope,1867 scope: *Scope,
1802 src: usize,1868 src_index: usize,
1803 contents_hash: std.zig.SrcHash,1869 contents_hash: std.zig.SrcHash,
1804) !*Decl {1870) !*Decl {
1805 const new_decl = try self.allocator.create(Decl);1871 const new_decl = try self.allocator.create(Decl);
1806 new_decl.* = .{1872 new_decl.* = .{
1807 .name = "",1873 .name = "",
1808 .scope = scope.namespace(),1874 .scope = scope.namespace(),
1809 .src = src,1875 .src_index = src_index,
1810 .typed_value = .{ .never_succeeded = {} },1876 .typed_value = .{ .never_succeeded = {} },
1811 .analysis = .in_progress,1877 .analysis = .unreferenced,
1812 .deletion_flag = false,1878 .deletion_flag = false,
1813 .contents_hash = contents_hash,1879 .contents_hash = contents_hash,
1814 .link = link.ElfFile.TextBlock.empty,1880 .link = link.ElfFile.TextBlock.empty,
...@@ -1821,12 +1887,12 @@ fn createNewDecl(...@@ -1821,12 +1887,12 @@ fn createNewDecl(
1821 self: *Module,1887 self: *Module,
1822 scope: *Scope,1888 scope: *Scope,
1823 decl_name: []const u8,1889 decl_name: []const u8,
1824 src: usize,1890 src_index: usize,
1825 name_hash: Decl.Hash,1891 name_hash: Scope.NameHash,
1826 contents_hash: std.zig.SrcHash,1892 contents_hash: std.zig.SrcHash,
1827) !*Decl {1893) !*Decl {
1828 try self.decl_table.ensureCapacity(self.decl_table.size + 1);1894 try self.decl_table.ensureCapacity(self.decl_table.size + 1);
1829 const new_decl = try self.allocateNewDecl(scope, src, contents_hash);1895 const new_decl = try self.allocateNewDecl(scope, src_index, contents_hash);
1830 errdefer self.allocator.destroy(new_decl);1896 errdefer self.allocator.destroy(new_decl);
1831 new_decl.name = try mem.dupeZ(self.allocator, u8, decl_name);1897 new_decl.name = try mem.dupeZ(self.allocator, u8, decl_name);
1832 self.decl_table.putAssumeCapacityNoClobber(name_hash, new_decl);1898 self.decl_table.putAssumeCapacityNoClobber(name_hash, new_decl);
...@@ -1840,6 +1906,8 @@ fn analyzeNewDecl(self: *Module, new_decl: *Decl, old_inst: *zir.Inst) InnerErro...@@ -1840,6 +1906,8 @@ fn analyzeNewDecl(self: *Module, new_decl: *Decl, old_inst: *zir.Inst) InnerErro
1840 };1906 };
1841 errdefer decl_scope.arena.deinit();1907 errdefer decl_scope.arena.deinit();
18421908
1909 new_decl.analysis = .in_progress;
1910
1843 const typed_value = self.analyzeConstInst(&decl_scope.base, old_inst) catch |err| switch (err) {1911 const typed_value = self.analyzeConstInst(&decl_scope.base, old_inst) catch |err| switch (err) {
1844 error.OutOfMemory => return error.OutOfMemory,1912 error.OutOfMemory => return error.OutOfMemory,
1845 error.AnalysisFail => {1913 error.AnalysisFail => {
...@@ -1873,37 +1941,40 @@ fn analyzeNewDecl(self: *Module, new_decl: *Decl, old_inst: *zir.Inst) InnerErro...@@ -1873,37 +1941,40 @@ fn analyzeNewDecl(self: *Module, new_decl: *Decl, old_inst: *zir.Inst) InnerErro
1873}1941}
18741942
1875fn resolveDecl(self: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError!*Decl {1943fn resolveDecl(self: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError!*Decl {
1876 if (old_inst.name.len == 0) {1944 assert(old_inst.name.len == 0);
1877 // If the name is empty, then we make this an anonymous Decl.1945 // If the name is empty, then we make this an anonymous Decl.
1878 const new_decl = try self.allocateNewDecl(scope, old_inst.src, old_inst.contents_hash);1946 const scope_decl = scope.decl().?;
1879 try self.analyzeNewDecl(new_decl, old_inst);1947 const new_decl = try self.allocateNewDecl(scope, scope_decl.src_index, old_inst.contents_hash);
1880 return new_decl;1948 try self.analyzeNewDecl(new_decl, old_inst);
1881 }1949 return new_decl;
1882 const name_hash = Decl.hashSimpleName(old_inst.name);1950 //const name_hash = Decl.hashSimpleName(old_inst.name);
1883 if (self.decl_table.get(name_hash)) |kv| {1951 //if (self.decl_table.get(name_hash)) |kv| {
1884 const decl = kv.value;1952 // const decl = kv.value;
1885 try self.reAnalyzeDecl(decl, old_inst);1953 // decl.src = old_inst.src;
1886 return decl;1954 // try self.reAnalyzeDecl(decl, old_inst);
1887 } else if (old_inst.cast(zir.Inst.DeclVal)) |decl_val| {1955 // return decl;
1888 // This is just a named reference to another decl.1956 //} else if (old_inst.cast(zir.Inst.DeclVal)) |decl_val| {
1889 return self.analyzeDeclVal(scope, decl_val);1957 // // This is just a named reference to another decl.
1890 } else {1958 // return self.analyzeDeclVal(scope, decl_val);
1891 const new_decl = try self.createNewDecl(scope, old_inst.name, old_inst.src, name_hash, old_inst.contents_hash);1959 //} else {
1892 try self.analyzeNewDecl(new_decl, old_inst);1960 // const new_decl = try self.createNewDecl(scope, old_inst.name, old_inst.src, name_hash, old_inst.contents_hash);
18931961 // try self.analyzeNewDecl(new_decl, old_inst);
1894 return new_decl;1962
1895 }1963 // return new_decl;
1964 //}
1896}1965}
18971966
1898/// Declares a dependency on the decl.1967/// Declares a dependency on the decl.
1899fn resolveCompleteDecl(self: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError!*Decl {1968fn resolveCompleteDecl(self: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError!*Decl {
1900 const decl = try self.resolveDecl(scope, old_inst);1969 const decl = try self.resolveDecl(scope, old_inst);
1901 switch (decl.analysis) {1970 switch (decl.analysis) {
1971 .unreferenced => unreachable,
1902 .in_progress => unreachable,1972 .in_progress => unreachable,
1903 .outdated => unreachable,1973 .outdated => unreachable,
19041974
1905 .dependency_failure,1975 .dependency_failure,
1906 .sema_failure,1976 .sema_failure,
1977 .sema_failure_retryable,
1907 .codegen_failure,1978 .codegen_failure,
1908 .codegen_failure_retryable,1979 .codegen_failure_retryable,
1909 => return error.AnalysisFail,1980 => return error.AnalysisFail,
...@@ -1916,20 +1987,9 @@ fn resolveCompleteDecl(self: *Module, scope: *Scope, old_inst: *zir.Inst) InnerE...@@ -1916,20 +1987,9 @@ fn resolveCompleteDecl(self: *Module, scope: *Scope, old_inst: *zir.Inst) InnerE
1916 return decl;1987 return decl;
1917}1988}
19181989
1990/// TODO look into removing this function
1919fn resolveInst(self: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError!*Inst {1991fn resolveInst(self: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError!*Inst {
1920 if (scope.cast(Scope.Block)) |block| {1992 return old_inst.analyzed_inst;
1921 if (block.func.analysis.in_progress.inst_table.get(old_inst)) |kv| {
1922 return kv.value;
1923 }
1924 }
1925
1926 if (scope.namespace().tag == .zir_module) {
1927 const decl = try self.resolveCompleteDecl(scope, old_inst);
1928 const decl_ref = try self.analyzeDeclRef(scope, old_inst.src, decl);
1929 return self.analyzeDeref(scope, old_inst.src, decl_ref, old_inst.src);
1930 }
1931
1932 return self.analyzeInst(scope, old_inst);
1933}1993}
19341994
1935fn requireRuntimeBlock(self: *Module, scope: *Scope, src: usize) !*Scope.Block {1995fn requireRuntimeBlock(self: *Module, scope: *Scope, src: usize) !*Scope.Block {
...@@ -1977,21 +2037,15 @@ fn resolveType(self: *Module, scope: *Scope, old_inst: *zir.Inst) !Type {...@@ -1977,21 +2037,15 @@ fn resolveType(self: *Module, scope: *Scope, old_inst: *zir.Inst) !Type {
1977 return val.toType();2037 return val.toType();
1978}2038}
19792039
1980fn analyzeExport(self: *Module, scope: *Scope, export_inst: *zir.Inst.Export) InnerError!void {2040fn analyzeExport(self: *Module, scope: *Scope, src: usize, symbol_name: []const u8, exported_decl: *Decl) !void {
1981 try self.decl_exports.ensureCapacity(self.decl_exports.size + 1);
1982 try self.export_owners.ensureCapacity(self.export_owners.size + 1);
1983 const symbol_name = try self.resolveConstString(scope, export_inst.positionals.symbol_name);
1984 const exported_decl = try self.resolveCompleteDecl(scope, export_inst.positionals.value);
1985 const typed_value = exported_decl.typed_value.most_recent.typed_value;2041 const typed_value = exported_decl.typed_value.most_recent.typed_value;
1986 switch (typed_value.ty.zigTypeTag()) {2042 switch (typed_value.ty.zigTypeTag()) {
1987 .Fn => {},2043 .Fn => {},
1988 else => return self.fail(2044 else => return self.fail(scope, src, "unable to export type '{}'", .{typed_value.ty}),
1989 scope,
1990 export_inst.positionals.value.src,
1991 "unable to export type '{}'",
1992 .{typed_value.ty},
1993 ),
1994 }2045 }
2046 try self.decl_exports.ensureCapacity(self.decl_exports.size + 1);
2047 try self.export_owners.ensureCapacity(self.export_owners.size + 1);
2048
1995 const new_export = try self.allocator.create(Export);2049 const new_export = try self.allocator.create(Export);
1996 errdefer self.allocator.destroy(new_export);2050 errdefer self.allocator.destroy(new_export);
19972051
...@@ -1999,7 +2053,7 @@ fn analyzeExport(self: *Module, scope: *Scope, export_inst: *zir.Inst.Export) In...@@ -1999,7 +2053,7 @@ fn analyzeExport(self: *Module, scope: *Scope, export_inst: *zir.Inst.Export) In
19992053
2000 new_export.* = .{2054 new_export.* = .{
2001 .options = .{ .name = symbol_name },2055 .options = .{ .name = symbol_name },
2002 .src = export_inst.base.src,2056 .src = src,
2003 .link = .{},2057 .link = .{},
2004 .owner_decl = owner_decl,2058 .owner_decl = owner_decl,
2005 .exported_decl = exported_decl,2059 .exported_decl = exported_decl,
...@@ -2030,7 +2084,7 @@ fn analyzeExport(self: *Module, scope: *Scope, export_inst: *zir.Inst.Export) In...@@ -2030,7 +2084,7 @@ fn analyzeExport(self: *Module, scope: *Scope, export_inst: *zir.Inst.Export) In
2030 try self.failed_exports.ensureCapacity(self.failed_exports.size + 1);2084 try self.failed_exports.ensureCapacity(self.failed_exports.size + 1);
2031 self.failed_exports.putAssumeCapacityNoClobber(new_export, try ErrorMsg.create(2085 self.failed_exports.putAssumeCapacityNoClobber(new_export, try ErrorMsg.create(
2032 self.allocator,2086 self.allocator,
2033 export_inst.base.src,2087 src,
2034 "unable to export: {}",2088 "unable to export: {}",
2035 .{@errorName(err)},2089 .{@errorName(err)},
2036 ));2090 ));
...@@ -2039,7 +2093,6 @@ fn analyzeExport(self: *Module, scope: *Scope, export_inst: *zir.Inst.Export) In...@@ -2039,7 +2093,6 @@ fn analyzeExport(self: *Module, scope: *Scope, export_inst: *zir.Inst.Export) In
2039 };2093 };
2040}2094}
20412095
2042/// TODO should not need the cast on the last parameter at the callsites
2043fn addNewInstArgs(2096fn addNewInstArgs(
2044 self: *Module,2097 self: *Module,
2045 block: *Scope.Block,2098 block: *Scope.Block,
...@@ -2053,6 +2106,47 @@ fn addNewInstArgs(...@@ -2053,6 +2106,47 @@ fn addNewInstArgs(
2053 return &inst.base;2106 return &inst.base;
2054}2107}
20552108
2109fn newZIRInst(
2110 allocator: *Allocator,
2111 src: usize,
2112 comptime T: type,
2113 positionals: std.meta.fieldInfo(T, "positionals").field_type,
2114 kw_args: std.meta.fieldInfo(T, "kw_args").field_type,
2115) !*zir.Inst {
2116 const inst = try allocator.create(T);
2117 inst.* = .{
2118 .base = .{
2119 .tag = T.base_tag,
2120 .name = "",
2121 .src = src,
2122 },
2123 .positionals = positionals,
2124 .kw_args = kw_args,
2125 };
2126 return &inst.base;
2127}
2128
2129fn addZIRInst(
2130 self: *Module,
2131 scope: *Scope,
2132 src: usize,
2133 comptime T: type,
2134 positionals: std.meta.fieldInfo(T, "positionals").field_type,
2135 kw_args: std.meta.fieldInfo(T, "kw_args").field_type,
2136) !*zir.Inst {
2137 const gen_zir = scope.cast(Scope.GenZIR).?;
2138 try gen_zir.instructions.ensureCapacity(gen_zir.instructions.items.len + 1);
2139 const inst = try newZIRInst(&gen_zir.arena.allocator, src, T, positionals, kw_args);
2140 gen_zir.instructions.appendAssumeCapacity(inst);
2141 return inst;
2142}
2143
2144/// TODO The existence of this function is a workaround for a bug in stage1.
2145fn addZIRInstConst(self: *Module, scope: *Scope, src: usize, typed_value: TypedValue) !*zir.Inst {
2146 const P = std.meta.fieldInfo(zir.Inst.Const, "positionals").field_type;
2147 return self.addZIRInst(scope, src, zir.Inst.Const, P{ .typed_value = typed_value }, .{});
2148}
2149
2056fn addNewInst(self: *Module, block: *Scope.Block, src: usize, ty: Type, comptime T: type) !*T {2150fn addNewInst(self: *Module, block: *Scope.Block, src: usize, ty: Type, comptime T: type) !*T {
2057 const inst = try block.arena.create(T);2151 const inst = try block.arena.create(T);
2058 inst.* = .{2152 inst.* = .{
...@@ -2107,6 +2201,13 @@ fn constVoid(self: *Module, scope: *Scope, src: usize) !*Inst {...@@ -2107,6 +2201,13 @@ fn constVoid(self: *Module, scope: *Scope, src: usize) !*Inst {
2107 });2201 });
2108}2202}
21092203
2204fn constNoReturn(self: *Module, scope: *Scope, src: usize) !*Inst {
2205 return self.constInst(scope, src, .{
2206 .ty = Type.initTag(.noreturn),
2207 .val = Value.initTag(.the_one_possible_value),
2208 });
2209}
2210
2110fn constUndef(self: *Module, scope: *Scope, src: usize, ty: Type) !*Inst {2211fn constUndef(self: *Module, scope: *Scope, src: usize, ty: Type) !*Inst {
2111 return self.constInst(scope, src, .{2212 return self.constInst(scope, src, .{
2112 .ty = ty,2213 .ty = ty,
...@@ -2179,7 +2280,10 @@ fn analyzeConstInst(self: *Module, scope: *Scope, old_inst: *zir.Inst) InnerErro...@@ -2179,7 +2280,10 @@ fn analyzeConstInst(self: *Module, scope: *Scope, old_inst: *zir.Inst) InnerErro
2179}2280}
21802281
2181fn analyzeInstConst(self: *Module, scope: *Scope, const_inst: *zir.Inst.Const) InnerError!*Inst {2282fn analyzeInstConst(self: *Module, scope: *Scope, const_inst: *zir.Inst.Const) InnerError!*Inst {
2182 return self.constInst(scope, const_inst.base.src, const_inst.positionals.typed_value);2283 // Move the TypedValue from old memory to new memory. This allows freeing the ZIR instructions
2284 // after analysis.
2285 const typed_value_copy = try const_inst.positionals.typed_value.copy(scope.arena());
2286 return self.constInst(scope, const_inst.base.src, typed_value_copy);
2183}2287}
21842288
2185fn analyzeInst(self: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError!*Inst {2289fn analyzeInst(self: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError!*Inst {
...@@ -2190,6 +2294,7 @@ fn analyzeInst(self: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError!*In...@@ -2190,6 +2294,7 @@ fn analyzeInst(self: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError!*In
2190 .@"const" => return self.analyzeInstConst(scope, old_inst.cast(zir.Inst.Const).?),2294 .@"const" => return self.analyzeInstConst(scope, old_inst.cast(zir.Inst.Const).?),
2191 .declref => return self.analyzeInstDeclRef(scope, old_inst.cast(zir.Inst.DeclRef).?),2295 .declref => return self.analyzeInstDeclRef(scope, old_inst.cast(zir.Inst.DeclRef).?),
2192 .declval => return self.analyzeInstDeclVal(scope, old_inst.cast(zir.Inst.DeclVal).?),2296 .declval => return self.analyzeInstDeclVal(scope, old_inst.cast(zir.Inst.DeclVal).?),
2297 .declval_in_module => return self.analyzeInstDeclValInModule(scope, old_inst.cast(zir.Inst.DeclValInModule).?),
2193 .str => {2298 .str => {
2194 const bytes = old_inst.cast(zir.Inst.Str).?.positionals.bytes;2299 const bytes = old_inst.cast(zir.Inst.Str).?.positionals.bytes;
2195 // The bytes references memory inside the ZIR module, which can get deallocated2300 // The bytes references memory inside the ZIR module, which can get deallocated
...@@ -2208,11 +2313,9 @@ fn analyzeInst(self: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError!*In...@@ -2208,11 +2313,9 @@ fn analyzeInst(self: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError!*In
2208 .@"asm" => return self.analyzeInstAsm(scope, old_inst.cast(zir.Inst.Asm).?),2313 .@"asm" => return self.analyzeInstAsm(scope, old_inst.cast(zir.Inst.Asm).?),
2209 .@"unreachable" => return self.analyzeInstUnreachable(scope, old_inst.cast(zir.Inst.Unreachable).?),2314 .@"unreachable" => return self.analyzeInstUnreachable(scope, old_inst.cast(zir.Inst.Unreachable).?),
2210 .@"return" => return self.analyzeInstRet(scope, old_inst.cast(zir.Inst.Return).?),2315 .@"return" => return self.analyzeInstRet(scope, old_inst.cast(zir.Inst.Return).?),
2316 .returnvoid => return self.analyzeInstRetVoid(scope, old_inst.cast(zir.Inst.ReturnVoid).?),
2211 .@"fn" => return self.analyzeInstFn(scope, old_inst.cast(zir.Inst.Fn).?),2317 .@"fn" => return self.analyzeInstFn(scope, old_inst.cast(zir.Inst.Fn).?),
2212 .@"export" => {2318 .@"export" => return self.analyzeInstExport(scope, old_inst.cast(zir.Inst.Export).?),
2213 try self.analyzeExport(scope, old_inst.cast(zir.Inst.Export).?);
2214 return self.constVoid(scope, old_inst.src);
2215 },
2216 .primitive => return self.analyzeInstPrimitive(scope, old_inst.cast(zir.Inst.Primitive).?),2319 .primitive => return self.analyzeInstPrimitive(scope, old_inst.cast(zir.Inst.Primitive).?),
2217 .ref => return self.analyzeInstRef(scope, old_inst.cast(zir.Inst.Ref).?),2320 .ref => return self.analyzeInstRef(scope, old_inst.cast(zir.Inst.Ref).?),
2218 .fntype => return self.analyzeInstFnType(scope, old_inst.cast(zir.Inst.FnType).?),2321 .fntype => return self.analyzeInstFnType(scope, old_inst.cast(zir.Inst.FnType).?),
...@@ -2227,13 +2330,20 @@ fn analyzeInst(self: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError!*In...@@ -2227,13 +2330,20 @@ fn analyzeInst(self: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError!*In
2227 }2330 }
2228}2331}
22292332
2333fn analyzeInstExport(self: *Module, scope: *Scope, export_inst: *zir.Inst.Export) InnerError!*Inst {
2334 const symbol_name = try self.resolveConstString(scope, export_inst.positionals.symbol_name);
2335 const exported_decl = try self.resolveCompleteDecl(scope, export_inst.positionals.value);
2336 try self.analyzeExport(scope, export_inst.base.src, symbol_name, exported_decl);
2337 return self.constVoid(scope, export_inst.base.src);
2338}
2339
2230fn analyzeInstCompileError(self: *Module, scope: *Scope, inst: *zir.Inst.CompileError) InnerError!*Inst {2340fn analyzeInstCompileError(self: *Module, scope: *Scope, inst: *zir.Inst.CompileError) InnerError!*Inst {
2231 return self.fail(scope, inst.base.src, "{}", .{inst.positionals.msg});2341 return self.fail(scope, inst.base.src, "{}", .{inst.positionals.msg});
2232}2342}
22332343
2234fn analyzeInstBreakpoint(self: *Module, scope: *Scope, inst: *zir.Inst.Breakpoint) InnerError!*Inst {2344fn analyzeInstBreakpoint(self: *Module, scope: *Scope, inst: *zir.Inst.Breakpoint) InnerError!*Inst {
2235 const b = try self.requireRuntimeBlock(scope, inst.base.src);2345 const b = try self.requireRuntimeBlock(scope, inst.base.src);
2236 return self.addNewInstArgs(b, inst.base.src, Type.initTag(.void), Inst.Breakpoint, Inst.Args(Inst.Breakpoint){});2346 return self.addNewInstArgs(b, inst.base.src, Type.initTag(.void), Inst.Breakpoint, {});
2237}2347}
22382348
2239fn analyzeInstRef(self: *Module, scope: *Scope, inst: *zir.Inst.Ref) InnerError!*Inst {2349fn analyzeInstRef(self: *Module, scope: *Scope, inst: *zir.Inst.Ref) InnerError!*Inst {
...@@ -2251,7 +2361,7 @@ fn analyzeInstDeclRef(self: *Module, scope: *Scope, inst: *zir.Inst.DeclRef) Inn...@@ -2251,7 +2361,7 @@ fn analyzeInstDeclRef(self: *Module, scope: *Scope, inst: *zir.Inst.DeclRef) Inn
2251 const src_decl = zir_module.contents.module.findDecl(decl_name) orelse2361 const src_decl = zir_module.contents.module.findDecl(decl_name) orelse
2252 return self.fail(scope, inst.positionals.name.src, "use of undeclared identifier '{}'", .{decl_name});2362 return self.fail(scope, inst.positionals.name.src, "use of undeclared identifier '{}'", .{decl_name});
22532363
2254 const decl = try self.resolveCompleteDecl(scope, src_decl);2364 const decl = try self.resolveCompleteDecl(scope, src_decl.decl);
2255 return self.analyzeDeclRef(scope, inst.base.src, decl);2365 return self.analyzeDeclRef(scope, inst.base.src, decl);
2256 } else {2366 } else {
2257 unreachable;2367 unreachable;
...@@ -2264,7 +2374,7 @@ fn analyzeDeclVal(self: *Module, scope: *Scope, inst: *zir.Inst.DeclVal) InnerEr...@@ -2264,7 +2374,7 @@ fn analyzeDeclVal(self: *Module, scope: *Scope, inst: *zir.Inst.DeclVal) InnerEr
2264 const src_decl = zir_module.contents.module.findDecl(decl_name) orelse2374 const src_decl = zir_module.contents.module.findDecl(decl_name) orelse
2265 return self.fail(scope, inst.base.src, "use of undeclared identifier '{}'", .{decl_name});2375 return self.fail(scope, inst.base.src, "use of undeclared identifier '{}'", .{decl_name});
22662376
2267 const decl = try self.resolveCompleteDecl(scope, src_decl);2377 const decl = try self.resolveCompleteDecl(scope, src_decl.decl);
22682378
2269 return decl;2379 return decl;
2270}2380}
...@@ -2275,12 +2385,34 @@ fn analyzeInstDeclVal(self: *Module, scope: *Scope, inst: *zir.Inst.DeclVal) Inn...@@ -2275,12 +2385,34 @@ fn analyzeInstDeclVal(self: *Module, scope: *Scope, inst: *zir.Inst.DeclVal) Inn
2275 return self.analyzeDeref(scope, inst.base.src, ptr, inst.base.src);2385 return self.analyzeDeref(scope, inst.base.src, ptr, inst.base.src);
2276}2386}
22772387
2388fn analyzeInstDeclValInModule(self: *Module, scope: *Scope, inst: *zir.Inst.DeclValInModule) InnerError!*Inst {
2389 const decl = inst.positionals.decl;
2390 const ptr = try self.analyzeDeclRef(scope, inst.base.src, decl);
2391 return self.analyzeDeref(scope, inst.base.src, ptr, inst.base.src);
2392}
2393
2278fn analyzeDeclRef(self: *Module, scope: *Scope, src: usize, decl: *Decl) InnerError!*Inst {2394fn analyzeDeclRef(self: *Module, scope: *Scope, src: usize, decl: *Decl) InnerError!*Inst {
2395 const scope_decl = scope.decl().?;
2396 try self.declareDeclDependency(scope_decl, decl);
2397 self.ensureDeclAnalyzed(decl) catch |err| {
2398 if (scope.cast(Scope.Block)) |block| {
2399 if (block.func) |func| {
2400 func.analysis = .dependency_failure;
2401 } else {
2402 block.decl.analysis = .dependency_failure;
2403 }
2404 } else {
2405 scope_decl.analysis = .dependency_failure;
2406 }
2407 return err;
2408 };
2409
2279 const decl_tv = try decl.typedValue();2410 const decl_tv = try decl.typedValue();
2280 const ty_payload = try scope.arena().create(Type.Payload.SingleConstPointer);2411 const ty_payload = try scope.arena().create(Type.Payload.SingleConstPointer);
2281 ty_payload.* = .{ .pointee_type = decl_tv.ty };2412 ty_payload.* = .{ .pointee_type = decl_tv.ty };
2282 const val_payload = try scope.arena().create(Value.Payload.DeclRef);2413 const val_payload = try scope.arena().create(Value.Payload.DeclRef);
2283 val_payload.* = .{ .decl = decl };2414 val_payload.* = .{ .decl = decl };
2415
2284 return self.constInst(scope, src, .{2416 return self.constInst(scope, src, .{
2285 .ty = Type.initPayload(&ty_payload.base),2417 .ty = Type.initPayload(&ty_payload.base),
2286 .val = Value.initPayload(&val_payload.base),2418 .val = Value.initPayload(&val_payload.base),
...@@ -2345,26 +2477,26 @@ fn analyzeInstCall(self: *Module, scope: *Scope, inst: *zir.Inst.Call) InnerErro...@@ -2345,26 +2477,26 @@ fn analyzeInstCall(self: *Module, scope: *Scope, inst: *zir.Inst.Call) InnerErro
2345 }2477 }
23462478
2347 const b = try self.requireRuntimeBlock(scope, inst.base.src);2479 const b = try self.requireRuntimeBlock(scope, inst.base.src);
2348 return self.addNewInstArgs(b, inst.base.src, Type.initTag(.void), Inst.Call, Inst.Args(Inst.Call){2480 return self.addNewInstArgs(b, inst.base.src, Type.initTag(.void), Inst.Call, .{
2349 .func = func,2481 .func = func,
2350 .args = casted_args,2482 .args = casted_args,
2351 });2483 });
2352}2484}
23532485
2354fn analyzeInstFn(self: *Module, scope: *Scope, fn_inst: *zir.Inst.Fn) InnerError!*Inst {2486fn analyzeInstFn(self: *Module, scope: *Scope, fn_inst: *zir.Inst.Fn) InnerError!*Inst {
2355 const fn_type = try self.resolveType(scope, fn_inst.positionals.fn_type);2487 return self.fail(scope, fn_inst.base.src, "TODO implement ZIR fn inst", .{});
2356 const new_func = try scope.arena().create(Fn);2488 //const fn_type = try self.resolveType(scope, fn_inst.positionals.fn_type);
2357 new_func.* = .{2489 //const new_func = try scope.arena().create(Fn);
2358 .fn_type = fn_type,2490 //new_func.* = .{
2359 .analysis = .{ .queued = fn_inst },2491 // .analysis = .{ .queued = fn_inst },
2360 .owner_decl = scope.decl().?,2492 // .owner_decl = scope.decl().?,
2361 };2493 //};
2362 const fn_payload = try scope.arena().create(Value.Payload.Function);2494 //const fn_payload = try scope.arena().create(Value.Payload.Function);
2363 fn_payload.* = .{ .func = new_func };2495 //fn_payload.* = .{ .func = new_func };
2364 return self.constInst(scope, fn_inst.base.src, .{2496 //return self.constInst(scope, fn_inst.base.src, .{
2365 .ty = fn_type,2497 // .ty = fn_type,
2366 .val = Value.initPayload(&fn_payload.base),2498 // .val = Value.initPayload(&fn_payload.base),
2367 });2499 //});
2368}2500}
23692501
2370fn analyzeInstFnType(self: *Module, scope: *Scope, fntype: *zir.Inst.FnType) InnerError!*Inst {2502fn analyzeInstFnType(self: *Module, scope: *Scope, fntype: *zir.Inst.FnType) InnerError!*Inst {
...@@ -2377,6 +2509,13 @@ fn analyzeInstFnType(self: *Module, scope: *Scope, fntype: *zir.Inst.FnType) Inn...@@ -2377,6 +2509,13 @@ fn analyzeInstFnType(self: *Module, scope: *Scope, fntype: *zir.Inst.FnType) Inn
2377 return self.constType(scope, fntype.base.src, Type.initTag(.fn_noreturn_no_args));2509 return self.constType(scope, fntype.base.src, Type.initTag(.fn_noreturn_no_args));
2378 }2510 }
23792511
2512 if (return_type.zigTypeTag() == .Void and
2513 fntype.positionals.param_types.len == 0 and
2514 fntype.kw_args.cc == .Unspecified)
2515 {
2516 return self.constType(scope, fntype.base.src, Type.initTag(.fn_void_no_args));
2517 }
2518
2380 if (return_type.zigTypeTag() == .NoReturn and2519 if (return_type.zigTypeTag() == .NoReturn and
2381 fntype.positionals.param_types.len == 0 and2520 fntype.positionals.param_types.len == 0 and
2382 fntype.kw_args.cc == .Naked)2521 fntype.kw_args.cc == .Naked)
...@@ -2412,7 +2551,7 @@ fn analyzeInstPtrToInt(self: *Module, scope: *Scope, ptrtoint: *zir.Inst.PtrToIn...@@ -2412,7 +2551,7 @@ fn analyzeInstPtrToInt(self: *Module, scope: *Scope, ptrtoint: *zir.Inst.PtrToIn
2412 // TODO handle known-pointer-address2551 // TODO handle known-pointer-address
2413 const b = try self.requireRuntimeBlock(scope, ptrtoint.base.src);2552 const b = try self.requireRuntimeBlock(scope, ptrtoint.base.src);
2414 const ty = Type.initTag(.usize);2553 const ty = Type.initTag(.usize);
2415 return self.addNewInstArgs(b, ptrtoint.base.src, ty, Inst.PtrToInt, Inst.Args(Inst.PtrToInt){ .ptr = ptr });2554 return self.addNewInstArgs(b, ptrtoint.base.src, ty, Inst.PtrToInt, .{ .ptr = ptr });
2416}2555}
24172556
2418fn analyzeInstFieldPtr(self: *Module, scope: *Scope, fieldptr: *zir.Inst.FieldPtr) InnerError!*Inst {2557fn analyzeInstFieldPtr(self: *Module, scope: *Scope, fieldptr: *zir.Inst.FieldPtr) InnerError!*Inst {
...@@ -2604,7 +2743,7 @@ fn analyzeInstAsm(self: *Module, scope: *Scope, assembly: *zir.Inst.Asm) InnerEr...@@ -2604,7 +2743,7 @@ fn analyzeInstAsm(self: *Module, scope: *Scope, assembly: *zir.Inst.Asm) InnerEr
2604 }2743 }
26052744
2606 const b = try self.requireRuntimeBlock(scope, assembly.base.src);2745 const b = try self.requireRuntimeBlock(scope, assembly.base.src);
2607 return self.addNewInstArgs(b, assembly.base.src, return_type, Inst.Assembly, Inst.Args(Inst.Assembly){2746 return self.addNewInstArgs(b, assembly.base.src, return_type, Inst.Assembly, .{
2608 .asm_source = asm_source,2747 .asm_source = asm_source,
2609 .is_volatile = assembly.kw_args.@"volatile",2748 .is_volatile = assembly.kw_args.@"volatile",
2610 .output = output,2749 .output = output,
...@@ -2640,20 +2779,12 @@ fn analyzeInstCmp(self: *Module, scope: *Scope, inst: *zir.Inst.Cmp) InnerError!...@@ -2640,20 +2779,12 @@ fn analyzeInstCmp(self: *Module, scope: *Scope, inst: *zir.Inst.Cmp) InnerError!
2640 }2779 }
2641 const b = try self.requireRuntimeBlock(scope, inst.base.src);2780 const b = try self.requireRuntimeBlock(scope, inst.base.src);
2642 switch (op) {2781 switch (op) {
2643 .eq => return self.addNewInstArgs(2782 .eq => return self.addNewInstArgs(b, inst.base.src, Type.initTag(.bool), Inst.IsNull, .{
2644 b,2783 .operand = opt_operand,
2645 inst.base.src,2784 }),
2646 Type.initTag(.bool),2785 .neq => return self.addNewInstArgs(b, inst.base.src, Type.initTag(.bool), Inst.IsNonNull, .{
2647 Inst.IsNull,2786 .operand = opt_operand,
2648 Inst.Args(Inst.IsNull){ .operand = opt_operand },2787 }),
2649 ),
2650 .neq => return self.addNewInstArgs(
2651 b,
2652 inst.base.src,
2653 Type.initTag(.bool),
2654 Inst.IsNonNull,
2655 Inst.Args(Inst.IsNonNull){ .operand = opt_operand },
2656 ),
2657 else => unreachable,2788 else => unreachable,
2658 }2789 }
2659 } else if (is_equality_cmp and2790 } else if (is_equality_cmp and
...@@ -2748,23 +2879,19 @@ fn analyzeInstUnreachable(self: *Module, scope: *Scope, unreach: *zir.Inst.Unrea...@@ -2748,23 +2879,19 @@ fn analyzeInstUnreachable(self: *Module, scope: *Scope, unreach: *zir.Inst.Unrea
2748}2879}
27492880
2750fn analyzeInstRet(self: *Module, scope: *Scope, inst: *zir.Inst.Return) InnerError!*Inst {2881fn analyzeInstRet(self: *Module, scope: *Scope, inst: *zir.Inst.Return) InnerError!*Inst {
2882 const operand = try self.resolveInst(scope, inst.positionals.operand);
2751 const b = try self.requireRuntimeBlock(scope, inst.base.src);2883 const b = try self.requireRuntimeBlock(scope, inst.base.src);
2752 return self.addNewInstArgs(b, inst.base.src, Type.initTag(.noreturn), Inst.Ret, {});2884 return self.addNewInstArgs(b, inst.base.src, Type.initTag(.noreturn), Inst.Ret, .{ .operand = operand });
2885}
2886
2887fn analyzeInstRetVoid(self: *Module, scope: *Scope, inst: *zir.Inst.ReturnVoid) InnerError!*Inst {
2888 const b = try self.requireRuntimeBlock(scope, inst.base.src);
2889 return self.addNewInstArgs(b, inst.base.src, Type.initTag(.noreturn), Inst.RetVoid, {});
2753}2890}
27542891
2755fn analyzeBody(self: *Module, scope: *Scope, body: zir.Module.Body) !void {2892fn analyzeBody(self: *Module, scope: *Scope, body: zir.Module.Body) !void {
2756 if (scope.cast(Scope.Block)) |b| {2893 for (body.instructions) |src_inst| {
2757 const analysis = b.func.analysis.in_progress;2894 src_inst.analyzed_inst = try self.analyzeInst(scope, src_inst);
2758 analysis.needed_inst_capacity += body.instructions.len;
2759 try analysis.inst_table.ensureCapacity(analysis.needed_inst_capacity);
2760 for (body.instructions) |src_inst| {
2761 const new_inst = try self.analyzeInst(scope, src_inst);
2762 analysis.inst_table.putAssumeCapacityNoClobber(src_inst, new_inst);
2763 }
2764 } else {
2765 for (body.instructions) |src_inst| {
2766 _ = try self.analyzeInst(scope, src_inst);
2767 }
2768 }2895 }
2769}2896}
27702897
...@@ -2847,7 +2974,7 @@ fn cmpNumeric(...@@ -2847,7 +2974,7 @@ fn cmpNumeric(
2847 };2974 };
2848 const casted_lhs = try self.coerce(scope, dest_type, lhs);2975 const casted_lhs = try self.coerce(scope, dest_type, lhs);
2849 const casted_rhs = try self.coerce(scope, dest_type, rhs);2976 const casted_rhs = try self.coerce(scope, dest_type, rhs);
2850 return self.addNewInstArgs(b, src, dest_type, Inst.Cmp, Inst.Args(Inst.Cmp){2977 return self.addNewInstArgs(b, src, dest_type, Inst.Cmp, .{
2851 .lhs = casted_lhs,2978 .lhs = casted_lhs,
2852 .rhs = casted_rhs,2979 .rhs = casted_rhs,
2853 .op = op,2980 .op = op,
...@@ -2951,7 +3078,7 @@ fn cmpNumeric(...@@ -2951,7 +3078,7 @@ fn cmpNumeric(
2951 const casted_lhs = try self.coerce(scope, dest_type, lhs);3078 const casted_lhs = try self.coerce(scope, dest_type, lhs);
2952 const casted_rhs = try self.coerce(scope, dest_type, lhs);3079 const casted_rhs = try self.coerce(scope, dest_type, lhs);
29533080
2954 return self.addNewInstArgs(b, src, dest_type, Inst.Cmp, Inst.Args(Inst.Cmp){3081 return self.addNewInstArgs(b, src, dest_type, Inst.Cmp, .{
2955 .lhs = casted_lhs,3082 .lhs = casted_lhs,
2956 .rhs = casted_rhs,3083 .rhs = casted_rhs,
2957 .op = op,3084 .op = op,
...@@ -3028,7 +3155,7 @@ fn bitcast(self: *Module, scope: *Scope, dest_type: Type, inst: *Inst) !*Inst {...@@ -3028,7 +3155,7 @@ fn bitcast(self: *Module, scope: *Scope, dest_type: Type, inst: *Inst) !*Inst {
3028 }3155 }
3029 // TODO validate the type size and other compile errors3156 // TODO validate the type size and other compile errors
3030 const b = try self.requireRuntimeBlock(scope, inst.src);3157 const b = try self.requireRuntimeBlock(scope, inst.src);
3031 return self.addNewInstArgs(b, inst.src, dest_type, Inst.BitCast, Inst.Args(Inst.BitCast){ .operand = inst });3158 return self.addNewInstArgs(b, inst.src, dest_type, Inst.BitCast, .{ .operand = inst });
3032}3159}
30333160
3034fn coerceArrayPtrToSlice(self: *Module, scope: *Scope, dest_type: Type, inst: *Inst) !*Inst {3161fn coerceArrayPtrToSlice(self: *Module, scope: *Scope, dest_type: Type, inst: *Inst) !*Inst {
...@@ -3083,9 +3210,18 @@ fn failWithOwnedErrorMsg(self: *Module, scope: *Scope, src: usize, err_msg: *Err...@@ -3083,9 +3210,18 @@ fn failWithOwnedErrorMsg(self: *Module, scope: *Scope, src: usize, err_msg: *Err
3083 },3210 },
3084 .block => {3211 .block => {
3085 const block = scope.cast(Scope.Block).?;3212 const block = scope.cast(Scope.Block).?;
3086 block.func.analysis = .sema_failure;3213 if (block.func) |func| {
3214 func.analysis = .sema_failure;
3215 } else {
3216 block.decl.analysis = .sema_failure;
3217 }
3087 self.failed_decls.putAssumeCapacityNoClobber(block.decl, err_msg);3218 self.failed_decls.putAssumeCapacityNoClobber(block.decl, err_msg);
3088 },3219 },
3220 .gen_zir => {
3221 const gen_zir = scope.cast(Scope.GenZIR).?;
3222 gen_zir.decl.analysis = .sema_failure;
3223 self.failed_decls.putAssumeCapacityNoClobber(gen_zir.decl, err_msg);
3224 },
3089 .zir_module => {3225 .zir_module => {
3090 const zir_module = scope.cast(Scope.ZIRModule).?;3226 const zir_module = scope.cast(Scope.ZIRModule).?;
3091 zir_module.status = .loaded_sema_failure;3227 zir_module.status = .loaded_sema_failure;
src-self-hosted/TypedValue.zig+8
...@@ -21,3 +21,11 @@ pub const Managed = struct {...@@ -21,3 +21,11 @@ pub const Managed = struct {
21 self.* = undefined;21 self.* = undefined;
22 }22 }
23};23};
24
25/// Assumes arena allocation. Does a recursive copy.
26pub fn copy(self: TypedValue, allocator: *Allocator) error{OutOfMemory}!TypedValue {
27 return TypedValue{
28 .ty = try self.ty.copy(allocator),
29 .val = try self.val.copy(allocator),
30 };
31}
src-self-hosted/codegen.zig+16-3
...@@ -178,6 +178,7 @@ const Function = struct {...@@ -178,6 +178,7 @@ const Function = struct {
178 .ptrtoint => return self.genPtrToInt(inst.cast(ir.Inst.PtrToInt).?),178 .ptrtoint => return self.genPtrToInt(inst.cast(ir.Inst.PtrToInt).?),
179 .bitcast => return self.genBitCast(inst.cast(ir.Inst.BitCast).?),179 .bitcast => return self.genBitCast(inst.cast(ir.Inst.BitCast).?),
180 .ret => return self.genRet(inst.cast(ir.Inst.Ret).?),180 .ret => return self.genRet(inst.cast(ir.Inst.Ret).?),
181 .retvoid => return self.genRetVoid(inst.cast(ir.Inst.RetVoid).?),
181 .cmp => return self.genCmp(inst.cast(ir.Inst.Cmp).?),182 .cmp => return self.genCmp(inst.cast(ir.Inst.Cmp).?),
182 .condbr => return self.genCondBr(inst.cast(ir.Inst.CondBr).?),183 .condbr => return self.genCondBr(inst.cast(ir.Inst.CondBr).?),
183 .isnull => return self.genIsNull(inst.cast(ir.Inst.IsNull).?),184 .isnull => return self.genIsNull(inst.cast(ir.Inst.IsNull).?),
...@@ -213,7 +214,7 @@ const Function = struct {...@@ -213,7 +214,7 @@ const Function = struct {
213 try self.code.resize(self.code.items.len + 7);214 try self.code.resize(self.code.items.len + 7);
214 self.code.items[self.code.items.len - 7 ..][0..3].* = [3]u8{ 0xff, 0x14, 0x25 };215 self.code.items[self.code.items.len - 7 ..][0..3].* = [3]u8{ 0xff, 0x14, 0x25 };
215 mem.writeIntLittle(u32, self.code.items[self.code.items.len - 4 ..][0..4], got_addr);216 mem.writeIntLittle(u32, self.code.items[self.code.items.len - 4 ..][0..4], got_addr);
216 const return_type = func.fn_type.fnReturnType();217 const return_type = func.owner_decl.typed_value.most_recent.typed_value.ty.fnReturnType();
217 switch (return_type.zigTypeTag()) {218 switch (return_type.zigTypeTag()) {
218 .Void => return MCValue{ .none = {} },219 .Void => return MCValue{ .none = {} },
219 .NoReturn => return MCValue{ .unreach = {} },220 .NoReturn => return MCValue{ .unreach = {} },
...@@ -230,16 +231,28 @@ const Function = struct {...@@ -230,16 +231,28 @@ const Function = struct {
230 }231 }
231 }232 }
232233
233 fn genRet(self: *Function, inst: *ir.Inst.Ret) !MCValue {234 fn ret(self: *Function, src: usize, mcv: MCValue) !MCValue {
235 if (mcv != .none) {
236 return self.fail(src, "TODO implement return with non-void operand", .{});
237 }
234 switch (self.target.cpu.arch) {238 switch (self.target.cpu.arch) {
235 .i386, .x86_64 => {239 .i386, .x86_64 => {
236 try self.code.append(0xc3); // ret240 try self.code.append(0xc3); // ret
237 },241 },
238 else => return self.fail(inst.base.src, "TODO implement return for {}", .{self.target.cpu.arch}),242 else => return self.fail(src, "TODO implement return for {}", .{self.target.cpu.arch}),
239 }243 }
240 return .unreach;244 return .unreach;
241 }245 }
242246
247 fn genRet(self: *Function, inst: *ir.Inst.Ret) !MCValue {
248 const operand = try self.resolveInst(inst.args.operand);
249 return self.ret(inst.base.src, operand);
250 }
251
252 fn genRetVoid(self: *Function, inst: *ir.Inst.RetVoid) !MCValue {
253 return self.ret(inst.base.src, .none);
254 }
255
243 fn genCmp(self: *Function, inst: *ir.Inst.Cmp) !MCValue {256 fn genCmp(self: *Function, inst: *ir.Inst.Cmp) !MCValue {
244 switch (self.target.cpu.arch) {257 switch (self.target.cpu.arch) {
245 else => return self.fail(inst.base.src, "TODO implement cmp for {}", .{self.target.cpu.arch}),258 else => return self.fail(inst.base.src, "TODO implement cmp for {}", .{self.target.cpu.arch}),
src-self-hosted/ir.zig+9
...@@ -26,6 +26,7 @@ pub const Inst = struct {...@@ -26,6 +26,7 @@ pub const Inst = struct {
26 isnull,26 isnull,
27 ptrtoint,27 ptrtoint,
28 ret,28 ret,
29 retvoid,
29 unreach,30 unreach,
30 };31 };
3132
...@@ -146,6 +147,14 @@ pub const Inst = struct {...@@ -146,6 +147,14 @@ pub const Inst = struct {
146 pub const Ret = struct {147 pub const Ret = struct {
147 pub const base_tag = Tag.ret;148 pub const base_tag = Tag.ret;
148 base: Inst,149 base: Inst,
150 args: struct {
151 operand: *Inst,
152 },
153 };
154
155 pub const RetVoid = struct {
156 pub const base_tag = Tag.retvoid;
157 base: Inst,
149 args: void,158 args: void,
150 };159 };
151160
src-self-hosted/link.zig+6-6
...@@ -956,10 +956,10 @@ pub const ElfFile = struct {...@@ -956,10 +956,10 @@ pub const ElfFile = struct {
956 try self.offset_table_free_list.ensureCapacity(self.allocator, self.local_symbols.items.len);956 try self.offset_table_free_list.ensureCapacity(self.allocator, self.local_symbols.items.len);
957957
958 if (self.local_symbol_free_list.popOrNull()) |i| {958 if (self.local_symbol_free_list.popOrNull()) |i| {
959 //std.debug.warn("reusing symbol index {} for {}\n", .{i, decl.name});959 std.debug.warn("reusing symbol index {} for {}\n", .{i, decl.name});
960 decl.link.local_sym_index = i;960 decl.link.local_sym_index = i;
961 } else {961 } else {
962 //std.debug.warn("allocating symbol index {} for {}\n", .{self.local_symbols.items.len, decl.name});962 std.debug.warn("allocating symbol index {} for {}\n", .{self.local_symbols.items.len, decl.name});
963 decl.link.local_sym_index = @intCast(u32, self.local_symbols.items.len);963 decl.link.local_sym_index = @intCast(u32, self.local_symbols.items.len);
964 _ = self.local_symbols.addOneAssumeCapacity();964 _ = self.local_symbols.addOneAssumeCapacity();
965 }965 }
...@@ -1002,7 +1002,7 @@ pub const ElfFile = struct {...@@ -1002,7 +1002,7 @@ pub const ElfFile = struct {
1002 defer code_buffer.deinit();1002 defer code_buffer.deinit();
10031003
1004 const typed_value = decl.typed_value.most_recent.typed_value;1004 const typed_value = decl.typed_value.most_recent.typed_value;
1005 const code = switch (try codegen.generateSymbol(self, decl.src, typed_value, &code_buffer)) {1005 const code = switch (try codegen.generateSymbol(self, decl.src(), typed_value, &code_buffer)) {
1006 .externally_managed => |x| x,1006 .externally_managed => |x| x,
1007 .appended => code_buffer.items,1007 .appended => code_buffer.items,
1008 .fail => |em| {1008 .fail => |em| {
...@@ -1027,11 +1027,11 @@ pub const ElfFile = struct {...@@ -1027,11 +1027,11 @@ pub const ElfFile = struct {
1027 !mem.isAlignedGeneric(u64, local_sym.st_value, required_alignment);1027 !mem.isAlignedGeneric(u64, local_sym.st_value, required_alignment);
1028 if (need_realloc) {1028 if (need_realloc) {
1029 const vaddr = try self.growTextBlock(&decl.link, code.len, required_alignment);1029 const vaddr = try self.growTextBlock(&decl.link, code.len, required_alignment);
1030 //std.debug.warn("growing {} from 0x{x} to 0x{x}\n", .{ decl.name, local_sym.st_value, vaddr });1030 std.debug.warn("growing {} from 0x{x} to 0x{x}\n", .{ decl.name, local_sym.st_value, vaddr });
1031 if (vaddr != local_sym.st_value) {1031 if (vaddr != local_sym.st_value) {
1032 local_sym.st_value = vaddr;1032 local_sym.st_value = vaddr;
10331033
1034 //std.debug.warn(" (writing new offset table entry)\n", .{});1034 std.debug.warn(" (writing new offset table entry)\n", .{});
1035 self.offset_table.items[decl.link.offset_table_index] = vaddr;1035 self.offset_table.items[decl.link.offset_table_index] = vaddr;
1036 try self.writeOffsetTableEntry(decl.link.offset_table_index);1036 try self.writeOffsetTableEntry(decl.link.offset_table_index);
1037 }1037 }
...@@ -1049,7 +1049,7 @@ pub const ElfFile = struct {...@@ -1049,7 +1049,7 @@ pub const ElfFile = struct {
1049 const decl_name = mem.spanZ(decl.name);1049 const decl_name = mem.spanZ(decl.name);
1050 const name_str_index = try self.makeString(decl_name);1050 const name_str_index = try self.makeString(decl_name);
1051 const vaddr = try self.allocateTextBlock(&decl.link, code.len, required_alignment);1051 const vaddr = try self.allocateTextBlock(&decl.link, code.len, required_alignment);
1052 //std.debug.warn("allocated text block for {} at 0x{x}\n", .{ decl_name, vaddr });1052 std.debug.warn("allocated text block for {} at 0x{x}\n", .{ decl_name, vaddr });
1053 errdefer self.freeTextBlock(&decl.link);1053 errdefer self.freeTextBlock(&decl.link);
10541054
1055 local_sym.* = .{1055 local_sym.* = .{
src-self-hosted/type.zig+96-1
...@@ -54,6 +54,7 @@ pub const Type = extern union {...@@ -54,6 +54,7 @@ pub const Type = extern union {
54 .@"undefined" => return .Undefined,54 .@"undefined" => return .Undefined,
5555
56 .fn_noreturn_no_args => return .Fn,56 .fn_noreturn_no_args => return .Fn,
57 .fn_void_no_args => return .Fn,
57 .fn_naked_noreturn_no_args => return .Fn,58 .fn_naked_noreturn_no_args => return .Fn,
58 .fn_ccc_void_no_args => return .Fn,59 .fn_ccc_void_no_args => return .Fn,
5960
...@@ -163,6 +164,77 @@ pub const Type = extern union {...@@ -163,6 +164,77 @@ pub const Type = extern union {
163 }164 }
164 }165 }
165166
167 pub fn copy(self: Type, allocator: *Allocator) error{OutOfMemory}!Type {
168 if (self.tag_if_small_enough < Tag.no_payload_count) {
169 return Type{ .tag_if_small_enough = self.tag_if_small_enough };
170 } else switch (self.ptr_otherwise.tag) {
171 .u8,
172 .i8,
173 .isize,
174 .usize,
175 .c_short,
176 .c_ushort,
177 .c_int,
178 .c_uint,
179 .c_long,
180 .c_ulong,
181 .c_longlong,
182 .c_ulonglong,
183 .c_longdouble,
184 .c_void,
185 .f16,
186 .f32,
187 .f64,
188 .f128,
189 .bool,
190 .void,
191 .type,
192 .anyerror,
193 .comptime_int,
194 .comptime_float,
195 .noreturn,
196 .@"null",
197 .@"undefined",
198 .fn_noreturn_no_args,
199 .fn_void_no_args,
200 .fn_naked_noreturn_no_args,
201 .fn_ccc_void_no_args,
202 .single_const_pointer_to_comptime_int,
203 .const_slice_u8,
204 => unreachable,
205
206 .array_u8_sentinel_0 => return self.copyPayloadShallow(allocator, Payload.Array_u8_Sentinel0),
207 .array => {
208 const payload = @fieldParentPtr(Payload.Array, "base", self.ptr_otherwise);
209 const new_payload = try allocator.create(Payload.Array);
210 new_payload.* = .{
211 .base = payload.base,
212 .len = payload.len,
213 .elem_type = try payload.elem_type.copy(allocator),
214 };
215 return Type{ .ptr_otherwise = &new_payload.base };
216 },
217 .single_const_pointer => {
218 const payload = @fieldParentPtr(Payload.SingleConstPointer, "base", self.ptr_otherwise);
219 const new_payload = try allocator.create(Payload.SingleConstPointer);
220 new_payload.* = .{
221 .base = payload.base,
222 .pointee_type = try payload.pointee_type.copy(allocator),
223 };
224 return Type{ .ptr_otherwise = &new_payload.base };
225 },
226 .int_signed => return self.copyPayloadShallow(allocator, Payload.IntSigned),
227 .int_unsigned => return self.copyPayloadShallow(allocator, Payload.IntUnsigned),
228 }
229 }
230
231 fn copyPayloadShallow(self: Type, allocator: *Allocator, comptime T: type) error{OutOfMemory}!Type {
232 const payload = @fieldParentPtr(T, "base", self.ptr_otherwise);
233 const new_payload = try allocator.create(T);
234 new_payload.* = payload.*;
235 return Type{ .ptr_otherwise = &new_payload.base };
236 }
237
166 pub fn format(238 pub fn format(
167 self: Type,239 self: Type,
168 comptime fmt: []const u8,240 comptime fmt: []const u8,
...@@ -206,6 +278,7 @@ pub const Type = extern union {...@@ -206,6 +278,7 @@ pub const Type = extern union {
206278
207 .const_slice_u8 => return out_stream.writeAll("[]const u8"),279 .const_slice_u8 => return out_stream.writeAll("[]const u8"),
208 .fn_noreturn_no_args => return out_stream.writeAll("fn() noreturn"),280 .fn_noreturn_no_args => return out_stream.writeAll("fn() noreturn"),
281 .fn_void_no_args => return out_stream.writeAll("fn() void"),
209 .fn_naked_noreturn_no_args => return out_stream.writeAll("fn() callconv(.Naked) noreturn"),282 .fn_naked_noreturn_no_args => return out_stream.writeAll("fn() callconv(.Naked) noreturn"),
210 .fn_ccc_void_no_args => return out_stream.writeAll("fn() callconv(.C) void"),283 .fn_ccc_void_no_args => return out_stream.writeAll("fn() callconv(.C) void"),
211 .single_const_pointer_to_comptime_int => return out_stream.writeAll("*const comptime_int"),284 .single_const_pointer_to_comptime_int => return out_stream.writeAll("*const comptime_int"),
...@@ -269,6 +342,7 @@ pub const Type = extern union {...@@ -269,6 +342,7 @@ pub const Type = extern union {
269 .@"null" => return Value.initTag(.null_type),342 .@"null" => return Value.initTag(.null_type),
270 .@"undefined" => return Value.initTag(.undefined_type),343 .@"undefined" => return Value.initTag(.undefined_type),
271 .fn_noreturn_no_args => return Value.initTag(.fn_noreturn_no_args_type),344 .fn_noreturn_no_args => return Value.initTag(.fn_noreturn_no_args_type),
345 .fn_void_no_args => return Value.initTag(.fn_void_no_args_type),
272 .fn_naked_noreturn_no_args => return Value.initTag(.fn_naked_noreturn_no_args_type),346 .fn_naked_noreturn_no_args => return Value.initTag(.fn_naked_noreturn_no_args_type),
273 .fn_ccc_void_no_args => return Value.initTag(.fn_ccc_void_no_args_type),347 .fn_ccc_void_no_args => return Value.initTag(.fn_ccc_void_no_args_type),
274 .single_const_pointer_to_comptime_int => return Value.initTag(.single_const_pointer_to_comptime_int_type),348 .single_const_pointer_to_comptime_int => return Value.initTag(.single_const_pointer_to_comptime_int_type),
...@@ -303,6 +377,7 @@ pub const Type = extern union {...@@ -303,6 +377,7 @@ pub const Type = extern union {
303 .bool,377 .bool,
304 .anyerror,378 .anyerror,
305 .fn_noreturn_no_args,379 .fn_noreturn_no_args,
380 .fn_void_no_args,
306 .fn_naked_noreturn_no_args,381 .fn_naked_noreturn_no_args,
307 .fn_ccc_void_no_args,382 .fn_ccc_void_no_args,
308 .single_const_pointer_to_comptime_int,383 .single_const_pointer_to_comptime_int,
...@@ -333,6 +408,7 @@ pub const Type = extern union {...@@ -333,6 +408,7 @@ pub const Type = extern union {
333 .i8,408 .i8,
334 .bool,409 .bool,
335 .fn_noreturn_no_args, // represents machine code; not a pointer410 .fn_noreturn_no_args, // represents machine code; not a pointer
411 .fn_void_no_args, // represents machine code; not a pointer
336 .fn_naked_noreturn_no_args, // represents machine code; not a pointer412 .fn_naked_noreturn_no_args, // represents machine code; not a pointer
337 .fn_ccc_void_no_args, // represents machine code; not a pointer413 .fn_ccc_void_no_args, // represents machine code; not a pointer
338 .array_u8_sentinel_0,414 .array_u8_sentinel_0,
...@@ -420,6 +496,7 @@ pub const Type = extern union {...@@ -420,6 +496,7 @@ pub const Type = extern union {
420 .array_u8_sentinel_0,496 .array_u8_sentinel_0,
421 .const_slice_u8,497 .const_slice_u8,
422 .fn_noreturn_no_args,498 .fn_noreturn_no_args,
499 .fn_void_no_args,
423 .fn_naked_noreturn_no_args,500 .fn_naked_noreturn_no_args,
424 .fn_ccc_void_no_args,501 .fn_ccc_void_no_args,
425 .int_unsigned,502 .int_unsigned,
...@@ -466,6 +543,7 @@ pub const Type = extern union {...@@ -466,6 +543,7 @@ pub const Type = extern union {
466 .single_const_pointer,543 .single_const_pointer,
467 .single_const_pointer_to_comptime_int,544 .single_const_pointer_to_comptime_int,
468 .fn_noreturn_no_args,545 .fn_noreturn_no_args,
546 .fn_void_no_args,
469 .fn_naked_noreturn_no_args,547 .fn_naked_noreturn_no_args,
470 .fn_ccc_void_no_args,548 .fn_ccc_void_no_args,
471 .int_unsigned,549 .int_unsigned,
...@@ -509,6 +587,7 @@ pub const Type = extern union {...@@ -509,6 +587,7 @@ pub const Type = extern union {
509 .array,587 .array,
510 .array_u8_sentinel_0,588 .array_u8_sentinel_0,
511 .fn_noreturn_no_args,589 .fn_noreturn_no_args,
590 .fn_void_no_args,
512 .fn_naked_noreturn_no_args,591 .fn_naked_noreturn_no_args,
513 .fn_ccc_void_no_args,592 .fn_ccc_void_no_args,
514 .int_unsigned,593 .int_unsigned,
...@@ -553,6 +632,7 @@ pub const Type = extern union {...@@ -553,6 +632,7 @@ pub const Type = extern union {
553 .@"null",632 .@"null",
554 .@"undefined",633 .@"undefined",
555 .fn_noreturn_no_args,634 .fn_noreturn_no_args,
635 .fn_void_no_args,
556 .fn_naked_noreturn_no_args,636 .fn_naked_noreturn_no_args,
557 .fn_ccc_void_no_args,637 .fn_ccc_void_no_args,
558 .int_unsigned,638 .int_unsigned,
...@@ -597,6 +677,7 @@ pub const Type = extern union {...@@ -597,6 +677,7 @@ pub const Type = extern union {
597 .@"null",677 .@"null",
598 .@"undefined",678 .@"undefined",
599 .fn_noreturn_no_args,679 .fn_noreturn_no_args,
680 .fn_void_no_args,
600 .fn_naked_noreturn_no_args,681 .fn_naked_noreturn_no_args,
601 .fn_ccc_void_no_args,682 .fn_ccc_void_no_args,
602 .single_const_pointer,683 .single_const_pointer,
...@@ -642,6 +723,7 @@ pub const Type = extern union {...@@ -642,6 +723,7 @@ pub const Type = extern union {
642 .@"null",723 .@"null",
643 .@"undefined",724 .@"undefined",
644 .fn_noreturn_no_args,725 .fn_noreturn_no_args,
726 .fn_void_no_args,
645 .fn_naked_noreturn_no_args,727 .fn_naked_noreturn_no_args,
646 .fn_ccc_void_no_args,728 .fn_ccc_void_no_args,
647 .single_const_pointer,729 .single_const_pointer,
...@@ -675,6 +757,7 @@ pub const Type = extern union {...@@ -675,6 +757,7 @@ pub const Type = extern union {
675 .@"null",757 .@"null",
676 .@"undefined",758 .@"undefined",
677 .fn_noreturn_no_args,759 .fn_noreturn_no_args,
760 .fn_void_no_args,
678 .fn_naked_noreturn_no_args,761 .fn_naked_noreturn_no_args,
679 .fn_ccc_void_no_args,762 .fn_ccc_void_no_args,
680 .array,763 .array,
...@@ -721,6 +804,7 @@ pub const Type = extern union {...@@ -721,6 +804,7 @@ pub const Type = extern union {
721 .@"null",804 .@"null",
722 .@"undefined",805 .@"undefined",
723 .fn_noreturn_no_args,806 .fn_noreturn_no_args,
807 .fn_void_no_args,
724 .fn_naked_noreturn_no_args,808 .fn_naked_noreturn_no_args,
725 .fn_ccc_void_no_args,809 .fn_ccc_void_no_args,
726 .array,810 .array,
...@@ -777,6 +861,7 @@ pub const Type = extern union {...@@ -777,6 +861,7 @@ pub const Type = extern union {
777 pub fn fnParamLen(self: Type) usize {861 pub fn fnParamLen(self: Type) usize {
778 return switch (self.tag()) {862 return switch (self.tag()) {
779 .fn_noreturn_no_args => 0,863 .fn_noreturn_no_args => 0,
864 .fn_void_no_args => 0,
780 .fn_naked_noreturn_no_args => 0,865 .fn_naked_noreturn_no_args => 0,
781 .fn_ccc_void_no_args => 0,866 .fn_ccc_void_no_args => 0,
782867
...@@ -823,6 +908,7 @@ pub const Type = extern union {...@@ -823,6 +908,7 @@ pub const Type = extern union {
823 pub fn fnParamTypes(self: Type, types: []Type) void {908 pub fn fnParamTypes(self: Type, types: []Type) void {
824 switch (self.tag()) {909 switch (self.tag()) {
825 .fn_noreturn_no_args => return,910 .fn_noreturn_no_args => return,
911 .fn_void_no_args => return,
826 .fn_naked_noreturn_no_args => return,912 .fn_naked_noreturn_no_args => return,
827 .fn_ccc_void_no_args => return,913 .fn_ccc_void_no_args => return,
828914
...@@ -869,7 +955,10 @@ pub const Type = extern union {...@@ -869,7 +955,10 @@ pub const Type = extern union {
869 return switch (self.tag()) {955 return switch (self.tag()) {
870 .fn_noreturn_no_args => Type.initTag(.noreturn),956 .fn_noreturn_no_args => Type.initTag(.noreturn),
871 .fn_naked_noreturn_no_args => Type.initTag(.noreturn),957 .fn_naked_noreturn_no_args => Type.initTag(.noreturn),
872 .fn_ccc_void_no_args => Type.initTag(.void),958
959 .fn_void_no_args,
960 .fn_ccc_void_no_args,
961 => Type.initTag(.void),
873962
874 .f16,963 .f16,
875 .f32,964 .f32,
...@@ -913,6 +1002,7 @@ pub const Type = extern union {...@@ -913,6 +1002,7 @@ pub const Type = extern union {
913 pub fn fnCallingConvention(self: Type) std.builtin.CallingConvention {1002 pub fn fnCallingConvention(self: Type) std.builtin.CallingConvention {
914 return switch (self.tag()) {1003 return switch (self.tag()) {
915 .fn_noreturn_no_args => .Unspecified,1004 .fn_noreturn_no_args => .Unspecified,
1005 .fn_void_no_args => .Unspecified,
916 .fn_naked_noreturn_no_args => .Naked,1006 .fn_naked_noreturn_no_args => .Naked,
917 .fn_ccc_void_no_args => .C,1007 .fn_ccc_void_no_args => .C,
9181008
...@@ -958,6 +1048,7 @@ pub const Type = extern union {...@@ -958,6 +1048,7 @@ pub const Type = extern union {
958 pub fn fnIsVarArgs(self: Type) bool {1048 pub fn fnIsVarArgs(self: Type) bool {
959 return switch (self.tag()) {1049 return switch (self.tag()) {
960 .fn_noreturn_no_args => false,1050 .fn_noreturn_no_args => false,
1051 .fn_void_no_args => false,
961 .fn_naked_noreturn_no_args => false,1052 .fn_naked_noreturn_no_args => false,
962 .fn_ccc_void_no_args => false,1053 .fn_ccc_void_no_args => false,
9631054
...@@ -1033,6 +1124,7 @@ pub const Type = extern union {...@@ -1033,6 +1124,7 @@ pub const Type = extern union {
1033 .@"null",1124 .@"null",
1034 .@"undefined",1125 .@"undefined",
1035 .fn_noreturn_no_args,1126 .fn_noreturn_no_args,
1127 .fn_void_no_args,
1036 .fn_naked_noreturn_no_args,1128 .fn_naked_noreturn_no_args,
1037 .fn_ccc_void_no_args,1129 .fn_ccc_void_no_args,
1038 .array,1130 .array,
...@@ -1070,6 +1162,7 @@ pub const Type = extern union {...@@ -1070,6 +1162,7 @@ pub const Type = extern union {
1070 .type,1162 .type,
1071 .anyerror,1163 .anyerror,
1072 .fn_noreturn_no_args,1164 .fn_noreturn_no_args,
1165 .fn_void_no_args,
1073 .fn_naked_noreturn_no_args,1166 .fn_naked_noreturn_no_args,
1074 .fn_ccc_void_no_args,1167 .fn_ccc_void_no_args,
1075 .single_const_pointer_to_comptime_int,1168 .single_const_pointer_to_comptime_int,
...@@ -1126,6 +1219,7 @@ pub const Type = extern union {...@@ -1126,6 +1219,7 @@ pub const Type = extern union {
1126 .type,1219 .type,
1127 .anyerror,1220 .anyerror,
1128 .fn_noreturn_no_args,1221 .fn_noreturn_no_args,
1222 .fn_void_no_args,
1129 .fn_naked_noreturn_no_args,1223 .fn_naked_noreturn_no_args,
1130 .fn_ccc_void_no_args,1224 .fn_ccc_void_no_args,
1131 .single_const_pointer_to_comptime_int,1225 .single_const_pointer_to_comptime_int,
...@@ -1180,6 +1274,7 @@ pub const Type = extern union {...@@ -1180,6 +1274,7 @@ pub const Type = extern union {
1180 @"null",1274 @"null",
1181 @"undefined",1275 @"undefined",
1182 fn_noreturn_no_args,1276 fn_noreturn_no_args,
1277 fn_void_no_args,
1183 fn_naked_noreturn_no_args,1278 fn_naked_noreturn_no_args,
1184 fn_ccc_void_no_args,1279 fn_ccc_void_no_args,
1185 single_const_pointer_to_comptime_int,1280 single_const_pointer_to_comptime_int,
src-self-hosted/value.zig+115-5
...@@ -49,6 +49,7 @@ pub const Value = extern union {...@@ -49,6 +49,7 @@ pub const Value = extern union {
49 null_type,49 null_type,
50 undefined_type,50 undefined_type,
51 fn_noreturn_no_args_type,51 fn_noreturn_no_args_type,
52 fn_void_no_args_type,
52 fn_naked_noreturn_no_args_type,53 fn_naked_noreturn_no_args_type,
53 fn_ccc_void_no_args_type,54 fn_ccc_void_no_args_type,
54 single_const_pointer_to_comptime_int_type,55 single_const_pointer_to_comptime_int_type,
...@@ -107,6 +108,109 @@ pub const Value = extern union {...@@ -107,6 +108,109 @@ pub const Value = extern union {
107 return @fieldParentPtr(T, "base", self.ptr_otherwise);108 return @fieldParentPtr(T, "base", self.ptr_otherwise);
108 }109 }
109110
111 pub fn copy(self: Value, allocator: *Allocator) error{OutOfMemory}!Value {
112 if (self.tag_if_small_enough < Tag.no_payload_count) {
113 return Value{ .tag_if_small_enough = self.tag_if_small_enough };
114 } else switch (self.ptr_otherwise.tag) {
115 .u8_type,
116 .i8_type,
117 .isize_type,
118 .usize_type,
119 .c_short_type,
120 .c_ushort_type,
121 .c_int_type,
122 .c_uint_type,
123 .c_long_type,
124 .c_ulong_type,
125 .c_longlong_type,
126 .c_ulonglong_type,
127 .c_longdouble_type,
128 .f16_type,
129 .f32_type,
130 .f64_type,
131 .f128_type,
132 .c_void_type,
133 .bool_type,
134 .void_type,
135 .type_type,
136 .anyerror_type,
137 .comptime_int_type,
138 .comptime_float_type,
139 .noreturn_type,
140 .null_type,
141 .undefined_type,
142 .fn_noreturn_no_args_type,
143 .fn_void_no_args_type,
144 .fn_naked_noreturn_no_args_type,
145 .fn_ccc_void_no_args_type,
146 .single_const_pointer_to_comptime_int_type,
147 .const_slice_u8_type,
148 .undef,
149 .zero,
150 .the_one_possible_value,
151 .null_value,
152 .bool_true,
153 .bool_false,
154 => unreachable,
155
156 .ty => {
157 const payload = @fieldParentPtr(Payload.Ty, "base", self.ptr_otherwise);
158 const new_payload = try allocator.create(Payload.Ty);
159 new_payload.* = .{
160 .base = payload.base,
161 .ty = try payload.ty.copy(allocator),
162 };
163 return Value{ .ptr_otherwise = &new_payload.base };
164 },
165 .int_u64 => return self.copyPayloadShallow(allocator, Payload.Int_u64),
166 .int_i64 => return self.copyPayloadShallow(allocator, Payload.Int_i64),
167 .int_big_positive => {
168 @panic("TODO implement copying of big ints");
169 },
170 .int_big_negative => {
171 @panic("TODO implement copying of big ints");
172 },
173 .function => return self.copyPayloadShallow(allocator, Payload.Function),
174 .ref_val => {
175 const payload = @fieldParentPtr(Payload.RefVal, "base", self.ptr_otherwise);
176 const new_payload = try allocator.create(Payload.RefVal);
177 new_payload.* = .{
178 .base = payload.base,
179 .val = try payload.val.copy(allocator),
180 };
181 return Value{ .ptr_otherwise = &new_payload.base };
182 },
183 .decl_ref => return self.copyPayloadShallow(allocator, Payload.DeclRef),
184 .elem_ptr => {
185 const payload = @fieldParentPtr(Payload.ElemPtr, "base", self.ptr_otherwise);
186 const new_payload = try allocator.create(Payload.ElemPtr);
187 new_payload.* = .{
188 .base = payload.base,
189 .array_ptr = try payload.array_ptr.copy(allocator),
190 .index = payload.index,
191 };
192 return Value{ .ptr_otherwise = &new_payload.base };
193 },
194 .bytes => return self.copyPayloadShallow(allocator, Payload.Bytes),
195 .repeated => {
196 const payload = @fieldParentPtr(Payload.Repeated, "base", self.ptr_otherwise);
197 const new_payload = try allocator.create(Payload.Repeated);
198 new_payload.* = .{
199 .base = payload.base,
200 .val = try payload.val.copy(allocator),
201 };
202 return Value{ .ptr_otherwise = &new_payload.base };
203 },
204 }
205 }
206
207 fn copyPayloadShallow(self: Value, allocator: *Allocator, comptime T: type) error{OutOfMemory}!Value {
208 const payload = @fieldParentPtr(T, "base", self.ptr_otherwise);
209 const new_payload = try allocator.create(T);
210 new_payload.* = payload.*;
211 return Value{ .ptr_otherwise = &new_payload.base };
212 }
213
110 pub fn format(214 pub fn format(
111 self: Value,215 self: Value,
112 comptime fmt: []const u8,216 comptime fmt: []const u8,
...@@ -144,6 +248,7 @@ pub const Value = extern union {...@@ -144,6 +248,7 @@ pub const Value = extern union {
144 .null_type => return out_stream.writeAll("@TypeOf(null)"),248 .null_type => return out_stream.writeAll("@TypeOf(null)"),
145 .undefined_type => return out_stream.writeAll("@TypeOf(undefined)"),249 .undefined_type => return out_stream.writeAll("@TypeOf(undefined)"),
146 .fn_noreturn_no_args_type => return out_stream.writeAll("fn() noreturn"),250 .fn_noreturn_no_args_type => return out_stream.writeAll("fn() noreturn"),
251 .fn_void_no_args_type => return out_stream.writeAll("fn() void"),
147 .fn_naked_noreturn_no_args_type => return out_stream.writeAll("fn() callconv(.Naked) noreturn"),252 .fn_naked_noreturn_no_args_type => return out_stream.writeAll("fn() callconv(.Naked) noreturn"),
148 .fn_ccc_void_no_args_type => return out_stream.writeAll("fn() callconv(.C) void"),253 .fn_ccc_void_no_args_type => return out_stream.writeAll("fn() callconv(.C) void"),
149 .single_const_pointer_to_comptime_int_type => return out_stream.writeAll("*const comptime_int"),254 .single_const_pointer_to_comptime_int_type => return out_stream.writeAll("*const comptime_int"),
...@@ -229,6 +334,7 @@ pub const Value = extern union {...@@ -229,6 +334,7 @@ pub const Value = extern union {
229 .null_type => Type.initTag(.@"null"),334 .null_type => Type.initTag(.@"null"),
230 .undefined_type => Type.initTag(.@"undefined"),335 .undefined_type => Type.initTag(.@"undefined"),
231 .fn_noreturn_no_args_type => Type.initTag(.fn_noreturn_no_args),336 .fn_noreturn_no_args_type => Type.initTag(.fn_noreturn_no_args),
337 .fn_void_no_args_type => Type.initTag(.fn_void_no_args),
232 .fn_naked_noreturn_no_args_type => Type.initTag(.fn_naked_noreturn_no_args),338 .fn_naked_noreturn_no_args_type => Type.initTag(.fn_naked_noreturn_no_args),
233 .fn_ccc_void_no_args_type => Type.initTag(.fn_ccc_void_no_args),339 .fn_ccc_void_no_args_type => Type.initTag(.fn_ccc_void_no_args),
234 .single_const_pointer_to_comptime_int_type => Type.initTag(.single_const_pointer_to_comptime_int),340 .single_const_pointer_to_comptime_int_type => Type.initTag(.single_const_pointer_to_comptime_int),
...@@ -286,6 +392,7 @@ pub const Value = extern union {...@@ -286,6 +392,7 @@ pub const Value = extern union {
286 .null_type,392 .null_type,
287 .undefined_type,393 .undefined_type,
288 .fn_noreturn_no_args_type,394 .fn_noreturn_no_args_type,
395 .fn_void_no_args_type,
289 .fn_naked_noreturn_no_args_type,396 .fn_naked_noreturn_no_args_type,
290 .fn_ccc_void_no_args_type,397 .fn_ccc_void_no_args_type,
291 .single_const_pointer_to_comptime_int_type,398 .single_const_pointer_to_comptime_int_type,
...@@ -345,6 +452,7 @@ pub const Value = extern union {...@@ -345,6 +452,7 @@ pub const Value = extern union {
345 .null_type,452 .null_type,
346 .undefined_type,453 .undefined_type,
347 .fn_noreturn_no_args_type,454 .fn_noreturn_no_args_type,
455 .fn_void_no_args_type,
348 .fn_naked_noreturn_no_args_type,456 .fn_naked_noreturn_no_args_type,
349 .fn_ccc_void_no_args_type,457 .fn_ccc_void_no_args_type,
350 .single_const_pointer_to_comptime_int_type,458 .single_const_pointer_to_comptime_int_type,
...@@ -405,6 +513,7 @@ pub const Value = extern union {...@@ -405,6 +513,7 @@ pub const Value = extern union {
405 .null_type,513 .null_type,
406 .undefined_type,514 .undefined_type,
407 .fn_noreturn_no_args_type,515 .fn_noreturn_no_args_type,
516 .fn_void_no_args_type,
408 .fn_naked_noreturn_no_args_type,517 .fn_naked_noreturn_no_args_type,
409 .fn_ccc_void_no_args_type,518 .fn_ccc_void_no_args_type,
410 .single_const_pointer_to_comptime_int_type,519 .single_const_pointer_to_comptime_int_type,
...@@ -470,6 +579,7 @@ pub const Value = extern union {...@@ -470,6 +579,7 @@ pub const Value = extern union {
470 .null_type,579 .null_type,
471 .undefined_type,580 .undefined_type,
472 .fn_noreturn_no_args_type,581 .fn_noreturn_no_args_type,
582 .fn_void_no_args_type,
473 .fn_naked_noreturn_no_args_type,583 .fn_naked_noreturn_no_args_type,
474 .fn_ccc_void_no_args_type,584 .fn_ccc_void_no_args_type,
475 .single_const_pointer_to_comptime_int_type,585 .single_const_pointer_to_comptime_int_type,
...@@ -564,6 +674,7 @@ pub const Value = extern union {...@@ -564,6 +674,7 @@ pub const Value = extern union {
564 .null_type,674 .null_type,
565 .undefined_type,675 .undefined_type,
566 .fn_noreturn_no_args_type,676 .fn_noreturn_no_args_type,
677 .fn_void_no_args_type,
567 .fn_naked_noreturn_no_args_type,678 .fn_naked_noreturn_no_args_type,
568 .fn_ccc_void_no_args_type,679 .fn_ccc_void_no_args_type,
569 .single_const_pointer_to_comptime_int_type,680 .single_const_pointer_to_comptime_int_type,
...@@ -620,6 +731,7 @@ pub const Value = extern union {...@@ -620,6 +731,7 @@ pub const Value = extern union {
620 .null_type,731 .null_type,
621 .undefined_type,732 .undefined_type,
622 .fn_noreturn_no_args_type,733 .fn_noreturn_no_args_type,
734 .fn_void_no_args_type,
623 .fn_naked_noreturn_no_args_type,735 .fn_naked_noreturn_no_args_type,
624 .fn_ccc_void_no_args_type,736 .fn_ccc_void_no_args_type,
625 .single_const_pointer_to_comptime_int_type,737 .single_const_pointer_to_comptime_int_type,
...@@ -721,6 +833,7 @@ pub const Value = extern union {...@@ -721,6 +833,7 @@ pub const Value = extern union {
721 .null_type,833 .null_type,
722 .undefined_type,834 .undefined_type,
723 .fn_noreturn_no_args_type,835 .fn_noreturn_no_args_type,
836 .fn_void_no_args_type,
724 .fn_naked_noreturn_no_args_type,837 .fn_naked_noreturn_no_args_type,
725 .fn_ccc_void_no_args_type,838 .fn_ccc_void_no_args_type,
726 .single_const_pointer_to_comptime_int_type,839 .single_const_pointer_to_comptime_int_type,
...@@ -783,6 +896,7 @@ pub const Value = extern union {...@@ -783,6 +896,7 @@ pub const Value = extern union {
783 .null_type,896 .null_type,
784 .undefined_type,897 .undefined_type,
785 .fn_noreturn_no_args_type,898 .fn_noreturn_no_args_type,
899 .fn_void_no_args_type,
786 .fn_naked_noreturn_no_args_type,900 .fn_naked_noreturn_no_args_type,
787 .fn_ccc_void_no_args_type,901 .fn_ccc_void_no_args_type,
788 .single_const_pointer_to_comptime_int_type,902 .single_const_pointer_to_comptime_int_type,
...@@ -862,6 +976,7 @@ pub const Value = extern union {...@@ -862,6 +976,7 @@ pub const Value = extern union {
862 .null_type,976 .null_type,
863 .undefined_type,977 .undefined_type,
864 .fn_noreturn_no_args_type,978 .fn_noreturn_no_args_type,
979 .fn_void_no_args_type,
865 .fn_naked_noreturn_no_args_type,980 .fn_naked_noreturn_no_args_type,
866 .fn_ccc_void_no_args_type,981 .fn_ccc_void_no_args_type,
867 .single_const_pointer_to_comptime_int_type,982 .single_const_pointer_to_comptime_int_type,
...@@ -929,11 +1044,6 @@ pub const Value = extern union {...@@ -929,11 +1044,6 @@ pub const Value = extern union {
929 len: u64,1044 len: u64,
930 };1045 };
9311046
932 pub const SingleConstPtrType = struct {
933 base: Payload = Payload{ .tag = .single_const_ptr_type },
934 elem_type: *Type,
935 };
936
937 /// Represents a pointer to another immutable value.1047 /// Represents a pointer to another immutable value.
938 pub const RefVal = struct {1048 pub const RefVal = struct {
939 base: Payload = Payload{ .tag = .ref_val },1049 base: Payload = Payload{ .tag = .ref_val },
src-self-hosted/zir.zig+66-8
...@@ -25,6 +25,9 @@ pub const Inst = struct {...@@ -25,6 +25,9 @@ pub const Inst = struct {
25 /// Hash of slice into the source of the part after the = and before the next instruction.25 /// Hash of slice into the source of the part after the = and before the next instruction.
26 contents_hash: std.zig.SrcHash = undefined,26 contents_hash: std.zig.SrcHash = undefined,
2727
28 /// Pre-allocated field for mapping ZIR text instructions to post-analysis instructions.
29 analyzed_inst: *ir.Inst = undefined,
30
28 /// These names are used directly as the instruction names in the text format.31 /// These names are used directly as the instruction names in the text format.
29 pub const Tag = enum {32 pub const Tag = enum {
30 breakpoint,33 breakpoint,
...@@ -37,6 +40,8 @@ pub const Inst = struct {...@@ -37,6 +40,8 @@ pub const Inst = struct {
37 /// The syntax `@foo` is equivalent to `declval("foo")`.40 /// The syntax `@foo` is equivalent to `declval("foo")`.
38 /// declval is equivalent to declref followed by deref.41 /// declval is equivalent to declref followed by deref.
39 declval,42 declval,
43 /// Same as declval but the parameter is a `*Module.Decl` rather than a name.
44 declval_in_module,
40 str,45 str,
41 int,46 int,
42 ptrtoint,47 ptrtoint,
...@@ -46,6 +51,7 @@ pub const Inst = struct {...@@ -46,6 +51,7 @@ pub const Inst = struct {
46 @"asm",51 @"asm",
47 @"unreachable",52 @"unreachable",
48 @"return",53 @"return",
54 returnvoid,
49 @"fn",55 @"fn",
50 fntype,56 fntype,
51 @"export",57 @"export",
...@@ -67,6 +73,7 @@ pub const Inst = struct {...@@ -67,6 +73,7 @@ pub const Inst = struct {
67 .call => Call,73 .call => Call,
68 .declref => DeclRef,74 .declref => DeclRef,
69 .declval => DeclVal,75 .declval => DeclVal,
76 .declval_in_module => DeclValInModule,
70 .compileerror => CompileError,77 .compileerror => CompileError,
71 .@"const" => Const,78 .@"const" => Const,
72 .str => Str,79 .str => Str,
...@@ -78,6 +85,7 @@ pub const Inst = struct {...@@ -78,6 +85,7 @@ pub const Inst = struct {
78 .@"asm" => Asm,85 .@"asm" => Asm,
79 .@"unreachable" => Unreachable,86 .@"unreachable" => Unreachable,
80 .@"return" => Return,87 .@"return" => Return,
88 .returnvoid => ReturnVoid,
81 .@"fn" => Fn,89 .@"fn" => Fn,
82 .@"export" => Export,90 .@"export" => Export,
83 .primitive => Primitive,91 .primitive => Primitive,
...@@ -142,6 +150,16 @@ pub const Inst = struct {...@@ -142,6 +150,16 @@ pub const Inst = struct {
142 kw_args: struct {},150 kw_args: struct {},
143 };151 };
144152
153 pub const DeclValInModule = struct {
154 pub const base_tag = Tag.declval_in_module;
155 base: Inst,
156
157 positionals: struct {
158 decl: *IrModule.Decl,
159 },
160 kw_args: struct {},
161 };
162
145 pub const CompileError = struct {163 pub const CompileError = struct {
146 pub const base_tag = Tag.compileerror;164 pub const base_tag = Tag.compileerror;
147 base: Inst,165 base: Inst,
...@@ -253,6 +271,16 @@ pub const Inst = struct {...@@ -253,6 +271,16 @@ pub const Inst = struct {
253 pub const base_tag = Tag.@"return";271 pub const base_tag = Tag.@"return";
254 base: Inst,272 base: Inst,
255273
274 positionals: struct {
275 operand: *Inst,
276 },
277 kw_args: struct {},
278 };
279
280 pub const ReturnVoid = struct {
281 pub const base_tag = Tag.returnvoid;
282 base: Inst,
283
256 positionals: struct {},284 positionals: struct {},
257 kw_args: struct {},285 kw_args: struct {},
258 };286 };
...@@ -492,11 +520,19 @@ pub const Module = struct {...@@ -492,11 +520,19 @@ pub const Module = struct {
492520
493 const InstPtrTable = std.AutoHashMap(*Inst, struct { inst: *Inst, index: ?usize });521 const InstPtrTable = std.AutoHashMap(*Inst, struct { inst: *Inst, index: ?usize });
494522
523 const DeclAndIndex = struct {
524 decl: *Inst,
525 index: usize,
526 };
527
495 /// TODO Look into making a table to speed this up.528 /// TODO Look into making a table to speed this up.
496 pub fn findDecl(self: Module, name: []const u8) ?*Inst {529 pub fn findDecl(self: Module, name: []const u8) ?DeclAndIndex {
497 for (self.decls) |decl| {530 for (self.decls) |decl, i| {
498 if (mem.eql(u8, decl.name, name)) {531 if (mem.eql(u8, decl.name, name)) {
499 return decl;532 return DeclAndIndex{
533 .decl = decl,
534 .index = i,
535 };
500 }536 }
501 }537 }
502 return null;538 return null;
...@@ -540,6 +576,7 @@ pub const Module = struct {...@@ -540,6 +576,7 @@ pub const Module = struct {
540 .call => return self.writeInstToStreamGeneric(stream, .call, decl, inst_table),576 .call => return self.writeInstToStreamGeneric(stream, .call, decl, inst_table),
541 .declref => return self.writeInstToStreamGeneric(stream, .declref, decl, inst_table),577 .declref => return self.writeInstToStreamGeneric(stream, .declref, decl, inst_table),
542 .declval => return self.writeInstToStreamGeneric(stream, .declval, decl, inst_table),578 .declval => return self.writeInstToStreamGeneric(stream, .declval, decl, inst_table),
579 .declval_in_module => return self.writeInstToStreamGeneric(stream, .declval_in_module, decl, inst_table),
543 .compileerror => return self.writeInstToStreamGeneric(stream, .compileerror, decl, inst_table),580 .compileerror => return self.writeInstToStreamGeneric(stream, .compileerror, decl, inst_table),
544 .@"const" => return self.writeInstToStreamGeneric(stream, .@"const", decl, inst_table),581 .@"const" => return self.writeInstToStreamGeneric(stream, .@"const", decl, inst_table),
545 .str => return self.writeInstToStreamGeneric(stream, .str, decl, inst_table),582 .str => return self.writeInstToStreamGeneric(stream, .str, decl, inst_table),
...@@ -551,6 +588,7 @@ pub const Module = struct {...@@ -551,6 +588,7 @@ pub const Module = struct {
551 .@"asm" => return self.writeInstToStreamGeneric(stream, .@"asm", decl, inst_table),588 .@"asm" => return self.writeInstToStreamGeneric(stream, .@"asm", decl, inst_table),
552 .@"unreachable" => return self.writeInstToStreamGeneric(stream, .@"unreachable", decl, inst_table),589 .@"unreachable" => return self.writeInstToStreamGeneric(stream, .@"unreachable", decl, inst_table),
553 .@"return" => return self.writeInstToStreamGeneric(stream, .@"return", decl, inst_table),590 .@"return" => return self.writeInstToStreamGeneric(stream, .@"return", decl, inst_table),
591 .returnvoid => return self.writeInstToStreamGeneric(stream, .returnvoid, decl, inst_table),
554 .@"fn" => return self.writeInstToStreamGeneric(stream, .@"fn", decl, inst_table),592 .@"fn" => return self.writeInstToStreamGeneric(stream, .@"fn", decl, inst_table),
555 .@"export" => return self.writeInstToStreamGeneric(stream, .@"export", decl, inst_table),593 .@"export" => return self.writeInstToStreamGeneric(stream, .@"export", decl, inst_table),
556 .ref => return self.writeInstToStreamGeneric(stream, .ref, decl, inst_table),594 .ref => return self.writeInstToStreamGeneric(stream, .ref, decl, inst_table),
...@@ -636,6 +674,7 @@ pub const Module = struct {...@@ -636,6 +674,7 @@ pub const Module = struct {
636 []u8, []const u8 => return std.zig.renderStringLiteral(param, stream),674 []u8, []const u8 => return std.zig.renderStringLiteral(param, stream),
637 BigIntConst => return stream.print("{}", .{param}),675 BigIntConst => return stream.print("{}", .{param}),
638 TypedValue => unreachable, // this is a special case676 TypedValue => unreachable, // this is a special case
677 *IrModule.Decl => unreachable, // this is a special case
639 else => |T| @compileError("unimplemented: rendering parameter of type " ++ @typeName(T)),678 else => |T| @compileError("unimplemented: rendering parameter of type " ++ @typeName(T)),
640 }679 }
641 }680 }
...@@ -649,6 +688,8 @@ pub const Module = struct {...@@ -649,6 +688,8 @@ pub const Module = struct {
649 }688 }
650 } else if (inst.cast(Inst.DeclVal)) |decl_val| {689 } else if (inst.cast(Inst.DeclVal)) |decl_val| {
651 try stream.print("@{}", .{decl_val.positionals.name});690 try stream.print("@{}", .{decl_val.positionals.name});
691 } else if (inst.cast(Inst.DeclValInModule)) |decl_val| {
692 try stream.print("@{}", .{decl_val.positionals.decl.name});
652 } else {693 } else {
653 //try stream.print("?", .{});694 //try stream.print("?", .{});
654 unreachable;695 unreachable;
...@@ -996,6 +1037,7 @@ const Parser = struct {...@@ -996,6 +1037,7 @@ const Parser = struct {
996 []u8, []const u8 => return self.parseStringLiteral(),1037 []u8, []const u8 => return self.parseStringLiteral(),
997 BigIntConst => return self.parseIntegerLiteral(),1038 BigIntConst => return self.parseIntegerLiteral(),
998 TypedValue => return self.fail("'const' is a special instruction; not legal in ZIR text", .{}),1039 TypedValue => return self.fail("'const' is a special instruction; not legal in ZIR text", .{}),
1040 *IrModule.Decl => return self.fail("'declval_in_module' is a special instruction; not legal in ZIR text", .{}),
999 else => @compileError("Unimplemented: ir parseParameterGeneric for type " ++ @typeName(T)),1041 else => @compileError("Unimplemented: ir parseParameterGeneric for type " ++ @typeName(T)),
1000 }1042 }
1001 return self.fail("TODO parse parameter {}", .{@typeName(T)});1043 return self.fail("TODO parse parameter {}", .{@typeName(T)});
...@@ -1105,7 +1147,7 @@ const EmitZIR = struct {...@@ -1105,7 +1147,7 @@ const EmitZIR = struct {
1105 }1147 }
1106 std.sort.sort(*IrModule.Decl, src_decls.items, {}, (struct {1148 std.sort.sort(*IrModule.Decl, src_decls.items, {}, (struct {
1107 fn lessThan(context: void, a: *IrModule.Decl, b: *IrModule.Decl) bool {1149 fn lessThan(context: void, a: *IrModule.Decl, b: *IrModule.Decl) bool {
1108 return a.src < b.src;1150 return a.src_index < b.src_index;
1109 }1151 }
1110 }).lessThan);1152 }).lessThan);
11111153
...@@ -1113,7 +1155,7 @@ const EmitZIR = struct {...@@ -1113,7 +1155,7 @@ const EmitZIR = struct {
1113 for (src_decls.items) |ir_decl| {1155 for (src_decls.items) |ir_decl| {
1114 if (self.old_module.export_owners.getValue(ir_decl)) |exports| {1156 if (self.old_module.export_owners.getValue(ir_decl)) |exports| {
1115 for (exports) |module_export| {1157 for (exports) |module_export| {
1116 const declval = try self.emitDeclVal(ir_decl.src, mem.spanZ(module_export.exported_decl.name));1158 const declval = try self.emitDeclVal(ir_decl.src(), mem.spanZ(module_export.exported_decl.name));
1117 const symbol_name = try self.emitStringLiteral(module_export.src, module_export.options.name);1159 const symbol_name = try self.emitStringLiteral(module_export.src, module_export.options.name);
1118 const export_inst = try self.arena.allocator.create(Inst.Export);1160 const export_inst = try self.arena.allocator.create(Inst.Export);
1119 export_inst.* = .{1161 export_inst.* = .{
...@@ -1131,7 +1173,7 @@ const EmitZIR = struct {...@@ -1131,7 +1173,7 @@ const EmitZIR = struct {
1131 try self.decls.append(self.allocator, &export_inst.base);1173 try self.decls.append(self.allocator, &export_inst.base);
1132 }1174 }
1133 } else {1175 } else {
1134 const new_decl = try self.emitTypedValue(ir_decl.src, ir_decl.typed_value.most_recent.typed_value);1176 const new_decl = try self.emitTypedValue(ir_decl.src(), ir_decl.typed_value.most_recent.typed_value);
1135 new_decl.name = try self.arena.allocator.dupe(u8, mem.spanZ(ir_decl.name));1177 new_decl.name = try self.arena.allocator.dupe(u8, mem.spanZ(ir_decl.name));
1136 }1178 }
1137 }1179 }
...@@ -1301,7 +1343,7 @@ const EmitZIR = struct {...@@ -1301,7 +1343,7 @@ const EmitZIR = struct {
1301 },1343 },
1302 }1344 }
13031345
1304 const fn_type = try self.emitType(src, module_fn.fn_type);1346 const fn_type = try self.emitType(src, typed_value.ty);
13051347
1306 const arena_instrs = try self.arena.allocator.alloc(*Inst, instructions.items.len);1348 const arena_instrs = try self.arena.allocator.alloc(*Inst, instructions.items.len);
1307 mem.copy(*Inst, arena_instrs, instructions.items);1349 mem.copy(*Inst, arena_instrs, instructions.items);
...@@ -1399,7 +1441,23 @@ const EmitZIR = struct {...@@ -1399,7 +1441,23 @@ const EmitZIR = struct {
1399 break :blk &new_inst.base;1441 break :blk &new_inst.base;
1400 },1442 },
1401 .unreach => try self.emitTrivial(inst.src, Inst.Unreachable),1443 .unreach => try self.emitTrivial(inst.src, Inst.Unreachable),
1402 .ret => try self.emitTrivial(inst.src, Inst.Return),1444 .ret => blk: {
1445 const old_inst = inst.cast(ir.Inst.Ret).?;
1446 const new_inst = try self.arena.allocator.create(Inst.Return);
1447 new_inst.* = .{
1448 .base = .{
1449 .name = try self.autoName(),
1450 .src = inst.src,
1451 .tag = Inst.Return.base_tag,
1452 },
1453 .positionals = .{
1454 .operand = try self.resolveInst(inst_table, old_inst.args.operand),
1455 },
1456 .kw_args = .{},
1457 };
1458 break :blk &new_inst.base;
1459 },
1460 .retvoid => try self.emitTrivial(inst.src, Inst.ReturnVoid),
1403 .constant => unreachable, // excluded from function bodies1461 .constant => unreachable, // excluded from function bodies
1404 .assembly => blk: {1462 .assembly => blk: {
1405 const old_inst = inst.cast(ir.Inst.Assembly).?;1463 const old_inst = inst.cast(ir.Inst.Assembly).?;
src/codegen.cpp+6
...@@ -7473,6 +7473,12 @@ static LLVMValueRef gen_const_val(CodeGen *g, ZigValue *const_val, const char *n...@@ -7473,6 +7473,12 @@ static LLVMValueRef gen_const_val(CodeGen *g, ZigValue *const_val, const char *n
7473 continue;7473 continue;
7474 }7474 }
7475 ZigValue *field_val = const_val->data.x_struct.fields[i];7475 ZigValue *field_val = const_val->data.x_struct.fields[i];
7476 if (field_val == nullptr) {
7477 add_node_error(g, type_struct_field->decl_node,
7478 buf_sprintf("compiler bug: generating const value for struct field '%s'",
7479 buf_ptr(type_struct_field->name)));
7480 codegen_report_errors_and_exit(g);
7481 }
7476 ZigType *field_type = field_val->type;7482 ZigType *field_type = field_val->type;
7477 assert(field_type != nullptr);7483 assert(field_type != nullptr);
7478 if ((err = ensure_const_val_repr(nullptr, g, nullptr, field_val, field_type))) {7484 if ((err = ensure_const_val_repr(nullptr, g, nullptr, field_val, field_type))) {