@@ -13,7 +13,7 @@ use crate::ir::{
1313
1414use super :: regalloc:: { HardwareRegister , Register , RegisterAllocator } ;
1515
16- type Registers < ' a > = HashMap < ( BlockIndex , NodeIndex ) , Box < dyn Register > > ;
16+ pub type Registers = HashMap < ( BlockIndex , NodeIndex ) , Box < dyn Register > > ;
1717
1818const TEMPLATE : & str = " .section .note.GNU-stack,\" \" ,@progbits
1919.global main
@@ -135,14 +135,15 @@ impl CodeGenerator {
135135 ir_graph : & IRGraph ,
136136 registers : & Registers ,
137137 ) -> String {
138- // Start and End Nodes should not emit code
138+ // End Node should not emit code
139139 if block. get_nodes ( ) . is_empty ( ) {
140140 return String :: new ( ) ;
141141 }
142142
143143 let mut code = String :: new ( ) ;
144144 let block_label = self . jump_label . get ( & block_index) . unwrap ( ) ;
145145 code. push_str ( & format ! ( "{}:\n " , block_label) ) ;
146+
146147 for ( node_index, node) in block. get_nodes ( ) . iter ( ) . enumerate ( ) {
147148 code. push_str ( & self . generate_for_node (
148149 node,
@@ -229,7 +230,7 @@ impl CodeGenerator {
229230 ) ) ;
230231 }
231232 Node :: Return ( data) => {
232- code. push_str ( & self . generate_return ( ir_graph , data, registers) ) ;
233+ code. push_str ( & self . generate_return ( block , block_index , data, registers) ) ;
233234 }
234235 Node :: ConstantInt ( data) => {
235236 code. push_str ( & self . generate_constant_int (
@@ -268,19 +269,33 @@ impl CodeGenerator {
268269 | Node :: NotEquals ( data)
269270 | Node :: Lower ( data)
270271 | Node :: Higher ( data) => {
271- code. push_str ( & self . generate_comparison ( block, data, ir_graph, registers) ) ;
272+ code. push_str ( & self . generate_comparison (
273+ block,
274+ block_index,
275+ data,
276+ ir_graph,
277+ registers,
278+ ) ) ;
272279 }
273- Node :: ConstantBool ( data) => code . push_str ( & self . generate_constant_bool ( data . value ( ) ) ) ,
274- Node :: Phi ( data ) => {
275- debug ! ( "Warning! Phi present: Aliasing {:? }" , data . operands ( ) ) ;
280+ Node :: BitwiseNegate ( data) => {
281+ let register = registers . get ( & ( block_index , data . input ( ) ) ) . unwrap ( ) ;
282+ code . push_str ( & format ! ( "not { }" , register . as_assembly ( ) ) ) ;
276283 }
284+ Node :: ConstantBool ( data) => code. push_str ( & self . generate_constant_bool ( data. value ( ) ) ) ,
285+ Node :: Phi ( data) => { }
277286 Node :: Jump => {
278287 trace ! (
279288 "Generating assembly for jump: {} with destination XXX" ,
280289 node,
281290 ) ;
282- let previous_block_index = jump_information. get ( & node_index) . unwrap ( ) ;
283- let label = self . jump_label . get ( previous_block_index) . unwrap ( ) ;
291+ let following_block_index = jump_information. get ( & node_index) . unwrap ( ) ;
292+ let label = self . jump_label . get ( following_block_index) . unwrap ( ) ;
293+ code. push_str ( & self . generate_phi_moves (
294+ block_index,
295+ * following_block_index,
296+ registers,
297+ ir_graph,
298+ ) ) ;
284299 code. push_str ( & format ! ( "jmp {}\n " , label) ) ;
285300 }
286301 Node :: ConditionalJump ( _) => { }
@@ -289,19 +304,37 @@ impl CodeGenerator {
289304 "Generating IR for true projection (including jump) with jump information {:?}" ,
290305 jump_information
291306 ) ;
292- let previous_block_index = jump_information. get ( & node_index) . unwrap ( ) ;
293- let conditional_jump_code =
294- self . generate_conditional_jump ( node_index, block, * previous_block_index) ;
307+ let following_block_index = jump_information. get ( & node_index) . unwrap ( ) ;
308+ let conditional_jump_code = self . generate_conditional_jump (
309+ node_index,
310+ block,
311+ block_index,
312+ * following_block_index,
313+ registers,
314+ ) ;
315+ code. push_str ( & self . generate_phi_moves (
316+ block_index,
317+ * following_block_index,
318+ registers,
319+ ir_graph,
320+ ) ) ;
295321 code. push_str ( & conditional_jump_code. expect ( "Expected jump code" ) ) ;
296322 }
297323 Node :: Projection ( data)
298324 if data. projection_info ( ) . eq ( & ProjectionInformation :: IfFalse ) =>
299325 {
300- let previous_block_index = jump_information. get ( & node_index) . unwrap ( ) ;
326+ let following_block_index = jump_information. get ( & node_index) . unwrap ( ) ;
301327 let jump_label = self
302328 . jump_label
303- . get ( previous_block_index )
329+ . get ( following_block_index )
304330 . expect ( "Expected jump label for false if" ) ;
331+ code. push_str ( & self . generate_phi_moves (
332+ block_index,
333+ * following_block_index,
334+ registers,
335+ ir_graph,
336+ ) ) ;
337+
305338 code. push_str ( & format ! ( "jmp {}\n " , jump_label) ) ;
306339 }
307340 Node :: Projection ( _) => return code,
@@ -311,6 +344,42 @@ impl CodeGenerator {
311344 code
312345 }
313346
347+ pub fn generate_phi_moves (
348+ & self ,
349+ current_block_index : BlockIndex ,
350+ following_block_index : BlockIndex ,
351+ registers : & Registers ,
352+ ir_graph : & IRGraph ,
353+ ) -> String {
354+ let mut code = String :: new ( ) ;
355+ let following_block = ir_graph. get_block ( following_block_index) ;
356+ for phi_index in following_block. phis ( ) {
357+ let phi = following_block. get_node ( * phi_index) ;
358+ if let Node :: Phi ( data) = phi {
359+ let destination_register =
360+ registers. get ( & ( following_block_index, * phi_index) ) . unwrap ( ) ;
361+ for operand in data. operands ( ) {
362+ if operand. 0 != current_block_index {
363+ continue ;
364+ }
365+ let source_register = registers. get ( & operand) . unwrap ( ) ;
366+ code. push_str ( & format ! (
367+ "movq {}, {}\n " ,
368+ source_register. as_assembly( ) ,
369+ destination_register. as_assembly( )
370+ ) ) ;
371+ break ;
372+ }
373+ }
374+ }
375+ trace ! (
376+ "Generated the following phi moves for block {}: {}" ,
377+ current_block_index,
378+ code
379+ ) ;
380+ code
381+ }
382+
314383 pub fn generate_constant_bool ( & self , value : bool ) -> String {
315384 let mut code = String :: new ( ) ;
316385 if value {
@@ -325,7 +394,9 @@ impl CodeGenerator {
325394 & self ,
326395 projection_index : usize ,
327396 current_block : & Block ,
397+ current_block_index : BlockIndex ,
328398 previous_block : usize ,
399+ registers : & Registers ,
329400 ) -> Option < String > {
330401 let mut code = String :: new ( ) ;
331402 let true_label = self . jump_label . get ( & previous_block) . unwrap ( ) ;
@@ -343,6 +414,13 @@ impl CodeGenerator {
343414 Node :: HigherEquals ( _) => "jae" ,
344415 Node :: Higher ( _) => "ja" ,
345416 Node :: ConstantBool ( _) => "je" ,
417+ Node :: BitwiseNegate ( _) => "jne" ,
418+ Node :: Phi ( _) | Node :: ConstantInt ( _) => {
419+ let register = registers. get ( & ( current_block_index, comparision) ) . unwrap ( ) ;
420+ code. push_str ( & format ! ( "testq $0x1, {}\n " , register. as_assembly( ) ) ) ;
421+ code. push_str ( & format ! ( "jnz {}\n " , true_label) ) ;
422+ return Some ( code) ;
423+ }
346424 node => panic ! ( "Invalid operation before conditional jump: {}" , node) ,
347425 } ;
348426 code. push_str ( & format ! ( "{} {}\n " , op_code, true_label) ) ;
@@ -352,15 +430,22 @@ impl CodeGenerator {
352430 pub fn generate_comparison (
353431 & self ,
354432 block : & Block ,
433+ block_index : BlockIndex ,
355434 operation_data : & BinaryOperationData ,
356435 ir_graph : & IRGraph ,
357436 registers : & Registers ,
358437 ) -> String {
359438 let left_value = registers
360- . get ( & predecessor_skip_projection ( ir_graph, operation_data. lhs ( ) ) )
439+ . get ( & (
440+ block_index,
441+ predecessor_skip_projection ( block, operation_data. lhs ( ) ) ,
442+ ) )
361443 . unwrap ( ) ;
362444 let right_value = registers
363- . get ( & predecessor_skip_projection ( ir_graph, operation_data. rhs ( ) ) )
445+ . get ( & (
446+ block_index,
447+ predecessor_skip_projection ( block, operation_data. rhs ( ) ) ,
448+ ) )
364449 . unwrap ( ) ;
365450 let mut code = String :: new ( ) ;
366451 if !left_value. hardware_register ( ) && !right_value. hardware_register ( ) {
@@ -393,10 +478,10 @@ impl CodeGenerator {
393478 op_code : & str ,
394479 ) -> String {
395480 let left_value = registers
396- . get ( & predecessor_skip_projection ( ir_graph , data. lhs ( ) ) )
481+ . get ( & ( block_index , predecessor_skip_projection ( block , data. lhs ( ) ) ) )
397482 . unwrap ( ) ;
398483 let right_value = registers
399- . get ( & predecessor_skip_projection ( ir_graph , data. rhs ( ) ) )
484+ . get ( & ( block_index , predecessor_skip_projection ( block , data. rhs ( ) ) ) )
400485 . unwrap ( ) ;
401486
402487 let destination_register = registers. get ( & ( block_index, node_index) ) . unwrap ( ) ;
@@ -444,10 +529,10 @@ impl CodeGenerator {
444529 mode : & str ,
445530 ) -> String {
446531 let left_value = registers
447- . get ( & predecessor_skip_projection ( ir_graph , data. lhs ( ) ) )
532+ . get ( & ( block_index , predecessor_skip_projection ( block , data. lhs ( ) ) ) )
448533 . unwrap ( ) ;
449534 let right_value = registers
450- . get ( & predecessor_skip_projection ( ir_graph , data. rhs ( ) ) )
535+ . get ( & ( block_index , predecessor_skip_projection ( block , data. rhs ( ) ) ) )
451536 . unwrap ( ) ;
452537 let destination_register = registers. get ( & ( block_index, node_index) ) . unwrap ( ) ;
453538 let mut code = String :: new ( ) ;
@@ -491,8 +576,8 @@ impl CodeGenerator {
491576 op_code : & str ,
492577 ) -> String {
493578 let mut code = String :: new ( ) ;
494- let left_value = registers. get ( & data. lhs ( ) ) . unwrap ( ) ;
495- let right_value = registers. get ( & data. rhs ( ) ) . unwrap ( ) ;
579+ let left_value = registers. get ( & ( block_index , data. lhs ( ) ) ) . unwrap ( ) ;
580+ let right_value = registers. get ( & ( block_index , data. rhs ( ) ) ) . unwrap ( ) ;
496581 code. push_str ( & format ! (
497582 "movq {}, {}\n " ,
498583 right_value. as_assembly( ) ,
@@ -515,21 +600,27 @@ impl CodeGenerator {
515600
516601 pub fn generate_return (
517602 & self ,
518- ir_graph : & IRGraph ,
603+ block : & Block ,
604+ block_index : BlockIndex ,
519605 data : & ReturnData ,
520606 registers : & Registers ,
521607 ) -> String {
522608 debug ! ( "Generating assembly for return" ) ;
523- let return_node = predecessor_skip_projection ( ir_graph , data. input ( ) ) ;
609+ let return_node = predecessor_skip_projection ( block , data. input ( ) ) ;
524610 debug ! (
525611 "Determined node {} that contains the return result" ,
526- ir_graph . get_node( return_node)
612+ block . get_node( return_node)
527613 ) ;
528614 debug ! ( "Registers: {:?}" , registers) ;
529615
530616 let mut code = String :: new ( ) ;
531617 code. push_str ( "mov " ) ;
532- code. push_str ( & registers. get ( & return_node) . unwrap ( ) . as_assembly ( ) ) ;
618+ code. push_str (
619+ & registers
620+ . get ( & ( block_index, return_node) )
621+ . unwrap ( )
622+ . as_assembly ( ) ,
623+ ) ;
533624 code. push_str ( ", %rax" ) ;
534625 code. push ( '\n' ) ;
535626
@@ -558,11 +649,8 @@ impl CodeGenerator {
558649 }
559650}
560651
561- fn predecessor_skip_projection (
562- ir_graph : & IRGraph ,
563- data : ( BlockIndex , NodeIndex ) ,
564- ) -> ( BlockIndex , NodeIndex ) {
565- let predecessor = ir_graph. get_node ( data) ;
652+ fn predecessor_skip_projection ( block : & Block , data : NodeIndex ) -> NodeIndex {
653+ let predecessor = block. get_node ( data) ;
566654 if let Node :: Projection ( data) = predecessor {
567655 data. input ( )
568656 } else {
0 commit comments