Skip to content

Commit c019886

Browse files
committed
Add unstable hotpatch flag.
1 parent f21fbac commit c019886

File tree

16 files changed

+229
-1
lines changed

16 files changed

+229
-1
lines changed

compiler/rustc_codegen_llvm/src/attributes.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -378,6 +378,15 @@ pub(crate) fn llfn_attrs_from_instance<'ll, 'tcx>(
378378
to_add.push(llvm::CreateAttrString(cx.llcx, "use-sample-profile"));
379379
}
380380

381+
// patchable-function is only implemented on x86 on LLVM
382+
if cx.sess().opts.unstable_opts.hotpatch && cx.sess().target.is_x86() {
383+
to_add.push(llvm::CreateAttrStringValue(
384+
cx.llcx,
385+
"patchable-function",
386+
"prologue-short-redirect",
387+
));
388+
}
389+
381390
// FIXME: none of these functions interact with source level attributes.
382391
to_add.extend(frame_pointer_type_attr(cx));
383392
to_add.extend(function_return_attr(cx));

compiler/rustc_codegen_llvm/src/back/owned_target_machine.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ impl OwnedTargetMachine {
3434
emit_stack_size_section: bool,
3535
relax_elf_relocations: bool,
3636
use_init_array: bool,
37+
is_hotpatchable: bool,
3738
split_dwarf_file: &CStr,
3839
output_obj_file: &CStr,
3940
debug_info_compression: &CStr,
@@ -66,6 +67,7 @@ impl OwnedTargetMachine {
6667
emit_stack_size_section,
6768
relax_elf_relocations,
6869
use_init_array,
70+
is_hotpatchable,
6971
split_dwarf_file.as_ptr(),
7072
output_obj_file.as_ptr(),
7173
debug_info_compression.as_ptr(),

compiler/rustc_codegen_llvm/src/back/write.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,11 @@ pub(crate) fn target_machine_factory(
244244
let use_init_array =
245245
!sess.opts.unstable_opts.use_ctors_section.unwrap_or(sess.target.use_ctors_section);
246246

247+
// this makes LLVM add a hotpatch flag in the codeview S_COMPILE3 record,
248+
// which is required by linkers for the functionpadmin option
249+
// aarch64 is always hotpatchable
250+
let is_hotpatchable = sess.opts.unstable_opts.hotpatch || sess.target.arch.contains("aarch64");
251+
247252
let path_mapping = sess.source_map().path_mapping().clone();
248253

249254
let use_emulated_tls = matches!(sess.tls_model(), TlsModel::Emulated);
@@ -316,6 +321,7 @@ pub(crate) fn target_machine_factory(
316321
emit_stack_size_section,
317322
relax_elf_relocations,
318323
use_init_array,
324+
is_hotpatchable,
319325
&split_dwarf_file,
320326
&output_obj_file,
321327
&debuginfo_compression,

compiler/rustc_codegen_llvm/src/llvm/ffi.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2419,6 +2419,7 @@ unsafe extern "C" {
24192419
EmitStackSizeSection: bool,
24202420
RelaxELFRelocations: bool,
24212421
UseInitArray: bool,
2422+
IsHotpatchable: bool,
24222423
SplitDwarfFile: *const c_char,
24232424
OutputObjFile: *const c_char,
24242425
DebugInfoCompression: *const c_char,

compiler/rustc_interface/src/tests.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -804,6 +804,7 @@ fn test_unstable_options_tracking_hash() {
804804
tracked!(function_return, FunctionReturn::ThunkExtern);
805805
tracked!(function_sections, Some(false));
806806
tracked!(hint_mostly_unused, true);
807+
tracked!(hotpatch, true);
807808
tracked!(human_readable_cgu_names, true);
808809
tracked!(incremental_ignore_spans, true);
809810
tracked!(inline_mir, Some(true));

compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -394,7 +394,7 @@ extern "C" LLVMTargetMachineRef LLVMRustCreateTargetMachine(
394394
bool FunctionSections, bool DataSections, bool UniqueSectionNames,
395395
bool TrapUnreachable, bool Singlethread, bool VerboseAsm,
396396
bool EmitStackSizeSection, bool RelaxELFRelocations, bool UseInitArray,
397-
const char *SplitDwarfFile, const char *OutputObjFile,
397+
bool IsHotpatchable, const char *SplitDwarfFile, const char *OutputObjFile,
398398
const char *DebugInfoCompression, bool UseEmulatedTls,
399399
const char *ArgsCstrBuff, size_t ArgsCstrBuffLen) {
400400

@@ -422,6 +422,7 @@ extern "C" LLVMTargetMachineRef LLVMRustCreateTargetMachine(
422422
// Always preserve comments that were written by the user
423423
Options.MCOptions.PreserveAsmComments = true;
424424
Options.MCOptions.ABIName = ABIStr;
425+
Options.Hotpatch = IsHotpatchable;
425426
if (SplitDwarfFile) {
426427
Options.MCOptions.SplitDwarfFile = SplitDwarfFile;
427428
}

compiler/rustc_session/src/options.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2258,6 +2258,10 @@ options! {
22582258
"explicitly enable the `cfg(target_thread_local)` directive"),
22592259
hint_mostly_unused: bool = (false, parse_bool, [TRACKED],
22602260
"hint that most of this crate will go unused, to minimize work for uncalled functions"),
2261+
hotpatch: bool = (false, parse_bool, [TRACKED],
2262+
"ensures hotpatching is always possible by ensuring that the first instruction of \
2263+
each function is at least two bytes, and no jump within the function goes to the first instruction. \
2264+
Should be combined with link-arg passing -functionpadmin to the linker. Currently only supported for x86 (default: false)"),
22612265
human_readable_cgu_names: bool = (false, parse_bool, [TRACKED],
22622266
"generate human-readable, predictable names for codegen units (default: no)"),
22632267
identify_regions: bool = (false, parse_bool, [UNTRACKED],

compiler/rustc_target/src/spec/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2238,6 +2238,9 @@ impl Target {
22382238

22392239
Ok(dl)
22402240
}
2241+
pub fn is_x86(&self) -> bool {
2242+
["x86", "x86_64"].contains(&&self.arch[..])
2243+
}
22412244
}
22422245

22432246
pub trait HasTargetSpec {

src/tools/run-make-support/src/external_deps/llvm.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,13 @@ impl LlvmFilecheck {
282282
self
283283
}
284284

285+
/// Specify the prefix (without :) for patterns to match. By default, these patterns are prefixed with "CHECK:".
286+
pub fn check_prefix(&mut self, prefix: &str) -> &mut Self {
287+
self.cmd.arg("--check-prefix");
288+
self.cmd.arg(prefix);
289+
self
290+
}
291+
285292
/// `--input-file` option.
286293
pub fn input_file<P: AsRef<Path>>(&mut self, input_file: P) -> &mut Self {
287294
self.cmd.arg("--input-file");

tests/codegen/hotpatch.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// check if functions get the attribute, so that LLVM ensures they are hotpatchable
2+
// the attribute is only implemented for x86, aarch64 does not require it
3+
4+
//@ revisions: x32 x64
5+
//@[x32] only-x86
6+
//@[x64] only-x86_64
7+
//@ compile-flags: -Z hotpatch
8+
9+
#![crate_type = "lib"]
10+
11+
#[no_mangle]
12+
pub fn foo() {}
13+
14+
// CHECK-LABEL: @foo() unnamed_addr #0
15+
// CHECK: attributes #0 = { {{.*}} "patchable-function"="prologue-short-redirect" {{.*}}}

0 commit comments

Comments
 (0)