Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
9697363
Added codeview annotation intrinsic
gurry Jan 26, 2026
3bc1e58
Changed codeview annotation to take an array
gurry Mar 26, 2026
35b35a4
Changed intrinsic arg from array to array ref
gurry Mar 28, 2026
501ab33
Changed intrinsic arg from array ref to slice
gurry Mar 28, 2026
84d9cbf
Added tests to verify annotation survives optimizations
gurry Mar 30, 2026
14dcac3
Renamed codeview_annotation to debug_annotation
gurry Apr 8, 2026
9a0aa43
Now intercepting string arg while lowering to MIR
gurry Apr 8, 2026
8c801fe
Some cleanup
gurry Apr 8, 2026
aa7d187
Added a missing match entry
gurry Apr 9, 2026
287451c
Cleaned up and simplified
gurry Apr 9, 2026
671a637
Added more tests
gurry Apr 9, 2026
04d8f70
Renamed back to codeview_annotation
gurry Apr 9, 2026
2650d06
Replaced loop with while loop
gurry Apr 9, 2026
01c0530
Added support for const args
gurry Apr 9, 2026
06dcc88
Improved error messages
gurry Apr 9, 2026
ff5a335
Added support for consts
gurry Apr 9, 2026
5b1dd58
Lifetimes are no longer static
gurry Apr 9, 2026
32628fe
Simplified typeck code
gurry Apr 9, 2026
bdee988
Added some more tests
gurry Apr 9, 2026
98fec1a
Fixed formatting issues
gurry Apr 10, 2026
ae6b428
Using self.typing_env()
gurry Apr 10, 2026
31ac7a9
Passing symbols to backend for lowering instead of byte arrays
gurry Apr 10, 2026
55ab65a
Added check for string count
gurry Apr 10, 2026
edaf83a
Multiple cosmetic improvements
gurry Apr 10, 2026
ce11270
Minor comment improvements
gurry Apr 10, 2026
95e9663
Removed some comments
gurry Apr 10, 2026
94b1e7a
Fixed a few typos
gurry Apr 10, 2026
6655f74
Added more tests
gurry Apr 12, 2026
dd705e1
A few more fixes
gurry Apr 12, 2026
1c6f36e
Removed a stray underscore
gurry Apr 13, 2026
fbb804a
Improved error messages
gurry Apr 13, 2026
b77319f
Improvements in comments
gurry Apr 13, 2026
c4b77c2
Fixed a mistake in args in a test
gurry Apr 13, 2026
b4d7a41
Renamed some consts
gurry Apr 13, 2026
77c182e
Added a bug() for empty strings in codegen
gurry Apr 13, 2026
671f701
Rejecting consts with generic params
gurry Apr 25, 2026
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
3 changes: 2 additions & 1 deletion compiler/rustc_borrowck/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -828,7 +828,8 @@ impl<'a, 'tcx> ResultsVisitor<'tcx, Borrowck<'a, 'tcx>> for MirBorrowckCtxt<'a,
NonDivergingIntrinsic::CopyNonOverlapping(..) => span_bug!(
span,
"Unexpected CopyNonOverlapping, should only appear after lower_intrinsics",
)
),
NonDivergingIntrinsic::CodeviewAnnotation(_) => {},
}
// Only relevant for mir typeck
StatementKind::AscribeUserType(..)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ impl<'a, 'tcx> Visitor<'tcx> for LoanInvalidationsGenerator<'a, 'tcx> {
self.consume_operand(location, dst);
self.consume_operand(location, count);
}
// Doesn't have any language semantics
StatementKind::Intrinsic(box NonDivergingIntrinsic::CodeviewAnnotation(_)) => {}
// Only relevant for mir typeck
StatementKind::AscribeUserType(..)
// Only relevant for liveness and unsafeck
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_borrowck/src/type_check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -691,6 +691,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
}
}
StatementKind::Intrinsic(box NonDivergingIntrinsic::Assume(..))
| StatementKind::Intrinsic(box NonDivergingIntrinsic::CodeviewAnnotation(..))
| StatementKind::FakeRead(..)
| StatementKind::StorageLive(..)
| StatementKind::StorageDead(..)
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_codegen_cranelift/src/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -918,6 +918,8 @@ fn codegen_stmt<'tcx>(fx: &mut FunctionCx<'_, '_, 'tcx>, cur_block: Block, stmt:
StatementKind::Intrinsic(intrinsic) => match &**intrinsic {
// We ignore `assume` intrinsics, they are only useful for optimizations
NonDivergingIntrinsic::Assume(_) => {}
// codeview_annotation is supported only by the LLVM backend
NonDivergingIntrinsic::CodeviewAnnotation(_) => {}
NonDivergingIntrinsic::CopyNonOverlapping(mir::CopyNonOverlapping {
src,
dst,
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_codegen_cranelift/src/constant.rs
Original file line number Diff line number Diff line change
Expand Up @@ -606,6 +606,7 @@ pub(crate) fn mir_operand_get_const_val<'tcx>(
StatementKind::Intrinsic(intrinsic) => match **intrinsic {
NonDivergingIntrinsic::CopyNonOverlapping(..) => return None,
NonDivergingIntrinsic::Assume(..) => {}
NonDivergingIntrinsic::CodeviewAnnotation(..) => {}
},
// conservative handling
StatementKind::Assign(_)
Expand Down
5 changes: 5 additions & 0 deletions compiler/rustc_codegen_gcc/src/intrinsic/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -716,6 +716,11 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc
// FIXME(antoyo): implement.
self.context.new_rvalue_from_int(self.int_type, 0)
}

fn codeview_annotation(&mut self, _strings: &[Symbol]) {
// No-op as codeview_annotation is supported only by the LLVM backend.
// GCC has no intrinsic we can lower to
}
}

impl<'a, 'gcc, 'tcx> ArgAbiBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
Expand Down
22 changes: 21 additions & 1 deletion compiler/rustc_codegen_llvm/src/intrinsic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ use crate::declare::declare_raw_fn;
use crate::errors::{
AutoDiffWithoutEnable, AutoDiffWithoutLto, OffloadWithoutEnable, OffloadWithoutFatLTO,
};
use crate::llvm::{self, Type, Value};
use crate::llvm::{self, Metadata, Type, Value};
use crate::type_of::LayoutLlvmExt;
use crate::va_arg::emit_va_arg;

Expand Down Expand Up @@ -834,6 +834,26 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
fn va_end(&mut self, va_list: &'ll Value) -> &'ll Value {
self.call_intrinsic("llvm.va_end", &[self.val_ty(va_list)], &[va_list])
}

fn codeview_annotation(&mut self, strings: &[Symbol]) {
if !self.cx.sess().target.is_like_msvc {
return;
}

if strings.is_empty() {
bug!("codeview_annotation with empty strings should not reach codegen");
}

let md_strings: Vec<&Metadata> =
strings.iter().map(|s| self.cx.create_metadata(s.as_str().as_bytes())).collect();
let md_tuple = unsafe {
llvm::LLVMMDNodeInContext2(self.cx.llcx, md_strings.as_ptr(), md_strings.len())
};
let md_value = self.cx.get_metadata_value(md_tuple);
let (fn_ty, intrinsic_fn) = self.cx.get_intrinsic("llvm.codeview.annotation".into(), &[]);

self.call(fn_ty, None, None, intrinsic_fn, &[md_value], None, None);
}
}

fn catch_unwind_intrinsic<'ll, 'tcx>(
Expand Down
5 changes: 5 additions & 0 deletions compiler/rustc_codegen_ssa/src/mir/statement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {

bx.memcpy(dst, align, src, align, bytes, crate::MemFlags::empty(), None);
}
mir::StatementKind::Intrinsic(box NonDivergingIntrinsic::CodeviewAnnotation(
ref symbols,
)) => {
bx.codeview_annotation(symbols);
}
mir::StatementKind::FakeRead(..)
| mir::StatementKind::Retag { .. }
| mir::StatementKind::AscribeUserType(..)
Expand Down
5 changes: 4 additions & 1 deletion compiler/rustc_codegen_ssa/src/traits/intrinsic.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use rustc_middle::ty;
use rustc_span::Span;
use rustc_span::{Span, Symbol};

use super::BackendTypes;
use crate::mir::operand::OperandRef;
Expand Down Expand Up @@ -49,4 +49,7 @@ pub trait IntrinsicCallBuilderMethods<'tcx>: BackendTypes {
/// Trait method used to inject `va_end` on the "spoofed" `VaList` before
/// Rust defined C-variadic functions return.
fn va_end(&mut self, val: Self::Value) -> Self::Value;

/// Emit a codeview_annotation with the given strings.
fn codeview_annotation(&mut self, strings: &[Symbol]);
}
1 change: 1 addition & 0 deletions compiler/rustc_const_eval/src/interpret/intrinsics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -776,6 +776,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
let count = self.eval_operand(count, None)?;
self.copy_intrinsic(&src, &dst, &count, /* nonoverlapping */ true)
}
NonDivergingIntrinsic::CodeviewAnnotation(_) => interp_ok(()),
}
}

Expand Down
26 changes: 26 additions & 0 deletions compiler/rustc_hir_analysis/src/check/intrinsic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) -> hi
| sym::ceilf32
| sym::ceilf64
| sym::ceilf128
| sym::codeview_annotation
| sym::cold_path
| sym::const_eval_select
| sym::contract_check_ensures
Expand Down Expand Up @@ -293,6 +294,31 @@ pub(crate) fn check_intrinsic_type(
sym::amdgpu_dispatch_ptr => (0, 0, vec![], Ty::new_imm_ptr(tcx, tcx.types.unit)),
sym::unreachable => (0, 0, vec![], tcx.types.never),
sym::breakpoint => (0, 0, vec![], tcx.types.unit),
sym::codeview_annotation => {
let str_ref = Ty::new_imm_ref(
tcx,
ty::Region::new_bound(
tcx,
ty::INNERMOST,
ty::BoundRegion {
var: ty::BoundVar::from_u32(1),
kind: ty::BoundRegionKind::Anon,
},
),
tcx.types.str_,
);
let slice_ty = Ty::new_slice(tcx, str_ref);
let ref_to_slice = Ty::new_imm_ref(
tcx,
ty::Region::new_bound(
tcx,
ty::INNERMOST,
ty::BoundRegion { var: ty::BoundVar::ZERO, kind: ty::BoundRegionKind::Anon },
),
slice_ty,
);
(0, 0, vec![ref_to_slice], tcx.types.unit)
}
sym::size_of | sym::align_of | sym::variant_count => (1, 0, vec![], tcx.types.usize),
sym::size_of_val | sym::align_of_val => {
(1, 0, vec![Ty::new_imm_ptr(tcx, param(0))], tcx.types.usize)
Expand Down
10 changes: 10 additions & 0 deletions compiler/rustc_middle/src/mir/pretty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -870,6 +870,16 @@ impl Display for NonDivergingIntrinsic<'_> {
Self::CopyNonOverlapping(CopyNonOverlapping { src, dst, count }) => {
write!(f, "copy_nonoverlapping(dst = {dst:?}, src = {src:?}, count = {count:?})")
}
Self::CodeviewAnnotation(symbols) => {
write!(f, "codeview_annotation(")?;
for (i, sym) in symbols.iter().enumerate() {
if i > 0 {
write!(f, ", ")?;
}
write!(f, "{sym:?}")?;
}
write!(f, ")")
}
}
}
}
Expand Down
10 changes: 10 additions & 0 deletions compiler/rustc_middle/src/mir/syntax.rs
Original file line number Diff line number Diff line change
Expand Up @@ -504,6 +504,16 @@ pub enum NonDivergingIntrinsic<'tcx> {
/// **Needs clarification**: Is this typed or not, ie is there a typed load and store involved?
/// I vaguely remember Ralf saying somewhere that he thought it should not be.
CopyNonOverlapping(CopyNonOverlapping<'tcx>),

/// Denotes a call to the intrinsic function `codeview_annotation`.
///
/// Gets lowered to `llvm.codeview.annotation` on LLVM for MSVC targets.
/// Is a no-op on other targets and backends.
CodeviewAnnotation(
#[type_foldable(identity)]
#[type_visitable(ignore)]
Box<[rustc_span::Symbol]>,
),
}

/// Describes what kind of retag is to be performed.
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_middle/src/mir/visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -495,6 +495,7 @@ macro_rules! make_mir_visitor {
self.visit_operand(dst, location);
self.visit_operand(count, location);
}
NonDivergingIntrinsic::CodeviewAnnotation(_) => {}
}
}
StatementKind::BackwardIncompatibleDropHint { place, .. } => {
Expand Down
Loading
Loading