From b473e9c4425c61168ab5295efb47a2009aaf334c Mon Sep 17 00:00:00 2001 From: Florian Schmiderer Date: Tue, 30 Apr 2024 20:44:07 +0200 Subject: [PATCH 01/10] Add hotpatch flag. Proof of concept only working on x86/x64. --- compiler/rustc_codegen_llvm/src/attributes.rs | 9 +++++++++ .../src/back/owned_target_machine.rs | 2 ++ compiler/rustc_codegen_llvm/src/back/write.rs | 5 +++++ compiler/rustc_codegen_llvm/src/llvm/ffi.rs | 1 + compiler/rustc_interface/src/tests.rs | 1 + compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp | 3 ++- compiler/rustc_session/src/options.rs | 4 ++++ compiler/rustc_target/src/spec/mod.rs | 3 +++ tests/codegen/hotpatch.rs | 12 ++++++++++++ 9 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 tests/codegen/hotpatch.rs diff --git a/compiler/rustc_codegen_llvm/src/attributes.rs b/compiler/rustc_codegen_llvm/src/attributes.rs index 2c5ec9dad59f1..1d2e39119817a 100644 --- a/compiler/rustc_codegen_llvm/src/attributes.rs +++ b/compiler/rustc_codegen_llvm/src/attributes.rs @@ -378,6 +378,15 @@ pub(crate) fn llfn_attrs_from_instance<'ll, 'tcx>( to_add.push(llvm::CreateAttrString(cx.llcx, "use-sample-profile")); } + // patchable-function is only implemented on x86 on LLVM + if cx.sess().opts.unstable_opts.hotpatch && cx.sess().target.is_x86() { + to_add.push(llvm::CreateAttrStringValue( + cx.llcx, + "patchable-function", + "prologue-short-redirect", + )); + } + // FIXME: none of these functions interact with source level attributes. to_add.extend(frame_pointer_type_attr(cx)); to_add.extend(function_return_attr(cx)); diff --git a/compiler/rustc_codegen_llvm/src/back/owned_target_machine.rs b/compiler/rustc_codegen_llvm/src/back/owned_target_machine.rs index 44c30d22a9e9c..07571d21de0ce 100644 --- a/compiler/rustc_codegen_llvm/src/back/owned_target_machine.rs +++ b/compiler/rustc_codegen_llvm/src/back/owned_target_machine.rs @@ -35,6 +35,7 @@ impl OwnedTargetMachine { emit_stack_size_section: bool, relax_elf_relocations: bool, use_init_array: bool, + use_hotpatch: bool, split_dwarf_file: &CStr, output_obj_file: &CStr, debug_info_compression: &CStr, @@ -67,6 +68,7 @@ impl OwnedTargetMachine { emit_stack_size_section, relax_elf_relocations, use_init_array, + use_hotpatch, split_dwarf_file.as_ptr(), output_obj_file.as_ptr(), debug_info_compression.as_ptr(), diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs index afdd2b581b86e..3a732c602559e 100644 --- a/compiler/rustc_codegen_llvm/src/back/write.rs +++ b/compiler/rustc_codegen_llvm/src/back/write.rs @@ -225,6 +225,10 @@ pub(crate) fn target_machine_factory( let use_init_array = !sess.opts.unstable_opts.use_ctors_section.unwrap_or(sess.target.use_ctors_section); + // this annotes in the debug file that code is hotpatchable. In addtion without it -functionpadmin will be ignored. + // See: https://github.com/llvm/llvm-project/blob/d703b922961e0d02a5effdd4bfbb23ad50a3cc9f/lld/COFF/Writer.cpp#L1298 + let use_hotpatch = sess.opts.unstable_opts.hotpatch && sess.target.is_x86(); + let path_mapping = sess.source_map().path_mapping().clone(); let use_emulated_tls = matches!(sess.tls_model(), TlsModel::Emulated); @@ -297,6 +301,7 @@ pub(crate) fn target_machine_factory( emit_stack_size_section, relax_elf_relocations, use_init_array, + use_hotpatch, &split_dwarf_file, &output_obj_file, &debuginfo_compression, diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 661debbb9f126..68bae8dc3ae7a 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -2170,6 +2170,7 @@ unsafe extern "C" { EmitStackSizeSection: bool, RelaxELFRelocations: bool, UseInitArray: bool, + UseHotpatch: bool, SplitDwarfFile: *const c_char, OutputObjFile: *const c_char, DebugInfoCompression: *const c_char, diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 536ce154cd071..b030271a64245 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -788,6 +788,7 @@ fn test_unstable_options_tracking_hash() { tracked!(fuel, Some(("abc".to_string(), 99))); tracked!(function_return, FunctionReturn::ThunkExtern); tracked!(function_sections, Some(false)); + tracked!(hotpatch, true); tracked!(human_readable_cgu_names, true); tracked!(incremental_ignore_spans, true); tracked!(inline_in_all_cgus, Some(true)); diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp index 8f0b1b8127657..aee772e4c44ca 100644 --- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp @@ -395,7 +395,7 @@ extern "C" LLVMTargetMachineRef LLVMRustCreateTargetMachine( LLVMRustCodeGenOptLevel RustOptLevel, bool UseSoftFloat, bool FunctionSections, bool DataSections, bool UniqueSectionNames, bool TrapUnreachable, bool Singlethread, bool VerboseAsm, - bool EmitStackSizeSection, bool RelaxELFRelocations, bool UseInitArray, + bool EmitStackSizeSection, bool RelaxELFRelocations, bool UseInitArray, bool UseHotpatch, const char *SplitDwarfFile, const char *OutputObjFile, const char *DebugInfoCompression, bool UseEmulatedTls, const char *ArgsCstrBuff, size_t ArgsCstrBuffLen) { @@ -426,6 +426,7 @@ extern "C" LLVMTargetMachineRef LLVMRustCreateTargetMachine( // Always preserve comments that were written by the user Options.MCOptions.PreserveAsmComments = true; Options.MCOptions.ABIName = ABIStr; + Options.Hotpatch = UseHotpatch; if (SplitDwarfFile) { Options.MCOptions.SplitDwarfFile = SplitDwarfFile; } diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index d63276db4938b..e520154fb78cf 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -1810,6 +1810,10 @@ options! { "explicitly enable the `cfg(target_thread_local)` directive"), hir_stats: bool = (false, parse_bool, [UNTRACKED], "print some statistics about AST and HIR (default: no)"), + hotpatch: bool = (false, parse_bool, [TRACKED], + "ensures hotpatching is always possible by ensuring that the first instruction of \ + each function is at least two bytes, and no jump within the function goes to the first instruction. \ + Should be combined with link-arg passing -functionpadmin to the linker. Currently only supported for x86 (default: false)"), human_readable_cgu_names: bool = (false, parse_bool, [TRACKED], "generate human-readable, predictable names for codegen units (default: no)"), identify_regions: bool = (false, parse_bool, [UNTRACKED], diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 82e11a3afce32..77b1be581c3fb 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -2070,6 +2070,9 @@ impl Target { Ok(dl) } + pub fn is_x86(&self) -> bool { + ["x86", "x86_64"].contains(&&self.arch[..]) + } } pub trait HasTargetSpec { diff --git a/tests/codegen/hotpatch.rs b/tests/codegen/hotpatch.rs new file mode 100644 index 0000000000000..91d6ac8759d67 --- /dev/null +++ b/tests/codegen/hotpatch.rs @@ -0,0 +1,12 @@ +//@ revisions: x32 x64 +//@[x32] only-x86 +//@[x64] only-x86_64 +//@ compile-flags: -Z hotpatch + +#![crate_type = "lib"] + +#[no_mangle] +pub fn foo() {} + +// CHECK: @foo() unnamed_addr #0 +// CHECK: attributes #0 = { {{.*}} "patchable-function"="prologue-short-redirect" {{.*}}} From ef9f88fac2e4f7a4662ef2f994c41e51e9b57316 Mon Sep 17 00:00:00 2001 From: Florian Schmiderer Date: Wed, 3 Jul 2024 12:21:53 +0200 Subject: [PATCH 02/10] tidy --- compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp index aee772e4c44ca..354d61bd36fc8 100644 --- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp @@ -395,8 +395,8 @@ extern "C" LLVMTargetMachineRef LLVMRustCreateTargetMachine( LLVMRustCodeGenOptLevel RustOptLevel, bool UseSoftFloat, bool FunctionSections, bool DataSections, bool UniqueSectionNames, bool TrapUnreachable, bool Singlethread, bool VerboseAsm, - bool EmitStackSizeSection, bool RelaxELFRelocations, bool UseInitArray, bool UseHotpatch, - const char *SplitDwarfFile, const char *OutputObjFile, + bool EmitStackSizeSection, bool RelaxELFRelocations, bool UseInitArray, + bool UseHotpatch, const char *SplitDwarfFile, const char *OutputObjFile, const char *DebugInfoCompression, bool UseEmulatedTls, const char *ArgsCstrBuff, size_t ArgsCstrBuffLen) { From 068ecd4ffbfb6859db213b60052a3356381b82b3 Mon Sep 17 00:00:00 2001 From: Florian Schmiderer Date: Sun, 22 Sep 2024 14:07:06 +0200 Subject: [PATCH 03/10] Added tests to validate functions are hotpatchable --- .../src/external_deps/llvm.rs | 7 ++ tests/run-make/hotpatch/lib.rs | 64 +++++++++++++++++++ tests/run-make/hotpatch/rmake.rs | 44 +++++++++++++ 3 files changed, 115 insertions(+) create mode 100644 tests/run-make/hotpatch/lib.rs create mode 100644 tests/run-make/hotpatch/rmake.rs diff --git a/src/tools/run-make-support/src/external_deps/llvm.rs b/src/tools/run-make-support/src/external_deps/llvm.rs index 38a9ac923b4dc..d644488548251 100644 --- a/src/tools/run-make-support/src/external_deps/llvm.rs +++ b/src/tools/run-make-support/src/external_deps/llvm.rs @@ -254,6 +254,13 @@ impl LlvmFilecheck { self } + /// Specify the prefix (without :) for patterns to match. By default, these patterns are prefixed with "CHECK:". + pub fn check_prefix(&mut self, prefix: &str) -> &mut Self { + self.cmd.arg("--check-prefix"); + self.cmd.arg(prefix); + self + } + /// `--input-file` option. pub fn input_file>(&mut self, input_file: P) -> &mut Self { self.cmd.arg("--input-file"); diff --git a/tests/run-make/hotpatch/lib.rs b/tests/run-make/hotpatch/lib.rs new file mode 100644 index 0000000000000..6a0d0ce550823 --- /dev/null +++ b/tests/run-make/hotpatch/lib.rs @@ -0,0 +1,64 @@ +// hotpatch has two requirements: +// 1. the first instruction of a functin must be at least two bytes long +// 2. there must not be a jump to the first instruction + +// the hotpatch flag should insert nops as needed to fullfil the requirements, +// but only if the the function does not already fulfill them. +// Over 99% of function in regular codebases already fulfill the conditions, +// so its important to check that those are +// unneccessarily affected + +// ------------------------------------------------------------------------------------------------ + +// regularly this tailcall would jump to the first instruction the function +// CHECK-LABEL: : +// CHECK: jne 0x0 + +// hotpatch insert nops so that the tailcall will not jump to the first instruction of the function +// HOTPATCH-LABEL: : +// HOTPATCH-NOT: jne 0x0 + +#[no_mangle] +pub fn tailcall_fn() { + use std::sync::atomic::{AtomicUsize, Ordering}; + static COUNT: AtomicUsize = AtomicUsize::new(0); + if COUNT.fetch_sub(1, Ordering::Relaxed) != 0 { + tailcall_fn() + } +} + +// ------------------------------------------------------------------------------------------------ + +// empty_fn just returns. Note that 'ret' is a single byte instruction, but hotpatch requires a two +// or more byte instructions to be at the start of the functions. +// Preferably we would also tests a different single byte instruction, +// but I was not able to make rustc emit anything but 'ret'. + +// CHECK-LABEL: : +// CHECK-NEXT: ret + +// HOTPATCH-LABEL: : +// HOTPATCH-NOT: ret +// HOTPATCH: ret + +#[no_mangle] +#[inline(never)] +pub fn empty_fn() {} + +// ------------------------------------------------------------------------------------------------ + +// return_42 should not be affected by hotpatch + +// CHECK-LABEL: : +// CHECK-NEXT: 0: +// CHECK-NEXT: ret + +// HOTPATCH-LABEL: : +// HOTPATCH-NEXT: 0: +// HOTPATCH-NEXT: ret + +#[no_mangle] +#[inline(never)] +pub fn return_42() -> i32 { + 42 +} diff --git a/tests/run-make/hotpatch/rmake.rs b/tests/run-make/hotpatch/rmake.rs new file mode 100644 index 0000000000000..65635b3afcba9 --- /dev/null +++ b/tests/run-make/hotpatch/rmake.rs @@ -0,0 +1,44 @@ +// Check if hotpatch only makes the functions hotpachable that were not, +// but leaving the other functions untouched +// More details in lib.rs + +//@ revisions: x32 x64 +//@[x32] only-x86 +//@[x64] only-x86_64 +// Reason: hotpatch is only implemented for X86 + +use run_make_support::{llvm, rfs, rustc}; + +fn main() { + { + rustc().input("lib.rs").crate_name("regular").crate_type("lib").opt_level("3").run(); + + let regular_dump = llvm::llvm_objdump() + .arg("--disassemble-symbols=tailcall_fn,empty_fn,return_42") + .input("libregular.rlib") + .run(); + + llvm::llvm_filecheck().patterns("lib.rs").stdin_buf(regular_dump.stdout_utf8()).run(); + } + + { + rustc() + .input("lib.rs") + .crate_name("hotpatch") + .crate_type("lib") + .opt_level("3") + .arg("-Zhotpatch") + .run(); + + let hotpatch_dump = llvm::llvm_objdump() + .arg("--disassemble-symbols=tailcall_fn,empty_fn,return_42") + .input("libhotpatch.rlib") + .run(); + + llvm::llvm_filecheck() + .patterns("lib.rs") + .check_prefix("HOTPATCH") + .stdin_buf(hotpatch_dump.stdout_utf8()) + .run(); + } +} From 8d9009f24b2ed5dcff7aeb19a1a3b7f919b4f990 Mon Sep 17 00:00:00 2001 From: Florian Schmiderer Date: Mon, 23 Sep 2024 20:43:01 +0200 Subject: [PATCH 04/10] seperated hotpatch test types, improved tests --- tests/run-make/hotpatch-unaffected/lib.rs | 25 ++++++++++ tests/run-make/hotpatch-unaffected/rmake.rs | 53 +++++++++++++++++++++ tests/run-make/hotpatch/lib.rs | 33 ++++--------- tests/run-make/hotpatch/rmake.rs | 17 ++++--- 4 files changed, 96 insertions(+), 32 deletions(-) create mode 100644 tests/run-make/hotpatch-unaffected/lib.rs create mode 100644 tests/run-make/hotpatch-unaffected/rmake.rs diff --git a/tests/run-make/hotpatch-unaffected/lib.rs b/tests/run-make/hotpatch-unaffected/lib.rs new file mode 100644 index 0000000000000..d441d3e412544 --- /dev/null +++ b/tests/run-make/hotpatch-unaffected/lib.rs @@ -0,0 +1,25 @@ +// hotpatch has two requirements: +// 1. the first instruction of a functin must be at least two bytes long +// 2. there must not be a jump to the first instruction + +// the functions in this file already fulfill the conditions so hotpatch should not affect them + +// -------------------------------------------------------------------------------------------- + +#[no_mangle] +#[inline(never)] +pub fn return_42() -> i32 { + 42 +} + +// -------------------------------------------------------------------------------------------- +// This tailcall does not jump to the first instruction so hotpatch should leave it unaffected + +#[no_mangle] +pub fn tailcall(a: i32) -> i32 { + if a > 10000 { + return a; + } + + if a % 2 == 0 { tailcall(a / 2) } else { tailcall(a * 3 + 1) } +} diff --git a/tests/run-make/hotpatch-unaffected/rmake.rs b/tests/run-make/hotpatch-unaffected/rmake.rs new file mode 100644 index 0000000000000..30de06a391fdd --- /dev/null +++ b/tests/run-make/hotpatch-unaffected/rmake.rs @@ -0,0 +1,53 @@ +// Check if hotpatch leaves the functions that are already hotpatchable untouched + +//@ revisions: x32 x64 +//@[x32] only-x86 +//@[x64] only-x86_64 +// Reason: hotpatch is only implemented for X86 + +use run_make_support::{assertion_helpers, llvm, rustc}; + +fn main() { + let disassemble_symbols_arg = "--disassemble-symbols=return_42,tailcall"; + + rustc().input("lib.rs").crate_name("regular").crate_type("lib").opt_level("3").run(); + + let regular_dump = llvm::llvm_objdump() + .arg(disassemble_symbols_arg) + .input("libregular.rlib") + .run() + .stdout_utf8(); + + rustc() + .input("lib.rs") + .crate_name("hotpatch") + .crate_type("lib") + .opt_level("3") + .arg("-Zhotpatch") + .run(); + + let hotpatch_dump = llvm::llvm_objdump() + .arg(disassemble_symbols_arg) + .input("libhotpatch.rlib") + .run() + .stdout_utf8(); + + { + let mut lines_regular = regular_dump.lines(); + let mut lines_hotpatch = hotpatch_dump.lines(); + + loop { + match (lines_regular.next(), lines_hotpatch.next()) { + (None, None) => break, + (Some(r), Some(h)) => { + if r.contains("libregular.rlib") { + assertion_helpers::assert_contains(h, "libhotpatch.rlib") + } else { + assertion_helpers::assert_equals(&r, &h) + } + } + _ => panic!("the files should have equal length"), + } + } + } +} diff --git a/tests/run-make/hotpatch/lib.rs b/tests/run-make/hotpatch/lib.rs index 6a0d0ce550823..365c145e0424b 100644 --- a/tests/run-make/hotpatch/lib.rs +++ b/tests/run-make/hotpatch/lib.rs @@ -8,7 +8,7 @@ // so its important to check that those are // unneccessarily affected -// ------------------------------------------------------------------------------------------------ +// ---------------------------------------------------------------------------------------------- // regularly this tailcall would jump to the first instruction the function // CHECK-LABEL: : @@ -27,38 +27,21 @@ pub fn tailcall_fn() { } } -// ------------------------------------------------------------------------------------------------ +// ---------------------------------------------------------------------------------------------- -// empty_fn just returns. Note that 'ret' is a single byte instruction, but hotpatch requires a two -// or more byte instructions to be at the start of the functions. +// empty_fn just returns. Note that 'ret' is a single byte instruction, but hotpatch requires +// a two or more byte instructions to be at the start of the functions. // Preferably we would also tests a different single byte instruction, // but I was not able to make rustc emit anything but 'ret'. +// check that if the first instruction is just a single byte, so our test is valid // CHECK-LABEL: : -// CHECK-NEXT: ret +// CHECK-NOT: 0: {{[0-9a-f][0-9a-f]}} {{[0-9a-f][0-9a-f]}} {{.*}} +// check that the first instruction is at least 2 bytes long // HOTPATCH-LABEL: : -// HOTPATCH-NOT: ret -// HOTPATCH: ret +// HOTPATCH-NEXT: 0: {{[0-9a-f][0-9a-f]}} {{[0-9a-f][0-9a-f]}} {{.*}} #[no_mangle] #[inline(never)] pub fn empty_fn() {} - -// ------------------------------------------------------------------------------------------------ - -// return_42 should not be affected by hotpatch - -// CHECK-LABEL: : -// CHECK-NEXT: 0: -// CHECK-NEXT: ret - -// HOTPATCH-LABEL: : -// HOTPATCH-NEXT: 0: -// HOTPATCH-NEXT: ret - -#[no_mangle] -#[inline(never)] -pub fn return_42() -> i32 { - 42 -} diff --git a/tests/run-make/hotpatch/rmake.rs b/tests/run-make/hotpatch/rmake.rs index 65635b3afcba9..e1352827bce03 100644 --- a/tests/run-make/hotpatch/rmake.rs +++ b/tests/run-make/hotpatch/rmake.rs @@ -7,18 +7,20 @@ //@[x64] only-x86_64 // Reason: hotpatch is only implemented for X86 -use run_make_support::{llvm, rfs, rustc}; +use run_make_support::{llvm, rustc}; fn main() { + let disassemble_symbols_arg = "--disassemble-symbols=tailcall_fn,empty_fn"; { rustc().input("lib.rs").crate_name("regular").crate_type("lib").opt_level("3").run(); let regular_dump = llvm::llvm_objdump() - .arg("--disassemble-symbols=tailcall_fn,empty_fn,return_42") + .arg(disassemble_symbols_arg) .input("libregular.rlib") - .run(); + .run() + .stdout_utf8(); - llvm::llvm_filecheck().patterns("lib.rs").stdin_buf(regular_dump.stdout_utf8()).run(); + llvm::llvm_filecheck().patterns("lib.rs").stdin_buf(regular_dump).run(); } { @@ -31,14 +33,15 @@ fn main() { .run(); let hotpatch_dump = llvm::llvm_objdump() - .arg("--disassemble-symbols=tailcall_fn,empty_fn,return_42") + .arg(disassemble_symbols_arg) .input("libhotpatch.rlib") - .run(); + .run() + .stdout_utf8(); llvm::llvm_filecheck() .patterns("lib.rs") .check_prefix("HOTPATCH") - .stdin_buf(hotpatch_dump.stdout_utf8()) + .stdin_buf(hotpatch_dump) .run(); } } From 06b559a6daf3a7cfa2f1343674927c3e16ece6df Mon Sep 17 00:00:00 2001 From: Florian Schmiderer Date: Mon, 30 Sep 2024 21:20:56 +0200 Subject: [PATCH 05/10] simplified tests --- tests/run-make/hotpatch-unaffected/rmake.rs | 44 ++++++++++----------- tests/run-make/hotpatch/rmake.rs | 36 ++++++++--------- 2 files changed, 36 insertions(+), 44 deletions(-) diff --git a/tests/run-make/hotpatch-unaffected/rmake.rs b/tests/run-make/hotpatch-unaffected/rmake.rs index 30de06a391fdd..d26bcf8ee85c0 100644 --- a/tests/run-make/hotpatch-unaffected/rmake.rs +++ b/tests/run-make/hotpatch-unaffected/rmake.rs @@ -8,29 +8,25 @@ use run_make_support::{assertion_helpers, llvm, rustc}; fn main() { - let disassemble_symbols_arg = "--disassemble-symbols=return_42,tailcall"; - - rustc().input("lib.rs").crate_name("regular").crate_type("lib").opt_level("3").run(); - - let regular_dump = llvm::llvm_objdump() - .arg(disassemble_symbols_arg) - .input("libregular.rlib") - .run() - .stdout_utf8(); - - rustc() - .input("lib.rs") - .crate_name("hotpatch") - .crate_type("lib") - .opt_level("3") - .arg("-Zhotpatch") - .run(); - - let hotpatch_dump = llvm::llvm_objdump() - .arg(disassemble_symbols_arg) - .input("libhotpatch.rlib") - .run() - .stdout_utf8(); + fn base_rustc() -> rustc::Rustc { + let mut rustc = rustc(); + rustc.input("lib.rs").crate_type("lib").opt_level("3"); + rustc + } + + fn dump_lib(libname: &str) -> String { + llvm::llvm_objdump() + .arg("--disassemble-symbols=return_42,tailcall") + .input(libname) + .run() + .stdout_utf8() + } + + base_rustc().crate_name("regular").run(); + let regular_dump = dump_lib("libregular.rlib"); + + base_rustc().crate_name("hotpatch").arg("-Zhotpatch").run(); + let hotpatch_dump = dump_lib("libhotpatch.rlib"); { let mut lines_regular = regular_dump.lines(); @@ -46,7 +42,7 @@ fn main() { assertion_helpers::assert_equals(&r, &h) } } - _ => panic!("the files should have equal length"), + _ => panic!("expected files to have equal number of lines"), } } } diff --git a/tests/run-make/hotpatch/rmake.rs b/tests/run-make/hotpatch/rmake.rs index e1352827bce03..18de5ebac2589 100644 --- a/tests/run-make/hotpatch/rmake.rs +++ b/tests/run-make/hotpatch/rmake.rs @@ -10,33 +10,29 @@ use run_make_support::{llvm, rustc}; fn main() { - let disassemble_symbols_arg = "--disassemble-symbols=tailcall_fn,empty_fn"; - { - rustc().input("lib.rs").crate_name("regular").crate_type("lib").opt_level("3").run(); + fn base_rustc() -> rustc::Rustc { + let mut rustc = rustc(); + rustc.input("lib.rs").crate_type("lib").opt_level("3"); + rustc + } - let regular_dump = llvm::llvm_objdump() - .arg(disassemble_symbols_arg) - .input("libregular.rlib") + fn dump_lib(libname: &str) -> String { + llvm::llvm_objdump() + .arg("--disassemble-symbols=tailcall_fn,empty_fn") + .input(libname) .run() - .stdout_utf8(); + .stdout_utf8() + } + { + base_rustc().crate_name("regular").run(); + let regular_dump = dump_lib("libregular.rlib"); llvm::llvm_filecheck().patterns("lib.rs").stdin_buf(regular_dump).run(); } { - rustc() - .input("lib.rs") - .crate_name("hotpatch") - .crate_type("lib") - .opt_level("3") - .arg("-Zhotpatch") - .run(); - - let hotpatch_dump = llvm::llvm_objdump() - .arg(disassemble_symbols_arg) - .input("libhotpatch.rlib") - .run() - .stdout_utf8(); + base_rustc().crate_name("hotpatch").arg("-Zhotpatch").run(); + let hotpatch_dump = dump_lib("libhotpatch.rlib"); llvm::llvm_filecheck() .patterns("lib.rs") From 13bc99864c33864bdaa9010d8555f5051f2e053a Mon Sep 17 00:00:00 2001 From: Florian Schmiderer Date: Thu, 10 Oct 2024 22:57:06 +0200 Subject: [PATCH 06/10] automatically set hotpatch for aarch64 as it already fulfils the conditions --- compiler/rustc_codegen_llvm/src/back/write.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs index 3a732c602559e..a7dd0b22773ae 100644 --- a/compiler/rustc_codegen_llvm/src/back/write.rs +++ b/compiler/rustc_codegen_llvm/src/back/write.rs @@ -225,9 +225,10 @@ pub(crate) fn target_machine_factory( let use_init_array = !sess.opts.unstable_opts.use_ctors_section.unwrap_or(sess.target.use_ctors_section); - // this annotes in the debug file that code is hotpatchable. In addtion without it -functionpadmin will be ignored. - // See: https://github.com/llvm/llvm-project/blob/d703b922961e0d02a5effdd4bfbb23ad50a3cc9f/lld/COFF/Writer.cpp#L1298 - let use_hotpatch = sess.opts.unstable_opts.hotpatch && sess.target.is_x86(); + // this makes LLVM add a hotpatch flag in the codeview S_COMPILE3 record, + // which is required by linkers for the functionpadmin option + // aarch64 is always hotpatchable + let use_hotpatch = sess.opts.unstable_opts.hotpatch || sess.target.arch.contains("aarch64"); let path_mapping = sess.source_map().path_mapping().clone(); From 8764e73ab662c522bbf5b6358c9dd6b60b4f6423 Mon Sep 17 00:00:00 2001 From: Florian Schmiderer Date: Sat, 12 Oct 2024 17:01:29 +0200 Subject: [PATCH 07/10] added new test. Adjusted test as we dropped the 'no jump to first instruction' condition --- tests/run-make/hotpatch-unaffected/rmake.rs | 6 ++-- tests/run-make/hotpatch/lib.rs | 34 +++++---------------- tests/run-make/hotpatch/rmake.rs | 9 +++--- tests/run-make/hotpatch_pdb/main.rs | 6 ++++ tests/run-make/hotpatch_pdb/rmake.rs | 30 ++++++++++++++++++ 5 files changed, 52 insertions(+), 33 deletions(-) create mode 100644 tests/run-make/hotpatch_pdb/main.rs create mode 100644 tests/run-make/hotpatch_pdb/rmake.rs diff --git a/tests/run-make/hotpatch-unaffected/rmake.rs b/tests/run-make/hotpatch-unaffected/rmake.rs index d26bcf8ee85c0..6f403189595b4 100644 --- a/tests/run-make/hotpatch-unaffected/rmake.rs +++ b/tests/run-make/hotpatch-unaffected/rmake.rs @@ -1,9 +1,11 @@ // Check if hotpatch leaves the functions that are already hotpatchable untouched -//@ revisions: x32 x64 +//@ revisions: x32 x64 aarch64 //@[x32] only-x86 //@[x64] only-x86_64 -// Reason: hotpatch is only implemented for X86 +//@[aarch64] only-aarch64 + +// Reason: hotpatch is only implemented for X86 and aarch64 use run_make_support::{assertion_helpers, llvm, rustc}; diff --git a/tests/run-make/hotpatch/lib.rs b/tests/run-make/hotpatch/lib.rs index 365c145e0424b..627f035fbb66d 100644 --- a/tests/run-make/hotpatch/lib.rs +++ b/tests/run-make/hotpatch/lib.rs @@ -1,38 +1,18 @@ // hotpatch has two requirements: -// 1. the first instruction of a functin must be at least two bytes long -// 2. there must not be a jump to the first instruction +// 1) the first instruction of a functin must be at least two bytes long +// 2) there must not be a jump to the first instruction -// the hotpatch flag should insert nops as needed to fullfil the requirements, -// but only if the the function does not already fulfill them. -// Over 99% of function in regular codebases already fulfill the conditions, -// so its important to check that those are -// unneccessarily affected - -// ---------------------------------------------------------------------------------------------- - -// regularly this tailcall would jump to the first instruction the function -// CHECK-LABEL: : -// CHECK: jne 0x0 - -// hotpatch insert nops so that the tailcall will not jump to the first instruction of the function -// HOTPATCH-LABEL: : -// HOTPATCH-NOT: jne 0x0 - -#[no_mangle] -pub fn tailcall_fn() { - use std::sync::atomic::{AtomicUsize, Ordering}; - static COUNT: AtomicUsize = AtomicUsize::new(0); - if COUNT.fetch_sub(1, Ordering::Relaxed) != 0 { - tailcall_fn() - } -} +// The LLVM attribute we use '"patchable-function", "prologue-short-redirect"' only ensures 1) +// However in practice 2) rarely matters. Its rare that it occurs and the problems it caused can be +// avoided by the hotpatch tool. +// In this test we check if 1) is ensured by inserted nops as needed // ---------------------------------------------------------------------------------------------- // empty_fn just returns. Note that 'ret' is a single byte instruction, but hotpatch requires // a two or more byte instructions to be at the start of the functions. // Preferably we would also tests a different single byte instruction, -// but I was not able to make rustc emit anything but 'ret'. +// but I was not able to find an example with another one byte intstruction. // check that if the first instruction is just a single byte, so our test is valid // CHECK-LABEL: : diff --git a/tests/run-make/hotpatch/rmake.rs b/tests/run-make/hotpatch/rmake.rs index 18de5ebac2589..a88de257f4b3e 100644 --- a/tests/run-make/hotpatch/rmake.rs +++ b/tests/run-make/hotpatch/rmake.rs @@ -1,11 +1,12 @@ -// Check if hotpatch only makes the functions hotpachable that were not, -// but leaving the other functions untouched +// Check if hotpatch makes the functions hotpachable that were not // More details in lib.rs //@ revisions: x32 x64 //@[x32] only-x86 //@[x64] only-x86_64 -// Reason: hotpatch is only implemented for X86 + +// Reason: hotpatch is only implemented for x86 and aarch64, but for aarch64 they +// are always hotpatchable so we don't need to check it use run_make_support::{llvm, rustc}; @@ -18,7 +19,7 @@ fn main() { fn dump_lib(libname: &str) -> String { llvm::llvm_objdump() - .arg("--disassemble-symbols=tailcall_fn,empty_fn") + .arg("--disassemble-symbols=empty_fn") .input(libname) .run() .stdout_utf8() diff --git a/tests/run-make/hotpatch_pdb/main.rs b/tests/run-make/hotpatch_pdb/main.rs new file mode 100644 index 0000000000000..248ccf37d6115 --- /dev/null +++ b/tests/run-make/hotpatch_pdb/main.rs @@ -0,0 +1,6 @@ +// CHECK: S_OBJNAME{{.*}}hotpatch_pdb{{.*}}.o +// CHECK: S_COMPILE3 +// CHECK-NOT: S_ +// CHECK: flags = {{.*}}hot patchable + +pub fn main() {} diff --git a/tests/run-make/hotpatch_pdb/rmake.rs b/tests/run-make/hotpatch_pdb/rmake.rs new file mode 100644 index 0000000000000..6e217baa0d3a9 --- /dev/null +++ b/tests/run-make/hotpatch_pdb/rmake.rs @@ -0,0 +1,30 @@ +// Check if hotpatch flag is present in the Codeview. +// This is need so linkers actually pad functions when given the functionpadmin arg. + +//@ revisions: x32 x64 aarch64 +//@[x32] only-x86 +//@[x64] only-x86_64 +//@[aarch64] only-aarch64 + +// Reason: Hotpatch is only implemented for x86 and aarch64 + +use run_make_support::{llvm, rustc}; + +fn main() { + let output = rustc() + .input("main.rs") + .arg("-g") + .arg("-Zhotpatch") + .crate_name("hotpatch_pdb") + .crate_type("bin") + .run(); + + let pdbutil_output = llvm::llvm_pdbutil() + .arg("dump") + .arg("-symbols") + .input("hotpatch_pdb.pdb") + .run() + .stdout_utf8(); + + llvm::llvm_filecheck().patterns("main.rs").stdin_buf(&pdbutil_output).run(); +} From 4f2ba9c694d83062af50aff90c339fa78073b5e5 Mon Sep 17 00:00:00 2001 From: Florian Schmiderer Date: Sat, 12 Oct 2024 18:18:31 +0200 Subject: [PATCH 08/10] fixed/cleaned up tests --- tests/codegen/hotpatch.rs | 5 +- tests/run-make/hotpatch-unaffected/rmake.rs | 71 ++++++++++----------- tests/run-make/hotpatch/rmake.rs | 67 ++++++++++--------- tests/run-make/hotpatch_pdb/rmake.rs | 40 ++++++------ 4 files changed, 91 insertions(+), 92 deletions(-) diff --git a/tests/codegen/hotpatch.rs b/tests/codegen/hotpatch.rs index 91d6ac8759d67..70ca8b27bff91 100644 --- a/tests/codegen/hotpatch.rs +++ b/tests/codegen/hotpatch.rs @@ -1,3 +1,6 @@ +// check if functions get the attribute, so that LLVM ensures they are hotpatchable +// the attribute is only implemented for x86, aarch64 does not require it + //@ revisions: x32 x64 //@[x32] only-x86 //@[x64] only-x86_64 @@ -8,5 +11,5 @@ #[no_mangle] pub fn foo() {} -// CHECK: @foo() unnamed_addr #0 +// CHECK-LABEL: @foo() unnamed_addr #0 // CHECK: attributes #0 = { {{.*}} "patchable-function"="prologue-short-redirect" {{.*}}} diff --git a/tests/run-make/hotpatch-unaffected/rmake.rs b/tests/run-make/hotpatch-unaffected/rmake.rs index 6f403189595b4..27199963d5c52 100644 --- a/tests/run-make/hotpatch-unaffected/rmake.rs +++ b/tests/run-make/hotpatch-unaffected/rmake.rs @@ -1,50 +1,49 @@ // Check if hotpatch leaves the functions that are already hotpatchable untouched -//@ revisions: x32 x64 aarch64 -//@[x32] only-x86 -//@[x64] only-x86_64 -//@[aarch64] only-aarch64 - -// Reason: hotpatch is only implemented for X86 and aarch64 - use run_make_support::{assertion_helpers, llvm, rustc}; fn main() { - fn base_rustc() -> rustc::Rustc { - let mut rustc = rustc(); - rustc.input("lib.rs").crate_type("lib").opt_level("3"); - rustc - } - fn dump_lib(libname: &str) -> String { - llvm::llvm_objdump() - .arg("--disassemble-symbols=return_42,tailcall") - .input(libname) - .run() - .stdout_utf8() - } + // hotpatch is only implemented for X86 and aarch64 + #[cfg(any(target_arch = "x86", target_arch = "x86_64", target_arch = "aarch64"))] + { - base_rustc().crate_name("regular").run(); - let regular_dump = dump_lib("libregular.rlib"); + fn base_rustc() -> rustc::Rustc { + let mut rustc = rustc(); + rustc.input("lib.rs").crate_type("lib").opt_level("3"); + rustc + } - base_rustc().crate_name("hotpatch").arg("-Zhotpatch").run(); - let hotpatch_dump = dump_lib("libhotpatch.rlib"); + fn dump_lib(libname: &str) -> String { + llvm::llvm_objdump() + .arg("--disassemble-symbols=return_42,tailcall") + .input(libname) + .run() + .stdout_utf8() + } - { - let mut lines_regular = regular_dump.lines(); - let mut lines_hotpatch = hotpatch_dump.lines(); - - loop { - match (lines_regular.next(), lines_hotpatch.next()) { - (None, None) => break, - (Some(r), Some(h)) => { - if r.contains("libregular.rlib") { - assertion_helpers::assert_contains(h, "libhotpatch.rlib") - } else { - assertion_helpers::assert_equals(&r, &h) + base_rustc().crate_name("regular").run(); + let regular_dump = dump_lib("libregular.rlib"); + + base_rustc().crate_name("hotpatch").arg("-Zhotpatch").run(); + let hotpatch_dump = dump_lib("libhotpatch.rlib"); + + { + let mut lines_regular = regular_dump.lines(); + let mut lines_hotpatch = hotpatch_dump.lines(); + + loop { + match (lines_regular.next(), lines_hotpatch.next()) { + (None, None) => break, + (Some(r), Some(h)) => { + if r.contains("libregular.rlib") { + assertion_helpers::assert_contains(h, "libhotpatch.rlib") + } else { + assertion_helpers::assert_equals(&r, &h) + } } + _ => panic!("expected files to have equal number of lines"), } - _ => panic!("expected files to have equal number of lines"), } } } diff --git a/tests/run-make/hotpatch/rmake.rs b/tests/run-make/hotpatch/rmake.rs index a88de257f4b3e..e308b8c8ee568 100644 --- a/tests/run-make/hotpatch/rmake.rs +++ b/tests/run-make/hotpatch/rmake.rs @@ -1,44 +1,43 @@ // Check if hotpatch makes the functions hotpachable that were not // More details in lib.rs -//@ revisions: x32 x64 -//@[x32] only-x86 -//@[x64] only-x86_64 - -// Reason: hotpatch is only implemented for x86 and aarch64, but for aarch64 they -// are always hotpatchable so we don't need to check it - use run_make_support::{llvm, rustc}; fn main() { - fn base_rustc() -> rustc::Rustc { - let mut rustc = rustc(); - rustc.input("lib.rs").crate_type("lib").opt_level("3"); - rustc - } - - fn dump_lib(libname: &str) -> String { - llvm::llvm_objdump() - .arg("--disassemble-symbols=empty_fn") - .input(libname) - .run() - .stdout_utf8() - } + // hotpatch is only implemented for x86 and aarch64, but for aarch64 functions + // are always hotpatchable so we don't need to check it + #[cfg(any(target_arch = "x86", target_arch = "x86_64", target_arch = "aarch64"))] { - base_rustc().crate_name("regular").run(); - let regular_dump = dump_lib("libregular.rlib"); - llvm::llvm_filecheck().patterns("lib.rs").stdin_buf(regular_dump).run(); - } - - { - base_rustc().crate_name("hotpatch").arg("-Zhotpatch").run(); - let hotpatch_dump = dump_lib("libhotpatch.rlib"); - - llvm::llvm_filecheck() - .patterns("lib.rs") - .check_prefix("HOTPATCH") - .stdin_buf(hotpatch_dump) - .run(); + fn base_rustc() -> rustc::Rustc { + let mut rustc = rustc(); + rustc.input("lib.rs").crate_type("lib").opt_level("3"); + rustc + } + + fn dump_lib(libname: &str) -> String { + llvm::llvm_objdump() + .arg("--disassemble-symbols=empty_fn") + .input(libname) + .run() + .stdout_utf8() + } + + { + base_rustc().crate_name("regular").run(); + let regular_dump = dump_lib("libregular.rlib"); + llvm::llvm_filecheck().patterns("lib.rs").stdin_buf(regular_dump).run(); + } + + { + base_rustc().crate_name("hotpatch").arg("-Zhotpatch").run(); + let hotpatch_dump = dump_lib("libhotpatch.rlib"); + + llvm::llvm_filecheck() + .patterns("lib.rs") + .check_prefix("HOTPATCH") + .stdin_buf(hotpatch_dump) + .run(); + } } } diff --git a/tests/run-make/hotpatch_pdb/rmake.rs b/tests/run-make/hotpatch_pdb/rmake.rs index 6e217baa0d3a9..0452ec27ab7f0 100644 --- a/tests/run-make/hotpatch_pdb/rmake.rs +++ b/tests/run-make/hotpatch_pdb/rmake.rs @@ -1,30 +1,28 @@ // Check if hotpatch flag is present in the Codeview. // This is need so linkers actually pad functions when given the functionpadmin arg. -//@ revisions: x32 x64 aarch64 -//@[x32] only-x86 -//@[x64] only-x86_64 -//@[aarch64] only-aarch64 - -// Reason: Hotpatch is only implemented for x86 and aarch64 - use run_make_support::{llvm, rustc}; fn main() { - let output = rustc() - .input("main.rs") - .arg("-g") - .arg("-Zhotpatch") - .crate_name("hotpatch_pdb") - .crate_type("bin") - .run(); - let pdbutil_output = llvm::llvm_pdbutil() - .arg("dump") - .arg("-symbols") - .input("hotpatch_pdb.pdb") - .run() - .stdout_utf8(); + // Hotpatch is only implemented for x86 and aarch64 + #[cfg(any(target_arch = "x86", target_arch = "x86_64", target_arch = "aarch64"))] + { + let output = rustc() + .input("main.rs") + .arg("-g") + .arg("-Zhotpatch") + .crate_name("hotpatch_pdb") + .crate_type("bin") + .run(); + + let pdbutil_output = llvm::llvm_pdbutil() + .arg("dump") + .arg("-symbols") + .input("hotpatch_pdb.pdb") + .run() + .stdout_utf8(); - llvm::llvm_filecheck().patterns("main.rs").stdin_buf(&pdbutil_output).run(); + llvm::llvm_filecheck().patterns("main.rs").stdin_buf(&pdbutil_output).run(); + } } From 963919ad2897d9ff4be89ec9f224eda90bb9063a Mon Sep 17 00:00:00 2001 From: Florian Schmiderer Date: Sat, 12 Oct 2024 19:04:01 +0200 Subject: [PATCH 09/10] adjusted tests --- tests/run-make/hotpatch-unaffected/rmake.rs | 2 -- tests/run-make/hotpatch/rmake.rs | 1 - tests/run-make/hotpatch_pdb/rmake.rs | 10 ++++++---- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/tests/run-make/hotpatch-unaffected/rmake.rs b/tests/run-make/hotpatch-unaffected/rmake.rs index 27199963d5c52..b50047e529c41 100644 --- a/tests/run-make/hotpatch-unaffected/rmake.rs +++ b/tests/run-make/hotpatch-unaffected/rmake.rs @@ -3,11 +3,9 @@ use run_make_support::{assertion_helpers, llvm, rustc}; fn main() { - // hotpatch is only implemented for X86 and aarch64 #[cfg(any(target_arch = "x86", target_arch = "x86_64", target_arch = "aarch64"))] { - fn base_rustc() -> rustc::Rustc { let mut rustc = rustc(); rustc.input("lib.rs").crate_type("lib").opt_level("3"); diff --git a/tests/run-make/hotpatch/rmake.rs b/tests/run-make/hotpatch/rmake.rs index e308b8c8ee568..4f43aaa985143 100644 --- a/tests/run-make/hotpatch/rmake.rs +++ b/tests/run-make/hotpatch/rmake.rs @@ -4,7 +4,6 @@ use run_make_support::{llvm, rustc}; fn main() { - // hotpatch is only implemented for x86 and aarch64, but for aarch64 functions // are always hotpatchable so we don't need to check it #[cfg(any(target_arch = "x86", target_arch = "x86_64", target_arch = "aarch64"))] diff --git a/tests/run-make/hotpatch_pdb/rmake.rs b/tests/run-make/hotpatch_pdb/rmake.rs index 0452ec27ab7f0..800245f87cdc8 100644 --- a/tests/run-make/hotpatch_pdb/rmake.rs +++ b/tests/run-make/hotpatch_pdb/rmake.rs @@ -4,9 +4,11 @@ use run_make_support::{llvm, rustc}; fn main() { - - // Hotpatch is only implemented for x86 and aarch64 - #[cfg(any(target_arch = "x86", target_arch = "x86_64", target_arch = "aarch64"))] + // PDBs are windows only and hotpatch is only implemented for x86 and aarch64 + #[cfg(all( + target_os = "windows", + any(target_arch = "x86", target_arch = "x86_64", target_arch = "aarch64") + ))] { let output = rustc() .input("main.rs") @@ -24,5 +26,5 @@ fn main() { .stdout_utf8(); llvm::llvm_filecheck().patterns("main.rs").stdin_buf(&pdbutil_output).run(); - } + } } From d898368e860d2b1d71ecc473810c3ec067899778 Mon Sep 17 00:00:00 2001 From: Florian Schmiderer Date: Sun, 13 Oct 2024 01:45:19 +0200 Subject: [PATCH 10/10] improved variable name --- compiler/rustc_codegen_llvm/src/back/owned_target_machine.rs | 4 ++-- compiler/rustc_codegen_llvm/src/back/write.rs | 4 ++-- compiler/rustc_codegen_llvm/src/llvm/ffi.rs | 2 +- compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/back/owned_target_machine.rs b/compiler/rustc_codegen_llvm/src/back/owned_target_machine.rs index 07571d21de0ce..c866c77495cd0 100644 --- a/compiler/rustc_codegen_llvm/src/back/owned_target_machine.rs +++ b/compiler/rustc_codegen_llvm/src/back/owned_target_machine.rs @@ -35,7 +35,7 @@ impl OwnedTargetMachine { emit_stack_size_section: bool, relax_elf_relocations: bool, use_init_array: bool, - use_hotpatch: bool, + is_hotpatchable: bool, split_dwarf_file: &CStr, output_obj_file: &CStr, debug_info_compression: &CStr, @@ -68,7 +68,7 @@ impl OwnedTargetMachine { emit_stack_size_section, relax_elf_relocations, use_init_array, - use_hotpatch, + is_hotpatchable, split_dwarf_file.as_ptr(), output_obj_file.as_ptr(), debug_info_compression.as_ptr(), diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs index a7dd0b22773ae..b2212950b7377 100644 --- a/compiler/rustc_codegen_llvm/src/back/write.rs +++ b/compiler/rustc_codegen_llvm/src/back/write.rs @@ -228,7 +228,7 @@ pub(crate) fn target_machine_factory( // this makes LLVM add a hotpatch flag in the codeview S_COMPILE3 record, // which is required by linkers for the functionpadmin option // aarch64 is always hotpatchable - let use_hotpatch = sess.opts.unstable_opts.hotpatch || sess.target.arch.contains("aarch64"); + let is_hotpatchable = sess.opts.unstable_opts.hotpatch || sess.target.arch.contains("aarch64"); let path_mapping = sess.source_map().path_mapping().clone(); @@ -302,7 +302,7 @@ pub(crate) fn target_machine_factory( emit_stack_size_section, relax_elf_relocations, use_init_array, - use_hotpatch, + is_hotpatchable, &split_dwarf_file, &output_obj_file, &debuginfo_compression, diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 68bae8dc3ae7a..2eb661b0fc2a1 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -2170,7 +2170,7 @@ unsafe extern "C" { EmitStackSizeSection: bool, RelaxELFRelocations: bool, UseInitArray: bool, - UseHotpatch: bool, + IsHotpatchable: bool, SplitDwarfFile: *const c_char, OutputObjFile: *const c_char, DebugInfoCompression: *const c_char, diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp index 354d61bd36fc8..69fab1a1f58bd 100644 --- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp @@ -396,7 +396,7 @@ extern "C" LLVMTargetMachineRef LLVMRustCreateTargetMachine( bool FunctionSections, bool DataSections, bool UniqueSectionNames, bool TrapUnreachable, bool Singlethread, bool VerboseAsm, bool EmitStackSizeSection, bool RelaxELFRelocations, bool UseInitArray, - bool UseHotpatch, const char *SplitDwarfFile, const char *OutputObjFile, + bool IsHotpatchable, const char *SplitDwarfFile, const char *OutputObjFile, const char *DebugInfoCompression, bool UseEmulatedTls, const char *ArgsCstrBuff, size_t ArgsCstrBuffLen) { @@ -426,7 +426,7 @@ extern "C" LLVMTargetMachineRef LLVMRustCreateTargetMachine( // Always preserve comments that were written by the user Options.MCOptions.PreserveAsmComments = true; Options.MCOptions.ABIName = ABIStr; - Options.Hotpatch = UseHotpatch; + Options.Hotpatch = IsHotpatchable; if (SplitDwarfFile) { Options.MCOptions.SplitDwarfFile = SplitDwarfFile; }