authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-05-12 23:59:46-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-05-12 23:59:46-04:00
loga3da584248c1152c01a1a7f878c164fb19b8e04a
treedb3b48c29d15f3c324ec9452740d99e99b265436
parente3a0fac1a77a8c637c790670ff749879298becad

self-hosted: ir: implement separated analysis of Decl and Fn


3 files changed, 209 insertions(+), 148 deletions(-)

src-self-hosted/ir.zig+197-136
......@@ -2,7 +2,6 @@ const std = @import("std");
22const mem = std.mem;
33const Allocator = std.mem.Allocator;
44const ArrayListUnmanaged = std.ArrayListUnmanaged;
5const LinkedList = std.TailQueue;
65const Value = @import("value.zig").Value;
76const Type = @import("type.zig").Type;
87const TypedValue = @import("TypedValue.zig");
......@@ -168,17 +167,6 @@ pub const Inst = struct {
168167 };
169168};
170169
171fn swapRemoveElem(allocator: *Allocator, comptime T: type, item: T, list: *ArrayListUnmanaged(T)) void {
172 var i: usize = 0;
173 while (i < list.items.len) {
174 if (list.items[i] == item) {
175 list.swapRemove(allocator, i);
176 continue;
177 }
178 i += 1;
179 }
180}
181
182170pub const Module = struct {
183171 /// General-purpose allocator.
184172 allocator: *Allocator,
......@@ -203,6 +191,8 @@ pub const Module = struct {
203191 optimize_mode: std.builtin.Mode,
204192 link_error_flags: link.ElfFile.ErrorFlags = link.ElfFile.ErrorFlags{},
205193
194 work_stack: ArrayListUnmanaged(WorkItem) = ArrayListUnmanaged(WorkItem){},
195
206196 /// We optimize memory usage for a compilation with no compile errors by storing the
207197 /// error messages and mapping outside of `Decl`.
208198 /// The ErrorMsg memory is owned by the decl, using Module's allocator.
......@@ -218,6 +208,11 @@ pub const Module = struct {
218208 /// The ErrorMsg memory is owned by the `Export`, using Module's allocator.
219209 failed_exports: std.AutoHashMap(*Export, *ErrorMsg),
220210
211 pub const WorkItem = union(enum) {
212 /// Write the machine code for a Decl to the output file.
213 codegen_decl: *Decl,
214 };
215
221216 pub const Export = struct {
222217 options: std.builtin.ExportOptions,
223218 /// Byte offset into the file that contains the export directive.
......@@ -322,11 +317,13 @@ pub const Module = struct {
322317 }
323318 };
324319
325 /// Memory is managed by the arena of the owning Decl.
320 /// Fn struct memory is owned by the Decl's TypedValue.Managed arena allocator.
326321 pub const Fn = struct {
322 /// This memory owned by the Decl's TypedValue.Managed arena allocator.
327323 fn_type: Type,
328324 analysis: union(enum) {
329 queued,
325 /// The value is the source instruction.
326 queued: *text.Inst.Fn,
330327 in_progress: *Analysis,
331328 /// There will be a corresponding ErrorMsg in Module.failed_fns
332329 failure,
......@@ -336,11 +333,14 @@ pub const Module = struct {
336333 /// self-hosted supports proper struct types and Zig AST => ZIR.
337334 scope: *Scope.ZIRModule,
338335
339 /// This memory managed by the general purpose allocator.
336 /// This memory is temporary and points to stack memory for the duration
337 /// of Fn analysis.
340338 pub const Analysis = struct {
341339 inner_block: Scope.Block,
342340 /// null value means a semantic analysis error happened.
343341 inst_table: std.AutoHashMap(*text.Inst, ?*Inst),
342 /// Owns the memory for instructions
343 arena: std.heap.ArenaAllocator,
344344 };
345345 };
346346
......@@ -354,6 +354,26 @@ pub const Module = struct {
354354 return @fieldParentPtr(T, "base", base);
355355 }
356356
357 /// Asserts the scope has a parent which is a DeclAnalysis and
358 /// returns the arena Allocator.
359 pub fn arena(self: *Scope) *Allocator {
360 switch (self.tag) {
361 .block => return self.cast(Block).?.arena,
362 .decl => return &self.cast(DeclAnalysis).?.arena.allocator,
363 .zir_module => unreachable,
364 }
365 }
366
367 /// Asserts the scope has a parent which is a DeclAnalysis and
368 /// returns the Decl.
369 pub fn decl(self: *Scope) *Decl {
370 switch (self.tag) {
371 .block => return self.cast(Block).?.decl,
372 .decl => return self.cast(DeclAnalysis).?.decl,
373 .zir_module => unreachable,
374 }
375 }
376
357377 pub const Tag = enum {
358378 zir_module,
359379 block,
......@@ -404,7 +424,10 @@ pub const Module = struct {
404424 pub const base_tag: Tag = .block;
405425 base: Scope = Scope{ .tag = base_tag },
406426 func: *Fn,
427 decl: *Decl,
407428 instructions: ArrayListUnmanaged(*Inst),
429 /// Points to the arena allocator of DeclAnalysis
430 arena: *Allocator,
408431 };
409432
410433 /// This is a temporary structure, references to it are valid only
......@@ -413,6 +436,7 @@ pub const Module = struct {
413436 pub const base_tag: Tag = .decl;
414437 base: Scope = Scope{ .tag = base_tag },
415438 decl: *Decl,
439 arena: std.heap.ArenaAllocator,
416440 };
417441 };
418442
......@@ -616,21 +640,62 @@ pub const Module = struct {
616640
617641 // Here we ensure enough queue capacity to store all the decls, so that later we can use
618642 // appendAssumeCapacity.
619 try self.analysis_queue.ensureCapacity(self.analysis_queue.items.len + contents.module.decls.len);
643 try self.work_stack.ensureCapacity(
644 self.allocator,
645 self.work_stack.items.len + src_module.decls.len,
646 );
620647
621 for (contents.module.decls) |decl| {
648 for (src_module.decls) |decl| {
622649 if (decl.cast(text.Inst.Export)) |export_inst| {
623650 try analyzeExport(self, &root_scope.base, export_inst);
624651 }
625652 }
626653
627 while (self.analysis_queue.popOrNull()) |work_item| {
628 switch (work_item) {
629 .decl => |decl| switch (decl.analysis) {
630 .success => try self.bin_file.updateDecl(self, decl),
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);
631672 },
632 }
633 }
673 },
674 };
675 }
676
677 fn analyzeFnBody(self: *Module, decl: *Decl, func: *Fn) !void {
678 // Use the Decl's arena for function memory.
679 var arena = decl.typed_value.most_recent.arena.?.promote(self.allocator);
680 defer decl.typed_value.most_recent.arena.?.* = arena.state;
681 var analysis: Analysis = .{
682 .inner_block = .{
683 .func = func,
684 .decl = decl,
685 .instructions = .{},
686 .arena = &arena.allocator,
687 },
688 .inst_table = std.AutoHashMap(*text.Inst, ?*Inst).init(self.allocator),
689 };
690 defer analysis.inner_block.instructions.deinit();
691 defer analysis.inst_table.deinit();
692
693 const fn_inst = func.analysis.queued;
694 func.analysis = .{ .in_progress = &analysis };
695
696 try self.analyzeBody(&analysis.inner_block, fn_inst.positionals.body);
697
698 func.analysis = .{ .success = .{ .instructions = analysis.inner_block.instructions.toOwnedSlice() } };
634699 }
635700
636701 fn resolveDecl(self: *Module, scope: *Scope, old_inst: *text.Inst) InnerError!*Decl {
......@@ -656,19 +721,27 @@ pub const Module = struct {
656721 };
657722
658723 var decl_scope: Scope.DeclAnalysis = .{
659 .base = .{ .parent = scope },
660724 .decl = new_decl,
725 .arena = std.heap.ArenaAllocator.init(self.allocator),
661726 };
662 const typed_value = self.analyzeInstConst(&decl_scope.base, old_inst) catch |err| switch (err) {
663 error.AnalysisFail => {
664 assert(new_decl.analysis == .failure);
665 return error.AnalysisFail;
727 errdefer decl_scope.arena.deinit();
728
729 const arena_state = try self.allocator.create(std.heap.ArenaAllocator.State);
730 errdefer self.allocator.destroy(arena_state);
731
732 const typed_value = try self.analyzeInstConst(&decl_scope.base, old_inst);
733
734 arena_state.* = decl_scope.arena;
735
736 new_decl.typed_value = .{
737 .most_recent = .{
738 .typed_value = typed_value,
739 .arena = arena_state,
666740 },
667 else => |e| return e,
668741 };
669 new_decl.analysis = .{ .success = typed_value };
742 new_decl.analysis = .complete;
670743 // We ensureCapacity when scanning for decls.
671 self.analysis_queue.appendAssumeCapacity(.{ .decl = new_decl });
744 self.work_stack.appendAssumeCapacity(self.allocator, .{ .codegen_decl = new_decl });
672745 return new_decl;
673746 }
674747 }
......@@ -708,7 +781,7 @@ pub const Module = struct {
708781
709782 fn resolveInstConst(self: *Module, scope: *Scope, old_inst: *text.Inst) InnerError!TypedValue {
710783 const new_inst = try self.resolveInst(scope, old_inst);
711 const val = try self.resolveConstValue(new_inst);
784 const val = try self.resolveConstValue(scope, new_inst);
712785 return TypedValue{
713786 .ty = new_inst.ty,
714787 .val = val,
......@@ -716,7 +789,7 @@ pub const Module = struct {
716789 }
717790
718791 fn resolveConstValue(self: *Module, scope: *Scope, base: *Inst) !Value {
719 return (try self.resolveDefinedValue(base)) orelse
792 return (try self.resolveDefinedValue(scope, base)) orelse
720793 return self.fail(scope, base.src, "unable to resolve comptime value", .{});
721794 }
722795
......@@ -734,15 +807,15 @@ pub const Module = struct {
734807 const new_inst = try self.resolveInst(scope, old_inst);
735808 const wanted_type = Type.initTag(.const_slice_u8);
736809 const coerced_inst = try self.coerce(scope, wanted_type, new_inst);
737 const val = try self.resolveConstValue(coerced_inst);
738 return val.toAllocatedBytes(&self.arena.allocator);
810 const val = try self.resolveConstValue(scope, coerced_inst);
811 return val.toAllocatedBytes(scope.arena());
739812 }
740813
741814 fn resolveType(self: *Module, scope: *Scope, old_inst: *text.Inst) !Type {
742815 const new_inst = try self.resolveInst(scope, old_inst);
743816 const wanted_type = Type.initTag(.@"type");
744817 const coerced_inst = try self.coerce(scope, wanted_type, new_inst);
745 const val = try self.resolveConstValue(coerced_inst);
818 const val = try self.resolveConstValue(scope, coerced_inst);
746819 return val.toType();
747820 }
748821
......@@ -764,7 +837,7 @@ pub const Module = struct {
764837 const new_export = try self.allocator.create(Export);
765838 errdefer self.allocator.destroy(new_export);
766839
767 const owner_decl = scope.getDecl();
840 const owner_decl = scope.decl();
768841
769842 new_export.* = .{
770843 .options = .{ .data = .{ .name = symbol_name } },
......@@ -810,7 +883,7 @@ pub const Module = struct {
810883 }
811884
812885 fn addNewInst(self: *Module, block: *Scope.Block, src: usize, ty: Type, comptime T: type) !*T {
813 const inst = try self.arena.allocator.create(T);
886 const inst = try block.arena.create(T);
814887 inst.* = .{
815888 .base = .{
816889 .tag = T.base_tag,
......@@ -823,8 +896,8 @@ pub const Module = struct {
823896 return inst;
824897 }
825898
826 fn constInst(self: *Module, src: usize, typed_value: TypedValue) !*Inst {
827 const const_inst = try self.arena.allocator.create(Inst.Constant);
899 fn constInst(self: *Module, scope: *Scope, src: usize, typed_value: TypedValue) !*Inst {
900 const const_inst = try scope.arena().create(Inst.Constant);
828901 const_inst.* = .{
829902 .base = .{
830903 .tag = Inst.Constant.base_tag,
......@@ -836,71 +909,71 @@ pub const Module = struct {
836909 return &const_inst.base;
837910 }
838911
839 fn constStr(self: *Module, src: usize, str: []const u8) !*Inst {
840 const array_payload = try self.arena.allocator.create(Type.Payload.Array_u8_Sentinel0);
912 fn constStr(self: *Module, scope: *Scope, src: usize, str: []const u8) !*Inst {
913 const array_payload = try scope.arena().create(Type.Payload.Array_u8_Sentinel0);
841914 array_payload.* = .{ .len = str.len };
842915
843 const ty_payload = try self.arena.allocator.create(Type.Payload.SingleConstPointer);
916 const ty_payload = try scope.arena().create(Type.Payload.SingleConstPointer);
844917 ty_payload.* = .{ .pointee_type = Type.initPayload(&array_payload.base) };
845918
846 const bytes_payload = try self.arena.allocator.create(Value.Payload.Bytes);
919 const bytes_payload = try scope.arena().create(Value.Payload.Bytes);
847920 bytes_payload.* = .{ .data = str };
848921
849 return self.constInst(src, .{
922 return self.constInst(scope, src, .{
850923 .ty = Type.initPayload(&ty_payload.base),
851924 .val = Value.initPayload(&bytes_payload.base),
852925 });
853926 }
854927
855 fn constType(self: *Module, src: usize, ty: Type) !*Inst {
856 return self.constInst(src, .{
928 fn constType(self: *Module, scope: *Scope, src: usize, ty: Type) !*Inst {
929 return self.constInst(scope, src, .{
857930 .ty = Type.initTag(.type),
858 .val = try ty.toValue(&self.arena.allocator),
931 .val = try ty.toValue(scope.arena()),
859932 });
860933 }
861934
862 fn constVoid(self: *Module, src: usize) !*Inst {
863 return self.constInst(src, .{
935 fn constVoid(self: *Module, scope: *Scope, src: usize) !*Inst {
936 return self.constInst(scope, src, .{
864937 .ty = Type.initTag(.void),
865938 .val = Value.initTag(.the_one_possible_value),
866939 });
867940 }
868941
869 fn constUndef(self: *Module, src: usize, ty: Type) !*Inst {
870 return self.constInst(src, .{
942 fn constUndef(self: *Module, scope: *Scope, src: usize, ty: Type) !*Inst {
943 return self.constInst(scope, src, .{
871944 .ty = ty,
872945 .val = Value.initTag(.undef),
873946 });
874947 }
875948
876 fn constBool(self: *Module, src: usize, v: bool) !*Inst {
877 return self.constInst(src, .{
949 fn constBool(self: *Module, scope: *Scope, src: usize, v: bool) !*Inst {
950 return self.constInst(scope, src, .{
878951 .ty = Type.initTag(.bool),
879952 .val = ([2]Value{ Value.initTag(.bool_false), Value.initTag(.bool_true) })[@boolToInt(v)],
880953 });
881954 }
882955
883 fn constIntUnsigned(self: *Module, src: usize, ty: Type, int: u64) !*Inst {
884 const int_payload = try self.arena.allocator.create(Value.Payload.Int_u64);
956 fn constIntUnsigned(self: *Module, scope: *Scope, src: usize, ty: Type, int: u64) !*Inst {
957 const int_payload = try scope.arena().create(Value.Payload.Int_u64);
885958 int_payload.* = .{ .int = int };
886959
887 return self.constInst(src, .{
960 return self.constInst(scope, src, .{
888961 .ty = ty,
889962 .val = Value.initPayload(&int_payload.base),
890963 });
891964 }
892965
893 fn constIntSigned(self: *Module, src: usize, ty: Type, int: i64) !*Inst {
894 const int_payload = try self.arena.allocator.create(Value.Payload.Int_i64);
966 fn constIntSigned(self: *Module, scope: *Scope, src: usize, ty: Type, int: i64) !*Inst {
967 const int_payload = try scope.arena().create(Value.Payload.Int_i64);
895968 int_payload.* = .{ .int = int };
896969
897 return self.constInst(src, .{
970 return self.constInst(scope, src, .{
898971 .ty = ty,
899972 .val = Value.initPayload(&int_payload.base),
900973 });
901974 }
902975
903 fn constIntBig(self: *Module, src: usize, ty: Type, big_int: BigIntConst) !*Inst {
976 fn constIntBig(self: *Module, scope: *Scope, src: usize, ty: Type, big_int: BigIntConst) !*Inst {
904977 const val_payload = if (big_int.positive) blk: {
905978 if (big_int.to(u64)) |x| {
906979 return self.constIntUnsigned(src, ty, x);
......@@ -908,7 +981,7 @@ pub const Module = struct {
908981 error.NegativeIntoUnsigned => unreachable,
909982 error.TargetTooSmall => {}, // handled below
910983 }
911 const big_int_payload = try self.arena.allocator.create(Value.Payload.IntBigPositive);
984 const big_int_payload = try scope.arena().create(Value.Payload.IntBigPositive);
912985 big_int_payload.* = .{ .limbs = big_int.limbs };
913986 break :blk &big_int_payload.base;
914987 } else blk: {
......@@ -918,12 +991,12 @@ pub const Module = struct {
918991 error.NegativeIntoUnsigned => unreachable,
919992 error.TargetTooSmall => {}, // handled below
920993 }
921 const big_int_payload = try self.arena.allocator.create(Value.Payload.IntBigNegative);
994 const big_int_payload = try scope.arena().create(Value.Payload.IntBigNegative);
922995 big_int_payload.* = .{ .limbs = big_int.limbs };
923996 break :blk &big_int_payload.base;
924997 };
925998
926 return self.constInst(src, .{
999 return self.constInst(scope, src, .{
9271000 .ty = ty,
9281001 .val = Value.initPayload(val_payload),
9291002 });
......@@ -958,11 +1031,10 @@ pub const Module = struct {
9581031 .@"asm" => return self.analyzeInstAsm(scope, old_inst.cast(text.Inst.Asm).?),
9591032 .@"unreachable" => return self.analyzeInstUnreachable(scope, old_inst.cast(text.Inst.Unreachable).?),
9601033 .@"return" => return self.analyzeInstRet(scope, old_inst.cast(text.Inst.Return).?),
961 // TODO postpone function analysis until later
9621034 .@"fn" => return self.analyzeInstFn(scope, old_inst.cast(text.Inst.Fn).?),
9631035 .@"export" => {
9641036 try self.analyzeExport(scope, old_inst.cast(text.Inst.Export).?);
965 return self.constVoid(old_inst.src);
1037 return self.constVoid(scope, old_inst.src);
9661038 },
9671039 .primitive => return self.analyzeInstPrimitive(old_inst.cast(text.Inst.Primitive).?),
9681040 .fntype => return self.analyzeInstFnType(scope, old_inst.cast(text.Inst.FnType).?),
......@@ -1033,7 +1105,7 @@ pub const Module = struct {
10331105 defer self.allocator.free(fn_param_types);
10341106 func.ty.fnParamTypes(fn_param_types);
10351107
1036 const casted_args = try self.arena.allocator.alloc(*Inst, fn_params_len);
1108 const casted_args = try scope.arena().alloc(*Inst, fn_params_len);
10371109 for (inst.positionals.args) |src_arg, i| {
10381110 const uncasted_arg = try self.resolveInst(scope, src_arg);
10391111 casted_args[i] = try self.coerce(scope, fn_param_types[i], uncasted_arg);
......@@ -1048,36 +1120,15 @@ pub const Module = struct {
10481120
10491121 fn analyzeInstFn(self: *Module, scope: *Scope, fn_inst: *text.Inst.Fn) InnerError!*Inst {
10501122 const fn_type = try self.resolveType(scope, fn_inst.positionals.fn_type);
1051
1052 var new_func: Fn = .{
1053 .fn_index = self.fns.items.len,
1054 .inner_block = .{
1055 .func = undefined,
1056 .instructions = .{},
1057 },
1058 .inst_table = std.AutoHashMap(*text.Inst, ?*Inst).init(self.allocator),
1059 };
1060 new_func.inner_block.func = &new_func;
1061 defer new_func.inner_block.instructions.deinit();
1062 defer new_func.inst_table.deinit();
1063 // Don't hang on to a reference to this when analyzing body instructions, since the memory
1064 // could become invalid.
1065 (try self.fns.addOne(self.allocator)).* = .{
1066 .analysis_status = .in_progress,
1123 const new_func = try scope.arena().create(Fn);
1124 new_func.* = .{
10671125 .fn_type = fn_type,
1068 .body = undefined,
1126 .analysis = .{ .queued = fn_inst.positionals.body },
1127 .scope = scope.namespace(),
10691128 };
1070
1071 try self.analyzeBody(&new_func.inner_block, fn_inst.positionals.body);
1072
1073 const f = &self.fns.items[new_func.fn_index];
1074 f.analysis_status = .success;
1075 f.body = .{ .instructions = new_func.inner_block.instructions.toOwnedSlice() };
1076
1077 const fn_payload = try self.arena.allocator.create(Value.Payload.Function);
1078 fn_payload.* = .{ .index = new_func.fn_index };
1079
1080 return self.constInst(fn_inst.base.src, .{
1129 const fn_payload = try scope.arena().create(Value.Payload.Function);
1130 fn_payload.* = .{ .func = new_func };
1131 return self.constInst(scope, fn_inst.base.src, .{
10811132 .ty = fn_type,
10821133 .val = Value.initPayload(&fn_payload.base),
10831134 });
......@@ -1142,13 +1193,13 @@ pub const Module = struct {
11421193 switch (elem_ty.zigTypeTag()) {
11431194 .Array => {
11441195 if (mem.eql(u8, field_name, "len")) {
1145 const len_payload = try self.arena.allocator.create(Value.Payload.Int_u64);
1196 const len_payload = try scope.arena().create(Value.Payload.Int_u64);
11461197 len_payload.* = .{ .int = elem_ty.arrayLen() };
11471198
1148 const ref_payload = try self.arena.allocator.create(Value.Payload.RefVal);
1199 const ref_payload = try scope.arena().create(Value.Payload.RefVal);
11491200 ref_payload.* = .{ .val = Value.initPayload(&len_payload.base) };
11501201
1151 return self.constInst(fieldptr.base.src, .{
1202 return self.constInst(scope, fieldptr.base.src, .{
11521203 .ty = Type.initTag(.single_const_pointer_to_comptime_int),
11531204 .val = Value.initPayload(&ref_payload.base),
11541205 });
......@@ -1217,12 +1268,12 @@ pub const Module = struct {
12171268 const index_u64 = index_val.toUnsignedInt();
12181269 // @intCast here because it would have been impossible to construct a value that
12191270 // required a larger index.
1220 const elem_ptr = try array_ptr_val.elemPtr(&self.arena.allocator, @intCast(usize, index_u64));
1271 const elem_ptr = try array_ptr_val.elemPtr(scope.arena(), @intCast(usize, index_u64));
12211272
1222 const type_payload = try self.arena.allocator.create(Type.Payload.SingleConstPointer);
1273 const type_payload = try scope.arena().create(Type.Payload.SingleConstPointer);
12231274 type_payload.* = .{ .pointee_type = array_ptr.ty.elemType().elemType() };
12241275
1225 return self.constInst(inst.base.src, .{
1276 return self.constInst(scope, inst.base.src, .{
12261277 .ty = Type.initPayload(&type_payload.base),
12271278 .val = elem_ptr,
12281279 });
......@@ -1246,7 +1297,7 @@ pub const Module = struct {
12461297 var rhs_space: Value.BigIntSpace = undefined;
12471298 const lhs_bigint = lhs_val.toBigInt(&lhs_space);
12481299 const rhs_bigint = rhs_val.toBigInt(&rhs_space);
1249 const limbs = try self.arena.allocator.alloc(
1300 const limbs = try scope.arena().alloc(
12501301 std.math.big.Limb,
12511302 std.math.max(lhs_bigint.limbs.len, rhs_bigint.limbs.len) + 1,
12521303 );
......@@ -1259,16 +1310,16 @@ pub const Module = struct {
12591310 }
12601311
12611312 const val_payload = if (result_bigint.positive) blk: {
1262 const val_payload = try self.arena.allocator.create(Value.Payload.IntBigPositive);
1313 const val_payload = try scope.arena().create(Value.Payload.IntBigPositive);
12631314 val_payload.* = .{ .limbs = result_limbs };
12641315 break :blk &val_payload.base;
12651316 } else blk: {
1266 const val_payload = try self.arena.allocator.create(Value.Payload.IntBigNegative);
1317 const val_payload = try scope.arena().create(Value.Payload.IntBigNegative);
12671318 val_payload.* = .{ .limbs = result_limbs };
12681319 break :blk &val_payload.base;
12691320 };
12701321
1271 return self.constInst(inst.base.src, .{
1322 return self.constInst(scope, inst.base.src, .{
12721323 .ty = lhs.ty,
12731324 .val = Value.initPayload(val_payload),
12741325 });
......@@ -1286,7 +1337,7 @@ pub const Module = struct {
12861337 else => return self.fail(scope, deref.positionals.ptr.src, "expected pointer, found '{}'", .{ptr.ty}),
12871338 };
12881339 if (ptr.value()) |val| {
1289 return self.constInst(deref.base.src, .{
1340 return self.constInst(scope, deref.base.src, .{
12901341 .ty = elem_ty,
12911342 .val = val.pointerDeref(),
12921343 });
......@@ -1300,9 +1351,9 @@ pub const Module = struct {
13001351 const asm_source = try self.resolveConstString(scope, assembly.positionals.asm_source);
13011352 const output = if (assembly.kw_args.output) |o| try self.resolveConstString(scope, o) else null;
13021353
1303 const inputs = try self.arena.allocator.alloc([]const u8, assembly.kw_args.inputs.len);
1304 const clobbers = try self.arena.allocator.alloc([]const u8, assembly.kw_args.clobbers.len);
1305 const args = try self.arena.allocator.alloc(*Inst, assembly.kw_args.args.len);
1354 const inputs = try scope.arena().alloc([]const u8, assembly.kw_args.inputs.len);
1355 const clobbers = try scope.arena().alloc([]const u8, assembly.kw_args.clobbers.len);
1356 const args = try scope.arena().alloc(*Inst, assembly.kw_args.args.len);
13061357
13071358 for (inputs) |*elem, i| {
13081359 elem.* = try self.resolveConstString(scope, assembly.kw_args.inputs[i]);
......@@ -1408,15 +1459,16 @@ pub const Module = struct {
14081459 const uncasted_cond = try self.resolveInst(scope, inst.positionals.condition);
14091460 const cond = try self.coerce(scope, Type.initTag(.bool), uncasted_cond);
14101461
1411 if (try self.resolveDefinedValue(cond)) |cond_val| {
1462 if (try self.resolveDefinedValue(scope, cond)) |cond_val| {
14121463 const body = if (cond_val.toBool()) &inst.positionals.true_body else &inst.positionals.false_body;
14131464 try self.analyzeBody(scope, body.*);
1414 return self.constVoid(inst.base.src);
1465 return self.constVoid(scope, inst.base.src);
14151466 }
14161467
14171468 const parent_block = try self.requireRuntimeBlock(scope, inst.base.src);
14181469
14191470 var true_block: Scope.Block = .{
1471 .base = .{ .parent = scope },
14201472 .func = parent_block.func,
14211473 .instructions = .{},
14221474 };
......@@ -1424,6 +1476,7 @@ pub const Module = struct {
14241476 try self.analyzeBody(&true_block.base, inst.positionals.true_body);
14251477
14261478 var false_block: Scope.Block = .{
1479 .base = .{ .parent = scope },
14271480 .func = parent_block.func,
14281481 .instructions = .{},
14291482 };
......@@ -1431,8 +1484,8 @@ pub const Module = struct {
14311484 try self.analyzeBody(&false_block.base, inst.positionals.false_body);
14321485
14331486 // Copy the instruction pointers to the arena memory
1434 const true_instructions = try self.arena.allocator.alloc(*Inst, true_block.instructions.items.len);
1435 const false_instructions = try self.arena.allocator.alloc(*Inst, false_block.instructions.items.len);
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);
14361489
14371490 mem.copy(*Inst, true_instructions, true_block.instructions.items);
14381491 mem.copy(*Inst, false_instructions, false_block.instructions.items);
......@@ -1586,7 +1639,7 @@ pub const Module = struct {
15861639 var lhs_bits: usize = undefined;
15871640 if (lhs.value()) |lhs_val| {
15881641 if (lhs_val.isUndef())
1589 return self.constUndef(src, Type.initTag(.bool));
1642 return self.constUndef(scope, src, Type.initTag(.bool));
15901643 const is_unsigned = if (lhs_is_float) x: {
15911644 var bigint_space: Value.BigIntSpace = undefined;
15921645 var bigint = try lhs_val.toBigInt(&bigint_space).toManaged(self.allocator);
......@@ -1621,7 +1674,7 @@ pub const Module = struct {
16211674 var rhs_bits: usize = undefined;
16221675 if (rhs.value()) |rhs_val| {
16231676 if (rhs_val.isUndef())
1624 return self.constUndef(src, Type.initTag(.bool));
1677 return self.constUndef(scope, src, Type.initTag(.bool));
16251678 const is_unsigned = if (rhs_is_float) x: {
16261679 var bigint_space: Value.BigIntSpace = undefined;
16271680 var bigint = try rhs_val.toBigInt(&bigint_space).toManaged(self.allocator);
......@@ -1670,13 +1723,13 @@ pub const Module = struct {
16701723 });
16711724 }
16721725
1673 fn makeIntType(self: *Module, signed: bool, bits: u16) !Type {
1726 fn makeIntType(self: *Module, scope: *Scope, signed: bool, bits: u16) !Type {
16741727 if (signed) {
1675 const int_payload = try self.arena.allocator.create(Type.Payload.IntSigned);
1728 const int_payload = try scope.arena().create(Type.Payload.IntSigned);
16761729 int_payload.* = .{ .bits = bits };
16771730 return Type.initPayload(&int_payload.base);
16781731 } else {
1679 const int_payload = try self.arena.allocator.create(Type.Payload.IntUnsigned);
1732 const int_payload = try scope.arena().create(Type.Payload.IntUnsigned);
16801733 int_payload.* = .{ .bits = bits };
16811734 return Type.initPayload(&int_payload.base);
16821735 }
......@@ -1701,7 +1754,7 @@ pub const Module = struct {
17011754 if (array_type.zigTypeTag() == .Array and
17021755 coerceInMemoryAllowed(dst_elem_type, array_type.elemType()) == .ok)
17031756 {
1704 return self.coerceArrayPtrToSlice(dest_type, inst);
1757 return self.coerceArrayPtrToSlice(scope, dest_type, inst);
17051758 }
17061759 }
17071760
......@@ -1712,7 +1765,7 @@ pub const Module = struct {
17121765 if (!val.intFitsInType(dest_type, self.target())) {
17131766 return self.fail(scope, inst.src, "type {} cannot represent integer value {}", .{ inst.ty, val });
17141767 }
1715 return self.constInst(inst.src, .{ .ty = dest_type, .val = val });
1768 return self.constInst(scope, inst.src, .{ .ty = dest_type, .val = val });
17161769 }
17171770
17181771 // integer widening
......@@ -1721,7 +1774,7 @@ pub const Module = struct {
17211774 const dst_info = dest_type.intInfo(self.target());
17221775 if (src_info.signed == dst_info.signed and dst_info.bits >= src_info.bits) {
17231776 if (inst.value()) |val| {
1724 return self.constInst(inst.src, .{ .ty = dest_type, .val = val });
1777 return self.constInst(scope, inst.src, .{ .ty = dest_type, .val = val });
17251778 } else {
17261779 return self.fail(scope, inst.src, "TODO implement runtime integer widening", .{});
17271780 }
......@@ -1736,33 +1789,41 @@ pub const Module = struct {
17361789 fn bitcast(self: *Module, scope: *Scope, dest_type: Type, inst: *Inst) !*Inst {
17371790 if (inst.value()) |val| {
17381791 // Keep the comptime Value representation; take the new type.
1739 return self.constInst(inst.src, .{ .ty = dest_type, .val = val });
1792 return self.constInst(scope, inst.src, .{ .ty = dest_type, .val = val });
17401793 }
17411794 // TODO validate the type size and other compile errors
17421795 const b = try self.requireRuntimeBlock(scope, inst.src);
17431796 return self.addNewInstArgs(b, inst.src, dest_type, Inst.BitCast, Inst.Args(Inst.BitCast){ .operand = inst });
17441797 }
17451798
1746 fn coerceArrayPtrToSlice(self: *Module, dest_type: Type, inst: *Inst) !*Inst {
1799 fn coerceArrayPtrToSlice(self: *Module, scope: *Scope, dest_type: Type, inst: *Inst) !*Inst {
17471800 if (inst.value()) |val| {
17481801 // The comptime Value representation is compatible with both types.
1749 return self.constInst(inst.src, .{ .ty = dest_type, .val = val });
1802 return self.constInst(scope, inst.src, .{ .ty = dest_type, .val = val });
17501803 }
17511804 return self.fail(scope, inst.src, "TODO implement coerceArrayPtrToSlice runtime instruction", .{});
17521805 }
17531806
17541807 fn fail(self: *Module, scope: *Scope, src: usize, comptime format: []const u8, args: var) InnerError {
17551808 @setCold(true);
1756 const err_msg = ErrorMsg{
1757 .byte_offset = src,
1758 .msg = try std.fmt.allocPrint(self.allocator, format, args),
1759 };
1760 if (scope.cast(Scope.Block)) |block| {
1761 block.func.analysis = .{ .failure = err_msg };
1762 } else if (scope.cast(Scope.Decl)) |scope_decl| {
1763 scope_decl.decl.analysis = .{ .failure = err_msg };
1764 } else {
1765 unreachable;
1809 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);
1812 switch (scope.tag) {
1813 .decl => {
1814 const decl = scope.cast(Scope.DeclAnalysis).?.decl;
1815 switch (decl.analysis) {
1816 .initial_in_progress => decl.analysis = .initial_sema_failure,
1817 .repeat_in_progress => decl.analysis = .repeat_sema_failure,
1818 else => unreachable,
1819 }
1820 self.failed_decls.putAssumeCapacityNoClobber(decl, err_msg);
1821 },
1822 .block => {
1823 const func = scope.cast(Scope.Block).?.func;
1824 func.analysis = .failure;
1825 self.failed_fns.putAssumeCapacityNoClobber(func, err_msg);
1826 },
17661827 }
17671828 return error.AnalysisFail;
17681829 }
......@@ -1788,8 +1849,8 @@ pub const ErrorMsg = struct {
17881849
17891850 pub fn create(allocator: *Allocator, byte_offset: usize, comptime format: []const u8, args: var) !*ErrorMsg {
17901851 const self = try allocator.create(ErrorMsg);
1791 errdefer allocator.destroy(ErrorMsg);
1792 self.* = init(allocator, byte_offset, format, args);
1852 errdefer allocator.destroy(self);
1853 self.* = try init(allocator, byte_offset, format, args);
17931854 return self;
17941855 }
17951856
src-self-hosted/ir/text.zig+11-11
......@@ -631,7 +631,7 @@ const Parser = struct {
631631 if (try body_context.name_map.put(ident, ident_index)) |_| {
632632 return self.fail("redefinition of identifier '{}'", .{ident});
633633 }
634 try body_context.instructions.append(inst);
634 try body_context.instructions.append(self.allocator, inst);
635635 continue;
636636 },
637637 ' ', '\n' => continue,
......@@ -717,7 +717,7 @@ const Parser = struct {
717717 if (try self.global_name_map.put(ident, ident_index)) |_| {
718718 return self.fail("redefinition of identifier '{}'", .{ident});
719719 }
720 try self.decls.append(inst);
720 try self.decls.append(self.allocator, inst);
721721 },
722722 ' ', '\n' => self.i += 1,
723723 0 => break,
......@@ -885,7 +885,7 @@ const Parser = struct {
885885 var instructions = std.ArrayList(*Inst).init(&self.arena.allocator);
886886 while (true) {
887887 skipSpace(self);
888 try instructions.append(try parseParameterInst(self, body_ctx));
888 try instructions.append(self.allocator, try parseParameterInst(self, body_ctx));
889889 skipSpace(self);
890890 if (!eatByte(self, ',')) break;
891891 }
......@@ -991,7 +991,7 @@ const EmitZIR = struct {
991991 },
992992 .kw_args = .{},
993993 };
994 try self.decls.append(&export_inst.base);
994 try self.decls.append(self.allocator, &export_inst.base);
995995 }
996996 }
997997
......@@ -1018,7 +1018,7 @@ const EmitZIR = struct {
10181018 },
10191019 .kw_args = .{},
10201020 };
1021 try self.decls.append(&int_inst.base);
1021 try self.decls.append(self.allocator, &int_inst.base);
10221022 return &int_inst.base;
10231023 }
10241024
......@@ -1051,7 +1051,7 @@ const EmitZIR = struct {
10511051 },
10521052 .kw_args = .{},
10531053 };
1054 try self.decls.append(&as_inst.base);
1054 try self.decls.append(self.allocator, &as_inst.base);
10551055
10561056 return &as_inst.base;
10571057 },
......@@ -1085,7 +1085,7 @@ const EmitZIR = struct {
10851085 },
10861086 .kw_args = .{},
10871087 };
1088 try self.decls.append(&fn_inst.base);
1088 try self.decls.append(self.allocator, &fn_inst.base);
10891089 return &fn_inst.base;
10901090 },
10911091 else => |t| std.debug.panic("TODO implement emitTypedValue for {}", .{@tagName(t)}),
......@@ -1258,7 +1258,7 @@ const EmitZIR = struct {
12581258 break :blk &new_inst.base;
12591259 },
12601260 };
1261 try instructions.append(new_inst);
1261 try instructions.append(self.allocator, new_inst);
12621262 try inst_table.putNoClobber(inst, new_inst);
12631263 }
12641264 }
......@@ -1310,7 +1310,7 @@ const EmitZIR = struct {
13101310 .cc = ty.fnCallingConvention(),
13111311 },
13121312 };
1313 try self.decls.append(&fntype_inst.base);
1313 try self.decls.append(self.allocator, &fntype_inst.base);
13141314 return &fntype_inst.base;
13151315 },
13161316 else => std.debug.panic("TODO implement emitType for {}", .{ty}),
......@@ -1327,7 +1327,7 @@ const EmitZIR = struct {
13271327 },
13281328 .kw_args = .{},
13291329 };
1330 try self.decls.append(&primitive_inst.base);
1330 try self.decls.append(self.allocator, &primitive_inst.base);
13311331 return &primitive_inst.base;
13321332 }
13331333
......@@ -1340,7 +1340,7 @@ const EmitZIR = struct {
13401340 },
13411341 .kw_args = .{},
13421342 };
1343 try self.decls.append(&str_inst.base);
1343 try self.decls.append(self.allocator, &str_inst.base);
13441344 return &str_inst.base;
13451345 }
13461346};
src-self-hosted/value.zig+1-1
......@@ -160,7 +160,7 @@ pub const Value = extern union {
160160 .function => return out_stream.writeAll("(function)"),
161161 .decl_ref => return out_stream.writeAll("(decl ref)"),
162162 .elem_ptr => {
163 const elem_ptr = val.cast(Payload.Int_u64).?;
163 const elem_ptr = val.cast(Payload.ElemPtr).?;
164164 try out_stream.print("&[{}] ", .{elem_ptr.index});
165165 val = elem_ptr.array_ptr;
166166 },