about summary refs log tree commit diff
path: root/compiler/rustc_codegen_llvm/src
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_codegen_llvm/src')
-rw-r--r--compiler/rustc_codegen_llvm/src/asm.rs18
-rw-r--r--compiler/rustc_codegen_llvm/src/back/command_line_args.rs37
-rw-r--r--compiler/rustc_codegen_llvm/src/back/command_line_args/tests.rs25
-rw-r--r--compiler/rustc_codegen_llvm/src/back/mod.rs1
-rw-r--r--compiler/rustc_codegen_llvm/src/back/owned_target_machine.rs14
-rw-r--r--compiler/rustc_codegen_llvm/src/back/write.rs40
-rw-r--r--compiler/rustc_codegen_llvm/src/intrinsic.rs3
-rw-r--r--compiler/rustc_codegen_llvm/src/lib.rs16
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm/ffi.rs7
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm_util.rs2
10 files changed, 115 insertions, 48 deletions
diff --git a/compiler/rustc_codegen_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs
index b79176e9098..cc09fa5b69b 100644
--- a/compiler/rustc_codegen_llvm/src/asm.rs
+++ b/compiler/rustc_codegen_llvm/src/asm.rs
@@ -340,8 +340,8 @@ impl<'ll, 'tcx> AsmBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
             attrs.push(llvm::AttributeKind::WillReturn.create_attr(self.cx.llcx));
         } else if options.contains(InlineAsmOptions::NOMEM) {
             attrs.push(llvm::MemoryEffects::InaccessibleMemOnly.create_attr(self.cx.llcx));
-        } else {
-            // LLVM doesn't have an attribute to represent ReadOnly + SideEffect
+        } else if options.contains(InlineAsmOptions::READONLY) {
+            attrs.push(llvm::MemoryEffects::ReadOnlyNotPure.create_attr(self.cx.llcx));
         }
         attributes::apply_to_callsite(result, llvm::AttributePlace::Function, &{ attrs });
 
@@ -662,7 +662,12 @@ fn reg_to_llvm(reg: InlineAsmRegOrRegClass, layout: Option<&TyAndLayout<'_>>) ->
             PowerPC(PowerPCInlineAsmRegClass::reg_nonzero) => "b",
             PowerPC(PowerPCInlineAsmRegClass::freg) => "f",
             PowerPC(PowerPCInlineAsmRegClass::vreg) => "v",
-            PowerPC(PowerPCInlineAsmRegClass::cr) | PowerPC(PowerPCInlineAsmRegClass::xer) => {
+            PowerPC(
+                PowerPCInlineAsmRegClass::cr
+                | PowerPCInlineAsmRegClass::ctr
+                | PowerPCInlineAsmRegClass::lr
+                | PowerPCInlineAsmRegClass::xer,
+            ) => {
                 unreachable!("clobber-only")
             }
             RiscV(RiscVInlineAsmRegClass::reg) => "r",
@@ -830,7 +835,12 @@ fn dummy_output_type<'ll>(cx: &CodegenCx<'ll, '_>, reg: InlineAsmRegClass) -> &'
         PowerPC(PowerPCInlineAsmRegClass::reg_nonzero) => cx.type_i32(),
         PowerPC(PowerPCInlineAsmRegClass::freg) => cx.type_f64(),
         PowerPC(PowerPCInlineAsmRegClass::vreg) => cx.type_vector(cx.type_i32(), 4),
-        PowerPC(PowerPCInlineAsmRegClass::cr) | PowerPC(PowerPCInlineAsmRegClass::xer) => {
+        PowerPC(
+            PowerPCInlineAsmRegClass::cr
+            | PowerPCInlineAsmRegClass::ctr
+            | PowerPCInlineAsmRegClass::lr
+            | PowerPCInlineAsmRegClass::xer,
+        ) => {
             unreachable!("clobber-only")
         }
         RiscV(RiscVInlineAsmRegClass::reg) => cx.type_i32(),
diff --git a/compiler/rustc_codegen_llvm/src/back/command_line_args.rs b/compiler/rustc_codegen_llvm/src/back/command_line_args.rs
new file mode 100644
index 00000000000..b14713969b3
--- /dev/null
+++ b/compiler/rustc_codegen_llvm/src/back/command_line_args.rs
@@ -0,0 +1,37 @@
+#[cfg(test)]
+mod tests;
+
+/// Joins command-line arguments into a single space-separated string, quoting
+/// and escaping individual arguments as necessary.
+///
+/// The result is intended to be informational, for embedding in debug metadata,
+/// and might not be properly quoted/escaped for actual command-line use.
+pub(crate) fn quote_command_line_args(args: &[String]) -> String {
+    // Start with a decent-sized buffer, since rustc invocations tend to be long.
+    let mut buf = String::with_capacity(128);
+
+    for arg in args {
+        if !buf.is_empty() {
+            buf.push(' ');
+        }
+
+        print_arg_quoted(&mut buf, arg);
+    }
+
+    buf
+}
+
+/// Equivalent to LLVM's `sys::printArg` with quoting always enabled
+/// (see llvm/lib/Support/Program.cpp).
+fn print_arg_quoted(buf: &mut String, arg: &str) {
+    buf.reserve(arg.len() + 2);
+
+    buf.push('"');
+    for ch in arg.chars() {
+        if matches!(ch, '"' | '\\' | '$') {
+            buf.push('\\');
+        }
+        buf.push(ch);
+    }
+    buf.push('"');
+}
diff --git a/compiler/rustc_codegen_llvm/src/back/command_line_args/tests.rs b/compiler/rustc_codegen_llvm/src/back/command_line_args/tests.rs
new file mode 100644
index 00000000000..69641fed3bc
--- /dev/null
+++ b/compiler/rustc_codegen_llvm/src/back/command_line_args/tests.rs
@@ -0,0 +1,25 @@
+#[test]
+fn quote_command_line_args() {
+    use super::quote_command_line_args;
+
+    struct Case<'a> {
+        args: &'a [&'a str],
+        expected: &'a str,
+    }
+
+    let cases = &[
+        Case { args: &[], expected: "" },
+        Case { args: &["--hello", "world"], expected: r#""--hello" "world""# },
+        Case { args: &["--hello world"], expected: r#""--hello world""# },
+        Case {
+            args: &["plain", "$dollar", "spa ce", r"back\slash", r#""quote""#, "plain"],
+            expected: r#""plain" "\$dollar" "spa ce" "back\\slash" "\"quote\"" "plain""#,
+        },
+    ];
+
+    for &Case { args, expected } in cases {
+        let args = args.iter().copied().map(str::to_owned).collect::<Vec<_>>();
+        let actual = quote_command_line_args(&args);
+        assert_eq!(actual, expected, "args {args:?}");
+    }
+}
diff --git a/compiler/rustc_codegen_llvm/src/back/mod.rs b/compiler/rustc_codegen_llvm/src/back/mod.rs
index 6cb89f80ab8..fe3883e8c73 100644
--- a/compiler/rustc_codegen_llvm/src/back/mod.rs
+++ b/compiler/rustc_codegen_llvm/src/back/mod.rs
@@ -1,4 +1,5 @@
 pub(crate) mod archive;
+mod command_line_args;
 pub(crate) mod lto;
 pub(crate) mod owned_target_machine;
 mod profiling;
diff --git a/compiler/rustc_codegen_llvm/src/back/owned_target_machine.rs b/compiler/rustc_codegen_llvm/src/back/owned_target_machine.rs
index 6d8178320fe..d5228f0e0de 100644
--- a/compiler/rustc_codegen_llvm/src/back/owned_target_machine.rs
+++ b/compiler/rustc_codegen_llvm/src/back/owned_target_machine.rs
@@ -1,4 +1,3 @@
-use std::assert_matches::assert_matches;
 use std::ffi::CStr;
 use std::marker::PhantomData;
 use std::ptr::NonNull;
@@ -39,13 +38,10 @@ impl OwnedTargetMachine {
         output_obj_file: &CStr,
         debug_info_compression: &CStr,
         use_emulated_tls: bool,
-        args_cstr_buff: &[u8],
+        argv0: &str,
+        command_line_args: &str,
         use_wasm_eh: bool,
     ) -> Result<Self, LlvmError<'static>> {
-        // The argument list is passed as the concatenation of one or more C strings.
-        // This implies that there must be a last byte, and it must be 0.
-        assert_matches!(args_cstr_buff, [.., b'\0'], "the last byte must be a NUL terminator");
-
         // SAFETY: llvm::LLVMRustCreateTargetMachine copies pointed to data
         let tm_ptr = unsafe {
             llvm::LLVMRustCreateTargetMachine(
@@ -70,8 +66,10 @@ impl OwnedTargetMachine {
                 output_obj_file.as_ptr(),
                 debug_info_compression.as_ptr(),
                 use_emulated_tls,
-                args_cstr_buff.as_ptr(),
-                args_cstr_buff.len(),
+                argv0.as_ptr(),
+                argv0.len(),
+                command_line_args.as_ptr(),
+                command_line_args.len(),
                 use_wasm_eh,
             )
         };
diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs
index bda81fbd19e..1950b8288d1 100644
--- a/compiler/rustc_codegen_llvm/src/back/write.rs
+++ b/compiler/rustc_codegen_llvm/src/back/write.rs
@@ -31,6 +31,7 @@ use rustc_span::{BytePos, InnerSpan, Pos, SpanData, SyntaxContext, sym};
 use rustc_target::spec::{CodeModel, FloatAbi, RelocModel, SanitizerSet, SplitDebuginfo, TlsModel};
 use tracing::{debug, trace};
 
+use crate::back::command_line_args::quote_command_line_args;
 use crate::back::lto::ThinBuffer;
 use crate::back::owned_target_machine::OwnedTargetMachine;
 use crate::back::profiling::{
@@ -203,6 +204,9 @@ pub(crate) fn target_machine_factory(
     optlvl: config::OptLevel,
     target_features: &[String],
 ) -> TargetMachineFactoryFn<LlvmCodegenBackend> {
+    // Self-profile timer for creating a _factory_.
+    let _prof_timer = sess.prof.generic_activity("target_machine_factory");
+
     let reloc_model = to_llvm_relocation_model(sess.relocation_model());
 
     let (opt_level, _) = to_llvm_opt_settings(optlvl);
@@ -249,23 +253,18 @@ pub(crate) fn target_machine_factory(
 
     let use_emulated_tls = matches!(sess.tls_model(), TlsModel::Emulated);
 
-    // copy the exe path, followed by path all into one buffer
-    // null terminating them so we can use them as null terminated strings
-    let args_cstr_buff = {
-        let mut args_cstr_buff: Vec<u8> = Vec::new();
-        let exe_path = std::env::current_exe().unwrap_or_default();
-        let exe_path_str = exe_path.into_os_string().into_string().unwrap_or_default();
-
-        args_cstr_buff.extend_from_slice(exe_path_str.as_bytes());
-        args_cstr_buff.push(0);
-
-        for arg in sess.expanded_args.iter() {
-            args_cstr_buff.extend_from_slice(arg.as_bytes());
-            args_cstr_buff.push(0);
-        }
-
-        args_cstr_buff
-    };
+    // Command-line information to be included in the target machine.
+    // This seems to only be used for embedding in PDB debuginfo files.
+    // FIXME(Zalathar): Maybe skip this for non-PDB targets?
+    let argv0 = std::env::current_exe()
+        .unwrap_or_default()
+        .into_os_string()
+        .into_string()
+        .unwrap_or_default();
+    let command_line_args = quote_command_line_args(&sess.expanded_args);
+    // Self-profile counter for the number of bytes produced by command-line quoting.
+    // Values are summed, so the summary result is cumulative across all TM factories.
+    sess.prof.artifact_size("quoted_command_line_args", "-", command_line_args.len() as u64);
 
     let debuginfo_compression = sess.opts.debuginfo_compression.to_string();
     match sess.opts.debuginfo_compression {
@@ -288,7 +287,11 @@ pub(crate) fn target_machine_factory(
 
     let use_wasm_eh = wants_wasm_eh(sess);
 
+    let prof = SelfProfilerRef::clone(&sess.prof);
     Arc::new(move |config: TargetMachineFactoryConfig| {
+        // Self-profile timer for invoking a factory to create a target machine.
+        let _prof_timer = prof.generic_activity("target_machine_factory_inner");
+
         let path_to_cstring_helper = |path: Option<PathBuf>| -> CString {
             let path = path.unwrap_or_default();
             let path = path_mapping
@@ -323,7 +326,8 @@ pub(crate) fn target_machine_factory(
             &output_obj_file,
             &debuginfo_compression,
             use_emulated_tls,
-            &args_cstr_buff,
+            &argv0,
+            &command_line_args,
             use_wasm_eh,
         )
     })
diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs
index e7f4a357048..50398a32142 100644
--- a/compiler/rustc_codegen_llvm/src/intrinsic.rs
+++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs
@@ -18,7 +18,6 @@ use rustc_middle::{bug, span_bug};
 use rustc_span::{Span, Symbol, sym};
 use rustc_symbol_mangling::{mangle_internal_symbol, symbol_name_for_instance_in_crate};
 use rustc_target::callconv::PassMode;
-use rustc_target::spec::PanicStrategy;
 use tracing::debug;
 
 use crate::abi::FnAbiLlvmExt;
@@ -674,7 +673,7 @@ fn catch_unwind_intrinsic<'ll, 'tcx>(
     catch_func: &'ll Value,
     dest: PlaceRef<'tcx, &'ll Value>,
 ) {
-    if bx.sess().panic_strategy() == PanicStrategy::Abort {
+    if !bx.sess().panic_strategy().unwinds() {
         let try_func_ty = bx.type_func(&[bx.type_ptr()], bx.type_void());
         bx.call(try_func_ty, None, None, try_func, &[data], None, None);
         // Return 0 unconditionally from the intrinsic call;
diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs
index 6fb23d09843..13bdb7cb1a2 100644
--- a/compiler/rustc_codegen_llvm/src/lib.rs
+++ b/compiler/rustc_codegen_llvm/src/lib.rs
@@ -45,6 +45,7 @@ use rustc_middle::util::Providers;
 use rustc_session::Session;
 use rustc_session::config::{OptLevel, OutputFilenames, PrintKind, PrintRequest};
 use rustc_span::Symbol;
+use rustc_target::spec::{RelocModel, TlsModel};
 
 mod abi;
 mod allocator;
@@ -244,16 +245,7 @@ impl CodegenBackend for LlvmCodegenBackend {
         match req.kind {
             PrintKind::RelocationModels => {
                 writeln!(out, "Available relocation models:").unwrap();
-                for name in &[
-                    "static",
-                    "pic",
-                    "pie",
-                    "dynamic-no-pic",
-                    "ropi",
-                    "rwpi",
-                    "ropi-rwpi",
-                    "default",
-                ] {
+                for name in RelocModel::ALL.iter().map(RelocModel::desc).chain(["default"]) {
                     writeln!(out, "    {name}").unwrap();
                 }
                 writeln!(out).unwrap();
@@ -267,9 +259,7 @@ impl CodegenBackend for LlvmCodegenBackend {
             }
             PrintKind::TlsModels => {
                 writeln!(out, "Available TLS models:").unwrap();
-                for name in
-                    &["global-dynamic", "local-dynamic", "initial-exec", "local-exec", "emulated"]
-                {
+                for name in TlsModel::ALL.iter().map(TlsModel::desc) {
                     writeln!(out, "    {name}").unwrap();
                 }
                 writeln!(out).unwrap();
diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
index 1124ebc3d44..fd972f371df 100644
--- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
@@ -710,6 +710,7 @@ pub(crate) enum MemoryEffects {
     None,
     ReadOnly,
     InaccessibleMemOnly,
+    ReadOnlyNotPure,
 }
 
 /// LLVMOpcode
@@ -2491,8 +2492,10 @@ unsafe extern "C" {
         OutputObjFile: *const c_char,
         DebugInfoCompression: *const c_char,
         UseEmulatedTls: bool,
-        ArgsCstrBuff: *const c_uchar, // See "PTR_LEN_STR".
-        ArgsCstrBuffLen: usize,
+        Argv0: *const c_uchar, // See "PTR_LEN_STR".
+        Argv0Len: size_t,
+        CommandLineArgs: *const c_uchar, // See "PTR_LEN_STR".
+        CommandLineArgsLen: size_t,
         UseWasmEH: bool,
     ) -> *mut TargetMachine;
 
diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs
index 45c5c9aa551..3b920168e06 100644
--- a/compiler/rustc_codegen_llvm/src/llvm_util.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs
@@ -106,7 +106,7 @@ unsafe fn configure_llvm(sess: &Session) {
 
         if sess.target.os == "emscripten"
             && !sess.opts.unstable_opts.emscripten_wasm_eh
-            && sess.panic_strategy() == PanicStrategy::Unwind
+            && sess.panic_strategy().unwinds()
         {
             add("-enable-emscripten-cxx-exceptions", false);
         }