Support .comment section like GCC/Clang (!llvm.ident)

Both GCC and Clang write by default a `.comment` section with compiler
information:

```txt
$ gcc -c -xc /dev/null && readelf -p '.comment' null.o

String dump of section '.comment':
  [     1]  GCC: (GNU) 11.2.0

$ clang -c -xc /dev/null && readelf -p '.comment' null.o

String dump of section '.comment':
  [     1]  clang version 14.0.1 (https://github.com/llvm/llvm-project.git c62053979489ccb002efe411c3af059addcb5d7d)
```

They also implement the `-Qn` flag to avoid doing so:

```txt
$ gcc -Qn -c -xc /dev/null && readelf -p '.comment' null.o
readelf: Warning: Section '.comment' was not dumped because it does not exist!

$ clang -Qn -c -xc /dev/null && readelf -p '.comment' null.o
readelf: Warning: Section '.comment' was not dumped because it does not exist!
```

So far, `rustc` only does it for WebAssembly targets and only
when debug info is enabled:

```txt
$ echo 'fn main(){}' | rustc --target=wasm32-unknown-unknown --emit=llvm-ir -Cdebuginfo=2 - && grep llvm.ident rust_out.ll
!llvm.ident = !{!27}
```

In the RFC part of this PR it was decided to always add
the information, which gets us closer to other popular compilers.
An opt-out flag like GCC and Clang may be added later on if deemed
necessary.

Implementation-wise, this covers both `ModuleLlvm::new()` and
`ModuleLlvm::new_metadata()` cases by moving the addition to
`context::create_module` and adds a few test cases.

ThinLTO also sees the `llvm.ident` named metadata duplicated (in
temporary outputs), so this deduplicates it like it is done for
`wasm.custom_sections`. The tests also check this duplication does
not take place.

Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
This commit is contained in:
Miguel Ojeda 2022-05-29 01:10:44 +02:00
parent c3c5a5c5f7
commit 74b8d324eb
6 changed files with 72 additions and 15 deletions

View file

@ -33,6 +33,7 @@ use rustc_target::abi::{
use rustc_target::spec::{HasTargetSpec, RelocModel, Target, TlsModel};
use smallvec::SmallVec;
use libc::c_uint;
use std::cell::{Cell, RefCell};
use std::ffi::CStr;
use std::str;
@ -349,6 +350,23 @@ pub unsafe fn create_module<'ll>(
);
}
// Insert `llvm.ident` metadata.
//
// On the wasm targets it will get hooked up to the "producer" sections
// `processed-by` information.
let rustc_producer =
format!("rustc version {}", option_env!("CFG_VERSION").expect("CFG_VERSION"));
let name_metadata = llvm::LLVMMDStringInContext(
llcx,
rustc_producer.as_ptr().cast(),
rustc_producer.as_bytes().len() as c_uint,
);
llvm::LLVMAddNamedMetadataOperand(
llmod,
cstr!("llvm.ident").as_ptr(),
llvm::LLVMMDNodeInContext(llcx, &name_metadata, 1),
);
llmod
}

View file

@ -888,21 +888,6 @@ pub fn build_compile_unit_di_node<'ll, 'tcx>(
llvm::LLVMAddNamedMetadataOperand(debug_context.llmod, llvm_gcov_ident.as_ptr(), val);
}
// Insert `llvm.ident` metadata on the wasm targets since that will
// get hooked up to the "producer" sections `processed-by` information.
if tcx.sess.target.is_like_wasm {
let name_metadata = llvm::LLVMMDStringInContext(
debug_context.llcontext,
rustc_producer.as_ptr().cast(),
rustc_producer.as_bytes().len() as c_uint,
);
llvm::LLVMAddNamedMetadataOperand(
debug_context.llmod,
cstr!("llvm.ident").as_ptr(),
llvm::LLVMMDNodeInContext(debug_context.llcontext, &name_metadata, 1),
);
}
return unit_metadata;
};