diff options
Diffstat (limited to 'compiler/rustc_builtin_macros/src')
| -rw-r--r-- | compiler/rustc_builtin_macros/src/asm.rs | 387 | ||||
| -rw-r--r-- | compiler/rustc_builtin_macros/src/errors.rs | 79 |
2 files changed, 11 insertions, 455 deletions
diff --git a/compiler/rustc_builtin_macros/src/asm.rs b/compiler/rustc_builtin_macros/src/asm.rs index 593d9ddfdf8..1fb99817222 100644 --- a/compiler/rustc_builtin_macros/src/asm.rs +++ b/compiler/rustc_builtin_macros/src/asm.rs @@ -1,4 +1,3 @@ -use ast::token::IdentIsRaw; use lint::BuiltinLintDiag; use rustc_ast::ptr::P; use rustc_ast::tokenstream::TokenStream; @@ -7,11 +6,10 @@ use rustc_data_structures::fx::{FxHashMap, FxIndexMap}; use rustc_errors::PResult; use rustc_expand::base::*; use rustc_index::bit_set::GrowableBitSet; -use rustc_parse::exp; -use rustc_parse::parser::{ExpKeywordPair, Parser}; +use rustc_parse::parser::asm::*; use rustc_session::lint; use rustc_session::parse::feature_err; -use rustc_span::{ErrorGuaranteed, InnerSpan, Span, Symbol, kw, sym}; +use rustc_span::{ErrorGuaranteed, InnerSpan, Span, Symbol, sym}; use rustc_target::asm::InlineAsmArch; use smallvec::smallvec; use {rustc_ast as ast, rustc_parse_format as parse}; @@ -19,30 +17,6 @@ use {rustc_ast as ast, rustc_parse_format as parse}; use crate::util::{ExprToSpannedString, expr_to_spanned_string}; use crate::{errors, fluent_generated as fluent}; -/// An argument to one of the `asm!` macros. The argument is syntactically valid, but is otherwise -/// not validated at all. -pub struct AsmArg { - pub kind: AsmArgKind, - pub attributes: AsmAttrVec, - pub span: Span, -} - -pub enum AsmArgKind { - Template(P<ast::Expr>), - Operand(Option<Symbol>, ast::InlineAsmOperand), - Options(Vec<AsmOption>), - ClobberAbi(Vec<(Symbol, Span)>), -} - -pub struct AsmOption { - pub symbol: Symbol, - pub span: Span, - // A bitset, with only the bit for this option's symbol set. - pub options: ast::InlineAsmOptions, - // Used when suggesting to remove an option. - pub span_with_comma: Span, -} - /// Validated assembly arguments, ready for macro expansion. struct ValidatedAsmArgs { pub templates: Vec<P<ast::Expr>>, @@ -54,266 +28,6 @@ struct ValidatedAsmArgs { pub options_spans: Vec<Span>, } -/// A parsed list of attributes that is not attached to any item. -/// Used to check whether `asm!` arguments are configured out. -pub struct AsmAttrVec(pub ast::AttrVec); - -impl AsmAttrVec { - fn parse<'a>(p: &mut Parser<'a>) -> PResult<'a, Self> { - let mut attributes = ast::AttrVec::new(); - while p.token == token::Pound { - let attr = p.parse_attribute(rustc_parse::parser::attr::InnerAttrPolicy::Permitted)?; - attributes.push(attr); - } - - Ok(Self(attributes)) - } -} -impl ast::HasAttrs for AsmAttrVec { - // Follows `ast::Expr`. - const SUPPORTS_CUSTOM_INNER_ATTRS: bool = false; - - fn attrs(&self) -> &[rustc_ast::Attribute] { - &self.0 - } - - fn visit_attrs(&mut self, f: impl FnOnce(&mut rustc_ast::AttrVec)) { - f(&mut self.0) - } -} - -impl ast::HasTokens for AsmAttrVec { - fn tokens(&self) -> Option<&rustc_ast::tokenstream::LazyAttrTokenStream> { - None - } - - fn tokens_mut(&mut self) -> Option<&mut Option<rustc_ast::tokenstream::LazyAttrTokenStream>> { - None - } -} - -/// Used for better error messages when operand types are used that are not -/// supported by the current macro (e.g. `in` or `out` for `global_asm!`) -/// -/// returns -/// -/// - `Ok(true)` if the current token matches the keyword, and was expected -/// - `Ok(false)` if the current token does not match the keyword -/// - `Err(_)` if the current token matches the keyword, but was not expected -fn eat_operand_keyword<'a>( - p: &mut Parser<'a>, - exp: ExpKeywordPair, - asm_macro: AsmMacro, -) -> PResult<'a, bool> { - if matches!(asm_macro, AsmMacro::Asm) { - Ok(p.eat_keyword(exp)) - } else { - let span = p.token.span; - if p.eat_keyword_noexpect(exp.kw) { - // in gets printed as `r#in` otherwise - let symbol = if exp.kw == kw::In { "in" } else { exp.kw.as_str() }; - Err(p.dcx().create_err(errors::AsmUnsupportedOperand { - span, - symbol, - macro_name: asm_macro.macro_name(), - })) - } else { - Ok(false) - } - } -} - -fn parse_asm_operand<'a>( - p: &mut Parser<'a>, - asm_macro: AsmMacro, -) -> PResult<'a, Option<ast::InlineAsmOperand>> { - let dcx = p.dcx(); - - Ok(Some(if eat_operand_keyword(p, exp!(In), asm_macro)? { - let reg = parse_reg(p)?; - if p.eat_keyword(exp!(Underscore)) { - let err = dcx.create_err(errors::AsmUnderscoreInput { span: p.token.span }); - return Err(err); - } - let expr = p.parse_expr()?; - ast::InlineAsmOperand::In { reg, expr } - } else if eat_operand_keyword(p, exp!(Out), asm_macro)? { - let reg = parse_reg(p)?; - let expr = if p.eat_keyword(exp!(Underscore)) { None } else { Some(p.parse_expr()?) }; - ast::InlineAsmOperand::Out { reg, expr, late: false } - } else if eat_operand_keyword(p, exp!(Lateout), asm_macro)? { - let reg = parse_reg(p)?; - let expr = if p.eat_keyword(exp!(Underscore)) { None } else { Some(p.parse_expr()?) }; - ast::InlineAsmOperand::Out { reg, expr, late: true } - } else if eat_operand_keyword(p, exp!(Inout), asm_macro)? { - let reg = parse_reg(p)?; - if p.eat_keyword(exp!(Underscore)) { - let err = dcx.create_err(errors::AsmUnderscoreInput { span: p.token.span }); - return Err(err); - } - let expr = p.parse_expr()?; - if p.eat(exp!(FatArrow)) { - let out_expr = - if p.eat_keyword(exp!(Underscore)) { None } else { Some(p.parse_expr()?) }; - ast::InlineAsmOperand::SplitInOut { reg, in_expr: expr, out_expr, late: false } - } else { - ast::InlineAsmOperand::InOut { reg, expr, late: false } - } - } else if eat_operand_keyword(p, exp!(Inlateout), asm_macro)? { - let reg = parse_reg(p)?; - if p.eat_keyword(exp!(Underscore)) { - let err = dcx.create_err(errors::AsmUnderscoreInput { span: p.token.span }); - return Err(err); - } - let expr = p.parse_expr()?; - if p.eat(exp!(FatArrow)) { - let out_expr = - if p.eat_keyword(exp!(Underscore)) { None } else { Some(p.parse_expr()?) }; - ast::InlineAsmOperand::SplitInOut { reg, in_expr: expr, out_expr, late: true } - } else { - ast::InlineAsmOperand::InOut { reg, expr, late: true } - } - } else if eat_operand_keyword(p, exp!(Label), asm_macro)? { - let block = p.parse_block()?; - ast::InlineAsmOperand::Label { block } - } else if p.eat_keyword(exp!(Const)) { - let anon_const = p.parse_expr_anon_const()?; - ast::InlineAsmOperand::Const { anon_const } - } else if p.eat_keyword(exp!(Sym)) { - let expr = p.parse_expr()?; - let ast::ExprKind::Path(qself, path) = &expr.kind else { - let err = dcx.create_err(errors::AsmSymNoPath { span: expr.span }); - return Err(err); - }; - let sym = - ast::InlineAsmSym { id: ast::DUMMY_NODE_ID, qself: qself.clone(), path: path.clone() }; - ast::InlineAsmOperand::Sym { sym } - } else { - return Ok(None); - })) -} - -// Public for rustfmt. -pub fn parse_asm_args<'a>( - p: &mut Parser<'a>, - sp: Span, - asm_macro: AsmMacro, -) -> PResult<'a, Vec<AsmArg>> { - let dcx = p.dcx(); - - if p.token == token::Eof { - return Err(dcx.create_err(errors::AsmRequiresTemplate { span: sp })); - } - - let mut args = Vec::new(); - - let attributes = AsmAttrVec::parse(p)?; - let first_template = p.parse_expr()?; - args.push(AsmArg { - span: first_template.span, - kind: AsmArgKind::Template(first_template), - attributes, - }); - - let mut allow_templates = true; - - while p.token != token::Eof { - if !p.eat(exp!(Comma)) { - if allow_templates { - // After a template string, we always expect *only* a comma... - return Err(dcx.create_err(errors::AsmExpectedComma { span: p.token.span })); - } else { - // ...after that delegate to `expect` to also include the other expected tokens. - return Err(p.expect(exp!(Comma)).err().unwrap()); - } - } - - // Accept trailing commas. - if p.token == token::Eof { - break; - } - - let attributes = AsmAttrVec::parse(p)?; - let span_start = p.token.span; - - // Parse `clobber_abi`. - if p.eat_keyword(exp!(ClobberAbi)) { - allow_templates = false; - - args.push(AsmArg { - kind: AsmArgKind::ClobberAbi(parse_clobber_abi(p)?), - span: span_start.to(p.prev_token.span), - attributes, - }); - - continue; - } - - // Parse `options`. - if p.eat_keyword(exp!(Options)) { - allow_templates = false; - - args.push(AsmArg { - kind: AsmArgKind::Options(parse_options(p, asm_macro)?), - span: span_start.to(p.prev_token.span), - attributes, - }); - - continue; - } - - // Parse operand names. - let name = if p.token.is_ident() && p.look_ahead(1, |t| *t == token::Eq) { - let (ident, _) = p.token.ident().unwrap(); - p.bump(); - p.expect(exp!(Eq))?; - allow_templates = false; - Some(ident.name) - } else { - None - }; - - if let Some(op) = parse_asm_operand(p, asm_macro)? { - allow_templates = false; - - args.push(AsmArg { - span: span_start.to(p.prev_token.span), - kind: AsmArgKind::Operand(name, op), - attributes, - }); - } else if allow_templates { - let template = p.parse_expr()?; - // If it can't possibly expand to a string, provide diagnostics here to include other - // things it could have been. - match template.kind { - ast::ExprKind::Lit(token_lit) - if matches!( - token_lit.kind, - token::LitKind::Str | token::LitKind::StrRaw(_) - ) => {} - ast::ExprKind::MacCall(..) => {} - _ => { - let err = dcx.create_err(errors::AsmExpectedOther { - span: template.span, - is_inline_asm: matches!(asm_macro, AsmMacro::Asm), - }); - return Err(err); - } - } - - args.push(AsmArg { - span: template.span, - kind: AsmArgKind::Template(template), - attributes, - }); - } else { - p.unexpected_any()? - } - } - - Ok(args) -} - fn parse_args<'a>( ecx: &ExtCtxt<'a>, sp: Span, @@ -559,103 +273,6 @@ fn validate_asm_args<'a>( Ok(validated) } -fn parse_options<'a>(p: &mut Parser<'a>, asm_macro: AsmMacro) -> PResult<'a, Vec<AsmOption>> { - p.expect(exp!(OpenParen))?; - - let mut asm_options = Vec::new(); - - while !p.eat(exp!(CloseParen)) { - const OPTIONS: [(ExpKeywordPair, ast::InlineAsmOptions); ast::InlineAsmOptions::COUNT] = [ - (exp!(Pure), ast::InlineAsmOptions::PURE), - (exp!(Nomem), ast::InlineAsmOptions::NOMEM), - (exp!(Readonly), ast::InlineAsmOptions::READONLY), - (exp!(PreservesFlags), ast::InlineAsmOptions::PRESERVES_FLAGS), - (exp!(Noreturn), ast::InlineAsmOptions::NORETURN), - (exp!(Nostack), ast::InlineAsmOptions::NOSTACK), - (exp!(MayUnwind), ast::InlineAsmOptions::MAY_UNWIND), - (exp!(AttSyntax), ast::InlineAsmOptions::ATT_SYNTAX), - (exp!(Raw), ast::InlineAsmOptions::RAW), - ]; - - 'blk: { - for (exp, options) in OPTIONS { - // Gives a more accurate list of expected next tokens. - let kw_matched = if asm_macro.is_supported_option(options) { - p.eat_keyword(exp) - } else { - p.eat_keyword_noexpect(exp.kw) - }; - - if kw_matched { - let span = p.prev_token.span; - let span_with_comma = - if p.token == token::Comma { span.to(p.token.span) } else { span }; - - asm_options.push(AsmOption { symbol: exp.kw, span, options, span_with_comma }); - break 'blk; - } - } - - return p.unexpected_any(); - } - - // Allow trailing commas. - if p.eat(exp!(CloseParen)) { - break; - } - p.expect(exp!(Comma))?; - } - - Ok(asm_options) -} - -fn parse_clobber_abi<'a>(p: &mut Parser<'a>) -> PResult<'a, Vec<(Symbol, Span)>> { - p.expect(exp!(OpenParen))?; - - if p.eat(exp!(CloseParen)) { - return Err(p.dcx().create_err(errors::NonABI { span: p.token.span })); - } - - let mut new_abis = Vec::new(); - while !p.eat(exp!(CloseParen)) { - match p.parse_str_lit() { - Ok(str_lit) => { - new_abis.push((str_lit.symbol_unescaped, str_lit.span)); - } - Err(opt_lit) => { - let span = opt_lit.map_or(p.token.span, |lit| lit.span); - return Err(p.dcx().create_err(errors::AsmExpectedStringLiteral { span })); - } - }; - - // Allow trailing commas - if p.eat(exp!(CloseParen)) { - break; - } - p.expect(exp!(Comma))?; - } - - Ok(new_abis) -} - -fn parse_reg<'a>(p: &mut Parser<'a>) -> PResult<'a, ast::InlineAsmRegOrRegClass> { - p.expect(exp!(OpenParen))?; - let result = match p.token.uninterpolate().kind { - token::Ident(name, IdentIsRaw::No) => ast::InlineAsmRegOrRegClass::RegClass(name), - token::Literal(token::Lit { kind: token::LitKind::Str, symbol, suffix: _ }) => { - ast::InlineAsmRegOrRegClass::Reg(symbol) - } - _ => { - return Err(p.dcx().create_err(errors::ExpectedRegisterClassOrExplicitRegister { - span: p.token.span, - })); - } - }; - p.bump(); - p.expect(exp!(CloseParen))?; - Ok(result) -} - fn expand_preparsed_asm( ecx: &mut ExtCtxt<'_>, asm_macro: AsmMacro, diff --git a/compiler/rustc_builtin_macros/src/errors.rs b/compiler/rustc_builtin_macros/src/errors.rs index 73e8fed321c..75d06a8df14 100644 --- a/compiler/rustc_builtin_macros/src/errors.rs +++ b/compiler/rustc_builtin_macros/src/errors.rs @@ -110,13 +110,6 @@ pub(crate) struct ProcMacro { } #[derive(Diagnostic)] -#[diag(builtin_macros_non_abi)] -pub(crate) struct NonABI { - #[primary_span] - pub(crate) span: Span, -} - -#[derive(Diagnostic)] #[diag(builtin_macros_trace_macros)] pub(crate) struct TraceMacros { #[primary_span] @@ -789,13 +782,6 @@ pub(crate) struct AsmModifierInvalid { } #[derive(Diagnostic)] -#[diag(builtin_macros_asm_requires_template)] -pub(crate) struct AsmRequiresTemplate { - #[primary_span] - pub(crate) span: Span, -} - -#[derive(Diagnostic)] #[diag(builtin_macros_asm_attribute_not_supported)] pub(crate) struct AsmAttributeNotSupported { #[primary_span] @@ -803,45 +789,6 @@ pub(crate) struct AsmAttributeNotSupported { } #[derive(Diagnostic)] -#[diag(builtin_macros_asm_expected_comma)] -pub(crate) struct AsmExpectedComma { - #[primary_span] - #[label] - pub(crate) span: Span, -} - -#[derive(Diagnostic)] -#[diag(builtin_macros_asm_expected_string_literal)] -pub(crate) struct AsmExpectedStringLiteral { - #[primary_span] - #[label] - pub(crate) span: Span, -} - -#[derive(Diagnostic)] -#[diag(builtin_macros_asm_underscore_input)] -pub(crate) struct AsmUnderscoreInput { - #[primary_span] - pub(crate) span: Span, -} - -#[derive(Diagnostic)] -#[diag(builtin_macros_asm_sym_no_path)] -pub(crate) struct AsmSymNoPath { - #[primary_span] - pub(crate) span: Span, -} - -#[derive(Diagnostic)] -#[diag(builtin_macros_asm_expected_other)] -pub(crate) struct AsmExpectedOther { - #[primary_span] - #[label(builtin_macros_asm_expected_other)] - pub(crate) span: Span, - pub(crate) is_inline_asm: bool, -} - -#[derive(Diagnostic)] #[diag(builtin_macros_asm_duplicate_arg)] pub(crate) struct AsmDuplicateArg { #[primary_span] @@ -933,16 +880,6 @@ pub(crate) struct AsmUnsupportedOption { } #[derive(Diagnostic)] -#[diag(builtin_macros_asm_unsupported_operand)] -pub(crate) struct AsmUnsupportedOperand<'a> { - #[primary_span] - #[label] - pub(crate) span: Span, - pub(crate) symbol: &'a str, - pub(crate) macro_name: &'static str, -} - -#[derive(Diagnostic)] #[diag(builtin_macros_asm_unsupported_clobber_abi)] pub(crate) struct AsmUnsupportedClobberAbi { #[primary_span] @@ -965,13 +902,6 @@ pub(crate) struct TestRunnerNargs { } #[derive(Diagnostic)] -#[diag(builtin_macros_expected_register_class_or_explicit_register)] -pub(crate) struct ExpectedRegisterClassOrExplicitRegister { - #[primary_span] - pub(crate) span: Span, -} - -#[derive(Diagnostic)] #[diag(builtin_macros_expected_comma_in_list)] pub(crate) struct ExpectedCommaInList { #[primary_span] @@ -1034,3 +964,12 @@ pub(crate) struct NonGenericPointee { #[primary_span] pub span: Span, } + +#[derive(Diagnostic)] +#[diag(builtin_macros_expected_other)] +pub(crate) struct AsmExpectedOther { + #[primary_span] + #[label(builtin_macros_expected_other)] + pub(crate) span: Span, + pub(crate) is_inline_asm: bool, +} |
