place-value stuff should work now
This commit is contained in:
parent
6d70231c91
commit
1be3f29e23
|
@ -1315,6 +1315,14 @@ impl InternPool {
|
|||
};
|
||||
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(
|
||||
&self,
|
||||
pointee: Index,
|
||||
|
|
322
src/ast2/mod.rs
322
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,7 +1425,35 @@ 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());
|
||||
|
@ -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<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> {
|
||||
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<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(
|
||||
&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<Self::Value, Self::Error> {
|
||||
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<Self::Value, Self::Error> {
|
||||
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<Self::Value, Self::Error> {
|
||||
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<Self::Value, Self::Error> {
|
||||
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<Self::Value, Self::Error> {
|
||||
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<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
|
||||
/// both lhs and rhs.
|
||||
fn visit_binop_expr(
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue