mirror of
https://github.com/ziglang/zig.git
synced 2026-01-07 14:03:26 +00:00
This branch introduced an arena allocator for temporary allocations in Compilation.update. Almost every implementation of flush() inside the linker code was already creating a local arena that had the lifetime of the function call. This commit passes the update arena so that all those local ones can be deleted, resulting in slightly more efficient memory usage with every compilation update. While at it, this commit also removes the Compilation parameter from the linker flush function API since a reference to the Compilation is now already stored in `link.File`.
124 lines
4.1 KiB
Zig
124 lines
4.1 KiB
Zig
//! NVidia PTX (Parallel Thread Execution)
|
|
//! https://docs.nvidia.com/cuda/parallel-thread-execution/index.html
|
|
//! For this we rely on the nvptx backend of LLVM
|
|
//! Kernel functions need to be marked both as "export" and "callconv(.Kernel)"
|
|
|
|
const NvPtx = @This();
|
|
|
|
const std = @import("std");
|
|
const builtin = @import("builtin");
|
|
|
|
const Allocator = std.mem.Allocator;
|
|
const assert = std.debug.assert;
|
|
const log = std.log.scoped(.link);
|
|
|
|
const Module = @import("../Module.zig");
|
|
const InternPool = @import("../InternPool.zig");
|
|
const Compilation = @import("../Compilation.zig");
|
|
const link = @import("../link.zig");
|
|
const trace = @import("../tracy.zig").trace;
|
|
const build_options = @import("build_options");
|
|
const Air = @import("../Air.zig");
|
|
const Liveness = @import("../Liveness.zig");
|
|
const LlvmObject = @import("../codegen/llvm.zig").Object;
|
|
|
|
base: link.File,
|
|
llvm_object: *LlvmObject,
|
|
|
|
pub fn createEmpty(
|
|
arena: Allocator,
|
|
comp: *Compilation,
|
|
emit: Compilation.Emit,
|
|
options: link.File.OpenOptions,
|
|
) !*NvPtx {
|
|
const target = comp.root_mod.resolved_target.result;
|
|
const use_lld = build_options.have_llvm and comp.config.use_lld;
|
|
const use_llvm = comp.config.use_llvm;
|
|
|
|
assert(use_llvm); // Caught by Compilation.Config.resolve.
|
|
assert(!use_lld); // Caught by Compilation.Config.resolve.
|
|
assert(target.cpu.arch.isNvptx()); // Caught by Compilation.Config.resolve.
|
|
|
|
switch (target.os.tag) {
|
|
// TODO: does it also work with nvcl ?
|
|
.cuda => {},
|
|
else => return error.PtxArchNotSupported,
|
|
}
|
|
|
|
const llvm_object = try LlvmObject.create(arena, comp);
|
|
const nvptx = try arena.create(NvPtx);
|
|
nvptx.* = .{
|
|
.base = .{
|
|
.tag = .nvptx,
|
|
.comp = comp,
|
|
.emit = emit,
|
|
.gc_sections = options.gc_sections orelse false,
|
|
.print_gc_sections = options.print_gc_sections,
|
|
.stack_size = options.stack_size orelse 0,
|
|
.allow_shlib_undefined = options.allow_shlib_undefined orelse false,
|
|
.file = null,
|
|
.disable_lld_caching = options.disable_lld_caching,
|
|
.build_id = options.build_id,
|
|
.rpath_list = options.rpath_list,
|
|
},
|
|
.llvm_object = llvm_object,
|
|
};
|
|
|
|
return nvptx;
|
|
}
|
|
|
|
pub fn open(
|
|
arena: Allocator,
|
|
comp: *Compilation,
|
|
emit: Compilation.Emit,
|
|
options: link.File.OpenOptions,
|
|
) !*NvPtx {
|
|
const target = comp.root_mod.resolved_target.result;
|
|
assert(target.ofmt == .nvptx);
|
|
return createEmpty(arena, comp, emit, options);
|
|
}
|
|
|
|
pub fn deinit(self: *NvPtx) void {
|
|
self.llvm_object.deinit();
|
|
}
|
|
|
|
pub fn updateFunc(self: *NvPtx, module: *Module, func_index: InternPool.Index, air: Air, liveness: Liveness) !void {
|
|
try self.llvm_object.updateFunc(module, func_index, air, liveness);
|
|
}
|
|
|
|
pub fn updateDecl(self: *NvPtx, module: *Module, decl_index: InternPool.DeclIndex) !void {
|
|
return self.llvm_object.updateDecl(module, decl_index);
|
|
}
|
|
|
|
pub fn updateExports(
|
|
self: *NvPtx,
|
|
module: *Module,
|
|
exported: Module.Exported,
|
|
exports: []const *Module.Export,
|
|
) !void {
|
|
if (build_options.skip_non_native and builtin.object_format != .nvptx)
|
|
@panic("Attempted to compile for object format that was disabled by build configuration");
|
|
|
|
return self.llvm_object.updateExports(module, exported, exports);
|
|
}
|
|
|
|
pub fn freeDecl(self: *NvPtx, decl_index: InternPool.DeclIndex) void {
|
|
return self.llvm_object.freeDecl(decl_index);
|
|
}
|
|
|
|
pub fn flush(self: *NvPtx, arena: Allocator, prog_node: *std.Progress.Node) link.File.FlushError!void {
|
|
return self.flushModule(arena, prog_node);
|
|
}
|
|
|
|
pub fn flushModule(self: *NvPtx, arena: Allocator, prog_node: *std.Progress.Node) link.File.FlushError!void {
|
|
if (build_options.skip_non_native)
|
|
@panic("Attempted to compile for architecture that was disabled by build configuration");
|
|
|
|
// The code that was here before mutated the Compilation's file emission mechanism.
|
|
// That's not supposed to happen in flushModule, so I deleted the code.
|
|
_ = arena;
|
|
_ = self;
|
|
_ = prog_node;
|
|
@panic("TODO: rewrite the NvPtx.flushModule function");
|
|
}
|