@@ -34,9 +34,10 @@ use crate::{
34
34
FormatArgumentsCollector , FormatCount , FormatDebugHex , FormatOptions ,
35
35
FormatPlaceholder , FormatSign , FormatTrait ,
36
36
} ,
37
- Array , Binding , BindingAnnotation , BindingId , BindingProblems , CaptureBy , ClosureKind ,
38
- Expr , ExprId , InlineAsm , Label , LabelId , Literal , LiteralOrConst , MatchArm , Movability ,
39
- OffsetOf , Pat , PatId , RecordFieldPat , RecordLitField , Statement ,
37
+ Array , AsmOperand , AsmOptions , Binding , BindingAnnotation , BindingId , BindingProblems ,
38
+ CaptureBy , ClosureKind , Expr , ExprId , InlineAsm , InlineAsmRegOrRegClass , Label , LabelId ,
39
+ Literal , LiteralOrConst , MatchArm , Movability , OffsetOf , Pat , PatId , RecordFieldPat ,
40
+ RecordLitField , Statement ,
40
41
} ,
41
42
item_scope:: BuiltinShadowMode ,
42
43
lang_item:: LangItem ,
@@ -693,13 +694,7 @@ impl ExprCollector<'_> {
693
694
}
694
695
}
695
696
ast:: Expr :: UnderscoreExpr ( _) => self . alloc_expr ( Expr :: Underscore , syntax_ptr) ,
696
- ast:: Expr :: AsmExpr ( e) => {
697
- let template = e. template ( ) . map ( |it| self . collect_expr ( it) ) . collect ( ) ;
698
- self . alloc_expr (
699
- Expr :: InlineAsm ( InlineAsm { template, operands : Box :: default ( ) } ) ,
700
- syntax_ptr,
701
- )
702
- }
697
+ ast:: Expr :: AsmExpr ( e) => self . lower_inline_asm ( e, syntax_ptr) ,
703
698
ast:: Expr :: OffsetOfExpr ( e) => {
704
699
let container = Interned :: new ( TypeRef :: from_ast_opt ( & self . ctx ( ) , e. ty ( ) ) ) ;
705
700
let fields = e. fields ( ) . map ( |it| it. as_name ( ) ) . collect ( ) ;
@@ -2055,7 +2050,123 @@ impl ExprCollector<'_> {
2055
2050
is_assignee_expr : false ,
2056
2051
} )
2057
2052
}
2053
+
2058
2054
// endregion: format
2055
+ fn lower_inline_asm ( & mut self , asm : ast:: AsmExpr , syntax_ptr : AstPtr < ast:: Expr > ) -> ExprId {
2056
+ let mut clobber_abis = FxIndexSet :: default ( ) ;
2057
+ let mut operands = vec ! [ ] ;
2058
+ let mut options = AsmOptions :: empty ( ) ;
2059
+ for operand in asm. asm_operands ( ) {
2060
+ let lower_reg = |reg : Option < ast:: AsmRegSpec > | {
2061
+ let reg = reg?;
2062
+ if let Some ( string) = reg. string_token ( ) {
2063
+ Some ( InlineAsmRegOrRegClass :: Reg ( Symbol :: intern ( string. text ( ) ) ) )
2064
+ } else {
2065
+ reg. name_ref ( ) . map ( |name_ref| {
2066
+ InlineAsmRegOrRegClass :: RegClass ( Symbol :: intern ( & name_ref. text ( ) ) )
2067
+ } )
2068
+ }
2069
+ } ;
2070
+
2071
+ let op = match operand {
2072
+ ast:: AsmOperand :: AsmClobberAbi ( clobber_abi) => {
2073
+ if let Some ( abi_name) = clobber_abi. string_token ( ) {
2074
+ clobber_abis. insert ( Symbol :: intern ( abi_name. text ( ) ) ) ;
2075
+ }
2076
+ continue ;
2077
+ }
2078
+ ast:: AsmOperand :: AsmOptions ( opt) => {
2079
+ opt. asm_options ( ) . for_each ( |opt| {
2080
+ if opt. att_syntax_token ( ) . is_some ( ) {
2081
+ options |= AsmOptions :: ATT_SYNTAX ;
2082
+ } else if opt. may_unwind_token ( ) . is_some ( ) {
2083
+ options |= AsmOptions :: MAY_UNWIND ;
2084
+ } else if opt. nomem_token ( ) . is_some ( ) {
2085
+ options |= AsmOptions :: NOMEM ;
2086
+ } else if opt. noreturn_token ( ) . is_some ( ) {
2087
+ options |= AsmOptions :: NORETURN ;
2088
+ } else if opt. nostack_token ( ) . is_some ( ) {
2089
+ options |= AsmOptions :: NOSTACK ;
2090
+ } else if opt. preserves_flags_token ( ) . is_some ( ) {
2091
+ options |= AsmOptions :: PRESERVES_FLAGS ;
2092
+ } else if opt. pure_token ( ) . is_some ( ) {
2093
+ options |= AsmOptions :: PURE ;
2094
+ } else if opt. raw_token ( ) . is_some ( ) {
2095
+ options |= AsmOptions :: RAW ;
2096
+ } else if opt. readonly_token ( ) . is_some ( ) {
2097
+ options |= AsmOptions :: READONLY ;
2098
+ }
2099
+ } ) ;
2100
+ continue ;
2101
+ }
2102
+ ast:: AsmOperand :: AsmRegOperand ( op) => {
2103
+ let dir_spec = op. asm_dir_spec ( ) . unwrap ( ) ;
2104
+ let Some ( reg) = lower_reg ( op. asm_reg_spec ( ) ) else {
2105
+ continue ;
2106
+ } ;
2107
+ if dir_spec. in_token ( ) . is_some ( ) {
2108
+ let expr = self
2109
+ . collect_expr_opt ( op. asm_operand_expr ( ) . and_then ( |it| it. in_expr ( ) ) ) ;
2110
+ AsmOperand :: In { reg, expr }
2111
+ } else if dir_spec. out_token ( ) . is_some ( ) {
2112
+ let expr = self
2113
+ . collect_expr_opt ( op. asm_operand_expr ( ) . and_then ( |it| it. in_expr ( ) ) ) ;
2114
+ AsmOperand :: Out { reg, expr : Some ( expr) , late : false }
2115
+ } else if dir_spec. lateout_token ( ) . is_some ( ) {
2116
+ let expr = self
2117
+ . collect_expr_opt ( op. asm_operand_expr ( ) . and_then ( |it| it. in_expr ( ) ) ) ;
2118
+ AsmOperand :: Out { reg, expr : Some ( expr) , late : true }
2119
+ } else if dir_spec. inout_token ( ) . is_some ( ) {
2120
+ let op_expr = op. asm_operand_expr ( ) . unwrap ( ) ;
2121
+ let in_expr = self . collect_expr_opt ( op_expr. in_expr ( ) ) ;
2122
+ let out_expr = op_expr. out_expr ( ) . map ( |it| self . collect_expr ( it) ) ;
2123
+ match out_expr {
2124
+ Some ( out_expr) => AsmOperand :: SplitInOut {
2125
+ reg,
2126
+ in_expr,
2127
+ out_expr : Some ( out_expr) ,
2128
+ late : false ,
2129
+ } ,
2130
+ None => AsmOperand :: InOut { reg, expr : in_expr, late : false } ,
2131
+ }
2132
+ } else if dir_spec. inlateout_token ( ) . is_some ( ) {
2133
+ let op_expr = op. asm_operand_expr ( ) . unwrap ( ) ;
2134
+ let in_expr = self . collect_expr_opt ( op_expr. in_expr ( ) ) ;
2135
+ let out_expr = op_expr. out_expr ( ) . map ( |it| self . collect_expr ( it) ) ;
2136
+ match out_expr {
2137
+ Some ( out_expr) => AsmOperand :: SplitInOut {
2138
+ reg,
2139
+ in_expr,
2140
+ out_expr : Some ( out_expr) ,
2141
+ late : false ,
2142
+ } ,
2143
+ None => AsmOperand :: InOut { reg, expr : in_expr, late : false } ,
2144
+ }
2145
+ } else {
2146
+ continue ;
2147
+ }
2148
+ }
2149
+ ast:: AsmOperand :: AsmLabel ( l) => {
2150
+ AsmOperand :: Label ( self . collect_block_opt ( l. block_expr ( ) ) )
2151
+ }
2152
+ ast:: AsmOperand :: AsmConst ( c) => AsmOperand :: Const ( self . collect_expr_opt ( c. expr ( ) ) ) ,
2153
+ ast:: AsmOperand :: AsmSym ( s) => {
2154
+ let Some ( path) = s. path ( ) . and_then ( |p| self . expander . parse_path ( self . db , p) )
2155
+ else {
2156
+ continue ;
2157
+ } ;
2158
+ AsmOperand :: Sym ( path)
2159
+ }
2160
+ } ;
2161
+ operands. push ( op) ;
2162
+ }
2163
+
2164
+ let template = asm. template ( ) . map ( |it| self . collect_expr ( it) ) . collect ( ) ;
2165
+ self . alloc_expr (
2166
+ Expr :: InlineAsm ( InlineAsm { template, operands : operands. into_boxed_slice ( ) , options } ) ,
2167
+ syntax_ptr,
2168
+ )
2169
+ }
2059
2170
}
2060
2171
2061
2172
fn pat_literal_to_hir ( lit : & ast:: LiteralPat ) -> Option < ( Literal , ast:: Literal ) > {
0 commit comments