authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-05-13 22:12:38-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-05-13 22:12:38-04:00
log6a2425c38c2a776d2aafd68b25da8c4c1164f614
tree418f27f237b06c20907434b90d99350a6f6a9787
parent080022f6c670b0f74c39fe01096ebdbaafeda1b2

self-hosted: fix the rest of the compile errors


3 files changed, 57 insertions(+), 50 deletions(-)

lib/std/fs/file.zig+7-4
...@@ -527,19 +527,21 @@ pub const File = struct {...@@ -527,19 +527,21 @@ pub const File = struct {
527 }527 }
528 }528 }
529529
530 pub fn copyRange(in: File, in_offset: u64, out: File, out_offset: u64, len: usize) PWriteError!usize {530 pub const CopyRangeError = PWriteError || PReadError;
531
532 pub fn copyRange(in: File, in_offset: u64, out: File, out_offset: u64, len: usize) CopyRangeError!usize {
531 // TODO take advantage of copy_file_range OS APIs533 // TODO take advantage of copy_file_range OS APIs
532 var buf: [8 * 4096]u8 = undefined;534 var buf: [8 * 4096]u8 = undefined;
533 const adjusted_count = math.min(buf.len, len);535 const adjusted_count = math.min(buf.len, len);
534 const amt_read = try in.pread(buf[0..adjusted_count], in_offset);536 const amt_read = try in.pread(buf[0..adjusted_count], in_offset);
535 if (amt_read == 0) return 0;537 if (amt_read == 0) return @as(usize, 0);
536 return out.pwrite(buf[0..amt_read], out_offset);538 return out.pwrite(buf[0..amt_read], out_offset);
537 }539 }
538540
539 /// Returns the number of bytes copied. If the number read is smaller than `buffer.len`, it541 /// Returns the number of bytes copied. If the number read is smaller than `buffer.len`, it
540 /// means the in file reached the end. Reaching the end of a file is not an error condition.542 /// means the in file reached the end. Reaching the end of a file is not an error condition.
541 pub fn copyRangeAll(in: File, in_offset: u64, out: File, out_offset: u64, len: usize) PWriteError!usize {543 pub fn copyRangeAll(in: File, in_offset: u64, out: File, out_offset: u64, len: usize) CopyRangeError!usize {
542 var total_bytes_copied = 0;544 var total_bytes_copied: usize = 0;
543 var in_off = in_offset;545 var in_off = in_offset;
544 var out_off = out_offset;546 var out_off = out_offset;
545 while (total_bytes_copied < len) {547 while (total_bytes_copied < len) {
...@@ -549,6 +551,7 @@ pub const File = struct {...@@ -549,6 +551,7 @@ pub const File = struct {
549 in_off += amt_copied;551 in_off += amt_copied;
550 out_off += amt_copied;552 out_off += amt_copied;
551 }553 }
554 return total_bytes_copied;
552 }555 }
553556
554 pub const WriteFileOptions = struct {557 pub const WriteFileOptions = struct {
src-self-hosted/codegen.zig+24-23
...@@ -5,16 +5,17 @@ const ir = @import("ir.zig");...@@ -5,16 +5,17 @@ const ir = @import("ir.zig");
5const Type = @import("type.zig").Type;5const Type = @import("type.zig").Type;
6const Value = @import("value.zig").Value;6const Value = @import("value.zig").Value;
7const TypedValue = @import("TypedValue.zig");7const TypedValue = @import("TypedValue.zig");
8const link = @import("link.zig");
8const Target = std.Target;9const Target = std.Target;
9const Allocator = mem.Allocator;10const Allocator = mem.Allocator;
1011
11pub fn generateSymbol(typed_value: TypedValue, module: ir.Module, code: *std.ArrayList(u8)) !?*ir.ErrorMsg {12pub fn generateSymbol(bin_file: *link.ElfFile, typed_value: TypedValue, code: *std.ArrayList(u8)) !?*ir.ErrorMsg {
12 switch (typed_value.ty.zigTypeTag()) {13 switch (typed_value.ty.zigTypeTag()) {
13 .Fn => {14 .Fn => {
14 const module_fn = typed_value.val.cast(Value.Payload.Function).?.func;15 const module_fn = typed_value.val.cast(Value.Payload.Function).?.func;
1516
16 var function = Function{17 var function = Function{
17 .module = &module,18 .target = &bin_file.options.target,
18 .mod_fn = module_fn,19 .mod_fn = module_fn,
19 .code = code,20 .code = code,
20 .inst_table = std.AutoHashMap(*ir.Inst, Function.MCValue).init(code.allocator),21 .inst_table = std.AutoHashMap(*ir.Inst, Function.MCValue).init(code.allocator),
...@@ -22,7 +23,7 @@ pub fn generateSymbol(typed_value: TypedValue, module: ir.Module, code: *std.Arr...@@ -22,7 +23,7 @@ pub fn generateSymbol(typed_value: TypedValue, module: ir.Module, code: *std.Arr
22 };23 };
23 defer function.inst_table.deinit();24 defer function.inst_table.deinit();
2425
25 for (module_fn.body.instructions) |inst| {26 for (module_fn.analysis.success.instructions) |inst| {
26 const new_inst = function.genFuncInst(inst) catch |err| switch (err) {27 const new_inst = function.genFuncInst(inst) catch |err| switch (err) {
27 error.CodegenFail => {28 error.CodegenFail => {
28 assert(function.err_msg != null);29 assert(function.err_msg != null);
...@@ -40,7 +41,7 @@ pub fn generateSymbol(typed_value: TypedValue, module: ir.Module, code: *std.Arr...@@ -40,7 +41,7 @@ pub fn generateSymbol(typed_value: TypedValue, module: ir.Module, code: *std.Arr
40}41}
4142
42const Function = struct {43const Function = struct {
43 module: *const ir.Module,44 target: *const std.Target,
44 mod_fn: *const ir.Module.Fn,45 mod_fn: *const ir.Module.Fn,
45 code: *std.ArrayList(u8),46 code: *std.ArrayList(u8),
46 inst_table: std.AutoHashMap(*ir.Inst, MCValue),47 inst_table: std.AutoHashMap(*ir.Inst, MCValue),
...@@ -76,60 +77,60 @@ const Function = struct {...@@ -76,60 +77,60 @@ const Function = struct {
76 }77 }
7778
78 fn genBreakpoint(self: *Function, src: usize) !MCValue {79 fn genBreakpoint(self: *Function, src: usize) !MCValue {
79 switch (self.module.target.cpu.arch) {80 switch (self.target.cpu.arch) {
80 .i386, .x86_64 => {81 .i386, .x86_64 => {
81 try self.code.append(0xcc); // int382 try self.code.append(0xcc); // int3
82 },83 },
83 else => return self.fail(src, "TODO implement @breakpoint() for {}", .{self.module.target.cpu.arch}),84 else => return self.fail(src, "TODO implement @breakpoint() for {}", .{self.target.cpu.arch}),
84 }85 }
85 return .unreach;86 return .unreach;
86 }87 }
8788
88 fn genCall(self: *Function, inst: *ir.Inst.Call) !MCValue {89 fn genCall(self: *Function, inst: *ir.Inst.Call) !MCValue {
89 switch (self.module.target.cpu.arch) {90 switch (self.target.cpu.arch) {
90 else => return self.fail(inst.base.src, "TODO implement call for {}", .{self.module.target.cpu.arch}),91 else => return self.fail(inst.base.src, "TODO implement call for {}", .{self.target.cpu.arch}),
91 }92 }
92 return .unreach;93 return .unreach;
93 }94 }
9495
95 fn genRet(self: *Function, inst: *ir.Inst.Ret) !MCValue {96 fn genRet(self: *Function, inst: *ir.Inst.Ret) !MCValue {
96 switch (self.module.target.cpu.arch) {97 switch (self.target.cpu.arch) {
97 .i386, .x86_64 => {98 .i386, .x86_64 => {
98 try self.code.append(0xc3); // ret99 try self.code.append(0xc3); // ret
99 },100 },
100 else => return self.fail(inst.base.src, "TODO implement return for {}", .{self.module.target.cpu.arch}),101 else => return self.fail(inst.base.src, "TODO implement return for {}", .{self.target.cpu.arch}),
101 }102 }
102 return .unreach;103 return .unreach;
103 }104 }
104105
105 fn genCmp(self: *Function, inst: *ir.Inst.Cmp) !MCValue {106 fn genCmp(self: *Function, inst: *ir.Inst.Cmp) !MCValue {
106 switch (self.module.target.cpu.arch) {107 switch (self.target.cpu.arch) {
107 else => return self.fail(inst.base.src, "TODO implement cmp for {}", .{self.module.target.cpu.arch}),108 else => return self.fail(inst.base.src, "TODO implement cmp for {}", .{self.target.cpu.arch}),
108 }109 }
109 }110 }
110111
111 fn genCondBr(self: *Function, inst: *ir.Inst.CondBr) !MCValue {112 fn genCondBr(self: *Function, inst: *ir.Inst.CondBr) !MCValue {
112 switch (self.module.target.cpu.arch) {113 switch (self.target.cpu.arch) {
113 else => return self.fail(inst.base.src, "TODO implement condbr for {}", .{self.module.target.cpu.arch}),114 else => return self.fail(inst.base.src, "TODO implement condbr for {}", .{self.target.cpu.arch}),
114 }115 }
115 }116 }
116117
117 fn genIsNull(self: *Function, inst: *ir.Inst.IsNull) !MCValue {118 fn genIsNull(self: *Function, inst: *ir.Inst.IsNull) !MCValue {
118 switch (self.module.target.cpu.arch) {119 switch (self.target.cpu.arch) {
119 else => return self.fail(inst.base.src, "TODO implement isnull for {}", .{self.module.target.cpu.arch}),120 else => return self.fail(inst.base.src, "TODO implement isnull for {}", .{self.target.cpu.arch}),
120 }121 }
121 }122 }
122123
123 fn genIsNonNull(self: *Function, inst: *ir.Inst.IsNonNull) !MCValue {124 fn genIsNonNull(self: *Function, inst: *ir.Inst.IsNonNull) !MCValue {
124 // Here you can specialize this instruction if it makes sense to, otherwise the default125 // Here you can specialize this instruction if it makes sense to, otherwise the default
125 // will call genIsNull and invert the result.126 // will call genIsNull and invert the result.
126 switch (self.module.target.cpu.arch) {127 switch (self.target.cpu.arch) {
127 else => return self.fail(inst.base.src, "TODO call genIsNull and invert the result ", .{}),128 else => return self.fail(inst.base.src, "TODO call genIsNull and invert the result ", .{}),
128 }129 }
129 }130 }
130131
131 fn genRelativeFwdJump(self: *Function, src: usize, amount: u32) !void {132 fn genRelativeFwdJump(self: *Function, src: usize, amount: u32) !void {
132 switch (self.module.target.cpu.arch) {133 switch (self.target.cpu.arch) {
133 .i386, .x86_64 => {134 .i386, .x86_64 => {
134 // TODO x86 treats the operands as signed135 // TODO x86 treats the operands as signed
135 if (amount <= std.math.maxInt(u8)) {136 if (amount <= std.math.maxInt(u8)) {
...@@ -143,13 +144,13 @@ const Function = struct {...@@ -143,13 +144,13 @@ const Function = struct {
143 mem.writeIntLittle(u32, imm_ptr, amount);144 mem.writeIntLittle(u32, imm_ptr, amount);
144 }145 }
145 },146 },
146 else => return self.fail(src, "TODO implement relative forward jump for {}", .{self.module.target.cpu.arch}),147 else => return self.fail(src, "TODO implement relative forward jump for {}", .{self.target.cpu.arch}),
147 }148 }
148 }149 }
149150
150 fn genAsm(self: *Function, inst: *ir.Inst.Assembly) !MCValue {151 fn genAsm(self: *Function, inst: *ir.Inst.Assembly) !MCValue {
151 // TODO convert to inline function152 // TODO convert to inline function
152 switch (self.module.target.cpu.arch) {153 switch (self.target.cpu.arch) {
153 .arm => return self.genAsmArch(.arm, inst),154 .arm => return self.genAsmArch(.arm, inst),
154 .armeb => return self.genAsmArch(.armeb, inst),155 .armeb => return self.genAsmArch(.armeb, inst),
155 .aarch64 => return self.genAsmArch(.aarch64, inst),156 .aarch64 => return self.genAsmArch(.aarch64, inst),
...@@ -388,7 +389,7 @@ const Function = struct {...@@ -388,7 +389,7 @@ const Function = struct {
388 }389 }
389 }390 }
390391
391 fn genTypedValue(self: *Function, src: usize, typed_value: ir.TypedValue) !MCValue {392 fn genTypedValue(self: *Function, src: usize, typed_value: TypedValue) !MCValue {
392 switch (typed_value.ty.zigTypeTag()) {393 switch (typed_value.ty.zigTypeTag()) {
393 .Pointer => {394 .Pointer => {
394 const ptr_elem_type = typed_value.ty.elemType();395 const ptr_elem_type = typed_value.ty.elemType();
...@@ -410,8 +411,8 @@ const Function = struct {...@@ -410,8 +411,8 @@ const Function = struct {
410 }411 }
411 },412 },
412 .Int => {413 .Int => {
413 const info = typed_value.ty.intInfo(self.module.target);414 const info = typed_value.ty.intInfo(self.target.*);
414 const ptr_bits = self.module.target.cpu.arch.ptrBitWidth();415 const ptr_bits = self.target.cpu.arch.ptrBitWidth();
415 if (info.bits > ptr_bits or info.signed) {416 if (info.bits > ptr_bits or info.signed) {
416 return self.fail(src, "TODO const int bigger than ptr and signed int", .{});417 return self.fail(src, "TODO const int bigger than ptr and signed int", .{});
417 }418 }
src-self-hosted/link.zig+26-23
...@@ -685,23 +685,20 @@ pub const ElfFile = struct {...@@ -685,23 +685,20 @@ pub const ElfFile = struct {
685 // TODO Also detect virtual address collisions.685 // TODO Also detect virtual address collisions.
686 const text_capacity = self.allocatedSize(shdr.sh_offset);686 const text_capacity = self.allocatedSize(shdr.sh_offset);
687 // TODO instead of looping here, maintain a free list and a pointer to the end.687 // TODO instead of looping here, maintain a free list and a pointer to the end.
688 const end_vaddr = blk: {688 var last_start: u64 = 0;
689 var start: u64 = 0;689 var last_size: u64 = 0;
690 var size: u64 = 0;690 for (self.symbols.items) |sym| {
691 for (self.symbols.items) |sym| {691 if (sym.st_value > last_start) {
692 if (sym.st_value > start) {692 last_start = sym.st_value;
693 start = sm.st_value;693 last_size = sym.st_size;
694 size = sym.st_size;
695 }
696 }694 }
697 break :blk start + (size * alloc_num / alloc_den);695 }
698 };696 const end_vaddr = last_start + (last_size * alloc_num / alloc_den);
699697 const needed_size = (end_vaddr + new_block_size) - phdr.p_vaddr;
700 const text_size = end_vaddr - phdr.p_vaddr;
701 const needed_size = text_size + new_block_size;
702 if (needed_size > text_capacity) {698 if (needed_size > text_capacity) {
703 // Must move the entire text section.699 // Must move the entire text section.
704 const new_offset = self.findFreeSpace(needed_size, 0x1000);700 const new_offset = self.findFreeSpace(needed_size, 0x1000);
701 const text_size = (last_start + last_size) - phdr.p_vaddr;
705 const amt = try self.file.copyRangeAll(shdr.sh_offset, self.file, new_offset, text_size);702 const amt = try self.file.copyRangeAll(shdr.sh_offset, self.file, new_offset, text_size);
706 if (amt != text_size) return error.InputOutput;703 if (amt != text_size) return error.InputOutput;
707 shdr.sh_offset = new_offset;704 shdr.sh_offset = new_offset;
...@@ -713,6 +710,12 @@ pub const ElfFile = struct {...@@ -713,6 +710,12 @@ pub const ElfFile = struct {
713710
714 self.phdr_table_dirty = true; // TODO look into making only the one program header dirty711 self.phdr_table_dirty = true; // TODO look into making only the one program header dirty
715 self.shdr_table_dirty = true; // TODO look into making only the one section dirty712 self.shdr_table_dirty = true; // TODO look into making only the one section dirty
713
714 return AllocatedBlock{
715 .vaddr = end_vaddr,
716 .file_offset = shdr.sh_offset + (end_vaddr - phdr.p_vaddr),
717 .size_capacity = text_capacity - end_vaddr,
718 };
716 }719 }
717720
718 fn findAllocatedTextBlock(self: *ElfFile, sym: elf.Elf64_Sym) AllocatedBlock {721 fn findAllocatedTextBlock(self: *ElfFile, sym: elf.Elf64_Sym) AllocatedBlock {
...@@ -739,8 +742,8 @@ pub const ElfFile = struct {...@@ -739,8 +742,8 @@ pub const ElfFile = struct {
739 defer code.deinit();742 defer code.deinit();
740743
741 const typed_value = decl.typed_value.most_recent.typed_value;744 const typed_value = decl.typed_value.most_recent.typed_value;
742 const err_msg = try codegen.generateSymbol(typed_value, module.*, &code);745 const err_msg = try codegen.generateSymbol(self, typed_value, &code);
743 if (err_msg != null) |em| {746 if (err_msg) |em| {
744 decl.analysis = .codegen_failure;747 decl.analysis = .codegen_failure;
745 _ = try module.failed_decls.put(decl, em);748 _ = try module.failed_decls.put(decl, em);
746 return;749 return;
...@@ -755,7 +758,7 @@ pub const ElfFile = struct {...@@ -755,7 +758,7 @@ pub const ElfFile = struct {
755758
756 if (decl.link.local_sym_index != 0) {759 if (decl.link.local_sym_index != 0) {
757 const local_sym = &self.symbols.items[decl.link.local_sym_index];760 const local_sym = &self.symbols.items[decl.link.local_sym_index];
758 const existing_block = self.findAllocatedTextBlock(local_sym);761 const existing_block = self.findAllocatedTextBlock(local_sym.*);
759 const file_offset = if (code_size > existing_block.size_capacity) fo: {762 const file_offset = if (code_size > existing_block.size_capacity) fo: {
760 const new_block = try self.allocateTextBlock(code_size);763 const new_block = try self.allocateTextBlock(code_size);
761 local_sym.st_value = new_block.vaddr;764 local_sym.st_value = new_block.vaddr;
...@@ -765,7 +768,7 @@ pub const ElfFile = struct {...@@ -765,7 +768,7 @@ pub const ElfFile = struct {
765768
766 break :fo new_block.file_offset;769 break :fo new_block.file_offset;
767 } else existing_block.file_offset;770 } else existing_block.file_offset;
768 local_sym.st_name = try self.updateString(local_sym.st_name, mem.spanZ(u8, decl.name));771 local_sym.st_name = try self.updateString(local_sym.st_name, mem.spanZ(decl.name));
769 local_sym.st_info = (elf.STB_LOCAL << 4) | stt_bits;772 local_sym.st_info = (elf.STB_LOCAL << 4) | stt_bits;
770 // TODO this write could be avoided if no fields of the symbol were changed.773 // TODO this write could be avoided if no fields of the symbol were changed.
771 try self.writeSymbol(decl.link.local_sym_index);774 try self.writeSymbol(decl.link.local_sym_index);
...@@ -773,7 +776,7 @@ pub const ElfFile = struct {...@@ -773,7 +776,7 @@ pub const ElfFile = struct {
773 } else {776 } else {
774 try self.symbols.ensureCapacity(self.allocator, self.symbols.items.len + 1);777 try self.symbols.ensureCapacity(self.allocator, self.symbols.items.len + 1);
775 try self.offset_table.ensureCapacity(self.allocator, self.offset_table.items.len + 1);778 try self.offset_table.ensureCapacity(self.allocator, self.offset_table.items.len + 1);
776 const decl_name = mem.spanZ(u8, decl.name);779 const decl_name = mem.spanZ(decl.name);
777 const name_str_index = try self.makeString(decl_name);780 const name_str_index = try self.makeString(decl_name);
778 const new_block = try self.allocateTextBlock(code_size);781 const new_block = try self.allocateTextBlock(code_size);
779 const local_sym_index = self.symbols.items.len;782 const local_sym_index = self.symbols.items.len;
...@@ -796,8 +799,8 @@ pub const ElfFile = struct {...@@ -796,8 +799,8 @@ pub const ElfFile = struct {
796 self.symbol_count_dirty = true;799 self.symbol_count_dirty = true;
797 self.offset_table_count_dirty = true;800 self.offset_table_count_dirty = true;
798 decl.link = .{801 decl.link = .{
799 .local_sym_index = local_sym_index,802 .local_sym_index = @intCast(u32, local_sym_index),
800 .offset_table_index = offset_table_index,803 .offset_table_index = @intCast(u32, offset_table_index),
801 };804 };
802805
803 break :blk new_block.file_offset;806 break :blk new_block.file_offset;
...@@ -807,7 +810,7 @@ pub const ElfFile = struct {...@@ -807,7 +810,7 @@ pub const ElfFile = struct {
807 try self.file.pwriteAll(code.items, file_offset);810 try self.file.pwriteAll(code.items, file_offset);
808811
809 // Since we updated the vaddr and the size, each corresponding export symbol also needs to be updated.812 // Since we updated the vaddr and the size, each corresponding export symbol also needs to be updated.
810 const decl_exports = module.decl_exports.get(decl) orelse &[0]*ir.Module.Export{};813 const decl_exports = module.decl_exports.getValue(decl) orelse &[0]*ir.Module.Export{};
811 return self.updateDeclExports(module, decl, decl_exports);814 return self.updateDeclExports(module, decl, decl_exports);
812 }815 }
813816
...@@ -938,9 +941,9 @@ pub const ElfFile = struct {...@@ -938,9 +941,9 @@ pub const ElfFile = struct {
938 const needed_size = self.symbols.items.len * shdr.sh_entsize;941 const needed_size = self.symbols.items.len * shdr.sh_entsize;
939 if (needed_size > allocated_size) {942 if (needed_size > allocated_size) {
940 // Must move the entire got section.943 // Must move the entire got section.
941 const new_offset = self.findFreeSpace(needed_size, shdr.sh_entsize);944 const new_offset = self.findFreeSpace(needed_size, @intCast(u16, shdr.sh_entsize));
942 const amt = try self.file.copyRangeAll(shdr.sh_offset, self.file, new_offset, shdr.sh_size);945 const amt = try self.file.copyRangeAll(shdr.sh_offset, self.file, new_offset, shdr.sh_size);
943 if (amt != text_size) return error.InputOutput;946 if (amt != shdr.sh_size) return error.InputOutput;
944 shdr.sh_offset = new_offset;947 shdr.sh_offset = new_offset;
945 }948 }
946 shdr.sh_size = needed_size;949 shdr.sh_size = needed_size;