| author | |
| committer | |
| log | 1634d45f1d53c8d7bfefa56ab4d2fa4cc8218b6d |
| tree | 85ec2c108a227da13542385d601364d7394e853b |
| parent | 939bd52c8a389993ab168ec9bb88c4e395045ac7 |
| signature |
12 files changed, 119 insertions(+), 38 deletions(-)
src/Compilation.zig+13-12| ... | @@ -1350,8 +1350,11 @@ pub fn totalErrorCount(self: *Compilation) usize { | ... | @@ -1350,8 +1350,11 @@ pub fn totalErrorCount(self: *Compilation) usize { |
| 1350 | var total: usize = self.failed_c_objects.items().len; | 1350 | var total: usize = self.failed_c_objects.items().len; |
| 1351 | 1351 | ||
| 1352 | if (self.bin_file.options.module) |module| { | 1352 | if (self.bin_file.options.module) |module| { |
| 1353 | total += module.failed_decls.items().len + | 1353 | for (module.failed_decls.items()) |entry| { |
| 1354 | module.failed_exports.items().len + | 1354 | assert(entry.value.items.len > 0); |
| 1355 | total += entry.value.items.len; | ||
| 1356 | } | ||
| 1357 | total += module.failed_exports.items().len + | ||
| 1355 | module.failed_files.items().len + | 1358 | module.failed_files.items().len + |
| 1356 | @boolToInt(module.failed_root_src_file != null); | 1359 | @boolToInt(module.failed_root_src_file != null); |
| 1357 | } | 1360 | } |
| ... | @@ -1385,9 +1388,11 @@ pub fn getAllErrorsAlloc(self: *Compilation) !AllErrors { | ... | @@ -1385,9 +1388,11 @@ pub fn getAllErrorsAlloc(self: *Compilation) !AllErrors { |
| 1385 | } | 1388 | } |
| 1386 | for (module.failed_decls.items()) |entry| { | 1389 | for (module.failed_decls.items()) |entry| { |
| 1387 | const decl = entry.key; | 1390 | const decl = entry.key; |
| 1388 | const err_msg = entry.value; | 1391 | const err_msg_list = entry.value; |
| 1389 | const source = try decl.scope.getSource(module); | 1392 | for (err_msg_list.items) |err_msg| { |
| 1390 | try AllErrors.add(&arena, &errors, decl.scope.subFilePath(), source, err_msg.*); | 1393 | const source = try decl.scope.getSource(module); |
| 1394 | try AllErrors.add(&arena, &errors, decl.scope.subFilePath(), source, err_msg.*); | ||
| 1395 | } | ||
| 1391 | } | 1396 | } |
| 1392 | for (module.failed_exports.items()) |entry| { | 1397 | for (module.failed_exports.items()) |entry| { |
| 1393 | const decl = entry.key.owner_decl; | 1398 | const decl = entry.key.owner_decl; |
| ... | @@ -1480,7 +1485,6 @@ pub fn performAllTheWork(self: *Compilation) error{ TimerUnsupported, OutOfMemor | ... | @@ -1480,7 +1485,6 @@ pub fn performAllTheWork(self: *Compilation) error{ TimerUnsupported, OutOfMemor |
| 1480 | } | 1485 | } |
| 1481 | 1486 | ||
| 1482 | assert(decl.typed_value.most_recent.typed_value.ty.hasCodeGenBits()); | 1487 | assert(decl.typed_value.most_recent.typed_value.ty.hasCodeGenBits()); |
| 1483 | |||
| 1484 | self.bin_file.updateDecl(module, decl) catch |err| { | 1488 | self.bin_file.updateDecl(module, decl) catch |err| { |
| 1485 | switch (err) { | 1489 | switch (err) { |
| 1486 | error.OutOfMemory => return error.OutOfMemory, | 1490 | error.OutOfMemory => return error.OutOfMemory, |
| ... | @@ -1488,8 +1492,7 @@ pub fn performAllTheWork(self: *Compilation) error{ TimerUnsupported, OutOfMemor | ... | @@ -1488,8 +1492,7 @@ pub fn performAllTheWork(self: *Compilation) error{ TimerUnsupported, OutOfMemor |
| 1488 | decl.analysis = .dependency_failure; | 1492 | decl.analysis = .dependency_failure; |
| 1489 | }, | 1493 | }, |
| 1490 | else => { | 1494 | else => { |
| 1491 | try module.failed_decls.ensureCapacity(module.gpa, module.failed_decls.items().len + 1); | 1495 | try module.addDeclErr(decl, try ErrorMsg.create( |
| 1492 | module.failed_decls.putAssumeCapacityNoClobber(decl, try ErrorMsg.create( | ||
| 1493 | module.gpa, | 1496 | module.gpa, |
| 1494 | decl.src(), | 1497 | decl.src(), |
| 1495 | "unable to codegen: {}", | 1498 | "unable to codegen: {}", |
| ... | @@ -1508,8 +1511,7 @@ pub fn performAllTheWork(self: *Compilation) error{ TimerUnsupported, OutOfMemor | ... | @@ -1508,8 +1511,7 @@ pub fn performAllTheWork(self: *Compilation) error{ TimerUnsupported, OutOfMemor |
| 1508 | decl.analysis = .dependency_failure; | 1511 | decl.analysis = .dependency_failure; |
| 1509 | }, | 1512 | }, |
| 1510 | else => { | 1513 | else => { |
| 1511 | try module.failed_decls.ensureCapacity(module.gpa, module.failed_decls.items().len + 1); | 1514 | try module.addDeclErr(decl, try ErrorMsg.create( |
| 1512 | module.failed_decls.putAssumeCapacityNoClobber(decl, try ErrorMsg.create( | ||
| 1513 | module.gpa, | 1515 | module.gpa, |
| 1514 | decl.src(), | 1516 | decl.src(), |
| 1515 | "unable to generate C header: {}", | 1517 | "unable to generate C header: {}", |
| ... | @@ -1531,8 +1533,7 @@ pub fn performAllTheWork(self: *Compilation) error{ TimerUnsupported, OutOfMemor | ... | @@ -1531,8 +1533,7 @@ pub fn performAllTheWork(self: *Compilation) error{ TimerUnsupported, OutOfMemor |
| 1531 | .update_line_number => |decl| { | 1533 | .update_line_number => |decl| { |
| 1532 | const module = self.bin_file.options.module.?; | 1534 | const module = self.bin_file.options.module.?; |
| 1533 | self.bin_file.updateDeclLineNumber(module, decl) catch |err| { | 1535 | self.bin_file.updateDeclLineNumber(module, decl) catch |err| { |
| 1534 | try module.failed_decls.ensureCapacity(module.gpa, module.failed_decls.items().len + 1); | 1536 | try module.addDeclErr(decl, try ErrorMsg.create( |
| 1535 | module.failed_decls.putAssumeCapacityNoClobber(decl, try ErrorMsg.create( | ||
| 1536 | module.gpa, | 1537 | module.gpa, |
| 1537 | decl.src(), | 1538 | decl.src(), |
| 1538 | "unable to update line number: {}", | 1539 | "unable to update line number: {}", |
src/Module.zig+29-17| ... | @@ -53,7 +53,7 @@ decl_table: std.ArrayHashMapUnmanaged(Scope.NameHash, *Decl, Scope.name_hash_has | ... | @@ -53,7 +53,7 @@ decl_table: std.ArrayHashMapUnmanaged(Scope.NameHash, *Decl, Scope.name_hash_has |
| 53 | /// The ErrorMsg memory is owned by the decl, using Module's general purpose allocator. | 53 | /// The ErrorMsg memory is owned by the decl, using Module's general purpose allocator. |
| 54 | /// Note that a Decl can succeed but the Fn it represents can fail. In this case, | 54 | /// Note that a Decl can succeed but the Fn it represents can fail. In this case, |
| 55 | /// a Decl can have a failed_decls entry but have analysis status of success. | 55 | /// a Decl can have a failed_decls entry but have analysis status of success. |
| 56 | failed_decls: std.AutoArrayHashMapUnmanaged(*Decl, *Compilation.ErrorMsg) = .{}, | 56 | failed_decls: std.AutoArrayHashMapUnmanaged(*Decl, ArrayListUnmanaged(*Compilation.ErrorMsg)) = .{}, |
| 57 | /// Using a map here for consistency with the other fields here. | 57 | /// Using a map here for consistency with the other fields here. |
| 58 | /// The ErrorMsg memory is owned by the `Scope`, using Module's general purpose allocator. | 58 | /// The ErrorMsg memory is owned by the `Scope`, using Module's general purpose allocator. |
| 59 | failed_files: std.AutoArrayHashMapUnmanaged(*Scope, *Compilation.ErrorMsg) = .{}, | 59 | failed_files: std.AutoArrayHashMapUnmanaged(*Scope, *Compilation.ErrorMsg) = .{}, |
| ... | @@ -845,8 +845,11 @@ pub fn deinit(self: *Module) void { | ... | @@ -845,8 +845,11 @@ pub fn deinit(self: *Module) void { |
| 845 | } | 845 | } |
| 846 | self.decl_table.deinit(gpa); | 846 | self.decl_table.deinit(gpa); |
| 847 | 847 | ||
| 848 | for (self.failed_decls.items()) |entry| { | 848 | for (self.failed_decls.items()) |*entry| { |
| 849 | entry.value.destroy(gpa); | 849 | for (entry.value.items) |compile_err| { |
| 850 | compile_err.destroy(gpa); | ||
| 851 | } | ||
| 852 | entry.value.deinit(gpa); | ||
| 850 | } | 853 | } |
| 851 | self.failed_decls.deinit(gpa); | 854 | self.failed_decls.deinit(gpa); |
| 852 | 855 | ||
| ... | @@ -942,8 +945,7 @@ pub fn ensureDeclAnalyzed(self: *Module, decl: *Decl) InnerError!void { | ... | @@ -942,8 +945,7 @@ pub fn ensureDeclAnalyzed(self: *Module, decl: *Decl) InnerError!void { |
| 942 | error.OutOfMemory => return error.OutOfMemory, | 945 | error.OutOfMemory => return error.OutOfMemory, |
| 943 | error.AnalysisFail => return error.AnalysisFail, | 946 | error.AnalysisFail => return error.AnalysisFail, |
| 944 | else => { | 947 | else => { |
| 945 | try self.failed_decls.ensureCapacity(self.gpa, self.failed_decls.items().len + 1); | 948 | try self.addDeclErr(decl, try Compilation.ErrorMsg.create( |
| 946 | self.failed_decls.putAssumeCapacityNoClobber(decl, try Compilation.ErrorMsg.create( | ||
| 947 | self.gpa, | 949 | self.gpa, |
| 948 | decl.src(), | 950 | decl.src(), |
| 949 | "unable to analyze: {}", | 951 | "unable to analyze: {}", |
| ... | @@ -1550,7 +1552,7 @@ pub fn analyzeContainer(self: *Module, container_scope: *Scope.Container) !void | ... | @@ -1550,7 +1552,7 @@ pub fn analyzeContainer(self: *Module, container_scope: *Scope.Container) !void |
| 1550 | decl.analysis = .sema_failure; | 1552 | decl.analysis = .sema_failure; |
| 1551 | const err_msg = try Compilation.ErrorMsg.create(self.gpa, tree.token_locs[name_tok].start, "redefinition of '{}'", .{decl.name}); | 1553 | const err_msg = try Compilation.ErrorMsg.create(self.gpa, tree.token_locs[name_tok].start, "redefinition of '{}'", .{decl.name}); |
| 1552 | errdefer err_msg.destroy(self.gpa); | 1554 | errdefer err_msg.destroy(self.gpa); |
| 1553 | try self.failed_decls.putNoClobber(self.gpa, decl, err_msg); | 1555 | try self.addDeclErr(decl, err_msg); |
| 1554 | } else { | 1556 | } else { |
| 1555 | if (!srcHashEql(decl.contents_hash, contents_hash)) { | 1557 | if (!srcHashEql(decl.contents_hash, contents_hash)) { |
| 1556 | try self.markOutdatedDecl(decl); | 1558 | try self.markOutdatedDecl(decl); |
| ... | @@ -1592,7 +1594,7 @@ pub fn analyzeContainer(self: *Module, container_scope: *Scope.Container) !void | ... | @@ -1592,7 +1594,7 @@ pub fn analyzeContainer(self: *Module, container_scope: *Scope.Container) !void |
| 1592 | decl.analysis = .sema_failure; | 1594 | decl.analysis = .sema_failure; |
| 1593 | const err_msg = try Compilation.ErrorMsg.create(self.gpa, name_loc.start, "redefinition of '{}'", .{decl.name}); | 1595 | const err_msg = try Compilation.ErrorMsg.create(self.gpa, name_loc.start, "redefinition of '{}'", .{decl.name}); |
| 1594 | errdefer err_msg.destroy(self.gpa); | 1596 | errdefer err_msg.destroy(self.gpa); |
| 1595 | try self.failed_decls.putNoClobber(self.gpa, decl, err_msg); | 1597 | try self.addDeclErr(decl, err_msg); |
| 1596 | } else if (!srcHashEql(decl.contents_hash, contents_hash)) { | 1598 | } else if (!srcHashEql(decl.contents_hash, contents_hash)) { |
| 1597 | try self.markOutdatedDecl(decl); | 1599 | try self.markOutdatedDecl(decl); |
| 1598 | decl.contents_hash = contents_hash; | 1600 | decl.contents_hash = contents_hash; |
| ... | @@ -1718,8 +1720,11 @@ pub fn deleteDecl(self: *Module, decl: *Decl) !void { | ... | @@ -1718,8 +1720,11 @@ pub fn deleteDecl(self: *Module, decl: *Decl) !void { |
| 1718 | try self.markOutdatedDecl(dep); | 1720 | try self.markOutdatedDecl(dep); |
| 1719 | } | 1721 | } |
| 1720 | } | 1722 | } |
| 1721 | if (self.failed_decls.remove(decl)) |entry| { | 1723 | if (self.failed_decls.remove(decl)) |*entry| { |
| 1722 | entry.value.destroy(self.gpa); | 1724 | for (entry.value.items) |compile_err| { |
| 1725 | compile_err.destroy(self.gpa); | ||
| 1726 | } | ||
| 1727 | entry.value.deinit(self.gpa); | ||
| 1723 | } | 1728 | } |
| 1724 | self.deleteDeclExports(decl); | 1729 | self.deleteDeclExports(decl); |
| 1725 | self.comp.bin_file.freeDecl(decl); | 1730 | self.comp.bin_file.freeDecl(decl); |
| ... | @@ -1798,8 +1803,11 @@ pub fn analyzeFnBody(self: *Module, decl: *Decl, func: *Fn) !void { | ... | @@ -1798,8 +1803,11 @@ pub fn analyzeFnBody(self: *Module, decl: *Decl, func: *Fn) !void { |
| 1798 | fn markOutdatedDecl(self: *Module, decl: *Decl) !void { | 1803 | fn markOutdatedDecl(self: *Module, decl: *Decl) !void { |
| 1799 | log.debug("mark {} outdated\n", .{decl.name}); | 1804 | log.debug("mark {} outdated\n", .{decl.name}); |
| 1800 | try self.comp.work_queue.writeItem(.{ .analyze_decl = decl }); | 1805 | try self.comp.work_queue.writeItem(.{ .analyze_decl = decl }); |
| 1801 | if (self.failed_decls.remove(decl)) |entry| { | 1806 | if (self.failed_decls.remove(decl)) |*entry| { |
| 1802 | entry.value.destroy(self.gpa); | 1807 | for (entry.value.items) |compile_err| { |
| 1808 | compile_err.destroy(self.gpa); | ||
| 1809 | } | ||
| 1810 | entry.value.deinit(self.gpa); | ||
| 1803 | } | 1811 | } |
| 1804 | decl.analysis = .outdated; | 1812 | decl.analysis = .outdated; |
| 1805 | } | 1813 | } |
| ... | @@ -2944,10 +2952,14 @@ pub fn failNode( | ... | @@ -2944,10 +2952,14 @@ pub fn failNode( |
| 2944 | return self.fail(scope, src, format, args); | 2952 | return self.fail(scope, src, format, args); |
| 2945 | } | 2953 | } |
| 2946 | 2954 | ||
| 2955 | pub fn addDeclErr(self: *Module, decl: *Decl, err: *Compilation.ErrorMsg) error{OutOfMemory}!void { | ||
| 2956 | const entry = try self.failed_decls.getOrPutValue(self.gpa, decl, .{}); | ||
| 2957 | try entry.value.append(self.gpa, err); | ||
| 2958 | } | ||
| 2959 | |||
| 2947 | fn failWithOwnedErrorMsg(self: *Module, scope: *Scope, src: usize, err_msg: *Compilation.ErrorMsg) InnerError { | 2960 | fn failWithOwnedErrorMsg(self: *Module, scope: *Scope, src: usize, err_msg: *Compilation.ErrorMsg) InnerError { |
| 2948 | { | 2961 | { |
| 2949 | errdefer err_msg.destroy(self.gpa); | 2962 | errdefer err_msg.destroy(self.gpa); |
| 2950 | try self.failed_decls.ensureCapacity(self.gpa, self.failed_decls.items().len + 1); | ||
| 2951 | try self.failed_files.ensureCapacity(self.gpa, self.failed_files.items().len + 1); | 2963 | try self.failed_files.ensureCapacity(self.gpa, self.failed_files.items().len + 1); |
| 2952 | } | 2964 | } |
| 2953 | switch (scope.tag) { | 2965 | switch (scope.tag) { |
| ... | @@ -2955,7 +2967,7 @@ fn failWithOwnedErrorMsg(self: *Module, scope: *Scope, src: usize, err_msg: *Com | ... | @@ -2955,7 +2967,7 @@ fn failWithOwnedErrorMsg(self: *Module, scope: *Scope, src: usize, err_msg: *Com |
| 2955 | const decl = scope.cast(Scope.DeclAnalysis).?.decl; | 2967 | const decl = scope.cast(Scope.DeclAnalysis).?.decl; |
| 2956 | decl.analysis = .sema_failure; | 2968 | decl.analysis = .sema_failure; |
| 2957 | decl.generation = self.generation; | 2969 | decl.generation = self.generation; |
| 2958 | self.failed_decls.putAssumeCapacityNoClobber(decl, err_msg); | 2970 | try self.addDeclErr(decl, err_msg); |
| 2959 | }, | 2971 | }, |
| 2960 | .block => { | 2972 | .block => { |
| 2961 | const block = scope.cast(Scope.Block).?; | 2973 | const block = scope.cast(Scope.Block).?; |
| ... | @@ -2965,25 +2977,25 @@ fn failWithOwnedErrorMsg(self: *Module, scope: *Scope, src: usize, err_msg: *Com | ... | @@ -2965,25 +2977,25 @@ fn failWithOwnedErrorMsg(self: *Module, scope: *Scope, src: usize, err_msg: *Com |
| 2965 | block.decl.analysis = .sema_failure; | 2977 | block.decl.analysis = .sema_failure; |
| 2966 | block.decl.generation = self.generation; | 2978 | block.decl.generation = self.generation; |
| 2967 | } | 2979 | } |
| 2968 | self.failed_decls.putAssumeCapacityNoClobber(block.decl, err_msg); | 2980 | try self.addDeclErr(block.decl, err_msg); |
| 2969 | }, | 2981 | }, |
| 2970 | .gen_zir => { | 2982 | .gen_zir => { |
| 2971 | const gen_zir = scope.cast(Scope.GenZIR).?; | 2983 | const gen_zir = scope.cast(Scope.GenZIR).?; |
| 2972 | gen_zir.decl.analysis = .sema_failure; | 2984 | gen_zir.decl.analysis = .sema_failure; |
| 2973 | gen_zir.decl.generation = self.generation; | 2985 | gen_zir.decl.generation = self.generation; |
| 2974 | self.failed_decls.putAssumeCapacityNoClobber(gen_zir.decl, err_msg); | 2986 | try self.addDeclErr(gen_zir.decl, err_msg); |
| 2975 | }, | 2987 | }, |
| 2976 | .local_val => { | 2988 | .local_val => { |
| 2977 | const gen_zir = scope.cast(Scope.LocalVal).?.gen_zir; | 2989 | const gen_zir = scope.cast(Scope.LocalVal).?.gen_zir; |
| 2978 | gen_zir.decl.analysis = .sema_failure; | 2990 | gen_zir.decl.analysis = .sema_failure; |
| 2979 | gen_zir.decl.generation = self.generation; | 2991 | gen_zir.decl.generation = self.generation; |
| 2980 | self.failed_decls.putAssumeCapacityNoClobber(gen_zir.decl, err_msg); | 2992 | try self.addDeclErr(gen_zir.decl, err_msg); |
| 2981 | }, | 2993 | }, |
| 2982 | .local_ptr => { | 2994 | .local_ptr => { |
| 2983 | const gen_zir = scope.cast(Scope.LocalPtr).?.gen_zir; | 2995 | const gen_zir = scope.cast(Scope.LocalPtr).?.gen_zir; |
| 2984 | gen_zir.decl.analysis = .sema_failure; | 2996 | gen_zir.decl.analysis = .sema_failure; |
| 2985 | gen_zir.decl.generation = self.generation; | 2997 | gen_zir.decl.generation = self.generation; |
| 2986 | self.failed_decls.putAssumeCapacityNoClobber(gen_zir.decl, err_msg); | 2998 | try self.addDeclErr(gen_zir.decl, err_msg); |
| 2987 | }, | 2999 | }, |
| 2988 | .zir_module => { | 3000 | .zir_module => { |
| 2989 | const zir_module = scope.cast(Scope.ZIRModule).?; | 3001 | const zir_module = scope.cast(Scope.ZIRModule).?; |
src/astgen.zig+13| ... | @@ -2248,6 +2248,17 @@ fn import(mod: *Module, scope: *Scope, call: *ast.Node.BuiltinCall) InnerError!* | ... | @@ -2248,6 +2248,17 @@ fn import(mod: *Module, scope: *Scope, call: *ast.Node.BuiltinCall) InnerError!* |
| 2248 | return addZIRUnOp(mod, scope, src, .import, target); | 2248 | return addZIRUnOp(mod, scope, src, .import, target); |
| 2249 | } | 2249 | } |
| 2250 | 2250 | ||
| 2251 | fn compileLog(mod: *Module, scope: *Scope, call: *ast.Node.BuiltinCall) InnerError!*zir.Inst { | ||
| 2252 | const tree = scope.tree(); | ||
| 2253 | const arena = scope.arena(); | ||
| 2254 | const src = tree.token_locs[call.builtin_token].start; | ||
| 2255 | const params = call.params(); | ||
| 2256 | var targets = try arena.alloc(*zir.Inst, params.len); | ||
| 2257 | for (params) |param, param_i| | ||
| 2258 | targets[param_i] = try expr(mod, scope, .none, param); | ||
| 2259 | return addZIRInst(mod, scope, src, zir.Inst.CompileLog, .{ .to_log = targets }, .{}); | ||
| 2260 | } | ||
| 2261 | |||
| 2251 | fn typeOf(mod: *Module, scope: *Scope, rl: ResultLoc, call: *ast.Node.BuiltinCall) InnerError!*zir.Inst { | 2262 | fn typeOf(mod: *Module, scope: *Scope, rl: ResultLoc, call: *ast.Node.BuiltinCall) InnerError!*zir.Inst { |
| 2252 | const tree = scope.tree(); | 2263 | const tree = scope.tree(); |
| 2253 | const arena = scope.arena(); | 2264 | const arena = scope.arena(); |
| ... | @@ -2291,6 +2302,8 @@ fn builtinCall(mod: *Module, scope: *Scope, rl: ResultLoc, call: *ast.Node.Built | ... | @@ -2291,6 +2302,8 @@ fn builtinCall(mod: *Module, scope: *Scope, rl: ResultLoc, call: *ast.Node.Built |
| 2291 | return rlWrap(mod, scope, rl, try addZIRNoOp(mod, scope, src, .breakpoint)); | 2302 | return rlWrap(mod, scope, rl, try addZIRNoOp(mod, scope, src, .breakpoint)); |
| 2292 | } else if (mem.eql(u8, builtin_name, "@import")) { | 2303 | } else if (mem.eql(u8, builtin_name, "@import")) { |
| 2293 | return rlWrap(mod, scope, rl, try import(mod, scope, call)); | 2304 | return rlWrap(mod, scope, rl, try import(mod, scope, call)); |
| 2305 | } else if (mem.eql(u8, builtin_name, "@compileLog")) { | ||
| 2306 | return compileLog(mod, scope, call); | ||
| 2294 | } else { | 2307 | } else { |
| 2295 | return mod.failTok(scope, call.builtin_token, "invalid builtin function: '{}'", .{builtin_name}); | 2308 | return mod.failTok(scope, call.builtin_token, "invalid builtin function: '{}'", .{builtin_name}); |
| 2296 | } | 2309 | } |
src/codegen/c.zig+1-1| ... | @@ -106,7 +106,7 @@ pub fn generateHeader( | ... | @@ -106,7 +106,7 @@ pub fn generateHeader( |
| 106 | const writer = header.buf.writer(); | 106 | const writer = header.buf.writer(); |
| 107 | renderFunctionSignature(&ctx, header, writer, decl) catch |err| { | 107 | renderFunctionSignature(&ctx, header, writer, decl) catch |err| { |
| 108 | if (err == error.AnalysisFail) { | 108 | if (err == error.AnalysisFail) { |
| 109 | try module.failed_decls.put(module.gpa, decl, ctx.error_msg); | 109 | try module.addDeclErr(decl, ctx.error_msg); |
| 110 | } | 110 | } |
| 111 | return err; | 111 | return err; |
| 112 | }; | 112 | }; |
src/link/C.zig+1-1| ... | @@ -106,7 +106,7 @@ pub fn deinit(self: *C) void { | ... | @@ -106,7 +106,7 @@ pub fn deinit(self: *C) void { |
| 106 | pub fn updateDecl(self: *C, module: *Module, decl: *Module.Decl) !void { | 106 | pub fn updateDecl(self: *C, module: *Module, decl: *Module.Decl) !void { |
| 107 | codegen.generate(self, decl) catch |err| { | 107 | codegen.generate(self, decl) catch |err| { |
| 108 | if (err == error.AnalysisFail) { | 108 | if (err == error.AnalysisFail) { |
| 109 | try module.failed_decls.put(module.gpa, decl, self.error_msg); | 109 | try module.addDeclErr(decl, self.error_msg); |
| 110 | } | 110 | } |
| 111 | return err; | 111 | return err; |
| 112 | }; | 112 | }; |
src/link/Coff.zig+1-1| ... | @@ -658,7 +658,7 @@ pub fn updateDecl(self: *Coff, module: *Module, decl: *Module.Decl) !void { | ... | @@ -658,7 +658,7 @@ pub fn updateDecl(self: *Coff, module: *Module, decl: *Module.Decl) !void { |
| 658 | .appended => code_buffer.items, | 658 | .appended => code_buffer.items, |
| 659 | .fail => |em| { | 659 | .fail => |em| { |
| 660 | decl.analysis = .codegen_failure; | 660 | decl.analysis = .codegen_failure; |
| 661 | try module.failed_decls.put(module.gpa, decl, em); | 661 | try module.addDeclErr(decl, em); |
| 662 | return; | 662 | return; |
| 663 | }, | 663 | }, |
| 664 | }; | 664 | }; |
src/link/Elf.zig+1-1| ... | @@ -2248,7 +2248,7 @@ pub fn updateDecl(self: *Elf, module: *Module, decl: *Module.Decl) !void { | ... | @@ -2248,7 +2248,7 @@ pub fn updateDecl(self: *Elf, module: *Module, decl: *Module.Decl) !void { |
| 2248 | .appended => code_buffer.items, | 2248 | .appended => code_buffer.items, |
| 2249 | .fail => |em| { | 2249 | .fail => |em| { |
| 2250 | decl.analysis = .codegen_failure; | 2250 | decl.analysis = .codegen_failure; |
| 2251 | try module.failed_decls.put(module.gpa, decl, em); | 2251 | try module.addDeclErr(decl, em); |
| 2252 | return; | 2252 | return; |
| 2253 | }, | 2253 | }, |
| 2254 | }; | 2254 | }; |
src/link/MachO.zig+1-1| ... | @@ -1062,7 +1062,7 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void { | ... | @@ -1062,7 +1062,7 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void { |
| 1062 | .appended => code_buffer.items, | 1062 | .appended => code_buffer.items, |
| 1063 | .fail => |em| { | 1063 | .fail => |em| { |
| 1064 | decl.analysis = .codegen_failure; | 1064 | decl.analysis = .codegen_failure; |
| 1065 | try module.failed_decls.put(module.gpa, decl, em); | 1065 | try module.addDeclErr(decl, em); |
| 1066 | return; | 1066 | return; |
| 1067 | }, | 1067 | }, |
| 1068 | }; | 1068 | }; |
src/value.zig+1-1| ... | @@ -350,7 +350,7 @@ pub const Value = extern union { | ... | @@ -350,7 +350,7 @@ pub const Value = extern union { |
| 350 | val = elem_ptr.array_ptr; | 350 | val = elem_ptr.array_ptr; |
| 351 | }, | 351 | }, |
| 352 | .empty_array => return out_stream.writeAll(".{}"), | 352 | .empty_array => return out_stream.writeAll(".{}"), |
| 353 | .enum_literal => return out_stream.print(".{z}", .{self.cast(Payload.Bytes).?.data}), | 353 | .enum_literal => return out_stream.print(".{z}", .{@fieldParentPtr(Payload.Bytes, "base", self.ptr_otherwise).data}), |
| 354 | .bytes => return out_stream.print("\"{Z}\"", .{self.cast(Payload.Bytes).?.data}), | 354 | .bytes => return out_stream.print("\"{Z}\"", .{self.cast(Payload.Bytes).?.data}), |
| 355 | .repeated => { | 355 | .repeated => { |
| 356 | try out_stream.writeAll("(repeated) "); | 356 | try out_stream.writeAll("(repeated) "); |
src/zir.zig+20-3| ... | @@ -122,6 +122,8 @@ pub const Inst = struct { | ... | @@ -122,6 +122,8 @@ pub const Inst = struct { |
| 122 | coerce_to_ptr_elem, | 122 | coerce_to_ptr_elem, |
| 123 | /// Emit an error message and fail compilation. | 123 | /// Emit an error message and fail compilation. |
| 124 | compileerror, | 124 | compileerror, |
| 125 | /// Log compile time variables and emit an error message. | ||
| 126 | compilelog, | ||
| 125 | /// Conditional branch. Splits control flow based on a boolean condition value. | 127 | /// Conditional branch. Splits control flow based on a boolean condition value. |
| 126 | condbr, | 128 | condbr, |
| 127 | /// Special case, has no textual representation. | 129 | /// Special case, has no textual representation. |
| ... | @@ -386,6 +388,7 @@ pub const Inst = struct { | ... | @@ -386,6 +388,7 @@ pub const Inst = struct { |
| 386 | .declval_in_module => DeclValInModule, | 388 | .declval_in_module => DeclValInModule, |
| 387 | .coerce_result_block_ptr => CoerceResultBlockPtr, | 389 | .coerce_result_block_ptr => CoerceResultBlockPtr, |
| 388 | .compileerror => CompileError, | 390 | .compileerror => CompileError, |
| 391 | .compilelog => CompileLog, | ||
| 389 | .loop => Loop, | 392 | .loop => Loop, |
| 390 | .@"const" => Const, | 393 | .@"const" => Const, |
| 391 | .str => Str, | 394 | .str => Str, |
| ... | @@ -513,6 +516,7 @@ pub const Inst = struct { | ... | @@ -513,6 +516,7 @@ pub const Inst = struct { |
| 513 | .slice_start, | 516 | .slice_start, |
| 514 | .import, | 517 | .import, |
| 515 | .switch_range, | 518 | .switch_range, |
| 519 | .compilelog, | ||
| 516 | .typeof_peer, | 520 | .typeof_peer, |
| 517 | => false, | 521 | => false, |
| 518 | 522 | ||
| ... | @@ -707,6 +711,19 @@ pub const Inst = struct { | ... | @@ -707,6 +711,19 @@ pub const Inst = struct { |
| 707 | kw_args: struct {}, | 711 | kw_args: struct {}, |
| 708 | }; | 712 | }; |
| 709 | 713 | ||
| 714 | pub const CompileLog = struct { | ||
| 715 | pub const base_tag = Tag.compilelog; | ||
| 716 | base: Inst, | ||
| 717 | |||
| 718 | positionals: struct { | ||
| 719 | to_log: []*Inst, | ||
| 720 | }, | ||
| 721 | kw_args: struct { | ||
| 722 | /// If we have seen it already so don't make another error | ||
| 723 | seen: bool = false, | ||
| 724 | }, | ||
| 725 | }; | ||
| 726 | |||
| 710 | pub const Const = struct { | 727 | pub const Const = struct { |
| 711 | pub const base_tag = Tag.@"const"; | 728 | pub const base_tag = Tag.@"const"; |
| 712 | base: Inst, | 729 | base: Inst, |
| ... | @@ -1925,7 +1942,7 @@ const EmitZIR = struct { | ... | @@ -1925,7 +1942,7 @@ const EmitZIR = struct { |
| 1925 | .sema_failure, | 1942 | .sema_failure, |
| 1926 | .sema_failure_retryable, | 1943 | .sema_failure_retryable, |
| 1927 | .dependency_failure, | 1944 | .dependency_failure, |
| 1928 | => if (self.old_module.failed_decls.get(ir_decl)) |err_msg| { | 1945 | => if (self.old_module.failed_decls.get(ir_decl)) |err_msg_list| { |
| 1929 | const fail_inst = try self.arena.allocator.create(Inst.CompileError); | 1946 | const fail_inst = try self.arena.allocator.create(Inst.CompileError); |
| 1930 | fail_inst.* = .{ | 1947 | fail_inst.* = .{ |
| 1931 | .base = .{ | 1948 | .base = .{ |
| ... | @@ -1933,7 +1950,7 @@ const EmitZIR = struct { | ... | @@ -1933,7 +1950,7 @@ const EmitZIR = struct { |
| 1933 | .tag = Inst.CompileError.base_tag, | 1950 | .tag = Inst.CompileError.base_tag, |
| 1934 | }, | 1951 | }, |
| 1935 | .positionals = .{ | 1952 | .positionals = .{ |
| 1936 | .msg = try self.arena.allocator.dupe(u8, err_msg.msg), | 1953 | .msg = try self.arena.allocator.dupe(u8, err_msg_list.items[0].msg), |
| 1937 | }, | 1954 | }, |
| 1938 | .kw_args = .{}, | 1955 | .kw_args = .{}, |
| 1939 | }; | 1956 | }; |
| ... | @@ -2055,7 +2072,7 @@ const EmitZIR = struct { | ... | @@ -2055,7 +2072,7 @@ const EmitZIR = struct { |
| 2055 | try self.emitBody(body, &inst_table, &instructions); | 2072 | try self.emitBody(body, &inst_table, &instructions); |
| 2056 | }, | 2073 | }, |
| 2057 | .sema_failure => { | 2074 | .sema_failure => { |
| 2058 | const err_msg = self.old_module.failed_decls.get(module_fn.owner_decl).?; | 2075 | const err_msg = self.old_module.failed_decls.get(module_fn.owner_decl).?.items[0]; |
| 2059 | const fail_inst = try self.arena.allocator.create(Inst.CompileError); | 2076 | const fail_inst = try self.arena.allocator.create(Inst.CompileError); |
| 2060 | fail_inst.* = .{ | 2077 | fail_inst.* = .{ |
| 2061 | .base = .{ | 2078 | .base = .{ |
src/zir_sema.zig+23| ... | @@ -43,6 +43,7 @@ pub fn analyzeInst(mod: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError! | ... | @@ -43,6 +43,7 @@ pub fn analyzeInst(mod: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError! |
| 43 | .coerce_result_ptr => return analyzeInstCoerceResultPtr(mod, scope, old_inst.castTag(.coerce_result_ptr).?), | 43 | .coerce_result_ptr => return analyzeInstCoerceResultPtr(mod, scope, old_inst.castTag(.coerce_result_ptr).?), |
| 44 | .coerce_to_ptr_elem => return analyzeInstCoerceToPtrElem(mod, scope, old_inst.castTag(.coerce_to_ptr_elem).?), | 44 | .coerce_to_ptr_elem => return analyzeInstCoerceToPtrElem(mod, scope, old_inst.castTag(.coerce_to_ptr_elem).?), |
| 45 | .compileerror => return analyzeInstCompileError(mod, scope, old_inst.castTag(.compileerror).?), | 45 | .compileerror => return analyzeInstCompileError(mod, scope, old_inst.castTag(.compileerror).?), |
| 46 | .compilelog => return analyzeInstCompileLog(mod, scope, old_inst.castTag(.compilelog).?), | ||
| 46 | .@"const" => return analyzeInstConst(mod, scope, old_inst.castTag(.@"const").?), | 47 | .@"const" => return analyzeInstConst(mod, scope, old_inst.castTag(.@"const").?), |
| 47 | .dbg_stmt => return analyzeInstDbgStmt(mod, scope, old_inst.castTag(.dbg_stmt).?), | 48 | .dbg_stmt => return analyzeInstDbgStmt(mod, scope, old_inst.castTag(.dbg_stmt).?), |
| 48 | .declref => return analyzeInstDeclRef(mod, scope, old_inst.castTag(.declref).?), | 49 | .declref => return analyzeInstDeclRef(mod, scope, old_inst.castTag(.declref).?), |
| ... | @@ -489,6 +490,28 @@ fn analyzeInstCompileError(mod: *Module, scope: *Scope, inst: *zir.Inst.CompileE | ... | @@ -489,6 +490,28 @@ fn analyzeInstCompileError(mod: *Module, scope: *Scope, inst: *zir.Inst.CompileE |
| 489 | return mod.fail(scope, inst.base.src, "{}", .{inst.positionals.msg}); | 490 | return mod.fail(scope, inst.base.src, "{}", .{inst.positionals.msg}); |
| 490 | } | 491 | } |
| 491 | 492 | ||
| 493 | fn analyzeInstCompileLog(mod: *Module, scope: *Scope, inst: *zir.Inst.CompileLog) InnerError!*Inst { | ||
| 494 | std.debug.print("| ", .{}); | ||
| 495 | for (inst.positionals.to_log) |item, i| { | ||
| 496 | const to_log = try resolveInst(mod, scope, item); | ||
| 497 | if (to_log.value()) |val| { | ||
| 498 | std.debug.print("{}", .{val}); | ||
| 499 | } else { | ||
| 500 | std.debug.print("(runtime value)", .{}); | ||
| 501 | } | ||
| 502 | if (i != inst.positionals.to_log.len - 1) std.debug.print(", ", .{}); | ||
| 503 | } | ||
| 504 | std.debug.print("\n", .{}); | ||
| 505 | if (!inst.kw_args.seen) { | ||
| 506 | inst.kw_args.seen = true; // so that we do not give multiple compile errors if it gets evaled twice | ||
| 507 | switch (mod.fail(scope, inst.base.src, "found compile log statement", .{})) { | ||
| 508 | error.AnalysisFail => {}, // analysis continues | ||
| 509 | else => |e| return e, | ||
| 510 | } | ||
| 511 | } | ||
| 512 | return mod.constVoid(scope, inst.base.src); | ||
| 513 | } | ||
| 514 | |||
| 492 | fn analyzeInstArg(mod: *Module, scope: *Scope, inst: *zir.Inst.Arg) InnerError!*Inst { | 515 | fn analyzeInstArg(mod: *Module, scope: *Scope, inst: *zir.Inst.Arg) InnerError!*Inst { |
| 493 | const b = try mod.requireRuntimeBlock(scope, inst.base.src); | 516 | const b = try mod.requireRuntimeBlock(scope, inst.base.src); |
| 494 | const fn_ty = b.func.?.owner_decl.typed_value.most_recent.typed_value.ty; | 517 | const fn_ty = b.func.?.owner_decl.typed_value.most_recent.typed_value.ty; |
test/stage2/test.zig+15| ... | @@ -1171,6 +1171,21 @@ pub fn addCases(ctx: *TestContext) !void { | ... | @@ -1171,6 +1171,21 @@ pub fn addCases(ctx: *TestContext) !void { |
| 1171 | \\fn entry() void {} | 1171 | \\fn entry() void {} |
| 1172 | , &[_][]const u8{":2:4: error: redefinition of 'entry'"}); | 1172 | , &[_][]const u8{":2:4: error: redefinition of 'entry'"}); |
| 1173 | 1173 | ||
| 1174 | ctx.compileError("compileLog", linux_x64, | ||
| 1175 | \\export fn _start() noreturn { | ||
| 1176 | \\ const b = true; | ||
| 1177 | \\ var f: u32 = 1; | ||
| 1178 | \\ @compileLog(b, 20, f, x, .foo); | ||
| 1179 | \\ var y: u32 = true; | ||
| 1180 | \\ unreachable; | ||
| 1181 | \\} | ||
| 1182 | \\fn x() void {} | ||
| 1183 | , &[_][]const u8{ | ||
| 1184 | ":4:3: error: found compile log statement", ":5:16: error: expected u32, found bool", | ||
| 1185 | }); | ||
| 1186 | |||
| 1187 | // "| true, 20, (runtime value), (function)" // TODO if this is here it invalidates the compile error checker. Need a way to check though. | ||
| 1188 | |||
| 1174 | { | 1189 | { |
| 1175 | var case = ctx.obj("variable shadowing", linux_x64); | 1190 | var case = ctx.obj("variable shadowing", linux_x64); |
| 1176 | case.addError( | 1191 | case.addError( |