| author | |
| committer | |
| log | 6afcaf4a08b6fb1cce0cdb2393fc1d4cd041509c |
| tree | bf4a17c51d53b720077e8315c5d0a38f20eba219 |
| parent | 96e5f661bd34d98bba89bcb70c9db059aaf38641 |
* Introduce a mechanism into Sema for emitting a compile error when an
integer is too big and we need it to fit into a usize.
* Add `@intCast` where necessary
* link/MachO: fix an unnecessary allocation when all that was happening
was appending zeroes to an ArrayList.
* Add `error.Overflow` as a possible error to some codepaths, allowing
usage of `math.intCast`.
closes #971011 files changed, 163 insertions(+), 85 deletions(-)
src/Module.zig+4-2| ... | ... | @@ -3661,7 +3661,8 @@ pub fn embedFile(mod: *Module, cur_file: *File, rel_file_path: []const u8) !*Emb |
| 3661 | 3661 | defer file.close(); |
| 3662 | 3662 | |
| 3663 | 3663 | const stat = try file.stat(); |
| 3664 | const bytes = try file.readToEndAllocOptions(gpa, std.math.maxInt(u32), stat.size, 1, 0); | |
| 3664 | const size_usize = try std.math.cast(usize, stat.size); | |
| 3665 | const bytes = try file.readToEndAllocOptions(gpa, std.math.maxInt(u32), size_usize, 1, 0); | |
| 3665 | 3666 | |
| 3666 | 3667 | log.debug("new embedFile. resolved_root_path={s}, resolved_path={s}, sub_file_path={s}, rel_file_path={s}", .{ |
| 3667 | 3668 | resolved_root_path, resolved_path, sub_file_path, rel_file_path, |
| ... | ... | @@ -3694,7 +3695,8 @@ pub fn detectEmbedFileUpdate(mod: *Module, embed_file: *EmbedFile) !void { |
| 3694 | 3695 | if (unchanged_metadata) return; |
| 3695 | 3696 | |
| 3696 | 3697 | const gpa = mod.gpa; |
| 3697 | const bytes = try file.readToEndAllocOptions(gpa, std.math.maxInt(u32), stat.size, 1, 0); | |
| 3698 | const size_usize = try std.math.cast(usize, stat.size); | |
| 3699 | const bytes = try file.readToEndAllocOptions(gpa, std.math.maxInt(u32), size_usize, 1, 0); | |
| 3698 | 3700 | gpa.free(embed_file.bytes); |
| 3699 | 3701 | embed_file.bytes = bytes; |
| 3700 | 3702 | embed_file.stat_size = stat.size; |
src/Sema.zig+63-27| ... | ... | @@ -7020,7 +7020,7 @@ fn zirBitNot(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. |
| 7020 | 7020 | if (val.isUndef()) { |
| 7021 | 7021 | return sema.addConstUndef(scalar_type); |
| 7022 | 7022 | } else if (operand_type.zigTypeTag() == .Vector) { |
| 7023 | const vec_len = operand_type.arrayLen(); | |
| 7023 | const vec_len = try sema.usizeCast(block, operand_src, operand_type.arrayLen()); | |
| 7024 | 7024 | var elem_val_buf: Value.ElemValueBuffer = undefined; |
| 7025 | 7025 | const elems = try sema.arena.alloc(Value, vec_len); |
| 7026 | 7026 | for (elems) |*elem, i| { |
| ... | ... | @@ -7073,7 +7073,9 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 7073 | 7073 | |
| 7074 | 7074 | if (try sema.resolveDefinedValue(block, lhs_src, lhs)) |lhs_val| { |
| 7075 | 7075 | if (try sema.resolveDefinedValue(block, rhs_src, rhs)) |rhs_val| { |
| 7076 | const final_len = lhs_info.len + rhs_info.len; | |
| 7076 | const lhs_len = try sema.usizeCast(block, lhs_src, lhs_info.len); | |
| 7077 | const rhs_len = try sema.usizeCast(block, lhs_src, rhs_info.len); | |
| 7078 | const final_len = lhs_len + rhs_len; | |
| 7077 | 7079 | const final_len_including_sent = final_len + @boolToInt(res_sent != null); |
| 7078 | 7080 | const is_pointer = lhs_ty.zigTypeTag() == .Pointer; |
| 7079 | 7081 | const lhs_sub_val = if (is_pointer) (try sema.pointerDeref(block, lhs_src, lhs_val, lhs_ty)).? else lhs_val; |
| ... | ... | @@ -7083,17 +7085,17 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 7083 | 7085 | |
| 7084 | 7086 | const buf = try anon_decl.arena().alloc(Value, final_len_including_sent); |
| 7085 | 7087 | { |
| 7086 | var i: u64 = 0; | |
| 7087 | while (i < lhs_info.len) : (i += 1) { | |
| 7088 | var i: usize = 0; | |
| 7089 | while (i < lhs_len) : (i += 1) { | |
| 7088 | 7090 | const val = try lhs_sub_val.elemValue(sema.arena, i); |
| 7089 | 7091 | buf[i] = try val.copy(anon_decl.arena()); |
| 7090 | 7092 | } |
| 7091 | 7093 | } |
| 7092 | 7094 | { |
| 7093 | var i: u64 = 0; | |
| 7094 | while (i < rhs_info.len) : (i += 1) { | |
| 7095 | var i: usize = 0; | |
| 7096 | while (i < rhs_len) : (i += 1) { | |
| 7095 | 7097 | const val = try rhs_sub_val.elemValue(sema.arena, i); |
| 7096 | buf[lhs_info.len + i] = try val.copy(anon_decl.arena()); | |
| 7098 | buf[lhs_len + i] = try val.copy(anon_decl.arena()); | |
| 7097 | 7099 | } |
| 7098 | 7100 | } |
| 7099 | 7101 | const ty = if (res_sent) |rs| ty: { |
| ... | ... | @@ -7143,6 +7145,7 @@ fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 7143 | 7145 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; |
| 7144 | 7146 | const lhs = sema.resolveInst(extra.lhs); |
| 7145 | 7147 | const lhs_ty = sema.typeOf(lhs); |
| 7148 | const src: LazySrcLoc = inst_data.src(); | |
| 7146 | 7149 | const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node }; |
| 7147 | 7150 | const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = inst_data.src_node }; |
| 7148 | 7151 | |
| ... | ... | @@ -7151,11 +7154,14 @@ fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 7151 | 7154 | const mulinfo = getArrayCatInfo(lhs_ty) orelse |
| 7152 | 7155 | return sema.fail(block, lhs_src, "expected array, found '{}'", .{lhs_ty}); |
| 7153 | 7156 | |
| 7154 | const final_len = std.math.mul(u64, mulinfo.len, factor) catch | |
| 7157 | const final_len_u64 = std.math.mul(u64, mulinfo.len, factor) catch | |
| 7155 | 7158 | return sema.fail(block, rhs_src, "operation results in overflow", .{}); |
| 7156 | const final_len_including_sent = final_len + @boolToInt(mulinfo.sentinel != null); | |
| 7157 | 7159 | |
| 7158 | 7160 | if (try sema.resolveDefinedValue(block, lhs_src, lhs)) |lhs_val| { |
| 7161 | const final_len = try sema.usizeCast(block, src, final_len_u64); | |
| 7162 | const final_len_including_sent = final_len + @boolToInt(mulinfo.sentinel != null); | |
| 7163 | const lhs_len = try sema.usizeCast(block, lhs_src, mulinfo.len); | |
| 7164 | ||
| 7159 | 7165 | const lhs_sub_val = if (lhs_ty.zigTypeTag() == .Pointer) (try sema.pointerDeref(block, lhs_src, lhs_val, lhs_ty)).? else lhs_val; |
| 7160 | 7166 | |
| 7161 | 7167 | var anon_decl = try block.startAnonDecl(); |
| ... | ... | @@ -7176,18 +7182,18 @@ fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 7176 | 7182 | |
| 7177 | 7183 | // Optimization for the common pattern of a single element repeated N times, such |
| 7178 | 7184 | // as zero-filling a byte array. |
| 7179 | const val = if (mulinfo.len == 1) blk: { | |
| 7185 | const val = if (lhs_len == 1) blk: { | |
| 7180 | 7186 | const elem_val = try lhs_sub_val.elemValue(sema.arena, 0); |
| 7181 | 7187 | const copied_val = try elem_val.copy(anon_decl.arena()); |
| 7182 | 7188 | break :blk try Value.Tag.repeated.create(anon_decl.arena(), copied_val); |
| 7183 | 7189 | } else blk: { |
| 7184 | 7190 | // the actual loop |
| 7185 | var i: u64 = 0; | |
| 7191 | var i: usize = 0; | |
| 7186 | 7192 | while (i < factor) : (i += 1) { |
| 7187 | var j: u64 = 0; | |
| 7188 | while (j < mulinfo.len) : (j += 1) { | |
| 7193 | var j: usize = 0; | |
| 7194 | while (j < lhs_len) : (j += 1) { | |
| 7189 | 7195 | const val = try lhs_sub_val.elemValue(sema.arena, j); |
| 7190 | buf[mulinfo.len * i + j] = try val.copy(anon_decl.arena()); | |
| 7196 | buf[lhs_len * i + j] = try val.copy(anon_decl.arena()); | |
| 7191 | 7197 | } |
| 7192 | 7198 | } |
| 7193 | 7199 | if (mulinfo.sentinel) |sent| { |
| ... | ... | @@ -8122,7 +8128,7 @@ fn analyzePtrArithmetic( |
| 8122 | 8128 | return sema.addConstUndef(new_ptr_ty); |
| 8123 | 8129 | } |
| 8124 | 8130 | |
| 8125 | const offset_int = offset_val.toUnsignedInt(); | |
| 8131 | const offset_int = try sema.usizeCast(block, offset_src, offset_val.toUnsignedInt()); | |
| 8126 | 8132 | if (ptr_val.getUnsignedInt()) |addr| { |
| 8127 | 8133 | const target = sema.mod.getTarget(); |
| 8128 | 8134 | const ptr_child_ty = ptr_ty.childType(); |
| ... | ... | @@ -10204,7 +10210,7 @@ fn checkComptimeVarStore( |
| 10204 | 10210 | } |
| 10205 | 10211 | |
| 10206 | 10212 | const SimdBinOp = struct { |
| 10207 | len: ?u64, | |
| 10213 | len: ?usize, | |
| 10208 | 10214 | /// Coerced to `result_ty`. |
| 10209 | 10215 | lhs: Air.Inst.Ref, |
| 10210 | 10216 | /// Coerced to `result_ty`. |
| ... | ... | @@ -10230,7 +10236,7 @@ fn checkSimdBinOp( |
| 10230 | 10236 | const lhs_zig_ty_tag = try lhs_ty.zigTypeTagOrPoison(); |
| 10231 | 10237 | const rhs_zig_ty_tag = try rhs_ty.zigTypeTagOrPoison(); |
| 10232 | 10238 | |
| 10233 | var vec_len: ?u64 = null; | |
| 10239 | var vec_len: ?usize = null; | |
| 10234 | 10240 | if (lhs_zig_ty_tag == .Vector and rhs_zig_ty_tag == .Vector) { |
| 10235 | 10241 | const lhs_len = lhs_ty.arrayLen(); |
| 10236 | 10242 | const rhs_len = rhs_ty.arrayLen(); |
| ... | ... | @@ -10244,7 +10250,7 @@ fn checkSimdBinOp( |
| 10244 | 10250 | }; |
| 10245 | 10251 | return sema.failWithOwnedErrorMsg(msg); |
| 10246 | 10252 | } |
| 10247 | vec_len = lhs_len; | |
| 10253 | vec_len = try sema.usizeCast(block, lhs_src, lhs_len); | |
| 10248 | 10254 | } else if (lhs_zig_ty_tag == .Vector or rhs_zig_ty_tag == .Vector) { |
| 10249 | 10255 | const msg = msg: { |
| 10250 | 10256 | const msg = try sema.errMsg(block, src, "mixed scalar and vector operands: {} and {}", .{ |
| ... | ... | @@ -12671,8 +12677,7 @@ fn storePtrVal( |
| 12671 | 12677 | var kit = try beginComptimePtrMutation(sema, block, src, ptr_val); |
| 12672 | 12678 | try sema.checkComptimeVarStore(block, src, kit.decl_ref_mut); |
| 12673 | 12679 | |
| 12674 | const target = sema.mod.getTarget(); | |
| 12675 | const bitcasted_val = try operand_val.bitCast(operand_ty, kit.ty, target, sema.gpa, sema.arena); | |
| 12680 | const bitcasted_val = try sema.bitCastVal(block, src, operand_val, operand_ty, kit.ty); | |
| 12676 | 12681 | |
| 12677 | 12682 | const arena = kit.beginArena(sema.gpa); |
| 12678 | 12683 | defer kit.finishArena(); |
| ... | ... | @@ -12724,7 +12729,9 @@ fn beginComptimePtrMutation( |
| 12724 | 12729 | const arena = parent.beginArena(sema.gpa); |
| 12725 | 12730 | defer parent.finishArena(); |
| 12726 | 12731 | |
| 12727 | const elems = try arena.alloc(Value, parent.ty.arrayLenIncludingSentinel()); | |
| 12732 | const array_len_including_sentinel = | |
| 12733 | try sema.usizeCast(block, src, parent.ty.arrayLenIncludingSentinel()); | |
| 12734 | const elems = try arena.alloc(Value, array_len_including_sentinel); | |
| 12728 | 12735 | mem.set(Value, elems, Value.undef); |
| 12729 | 12736 | |
| 12730 | 12737 | parent.val.* = try Value.Tag.array.create(arena, elems); |
| ... | ... | @@ -12771,7 +12778,9 @@ fn beginComptimePtrMutation( |
| 12771 | 12778 | defer parent.finishArena(); |
| 12772 | 12779 | |
| 12773 | 12780 | const repeated_val = try parent.val.castTag(.repeated).?.data.copy(arena); |
| 12774 | const elems = try arena.alloc(Value, parent.ty.arrayLenIncludingSentinel()); | |
| 12781 | const array_len_including_sentinel = | |
| 12782 | try sema.usizeCast(block, src, parent.ty.arrayLenIncludingSentinel()); | |
| 12783 | const elems = try arena.alloc(Value, array_len_including_sentinel); | |
| 12775 | 12784 | mem.set(Value, elems, repeated_val); |
| 12776 | 12785 | |
| 12777 | 12786 | parent.val.* = try Value.Tag.array.create(arena, elems); |
| ... | ... | @@ -12925,7 +12934,7 @@ fn beginComptimePtrLoad( |
| 12925 | 12934 | .root_val = parent.root_val, |
| 12926 | 12935 | .val = try parent.val.elemValue(sema.arena, elem_ptr.index), |
| 12927 | 12936 | .ty = elem_ty, |
| 12928 | .byte_offset = parent.byte_offset + elem_size * elem_ptr.index, | |
| 12937 | .byte_offset = try sema.usizeCast(block, src, parent.byte_offset + elem_size * elem_ptr.index), | |
| 12929 | 12938 | .is_mutable = parent.is_mutable, |
| 12930 | 12939 | }; |
| 12931 | 12940 | }, |
| ... | ... | @@ -12939,7 +12948,7 @@ fn beginComptimePtrLoad( |
| 12939 | 12948 | .root_val = parent.root_val, |
| 12940 | 12949 | .val = try parent.val.fieldValue(sema.arena, field_index), |
| 12941 | 12950 | .ty = parent.ty.structFieldType(field_index), |
| 12942 | .byte_offset = parent.byte_offset + field_offset, | |
| 12951 | .byte_offset = try sema.usizeCast(block, src, parent.byte_offset + field_offset), | |
| 12943 | 12952 | .is_mutable = parent.is_mutable, |
| 12944 | 12953 | }; |
| 12945 | 12954 | }, |
| ... | ... | @@ -12990,15 +12999,34 @@ fn bitCast( |
| 12990 | 12999 | ) CompileError!Air.Inst.Ref { |
| 12991 | 13000 | // TODO validate the type size and other compile errors |
| 12992 | 13001 | if (try sema.resolveMaybeUndefVal(block, inst_src, inst)) |val| { |
| 12993 | const target = sema.mod.getTarget(); | |
| 12994 | 13002 | const old_ty = sema.typeOf(inst); |
| 12995 | const result_val = try val.bitCast(old_ty, dest_ty, target, sema.gpa, sema.arena); | |
| 13003 | const result_val = try sema.bitCastVal(block, inst_src, val, old_ty, dest_ty); | |
| 12996 | 13004 | return sema.addConstant(dest_ty, result_val); |
| 12997 | 13005 | } |
| 12998 | 13006 | try sema.requireRuntimeBlock(block, inst_src); |
| 12999 | 13007 | return block.addBitCast(dest_ty, inst); |
| 13000 | 13008 | } |
| 13001 | 13009 | |
| 13010 | pub fn bitCastVal( | |
| 13011 | sema: *Sema, | |
| 13012 | block: *Block, | |
| 13013 | src: LazySrcLoc, | |
| 13014 | val: Value, | |
| 13015 | old_ty: Type, | |
| 13016 | new_ty: Type, | |
| 13017 | ) !Value { | |
| 13018 | if (old_ty.eql(new_ty)) return val; | |
| 13019 | ||
| 13020 | // For types with well-defined memory layouts, we serialize them a byte buffer, | |
| 13021 | // then deserialize to the new type. | |
| 13022 | const target = sema.mod.getTarget(); | |
| 13023 | const abi_size = try sema.usizeCast(block, src, old_ty.abiSize(target)); | |
| 13024 | const buffer = try sema.gpa.alloc(u8, abi_size); | |
| 13025 | defer sema.gpa.free(buffer); | |
| 13026 | val.writeToMemory(old_ty, target, buffer); | |
| 13027 | return Value.readFromMemory(new_ty, target, buffer, sema.arena); | |
| 13028 | } | |
| 13029 | ||
| 13002 | 13030 | fn coerceArrayPtrToSlice( |
| 13003 | 13031 | sema: *Sema, |
| 13004 | 13032 | block: *Block, |
| ... | ... | @@ -15103,7 +15131,7 @@ fn pointerDeref(sema: *Sema, block: *Block, src: LazySrcLoc, ptr_val: Value, ptr |
| 15103 | 15131 | // The Type it is stored as in the compiler has an ABI size greater or equal to |
| 15104 | 15132 | // the ABI size of `load_ty`. We may perform the bitcast based on |
| 15105 | 15133 | // `parent.val` alone (more efficient). |
| 15106 | return try parent.val.bitCast(parent.ty, load_ty, target, sema.gpa, sema.arena); | |
| 15134 | return try sema.bitCastVal(block, src, parent.val, parent.ty, load_ty); | |
| 15107 | 15135 | } |
| 15108 | 15136 | |
| 15109 | 15137 | // The Type it is stored as in the compiler has an ABI size less than the ABI size |
| ... | ... | @@ -15111,3 +15139,11 @@ fn pointerDeref(sema: *Sema, block: *Block, src: LazySrcLoc, ptr_val: Value, ptr |
| 15111 | 15139 | // and reinterpreted starting at `parent.byte_offset`. |
| 15112 | 15140 | return sema.fail(block, src, "TODO: implement bitcast with index offset", .{}); |
| 15113 | 15141 | } |
| 15142 | ||
| 15143 | /// Used to convert a u64 value to a usize value, emitting a compile error if the number | |
| 15144 | /// is too big to fit. | |
| 15145 | fn usizeCast(sema: *Sema, block: *Block, src: LazySrcLoc, int: u64) CompileError!usize { | |
| 15146 | return std.math.cast(usize, int) catch |err| switch (err) { | |
| 15147 | error.Overflow => return sema.fail(block, src, "expression produces integer value {d} which is too big for this compiler implementation to handle", .{int}), | |
| 15148 | }; | |
| 15149 | } |
src/arch/wasm/CodeGen.zig+4-1| ... | ... | @@ -538,6 +538,8 @@ const InnerError = error{ |
| 538 | 538 | AnalysisFail, |
| 539 | 539 | /// Failed to emit MIR instructions to binary/textual representation. |
| 540 | 540 | EmitFail, |
| 541 | /// Compiler implementation could not handle a large integer. | |
| 542 | Overflow, | |
| 541 | 543 | }; |
| 542 | 544 | |
| 543 | 545 | pub fn deinit(self: *Self) void { |
| ... | ... | @@ -877,7 +879,8 @@ pub fn gen(self: *Self, ty: Type, val: Value) InnerError!Result { |
| 877 | 879 | }, |
| 878 | 880 | .Struct => { |
| 879 | 881 | // TODO write the fields for real |
| 880 | try self.code.writer().writeByteNTimes(0xaa, ty.abiSize(self.target)); | |
| 882 | const abi_size = try std.math.cast(usize, ty.abiSize(self.target)); | |
| 883 | try self.code.writer().writeByteNTimes(0xaa, abi_size); | |
| 881 | 884 | return Result{ .appended = {} }; |
| 882 | 885 | }, |
| 883 | 886 | else => |tag| return self.fail("TODO: Implement zig type codegen for type: '{s}'", .{tag}), |
src/arch/x86_64/Emit.zig+3-1| ... | ... | @@ -42,6 +42,7 @@ relocs: std.ArrayListUnmanaged(Reloc) = .{}, |
| 42 | 42 | |
| 43 | 43 | const InnerError = error{ |
| 44 | 44 | OutOfMemory, |
| 45 | Overflow, | |
| 45 | 46 | EmitFail, |
| 46 | 47 | }; |
| 47 | 48 | |
| ... | ... | @@ -174,10 +175,11 @@ fn fixupRelocs(emit: *Emit) InnerError!void { |
| 174 | 175 | // possible resolution, i.e., 8bit, and iteratively converge on the minimum required resolution |
| 175 | 176 | // until the entire decl is correctly emitted with all JMP/CALL instructions within range. |
| 176 | 177 | for (emit.relocs.items) |reloc| { |
| 178 | const offset = try math.cast(usize, reloc.offset); | |
| 177 | 179 | const target = emit.code_offset_mapping.get(reloc.target) orelse |
| 178 | 180 | return emit.fail("JMP/CALL relocation target not found!", .{}); |
| 179 | 181 | const disp = @intCast(i32, @intCast(i64, target) - @intCast(i64, reloc.source + reloc.length)); |
| 180 | mem.writeIntLittle(i32, emit.code.items[reloc.offset..][0..4], disp); | |
| 182 | mem.writeIntLittle(i32, emit.code.items[offset..][0..4], disp); | |
| 181 | 183 | } |
| 182 | 184 | } |
| 183 | 185 |
src/arch/x86_64/abi.zig+2-2| ... | ... | @@ -207,7 +207,7 @@ pub fn classifySystemV(ty: Type, target: Target) [8]Class { |
| 207 | 207 | // "Otherwise class SSE is used." |
| 208 | 208 | result[result_i] = .sse; |
| 209 | 209 | } |
| 210 | byte_i += field_size; | |
| 210 | byte_i += @intCast(usize, field_size); | |
| 211 | 211 | if (byte_i == 8) { |
| 212 | 212 | byte_i = 0; |
| 213 | 213 | result_i += 1; |
| ... | ... | @@ -222,7 +222,7 @@ pub fn classifySystemV(ty: Type, target: Target) [8]Class { |
| 222 | 222 | result_i += field_class.len; |
| 223 | 223 | // If there are any bytes leftover, we have to try to combine |
| 224 | 224 | // the next field with them. |
| 225 | byte_i = field_size % 8; | |
| 225 | byte_i = @intCast(usize, field_size % 8); | |
| 226 | 226 | if (byte_i != 0) result_i -= 1; |
| 227 | 227 | } |
| 228 | 228 | } |
src/codegen.zig+3-1| ... | ... | @@ -37,6 +37,7 @@ pub const Result = union(enum) { |
| 37 | 37 | |
| 38 | 38 | pub const GenerateSymbolError = error{ |
| 39 | 39 | OutOfMemory, |
| 40 | Overflow, | |
| 40 | 41 | /// A Decl that this symbol depends on had a semantic analysis failure. |
| 41 | 42 | AnalysisFail, |
| 42 | 43 | }; |
| ... | ... | @@ -289,7 +290,8 @@ pub fn generateSymbol( |
| 289 | 290 | const field_vals = typed_value.val.castTag(.@"struct").?.data; |
| 290 | 291 | _ = field_vals; // TODO write the fields for real |
| 291 | 292 | const target = bin_file.options.target; |
| 292 | try code.writer().writeByteNTimes(0xaa, typed_value.ty.abiSize(target)); | |
| 293 | const abi_size = try math.cast(usize, typed_value.ty.abiSize(target)); | |
| 294 | try code.writer().writeByteNTimes(0xaa, abi_size); | |
| 293 | 295 | return Result{ .appended = {} }; |
| 294 | 296 | }, |
| 295 | 297 | else => |t| { |
src/codegen/llvm.zig+28-12| ... | ... | @@ -1006,10 +1006,18 @@ pub const DeclGen = struct { |
| 1006 | 1006 | const int_info = tv.ty.intInfo(target); |
| 1007 | 1007 | const llvm_type = self.context.intType(int_info.bits); |
| 1008 | 1008 | |
| 1009 | const unsigned_val = if (bigint.limbs.len == 1) | |
| 1010 | llvm_type.constInt(bigint.limbs[0], .False) | |
| 1011 | else | |
| 1012 | llvm_type.constIntOfArbitraryPrecision(@intCast(c_uint, bigint.limbs.len), bigint.limbs.ptr); | |
| 1009 | const unsigned_val = v: { | |
| 1010 | if (bigint.limbs.len == 1) { | |
| 1011 | break :v llvm_type.constInt(bigint.limbs[0], .False); | |
| 1012 | } | |
| 1013 | if (@sizeOf(usize) == @sizeOf(u64)) { | |
| 1014 | break :v llvm_type.constIntOfArbitraryPrecision( | |
| 1015 | @intCast(c_uint, bigint.limbs.len), | |
| 1016 | bigint.limbs.ptr, | |
| 1017 | ); | |
| 1018 | } | |
| 1019 | @panic("TODO implement bigint to llvm int for 32-bit compiler builds"); | |
| 1020 | }; | |
| 1013 | 1021 | if (!bigint.positive) { |
| 1014 | 1022 | return llvm.constNeg(unsigned_val); |
| 1015 | 1023 | } |
| ... | ... | @@ -1026,10 +1034,18 @@ pub const DeclGen = struct { |
| 1026 | 1034 | const int_info = tv.ty.intInfo(target); |
| 1027 | 1035 | const llvm_type = self.context.intType(int_info.bits); |
| 1028 | 1036 | |
| 1029 | const unsigned_val = if (bigint.limbs.len == 1) | |
| 1030 | llvm_type.constInt(bigint.limbs[0], .False) | |
| 1031 | else | |
| 1032 | llvm_type.constIntOfArbitraryPrecision(@intCast(c_uint, bigint.limbs.len), bigint.limbs.ptr); | |
| 1037 | const unsigned_val = v: { | |
| 1038 | if (bigint.limbs.len == 1) { | |
| 1039 | break :v llvm_type.constInt(bigint.limbs[0], .False); | |
| 1040 | } | |
| 1041 | if (@sizeOf(usize) == @sizeOf(u64)) { | |
| 1042 | break :v llvm_type.constIntOfArbitraryPrecision( | |
| 1043 | @intCast(c_uint, bigint.limbs.len), | |
| 1044 | bigint.limbs.ptr, | |
| 1045 | ); | |
| 1046 | } | |
| 1047 | @panic("TODO implement bigint to llvm int for 32-bit compiler builds"); | |
| 1048 | }; | |
| 1033 | 1049 | if (!bigint.positive) { |
| 1034 | 1050 | return llvm.constNeg(unsigned_val); |
| 1035 | 1051 | } |
| ... | ... | @@ -1144,7 +1160,7 @@ pub const DeclGen = struct { |
| 1144 | 1160 | const val = tv.val.castTag(.repeated).?.data; |
| 1145 | 1161 | const elem_ty = tv.ty.elemType(); |
| 1146 | 1162 | const sentinel = tv.ty.sentinel(); |
| 1147 | const len = tv.ty.arrayLen(); | |
| 1163 | const len = @intCast(usize, tv.ty.arrayLen()); | |
| 1148 | 1164 | const len_including_sent = len + @boolToInt(sentinel != null); |
| 1149 | 1165 | const gpa = self.gpa; |
| 1150 | 1166 | const llvm_elems = try gpa.alloc(*const llvm.Value, len_including_sent); |
| ... | ... | @@ -1317,7 +1333,7 @@ pub const DeclGen = struct { |
| 1317 | 1333 | .bytes => { |
| 1318 | 1334 | // Note, sentinel is not stored even if the type has a sentinel. |
| 1319 | 1335 | const bytes = tv.val.castTag(.bytes).?.data; |
| 1320 | const vector_len = tv.ty.arrayLen(); | |
| 1336 | const vector_len = @intCast(usize, tv.ty.arrayLen()); | |
| 1321 | 1337 | assert(vector_len == bytes.len or vector_len + 1 == bytes.len); |
| 1322 | 1338 | |
| 1323 | 1339 | const elem_ty = tv.ty.elemType(); |
| ... | ... | @@ -1343,7 +1359,7 @@ pub const DeclGen = struct { |
| 1343 | 1359 | // Note, sentinel is not stored even if the type has a sentinel. |
| 1344 | 1360 | // The value includes the sentinel in those cases. |
| 1345 | 1361 | const elem_vals = tv.val.castTag(.array).?.data; |
| 1346 | const vector_len = tv.ty.arrayLen(); | |
| 1362 | const vector_len = @intCast(usize, tv.ty.arrayLen()); | |
| 1347 | 1363 | assert(vector_len == elem_vals.len or vector_len + 1 == elem_vals.len); |
| 1348 | 1364 | const elem_ty = tv.ty.elemType(); |
| 1349 | 1365 | const llvm_elems = try self.gpa.alloc(*const llvm.Value, vector_len); |
| ... | ... | @@ -1360,7 +1376,7 @@ pub const DeclGen = struct { |
| 1360 | 1376 | // Note, sentinel is not stored even if the type has a sentinel. |
| 1361 | 1377 | const val = tv.val.castTag(.repeated).?.data; |
| 1362 | 1378 | const elem_ty = tv.ty.elemType(); |
| 1363 | const len = tv.ty.arrayLen(); | |
| 1379 | const len = @intCast(usize, tv.ty.arrayLen()); | |
| 1364 | 1380 | const llvm_elems = try self.gpa.alloc(*const llvm.Value, len); |
| 1365 | 1381 | defer self.gpa.free(llvm_elems); |
| 1366 | 1382 | for (llvm_elems) |*elem| { |
src/link.zig+40-5| ... | ... | @@ -350,9 +350,39 @@ pub const File = struct { |
| 350 | 350 | } |
| 351 | 351 | } |
| 352 | 352 | |
| 353 | pub const UpdateDeclError = error{ | |
| 354 | OutOfMemory, | |
| 355 | Overflow, | |
| 356 | Underflow, | |
| 357 | FileTooBig, | |
| 358 | InputOutput, | |
| 359 | FilesOpenedWithWrongFlags, | |
| 360 | IsDir, | |
| 361 | NoSpaceLeft, | |
| 362 | Unseekable, | |
| 363 | PermissionDenied, | |
| 364 | FileBusy, | |
| 365 | SystemResources, | |
| 366 | OperationAborted, | |
| 367 | BrokenPipe, | |
| 368 | ConnectionResetByPeer, | |
| 369 | ConnectionTimedOut, | |
| 370 | NotOpenForReading, | |
| 371 | WouldBlock, | |
| 372 | AccessDenied, | |
| 373 | Unexpected, | |
| 374 | DiskQuota, | |
| 375 | NotOpenForWriting, | |
| 376 | AnalysisFail, | |
| 377 | CodegenFail, | |
| 378 | EmitFail, | |
| 379 | NameTooLong, | |
| 380 | CurrentWorkingDirectoryUnlinked, | |
| 381 | }; | |
| 382 | ||
| 353 | 383 | /// May be called before or after updateDeclExports but must be called |
| 354 | 384 | /// after allocateDeclIndexes for any given Decl. |
| 355 | pub fn updateDecl(base: *File, module: *Module, decl: *Module.Decl) !void { | |
| 385 | pub fn updateDecl(base: *File, module: *Module, decl: *Module.Decl) UpdateDeclError!void { | |
| 356 | 386 | log.debug("updateDecl {*} ({s}), type={}", .{ decl, decl.name, decl.ty }); |
| 357 | 387 | assert(decl.has_tv); |
| 358 | 388 | switch (base.tag) { |
| ... | ... | @@ -370,7 +400,7 @@ pub const File = struct { |
| 370 | 400 | |
| 371 | 401 | /// May be called before or after updateDeclExports but must be called |
| 372 | 402 | /// after allocateDeclIndexes for any given Decl. |
| 373 | pub fn updateFunc(base: *File, module: *Module, func: *Module.Fn, air: Air, liveness: Liveness) !void { | |
| 403 | pub fn updateFunc(base: *File, module: *Module, func: *Module.Fn, air: Air, liveness: Liveness) UpdateDeclError!void { | |
| 374 | 404 | log.debug("updateFunc {*} ({s}), type={}", .{ |
| 375 | 405 | func.owner_decl, func.owner_decl.name, func.owner_decl.ty, |
| 376 | 406 | }); |
| ... | ... | @@ -387,7 +417,7 @@ pub const File = struct { |
| 387 | 417 | } |
| 388 | 418 | } |
| 389 | 419 | |
| 390 | pub fn updateDeclLineNumber(base: *File, module: *Module, decl: *Module.Decl) !void { | |
| 420 | pub fn updateDeclLineNumber(base: *File, module: *Module, decl: *Module.Decl) UpdateDeclError!void { | |
| 391 | 421 | log.debug("updateDeclLineNumber {*} ({s}), line={}", .{ |
| 392 | 422 | decl, decl.name, decl.src_line + 1, |
| 393 | 423 | }); |
| ... | ... | @@ -407,12 +437,17 @@ pub const File = struct { |
| 407 | 437 | /// TODO we're transitioning to deleting this function and instead having |
| 408 | 438 | /// each linker backend notice the first time updateDecl or updateFunc is called, or |
| 409 | 439 | /// a callee referenced from AIR. |
| 410 | pub fn allocateDeclIndexes(base: *File, decl: *Module.Decl) !void { | |
| 440 | pub fn allocateDeclIndexes(base: *File, decl: *Module.Decl) error{OutOfMemory}!void { | |
| 411 | 441 | log.debug("allocateDeclIndexes {*} ({s})", .{ decl, decl.name }); |
| 412 | 442 | switch (base.tag) { |
| 413 | 443 | .coff => return @fieldParentPtr(Coff, "base", base).allocateDeclIndexes(decl), |
| 414 | 444 | .elf => return @fieldParentPtr(Elf, "base", base).allocateDeclIndexes(decl), |
| 415 | .macho => return @fieldParentPtr(MachO, "base", base).allocateDeclIndexes(decl), | |
| 445 | .macho => return @fieldParentPtr(MachO, "base", base).allocateDeclIndexes(decl) catch |err| switch (err) { | |
| 446 | // remap this error code because we are transitioning away from | |
| 447 | // `allocateDeclIndexes`. | |
| 448 | error.Overflow => return error.OutOfMemory, | |
| 449 | error.OutOfMemory => return error.OutOfMemory, | |
| 450 | }, | |
| 416 | 451 | .wasm => return @fieldParentPtr(Wasm, "base", base).allocateDeclIndexes(decl), |
| 417 | 452 | .plan9 => return @fieldParentPtr(Plan9, "base", base).allocateDeclIndexes(decl), |
| 418 | 453 | .c, .spirv => {}, |
src/link/MachO.zig+8-8| ... | ... | @@ -1788,19 +1788,18 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio |
| 1788 | 1788 | } |
| 1789 | 1789 | |
| 1790 | 1790 | pub fn createEmptyAtom(self: *MachO, local_sym_index: u32, size: u64, alignment: u32) !*Atom { |
| 1791 | const code = try self.base.allocator.alloc(u8, size); | |
| 1792 | defer self.base.allocator.free(code); | |
| 1793 | mem.set(u8, code, 0); | |
| 1794 | ||
| 1791 | const size_usize = try math.cast(usize, size); | |
| 1795 | 1792 | const atom = try self.base.allocator.create(Atom); |
| 1796 | 1793 | errdefer self.base.allocator.destroy(atom); |
| 1797 | 1794 | atom.* = Atom.empty; |
| 1798 | 1795 | atom.local_sym_index = local_sym_index; |
| 1799 | 1796 | atom.size = size; |
| 1800 | 1797 | atom.alignment = alignment; |
| 1801 | try atom.code.appendSlice(self.base.allocator, code); | |
| 1802 | try self.managed_atoms.append(self.base.allocator, atom); | |
| 1803 | 1798 | |
| 1799 | try atom.code.resize(self.base.allocator, size_usize); | |
| 1800 | mem.set(u8, atom.code.items, 0); | |
| 1801 | ||
| 1802 | try self.managed_atoms.append(self.base.allocator, atom); | |
| 1804 | 1803 | return atom; |
| 1805 | 1804 | } |
| 1806 | 1805 | |
| ... | ... | @@ -1872,9 +1871,10 @@ fn writeAtoms(self: *MachO) !void { |
| 1872 | 1871 | while (true) { |
| 1873 | 1872 | if (atom.dirty or self.invalidate_relocs) { |
| 1874 | 1873 | const atom_sym = self.locals.items[atom.local_sym_index]; |
| 1875 | const padding_size: u64 = if (atom.next) |next| blk: { | |
| 1874 | const padding_size: usize = if (atom.next) |next| blk: { | |
| 1876 | 1875 | const next_sym = self.locals.items[next.local_sym_index]; |
| 1877 | break :blk next_sym.n_value - (atom_sym.n_value + atom.size); | |
| 1876 | const size = next_sym.n_value - (atom_sym.n_value + atom.size); | |
| 1877 | break :blk try math.cast(usize, size); | |
| 1878 | 1878 | } else 0; |
| 1879 | 1879 | |
| 1880 | 1880 | log.debug(" (adding atom {s} to buffer: {})", .{ self.getString(atom_sym.n_strx), atom_sym }); |
src/link/Plan9.zig+4-4| ... | ... | @@ -71,9 +71,9 @@ entry_val: ?u64 = null, |
| 71 | 71 | got_len: usize = 0, |
| 72 | 72 | // A list of all the free got indexes, so when making a new decl |
| 73 | 73 | // don't make a new one, just use one from here. |
| 74 | got_index_free_list: std.ArrayListUnmanaged(u64) = .{}, | |
| 74 | got_index_free_list: std.ArrayListUnmanaged(usize) = .{}, | |
| 75 | 75 | |
| 76 | syms_index_free_list: std.ArrayListUnmanaged(u64) = .{}, | |
| 76 | syms_index_free_list: std.ArrayListUnmanaged(usize) = .{}, | |
| 77 | 77 | |
| 78 | 78 | const Bases = struct { |
| 79 | 79 | text: u64, |
| ... | ... | @@ -356,8 +356,8 @@ pub fn changeLine(l: *std.ArrayList(u8), delta_line: i32) !void { |
| 356 | 356 | } |
| 357 | 357 | } |
| 358 | 358 | |
| 359 | fn declCount(self: *Plan9) u64 { | |
| 360 | var fn_decl_count: u64 = 0; | |
| 359 | fn declCount(self: *Plan9) usize { | |
| 360 | var fn_decl_count: usize = 0; | |
| 361 | 361 | var itf_files = self.fn_decl_table.iterator(); |
| 362 | 362 | while (itf_files.next()) |ent| { |
| 363 | 363 | // get the submap |
src/value.zig+4-22| ... | ... | @@ -995,24 +995,6 @@ pub const Value = extern union { |
| 995 | 995 | }; |
| 996 | 996 | } |
| 997 | 997 | |
| 998 | pub fn bitCast( | |
| 999 | val: Value, | |
| 1000 | old_ty: Type, | |
| 1001 | new_ty: Type, | |
| 1002 | target: Target, | |
| 1003 | gpa: *Allocator, | |
| 1004 | arena: *Allocator, | |
| 1005 | ) !Value { | |
| 1006 | if (old_ty.eql(new_ty)) return val; | |
| 1007 | ||
| 1008 | // For types with well-defined memory layouts, we serialize them a byte buffer, | |
| 1009 | // then deserialize to the new type. | |
| 1010 | const buffer = try gpa.alloc(u8, old_ty.abiSize(target)); | |
| 1011 | defer gpa.free(buffer); | |
| 1012 | val.writeToMemory(old_ty, target, buffer); | |
| 1013 | return Value.readFromMemory(new_ty, target, buffer, arena); | |
| 1014 | } | |
| 1015 | ||
| 1016 | 998 | pub fn writeToMemory(val: Value, ty: Type, target: Target, buffer: []u8) void { |
| 1017 | 999 | switch (ty.zigTypeTag()) { |
| 1018 | 1000 | .Int => { |
| ... | ... | @@ -1039,7 +1021,7 @@ pub const Value = extern union { |
| 1039 | 1021 | .Array, .Vector => { |
| 1040 | 1022 | const len = ty.arrayLen(); |
| 1041 | 1023 | const elem_ty = ty.childType(); |
| 1042 | const elem_size = elem_ty.abiSize(target); | |
| 1024 | const elem_size = @intCast(usize, elem_ty.abiSize(target)); | |
| 1043 | 1025 | var elem_i: usize = 0; |
| 1044 | 1026 | var elem_value_buf: ElemValueBuffer = undefined; |
| 1045 | 1027 | var buf_off: usize = 0; |
| ... | ... | @@ -2494,7 +2476,7 @@ pub const Value = extern union { |
| 2494 | 2476 | // resorting to BigInt first. |
| 2495 | 2477 | var lhs_space: Value.BigIntSpace = undefined; |
| 2496 | 2478 | const lhs_bigint = lhs.toBigInt(&lhs_space); |
| 2497 | const shift = rhs.toUnsignedInt(); | |
| 2479 | const shift = @intCast(usize, rhs.toUnsignedInt()); | |
| 2498 | 2480 | const limbs = try allocator.alloc( |
| 2499 | 2481 | std.math.big.Limb, |
| 2500 | 2482 | lhs_bigint.limbs.len + (shift / (@sizeOf(std.math.big.Limb) * 8)) + 1, |
| ... | ... | @@ -2521,7 +2503,7 @@ pub const Value = extern union { |
| 2521 | 2503 | |
| 2522 | 2504 | var lhs_space: Value.BigIntSpace = undefined; |
| 2523 | 2505 | const lhs_bigint = lhs.toBigInt(&lhs_space); |
| 2524 | const shift = rhs.toUnsignedInt(); | |
| 2506 | const shift = @intCast(usize, rhs.toUnsignedInt()); | |
| 2525 | 2507 | const limbs = try arena.alloc( |
| 2526 | 2508 | std.math.big.Limb, |
| 2527 | 2509 | std.math.big.int.calcTwosCompLimbCount(info.bits), |
| ... | ... | @@ -2540,7 +2522,7 @@ pub const Value = extern union { |
| 2540 | 2522 | // resorting to BigInt first. |
| 2541 | 2523 | var lhs_space: Value.BigIntSpace = undefined; |
| 2542 | 2524 | const lhs_bigint = lhs.toBigInt(&lhs_space); |
| 2543 | const shift = rhs.toUnsignedInt(); | |
| 2525 | const shift = @intCast(usize, rhs.toUnsignedInt()); | |
| 2544 | 2526 | const limbs = try allocator.alloc( |
| 2545 | 2527 | std.math.big.Limb, |
| 2546 | 2528 | lhs_bigint.limbs.len - (shift / (@sizeOf(std.math.big.Limb) * 8)), |