Skip to content

Commit

Permalink
Auto merge of #87570 - nikic:llvm-13, r=nagisa
Browse files Browse the repository at this point in the history
Upgrade to LLVM 13

Work in progress update to LLVM 13. Main changes:

 * InlineAsm diagnostics reported using SrcMgr diagnostic kind are now handled. Previously these used a separate diag handler.
 * Codegen tests are updated for additional attributes.
 * Some data layouts have changed.
 * Switch `#[used]` attribute from `llvm.used` to `llvm.compiler.used` to avoid SHF_GNU_RETAIN flag introduced in https://reviews.llvm.org/D97448, which appears to trigger a bug in older versions of gold.
 * Set `LLVM_INCLUDE_TESTS=OFF` to avoid Python 3.6 requirement.

Upstream issues:

 * ~~https://bugs.llvm.org/show_bug.cgi?id=51210 (InlineAsm diagnostic reporting for module asm)~~ Fixed by llvm/llvm-project@1558bb8.
 * ~~https://bugs.llvm.org/show_bug.cgi?id=51476 (Miscompile on AArch64 due to incorrect comparison elimination)~~ Fixed by llvm/llvm-project@81b1065.
 * https://bugs.llvm.org/show_bug.cgi?id=51207 (Can't set custom section flags anymore). Problematic change reverted in our fork, https://reviews.llvm.org/D107216 posted for upstream revert.
 * https://bugs.llvm.org/show_bug.cgi?id=51211 (Regression in codegen for #83623). This is an optimization regression that we may likely have to eat for this release. The fix for #83623 was based on an incorrect premise, and this needs to be properly addressed in the MergeICmps pass.

The [compile-time impact](https://perf.rust-lang.org/compare.html?start=ef9549b6c0efb7525c9b012148689c8d070f9bc0&end=0983094463497eec22d550dad25576a894687002) is mixed, but quite positive as LLVM upgrades go.

The LLVM 13 final release is scheduled for Sep 21st. The current nightly is scheduled for stable release on Oct 21st.

r? `@ghost`
  • Loading branch information
bors committed Aug 21, 2021
2 parents e7f7fe4 + 306259c commit db002a0
Show file tree
Hide file tree
Showing 30 changed files with 201 additions and 168 deletions.
2 changes: 1 addition & 1 deletion .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
[submodule "src/llvm-project"]
path = src/llvm-project
url = https://github.com/rust-lang/llvm-project.git
branch = rustc/12.0-2021-07-10
branch = rustc/13.0-2021-08-08
[submodule "src/doc/embedded-book"]
path = src/doc/embedded-book
url = https://github.com/rust-embedded/book.git
Expand Down
43 changes: 3 additions & 40 deletions compiler/rustc_codegen_llvm/src/back/write.rs
Original file line number Diff line number Diff line change
Expand Up @@ -296,39 +296,8 @@ unsafe extern "C" fn inline_asm_handler(diag: &SMDiagnostic, user: *const c_void
}
let (cgcx, _) = *(user as *const (&CodegenContext<LlvmCodegenBackend>, &Handler));

// Recover the post-substitution assembly code from LLVM for better
// diagnostics.
let mut have_source = false;
let mut buffer = String::new();
let mut level = llvm::DiagnosticLevel::Error;
let mut loc = 0;
let mut ranges = [0; 8];
let mut num_ranges = ranges.len() / 2;
let msg = llvm::build_string(|msg| {
buffer = llvm::build_string(|buffer| {
have_source = llvm::LLVMRustUnpackSMDiagnostic(
diag,
msg,
buffer,
&mut level,
&mut loc,
ranges.as_mut_ptr(),
&mut num_ranges,
);
})
.expect("non-UTF8 inline asm");
})
.expect("non-UTF8 SMDiagnostic");

let source = have_source.then(|| {
let mut spans = vec![InnerSpan::new(loc as usize, loc as usize)];
for i in 0..num_ranges {
spans.push(InnerSpan::new(ranges[i * 2] as usize, ranges[i * 2 + 1] as usize));
}
(buffer, spans)
});

report_inline_asm(cgcx, msg, level, cookie, source);
let smdiag = llvm::diagnostic::SrcMgrDiagnostic::unpack(diag);
report_inline_asm(cgcx, smdiag.message, smdiag.level, cookie, smdiag.source);
}

unsafe extern "C" fn diagnostic_handler(info: &DiagnosticInfo, user: *mut c_void) {
Expand All @@ -339,13 +308,7 @@ unsafe extern "C" fn diagnostic_handler(info: &DiagnosticInfo, user: *mut c_void

match llvm::diagnostic::Diagnostic::unpack(info) {
llvm::diagnostic::InlineAsm(inline) => {
report_inline_asm(
cgcx,
llvm::twine_to_string(inline.message),
inline.level,
inline.cookie,
None,
);
report_inline_asm(cgcx, inline.message, inline.level, inline.cookie, inline.source);
}

llvm::diagnostic::Optimization(opt) => {
Expand Down
8 changes: 5 additions & 3 deletions compiler/rustc_codegen_llvm/src/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -157,16 +157,18 @@ pub fn compile_codegen_unit(
}

// Finalize code coverage by injecting the coverage map. Note, the coverage map will
// also be added to the `llvm.used` variable, created next.
// also be added to the `llvm.compiler.used` variable, created next.
if cx.sess().instrument_coverage() {
cx.coverageinfo_finalize();
}

// Create the llvm.used variable
// This variable has type [N x i8*] and is stored in the llvm.metadata section
// Create the llvm.used and llvm.compiler.used variables.
if !cx.used_statics().borrow().is_empty() {
cx.create_used_variable()
}
if !cx.compiler_used_statics().borrow().is_empty() {
cx.create_compiler_used_variable()
}

// Finalize debuginfo
if cx.sess().opts.debuginfo != DebugInfo::None {
Expand Down
15 changes: 14 additions & 1 deletion compiler/rustc_codegen_llvm/src/consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -474,7 +474,13 @@ impl StaticMethods for CodegenCx<'ll, 'tcx> {
}

if attrs.flags.contains(CodegenFnAttrFlags::USED) {
self.add_used_global(g);
// The semantics of #[used] in Rust only require the symbol to make it into the
// object file. It is explicitly allowed for the linker to strip the symbol if it
// is dead. As such, use llvm.compiler.used instead of llvm.used.
// Additionally, https://reviews.llvm.org/D97448 in LLVM 13 started emitting unique
// sections with SHF_GNU_RETAIN flag for llvm.used symbols, which may trigger bugs
// in some versions of the gold linker.
self.add_compiler_used_global(g);
}
}
}
Expand All @@ -484,4 +490,11 @@ impl StaticMethods for CodegenCx<'ll, 'tcx> {
let cast = unsafe { llvm::LLVMConstPointerCast(global, self.type_i8p()) };
self.used_statics.borrow_mut().push(cast);
}

/// Add a global value to a list to be stored in the `llvm.compiler.used` variable,
/// an array of i8*.
fn add_compiler_used_global(&self, global: &'ll Value) {
let cast = unsafe { llvm::LLVMConstPointerCast(global, self.type_i8p()) };
self.compiler_used_statics.borrow_mut().push(cast);
}
}
55 changes: 40 additions & 15 deletions compiler/rustc_codegen_llvm/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,10 @@ pub struct CodegenCx<'ll, 'tcx> {
/// See <https://llvm.org/docs/LangRef.html#the-llvm-used-global-variable> for details
pub used_statics: RefCell<Vec<&'ll Value>>,

/// Statics that will be placed in the llvm.compiler.used variable
/// See <https://llvm.org/docs/LangRef.html#the-llvm-compiler-used-global-variable> for details
pub compiler_used_statics: RefCell<Vec<&'ll Value>>,

/// Mapping of non-scalar types to llvm types and field remapping if needed.
pub type_lowering: RefCell<FxHashMap<(Ty<'tcx>, Option<VariantIdx>), TypeLowering<'ll>>>,

Expand Down Expand Up @@ -115,10 +119,6 @@ fn to_llvm_tls_model(tls_model: TlsModel) -> llvm::ThreadLocalMode {
}
}

fn strip_powerpc64_vectors(data_layout: String) -> String {
data_layout.replace("-v256:256:256-v512:512:512", "")
}

pub unsafe fn create_module(
tcx: TyCtxt<'_>,
llcx: &'ll llvm::Context,
Expand All @@ -130,7 +130,18 @@ pub unsafe fn create_module(

let mut target_data_layout = sess.target.data_layout.clone();
if llvm_util::get_version() < (12, 0, 0) && sess.target.arch == "powerpc64" {
target_data_layout = strip_powerpc64_vectors(target_data_layout);
target_data_layout = target_data_layout.replace("-v256:256:256-v512:512:512", "");
}
if llvm_util::get_version() < (13, 0, 0) {
if sess.target.arch == "powerpc64" {
target_data_layout = target_data_layout.replace("-S128", "");
}
if sess.target.arch == "wasm32" {
target_data_layout = "e-m:e-p:32:32-i64:64-n32:64-S128".to_string();
}
if sess.target.arch == "wasm64" {
target_data_layout = "e-m:e-p:64:64-i64:64-n32:64-S128".to_string();
}
}

// Ensure the data-layout values hardcoded remain the defaults.
Expand Down Expand Up @@ -318,6 +329,7 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
const_globals: Default::default(),
statics_to_rauw: RefCell::new(Vec::new()),
used_statics: RefCell::new(Vec::new()),
compiler_used_statics: RefCell::new(Vec::new()),
type_lowering: Default::default(),
scalar_lltypes: Default::default(),
pointee_infos: Default::default(),
Expand All @@ -340,6 +352,18 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
pub fn coverage_context(&'a self) -> Option<&'a coverageinfo::CrateCoverageContext<'ll, 'tcx>> {
self.coverage_cx.as_ref()
}

fn create_used_variable_impl(&self, name: &'static CStr, values: &[&'ll Value]) {
let section = cstr!("llvm.metadata");
let array = self.const_array(&self.type_ptr_to(self.type_i8()), values);

unsafe {
let g = llvm::LLVMAddGlobal(self.llmod, self.val_ty(array), name.as_ptr());
llvm::LLVMSetInitializer(g, array);
llvm::LLVMRustSetLinkage(g, llvm::Linkage::AppendingLinkage);
llvm::LLVMSetSection(g, section.as_ptr());
}
}
}

impl MiscMethods<'tcx> for CodegenCx<'ll, 'tcx> {
Expand Down Expand Up @@ -430,6 +454,10 @@ impl MiscMethods<'tcx> for CodegenCx<'ll, 'tcx> {
&self.used_statics
}

fn compiler_used_statics(&self) -> &RefCell<Vec<&'ll Value>> {
&self.compiler_used_statics
}

fn set_frame_pointer_type(&self, llfn: &'ll Value) {
attributes::set_frame_pointer_type(self, llfn)
}
Expand All @@ -440,17 +468,14 @@ impl MiscMethods<'tcx> for CodegenCx<'ll, 'tcx> {
}

fn create_used_variable(&self) {
let name = cstr!("llvm.used");
let section = cstr!("llvm.metadata");
let array =
self.const_array(&self.type_ptr_to(self.type_i8()), &*self.used_statics.borrow());
self.create_used_variable_impl(cstr!("llvm.used"), &*self.used_statics.borrow());
}

unsafe {
let g = llvm::LLVMAddGlobal(self.llmod, self.val_ty(array), name.as_ptr());
llvm::LLVMSetInitializer(g, array);
llvm::LLVMRustSetLinkage(g, llvm::Linkage::AppendingLinkage);
llvm::LLVMSetSection(g, section.as_ptr());
}
fn create_compiler_used_variable(&self) {
self.create_used_variable_impl(
cstr!("llvm.compiler.used"),
&*self.compiler_used_statics.borrow(),
);
}

fn declare_c_main(&self, fn_type: Self::Type) -> Option<Self::Function> {
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_codegen_llvm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -352,8 +352,8 @@ impl ModuleLlvm {
impl Drop for ModuleLlvm {
fn drop(&mut self) {
unsafe {
llvm::LLVMContextDispose(&mut *(self.llcx as *mut _));
llvm::LLVMRustDisposeTargetMachine(&mut *(self.tm as *mut _));
llvm::LLVMContextDispose(&mut *(self.llcx as *mut _));
}
}
}
94 changes: 76 additions & 18 deletions compiler/rustc_codegen_llvm/src/llvm/diagnostic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ pub use self::OptimizationDiagnosticKind::*;
use crate::value::Value;
use libc::c_uint;

use super::{DiagnosticInfo, Twine};
use super::{DiagnosticInfo, SMDiagnostic};
use rustc_span::InnerSpan;

#[derive(Copy, Clone)]
pub enum OptimizationDiagnosticKind {
Expand Down Expand Up @@ -86,36 +87,91 @@ impl OptimizationDiagnostic<'ll> {
}
}

#[derive(Copy, Clone)]
pub struct InlineAsmDiagnostic<'ll> {
pub struct SrcMgrDiagnostic {
pub level: super::DiagnosticLevel,
pub message: String,
pub source: Option<(String, Vec<InnerSpan>)>,
}

impl SrcMgrDiagnostic {
pub unsafe fn unpack(diag: &SMDiagnostic) -> SrcMgrDiagnostic {
// Recover the post-substitution assembly code from LLVM for better
// diagnostics.
let mut have_source = false;
let mut buffer = String::new();
let mut level = super::DiagnosticLevel::Error;
let mut loc = 0;
let mut ranges = [0; 8];
let mut num_ranges = ranges.len() / 2;
let message = super::build_string(|message| {
buffer = super::build_string(|buffer| {
have_source = super::LLVMRustUnpackSMDiagnostic(
diag,
message,
buffer,
&mut level,
&mut loc,
ranges.as_mut_ptr(),
&mut num_ranges,
);
})
.expect("non-UTF8 inline asm");
})
.expect("non-UTF8 SMDiagnostic");

SrcMgrDiagnostic {
message,
level,
source: have_source.then(|| {
let mut spans = vec![InnerSpan::new(loc as usize, loc as usize)];
for i in 0..num_ranges {
spans.push(InnerSpan::new(ranges[i * 2] as usize, ranges[i * 2 + 1] as usize));
}
(buffer, spans)
}),
}
}
}

#[derive(Clone)]
pub struct InlineAsmDiagnostic {
pub level: super::DiagnosticLevel,
pub cookie: c_uint,
pub message: &'ll Twine,
pub instruction: Option<&'ll Value>,
pub message: String,
pub source: Option<(String, Vec<InnerSpan>)>,
}

impl InlineAsmDiagnostic<'ll> {
unsafe fn unpack(di: &'ll DiagnosticInfo) -> Self {
impl InlineAsmDiagnostic {
unsafe fn unpackInlineAsm(di: &'ll DiagnosticInfo) -> Self {
let mut cookie = 0;
let mut message = None;
let mut instruction = None;
let mut level = super::DiagnosticLevel::Error;

super::LLVMRustUnpackInlineAsmDiagnostic(
di,
&mut level,
&mut cookie,
&mut message,
&mut instruction,
);
super::LLVMRustUnpackInlineAsmDiagnostic(di, &mut level, &mut cookie, &mut message);

InlineAsmDiagnostic { level, cookie, message: message.unwrap(), instruction }
InlineAsmDiagnostic {
level,
cookie,
message: super::twine_to_string(message.unwrap()),
source: None,
}
}

unsafe fn unpackSrcMgr(di: &'ll DiagnosticInfo) -> Self {
let mut cookie = 0;
let smdiag = SrcMgrDiagnostic::unpack(super::LLVMRustGetSMDiagnostic(di, &mut cookie));
InlineAsmDiagnostic {
level: smdiag.level,
cookie,
message: smdiag.message,
source: smdiag.source,
}
}
}

pub enum Diagnostic<'ll> {
Optimization(OptimizationDiagnostic<'ll>),
InlineAsm(InlineAsmDiagnostic<'ll>),
InlineAsm(InlineAsmDiagnostic),
PGO(&'ll DiagnosticInfo),
Linker(&'ll DiagnosticInfo),
Unsupported(&'ll DiagnosticInfo),
Expand All @@ -130,7 +186,7 @@ impl Diagnostic<'ll> {
let kind = super::LLVMRustGetDiagInfoKind(di);

match kind {
Dk::InlineAsm => InlineAsm(InlineAsmDiagnostic::unpack(di)),
Dk::InlineAsm => InlineAsm(InlineAsmDiagnostic::unpackInlineAsm(di)),

Dk::OptimizationRemark => {
Optimization(OptimizationDiagnostic::unpack(OptimizationRemark, di))
Expand Down Expand Up @@ -162,6 +218,8 @@ impl Diagnostic<'ll> {
Dk::Linker => Linker(di),
Dk::Unsupported => Unsupported(di),

Dk::SrcMgr => InlineAsm(InlineAsmDiagnostic::unpackSrcMgr(di)),

_ => UnknownDiagnostic(di),
}
}
Expand Down
7 changes: 6 additions & 1 deletion compiler/rustc_codegen_llvm/src/llvm/ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -490,6 +490,7 @@ pub enum DiagnosticKind {
PGOProfile,
Linker,
Unsupported,
SrcMgr,
}

/// LLVMRustDiagnosticLevel
Expand Down Expand Up @@ -2264,13 +2265,17 @@ extern "C" {
level_out: &mut DiagnosticLevel,
cookie_out: &mut c_uint,
message_out: &mut Option<&'a Twine>,
instruction_out: &mut Option<&'a Value>,
);

#[allow(improper_ctypes)]
pub fn LLVMRustWriteDiagnosticInfoToString(DI: &DiagnosticInfo, s: &RustString);
pub fn LLVMRustGetDiagInfoKind(DI: &DiagnosticInfo) -> DiagnosticKind;

pub fn LLVMRustGetSMDiagnostic(
DI: &'a DiagnosticInfo,
cookie_out: &mut c_uint,
) -> &'a SMDiagnostic;

pub fn LLVMRustSetInlineAsmDiagnosticHandler(
C: &Context,
H: InlineAsmDiagHandler,
Expand Down

0 comments on commit db002a0

Please sign in to comment.