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....@@ -5703,27 +5703,7 @@ fn addStrLit(sema: *Sema, string: InternPool.String, len: u64) CompileError!Air.
5703}5703}
57045704
5705fn uavRef(sema: *Sema, val: InternPool.Index) CompileError!Air.Inst.Ref {5705fn uavRef(sema: *Sema, val: InternPool.Index) CompileError!Air.Inst.Ref {
5706 return Air.internedToRef(try sema.refValue(val));5706 return Air.internedToRef(try sema.pt.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 } });
5727}5707}
57285708
5729fn zirInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {5709fn zirInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
...@@ -17402,6 +17382,7 @@ fn analyzeArithmetic(...@@ -17402,6 +17382,7 @@ fn analyzeArithmetic(
1740217382
17403 if (block.wantSafety() and want_safety and scalar_tag == .int) {17383 if (block.wantSafety() and want_safety and scalar_tag == .int) {
17404 if (zcu.backendSupportsFeature(.safety_checked_instructions)) {17384 if (zcu.backendSupportsFeature(.safety_checked_instructions)) {
17385 if (air_tag != air_tag_safe) try sema.preparePanicIntegerOverflow(block, src);
17405 return block.addBinOp(air_tag_safe, casted_lhs, casted_rhs);17386 return block.addBinOp(air_tag_safe, casted_lhs, casted_rhs);
17406 } else {17387 } else {
17407 const maybe_op_ov: ?Air.Inst.Tag = switch (air_tag) {17388 const maybe_op_ov: ?Air.Inst.Tag = switch (air_tag) {
...@@ -27706,6 +27687,24 @@ fn preparePanic(sema: *Sema, block: *Block, src: LazySrcLoc) !void {...@@ -27706,6 +27687,24 @@ fn preparePanic(sema: *Sema, block: *Block, src: LazySrcLoc) !void {
27706 const panic_cause_ty = try pt.getBuiltinType("PanicCause");27687 const panic_cause_ty = try pt.getBuiltinType("PanicCause");
27707 try panic_cause_ty.resolveFields(pt);27688 try panic_cause_ty.resolveFields(pt);
27708 zcu.panic_cause_type = panic_cause_ty.toIntern();27689 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());
27709 }27708 }
27710}27709}
2771127710
...@@ -32669,7 +32668,7 @@ fn optRefValue(sema: *Sema, opt_val: ?Value) !Value {...@@ -32669,7 +32668,7 @@ fn optRefValue(sema: *Sema, opt_val: ?Value) !Value {
32669 return Value.fromInterned(try pt.intern(.{ .opt = .{32668 return Value.fromInterned(try pt.intern(.{ .opt = .{
32670 .ty = (try pt.optionalType(ptr_anyopaque_ty.toIntern())).toIntern(),32669 .ty = (try pt.optionalType(ptr_anyopaque_ty.toIntern())).toIntern(),
32671 .val = if (opt_val) |val| (try pt.getCoerced(32670 .val = if (opt_val) |val| (try pt.getCoerced(
32672 Value.fromInterned(try sema.refValue(val.toIntern())),32671 Value.fromInterned(try pt.refValue(val.toIntern())),
32673 ptr_anyopaque_ty,32672 ptr_anyopaque_ty,
32674 )).toIntern() else .none,32673 )).toIntern() else .none,
32675 } }));32674 } }));
src/Zcu.zig+2
...@@ -214,6 +214,8 @@ free_type_references: std.ArrayListUnmanaged(u32) = .empty,...@@ -214,6 +214,8 @@ free_type_references: std.ArrayListUnmanaged(u32) = .empty,
214panic_func_index: InternPool.Index = .none,214panic_func_index: InternPool.Index = .none,
215null_stack_trace: InternPool.Index = .none,215null_stack_trace: InternPool.Index = .none,
216panic_cause_type: InternPool.Index = .none,216panic_cause_type: InternPool.Index = .none,
217panic_cause_tag_type: InternPool.Index = .none,
218panic_cause_integer_overflow: InternPool.Index = .none,
217219
218generation: u32 = 0,220generation: u32 = 0,
219221
src/Zcu/PerThread.zig+19
...@@ -3656,6 +3656,25 @@ pub fn ensureNamespaceUpToDate(pt: Zcu.PerThread, namespace_index: Zcu.Namespace...@@ -3656,6 +3656,25 @@ pub fn ensureNamespaceUpToDate(pt: Zcu.PerThread, namespace_index: Zcu.Namespace
3656 namespace.generation = zcu.generation;3656 namespace.generation = zcu.generation;
3657}3657}
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
3659const Air = @import("../Air.zig");3678const Air = @import("../Air.zig");
3660const Allocator = std.mem.Allocator;3679const Allocator = std.mem.Allocator;
3661const assert = std.debug.assert;3680const assert = std.debug.assert;
src/codegen/llvm.zig+32-41
...@@ -5677,46 +5677,37 @@ pub const FuncGen = struct {...@@ -5677,46 +5677,37 @@ pub const FuncGen = struct {
56775677
5678 const PanicCauseTag = @typeInfo(std.builtin.PanicCause).@"union".tag_type.?;5678 const PanicCauseTag = @typeInfo(std.builtin.PanicCause).@"union".tag_type.?;
56795679
5680 fn buildSimplePanic(fg: *FuncGen, panic_cause_tag: PanicCauseTag) !void {5680 fn buildSimplePanic(fg: *FuncGen, panic_cause: InternPool.Index) !void {
5681 // TODO update this before merging the branch5681 const o = fg.ng.object;
5682 _ = panic_cause_tag;5682 const zcu = o.pt.zcu;
5683 //const o = fg.ng.object;5683 const ip = &zcu.intern_pool;
5684 //const zcu = o.pt.zcu;5684 const cause_ptr = try o.lowerValue(panic_cause);
5685 //const ip = &zcu.intern_pool;5685 const null_opt_addr_global = try fg.resolveNullOptUsize();
5686 //const msg_nav_index = zcu.panic_messages[@intFromEnum(panic_id)].unwrap().?;5686 const target = zcu.getTarget();
5687 //const msg_nav = ip.getNav(msg_nav_index);5687 // example:
5688 //const msg_len = Type.fromInterned(msg_nav.typeOf(ip)).childType(zcu).arrayLen(zcu);5688 // call fastcc void @test2.panic(
5689 //const msg_ptr = try o.lowerValue(msg_nav.status.resolved.val);5689 // ptr @foo, ; panic_cause
5690 //const null_opt_addr_global = try fg.resolveNullOptUsize();5690 // ptr null, ; stack trace
5691 //const target = zcu.getTarget();5691 // ptr @2, ; addr (null ?usize)
5692 //const llvm_usize = try o.lowerType(Type.usize);5692 // )
5693 //// example:5693 const panic_func = zcu.funcInfo(zcu.panic_func_index);
5694 //// call fastcc void @test2.panic(5694 const panic_nav = ip.getNav(panic_func.owner_nav);
5695 //// ptr @builtin.panic_messages.integer_overflow__anon_987, ; msg.ptr5695 const fn_info = zcu.typeToFunc(Type.fromInterned(panic_nav.typeOf(ip))).?;
5696 //// i64 16, ; msg.len5696 const panic_global = try o.resolveLlvmFunction(panic_func.owner_nav);
5697 //// ptr null, ; stack trace5697 _ = try fg.wip.callIntrinsicAssumeCold();
5698 //// ptr @2, ; addr (null ?usize)5698 _ = try fg.wip.call(
5699 //// )5699 .normal,
5700 //const panic_func = zcu.funcInfo(zcu.panic_func_index);5700 toLlvmCallConv(fn_info.cc, target),
5701 //const panic_nav = ip.getNav(panic_func.owner_nav);5701 .none,
5702 //const fn_info = zcu.typeToFunc(Type.fromInterned(panic_nav.typeOf(ip))).?;5702 panic_global.typeOf(&o.builder),
5703 //const panic_global = try o.resolveLlvmFunction(panic_func.owner_nav);5703 panic_global.toValue(&o.builder),
5704 //_ = try fg.wip.callIntrinsicAssumeCold();5704 &.{
5705 //_ = try fg.wip.call(5705 cause_ptr.toValue(),
5706 // .normal,5706 try o.builder.nullValue(.ptr),
5707 // toLlvmCallConv(fn_info.cc, target),5707 null_opt_addr_global.toValue(),
5708 // .none,5708 },
5709 // panic_global.typeOf(&o.builder),5709 "",
5710 // panic_global.toValue(&o.builder),5710 );
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, &.{}, &.{}, "");
5720 _ = try fg.wip.@"unreachable"();5711 _ = try fg.wip.@"unreachable"();
5721 }5712 }
57225713
...@@ -8340,7 +8331,7 @@ pub const FuncGen = struct {...@@ -8340,7 +8331,7 @@ pub const FuncGen = struct {
8340 _ = try fg.wip.brCond(overflow_bit, fail_block, ok_block, .none);8331 _ = try fg.wip.brCond(overflow_bit, fail_block, ok_block, .none);
83418332
8342 fg.wip.cursor = .{ .block = fail_block };8333 fg.wip.cursor = .{ .block = fail_block };
8343 try fg.buildSimplePanic(.integer_overflow);8334 try fg.buildSimplePanic(zcu.panic_cause_integer_overflow);
83448335
8345 fg.wip.cursor = .{ .block = ok_block };8336 fg.wip.cursor = .{ .block = ok_block };
8346 return fg.wip.extractValue(results, &.{0}, "");8337 return fg.wip.extractValue(results, &.{0}, "");