| ... | ... | @@ -882,14 +882,14 @@ pub const DeclGen = struct { |
| 882 | 882 | var literal = stringLiteral(writer); |
| 883 | 883 | try literal.start(); |
| 884 | 884 | const c_len = ty.arrayLenIncludingSentinel(); |
| 885 | | var index: usize = 0; |
| 885 | var index: u64 = 0; |
| 886 | 886 | while (index < c_len) : (index += 1) |
| 887 | 887 | try literal.writeChar(0xaa); |
| 888 | 888 | return literal.end(); |
| 889 | 889 | } else { |
| 890 | 890 | try writer.writeByte('{'); |
| 891 | 891 | const c_len = ty.arrayLenIncludingSentinel(); |
| 892 | | var index: usize = 0; |
| 892 | var index: u64 = 0; |
| 893 | 893 | while (index < c_len) : (index += 1) { |
| 894 | 894 | if (index > 0) try writer.writeAll(", "); |
| 895 | 895 | try dg.renderValue(writer, ty.childType(), val, initializer_type); |
| ... | ... | @@ -1089,8 +1089,8 @@ pub const DeclGen = struct { |
| 1089 | 1089 | // First try specific tag representations for more efficiency. |
| 1090 | 1090 | switch (val.tag()) { |
| 1091 | 1091 | .undef, .empty_struct_value, .empty_array => { |
| 1092 | | try writer.writeByte('{'); |
| 1093 | 1092 | const ai = ty.arrayInfo(); |
| 1093 | try writer.writeByte('{'); |
| 1094 | 1094 | if (ai.sentinel) |s| { |
| 1095 | 1095 | try dg.renderValue(writer, ai.elem_type, s, initializer_type); |
| 1096 | 1096 | } else { |
| ... | ... | @@ -1098,13 +1098,19 @@ pub const DeclGen = struct { |
| 1098 | 1098 | } |
| 1099 | 1099 | try writer.writeByte('}'); |
| 1100 | 1100 | }, |
| 1101 | | .bytes => { |
| 1102 | | try writer.print("{s}", .{fmtStringLiteral(val.castTag(.bytes).?.data)}); |
| 1103 | | }, |
| 1104 | | .str_lit => { |
| 1105 | | const str_lit = val.castTag(.str_lit).?.data; |
| 1106 | | const bytes = dg.module.string_literal_bytes.items[str_lit.index..][0..str_lit.len]; |
| 1107 | | try writer.print("{s}", .{fmtStringLiteral(bytes)}); |
| 1101 | .bytes, .str_lit => |t| { |
| 1102 | const bytes = switch (t) { |
| 1103 | .bytes => val.castTag(.bytes).?.data, |
| 1104 | .str_lit => bytes: { |
| 1105 | const str_lit = val.castTag(.str_lit).?.data; |
| 1106 | break :bytes dg.module.string_literal_bytes.items[str_lit.index..][0..str_lit.len]; |
| 1107 | }, |
| 1108 | else => unreachable, |
| 1109 | }; |
| 1110 | const sentinel = if (ty.sentinel()) |sentinel| @intCast(u8, sentinel.toUnsignedInt(target)) else null; |
| 1111 | try writer.print("{s}", .{ |
| 1112 | fmtStringLiteral(bytes[0..@intCast(usize, ty.arrayLen())], sentinel), |
| 1113 | }); |
| 1108 | 1114 | }, |
| 1109 | 1115 | else => { |
| 1110 | 1116 | // Fall back to generic implementation. |
| ... | ... | @@ -1128,7 +1134,7 @@ pub const DeclGen = struct { |
| 1128 | 1134 | } |
| 1129 | 1135 | if (ai.sentinel) |s| { |
| 1130 | 1136 | const s_u8 = @intCast(u8, s.toUnsignedInt(target)); |
| 1131 | | try literal.writeChar(s_u8); |
| 1137 | if (s_u8 != 0) try literal.writeChar(s_u8); |
| 1132 | 1138 | } |
| 1133 | 1139 | try literal.end(); |
| 1134 | 1140 | } else { |
| ... | ... | @@ -1638,6 +1644,11 @@ pub const DeclGen = struct { |
| 1638 | 1644 | try context.writeValue(dg, w, src_ty, location); |
| 1639 | 1645 | } else if (dest_bits <= 64 and src_bits > 64) { |
| 1640 | 1646 | assert(!src_is_ptr); |
| 1647 | if (dest_bits < 64) { |
| 1648 | try w.writeByte('('); |
| 1649 | try dg.renderType(w, dest_ty); |
| 1650 | try w.writeByte(')'); |
| 1651 | } |
| 1641 | 1652 | try w.writeAll("zig_lo_"); |
| 1642 | 1653 | try dg.renderTypeForBuiltinFnName(w, src_eff_ty); |
| 1643 | 1654 | try w.writeByte('('); |
| ... | ... | @@ -2380,9 +2391,7 @@ pub fn genTypeDecl( |
| 2380 | 2391 | |
| 2381 | 2392 | pub fn genGlobalAsm(mod: *Module, writer: anytype) !void { |
| 2382 | 2393 | var it = mod.global_assembly.valueIterator(); |
| 2383 | | while (it.next()) |asm_source| { |
| 2384 | | try writer.print("__asm({s});\n", .{fmtStringLiteral(asm_source.*)}); |
| 2385 | | } |
| 2394 | while (it.next()) |asm_source| try writer.print("__asm({s});\n", .{fmtStringLiteral(asm_source.*, null)}); |
| 2386 | 2395 | } |
| 2387 | 2396 | |
| 2388 | 2397 | pub fn genErrDecls(o: *Object) !void { |
| ... | ... | @@ -2400,22 +2409,20 @@ pub fn genErrDecls(o: *Object) !void { |
| 2400 | 2409 | o.indent_writer.popIndent(); |
| 2401 | 2410 | try writer.writeAll("};\n"); |
| 2402 | 2411 | |
| 2403 | | const name_prefix = "zig_errorName"; |
| 2404 | | const name_buf = try o.dg.gpa.alloc(u8, name_prefix.len + "_".len + max_name_len + 1); |
| 2412 | const array_identifier = "zig_errorName"; |
| 2413 | const name_prefix = array_identifier ++ "_"; |
| 2414 | const name_buf = try o.dg.gpa.alloc(u8, name_prefix.len + max_name_len); |
| 2405 | 2415 | defer o.dg.gpa.free(name_buf); |
| 2406 | 2416 | |
| 2407 | | std.mem.copy(u8, name_buf, name_prefix ++ "_"); |
| 2417 | std.mem.copy(u8, name_buf, name_prefix); |
| 2408 | 2418 | for (o.dg.module.error_name_list.items) |name| { |
| 2409 | | std.mem.copy(u8, name_buf[name_prefix.len + "_".len ..], name); |
| 2410 | | name_buf[name_prefix.len + "_".len + name.len] = 0; |
| 2411 | | |
| 2412 | | const identifier = name_buf[0 .. name_prefix.len + "_".len + name.len :0]; |
| 2413 | | const name_z = identifier[name_prefix.len + "_".len ..]; |
| 2419 | std.mem.copy(u8, name_buf[name_prefix.len..], name); |
| 2420 | const identifier = name_buf[0 .. name_prefix.len + name.len]; |
| 2414 | 2421 | |
| 2415 | 2422 | var name_ty_pl = Type.Payload.Len{ .base = .{ .tag = .array_u8_sentinel_0 }, .data = name.len }; |
| 2416 | 2423 | const name_ty = Type.initPayload(&name_ty_pl.base); |
| 2417 | 2424 | |
| 2418 | | var name_pl = Value.Payload.Bytes{ .base = .{ .tag = .bytes }, .data = name_z }; |
| 2425 | var name_pl = Value.Payload.Bytes{ .base = .{ .tag = .bytes }, .data = name }; |
| 2419 | 2426 | const name_val = Value.initPayload(&name_pl.base); |
| 2420 | 2427 | |
| 2421 | 2428 | try writer.writeAll("static "); |
| ... | ... | @@ -2432,7 +2439,7 @@ pub fn genErrDecls(o: *Object) !void { |
| 2432 | 2439 | const name_array_ty = Type.initPayload(&name_array_ty_pl.base); |
| 2433 | 2440 | |
| 2434 | 2441 | try writer.writeAll("static "); |
| 2435 | | try o.dg.renderTypeAndName(writer, name_array_ty, .{ .identifier = name_prefix }, Const, 0, .complete); |
| 2442 | try o.dg.renderTypeAndName(writer, name_array_ty, .{ .identifier = array_identifier }, Const, 0, .complete); |
| 2436 | 2443 | try writer.writeAll(" = {"); |
| 2437 | 2444 | for (o.dg.module.error_name_list.items, 0..) |name, value| { |
| 2438 | 2445 | if (value != 0) try writer.writeByte(','); |
| ... | ... | @@ -2440,7 +2447,7 @@ pub fn genErrDecls(o: *Object) !void { |
| 2440 | 2447 | var len_pl = Value.Payload.U64{ .base = .{ .tag = .int_u64 }, .data = name.len }; |
| 2441 | 2448 | const len_val = Value.initPayload(&len_pl.base); |
| 2442 | 2449 | |
| 2443 | | try writer.print("{{" ++ name_prefix ++ "_{}, {}}}", .{ |
| 2450 | try writer.print("{{" ++ name_prefix ++ "{}, {}}}", .{ |
| 2444 | 2451 | fmtIdent(name), try o.dg.fmtIntLiteral(Type.usize, len_val), |
| 2445 | 2452 | }); |
| 2446 | 2453 | } |
| ... | ... | @@ -2457,8 +2464,8 @@ fn genExports(o: *Object) !void { |
| 2457 | 2464 | try fwd_decl_writer.writeAll("zig_export("); |
| 2458 | 2465 | try o.dg.renderFunctionSignature(fwd_decl_writer, o.dg.decl_index.unwrap().?, .forward, .{ .export_index = @intCast(u32, i) }); |
| 2459 | 2466 | try fwd_decl_writer.print(", {s}, {s});\n", .{ |
| 2460 | | fmtStringLiteral(exports.items[0].options.name), |
| 2461 | | fmtStringLiteral(@"export".options.name), |
| 2467 | fmtStringLiteral(exports.items[0].options.name, null), |
| 2468 | fmtStringLiteral(@"export".options.name, null), |
| 2462 | 2469 | }); |
| 2463 | 2470 | } |
| 2464 | 2471 | } |
| ... | ... | @@ -2483,10 +2490,6 @@ pub fn genLazyFn(o: *Object, lazy_fn: LazyFnMap.Entry) !void { |
| 2483 | 2490 | try o.dg.renderTypeAndName(w, enum_ty, .{ .identifier = "tag" }, Const, 0, .complete); |
| 2484 | 2491 | try w.writeAll(") {\n switch (tag) {\n"); |
| 2485 | 2492 | for (enum_ty.enumFields().keys(), 0..) |name, index| { |
| 2486 | | const name_z = try o.dg.gpa.dupeZ(u8, name); |
| 2487 | | defer o.dg.gpa.free(name_z); |
| 2488 | | const name_bytes = name_z[0 .. name_z.len + 1]; |
| 2489 | | |
| 2490 | 2493 | var tag_pl: Value.Payload.U32 = .{ |
| 2491 | 2494 | .base = .{ .tag = .enum_field_index }, |
| 2492 | 2495 | .data = @intCast(u32, index), |
| ... | ... | @@ -2499,7 +2502,7 @@ pub fn genLazyFn(o: *Object, lazy_fn: LazyFnMap.Entry) !void { |
| 2499 | 2502 | var name_ty_pl = Type.Payload.Len{ .base = .{ .tag = .array_u8_sentinel_0 }, .data = name.len }; |
| 2500 | 2503 | const name_ty = Type.initPayload(&name_ty_pl.base); |
| 2501 | 2504 | |
| 2502 | | var name_pl = Value.Payload.Bytes{ .base = .{ .tag = .bytes }, .data = name_bytes }; |
| 2505 | var name_pl = Value.Payload.Bytes{ .base = .{ .tag = .bytes }, .data = name }; |
| 2503 | 2506 | const name_val = Value.initPayload(&name_pl.base); |
| 2504 | 2507 | |
| 2505 | 2508 | var len_pl = Value.Payload.U64{ .base = .{ .tag = .int_u64 }, .data = name.len }; |
| ... | ... | @@ -3459,15 +3462,17 @@ fn airTrunc(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3459 | 3462 | try f.writeCValue(writer, local, .Other); |
| 3460 | 3463 | try writer.writeAll(" = "); |
| 3461 | 3464 | |
| 3465 | if (dest_c_bits < 64) { |
| 3466 | try writer.writeByte('('); |
| 3467 | try f.renderType(writer, inst_ty); |
| 3468 | try writer.writeByte(')'); |
| 3469 | } |
| 3470 | |
| 3462 | 3471 | const needs_lo = operand_int_info.bits > 64 and dest_bits <= 64; |
| 3463 | 3472 | if (needs_lo) { |
| 3464 | 3473 | try writer.writeAll("zig_lo_"); |
| 3465 | 3474 | try f.object.dg.renderTypeForBuiltinFnName(writer, operand_ty); |
| 3466 | 3475 | try writer.writeByte('('); |
| 3467 | | } else if (dest_c_bits <= 64) { |
| 3468 | | try writer.writeByte('('); |
| 3469 | | try f.renderType(writer, inst_ty); |
| 3470 | | try writer.writeByte(')'); |
| 3471 | 3476 | } |
| 3472 | 3477 | |
| 3473 | 3478 | if (dest_bits >= 8 and std.math.isPowerOfTwo(dest_bits)) { |
| ... | ... | @@ -4228,8 +4233,9 @@ fn airBlock(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4228 | 4233 | |
| 4229 | 4234 | try genBodyInner(f, body); |
| 4230 | 4235 | try f.object.indent_writer.insertNewline(); |
| 4236 | // label might be unused, add a dummy goto |
| 4231 | 4237 | // label must be followed by an expression, add an empty one. |
| 4232 | | try writer.print("zig_block_{d}:;\n", .{block_id}); |
| 4238 | try writer.print("goto zig_block_{d};\nzig_block_{d}: (void)0;\n", .{ block_id, block_id }); |
| 4233 | 4239 | return result; |
| 4234 | 4240 | } |
| 4235 | 4241 | |
| ... | ... | @@ -4608,8 +4614,7 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4608 | 4614 | const last_case_i = switch_br.data.cases_len - @boolToInt(switch_br.data.else_body_len == 0); |
| 4609 | 4615 | |
| 4610 | 4616 | var extra_index: usize = switch_br.end; |
| 4611 | | var case_i: u32 = 0; |
| 4612 | | while (case_i < switch_br.data.cases_len) : (case_i += 1) { |
| 4617 | for (0..switch_br.data.cases_len) |case_i| { |
| 4613 | 4618 | const case = f.air.extraData(Air.SwitchBr.Case, extra_index); |
| 4614 | 4619 | const items = @ptrCast([]const Air.Inst.Ref, f.air.extra[case.end..][0..case.data.items_len]); |
| 4615 | 4620 | const case_body = f.air.extra[case.end + items.len ..][0..case.data.body_len]; |
| ... | ... | @@ -4789,14 +4794,11 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4789 | 4794 | try writer.writeAll(";\n"); |
| 4790 | 4795 | } |
| 4791 | 4796 | } |
| 4792 | | { |
| 4793 | | var clobber_i: u32 = 0; |
| 4794 | | while (clobber_i < clobbers_len) : (clobber_i += 1) { |
| 4795 | | const clobber = std.mem.sliceTo(std.mem.sliceAsBytes(f.air.extra[extra_i..]), 0); |
| 4796 | | // This equation accounts for the fact that even if we have exactly 4 bytes |
| 4797 | | // for the string, we still use the next u32 for the null terminator. |
| 4798 | | extra_i += clobber.len / 4 + 1; |
| 4799 | | } |
| 4797 | for (0..clobbers_len) |_| { |
| 4798 | const clobber = std.mem.sliceTo(std.mem.sliceAsBytes(f.air.extra[extra_i..]), 0); |
| 4799 | // This equation accounts for the fact that even if we have exactly 4 bytes |
| 4800 | // for the string, we still use the next u32 for the null terminator. |
| 4801 | extra_i += clobber.len / 4 + 1; |
| 4800 | 4802 | } |
| 4801 | 4803 | |
| 4802 | 4804 | { |
| ... | ... | @@ -4851,7 +4853,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4851 | 4853 | |
| 4852 | 4854 | try writer.writeAll("__asm"); |
| 4853 | 4855 | if (is_volatile) try writer.writeAll(" volatile"); |
| 4854 | | try writer.print("({s}", .{fmtStringLiteral(fixed_asm_source[0..dst_i])}); |
| 4856 | try writer.print("({s}", .{fmtStringLiteral(fixed_asm_source[0..dst_i], null)}); |
| 4855 | 4857 | } |
| 4856 | 4858 | |
| 4857 | 4859 | extra_i = constraints_extra_begin; |
| ... | ... | @@ -4869,7 +4871,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4869 | 4871 | try writer.writeByte(' '); |
| 4870 | 4872 | if (!std.mem.eql(u8, name, "_")) try writer.print("[{s}]", .{name}); |
| 4871 | 4873 | const is_reg = constraint[1] == '{'; |
| 4872 | | try writer.print("{s}(", .{fmtStringLiteral(if (is_reg) "=r" else constraint)}); |
| 4874 | try writer.print("{s}(", .{fmtStringLiteral(if (is_reg) "=r" else constraint, null)}); |
| 4873 | 4875 | if (is_reg) { |
| 4874 | 4876 | try f.writeCValue(writer, .{ .local = locals_index }, .Other); |
| 4875 | 4877 | locals_index += 1; |
| ... | ... | @@ -4895,7 +4897,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4895 | 4897 | |
| 4896 | 4898 | const is_reg = constraint[0] == '{'; |
| 4897 | 4899 | const input_val = try f.resolveInst(input); |
| 4898 | | try writer.print("{s}(", .{fmtStringLiteral(if (is_reg) "r" else constraint)}); |
| 4900 | try writer.print("{s}(", .{fmtStringLiteral(if (is_reg) "r" else constraint, null)}); |
| 4899 | 4901 | try f.writeCValue(writer, if (asmInputNeedsLocal(constraint, input_val)) local: { |
| 4900 | 4902 | const input_local = CValue{ .local = locals_index }; |
| 4901 | 4903 | locals_index += 1; |
| ... | ... | @@ -4904,19 +4906,16 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4904 | 4906 | try writer.writeByte(')'); |
| 4905 | 4907 | } |
| 4906 | 4908 | try writer.writeByte(':'); |
| 4907 | | { |
| 4908 | | var clobber_i: u32 = 0; |
| 4909 | | while (clobber_i < clobbers_len) : (clobber_i += 1) { |
| 4910 | | const clobber = std.mem.sliceTo(std.mem.sliceAsBytes(f.air.extra[extra_i..]), 0); |
| 4911 | | // This equation accounts for the fact that even if we have exactly 4 bytes |
| 4912 | | // for the string, we still use the next u32 for the null terminator. |
| 4913 | | extra_i += clobber.len / 4 + 1; |
| 4909 | for (0..clobbers_len) |clobber_i| { |
| 4910 | const clobber = std.mem.sliceTo(std.mem.sliceAsBytes(f.air.extra[extra_i..]), 0); |
| 4911 | // This equation accounts for the fact that even if we have exactly 4 bytes |
| 4912 | // for the string, we still use the next u32 for the null terminator. |
| 4913 | extra_i += clobber.len / 4 + 1; |
| 4914 | 4914 | |
| 4915 | | if (clobber.len == 0) continue; |
| 4915 | if (clobber.len == 0) continue; |
| 4916 | 4916 | |
| 4917 | | if (clobber_i > 0) try writer.writeByte(','); |
| 4918 | | try writer.print(" {s}", .{fmtStringLiteral(clobber)}); |
| 4919 | | } |
| 4917 | if (clobber_i > 0) try writer.writeByte(','); |
| 4918 | try writer.print(" {s}", .{fmtStringLiteral(clobber, null)}); |
| 4920 | 4919 | } |
| 4921 | 4920 | try writer.writeAll(");\n"); |
| 4922 | 4921 | |
| ... | ... | @@ -5340,8 +5339,9 @@ fn fieldPtr( |
| 5340 | 5339 | try writer.print(" + {})", .{try f.fmtIntLiteral(Type.usize, byte_offset_val)}); |
| 5341 | 5340 | }, |
| 5342 | 5341 | .end => { |
| 5342 | try writer.writeByte('('); |
| 5343 | 5343 | try f.writeCValue(writer, container_ptr_val, .Other); |
| 5344 | | try writer.print(" + {}", .{try f.fmtIntLiteral(Type.usize, Value.one)}); |
| 5344 | try writer.print(" + {})", .{try f.fmtIntLiteral(Type.usize, Value.one)}); |
| 5345 | 5345 | }, |
| 5346 | 5346 | } |
| 5347 | 5347 | |
| ... | ... | @@ -6448,10 +6448,9 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6448 | 6448 | // |
| 6449 | 6449 | // Equivalent to: |
| 6450 | 6450 | // reduce: { |
| 6451 | | // var i: usize = 0; |
| 6452 | 6451 | // var accum: T = init; |
| 6453 | | // while (i < vec.len) : (i += 1) { |
| 6454 | | // accum = func(accum, vec[i]); |
| 6452 | // for (vec) : (elem) { |
| 6453 | // accum = func(accum, elem); |
| 6455 | 6454 | // } |
| 6456 | 6455 | // break :reduce accum; |
| 6457 | 6456 | // } |
| ... | ... | @@ -7162,8 +7161,9 @@ fn stringLiteral(child_stream: anytype) StringLiteral(@TypeOf(child_stream)) { |
| 7162 | 7161 | return .{ .counting_writer = std.io.countingWriter(child_stream) }; |
| 7163 | 7162 | } |
| 7164 | 7163 | |
| 7164 | const FormatStringContext = struct { str: []const u8, sentinel: ?u8 }; |
| 7165 | 7165 | fn formatStringLiteral( |
| 7166 | | str: []const u8, |
| 7166 | data: FormatStringContext, |
| 7167 | 7167 | comptime fmt: []const u8, |
| 7168 | 7168 | _: std.fmt.FormatOptions, |
| 7169 | 7169 | writer: anytype, |
| ... | ... | @@ -7172,13 +7172,13 @@ fn formatStringLiteral( |
| 7172 | 7172 | |
| 7173 | 7173 | var literal = stringLiteral(writer); |
| 7174 | 7174 | try literal.start(); |
| 7175 | | for (str) |c| |
| 7176 | | try literal.writeChar(c); |
| 7175 | for (data.str) |c| try literal.writeChar(c); |
| 7176 | if (data.sentinel) |sentinel| if (sentinel != 0) try literal.writeChar(sentinel); |
| 7177 | 7177 | try literal.end(); |
| 7178 | 7178 | } |
| 7179 | 7179 | |
| 7180 | | fn fmtStringLiteral(str: []const u8) std.fmt.Formatter(formatStringLiteral) { |
| 7181 | | return .{ .data = str }; |
| 7180 | fn fmtStringLiteral(str: []const u8, sentinel: ?u8) std.fmt.Formatter(formatStringLiteral) { |
| 7181 | return .{ .data = .{ .str = str, .sentinel = sentinel } }; |
| 7182 | 7182 | } |
| 7183 | 7183 | |
| 7184 | 7184 | fn undefPattern(comptime IntType: type) IntType { |