mirror of
https://github.com/ziglang/zig.git
synced 2026-02-14 05:20:34 +00:00
macho: unify resolving globals
This commit is contained in:
parent
7f6973fbae
commit
84853c5c56
@ -245,6 +245,82 @@ pub const Zld = struct {
|
||||
try self.resolveSymbolsAtLoading();
|
||||
}
|
||||
|
||||
fn resolveGlobalSymbol(self: *Zld, current: SymbolWithLoc) !void {
|
||||
const gpa = self.gpa;
|
||||
const sym = self.getSymbol(current);
|
||||
const sym_name = self.getSymbolName(current);
|
||||
|
||||
const gop = try self.getOrPutGlobalPtr(sym_name);
|
||||
if (!gop.found_existing) {
|
||||
gop.value_ptr.* = current;
|
||||
if (sym.undf() and !sym.tentative()) {
|
||||
try self.unresolved.putNoClobber(gpa, self.getGlobalIndex(sym_name).?, {});
|
||||
}
|
||||
return;
|
||||
}
|
||||
const global_index = self.getGlobalIndex(sym_name).?;
|
||||
const global = gop.value_ptr.*;
|
||||
const global_sym = self.getSymbol(global);
|
||||
|
||||
// Cases to consider: sym vs global_sym
|
||||
// 1. strong(sym) and strong(global_sym) => error
|
||||
// 2. strong(sym) and weak(global_sym) => sym
|
||||
// 3. strong(sym) and tentative(global_sym) => sym
|
||||
// 4. strong(sym) and undf(global_sym) => sym
|
||||
// 5. weak(sym) and strong(global_sym) => global_sym
|
||||
// 6. weak(sym) and tentative(global_sym) => sym
|
||||
// 7. weak(sym) and undf(global_sym) => sym
|
||||
// 8. tentative(sym) and strong(global_sym) => global_sym
|
||||
// 9. tentative(sym) and weak(global_sym) => global_sym
|
||||
// 10. tentative(sym) and tentative(global_sym) => pick larger
|
||||
// 11. tentative(sym) and undf(global_sym) => sym
|
||||
// 12. undf(sym) and * => global_sym
|
||||
//
|
||||
// Reduces to:
|
||||
// 1. strong(sym) and strong(global_sym) => error
|
||||
// 2. * and strong(global_sym) => global_sym
|
||||
// 3. weak(sym) and weak(global_sym) => global_sym
|
||||
// 4. tentative(sym) and tentative(global_sym) => pick larger
|
||||
// 5. undf(sym) and * => global_sym
|
||||
// 6. else => sym
|
||||
|
||||
const sym_is_strong = sym.sect() and !(sym.weakDef() or sym.pext());
|
||||
const global_is_strong = global_sym.sect() and !(global_sym.weakDef() or global_sym.pext());
|
||||
const sym_is_weak = sym.sect() and (sym.weakDef() or sym.pext());
|
||||
const global_is_weak = global_sym.sect() and (global_sym.weakDef() or global_sym.pext());
|
||||
|
||||
if (sym_is_strong and global_is_strong) {
|
||||
log.err("symbol '{s}' defined multiple times", .{sym_name});
|
||||
if (global.getFile()) |file| {
|
||||
log.err(" first definition in '{s}'", .{self.objects.items[file].name});
|
||||
}
|
||||
if (current.getFile()) |file| {
|
||||
log.err(" next definition in '{s}'", .{self.objects.items[file].name});
|
||||
}
|
||||
return error.MultipleSymbolDefinitions;
|
||||
}
|
||||
|
||||
if (current.getFile()) |file| {
|
||||
const object = &self.objects.items[file];
|
||||
object.globals_lookup[current.sym_index] = global_index;
|
||||
}
|
||||
|
||||
if (global_is_strong) return;
|
||||
if (sym_is_weak and global_is_weak) return;
|
||||
if (sym.tentative() and global_sym.tentative()) {
|
||||
if (global_sym.n_value >= sym.n_value) return;
|
||||
}
|
||||
if (sym.undf() and !sym.tentative()) return;
|
||||
|
||||
if (global.getFile()) |file| {
|
||||
const global_object = &self.objects.items[file];
|
||||
global_object.globals_lookup[global.sym_index] = global_index;
|
||||
}
|
||||
_ = self.unresolved.swapRemove(global_index);
|
||||
|
||||
gop.value_ptr.* = current;
|
||||
}
|
||||
|
||||
fn resolveSymbolsInObject(self: *Zld, object_id: u32) !void {
|
||||
const object = &self.objects.items[object_id];
|
||||
const in_symtab = object.in_symtab orelse return;
|
||||
@ -285,76 +361,7 @@ pub const Zld = struct {
|
||||
continue;
|
||||
}
|
||||
|
||||
const sym_loc = SymbolWithLoc{ .sym_index = sym_index, .file = object_id + 1 };
|
||||
|
||||
const gop = try self.getOrPutGlobalPtr(sym_name);
|
||||
if (!gop.found_existing) {
|
||||
gop.value_ptr.* = sym_loc;
|
||||
if (sym.undf() and !sym.tentative()) {
|
||||
try self.unresolved.putNoClobber(self.gpa, self.getGlobalIndex(sym_name).?, {});
|
||||
}
|
||||
continue;
|
||||
}
|
||||
const global_index = self.getGlobalIndex(sym_name).?;
|
||||
const global = gop.value_ptr;
|
||||
const global_sym = self.getSymbol(global.*);
|
||||
|
||||
// Cases to consider: sym vs global_sym
|
||||
// 1. strong(sym) and strong(global_sym) => error
|
||||
// 2. strong(sym) and weak(global_sym) => sym
|
||||
// 3. strong(sym) and tentative(global_sym) => sym
|
||||
// 4. strong(sym) and undf(global_sym) => sym
|
||||
// 5. weak(sym) and strong(global_sym) => global_sym
|
||||
// 6. weak(sym) and tentative(global_sym) => sym
|
||||
// 7. weak(sym) and undf(global_sym) => sym
|
||||
// 8. tentative(sym) and strong(global_sym) => global_sym
|
||||
// 9. tentative(sym) and weak(global_sym) => global_sym
|
||||
// 10. tentative(sym) and tentative(global_sym) => pick larger
|
||||
// 11. tentative(sym) and undf(global_sym) => sym
|
||||
// 12. undf(sym) and * => global_sym
|
||||
//
|
||||
// Reduces to:
|
||||
// 1. strong(sym) and strong(global_sym) => error
|
||||
// 2. * and strong(global_sym) => global_sym
|
||||
// 3. weak(sym) and weak(global_sym) => global_sym
|
||||
// 4. tentative(sym) and tentative(global_sym) => pick larger
|
||||
// 5. undf(sym) and * => global_sym
|
||||
// 6. else => sym
|
||||
|
||||
const sym_is_strong = sym.sect() and !(sym.weakDef() or sym.pext());
|
||||
const global_is_strong = global_sym.sect() and !(global_sym.weakDef() or global_sym.pext());
|
||||
const sym_is_weak = sym.sect() and (sym.weakDef() or sym.pext());
|
||||
const global_is_weak = global_sym.sect() and (global_sym.weakDef() or global_sym.pext());
|
||||
|
||||
if (sym_is_strong and global_is_strong) {
|
||||
log.err("symbol '{s}' defined multiple times", .{sym_name});
|
||||
if (global.getFile()) |file| {
|
||||
log.err(" first definition in '{s}'", .{self.objects.items[file].name});
|
||||
}
|
||||
log.err(" next definition in '{s}'", .{self.objects.items[object_id].name});
|
||||
return error.MultipleSymbolDefinitions;
|
||||
}
|
||||
|
||||
const update_global = blk: {
|
||||
if (global_is_strong) break :blk false;
|
||||
if (sym_is_weak and global_is_weak) break :blk false;
|
||||
if (sym.tentative() and global_sym.tentative()) {
|
||||
if (global_sym.n_value >= sym.n_value) break :blk false;
|
||||
}
|
||||
if (sym.undf() and !sym.tentative()) break :blk false;
|
||||
break :blk true;
|
||||
};
|
||||
|
||||
if (update_global) {
|
||||
if (global.getFile()) |file| {
|
||||
const global_object = &self.objects.items[file];
|
||||
global_object.globals_lookup[global.sym_index] = global_index;
|
||||
}
|
||||
_ = self.unresolved.swapRemove(global_index);
|
||||
global.* = sym_loc;
|
||||
} else {
|
||||
object.globals_lookup[sym_index] = global_index;
|
||||
}
|
||||
try self.resolveGlobalSymbol(.{ .sym_index = sym_index, .file = object_id + 1 });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user