From 520081721cb1aa8ec9430959f335866304415a42 Mon Sep 17 00:00:00 2001 From: DianQK Date: Thu, 10 Aug 2023 16:51:03 +0800 Subject: [PATCH 01/10] Restore `#![no_builtins]` crates participation in LTO. After #113716, we can make `#![no_builtins]` crates participate in LTO again. `#![no_builtins]` with LTO does not result in undefined references to the error. --- compiler/rustc_codegen_ssa/src/back/link.rs | 36 +++---------------- compiler/rustc_codegen_ssa/src/back/write.rs | 16 +-------- compiler/rustc_codegen_ssa/src/base.rs | 4 +-- tests/run-make/no-builtins-lto/Makefile | 18 ++++++---- .../no-builtins-lto/filecheck.lto.txt | 17 +++++++++ tests/run-make/no-builtins-lto/foo.rs | 33 +++++++++++++++++ tests/run-make/no-builtins-lto/main.rs | 27 +++++++++++++- tests/run-make/no-builtins-lto/no_builtins.rs | 13 +++++++ 8 files changed, 107 insertions(+), 57 deletions(-) create mode 100644 tests/run-make/no-builtins-lto/filecheck.lto.txt create mode 100644 tests/run-make/no-builtins-lto/foo.rs diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 28a51711b9361..535b594649c39 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -510,8 +510,7 @@ fn link_staticlib<'a>( &codegen_results.crate_info, Some(CrateType::Staticlib), &mut |cnum, path| { - let lto = are_upstream_rust_objects_already_included(sess) - && !ignored_for_lto(sess, &codegen_results.crate_info, cnum); + let lto = are_upstream_rust_objects_already_included(sess); let native_libs = codegen_results.crate_info.native_libraries[&cnum].iter(); let relevant = native_libs.clone().filter(|lib| relevant_lib(sess, &lib)); @@ -1250,24 +1249,6 @@ fn link_sanitizer_runtime(sess: &Session, linker: &mut dyn Linker, name: &str) { } } -/// Returns a boolean indicating whether the specified crate should be ignored -/// during LTO. -/// -/// Crates ignored during LTO are not lumped together in the "massive object -/// file" that we create and are linked in their normal rlib states. See -/// comments below for what crates do not participate in LTO. -/// -/// It's unusual for a crate to not participate in LTO. Typically only -/// compiler-specific and unstable crates have a reason to not participate in -/// LTO. -pub fn ignored_for_lto(sess: &Session, info: &CrateInfo, cnum: CrateNum) -> bool { - // If our target enables builtin function lowering in LLVM then the - // crates providing these functions don't participate in LTO (e.g. - // no_builtins or compiler builtins crates). - !sess.target.no_builtins - && (info.compiler_builtins == Some(cnum) || info.is_no_builtins.contains(&cnum)) -} - /// This functions tries to determine the appropriate linker (and corresponding LinkerFlavor) to use pub fn linker_and_flavor(sess: &Session) -> (PathBuf, LinkerFlavor) { fn infer_from( @@ -2733,10 +2714,6 @@ fn rehome_sysroot_lib_dir<'a>(sess: &'a Session, lib_dir: &Path) -> PathBuf { // symbols). We must continue to include the rest of the rlib, however, as // it may contain static native libraries which must be linked in. // -// (*) Crates marked with `#![no_builtins]` don't participate in LTO and -// their bytecode wasn't included. The object files in those libraries must -// still be passed to the linker. -// // Note, however, that if we're not doing LTO we can just pass the rlib // blindly to the linker (fast) because it's fine if it's not actually // included as we're at the end of the dependency chain. @@ -2762,9 +2739,7 @@ fn add_static_crate<'a>( cmd.link_rlib(&rlib_path); }; - if !are_upstream_rust_objects_already_included(sess) - || ignored_for_lto(sess, &codegen_results.crate_info, cnum) - { + if !are_upstream_rust_objects_already_included(sess) { link_upstream(cratepath); return; } @@ -2778,8 +2753,6 @@ fn add_static_crate<'a>( let canonical_name = name.replace('-', "_"); let upstream_rust_objects_already_included = are_upstream_rust_objects_already_included(sess); - let is_builtins = - sess.target.no_builtins || !codegen_results.crate_info.is_no_builtins.contains(&cnum); let mut archive = archive_builder_builder.new_archive_builder(sess); if let Err(error) = archive.add_archive( @@ -2796,9 +2769,8 @@ fn add_static_crate<'a>( // If we're performing LTO and this is a rust-generated object // file, then we don't need the object file as it's part of the - // LTO module. Note that `#![no_builtins]` is excluded from LTO, - // though, so we let that object file slide. - if upstream_rust_objects_already_included && is_rust_object && is_builtins { + // LTO module. + if upstream_rust_objects_already_included && is_rust_object { return true; } diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index f192747c8abaa..9940442368365 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -149,23 +149,12 @@ impl ModuleConfig { let emit_obj = if !should_emit_obj { EmitObj::None - } else if sess.target.obj_is_bitcode - || (sess.opts.cg.linker_plugin_lto.enabled() && !no_builtins) - { + } else if sess.target.obj_is_bitcode || sess.opts.cg.linker_plugin_lto.enabled() { // This case is selected if the target uses objects as bitcode, or // if linker plugin LTO is enabled. In the linker plugin LTO case // the assumption is that the final link-step will read the bitcode // and convert it to object code. This may be done by either the // native linker or rustc itself. - // - // Note, however, that the linker-plugin-lto requested here is - // explicitly ignored for `#![no_builtins]` crates. These crates are - // specifically ignored by rustc's LTO passes and wouldn't work if - // loaded into the linker. These crates define symbols that LLVM - // lowers intrinsics to, and these symbol dependencies aren't known - // until after codegen. As a result any crate marked - // `#![no_builtins]` is assumed to not participate in LTO and - // instead goes on to generate object code. EmitObj::Bitcode } else if need_bitcode_in_object(tcx) { EmitObj::ObjectCode(BitcodeSection::Full) @@ -1040,9 +1029,6 @@ fn start_executing_work( let mut each_linked_rlib_for_lto = Vec::new(); drop(link::each_linked_rlib(crate_info, None, &mut |cnum, path| { - if link::ignored_for_lto(sess, crate_info, cnum) { - return; - } each_linked_rlib_for_lto.push((cnum, path.to_path_buf())); })); diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index 1e4ea73a1724f..53ea0c4924a70 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -885,9 +885,7 @@ impl CrateInfo { // If global LTO is enabled then almost everything (*) is glued into a single object file, // so this logic is not necessary and can cause issues on some targets (due to weak lang // item symbols being "privatized" to that object file), so we disable it. - // (*) Native libs, and `#[compiler_builtins]` and `#[no_builtins]` crates are not glued, - // and we assume that they cannot define weak lang items. This is not currently enforced - // by the compiler, but that's ok because all this stuff is unstable anyway. + // (*) Native libs are not glued, and we assume that they cannot define weak lang items. let target = &tcx.sess.target; if !are_upstream_rust_objects_already_included(tcx.sess) { let missing_weak_lang_items: FxHashSet = info diff --git a/tests/run-make/no-builtins-lto/Makefile b/tests/run-make/no-builtins-lto/Makefile index c8f05d9918b91..717d047c4469d 100644 --- a/tests/run-make/no-builtins-lto/Makefile +++ b/tests/run-make/no-builtins-lto/Makefile @@ -1,9 +1,15 @@ include ../tools.mk +# only-x86_64 + +# We want to check that `no_builtins` is correctly participating in LTO. +# First, verify that the `foo::foo` symbol can be found when linking. +# Next, verify that `memcpy` can be customized using `no_builtins` under LTO. +# Others will use the built-in memcpy. + all: - # Compile a `#![no_builtins]` rlib crate - $(RUSTC) no_builtins.rs - # Build an executable that depends on that crate using LTO. The no_builtins crate doesn't - # participate in LTO, so its rlib must be explicitly linked into the final binary. Verify this by - # grepping the linker arguments. - $(RUSTC) main.rs -C lto --print link-args | $(CGREP) 'libno_builtins.rlib' + $(RUSTC) -C linker-plugin-lto -C opt-level=2 -C debuginfo=0 foo.rs + $(RUSTC) -C linker-plugin-lto -C opt-level=2 -C debuginfo=0 no_builtins.rs + $(RUSTC) main.rs -C lto -C opt-level=2 -C debuginfo=0 -C save-temps -C metadata=1 -C codegen-units=1 + $(LLVM_BIN_DIR)/llvm-dis $(TMPDIR)/main.main.*-cgu.0.rcgu.lto.input.bc -o $(TMPDIR)/lto.ll + cat "$(TMPDIR)"/lto.ll | "$(LLVM_FILECHECK)" filecheck.lto.txt diff --git a/tests/run-make/no-builtins-lto/filecheck.lto.txt b/tests/run-make/no-builtins-lto/filecheck.lto.txt new file mode 100644 index 0000000000000..79dc3a51501db --- /dev/null +++ b/tests/run-make/no-builtins-lto/filecheck.lto.txt @@ -0,0 +1,17 @@ +CHECK: define{{.*}} void @bar +CHECK-NEXT: call void @no_builtins +CHECK-NEXT: call void @llvm.memcpy + +CHECK: define{{.*}} i32 @main +CHECK: call void @bar + +CHECK: define{{.*}} void @foo +CHECK-NEXT: call void @llvm.memcpy + +CHECK: define{{.*}} void @no_builtins +CHECK-SAME: #[[ATTR:[0-9]+]] { +CHECK: call void @foo +CHECK-NEXT: call{{.*}} @memcpy + +CHECK: attributes #[[ATTR]] +CHECK-SAME: no-builtins diff --git a/tests/run-make/no-builtins-lto/foo.rs b/tests/run-make/no-builtins-lto/foo.rs new file mode 100644 index 0000000000000..f09ac40b152a2 --- /dev/null +++ b/tests/run-make/no-builtins-lto/foo.rs @@ -0,0 +1,33 @@ +#![feature(lang_items, no_core)] +#![no_std] +#![no_core] +#![crate_type = "lib"] + +#[inline(never)] +#[no_mangle] +pub unsafe fn foo(dest: *mut u8, src: *const u8) { + // should call `@llvm.memcpy`. + memcpy(dest, src, 1024); +} + +#[no_mangle] +#[inline(never)] +pub unsafe extern "C" fn memcpy(dest: *mut u8, src: *const u8, _n: usize) -> *mut u8 { + *dest = 0; + return src as *mut u8; +} + +#[lang = "sized"] +trait Sized {} +#[lang = "copy"] +trait Copy {} +impl Copy for *mut u8 {} +impl Copy for *const u8 {} + +#[lang = "drop_in_place"] +#[allow(unconditional_recursion)] +pub unsafe fn drop_in_place(to_drop: *mut T) { + // Code here does not matter - this is replaced by the + // real drop glue by the compiler. + drop_in_place(to_drop); +} diff --git a/tests/run-make/no-builtins-lto/main.rs b/tests/run-make/no-builtins-lto/main.rs index 890c999c8ccf7..c474527a5ae80 100644 --- a/tests/run-make/no-builtins-lto/main.rs +++ b/tests/run-make/no-builtins-lto/main.rs @@ -1,3 +1,28 @@ +#![feature(no_core, start, lang_items)] +#![no_std] +// We use `no_core` to reduce the LTO products is small enough. +#![no_core] + extern crate no_builtins; +extern crate foo; + +#[link(name = "c")] +extern "C" {} + +#[start] +fn main(_: isize, p: *const *const u8) -> isize { + // Make sure the symbols are retained. + unsafe { bar(*p as *mut u8, *p); } + 0 +} + +#[no_mangle] +#[inline(never)] +pub unsafe extern "C" fn bar(dest: *mut u8, src: *const u8) { + no_builtins::no_builtins(dest, src); + // should call `@llvm.memcpy` + foo::memcpy(dest, src, 1024); +} -fn main() {} +#[lang = "eh_personality"] +fn eh_personality() {} diff --git a/tests/run-make/no-builtins-lto/no_builtins.rs b/tests/run-make/no-builtins-lto/no_builtins.rs index 5d001031a57fa..33ed68e3aee3d 100644 --- a/tests/run-make/no-builtins-lto/no_builtins.rs +++ b/tests/run-make/no-builtins-lto/no_builtins.rs @@ -1,2 +1,15 @@ +#![feature(lang_items, no_core)] +#![no_std] +#![no_core] #![crate_type = "lib"] #![no_builtins] + +extern crate foo; + +#[no_mangle] +pub unsafe fn no_builtins(dest: *mut u8, src: *const u8) { + // There should be no "undefined reference to `foo::foo'". + foo::foo(dest, src); + // should call `@memcpy` instead of `@llvm.memcpy`. + foo::memcpy(dest, src, 1024); +} From 6762d640637740dce9db07b338230de11f831cb6 Mon Sep 17 00:00:00 2001 From: DianQK Date: Thu, 10 Aug 2023 19:01:38 +0800 Subject: [PATCH 02/10] Removes the useless DisableSimplifyLibCalls parameter. After applying no_builtins to the function attributes, we can remove the DisableSimplifyLibCalls parameter. --- compiler/rustc_codegen_llvm/src/back/write.rs | 8 +++----- compiler/rustc_codegen_llvm/src/llvm/ffi.rs | 8 +------- compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp | 9 ++------- 3 files changed, 6 insertions(+), 19 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs index c778a6e017fac..383a7bdcaaa4b 100644 --- a/compiler/rustc_codegen_llvm/src/back/write.rs +++ b/compiler/rustc_codegen_llvm/src/back/write.rs @@ -563,7 +563,6 @@ pub(crate) unsafe fn llvm_optimize( unroll_loops, config.vectorize_slp, config.vectorize_loop, - config.no_builtins, config.emit_lifetime_markers, sanitizer_options.as_ref(), pgo_gen_path.as_ref().map_or(std::ptr::null(), |s| s.as_ptr()), @@ -678,7 +677,6 @@ pub(crate) unsafe fn codegen( unsafe fn with_codegen<'ll, F, R>( tm: &'ll llvm::TargetMachine, llmod: &'ll llvm::Module, - no_builtins: bool, f: F, ) -> R where @@ -686,7 +684,7 @@ pub(crate) unsafe fn codegen( { let cpm = llvm::LLVMCreatePassManager(); llvm::LLVMAddAnalysisPasses(tm, cpm); - llvm::LLVMRustAddLibraryInfo(cpm, llmod, no_builtins); + llvm::LLVMRustAddLibraryInfo(cpm, llmod); f(cpm) } @@ -789,7 +787,7 @@ pub(crate) unsafe fn codegen( } else { llmod }; - with_codegen(tm, llmod, config.no_builtins, |cpm| { + with_codegen(tm, llmod, |cpm| { write_output_file( diag_handler, tm, @@ -824,7 +822,7 @@ pub(crate) unsafe fn codegen( (_, SplitDwarfKind::Split) => Some(dwo_out.as_path()), }; - with_codegen(tm, llmod, config.no_builtins, |cpm| { + with_codegen(tm, llmod, |cpm| { write_output_file( diag_handler, tm, diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index a038b3af03dd6..528447b016aa3 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -2139,13 +2139,8 @@ extern "C" { ArgsCstrBuff: *const c_char, ArgsCstrBuffLen: usize, ) -> *mut TargetMachine; - pub fn LLVMRustDisposeTargetMachine(T: *mut TargetMachine); - pub fn LLVMRustAddLibraryInfo<'a>( - PM: &PassManager<'a>, - M: &'a Module, - DisableSimplifyLibCalls: bool, - ); + pub fn LLVMRustAddLibraryInfo<'a>(PM: &PassManager<'a>, M: &'a Module); pub fn LLVMRustWriteOutputFile<'a>( T: &'a TargetMachine, PM: &PassManager<'a>, @@ -2167,7 +2162,6 @@ extern "C" { UnrollLoops: bool, SLPVectorize: bool, LoopVectorize: bool, - DisableSimplifyLibCalls: bool, EmitLifetimeMarkers: bool, SanitizerOptions: Option<&SanitizerOptions>, PGOGenPath: *const c_char, diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp index 31565db1b7929..ff2ec388a5f2c 100644 --- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp @@ -535,12 +535,9 @@ extern "C" void LLVMRustDisposeTargetMachine(LLVMTargetMachineRef TM) { // Unfortunately, the LLVM C API doesn't provide a way to create the // TargetLibraryInfo pass, so we use this method to do so. -extern "C" void LLVMRustAddLibraryInfo(LLVMPassManagerRef PMR, LLVMModuleRef M, - bool DisableSimplifyLibCalls) { +extern "C" void LLVMRustAddLibraryInfo(LLVMPassManagerRef PMR, LLVMModuleRef M) { Triple TargetTriple(unwrap(M)->getTargetTriple()); TargetLibraryInfoImpl TLII(TargetTriple); - if (DisableSimplifyLibCalls) - TLII.disableAllFunctions(); unwrap(PMR)->add(new TargetLibraryInfoWrapperPass(TLII)); } @@ -707,7 +704,7 @@ LLVMRustOptimize( bool IsLinkerPluginLTO, bool NoPrepopulatePasses, bool VerifyIR, bool UseThinLTOBuffers, bool MergeFunctions, bool UnrollLoops, bool SLPVectorize, bool LoopVectorize, - bool DisableSimplifyLibCalls, bool EmitLifetimeMarkers, + bool EmitLifetimeMarkers, LLVMRustSanitizerOptions *SanitizerOptions, const char *PGOGenPath, const char *PGOUsePath, bool InstrumentCoverage, const char *InstrProfileOutput, @@ -813,8 +810,6 @@ LLVMRustOptimize( Triple TargetTriple(TheModule->getTargetTriple()); std::unique_ptr TLII(new TargetLibraryInfoImpl(TargetTriple)); - if (DisableSimplifyLibCalls) - TLII->disableAllFunctions(); FAM.registerPass([&] { return TargetLibraryAnalysis(*TLII); }); PB.registerModuleAnalyses(MAM); From a6f7596fb9dd6790b237f6a628d6af8d80930bdb Mon Sep 17 00:00:00 2001 From: DianQK Date: Sat, 19 Aug 2023 16:10:49 +0800 Subject: [PATCH 03/10] Add `PreservedSymbols` from LLVM to LTO. When building with LTO, builtin functions that are defined but whose calls have not been inserted yet, get internalized. We need to prevent these symbols from being internalized at LTO time. Refer to https://reviews.llvm.org/D49434. --- .../rustc_llvm/llvm-wrapper/PassWrapper.cpp | 104 +++++++++++++++++- .../Makefile | 0 .../main.rs | 4 +- .../verify.js | 0 4 files changed, 105 insertions(+), 3 deletions(-) rename tests/run-make/{wasm-spurious-import => wasm-builtins-import}/Makefile (100%) rename tests/run-make/{wasm-spurious-import => wasm-builtins-import}/main.rs (65%) rename tests/run-make/{wasm-spurious-import => wasm-builtins-import}/verify.js (100%) diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp index ff2ec388a5f2c..f338b914c67b0 100644 --- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp @@ -1120,6 +1120,102 @@ extern "C" void LLVMRustPrintPasses() { PB.printPassNames(outs()); } +// from https://github.com/llvm/llvm-project/blob/7021182d6b43de9488ab70de626192ce70b3a4a6/llvm/lib/Object/IRSymtab.cpp#L48-L57 +static const char *PreservedLibcallSymbols[] = { +#define HANDLE_LIBCALL(code, name) name, +#include "llvm/IR/RuntimeLibcalls.def" +#undef HANDLE_LIBCALL + // RuntimeLibcalls.def missing symbols. + "__ctzsi2", + "__ctzdi2", + "__ctzti2", + "__ffssi2", + "__ffsdi2", + "__ffsti2", + "__paritysi2", + "__paritydi2", + "__parityti2", + "__popcountsi2", + "__popcountdi2", + "__popcountti2", + "__bswapsi2", + "__bswapdi2", + "__negti2", + "__udivmoddi4", + "__udivmodti4", + "__udivmodsi4", + "__divmodsi4", + "__divmoddi4", + "__divmodti4", + "__absvsi2", + "__absvdi2", + "__absvti2", + "__negvsi2", + "__negvdi2", + "__negvti2", + "__addvsi3", + "__addvdi3", + "__addvti3", + "__subvsi3", + "__subvdi3", + "__subvti3", + "__mulvsi3", + "__mulvdi3", + "__mulvti3", + "__cmpdi2", + "__cmpti2", + "__ucmpdi2", + "__ucmpti2", + "__mulsc3", + "__muldc3", + "__mulxc3", + "__multc3", + "__divsc3", + "__divdc3", + "__divxc3", + "__divtc3", + "__clear_cache", + "__enable_execute_stack", + "__gcc_personality_v0", + "__eprintf", + "__emutls_get_address", + "__trampoline_setup", + "__addsf3vfp", + "__adddf3vfp", + "__divsf3vfp", + "__divdf3vfp", + "__eqsf2vfp", + "__eqdf2vfp", + "__extendsfdf2vfp", + "__fixdfsivfp", + "__fixsfsivfp", + "__fixunssfsivfp", + "__fixunsdfsivfp", + "__floatsidfvfp", + "__floatsisfvfp", + "__floatunssidfvfp", + "__floatunssisfvfp", + "__gedf2vfp", + "__gesf2vfp", + "__gtdf2vfp", + "__gtsf2vfp", + "__ledf2vfp", + "__lesf2vfp", + "__ltdf2vfp", + "__ltsf2vfp", + "__muldf3vfp", + "__mulsf3vfp", + "__nedf2vfp", + "__negdf2vfp", + "__negsf2vfp", + "__negsf2vfp", + "__subdf3vfp", + "__subsf3vfp", + "__truncdfsf2vfp", + "__unorddf2vfp", + "__unordsf2vfp", +}; + extern "C" void LLVMRustRunRestrictionPass(LLVMModuleRef M, char **Symbols, size_t Len) { auto PreserveFunctions = [=](const GlobalValue &GV) { @@ -1135,7 +1231,7 @@ extern "C" void LLVMRustRunRestrictionPass(LLVMModuleRef M, char **Symbols, return true; } } - return false; + return llvm::is_contained(PreservedLibcallSymbols, GV.getName()); }; internalizeModule(*unwrap(M), PreserveFunctions); @@ -1293,6 +1389,12 @@ LLVMRustCreateThinLTOData(LLVMRustThinLTOModule *modules, auto GUID = GlobalValue::getGUID(preserved_symbols[i]); Ret->GUIDPreservedSymbols.insert(GUID); } + for (int i = 0; i < sizeof(PreservedLibcallSymbols) / sizeof(PreservedLibcallSymbols[0]); i++) { + if (auto *PreservedLibcallSymbol = PreservedLibcallSymbols[i]) { + auto GUID = GlobalValue::getGUID(PreservedLibcallSymbol); + Ret->GUIDPreservedSymbols.insert(GUID); + } + } // Collect the import/export lists for all modules from the call-graph in the // combined index diff --git a/tests/run-make/wasm-spurious-import/Makefile b/tests/run-make/wasm-builtins-import/Makefile similarity index 100% rename from tests/run-make/wasm-spurious-import/Makefile rename to tests/run-make/wasm-builtins-import/Makefile diff --git a/tests/run-make/wasm-spurious-import/main.rs b/tests/run-make/wasm-builtins-import/main.rs similarity index 65% rename from tests/run-make/wasm-spurious-import/main.rs rename to tests/run-make/wasm-builtins-import/main.rs index fcbead5e28bd2..d7dbbe32ca4d2 100644 --- a/tests/run-make/wasm-spurious-import/main.rs +++ b/tests/run-make/wasm-builtins-import/main.rs @@ -8,7 +8,7 @@ fn my_panic(_info: &core::panic::PanicInfo) -> ! { #[no_mangle] pub fn multer(a: i128, b: i128) -> i128 { - // Trigger usage of the __multi3 compiler intrinsic which then leads to an imported - // panic function in case of a bug. We verify that no imports exist in our verifier. + // Trigger usage of the __multi3 compiler intrinsic which then leads to an imported function + // such as panic or __multi3 in case of a bug. We verify that no imports exist in our verifier. a * b } diff --git a/tests/run-make/wasm-spurious-import/verify.js b/tests/run-make/wasm-builtins-import/verify.js similarity index 100% rename from tests/run-make/wasm-spurious-import/verify.js rename to tests/run-make/wasm-builtins-import/verify.js From 7d0675125c948fbf78f8dbfaf8d6824c2263082e Mon Sep 17 00:00:00 2001 From: Felix S Klock II Date: Tue, 17 Oct 2023 11:10:33 -0400 Subject: [PATCH 04/10] Update tests/run-make/wasm-builtins-import/main.rs clarify seemingly circular reference --- tests/run-make/wasm-builtins-import/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/run-make/wasm-builtins-import/main.rs b/tests/run-make/wasm-builtins-import/main.rs index d7dbbe32ca4d2..3b068d8d79ebd 100644 --- a/tests/run-make/wasm-builtins-import/main.rs +++ b/tests/run-make/wasm-builtins-import/main.rs @@ -9,6 +9,6 @@ fn my_panic(_info: &core::panic::PanicInfo) -> ! { #[no_mangle] pub fn multer(a: i128, b: i128) -> i128 { // Trigger usage of the __multi3 compiler intrinsic which then leads to an imported function - // such as panic or __multi3 in case of a bug. We verify that no imports exist in our verifier. + // such as panic or __multi3 (externally defined) in case of a bug. We verify that no imports exist in our verifier. a * b } From 665da1ed320abeaf276dafbfd041ebcda50034cf Mon Sep 17 00:00:00 2001 From: Felix S Klock II Date: Tue, 17 Oct 2023 11:31:30 -0400 Subject: [PATCH 05/10] Update tests/run-make/wasm-builtins-import/main.rs placate tidy (hopefully) --- tests/run-make/wasm-builtins-import/main.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/run-make/wasm-builtins-import/main.rs b/tests/run-make/wasm-builtins-import/main.rs index 3b068d8d79ebd..5eb99df6ff74c 100644 --- a/tests/run-make/wasm-builtins-import/main.rs +++ b/tests/run-make/wasm-builtins-import/main.rs @@ -9,6 +9,7 @@ fn my_panic(_info: &core::panic::PanicInfo) -> ! { #[no_mangle] pub fn multer(a: i128, b: i128) -> i128 { // Trigger usage of the __multi3 compiler intrinsic which then leads to an imported function - // such as panic or __multi3 (externally defined) in case of a bug. We verify that no imports exist in our verifier. + // such as panic or __multi3 (externally defined) in case of a bug. We verify that + // no imports exist in our verifier. a * b } From b592f29a8e7b1f83958f429ca42947f32ec6898c Mon Sep 17 00:00:00 2001 From: DianQK Date: Wed, 18 Oct 2023 22:29:00 +0800 Subject: [PATCH 06/10] Treat extern in compiler-builtins as `used` We have to preserve the symbols of the built-in functions during LTO. --- .../src/back/symbol_export.rs | 10 +- .../rustc_llvm/llvm-wrapper/PassWrapper.cpp | 104 +----------------- 2 files changed, 8 insertions(+), 106 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs index 9cd4394108a4a..0e436f247b0b6 100644 --- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs +++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs @@ -54,8 +54,8 @@ fn reachable_non_generics_provider(tcx: TyCtxt<'_>, _: LocalCrate) -> DefIdMap = tcx .reachable_set(()) @@ -107,7 +107,11 @@ fn reachable_non_generics_provider(tcx: TyCtxt<'_>, _: LocalCrate) -> DefIdMapGUIDPreservedSymbols.insert(GUID); } - for (int i = 0; i < sizeof(PreservedLibcallSymbols) / sizeof(PreservedLibcallSymbols[0]); i++) { - if (auto *PreservedLibcallSymbol = PreservedLibcallSymbols[i]) { - auto GUID = GlobalValue::getGUID(PreservedLibcallSymbol); - Ret->GUIDPreservedSymbols.insert(GUID); - } - } // Collect the import/export lists for all modules from the call-graph in the // combined index From d047968462d3800b31606db911b60cdcd895b9d2 Mon Sep 17 00:00:00 2001 From: DianQK Date: Sat, 21 Oct 2023 19:28:20 +0800 Subject: [PATCH 07/10] Removes fields from `CrateInfo` that are no longer used. --- compiler/rustc_codegen_ssa/src/base.rs | 4 ---- compiler/rustc_codegen_ssa/src/lib.rs | 3 +-- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index 53ea0c4924a70..5fa3e17ba13bd 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -848,7 +848,6 @@ impl CrateInfo { local_crate_name, compiler_builtins, profiler_runtime: None, - is_no_builtins: Default::default(), native_libraries: Default::default(), used_libraries: tcx.native_libraries(LOCAL_CRATE).iter().map(Into::into).collect(), crate_name: Default::default(), @@ -875,9 +874,6 @@ impl CrateInfo { if tcx.is_profiler_runtime(cnum) { info.profiler_runtime = Some(cnum); } - if tcx.is_no_builtins(cnum) { - info.is_no_builtins.insert(cnum); - } } // Handle circular dependencies in the standard library. diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs index b4728ac2aa67a..cfbf3de01b31a 100644 --- a/compiler/rustc_codegen_ssa/src/lib.rs +++ b/compiler/rustc_codegen_ssa/src/lib.rs @@ -25,7 +25,7 @@ extern crate tracing; extern crate rustc_middle; use rustc_ast as ast; -use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync::Lrc; use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage}; use rustc_fluent_macro::fluent_messages; @@ -158,7 +158,6 @@ pub struct CrateInfo { pub local_crate_name: Symbol, pub compiler_builtins: Option, pub profiler_runtime: Option, - pub is_no_builtins: FxHashSet, pub native_libraries: FxHashMap>, pub crate_name: FxHashMap, pub used_libraries: Vec, From 8d69a1e69e61fe71b1672950ffc6bb28269c314d Mon Sep 17 00:00:00 2001 From: dianqk Date: Thu, 2 Nov 2023 23:13:12 +0800 Subject: [PATCH 08/10] Add crate `compiler_builtins` to LTO even if the `Linkage` is `IncludedFromDylib` --- compiler/rustc_codegen_ssa/src/back/link.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 535b594649c39..586bcaa80e34f 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -268,8 +268,14 @@ pub fn each_linked_rlib( for &cnum in crates { match fmts.get(cnum.as_usize() - 1) { - Some(&Linkage::NotLinked | &Linkage::Dynamic | &Linkage::IncludedFromDylib) => continue, - Some(_) => {} + Some(&Linkage::NotLinked | &Linkage::Dynamic) => continue, + Some(&Linkage::IncludedFromDylib) => { + // We always link crate `compiler_builtins` statically. When enabling LTO, we include it as well. + if info.compiler_builtins != Some(cnum) { + continue; + } + } + Some(&Linkage::Static) => {} None => return Err(errors::LinkRlibError::MissingFormat), } let crate_name = info.crate_name[&cnum]; From 436d4f62e0bdd14f30c64e0e2978601d8c8cc183 Mon Sep 17 00:00:00 2001 From: DianQK Date: Fri, 1 Dec 2023 22:16:32 +0800 Subject: [PATCH 09/10] Fix link name for `extern "C"` in msvc --- tests/run-make/no-builtins-lto/main.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/run-make/no-builtins-lto/main.rs b/tests/run-make/no-builtins-lto/main.rs index c474527a5ae80..4421a2afbce68 100644 --- a/tests/run-make/no-builtins-lto/main.rs +++ b/tests/run-make/no-builtins-lto/main.rs @@ -6,7 +6,8 @@ extern crate no_builtins; extern crate foo; -#[link(name = "c")] +#[cfg_attr(unix, link(name = "c"))] +#[cfg_attr(target_env = "msvc", link(name = "msvcrt"))] extern "C" {} #[start] From b9f53be1e911542d5f10fbc5fcb402b0f8f439e2 Mon Sep 17 00:00:00 2001 From: DianQK Date: Sat, 2 Dec 2023 04:40:08 +0800 Subject: [PATCH 10/10] Put `$(LLVM_BIN_DIR)` in quotes to prevent missing backslashes --- tests/run-make/no-builtins-lto/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/run-make/no-builtins-lto/Makefile b/tests/run-make/no-builtins-lto/Makefile index 717d047c4469d..c7be4836466db 100644 --- a/tests/run-make/no-builtins-lto/Makefile +++ b/tests/run-make/no-builtins-lto/Makefile @@ -11,5 +11,5 @@ all: $(RUSTC) -C linker-plugin-lto -C opt-level=2 -C debuginfo=0 foo.rs $(RUSTC) -C linker-plugin-lto -C opt-level=2 -C debuginfo=0 no_builtins.rs $(RUSTC) main.rs -C lto -C opt-level=2 -C debuginfo=0 -C save-temps -C metadata=1 -C codegen-units=1 - $(LLVM_BIN_DIR)/llvm-dis $(TMPDIR)/main.main.*-cgu.0.rcgu.lto.input.bc -o $(TMPDIR)/lto.ll + "$(LLVM_BIN_DIR)"/llvm-dis $(TMPDIR)/main.main.*-cgu.0.rcgu.lto.input.bc -o $(TMPDIR)/lto.ll cat "$(TMPDIR)"/lto.ll | "$(LLVM_FILECHECK)" filecheck.lto.txt