authorgravatar for noam@pixelhero.devNoam Preil <noam@pixelhero.dev> 2020-07-07 23:11:17-04:00
committergravatar for noam@pixelhero.devNoam Preil <noam@pixelhero.dev> 2020-07-07 23:11:17-04:00
log173e6712417c8102ff6bbd28fd964b89eda14f36
tree8bd5aba37e7e9672493b683549a5cdf7847a777e
parentb91cf1597267275dbbf57551acbe0461216ff08e
signaturelock-open Commit is signed but in an unrecognized format.

CBE: Some cleanup


3 files changed, 44 insertions(+), 51 deletions(-)

src-self-hosted/link.zig+43-45
...@@ -125,36 +125,34 @@ pub const File = struct {...@@ -125,36 +125,34 @@ pub const File = struct {
125 }125 }
126126
127 pub fn makeWritable(base: *File, dir: fs.Dir, sub_path: []const u8) !void {127 pub fn makeWritable(base: *File, dir: fs.Dir, sub_path: []const u8) !void {
128 try switch (base.tag) {128 switch (base.tag) {
129 .Elf => @fieldParentPtr(Elf, "base", base).makeWritable(dir, sub_path),129 .Elf => return @fieldParentPtr(Elf, "base", base).makeWritable(dir, sub_path),
130 .C => @fieldParentPtr(C, "base", base).makeWritable(dir, sub_path),130 .C => return @fieldParentPtr(C, "base", base).makeWritable(dir, sub_path),
131 else => unreachable,131 else => unreachable,
132 };132 }
133 }133 }
134134
135 pub fn makeExecutable(base: *File) !void {135 pub fn makeExecutable(base: *File) !void {
136 try switch (base.tag) {136 switch (base.tag) {
137 .Elf => @fieldParentPtr(Elf, "base", base).makeExecutable(),137 .Elf => return @fieldParentPtr(Elf, "base", base).makeExecutable(),
138 else => unreachable,138 else => unreachable,
139 };139 }
140 }140 }
141141
142 pub fn updateDecl(base: *File, module: *Module, decl: *Module.Decl) !void {142 pub fn updateDecl(base: *File, module: *Module, decl: *Module.Decl) !void {
143 try switch (base.tag) {143 switch (base.tag) {
144 .Elf => @fieldParentPtr(Elf, "base", base).updateDecl(module, decl),144 .Elf => return @fieldParentPtr(Elf, "base", base).updateDecl(module, decl),
145 .C => @fieldParentPtr(C, "base", base).updateDecl(module, decl),145 .C => return @fieldParentPtr(C, "base", base).updateDecl(module, decl),
146 else => unreachable,146 else => unreachable,
147 };147 }
148 }148 }
149149
150 pub fn allocateDeclIndexes(base: *File, decl: *Module.Decl) !void {150 pub fn allocateDeclIndexes(base: *File, decl: *Module.Decl) !void {
151 try switch (base.tag) {151 switch (base.tag) {
152 .Elf => @fieldParentPtr(Elf, "base", base).allocateDeclIndexes(decl),152 .Elf => return @fieldParentPtr(Elf, "base", base).allocateDeclIndexes(decl),
153 .C => {153 .C => {},
154 //TODO
155 },
156 else => unreachable,154 else => unreachable,
157 };155 }
158 }156 }
159157
160 pub fn deinit(base: *File) void {158 pub fn deinit(base: *File) void {
...@@ -380,7 +378,7 @@ pub const File = struct {...@@ -380,7 +378,7 @@ pub const File = struct {
380 /// Returns how much room there is to grow in virtual address space.378 /// Returns how much room there is to grow in virtual address space.
381 /// File offset relocation happens transparently, so it is not included in379 /// File offset relocation happens transparently, so it is not included in
382 /// this calculation.380 /// this calculation.
383 fn capacity(self: TextBlock, elf_file: File.Elf) u64 {381 fn capacity(self: TextBlock, elf_file: Elf) u64 {
384 const self_sym = elf_file.local_symbols.items[self.local_sym_index];382 const self_sym = elf_file.local_symbols.items[self.local_sym_index];
385 if (self.next) |next| {383 if (self.next) |next| {
386 const next_sym = elf_file.local_symbols.items[next.local_sym_index];384 const next_sym = elf_file.local_symbols.items[next.local_sym_index];
...@@ -391,7 +389,7 @@ pub const File = struct {...@@ -391,7 +389,7 @@ pub const File = struct {
391 }389 }
392 }390 }
393391
394 fn freeListEligible(self: TextBlock, elf_file: File.Elf) bool {392 fn freeListEligible(self: TextBlock, elf_file: Elf) bool {
395 // No need to keep a free list node for the last block.393 // No need to keep a free list node for the last block.
396 const next = self.next orelse return false;394 const next = self.next orelse return false;
397 const self_sym = elf_file.local_symbols.items[self.local_sym_index];395 const self_sym = elf_file.local_symbols.items[self.local_sym_index];
...@@ -408,7 +406,7 @@ pub const File = struct {...@@ -408,7 +406,7 @@ pub const File = struct {
408 sym_index: ?u32 = null,406 sym_index: ?u32 = null,
409 };407 };
410408
411 pub fn deinit(self: *File.Elf) void {409 pub fn deinit(self: *Elf) void {
412 self.sections.deinit(self.allocator);410 self.sections.deinit(self.allocator);
413 self.program_headers.deinit(self.allocator);411 self.program_headers.deinit(self.allocator);
414 self.shstrtab.deinit(self.allocator);412 self.shstrtab.deinit(self.allocator);
...@@ -424,7 +422,7 @@ pub const File = struct {...@@ -424,7 +422,7 @@ pub const File = struct {
424 }422 }
425 }423 }
426424
427 pub fn makeExecutable(self: *File.Elf) !void {425 pub fn makeExecutable(self: *Elf) !void {
428 assert(self.owns_file_handle);426 assert(self.owns_file_handle);
429 if (self.file) |f| {427 if (self.file) |f| {
430 f.close();428 f.close();
...@@ -432,7 +430,7 @@ pub const File = struct {...@@ -432,7 +430,7 @@ pub const File = struct {
432 }430 }
433 }431 }
434432
435 pub fn makeWritable(self: *File.Elf, dir: fs.Dir, sub_path: []const u8) !void {433 pub fn makeWritable(self: *Elf, dir: fs.Dir, sub_path: []const u8) !void {
436 assert(self.owns_file_handle);434 assert(self.owns_file_handle);
437 if (self.file != null) return;435 if (self.file != null) return;
438 self.file = try dir.createFile(sub_path, .{436 self.file = try dir.createFile(sub_path, .{
...@@ -443,7 +441,7 @@ pub const File = struct {...@@ -443,7 +441,7 @@ pub const File = struct {
443 }441 }
444442
445 /// Returns end pos of collision, if any.443 /// Returns end pos of collision, if any.
446 fn detectAllocCollision(self: *File.Elf, start: u64, size: u64) ?u64 {444 fn detectAllocCollision(self: *Elf, start: u64, size: u64) ?u64 {
447 const small_ptr = self.options.target.cpu.arch.ptrBitWidth() == 32;445 const small_ptr = self.options.target.cpu.arch.ptrBitWidth() == 32;
448 const ehdr_size: u64 = if (small_ptr) @sizeOf(elf.Elf32_Ehdr) else @sizeOf(elf.Elf64_Ehdr);446 const ehdr_size: u64 = if (small_ptr) @sizeOf(elf.Elf32_Ehdr) else @sizeOf(elf.Elf64_Ehdr);
449 if (start < ehdr_size)447 if (start < ehdr_size)
...@@ -488,7 +486,7 @@ pub const File = struct {...@@ -488,7 +486,7 @@ pub const File = struct {
488 return null;486 return null;
489 }487 }
490488
491 fn allocatedSize(self: *File.Elf, start: u64) u64 {489 fn allocatedSize(self: *Elf, start: u64) u64 {
492 var min_pos: u64 = std.math.maxInt(u64);490 var min_pos: u64 = std.math.maxInt(u64);
493 if (self.shdr_table_offset) |off| {491 if (self.shdr_table_offset) |off| {
494 if (off > start and off < min_pos) min_pos = off;492 if (off > start and off < min_pos) min_pos = off;
...@@ -507,7 +505,7 @@ pub const File = struct {...@@ -507,7 +505,7 @@ pub const File = struct {
507 return min_pos - start;505 return min_pos - start;
508 }506 }
509507
510 fn findFreeSpace(self: *File.Elf, object_size: u64, min_alignment: u16) u64 {508 fn findFreeSpace(self: *Elf, object_size: u64, min_alignment: u16) u64 {
511 var start: u64 = 0;509 var start: u64 = 0;
512 while (self.detectAllocCollision(start, object_size)) |item_end| {510 while (self.detectAllocCollision(start, object_size)) |item_end| {
513 start = mem.alignForwardGeneric(u64, item_end, min_alignment);511 start = mem.alignForwardGeneric(u64, item_end, min_alignment);
...@@ -515,7 +513,7 @@ pub const File = struct {...@@ -515,7 +513,7 @@ pub const File = struct {
515 return start;513 return start;
516 }514 }
517515
518 fn makeString(self: *File.Elf, bytes: []const u8) !u32 {516 fn makeString(self: *Elf, bytes: []const u8) !u32 {
519 try self.shstrtab.ensureCapacity(self.allocator, self.shstrtab.items.len + bytes.len + 1);517 try self.shstrtab.ensureCapacity(self.allocator, self.shstrtab.items.len + bytes.len + 1);
520 const result = self.shstrtab.items.len;518 const result = self.shstrtab.items.len;
521 self.shstrtab.appendSliceAssumeCapacity(bytes);519 self.shstrtab.appendSliceAssumeCapacity(bytes);
...@@ -523,12 +521,12 @@ pub const File = struct {...@@ -523,12 +521,12 @@ pub const File = struct {
523 return @intCast(u32, result);521 return @intCast(u32, result);
524 }522 }
525523
526 fn getString(self: *File.Elf, str_off: u32) []const u8 {524 fn getString(self: *Elf, str_off: u32) []const u8 {
527 assert(str_off < self.shstrtab.items.len);525 assert(str_off < self.shstrtab.items.len);
528 return mem.spanZ(@ptrCast([*:0]const u8, self.shstrtab.items.ptr + str_off));526 return mem.spanZ(@ptrCast([*:0]const u8, self.shstrtab.items.ptr + str_off));
529 }527 }
530528
531 fn updateString(self: *File.Elf, old_str_off: u32, new_name: []const u8) !u32 {529 fn updateString(self: *Elf, old_str_off: u32, new_name: []const u8) !u32 {
532 const existing_name = self.getString(old_str_off);530 const existing_name = self.getString(old_str_off);
533 if (mem.eql(u8, existing_name, new_name)) {531 if (mem.eql(u8, existing_name, new_name)) {
534 return old_str_off;532 return old_str_off;
...@@ -536,7 +534,7 @@ pub const File = struct {...@@ -536,7 +534,7 @@ pub const File = struct {
536 return self.makeString(new_name);534 return self.makeString(new_name);
537 }535 }
538536
539 pub fn populateMissingMetadata(self: *File.Elf) !void {537 pub fn populateMissingMetadata(self: *Elf) !void {
540 const small_ptr = switch (self.ptr_width) {538 const small_ptr = switch (self.ptr_width) {
541 .p32 => true,539 .p32 => true,
542 .p64 => false,540 .p64 => false,
...@@ -703,7 +701,7 @@ pub const File = struct {...@@ -703,7 +701,7 @@ pub const File = struct {
703 }701 }
704702
705 /// Commit pending changes and write headers.703 /// Commit pending changes and write headers.
706 pub fn flush(self: *File.Elf) !void {704 pub fn flush(self: *Elf) !void {
707 const foreign_endian = self.options.target.cpu.arch.endian() != std.Target.current.cpu.arch.endian();705 const foreign_endian = self.options.target.cpu.arch.endian() != std.Target.current.cpu.arch.endian();
708706
709 // Unfortunately these have to be buffered and done at the end because ELF does not allow707 // Unfortunately these have to be buffered and done at the end because ELF does not allow
...@@ -839,7 +837,7 @@ pub const File = struct {...@@ -839,7 +837,7 @@ pub const File = struct {
839 assert(syms_sect.sh_info == self.local_symbols.items.len);837 assert(syms_sect.sh_info == self.local_symbols.items.len);
840 }838 }
841839
842 fn writeElfHeader(self: *File.Elf) !void {840 fn writeElfHeader(self: *Elf) !void {
843 var hdr_buf: [@sizeOf(elf.Elf64_Ehdr)]u8 = undefined;841 var hdr_buf: [@sizeOf(elf.Elf64_Ehdr)]u8 = undefined;
844842
845 var index: usize = 0;843 var index: usize = 0;
...@@ -960,7 +958,7 @@ pub const File = struct {...@@ -960,7 +958,7 @@ pub const File = struct {
960 try self.file.?.pwriteAll(hdr_buf[0..index], 0);958 try self.file.?.pwriteAll(hdr_buf[0..index], 0);
961 }959 }
962960
963 fn freeTextBlock(self: *File.Elf, text_block: *TextBlock) void {961 fn freeTextBlock(self: *Elf, text_block: *TextBlock) void {
964 var already_have_free_list_node = false;962 var already_have_free_list_node = false;
965 {963 {
966 var i: usize = 0;964 var i: usize = 0;
...@@ -1000,12 +998,12 @@ pub const File = struct {...@@ -1000,12 +998,12 @@ pub const File = struct {
1000 }998 }
1001 }999 }
10021000
1003 fn shrinkTextBlock(self: *File.Elf, text_block: *TextBlock, new_block_size: u64) void {1001 fn shrinkTextBlock(self: *Elf, text_block: *TextBlock, new_block_size: u64) void {
1004 // TODO check the new capacity, and if it crosses the size threshold into a big enough1002 // TODO check the new capacity, and if it crosses the size threshold into a big enough
1005 // capacity, insert a free list node for it.1003 // capacity, insert a free list node for it.
1006 }1004 }
10071005
1008 fn growTextBlock(self: *File.Elf, text_block: *TextBlock, new_block_size: u64, alignment: u64) !u64 {1006 fn growTextBlock(self: *Elf, text_block: *TextBlock, new_block_size: u64, alignment: u64) !u64 {
1009 const sym = self.local_symbols.items[text_block.local_sym_index];1007 const sym = self.local_symbols.items[text_block.local_sym_index];
1010 const align_ok = mem.alignBackwardGeneric(u64, sym.st_value, alignment) == sym.st_value;1008 const align_ok = mem.alignBackwardGeneric(u64, sym.st_value, alignment) == sym.st_value;
1011 const need_realloc = !align_ok or new_block_size > text_block.capacity(self.*);1009 const need_realloc = !align_ok or new_block_size > text_block.capacity(self.*);
...@@ -1013,7 +1011,7 @@ pub const File = struct {...@@ -1013,7 +1011,7 @@ pub const File = struct {
1013 return self.allocateTextBlock(text_block, new_block_size, alignment);1011 return self.allocateTextBlock(text_block, new_block_size, alignment);
1014 }1012 }
10151013
1016 fn allocateTextBlock(self: *File.Elf, text_block: *TextBlock, new_block_size: u64, alignment: u64) !u64 {1014 fn allocateTextBlock(self: *Elf, text_block: *TextBlock, new_block_size: u64, alignment: u64) !u64 {
1017 const phdr = &self.program_headers.items[self.phdr_load_re_index.?];1015 const phdr = &self.program_headers.items[self.phdr_load_re_index.?];
1018 const shdr = &self.sections.items[self.text_section_index.?];1016 const shdr = &self.sections.items[self.text_section_index.?];
1019 const new_block_ideal_capacity = new_block_size * alloc_num / alloc_den;1017 const new_block_ideal_capacity = new_block_size * alloc_num / alloc_den;
...@@ -1127,7 +1125,7 @@ pub const File = struct {...@@ -1127,7 +1125,7 @@ pub const File = struct {
1127 return vaddr;1125 return vaddr;
1128 }1126 }
11291127
1130 pub fn allocateDeclIndexes(self: *File.Elf, decl: *Module.Decl) !void {1128 pub fn allocateDeclIndexes(self: *Elf, decl: *Module.Decl) !void {
1131 if (decl.link.local_sym_index != 0) return;1129 if (decl.link.local_sym_index != 0) return;
11321130
1133 // Here we also ensure capacity for the free lists so that they can be appended to without fail.1131 // Here we also ensure capacity for the free lists so that they can be appended to without fail.
...@@ -1166,7 +1164,7 @@ pub const File = struct {...@@ -1166,7 +1164,7 @@ pub const File = struct {
1166 self.offset_table.items[decl.link.offset_table_index] = 0;1164 self.offset_table.items[decl.link.offset_table_index] = 0;
1167 }1165 }
11681166
1169 pub fn freeDecl(self: *File.Elf, decl: *Module.Decl) void {1167 pub fn freeDecl(self: *Elf, decl: *Module.Decl) void {
1170 self.freeTextBlock(&decl.link);1168 self.freeTextBlock(&decl.link);
1171 if (decl.link.local_sym_index != 0) {1169 if (decl.link.local_sym_index != 0) {
1172 self.local_symbol_free_list.appendAssumeCapacity(decl.link.local_sym_index);1170 self.local_symbol_free_list.appendAssumeCapacity(decl.link.local_sym_index);
...@@ -1178,7 +1176,7 @@ pub const File = struct {...@@ -1178,7 +1176,7 @@ pub const File = struct {
1178 }1176 }
1179 }1177 }
11801178
1181 pub fn updateDecl(self: *File.Elf, module: *Module, decl: *Module.Decl) !void {1179 pub fn updateDecl(self: *Elf, module: *Module, decl: *Module.Decl) !void {
1182 var code_buffer = std.ArrayList(u8).init(self.allocator);1180 var code_buffer = std.ArrayList(u8).init(self.allocator);
1183 defer code_buffer.deinit();1181 defer code_buffer.deinit();
11841182
...@@ -1258,7 +1256,7 @@ pub const File = struct {...@@ -1258,7 +1256,7 @@ pub const File = struct {
12581256
1259 /// Must be called only after a successful call to `updateDecl`.1257 /// Must be called only after a successful call to `updateDecl`.
1260 pub fn updateDeclExports(1258 pub fn updateDeclExports(
1261 self: *File.Elf,1259 self: *Elf,
1262 module: *Module,1260 module: *Module,
1263 decl: *const Module.Decl,1261 decl: *const Module.Decl,
1264 exports: []const *Module.Export,1262 exports: []const *Module.Export,
...@@ -1331,13 +1329,13 @@ pub const File = struct {...@@ -1331,13 +1329,13 @@ pub const File = struct {
1331 }1329 }
1332 }1330 }
13331331
1334 pub fn deleteExport(self: *File.Elf, exp: Export) void {1332 pub fn deleteExport(self: *Elf, exp: Export) void {
1335 const sym_index = exp.sym_index orelse return;1333 const sym_index = exp.sym_index orelse return;
1336 self.global_symbol_free_list.appendAssumeCapacity(sym_index);1334 self.global_symbol_free_list.appendAssumeCapacity(sym_index);
1337 self.global_symbols.items[sym_index].st_info = 0;1335 self.global_symbols.items[sym_index].st_info = 0;
1338 }1336 }
13391337
1340 fn writeProgHeader(self: *File.Elf, index: usize) !void {1338 fn writeProgHeader(self: *Elf, index: usize) !void {
1341 const foreign_endian = self.options.target.cpu.arch.endian() != std.Target.current.cpu.arch.endian();1339 const foreign_endian = self.options.target.cpu.arch.endian() != std.Target.current.cpu.arch.endian();
1342 const offset = self.program_headers.items[index].p_offset;1340 const offset = self.program_headers.items[index].p_offset;
1343 switch (self.options.target.cpu.arch.ptrBitWidth()) {1341 switch (self.options.target.cpu.arch.ptrBitWidth()) {
...@@ -1359,7 +1357,7 @@ pub const File = struct {...@@ -1359,7 +1357,7 @@ pub const File = struct {
1359 }1357 }
1360 }1358 }
13611359
1362 fn writeSectHeader(self: *File.Elf, index: usize) !void {1360 fn writeSectHeader(self: *Elf, index: usize) !void {
1363 const foreign_endian = self.options.target.cpu.arch.endian() != std.Target.current.cpu.arch.endian();1361 const foreign_endian = self.options.target.cpu.arch.endian() != std.Target.current.cpu.arch.endian();
1364 const offset = self.sections.items[index].sh_offset;1362 const offset = self.sections.items[index].sh_offset;
1365 switch (self.options.target.cpu.arch.ptrBitWidth()) {1363 switch (self.options.target.cpu.arch.ptrBitWidth()) {
...@@ -1382,7 +1380,7 @@ pub const File = struct {...@@ -1382,7 +1380,7 @@ pub const File = struct {
1382 }1380 }
1383 }1381 }
13841382
1385 fn writeOffsetTableEntry(self: *File.Elf, index: usize) !void {1383 fn writeOffsetTableEntry(self: *Elf, index: usize) !void {
1386 const shdr = &self.sections.items[self.got_section_index.?];1384 const shdr = &self.sections.items[self.got_section_index.?];
1387 const phdr = &self.program_headers.items[self.phdr_got_index.?];1385 const phdr = &self.program_headers.items[self.phdr_got_index.?];
1388 const entry_size: u16 = switch (self.ptr_width) {1386 const entry_size: u16 = switch (self.ptr_width) {
...@@ -1426,7 +1424,7 @@ pub const File = struct {...@@ -1426,7 +1424,7 @@ pub const File = struct {
1426 }1424 }
1427 }1425 }
14281426
1429 fn writeSymbol(self: *File.Elf, index: usize) !void {1427 fn writeSymbol(self: *Elf, index: usize) !void {
1430 const syms_sect = &self.sections.items[self.symtab_section_index.?];1428 const syms_sect = &self.sections.items[self.symtab_section_index.?];
1431 // Make sure we are not pointlessly writing symbol data that will have to get relocated1429 // Make sure we are not pointlessly writing symbol data that will have to get relocated
1432 // due to running out of space.1430 // due to running out of space.
...@@ -1482,7 +1480,7 @@ pub const File = struct {...@@ -1482,7 +1480,7 @@ pub const File = struct {
1482 }1480 }
1483 }1481 }
14841482
1485 fn writeAllGlobalSymbols(self: *File.Elf) !void {1483 fn writeAllGlobalSymbols(self: *Elf) !void {
1486 const syms_sect = &self.sections.items[self.symtab_section_index.?];1484 const syms_sect = &self.sections.items[self.symtab_section_index.?];
1487 const sym_size: u64 = switch (self.ptr_width) {1485 const sym_size: u64 = switch (self.ptr_width) {
1488 .p32 => @sizeOf(elf.Elf32_Sym),1486 .p32 => @sizeOf(elf.Elf32_Sym),
src-self-hosted/main.zig-5
...@@ -364,11 +364,6 @@ fn buildOutputType(...@@ -364,11 +364,6 @@ fn buildOutputType(
364 }364 }
365 }365 }
366366
367 if (cbe and output_mode != .Obj) {
368 std.debug.print("The C backend must be used with build-obj\n", .{});
369 process.exit(1);
370 }
371
372 const root_name = if (provided_name) |n| n else blk: {367 const root_name = if (provided_name) |n| n else blk: {
373 if (root_src_file) |file| {368 if (root_src_file) |file| {
374 const basename = fs.path.basename(file);369 const basename = fs.path.basename(file);
src-self-hosted/test.zig+1-1
...@@ -66,7 +66,7 @@ pub const TestContext = struct {...@@ -66,7 +66,7 @@ pub const TestContext = struct {
66 /// such as QEMU is required for tests to complete.66 /// such as QEMU is required for tests to complete.
67 target: std.zig.CrossTarget,67 target: std.zig.CrossTarget,
68 /// In order to be able to run e.g. Execution updates, this must be set68 /// In order to be able to run e.g. Execution updates, this must be set
69 /// to Executable. This is ignored when generating C output.69 /// to Executable.
70 output_mode: std.builtin.OutputMode,70 output_mode: std.builtin.OutputMode,
71 updates: std.ArrayList(Update),71 updates: std.ArrayList(Update),
72 extension: TestType,72 extension: TestType,