| ... | @@ -77,7 +77,7 @@ embed_file_work_queue: std.fifo.LinearFifo(*Module.EmbedFile, .Dynamic), | ... | @@ -77,7 +77,7 @@ embed_file_work_queue: std.fifo.LinearFifo(*Module.EmbedFile, .Dynamic), |
| 77 | | 77 | |
| 78 | /// The ErrorMsg memory is owned by the `CObject`, using Compilation's general purpose allocator. | 78 | /// The ErrorMsg memory is owned by the `CObject`, using Compilation's general purpose allocator. |
| 79 | /// This data is accessed by multiple threads and is protected by `mutex`. | 79 | /// This data is accessed by multiple threads and is protected by `mutex`. |
| 80 | failed_c_objects: std.AutoArrayHashMapUnmanaged(*CObject, *CObject.ErrorMsg) = .{}, | 80 | failed_c_objects: std.AutoArrayHashMapUnmanaged(*CObject, *CObject.Diag.Bundle) = .{}, |
| 81 | | 81 | |
| 82 | /// The ErrorBundle memory is owned by the `Win32Resource`, using Compilation's general purpose allocator. | 82 | /// The ErrorBundle memory is owned by the `Win32Resource`, using Compilation's general purpose allocator. |
| 83 | /// This data is accessed by multiple threads and is protected by `mutex`. | 83 | /// This data is accessed by multiple threads and is protected by `mutex`. |
| ... | @@ -318,15 +318,286 @@ pub const CObject = struct { | ... | @@ -318,15 +318,286 @@ pub const CObject = struct { |
| 318 | failure_retryable, | 318 | failure_retryable, |
| 319 | }, | 319 | }, |
| 320 | | 320 | |
| 321 | pub const ErrorMsg = struct { | 321 | pub const Diag = struct { |
| 322 | msg: []const u8, | 322 | level: u32 = 0, |
| 323 | line: u32, | 323 | category: u32 = 0, |
| 324 | column: u32, | 324 | msg: []const u8 = &.{}, |
| | 325 | src_loc: SrcLoc = .{}, |
| | 326 | src_ranges: []const SrcRange = &.{}, |
| | 327 | sub_diags: []const Diag = &.{}, |
| | 328 | |
| | 329 | pub const SrcLoc = struct { |
| | 330 | file: u32 = 0, |
| | 331 | line: u32 = 0, |
| | 332 | column: u32 = 0, |
| | 333 | offset: u32 = 0, |
| | 334 | }; |
| | 335 | |
| | 336 | pub const SrcRange = struct { |
| | 337 | start: SrcLoc = .{}, |
| | 338 | end: SrcLoc = .{}, |
| | 339 | }; |
| | 340 | |
| | 341 | pub fn deinit(diag: *Diag, gpa: Allocator) void { |
| | 342 | gpa.free(diag.msg); |
| | 343 | gpa.free(diag.src_ranges); |
| | 344 | for (diag.sub_diags) |sub_diag| { |
| | 345 | var sub_diag_mut = sub_diag; |
| | 346 | sub_diag_mut.deinit(gpa); |
| | 347 | } |
| | 348 | gpa.free(diag.sub_diags); |
| | 349 | diag.* = undefined; |
| | 350 | } |
| 325 | | 351 | |
| 326 | pub fn destroy(em: *ErrorMsg, gpa: Allocator) void { | 352 | pub fn count(diag: Diag) u32 { |
| 327 | gpa.free(em.msg); | 353 | var total: u32 = 1; |
| 328 | gpa.destroy(em); | 354 | for (diag.sub_diags) |sub_diag| total += sub_diag.count(); |
| | 355 | return total; |
| 329 | } | 356 | } |
| | 357 | |
| | 358 | pub fn addToErrorBundle(diag: Diag, eb: *ErrorBundle.Wip, bundle: Bundle, note: *u32) !void { |
| | 359 | const err_msg = try eb.addErrorMessage(try diag.toErrorMessage(eb, bundle, 0)); |
| | 360 | eb.extra.items[note.*] = @intFromEnum(err_msg); |
| | 361 | note.* += 1; |
| | 362 | for (diag.sub_diags) |sub_diag| try sub_diag.addToErrorBundle(eb, bundle, note); |
| | 363 | } |
| | 364 | |
| | 365 | pub fn toErrorMessage( |
| | 366 | diag: Diag, |
| | 367 | eb: *ErrorBundle.Wip, |
| | 368 | bundle: Bundle, |
| | 369 | notes_len: u32, |
| | 370 | ) !ErrorBundle.ErrorMessage { |
| | 371 | var start = diag.src_loc.offset; |
| | 372 | var end = diag.src_loc.offset; |
| | 373 | for (diag.src_ranges) |src_range| { |
| | 374 | if (src_range.start.file == diag.src_loc.file and |
| | 375 | src_range.start.line == diag.src_loc.line) |
| | 376 | { |
| | 377 | start = @min(src_range.start.offset, start); |
| | 378 | } |
| | 379 | if (src_range.end.file == diag.src_loc.file and |
| | 380 | src_range.end.line == diag.src_loc.line) |
| | 381 | { |
| | 382 | end = @max(src_range.end.offset, end); |
| | 383 | } |
| | 384 | } |
| | 385 | |
| | 386 | const file_name = bundle.file_names.get(diag.src_loc.file) orelse ""; |
| | 387 | const source_line = source_line: { |
| | 388 | if (diag.src_loc.offset == 0 or diag.src_loc.column == 0) break :source_line 0; |
| | 389 | |
| | 390 | const file = std.fs.cwd().openFile(file_name, .{}) catch break :source_line 0; |
| | 391 | defer file.close(); |
| | 392 | file.seekTo(diag.src_loc.offset + 1 - diag.src_loc.column) catch break :source_line 0; |
| | 393 | |
| | 394 | var line = std.ArrayList(u8).init(eb.gpa); |
| | 395 | defer line.deinit(); |
| | 396 | file.reader().readUntilDelimiterArrayList(&line, '\n', 1 << 10) catch break :source_line 0; |
| | 397 | |
| | 398 | break :source_line try eb.addString(line.items); |
| | 399 | }; |
| | 400 | |
| | 401 | return .{ |
| | 402 | .msg = try eb.addString(diag.msg), |
| | 403 | .src_loc = try eb.addSourceLocation(.{ |
| | 404 | .src_path = try eb.addString(file_name), |
| | 405 | .line = diag.src_loc.line -| 1, |
| | 406 | .column = diag.src_loc.column -| 1, |
| | 407 | .span_start = start, |
| | 408 | .span_main = diag.src_loc.offset, |
| | 409 | .span_end = end + 1, |
| | 410 | .source_line = source_line, |
| | 411 | }), |
| | 412 | .notes_len = notes_len, |
| | 413 | }; |
| | 414 | } |
| | 415 | |
| | 416 | pub const Bundle = struct { |
| | 417 | file_names: std.AutoHashMapUnmanaged(u32, []const u8) = .{}, |
| | 418 | category_names: std.AutoHashMapUnmanaged(u32, []const u8) = .{}, |
| | 419 | diags: []Diag = &.{}, |
| | 420 | |
| | 421 | pub fn destroy(bundle: *Bundle, gpa: Allocator) void { |
| | 422 | var file_name_it = bundle.file_names.valueIterator(); |
| | 423 | while (file_name_it.next()) |file_name| gpa.free(file_name.*); |
| | 424 | bundle.file_names.deinit(gpa); |
| | 425 | |
| | 426 | var category_name_it = bundle.category_names.valueIterator(); |
| | 427 | while (category_name_it.next()) |category_name| gpa.free(category_name.*); |
| | 428 | bundle.category_names.deinit(gpa); |
| | 429 | |
| | 430 | for (bundle.diags) |*diag| diag.deinit(gpa); |
| | 431 | gpa.free(bundle.diags); |
| | 432 | |
| | 433 | gpa.destroy(bundle); |
| | 434 | } |
| | 435 | |
| | 436 | pub fn parse(gpa: Allocator, path: []const u8) !*Bundle { |
| | 437 | const BitcodeReader = @import("codegen/llvm/BitcodeReader.zig"); |
| | 438 | const BlockId = enum(u32) { |
| | 439 | Meta = 8, |
| | 440 | Diag, |
| | 441 | _, |
| | 442 | }; |
| | 443 | const RecordId = enum(u32) { |
| | 444 | Version = 1, |
| | 445 | DiagInfo, |
| | 446 | SrcRange, |
| | 447 | DiagFlag, |
| | 448 | CatName, |
| | 449 | FileName, |
| | 450 | FixIt, |
| | 451 | _, |
| | 452 | }; |
| | 453 | const WipDiag = struct { |
| | 454 | level: u32 = 0, |
| | 455 | category: u32 = 0, |
| | 456 | msg: []const u8 = &.{}, |
| | 457 | src_loc: SrcLoc = .{}, |
| | 458 | src_ranges: std.ArrayListUnmanaged(SrcRange) = .{}, |
| | 459 | sub_diags: std.ArrayListUnmanaged(Diag) = .{}, |
| | 460 | |
| | 461 | fn deinit(wip_diag: *@This(), allocator: Allocator) void { |
| | 462 | allocator.free(wip_diag.msg); |
| | 463 | wip_diag.src_ranges.deinit(allocator); |
| | 464 | for (wip_diag.sub_diags.items) |*sub_diag| sub_diag.deinit(allocator); |
| | 465 | wip_diag.sub_diags.deinit(allocator); |
| | 466 | wip_diag.* = undefined; |
| | 467 | } |
| | 468 | }; |
| | 469 | |
| | 470 | const file = try std.fs.cwd().openFile(path, .{}); |
| | 471 | defer file.close(); |
| | 472 | var br = std.io.bufferedReader(file.reader()); |
| | 473 | const reader = br.reader(); |
| | 474 | var bc = BitcodeReader.init(gpa, .{ .reader = reader.any() }); |
| | 475 | defer bc.deinit(); |
| | 476 | |
| | 477 | var file_names: std.AutoHashMapUnmanaged(u32, []const u8) = .{}; |
| | 478 | errdefer { |
| | 479 | var file_name_it = file_names.valueIterator(); |
| | 480 | while (file_name_it.next()) |file_name| gpa.free(file_name.*); |
| | 481 | file_names.deinit(gpa); |
| | 482 | } |
| | 483 | |
| | 484 | var category_names: std.AutoHashMapUnmanaged(u32, []const u8) = .{}; |
| | 485 | errdefer { |
| | 486 | var category_name_it = category_names.valueIterator(); |
| | 487 | while (category_name_it.next()) |category_name| gpa.free(category_name.*); |
| | 488 | category_names.deinit(gpa); |
| | 489 | } |
| | 490 | |
| | 491 | var stack: std.ArrayListUnmanaged(WipDiag) = .{}; |
| | 492 | defer { |
| | 493 | for (stack.items) |*wip_diag| wip_diag.deinit(gpa); |
| | 494 | stack.deinit(gpa); |
| | 495 | } |
| | 496 | try stack.append(gpa, .{}); |
| | 497 | |
| | 498 | try bc.checkMagic("DIAG"); |
| | 499 | while (try bc.next()) |item| switch (item) { |
| | 500 | .start_block => |block| switch (@as(BlockId, @enumFromInt(block.id))) { |
| | 501 | .Meta => if (stack.items.len > 0) try bc.skipBlock(block), |
| | 502 | .Diag => try stack.append(gpa, .{}), |
| | 503 | _ => try bc.skipBlock(block), |
| | 504 | }, |
| | 505 | .record => |record| switch (@as(RecordId, @enumFromInt(record.id))) { |
| | 506 | .Version => if (record.operands[0] != 2) return error.InvalidVersion, |
| | 507 | .DiagInfo => { |
| | 508 | const top = &stack.items[stack.items.len - 1]; |
| | 509 | top.level = @intCast(record.operands[0]); |
| | 510 | top.src_loc = .{ |
| | 511 | .file = @intCast(record.operands[1]), |
| | 512 | .line = @intCast(record.operands[2]), |
| | 513 | .column = @intCast(record.operands[3]), |
| | 514 | .offset = @intCast(record.operands[4]), |
| | 515 | }; |
| | 516 | top.category = @intCast(record.operands[5]); |
| | 517 | top.msg = try gpa.dupe(u8, record.blob); |
| | 518 | }, |
| | 519 | .SrcRange => try stack.items[stack.items.len - 1].src_ranges.append(gpa, .{ |
| | 520 | .start = .{ |
| | 521 | .file = @intCast(record.operands[0]), |
| | 522 | .line = @intCast(record.operands[1]), |
| | 523 | .column = @intCast(record.operands[2]), |
| | 524 | .offset = @intCast(record.operands[3]), |
| | 525 | }, |
| | 526 | .end = .{ |
| | 527 | .file = @intCast(record.operands[4]), |
| | 528 | .line = @intCast(record.operands[5]), |
| | 529 | .column = @intCast(record.operands[6]), |
| | 530 | .offset = @intCast(record.operands[7]), |
| | 531 | }, |
| | 532 | }), |
| | 533 | .DiagFlag => {}, |
| | 534 | .CatName => { |
| | 535 | try category_names.ensureUnusedCapacity(gpa, 1); |
| | 536 | category_names.putAssumeCapacity( |
| | 537 | @intCast(record.operands[0]), |
| | 538 | try gpa.dupe(u8, record.blob), |
| | 539 | ); |
| | 540 | }, |
| | 541 | .FileName => { |
| | 542 | try file_names.ensureUnusedCapacity(gpa, 1); |
| | 543 | file_names.putAssumeCapacity( |
| | 544 | @intCast(record.operands[0]), |
| | 545 | try gpa.dupe(u8, record.blob), |
| | 546 | ); |
| | 547 | }, |
| | 548 | .FixIt => {}, |
| | 549 | _ => {}, |
| | 550 | }, |
| | 551 | .end_block => |block| switch (@as(BlockId, @enumFromInt(block.id))) { |
| | 552 | .Meta => {}, |
| | 553 | .Diag => { |
| | 554 | var wip_diag = stack.pop(); |
| | 555 | errdefer wip_diag.deinit(gpa); |
| | 556 | |
| | 557 | const src_ranges = try wip_diag.src_ranges.toOwnedSlice(gpa); |
| | 558 | errdefer gpa.free(src_ranges); |
| | 559 | |
| | 560 | const sub_diags = try wip_diag.sub_diags.toOwnedSlice(gpa); |
| | 561 | errdefer { |
| | 562 | for (sub_diags) |*sub_diag| sub_diag.deinit(gpa); |
| | 563 | gpa.free(sub_diags); |
| | 564 | } |
| | 565 | |
| | 566 | try stack.items[stack.items.len - 1].sub_diags.append(gpa, .{ |
| | 567 | .level = wip_diag.level, |
| | 568 | .category = wip_diag.category, |
| | 569 | .msg = wip_diag.msg, |
| | 570 | .src_loc = wip_diag.src_loc, |
| | 571 | .src_ranges = src_ranges, |
| | 572 | .sub_diags = sub_diags, |
| | 573 | }); |
| | 574 | }, |
| | 575 | _ => {}, |
| | 576 | }, |
| | 577 | }; |
| | 578 | |
| | 579 | const bundle = try gpa.create(Bundle); |
| | 580 | assert(stack.items.len == 1); |
| | 581 | bundle.* = .{ |
| | 582 | .file_names = file_names, |
| | 583 | .category_names = category_names, |
| | 584 | .diags = try stack.items[0].sub_diags.toOwnedSlice(gpa), |
| | 585 | }; |
| | 586 | return bundle; |
| | 587 | } |
| | 588 | |
| | 589 | pub fn addToErrorBundle(bundle: Bundle, eb: *ErrorBundle.Wip) !void { |
| | 590 | for (bundle.diags) |diag| { |
| | 591 | const notes_len = diag.count() - 1; |
| | 592 | try eb.addRootErrorMessage(try diag.toErrorMessage(eb, bundle, notes_len)); |
| | 593 | if (notes_len > 0) { |
| | 594 | var note = try eb.reserveNotes(notes_len); |
| | 595 | for (diag.sub_diags) |sub_diag| |
| | 596 | try sub_diag.addToErrorBundle(eb, bundle, &note); |
| | 597 | } |
| | 598 | } |
| | 599 | } |
| | 600 | }; |
| 330 | }; | 601 | }; |
| 331 | | 602 | |
| 332 | /// Returns if there was failure. | 603 | /// Returns if there was failure. |
| ... | @@ -2826,11 +3097,16 @@ fn addBuf(bufs_list: []std.os.iovec_const, bufs_len: *usize, buf: []const u8) vo | ... | @@ -2826,11 +3097,16 @@ fn addBuf(bufs_list: []std.os.iovec_const, bufs_len: *usize, buf: []const u8) vo |
| 2826 | | 3097 | |
| 2827 | /// This function is temporally single-threaded. | 3098 | /// This function is temporally single-threaded. |
| 2828 | pub fn totalErrorCount(self: *Compilation) u32 { | 3099 | pub fn totalErrorCount(self: *Compilation) u32 { |
| 2829 | var total: usize = self.failed_c_objects.count() + | 3100 | var total: usize = |
| 2830 | self.misc_failures.count() + | 3101 | self.misc_failures.count() + |
| 2831 | @intFromBool(self.alloc_failure_occurred) + | 3102 | @intFromBool(self.alloc_failure_occurred) + |
| 2832 | self.lld_errors.items.len; | 3103 | self.lld_errors.items.len; |
| 2833 | | 3104 | |
| | 3105 | { |
| | 3106 | var it = self.failed_c_objects.iterator(); |
| | 3107 | while (it.next()) |entry| total += entry.value_ptr.*.diags.len; |
| | 3108 | } |
| | 3109 | |
| 2834 | if (!build_options.only_core_functionality) { | 3110 | if (!build_options.only_core_functionality) { |
| 2835 | for (self.failed_win32_resources.values()) |errs| { | 3111 | for (self.failed_win32_resources.values()) |errs| { |
| 2836 | total += errs.errorMessageCount(); | 3112 | total += errs.errorMessageCount(); |
| ... | @@ -2911,24 +3187,7 @@ pub fn getAllErrorsAlloc(self: *Compilation) !ErrorBundle { | ... | @@ -2911,24 +3187,7 @@ pub fn getAllErrorsAlloc(self: *Compilation) !ErrorBundle { |
| 2911 | | 3187 | |
| 2912 | { | 3188 | { |
| 2913 | var it = self.failed_c_objects.iterator(); | 3189 | var it = self.failed_c_objects.iterator(); |
| 2914 | while (it.next()) |entry| { | 3190 | while (it.next()) |entry| try entry.value_ptr.*.addToErrorBundle(&bundle); |
| 2915 | const c_object = entry.key_ptr.*; | | |
| 2916 | const err_msg = entry.value_ptr.*; | | |
| 2917 | // TODO these fields will need to be adjusted when we have proper | | |
| 2918 | // C error reporting bubbling up. | | |
| 2919 | try bundle.addRootErrorMessage(.{ | | |
| 2920 | .msg = try bundle.printString("unable to build C object: {s}", .{err_msg.msg}), | | |
| 2921 | .src_loc = try bundle.addSourceLocation(.{ | | |
| 2922 | .src_path = try bundle.addString(c_object.src.src_path), | | |
| 2923 | .span_start = 0, | | |
| 2924 | .span_main = 0, | | |
| 2925 | .span_end = 1, | | |
| 2926 | .line = err_msg.line, | | |
| 2927 | .column = err_msg.column, | | |
| 2928 | .source_line = 0, // TODO | | |
| 2929 | }), | | |
| 2930 | }); | | |
| 2931 | } | | |
| 2932 | } | 3191 | } |
| 2933 | | 3192 | |
| 2934 | if (!build_options.only_core_functionality) { | 3193 | if (!build_options.only_core_functionality) { |
| ... | @@ -4209,19 +4468,9 @@ fn reportRetryableCObjectError( | ... | @@ -4209,19 +4468,9 @@ fn reportRetryableCObjectError( |
| 4209 | ) error{OutOfMemory}!void { | 4468 | ) error{OutOfMemory}!void { |
| 4210 | c_object.status = .failure_retryable; | 4469 | c_object.status = .failure_retryable; |
| 4211 | | 4470 | |
| 4212 | const c_obj_err_msg = try comp.gpa.create(CObject.ErrorMsg); | 4471 | switch (comp.failCObj(c_object, "{s}", .{@errorName(err)})) { |
| 4213 | errdefer comp.gpa.destroy(c_obj_err_msg); | 4472 | error.AnalysisFail => return, |
| 4214 | const msg = try std.fmt.allocPrint(comp.gpa, "{s}", .{@errorName(err)}); | 4473 | else => |e| return e, |
| 4215 | errdefer comp.gpa.free(msg); | | |
| 4216 | c_obj_err_msg.* = .{ | | |
| 4217 | .msg = msg, | | |
| 4218 | .line = 0, | | |
| 4219 | .column = 0, | | |
| 4220 | }; | | |
| 4221 | { | | |
| 4222 | comp.mutex.lock(); | | |
| 4223 | defer comp.mutex.unlock(); | | |
| 4224 | try comp.failed_c_objects.putNoClobber(comp.gpa, c_object, c_obj_err_msg); | | |
| 4225 | } | 4474 | } |
| 4226 | } | 4475 | } |
| 4227 | | 4476 | |
| ... | @@ -4457,6 +4706,7 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: *std.P | ... | @@ -4457,6 +4706,7 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: *std.P |
| 4457 | // We can't know the digest until we do the C compiler invocation, | 4706 | // We can't know the digest until we do the C compiler invocation, |
| 4458 | // so we need a temporary filename. | 4707 | // so we need a temporary filename. |
| 4459 | const out_obj_path = try comp.tmpFilePath(arena, o_basename); | 4708 | const out_obj_path = try comp.tmpFilePath(arena, o_basename); |
| | 4709 | const out_diag_path = try std.fmt.allocPrint(arena, "{s}.diag", .{out_obj_path}); |
| 4460 | var zig_cache_tmp_dir = try comp.local_cache_directory.handle.makeOpenPath("tmp", .{}); | 4710 | var zig_cache_tmp_dir = try comp.local_cache_directory.handle.makeOpenPath("tmp", .{}); |
| 4461 | defer zig_cache_tmp_dir.close(); | 4711 | defer zig_cache_tmp_dir.close(); |
| 4462 | | 4712 | |
| ... | @@ -4470,18 +4720,20 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: *std.P | ... | @@ -4470,18 +4720,20 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: *std.P |
| 4470 | | 4720 | |
| 4471 | try argv.ensureUnusedCapacity(5); | 4721 | try argv.ensureUnusedCapacity(5); |
| 4472 | switch (comp.clang_preprocessor_mode) { | 4722 | switch (comp.clang_preprocessor_mode) { |
| 4473 | .no => argv.appendSliceAssumeCapacity(&[_][]const u8{ "-c", "-o", out_obj_path }), | 4723 | .no => argv.appendSliceAssumeCapacity(&.{ "-c", "-o", out_obj_path }), |
| 4474 | .yes => argv.appendSliceAssumeCapacity(&[_][]const u8{ "-E", "-o", out_obj_path }), | 4724 | .yes => argv.appendSliceAssumeCapacity(&.{ "-E", "-o", out_obj_path }), |
| 4475 | .stdout => argv.appendAssumeCapacity("-E"), | 4725 | .stdout => argv.appendAssumeCapacity("-E"), |
| 4476 | } | 4726 | } |
| 4477 | if (comp.clang_passthrough_mode) { | 4727 | if (comp.clang_passthrough_mode) { |
| 4478 | if (comp.emit_asm != null) { | 4728 | if (comp.emit_asm != null) { |
| 4479 | argv.appendAssumeCapacity("-S"); | 4729 | argv.appendAssumeCapacity("-S"); |
| 4480 | } else if (comp.emit_llvm_ir != null) { | 4730 | } else if (comp.emit_llvm_ir != null) { |
| 4481 | argv.appendSliceAssumeCapacity(&[_][]const u8{ "-emit-llvm", "-S" }); | 4731 | argv.appendSliceAssumeCapacity(&.{ "-emit-llvm", "-S" }); |
| 4482 | } else if (comp.emit_llvm_bc != null) { | 4732 | } else if (comp.emit_llvm_bc != null) { |
| 4483 | argv.appendAssumeCapacity("-emit-llvm"); | 4733 | argv.appendAssumeCapacity("-emit-llvm"); |
| 4484 | } | 4734 | } |
| | 4735 | } else { |
| | 4736 | argv.appendSliceAssumeCapacity(&.{ "--serialize-diagnostics", out_diag_path }); |
| 4485 | } | 4737 | } |
| 4486 | | 4738 | |
| 4487 | if (comp.verbose_cc) { | 4739 | if (comp.verbose_cc) { |
| ... | @@ -4524,10 +4776,11 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: *std.P | ... | @@ -4524,10 +4776,11 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: *std.P |
| 4524 | switch (term) { | 4776 | switch (term) { |
| 4525 | .Exited => |code| { | 4777 | .Exited => |code| { |
| 4526 | if (code != 0) { | 4778 | if (code != 0) { |
| 4527 | // TODO parse clang stderr and turn it into an error message | 4779 | const bundle = CObject.Diag.Bundle.parse(comp.gpa, out_diag_path) catch |err| { |
| 4528 | // and then call failCObjWithOwnedErrorMsg | 4780 | log.err("{}: failed to parse clang diagnostics: {s}", .{ err, stderr }); |
| 4529 | log.err("clang failed with stderr: {s}", .{stderr}); | 4781 | return comp.failCObj(c_object, "clang exited with code {d}", .{code}); |
| 4530 | return comp.failCObj(c_object, "clang exited with code {d}", .{code}); | 4782 | }; |
| | 4783 | return comp.failCObjWithOwnedDiagBundle(c_object, bundle); |
| 4531 | } | 4784 | } |
| 4532 | }, | 4785 | }, |
| 4533 | else => { | 4786 | else => { |
| ... | @@ -5413,37 +5666,45 @@ pub fn addCCArgs( | ... | @@ -5413,37 +5666,45 @@ pub fn addCCArgs( |
| 5413 | try argv.appendSlice(comp.clang_argv); | 5666 | try argv.appendSlice(comp.clang_argv); |
| 5414 | } | 5667 | } |
| 5415 | | 5668 | |
| 5416 | fn failCObj(comp: *Compilation, c_object: *CObject, comptime format: []const u8, args: anytype) SemaError { | 5669 | fn failCObj( |
| | 5670 | comp: *Compilation, |
| | 5671 | c_object: *CObject, |
| | 5672 | comptime format: []const u8, |
| | 5673 | args: anytype, |
| | 5674 | ) SemaError { |
| 5417 | @setCold(true); | 5675 | @setCold(true); |
| 5418 | const err_msg = blk: { | 5676 | const diag_bundle = blk: { |
| 5419 | const msg = try std.fmt.allocPrint(comp.gpa, format, args); | 5677 | const diag_bundle = try comp.gpa.create(CObject.Diag.Bundle); |
| 5420 | errdefer comp.gpa.free(msg); | 5678 | diag_bundle.* = .{}; |
| 5421 | const err_msg = try comp.gpa.create(CObject.ErrorMsg); | 5679 | errdefer diag_bundle.destroy(comp.gpa); |
| 5422 | errdefer comp.gpa.destroy(err_msg); | 5680 | |
| 5423 | err_msg.* = .{ | 5681 | try diag_bundle.file_names.ensureTotalCapacity(comp.gpa, 1); |
| 5424 | .msg = msg, | 5682 | diag_bundle.file_names.putAssumeCapacity(1, try comp.gpa.dupe(u8, c_object.src.src_path)); |
| 5425 | .line = 0, | 5683 | |
| 5426 | .column = 0, | 5684 | diag_bundle.diags = try comp.gpa.alloc(CObject.Diag, 1); |
| 5427 | }; | 5685 | diag_bundle.diags[0] = .{}; |
| 5428 | break :blk err_msg; | 5686 | diag_bundle.diags[0].level = 3; |
| | 5687 | diag_bundle.diags[0].msg = try std.fmt.allocPrint(comp.gpa, format, args); |
| | 5688 | diag_bundle.diags[0].src_loc.file = 1; |
| | 5689 | break :blk diag_bundle; |
| 5429 | }; | 5690 | }; |
| 5430 | return comp.failCObjWithOwnedErrorMsg(c_object, err_msg); | 5691 | return comp.failCObjWithOwnedDiagBundle(c_object, diag_bundle); |
| 5431 | } | 5692 | } |
| 5432 | | 5693 | |
| 5433 | fn failCObjWithOwnedErrorMsg( | 5694 | fn failCObjWithOwnedDiagBundle( |
| 5434 | comp: *Compilation, | 5695 | comp: *Compilation, |
| 5435 | c_object: *CObject, | 5696 | c_object: *CObject, |
| 5436 | err_msg: *CObject.ErrorMsg, | 5697 | diag_bundle: *CObject.Diag.Bundle, |
| 5437 | ) SemaError { | 5698 | ) SemaError { |
| 5438 | @setCold(true); | 5699 | @setCold(true); |
| 5439 | { | 5700 | { |
| 5440 | comp.mutex.lock(); | 5701 | comp.mutex.lock(); |
| 5441 | defer comp.mutex.unlock(); | 5702 | defer comp.mutex.unlock(); |
| 5442 | { | 5703 | { |
| 5443 | errdefer err_msg.destroy(comp.gpa); | 5704 | errdefer diag_bundle.destroy(comp.gpa); |
| 5444 | try comp.failed_c_objects.ensureUnusedCapacity(comp.gpa, 1); | 5705 | try comp.failed_c_objects.ensureUnusedCapacity(comp.gpa, 1); |
| 5445 | } | 5706 | } |
| 5446 | comp.failed_c_objects.putAssumeCapacityNoClobber(c_object, err_msg); | 5707 | comp.failed_c_objects.putAssumeCapacityNoClobber(c_object, diag_bundle); |
| 5447 | } | 5708 | } |
| 5448 | c_object.status = .failure; | 5709 | c_object.status = .failure; |
| 5449 | return error.AnalysisFail; | 5710 | return error.AnalysisFail; |