diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2021-10-22 16:23:34 -0700 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2021-10-22 16:23:34 -0700 |
| commit | b24e9b6347afc66aa94f61b3ed4c2d02cdb0d0ee (patch) | |
| tree | 7a9d2af51b046c8422facc14377b99a210250787 /src | |
| parent | f0dcdd7931f1eb4f3b6a0a87c914baf770f6df03 (diff) | |
| download | zig-b24e9b6347afc66aa94f61b3ed4c2d02cdb0d0ee.tar.gz zig-b24e9b6347afc66aa94f61b3ed4c2d02cdb0d0ee.zip | |
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.
Diffstat (limited to 'src')
| -rw-r--r-- | src/Sema.zig | 58 | ||||
| -rw-r--r-- | src/codegen/llvm.zig | 6 |
2 files changed, 41 insertions, 23 deletions
diff --git a/src/Sema.zig b/src/Sema.zig index 166b668731..92a3a6a50f 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -224,6 +224,16 @@ pub const Block = struct { }); } + pub fn addBitCast(block: *Block, ty: Type, operand: Air.Inst.Ref) Allocator.Error!Air.Inst.Ref { + return block.addInst(.{ + .tag = .bitcast, + .data = .{ .ty_op = .{ + .ty = try block.sema.addType(ty), + .operand = operand, + } }, + }); + } + pub fn addNoOp(block: *Block, tag: Air.Inst.Tag) error{OutOfMemory}!Air.Inst.Ref { return block.addInst(.{ .tag = tag, @@ -1409,7 +1419,7 @@ fn zirCoerceResultPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE // for the inferred allocation. // This instruction will not make it to codegen; it is only to participate // in the `stored_inst_list` of the `inferred_alloc`. - const operand = try block.addTyOp(.bitcast, pointee_ty, .void_value); + const operand = try block.addBitCast(pointee_ty, .void_value); try inferred_alloc.stored_inst_list.append(sema.arena, operand); }, .inferred_alloc_comptime => { @@ -1436,7 +1446,7 @@ fn zirCoerceResultPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE } } try sema.requireRuntimeBlock(block, src); - const bitcasted_ptr = try block.addTyOp(.bitcast, ptr_ty, ptr); + const bitcasted_ptr = try block.addBitCast(ptr_ty, ptr); return bitcasted_ptr; } @@ -2509,7 +2519,7 @@ fn zirStoreToBlockPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE // if expressions should force it when the condition is compile-time known. const src: LazySrcLoc = .unneeded; try sema.requireRuntimeBlock(block, src); - const bitcasted_ptr = try block.addTyOp(.bitcast, ptr_ty, ptr); + const bitcasted_ptr = try block.addBitCast(ptr_ty, ptr); return sema.storePtr(block, src, bitcasted_ptr, value); } @@ -2555,7 +2565,7 @@ fn zirStoreToInferredPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Compi .pointee_type = operand_ty, .@"addrspace" = target_util.defaultAddressSpace(sema.mod.getTarget(), .local), }); - const bitcasted_ptr = try block.addTyOp(.bitcast, ptr_ty, ptr); + const bitcasted_ptr = try block.addBitCast(ptr_ty, ptr); return sema.storePtr(block, src, bitcasted_ptr, operand); } unreachable; @@ -4310,7 +4320,7 @@ fn zirErrorToInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! } try sema.requireRuntimeBlock(block, src); - return block.addTyOp(.bitcast, result_ty, op_coerced); + return block.addBitCast(result_ty, op_coerced); } fn 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! // const is_gt_max = @panic("TODO get max errors in compilation"); // try sema.addSafetyCheck(block, is_gt_max, .invalid_error_code); } - return block.addTyOp(.bitcast, Type.anyerror, op); + return block.addInst(.{ + .tag = .bitcast, + .data = .{ .ty_op = .{ + .ty = Air.Inst.Ref.anyerror_type, + .operand = op, + } }, + }); } fn 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 } try sema.requireRuntimeBlock(block, src); - return block.addTyOp(.bitcast, int_tag_ty, enum_tag); + return block.addBitCast(int_tag_ty, enum_tag); } fn 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 try sema.addSafetyCheck(block, is_aligned, .incorrect_alignment); } } - return block.addTyOp(.bitcast, type_res, operand_coerced); + return block.addBitCast(type_res, operand_coerced); } fn 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 if (try sema.resolveMaybeUndefVal(block, operand_src, operand)) |val| { return sema.addConstant(dest_ty, val); } - return block.addTyOp(.bitcast, dest_ty, operand); + return block.addBitCast(dest_ty, operand); } fn zirTruncate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { @@ -11871,7 +11887,7 @@ fn coerce( return sema.addConstant(dest_ty, val); } try sema.requireRuntimeBlock(block, inst_src); - return block.addTyOp(.bitcast, dest_ty, inst); + return block.addBitCast(dest_ty, inst); } // undefined to anything @@ -11896,8 +11912,7 @@ fn coerce( } // T to ?T - var buf: Type.Payload.ElemType = undefined; - const child_type = dest_ty.optionalChild(&buf); + const child_type = try dest_ty.optionalChildAlloc(sema.arena); const intermediate = try sema.coerce(block, child_type, inst, inst_src); return sema.wrapOptional(block, dest_ty, intermediate, inst_src); }, @@ -12603,11 +12618,10 @@ fn beginComptimePtrLoad( .opt_payload_ptr => { const opt_ptr = ptr_val.castTag(.opt_payload_ptr).?.data; const parent = try beginComptimePtrLoad(sema, block, src, opt_ptr); - var buf: Type.Payload.ElemType = undefined; return ComptimePtrLoadKit{ .root_val = parent.root_val, .val = parent.val.castTag(.opt_payload).?.data, - .ty = parent.ty.optionalChild(&buf), + .ty = try parent.ty.optionalChildAlloc(sema.arena), .byte_offset = undefined, .is_mutable = parent.is_mutable, }; @@ -12643,7 +12657,7 @@ fn bitCast( return sema.addConstant(dest_ty, result_val); } try sema.requireRuntimeBlock(block, inst_src); - return block.addTyOp(.bitcast, dest_ty, inst); + return block.addBitCast(dest_ty, inst); } fn coerceArrayPtrToSlice( @@ -12756,7 +12770,7 @@ fn coerceEnumToUnion( // If the union has all fields 0 bits, the union value is just the enum value. if (union_ty.unionHasAllZeroBitFieldTypes()) { - return block.addTyOp(.bitcast, union_ty, enum_tag); + return block.addBitCast(union_ty, enum_tag); } // TODO resolve the field names and add a hint that says "field 'foo' has type 'bar'" @@ -12814,7 +12828,7 @@ fn coerceVectorInMemory( } try sema.requireRuntimeBlock(block, inst_src); - return block.addTyOp(.bitcast, dest_ty, inst); + return block.addBitCast(dest_ty, inst); } fn coerceCompatibleErrorSets( @@ -12828,7 +12842,13 @@ fn coerceCompatibleErrorSets( return sema.addConstant(Type.anyerror, err_set_val); } try sema.requireRuntimeBlock(block, err_set_src); - return block.addTyOp(.bitcast, Type.anyerror, err_set); + return block.addInst(.{ + .tag = .bitcast, + .data = .{ .ty_op = .{ + .ty = Air.Inst.Ref.anyerror_type, + .operand = err_set, + } }, + }); } fn analyzeDeclVal( @@ -13128,7 +13148,7 @@ fn analyzeSlice( if (opt_new_ptr_val) |new_ptr_val| { return sema.addConstant(return_ty, new_ptr_val); } else { - return block.addTyOp(.bitcast, return_ty, new_ptr); + return block.addBitCast(return_ty, new_ptr); } } diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 1fd75b5180..d6b41208f2 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -2598,9 +2598,9 @@ pub const FuncGen = struct { if (self.liveness.isUnused(inst)) return null; const ty_op = self.air.instructions.items(.data)[inst].ty_op; - const operand_ty = self.air.typeOf(ty_op.operand); + const payload_ty = self.air.typeOf(ty_op.operand); const non_null_bit = self.context.intType(1).constAllOnes(); - if (!operand_ty.hasCodeGenBits()) return non_null_bit; + if (!payload_ty.hasCodeGenBits()) return non_null_bit; const operand = try self.resolveInst(ty_op.operand); const optional_ty = self.air.typeOfIndex(inst); if (optional_ty.isPtrLikeOptional()) return operand; @@ -2608,8 +2608,6 @@ pub const FuncGen = struct { if (isByRef(optional_ty)) { const optional_ptr = self.buildAlloca(llvm_optional_ty); const payload_ptr = self.builder.buildStructGEP(optional_ptr, 0, ""); - var buf: Type.Payload.ElemType = undefined; - const payload_ty = operand_ty.optionalChild(&buf); var ptr_ty_payload: Type.Payload.ElemType = .{ .base = .{ .tag = .single_mut_pointer }, .data = payload_ty, |
