11use super :: Emitter ;
2- use crate :: ir:: tac:: { BasicBlock , Entity , Instruction , TempId , Value } ;
2+ use crate :: ir:: tac:: { BasicBlock , Entity , Instruction , TempId , Type , Value } ;
33use std:: collections:: { HashMap , HashSet } ;
44use std:: fmt:: Write ;
55
@@ -11,7 +11,6 @@ pub struct CodeGenerator {
1111 current_stack_offset : HashMap < String , usize > , // (function label -> stack offset)
1212 current_function : Option < String > ,
1313}
14-
1514impl CodeGenerator {
1615 pub fn new ( ) -> Self {
1716 Self {
@@ -135,8 +134,20 @@ impl CodeGenerator {
135134 unreachable ! ( )
136135 }
137136 }
138- Instruction :: Not { .. } => {
139- self . text_section . push_str ( " TODO: not\n " ) ;
137+ Instruction :: Not { dest, src } => {
138+ if let Value :: Temp ( temp_id) = dest. value {
139+ self . allocate_temp_value ( temp_id, dest) ;
140+
141+ let src_asm = self . entity_to_asm ( src) ;
142+
143+ let _ = writeln ! ( self . text_section, " mov rax, {src_asm}" ) ;
144+ let _ = writeln ! ( self . text_section, " cmp rax, 0" ) ;
145+ let _ = writeln ! ( self . text_section, " sete al" ) ;
146+ let _ = writeln ! ( self . text_section, " movzx eax, al" ) ;
147+ let _ = writeln ! ( self . text_section, " push qword rax" ) ;
148+ } else {
149+ unreachable ! ( )
150+ }
140151 }
141152 Instruction :: Assign { dest, src } => match ( & dest. value , & src. ty ) {
142153 ( Value :: Variable ( name) , ty) => {
@@ -151,8 +162,23 @@ impl CodeGenerator {
151162 }
152163 _ => unreachable ! ( ) ,
153164 } ,
154- Instruction :: Conditional { .. } => {
155- self . text_section . push_str ( " TODO: conditional\n " ) ;
165+ Instruction :: Conditional {
166+ dest,
167+ condition,
168+ false_label,
169+ } => {
170+ if let Value :: Temp ( temp_id) = dest. value {
171+ self . allocate_temp_value ( temp_id, dest) ;
172+
173+ let condition_asm = self . entity_to_asm ( condition) ;
174+
175+ let _ = writeln ! ( self . text_section, " sub rsp, {}" , dest. ty. size_in_bytes( ) ) ;
176+ let _ = writeln ! ( self . text_section, " mov rax, {condition_asm}" ) ;
177+ let _ = writeln ! ( self . text_section, " cmp rax, 0" ) ;
178+ let _ = writeln ! ( self . text_section, " je {false_label}" ) ;
179+ } else {
180+ unreachable ! ( )
181+ }
156182 }
157183 Instruction :: Call { dest, callee, args } => {
158184 if let Value :: Temp ( temp_id) = dest. value {
@@ -176,17 +202,34 @@ impl CodeGenerator {
176202 let _ = writeln ! ( self . text_section, " jmp {label}" ) ;
177203 }
178204 Instruction :: Ret ( entity) => {
179- let entity_asm = self . entity_to_asm ( entity) ;
205+ let entity_asm = if matches ! ( entity. ty, Type :: Unit ) {
206+ "0" . to_string ( )
207+ } else {
208+ self . entity_to_asm ( entity)
209+ } ;
180210 let _ = writeln ! ( self . text_section, " mov rax, {entity_asm}" ) ;
181211 let _ = writeln ! ( self . text_section, " leave" ) ;
182212 let _ = writeln ! ( self . text_section, " ret" ) ;
183213 }
184214 Instruction :: Exit ( entity) => {
185215 self . text_section . push_str ( " mov rax, 60\n " ) ;
186- let entity_asm = self . entity_to_asm ( entity) ;
216+ let entity_asm = if matches ! ( entity. ty, Type :: Unit ) {
217+ "0" . to_string ( )
218+ } else {
219+ self . entity_to_asm ( entity)
220+ } ;
187221 let _ = writeln ! ( self . text_section, " mov rdi, {entity_asm}" ) ;
188222 let _ = writeln ! ( self . text_section, " syscall" ) ;
189223 }
224+ Instruction :: Label ( label) => {
225+ let _ = writeln ! ( self . text_section, "{label}:" ) ;
226+ }
227+ Instruction :: Move { dest, src } => {
228+ let dest_asm = self . entity_to_asm ( dest) ;
229+ let src_asm = self . entity_to_asm ( src) ;
230+
231+ let _ = writeln ! ( self . text_section, " mov {dest_asm}, {src_asm}" ) ;
232+ }
190233 }
191234 }
192235
@@ -224,7 +267,7 @@ impl CodeGenerator {
224267 }
225268 Value :: Unit => todo ! ( "unit" ) ,
226269 Value :: Int ( num) => num. to_string ( ) ,
227- Value :: Bool ( _ ) => todo ! ( "bool" ) ,
270+ Value :: Bool ( val ) => if * val { "1" } else { "0" } . to_string ( ) ,
228271 Value :: Variable ( name) => {
229272 if let Some ( var_name) = self . global_vars . get ( name) {
230273 return format ! ( "[{var_name}]" ) ;
0 commit comments