From 1be3f29e235893e975539a527dfca2cd6c19dec0 Mon Sep 17 00:00:00 2001 From: Janis Date: Thu, 6 Mar 2025 01:02:35 +0100 Subject: [PATCH] place-value stuff should work now --- src/ast2/intern.rs | 8 ++ src/ast2/mod.rs | 322 ++++++++++++++++++++++++++++----------------- src/triples.rs | 3 + 3 files changed, 212 insertions(+), 121 deletions(-) diff --git a/src/ast2/intern.rs b/src/ast2/intern.rs index bb15a39..a02c3d2 100644 --- a/src/ast2/intern.rs +++ b/src/ast2/intern.rs @@ -1315,6 +1315,14 @@ impl InternPool { }; self.get_or_insert(key) } + + pub fn try_get_pointee_type(&self, pointer: Index) -> Option { + match self.get_key(pointer) { + Key::PointerType { pointee, .. } | Key::ArrayType { pointee, .. } => Some(pointee), + _ => None, + } + } + pub fn try_get_pointer_type( &self, pointee: Index, diff --git a/src/ast2/mod.rs b/src/ast2/mod.rs index d7ef354..0196535 100644 --- a/src/ast2/mod.rs +++ b/src/ast2/mod.rs @@ -1332,17 +1332,26 @@ impl Ast { | Tag::Block | Tag::ParameterList | 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(); - 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(); - self.get_type_of_node(ip, cache, Index::from_u32(self.extra[a + 1]).unwrap()) + let pointee = + self.get_type_of_node(ip, cache, Index::from_u32(self.extra[b - 1]).unwrap()); + + ip.try_get_pointer_type( + pointee, + Some(PointerFlags::new(tag == Tag::VarDecl, false, false)), + ) + .unwrap() } + // these all evaluate to pointers Tag::GlobalDecl => { 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::FunctionProto => { @@ -1392,10 +1401,11 @@ impl Ast { let (_, a) = data.as_two_indices(); self.get_type_of_node(ip, cache, a) } + // this evaluates to a pointer Tag::FieldAccess => { let (ty_expr, name) = data.as_index_intern(); 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, .. } if let intern::Key::StructType { fields, .. } = ip.get_key(pointee) => { @@ -1415,8 +1425,36 @@ impl Ast { _ => { 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 => { let ty = self.get_type_of_node(ip, cache, data.as_index()); if let intern::Key::PointerType { pointee, .. } = ip.get_key(ty) { @@ -1426,25 +1464,15 @@ impl Ast { void } } - Tag::SubscriptExpr => { - 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 => { + Tag::ValueToPlaceConversion => { 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() } - Tag::ValueToPlaceConversion | Tag::PlaceToValueConversion | Tag::Not | Tag::Negate => { - self.get_type_of_node(ip, cache, data.as_index()) + Tag::PlaceToValueConversion => { + 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::And | Tag::BitOr @@ -1667,7 +1695,10 @@ impl Ast { Tag::ReturnExprStmt => are_children_comptime(self, cache), Tag::MutVarDecl | Tag::MutVarDeclAssignment => false, // 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::StructDecl => true, Tag::FieldDecl => true, @@ -1707,7 +1738,7 @@ impl Ast { | Tag::Sub | Tag::Mul | Tag::Div - | Tag::SubscriptExpr + | Tag::SubscriptExpr // TODO: add array decl expression | Tag::Rem => are_children_comptime(self, cache), Tag::Assign => { let (left, _) = data.as_two_indices(); @@ -1771,7 +1802,12 @@ impl Ast { 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 => { let (expr, ty) = data.as_two_indices(); let ty = ip.as_ast1_type(intern::AMD64_POINTER_BITS, self.datas[ty].as_intern()); @@ -4681,6 +4717,28 @@ pub trait AstVisitorTrait { _ = (ast, idx); Err(Self::UNIMPL) } + fn visit_value_to_place_conversion( + &mut self, + ast: &mut Ast, + idx: Index, + ) -> Result { + 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 { + 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 { use visitor::AstExt; @@ -4741,6 +4799,8 @@ pub trait AstVisitorTrait { Tag::SubscriptExpr => self.visit_subscript_expr(ast, idx), Tag::IfExpr => self.visit_if_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::Undefined => todo!(), _ => todo!(), @@ -4823,6 +4883,50 @@ pub mod ir { Ok(None) } + fn visit_place_to_value_conversion( + &mut self, + ast: &mut super::Ast, + idx: Index, + ) -> Result { + 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 { + 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( &mut self, ast: &mut super::Ast, @@ -4831,7 +4935,9 @@ pub mod ir { let data = ast.expect_node_data_for_tag(idx, super::Tag::DeclRef); let decl = data.as_index(); - todo!() + let alloca = self.ref_lookup.get(&decl).cloned().expect("declref"); + + Ok(Some(alloca)) } fn visit_var_decl( @@ -4839,118 +4945,31 @@ pub mod ir { ast: &mut super::Ast, idx: Index, ) -> Result { - let data = ast.expect_node_data_for_tag(idx, super::Tag::VarDecl); - 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)) + self.visit_var_decl_common(ast, idx) } + fn visit_mut_var_decl( &mut self, ast: &mut super::Ast, idx: Index, ) -> Result { - let data = ast.expect_node_data_for_tag(idx, super::Tag::MutVarDecl); - 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)) + self.visit_var_decl_common(ast, idx) } + fn visit_var_assign_decl( &mut self, ast: &mut super::Ast, idx: Index, ) -> Result { - let data = ast.expect_node_data_for_tag(idx, super::Tag::VarDeclAssignment); - 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)) + self.visit_var_decl_common(ast, idx) } + fn visit_mut_var_assign_decl( &mut self, ast: &mut super::Ast, idx: Index, ) -> Result { - let data = ast.expect_node_data_for_tag(idx, super::Tag::MutVarDeclAssignment); - 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)) + self.visit_var_decl_common(ast, idx) } fn visit_return( @@ -5001,6 +5020,8 @@ pub mod ir { ) -> Result { let data = ast.expect_node_data_for_tag(idx, super::Tag::SubscriptExpr); let (lhs, index) = data.as_two_indices(); + + // pointer type let ty = ast.get_type_of_node(&self.ip, &mut self.type_cache, idx); let lhs = self.visit_any(ast, lhs)?.unwrap(); @@ -5525,6 +5546,65 @@ pub mod ir { } impl IrFunctionBuilder<'_> { + fn visit_var_decl_common( + &mut self, + ast: &mut super::Ast, + idx: Index, + ) -> Result, 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 /// both lhs and rhs. fn visit_binop_expr( diff --git a/src/triples.rs b/src/triples.rs index 393e31e..078505e 100644 --- a/src/triples.rs +++ b/src/triples.rs @@ -159,10 +159,13 @@ pub enum Inst { Constant, /// size, align Alloca, + /// (pointee type) /// src Load(intern::Index), + /// (pointee type) /// src, dst Store(intern::Index), + /// (pointer type) /// ptr, index, GetElementPtr(intern::Index), /// size, align