66use crate :: backend:: Backend ;
77use crate :: ir:: * ;
88
9+ const INDENT : & str = " " ;
10+
11+ /// Format a function call result assignment.
12+ fn emit_call_result ( dest : Option < VarId > , call_expr : & str ) -> String {
13+ match dest {
14+ Some ( d) => format ! ( "{}{} = {};" , INDENT , d, call_expr) ,
15+ None => format ! ( "{}{};" , INDENT , call_expr) ,
16+ }
17+ }
18+
19+ /// Emit a f32 const, handling NaN and infinity special values.
20+ fn emit_f32_const ( dest : VarId , value : f32 ) -> String {
21+ if value. is_nan ( ) {
22+ format ! ( "{}{dest} = f32::NAN;" , INDENT )
23+ } else if value. is_infinite ( ) {
24+ if value. is_sign_positive ( ) {
25+ format ! ( "{}{dest} = f32::INFINITY;" , INDENT )
26+ } else {
27+ format ! ( "{}{dest} = f32::NEG_INFINITY;" , INDENT )
28+ }
29+ } else {
30+ format ! ( "{}{dest} = {value}f32;" , INDENT )
31+ }
32+ }
33+
34+ /// Emit a f64 const, handling NaN and infinity special values.
35+ fn emit_f64_const ( dest : VarId , value : f64 ) -> String {
36+ if value. is_nan ( ) {
37+ format ! ( "{}{dest} = f64::NAN;" , INDENT )
38+ } else if value. is_infinite ( ) {
39+ if value. is_sign_positive ( ) {
40+ format ! ( "{}{dest} = f64::INFINITY;" , INDENT )
41+ } else {
42+ format ! ( "{}{dest} = f64::NEG_INFINITY;" , INDENT )
43+ }
44+ } else {
45+ format ! ( "{}{dest} = {value}f64;" , INDENT )
46+ }
47+ }
48+
949/// Safe code generation backend.
1050pub struct SafeBackend ;
1151
@@ -26,33 +66,8 @@ impl Backend for SafeBackend {
2666 match value {
2767 IrValue :: I32 ( v) => format ! ( " {dest} = {v}i32;" ) ,
2868 IrValue :: I64 ( v) => format ! ( " {dest} = {v}i64;" ) ,
29- IrValue :: F32 ( v) => {
30- // Handle special float values
31- if v. is_nan ( ) {
32- format ! ( " {dest} = f32::NAN;" )
33- } else if v. is_infinite ( ) {
34- if v. is_sign_positive ( ) {
35- format ! ( " {dest} = f32::INFINITY;" )
36- } else {
37- format ! ( " {dest} = f32::NEG_INFINITY;" )
38- }
39- } else {
40- format ! ( " {dest} = {v}f32;" )
41- }
42- }
43- IrValue :: F64 ( v) => {
44- if v. is_nan ( ) {
45- format ! ( " {dest} = f64::NAN;" )
46- } else if v. is_infinite ( ) {
47- if v. is_sign_positive ( ) {
48- format ! ( " {dest} = f64::INFINITY;" )
49- } else {
50- format ! ( " {dest} = f64::NEG_INFINITY;" )
51- }
52- } else {
53- format ! ( " {dest} = {v}f64;" )
54- }
55- }
69+ IrValue :: F32 ( v) => emit_f32_const ( dest, * v) ,
70+ IrValue :: F64 ( v) => emit_f64_const ( dest, * v) ,
5671 }
5772 }
5873
@@ -490,10 +505,7 @@ impl Backend for SafeBackend {
490505 call_args. push ( "table" . to_string ( ) ) ;
491506 }
492507 let call_expr = format ! ( "func_{}({})?" , func_idx, call_args. join( ", " ) ) ;
493- match dest {
494- Some ( d) => format ! ( " {} = {};" , d, call_expr) ,
495- None => format ! ( " {};" , call_expr) ,
496- }
508+ emit_call_result ( dest, & call_expr)
497509 }
498510
499511 fn emit_call_import (
@@ -507,10 +519,7 @@ impl Backend for SafeBackend {
507519 // Note: module_name is ignored for now (Milestone 3 will use it for trait names)
508520 let args_str: Vec < String > = args. iter ( ) . map ( |a| a. to_string ( ) ) . collect ( ) ;
509521 let call_expr = format ! ( "host.{}({})?" , func_name, args_str. join( ", " ) ) ;
510- match dest {
511- Some ( d) => format ! ( " {} = {};" , d, call_expr) ,
512- None => format ! ( " {};" , call_expr) ,
513- }
522+ emit_call_result ( dest, & call_expr)
514523 }
515524
516525 fn emit_global_get ( & self , dest : VarId , index : usize , is_mutable : bool ) -> String {
0 commit comments