Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
80c0b99
add `simd_splat` intrinsic
folkertdev Jan 18, 2026
120388c
`simd_splat`: custom error in gcc backend for invalid element type
folkertdev Jan 19, 2026
34481f8
const-eval: do not call `immediate_const_vector` on vector of pointers
folkertdev Jan 19, 2026
03fa11a
Remove a couple of unnecessary impls
bjorn3 Oct 3, 2025
8c1e51f
hexagon: Add HVX target features
androm3da Jan 22, 2026
c65076a
Handle FreeFunctions outside with_api_handle_types
bjorn3 Oct 3, 2025
5dd7c0b
Rationalise the Armv7-A, Armv7-R and Armv8-R bare-metal target configs
thejpster Dec 31, 2025
96647dd
Add Thumb-mode targets for Armv7-R, Armv7-A and Armv8-R.
thejpster Dec 31, 2025
fb05cac
Update SUMMARY.md too
thejpster Jan 1, 2026
1652f3f
Expand with_api_handle_types
bjorn3 Oct 3, 2025
d3b5f72
Move all bridge methods into a single type
bjorn3 Jan 22, 2026
31c696d
Various simplifications after moving all bridge methods to a single type
bjorn3 Jan 22, 2026
5c2052a
Merge FreeFunctions trait into Server trait
bjorn3 Jan 22, 2026
44fcd04
Get rid of MarkedTypes
bjorn3 Oct 3, 2025
76f9a90
Use rustc_proc_macro in rust-analyzer-proc-macro-srv
bjorn3 Jan 22, 2026
0a2bb4b
Ensure armv7a-none-eabi.md mentions all four targets
thejpster Jan 22, 2026
19d1be5
Ensure armv7r-none-eabi.md mentions all four targets
thejpster Jan 22, 2026
fa526c4
Update armv8r-none-eabi.md - note both targets are hardfloat
thejpster Jan 22, 2026
ff9c5cf
Enable reproducible binary builds with debuginfo on Linux
paradoxicalguy Jan 22, 2026
081c4c6
reenable tests
bend-n Jan 22, 2026
1e8ffd9
Removed comment on reproducibility issue #89911
paradoxicalguy Jan 23, 2026
207dcbb
constify boolean methods
bend-n Jan 22, 2026
78afe87
Add 'Skip to main content' link for keyboard navigation in rustdoc
ThanhNguyxn Jan 23, 2026
e47138f
Fix review comments
bjorn3 Jan 23, 2026
e38b55d
Don't use default build-script fingerprinting in `test`
ehuss Jan 23, 2026
9ce4943
Rollup merge of #150556 - thejpster:add-thumbv7a-thumbv7r-thumbv8r, r…
jhpratt Jan 24, 2026
3f3fc65
Rollup merge of #151346 - folkertdev:simd-splat, r=workingjubilee
jhpratt Jan 24, 2026
5087bdd
Rollup merge of #151500 - androm3da:bcain/hexagon_hvx_feat, r=folkertdev
jhpratt Jan 24, 2026
6901397
Rollup merge of #151505 - bjorn3:proc_macro_refactors, r=petrochenkov
jhpratt Jan 24, 2026
03ef5dc
Rollup merge of #151517 - paradoxicalguy:enable-debuginfo-tests-linux…
jhpratt Jan 24, 2026
e8031a5
Rollup merge of #151482 - ThanhNguyxn:fix/rustdoc-skip-nav, r=Guillau…
jhpratt Jan 24, 2026
f20485c
Rollup merge of #151489 - bend-n:constify-all-boolean-methods-under-f…
jhpratt Jan 24, 2026
a32b322
Rollup merge of #151551 - ehuss:test-build-script, r=jhpratt
jhpratt Jan 24, 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
25 changes: 25 additions & 0 deletions compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,31 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
ret.write_cvalue(fx, ret_lane);
}

sym::simd_splat => {
intrinsic_args!(fx, args => (value); intrinsic);

if !ret.layout().ty.is_simd() {
report_simd_type_validation_error(fx, intrinsic, span, ret.layout().ty);
return;
}
let (lane_count, lane_ty) = ret.layout().ty.simd_size_and_type(fx.tcx);

if value.layout().ty != lane_ty {
fx.tcx.dcx().span_fatal(
span,
format!(
"[simd_splat] expected element type {lane_ty:?}, got {got:?}",
got = value.layout().ty
),
);
}

for i in 0..lane_count {
let ret_lane = ret.place_lane(fx, i.into());
ret_lane.write_cvalue(fx, value);
}
}

sym::simd_neg
| sym::simd_bswap
| sym::simd_bitreverse
Expand Down
36 changes: 36 additions & 0 deletions compiler/rustc_codegen_gcc/src/intrinsic/simd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,42 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
return Ok(bx.vector_select(vector_mask, arg1, args[2].immediate()));
}

#[cfg(feature = "master")]
if name == sym::simd_splat {
let (out_len, out_ty) = require_simd2!(ret_ty, SimdReturn);

require!(
args[0].layout.ty == out_ty,
InvalidMonomorphization::ExpectedVectorElementType {
span,
name,
expected_element: out_ty,
vector_type: ret_ty,
}
);

let vec_ty = llret_ty.unqualified().dyncast_vector().expect("vector return type");
let elem_ty = vec_ty.get_element_type();

// Cast pointer type to usize (GCC does not support pointer SIMD vectors).
let value = args[0];
let scalar = if value.layout.ty.is_numeric() {
value.immediate()
} else if value.layout.ty.is_raw_ptr() {
bx.ptrtoint(value.immediate(), elem_ty)
} else {
return_error!(InvalidMonomorphization::UnsupportedOperation {
span,
name,
in_ty: ret_ty,
in_elem: value.layout.ty
});
};

let elements = vec![scalar; out_len as usize];
return Ok(bx.context.new_rvalue_from_vector(bx.location, llret_ty, &elements));
}

// every intrinsic below takes a SIMD vector as its first argument
require_simd!(
args[0].layout.ty,
Expand Down
25 changes: 25 additions & 0 deletions compiler/rustc_codegen_llvm/src/intrinsic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1581,6 +1581,31 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
return Ok(bx.select(m_i1s, args[1].immediate(), args[2].immediate()));
}

if name == sym::simd_splat {
let (_out_len, out_ty) = require_simd!(ret_ty, SimdReturn);

require!(
args[0].layout.ty == out_ty,
InvalidMonomorphization::ExpectedVectorElementType {
span,
name,
expected_element: out_ty,
vector_type: ret_ty,
}
);

// `insertelement <N x elem> poison, elem %x, i32 0`
let poison_vec = bx.const_poison(llret_ty);
let idx0 = bx.const_i32(0);
let v0 = bx.insert_element(poison_vec, args[0].immediate(), idx0);

// `shufflevector <N x elem> v0, <N x elem> poison, <N x i32> zeroinitializer`
// The masks is all zeros, so this splats lane 0 (which has our element in it).
let splat = bx.shuffle_vector(v0, poison_vec, bx.const_null(llret_ty));

return Ok(splat);
}

// every intrinsic below takes a SIMD vector as its first argument
let (in_len, in_elem) = require_simd!(args[0].layout.ty, SimdInput);
let in_ty = args[0].layout.ty;
Expand Down
8 changes: 7 additions & 1 deletion compiler/rustc_codegen_ssa/src/mir/operand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1074,8 +1074,14 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
if constant_ty.is_simd() {
// However, some SIMD types do not actually use the vector ABI
// (in particular, packed SIMD types do not). Ensure we exclude those.
//
// We also have to exclude vectors of pointers because `immediate_const_vector`
// does not work for those.
let layout = bx.layout_of(constant_ty);
if let BackendRepr::SimdVector { .. } = layout.backend_repr {
let (_, element_ty) = constant_ty.simd_size_and_type(bx.tcx());
if let BackendRepr::SimdVector { .. } = layout.backend_repr
&& element_ty.is_numeric()
{
let (llval, ty) = self.immediate_const_vector(bx, constant);
return OperandRef {
val: OperandValue::Immediate(llval),
Expand Down
9 changes: 9 additions & 0 deletions compiler/rustc_const_eval/src/interpret/intrinsics/simd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,15 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
}
self.copy_op(&self.project_index(&input, index)?, &dest)?;
}
sym::simd_splat => {
let elem = &args[0];
let (dest, dest_len) = self.project_to_simd(&dest)?;

for i in 0..dest_len {
let place = self.project_index(&dest, i)?;
self.copy_op(elem, &place)?;
}
}
sym::simd_neg
| sym::simd_fabs
| sym::simd_ceil
Expand Down
103 changes: 50 additions & 53 deletions compiler/rustc_expand/src/proc_macro_server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -431,8 +431,6 @@ impl ToInternal<rustc_errors::Level> for Level {
}
}

pub(crate) struct FreeFunctions;

pub(crate) struct Rustc<'a, 'b> {
ecx: &'a mut ExtCtxt<'b>,
def_site: Span,
Expand Down Expand Up @@ -461,13 +459,28 @@ impl<'a, 'b> Rustc<'a, 'b> {
}

impl server::Types for Rustc<'_, '_> {
type FreeFunctions = FreeFunctions;
type TokenStream = TokenStream;
type Span = Span;
type Symbol = Symbol;
}

impl server::FreeFunctions for Rustc<'_, '_> {
impl server::Server for Rustc<'_, '_> {
fn globals(&mut self) -> ExpnGlobals<Self::Span> {
ExpnGlobals {
def_site: self.def_site,
call_site: self.call_site,
mixed_site: self.mixed_site,
}
}

fn intern_symbol(string: &str) -> Self::Symbol {
Symbol::intern(string)
}

fn with_symbol_string(symbol: &Self::Symbol, f: impl FnOnce(&str)) {
f(symbol.as_str())
}

fn injected_env_var(&mut self, var: &str) -> Option<String> {
self.ecx.sess.opts.logical_env.get(var).cloned()
}
Expand Down Expand Up @@ -552,14 +565,20 @@ impl server::FreeFunctions for Rustc<'_, '_> {
}
diag.emit();
}
}

impl server::TokenStream for Rustc<'_, '_> {
fn is_empty(&mut self, stream: &Self::TokenStream) -> bool {
fn ts_drop(&mut self, stream: Self::TokenStream) {
drop(stream);
}

fn ts_clone(&mut self, stream: &Self::TokenStream) -> Self::TokenStream {
stream.clone()
}

fn ts_is_empty(&mut self, stream: &Self::TokenStream) -> bool {
stream.is_empty()
}

fn from_str(&mut self, src: &str) -> Self::TokenStream {
fn ts_from_str(&mut self, src: &str) -> Self::TokenStream {
unwrap_or_emit_fatal(source_str_to_stream(
self.psess(),
FileName::proc_macro_source_code(src),
Expand All @@ -568,11 +587,11 @@ impl server::TokenStream for Rustc<'_, '_> {
))
}

fn to_string(&mut self, stream: &Self::TokenStream) -> String {
fn ts_to_string(&mut self, stream: &Self::TokenStream) -> String {
pprust::tts_to_string(stream)
}

fn expand_expr(&mut self, stream: &Self::TokenStream) -> Result<Self::TokenStream, ()> {
fn ts_expand_expr(&mut self, stream: &Self::TokenStream) -> Result<Self::TokenStream, ()> {
// Parse the expression from our tokenstream.
let expr: PResult<'_, _> = try {
let mut p = Parser::new(self.psess(), stream.clone(), Some("proc_macro expand expr"));
Expand Down Expand Up @@ -633,14 +652,14 @@ impl server::TokenStream for Rustc<'_, '_> {
}
}

fn from_token_tree(
fn ts_from_token_tree(
&mut self,
tree: TokenTree<Self::TokenStream, Self::Span, Self::Symbol>,
) -> Self::TokenStream {
Self::TokenStream::new((tree, &mut *self).to_internal().into_iter().collect::<Vec<_>>())
}

fn concat_trees(
fn ts_concat_trees(
&mut self,
base: Option<Self::TokenStream>,
trees: Vec<TokenTree<Self::TokenStream, Self::Span, Self::Symbol>>,
Expand All @@ -654,7 +673,7 @@ impl server::TokenStream for Rustc<'_, '_> {
stream
}

fn concat_streams(
fn ts_concat_streams(
&mut self,
base: Option<Self::TokenStream>,
streams: Vec<Self::TokenStream>,
Expand All @@ -666,24 +685,22 @@ impl server::TokenStream for Rustc<'_, '_> {
stream
}

fn into_trees(
fn ts_into_trees(
&mut self,
stream: Self::TokenStream,
) -> Vec<TokenTree<Self::TokenStream, Self::Span, Self::Symbol>> {
FromInternal::from_internal((stream, self))
}
}

impl server::Span for Rustc<'_, '_> {
fn debug(&mut self, span: Self::Span) -> String {
fn span_debug(&mut self, span: Self::Span) -> String {
if self.ecx.ecfg.span_debug {
format!("{span:?}")
} else {
format!("{:?} bytes({}..{})", span.ctxt(), span.lo().0, span.hi().0)
}
}

fn file(&mut self, span: Self::Span) -> String {
fn span_file(&mut self, span: Self::Span) -> String {
self.psess()
.source_map()
.lookup_char_pos(span.lo())
Expand All @@ -693,7 +710,7 @@ impl server::Span for Rustc<'_, '_> {
.to_string()
}

fn local_file(&mut self, span: Self::Span) -> Option<String> {
fn span_local_file(&mut self, span: Self::Span) -> Option<String> {
self.psess()
.source_map()
.lookup_char_pos(span.lo())
Expand All @@ -708,41 +725,41 @@ impl server::Span for Rustc<'_, '_> {
})
}

fn parent(&mut self, span: Self::Span) -> Option<Self::Span> {
fn span_parent(&mut self, span: Self::Span) -> Option<Self::Span> {
span.parent_callsite()
}

fn source(&mut self, span: Self::Span) -> Self::Span {
fn span_source(&mut self, span: Self::Span) -> Self::Span {
span.source_callsite()
}

fn byte_range(&mut self, span: Self::Span) -> Range<usize> {
fn span_byte_range(&mut self, span: Self::Span) -> Range<usize> {
let source_map = self.psess().source_map();

let relative_start_pos = source_map.lookup_byte_offset(span.lo()).pos;
let relative_end_pos = source_map.lookup_byte_offset(span.hi()).pos;

Range { start: relative_start_pos.0 as usize, end: relative_end_pos.0 as usize }
}
fn start(&mut self, span: Self::Span) -> Self::Span {
fn span_start(&mut self, span: Self::Span) -> Self::Span {
span.shrink_to_lo()
}

fn end(&mut self, span: Self::Span) -> Self::Span {
fn span_end(&mut self, span: Self::Span) -> Self::Span {
span.shrink_to_hi()
}

fn line(&mut self, span: Self::Span) -> usize {
fn span_line(&mut self, span: Self::Span) -> usize {
let loc = self.psess().source_map().lookup_char_pos(span.lo());
loc.line
}

fn column(&mut self, span: Self::Span) -> usize {
fn span_column(&mut self, span: Self::Span) -> usize {
let loc = self.psess().source_map().lookup_char_pos(span.lo());
loc.col.to_usize() + 1
}

fn join(&mut self, first: Self::Span, second: Self::Span) -> Option<Self::Span> {
fn span_join(&mut self, first: Self::Span, second: Self::Span) -> Option<Self::Span> {
let self_loc = self.psess().source_map().lookup_char_pos(first.lo());
let other_loc = self.psess().source_map().lookup_char_pos(second.lo());

Expand All @@ -753,7 +770,7 @@ impl server::Span for Rustc<'_, '_> {
Some(first.to(second))
}

fn subspan(
fn span_subspan(
&mut self,
span: Self::Span,
start: Bound<usize>,
Expand Down Expand Up @@ -789,11 +806,11 @@ impl server::Span for Rustc<'_, '_> {
Some(span.with_lo(new_lo).with_hi(new_hi))
}

fn resolved_at(&mut self, span: Self::Span, at: Self::Span) -> Self::Span {
fn span_resolved_at(&mut self, span: Self::Span, at: Self::Span) -> Self::Span {
span.with_ctxt(at.ctxt())
}

fn source_text(&mut self, span: Self::Span) -> Option<String> {
fn span_source_text(&mut self, span: Self::Span) -> Option<String> {
self.psess().source_map().span_to_snippet(span).ok()
}

Expand Down Expand Up @@ -821,41 +838,21 @@ impl server::Span for Rustc<'_, '_> {
/// span from the metadata of `my_proc_macro` (which we have access to,
/// since we've loaded `my_proc_macro` from disk in order to execute it).
/// In this way, we have obtained a span pointing into `my_proc_macro`
fn save_span(&mut self, span: Self::Span) -> usize {
fn span_save_span(&mut self, span: Self::Span) -> usize {
self.psess().save_proc_macro_span(span)
}

fn recover_proc_macro_span(&mut self, id: usize) -> Self::Span {
fn span_recover_proc_macro_span(&mut self, id: usize) -> Self::Span {
let (resolver, krate, def_site) = (&*self.ecx.resolver, self.krate, self.def_site);
*self.rebased_spans.entry(id).or_insert_with(|| {
// FIXME: `SyntaxContext` for spans from proc macro crates is lost during encoding,
// replace it with a def-site context until we are encoding it properly.
resolver.get_proc_macro_quoted_span(krate, id).with_ctxt(def_site.ctxt())
})
}
}

impl server::Symbol for Rustc<'_, '_> {
fn normalize_and_validate_ident(&mut self, string: &str) -> Result<Self::Symbol, ()> {
fn symbol_normalize_and_validate_ident(&mut self, string: &str) -> Result<Self::Symbol, ()> {
let sym = nfc_normalize(string);
if rustc_lexer::is_ident(sym.as_str()) { Ok(sym) } else { Err(()) }
}
}

impl server::Server for Rustc<'_, '_> {
fn globals(&mut self) -> ExpnGlobals<Self::Span> {
ExpnGlobals {
def_site: self.def_site,
call_site: self.call_site,
mixed_site: self.mixed_site,
}
}

fn intern_symbol(string: &str) -> Self::Symbol {
Symbol::intern(string)
}

fn with_symbol_string(symbol: &Self::Symbol, f: impl FnOnce(&str)) {
f(symbol.as_str())
}
}
Loading
Loading