From c59b82353d70122b59f5bc428be9464f49a99326 Mon Sep 17 00:00:00 2001 From: James Farrell Date: Tue, 13 Jun 2023 16:16:06 +0000 Subject: Better diagnostics for dlltool errors. When dlltool fails, show the full command that was executed. In particular, llvm-dlltool is not very helpful, printing a generic usage message rather than what actually went wrong, so stdout and stderr aren't of much use when troubleshooting. --- compiler/rustc_codegen_llvm/src/back/archive.rs | 43 ++++++++++++++----------- compiler/rustc_codegen_llvm/src/errors.rs | 2 ++ 2 files changed, 26 insertions(+), 19 deletions(-) (limited to 'compiler/rustc_codegen_llvm/src') diff --git a/compiler/rustc_codegen_llvm/src/back/archive.rs b/compiler/rustc_codegen_llvm/src/back/archive.rs index a6416e9540c..10bf954d242 100644 --- a/compiler/rustc_codegen_llvm/src/back/archive.rs +++ b/compiler/rustc_codegen_llvm/src/back/archive.rs @@ -198,25 +198,24 @@ impl ArchiveBuilderBuilder for LlvmArchiveBuilderBuilder { "arm" => ("arm", "--32"), _ => panic!("unsupported arch {}", sess.target.arch), }; - let result = std::process::Command::new(&dlltool) - .args([ - "-d", - def_file_path.to_str().unwrap(), - "-D", - lib_name, - "-l", - output_path.to_str().unwrap(), - "-m", - dlltool_target_arch, - "-f", - dlltool_target_bitness, - "--no-leading-underscore", - "--temp-prefix", - temp_prefix.to_str().unwrap(), - ]) - .output(); - - match result { + let mut dlltool_cmd = std::process::Command::new(&dlltool); + dlltool_cmd.args([ + "-d", + def_file_path.to_str().unwrap(), + "-D", + lib_name, + "-l", + output_path.to_str().unwrap(), + "-m", + dlltool_target_arch, + "-f", + dlltool_target_bitness, + "--no-leading-underscore", + "--temp-prefix", + temp_prefix.to_str().unwrap(), + ]); + + match dlltool_cmd.output() { Err(e) => { sess.emit_fatal(ErrorCallingDllTool { dlltool_path: dlltool.to_string_lossy(), @@ -226,6 +225,12 @@ impl ArchiveBuilderBuilder for LlvmArchiveBuilderBuilder { // dlltool returns '0' on failure, so check for error output instead. Ok(output) if !output.stderr.is_empty() => { sess.emit_fatal(DlltoolFailImportLibrary { + dlltool_path: dlltool.to_string_lossy(), + dlltool_args: dlltool_cmd + .get_args() + .map(|arg| arg.to_string_lossy()) + .collect::>() + .join(" "), stdout: String::from_utf8_lossy(&output.stdout), stderr: String::from_utf8_lossy(&output.stderr), }) diff --git a/compiler/rustc_codegen_llvm/src/errors.rs b/compiler/rustc_codegen_llvm/src/errors.rs index 44869ced1ae..fced6d504d2 100644 --- a/compiler/rustc_codegen_llvm/src/errors.rs +++ b/compiler/rustc_codegen_llvm/src/errors.rs @@ -81,6 +81,8 @@ pub(crate) struct ErrorCallingDllTool<'a> { #[derive(Diagnostic)] #[diag(codegen_llvm_dlltool_fail_import_library)] pub(crate) struct DlltoolFailImportLibrary<'a> { + pub dlltool_path: Cow<'a, str>, + pub dlltool_args: String, pub stdout: Cow<'a, str>, pub stderr: Cow<'a, str>, } -- cgit 1.4.1-3-g733a5 From cc08749df2613c17c8c2e9d8224a24a24c126423 Mon Sep 17 00:00:00 2001 From: DianQK Date: Tue, 18 Jul 2023 22:15:47 +0800 Subject: Add the `no-builtins` attribute to functions when `no_builtins` is applied at the crate level. When `no_builtins` is applied at the crate level, we should add the `no-builtins` attribute to each function to ensure it takes effect in LTO. --- compiler/rustc_codegen_llvm/src/attributes.rs | 4 ++++ compiler/rustc_codegen_ssa/src/codegen_attrs.rs | 10 ++++++++- .../rustc_middle/src/middle/codegen_fn_attrs.rs | 2 ++ tests/codegen/no_builtins-at-crate.rs | 24 ++++++++++++++++++++++ tests/run-make/no-builtins-attribute/Makefile | 9 ++++++++ .../no-builtins-attribute/filecheck.main.txt | 5 +++++ tests/run-make/no-builtins-attribute/main.rs | 10 +++++++++ .../run-make/no-builtins-attribute/no_builtins.rs | 5 +++++ 8 files changed, 68 insertions(+), 1 deletion(-) create mode 100644 tests/codegen/no_builtins-at-crate.rs create mode 100644 tests/run-make/no-builtins-attribute/Makefile create mode 100644 tests/run-make/no-builtins-attribute/filecheck.main.txt create mode 100644 tests/run-make/no-builtins-attribute/main.rs create mode 100644 tests/run-make/no-builtins-attribute/no_builtins.rs (limited to 'compiler/rustc_codegen_llvm/src') diff --git a/compiler/rustc_codegen_llvm/src/attributes.rs b/compiler/rustc_codegen_llvm/src/attributes.rs index 39275272e42..4c69b9503a2 100644 --- a/compiler/rustc_codegen_llvm/src/attributes.rs +++ b/compiler/rustc_codegen_llvm/src/attributes.rs @@ -335,6 +335,10 @@ pub fn from_fn_attrs<'ll, 'tcx>( to_add.extend(probestack_attr(cx)); to_add.extend(stackprotector_attr(cx)); + if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::NO_BUILTINS) { + to_add.push(llvm::CreateAttrString(cx.llcx, "no-builtins")); + } + if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::COLD) { to_add.push(AttributeKind::Cold.create_attr(cx.llcx)); } diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs index d6c23012762..0c7b8a79612 100644 --- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs +++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs @@ -1,4 +1,4 @@ -use rustc_ast::{ast, MetaItemKind, NestedMetaItem}; +use rustc_ast::{ast, attr, MetaItemKind, NestedMetaItem}; use rustc_attr::{list_contains_name, InlineAttr, InstructionSetAttr, OptimizeAttr}; use rustc_errors::struct_span_err; use rustc_hir as hir; @@ -60,6 +60,14 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { codegen_fn_attrs.flags |= CodegenFnAttrFlags::TRACK_CALLER; } + // When `no_builtins` is applied at the crate level, we should add the + // `no-builtins` attribute to each function to ensure it takes effect in LTO. + let crate_attrs = tcx.hir().attrs(rustc_hir::CRATE_HIR_ID); + let no_builtins = attr::contains_name(crate_attrs, sym::no_builtins); + if no_builtins { + codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_BUILTINS; + } + let supported_target_features = tcx.supported_target_features(LOCAL_CRATE); let mut inline_span = None; diff --git a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs index c4601a1fb41..02fd6ed7ba6 100644 --- a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs +++ b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs @@ -100,6 +100,8 @@ bitflags! { const REALLOCATOR = 1 << 18; /// `#[rustc_allocator_zeroed]`: a hint to LLVM that the function only allocates zeroed memory. const ALLOCATOR_ZEROED = 1 << 19; + /// `#[no_builtins]`: indicates that disable implicit builtin knowledge of functions for the function. + const NO_BUILTINS = 1 << 20; } } diff --git a/tests/codegen/no_builtins-at-crate.rs b/tests/codegen/no_builtins-at-crate.rs new file mode 100644 index 00000000000..02ed670900e --- /dev/null +++ b/tests/codegen/no_builtins-at-crate.rs @@ -0,0 +1,24 @@ +// compile-flags: -C opt-level=1 + +#![no_builtins] +#![crate_type = "lib"] + +// CHECK: define +// CHECK-SAME: @__aeabi_memcpy +// CHECK-SAME: #0 +#[no_mangle] +pub unsafe extern "C" fn __aeabi_memcpy(dest: *mut u8, src: *const u8, size: usize) { + // CHECK: call + // CHECK-SAME: @memcpy( + memcpy(dest, src, size); +} + +// CHECK: declare +// CHECK-SAME: @memcpy +// CHECK-SAME: #0 +extern "C" { + pub fn memcpy(dest: *mut u8, src: *const u8, n: usize) -> *mut u8; +} + +// CHECK: attributes #0 +// CHECK-SAME: "no-builtins" diff --git a/tests/run-make/no-builtins-attribute/Makefile b/tests/run-make/no-builtins-attribute/Makefile new file mode 100644 index 00000000000..0ce95facaea --- /dev/null +++ b/tests/run-make/no-builtins-attribute/Makefile @@ -0,0 +1,9 @@ +include ../tools.mk + +# We want to check if `no-builtins` is also added to the function declarations in the used crate. + +all: + $(RUSTC) no_builtins.rs --emit=link + $(RUSTC) main.rs --emit=llvm-ir + + cat "$(TMPDIR)"/main.ll | "$(LLVM_FILECHECK)" filecheck.main.txt diff --git a/tests/run-make/no-builtins-attribute/filecheck.main.txt b/tests/run-make/no-builtins-attribute/filecheck.main.txt new file mode 100644 index 00000000000..ecd650bdca8 --- /dev/null +++ b/tests/run-make/no-builtins-attribute/filecheck.main.txt @@ -0,0 +1,5 @@ +CHECK: declare void @foo() +CHECK-SAME: #[[ATTR_3:[0-9]+]] + +CHECK: attributes #[[ATTR_3]] +CHECK-SAME: no-builtins diff --git a/tests/run-make/no-builtins-attribute/main.rs b/tests/run-make/no-builtins-attribute/main.rs new file mode 100644 index 00000000000..77754b37e31 --- /dev/null +++ b/tests/run-make/no-builtins-attribute/main.rs @@ -0,0 +1,10 @@ +extern crate no_builtins; + +#[no_mangle] +fn call_foo() { + no_builtins::foo(); +} + +fn main() { + call_foo(); +} diff --git a/tests/run-make/no-builtins-attribute/no_builtins.rs b/tests/run-make/no-builtins-attribute/no_builtins.rs new file mode 100644 index 00000000000..8ca862d2f77 --- /dev/null +++ b/tests/run-make/no-builtins-attribute/no_builtins.rs @@ -0,0 +1,5 @@ +#![crate_type = "lib"] +#![no_builtins] + +#[no_mangle] +pub fn foo() {} -- cgit 1.4.1-3-g733a5