@@ -3,18 +3,26 @@ mod codegen_state;
33mod error;
44mod function;
55mod instruction;
6- mod register_allocation;
76mod slot;
87
9- use iced_x86 :: { code_asm :: CodeAssembler , BlockEncoderOptions , DecoderOptions } ;
8+ use std :: collections :: HashMap ;
109
11- use crate :: { codegen:: x86_64:: codegen_state:: CodegenState , ir, value:: EncodedValue } ;
10+ use iced_x86:: {
11+ code_asm:: { r10, r11, r8, r9, rax, rcx, rdi, rdx, rsi, AsmRegister64 , CodeAssembler } ,
12+ BlockEncoderOptions , DecoderOptions , Register ,
13+ } ;
14+
15+ use crate :: {
16+ codegen:: x86_64:: codegen_state:: CodegenState ,
17+ ir:: { self , Slot } ,
18+ value:: EncodedValue ,
19+ } ;
1220
1321use self :: {
1422 abi:: { emit_function_epilogue, emit_function_prelude} ,
1523 instruction:: codegen_instruction,
1624} ;
17- pub use self :: { error:: CodegenError , function:: Function , register_allocation :: Register } ;
25+ pub use self :: { error:: CodegenError , function:: Function } ;
1826
1927use super :: CodegenResult ;
2028
@@ -72,16 +80,148 @@ fn codegen_block(
7280 assembler : & mut CodeAssembler ,
7381 block : ir:: Block ,
7482) -> CodegenResult < ( ) > {
83+ let register_map = allocate_registers ( & block) ;
84+
7585 let mut epilogue_label = assembler. create_label ( ) ;
7686
7787 emit_function_prelude ( assembler, & block) ?;
7888
7989 for instruction in block. instructions ( ) {
80- codegen_instruction ( state, assembler, instruction, & epilogue_label) ?;
90+ codegen_instruction (
91+ state,
92+ & register_map,
93+ assembler,
94+ instruction,
95+ & epilogue_label,
96+ ) ?;
8197 }
8298
8399 assembler. set_label ( & mut epilogue_label) ?;
84100 emit_function_epilogue ( assembler, block) ?;
85101
86102 Ok ( ( ) )
87103}
104+
105+ fn allocate_registers ( block : & ir:: Block ) -> HashMap < Slot , AsmRegister64 > {
106+ let mut free_registers = vec ! [ r8, r9, r10, r11] ;
107+
108+ let mut register_map = HashMap :: new ( ) ;
109+
110+ fn assign_register (
111+ register_map : & mut HashMap < Slot , AsmRegister64 > ,
112+ slot : & Slot ,
113+ register : AsmRegister64 ,
114+ ) {
115+ if !register_map. contains_key ( slot) {
116+ register_map. insert ( slot. clone ( ) , register) ;
117+ }
118+ }
119+
120+ fn choose_register (
121+ register_map : & mut HashMap < Slot , AsmRegister64 > ,
122+ free_registers : & mut Vec < AsmRegister64 > ,
123+ slot : & Slot ,
124+ ) -> AsmRegister64 {
125+ let register = free_registers. pop ( ) . unwrap ( ) ;
126+
127+ if let Some ( register) = register_map. get ( slot) {
128+ * register
129+ } else {
130+ assign_register ( register_map, slot, register) ;
131+ register
132+ }
133+ }
134+
135+ fn release_register (
136+ register_map : & mut HashMap < Slot , AsmRegister64 > ,
137+ free_registers : & mut Vec < AsmRegister64 > ,
138+ slot : & Slot ,
139+ ) {
140+ if let Some ( register) = register_map. get ( slot) {
141+ free_registers. push ( * register) ;
142+ }
143+ }
144+
145+ for instruction in block. instructions ( ) . iter ( ) . rev ( ) {
146+ match instruction {
147+ ir:: Instruction :: Label ( _) => { }
148+ ir:: Instruction :: Assign ( _, slot) => {
149+ choose_register ( & mut register_map, & mut free_registers, slot) ;
150+ }
151+ ir:: Instruction :: Opcode {
152+ destination,
153+ opcode,
154+ } => match opcode {
155+ ir:: Opcode :: Return => { }
156+ ir:: Opcode :: Jump ( condition, _) => match condition {
157+ ir:: JumpCondition :: Unconditional => { }
158+ ir:: JumpCondition :: Equal ( lhs, rhs)
159+ | ir:: JumpCondition :: NotEqual ( lhs, rhs)
160+ | ir:: JumpCondition :: Less ( lhs, rhs)
161+ | ir:: JumpCondition :: Greater ( lhs, rhs)
162+ | ir:: JumpCondition :: LessOrEqual ( lhs, rhs)
163+ | ir:: JumpCondition :: GreaterOrEqual ( lhs, rhs) => {
164+ choose_register ( & mut register_map, & mut free_registers, lhs) ;
165+ choose_register ( & mut register_map, & mut free_registers, rhs) ;
166+ }
167+ ir:: JumpCondition :: Zero ( slot) | ir:: JumpCondition :: NotZero ( slot) => {
168+ choose_register ( & mut register_map, & mut free_registers, slot) ;
169+ }
170+ } ,
171+
172+ ir:: Opcode :: SetReturnValue ( slot) => {
173+ assign_register ( & mut register_map, slot, rax) ;
174+ }
175+
176+ ir:: Opcode :: Literal ( _)
177+ | ir:: Opcode :: FunctionArgument ( _)
178+ | ir:: Opcode :: StackVariable ( _) => {
179+ release_register ( & mut register_map, & mut free_registers, destination) ;
180+ }
181+
182+ ir:: Opcode :: CallFunction ( _, parameters) => {
183+ for ( index, parameter) in parameters. iter ( ) . enumerate ( ) {
184+ let register = match index {
185+ 0 => rdi,
186+ 1 => rsi,
187+ 2 => rdx,
188+ 3 => rcx,
189+ 4 => r8,
190+ 5 => r9,
191+ _ => panic ! ( "too many arguments" ) ,
192+ } ;
193+ assign_register ( & mut register_map, parameter, register) ;
194+ }
195+ }
196+ ir:: Opcode :: BinaryOperator ( lhs, _, rhs) => {
197+ let register = register_map
198+ . get ( destination)
199+ . expect ( & format ! (
200+ "destination register not yet set for slot {destination}"
201+ ) )
202+ . clone ( ) ;
203+
204+ assign_register ( & mut register_map, destination, register) ;
205+ assign_register ( & mut register_map, lhs, register) ;
206+ choose_register ( & mut register_map, & mut free_registers, rhs) ;
207+ }
208+ ir:: Opcode :: Phi ( slots) => {
209+ if let Some ( register) = register_map. get ( destination) {
210+ let register = register. clone ( ) ;
211+ for slot in slots {
212+ assign_register ( & mut register_map, slot, register) ;
213+ }
214+ }
215+ }
216+ } ,
217+ } ;
218+ }
219+
220+ println ! ( "Register map:" ) ;
221+ for ( slot, register) in & register_map {
222+ println ! ( " {}: {:?}" , slot, Register :: from( * register) ) ;
223+ }
224+ println ! ( ) ;
225+
226+ register_map
227+ }
0 commit comments