Skip to content
Closed
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
66 changes: 40 additions & 26 deletions compiler/rustc_ast/src/tokenstream.rs
Original file line number Diff line number Diff line change
Expand Up @@ -249,14 +249,14 @@ impl LazyAttrTokenStreamInner {
break_last_token,
node_replacements,
} => {
// The token produced by the final call to `{,inlined_}next` was not
// The token produced by the final call to `{,inlined_}next_and_bump` was not
// actually consumed by the callback. The combination of chaining the
// initial token and using `take` produces the desired result - we
// produce an empty `TokenStream` if no calls were made, and omit the
// final token otherwise.
let mut cursor_snapshot = cursor_snapshot.clone();
let tokens = iter::once(FlatToken::Token(*start_token))
.chain(iter::repeat_with(|| FlatToken::Token(cursor_snapshot.next())))
.chain(iter::repeat_with(|| FlatToken::Token(cursor_snapshot.next_and_bump())))
.take(*num_calls as usize);

if node_replacements.is_empty() {
Expand Down Expand Up @@ -883,36 +883,48 @@ impl<'t> Iterator for TokenStreamIter<'t> {
#[derive(Clone, Debug)]
struct TokenTreeCursor {
stream: TokenStream,
/// Points to the current token tree in the stream. In `TokenCursor::curr`,
/// this can be any token tree. In `TokenCursor::stack`, this is always a
/// `TokenTree::Delimited`.
index: usize,
/// Points to the next token tree (or one past the end of the stream).
next_idx: usize,
}

impl TokenTreeCursor {
#[inline]
fn new(stream: TokenStream) -> Self {
TokenTreeCursor { stream, index: 0 }
TokenTreeCursor { stream, next_idx: 0 }
}

/// Gets the current token tree within this cursor. In a debug build it panics on a cursor that
/// hasn't been bumped; in a release build it will return `None`.
#[inline]
fn curr(&self) -> Option<&TokenTree> {
self.stream.get(self.index)
debug_assert!(self.next_idx > 0);
self.stream.get(self.next_idx - 1)
}

/// Gets the next token tree without advancing.
#[inline]
fn next(&self) -> Option<&TokenTree> {
self.stream.get(self.next_idx)
}

/// Gets the token tree `n` ahead. `look_ahead(1)` is equivalent to `next()`. `look_ahead(0)`
/// isn't allowed and will panic.
#[inline]
fn look_ahead(&self, n: usize) -> Option<&TokenTree> {
self.stream.get(self.index + n)
assert_ne!(n, 0);
self.stream.get(self.next_idx + (n - 1))
}

/// Move the cursor to the next token tree.
#[inline]
fn bump(&mut self) {
self.index += 1;
self.next_idx += 1;
}

// For skipping ahead in rare circumstances.
/// For skipping ahead in rare circumstances.
#[inline]
fn bump_to_end(&mut self) {
self.index = self.stream.len();
self.next_idx = self.stream.len();
}
}

Expand All @@ -922,15 +934,16 @@ impl TokenTreeCursor {
/// what the parser expects, for the most part.
#[derive(Clone, Debug)]
pub struct TokenCursor {
// Cursor for the current (innermost) token stream. The index within the
// Cursor for the current (innermost) token stream. The `next_idx` within the
// cursor can point to any token tree in the stream (or one past the end).
// The delimiters for this token stream are found in `self.stack.last()`;
// if that is `None` we are in the outermost token stream which never has
// delimiters.
// The delimiters for this token stream are found in the current token tree
// in `self.stack.last()`; if that is `None` we are in the outermost token
// stream which never has delimiters.
curr: TokenTreeCursor,

// Token streams surrounding the current one. The index within each cursor
// always points to a `TokenTree::Delimited`.
// Token streams surrounding the current one. The `next_idx` within each cursor
// is always greater than zero and always points one past the current
// `TokenTree::Delimited`.
stack: Vec<TokenTreeCursor>,
}

Expand All @@ -940,12 +953,13 @@ impl TokenCursor {
TokenCursor { curr: TokenTreeCursor::new(stream), stack: vec![] }
}

pub fn next(&mut self) -> (Token, Spacing) {
self.inlined_next()
/// Gets the next token and advances the cursor by one.
pub fn next_and_bump(&mut self) -> (Token, Spacing) {
self.inlined_next_and_bump()
}

/// An `n` of zero is the next token tree in the current token stream; won't look outside the
/// current token stream.
/// An `n` of 1 is the next token tree in the current token stream; won't look outside the
/// current token stream. `look_ahead(0)` isn't allowed and will panic.
#[inline]
pub fn look_ahead(&self, n: usize) -> Option<&TokenTree> {
self.curr.look_ahead(n)
Expand All @@ -955,7 +969,7 @@ impl TokenCursor {
/// delimited sequence. Panics if we are not within a delimited sequence.
#[inline]
pub fn look_ahead_past_close_delim(&self) -> Option<&TokenTree> {
self.stack.last().unwrap().look_ahead(1)
self.stack.last().unwrap().next()
}

/// Clones the `TokenTree::Delimited` that we are currently within. Panics if we are not within
Expand Down Expand Up @@ -991,12 +1005,12 @@ impl TokenCursor {

/// This always-inlined version should only be used on hot code paths.
#[inline(always)]
pub fn inlined_next(&mut self) -> (Token, Spacing) {
pub fn inlined_next_and_bump(&mut self) -> (Token, Spacing) {
loop {
// FIXME: we currently don't return `Delimiter::Invisible` open/close delims. To fix
// #67062 we will need to, whereupon the `delim != Delimiter::Invisible` conditions
// below can be removed.
if let Some(tree) = self.curr.curr() {
if let Some(tree) = self.curr.next() {
match tree {
&TokenTree::Token(token, spacing) => {
debug_assert!(!token.kind.is_delim());
Expand All @@ -1006,6 +1020,7 @@ impl TokenCursor {
}
&TokenTree::Delimited(sp, spacing, delim, ref tts) => {
let trees = TokenTreeCursor::new(tts.clone());
self.curr.bump(); // move past the `Delimited`
self.stack.push(mem::replace(&mut self.curr, trees));
if !delim.skip() {
return (Token::new(delim.as_open_token_kind(), sp.open), spacing.open);
Expand All @@ -1019,7 +1034,6 @@ impl TokenCursor {
panic!("parent should be Delimited")
};
self.curr = parent;
self.curr.bump(); // move past the `Delimited`
if !delim.skip() {
return (Token::new(delim.as_close_token_kind(), span.close), spacing.close);
}
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_codegen_cranelift/src/abi/pass_mode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,8 +122,8 @@ impl<'tcx> ArgAbiExt<'tcx> for ArgAbi<'tcx, Ty<'tcx>> {
}
_ => unreachable!("{:?}", self.layout.backend_repr),
},
PassMode::Cast { ref cast, pad_i32 } => {
assert!(!pad_i32, "padding support not yet implemented");
PassMode::Cast { ref cast, pad_i32_count } => {
assert_eq!(pad_i32_count, 0, "padding support not yet implemented");
cast_target_to_abi_params(cast).into_iter().map(|(_, param)| param).collect()
}
PassMode::Indirect { attrs, meta_attrs: None, on_stack } => {
Expand Down
12 changes: 7 additions & 5 deletions compiler/rustc_codegen_gcc/src/abi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -168,11 +168,13 @@ impl<'gcc, 'tcx> FnAbiGccExt<'gcc, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
));
continue;
}
PassMode::Cast { ref cast, pad_i32 } => {
// add padding
if pad_i32 {
argument_tys.push(Reg::i32().gcc_type(cx));
}
PassMode::Cast { ref cast, pad_i32_count } => {
// Add padding.
argument_tys.extend(std::iter::repeat_n(
Reg::i32().gcc_type(cx),
usize::from(pad_i32_count),
));

let ty = cast.gcc_type(cx);
apply_attrs(ty, &cast.attrs, argument_tys.len())
}
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_codegen_gcc/src/type_of.rs
Original file line number Diff line number Diff line change
Expand Up @@ -346,8 +346,8 @@ impl<'gcc, 'tcx> LayoutTypeCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
fn_abi.ptr_to_gcc_type(self)
}

fn reg_backend_type(&self, _ty: &Reg) -> Type<'gcc> {
unimplemented!();
fn reg_backend_type(&self, ty: &Reg) -> Type<'gcc> {
ty.gcc_type(self)
}

fn fn_decl_backend_type(&self, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> Type<'gcc> {
Expand Down
28 changes: 15 additions & 13 deletions compiler/rustc_codegen_llvm/src/abi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@ impl<'ll, 'tcx> ArgAbiExt<'ll, 'tcx> for ArgAbi<'tcx, Ty<'tcx>> {
PassMode::Indirect { attrs: _, meta_attrs: Some(_), on_stack: _ } => {
bug!("unsized `ArgAbi` cannot be stored");
}
PassMode::Cast { cast, pad_i32: _ } => {
PassMode::Cast { cast, pad_i32_count: _ } => {
// The ABI mandates that the value is passed as a different struct representation.
// Spill and reload it from the stack to convert from the ABI representation to
// the Rust representation.
Expand Down Expand Up @@ -366,7 +366,7 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
let llreturn_ty = match &self.ret.mode {
PassMode::Ignore => cx.type_void(),
PassMode::Direct(_) | PassMode::Pair(..) => self.ret.layout.immediate_llvm_type(cx),
PassMode::Cast { cast, pad_i32: _ } => cast.llvm_type(cx),
PassMode::Cast { cast, pad_i32_count: _ } => cast.llvm_type(cx),
PassMode::Indirect { .. } => {
llargument_tys.push(cx.type_ptr());
cx.type_void()
Expand Down Expand Up @@ -405,11 +405,13 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
continue;
}
PassMode::Indirect { attrs: _, meta_attrs: None, on_stack: _ } => cx.type_ptr(),
PassMode::Cast { cast, pad_i32 } => {
// add padding
if *pad_i32 {
llargument_tys.push(Reg::i32().llvm_type(cx));
}
PassMode::Cast { cast, pad_i32_count } => {
// Add padding.
llargument_tys.extend(std::iter::repeat_n(
Reg::i32().llvm_type(cx),
usize::from(*pad_i32_count),
));

// Compute the LLVM type we use for this function from the cast type.
// We assume here that ABI-compatible Rust types have the same cast type.
cast.llvm_type(cx)
Expand Down Expand Up @@ -511,7 +513,7 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
);
}
}
PassMode::Cast { cast, pad_i32: _ } => {
PassMode::Cast { cast, pad_i32_count: _ } => {
cast.attrs.apply_attrs_to_llfn(llvm::AttributePlace::ReturnValue, cx, llfn);
}
_ => {}
Expand Down Expand Up @@ -580,8 +582,8 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
apply_range_attr(llvm::AttributePlace::Argument(ii), scalar_b);
}
}
PassMode::Cast { cast, pad_i32 } => {
if *pad_i32 {
PassMode::Cast { cast, pad_i32_count } => {
for _ in 0..*pad_i32_count {
apply(&ArgAttributes::new());
}
apply(&cast.attrs);
Expand Down Expand Up @@ -630,7 +632,7 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
);
attributes::apply_to_callsite(callsite, llvm::AttributePlace::Argument(i), &[sret]);
}
PassMode::Cast { cast, pad_i32: _ } => {
PassMode::Cast { cast, pad_i32_count: _ } => {
cast.attrs.apply_attrs_to_callsite(
llvm::AttributePlace::ReturnValue,
bx.cx,
Expand Down Expand Up @@ -666,8 +668,8 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
apply(bx.cx, a);
apply(bx.cx, b);
}
PassMode::Cast { cast, pad_i32 } => {
if *pad_i32 {
PassMode::Cast { cast, pad_i32_count } => {
for _ in 0..*pad_i32_count {
apply(bx.cx, &ArgAttributes::new());
}
apply(bx.cx, &cast.attrs);
Expand Down
9 changes: 5 additions & 4 deletions compiler/rustc_codegen_ssa/src/mir/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -588,7 +588,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
}
}

PassMode::Cast { cast: cast_ty, pad_i32: _ } => {
PassMode::Cast { cast: cast_ty, pad_i32_count: _ } => {
let op = match self.locals[mir::RETURN_PLACE] {
LocalRef::Operand(op) => op,
LocalRef::PendingOperand => bug!("use of return before def"),
Expand Down Expand Up @@ -1936,9 +1936,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
) {
match arg.mode {
PassMode::Ignore => return,
PassMode::Cast { pad_i32: true, .. } => {
PassMode::Cast { pad_i32_count, .. } => {
// Fill padding with undef value, where applicable.
llargs.push(bx.const_undef(bx.reg_backend_type(&Reg::i32())));
let undef = bx.const_undef(bx.reg_backend_type(&Reg::i32()));
llargs.extend(std::iter::repeat_n(undef, usize::from(pad_i32_count)));
}
PassMode::Pair(..) => match op.val {
Pair(a, b) => {
Expand Down Expand Up @@ -2025,7 +2026,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {

if by_ref && !arg.is_indirect() {
// Have to load the argument, maybe while casting it.
if let PassMode::Cast { cast, pad_i32: _ } = &arg.mode {
if let PassMode::Cast { cast, pad_i32_count: _ } = &arg.mode {
// The ABI mandates that the value is passed as a different struct representation.
// Spill and reload it from the stack to convert from the Rust representation to
// the ABI representation.
Expand Down
8 changes: 4 additions & 4 deletions compiler/rustc_codegen_ssa/src/mir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -501,8 +501,8 @@ fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
for i in 0..tupled_arg_tys.len() {
let arg = &fx.fn_abi.args[idx];
idx += 1;
if let PassMode::Cast { pad_i32: true, .. } = arg.mode {
llarg_idx += 1;
if let PassMode::Cast { pad_i32_count, .. } = arg.mode {
llarg_idx += usize::from(pad_i32_count);
}
let pr_field = place.project_field(bx, i);
bx.store_fn_arg(arg, &mut llarg_idx, pr_field);
Expand All @@ -529,8 +529,8 @@ fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(

let arg = &fx.fn_abi.args[idx];
idx += 1;
if let PassMode::Cast { pad_i32: true, .. } = arg.mode {
llarg_idx += 1;
if let PassMode::Cast { pad_i32_count, .. } = arg.mode {
llarg_idx += usize::from(pad_i32_count);
}

if !memory_locals.contains(local) {
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_codegen_ssa/src/mir/naked_asm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -472,9 +472,9 @@ fn wasm_type<'tcx>(signature: &mut String, arg_abi: &ArgAbi<'_, Ty<'tcx>>, ptr_t
}
other => unreachable!("{other:?}"),
},
PassMode::Cast { pad_i32, ref cast } => {
PassMode::Cast { pad_i32_count, ref cast } => {
// For wasm, Cast is used for single-field primitive wrappers like `struct Wrapper(i64);`
assert!(!pad_i32, "not currently used by wasm calling convention");
assert_eq!(pad_i32_count, 0, "not currently used by wasm calling convention");
assert!(cast.prefix.is_empty(), "no prefix");
assert_eq!(cast.rest.total, arg_abi.layout.size, "single item");

Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_monomorphize/src/mono_checks/abi_check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ enum UsesVectorRegisters {
fn passes_vectors_by_value(mode: &PassMode, repr: &BackendRepr) -> UsesVectorRegisters {
match mode {
PassMode::Ignore | PassMode::Indirect { .. } => UsesVectorRegisters::No,
PassMode::Cast { pad_i32: _, cast }
PassMode::Cast { pad_i32_count: _, cast }
if cast.prefix.iter().any(|x| matches!(x.kind, RegKind::Vector { .. }))
|| matches!(cast.rest.unit.kind, RegKind::Vector { .. }) =>
{
Expand Down
Loading
Loading