authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-05-13 20:06:01-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-05-13 20:06:01-04:00
log080022f6c670b0f74c39fe01096ebdbaafeda1b2
treeaa3dae7fa7f88f84a8cc32496d0db00222b16ea4
parenta3da584248c1152c01a1a7f878c164fb19b8e04a

self-hosted: fix compile errors, except for codegen.zig


8 files changed, 525 insertions(+), 264 deletions(-)

lib/std/array_list.zig+1-8
...@@ -269,13 +269,6 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type {...@@ -269,13 +269,6 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type {
269269
270/// Bring-your-own allocator with every function call.270/// Bring-your-own allocator with every function call.
271/// Initialize directly and deinitialize with `deinit` or use `toOwnedSlice`.271/// Initialize directly and deinitialize with `deinit` or use `toOwnedSlice`.
272pub fn init() Self {
273 return .{
274 .items = &[_]T{},
275 .capacity = 0,
276 };
277}
278
279pub fn ArrayListUnmanaged(comptime T: type) type {272pub fn ArrayListUnmanaged(comptime T: type) type {
280 return ArrayListAlignedUnmanaged(T, null);273 return ArrayListAlignedUnmanaged(T, null);
281}274}
...@@ -317,7 +310,7 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ...@@ -317,7 +310,7 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ
317 /// The caller owns the returned memory. ArrayList becomes empty.310 /// The caller owns the returned memory. ArrayList becomes empty.
318 pub fn toOwnedSlice(self: *Self, allocator: *Allocator) Slice {311 pub fn toOwnedSlice(self: *Self, allocator: *Allocator) Slice {
319 const result = allocator.shrink(self.allocatedSlice(), self.items.len);312 const result = allocator.shrink(self.allocatedSlice(), self.items.len);
320 self.* = init(allocator);313 self.* = Self{};
321 return result;314 return result;
322 }315 }
323316
lib/std/mem.zig+19-9
...@@ -279,6 +279,21 @@ pub const Allocator = struct {...@@ -279,6 +279,21 @@ pub const Allocator = struct {
279 const shrink_result = self.shrinkFn(self, non_const_ptr[0..bytes_len], Slice.alignment, 0, 1);279 const shrink_result = self.shrinkFn(self, non_const_ptr[0..bytes_len], Slice.alignment, 0, 1);
280 assert(shrink_result.len == 0);280 assert(shrink_result.len == 0);
281 }281 }
282
283 /// Copies `m` to newly allocated memory. Caller owns the memory.
284 pub fn dupe(allocator: *Allocator, comptime T: type, m: []const T) ![]T {
285 const new_buf = try allocator.alloc(T, m.len);
286 copy(T, new_buf, m);
287 return new_buf;
288 }
289
290 /// Copies `m` to newly allocated memory, with a null-terminated element. Caller owns the memory.
291 pub fn dupeZ(allocator: *Allocator, comptime T: type, m: []const T) ![:0]T {
292 const new_buf = try allocator.alloc(T, m.len + 1);
293 copy(T, new_buf, m);
294 new_buf[m.len] = 0;
295 return new_buf[0..m.len :0];
296 }
282};297};
283298
284/// Copy all of source into dest at position 0.299/// Copy all of source into dest at position 0.
...@@ -762,19 +777,14 @@ pub fn allEqual(comptime T: type, slice: []const T, scalar: T) bool {...@@ -762,19 +777,14 @@ pub fn allEqual(comptime T: type, slice: []const T, scalar: T) bool {
762 return true;777 return true;
763}778}
764779
765/// Copies `m` to newly allocated memory. Caller owns the memory.780/// Deprecated, use `Allocator.dupe`.
766pub fn dupe(allocator: *Allocator, comptime T: type, m: []const T) ![]T {781pub fn dupe(allocator: *Allocator, comptime T: type, m: []const T) ![]T {
767 const new_buf = try allocator.alloc(T, m.len);782 return allocator.dupe(T, m);
768 copy(T, new_buf, m);
769 return new_buf;
770}783}
771784
772/// Copies `m` to newly allocated memory, with a null-terminated element. Caller owns the memory.785/// Deprecated, use `Allocator.dupeZ`.
773pub fn dupeZ(allocator: *Allocator, comptime T: type, m: []const T) ![:0]T {786pub fn dupeZ(allocator: *Allocator, comptime T: type, m: []const T) ![:0]T {
774 const new_buf = try allocator.alloc(T, m.len + 1);787 return allocator.dupeZ(T, m);
775 copy(T, new_buf, m);
776 new_buf[m.len] = 0;
777 return new_buf[0..m.len :0];
778}788}
779789
780/// Remove values from the beginning of a slice.790/// Remove values from the beginning of a slice.
src-self-hosted/TypedValue.zig+1-1
...@@ -16,7 +16,7 @@ pub const Managed = struct {...@@ -16,7 +16,7 @@ pub const Managed = struct {
16 /// If this is `null` then there is no memory management needed.16 /// If this is `null` then there is no memory management needed.
17 arena: ?*std.heap.ArenaAllocator.State = null,17 arena: ?*std.heap.ArenaAllocator.State = null,
1818
19 pub fn deinit(self: *ManagedTypedValue, allocator: *Allocator) void {19 pub fn deinit(self: *Managed, allocator: *Allocator) void {
20 if (self.arena) |a| a.promote(allocator).deinit();20 if (self.arena) |a| a.promote(allocator).deinit();
21 self.* = undefined;21 self.* = undefined;
22 }22 }
src-self-hosted/codegen.zig+2-1
...@@ -4,10 +4,11 @@ const assert = std.debug.assert;...@@ -4,10 +4,11 @@ const assert = std.debug.assert;
4const ir = @import("ir.zig");4const ir = @import("ir.zig");
5const Type = @import("type.zig").Type;5const Type = @import("type.zig").Type;
6const Value = @import("value.zig").Value;6const Value = @import("value.zig").Value;
7const TypedValue = @import("TypedValue.zig");
7const Target = std.Target;8const Target = std.Target;
8const Allocator = mem.Allocator;9const Allocator = mem.Allocator;
910
10pub fn generateSymbol(typed_value: ir.TypedValue, module: ir.Module, code: *std.ArrayList(u8)) !?*ir.ErrorMsg {11pub fn generateSymbol(typed_value: TypedValue, module: ir.Module, code: *std.ArrayList(u8)) !?*ir.ErrorMsg {
11 switch (typed_value.ty.zigTypeTag()) {12 switch (typed_value.ty.zigTypeTag()) {
12 .Fn => {13 .Fn => {
13 const module_fn = typed_value.val.cast(Value.Payload.Function).?.func;14 const module_fn = typed_value.val.cast(Value.Payload.Function).?.func;
src-self-hosted/ir.zig+272-158
...@@ -196,11 +196,9 @@ pub const Module = struct {...@@ -196,11 +196,9 @@ pub const Module = struct {
196 /// We optimize memory usage for a compilation with no compile errors by storing the196 /// We optimize memory usage for a compilation with no compile errors by storing the
197 /// error messages and mapping outside of `Decl`.197 /// error messages and mapping outside of `Decl`.
198 /// The ErrorMsg memory is owned by the decl, using Module's allocator.198 /// The ErrorMsg memory is owned by the decl, using Module's allocator.
199 /// Note that a Decl can succeed but the Fn it represents can fail. In this case,
200 /// a Decl can have a failed_decls entry but have analysis status of success.
199 failed_decls: std.AutoHashMap(*Decl, *ErrorMsg),201 failed_decls: std.AutoHashMap(*Decl, *ErrorMsg),
200 /// We optimize memory usage for a compilation with no compile errors by storing the
201 /// error messages and mapping outside of `Fn`.
202 /// The ErrorMsg memory is owned by the `Fn`, using Module's allocator.
203 failed_fns: std.AutoHashMap(*Fn, *ErrorMsg),
204 /// Using a map here for consistency with the other fields here.202 /// Using a map here for consistency with the other fields here.
205 /// The ErrorMsg memory is owned by the `Scope.ZIRModule`, using Module's allocator.203 /// The ErrorMsg memory is owned by the `Scope.ZIRModule`, using Module's allocator.
206 failed_files: std.AutoHashMap(*Scope.ZIRModule, *ErrorMsg),204 failed_files: std.AutoHashMap(*Scope.ZIRModule, *ErrorMsg),
...@@ -221,7 +219,14 @@ pub const Module = struct {...@@ -221,7 +219,14 @@ pub const Module = struct {
221 link: link.ElfFile.Export,219 link: link.ElfFile.Export,
222 /// The Decl that performs the export. Note that this is *not* the Decl being exported.220 /// The Decl that performs the export. Note that this is *not* the Decl being exported.
223 owner_decl: *Decl,221 owner_decl: *Decl,
224 status: enum { in_progress, failed, complete },222 status: enum {
223 in_progress,
224 failed,
225 /// Indicates that the failure was due to a temporary issue, such as an I/O error
226 /// when writing to the output file. Retrying the export may succeed.
227 failed_retryable,
228 complete,
229 },
225 };230 };
226231
227 pub const Decl = struct {232 pub const Decl = struct {
...@@ -260,6 +265,11 @@ pub const Module = struct {...@@ -260,6 +265,11 @@ pub const Module = struct {
260 /// In this case the `typed_value.most_recent` can still be accessed.265 /// In this case the `typed_value.most_recent` can still be accessed.
261 /// There will be a corresponding ErrorMsg in Module.failed_decls.266 /// There will be a corresponding ErrorMsg in Module.failed_decls.
262 codegen_failure,267 codegen_failure,
268 /// In this case the `typed_value.most_recent` can still be accessed.
269 /// There will be a corresponding ErrorMsg in Module.failed_decls.
270 /// This indicates the failure was something like running out of disk space,
271 /// and attempting codegen again may succeed.
272 codegen_failure_retryable,
263 /// This Decl might be OK but it depends on another one which did not successfully complete273 /// This Decl might be OK but it depends on another one which did not successfully complete
264 /// semantic analysis. There is a most recent value available.274 /// semantic analysis. There is a most recent value available.
265 repeat_dependency_failure,275 repeat_dependency_failure,
...@@ -280,40 +290,63 @@ pub const Module = struct {...@@ -280,40 +290,63 @@ pub const Module = struct {
280 /// The shallow set of other decls whose typed_value could possibly change if this Decl's290 /// The shallow set of other decls whose typed_value could possibly change if this Decl's
281 /// typed_value is modified.291 /// typed_value is modified.
282 /// TODO look into using a lightweight map/set data structure rather than a linear array.292 /// TODO look into using a lightweight map/set data structure rather than a linear array.
283 dependants: ArrayListUnmanaged(*Decl) = .{},293 dependants: ArrayListUnmanaged(*Decl) = ArrayListUnmanaged(*Decl){},
284
285 pub fn typedValue(self: Decl) ?TypedValue {
286 switch (self.analysis) {
287 .initial_in_progress,
288 .initial_dependency_failure,
289 .initial_sema_failure,
290 => return null,
291 .codegen_failure,
292 .repeat_dependency_failure,
293 .repeat_sema_failure,
294 .repeat_in_progress,
295 .complete,
296 => return self.typed_value.most_recent,
297 }
298 }
299294
300 pub fn destroy(self: *Decl, allocator: *Allocator) void {295 pub fn destroy(self: *Decl, allocator: *Allocator) void {
301 allocator.free(mem.spanZ(u8, self.name));296 allocator.free(mem.spanZ(self.name));
302 if (self.typedValue()) |tv| tv.deinit(allocator);297 if (self.typedValueManaged()) |tvm| {
298 tvm.deinit(allocator);
299 }
303 allocator.destroy(self);300 allocator.destroy(self);
304 }301 }
305302
306 pub const Hash = [16]u8;303 pub const Hash = [16]u8;
307304
305 /// If the name is small enough, it is used directly as the hash.
306 /// If it is long, blake3 hash is computed.
307 pub fn hashSimpleName(name: []const u8) Hash {
308 var out: Hash = undefined;
309 if (name.len <= Hash.len) {
310 mem.copy(u8, &out, name);
311 mem.set(u8, out[name.len..], 0);
312 } else {
313 std.crypto.Blake3.hash(name, &out);
314 }
315 return out;
316 }
317
308 /// Must generate unique bytes with no collisions with other decls.318 /// Must generate unique bytes with no collisions with other decls.
309 /// The point of hashing here is only to limit the number of bytes of319 /// The point of hashing here is only to limit the number of bytes of
310 /// the unique identifier to a fixed size (16 bytes).320 /// the unique identifier to a fixed size (16 bytes).
311 pub fn fullyQualifiedNameHash(self: Decl) Hash {321 pub fn fullyQualifiedNameHash(self: Decl) Hash {
312 // Right now we only have ZIRModule as the source. So this is simply the322 // Right now we only have ZIRModule as the source. So this is simply the
313 // relative name of the decl.323 // relative name of the decl.
314 var out: Hash = undefined;324 return hashSimpleName(mem.spanZ(u8, self.name));
315 std.crypto.Blake3.hash(mem.spanZ(u8, self.name), &out);325 }
316 return out;326
327 pub fn typedValue(self: *Decl) error{AnalysisFail}!TypedValue {
328 const tvm = self.typedValueManaged() orelse return error.AnalysisFail;
329 return tvm.typed_value;
330 }
331
332 pub fn value(self: *Decl) error{AnalysisFail}!Value {
333 return (try self.typedValue()).val;
334 }
335
336 fn typedValueManaged(self: *Decl) ?*TypedValue.Managed {
337 switch (self.analysis) {
338 .initial_in_progress,
339 .initial_dependency_failure,
340 .initial_sema_failure,
341 => return null,
342 .codegen_failure,
343 .codegen_failure_retryable,
344 .repeat_dependency_failure,
345 .repeat_sema_failure,
346 .repeat_in_progress,
347 .complete,
348 => return &self.typed_value.most_recent,
349 }
317 }350 }
318 };351 };
319352
...@@ -325,22 +358,19 @@ pub const Module = struct {...@@ -325,22 +358,19 @@ pub const Module = struct {
325 /// The value is the source instruction.358 /// The value is the source instruction.
326 queued: *text.Inst.Fn,359 queued: *text.Inst.Fn,
327 in_progress: *Analysis,360 in_progress: *Analysis,
328 /// There will be a corresponding ErrorMsg in Module.failed_fns361 /// There will be a corresponding ErrorMsg in Module.failed_decls
329 failure,362 failure,
330 success: Body,363 success: Body,
331 },364 },
332 /// The direct container of the Fn. This field will need to get more fleshed out when
333 /// self-hosted supports proper struct types and Zig AST => ZIR.
334 scope: *Scope.ZIRModule,
335365
336 /// This memory is temporary and points to stack memory for the duration366 /// This memory is temporary and points to stack memory for the duration
337 /// of Fn analysis.367 /// of Fn analysis.
338 pub const Analysis = struct {368 pub const Analysis = struct {
339 inner_block: Scope.Block,369 inner_block: Scope.Block,
340 /// null value means a semantic analysis error happened.370 /// TODO Performance optimization idea: instead of this inst_table,
341 inst_table: std.AutoHashMap(*text.Inst, ?*Inst),371 /// use a field in the text.Inst instead to track corresponding instructions
342 /// Owns the memory for instructions372 inst_table: std.AutoHashMap(*text.Inst, *Inst),
343 arena: std.heap.ArenaAllocator,373 needed_inst_capacity: usize,
344 };374 };
345 };375 };
346376
...@@ -374,6 +404,16 @@ pub const Module = struct {...@@ -374,6 +404,16 @@ pub const Module = struct {
374 }404 }
375 }405 }
376406
407 /// Asserts the scope has a parent which is a ZIRModule and
408 /// returns it.
409 pub fn namespace(self: *Scope) *ZIRModule {
410 switch (self.tag) {
411 .block => return self.cast(Block).?.decl.scope,
412 .decl => return self.cast(DeclAnalysis).?.decl.scope,
413 .zir_module => return self.cast(ZIRModule).?,
414 }
415 }
416
377 pub const Tag = enum {417 pub const Tag = enum {
378 zir_module,418 zir_module,
379 block,419 block,
...@@ -407,11 +447,11 @@ pub const Module = struct {...@@ -407,11 +447,11 @@ pub const Module = struct {
407 .unloaded_parse_failure,447 .unloaded_parse_failure,
408 => {},448 => {},
409 .loaded_success => {449 .loaded_success => {
410 allocator.free(contents.source);450 allocator.free(self.source.bytes);
411 self.contents.module.deinit(allocator);451 self.contents.module.deinit(allocator);
412 },452 },
413 .loaded_parse_failure => {453 .loaded_parse_failure => {
414 allocator.free(contents.source);454 allocator.free(self.source.bytes);
415 },455 },
416 }456 }
417 self.* = undefined;457 self.* = undefined;
...@@ -469,8 +509,8 @@ pub const Module = struct {...@@ -469,8 +509,8 @@ pub const Module = struct {
469 ) !void {509 ) !void {
470 const loc = std.zig.findLineColumn(source, simple_err_msg.byte_offset);510 const loc = std.zig.findLineColumn(source, simple_err_msg.byte_offset);
471 try errors.append(.{511 try errors.append(.{
472 .src_path = try mem.dupe(u8, &arena.allocator, sub_file_path),512 .src_path = try arena.allocator.dupe(u8, sub_file_path),
473 .msg = try mem.dupe(u8, &arena.allocator, simple_err_msg.msg),513 .msg = try arena.allocator.dupe(u8, simple_err_msg.msg),
474 .byte_offset = simple_err_msg.byte_offset,514 .byte_offset = simple_err_msg.byte_offset,
475 .line = loc.line,515 .line = loc.line,
476 .column = loc.column,516 .column = loc.column,
...@@ -480,7 +520,7 @@ pub const Module = struct {...@@ -480,7 +520,7 @@ pub const Module = struct {
480520
481 pub fn deinit(self: *Module) void {521 pub fn deinit(self: *Module) void {
482 const allocator = self.allocator;522 const allocator = self.allocator;
483 allocator.free(self.errors);523 self.work_stack.deinit(allocator);
484 {524 {
485 var it = self.decl_table.iterator();525 var it = self.decl_table.iterator();
486 while (it.next()) |kv| {526 while (it.next()) |kv| {
...@@ -488,8 +528,44 @@ pub const Module = struct {...@@ -488,8 +528,44 @@ pub const Module = struct {
488 }528 }
489 self.decl_table.deinit();529 self.decl_table.deinit();
490 }530 }
531 {
532 var it = self.failed_decls.iterator();
533 while (it.next()) |kv| {
534 kv.value.destroy(allocator);
535 }
536 self.failed_decls.deinit();
537 }
538 {
539 var it = self.failed_files.iterator();
540 while (it.next()) |kv| {
541 kv.value.destroy(allocator);
542 }
543 self.failed_files.deinit();
544 }
545 {
546 var it = self.failed_exports.iterator();
547 while (it.next()) |kv| {
548 kv.value.destroy(allocator);
549 }
550 self.failed_exports.deinit();
551 }
552 self.decl_exports.deinit();
553 {
554 var it = self.export_owners.iterator();
555 while (it.next()) |kv| {
556 const export_list = kv.value;
557 for (export_list) |exp| {
558 allocator.destroy(exp);
559 }
560 allocator.free(export_list);
561 }
562 self.failed_exports.deinit();
563 }
491 self.root_pkg.destroy();564 self.root_pkg.destroy();
492 self.root_scope.deinit();565 {
566 self.root_scope.deinit(allocator);
567 allocator.destroy(self.root_scope);
568 }
493 self.* = undefined;569 self.* = undefined;
494 }570 }
495571
...@@ -504,19 +580,20 @@ pub const Module = struct {...@@ -504,19 +580,20 @@ pub const Module = struct {
504 // Analyze the root source file now.580 // Analyze the root source file now.
505 self.analyzeRoot(self.root_scope) catch |err| switch (err) {581 self.analyzeRoot(self.root_scope) catch |err| switch (err) {
506 error.AnalysisFail => {582 error.AnalysisFail => {
507 assert(self.failed_files.size != 0);583 assert(self.totalErrorCount() != 0);
508 },584 },
509 else => |e| return e,585 else => |e| return e,
510 };586 };
511587
588 try self.performAllTheWork();
589
512 try self.bin_file.flush();590 try self.bin_file.flush();
513 self.link_error_flags = self.bin_file.error_flags;591 self.link_error_flags = self.bin_file.error_flags;
514 }592 }
515593
516 pub fn totalErrorCount(self: *Module) usize {594 pub fn totalErrorCount(self: *Module) usize {
517 return self.failed_decls.size +595 return self.failed_decls.size +
518 self.failed_fns.size +596 self.failed_files.size +
519 self.failed_decls.size +
520 self.failed_exports.size +597 self.failed_exports.size +
521 @boolToInt(self.link_error_flags.no_entry_point_found);598 @boolToInt(self.link_error_flags.no_entry_point_found);
522 }599 }
...@@ -533,17 +610,8 @@ pub const Module = struct {...@@ -533,17 +610,8 @@ pub const Module = struct {
533 while (it.next()) |kv| {610 while (it.next()) |kv| {
534 const scope = kv.key;611 const scope = kv.key;
535 const err_msg = kv.value;612 const err_msg = kv.value;
536 const source = scope.parse_failure.source;613 const source = scope.source.bytes;
537 AllErrors.add(&arena, &errors, scope.sub_file_path, source, err_msg);614 try AllErrors.add(&arena, &errors, scope.sub_file_path, source, err_msg.*);
538 }
539 }
540 {
541 var it = self.failed_fns.iterator();
542 while (it.next()) |kv| {
543 const func = kv.key;
544 const err_msg = kv.value;
545 const source = func.scope.success.source;
546 AllErrors.add(&arena, &errors, func.scope.sub_file_path, source, err_msg);
547 }615 }
548 }616 }
549 {617 {
...@@ -551,8 +619,8 @@ pub const Module = struct {...@@ -551,8 +619,8 @@ pub const Module = struct {
551 while (it.next()) |kv| {619 while (it.next()) |kv| {
552 const decl = kv.key;620 const decl = kv.key;
553 const err_msg = kv.value;621 const err_msg = kv.value;
554 const source = decl.scope.success.source;622 const source = decl.scope.source.bytes;
555 AllErrors.add(&arena, &errors, decl.scope.sub_file_path, source, err_msg);623 try AllErrors.add(&arena, &errors, decl.scope.sub_file_path, source, err_msg.*);
556 }624 }
557 }625 }
558 {626 {
...@@ -560,14 +628,14 @@ pub const Module = struct {...@@ -560,14 +628,14 @@ pub const Module = struct {
560 while (it.next()) |kv| {628 while (it.next()) |kv| {
561 const decl = kv.key.owner_decl;629 const decl = kv.key.owner_decl;
562 const err_msg = kv.value;630 const err_msg = kv.value;
563 const source = decl.scope.success.source;631 const source = decl.scope.source.bytes;
564 try AllErrors.add(&arena, &errors, decl.scope.sub_file_path, source, err_msg);632 try AllErrors.add(&arena, &errors, decl.scope.sub_file_path, source, err_msg.*);
565 }633 }
566 }634 }
567635
568 if (self.link_error_flags.no_entry_point_found) {636 if (self.link_error_flags.no_entry_point_found) {
569 try errors.append(.{637 try errors.append(.{
570 .src_path = self.module.root_src_path,638 .src_path = self.root_pkg.root_src_path,
571 .line = 0,639 .line = 0,
572 .column = 0,640 .column = 0,
573 .byte_offset = 0,641 .byte_offset = 0,
...@@ -579,12 +647,56 @@ pub const Module = struct {...@@ -579,12 +647,56 @@ pub const Module = struct {
579647
580 return AllErrors{648 return AllErrors{
581 .arena = arena.state,649 .arena = arena.state,
582 .list = try mem.dupe(&arena.allocator, AllErrors.Message, errors.items),650 .list = try arena.allocator.dupe(AllErrors.Message, errors.items),
583 };651 };
584 }652 }
585653
586 const InnerError = error{ OutOfMemory, AnalysisFail };654 const InnerError = error{ OutOfMemory, AnalysisFail };
587655
656 pub fn performAllTheWork(self: *Module) error{OutOfMemory}!void {
657 while (self.work_stack.popOrNull()) |work_item| switch (work_item) {
658 .codegen_decl => |decl| switch (decl.analysis) {
659 .initial_in_progress,
660 .repeat_in_progress,
661 => unreachable,
662
663 .initial_sema_failure,
664 .repeat_sema_failure,
665 .codegen_failure,
666 .initial_dependency_failure,
667 .repeat_dependency_failure,
668 => continue,
669
670 .complete, .codegen_failure_retryable => {
671 if (decl.typed_value.most_recent.typed_value.val.cast(Value.Payload.Function)) |payload| {
672 switch (payload.func.analysis) {
673 .queued => self.analyzeFnBody(decl, payload.func) catch |err| switch (err) {
674 error.AnalysisFail => continue,
675 else => |e| return e,
676 },
677 .in_progress => unreachable,
678 .failure => continue,
679 .success => {},
680 }
681 }
682 self.bin_file.updateDecl(self, decl) catch |err| switch (err) {
683 error.OutOfMemory => return error.OutOfMemory,
684 else => {
685 try self.failed_decls.ensureCapacity(self.failed_decls.size + 1);
686 self.failed_decls.putAssumeCapacityNoClobber(decl, try ErrorMsg.create(
687 self.allocator,
688 decl.src,
689 "unable to codegen: {}",
690 .{@errorName(err)},
691 ));
692 decl.analysis = .codegen_failure_retryable;
693 },
694 };
695 },
696 },
697 };
698 }
699
588 fn analyzeRoot(self: *Module, root_scope: *Scope.ZIRModule) !void {700 fn analyzeRoot(self: *Module, root_scope: *Scope.ZIRModule) !void {
589 // TODO use the cache to identify, from the modified source files, the decls which have701 // TODO use the cache to identify, from the modified source files, the decls which have
590 // changed based on the span of memory that represents the decl in the re-parsed source file.702 // changed based on the span of memory that represents the decl in the re-parsed source file.
...@@ -650,56 +762,39 @@ pub const Module = struct {...@@ -650,56 +762,39 @@ pub const Module = struct {
650 try analyzeExport(self, &root_scope.base, export_inst);762 try analyzeExport(self, &root_scope.base, export_inst);
651 }763 }
652 }764 }
653
654 while (self.work_stack.pop()) |work_item| switch (work_item) {
655 .codegen_decl => |decl| switch (decl.analysis) {
656 .success => {
657 if (decl.typed_value.most_recent.typed_value.val.cast(Value.Function)) |payload| {
658 switch (payload.func.analysis) {
659 .queued => self.analyzeFnBody(decl, payload.func) catch |err| switch (err) {
660 error.AnalysisFail => {
661 assert(func_payload.func.analysis == .failure);
662 continue;
663 },
664 else => |e| return e,
665 },
666 .in_progress => unreachable,
667 .failure => continue,
668 .success => {},
669 }
670 }
671 try self.bin_file.updateDecl(self, decl);
672 },
673 },
674 };
675 }765 }
676766
677 fn analyzeFnBody(self: *Module, decl: *Decl, func: *Fn) !void {767 fn analyzeFnBody(self: *Module, decl: *Decl, func: *Fn) !void {
678 // Use the Decl's arena for function memory.768 // Use the Decl's arena for function memory.
679 var arena = decl.typed_value.most_recent.arena.?.promote(self.allocator);769 var arena = decl.typed_value.most_recent.arena.?.promote(self.allocator);
680 defer decl.typed_value.most_recent.arena.?.* = arena.state;770 defer decl.typed_value.most_recent.arena.?.* = arena.state;
681 var analysis: Analysis = .{771 var analysis: Fn.Analysis = .{
682 .inner_block = .{772 .inner_block = .{
683 .func = func,773 .func = func,
684 .decl = decl,774 .decl = decl,
685 .instructions = .{},775 .instructions = .{},
686 .arena = &arena.allocator,776 .arena = &arena.allocator,
687 },777 },
688 .inst_table = std.AutoHashMap(*text.Inst, ?*Inst).init(self.allocator),778 .needed_inst_capacity = 0,
779 .inst_table = std.AutoHashMap(*text.Inst, *Inst).init(self.allocator),
689 };780 };
690 defer analysis.inner_block.instructions.deinit();781 defer analysis.inner_block.instructions.deinit(self.allocator);
691 defer analysis.inst_table.deinit();782 defer analysis.inst_table.deinit();
692783
693 const fn_inst = func.analysis.queued;784 const fn_inst = func.analysis.queued;
694 func.analysis = .{ .in_progress = &analysis };785 func.analysis = .{ .in_progress = &analysis };
695786
696 try self.analyzeBody(&analysis.inner_block, fn_inst.positionals.body);787 try self.analyzeBody(&analysis.inner_block.base, fn_inst.positionals.body);
697788
698 func.analysis = .{ .success = .{ .instructions = analysis.inner_block.instructions.toOwnedSlice() } };789 func.analysis = .{
790 .success = .{
791 .instructions = try arena.allocator.dupe(*Inst, analysis.inner_block.instructions.items),
792 },
793 };
699 }794 }
700795
701 fn resolveDecl(self: *Module, scope: *Scope, old_inst: *text.Inst) InnerError!*Decl {796 fn resolveDecl(self: *Module, scope: *Scope, old_inst: *text.Inst) InnerError!*Decl {
702 const hash = old_inst.fullyQualifiedNameHash();797 const hash = Decl.hashSimpleName(old_inst.name);
703 if (self.decl_table.get(hash)) |kv| {798 if (self.decl_table.get(hash)) |kv| {
704 return kv.value;799 return kv.value;
705 } else {800 } else {
...@@ -711,7 +806,7 @@ pub const Module = struct {...@@ -711,7 +806,7 @@ pub const Module = struct {
711 errdefer self.allocator.free(name);806 errdefer self.allocator.free(name);
712 new_decl.* = .{807 new_decl.* = .{
713 .name = name,808 .name = name,
714 .scope = scope.findZIRModule(),809 .scope = scope.namespace(),
715 .src = old_inst.src,810 .src = old_inst.src,
716 .typed_value = .{ .never_succeeded = {} },811 .typed_value = .{ .never_succeeded = {} },
717 .analysis = .initial_in_progress,812 .analysis = .initial_in_progress,
...@@ -726,12 +821,11 @@ pub const Module = struct {...@@ -726,12 +821,11 @@ pub const Module = struct {
726 };821 };
727 errdefer decl_scope.arena.deinit();822 errdefer decl_scope.arena.deinit();
728823
729 const arena_state = try self.allocator.create(std.heap.ArenaAllocator.State);824 const arena_state = try decl_scope.arena.allocator.create(std.heap.ArenaAllocator.State);
730 errdefer self.allocator.destroy(arena_state);
731825
732 const typed_value = try self.analyzeInstConst(&decl_scope.base, old_inst);826 const typed_value = try self.analyzeInstConst(&decl_scope.base, old_inst);
733827
734 arena_state.* = decl_scope.arena;828 arena_state.* = decl_scope.arena.state;
735829
736 new_decl.typed_value = .{830 new_decl.typed_value = .{
737 .most_recent = .{831 .most_recent = .{
...@@ -741,7 +835,7 @@ pub const Module = struct {...@@ -741,7 +835,7 @@ pub const Module = struct {
741 };835 };
742 new_decl.analysis = .complete;836 new_decl.analysis = .complete;
743 // We ensureCapacity when scanning for decls.837 // We ensureCapacity when scanning for decls.
744 self.work_stack.appendAssumeCapacity(self.allocator, .{ .codegen_decl = new_decl });838 self.work_stack.appendAssumeCapacity(.{ .codegen_decl = new_decl });
745 return new_decl;839 return new_decl;
746 }840 }
747 }841 }
...@@ -756,6 +850,7 @@ pub const Module = struct {...@@ -756,6 +850,7 @@ pub const Module = struct {
756 .initial_sema_failure,850 .initial_sema_failure,
757 .repeat_sema_failure,851 .repeat_sema_failure,
758 .codegen_failure,852 .codegen_failure,
853 .codegen_failure_retryable,
759 => return error.AnalysisFail,854 => return error.AnalysisFail,
760855
761 .complete => return decl,856 .complete => return decl,
...@@ -764,14 +859,14 @@ pub const Module = struct {...@@ -764,14 +859,14 @@ pub const Module = struct {
764859
765 fn resolveInst(self: *Module, scope: *Scope, old_inst: *text.Inst) InnerError!*Inst {860 fn resolveInst(self: *Module, scope: *Scope, old_inst: *text.Inst) InnerError!*Inst {
766 if (scope.cast(Scope.Block)) |block| {861 if (scope.cast(Scope.Block)) |block| {
767 if (block.func.inst_table.get(old_inst)) |kv| {862 if (block.func.analysis.in_progress.inst_table.get(old_inst)) |kv| {
768 return kv.value.ptr orelse return error.AnalysisFail;863 return kv.value;
769 }864 }
770 }865 }
771866
772 const decl = try self.resolveCompleteDecl(scope, old_inst);867 const decl = try self.resolveCompleteDecl(scope, old_inst);
773 const decl_ref = try self.analyzeDeclRef(scope, old_inst.src, decl);868 const decl_ref = try self.analyzeDeclRef(scope, old_inst.src, decl);
774 return self.analyzeDeref(scope, old_inst.src, decl_ref);869 return self.analyzeDeref(scope, old_inst.src, decl_ref, old_inst.src);
775 }870 }
776871
777 fn requireRuntimeBlock(self: *Module, scope: *Scope, src: usize) !*Scope.Block {872 fn requireRuntimeBlock(self: *Module, scope: *Scope, src: usize) !*Scope.Block {
...@@ -819,7 +914,7 @@ pub const Module = struct {...@@ -819,7 +914,7 @@ pub const Module = struct {
819 return val.toType();914 return val.toType();
820 }915 }
821916
822 fn analyzeExport(self: *Module, scope: *Scope, export_inst: *text.Inst.Export) !void {917 fn analyzeExport(self: *Module, scope: *Scope, export_inst: *text.Inst.Export) InnerError!void {
823 try self.decl_exports.ensureCapacity(self.decl_exports.size + 1);918 try self.decl_exports.ensureCapacity(self.decl_exports.size + 1);
824 try self.export_owners.ensureCapacity(self.export_owners.size + 1);919 try self.export_owners.ensureCapacity(self.export_owners.size + 1);
825 const symbol_name = try self.resolveConstString(scope, export_inst.positionals.symbol_name);920 const symbol_name = try self.resolveConstString(scope, export_inst.positionals.symbol_name);
...@@ -840,7 +935,7 @@ pub const Module = struct {...@@ -840,7 +935,7 @@ pub const Module = struct {
840 const owner_decl = scope.decl();935 const owner_decl = scope.decl();
841936
842 new_export.* = .{937 new_export.* = .{
843 .options = .{ .data = .{ .name = symbol_name } },938 .options = .{ .name = symbol_name },
844 .src = export_inst.base.src,939 .src = export_inst.base.src,
845 .link = .{},940 .link = .{},
846 .owner_decl = owner_decl,941 .owner_decl = owner_decl,
...@@ -865,7 +960,19 @@ pub const Module = struct {...@@ -865,7 +960,19 @@ pub const Module = struct {
865 de_gop.kv.value[de_gop.kv.value.len - 1] = new_export;960 de_gop.kv.value[de_gop.kv.value.len - 1] = new_export;
866 errdefer de_gop.kv.value = self.allocator.shrink(de_gop.kv.value, de_gop.kv.value.len - 1);961 errdefer de_gop.kv.value = self.allocator.shrink(de_gop.kv.value, de_gop.kv.value.len - 1);
867962
868 try self.bin_file.updateDeclExports(self, decl, de_gop.kv.value);963 self.bin_file.updateDeclExports(self, exported_decl, de_gop.kv.value) catch |err| switch (err) {
964 error.OutOfMemory => return error.OutOfMemory,
965 else => {
966 try self.failed_exports.ensureCapacity(self.failed_exports.size + 1);
967 self.failed_exports.putAssumeCapacityNoClobber(new_export, try ErrorMsg.create(
968 self.allocator,
969 export_inst.base.src,
970 "unable to export: {}",
971 .{@errorName(err)},
972 ));
973 new_export.status = .failed_retryable;
974 },
975 };
869 }976 }
870977
871 /// TODO should not need the cast on the last parameter at the callsites978 /// TODO should not need the cast on the last parameter at the callsites
...@@ -976,7 +1083,7 @@ pub const Module = struct {...@@ -976,7 +1083,7 @@ pub const Module = struct {
976 fn constIntBig(self: *Module, scope: *Scope, src: usize, ty: Type, big_int: BigIntConst) !*Inst {1083 fn constIntBig(self: *Module, scope: *Scope, src: usize, ty: Type, big_int: BigIntConst) !*Inst {
977 const val_payload = if (big_int.positive) blk: {1084 const val_payload = if (big_int.positive) blk: {
978 if (big_int.to(u64)) |x| {1085 if (big_int.to(u64)) |x| {
979 return self.constIntUnsigned(src, ty, x);1086 return self.constIntUnsigned(scope, src, ty, x);
980 } else |err| switch (err) {1087 } else |err| switch (err) {
981 error.NegativeIntoUnsigned => unreachable,1088 error.NegativeIntoUnsigned => unreachable,
982 error.TargetTooSmall => {}, // handled below1089 error.TargetTooSmall => {}, // handled below
...@@ -986,7 +1093,7 @@ pub const Module = struct {...@@ -986,7 +1093,7 @@ pub const Module = struct {
986 break :blk &big_int_payload.base;1093 break :blk &big_int_payload.base;
987 } else blk: {1094 } else blk: {
988 if (big_int.to(i64)) |x| {1095 if (big_int.to(i64)) |x| {
989 return self.constIntSigned(src, ty, x);1096 return self.constIntSigned(scope, src, ty, x);
990 } else |err| switch (err) {1097 } else |err| switch (err) {
991 error.NegativeIntoUnsigned => unreachable,1098 error.NegativeIntoUnsigned => unreachable,
992 error.TargetTooSmall => {}, // handled below1099 error.TargetTooSmall => {}, // handled below
...@@ -1014,15 +1121,17 @@ pub const Module = struct {...@@ -1014,15 +1121,17 @@ pub const Module = struct {
1014 switch (old_inst.tag) {1121 switch (old_inst.tag) {
1015 .breakpoint => return self.analyzeInstBreakpoint(scope, old_inst.cast(text.Inst.Breakpoint).?),1122 .breakpoint => return self.analyzeInstBreakpoint(scope, old_inst.cast(text.Inst.Breakpoint).?),
1016 .call => return self.analyzeInstCall(scope, old_inst.cast(text.Inst.Call).?),1123 .call => return self.analyzeInstCall(scope, old_inst.cast(text.Inst.Call).?),
1124 .declref => return self.analyzeInstDeclRef(scope, old_inst.cast(text.Inst.DeclRef).?),
1017 .str => {1125 .str => {
1018 // We can use this reference because Inst.Const's Value is arena-allocated.
1019 // The value would get copied to a MemoryCell before the `text.Inst.Str` lifetime ends.
1020 const bytes = old_inst.cast(text.Inst.Str).?.positionals.bytes;1126 const bytes = old_inst.cast(text.Inst.Str).?.positionals.bytes;
1021 return self.constStr(old_inst.src, bytes);1127 // The bytes references memory inside the ZIR text module, which can get deallocated
1128 // after semantic analysis is complete. We need the memory to be in the Decl's arena.
1129 const arena_bytes = try scope.arena().dupe(u8, bytes);
1130 return self.constStr(scope, old_inst.src, arena_bytes);
1022 },1131 },
1023 .int => {1132 .int => {
1024 const big_int = old_inst.cast(text.Inst.Int).?.positionals.int;1133 const big_int = old_inst.cast(text.Inst.Int).?.positionals.int;
1025 return self.constIntBig(old_inst.src, Type.initTag(.comptime_int), big_int);1134 return self.constIntBig(scope, old_inst.src, Type.initTag(.comptime_int), big_int);
1026 },1135 },
1027 .ptrtoint => return self.analyzeInstPtrToInt(scope, old_inst.cast(text.Inst.PtrToInt).?),1136 .ptrtoint => return self.analyzeInstPtrToInt(scope, old_inst.cast(text.Inst.PtrToInt).?),
1028 .fieldptr => return self.analyzeInstFieldPtr(scope, old_inst.cast(text.Inst.FieldPtr).?),1137 .fieldptr => return self.analyzeInstFieldPtr(scope, old_inst.cast(text.Inst.FieldPtr).?),
...@@ -1036,7 +1145,7 @@ pub const Module = struct {...@@ -1036,7 +1145,7 @@ pub const Module = struct {
1036 try self.analyzeExport(scope, old_inst.cast(text.Inst.Export).?);1145 try self.analyzeExport(scope, old_inst.cast(text.Inst.Export).?);
1037 return self.constVoid(scope, old_inst.src);1146 return self.constVoid(scope, old_inst.src);
1038 },1147 },
1039 .primitive => return self.analyzeInstPrimitive(old_inst.cast(text.Inst.Primitive).?),1148 .primitive => return self.analyzeInstPrimitive(scope, old_inst.cast(text.Inst.Primitive).?),
1040 .fntype => return self.analyzeInstFnType(scope, old_inst.cast(text.Inst.FnType).?),1149 .fntype => return self.analyzeInstFnType(scope, old_inst.cast(text.Inst.FnType).?),
1041 .intcast => return self.analyzeInstIntCast(scope, old_inst.cast(text.Inst.IntCast).?),1150 .intcast => return self.analyzeInstIntCast(scope, old_inst.cast(text.Inst.IntCast).?),
1042 .bitcast => return self.analyzeInstBitCast(scope, old_inst.cast(text.Inst.BitCast).?),1151 .bitcast => return self.analyzeInstBitCast(scope, old_inst.cast(text.Inst.BitCast).?),
...@@ -1054,6 +1163,14 @@ pub const Module = struct {...@@ -1054,6 +1163,14 @@ pub const Module = struct {
1054 return self.addNewInstArgs(b, inst.base.src, Type.initTag(.void), Inst.Breakpoint, Inst.Args(Inst.Breakpoint){});1163 return self.addNewInstArgs(b, inst.base.src, Type.initTag(.void), Inst.Breakpoint, Inst.Args(Inst.Breakpoint){});
1055 }1164 }
10561165
1166 fn analyzeInstDeclRef(self: *Module, scope: *Scope, inst: *text.Inst.DeclRef) InnerError!*Inst {
1167 return self.fail(scope, inst.base.src, "TODO implement analyzeInstDeclFef", .{});
1168 }
1169
1170 fn analyzeDeclRef(self: *Module, scope: *Scope, src: usize, decl: *Decl) InnerError!*Inst {
1171 return self.fail(scope, src, "TODO implement analyzeDeclRef", .{});
1172 }
1173
1057 fn analyzeInstCall(self: *Module, scope: *Scope, inst: *text.Inst.Call) InnerError!*Inst {1174 fn analyzeInstCall(self: *Module, scope: *Scope, inst: *text.Inst.Call) InnerError!*Inst {
1058 const func = try self.resolveInst(scope, inst.positionals.func);1175 const func = try self.resolveInst(scope, inst.positionals.func);
1059 if (func.ty.zigTypeTag() != .Fn)1176 if (func.ty.zigTypeTag() != .Fn)
...@@ -1123,8 +1240,7 @@ pub const Module = struct {...@@ -1123,8 +1240,7 @@ pub const Module = struct {
1123 const new_func = try scope.arena().create(Fn);1240 const new_func = try scope.arena().create(Fn);
1124 new_func.* = .{1241 new_func.* = .{
1125 .fn_type = fn_type,1242 .fn_type = fn_type,
1126 .analysis = .{ .queued = fn_inst.positionals.body },1243 .analysis = .{ .queued = fn_inst },
1127 .scope = scope.namespace(),
1128 };1244 };
1129 const fn_payload = try scope.arena().create(Value.Payload.Function);1245 const fn_payload = try scope.arena().create(Value.Payload.Function);
1130 fn_payload.* = .{ .func = new_func };1246 fn_payload.* = .{ .func = new_func };
...@@ -1141,28 +1257,28 @@ pub const Module = struct {...@@ -1141,28 +1257,28 @@ pub const Module = struct {
1141 fntype.positionals.param_types.len == 0 and1257 fntype.positionals.param_types.len == 0 and
1142 fntype.kw_args.cc == .Unspecified)1258 fntype.kw_args.cc == .Unspecified)
1143 {1259 {
1144 return self.constType(fntype.base.src, Type.initTag(.fn_noreturn_no_args));1260 return self.constType(scope, fntype.base.src, Type.initTag(.fn_noreturn_no_args));
1145 }1261 }
11461262
1147 if (return_type.zigTypeTag() == .NoReturn and1263 if (return_type.zigTypeTag() == .NoReturn and
1148 fntype.positionals.param_types.len == 0 and1264 fntype.positionals.param_types.len == 0 and
1149 fntype.kw_args.cc == .Naked)1265 fntype.kw_args.cc == .Naked)
1150 {1266 {
1151 return self.constType(fntype.base.src, Type.initTag(.fn_naked_noreturn_no_args));1267 return self.constType(scope, fntype.base.src, Type.initTag(.fn_naked_noreturn_no_args));
1152 }1268 }
11531269
1154 if (return_type.zigTypeTag() == .Void and1270 if (return_type.zigTypeTag() == .Void and
1155 fntype.positionals.param_types.len == 0 and1271 fntype.positionals.param_types.len == 0 and
1156 fntype.kw_args.cc == .C)1272 fntype.kw_args.cc == .C)
1157 {1273 {
1158 return self.constType(fntype.base.src, Type.initTag(.fn_ccc_void_no_args));1274 return self.constType(scope, fntype.base.src, Type.initTag(.fn_ccc_void_no_args));
1159 }1275 }
11601276
1161 return self.fail(scope, fntype.base.src, "TODO implement fntype instruction more", .{});1277 return self.fail(scope, fntype.base.src, "TODO implement fntype instruction more", .{});
1162 }1278 }
11631279
1164 fn analyzeInstPrimitive(self: *Module, primitive: *text.Inst.Primitive) InnerError!*Inst {1280 fn analyzeInstPrimitive(self: *Module, scope: *Scope, primitive: *text.Inst.Primitive) InnerError!*Inst {
1165 return self.constType(primitive.base.src, primitive.positionals.tag.toType());1281 return self.constType(scope, primitive.base.src, primitive.positionals.tag.toType());
1166 }1282 }
11671283
1168 fn analyzeInstAs(self: *Module, scope: *Scope, as: *text.Inst.As) InnerError!*Inst {1284 fn analyzeInstAs(self: *Module, scope: *Scope, as: *text.Inst.As) InnerError!*Inst {
...@@ -1332,18 +1448,22 @@ pub const Module = struct {...@@ -1332,18 +1448,22 @@ pub const Module = struct {
13321448
1333 fn analyzeInstDeref(self: *Module, scope: *Scope, deref: *text.Inst.Deref) InnerError!*Inst {1449 fn analyzeInstDeref(self: *Module, scope: *Scope, deref: *text.Inst.Deref) InnerError!*Inst {
1334 const ptr = try self.resolveInst(scope, deref.positionals.ptr);1450 const ptr = try self.resolveInst(scope, deref.positionals.ptr);
1451 return self.analyzeDeref(scope, deref.base.src, ptr, deref.positionals.ptr.src);
1452 }
1453
1454 fn analyzeDeref(self: *Module, scope: *Scope, src: usize, ptr: *Inst, ptr_src: usize) InnerError!*Inst {
1335 const elem_ty = switch (ptr.ty.zigTypeTag()) {1455 const elem_ty = switch (ptr.ty.zigTypeTag()) {
1336 .Pointer => ptr.ty.elemType(),1456 .Pointer => ptr.ty.elemType(),
1337 else => return self.fail(scope, deref.positionals.ptr.src, "expected pointer, found '{}'", .{ptr.ty}),1457 else => return self.fail(scope, ptr_src, "expected pointer, found '{}'", .{ptr.ty}),
1338 };1458 };
1339 if (ptr.value()) |val| {1459 if (ptr.value()) |val| {
1340 return self.constInst(scope, deref.base.src, .{1460 return self.constInst(scope, src, .{
1341 .ty = elem_ty,1461 .ty = elem_ty,
1342 .val = val.pointerDeref(),1462 .val = try val.pointerDeref(scope.arena()),
1343 });1463 });
1344 }1464 }
13451465
1346 return self.fail(scope, deref.base.src, "TODO implement runtime deref", .{});1466 return self.fail(scope, src, "TODO implement runtime deref", .{});
1347 }1467 }
13481468
1349 fn analyzeInstAsm(self: *Module, scope: *Scope, assembly: *text.Inst.Asm) InnerError!*Inst {1469 fn analyzeInstAsm(self: *Module, scope: *Scope, assembly: *text.Inst.Asm) InnerError!*Inst {
...@@ -1390,7 +1510,7 @@ pub const Module = struct {...@@ -1390,7 +1510,7 @@ pub const Module = struct {
1390 const rhs_ty_tag = rhs.ty.zigTypeTag();1510 const rhs_ty_tag = rhs.ty.zigTypeTag();
1391 if (is_equality_cmp and lhs_ty_tag == .Null and rhs_ty_tag == .Null) {1511 if (is_equality_cmp and lhs_ty_tag == .Null and rhs_ty_tag == .Null) {
1392 // null == null, null != null1512 // null == null, null != null
1393 return self.constBool(inst.base.src, op == .eq);1513 return self.constBool(scope, inst.base.src, op == .eq);
1394 } else if (is_equality_cmp and1514 } else if (is_equality_cmp and
1395 ((lhs_ty_tag == .Null and rhs_ty_tag == .Optional) or1515 ((lhs_ty_tag == .Null and rhs_ty_tag == .Optional) or
1396 rhs_ty_tag == .Null and lhs_ty_tag == .Optional))1516 rhs_ty_tag == .Null and lhs_ty_tag == .Optional))
...@@ -1399,7 +1519,7 @@ pub const Module = struct {...@@ -1399,7 +1519,7 @@ pub const Module = struct {
1399 const opt_operand = if (lhs_ty_tag == .Optional) lhs else rhs;1519 const opt_operand = if (lhs_ty_tag == .Optional) lhs else rhs;
1400 if (opt_operand.value()) |opt_val| {1520 if (opt_operand.value()) |opt_val| {
1401 const is_null = opt_val.isNull();1521 const is_null = opt_val.isNull();
1402 return self.constBool(inst.base.src, if (op == .eq) is_null else !is_null);1522 return self.constBool(scope, inst.base.src, if (op == .eq) is_null else !is_null);
1403 }1523 }
1404 const b = try self.requireRuntimeBlock(scope, inst.base.src);1524 const b = try self.requireRuntimeBlock(scope, inst.base.src);
1405 switch (op) {1525 switch (op) {
...@@ -1468,32 +1588,27 @@ pub const Module = struct {...@@ -1468,32 +1588,27 @@ pub const Module = struct {
1468 const parent_block = try self.requireRuntimeBlock(scope, inst.base.src);1588 const parent_block = try self.requireRuntimeBlock(scope, inst.base.src);
14691589
1470 var true_block: Scope.Block = .{1590 var true_block: Scope.Block = .{
1471 .base = .{ .parent = scope },
1472 .func = parent_block.func,1591 .func = parent_block.func,
1592 .decl = parent_block.decl,
1473 .instructions = .{},1593 .instructions = .{},
1594 .arena = parent_block.arena,
1474 };1595 };
1475 defer true_block.instructions.deinit();1596 defer true_block.instructions.deinit(self.allocator);
1476 try self.analyzeBody(&true_block.base, inst.positionals.true_body);1597 try self.analyzeBody(&true_block.base, inst.positionals.true_body);
14771598
1478 var false_block: Scope.Block = .{1599 var false_block: Scope.Block = .{
1479 .base = .{ .parent = scope },
1480 .func = parent_block.func,1600 .func = parent_block.func,
1601 .decl = parent_block.decl,
1481 .instructions = .{},1602 .instructions = .{},
1603 .arena = parent_block.arena,
1482 };1604 };
1483 defer false_block.instructions.deinit();1605 defer false_block.instructions.deinit(self.allocator);
1484 try self.analyzeBody(&false_block.base, inst.positionals.false_body);1606 try self.analyzeBody(&false_block.base, inst.positionals.false_body);
14851607
1486 // Copy the instruction pointers to the arena memory
1487 const true_instructions = try scope.arena().alloc(*Inst, true_block.instructions.items.len);
1488 const false_instructions = try scope.arena().alloc(*Inst, false_block.instructions.items.len);
1489
1490 mem.copy(*Inst, true_instructions, true_block.instructions.items);
1491 mem.copy(*Inst, false_instructions, false_block.instructions.items);
1492
1493 return self.addNewInstArgs(parent_block, inst.base.src, Type.initTag(.void), Inst.CondBr, Inst.Args(Inst.CondBr){1608 return self.addNewInstArgs(parent_block, inst.base.src, Type.initTag(.void), Inst.CondBr, Inst.Args(Inst.CondBr){
1494 .condition = cond,1609 .condition = cond,
1495 .true_body = .{ .instructions = true_instructions },1610 .true_body = .{ .instructions = try scope.arena().dupe(*Inst, true_block.instructions.items) },
1496 .false_body = .{ .instructions = false_instructions },1611 .false_body = .{ .instructions = try scope.arena().dupe(*Inst, false_block.instructions.items) },
1497 });1612 });
1498 }1613 }
14991614
...@@ -1521,15 +1636,18 @@ pub const Module = struct {...@@ -1521,15 +1636,18 @@ pub const Module = struct {
1521 }1636 }
15221637
1523 fn analyzeBody(self: *Module, scope: *Scope, body: text.Module.Body) !void {1638 fn analyzeBody(self: *Module, scope: *Scope, body: text.Module.Body) !void {
1524 for (body.instructions) |src_inst| {1639 if (scope.cast(Scope.Block)) |b| {
1525 const new_inst = self.analyzeInst(scope, src_inst) catch |err| {1640 const analysis = b.func.analysis.in_progress;
1526 if (scope.cast(Scope.Block)) |b| {1641 analysis.needed_inst_capacity += body.instructions.len;
1527 self.fns.items[b.func.fn_index].analysis_status = .failure;1642 try analysis.inst_table.ensureCapacity(analysis.needed_inst_capacity);
1528 try b.func.inst_table.putNoClobber(src_inst, .{ .ptr = null });1643 for (body.instructions) |src_inst| {
1529 }1644 const new_inst = try self.analyzeInst(scope, src_inst);
1530 return err;1645 analysis.inst_table.putAssumeCapacityNoClobber(src_inst, new_inst);
1531 };1646 }
1532 if (scope.cast(Scope.Block)) |b| try b.func.inst_table.putNoClobber(src_inst, .{ .ptr = new_inst });1647 } else {
1648 for (body.instructions) |src_inst| {
1649 _ = try self.analyzeInst(scope, src_inst);
1650 }
1533 }1651 }
1534 }1652 }
15351653
...@@ -1575,7 +1693,7 @@ pub const Module = struct {...@@ -1575,7 +1693,7 @@ pub const Module = struct {
15751693
1576 if (lhs.value()) |lhs_val| {1694 if (lhs.value()) |lhs_val| {
1577 if (rhs.value()) |rhs_val| {1695 if (rhs.value()) |rhs_val| {
1578 return self.constBool(src, Value.compare(lhs_val, op, rhs_val));1696 return self.constBool(scope, src, Value.compare(lhs_val, op, rhs_val));
1579 }1697 }
1580 }1698 }
15811699
...@@ -1647,8 +1765,8 @@ pub const Module = struct {...@@ -1647,8 +1765,8 @@ pub const Module = struct {
1647 const zcmp = lhs_val.orderAgainstZero();1765 const zcmp = lhs_val.orderAgainstZero();
1648 if (lhs_val.floatHasFraction()) {1766 if (lhs_val.floatHasFraction()) {
1649 switch (op) {1767 switch (op) {
1650 .eq => return self.constBool(src, false),1768 .eq => return self.constBool(scope, src, false),
1651 .neq => return self.constBool(src, true),1769 .neq => return self.constBool(scope, src, true),
1652 else => {},1770 else => {},
1653 }1771 }
1654 if (zcmp == .lt) {1772 if (zcmp == .lt) {
...@@ -1682,8 +1800,8 @@ pub const Module = struct {...@@ -1682,8 +1800,8 @@ pub const Module = struct {
1682 const zcmp = rhs_val.orderAgainstZero();1800 const zcmp = rhs_val.orderAgainstZero();
1683 if (rhs_val.floatHasFraction()) {1801 if (rhs_val.floatHasFraction()) {
1684 switch (op) {1802 switch (op) {
1685 .eq => return self.constBool(src, false),1803 .eq => return self.constBool(scope, src, false),
1686 .neq => return self.constBool(src, true),1804 .neq => return self.constBool(scope, src, true),
1687 else => {},1805 else => {},
1688 }1806 }
1689 if (zcmp == .lt) {1807 if (zcmp == .lt) {
...@@ -1711,7 +1829,7 @@ pub const Module = struct {...@@ -1711,7 +1829,7 @@ pub const Module = struct {
1711 const casted_bits = std.math.cast(u16, max_bits) catch |err| switch (err) {1829 const casted_bits = std.math.cast(u16, max_bits) catch |err| switch (err) {
1712 error.Overflow => return self.fail(scope, src, "{} exceeds maximum integer bit count", .{max_bits}),1830 error.Overflow => return self.fail(scope, src, "{} exceeds maximum integer bit count", .{max_bits}),
1713 };1831 };
1714 break :blk try self.makeIntType(dest_int_is_signed, casted_bits);1832 break :blk try self.makeIntType(scope, dest_int_is_signed, casted_bits);
1715 };1833 };
1716 const casted_lhs = try self.coerce(scope, dest_type, lhs);1834 const casted_lhs = try self.coerce(scope, dest_type, lhs);
1717 const casted_rhs = try self.coerce(scope, dest_type, lhs);1835 const casted_rhs = try self.coerce(scope, dest_type, lhs);
...@@ -1807,7 +1925,6 @@ pub const Module = struct {...@@ -1807,7 +1925,6 @@ pub const Module = struct {
1807 fn fail(self: *Module, scope: *Scope, src: usize, comptime format: []const u8, args: var) InnerError {1925 fn fail(self: *Module, scope: *Scope, src: usize, comptime format: []const u8, args: var) InnerError {
1808 @setCold(true);1926 @setCold(true);
1809 try self.failed_decls.ensureCapacity(self.failed_decls.size + 1);1927 try self.failed_decls.ensureCapacity(self.failed_decls.size + 1);
1810 try self.failed_fns.ensureCapacity(self.failed_fns.size + 1);
1811 const err_msg = try ErrorMsg.create(self.allocator, src, format, args);1928 const err_msg = try ErrorMsg.create(self.allocator, src, format, args);
1812 switch (scope.tag) {1929 switch (scope.tag) {
1813 .decl => {1930 .decl => {
...@@ -1820,10 +1937,11 @@ pub const Module = struct {...@@ -1820,10 +1937,11 @@ pub const Module = struct {
1820 self.failed_decls.putAssumeCapacityNoClobber(decl, err_msg);1937 self.failed_decls.putAssumeCapacityNoClobber(decl, err_msg);
1821 },1938 },
1822 .block => {1939 .block => {
1823 const func = scope.cast(Scope.Block).?.func;1940 const block = scope.cast(Scope.Block).?;
1824 func.analysis = .failure;1941 block.func.analysis = .failure;
1825 self.failed_fns.putAssumeCapacityNoClobber(func, err_msg);1942 self.failed_decls.putAssumeCapacityNoClobber(block.decl, err_msg);
1826 },1943 },
1944 .zir_module => unreachable,
1827 }1945 }
1828 return error.AnalysisFail;1946 return error.AnalysisFail;
1829 }1947 }
...@@ -1868,7 +1986,7 @@ pub const ErrorMsg = struct {...@@ -1868,7 +1986,7 @@ pub const ErrorMsg = struct {
1868 }1986 }
18691987
1870 pub fn deinit(self: *ErrorMsg, allocator: *Allocator) void {1988 pub fn deinit(self: *ErrorMsg, allocator: *Allocator) void {
1871 allocator.free(err_msg.msg);1989 allocator.free(self.msg);
1872 self.* = undefined;1990 self.* = undefined;
1873 }1991 }
1874};1992};
...@@ -1920,7 +2038,6 @@ pub fn main() anyerror!void {...@@ -1920,7 +2038,6 @@ pub fn main() anyerror!void {
1920 .decl_exports = std.AutoHashMap(*Module.Decl, []*Module.Export).init(allocator),2038 .decl_exports = std.AutoHashMap(*Module.Decl, []*Module.Export).init(allocator),
1921 .export_owners = std.AutoHashMap(*Module.Decl, []*Module.Export).init(allocator),2039 .export_owners = std.AutoHashMap(*Module.Decl, []*Module.Export).init(allocator),
1922 .failed_decls = std.AutoHashMap(*Module.Decl, *ErrorMsg).init(allocator),2040 .failed_decls = std.AutoHashMap(*Module.Decl, *ErrorMsg).init(allocator),
1923 .failed_fns = std.AutoHashMap(*Module.Fn, *ErrorMsg).init(allocator),
1924 .failed_files = std.AutoHashMap(*Module.Scope.ZIRModule, *ErrorMsg).init(allocator),2041 .failed_files = std.AutoHashMap(*Module.Scope.ZIRModule, *ErrorMsg).init(allocator),
1925 .failed_exports = std.AutoHashMap(*Module.Export, *ErrorMsg).init(allocator),2042 .failed_exports = std.AutoHashMap(*Module.Export, *ErrorMsg).init(allocator),
1926 };2043 };
...@@ -1929,8 +2046,8 @@ pub fn main() anyerror!void {...@@ -1929,8 +2046,8 @@ pub fn main() anyerror!void {
19292046
1930 try module.update();2047 try module.update();
19312048
1932 const errors = try module.getAllErrorsAlloc();2049 var errors = try module.getAllErrorsAlloc();
1933 defer errors.deinit();2050 defer errors.deinit(allocator);
19342051
1935 if (errors.list.len != 0) {2052 if (errors.list.len != 0) {
1936 for (errors.list) |full_err_msg| {2053 for (errors.list) |full_err_msg| {
...@@ -1954,6 +2071,3 @@ pub fn main() anyerror!void {...@@ -1954,6 +2071,3 @@ pub fn main() anyerror!void {
1954 try bos.flush();2071 try bos.flush();
1955 }2072 }
1956}2073}
1957
1958// Performance optimization ideas:
1959// * when analyzing use a field in the Inst instead of HashMap to track corresponding instructions
src-self-hosted/ir/text.zig+139-47
...@@ -8,6 +8,7 @@ const BigIntConst = std.math.big.int.Const;...@@ -8,6 +8,7 @@ const BigIntConst = std.math.big.int.Const;
8const BigIntMutable = std.math.big.int.Mutable;8const BigIntMutable = std.math.big.int.Mutable;
9const Type = @import("../type.zig").Type;9const Type = @import("../type.zig").Type;
10const Value = @import("../value.zig").Value;10const Value = @import("../value.zig").Value;
11const TypedValue = @import("../TypedValue.zig");
11const ir = @import("../ir.zig");12const ir = @import("../ir.zig");
1213
13/// These are instructions that correspond to the ZIR text format. See `ir.Inst` for14/// These are instructions that correspond to the ZIR text format. See `ir.Inst` for
...@@ -462,6 +463,7 @@ pub const Module = struct {...@@ -462,6 +463,7 @@ pub const Module = struct {
462 switch (decl.tag) {463 switch (decl.tag) {
463 .breakpoint => return self.writeInstToStreamGeneric(stream, .breakpoint, decl, inst_table),464 .breakpoint => return self.writeInstToStreamGeneric(stream, .breakpoint, decl, inst_table),
464 .call => return self.writeInstToStreamGeneric(stream, .call, decl, inst_table),465 .call => return self.writeInstToStreamGeneric(stream, .call, decl, inst_table),
466 .declref => return self.writeInstToStreamGeneric(stream, .declref, decl, inst_table),
465 .str => return self.writeInstToStreamGeneric(stream, .str, decl, inst_table),467 .str => return self.writeInstToStreamGeneric(stream, .str, decl, inst_table),
466 .int => return self.writeInstToStreamGeneric(stream, .int, decl, inst_table),468 .int => return self.writeInstToStreamGeneric(stream, .int, decl, inst_table),
467 .ptrtoint => return self.writeInstToStreamGeneric(stream, .ptrtoint, decl, inst_table),469 .ptrtoint => return self.writeInstToStreamGeneric(stream, .ptrtoint, decl, inst_table),
...@@ -576,6 +578,7 @@ pub fn parse(allocator: *Allocator, source: [:0]const u8) Allocator.Error!Module...@@ -576,6 +578,7 @@ pub fn parse(allocator: *Allocator, source: [:0]const u8) Allocator.Error!Module
576 .source = source,578 .source = source,
577 .global_name_map = &global_name_map,579 .global_name_map = &global_name_map,
578 .decls = .{},580 .decls = .{},
581 .unnamed_index = 0,
579 };582 };
580 errdefer parser.arena.deinit();583 errdefer parser.arena.deinit();
581584
...@@ -601,6 +604,7 @@ const Parser = struct {...@@ -601,6 +604,7 @@ const Parser = struct {
601 decls: std.ArrayListUnmanaged(*Inst),604 decls: std.ArrayListUnmanaged(*Inst),
602 global_name_map: *std.StringHashMap(usize),605 global_name_map: *std.StringHashMap(usize),
603 error_msg: ?ErrorMsg = null,606 error_msg: ?ErrorMsg = null,
607 unnamed_index: usize,
604608
605 const Body = struct {609 const Body = struct {
606 instructions: std.ArrayList(*Inst),610 instructions: std.ArrayList(*Inst),
...@@ -626,12 +630,12 @@ const Parser = struct {...@@ -626,12 +630,12 @@ const Parser = struct {
626 skipSpace(self);630 skipSpace(self);
627 try requireEatBytes(self, "=");631 try requireEatBytes(self, "=");
628 skipSpace(self);632 skipSpace(self);
629 const inst = try parseInstruction(self, &body_context);633 const inst = try parseInstruction(self, &body_context, ident[1..]);
630 const ident_index = body_context.instructions.items.len;634 const ident_index = body_context.instructions.items.len;
631 if (try body_context.name_map.put(ident, ident_index)) |_| {635 if (try body_context.name_map.put(ident, ident_index)) |_| {
632 return self.fail("redefinition of identifier '{}'", .{ident});636 return self.fail("redefinition of identifier '{}'", .{ident});
633 }637 }
634 try body_context.instructions.append(self.allocator, inst);638 try body_context.instructions.append(inst);
635 continue;639 continue;
636 },640 },
637 ' ', '\n' => continue,641 ' ', '\n' => continue,
...@@ -712,7 +716,7 @@ const Parser = struct {...@@ -712,7 +716,7 @@ const Parser = struct {
712 skipSpace(self);716 skipSpace(self);
713 try requireEatBytes(self, "=");717 try requireEatBytes(self, "=");
714 skipSpace(self);718 skipSpace(self);
715 const inst = try parseInstruction(self, null);719 const inst = try parseInstruction(self, null, ident[1..]);
716 const ident_index = self.decls.items.len;720 const ident_index = self.decls.items.len;
717 if (try self.global_name_map.put(ident, ident_index)) |_| {721 if (try self.global_name_map.put(ident, ident_index)) |_| {
718 return self.fail("redefinition of identifier '{}'", .{ident});722 return self.fail("redefinition of identifier '{}'", .{ident});
...@@ -781,12 +785,12 @@ const Parser = struct {...@@ -781,12 +785,12 @@ const Parser = struct {
781 return error.ParseFailure;785 return error.ParseFailure;
782 }786 }
783787
784 fn parseInstruction(self: *Parser, body_ctx: ?*Body) InnerError!*Inst {788 fn parseInstruction(self: *Parser, body_ctx: ?*Body, name: []const u8) InnerError!*Inst {
785 const fn_name = try skipToAndOver(self, '(');789 const fn_name = try skipToAndOver(self, '(');
786 inline for (@typeInfo(Inst.Tag).Enum.fields) |field| {790 inline for (@typeInfo(Inst.Tag).Enum.fields) |field| {
787 if (mem.eql(u8, field.name, fn_name)) {791 if (mem.eql(u8, field.name, fn_name)) {
788 const tag = @field(Inst.Tag, field.name);792 const tag = @field(Inst.Tag, field.name);
789 return parseInstructionGeneric(self, field.name, Inst.TagToType(tag), body_ctx);793 return parseInstructionGeneric(self, field.name, Inst.TagToType(tag), body_ctx, name);
790 }794 }
791 }795 }
792 return self.fail("unknown instruction '{}'", .{fn_name});796 return self.fail("unknown instruction '{}'", .{fn_name});
...@@ -797,9 +801,11 @@ const Parser = struct {...@@ -797,9 +801,11 @@ const Parser = struct {
797 comptime fn_name: []const u8,801 comptime fn_name: []const u8,
798 comptime InstType: type,802 comptime InstType: type,
799 body_ctx: ?*Body,803 body_ctx: ?*Body,
800 ) !*Inst {804 inst_name: []const u8,
805 ) InnerError!*Inst {
801 const inst_specific = try self.arena.allocator.create(InstType);806 const inst_specific = try self.arena.allocator.create(InstType);
802 inst_specific.base = .{807 inst_specific.base = .{
808 .name = inst_name,
803 .src = self.i,809 .src = self.i,
804 .tag = InstType.base_tag,810 .tag = InstType.base_tag,
805 };811 };
...@@ -885,7 +891,7 @@ const Parser = struct {...@@ -885,7 +891,7 @@ const Parser = struct {
885 var instructions = std.ArrayList(*Inst).init(&self.arena.allocator);891 var instructions = std.ArrayList(*Inst).init(&self.arena.allocator);
886 while (true) {892 while (true) {
887 skipSpace(self);893 skipSpace(self);
888 try instructions.append(self.allocator, try parseParameterInst(self, body_ctx));894 try instructions.append(try parseParameterInst(self, body_ctx));
889 skipSpace(self);895 skipSpace(self);
890 if (!eatByte(self, ',')) break;896 if (!eatByte(self, ',')) break;
891 }897 }
...@@ -930,13 +936,21 @@ const Parser = struct {...@@ -930,13 +936,21 @@ const Parser = struct {
930 } else {936 } else {
931 const name = try self.arena.allocator.create(Inst.Str);937 const name = try self.arena.allocator.create(Inst.Str);
932 name.* = .{938 name.* = .{
933 .base = .{ .src = src, .tag = Inst.Str.base_tag },939 .base = .{
940 .name = try self.generateName(),
941 .src = src,
942 .tag = Inst.Str.base_tag,
943 },
934 .positionals = .{ .bytes = ident },944 .positionals = .{ .bytes = ident },
935 .kw_args = .{},945 .kw_args = .{},
936 };946 };
937 const declref = try self.arena.allocator.create(Inst.DeclRef);947 const declref = try self.arena.allocator.create(Inst.DeclRef);
938 declref.* = .{948 declref.* = .{
939 .base = .{ .src = src, .tag = Inst.DeclRef.base_tag },949 .base = .{
950 .name = try self.generateName(),
951 .src = src,
952 .tag = Inst.DeclRef.base_tag,
953 },
940 .positionals = .{ .name = &name.base },954 .positionals = .{ .name = &name.base },
941 .kw_args = .{},955 .kw_args = .{},
942 };956 };
...@@ -949,25 +963,31 @@ const Parser = struct {...@@ -949,25 +963,31 @@ const Parser = struct {
949 return self.decls.items[kv.value];963 return self.decls.items[kv.value];
950 }964 }
951 }965 }
966
967 fn generateName(self: *Parser) ![]u8 {
968 const result = try std.fmt.allocPrint(&self.arena.allocator, "unnamed${}", .{self.unnamed_index});
969 self.unnamed_index += 1;
970 return result;
971 }
952};972};
953973
954pub fn emit_zir(allocator: *Allocator, old_module: ir.Module) !Module {974pub fn emit_zir(allocator: *Allocator, old_module: ir.Module) !Module {
955 var ctx: EmitZIR = .{975 var ctx: EmitZIR = .{
956 .allocator = allocator,976 .allocator = allocator,
957 .decls = std.ArrayList(*Inst).init(allocator),977 .decls = .{},
958 .decl_table = std.AutoHashMap(*ir.Inst, *Inst).init(allocator),978 .decl_table = std.AutoHashMap(*ir.Inst, *Inst).init(allocator),
959 .arena = std.heap.ArenaAllocator.init(allocator),979 .arena = std.heap.ArenaAllocator.init(allocator),
960 .old_module = &old_module,980 .old_module = &old_module,
961 };981 };
962 defer ctx.decls.deinit();982 defer ctx.decls.deinit(allocator);
963 defer ctx.decl_table.deinit();983 defer ctx.decl_table.deinit();
964 errdefer ctx.arena.deinit();984 errdefer ctx.arena.deinit();
965985
966 try ctx.emit();986 try ctx.emit();
967987
968 return Module{988 return Module{
969 .decls = ctx.decls.toOwnedSlice(),989 .decls = ctx.decls.toOwnedSlice(allocator),
970 .arena = ctx.arena,990 .arena = ctx.arena.state,
971 };991 };
972}992}
973993
...@@ -975,23 +995,32 @@ const EmitZIR = struct {...@@ -975,23 +995,32 @@ const EmitZIR = struct {
975 allocator: *Allocator,995 allocator: *Allocator,
976 arena: std.heap.ArenaAllocator,996 arena: std.heap.ArenaAllocator,
977 old_module: *const ir.Module,997 old_module: *const ir.Module,
978 decls: std.ArrayList(*Inst),998 decls: std.ArrayListUnmanaged(*Inst),
979 decl_table: std.AutoHashMap(*ir.Inst, *Inst),999 decl_table: std.AutoHashMap(*ir.Inst, *Inst),
9801000
981 fn emit(self: *EmitZIR) !void {1001 fn emit(self: *EmitZIR) !void {
982 for (self.old_module.exports) |module_export| {1002 var it = self.old_module.decl_exports.iterator();
983 const export_value = try self.emitTypedValue(module_export.src, module_export.typed_value);1003 while (it.next()) |kv| {
984 const symbol_name = try self.emitStringLiteral(module_export.src, module_export.name);1004 const decl = kv.key;
985 const export_inst = try self.arena.allocator.create(Inst.Export);1005 const exports = kv.value;
986 export_inst.* = .{1006 const export_value = try self.emitTypedValue(decl.src, decl.typed_value.most_recent.typed_value);
987 .base = .{ .src = module_export.src, .tag = Inst.Export.base_tag },1007 for (exports) |module_export| {
988 .positionals = .{1008 const symbol_name = try self.emitStringLiteral(module_export.src, module_export.options.name);
989 .symbol_name = symbol_name,1009 const export_inst = try self.arena.allocator.create(Inst.Export);
990 .value = export_value,1010 export_inst.* = .{
991 },1011 .base = .{
992 .kw_args = .{},1012 .name = try self.autoName(),
993 };1013 .src = module_export.src,
994 try self.decls.append(self.allocator, &export_inst.base);1014 .tag = Inst.Export.base_tag,
1015 },
1016 .positionals = .{
1017 .symbol_name = symbol_name,
1018 .value = export_value,
1019 },
1020 .kw_args = .{},
1021 };
1022 try self.decls.append(self.allocator, &export_inst.base);
1023 }
995 }1024 }
996 }1025 }
9971026
...@@ -1012,7 +1041,11 @@ const EmitZIR = struct {...@@ -1012,7 +1041,11 @@ const EmitZIR = struct {
1012 const big_int_space = try self.arena.allocator.create(Value.BigIntSpace);1041 const big_int_space = try self.arena.allocator.create(Value.BigIntSpace);
1013 const int_inst = try self.arena.allocator.create(Inst.Int);1042 const int_inst = try self.arena.allocator.create(Inst.Int);
1014 int_inst.* = .{1043 int_inst.* = .{
1015 .base = .{ .src = src, .tag = Inst.Int.base_tag },1044 .base = .{
1045 .name = try self.autoName(),
1046 .src = src,
1047 .tag = Inst.Int.base_tag,
1048 },
1016 .positionals = .{1049 .positionals = .{
1017 .int = val.toBigInt(big_int_space),1050 .int = val.toBigInt(big_int_space),
1018 },1051 },
...@@ -1022,7 +1055,7 @@ const EmitZIR = struct {...@@ -1022,7 +1055,7 @@ const EmitZIR = struct {
1022 return &int_inst.base;1055 return &int_inst.base;
1023 }1056 }
10241057
1025 fn emitTypedValue(self: *EmitZIR, src: usize, typed_value: ir.TypedValue) Allocator.Error!*Inst {1058 fn emitTypedValue(self: *EmitZIR, src: usize, typed_value: TypedValue) Allocator.Error!*Inst {
1026 switch (typed_value.ty.zigTypeTag()) {1059 switch (typed_value.ty.zigTypeTag()) {
1027 .Pointer => {1060 .Pointer => {
1028 const ptr_elem_type = typed_value.ty.elemType();1061 const ptr_elem_type = typed_value.ty.elemType();
...@@ -1044,7 +1077,11 @@ const EmitZIR = struct {...@@ -1044,7 +1077,11 @@ const EmitZIR = struct {
1044 .Int => {1077 .Int => {
1045 const as_inst = try self.arena.allocator.create(Inst.As);1078 const as_inst = try self.arena.allocator.create(Inst.As);
1046 as_inst.* = .{1079 as_inst.* = .{
1047 .base = .{ .src = src, .tag = Inst.As.base_tag },1080 .base = .{
1081 .name = try self.autoName(),
1082 .src = src,
1083 .tag = Inst.As.base_tag,
1084 },
1048 .positionals = .{1085 .positionals = .{
1049 .dest_type = try self.emitType(src, typed_value.ty),1086 .dest_type = try self.emitType(src, typed_value.ty),
1050 .value = try self.emitComptimeIntVal(src, typed_value.val),1087 .value = try self.emitComptimeIntVal(src, typed_value.val),
...@@ -1060,8 +1097,7 @@ const EmitZIR = struct {...@@ -1060,8 +1097,7 @@ const EmitZIR = struct {
1060 return self.emitType(src, ty);1097 return self.emitType(src, ty);
1061 },1098 },
1062 .Fn => {1099 .Fn => {
1063 const index = typed_value.val.cast(Value.Payload.Function).?.index;1100 const module_fn = typed_value.val.cast(Value.Payload.Function).?.func;
1064 const module_fn = self.old_module.fns[index];
10651101
1066 var inst_table = std.AutoHashMap(*ir.Inst, *Inst).init(self.allocator);1102 var inst_table = std.AutoHashMap(*ir.Inst, *Inst).init(self.allocator);
1067 defer inst_table.deinit();1103 defer inst_table.deinit();
...@@ -1069,7 +1105,7 @@ const EmitZIR = struct {...@@ -1069,7 +1105,7 @@ const EmitZIR = struct {
1069 var instructions = std.ArrayList(*Inst).init(self.allocator);1105 var instructions = std.ArrayList(*Inst).init(self.allocator);
1070 defer instructions.deinit();1106 defer instructions.deinit();
10711107
1072 try self.emitBody(module_fn.body, &inst_table, &instructions);1108 try self.emitBody(module_fn.analysis.success, &inst_table, &instructions);
10731109
1074 const fn_type = try self.emitType(src, module_fn.fn_type);1110 const fn_type = try self.emitType(src, module_fn.fn_type);
10751111
...@@ -1078,7 +1114,11 @@ const EmitZIR = struct {...@@ -1078,7 +1114,11 @@ const EmitZIR = struct {
10781114
1079 const fn_inst = try self.arena.allocator.create(Inst.Fn);1115 const fn_inst = try self.arena.allocator.create(Inst.Fn);
1080 fn_inst.* = .{1116 fn_inst.* = .{
1081 .base = .{ .src = src, .tag = Inst.Fn.base_tag },1117 .base = .{
1118 .name = try self.autoName(),
1119 .src = src,
1120 .tag = Inst.Fn.base_tag,
1121 },
1082 .positionals = .{1122 .positionals = .{
1083 .fn_type = fn_type,1123 .fn_type = fn_type,
1084 .body = .{ .instructions = arena_instrs },1124 .body = .{ .instructions = arena_instrs },
...@@ -1095,7 +1135,11 @@ const EmitZIR = struct {...@@ -1095,7 +1135,11 @@ const EmitZIR = struct {
1095 fn emitTrivial(self: *EmitZIR, src: usize, comptime T: type) Allocator.Error!*Inst {1135 fn emitTrivial(self: *EmitZIR, src: usize, comptime T: type) Allocator.Error!*Inst {
1096 const new_inst = try self.arena.allocator.create(T);1136 const new_inst = try self.arena.allocator.create(T);
1097 new_inst.* = .{1137 new_inst.* = .{
1098 .base = .{ .src = src, .tag = T.base_tag },1138 .base = .{
1139 .name = try self.autoName(),
1140 .src = src,
1141 .tag = T.base_tag,
1142 },
1099 .positionals = .{},1143 .positionals = .{},
1100 .kw_args = .{},1144 .kw_args = .{},
1101 };1145 };
...@@ -1120,7 +1164,11 @@ const EmitZIR = struct {...@@ -1120,7 +1164,11 @@ const EmitZIR = struct {
1120 elem.* = try self.resolveInst(inst_table, old_inst.args.args[i]);1164 elem.* = try self.resolveInst(inst_table, old_inst.args.args[i]);
1121 }1165 }
1122 new_inst.* = .{1166 new_inst.* = .{
1123 .base = .{ .src = inst.src, .tag = Inst.Call.base_tag },1167 .base = .{
1168 .name = try self.autoName(),
1169 .src = inst.src,
1170 .tag = Inst.Call.base_tag,
1171 },
1124 .positionals = .{1172 .positionals = .{
1125 .func = try self.resolveInst(inst_table, old_inst.args.func),1173 .func = try self.resolveInst(inst_table, old_inst.args.func),
1126 .args = args,1174 .args = args,
...@@ -1152,7 +1200,11 @@ const EmitZIR = struct {...@@ -1152,7 +1200,11 @@ const EmitZIR = struct {
1152 }1200 }
11531201
1154 new_inst.* = .{1202 new_inst.* = .{
1155 .base = .{ .src = inst.src, .tag = Inst.Asm.base_tag },1203 .base = .{
1204 .name = try self.autoName(),
1205 .src = inst.src,
1206 .tag = Inst.Asm.base_tag,
1207 },
1156 .positionals = .{1208 .positionals = .{
1157 .asm_source = try self.emitStringLiteral(inst.src, old_inst.args.asm_source),1209 .asm_source = try self.emitStringLiteral(inst.src, old_inst.args.asm_source),
1158 .return_type = try self.emitType(inst.src, inst.ty),1210 .return_type = try self.emitType(inst.src, inst.ty),
...@@ -1174,7 +1226,11 @@ const EmitZIR = struct {...@@ -1174,7 +1226,11 @@ const EmitZIR = struct {
1174 const old_inst = inst.cast(ir.Inst.PtrToInt).?;1226 const old_inst = inst.cast(ir.Inst.PtrToInt).?;
1175 const new_inst = try self.arena.allocator.create(Inst.PtrToInt);1227 const new_inst = try self.arena.allocator.create(Inst.PtrToInt);
1176 new_inst.* = .{1228 new_inst.* = .{
1177 .base = .{ .src = inst.src, .tag = Inst.PtrToInt.base_tag },1229 .base = .{
1230 .name = try self.autoName(),
1231 .src = inst.src,
1232 .tag = Inst.PtrToInt.base_tag,
1233 },
1178 .positionals = .{1234 .positionals = .{
1179 .ptr = try self.resolveInst(inst_table, old_inst.args.ptr),1235 .ptr = try self.resolveInst(inst_table, old_inst.args.ptr),
1180 },1236 },
...@@ -1186,7 +1242,11 @@ const EmitZIR = struct {...@@ -1186,7 +1242,11 @@ const EmitZIR = struct {
1186 const old_inst = inst.cast(ir.Inst.BitCast).?;1242 const old_inst = inst.cast(ir.Inst.BitCast).?;
1187 const new_inst = try self.arena.allocator.create(Inst.BitCast);1243 const new_inst = try self.arena.allocator.create(Inst.BitCast);
1188 new_inst.* = .{1244 new_inst.* = .{
1189 .base = .{ .src = inst.src, .tag = Inst.BitCast.base_tag },1245 .base = .{
1246 .name = try self.autoName(),
1247 .src = inst.src,
1248 .tag = Inst.BitCast.base_tag,
1249 },
1190 .positionals = .{1250 .positionals = .{
1191 .dest_type = try self.emitType(inst.src, inst.ty),1251 .dest_type = try self.emitType(inst.src, inst.ty),
1192 .operand = try self.resolveInst(inst_table, old_inst.args.operand),1252 .operand = try self.resolveInst(inst_table, old_inst.args.operand),
...@@ -1199,7 +1259,11 @@ const EmitZIR = struct {...@@ -1199,7 +1259,11 @@ const EmitZIR = struct {
1199 const old_inst = inst.cast(ir.Inst.Cmp).?;1259 const old_inst = inst.cast(ir.Inst.Cmp).?;
1200 const new_inst = try self.arena.allocator.create(Inst.Cmp);1260 const new_inst = try self.arena.allocator.create(Inst.Cmp);
1201 new_inst.* = .{1261 new_inst.* = .{
1202 .base = .{ .src = inst.src, .tag = Inst.Cmp.base_tag },1262 .base = .{
1263 .name = try self.autoName(),
1264 .src = inst.src,
1265 .tag = Inst.Cmp.base_tag,
1266 },
1203 .positionals = .{1267 .positionals = .{
1204 .lhs = try self.resolveInst(inst_table, old_inst.args.lhs),1268 .lhs = try self.resolveInst(inst_table, old_inst.args.lhs),
1205 .rhs = try self.resolveInst(inst_table, old_inst.args.rhs),1269 .rhs = try self.resolveInst(inst_table, old_inst.args.rhs),
...@@ -1223,7 +1287,11 @@ const EmitZIR = struct {...@@ -1223,7 +1287,11 @@ const EmitZIR = struct {
12231287
1224 const new_inst = try self.arena.allocator.create(Inst.CondBr);1288 const new_inst = try self.arena.allocator.create(Inst.CondBr);
1225 new_inst.* = .{1289 new_inst.* = .{
1226 .base = .{ .src = inst.src, .tag = Inst.CondBr.base_tag },1290 .base = .{
1291 .name = try self.autoName(),
1292 .src = inst.src,
1293 .tag = Inst.CondBr.base_tag,
1294 },
1227 .positionals = .{1295 .positionals = .{
1228 .condition = try self.resolveInst(inst_table, old_inst.args.condition),1296 .condition = try self.resolveInst(inst_table, old_inst.args.condition),
1229 .true_body = .{ .instructions = true_body.toOwnedSlice() },1297 .true_body = .{ .instructions = true_body.toOwnedSlice() },
...@@ -1237,7 +1305,11 @@ const EmitZIR = struct {...@@ -1237,7 +1305,11 @@ const EmitZIR = struct {
1237 const old_inst = inst.cast(ir.Inst.IsNull).?;1305 const old_inst = inst.cast(ir.Inst.IsNull).?;
1238 const new_inst = try self.arena.allocator.create(Inst.IsNull);1306 const new_inst = try self.arena.allocator.create(Inst.IsNull);
1239 new_inst.* = .{1307 new_inst.* = .{
1240 .base = .{ .src = inst.src, .tag = Inst.IsNull.base_tag },1308 .base = .{
1309 .name = try self.autoName(),
1310 .src = inst.src,
1311 .tag = Inst.IsNull.base_tag,
1312 },
1241 .positionals = .{1313 .positionals = .{
1242 .operand = try self.resolveInst(inst_table, old_inst.args.operand),1314 .operand = try self.resolveInst(inst_table, old_inst.args.operand),
1243 },1315 },
...@@ -1249,7 +1321,11 @@ const EmitZIR = struct {...@@ -1249,7 +1321,11 @@ const EmitZIR = struct {
1249 const old_inst = inst.cast(ir.Inst.IsNonNull).?;1321 const old_inst = inst.cast(ir.Inst.IsNonNull).?;
1250 const new_inst = try self.arena.allocator.create(Inst.IsNonNull);1322 const new_inst = try self.arena.allocator.create(Inst.IsNonNull);
1251 new_inst.* = .{1323 new_inst.* = .{
1252 .base = .{ .src = inst.src, .tag = Inst.IsNonNull.base_tag },1324 .base = .{
1325 .name = try self.autoName(),
1326 .src = inst.src,
1327 .tag = Inst.IsNonNull.base_tag,
1328 },
1253 .positionals = .{1329 .positionals = .{
1254 .operand = try self.resolveInst(inst_table, old_inst.args.operand),1330 .operand = try self.resolveInst(inst_table, old_inst.args.operand),
1255 },1331 },
...@@ -1258,7 +1334,7 @@ const EmitZIR = struct {...@@ -1258,7 +1334,7 @@ const EmitZIR = struct {
1258 break :blk &new_inst.base;1334 break :blk &new_inst.base;
1259 },1335 },
1260 };1336 };
1261 try instructions.append(self.allocator, new_inst);1337 try instructions.append(new_inst);
1262 try inst_table.putNoClobber(inst, new_inst);1338 try inst_table.putNoClobber(inst, new_inst);
1263 }1339 }
1264 }1340 }
...@@ -1301,7 +1377,11 @@ const EmitZIR = struct {...@@ -1301,7 +1377,11 @@ const EmitZIR = struct {
13011377
1302 const fntype_inst = try self.arena.allocator.create(Inst.FnType);1378 const fntype_inst = try self.arena.allocator.create(Inst.FnType);
1303 fntype_inst.* = .{1379 fntype_inst.* = .{
1304 .base = .{ .src = src, .tag = Inst.FnType.base_tag },1380 .base = .{
1381 .name = try self.autoName(),
1382 .src = src,
1383 .tag = Inst.FnType.base_tag,
1384 },
1305 .positionals = .{1385 .positionals = .{
1306 .param_types = emitted_params,1386 .param_types = emitted_params,
1307 .return_type = try self.emitType(src, ty.fnReturnType()),1387 .return_type = try self.emitType(src, ty.fnReturnType()),
...@@ -1318,10 +1398,18 @@ const EmitZIR = struct {...@@ -1318,10 +1398,18 @@ const EmitZIR = struct {
1318 }1398 }
1319 }1399 }
13201400
1401 fn autoName(self: *EmitZIR) ![]u8 {
1402 return std.fmt.allocPrint(&self.arena.allocator, "{}", .{self.decls.items.len});
1403 }
1404
1321 fn emitPrimitiveType(self: *EmitZIR, src: usize, tag: Inst.Primitive.BuiltinType) !*Inst {1405 fn emitPrimitiveType(self: *EmitZIR, src: usize, tag: Inst.Primitive.BuiltinType) !*Inst {
1322 const primitive_inst = try self.arena.allocator.create(Inst.Primitive);1406 const primitive_inst = try self.arena.allocator.create(Inst.Primitive);
1323 primitive_inst.* = .{1407 primitive_inst.* = .{
1324 .base = .{ .src = src, .tag = Inst.Primitive.base_tag },1408 .base = .{
1409 .name = try self.autoName(),
1410 .src = src,
1411 .tag = Inst.Primitive.base_tag,
1412 },
1325 .positionals = .{1413 .positionals = .{
1326 .tag = tag,1414 .tag = tag,
1327 },1415 },
...@@ -1334,7 +1422,11 @@ const EmitZIR = struct {...@@ -1334,7 +1422,11 @@ const EmitZIR = struct {
1334 fn emitStringLiteral(self: *EmitZIR, src: usize, str: []const u8) !*Inst {1422 fn emitStringLiteral(self: *EmitZIR, src: usize, str: []const u8) !*Inst {
1335 const str_inst = try self.arena.allocator.create(Inst.Str);1423 const str_inst = try self.arena.allocator.create(Inst.Str);
1336 str_inst.* = .{1424 str_inst.* = .{
1337 .base = .{ .src = src, .tag = Inst.Str.base_tag },1425 .base = .{
1426 .name = try self.autoName(),
1427 .src = src,
1428 .tag = Inst.Str.base_tag,
1429 },
1338 .positionals = .{1430 .positionals = .{
1339 .bytes = str,1431 .bytes = str,
1340 },1432 },
src-self-hosted/link.zig+61-29
...@@ -153,7 +153,7 @@ pub const ElfFile = struct {...@@ -153,7 +153,7 @@ pub const ElfFile = struct {
153 };153 };
154154
155 pub const Export = struct {155 pub const Export = struct {
156 sym_index: usize,156 sym_index: ?usize = null,
157 };157 };
158158
159 pub fn deinit(self: *ElfFile) void {159 pub fn deinit(self: *ElfFile) void {
...@@ -249,6 +249,11 @@ pub const ElfFile = struct {...@@ -249,6 +249,11 @@ pub const ElfFile = struct {
249 return @intCast(u32, result);249 return @intCast(u32, result);
250 }250 }
251251
252 fn getString(self: *ElfFile, str_off: u32) []const u8 {
253 assert(str_off < self.shstrtab.items.len);
254 return mem.spanZ(@ptrCast([*:0]const u8, self.shstrtab.items.ptr + str_off));
255 }
256
252 fn updateString(self: *ElfFile, old_str_off: u32, new_name: []const u8) !u32 {257 fn updateString(self: *ElfFile, old_str_off: u32, new_name: []const u8) !u32 {
253 const existing_name = self.getString(old_str_off);258 const existing_name = self.getString(old_str_off);
254 if (mem.eql(u8, existing_name, new_name)) {259 if (mem.eql(u8, existing_name, new_name)) {
...@@ -418,6 +423,14 @@ pub const ElfFile = struct {...@@ -418,6 +423,14 @@ pub const ElfFile = struct {
418 const foreign_endian = self.options.target.cpu.arch.endian() != std.Target.current.cpu.arch.endian();423 const foreign_endian = self.options.target.cpu.arch.endian() != std.Target.current.cpu.arch.endian();
419424
420 if (self.phdr_table_dirty) {425 if (self.phdr_table_dirty) {
426 const phsize: u64 = switch (self.ptr_width) {
427 .p32 => @sizeOf(elf.Elf32_Phdr),
428 .p64 => @sizeOf(elf.Elf64_Phdr),
429 };
430 const phalign: u16 = switch (self.ptr_width) {
431 .p32 => @alignOf(elf.Elf32_Phdr),
432 .p64 => @alignOf(elf.Elf64_Phdr),
433 };
421 const allocated_size = self.allocatedSize(self.phdr_table_offset.?);434 const allocated_size = self.allocatedSize(self.phdr_table_offset.?);
422 const needed_size = self.program_headers.items.len * phsize;435 const needed_size = self.program_headers.items.len * phsize;
423436
...@@ -426,11 +439,10 @@ pub const ElfFile = struct {...@@ -426,11 +439,10 @@ pub const ElfFile = struct {
426 self.phdr_table_offset = self.findFreeSpace(needed_size, phalign);439 self.phdr_table_offset = self.findFreeSpace(needed_size, phalign);
427 }440 }
428441
429 const allocator = self.program_headers.allocator;
430 switch (self.ptr_width) {442 switch (self.ptr_width) {
431 .p32 => {443 .p32 => {
432 const buf = try allocator.alloc(elf.Elf32_Phdr, self.program_headers.items.len);444 const buf = try self.allocator.alloc(elf.Elf32_Phdr, self.program_headers.items.len);
433 defer allocator.free(buf);445 defer self.allocator.free(buf);
434446
435 for (buf) |*phdr, i| {447 for (buf) |*phdr, i| {
436 phdr.* = progHeaderTo32(self.program_headers.items[i]);448 phdr.* = progHeaderTo32(self.program_headers.items[i]);
...@@ -441,8 +453,8 @@ pub const ElfFile = struct {...@@ -441,8 +453,8 @@ pub const ElfFile = struct {
441 try self.file.pwriteAll(mem.sliceAsBytes(buf), self.phdr_table_offset.?);453 try self.file.pwriteAll(mem.sliceAsBytes(buf), self.phdr_table_offset.?);
442 },454 },
443 .p64 => {455 .p64 => {
444 const buf = try allocator.alloc(elf.Elf64_Phdr, self.program_headers.items.len);456 const buf = try self.allocator.alloc(elf.Elf64_Phdr, self.program_headers.items.len);
445 defer allocator.free(buf);457 defer self.allocator.free(buf);
446458
447 for (buf) |*phdr, i| {459 for (buf) |*phdr, i| {
448 phdr.* = self.program_headers.items[i];460 phdr.* = self.program_headers.items[i];
...@@ -478,12 +490,20 @@ pub const ElfFile = struct {...@@ -478,12 +490,20 @@ pub const ElfFile = struct {
478 }490 }
479 }491 }
480 if (self.shdr_table_dirty) {492 if (self.shdr_table_dirty) {
493 const shsize: u64 = switch (self.ptr_width) {
494 .p32 => @sizeOf(elf.Elf32_Shdr),
495 .p64 => @sizeOf(elf.Elf64_Shdr),
496 };
497 const shalign: u16 = switch (self.ptr_width) {
498 .p32 => @alignOf(elf.Elf32_Shdr),
499 .p64 => @alignOf(elf.Elf64_Shdr),
500 };
481 const allocated_size = self.allocatedSize(self.shdr_table_offset.?);501 const allocated_size = self.allocatedSize(self.shdr_table_offset.?);
482 const needed_size = self.sections.items.len * phsize;502 const needed_size = self.sections.items.len * shsize;
483503
484 if (needed_size > allocated_size) {504 if (needed_size > allocated_size) {
485 self.shdr_table_offset = null; // free the space505 self.shdr_table_offset = null; // free the space
486 self.shdr_table_offset = self.findFreeSpace(needed_size, phalign);506 self.shdr_table_offset = self.findFreeSpace(needed_size, shalign);
487 }507 }
488508
489 switch (self.ptr_width) {509 switch (self.ptr_width) {
...@@ -719,7 +739,7 @@ pub const ElfFile = struct {...@@ -719,7 +739,7 @@ pub const ElfFile = struct {
719 defer code.deinit();739 defer code.deinit();
720740
721 const typed_value = decl.typed_value.most_recent.typed_value;741 const typed_value = decl.typed_value.most_recent.typed_value;
722 const err_msg = try codegen.generateSymbol(typed_value, module, &code);742 const err_msg = try codegen.generateSymbol(typed_value, module.*, &code);
723 if (err_msg != null) |em| {743 if (err_msg != null) |em| {
724 decl.analysis = .codegen_failure;744 decl.analysis = .codegen_failure;
725 _ = try module.failed_decls.put(decl, em);745 _ = try module.failed_decls.put(decl, em);
...@@ -751,15 +771,15 @@ pub const ElfFile = struct {...@@ -751,15 +771,15 @@ pub const ElfFile = struct {
751 try self.writeSymbol(decl.link.local_sym_index);771 try self.writeSymbol(decl.link.local_sym_index);
752 break :blk file_offset;772 break :blk file_offset;
753 } else {773 } else {
754 try self.symbols.ensureCapacity(self.symbols.items.len + 1);774 try self.symbols.ensureCapacity(self.allocator, self.symbols.items.len + 1);
755 try self.offset_table.ensureCapacity(self.offset_table.items.len + 1);775 try self.offset_table.ensureCapacity(self.allocator, self.offset_table.items.len + 1);
756 const decl_name = mem.spanZ(u8, decl.name);776 const decl_name = mem.spanZ(u8, decl.name);
757 const name_str_index = try self.makeString(decl_name);777 const name_str_index = try self.makeString(decl_name);
758 const new_block = try self.allocateTextBlock(code_size);778 const new_block = try self.allocateTextBlock(code_size);
759 const local_sym_index = self.symbols.items.len;779 const local_sym_index = self.symbols.items.len;
760 const offset_table_index = self.offset_table.items.len;780 const offset_table_index = self.offset_table.items.len;
761781
762 self.symbols.appendAssumeCapacity(self.allocator, .{782 self.symbols.appendAssumeCapacity(.{
763 .st_name = name_str_index,783 .st_name = name_str_index,
764 .st_info = (elf.STB_LOCAL << 4) | stt_bits,784 .st_info = (elf.STB_LOCAL << 4) | stt_bits,
765 .st_other = 0,785 .st_other = 0,
...@@ -767,9 +787,9 @@ pub const ElfFile = struct {...@@ -767,9 +787,9 @@ pub const ElfFile = struct {
767 .st_value = new_block.vaddr,787 .st_value = new_block.vaddr,
768 .st_size = code_size,788 .st_size = code_size,
769 });789 });
770 errdefer self.symbols.shrink(self.symbols.items.len - 1);790 errdefer self.symbols.shrink(self.allocator, self.symbols.items.len - 1);
771 self.offset_table.appendAssumeCapacity(self.allocator, new_block.vaddr);791 self.offset_table.appendAssumeCapacity(new_block.vaddr);
772 errdefer self.offset_table.shrink(self.offset_table.items.len - 1);792 errdefer self.offset_table.shrink(self.allocator, self.offset_table.items.len - 1);
773 try self.writeSymbol(local_sym_index);793 try self.writeSymbol(local_sym_index);
774 try self.writeOffsetTableEntry(offset_table_index);794 try self.writeOffsetTableEntry(offset_table_index);
775795
...@@ -796,11 +816,12 @@ pub const ElfFile = struct {...@@ -796,11 +816,12 @@ pub const ElfFile = struct {
796 self: *ElfFile,816 self: *ElfFile,
797 module: *ir.Module,817 module: *ir.Module,
798 decl: *const ir.Module.Decl,818 decl: *const ir.Module.Decl,
799 exports: []const *const Export,819 exports: []const *ir.Module.Export,
800 ) !void {820 ) !void {
801 try self.symbols.ensureCapacity(self.symbols.items.len + exports.len);821 try self.symbols.ensureCapacity(self.allocator, self.symbols.items.len + exports.len);
802 const typed_value = decl.typed_value.most_recent.typed_value;822 const typed_value = decl.typed_value.most_recent.typed_value;
803 const decl_sym = self.symbols.items[decl.link.local_sym_index.?];823 assert(decl.link.local_sym_index != 0);
824 const decl_sym = self.symbols.items[decl.link.local_sym_index];
804825
805 for (exports) |exp| {826 for (exports) |exp| {
806 if (exp.options.section) |section_name| {827 if (exp.options.section) |section_name| {
...@@ -808,15 +829,16 @@ pub const ElfFile = struct {...@@ -808,15 +829,16 @@ pub const ElfFile = struct {
808 try module.failed_exports.ensureCapacity(module.failed_exports.size + 1);829 try module.failed_exports.ensureCapacity(module.failed_exports.size + 1);
809 module.failed_exports.putAssumeCapacityNoClobber(830 module.failed_exports.putAssumeCapacityNoClobber(
810 exp,831 exp,
811 try ir.ErrorMsg.create(0, "Unimplemented: ExportOptions.section", .{}),832 try ir.ErrorMsg.create(self.allocator, 0, "Unimplemented: ExportOptions.section", .{}),
812 );833 );
834 continue;
813 }835 }
814 }836 }
815 const stb_bits = switch (exp.options.linkage) {837 const stb_bits: u8 = switch (exp.options.linkage) {
816 .Internal => elf.STB_LOCAL,838 .Internal => elf.STB_LOCAL,
817 .Strong => blk: {839 .Strong => blk: {
818 if (mem.eql(u8, exp.options.name, "_start")) {840 if (mem.eql(u8, exp.options.name, "_start")) {
819 self.entry_addr = decl_symbol.vaddr;841 self.entry_addr = decl_sym.st_value;
820 }842 }
821 break :blk elf.STB_GLOBAL;843 break :blk elf.STB_GLOBAL;
822 },844 },
...@@ -825,8 +847,9 @@ pub const ElfFile = struct {...@@ -825,8 +847,9 @@ pub const ElfFile = struct {
825 try module.failed_exports.ensureCapacity(module.failed_exports.size + 1);847 try module.failed_exports.ensureCapacity(module.failed_exports.size + 1);
826 module.failed_exports.putAssumeCapacityNoClobber(848 module.failed_exports.putAssumeCapacityNoClobber(
827 exp,849 exp,
828 try ir.ErrorMsg.create(0, "Unimplemented: GlobalLinkage.LinkOnce", .{}),850 try ir.ErrorMsg.create(self.allocator, 0, "Unimplemented: GlobalLinkage.LinkOnce", .{}),
829 );851 );
852 continue;
830 },853 },
831 };854 };
832 const stt_bits: u8 = @truncate(u4, decl_sym.st_info);855 const stt_bits: u8 = @truncate(u4, decl_sym.st_info);
...@@ -844,15 +867,15 @@ pub const ElfFile = struct {...@@ -844,15 +867,15 @@ pub const ElfFile = struct {
844 } else {867 } else {
845 const name = try self.makeString(exp.options.name);868 const name = try self.makeString(exp.options.name);
846 const i = self.symbols.items.len;869 const i = self.symbols.items.len;
847 self.symbols.appendAssumeCapacity(self.allocator, .{870 self.symbols.appendAssumeCapacity(.{
848 .st_name = sn.name,871 .st_name = name,
849 .st_info = (stb_bits << 4) | stt_bits,872 .st_info = (stb_bits << 4) | stt_bits,
850 .st_other = 0,873 .st_other = 0,
851 .st_shndx = self.text_section_index.?,874 .st_shndx = self.text_section_index.?,
852 .st_value = decl_sym.st_value,875 .st_value = decl_sym.st_value,
853 .st_size = decl_sym.st_size,876 .st_size = decl_sym.st_size,
854 });877 });
855 errdefer self.symbols.shrink(self.symbols.items.len - 1);878 errdefer self.symbols.shrink(self.allocator, self.symbols.items.len - 1);
856 try self.writeSymbol(i);879 try self.writeSymbol(i);
857880
858 self.symbol_count_dirty = true;881 self.symbol_count_dirty = true;
...@@ -946,10 +969,15 @@ pub const ElfFile = struct {...@@ -946,10 +969,15 @@ pub const ElfFile = struct {
946 }969 }
947970
948 fn writeSymbol(self: *ElfFile, index: usize) !void {971 fn writeSymbol(self: *ElfFile, index: usize) !void {
972 assert(index != 0);
949 const syms_sect = &self.sections.items[self.symtab_section_index.?];973 const syms_sect = &self.sections.items[self.symtab_section_index.?];
950 // Make sure we are not pointlessly writing symbol data that will have to get relocated974 // Make sure we are not pointlessly writing symbol data that will have to get relocated
951 // due to running out of space.975 // due to running out of space.
952 if (self.symbol_count_dirty) {976 if (self.symbol_count_dirty) {
977 const sym_size: u64 = switch (self.ptr_width) {
978 .p32 => @sizeOf(elf.Elf32_Sym),
979 .p64 => @sizeOf(elf.Elf64_Sym),
980 };
953 const allocated_size = self.allocatedSize(syms_sect.sh_offset);981 const allocated_size = self.allocatedSize(syms_sect.sh_offset);
954 const needed_size = self.symbols.items.len * sym_size;982 const needed_size = self.symbols.items.len * sym_size;
955 if (needed_size > allocated_size) {983 if (needed_size > allocated_size) {
...@@ -990,11 +1018,15 @@ pub const ElfFile = struct {...@@ -990,11 +1018,15 @@ pub const ElfFile = struct {
990 }1018 }
9911019
992 fn writeAllSymbols(self: *ElfFile) !void {1020 fn writeAllSymbols(self: *ElfFile) !void {
993 const small_ptr = self.ptr_width == .p32;
994 const syms_sect = &self.sections.items[self.symtab_section_index.?];1021 const syms_sect = &self.sections.items[self.symtab_section_index.?];
995 const sym_align: u16 = if (small_ptr) @alignOf(elf.Elf32_Sym) else @alignOf(elf.Elf64_Sym);1022 const sym_align: u16 = switch (self.ptr_width) {
996 const sym_size: u64 = if (small_ptr) @sizeOf(elf.Elf32_Sym) else @sizeOf(elf.Elf64_Sym);1023 .p32 => @alignOf(elf.Elf32_Sym),
9971024 .p64 => @alignOf(elf.Elf64_Sym),
1025 };
1026 const sym_size: u64 = switch (self.ptr_width) {
1027 .p32 => @sizeOf(elf.Elf32_Sym),
1028 .p64 => @sizeOf(elf.Elf64_Sym),
1029 };
998 const allocated_size = self.allocatedSize(syms_sect.sh_offset);1030 const allocated_size = self.allocatedSize(syms_sect.sh_offset);
999 const needed_size = self.symbols.items.len * sym_size;1031 const needed_size = self.symbols.items.len * sym_size;
1000 if (needed_size > allocated_size) {1032 if (needed_size > allocated_size) {
src-self-hosted/value.zig+30-11
...@@ -67,6 +67,7 @@ pub const Value = extern union {...@@ -67,6 +67,7 @@ pub const Value = extern union {
67 int_big_positive,67 int_big_positive,
68 int_big_negative,68 int_big_negative,
69 function,69 function,
70 ref_val,
70 decl_ref,71 decl_ref,
71 elem_ptr,72 elem_ptr,
72 bytes,73 bytes,
...@@ -158,6 +159,11 @@ pub const Value = extern union {...@@ -158,6 +159,11 @@ pub const Value = extern union {
158 .int_big_positive => return out_stream.print("{}", .{val.cast(Payload.IntBigPositive).?.asBigInt()}),159 .int_big_positive => return out_stream.print("{}", .{val.cast(Payload.IntBigPositive).?.asBigInt()}),
159 .int_big_negative => return out_stream.print("{}", .{val.cast(Payload.IntBigNegative).?.asBigInt()}),160 .int_big_negative => return out_stream.print("{}", .{val.cast(Payload.IntBigNegative).?.asBigInt()}),
160 .function => return out_stream.writeAll("(function)"),161 .function => return out_stream.writeAll("(function)"),
162 .ref_val => {
163 const ref_val = val.cast(Payload.RefVal).?;
164 try out_stream.writeAll("&const ");
165 val = ref_val.val;
166 },
161 .decl_ref => return out_stream.writeAll("(decl ref)"),167 .decl_ref => return out_stream.writeAll("(decl ref)"),
162 .elem_ptr => {168 .elem_ptr => {
163 const elem_ptr = val.cast(Payload.ElemPtr).?;169 const elem_ptr = val.cast(Payload.ElemPtr).?;
...@@ -229,6 +235,7 @@ pub const Value = extern union {...@@ -229,6 +235,7 @@ pub const Value = extern union {
229 .int_big_positive,235 .int_big_positive,
230 .int_big_negative,236 .int_big_negative,
231 .function,237 .function,
238 .ref_val,
232 .decl_ref,239 .decl_ref,
233 .elem_ptr,240 .elem_ptr,
234 .bytes,241 .bytes,
...@@ -276,6 +283,7 @@ pub const Value = extern union {...@@ -276,6 +283,7 @@ pub const Value = extern union {
276 .bool_false,283 .bool_false,
277 .null_value,284 .null_value,
278 .function,285 .function,
286 .ref_val,
279 .decl_ref,287 .decl_ref,
280 .elem_ptr,288 .elem_ptr,
281 .bytes,289 .bytes,
...@@ -333,6 +341,7 @@ pub const Value = extern union {...@@ -333,6 +341,7 @@ pub const Value = extern union {
333 .bool_false,341 .bool_false,
334 .null_value,342 .null_value,
335 .function,343 .function,
344 .ref_val,
336 .decl_ref,345 .decl_ref,
337 .elem_ptr,346 .elem_ptr,
338 .bytes,347 .bytes,
...@@ -391,6 +400,7 @@ pub const Value = extern union {...@@ -391,6 +400,7 @@ pub const Value = extern union {
391 .bool_false,400 .bool_false,
392 .null_value,401 .null_value,
393 .function,402 .function,
403 .ref_val,
394 .decl_ref,404 .decl_ref,
395 .elem_ptr,405 .elem_ptr,
396 .bytes,406 .bytes,
...@@ -454,6 +464,7 @@ pub const Value = extern union {...@@ -454,6 +464,7 @@ pub const Value = extern union {
454 .bool_false,464 .bool_false,
455 .null_value,465 .null_value,
456 .function,466 .function,
467 .ref_val,
457 .decl_ref,468 .decl_ref,
458 .elem_ptr,469 .elem_ptr,
459 .bytes,470 .bytes,
...@@ -546,6 +557,7 @@ pub const Value = extern union {...@@ -546,6 +557,7 @@ pub const Value = extern union {
546 .bool_false,557 .bool_false,
547 .null_value,558 .null_value,
548 .function,559 .function,
560 .ref_val,
549 .decl_ref,561 .decl_ref,
550 .elem_ptr,562 .elem_ptr,
551 .bytes,563 .bytes,
...@@ -600,6 +612,7 @@ pub const Value = extern union {...@@ -600,6 +612,7 @@ pub const Value = extern union {
600 .bool_false,612 .bool_false,
601 .null_value,613 .null_value,
602 .function,614 .function,
615 .ref_val,
603 .decl_ref,616 .decl_ref,
604 .elem_ptr,617 .elem_ptr,
605 .bytes,618 .bytes,
...@@ -655,7 +668,8 @@ pub const Value = extern union {...@@ -655,7 +668,8 @@ pub const Value = extern union {
655 }668 }
656669
657 /// Asserts the value is a pointer and dereferences it.670 /// Asserts the value is a pointer and dereferences it.
658 pub fn pointerDeref(self: Value, module: *ir.Module) !Value {671 /// Returns error.AnalysisFail if the pointer points to a Decl that failed semantic analysis.
672 pub fn pointerDeref(self: Value, allocator: *Allocator) error{ AnalysisFail, OutOfMemory }!Value {
659 return switch (self.tag()) {673 return switch (self.tag()) {
660 .ty,674 .ty,
661 .u8_type,675 .u8_type,
...@@ -704,21 +718,19 @@ pub const Value = extern union {...@@ -704,21 +718,19 @@ pub const Value = extern union {
704 => unreachable,718 => unreachable,
705719
706 .the_one_possible_value => Value.initTag(.the_one_possible_value),720 .the_one_possible_value => Value.initTag(.the_one_possible_value),
707 .decl_ref => {721 .ref_val => self.cast(Payload.RefVal).?.val,
708 const index = self.cast(Payload.DeclRef).?.index;722 .decl_ref => self.cast(Payload.DeclRef).?.decl.value(),
709 return module.getDeclValue(index);
710 },
711 .elem_ptr => {723 .elem_ptr => {
712 const elem_ptr = self.cast(ElemPtr).?;724 const elem_ptr = self.cast(Payload.ElemPtr).?;
713 const array_val = try elem_ptr.array_ptr.pointerDeref(module);725 const array_val = try elem_ptr.array_ptr.pointerDeref(allocator);
714 return self.elemValue(array_val, elem_ptr.index);726 return array_val.elemValue(allocator, elem_ptr.index);
715 },727 },
716 };728 };
717 }729 }
718730
719 /// Asserts the value is a single-item pointer to an array, or an array,731 /// Asserts the value is a single-item pointer to an array, or an array,
720 /// or an unknown-length pointer, and returns the element value at the index.732 /// or an unknown-length pointer, and returns the element value at the index.
721 pub fn elemValue(self: Value, index: usize) Value {733 pub fn elemValue(self: Value, allocator: *Allocator, index: usize) error{OutOfMemory}!Value {
722 switch (self.tag()) {734 switch (self.tag()) {
723 .ty,735 .ty,
724 .u8_type,736 .u8_type,
...@@ -764,6 +776,7 @@ pub const Value = extern union {...@@ -764,6 +776,7 @@ pub const Value = extern union {
764 .int_big_negative,776 .int_big_negative,
765 .undef,777 .undef,
766 .elem_ptr,778 .elem_ptr,
779 .ref_val,
767 .decl_ref,780 .decl_ref,
768 => unreachable,781 => unreachable,
769782
...@@ -838,6 +851,7 @@ pub const Value = extern union {...@@ -838,6 +851,7 @@ pub const Value = extern union {
838 .int_i64,851 .int_i64,
839 .int_big_positive,852 .int_big_positive,
840 .int_big_negative,853 .int_big_negative,
854 .ref_val,
841 .decl_ref,855 .decl_ref,
842 .elem_ptr,856 .elem_ptr,
843 .bytes,857 .bytes,
...@@ -896,11 +910,16 @@ pub const Value = extern union {...@@ -896,11 +910,16 @@ pub const Value = extern union {
896 elem_type: *Type,910 elem_type: *Type,
897 };911 };
898912
913 /// Represents a pointer to another immutable value.
914 pub const RefVal = struct {
915 base: Payload = Payload{ .tag = .ref_val },
916 val: Value,
917 };
918
899 /// Represents a pointer to a decl, not the value of the decl.919 /// Represents a pointer to a decl, not the value of the decl.
900 pub const DeclRef = struct {920 pub const DeclRef = struct {
901 base: Payload = Payload{ .tag = .decl_ref },921 base: Payload = Payload{ .tag = .decl_ref },
902 /// Index into the Module's decls list922 decl: *ir.Module.Decl,
903 index: usize,
904 };923 };
905924
906 pub const ElemPtr = struct {925 pub const ElemPtr = struct {