authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-09-25 18:23:45-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-09-26 12:35:14-07:00
logb66cc5af41aa0cc90996a75468a84ca83b46c1fd
tree115331e42f1294efa4639c51a853ba658bb8849e
parentf2c8940aa6b1bd6ca20730e13b8148af002e1b91

reimplement integer overflow safety panic function calls

in the llvm backend.

4 files changed, 74 insertions(+), 63 deletions(-)

src/Sema.zig+21-22
......@@ -5703,27 +5703,7 @@ fn addStrLit(sema: *Sema, string: InternPool.String, len: u64) CompileError!Air.
57035703}
57045704
57055705fn uavRef(sema: *Sema, val: InternPool.Index) CompileError!Air.Inst.Ref {
5706 return Air.internedToRef(try sema.refValue(val));
5707}
5708
5709fn refValue(sema: *Sema, val: InternPool.Index) CompileError!InternPool.Index {
5710 const pt = sema.pt;
5711 const ptr_ty = (try pt.ptrTypeSema(.{
5712 .child = pt.zcu.intern_pool.typeOf(val),
5713 .flags = .{
5714 .alignment = .none,
5715 .is_const = true,
5716 .address_space = .generic,
5717 },
5718 })).toIntern();
5719 return pt.intern(.{ .ptr = .{
5720 .ty = ptr_ty,
5721 .base_addr = .{ .uav = .{
5722 .val = val,
5723 .orig_ty = ptr_ty,
5724 } },
5725 .byte_offset = 0,
5726 } });
5706 return Air.internedToRef(try sema.pt.refValue(val));
57275707}
57285708
57295709fn zirInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
......@@ -17402,6 +17382,7 @@ fn analyzeArithmetic(
1740217382
1740317383 if (block.wantSafety() and want_safety and scalar_tag == .int) {
1740417384 if (zcu.backendSupportsFeature(.safety_checked_instructions)) {
17385 if (air_tag != air_tag_safe) try sema.preparePanicIntegerOverflow(block, src);
1740517386 return block.addBinOp(air_tag_safe, casted_lhs, casted_rhs);
1740617387 } else {
1740717388 const maybe_op_ov: ?Air.Inst.Tag = switch (air_tag) {
......@@ -27706,6 +27687,24 @@ fn preparePanic(sema: *Sema, block: *Block, src: LazySrcLoc) !void {
2770627687 const panic_cause_ty = try pt.getBuiltinType("PanicCause");
2770727688 try panic_cause_ty.resolveFields(pt);
2770827689 zcu.panic_cause_type = panic_cause_ty.toIntern();
27690 zcu.panic_cause_tag_type = panic_cause_ty.unionTagType(zcu).?.toIntern();
27691 }
27692}
27693
27694fn preparePanicIntegerOverflow(sema: *Sema, block: *Block, src: LazySrcLoc) !void {
27695 const pt = sema.pt;
27696 const zcu = pt.zcu;
27697 try preparePanic(sema, block, src);
27698 if (zcu.panic_cause_integer_overflow == .none) {
27699 const union_val = try pt.unionValue(
27700 Type.fromInterned(zcu.panic_cause_type),
27701 try pt.enumValueFieldIndex(
27702 Type.fromInterned(zcu.panic_cause_tag_type),
27703 @intFromEnum(PanicCauseTag.integer_overflow),
27704 ),
27705 Value.void,
27706 );
27707 zcu.panic_cause_integer_overflow = try pt.refValue(union_val.toIntern());
2770927708 }
2771027709}
2771127710
......@@ -32669,7 +32668,7 @@ fn optRefValue(sema: *Sema, opt_val: ?Value) !Value {
3266932668 return Value.fromInterned(try pt.intern(.{ .opt = .{
3267032669 .ty = (try pt.optionalType(ptr_anyopaque_ty.toIntern())).toIntern(),
3267132670 .val = if (opt_val) |val| (try pt.getCoerced(
32672 Value.fromInterned(try sema.refValue(val.toIntern())),
32671 Value.fromInterned(try pt.refValue(val.toIntern())),
3267332672 ptr_anyopaque_ty,
3267432673 )).toIntern() else .none,
3267532674 } }));
src/Zcu.zig+2
......@@ -214,6 +214,8 @@ free_type_references: std.ArrayListUnmanaged(u32) = .empty,
214214panic_func_index: InternPool.Index = .none,
215215null_stack_trace: InternPool.Index = .none,
216216panic_cause_type: InternPool.Index = .none,
217panic_cause_tag_type: InternPool.Index = .none,
218panic_cause_integer_overflow: InternPool.Index = .none,
217219
218220generation: u32 = 0,
219221
src/Zcu/PerThread.zig+19
......@@ -3656,6 +3656,25 @@ pub fn ensureNamespaceUpToDate(pt: Zcu.PerThread, namespace_index: Zcu.Namespace
36563656 namespace.generation = zcu.generation;
36573657}
36583658
3659pub fn refValue(pt: Zcu.PerThread, val: InternPool.Index) Zcu.SemaError!InternPool.Index {
3660 const ptr_ty = (try pt.ptrTypeSema(.{
3661 .child = pt.zcu.intern_pool.typeOf(val),
3662 .flags = .{
3663 .alignment = .none,
3664 .is_const = true,
3665 .address_space = .generic,
3666 },
3667 })).toIntern();
3668 return pt.intern(.{ .ptr = .{
3669 .ty = ptr_ty,
3670 .base_addr = .{ .uav = .{
3671 .val = val,
3672 .orig_ty = ptr_ty,
3673 } },
3674 .byte_offset = 0,
3675 } });
3676}
3677
36593678const Air = @import("../Air.zig");
36603679const Allocator = std.mem.Allocator;
36613680const assert = std.debug.assert;
src/codegen/llvm.zig+32-41
......@@ -5677,46 +5677,37 @@ pub const FuncGen = struct {
56775677
56785678 const PanicCauseTag = @typeInfo(std.builtin.PanicCause).@"union".tag_type.?;
56795679
5680 fn buildSimplePanic(fg: *FuncGen, panic_cause_tag: PanicCauseTag) !void {
5681 // TODO update this before merging the branch
5682 _ = panic_cause_tag;
5683 //const o = fg.ng.object;
5684 //const zcu = o.pt.zcu;
5685 //const ip = &zcu.intern_pool;
5686 //const msg_nav_index = zcu.panic_messages[@intFromEnum(panic_id)].unwrap().?;
5687 //const msg_nav = ip.getNav(msg_nav_index);
5688 //const msg_len = Type.fromInterned(msg_nav.typeOf(ip)).childType(zcu).arrayLen(zcu);
5689 //const msg_ptr = try o.lowerValue(msg_nav.status.resolved.val);
5690 //const null_opt_addr_global = try fg.resolveNullOptUsize();
5691 //const target = zcu.getTarget();
5692 //const llvm_usize = try o.lowerType(Type.usize);
5693 //// example:
5694 //// call fastcc void @test2.panic(
5695 //// ptr @builtin.panic_messages.integer_overflow__anon_987, ; msg.ptr
5696 //// i64 16, ; msg.len
5697 //// ptr null, ; stack trace
5698 //// ptr @2, ; addr (null ?usize)
5699 //// )
5700 //const panic_func = zcu.funcInfo(zcu.panic_func_index);
5701 //const panic_nav = ip.getNav(panic_func.owner_nav);
5702 //const fn_info = zcu.typeToFunc(Type.fromInterned(panic_nav.typeOf(ip))).?;
5703 //const panic_global = try o.resolveLlvmFunction(panic_func.owner_nav);
5704 //_ = try fg.wip.callIntrinsicAssumeCold();
5705 //_ = try fg.wip.call(
5706 // .normal,
5707 // toLlvmCallConv(fn_info.cc, target),
5708 // .none,
5709 // panic_global.typeOf(&o.builder),
5710 // panic_global.toValue(&o.builder),
5711 // &.{
5712 // msg_ptr.toValue(),
5713 // try o.builder.intValue(llvm_usize, msg_len),
5714 // try o.builder.nullValue(.ptr),
5715 // null_opt_addr_global.toValue(),
5716 // },
5717 // "",
5718 //);
5719 _ = try fg.wip.callIntrinsic(.normal, .none, .trap, &.{}, &.{}, "");
5680 fn buildSimplePanic(fg: *FuncGen, panic_cause: InternPool.Index) !void {
5681 const o = fg.ng.object;
5682 const zcu = o.pt.zcu;
5683 const ip = &zcu.intern_pool;
5684 const cause_ptr = try o.lowerValue(panic_cause);
5685 const null_opt_addr_global = try fg.resolveNullOptUsize();
5686 const target = zcu.getTarget();
5687 // example:
5688 // call fastcc void @test2.panic(
5689 // ptr @foo, ; panic_cause
5690 // ptr null, ; stack trace
5691 // ptr @2, ; addr (null ?usize)
5692 // )
5693 const panic_func = zcu.funcInfo(zcu.panic_func_index);
5694 const panic_nav = ip.getNav(panic_func.owner_nav);
5695 const fn_info = zcu.typeToFunc(Type.fromInterned(panic_nav.typeOf(ip))).?;
5696 const panic_global = try o.resolveLlvmFunction(panic_func.owner_nav);
5697 _ = try fg.wip.callIntrinsicAssumeCold();
5698 _ = try fg.wip.call(
5699 .normal,
5700 toLlvmCallConv(fn_info.cc, target),
5701 .none,
5702 panic_global.typeOf(&o.builder),
5703 panic_global.toValue(&o.builder),
5704 &.{
5705 cause_ptr.toValue(),
5706 try o.builder.nullValue(.ptr),
5707 null_opt_addr_global.toValue(),
5708 },
5709 "",
5710 );
57205711 _ = try fg.wip.@"unreachable"();
57215712 }
57225713
......@@ -8340,7 +8331,7 @@ pub const FuncGen = struct {
83408331 _ = try fg.wip.brCond(overflow_bit, fail_block, ok_block, .none);
83418332
83428333 fg.wip.cursor = .{ .block = fail_block };
8343 try fg.buildSimplePanic(.integer_overflow);
8334 try fg.buildSimplePanic(zcu.panic_cause_integer_overflow);
83448335
83458336 fg.wip.cursor = .{ .block = ok_block };
83468337 return fg.wip.extractValue(results, &.{0}, "");