@@ -1173,8 +1173,7 @@ impl CraneliftBackend {
11731173 BinaryOp :: FMul => builder. ins ( ) . fmul ( lhs, rhs) ,
11741174 BinaryOp :: FDiv => builder. ins ( ) . fdiv ( lhs, rhs) ,
11751175 BinaryOp :: FRem => {
1176- // TODO: Re-implement fmod import in multi-block context
1177- builder. ins ( ) . f64const ( 0.0 )
1176+ Self :: call_libm_fmod ( & mut self . module , & mut builder, lhs, rhs) ?
11781177 }
11791178 // Float comparisons also always return bool (i8)
11801179 BinaryOp :: FEq
@@ -4148,27 +4147,49 @@ impl CraneliftBackend {
41484147 }
41494148 }
41504149
4151- /// Call libm fmod function for float remainder operation
4152- fn call_libm_fmod (
4153- & mut self ,
4150+ /// Call libm fmod function for float remainder operation.
4151+ /// Supports scalar f32 (fmodf) and f64 (fmod); vector frem is rejected.
4152+ fn call_libm_fmod < M : Module > (
4153+ module : & mut M ,
41544154 builder : & mut FunctionBuilder ,
41554155 lhs : Value ,
41564156 rhs : Value ,
41574157 ) -> CompilerResult < Value > {
4158- // Declare fmod signature: double fmod(double x, double y)
4159- let mut sig = self . module . make_signature ( ) ;
4160- sig. params . push ( AbiParam :: new ( types:: F64 ) ) ;
4161- sig. params . push ( AbiParam :: new ( types:: F64 ) ) ;
4162- sig. returns . push ( AbiParam :: new ( types:: F64 ) ) ;
4158+ let lhs_ty = builder. func . dfg . value_type ( lhs) ;
4159+ let rhs_ty = builder. func . dfg . value_type ( rhs) ;
4160+ if lhs_ty != rhs_ty {
4161+ return Err ( CompilerError :: CodeGen ( format ! (
4162+ "frem operand type mismatch: lhs={:?}, rhs={:?}" ,
4163+ lhs_ty, rhs_ty
4164+ ) ) ) ;
4165+ }
41634166
4164- // Declare fmod as an external function
4165- let fmod_id = self
4166- . module
4167- . declare_function ( "fmod" , Linkage :: Import , & sig)
4168- . map_err ( |e| CompilerError :: Backend ( format ! ( "Failed to declare fmod: {}" , e) ) ) ?;
4167+ let ( symbol_name, param_ty) = match lhs_ty {
4168+ types:: F64 => ( "fmod" , types:: F64 ) ,
4169+ types:: F32 => ( "fmodf" , types:: F32 ) ,
4170+ other => {
4171+ return Err ( CompilerError :: CodeGen ( format ! (
4172+ "frem currently supports scalar f32/f64 only, got {:?}" ,
4173+ other
4174+ ) ) ) ;
4175+ }
4176+ } ;
4177+
4178+ // Declare fmod signature for the selected scalar float width.
4179+ let mut sig = module. make_signature ( ) ;
4180+ sig. params . push ( AbiParam :: new ( param_ty) ) ;
4181+ sig. params . push ( AbiParam :: new ( param_ty) ) ;
4182+ sig. returns . push ( AbiParam :: new ( param_ty) ) ;
4183+
4184+ // Declare fmod/fmodf as an external function.
4185+ let fmod_id = module
4186+ . declare_function ( symbol_name, Linkage :: Import , & sig)
4187+ . map_err ( |e| {
4188+ CompilerError :: Backend ( format ! ( "Failed to declare {}: {}" , symbol_name, e) )
4189+ } ) ?;
41694190
41704191 // Import the function into the current function
4171- let fmod_func = self . module . declare_func_in_func ( fmod_id, builder. func ) ;
4192+ let fmod_func = module. declare_func_in_func ( fmod_id, builder. func ) ;
41724193
41734194 // Call fmod
41744195 let call = builder. ins ( ) . call ( fmod_func, & [ lhs, rhs] ) ;
@@ -4467,7 +4488,7 @@ impl CraneliftBackend {
44674488 BinaryOp :: FMul => builder. ins ( ) . fmul ( lhs, rhs) ,
44684489 BinaryOp :: FDiv => builder. ins ( ) . fdiv ( lhs, rhs) ,
44694490 // Float remainder requires libm fmod function call
4470- BinaryOp :: FRem => self . call_libm_fmod ( builder, lhs, rhs) ?,
4491+ BinaryOp :: FRem => Self :: call_libm_fmod ( & mut self . module , builder, lhs, rhs) ?,
44714492
44724493 // Bitwise
44734494 BinaryOp :: And => builder. ins ( ) . band ( lhs, rhs) ,
@@ -4618,7 +4639,7 @@ impl CraneliftBackend {
46184639 BinaryOp :: FDiv => builder. ins ( ) . fdiv ( lhs, rhs) ,
46194640 BinaryOp :: FRem => {
46204641 // Cranelift doesn't have frem, use libm fmod
4621- self . call_libm_fmod ( builder, lhs, rhs) ?
4642+ Self :: call_libm_fmod ( & mut self . module , builder, lhs, rhs) ?
46224643 }
46234644 // Floating point comparisons - always return i8 (bool), never uextend
46244645 BinaryOp :: FEq => builder. ins ( ) . fcmp ( FloatCC :: Equal , lhs, rhs) ,
@@ -6079,7 +6100,7 @@ impl CraneliftBackend {
60796100 BinaryOp :: FSub => builder. ins ( ) . fsub ( lhs, rhs) ,
60806101 BinaryOp :: FMul => builder. ins ( ) . fmul ( lhs, rhs) ,
60816102 BinaryOp :: FDiv => builder. ins ( ) . fdiv ( lhs, rhs) ,
6082- BinaryOp :: FRem => self . call_libm_fmod ( builder, lhs, rhs) ?,
6103+ BinaryOp :: FRem => Self :: call_libm_fmod ( & mut self . module , builder, lhs, rhs) ?,
60836104 // Float comparisons - also always return bool (i8)
60846105 BinaryOp :: FEq
60856106 | BinaryOp :: FNe
0 commit comments