authorgravatar for mail@isaacfreund.comIsaac Freund <mail@isaacfreund.com> 2020-08-08 01:18:22+02:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-08-07 19:25:06-04:00
log2fc18b52788f789ceba7b4f60e850de3ce67495c
tree750f7dccac4515a5f337c1aac8bd613c2efd6f81
parenta2bb246db4c2bb88f402215d5db79a535dbff4b6

stage2: make link data in Decl into unions

This will allow for implementation of non-Elf backends without wasting memory.

3 files changed, 69 insertions(+), 49 deletions(-)

src-self-hosted/Module.zig+17-7
...@@ -177,14 +177,14 @@ pub const Decl = struct {...@@ -177,14 +177,14 @@ pub const Decl = struct {
177177
178 /// Represents the position of the code in the output file.178 /// Represents the position of the code in the output file.
179 /// This is populated regardless of semantic analysis and code generation.179 /// This is populated regardless of semantic analysis and code generation.
180 link: link.File.Elf.TextBlock = link.File.Elf.TextBlock.empty,180 link: link.File.LinkBlock,
181181
182 /// Represents the function in the linked output file, if the `Decl` is a function.182 /// Represents the function in the linked output file, if the `Decl` is a function.
183 /// This is stored here and not in `Fn` because `Decl` survives across updates but183 /// This is stored here and not in `Fn` because `Decl` survives across updates but
184 /// `Fn` does not.184 /// `Fn` does not.
185 /// TODO Look into making `Fn` a longer lived structure and moving this field there185 /// TODO Look into making `Fn` a longer lived structure and moving this field there
186 /// to save on memory usage.186 /// to save on memory usage.
187 fn_link: link.File.Elf.SrcFn = link.File.Elf.SrcFn.empty,187 fn_link: link.File.LinkFn,
188188
189 contents_hash: std.zig.SrcHash,189 contents_hash: std.zig.SrcHash,
190190
...@@ -1538,10 +1538,13 @@ fn analyzeRootSrcFile(self: *Module, root_scope: *Scope.File) !void {...@@ -1538,10 +1538,13 @@ fn analyzeRootSrcFile(self: *Module, root_scope: *Scope.File) !void {
1538 if (!srcHashEql(decl.contents_hash, contents_hash)) {1538 if (!srcHashEql(decl.contents_hash, contents_hash)) {
1539 try self.markOutdatedDecl(decl);1539 try self.markOutdatedDecl(decl);
1540 decl.contents_hash = contents_hash;1540 decl.contents_hash = contents_hash;
1541 } else if (decl.fn_link.len != 0) {1541 } else switch (self.bin_file.tag) {
1542 // TODO Look into detecting when this would be unnecessary by storing enough state1542 .elf => if (decl.fn_link.elf.len != 0) {
1543 // in `Decl` to notice that the line number did not change.1543 // TODO Look into detecting when this would be unnecessary by storing enough state
1544 self.work_queue.writeItemAssumeCapacity(.{ .update_line_number = decl });1544 // in `Decl` to notice that the line number did not change.
1545 self.work_queue.writeItemAssumeCapacity(.{ .update_line_number = decl });
1546 },
1547 .c => {},
1545 }1548 }
1546 }1549 }
1547 } else {1550 } else {
...@@ -1745,7 +1748,14 @@ fn allocateNewDecl(...@@ -1745,7 +1748,14 @@ fn allocateNewDecl(
1745 .analysis = .unreferenced,1748 .analysis = .unreferenced,
1746 .deletion_flag = false,1749 .deletion_flag = false,
1747 .contents_hash = contents_hash,1750 .contents_hash = contents_hash,
1748 .link = link.File.Elf.TextBlock.empty,1751 .link = switch (self.bin_file.tag) {
1752 .elf => .{ .elf = link.File.Elf.TextBlock.empty },
1753 .c => .{ .c = {} },
1754 },
1755 .fn_link = switch (self.bin_file.tag) {
1756 .elf => .{ .elf = link.File.Elf.SrcFn.empty },
1757 .c => .{ .c = {} },
1758 },
1749 .generation = 0,1759 .generation = 0,
1750 };1760 };
1751 return new_decl;1761 return new_decl;
src-self-hosted/codegen.zig+5-5
...@@ -145,10 +145,10 @@ pub fn generateSymbol(...@@ -145,10 +145,10 @@ pub fn generateSymbol(
145 if (typed_value.val.cast(Value.Payload.DeclRef)) |payload| {145 if (typed_value.val.cast(Value.Payload.DeclRef)) |payload| {
146 const decl = payload.decl;146 const decl = payload.decl;
147 if (decl.analysis != .complete) return error.AnalysisFail;147 if (decl.analysis != .complete) return error.AnalysisFail;
148 assert(decl.link.local_sym_index != 0);148 assert(decl.link.elf.local_sym_index != 0);
149 // TODO handle the dependency of this symbol on the decl's vaddr.149 // TODO handle the dependency of this symbol on the decl's vaddr.
150 // If the decl changes vaddr, then this symbol needs to get regenerated.150 // If the decl changes vaddr, then this symbol needs to get regenerated.
151 const vaddr = bin_file.local_symbols.items[decl.link.local_sym_index].st_value;151 const vaddr = bin_file.local_symbols.items[decl.link.elf.local_sym_index].st_value;
152 const endian = bin_file.base.options.target.cpu.arch.endian();152 const endian = bin_file.base.options.target.cpu.arch.endian();
153 switch (bin_file.base.options.target.cpu.arch.ptrBitWidth()) {153 switch (bin_file.base.options.target.cpu.arch.ptrBitWidth()) {
154 16 => {154 16 => {
...@@ -1085,7 +1085,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -1085,7 +1085,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
1085 const got = &self.bin_file.program_headers.items[self.bin_file.phdr_got_index.?];1085 const got = &self.bin_file.program_headers.items[self.bin_file.phdr_got_index.?];
1086 const ptr_bits = self.target.cpu.arch.ptrBitWidth();1086 const ptr_bits = self.target.cpu.arch.ptrBitWidth();
1087 const ptr_bytes: u64 = @divExact(ptr_bits, 8);1087 const ptr_bytes: u64 = @divExact(ptr_bits, 8);
1088 const got_addr = @intCast(u32, got.p_vaddr + func.owner_decl.link.offset_table_index * ptr_bytes);1088 const got_addr = @intCast(u32, got.p_vaddr + func.owner_decl.link.elf.offset_table_index * ptr_bytes);
1089 // ff 14 25 xx xx xx xx call [addr]1089 // ff 14 25 xx xx xx xx call [addr]
1090 try self.code.ensureCapacity(self.code.items.len + 7);1090 try self.code.ensureCapacity(self.code.items.len + 7);
1091 self.code.appendSliceAssumeCapacity(&[3]u8{ 0xff, 0x14, 0x25 });1091 self.code.appendSliceAssumeCapacity(&[3]u8{ 0xff, 0x14, 0x25 });
...@@ -1106,7 +1106,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -1106,7 +1106,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
1106 const got = &self.bin_file.program_headers.items[self.bin_file.phdr_got_index.?];1106 const got = &self.bin_file.program_headers.items[self.bin_file.phdr_got_index.?];
1107 const ptr_bits = self.target.cpu.arch.ptrBitWidth();1107 const ptr_bits = self.target.cpu.arch.ptrBitWidth();
1108 const ptr_bytes: u64 = @divExact(ptr_bits, 8);1108 const ptr_bytes: u64 = @divExact(ptr_bits, 8);
1109 const got_addr = @intCast(u32, got.p_vaddr + func.owner_decl.link.offset_table_index * ptr_bytes);1109 const got_addr = @intCast(u32, got.p_vaddr + func.owner_decl.link.elf.offset_table_index * ptr_bytes);
11101110
1111 try self.genSetReg(inst.base.src, .ra, .{ .memory = got_addr });1111 try self.genSetReg(inst.base.src, .ra, .{ .memory = got_addr });
1112 const jalr = instructions.Jalr{1112 const jalr = instructions.Jalr{
...@@ -1934,7 +1934,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -1934,7 +1934,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
1934 if (typed_value.val.cast(Value.Payload.DeclRef)) |payload| {1934 if (typed_value.val.cast(Value.Payload.DeclRef)) |payload| {
1935 const got = &self.bin_file.program_headers.items[self.bin_file.phdr_got_index.?];1935 const got = &self.bin_file.program_headers.items[self.bin_file.phdr_got_index.?];
1936 const decl = payload.decl;1936 const decl = payload.decl;
1937 const got_addr = got.p_vaddr + decl.link.offset_table_index * ptr_bytes;1937 const got_addr = got.p_vaddr + decl.link.elf.offset_table_index * ptr_bytes;
1938 return MCValue{ .memory = got_addr };1938 return MCValue{ .memory = got_addr };
1939 }1939 }
1940 return self.fail(src, "TODO codegen more kinds of const pointers", .{});1940 return self.fail(src, "TODO codegen more kinds of const pointers", .{});
src-self-hosted/link.zig+47-37
...@@ -38,6 +38,16 @@ pub const Options = struct {...@@ -38,6 +38,16 @@ pub const Options = struct {
3838
3939
40pub const File = struct {40pub const File = struct {
41 pub const LinkBlock = union {
42 elf: Elf.TextBlock,
43 c: void,
44 };
45
46 pub const LinkFn = union {
47 elf: Elf.SrcFn,
48 c: void,
49 };
50
41 tag: Tag,51 tag: Tag,
42 options: Options,52 options: Options,
43 file: ?fs.File,53 file: ?fs.File,
...@@ -1720,31 +1730,31 @@ pub const File = struct {...@@ -1720,31 +1730,31 @@ pub const File = struct {
1720 }1730 }
17211731
1722 pub fn allocateDeclIndexes(self: *Elf, decl: *Module.Decl) !void {1732 pub fn allocateDeclIndexes(self: *Elf, decl: *Module.Decl) !void {
1723 if (decl.link.local_sym_index != 0) return;1733 if (decl.link.elf.local_sym_index != 0) return;
17241734
1725 try self.local_symbols.ensureCapacity(self.base.allocator, self.local_symbols.items.len + 1);1735 try self.local_symbols.ensureCapacity(self.base.allocator, self.local_symbols.items.len + 1);
1726 try self.offset_table.ensureCapacity(self.base.allocator, self.offset_table.items.len + 1);1736 try self.offset_table.ensureCapacity(self.base.allocator, self.offset_table.items.len + 1);
17271737
1728 if (self.local_symbol_free_list.popOrNull()) |i| {1738 if (self.local_symbol_free_list.popOrNull()) |i| {
1729 log.debug(.link, "reusing symbol index {} for {}\n", .{ i, decl.name });1739 log.debug(.link, "reusing symbol index {} for {}\n", .{ i, decl.name });
1730 decl.link.local_sym_index = i;1740 decl.link.elf.local_sym_index = i;
1731 } else {1741 } else {
1732 log.debug(.link, "allocating symbol index {} for {}\n", .{ self.local_symbols.items.len, decl.name });1742 log.debug(.link, "allocating symbol index {} for {}\n", .{ self.local_symbols.items.len, decl.name });
1733 decl.link.local_sym_index = @intCast(u32, self.local_symbols.items.len);1743 decl.link.elf.local_sym_index = @intCast(u32, self.local_symbols.items.len);
1734 _ = self.local_symbols.addOneAssumeCapacity();1744 _ = self.local_symbols.addOneAssumeCapacity();
1735 }1745 }
17361746
1737 if (self.offset_table_free_list.popOrNull()) |i| {1747 if (self.offset_table_free_list.popOrNull()) |i| {
1738 decl.link.offset_table_index = i;1748 decl.link.elf.offset_table_index = i;
1739 } else {1749 } else {
1740 decl.link.offset_table_index = @intCast(u32, self.offset_table.items.len);1750 decl.link.elf.offset_table_index = @intCast(u32, self.offset_table.items.len);
1741 _ = self.offset_table.addOneAssumeCapacity();1751 _ = self.offset_table.addOneAssumeCapacity();
1742 self.offset_table_count_dirty = true;1752 self.offset_table_count_dirty = true;
1743 }1753 }
17441754
1745 const phdr = &self.program_headers.items[self.phdr_load_re_index.?];1755 const phdr = &self.program_headers.items[self.phdr_load_re_index.?];
17461756
1747 self.local_symbols.items[decl.link.local_sym_index] = .{1757 self.local_symbols.items[decl.link.elf.local_sym_index] = .{
1748 .st_name = 0,1758 .st_name = 0,
1749 .st_info = 0,1759 .st_info = 0,
1750 .st_other = 0,1760 .st_other = 0,
...@@ -1752,39 +1762,39 @@ pub const File = struct {...@@ -1752,39 +1762,39 @@ pub const File = struct {
1752 .st_value = phdr.p_vaddr,1762 .st_value = phdr.p_vaddr,
1753 .st_size = 0,1763 .st_size = 0,
1754 };1764 };
1755 self.offset_table.items[decl.link.offset_table_index] = 0;1765 self.offset_table.items[decl.link.elf.offset_table_index] = 0;
1756 }1766 }
17571767
1758 pub fn freeDecl(self: *Elf, decl: *Module.Decl) void {1768 pub fn freeDecl(self: *Elf, decl: *Module.Decl) void {
1759 // Appending to free lists is allowed to fail because the free lists are heuristics based anyway.1769 // Appending to free lists is allowed to fail because the free lists are heuristics based anyway.
1760 self.freeTextBlock(&decl.link);1770 self.freeTextBlock(&decl.link.elf);
1761 if (decl.link.local_sym_index != 0) {1771 if (decl.link.elf.local_sym_index != 0) {
1762 self.local_symbol_free_list.append(self.base.allocator, decl.link.local_sym_index) catch {};1772 self.local_symbol_free_list.append(self.base.allocator, decl.link.elf.local_sym_index) catch {};
1763 self.offset_table_free_list.append(self.base.allocator, decl.link.offset_table_index) catch {};1773 self.offset_table_free_list.append(self.base.allocator, decl.link.elf.offset_table_index) catch {};
17641774
1765 self.local_symbols.items[decl.link.local_sym_index].st_info = 0;1775 self.local_symbols.items[decl.link.elf.local_sym_index].st_info = 0;
17661776
1767 decl.link.local_sym_index = 0;1777 decl.link.elf.local_sym_index = 0;
1768 }1778 }
1769 // TODO make this logic match freeTextBlock. Maybe abstract the logic out since the same thing1779 // TODO make this logic match freeTextBlock. Maybe abstract the logic out since the same thing
1770 // is desired for both.1780 // is desired for both.
1771 _ = self.dbg_line_fn_free_list.remove(&decl.fn_link);1781 _ = self.dbg_line_fn_free_list.remove(&decl.fn_link.elf);
1772 if (decl.fn_link.prev) |prev| {1782 if (decl.fn_link.elf.prev) |prev| {
1773 _ = self.dbg_line_fn_free_list.put(self.base.allocator, prev, {}) catch {};1783 _ = self.dbg_line_fn_free_list.put(self.base.allocator, prev, {}) catch {};
1774 prev.next = decl.fn_link.next;1784 prev.next = decl.fn_link.elf.next;
1775 if (decl.fn_link.next) |next| {1785 if (decl.fn_link.elf.next) |next| {
1776 next.prev = prev;1786 next.prev = prev;
1777 } else {1787 } else {
1778 self.dbg_line_fn_last = prev;1788 self.dbg_line_fn_last = prev;
1779 }1789 }
1780 } else if (decl.fn_link.next) |next| {1790 } else if (decl.fn_link.elf.next) |next| {
1781 self.dbg_line_fn_first = next;1791 self.dbg_line_fn_first = next;
1782 next.prev = null;1792 next.prev = null;
1783 }1793 }
1784 if (self.dbg_line_fn_first == &decl.fn_link) {1794 if (self.dbg_line_fn_first == &decl.fn_link.elf) {
1785 self.dbg_line_fn_first = null;1795 self.dbg_line_fn_first = null;
1786 }1796 }
1787 if (self.dbg_line_fn_last == &decl.fn_link) {1797 if (self.dbg_line_fn_last == &decl.fn_link.elf) {
1788 self.dbg_line_fn_last = null;1798 self.dbg_line_fn_last = null;
1789 }1799 }
1790 }1800 }
...@@ -1870,24 +1880,24 @@ pub const File = struct {...@@ -1870,24 +1880,24 @@ pub const File = struct {
18701880
1871 const stt_bits: u8 = if (is_fn) elf.STT_FUNC else elf.STT_OBJECT;1881 const stt_bits: u8 = if (is_fn) elf.STT_FUNC else elf.STT_OBJECT;
18721882
1873 assert(decl.link.local_sym_index != 0); // Caller forgot to allocateDeclIndexes()1883 assert(decl.link.elf.local_sym_index != 0); // Caller forgot to allocateDeclIndexes()
1874 const local_sym = &self.local_symbols.items[decl.link.local_sym_index];1884 const local_sym = &self.local_symbols.items[decl.link.elf.local_sym_index];
1875 if (local_sym.st_size != 0) {1885 if (local_sym.st_size != 0) {
1876 const capacity = decl.link.capacity(self.*);1886 const capacity = decl.link.elf.capacity(self.*);
1877 const need_realloc = code.len > capacity or1887 const need_realloc = code.len > capacity or
1878 !mem.isAlignedGeneric(u64, local_sym.st_value, required_alignment);1888 !mem.isAlignedGeneric(u64, local_sym.st_value, required_alignment);
1879 if (need_realloc) {1889 if (need_realloc) {
1880 const vaddr = try self.growTextBlock(&decl.link, code.len, required_alignment);1890 const vaddr = try self.growTextBlock(&decl.link.elf, code.len, required_alignment);
1881 log.debug(.link, "growing {} from 0x{x} to 0x{x}\n", .{ decl.name, local_sym.st_value, vaddr });1891 log.debug(.link, "growing {} from 0x{x} to 0x{x}\n", .{ decl.name, local_sym.st_value, vaddr });
1882 if (vaddr != local_sym.st_value) {1892 if (vaddr != local_sym.st_value) {
1883 local_sym.st_value = vaddr;1893 local_sym.st_value = vaddr;
18841894
1885 log.debug(.link, " (writing new offset table entry)\n", .{});1895 log.debug(.link, " (writing new offset table entry)\n", .{});
1886 self.offset_table.items[decl.link.offset_table_index] = vaddr;1896 self.offset_table.items[decl.link.elf.offset_table_index] = vaddr;
1887 try self.writeOffsetTableEntry(decl.link.offset_table_index);1897 try self.writeOffsetTableEntry(decl.link.elf.offset_table_index);
1888 }1898 }
1889 } else if (code.len < local_sym.st_size) {1899 } else if (code.len < local_sym.st_size) {
1890 self.shrinkTextBlock(&decl.link, code.len);1900 self.shrinkTextBlock(&decl.link.elf, code.len);
1891 }1901 }
1892 local_sym.st_size = code.len;1902 local_sym.st_size = code.len;
1893 local_sym.st_name = try self.updateString(local_sym.st_name, mem.spanZ(decl.name));1903 local_sym.st_name = try self.updateString(local_sym.st_name, mem.spanZ(decl.name));
...@@ -1895,13 +1905,13 @@ pub const File = struct {...@@ -1895,13 +1905,13 @@ pub const File = struct {
1895 local_sym.st_other = 0;1905 local_sym.st_other = 0;
1896 local_sym.st_shndx = self.text_section_index.?;1906 local_sym.st_shndx = self.text_section_index.?;
1897 // TODO this write could be avoided if no fields of the symbol were changed.1907 // TODO this write could be avoided if no fields of the symbol were changed.
1898 try self.writeSymbol(decl.link.local_sym_index);1908 try self.writeSymbol(decl.link.elf.local_sym_index);
1899 } else {1909 } else {
1900 const decl_name = mem.spanZ(decl.name);1910 const decl_name = mem.spanZ(decl.name);
1901 const name_str_index = try self.makeString(decl_name);1911 const name_str_index = try self.makeString(decl_name);
1902 const vaddr = try self.allocateTextBlock(&decl.link, code.len, required_alignment);1912 const vaddr = try self.allocateTextBlock(&decl.link.elf, code.len, required_alignment);
1903 log.debug(.link, "allocated text block for {} at 0x{x}\n", .{ decl_name, vaddr });1913 log.debug(.link, "allocated text block for {} at 0x{x}\n", .{ decl_name, vaddr });
1904 errdefer self.freeTextBlock(&decl.link);1914 errdefer self.freeTextBlock(&decl.link.elf);
19051915
1906 local_sym.* = .{1916 local_sym.* = .{
1907 .st_name = name_str_index,1917 .st_name = name_str_index,
...@@ -1911,10 +1921,10 @@ pub const File = struct {...@@ -1911,10 +1921,10 @@ pub const File = struct {
1911 .st_value = vaddr,1921 .st_value = vaddr,
1912 .st_size = code.len,1922 .st_size = code.len,
1913 };1923 };
1914 self.offset_table.items[decl.link.offset_table_index] = vaddr;1924 self.offset_table.items[decl.link.elf.offset_table_index] = vaddr;
19151925
1916 try self.writeSymbol(decl.link.local_sym_index);1926 try self.writeSymbol(decl.link.elf.local_sym_index);
1917 try self.writeOffsetTableEntry(decl.link.offset_table_index);1927 try self.writeOffsetTableEntry(decl.link.elf.offset_table_index);
1918 }1928 }
19191929
1920 const section_offset = local_sym.st_value - self.program_headers.items[self.phdr_load_re_index.?].p_vaddr;1930 const section_offset = local_sym.st_value - self.program_headers.items[self.phdr_load_re_index.?].p_vaddr;
...@@ -1941,7 +1951,7 @@ pub const File = struct {...@@ -1941,7 +1951,7 @@ pub const File = struct {
1941 // Now we have the full contents and may allocate a region to store it.1951 // Now we have the full contents and may allocate a region to store it.
19421952
1943 const debug_line_sect = &self.sections.items[self.debug_line_section_index.?];1953 const debug_line_sect = &self.sections.items[self.debug_line_section_index.?];
1944 const src_fn = &decl.fn_link;1954 const src_fn = &decl.fn_link.elf;
1945 src_fn.len = @intCast(u32, dbg_line_buffer.items.len);1955 src_fn.len = @intCast(u32, dbg_line_buffer.items.len);
1946 if (self.dbg_line_fn_last) |last| {1956 if (self.dbg_line_fn_last) |last| {
1947 if (src_fn.next) |next| {1957 if (src_fn.next) |next| {
...@@ -2026,8 +2036,8 @@ pub const File = struct {...@@ -2026,8 +2036,8 @@ pub const File = struct {
20262036
2027 try self.global_symbols.ensureCapacity(self.base.allocator, self.global_symbols.items.len + exports.len);2037 try self.global_symbols.ensureCapacity(self.base.allocator, self.global_symbols.items.len + exports.len);
2028 const typed_value = decl.typed_value.most_recent.typed_value;2038 const typed_value = decl.typed_value.most_recent.typed_value;
2029 if (decl.link.local_sym_index == 0) return;2039 if (decl.link.elf.local_sym_index == 0) return;
2030 const decl_sym = self.local_symbols.items[decl.link.local_sym_index];2040 const decl_sym = self.local_symbols.items[decl.link.elf.local_sym_index];
20312041
2032 for (exports) |exp| {2042 for (exports) |exp| {
2033 if (exp.options.section) |section_name| {2043 if (exp.options.section) |section_name| {
...@@ -2105,7 +2115,7 @@ pub const File = struct {...@@ -2105,7 +2115,7 @@ pub const File = struct {
2105 const casted_line_off = @intCast(u28, line_delta);2115 const casted_line_off = @intCast(u28, line_delta);
21062116
2107 const shdr = &self.sections.items[self.debug_line_section_index.?];2117 const shdr = &self.sections.items[self.debug_line_section_index.?];
2108 const file_pos = shdr.sh_offset + decl.fn_link.off + self.getRelocDbgLineOff();2118 const file_pos = shdr.sh_offset + decl.fn_link.elf.off + self.getRelocDbgLineOff();
2109 var data: [4]u8 = undefined;2119 var data: [4]u8 = undefined;
2110 leb128.writeUnsignedFixed(4, &data, casted_line_off);2120 leb128.writeUnsignedFixed(4, &data, casted_line_off);
2111 try self.base.file.?.pwriteAll(&data, file_pos);2121 try self.base.file.?.pwriteAll(&data, file_pos);