Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 53 additions & 3 deletions build.zig
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ pub fn build(b: *std.Build) void {

// ************************************************ CODEGEN IR LIB_MODEL*****************************************
// $ zig build lib-gen -Dmodel="myModel" ...
lib_codegen(b, zantBuild);
const codegen_run_step = lib_codegen(b, zantBuild);

// ************************************************ LIB_MODEL EXECUTABLE ****************************************
// $ zig build lib-exe -Dmodel="myModel" ...
Expand All @@ -50,6 +50,10 @@ pub fn build(b: *std.Build) void {
// $ zig build lib -Dmodel="myModel" [ -Dtarget=... -Dcpu=... -Doptimize=[ReleaseSmall, ReleaseFast]]
const static_lib: *std.Build.Step.Compile = lib_creation(b, zantBuild) catch unreachable;

// *********************************************** REWRITE SECTIONS WHEN NEEDED (ELF + XIP) ********************
// $ zig build lib -Dmodel="myModel" -Dxip=true ...
rewrite_sections(b, zantBuild, codegen_run_step, static_lib);

// ************************************************ ONEOP CODEGEN ************************************************
// $ zig build op-codegen-gen [ -Dop="OpName" ]
op_codegen_gen(b, zantBuild);
Expand Down Expand Up @@ -108,12 +112,12 @@ inline fn unit_test_creation(b: *std.Build, zantBuild: ZantBuild) void {
test_step.dependOn(&run_unit_tests.step);
}

inline fn lib_codegen(b: *std.Build, zantBuild: ZantBuild) void {
inline fn lib_codegen(b: *std.Build, zantBuild: ZantBuild) *std.Build.Step {
const IR_codeGen_exe = b.addExecutable(.{
.name = "codegen",
.root_module = b.createModule(.{
.root_source_file = b.path("src/codegen/main.zig"),
.target = target,
.target = b.graph.host,
.optimize = optimize,
}),
});
Expand All @@ -140,6 +144,8 @@ inline fn lib_codegen(b: *std.Build, zantBuild: ZantBuild) void {
// Create a build step to run the application.
const IR_codegen_step = b.step("lib-gen", "code generation");
IR_codegen_step.dependOn(&IR_codegen_cmd.step);

return &IR_codegen_cmd.step;
}

inline fn lib_exe(b: *std.Build, zantBuild: ZantBuild) void {
Expand Down Expand Up @@ -497,3 +503,47 @@ inline fn build_main(b: *std.Build, zantBuild: ZantBuild, static_lib: *std.Build
const build_main_step = b.step("build-main", "Build the main executable for profiling");
build_main_step.dependOn(&install_main_exe_step.step);
}

inline fn addRewriteSectionsStep(
b: *std.Build,
generated_dir: []const u8,
) *std.Build.Step {
const file_path = std.fs.path.join(
b.allocator,
&.{ generated_dir, "static_parameters.zig" },
) catch @panic("path join failed");

// In 0.15.x, set target/optimize on the module, not on the exe.
const mod = b.createModule(.{
.root_source_file = b.path("src/codegen/cg_v1/parameters/rewrite_sections.zig"),
.target = b.graph.host, // host tool
.optimize = optimize, // small helper
});

const tool = b.addExecutable(.{
.name = "rewrite_sections",
.root_module = mod,
});

const run = b.addRunArtifact(tool);
run.addArg(file_path);

return &run.step;
}

inline fn rewrite_sections(b: *std.Build, zantBuild: ZantBuild, codegen_run_step: *std.Build.Step, static_lib: *std.Build.Step.Compile) void {
// If the target output is ELF (e.g., Cortex-M) and XIP is enabled, normalize
// Mach-O-style names in generated/static_parameters.zig before building the lib.
const is_elf = target.result.ofmt == .elf;
const xip_enabled = zantBuild.zantOptions.codegen_flags.xip_enabled;
if (is_elf and xip_enabled) {
// Step: build & run small host-side tool
const rw = addRewriteSectionsStep(
b,
zantBuild.zantOptions.codegen_flags.generated_path_option,
);
// Order: codegen → rewrite → static lib
rw.dependOn(codegen_run_step);
static_lib.step.dependOn(rw);
}
}
6 changes: 5 additions & 1 deletion src/codegen/cg_v1/parameters/parameters.zig
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,15 @@ pub const XIPConfig = struct {
if (!self.enabled) {
// For macOS (mach-o), section specifiers must be in "segment,section" format
if (comptime @import("builtin").target.os.tag == .macos) {
return "__DATA";
return "__TEXT,__const";
} else {
return ".rodata";
}
}
// For macOS (mach-o), section specifiers must be in "segment,section" format
if (comptime @import("builtin").target.os.tag == .macos) {
return "__DATA,__flash_weights";
}
// For other platforms, use the original format
return self.section_name;
}
Expand Down
57 changes: 57 additions & 0 deletions src/codegen/cg_v1/parameters/rewrite_sections.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
const std = @import("std");

/// Helper that replaces text and frees the previous buffer
fn replaceAndFree(
alloc: std.mem.Allocator,
buf: []u8,
needle: []const u8,
repl: []const u8,
) ![]u8 {
const out = try std.mem.replaceOwned(u8, alloc, buf, needle, repl);
alloc.free(buf);
return out;
}

pub fn main() !void {
// -------------------------------------------------------------------------
// Allocator setup with leak check (works in Zig 0.15.x)
// -------------------------------------------------------------------------
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
defer {
const check = gpa.deinit();
if (check == .leak)
std.debug.panic("memory leak detected in rewrite_sections", .{});
}
const alloc = gpa.allocator();

// -------------------------------------------------------------------------
// Argument parsing
// -------------------------------------------------------------------------
var it = try std.process.argsWithAllocator(alloc);
defer it.deinit();

_ = it.next(); // exe name
const path = it.next() orelse {
std.log.err("usage: rewrite_sections <path-to-static_parameters.zig>", .{});
return error.MissingPath;
};

// -------------------------------------------------------------------------
// Read file into memory
// -------------------------------------------------------------------------
var text = try std.fs.cwd().readFileAlloc(alloc, path, 10 * 1024 * 1024);
defer alloc.free(text);

// -------------------------------------------------------------------------
// Replace Mach-O section names with ELF ones
// -------------------------------------------------------------------------
text = try replaceAndFree(alloc, text, "__DATA,__flash_weights", ".flash_weights");
text = try replaceAndFree(alloc, text, "__TEXT,__const", ".rodata");

// -------------------------------------------------------------------------
// Overwrite the original file with the fixed content
// -------------------------------------------------------------------------
try std.fs.cwd().writeFile(.{ .sub_path = path, .data = text });

std.log.info("rewrite_sections: updated {s}", .{path});
}