adding floating point conversions
This commit is contained in:
parent
80558ea7e6
commit
24b9f9e78b
|
@ -277,6 +277,9 @@ main := fn(): uint {
|
||||||
same_type_as_byte := @as(@TypeOf(byte), 30)
|
same_type_as_byte := @as(@TypeOf(byte), 30)
|
||||||
wide_uint := @as(u32, 40)
|
wide_uint := @as(u32, 40)
|
||||||
truncated_uint := @as(u8, @intcast(wide_uint))
|
truncated_uint := @as(u8, @intcast(wide_uint))
|
||||||
|
widened_float := @as(f64, @floatcast(1.))
|
||||||
|
int_from_float := @as(int, @fti(1.))
|
||||||
|
float_from_int := @as(f64, @itf(@as(int, 1)))
|
||||||
size_of_Type_in_bytes := @sizeof(foo.Type)
|
size_of_Type_in_bytes := @sizeof(foo.Type)
|
||||||
align_of_Type_in_bytes := @alignof(foo.Type)
|
align_of_Type_in_bytes := @alignof(foo.Type)
|
||||||
hardcoded_pointer := @as(^u8, @bitcast(10))
|
hardcoded_pointer := @as(^u8, @bitcast(10))
|
||||||
|
|
|
@ -257,9 +257,16 @@ impl TokenKind {
|
||||||
&& self.precedence() != Self::Eof.precedence()
|
&& self.precedence() != Self::Eof.precedence()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn apply_unop(&self, value: i64) -> i64 {
|
pub fn apply_unop(&self, value: i64, float: bool) -> i64 {
|
||||||
match self {
|
match self {
|
||||||
|
Self::Sub if float => (-f64::from_bits(value as _)).to_bits() as _,
|
||||||
Self::Sub => value.wrapping_neg(),
|
Self::Sub => value.wrapping_neg(),
|
||||||
|
Self::Float if float => value,
|
||||||
|
Self::Float => (value as f64).to_bits() as _,
|
||||||
|
Self::Number => {
|
||||||
|
debug_assert!(float);
|
||||||
|
f64::from_bits(value as _).to_bits() as _
|
||||||
|
}
|
||||||
s => todo!("{s}"),
|
s => todo!("{s}"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -792,10 +792,14 @@ impl Nodes {
|
||||||
let &[ctrl, oper] = self[target].inputs.as_slice() else { unreachable!() };
|
let &[ctrl, oper] = self[target].inputs.as_slice() else { unreachable!() };
|
||||||
let ty = self[target].ty;
|
let ty = self[target].ty;
|
||||||
|
|
||||||
|
let is_float = self[oper].ty.is_float();
|
||||||
|
|
||||||
if let K::CInt { value } = self[oper].kind {
|
if let K::CInt { value } = self[oper].kind {
|
||||||
return Some(
|
return Some(self.new_node(
|
||||||
self.new_node(ty, K::CInt { value: op.apply_unop(value) }, [ctrl]),
|
ty,
|
||||||
);
|
K::CInt { value: op.apply_unop(value, is_float) },
|
||||||
|
[ctrl],
|
||||||
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
K::If => {
|
K::If => {
|
||||||
|
@ -2649,6 +2653,79 @@ impl<'a> Codegen<'a> {
|
||||||
Some(val.ty(ty))
|
Some(val.ty(ty))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Expr::Directive { pos, name: "floatcast", args: [expr] } => {
|
||||||
|
let val = self.expr(expr)?;
|
||||||
|
|
||||||
|
if !val.ty.is_float() {
|
||||||
|
self.report(
|
||||||
|
expr.pos(),
|
||||||
|
fa!(
|
||||||
|
"only floats can be truncated ('{}' is not a float)",
|
||||||
|
self.ty_display(val.ty)
|
||||||
|
),
|
||||||
|
);
|
||||||
|
return Value::NEVER;
|
||||||
|
}
|
||||||
|
|
||||||
|
inference!(ty, ctx, self, pos, "float", "@as(<floaty>, @floatcast(<expr>))");
|
||||||
|
|
||||||
|
if !ty.is_float() {
|
||||||
|
self.report(
|
||||||
|
expr.pos(),
|
||||||
|
fa!(
|
||||||
|
"floatcast is inferred to output '{}', which is not a float",
|
||||||
|
self.ty_display(ty)
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.tys.size_of(val.ty) < self.tys.size_of(ty) {
|
||||||
|
Some(
|
||||||
|
self.ci
|
||||||
|
.nodes
|
||||||
|
.new_node_lit(ty, Kind::UnOp { op: TokenKind::Float }, [VOID, val.id]),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
Some(val.ty(ty))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Expr::Directive { name: "fti", args: [expr], .. } => {
|
||||||
|
let val = self.expr(expr)?;
|
||||||
|
|
||||||
|
let ret_ty = match val.ty {
|
||||||
|
ty::Id::F64 => ty::Id::INT,
|
||||||
|
ty::Id::F32 => ty::Id::I32,
|
||||||
|
_ => {
|
||||||
|
self.report(
|
||||||
|
expr.pos(),
|
||||||
|
fa!("expected float ('{}' is not a float)", self.ty_display(val.ty)),
|
||||||
|
);
|
||||||
|
return Value::NEVER;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Some(
|
||||||
|
self.ci
|
||||||
|
.nodes
|
||||||
|
.new_node_lit(ret_ty, Kind::UnOp { op: TokenKind::Number }, [VOID, val.id]),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Expr::Directive { name: "itf", args: [expr], .. } => {
|
||||||
|
let mut val = self.expr(expr)?;
|
||||||
|
|
||||||
|
let (ret_ty, expected) = match val.ty.simple_size().unwrap() {
|
||||||
|
8 => (ty::Id::F64, ty::Id::INT),
|
||||||
|
_ => (ty::Id::F32, ty::Id::I32),
|
||||||
|
};
|
||||||
|
|
||||||
|
self.assert_ty(expr.pos(), &mut val, expected, "converted integer");
|
||||||
|
|
||||||
|
Some(
|
||||||
|
self.ci
|
||||||
|
.nodes
|
||||||
|
.new_node_lit(ret_ty, Kind::UnOp { op: TokenKind::Float }, [VOID, val.id]),
|
||||||
|
)
|
||||||
|
}
|
||||||
Expr::Directive { name: "as", args: [ty, expr], .. } => {
|
Expr::Directive { name: "as", args: [ty, expr], .. } => {
|
||||||
let ty = self.ty(ty);
|
let ty = self.ty(ty);
|
||||||
let ctx = Ctx::default().with_ty(ty);
|
let ctx = Ctx::default().with_ty(ty);
|
||||||
|
|
|
@ -323,7 +323,9 @@ impl ItemCtx {
|
||||||
_ => instrs::li64(atr(allocs[0]), value as _),
|
_ => instrs::li64(atr(allocs[0]), value as _),
|
||||||
}),
|
}),
|
||||||
Kind::UnOp { op } => {
|
Kind::UnOp { op } => {
|
||||||
let op = op.unop().expect("TODO: unary operator not supported");
|
let op = op
|
||||||
|
.unop(node.ty, fuc.nodes[node.inputs[1]].ty)
|
||||||
|
.expect("TODO: unary operator not supported");
|
||||||
let &[dst, oper] = allocs else { unreachable!() };
|
let &[dst, oper] = allocs else { unreachable!() };
|
||||||
self.emit(op(atr(dst), atr(oper)));
|
self.emit(op(atr(dst), atr(oper)));
|
||||||
}
|
}
|
||||||
|
@ -1332,9 +1334,19 @@ impl TokenKind {
|
||||||
Some(ops[size.ilog2() as usize])
|
Some(ops[size.ilog2() as usize])
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn unop(&self) -> Option<fn(u8, u8) -> EncodedInstr> {
|
pub fn unop(&self, dst: ty::Id, src: ty::Id) -> Option<fn(u8, u8) -> EncodedInstr> {
|
||||||
|
let src_idx = src.simple_size().unwrap().ilog2() as usize - 2;
|
||||||
Some(match self {
|
Some(match self {
|
||||||
Self::Sub => instrs::neg,
|
Self::Sub => instrs::neg,
|
||||||
|
Self::Float if dst.is_float() && src.is_integer() => {
|
||||||
|
[instrs::itf32, instrs::itf64][src_idx]
|
||||||
|
}
|
||||||
|
Self::Number if src.is_float() && dst.is_integer() => {
|
||||||
|
[|a, b| instrs::fti32(a, b, 1), |a, b| instrs::fti64(a, b, 1)][src_idx]
|
||||||
|
}
|
||||||
|
Self::Float if dst.is_float() && src.is_float() => {
|
||||||
|
[instrs::fc32t64, |a, b| instrs::fc64t32(a, b, 1)][src_idx]
|
||||||
|
}
|
||||||
_ => return None,
|
_ => return None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue