place-value stuff should work now

This commit is contained in:
Janis 2025-03-06 01:02:35 +01:00
parent 6d70231c91
commit 1be3f29e23
3 changed files with 212 additions and 121 deletions

View file

@ -1315,6 +1315,14 @@ impl InternPool {
}; };
self.get_or_insert(key) self.get_or_insert(key)
} }
pub fn try_get_pointee_type(&self, pointer: Index) -> Option<Index> {
match self.get_key(pointer) {
Key::PointerType { pointee, .. } | Key::ArrayType { pointee, .. } => Some(pointee),
_ => None,
}
}
pub fn try_get_pointer_type( pub fn try_get_pointer_type(
&self, &self,
pointee: Index, pointee: Index,

View file

@ -1332,17 +1332,26 @@ impl Ast {
| Tag::Block | Tag::Block
| Tag::ParameterList | Tag::ParameterList
| Tag::File => void, | Tag::File => void,
Tag::VarDeclAssignment | Tag::MutVarDeclAssignment => { // these all evaluate to pointers
Tag::VarDecl | Tag::MutVarDecl | Tag::VarDeclAssignment | Tag::MutVarDeclAssignment => {
let (_, b) = data.as_extra_range(); let (_, b) = data.as_extra_range();
self.get_type_of_node(ip, cache, Index::from_u32(self.extra[b - 1]).unwrap()) let pointee =
} self.get_type_of_node(ip, cache, Index::from_u32(self.extra[b - 1]).unwrap());
Tag::VarDecl | Tag::MutVarDecl => {
let (a, _b) = data.as_extra_range(); ip.try_get_pointer_type(
self.get_type_of_node(ip, cache, Index::from_u32(self.extra[a + 1]).unwrap()) pointee,
Some(PointerFlags::new(tag == Tag::VarDecl, false, false)),
)
.unwrap()
} }
// these all evaluate to pointers
Tag::GlobalDecl => { Tag::GlobalDecl => {
let (_, a) = data.as_intern_and_extra_offset(); let (_, a) = data.as_intern_and_extra_offset();
self.get_type_of_node(ip, cache, Index::from_u32(self.extra[a]).unwrap()) let pointee =
self.get_type_of_node(ip, cache, Index::from_u32(self.extra[a]).unwrap());
ip.try_get_pointer_type(pointee, Some(PointerFlags::new(true, false, true)))
.unwrap()
} }
Tag::FunctionDecl => self.get_type_of_node(ip, cache, data.as_two_indices().0), Tag::FunctionDecl => self.get_type_of_node(ip, cache, data.as_two_indices().0),
Tag::FunctionProto => { Tag::FunctionProto => {
@ -1392,10 +1401,11 @@ impl Ast {
let (_, a) = data.as_two_indices(); let (_, a) = data.as_two_indices();
self.get_type_of_node(ip, cache, a) self.get_type_of_node(ip, cache, a)
} }
// this evaluates to a pointer
Tag::FieldAccess => { Tag::FieldAccess => {
let (ty_expr, name) = data.as_index_intern(); let (ty_expr, name) = data.as_index_intern();
let ty = self.get_type_of_node(ip, cache, ty_expr); let ty = self.get_type_of_node(ip, cache, ty_expr);
match ip.get_key(ty) { let pointee = match ip.get_key(ty) {
intern::Key::PointerType { pointee, .. } intern::Key::PointerType { pointee, .. }
if let intern::Key::StructType { fields, .. } = ip.get_key(pointee) => if let intern::Key::StructType { fields, .. } = ip.get_key(pointee) =>
{ {
@ -1415,8 +1425,36 @@ impl Ast {
_ => { _ => {
unimplemented!() unimplemented!()
} }
};
ip.try_get_pointer_type(pointee, None).unwrap()
}
// this evaluates to a pointer
Tag::SubscriptExpr => {
let ty = self.get_type_of_node(ip, cache, data.as_two_indices().0);
match ip.get_key(ty) {
intern::Key::PointerType { .. } | intern::Key::ArrayType { .. } => {
// note: because of value-to-place and place-to-value,
// this is actually a pointer.
// pointee
ty
}
_ => {
eprintln!("lhs of subscript is not an array or pointer!");
void
}
} }
} }
// this evaluates to a pointer
Tag::AddressOf => {
let ty = self.get_type_of_node(ip, cache, data.as_index());
// TODO: find out of the expression is const, volatile for flags
// ip.try_get_pointer_type(ty, None).unwrap()
// note: because of value-to-place and place-to-value,
// this is actually the same type.
ty
}
Tag::Deref => { Tag::Deref => {
let ty = self.get_type_of_node(ip, cache, data.as_index()); let ty = self.get_type_of_node(ip, cache, data.as_index());
if let intern::Key::PointerType { pointee, .. } = ip.get_key(ty) { if let intern::Key::PointerType { pointee, .. } = ip.get_key(ty) {
@ -1426,25 +1464,15 @@ impl Ast {
void void
} }
} }
Tag::SubscriptExpr => { Tag::ValueToPlaceConversion => {
let ty = self.get_type_of_node(ip, cache, data.as_two_indices().0);
match ip.get_key(ty) {
intern::Key::PointerType { pointee, .. }
| intern::Key::ArrayType { pointee, .. } => pointee,
_ => {
eprintln!("lhs of subscript is not an array or pointer!");
void
}
}
}
Tag::AddressOf => {
let ty = self.get_type_of_node(ip, cache, data.as_index()); let ty = self.get_type_of_node(ip, cache, data.as_index());
// TODO: find out of the expression is const, volatile for flags
ip.try_get_pointer_type(ty, None).unwrap() ip.try_get_pointer_type(ty, None).unwrap()
} }
Tag::ValueToPlaceConversion | Tag::PlaceToValueConversion | Tag::Not | Tag::Negate => { Tag::PlaceToValueConversion => {
self.get_type_of_node(ip, cache, data.as_index()) let ty = self.get_type_of_node(ip, cache, data.as_index());
ip.try_get_pointee_type(ty).unwrap()
} }
Tag::Not | Tag::Negate => self.get_type_of_node(ip, cache, data.as_index()),
Tag::Or Tag::Or
| Tag::And | Tag::And
| Tag::BitOr | Tag::BitOr
@ -1667,7 +1695,10 @@ impl Ast {
Tag::ReturnExprStmt => are_children_comptime(self, cache), Tag::ReturnExprStmt => are_children_comptime(self, cache),
Tag::MutVarDecl | Tag::MutVarDeclAssignment => false, Tag::MutVarDecl | Tag::MutVarDeclAssignment => false,
// Tag::VarDecl => true, // Tag::VarDecl => true,
Tag::VarDeclAssignment => are_children_comptime(self, cache), // Tag::ValueToPlaceConversion => false,
Tag::PlaceToValueConversion | Tag::VarDeclAssignment => {
are_children_comptime(self, cache)
}
Tag::GlobalDecl => true, Tag::GlobalDecl => true,
Tag::StructDecl => true, Tag::StructDecl => true,
Tag::FieldDecl => true, Tag::FieldDecl => true,
@ -1707,7 +1738,7 @@ impl Ast {
| Tag::Sub | Tag::Sub
| Tag::Mul | Tag::Mul
| Tag::Div | Tag::Div
| Tag::SubscriptExpr | Tag::SubscriptExpr // TODO: add array decl expression
| Tag::Rem => are_children_comptime(self, cache), | Tag::Rem => are_children_comptime(self, cache),
Tag::Assign => { Tag::Assign => {
let (left, _) = data.as_two_indices(); let (left, _) = data.as_two_indices();
@ -1771,7 +1802,12 @@ impl Ast {
Index::from_u32(self.extra[a + 1]).unwrap(), Index::from_u32(self.extra[a + 1]).unwrap(),
) )
} }
Tag::DeclRef => self.comptime_value_of_node(ip, pointer_bits, cache, data.as_index()), Tag::SubscriptExpr => {
todo!()
}
Tag::PlaceToValueConversion | Tag::DeclRef => {
self.comptime_value_of_node(ip, pointer_bits, cache, data.as_index())
}
Tag::ExplicitCast => { Tag::ExplicitCast => {
let (expr, ty) = data.as_two_indices(); let (expr, ty) = data.as_two_indices();
let ty = ip.as_ast1_type(intern::AMD64_POINTER_BITS, self.datas[ty].as_intern()); let ty = ip.as_ast1_type(intern::AMD64_POINTER_BITS, self.datas[ty].as_intern());
@ -4681,6 +4717,28 @@ pub trait AstVisitorTrait {
_ = (ast, idx); _ = (ast, idx);
Err(Self::UNIMPL) Err(Self::UNIMPL)
} }
fn visit_value_to_place_conversion(
&mut self,
ast: &mut Ast,
idx: Index,
) -> Result<Self::Value, Self::Error> {
let idx = ast
.get_node_data_for_tag(idx, Tag::ValueToPlaceConversion)
.unwrap()
.as_index();
self.visit_any(ast, idx)
}
fn visit_place_to_value_conversion(
&mut self,
ast: &mut Ast,
idx: Index,
) -> Result<Self::Value, Self::Error> {
let idx = ast
.get_node_data_for_tag(idx, Tag::PlaceToValueConversion)
.unwrap()
.as_index();
self.visit_any(ast, idx)
}
fn visit_any(&mut self, ast: &mut Ast, idx: Index) -> Result<Self::Value, Self::Error> { fn visit_any(&mut self, ast: &mut Ast, idx: Index) -> Result<Self::Value, Self::Error> {
use visitor::AstExt; use visitor::AstExt;
@ -4741,6 +4799,8 @@ pub trait AstVisitorTrait {
Tag::SubscriptExpr => self.visit_subscript_expr(ast, idx), Tag::SubscriptExpr => self.visit_subscript_expr(ast, idx),
Tag::IfExpr => self.visit_if_expr(ast, idx), Tag::IfExpr => self.visit_if_expr(ast, idx),
Tag::IfElseExpr => self.visit_if_else_expr(ast, idx), Tag::IfElseExpr => self.visit_if_else_expr(ast, idx),
Tag::PlaceToValueConversion => self.visit_place_to_value_conversion(ast, idx),
Tag::ValueToPlaceConversion => self.visit_value_to_place_conversion(ast, idx),
Tag::Error => todo!(), Tag::Error => todo!(),
Tag::Undefined => todo!(), Tag::Undefined => todo!(),
_ => todo!(), _ => todo!(),
@ -4823,6 +4883,50 @@ pub mod ir {
Ok(None) Ok(None)
} }
fn visit_place_to_value_conversion(
&mut self,
ast: &mut super::Ast,
idx: Index,
) -> Result<Self::Value, Self::Error> {
let data = ast.expect_node_data_for_tag(idx, super::Tag::PlaceToValueConversion);
let expr = data.as_index();
// idx's (this) type is the pointee type
let ty = ast.get_type_of_node(&self.ip, &mut self.type_cache, idx);
let expr = self.visit_any(ast, expr)?.unwrap();
let ir = self.ir.push(Inst::Load(ty), Some(triples::Data::lhs(expr)));
Ok(Some(ir))
}
fn visit_value_to_place_conversion(
&mut self,
ast: &mut super::Ast,
idx: Index,
) -> Result<Self::Value, Self::Error> {
let data = ast.expect_node_data_for_tag(idx, super::Tag::ValueToPlaceConversion);
let expr = data.as_index();
// expr's type is the pointee type
let ty = ast.get_type_of_node(&self.ip, &mut self.type_cache, expr);
let expr = self.visit_any(ast, expr)?.unwrap();
let info = self.ip.size_of_type(ty, AMD64_POINTER_TYPE_INFO);
let alloca = self.ir.push(
Inst::Alloca,
Some(triples::Data::new(info.size(), info.align())),
);
_ = self
.ir
.push(Inst::Store(ty), Some(triples::Data::new(expr, alloca)));
Ok(Some(alloca))
}
fn visit_decl_ref( fn visit_decl_ref(
&mut self, &mut self,
ast: &mut super::Ast, ast: &mut super::Ast,
@ -4831,7 +4935,9 @@ pub mod ir {
let data = ast.expect_node_data_for_tag(idx, super::Tag::DeclRef); let data = ast.expect_node_data_for_tag(idx, super::Tag::DeclRef);
let decl = data.as_index(); let decl = data.as_index();
todo!() let alloca = self.ref_lookup.get(&decl).cloned().expect("declref");
Ok(Some(alloca))
} }
fn visit_var_decl( fn visit_var_decl(
@ -4839,118 +4945,31 @@ pub mod ir {
ast: &mut super::Ast, ast: &mut super::Ast,
idx: Index, idx: Index,
) -> Result<Self::Value, Self::Error> { ) -> Result<Self::Value, Self::Error> {
let data = ast.expect_node_data_for_tag(idx, super::Tag::VarDecl); self.visit_var_decl_common(ast, idx)
let (a, _) = data.as_extra_range();
let ty = Index::from_u32(ast.extra[a + 1]).unwrap();
let ty = ast.get_type_of_node(&self.ip, &mut self.type_cache, ty);
let info = self.ip.size_of_type(ty, AMD64_POINTER_TYPE_INFO);
let alloca = self.ir.push(
Inst::Alloca,
Some(triples::Data::new(info.size(), info.align())),
);
self.ref_lookup.insert(idx, alloca);
Ok(Some(alloca))
} }
fn visit_mut_var_decl( fn visit_mut_var_decl(
&mut self, &mut self,
ast: &mut super::Ast, ast: &mut super::Ast,
idx: Index, idx: Index,
) -> Result<Self::Value, Self::Error> { ) -> Result<Self::Value, Self::Error> {
let data = ast.expect_node_data_for_tag(idx, super::Tag::MutVarDecl); self.visit_var_decl_common(ast, idx)
let (a, _) = data.as_extra_range();
let ty = Index::from_u32(ast.extra[a + 1]).unwrap();
let ty = ast.get_type_of_node(&self.ip, &mut self.type_cache, ty);
let info = self.ip.size_of_type(ty, AMD64_POINTER_TYPE_INFO);
let alloca = self.ir.push(
Inst::Alloca,
Some(triples::Data::new(info.size(), info.align())),
);
self.ref_lookup.insert(idx, alloca);
Ok(Some(alloca))
} }
fn visit_var_assign_decl( fn visit_var_assign_decl(
&mut self, &mut self,
ast: &mut super::Ast, ast: &mut super::Ast,
idx: Index, idx: Index,
) -> Result<Self::Value, Self::Error> { ) -> Result<Self::Value, Self::Error> {
let data = ast.expect_node_data_for_tag(idx, super::Tag::VarDeclAssignment); self.visit_var_decl_common(ast, idx)
let (a, b) = data.as_extra_range();
let range = &ast.extra[a..b];
let _name = range.get(0).unwrap();
let expr = range
.get(1)
.cloned()
.map(Index::from_u32)
.flatten()
.unwrap();
let ty = range
.get(2)
.cloned()
.map(Index::from_u32)
.flatten()
.unwrap_or(expr);
let ty = ast.get_type_of_node(&self.ip, &mut self.type_cache, ty);
let info = self.ip.size_of_type(ty, AMD64_POINTER_TYPE_INFO);
let alloca = self.ir.push(
Inst::Alloca,
Some(triples::Data::new(info.size(), info.align())),
);
let expr = self.visit_any(ast, expr)?.unwrap();
self.ir
.push(Inst::Store(ty), Some(triples::Data::new(expr, alloca)));
self.ref_lookup.insert(idx, alloca);
Ok(Some(alloca))
} }
fn visit_mut_var_assign_decl( fn visit_mut_var_assign_decl(
&mut self, &mut self,
ast: &mut super::Ast, ast: &mut super::Ast,
idx: Index, idx: Index,
) -> Result<Self::Value, Self::Error> { ) -> Result<Self::Value, Self::Error> {
let data = ast.expect_node_data_for_tag(idx, super::Tag::MutVarDeclAssignment); self.visit_var_decl_common(ast, idx)
let (a, b) = data.as_extra_range();
let range = &ast.extra[a..b];
let _name = range.get(0).unwrap();
let expr = range
.get(1)
.cloned()
.map(Index::from_u32)
.flatten()
.unwrap();
let ty = range
.get(2)
.cloned()
.map(Index::from_u32)
.flatten()
.unwrap_or(expr);
let ty = ast.get_type_of_node(&self.ip, &mut self.type_cache, ty);
let info = self.ip.size_of_type(ty, AMD64_POINTER_TYPE_INFO);
let alloca = self.ir.push(
Inst::Alloca,
Some(triples::Data::new(info.size(), info.align())),
);
let expr = self.visit_any(ast, expr)?.unwrap();
self.ir
.push(Inst::Store(ty), Some(triples::Data::new(expr, alloca)));
self.ref_lookup.insert(idx, alloca);
Ok(Some(alloca))
} }
fn visit_return( fn visit_return(
@ -5001,6 +5020,8 @@ pub mod ir {
) -> Result<Self::Value, Self::Error> { ) -> Result<Self::Value, Self::Error> {
let data = ast.expect_node_data_for_tag(idx, super::Tag::SubscriptExpr); let data = ast.expect_node_data_for_tag(idx, super::Tag::SubscriptExpr);
let (lhs, index) = data.as_two_indices(); let (lhs, index) = data.as_two_indices();
// pointer type
let ty = ast.get_type_of_node(&self.ip, &mut self.type_cache, idx); let ty = ast.get_type_of_node(&self.ip, &mut self.type_cache, idx);
let lhs = self.visit_any(ast, lhs)?.unwrap(); let lhs = self.visit_any(ast, lhs)?.unwrap();
@ -5525,6 +5546,65 @@ pub mod ir {
} }
impl IrFunctionBuilder<'_> { impl IrFunctionBuilder<'_> {
fn visit_var_decl_common(
&mut self,
ast: &mut super::Ast,
idx: Index,
) -> Result<Option<u32>, Error> {
let (tag, data) = ast.get_node_tag_and_data(idx);
let (a, b) = data.as_extra_range();
let range = &ast.extra[a..b];
let _name = range.get(0).unwrap();
let (expr, typed_index) = match tag {
super::Tag::VarDecl | super::Tag::MutVarDecl => {
let typed_index = range
.get(1)
.cloned()
.map(Index::from_u32)
.flatten()
.unwrap();
(None, typed_index)
}
super::Tag::VarDeclAssignment | super::Tag::MutVarDeclAssignment => {
let expr = range
.get(1)
.cloned()
.map(Index::from_u32)
.flatten()
.unwrap();
let typed_index = range
.get(2)
.cloned()
.map(Index::from_u32)
.flatten()
.unwrap_or(expr);
(Some(expr), typed_index)
}
_ => unreachable!(),
};
let ty = ast.get_type_of_node(&self.ip, &mut self.type_cache, typed_index);
let info = self.ip.size_of_type(ty, AMD64_POINTER_TYPE_INFO);
let alloca = self.ir.push(
Inst::Alloca,
Some(triples::Data::new(info.size(), info.align())),
);
if let Some(idx) = expr {
let expr = self.visit_any(ast, idx)?.unwrap();
_ = self
.ir
.push(Inst::Store(ty), Some(triples::Data::new(expr, alloca)));
}
self.ref_lookup.insert(idx, alloca);
Ok(Some(alloca))
}
/// handles all binary operations that don't short circuit and visit /// handles all binary operations that don't short circuit and visit
/// both lhs and rhs. /// both lhs and rhs.
fn visit_binop_expr( fn visit_binop_expr(

View file

@ -159,10 +159,13 @@ pub enum Inst {
Constant, Constant,
/// size, align /// size, align
Alloca, Alloca,
/// (pointee type)
/// src /// src
Load(intern::Index), Load(intern::Index),
/// (pointee type)
/// src, dst /// src, dst
Store(intern::Index), Store(intern::Index),
/// (pointer type)
/// ptr, index, /// ptr, index,
GetElementPtr(intern::Index), GetElementPtr(intern::Index),
/// size, align /// size, align