Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions compiler/rustc_codegen_cranelift/src/driver/aot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,7 @@ impl ExtraBackendMethods for AotDriver {
&self,
tcx: TyCtxt<'_>,
cgu_name: Symbol,
_bitcode_needed: bool,
) -> (ModuleCodegen<Self::Module>, u64) {
let start_time = Instant::now();

Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_codegen_gcc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -365,6 +365,7 @@ impl ExtraBackendMethods for GccCodegenBackend {
&self,
tcx: TyCtxt<'_>,
cgu_name: Symbol,
_bitcode_needed: bool,
) -> (ModuleCodegen<Self::Module>, u64) {
base::compile_codegen_unit(
tcx,
Expand Down
55 changes: 36 additions & 19 deletions compiler/rustc_codegen_llvm/src/asm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ use rustc_middle::mir::interpret::{PointerArithmetic, Scalar as ConstScalar};
use rustc_middle::ty::Instance;
use rustc_middle::ty::layout::TyAndLayout;
use rustc_middle::{bug, span_bug};
use rustc_session::Session;
use rustc_session::config::Lto;
use rustc_span::{Pos, Span, Symbol, sym};
use rustc_target::asm::*;
use rustc_target::spec::HasTargetSpec;
Expand Down Expand Up @@ -594,30 +596,45 @@ pub(crate) fn inline_asm_call<'ll>(
let key = "srcloc";
let kind = bx.get_md_kind_id(key);

// `srcloc` contains one 64-bit integer for each line of assembly code,
// where the lower 32 bits hold the lo byte position and the upper 32 bits
// hold the hi byte position.
let mut srcloc = vec![];
if dia == llvm::AsmDialect::Intel && line_spans.len() > 1 {
// LLVM inserts an extra line to add the ".intel_syntax", so add
// a dummy srcloc entry for it.
//
// Don't do this if we only have 1 line span since that may be
// due to the asm template string coming from a macro. LLVM will
// default to the first srcloc for lines that don't have an
// associated srcloc.
srcloc.push(llvm::LLVMValueAsMetadata(bx.const_u64(0)));
if allow_raw_span_inline_asm_srcloc(bx.tcx.sess, bx.bitcode_needed) {
// `srcloc` contains one 64-bit integer for each line of assembly code,
// where the lower 32 bits hold the lo byte position and the upper 32 bits
// hold the hi byte position.
let mut srcloc = vec![];
if dia == llvm::AsmDialect::Intel && line_spans.len() > 1 {
// LLVM inserts an extra line to add the ".intel_syntax", so add
// a dummy srcloc entry for it.
//
// Don't do this if we only have 1 line span since that may be
// due to the asm template string coming from a macro. LLVM will
// default to the first srcloc for lines that don't have an
// associated srcloc.
srcloc.push(llvm::LLVMValueAsMetadata(bx.const_u64(0)));
}
srcloc.extend(line_spans.iter().map(|span| {
llvm::LLVMValueAsMetadata(
bx.const_u64(u64::from(span.lo().to_u32()) | (u64::from(span.hi().to_u32()) << 32)),
)
}));
bx.cx.set_metadata_node(call, kind, &srcloc);
}
srcloc.extend(line_spans.iter().map(|span| {
llvm::LLVMValueAsMetadata(
bx.const_u64(u64::from(span.lo().to_u32()) | (u64::from(span.hi().to_u32()) << 32)),
)
}));
bx.cx.set_metadata_node(call, kind, &srcloc);

Some(call)
}

/// Whenever inline assembly bitcode is built, its `srcloc` contains the raw span numbers
/// as location cookies. This is problematic since that is nondeterministic when using
/// the parallel frontend. Even without parallelism, the cookies are meaningless in another
/// rustc session.
///
/// Discussion about replacing the cookies with something stable: rust-lang/rust#150451
fn allow_raw_span_inline_asm_srcloc(sess: &Session, bitcode_needed: bool) -> bool {
// even for Lto::ThinLocal, where the bitcode isn't serialized into files, the changes in
// raw span positions would reflect in the LTO module hashes, which could lead to
// nondeterminism
sess.lto() == Lto::No && !bitcode_needed
}

/// If the register is an xmm/ymm/zmm register then return its index.
fn xmm_reg_index(reg: InlineAsmReg) -> Option<u32> {
use X86InlineAsmReg::*;
Expand Down
11 changes: 8 additions & 3 deletions compiler/rustc_codegen_llvm/src/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,14 +64,15 @@ pub(crate) fn iter_global_aliases(llmod: &llvm::Module) -> ValueIter<'_> {
pub(crate) fn compile_codegen_unit(
tcx: TyCtxt<'_>,
cgu_name: Symbol,
bitcode_needed: bool,
) -> (ModuleCodegen<ModuleLlvm>, u64) {
let start_time = Instant::now();

let dep_node = tcx.codegen_unit(cgu_name).codegen_dep_node(tcx);
let (module, _) = tcx.dep_graph.with_task(
dep_node,
tcx,
|| module_codegen(tcx, cgu_name),
|| module_codegen(tcx, cgu_name, bitcode_needed),
Some(dep_graph::hash_result),
);
let time_to_codegen = start_time.elapsed();
Expand All @@ -80,7 +81,11 @@ pub(crate) fn compile_codegen_unit(
// the time we needed for codegenning it.
let cost = time_to_codegen.as_nanos() as u64;

fn module_codegen(tcx: TyCtxt<'_>, cgu_name: Symbol) -> ModuleCodegen<ModuleLlvm> {
fn module_codegen(
tcx: TyCtxt<'_>,
cgu_name: Symbol,
needs_bitcode: bool,
) -> ModuleCodegen<ModuleLlvm> {
let cgu = tcx.codegen_unit(cgu_name);
let _prof_timer =
tcx.prof.generic_activity_with_arg_recorder("codegen_module", |recorder| {
Expand All @@ -90,7 +95,7 @@ pub(crate) fn compile_codegen_unit(
// Instantiate monomorphizations without filling out definitions yet...
let llvm_module = ModuleLlvm::new(tcx, cgu_name.as_str());
{
let mut cx = CodegenCx::new(tcx, cgu, &llvm_module);
let mut cx = CodegenCx::new(tcx, cgu, &llvm_module, needs_bitcode);

// Declare and store globals shared by all offload kernels
//
Expand Down
3 changes: 3 additions & 0 deletions compiler/rustc_codegen_llvm/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ pub(crate) type CodegenCx<'ll, 'tcx> = GenericCx<'ll, FullCx<'ll, 'tcx>>;

pub(crate) struct FullCx<'ll, 'tcx> {
pub tcx: TyCtxt<'tcx>,
pub bitcode_needed: bool,
pub scx: SimpleCx<'ll>,
pub use_dll_storage_attrs: bool,
pub tls_model: llvm::ThreadLocalMode,
Expand Down Expand Up @@ -606,6 +607,7 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
tcx: TyCtxt<'tcx>,
codegen_unit: &'tcx CodegenUnit<'tcx>,
llvm_module: &'ll crate::ModuleLlvm,
bitcode_needed: bool,
) -> Self {
// An interesting part of Windows which MSVC forces our hand on (and
// apparently MinGW didn't) is the usage of `dllimport` and `dllexport`
Expand Down Expand Up @@ -683,6 +685,7 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
GenericCx(
FullCx {
tcx,
bitcode_needed,
scx: SimpleCx::new(llmod, llcx, tcx.data_layout.pointer_size()),
use_dll_storage_attrs,
tls_model,
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_codegen_llvm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,8 +112,9 @@ impl ExtraBackendMethods for LlvmCodegenBackend {
&self,
tcx: TyCtxt<'_>,
cgu_name: Symbol,
bitcode_needed: bool,
) -> (ModuleCodegen<ModuleLlvm>, u64) {
base::compile_codegen_unit(tcx, cgu_name)
base::compile_codegen_unit(tcx, cgu_name, bitcode_needed)
}
}

Expand Down
14 changes: 5 additions & 9 deletions compiler/rustc_codegen_ssa/src/back/write.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ use rustc_errors::{
Level, MultiSpan, Style, Suggestions, catch_fatal_errors,
};
use rustc_fs_util::link_or_copy;
use rustc_hir::find_attr;
use rustc_incremental::{copy_cgu_workproduct_to_incr_comp_cache_dir, in_incr_comp_dir_sess};
use rustc_macros::{Decodable, Encodable};
use rustc_metadata::fs::copy_to_stdout;
Expand Down Expand Up @@ -114,7 +113,7 @@ pub struct ModuleConfig {
}

impl ModuleConfig {
fn new(kind: ModuleKind, tcx: TyCtxt<'_>, no_builtins: bool) -> ModuleConfig {
pub(crate) fn new(kind: ModuleKind, tcx: TyCtxt<'_>, no_builtins: bool) -> ModuleConfig {
// If it's a regular module, use `$regular`, otherwise use `$other`.
// `$regular` and `$other` are evaluated lazily.
macro_rules! if_regular {
Expand Down Expand Up @@ -426,15 +425,12 @@ fn need_pre_lto_bitcode_for_incr_comp(sess: &Session) -> bool {
pub(crate) fn start_async_codegen<B: WriteBackendMethods>(
backend: B,
tcx: TyCtxt<'_>,
regular_config: Arc<ModuleConfig>,
allocator_config: Arc<ModuleConfig>,
allocator_module: Option<ModuleCodegen<B::Module>>,
) -> OngoingCodegen<B> {
let (coordinator_send, coordinator_receive) = channel();

let no_builtins = find_attr!(tcx, crate, NoBuiltins);

let regular_config = ModuleConfig::new(ModuleKind::Regular, tcx, no_builtins);
let allocator_config = ModuleConfig::new(ModuleKind::Allocator, tcx, no_builtins);

let (shared_emitter, shared_emitter_main) = SharedEmitter::new();
let (codegen_worker_send, codegen_worker_receive) = channel();

Expand All @@ -444,8 +440,8 @@ pub(crate) fn start_async_codegen<B: WriteBackendMethods>(
shared_emitter,
codegen_worker_send,
coordinator_receive,
Arc::new(regular_config),
Arc::new(allocator_config),
regular_config,
allocator_config,
allocator_module,
coordinator_send.clone(),
);
Expand Down
22 changes: 17 additions & 5 deletions compiler/rustc_codegen_ssa/src/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ use tracing::{debug, info};
use crate::assert_module_sources::CguReuse;
use crate::back::link::are_upstream_rust_objects_already_included;
use crate::back::write::{
ComputedLtoType, OngoingCodegen, compute_per_cgu_lto_type, start_async_codegen,
ComputedLtoType, ModuleConfig, OngoingCodegen, compute_per_cgu_lto_type, start_async_codegen,
submit_codegened_module_to_llvm, submit_post_lto_module_to_llvm, submit_pre_lto_module_to_llvm,
};
use crate::common::{self, IntPredicate, RealPredicate, TypeKind};
Expand All @@ -52,7 +52,7 @@ use crate::mir::place::PlaceRef;
use crate::traits::*;
use crate::{
CachedModuleCodegen, CodegenLintLevelSpecs, CrateInfo, EiiLinkageImplInfo, EiiLinkageInfo,
ModuleCodegen, diagnostics, meth, mir,
ModuleCodegen, ModuleKind, diagnostics, meth, mir,
};

pub(crate) fn bin_op_to_icmp_predicate(op: BinOp, signed: bool) -> IntPredicate {
Expand Down Expand Up @@ -762,7 +762,18 @@ pub fn codegen_crate<
None
};

let ongoing_codegen = start_async_codegen(backend.clone(), tcx, allocator_module);
let no_builtins = find_attr!(tcx, crate, NoBuiltins);
let regular_module_config = ModuleConfig::new(ModuleKind::Regular, tcx, no_builtins);
let bitcode_needed = regular_module_config.bitcode_needed();
let allocator_module_config = ModuleConfig::new(ModuleKind::Allocator, tcx, no_builtins);

let ongoing_codegen = start_async_codegen(
backend.clone(),
tcx,
Arc::new(regular_module_config),
Arc::new(allocator_module_config),
allocator_module,
);

// For better throughput during parallel processing by LLVM, we used to sort
// CGUs largest to smallest. This would lead to better thread utilization
Expand Down Expand Up @@ -822,7 +833,8 @@ pub fn codegen_crate<
let start_time = Instant::now();

let pre_compiled_cgus = par_map(cgus, |(i, _)| {
let module = backend.compile_codegen_unit(tcx, codegen_units[i].name());
let module =
backend.compile_codegen_unit(tcx, codegen_units[i].name(), bitcode_needed);
(i, IntoDynSyncSend(module))
});

Expand All @@ -846,7 +858,7 @@ pub fn codegen_crate<
cgu.0
} else {
let start_time = Instant::now();
let module = backend.compile_codegen_unit(tcx, cgu.name());
let module = backend.compile_codegen_unit(tcx, cgu.name(), bitcode_needed);
total_codegen_time += start_time.elapsed();
module
};
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_codegen_ssa/src/traits/backend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -177,5 +177,6 @@ pub trait ExtraBackendMethods: Send + Sync + DynSend + DynSync {
&self,
tcx: TyCtxt<'_>,
cgu_name: Symbol,
bitcode_needed: bool,
) -> (ModuleCodegen<Self::Module>, u64);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
use std::thread;

fn _main() {
let _t1 = thread::spawn(|| {
for _ in 0..100 {
println!("test");
}
});
}
42 changes: 42 additions & 0 deletions tests/run-make/parallel-reproducible-inline-asm-cookie/rmake.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
//@ needs-target-std
//@ ignore-cross-compile
//@ ignore-windows-gnu
// GNU Linker for Windows is non-deterministic. (from `reproducible-build-2` test in this suite)

use std::rc::Rc;

use run_make_support::{bin_name, is_windows_msvc, rfs, run_in_tmpdir, rustc};

/// Test that parallel compiler produces identical binaries.
fn main() {
const FILE_NAME: &str = "inline-asm-cookie-issue-150451";
let bin_name = bin_name(FILE_NAME);

let mut reference = None;

for _ in 0..10 {
// Tmp dir as previous runs affect output binary on windows.
run_in_tmpdir(|| {
let mut rustc = rustc();
rustc
.input(format!("{FILE_NAME}.rs"))
.arg("--crate-type=lib")
.arg("-Zthreads=3")
.arg("-Clink-dead-code=true")
.arg("-Copt-level=0")
.arg("-Cembed-bitcode=true")
.output(&bin_name);

if is_windows_msvc() {
rustc.arg("-Clink-arg=/Brepro");
}

rustc.run();

let current = Rc::new(rfs::read(&bin_name));
reference.get_or_insert(Rc::clone(&current));

assert_eq!(Some(current), reference);
});
}
}
2 changes: 1 addition & 1 deletion tests/ui/asm/aarch64/srcloc.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//@ add-minicore
//@ build-fail
//@ needs-asm-support
//@ compile-flags: --target aarch64-unknown-linux-gnu -Ccodegen-units=1
//@ compile-flags: --target aarch64-unknown-linux-gnu -Ccodegen-units=1 -Cembed-bitcode=false -Clto=no
//@ needs-llvm-components: aarch64
//@ ignore-backends: gcc
#![crate_type = "lib"]
Expand Down
11 changes: 1 addition & 10 deletions tests/ui/asm/inline-syntax.arm.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,6 @@ note: instantiated into assembly here
LL | .intel_syntax noprefix
| ^

error: unknown directive
|
note: instantiated into assembly here
--> <inline asm>:1:1
|
LL | .intel_syntax noprefix
| ^
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`

error: unknown directive
--> $DIR/inline-syntax.rs:21:15
|
Expand Down Expand Up @@ -87,5 +78,5 @@ note: instantiated into assembly here
LL | .intel_syntax noprefix
| ^

error: aborting due to 8 previous errors
error: aborting due to 7 previous errors

5 changes: 2 additions & 3 deletions tests/ui/asm/inline-syntax.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
//@ add-minicore
//@ revisions: x86_64 arm
//@[x86_64] compile-flags: --target x86_64-unknown-linux-gnu
//@[x86_64] compile-flags: --target x86_64-unknown-linux-gnu -Cembed-bitcode=false -Clto=no
//@[x86_64] check-pass
//@[x86_64] needs-llvm-components: x86
//@[arm] compile-flags: --target armv7-unknown-linux-gnueabihf
//@[arm] compile-flags: --target armv7-unknown-linux-gnueabihf -Cembed-bitcode=false -Clto=no
//@[arm] build-fail
//@[arm] needs-llvm-components: arm
//@[arm] min-llvm-version: 23
Expand Down Expand Up @@ -49,4 +49,3 @@ global_asm!(".intel_syntax noprefix", "nop");
// Global assembly errors don't have line numbers, so no error on ARM.

//[arm]~? ERROR unknown directive
//[arm]~? ERROR unknown directive

@petrochenkov petrochenkov Sep 4, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change (and its equivalent in tests/ui/asm/inline-syntax.arm.stderr) should be reverted, since the flags were added above?

View changes since the review

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Testing in #160197 (comment).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interesting, the tests pass.
Why did these diagnostics change?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't request a review because I am still trying to get to the bottom of this. I don't know why there were 2 of those in the first place. Both of them came from the global_asm! in the test.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Setting -Cembed-bitcode=false before my patches also removes the copy.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have moved the last commit (one changing the asm ui test flags) to be the first. This already requires changing the expected stderr to not have duplicate errors. The later change to loc cookie encoding has no effect on the output, the ui tests pass without more changes.

As for why it was duplicated when embedding bitcode, I have no idea.

2 changes: 1 addition & 1 deletion tests/ui/asm/riscv/riscv32e-registers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
//@ build-fail
//@ revisions: riscv32e_llvm23 riscv32em_llvm23 riscv32emc_llvm23
//@ revisions: riscv32e_llvm24 riscv32em_llvm24 riscv32emc_llvm24
//@ compile-flags: --crate-type=rlib
//@ compile-flags: --crate-type=rlib -Cembed-bitcode=false -Clto=no
//@ [riscv32e_llvm23] needs-llvm-components: riscv
//@ [riscv32e_llvm23] compile-flags: --target=riscv32e-unknown-none-elf
//@ [riscv32e_llvm23] max-llvm-major-version: 23
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/asm/x86_64/srcloc.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//@ add-minicore
//@ build-fail
//@ compile-flags: --target x86_64-unknown-linux-gnu -Ccodegen-units=1
//@ compile-flags: --target x86_64-unknown-linux-gnu -Ccodegen-units=1 -Cembed-bitcode=false -Clto=no
//@ needs-llvm-components: x86
//@ ignore-backends: gcc
#![crate_type = "lib"]
Expand Down
Loading