| ... | @@ -1,6 +1,7 @@ | ... | @@ -1,6 +1,7 @@ |
| 1 | const std = @import("std"); | 1 | const std = @import("std"); |
| 2 | const builtin = @import("builtin"); | 2 | const builtin = @import("builtin"); |
| 3 | const assert = std.debug.assert; | 3 | const assert = std.debug.assert; |
| | 4 | const panic = std.debug.panicExtra; |
| 4 | | 5 | |
| 5 | const SourceLocation = extern struct { | 6 | const SourceLocation = extern struct { |
| 6 | file_name: ?[*:0]const u8, | 7 | file_name: ?[*:0]const u8, |
| ... | @@ -175,7 +176,7 @@ fn overflowHandler( | ... | @@ -175,7 +176,7 @@ fn overflowHandler( |
| 175 | const fmt = "{s} integer overflow: " ++ "{} " ++ | 176 | const fmt = "{s} integer overflow: " ++ "{} " ++ |
| 176 | operator ++ " {} cannot be represented in type {s}"; | 177 | operator ++ " {} cannot be represented in type {s}"; |
| 177 | | 178 | |
| 178 | logMessage(fmt, .{ | 179 | panic(@returnAddress(), fmt, .{ |
| 179 | if (is_signed) "signed" else "unsigned", | 180 | if (is_signed) "signed" else "unsigned", |
| 180 | lhs, | 181 | lhs, |
| 181 | rhs, | 182 | rhs, |
| ... | @@ -199,7 +200,8 @@ fn negationHandler( | ... | @@ -199,7 +200,8 @@ fn negationHandler( |
| 199 | value_handle: ValueHandle, | 200 | value_handle: ValueHandle, |
| 200 | ) callconv(.c) noreturn { | 201 | ) callconv(.c) noreturn { |
| 201 | const value: Value = .{ .handle = value_handle, .td = data.td }; | 202 | const value: Value = .{ .handle = value_handle, .td = data.td }; |
| 202 | logMessage( | 203 | panic( |
| | 204 | @returnAddress(), |
| 203 | "negation of {} cannot be represented in type {s}", | 205 | "negation of {} cannot be represented in type {s}", |
| 204 | .{ value, data.td.getName() }, | 206 | .{ value, data.td.getName() }, |
| 205 | ); | 207 | ); |
| ... | @@ -222,11 +224,12 @@ fn divRemHandler( | ... | @@ -222,11 +224,12 @@ fn divRemHandler( |
| 222 | const rhs: Value = .{ .handle = rhs_handle, .td = data.td }; | 224 | const rhs: Value = .{ .handle = rhs_handle, .td = data.td }; |
| 223 | | 225 | |
| 224 | if (rhs.isMinusOne()) { | 226 | if (rhs.isMinusOne()) { |
| 225 | logMessage( | 227 | panic( |
| | 228 | @returnAddress(), |
| 226 | "division of {} by -1 cannot be represented in type {s}", | 229 | "division of {} by -1 cannot be represented in type {s}", |
| 227 | .{ lhs, data.td.getName() }, | 230 | .{ lhs, data.td.getName() }, |
| 228 | ); | 231 | ); |
| 229 | } else logMessage("division by zero", .{}); | 232 | } else panic(@returnAddress(), "division by zero", .{}); |
| 230 | } | 233 | } |
| 231 | | 234 | |
| 232 | const AlignmentAssumptionData = extern struct { | 235 | const AlignmentAssumptionData = extern struct { |
| ... | @@ -263,7 +266,8 @@ fn alignmentAssumptionHandler( | ... | @@ -263,7 +266,8 @@ fn alignmentAssumptionHandler( |
| 263 | const alignment: Value = .{ .handle = alignment_handle, .td = data.td }; | 266 | const alignment: Value = .{ .handle = alignment_handle, .td = data.td }; |
| 264 | | 267 | |
| 265 | if (maybe_offset) |offset| { | 268 | if (maybe_offset) |offset| { |
| 266 | logMessage( | 269 | panic( |
| | 270 | @returnAddress(), |
| 267 | "assumption of {} byte alignment (with offset of {} byte) for pointer of type {s} failed\n" ++ | 271 | "assumption of {} byte alignment (with offset of {} byte) for pointer of type {s} failed\n" ++ |
| 268 | "offset address is {} aligned, misalignment offset is {} bytes", | 272 | "offset address is {} aligned, misalignment offset is {} bytes", |
| 269 | .{ | 273 | .{ |
| ... | @@ -275,7 +279,8 @@ fn alignmentAssumptionHandler( | ... | @@ -275,7 +279,8 @@ fn alignmentAssumptionHandler( |
| 275 | }, | 279 | }, |
| 276 | ); | 280 | ); |
| 277 | } else { | 281 | } else { |
| 278 | logMessage( | 282 | panic( |
| | 283 | @returnAddress(), |
| 279 | "assumption of {} byte alignment for pointer of type {s} failed\n" ++ | 284 | "assumption of {} byte alignment for pointer of type {s} failed\n" ++ |
| 280 | "address is {} aligned, misalignment offset is {} bytes", | 285 | "address is {} aligned, misalignment offset is {} bytes", |
| 281 | .{ | 286 | .{ |
| ... | @@ -314,18 +319,20 @@ fn shiftOob( | ... | @@ -314,18 +319,20 @@ fn shiftOob( |
| 314 | rhs.getPositiveInteger() >= data.lhs_type.getIntegerSize()) | 319 | rhs.getPositiveInteger() >= data.lhs_type.getIntegerSize()) |
| 315 | { | 320 | { |
| 316 | if (rhs.isNegative()) { | 321 | if (rhs.isNegative()) { |
| 317 | logMessage("shift exponent {} is negative", .{rhs}); | 322 | panic(@returnAddress(), "shift exponent {} is negative", .{rhs}); |
| 318 | } else { | 323 | } else { |
| 319 | logMessage( | 324 | panic( |
| | 325 | @returnAddress(), |
| 320 | "shift exponent {} is too large for {}-bit type {s}", | 326 | "shift exponent {} is too large for {}-bit type {s}", |
| 321 | .{ rhs, data.lhs_type.getIntegerSize(), data.lhs_type.getName() }, | 327 | .{ rhs, data.lhs_type.getIntegerSize(), data.lhs_type.getName() }, |
| 322 | ); | 328 | ); |
| 323 | } | 329 | } |
| 324 | } else { | 330 | } else { |
| 325 | if (lhs.isNegative()) { | 331 | if (lhs.isNegative()) { |
| 326 | logMessage("left shift of negative value {}", .{lhs}); | 332 | panic(@returnAddress(), "left shift of negative value {}", .{lhs}); |
| 327 | } else { | 333 | } else { |
| 328 | logMessage( | 334 | panic( |
| | 335 | @returnAddress(), |
| 329 | "left shift of {} by {} places cannot be represented in type {s}", | 336 | "left shift of {} by {} places cannot be represented in type {s}", |
| 330 | .{ lhs, rhs, data.lhs_type.getName() }, | 337 | .{ lhs, rhs, data.lhs_type.getName() }, |
| 331 | ); | 338 | ); |
| ... | @@ -351,7 +358,8 @@ fn outOfBounds( | ... | @@ -351,7 +358,8 @@ fn outOfBounds( |
| 351 | index_handle: ValueHandle, | 358 | index_handle: ValueHandle, |
| 352 | ) callconv(.c) noreturn { | 359 | ) callconv(.c) noreturn { |
| 353 | const index: Value = .{ .handle = index_handle, .td = data.index_type }; | 360 | const index: Value = .{ .handle = index_handle, .td = data.index_type }; |
| 354 | logMessage( | 361 | panic( |
| | 362 | @returnAddress(), |
| 355 | "index {} out of bounds for type {s}", | 363 | "index {} out of bounds for type {s}", |
| 356 | .{ index, data.array_type.getName() }, | 364 | .{ index, data.array_type.getName() }, |
| 357 | ); | 365 | ); |
| ... | @@ -376,13 +384,14 @@ fn pointerOverflow( | ... | @@ -376,13 +384,14 @@ fn pointerOverflow( |
| 376 | ) callconv(.c) noreturn { | 384 | ) callconv(.c) noreturn { |
| 377 | if (base == 0) { | 385 | if (base == 0) { |
| 378 | if (result == 0) { | 386 | if (result == 0) { |
| 379 | logMessage("applying zero offset to null pointer", .{}); | 387 | panic(@returnAddress(), "applying zero offset to null pointer", .{}); |
| 380 | } else { | 388 | } else { |
| 381 | logMessage("applying non-zero offset {} to null pointer", .{result}); | 389 | panic(@returnAddress(), "applying non-zero offset {} to null pointer", .{result}); |
| 382 | } | 390 | } |
| 383 | } else { | 391 | } else { |
| 384 | if (result == 0) { | 392 | if (result == 0) { |
| 385 | logMessage( | 393 | panic( |
| | 394 | @returnAddress(), |
| 386 | "applying non-zero offset to non-null pointer 0x{x} produced null pointer", | 395 | "applying non-zero offset to non-null pointer 0x{x} produced null pointer", |
| 387 | .{base}, | 396 | .{base}, |
| 388 | ); | 397 | ); |
| ... | @@ -391,18 +400,21 @@ fn pointerOverflow( | ... | @@ -391,18 +400,21 @@ fn pointerOverflow( |
| 391 | const signed_result: isize = @bitCast(result); | 400 | const signed_result: isize = @bitCast(result); |
| 392 | if ((signed_base >= 0) == (signed_result >= 0)) { | 401 | if ((signed_base >= 0) == (signed_result >= 0)) { |
| 393 | if (base > result) { | 402 | if (base > result) { |
| 394 | logMessage( | 403 | panic( |
| | 404 | @returnAddress(), |
| 395 | "addition of unsigned offset to 0x{x} overflowed to 0x{x}", | 405 | "addition of unsigned offset to 0x{x} overflowed to 0x{x}", |
| 396 | .{ base, result }, | 406 | .{ base, result }, |
| 397 | ); | 407 | ); |
| 398 | } else { | 408 | } else { |
| 399 | logMessage( | 409 | panic( |
| | 410 | @returnAddress(), |
| 400 | "subtraction of unsigned offset to 0x{x} overflowed to 0x{x}", | 411 | "subtraction of unsigned offset to 0x{x} overflowed to 0x{x}", |
| 401 | .{ base, result }, | 412 | .{ base, result }, |
| 402 | ); | 413 | ); |
| 403 | } | 414 | } |
| 404 | } else { | 415 | } else { |
| 405 | logMessage( | 416 | panic( |
| | 417 | @returnAddress(), |
| 406 | "pointer index expression with base 0x{x} overflowed to 0x{x}", | 418 | "pointer index expression with base 0x{x} overflowed to 0x{x}", |
| 407 | .{ base, result }, | 419 | .{ base, result }, |
| 408 | ); | 420 | ); |
| ... | @@ -462,17 +474,20 @@ fn typeMismatch( | ... | @@ -462,17 +474,20 @@ fn typeMismatch( |
| 462 | const handle: usize = @intFromPtr(pointer); | 474 | const handle: usize = @intFromPtr(pointer); |
| 463 | | 475 | |
| 464 | if (pointer == null) { | 476 | if (pointer == null) { |
| 465 | logMessage( | 477 | panic( |
| | 478 | @returnAddress(), |
| 466 | "{s} null pointer of type {s}", | 479 | "{s} null pointer of type {s}", |
| 467 | .{ data.kind.getName(), data.td.getName() }, | 480 | .{ data.kind.getName(), data.td.getName() }, |
| 468 | ); | 481 | ); |
| 469 | } else if (!std.mem.isAligned(handle, alignment)) { | 482 | } else if (!std.mem.isAligned(handle, alignment)) { |
| 470 | logMessage( | 483 | panic( |
| | 484 | @returnAddress(), |
| 471 | "{s} misaligned address 0x{x} for type {s}, which requires {} byte alignment", | 485 | "{s} misaligned address 0x{x} for type {s}, which requires {} byte alignment", |
| 472 | .{ data.kind.getName(), handle, data.td.getName(), alignment }, | 486 | .{ data.kind.getName(), handle, data.td.getName(), alignment }, |
| 473 | ); | 487 | ); |
| 474 | } else { | 488 | } else { |
| 475 | logMessage( | 489 | panic( |
| | 490 | @returnAddress(), |
| 476 | "{s} address 0x{x} with insufficient space for an object of type {s}", | 491 | "{s} address 0x{x} with insufficient space for an object of type {s}", |
| 477 | .{ data.kind.getName(), handle, data.td.getName() }, | 492 | .{ data.kind.getName(), handle, data.td.getName() }, |
| 478 | ); | 493 | ); |
| ... | @@ -484,11 +499,11 @@ const UnreachableData = extern struct { | ... | @@ -484,11 +499,11 @@ const UnreachableData = extern struct { |
| 484 | }; | 499 | }; |
| 485 | | 500 | |
| 486 | fn builtinUnreachable(_: *const UnreachableData) callconv(.c) noreturn { | 501 | fn builtinUnreachable(_: *const UnreachableData) callconv(.c) noreturn { |
| 487 | logMessage("execution reached an unreachable program point", .{}); | 502 | panic(@returnAddress(), "execution reached an unreachable program point", .{}); |
| 488 | } | 503 | } |
| 489 | | 504 | |
| 490 | fn missingReturn(_: *const UnreachableData) callconv(.c) noreturn { | 505 | fn missingReturn(_: *const UnreachableData) callconv(.c) noreturn { |
| 491 | logMessage("execution reached the end of a value-returning function without returning a value", .{}); | 506 | panic(@returnAddress(), "execution reached the end of a value-returning function without returning a value", .{}); |
| 492 | } | 507 | } |
| 493 | | 508 | |
| 494 | const NonNullReturnData = extern struct { | 509 | const NonNullReturnData = extern struct { |
| ... | @@ -499,7 +514,7 @@ fn nonNullReturnAbort(data: *const NonNullReturnData) callconv(.c) noreturn { | ... | @@ -499,7 +514,7 @@ fn nonNullReturnAbort(data: *const NonNullReturnData) callconv(.c) noreturn { |
| 499 | nonNullReturn(data); | 514 | nonNullReturn(data); |
| 500 | } | 515 | } |
| 501 | fn nonNullReturn(_: *const NonNullReturnData) callconv(.c) noreturn { | 516 | fn nonNullReturn(_: *const NonNullReturnData) callconv(.c) noreturn { |
| 502 | logMessage("null pointer returned from function declared to never return null", .{}); | 517 | panic(@returnAddress(), "null pointer returned from function declared to never return null", .{}); |
| 503 | } | 518 | } |
| 504 | | 519 | |
| 505 | const NonNullArgData = extern struct { | 520 | const NonNullArgData = extern struct { |
| ... | @@ -513,7 +528,8 @@ fn nonNullArgAbort(data: *const NonNullArgData) callconv(.c) noreturn { | ... | @@ -513,7 +528,8 @@ fn nonNullArgAbort(data: *const NonNullArgData) callconv(.c) noreturn { |
| 513 | } | 528 | } |
| 514 | | 529 | |
| 515 | fn nonNullArg(data: *const NonNullArgData) callconv(.c) noreturn { | 530 | fn nonNullArg(data: *const NonNullArgData) callconv(.c) noreturn { |
| 516 | logMessage( | 531 | panic( |
| | 532 | @returnAddress(), |
| 517 | "null pointer passed as argument {}, which is declared to never be null", | 533 | "null pointer passed as argument {}, which is declared to never be null", |
| 518 | .{data.arg_index}, | 534 | .{data.arg_index}, |
| 519 | ); | 535 | ); |
| ... | @@ -536,7 +552,8 @@ fn loadInvalidValue( | ... | @@ -536,7 +552,8 @@ fn loadInvalidValue( |
| 536 | value_handle: ValueHandle, | 552 | value_handle: ValueHandle, |
| 537 | ) callconv(.c) noreturn { | 553 | ) callconv(.c) noreturn { |
| 538 | const value: Value = .{ .handle = value_handle, .td = data.td }; | 554 | const value: Value = .{ .handle = value_handle, .td = data.td }; |
| 539 | logMessage( | 555 | panic( |
| | 556 | @returnAddress(), |
| 540 | "load of value {}, which is not valid for type {s}", | 557 | "load of value {}, which is not valid for type {s}", |
| 541 | .{ value, data.td.getName() }, | 558 | .{ value, data.td.getName() }, |
| 542 | ); | 559 | ); |
| ... | @@ -554,7 +571,8 @@ fn invalidBuiltinAbort(data: *const InvalidBuiltinData) callconv(.c) noreturn { | ... | @@ -554,7 +571,8 @@ fn invalidBuiltinAbort(data: *const InvalidBuiltinData) callconv(.c) noreturn { |
| 554 | } | 571 | } |
| 555 | | 572 | |
| 556 | fn invalidBuiltin(data: *const InvalidBuiltinData) callconv(.c) noreturn { | 573 | fn invalidBuiltin(data: *const InvalidBuiltinData) callconv(.c) noreturn { |
| 557 | logMessage( | 574 | panic( |
| | 575 | @returnAddress(), |
| 558 | "passing zero to {s}(), which is not a valid argument", | 576 | "passing zero to {s}(), which is not a valid argument", |
| 559 | .{@tagName(data.kind)}, | 577 | .{@tagName(data.kind)}, |
| 560 | ); | 578 | ); |
| ... | @@ -577,7 +595,8 @@ fn vlaBoundNotPositive( | ... | @@ -577,7 +595,8 @@ fn vlaBoundNotPositive( |
| 577 | bound_handle: ValueHandle, | 595 | bound_handle: ValueHandle, |
| 578 | ) callconv(.c) noreturn { | 596 | ) callconv(.c) noreturn { |
| 579 | const bound: Value = .{ .handle = bound_handle, .td = data.td }; | 597 | const bound: Value = .{ .handle = bound_handle, .td = data.td }; |
| 580 | logMessage( | 598 | panic( |
| | 599 | @returnAddress(), |
| 581 | "variable length array bound evaluates to non-positive value {}", | 600 | "variable length array bound evaluates to non-positive value {}", |
| 582 | .{bound}, | 601 | .{bound}, |
| 583 | ); | 602 | ); |
| ... | @@ -611,22 +630,18 @@ fn floatCastOverflow( | ... | @@ -611,22 +630,18 @@ fn floatCastOverflow( |
| 611 | if (@as(u16, ptr[0]) + @as(u16, ptr[1]) < 2 or ptr[0] == 0xFF or ptr[1] == 0xFF) { | 630 | if (@as(u16, ptr[0]) + @as(u16, ptr[1]) < 2 or ptr[0] == 0xFF or ptr[1] == 0xFF) { |
| 612 | const data: *const FloatCastOverflowData = @ptrCast(data_handle); | 631 | const data: *const FloatCastOverflowData = @ptrCast(data_handle); |
| 613 | const from_value: Value = .{ .handle = from_handle, .td = data.from }; | 632 | const from_value: Value = .{ .handle = from_handle, .td = data.from }; |
| 614 | logMessage("{} is outside the range of representable values of type {s}", .{ | 633 | panic(@returnAddress(), "{} is outside the range of representable values of type {s}", .{ |
| 615 | from_value, data.to.getName(), | 634 | from_value, data.to.getName(), |
| 616 | }); | 635 | }); |
| 617 | } else { | 636 | } else { |
| 618 | const data: *const FloatCastOverflowDataV2 = @ptrCast(data_handle); | 637 | const data: *const FloatCastOverflowDataV2 = @ptrCast(data_handle); |
| 619 | const from_value: Value = .{ .handle = from_handle, .td = data.from }; | 638 | const from_value: Value = .{ .handle = from_handle, .td = data.from }; |
| 620 | logMessage("{} is outside the range of representable values of type {s}", .{ | 639 | panic(@returnAddress(), "{} is outside the range of representable values of type {s}", .{ |
| 621 | from_value, data.to.getName(), | 640 | from_value, data.to.getName(), |
| 622 | }); | 641 | }); |
| 623 | } | 642 | } |
| 624 | } | 643 | } |
| 625 | | 644 | |
| 626 | inline fn logMessage(comptime fmt: []const u8, args: anytype) noreturn { | | |
| 627 | std.debug.panicExtra(@returnAddress(), fmt, args); | | |
| 628 | } | | |
| 629 | | | |
| 630 | fn exportHandler( | 645 | fn exportHandler( |
| 631 | handler: anytype, | 646 | handler: anytype, |
| 632 | comptime sym_name: []const u8, | 647 | comptime sym_name: []const u8, |