authorgravatar for abbix@riseup.netlg <abbix@riseup.net> 2026-09-03 14:41:10-04:00
committergravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2026-09-16 19:21:21+02:00
log39512c3e5547b411294369c8eec8093045f74d64
treeed239d2a11a5fddc1abbf0dc3db3479d7f283658
parent2ec5523d5a70db80bac8563e1f06d3b164f53db3

compiler: add support for patchable functions


17 files changed, 164 insertions(+), 32 deletions(-)

lib/compiler/Maker/Step/Compile.zig+8
...@@ -1279,6 +1279,14 @@ fn appendModuleFlags(...@@ -1279,6 +1279,14 @@ fn appendModuleFlags(
1279 }1279 }
1280 }1280 }
12811281
1282 if (m.patchable_function_entry > 0) {
1283 const count = m.patchable_function_entry;
1284 try zig_args.append(
1285 gpa,
1286 try arena.print("-fpatchable-function-entry={d}", .{count}),
1287 );
1288 }
1289
1282 if (m.resolved_target.get(conf)) |resolved_target| {1290 if (m.resolved_target.get(conf)) |resolved_target| {
1283 // Communicate the query via CLI since it's more compact.1291 // Communicate the query via CLI since it's more compact.
1284 if (resolved_target.unwrapQuery(conf)) |query| {1292 if (resolved_target.unwrapQuery(conf)) |query| {
lib/std/Build/Configuration.zig+1
...@@ -1652,6 +1652,7 @@ pub const Module = struct {...@@ -1652,6 +1652,7 @@ pub const Module = struct {
1652 rpaths: Storage.UnionList(.flags, .rpaths, RPath),1652 rpaths: Storage.UnionList(.flags, .rpaths, RPath),
1653 link_objects: Storage.UnionList(.flags, .link_objects, LinkObject),1653 link_objects: Storage.UnionList(.flags, .link_objects, LinkObject),
1654 frameworks: Storage.FlagLengthPrefixedList(.flags, .frameworks, Framework),1654 frameworks: Storage.FlagLengthPrefixedList(.flags, .frameworks, Framework),
1655 patchable_function_entry: u32,
16551656
1656 pub const Optimize = enum(u3) {1657 pub const Optimize = enum(u3) {
1657 debug,1658 debug,
lib/std/Build/Module.zig+3
...@@ -42,6 +42,7 @@ error_tracing: ?bool,...@@ -42,6 +42,7 @@ error_tracing: ?bool,
42link_libc: ?bool,42link_libc: ?bool,
43link_libcpp: ?bool,43link_libcpp: ?bool,
44no_builtin: ?bool,44no_builtin: ?bool,
45patchable_function_entry: u16,
4546
46/// Symbols to be exported when compiling to WebAssembly.47/// Symbols to be exported when compiling to WebAssembly.
47export_symbol_names: []const []const u8 = &.{},48export_symbol_names: []const []const u8 = &.{},
...@@ -230,6 +231,7 @@ pub const CreateOptions = struct {...@@ -230,6 +231,7 @@ pub const CreateOptions = struct {
230 omit_frame_pointer: ?bool = null,231 omit_frame_pointer: ?bool = null,
231 error_tracing: ?bool = null,232 error_tracing: ?bool = null,
232 no_builtin: ?bool = null,233 no_builtin: ?bool = null,
234 patchable_function_entry: u16 = 0,
233};235};
234236
235pub const Import = struct {237pub const Import = struct {
...@@ -278,6 +280,7 @@ pub fn init(...@@ -278,6 +280,7 @@ pub fn init(
278 .error_tracing = options.error_tracing,280 .error_tracing = options.error_tracing,
279 .export_symbol_names = &.{},281 .export_symbol_names = &.{},
280 .no_builtin = options.no_builtin,282 .no_builtin = options.no_builtin,
283 .patchable_function_entry = options.patchable_function_entry,
281 };284 };
282285
283 m.import_table.ensureUnusedCapacity(arena, options.imports.len) catch @panic("OOM");286 m.import_table.ensureUnusedCapacity(arena, options.imports.len) catch @panic("OOM");
lib/std/Build/Serialize.zig+1
...@@ -1243,6 +1243,7 @@ fn addModule(s: *Serialize, m: *std.Build.Module) !Configuration.Module.Index {...@@ -1243,6 +1243,7 @@ fn addModule(s: *Serialize, m: *std.Build.Module) !Configuration.Module.Index {
1243 .rpaths = .init(rpaths),1243 .rpaths = .init(rpaths),
1244 .link_objects = .init(link_objects),1244 .link_objects = .init(link_objects),
1245 .frameworks = .{ .slice = frameworks },1245 .frameworks = .{ .slice = frameworks },
1246 .patchable_function_entry = m.patchable_function_entry,
1246 });1247 });
12471248
1248 // The import table is the only place that modules can form dependency1249 // The import table is the only place that modules can form dependency
lib/std/zig.zig+1
...@@ -1202,6 +1202,7 @@ pub const ClangCliParam = struct {...@@ -1202,6 +1202,7 @@ pub const ClangCliParam = struct {
1202 static,1202 static,
1203 dynamic,1203 dynamic,
1204 version,1204 version,
1205 patchable_function_entry,
1205 };1206 };
12061207
1207 pub fn matchEql(self: @This(), arg: []const u8) u2 {1208 pub fn matchEql(self: @This(), arg: []const u8) u2 {
lib/zig.h+6
...@@ -261,6 +261,12 @@...@@ -261,6 +261,12 @@
261#define zig_no_builtin261#define zig_no_builtin
262#endif262#endif
263263
264#if zig_has_attribute(patchable_function_entry)
265#define zig_patchable_function_entry(count) __attribute__((patchable_function_entry(count)))
266#else
267#define zig_patchable_function_entry(count) zig_patchable_function_entry_unavailable
268#endif
269
264#if zig_has_attribute(aligned) || defined(zig_tinyc)270#if zig_has_attribute(aligned) || defined(zig_tinyc)
265#define zig_under_align(alignment) __attribute__((aligned(alignment)))271#define zig_under_align(alignment) __attribute__((aligned(alignment)))
266#elif defined(zig_msvc)272#elif defined(zig_msvc)
src/Compilation.zig+10
...@@ -1306,6 +1306,7 @@ pub const cache_helpers = struct {...@@ -1306,6 +1306,7 @@ pub const cache_helpers = struct {
1306 hh.add(mod.fuzz);1306 hh.add(mod.fuzz);
1307 hh.add(mod.unwind_tables);1307 hh.add(mod.unwind_tables);
1308 hh.add(mod.no_builtin);1308 hh.add(mod.no_builtin);
1309 hh.add(mod.patchable_function_entry);
1309 hh.addListOfBytes(mod.cc_argv);1310 hh.addListOfBytes(mod.cc_argv);
1310 }1311 }
13111312
...@@ -1847,6 +1848,7 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic,...@@ -1847,6 +1848,7 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic,
1847 error.PieRequiresPic => unreachable,1848 error.PieRequiresPic => unreachable,
1848 error.DynamicLinkingRequiresPic => unreachable,1849 error.DynamicLinkingRequiresPic => unreachable,
1849 error.TargetHasNoRedZone => unreachable,1850 error.TargetHasNoRedZone => unreachable,
1851 error.PatchableFunctionEntryUnsupportedByBackend => unreachable,
1850 // These are not possible because are explicitly *not* requesting these things.1852 // These are not possible because are explicitly *not* requesting these things.
1851 error.StackCheckUnsupportedByTarget => unreachable,1853 error.StackCheckUnsupportedByTarget => unreachable,
1852 error.StackProtectorUnsupportedByTarget => unreachable,1854 error.StackProtectorUnsupportedByTarget => unreachable,
...@@ -1908,6 +1910,7 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic,...@@ -1908,6 +1910,7 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic,
1908 error.StackCheckUnsupportedByTarget => unreachable,1910 error.StackCheckUnsupportedByTarget => unreachable,
1909 error.StackProtectorUnsupportedByTarget => unreachable,1911 error.StackProtectorUnsupportedByTarget => unreachable,
1910 error.StackProtectorUnavailableWithoutLibC => unreachable,1912 error.StackProtectorUnavailableWithoutLibC => unreachable,
1913 error.PatchableFunctionEntryUnsupportedByBackend => unreachable,
1911 };1914 };
1912 try options.root_mod.deps.putNoClobber(arena, "ubsan_rt", ubsan_rt_mod);1915 try options.root_mod.deps.putNoClobber(arena, "ubsan_rt", ubsan_rt_mod);
1913 }1916 }
...@@ -1953,6 +1956,7 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic,...@@ -1953,6 +1956,7 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic,
1953 error.StackCheckUnsupportedByTarget => unreachable,1956 error.StackCheckUnsupportedByTarget => unreachable,
1954 error.StackProtectorUnsupportedByTarget => unreachable,1957 error.StackProtectorUnsupportedByTarget => unreachable,
1955 error.StackProtectorUnavailableWithoutLibC => unreachable,1958 error.StackProtectorUnavailableWithoutLibC => unreachable,
1959 error.PatchableFunctionEntryUnsupportedByBackend => unreachable,
1956 };1960 };
1957 try options.root_mod.deps.putNoClobber(arena, "zigc", zigc_mod);1961 try options.root_mod.deps.putNoClobber(arena, "zigc", zigc_mod);
1958 }1962 }
...@@ -2085,6 +2089,7 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic,...@@ -2085,6 +2089,7 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic,
2085 error.StackCheckUnsupportedByTarget => unreachable,2089 error.StackCheckUnsupportedByTarget => unreachable,
2086 error.StackProtectorUnsupportedByTarget => unreachable,2090 error.StackProtectorUnsupportedByTarget => unreachable,
2087 error.StackProtectorUnavailableWithoutLibC => unreachable,2091 error.StackProtectorUnavailableWithoutLibC => unreachable,
2092 error.PatchableFunctionEntryUnsupportedByBackend => unreachable,
2088 };2093 };
20892094
2090 const zcu = try arena.create(Zcu);2095 const zcu = try arena.create(Zcu);
...@@ -6639,6 +6644,11 @@ pub fn addCCArgs(...@@ -6639,6 +6644,11 @@ pub fn addCCArgs(
6639 });6644 });
6640 }6645 }
66416646
6647 if (mod.patchable_function_entry > 0) {
6648 const pf = mod.patchable_function_entry;
6649 try argv.append(try std.fmt.allocPrint(arena, "-fpatchable-function-entry={}", .{pf}));
6650 }
6651
6642 try comp.addCommonCCArgs(arena, argv, ext, out_dep_path, mod, comp.config.c_frontend);6652 try comp.addCommonCCArgs(arena, argv, ext, out_dep_path, mod, comp.config.c_frontend);
66436653
6644 // Only assembly files support these flags.6654 // Only assembly files support these flags.
src/Module.zig+39
...@@ -43,6 +43,7 @@ fuzz: bool,...@@ -43,6 +43,7 @@ fuzz: bool,
43unwind_tables: std.lang.UnwindTables,43unwind_tables: std.lang.UnwindTables,
44cc_argv: []const []const u8,44cc_argv: []const []const u8,
45no_builtin: bool,45no_builtin: bool,
46patchable_function_entry: u16,
4647
47pub const Deps = std.array_hash_map.String(*Module);48pub const Deps = std.array_hash_map.String(*Module);
4849
...@@ -84,6 +85,7 @@ pub const CreateOptions = struct {...@@ -84,6 +85,7 @@ pub const CreateOptions = struct {
84 sanitize_thread: ?bool = null,85 sanitize_thread: ?bool = null,
85 fuzz: ?bool = null,86 fuzz: ?bool = null,
86 no_builtin: ?bool = null,87 no_builtin: ?bool = null,
88 patchable_function_entry: u16 = 0,
87 };89 };
88};90};
8991
...@@ -107,6 +109,7 @@ pub const CreateError = error{...@@ -107,6 +109,7 @@ pub const CreateError = error{
107 StackCheckUnsupportedByTarget,109 StackCheckUnsupportedByTarget,
108 StackProtectorUnsupportedByTarget,110 StackProtectorUnsupportedByTarget,
109 StackProtectorUnavailableWithoutLibC,111 StackProtectorUnavailableWithoutLibC,
112 PatchableFunctionEntryUnsupportedByBackend,
110};113};
111114
112/// At least one of `parent` and `resolved_target` must be non-null.115/// At least one of `parent` and `resolved_target` must be non-null.
...@@ -324,6 +327,39 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Module {...@@ -324,6 +327,39 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Module {
324 break :b target.cpu.arch.isBpf();327 break :b target.cpu.arch.isBpf();
325 };328 };
326329
330 const patchable_function_entry = b: {
331 const x = options.inherited.patchable_function_entry;
332 if (x > 0) {
333 switch (zig_backend) {
334 .stage2_llvm,
335 .stage2_x86_64,
336 .stage2_aarch64,
337 .stage2_c,
338 .stage2_riscv64,
339 .stage2_loongarch,
340 => {},
341
342 // Does not apply to this architecture.
343 .stage2_spirv,
344 .zsf_spork8,
345 .stage2_wasm,
346 => return error.PatchableFunctionEntryUnsupportedByBackend,
347
348 // Not implemented.
349 .stage2_sparc64,
350 .stage2_x86,
351 .stage2_arm,
352 .stage2_powerpc,
353 => return error.PatchableFunctionEntryUnsupportedByBackend,
354
355 .other, .stage1, _ => unreachable,
356 }
357 break :b x;
358 }
359 if (options.parent) |p| break :b p.patchable_function_entry;
360 break :b 0;
361 };
362
327 const llvm_cpu_features: ?[*:0]const u8 = b: {363 const llvm_cpu_features: ?[*:0]const u8 = b: {
328 if (resolved_target.llvm_cpu_features) |x| break :b x;364 if (resolved_target.llvm_cpu_features) |x| break :b x;
329 if (!options.global.use_llvm) break :b null;365 if (!options.global.use_llvm) break :b null;
...@@ -398,6 +434,7 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Module {...@@ -398,6 +434,7 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Module {
398 .unwind_tables = unwind_tables,434 .unwind_tables = unwind_tables,
399 .cc_argv = options.cc_argv,435 .cc_argv = options.cc_argv,
400 .no_builtin = no_builtin,436 .no_builtin = no_builtin,
437 .patchable_function_entry = patchable_function_entry,
401 };438 };
402 return mod;439 return mod;
403}440}
...@@ -436,6 +473,7 @@ pub fn createLimited(gpa: Allocator, options: LimitedOptions) Allocator.Error!*M...@@ -436,6 +473,7 @@ pub fn createLimited(gpa: Allocator, options: LimitedOptions) Allocator.Error!*M
436 .unwind_tables = undefined,473 .unwind_tables = undefined,
437 .cc_argv = undefined,474 .cc_argv = undefined,
438 .no_builtin = undefined,475 .no_builtin = undefined,
476 .patchable_function_entry = undefined,
439 };477 };
440 return mod;478 return mod;
441}479}
...@@ -474,6 +512,7 @@ pub fn createBuiltin(arena: Allocator, opts: Builtin, dirs: std.zig.Directories)...@@ -474,6 +512,7 @@ pub fn createBuiltin(arena: Allocator, opts: Builtin, dirs: std.zig.Directories)
474 .red_zone = false,512 .red_zone = false,
475 .sanitize_c = .off,513 .sanitize_c = .off,
476 .no_builtin = false,514 .no_builtin = false,
515 .patchable_function_entry = 0,
477 };516 };
478 return new;517 return new;
479}518}
src/clang_options.zon+6-2
...@@ -3603,7 +3603,11 @@...@@ -3603,7 +3603,11 @@
3603.{ .name = "fms-compatibility-version=", .syntax = .joined },3603.{ .name = "fms-compatibility-version=", .syntax = .joined },
3604.{ .name = "fopenmp-cuda-number-of-sm=", .syntax = .joined },3604.{ .name = "fopenmp-cuda-number-of-sm=", .syntax = .joined },
3605.{ .name = "foptimization-record-file=", .syntax = .joined },3605.{ .name = "foptimization-record-file=", .syntax = .joined },
3606.{ .name = "fpatchable-function-entry=", .syntax = .joined },3606.{
3607 .name = "fpatchable-function-entry=",
3608 .ze = .patchable_function_entry,
3609 .syntax = .joined,
3610},
3607.{ .name = "frepack-arrays-contiguity=", .syntax = .joined },3611.{ .name = "frepack-arrays-contiguity=", .syntax = .joined },
3608.{ .name = "fsanitize-skip-hot-cutoff=", .syntax = .comma_joined },3612.{ .name = "fsanitize-skip-hot-cutoff=", .syntax = .comma_joined },
3609.{ .name = "fsave-optimization-record=", .syntax = .joined },3613.{ .name = "fsave-optimization-record=", .syntax = .joined },
...@@ -5134,4 +5138,4 @@...@@ -5134,4 +5138,4 @@
5134 .syntax = .joined_or_separate,5138 .syntax = .joined_or_separate,
5135},5139},
5136.{ .name = "y", .syntax = .joined },5140.{ .name = "y", .syntax = .joined },
5137}
\ No newline at end of file
5141}
src/codegen/aarch64/Select.zig+5
...@@ -7757,6 +7757,11 @@ pub fn layout(...@@ -7757,6 +7757,11 @@ pub fn layout(
77577757
7758 {7758 {
7759 wip_mir_log.debug("{f}<prologue>:", .{nav.fqn.fmt(ip)});7759 wip_mir_log.debug("{f}<prologue>:", .{nav.fqn.fmt(ip)});
7760
7761 for (0..mod.patchable_function_entry) |_| {
7762 try isel.emit(.nop());
7763 }
7764
7760 var save_index: usize = 0;7765 var save_index: usize = 0;
7761 while (save_index < saves.len) if (save_index + 2 <= saves.len and7766 while (save_index < saves.len) if (save_index + 2 <= saves.len and
7762 saves[save_index + 0].class == saves[save_index + 1].class and7767 saves[save_index + 0].class == saves[save_index + 1].class and
src/codegen/c.zig+8
...@@ -1735,6 +1735,14 @@ pub const DeclGen = struct {...@@ -1735,6 +1735,14 @@ pub const DeclGen = struct {
1735 const fn_ty = fn_val.typeOf(zcu);1735 const fn_ty = fn_val.typeOf(zcu);
17361736
1737 const fn_info = zcu.typeToFunc(fn_ty).?;1737 const fn_info = zcu.typeToFunc(fn_ty).?;
1738
1739 if (kind == .definition) {
1740 if (dg.mod.patchable_function_entry > 0) {
1741 const count = dg.mod.patchable_function_entry;
1742 try w.print("zig_patchable_function_entry({d}) ", .{count});
1743 }
1744 }
1745
1738 if (fn_info.cc == .naked) {1746 if (fn_info.cc == .naked) {
1739 switch (kind) {1747 switch (kind) {
1740 .forward_decl => try w.writeAll("zig_naked_decl "),1748 .forward_decl => try w.writeAll("zig_naked_decl "),
src/codegen/llvm.zig+9
...@@ -2218,6 +2218,15 @@ pub const Object = struct {...@@ -2218,6 +2218,15 @@ pub const Object = struct {
2218 .value = try o.builder.string(std.mem.span(s)),2218 .value = try o.builder.string(std.mem.span(s)),
2219 } }, &o.builder);2219 } }, &o.builder);
2220 }2220 }
2221
2222 if (owner_mod.patchable_function_entry > 0) {
2223 const count = owner_mod.patchable_function_entry;
2224 try attributes.addFnAttr(.{ .string = .{
2225 .kind = try o.builder.string("patchable-function-entry"),
2226 .value = try o.builder.fmt("{d}", .{count}),
2227 } }, &o.builder);
2228 }
2229
2221 if (target.abi.float() == .soft) {2230 if (target.abi.float() == .soft) {
2222 // `use-soft-float` means "use software routines for floating point computations". In2231 // `use-soft-float` means "use software routines for floating point computations". In
2223 // other words, it configures how LLVM lowers basic float instructions like `fcmp`,2232 // other words, it configures how LLVM lowers basic float instructions like `fcmp`,
src/codegen/loongarch/Select.zig+4-1
...@@ -4756,7 +4756,6 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) codegen.Error!void...@@ -4756,7 +4756,6 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) codegen.Error!void
4756/// FP saving/restoring is not yet implemented.4756/// FP saving/restoring is not yet implemented.
4757pub fn layout(isel: *Select, cc_it: CallAbiIterator, mod: *const Module) !usize {4757pub fn layout(isel: *Select, cc_it: CallAbiIterator, mod: *const Module) !usize {
4758 _ = cc_it;4758 _ = cc_it;
4759 _ = mod;
4760 const zcu = isel.pt.zcu;4759 const zcu = isel.pt.zcu;
4761 const ip = &zcu.intern_pool;4760 const ip = &zcu.intern_pool;
4762 const nav = ip.getNav(isel.nav_index);4761 const nav = ip.getNav(isel.nav_index);
...@@ -4879,6 +4878,10 @@ pub fn layout(isel: *Select, cc_it: CallAbiIterator, mod: *const Module) !usize...@@ -4879,6 +4878,10 @@ pub fn layout(isel: *Select, cc_it: CallAbiIterator, mod: *const Module) !usize
4879 .fcc => unreachable,4878 .fcc => unreachable,
4880 }4879 }
4881 }4880 }
4881
4882 for (0..mod.patchable_function_entry) |_| {
4883 try isel.emit(.andi(.zero, .zero, 0));
4884 }
4882 wip_mir_log.debug("{f}<prologue>:", .{nav.fqn.fmt(ip)});4885 wip_mir_log.debug("{f}<prologue>:", .{nav.fqn.fmt(ip)});
4883 }4886 }
48844887
src/codegen/riscv64/CodeGen.zig+11
...@@ -1126,6 +1126,17 @@ fn gen(func: *Func) !void {...@@ -1126,6 +1126,17 @@ fn gen(func: *Func) !void {
1126 }1126 }
1127 }1127 }
11281128
1129 for (0..func.mod.patchable_function_entry) |_| {
1130 _ = try func.addInst(.{
1131 .tag = .addi,
1132 .data = .{ .i_type = .{
1133 .rd = .zero,
1134 .rs1 = .zero,
1135 .imm12 = Immediate.s(0),
1136 } },
1137 });
1138 }
1139
1129 if (fn_info.cc != .naked) {1140 if (fn_info.cc != .naked) {
1130 _ = try func.addPseudo(.pseudo_dbg_prologue_end);1141 _ = try func.addPseudo(.pseudo_dbg_prologue_end);
11311142
src/codegen/x86_64/CodeGen.zig+5
...@@ -2067,6 +2067,11 @@ fn gen(...@@ -2067,6 +2067,11 @@ fn gen(
2067 const pt = self.pt;2067 const pt = self.pt;
2068 const zcu = pt.zcu;2068 const zcu = pt.zcu;
2069 const fn_info = zcu.typeToFunc(self.fn_type).?;2069 const fn_info = zcu.typeToFunc(self.fn_type).?;
2070
2071 for (0..self.mod.patchable_function_entry) |_| {
2072 try self.asmOpOnly(.{ ._, .nop });
2073 }
2074
2070 if (fn_info.cc != .naked) {2075 if (fn_info.cc != .naked) {
2071 try self.asmRegister(.{ ._, .push }, .rbp);2076 try self.asmRegister(.{ ._, .push }, .rbp);
2072 try self.asmPseudoImmediate(.pseudo_cfi_adjust_cfa_offset_i_s, .s(8));2077 try self.asmPseudoImmediate(.pseudo_cfi_adjust_cfa_offset_i_s, .s(8));
src/main.zig+43-29
...@@ -567,35 +567,36 @@ const compile_usage =...@@ -567,35 +567,36 @@ const compile_usage =
567 \\ --build-root [path] Override path to project source files567 \\ --build-root [path] Override path to project source files
568 \\568 \\
569 \\Global Compile Options:569 \\Global Compile Options:
570 \\ --name [name] Compilation unit name (not a file path)570 \\ --name [name] Compilation unit name (not a file path)
571 \\ -M[name][=src] Create a module based on the current per-module settings.571 \\ -M[name][=src] Create a module based on the current per-module settings.
572 \\ The first module is the main module.572 \\ The first module is the main module.
573 \\ "std" can be configured by omitting src573 \\ "std" can be configured by omitting src
574 \\ After a -M argument, per-module settings are reset.574 \\ After a -M argument, per-module settings are reset.
575 \\ --libc [file] Provide a file which specifies libc paths575 \\ --libc [file] Provide a file which specifies libc paths
576 \\ -x [language] Treat subsequent input files as having type <language>576 \\ -x [language] Treat subsequent input files as having type <language>
577 \\ --error-limit [num] Set the maximum amount of distinct error values577 \\ --error-limit [num] Set the maximum amount of distinct error values
578 \\ -fllvm Force using LLVM as the codegen backend578 \\ -fllvm Force using LLVM as the codegen backend
579 \\ -fno-llvm Prevent using LLVM as the codegen backend579 \\ -fno-llvm Prevent using LLVM as the codegen backend
580 \\ -flibllvm Force using the LLVM API in the codegen backend580 \\ -flibllvm Force using the LLVM API in the codegen backend
581 \\ -fno-libllvm Prevent using the LLVM API in the codegen backend581 \\ -fno-libllvm Prevent using the LLVM API in the codegen backend
582 \\ -fclang Force using Clang as the C/C++ compilation backend582 \\ -fclang Force using Clang as the C/C++ compilation backend
583 \\ -fno-clang Prevent using Clang as the C/C++ compilation backend583 \\ -fno-clang Prevent using Clang as the C/C++ compilation backend
584 \\ -fPIE Force-enable Position Independent Executable584 \\ -fPIE Force-enable Position Independent Executable
585 \\ -fno-PIE Force-disable Position Independent Executable585 \\ -fno-PIE Force-disable Position Independent Executable
586 \\ -flto Force-enable Link Time Optimization (requires LLVM extensions)586 \\ -flto Force-enable Link Time Optimization (requires LLVM extensions)
587 \\ -fno-lto Force-disable Link Time Optimization587 \\ -fno-lto Force-disable Link Time Optimization
588 \\ -fdll-export-fns Mark exported functions as DLL exports (Windows)588 \\ -fdll-export-fns Mark exported functions as DLL exports (Windows)
589 \\ -fno-dll-export-fns Force-disable marking exported functions as DLL exports589 \\ -fno-dll-export-fns Force-disable marking exported functions as DLL exports
590 \\ -freference-trace[=num] Show num lines of reference trace per compile error590 \\ -freference-trace[=num] Show num lines of reference trace per compile error
591 \\ -fno-reference-trace Disable reference trace591 \\ -fno-reference-trace Disable reference trace
592 \\ -ffunction-sections Places each function in a separate section592 \\ -ffunction-sections Places each function in a separate section
593 \\ -fno-function-sections All functions go into same section593 \\ -fno-function-sections All functions go into same section
594 \\ -fdata-sections Places each data in a separate section594 \\ -fdata-sections Places each data in a separate section
595 \\ -fno-data-sections All data go into same section595 \\ -fno-data-sections All data go into same section
596 \\ -mexec-model=[value] (WASI) Execution model596 \\ -fpatchable-function-entry=[num] Add num NOPs of padding in function prologues
597 \\ -municode (Windows) Use wmain/wWinMain as entry point597 \\ -mexec-model=[value] (WASI) Execution model
598 \\ --time-report Send timing diagnostics to '--listen' clients598 \\ -municode (Windows) Use wmain/wWinMain as entry point
599 \\ --time-report Send timing diagnostics to '--listen' clients
599 \\600 \\
600 \\Per-Module Compile Options:601 \\Per-Module Compile Options:
601 \\ --dep [[import=]name] Add an entry to the next module's import table602 \\ --dep [[import=]name] Add an entry to the next module's import table
...@@ -1705,6 +1706,10 @@ fn buildOutputType(...@@ -1705,6 +1706,10 @@ fn buildOutputType(
1705 } else if (mem.cutPrefix(u8, arg, "-fopt-bisect-limit=")) |next_arg| {1706 } else if (mem.cutPrefix(u8, arg, "-fopt-bisect-limit=")) |next_arg| {
1706 llvm_opt_bisect_limit = std.fmt.parseInt(c_int, next_arg, 0) catch |err|1707 llvm_opt_bisect_limit = std.fmt.parseInt(c_int, next_arg, 0) catch |err|
1707 fatal("unable to parse {q}: {t}", .{ arg, err });1708 fatal("unable to parse {q}: {t}", .{ arg, err });
1709 } else if (mem.cutPrefix(u8, arg, "-fpatchable-function-entry=")) |num| {
1710 mod_opts.patchable_function_entry = std.fmt.parseUnsigned(u16, num, 10) catch |err| {
1711 fatal("unable to parse patchable-function-entry count {q}: {t}", .{ num, err });
1712 };
1708 } else if (mem.eql(u8, arg, "--eh-frame-hdr")) {1713 } else if (mem.eql(u8, arg, "--eh-frame-hdr")) {
1709 link_eh_frame_hdr = true;1714 link_eh_frame_hdr = true;
1710 } else if (mem.eql(u8, arg, "--no-eh-frame-hdr")) {1715 } else if (mem.eql(u8, arg, "--no-eh-frame-hdr")) {
...@@ -2175,6 +2180,14 @@ fn buildOutputType(...@@ -2175,6 +2180,14 @@ fn buildOutputType(
2175 } else {2180 } else {
2176 mod_opts.unwind_tables = .sync;2181 mod_opts.unwind_tables = .sync;
2177 },2182 },
2183 .patchable_function_entry => {
2184 mod_opts.patchable_function_entry =
2185 std.fmt.parseUnsigned(u16, it.only_arg, 10) catch |err| {
2186 fatal("unable to parse patchable function entry count {q}: {t}", .{
2187 it.only_arg, err,
2188 });
2189 };
2190 },
2178 .nostdlib => {2191 .nostdlib => {
2179 create_module.opts.ensure_libc_on_non_freestanding = false;2192 create_module.opts.ensure_libc_on_non_freestanding = false;
2180 create_module.opts.ensure_libcpp_on_non_freestanding = false;2193 create_module.opts.ensure_libcpp_on_non_freestanding = false;
...@@ -4325,6 +4338,7 @@ fn createModule(...@@ -4325,6 +4338,7 @@ fn createModule(
4325 error.StackCheckUnsupportedByTarget => fatal("unable to create module {q}: the selected target does not support stack checking", .{name}),4338 error.StackCheckUnsupportedByTarget => fatal("unable to create module {q}: the selected target does not support stack checking", .{name}),
4326 error.StackProtectorUnsupportedByTarget => fatal("unable to create module {q}: the selected target does not support stack protection", .{name}),4339 error.StackProtectorUnsupportedByTarget => fatal("unable to create module {q}: the selected target does not support stack protection", .{name}),
4327 error.StackProtectorUnavailableWithoutLibC => fatal("unable to create module {q}: enabling stack protection requires libc", .{name}),4340 error.StackProtectorUnavailableWithoutLibC => fatal("unable to create module {q}: enabling stack protection requires libc", .{name}),
4341 error.PatchableFunctionEntryUnsupportedByBackend => fatal("unable to create module {q}: patchable function entries are unsupported by the selected backend", .{name}),
4328 error.OutOfMemory => |e| return e,4342 error.OutOfMemory => |e| return e,
4329 };4343 };
4330 cli_mod.resolved = mod;4344 cli_mod.resolved = mod;
tools/update_clang_options.zig+4
...@@ -594,6 +594,10 @@ const known_options = [_]KnownOpt{...@@ -594,6 +594,10 @@ const known_options = [_]KnownOpt{
594 .name = "version",594 .name = "version",
595 .ident = "version",595 .ident = "version",
596 },596 },
597 .{
598 .name = "fpatchable-function-entry",
599 .ident = "patchable_function_entry",
600 },
597};601};
598602
599const blacklisted_options = [_][]const u8{};603const blacklisted_options = [_][]const u8{};