@@ -10,73 +10,190 @@ extern crate rustc_driver;
10
10
use rustc_codegen_ssa:: CrateInfo ;
11
11
use std:: any:: Any ;
12
12
use rustc_codegen_ssa:: { traits:: CodegenBackend , CodegenResults } ;
13
- use rustc_middle:: { ty:: { TyCtxt , Ty , ParamEnv , Instance , PolyFnSig } , dep_graph:: { WorkProductId , WorkProduct } , mir:: { Statement , StatementKind , Rvalue , mono:: MonoItem , Operand } } ;
13
+ use rustc_middle:: { ty:: { TyCtxt , Ty , ParamEnv , Instance , PolyFnSig , TyKind , IntTy } , dep_graph:: { WorkProductId , WorkProduct } , mir:: { Statement , StatementKind , Terminator , TerminatorKind , Rvalue , BinOp , Operand , ConstantKind , AggregateKind , interpret :: ConstValue , mono:: MonoItem } } ;
14
14
use rustc_metadata:: EncodedMetadata ;
15
15
use rustc_span:: ErrorGuaranteed ;
16
16
use std:: hash:: BuildHasherDefault ;
17
17
use rustc_session:: { config:: OutputFilenames , Session } ;
18
18
use rustc_data_structures:: fx:: FxIndexMap ;
19
- #[ derive( Debug ) ]
20
- enum CLROp {
19
+ #[ derive( Debug , Clone ) ]
20
+ enum BaseIR {
21
+ LDConstI32 ( i32 ) ,
21
22
STArg ( u32 ) ,
22
23
LDArg ( u32 ) ,
23
24
STLoc ( u32 ) ,
24
25
LDLoc ( u32 ) ,
26
+ Add ,
27
+ Mul ,
28
+ Shl ,
29
+ Return ,
25
30
}
26
31
struct MyBackend ;
27
32
struct CustomCodegen { }
28
33
#[ derive( Debug ) ]
29
34
struct CLRMethod {
30
- ops : Vec < CLROp > ,
35
+ ops : Vec < BaseIR > ,
31
36
argc : u32 ,
32
37
}
38
+ enum LocalPlacement {
39
+ Arg ( u32 ) ,
40
+ Var ( u32 ) ,
41
+ }
33
42
impl CLRMethod {
34
43
fn argc ( & self ) ->u32 { self . argc }
44
+ fn remove_sl ( & mut self ) ->usize {
45
+ let mut opt_ops: Vec < BaseIR > = Vec :: with_capacity ( self . ops . len ( ) ) ;
46
+ let mut ops_peek = self . ops . iter ( ) . peekable ( ) ;
47
+ while let Some ( op) = ops_peek. next ( ) {
48
+ match op{
49
+ BaseIR :: STLoc ( local_id) =>{
50
+ if let Some ( BaseIR :: LDLoc ( other_id) ) = ops_peek. peek ( ) {
51
+ //Ops store and the load the same value, being effectively a NOP.
52
+ if local_id == other_id{
53
+ ops_peek. next ( ) ;
54
+ continue ;
55
+ }
56
+ }
57
+ }
58
+ _=>( ) ,
59
+ }
60
+ opt_ops. push ( op. clone ( ) ) ;
61
+ }
62
+ self . ops = opt_ops;
63
+ self . ops . len ( )
64
+ }
65
+ fn opt ( & mut self ) {
66
+ const MAX_OPT_PASS : usize = 8 ;
67
+ for _ in 0 ..MAX_OPT_PASS {
68
+ let prev_length = self . ops . len ( ) ;
69
+ if !( self . remove_sl ( ) < prev_length) { continue ; }
70
+ }
71
+ }
72
+ fn has_return ( & self ) ->bool { true }
35
73
fn new ( argc : u32 ) ->Self {
36
74
Self { argc, ops : Vec :: with_capacity ( 0xF ) }
37
75
}
38
- fn load ( & mut self , var : u32 ) {
39
- if var < self . argc ( ) {
40
- self . ops . push ( CLROp :: LDArg ( var) ) ;
76
+ fn var_live ( & mut self , local : u32 ) {
77
+ //TODO: use variable lifetimes!
78
+ }
79
+ fn var_dead ( & mut self , local : u32 ) {
80
+ //TODO: use variable lifetimes!
81
+ }
82
+ fn local_id_placement ( & self , local : u32 ) ->LocalPlacement {
83
+ // I assume local 0 is supposed to be the return value. TODO: check if this is always the case.
84
+ if self . has_return ( ) {
85
+ if local == 0 {
86
+ LocalPlacement :: Var ( 0 )
87
+ }
88
+ else if local - 1 < self . argc ( ) {
89
+ LocalPlacement :: Arg ( local - 1 )
90
+ }
91
+ else {
92
+ LocalPlacement :: Var ( local - self . argc ( ) )
93
+ }
41
94
}
42
95
else {
43
- println ! ( "argc:{}, var:{var}" , self . argc) ;
44
- self . ops . push ( CLROp :: LDLoc ( var - self . argc ( ) ) ) ;
96
+ panic ! ( "Can't handle void functions yet. Diagnose MIR to determine what happens to the return var(0)!" ) ;
45
97
}
98
+
99
+ }
100
+ fn load ( & mut self , local : u32 ) {
101
+ self . ops . push ( match self . local_id_placement ( local) {
102
+ LocalPlacement :: Arg ( arg_id) =>BaseIR :: LDArg ( arg_id) ,
103
+ LocalPlacement :: Var ( var_id) =>BaseIR :: LDLoc ( var_id) ,
104
+ } )
105
+ }
106
+ fn store ( & mut self , local : u32 ) {
107
+ self . ops . push ( match self . local_id_placement ( local) {
108
+ LocalPlacement :: Arg ( arg_id) =>BaseIR :: STArg ( arg_id) ,
109
+ LocalPlacement :: Var ( var_id) =>BaseIR :: STLoc ( var_id) ,
110
+ } )
111
+ }
112
+ fn process_constant ( & mut self , constant : ConstantKind ) {
113
+ self . ops . push ( match constant{
114
+ ConstantKind :: Val ( value, r#type) => match value{
115
+ ConstValue :: Scalar ( scalar) =>{
116
+ match r#type. kind ( ) {
117
+ TyKind :: Int ( IntTy :: I32 ) =>BaseIR :: LDConstI32 ( scalar. to_i32 ( ) . expect ( "Type is i32, but odes not fit in i32." ) ) ,
118
+ _=>todo ! ( "Unhandled type kind {:?}" , r#type. kind( ) ) ,
119
+ }
120
+ }
121
+ _=>todo ! ( "Unhanled constant value {value:?}" ) ,
122
+ }
123
+ _=>todo ! ( "Unhanled constant {constant:?}" ) ,
124
+ } ) ;
46
125
}
47
126
// Makes so the top of the stack is the value of RValue
48
127
fn process_operand ( & mut self , operand : & Operand ) {
49
128
match operand{
50
129
Operand :: Copy ( place) => self . load ( place. local . into ( ) ) ,
130
+ //TODO:Do moves need to be treated any diffrently forom copies in the context of CLR?
131
+ Operand :: Move ( place) => self . load ( place. local . into ( ) ) ,
132
+ Operand :: Constant ( const_val) =>{
133
+ self . process_constant ( const_val. literal ) ;
134
+ } ,
51
135
_=>todo ! ( "Unhanled operand {operand:?}" ) ,
52
136
}
53
137
}
54
138
// Makes so the top of the stack is the value of RValue
55
139
fn process_rvalue ( & mut self , rvalue : & Rvalue ) {
56
140
match rvalue{
57
141
Rvalue :: Use ( operand) =>self . process_operand ( operand) ,
142
+ Rvalue :: BinaryOp ( binop, operands) =>{
143
+ let ( a, b) : ( _ , _ ) = ( & operands. 0 , & operands. 1 ) ;
144
+ self . process_operand ( a) ;
145
+ self . process_operand ( b) ;
146
+ self . ops . push ( match binop{
147
+ BinOp :: Add =>BaseIR :: Add ,
148
+ BinOp :: Mul =>BaseIR :: Mul ,
149
+ BinOp :: Shl =>BaseIR :: Shl ,
150
+ _=>todo ! ( "Unknown binop:{binop:?}" ) ,
151
+ } ) ;
152
+ }
153
+ Rvalue :: Aggregate ( kind, operands) =>{
154
+ match kind. as_ref ( ) {
155
+ AggregateKind :: Adt ( def_id, variant_idx, subst_ref, utai, fidx) =>{
156
+ //let (def_id,variant_idx,subst_ref,utai,fidx) = *adt;
157
+ panic ! ( "def_id:{def_id:?},variant_idx:{variant_idx:?},subst_ref:{subst_ref:?},utai:{utai:?},fidx:{fidx:?},\n operands:{operands}" ) ;
158
+ }
159
+ _=> todo ! ( "Can't yet handle the aggregate of kind {kind:?} and operands:{operands:?}" ) ,
160
+ }
161
+ }
58
162
_=>todo ! ( "Can't yet handle a rvalue of type {rvalue:?}" ) ,
59
163
}
60
164
}
61
- fn store ( & mut self , var : u32 ) {
62
- if var < self . argc ( ) {
63
- self . ops . push ( CLROp :: STArg ( var) ) ;
64
- }
65
- else {
66
- self . ops . push ( CLROp :: STLoc ( var - self . argc ( ) ) ) ;
67
- }
68
- }
69
165
fn add_statement ( & mut self , statement : & Statement ) {
166
+ println ! ( "statement:{statement:?}" ) ;
70
167
match & statement. kind {
71
168
StatementKind :: Assign ( asign_box) =>{
72
169
let ( place, rvalue) = ( asign_box. 0 , & asign_box. 1 ) ;
73
170
self . process_rvalue ( rvalue) ;
74
171
self . store ( place. local . into ( ) ) ;
75
172
//panic!("place:{place:?},rvalue:{rvalue:?}");
173
+ } ,
174
+ StatementKind :: StorageLive ( local) =>{
175
+ self . var_live ( ( * local) . into ( ) ) ;
176
+ }
177
+ StatementKind :: StorageDead ( local) =>{
178
+ self . var_dead ( ( * local) . into ( ) ) ;
76
179
}
77
180
_=>todo ! ( "Unhanded statement:{:?}" , statement. kind) ,
78
181
}
79
182
}
183
+ fn add_terminator ( & mut self , terminator : & Terminator ) {
184
+ match terminator. kind {
185
+ TerminatorKind :: Return =>{
186
+ if self . has_return ( ) {
187
+ self . load ( 0 ) ;
188
+ self . ops . push ( BaseIR :: Return ) ;
189
+ }
190
+ else {
191
+ todo ! ( "Can't yet return from a void method!" ) ;
192
+ }
193
+ }
194
+ _=>todo ! ( "Unknown terminator type {terminator:?}" ) ,
195
+ }
196
+ }
80
197
}
81
198
impl CustomCodegen {
82
199
fn add_fn < ' tcx > ( & mut self , instance : Instance < ' tcx > , tcx : TyCtxt < ' tcx > ) {
@@ -92,8 +209,12 @@ impl CustomCodegen{
92
209
for statement in & block_data. statements {
93
210
clr_method. add_statement ( statement) ;
94
211
}
95
-
212
+ match & block_data. terminator {
213
+ Some ( term) =>clr_method. add_terminator ( term) ,
214
+ None =>( ) ,
215
+ }
96
216
}
217
+ clr_method. opt ( ) ;
97
218
println ! ( "clr_method:{clr_method:?}" ) ;
98
219
println ! ( "instance:{instance:?}\n " ) ;
99
220
}
0 commit comments