mirror of
https://github.com/ziglang/zig.git
synced 2026-02-21 16:54:52 +00:00
update codegen.llvm references to bin_file.options
This commit is contained in:
parent
92b54e50c8
commit
b54ad93175
@ -822,7 +822,7 @@ pub const Object = struct {
|
||||
type_map: TypeMap,
|
||||
di_type_map: DITypeMap,
|
||||
/// The LLVM global table which holds the names corresponding to Zig errors.
|
||||
/// Note that the values are not added until flushModule, when all errors in
|
||||
/// Note that the values are not added until `emit`, when all errors in
|
||||
/// the compilation are known.
|
||||
error_name_table: Builder.Variable.Index,
|
||||
/// This map is usually very close to empty. It tracks only the cases when a
|
||||
@ -850,7 +850,7 @@ pub const Object = struct {
|
||||
|
||||
pub const TypeMap = std.AutoHashMapUnmanaged(InternPool.Index, Builder.Type);
|
||||
|
||||
/// This is an ArrayHashMap as opposed to a HashMap because in `flushModule` we
|
||||
/// This is an ArrayHashMap as opposed to a HashMap because in `emit` we
|
||||
/// want to iterate over it while adding entries to it.
|
||||
pub const DITypeMap = std.AutoArrayHashMapUnmanaged(InternPool.Index, AnnotatedDITypePtr);
|
||||
|
||||
@ -1026,17 +1026,6 @@ pub const Object = struct {
|
||||
self.* = undefined;
|
||||
}
|
||||
|
||||
fn locPath(
|
||||
arena: Allocator,
|
||||
opt_loc: ?Compilation.EmitLoc,
|
||||
cache_directory: Compilation.Directory,
|
||||
) !?[*:0]u8 {
|
||||
const loc = opt_loc orelse return null;
|
||||
const directory = loc.directory orelse cache_directory;
|
||||
const slice = try directory.joinZ(arena, &[_][]const u8{loc.basename});
|
||||
return slice.ptr;
|
||||
}
|
||||
|
||||
fn genErrorNameTable(o: *Object) Allocator.Error!void {
|
||||
// If o.error_name_table is null, then it was not referenced by any instructions.
|
||||
if (o.error_name_table == .none) return;
|
||||
@ -1175,12 +1164,22 @@ pub const Object = struct {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn flushModule(self: *Object, comp: *Compilation, prog_node: *std.Progress.Node) !void {
|
||||
var sub_prog_node = prog_node.start("LLVM Emit Object", 0);
|
||||
sub_prog_node.activate();
|
||||
sub_prog_node.context.refresh();
|
||||
defer sub_prog_node.end();
|
||||
pub const EmitOptions = struct {
|
||||
pre_ir_path: ?[]const u8,
|
||||
pre_bc_path: ?[]const u8,
|
||||
bin_path: ?[*:0]const u8,
|
||||
emit_asm: ?[*:0]const u8,
|
||||
post_ir_path: ?[*:0]const u8,
|
||||
post_bc_path: ?[*:0]const u8,
|
||||
|
||||
is_debug: bool,
|
||||
is_small: bool,
|
||||
time_report: bool,
|
||||
sanitize_thread: bool,
|
||||
lto: bool,
|
||||
};
|
||||
|
||||
pub fn emit(self: *Object, options: EmitOptions) !void {
|
||||
try self.resolveExportExternCollisions();
|
||||
try self.genErrorNameTable();
|
||||
try self.genCmpLtErrorsLenFunction();
|
||||
@ -1206,7 +1205,7 @@ pub const Object = struct {
|
||||
dib.finalize();
|
||||
}
|
||||
|
||||
if (comp.verbose_llvm_ir) |path| {
|
||||
if (options.pre_ir_path) |path| {
|
||||
if (std.mem.eql(u8, path, "-")) {
|
||||
self.builder.dump();
|
||||
} else {
|
||||
@ -1214,91 +1213,72 @@ pub const Object = struct {
|
||||
}
|
||||
}
|
||||
|
||||
if (comp.verbose_llvm_bc) |path| _ = try self.builder.writeBitcodeToFile(path);
|
||||
|
||||
var arena_allocator = std.heap.ArenaAllocator.init(comp.gpa);
|
||||
defer arena_allocator.deinit();
|
||||
const arena = arena_allocator.allocator();
|
||||
|
||||
const mod = comp.module.?;
|
||||
const cache_dir = mod.zig_cache_artifact_directory;
|
||||
if (options.pre_bc_path) |path| _ = try self.builder.writeBitcodeToFile(path);
|
||||
|
||||
if (std.debug.runtime_safety and !try self.builder.verify()) {
|
||||
if (try locPath(arena, comp.emit_llvm_ir, cache_dir)) |emit_llvm_ir_path|
|
||||
_ = self.builder.printToFileZ(emit_llvm_ir_path);
|
||||
@panic("LLVM module verification failed");
|
||||
}
|
||||
|
||||
var emit_bin_path: ?[*:0]const u8 = if (comp.bin_file.options.emit) |emit|
|
||||
try emit.basenamePath(arena, try arena.dupeZ(u8, comp.bin_file.intermediary_basename.?))
|
||||
else
|
||||
null;
|
||||
|
||||
const emit_asm_path = try locPath(arena, comp.emit_asm, cache_dir);
|
||||
var emit_llvm_ir_path = try locPath(arena, comp.emit_llvm_ir, cache_dir);
|
||||
const emit_llvm_bc_path = try locPath(arena, comp.emit_llvm_bc, cache_dir);
|
||||
|
||||
const emit_asm_msg = emit_asm_path orelse "(none)";
|
||||
const emit_bin_msg = emit_bin_path orelse "(none)";
|
||||
const emit_llvm_ir_msg = emit_llvm_ir_path orelse "(none)";
|
||||
const emit_llvm_bc_msg = emit_llvm_bc_path orelse "(none)";
|
||||
const emit_asm_msg = options.asm_path orelse "(none)";
|
||||
const emit_bin_msg = options.bin_path orelse "(none)";
|
||||
const post_llvm_ir_msg = options.post_ir_path orelse "(none)";
|
||||
const post_llvm_bc_msg = options.post_bc_path orelse "(none)";
|
||||
log.debug("emit LLVM object asm={s} bin={s} ir={s} bc={s}", .{
|
||||
emit_asm_msg, emit_bin_msg, emit_llvm_ir_msg, emit_llvm_bc_msg,
|
||||
emit_asm_msg, emit_bin_msg, post_llvm_ir_msg, post_llvm_bc_msg,
|
||||
});
|
||||
|
||||
if (emit_asm_path == null and emit_bin_path == null and
|
||||
emit_llvm_ir_path == null and emit_llvm_bc_path == null) return;
|
||||
if (options.asm_path == null and options.bin_path == null and
|
||||
options.post_ir_path == null and options.post_bc_path == null) return;
|
||||
|
||||
if (!self.builder.useLibLlvm()) {
|
||||
log.err("emitting without libllvm not implemented", .{});
|
||||
return error.FailedToEmit;
|
||||
}
|
||||
if (!self.builder.useLibLlvm()) unreachable; // caught in Compilation.Config.resolve
|
||||
|
||||
// Unfortunately, LLVM shits the bed when we ask for both binary and assembly.
|
||||
// So we call the entire pipeline multiple times if this is requested.
|
||||
var error_message: [*:0]const u8 = undefined;
|
||||
if (emit_asm_path != null and emit_bin_path != null) {
|
||||
var emit_bin_path = options.bin_path;
|
||||
var post_ir_path = options.post_ir_path;
|
||||
if (options.asm_path != null and options.bin_path != null) {
|
||||
if (self.target_machine.emitToFile(
|
||||
self.builder.llvm.module.?,
|
||||
&error_message,
|
||||
comp.bin_file.options.optimize_mode == .Debug,
|
||||
comp.bin_file.options.optimize_mode == .ReleaseSmall,
|
||||
comp.time_report,
|
||||
comp.bin_file.options.tsan,
|
||||
comp.bin_file.options.lto,
|
||||
options.is_debug,
|
||||
options.is_small,
|
||||
options.time_report,
|
||||
options.sanitize_thread,
|
||||
options.lto,
|
||||
null,
|
||||
emit_bin_path,
|
||||
emit_llvm_ir_path,
|
||||
post_ir_path,
|
||||
null,
|
||||
)) {
|
||||
defer llvm.disposeMessage(error_message);
|
||||
|
||||
log.err("LLVM failed to emit bin={s} ir={s}: {s}", .{
|
||||
emit_bin_msg, emit_llvm_ir_msg, error_message,
|
||||
emit_bin_msg, post_llvm_ir_msg, error_message,
|
||||
});
|
||||
return error.FailedToEmit;
|
||||
}
|
||||
emit_bin_path = null;
|
||||
emit_llvm_ir_path = null;
|
||||
post_ir_path = null;
|
||||
}
|
||||
|
||||
if (self.target_machine.emitToFile(
|
||||
self.builder.llvm.module.?,
|
||||
&error_message,
|
||||
comp.bin_file.options.optimize_mode == .Debug,
|
||||
comp.bin_file.options.optimize_mode == .ReleaseSmall,
|
||||
comp.time_report,
|
||||
comp.bin_file.options.tsan,
|
||||
comp.bin_file.options.lto,
|
||||
emit_asm_path,
|
||||
options.is_debug,
|
||||
options.is_small,
|
||||
options.time_report,
|
||||
options.sanitize_thread,
|
||||
options.lto,
|
||||
options.asm_path,
|
||||
emit_bin_path,
|
||||
emit_llvm_ir_path,
|
||||
emit_llvm_bc_path,
|
||||
post_ir_path,
|
||||
options.post_bc_path,
|
||||
)) {
|
||||
defer llvm.disposeMessage(error_message);
|
||||
|
||||
log.err("LLVM failed to emit asm={s} bin={s} ir={s} bc={s}: {s}", .{
|
||||
emit_asm_msg, emit_bin_msg, emit_llvm_ir_msg, emit_llvm_bc_msg,
|
||||
emit_asm_msg, emit_bin_msg, post_llvm_ir_msg, post_llvm_bc_msg,
|
||||
error_message,
|
||||
});
|
||||
return error.FailedToEmit;
|
||||
@ -1307,17 +1287,19 @@ pub const Object = struct {
|
||||
|
||||
pub fn updateFunc(
|
||||
o: *Object,
|
||||
mod: *Module,
|
||||
zcu: *Module,
|
||||
func_index: InternPool.Index,
|
||||
air: Air,
|
||||
liveness: Liveness,
|
||||
) !void {
|
||||
const func = mod.funcInfo(func_index);
|
||||
const func = zcu.funcInfo(func_index);
|
||||
const decl_index = func.owner_decl;
|
||||
const decl = mod.declPtr(decl_index);
|
||||
const fn_info = mod.typeToFunc(decl.ty).?;
|
||||
const target = mod.getTarget();
|
||||
const ip = &mod.intern_pool;
|
||||
const decl = zcu.declPtr(decl_index);
|
||||
const namespace = zcu.namespacePtr(decl.src_namespace);
|
||||
const owner_mod = namespace.file_scope.mod;
|
||||
const fn_info = zcu.typeToFunc(decl.ty).?;
|
||||
const target = zcu.getTarget();
|
||||
const ip = &zcu.intern_pool;
|
||||
|
||||
var dg: DeclGen = .{
|
||||
.object = o,
|
||||
@ -1352,7 +1334,7 @@ pub const Object = struct {
|
||||
}
|
||||
|
||||
// TODO: disable this if safety is off for the function scope
|
||||
const ssp_buf_size = mod.comp.bin_file.options.stack_protector;
|
||||
const ssp_buf_size = owner_mod.stack_protector;
|
||||
if (ssp_buf_size != 0) {
|
||||
try attributes.addFnAttr(.sspstrong, &o.builder);
|
||||
try attributes.addFnAttr(.{ .string = .{
|
||||
@ -1362,7 +1344,7 @@ pub const Object = struct {
|
||||
}
|
||||
|
||||
// TODO: disable this if safety is off for the function scope
|
||||
if (mod.comp.bin_file.options.stack_check) {
|
||||
if (owner_mod.stack_check) {
|
||||
try attributes.addFnAttr(.{ .string = .{
|
||||
.kind = try o.builder.string("probe-stack"),
|
||||
.value = try o.builder.string("__zig_probe_stack"),
|
||||
@ -1385,20 +1367,22 @@ pub const Object = struct {
|
||||
var llvm_arg_i: u32 = 0;
|
||||
|
||||
// This gets the LLVM values from the function and stores them in `dg.args`.
|
||||
const sret = firstParamSRet(fn_info, mod);
|
||||
const sret = firstParamSRet(fn_info, zcu);
|
||||
const ret_ptr: Builder.Value = if (sret) param: {
|
||||
const param = wip.arg(llvm_arg_i);
|
||||
llvm_arg_i += 1;
|
||||
break :param param;
|
||||
} else .none;
|
||||
|
||||
if (ccAbiPromoteInt(fn_info.cc, mod, Type.fromInterned(fn_info.return_type))) |s| switch (s) {
|
||||
if (ccAbiPromoteInt(fn_info.cc, zcu, Type.fromInterned(fn_info.return_type))) |s| switch (s) {
|
||||
.signed => try attributes.addRetAttr(.signext, &o.builder),
|
||||
.unsigned => try attributes.addRetAttr(.zeroext, &o.builder),
|
||||
};
|
||||
|
||||
const err_return_tracing = Type.fromInterned(fn_info.return_type).isError(mod) and
|
||||
mod.comp.config.any_error_tracing;
|
||||
const comp = zcu.comp;
|
||||
|
||||
const err_return_tracing = Type.fromInterned(fn_info.return_type).isError(zcu) and
|
||||
comp.config.any_error_tracing;
|
||||
|
||||
const err_ret_trace: Builder.Value = if (err_return_tracing) param: {
|
||||
const param = wip.arg(llvm_arg_i);
|
||||
@ -1426,8 +1410,8 @@ pub const Object = struct {
|
||||
const param_ty = Type.fromInterned(fn_info.param_types.get(ip)[param_index]);
|
||||
const param = wip.arg(llvm_arg_i);
|
||||
|
||||
if (isByRef(param_ty, mod)) {
|
||||
const alignment = param_ty.abiAlignment(mod).toLlvm();
|
||||
if (isByRef(param_ty, zcu)) {
|
||||
const alignment = param_ty.abiAlignment(zcu).toLlvm();
|
||||
const param_llvm_ty = param.typeOfWip(&wip);
|
||||
const arg_ptr = try buildAllocaInner(&wip, false, param_llvm_ty, alignment, target);
|
||||
_ = try wip.store(.normal, param, arg_ptr, alignment);
|
||||
@ -1443,12 +1427,12 @@ pub const Object = struct {
|
||||
const param_ty = Type.fromInterned(fn_info.param_types.get(ip)[it.zig_index - 1]);
|
||||
const param_llvm_ty = try o.lowerType(param_ty);
|
||||
const param = wip.arg(llvm_arg_i);
|
||||
const alignment = param_ty.abiAlignment(mod).toLlvm();
|
||||
const alignment = param_ty.abiAlignment(zcu).toLlvm();
|
||||
|
||||
try o.addByRefParamAttrs(&attributes, llvm_arg_i, alignment, it.byval_attr, param_llvm_ty);
|
||||
llvm_arg_i += 1;
|
||||
|
||||
if (isByRef(param_ty, mod)) {
|
||||
if (isByRef(param_ty, zcu)) {
|
||||
args.appendAssumeCapacity(param);
|
||||
} else {
|
||||
args.appendAssumeCapacity(try wip.load(.normal, param_llvm_ty, param, alignment, ""));
|
||||
@ -1458,12 +1442,12 @@ pub const Object = struct {
|
||||
const param_ty = Type.fromInterned(fn_info.param_types.get(ip)[it.zig_index - 1]);
|
||||
const param_llvm_ty = try o.lowerType(param_ty);
|
||||
const param = wip.arg(llvm_arg_i);
|
||||
const alignment = param_ty.abiAlignment(mod).toLlvm();
|
||||
const alignment = param_ty.abiAlignment(zcu).toLlvm();
|
||||
|
||||
try attributes.addParamAttr(llvm_arg_i, .noundef, &o.builder);
|
||||
llvm_arg_i += 1;
|
||||
|
||||
if (isByRef(param_ty, mod)) {
|
||||
if (isByRef(param_ty, zcu)) {
|
||||
args.appendAssumeCapacity(param);
|
||||
} else {
|
||||
args.appendAssumeCapacity(try wip.load(.normal, param_llvm_ty, param, alignment, ""));
|
||||
@ -1476,11 +1460,11 @@ pub const Object = struct {
|
||||
llvm_arg_i += 1;
|
||||
|
||||
const param_llvm_ty = try o.lowerType(param_ty);
|
||||
const alignment = param_ty.abiAlignment(mod).toLlvm();
|
||||
const alignment = param_ty.abiAlignment(zcu).toLlvm();
|
||||
const arg_ptr = try buildAllocaInner(&wip, false, param_llvm_ty, alignment, target);
|
||||
_ = try wip.store(.normal, param, arg_ptr, alignment);
|
||||
|
||||
args.appendAssumeCapacity(if (isByRef(param_ty, mod))
|
||||
args.appendAssumeCapacity(if (isByRef(param_ty, zcu))
|
||||
arg_ptr
|
||||
else
|
||||
try wip.load(.normal, param_llvm_ty, arg_ptr, alignment, ""));
|
||||
@ -1488,14 +1472,14 @@ pub const Object = struct {
|
||||
.slice => {
|
||||
assert(!it.byval_attr);
|
||||
const param_ty = Type.fromInterned(fn_info.param_types.get(ip)[it.zig_index - 1]);
|
||||
const ptr_info = param_ty.ptrInfo(mod);
|
||||
const ptr_info = param_ty.ptrInfo(zcu);
|
||||
|
||||
if (math.cast(u5, it.zig_index - 1)) |i| {
|
||||
if (@as(u1, @truncate(fn_info.noalias_bits >> i)) != 0) {
|
||||
try attributes.addParamAttr(llvm_arg_i, .@"noalias", &o.builder);
|
||||
}
|
||||
}
|
||||
if (param_ty.zigTypeTag(mod) != .Optional) {
|
||||
if (param_ty.zigTypeTag(zcu) != .Optional) {
|
||||
try attributes.addParamAttr(llvm_arg_i, .nonnull, &o.builder);
|
||||
}
|
||||
if (ptr_info.flags.is_const) {
|
||||
@ -1504,7 +1488,7 @@ pub const Object = struct {
|
||||
const elem_align = (if (ptr_info.flags.alignment != .none)
|
||||
@as(InternPool.Alignment, ptr_info.flags.alignment)
|
||||
else
|
||||
Type.fromInterned(ptr_info.child).abiAlignment(mod).max(.@"1")).toLlvm();
|
||||
Type.fromInterned(ptr_info.child).abiAlignment(zcu).max(.@"1")).toLlvm();
|
||||
try attributes.addParamAttr(llvm_arg_i, .{ .@"align" = elem_align }, &o.builder);
|
||||
const ptr_param = wip.arg(llvm_arg_i);
|
||||
llvm_arg_i += 1;
|
||||
@ -1521,7 +1505,7 @@ pub const Object = struct {
|
||||
const field_types = it.types_buffer[0..it.types_len];
|
||||
const param_ty = Type.fromInterned(fn_info.param_types.get(ip)[it.zig_index - 1]);
|
||||
const param_llvm_ty = try o.lowerType(param_ty);
|
||||
const param_alignment = param_ty.abiAlignment(mod).toLlvm();
|
||||
const param_alignment = param_ty.abiAlignment(zcu).toLlvm();
|
||||
const arg_ptr = try buildAllocaInner(&wip, false, param_llvm_ty, param_alignment, target);
|
||||
const llvm_ty = try o.builder.structType(.normal, field_types);
|
||||
for (0..field_types.len) |field_i| {
|
||||
@ -1533,7 +1517,7 @@ pub const Object = struct {
|
||||
_ = try wip.store(.normal, param, field_ptr, alignment);
|
||||
}
|
||||
|
||||
const is_by_ref = isByRef(param_ty, mod);
|
||||
const is_by_ref = isByRef(param_ty, zcu);
|
||||
args.appendAssumeCapacity(if (is_by_ref)
|
||||
arg_ptr
|
||||
else
|
||||
@ -1551,11 +1535,11 @@ pub const Object = struct {
|
||||
const param = wip.arg(llvm_arg_i);
|
||||
llvm_arg_i += 1;
|
||||
|
||||
const alignment = param_ty.abiAlignment(mod).toLlvm();
|
||||
const alignment = param_ty.abiAlignment(zcu).toLlvm();
|
||||
const arg_ptr = try buildAllocaInner(&wip, false, param_llvm_ty, alignment, target);
|
||||
_ = try wip.store(.normal, param, arg_ptr, alignment);
|
||||
|
||||
args.appendAssumeCapacity(if (isByRef(param_ty, mod))
|
||||
args.appendAssumeCapacity(if (isByRef(param_ty, zcu))
|
||||
arg_ptr
|
||||
else
|
||||
try wip.load(.normal, param_llvm_ty, arg_ptr, alignment, ""));
|
||||
@ -1566,11 +1550,11 @@ pub const Object = struct {
|
||||
const param = wip.arg(llvm_arg_i);
|
||||
llvm_arg_i += 1;
|
||||
|
||||
const alignment = param_ty.abiAlignment(mod).toLlvm();
|
||||
const alignment = param_ty.abiAlignment(zcu).toLlvm();
|
||||
const arg_ptr = try buildAllocaInner(&wip, false, param_llvm_ty, alignment, target);
|
||||
_ = try wip.store(.normal, param, arg_ptr, alignment);
|
||||
|
||||
args.appendAssumeCapacity(if (isByRef(param_ty, mod))
|
||||
args.appendAssumeCapacity(if (isByRef(param_ty, zcu))
|
||||
arg_ptr
|
||||
else
|
||||
try wip.load(.normal, param_llvm_ty, arg_ptr, alignment, ""));
|
||||
@ -1584,14 +1568,12 @@ pub const Object = struct {
|
||||
var di_file: ?if (build_options.have_llvm) *llvm.DIFile else noreturn = null;
|
||||
var di_scope: ?if (build_options.have_llvm) *llvm.DIScope else noreturn = null;
|
||||
|
||||
const namespace = mod.namespacePtr(decl.src_namespace);
|
||||
|
||||
if (o.di_builder) |dib| {
|
||||
di_file = try o.getDIFile(gpa, namespace.file_scope);
|
||||
|
||||
const line_number = decl.src_line + 1;
|
||||
const is_internal_linkage = decl.val.getExternFunc(mod) == null and
|
||||
!mod.decl_exports.contains(decl_index);
|
||||
const is_internal_linkage = decl.val.getExternFunc(zcu) == null and
|
||||
!zcu.decl_exports.contains(decl_index);
|
||||
const noret_bit: c_uint = if (fn_info.return_type == .noreturn_type)
|
||||
llvm.DIFlags.NoReturn
|
||||
else
|
||||
@ -1608,7 +1590,7 @@ pub const Object = struct {
|
||||
true, // is definition
|
||||
line_number + func.lbrace_line, // scope line
|
||||
llvm.DIFlags.StaticMember | noret_bit,
|
||||
mod.comp.bin_file.options.optimize_mode != .Debug,
|
||||
owner_mod.optimize_mode != .Debug,
|
||||
null, // decl_subprogram
|
||||
);
|
||||
try o.di_map.put(gpa, decl, subprogram.toNode());
|
||||
@ -1618,8 +1600,6 @@ pub const Object = struct {
|
||||
di_scope = subprogram.toScope();
|
||||
}
|
||||
|
||||
const single_threaded = namespace.file_scope.mod.single_threaded;
|
||||
|
||||
var fg: FuncGen = .{
|
||||
.gpa = gpa,
|
||||
.air = air,
|
||||
@ -1631,7 +1611,7 @@ pub const Object = struct {
|
||||
.arg_index = 0,
|
||||
.func_inst_table = .{},
|
||||
.blocks = .{},
|
||||
.sync_scope = if (single_threaded) .singlethread else .system,
|
||||
.sync_scope = if (owner_mod.single_threaded) .singlethread else .system,
|
||||
.di_scope = di_scope,
|
||||
.di_file = di_file,
|
||||
.base_line = dg.decl.src_line,
|
||||
@ -1645,7 +1625,7 @@ pub const Object = struct {
|
||||
fg.genBody(air.getMainBody()) catch |err| switch (err) {
|
||||
error.CodegenFail => {
|
||||
decl.analysis = .codegen_failure;
|
||||
try mod.failed_decls.put(mod.gpa, decl_index, dg.err_msg.?);
|
||||
try zcu.failed_decls.put(zcu.gpa, decl_index, dg.err_msg.?);
|
||||
dg.err_msg = null;
|
||||
return;
|
||||
},
|
||||
@ -1654,7 +1634,7 @@ pub const Object = struct {
|
||||
|
||||
try fg.wip.finish();
|
||||
|
||||
try o.updateExports(mod, .{ .decl_index = decl_index }, mod.getDeclExports(decl_index));
|
||||
try o.updateExports(zcu, .{ .decl_index = decl_index }, zcu.getDeclExports(decl_index));
|
||||
}
|
||||
|
||||
pub fn updateDecl(self: *Object, module: *Module, decl_index: InternPool.DeclIndex) !void {
|
||||
@ -2933,22 +2913,24 @@ pub const Object = struct {
|
||||
o: *Object,
|
||||
decl_index: InternPool.DeclIndex,
|
||||
) Allocator.Error!Builder.Function.Index {
|
||||
const mod = o.module;
|
||||
const ip = &mod.intern_pool;
|
||||
const zcu = o.module;
|
||||
const ip = &zcu.intern_pool;
|
||||
const gpa = o.gpa;
|
||||
const decl = mod.declPtr(decl_index);
|
||||
const decl = zcu.declPtr(decl_index);
|
||||
const namespace = zcu.namespacePtr(decl.src_namespace);
|
||||
const owner_mod = namespace.file_scope.mod;
|
||||
const zig_fn_type = decl.ty;
|
||||
const gop = try o.decl_map.getOrPut(gpa, decl_index);
|
||||
if (gop.found_existing) return gop.value_ptr.ptr(&o.builder).kind.function;
|
||||
|
||||
assert(decl.has_tv);
|
||||
const fn_info = mod.typeToFunc(zig_fn_type).?;
|
||||
const target = mod.getTarget();
|
||||
const sret = firstParamSRet(fn_info, mod);
|
||||
const fn_info = zcu.typeToFunc(zig_fn_type).?;
|
||||
const target = owner_mod.resolved_target.result;
|
||||
const sret = firstParamSRet(fn_info, zcu);
|
||||
|
||||
const function_index = try o.builder.addFunction(
|
||||
try o.lowerType(zig_fn_type),
|
||||
try o.builder.string(ip.stringToSlice(try decl.getFullyQualifiedName(mod))),
|
||||
try o.builder.string(ip.stringToSlice(try decl.getFullyQualifiedName(zcu))),
|
||||
toLlvmAddressSpace(decl.@"addrspace", target),
|
||||
);
|
||||
gop.value_ptr.* = function_index.ptrConst(&o.builder).global;
|
||||
@ -2956,7 +2938,7 @@ pub const Object = struct {
|
||||
var attributes: Builder.FunctionAttributes.Wip = .{};
|
||||
defer attributes.deinit(&o.builder);
|
||||
|
||||
const is_extern = decl.isExtern(mod);
|
||||
const is_extern = decl.isExtern(zcu);
|
||||
if (!is_extern) {
|
||||
function_index.setLinkage(.internal, &o.builder);
|
||||
function_index.setUnnamedAddr(.unnamed_addr, &o.builder);
|
||||
@ -2966,7 +2948,7 @@ pub const Object = struct {
|
||||
.kind = try o.builder.string("wasm-import-name"),
|
||||
.value = try o.builder.string(ip.stringToSlice(decl.name)),
|
||||
} }, &o.builder);
|
||||
if (ip.stringToSliceUnwrap(decl.getOwnedExternFunc(mod).?.lib_name)) |lib_name| {
|
||||
if (ip.stringToSliceUnwrap(decl.getOwnedExternFunc(zcu).?.lib_name)) |lib_name| {
|
||||
if (!std.mem.eql(u8, lib_name, "c")) try attributes.addFnAttr(.{ .string = .{
|
||||
.kind = try o.builder.string("wasm-import-module"),
|
||||
.value = try o.builder.string(lib_name),
|
||||
@ -2987,8 +2969,8 @@ pub const Object = struct {
|
||||
llvm_arg_i += 1;
|
||||
}
|
||||
|
||||
const err_return_tracing = Type.fromInterned(fn_info.return_type).isError(mod) and
|
||||
mod.comp.config.any_error_tracing;
|
||||
const err_return_tracing = Type.fromInterned(fn_info.return_type).isError(zcu) and
|
||||
zcu.comp.config.any_error_tracing;
|
||||
|
||||
if (err_return_tracing) {
|
||||
try attributes.addParamAttr(llvm_arg_i, .nonnull, &o.builder);
|
||||
@ -3009,7 +2991,7 @@ pub const Object = struct {
|
||||
function_index.setAlignment(fn_info.alignment.toLlvm(), &o.builder);
|
||||
|
||||
// Function attributes that are independent of analysis results of the function body.
|
||||
try o.addCommonFnAttributes(&attributes);
|
||||
try o.addCommonFnAttributes(&attributes, owner_mod);
|
||||
|
||||
if (fn_info.return_type == .noreturn_type) try attributes.addFnAttr(.noreturn, &o.builder);
|
||||
|
||||
@ -3022,14 +3004,14 @@ pub const Object = struct {
|
||||
.byval => {
|
||||
const param_index = it.zig_index - 1;
|
||||
const param_ty = Type.fromInterned(fn_info.param_types.get(ip)[param_index]);
|
||||
if (!isByRef(param_ty, mod)) {
|
||||
if (!isByRef(param_ty, zcu)) {
|
||||
try o.addByValParamAttrs(&attributes, param_ty, param_index, fn_info, it.llvm_index - 1);
|
||||
}
|
||||
},
|
||||
.byref => {
|
||||
const param_ty = Type.fromInterned(fn_info.param_types.get(ip)[it.zig_index - 1]);
|
||||
const param_llvm_ty = try o.lowerType(param_ty);
|
||||
const alignment = param_ty.abiAlignment(mod);
|
||||
const alignment = param_ty.abiAlignment(zcu);
|
||||
try o.addByRefParamAttrs(&attributes, it.llvm_index - 1, alignment.toLlvm(), it.byval_attr, param_llvm_ty);
|
||||
},
|
||||
.byref_mut => try attributes.addParamAttr(it.llvm_index - 1, .noundef, &o.builder),
|
||||
@ -3055,13 +3037,14 @@ pub const Object = struct {
|
||||
fn addCommonFnAttributes(
|
||||
o: *Object,
|
||||
attributes: *Builder.FunctionAttributes.Wip,
|
||||
owner_mod: *Package.Module,
|
||||
) Allocator.Error!void {
|
||||
const comp = o.module.comp;
|
||||
|
||||
if (!comp.bin_file.options.red_zone) {
|
||||
if (!owner_mod.red_zone) {
|
||||
try attributes.addFnAttr(.noredzone, &o.builder);
|
||||
}
|
||||
if (comp.bin_file.options.omit_frame_pointer) {
|
||||
if (owner_mod.omit_frame_pointer) {
|
||||
try attributes.addFnAttr(.{ .string = .{
|
||||
.kind = try o.builder.string("frame-pointer"),
|
||||
.value = try o.builder.string("none"),
|
||||
@ -3073,7 +3056,7 @@ pub const Object = struct {
|
||||
} }, &o.builder);
|
||||
}
|
||||
try attributes.addFnAttr(.nounwind, &o.builder);
|
||||
if (comp.unwind_tables) {
|
||||
if (owner_mod.unwind_tables) {
|
||||
try attributes.addFnAttr(.{ .uwtable = Builder.Attribute.UwTable.default }, &o.builder);
|
||||
}
|
||||
if (comp.skip_linker_dependencies or comp.no_builtin) {
|
||||
@ -3084,26 +3067,27 @@ pub const Object = struct {
|
||||
// overflow instead of performing memcpy.
|
||||
try attributes.addFnAttr(.nobuiltin, &o.builder);
|
||||
}
|
||||
if (comp.bin_file.options.optimize_mode == .ReleaseSmall) {
|
||||
if (owner_mod.optimize_mode == .ReleaseSmall) {
|
||||
try attributes.addFnAttr(.minsize, &o.builder);
|
||||
try attributes.addFnAttr(.optsize, &o.builder);
|
||||
}
|
||||
if (comp.bin_file.options.tsan) {
|
||||
if (owner_mod.sanitize_thread) {
|
||||
try attributes.addFnAttr(.sanitize_thread, &o.builder);
|
||||
}
|
||||
if (comp.getTarget().cpu.model.llvm_name) |s| {
|
||||
const target = owner_mod.resolved_target.result;
|
||||
if (target.cpu.model.llvm_name) |s| {
|
||||
try attributes.addFnAttr(.{ .string = .{
|
||||
.kind = try o.builder.string("target-cpu"),
|
||||
.value = try o.builder.string(s),
|
||||
} }, &o.builder);
|
||||
}
|
||||
if (comp.bin_file.options.llvm_cpu_features) |s| {
|
||||
if (owner_mod.resolved_target.llvm_cpu_features) |s| {
|
||||
try attributes.addFnAttr(.{ .string = .{
|
||||
.kind = try o.builder.string("target-features"),
|
||||
.value = try o.builder.string(std.mem.span(s)),
|
||||
} }, &o.builder);
|
||||
}
|
||||
if (comp.getTarget().cpu.arch.isBpf()) {
|
||||
if (target.cpu.arch.isBpf()) {
|
||||
try attributes.addFnAttr(.{ .string = .{
|
||||
.kind = try o.builder.string("no-builtins"),
|
||||
.value = .empty,
|
||||
@ -4646,6 +4630,100 @@ pub const Object = struct {
|
||||
.field_index = @intCast(field_index),
|
||||
});
|
||||
}
|
||||
|
||||
fn getCmpLtErrorsLenFunction(o: *Object) !Builder.Function.Index {
|
||||
const name = try o.builder.string(lt_errors_fn_name);
|
||||
if (o.builder.getGlobal(name)) |llvm_fn| return llvm_fn.ptrConst(&o.builder).kind.function;
|
||||
|
||||
const zcu = o.module;
|
||||
const target = zcu.root_mod.resolved_target.result;
|
||||
const function_index = try o.builder.addFunction(
|
||||
try o.builder.fnType(.i1, &.{try o.errorIntType()}, .normal),
|
||||
name,
|
||||
toLlvmAddressSpace(.generic, target),
|
||||
);
|
||||
|
||||
var attributes: Builder.FunctionAttributes.Wip = .{};
|
||||
defer attributes.deinit(&o.builder);
|
||||
try o.addCommonFnAttributes(&attributes, zcu.root_mod);
|
||||
|
||||
function_index.setLinkage(.internal, &o.builder);
|
||||
function_index.setCallConv(.fastcc, &o.builder);
|
||||
function_index.setAttributes(try attributes.finish(&o.builder), &o.builder);
|
||||
return function_index;
|
||||
}
|
||||
|
||||
fn getEnumTagNameFunction(o: *Object, enum_ty: Type) !Builder.Function.Index {
|
||||
const zcu = o.module;
|
||||
const ip = &zcu.intern_pool;
|
||||
const enum_type = ip.indexToKey(enum_ty.toIntern()).enum_type;
|
||||
|
||||
// TODO: detect when the type changes and re-emit this function.
|
||||
const gop = try o.decl_map.getOrPut(o.gpa, enum_type.decl);
|
||||
if (gop.found_existing) return gop.value_ptr.ptrConst(&o.builder).kind.function;
|
||||
errdefer assert(o.decl_map.remove(enum_type.decl));
|
||||
|
||||
const usize_ty = try o.lowerType(Type.usize);
|
||||
const ret_ty = try o.lowerType(Type.slice_const_u8_sentinel_0);
|
||||
const fqn = try zcu.declPtr(enum_type.decl).getFullyQualifiedName(zcu);
|
||||
const target = zcu.root_mod.resolved_target.result;
|
||||
const function_index = try o.builder.addFunction(
|
||||
try o.builder.fnType(ret_ty, &.{try o.lowerType(Type.fromInterned(enum_type.tag_ty))}, .normal),
|
||||
try o.builder.fmt("__zig_tag_name_{}", .{fqn.fmt(ip)}),
|
||||
toLlvmAddressSpace(.generic, target),
|
||||
);
|
||||
|
||||
var attributes: Builder.FunctionAttributes.Wip = .{};
|
||||
defer attributes.deinit(&o.builder);
|
||||
try o.addCommonFnAttributes(&attributes, zcu.root_mod);
|
||||
|
||||
function_index.setLinkage(.internal, &o.builder);
|
||||
function_index.setCallConv(.fastcc, &o.builder);
|
||||
function_index.setAttributes(try attributes.finish(&o.builder), &o.builder);
|
||||
gop.value_ptr.* = function_index.ptrConst(&o.builder).global;
|
||||
|
||||
var wip = try Builder.WipFunction.init(&o.builder, function_index);
|
||||
defer wip.deinit();
|
||||
wip.cursor = .{ .block = try wip.block(0, "Entry") };
|
||||
|
||||
const bad_value_block = try wip.block(1, "BadValue");
|
||||
const tag_int_value = wip.arg(0);
|
||||
var wip_switch =
|
||||
try wip.@"switch"(tag_int_value, bad_value_block, @intCast(enum_type.names.len));
|
||||
defer wip_switch.finish(&wip);
|
||||
|
||||
for (0..enum_type.names.len) |field_index| {
|
||||
const name = try o.builder.string(ip.stringToSlice(enum_type.names.get(ip)[field_index]));
|
||||
const name_init = try o.builder.stringNullConst(name);
|
||||
const name_variable_index =
|
||||
try o.builder.addVariable(.empty, name_init.typeOf(&o.builder), .default);
|
||||
try name_variable_index.setInitializer(name_init, &o.builder);
|
||||
name_variable_index.setLinkage(.private, &o.builder);
|
||||
name_variable_index.setMutability(.constant, &o.builder);
|
||||
name_variable_index.setUnnamedAddr(.unnamed_addr, &o.builder);
|
||||
name_variable_index.setAlignment(comptime Builder.Alignment.fromByteUnits(1), &o.builder);
|
||||
|
||||
const name_val = try o.builder.structValue(ret_ty, &.{
|
||||
name_variable_index.toConst(&o.builder),
|
||||
try o.builder.intConst(usize_ty, name.slice(&o.builder).?.len),
|
||||
});
|
||||
|
||||
const return_block = try wip.block(1, "Name");
|
||||
const this_tag_int_value = try o.lowerValue(
|
||||
(try zcu.enumValueFieldIndex(enum_ty, @intCast(field_index))).toIntern(),
|
||||
);
|
||||
try wip_switch.addCase(this_tag_int_value, return_block, &wip);
|
||||
|
||||
wip.cursor = .{ .block = return_block };
|
||||
_ = try wip.ret(name_val);
|
||||
}
|
||||
|
||||
wip.cursor = .{ .block = bad_value_block };
|
||||
_ = try wip.@"unreachable"();
|
||||
|
||||
try wip.finish();
|
||||
return function_index;
|
||||
}
|
||||
};
|
||||
|
||||
pub const DeclGen = struct {
|
||||
@ -4654,6 +4732,13 @@ pub const DeclGen = struct {
|
||||
decl_index: InternPool.DeclIndex,
|
||||
err_msg: ?*Module.ErrorMsg,
|
||||
|
||||
fn ownerModule(dg: DeclGen) *Package.Module {
|
||||
const o = dg.object;
|
||||
const zcu = o.module;
|
||||
const namespace = zcu.namespacePtr(dg.decl.src_namespace);
|
||||
return namespace.file_scope.mod;
|
||||
}
|
||||
|
||||
fn todo(dg: *DeclGen, comptime format: []const u8, args: anytype) Error {
|
||||
@setCold(true);
|
||||
assert(dg.err_msg == null);
|
||||
@ -5614,7 +5699,7 @@ pub const FuncGen = struct {
|
||||
const o = self.dg.object;
|
||||
const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
|
||||
const operand = try self.resolveInst(un_op);
|
||||
const llvm_fn = try self.getCmpLtErrorsLenFunction();
|
||||
const llvm_fn = try o.getCmpLtErrorsLenFunction();
|
||||
return self.wip.call(
|
||||
.normal,
|
||||
.fastcc,
|
||||
@ -6547,11 +6632,13 @@ pub const FuncGen = struct {
|
||||
const dib = o.di_builder orelse return .none;
|
||||
const ty_fn = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_fn;
|
||||
|
||||
const mod = o.module;
|
||||
const func = mod.funcInfo(ty_fn.func);
|
||||
const zcu = o.module;
|
||||
const func = zcu.funcInfo(ty_fn.func);
|
||||
const decl_index = func.owner_decl;
|
||||
const decl = mod.declPtr(decl_index);
|
||||
const di_file = try o.getDIFile(self.gpa, mod.namespacePtr(decl.src_namespace).file_scope);
|
||||
const decl = zcu.declPtr(decl_index);
|
||||
const namespace = zcu.namespacePtr(decl.src_namespace);
|
||||
const owner_mod = namespace.file_scope.mod;
|
||||
const di_file = try o.getDIFile(self.gpa, zcu.namespacePtr(decl.src_namespace).file_scope);
|
||||
self.di_file = di_file;
|
||||
const line_number = decl.src_line + 1;
|
||||
const cur_debug_location = self.wip.llvm.builder.getCurrentDebugLocation2();
|
||||
@ -6562,18 +6649,18 @@ pub const FuncGen = struct {
|
||||
.base_line = self.base_line,
|
||||
});
|
||||
|
||||
const fqn = try decl.getFullyQualifiedName(mod);
|
||||
const fqn = try decl.getFullyQualifiedName(zcu);
|
||||
|
||||
const is_internal_linkage = !mod.decl_exports.contains(decl_index);
|
||||
const fn_ty = try mod.funcType(.{
|
||||
const is_internal_linkage = !zcu.decl_exports.contains(decl_index);
|
||||
const fn_ty = try zcu.funcType(.{
|
||||
.param_types = &.{},
|
||||
.return_type = .void_type,
|
||||
});
|
||||
const fn_di_ty = try o.lowerDebugType(fn_ty, .full);
|
||||
const subprogram = dib.createFunction(
|
||||
di_file.toScope(),
|
||||
mod.intern_pool.stringToSlice(decl.name),
|
||||
mod.intern_pool.stringToSlice(fqn),
|
||||
zcu.intern_pool.stringToSlice(decl.name),
|
||||
zcu.intern_pool.stringToSlice(fqn),
|
||||
di_file,
|
||||
line_number,
|
||||
fn_di_ty,
|
||||
@ -6581,7 +6668,7 @@ pub const FuncGen = struct {
|
||||
true, // is definition
|
||||
line_number + func.lbrace_line, // scope line
|
||||
llvm.DIFlags.StaticMember,
|
||||
mod.comp.bin_file.options.optimize_mode != .Debug,
|
||||
owner_mod.optimize_mode != .Debug,
|
||||
null, // decl_subprogram
|
||||
);
|
||||
|
||||
@ -6676,11 +6763,12 @@ pub const FuncGen = struct {
|
||||
null;
|
||||
const debug_loc = llvm.getDebugLoc(self.prev_dbg_line, self.prev_dbg_column, self.di_scope.?, inlined_at);
|
||||
const insert_block = self.wip.cursor.block.toLlvm(&self.wip);
|
||||
const mod = o.module;
|
||||
if (isByRef(operand_ty, mod)) {
|
||||
const zcu = o.module;
|
||||
const owner_mod = self.dg.ownerModule();
|
||||
if (isByRef(operand_ty, zcu)) {
|
||||
_ = dib.insertDeclareAtEnd(operand.toLlvm(&self.wip), di_local_var, debug_loc, insert_block);
|
||||
} else if (o.module.comp.bin_file.options.optimize_mode == .Debug) {
|
||||
const alignment = operand_ty.abiAlignment(mod).toLlvm();
|
||||
} else if (owner_mod.optimize_mode == .Debug) {
|
||||
const alignment = operand_ty.abiAlignment(zcu).toLlvm();
|
||||
const alloca = try self.buildAlloca(operand.typeOfWip(&self.wip), alignment);
|
||||
_ = try self.wip.store(.normal, operand, alloca, alignment);
|
||||
_ = dib.insertDeclareAtEnd(alloca.toLlvm(&self.wip), di_local_var, debug_loc, insert_block);
|
||||
@ -8729,9 +8817,10 @@ pub const FuncGen = struct {
|
||||
|
||||
const debug_loc = llvm.getDebugLoc(lbrace_line, lbrace_col, self.di_scope.?, null);
|
||||
const insert_block = self.wip.cursor.block.toLlvm(&self.wip);
|
||||
const owner_mod = self.dg.ownerModule();
|
||||
if (isByRef(inst_ty, mod)) {
|
||||
_ = dib.insertDeclareAtEnd(arg_val.toLlvm(&self.wip), di_local_var, debug_loc, insert_block);
|
||||
} else if (o.module.comp.bin_file.options.optimize_mode == .Debug) {
|
||||
} else if (owner_mod.optimize_mode == .Debug) {
|
||||
const alignment = inst_ty.abiAlignment(mod).toLlvm();
|
||||
const alloca = try self.buildAlloca(arg_val.typeOfWip(&self.wip), alignment);
|
||||
_ = try self.wip.store(.normal, arg_val, alloca, alignment);
|
||||
@ -8821,7 +8910,8 @@ pub const FuncGen = struct {
|
||||
len,
|
||||
if (ptr_ty.isVolatilePtr(mod)) .@"volatile" else .normal,
|
||||
);
|
||||
if (safety and mod.comp.bin_file.options.valgrind) {
|
||||
const owner_mod = self.dg.ownerModule();
|
||||
if (safety and owner_mod.valgrind) {
|
||||
try self.valgrindMarkUndef(dest_ptr, len);
|
||||
}
|
||||
return .none;
|
||||
@ -9137,7 +9227,8 @@ pub const FuncGen = struct {
|
||||
} else {
|
||||
_ = try self.wip.callMemSet(dest_ptr, dest_ptr_align, fill_byte, len, access_kind);
|
||||
}
|
||||
if (safety and mod.comp.bin_file.options.valgrind) {
|
||||
const owner_mod = self.dg.ownerModule();
|
||||
if (safety and owner_mod.valgrind) {
|
||||
try self.valgrindMarkUndef(dest_ptr, len);
|
||||
}
|
||||
return .none;
|
||||
@ -9488,24 +9579,25 @@ pub const FuncGen = struct {
|
||||
|
||||
fn getIsNamedEnumValueFunction(self: *FuncGen, enum_ty: Type) !Builder.Function.Index {
|
||||
const o = self.dg.object;
|
||||
const mod = o.module;
|
||||
const enum_type = mod.intern_pool.indexToKey(enum_ty.toIntern()).enum_type;
|
||||
const zcu = o.module;
|
||||
const enum_type = zcu.intern_pool.indexToKey(enum_ty.toIntern()).enum_type;
|
||||
|
||||
// TODO: detect when the type changes and re-emit this function.
|
||||
const gop = try o.named_enum_map.getOrPut(o.gpa, enum_type.decl);
|
||||
if (gop.found_existing) return gop.value_ptr.*;
|
||||
errdefer assert(o.named_enum_map.remove(enum_type.decl));
|
||||
|
||||
const fqn = try mod.declPtr(enum_type.decl).getFullyQualifiedName(mod);
|
||||
const fqn = try zcu.declPtr(enum_type.decl).getFullyQualifiedName(zcu);
|
||||
const target = zcu.root_mod.resolved_target.result;
|
||||
const function_index = try o.builder.addFunction(
|
||||
try o.builder.fnType(.i1, &.{try o.lowerType(Type.fromInterned(enum_type.tag_ty))}, .normal),
|
||||
try o.builder.fmt("__zig_is_named_enum_value_{}", .{fqn.fmt(&mod.intern_pool)}),
|
||||
toLlvmAddressSpace(.generic, mod.getTarget()),
|
||||
try o.builder.fmt("__zig_is_named_enum_value_{}", .{fqn.fmt(&zcu.intern_pool)}),
|
||||
toLlvmAddressSpace(.generic, target),
|
||||
);
|
||||
|
||||
var attributes: Builder.FunctionAttributes.Wip = .{};
|
||||
defer attributes.deinit(&o.builder);
|
||||
try o.addCommonFnAttributes(&attributes);
|
||||
try o.addCommonFnAttributes(&attributes, zcu.root_mod);
|
||||
|
||||
function_index.setLinkage(.internal, &o.builder);
|
||||
function_index.setCallConv(.fastcc, &o.builder);
|
||||
@ -9524,7 +9616,7 @@ pub const FuncGen = struct {
|
||||
|
||||
for (0..enum_type.names.len) |field_index| {
|
||||
const this_tag_int_value = try o.lowerValue(
|
||||
(try mod.enumValueFieldIndex(enum_ty, @intCast(field_index))).toIntern(),
|
||||
(try zcu.enumValueFieldIndex(enum_ty, @intCast(field_index))).toIntern(),
|
||||
);
|
||||
try wip_switch.addCase(this_tag_int_value, named_block, &wip);
|
||||
}
|
||||
@ -9544,7 +9636,7 @@ pub const FuncGen = struct {
|
||||
const operand = try self.resolveInst(un_op);
|
||||
const enum_ty = self.typeOf(un_op);
|
||||
|
||||
const llvm_fn = try self.getEnumTagNameFunction(enum_ty);
|
||||
const llvm_fn = try o.getEnumTagNameFunction(enum_ty);
|
||||
return self.wip.call(
|
||||
.normal,
|
||||
.fastcc,
|
||||
@ -9556,100 +9648,6 @@ pub const FuncGen = struct {
|
||||
);
|
||||
}
|
||||
|
||||
fn getEnumTagNameFunction(self: *FuncGen, enum_ty: Type) !Builder.Function.Index {
|
||||
const o = self.dg.object;
|
||||
const mod = o.module;
|
||||
const ip = &mod.intern_pool;
|
||||
const enum_type = ip.indexToKey(enum_ty.toIntern()).enum_type;
|
||||
|
||||
// TODO: detect when the type changes and re-emit this function.
|
||||
const gop = try o.decl_map.getOrPut(o.gpa, enum_type.decl);
|
||||
if (gop.found_existing) return gop.value_ptr.ptrConst(&o.builder).kind.function;
|
||||
errdefer assert(o.decl_map.remove(enum_type.decl));
|
||||
|
||||
const usize_ty = try o.lowerType(Type.usize);
|
||||
const ret_ty = try o.lowerType(Type.slice_const_u8_sentinel_0);
|
||||
const fqn = try mod.declPtr(enum_type.decl).getFullyQualifiedName(mod);
|
||||
const function_index = try o.builder.addFunction(
|
||||
try o.builder.fnType(ret_ty, &.{try o.lowerType(Type.fromInterned(enum_type.tag_ty))}, .normal),
|
||||
try o.builder.fmt("__zig_tag_name_{}", .{fqn.fmt(ip)}),
|
||||
toLlvmAddressSpace(.generic, mod.getTarget()),
|
||||
);
|
||||
|
||||
var attributes: Builder.FunctionAttributes.Wip = .{};
|
||||
defer attributes.deinit(&o.builder);
|
||||
try o.addCommonFnAttributes(&attributes);
|
||||
|
||||
function_index.setLinkage(.internal, &o.builder);
|
||||
function_index.setCallConv(.fastcc, &o.builder);
|
||||
function_index.setAttributes(try attributes.finish(&o.builder), &o.builder);
|
||||
gop.value_ptr.* = function_index.ptrConst(&o.builder).global;
|
||||
|
||||
var wip = try Builder.WipFunction.init(&o.builder, function_index);
|
||||
defer wip.deinit();
|
||||
wip.cursor = .{ .block = try wip.block(0, "Entry") };
|
||||
|
||||
const bad_value_block = try wip.block(1, "BadValue");
|
||||
const tag_int_value = wip.arg(0);
|
||||
var wip_switch =
|
||||
try wip.@"switch"(tag_int_value, bad_value_block, @intCast(enum_type.names.len));
|
||||
defer wip_switch.finish(&wip);
|
||||
|
||||
for (0..enum_type.names.len) |field_index| {
|
||||
const name = try o.builder.string(ip.stringToSlice(enum_type.names.get(ip)[field_index]));
|
||||
const name_init = try o.builder.stringNullConst(name);
|
||||
const name_variable_index =
|
||||
try o.builder.addVariable(.empty, name_init.typeOf(&o.builder), .default);
|
||||
try name_variable_index.setInitializer(name_init, &o.builder);
|
||||
name_variable_index.setLinkage(.private, &o.builder);
|
||||
name_variable_index.setMutability(.constant, &o.builder);
|
||||
name_variable_index.setUnnamedAddr(.unnamed_addr, &o.builder);
|
||||
name_variable_index.setAlignment(comptime Builder.Alignment.fromByteUnits(1), &o.builder);
|
||||
|
||||
const name_val = try o.builder.structValue(ret_ty, &.{
|
||||
name_variable_index.toConst(&o.builder),
|
||||
try o.builder.intConst(usize_ty, name.slice(&o.builder).?.len),
|
||||
});
|
||||
|
||||
const return_block = try wip.block(1, "Name");
|
||||
const this_tag_int_value = try o.lowerValue(
|
||||
(try mod.enumValueFieldIndex(enum_ty, @intCast(field_index))).toIntern(),
|
||||
);
|
||||
try wip_switch.addCase(this_tag_int_value, return_block, &wip);
|
||||
|
||||
wip.cursor = .{ .block = return_block };
|
||||
_ = try wip.ret(name_val);
|
||||
}
|
||||
|
||||
wip.cursor = .{ .block = bad_value_block };
|
||||
_ = try wip.@"unreachable"();
|
||||
|
||||
try wip.finish();
|
||||
return function_index;
|
||||
}
|
||||
|
||||
fn getCmpLtErrorsLenFunction(self: *FuncGen) !Builder.Function.Index {
|
||||
const o = self.dg.object;
|
||||
|
||||
const name = try o.builder.string(lt_errors_fn_name);
|
||||
if (o.builder.getGlobal(name)) |llvm_fn| return llvm_fn.ptrConst(&o.builder).kind.function;
|
||||
|
||||
const function_index = try o.builder.addFunction(
|
||||
try o.builder.fnType(.i1, &.{try o.errorIntType()}, .normal),
|
||||
name,
|
||||
toLlvmAddressSpace(.generic, o.module.getTarget()),
|
||||
);
|
||||
|
||||
var attributes: Builder.FunctionAttributes.Wip = .{};
|
||||
defer attributes.deinit(&o.builder);
|
||||
try o.addCommonFnAttributes(&attributes);
|
||||
|
||||
function_index.setLinkage(.internal, &o.builder);
|
||||
function_index.setCallConv(.fastcc, &o.builder);
|
||||
function_index.setAttributes(try attributes.finish(&o.builder), &o.builder);
|
||||
return function_index;
|
||||
}
|
||||
|
||||
fn airErrorName(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
|
||||
const o = self.dg.object;
|
||||
const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
|
||||
|
||||
46
src/link.zig
46
src/link.zig
@ -18,6 +18,7 @@ const Module = @import("Module.zig");
|
||||
const InternPool = @import("InternPool.zig");
|
||||
const Type = @import("type.zig").Type;
|
||||
const TypedValue = @import("TypedValue.zig");
|
||||
const LlvmObject = @import("codegen/llvm.zig").Object;
|
||||
|
||||
/// When adding a new field, remember to update `hashAddSystemLibs`.
|
||||
/// These are *always* dynamically linked. Static libraries will be
|
||||
@ -1046,6 +1047,51 @@ pub const File = struct {
|
||||
return output_mode == .Lib and !self.isStatic();
|
||||
}
|
||||
|
||||
pub fn resolveEmitLoc(
|
||||
base: File,
|
||||
arena: Allocator,
|
||||
opt_loc: ?Compilation.EmitLoc,
|
||||
) Allocator.Error!?[*:0]u8 {
|
||||
const loc = opt_loc orelse return null;
|
||||
const slice = if (loc.directory) |directory|
|
||||
try directory.joinZ(arena, &.{loc.basename})
|
||||
else
|
||||
try base.emit.basenamePath(arena, loc.basename);
|
||||
return slice.ptr;
|
||||
}
|
||||
|
||||
pub fn emitLlvmObject(
|
||||
base: File,
|
||||
arena: Allocator,
|
||||
llvm_object: *LlvmObject,
|
||||
prog_node: *std.Progress.Node,
|
||||
) !void {
|
||||
const comp = base.comp;
|
||||
|
||||
var sub_prog_node = prog_node.start("LLVM Emit Object", 0);
|
||||
sub_prog_node.activate();
|
||||
sub_prog_node.context.refresh();
|
||||
defer sub_prog_node.end();
|
||||
|
||||
try llvm_object.emit(comp, .{
|
||||
.pre_ir_path = comp.verbose_llvm_ir,
|
||||
.pre_bc_path = comp.verbose_llvm_bc,
|
||||
.bin_path = try base.resolveEmitLoc(arena, .{
|
||||
.directory = null,
|
||||
.basename = base.intermediary_basename.?,
|
||||
}),
|
||||
.asm_path = try base.resolveEmitLoc(arena, comp.emit_asm),
|
||||
.post_llvm_ir_path = try base.resolveEmitLoc(arena, comp.emit_llvm_ir),
|
||||
.post_llvm_bc_path = try base.resolveEmitLoc(arena, comp.emit_llvm_bc),
|
||||
|
||||
.is_debug = comp.root_mod.optimize_mode == .Debug,
|
||||
.is_small = comp.root_mod.optimize_mode == .ReleaseSmall,
|
||||
.time_report = comp.time_report,
|
||||
.sanitize_thread = comp.config.any_sanitize_thread,
|
||||
.lto = comp.config.lto,
|
||||
});
|
||||
}
|
||||
|
||||
pub const C = @import("link/C.zig");
|
||||
pub const Coff = @import("link/Coff.zig");
|
||||
pub const Plan9 = @import("link/Plan9.zig");
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
//! LLD for traditional linking (linking relocatable object files).
|
||||
//! LLD is also the default linker for LLVM.
|
||||
|
||||
/// If this is not null, an object file is created by LLVM and linked with LLD afterwards.
|
||||
/// If this is not null, an object file is created by LLVM and emitted to intermediary_basename.
|
||||
llvm_object: ?*LlvmObject = null,
|
||||
|
||||
base: link.File,
|
||||
@ -1711,17 +1711,22 @@ pub fn flushModule(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod
|
||||
const tracy = trace(@src());
|
||||
defer tracy.end();
|
||||
|
||||
const gpa = comp.gpa;
|
||||
|
||||
if (self.llvm_object) |llvm_object| {
|
||||
return try llvm_object.flushModule(comp, prog_node);
|
||||
var arena_allocator = std.heap.ArenaAllocator.init(gpa);
|
||||
defer arena_allocator.deinit();
|
||||
const arena = arena_allocator.allocator();
|
||||
|
||||
try self.base.emitLlvmObject(arena, llvm_object, prog_node);
|
||||
return;
|
||||
}
|
||||
|
||||
var sub_prog_node = prog_node.start("COFF Flush", 0);
|
||||
sub_prog_node.activate();
|
||||
defer sub_prog_node.end();
|
||||
|
||||
const gpa = self.base.comp.gpa;
|
||||
|
||||
const module = self.base.comp.module orelse return error.LinkingWithoutZigSourceUnimplemented;
|
||||
const module = comp.module orelse return error.LinkingWithoutZigSourceUnimplemented;
|
||||
|
||||
if (self.lazy_syms.getPtr(.none)) |metadata| {
|
||||
// Most lazy symbols can be updated on first use, but
|
||||
@ -1822,7 +1827,7 @@ pub fn flushModule(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod
|
||||
try self.writeDataDirectoriesHeaders();
|
||||
try self.writeSectionHeaders();
|
||||
|
||||
if (self.entry_addr == null and self.base.comp.config.output_mode == .Exe) {
|
||||
if (self.entry_addr == null and comp.config.output_mode == .Exe) {
|
||||
log.debug("flushing. no_entry_point_found = true\n", .{});
|
||||
self.base.error_flags.no_entry_point_found = true;
|
||||
} else {
|
||||
|
||||
@ -27,7 +27,7 @@ version_script: ?[]const u8,
|
||||
|
||||
ptr_width: PtrWidth,
|
||||
|
||||
/// If this is not null, an object file is created by LLVM and linked with LLD afterwards.
|
||||
/// If this is not null, an object file is created by LLVM and emitted to intermediary_basename.
|
||||
llvm_object: ?*LlvmObject = null,
|
||||
|
||||
/// A list of all input files.
|
||||
@ -1031,24 +1031,23 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
|
||||
const tracy = trace(@src());
|
||||
defer tracy.end();
|
||||
|
||||
if (self.llvm_object) |llvm_object| {
|
||||
try llvm_object.flushModule(comp, prog_node);
|
||||
|
||||
const use_lld = build_options.have_llvm and self.base.comp.config.use_lld;
|
||||
if (use_lld) return;
|
||||
}
|
||||
|
||||
const gpa = self.base.comp.gpa;
|
||||
var sub_prog_node = prog_node.start("ELF Flush", 0);
|
||||
sub_prog_node.activate();
|
||||
defer sub_prog_node.end();
|
||||
|
||||
const gpa = comp.gpa;
|
||||
var arena_allocator = std.heap.ArenaAllocator.init(gpa);
|
||||
defer arena_allocator.deinit();
|
||||
const arena = arena_allocator.allocator();
|
||||
|
||||
const target = self.base.comp.root_mod.resolved_target.result;
|
||||
const link_mode = self.base.comp.config.link_mode;
|
||||
if (self.llvm_object) |llvm_object| {
|
||||
try self.base.emitLlvmObject(arena, llvm_object, prog_node);
|
||||
const use_lld = build_options.have_llvm and comp.config.use_lld;
|
||||
if (use_lld) return;
|
||||
}
|
||||
|
||||
var sub_prog_node = prog_node.start("ELF Flush", 0);
|
||||
sub_prog_node.activate();
|
||||
defer sub_prog_node.end();
|
||||
|
||||
const target = comp.root_mod.resolved_target.result;
|
||||
const link_mode = comp.config.link_mode;
|
||||
const directory = self.base.emit.directory; // Just an alias to make it shorter to type.
|
||||
const full_out_path = try directory.join(arena, &[_][]const u8{self.base.emit.sub_path});
|
||||
const module_obj_path: ?[]const u8 = if (self.base.intermediary_basename) |path| blk: {
|
||||
@ -1060,7 +1059,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
|
||||
} else null;
|
||||
|
||||
// --verbose-link
|
||||
if (self.base.comp.verbose_link) try self.dumpArgv(comp);
|
||||
if (comp.verbose_link) try self.dumpArgv(comp);
|
||||
|
||||
const csu = try CsuObjects.init(arena, comp);
|
||||
const compiler_rt_path: ?[]const u8 = blk: {
|
||||
@ -1082,8 +1081,8 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
|
||||
if (csu.crti) |v| try positionals.append(.{ .path = v });
|
||||
if (csu.crtbegin) |v| try positionals.append(.{ .path = v });
|
||||
|
||||
try positionals.ensureUnusedCapacity(self.base.comp.objects.len);
|
||||
positionals.appendSliceAssumeCapacity(self.base.comp.objects);
|
||||
try positionals.ensureUnusedCapacity(comp.objects.len);
|
||||
positionals.appendSliceAssumeCapacity(comp.objects);
|
||||
|
||||
// This is a set of object files emitted by clang in a single `build-exe` invocation.
|
||||
// For instance, the implicit `a.o` as compiled by `zig build-exe a.c` will end up
|
||||
@ -1106,13 +1105,13 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
|
||||
var test_path = std.ArrayList(u8).init(gpa);
|
||||
defer test_path.deinit();
|
||||
for (self.lib_dirs) |lib_dir_path| {
|
||||
for (self.base.comp.system_libs.keys()) |link_lib| {
|
||||
for (comp.system_libs.keys()) |link_lib| {
|
||||
if (!(try self.accessLibPath(&test_path, null, lib_dir_path, link_lib, .Dynamic)))
|
||||
continue;
|
||||
_ = try rpath_table.put(lib_dir_path, {});
|
||||
}
|
||||
}
|
||||
for (self.base.comp.objects) |obj| {
|
||||
for (comp.objects) |obj| {
|
||||
if (Compilation.classifyFileExt(obj.path) == .shared_library) {
|
||||
const lib_dir_path = std.fs.path.dirname(obj.path) orelse continue;
|
||||
if (obj.loption) continue;
|
||||
@ -1122,7 +1121,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
|
||||
}
|
||||
|
||||
// TSAN
|
||||
if (self.base.comp.config.any_sanitize_thread) {
|
||||
if (comp.config.any_sanitize_thread) {
|
||||
try positionals.append(.{ .path = comp.tsan_static_lib.?.full_object_path });
|
||||
}
|
||||
|
||||
@ -1146,27 +1145,27 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
|
||||
|
||||
var system_libs = std.ArrayList(SystemLib).init(arena);
|
||||
|
||||
try system_libs.ensureUnusedCapacity(self.base.comp.system_libs.values().len);
|
||||
for (self.base.comp.system_libs.values()) |lib_info| {
|
||||
try system_libs.ensureUnusedCapacity(comp.system_libs.values().len);
|
||||
for (comp.system_libs.values()) |lib_info| {
|
||||
system_libs.appendAssumeCapacity(.{ .needed = lib_info.needed, .path = lib_info.path.? });
|
||||
}
|
||||
|
||||
// libc++ dep
|
||||
if (self.base.comp.config.link_libcpp) {
|
||||
if (comp.config.link_libcpp) {
|
||||
try system_libs.ensureUnusedCapacity(2);
|
||||
system_libs.appendAssumeCapacity(.{ .path = comp.libcxxabi_static_lib.?.full_object_path });
|
||||
system_libs.appendAssumeCapacity(.{ .path = comp.libcxx_static_lib.?.full_object_path });
|
||||
}
|
||||
|
||||
// libunwind dep
|
||||
if (self.base.comp.config.link_libunwind) {
|
||||
if (comp.config.link_libunwind) {
|
||||
try system_libs.append(.{ .path = comp.libunwind_static_lib.?.full_object_path });
|
||||
}
|
||||
|
||||
// libc dep
|
||||
self.base.error_flags.missing_libc = false;
|
||||
if (self.base.comp.config.link_libc) {
|
||||
if (self.base.comp.libc_installation) |lc| {
|
||||
if (comp.config.link_libc) {
|
||||
if (comp.libc_installation) |lc| {
|
||||
const flags = target_util.libcFullLinkFlags(target);
|
||||
try system_libs.ensureUnusedCapacity(flags.len);
|
||||
|
||||
@ -1305,7 +1304,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
|
||||
// Look for entry address in objects if not set by the incremental compiler.
|
||||
if (self.entry_index == null) {
|
||||
const entry: ?[]const u8 = entry: {
|
||||
if (self.base.comp.config.entry) |entry| break :entry entry;
|
||||
if (comp.config.entry) |entry| break :entry entry;
|
||||
if (!self.base.isDynLib()) break :entry "_start";
|
||||
break :entry null;
|
||||
};
|
||||
|
||||
@ -43,7 +43,7 @@ pub fn outputShndx(symbol: Symbol) ?u16 {
|
||||
}
|
||||
|
||||
pub fn isLocal(symbol: Symbol, elf_file: *Elf) bool {
|
||||
if (elf_file.isRelocatable()) return symbol.elfSym(elf_file).st_bind() == elf.STB_LOCAL;
|
||||
if (elf_file.base.isRelocatable()) return symbol.elfSym(elf_file).st_bind() == elf.STB_LOCAL;
|
||||
return !(symbol.flags.import or symbol.flags.@"export");
|
||||
}
|
||||
|
||||
@ -186,7 +186,7 @@ const GetOrCreateZigGotEntryResult = struct {
|
||||
};
|
||||
|
||||
pub fn getOrCreateZigGotEntry(symbol: *Symbol, symbol_index: Index, elf_file: *Elf) !GetOrCreateZigGotEntryResult {
|
||||
assert(!elf_file.isRelocatable());
|
||||
assert(!elf_file.base.isRelocatable());
|
||||
assert(symbol.flags.needs_zig_got);
|
||||
if (symbol.flags.has_zig_got) return .{ .found_existing = true, .index = symbol.extra(elf_file).?.zig_got };
|
||||
const index = try elf_file.zig_got.addSymbol(symbol_index, elf_file);
|
||||
@ -237,7 +237,7 @@ pub fn setOutputSym(symbol: Symbol, elf_file: *Elf, out: *elf.Elf64_Sym) void {
|
||||
const st_shndx = blk: {
|
||||
if (symbol.flags.has_copy_rel) break :blk elf_file.copy_rel_section_index.?;
|
||||
if (file_ptr == .shared_object or esym.st_shndx == elf.SHN_UNDEF) break :blk elf.SHN_UNDEF;
|
||||
if (elf_file.isRelocatable() and esym.st_shndx == elf.SHN_COMMON) break :blk elf.SHN_COMMON;
|
||||
if (elf_file.base.isRelocatable() and esym.st_shndx == elf.SHN_COMMON) break :blk elf.SHN_COMMON;
|
||||
if (symbol.atom(elf_file) == null and file_ptr != .linker_defined) break :blk elf.SHN_ABS;
|
||||
break :blk symbol.outputShndx() orelse elf.SHN_UNDEF;
|
||||
};
|
||||
|
||||
@ -926,7 +926,7 @@ fn updateDeclCode(
|
||||
sym.value = atom_ptr.value;
|
||||
esym.st_value = atom_ptr.value;
|
||||
|
||||
if (!elf_file.isRelocatable()) {
|
||||
if (!elf_file.base.isRelocatable()) {
|
||||
log.debug(" (writing new offset table entry)", .{});
|
||||
assert(sym.flags.has_zig_got);
|
||||
const extra = sym.extra(elf_file).?;
|
||||
@ -944,7 +944,7 @@ fn updateDeclCode(
|
||||
sym.flags.needs_zig_got = true;
|
||||
esym.st_value = atom_ptr.value;
|
||||
|
||||
if (!elf_file.isRelocatable()) {
|
||||
if (!elf_file.base.isRelocatable()) {
|
||||
const gop = try sym.getOrCreateZigGotEntry(sym_index, elf_file);
|
||||
try elf_file.zig_got.writeOne(elf_file, gop.index);
|
||||
}
|
||||
@ -1262,7 +1262,7 @@ fn updateLazySymbol(
|
||||
local_sym.flags.needs_zig_got = true;
|
||||
local_esym.st_value = atom_ptr.value;
|
||||
|
||||
if (!elf_file.isRelocatable()) {
|
||||
if (!elf_file.base.isRelocatable()) {
|
||||
const gop = try local_sym.getOrCreateZigGotEntry(symbol_index, elf_file);
|
||||
try elf_file.zig_got.writeOne(elf_file, gop.index);
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
base: File,
|
||||
|
||||
/// If this is not null, an object file is created by LLVM and linked with LLD afterwards.
|
||||
/// If this is not null, an object file is created by LLVM and emitted to intermediary_basename.
|
||||
llvm_object: ?*LlvmObject = null,
|
||||
|
||||
/// Debug symbols bundle (or dSym).
|
||||
@ -352,22 +352,23 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No
|
||||
const tracy = trace(@src());
|
||||
defer tracy.end();
|
||||
|
||||
if (self.llvm_object) |llvm_object| {
|
||||
return try llvm_object.flushModule(comp, prog_node);
|
||||
}
|
||||
|
||||
const gpa = self.base.comp.gpa;
|
||||
const gpa = comp.gpa;
|
||||
var arena_allocator = std.heap.ArenaAllocator.init(gpa);
|
||||
defer arena_allocator.deinit();
|
||||
const arena = arena_allocator.allocator();
|
||||
|
||||
if (self.llvm_object) |llvm_object| {
|
||||
try self.base.emitLlvmObject(arena, llvm_object, prog_node);
|
||||
return;
|
||||
}
|
||||
|
||||
var sub_prog_node = prog_node.start("MachO Flush", 0);
|
||||
sub_prog_node.activate();
|
||||
defer sub_prog_node.end();
|
||||
|
||||
const output_mode = self.base.comp.config.output_mode;
|
||||
const module = self.base.comp.module orelse return error.LinkingWithoutZigSourceUnimplemented;
|
||||
const target = self.base.comp.root_mod.resolved_target.result;
|
||||
const output_mode = comp.config.output_mode;
|
||||
const module = comp.module orelse return error.LinkingWithoutZigSourceUnimplemented;
|
||||
const target = comp.root_mod.resolved_target.result;
|
||||
|
||||
if (self.lazy_syms.getPtr(.none)) |metadata| {
|
||||
// Most lazy symbols can be updated on first use, but
|
||||
@ -619,7 +620,7 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No
|
||||
.stacksize = self.base.stack_size,
|
||||
});
|
||||
},
|
||||
.Lib => if (self.base.comp.config.link_mode == .Dynamic) {
|
||||
.Lib => if (comp.config.link_mode == .Dynamic) {
|
||||
try load_commands.writeDylibIdLC(self, lc_writer);
|
||||
},
|
||||
else => {},
|
||||
|
||||
@ -3700,8 +3700,15 @@ pub fn flushModule(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod
|
||||
const tracy = trace(@src());
|
||||
defer tracy.end();
|
||||
|
||||
const gpa = comp.gpa;
|
||||
// Used for all temporary memory allocated during flushin
|
||||
var arena_instance = std.heap.ArenaAllocator.init(gpa);
|
||||
defer arena_instance.deinit();
|
||||
const arena = arena_instance.allocator();
|
||||
|
||||
if (wasm.llvm_object) |llvm_object| {
|
||||
return try llvm_object.flushModule(comp, prog_node);
|
||||
try wasm.base.emitLlvmObject(arena, llvm_object, prog_node);
|
||||
return;
|
||||
}
|
||||
|
||||
var sub_prog_node = prog_node.start("Wasm Flush", 0);
|
||||
@ -3711,13 +3718,7 @@ pub fn flushModule(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod
|
||||
// ensure the error names table is populated when an error name is referenced
|
||||
try wasm.populateErrorNameTable();
|
||||
|
||||
// Used for all temporary memory allocated during flushin
|
||||
const gpa = wasm.base.comp.gpa;
|
||||
var arena_instance = std.heap.ArenaAllocator.init(gpa);
|
||||
defer arena_instance.deinit();
|
||||
const arena = arena_instance.allocator();
|
||||
|
||||
const objects = wasm.base.comp.objects;
|
||||
const objects = comp.objects;
|
||||
|
||||
// Positional arguments to the linker such as object files and static archives.
|
||||
var positionals = std.ArrayList([]const u8).init(arena);
|
||||
@ -3755,7 +3756,7 @@ pub fn flushModule(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod
|
||||
try wasm.markReferences();
|
||||
try wasm.setupErrorsLen();
|
||||
try wasm.setupImports();
|
||||
if (wasm.base.comp.module) |mod| {
|
||||
if (comp.module) |mod| {
|
||||
var decl_it = wasm.decls.iterator();
|
||||
while (decl_it.next()) |entry| {
|
||||
const decl = mod.declPtr(entry.key_ptr.*);
|
||||
@ -3810,7 +3811,7 @@ pub fn flushModule(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod
|
||||
}
|
||||
|
||||
if (wasm.dwarf) |*dwarf| {
|
||||
try dwarf.flushModule(wasm.base.comp.module.?);
|
||||
try dwarf.flushModule(comp.module.?);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user