1
1
use rustc_middle:: mir:: interpret:: { ConstValue , Scalar } ;
2
2
use rustc_middle:: { mir:: * , thir:: * , ty} ;
3
+ use rustc_span:: Span ;
4
+ use rustc_target:: abi:: VariantIdx ;
5
+
6
+ use crate :: build:: custom:: ParseError ;
7
+ use crate :: build:: expr:: as_constant:: as_constant_inner;
3
8
4
9
use super :: { parse_by_kind, PResult , ParseCtxt } ;
5
10
@@ -12,6 +17,14 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
12
17
@call( "mir_retag_raw" , args) => {
13
18
Ok ( StatementKind :: Retag ( RetagKind :: Raw , Box :: new( self . parse_place( args[ 0 ] ) ?) ) )
14
19
} ,
20
+ @call( "mir_set_discriminant" , args) => {
21
+ let place = self . parse_place( args[ 0 ] ) ?;
22
+ let var = self . parse_integer_literal( args[ 1 ] ) ? as u32 ;
23
+ Ok ( StatementKind :: SetDiscriminant {
24
+ place: Box :: new( place) ,
25
+ variant_index: VariantIdx :: from_u32( var) ,
26
+ } )
27
+ } ,
15
28
ExprKind :: Assign { lhs, rhs } => {
16
29
let lhs = self . parse_place( * lhs) ?;
17
30
let rhs = self . parse_rvalue( * rhs) ?;
@@ -21,18 +34,60 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
21
34
}
22
35
23
36
pub fn parse_terminator ( & self , expr_id : ExprId ) -> PResult < TerminatorKind < ' tcx > > {
24
- parse_by_kind ! ( self , expr_id, _ , "terminator" ,
37
+ parse_by_kind ! ( self , expr_id, expr , "terminator" ,
25
38
@call( "mir_return" , _args) => {
26
39
Ok ( TerminatorKind :: Return )
27
40
} ,
28
41
@call( "mir_goto" , args) => {
29
42
Ok ( TerminatorKind :: Goto { target: self . parse_block( args[ 0 ] ) ? } )
30
43
} ,
44
+ ExprKind :: Match { scrutinee, arms } => {
45
+ let discr = self . parse_operand( * scrutinee) ?;
46
+ self . parse_match( arms, expr. span) . map( |t| TerminatorKind :: SwitchInt { discr, targets: t } )
47
+ } ,
31
48
)
32
49
}
33
50
51
+ fn parse_match ( & self , arms : & [ ArmId ] , span : Span ) -> PResult < SwitchTargets > {
52
+ let Some ( ( otherwise, rest) ) = arms. split_last ( ) else {
53
+ return Err ( ParseError {
54
+ span,
55
+ item_description : format ! ( "no arms" ) ,
56
+ expected : "at least one arm" . to_string ( ) ,
57
+ } )
58
+ } ;
59
+
60
+ let otherwise = & self . thir [ * otherwise] ;
61
+ let PatKind :: Wild = otherwise. pattern . kind else {
62
+ return Err ( ParseError {
63
+ span : otherwise. span ,
64
+ item_description : format ! ( "{:?}" , otherwise. pattern. kind) ,
65
+ expected : "wildcard pattern" . to_string ( ) ,
66
+ } )
67
+ } ;
68
+ let otherwise = self . parse_block ( otherwise. body ) ?;
69
+
70
+ let mut values = Vec :: new ( ) ;
71
+ let mut targets = Vec :: new ( ) ;
72
+ for arm in rest {
73
+ let arm = & self . thir [ * arm] ;
74
+ let PatKind :: Constant { value } = arm. pattern . kind else {
75
+ return Err ( ParseError {
76
+ span : arm. pattern . span ,
77
+ item_description : format ! ( "{:?}" , arm. pattern. kind) ,
78
+ expected : "constant pattern" . to_string ( ) ,
79
+ } )
80
+ } ;
81
+ values. push ( value. eval_bits ( self . tcx , self . param_env , arm. pattern . ty ) ) ;
82
+ targets. push ( self . parse_block ( arm. body ) ?) ;
83
+ }
84
+
85
+ Ok ( SwitchTargets :: new ( values. into_iter ( ) . zip ( targets) , otherwise) )
86
+ }
87
+
34
88
fn parse_rvalue ( & self , expr_id : ExprId ) -> PResult < Rvalue < ' tcx > > {
35
89
parse_by_kind ! ( self , expr_id, _, "rvalue" ,
90
+ @call( "mir_discriminant" , args) => self . parse_place( args[ 0 ] ) . map( Rvalue :: Discriminant ) ,
36
91
ExprKind :: Borrow { borrow_kind, arg } => Ok (
37
92
Rvalue :: Ref ( self . tcx. lifetimes. re_erased, * borrow_kind, self . parse_place( * arg) ?)
38
93
) ,
@@ -55,7 +110,7 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
55
110
| ExprKind :: ConstParam { .. }
56
111
| ExprKind :: ConstBlock { .. } => {
57
112
Ok ( Operand :: Constant ( Box :: new(
58
- crate :: build :: expr :: as_constant :: as_constant_inner( expr, |_| None , self . tcx)
113
+ as_constant_inner( expr, |_| None , self . tcx)
59
114
) ) )
60
115
} ,
61
116
_ => self . parse_place( expr_id) . map( Operand :: Copy ) ,
@@ -102,4 +157,16 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
102
157
} ,
103
158
)
104
159
}
160
+
161
+ fn parse_integer_literal ( & self , expr_id : ExprId ) -> PResult < u128 > {
162
+ parse_by_kind ! ( self , expr_id, expr, "constant" ,
163
+ ExprKind :: Literal { .. }
164
+ | ExprKind :: NamedConst { .. }
165
+ | ExprKind :: NonHirLiteral { .. }
166
+ | ExprKind :: ConstBlock { .. } => Ok ( {
167
+ let value = as_constant_inner( expr, |_| None , self . tcx) ;
168
+ value. literal. eval_bits( self . tcx, self . param_env, value. ty( ) )
169
+ } ) ,
170
+ )
171
+ }
105
172
}
0 commit comments