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 {
269269
270270/// Bring-your-own allocator with every function call.
271271/// Initialize directly and deinitialize with `deinit` or use `toOwnedSlice`.
272pub fn init() Self {
273 return .{
274 .items = &[_]T{},
275 .capacity = 0,
276 };
277}
278
279272pub fn ArrayListUnmanaged(comptime T: type) type {
280273 return ArrayListAlignedUnmanaged(T, null);
281274}
......@@ -317,7 +310,7 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ
317310 /// The caller owns the returned memory. ArrayList becomes empty.
318311 pub fn toOwnedSlice(self: *Self, allocator: *Allocator) Slice {
319312 const result = allocator.shrink(self.allocatedSlice(), self.items.len);
320 self.* = init(allocator);
313 self.* = Self{};
321314 return result;
322315 }
323316
lib/std/mem.zig+19-9
......@@ -279,6 +279,21 @@ pub const Allocator = struct {
279279 const shrink_result = self.shrinkFn(self, non_const_ptr[0..bytes_len], Slice.alignment, 0, 1);
280280 assert(shrink_result.len == 0);
281281 }
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 }
282297};
283298
284299/// 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 {
762777 return true;
763778}
764779
765/// Copies `m` to newly allocated memory. Caller owns the memory.
780/// Deprecated, use `Allocator.dupe`.
766781pub fn dupe(allocator: *Allocator, comptime T: type, m: []const T) ![]T {
767 const new_buf = try allocator.alloc(T, m.len);
768 copy(T, new_buf, m);
769 return new_buf;
782 return allocator.dupe(T, m);
770783}
771784
772/// Copies `m` to newly allocated memory, with a null-terminated element. Caller owns the memory.
785/// Deprecated, use `Allocator.dupeZ`.
773786pub fn dupeZ(allocator: *Allocator, comptime T: type, m: []const T) ![:0]T {
774 const new_buf = try allocator.alloc(T, m.len + 1);
775 copy(T, new_buf, m);
776 new_buf[m.len] = 0;
777 return new_buf[0..m.len :0];
787 return allocator.dupeZ(T, m);
778788}
779789
780790/// Remove values from the beginning of a slice.
src-self-hosted/TypedValue.zig+1-1
......@@ -16,7 +16,7 @@ pub const Managed = struct {
1616 /// If this is `null` then there is no memory management needed.
1717 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 {
2020 if (self.arena) |a| a.promote(allocator).deinit();
2121 self.* = undefined;
2222 }
src-self-hosted/codegen.zig+2-1
......@@ -4,10 +4,11 @@ const assert = std.debug.assert;
44const ir = @import("ir.zig");
55const Type = @import("type.zig").Type;
66const Value = @import("value.zig").Value;
7const TypedValue = @import("TypedValue.zig");
78const Target = std.Target;
89const 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 {
1112 switch (typed_value.ty.zigTypeTag()) {
1213 .Fn => {
1314 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 {
196196 /// We optimize memory usage for a compilation with no compile errors by storing the
197197 /// error messages and mapping outside of `Decl`.
198198 /// 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.
199201 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),
204202 /// Using a map here for consistency with the other fields here.
205203 /// The ErrorMsg memory is owned by the `Scope.ZIRModule`, using Module's allocator.
206204 failed_files: std.AutoHashMap(*Scope.ZIRModule, *ErrorMsg),
......@@ -221,7 +219,14 @@ pub const Module = struct {
221219 link: link.ElfFile.Export,
222220 /// The Decl that performs the export. Note that this is *not* the Decl being exported.
223221 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 },
225230 };
226231
227232 pub const Decl = struct {
......@@ -260,6 +265,11 @@ pub const Module = struct {
260265 /// In this case the `typed_value.most_recent` can still be accessed.
261266 /// There will be a corresponding ErrorMsg in Module.failed_decls.
262267 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,
263273 /// This Decl might be OK but it depends on another one which did not successfully complete
264274 /// semantic analysis. There is a most recent value available.
265275 repeat_dependency_failure,
......@@ -280,40 +290,63 @@ pub const Module = struct {
280290 /// The shallow set of other decls whose typed_value could possibly change if this Decl's
281291 /// typed_value is modified.
282292 /// TODO look into using a lightweight map/set data structure rather than a linear array.
283 dependants: 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 }
293 dependants: ArrayListUnmanaged(*Decl) = ArrayListUnmanaged(*Decl){},
299294
300295 pub fn destroy(self: *Decl, allocator: *Allocator) void {
301 allocator.free(mem.spanZ(u8, self.name));
302 if (self.typedValue()) |tv| tv.deinit(allocator);
296 allocator.free(mem.spanZ(self.name));
297 if (self.typedValueManaged()) |tvm| {
298 tvm.deinit(allocator);
299 }
303300 allocator.destroy(self);
304301 }
305302
306303 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
308318 /// Must generate unique bytes with no collisions with other decls.
309319 /// The point of hashing here is only to limit the number of bytes of
310320 /// the unique identifier to a fixed size (16 bytes).
311321 pub fn fullyQualifiedNameHash(self: Decl) Hash {
312322 // Right now we only have ZIRModule as the source. So this is simply the
313323 // relative name of the decl.
314 var out: Hash = undefined;
315 std.crypto.Blake3.hash(mem.spanZ(u8, self.name), &out);
316 return out;
324 return hashSimpleName(mem.spanZ(u8, self.name));
325 }
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 }
317350 }
318351 };
319352
......@@ -325,22 +358,19 @@ pub const Module = struct {
325358 /// The value is the source instruction.
326359 queued: *text.Inst.Fn,
327360 in_progress: *Analysis,
328 /// There will be a corresponding ErrorMsg in Module.failed_fns
361 /// There will be a corresponding ErrorMsg in Module.failed_decls
329362 failure,
330363 success: Body,
331364 },
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
336366 /// This memory is temporary and points to stack memory for the duration
337367 /// of Fn analysis.
338368 pub const Analysis = struct {
339369 inner_block: Scope.Block,
340 /// null value means a semantic analysis error happened.
341 inst_table: std.AutoHashMap(*text.Inst, ?*Inst),
342 /// Owns the memory for instructions
343 arena: std.heap.ArenaAllocator,
370 /// TODO Performance optimization idea: instead of this inst_table,
371 /// use a field in the text.Inst instead to track corresponding instructions
372 inst_table: std.AutoHashMap(*text.Inst, *Inst),
373 needed_inst_capacity: usize,
344374 };
345375 };
346376
......@@ -374,6 +404,16 @@ pub const Module = struct {
374404 }
375405 }
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
377417 pub const Tag = enum {
378418 zir_module,
379419 block,
......@@ -407,11 +447,11 @@ pub const Module = struct {
407447 .unloaded_parse_failure,
408448 => {},
409449 .loaded_success => {
410 allocator.free(contents.source);
450 allocator.free(self.source.bytes);
411451 self.contents.module.deinit(allocator);
412452 },
413453 .loaded_parse_failure => {
414 allocator.free(contents.source);
454 allocator.free(self.source.bytes);
415455 },
416456 }
417457 self.* = undefined;
......@@ -469,8 +509,8 @@ pub const Module = struct {
469509 ) !void {
470510 const loc = std.zig.findLineColumn(source, simple_err_msg.byte_offset);
471511 try errors.append(.{
472 .src_path = try mem.dupe(u8, &arena.allocator, sub_file_path),
473 .msg = try mem.dupe(u8, &arena.allocator, simple_err_msg.msg),
512 .src_path = try arena.allocator.dupe(u8, sub_file_path),
513 .msg = try arena.allocator.dupe(u8, simple_err_msg.msg),
474514 .byte_offset = simple_err_msg.byte_offset,
475515 .line = loc.line,
476516 .column = loc.column,
......@@ -480,7 +520,7 @@ pub const Module = struct {
480520
481521 pub fn deinit(self: *Module) void {
482522 const allocator = self.allocator;
483 allocator.free(self.errors);
523 self.work_stack.deinit(allocator);
484524 {
485525 var it = self.decl_table.iterator();
486526 while (it.next()) |kv| {
......@@ -488,8 +528,44 @@ pub const Module = struct {
488528 }
489529 self.decl_table.deinit();
490530 }
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 }
491564 self.root_pkg.destroy();
492 self.root_scope.deinit();
565 {
566 self.root_scope.deinit(allocator);
567 allocator.destroy(self.root_scope);
568 }
493569 self.* = undefined;
494570 }
495571
......@@ -504,19 +580,20 @@ pub const Module = struct {
504580 // Analyze the root source file now.
505581 self.analyzeRoot(self.root_scope) catch |err| switch (err) {
506582 error.AnalysisFail => {
507 assert(self.failed_files.size != 0);
583 assert(self.totalErrorCount() != 0);
508584 },
509585 else => |e| return e,
510586 };
511587
588 try self.performAllTheWork();
589
512590 try self.bin_file.flush();
513591 self.link_error_flags = self.bin_file.error_flags;
514592 }
515593
516594 pub fn totalErrorCount(self: *Module) usize {
517595 return self.failed_decls.size +
518 self.failed_fns.size +
519 self.failed_decls.size +
596 self.failed_files.size +
520597 self.failed_exports.size +
521598 @boolToInt(self.link_error_flags.no_entry_point_found);
522599 }
......@@ -533,17 +610,8 @@ pub const Module = struct {
533610 while (it.next()) |kv| {
534611 const scope = kv.key;
535612 const err_msg = kv.value;
536 const source = scope.parse_failure.source;
537 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);
613 const source = scope.source.bytes;
614 try AllErrors.add(&arena, &errors, scope.sub_file_path, source, err_msg.*);
547615 }
548616 }
549617 {
......@@ -551,8 +619,8 @@ pub const Module = struct {
551619 while (it.next()) |kv| {
552620 const decl = kv.key;
553621 const err_msg = kv.value;
554 const source = decl.scope.success.source;
555 AllErrors.add(&arena, &errors, decl.scope.sub_file_path, source, err_msg);
622 const source = decl.scope.source.bytes;
623 try AllErrors.add(&arena, &errors, decl.scope.sub_file_path, source, err_msg.*);
556624 }
557625 }
558626 {
......@@ -560,14 +628,14 @@ pub const Module = struct {
560628 while (it.next()) |kv| {
561629 const decl = kv.key.owner_decl;
562630 const err_msg = kv.value;
563 const source = decl.scope.success.source;
564 try AllErrors.add(&arena, &errors, decl.scope.sub_file_path, source, err_msg);
631 const source = decl.scope.source.bytes;
632 try AllErrors.add(&arena, &errors, decl.scope.sub_file_path, source, err_msg.*);
565633 }
566634 }
567635
568636 if (self.link_error_flags.no_entry_point_found) {
569637 try errors.append(.{
570 .src_path = self.module.root_src_path,
638 .src_path = self.root_pkg.root_src_path,
571639 .line = 0,
572640 .column = 0,
573641 .byte_offset = 0,
......@@ -579,12 +647,56 @@ pub const Module = struct {
579647
580648 return AllErrors{
581649 .arena = arena.state,
582 .list = try mem.dupe(&arena.allocator, AllErrors.Message, errors.items),
650 .list = try arena.allocator.dupe(AllErrors.Message, errors.items),
583651 };
584652 }
585653
586654 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
588700 fn analyzeRoot(self: *Module, root_scope: *Scope.ZIRModule) !void {
589701 // TODO use the cache to identify, from the modified source files, the decls which have
590702 // 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 {
650762 try analyzeExport(self, &root_scope.base, export_inst);
651763 }
652764 }
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 };
675765 }
676766
677767 fn analyzeFnBody(self: *Module, decl: *Decl, func: *Fn) !void {
678768 // Use the Decl's arena for function memory.
679769 var arena = decl.typed_value.most_recent.arena.?.promote(self.allocator);
680770 defer decl.typed_value.most_recent.arena.?.* = arena.state;
681 var analysis: Analysis = .{
771 var analysis: Fn.Analysis = .{
682772 .inner_block = .{
683773 .func = func,
684774 .decl = decl,
685775 .instructions = .{},
686776 .arena = &arena.allocator,
687777 },
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),
689780 };
690 defer analysis.inner_block.instructions.deinit();
781 defer analysis.inner_block.instructions.deinit(self.allocator);
691782 defer analysis.inst_table.deinit();
692783
693784 const fn_inst = func.analysis.queued;
694785 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 };
699794 }
700795
701796 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);
703798 if (self.decl_table.get(hash)) |kv| {
704799 return kv.value;
705800 } else {
......@@ -711,7 +806,7 @@ pub const Module = struct {
711806 errdefer self.allocator.free(name);
712807 new_decl.* = .{
713808 .name = name,
714 .scope = scope.findZIRModule(),
809 .scope = scope.namespace(),
715810 .src = old_inst.src,
716811 .typed_value = .{ .never_succeeded = {} },
717812 .analysis = .initial_in_progress,
......@@ -726,12 +821,11 @@ pub const Module = struct {
726821 };
727822 errdefer decl_scope.arena.deinit();
728823
729 const arena_state = try self.allocator.create(std.heap.ArenaAllocator.State);
730 errdefer self.allocator.destroy(arena_state);
824 const arena_state = try decl_scope.arena.allocator.create(std.heap.ArenaAllocator.State);
731825
732826 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
736830 new_decl.typed_value = .{
737831 .most_recent = .{
......@@ -741,7 +835,7 @@ pub const Module = struct {
741835 };
742836 new_decl.analysis = .complete;
743837 // 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 });
745839 return new_decl;
746840 }
747841 }
......@@ -756,6 +850,7 @@ pub const Module = struct {
756850 .initial_sema_failure,
757851 .repeat_sema_failure,
758852 .codegen_failure,
853 .codegen_failure_retryable,
759854 => return error.AnalysisFail,
760855
761856 .complete => return decl,
......@@ -764,14 +859,14 @@ pub const Module = struct {
764859
765860 fn resolveInst(self: *Module, scope: *Scope, old_inst: *text.Inst) InnerError!*Inst {
766861 if (scope.cast(Scope.Block)) |block| {
767 if (block.func.inst_table.get(old_inst)) |kv| {
768 return kv.value.ptr orelse return error.AnalysisFail;
862 if (block.func.analysis.in_progress.inst_table.get(old_inst)) |kv| {
863 return kv.value;
769864 }
770865 }
771866
772867 const decl = try self.resolveCompleteDecl(scope, old_inst);
773868 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);
775870 }
776871
777872 fn requireRuntimeBlock(self: *Module, scope: *Scope, src: usize) !*Scope.Block {
......@@ -819,7 +914,7 @@ pub const Module = struct {
819914 return val.toType();
820915 }
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 {
823918 try self.decl_exports.ensureCapacity(self.decl_exports.size + 1);
824919 try self.export_owners.ensureCapacity(self.export_owners.size + 1);
825920 const symbol_name = try self.resolveConstString(scope, export_inst.positionals.symbol_name);
......@@ -840,7 +935,7 @@ pub const Module = struct {
840935 const owner_decl = scope.decl();
841936
842937 new_export.* = .{
843 .options = .{ .data = .{ .name = symbol_name } },
938 .options = .{ .name = symbol_name },
844939 .src = export_inst.base.src,
845940 .link = .{},
846941 .owner_decl = owner_decl,
......@@ -865,7 +960,19 @@ pub const Module = struct {
865960 de_gop.kv.value[de_gop.kv.value.len - 1] = new_export;
866961 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 };
869976 }
870977
871978 /// TODO should not need the cast on the last parameter at the callsites
......@@ -976,7 +1083,7 @@ pub const Module = struct {
9761083 fn constIntBig(self: *Module, scope: *Scope, src: usize, ty: Type, big_int: BigIntConst) !*Inst {
9771084 const val_payload = if (big_int.positive) blk: {
9781085 if (big_int.to(u64)) |x| {
979 return self.constIntUnsigned(src, ty, x);
1086 return self.constIntUnsigned(scope, src, ty, x);
9801087 } else |err| switch (err) {
9811088 error.NegativeIntoUnsigned => unreachable,
9821089 error.TargetTooSmall => {}, // handled below
......@@ -986,7 +1093,7 @@ pub const Module = struct {
9861093 break :blk &big_int_payload.base;
9871094 } else blk: {
9881095 if (big_int.to(i64)) |x| {
989 return self.constIntSigned(src, ty, x);
1096 return self.constIntSigned(scope, src, ty, x);
9901097 } else |err| switch (err) {
9911098 error.NegativeIntoUnsigned => unreachable,
9921099 error.TargetTooSmall => {}, // handled below
......@@ -1014,15 +1121,17 @@ pub const Module = struct {
10141121 switch (old_inst.tag) {
10151122 .breakpoint => return self.analyzeInstBreakpoint(scope, old_inst.cast(text.Inst.Breakpoint).?),
10161123 .call => return self.analyzeInstCall(scope, old_inst.cast(text.Inst.Call).?),
1124 .declref => return self.analyzeInstDeclRef(scope, old_inst.cast(text.Inst.DeclRef).?),
10171125 .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.
10201126 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);
10221131 },
10231132 .int => {
10241133 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);
10261135 },
10271136 .ptrtoint => return self.analyzeInstPtrToInt(scope, old_inst.cast(text.Inst.PtrToInt).?),
10281137 .fieldptr => return self.analyzeInstFieldPtr(scope, old_inst.cast(text.Inst.FieldPtr).?),
......@@ -1036,7 +1145,7 @@ pub const Module = struct {
10361145 try self.analyzeExport(scope, old_inst.cast(text.Inst.Export).?);
10371146 return self.constVoid(scope, old_inst.src);
10381147 },
1039 .primitive => return self.analyzeInstPrimitive(old_inst.cast(text.Inst.Primitive).?),
1148 .primitive => return self.analyzeInstPrimitive(scope, old_inst.cast(text.Inst.Primitive).?),
10401149 .fntype => return self.analyzeInstFnType(scope, old_inst.cast(text.Inst.FnType).?),
10411150 .intcast => return self.analyzeInstIntCast(scope, old_inst.cast(text.Inst.IntCast).?),
10421151 .bitcast => return self.analyzeInstBitCast(scope, old_inst.cast(text.Inst.BitCast).?),
......@@ -1054,6 +1163,14 @@ pub const Module = struct {
10541163 return self.addNewInstArgs(b, inst.base.src, Type.initTag(.void), Inst.Breakpoint, Inst.Args(Inst.Breakpoint){});
10551164 }
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
10571174 fn analyzeInstCall(self: *Module, scope: *Scope, inst: *text.Inst.Call) InnerError!*Inst {
10581175 const func = try self.resolveInst(scope, inst.positionals.func);
10591176 if (func.ty.zigTypeTag() != .Fn)
......@@ -1123,8 +1240,7 @@ pub const Module = struct {
11231240 const new_func = try scope.arena().create(Fn);
11241241 new_func.* = .{
11251242 .fn_type = fn_type,
1126 .analysis = .{ .queued = fn_inst.positionals.body },
1127 .scope = scope.namespace(),
1243 .analysis = .{ .queued = fn_inst },
11281244 };
11291245 const fn_payload = try scope.arena().create(Value.Payload.Function);
11301246 fn_payload.* = .{ .func = new_func };
......@@ -1141,28 +1257,28 @@ pub const Module = struct {
11411257 fntype.positionals.param_types.len == 0 and
11421258 fntype.kw_args.cc == .Unspecified)
11431259 {
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));
11451261 }
11461262
11471263 if (return_type.zigTypeTag() == .NoReturn and
11481264 fntype.positionals.param_types.len == 0 and
11491265 fntype.kw_args.cc == .Naked)
11501266 {
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));
11521268 }
11531269
11541270 if (return_type.zigTypeTag() == .Void and
11551271 fntype.positionals.param_types.len == 0 and
11561272 fntype.kw_args.cc == .C)
11571273 {
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));
11591275 }
11601276
11611277 return self.fail(scope, fntype.base.src, "TODO implement fntype instruction more", .{});
11621278 }
11631279
1164 fn analyzeInstPrimitive(self: *Module, primitive: *text.Inst.Primitive) InnerError!*Inst {
1165 return self.constType(primitive.base.src, primitive.positionals.tag.toType());
1280 fn analyzeInstPrimitive(self: *Module, scope: *Scope, primitive: *text.Inst.Primitive) InnerError!*Inst {
1281 return self.constType(scope, primitive.base.src, primitive.positionals.tag.toType());
11661282 }
11671283
11681284 fn analyzeInstAs(self: *Module, scope: *Scope, as: *text.Inst.As) InnerError!*Inst {
......@@ -1332,18 +1448,22 @@ pub const Module = struct {
13321448
13331449 fn analyzeInstDeref(self: *Module, scope: *Scope, deref: *text.Inst.Deref) InnerError!*Inst {
13341450 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 {
13351455 const elem_ty = switch (ptr.ty.zigTypeTag()) {
13361456 .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}),
13381458 };
13391459 if (ptr.value()) |val| {
1340 return self.constInst(scope, deref.base.src, .{
1460 return self.constInst(scope, src, .{
13411461 .ty = elem_ty,
1342 .val = val.pointerDeref(),
1462 .val = try val.pointerDeref(scope.arena()),
13431463 });
13441464 }
13451465
1346 return self.fail(scope, deref.base.src, "TODO implement runtime deref", .{});
1466 return self.fail(scope, src, "TODO implement runtime deref", .{});
13471467 }
13481468
13491469 fn analyzeInstAsm(self: *Module, scope: *Scope, assembly: *text.Inst.Asm) InnerError!*Inst {
......@@ -1390,7 +1510,7 @@ pub const Module = struct {
13901510 const rhs_ty_tag = rhs.ty.zigTypeTag();
13911511 if (is_equality_cmp and lhs_ty_tag == .Null and rhs_ty_tag == .Null) {
13921512 // null == null, null != null
1393 return self.constBool(inst.base.src, op == .eq);
1513 return self.constBool(scope, inst.base.src, op == .eq);
13941514 } else if (is_equality_cmp and
13951515 ((lhs_ty_tag == .Null and rhs_ty_tag == .Optional) or
13961516 rhs_ty_tag == .Null and lhs_ty_tag == .Optional))
......@@ -1399,7 +1519,7 @@ pub const Module = struct {
13991519 const opt_operand = if (lhs_ty_tag == .Optional) lhs else rhs;
14001520 if (opt_operand.value()) |opt_val| {
14011521 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);
14031523 }
14041524 const b = try self.requireRuntimeBlock(scope, inst.base.src);
14051525 switch (op) {
......@@ -1468,32 +1588,27 @@ pub const Module = struct {
14681588 const parent_block = try self.requireRuntimeBlock(scope, inst.base.src);
14691589
14701590 var true_block: Scope.Block = .{
1471 .base = .{ .parent = scope },
14721591 .func = parent_block.func,
1592 .decl = parent_block.decl,
14731593 .instructions = .{},
1594 .arena = parent_block.arena,
14741595 };
1475 defer true_block.instructions.deinit();
1596 defer true_block.instructions.deinit(self.allocator);
14761597 try self.analyzeBody(&true_block.base, inst.positionals.true_body);
14771598
14781599 var false_block: Scope.Block = .{
1479 .base = .{ .parent = scope },
14801600 .func = parent_block.func,
1601 .decl = parent_block.decl,
14811602 .instructions = .{},
1603 .arena = parent_block.arena,
14821604 };
1483 defer false_block.instructions.deinit();
1605 defer false_block.instructions.deinit(self.allocator);
14841606 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
14931608 return self.addNewInstArgs(parent_block, inst.base.src, Type.initTag(.void), Inst.CondBr, Inst.Args(Inst.CondBr){
14941609 .condition = cond,
1495 .true_body = .{ .instructions = true_instructions },
1496 .false_body = .{ .instructions = false_instructions },
1610 .true_body = .{ .instructions = try scope.arena().dupe(*Inst, true_block.instructions.items) },
1611 .false_body = .{ .instructions = try scope.arena().dupe(*Inst, false_block.instructions.items) },
14971612 });
14981613 }
14991614
......@@ -1521,15 +1636,18 @@ pub const Module = struct {
15211636 }
15221637
15231638 fn analyzeBody(self: *Module, scope: *Scope, body: text.Module.Body) !void {
1524 for (body.instructions) |src_inst| {
1525 const new_inst = self.analyzeInst(scope, src_inst) catch |err| {
1526 if (scope.cast(Scope.Block)) |b| {
1527 self.fns.items[b.func.fn_index].analysis_status = .failure;
1528 try b.func.inst_table.putNoClobber(src_inst, .{ .ptr = null });
1529 }
1530 return err;
1531 };
1532 if (scope.cast(Scope.Block)) |b| try b.func.inst_table.putNoClobber(src_inst, .{ .ptr = new_inst });
1639 if (scope.cast(Scope.Block)) |b| {
1640 const analysis = b.func.analysis.in_progress;
1641 analysis.needed_inst_capacity += body.instructions.len;
1642 try analysis.inst_table.ensureCapacity(analysis.needed_inst_capacity);
1643 for (body.instructions) |src_inst| {
1644 const new_inst = try self.analyzeInst(scope, src_inst);
1645 analysis.inst_table.putAssumeCapacityNoClobber(src_inst, new_inst);
1646 }
1647 } else {
1648 for (body.instructions) |src_inst| {
1649 _ = try self.analyzeInst(scope, src_inst);
1650 }
15331651 }
15341652 }
15351653
......@@ -1575,7 +1693,7 @@ pub const Module = struct {
15751693
15761694 if (lhs.value()) |lhs_val| {
15771695 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));
15791697 }
15801698 }
15811699
......@@ -1647,8 +1765,8 @@ pub const Module = struct {
16471765 const zcmp = lhs_val.orderAgainstZero();
16481766 if (lhs_val.floatHasFraction()) {
16491767 switch (op) {
1650 .eq => return self.constBool(src, false),
1651 .neq => return self.constBool(src, true),
1768 .eq => return self.constBool(scope, src, false),
1769 .neq => return self.constBool(scope, src, true),
16521770 else => {},
16531771 }
16541772 if (zcmp == .lt) {
......@@ -1682,8 +1800,8 @@ pub const Module = struct {
16821800 const zcmp = rhs_val.orderAgainstZero();
16831801 if (rhs_val.floatHasFraction()) {
16841802 switch (op) {
1685 .eq => return self.constBool(src, false),
1686 .neq => return self.constBool(src, true),
1803 .eq => return self.constBool(scope, src, false),
1804 .neq => return self.constBool(scope, src, true),
16871805 else => {},
16881806 }
16891807 if (zcmp == .lt) {
......@@ -1711,7 +1829,7 @@ pub const Module = struct {
17111829 const casted_bits = std.math.cast(u16, max_bits) catch |err| switch (err) {
17121830 error.Overflow => return self.fail(scope, src, "{} exceeds maximum integer bit count", .{max_bits}),
17131831 };
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);
17151833 };
17161834 const casted_lhs = try self.coerce(scope, dest_type, lhs);
17171835 const casted_rhs = try self.coerce(scope, dest_type, lhs);
......@@ -1807,7 +1925,6 @@ pub const Module = struct {
18071925 fn fail(self: *Module, scope: *Scope, src: usize, comptime format: []const u8, args: var) InnerError {
18081926 @setCold(true);
18091927 try self.failed_decls.ensureCapacity(self.failed_decls.size + 1);
1810 try self.failed_fns.ensureCapacity(self.failed_fns.size + 1);
18111928 const err_msg = try ErrorMsg.create(self.allocator, src, format, args);
18121929 switch (scope.tag) {
18131930 .decl => {
......@@ -1820,10 +1937,11 @@ pub const Module = struct {
18201937 self.failed_decls.putAssumeCapacityNoClobber(decl, err_msg);
18211938 },
18221939 .block => {
1823 const func = scope.cast(Scope.Block).?.func;
1824 func.analysis = .failure;
1825 self.failed_fns.putAssumeCapacityNoClobber(func, err_msg);
1940 const block = scope.cast(Scope.Block).?;
1941 block.func.analysis = .failure;
1942 self.failed_decls.putAssumeCapacityNoClobber(block.decl, err_msg);
18261943 },
1944 .zir_module => unreachable,
18271945 }
18281946 return error.AnalysisFail;
18291947 }
......@@ -1868,7 +1986,7 @@ pub const ErrorMsg = struct {
18681986 }
18691987
18701988 pub fn deinit(self: *ErrorMsg, allocator: *Allocator) void {
1871 allocator.free(err_msg.msg);
1989 allocator.free(self.msg);
18721990 self.* = undefined;
18731991 }
18741992};
......@@ -1920,7 +2038,6 @@ pub fn main() anyerror!void {
19202038 .decl_exports = std.AutoHashMap(*Module.Decl, []*Module.Export).init(allocator),
19212039 .export_owners = std.AutoHashMap(*Module.Decl, []*Module.Export).init(allocator),
19222040 .failed_decls = std.AutoHashMap(*Module.Decl, *ErrorMsg).init(allocator),
1923 .failed_fns = std.AutoHashMap(*Module.Fn, *ErrorMsg).init(allocator),
19242041 .failed_files = std.AutoHashMap(*Module.Scope.ZIRModule, *ErrorMsg).init(allocator),
19252042 .failed_exports = std.AutoHashMap(*Module.Export, *ErrorMsg).init(allocator),
19262043 };
......@@ -1929,8 +2046,8 @@ pub fn main() anyerror!void {
19292046
19302047 try module.update();
19312048
1932 const errors = try module.getAllErrorsAlloc();
1933 defer errors.deinit();
2049 var errors = try module.getAllErrorsAlloc();
2050 defer errors.deinit(allocator);
19342051
19352052 if (errors.list.len != 0) {
19362053 for (errors.list) |full_err_msg| {
......@@ -1954,6 +2071,3 @@ pub fn main() anyerror!void {
19542071 try bos.flush();
19552072 }
19562073}
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;
88const BigIntMutable = std.math.big.int.Mutable;
99const Type = @import("../type.zig").Type;
1010const Value = @import("../value.zig").Value;
11const TypedValue = @import("../TypedValue.zig");
1112const ir = @import("../ir.zig");
1213
1314/// These are instructions that correspond to the ZIR text format. See `ir.Inst` for
......@@ -462,6 +463,7 @@ pub const Module = struct {
462463 switch (decl.tag) {
463464 .breakpoint => return self.writeInstToStreamGeneric(stream, .breakpoint, decl, inst_table),
464465 .call => return self.writeInstToStreamGeneric(stream, .call, decl, inst_table),
466 .declref => return self.writeInstToStreamGeneric(stream, .declref, decl, inst_table),
465467 .str => return self.writeInstToStreamGeneric(stream, .str, decl, inst_table),
466468 .int => return self.writeInstToStreamGeneric(stream, .int, decl, inst_table),
467469 .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
576578 .source = source,
577579 .global_name_map = &global_name_map,
578580 .decls = .{},
581 .unnamed_index = 0,
579582 };
580583 errdefer parser.arena.deinit();
581584
......@@ -601,6 +604,7 @@ const Parser = struct {
601604 decls: std.ArrayListUnmanaged(*Inst),
602605 global_name_map: *std.StringHashMap(usize),
603606 error_msg: ?ErrorMsg = null,
607 unnamed_index: usize,
604608
605609 const Body = struct {
606610 instructions: std.ArrayList(*Inst),
......@@ -626,12 +630,12 @@ const Parser = struct {
626630 skipSpace(self);
627631 try requireEatBytes(self, "=");
628632 skipSpace(self);
629 const inst = try parseInstruction(self, &body_context);
633 const inst = try parseInstruction(self, &body_context, ident[1..]);
630634 const ident_index = body_context.instructions.items.len;
631635 if (try body_context.name_map.put(ident, ident_index)) |_| {
632636 return self.fail("redefinition of identifier '{}'", .{ident});
633637 }
634 try body_context.instructions.append(self.allocator, inst);
638 try body_context.instructions.append(inst);
635639 continue;
636640 },
637641 ' ', '\n' => continue,
......@@ -712,7 +716,7 @@ const Parser = struct {
712716 skipSpace(self);
713717 try requireEatBytes(self, "=");
714718 skipSpace(self);
715 const inst = try parseInstruction(self, null);
719 const inst = try parseInstruction(self, null, ident[1..]);
716720 const ident_index = self.decls.items.len;
717721 if (try self.global_name_map.put(ident, ident_index)) |_| {
718722 return self.fail("redefinition of identifier '{}'", .{ident});
......@@ -781,12 +785,12 @@ const Parser = struct {
781785 return error.ParseFailure;
782786 }
783787
784 fn parseInstruction(self: *Parser, body_ctx: ?*Body) InnerError!*Inst {
788 fn parseInstruction(self: *Parser, body_ctx: ?*Body, name: []const u8) InnerError!*Inst {
785789 const fn_name = try skipToAndOver(self, '(');
786790 inline for (@typeInfo(Inst.Tag).Enum.fields) |field| {
787791 if (mem.eql(u8, field.name, fn_name)) {
788792 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);
790794 }
791795 }
792796 return self.fail("unknown instruction '{}'", .{fn_name});
......@@ -797,9 +801,11 @@ const Parser = struct {
797801 comptime fn_name: []const u8,
798802 comptime InstType: type,
799803 body_ctx: ?*Body,
800 ) !*Inst {
804 inst_name: []const u8,
805 ) InnerError!*Inst {
801806 const inst_specific = try self.arena.allocator.create(InstType);
802807 inst_specific.base = .{
808 .name = inst_name,
803809 .src = self.i,
804810 .tag = InstType.base_tag,
805811 };
......@@ -885,7 +891,7 @@ const Parser = struct {
885891 var instructions = std.ArrayList(*Inst).init(&self.arena.allocator);
886892 while (true) {
887893 skipSpace(self);
888 try instructions.append(self.allocator, try parseParameterInst(self, body_ctx));
894 try instructions.append(try parseParameterInst(self, body_ctx));
889895 skipSpace(self);
890896 if (!eatByte(self, ',')) break;
891897 }
......@@ -930,13 +936,21 @@ const Parser = struct {
930936 } else {
931937 const name = try self.arena.allocator.create(Inst.Str);
932938 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 },
934944 .positionals = .{ .bytes = ident },
935945 .kw_args = .{},
936946 };
937947 const declref = try self.arena.allocator.create(Inst.DeclRef);
938948 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 },
940954 .positionals = .{ .name = &name.base },
941955 .kw_args = .{},
942956 };
......@@ -949,25 +963,31 @@ const Parser = struct {
949963 return self.decls.items[kv.value];
950964 }
951965 }
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 }
952972};
953973
954974pub fn emit_zir(allocator: *Allocator, old_module: ir.Module) !Module {
955975 var ctx: EmitZIR = .{
956976 .allocator = allocator,
957 .decls = std.ArrayList(*Inst).init(allocator),
977 .decls = .{},
958978 .decl_table = std.AutoHashMap(*ir.Inst, *Inst).init(allocator),
959979 .arena = std.heap.ArenaAllocator.init(allocator),
960980 .old_module = &old_module,
961981 };
962 defer ctx.decls.deinit();
982 defer ctx.decls.deinit(allocator);
963983 defer ctx.decl_table.deinit();
964984 errdefer ctx.arena.deinit();
965985
966986 try ctx.emit();
967987
968988 return Module{
969 .decls = ctx.decls.toOwnedSlice(),
970 .arena = ctx.arena,
989 .decls = ctx.decls.toOwnedSlice(allocator),
990 .arena = ctx.arena.state,
971991 };
972992}
973993
......@@ -975,23 +995,32 @@ const EmitZIR = struct {
975995 allocator: *Allocator,
976996 arena: std.heap.ArenaAllocator,
977997 old_module: *const ir.Module,
978 decls: std.ArrayList(*Inst),
998 decls: std.ArrayListUnmanaged(*Inst),
979999 decl_table: std.AutoHashMap(*ir.Inst, *Inst),
9801000
9811001 fn emit(self: *EmitZIR) !void {
982 for (self.old_module.exports) |module_export| {
983 const export_value = try self.emitTypedValue(module_export.src, module_export.typed_value);
984 const symbol_name = try self.emitStringLiteral(module_export.src, module_export.name);
985 const export_inst = try self.arena.allocator.create(Inst.Export);
986 export_inst.* = .{
987 .base = .{ .src = module_export.src, .tag = Inst.Export.base_tag },
988 .positionals = .{
989 .symbol_name = symbol_name,
990 .value = export_value,
991 },
992 .kw_args = .{},
993 };
994 try self.decls.append(self.allocator, &export_inst.base);
1002 var it = self.old_module.decl_exports.iterator();
1003 while (it.next()) |kv| {
1004 const decl = kv.key;
1005 const exports = kv.value;
1006 const export_value = try self.emitTypedValue(decl.src, decl.typed_value.most_recent.typed_value);
1007 for (exports) |module_export| {
1008 const symbol_name = try self.emitStringLiteral(module_export.src, module_export.options.name);
1009 const export_inst = try self.arena.allocator.create(Inst.Export);
1010 export_inst.* = .{
1011 .base = .{
1012 .name = try self.autoName(),
1013 .src = module_export.src,
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 }
9951024 }
9961025 }
9971026
......@@ -1012,7 +1041,11 @@ const EmitZIR = struct {
10121041 const big_int_space = try self.arena.allocator.create(Value.BigIntSpace);
10131042 const int_inst = try self.arena.allocator.create(Inst.Int);
10141043 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 },
10161049 .positionals = .{
10171050 .int = val.toBigInt(big_int_space),
10181051 },
......@@ -1022,7 +1055,7 @@ const EmitZIR = struct {
10221055 return &int_inst.base;
10231056 }
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 {
10261059 switch (typed_value.ty.zigTypeTag()) {
10271060 .Pointer => {
10281061 const ptr_elem_type = typed_value.ty.elemType();
......@@ -1044,7 +1077,11 @@ const EmitZIR = struct {
10441077 .Int => {
10451078 const as_inst = try self.arena.allocator.create(Inst.As);
10461079 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 },
10481085 .positionals = .{
10491086 .dest_type = try self.emitType(src, typed_value.ty),
10501087 .value = try self.emitComptimeIntVal(src, typed_value.val),
......@@ -1060,8 +1097,7 @@ const EmitZIR = struct {
10601097 return self.emitType(src, ty);
10611098 },
10621099 .Fn => {
1063 const index = typed_value.val.cast(Value.Payload.Function).?.index;
1064 const module_fn = self.old_module.fns[index];
1100 const module_fn = typed_value.val.cast(Value.Payload.Function).?.func;
10651101
10661102 var inst_table = std.AutoHashMap(*ir.Inst, *Inst).init(self.allocator);
10671103 defer inst_table.deinit();
......@@ -1069,7 +1105,7 @@ const EmitZIR = struct {
10691105 var instructions = std.ArrayList(*Inst).init(self.allocator);
10701106 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
10741110 const fn_type = try self.emitType(src, module_fn.fn_type);
10751111
......@@ -1078,7 +1114,11 @@ const EmitZIR = struct {
10781114
10791115 const fn_inst = try self.arena.allocator.create(Inst.Fn);
10801116 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 },
10821122 .positionals = .{
10831123 .fn_type = fn_type,
10841124 .body = .{ .instructions = arena_instrs },
......@@ -1095,7 +1135,11 @@ const EmitZIR = struct {
10951135 fn emitTrivial(self: *EmitZIR, src: usize, comptime T: type) Allocator.Error!*Inst {
10961136 const new_inst = try self.arena.allocator.create(T);
10971137 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 },
10991143 .positionals = .{},
11001144 .kw_args = .{},
11011145 };
......@@ -1120,7 +1164,11 @@ const EmitZIR = struct {
11201164 elem.* = try self.resolveInst(inst_table, old_inst.args.args[i]);
11211165 }
11221166 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 },
11241172 .positionals = .{
11251173 .func = try self.resolveInst(inst_table, old_inst.args.func),
11261174 .args = args,
......@@ -1152,7 +1200,11 @@ const EmitZIR = struct {
11521200 }
11531201
11541202 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 },
11561208 .positionals = .{
11571209 .asm_source = try self.emitStringLiteral(inst.src, old_inst.args.asm_source),
11581210 .return_type = try self.emitType(inst.src, inst.ty),
......@@ -1174,7 +1226,11 @@ const EmitZIR = struct {
11741226 const old_inst = inst.cast(ir.Inst.PtrToInt).?;
11751227 const new_inst = try self.arena.allocator.create(Inst.PtrToInt);
11761228 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 },
11781234 .positionals = .{
11791235 .ptr = try self.resolveInst(inst_table, old_inst.args.ptr),
11801236 },
......@@ -1186,7 +1242,11 @@ const EmitZIR = struct {
11861242 const old_inst = inst.cast(ir.Inst.BitCast).?;
11871243 const new_inst = try self.arena.allocator.create(Inst.BitCast);
11881244 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 },
11901250 .positionals = .{
11911251 .dest_type = try self.emitType(inst.src, inst.ty),
11921252 .operand = try self.resolveInst(inst_table, old_inst.args.operand),
......@@ -1199,7 +1259,11 @@ const EmitZIR = struct {
11991259 const old_inst = inst.cast(ir.Inst.Cmp).?;
12001260 const new_inst = try self.arena.allocator.create(Inst.Cmp);
12011261 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 },
12031267 .positionals = .{
12041268 .lhs = try self.resolveInst(inst_table, old_inst.args.lhs),
12051269 .rhs = try self.resolveInst(inst_table, old_inst.args.rhs),
......@@ -1223,7 +1287,11 @@ const EmitZIR = struct {
12231287
12241288 const new_inst = try self.arena.allocator.create(Inst.CondBr);
12251289 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 },
12271295 .positionals = .{
12281296 .condition = try self.resolveInst(inst_table, old_inst.args.condition),
12291297 .true_body = .{ .instructions = true_body.toOwnedSlice() },
......@@ -1237,7 +1305,11 @@ const EmitZIR = struct {
12371305 const old_inst = inst.cast(ir.Inst.IsNull).?;
12381306 const new_inst = try self.arena.allocator.create(Inst.IsNull);
12391307 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 },
12411313 .positionals = .{
12421314 .operand = try self.resolveInst(inst_table, old_inst.args.operand),
12431315 },
......@@ -1249,7 +1321,11 @@ const EmitZIR = struct {
12491321 const old_inst = inst.cast(ir.Inst.IsNonNull).?;
12501322 const new_inst = try self.arena.allocator.create(Inst.IsNonNull);
12511323 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 },
12531329 .positionals = .{
12541330 .operand = try self.resolveInst(inst_table, old_inst.args.operand),
12551331 },
......@@ -1258,7 +1334,7 @@ const EmitZIR = struct {
12581334 break :blk &new_inst.base;
12591335 },
12601336 };
1261 try instructions.append(self.allocator, new_inst);
1337 try instructions.append(new_inst);
12621338 try inst_table.putNoClobber(inst, new_inst);
12631339 }
12641340 }
......@@ -1301,7 +1377,11 @@ const EmitZIR = struct {
13011377
13021378 const fntype_inst = try self.arena.allocator.create(Inst.FnType);
13031379 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 },
13051385 .positionals = .{
13061386 .param_types = emitted_params,
13071387 .return_type = try self.emitType(src, ty.fnReturnType()),
......@@ -1318,10 +1398,18 @@ const EmitZIR = struct {
13181398 }
13191399 }
13201400
1401 fn autoName(self: *EmitZIR) ![]u8 {
1402 return std.fmt.allocPrint(&self.arena.allocator, "{}", .{self.decls.items.len});
1403 }
1404
13211405 fn emitPrimitiveType(self: *EmitZIR, src: usize, tag: Inst.Primitive.BuiltinType) !*Inst {
13221406 const primitive_inst = try self.arena.allocator.create(Inst.Primitive);
13231407 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 },
13251413 .positionals = .{
13261414 .tag = tag,
13271415 },
......@@ -1334,7 +1422,11 @@ const EmitZIR = struct {
13341422 fn emitStringLiteral(self: *EmitZIR, src: usize, str: []const u8) !*Inst {
13351423 const str_inst = try self.arena.allocator.create(Inst.Str);
13361424 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 },
13381430 .positionals = .{
13391431 .bytes = str,
13401432 },
src-self-hosted/link.zig+61-29
......@@ -153,7 +153,7 @@ pub const ElfFile = struct {
153153 };
154154
155155 pub const Export = struct {
156 sym_index: usize,
156 sym_index: ?usize = null,
157157 };
158158
159159 pub fn deinit(self: *ElfFile) void {
......@@ -249,6 +249,11 @@ pub const ElfFile = struct {
249249 return @intCast(u32, result);
250250 }
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
252257 fn updateString(self: *ElfFile, old_str_off: u32, new_name: []const u8) !u32 {
253258 const existing_name = self.getString(old_str_off);
254259 if (mem.eql(u8, existing_name, new_name)) {
......@@ -418,6 +423,14 @@ pub const ElfFile = struct {
418423 const foreign_endian = self.options.target.cpu.arch.endian() != std.Target.current.cpu.arch.endian();
419424
420425 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 };
421434 const allocated_size = self.allocatedSize(self.phdr_table_offset.?);
422435 const needed_size = self.program_headers.items.len * phsize;
423436
......@@ -426,11 +439,10 @@ pub const ElfFile = struct {
426439 self.phdr_table_offset = self.findFreeSpace(needed_size, phalign);
427440 }
428441
429 const allocator = self.program_headers.allocator;
430442 switch (self.ptr_width) {
431443 .p32 => {
432 const buf = try allocator.alloc(elf.Elf32_Phdr, self.program_headers.items.len);
433 defer allocator.free(buf);
444 const buf = try self.allocator.alloc(elf.Elf32_Phdr, self.program_headers.items.len);
445 defer self.allocator.free(buf);
434446
435447 for (buf) |*phdr, i| {
436448 phdr.* = progHeaderTo32(self.program_headers.items[i]);
......@@ -441,8 +453,8 @@ pub const ElfFile = struct {
441453 try self.file.pwriteAll(mem.sliceAsBytes(buf), self.phdr_table_offset.?);
442454 },
443455 .p64 => {
444 const buf = try allocator.alloc(elf.Elf64_Phdr, self.program_headers.items.len);
445 defer allocator.free(buf);
456 const buf = try self.allocator.alloc(elf.Elf64_Phdr, self.program_headers.items.len);
457 defer self.allocator.free(buf);
446458
447459 for (buf) |*phdr, i| {
448460 phdr.* = self.program_headers.items[i];
......@@ -478,12 +490,20 @@ pub const ElfFile = struct {
478490 }
479491 }
480492 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 };
481501 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
484504 if (needed_size > allocated_size) {
485505 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);
487507 }
488508
489509 switch (self.ptr_width) {
......@@ -719,7 +739,7 @@ pub const ElfFile = struct {
719739 defer code.deinit();
720740
721741 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);
723743 if (err_msg != null) |em| {
724744 decl.analysis = .codegen_failure;
725745 _ = try module.failed_decls.put(decl, em);
......@@ -751,15 +771,15 @@ pub const ElfFile = struct {
751771 try self.writeSymbol(decl.link.local_sym_index);
752772 break :blk file_offset;
753773 } else {
754 try self.symbols.ensureCapacity(self.symbols.items.len + 1);
755 try self.offset_table.ensureCapacity(self.offset_table.items.len + 1);
774 try self.symbols.ensureCapacity(self.allocator, self.symbols.items.len + 1);
775 try self.offset_table.ensureCapacity(self.allocator, self.offset_table.items.len + 1);
756776 const decl_name = mem.spanZ(u8, decl.name);
757777 const name_str_index = try self.makeString(decl_name);
758778 const new_block = try self.allocateTextBlock(code_size);
759779 const local_sym_index = self.symbols.items.len;
760780 const offset_table_index = self.offset_table.items.len;
761781
762 self.symbols.appendAssumeCapacity(self.allocator, .{
782 self.symbols.appendAssumeCapacity(.{
763783 .st_name = name_str_index,
764784 .st_info = (elf.STB_LOCAL << 4) | stt_bits,
765785 .st_other = 0,
......@@ -767,9 +787,9 @@ pub const ElfFile = struct {
767787 .st_value = new_block.vaddr,
768788 .st_size = code_size,
769789 });
770 errdefer self.symbols.shrink(self.symbols.items.len - 1);
771 self.offset_table.appendAssumeCapacity(self.allocator, new_block.vaddr);
772 errdefer self.offset_table.shrink(self.offset_table.items.len - 1);
790 errdefer self.symbols.shrink(self.allocator, self.symbols.items.len - 1);
791 self.offset_table.appendAssumeCapacity(new_block.vaddr);
792 errdefer self.offset_table.shrink(self.allocator, self.offset_table.items.len - 1);
773793 try self.writeSymbol(local_sym_index);
774794 try self.writeOffsetTableEntry(offset_table_index);
775795
......@@ -796,11 +816,12 @@ pub const ElfFile = struct {
796816 self: *ElfFile,
797817 module: *ir.Module,
798818 decl: *const ir.Module.Decl,
799 exports: []const *const Export,
819 exports: []const *ir.Module.Export,
800820 ) !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);
802822 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
805826 for (exports) |exp| {
806827 if (exp.options.section) |section_name| {
......@@ -808,15 +829,16 @@ pub const ElfFile = struct {
808829 try module.failed_exports.ensureCapacity(module.failed_exports.size + 1);
809830 module.failed_exports.putAssumeCapacityNoClobber(
810831 exp,
811 try ir.ErrorMsg.create(0, "Unimplemented: ExportOptions.section", .{}),
832 try ir.ErrorMsg.create(self.allocator, 0, "Unimplemented: ExportOptions.section", .{}),
812833 );
834 continue;
813835 }
814836 }
815 const stb_bits = switch (exp.options.linkage) {
837 const stb_bits: u8 = switch (exp.options.linkage) {
816838 .Internal => elf.STB_LOCAL,
817839 .Strong => blk: {
818840 if (mem.eql(u8, exp.options.name, "_start")) {
819 self.entry_addr = decl_symbol.vaddr;
841 self.entry_addr = decl_sym.st_value;
820842 }
821843 break :blk elf.STB_GLOBAL;
822844 },
......@@ -825,8 +847,9 @@ pub const ElfFile = struct {
825847 try module.failed_exports.ensureCapacity(module.failed_exports.size + 1);
826848 module.failed_exports.putAssumeCapacityNoClobber(
827849 exp,
828 try ir.ErrorMsg.create(0, "Unimplemented: GlobalLinkage.LinkOnce", .{}),
850 try ir.ErrorMsg.create(self.allocator, 0, "Unimplemented: GlobalLinkage.LinkOnce", .{}),
829851 );
852 continue;
830853 },
831854 };
832855 const stt_bits: u8 = @truncate(u4, decl_sym.st_info);
......@@ -844,15 +867,15 @@ pub const ElfFile = struct {
844867 } else {
845868 const name = try self.makeString(exp.options.name);
846869 const i = self.symbols.items.len;
847 self.symbols.appendAssumeCapacity(self.allocator, .{
848 .st_name = sn.name,
870 self.symbols.appendAssumeCapacity(.{
871 .st_name = name,
849872 .st_info = (stb_bits << 4) | stt_bits,
850873 .st_other = 0,
851874 .st_shndx = self.text_section_index.?,
852875 .st_value = decl_sym.st_value,
853876 .st_size = decl_sym.st_size,
854877 });
855 errdefer self.symbols.shrink(self.symbols.items.len - 1);
878 errdefer self.symbols.shrink(self.allocator, self.symbols.items.len - 1);
856879 try self.writeSymbol(i);
857880
858881 self.symbol_count_dirty = true;
......@@ -946,10 +969,15 @@ pub const ElfFile = struct {
946969 }
947970
948971 fn writeSymbol(self: *ElfFile, index: usize) !void {
972 assert(index != 0);
949973 const syms_sect = &self.sections.items[self.symtab_section_index.?];
950974 // Make sure we are not pointlessly writing symbol data that will have to get relocated
951975 // due to running out of space.
952976 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 };
953981 const allocated_size = self.allocatedSize(syms_sect.sh_offset);
954982 const needed_size = self.symbols.items.len * sym_size;
955983 if (needed_size > allocated_size) {
......@@ -990,11 +1018,15 @@ pub const ElfFile = struct {
9901018 }
9911019
9921020 fn writeAllSymbols(self: *ElfFile) !void {
993 const small_ptr = self.ptr_width == .p32;
9941021 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);
996 const sym_size: u64 = if (small_ptr) @sizeOf(elf.Elf32_Sym) else @sizeOf(elf.Elf64_Sym);
997
1022 const sym_align: u16 = switch (self.ptr_width) {
1023 .p32 => @alignOf(elf.Elf32_Sym),
1024 .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 };
9981030 const allocated_size = self.allocatedSize(syms_sect.sh_offset);
9991031 const needed_size = self.symbols.items.len * sym_size;
10001032 if (needed_size > allocated_size) {
src-self-hosted/value.zig+30-11
......@@ -67,6 +67,7 @@ pub const Value = extern union {
6767 int_big_positive,
6868 int_big_negative,
6969 function,
70 ref_val,
7071 decl_ref,
7172 elem_ptr,
7273 bytes,
......@@ -158,6 +159,11 @@ pub const Value = extern union {
158159 .int_big_positive => return out_stream.print("{}", .{val.cast(Payload.IntBigPositive).?.asBigInt()}),
159160 .int_big_negative => return out_stream.print("{}", .{val.cast(Payload.IntBigNegative).?.asBigInt()}),
160161 .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 },
161167 .decl_ref => return out_stream.writeAll("(decl ref)"),
162168 .elem_ptr => {
163169 const elem_ptr = val.cast(Payload.ElemPtr).?;
......@@ -229,6 +235,7 @@ pub const Value = extern union {
229235 .int_big_positive,
230236 .int_big_negative,
231237 .function,
238 .ref_val,
232239 .decl_ref,
233240 .elem_ptr,
234241 .bytes,
......@@ -276,6 +283,7 @@ pub const Value = extern union {
276283 .bool_false,
277284 .null_value,
278285 .function,
286 .ref_val,
279287 .decl_ref,
280288 .elem_ptr,
281289 .bytes,
......@@ -333,6 +341,7 @@ pub const Value = extern union {
333341 .bool_false,
334342 .null_value,
335343 .function,
344 .ref_val,
336345 .decl_ref,
337346 .elem_ptr,
338347 .bytes,
......@@ -391,6 +400,7 @@ pub const Value = extern union {
391400 .bool_false,
392401 .null_value,
393402 .function,
403 .ref_val,
394404 .decl_ref,
395405 .elem_ptr,
396406 .bytes,
......@@ -454,6 +464,7 @@ pub const Value = extern union {
454464 .bool_false,
455465 .null_value,
456466 .function,
467 .ref_val,
457468 .decl_ref,
458469 .elem_ptr,
459470 .bytes,
......@@ -546,6 +557,7 @@ pub const Value = extern union {
546557 .bool_false,
547558 .null_value,
548559 .function,
560 .ref_val,
549561 .decl_ref,
550562 .elem_ptr,
551563 .bytes,
......@@ -600,6 +612,7 @@ pub const Value = extern union {
600612 .bool_false,
601613 .null_value,
602614 .function,
615 .ref_val,
603616 .decl_ref,
604617 .elem_ptr,
605618 .bytes,
......@@ -655,7 +668,8 @@ pub const Value = extern union {
655668 }
656669
657670 /// 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 {
659673 return switch (self.tag()) {
660674 .ty,
661675 .u8_type,
......@@ -704,21 +718,19 @@ pub const Value = extern union {
704718 => unreachable,
705719
706720 .the_one_possible_value => Value.initTag(.the_one_possible_value),
707 .decl_ref => {
708 const index = self.cast(Payload.DeclRef).?.index;
709 return module.getDeclValue(index);
710 },
721 .ref_val => self.cast(Payload.RefVal).?.val,
722 .decl_ref => self.cast(Payload.DeclRef).?.decl.value(),
711723 .elem_ptr => {
712 const elem_ptr = self.cast(ElemPtr).?;
713 const array_val = try elem_ptr.array_ptr.pointerDeref(module);
714 return self.elemValue(array_val, elem_ptr.index);
724 const elem_ptr = self.cast(Payload.ElemPtr).?;
725 const array_val = try elem_ptr.array_ptr.pointerDeref(allocator);
726 return array_val.elemValue(allocator, elem_ptr.index);
715727 },
716728 };
717729 }
718730
719731 /// Asserts the value is a single-item pointer to an array, or an array,
720732 /// 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 {
722734 switch (self.tag()) {
723735 .ty,
724736 .u8_type,
......@@ -764,6 +776,7 @@ pub const Value = extern union {
764776 .int_big_negative,
765777 .undef,
766778 .elem_ptr,
779 .ref_val,
767780 .decl_ref,
768781 => unreachable,
769782
......@@ -838,6 +851,7 @@ pub const Value = extern union {
838851 .int_i64,
839852 .int_big_positive,
840853 .int_big_negative,
854 .ref_val,
841855 .decl_ref,
842856 .elem_ptr,
843857 .bytes,
......@@ -896,11 +910,16 @@ pub const Value = extern union {
896910 elem_type: *Type,
897911 };
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
899919 /// Represents a pointer to a decl, not the value of the decl.
900920 pub const DeclRef = struct {
901921 base: Payload = Payload{ .tag = .decl_ref },
902 /// Index into the Module's decls list
903 index: usize,
922 decl: *ir.Module.Decl,
904923 };
905924
906925 pub const ElemPtr = struct {