authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-10-22 16:23:34-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-10-22 16:23:34-07:00
logb24e9b6347afc66aa94f61b3ed4c2d02cdb0d0ee
tree7a9d2af51b046c8422facc14377b99a210250787
parentf0dcdd7931f1eb4f3b6a0a87c914baf770f6df03

Sema: fix a couple use-after-free bugs

Also switch to the more efficient encoding of the bitcast instruction when the destination type is anyerror in 2 common cases. LLVM backend: fix using the wrong type as the optional payload type in the `wrap_optional` AIR instruction.

2 files changed, 41 insertions(+), 23 deletions(-)

src/Sema.zig+39-19
...@@ -224,6 +224,16 @@ pub const Block = struct {...@@ -224,6 +224,16 @@ pub const Block = struct {
224 });224 });
225 }225 }
226226
227 pub fn addBitCast(block: *Block, ty: Type, operand: Air.Inst.Ref) Allocator.Error!Air.Inst.Ref {
228 return block.addInst(.{
229 .tag = .bitcast,
230 .data = .{ .ty_op = .{
231 .ty = try block.sema.addType(ty),
232 .operand = operand,
233 } },
234 });
235 }
236
227 pub fn addNoOp(block: *Block, tag: Air.Inst.Tag) error{OutOfMemory}!Air.Inst.Ref {237 pub fn addNoOp(block: *Block, tag: Air.Inst.Tag) error{OutOfMemory}!Air.Inst.Ref {
228 return block.addInst(.{238 return block.addInst(.{
229 .tag = tag,239 .tag = tag,
...@@ -1409,7 +1419,7 @@ fn zirCoerceResultPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE...@@ -1409,7 +1419,7 @@ fn zirCoerceResultPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE
1409 // for the inferred allocation.1419 // for the inferred allocation.
1410 // This instruction will not make it to codegen; it is only to participate1420 // This instruction will not make it to codegen; it is only to participate
1411 // in the `stored_inst_list` of the `inferred_alloc`.1421 // in the `stored_inst_list` of the `inferred_alloc`.
1412 const operand = try block.addTyOp(.bitcast, pointee_ty, .void_value);1422 const operand = try block.addBitCast(pointee_ty, .void_value);
1413 try inferred_alloc.stored_inst_list.append(sema.arena, operand);1423 try inferred_alloc.stored_inst_list.append(sema.arena, operand);
1414 },1424 },
1415 .inferred_alloc_comptime => {1425 .inferred_alloc_comptime => {
...@@ -1436,7 +1446,7 @@ fn zirCoerceResultPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE...@@ -1436,7 +1446,7 @@ fn zirCoerceResultPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE
1436 }1446 }
1437 }1447 }
1438 try sema.requireRuntimeBlock(block, src);1448 try sema.requireRuntimeBlock(block, src);
1439 const bitcasted_ptr = try block.addTyOp(.bitcast, ptr_ty, ptr);1449 const bitcasted_ptr = try block.addBitCast(ptr_ty, ptr);
1440 return bitcasted_ptr;1450 return bitcasted_ptr;
1441}1451}
14421452
...@@ -2509,7 +2519,7 @@ fn zirStoreToBlockPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE...@@ -2509,7 +2519,7 @@ fn zirStoreToBlockPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE
2509 // if expressions should force it when the condition is compile-time known.2519 // if expressions should force it when the condition is compile-time known.
2510 const src: LazySrcLoc = .unneeded;2520 const src: LazySrcLoc = .unneeded;
2511 try sema.requireRuntimeBlock(block, src);2521 try sema.requireRuntimeBlock(block, src);
2512 const bitcasted_ptr = try block.addTyOp(.bitcast, ptr_ty, ptr);2522 const bitcasted_ptr = try block.addBitCast(ptr_ty, ptr);
2513 return sema.storePtr(block, src, bitcasted_ptr, value);2523 return sema.storePtr(block, src, bitcasted_ptr, value);
2514}2524}
25152525
...@@ -2555,7 +2565,7 @@ fn zirStoreToInferredPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Compi...@@ -2555,7 +2565,7 @@ fn zirStoreToInferredPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Compi
2555 .pointee_type = operand_ty,2565 .pointee_type = operand_ty,
2556 .@"addrspace" = target_util.defaultAddressSpace(sema.mod.getTarget(), .local),2566 .@"addrspace" = target_util.defaultAddressSpace(sema.mod.getTarget(), .local),
2557 });2567 });
2558 const bitcasted_ptr = try block.addTyOp(.bitcast, ptr_ty, ptr);2568 const bitcasted_ptr = try block.addBitCast(ptr_ty, ptr);
2559 return sema.storePtr(block, src, bitcasted_ptr, operand);2569 return sema.storePtr(block, src, bitcasted_ptr, operand);
2560 }2570 }
2561 unreachable;2571 unreachable;
...@@ -4310,7 +4320,7 @@ fn zirErrorToInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!...@@ -4310,7 +4320,7 @@ fn zirErrorToInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!
4310 }4320 }
43114321
4312 try sema.requireRuntimeBlock(block, src);4322 try sema.requireRuntimeBlock(block, src);
4313 return block.addTyOp(.bitcast, result_ty, op_coerced);4323 return block.addBitCast(result_ty, op_coerced);
4314}4324}
43154325
4316fn zirIntToError(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {4326fn zirIntToError(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
...@@ -4340,7 +4350,13 @@ fn zirIntToError(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!...@@ -4340,7 +4350,13 @@ fn zirIntToError(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!
4340 // const is_gt_max = @panic("TODO get max errors in compilation");4350 // const is_gt_max = @panic("TODO get max errors in compilation");
4341 // try sema.addSafetyCheck(block, is_gt_max, .invalid_error_code);4351 // try sema.addSafetyCheck(block, is_gt_max, .invalid_error_code);
4342 }4352 }
4343 return block.addTyOp(.bitcast, Type.anyerror, op);4353 return block.addInst(.{
4354 .tag = .bitcast,
4355 .data = .{ .ty_op = .{
4356 .ty = Air.Inst.Ref.anyerror_type,
4357 .operand = op,
4358 } },
4359 });
4344}4360}
43454361
4346fn zirMergeErrorSets(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {4362fn zirMergeErrorSets(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
...@@ -4483,7 +4499,7 @@ fn zirEnumToInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A...@@ -4483,7 +4499,7 @@ fn zirEnumToInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
4483 }4499 }
44844500
4485 try sema.requireRuntimeBlock(block, src);4501 try sema.requireRuntimeBlock(block, src);
4486 return block.addTyOp(.bitcast, int_tag_ty, enum_tag);4502 return block.addBitCast(int_tag_ty, enum_tag);
4487}4503}
44884504
4489fn zirIntToEnum(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {4505fn zirIntToEnum(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
...@@ -9620,7 +9636,7 @@ fn zirIntToPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -9620,7 +9636,7 @@ fn zirIntToPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
9620 try sema.addSafetyCheck(block, is_aligned, .incorrect_alignment);9636 try sema.addSafetyCheck(block, is_aligned, .incorrect_alignment);
9621 }9637 }
9622 }9638 }
9623 return block.addTyOp(.bitcast, type_res, operand_coerced);9639 return block.addBitCast(type_res, operand_coerced);
9624}9640}
96259641
9626fn zirErrSetCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {9642fn zirErrSetCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
...@@ -9650,7 +9666,7 @@ fn zirPtrCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -9650,7 +9666,7 @@ fn zirPtrCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
9650 if (try sema.resolveMaybeUndefVal(block, operand_src, operand)) |val| {9666 if (try sema.resolveMaybeUndefVal(block, operand_src, operand)) |val| {
9651 return sema.addConstant(dest_ty, val);9667 return sema.addConstant(dest_ty, val);
9652 }9668 }
9653 return block.addTyOp(.bitcast, dest_ty, operand);9669 return block.addBitCast(dest_ty, operand);
9654}9670}
96559671
9656fn zirTruncate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {9672fn zirTruncate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
...@@ -11871,7 +11887,7 @@ fn coerce(...@@ -11871,7 +11887,7 @@ fn coerce(
11871 return sema.addConstant(dest_ty, val);11887 return sema.addConstant(dest_ty, val);
11872 }11888 }
11873 try sema.requireRuntimeBlock(block, inst_src);11889 try sema.requireRuntimeBlock(block, inst_src);
11874 return block.addTyOp(.bitcast, dest_ty, inst);11890 return block.addBitCast(dest_ty, inst);
11875 }11891 }
1187611892
11877 // undefined to anything11893 // undefined to anything
...@@ -11896,8 +11912,7 @@ fn coerce(...@@ -11896,8 +11912,7 @@ fn coerce(
11896 }11912 }
1189711913
11898 // T to ?T11914 // T to ?T
11899 var buf: Type.Payload.ElemType = undefined;11915 const child_type = try dest_ty.optionalChildAlloc(sema.arena);
11900 const child_type = dest_ty.optionalChild(&buf);
11901 const intermediate = try sema.coerce(block, child_type, inst, inst_src);11916 const intermediate = try sema.coerce(block, child_type, inst, inst_src);
11902 return sema.wrapOptional(block, dest_ty, intermediate, inst_src);11917 return sema.wrapOptional(block, dest_ty, intermediate, inst_src);
11903 },11918 },
...@@ -12603,11 +12618,10 @@ fn beginComptimePtrLoad(...@@ -12603,11 +12618,10 @@ fn beginComptimePtrLoad(
12603 .opt_payload_ptr => {12618 .opt_payload_ptr => {
12604 const opt_ptr = ptr_val.castTag(.opt_payload_ptr).?.data;12619 const opt_ptr = ptr_val.castTag(.opt_payload_ptr).?.data;
12605 const parent = try beginComptimePtrLoad(sema, block, src, opt_ptr);12620 const parent = try beginComptimePtrLoad(sema, block, src, opt_ptr);
12606 var buf: Type.Payload.ElemType = undefined;
12607 return ComptimePtrLoadKit{12621 return ComptimePtrLoadKit{
12608 .root_val = parent.root_val,12622 .root_val = parent.root_val,
12609 .val = parent.val.castTag(.opt_payload).?.data,12623 .val = parent.val.castTag(.opt_payload).?.data,
12610 .ty = parent.ty.optionalChild(&buf),12624 .ty = try parent.ty.optionalChildAlloc(sema.arena),
12611 .byte_offset = undefined,12625 .byte_offset = undefined,
12612 .is_mutable = parent.is_mutable,12626 .is_mutable = parent.is_mutable,
12613 };12627 };
...@@ -12643,7 +12657,7 @@ fn bitCast(...@@ -12643,7 +12657,7 @@ fn bitCast(
12643 return sema.addConstant(dest_ty, result_val);12657 return sema.addConstant(dest_ty, result_val);
12644 }12658 }
12645 try sema.requireRuntimeBlock(block, inst_src);12659 try sema.requireRuntimeBlock(block, inst_src);
12646 return block.addTyOp(.bitcast, dest_ty, inst);12660 return block.addBitCast(dest_ty, inst);
12647}12661}
1264812662
12649fn coerceArrayPtrToSlice(12663fn coerceArrayPtrToSlice(
...@@ -12756,7 +12770,7 @@ fn coerceEnumToUnion(...@@ -12756,7 +12770,7 @@ fn coerceEnumToUnion(
1275612770
12757 // If the union has all fields 0 bits, the union value is just the enum value.12771 // If the union has all fields 0 bits, the union value is just the enum value.
12758 if (union_ty.unionHasAllZeroBitFieldTypes()) {12772 if (union_ty.unionHasAllZeroBitFieldTypes()) {
12759 return block.addTyOp(.bitcast, union_ty, enum_tag);12773 return block.addBitCast(union_ty, enum_tag);
12760 }12774 }
1276112775
12762 // TODO resolve the field names and add a hint that says "field 'foo' has type 'bar'"12776 // TODO resolve the field names and add a hint that says "field 'foo' has type 'bar'"
...@@ -12814,7 +12828,7 @@ fn coerceVectorInMemory(...@@ -12814,7 +12828,7 @@ fn coerceVectorInMemory(
12814 }12828 }
1281512829
12816 try sema.requireRuntimeBlock(block, inst_src);12830 try sema.requireRuntimeBlock(block, inst_src);
12817 return block.addTyOp(.bitcast, dest_ty, inst);12831 return block.addBitCast(dest_ty, inst);
12818}12832}
1281912833
12820fn coerceCompatibleErrorSets(12834fn coerceCompatibleErrorSets(
...@@ -12828,7 +12842,13 @@ fn coerceCompatibleErrorSets(...@@ -12828,7 +12842,13 @@ fn coerceCompatibleErrorSets(
12828 return sema.addConstant(Type.anyerror, err_set_val);12842 return sema.addConstant(Type.anyerror, err_set_val);
12829 }12843 }
12830 try sema.requireRuntimeBlock(block, err_set_src);12844 try sema.requireRuntimeBlock(block, err_set_src);
12831 return block.addTyOp(.bitcast, Type.anyerror, err_set);12845 return block.addInst(.{
12846 .tag = .bitcast,
12847 .data = .{ .ty_op = .{
12848 .ty = Air.Inst.Ref.anyerror_type,
12849 .operand = err_set,
12850 } },
12851 });
12832}12852}
1283312853
12834fn analyzeDeclVal(12854fn analyzeDeclVal(
...@@ -13128,7 +13148,7 @@ fn analyzeSlice(...@@ -13128,7 +13148,7 @@ fn analyzeSlice(
13128 if (opt_new_ptr_val) |new_ptr_val| {13148 if (opt_new_ptr_val) |new_ptr_val| {
13129 return sema.addConstant(return_ty, new_ptr_val);13149 return sema.addConstant(return_ty, new_ptr_val);
13130 } else {13150 } else {
13131 return block.addTyOp(.bitcast, return_ty, new_ptr);13151 return block.addBitCast(return_ty, new_ptr);
13132 }13152 }
13133 }13153 }
1313413154
src/codegen/llvm.zig+2-4
...@@ -2598,9 +2598,9 @@ pub const FuncGen = struct {...@@ -2598,9 +2598,9 @@ pub const FuncGen = struct {
2598 if (self.liveness.isUnused(inst)) return null;2598 if (self.liveness.isUnused(inst)) return null;
25992599
2600 const ty_op = self.air.instructions.items(.data)[inst].ty_op;2600 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
2601 const operand_ty = self.air.typeOf(ty_op.operand);2601 const payload_ty = self.air.typeOf(ty_op.operand);
2602 const non_null_bit = self.context.intType(1).constAllOnes();2602 const non_null_bit = self.context.intType(1).constAllOnes();
2603 if (!operand_ty.hasCodeGenBits()) return non_null_bit;2603 if (!payload_ty.hasCodeGenBits()) return non_null_bit;
2604 const operand = try self.resolveInst(ty_op.operand);2604 const operand = try self.resolveInst(ty_op.operand);
2605 const optional_ty = self.air.typeOfIndex(inst);2605 const optional_ty = self.air.typeOfIndex(inst);
2606 if (optional_ty.isPtrLikeOptional()) return operand;2606 if (optional_ty.isPtrLikeOptional()) return operand;
...@@ -2608,8 +2608,6 @@ pub const FuncGen = struct {...@@ -2608,8 +2608,6 @@ pub const FuncGen = struct {
2608 if (isByRef(optional_ty)) {2608 if (isByRef(optional_ty)) {
2609 const optional_ptr = self.buildAlloca(llvm_optional_ty);2609 const optional_ptr = self.buildAlloca(llvm_optional_ty);
2610 const payload_ptr = self.builder.buildStructGEP(optional_ptr, 0, "");2610 const payload_ptr = self.builder.buildStructGEP(optional_ptr, 0, "");
2611 var buf: Type.Payload.ElemType = undefined;
2612 const payload_ty = operand_ty.optionalChild(&buf);
2613 var ptr_ty_payload: Type.Payload.ElemType = .{2611 var ptr_ty_payload: Type.Payload.ElemType = .{
2614 .base = .{ .tag = .single_mut_pointer },2612 .base = .{ .tag = .single_mut_pointer },
2615 .data = payload_ty,2613 .data = payload_ty,