| ... | ... | @@ -220,8 +220,8 @@ fn isReservedIdent(ident: []const u8) bool { |
| 220 | 220 | 'A'...'Z', '_' => return true, |
| 221 | 221 | else => return false, |
| 222 | 222 | } |
| 223 | | } else if (std.mem.startsWith(u8, ident, "DUMMYSTRUCTNAME") or |
| 224 | | std.mem.startsWith(u8, ident, "DUMMYUNIONNAME")) |
| 223 | } else if (mem.startsWith(u8, ident, "DUMMYSTRUCTNAME") or |
| 224 | mem.startsWith(u8, ident, "DUMMYUNIONNAME")) |
| 225 | 225 | { // windows.h |
| 226 | 226 | return true; |
| 227 | 227 | } else return reserved_idents.has(ident); |
| ... | ... | @@ -279,8 +279,6 @@ pub const Function = struct { |
| 279 | 279 | /// by type alignment. |
| 280 | 280 | /// The value is whether the alloc needs to be emitted in the header. |
| 281 | 281 | allocs: std.AutoArrayHashMapUnmanaged(LocalIndex, bool) = .{}, |
| 282 | | /// Needed for memory used by the keys of free_locals_map entries. |
| 283 | | arena: std.heap.ArenaAllocator, |
| 284 | 282 | |
| 285 | 283 | fn resolveInst(f: *Function, ref: Air.Inst.Ref) !CValue { |
| 286 | 284 | if (Air.refToIndex(ref)) |inst| { |
| ... | ... | @@ -481,7 +479,6 @@ pub const Function = struct { |
| 481 | 479 | f.object.code.deinit(); |
| 482 | 480 | f.object.dg.ctypes.deinit(gpa); |
| 483 | 481 | f.object.dg.fwd_decl.deinit(); |
| 484 | | f.arena.deinit(); |
| 485 | 482 | } |
| 486 | 483 | }; |
| 487 | 484 | |
| ... | ... | @@ -501,7 +498,7 @@ pub const Object = struct { |
| 501 | 498 | |
| 502 | 499 | /// This data is available both when outputting .c code and when outputting an .h file. |
| 503 | 500 | pub const DeclGen = struct { |
| 504 | | gpa: std.mem.Allocator, |
| 501 | gpa: mem.Allocator, |
| 505 | 502 | module: *Module, |
| 506 | 503 | decl: ?*Decl, |
| 507 | 504 | decl_index: Decl.OptionalIndex, |
| ... | ... | @@ -539,6 +536,9 @@ pub const DeclGen = struct { |
| 539 | 536 | if (func.data.owner_decl != decl_index) |
| 540 | 537 | return dg.renderDeclValue(writer, ty, val, func.data.owner_decl, location); |
| 541 | 538 | |
| 539 | if (decl.val.castTag(.variable)) |var_payload| |
| 540 | try dg.renderFwdDecl(decl_index, var_payload.data); |
| 541 | |
| 542 | 542 | if (ty.isSlice()) { |
| 543 | 543 | if (location == .StaticInitializer) { |
| 544 | 544 | try writer.writeByte('{'); |
| ... | ... | @@ -1819,8 +1819,23 @@ pub const DeclGen = struct { |
| 1819 | 1819 | try dg.writeCValue(writer, member); |
| 1820 | 1820 | } |
| 1821 | 1821 | |
| 1822 | | const IdentHasher = std.crypto.auth.siphash.SipHash128(1, 3); |
| 1823 | | const ident_hasher_init: IdentHasher = IdentHasher.init(&[_]u8{0} ** IdentHasher.key_length); |
| 1822 | fn renderFwdDecl(dg: *DeclGen, decl_index: Decl.Index, variable: *Module.Var) !void { |
| 1823 | const decl = dg.module.declPtr(decl_index); |
| 1824 | const fwd_decl_writer = dg.fwd_decl.writer(); |
| 1825 | const is_global = dg.declIsGlobal(.{ .ty = decl.ty, .val = decl.val }) or variable.is_extern; |
| 1826 | try fwd_decl_writer.writeAll(if (is_global) "zig_extern " else "static "); |
| 1827 | if (variable.is_threadlocal) try fwd_decl_writer.writeAll("zig_threadlocal "); |
| 1828 | if (variable.is_weak_linkage) try fwd_decl_writer.writeAll("zig_weak_linkage "); |
| 1829 | try dg.renderTypeAndName( |
| 1830 | fwd_decl_writer, |
| 1831 | decl.ty, |
| 1832 | .{ .decl = decl_index }, |
| 1833 | CQualifiers.init(.{ .@"const" = !variable.is_mutable }), |
| 1834 | decl.@"align", |
| 1835 | .complete, |
| 1836 | ); |
| 1837 | try fwd_decl_writer.writeAll(";\n"); |
| 1838 | } |
| 1824 | 1839 | |
| 1825 | 1840 | fn renderDeclName(dg: *DeclGen, writer: anytype, decl_index: Decl.Index, export_index: u32) !void { |
| 1826 | 1841 | const decl = dg.module.declPtr(decl_index); |
| ... | ... | @@ -1829,7 +1844,7 @@ pub const DeclGen = struct { |
| 1829 | 1844 | if (dg.module.decl_exports.get(decl_index)) |exports| { |
| 1830 | 1845 | try writer.writeAll(exports.items[export_index].options.name); |
| 1831 | 1846 | } else if (decl.isExtern()) { |
| 1832 | | try writer.writeAll(mem.sliceTo(decl.name, 0)); |
| 1847 | try writer.writeAll(mem.span(decl.name)); |
| 1833 | 1848 | } else { |
| 1834 | 1849 | // MSVC has a limit of 4095 character token length limit, and fmtIdent can (worst case), |
| 1835 | 1850 | // expand to 3x the length of its input, but let's cut it off at a much shorter limit. |
| ... | ... | @@ -2396,9 +2411,9 @@ pub fn genErrDecls(o: *Object) !void { |
| 2396 | 2411 | const name_buf = try o.dg.gpa.alloc(u8, name_prefix.len + max_name_len); |
| 2397 | 2412 | defer o.dg.gpa.free(name_buf); |
| 2398 | 2413 | |
| 2399 | | std.mem.copy(u8, name_buf, name_prefix); |
| 2414 | mem.copy(u8, name_buf, name_prefix); |
| 2400 | 2415 | for (o.dg.module.error_name_list.items) |name| { |
| 2401 | | std.mem.copy(u8, name_buf[name_prefix.len..], name); |
| 2416 | mem.copy(u8, name_buf[name_prefix.len..], name); |
| 2402 | 2417 | const identifier = name_buf[0 .. name_prefix.len + name.len]; |
| 2403 | 2418 | |
| 2404 | 2419 | var name_ty_pl = Type.Payload.Len{ .base = .{ .tag = .array_u8_sentinel_0 }, .data = name.len }; |
| ... | ... | @@ -2644,21 +2659,16 @@ pub fn genDecl(o: *Object) !void { |
| 2644 | 2659 | try genExports(o); |
| 2645 | 2660 | } else if (tv.val.castTag(.variable)) |var_payload| { |
| 2646 | 2661 | const variable: *Module.Var = var_payload.data; |
| 2647 | | |
| 2648 | | const is_global = o.dg.declIsGlobal(tv) or variable.is_extern; |
| 2649 | | const fwd_decl_writer = o.dg.fwd_decl.writer(); |
| 2650 | | |
| 2651 | | try fwd_decl_writer.writeAll(if (is_global) "zig_extern " else "static "); |
| 2652 | | if (variable.is_threadlocal) try fwd_decl_writer.writeAll("zig_threadlocal "); |
| 2653 | | try o.dg.renderTypeAndName(fwd_decl_writer, decl.ty, decl_c_value, .{}, decl.@"align", .complete); |
| 2654 | | try fwd_decl_writer.writeAll(";\n"); |
| 2662 | try o.dg.renderFwdDecl(decl_c_value.decl, variable); |
| 2655 | 2663 | try genExports(o); |
| 2656 | 2664 | |
| 2657 | 2665 | if (variable.is_extern) return; |
| 2658 | 2666 | |
| 2667 | const is_global = o.dg.declIsGlobal(tv) or variable.is_extern; |
| 2659 | 2668 | const w = o.writer(); |
| 2660 | 2669 | if (!is_global) try w.writeAll("static "); |
| 2661 | 2670 | if (variable.is_threadlocal) try w.writeAll("zig_threadlocal "); |
| 2671 | if (variable.is_weak_linkage) try w.writeAll("zig_weak_linkage "); |
| 2662 | 2672 | if (decl.@"linksection") |section| try w.print("zig_linksection(\"{s}\", ", .{section}); |
| 2663 | 2673 | try o.dg.renderTypeAndName(w, tv.ty, decl_c_value, .{}, decl.@"align", .complete); |
| 2664 | 2674 | if (decl.@"linksection" != null) try w.writeAll(", read, write)"); |
| ... | ... | @@ -3396,7 +3406,7 @@ fn airRet(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValue { |
| 3396 | 3406 | var deref = is_ptr; |
| 3397 | 3407 | const is_array = lowersToArray(ret_ty, target); |
| 3398 | 3408 | const ret_val = if (is_array) ret_val: { |
| 3399 | | const array_local = try f.allocLocal(inst, try lowered_ret_ty.copy(f.arena.allocator())); |
| 3409 | const array_local = try f.allocLocal(inst, lowered_ret_ty); |
| 3400 | 3410 | try writer.writeAll("memcpy("); |
| 3401 | 3411 | try f.writeCValueMember(writer, array_local, .{ .identifier = "array" }); |
| 3402 | 3412 | try writer.writeAll(", "); |
| ... | ... | @@ -4113,7 +4123,7 @@ fn airCall( |
| 4113 | 4123 | var lowered_arg_buf: LowerFnRetTyBuffer = undefined; |
| 4114 | 4124 | const lowered_arg_ty = lowerFnRetTy(arg_ty, &lowered_arg_buf, target); |
| 4115 | 4125 | |
| 4116 | | const array_local = try f.allocLocal(inst, try lowered_arg_ty.copy(f.arena.allocator())); |
| 4126 | const array_local = try f.allocLocal(inst, lowered_arg_ty); |
| 4117 | 4127 | try writer.writeAll("memcpy("); |
| 4118 | 4128 | try f.writeCValueMember(writer, array_local, .{ .identifier = "array" }); |
| 4119 | 4129 | try writer.writeAll(", "); |
| ... | ... | @@ -4156,7 +4166,7 @@ fn airCall( |
| 4156 | 4166 | try writer.writeByte(')'); |
| 4157 | 4167 | break :result .none; |
| 4158 | 4168 | } else { |
| 4159 | | const local = try f.allocLocal(inst, try lowered_ret_ty.copy(f.arena.allocator())); |
| 4169 | const local = try f.allocLocal(inst, lowered_ret_ty); |
| 4160 | 4170 | try f.writeCValue(writer, local, .Other); |
| 4161 | 4171 | try writer.writeAll(" = "); |
| 4162 | 4172 | break :result local; |
| ... | ... | @@ -4732,9 +4742,9 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4732 | 4742 | const locals_begin = @intCast(LocalIndex, f.locals.items.len); |
| 4733 | 4743 | const constraints_extra_begin = extra_i; |
| 4734 | 4744 | for (outputs) |output| { |
| 4735 | | const extra_bytes = std.mem.sliceAsBytes(f.air.extra[extra_i..]); |
| 4736 | | const constraint = std.mem.sliceTo(extra_bytes, 0); |
| 4737 | | const name = std.mem.sliceTo(extra_bytes[constraint.len + 1 ..], 0); |
| 4745 | const extra_bytes = mem.sliceAsBytes(f.air.extra[extra_i..]); |
| 4746 | const constraint = mem.sliceTo(extra_bytes, 0); |
| 4747 | const name = mem.sliceTo(extra_bytes[constraint.len + 1 ..], 0); |
| 4738 | 4748 | // This equation accounts for the fact that even if we have exactly 4 bytes |
| 4739 | 4749 | // for the string, we still use the next u32 for the null terminator. |
| 4740 | 4750 | extra_i += (constraint.len + name.len + (2 + 3)) / 4; |
| ... | ... | @@ -4764,14 +4774,14 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4764 | 4774 | } |
| 4765 | 4775 | } |
| 4766 | 4776 | for (inputs) |input| { |
| 4767 | | const extra_bytes = std.mem.sliceAsBytes(f.air.extra[extra_i..]); |
| 4768 | | const constraint = std.mem.sliceTo(extra_bytes, 0); |
| 4769 | | const name = std.mem.sliceTo(extra_bytes[constraint.len + 1 ..], 0); |
| 4777 | const extra_bytes = mem.sliceAsBytes(f.air.extra[extra_i..]); |
| 4778 | const constraint = mem.sliceTo(extra_bytes, 0); |
| 4779 | const name = mem.sliceTo(extra_bytes[constraint.len + 1 ..], 0); |
| 4770 | 4780 | // This equation accounts for the fact that even if we have exactly 4 bytes |
| 4771 | 4781 | // for the string, we still use the next u32 for the null terminator. |
| 4772 | 4782 | extra_i += (constraint.len + name.len + (2 + 3)) / 4; |
| 4773 | 4783 | |
| 4774 | | if (constraint.len < 1 or std.mem.indexOfScalar(u8, "=+&%", constraint[0]) != null or |
| 4784 | if (constraint.len < 1 or mem.indexOfScalar(u8, "=+&%", constraint[0]) != null or |
| 4775 | 4785 | (constraint[0] == '{' and constraint[constraint.len - 1] != '}')) |
| 4776 | 4786 | { |
| 4777 | 4787 | return f.fail("CBE: constraint not supported: '{s}'", .{constraint}); |
| ... | ... | @@ -4797,7 +4807,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4797 | 4807 | } |
| 4798 | 4808 | } |
| 4799 | 4809 | for (0..clobbers_len) |_| { |
| 4800 | | const clobber = std.mem.sliceTo(std.mem.sliceAsBytes(f.air.extra[extra_i..]), 0); |
| 4810 | const clobber = mem.sliceTo(mem.sliceAsBytes(f.air.extra[extra_i..]), 0); |
| 4801 | 4811 | // This equation accounts for the fact that even if we have exactly 4 bytes |
| 4802 | 4812 | // for the string, we still use the next u32 for the null terminator. |
| 4803 | 4813 | extra_i += clobber.len / 4 + 1; |
| ... | ... | @@ -4862,16 +4872,16 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4862 | 4872 | var locals_index = locals_begin; |
| 4863 | 4873 | try writer.writeByte(':'); |
| 4864 | 4874 | for (outputs, 0..) |output, index| { |
| 4865 | | const extra_bytes = std.mem.sliceAsBytes(f.air.extra[extra_i..]); |
| 4866 | | const constraint = std.mem.sliceTo(extra_bytes, 0); |
| 4867 | | const name = std.mem.sliceTo(extra_bytes[constraint.len + 1 ..], 0); |
| 4875 | const extra_bytes = mem.sliceAsBytes(f.air.extra[extra_i..]); |
| 4876 | const constraint = mem.sliceTo(extra_bytes, 0); |
| 4877 | const name = mem.sliceTo(extra_bytes[constraint.len + 1 ..], 0); |
| 4868 | 4878 | // This equation accounts for the fact that even if we have exactly 4 bytes |
| 4869 | 4879 | // for the string, we still use the next u32 for the null terminator. |
| 4870 | 4880 | extra_i += (constraint.len + name.len + (2 + 3)) / 4; |
| 4871 | 4881 | |
| 4872 | 4882 | if (index > 0) try writer.writeByte(','); |
| 4873 | 4883 | try writer.writeByte(' '); |
| 4874 | | if (!std.mem.eql(u8, name, "_")) try writer.print("[{s}]", .{name}); |
| 4884 | if (!mem.eql(u8, name, "_")) try writer.print("[{s}]", .{name}); |
| 4875 | 4885 | const is_reg = constraint[1] == '{'; |
| 4876 | 4886 | try writer.print("{s}(", .{fmtStringLiteral(if (is_reg) "=r" else constraint, null)}); |
| 4877 | 4887 | if (is_reg) { |
| ... | ... | @@ -4886,16 +4896,16 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4886 | 4896 | } |
| 4887 | 4897 | try writer.writeByte(':'); |
| 4888 | 4898 | for (inputs, 0..) |input, index| { |
| 4889 | | const extra_bytes = std.mem.sliceAsBytes(f.air.extra[extra_i..]); |
| 4890 | | const constraint = std.mem.sliceTo(extra_bytes, 0); |
| 4891 | | const name = std.mem.sliceTo(extra_bytes[constraint.len + 1 ..], 0); |
| 4899 | const extra_bytes = mem.sliceAsBytes(f.air.extra[extra_i..]); |
| 4900 | const constraint = mem.sliceTo(extra_bytes, 0); |
| 4901 | const name = mem.sliceTo(extra_bytes[constraint.len + 1 ..], 0); |
| 4892 | 4902 | // This equation accounts for the fact that even if we have exactly 4 bytes |
| 4893 | 4903 | // for the string, we still use the next u32 for the null terminator. |
| 4894 | 4904 | extra_i += (constraint.len + name.len + (2 + 3)) / 4; |
| 4895 | 4905 | |
| 4896 | 4906 | if (index > 0) try writer.writeByte(','); |
| 4897 | 4907 | try writer.writeByte(' '); |
| 4898 | | if (!std.mem.eql(u8, name, "_")) try writer.print("[{s}]", .{name}); |
| 4908 | if (!mem.eql(u8, name, "_")) try writer.print("[{s}]", .{name}); |
| 4899 | 4909 | |
| 4900 | 4910 | const is_reg = constraint[0] == '{'; |
| 4901 | 4911 | const input_val = try f.resolveInst(input); |
| ... | ... | @@ -4909,7 +4919,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4909 | 4919 | } |
| 4910 | 4920 | try writer.writeByte(':'); |
| 4911 | 4921 | for (0..clobbers_len) |clobber_i| { |
| 4912 | | const clobber = std.mem.sliceTo(std.mem.sliceAsBytes(f.air.extra[extra_i..]), 0); |
| 4922 | const clobber = mem.sliceTo(mem.sliceAsBytes(f.air.extra[extra_i..]), 0); |
| 4913 | 4923 | // This equation accounts for the fact that even if we have exactly 4 bytes |
| 4914 | 4924 | // for the string, we still use the next u32 for the null terminator. |
| 4915 | 4925 | extra_i += clobber.len / 4 + 1; |
| ... | ... | @@ -4924,9 +4934,9 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4924 | 4934 | extra_i = constraints_extra_begin; |
| 4925 | 4935 | locals_index = locals_begin; |
| 4926 | 4936 | for (outputs) |output| { |
| 4927 | | const extra_bytes = std.mem.sliceAsBytes(f.air.extra[extra_i..]); |
| 4928 | | const constraint = std.mem.sliceTo(extra_bytes, 0); |
| 4929 | | const name = std.mem.sliceTo(extra_bytes[constraint.len + 1 ..], 0); |
| 4937 | const extra_bytes = mem.sliceAsBytes(f.air.extra[extra_i..]); |
| 4938 | const constraint = mem.sliceTo(extra_bytes, 0); |
| 4939 | const name = mem.sliceTo(extra_bytes[constraint.len + 1 ..], 0); |
| 4930 | 4940 | // This equation accounts for the fact that even if we have exactly 4 bytes |
| 4931 | 4941 | // for the string, we still use the next u32 for the null terminator. |
| 4932 | 4942 | extra_i += (constraint.len + name.len + (2 + 3)) / 4; |
| ... | ... | @@ -5363,7 +5373,7 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5363 | 5373 | }; |
| 5364 | 5374 | const field_int_ty = Type.initPayload(&field_int_pl.base); |
| 5365 | 5375 | |
| 5366 | | const temp_local = try f.allocLocal(inst, try field_int_ty.copy(f.arena.allocator())); |
| 5376 | const temp_local = try f.allocLocal(inst, field_int_ty); |
| 5367 | 5377 | try f.writeCValue(writer, temp_local, .Other); |
| 5368 | 5378 | try writer.writeAll(" = zig_wrap_"); |
| 5369 | 5379 | try f.object.dg.renderTypeForBuiltinFnName(writer, field_int_ty); |
| ... | ... | @@ -7277,7 +7287,7 @@ fn formatIntLiteral( |
| 7277 | 7287 | var int_buf: Value.BigIntSpace = undefined; |
| 7278 | 7288 | const int = if (data.val.isUndefDeep()) blk: { |
| 7279 | 7289 | undef_limbs = try allocator.alloc(BigIntLimb, BigInt.calcTwosCompLimbCount(data.int_info.bits)); |
| 7280 | | std.mem.set(BigIntLimb, undef_limbs, undefPattern(BigIntLimb)); |
| 7290 | mem.set(BigIntLimb, undef_limbs, undefPattern(BigIntLimb)); |
| 7281 | 7291 | |
| 7282 | 7292 | var undef_int = BigInt.Mutable{ |
| 7283 | 7293 | .limbs = undef_limbs, |
| ... | ... | @@ -7372,7 +7382,7 @@ fn formatIntLiteral( |
| 7372 | 7382 | } else { |
| 7373 | 7383 | try data.cty.renderLiteralPrefix(writer, data.kind); |
| 7374 | 7384 | wrap.convertToTwosComplement(int, data.int_info.signedness, c_bits); |
| 7375 | | std.mem.set(BigIntLimb, wrap.limbs[wrap.len..], 0); |
| 7385 | mem.set(BigIntLimb, wrap.limbs[wrap.len..], 0); |
| 7376 | 7386 | wrap.len = wrap.limbs.len; |
| 7377 | 7387 | const limbs_per_c_limb = @divExact(wrap.len, c_limb_info.count); |
| 7378 | 7388 | |