floats iter 4.1: codegen primitive registration + Float literal hex-double lowering

This commit is contained in:
2026-05-10 15:54:20 +02:00
parent 0c514e034b
commit ac5e17e541
2 changed files with 45 additions and 2 deletions
+43 -2
View File
@@ -925,7 +925,7 @@ impl<'a> Emitter<'a> {
let g = self.intern_string("str", value);
("ptr".to_string(), format!("@{g}"))
}
Literal::Float { .. } => unimplemented!("Floats milestone iter 4: codegen"),
Literal::Float { bits } => ("double".to_string(), format!("0x{:016X}", bits)),
};
if val_ty != lty {
return Err(CodegenError::Internal(format!(
@@ -1225,7 +1225,7 @@ impl<'a> Emitter<'a> {
(format!("@{g}"), "ptr".into())
}
Literal::Unit => ("0".into(), "i8".into()),
Literal::Float { .. } => unimplemented!("Floats milestone iter 4: codegen"),
Literal::Float { bits } => (format!("0x{:016X}", bits), "double".into()),
}),
Term::Var { name } => {
// Iter 16d: `__unreachable__` is a polymorphic bottom
@@ -2877,4 +2877,45 @@ mod tests {
"gc IR should not declare/define any per-type drop fn. IR was:\n{ir_gc}"
);
}
/// Floats iter 4.1 RED: a `Literal::Float { bits: 0x3ff8_0000_0000_0000 }`
/// (= `1.5_f64`) lowers in a `Const` definition as an LLVM hex-float
/// `double` SSA constant. The exact IR snippet pinned: `@ail_t_k =
/// constant double 0x3FF8000000000000`.
#[test]
fn lowers_float_const_to_hex_double() {
use ailang_core::ast::*;
let m = Module {
schema: ailang_core::SCHEMA.to_string(),
name: "t".into(),
imports: vec![],
defs: vec![
Def::Const(ConstDef {
name: "k".into(),
ty: Type::float(),
value: Term::Lit { lit: Literal::Float { bits: 0x3ff8_0000_0000_0000u64 } },
doc: None,
}),
Def::Fn(FnDef {
name: "main".into(),
ty: Type::Fn {
params: vec![],
ret: Box::new(Type::unit()),
effects: vec![],
param_modes: vec![],
ret_mode: ParamMode::Implicit,
},
params: vec![],
body: Term::Lit { lit: Literal::Unit },
suppress: vec![],
doc: None,
}),
],
};
let ir = emit_ir(&m).unwrap();
assert!(
ir.contains("@ail_t_k = constant double 0x3FF8000000000000"),
"ir missing the Float literal lowering: {ir}"
);
}
}
+2
View File
@@ -18,6 +18,7 @@ pub(crate) fn llvm_type(t: &Type) -> Result<String> {
"Bool" => Ok("i1".into()),
"Unit" => Ok("i8".into()),
"Str" => Ok("ptr".into()),
"Float" => Ok("double".into()),
// All other type names are treated as ADT (boxed).
// If the typechecker didn't reject this earlier, it's
// intentional — otherwise `ptr` would mask a wrong value.
@@ -207,6 +208,7 @@ pub(crate) fn type_descriptor(t: &Type) -> String {
"Bool" => "B".into(),
"Unit" => "U".into(),
"Str" => "S".into(),
"Float" => "Fl".into(),
other => format!("F{other}"),
};
if args.is_empty() {