From 3431d586e5c61c8387e07972a4a19781ac785223 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Tue, 5 Sep 2023 13:28:41 +0200 Subject: [PATCH] Insert builtin#asm into asm! expansion --- crates/hir-def/src/body/lower.rs | 9 ++- crates/hir-def/src/body/pretty.rs | 3 +- crates/hir-def/src/hir.rs | 7 +++ crates/hir-ty/src/infer/closure.rs | 1 + crates/hir-ty/src/infer/expr.rs | 4 ++ crates/hir-ty/src/infer/mutability.rs | 1 + crates/hir-ty/src/mir/lower.rs | 3 + .../test_data/highlight_strings.html | 10 ++- crates/parser/src/grammar/expressions/atom.rs | 1 + .../parser/inline/ok/0207_builtin_expr.rast | 62 +++++++++++++++++++ .../parser/inline/ok/0207_builtin_expr.rs | 5 ++ crates/syntax/rust.ungram | 2 +- crates/syntax/src/ast/generated/nodes.rs | 1 + 13 files changed, 103 insertions(+), 6 deletions(-) create mode 100644 crates/parser/test_data/parser/inline/ok/0207_builtin_expr.rast create mode 100644 crates/parser/test_data/parser/inline/ok/0207_builtin_expr.rs diff --git a/crates/hir-def/src/body/lower.rs b/crates/hir-def/src/body/lower.rs index b536da2e57c..038032e05d8 100644 --- a/crates/hir-def/src/body/lower.rs +++ b/crates/hir-def/src/body/lower.rs @@ -30,8 +30,8 @@ use crate::{ expander::Expander, hir::{ dummy_expr_id, Array, Binding, BindingAnnotation, BindingId, BindingProblems, CaptureBy, - ClosureKind, Expr, ExprId, Label, LabelId, Literal, LiteralOrConst, MatchArm, Movability, - OffsetOf, Pat, PatId, RecordFieldPat, RecordLitField, Statement, + ClosureKind, Expr, ExprId, InlineAsm, Label, LabelId, Literal, LiteralOrConst, MatchArm, + Movability, OffsetOf, Pat, PatId, RecordFieldPat, RecordLitField, Statement, }, item_scope::BuiltinShadowMode, lang_item::LangItem, @@ -648,7 +648,10 @@ impl ExprCollector<'_> { } } ast::Expr::UnderscoreExpr(_) => self.alloc_expr(Expr::Underscore, syntax_ptr), - ast::Expr::AsmExpr(_) => self.missing_expr(), + ast::Expr::AsmExpr(e) => { + let expr = Expr::InlineAsm(InlineAsm { e: self.collect_expr_opt(e.expr()) }); + self.alloc_expr(expr, syntax_ptr) + } ast::Expr::OffsetOfExpr(e) => { let container = Interned::new(TypeRef::from_ast_opt(&self.ctx(), e.ty())); let fields = e.fields().map(|it| it.as_name()).collect(); diff --git a/crates/hir-def/src/body/pretty.rs b/crates/hir-def/src/body/pretty.rs index 6058fcbb652..602a7983c7c 100644 --- a/crates/hir-def/src/body/pretty.rs +++ b/crates/hir-def/src/body/pretty.rs @@ -155,8 +155,9 @@ impl Printer<'_> { match expr { Expr::Missing => w!(self, "�"), Expr::Underscore => w!(self, "_"), + Expr::InlineAsm(_) => w!(self, "builtin#asm(_)"), Expr::OffsetOf(offset_of) => { - w!(self, "builtin#offset_of!("); + w!(self, "builtin#offset_of("); self.print_type_ref(&offset_of.container); w!( self, diff --git a/crates/hir-def/src/hir.rs b/crates/hir-def/src/hir.rs index f03df800a05..1c86af456d1 100644 --- a/crates/hir-def/src/hir.rs +++ b/crates/hir-def/src/hir.rs @@ -282,6 +282,7 @@ pub enum Expr { Literal(Literal), Underscore, OffsetOf(OffsetOf), + InlineAsm(InlineAsm), } #[derive(Debug, Clone, PartialEq, Eq)] @@ -290,6 +291,11 @@ pub struct OffsetOf { pub fields: Box<[Name]>, } +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct InlineAsm { + pub e: ExprId, +} + #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum ClosureKind { Closure, @@ -349,6 +355,7 @@ impl Expr { match self { Expr::Missing => {} Expr::Path(_) | Expr::OffsetOf(_) => {} + Expr::InlineAsm(e) => f(e.e), Expr::If { condition, then_branch, else_branch } => { f(*condition); f(*then_branch); diff --git a/crates/hir-ty/src/infer/closure.rs b/crates/hir-ty/src/infer/closure.rs index ceb96a71653..1f040393f1f 100644 --- a/crates/hir-ty/src/infer/closure.rs +++ b/crates/hir-ty/src/infer/closure.rs @@ -453,6 +453,7 @@ impl InferenceContext<'_> { fn walk_expr_without_adjust(&mut self, tgt_expr: ExprId) { match &self.body[tgt_expr] { Expr::OffsetOf(_) => (), + Expr::InlineAsm(e) => self.walk_expr_without_adjust(e.e), Expr::If { condition, then_branch, else_branch } => { self.consume_expr(*condition); self.consume_expr(*then_branch); diff --git a/crates/hir-ty/src/infer/expr.rs b/crates/hir-ty/src/infer/expr.rs index d139d929fc3..555a9fae48e 100644 --- a/crates/hir-ty/src/infer/expr.rs +++ b/crates/hir-ty/src/infer/expr.rs @@ -844,6 +844,10 @@ impl InferenceContext<'_> { expected } Expr::OffsetOf(_) => TyKind::Scalar(Scalar::Uint(UintTy::Usize)).intern(Interner), + Expr::InlineAsm(it) => { + self.infer_expr_no_expect(it.e); + self.result.standard_types.unit.clone() + } }; // use a new type variable if we got unknown here let ty = self.insert_type_vars_shallow(ty); diff --git a/crates/hir-ty/src/infer/mutability.rs b/crates/hir-ty/src/infer/mutability.rs index 853c171a06a..b8a1af96fba 100644 --- a/crates/hir-ty/src/infer/mutability.rs +++ b/crates/hir-ty/src/infer/mutability.rs @@ -35,6 +35,7 @@ impl InferenceContext<'_> { fn infer_mut_expr_without_adjust(&mut self, tgt_expr: ExprId, mutability: Mutability) { match &self.body[tgt_expr] { Expr::Missing => (), + Expr::InlineAsm(e) => self.infer_mut_expr_without_adjust(e.e, Mutability::Not), Expr::OffsetOf(_) => (), &Expr::If { condition, then_branch, else_branch } => { self.infer_mut_expr(condition, Mutability::Not); diff --git a/crates/hir-ty/src/mir/lower.rs b/crates/hir-ty/src/mir/lower.rs index 3410c87d391..b6408cea502 100644 --- a/crates/hir-ty/src/mir/lower.rs +++ b/crates/hir-ty/src/mir/lower.rs @@ -373,6 +373,9 @@ impl<'ctx> MirLowerCtx<'ctx> { Expr::OffsetOf(_) => { not_supported!("builtin#offset_of") } + Expr::InlineAsm(_) => { + not_supported!("builtin#asm") + } Expr::Missing => { if let DefWithBodyId::FunctionId(f) = self.owner { let assoc = f.lookup(self.db.upcast()); diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html b/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html index 3ac8aa9cc9d..9c5c6d50ea7 100644 --- a/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html +++ b/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html @@ -176,7 +176,15 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd assert!(true, "{}", 1); assert!(true, "{} asdasd", 1); toho!("{}fmt", 0); - asm!("mov eax, {0}"); + let i: u64 = 3; + let o: u64; + asm!( + "mov {0}, {1}", + "add {0}, 5", + out(reg) o, + in(reg) i, + ); + format_args!(concat!("{}"), "{}"); format_args!("{} {} {} {} {} {}", backslash, format_args!("{}", 0), foo, "bar", toho!(), backslash); } \ No newline at end of file diff --git a/crates/parser/src/grammar/expressions/atom.rs b/crates/parser/src/grammar/expressions/atom.rs index 1dd68f556c4..e13284d1b7a 100644 --- a/crates/parser/src/grammar/expressions/atom.rs +++ b/crates/parser/src/grammar/expressions/atom.rs @@ -254,6 +254,7 @@ fn builtin_expr(p: &mut Parser<'_>) -> Option { } else if p.at_contextual_kw(T![asm]) { p.bump_remap(T![asm]); p.expect(T!['(']); + // FIXME: We just put expression here so highlighting kind of keeps working expr(p); p.expect(T![')']); Some(m.complete(p, ASM_EXPR)) diff --git a/crates/parser/test_data/parser/inline/ok/0207_builtin_expr.rast b/crates/parser/test_data/parser/inline/ok/0207_builtin_expr.rast new file mode 100644 index 00000000000..f127b3e8c89 --- /dev/null +++ b/crates/parser/test_data/parser/inline/ok/0207_builtin_expr.rast @@ -0,0 +1,62 @@ +SOURCE_FILE + FN + FN_KW "fn" + WHITESPACE " " + NAME + IDENT "foo" + PARAM_LIST + L_PAREN "(" + R_PAREN ")" + WHITESPACE " " + BLOCK_EXPR + STMT_LIST + L_CURLY "{" + WHITESPACE "\n " + EXPR_STMT + ASM_EXPR + BUILTIN_KW "builtin" + POUND "#" + ASM_KW "asm" + L_PAREN "(" + LITERAL + INT_NUMBER "0" + R_PAREN ")" + SEMICOLON ";" + WHITESPACE "\n " + EXPR_STMT + FORMAT_ARGS_EXPR + BUILTIN_KW "builtin" + POUND "#" + FORMAT_ARGS_KW "format_args" + L_PAREN "(" + LITERAL + INT_NUMBER "0" + R_PAREN ")" + SEMICOLON ";" + WHITESPACE "\n " + EXPR_STMT + OFFSET_OF_EXPR + BUILTIN_KW "builtin" + POUND "#" + OFFSET_OF_KW "offset_of" + L_PAREN "(" + PATH_TYPE + PATH + PATH_SEGMENT + NAME_REF + IDENT "Foo" + COMMA "," + WHITESPACE " " + NAME_REF + IDENT "bar" + DOT "." + NAME_REF + IDENT "baz" + DOT "." + NAME_REF + INT_NUMBER "0" + R_PAREN ")" + SEMICOLON ";" + WHITESPACE "\n" + R_CURLY "}" + WHITESPACE "\n" diff --git a/crates/parser/test_data/parser/inline/ok/0207_builtin_expr.rs b/crates/parser/test_data/parser/inline/ok/0207_builtin_expr.rs new file mode 100644 index 00000000000..dbad0a91df9 --- /dev/null +++ b/crates/parser/test_data/parser/inline/ok/0207_builtin_expr.rs @@ -0,0 +1,5 @@ +fn foo() { + builtin#asm(0); + builtin#format_args(0); + builtin#offset_of(Foo, bar.baz.0); +} diff --git a/crates/syntax/rust.ungram b/crates/syntax/rust.ungram index d7b1c91216b..2ce609b97a6 100644 --- a/crates/syntax/rust.ungram +++ b/crates/syntax/rust.ungram @@ -379,7 +379,7 @@ OffsetOfExpr = Attr* 'builtin' '#' 'offset_of' '(' Type ',' fields:(NameRef ('.' NameRef)* ) ')' AsmExpr = - Attr* 'builtin' '#' 'asm' '(' ')' + Attr* 'builtin' '#' 'asm' '(' Expr ')' FormatArgsExpr = Attr* 'builtin' '#' 'format_args' '(' ')' diff --git a/crates/syntax/src/ast/generated/nodes.rs b/crates/syntax/src/ast/generated/nodes.rs index d817589223e..1c5e2282ecb 100644 --- a/crates/syntax/src/ast/generated/nodes.rs +++ b/crates/syntax/src/ast/generated/nodes.rs @@ -814,6 +814,7 @@ impl AsmExpr { pub fn pound_token(&self) -> Option { support::token(&self.syntax, T![#]) } pub fn asm_token(&self) -> Option { support::token(&self.syntax, T![asm]) } pub fn l_paren_token(&self) -> Option { support::token(&self.syntax, T!['(']) } + pub fn expr(&self) -> Option { support::child(&self.syntax) } pub fn r_paren_token(&self) -> Option { support::token(&self.syntax, T![')']) } }