| author | |
| committer | |
| log | 39512c3e5547b411294369c8eec8093045f74d64 |
| tree | ed239d2a11a5fddc1abbf0dc3db3479d7f283658 |
| parent | 2ec5523d5a70db80bac8563e1f06d3b164f53db3 |
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 | } |
| 1281 | 1281 | ||
| 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, | ||
| 1655 | 1656 | ||
| 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, |
| 42 | link_libc: ?bool, | 42 | link_libc: ?bool, |
| 43 | link_libcpp: ?bool, | 43 | link_libcpp: ?bool, |
| 44 | no_builtin: ?bool, | 44 | no_builtin: ?bool, |
| 45 | patchable_function_entry: u16, | ||
| 45 | 46 | ||
| 46 | /// Symbols to be exported when compiling to WebAssembly. | 47 | /// Symbols to be exported when compiling to WebAssembly. |
| 47 | export_symbol_names: []const []const u8 = &.{}, | 48 | export_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 | }; |
| 234 | 236 | ||
| 235 | pub const Import = struct { | 237 | pub 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 | }; |
| 282 | 285 | ||
| 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 | }); |
| 1247 | 1248 | ||
| 1248 | // The import table is the only place that modules can form dependency | 1249 | // 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 | }; |
| 1206 | 1207 | ||
| 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_builtin | 261 | #define zig_no_builtin |
| 262 | #endif | 262 | #endif |
| 263 | 263 | ||
| 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 | } |
| 1311 | 1312 | ||
| ... | @@ -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 | }; |
| 2089 | 2094 | ||
| 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 | } |
| 6641 | 6646 | ||
| 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); |
| 6643 | 6653 | ||
| 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, |
| 43 | unwind_tables: std.lang.UnwindTables, | 43 | unwind_tables: std.lang.UnwindTables, |
| 44 | cc_argv: []const []const u8, | 44 | cc_argv: []const []const u8, |
| 45 | no_builtin: bool, | 45 | no_builtin: bool, |
| 46 | patchable_function_entry: u16, | ||
| 46 | 47 | ||
| 47 | pub const Deps = std.array_hash_map.String(*Module); | 48 | pub const Deps = std.array_hash_map.String(*Module); |
| 48 | 49 | ||
| ... | @@ -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 | }; |
| 89 | 91 | ||
| ... | @@ -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 | }; |
| 111 | 114 | ||
| 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 | }; |
| 326 | 329 | ||
| 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( |
| 7757 | 7757 | ||
| 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 and | 7766 | while (save_index < saves.len) if (save_index + 2 <= saves.len and |
| 7762 | saves[save_index + 0].class == saves[save_index + 1].class and | 7767 | 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); |
| 1736 | 1736 | ||
| 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". In | 2231 | // `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. |
| 4757 | pub fn layout(isel: *Select, cc_it: CallAbiIterator, mod: *const Module) !usize { | 4757 | pub 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 | } |
| 4884 | 4887 |
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 | } |
| 1128 | 1128 | ||
| 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); |
| 1131 | 1142 |
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 files | 567 | \\ --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 src | 573 | \\ "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 paths | 575 | \\ --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 values | 577 | \\ --error-limit [num] Set the maximum amount of distinct error values |
| 578 | \\ -fllvm Force using LLVM as the codegen backend | 578 | \\ -fllvm Force using LLVM as the codegen backend |
| 579 | \\ -fno-llvm Prevent using LLVM as the codegen backend | 579 | \\ -fno-llvm Prevent using LLVM as the codegen backend |
| 580 | \\ -flibllvm Force using the LLVM API in the codegen backend | 580 | \\ -flibllvm Force using the LLVM API in the codegen backend |
| 581 | \\ -fno-libllvm Prevent using the LLVM API in the codegen backend | 581 | \\ -fno-libllvm Prevent using the LLVM API in the codegen backend |
| 582 | \\ -fclang Force using Clang as the C/C++ compilation backend | 582 | \\ -fclang Force using Clang as the C/C++ compilation backend |
| 583 | \\ -fno-clang Prevent using Clang as the C/C++ compilation backend | 583 | \\ -fno-clang Prevent using Clang as the C/C++ compilation backend |
| 584 | \\ -fPIE Force-enable Position Independent Executable | 584 | \\ -fPIE Force-enable Position Independent Executable |
| 585 | \\ -fno-PIE Force-disable Position Independent Executable | 585 | \\ -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 Optimization | 587 | \\ -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 exports | 589 | \\ -fno-dll-export-fns Force-disable marking exported functions as DLL exports |
| 590 | \\ -freference-trace[=num] Show num lines of reference trace per compile error | 590 | \\ -freference-trace[=num] Show num lines of reference trace per compile error |
| 591 | \\ -fno-reference-trace Disable reference trace | 591 | \\ -fno-reference-trace Disable reference trace |
| 592 | \\ -ffunction-sections Places each function in a separate section | 592 | \\ -ffunction-sections Places each function in a separate section |
| 593 | \\ -fno-function-sections All functions go into same section | 593 | \\ -fno-function-sections All functions go into same section |
| 594 | \\ -fdata-sections Places each data in a separate section | 594 | \\ -fdata-sections Places each data in a separate section |
| 595 | \\ -fno-data-sections All data go into same section | 595 | \\ -fno-data-sections All data go into same section |
| 596 | \\ -mexec-model=[value] (WASI) Execution model | 596 | \\ -fpatchable-function-entry=[num] Add num NOPs of padding in function prologues |
| 597 | \\ -municode (Windows) Use wmain/wWinMain as entry point | 597 | \\ -mexec-model=[value] (WASI) Execution model |
| 598 | \\ --time-report Send timing diagnostics to '--listen' clients | 598 | \\ -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 table | 602 | \\ --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 | }; |
| 598 | 602 | ||
| 599 | const blacklisted_options = [_][]const u8{}; | 603 | const blacklisted_options = [_][]const u8{}; |