about summary refs log tree commit diff
path: root/compiler/rustc_builtin_macros/src
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_builtin_macros/src')
-rw-r--r--compiler/rustc_builtin_macros/src/asm.rs387
-rw-r--r--compiler/rustc_builtin_macros/src/errors.rs79
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,
+}