From 96863e0397de9c56d596b0a0337932c90c8fe6e1 Mon Sep 17 00:00:00 2001 From: Janis Date: Sun, 22 Dec 2024 19:01:22 +0100 Subject: [PATCH] `cargo fmt` --- src/asm/amd64.rs | 46 +- src/ast.rs | 46 +- src/ast2/mod.rs | 1271 ++++++++++++++++++++++++++++++------------ src/bin/main.rs | 9 +- src/bin/tokenizer.rs | 3 +- src/common.rs | 4 +- src/comptime.rs | 414 ++++++++++---- src/lexer.rs | 97 +++- src/lib.rs | 5 +- src/mir.rs | 1100 ++++++++++++++++++++++++++++-------- src/parser.rs | 413 ++++++++++---- src/string_table.rs | 10 +- src/symbol_table.rs | 80 ++- src/triples.rs | 539 +++++++++++++----- 14 files changed, 3003 insertions(+), 1034 deletions(-) diff --git a/src/asm/amd64.rs b/src/asm/amd64.rs index 88d7495..4bef347 100644 --- a/src/asm/amd64.rs +++ b/src/asm/amd64.rs @@ -220,27 +220,27 @@ impl Register { const fn bit_size(self) -> u32 { use Register::*; match self { - ah | bh | ch | dh | al | bl | cl | dl | sil | dil | spl | bpl | r8b | r9b | r10b - | r11b | r12b | r13b | r14b | r15b => 8, + ah | bh | ch | dh | al | bl | cl | dl | sil | dil | spl | bpl + | r8b | r9b | r10b | r11b | r12b | r13b | r14b | r15b => 8, - ax | bx | cx | dx | si | di | sp | bp | ip | r8w | r9w | r10w | r11w | r12w | r13w - | r14w | r15w => 16, + ax | bx | cx | dx | si | di | sp | bp | ip | r8w | r9w | r10w + | r11w | r12w | r13w | r14w | r15w => 16, - eax | ebx | ecx | edx | esi | edi | esp | ebp | eip | r8d | r9d | r10d | r11d - | r12d | r13d | r14d | r15d => 32, + eax | ebx | ecx | edx | esi | edi | esp | ebp | eip | r8d | r9d + | r10d | r11d | r12d | r13d | r14d | r15d => 32, - rax | rbx | rcx | rdx | rsi | rdi | rsp | rbp | rip | r8 | r9 | r10 | r11 | r12 - | r13 | r14 | r15 => 64, + rax | rbx | rcx | rdx | rsi | rdi | rsp | rbp | rip | r8 | r9 + | r10 | r11 | r12 | r13 | r14 | r15 => 64, mm0 | mm1 | mm2 | mm3 | mm4 | mm5 | mm6 | mm7 => 64, st0 | st1 | st2 | st3 | st4 | st5 | st6 | st7 => 80, - xmm0 | xmm1 | xmm2 | xmm3 | xmm4 | xmm5 | xmm6 | xmm7 | xmm8 | xmm9 | xmm10 | xmm11 - | xmm12 | xmm13 | xmm14 | xmm15 => 128, + xmm0 | xmm1 | xmm2 | xmm3 | xmm4 | xmm5 | xmm6 | xmm7 | xmm8 + | xmm9 | xmm10 | xmm11 | xmm12 | xmm13 | xmm14 | xmm15 => 128, - ymm0 | ymm1 | ymm2 | ymm3 | ymm4 | ymm5 | ymm6 | ymm7 | ymm8 | ymm9 | ymm10 | ymm11 - | ymm12 | ymm13 | ymm14 | ymm15 => 256, + ymm0 | ymm1 | ymm2 | ymm3 | ymm4 | ymm5 | ymm6 | ymm7 | ymm8 + | ymm9 | ymm10 | ymm11 | ymm12 | ymm13 | ymm14 | ymm15 => 256, _ => unreachable!(), } } @@ -338,28 +338,30 @@ impl Register { pub const SSE: [Register; 16] = { use Register::*; [ - xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, - xmm14, xmm15, + xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8, xmm9, xmm10, + xmm11, xmm12, xmm13, xmm14, xmm15, ] }; pub const fn is_gp(self) -> bool { use Register::*; match self { - rax | eax | ax | ah | al | rbx | ebx | bx | bh | bl | rcx | ecx | cx | ch | cl - | rdx | edx | dx | dh | dl | rsi | esi | si | sil | rdi | edi | di | dil | r8 | r8d - | r8w | r8b | r9 | r9d | r9w | r9b | r10 | r10d | r10w | r10b | r11 | r11d | r11w - | r11b | r12 | r12d | r12w | r12b | r13 | r13d | r13w | r13b | r14 | r14d | r14w - | r14b | r15 | r15d | r15w | r15b => true, + rax | eax | ax | ah | al | rbx | ebx | bx | bh | bl | rcx | ecx + | cx | ch | cl | rdx | edx | dx | dh | dl | rsi | esi | si + | sil | rdi | edi | di | dil | r8 | r8d | r8w | r8b | r9 | r9d + | r9w | r9b | r10 | r10d | r10w | r10b | r11 | r11d | r11w + | r11b | r12 | r12d | r12w | r12b | r13 | r13d | r13w | r13b + | r14 | r14d | r14w | r14b | r15 | r15d | r15w | r15b => true, _ => false, } } pub const fn is_sse(self) -> bool { use Register::*; match self { - xmm0 | xmm1 | xmm2 | xmm3 | xmm4 | xmm5 | xmm6 | xmm7 | xmm8 | xmm9 | xmm10 | xmm11 - | xmm12 | xmm13 | xmm14 | xmm15 | ymm0 | ymm1 | ymm2 | ymm3 | ymm4 | ymm5 | ymm6 - | ymm7 | ymm8 | ymm9 | ymm10 | ymm11 | ymm12 | ymm13 | ymm14 | ymm15 => true, + xmm0 | xmm1 | xmm2 | xmm3 | xmm4 | xmm5 | xmm6 | xmm7 | xmm8 + | xmm9 | xmm10 | xmm11 | xmm12 | xmm13 | xmm14 | xmm15 | ymm0 + | ymm1 | ymm2 | ymm3 | ymm4 | ymm5 | ymm6 | ymm7 | ymm8 | ymm9 + | ymm10 | ymm11 | ymm12 | ymm13 | ymm14 | ymm15 => true, _ => false, } } diff --git a/src/ast.rs b/src/ast.rs index 7a9b35a..1cbbd8e 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -294,14 +294,21 @@ impl core::fmt::Display for Type { Type::Integer(t) => t.fmt(f), Type::Floating(t) => t.fmt(f), Type::Pointer { constness, pointee } => { - write!(f, "*{}{}", if *constness { "const " } else { "" }, pointee) + write!( + f, + "*{}{}", + if *constness { "const " } else { "" }, + pointee + ) } Type::Fn { parameter_types, return_type, } => { write!(f, "fn (")?; - for param in parameter_types.iter().map(|p| Some(p)).intersperse(None) { + for param in + parameter_types.iter().map(|p| Some(p)).intersperse(None) + { match param { Some(param) => param.fmt(f)?, None => write!(f, ", ")?, @@ -340,8 +347,13 @@ impl Type { parameter_types: r_parameter_types, return_type: r_return_type, }, - ) => l_parameter_types == r_parameter_types && l_return_type == r_return_type, - _ => core::mem::discriminant(self) == core::mem::discriminant(other), + ) => { + l_parameter_types == r_parameter_types + && l_return_type == r_return_type + } + _ => { + core::mem::discriminant(self) == core::mem::discriminant(other) + } } } pub fn as_primitive_type(&self) -> Option { @@ -460,9 +472,10 @@ impl Type { pub fn can_add_sub(&self) -> bool { match self { - Type::ComptimeNumber | Type::Pointer { .. } | Type::Floating(_) | Type::Integer(_) => { - true - } + Type::ComptimeNumber + | Type::Pointer { .. } + | Type::Floating(_) + | Type::Integer(_) => true, _ => false, } } @@ -484,9 +497,10 @@ impl Type { } pub fn can_cmp(&self) -> bool { match self { - Type::ComptimeNumber | Type::Pointer { .. } | Type::Floating(_) | Type::Integer(_) => { - true - } + Type::ComptimeNumber + | Type::Pointer { .. } + | Type::Floating(_) + | Type::Integer(_) => true, _ => false, } } @@ -595,7 +609,12 @@ pub mod tree_visitor { pub fn new_range(start: Node, end: Node, pre: F1, post: F2) -> Self { Self::new_inner(start, End::Exclusive(end), pre, post) } - pub fn new_range_inclusive(start: Node, end: Node, pre: F1, post: F2) -> Self { + pub fn new_range_inclusive( + start: Node, + end: Node, + pre: F1, + post: F2, + ) -> Self { Self::new_inner(start, End::Inclusive(end), pre, post) } pub fn new_seek(tree: &Tree, start: Node, pre: F1, post: F2) -> Self { @@ -694,7 +713,10 @@ pub mod tree_visitor { } /// short-circuits on the first E - pub fn visit_ok(mut self, tree: &Tree) -> core::result::Result + pub fn visit_ok( + mut self, + tree: &Tree, + ) -> core::result::Result where F1: FnMut(&Tree, Node) -> core::result::Result, F2: FnMut(&Tree, Node) -> core::result::Result, diff --git a/src/ast2/mod.rs b/src/ast2/mod.rs index 158e756..4d3723b 100644 --- a/src/ast2/mod.rs +++ b/src/ast2/mod.rs @@ -340,7 +340,9 @@ impl From<(Tag, Data)> for ExpandedData { | Tag::MutVarDeclAssignment | Tag::BlockTrailingExpr | Tag::Block => Self::from_extra_range(data), - Tag::FieldDecl | Tag::Constant | Tag::Parameter => Self::from_index_intern(data), + Tag::FieldDecl | Tag::Constant | Tag::Parameter => { + Self::from_index_intern(data) + } Tag::Or | Tag::And | Tag::BitOr @@ -381,7 +383,9 @@ impl From<(Tag, Data)> for ExpandedData { | Tag::ExplicitCast => Self::from_index_intern(data), Tag::GlobalDecl => Self::from_intern_and_extra_offset(data), Tag::InternedType | Tag::StructDecl => Self::from_intern(data), - Tag::PointerType | Tag::IfElseExpr => Self::from_index_and_extra_offset(data), + Tag::PointerType | Tag::IfElseExpr => { + Self::from_index_and_extra_offset(data) + } Tag::Error => Self::from_error(data), Tag::ReturnStmt | Tag::Undefined => Self::from_none(), } @@ -488,7 +492,10 @@ impl Debug for Ast { let mut list = f.debug_list(); struct LocDisplay(SourceLocation); impl Debug for LocDisplay { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + fn fmt( + &self, + f: &mut std::fmt::Formatter<'_>, + ) -> std::fmt::Result { write!(f, "({})", self.0) } } @@ -500,7 +507,12 @@ impl Debug for Ast { .zip(self.source_locs.iter().cloned()) .enumerate() .map(|(i, ((tag, data), loc))| { - (i, tag, ExpandedData::from((tag, data)), LocDisplay(loc)) + ( + i, + tag, + ExpandedData::from((tag, data)), + LocDisplay(loc), + ) }); list.entries(entries).finish() }) @@ -520,7 +532,8 @@ impl Ast { } fn reserve_node(&mut self) -> Index { - let i = unsafe { Index(NonZero::new_unchecked(self.tags.len() as u32)) }; + let i = + unsafe { Index(NonZero::new_unchecked(self.tags.len() as u32)) }; self.tags.push(Tag::Undefined); self.datas.push(Data::none()); self.source_locs.push(SourceLocation::invalid()); @@ -539,12 +552,26 @@ impl Ast { i } - fn set_file>(&mut self, i: Index, decls: I, loc: SourceLocation) { + fn set_file>( + &mut self, + i: Index, + decls: I, + loc: SourceLocation, + ) { let (extra_start, extra_end) = self.extend_extra_by_indices(decls); - self.set_tag_data_source_loc(i, Tag::File, Data::extra_range(extra_start, extra_end), loc); + self.set_tag_data_source_loc( + i, + Tag::File, + Data::extra_range(extra_start, extra_end), + loc, + ); } - fn push_file>(&mut self, decls: I, loc: SourceLocation) -> Index { + fn push_file>( + &mut self, + decls: I, + loc: SourceLocation, + ) -> Index { let i = self.reserve_node(); self.set_file(i, decls, loc); i @@ -569,7 +596,8 @@ impl Ast { loc: SourceLocation, ) -> Index { let i = self.reserve_node(); - let (extra_start, _) = self.extend_extra([ty.into_u32(), expr.into_u32()]); + let (extra_start, _) = + self.extend_extra([ty.into_u32(), expr.into_u32()]); self.set_tag_data_source_loc( i, Tag::GlobalDecl, @@ -580,11 +608,27 @@ impl Ast { i } - fn set_fn_decl(&mut self, i: Index, proto: Index, body: Index, loc: SourceLocation) { - self.set_tag_data_source_loc(i, Tag::FunctionDecl, Data::two_indices(proto, body), loc); + fn set_fn_decl( + &mut self, + i: Index, + proto: Index, + body: Index, + loc: SourceLocation, + ) { + self.set_tag_data_source_loc( + i, + Tag::FunctionDecl, + Data::two_indices(proto, body), + loc, + ); } - fn push_fn_decl(&mut self, proto: Index, body: Index, loc: SourceLocation) -> Index { + fn push_fn_decl( + &mut self, + proto: Index, + body: Index, + loc: SourceLocation, + ) -> Index { let i = self.reserve_node(); self.set_fn_decl(i, proto, body, loc); i @@ -593,10 +637,18 @@ impl Ast { fn push_ret(&mut self, expr: Option, loc: SourceLocation) -> Index { let i = self.reserve_node(); match expr { - Some(expr) => { - self.set_tag_data_source_loc(i, Tag::ReturnExprStmt, Data::index(expr), loc) - } - None => self.set_tag_data_source_loc(i, Tag::ReturnStmt, Data::none(), loc), + Some(expr) => self.set_tag_data_source_loc( + i, + Tag::ReturnExprStmt, + Data::index(expr), + loc, + ), + None => self.set_tag_data_source_loc( + i, + Tag::ReturnStmt, + Data::none(), + loc, + ), } i @@ -625,7 +677,12 @@ impl Ast { (false, true) => Tag::MutVarDeclAssignment, }; - self.set_tag_data_source_loc(i, tag, Data::extra_range(start, end), loc); + self.set_tag_data_source_loc( + i, + tag, + Data::extra_range(start, end), + loc, + ); i } @@ -638,8 +695,8 @@ impl Ast { loc: SourceLocation, ) -> Index { let i = self.reserve_node(); - let (extra_start, _) = - self.extend_extra([return_type.into_u32(), parameter_list.into_u32()]); + let (extra_start, _) = self + .extend_extra([return_type.into_u32(), parameter_list.into_u32()]); self.set_tag_data_source_loc( i, Tag::FunctionProto, @@ -657,8 +714,9 @@ impl Ast { trailing: Option, loc: SourceLocation, ) { - let (extra_start, extra_end) = - self.extend_extra_by_indices(statements.into_iter().chain(trailing.into_iter())); + let (extra_start, extra_end) = self.extend_extra_by_indices( + statements.into_iter().chain(trailing.into_iter()), + ); if trailing.is_some() { self.set_tag_data_source_loc( i, @@ -728,9 +786,19 @@ impl Ast { i } - fn push_parameter(&mut self, name: intern::Index, ty: Index, loc: SourceLocation) -> Index { + fn push_parameter( + &mut self, + name: intern::Index, + ty: Index, + loc: SourceLocation, + ) -> Index { let i = self.reserve_node(); - self.set_tag_data_source_loc(i, Tag::Parameter, Data::index_and_intern(ty, name), loc); + self.set_tag_data_source_loc( + i, + Tag::Parameter, + Data::index_and_intern(ty, name), + loc, + ); i } @@ -752,37 +820,78 @@ impl Ast { i } - fn push_unary(&mut self, tag: Tag, lhs: Index, loc: SourceLocation) -> Index { + fn push_unary( + &mut self, + tag: Tag, + lhs: Index, + loc: SourceLocation, + ) -> Index { let i = self.reserve_node(); self.set_tag_data_source_loc(i, tag, Data::index(lhs), loc); i } - fn push_binary(&mut self, tag: Tag, lhs: Index, rhs: Index, loc: SourceLocation) -> Index { + fn push_binary( + &mut self, + tag: Tag, + lhs: Index, + rhs: Index, + loc: SourceLocation, + ) -> Index { let i = self.reserve_node(); self.set_tag_data_source_loc(i, tag, Data::two_indices(lhs, rhs), loc); i } - fn push_assign(&mut self, lhs: Index, rhs: Index, loc: SourceLocation) -> Index { + fn push_assign( + &mut self, + lhs: Index, + rhs: Index, + loc: SourceLocation, + ) -> Index { let i = self.reserve_node(); - self.set_tag_data_source_loc(i, Tag::Assign, Data::two_indices(lhs, rhs), loc); + self.set_tag_data_source_loc( + i, + Tag::Assign, + Data::two_indices(lhs, rhs), + loc, + ); i } - fn push_cast(&mut self, lhs: Index, ty: Index, loc: SourceLocation) -> Index { + fn push_cast( + &mut self, + lhs: Index, + ty: Index, + loc: SourceLocation, + ) -> Index { let i = self.reserve_node(); - self.set_tag_data_source_loc(i, Tag::ExplicitCast, Data::two_indices(lhs, ty), loc); + self.set_tag_data_source_loc( + i, + Tag::ExplicitCast, + Data::two_indices(lhs, ty), + loc, + ); i } - fn push_if(&mut self, cond: Index, body: Index, loc: SourceLocation) -> Index { + fn push_if( + &mut self, + cond: Index, + body: Index, + loc: SourceLocation, + ) -> Index { let i = self.reserve_node(); - self.set_tag_data_source_loc(i, Tag::IfExpr, Data::two_indices(cond, body), loc); + self.set_tag_data_source_loc( + i, + Tag::IfExpr, + Data::two_indices(cond, body), + loc, + ); i } @@ -806,9 +915,19 @@ impl Ast { i } - fn push_call_expr(&mut self, lhs: Index, args: Index, loc: SourceLocation) -> Index { + fn push_call_expr( + &mut self, + lhs: Index, + args: Index, + loc: SourceLocation, + ) -> Index { let i = self.reserve_node(); - self.set_tag_data_source_loc(i, Tag::CallExpr, Data::two_indices(lhs, args), loc); + self.set_tag_data_source_loc( + i, + Tag::CallExpr, + Data::two_indices(lhs, args), + loc, + ); i } @@ -859,9 +978,19 @@ impl Ast { i } - fn push_field_decl(&mut self, name: intern::Index, ty: Index, loc: SourceLocation) -> Index { + fn push_field_decl( + &mut self, + name: intern::Index, + ty: Index, + loc: SourceLocation, + ) -> Index { let i = self.reserve_node(); - self.set_tag_data_source_loc(i, Tag::FieldDecl, Data::index_and_intern(ty, name), loc); + self.set_tag_data_source_loc( + i, + Tag::FieldDecl, + Data::index_and_intern(ty, name), + loc, + ); i } @@ -873,14 +1002,28 @@ impl Ast { loc: SourceLocation, ) -> Index { let i = self.reserve_node(); - self.set_tag_data_source_loc(i, Tag::FieldAccess, Data::index_and_intern(expr, name), loc); + self.set_tag_data_source_loc( + i, + Tag::FieldAccess, + Data::index_and_intern(expr, name), + loc, + ); i } - fn push_interend_type(&mut self, ty: intern::Index, loc: SourceLocation) -> Index { + fn push_interend_type( + &mut self, + ty: intern::Index, + loc: SourceLocation, + ) -> Index { let i = self.reserve_node(); - self.set_tag_data_source_loc(i, Tag::InternedType, Data::intern(ty), loc); + self.set_tag_data_source_loc( + i, + Tag::InternedType, + Data::intern(ty), + loc, + ); i } @@ -902,7 +1045,12 @@ impl Ast { i } - fn push_pointer_type(&mut self, ty: Index, flags: PointerFlags, loc: SourceLocation) -> Index { + fn push_pointer_type( + &mut self, + ty: Index, + flags: PointerFlags, + loc: SourceLocation, + ) -> Index { let i = self.reserve_node(); self.set_tag_data_source_loc( i, @@ -944,23 +1092,45 @@ impl Ast { i } - fn push_constant(&mut self, value: intern::Index, ty: Index, loc: SourceLocation) -> Index { + fn push_constant( + &mut self, + value: intern::Index, + ty: Index, + loc: SourceLocation, + ) -> Index { let i = self.reserve_node(); - self.set_tag_data_source_loc(i, Tag::Constant, Data::index_and_intern(ty, value), loc); + self.set_tag_data_source_loc( + i, + Tag::Constant, + Data::index_and_intern(ty, value), + loc, + ); i } - fn extend_extra_by_indices>(&mut self, indices: I) -> (u32, u32) { + fn extend_extra_by_indices>( + &mut self, + indices: I, + ) -> (u32, u32) { self.extend_extra(indices.into_iter().map(|i| i.0.get())) } - fn extend_extra>(&mut self, words: I) -> (u32, u32) { + fn extend_extra>( + &mut self, + words: I, + ) -> (u32, u32) { let i = self.extra.len() as u32; self.extra.extend(words); (i, self.extra.len() as u32) } - fn set_tag_data_source_loc(&mut self, index: Index, tag: Tag, data: Data, loc: SourceLocation) { + fn set_tag_data_source_loc( + &mut self, + index: Index, + tag: Tag, + data: Data, + loc: SourceLocation, + ) { self.tags[index.index()] = tag; self.datas[index.index()] = data; self.source_locs[index.index()] = loc; @@ -1049,12 +1219,16 @@ impl Ast { let (_, a) = data.as_intern_and_extra_offset(); self.get_type_of_node(ip, cache, Index::new(self.extra[a])) } - 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 => { let (_, i) = data.as_intern_and_extra_offset(); - let return_type = { self.datas[self.extra[i] as usize].as_intern() }; + let return_type = + { self.datas[self.extra[i] as usize].as_intern() }; let parameters = { - let (a, b) = self.datas[self.extra[i + 1] as usize].as_extra_range(); + let (a, b) = + self.datas[self.extra[i + 1] as usize].as_extra_range(); self.extra[a..b].iter().map(|&i| { // i is index to a parameter, a parameter is (index, intern) let ty = self.datas[i as usize].as_index_intern().0; @@ -1071,7 +1245,9 @@ impl Ast { Tag::CallExpr => { let (expr, _args) = data.as_two_indices(); let fn_ty = self.get_type_of_node(ip, cache, expr); - if let intern::Key::FunctionType { return_type, .. } = ip.get_key(fn_ty) { + if let intern::Key::FunctionType { return_type, .. } = + ip.get_key(fn_ty) + { return_type } else { eprintln!("lhs of call expr is not a function!"); @@ -1092,7 +1268,8 @@ impl Ast { let ty = self.get_type_of_node(ip, cache, ty_expr); match ip.get_key(ty) { intern::Key::PointerType { pointee, .. } - if let intern::Key::StructType { fields, .. } = ip.get_key(pointee) => + if let intern::Key::StructType { fields, .. } = + ip.get_key(pointee) => { fields .iter() @@ -1114,7 +1291,8 @@ impl Ast { } Tag::Deref => { 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) + { pointee } else { eprintln!("lhs of deref is not a pointer!"); @@ -1122,12 +1300,15 @@ impl Ast { } } Tag::SubscriptExpr => { - let ty = self.get_type_of_node(ip, cache, data.as_two_indices().0); + 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!"); + eprintln!( + "lhs of subscript is not an array or pointer!" + ); void } } @@ -1137,7 +1318,9 @@ impl Ast { // TODO: find out of the expression is const, volatile for flags ip.try_get_pointer_type(ty, None).unwrap() } - Tag::Not | Tag::Negate => self.get_type_of_node(ip, cache, data.as_index()), + Tag::Not | Tag::Negate => { + self.get_type_of_node(ip, cache, data.as_index()) + } Tag::Or | Tag::And | Tag::BitOr @@ -1155,7 +1338,9 @@ impl Ast { | Tag::Sub | Tag::Mul | Tag::Div - | Tag::Rem => self.get_type_of_node(ip, cache, data.as_two_indices().0), + | Tag::Rem => { + self.get_type_of_node(ip, cache, data.as_two_indices().0) + } Tag::IfExpr => ip.get_bool_type(), // really? Tag::IfElseExpr => { let (_, b) = data.as_index_and_extra_offset(); @@ -1176,11 +1361,14 @@ impl Ast { | Tag::Error | Tag::Undefined | Tag::ReturnStmt => void, - Tag::FieldDecl => self.get_type_of_node(ip, cache, data.as_index_intern().0), - Tag::InternedType => data.as_intern(), - Tag::TypeDeclRef | Tag::TypeDeclRefUnresolved | Tag::PointerType | Tag::ArrayType => { - ip.get_void_type() + Tag::FieldDecl => { + self.get_type_of_node(ip, cache, data.as_index_intern().0) } + Tag::InternedType => data.as_intern(), + Tag::TypeDeclRef + | Tag::TypeDeclRefUnresolved + | Tag::PointerType + | Tag::ArrayType => ip.get_void_type(), }; cache.insert(index, ty); @@ -1317,7 +1505,11 @@ impl Ast { } } - fn is_node_comptime_evaluable(&self, cache: &mut ComptimeCache, index: Index) -> bool { + fn is_node_comptime_evaluable( + &self, + cache: &mut ComptimeCache, + index: Index, + ) -> bool { if let Some(a) = cache.get(&index) { a } else { @@ -1326,15 +1518,20 @@ impl Ast { let children = self.get_node_children(index); - let are_children_comptime = |this: &Self, cache: &mut ComptimeCache| { - children - .iter() - .all(|&i| this.is_node_comptime_evaluable(cache, i)) - }; + let are_children_comptime = + |this: &Self, cache: &mut ComptimeCache| { + children + .iter() + .all(|&i| this.is_node_comptime_evaluable(cache, i)) + }; let is_comptime = match tag { Tag::Parameter => false, - // Tag::Block | Tag::BlockTrailingExpr => are_children_comptime(self, cache), + // TODO: figure out if there are function protos that arent const + Tag::FunctionProto => true, + Tag::FunctionDecl | Tag::Block | Tag::BlockTrailingExpr => { + are_children_comptime(self, cache) + } Tag::Constant => true, Tag::ReturnStmt => true, Tag::ReturnExprStmt => are_children_comptime(self, cache), @@ -1344,22 +1541,29 @@ impl Ast { Tag::GlobalDecl => true, Tag::StructDecl => true, Tag::FieldDecl => true, - Tag::DeclRef => self.tags[data.as_index().index()] == Tag::GlobalDecl, - Tag::InternedType | Tag::PointerType | Tag::ArrayType | Tag::TypeDeclRef => true, - // Tag::CallExpr => are_children_comptime(self, cache), + Tag::DeclRef => { + self.tags[data.as_index().index()] == Tag::GlobalDecl + } + Tag::InternedType + | Tag::PointerType + | Tag::ArrayType + | Tag::TypeDeclRef => true, + Tag::CallExpr => are_children_comptime(self, cache), // Tag::FieldAccess => { // let parent = data.as_index_intern().0; // cache.mark_as_dominated_by(index, parent); // self.is_node_comptime_evaluable(cache, parent) // } Tag::ArgumentList => are_children_comptime(self, cache), - Tag::Argument => self.is_node_comptime_evaluable(cache, data.as_index()), - Tag::NamedArgument => { - self.is_node_comptime_evaluable(cache, data.as_index_intern().0) - } - Tag::ExplicitCast => { - self.is_node_comptime_evaluable(cache, data.as_two_indices().0) + Tag::Argument => { + self.is_node_comptime_evaluable(cache, data.as_index()) } + Tag::NamedArgument => self.is_node_comptime_evaluable( + cache, + data.as_index_intern().0, + ), + Tag::ExplicitCast => self + .is_node_comptime_evaluable(cache, data.as_two_indices().0), Tag::Deref | Tag::AddressOf => false, Tag::Not | Tag::Negate @@ -1390,8 +1594,6 @@ impl Ast { // Tag::IfExpr | Tag::IfElseExpr => are_children_comptime(self, cache), Tag::Root | Tag::File - | Tag::FunctionProto - | Tag::FunctionDecl | Tag::ParameterList | Tag::ExprStmt | Tag::DeclRefUnresolved @@ -1439,16 +1641,27 @@ impl Ast { } Tag::VarDeclAssignment => { let (a, _) = data.as_extra_range(); - self.comptime_value_of_node(ip, pointer_bits, cache, Index::new(self.extra[a + 1])) + self.comptime_value_of_node( + ip, + pointer_bits, + cache, + Index::new(self.extra[a + 1]), + ) } - Tag::DeclRef => self.comptime_value_of_node(ip, pointer_bits, cache, data.as_index()), + 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.index()].as_intern(), ); - let val = self.comptime_value_of_node(ip, pointer_bits, cache, expr); + let val = + self.comptime_value_of_node(ip, pointer_bits, cache, expr); val.and_then(|i| i.explicit_cast(ty).ok()) } Tag::Add => { @@ -1700,27 +1913,41 @@ fn interned_type_and_value_to_comptime_number( intern::Key::SIntType { bits } | intern::Key::UIntType { bits } => { let ty = IntegralType::new(false, bits); match ip.get_key(val) { - intern::Key::SIntSmall { bits } => ComptimeNumber::Integral(ComptimeInt::Native { - bits: bits as _, - ty, - }), - intern::Key::UIntSmall { bits } => ComptimeNumber::Integral(ComptimeInt::Native { - bits: bits as _, - ty, - }), - intern::Key::SInt64 { bits } => ComptimeNumber::Integral(ComptimeInt::Native { - bits: bits as _, - ty, - }), - intern::Key::UInt64 { bits } => ComptimeNumber::Integral(ComptimeInt::Native { - bits: bits as _, - ty, - }), + intern::Key::SIntSmall { bits } => { + ComptimeNumber::Integral(ComptimeInt::Native { + bits: bits as _, + ty, + }) + } + intern::Key::UIntSmall { bits } => { + ComptimeNumber::Integral(ComptimeInt::Native { + bits: bits as _, + ty, + }) + } + intern::Key::SInt64 { bits } => { + ComptimeNumber::Integral(ComptimeInt::Native { + bits: bits as _, + ty, + }) + } + intern::Key::UInt64 { bits } => { + ComptimeNumber::Integral(ComptimeInt::Native { + bits: bits as _, + ty, + }) + } intern::Key::PositiveInt { bigint } => { - ComptimeNumber::Integral(ComptimeInt::BigInt { bits: bigint, ty }) + ComptimeNumber::Integral(ComptimeInt::BigInt { + bits: bigint, + ty, + }) } intern::Key::NegativeInt { bigint } => { - ComptimeNumber::Integral(ComptimeInt::BigInt { bits: bigint, ty }) + ComptimeNumber::Integral(ComptimeInt::BigInt { + bits: bigint, + ty, + }) } _ => { unreachable!() @@ -1774,19 +2001,29 @@ fn interned_type_and_value_to_comptime_number( ty, }) } - intern::Key::SInt64 { bits } => ComptimeNumber::Integral(ComptimeInt::Native { - bits: bits as _, - ty, - }), - intern::Key::UInt64 { bits } => ComptimeNumber::Integral(ComptimeInt::Native { - bits: bits as _, - ty, - }), + intern::Key::SInt64 { bits } => { + ComptimeNumber::Integral(ComptimeInt::Native { + bits: bits as _, + ty, + }) + } + intern::Key::UInt64 { bits } => { + ComptimeNumber::Integral(ComptimeInt::Native { + bits: bits as _, + ty, + }) + } intern::Key::PositiveInt { bigint } => { - ComptimeNumber::Integral(ComptimeInt::BigInt { bits: bigint, ty }) + ComptimeNumber::Integral(ComptimeInt::BigInt { + bits: bigint, + ty, + }) } intern::Key::NegativeInt { bigint } => { - ComptimeNumber::Integral(ComptimeInt::BigInt { bits: bigint, ty }) + ComptimeNumber::Integral(ComptimeInt::BigInt { + bits: bigint, + ty, + }) } _ => { unreachable!() @@ -1807,9 +2044,8 @@ fn interned_type_and_value_to_comptime_number( intern::Key::UInt64 { bits } => { BigInt::from_signed_bytes_le(&bits.to_le_bytes()) } - intern::Key::PositiveInt { bigint } | intern::Key::NegativeInt { bigint } => { - bigint - } + intern::Key::PositiveInt { bigint } + | intern::Key::NegativeInt { bigint } => bigint, _ => { unreachable!() } @@ -1844,9 +2080,9 @@ impl<'a> Display for NodeDisplay<'a> { let loc = self.ast.source_locs[node.index()]; let children = Children(self.ast.get_node_children(node)); - let ty = self - .ast - .get_type_of_node(self.ip, &mut TypeCache::new(), node); + let ty = + self.ast + .get_type_of_node(self.ip, &mut TypeCache::new(), node); let is_comptime = self .ast @@ -1978,7 +2214,8 @@ pub mod ast_gen { pub fn create_comptime_folding_graph(&mut self, pointer_bits: u16) { let mut type_cache = TypeCache::new(); let mut cache = ComptimeCache::default(); - let mut nodes = self.ast.get_root_file_indices().collect::>(); + let mut nodes = + self.ast.get_root_file_indices().collect::>(); while let Some(node) = nodes.pop() { if !self.ast.is_node_comptime_evaluable(&mut cache, node) { nodes.extend(self.ast.get_node_children(node)); @@ -1990,19 +2227,25 @@ pub mod ast_gen { .inner .iter() .filter(|(_, b)| **b) - .map(|(e, _)| self.ast.get_node_children(*e).into_iter().map(|d| (*e, d))) + .map(|(e, _)| { + self.ast.get_node_children(*e).into_iter().map(|d| (*e, d)) + }) .flatten() // .map(|(a, b)| (a.into_u32(), b.into_u32())) .map(|(a, b)| { ( - node_map.iter().position(|&i| i == a).unwrap_or_else(|| { - node_map.push(a); - node_map.len() - 1 - }) as u32, - node_map.iter().position(|&i| i == b).unwrap_or_else(|| { - node_map.push(b); - node_map.len() - 1 - }) as u32, + node_map.iter().position(|&i| i == a).unwrap_or_else( + || { + node_map.push(a); + node_map.len() - 1 + }, + ) as u32, + node_map.iter().position(|&i| i == b).unwrap_or_else( + || { + node_map.push(b); + node_map.len() - 1 + }, + ) as u32, ) }) .collect::>(); @@ -2011,14 +2254,19 @@ pub mod ast_gen { .inner .iter() .filter(|(i, b)| **b) - .filter_map(|(i, _)| (!node_map.contains(i)).then(|| node_map.push(*i))) + .filter_map(|(i, _)| { + (!node_map.contains(i)).then(|| node_map.push(*i)) + }) .count(); eprintln!("cache: {cache:?}"); eprintln!("node_map: {node_map:?}"); eprintln!("edges: {edges:?}"); - let mut graph = petgraph::stable_graph::StableDiGraph::<(), ()>::from_edges(edges); + let mut graph = + petgraph::stable_graph::StableDiGraph::<(), ()>::from_edges( + edges, + ); for _ in 0..extra_nodes { graph.add_node(()); } @@ -2031,14 +2279,19 @@ pub mod ast_gen { &[], &|graph, edgeref| { "".to_string() }, &|graph, noderef| { - format!("label = \"{}\"", node_map[noderef.0.index()]) + format!( + "label = \"{}\"", + node_map[noderef.0.index()] + ) } ) ), ) .expect("writing comptime graph repr"); - while let Some(external) = graph.externals(petgraph::Direction::Outgoing).next() { + while let Some(external) = + graph.externals(petgraph::Direction::Outgoing).next() + { let node = node_map[external.index()]; if !(self.ast.tags[node.index()] == Tag::Constant || self.ast.tags[node.index()].is_type()) @@ -2047,14 +2300,21 @@ pub mod ast_gen { eprintln!("folding {node}:\n{}", self.node_display(node)); let value = self .ast - .comptime_value_of_node(&self.intern, pointer_bits, &mut type_cache, node) + .comptime_value_of_node( + &self.intern, + pointer_bits, + &mut type_cache, + node, + ) .expect(&format!("{node} has value of None?")); - let (value, ty) = comptime_number_to_interned_type_and_value( - &mut self.intern, - pointer_bits, - value, - ); - let ty = self.ast.push_interend_type(ty, self.ast.get_loc(node)); + let (value, ty) = + comptime_number_to_interned_type_and_value( + &mut self.intern, + pointer_bits, + value, + ); + let ty = + self.ast.push_interend_type(ty, self.ast.get_loc(node)); self.ast.set_tag_data_source_loc( node, Tag::Constant, @@ -2098,33 +2358,53 @@ pub mod ast_gen { match tag { Tag::ArrayType => { let (length, pointee) = data.as_two_indices(); - let pointee = self.ast.datas[pointee.index()].as_intern(); + let pointee = + self.ast.datas[pointee.index()].as_intern(); variant!( self.intern.get_key(pointee) => intern::Key::PointerType { pointee, flags }); // get interened value from constant node let length = { - let value = self.ast.datas[length.index()].as_index_intern().1; + let value = self.ast.datas[length.index()] + .as_index_intern() + .1; match self.intern.get_key(value) { - intern::Key::SIntSmall { bits } => bits as u32, - intern::Key::UIntSmall { bits } => bits as u32, - intern::Key::SInt64 { bits } => bits as u32, - intern::Key::UInt64 { bits } => bits as u32, + intern::Key::SIntSmall { bits } => { + bits as u32 + } + intern::Key::UIntSmall { bits } => { + bits as u32 + } + intern::Key::SInt64 { bits } => { + bits as u32 + } + intern::Key::UInt64 { bits } => { + bits as u32 + } intern::Key::NegativeInt { bigint } | intern::Key::PositiveInt { bigint } => { - bigint.iter_u32_digits().next().unwrap_or(0) + bigint + .iter_u32_digits() + .next() + .unwrap_or(0) } _ => 0, } }; - let ty = self.intern.get_array_type(pointee, Some(flags), length); + let ty = self.intern.get_array_type( + pointee, + Some(flags), + length, + ); self.ast.tags[i.index()] = Tag::InternedType; self.ast.datas[i.index()] = Data::intern(ty); } Tag::PointerType => { - let (pointee, flags) = data.as_index_and_extra_offset(); - let pointee = self.ast.datas[pointee.index()].as_intern(); + let (pointee, flags) = + data.as_index_and_extra_offset(); + let pointee = + self.ast.datas[pointee.index()].as_intern(); let ty = self.intern.get_pointer_type( pointee, Some(PointerFlags::unpack(flags as u8)), @@ -2134,10 +2414,11 @@ pub mod ast_gen { } Tag::TypeDeclRef => { let decl = data.as_index(); - let (name, _) = - self.ast.datas[decl.index()].as_intern_and_extra_offset(); + let (name, _) = self.ast.datas[decl.index()] + .as_intern_and_extra_offset(); - let ty = self.intern.get_struct_type(name, decl); + let ty = + self.intern.get_struct_type(name, decl); self.ast.tags[i.index()] = Tag::InternedType; self.ast.datas[i.index()] = Data::intern(ty); } @@ -2149,30 +2430,44 @@ pub mod ast_gen { Index::new(self.ast.extra[i]), ); let parameters = { - let (a, b) = self.ast.datas[self.ast.extra[i + 1] as usize] + let (a, b) = self.ast.datas + [self.ast.extra[i + 1] as usize] .as_extra_range(); self.ast.extra[a..b].iter().map(|&i| { // i is index to a parameter, a parameter is (index, intern) - let ty = self.ast.datas[i as usize].as_index_intern().0; + let ty = self.ast.datas[i as usize] + .as_index_intern() + .0; self.ast.datas[ty.index()].as_intern() }) }; - self.intern.get_function_type(return_type, parameters); + self.intern + .get_function_type(return_type, parameters); } Tag::StructDecl => { - let (name, offset) = data.as_intern_and_extra_offset(); - let flags = StructFlags::unpack(self.ast.extra[offset]); + let (name, offset) = + data.as_intern_and_extra_offset(); + let flags = + StructFlags::unpack(self.ast.extra[offset]); - let types = (offset + 1)..(offset + 1 + flags.num_fields as usize); - let names = (offset + 1 + flags.num_fields as usize) - ..(offset + 1 + flags.num_fields as usize * 2); + let types = (offset + 1) + ..(offset + 1 + flags.num_fields as usize); + let names = + (offset + 1 + flags.num_fields as usize) + ..(offset + + 1 + + flags.num_fields as usize * 2); let types = self.ast.extra[types] .iter() .map(|&i| Index::new(i)) - .map(|i| self.ast.datas[i.index()].as_intern()); - let names = self.ast.extra[names].iter().map(|&i| intern::Index(i)); + .map(|i| { + self.ast.datas[i.index()].as_intern() + }); + let names = self.ast.extra[names] + .iter() + .map(|&i| intern::Index(i)); self.intern.insert_or_replace_struct_type( name, @@ -2190,12 +2485,16 @@ pub mod ast_gen { } pub fn resolve_decl_refs(&mut self) { - let mut nodes = self.ast.get_root_file_indices().collect::>(); + let mut nodes = + self.ast.get_root_file_indices().collect::>(); let mut scopes = Vec::new(); while let Some(node) = nodes.pop() { match self.ast.tags[node.index()] { - Tag::File | Tag::FunctionDecl | Tag::Block | Tag::BlockTrailingExpr => { + Tag::File + | Tag::FunctionDecl + | Tag::Block + | Tag::BlockTrailingExpr => { scopes.push(node); } _ => {} @@ -2205,11 +2504,15 @@ pub mod ast_gen { nodes.extend(children.into_iter().rev()); match self.ast.tags[node.index()] { - Tag::File | Tag::FunctionDecl | Tag::Block | Tag::BlockTrailingExpr => { + Tag::File + | Tag::FunctionDecl + | Tag::Block + | Tag::BlockTrailingExpr => { scopes.pop(); } Tag::TypeDeclRefUnresolved => { - let (scope, name) = self.ast.datas[node.index()].as_index_intern(); + let (scope, name) = + self.ast.datas[node.index()].as_index_intern(); // look in my_scope if let Some(decl) = self.syms.find_type_symbol( scope, @@ -2220,13 +2523,15 @@ pub mod ast_gen { }; } Tag::DeclRefUnresolved => { - let (scope, name) = self.ast.datas[node.index()].as_index_intern(); + let (scope, name) = + self.ast.datas[node.index()].as_index_intern(); // look in my_scope - if let Some(decl) = - self.syms - .find_symbol(scope, name, self.ast.source_locs[node.index()]) - { + if let Some(decl) = self.syms.find_symbol( + scope, + name, + self.ast.source_locs[node.index()], + ) { self.ast.resolve_decl_ref(node, decl) }; } @@ -2239,11 +2544,15 @@ pub mod ast_gen { self.scopes.last().cloned().unwrap() } - fn parse_ident(&mut self, tokens: &mut TokenIterator) -> Result { - let ident = tokens.expect_token(Token::Ident).map_err(|_| ErrorInfo { - error: ParseError::ExpectedIdent, - loc: tokens.current_source_location(), - })?; + fn parse_ident( + &mut self, + tokens: &mut TokenIterator, + ) -> Result { + let ident = + tokens.expect_token(Token::Ident).map_err(|_| ErrorInfo { + error: ParseError::ExpectedIdent, + loc: tokens.current_source_location(), + })?; let name = self.intern.get_or_insert(intern::Key::String { str: ident.lexeme(), @@ -2252,83 +2561,110 @@ pub mod ast_gen { Ok(name) } - fn parse_pointer(&mut self, tokens: &mut TokenIterator) -> ParseResult { + fn parse_pointer( + &mut self, + tokens: &mut TokenIterator, + ) -> ParseResult { let loc = tokens.current_source_location(); tokens.eat_token(Token::Star).ok_or(ErrorInfo { error: ParseError::ExpectedToken(Token::Star), loc: tokens.current_source_location(), })?; - let &[cnst, vol, noalias] = - &tokens.eat_all_zero_or_once(&[Token::Const, Token::Volatile, Token::Noalias])[..3] - else { + let &[cnst, vol, noalias] = &tokens.eat_all_zero_or_once(&[ + Token::Const, + Token::Volatile, + Token::Noalias, + ])[..3] else { unreachable!() }; let pointee = self.parse_type(tokens)?; - Ok(self - .ast - .push_pointer_type(pointee, PointerFlags::new(cnst, vol, noalias), loc)) + Ok(self.ast.push_pointer_type( + pointee, + PointerFlags::new(cnst, vol, noalias), + loc, + )) } /// [LENGTH]const? volatile? noalias? TYPE - fn parse_array_type(&mut self, tokens: &mut TokenIterator) -> ParseResult { + fn parse_array_type( + &mut self, + tokens: &mut TokenIterator, + ) -> ParseResult { let loc = tokens.current_source_location(); - let length_expr = self.parse_bracketed(tokens, |this, tokens| { - this.parse_expr(tokens) - // let next = tokens.peek_token().ok_or(ErrorInfo { - // error: ParseError::UnexpectedEndOfTokens, - // loc: tokens.current_source_location(), - // })?; - // match next.token() { - // Token::IntegerBinConstant - // | Token::IntegerHexConstant - // | Token::IntegerOctConstant - // | Token::IntegerConstant => { - // _ = tokens.next(); - // Ok(this.parse_integral_constant(&next, next.source_location())) - // } - // _ => Err(ErrorInfo { - // error: ParseError::ExpectedConstantLiteral, - // loc: tokens.current_source_location(), - // }), - // } - })?; + let length_expr = + self.parse_bracketed(tokens, |this, tokens| { + this.parse_expr(tokens) + // let next = tokens.peek_token().ok_or(ErrorInfo { + // error: ParseError::UnexpectedEndOfTokens, + // loc: tokens.current_source_location(), + // })?; + // match next.token() { + // Token::IntegerBinConstant + // | Token::IntegerHexConstant + // | Token::IntegerOctConstant + // | Token::IntegerConstant => { + // _ = tokens.next(); + // Ok(this.parse_integral_constant(&next, next.source_location())) + // } + // _ => Err(ErrorInfo { + // error: ParseError::ExpectedConstantLiteral, + // loc: tokens.current_source_location(), + // }), + // } + })?; - let &[cnst, vol, noalias] = - &tokens.eat_all_zero_or_once(&[Token::Const, Token::Volatile, Token::Noalias])[..3] - else { + let &[cnst, vol, noalias] = &tokens.eat_all_zero_or_once(&[ + Token::Const, + Token::Volatile, + Token::Noalias, + ])[..3] else { unreachable!() }; let pointee = self.parse_type(tokens)?; - let pointer = - self.ast - .push_pointer_type(pointee, PointerFlags::new(cnst, vol, noalias), loc); + let pointer = self.ast.push_pointer_type( + pointee, + PointerFlags::new(cnst, vol, noalias), + loc, + ); Ok(self.ast.push_array_type(length_expr, pointer, loc)) } fn parse_simple_type(&mut self, token: Token) -> Option { match token { - Token::Void => Some(self.intern.get_assume_present(&intern::Key::SimpleType { - ty: SimpleType::Void, - })), - Token::Bool => Some(self.intern.get_assume_present(&intern::Key::SimpleType { - ty: SimpleType::Bool, - })), - Token::F32 => Some(self.intern.get_assume_present(&intern::Key::SimpleType { - ty: SimpleType::F32, - })), - Token::F64 => Some(self.intern.get_assume_present(&intern::Key::SimpleType { - ty: SimpleType::F64, - })), - Token::USize => Some(self.intern.get_assume_present(&intern::Key::SimpleType { - ty: SimpleType::USize, - })), - Token::ISize => Some(self.intern.get_assume_present(&intern::Key::SimpleType { - ty: SimpleType::ISize, - })), + Token::Void => Some(self.intern.get_assume_present( + &intern::Key::SimpleType { + ty: SimpleType::Void, + }, + )), + Token::Bool => Some(self.intern.get_assume_present( + &intern::Key::SimpleType { + ty: SimpleType::Bool, + }, + )), + Token::F32 => Some(self.intern.get_assume_present( + &intern::Key::SimpleType { + ty: SimpleType::F32, + }, + )), + Token::F64 => Some(self.intern.get_assume_present( + &intern::Key::SimpleType { + ty: SimpleType::F64, + }, + )), + Token::USize => Some(self.intern.get_assume_present( + &intern::Key::SimpleType { + ty: SimpleType::USize, + }, + )), + Token::ISize => Some(self.intern.get_assume_present( + &intern::Key::SimpleType { + ty: SimpleType::ISize, + }, + )), _ => None, } } @@ -2404,7 +2740,8 @@ pub mod ast_gen { .map(|(_, c)| c) .collect::>(); - let value = comptime::bigint::parse_bigint(digits.into_iter(), radix); + let value = + comptime::bigint::parse_bigint(digits.into_iter(), radix); let ty = match chars.clone().next() { Some((i, 'u')) | Some((i, 'i')) => self @@ -2425,7 +2762,10 @@ pub mod ast_gen { self.intern.get_or_insert(intern::Key::UInt64 { bits }) } _ => { - let bigint = BigInt::from_biguint(num_bigint::Sign::Plus, BigUint::new(value)); + let bigint = BigInt::from_biguint( + num_bigint::Sign::Plus, + BigUint::new(value), + ); self.intern .get_or_insert(intern::Key::PositiveInt { bigint }) } @@ -2435,13 +2775,21 @@ pub mod ast_gen { (interned, ty) } - fn parse_integral_constant(&mut self, item: &TokenItem, loc: SourceLocation) -> Index { + fn parse_integral_constant( + &mut self, + item: &TokenItem, + loc: SourceLocation, + ) -> Index { let (interned, ty) = self.parse_integral_constant_inner(item); let ty = self.ast.push_interend_type(ty, loc); return self.ast.push_constant(interned, ty, loc); } - fn parse_floating_constant(&mut self, item: &TokenItem, loc: SourceLocation) -> Index { + fn parse_floating_constant( + &mut self, + item: &TokenItem, + loc: SourceLocation, + ) -> Index { let lexeme = item.lexeme(); let lexeme = lexeme .strip_suffix("f32") @@ -2473,7 +2821,10 @@ pub mod ast_gen { /// SIMPLE_TYPE /// [ TYPE ; CONSTANT_EXPR ] /// INTEGRAL_TYPE // u[0..65535] | i[0..65535] - fn parse_type(&mut self, tokens: &mut TokenIterator) -> ParseResult { + fn parse_type( + &mut self, + tokens: &mut TokenIterator, + ) -> ParseResult { let loc = tokens.current_source_location(); match tokens .peek_token() @@ -2487,30 +2838,35 @@ pub mod ast_gen { Token::OpenSquareBracket => self.parse_array_type(tokens), Token::Ident => { let token = tokens.next().unwrap(); - match self - .try_parse_integral_type(token.lexeme()) - .map_err(|error| ErrorInfo { + match self.try_parse_integral_type(token.lexeme()).map_err( + |error| ErrorInfo { error, loc: token.source_location(), - })? { + }, + )? { Some(int) => Ok(self.ast.push_interend_type(int, loc)), None => { - let name = self.intern.get_or_insert(intern::Key::String { - str: token.lexeme(), - }); + let name = self.intern.get_or_insert( + intern::Key::String { + str: token.lexeme(), + }, + ); // TODO: this will cause issues with redefinitions of types with the same name // and actually, make type into a proper node of the ast - Ok(self - .ast - .push_type_ref_unresolved(self.current_scope(), name, loc)) + Ok(self.ast.push_type_ref_unresolved( + self.current_scope(), + name, + loc, + )) } } } token => { - let ty = self.parse_simple_type(token).ok_or(ErrorInfo { - error: ParseError::ExpectedTypeName, - loc: tokens.current_source_location(), - })?; + let ty = + self.parse_simple_type(token).ok_or(ErrorInfo { + error: ParseError::ExpectedTypeName, + loc: tokens.current_source_location(), + })?; _ = tokens.next(); Ok(self.ast.push_interend_type(ty, loc)) @@ -2520,7 +2876,10 @@ pub mod ast_gen { /// GLOBAL_DECL <- /// const IDENTIFIER: TYPENAME = EXPR; - fn parse_const_decl(&mut self, tokens: &mut TokenIterator) -> ParseResult { + fn parse_const_decl( + &mut self, + tokens: &mut TokenIterator, + ) -> ParseResult { let err = 'blk: { let loc = tokens.current_source_location(); let Some(_) = tokens.eat_token(Token::Const) else { @@ -2572,9 +2931,14 @@ pub mod ast_gen { }; }; - let decl = self.ast.push_global_decl(ident, typename, expr, loc); - self.syms - .insert_symbol(self.current_scope(), ident, SymbolKind::Const, decl); + let decl = + self.ast.push_global_decl(ident, typename, expr, loc); + self.syms.insert_symbol( + self.current_scope(), + ident, + SymbolKind::Const, + decl, + ); return Ok(decl); }; @@ -2604,29 +2968,35 @@ pub mod ast_gen { let ident = self.parse_ident(tokens)?; - let parameters = self.parse_parenthesised(tokens, |this, tokens| { - if tokens.is_next_token(Token::CloseParens) { - Ok(this.ast.push_parameter_list([], loc)) - } else { - this.parse_parameter_list(tokens) - } - })?; + let parameters = + self.parse_parenthesised(tokens, |this, tokens| { + if tokens.is_next_token(Token::CloseParens) { + Ok(this.ast.push_parameter_list([], loc)) + } else { + this.parse_parameter_list(tokens) + } + })?; + + let return_type = + if let Some(_) = tokens.eat_token(Token::MinusGreater) { + self.parse_type(tokens)? + } else { + self.ast.push_interend_type( + self.intern.get_void_type(), + tokens.current_source_location(), + ) + }; - let return_type = if let Some(_) = tokens.eat_token(Token::MinusGreater) { - self.parse_type(tokens)? - } else { - self.ast.push_interend_type( - self.intern.get_void_type(), - tokens.current_source_location(), - ) - }; let decl = self.ast.push_fn_proto(ident, return_type, parameters, loc); Ok((decl, ident)) } - fn parse_fn_inner(&mut self, tokens: &mut TokenIterator) -> ParseResult { + fn parse_fn_inner( + &mut self, + tokens: &mut TokenIterator, + ) -> ParseResult { let loc = tokens.current_source_location(); let func = self.ast.reserve_node(); @@ -2669,7 +3039,10 @@ pub mod ast_gen { /// RETURN_STATEMENT <- /// return EXPRESSION? ; - fn parse_return_stmt(&mut self, tokens: &mut TokenIterator) -> ParseResult { + fn parse_return_stmt( + &mut self, + tokens: &mut TokenIterator, + ) -> ParseResult { // SAFETY: function invariance let ret = tokens.next().unwrap(); let loc = ret.source_location(); @@ -2701,7 +3074,10 @@ pub mod ast_gen { /// VAR_DECL <- /// (let | var) IDENTIFIER (: TYPENAME)? ; /// (let | var) IDENTIFIER (: TYPENAME)? = EXPRESSION ; - fn parse_var_decl(&mut self, tokens: &mut TokenIterator) -> ParseResult { + fn parse_var_decl( + &mut self, + tokens: &mut TokenIterator, + ) -> ParseResult { match self.parse_var_decl_inner(tokens) { Ok(i) => { _ = tokens.eat_token(Token::Semi).ok_or(ErrorInfo { @@ -2720,7 +3096,10 @@ pub mod ast_gen { } } - fn parse_var_decl_inner(&mut self, tokens: &mut TokenIterator) -> ParseResult { + fn parse_var_decl_inner( + &mut self, + tokens: &mut TokenIterator, + ) -> ParseResult { // SAFETY: function invariance let let_or_var = tokens.next().unwrap(); let loc = let_or_var.source_location(); @@ -2741,7 +3120,8 @@ pub mod ast_gen { None }; - let decl = self.ast.push_var_decl(is_let, name, ty, assignment, loc); + let decl = + self.ast.push_var_decl(is_let, name, ty, assignment, loc); self.syms.insert_symbol( self.current_scope(), name, @@ -2782,10 +3162,10 @@ pub mod ast_gen { _ => { if self.is_statement(tokens) { // expr -> statements - let expr = self - .parse_with_trailing_semi(tokens, |this, tokens| { - this.parse_expr(tokens) - })?; + let expr = self.parse_with_trailing_semi( + tokens, + |this, tokens| this.parse_expr(tokens), + )?; statements.push(expr); } else { @@ -2811,7 +3191,10 @@ pub mod ast_gen { /// BLOCK <- /// { STATEMENT* EXPRESSION? } - fn parse_block(&mut self, tokens: &mut TokenIterator) -> ParseResult { + fn parse_block( + &mut self, + tokens: &mut TokenIterator, + ) -> ParseResult { let block = self.parse_braced(tokens, |this, tokens| { let block = this.ast.reserve_node(); this.push_scope(block, intern::Index::invalid()); @@ -2827,7 +3210,10 @@ pub mod ast_gen { /// PARAMETER_LIST <- /// PARAMETER /// PARAMETER_LIST , ARGUMENT - fn parse_parameter_list(&mut self, tokens: &mut TokenIterator) -> ParseResult { + fn parse_parameter_list( + &mut self, + tokens: &mut TokenIterator, + ) -> ParseResult { let loc = tokens.current_source_location(); let mut params = Vec::new(); @@ -2849,7 +3235,10 @@ pub mod ast_gen { /// PARAMETER <- /// IDENT : TYPENAME - fn parse_parameter(&mut self, tokens: &mut TokenIterator) -> ParseResult { + fn parse_parameter( + &mut self, + tokens: &mut TokenIterator, + ) -> ParseResult { let loc = tokens.current_source_location(); let name = self.parse_ident(tokens)?; let Some(_) = tokens.eat_token(Token::Colon) else { @@ -2861,8 +3250,12 @@ pub mod ast_gen { let ty = self.parse_type(tokens)?; let param = self.ast.push_parameter(name, ty, loc); - self.syms - .insert_symbol(self.current_scope(), name, SymbolKind::Local(loc), param); + self.syms.insert_symbol( + self.current_scope(), + name, + SymbolKind::Local(loc), + param, + ); return Ok(param); } @@ -2870,9 +3263,13 @@ pub mod ast_gen { /// ARGUMENT <- /// IDENT : EXPR /// EXPR - fn parse_argument(&mut self, tokens: &mut TokenIterator) -> ParseResult { + fn parse_argument( + &mut self, + tokens: &mut TokenIterator, + ) -> ParseResult { let loc = tokens.current_source_location(); - let name = if tokens.is_next_token2(Token::Colon) && tokens.is_next_token(Token::Ident) + let name = if tokens.is_next_token2(Token::Colon) + && tokens.is_next_token(Token::Ident) { let name = self.parse_ident(tokens)?; // we checked `is_next_token2` @@ -2894,7 +3291,10 @@ pub mod ast_gen { /// ARGUMENT_LIST <- /// ARGUMENT /// ARGUMENT_LIST , ARGUMENT - fn parse_argument_list(&mut self, tokens: &mut TokenIterator) -> ParseResult { + fn parse_argument_list( + &mut self, + tokens: &mut TokenIterator, + ) -> ParseResult { let loc = tokens.current_source_location(); let mut args = Vec::new(); loop { @@ -2918,7 +3318,10 @@ pub mod ast_gen { /// FLOATING_CONSTANT /// ( EXPRESSION ) /// BLOCK - fn parse_primary_expr(&mut self, tokens: &mut TokenIterator) -> ParseResult { + fn parse_primary_expr( + &mut self, + tokens: &mut TokenIterator, + ) -> ParseResult { let loc = tokens.current_source_location(); let Some(next) = tokens.peek_token() else { @@ -2934,19 +3337,27 @@ pub mod ast_gen { | Token::IntegerOctConstant | Token::IntegerConstant => { _ = tokens.next(); - return Ok(self.parse_integral_constant(&next, next.source_location())); + return Ok(self.parse_integral_constant( + &next, + next.source_location(), + )); } Token::FloatingConstant | Token::FloatingExpConstant | Token::DotFloatingConstant | Token::DotFloatingExpConstant => { _ = tokens.next(); - return Ok(self.parse_floating_constant(&next, next.source_location())); + return Ok(self.parse_floating_constant( + &next, + next.source_location(), + )); } Token::OpenParens => { - let expr = - self.parse_parenthesised(tokens, |this, tokens| this.parse_expr(tokens))?; + let expr = self + .parse_parenthesised(tokens, |this, tokens| { + this.parse_expr(tokens) + })?; return Ok(expr); } @@ -2959,9 +3370,11 @@ pub mod ast_gen { let ident = self .intern .get_or_insert(intern::Key::String { str: ident }); - return Ok(self - .ast - .push_decl_ref_unresolved(self.current_scope(), ident, loc)); + return Ok(self.ast.push_decl_ref_unresolved( + self.current_scope(), + ident, + loc, + )); } // TODO: eventually handle paths _ => { @@ -2979,9 +3392,14 @@ pub mod ast_gen { /// PRIMARY_EXPR ( ARGUMENT_LIST ) /// PRIMARY_EXPR [ EXPR ] /// POSTFIX_EXPR . IDENTIFIER - fn parse_postfix_expr(&mut self, tokens: &mut TokenIterator) -> ParseResult { + fn parse_postfix_expr( + &mut self, + tokens: &mut TokenIterator, + ) -> ParseResult { let mut lhs = self.parse_primary_expr(tokens)?; - while let Some(postfix) = self.try_parse_postfix_expr_inner(tokens, lhs)? { + while let Some(postfix) = + self.try_parse_postfix_expr_inner(tokens, lhs)? + { lhs = postfix; } @@ -2997,24 +3415,31 @@ pub mod ast_gen { let loc = next.source_location(); match next.token() { Token::OpenParens => { - let arguments = self.parse_parenthesised(tokens, |this, tokens| { - if tokens.is_next_token(Token::CloseParens) { - Ok(this.ast.push_argument_list([], loc)) - } else { - this.parse_argument_list(tokens) - } - })?; + let arguments = self.parse_parenthesised( + tokens, + |this, tokens| { + if tokens.is_next_token(Token::CloseParens) { + Ok(this.ast.push_argument_list([], loc)) + } else { + this.parse_argument_list(tokens) + } + }, + )?; Some(self.ast.push_call_expr(lhs, arguments, loc)) } Token::OpenSquareBracket => { - let subscript = - self.parse_bracketed(tokens, |this, tokens| this.parse_expr(tokens))?; + let subscript = self + .parse_bracketed(tokens, |this, tokens| { + this.parse_expr(tokens) + })?; - Some( - self.ast - .push_binary(Tag::SubscriptExpr, lhs, subscript, loc), - ) + Some(self.ast.push_binary( + Tag::SubscriptExpr, + lhs, + subscript, + loc, + )) } Token::Dot if tokens.is_next_token2(Token::Ident) => { _ = tokens.next(); @@ -3032,7 +3457,11 @@ pub mod ast_gen { Ok(lhs) } - fn push_error(&mut self, error: ParseError, loc: SourceLocation) -> Index { + fn push_error( + &mut self, + error: ParseError, + loc: SourceLocation, + ) -> Index { self.errors.push(ErrorInfo { error, loc }); self.ast.push_error(error, loc) } @@ -3043,7 +3472,10 @@ pub mod ast_gen { /// - POSTFIX_EXPR /// & POSTFIX_EXPR /// * POSTFIX_EXPR - fn parse_prefix_expr(&mut self, tokens: &mut TokenIterator) -> ParseResult { + fn parse_prefix_expr( + &mut self, + tokens: &mut TokenIterator, + ) -> ParseResult { let next = tokens.peek_token().ok_or(ErrorInfo { error: ParseError::ExpectedPrefixExpression, loc: tokens.current_source_location(), @@ -3081,7 +3513,10 @@ pub mod ast_gen { /// AS_EXPR <- /// PREFIX_EXPR /// PREFIX_EXPR as TYPENAME - fn parse_as_expr(&mut self, tokens: &mut TokenIterator) -> ParseResult { + fn parse_as_expr( + &mut self, + tokens: &mut TokenIterator, + ) -> ParseResult { let loc = tokens.current_source_location(); let expr = self.parse_prefix_expr(tokens)?; @@ -3126,7 +3561,8 @@ pub mod ast_gen { break; }; let loc = tok.source_location(); - let Some(prec) = PRECEDENCE_MAP.get(&tok.token()).cloned() else { + let Some(prec) = PRECEDENCE_MAP.get(&tok.token()).cloned() + else { break; }; @@ -3173,7 +3609,10 @@ pub mod ast_gen { /// BINARY_EXPRESSION ASSIGNMENT_OP EXPRESSION /// ASSIGNMENT_OP <- /// = += -= *= /= %= ... - fn parse_assignment_expr(&mut self, tokens: &mut TokenIterator) -> ParseResult { + fn parse_assignment_expr( + &mut self, + tokens: &mut TokenIterator, + ) -> ParseResult { let lhs = self.parse_binary_expr(tokens, 0)?; if tokens @@ -3215,7 +3654,10 @@ pub mod ast_gen { /// ELSE_EXPR <- /// 'else' (IF_EXPR | EXPR_OR_STATEMENT_OR_BLOCK) - fn parse_else_expr(&mut self, tokens: &mut TokenIterator) -> ParseResult { + fn parse_else_expr( + &mut self, + tokens: &mut TokenIterator, + ) -> ParseResult { // SAFETY: function invariance let _else_ = tokens.eat_token(Token::Else).unwrap(); @@ -3228,12 +3670,17 @@ pub mod ast_gen { /// IF_EXPR <- /// 'if' ( EXPR ) EXPR_OR_STATEMENT_OR_BLOCK ELSE_EXPR? - fn parse_if_expr(&mut self, tokens: &mut TokenIterator) -> ParseResult { + fn parse_if_expr( + &mut self, + tokens: &mut TokenIterator, + ) -> ParseResult { // SAFETY: function invariance let iff = tokens.eat_token(Token::If).unwrap(); let loc = iff.source_location(); - let cond = self.parse_parenthesised(tokens, |this, tokens| this.parse_expr(tokens))?; + let cond = self.parse_parenthesised(tokens, |this, tokens| { + this.parse_expr(tokens) + })?; let body = self.parse_expr_or_block_as_block(tokens)?; @@ -3266,7 +3713,10 @@ pub mod ast_gen { } } - fn parse_expr(&mut self, tokens: &mut TokenIterator) -> ParseResult { + fn parse_expr( + &mut self, + tokens: &mut TokenIterator, + ) -> ParseResult { let loc = tokens.current_source_location(); let Some(next) = tokens.peek_token() else { return Err(ErrorInfo { @@ -3287,7 +3737,10 @@ pub mod ast_gen { /// type IDENTIFIER = extern? union { (IDENTIFIER: TYPE,)* } /// type IDENTIFIER = extern? packed? enum { (IDENTIFIER (= EXPRESSION),)* } /// type IDENTIFIER = extern? packed? struct { (IDENTIFIER: TYPE,)* } - fn parse_type_decl(&mut self, tokens: &mut TokenIterator) -> ParseResult { + fn parse_type_decl( + &mut self, + tokens: &mut TokenIterator, + ) -> ParseResult { _ = tokens.eat_token(Token::Type).ok_or(ErrorInfo { error: ParseError::ExpectedToken(Token::Type), loc: tokens.current_source_location(), @@ -3302,7 +3755,8 @@ pub mod ast_gen { }); let (has_attributes, c_like, packed) = { - let vec = tokens.eat_all_zero_or_once(&[Token::Extern, Token::Packed]); + let vec = tokens + .eat_all_zero_or_once(&[Token::Extern, Token::Packed]); (vec[0] || vec[1], vec[0], vec[1]) }; @@ -3314,7 +3768,9 @@ pub mod ast_gen { }; let decl = match next.token() { - Token::Struct => self.parse_struct_decl(tokens, name, c_like, packed, loc), + Token::Struct => { + self.parse_struct_decl(tokens, name, c_like, packed, loc) + } Token::Union => { unimplemented!() } @@ -3347,8 +3803,12 @@ pub mod ast_gen { } }?; - self.syms - .insert_symbol(self.current_scope(), name, SymbolKind::Type, decl); + self.syms.insert_symbol( + self.current_scope(), + name, + SymbolKind::Type, + decl, + ); Ok(decl) } @@ -3358,25 +3818,37 @@ pub mod ast_gen { /// TYPE_UNION <- /// TYPE (| TYPE_UNION)? /// IDENTIFIER: TYPE (| TYPE_UNION)? - fn parse_sumtype_decl(&mut self, tokens: &mut TokenIterator) -> ParseResult { + fn parse_sumtype_decl( + &mut self, + tokens: &mut TokenIterator, + ) -> ParseResult { todo!() } /// TUPLE_DECL <- /// type IDENTIFIER = (TYPE,* ) - fn parse_tuple_decl(&mut self, tokens: &mut TokenIterator) -> ParseResult { + fn parse_tuple_decl( + &mut self, + tokens: &mut TokenIterator, + ) -> ParseResult { todo!() } /// UNION_DECL <- /// type IDENTIFIER = union { IDENTIFIER: TYPE,* } - fn parse_union_decl(&mut self, tokens: &mut TokenIterator) -> ParseResult { + fn parse_union_decl( + &mut self, + tokens: &mut TokenIterator, + ) -> ParseResult { todo!() } /// ENUM_DECL <- /// type IDENTIFIER = packed? enum { IDENTIFIER (= EXPRESSION),* } - fn parse_enum_decl(&mut self, tokens: &mut TokenIterator) -> ParseResult { + fn parse_enum_decl( + &mut self, + tokens: &mut TokenIterator, + ) -> ParseResult { todo!() } @@ -3400,7 +3872,8 @@ pub mod ast_gen { let decl = self.parse_braced(tokens, |this, tokens| { this.parse_struct_fields(tokens).map(|fields| { _ = tokens.eat_token(Token::Comma); - let flags = StructFlags::new(packed, c_like, fields.len() as u32); + let flags = + StructFlags::new(packed, c_like, fields.len() as u32); this.ast.push_struct_decl(name, flags, fields, loc) }) })?; @@ -3445,7 +3918,12 @@ pub mod ast_gen { ) -> ParseResult where F: FnOnce(&mut Self, &mut TokenIterator) -> ParseResult, - E: FnOnce(&mut Self, &mut TokenIterator, ErrorInfo, TokenItem) -> ParseResult, + E: FnOnce( + &mut Self, + &mut TokenIterator, + ErrorInfo, + TokenItem, + ) -> ParseResult, { let Some(start) = tokens.eat_token(open) else { return Err(ErrorInfo { @@ -3458,14 +3936,20 @@ pub mod ast_gen { Ok(i) => { _ = tokens.eat_token(close).ok_or(ErrorInfo { error: match open { - Token::OpenBrace => ParseError::UnmatchedBrace(start.token_pos().start), - Token::OpenParens => { - ParseError::UnmatchedParens(start.token_pos().start) - } + Token::OpenBrace => ParseError::UnmatchedBrace( + start.token_pos().start, + ), + Token::OpenParens => ParseError::UnmatchedParens( + start.token_pos().start, + ), Token::OpenSquareBracket => { - ParseError::UnmatchedSquareBracket(start.token_pos().start) + ParseError::UnmatchedSquareBracket( + start.token_pos().start, + ) } - _ => ParseError::UnmatchedDelimiter(start.token_pos().start), + _ => ParseError::UnmatchedDelimiter( + start.token_pos().start, + ), }, loc: tokens.current_source_location(), })?; @@ -3486,39 +3970,61 @@ pub mod ast_gen { where F: FnOnce(&mut Self, &mut TokenIterator) -> ParseResult, { - self.parse_inner(tokens, open, close, parse, |this, tokens, err, start| { - match close { - Token::CloseBrace => { - tokens.advance_past_end_of_braced().ok_or(ErrorInfo { - error: ParseError::UnmatchedBrace(start.token_pos().start), - loc: tokens.current_source_location(), - })?; + self.parse_inner( + tokens, + open, + close, + parse, + |this, tokens, err, start| { + match close { + Token::CloseBrace => { + tokens.advance_past_end_of_braced().ok_or( + ErrorInfo { + error: ParseError::UnmatchedBrace( + start.token_pos().start, + ), + loc: tokens.current_source_location(), + }, + )?; + } + Token::CloseParens => { + tokens.advance_past_end_of_parens().ok_or( + ErrorInfo { + error: ParseError::UnmatchedParens( + start.token_pos().start, + ), + loc: tokens.current_source_location(), + }, + )?; + } + Token::CloseSquareBracket => { + tokens.advance_past_end_of_bracketed().ok_or( + ErrorInfo { + error: ParseError::UnmatchedSquareBracket( + start.token_pos().start, + ), + loc: tokens.current_source_location(), + }, + )?; + } + Token::Semi => { + tokens.advance_past_semi().ok_or(ErrorInfo { + error: ParseError::ExpectedToken(Token::Semi), + loc: tokens.current_source_location(), + })?; + } + _ => unimplemented!(), } - Token::CloseParens => { - tokens.advance_past_end_of_parens().ok_or(ErrorInfo { - error: ParseError::UnmatchedParens(start.token_pos().start), - loc: tokens.current_source_location(), - })?; - } - Token::CloseSquareBracket => { - tokens.advance_past_end_of_bracketed().ok_or(ErrorInfo { - error: ParseError::UnmatchedSquareBracket(start.token_pos().start), - loc: tokens.current_source_location(), - })?; - } - Token::Semi => { - tokens.advance_past_semi().ok_or(ErrorInfo { - error: ParseError::ExpectedToken(Token::Semi), - loc: tokens.current_source_location(), - })?; - } - _ => unimplemented!(), - } - Ok(this.push_error(err.error, err.loc)) - }) + Ok(this.push_error(err.error, err.loc)) + }, + ) } - fn parse_bracketed(&mut self, tokens: &mut TokenIterator, parse: F) -> ParseResult + fn parse_bracketed( + &mut self, + tokens: &mut TokenIterator, + parse: F, + ) -> ParseResult where F: FnOnce(&mut Self, &mut TokenIterator) -> ParseResult, { @@ -3530,11 +4036,20 @@ pub mod ast_gen { ) } - fn parse_braced(&mut self, tokens: &mut TokenIterator, parse: F) -> ParseResult + fn parse_braced( + &mut self, + tokens: &mut TokenIterator, + parse: F, + ) -> ParseResult where F: FnOnce(&mut Self, &mut TokenIterator) -> ParseResult, { - self.parse_inner2(tokens, Token::OpenBrace, Token::CloseBrace, parse) + self.parse_inner2( + tokens, + Token::OpenBrace, + Token::CloseBrace, + parse, + ) } fn parse_parenthesised( @@ -3545,7 +4060,12 @@ pub mod ast_gen { where F: FnOnce(&mut Self, &mut TokenIterator) -> ParseResult, { - self.parse_inner2(tokens, Token::OpenParens, Token::CloseParens, parse) + self.parse_inner2( + tokens, + Token::OpenParens, + Token::CloseParens, + parse, + ) } fn parse_struct_fields( @@ -3618,17 +4138,19 @@ pub mod ast_gen { while let Some(next) = tokens.peek_token() { let loc = next.source_location(); - let decl = match self.parse_constant_decls(tokens).and_then(|i| match i { - Some(i) => Ok(i), - None => { - let error = ParseError::UnexpectedTokenAtFileScope; - let node = self.push_error(error, loc); + let decl = match self.parse_constant_decls(tokens).and_then( + |i| match i { + Some(i) => Ok(i), + None => { + let error = ParseError::UnexpectedTokenAtFileScope; + let node = self.push_error(error, loc); - self.find_next_fn_or_const(tokens); + self.find_next_fn_or_const(tokens); - Ok(node) - } - }) { + Ok(node) + } + }, + ) { Ok(i) => i, Err(err) => self.push_error(err.error, err.loc), }; @@ -3710,9 +4232,16 @@ pub mod ast_gen { false } - fn find_next_fn_or_const(&mut self, tokens: &mut TokenIterator) -> Option<()> { + fn find_next_fn_or_const( + &mut self, + tokens: &mut TokenIterator, + ) -> Option<()> { tokens - .advance_until_before_one_of(&[Token::Const, Token::Fn, Token::Type]) + .advance_until_before_one_of(&[ + Token::Const, + Token::Fn, + Token::Type, + ]) .map(|_| ()) } } diff --git a/src/bin/main.rs b/src/bin/main.rs index 52cc746..ab8c32b 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -27,7 +27,8 @@ fn main() { .subcommands([ Command::new("ast").about("output AST."), Command::new("ast2").about("output AST."), - Command::new("mir").about("output machine-level intermediate representation."), + Command::new("mir") + .about("output machine-level intermediate representation."), Command::new("ir").about("output intermediate representation."), Command::new("asm").about("output x86-64 assembly (intel syntax)."), ]); @@ -80,7 +81,11 @@ fn main() { } = mir; for (name, mir) in functions { - println!("{}:\n{}", strings.get_str(name), mir.display(&strings)); + println!( + "{}:\n{}", + strings.get_str(name), + mir.display(&strings) + ); } } "asm" => { diff --git a/src/bin/tokenizer.rs b/src/bin/tokenizer.rs index f5819b4..da6fcd0 100644 --- a/src/bin/tokenizer.rs +++ b/src/bin/tokenizer.rs @@ -41,7 +41,8 @@ fn main() { } eprintln!(":"); for error in &errors { - let lines = tokens.src().get_lines(error.range.start, error.range.end); + let lines = + tokens.src().get_lines(error.range.start, error.range.end); let location = tokens .src() .get_source_span(error.range.start, error.range.end); diff --git a/src/common.rs b/src/common.rs index 7d68574..b95e9cd 100644 --- a/src/common.rs +++ b/src/common.rs @@ -72,7 +72,9 @@ pub fn is_oct_digit(ch: char) -> bool { } pub fn is_hex_digit(ch: char) -> bool { - ('0'..='9').contains(&ch) || ('a'..='f').contains(&ch) || ('A'..='F').contains(&ch) + ('0'..='9').contains(&ch) + || ('a'..='f').contains(&ch) + || ('A'..='F').contains(&ch) } /// Trait for only yielding the next item in the Iterator if it tests true for some predicate diff --git a/src/comptime.rs b/src/comptime.rs index cfda42e..580026f 100644 --- a/src/comptime.rs +++ b/src/comptime.rs @@ -12,7 +12,10 @@ pub mod bigint { pub struct BigInt(Vec); impl BigInt { - pub fn parse_digits>(text: C, radix: Radix) -> BigInt { + pub fn parse_digits>( + text: C, + radix: Radix, + ) -> BigInt { Self(parse_bigint(text.into_iter(), radix)) } pub fn from_u32(v: u32) -> BigInt { @@ -237,9 +240,13 @@ pub mod bigint { fn sub(mut self, rhs: Self) -> Self::Output { if self.0.len() < rhs.0.len() { - println!("extending self by {} zeroes", rhs.0.len() - self.0.len()); - self.0 - .extend(core::iter::repeat(0).take(rhs.0.len() - self.0.len())); + println!( + "extending self by {} zeroes", + rhs.0.len() - self.0.len() + ); + self.0.extend( + core::iter::repeat(0).take(rhs.0.len() - self.0.len()), + ); println!("self: {self:?}"); } sub_bigint(&mut self.0, &rhs.0); @@ -497,7 +504,10 @@ pub mod bigint { _ => { if scalar.is_power_of_two() { lhs.push(0); - shl_bitint(lhs.as_mut_slice(), scalar.trailing_zeros() as usize); + shl_bitint( + lhs.as_mut_slice(), + scalar.trailing_zeros() as usize, + ); } else { let mut carry = 0; for a in lhs.iter_mut() { @@ -583,7 +593,10 @@ pub mod bigint { #[allow(dead_code)] /// divident must be at least as wide as divisor /// returns (quotient, remainder) - pub fn div_rem_bigint_ref(divident: &BigInt, divisor: &BigInt) -> (BigInt, BigInt) { + pub fn div_rem_bigint_ref( + divident: &BigInt, + divisor: &BigInt, + ) -> (BigInt, BigInt) { if bigint_is_zero(&divisor.0) { panic!("divide by zero!"); } @@ -601,7 +614,8 @@ pub mod bigint { if divisor.is_power_of_two() { let exp = divisor.trailing_zeros(); - let (div, rem) = divident.0.split_at(exp.div_floor(u32::BITS as usize)); + let (div, rem) = + divident.0.split_at(exp.div_floor(u32::BITS as usize)); let (mut div, mut rem) = (div.to_vec(), rem.to_vec()); shr_bitint(&mut div, exp % u32::BITS as usize); @@ -627,7 +641,10 @@ pub mod bigint { if shift == 0 { div_rem_core(divident.clone(), &divisor.0) } else { - let (q, r) = div_rem_core(divident.clone() << shift, &(divisor.clone() << shift).0); + let (q, r) = div_rem_core( + divident.clone() << shift, + &(divisor.clone() << shift).0, + ); (q, r >> shift) } @@ -636,7 +653,10 @@ pub mod bigint { #[allow(dead_code)] /// divident must be at least as wide as divisor /// returns (quotient, remainder) - pub fn div_rem_bigint(divident: BigInt, divisor: BigInt) -> (BigInt, BigInt) { + pub fn div_rem_bigint( + divident: BigInt, + divisor: BigInt, + ) -> (BigInt, BigInt) { let divident = divident.normalised(); let mut divisor = divisor.normalised(); @@ -657,7 +677,8 @@ pub mod bigint { if divisor.is_power_of_two() { let exp = divisor.trailing_zeros(); - let (div, rem) = divident.0.split_at(exp.div_floor(u32::BITS as usize)); + let (div, rem) = + divident.0.split_at(exp.div_floor(u32::BITS as usize)); let (mut div, mut rem) = (div.to_vec(), rem.to_vec()); shr_bitint(&mut div, exp % u32::BITS as usize); @@ -789,7 +810,9 @@ pub mod bigint { // q0 is too large if: // [a2,a1,a0] < q0 * [b1,b0] // (r << BITS) + a2 < q0 * b1 - while r <= u32::MAX as u64 && from_lo_hi_dwords(r as u32, a2) < q0 as u64 * b1 as u64 { + while r <= u32::MAX as u64 + && from_lo_hi_dwords(r as u32, a2) < q0 as u64 * b1 as u64 + { q0 -= 1; r += b0 as u64; } @@ -1018,7 +1041,10 @@ pub mod bigint { carry } - pub fn parse_bigint(text: impl Iterator, radix: Radix) -> Vec { + pub fn parse_bigint( + text: impl Iterator, + radix: Radix, + ) -> Vec { let digits = text .filter_map(|c| match c { '_' => None, @@ -1086,14 +1112,20 @@ pub mod bigint { #[test] fn parse() { - let bigint = BigInt::parse_digits("2_cafe_babe_dead_beef".chars(), Radix::Hex); + let bigint = BigInt::parse_digits( + "2_cafe_babe_dead_beef".chars(), + Radix::Hex, + ); println!("{:#x?}", bigint); let bigint = BigInt::parse_digits("f".chars(), Radix::Hex); println!("{:#x?}", bigint); } #[test] fn add() { - let a = BigInt::parse_digits("2_0000_0000_0000_0000".chars(), Radix::Hex); + let a = BigInt::parse_digits( + "2_0000_0000_0000_0000".chars(), + Radix::Hex, + ); println!("{:#x?}", a); let b = BigInt::parse_digits("cafebabe".chars(), Radix::Hex); println!("{:#x?}", b); @@ -1111,7 +1143,10 @@ pub mod bigint { } #[test] fn overflowing_sub() { - let a = BigInt::parse_digits("2_0000_0000_0000_0000".chars(), Radix::Hex); + let a = BigInt::parse_digits( + "2_0000_0000_0000_0000".chars(), + Radix::Hex, + ); println!("{:#x?}", a); let b = BigInt::parse_digits("ffff_ffff".chars(), Radix::Hex); println!("{:#x?}", b); @@ -1120,7 +1155,8 @@ pub mod bigint { } #[test] fn shr() { - let mut a = BigInt::parse_digits("cafe_babe_0000".chars(), Radix::Hex); + let mut a = + BigInt::parse_digits("cafe_babe_0000".chars(), Radix::Hex); print!("{:0>8x?} >> 32 ", a); shr_bitint(&mut a.0, 32); println!("{:0>8x?}", a); @@ -1152,7 +1188,9 @@ pub mod bigint { pub mod bigsint { use std::{ cmp::Ordering, - ops::{Add, AddAssign, Div, Mul, Neg, Not, Rem, Shl, Shr, Sub, SubAssign}, + ops::{ + Add, AddAssign, Div, Mul, Neg, Not, Rem, Shl, Shr, Sub, SubAssign, + }, }; use super::bigint::{self, *}; @@ -1295,11 +1333,13 @@ pub mod bigsint { match (self.sign, rhs.sign) { (_, Sign::None) => self, (Sign::None, _) => rhs, - (Sign::Positive, Sign::Positive) | (Sign::Negative, Sign::Negative) => Self { + (Sign::Positive, Sign::Positive) + | (Sign::Negative, Sign::Negative) => Self { sign: self.sign, bigint: self.bigint + rhs.bigint, }, - (Sign::Positive, Sign::Negative) | (Sign::Negative, Sign::Positive) => { + (Sign::Positive, Sign::Negative) + | (Sign::Negative, Sign::Positive) => { match self.bigint.cmp(&rhs.bigint) { Ordering::Less => Self { sign: rhs.sign, @@ -1321,11 +1361,13 @@ pub mod bigsint { fn add(self, rhs: u32) -> Self::Output { match self.sign { - Sign::Negative => match self.bigint.partial_cmp(&rhs).unwrap() { - Ordering::Less => Self::positive(rhs - self.bigint), - Ordering::Equal => Self::zero(), - Ordering::Greater => -Self::positive(self.bigint - rhs), - }, + Sign::Negative => { + match self.bigint.partial_cmp(&rhs).unwrap() { + Ordering::Less => Self::positive(rhs - self.bigint), + Ordering::Equal => Self::zero(), + Ordering::Greater => -Self::positive(self.bigint - rhs), + } + } Sign::None => Self::from_u32(rhs), Sign::Positive => Self::positive(self.bigint + rhs), } @@ -1337,11 +1379,13 @@ pub mod bigsint { fn add(self, rhs: u64) -> Self::Output { match self.sign { - Sign::Negative => match self.bigint.partial_cmp(&rhs).unwrap() { - Ordering::Less => Self::positive(rhs - self.bigint), - Ordering::Equal => Self::zero(), - Ordering::Greater => -Self::positive(self.bigint - rhs), - }, + Sign::Negative => { + match self.bigint.partial_cmp(&rhs).unwrap() { + Ordering::Less => Self::positive(rhs - self.bigint), + Ordering::Equal => Self::zero(), + Ordering::Greater => -Self::positive(self.bigint - rhs), + } + } Sign::None => Self::from_u64(rhs), Sign::Positive => Self::positive(self.bigint + rhs), } @@ -1362,11 +1406,13 @@ pub mod bigsint { match (self.sign, rhs.sign) { (_, Sign::None) => self, (Sign::None, _) => -rhs, - (Sign::Positive, Sign::Negative) | (Sign::Negative, Sign::Positive) => Self { + (Sign::Positive, Sign::Negative) + | (Sign::Negative, Sign::Positive) => Self { sign: self.sign, bigint: self.bigint + rhs.bigint, }, - (Sign::Positive, Sign::Positive) | (Sign::Negative, Sign::Negative) => { + (Sign::Positive, Sign::Positive) + | (Sign::Negative, Sign::Negative) => { match self.bigint.cmp(&rhs.bigint) { Ordering::Less => Self { sign: -self.sign, @@ -1539,14 +1585,20 @@ impl ComptimeInt { pub fn add(self, other: Self) -> Result { let (a, b) = self.coalesce(other)?; match (a, b) { - (ComptimeInt::Native { bits: a, ty }, ComptimeInt::Native { bits: b, .. }) => { + ( + ComptimeInt::Native { bits: a, ty }, + ComptimeInt::Native { bits: b, .. }, + ) => { let bits = a.checked_add(b).ok_or(Error::IntegerOverflow)?; if bits & !ty.u128_bitmask() != 0 { return Err(Error::IntegerOverflow); } Ok(Self::Native { bits, ty }) } - (ComptimeInt::BigInt { bits: a, ty }, ComptimeInt::BigInt { bits: b, .. }) => { + ( + ComptimeInt::BigInt { bits: a, ty }, + ComptimeInt::BigInt { bits: b, .. }, + ) => { let width = ty.bits - ty.signed as u16; let bits = a + b; if bits.bits() > width as u64 { @@ -1555,7 +1607,9 @@ impl ComptimeInt { Ok(Self::BigInt { bits, ty }) } } - (ComptimeInt::Comptime(a), ComptimeInt::Comptime(b)) => Ok(Self::Comptime(a + b)), + (ComptimeInt::Comptime(a), ComptimeInt::Comptime(b)) => { + Ok(Self::Comptime(a + b)) + } _ => { unreachable!() } @@ -1565,14 +1619,20 @@ impl ComptimeInt { pub fn sub(self, other: Self) -> Result { let (a, b) = self.coalesce(other)?; match (a, b) { - (ComptimeInt::Native { bits: a, ty }, ComptimeInt::Native { bits: b, .. }) => { + ( + ComptimeInt::Native { bits: a, ty }, + ComptimeInt::Native { bits: b, .. }, + ) => { let bits = a.checked_sub(b).ok_or(Error::IntegerOverflow)?; if bits & !ty.u128_bitmask() != 0 { return Err(Error::IntegerOverflow); } Ok(Self::Native { bits, ty }) } - (ComptimeInt::BigInt { bits: a, ty }, ComptimeInt::BigInt { bits: b, .. }) => { + ( + ComptimeInt::BigInt { bits: a, ty }, + ComptimeInt::BigInt { bits: b, .. }, + ) => { let width = ty.bits - ty.signed as u16; let bits = a - b; if bits.bits() > width as u64 { @@ -1581,7 +1641,9 @@ impl ComptimeInt { Ok(Self::BigInt { bits, ty }) } } - (ComptimeInt::Comptime(a), ComptimeInt::Comptime(b)) => Ok(Self::Comptime(a - b)), + (ComptimeInt::Comptime(a), ComptimeInt::Comptime(b)) => { + Ok(Self::Comptime(a - b)) + } _ => { unreachable!() } @@ -1591,14 +1653,20 @@ impl ComptimeInt { pub fn mul(self, other: Self) -> Result { let (a, b) = self.coalesce(other)?; match (a, b) { - (ComptimeInt::Native { bits: a, ty }, ComptimeInt::Native { bits: b, .. }) => { + ( + ComptimeInt::Native { bits: a, ty }, + ComptimeInt::Native { bits: b, .. }, + ) => { let bits = a.checked_mul(b).ok_or(Error::IntegerOverflow)?; if bits & !ty.u128_bitmask() != 0 { return Err(Error::IntegerOverflow); } Ok(Self::Native { bits, ty }) } - (ComptimeInt::BigInt { bits: a, ty }, ComptimeInt::BigInt { bits: b, .. }) => { + ( + ComptimeInt::BigInt { bits: a, ty }, + ComptimeInt::BigInt { bits: b, .. }, + ) => { let width = ty.bits - ty.signed as u16; let bits = a * b; if bits.bits() > width as u64 { @@ -1607,7 +1675,9 @@ impl ComptimeInt { Ok(Self::BigInt { bits, ty }) } } - (ComptimeInt::Comptime(a), ComptimeInt::Comptime(b)) => Ok(Self::Comptime(a * b)), + (ComptimeInt::Comptime(a), ComptimeInt::Comptime(b)) => { + Ok(Self::Comptime(a * b)) + } _ => { unreachable!() } @@ -1617,14 +1687,20 @@ impl ComptimeInt { pub fn div(self, other: Self) -> Result { let (a, b) = self.coalesce(other)?; match (a, b) { - (ComptimeInt::Native { bits: a, ty }, ComptimeInt::Native { bits: b, .. }) => { + ( + ComptimeInt::Native { bits: a, ty }, + ComptimeInt::Native { bits: b, .. }, + ) => { let bits = a.checked_div(b).ok_or(Error::IntegerOverflow)?; if bits & !ty.u128_bitmask() != 0 { return Err(Error::IntegerOverflow); } Ok(Self::Native { bits, ty }) } - (ComptimeInt::BigInt { bits: a, ty }, ComptimeInt::BigInt { bits: b, .. }) => { + ( + ComptimeInt::BigInt { bits: a, ty }, + ComptimeInt::BigInt { bits: b, .. }, + ) => { let width = ty.bits - ty.signed as u16; let bits = a / b; if bits.bits() > width as u64 { @@ -1633,7 +1709,9 @@ impl ComptimeInt { Ok(Self::BigInt { bits, ty }) } } - (ComptimeInt::Comptime(a), ComptimeInt::Comptime(b)) => Ok(Self::Comptime(a / b)), + (ComptimeInt::Comptime(a), ComptimeInt::Comptime(b)) => { + Ok(Self::Comptime(a / b)) + } _ => { unreachable!() } @@ -1643,14 +1721,20 @@ impl ComptimeInt { pub fn rem(self, other: Self) -> Result { let (a, b) = self.coalesce(other)?; match (a, b) { - (ComptimeInt::Native { bits: a, ty }, ComptimeInt::Native { bits: b, .. }) => { + ( + ComptimeInt::Native { bits: a, ty }, + ComptimeInt::Native { bits: b, .. }, + ) => { let bits = a.checked_rem(b).ok_or(Error::IntegerOverflow)?; if bits & !ty.u128_bitmask() != 0 { return Err(Error::IntegerOverflow); } Ok(Self::Native { bits, ty }) } - (ComptimeInt::BigInt { bits: a, ty }, ComptimeInt::BigInt { bits: b, .. }) => { + ( + ComptimeInt::BigInt { bits: a, ty }, + ComptimeInt::BigInt { bits: b, .. }, + ) => { let width = ty.bits - ty.signed as u16; let bits = a % b; if bits.bits() > width as u64 { @@ -1659,7 +1743,9 @@ impl ComptimeInt { Ok(Self::BigInt { bits, ty }) } } - (ComptimeInt::Comptime(a), ComptimeInt::Comptime(b)) => Ok(Self::Comptime(a % b)), + (ComptimeInt::Comptime(a), ComptimeInt::Comptime(b)) => { + Ok(Self::Comptime(a % b)) + } _ => { unreachable!() } @@ -1669,15 +1755,23 @@ impl ComptimeInt { pub fn bitand(self, other: Self) -> Result { let (a, b) = self.coalesce(other)?; match (a, b) { - (ComptimeInt::Native { bits: a, ty }, ComptimeInt::Native { bits: b, .. }) => { + ( + ComptimeInt::Native { bits: a, ty }, + ComptimeInt::Native { bits: b, .. }, + ) => { let bits = a.bitand(b); Ok(Self::Native { bits, ty }) } - (ComptimeInt::BigInt { bits: a, ty }, ComptimeInt::BigInt { bits: b, .. }) => { + ( + ComptimeInt::BigInt { bits: a, ty }, + ComptimeInt::BigInt { bits: b, .. }, + ) => { let bits = a & b; Ok(Self::BigInt { bits, ty }) } - (ComptimeInt::Comptime(a), ComptimeInt::Comptime(b)) => Ok(Self::Comptime(a & b)), + (ComptimeInt::Comptime(a), ComptimeInt::Comptime(b)) => { + Ok(Self::Comptime(a & b)) + } _ => { unreachable!() } @@ -1687,15 +1781,23 @@ impl ComptimeInt { pub fn bitor(self, other: Self) -> Result { let (a, b) = self.coalesce(other)?; match (a, b) { - (ComptimeInt::Native { bits: a, ty }, ComptimeInt::Native { bits: b, .. }) => { + ( + ComptimeInt::Native { bits: a, ty }, + ComptimeInt::Native { bits: b, .. }, + ) => { let bits = a.bitor(b); Ok(Self::Native { bits, ty }) } - (ComptimeInt::BigInt { bits: a, ty }, ComptimeInt::BigInt { bits: b, .. }) => { + ( + ComptimeInt::BigInt { bits: a, ty }, + ComptimeInt::BigInt { bits: b, .. }, + ) => { let bits = a | b; Ok(Self::BigInt { bits, ty }) } - (ComptimeInt::Comptime(a), ComptimeInt::Comptime(b)) => Ok(Self::Comptime(a | b)), + (ComptimeInt::Comptime(a), ComptimeInt::Comptime(b)) => { + Ok(Self::Comptime(a | b)) + } _ => { unreachable!() } @@ -1705,15 +1807,23 @@ impl ComptimeInt { pub fn bitxor(self, other: Self) -> Result { let (a, b) = self.coalesce(other)?; match (a, b) { - (ComptimeInt::Native { bits: a, ty }, ComptimeInt::Native { bits: b, .. }) => { + ( + ComptimeInt::Native { bits: a, ty }, + ComptimeInt::Native { bits: b, .. }, + ) => { let bits = a.bitxor(b); Ok(Self::Native { bits, ty }) } - (ComptimeInt::BigInt { bits: a, ty }, ComptimeInt::BigInt { bits: b, .. }) => { + ( + ComptimeInt::BigInt { bits: a, ty }, + ComptimeInt::BigInt { bits: b, .. }, + ) => { let bits = a ^ b; Ok(Self::BigInt { bits, ty }) } - (ComptimeInt::Comptime(a), ComptimeInt::Comptime(b)) => Ok(Self::Comptime(a ^ b)), + (ComptimeInt::Comptime(a), ComptimeInt::Comptime(b)) => { + Ok(Self::Comptime(a ^ b)) + } _ => { unreachable!() } @@ -1722,8 +1832,14 @@ impl ComptimeInt { pub fn cmp(self, other: Self) -> Result { let (a, b) = self.coalesce(other)?; let ord = match (a, b) { - (ComptimeInt::Native { bits: a, .. }, ComptimeInt::Native { bits: b, .. }) => a.cmp(&b), - (ComptimeInt::BigInt { bits: a, .. }, ComptimeInt::BigInt { bits: b, .. }) => a.cmp(&b), + ( + ComptimeInt::Native { bits: a, .. }, + ComptimeInt::Native { bits: b, .. }, + ) => a.cmp(&b), + ( + ComptimeInt::BigInt { bits: a, .. }, + ComptimeInt::BigInt { bits: b, .. }, + ) => a.cmp(&b), (ComptimeInt::Comptime(a), ComptimeInt::Comptime(b)) => a.cmp(&b), _ => { unreachable!() @@ -1741,11 +1857,13 @@ impl ComptimeInt { let bits = if ty.signed { (bits as i128) .checked_shl(shift) - .ok_or(Error::IntegerOverflow)? as u128 + .ok_or(Error::IntegerOverflow)? + as u128 } else { (bits as u128) .checked_shl(shift) - .ok_or(Error::IntegerOverflow)? as u128 + .ok_or(Error::IntegerOverflow)? + as u128 } & ty.u128_bitmask(); Ok(Self::Native { bits, ty }) @@ -1770,11 +1888,13 @@ impl ComptimeInt { let bits = if ty.signed { (bits as i128) .checked_shr(shift) - .ok_or(Error::IntegerOverflow)? as u128 + .ok_or(Error::IntegerOverflow)? + as u128 } else { (bits as u128) .checked_shr(shift) - .ok_or(Error::IntegerOverflow)? as u128 + .ok_or(Error::IntegerOverflow)? + as u128 }; Ok(Self::Native { bits, ty }) @@ -1793,7 +1913,9 @@ impl ComptimeInt { if ty.signed { return Err(Error::UnsignedNegation); } - let bits = (a as i128).checked_neg().ok_or(Error::IntegerOverflow)? as u128; + let bits = + (a as i128).checked_neg().ok_or(Error::IntegerOverflow)? + as u128; if bits & !ty.u128_bitmask() != 0 { return Err(Error::IntegerOverflow); @@ -1811,7 +1933,9 @@ impl ComptimeInt { bits: !bits | ty.u128_bitmask(), ty, }), - ComptimeInt::BigInt { bits, ty } => Ok(Self::BigInt { bits: !bits, ty }), + ComptimeInt::BigInt { bits, ty } => { + Ok(Self::BigInt { bits: !bits, ty }) + } ComptimeInt::Comptime(bigint) => Ok(Self::Comptime(!bigint)), } } @@ -1827,8 +1951,14 @@ impl ComptimeInt { fn coalesce(self, other: Self) -> Result<(ComptimeInt, ComptimeInt)> { match (self, other) { - (lhs @ ComptimeInt::Native { ty: a_ty, .. }, ComptimeInt::Comptime(b)) - | (lhs @ ComptimeInt::Native { ty: a_ty, .. }, ComptimeInt::BigInt { bits: b, .. }) => { + ( + lhs @ ComptimeInt::Native { ty: a_ty, .. }, + ComptimeInt::Comptime(b), + ) + | ( + lhs @ ComptimeInt::Native { ty: a_ty, .. }, + ComptimeInt::BigInt { bits: b, .. }, + ) => { let b_signed = b.sign() == Sign::Minus; if !a_ty.signed && b_signed { return Err(Error::IncompatibleTypes); @@ -1845,8 +1975,14 @@ impl ComptimeInt { }; Ok((lhs, Self::Native { bits: b, ty: a_ty })) } - (ComptimeInt::Comptime(b), rhs @ ComptimeInt::Native { ty: a_ty, .. }) - | (ComptimeInt::BigInt { bits: b, .. }, rhs @ ComptimeInt::Native { ty: a_ty, .. }) => { + ( + ComptimeInt::Comptime(b), + rhs @ ComptimeInt::Native { ty: a_ty, .. }, + ) + | ( + ComptimeInt::BigInt { bits: b, .. }, + rhs @ ComptimeInt::Native { ty: a_ty, .. }, + ) => { let b_signed = b.sign() == Sign::Minus; if !a_ty.signed && b_signed { return Err(Error::IncompatibleTypes); @@ -1863,7 +1999,10 @@ impl ComptimeInt { }; Ok((Self::Native { bits: b, ty: a_ty }, rhs)) } - (lhs @ ComptimeInt::BigInt { ty, .. }, ComptimeInt::Comptime(b)) => { + ( + lhs @ ComptimeInt::BigInt { ty, .. }, + ComptimeInt::Comptime(b), + ) => { let b_signed = b.sign() == Sign::Minus; if !ty.signed && b_signed { return Err(Error::IncompatibleTypes); @@ -1875,7 +2014,10 @@ impl ComptimeInt { } Ok((lhs, Self::BigInt { bits: b, ty })) } - (ComptimeInt::Comptime(b), rhs @ ComptimeInt::BigInt { ty, .. }) => { + ( + ComptimeInt::Comptime(b), + rhs @ ComptimeInt::BigInt { ty, .. }, + ) => { let b_signed = b.sign() == Sign::Minus; if !ty.signed && b_signed { return Err(Error::IncompatibleTypes); @@ -1887,14 +2029,20 @@ impl ComptimeInt { } Ok((Self::BigInt { bits: b, ty }, rhs)) } - (lhs @ ComptimeInt::Native { ty: a, .. }, rhs @ ComptimeInt::Native { ty: b, .. }) => { + ( + lhs @ ComptimeInt::Native { ty: a, .. }, + rhs @ ComptimeInt::Native { ty: b, .. }, + ) => { if a == b { Ok((lhs, rhs)) } else { Err(Error::IncompatibleTypes) } } - (lhs @ ComptimeInt::BigInt { ty: a, .. }, rhs @ ComptimeInt::BigInt { ty: b, .. }) => { + ( + lhs @ ComptimeInt::BigInt { ty: a, .. }, + rhs @ ComptimeInt::BigInt { ty: b, .. }, + ) => { if a == b { Ok((lhs, rhs)) } else { @@ -1915,36 +2063,56 @@ pub enum ComptimeFloat { impl ComptimeFloat { pub fn add(self, other: Self) -> Result { match (self, other) { - (ComptimeFloat::Binary32(a), ComptimeFloat::Binary32(b)) => Ok(Self::Binary32(a + b)), - (ComptimeFloat::Binary64(a), ComptimeFloat::Binary64(b)) => Ok(Self::Binary64(a + b)), + (ComptimeFloat::Binary32(a), ComptimeFloat::Binary32(b)) => { + Ok(Self::Binary32(a + b)) + } + (ComptimeFloat::Binary64(a), ComptimeFloat::Binary64(b)) => { + Ok(Self::Binary64(a + b)) + } _ => Err(Error::IncompatibleTypes), } } pub fn sub(self, other: Self) -> Result { match (self, other) { - (ComptimeFloat::Binary32(a), ComptimeFloat::Binary32(b)) => Ok(Self::Binary32(a - b)), - (ComptimeFloat::Binary64(a), ComptimeFloat::Binary64(b)) => Ok(Self::Binary64(a - b)), + (ComptimeFloat::Binary32(a), ComptimeFloat::Binary32(b)) => { + Ok(Self::Binary32(a - b)) + } + (ComptimeFloat::Binary64(a), ComptimeFloat::Binary64(b)) => { + Ok(Self::Binary64(a - b)) + } _ => Err(Error::IncompatibleTypes), } } pub fn mul(self, other: Self) -> Result { match (self, other) { - (ComptimeFloat::Binary32(a), ComptimeFloat::Binary32(b)) => Ok(Self::Binary32(a * b)), - (ComptimeFloat::Binary64(a), ComptimeFloat::Binary64(b)) => Ok(Self::Binary64(a * b)), + (ComptimeFloat::Binary32(a), ComptimeFloat::Binary32(b)) => { + Ok(Self::Binary32(a * b)) + } + (ComptimeFloat::Binary64(a), ComptimeFloat::Binary64(b)) => { + Ok(Self::Binary64(a * b)) + } _ => Err(Error::IncompatibleTypes), } } pub fn div(self, other: Self) -> Result { match (self, other) { - (ComptimeFloat::Binary32(a), ComptimeFloat::Binary32(b)) => Ok(Self::Binary32(a / b)), - (ComptimeFloat::Binary64(a), ComptimeFloat::Binary64(b)) => Ok(Self::Binary64(a / b)), + (ComptimeFloat::Binary32(a), ComptimeFloat::Binary32(b)) => { + Ok(Self::Binary32(a / b)) + } + (ComptimeFloat::Binary64(a), ComptimeFloat::Binary64(b)) => { + Ok(Self::Binary64(a / b)) + } _ => Err(Error::IncompatibleTypes), } } pub fn rem(self, other: Self) -> Result { match (self, other) { - (ComptimeFloat::Binary32(a), ComptimeFloat::Binary32(b)) => Ok(Self::Binary32(a % b)), - (ComptimeFloat::Binary64(a), ComptimeFloat::Binary64(b)) => Ok(Self::Binary64(a % b)), + (ComptimeFloat::Binary32(a), ComptimeFloat::Binary32(b)) => { + Ok(Self::Binary32(a % b)) + } + (ComptimeFloat::Binary64(a), ComptimeFloat::Binary64(b)) => { + Ok(Self::Binary64(a % b)) + } _ => Err(Error::IncompatibleTypes), } } @@ -1956,8 +2124,12 @@ impl ComptimeFloat { } pub fn cmp(self, other: Self) -> Result { let ord = match (self, other) { - (ComptimeFloat::Binary32(a), ComptimeFloat::Binary32(b)) => a.partial_cmp(&b), - (ComptimeFloat::Binary64(a), ComptimeFloat::Binary64(b)) => a.partial_cmp(&b), + (ComptimeFloat::Binary32(a), ComptimeFloat::Binary32(b)) => { + a.partial_cmp(&b) + } + (ComptimeFloat::Binary64(a), ComptimeFloat::Binary64(b)) => { + a.partial_cmp(&b) + } _ => { return Err(Error::IncompatibleTypes); } @@ -2109,7 +2281,9 @@ impl ComptimeNumber { // (ComptimeNumber::Floating(a), ComptimeNumber::Floating(b)) => { // Ok(Self::Floating(a.sub(b)?)) // } - (ComptimeNumber::Bool(a), ComptimeNumber::Bool(b)) => Ok(Self::Bool(a.bitand(b))), + (ComptimeNumber::Bool(a), ComptimeNumber::Bool(b)) => { + Ok(Self::Bool(a.bitand(b))) + } _ => Err(Error::IncompatibleTypes), } } @@ -2121,7 +2295,9 @@ impl ComptimeNumber { // (ComptimeNumber::Floating(a), ComptimeNumber::Floating(b)) => { // Ok(Self::Floating(a.bitor(b)?)) // } - (ComptimeNumber::Bool(a), ComptimeNumber::Bool(b)) => Ok(Self::Bool(a.bitor(b))), + (ComptimeNumber::Bool(a), ComptimeNumber::Bool(b)) => { + Ok(Self::Bool(a.bitor(b))) + } _ => Err(Error::IncompatibleTypes), } } @@ -2133,7 +2309,9 @@ impl ComptimeNumber { // (ComptimeNumber::Floating(a), ComptimeNumber::Floating(b)) => { // Ok(Self::Floating(a.bitxor(b)?)) // } - (ComptimeNumber::Bool(a), ComptimeNumber::Bool(b)) => Ok(Self::Bool(a.bitxor(b))), + (ComptimeNumber::Bool(a), ComptimeNumber::Bool(b)) => { + Ok(Self::Bool(a.bitxor(b))) + } _ => Err(Error::IncompatibleTypes), } } @@ -2169,7 +2347,9 @@ impl ComptimeNumber { // (ComptimeNumber::Floating(a), ComptimeNumber::Floating(b)) => { // Ok(Self::Floating(a.bitxor(b)?)) // } - (ComptimeNumber::Bool(a), ComptimeNumber::Bool(b)) => Ok(Self::Bool(a || b)), + (ComptimeNumber::Bool(a), ComptimeNumber::Bool(b)) => { + Ok(Self::Bool(a || b)) + } _ => Err(Error::IncompatibleTypes), } } @@ -2181,23 +2361,35 @@ impl ComptimeNumber { // (ComptimeNumber::Floating(a), ComptimeNumber::Floating(b)) => { // Ok(Self::Floating(a.bitxor(b)?)) // } - (ComptimeNumber::Bool(a), ComptimeNumber::Bool(b)) => Ok(Self::Bool(a && b)), + (ComptimeNumber::Bool(a), ComptimeNumber::Bool(b)) => { + Ok(Self::Bool(a && b)) + } _ => Err(Error::IncompatibleTypes), } } pub fn eq(self, other: Self) -> Result { match (self, other) { - (ComptimeNumber::Integral(a), ComptimeNumber::Integral(b)) => Ok(Self::Bool(a == b)), - (ComptimeNumber::Floating(a), ComptimeNumber::Floating(b)) => Ok(Self::Bool(a == b)), - (ComptimeNumber::Bool(a), ComptimeNumber::Bool(b)) => Ok(Self::Bool(a == b)), + (ComptimeNumber::Integral(a), ComptimeNumber::Integral(b)) => { + Ok(Self::Bool(a == b)) + } + (ComptimeNumber::Floating(a), ComptimeNumber::Floating(b)) => { + Ok(Self::Bool(a == b)) + } + (ComptimeNumber::Bool(a), ComptimeNumber::Bool(b)) => { + Ok(Self::Bool(a == b)) + } _ => Err(Error::IncompatibleTypes), } } pub fn cmp(self, other: Self) -> Result { let ord = match (self, other) { - (ComptimeNumber::Integral(a), ComptimeNumber::Integral(b)) => a.cmp(b)?, - (ComptimeNumber::Floating(a), ComptimeNumber::Floating(b)) => a.cmp(b)?, + (ComptimeNumber::Integral(a), ComptimeNumber::Integral(b)) => { + a.cmp(b)? + } + (ComptimeNumber::Floating(a), ComptimeNumber::Floating(b)) => { + a.cmp(b)? + } (ComptimeNumber::Bool(a), ComptimeNumber::Bool(b)) => a.cmp(&b), _ => { return Err(Error::IncompatibleTypes); @@ -2237,12 +2429,17 @@ impl ComptimeNumber { match self { ComptimeNumber::Integral(i) => match i { ComptimeInt::Native { bits, .. } => Ok((bits != 0).into()), - ComptimeInt::Comptime(bits) | ComptimeInt::BigInt { bits, .. } => { + ComptimeInt::Comptime(bits) + | ComptimeInt::BigInt { bits, .. } => { Ok((bits.sign() != Sign::NoSign).into()) } }, - ComptimeNumber::Floating(ComptimeFloat::Binary32(f)) => Ok((f != 0.0).into()), - ComptimeNumber::Floating(ComptimeFloat::Binary64(f)) => Ok((f != 0.0).into()), + ComptimeNumber::Floating(ComptimeFloat::Binary32(f)) => { + Ok((f != 0.0).into()) + } + ComptimeNumber::Floating(ComptimeFloat::Binary64(f)) => { + Ok((f != 0.0).into()) + } a => Ok(a), } } @@ -2250,19 +2447,29 @@ impl ComptimeNumber { pub fn into_int(self, ty: IntegralType) -> Result { match self { ComptimeNumber::Integral(i) => match i { - ComptimeInt::Native { bits, .. } => Ok((bits & ty.u128_bitmask(), ty).into()), - ComptimeInt::Comptime(bits) | ComptimeInt::BigInt { bits, .. } => { - let max = BigUint::from(2u32).pow((ty.bits - ty.signed as u16) as u32); + ComptimeInt::Native { bits, .. } => { + Ok((bits & ty.u128_bitmask(), ty).into()) + } + ComptimeInt::Comptime(bits) + | ComptimeInt::BigInt { bits, .. } => { + let max = BigUint::from(2u32) + .pow((ty.bits - ty.signed as u16) as u32); let (sign, data) = bits.into_parts(); let data = data.clamp(BigUint::ZERO, max); Ok((BigInt::from_biguint(sign, data), ty).into()) } }, - ComptimeNumber::Bool(b) => Ok((b as u128 & ty.u128_bitmask(), ty).into()), + ComptimeNumber::Bool(b) => { + Ok((b as u128 & ty.u128_bitmask(), ty).into()) + } ComptimeNumber::Floating(f) => match f { - ComptimeFloat::Binary32(f) => Ok((f as u128 & ty.u128_bitmask(), ty).into()), - ComptimeFloat::Binary64(f) => Ok((f as u128 & ty.u128_bitmask(), ty).into()), + ComptimeFloat::Binary32(f) => { + Ok((f as u128 & ty.u128_bitmask(), ty).into()) + } + ComptimeFloat::Binary64(f) => { + Ok((f as u128 & ty.u128_bitmask(), ty).into()) + } }, ComptimeNumber::Void => { return Err(Error::VoidConversion); @@ -2273,7 +2480,8 @@ impl ComptimeNumber { let f = match self { ComptimeNumber::Integral(i) => match i { ComptimeInt::Native { bits, .. } => bits as f64, - ComptimeInt::Comptime(bits) | ComptimeInt::BigInt { bits, .. } => { + ComptimeInt::Comptime(bits) + | ComptimeInt::BigInt { bits, .. } => { bits.to_f64().unwrap_or(f64::NAN) } }, diff --git a/src/lexer.rs b/src/lexer.rs index d5998a8..108c4ed 100644 --- a/src/lexer.rs +++ b/src/lexer.rs @@ -83,7 +83,11 @@ impl<'a> Chars<'a> { SourceLocation::new(start_l, start_c) } - pub fn get_source_span(&self, start: u32, end: u32) -> std::ops::Range { + pub fn get_source_span( + &self, + start: u32, + end: u32, + ) -> std::ops::Range { let (start_l, start_c) = { let range = self.get_from_to(0, start); range.chars().fold((1u32, 0u32), |(line, col), c| { @@ -134,12 +138,18 @@ impl<'a> Chars<'a> { pub fn get_range(&self, range: core::ops::Range) -> &str { unsafe { - core::str::from_utf8_unchecked(&self.bytes[range.start as usize..range.end as usize]) + core::str::from_utf8_unchecked( + &self.bytes[range.start as usize..range.end as usize], + ) } } pub fn get_from_to(&self, start: u32, end: u32) -> &str { - unsafe { core::str::from_utf8_unchecked(&self.bytes[start as usize..end as usize]) } + unsafe { + core::str::from_utf8_unchecked( + &self.bytes[start as usize..end as usize], + ) + } } fn next_char(&mut self) -> Option { @@ -205,7 +215,12 @@ impl DelimitorConditions { || self.semis > cond.semis } - fn from_i32s(braces: i32, parens: i32, brackets: i32, semis: Option) -> Self { + fn from_i32s( + braces: i32, + parens: i32, + brackets: i32, + semis: Option, + ) -> Self { Self { braces: DelimitorCondition::from_i32(braces), parens: DelimitorCondition::from_i32(parens), @@ -216,7 +231,10 @@ impl DelimitorConditions { } impl<'a> TokenIterator<'a> { - pub fn advance_until_before_token(&mut self, token: Token) -> Option { + pub fn advance_until_before_token( + &mut self, + token: Token, + ) -> Option { while let Some(next) = self.peek_token() { if next.token() == token { return Some(token); @@ -226,7 +244,10 @@ impl<'a> TokenIterator<'a> { None } - pub fn advance_until_before_one_of(&mut self, tokens: &[Token]) -> Option { + pub fn advance_until_before_one_of( + &mut self, + tokens: &[Token], + ) -> Option { while let Some(next) = self.peek_token() { if tokens.contains(&next.token()) { return Some(next.token()); @@ -304,13 +325,19 @@ impl<'a> TokenIterator<'a> { }) } - fn advance_until_condition(&mut self, cond: DelimitorConditions) -> Option<()> { + fn advance_until_condition( + &mut self, + cond: DelimitorConditions, + ) -> Option<()> { self.advance_past_condition(cond)?; _ = self.offset.saturating_sub(1); Some(()) } - fn advance_past_condition(&mut self, cond: DelimitorConditions) -> Option<()> { + fn advance_past_condition( + &mut self, + cond: DelimitorConditions, + ) -> Option<()> { let mut braces = 0; let mut parens = 0; let mut brackets = 0; @@ -341,8 +368,12 @@ impl<'a> TokenIterator<'a> { _ => { /* nada */ } } - let current = - DelimitorConditions::from_i32s(braces, parens, brackets, cond.semis.map(|_| semis)); + let current = DelimitorConditions::from_i32s( + braces, + parens, + brackets, + cond.semis.map(|_| semis), + ); if cond == current { return Some(()); } @@ -377,13 +408,16 @@ impl<'a> TokenIterator<'a> { .next() .map(|i| i.source_location()) .unwrap_or_else(|| { - self.tokenizer - .source - .offset_to_source_location(self.tokenizer.source.num_bytes() as u32) + self.tokenizer.source.offset_to_source_location( + self.tokenizer.source.num_bytes() as u32, + ) }) } - pub fn expect_token(&mut self, token: Token) -> crate::parser::Result> { + pub fn expect_token( + &mut self, + token: Token, + ) -> crate::parser::Result> { self.next_if(|item| item.token() == token) .ok_or(crate::parser::Error::ExpectedTokenNotFound(token)) } @@ -395,13 +429,18 @@ impl<'a> TokenIterator<'a> { pub fn peek_token(&mut self) -> Option> { self.clone().next() } - pub fn peek_token_or_err(&mut self) -> crate::parser::Result> { + pub fn peek_token_or_err( + &mut self, + ) -> crate::parser::Result> { self.clone() .next() .ok_or(crate::parser::Error::UnexpectedEndOfTokens) } - pub fn peek_expect_token(&mut self, token: Token) -> crate::parser::Result> { + pub fn peek_expect_token( + &mut self, + token: Token, + ) -> crate::parser::Result> { self.clone() .next() .ok_or(crate::parser::Error::ExpectedTokenNotFound(token)) @@ -644,9 +683,16 @@ impl<'a> Tokenizer<'a> { // .unwrap_or(false); let end = this.source.position(); - if this.source.peek().map(|c| crate::common::is_whitespace(c)) != Some(true) { + if this + .source + .peek() + .map(|c| crate::common::is_whitespace(c)) + != Some(true) + { this.source - .take_while_ref(|&c| !crate::common::is_whitespace(c)) + .take_while_ref(|&c| { + !crate::common::is_whitespace(c) + }) .count(); } @@ -713,7 +759,10 @@ impl<'a> Tokenizer<'a> { let mut peeking = self.source.clone(); match peeking.next() { Some('0'..='9') => Some(parse_constant(&mut self.source)?), - Some('.') if peeking.next().map(|c| crate::common::is_digit(c)) == Some(true) => { + Some('.') + if peeking.next().map(|c| crate::common::is_digit(c)) + == Some(true) => + { Some(parse_constant(&mut self.source)?) } _ => None, @@ -796,7 +845,11 @@ impl<'a> Tokenizer<'a> { .count() .gt(&0) { - return self.push_token(Token::Ident, start, self.source.position()); + return self.push_token( + Token::Ident, + start, + self.source.position(), + ); } } @@ -1046,7 +1099,9 @@ fn parse_constant_inner(source: &mut Chars) -> Result { Err(e) => Err(e), }?; - if let Some(_) = source.try_parse_result(|source| try_parse_integral_type(source))? { + if let Some(_) = + source.try_parse_result(|source| try_parse_integral_type(source))? + { return Ok(Token::IntegerConstant); } diff --git a/src/lib.rs b/src/lib.rs index ddf2975..39c1a7a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -30,6 +30,9 @@ pub mod triples; pub fn tokenize<'a>( bytes: &'a [u8], -) -> Result, (lexer::Tokenizer<'a>, Vec)> { +) -> Result< + lexer::Tokenizer<'a>, + (lexer::Tokenizer<'a>, Vec), +> { lexer::Tokenizer::new_with_errors(bytes) } diff --git a/src/mir.rs b/src/mir.rs index d5492b0..3835113 100644 --- a/src/mir.rs +++ b/src/mir.rs @@ -514,12 +514,16 @@ impl OperandKinds { reg.union(mem).union(imm) } const fn to_lhs_binop(self) -> BinaryOperandFlags { - let reg = if self.intersects(Self::RegReg.union(Self::RegImm).union(Self::RegMem)) { + let reg = if self + .intersects(Self::RegReg.union(Self::RegImm).union(Self::RegMem)) + { BinaryOperandFlags::LhsReg } else { BinaryOperandFlags::empty() }; - let mem = if self.intersects(Self::MemReg.union(Self::MemMem).union(Self::MemImm)) { + let mem = if self + .intersects(Self::MemReg.union(Self::MemMem).union(Self::MemImm)) + { BinaryOperandFlags::LhsMem } else { BinaryOperandFlags::empty() @@ -591,7 +595,13 @@ struct BinaryOperandsRunner<'a> { impl<'a> BinaryOperandsRunner<'a> { #[allow(dead_code)] - fn new(inner: BinaryOperands<'a>, lhs: u32, lhs_type: Type, rhs: u32, rhs_type: Type) -> Self { + fn new( + inner: BinaryOperands<'a>, + lhs: u32, + lhs_type: Type, + rhs: u32, + rhs_type: Type, + ) -> Self { Self { inner, lhs: (lhs, lhs_type), @@ -642,7 +652,9 @@ impl<'a> BinaryOperandsRunner<'a> { let l_kind = self.mir().as_operand_kind(lhs).as_lhs(); let r_kind = self.mir().as_operand_kind(rhs).as_rhs(); - if self.inner.commutative && (!l_legal.contains(l_kind) && l_legal.contains(r_kind)) { + if self.inner.commutative + && (!l_legal.contains(l_kind) && l_legal.contains(r_kind)) + { core::mem::swap(&mut self.lhs, &mut self.rhs); } } @@ -703,7 +715,13 @@ impl<'a> BinaryOperands<'a> { Self::new(mir, false, OperandKinds::shift()) } - fn wrangle(self, lhs: u32, lhs_type: Type, rhs: u32, rhs_type: Type) -> (u32, u32) { + fn wrangle( + self, + lhs: u32, + lhs_type: Type, + rhs: u32, + rhs_type: Type, + ) -> (u32, u32) { let mut runner = BinaryOperandsRunner { inner: self, lhs: (lhs, lhs_type), @@ -780,7 +798,10 @@ impl Mir { self.data[node.index()] = data; } - fn indices(&self) -> impl Iterator + DoubleEndedIterator + FusedIterator { + fn indices( + &self, + ) -> impl Iterator + DoubleEndedIterator + FusedIterator + { (0..self.nodes.len() as u32).map(|n| NodeRef::from(n)) } } @@ -919,27 +940,63 @@ impl Mir { } } - pub fn gen_is_eq(&mut self, ty: Type, signed: bool, lhs: u32, rhs: u32) -> u32 { + pub fn gen_is_eq( + &mut self, + ty: Type, + signed: bool, + lhs: u32, + rhs: u32, + ) -> u32 { let cmp = self.gen_cmp(ty, lhs, rhs); self.push(Inst::IsEq(signed), Data::node(cmp)) } - pub fn gen_is_neq(&mut self, ty: Type, signed: bool, lhs: u32, rhs: u32) -> u32 { + pub fn gen_is_neq( + &mut self, + ty: Type, + signed: bool, + lhs: u32, + rhs: u32, + ) -> u32 { let cmp = self.gen_cmp(ty, lhs, rhs); self.push(Inst::IsNeq(signed), Data::node(cmp)) } - pub fn gen_is_gt(&mut self, ty: Type, signed: bool, lhs: u32, rhs: u32) -> u32 { + pub fn gen_is_gt( + &mut self, + ty: Type, + signed: bool, + lhs: u32, + rhs: u32, + ) -> u32 { let cmp = self.gen_cmp(ty, lhs, rhs); self.push(Inst::IsGt(signed), Data::node(cmp)) } - pub fn gen_is_lt(&mut self, ty: Type, signed: bool, lhs: u32, rhs: u32) -> u32 { + pub fn gen_is_lt( + &mut self, + ty: Type, + signed: bool, + lhs: u32, + rhs: u32, + ) -> u32 { let cmp = self.gen_cmp(ty, lhs, rhs); self.push(Inst::IsLt(signed), Data::node(cmp)) } - pub fn gen_is_ge(&mut self, ty: Type, signed: bool, lhs: u32, rhs: u32) -> u32 { + pub fn gen_is_ge( + &mut self, + ty: Type, + signed: bool, + lhs: u32, + rhs: u32, + ) -> u32 { let cmp = self.gen_cmp(ty, lhs, rhs); self.push(Inst::IsGe(signed), Data::node(cmp)) } - pub fn gen_is_le(&mut self, ty: Type, signed: bool, lhs: u32, rhs: u32) -> u32 { + pub fn gen_is_le( + &mut self, + ty: Type, + signed: bool, + lhs: u32, + rhs: u32, + ) -> u32 { let cmp = self.gen_cmp(ty, lhs, rhs); self.push(Inst::IsLe(signed), Data::node(cmp)) } @@ -966,7 +1023,12 @@ impl Mir { pub fn gen_load(&mut self, ty: Type, src: u32) -> u32 { self.push(Inst::Load(ty), Data::node(src)) } - pub fn gen_get_element_ptr(&mut self, ty: Type, src: u32, index: u32) -> u32 { + pub fn gen_get_element_ptr( + &mut self, + ty: Type, + src: u32, + index: u32, + ) -> u32 { self.push(Inst::GetElementPtr(ty), Data::binary(src, index)) } pub fn gen_store(&mut self, ty: Type, src: u32, dst: u32) -> u32 { @@ -1004,7 +1066,13 @@ impl Mir { } /// truncates a value `src` of `mir::Type` `ty` to `bits` bits, while preserving the sign - pub fn gen_truncate_integer(&mut self, src: u32, ty: Type, signed: bool, bits: u16) -> u32 { + pub fn gen_truncate_integer( + &mut self, + src: u32, + ty: Type, + signed: bool, + bits: u16, + ) -> u32 { // example: u4 -> (byte, false, 4) // 1111_1111 << 4 = 1111_0000 // mask = 0000_1111; @@ -1036,13 +1104,19 @@ impl Mir { // if both types fit into the same mir::Type, then this is a noop // if signed sign extend, otherwise zero-extend (or zero the register) // `ty` is the output type - pub fn gen_extend_integer(&mut self, src: u32, from: IntegralType, to: IntegralType) -> u32 { + pub fn gen_extend_integer( + &mut self, + src: u32, + from: IntegralType, + to: IntegralType, + ) -> u32 { // example: u4 -> (byte, false, 4) // 1111_1111 << 4 = 1111_0000 // mask = 0000_1111; // shift = 8 - 4; let src_ty = Type::from_bitsize_int(from.bits as u32); - let truncated = self.gen_truncate_integer(src, src_ty, from.signed, from.bits); + let truncated = + self.gen_truncate_integer(src, src_ty, from.signed, from.bits); let dst_ty = Type::from_bitsize_int(to.bits as u32); if to.signed { @@ -1065,7 +1139,8 @@ impl Mir { let (lhs, rhs) = if ty.is_floating() { BinaryOperands::new_sse(self).wrangle(lhs, ty, rhs, ty) } else { - BinaryOperands::new_add_or_and_xor_adc(self).wrangle(lhs, ty, rhs, ty) + BinaryOperands::new_add_or_and_xor_adc(self) + .wrangle(lhs, ty, rhs, ty) }; self.push(Inst::Add(ty), Data::binary(lhs, rhs)) } @@ -1077,7 +1152,13 @@ impl Mir { }; self.push(Inst::Sub(ty), Data::binary(lhs, rhs)) } - pub fn gen_mul(&mut self, ty: Type, signed: bool, lhs: u32, rhs: u32) -> u32 { + pub fn gen_mul( + &mut self, + ty: Type, + signed: bool, + lhs: u32, + rhs: u32, + ) -> u32 { if ty.is_floating() { self.gen_mul_sse(ty, lhs, rhs) } else if signed { @@ -1087,18 +1168,27 @@ impl Mir { } } pub fn gen_mul_sse(&mut self, ty: Type, lhs: u32, rhs: u32) -> u32 { - let (lhs, rhs) = BinaryOperands::new_sse(self).wrangle(lhs, ty, rhs, ty); + let (lhs, rhs) = + BinaryOperands::new_sse(self).wrangle(lhs, ty, rhs, ty); self.push(Inst::MulSSE(ty), Data::binary(lhs, rhs)) } pub fn gen_mul_unsigned(&mut self, ty: Type, lhs: u32, rhs: u32) -> u32 { - let (lhs, rhs) = BinaryOperands::new_mul(self).wrangle(lhs, ty, rhs, ty); + let (lhs, rhs) = + BinaryOperands::new_mul(self).wrangle(lhs, ty, rhs, ty); self.push(Inst::Mul(ty), Data::binary(lhs, rhs)) } pub fn gen_mul_signed(&mut self, ty: Type, lhs: u32, rhs: u32) -> u32 { - let (lhs, rhs) = BinaryOperands::new_imul(self).wrangle(lhs, ty, rhs, ty); + let (lhs, rhs) = + BinaryOperands::new_imul(self).wrangle(lhs, ty, rhs, ty); self.push(Inst::MulSigned(ty), Data::binary(lhs, rhs)) } - pub fn gen_div(&mut self, ty: Type, signed: bool, lhs: u32, rhs: u32) -> u32 { + pub fn gen_div( + &mut self, + ty: Type, + signed: bool, + lhs: u32, + rhs: u32, + ) -> u32 { if ty.is_floating() { self.gen_div_sse(ty, lhs, rhs) } else if signed { @@ -1108,18 +1198,27 @@ impl Mir { } } pub fn gen_div_sse(&mut self, ty: Type, lhs: u32, rhs: u32) -> u32 { - let (lhs, rhs) = BinaryOperands::new_sse(self).wrangle(lhs, ty, rhs, ty); + let (lhs, rhs) = + BinaryOperands::new_sse(self).wrangle(lhs, ty, rhs, ty); self.push(Inst::DivSSE(ty), Data::binary(lhs, rhs)) } pub fn gen_div_unsigned(&mut self, ty: Type, lhs: u32, rhs: u32) -> u32 { - let (lhs, rhs) = BinaryOperands::new_div_idiv_rem_irem(self).wrangle(lhs, ty, rhs, ty); + let (lhs, rhs) = BinaryOperands::new_div_idiv_rem_irem(self) + .wrangle(lhs, ty, rhs, ty); self.push(Inst::Div(ty), Data::binary(lhs, rhs)) } pub fn gen_div_signed(&mut self, ty: Type, lhs: u32, rhs: u32) -> u32 { - let (lhs, rhs) = BinaryOperands::new_div_idiv_rem_irem(self).wrangle(lhs, ty, rhs, ty); + let (lhs, rhs) = BinaryOperands::new_div_idiv_rem_irem(self) + .wrangle(lhs, ty, rhs, ty); self.push(Inst::DivSigned(ty), Data::binary(lhs, rhs)) } - pub fn gen_rem(&mut self, ty: Type, signed: bool, lhs: u32, rhs: u32) -> u32 { + pub fn gen_rem( + &mut self, + ty: Type, + signed: bool, + lhs: u32, + rhs: u32, + ) -> u32 { if ty.is_floating() { self.gen_rem_fp(ty, lhs, rhs) } else if signed { @@ -1130,28 +1229,34 @@ impl Mir { } pub fn gen_rem_fp(&mut self, ty: Type, lhs: u32, rhs: u32) -> u32 { let (lhs, rhs) = - BinaryOperands::new(self, false, OperandKinds::any_mem_reg()).wrangle(lhs, ty, rhs, ty); + BinaryOperands::new(self, false, OperandKinds::any_mem_reg()) + .wrangle(lhs, ty, rhs, ty); self.push(Inst::RemFP(ty), Data::binary(lhs, rhs)) } pub fn gen_rem_unsigned(&mut self, ty: Type, lhs: u32, rhs: u32) -> u32 { - let (lhs, rhs) = BinaryOperands::new_div_idiv_rem_irem(self).wrangle(lhs, ty, rhs, ty); + let (lhs, rhs) = BinaryOperands::new_div_idiv_rem_irem(self) + .wrangle(lhs, ty, rhs, ty); self.push(Inst::Rem(ty), Data::binary(lhs, rhs)) } pub fn gen_rem_signed(&mut self, ty: Type, lhs: u32, rhs: u32) -> u32 { - let (lhs, rhs) = BinaryOperands::new_div_idiv_rem_irem(self).wrangle(lhs, ty, rhs, ty); + let (lhs, rhs) = BinaryOperands::new_div_idiv_rem_irem(self) + .wrangle(lhs, ty, rhs, ty); self.push(Inst::RemSigned(ty), Data::binary(lhs, rhs)) } pub fn gen_bitand(&mut self, ty: Type, lhs: u32, rhs: u32) -> u32 { - let (lhs, rhs) = BinaryOperands::new_add_or_and_xor_adc(self).wrangle(lhs, ty, rhs, ty); + let (lhs, rhs) = BinaryOperands::new_add_or_and_xor_adc(self) + .wrangle(lhs, ty, rhs, ty); self.push(Inst::BitAnd(ty), Data::binary(lhs, rhs)) } pub fn gen_bitor(&mut self, ty: Type, lhs: u32, rhs: u32) -> u32 { - let (lhs, rhs) = BinaryOperands::new_add_or_and_xor_adc(self).wrangle(lhs, ty, rhs, ty); + let (lhs, rhs) = BinaryOperands::new_add_or_and_xor_adc(self) + .wrangle(lhs, ty, rhs, ty); self.push(Inst::BitOr(ty), Data::binary(lhs, rhs)) } pub fn gen_bitxor(&mut self, ty: Type, lhs: u32, rhs: u32) -> u32 { - let (lhs, rhs) = BinaryOperands::new_add_or_and_xor_adc(self).wrangle(lhs, ty, rhs, ty); + let (lhs, rhs) = BinaryOperands::new_add_or_and_xor_adc(self) + .wrangle(lhs, ty, rhs, ty); self.push(Inst::BitXOr(ty), Data::binary(lhs, rhs)) } pub fn gen_negate(&mut self, ty: Type, src: u32) -> u32 { @@ -1165,17 +1270,20 @@ impl Mir { #[doc(alias = "gen_shift_left")] pub fn gen_shl(&mut self, ty: Type, src: u32, shift: u32) -> u32 { - let (src, shift) = BinaryOperands::new_shift(self).wrangle(src, ty, shift, Type::Byte); + let (src, shift) = + BinaryOperands::new_shift(self).wrangle(src, ty, shift, Type::Byte); self.push(Inst::ShiftLeft(ty), Data::binary(src, shift)) } #[doc(alias = "gen_shift_right")] pub fn gen_shr(&mut self, ty: Type, src: u32, shift: u32) -> u32 { - let (src, shift) = BinaryOperands::new_shift(self).wrangle(src, ty, shift, Type::Byte); + let (src, shift) = + BinaryOperands::new_shift(self).wrangle(src, ty, shift, Type::Byte); self.push(Inst::ShiftRightUnsigned(ty), Data::binary(src, shift)) } #[doc(alias = "gen_shift_right_signed")] pub fn gen_sar(&mut self, ty: Type, src: u32, shift: u32) -> u32 { - let (src, shift) = BinaryOperands::new_shift(self).wrangle(src, ty, shift, Type::Byte); + let (src, shift) = + BinaryOperands::new_shift(self).wrangle(src, ty, shift, Type::Byte); self.push(Inst::ShiftRightSigned(ty), Data::binary(src, shift)) } pub fn gen_ret_val(&mut self, ty: Type, val: u32) -> u32 { @@ -1203,16 +1311,28 @@ impl Mir { } match inst { - Inst::Label => writeln!(w, "%{node} = label {}", strings.get_str(data.as_index())), + Inst::Label => writeln!( + w, + "%{node} = label {}", + strings.get_str(data.as_index()) + ), Inst::ConstantBytes => writeln!( w, "%{node} = bytes({:x?})", strings.get_bytes(data.as_index()) ), - Inst::ConstantByte => writeln!(w, "%{node} = imm8({:x?})", data.as_imm8()), - Inst::ConstantWord => writeln!(w, "%{node} = imm16({:x?})", data.as_imm16()), - Inst::ConstantDWord => writeln!(w, "%{node} = imm32({:x?})", data.as_imm32()), - Inst::ConstantQWord => writeln!(w, "%{node} = imm64({:x?})", data.as_imm64()), + Inst::ConstantByte => { + writeln!(w, "%{node} = imm8({:x?})", data.as_imm8()) + } + Inst::ConstantWord => { + writeln!(w, "%{node} = imm16({:x?})", data.as_imm16()) + } + Inst::ConstantDWord => { + writeln!(w, "%{node} = imm32({:x?})", data.as_imm32()) + } + Inst::ConstantQWord => { + writeln!(w, "%{node} = imm64({:x?})", data.as_imm64()) + } Inst::ConstantSinglePrecision => writeln!( w, "%{node} = imm32fp({:x?})", @@ -1240,7 +1360,10 @@ impl Mir { } Inst::GetElementPtr(ty) => { let (ptr, idx) = data.as_binary(); - writeln!(w, "%{node} = get element ptr {ty}, ptr %{ptr}, idx {idx}") + writeln!( + w, + "%{node} = get element ptr {ty}, ptr %{ptr}, idx {idx}" + ) } Inst::Load(ty) => { writeln!(w, "%{node} = load {ty}, ptr %{}", data.as_node()) @@ -1377,7 +1500,10 @@ impl Mir { } Inst::ShiftRightSigned(ty) => { let (lhs, rhs) = data.as_binary(); - writeln!(w, "%{node} = signed shift right {ty} %{lhs}, {ty} %{rhs}") + writeln!( + w, + "%{node} = signed shift right {ty} %{lhs}, {ty} %{rhs}" + ) } Inst::ReturnValue(ty) => { let lhs = data.as_node(); @@ -1413,7 +1539,10 @@ impl Mir { Ok(()) } - pub fn display<'a, 'b>(&'a self, strings: &'b StringTable) -> DisplayMir<'a, 'b> { + pub fn display<'a, 'b>( + &'a self, + strings: &'b StringTable, + ) -> DisplayMir<'a, 'b> { DisplayMir { mir: self, strings } } } @@ -1460,9 +1589,9 @@ pub mod liveness { let dirty = self .interference_graph_for_node(node) .map(|graph| { - graph - .neighbors(node.0.into()) - .filter_map(|n| register_map.get(&NodeRef(n.index() as u32)).cloned()) + graph.neighbors(node.0.into()).filter_map(|n| { + register_map.get(&NodeRef(n.index() as u32)).cloned() + }) }) .into_iter() .flatten() @@ -1519,7 +1648,10 @@ pub mod liveness { } } - pub fn new(mir: &Mir, references: &BTreeSet<(NodeRef, NodeRef)>) -> Self { + pub fn new( + mir: &Mir, + references: &BTreeSet<(NodeRef, NodeRef)>, + ) -> Self { let mut sorted_branches = Vec::new(); let mut branch_graph_edges = Vec::new(); @@ -1615,7 +1747,9 @@ pub mod liveness { .map(|(range, edges)| { ( range, - InterferenceGraph::from_edges(edges.into_iter().map(|(a, b)| (a.0, b.0))), + InterferenceGraph::from_edges( + edges.into_iter().map(|(a, b)| (a.0, b.0)), + ), ) }) .collect::>(); @@ -1642,11 +1776,16 @@ pub mod liveness { fn branch_index_for_node(&self, node: NodeRef) -> Option { self.branches - .binary_search_by(|(range, _)| range.partial_cmp(&node).unwrap()) + .binary_search_by(|(range, _)| { + range.partial_cmp(&node).unwrap() + }) .ok() } - pub fn interference_graph_for_node(&self, node: NodeRef) -> Option<&InterferenceGraph> { + pub fn interference_graph_for_node( + &self, + node: NodeRef, + ) -> Option<&InterferenceGraph> { if let Some(index) = self.branch_index_for_node(node) { Some(&self.branches[index].1) } else { @@ -1730,7 +1869,8 @@ pub mod liveness { use Register::*; let mut in_colors = [r9, r8, rcx, rdx, rdi, rsi].to_vec(); - let mut in_colors_sse = [xmm7, xmm6, xmm5, xmm4, xmm3, xmm2, xmm1, xmm0].to_vec(); + let mut in_colors_sse = + [xmm7, xmm6, xmm5, xmm4, xmm3, xmm2, xmm1, xmm0].to_vec(); for node in self.mir.indices() { let want_color = match self.mir.get_node(node).0 { @@ -1744,7 +1884,9 @@ pub mod liveness { Inst::ShiftLeft(_) | Inst::ShiftRightSigned(_) | Inst::ShiftRightUnsigned(_) => Some(rcx), - Inst::Mul(_) | Inst::Div(_) | Inst::DivSigned(_) => Some(rax), + Inst::Mul(_) | Inst::Div(_) | Inst::DivSigned(_) => { + Some(rax) + } Inst::Rem(_) | Inst::RemSigned(_) => Some(rdx), Inst::ReturnValue(ty) => { if ty.is_floating() { @@ -1803,10 +1945,15 @@ pub mod liveness { pub fn get_register(&self, node: NodeRef) -> Option { self.register_map.get(&node).cloned() } - pub fn dirty_registers(&self) -> std::collections::btree_map::Values { + pub fn dirty_registers( + &self, + ) -> std::collections::btree_map::Values { self.register_map.values() } - pub fn get_scratch_register_at_node(&self, node: NodeRef) -> Option { + pub fn get_scratch_register_at_node( + &self, + node: NodeRef, + ) -> Option { let dirty = self .branches .dirty_registers_at_node(&self.register_map, node); @@ -1817,7 +1964,11 @@ pub mod liveness { .next() } - pub fn is_register_in_use_at_node(&self, node: NodeRef, reg: Register) -> bool { + pub fn is_register_in_use_at_node( + &self, + node: NodeRef, + reg: Register, + ) -> bool { self.branches .dirty_registers_at_node(&self.register_map, node) .contains(®) @@ -1889,7 +2040,11 @@ pub mod liveness { .map(|graph| { graph .neighbors(node) - .filter_map(|n| self.colors.get(&NodeRef(n.index() as u32)).cloned()) + .filter_map(|n| { + self.colors + .get(&NodeRef(n.index() as u32)) + .cloned() + }) .find(|color| color.color() == preferred_color) }) .flatten(); @@ -1923,7 +2078,9 @@ pub mod liveness { .map(|graph| { graph .neighbors(node) - .filter_map(|n| self.colors.get(&NodeRef(n.index() as u32)).cloned()) + .filter_map(|n| { + self.colors.get(&NodeRef(n.index() as u32)).cloned() + }) .collect::>() }) .unwrap_or_default(); @@ -1945,7 +2102,9 @@ pub mod liveness { // here we want to first check clique_colors with tentative coloring. let color = colors .into_iter() - .find_or_first(|&c| !clique_colors.contains(&Color::Tentative(c))) + .find_or_first(|&c| { + !clique_colors.contains(&Color::Tentative(c)) + }) .expect("ran out of registers :("); v.insert(Color::Final(color)); color @@ -2264,7 +2423,9 @@ impl core::fmt::Display for RipRelative { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Self::Reference(label) => write!(f, "{label}"), - RipRelative::Label(ty, label) => write!(f, "{} ptr [rip + {label}]", ty.int_repr()), + RipRelative::Label(ty, label) => { + write!(f, "{} ptr [rip + {label}]", ty.int_repr()) + } RipRelative::Offset(ty, offset) => { write!(f, "{} ptr [rip + {offset}]", ty.int_repr()) } @@ -2298,14 +2459,20 @@ impl Function { } } - pub fn finish_as_function(self, strings: &StringTable) -> Result { + pub fn finish_as_function( + self, + strings: &StringTable, + ) -> Result { let mut buf = String::new(); self.finish(&mut buf, strings)?; Ok(buf) } - pub fn finish_constants(self, strings: &StringTable) -> Result { + pub fn finish_constants( + self, + strings: &StringTable, + ) -> Result { use core::fmt::Write; let mut buf = String::new(); let w = &mut buf; @@ -2463,7 +2630,9 @@ impl Mir { let label = func.get_constant_label(node as usize); ImmRegMem::Rip(RipRelative::Label(Type::QWord, label)) } - Inst::GetElementPtr(ty) => liveness.get_register(node.into()).unwrap().into(), + Inst::GetElementPtr(ty) => { + liveness.get_register(node.into()).unwrap().into() + } Inst::Parameter(ty) | Inst::Call(ty) | Inst::Phi2(ty) @@ -2520,7 +2689,10 @@ impl Mir { } } - pub fn assemble(&self, strings: &StringTable) -> Result { + pub fn assemble( + &self, + strings: &StringTable, + ) -> Result { use core::fmt::Write; // mapping if (i, (stack_offset, bytes)) for local stack variables let mut mapping = BTreeMap::::new(); @@ -2546,7 +2718,9 @@ impl Mir { | Inst::ConstantWord | Inst::ConstantDWord | Inst::ConstantQWord => { - func.add_constant_from_inst_and_data(i, inst, data, strings); + func.add_constant_from_inst_and_data( + i, inst, data, strings, + ); } Inst::ConstantSinglePrecision => { let bits = data.as_imm32(); @@ -2558,8 +2732,12 @@ impl Mir { } Inst::LoadRegister(ty) => { let src = data.as_node(); - let dst = ty.register_width(liveness.get_register(node.into()).unwrap()); - let src = self.node_as_operand(&liveness, &mapping, &mut func, strings, src); + let dst = ty.register_width( + liveness.get_register(node.into()).unwrap(), + ); + let src = self.node_as_operand( + &liveness, &mapping, &mut func, strings, src, + ); if ty.is_floating() { match src { ImmRegMem::Byte(_) @@ -2575,7 +2753,10 @@ impl Mir { }); if spill_rax { - writeln!(func.current_branch(), "push rax")?; + writeln!( + func.current_branch(), + "push rax" + )?; } writeln!( @@ -2594,10 +2775,16 @@ impl Mir { } } ImmRegMem::Mem(_) | ImmRegMem::Rip(_) => { - writeln!(func.current_branch(), "movss {dst}, {src}",)?; + writeln!( + func.current_branch(), + "movss {dst}, {src}", + )?; } ImmRegMem::Reg(_) => { - writeln!(func.current_branch(), "movd {dst}, {src}",)?; + writeln!( + func.current_branch(), + "movd {dst}, {src}", + )?; } } } else { @@ -2611,12 +2798,21 @@ impl Mir { mapping.insert(i, (offset, size)); } Inst::Load(ty) => { - let dst = ty.register_width(liveness.get_register(node.into()).unwrap()); + let dst = ty.register_width( + liveness.get_register(node.into()).unwrap(), + ); let src = data.as_node(); - let src = self.node_as_operand(&liveness, &mapping, &mut func, strings, src); + let src = self.node_as_operand( + &liveness, &mapping, &mut func, strings, src, + ); match src { ImmRegMem::Reg(_) => { - writeln!(func.current_branch(), "mov {}, {ty} ptr [{}]", dst, src,)?; + writeln!( + func.current_branch(), + "mov {}, {ty} ptr [{}]", + dst, + src, + )?; } ImmRegMem::Mem(ref mem) => { let mut spill_rax = false; @@ -2630,8 +2826,18 @@ impl Mir { if spill_rax { writeln!(func.current_branch(), "push rax")?; } - writeln!(func.current_branch(), "mov {}, {}", scratch, src)?; - writeln!(func.current_branch(), "mov {}, [{}]", dst, scratch)?; + writeln!( + func.current_branch(), + "mov {}, {}", + scratch, + src + )?; + writeln!( + func.current_branch(), + "mov {}, [{}]", + dst, + scratch + )?; if spill_rax { writeln!(func.current_branch(), "pop rax")?; } @@ -2643,8 +2849,12 @@ impl Mir { } Inst::Store(ty) => { let (src, dst) = data.as_binary(); - let src = self.node_as_operand(&liveness, &mapping, &mut func, strings, src); - let dst = self.node_as_operand(&liveness, &mapping, &mut func, strings, dst); + let src = self.node_as_operand( + &liveness, &mapping, &mut func, strings, src, + ); + let dst = self.node_as_operand( + &liveness, &mapping, &mut func, strings, dst, + ); if src.is_floating() { writeln!(func.current_branch(), "movss {dst}, {src}")?; } else { @@ -2654,7 +2864,9 @@ impl Mir { Inst::GetElementPtr(ty) => { let dst = liveness.get_register(node.into()).unwrap(); let (src, idx) = data.as_binary(); - let src = self.node_as_operand(&liveness, &mapping, &mut func, strings, src); + let src = self.node_as_operand( + &liveness, &mapping, &mut func, strings, src, + ); if let ImmRegMem::Mem(_) = &src { writeln!(func.current_branch(), "lea {dst}, {src}",)?; @@ -2662,7 +2874,10 @@ impl Mir { let offset = idx * ty.bytes(); if offset != 0 { - writeln!(func.current_branch(), "lea {dst}, [{dst} + {offset}]",)?; + writeln!( + func.current_branch(), + "lea {dst}, [{dst} + {offset}]", + )?; } } Inst::Parameter(ty) => { @@ -2685,10 +2900,19 @@ impl Mir { let mut spilled_registers = vec![]; - let mut gprs = Register::SYSV_ARG_GPR.into_iter().rev().collect::>(); - let mut sses = Register::SYSV_ARG_SSE.into_iter().rev().collect::>(); + let mut gprs = Register::SYSV_ARG_GPR + .into_iter() + .rev() + .collect::>(); + let mut sses = Register::SYSV_ARG_SSE + .into_iter() + .rev() + .collect::>(); - if liveness.is_register_in_use_at_node(NodeRef(node), Register::rax) { + if liveness.is_register_in_use_at_node( + NodeRef(node), + Register::rax, + ) { writeln!(func.current_branch(), "push rax")?; spilled_registers.push(Register::rax); } @@ -2696,38 +2920,56 @@ impl Mir { for arg in (start + 1)..end { variant!(self.nodes[arg as usize] => Inst::Argument(ty)); let arg = self.data[arg as usize].as_node(); - let src = - self.node_as_operand(&liveness, &mapping, &mut func, strings, arg); + let src = self.node_as_operand( + &liveness, &mapping, &mut func, strings, arg, + ); if ty.is_floating() { let reg = sses.pop().unwrap(); - if liveness.is_register_in_use_at_node(NodeRef(node), reg) { + if liveness + .is_register_in_use_at_node(NodeRef(node), reg) + { writeln!(func.current_branch(), "push {reg}")?; spilled_registers.push(reg); } - writeln!(func.current_branch(), "movss {reg}, {src}")?; + writeln!( + func.current_branch(), + "movss {reg}, {src}" + )?; } else { let reg = gprs.pop().unwrap(); - if liveness.is_register_in_use_at_node(NodeRef(node), reg) { + if liveness + .is_register_in_use_at_node(NodeRef(node), reg) + { writeln!(func.current_branch(), "push {reg}")?; spilled_registers.push(reg); } let reg = ty.register_width(reg); - writeln!(func.current_branch(), "mov {reg}, {src}")?; + writeln!( + func.current_branch(), + "mov {reg}, {src}" + )?; } } let f = self.data[start as usize].as_node(); - let f = self.node_as_operand(&liveness, &mapping, &mut func, strings, f); + let f = self.node_as_operand( + &liveness, &mapping, &mut func, strings, f, + ); writeln!(func.current_branch(), "test rax, rax")?; writeln!(func.current_branch(), "call {f}")?; - let dst = ty.register_width(liveness.get_register(node.into()).unwrap()); + let dst = ty.register_width( + liveness.get_register(node.into()).unwrap(), + ); if ty.is_floating() { if dst.parent_reg() != Register::xmm0 { - writeln!(func.current_branch(), "movss {dst}, xmm0")?; + writeln!( + func.current_branch(), + "movss {dst}, xmm0" + )?; } } else { if dst.parent_reg() != Register::rax { @@ -2747,51 +2989,83 @@ impl Mir { } } Inst::Add(ty) => { - let dst = ty.register_width(liveness.get_register(node.into()).unwrap()); + let dst = ty.register_width( + liveness.get_register(node.into()).unwrap(), + ); let (lhs, rhs) = data.as_binary(); - let lhs = self.node_as_operand(&liveness, &mapping, &mut func, strings, lhs); - let rhs = self.node_as_operand(&liveness, &mapping, &mut func, strings, rhs); + let lhs = self.node_as_operand( + &liveness, &mapping, &mut func, strings, lhs, + ); + let rhs = self.node_as_operand( + &liveness, &mapping, &mut func, strings, rhs, + ); if ty.is_floating() { writeln!(func.current_branch(), "addss {lhs}, {rhs}")?; if !lhs.occupy_same_register(dst) { - writeln!(func.current_branch(), "movss {dst}, {lhs}")?; + writeln!( + func.current_branch(), + "movss {dst}, {lhs}" + )?; } } else { writeln!(func.current_branch(), "add {lhs}, {rhs}")?; if !lhs.occupy_same_register(dst) { - writeln!(func.current_branch(), "mov {dst}, {lhs}")?; + writeln!( + func.current_branch(), + "mov {dst}, {lhs}" + )?; } } } Inst::Sub(ty) => { - let dst = ty.register_width(liveness.get_register(node.into()).unwrap()); + let dst = ty.register_width( + liveness.get_register(node.into()).unwrap(), + ); let (lhs, rhs) = data.as_binary(); - let lhs = self.node_as_operand(&liveness, &mapping, &mut func, strings, lhs); - let rhs = self.node_as_operand(&liveness, &mapping, &mut func, strings, rhs); + let lhs = self.node_as_operand( + &liveness, &mapping, &mut func, strings, lhs, + ); + let rhs = self.node_as_operand( + &liveness, &mapping, &mut func, strings, rhs, + ); if ty.is_floating() { writeln!(func.current_branch(), "subss {lhs}, {rhs}")?; if !lhs.occupy_same_register(dst) { - writeln!(func.current_branch(), "movss {dst}, {lhs}")?; + writeln!( + func.current_branch(), + "movss {dst}, {lhs}" + )?; } } else { writeln!(func.current_branch(), "sub {lhs}, {rhs}")?; if !lhs.occupy_same_register(dst) { - writeln!(func.current_branch(), "mov {dst}, {lhs}")?; + writeln!( + func.current_branch(), + "mov {dst}, {lhs}" + )?; } } } Inst::Mul(ty) => { - let dst = ty.register_width(liveness.get_register(node.into()).unwrap()); + let dst = ty.register_width( + liveness.get_register(node.into()).unwrap(), + ); let (lhs, rhs) = data.as_binary(); - let lhs = self.node_as_operand(&liveness, &mapping, &mut func, strings, lhs); - let rhs = self.node_as_operand(&liveness, &mapping, &mut func, strings, rhs); + let lhs = self.node_as_operand( + &liveness, &mapping, &mut func, strings, lhs, + ); + let rhs = self.node_as_operand( + &liveness, &mapping, &mut func, strings, rhs, + ); - let spill_rax = liveness.is_register_in_use_at_node(node.into(), Register::rax) + let spill_rax = liveness + .is_register_in_use_at_node(node.into(), Register::rax) && !(lhs.occupy_same_register(Register::rax) || rhs.occupy_same_register(Register::rax) || dst.parent_reg() == Register::rax); - let spill_rdx = liveness.is_register_in_use_at_node(node.into(), Register::rdx) + let spill_rdx = liveness + .is_register_in_use_at_node(node.into(), Register::rdx) && !(lhs.occupy_same_register(Register::rdx) || rhs.occupy_same_register(Register::rdx) || dst.parent_reg() == Register::rdx); @@ -2829,16 +3103,24 @@ impl Mir { } } Inst::MulSigned(ty) => { - let dst = ty.register_width(liveness.get_register(node.into()).unwrap()); + let dst = ty.register_width( + liveness.get_register(node.into()).unwrap(), + ); let (lhs, rhs) = data.as_binary(); - let lhs = self.node_as_operand(&liveness, &mapping, &mut func, strings, lhs); - let rhs = self.node_as_operand(&liveness, &mapping, &mut func, strings, rhs); + let lhs = self.node_as_operand( + &liveness, &mapping, &mut func, strings, lhs, + ); + let rhs = self.node_as_operand( + &liveness, &mapping, &mut func, strings, rhs, + ); - let spill_rax = liveness.is_register_in_use_at_node(node.into(), Register::rax) + let spill_rax = liveness + .is_register_in_use_at_node(node.into(), Register::rax) && !(lhs.occupy_same_register(Register::rax) || rhs.occupy_same_register(Register::rax) || dst.parent_reg() == Register::rax); - let spill_rdx = liveness.is_register_in_use_at_node(node.into(), Register::rdx) + let spill_rdx = liveness + .is_register_in_use_at_node(node.into(), Register::rdx) && !(lhs.occupy_same_register(Register::rdx) || rhs.occupy_same_register(Register::rdx) || dst.parent_reg() == Register::rdx); @@ -2864,16 +3146,24 @@ impl Mir { } } Inst::Div(ty) => { - let dst = ty.register_width(liveness.get_register(node.into()).unwrap()); + let dst = ty.register_width( + liveness.get_register(node.into()).unwrap(), + ); let (lhs, rhs) = data.as_binary(); - let lhs = self.node_as_operand(&liveness, &mapping, &mut func, strings, lhs); - let rhs = self.node_as_operand(&liveness, &mapping, &mut func, strings, rhs); + let lhs = self.node_as_operand( + &liveness, &mapping, &mut func, strings, lhs, + ); + let rhs = self.node_as_operand( + &liveness, &mapping, &mut func, strings, rhs, + ); - let spill_rax = liveness.is_register_in_use_at_node(node.into(), Register::rax) + let spill_rax = liveness + .is_register_in_use_at_node(node.into(), Register::rax) && !(lhs.occupy_same_register(Register::rax) || rhs.occupy_same_register(Register::rax) || dst.parent_reg() == Register::rax); - let spill_rdx = liveness.is_register_in_use_at_node(node.into(), Register::rdx) + let spill_rdx = liveness + .is_register_in_use_at_node(node.into(), Register::rdx) && !(lhs.occupy_same_register(Register::rdx) || rhs.occupy_same_register(Register::rdx) || dst.parent_reg() == Register::rdx); @@ -2911,16 +3201,24 @@ impl Mir { } } Inst::DivSigned(ty) => { - let dst = ty.register_width(liveness.get_register(node.into()).unwrap()); + let dst = ty.register_width( + liveness.get_register(node.into()).unwrap(), + ); let (lhs, rhs) = data.as_binary(); - let lhs = self.node_as_operand(&liveness, &mapping, &mut func, strings, lhs); - let rhs = self.node_as_operand(&liveness, &mapping, &mut func, strings, rhs); + let lhs = self.node_as_operand( + &liveness, &mapping, &mut func, strings, lhs, + ); + let rhs = self.node_as_operand( + &liveness, &mapping, &mut func, strings, rhs, + ); - let spill_rax = liveness.is_register_in_use_at_node(node.into(), Register::rax) + let spill_rax = liveness + .is_register_in_use_at_node(node.into(), Register::rax) && !(lhs.occupy_same_register(Register::rax) || rhs.occupy_same_register(Register::rax) || dst.parent_reg() == Register::rax); - let spill_rdx = liveness.is_register_in_use_at_node(node.into(), Register::rdx) + let spill_rdx = liveness + .is_register_in_use_at_node(node.into(), Register::rdx) && !(lhs.occupy_same_register(Register::rdx) || rhs.occupy_same_register(Register::rdx) || dst.parent_reg() == Register::rdx); @@ -2958,16 +3256,24 @@ impl Mir { } } Inst::Rem(ty) => { - let dst = ty.register_width(liveness.get_register(node.into()).unwrap()); + let dst = ty.register_width( + liveness.get_register(node.into()).unwrap(), + ); let (lhs, rhs) = data.as_binary(); - let lhs = self.node_as_operand(&liveness, &mapping, &mut func, strings, lhs); - let rhs = self.node_as_operand(&liveness, &mapping, &mut func, strings, rhs); + let lhs = self.node_as_operand( + &liveness, &mapping, &mut func, strings, lhs, + ); + let rhs = self.node_as_operand( + &liveness, &mapping, &mut func, strings, rhs, + ); - let spill_rax = liveness.is_register_in_use_at_node(node.into(), Register::rax) + let spill_rax = liveness + .is_register_in_use_at_node(node.into(), Register::rax) && !(lhs.occupy_same_register(Register::rax) || rhs.occupy_same_register(Register::rax) || dst.parent_reg() == Register::rax); - let spill_rdx = liveness.is_register_in_use_at_node(node.into(), Register::rdx) + let spill_rdx = liveness + .is_register_in_use_at_node(node.into(), Register::rdx) && !(lhs.occupy_same_register(Register::rdx) || rhs.occupy_same_register(Register::rdx) || dst.parent_reg() == Register::rdx); @@ -3005,16 +3311,24 @@ impl Mir { } } Inst::RemSigned(ty) => { - let dst = ty.register_width(liveness.get_register(node.into()).unwrap()); + let dst = ty.register_width( + liveness.get_register(node.into()).unwrap(), + ); let (lhs, rhs) = data.as_binary(); - let lhs = self.node_as_operand(&liveness, &mapping, &mut func, strings, lhs); - let rhs = self.node_as_operand(&liveness, &mapping, &mut func, strings, rhs); + let lhs = self.node_as_operand( + &liveness, &mapping, &mut func, strings, lhs, + ); + let rhs = self.node_as_operand( + &liveness, &mapping, &mut func, strings, rhs, + ); - let spill_rax = liveness.is_register_in_use_at_node(node.into(), Register::rax) + let spill_rax = liveness + .is_register_in_use_at_node(node.into(), Register::rax) && !(lhs.occupy_same_register(Register::rax) || rhs.occupy_same_register(Register::rax) || dst.parent_reg() == Register::rax); - let spill_rdx = liveness.is_register_in_use_at_node(node.into(), Register::rdx) + let spill_rdx = liveness + .is_register_in_use_at_node(node.into(), Register::rdx) && !(lhs.occupy_same_register(Register::rdx) || rhs.occupy_same_register(Register::rdx) || dst.parent_reg() == Register::rdx); @@ -3052,10 +3366,16 @@ impl Mir { } } Inst::MulSSE(ty) => { - let dst = ty.register_width(liveness.get_register(node.into()).unwrap()); + let dst = ty.register_width( + liveness.get_register(node.into()).unwrap(), + ); let (lhs, rhs) = data.as_binary(); - let lhs = self.node_as_operand(&liveness, &mapping, &mut func, strings, lhs); - let rhs = self.node_as_operand(&liveness, &mapping, &mut func, strings, rhs); + let lhs = self.node_as_operand( + &liveness, &mapping, &mut func, strings, lhs, + ); + let rhs = self.node_as_operand( + &liveness, &mapping, &mut func, strings, rhs, + ); writeln!(func.current_branch(), "mulss {lhs}, {rhs}")?; if !lhs.occupy_same_register(dst) { @@ -3063,10 +3383,16 @@ impl Mir { } } Inst::DivSSE(ty) => { - let dst = ty.register_width(liveness.get_register(node.into()).unwrap()); + let dst = ty.register_width( + liveness.get_register(node.into()).unwrap(), + ); let (lhs, rhs) = data.as_binary(); - let lhs = self.node_as_operand(&liveness, &mapping, &mut func, strings, lhs); - let rhs = self.node_as_operand(&liveness, &mapping, &mut func, strings, rhs); + let lhs = self.node_as_operand( + &liveness, &mapping, &mut func, strings, lhs, + ); + let rhs = self.node_as_operand( + &liveness, &mapping, &mut func, strings, rhs, + ); writeln!(func.current_branch(), "divss {lhs}, {rhs}")?; if !lhs.occupy_same_register(dst) { @@ -3074,61 +3400,108 @@ impl Mir { } } Inst::RemFP(ty) => { - let dst = ty.register_width(liveness.get_register(node.into()).unwrap()); + let dst = ty.register_width( + liveness.get_register(node.into()).unwrap(), + ); let (lhs, rhs) = data.as_binary(); - let lhs = self.node_as_operand(&liveness, &mapping, &mut func, strings, lhs); - let rhs = self.node_as_operand(&liveness, &mapping, &mut func, strings, rhs); + let lhs = self.node_as_operand( + &liveness, &mapping, &mut func, strings, lhs, + ); + let rhs = self.node_as_operand( + &liveness, &mapping, &mut func, strings, rhs, + ); let ty = ty.int_repr(); let size = ty.bytes(); - writeln!(func.current_branch(), "sub rsp, 0x{:x}", size * 2)?; - writeln!(func.current_branch(), "movss {ty} ptr [rsp], {lhs}")?; + writeln!( + func.current_branch(), + "sub rsp, 0x{:x}", + size * 2 + )?; + writeln!( + func.current_branch(), + "movss {ty} ptr [rsp], {lhs}" + )?; writeln!( func.current_branch(), "movss {ty} ptr [rsp + {size}], {rhs}" )?; - writeln!(func.current_branch(), "fld {ty} ptr [rsp + {size}]")?; + writeln!( + func.current_branch(), + "fld {ty} ptr [rsp + {size}]" + )?; writeln!(func.current_branch(), "fld {ty} ptr [rsp]")?; writeln!(func.current_branch(), "fprem")?; writeln!(func.current_branch(), "fst {ty} ptr [rsp]")?; - writeln!(func.current_branch(), "movss {dst}, {ty} ptr [rsp]")?; - writeln!(func.current_branch(), "add rsp, 0x{:x}", size * 2)?; + writeln!( + func.current_branch(), + "movss {dst}, {ty} ptr [rsp]" + )?; + writeln!( + func.current_branch(), + "add rsp, 0x{:x}", + size * 2 + )?; } Inst::BitAnd(ty) => { - let dst = ty.register_width(liveness.get_register(node.into()).unwrap()); + let dst = ty.register_width( + liveness.get_register(node.into()).unwrap(), + ); let (lhs, rhs) = data.as_binary(); - let lhs = self.node_as_operand(&liveness, &mapping, &mut func, strings, lhs); - let rhs = self.node_as_operand(&liveness, &mapping, &mut func, strings, rhs); + let lhs = self.node_as_operand( + &liveness, &mapping, &mut func, strings, lhs, + ); + let rhs = self.node_as_operand( + &liveness, &mapping, &mut func, strings, rhs, + ); writeln!(func.current_branch(), "and {lhs}, {rhs}")?; if !lhs.occupy_same_register(dst) { writeln!(func.current_branch(), "mov {dst}, {lhs}")?; } } Inst::BitOr(ty) => { - let dst = ty.register_width(liveness.get_register(node.into()).unwrap()); + let dst = ty.register_width( + liveness.get_register(node.into()).unwrap(), + ); let (lhs, rhs) = data.as_binary(); - let lhs = self.node_as_operand(&liveness, &mapping, &mut func, strings, lhs); - let rhs = self.node_as_operand(&liveness, &mapping, &mut func, strings, rhs); + let lhs = self.node_as_operand( + &liveness, &mapping, &mut func, strings, lhs, + ); + let rhs = self.node_as_operand( + &liveness, &mapping, &mut func, strings, rhs, + ); writeln!(func.current_branch(), "or {lhs}, {rhs}")?; if !lhs.occupy_same_register(dst) { writeln!(func.current_branch(), "mov {dst}, {lhs}")?; } } Inst::BitXOr(ty) => { - let dst = ty.register_width(liveness.get_register(node.into()).unwrap()); + let dst = ty.register_width( + liveness.get_register(node.into()).unwrap(), + ); let (lhs, rhs) = data.as_binary(); - let lhs = self.node_as_operand(&liveness, &mapping, &mut func, strings, lhs); - let rhs = self.node_as_operand(&liveness, &mapping, &mut func, strings, rhs); + let lhs = self.node_as_operand( + &liveness, &mapping, &mut func, strings, lhs, + ); + let rhs = self.node_as_operand( + &liveness, &mapping, &mut func, strings, rhs, + ); writeln!(func.current_branch(), "xor {lhs}, {rhs}")?; if !lhs.occupy_same_register(dst) { writeln!(func.current_branch(), "mov {dst}, {lhs}")?; } } Inst::ShiftLeft(ty) => { - let dst = ty.register_width(liveness.get_register(node.into()).unwrap()); + let dst = ty.register_width( + liveness.get_register(node.into()).unwrap(), + ); let (lhs, rhs) = data.as_binary(); - let lhs = self.node_as_operand(&liveness, &mapping, &mut func, strings, lhs); - let rhs = self.node_as_operand(&liveness, &mapping, &mut func, strings, rhs); + let lhs = self.node_as_operand( + &liveness, &mapping, &mut func, strings, lhs, + ); + let rhs = self.node_as_operand( + &liveness, &mapping, &mut func, strings, rhs, + ); let lhs_is_rcx = lhs.occupy_same_register(Register::rcx); let rhs_is_rcx = rhs.occupy_same_register(Register::rcx); @@ -3136,25 +3509,43 @@ impl Mir { match rhs { ImmRegMem::Byte(v) => { - writeln!(func.current_branch(), "shl {lhs}, {}", v as u8)?; + writeln!( + func.current_branch(), + "shl {lhs}, {}", + v as u8 + )?; } ImmRegMem::DWord(v) => { - writeln!(func.current_branch(), "shl {lhs}, {}", v as u8)?; + writeln!( + func.current_branch(), + "shl {lhs}, {}", + v as u8 + )?; } ImmRegMem::QWord(v) => { - writeln!(func.current_branch(), "shl {lhs}, {}", v as u8)?; + writeln!( + func.current_branch(), + "shl {lhs}, {}", + v as u8 + )?; } ImmRegMem::Word(v) => { - writeln!(func.current_branch(), "shl {lhs}, {}", v as u8)?; + writeln!( + func.current_branch(), + "shl {lhs}, {}", + v as u8 + )?; } ImmRegMem::Reg(reg) => { // reg needs to be moved to CL // if lhs is in rcx, lhs needs to move to rax and we spill rax temporarily // if neither lhs nor rhx nor dst are rcx, spill rcx temporarily - let spill_rcx = liveness - .is_register_in_use_at_node(node.into(), Register::rcx) - && !(lhs_is_rcx || rhs_is_rcx || dst_is_rcx); + let spill_rcx = + liveness.is_register_in_use_at_node( + node.into(), + Register::rcx, + ) && !(lhs_is_rcx || rhs_is_rcx || dst_is_rcx); if spill_rcx { writeln!(func.current_branch(), "push rcx")?; @@ -3170,11 +3561,20 @@ impl Mir { } if lhs_is_rcx { - if liveness.is_register_in_use_at_node(node.into(), Register::rax) { - writeln!(func.current_branch(), "push rax")?; + if liveness.is_register_in_use_at_node( + node.into(), + Register::rax, + ) { + writeln!( + func.current_branch(), + "push rax" + )?; } - writeln!(func.current_branch(), "test rax,rax")?; + writeln!( + func.current_branch(), + "test rax,rax" + )?; writeln!( func.current_branch(), "mov {}, {lhs}", @@ -3182,15 +3582,27 @@ impl Mir { .register_width(Register::rax) )?; writeln!(func.current_branch(), "shl rax, cl")?; - writeln!(func.current_branch(), "mov {dst}, rax")?; + writeln!( + func.current_branch(), + "mov {dst}, rax" + )?; - if liveness.is_register_in_use_at_node(node.into(), Register::rax) { + if liveness.is_register_in_use_at_node( + node.into(), + Register::rax, + ) { writeln!(func.current_branch(), "pop rax")?; } } else { - writeln!(func.current_branch(), "shl {lhs}, cl")?; + writeln!( + func.current_branch(), + "shl {lhs}, cl" + )?; if lhs.occupy_same_register(dst) { - writeln!(func.current_branch(), "mov {dst}, {lhs}")?; + writeln!( + func.current_branch(), + "mov {dst}, {lhs}" + )?; } } @@ -3205,10 +3617,16 @@ impl Mir { } } Inst::ShiftRightSigned(ty) => { - let dst = ty.register_width(liveness.get_register(node.into()).unwrap()); + let dst = ty.register_width( + liveness.get_register(node.into()).unwrap(), + ); let (lhs, rhs) = data.as_binary(); - let lhs = self.node_as_operand(&liveness, &mapping, &mut func, strings, lhs); - let rhs = self.node_as_operand(&liveness, &mapping, &mut func, strings, rhs); + let lhs = self.node_as_operand( + &liveness, &mapping, &mut func, strings, lhs, + ); + let rhs = self.node_as_operand( + &liveness, &mapping, &mut func, strings, rhs, + ); let lhs_is_rcx = lhs.occupy_same_register(Register::rcx); let rhs_is_rcx = rhs.occupy_same_register(Register::rcx); @@ -3216,25 +3634,43 @@ impl Mir { match rhs { ImmRegMem::Byte(v) => { - writeln!(func.current_branch(), "sar {lhs}, {}", v as u8)?; + writeln!( + func.current_branch(), + "sar {lhs}, {}", + v as u8 + )?; } ImmRegMem::DWord(v) => { - writeln!(func.current_branch(), "sar {lhs}, {}", v as u8)?; + writeln!( + func.current_branch(), + "sar {lhs}, {}", + v as u8 + )?; } ImmRegMem::QWord(v) => { - writeln!(func.current_branch(), "sar {lhs}, {}", v as u8)?; + writeln!( + func.current_branch(), + "sar {lhs}, {}", + v as u8 + )?; } ImmRegMem::Word(v) => { - writeln!(func.current_branch(), "sar {lhs}, {}", v as u8)?; + writeln!( + func.current_branch(), + "sar {lhs}, {}", + v as u8 + )?; } ImmRegMem::Reg(reg) => { // reg needs to be moved to CL // if lhs is in rcx, lhs needs to move to rax and we spill rax temporarily // if neither lhs nor rhx nor dst are rcx, spill rcx temporarily - let spill_rcx = liveness - .is_register_in_use_at_node(node.into(), Register::rcx) - && !(lhs_is_rcx || rhs_is_rcx || dst_is_rcx); + let spill_rcx = + liveness.is_register_in_use_at_node( + node.into(), + Register::rcx, + ) && !(lhs_is_rcx || rhs_is_rcx || dst_is_rcx); if spill_rcx { writeln!(func.current_branch(), "push rcx")?; @@ -3250,10 +3686,19 @@ impl Mir { } if lhs_is_rcx { - if liveness.is_register_in_use_at_node(node.into(), Register::rax) { - writeln!(func.current_branch(), "push rax")?; + if liveness.is_register_in_use_at_node( + node.into(), + Register::rax, + ) { + writeln!( + func.current_branch(), + "push rax" + )?; } - writeln!(func.current_branch(), "test rax,rax")?; + writeln!( + func.current_branch(), + "test rax,rax" + )?; writeln!( func.current_branch(), "mov {}, {lhs}", @@ -3261,15 +3706,27 @@ impl Mir { .register_width(Register::rax) )?; writeln!(func.current_branch(), "sar rax, cl")?; - writeln!(func.current_branch(), "mov {dst}, rax")?; + writeln!( + func.current_branch(), + "mov {dst}, rax" + )?; - if liveness.is_register_in_use_at_node(node.into(), Register::rax) { + if liveness.is_register_in_use_at_node( + node.into(), + Register::rax, + ) { writeln!(func.current_branch(), "pop rax")?; } } else { - writeln!(func.current_branch(), "sar {lhs}, cl")?; + writeln!( + func.current_branch(), + "sar {lhs}, cl" + )?; if lhs.occupy_same_register(dst) { - writeln!(func.current_branch(), "mov {dst}, {lhs}")?; + writeln!( + func.current_branch(), + "mov {dst}, {lhs}" + )?; } } @@ -3284,10 +3741,16 @@ impl Mir { } } Inst::ShiftRightUnsigned(ty) => { - let dst = ty.register_width(liveness.get_register(node.into()).unwrap()); + let dst = ty.register_width( + liveness.get_register(node.into()).unwrap(), + ); let (lhs, rhs) = data.as_binary(); - let lhs = self.node_as_operand(&liveness, &mapping, &mut func, strings, lhs); - let rhs = self.node_as_operand(&liveness, &mapping, &mut func, strings, rhs); + let lhs = self.node_as_operand( + &liveness, &mapping, &mut func, strings, lhs, + ); + let rhs = self.node_as_operand( + &liveness, &mapping, &mut func, strings, rhs, + ); let lhs_is_rcx = lhs.occupy_same_register(Register::rcx); let rhs_is_rcx = rhs.occupy_same_register(Register::rcx); @@ -3295,25 +3758,43 @@ impl Mir { match rhs { ImmRegMem::Byte(v) => { - writeln!(func.current_branch(), "shr {lhs}, {}", v as u8)?; + writeln!( + func.current_branch(), + "shr {lhs}, {}", + v as u8 + )?; } ImmRegMem::DWord(v) => { - writeln!(func.current_branch(), "shr {lhs}, {}", v as u8)?; + writeln!( + func.current_branch(), + "shr {lhs}, {}", + v as u8 + )?; } ImmRegMem::QWord(v) => { - writeln!(func.current_branch(), "shr {lhs}, {}", v as u8)?; + writeln!( + func.current_branch(), + "shr {lhs}, {}", + v as u8 + )?; } ImmRegMem::Word(v) => { - writeln!(func.current_branch(), "shr {lhs}, {}", v as u8)?; + writeln!( + func.current_branch(), + "shr {lhs}, {}", + v as u8 + )?; } ImmRegMem::Reg(reg) => { // reg needs to be moved to CL // if lhs is in rcx, lhs needs to move to rax and we spill rax temporarily // if neither lhs nor rhx nor dst are rcx, spill rcx temporarily - let spill_rcx = liveness - .is_register_in_use_at_node(node.into(), Register::rcx) - && !(lhs_is_rcx || rhs_is_rcx || dst_is_rcx); + let spill_rcx = + liveness.is_register_in_use_at_node( + node.into(), + Register::rcx, + ) && !(lhs_is_rcx || rhs_is_rcx || dst_is_rcx); if spill_rcx { writeln!(func.current_branch(), "push rcx")?; @@ -3329,11 +3810,20 @@ impl Mir { } if lhs_is_rcx { - if liveness.is_register_in_use_at_node(node.into(), Register::rax) { - writeln!(func.current_branch(), "push rax")?; + if liveness.is_register_in_use_at_node( + node.into(), + Register::rax, + ) { + writeln!( + func.current_branch(), + "push rax" + )?; } - writeln!(func.current_branch(), "test rax,rax")?; + writeln!( + func.current_branch(), + "test rax,rax" + )?; writeln!( func.current_branch(), "mov {}, {lhs}", @@ -3341,15 +3831,27 @@ impl Mir { .register_width(Register::rax) )?; writeln!(func.current_branch(), "shr rax, cl")?; - writeln!(func.current_branch(), "mov {dst}, rax")?; + writeln!( + func.current_branch(), + "mov {dst}, rax" + )?; - if liveness.is_register_in_use_at_node(node.into(), Register::rax) { + if liveness.is_register_in_use_at_node( + node.into(), + Register::rax, + ) { writeln!(func.current_branch(), "pop rax")?; } } else { - writeln!(func.current_branch(), "shr {lhs}, cl")?; + writeln!( + func.current_branch(), + "shr {lhs}, cl" + )?; if lhs.occupy_same_register(dst) { - writeln!(func.current_branch(), "mov {dst}, {lhs}")?; + writeln!( + func.current_branch(), + "mov {dst}, {lhs}" + )?; } } @@ -3364,9 +3866,13 @@ impl Mir { } } Inst::Not(ty) => { - let dst = ty.register_width(liveness.get_register(node.into()).unwrap()); + let dst = ty.register_width( + liveness.get_register(node.into()).unwrap(), + ); let lhs = data.as_node(); - let lhs = self.node_as_operand(&liveness, &mapping, &mut func, strings, lhs); + let lhs = self.node_as_operand( + &liveness, &mapping, &mut func, strings, lhs, + ); writeln!(func.current_branch(), "not {lhs}")?; if !lhs.occupy_same_register(dst) { @@ -3374,27 +3880,44 @@ impl Mir { } } Inst::Negate(ty) => { - let dst = ty.register_width(liveness.get_register(node.into()).unwrap()); + let dst = ty.register_width( + liveness.get_register(node.into()).unwrap(), + ); let lhs = data.as_node(); - let lhs = self.node_as_operand(&liveness, &mapping, &mut func, strings, lhs); + let lhs = self.node_as_operand( + &liveness, &mapping, &mut func, strings, lhs, + ); if ty.is_floating() { - writeln!(func.current_branch(), "mulss {lhs}, [rip + .NEG1F32]")?; + writeln!( + func.current_branch(), + "mulss {lhs}, [rip + .NEG1F32]" + )?; if lhs != ImmRegMem::Reg(dst) { - writeln!(func.current_branch(), "movss {dst}, {lhs}")?; + writeln!( + func.current_branch(), + "movss {dst}, {lhs}" + )?; } } else { writeln!(func.current_branch(), "neg {lhs}")?; if lhs != ImmRegMem::Reg(dst) { - writeln!(func.current_branch(), "mov {dst}, {lhs}")?; + writeln!( + func.current_branch(), + "mov {dst}, {lhs}" + )?; } } } Inst::SignExtend(ty) => { - let dst = ty.register_width(liveness.get_register(node.into()).unwrap()); + let dst = ty.register_width( + liveness.get_register(node.into()).unwrap(), + ); let lhs = data.as_node(); let lhs_ty = self.type_of_node(lhs).unwrap(); - let lhs = self.node_as_operand(&liveness, &mapping, &mut func, strings, lhs); + let lhs = self.node_as_operand( + &liveness, &mapping, &mut func, strings, lhs, + ); if ty == lhs_ty { writeln!(func.current_branch(), "test {dst}, {dst}")?; @@ -3402,7 +3925,11 @@ impl Mir { } else { match lhs { ImmRegMem::Byte(v) => { - writeln!(func.current_branch(), "mov {}, {v}", dst.into_byte())?; + writeln!( + func.current_branch(), + "mov {}, {v}", + dst.into_byte() + )?; writeln!( func.current_branch(), "movsx {dst}, {}", @@ -3410,7 +3937,11 @@ impl Mir { )?; } ImmRegMem::Word(v) => { - writeln!(func.current_branch(), "mov {},{v}", dst.into_word())?; + writeln!( + func.current_branch(), + "mov {},{v}", + dst.into_word() + )?; writeln!( func.current_branch(), "movsx {dst}, {}", @@ -3418,7 +3949,11 @@ impl Mir { )?; } ImmRegMem::DWord(v) => { - writeln!(func.current_branch(), "mov {},{v}", dst.into_dword())?; + writeln!( + func.current_branch(), + "mov {},{v}", + dst.into_dword() + )?; writeln!( func.current_branch(), "movsxd {dst}, {}", @@ -3426,17 +3961,30 @@ impl Mir { )?; } ImmRegMem::QWord(v) => { - writeln!(func.current_branch(), "mov {},{v}", dst.into_qword())?; + writeln!( + func.current_branch(), + "mov {},{v}", + dst.into_qword() + )?; } ImmRegMem::Mem(mem) => match lhs_ty { Type::Byte | Type::Word => { - writeln!(func.current_branch(), "movsx {dst}, {mem}")?; + writeln!( + func.current_branch(), + "movsx {dst}, {mem}" + )?; } Type::DWord => { - writeln!(func.current_branch(), "movsxd {dst}, {mem}")?; + writeln!( + func.current_branch(), + "movsxd {dst}, {mem}" + )?; } Type::QWord => { - writeln!(func.current_branch(), "movs {dst}, {mem}")?; + writeln!( + func.current_branch(), + "movs {dst}, {mem}" + )?; } _ => { panic!("cannot sign-extend a floating register") @@ -3444,13 +3992,22 @@ impl Mir { }, ImmRegMem::Reg(reg) => match lhs_ty { Type::Byte | Type::Word => { - writeln!(func.current_branch(), "movsx {dst}, {reg}")?; + writeln!( + func.current_branch(), + "movsx {dst}, {reg}" + )?; } Type::DWord => { - writeln!(func.current_branch(), "movsxd {dst}, {reg}")?; + writeln!( + func.current_branch(), + "movsxd {dst}, {reg}" + )?; } Type::QWord => { - writeln!(func.current_branch(), "mov {dst}, {reg}")?; + writeln!( + func.current_branch(), + "mov {dst}, {reg}" + )?; } _ => { panic!("cannot sign-extend a floating register") @@ -3461,28 +4018,52 @@ impl Mir { } } Inst::ZeroExtend(ty) => { - let dst = ty.register_width(liveness.get_register(node.into()).unwrap()); + let dst = ty.register_width( + liveness.get_register(node.into()).unwrap(), + ); let lhs = data.as_node(); let lhs_ty = self.type_of_node(lhs).unwrap(); - let lhs = self.node_as_operand(&liveness, &mapping, &mut func, strings, lhs); + let lhs = self.node_as_operand( + &liveness, &mapping, &mut func, strings, lhs, + ); if ty == lhs_ty { writeln!(func.current_branch(), "test {dst}, {dst}")?; writeln!(func.current_branch(), "mov {dst}, {lhs}")?; } else { - writeln!(func.current_branch(), "test {0}, {0}", dst.parent_reg())?; + writeln!( + func.current_branch(), + "test {0}, {0}", + dst.parent_reg() + )?; match lhs { ImmRegMem::Byte(v) => { - writeln!(func.current_branch(), "mov {}, {v}", dst.into_byte())?; + writeln!( + func.current_branch(), + "mov {}, {v}", + dst.into_byte() + )?; } ImmRegMem::Word(v) => { - writeln!(func.current_branch(), "mov {}, {v}", dst.into_word())?; + writeln!( + func.current_branch(), + "mov {}, {v}", + dst.into_word() + )?; } ImmRegMem::DWord(v) => { - writeln!(func.current_branch(), "mov {}, {v}", dst.into_dword())?; + writeln!( + func.current_branch(), + "mov {}, {v}", + dst.into_dword() + )?; } ImmRegMem::QWord(v) => { - writeln!(func.current_branch(), "mov {}, {v}", dst.into_qword())?; + writeln!( + func.current_branch(), + "mov {}, {v}", + dst.into_qword() + )?; } ImmRegMem::Mem(mem) => { writeln!( @@ -3504,8 +4085,12 @@ impl Mir { } Inst::Cmp(ty) => { let (lhs, rhs) = data.as_binary(); - let lhs = self.node_as_operand(&liveness, &mapping, &mut func, strings, lhs); - let rhs = self.node_as_operand(&liveness, &mapping, &mut func, strings, rhs); + let lhs = self.node_as_operand( + &liveness, &mapping, &mut func, strings, lhs, + ); + let rhs = self.node_as_operand( + &liveness, &mapping, &mut func, strings, rhs, + ); if ty.is_floating() { writeln!(func.current_branch(), "comiss {lhs}, {rhs}")?; @@ -3519,7 +4104,8 @@ impl Mir { | Inst::IsLt(signed) | Inst::IsGe(signed) | Inst::IsLe(signed) => { - let dst = liveness.get_register(node.into()).unwrap().into_byte(); + let dst = + liveness.get_register(node.into()).unwrap().into_byte(); #[cfg_attr(rustfmt, rustfmt::skip)] let mnemonic = match inst { @@ -3535,19 +4121,32 @@ impl Mir { writeln!(func.current_branch(), "{mnemonic} {dst}")?; } Inst::IsZero(ty) => { - let dst = ty.register_width(liveness.get_register(node.into()).unwrap()); + let dst = ty.register_width( + liveness.get_register(node.into()).unwrap(), + ); let lhs = data.as_node(); - let lhs = self.node_as_operand(&liveness, &mapping, &mut func, strings, lhs); + let lhs = self.node_as_operand( + &liveness, &mapping, &mut func, strings, lhs, + ); writeln!(func.current_branch(), "mov {dst}, {lhs}")?; writeln!(func.current_branch(), "test {dst}, {dst}")?; - writeln!(func.current_branch(), "setz {}", dst.into_byte())?; + writeln!( + func.current_branch(), + "setz {}", + dst.into_byte() + )?; } Inst::ReturnValue(ty) => { let lhs = data.as_node(); - let lhs = self.node_as_operand(&liveness, &mapping, &mut func, strings, lhs); + let lhs = self.node_as_operand( + &liveness, &mapping, &mut func, strings, lhs, + ); if ty.is_floating() { if !lhs.occupy_same_register(Register::xmm0) { - writeln!(func.current_branch(), "movss xmm0, {lhs}",)?; + writeln!( + func.current_branch(), + "movss xmm0, {lhs}", + )?; } } else { if !lhs.occupy_same_register(Register::rax) { @@ -3570,21 +4169,34 @@ impl Mir { } } Inst::Branch(condition) => { - let cond = - self.node_as_operand(&liveness, &mapping, &mut func, strings, condition); + let cond = self.node_as_operand( + &liveness, &mapping, &mut func, strings, condition, + ); let (lhs, rhs) = data.as_binary(); writeln!(func.current_branch(), "test {cond}, {cond}")?; match (lhs, rhs) { _ if lhs == node + 1 => { - writeln!(func.current_branch(), "jz .{name}__L{rhs}")?; + writeln!( + func.current_branch(), + "jz .{name}__L{rhs}" + )?; } _ if rhs == node + 1 => { - writeln!(func.current_branch(), "jnz .{name}__L{lhs}")?; + writeln!( + func.current_branch(), + "jnz .{name}__L{lhs}" + )?; } _ => { - writeln!(func.current_branch(), "jnz .{name}__L{lhs}")?; - writeln!(func.current_branch(), "jz .{name}__L{rhs}")?; + writeln!( + func.current_branch(), + "jnz .{name}__L{lhs}" + )?; + writeln!( + func.current_branch(), + "jz .{name}__L{rhs}" + )?; } } } diff --git a/src/parser.rs b/src/parser.rs index a824ece..905514c 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -4,7 +4,10 @@ use itertools::Itertools; use num_bigint::{BigInt, BigUint}; use crate::{ - ast::{self, FloatingType, IntegralType, LetOrVar, Node, PrimitiveType, Tag, Type}, + ast::{ + self, FloatingType, IntegralType, LetOrVar, Node, PrimitiveType, Tag, + Type, + }, common::NextIf, comptime::{self, ComptimeNumber}, error::{AnalysisError, AnalysisErrorTag}, @@ -145,13 +148,17 @@ impl Tree { .map(|decl| { let name = match self.nodes.get_node(*decl) { Tag::FunctionDecl { proto, .. } => { - let Tag::FunctionProto { name, .. } = self.nodes.get_node(*proto) else { + let Tag::FunctionProto { name, .. } = + self.nodes.get_node(*proto) + else { unreachable!() }; self.get_ident_str(*name).unwrap().to_owned() } - Tag::GlobalDecl { name, .. } => self.get_ident_str(*name).unwrap().to_owned(), + Tag::GlobalDecl { name, .. } => { + self.get_ident_str(*name).unwrap().to_owned() + } _ => { unreachable!() } @@ -237,7 +244,10 @@ impl Tree { IntegralType { signed, bits } } - fn parse_integral_constant(token: Token, lexeme: &str) -> (BigInt, Option) { + fn parse_integral_constant( + token: Token, + lexeme: &str, + ) -> (BigInt, Option) { let radix = Radix::from_token(token).unwrap(); // TODO: figure out how to do this safely for bigger types, whether to @@ -260,9 +270,9 @@ impl Tree { let value = comptime::bigint::parse_bigint(digits.into_iter(), radix); let ty = match iter.clone().next() { - Some((_, 'u')) | Some((_, 'i')) => { - Some(Self::parse_integral_type(&lexeme[iter.next().unwrap().0..])) - } + Some((_, 'u')) | Some((_, 'i')) => Some(Self::parse_integral_type( + &lexeme[iter.next().unwrap().0..], + )), _ => None, }; @@ -272,7 +282,10 @@ impl Tree { ) } - fn parse_floating_constant(_token: Token, lexeme: &str) -> (u64, FloatingType) { + fn parse_floating_constant( + _token: Token, + lexeme: &str, + ) -> (u64, FloatingType) { // let (dot, exp) = match token { // Token::DotFloatingExpConstant => (true, true), // Token::DotFloatingConstant => (true, false), @@ -292,8 +305,12 @@ impl Tree { ); let bits = match lexeme.1 { - FloatingType::Binary32 => lexeme.0.parse::().unwrap().to_bits() as u64, - FloatingType::Binary64 => lexeme.0.parse::().unwrap().to_bits() as u64, + FloatingType::Binary32 => { + lexeme.0.parse::().unwrap().to_bits() as u64 + } + FloatingType::Binary64 => { + lexeme.0.parse::().unwrap().to_bits() as u64 + } }; (bits, lexeme.1) @@ -312,7 +329,10 @@ impl Tree { } } - pub fn parse_primitive_type(&mut self, tokens: &mut TokenIterator) -> Result { + pub fn parse_primitive_type( + &mut self, + tokens: &mut TokenIterator, + ) -> Result { let token = tokens.next().ok_or(Error::UnexpectedEndOfTokens)?; let prim = match token.token() { Token::Void => PrimitiveType::Void, @@ -327,7 +347,10 @@ impl Tree { Ok(self.nodes.push_tag(Tag::PrimitiveType(prim))) } - pub fn parse_pointer(&mut self, tokens: &mut TokenIterator) -> Result { + pub fn parse_pointer( + &mut self, + tokens: &mut TokenIterator, + ) -> Result { tokens.expect_token(Token::Star)?; let _constness = tokens.eat_token(Token::Const); let typename = self.parse_typename(tokens)?; @@ -335,15 +358,21 @@ impl Tree { Ok(self.nodes.push_tag(Tag::Pointer { pointee: typename })) } - pub fn parse_typename(&mut self, tokens: &mut TokenIterator) -> Result { + pub fn parse_typename( + &mut self, + tokens: &mut TokenIterator, + ) -> Result { match tokens.peek_token_or_err()?.token() { Token::Star => self.parse_pointer(tokens), Token::Ident => { let token = tokens.next().unwrap(); match Self::try_parse_integral_type(token.lexeme())? { - Some(int) => Ok(self.nodes.push_tag(Tag::IntegralType(int))), + Some(int) => { + Ok(self.nodes.push_tag(Tag::IntegralType(int))) + } None => { - let name = self.strings.insert(token.lexeme().as_bytes()); + let name = + self.strings.insert(token.lexeme().as_bytes()); Ok(self.nodes.push_tag(Tag::Ident { name })) } } @@ -352,7 +381,10 @@ impl Tree { } } - pub fn parse_var_decl(&mut self, tokens: &mut TokenIterator) -> Result { + pub fn parse_var_decl( + &mut self, + tokens: &mut TokenIterator, + ) -> Result { let let_or_var = match tokens .eat_token(Token::Let) .or_else(|| tokens.eat_token(Token::Var)) @@ -400,7 +432,10 @@ impl Tree { /// GLOBAL_DECL <- /// const IDENTIFIER (: TYPENAME)? = EXPR; - pub fn parse_global_decl(&mut self, tokens: &mut TokenIterator) -> Result { + pub fn parse_global_decl( + &mut self, + tokens: &mut TokenIterator, + ) -> Result { _ = tokens.expect_token(Token::Const)?; let name = self.parse_ident(tokens)?; @@ -445,7 +480,10 @@ impl Tree { /// PARAMETER <- /// IDENTIFIER : TYPENAME - pub fn parse_parameter(&mut self, tokens: &mut TokenIterator) -> Result { + pub fn parse_parameter( + &mut self, + tokens: &mut TokenIterator, + ) -> Result { let name = self.parse_ident(tokens)?; tokens.expect_token(Token::Colon)?; let ty = self.parse_typename(tokens)?; @@ -464,7 +502,10 @@ impl Tree { /// PARAMETER_LIST <- /// PARAMETER /// PARAMETER_LIST , PARAMETER - pub fn parse_parameter_list(&mut self, tokens: &mut TokenIterator) -> Result { + pub fn parse_parameter_list( + &mut self, + tokens: &mut TokenIterator, + ) -> Result { let mut parameters = Vec::new(); loop { @@ -489,7 +530,10 @@ impl Tree { /// fn IDENTIFIER () -> TYPENAME /// fn IDENTIFIER ( PARAMETER_LIST ,? ) /// fn IDENTIFIER ( PARAMETER_LIST ,? ) -> TYPENAME - pub fn parse_fn_proto(&mut self, tokens: &mut TokenIterator) -> Result<(Node, Node)> { + pub fn parse_fn_proto( + &mut self, + tokens: &mut TokenIterator, + ) -> Result<(Node, Node)> { tokens.expect_token(Token::Fn)?; let name = self.parse_ident(tokens)?; tokens.expect_token(Token::OpenParens)?; @@ -520,7 +564,10 @@ impl Tree { /// FUNCTION_DECL <- /// FUNCTION_PROTO BLOCK - pub fn parse_fn_decl(&mut self, tokens: &mut TokenIterator) -> Result { + pub fn parse_fn_decl( + &mut self, + tokens: &mut TokenIterator, + ) -> Result { let (proto, name) = self.parse_fn_proto(tokens)?; let decl = match self @@ -530,8 +577,10 @@ impl Tree { Some(record) => record.node(), None => { let decl = self.nodes.reserve_node(); - self.st - .insert_orderless_symbol(&self.get_ident_str(name).unwrap().to_owned(), decl); + self.st.insert_orderless_symbol( + &self.get_ident_str(name).unwrap().to_owned(), + decl, + ); decl } }; @@ -541,7 +590,9 @@ impl Tree { let body = self.parse_block(tokens, Some(block))?; let unresolved = self .st - .extract_orderless_if(|_, v| self.nodes.get_node(v.node()) == &Tag::Undefined) + .extract_orderless_if(|_, v| { + self.nodes.get_node(v.node()) == &Tag::Undefined + }) .collect::>(); self.st.into_parent(); self.st.extend_orderless(unresolved); @@ -615,7 +666,10 @@ impl Tree { /// ASSIGNMENT_EXPR <- /// BINARY_EXPRESSION /// BINARY_EXPRESSION ASSIGNMENT_OP EXPRESSION - pub fn parse_assignment_expr(&mut self, tokens: &mut TokenIterator) -> Result { + pub fn parse_assignment_expr( + &mut self, + tokens: &mut TokenIterator, + ) -> Result { let lhs = self.parse_binary_expr(tokens, 0)?; Ok(self.try_parse_assignment(lhs, tokens)?.unwrap_or(lhs)) @@ -643,12 +697,24 @@ impl Tree { Token::MinusEqual => self.nodes.push_tag(Tag::Sub { lhs, rhs }), Token::StarEqual => self.nodes.push_tag(Tag::Mul { lhs, rhs }), Token::SlashEqual => self.nodes.push_tag(Tag::Sub { lhs, rhs }), - Token::PercentEqual => self.nodes.push_tag(Tag::Rem { lhs, rhs }), - Token::PipeEqual => self.nodes.push_tag(Tag::BitOr { lhs, rhs }), - Token::CaretEqual => self.nodes.push_tag(Tag::BitXOr { lhs, rhs }), - Token::AmpersandEqual => self.nodes.push_tag(Tag::BitAnd { lhs, rhs }), - Token::LessLessEqual => self.nodes.push_tag(Tag::Shl { lhs, rhs }), - Token::GreaterGreaterEqual => self.nodes.push_tag(Tag::Shr { lhs, rhs }), + Token::PercentEqual => { + self.nodes.push_tag(Tag::Rem { lhs, rhs }) + } + Token::PipeEqual => { + self.nodes.push_tag(Tag::BitOr { lhs, rhs }) + } + Token::CaretEqual => { + self.nodes.push_tag(Tag::BitXOr { lhs, rhs }) + } + Token::AmpersandEqual => { + self.nodes.push_tag(Tag::BitAnd { lhs, rhs }) + } + Token::LessLessEqual => { + self.nodes.push_tag(Tag::Shl { lhs, rhs }) + } + Token::GreaterGreaterEqual => { + self.nodes.push_tag(Tag::Shr { lhs, rhs }) + } Token::Equal => rhs, _ => { unreachable!() @@ -662,7 +728,10 @@ impl Tree { /// RETURN_STATEMENT <- /// return EXPRESSION? ; - pub fn try_parse_return_stmt(&mut self, tokens: &mut TokenIterator) -> Result> { + pub fn try_parse_return_stmt( + &mut self, + tokens: &mut TokenIterator, + ) -> Result> { if tokens.eat_token(Token::Return).is_some() { let expr = if !tokens.is_next_token(Token::Semi) { let expr = Some(self.parse_expr(tokens)?); @@ -683,7 +752,10 @@ impl Tree { /// RETURN_EXPRESSION /// VAR_DECL ; /// EXPRESSION ; - pub fn parse_statement(&mut self, tokens: &mut TokenIterator) -> Result { + pub fn parse_statement( + &mut self, + tokens: &mut TokenIterator, + ) -> Result { match tokens.peek_token_or_err()?.token() { Token::Return => Ok(self.try_parse_return_stmt(tokens)?.unwrap()), Token::Var | Token::Let => { @@ -779,7 +851,10 @@ impl Tree { /// - POSTFIX_EXPR /// & POSTFIX_EXPR /// * POSTFIX_EXPR - pub fn parse_prefix_expr(&mut self, tokens: &mut TokenIterator) -> Result { + pub fn parse_prefix_expr( + &mut self, + tokens: &mut TokenIterator, + ) -> Result { match tokens.peek_token_or_err()?.token() { Token::Bang => { _ = tokens.next(); @@ -808,7 +883,10 @@ impl Tree { /// AS_EXPR <- /// PREFIX_EXPR /// PREFIX_EXPR as TYPENAME - pub fn parse_as_expr(&mut self, tokens: &mut TokenIterator) -> Result { + pub fn parse_as_expr( + &mut self, + tokens: &mut TokenIterator, + ) -> Result { let expr = self.parse_prefix_expr(tokens)?; if tokens.eat_token(Token::As).is_some() { @@ -825,7 +903,10 @@ impl Tree { /// ARGUMENT <- /// IDENT : EXPR /// EXPR - pub fn parse_argument(&mut self, tokens: &mut TokenIterator) -> Result { + pub fn parse_argument( + &mut self, + tokens: &mut TokenIterator, + ) -> Result { if tokens.is_next_token2(Token::Colon) { let name = self.parse_ident(tokens)?; _ = tokens.expect_token(Token::Colon)?; @@ -843,7 +924,10 @@ impl Tree { /// ARGUMENT_LIST <- /// ARGUMENT /// ARGUMENT_LIST , ARGUMENT - pub fn parse_argument_list(&mut self, tokens: &mut TokenIterator) -> Result { + pub fn parse_argument_list( + &mut self, + tokens: &mut TokenIterator, + ) -> Result { let mut arguments = Vec::new(); loop { @@ -867,7 +951,10 @@ impl Tree { /// PRIMARY_EXPR /// PRIMARY_EXPR ( ) /// PRIMARY_EXPR ( ARGUMENT_LIST ) - pub fn parse_postfix_expr(&mut self, tokens: &mut TokenIterator) -> Result { + pub fn parse_postfix_expr( + &mut self, + tokens: &mut TokenIterator, + ) -> Result { let lhs = self.parse_primary_expr(tokens)?; if tokens.eat_token(Token::OpenParens).is_some() { @@ -893,7 +980,10 @@ impl Tree { /// FLOATING_CONSTANT /// ( EXPRESSION ) /// { STATEMENT* EXPRESSION? } - pub fn parse_primary_expr(&mut self, tokens: &mut TokenIterator) -> Result { + pub fn parse_primary_expr( + &mut self, + tokens: &mut TokenIterator, + ) -> Result { let token = tokens.peek_token_or_err()?; match token.token() { Token::Ident => { @@ -902,12 +992,16 @@ impl Tree { let name = ident.lexeme(); if let Some(record) = self.st.find_ordered_symbol(name) { Ok(self.nodes.push_tag(Tag::DeclRef(record.node()))) - } else if let Some(record) = self.st.find_orderless_symbol(name) { + } else if let Some(record) = self.st.find_orderless_symbol(name) + { Ok(self.nodes.push_tag(Tag::GlobalRef(record.node()))) } else { let node = self .st - .insert_orderless_symbol(name, self.nodes.reserve_node()) + .insert_orderless_symbol( + name, + self.nodes.reserve_node(), + ) .node(); Ok(self.nodes.push_tag(Tag::GlobalRef(node))) @@ -918,7 +1012,10 @@ impl Tree { | Token::IntegerOctConstant | Token::IntegerConstant => { _ = tokens.next(); - let (bits, ty) = Self::parse_integral_constant(token.token(), token.lexeme()); + let (bits, ty) = Self::parse_integral_constant( + token.token(), + token.lexeme(), + ); let (_, bytes) = bits.to_bytes_le(); const BUF_SIZE: usize = core::mem::size_of::(); @@ -927,12 +1024,14 @@ impl Tree { .copy_from_slice(&bytes[..bytes.len().min(BUF_SIZE)]); let bytes = match bytes.len() { 0..2 => { - let (buf, _) = buf.split_at(core::mem::size_of::()); + let (buf, _) = + buf.split_at(core::mem::size_of::()); let dw = u32::from_le_bytes(buf.try_into().unwrap()); ImmOrIndex::U32(dw) } 0..4 => { - let (buf, _) = buf.split_at(core::mem::size_of::()); + let (buf, _) = + buf.split_at(core::mem::size_of::()); let qw = u64::from_le_bytes(buf.try_into().unwrap()); ImmOrIndex::U64(qw) } @@ -954,7 +1053,10 @@ impl Tree { | Token::DotFloatingConstant | Token::DotFloatingExpConstant => { _ = tokens.next(); - let (bits, ty) = Self::parse_floating_constant(token.token(), token.lexeme()); + let (bits, ty) = Self::parse_floating_constant( + token.token(), + token.lexeme(), + ); let bytes = match ty { FloatingType::Binary32 => ImmOrIndex::U32(bits as u32), @@ -984,7 +1086,10 @@ impl Tree { /// BLOCK /// EXPR /// EXPR ; - pub fn parse_expr_or_stmt_or_block(&mut self, tokens: &mut TokenIterator) -> Result { + pub fn parse_expr_or_stmt_or_block( + &mut self, + tokens: &mut TokenIterator, + ) -> Result { let peek = tokens.peek_token_or_err()?; let body = match peek.token() { // block @@ -1015,7 +1120,10 @@ impl Tree { /// ELSE_EXPR <- /// 'else' (IF_EXPR | EXPR_OR_STATEMENT_OR_BLOCK) - pub fn try_parse_else_expr(&mut self, tokens: &mut TokenIterator) -> Result> { + pub fn try_parse_else_expr( + &mut self, + tokens: &mut TokenIterator, + ) -> Result> { if tokens.eat_token(Token::Else).is_none() { return Ok(None); } @@ -1030,7 +1138,10 @@ impl Tree { /// IF_EXPR <- /// 'if' ( EXPR ) EXPR_OR_STATEMENT_OR_BLOCK ELSE_EXPR? - pub fn try_parse_if_expr(&mut self, tokens: &mut TokenIterator) -> Result> { + pub fn try_parse_if_expr( + &mut self, + tokens: &mut TokenIterator, + ) -> Result> { if tokens.eat_token(Token::If).is_none() { return Ok(None); } @@ -1054,7 +1165,10 @@ impl Tree { /// IF_EXPR <- /// 'if' ( EXPR ) EXPR_OR_STATEMENT_OR_BLOCK ELSE_EXPR? - pub fn parse_if_expr(&mut self, tokens: &mut TokenIterator) -> Result { + pub fn parse_if_expr( + &mut self, + tokens: &mut TokenIterator, + ) -> Result { self.try_parse_if_expr(tokens)? .ok_or(Error::ExpectedTokenNotFound(Token::If)) } @@ -1146,7 +1260,9 @@ impl Tree { } children } - Tag::ReturnStmt { expr } => expr.into_iter().cloned().collect::>(), + Tag::ReturnStmt { expr } => { + expr.into_iter().cloned().collect::>() + } &Tag::ExprStmt { expr } => { vec![expr] } @@ -1193,7 +1309,10 @@ impl Tree { &Tag::ExplicitCast { lhs, typename } => { vec![lhs, typename] } - Tag::Deref { lhs } | Tag::Ref { lhs } | Tag::Not { lhs } | Tag::Negate { lhs } => { + Tag::Deref { lhs } + | Tag::Ref { lhs } + | Tag::Not { lhs } + | Tag::Negate { lhs } => { vec![*lhs] } Tag::Or { lhs, rhs } @@ -1240,8 +1359,17 @@ impl Tree { if let Some(parameters) = parameters { self.render_node(writer, parameters, indent)?; } - write_indented!(indent, writer, "%{} = function_proto: {{", node.get())?; - write!(writer, "name: \"{}\"", self.get_ident_str(name).unwrap())?; + write_indented!( + indent, + writer, + "%{} = function_proto: {{", + node.get() + )?; + write!( + writer, + "name: \"{}\"", + self.get_ident_str(name).unwrap() + )?; if let Some(parameters) = parameters { write!(writer, ", parameters: %{}", parameters.get())?; } @@ -1249,7 +1377,12 @@ impl Tree { writeln!(writer, "}}") } Tag::ParameterList { parameters } => { - writeln_indented!(indent, writer, "%{} = ParameterList [", node.get())?; + writeln_indented!( + indent, + writer, + "%{} = ParameterList [", + node.get() + )?; for param in parameters { self.render_node(writer, param, indent + 1)?; } @@ -1265,7 +1398,9 @@ impl Tree { self.get_typename_str(ty).unwrap() ) } - Tag::Pointer { .. } | Tag::IntegralType(_) | Tag::PrimitiveType(_) => { + Tag::Pointer { .. } + | Tag::IntegralType(_) + | Tag::PrimitiveType(_) => { writeln_indented!( indent, writer, @@ -1322,9 +1457,20 @@ impl Tree { Tag::ReturnStmt { expr } => { if let Some(expr) = expr { self.render_node(writer, expr, indent)?; - writeln_indented!(indent, writer, "%{} = return %{};", node.get(), expr.get()) + writeln_indented!( + indent, + writer, + "%{} = return %{};", + node.get(), + expr.get() + ) } else { - writeln_indented!(indent, writer, "%{} = return;", node.get()) + writeln_indented!( + indent, + writer, + "%{} = return;", + node.get() + ) } } Tag::ExprStmt { expr } => self.render_node(writer, expr, indent), @@ -1335,7 +1481,8 @@ impl Tree { assignment, } => { self.render_node(writer, name, indent)?; - explicit_type.map(|node| self.render_node(writer, node, indent)); + explicit_type + .map(|node| self.render_node(writer, node, indent)); assignment.map(|node| self.render_node(writer, node, indent)); write_indented!( @@ -1354,7 +1501,11 @@ impl Tree { self.get_ident_str(name).unwrap() )?; if let Some(ty) = explicit_type { - write!(writer, ", ty: {}", self.get_typename_str(ty).unwrap())?; + write!( + writer, + ", ty: {}", + self.get_typename_str(ty).unwrap() + )?; } if let Some(assignment) = assignment { write!(writer, ", value: %{assignment}")?; @@ -1378,7 +1529,11 @@ impl Tree { self.get_ident_str(name).unwrap() )?; if let Some(ty) = explicit_type { - write!(writer, ", ty: {}", self.get_typename_str(ty).unwrap())?; + write!( + writer, + ", ty: {}", + self.get_typename_str(ty).unwrap() + )?; } write!(writer, ", value: %{assignment}")?; writeln!(writer, ");")?; @@ -1388,13 +1543,26 @@ impl Tree { self.render_node(writer, lhs, indent)?; if let Some(rhs) = rhs { self.render_node(writer, rhs, indent)?; - writeln_indented!(indent, writer, "%{node} = call (%{lhs})(%{rhs})") + writeln_indented!( + indent, + writer, + "%{node} = call (%{lhs})(%{rhs})" + ) } else { - writeln_indented!(indent, writer, "%{node} = call (%{lhs})()") + writeln_indented!( + indent, + writer, + "%{node} = call (%{lhs})()" + ) } } Tag::ArgumentList { arguments } => { - writeln_indented!(indent, writer, "%{} = ArgumentList [", node.get())?; + writeln_indented!( + indent, + writer, + "%{} = ArgumentList [", + node.get() + )?; for args in arguments { self.render_node(writer, args, indent + 1)?; } @@ -1410,7 +1578,12 @@ impl Tree { self.get_ident_str(name).unwrap(), ) } else { - writeln_indented!(indent, writer, "%{} = %{expr},", node.get(),) + writeln_indented!( + indent, + writer, + "%{} = %{expr},", + node.get(), + ) } } @@ -1427,7 +1600,13 @@ impl Tree { } Tag::Deref { lhs } => { self.render_node(writer, lhs, indent)?; - writeln_indented!(indent, writer, "%{} = deref(%{})", node.get(), lhs.get()) + writeln_indented!( + indent, + writer, + "%{} = deref(%{})", + node.get(), + lhs.get() + ) } Tag::Ref { lhs } => { self.render_node(writer, lhs, indent)?; @@ -1445,7 +1624,13 @@ impl Tree { } Tag::Negate { lhs } => { self.render_node(writer, lhs, indent)?; - writeln_indented!(indent, writer, "%{} = not(%{})", node.get(), lhs.get()) + writeln_indented!( + indent, + writer, + "%{} = not(%{})", + node.get(), + lhs.get() + ) } Tag::Or { lhs, rhs } => { self.render_node(writer, lhs, indent)?; @@ -1753,7 +1938,10 @@ impl Tree { } } - pub fn render(&mut self, writer: &mut W) -> core::fmt::Result { + pub fn render( + &mut self, + writer: &mut W, + ) -> core::fmt::Result { for decl in &self.global_decls.clone() { self.render_node(writer, *decl, 0)?; } @@ -1851,7 +2039,9 @@ impl Tree { (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})") + &format!( + "incompatible types for %{a}({at}) and %{b}({bt})" + ) }), }; @@ -1876,7 +2066,9 @@ impl Tree { ty } - Tag::CallExpr { lhs, .. } => self.type_of_node(*lhs).return_type().unwrap().clone(), + Tag::CallExpr { lhs, .. } => { + self.type_of_node(*lhs).return_type().unwrap().clone() + } Tag::ExplicitCast { typename, .. } => self.type_of_node(*typename), Tag::Deref { lhs } => self.type_of_node(*lhs).remove_ptr().unwrap(), Tag::Ref { lhs } => self.type_of_node(*lhs).into_ptr(), @@ -1892,11 +2084,15 @@ impl Tree { | 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::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::Shr { lhs, .. } => self.type_of_node(*lhs), Tag::Eq { .. } => Type::bool(), @@ -1970,7 +2166,9 @@ impl Tree { is_comptime } - Tag::Not { lhs } | Tag::Negate { lhs } => self.is_node_comptime(*lhs, true), + Tag::Not { lhs } | Tag::Negate { lhs } => { + self.is_node_comptime(*lhs, true) + } Tag::Or { lhs, rhs } | Tag::And { lhs, rhs } | Tag::BitOr { lhs, rhs } @@ -1989,7 +2187,8 @@ impl Tree { | Tag::Mul { lhs, rhs } | Tag::Rem { lhs, rhs } | Tag::Div { lhs, rhs } => { - self.is_node_comptime(*lhs, true) && self.is_node_comptime(*rhs, true) + self.is_node_comptime(*lhs, true) + && self.is_node_comptime(*rhs, true) } _ => false, } @@ -2008,11 +2207,15 @@ impl Tree { let number: ComptimeNumber = match ty { Type::Bool => (bytes[0] != 0).into(), Type::ComptimeNumber => { - BigInt::from_bytes_le(num_bigint::Sign::Plus, bytes).into() + BigInt::from_bytes_le(num_bigint::Sign::Plus, bytes) + .into() } Type::Integer(ty) => { if bytes.len() > core::mem::size_of::() { - let bits = BigInt::from_bytes_le(num_bigint::Sign::Plus, bytes); + let bits = BigInt::from_bytes_le( + num_bigint::Sign::Plus, + bytes, + ); (bits, *ty).into() } else { let mut buf = [0u8; core::mem::size_of::()]; @@ -2022,12 +2225,14 @@ impl Tree { } } 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() - } + 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!(), }; @@ -2098,26 +2303,33 @@ impl Tree { let number: ComptimeNumber = match ty { Type::Bool => (bytes[0] != 0).into(), Type::ComptimeNumber => { - BigInt::from_bytes_le(num_bigint::Sign::Plus, bytes).into() + BigInt::from_bytes_le(num_bigint::Sign::Plus, bytes) + .into() } Type::Integer(ty) => { if bytes.len() > core::mem::size_of::() { - let bits = BigInt::from_bytes_le(num_bigint::Sign::Plus, bytes); + let bits = BigInt::from_bytes_le( + num_bigint::Sign::Plus, + bytes, + ); (bits, *ty).into() } else { - let mut buf = [0u8; core::mem::size_of::()]; + let mut buf = + [0u8; core::mem::size_of::()]; 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() - } + 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!(), }; @@ -2337,7 +2549,8 @@ impl Tree { match self.nodes[node].clone() { Tag::FunctionProto { .. } => {} Tag::FunctionDecl { proto, body } => { - let Tag::FunctionProto { return_type, .. } = self.nodes[proto] else { + let Tag::FunctionProto { return_type, .. } = self.nodes[proto] + else { unreachable!() }; @@ -2346,7 +2559,8 @@ impl Tree { if let Some(peer_t) = body_t.equal_type(&ret_t) { if body_t == Type::comptime_number() { - let Tag::Block { trailing_expr, .. } = self.nodes[body] else { + let Tag::Block { trailing_expr, .. } = self.nodes[body] + else { unreachable!() }; if let Some(expr) = trailing_expr { @@ -2360,7 +2574,9 @@ impl Tree { typename: ty, }); - let Tag::Block { trailing_expr, .. } = &mut self.nodes[body] else { + let Tag::Block { trailing_expr, .. } = + &mut self.nodes[body] + else { unreachable!() }; *trailing_expr = Some(expr) @@ -2376,7 +2592,10 @@ impl Tree { let bits = self.strings.count_bits(bytes); if bits < ty.bit_width() as u32 { errors.push(AnalysisError::new( - AnalysisErrorTag::InsufficientBitsInTypeForConstant(bits, ty.clone()), + AnalysisErrorTag::InsufficientBitsInTypeForConstant( + bits, + ty.clone(), + ), )); } } diff --git a/src/string_table.rs b/src/string_table.rs index 328bf06..fb74d42 100644 --- a/src/string_table.rs +++ b/src/string_table.rs @@ -55,7 +55,10 @@ impl StringTable { ImmOrIndex::Index(idx) => { let bytes = self.get_bytes(idx); let ints = unsafe { - core::slice::from_raw_parts(bytes.as_ptr().cast::(), bytes.len() / 4) + core::slice::from_raw_parts( + bytes.as_ptr().cast::(), + bytes.len() / 4, + ) }; bigint::count_bits(ints) as u32 } @@ -117,7 +120,10 @@ mod display { str: Option<&'a str>, } impl<'a> Debug for Test<'a> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + fn fmt( + &self, + f: &mut std::fmt::Formatter<'_>, + ) -> std::fmt::Result { write!(f, "{{ bytes: {:x?}", self.bytes)?; if let Some(str) = self.str { write!(f, ", str: {}", str)?; diff --git a/src/symbol_table.rs b/src/symbol_table.rs index b690c4c..7ca8de5 100644 --- a/src/symbol_table.rs +++ b/src/symbol_table.rs @@ -35,13 +35,25 @@ impl SymbolPath { for node in self.0.iter().skip(1).rev() { match tree.nodes.get_node(node.unwrap()) { Tag::VarDecl { name, .. } => { - _ = write!(&mut buf, "V{}::", tree.get_ident_str(*name).unwrap()); + _ = write!( + &mut buf, + "V{}::", + tree.get_ident_str(*name).unwrap() + ); } Tag::GlobalDecl { name, .. } => { - _ = write!(&mut buf, "G{}::", tree.get_ident_str(*name).unwrap()); + _ = write!( + &mut buf, + "G{}::", + tree.get_ident_str(*name).unwrap() + ); } Tag::FunctionProto { name, .. } => { - _ = write!(&mut buf, "F{}::", tree.get_ident_str(*name).unwrap()); + _ = write!( + &mut buf, + "F{}::", + tree.get_ident_str(*name).unwrap() + ); } _ => {} } @@ -130,7 +142,12 @@ impl Drop for InnerSymbolTable { } impl InnerSymbolTable { - fn insert_symbol(&mut self, name: &str, node: AstNode, kind: SymbolKind) -> &SymbolRecord { + fn insert_symbol( + &mut self, + name: &str, + node: AstNode, + kind: SymbolKind, + ) -> &SymbolRecord { match kind { SymbolKind::Var => { self.ordered_identifiers.push(SymbolRecord { @@ -143,7 +160,11 @@ impl InnerSymbolTable { } } - fn insert_orderless_symbol(&mut self, name: &str, node: AstNode) -> &SymbolRecord { + fn insert_orderless_symbol( + &mut self, + name: &str, + node: AstNode, + ) -> &SymbolRecord { self.orderless_identifiers.insert( name.to_owned(), SymbolRecord { @@ -154,7 +175,11 @@ impl InnerSymbolTable { self.orderless_identifiers.get(name).unwrap() } - fn find_symbol_or_insert_with<'a, F>(&'a mut self, name: &str, cb: F) -> &'a SymbolRecord + fn find_symbol_or_insert_with<'a, F>( + &'a mut self, + name: &str, + cb: F, + ) -> &'a SymbolRecord where F: FnOnce() -> (AstNode, SymbolKind), { @@ -177,7 +202,9 @@ impl InnerSymbolTable { .find(|(_, v)| v.decl == decl) .map(|(_, v)| v) }) - .or_else(|| self.parent_ref().and_then(|p| p.find_symbol_by_decl(decl))) + .or_else(|| { + self.parent_ref().and_then(|p| p.find_symbol_by_decl(decl)) + }) } fn find_any_symbol(&self, name: &str) -> Option<&SymbolRecord> { @@ -192,7 +219,9 @@ impl InnerSymbolTable { self.ordered_identifiers .iter() .find(|r| r.name.as_str() == name) - .or_else(|| self.parent_ref().and_then(|p| p.find_ordered_symbol(name))) + .or_else(|| { + self.parent_ref().and_then(|p| p.find_ordered_symbol(name)) + }) } fn find_orderless_symbol(&self, name: &str) -> Option<&SymbolRecord> { @@ -286,7 +315,12 @@ impl SymbolTableWrapper { } impl SymbolTableWrapper { - pub fn insert_symbol(&mut self, name: &str, node: AstNode, kind: SymbolKind) -> &SymbolRecord { + pub fn insert_symbol( + &mut self, + name: &str, + node: AstNode, + kind: SymbolKind, + ) -> &SymbolRecord { self.current_mut().insert_symbol(name, node, kind) } @@ -294,15 +328,27 @@ impl SymbolTableWrapper { self.root_mut().find_orderless_symbol(name) } - pub fn insert_root_symbol(&mut self, name: &str, node: AstNode) -> &SymbolRecord { + pub fn insert_root_symbol( + &mut self, + name: &str, + node: AstNode, + ) -> &SymbolRecord { self.root_mut().insert_orderless_symbol(name, node) } - pub fn insert_orderless_symbol(&mut self, name: &str, node: AstNode) -> &SymbolRecord { + pub fn insert_orderless_symbol( + &mut self, + name: &str, + node: AstNode, + ) -> &SymbolRecord { self.current_mut().insert_orderless_symbol(name, node) } - pub fn find_symbol_or_insert_with<'a, F>(&'a mut self, name: &str, cb: F) -> &'a SymbolRecord + pub fn find_symbol_or_insert_with<'a, F>( + &'a mut self, + name: &str, + cb: F, + ) -> &'a SymbolRecord where F: FnOnce() -> (AstNode, SymbolKind), { @@ -480,7 +526,9 @@ pub mod syms2 { } let entries = self.inner.iter().map(|(key, val)| { let payload = match key { - Key::ScopeByIndex { .. } => ExpandedPayload::Intern(val.as_intern()), + Key::ScopeByIndex { .. } => { + ExpandedPayload::Intern(val.as_intern()) + } _ => ExpandedPayload::Ast(val.as_ast()), }; @@ -589,8 +637,10 @@ pub mod syms2 { kind: SymbolKind, ast: AstIndex, ) { - self.inner - .insert(Key::Symbol { scope, name, kind }, Payload::new_ast(ast)); + self.inner.insert( + Key::Symbol { scope, name, kind }, + Payload::new_ast(ast), + ); } } } diff --git a/src/triples.rs b/src/triples.rs index 8d0c392..eb6577b 100644 --- a/src/triples.rs +++ b/src/triples.rs @@ -38,7 +38,9 @@ impl Into for Type2 { impl Type2 { fn mir_type(self) -> mir::Type { match self { - Type2::Integral(_, bits) => mir::Type::from_bitsize_int(bits as u32), + Type2::Integral(_, bits) => { + mir::Type::from_bitsize_int(bits as u32) + } Type2::Binary32 => mir::Type::SinglePrecision, Type2::Binary64 => mir::Type::DoublePrecision, Type2::Bool => mir::Type::from_bitsize_int(1), @@ -94,7 +96,9 @@ impl Type2 { impl core::fmt::Display for Type2 { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { - Type2::Integral(signed, bits) => write!(f, "{}{bits}", if *signed { "i" } else { "u" }), + Type2::Integral(signed, bits) => { + write!(f, "{}{bits}", if *signed { "i" } else { "u" }) + } Type2::Binary32 => write!(f, "f32"), Type2::Binary64 => write!(f, "f64"), Type2::Bool => write!(f, "bool"), @@ -121,7 +125,9 @@ impl From<&Type> for Type2 { Type::Pointer { .. } => Type2::Pointer, Type::Fn { .. } => Type2::Pointer, _ => { - unimplemented!("conversion from {value:?} to triples type not implemented") + unimplemented!( + "conversion from {value:?} to triples type not implemented" + ) } } } @@ -217,7 +223,9 @@ pub enum Inst { impl Inst { fn is_constant(self) -> bool { match self { - Inst::ConstantU32 | Inst::ConstantU64 | Inst::ConstantMultiByte => true, + Inst::ConstantU32 | Inst::ConstantU64 | Inst::ConstantMultiByte => { + true + } _ => false, } @@ -357,23 +365,30 @@ impl<'tree, 'ir> IRBuilder<'tree, 'ir> { ); self.ir.push(Inst::FunctionStart, { - variant!(Tag::Ident { name } = self.tree.nodes.get_node(*name)); + variant!( + Tag::Ident { name } = self.tree.nodes.get_node(*name) + ); Some((*name).into()) }); if let Some(parameters) = parameters { variant!( - Tag::ParameterList { parameters } = self.tree.nodes.get_node(*parameters) + Tag::ParameterList { parameters } = + self.tree.nodes.get_node(*parameters) ); for param in parameters { - variant!(Tag::Parameter { ty, .. } = self.tree.nodes.get_node(*param)); + variant!( + Tag::Parameter { ty, .. } = + self.tree.nodes.get_node(*param) + ); let ty = self.tree.type_of_node(*ty); let size = ty.size_of(); let align = ty.align_of(); - let ir = self - .ir - .push(Inst::Parameter(ty.into()), Some(Data::new(size, align))); + let ir = self.ir.push( + Inst::Parameter(ty.into()), + Some(Data::new(size, align)), + ); self.lookup.insert(*param, NodeOrList::Node(ir)); } @@ -384,39 +399,44 @@ impl<'tree, 'ir> IRBuilder<'tree, 'ir> { self.tree.st.into_parent(); if value != !0 { let ty = self.tree.type_of_node(*body); - self.ir - .push(Inst::ReturnValue(ty.into()), Some(Data::lhs(value))); + self.ir.push( + Inst::ReturnValue(ty.into()), + Some(Data::lhs(value)), + ); } self.ir.push(Inst::FunctionEnd, None) } Tag::CallExpr { lhs, rhs } => { - let ty = self.tree.type_of_node(*lhs).return_type().unwrap().clone(); - let args = - if let Some(args) = *rhs { - variant!( - self.tree.nodes.get_node(args) => Tag::ArgumentList { arguments } - ); + let ty = + self.tree.type_of_node(*lhs).return_type().unwrap().clone(); + let args = if let Some(args) = *rhs { + variant!( + self.tree.nodes.get_node(args) => Tag::ArgumentList { arguments } + ); - let args = arguments.clone().iter().map(|arg| { + let args = arguments.clone().iter().map(|arg| { variant!(*self.tree.nodes.get_node(*arg) => Tag::Argument { expr ,..}); (self.visit(expr), self.tree.type_of_node(expr)) }).collect::>(); - let start = self.ir.nodes.len(); - for (arg, ty) in args { - _ = self - .ir - .push(Inst::Argument(ty.into()), Some(Data::lhs(arg))); - } - let end = self.ir.nodes.len(); + let start = self.ir.nodes.len(); + for (arg, ty) in args { + _ = self.ir.push( + Inst::Argument(ty.into()), + Some(Data::lhs(arg)), + ); + } + let end = self.ir.nodes.len(); - Some((start as u32, end as u32)) - } else { - None - }; - let (start, end) = - args.unwrap_or((self.ir.nodes.len() as u32, self.ir.nodes.len() as u32)); + Some((start as u32, end as u32)) + } else { + None + }; + let (start, end) = args.unwrap_or(( + self.ir.nodes.len() as u32, + self.ir.nodes.len() as u32, + )); self.ir.push(Inst::InlineType(ty.into()), None); let func = self.visit(*lhs); @@ -440,16 +460,18 @@ impl<'tree, 'ir> IRBuilder<'tree, 'ir> { } Tag::VarDecl { assignment, .. } => { let ty = self.tree.type_of_node(node); - let alloca = self - .ir - .push(Inst::Alloca, Some(Data::new(ty.size_of(), ty.align_of()))); + let alloca = self.ir.push( + Inst::Alloca, + Some(Data::new(ty.size_of(), ty.align_of())), + ); if let Some(assignment) = assignment { let value = self.visit(*assignment); // discard store - let _ = self - .ir - .push(Inst::Store(ty.into()), Some(Data::new(value, alloca))); + let _ = self.ir.push( + Inst::Store(ty.into()), + Some(Data::new(value, alloca)), + ); } self.lookup.insert(node, NodeOrList::Node(alloca)); alloca @@ -474,9 +496,10 @@ impl<'tree, 'ir> IRBuilder<'tree, 'ir> { } Tag::GlobalRef(decl) => { let ty = self.tree.type_of_node(*decl); - let node = self - .ir - .push(Inst::ExternRef(ty.into()), Some(Data::lhs(decl.get()))); + let node = self.ir.push( + Inst::ExternRef(ty.into()), + Some(Data::lhs(decl.get())), + ); self.fixup.push(node); node } @@ -500,15 +523,18 @@ impl<'tree, 'ir> IRBuilder<'tree, 'ir> { if let Some(expr) = expr { let ty = self.tree.type_of_node(*expr); let expr = self.visit(*expr); - self.ir - .push(Inst::ReturnValue(ty.into()), Some(Data::lhs(expr))) + self.ir.push( + Inst::ReturnValue(ty.into()), + Some(Data::lhs(expr)), + ) } else { self.ir.push(Inst::Return, None) } } Tag::ExprStmt { expr } => self.visit(*expr), Tag::Deref { lhs } => { - let ty = self.tree.type_of_node(*lhs).pointee().unwrap().clone(); + let ty = + self.tree.type_of_node(*lhs).pointee().unwrap().clone(); let lhs = self.visit(*lhs); self.ir.push(Inst::Load(ty.into()), Some(Data::lhs(lhs))) } @@ -605,20 +631,28 @@ impl<'tree, 'ir> IRBuilder<'tree, 'ir> { let ty = self.tree.type_of_node(node); let lhs = self.visit(*lhs); let rhs = self.visit(*rhs); - self.ir - .push(Inst::ShiftRight(ty.into()), Some(Data::new(lhs, rhs))) + self.ir.push( + Inst::ShiftRight(ty.into()), + Some(Data::new(lhs, rhs)), + ) } Tag::Ref { lhs } => { let ty = self.tree.type_of_node(*lhs); let lhs = self.visit(*lhs); // self.ir.push(Inst::Load(ty.into()), Some(Data::lhs(lhs))) // nothing happens here because lhs is of type pointer - self.ir - .push(Inst::GetElementPtr(ty.into()), Some(Data::new(lhs, 0))) + self.ir.push( + Inst::GetElementPtr(ty.into()), + Some(Data::new(lhs, 0)), + ) } Tag::Constant { bytes, .. } => match bytes { - ImmOrIndex::U64(v) => self.ir.push(Inst::ConstantU64, Some((*v).into())), - ImmOrIndex::U32(v) => self.ir.push(Inst::ConstantU32, Some((*v).into())), + ImmOrIndex::U64(v) => { + self.ir.push(Inst::ConstantU64, Some((*v).into())) + } + ImmOrIndex::U32(v) => { + self.ir.push(Inst::ConstantU32, Some((*v).into())) + } ImmOrIndex::Index(idx) => { self.ir.push(Inst::ConstantMultiByte, Some((*idx).into())) } @@ -645,10 +679,14 @@ impl<'tree, 'ir> IRBuilder<'tree, 'ir> { let condition = self.visit(*condition); let br = self.ir.push(Inst::Branch(condition), None); - let label_lhs = self.ir.push(Inst::Label, Some(StringsIndex::none().into())); + let label_lhs = self + .ir + .push(Inst::Label, Some(StringsIndex::none().into())); let _ = self.visit(*body); let jmp = self.ir.push(Inst::Jump, None); - let nojump = self.ir.push(Inst::Label, Some(StringsIndex::none().into())); + let nojump = self + .ir + .push(Inst::Label, Some(StringsIndex::none().into())); self.ir.data[br as usize] = Some(Data::new(label_lhs, nojump)); self.ir.data[jmp as usize] = Some(Data::lhs(nojump)); @@ -665,21 +703,28 @@ impl<'tree, 'ir> IRBuilder<'tree, 'ir> { let condition = self.visit(*condition); let br = self.ir.push(Inst::Branch(condition), None); - let label_lhs = self.ir.push(Inst::Label, Some(StringsIndex::none().into())); + let label_lhs = self + .ir + .push(Inst::Label, Some(StringsIndex::none().into())); let lhs = self.visit(*body); let ljmp = self.ir.push(Inst::Jump, None); - let label_rhs = self.ir.push(Inst::Label, Some(StringsIndex::none().into())); + let label_rhs = self + .ir + .push(Inst::Label, Some(StringsIndex::none().into())); let rhs = self.visit(*else_expr); let rjmp = self.ir.push(Inst::Jump, None); - let nojump = self.ir.push(Inst::Label, Some(StringsIndex::none().into())); + let nojump = self + .ir + .push(Inst::Label, Some(StringsIndex::none().into())); let phi = if let Some(ty) = Type2::try_from_ast_type(&ty) { self.ir.push(Inst::Phi2(ty), Some(Data::new(lhs, rhs))) } else { br }; - self.ir.data[br as usize] = Some(Data::new(label_lhs, label_rhs)); + self.ir.data[br as usize] = + Some(Data::new(label_lhs, label_rhs)); self.ir.data[ljmp as usize] = Some(Data::lhs(nojump)); self.ir.data[rjmp as usize] = Some(Data::lhs(nojump)); phi @@ -712,7 +757,10 @@ impl IR { node } - pub fn build<'a, 'tree>(&'a mut self, tree: &'tree mut Tree) -> IRBuilder<'tree, 'a> { + pub fn build<'a, 'tree>( + &'a mut self, + tree: &'tree mut Tree, + ) -> IRBuilder<'tree, 'a> { let global_decls = tree.global_decls.clone(); let mut builder = IRBuilder::new(self, tree); @@ -723,7 +771,11 @@ impl IR { for &fix in builder.fixup.iter() { let ast_node = builder.ir.data[fix as usize].unwrap().lhs; - let idx = match builder.tree.nodes.get_node(AstNode::new(ast_node).unwrap()) { + let idx = match builder + .tree + .nodes + .get_node(AstNode::new(ast_node).unwrap()) + { Tag::FunctionDecl { proto, .. } => { variant!(builder.tree.nodes.get_node(*proto) => Tag::FunctionProto { name,..}); variant!(builder.tree.nodes.get_node(*name) => Tag::Ident { name }); @@ -758,7 +810,12 @@ impl<'tree, 'ir> IRBuilder<'tree, 'ir> { match inst { Inst::Label => { let label = self.tree.strings.get_str(data.as_index()); - writeln_indented!(indent - 1, w, "%{} = label \"{label}\":", node)?; + writeln_indented!( + indent - 1, + w, + "%{} = label \"{label}\":", + node + )?; } Inst::FunctionStart => { let label = self.tree.strings.get_str(data.as_index()); @@ -798,59 +855,158 @@ impl<'tree, 'ir> IRBuilder<'tree, 'ir> { writeln_indented!(indent, w, ")")?; } Inst::ConstantU32 => { - writeln_indented!(indent, w, "%{} = const i32 {}", node, data.as_u32())?; + writeln_indented!( + indent, + w, + "%{} = const i32 {}", + node, + data.as_u32() + )?; } Inst::ConstantU64 => { - writeln_indented!(indent, w, "%{} = const i64 {}", node, data.as_u64())?; + writeln_indented!( + indent, + w, + "%{} = const i64 {}", + node, + data.as_u64() + )?; } Inst::ConstantMultiByte => { let value = self.tree.strings.get_bytes(data.as_index()); - writeln_indented!(indent, w, "%{} = const bytes {:x?}", node, value)?; + writeln_indented!( + indent, + w, + "%{} = const bytes {:x?}", + node, + value + )?; } Inst::Add(ty) => { let (lhs, rhs) = data.as_lhs_rhs(); - writeln_indented!(indent, w, "%{} = add_{ty}(%{} + %{})", node, lhs, rhs)?; + writeln_indented!( + indent, + w, + "%{} = add_{ty}(%{} + %{})", + node, + lhs, + rhs + )?; } Inst::Sub(ty) => { let (lhs, rhs) = data.as_lhs_rhs(); - writeln_indented!(indent, w, "%{} = sub_{ty}(%{} - %{})", node, lhs, rhs)?; + writeln_indented!( + indent, + w, + "%{} = sub_{ty}(%{} - %{})", + node, + lhs, + rhs + )?; } Inst::Eq(ty) => { let (lhs, rhs) = data.as_lhs_rhs(); - writeln_indented!(indent, w, "%{} = eq_{ty}(%{} == %{})", node, lhs, rhs)?; + writeln_indented!( + indent, + w, + "%{} = eq_{ty}(%{} == %{})", + node, + lhs, + rhs + )?; } Inst::Neq(ty) => { let (lhs, rhs) = data.as_lhs_rhs(); - writeln_indented!(indent, w, "%{} = neq_{ty}(%{} != %{})", node, lhs, rhs)?; + writeln_indented!( + indent, + w, + "%{} = neq_{ty}(%{} != %{})", + node, + lhs, + rhs + )?; } Inst::Gt(ty) => { let (lhs, rhs) = data.as_lhs_rhs(); - writeln_indented!(indent, w, "%{} = gt_{ty}(%{} > %{})", node, lhs, rhs)?; + writeln_indented!( + indent, + w, + "%{} = gt_{ty}(%{} > %{})", + node, + lhs, + rhs + )?; } Inst::Lt(ty) => { let (lhs, rhs) = data.as_lhs_rhs(); - writeln_indented!(indent, w, "%{} = lt_{ty}(%{} < %{})", node, lhs, rhs)?; + writeln_indented!( + indent, + w, + "%{} = lt_{ty}(%{} < %{})", + node, + lhs, + rhs + )?; } Inst::Ge(ty) => { let (lhs, rhs) = data.as_lhs_rhs(); - writeln_indented!(indent, w, "%{} = ge_{ty}(%{} >= %{})", node, lhs, rhs)?; + writeln_indented!( + indent, + w, + "%{} = ge_{ty}(%{} >= %{})", + node, + lhs, + rhs + )?; } Inst::Le(ty) => { let (lhs, rhs) = data.as_lhs_rhs(); - writeln_indented!(indent, w, "%{} = le_{ty}(%{} <= %{})", node, lhs, rhs)?; + writeln_indented!( + indent, + w, + "%{} = le_{ty}(%{} <= %{})", + node, + lhs, + rhs + )?; } Inst::Mul(ty) => { let (lhs, rhs) = data.as_lhs_rhs(); - writeln_indented!(indent, w, "%{} = mul_{ty}(%{} * %{})", node, lhs, rhs)?; + writeln_indented!( + indent, + w, + "%{} = mul_{ty}(%{} * %{})", + node, + lhs, + rhs + )?; } Inst::Negate(ty) => { - writeln_indented!(indent, w, "%{} = negate_{ty}(%{})", node, data.lhs)?; + writeln_indented!( + indent, + w, + "%{} = negate_{ty}(%{})", + node, + data.lhs + )?; } Inst::Not(ty) => { - writeln_indented!(indent, w, "%{} = bitwise_not_{ty}(%{})", node, data.lhs)?; + writeln_indented!( + indent, + w, + "%{} = bitwise_not_{ty}(%{})", + node, + data.lhs + )?; } Inst::ExplicitCast(from, to) => { - writeln_indented!(indent, w, "%{} = cast_{from}_to_{to}(%{})", node, data.lhs)?; + writeln_indented!( + indent, + w, + "%{} = cast_{from}_to_{to}(%{})", + node, + data.lhs + )?; } Inst::ShiftLeft(ty) => { writeln_indented!( @@ -873,14 +1029,25 @@ impl<'tree, 'ir> IRBuilder<'tree, 'ir> { )?; } Inst::ReturnValue(ty) => { - writeln_indented!(indent, w, "%{} = return {ty} %{}", node, data.lhs)?; + writeln_indented!( + indent, + w, + "%{} = return {ty} %{}", + node, + data.lhs + )?; } Inst::Return => { writeln_indented!(indent, w, "%{} = return", node)?; } Inst::Alloca => { let (size, align) = data.as_lhs_rhs(); - writeln_indented!(indent, w, "%{} = alloca {size} (align: {align})", node)?; + writeln_indented!( + indent, + w, + "%{} = alloca {size} (align: {align})", + node + )?; } Inst::GetElementPtr(ty) => { let (ptr, idx) = data.as_lhs_rhs(); @@ -894,11 +1061,21 @@ impl<'tree, 'ir> IRBuilder<'tree, 'ir> { } Inst::Load(ty) => { let source = data.lhs; - writeln_indented!(indent, w, "%{} = load {ty}, %{source}", node)?; + writeln_indented!( + indent, + w, + "%{} = load {ty}, %{source}", + node + )?; } Inst::Store(ty) => { let (src, dst) = data.as_lhs_rhs(); - writeln_indented!(indent, w, "%{} = store {ty}, ptr %{dst}, %{src}", node)?; + writeln_indented!( + indent, + w, + "%{} = store {ty}, ptr %{dst}, %{src}", + node + )?; } Inst::ExternRef(ty) => { let idx = data.as_index(); @@ -923,12 +1100,20 @@ impl<'tree, 'ir> IRBuilder<'tree, 'ir> { } Inst::Phi2(ty) => { let (lhs, rhs) = data.as_lhs_rhs(); - writeln_indented!(indent, w, "%{node} = phi [{ty} %{lhs}, {ty} %{rhs}]")?; + writeln_indented!( + indent, + w, + "%{node} = phi [{ty} %{lhs}, {ty} %{rhs}]" + )?; } Inst::GlobalConstant(name, ty) => { let label = self.tree.strings.get_str(name); let value = data.lhs; - writeln_indented!(indent, w, "%{node} = global const '{label}' {ty} %{value}")?; + writeln_indented!( + indent, + w, + "%{node} = global const '{label}' {ty} %{value}" + )?; } _ => { unimplemented!("{inst:?} rendering unimplemented") @@ -1000,8 +1185,11 @@ impl<'a> IrToMirMapping<'a> { match self.ir.nodes[ir as usize] { Inst::GlobalConstant(name, ty) => { - eprintln!("does this even get hit anymore???????????????????//"); - let ext = mir::NodeRef(mir.gen_extern(Some(ty.mir_type()), name)); + eprintln!( + "does this even get hit anymore???????????????????//" + ); + let ext = + mir::NodeRef(mir.gen_extern(Some(ty.mir_type()), name)); self.insert(ir, ext); Some(ext) } @@ -1042,7 +1230,8 @@ impl<'a> MirBuilder<'a> { } } } - let mut unresolved_jumps_branches = BTreeSet::<(Node, LeftRight)>::new(); + let mut unresolved_jumps_branches = + BTreeSet::<(Node, LeftRight)>::new(); loop { let ir_node = self.ir.node(); @@ -1062,14 +1251,18 @@ impl<'a> MirBuilder<'a> { let range = unresolved_jumps_branches .range( (ir_node, LeftRight::Left(mir::NodeRef::MIN)) - ..=(ir_node, LeftRight::Right(mir::NodeRef::MAX)), + ..=( + ir_node, + LeftRight::Right(mir::NodeRef::MAX), + ), ) .map(|(_, n)| n) .cloned() .collect::>(); for unresolved in range { - unresolved_jumps_branches.remove(&(ir_node, unresolved)); + unresolved_jumps_branches + .remove(&(ir_node, unresolved)); let mir_node = unresolved.noderef(); let (inst, data) = mir.get_node_mut(mir_node); @@ -1082,8 +1275,12 @@ impl<'a> MirBuilder<'a> { let (lhs, rhs) = data.as_binary_noderefs(); *data = match unresolved { - LeftRight::Left(_) => mir::Data::binary(label, rhs.0), - LeftRight::Right(_) => mir::Data::binary(lhs.0, label), + LeftRight::Left(_) => { + mir::Data::binary(label, rhs.0) + } + LeftRight::Right(_) => { + mir::Data::binary(lhs.0, label) + } }; } _ => { @@ -1103,18 +1300,25 @@ impl<'a> MirBuilder<'a> { mir::Data::imm64(data.unwrap().as_u64()), ), Inst::ConstantMultiByte => { - let bytes = self.strings.get_bytes(data.unwrap().as_index()); + let bytes = + self.strings.get_bytes(data.unwrap().as_index()); let mut buf = [0u8; 8]; match bytes.len() { 1 => mir.gen_u8(bytes[0]), - 2 => mir.gen_u16(u16::from_le_bytes(bytes[..2].try_into().unwrap())), + 2 => mir.gen_u16(u16::from_le_bytes( + bytes[..2].try_into().unwrap(), + )), 3..=4 => { buf[..bytes.len()].copy_from_slice(bytes); - mir.gen_u32(u32::from_le_bytes(buf[..4].try_into().unwrap())) + mir.gen_u32(u32::from_le_bytes( + buf[..4].try_into().unwrap(), + )) } 5..=8 => { buf[..bytes.len()].copy_from_slice(bytes); - mir.gen_u64(u64::from_le_bytes(buf[..8].try_into().unwrap())) + mir.gen_u64(u64::from_le_bytes( + buf[..8].try_into().unwrap(), + )) } _ => { unimplemented!( @@ -1129,7 +1333,10 @@ impl<'a> MirBuilder<'a> { } Inst::Load(ty) => { let ty = mir::Type::from_bytesize_int(ty.size()); - let src = mapping.get(&mut mir, data.unwrap().as_u32()).unwrap().0; + let src = mapping + .get(&mut mir, data.unwrap().as_u32()) + .unwrap() + .0; mir.gen_load(ty, src) } Inst::Store(ty) => { @@ -1170,7 +1377,14 @@ impl<'a> MirBuilder<'a> { _ => unreachable!(), }; - mir.gen_cmp_byte(ty.mir_type(), ty.is_signed(), ord, invert, lhs, rhs) + mir.gen_cmp_byte( + ty.mir_type(), + ty.is_signed(), + ord, + invert, + lhs, + rhs, + ) } Inst::Add(ty) => { let (src, dst) = data.unwrap().as_lhs_rhs(); @@ -1187,15 +1401,22 @@ impl<'a> MirBuilder<'a> { unimplemented!() } bits => { - let ty = mir::Type::from_bitsize_int(bits as u32); + let ty = + mir::Type::from_bitsize_int(bits as u32); let sum = mir.gen_add(ty, lhs, rhs); mir.gen_truncate_integer(sum, ty, signed, bits) } }, - Type2::Binary32 => mir.gen_add(mir::Type::SinglePrecision, lhs, rhs), - Type2::Binary64 => mir.gen_add(mir::Type::DoublePrecision, lhs, rhs), - Type2::Pointer => mir.gen_add(mir::Type::QWord, lhs, rhs), + Type2::Binary32 => { + mir.gen_add(mir::Type::SinglePrecision, lhs, rhs) + } + Type2::Binary64 => { + mir.gen_add(mir::Type::DoublePrecision, lhs, rhs) + } + Type2::Pointer => { + mir.gen_add(mir::Type::QWord, lhs, rhs) + } _ => unreachable!(), } } @@ -1271,11 +1492,12 @@ impl<'a> MirBuilder<'a> { let unalignment = ty.mir_unalignment(); let ty = ty.mir_type(); - let (lhs, rhs) = if self.ir.ir.nodes[lhs as usize].is_constant() { - (rhs, lhs) - } else { - (lhs, rhs) - }; + let (lhs, rhs) = + if self.ir.ir.nodes[lhs as usize].is_constant() { + (rhs, lhs) + } else { + (lhs, rhs) + }; let lhs = mapping.get(&mut mir, lhs).unwrap().0; let rhs = mapping.get(&mut mir, rhs).unwrap().0; @@ -1293,11 +1515,12 @@ impl<'a> MirBuilder<'a> { let unalignment = ty.mir_unalignment(); let ty = ty.mir_type(); - let (lhs, rhs) = if self.ir.ir.nodes[lhs as usize].is_constant() { - (rhs, lhs) - } else { - (lhs, rhs) - }; + let (lhs, rhs) = + if self.ir.ir.nodes[lhs as usize].is_constant() { + (rhs, lhs) + } else { + (lhs, rhs) + }; let lhs = mapping.get(&mut mir, lhs).unwrap().0; let rhs = mapping.get(&mut mir, rhs).unwrap().0; @@ -1315,11 +1538,12 @@ impl<'a> MirBuilder<'a> { let unalignment = ty.mir_unalignment(); let ty = ty.mir_type(); - let (lhs, rhs) = if self.ir.ir.nodes[lhs as usize].is_constant() { - (rhs, lhs) - } else { - (lhs, rhs) - }; + let (lhs, rhs) = + if self.ir.ir.nodes[lhs as usize].is_constant() { + (rhs, lhs) + } else { + (lhs, rhs) + }; let lhs = mapping.get(&mut mir, lhs).unwrap().0; let rhs = mapping.get(&mut mir, rhs).unwrap().0; @@ -1337,7 +1561,8 @@ impl<'a> MirBuilder<'a> { let rhs = mapping.get(&mut mir, dst).unwrap().0; // TODO: check rhs type and pass it to gen_sh{l,r}? - let rhs = mir.gen_truncate_integer(rhs, ty.into(), false, 8); + let rhs = + mir.gen_truncate_integer(rhs, ty.into(), false, 8); match ty { Type2::Integral(signed, bits) => match bits { 8 => mir.gen_shl(mir::Type::Byte, lhs, rhs), @@ -1348,7 +1573,8 @@ impl<'a> MirBuilder<'a> { unimplemented!() } bits => { - let ty = mir::Type::from_bitsize_int(bits as u32); + let ty = + mir::Type::from_bitsize_int(bits as u32); let sum = mir.gen_shl(ty, lhs, rhs); mir.gen_truncate_integer(sum, ty, signed, bits) @@ -1365,7 +1591,8 @@ impl<'a> MirBuilder<'a> { match ty { Type2::Integral(signed, bits) => match bits { 8 | 16 | 32 | 64 => { - let ty = mir::Type::from_bitsize_int(bits as u32); + let ty = + mir::Type::from_bitsize_int(bits as u32); if signed { mir.gen_sar(ty, lhs, rhs) } else { @@ -1376,7 +1603,8 @@ impl<'a> MirBuilder<'a> { unimplemented!() } bits => { - let ty = mir::Type::from_bitsize_int(bits as u32); + let ty = + mir::Type::from_bitsize_int(bits as u32); let sum = if signed { mir.gen_sar(ty, lhs, rhs) @@ -1428,9 +1656,14 @@ impl<'a> MirBuilder<'a> { let lhs = mapping.get(&mut mir, lhs).unwrap().0; match (from, to) { - (Type2::Integral(a_signed, a), Type2::Integral(b_signed, b)) => { + ( + Type2::Integral(a_signed, a), + Type2::Integral(b_signed, b), + ) => { if a > b { - mir.gen_truncate_integer(lhs, to_mir, b_signed, b) + mir.gen_truncate_integer( + lhs, to_mir, b_signed, b, + ) } else if a < b { mir.gen_extend_integer( lhs, @@ -1445,11 +1678,12 @@ impl<'a> MirBuilder<'a> { let is_zero = mir.gen_is_zero(from_mir, lhs); mir.gen_negate(mir::Type::Byte, is_zero) } - (Type2::Bool, Type2::Integral(b_signed, b)) => mir.gen_extend_integer( - lhs, - IntegralType::u1(), - IntegralType::new(b_signed, b), - ), + (Type2::Bool, Type2::Integral(b_signed, b)) => mir + .gen_extend_integer( + lhs, + IntegralType::u1(), + IntegralType::new(b_signed, b), + ), _ => unimplemented!(), } } @@ -1468,13 +1702,18 @@ impl<'a> MirBuilder<'a> { let label = match mapping.get(&mut mir, label) { Some(label) => label.0, None => { - unresolved_jumps_branches - .insert((label, LeftRight::Left(mir::NodeRef(jmp)))); + unresolved_jumps_branches.insert(( + label, + LeftRight::Left(mir::NodeRef(jmp)), + )); 0 } }; - mir.set_node_data(mir::NodeRef(jmp), mir::Data::node(label)); + mir.set_node_data( + mir::NodeRef(jmp), + mir::Data::node(label), + ); jmp } @@ -1487,21 +1726,28 @@ impl<'a> MirBuilder<'a> { let lhs = match mapping.get(&mut mir, lhs) { Some(n) => n.0, None => { - unresolved_jumps_branches - .insert((lhs, LeftRight::Left(mir::NodeRef(br)))); + unresolved_jumps_branches.insert(( + lhs, + LeftRight::Left(mir::NodeRef(br)), + )); 0 } }; let rhs = match mapping.get(&mut mir, rhs) { Some(n) => n.0, None => { - unresolved_jumps_branches - .insert((rhs, LeftRight::Right(mir::NodeRef(br)))); + unresolved_jumps_branches.insert(( + rhs, + LeftRight::Right(mir::NodeRef(br)), + )); 0 } }; - mir.set_node_data(mir::NodeRef(br), mir::Data::binary(lhs, rhs)); + mir.set_node_data( + mir::NodeRef(br), + mir::Data::binary(lhs, rhs), + ); br } @@ -1539,12 +1785,13 @@ impl<'a> MirBuilder<'a> { Inst::Argument(_) | Inst::InlineType(_) => { continue; } - Inst::ExternRef(ty) => { - mir.gen_extern(Some(ty.mir_type()), data.unwrap().as_index()) - } + Inst::ExternRef(ty) => mir + .gen_extern(Some(ty.mir_type()), data.unwrap().as_index()), #[allow(unreachable_patterns)] _ => { - eprintln!("ir inst {inst:?} not supported in mir translation"); + eprintln!( + "ir inst {inst:?} not supported in mir translation" + ); unimplemented!() } }; @@ -1561,7 +1808,9 @@ impl<'a> MirBuilder<'a> { break; }; match inst { - Inst::FunctionStart => self.build_function(data.unwrap().as_index()), + Inst::FunctionStart => { + self.build_function(data.unwrap().as_index()) + } Inst::GlobalConstant(name, ..) => { let mut mir = mir::Mir::new(name); let value = data.unwrap().lhs; @@ -1577,20 +1826,26 @@ impl<'a> MirBuilder<'a> { mir::Data::imm64(data.unwrap().as_u64()), ), Inst::ConstantMultiByte => { - let bytes = self.strings.get_bytes(data.unwrap().as_index()); + let bytes = self + .strings + .get_bytes(data.unwrap().as_index()); let mut buf = [0u8; 8]; match bytes.len() { 1 => mir.gen_u8(bytes[0]), - 2 => { - mir.gen_u16(u16::from_le_bytes(bytes[..2].try_into().unwrap())) - } + 2 => mir.gen_u16(u16::from_le_bytes( + bytes[..2].try_into().unwrap(), + )), 3..=4 => { buf[..bytes.len()].copy_from_slice(bytes); - mir.gen_u32(u32::from_le_bytes(buf[..4].try_into().unwrap())) + mir.gen_u32(u32::from_le_bytes( + buf[..4].try_into().unwrap(), + )) } 5..=8 => { buf[..bytes.len()].copy_from_slice(bytes); - mir.gen_u64(u64::from_le_bytes(buf[..8].try_into().unwrap())) + mir.gen_u64(u64::from_le_bytes( + buf[..8].try_into().unwrap(), + )) } _ => { unimplemented!(