diff options
| author | Ralf Jung <post@ralfj.de> | 2024-11-10 09:29:44 +0000 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-11-10 09:29:44 +0000 |
| commit | a839fbf0a11bcfc2d594daeab3262f540d4b6178 (patch) | |
| tree | a0cb06654acfe3d0136f7e59c87b12f591903512 /compiler/rustc_codegen_llvm | |
| parent | 5ff90d069a2d9c1391c811278b9c50550e6861dc (diff) | |
| parent | a01f37c7f49b4bcdd4565bd642f68b289a25d832 (diff) | |
| download | rust-a839fbf0a11bcfc2d594daeab3262f540d4b6178.tar.gz rust-a839fbf0a11bcfc2d594daeab3262f540d4b6178.zip | |
Merge pull request #4021 from RalfJung/rustup
Rustup
Diffstat (limited to 'compiler/rustc_codegen_llvm')
| -rw-r--r-- | compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs | 60 | ||||
| -rw-r--r-- | compiler/rustc_codegen_llvm/src/llvm/ffi.rs | 23 | ||||
| -rw-r--r-- | compiler/rustc_codegen_llvm/src/llvm/mod.rs | 9 | ||||
| -rw-r--r-- | compiler/rustc_codegen_llvm/src/llvm_util.rs | 11 |
4 files changed, 75 insertions, 28 deletions
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs b/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs index ac6c2fb1b83..0f1909486ec 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs @@ -1,11 +1,15 @@ +use std::collections::hash_map::Entry; + use rustc_codegen_ssa::mir::debuginfo::{DebugScope, FunctionDebugContext}; use rustc_codegen_ssa::traits::*; +use rustc_data_structures::fx::FxHashMap; use rustc_index::Idx; use rustc_index::bit_set::BitSet; use rustc_middle::mir::{Body, SourceScope}; use rustc_middle::ty::layout::FnAbiOf; use rustc_middle::ty::{self, Instance}; use rustc_session::config::DebugInfo; +use rustc_span::BytePos; use super::metadata::file_metadata; use super::utils::DIB; @@ -37,10 +41,20 @@ pub(crate) fn compute_mir_scopes<'ll, 'tcx>( None }; let mut instantiated = BitSet::new_empty(mir.source_scopes.len()); + let mut discriminators = FxHashMap::default(); // Instantiate all scopes. for idx in 0..mir.source_scopes.len() { let scope = SourceScope::new(idx); - make_mir_scope(cx, instance, mir, &variables, debug_context, &mut instantiated, scope); + make_mir_scope( + cx, + instance, + mir, + &variables, + debug_context, + &mut instantiated, + &mut discriminators, + scope, + ); } assert!(instantiated.count() == mir.source_scopes.len()); } @@ -52,6 +66,7 @@ fn make_mir_scope<'ll, 'tcx>( variables: &Option<BitSet<SourceScope>>, debug_context: &mut FunctionDebugContext<'tcx, &'ll DIScope, &'ll DILocation>, instantiated: &mut BitSet<SourceScope>, + discriminators: &mut FxHashMap<BytePos, u32>, scope: SourceScope, ) { if instantiated.contains(scope) { @@ -60,7 +75,16 @@ fn make_mir_scope<'ll, 'tcx>( let scope_data = &mir.source_scopes[scope]; let parent_scope = if let Some(parent) = scope_data.parent_scope { - make_mir_scope(cx, instance, mir, variables, debug_context, instantiated, parent); + make_mir_scope( + cx, + instance, + mir, + variables, + debug_context, + instantiated, + discriminators, + parent, + ); debug_context.scopes[parent] } else { // The root is the function itself. @@ -117,7 +141,37 @@ fn make_mir_scope<'ll, 'tcx>( // FIXME(eddyb) this doesn't account for the macro-related // `Span` fixups that `rustc_codegen_ssa::mir::debuginfo` does. let callsite_scope = parent_scope.adjust_dbg_scope_for_span(cx, callsite_span); - cx.dbg_loc(callsite_scope, parent_scope.inlined_at, callsite_span) + let loc = cx.dbg_loc(callsite_scope, parent_scope.inlined_at, callsite_span); + + // NB: In order to produce proper debug info for variables (particularly + // arguments) in multiply-inline functions, LLVM expects to see a single + // DILocalVariable with multiple different DILocations in the IR. While + // the source information for each DILocation would be identical, their + // inlinedAt attributes will be unique to the particular callsite. + // + // We generate DILocations here based on the callsite's location in the + // source code. A single location in the source code usually can't + // produce multiple distinct calls so this mostly works, until + // proc-macros get involved. A proc-macro can generate multiple calls + // at the same span, which breaks the assumption that we're going to + // produce a unique DILocation for every scope we process here. We + // have to explicitly add discriminators if we see inlines into the + // same source code location. + // + // Note further that we can't key this hashtable on the span itself, + // because these spans could have distinct SyntaxContexts. We have + // to key on exactly what we're giving to LLVM. + match discriminators.entry(callsite_span.lo()) { + Entry::Occupied(mut o) => { + *o.get_mut() += 1; + unsafe { llvm::LLVMRustDILocationCloneWithBaseDiscriminator(loc, *o.get()) } + .expect("Failed to encode discriminator in DILocation") + } + Entry::Vacant(v) => { + v.insert(0); + loc + } + } }); debug_context.scopes[scope] = DebugScope { diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 8508f87c8d3..75a5ec44c22 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -204,7 +204,7 @@ pub enum DLLStorageClass { DllExport = 2, // Function to be accessible from DLL. } -/// Matches LLVMRustAttribute in LLVMWrapper.h +/// Must match the layout of `LLVMRustAttributeKind`. /// Semantically a subset of the C++ enum llvm::Attribute::AttrKind, /// though it is not ABI compatible (since it's a C++ enum) #[repr(C)] @@ -1766,11 +1766,9 @@ unsafe extern "C" { pub fn LLVMRustGetLastError() -> *const c_char; /// Prints the timing information collected by `-Ztime-llvm-passes`. - #[expect(improper_ctypes)] pub(crate) fn LLVMRustPrintPassTimings(OutStr: &RustString); /// Prints the statistics collected by `-Zprint-codegen-stats`. - #[expect(improper_ctypes)] pub(crate) fn LLVMRustPrintStatistics(OutStr: &RustString); /// Prepares inline assembly. @@ -1791,7 +1789,6 @@ unsafe extern "C" { ConstraintsLen: size_t, ) -> bool; - #[allow(improper_ctypes)] pub(crate) fn LLVMRustCoverageWriteFilenamesToBuffer( Filenames: *const *const c_char, FilenamesLen: size_t, @@ -1800,7 +1797,6 @@ unsafe extern "C" { BufferOut: &RustString, ); - #[allow(improper_ctypes)] pub(crate) fn LLVMRustCoverageWriteFunctionMappingsToBuffer( VirtualFileMappingIDs: *const c_uint, NumVirtualFileMappingIDs: size_t, @@ -1824,13 +1820,10 @@ unsafe extern "C" { ) -> &Value; pub(crate) fn LLVMRustCoverageHashBytes(Bytes: *const c_char, NumBytes: size_t) -> u64; - #[allow(improper_ctypes)] pub(crate) fn LLVMRustCoverageWriteCovmapSectionNameToString(M: &Module, OutStr: &RustString); - #[allow(improper_ctypes)] pub(crate) fn LLVMRustCoverageWriteCovfunSectionNameToString(M: &Module, OutStr: &RustString); - #[allow(improper_ctypes)] pub(crate) fn LLVMRustCoverageWriteCovmapVarNameToString(OutStr: &RustString); pub(crate) fn LLVMRustCoverageMappingVersion() -> u32; @@ -2181,18 +2174,19 @@ unsafe extern "C" { Scope: &'a DIScope, InlinedAt: Option<&'a DILocation>, ) -> &'a DILocation; + pub fn LLVMRustDILocationCloneWithBaseDiscriminator<'a>( + Location: &'a DILocation, + BD: c_uint, + ) -> Option<&'a DILocation>; pub fn LLVMRustDIBuilderCreateOpDeref() -> u64; pub fn LLVMRustDIBuilderCreateOpPlusUconst() -> u64; pub fn LLVMRustDIBuilderCreateOpLLVMFragment() -> u64; - #[allow(improper_ctypes)] pub fn LLVMRustWriteTypeToString(Type: &Type, s: &RustString); - #[allow(improper_ctypes)] pub fn LLVMRustWriteValueToString(value_ref: &Value, s: &RustString); pub fn LLVMRustHasFeature(T: &TargetMachine, s: *const c_char) -> bool; - #[allow(improper_ctypes)] pub(crate) fn LLVMRustPrintTargetCPUs(TM: &TargetMachine, OutStr: &RustString); pub fn LLVMRustGetTargetFeaturesCount(T: &TargetMachine) -> size_t; pub fn LLVMRustGetTargetFeature( @@ -2297,10 +2291,8 @@ unsafe extern "C" { pub fn LLVMRustArchiveIteratorFree<'a>(AIR: &'a mut ArchiveIterator<'a>); pub fn LLVMRustDestroyArchive(AR: &'static mut Archive); - #[allow(improper_ctypes)] pub fn LLVMRustWriteTwineToString(T: &Twine, s: &RustString); - #[allow(improper_ctypes)] pub fn LLVMRustUnpackOptimizationDiagnostic<'a>( DI: &'a DiagnosticInfo, pass_name_out: &RustString, @@ -2318,7 +2310,6 @@ unsafe extern "C" { message_out: &mut Option<&'a Twine>, ); - #[allow(improper_ctypes)] pub fn LLVMRustWriteDiagnosticInfoToString(DI: &DiagnosticInfo, s: &RustString); pub fn LLVMRustGetDiagInfoKind(DI: &DiagnosticInfo) -> DiagnosticKind; @@ -2327,7 +2318,6 @@ unsafe extern "C" { cookie_out: &mut c_uint, ) -> &'a SMDiagnostic; - #[allow(improper_ctypes)] pub fn LLVMRustUnpackSMDiagnostic( d: &SMDiagnostic, message_out: &RustString, @@ -2374,7 +2364,6 @@ unsafe extern "C" { pub fn LLVMRustModuleBufferLen(p: &ModuleBuffer) -> usize; pub fn LLVMRustModuleBufferFree(p: &'static mut ModuleBuffer); pub fn LLVMRustModuleCost(M: &Module) -> u64; - #[allow(improper_ctypes)] pub fn LLVMRustModuleInstructionStats(M: &Module, Str: &RustString); pub fn LLVMRustThinLTOBufferCreate( @@ -2427,7 +2416,6 @@ unsafe extern "C" { bytecode_len: usize, ) -> bool; pub fn LLVMRustLinkerFree<'a>(linker: &'a mut Linker<'a>); - #[allow(improper_ctypes)] pub fn LLVMRustComputeLTOCacheKey( key_out: &RustString, mod_id: *const c_char, @@ -2450,7 +2438,6 @@ unsafe extern "C" { pgo_available: bool, ); - #[allow(improper_ctypes)] pub fn LLVMRustGetMangledName(V: &Value, out: &RustString); pub fn LLVMRustGetElementTypeArgIndex(CallSite: &Value) -> i32; diff --git a/compiler/rustc_codegen_llvm/src/llvm/mod.rs b/compiler/rustc_codegen_llvm/src/llvm/mod.rs index 3b0bf47366e..909afe35a17 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/mod.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/mod.rs @@ -1,6 +1,5 @@ #![allow(non_snake_case)] -use std::cell::RefCell; use std::ffi::{CStr, CString}; use std::ops::Deref; use std::ptr; @@ -301,15 +300,11 @@ pub fn set_value_name(value: &Value, name: &[u8]) { } pub fn build_string(f: impl FnOnce(&RustString)) -> Result<String, FromUtf8Error> { - let sr = RustString { bytes: RefCell::new(Vec::new()) }; - f(&sr); - String::from_utf8(sr.bytes.into_inner()) + String::from_utf8(RustString::build_byte_buffer(f)) } pub fn build_byte_buffer(f: impl FnOnce(&RustString)) -> Vec<u8> { - let sr = RustString { bytes: RefCell::new(Vec::new()) }; - f(&sr); - sr.bytes.into_inner() + RustString::build_byte_buffer(f) } pub fn twine_to_string(tr: &Twine) -> String { diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index 6f2d86cc601..c382242d8d0 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -228,6 +228,8 @@ pub(crate) fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> Option<LLVMFea "x86" } else if sess.target.arch == "arm64ec" { "aarch64" + } else if sess.target.arch == "sparc64" { + "sparc" } else { &*sess.target.arch }; @@ -280,6 +282,13 @@ pub(crate) fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> Option<LLVMFea // Support for `wide-arithmetic` will first land in LLVM 20 as part of // llvm/llvm-project#111598 ("wasm32" | "wasm64", "wide-arithmetic") if get_version() < (20, 0, 0) => None, + ("sparc", "leoncasa") => Some(LLVMFeature::new("hasleoncasa")), + // In LLVM 19, there is no `v8plus` feature and `v9` means "SPARC-V9 instruction available and SPARC-V8+ ABI used". + // https://github.com/llvm/llvm-project/blob/llvmorg-19.1.0/llvm/lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp#L27-L28 + // Before LLVM 19, there is no `v8plus` feature and `v9` means "SPARC-V9 instruction available". + // https://github.com/llvm/llvm-project/blob/llvmorg-18.1.0/llvm/lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp#L26 + ("sparc", "v8plus") if get_version().0 == 19 => Some(LLVMFeature::new("v9")), + ("sparc", "v8plus") if get_version().0 < 19 => None, (_, s) => Some(LLVMFeature::new(s)), } } @@ -619,6 +628,8 @@ pub(crate) fn global_llvm_features( .features .split(',') .filter(|v| !v.is_empty() && backend_feature_name(sess, v).is_some()) + // Drop +v8plus feature introduced in LLVM 20. + .filter(|v| *v != "+v8plus" || get_version() >= (20, 0, 0)) .map(String::from), ); |
