Add skeleton for MachO support in stage2

This commit adds an empty skeleton for MachO format support in stage2.
This commit is contained in:
Jakub Konka
2020-08-16 18:11:10 +02:00
parent 6b141620a6
commit e23fc3905f
2 changed files with 117 additions and 2 deletions

View File

@@ -1568,6 +1568,9 @@ fn analyzeRootSrcFile(self: *Module, root_scope: *Scope.File) !void {
// in `Decl` to notice that the line number did not change.
self.work_queue.writeItemAssumeCapacity(.{ .update_line_number = decl });
},
.macho => {
// TODO Implement for MachO
},
.c => {},
}
}
@@ -1776,10 +1779,12 @@ fn allocateNewDecl(
.contents_hash = contents_hash,
.link = switch (self.bin_file.tag) {
.elf => .{ .elf = link.File.Elf.TextBlock.empty },
.macho => .{ .macho = link.File.MachO.TextBlock.empty },
.c => .{ .c = {} },
},
.fn_link = switch (self.bin_file.tag) {
.elf => .{ .elf = link.File.Elf.SrcFn.empty },
.macho => .{ .macho = link.File.MachO.SrcFn.empty },
.c => .{ .c = {} },
},
.generation = 0,

View File

@@ -44,11 +44,13 @@ pub const Options = struct {
pub const File = struct {
pub const LinkBlock = union {
elf: Elf.TextBlock,
macho: MachO.TextBlock,
c: void,
};
pub const LinkFn = union {
elf: Elf.SrcFn,
macho: MachO.SrcFn,
c: void,
};
@@ -66,7 +68,7 @@ pub const File = struct {
.unknown => unreachable,
.coff => return error.TODOImplementCoff,
.elf => return Elf.openPath(allocator, dir, sub_path, options),
.macho => return error.TODOImplementMacho,
.macho => return MachO.openPath(allocator, dir, sub_path, options),
.wasm => return error.TODOImplementWasm,
.c => return C.openPath(allocator, dir, sub_path, options),
.hex => return error.TODOImplementHex,
@@ -83,7 +85,7 @@ pub const File = struct {
pub fn makeWritable(base: *File, dir: fs.Dir, sub_path: []const u8) !void {
switch (base.tag) {
.elf => {
.elf, .macho => {
if (base.file != null) return;
base.file = try dir.createFile(sub_path, .{
.truncate = false,
@@ -106,6 +108,7 @@ pub const File = struct {
pub fn updateDecl(base: *File, module: *Module, decl: *Module.Decl) !void {
switch (base.tag) {
.elf => return @fieldParentPtr(Elf, "base", base).updateDecl(module, decl),
.macho => return @fieldParentPtr(MachO, "base", base).updateDecl(module, decl),
.c => return @fieldParentPtr(C, "base", base).updateDecl(module, decl),
}
}
@@ -113,6 +116,7 @@ pub const File = struct {
pub fn updateDeclLineNumber(base: *File, module: *Module, decl: *Module.Decl) !void {
switch (base.tag) {
.elf => return @fieldParentPtr(Elf, "base", base).updateDeclLineNumber(module, decl),
.macho => return @fieldParentPtr(MachO, "base", base).updateDeclLineNumber(module, decl),
.c => {},
}
}
@@ -120,6 +124,7 @@ pub const File = struct {
pub fn allocateDeclIndexes(base: *File, decl: *Module.Decl) !void {
switch (base.tag) {
.elf => return @fieldParentPtr(Elf, "base", base).allocateDeclIndexes(decl),
.macho => return @fieldParentPtr(MachO, "base", base).allocateDeclIndexes(decl),
.c => {},
}
}
@@ -128,6 +133,7 @@ pub const File = struct {
if (base.file) |f| f.close();
switch (base.tag) {
.elf => @fieldParentPtr(Elf, "base", base).deinit(),
.macho => @fieldParentPtr(MachO, "base", base).deinit(),
.c => @fieldParentPtr(C, "base", base).deinit(),
}
}
@@ -139,6 +145,11 @@ pub const File = struct {
parent.deinit();
base.allocator.destroy(parent);
},
.macho => {
const parent = @fieldParentPtr(MachO, "base", base);
parent.deinit();
base.allocator.destroy(parent);
},
.c => {
const parent = @fieldParentPtr(C, "base", base);
parent.deinit();
@@ -153,6 +164,7 @@ pub const File = struct {
try switch (base.tag) {
.elf => @fieldParentPtr(Elf, "base", base).flush(),
.macho => @fieldParentPtr(MachO, "base", base).flush(),
.c => @fieldParentPtr(C, "base", base).flush(),
};
}
@@ -160,6 +172,7 @@ pub const File = struct {
pub fn freeDecl(base: *File, decl: *Module.Decl) void {
switch (base.tag) {
.elf => @fieldParentPtr(Elf, "base", base).freeDecl(decl),
.macho => @fieldParentPtr(MachO, "base", base).freeDecl(decl),
.c => unreachable,
}
}
@@ -167,6 +180,7 @@ pub const File = struct {
pub fn errorFlags(base: *File) ErrorFlags {
return switch (base.tag) {
.elf => @fieldParentPtr(Elf, "base", base).error_flags,
.macho => @fieldParentPtr(MachO, "base", base).error_flags,
.c => return .{ .no_entry_point_found = false },
};
}
@@ -180,12 +194,14 @@ pub const File = struct {
) !void {
switch (base.tag) {
.elf => return @fieldParentPtr(Elf, "base", base).updateDeclExports(module, decl, exports),
.macho => return @fieldParentPtr(MachO, "base", base).updateDeclExports(module, decl, exports),
.c => return {},
}
}
pub const Tag = enum {
elf,
macho,
c,
};
@@ -2815,6 +2831,100 @@ pub const File = struct {
}
};
pub const MachO = struct {
pub const base_tag: Tag = .macho;
base: File,
ptr_width: enum { p32, p64 },
error_flags: ErrorFlags = ErrorFlags{},
pub const TextBlock = struct {
pub const empty = TextBlock{};
};
pub const SrcFn = struct {
pub const empty = SrcFn{};
};
pub fn openPath(allocator: *Allocator, dir: fs.Dir, sub_path: []const u8, options: Options) !*File {
assert(options.object_format == .macho);
const file = try dir.createFile(sub_path, .{ .truncate = false, .read = true, .mode = determineMode(options) });
errdefer file.close();
var macho_file = try allocator.create(MachO);
errdefer allocator.destroy(macho_file);
macho_file.* = openFile(allocator, file, options) catch |err| switch (err) {
error.IncrFailed => try createFile(allocator, file, options),
else => |e| return e,
};
return &macho_file.base;
}
/// Returns error.IncrFailed if incremental update could not be performed.
fn openFile(allocator: *Allocator, file: fs.File, options: Options) !MachO {
switch (options.output_mode) {
.Exe => {},
.Obj => {},
.Lib => return error.IncrFailed,
}
var self: MachO = .{
.base = .{
.file = file,
.tag = .macho,
.options = options,
.allocator = allocator,
},
.ptr_width = switch (options.target.cpu.arch.ptrBitWidth()) {
32 => .p32,
64 => .p64,
else => return error.UnsupportedELFArchitecture,
},
};
errdefer self.deinit();
// TODO implement reading the macho file
return error.IncrFailed;
//try self.populateMissingMetadata();
//return self;
}
/// Truncates the existing file contents and overwrites the contents.
/// Returns an error if `file` is not already open with +read +write +seek abilities.
fn createFile(allocator: *Allocator, file: fs.File, options: Options) !MachO {
switch (options.output_mode) {
.Exe => return error.TODOImplementWritingMachOExeFiles,
.Obj => return error.TODOImplementWritingMachOObjFiles,
.Lib => return error.TODOImplementWritingLibFiles,
}
}
/// Commit pending changes and write headers.
pub fn flush(self: *MachO) !void {}
pub fn deinit(self: *MachO) void {}
pub fn allocateDeclIndexes(self: *MachO, decl: *Module.Decl) !void {}
pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void {}
pub fn updateDeclLineNumber(self: *MachO, module: *Module, decl: *const Module.Decl) !void {}
/// Must be called only after a successful call to `updateDecl`.
pub fn updateDeclExports(
self: *MachO,
module: *Module,
decl: *const Module.Decl,
exports: []const *Module.Export,
) !void {}
pub fn freeDecl(self: *MachO, decl: *Module.Decl) void {}
};
};
/// Saturating multiplication