| ... | @@ -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. |
| 38 | export_owners: std.AutoHashMap(*Decl, []*Export), | 38 | export_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. |
| 40 | decl_table: std.AutoHashMap(Decl.Hash, *Decl), | 40 | decl_table: std.AutoHashMap(Scope.NameHash, *Decl), |
| 41 | | 41 | |
| 42 | optimize_mode: std.builtin.Mode, | 42 | optimize_mode: std.builtin.Mode, |
| 43 | link_error_flags: link.ElfFile.ErrorFlags = link.ElfFile.ErrorFlags{}, | 43 | link_error_flags: link.ElfFile.ErrorFlags = .{}, |
| 44 | | 44 | |
| 45 | work_queue: std.fifo.LinearFifo(WorkItem, .Dynamic), | 45 | work_queue: std.fifo.LinearFifo(WorkItem, .Dynamic), |
| 46 | | 46 | |
| ... | @@ -64,20 +64,15 @@ generation: u32 = 0, | ... | @@ -64,20 +64,15 @@ generation: u32 = 0, |
| 64 | | 64 | |
| 65 | /// Candidates for deletion. After a semantic analysis update completes, this list | 65 | /// 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. |
| 67 | deletion_set: std.ArrayListUnmanaged(*Decl) = std.ArrayListUnmanaged(*Decl){}, | 67 | deletion_set: std.ArrayListUnmanaged(*Decl) = .{}, |
| 68 | | 68 | |
| 69 | const WorkItem = union(enum) { | 69 | const 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 | }; |
| 82 | | 77 | |
| 83 | pub const Export = struct { | 78 | pub 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`. Functions | 119 | /// 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 complete | 127 | /// 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, |
| 160 | | 162 | |
| 161 | contents_hash: Hash, | 163 | contents_hash: std.zig.SrcHash, |
| 162 | | 164 | |
| 163 | /// The shallow set of other decls whose typed_value could possibly change if this Decl's | 165 | /// 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 | } |
| 179 | | 181 | |
| 180 | pub const Hash = [16]u8; | 182 | pub fn src(self: Decl) usize { |
| 181 | | 183 | 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 | } |
| 185 | | 201 | |
| 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 of | 203 | 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 | } |
| 194 | | 205 | |
| 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. |
| 248 | pub const Fn = struct { | 259 | pub 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_decls | 264 | /// 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 complete | 266 | /// 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 instructions | 278 | |
| 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 | }; |
| 274 | | 285 | |
| 275 | pub const Scope = struct { | 286 | pub const Scope = struct { |
| 276 | tag: Tag, | 287 | tag: Tag, |
| 277 | | 288 | |
| | 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 | } |
| 316 | | 332 | |
| | 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 | } |
| 326 | | 356 | |
| ... | @@ -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 | }; |
| 394 | | 429 | |
| 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 | }; |
| 465 | | 505 | |
| 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 | }; |
| 545 | | 590 | |
| 546 | /// This is a temporary structure, references to it are valid only | 591 | /// 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 DeclAnalysis | 599 | /// 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 | }; |
| 567 | | 622 | |
| 568 | pub const Body = struct { | 623 | pub 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 | } |
| 767 | | 822 | |
| | 823 | self.link_error_flags = self.bin_file.error_flags; |
| | 824 | |
| 768 | // If there are any errors, we anticipate the source files being loaded | 825 | // 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 | } |
| 777 | | 832 | |
| 778 | /// Having the file open for writing is problematic as far as executing the | 833 | /// 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 }; |
| 852 | pub fn performAllTheWork(self: *Module) error{OutOfMemory}!void { | 907 | pub 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, |
| 857 | | 913 | |
| 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, |
| 862 | | 919 | |
| 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, |
| 903 | | 959 | |
| 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, |
| 910 | | 967 | |
| 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 | } |
| 949 | | 1007 | |
| 950 | fn astGenDecl(self: *Module, parent_scope: *Scope, ast_node: *ast.Node) !void { | 1008 | fn 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 | |
| | 1042 | fn 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); |
| 954 | | 1049 | |
| 955 | const name_tok = fn_proto.name_token orelse | 1050 | 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 memory | 1060 | defer fn_type_scope.arena.deinit(); |
| 971 | //defer gen_scope.arena.deinit(); | 1061 | defer fn_type_scope.instructions.deinit(); |
| 972 | | 1062 | |
| 973 | const body_node = fn_proto.body_node orelse | 1063 | 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 | }; |
| 1005 | | 1095 | |
| 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 }); |
| 1037 | | 1172 | |
| 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 | } |
| 1087 | | 1189 | |
| | 1190 | fn 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 | |
| 1088 | fn astGenExpr(self: *Module, scope: *Scope, ast_node: *ast.Node) InnerError!*zir.Inst { | 1203 | fn 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 | } |
| 1099 | | 1216 | |
| | 1217 | fn 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 | |
| 1100 | fn astGenIdent(self: *Module, scope: *Scope, ident: *ast.Node.Identifier) InnerError!*zir.Inst { | 1237 | fn 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 | } |
| 1106 | | 1243 | |
| 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 | } |
| 1122 | | 1248 | |
| 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 | } |
| 1139 | | 1265 | |
| 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 | } |
| 1142 | | 1276 | |
| 1143 | fn astGenStringLiteral(self: *Module, scope: *Scope, str_lit: *ast.Node.StringLiteral) InnerError!*zir.Inst { | 1277 | fn 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 | }; |
| 1157 | | 1291 | |
| 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 | } |
| 1184 | | 1296 | |
| 1185 | fn astGenIntegerLiteral(self: *Module, scope: *Scope, int_lit: *ast.Node.IntegerLiteral) InnerError!*zir.Inst { | 1297 | fn 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 | } |
| 1222 | | 1321 | |
| 1223 | fn astGenBlock(self: *Module, scope: *Scope, block_node: *ast.Node.Block) !zir.Module.Body { | 1322 | fn 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 | } |
| 1241 | | 1330 | |
| 1242 | fn astGenAsm(self: *Module, scope: *Scope, asm_node: *ast.Node.Asm) InnerError!*zir.Inst { | 1331 | fn 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 | } |
| 1257 | | 1346 | |
| 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 | } |
| 1294 | | 1363 | |
| 1295 | fn astGenBuiltinCall(self: *Module, scope: *Scope, call: *ast.Node.BuiltinCall) InnerError!*zir.Inst { | 1364 | fn 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(); | | |
| 1299 | | 1367 | |
| 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 | } |
| 1321 | | 1380 | |
| | 1381 | fn 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 | |
| 1322 | fn astGenUnreachable(self: *Module, scope: *Scope, unreach_node: *ast.Node.Unreachable) InnerError!*zir.Inst { | 1396 | fn 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 | } |
| 1337 | | 1401 | |
| 1338 | fn getSimplePrimitiveValue(name: []const u8) ?TypedValue { | 1402 | fn 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 { |
| 1501 | | 1565 | |
| 1502 | try self.work_queue.ensureUnusedCapacity(decls.len); | 1566 | try self.work_queue.ensureUnusedCapacity(decls.len); |
| 1503 | | 1567 | |
| 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 globals | 1585 | // 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 | } |
| 1568 | | 1636 | |
| 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(); | | |
| 1679 | | 1742 | |
| 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}); |
| 1682 | | 1747 | |
| 1683 | try self.analyzeBody(&analysis.inner_block.base, fn_inst.positionals.body); | 1748 | try self.analyzeBody(&inner_block.base, fn_zir.body); |
| 1684 | | 1749 | |
| 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 | } |
| 1691 | | 1754 | |
| 1692 | fn reAnalyzeDecl(self: *Module, decl: *Decl, old_inst: *zir.Inst) InnerError!void { | 1755 | fn 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-analysis | 1767 | .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; | | |
| 1706 | | 1770 | |
| 1707 | // The exports this Decl performs will be re-discovered, so we remove them here | 1771 | // 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 update | 1840 | .outdated => continue, // already queued for update |
| 1776 | | 1841 | |
| 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 { |
| 1799 | fn allocateNewDecl( | 1865 | fn 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(); |
| 1842 | | 1908 | |
| | 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 | } |
| 1874 | | 1942 | |
| 1875 | fn resolveDecl(self: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError!*Decl { | 1943 | fn 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); |
| 1893 | | 1961 | // try self.analyzeNewDecl(new_decl, old_inst); |
| 1894 | return new_decl; | 1962 | |
| 1895 | } | 1963 | // return new_decl; |
| | 1964 | //} |
| 1896 | } | 1965 | } |
| 1897 | | 1966 | |
| 1898 | /// Declares a dependency on the decl. | 1967 | /// Declares a dependency on the decl. |
| 1899 | fn resolveCompleteDecl(self: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError!*Decl { | 1968 | fn 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, |
| 1904 | | 1974 | |
| 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 | } |
| 1918 | | 1989 | |
| | 1990 | /// TODO look into removing this function |
| 1919 | fn resolveInst(self: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError!*Inst { | 1991 | fn 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 | } |
| 1934 | | 1994 | |
| 1935 | fn requireRuntimeBlock(self: *Module, scope: *Scope, src: usize) !*Scope.Block { | 1995 | fn 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 | } |
| 1979 | | 2039 | |
| 1980 | fn analyzeExport(self: *Module, scope: *Scope, export_inst: *zir.Inst.Export) InnerError!void { | 2040 | fn 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); |
| 1997 | | 2051 | |
| ... | @@ -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 |
| 1999 | | 2053 | |
| 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 | } |
| 2041 | | 2095 | |
| 2042 | /// TODO should not need the cast on the last parameter at the callsites | | |
| 2043 | fn addNewInstArgs( | 2096 | fn 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 | } |
| 2055 | | 2108 | |
| | 2109 | fn 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 | |
| | 2129 | fn 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. |
| | 2145 | fn 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 | |
| 2056 | fn addNewInst(self: *Module, block: *Scope.Block, src: usize, ty: Type, comptime T: type) !*T { | 2150 | fn 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 | } |
| 2109 | | 2203 | |
| | 2204 | fn 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 | |
| 2110 | fn constUndef(self: *Module, scope: *Scope, src: usize, ty: Type) !*Inst { | 2211 | fn 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 | } |
| 2180 | | 2281 | |
| 2181 | fn analyzeInstConst(self: *Module, scope: *Scope, const_inst: *zir.Inst.Const) InnerError!*Inst { | 2282 | fn 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 | } |
| 2184 | | 2288 | |
| 2185 | fn analyzeInst(self: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError!*Inst { | 2289 | fn 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 deallocated | 2300 | // 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 | } |
| 2229 | | 2332 | |
| | 2333 | fn 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 | |
| 2230 | fn analyzeInstCompileError(self: *Module, scope: *Scope, inst: *zir.Inst.CompileError) InnerError!*Inst { | 2340 | fn 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 | } |
| 2233 | | 2343 | |
| 2234 | fn analyzeInstBreakpoint(self: *Module, scope: *Scope, inst: *zir.Inst.Breakpoint) InnerError!*Inst { | 2344 | fn 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 | } |
| 2238 | | 2348 | |
| 2239 | fn analyzeInstRef(self: *Module, scope: *Scope, inst: *zir.Inst.Ref) InnerError!*Inst { | 2349 | fn 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) orelse | 2361 | 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}); |
| 2253 | | 2363 | |
| 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) orelse | 2374 | 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}); |
| 2266 | | 2376 | |
| 2267 | const decl = try self.resolveCompleteDecl(scope, src_decl); | 2377 | const decl = try self.resolveCompleteDecl(scope, src_decl.decl); |
| 2268 | | 2378 | |
| 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 | } |
| 2277 | | 2387 | |
| | 2388 | fn 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 | |
| 2278 | fn analyzeDeclRef(self: *Module, scope: *Scope, src: usize, decl: *Decl) InnerError!*Inst { | 2394 | fn 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 | } |
| 2346 | | 2478 | |
| 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 | } |
| 2353 | | 2485 | |
| 2354 | fn analyzeInstFn(self: *Module, scope: *Scope, fn_inst: *zir.Inst.Fn) InnerError!*Inst { | 2486 | fn 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 | } |
| 2369 | | 2501 | |
| 2370 | fn analyzeInstFnType(self: *Module, scope: *Scope, fntype: *zir.Inst.FnType) InnerError!*Inst { | 2502 | fn 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 | } |
| 2379 | | 2511 | |
| | 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 and | 2519 | if (return_type.zigTypeTag() == .NoReturn and |
| 2381 | fntype.positionals.param_types.len == 0 and | 2520 | 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-address | 2551 | // 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 | } |
| 2417 | | 2556 | |
| 2418 | fn analyzeInstFieldPtr(self: *Module, scope: *Scope, fieldptr: *zir.Inst.FieldPtr) InnerError!*Inst { | 2557 | fn 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 | } |
| 2605 | | 2744 | |
| 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 and | 2790 | } 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 | } |
| 2749 | | 2880 | |
| 2750 | fn analyzeInstRet(self: *Module, scope: *Scope, inst: *zir.Inst.Return) InnerError!*Inst { | 2881 | fn 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 | |
| | 2887 | fn 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 | } |
| 2754 | | 2891 | |
| 2755 | fn analyzeBody(self: *Module, scope: *Scope, body: zir.Module.Body) !void { | 2892 | fn 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 | } |
| 2770 | | 2897 | |
| ... | @@ -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); |
| 2953 | | 3080 | |
| 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 errors | 3156 | // 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 | } |
| 3033 | | 3160 | |
| 3034 | fn coerceArrayPtrToSlice(self: *Module, scope: *Scope, dest_type: Type, inst: *Inst) !*Inst { | 3161 | fn 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; |