authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-04-24 17:58:23-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-04-25 11:23:41-07:00
log5378fdffdcc60a5273021bc9cfc5be917e87c992
treeab4ceb8185b8a8fa3977b7fa76e1a49450f0aabb
parentd604553ee0c32caa0632a01e263a34e31a95b2b3

stage2: introduce store_safe AIR instruction

store: The value to store may be undefined, in which case the destination memory region has undefined bytes after this instruction is evaluated. In such case ignoring this instruction is legal lowering. store_safe: Same as `store`, except if the value to store is undefined, the memory region should be filled with 0xaa bytes, and any other safety metadata such as Valgrind integrations should be notified of this memory region being undefined.

13 files changed, 131 insertions(+), 80 deletions(-)

src/Air.zig+14-2
......@@ -485,7 +485,16 @@ pub const Inst = struct {
485485 /// Write a value to a pointer. LHS is pointer, RHS is value.
486486 /// Result type is always void.
487487 /// Uses the `bin_op` field.
488 /// The value to store may be undefined, in which case the destination
489 /// memory region has undefined bytes after this instruction is
490 /// evaluated. In such case ignoring this instruction is legal
491 /// lowering.
488492 store,
493 /// Same as `store`, except if the value to store is undefined, the
494 /// memory region should be filled with 0xaa bytes, and any other
495 /// safety metadata such as Valgrind integrations should be notified of
496 /// this memory region being undefined.
497 store_safe,
489498 /// Indicates the program counter will never get to this instruction.
490499 /// Result type is always noreturn; no instructions in a block follow this one.
491500 unreach,
......@@ -639,8 +648,9 @@ pub const Inst = struct {
639648 /// Result type is always void.
640649 /// Uses the `bin_op` field. LHS is the dest slice. RHS is the element value.
641650 /// The element value may be undefined, in which case the destination
642 /// memory region has undefined bytes after this function executes. In
643 /// such case ignoring this instruction is legal lowering.
651 /// memory region has undefined bytes after this instruction is
652 /// evaluated. In such case ignoring this instruction is legal
653 /// lowering.
644654 /// If the length is compile-time known (due to the destination being a
645655 /// pointer-to-array), then it is guaranteed to be greater than zero.
646656 memset,
......@@ -1242,6 +1252,7 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type {
12421252 .dbg_var_ptr,
12431253 .dbg_var_val,
12441254 .store,
1255 .store_safe,
12451256 .fence,
12461257 .atomic_store_unordered,
12471258 .atomic_store_monotonic,
......@@ -1423,6 +1434,7 @@ pub fn mustLower(air: Air, inst: Air.Inst.Index) bool {
14231434 .ret,
14241435 .ret_load,
14251436 .store,
1437 .store_safe,
14261438 .unreach,
14271439 .optional_payload_ptr_set,
14281440 .errunion_payload_ptr_set,
src/Liveness.zig+2
......@@ -299,6 +299,7 @@ pub fn categorizeOperand(
299299 },
300300
301301 .store,
302 .store_safe,
302303 .atomic_store_unordered,
303304 .atomic_store_monotonic,
304305 .atomic_store_release,
......@@ -965,6 +966,7 @@ fn analyzeInst(
965966 .bool_and,
966967 .bool_or,
967968 .store,
969 .store_safe,
968970 .array_elem_val,
969971 .slice_elem_val,
970972 .ptr_elem_val,
src/Liveness/Verify.zig+1
......@@ -239,6 +239,7 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void {
239239 .bool_and,
240240 .bool_or,
241241 .store,
242 .store_safe,
242243 .array_elem_val,
243244 .slice_elem_val,
244245 .ptr_elem_val,
src/Sema.zig+24-9
......@@ -2500,7 +2500,7 @@ fn coerceResultPtr(
25002500
25012501 // The last one is always `store`.
25022502 const trash_inst = trash_block.instructions.items[trash_block.instructions.items.len - 1];
2503 if (air_tags[trash_inst] != .store) {
2503 if (air_tags[trash_inst] != .store and air_tags[trash_inst] != .store_safe) {
25042504 // no store instruction is generated for zero sized types
25052505 assert((try sema.typeHasOnePossibleValue(pointee_ty)) != null);
25062506 } else {
......@@ -3524,7 +3524,7 @@ fn zirMakePtrConst(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro
35243524 const candidate = block.instructions.items[search_index];
35253525 switch (air_tags[candidate]) {
35263526 .dbg_stmt, .dbg_block_begin, .dbg_block_end => continue,
3527 .store => break candidate,
3527 .store, .store_safe => break candidate,
35283528 else => break :ct,
35293529 }
35303530 };
......@@ -3750,7 +3750,7 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com
37503750 const candidate = block.instructions.items[search_index];
37513751 switch (air_tags[candidate]) {
37523752 .dbg_stmt, .dbg_block_begin, .dbg_block_end => continue,
3753 .store => break candidate,
3753 .store, .store_safe => break candidate,
37543754 else => break :ct,
37553755 }
37563756 };
......@@ -3860,7 +3860,7 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com
38603860 assert(replacement_block.instructions.items.len > 0);
38613861 break :result sub_ptr;
38623862 },
3863 .store => result: {
3863 .store, .store_safe => result: {
38643864 const bin_op = sema.air_instructions.items(.data)[placeholder_inst].bin_op;
38653865 try sema.storePtr2(&replacement_block, src, bin_op.lhs, src, bin_op.rhs, src, .bitcast);
38663866 break :result .void_value;
......@@ -4242,7 +4242,10 @@ fn validateUnionInit(
42424242 while (block_index > 0) : (block_index -= 1) {
42434243 const store_inst = block.instructions.items[block_index];
42444244 if (store_inst == field_ptr_air_inst) break;
4245 if (air_tags[store_inst] != .store) continue;
4245 switch (air_tags[store_inst]) {
4246 .store, .store_safe => {},
4247 else => continue,
4248 }
42464249 const bin_op = air_datas[store_inst].bin_op;
42474250 var lhs = bin_op.lhs;
42484251 if (Air.refToIndex(lhs)) |lhs_index| {
......@@ -4454,7 +4457,10 @@ fn validateStructInit(
44544457 struct_is_comptime = false;
44554458 continue :field;
44564459 }
4457 if (air_tags[store_inst] != .store) continue;
4460 switch (air_tags[store_inst]) {
4461 .store, .store_safe => {},
4462 else => continue,
4463 }
44584464 const bin_op = air_datas[store_inst].bin_op;
44594465 var lhs = bin_op.lhs;
44604466 {
......@@ -4682,7 +4688,10 @@ fn zirValidateArrayInit(
46824688 array_is_comptime = false;
46834689 continue :outer;
46844690 }
4685 if (air_tags[store_inst] != .store) continue;
4691 switch (air_tags[store_inst]) {
4692 .store, .store_safe => {},
4693 else => continue,
4694 }
46864695 const bin_op = air_datas[store_inst].bin_op;
46874696 var lhs = bin_op.lhs;
46884697 {
......@@ -5025,7 +5034,12 @@ fn zirStoreNode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!v
50255034
50265035 const ptr_src: LazySrcLoc = .{ .node_offset_store_ptr = inst_data.src_node };
50275036 const operand_src: LazySrcLoc = .{ .node_offset_store_operand = inst_data.src_node };
5028 const air_tag: Air.Inst.Tag = if (is_ret) .ret_ptr else .store;
5037 const air_tag: Air.Inst.Tag = if (is_ret)
5038 .ret_ptr
5039 else if (block.wantSafety())
5040 .store_safe
5041 else
5042 .store;
50295043 return sema.storePtr2(block, src, ptr, ptr_src, operand, operand_src, air_tag);
50305044}
50315045
......@@ -26704,7 +26718,8 @@ fn storePtr(
2670426718 ptr: Air.Inst.Ref,
2670526719 uncasted_operand: Air.Inst.Ref,
2670626720) CompileError!void {
26707 return sema.storePtr2(block, src, ptr, src, uncasted_operand, src, .store);
26721 const air_tag: Air.Inst.Tag = if (block.wantSafety()) .store_safe else .store;
26722 return sema.storePtr2(block, src, ptr, src, uncasted_operand, src, air_tag);
2670826723}
2670926724
2671026725fn storePtr2(
src/arch/aarch64/CodeGen.zig+8-2
......@@ -764,7 +764,8 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
764764 .ptrtoint => try self.airPtrToInt(inst),
765765 .ret => try self.airRet(inst),
766766 .ret_load => try self.airRetLoad(inst),
767 .store => try self.airStore(inst),
767 .store => try self.airStore(inst, false),
768 .store_safe => try self.airStore(inst, true),
768769 .struct_field_ptr=> try self.airStructFieldPtr(inst),
769770 .struct_field_val=> try self.airStructFieldVal(inst),
770771 .array_to_slice => try self.airArrayToSlice(inst),
......@@ -4036,7 +4037,12 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
40364037 }
40374038}
40384039
4039fn airStore(self: *Self, inst: Air.Inst.Index) !void {
4040fn airStore(self: *Self, inst: Air.Inst.Index, safety: bool) !void {
4041 if (safety) {
4042 // TODO if the value is undef, write 0xaa bytes to dest
4043 } else {
4044 // TODO if the value is undef, don't lower this instruction
4045 }
40404046 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
40414047 const ptr = try self.resolveInst(bin_op.lhs);
40424048 const value = try self.resolveInst(bin_op.rhs);
src/arch/arm/CodeGen.zig+8-2
......@@ -748,7 +748,8 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
748748 .ptrtoint => try self.airPtrToInt(inst),
749749 .ret => try self.airRet(inst),
750750 .ret_load => try self.airRetLoad(inst),
751 .store => try self.airStore(inst),
751 .store => try self.airStore(inst, false),
752 .store_safe => try self.airStore(inst, true),
752753 .struct_field_ptr=> try self.airStructFieldPtr(inst),
753754 .struct_field_val=> try self.airStructFieldVal(inst),
754755 .array_to_slice => try self.airArrayToSlice(inst),
......@@ -2836,7 +2837,12 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
28362837 }
28372838}
28382839
2839fn airStore(self: *Self, inst: Air.Inst.Index) !void {
2840fn airStore(self: *Self, inst: Air.Inst.Index, safety: bool) !void {
2841 if (safety) {
2842 // TODO if the value is undef, write 0xaa bytes to dest
2843 } else {
2844 // TODO if the value is undef, don't lower this instruction
2845 }
28402846 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
28412847 const ptr = try self.resolveInst(bin_op.lhs);
28422848 const value = try self.resolveInst(bin_op.rhs);
src/arch/riscv64/CodeGen.zig+8-2
......@@ -578,7 +578,8 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
578578 .ptrtoint => try self.airPtrToInt(inst),
579579 .ret => try self.airRet(inst),
580580 .ret_load => try self.airRetLoad(inst),
581 .store => try self.airStore(inst),
581 .store => try self.airStore(inst, false),
582 .store_safe => try self.airStore(inst, true),
582583 .struct_field_ptr=> try self.airStructFieldPtr(inst),
583584 .struct_field_val=> try self.airStructFieldVal(inst),
584585 .array_to_slice => try self.airArrayToSlice(inst),
......@@ -1573,7 +1574,12 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
15731574 }
15741575}
15751576
1576fn airStore(self: *Self, inst: Air.Inst.Index) !void {
1577fn airStore(self: *Self, inst: Air.Inst.Index, safety: bool) !void {
1578 if (safety) {
1579 // TODO if the value is undef, write 0xaa bytes to dest
1580 } else {
1581 // TODO if the value is undef, don't lower this instruction
1582 }
15771583 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
15781584 const ptr = try self.resolveInst(bin_op.lhs);
15791585 const value = try self.resolveInst(bin_op.rhs);
src/arch/sparc64/CodeGen.zig+8-2
......@@ -593,7 +593,8 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
593593 .ptrtoint => try self.airPtrToInt(inst),
594594 .ret => try self.airRet(inst),
595595 .ret_load => try self.airRetLoad(inst),
596 .store => try self.airStore(inst),
596 .store => try self.airStore(inst, false),
597 .store_safe => try self.airStore(inst, true),
597598 .struct_field_ptr=> @panic("TODO try self.airStructFieldPtr(inst)"),
598599 .struct_field_val=> try self.airStructFieldVal(inst),
599600 .array_to_slice => try self.airArrayToSlice(inst),
......@@ -2407,7 +2408,12 @@ fn airSplat(self: *Self, inst: Air.Inst.Index) !void {
24072408 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
24082409}
24092410
2410fn airStore(self: *Self, inst: Air.Inst.Index) !void {
2411fn airStore(self: *Self, inst: Air.Inst.Index, safety: bool) !void {
2412 if (safety) {
2413 // TODO if the value is undef, write 0xaa bytes to dest
2414 } else {
2415 // TODO if the value is undef, don't lower this instruction
2416 }
24112417 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
24122418 const ptr = try self.resolveInst(bin_op.lhs);
24132419 const value = try self.resolveInst(bin_op.rhs);
src/arch/wasm/CodeGen.zig+16-5
......@@ -1883,8 +1883,8 @@ fn genInst(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
18831883
18841884 .load => func.airLoad(inst),
18851885 .loop => func.airLoop(inst),
1886 // TODO: elide memset when writing undef without safety
1887 .memset, .memset_safe => func.airMemset(inst),
1886 .memset => func.airMemset(inst, false),
1887 .memset_safe => func.airMemset(inst, true),
18881888 .not => func.airNot(inst),
18891889 .optional_payload => func.airOptionalPayload(inst),
18901890 .optional_payload_ptr => func.airOptionalPayloadPtr(inst),
......@@ -1914,7 +1914,8 @@ fn genInst(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
19141914 .slice_ptr => func.airSlicePtr(inst),
19151915 .ptr_slice_len_ptr => func.airPtrSliceFieldPtr(inst, func.ptrSize()),
19161916 .ptr_slice_ptr_ptr => func.airPtrSliceFieldPtr(inst, 0),
1917 .store => func.airStore(inst),
1917 .store => func.airStore(inst, false),
1918 .store_safe => func.airStore(inst, true),
19181919
19191920 .set_union_tag => func.airSetUnionTag(inst),
19201921 .struct_field_ptr => func.airStructFieldPtr(inst),
......@@ -2222,7 +2223,12 @@ fn airAlloc(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
22222223 func.finishAir(inst, value, &.{});
22232224}
22242225
2225fn airStore(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
2226fn airStore(func: *CodeGen, inst: Air.Inst.Index, safety: bool) InnerError!void {
2227 if (safety) {
2228 // TODO if the value is undef, write 0xaa bytes to dest
2229 } else {
2230 // TODO if the value is undef, don't lower this instruction
2231 }
22262232 const bin_op = func.air.instructions.items(.data)[inst].bin_op;
22272233
22282234 const lhs = try func.resolveInst(bin_op.lhs);
......@@ -4384,7 +4390,12 @@ fn airPtrBinOp(func: *CodeGen, inst: Air.Inst.Index, op: Op) InnerError!void {
43844390 func.finishAir(inst, result, &.{ bin_op.lhs, bin_op.rhs });
43854391}
43864392
4387fn airMemset(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
4393fn airMemset(func: *CodeGen, inst: Air.Inst.Index, safety: bool) InnerError!void {
4394 if (safety) {
4395 // TODO if the value is undef, write 0xaa bytes to dest
4396 } else {
4397 // TODO if the value is undef, don't lower this instruction
4398 }
43884399 const bin_op = func.air.instructions.items(.data)[inst].bin_op;
43894400
43904401 const ptr = try func.resolveInst(bin_op.lhs);
src/arch/x86_64/CodeGen.zig+8-2
......@@ -1035,7 +1035,8 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
10351035 .ptrtoint => try self.airPtrToInt(inst),
10361036 .ret => try self.airRet(inst),
10371037 .ret_load => try self.airRetLoad(inst),
1038 .store => try self.airStore(inst),
1038 .store => try self.airStore(inst, false),
1039 .store_safe => try self.airStore(inst, true),
10391040 .struct_field_ptr=> try self.airStructFieldPtr(inst),
10401041 .struct_field_val=> try self.airStructFieldVal(inst),
10411042 .array_to_slice => try self.airArrayToSlice(inst),
......@@ -3936,7 +3937,12 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
39363937 }
39373938}
39383939
3939fn airStore(self: *Self, inst: Air.Inst.Index) !void {
3940fn airStore(self: *Self, inst: Air.Inst.Index, safety: bool) !void {
3941 if (safety) {
3942 // TODO if the value is undef, write 0xaa bytes to dest
3943 } else {
3944 // TODO if the value is undef, don't lower this instruction
3945 }
39403946 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
39413947 const ptr = try self.resolveInst(bin_op.lhs);
39423948 const ptr_ty = self.air.typeOf(bin_op.lhs);
src/codegen/c.zig+15-25
......@@ -2914,7 +2914,8 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail,
29142914 .load => try airLoad(f, inst),
29152915 .ret => try airRet(f, inst, false),
29162916 .ret_load => try airRet(f, inst, true),
2917 .store => try airStore(f, inst),
2917 .store => try airStore(f, inst, false),
2918 .store_safe => try airStore(f, inst, true),
29182919 .loop => try airLoop(f, inst),
29192920 .cond_br => try airCondBr(f, inst),
29202921 .br => try airBr(f, inst),
......@@ -3565,19 +3566,7 @@ fn airBoolToInt(f: *Function, inst: Air.Inst.Index) !CValue {
35653566 return local;
35663567}
35673568
3568fn storeUndefined(f: *Function, lhs_child_ty: Type, dest_ptr: CValue) !CValue {
3569 if (f.wantSafety()) {
3570 const writer = f.object.writer();
3571 try writer.writeAll("memset(");
3572 try f.writeCValue(writer, dest_ptr, .FunctionArgument);
3573 try writer.print(", {x}, sizeof(", .{try f.fmtIntLiteral(Type.u8, Value.undef)});
3574 try f.renderType(writer, lhs_child_ty);
3575 try writer.writeAll("));\n");
3576 }
3577 return .none;
3578}
3579
3580fn airStore(f: *Function, inst: Air.Inst.Index) !CValue {
3569fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
35813570 // *a = b;
35823571 const bin_op = f.air.instructions.items(.data)[inst].bin_op;
35833572
......@@ -3588,18 +3577,19 @@ fn airStore(f: *Function, inst: Air.Inst.Index) !CValue {
35883577 const ptr_val = try f.resolveInst(bin_op.lhs);
35893578 const src_ty = f.air.typeOf(bin_op.rhs);
35903579
3591 // TODO Sema should emit a different instruction when the store should
3592 // possibly do the safety 0xaa bytes for undefined.
3593 const src_val_is_undefined =
3594 if (f.air.value(bin_op.rhs)) |v| v.isUndefDeep() else false;
3595 if (src_val_is_undefined) {
3596 if (ptr_info.host_size == 0) {
3597 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
3598 return try storeUndefined(f, ptr_info.pointee_type, ptr_val);
3599 } else if (!f.wantSafety()) {
3600 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
3601 return .none;
3580 const val_is_undef = if (f.air.value(bin_op.rhs)) |v| v.isUndefDeep() else false;
3581
3582 if (val_is_undef) {
3583 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
3584 if (safety and ptr_info.host_size == 0) {
3585 const writer = f.object.writer();
3586 try writer.writeAll("memset(");
3587 try f.writeCValue(writer, ptr_val, .FunctionArgument);
3588 try writer.writeAll(", 0xaa, sizeof(");
3589 try f.renderType(writer, ptr_info.pointee_type);
3590 try writer.writeAll("));\n");
36023591 }
3592 return .none;
36033593 }
36043594
36053595 const target = f.object.dg.module.getTarget();
src/codegen/llvm.zig+18-29
......@@ -4649,7 +4649,8 @@ pub const FuncGen = struct {
46494649 .not => try self.airNot(inst),
46504650 .ret => try self.airRet(inst),
46514651 .ret_load => try self.airRetLoad(inst),
4652 .store => try self.airStore(inst),
4652 .store => try self.airStore(inst, false),
4653 .store_safe => try self.airStore(inst, true),
46534654 .assembly => try self.airAssembly(inst),
46544655 .slice_ptr => try self.airSliceField(inst, 0),
46554656 .slice_len => try self.airSliceField(inst, 1),
......@@ -8115,48 +8116,36 @@ pub const FuncGen = struct {
81158116 return buildAllocaInner(self.context, self.builder, self.llvm_func, self.di_scope != null, llvm_ty, alignment, self.dg.module.getTarget());
81168117 }
81178118
8118 fn airStore(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
8119 fn airStore(self: *FuncGen, inst: Air.Inst.Index, safety: bool) !?*llvm.Value {
81198120 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
81208121 const dest_ptr = try self.resolveInst(bin_op.lhs);
81218122 const ptr_ty = self.air.typeOf(bin_op.lhs);
81228123 const operand_ty = ptr_ty.childType();
81238124
8124 // TODO Sema should emit a different instruction when the store should
8125 // possibly do the safety 0xaa bytes for undefined.
81268125 const val_is_undef = if (self.air.value(bin_op.rhs)) |val| val.isUndefDeep() else false;
81278126 if (val_is_undef) {
8128 {
8129 // TODO let's handle this in AIR rather than by having each backend
8130 // check the optimization mode of the compilation because the plan is
8131 // to support setting the optimization mode at finer grained scopes
8132 // which happens in Sema. Codegen should not be aware of this logic.
8133 // I think this comment is basically the same as the other TODO comment just
8134 // above but I'm leaving them both here to make it look super messy and
8135 // thereby bait contributors (or let's be honest, probably myself) into
8136 // fixing this instead of letting it rot.
8137 const safety = switch (self.dg.module.comp.bin_file.options.optimize_mode) {
8138 .ReleaseSmall, .ReleaseFast => false,
8139 .Debug, .ReleaseSafe => true,
8140 };
8141 if (!safety) {
8142 return null;
8143 }
8144 }
8127 // Even if safety is disabled, we still emit a memset to undefined since it conveys
8128 // extra information to LLVM. However, safety makes the difference between using
8129 // 0xaa or actual undefined for the fill byte.
8130 const u8_llvm_ty = self.context.intType(8);
8131 const fill_byte = if (safety)
8132 u8_llvm_ty.constInt(0xaa, .False)
8133 else
8134 u8_llvm_ty.getUndef();
81458135 const target = self.dg.module.getTarget();
81468136 const operand_size = operand_ty.abiSize(target);
8147 const u8_llvm_ty = self.context.intType(8);
8148 const fill_char = u8_llvm_ty.constInt(0xaa, .False);
8149 const dest_ptr_align = ptr_ty.ptrAlignment(target);
81508137 const usize_llvm_ty = try self.dg.lowerType(Type.usize);
81518138 const len = usize_llvm_ty.constInt(operand_size, .False);
8152 _ = self.builder.buildMemSet(dest_ptr, fill_char, len, dest_ptr_align, ptr_ty.isVolatilePtr());
8153 if (self.dg.module.comp.bin_file.options.valgrind) {
8139 const dest_ptr_align = ptr_ty.ptrAlignment(target);
8140 _ = self.builder.buildMemSet(dest_ptr, fill_byte, len, dest_ptr_align, ptr_ty.isVolatilePtr());
8141 if (safety and self.dg.module.comp.bin_file.options.valgrind) {
81548142 self.valgrindMarkUndef(dest_ptr, len);
81558143 }
8156 } else {
8157 const src_operand = try self.resolveInst(bin_op.rhs);
8158 try self.store(dest_ptr, ptr_ty, src_operand, .NotAtomic);
8144 return null;
81598145 }
8146
8147 const src_operand = try self.resolveInst(bin_op.rhs);
8148 try self.store(dest_ptr, ptr_ty, src_operand, .NotAtomic);
81608149 return null;
81618150 }
81628151
src/print_air.zig+1
......@@ -140,6 +140,7 @@ const Writer = struct {
140140 .bool_and,
141141 .bool_or,
142142 .store,
143 .store_safe,
143144 .array_elem_val,
144145 .slice_elem_val,
145146 .ptr_elem_val,