something is wrong, but typechecking
This commit is contained in:
parent
70644ede3e
commit
e9335d3fc5
|
@ -241,7 +241,7 @@ impl IntegralType {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Eq, Hash)]
|
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
|
||||||
pub enum Type {
|
pub enum Type {
|
||||||
Any,
|
Any,
|
||||||
Void,
|
Void,
|
||||||
|
@ -289,8 +289,8 @@ impl core::fmt::Display for Type {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PartialEq for Type {
|
impl Type {
|
||||||
fn eq(&self, other: &Self) -> bool {
|
pub fn is_compatible_with(&self, other: &Self) -> bool {
|
||||||
match (self, other) {
|
match (self, other) {
|
||||||
(Self::ComptimeNumber, Self::Integer(_)) => true,
|
(Self::ComptimeNumber, Self::Integer(_)) => true,
|
||||||
(Self::Integer(_), Self::ComptimeNumber) => true,
|
(Self::Integer(_), Self::ComptimeNumber) => true,
|
||||||
|
@ -319,9 +319,6 @@ impl PartialEq for Type {
|
||||||
_ => core::mem::discriminant(self) == core::mem::discriminant(other),
|
_ => core::mem::discriminant(self) == core::mem::discriminant(other),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl Type {
|
|
||||||
pub fn as_primitive_type(&self) -> Option<PrimitiveType> {
|
pub fn as_primitive_type(&self) -> Option<PrimitiveType> {
|
||||||
match self {
|
match self {
|
||||||
Type::Void => Some(PrimitiveType::Void),
|
Type::Void => Some(PrimitiveType::Void),
|
||||||
|
|
|
@ -2009,6 +2009,20 @@ impl From<(u128, IntegralType)> for ComptimeNumber {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ComptimeNumber {
|
impl ComptimeNumber {
|
||||||
|
pub fn bit_count(&self) -> u16 {
|
||||||
|
match self {
|
||||||
|
ComptimeNumber::Integral(i) => match i {
|
||||||
|
ComptimeInt::Native { ty, .. } => ty.bits,
|
||||||
|
ComptimeInt::BigInt { ty, .. } => ty.bits,
|
||||||
|
ComptimeInt::Comptime(i) => i.bits() as u16,
|
||||||
|
},
|
||||||
|
ComptimeNumber::Bool(_) => 1,
|
||||||
|
ComptimeNumber::Floating(f) => match f {
|
||||||
|
ComptimeFloat::Binary32(_) => 32,
|
||||||
|
ComptimeFloat::Binary64(_) => 64,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
pub fn add(self, other: Self) -> Result<Self> {
|
pub fn add(self, other: Self) -> Result<Self> {
|
||||||
match (self, other) {
|
match (self, other) {
|
||||||
(ComptimeNumber::Integral(a), ComptimeNumber::Integral(b)) => {
|
(ComptimeNumber::Integral(a), ComptimeNumber::Integral(b)) => {
|
||||||
|
|
|
@ -1305,16 +1305,12 @@ pub mod liveness {
|
||||||
interval.map(|max| (node, max))
|
interval.map(|max| (node, max))
|
||||||
});
|
});
|
||||||
|
|
||||||
eprintln!("intervals: [");
|
|
||||||
|
|
||||||
let mut edges = HashSet::<(u32, u32)>::new();
|
let mut edges = HashSet::<(u32, u32)>::new();
|
||||||
for (from, to) in intervals {
|
for (from, to) in intervals {
|
||||||
eprint!("({from}..{to}), ");
|
|
||||||
for &(other, _) in references.range(from.exclusive_start()..to.inclusive_end()) {
|
for &(other, _) in references.range(from.exclusive_start()..to.inclusive_end()) {
|
||||||
edges.insert((from.0, other.0));
|
edges.insert((from.0, other.0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
eprintln!("]");
|
|
||||||
|
|
||||||
let inference_graph = petgraph::graph::UnGraph::<(), ()>::from_edges(edges.into_iter());
|
let inference_graph = petgraph::graph::UnGraph::<(), ()>::from_edges(edges.into_iter());
|
||||||
|
|
||||||
|
|
172
src/parser.rs
172
src/parser.rs
|
@ -12,6 +12,7 @@ use crate::{
|
||||||
string_table::{ImmOrIndex, Index, StringTable},
|
string_table::{ImmOrIndex, Index, StringTable},
|
||||||
symbol_table::{SymbolKind, SymbolTable},
|
symbol_table::{SymbolKind, SymbolTable},
|
||||||
tokens::Token,
|
tokens::Token,
|
||||||
|
variant,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, thiserror::Error)]
|
#[derive(Debug, thiserror::Error)]
|
||||||
|
@ -1498,7 +1499,7 @@ impl Tree {
|
||||||
writeln_indented!(
|
writeln_indented!(
|
||||||
indent,
|
indent,
|
||||||
writer,
|
writer,
|
||||||
"%{} = store(dst: %{}, val: %{})",
|
"%{} = store (dst: %{}, val: %{})",
|
||||||
node.get(),
|
node.get(),
|
||||||
lhs.get(),
|
lhs.get(),
|
||||||
rhs.get()
|
rhs.get()
|
||||||
|
@ -1560,6 +1561,28 @@ impl Tree {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn peer_type_of_nodes(&self, lhs: Node, rhs: Node) -> Option<Type> {
|
||||||
|
let lty = self.type_of_node(lhs);
|
||||||
|
let rty = self.type_of_node(rhs);
|
||||||
|
|
||||||
|
let peer = lty.equal_type(&rty)?;
|
||||||
|
|
||||||
|
if lty == Type::ComptimeNumber {
|
||||||
|
let value = self.value_of_comptime_node(lhs)?;
|
||||||
|
if value.bit_count() > rty.bit_width() {
|
||||||
|
panic!("comptime number is incompatible with type {rty}!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if rty == Type::ComptimeNumber {
|
||||||
|
let value = self.value_of_comptime_node(rhs)?;
|
||||||
|
if value.bit_count() > lty.bit_width() {
|
||||||
|
panic!("comptime number is incompatible with type {lty}!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Some(peer)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn type_of_node(&self, node: Node) -> crate::ast::Type {
|
pub fn type_of_node(&self, node: Node) -> crate::ast::Type {
|
||||||
match self.nodes.get_node(node) {
|
match self.nodes.get_node(node) {
|
||||||
Tag::FunctionDecl { proto, .. } => self.type_of_node(*proto),
|
Tag::FunctionDecl { proto, .. } => self.type_of_node(*proto),
|
||||||
|
@ -1600,36 +1623,44 @@ impl Tree {
|
||||||
Tag::Block { trailing_expr, .. } => trailing_expr
|
Tag::Block { trailing_expr, .. } => trailing_expr
|
||||||
.map(|n| self.type_of_node(n))
|
.map(|n| self.type_of_node(n))
|
||||||
.unwrap_or(Type::void()),
|
.unwrap_or(Type::void()),
|
||||||
Tag::VarDecl {
|
|
||||||
explicit_type,
|
|
||||||
assignment, // this is a Tag::Assign
|
|
||||||
..
|
|
||||||
} => {
|
|
||||||
let lhs = explicit_type.map(|n| self.type_of_node(n));
|
|
||||||
let rhs = assignment.map(|n| match self.nodes.get_node(n) {
|
|
||||||
Tag::Assign { rhs, .. } => self.type_of_node(*rhs),
|
|
||||||
_ => unreachable!(),
|
|
||||||
});
|
|
||||||
if lhs.as_ref().zip(rhs.as_ref()).map(|(l, r)| l != r) == Some(true) {
|
|
||||||
eprintln!("vardecl: incompatible types {lhs:?} and {rhs:?}.");
|
|
||||||
}
|
|
||||||
lhs.or(rhs)
|
|
||||||
.expect("Type could not be automatically deduced.")
|
|
||||||
}
|
|
||||||
Tag::GlobalDecl {
|
Tag::GlobalDecl {
|
||||||
explicit_type,
|
explicit_type,
|
||||||
assignment, // this is a Tag::Assign
|
assignment, // this is a Tag::Assign
|
||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
let lhs = explicit_type.map(|n| self.type_of_node(n));
|
variant!(self.nodes.get_node(*assignment) => Tag::Assign { rhs ,..});
|
||||||
let rhs = match self.nodes.get_node(*assignment) {
|
let ty = match (explicit_type.as_ref(), rhs) {
|
||||||
Tag::Assign { rhs, .. } => self.type_of_node(*rhs),
|
(None, b) => self.type_of_node(*b),
|
||||||
_ => unreachable!(),
|
(Some(a), b) => self.peer_type_of_nodes(*a, *b).expect({
|
||||||
|
let at = self.type_of_node(*a);
|
||||||
|
let bt = self.type_of_node(*b);
|
||||||
|
&format!("incompatible types for %{a}({at}) and %{b}({bt})")
|
||||||
|
}),
|
||||||
};
|
};
|
||||||
if lhs.as_ref().zip(Some(&rhs)).map(|(l, r)| l != r) == Some(true) {
|
|
||||||
eprintln!("vardecl: incompatible types {lhs:?} and {rhs:?}.");
|
ty
|
||||||
}
|
}
|
||||||
lhs.unwrap_or(rhs)
|
Tag::VarDecl {
|
||||||
|
explicit_type,
|
||||||
|
assignment, // this is a Tag::Assign
|
||||||
|
..
|
||||||
|
} => {
|
||||||
|
let rhs = assignment.map(|n| {
|
||||||
|
variant!(self.nodes.get_node(n) => Tag::Assign { rhs ,..});
|
||||||
|
*rhs
|
||||||
|
});
|
||||||
|
let ty = match (explicit_type.as_ref(), rhs.as_ref()) {
|
||||||
|
(None, None) => panic!("%{node}: no type specified?"),
|
||||||
|
(None, Some(b)) => self.type_of_node(*b),
|
||||||
|
(Some(a), None) => self.type_of_node(*a),
|
||||||
|
(Some(a), Some(b)) => self.peer_type_of_nodes(*a, *b).expect({
|
||||||
|
let at = self.type_of_node(*a);
|
||||||
|
let bt = self.type_of_node(*b);
|
||||||
|
&format!("incompatible types for %{a}({at}) and %{b}({bt})")
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
|
||||||
|
ty
|
||||||
}
|
}
|
||||||
Tag::CallExpr { lhs, .. } => self.type_of_node(*lhs),
|
Tag::CallExpr { lhs, .. } => self.type_of_node(*lhs),
|
||||||
Tag::ExplicitCast { typename, .. } => self.type_of_node(*typename),
|
Tag::ExplicitCast { typename, .. } => self.type_of_node(*typename),
|
||||||
|
@ -1637,18 +1668,23 @@ impl Tree {
|
||||||
Tag::Ref { lhs } => self.type_of_node(*lhs).into_ptr(),
|
Tag::Ref { lhs } => self.type_of_node(*lhs).into_ptr(),
|
||||||
Tag::Not { lhs } => self.type_of_node(*lhs),
|
Tag::Not { lhs } => self.type_of_node(*lhs),
|
||||||
Tag::Negate { lhs } => self.type_of_node(*lhs),
|
Tag::Negate { lhs } => self.type_of_node(*lhs),
|
||||||
Tag::Or { lhs, .. } => self.type_of_node(*lhs),
|
Tag::Assign { lhs, rhs }
|
||||||
Tag::And { lhs, .. } => self.type_of_node(*lhs),
|
| Tag::Add { lhs, rhs }
|
||||||
Tag::BitOr { lhs, .. } => self.type_of_node(*lhs),
|
| Tag::Sub { lhs, rhs }
|
||||||
Tag::BitAnd { lhs, .. } => self.type_of_node(*lhs),
|
| Tag::Mul { lhs, rhs }
|
||||||
Tag::BitXOr { lhs, .. } => self.type_of_node(*lhs),
|
| Tag::Rem { lhs, rhs }
|
||||||
|
| Tag::Div { lhs, rhs }
|
||||||
|
| Tag::Or { lhs, rhs }
|
||||||
|
| Tag::And { lhs, rhs }
|
||||||
|
| Tag::BitOr { lhs, rhs }
|
||||||
|
| Tag::BitAnd { lhs, rhs }
|
||||||
|
| Tag::BitXOr { lhs, rhs } => self.peer_type_of_nodes(*lhs, *rhs).expect({
|
||||||
|
let at = self.type_of_node(*lhs);
|
||||||
|
let bt = self.type_of_node(*rhs);
|
||||||
|
&format!("incompatible types for %{lhs}({at}) and %{rhs}({bt})")
|
||||||
|
}),
|
||||||
Tag::Shl { lhs, .. } => self.type_of_node(*lhs),
|
Tag::Shl { lhs, .. } => self.type_of_node(*lhs),
|
||||||
Tag::Shr { lhs, .. } => self.type_of_node(*lhs),
|
Tag::Shr { lhs, .. } => self.type_of_node(*lhs),
|
||||||
Tag::Add { lhs, .. } => self.type_of_node(*lhs),
|
|
||||||
Tag::Sub { lhs, .. } => self.type_of_node(*lhs),
|
|
||||||
Tag::Mul { lhs, .. } => self.type_of_node(*lhs),
|
|
||||||
Tag::Rem { lhs, .. } => self.type_of_node(*lhs),
|
|
||||||
Tag::Div { lhs, .. } => self.type_of_node(*lhs),
|
|
||||||
Tag::Eq { .. } => Type::bool(),
|
Tag::Eq { .. } => Type::bool(),
|
||||||
Tag::NEq { .. } => Type::bool(),
|
Tag::NEq { .. } => Type::bool(),
|
||||||
Tag::Lt { .. } => Type::bool(),
|
Tag::Lt { .. } => Type::bool(),
|
||||||
|
@ -1736,6 +1772,72 @@ impl Tree {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn value_of_comptime_node(&self, node: Node) -> Option<ComptimeNumber> {
|
||||||
|
match self.nodes.get_node(node) {
|
||||||
|
Tag::Constant { bytes, ty } => {
|
||||||
|
let bytes = match bytes {
|
||||||
|
ImmOrIndex::U64(v) => &v.to_le_bytes()[..],
|
||||||
|
|
||||||
|
ImmOrIndex::U32(v) => &v.to_le_bytes()[..],
|
||||||
|
ImmOrIndex::Index(idx) => self.strings.get_bytes(*idx),
|
||||||
|
};
|
||||||
|
|
||||||
|
let number: ComptimeNumber = match ty {
|
||||||
|
Type::Bool => (bytes[0] != 0).into(),
|
||||||
|
Type::ComptimeNumber => {
|
||||||
|
BigInt::from_bytes_le(num_bigint::Sign::Plus, bytes).into()
|
||||||
|
}
|
||||||
|
Type::Integer(ty) => {
|
||||||
|
if bytes.len() > core::mem::size_of::<u128>() {
|
||||||
|
let bits = BigInt::from_bytes_le(num_bigint::Sign::Plus, bytes);
|
||||||
|
(bits, *ty).into()
|
||||||
|
} else {
|
||||||
|
let mut buf = [0u8; core::mem::size_of::<u128>()];
|
||||||
|
buf[..bytes.len()].copy_from_slice(bytes);
|
||||||
|
let bits = u128::from_le_bytes(buf);
|
||||||
|
(bits, *ty).into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Type::Floating(ty) => match ty {
|
||||||
|
FloatingType::Binary32 => {
|
||||||
|
(f32::from_le_bytes((&bytes[..4]).try_into().unwrap())).into()
|
||||||
|
}
|
||||||
|
FloatingType::Binary64 => {
|
||||||
|
(f64::from_le_bytes((&bytes[..8]).try_into().unwrap())).into()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => unimplemented!(),
|
||||||
|
};
|
||||||
|
Some(number)
|
||||||
|
}
|
||||||
|
Tag::Block { .. } => todo!(),
|
||||||
|
&Tag::DeclRef(lhs) => {
|
||||||
|
let start = lhs;
|
||||||
|
let end = node;
|
||||||
|
let mut last_value = None;
|
||||||
|
|
||||||
|
ast::tree_visitor::Visitor::new_seek(
|
||||||
|
self,start,
|
||||||
|
|_: &Tree, _| {
|
||||||
|
},
|
||||||
|
|tree: &Tree, node| match tree.nodes.get_node(node) {
|
||||||
|
&Tag::Assign { lhs, rhs } => {
|
||||||
|
if lhs == start || matches!(tree.nodes.get_node(lhs), &Tag::DeclRef(decl) if decl == start) {
|
||||||
|
last_value = Some(rhs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.until_after(end)
|
||||||
|
.visit(self);
|
||||||
|
|
||||||
|
self.value_of_comptime_node(last_value?)
|
||||||
|
}
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn fold_comptime_with_visitor(&mut self, decl: Node) {
|
fn fold_comptime_with_visitor(&mut self, decl: Node) {
|
||||||
ast::tree_visitor::Visitor::new(
|
ast::tree_visitor::Visitor::new(
|
||||||
decl,
|
decl,
|
||||||
|
|
|
@ -260,6 +260,35 @@ impl<'tree, 'ir> IRBuilder<'tree, 'ir> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn peer_type_of_nodes(&self, lhs: AstNode, rhs: AstNode) -> Option<Type> {
|
||||||
|
let lty = self.tree.type_of_node(lhs);
|
||||||
|
let rty = self.tree.type_of_node(rhs);
|
||||||
|
|
||||||
|
let peer = lty
|
||||||
|
.equal_type(&rty)
|
||||||
|
.expect(&format!("types {lty} and {rty} are incompatible!"));
|
||||||
|
|
||||||
|
if lty == Type::ComptimeNumber {
|
||||||
|
eprintln!(
|
||||||
|
"%{lhs} is comptime number: {:?}",
|
||||||
|
self.tree.nodes.get_node(lhs)
|
||||||
|
);
|
||||||
|
let value = self.tree.value_of_comptime_node(lhs)?;
|
||||||
|
if value.bit_count() > rty.bit_width() {
|
||||||
|
panic!("comptime number is incompatible with type {rty}!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if rty == Type::ComptimeNumber {
|
||||||
|
eprintln!("%{rhs} is comptime number");
|
||||||
|
let value = self.tree.value_of_comptime_node(rhs)?;
|
||||||
|
if value.bit_count() > lty.bit_width() {
|
||||||
|
panic!("comptime number is incompatible with type {lty}!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Some(peer)
|
||||||
|
}
|
||||||
|
|
||||||
fn visit(&mut self, node: AstNode) -> Node {
|
fn visit(&mut self, node: AstNode) -> Node {
|
||||||
match &self.tree.nodes[node].clone() {
|
match &self.tree.nodes[node].clone() {
|
||||||
Tag::FunctionDecl { proto, body } => {
|
Tag::FunctionDecl { proto, body } => {
|
||||||
|
@ -353,7 +382,7 @@ impl<'tree, 'ir> IRBuilder<'tree, 'ir> {
|
||||||
self.ir.push(Inst::Load(ty.into()), Some(Data::lhs(lhs)))
|
self.ir.push(Inst::Load(ty.into()), Some(Data::lhs(lhs)))
|
||||||
}
|
}
|
||||||
Tag::Assign { lhs, rhs } => {
|
Tag::Assign { lhs, rhs } => {
|
||||||
let ty = self.tree.type_of_node(*rhs);
|
let ty = self.tree.type_of_node(node);
|
||||||
let dest = self.visit(*lhs);
|
let dest = self.visit(*lhs);
|
||||||
let source = self.visit(*rhs);
|
let source = self.visit(*rhs);
|
||||||
|
|
||||||
|
@ -361,40 +390,61 @@ impl<'tree, 'ir> IRBuilder<'tree, 'ir> {
|
||||||
.push(Inst::Store(ty.into()), Some(Data::new(source, dest)))
|
.push(Inst::Store(ty.into()), Some(Data::new(source, dest)))
|
||||||
}
|
}
|
||||||
Tag::Add { lhs, rhs } => {
|
Tag::Add { lhs, rhs } => {
|
||||||
let ty = self.tree.type_of_node(*lhs);
|
let ty = self.tree.type_of_node(node);
|
||||||
let lhs = self.visit(*lhs);
|
let lhs = self.visit(*lhs);
|
||||||
let rhs = self.visit(*rhs);
|
let rhs = self.visit(*rhs);
|
||||||
self.ir
|
self.ir
|
||||||
.push(Inst::Add(ty.into()), Some(Data::new(lhs, rhs)))
|
.push(Inst::Add(ty.into()), Some(Data::new(lhs, rhs)))
|
||||||
}
|
}
|
||||||
Tag::Sub { lhs, rhs } => {
|
Tag::Sub { lhs, rhs } => {
|
||||||
let ty = self.tree.type_of_node(*lhs);
|
let ty = self.tree.type_of_node(node);
|
||||||
let lhs = self.visit(*lhs);
|
let lhs = self.visit(*lhs);
|
||||||
let rhs = self.visit(*rhs);
|
let rhs = self.visit(*rhs);
|
||||||
self.ir
|
self.ir
|
||||||
.push(Inst::Sub(ty.into()), Some(Data::new(lhs, rhs)))
|
.push(Inst::Sub(ty.into()), Some(Data::new(lhs, rhs)))
|
||||||
}
|
}
|
||||||
|
Tag::BitAnd { lhs, rhs } => {
|
||||||
|
let ty = self.tree.type_of_node(node);
|
||||||
|
let lhs = self.visit(*lhs);
|
||||||
|
let rhs = self.visit(*rhs);
|
||||||
|
self.ir
|
||||||
|
.push(Inst::BitAnd(ty.into()), Some(Data::new(lhs, rhs)))
|
||||||
|
}
|
||||||
|
Tag::BitOr { lhs, rhs } => {
|
||||||
|
let ty = self.tree.type_of_node(node);
|
||||||
|
let lhs = self.visit(*lhs);
|
||||||
|
let rhs = self.visit(*rhs);
|
||||||
|
self.ir
|
||||||
|
.push(Inst::BitOr(ty.into()), Some(Data::new(lhs, rhs)))
|
||||||
|
}
|
||||||
|
Tag::BitXOr { lhs, rhs } => {
|
||||||
|
let ty = self.tree.type_of_node(node);
|
||||||
|
let lhs = self.visit(*lhs);
|
||||||
|
let rhs = self.visit(*rhs);
|
||||||
|
self.ir
|
||||||
|
.push(Inst::BitXOr(ty.into()), Some(Data::new(lhs, rhs)))
|
||||||
|
}
|
||||||
Tag::Mul { lhs, rhs } => {
|
Tag::Mul { lhs, rhs } => {
|
||||||
let ty = self.tree.type_of_node(*lhs);
|
let ty = self.tree.type_of_node(node);
|
||||||
let lhs = self.visit(*lhs);
|
let lhs = self.visit(*lhs);
|
||||||
let rhs = self.visit(*rhs);
|
let rhs = self.visit(*rhs);
|
||||||
self.ir
|
self.ir
|
||||||
.push(Inst::Mul(ty.into()), Some(Data::new(lhs, rhs)))
|
.push(Inst::Mul(ty.into()), Some(Data::new(lhs, rhs)))
|
||||||
}
|
}
|
||||||
Tag::Negate { lhs } => {
|
Tag::Negate { lhs } => {
|
||||||
let ty = self.tree.type_of_node(*lhs);
|
let ty = self.tree.type_of_node(node);
|
||||||
let lhs = self.visit(*lhs);
|
let lhs = self.visit(*lhs);
|
||||||
self.ir.push(Inst::Negate(ty.into()), Some(Data::lhs(lhs)))
|
self.ir.push(Inst::Negate(ty.into()), Some(Data::lhs(lhs)))
|
||||||
}
|
}
|
||||||
Tag::Shl { lhs, rhs } => {
|
Tag::Shl { lhs, rhs } => {
|
||||||
let ty = self.tree.type_of_node(*lhs);
|
let ty = self.tree.type_of_node(node);
|
||||||
let lhs = self.visit(*lhs);
|
let lhs = self.visit(*lhs);
|
||||||
let rhs = self.visit(*rhs);
|
let rhs = self.visit(*rhs);
|
||||||
self.ir
|
self.ir
|
||||||
.push(Inst::ShiftLeft(ty.into()), Some(Data::new(lhs, rhs)))
|
.push(Inst::ShiftLeft(ty.into()), Some(Data::new(lhs, rhs)))
|
||||||
}
|
}
|
||||||
Tag::Shr { lhs, rhs } => {
|
Tag::Shr { lhs, rhs } => {
|
||||||
let ty = self.tree.type_of_node(*lhs);
|
let ty = self.tree.type_of_node(node);
|
||||||
let lhs = self.visit(*lhs);
|
let lhs = self.visit(*lhs);
|
||||||
let rhs = self.visit(*rhs);
|
let rhs = self.visit(*rhs);
|
||||||
self.ir
|
self.ir
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
fn inverse_sqrt(n: f32) -> f32 {
|
fn inverse_sqrt(n: f32) -> f32 {
|
||||||
let x = n;
|
let x = n;
|
||||||
var i = *(&x as *i32);
|
var i = *(&x as *i32);
|
||||||
i = 0x5f3759dfi32 - (i >> 1);
|
i = 0x5f3759df - (i >> 1);
|
||||||
let y = *(&i as *f32);
|
let y = *(&i as *f32);
|
||||||
y * (1.5f32 - (x * 0.5f32 * y * y))
|
y * (1.5f32 - (x * 0.5f32 * y * y))
|
||||||
}
|
}
|
Loading…
Reference in a new issue