cargo fmt
This commit is contained in:
parent
30ce12988d
commit
96863e0397
|
@ -220,27 +220,27 @@ impl Register {
|
||||||
const fn bit_size(self) -> u32 {
|
const fn bit_size(self) -> u32 {
|
||||||
use Register::*;
|
use Register::*;
|
||||||
match self {
|
match self {
|
||||||
ah | bh | ch | dh | al | bl | cl | dl | sil | dil | spl | bpl | r8b | r9b | r10b
|
ah | bh | ch | dh | al | bl | cl | dl | sil | dil | spl | bpl
|
||||||
| r11b | r12b | r13b | r14b | r15b => 8,
|
| r8b | r9b | r10b | r11b | r12b | r13b | r14b | r15b => 8,
|
||||||
|
|
||||||
ax | bx | cx | dx | si | di | sp | bp | ip | r8w | r9w | r10w | r11w | r12w | r13w
|
ax | bx | cx | dx | si | di | sp | bp | ip | r8w | r9w | r10w
|
||||||
| r14w | r15w => 16,
|
| r11w | r12w | r13w | r14w | r15w => 16,
|
||||||
|
|
||||||
eax | ebx | ecx | edx | esi | edi | esp | ebp | eip | r8d | r9d | r10d | r11d
|
eax | ebx | ecx | edx | esi | edi | esp | ebp | eip | r8d | r9d
|
||||||
| r12d | r13d | r14d | r15d => 32,
|
| r10d | r11d | r12d | r13d | r14d | r15d => 32,
|
||||||
|
|
||||||
rax | rbx | rcx | rdx | rsi | rdi | rsp | rbp | rip | r8 | r9 | r10 | r11 | r12
|
rax | rbx | rcx | rdx | rsi | rdi | rsp | rbp | rip | r8 | r9
|
||||||
| r13 | r14 | r15 => 64,
|
| r10 | r11 | r12 | r13 | r14 | r15 => 64,
|
||||||
|
|
||||||
mm0 | mm1 | mm2 | mm3 | mm4 | mm5 | mm6 | mm7 => 64,
|
mm0 | mm1 | mm2 | mm3 | mm4 | mm5 | mm6 | mm7 => 64,
|
||||||
|
|
||||||
st0 | st1 | st2 | st3 | st4 | st5 | st6 | st7 => 80,
|
st0 | st1 | st2 | st3 | st4 | st5 | st6 | st7 => 80,
|
||||||
|
|
||||||
xmm0 | xmm1 | xmm2 | xmm3 | xmm4 | xmm5 | xmm6 | xmm7 | xmm8 | xmm9 | xmm10 | xmm11
|
xmm0 | xmm1 | xmm2 | xmm3 | xmm4 | xmm5 | xmm6 | xmm7 | xmm8
|
||||||
| xmm12 | xmm13 | xmm14 | xmm15 => 128,
|
| xmm9 | xmm10 | xmm11 | xmm12 | xmm13 | xmm14 | xmm15 => 128,
|
||||||
|
|
||||||
ymm0 | ymm1 | ymm2 | ymm3 | ymm4 | ymm5 | ymm6 | ymm7 | ymm8 | ymm9 | ymm10 | ymm11
|
ymm0 | ymm1 | ymm2 | ymm3 | ymm4 | ymm5 | ymm6 | ymm7 | ymm8
|
||||||
| ymm12 | ymm13 | ymm14 | ymm15 => 256,
|
| ymm9 | ymm10 | ymm11 | ymm12 | ymm13 | ymm14 | ymm15 => 256,
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -338,28 +338,30 @@ impl Register {
|
||||||
pub const SSE: [Register; 16] = {
|
pub const SSE: [Register; 16] = {
|
||||||
use Register::*;
|
use Register::*;
|
||||||
[
|
[
|
||||||
xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8, xmm9, xmm10, xmm11, xmm12, xmm13,
|
xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8, xmm9, xmm10,
|
||||||
xmm14, xmm15,
|
xmm11, xmm12, xmm13, xmm14, xmm15,
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const fn is_gp(self) -> bool {
|
pub const fn is_gp(self) -> bool {
|
||||||
use Register::*;
|
use Register::*;
|
||||||
match self {
|
match self {
|
||||||
rax | eax | ax | ah | al | rbx | ebx | bx | bh | bl | rcx | ecx | cx | ch | cl
|
rax | eax | ax | ah | al | rbx | ebx | bx | bh | bl | rcx | ecx
|
||||||
| rdx | edx | dx | dh | dl | rsi | esi | si | sil | rdi | edi | di | dil | r8 | r8d
|
| cx | ch | cl | rdx | edx | dx | dh | dl | rsi | esi | si
|
||||||
| r8w | r8b | r9 | r9d | r9w | r9b | r10 | r10d | r10w | r10b | r11 | r11d | r11w
|
| sil | rdi | edi | di | dil | r8 | r8d | r8w | r8b | r9 | r9d
|
||||||
| r11b | r12 | r12d | r12w | r12b | r13 | r13d | r13w | r13b | r14 | r14d | r14w
|
| r9w | r9b | r10 | r10d | r10w | r10b | r11 | r11d | r11w
|
||||||
| r14b | r15 | r15d | r15w | r15b => true,
|
| r11b | r12 | r12d | r12w | r12b | r13 | r13d | r13w | r13b
|
||||||
|
| r14 | r14d | r14w | r14b | r15 | r15d | r15w | r15b => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub const fn is_sse(self) -> bool {
|
pub const fn is_sse(self) -> bool {
|
||||||
use Register::*;
|
use Register::*;
|
||||||
match self {
|
match self {
|
||||||
xmm0 | xmm1 | xmm2 | xmm3 | xmm4 | xmm5 | xmm6 | xmm7 | xmm8 | xmm9 | xmm10 | xmm11
|
xmm0 | xmm1 | xmm2 | xmm3 | xmm4 | xmm5 | xmm6 | xmm7 | xmm8
|
||||||
| xmm12 | xmm13 | xmm14 | xmm15 | ymm0 | ymm1 | ymm2 | ymm3 | ymm4 | ymm5 | ymm6
|
| xmm9 | xmm10 | xmm11 | xmm12 | xmm13 | xmm14 | xmm15 | ymm0
|
||||||
| ymm7 | ymm8 | ymm9 | ymm10 | ymm11 | ymm12 | ymm13 | ymm14 | ymm15 => true,
|
| ymm1 | ymm2 | ymm3 | ymm4 | ymm5 | ymm6 | ymm7 | ymm8 | ymm9
|
||||||
|
| ymm10 | ymm11 | ymm12 | ymm13 | ymm14 | ymm15 => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
46
src/ast.rs
46
src/ast.rs
|
@ -294,14 +294,21 @@ impl core::fmt::Display for Type {
|
||||||
Type::Integer(t) => t.fmt(f),
|
Type::Integer(t) => t.fmt(f),
|
||||||
Type::Floating(t) => t.fmt(f),
|
Type::Floating(t) => t.fmt(f),
|
||||||
Type::Pointer { constness, pointee } => {
|
Type::Pointer { constness, pointee } => {
|
||||||
write!(f, "*{}{}", if *constness { "const " } else { "" }, pointee)
|
write!(
|
||||||
|
f,
|
||||||
|
"*{}{}",
|
||||||
|
if *constness { "const " } else { "" },
|
||||||
|
pointee
|
||||||
|
)
|
||||||
}
|
}
|
||||||
Type::Fn {
|
Type::Fn {
|
||||||
parameter_types,
|
parameter_types,
|
||||||
return_type,
|
return_type,
|
||||||
} => {
|
} => {
|
||||||
write!(f, "fn (")?;
|
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 {
|
match param {
|
||||||
Some(param) => param.fmt(f)?,
|
Some(param) => param.fmt(f)?,
|
||||||
None => write!(f, ", ")?,
|
None => write!(f, ", ")?,
|
||||||
|
@ -340,8 +347,13 @@ impl Type {
|
||||||
parameter_types: r_parameter_types,
|
parameter_types: r_parameter_types,
|
||||||
return_type: r_return_type,
|
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<PrimitiveType> {
|
pub fn as_primitive_type(&self) -> Option<PrimitiveType> {
|
||||||
|
@ -460,9 +472,10 @@ impl Type {
|
||||||
|
|
||||||
pub fn can_add_sub(&self) -> bool {
|
pub fn can_add_sub(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
Type::ComptimeNumber | Type::Pointer { .. } | Type::Floating(_) | Type::Integer(_) => {
|
Type::ComptimeNumber
|
||||||
true
|
| Type::Pointer { .. }
|
||||||
}
|
| Type::Floating(_)
|
||||||
|
| Type::Integer(_) => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -484,9 +497,10 @@ impl Type {
|
||||||
}
|
}
|
||||||
pub fn can_cmp(&self) -> bool {
|
pub fn can_cmp(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
Type::ComptimeNumber | Type::Pointer { .. } | Type::Floating(_) | Type::Integer(_) => {
|
Type::ComptimeNumber
|
||||||
true
|
| Type::Pointer { .. }
|
||||||
}
|
| Type::Floating(_)
|
||||||
|
| Type::Integer(_) => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -595,7 +609,12 @@ pub mod tree_visitor {
|
||||||
pub fn new_range(start: Node, end: Node, pre: F1, post: F2) -> Self {
|
pub fn new_range(start: Node, end: Node, pre: F1, post: F2) -> Self {
|
||||||
Self::new_inner(start, End::Exclusive(end), pre, post)
|
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)
|
Self::new_inner(start, End::Inclusive(end), pre, post)
|
||||||
}
|
}
|
||||||
pub fn new_seek(tree: &Tree, start: Node, pre: F1, post: F2) -> Self {
|
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
|
/// short-circuits on the first E
|
||||||
pub fn visit_ok<T, E>(mut self, tree: &Tree) -> core::result::Result<T, E>
|
pub fn visit_ok<T, E>(
|
||||||
|
mut self,
|
||||||
|
tree: &Tree,
|
||||||
|
) -> core::result::Result<T, E>
|
||||||
where
|
where
|
||||||
F1: FnMut(&Tree, Node) -> core::result::Result<T, E>,
|
F1: FnMut(&Tree, Node) -> core::result::Result<T, E>,
|
||||||
F2: FnMut(&Tree, Node) -> core::result::Result<T, E>,
|
F2: FnMut(&Tree, Node) -> core::result::Result<T, E>,
|
||||||
|
|
1071
src/ast2/mod.rs
1071
src/ast2/mod.rs
File diff suppressed because it is too large
Load diff
|
@ -27,7 +27,8 @@ fn main() {
|
||||||
.subcommands([
|
.subcommands([
|
||||||
Command::new("ast").about("output AST."),
|
Command::new("ast").about("output AST."),
|
||||||
Command::new("ast2").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("ir").about("output intermediate representation."),
|
||||||
Command::new("asm").about("output x86-64 assembly (intel syntax)."),
|
Command::new("asm").about("output x86-64 assembly (intel syntax)."),
|
||||||
]);
|
]);
|
||||||
|
@ -80,7 +81,11 @@ fn main() {
|
||||||
} = mir;
|
} = mir;
|
||||||
|
|
||||||
for (name, mir) in functions {
|
for (name, mir) in functions {
|
||||||
println!("{}:\n{}", strings.get_str(name), mir.display(&strings));
|
println!(
|
||||||
|
"{}:\n{}",
|
||||||
|
strings.get_str(name),
|
||||||
|
mir.display(&strings)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"asm" => {
|
"asm" => {
|
||||||
|
|
|
@ -41,7 +41,8 @@ fn main() {
|
||||||
}
|
}
|
||||||
eprintln!(":");
|
eprintln!(":");
|
||||||
for error in &errors {
|
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
|
let location = tokens
|
||||||
.src()
|
.src()
|
||||||
.get_source_span(error.range.start, error.range.end);
|
.get_source_span(error.range.start, error.range.end);
|
||||||
|
|
|
@ -72,7 +72,9 @@ pub fn is_oct_digit(ch: char) -> bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_hex_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
|
/// Trait for only yielding the next item in the Iterator if it tests true for some predicate
|
||||||
|
|
402
src/comptime.rs
402
src/comptime.rs
|
@ -12,7 +12,10 @@ pub mod bigint {
|
||||||
pub struct BigInt(Vec<u32>);
|
pub struct BigInt(Vec<u32>);
|
||||||
|
|
||||||
impl BigInt {
|
impl BigInt {
|
||||||
pub fn parse_digits<C: IntoIterator<Item = char>>(text: C, radix: Radix) -> BigInt {
|
pub fn parse_digits<C: IntoIterator<Item = char>>(
|
||||||
|
text: C,
|
||||||
|
radix: Radix,
|
||||||
|
) -> BigInt {
|
||||||
Self(parse_bigint(text.into_iter(), radix))
|
Self(parse_bigint(text.into_iter(), radix))
|
||||||
}
|
}
|
||||||
pub fn from_u32(v: u32) -> BigInt {
|
pub fn from_u32(v: u32) -> BigInt {
|
||||||
|
@ -237,9 +240,13 @@ pub mod bigint {
|
||||||
|
|
||||||
fn sub(mut self, rhs: Self) -> Self::Output {
|
fn sub(mut self, rhs: Self) -> Self::Output {
|
||||||
if self.0.len() < rhs.0.len() {
|
if self.0.len() < rhs.0.len() {
|
||||||
println!("extending self by {} zeroes", rhs.0.len() - self.0.len());
|
println!(
|
||||||
self.0
|
"extending self by {} zeroes",
|
||||||
.extend(core::iter::repeat(0).take(rhs.0.len() - self.0.len()));
|
rhs.0.len() - self.0.len()
|
||||||
|
);
|
||||||
|
self.0.extend(
|
||||||
|
core::iter::repeat(0).take(rhs.0.len() - self.0.len()),
|
||||||
|
);
|
||||||
println!("self: {self:?}");
|
println!("self: {self:?}");
|
||||||
}
|
}
|
||||||
sub_bigint(&mut self.0, &rhs.0);
|
sub_bigint(&mut self.0, &rhs.0);
|
||||||
|
@ -497,7 +504,10 @@ pub mod bigint {
|
||||||
_ => {
|
_ => {
|
||||||
if scalar.is_power_of_two() {
|
if scalar.is_power_of_two() {
|
||||||
lhs.push(0);
|
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 {
|
} else {
|
||||||
let mut carry = 0;
|
let mut carry = 0;
|
||||||
for a in lhs.iter_mut() {
|
for a in lhs.iter_mut() {
|
||||||
|
@ -583,7 +593,10 @@ pub mod bigint {
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
/// divident must be at least as wide as divisor
|
/// divident must be at least as wide as divisor
|
||||||
/// returns (quotient, remainder)
|
/// 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) {
|
if bigint_is_zero(&divisor.0) {
|
||||||
panic!("divide by zero!");
|
panic!("divide by zero!");
|
||||||
}
|
}
|
||||||
|
@ -601,7 +614,8 @@ pub mod bigint {
|
||||||
|
|
||||||
if divisor.is_power_of_two() {
|
if divisor.is_power_of_two() {
|
||||||
let exp = divisor.trailing_zeros();
|
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());
|
let (mut div, mut rem) = (div.to_vec(), rem.to_vec());
|
||||||
|
|
||||||
shr_bitint(&mut div, exp % u32::BITS as usize);
|
shr_bitint(&mut div, exp % u32::BITS as usize);
|
||||||
|
@ -627,7 +641,10 @@ pub mod bigint {
|
||||||
if shift == 0 {
|
if shift == 0 {
|
||||||
div_rem_core(divident.clone(), &divisor.0)
|
div_rem_core(divident.clone(), &divisor.0)
|
||||||
} else {
|
} 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)
|
(q, r >> shift)
|
||||||
}
|
}
|
||||||
|
@ -636,7 +653,10 @@ pub mod bigint {
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
/// divident must be at least as wide as divisor
|
/// divident must be at least as wide as divisor
|
||||||
/// returns (quotient, remainder)
|
/// 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 divident = divident.normalised();
|
||||||
let mut divisor = divisor.normalised();
|
let mut divisor = divisor.normalised();
|
||||||
|
|
||||||
|
@ -657,7 +677,8 @@ pub mod bigint {
|
||||||
|
|
||||||
if divisor.is_power_of_two() {
|
if divisor.is_power_of_two() {
|
||||||
let exp = divisor.trailing_zeros();
|
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());
|
let (mut div, mut rem) = (div.to_vec(), rem.to_vec());
|
||||||
|
|
||||||
shr_bitint(&mut div, exp % u32::BITS as usize);
|
shr_bitint(&mut div, exp % u32::BITS as usize);
|
||||||
|
@ -789,7 +810,9 @@ pub mod bigint {
|
||||||
// q0 is too large if:
|
// q0 is too large if:
|
||||||
// [a2,a1,a0] < q0 * [b1,b0]
|
// [a2,a1,a0] < q0 * [b1,b0]
|
||||||
// (r << BITS) + a2 < q0 * b1
|
// (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;
|
q0 -= 1;
|
||||||
r += b0 as u64;
|
r += b0 as u64;
|
||||||
}
|
}
|
||||||
|
@ -1018,7 +1041,10 @@ pub mod bigint {
|
||||||
carry
|
carry
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_bigint(text: impl Iterator<Item = char>, radix: Radix) -> Vec<u32> {
|
pub fn parse_bigint(
|
||||||
|
text: impl Iterator<Item = char>,
|
||||||
|
radix: Radix,
|
||||||
|
) -> Vec<u32> {
|
||||||
let digits = text
|
let digits = text
|
||||||
.filter_map(|c| match c {
|
.filter_map(|c| match c {
|
||||||
'_' => None,
|
'_' => None,
|
||||||
|
@ -1086,14 +1112,20 @@ pub mod bigint {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn parse() {
|
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);
|
println!("{:#x?}", bigint);
|
||||||
let bigint = BigInt::parse_digits("f".chars(), Radix::Hex);
|
let bigint = BigInt::parse_digits("f".chars(), Radix::Hex);
|
||||||
println!("{:#x?}", bigint);
|
println!("{:#x?}", bigint);
|
||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
fn add() {
|
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);
|
println!("{:#x?}", a);
|
||||||
let b = BigInt::parse_digits("cafebabe".chars(), Radix::Hex);
|
let b = BigInt::parse_digits("cafebabe".chars(), Radix::Hex);
|
||||||
println!("{:#x?}", b);
|
println!("{:#x?}", b);
|
||||||
|
@ -1111,7 +1143,10 @@ pub mod bigint {
|
||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
fn overflowing_sub() {
|
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);
|
println!("{:#x?}", a);
|
||||||
let b = BigInt::parse_digits("ffff_ffff".chars(), Radix::Hex);
|
let b = BigInt::parse_digits("ffff_ffff".chars(), Radix::Hex);
|
||||||
println!("{:#x?}", b);
|
println!("{:#x?}", b);
|
||||||
|
@ -1120,7 +1155,8 @@ pub mod bigint {
|
||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
fn shr() {
|
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);
|
print!("{:0>8x?} >> 32 ", a);
|
||||||
shr_bitint(&mut a.0, 32);
|
shr_bitint(&mut a.0, 32);
|
||||||
println!("{:0>8x?}", a);
|
println!("{:0>8x?}", a);
|
||||||
|
@ -1152,7 +1188,9 @@ pub mod bigint {
|
||||||
pub mod bigsint {
|
pub mod bigsint {
|
||||||
use std::{
|
use std::{
|
||||||
cmp::Ordering,
|
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, *};
|
use super::bigint::{self, *};
|
||||||
|
@ -1295,11 +1333,13 @@ pub mod bigsint {
|
||||||
match (self.sign, rhs.sign) {
|
match (self.sign, rhs.sign) {
|
||||||
(_, Sign::None) => self,
|
(_, Sign::None) => self,
|
||||||
(Sign::None, _) => rhs,
|
(Sign::None, _) => rhs,
|
||||||
(Sign::Positive, Sign::Positive) | (Sign::Negative, Sign::Negative) => Self {
|
(Sign::Positive, Sign::Positive)
|
||||||
|
| (Sign::Negative, Sign::Negative) => Self {
|
||||||
sign: self.sign,
|
sign: self.sign,
|
||||||
bigint: self.bigint + rhs.bigint,
|
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) {
|
match self.bigint.cmp(&rhs.bigint) {
|
||||||
Ordering::Less => Self {
|
Ordering::Less => Self {
|
||||||
sign: rhs.sign,
|
sign: rhs.sign,
|
||||||
|
@ -1321,11 +1361,13 @@ pub mod bigsint {
|
||||||
|
|
||||||
fn add(self, rhs: u32) -> Self::Output {
|
fn add(self, rhs: u32) -> Self::Output {
|
||||||
match self.sign {
|
match self.sign {
|
||||||
Sign::Negative => match self.bigint.partial_cmp(&rhs).unwrap() {
|
Sign::Negative => {
|
||||||
|
match self.bigint.partial_cmp(&rhs).unwrap() {
|
||||||
Ordering::Less => Self::positive(rhs - self.bigint),
|
Ordering::Less => Self::positive(rhs - self.bigint),
|
||||||
Ordering::Equal => Self::zero(),
|
Ordering::Equal => Self::zero(),
|
||||||
Ordering::Greater => -Self::positive(self.bigint - rhs),
|
Ordering::Greater => -Self::positive(self.bigint - rhs),
|
||||||
},
|
}
|
||||||
|
}
|
||||||
Sign::None => Self::from_u32(rhs),
|
Sign::None => Self::from_u32(rhs),
|
||||||
Sign::Positive => Self::positive(self.bigint + rhs),
|
Sign::Positive => Self::positive(self.bigint + rhs),
|
||||||
}
|
}
|
||||||
|
@ -1337,11 +1379,13 @@ pub mod bigsint {
|
||||||
|
|
||||||
fn add(self, rhs: u64) -> Self::Output {
|
fn add(self, rhs: u64) -> Self::Output {
|
||||||
match self.sign {
|
match self.sign {
|
||||||
Sign::Negative => match self.bigint.partial_cmp(&rhs).unwrap() {
|
Sign::Negative => {
|
||||||
|
match self.bigint.partial_cmp(&rhs).unwrap() {
|
||||||
Ordering::Less => Self::positive(rhs - self.bigint),
|
Ordering::Less => Self::positive(rhs - self.bigint),
|
||||||
Ordering::Equal => Self::zero(),
|
Ordering::Equal => Self::zero(),
|
||||||
Ordering::Greater => -Self::positive(self.bigint - rhs),
|
Ordering::Greater => -Self::positive(self.bigint - rhs),
|
||||||
},
|
}
|
||||||
|
}
|
||||||
Sign::None => Self::from_u64(rhs),
|
Sign::None => Self::from_u64(rhs),
|
||||||
Sign::Positive => Self::positive(self.bigint + rhs),
|
Sign::Positive => Self::positive(self.bigint + rhs),
|
||||||
}
|
}
|
||||||
|
@ -1362,11 +1406,13 @@ pub mod bigsint {
|
||||||
match (self.sign, rhs.sign) {
|
match (self.sign, rhs.sign) {
|
||||||
(_, Sign::None) => self,
|
(_, Sign::None) => self,
|
||||||
(Sign::None, _) => -rhs,
|
(Sign::None, _) => -rhs,
|
||||||
(Sign::Positive, Sign::Negative) | (Sign::Negative, Sign::Positive) => Self {
|
(Sign::Positive, Sign::Negative)
|
||||||
|
| (Sign::Negative, Sign::Positive) => Self {
|
||||||
sign: self.sign,
|
sign: self.sign,
|
||||||
bigint: self.bigint + rhs.bigint,
|
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) {
|
match self.bigint.cmp(&rhs.bigint) {
|
||||||
Ordering::Less => Self {
|
Ordering::Less => Self {
|
||||||
sign: -self.sign,
|
sign: -self.sign,
|
||||||
|
@ -1539,14 +1585,20 @@ impl ComptimeInt {
|
||||||
pub fn add(self, other: Self) -> Result<Self> {
|
pub fn add(self, other: Self) -> Result<Self> {
|
||||||
let (a, b) = self.coalesce(other)?;
|
let (a, b) = self.coalesce(other)?;
|
||||||
match (a, b) {
|
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)?;
|
let bits = a.checked_add(b).ok_or(Error::IntegerOverflow)?;
|
||||||
if bits & !ty.u128_bitmask() != 0 {
|
if bits & !ty.u128_bitmask() != 0 {
|
||||||
return Err(Error::IntegerOverflow);
|
return Err(Error::IntegerOverflow);
|
||||||
}
|
}
|
||||||
Ok(Self::Native { bits, ty })
|
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 width = ty.bits - ty.signed as u16;
|
||||||
let bits = a + b;
|
let bits = a + b;
|
||||||
if bits.bits() > width as u64 {
|
if bits.bits() > width as u64 {
|
||||||
|
@ -1555,7 +1607,9 @@ impl ComptimeInt {
|
||||||
Ok(Self::BigInt { bits, ty })
|
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!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
|
@ -1565,14 +1619,20 @@ impl ComptimeInt {
|
||||||
pub fn sub(self, other: Self) -> Result<Self> {
|
pub fn sub(self, other: Self) -> Result<Self> {
|
||||||
let (a, b) = self.coalesce(other)?;
|
let (a, b) = self.coalesce(other)?;
|
||||||
match (a, b) {
|
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)?;
|
let bits = a.checked_sub(b).ok_or(Error::IntegerOverflow)?;
|
||||||
if bits & !ty.u128_bitmask() != 0 {
|
if bits & !ty.u128_bitmask() != 0 {
|
||||||
return Err(Error::IntegerOverflow);
|
return Err(Error::IntegerOverflow);
|
||||||
}
|
}
|
||||||
Ok(Self::Native { bits, ty })
|
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 width = ty.bits - ty.signed as u16;
|
||||||
let bits = a - b;
|
let bits = a - b;
|
||||||
if bits.bits() > width as u64 {
|
if bits.bits() > width as u64 {
|
||||||
|
@ -1581,7 +1641,9 @@ impl ComptimeInt {
|
||||||
Ok(Self::BigInt { bits, ty })
|
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!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
|
@ -1591,14 +1653,20 @@ impl ComptimeInt {
|
||||||
pub fn mul(self, other: Self) -> Result<Self> {
|
pub fn mul(self, other: Self) -> Result<Self> {
|
||||||
let (a, b) = self.coalesce(other)?;
|
let (a, b) = self.coalesce(other)?;
|
||||||
match (a, b) {
|
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)?;
|
let bits = a.checked_mul(b).ok_or(Error::IntegerOverflow)?;
|
||||||
if bits & !ty.u128_bitmask() != 0 {
|
if bits & !ty.u128_bitmask() != 0 {
|
||||||
return Err(Error::IntegerOverflow);
|
return Err(Error::IntegerOverflow);
|
||||||
}
|
}
|
||||||
Ok(Self::Native { bits, ty })
|
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 width = ty.bits - ty.signed as u16;
|
||||||
let bits = a * b;
|
let bits = a * b;
|
||||||
if bits.bits() > width as u64 {
|
if bits.bits() > width as u64 {
|
||||||
|
@ -1607,7 +1675,9 @@ impl ComptimeInt {
|
||||||
Ok(Self::BigInt { bits, ty })
|
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!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
|
@ -1617,14 +1687,20 @@ impl ComptimeInt {
|
||||||
pub fn div(self, other: Self) -> Result<Self> {
|
pub fn div(self, other: Self) -> Result<Self> {
|
||||||
let (a, b) = self.coalesce(other)?;
|
let (a, b) = self.coalesce(other)?;
|
||||||
match (a, b) {
|
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)?;
|
let bits = a.checked_div(b).ok_or(Error::IntegerOverflow)?;
|
||||||
if bits & !ty.u128_bitmask() != 0 {
|
if bits & !ty.u128_bitmask() != 0 {
|
||||||
return Err(Error::IntegerOverflow);
|
return Err(Error::IntegerOverflow);
|
||||||
}
|
}
|
||||||
Ok(Self::Native { bits, ty })
|
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 width = ty.bits - ty.signed as u16;
|
||||||
let bits = a / b;
|
let bits = a / b;
|
||||||
if bits.bits() > width as u64 {
|
if bits.bits() > width as u64 {
|
||||||
|
@ -1633,7 +1709,9 @@ impl ComptimeInt {
|
||||||
Ok(Self::BigInt { bits, ty })
|
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!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
|
@ -1643,14 +1721,20 @@ impl ComptimeInt {
|
||||||
pub fn rem(self, other: Self) -> Result<Self> {
|
pub fn rem(self, other: Self) -> Result<Self> {
|
||||||
let (a, b) = self.coalesce(other)?;
|
let (a, b) = self.coalesce(other)?;
|
||||||
match (a, b) {
|
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)?;
|
let bits = a.checked_rem(b).ok_or(Error::IntegerOverflow)?;
|
||||||
if bits & !ty.u128_bitmask() != 0 {
|
if bits & !ty.u128_bitmask() != 0 {
|
||||||
return Err(Error::IntegerOverflow);
|
return Err(Error::IntegerOverflow);
|
||||||
}
|
}
|
||||||
Ok(Self::Native { bits, ty })
|
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 width = ty.bits - ty.signed as u16;
|
||||||
let bits = a % b;
|
let bits = a % b;
|
||||||
if bits.bits() > width as u64 {
|
if bits.bits() > width as u64 {
|
||||||
|
@ -1659,7 +1743,9 @@ impl ComptimeInt {
|
||||||
Ok(Self::BigInt { bits, ty })
|
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!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
|
@ -1669,15 +1755,23 @@ impl ComptimeInt {
|
||||||
pub fn bitand(self, other: Self) -> Result<Self> {
|
pub fn bitand(self, other: Self) -> Result<Self> {
|
||||||
let (a, b) = self.coalesce(other)?;
|
let (a, b) = self.coalesce(other)?;
|
||||||
match (a, b) {
|
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);
|
let bits = a.bitand(b);
|
||||||
Ok(Self::Native { bits, ty })
|
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;
|
let bits = a & b;
|
||||||
Ok(Self::BigInt { bits, ty })
|
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!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
|
@ -1687,15 +1781,23 @@ impl ComptimeInt {
|
||||||
pub fn bitor(self, other: Self) -> Result<Self> {
|
pub fn bitor(self, other: Self) -> Result<Self> {
|
||||||
let (a, b) = self.coalesce(other)?;
|
let (a, b) = self.coalesce(other)?;
|
||||||
match (a, b) {
|
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);
|
let bits = a.bitor(b);
|
||||||
Ok(Self::Native { bits, ty })
|
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;
|
let bits = a | b;
|
||||||
Ok(Self::BigInt { bits, ty })
|
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!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
|
@ -1705,15 +1807,23 @@ impl ComptimeInt {
|
||||||
pub fn bitxor(self, other: Self) -> Result<Self> {
|
pub fn bitxor(self, other: Self) -> Result<Self> {
|
||||||
let (a, b) = self.coalesce(other)?;
|
let (a, b) = self.coalesce(other)?;
|
||||||
match (a, b) {
|
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);
|
let bits = a.bitxor(b);
|
||||||
Ok(Self::Native { bits, ty })
|
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;
|
let bits = a ^ b;
|
||||||
Ok(Self::BigInt { bits, ty })
|
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!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
|
@ -1722,8 +1832,14 @@ impl ComptimeInt {
|
||||||
pub fn cmp(self, other: Self) -> Result<Ordering> {
|
pub fn cmp(self, other: Self) -> Result<Ordering> {
|
||||||
let (a, b) = self.coalesce(other)?;
|
let (a, b) = self.coalesce(other)?;
|
||||||
let ord = match (a, b) {
|
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),
|
(ComptimeInt::Comptime(a), ComptimeInt::Comptime(b)) => a.cmp(&b),
|
||||||
_ => {
|
_ => {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
|
@ -1741,11 +1857,13 @@ impl ComptimeInt {
|
||||||
let bits = if ty.signed {
|
let bits = if ty.signed {
|
||||||
(bits as i128)
|
(bits as i128)
|
||||||
.checked_shl(shift)
|
.checked_shl(shift)
|
||||||
.ok_or(Error::IntegerOverflow)? as u128
|
.ok_or(Error::IntegerOverflow)?
|
||||||
|
as u128
|
||||||
} else {
|
} else {
|
||||||
(bits as u128)
|
(bits as u128)
|
||||||
.checked_shl(shift)
|
.checked_shl(shift)
|
||||||
.ok_or(Error::IntegerOverflow)? as u128
|
.ok_or(Error::IntegerOverflow)?
|
||||||
|
as u128
|
||||||
} & ty.u128_bitmask();
|
} & ty.u128_bitmask();
|
||||||
|
|
||||||
Ok(Self::Native { bits, ty })
|
Ok(Self::Native { bits, ty })
|
||||||
|
@ -1770,11 +1888,13 @@ impl ComptimeInt {
|
||||||
let bits = if ty.signed {
|
let bits = if ty.signed {
|
||||||
(bits as i128)
|
(bits as i128)
|
||||||
.checked_shr(shift)
|
.checked_shr(shift)
|
||||||
.ok_or(Error::IntegerOverflow)? as u128
|
.ok_or(Error::IntegerOverflow)?
|
||||||
|
as u128
|
||||||
} else {
|
} else {
|
||||||
(bits as u128)
|
(bits as u128)
|
||||||
.checked_shr(shift)
|
.checked_shr(shift)
|
||||||
.ok_or(Error::IntegerOverflow)? as u128
|
.ok_or(Error::IntegerOverflow)?
|
||||||
|
as u128
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(Self::Native { bits, ty })
|
Ok(Self::Native { bits, ty })
|
||||||
|
@ -1793,7 +1913,9 @@ impl ComptimeInt {
|
||||||
if ty.signed {
|
if ty.signed {
|
||||||
return Err(Error::UnsignedNegation);
|
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 {
|
if bits & !ty.u128_bitmask() != 0 {
|
||||||
return Err(Error::IntegerOverflow);
|
return Err(Error::IntegerOverflow);
|
||||||
|
@ -1811,7 +1933,9 @@ impl ComptimeInt {
|
||||||
bits: !bits | ty.u128_bitmask(),
|
bits: !bits | ty.u128_bitmask(),
|
||||||
ty,
|
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)),
|
ComptimeInt::Comptime(bigint) => Ok(Self::Comptime(!bigint)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1827,8 +1951,14 @@ impl ComptimeInt {
|
||||||
|
|
||||||
fn coalesce(self, other: Self) -> Result<(ComptimeInt, ComptimeInt)> {
|
fn coalesce(self, other: Self) -> Result<(ComptimeInt, ComptimeInt)> {
|
||||||
match (self, other) {
|
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;
|
let b_signed = b.sign() == Sign::Minus;
|
||||||
if !a_ty.signed && b_signed {
|
if !a_ty.signed && b_signed {
|
||||||
return Err(Error::IncompatibleTypes);
|
return Err(Error::IncompatibleTypes);
|
||||||
|
@ -1845,8 +1975,14 @@ impl ComptimeInt {
|
||||||
};
|
};
|
||||||
Ok((lhs, Self::Native { bits: b, ty: a_ty }))
|
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;
|
let b_signed = b.sign() == Sign::Minus;
|
||||||
if !a_ty.signed && b_signed {
|
if !a_ty.signed && b_signed {
|
||||||
return Err(Error::IncompatibleTypes);
|
return Err(Error::IncompatibleTypes);
|
||||||
|
@ -1863,7 +1999,10 @@ impl ComptimeInt {
|
||||||
};
|
};
|
||||||
Ok((Self::Native { bits: b, ty: a_ty }, rhs))
|
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;
|
let b_signed = b.sign() == Sign::Minus;
|
||||||
if !ty.signed && b_signed {
|
if !ty.signed && b_signed {
|
||||||
return Err(Error::IncompatibleTypes);
|
return Err(Error::IncompatibleTypes);
|
||||||
|
@ -1875,7 +2014,10 @@ impl ComptimeInt {
|
||||||
}
|
}
|
||||||
Ok((lhs, Self::BigInt { bits: b, ty }))
|
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;
|
let b_signed = b.sign() == Sign::Minus;
|
||||||
if !ty.signed && b_signed {
|
if !ty.signed && b_signed {
|
||||||
return Err(Error::IncompatibleTypes);
|
return Err(Error::IncompatibleTypes);
|
||||||
|
@ -1887,14 +2029,20 @@ impl ComptimeInt {
|
||||||
}
|
}
|
||||||
Ok((Self::BigInt { bits: b, ty }, rhs))
|
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 {
|
if a == b {
|
||||||
Ok((lhs, rhs))
|
Ok((lhs, rhs))
|
||||||
} else {
|
} else {
|
||||||
Err(Error::IncompatibleTypes)
|
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 {
|
if a == b {
|
||||||
Ok((lhs, rhs))
|
Ok((lhs, rhs))
|
||||||
} else {
|
} else {
|
||||||
|
@ -1915,36 +2063,56 @@ pub enum ComptimeFloat {
|
||||||
impl ComptimeFloat {
|
impl ComptimeFloat {
|
||||||
pub fn add(self, other: Self) -> Result<ComptimeFloat> {
|
pub fn add(self, other: Self) -> Result<ComptimeFloat> {
|
||||||
match (self, other) {
|
match (self, other) {
|
||||||
(ComptimeFloat::Binary32(a), ComptimeFloat::Binary32(b)) => Ok(Self::Binary32(a + b)),
|
(ComptimeFloat::Binary32(a), ComptimeFloat::Binary32(b)) => {
|
||||||
(ComptimeFloat::Binary64(a), ComptimeFloat::Binary64(b)) => Ok(Self::Binary64(a + b)),
|
Ok(Self::Binary32(a + b))
|
||||||
|
}
|
||||||
|
(ComptimeFloat::Binary64(a), ComptimeFloat::Binary64(b)) => {
|
||||||
|
Ok(Self::Binary64(a + b))
|
||||||
|
}
|
||||||
_ => Err(Error::IncompatibleTypes),
|
_ => Err(Error::IncompatibleTypes),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn sub(self, other: Self) -> Result<ComptimeFloat> {
|
pub fn sub(self, other: Self) -> Result<ComptimeFloat> {
|
||||||
match (self, other) {
|
match (self, other) {
|
||||||
(ComptimeFloat::Binary32(a), ComptimeFloat::Binary32(b)) => Ok(Self::Binary32(a - b)),
|
(ComptimeFloat::Binary32(a), ComptimeFloat::Binary32(b)) => {
|
||||||
(ComptimeFloat::Binary64(a), ComptimeFloat::Binary64(b)) => Ok(Self::Binary64(a - b)),
|
Ok(Self::Binary32(a - b))
|
||||||
|
}
|
||||||
|
(ComptimeFloat::Binary64(a), ComptimeFloat::Binary64(b)) => {
|
||||||
|
Ok(Self::Binary64(a - b))
|
||||||
|
}
|
||||||
_ => Err(Error::IncompatibleTypes),
|
_ => Err(Error::IncompatibleTypes),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn mul(self, other: Self) -> Result<ComptimeFloat> {
|
pub fn mul(self, other: Self) -> Result<ComptimeFloat> {
|
||||||
match (self, other) {
|
match (self, other) {
|
||||||
(ComptimeFloat::Binary32(a), ComptimeFloat::Binary32(b)) => Ok(Self::Binary32(a * b)),
|
(ComptimeFloat::Binary32(a), ComptimeFloat::Binary32(b)) => {
|
||||||
(ComptimeFloat::Binary64(a), ComptimeFloat::Binary64(b)) => Ok(Self::Binary64(a * b)),
|
Ok(Self::Binary32(a * b))
|
||||||
|
}
|
||||||
|
(ComptimeFloat::Binary64(a), ComptimeFloat::Binary64(b)) => {
|
||||||
|
Ok(Self::Binary64(a * b))
|
||||||
|
}
|
||||||
_ => Err(Error::IncompatibleTypes),
|
_ => Err(Error::IncompatibleTypes),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn div(self, other: Self) -> Result<ComptimeFloat> {
|
pub fn div(self, other: Self) -> Result<ComptimeFloat> {
|
||||||
match (self, other) {
|
match (self, other) {
|
||||||
(ComptimeFloat::Binary32(a), ComptimeFloat::Binary32(b)) => Ok(Self::Binary32(a / b)),
|
(ComptimeFloat::Binary32(a), ComptimeFloat::Binary32(b)) => {
|
||||||
(ComptimeFloat::Binary64(a), ComptimeFloat::Binary64(b)) => Ok(Self::Binary64(a / b)),
|
Ok(Self::Binary32(a / b))
|
||||||
|
}
|
||||||
|
(ComptimeFloat::Binary64(a), ComptimeFloat::Binary64(b)) => {
|
||||||
|
Ok(Self::Binary64(a / b))
|
||||||
|
}
|
||||||
_ => Err(Error::IncompatibleTypes),
|
_ => Err(Error::IncompatibleTypes),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn rem(self, other: Self) -> Result<ComptimeFloat> {
|
pub fn rem(self, other: Self) -> Result<ComptimeFloat> {
|
||||||
match (self, other) {
|
match (self, other) {
|
||||||
(ComptimeFloat::Binary32(a), ComptimeFloat::Binary32(b)) => Ok(Self::Binary32(a % b)),
|
(ComptimeFloat::Binary32(a), ComptimeFloat::Binary32(b)) => {
|
||||||
(ComptimeFloat::Binary64(a), ComptimeFloat::Binary64(b)) => Ok(Self::Binary64(a % b)),
|
Ok(Self::Binary32(a % b))
|
||||||
|
}
|
||||||
|
(ComptimeFloat::Binary64(a), ComptimeFloat::Binary64(b)) => {
|
||||||
|
Ok(Self::Binary64(a % b))
|
||||||
|
}
|
||||||
_ => Err(Error::IncompatibleTypes),
|
_ => Err(Error::IncompatibleTypes),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1956,8 +2124,12 @@ impl ComptimeFloat {
|
||||||
}
|
}
|
||||||
pub fn cmp(self, other: Self) -> Result<Ordering> {
|
pub fn cmp(self, other: Self) -> Result<Ordering> {
|
||||||
let ord = match (self, other) {
|
let ord = match (self, other) {
|
||||||
(ComptimeFloat::Binary32(a), ComptimeFloat::Binary32(b)) => a.partial_cmp(&b),
|
(ComptimeFloat::Binary32(a), ComptimeFloat::Binary32(b)) => {
|
||||||
(ComptimeFloat::Binary64(a), ComptimeFloat::Binary64(b)) => a.partial_cmp(&b),
|
a.partial_cmp(&b)
|
||||||
|
}
|
||||||
|
(ComptimeFloat::Binary64(a), ComptimeFloat::Binary64(b)) => {
|
||||||
|
a.partial_cmp(&b)
|
||||||
|
}
|
||||||
_ => {
|
_ => {
|
||||||
return Err(Error::IncompatibleTypes);
|
return Err(Error::IncompatibleTypes);
|
||||||
}
|
}
|
||||||
|
@ -2109,7 +2281,9 @@ impl ComptimeNumber {
|
||||||
// (ComptimeNumber::Floating(a), ComptimeNumber::Floating(b)) => {
|
// (ComptimeNumber::Floating(a), ComptimeNumber::Floating(b)) => {
|
||||||
// Ok(Self::Floating(a.sub(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),
|
_ => Err(Error::IncompatibleTypes),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2121,7 +2295,9 @@ impl ComptimeNumber {
|
||||||
// (ComptimeNumber::Floating(a), ComptimeNumber::Floating(b)) => {
|
// (ComptimeNumber::Floating(a), ComptimeNumber::Floating(b)) => {
|
||||||
// Ok(Self::Floating(a.bitor(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),
|
_ => Err(Error::IncompatibleTypes),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2133,7 +2309,9 @@ impl ComptimeNumber {
|
||||||
// (ComptimeNumber::Floating(a), ComptimeNumber::Floating(b)) => {
|
// (ComptimeNumber::Floating(a), ComptimeNumber::Floating(b)) => {
|
||||||
// Ok(Self::Floating(a.bitxor(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),
|
_ => Err(Error::IncompatibleTypes),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2169,7 +2347,9 @@ impl ComptimeNumber {
|
||||||
// (ComptimeNumber::Floating(a), ComptimeNumber::Floating(b)) => {
|
// (ComptimeNumber::Floating(a), ComptimeNumber::Floating(b)) => {
|
||||||
// Ok(Self::Floating(a.bitxor(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),
|
_ => Err(Error::IncompatibleTypes),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2181,23 +2361,35 @@ impl ComptimeNumber {
|
||||||
// (ComptimeNumber::Floating(a), ComptimeNumber::Floating(b)) => {
|
// (ComptimeNumber::Floating(a), ComptimeNumber::Floating(b)) => {
|
||||||
// Ok(Self::Floating(a.bitxor(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),
|
_ => Err(Error::IncompatibleTypes),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn eq(self, other: Self) -> Result<Self> {
|
pub fn eq(self, other: Self) -> Result<Self> {
|
||||||
match (self, other) {
|
match (self, other) {
|
||||||
(ComptimeNumber::Integral(a), ComptimeNumber::Integral(b)) => Ok(Self::Bool(a == b)),
|
(ComptimeNumber::Integral(a), ComptimeNumber::Integral(b)) => {
|
||||||
(ComptimeNumber::Floating(a), ComptimeNumber::Floating(b)) => Ok(Self::Bool(a == b)),
|
Ok(Self::Bool(a == b))
|
||||||
(ComptimeNumber::Bool(a), ComptimeNumber::Bool(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),
|
_ => Err(Error::IncompatibleTypes),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn cmp(self, other: Self) -> Result<Ordering> {
|
pub fn cmp(self, other: Self) -> Result<Ordering> {
|
||||||
let ord = match (self, other) {
|
let ord = match (self, other) {
|
||||||
(ComptimeNumber::Integral(a), ComptimeNumber::Integral(b)) => a.cmp(b)?,
|
(ComptimeNumber::Integral(a), ComptimeNumber::Integral(b)) => {
|
||||||
(ComptimeNumber::Floating(a), ComptimeNumber::Floating(b)) => a.cmp(b)?,
|
a.cmp(b)?
|
||||||
|
}
|
||||||
|
(ComptimeNumber::Floating(a), ComptimeNumber::Floating(b)) => {
|
||||||
|
a.cmp(b)?
|
||||||
|
}
|
||||||
(ComptimeNumber::Bool(a), ComptimeNumber::Bool(b)) => a.cmp(&b),
|
(ComptimeNumber::Bool(a), ComptimeNumber::Bool(b)) => a.cmp(&b),
|
||||||
_ => {
|
_ => {
|
||||||
return Err(Error::IncompatibleTypes);
|
return Err(Error::IncompatibleTypes);
|
||||||
|
@ -2237,12 +2429,17 @@ impl ComptimeNumber {
|
||||||
match self {
|
match self {
|
||||||
ComptimeNumber::Integral(i) => match i {
|
ComptimeNumber::Integral(i) => match i {
|
||||||
ComptimeInt::Native { bits, .. } => Ok((bits != 0).into()),
|
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())
|
Ok((bits.sign() != Sign::NoSign).into())
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
ComptimeNumber::Floating(ComptimeFloat::Binary32(f)) => Ok((f != 0.0).into()),
|
ComptimeNumber::Floating(ComptimeFloat::Binary32(f)) => {
|
||||||
ComptimeNumber::Floating(ComptimeFloat::Binary64(f)) => Ok((f != 0.0).into()),
|
Ok((f != 0.0).into())
|
||||||
|
}
|
||||||
|
ComptimeNumber::Floating(ComptimeFloat::Binary64(f)) => {
|
||||||
|
Ok((f != 0.0).into())
|
||||||
|
}
|
||||||
a => Ok(a),
|
a => Ok(a),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2250,19 +2447,29 @@ impl ComptimeNumber {
|
||||||
pub fn into_int(self, ty: IntegralType) -> Result<Self> {
|
pub fn into_int(self, ty: IntegralType) -> Result<Self> {
|
||||||
match self {
|
match self {
|
||||||
ComptimeNumber::Integral(i) => match i {
|
ComptimeNumber::Integral(i) => match i {
|
||||||
ComptimeInt::Native { bits, .. } => Ok((bits & ty.u128_bitmask(), ty).into()),
|
ComptimeInt::Native { bits, .. } => {
|
||||||
ComptimeInt::Comptime(bits) | ComptimeInt::BigInt { bits, .. } => {
|
Ok((bits & ty.u128_bitmask(), ty).into())
|
||||||
let max = BigUint::from(2u32).pow((ty.bits - ty.signed as u16) as u32);
|
}
|
||||||
|
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 (sign, data) = bits.into_parts();
|
||||||
let data = data.clamp(BigUint::ZERO, max);
|
let data = data.clamp(BigUint::ZERO, max);
|
||||||
|
|
||||||
Ok((BigInt::from_biguint(sign, data), ty).into())
|
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 {
|
ComptimeNumber::Floating(f) => match f {
|
||||||
ComptimeFloat::Binary32(f) => Ok((f as u128 & ty.u128_bitmask(), ty).into()),
|
ComptimeFloat::Binary32(f) => {
|
||||||
ComptimeFloat::Binary64(f) => Ok((f as u128 & ty.u128_bitmask(), ty).into()),
|
Ok((f as u128 & ty.u128_bitmask(), ty).into())
|
||||||
|
}
|
||||||
|
ComptimeFloat::Binary64(f) => {
|
||||||
|
Ok((f as u128 & ty.u128_bitmask(), ty).into())
|
||||||
|
}
|
||||||
},
|
},
|
||||||
ComptimeNumber::Void => {
|
ComptimeNumber::Void => {
|
||||||
return Err(Error::VoidConversion);
|
return Err(Error::VoidConversion);
|
||||||
|
@ -2273,7 +2480,8 @@ impl ComptimeNumber {
|
||||||
let f = match self {
|
let f = match self {
|
||||||
ComptimeNumber::Integral(i) => match i {
|
ComptimeNumber::Integral(i) => match i {
|
||||||
ComptimeInt::Native { bits, .. } => bits as f64,
|
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)
|
bits.to_f64().unwrap_or(f64::NAN)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
97
src/lexer.rs
97
src/lexer.rs
|
@ -83,7 +83,11 @@ impl<'a> Chars<'a> {
|
||||||
SourceLocation::new(start_l, start_c)
|
SourceLocation::new(start_l, start_c)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_source_span(&self, start: u32, end: u32) -> std::ops::Range<SourceLocation> {
|
pub fn get_source_span(
|
||||||
|
&self,
|
||||||
|
start: u32,
|
||||||
|
end: u32,
|
||||||
|
) -> std::ops::Range<SourceLocation> {
|
||||||
let (start_l, start_c) = {
|
let (start_l, start_c) = {
|
||||||
let range = self.get_from_to(0, start);
|
let range = self.get_from_to(0, start);
|
||||||
range.chars().fold((1u32, 0u32), |(line, col), c| {
|
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<u32>) -> &str {
|
pub fn get_range(&self, range: core::ops::Range<u32>) -> &str {
|
||||||
unsafe {
|
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 {
|
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<char> {
|
fn next_char(&mut self) -> Option<char> {
|
||||||
|
@ -205,7 +215,12 @@ impl DelimitorConditions {
|
||||||
|| self.semis > cond.semis
|
|| self.semis > cond.semis
|
||||||
}
|
}
|
||||||
|
|
||||||
fn from_i32s(braces: i32, parens: i32, brackets: i32, semis: Option<u32>) -> Self {
|
fn from_i32s(
|
||||||
|
braces: i32,
|
||||||
|
parens: i32,
|
||||||
|
brackets: i32,
|
||||||
|
semis: Option<u32>,
|
||||||
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
braces: DelimitorCondition::from_i32(braces),
|
braces: DelimitorCondition::from_i32(braces),
|
||||||
parens: DelimitorCondition::from_i32(parens),
|
parens: DelimitorCondition::from_i32(parens),
|
||||||
|
@ -216,7 +231,10 @@ impl DelimitorConditions {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> TokenIterator<'a> {
|
impl<'a> TokenIterator<'a> {
|
||||||
pub fn advance_until_before_token(&mut self, token: Token) -> Option<Token> {
|
pub fn advance_until_before_token(
|
||||||
|
&mut self,
|
||||||
|
token: Token,
|
||||||
|
) -> Option<Token> {
|
||||||
while let Some(next) = self.peek_token() {
|
while let Some(next) = self.peek_token() {
|
||||||
if next.token() == token {
|
if next.token() == token {
|
||||||
return Some(token);
|
return Some(token);
|
||||||
|
@ -226,7 +244,10 @@ impl<'a> TokenIterator<'a> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn advance_until_before_one_of(&mut self, tokens: &[Token]) -> Option<Token> {
|
pub fn advance_until_before_one_of(
|
||||||
|
&mut self,
|
||||||
|
tokens: &[Token],
|
||||||
|
) -> Option<Token> {
|
||||||
while let Some(next) = self.peek_token() {
|
while let Some(next) = self.peek_token() {
|
||||||
if tokens.contains(&next.token()) {
|
if tokens.contains(&next.token()) {
|
||||||
return Some(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.advance_past_condition(cond)?;
|
||||||
_ = self.offset.saturating_sub(1);
|
_ = self.offset.saturating_sub(1);
|
||||||
Some(())
|
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 braces = 0;
|
||||||
let mut parens = 0;
|
let mut parens = 0;
|
||||||
let mut brackets = 0;
|
let mut brackets = 0;
|
||||||
|
@ -341,8 +368,12 @@ impl<'a> TokenIterator<'a> {
|
||||||
_ => { /* nada */ }
|
_ => { /* nada */ }
|
||||||
}
|
}
|
||||||
|
|
||||||
let current =
|
let current = DelimitorConditions::from_i32s(
|
||||||
DelimitorConditions::from_i32s(braces, parens, brackets, cond.semis.map(|_| semis));
|
braces,
|
||||||
|
parens,
|
||||||
|
brackets,
|
||||||
|
cond.semis.map(|_| semis),
|
||||||
|
);
|
||||||
if cond == current {
|
if cond == current {
|
||||||
return Some(());
|
return Some(());
|
||||||
}
|
}
|
||||||
|
@ -377,13 +408,16 @@ impl<'a> TokenIterator<'a> {
|
||||||
.next()
|
.next()
|
||||||
.map(|i| i.source_location())
|
.map(|i| i.source_location())
|
||||||
.unwrap_or_else(|| {
|
.unwrap_or_else(|| {
|
||||||
self.tokenizer
|
self.tokenizer.source.offset_to_source_location(
|
||||||
.source
|
self.tokenizer.source.num_bytes() as u32,
|
||||||
.offset_to_source_location(self.tokenizer.source.num_bytes() as u32)
|
)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn expect_token(&mut self, token: Token) -> crate::parser::Result<TokenItem<'a>> {
|
pub fn expect_token(
|
||||||
|
&mut self,
|
||||||
|
token: Token,
|
||||||
|
) -> crate::parser::Result<TokenItem<'a>> {
|
||||||
self.next_if(|item| item.token() == token)
|
self.next_if(|item| item.token() == token)
|
||||||
.ok_or(crate::parser::Error::ExpectedTokenNotFound(token))
|
.ok_or(crate::parser::Error::ExpectedTokenNotFound(token))
|
||||||
}
|
}
|
||||||
|
@ -395,13 +429,18 @@ impl<'a> TokenIterator<'a> {
|
||||||
pub fn peek_token(&mut self) -> Option<TokenItem<'a>> {
|
pub fn peek_token(&mut self) -> Option<TokenItem<'a>> {
|
||||||
self.clone().next()
|
self.clone().next()
|
||||||
}
|
}
|
||||||
pub fn peek_token_or_err(&mut self) -> crate::parser::Result<TokenItem<'a>> {
|
pub fn peek_token_or_err(
|
||||||
|
&mut self,
|
||||||
|
) -> crate::parser::Result<TokenItem<'a>> {
|
||||||
self.clone()
|
self.clone()
|
||||||
.next()
|
.next()
|
||||||
.ok_or(crate::parser::Error::UnexpectedEndOfTokens)
|
.ok_or(crate::parser::Error::UnexpectedEndOfTokens)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn peek_expect_token(&mut self, token: Token) -> crate::parser::Result<TokenItem<'a>> {
|
pub fn peek_expect_token(
|
||||||
|
&mut self,
|
||||||
|
token: Token,
|
||||||
|
) -> crate::parser::Result<TokenItem<'a>> {
|
||||||
self.clone()
|
self.clone()
|
||||||
.next()
|
.next()
|
||||||
.ok_or(crate::parser::Error::ExpectedTokenNotFound(token))
|
.ok_or(crate::parser::Error::ExpectedTokenNotFound(token))
|
||||||
|
@ -644,9 +683,16 @@ impl<'a> Tokenizer<'a> {
|
||||||
// .unwrap_or(false);
|
// .unwrap_or(false);
|
||||||
let end = this.source.position();
|
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
|
this.source
|
||||||
.take_while_ref(|&c| !crate::common::is_whitespace(c))
|
.take_while_ref(|&c| {
|
||||||
|
!crate::common::is_whitespace(c)
|
||||||
|
})
|
||||||
.count();
|
.count();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -713,7 +759,10 @@ impl<'a> Tokenizer<'a> {
|
||||||
let mut peeking = self.source.clone();
|
let mut peeking = self.source.clone();
|
||||||
match peeking.next() {
|
match peeking.next() {
|
||||||
Some('0'..='9') => Some(parse_constant(&mut self.source)?),
|
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)?)
|
Some(parse_constant(&mut self.source)?)
|
||||||
}
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
|
@ -796,7 +845,11 @@ impl<'a> Tokenizer<'a> {
|
||||||
.count()
|
.count()
|
||||||
.gt(&0)
|
.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<Token> {
|
||||||
Err(e) => Err(e),
|
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);
|
return Ok(Token::IntegerConstant);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,9 @@ pub mod triples;
|
||||||
|
|
||||||
pub fn tokenize<'a>(
|
pub fn tokenize<'a>(
|
||||||
bytes: &'a [u8],
|
bytes: &'a [u8],
|
||||||
) -> Result<lexer::Tokenizer<'a>, (lexer::Tokenizer<'a>, Vec<lexer::TokenizeError>)> {
|
) -> Result<
|
||||||
|
lexer::Tokenizer<'a>,
|
||||||
|
(lexer::Tokenizer<'a>, Vec<lexer::TokenizeError>),
|
||||||
|
> {
|
||||||
lexer::Tokenizer::new_with_errors(bytes)
|
lexer::Tokenizer::new_with_errors(bytes)
|
||||||
}
|
}
|
||||||
|
|
1100
src/mir.rs
1100
src/mir.rs
File diff suppressed because it is too large
Load diff
409
src/parser.rs
409
src/parser.rs
|
@ -4,7 +4,10 @@ use itertools::Itertools;
|
||||||
use num_bigint::{BigInt, BigUint};
|
use num_bigint::{BigInt, BigUint};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
ast::{self, FloatingType, IntegralType, LetOrVar, Node, PrimitiveType, Tag, Type},
|
ast::{
|
||||||
|
self, FloatingType, IntegralType, LetOrVar, Node, PrimitiveType, Tag,
|
||||||
|
Type,
|
||||||
|
},
|
||||||
common::NextIf,
|
common::NextIf,
|
||||||
comptime::{self, ComptimeNumber},
|
comptime::{self, ComptimeNumber},
|
||||||
error::{AnalysisError, AnalysisErrorTag},
|
error::{AnalysisError, AnalysisErrorTag},
|
||||||
|
@ -145,13 +148,17 @@ impl Tree {
|
||||||
.map(|decl| {
|
.map(|decl| {
|
||||||
let name = match self.nodes.get_node(*decl) {
|
let name = match self.nodes.get_node(*decl) {
|
||||||
Tag::FunctionDecl { proto, .. } => {
|
Tag::FunctionDecl { proto, .. } => {
|
||||||
let Tag::FunctionProto { name, .. } = self.nodes.get_node(*proto) else {
|
let Tag::FunctionProto { name, .. } =
|
||||||
|
self.nodes.get_node(*proto)
|
||||||
|
else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
};
|
};
|
||||||
|
|
||||||
self.get_ident_str(*name).unwrap().to_owned()
|
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!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
|
@ -237,7 +244,10 @@ impl Tree {
|
||||||
IntegralType { signed, bits }
|
IntegralType { signed, bits }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_integral_constant(token: Token, lexeme: &str) -> (BigInt, Option<IntegralType>) {
|
fn parse_integral_constant(
|
||||||
|
token: Token,
|
||||||
|
lexeme: &str,
|
||||||
|
) -> (BigInt, Option<IntegralType>) {
|
||||||
let radix = Radix::from_token(token).unwrap();
|
let radix = Radix::from_token(token).unwrap();
|
||||||
|
|
||||||
// TODO: figure out how to do this safely for bigger types, whether to
|
// 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 value = comptime::bigint::parse_bigint(digits.into_iter(), radix);
|
||||||
|
|
||||||
let ty = match iter.clone().next() {
|
let ty = match iter.clone().next() {
|
||||||
Some((_, 'u')) | Some((_, 'i')) => {
|
Some((_, 'u')) | Some((_, 'i')) => Some(Self::parse_integral_type(
|
||||||
Some(Self::parse_integral_type(&lexeme[iter.next().unwrap().0..]))
|
&lexeme[iter.next().unwrap().0..],
|
||||||
}
|
)),
|
||||||
_ => None,
|
_ => 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 {
|
// let (dot, exp) = match token {
|
||||||
// Token::DotFloatingExpConstant => (true, true),
|
// Token::DotFloatingExpConstant => (true, true),
|
||||||
// Token::DotFloatingConstant => (true, false),
|
// Token::DotFloatingConstant => (true, false),
|
||||||
|
@ -292,8 +305,12 @@ impl Tree {
|
||||||
);
|
);
|
||||||
|
|
||||||
let bits = match lexeme.1 {
|
let bits = match lexeme.1 {
|
||||||
FloatingType::Binary32 => lexeme.0.parse::<f32>().unwrap().to_bits() as u64,
|
FloatingType::Binary32 => {
|
||||||
FloatingType::Binary64 => lexeme.0.parse::<f64>().unwrap().to_bits() as u64,
|
lexeme.0.parse::<f32>().unwrap().to_bits() as u64
|
||||||
|
}
|
||||||
|
FloatingType::Binary64 => {
|
||||||
|
lexeme.0.parse::<f64>().unwrap().to_bits() as u64
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
(bits, lexeme.1)
|
(bits, lexeme.1)
|
||||||
|
@ -312,7 +329,10 @@ impl Tree {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_primitive_type(&mut self, tokens: &mut TokenIterator) -> Result<Node> {
|
pub fn parse_primitive_type(
|
||||||
|
&mut self,
|
||||||
|
tokens: &mut TokenIterator,
|
||||||
|
) -> Result<Node> {
|
||||||
let token = tokens.next().ok_or(Error::UnexpectedEndOfTokens)?;
|
let token = tokens.next().ok_or(Error::UnexpectedEndOfTokens)?;
|
||||||
let prim = match token.token() {
|
let prim = match token.token() {
|
||||||
Token::Void => PrimitiveType::Void,
|
Token::Void => PrimitiveType::Void,
|
||||||
|
@ -327,7 +347,10 @@ impl Tree {
|
||||||
Ok(self.nodes.push_tag(Tag::PrimitiveType(prim)))
|
Ok(self.nodes.push_tag(Tag::PrimitiveType(prim)))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_pointer(&mut self, tokens: &mut TokenIterator) -> Result<Node> {
|
pub fn parse_pointer(
|
||||||
|
&mut self,
|
||||||
|
tokens: &mut TokenIterator,
|
||||||
|
) -> Result<Node> {
|
||||||
tokens.expect_token(Token::Star)?;
|
tokens.expect_token(Token::Star)?;
|
||||||
let _constness = tokens.eat_token(Token::Const);
|
let _constness = tokens.eat_token(Token::Const);
|
||||||
let typename = self.parse_typename(tokens)?;
|
let typename = self.parse_typename(tokens)?;
|
||||||
|
@ -335,15 +358,21 @@ impl Tree {
|
||||||
Ok(self.nodes.push_tag(Tag::Pointer { pointee: typename }))
|
Ok(self.nodes.push_tag(Tag::Pointer { pointee: typename }))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_typename(&mut self, tokens: &mut TokenIterator) -> Result<Node> {
|
pub fn parse_typename(
|
||||||
|
&mut self,
|
||||||
|
tokens: &mut TokenIterator,
|
||||||
|
) -> Result<Node> {
|
||||||
match tokens.peek_token_or_err()?.token() {
|
match tokens.peek_token_or_err()?.token() {
|
||||||
Token::Star => self.parse_pointer(tokens),
|
Token::Star => self.parse_pointer(tokens),
|
||||||
Token::Ident => {
|
Token::Ident => {
|
||||||
let token = tokens.next().unwrap();
|
let token = tokens.next().unwrap();
|
||||||
match Self::try_parse_integral_type(token.lexeme())? {
|
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 => {
|
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 }))
|
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<Node> {
|
pub fn parse_var_decl(
|
||||||
|
&mut self,
|
||||||
|
tokens: &mut TokenIterator,
|
||||||
|
) -> Result<Node> {
|
||||||
let let_or_var = match tokens
|
let let_or_var = match tokens
|
||||||
.eat_token(Token::Let)
|
.eat_token(Token::Let)
|
||||||
.or_else(|| tokens.eat_token(Token::Var))
|
.or_else(|| tokens.eat_token(Token::Var))
|
||||||
|
@ -400,7 +432,10 @@ impl Tree {
|
||||||
|
|
||||||
/// GLOBAL_DECL <-
|
/// GLOBAL_DECL <-
|
||||||
/// const IDENTIFIER (: TYPENAME)? = EXPR;
|
/// const IDENTIFIER (: TYPENAME)? = EXPR;
|
||||||
pub fn parse_global_decl(&mut self, tokens: &mut TokenIterator) -> Result<Node> {
|
pub fn parse_global_decl(
|
||||||
|
&mut self,
|
||||||
|
tokens: &mut TokenIterator,
|
||||||
|
) -> Result<Node> {
|
||||||
_ = tokens.expect_token(Token::Const)?;
|
_ = tokens.expect_token(Token::Const)?;
|
||||||
|
|
||||||
let name = self.parse_ident(tokens)?;
|
let name = self.parse_ident(tokens)?;
|
||||||
|
@ -445,7 +480,10 @@ impl Tree {
|
||||||
|
|
||||||
/// PARAMETER <-
|
/// PARAMETER <-
|
||||||
/// IDENTIFIER : TYPENAME
|
/// IDENTIFIER : TYPENAME
|
||||||
pub fn parse_parameter(&mut self, tokens: &mut TokenIterator) -> Result<Node> {
|
pub fn parse_parameter(
|
||||||
|
&mut self,
|
||||||
|
tokens: &mut TokenIterator,
|
||||||
|
) -> Result<Node> {
|
||||||
let name = self.parse_ident(tokens)?;
|
let name = self.parse_ident(tokens)?;
|
||||||
tokens.expect_token(Token::Colon)?;
|
tokens.expect_token(Token::Colon)?;
|
||||||
let ty = self.parse_typename(tokens)?;
|
let ty = self.parse_typename(tokens)?;
|
||||||
|
@ -464,7 +502,10 @@ impl Tree {
|
||||||
/// PARAMETER_LIST <-
|
/// PARAMETER_LIST <-
|
||||||
/// PARAMETER
|
/// PARAMETER
|
||||||
/// PARAMETER_LIST , PARAMETER
|
/// PARAMETER_LIST , PARAMETER
|
||||||
pub fn parse_parameter_list(&mut self, tokens: &mut TokenIterator) -> Result<Node> {
|
pub fn parse_parameter_list(
|
||||||
|
&mut self,
|
||||||
|
tokens: &mut TokenIterator,
|
||||||
|
) -> Result<Node> {
|
||||||
let mut parameters = Vec::new();
|
let mut parameters = Vec::new();
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
|
@ -489,7 +530,10 @@ impl Tree {
|
||||||
/// fn IDENTIFIER () -> TYPENAME
|
/// fn IDENTIFIER () -> TYPENAME
|
||||||
/// fn IDENTIFIER ( PARAMETER_LIST ,? )
|
/// fn IDENTIFIER ( PARAMETER_LIST ,? )
|
||||||
/// fn IDENTIFIER ( PARAMETER_LIST ,? ) -> TYPENAME
|
/// 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)?;
|
tokens.expect_token(Token::Fn)?;
|
||||||
let name = self.parse_ident(tokens)?;
|
let name = self.parse_ident(tokens)?;
|
||||||
tokens.expect_token(Token::OpenParens)?;
|
tokens.expect_token(Token::OpenParens)?;
|
||||||
|
@ -520,7 +564,10 @@ impl Tree {
|
||||||
|
|
||||||
/// FUNCTION_DECL <-
|
/// FUNCTION_DECL <-
|
||||||
/// FUNCTION_PROTO BLOCK
|
/// FUNCTION_PROTO BLOCK
|
||||||
pub fn parse_fn_decl(&mut self, tokens: &mut TokenIterator) -> Result<Node> {
|
pub fn parse_fn_decl(
|
||||||
|
&mut self,
|
||||||
|
tokens: &mut TokenIterator,
|
||||||
|
) -> Result<Node> {
|
||||||
let (proto, name) = self.parse_fn_proto(tokens)?;
|
let (proto, name) = self.parse_fn_proto(tokens)?;
|
||||||
|
|
||||||
let decl = match self
|
let decl = match self
|
||||||
|
@ -530,8 +577,10 @@ impl Tree {
|
||||||
Some(record) => record.node(),
|
Some(record) => record.node(),
|
||||||
None => {
|
None => {
|
||||||
let decl = self.nodes.reserve_node();
|
let decl = self.nodes.reserve_node();
|
||||||
self.st
|
self.st.insert_orderless_symbol(
|
||||||
.insert_orderless_symbol(&self.get_ident_str(name).unwrap().to_owned(), decl);
|
&self.get_ident_str(name).unwrap().to_owned(),
|
||||||
|
decl,
|
||||||
|
);
|
||||||
decl
|
decl
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -541,7 +590,9 @@ impl Tree {
|
||||||
let body = self.parse_block(tokens, Some(block))?;
|
let body = self.parse_block(tokens, Some(block))?;
|
||||||
let unresolved = self
|
let unresolved = self
|
||||||
.st
|
.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::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
self.st.into_parent();
|
self.st.into_parent();
|
||||||
self.st.extend_orderless(unresolved);
|
self.st.extend_orderless(unresolved);
|
||||||
|
@ -615,7 +666,10 @@ impl Tree {
|
||||||
/// ASSIGNMENT_EXPR <-
|
/// ASSIGNMENT_EXPR <-
|
||||||
/// BINARY_EXPRESSION
|
/// BINARY_EXPRESSION
|
||||||
/// BINARY_EXPRESSION ASSIGNMENT_OP EXPRESSION
|
/// BINARY_EXPRESSION ASSIGNMENT_OP EXPRESSION
|
||||||
pub fn parse_assignment_expr(&mut self, tokens: &mut TokenIterator) -> Result<Node> {
|
pub fn parse_assignment_expr(
|
||||||
|
&mut self,
|
||||||
|
tokens: &mut TokenIterator,
|
||||||
|
) -> Result<Node> {
|
||||||
let lhs = self.parse_binary_expr(tokens, 0)?;
|
let lhs = self.parse_binary_expr(tokens, 0)?;
|
||||||
|
|
||||||
Ok(self.try_parse_assignment(lhs, tokens)?.unwrap_or(lhs))
|
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::MinusEqual => self.nodes.push_tag(Tag::Sub { lhs, rhs }),
|
||||||
Token::StarEqual => self.nodes.push_tag(Tag::Mul { lhs, rhs }),
|
Token::StarEqual => self.nodes.push_tag(Tag::Mul { lhs, rhs }),
|
||||||
Token::SlashEqual => self.nodes.push_tag(Tag::Sub { lhs, rhs }),
|
Token::SlashEqual => self.nodes.push_tag(Tag::Sub { lhs, rhs }),
|
||||||
Token::PercentEqual => self.nodes.push_tag(Tag::Rem { lhs, rhs }),
|
Token::PercentEqual => {
|
||||||
Token::PipeEqual => self.nodes.push_tag(Tag::BitOr { lhs, rhs }),
|
self.nodes.push_tag(Tag::Rem { lhs, rhs })
|
||||||
Token::CaretEqual => self.nodes.push_tag(Tag::BitXOr { lhs, rhs }),
|
}
|
||||||
Token::AmpersandEqual => self.nodes.push_tag(Tag::BitAnd { lhs, rhs }),
|
Token::PipeEqual => {
|
||||||
Token::LessLessEqual => self.nodes.push_tag(Tag::Shl { lhs, rhs }),
|
self.nodes.push_tag(Tag::BitOr { lhs, rhs })
|
||||||
Token::GreaterGreaterEqual => self.nodes.push_tag(Tag::Shr { 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,
|
Token::Equal => rhs,
|
||||||
_ => {
|
_ => {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
|
@ -662,7 +728,10 @@ impl Tree {
|
||||||
|
|
||||||
/// RETURN_STATEMENT <-
|
/// RETURN_STATEMENT <-
|
||||||
/// return EXPRESSION? ;
|
/// return EXPRESSION? ;
|
||||||
pub fn try_parse_return_stmt(&mut self, tokens: &mut TokenIterator) -> Result<Option<Node>> {
|
pub fn try_parse_return_stmt(
|
||||||
|
&mut self,
|
||||||
|
tokens: &mut TokenIterator,
|
||||||
|
) -> Result<Option<Node>> {
|
||||||
if tokens.eat_token(Token::Return).is_some() {
|
if tokens.eat_token(Token::Return).is_some() {
|
||||||
let expr = if !tokens.is_next_token(Token::Semi) {
|
let expr = if !tokens.is_next_token(Token::Semi) {
|
||||||
let expr = Some(self.parse_expr(tokens)?);
|
let expr = Some(self.parse_expr(tokens)?);
|
||||||
|
@ -683,7 +752,10 @@ impl Tree {
|
||||||
/// RETURN_EXPRESSION
|
/// RETURN_EXPRESSION
|
||||||
/// VAR_DECL ;
|
/// VAR_DECL ;
|
||||||
/// EXPRESSION ;
|
/// EXPRESSION ;
|
||||||
pub fn parse_statement(&mut self, tokens: &mut TokenIterator) -> Result<Node> {
|
pub fn parse_statement(
|
||||||
|
&mut self,
|
||||||
|
tokens: &mut TokenIterator,
|
||||||
|
) -> Result<Node> {
|
||||||
match tokens.peek_token_or_err()?.token() {
|
match tokens.peek_token_or_err()?.token() {
|
||||||
Token::Return => Ok(self.try_parse_return_stmt(tokens)?.unwrap()),
|
Token::Return => Ok(self.try_parse_return_stmt(tokens)?.unwrap()),
|
||||||
Token::Var | Token::Let => {
|
Token::Var | Token::Let => {
|
||||||
|
@ -779,7 +851,10 @@ impl Tree {
|
||||||
/// - POSTFIX_EXPR
|
/// - POSTFIX_EXPR
|
||||||
/// & POSTFIX_EXPR
|
/// & POSTFIX_EXPR
|
||||||
/// * POSTFIX_EXPR
|
/// * POSTFIX_EXPR
|
||||||
pub fn parse_prefix_expr(&mut self, tokens: &mut TokenIterator) -> Result<Node> {
|
pub fn parse_prefix_expr(
|
||||||
|
&mut self,
|
||||||
|
tokens: &mut TokenIterator,
|
||||||
|
) -> Result<Node> {
|
||||||
match tokens.peek_token_or_err()?.token() {
|
match tokens.peek_token_or_err()?.token() {
|
||||||
Token::Bang => {
|
Token::Bang => {
|
||||||
_ = tokens.next();
|
_ = tokens.next();
|
||||||
|
@ -808,7 +883,10 @@ impl Tree {
|
||||||
/// AS_EXPR <-
|
/// AS_EXPR <-
|
||||||
/// PREFIX_EXPR
|
/// PREFIX_EXPR
|
||||||
/// PREFIX_EXPR as TYPENAME
|
/// PREFIX_EXPR as TYPENAME
|
||||||
pub fn parse_as_expr(&mut self, tokens: &mut TokenIterator) -> Result<Node> {
|
pub fn parse_as_expr(
|
||||||
|
&mut self,
|
||||||
|
tokens: &mut TokenIterator,
|
||||||
|
) -> Result<Node> {
|
||||||
let expr = self.parse_prefix_expr(tokens)?;
|
let expr = self.parse_prefix_expr(tokens)?;
|
||||||
|
|
||||||
if tokens.eat_token(Token::As).is_some() {
|
if tokens.eat_token(Token::As).is_some() {
|
||||||
|
@ -825,7 +903,10 @@ impl Tree {
|
||||||
/// ARGUMENT <-
|
/// ARGUMENT <-
|
||||||
/// IDENT : EXPR
|
/// IDENT : EXPR
|
||||||
/// EXPR
|
/// EXPR
|
||||||
pub fn parse_argument(&mut self, tokens: &mut TokenIterator) -> Result<Node> {
|
pub fn parse_argument(
|
||||||
|
&mut self,
|
||||||
|
tokens: &mut TokenIterator,
|
||||||
|
) -> Result<Node> {
|
||||||
if tokens.is_next_token2(Token::Colon) {
|
if tokens.is_next_token2(Token::Colon) {
|
||||||
let name = self.parse_ident(tokens)?;
|
let name = self.parse_ident(tokens)?;
|
||||||
_ = tokens.expect_token(Token::Colon)?;
|
_ = tokens.expect_token(Token::Colon)?;
|
||||||
|
@ -843,7 +924,10 @@ impl Tree {
|
||||||
/// ARGUMENT_LIST <-
|
/// ARGUMENT_LIST <-
|
||||||
/// ARGUMENT
|
/// ARGUMENT
|
||||||
/// ARGUMENT_LIST , ARGUMENT
|
/// ARGUMENT_LIST , ARGUMENT
|
||||||
pub fn parse_argument_list(&mut self, tokens: &mut TokenIterator) -> Result<Node> {
|
pub fn parse_argument_list(
|
||||||
|
&mut self,
|
||||||
|
tokens: &mut TokenIterator,
|
||||||
|
) -> Result<Node> {
|
||||||
let mut arguments = Vec::new();
|
let mut arguments = Vec::new();
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
|
@ -867,7 +951,10 @@ impl Tree {
|
||||||
/// PRIMARY_EXPR
|
/// PRIMARY_EXPR
|
||||||
/// PRIMARY_EXPR ( )
|
/// PRIMARY_EXPR ( )
|
||||||
/// PRIMARY_EXPR ( ARGUMENT_LIST )
|
/// PRIMARY_EXPR ( ARGUMENT_LIST )
|
||||||
pub fn parse_postfix_expr(&mut self, tokens: &mut TokenIterator) -> Result<Node> {
|
pub fn parse_postfix_expr(
|
||||||
|
&mut self,
|
||||||
|
tokens: &mut TokenIterator,
|
||||||
|
) -> Result<Node> {
|
||||||
let lhs = self.parse_primary_expr(tokens)?;
|
let lhs = self.parse_primary_expr(tokens)?;
|
||||||
|
|
||||||
if tokens.eat_token(Token::OpenParens).is_some() {
|
if tokens.eat_token(Token::OpenParens).is_some() {
|
||||||
|
@ -893,7 +980,10 @@ impl Tree {
|
||||||
/// FLOATING_CONSTANT
|
/// FLOATING_CONSTANT
|
||||||
/// ( EXPRESSION )
|
/// ( EXPRESSION )
|
||||||
/// { STATEMENT* EXPRESSION? }
|
/// { STATEMENT* EXPRESSION? }
|
||||||
pub fn parse_primary_expr(&mut self, tokens: &mut TokenIterator) -> Result<Node> {
|
pub fn parse_primary_expr(
|
||||||
|
&mut self,
|
||||||
|
tokens: &mut TokenIterator,
|
||||||
|
) -> Result<Node> {
|
||||||
let token = tokens.peek_token_or_err()?;
|
let token = tokens.peek_token_or_err()?;
|
||||||
match token.token() {
|
match token.token() {
|
||||||
Token::Ident => {
|
Token::Ident => {
|
||||||
|
@ -902,12 +992,16 @@ impl Tree {
|
||||||
let name = ident.lexeme();
|
let name = ident.lexeme();
|
||||||
if let Some(record) = self.st.find_ordered_symbol(name) {
|
if let Some(record) = self.st.find_ordered_symbol(name) {
|
||||||
Ok(self.nodes.push_tag(Tag::DeclRef(record.node())))
|
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())))
|
Ok(self.nodes.push_tag(Tag::GlobalRef(record.node())))
|
||||||
} else {
|
} else {
|
||||||
let node = self
|
let node = self
|
||||||
.st
|
.st
|
||||||
.insert_orderless_symbol(name, self.nodes.reserve_node())
|
.insert_orderless_symbol(
|
||||||
|
name,
|
||||||
|
self.nodes.reserve_node(),
|
||||||
|
)
|
||||||
.node();
|
.node();
|
||||||
|
|
||||||
Ok(self.nodes.push_tag(Tag::GlobalRef(node)))
|
Ok(self.nodes.push_tag(Tag::GlobalRef(node)))
|
||||||
|
@ -918,7 +1012,10 @@ impl Tree {
|
||||||
| Token::IntegerOctConstant
|
| Token::IntegerOctConstant
|
||||||
| Token::IntegerConstant => {
|
| Token::IntegerConstant => {
|
||||||
_ = tokens.next();
|
_ = 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();
|
let (_, bytes) = bits.to_bytes_le();
|
||||||
|
|
||||||
const BUF_SIZE: usize = core::mem::size_of::<u64>();
|
const BUF_SIZE: usize = core::mem::size_of::<u64>();
|
||||||
|
@ -927,12 +1024,14 @@ impl Tree {
|
||||||
.copy_from_slice(&bytes[..bytes.len().min(BUF_SIZE)]);
|
.copy_from_slice(&bytes[..bytes.len().min(BUF_SIZE)]);
|
||||||
let bytes = match bytes.len() {
|
let bytes = match bytes.len() {
|
||||||
0..2 => {
|
0..2 => {
|
||||||
let (buf, _) = buf.split_at(core::mem::size_of::<u32>());
|
let (buf, _) =
|
||||||
|
buf.split_at(core::mem::size_of::<u32>());
|
||||||
let dw = u32::from_le_bytes(buf.try_into().unwrap());
|
let dw = u32::from_le_bytes(buf.try_into().unwrap());
|
||||||
ImmOrIndex::U32(dw)
|
ImmOrIndex::U32(dw)
|
||||||
}
|
}
|
||||||
0..4 => {
|
0..4 => {
|
||||||
let (buf, _) = buf.split_at(core::mem::size_of::<u64>());
|
let (buf, _) =
|
||||||
|
buf.split_at(core::mem::size_of::<u64>());
|
||||||
let qw = u64::from_le_bytes(buf.try_into().unwrap());
|
let qw = u64::from_le_bytes(buf.try_into().unwrap());
|
||||||
ImmOrIndex::U64(qw)
|
ImmOrIndex::U64(qw)
|
||||||
}
|
}
|
||||||
|
@ -954,7 +1053,10 @@ impl Tree {
|
||||||
| Token::DotFloatingConstant
|
| Token::DotFloatingConstant
|
||||||
| Token::DotFloatingExpConstant => {
|
| Token::DotFloatingExpConstant => {
|
||||||
_ = tokens.next();
|
_ = 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 {
|
let bytes = match ty {
|
||||||
FloatingType::Binary32 => ImmOrIndex::U32(bits as u32),
|
FloatingType::Binary32 => ImmOrIndex::U32(bits as u32),
|
||||||
|
@ -984,7 +1086,10 @@ impl Tree {
|
||||||
/// BLOCK
|
/// BLOCK
|
||||||
/// EXPR
|
/// EXPR
|
||||||
/// EXPR ;
|
/// EXPR ;
|
||||||
pub fn parse_expr_or_stmt_or_block(&mut self, tokens: &mut TokenIterator) -> Result<Node> {
|
pub fn parse_expr_or_stmt_or_block(
|
||||||
|
&mut self,
|
||||||
|
tokens: &mut TokenIterator,
|
||||||
|
) -> Result<Node> {
|
||||||
let peek = tokens.peek_token_or_err()?;
|
let peek = tokens.peek_token_or_err()?;
|
||||||
let body = match peek.token() {
|
let body = match peek.token() {
|
||||||
// block
|
// block
|
||||||
|
@ -1015,7 +1120,10 @@ impl Tree {
|
||||||
|
|
||||||
/// ELSE_EXPR <-
|
/// ELSE_EXPR <-
|
||||||
/// 'else' (IF_EXPR | EXPR_OR_STATEMENT_OR_BLOCK)
|
/// 'else' (IF_EXPR | EXPR_OR_STATEMENT_OR_BLOCK)
|
||||||
pub fn try_parse_else_expr(&mut self, tokens: &mut TokenIterator) -> Result<Option<Node>> {
|
pub fn try_parse_else_expr(
|
||||||
|
&mut self,
|
||||||
|
tokens: &mut TokenIterator,
|
||||||
|
) -> Result<Option<Node>> {
|
||||||
if tokens.eat_token(Token::Else).is_none() {
|
if tokens.eat_token(Token::Else).is_none() {
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
}
|
}
|
||||||
|
@ -1030,7 +1138,10 @@ impl Tree {
|
||||||
|
|
||||||
/// IF_EXPR <-
|
/// IF_EXPR <-
|
||||||
/// 'if' ( EXPR ) EXPR_OR_STATEMENT_OR_BLOCK ELSE_EXPR?
|
/// 'if' ( EXPR ) EXPR_OR_STATEMENT_OR_BLOCK ELSE_EXPR?
|
||||||
pub fn try_parse_if_expr(&mut self, tokens: &mut TokenIterator) -> Result<Option<Node>> {
|
pub fn try_parse_if_expr(
|
||||||
|
&mut self,
|
||||||
|
tokens: &mut TokenIterator,
|
||||||
|
) -> Result<Option<Node>> {
|
||||||
if tokens.eat_token(Token::If).is_none() {
|
if tokens.eat_token(Token::If).is_none() {
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
}
|
}
|
||||||
|
@ -1054,7 +1165,10 @@ impl Tree {
|
||||||
|
|
||||||
/// IF_EXPR <-
|
/// IF_EXPR <-
|
||||||
/// 'if' ( EXPR ) EXPR_OR_STATEMENT_OR_BLOCK ELSE_EXPR?
|
/// 'if' ( EXPR ) EXPR_OR_STATEMENT_OR_BLOCK ELSE_EXPR?
|
||||||
pub fn parse_if_expr(&mut self, tokens: &mut TokenIterator) -> Result<Node> {
|
pub fn parse_if_expr(
|
||||||
|
&mut self,
|
||||||
|
tokens: &mut TokenIterator,
|
||||||
|
) -> Result<Node> {
|
||||||
self.try_parse_if_expr(tokens)?
|
self.try_parse_if_expr(tokens)?
|
||||||
.ok_or(Error::ExpectedTokenNotFound(Token::If))
|
.ok_or(Error::ExpectedTokenNotFound(Token::If))
|
||||||
}
|
}
|
||||||
|
@ -1146,7 +1260,9 @@ impl Tree {
|
||||||
}
|
}
|
||||||
children
|
children
|
||||||
}
|
}
|
||||||
Tag::ReturnStmt { expr } => expr.into_iter().cloned().collect::<Vec<_>>(),
|
Tag::ReturnStmt { expr } => {
|
||||||
|
expr.into_iter().cloned().collect::<Vec<_>>()
|
||||||
|
}
|
||||||
&Tag::ExprStmt { expr } => {
|
&Tag::ExprStmt { expr } => {
|
||||||
vec![expr]
|
vec![expr]
|
||||||
}
|
}
|
||||||
|
@ -1193,7 +1309,10 @@ impl Tree {
|
||||||
&Tag::ExplicitCast { lhs, typename } => {
|
&Tag::ExplicitCast { lhs, typename } => {
|
||||||
vec![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]
|
vec![*lhs]
|
||||||
}
|
}
|
||||||
Tag::Or { lhs, rhs }
|
Tag::Or { lhs, rhs }
|
||||||
|
@ -1240,8 +1359,17 @@ impl Tree {
|
||||||
if let Some(parameters) = parameters {
|
if let Some(parameters) = parameters {
|
||||||
self.render_node(writer, parameters, indent)?;
|
self.render_node(writer, parameters, indent)?;
|
||||||
}
|
}
|
||||||
write_indented!(indent, writer, "%{} = function_proto: {{", node.get())?;
|
write_indented!(
|
||||||
write!(writer, "name: \"{}\"", self.get_ident_str(name).unwrap())?;
|
indent,
|
||||||
|
writer,
|
||||||
|
"%{} = function_proto: {{",
|
||||||
|
node.get()
|
||||||
|
)?;
|
||||||
|
write!(
|
||||||
|
writer,
|
||||||
|
"name: \"{}\"",
|
||||||
|
self.get_ident_str(name).unwrap()
|
||||||
|
)?;
|
||||||
if let Some(parameters) = parameters {
|
if let Some(parameters) = parameters {
|
||||||
write!(writer, ", parameters: %{}", parameters.get())?;
|
write!(writer, ", parameters: %{}", parameters.get())?;
|
||||||
}
|
}
|
||||||
|
@ -1249,7 +1377,12 @@ impl Tree {
|
||||||
writeln!(writer, "}}")
|
writeln!(writer, "}}")
|
||||||
}
|
}
|
||||||
Tag::ParameterList { parameters } => {
|
Tag::ParameterList { parameters } => {
|
||||||
writeln_indented!(indent, writer, "%{} = ParameterList [", node.get())?;
|
writeln_indented!(
|
||||||
|
indent,
|
||||||
|
writer,
|
||||||
|
"%{} = ParameterList [",
|
||||||
|
node.get()
|
||||||
|
)?;
|
||||||
for param in parameters {
|
for param in parameters {
|
||||||
self.render_node(writer, param, indent + 1)?;
|
self.render_node(writer, param, indent + 1)?;
|
||||||
}
|
}
|
||||||
|
@ -1265,7 +1398,9 @@ impl Tree {
|
||||||
self.get_typename_str(ty).unwrap()
|
self.get_typename_str(ty).unwrap()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
Tag::Pointer { .. } | Tag::IntegralType(_) | Tag::PrimitiveType(_) => {
|
Tag::Pointer { .. }
|
||||||
|
| Tag::IntegralType(_)
|
||||||
|
| Tag::PrimitiveType(_) => {
|
||||||
writeln_indented!(
|
writeln_indented!(
|
||||||
indent,
|
indent,
|
||||||
writer,
|
writer,
|
||||||
|
@ -1322,9 +1457,20 @@ impl Tree {
|
||||||
Tag::ReturnStmt { expr } => {
|
Tag::ReturnStmt { expr } => {
|
||||||
if let Some(expr) = expr {
|
if let Some(expr) = expr {
|
||||||
self.render_node(writer, expr, indent)?;
|
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 {
|
} else {
|
||||||
writeln_indented!(indent, writer, "%{} = return;", node.get())
|
writeln_indented!(
|
||||||
|
indent,
|
||||||
|
writer,
|
||||||
|
"%{} = return;",
|
||||||
|
node.get()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Tag::ExprStmt { expr } => self.render_node(writer, expr, indent),
|
Tag::ExprStmt { expr } => self.render_node(writer, expr, indent),
|
||||||
|
@ -1335,7 +1481,8 @@ impl Tree {
|
||||||
assignment,
|
assignment,
|
||||||
} => {
|
} => {
|
||||||
self.render_node(writer, name, indent)?;
|
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));
|
assignment.map(|node| self.render_node(writer, node, indent));
|
||||||
|
|
||||||
write_indented!(
|
write_indented!(
|
||||||
|
@ -1354,7 +1501,11 @@ impl Tree {
|
||||||
self.get_ident_str(name).unwrap()
|
self.get_ident_str(name).unwrap()
|
||||||
)?;
|
)?;
|
||||||
if let Some(ty) = explicit_type {
|
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 {
|
if let Some(assignment) = assignment {
|
||||||
write!(writer, ", value: %{assignment}")?;
|
write!(writer, ", value: %{assignment}")?;
|
||||||
|
@ -1378,7 +1529,11 @@ impl Tree {
|
||||||
self.get_ident_str(name).unwrap()
|
self.get_ident_str(name).unwrap()
|
||||||
)?;
|
)?;
|
||||||
if let Some(ty) = explicit_type {
|
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}")?;
|
write!(writer, ", value: %{assignment}")?;
|
||||||
writeln!(writer, ");")?;
|
writeln!(writer, ");")?;
|
||||||
|
@ -1388,13 +1543,26 @@ impl Tree {
|
||||||
self.render_node(writer, lhs, indent)?;
|
self.render_node(writer, lhs, indent)?;
|
||||||
if let Some(rhs) = rhs {
|
if let Some(rhs) = rhs {
|
||||||
self.render_node(writer, rhs, indent)?;
|
self.render_node(writer, rhs, indent)?;
|
||||||
writeln_indented!(indent, writer, "%{node} = call (%{lhs})(%{rhs})")
|
writeln_indented!(
|
||||||
|
indent,
|
||||||
|
writer,
|
||||||
|
"%{node} = call (%{lhs})(%{rhs})"
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
writeln_indented!(indent, writer, "%{node} = call (%{lhs})()")
|
writeln_indented!(
|
||||||
|
indent,
|
||||||
|
writer,
|
||||||
|
"%{node} = call (%{lhs})()"
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Tag::ArgumentList { arguments } => {
|
Tag::ArgumentList { arguments } => {
|
||||||
writeln_indented!(indent, writer, "%{} = ArgumentList [", node.get())?;
|
writeln_indented!(
|
||||||
|
indent,
|
||||||
|
writer,
|
||||||
|
"%{} = ArgumentList [",
|
||||||
|
node.get()
|
||||||
|
)?;
|
||||||
for args in arguments {
|
for args in arguments {
|
||||||
self.render_node(writer, args, indent + 1)?;
|
self.render_node(writer, args, indent + 1)?;
|
||||||
}
|
}
|
||||||
|
@ -1410,7 +1578,12 @@ impl Tree {
|
||||||
self.get_ident_str(name).unwrap(),
|
self.get_ident_str(name).unwrap(),
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
writeln_indented!(indent, writer, "%{} = %{expr},", node.get(),)
|
writeln_indented!(
|
||||||
|
indent,
|
||||||
|
writer,
|
||||||
|
"%{} = %{expr},",
|
||||||
|
node.get(),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1427,7 +1600,13 @@ impl Tree {
|
||||||
}
|
}
|
||||||
Tag::Deref { lhs } => {
|
Tag::Deref { lhs } => {
|
||||||
self.render_node(writer, lhs, indent)?;
|
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 } => {
|
Tag::Ref { lhs } => {
|
||||||
self.render_node(writer, lhs, indent)?;
|
self.render_node(writer, lhs, indent)?;
|
||||||
|
@ -1445,7 +1624,13 @@ impl Tree {
|
||||||
}
|
}
|
||||||
Tag::Negate { lhs } => {
|
Tag::Negate { lhs } => {
|
||||||
self.render_node(writer, lhs, indent)?;
|
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 } => {
|
Tag::Or { lhs, rhs } => {
|
||||||
self.render_node(writer, lhs, indent)?;
|
self.render_node(writer, lhs, indent)?;
|
||||||
|
@ -1753,7 +1938,10 @@ impl Tree {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn render<W: core::fmt::Write>(&mut self, writer: &mut W) -> core::fmt::Result {
|
pub fn render<W: core::fmt::Write>(
|
||||||
|
&mut self,
|
||||||
|
writer: &mut W,
|
||||||
|
) -> core::fmt::Result {
|
||||||
for decl in &self.global_decls.clone() {
|
for decl in &self.global_decls.clone() {
|
||||||
self.render_node(writer, *decl, 0)?;
|
self.render_node(writer, *decl, 0)?;
|
||||||
}
|
}
|
||||||
|
@ -1851,7 +2039,9 @@ impl Tree {
|
||||||
(Some(a), b) => self.peer_type_of_nodes(*a, *b).expect({
|
(Some(a), b) => self.peer_type_of_nodes(*a, *b).expect({
|
||||||
let at = self.type_of_node(*a);
|
let at = self.type_of_node(*a);
|
||||||
let bt = self.type_of_node(*b);
|
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
|
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::ExplicitCast { typename, .. } => self.type_of_node(*typename),
|
||||||
Tag::Deref { lhs } => self.type_of_node(*lhs).remove_ptr().unwrap(),
|
Tag::Deref { lhs } => self.type_of_node(*lhs).remove_ptr().unwrap(),
|
||||||
Tag::Ref { lhs } => self.type_of_node(*lhs).into_ptr(),
|
Tag::Ref { lhs } => self.type_of_node(*lhs).into_ptr(),
|
||||||
|
@ -1892,11 +2084,15 @@ impl Tree {
|
||||||
| Tag::And { lhs, rhs }
|
| Tag::And { lhs, rhs }
|
||||||
| Tag::BitOr { lhs, rhs }
|
| Tag::BitOr { lhs, rhs }
|
||||||
| Tag::BitAnd { lhs, rhs }
|
| Tag::BitAnd { lhs, rhs }
|
||||||
| Tag::BitXOr { lhs, rhs } => self.peer_type_of_nodes(*lhs, *rhs).expect({
|
| Tag::BitXOr { lhs, rhs } => {
|
||||||
|
self.peer_type_of_nodes(*lhs, *rhs).expect({
|
||||||
let at = self.type_of_node(*lhs);
|
let at = self.type_of_node(*lhs);
|
||||||
let bt = self.type_of_node(*rhs);
|
let bt = self.type_of_node(*rhs);
|
||||||
&format!("incompatible types for %{lhs}({at}) and %{rhs}({bt})")
|
&format!(
|
||||||
}),
|
"incompatible types for %{lhs}({at}) and %{rhs}({bt})"
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
Tag::Shl { lhs, .. } => self.type_of_node(*lhs),
|
Tag::Shl { lhs, .. } => self.type_of_node(*lhs),
|
||||||
Tag::Shr { lhs, .. } => self.type_of_node(*lhs),
|
Tag::Shr { lhs, .. } => self.type_of_node(*lhs),
|
||||||
Tag::Eq { .. } => Type::bool(),
|
Tag::Eq { .. } => Type::bool(),
|
||||||
|
@ -1970,7 +2166,9 @@ impl Tree {
|
||||||
|
|
||||||
is_comptime
|
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::Or { lhs, rhs }
|
||||||
| Tag::And { lhs, rhs }
|
| Tag::And { lhs, rhs }
|
||||||
| Tag::BitOr { lhs, rhs }
|
| Tag::BitOr { lhs, rhs }
|
||||||
|
@ -1989,7 +2187,8 @@ impl Tree {
|
||||||
| Tag::Mul { lhs, rhs }
|
| Tag::Mul { lhs, rhs }
|
||||||
| Tag::Rem { lhs, rhs }
|
| Tag::Rem { lhs, rhs }
|
||||||
| Tag::Div { 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,
|
_ => false,
|
||||||
}
|
}
|
||||||
|
@ -2008,11 +2207,15 @@ impl Tree {
|
||||||
let number: ComptimeNumber = match ty {
|
let number: ComptimeNumber = match ty {
|
||||||
Type::Bool => (bytes[0] != 0).into(),
|
Type::Bool => (bytes[0] != 0).into(),
|
||||||
Type::ComptimeNumber => {
|
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) => {
|
Type::Integer(ty) => {
|
||||||
if bytes.len() > core::mem::size_of::<u128>() {
|
if bytes.len() > core::mem::size_of::<u128>() {
|
||||||
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()
|
(bits, *ty).into()
|
||||||
} else {
|
} else {
|
||||||
let mut buf = [0u8; core::mem::size_of::<u128>()];
|
let mut buf = [0u8; core::mem::size_of::<u128>()];
|
||||||
|
@ -2022,12 +2225,14 @@ impl Tree {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Type::Floating(ty) => match ty {
|
Type::Floating(ty) => match ty {
|
||||||
FloatingType::Binary32 => {
|
FloatingType::Binary32 => (f32::from_le_bytes(
|
||||||
(f32::from_le_bytes((&bytes[..4]).try_into().unwrap())).into()
|
(&bytes[..4]).try_into().unwrap(),
|
||||||
}
|
))
|
||||||
FloatingType::Binary64 => {
|
.into(),
|
||||||
(f64::from_le_bytes((&bytes[..8]).try_into().unwrap())).into()
|
FloatingType::Binary64 => (f64::from_le_bytes(
|
||||||
}
|
(&bytes[..8]).try_into().unwrap(),
|
||||||
|
))
|
||||||
|
.into(),
|
||||||
},
|
},
|
||||||
_ => unimplemented!(),
|
_ => unimplemented!(),
|
||||||
};
|
};
|
||||||
|
@ -2098,26 +2303,33 @@ impl Tree {
|
||||||
let number: ComptimeNumber = match ty {
|
let number: ComptimeNumber = match ty {
|
||||||
Type::Bool => (bytes[0] != 0).into(),
|
Type::Bool => (bytes[0] != 0).into(),
|
||||||
Type::ComptimeNumber => {
|
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) => {
|
Type::Integer(ty) => {
|
||||||
if bytes.len() > core::mem::size_of::<u128>() {
|
if bytes.len() > core::mem::size_of::<u128>() {
|
||||||
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()
|
(bits, *ty).into()
|
||||||
} else {
|
} else {
|
||||||
let mut buf = [0u8; core::mem::size_of::<u128>()];
|
let mut buf =
|
||||||
|
[0u8; core::mem::size_of::<u128>()];
|
||||||
buf[..bytes.len()].copy_from_slice(bytes);
|
buf[..bytes.len()].copy_from_slice(bytes);
|
||||||
let bits = u128::from_le_bytes(buf);
|
let bits = u128::from_le_bytes(buf);
|
||||||
(bits, *ty).into()
|
(bits, *ty).into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Type::Floating(ty) => match ty {
|
Type::Floating(ty) => match ty {
|
||||||
FloatingType::Binary32 => {
|
FloatingType::Binary32 => (f32::from_le_bytes(
|
||||||
(f32::from_le_bytes((&bytes[..4]).try_into().unwrap())).into()
|
(&bytes[..4]).try_into().unwrap(),
|
||||||
}
|
))
|
||||||
FloatingType::Binary64 => {
|
.into(),
|
||||||
(f64::from_le_bytes((&bytes[..8]).try_into().unwrap())).into()
|
FloatingType::Binary64 => (f64::from_le_bytes(
|
||||||
}
|
(&bytes[..8]).try_into().unwrap(),
|
||||||
|
))
|
||||||
|
.into(),
|
||||||
},
|
},
|
||||||
_ => unimplemented!(),
|
_ => unimplemented!(),
|
||||||
};
|
};
|
||||||
|
@ -2337,7 +2549,8 @@ impl Tree {
|
||||||
match self.nodes[node].clone() {
|
match self.nodes[node].clone() {
|
||||||
Tag::FunctionProto { .. } => {}
|
Tag::FunctionProto { .. } => {}
|
||||||
Tag::FunctionDecl { proto, body } => {
|
Tag::FunctionDecl { proto, body } => {
|
||||||
let Tag::FunctionProto { return_type, .. } = self.nodes[proto] else {
|
let Tag::FunctionProto { return_type, .. } = self.nodes[proto]
|
||||||
|
else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2346,7 +2559,8 @@ impl Tree {
|
||||||
|
|
||||||
if let Some(peer_t) = body_t.equal_type(&ret_t) {
|
if let Some(peer_t) = body_t.equal_type(&ret_t) {
|
||||||
if body_t == Type::comptime_number() {
|
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!()
|
unreachable!()
|
||||||
};
|
};
|
||||||
if let Some(expr) = trailing_expr {
|
if let Some(expr) = trailing_expr {
|
||||||
|
@ -2360,7 +2574,9 @@ impl Tree {
|
||||||
typename: ty,
|
typename: ty,
|
||||||
});
|
});
|
||||||
|
|
||||||
let Tag::Block { trailing_expr, .. } = &mut self.nodes[body] else {
|
let Tag::Block { trailing_expr, .. } =
|
||||||
|
&mut self.nodes[body]
|
||||||
|
else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
};
|
};
|
||||||
*trailing_expr = Some(expr)
|
*trailing_expr = Some(expr)
|
||||||
|
@ -2376,7 +2592,10 @@ impl Tree {
|
||||||
let bits = self.strings.count_bits(bytes);
|
let bits = self.strings.count_bits(bytes);
|
||||||
if bits < ty.bit_width() as u32 {
|
if bits < ty.bit_width() as u32 {
|
||||||
errors.push(AnalysisError::new(
|
errors.push(AnalysisError::new(
|
||||||
AnalysisErrorTag::InsufficientBitsInTypeForConstant(bits, ty.clone()),
|
AnalysisErrorTag::InsufficientBitsInTypeForConstant(
|
||||||
|
bits,
|
||||||
|
ty.clone(),
|
||||||
|
),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,7 +55,10 @@ impl StringTable {
|
||||||
ImmOrIndex::Index(idx) => {
|
ImmOrIndex::Index(idx) => {
|
||||||
let bytes = self.get_bytes(idx);
|
let bytes = self.get_bytes(idx);
|
||||||
let ints = unsafe {
|
let ints = unsafe {
|
||||||
core::slice::from_raw_parts(bytes.as_ptr().cast::<u32>(), bytes.len() / 4)
|
core::slice::from_raw_parts(
|
||||||
|
bytes.as_ptr().cast::<u32>(),
|
||||||
|
bytes.len() / 4,
|
||||||
|
)
|
||||||
};
|
};
|
||||||
bigint::count_bits(ints) as u32
|
bigint::count_bits(ints) as u32
|
||||||
}
|
}
|
||||||
|
@ -117,7 +120,10 @@ mod display {
|
||||||
str: Option<&'a str>,
|
str: Option<&'a str>,
|
||||||
}
|
}
|
||||||
impl<'a> Debug for Test<'a> {
|
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)?;
|
write!(f, "{{ bytes: {:x?}", self.bytes)?;
|
||||||
if let Some(str) = self.str {
|
if let Some(str) = self.str {
|
||||||
write!(f, ", str: {}", str)?;
|
write!(f, ", str: {}", str)?;
|
||||||
|
|
|
@ -35,13 +35,25 @@ impl SymbolPath {
|
||||||
for node in self.0.iter().skip(1).rev() {
|
for node in self.0.iter().skip(1).rev() {
|
||||||
match tree.nodes.get_node(node.unwrap()) {
|
match tree.nodes.get_node(node.unwrap()) {
|
||||||
Tag::VarDecl { name, .. } => {
|
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, .. } => {
|
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, .. } => {
|
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 {
|
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 {
|
match kind {
|
||||||
SymbolKind::Var => {
|
SymbolKind::Var => {
|
||||||
self.ordered_identifiers.push(SymbolRecord {
|
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(
|
self.orderless_identifiers.insert(
|
||||||
name.to_owned(),
|
name.to_owned(),
|
||||||
SymbolRecord {
|
SymbolRecord {
|
||||||
|
@ -154,7 +175,11 @@ impl InnerSymbolTable {
|
||||||
self.orderless_identifiers.get(name).unwrap()
|
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
|
where
|
||||||
F: FnOnce() -> (AstNode, SymbolKind),
|
F: FnOnce() -> (AstNode, SymbolKind),
|
||||||
{
|
{
|
||||||
|
@ -177,7 +202,9 @@ impl InnerSymbolTable {
|
||||||
.find(|(_, v)| v.decl == decl)
|
.find(|(_, v)| v.decl == decl)
|
||||||
.map(|(_, v)| v)
|
.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> {
|
fn find_any_symbol(&self, name: &str) -> Option<&SymbolRecord> {
|
||||||
|
@ -192,7 +219,9 @@ impl InnerSymbolTable {
|
||||||
self.ordered_identifiers
|
self.ordered_identifiers
|
||||||
.iter()
|
.iter()
|
||||||
.find(|r| r.name.as_str() == name)
|
.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> {
|
fn find_orderless_symbol(&self, name: &str) -> Option<&SymbolRecord> {
|
||||||
|
@ -286,7 +315,12 @@ impl SymbolTableWrapper {
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
self.current_mut().insert_symbol(name, node, kind)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -294,15 +328,27 @@ impl SymbolTableWrapper {
|
||||||
self.root_mut().find_orderless_symbol(name)
|
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)
|
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)
|
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
|
where
|
||||||
F: FnOnce() -> (AstNode, SymbolKind),
|
F: FnOnce() -> (AstNode, SymbolKind),
|
||||||
{
|
{
|
||||||
|
@ -480,7 +526,9 @@ pub mod syms2 {
|
||||||
}
|
}
|
||||||
let entries = self.inner.iter().map(|(key, val)| {
|
let entries = self.inner.iter().map(|(key, val)| {
|
||||||
let payload = match key {
|
let payload = match key {
|
||||||
Key::ScopeByIndex { .. } => ExpandedPayload::Intern(val.as_intern()),
|
Key::ScopeByIndex { .. } => {
|
||||||
|
ExpandedPayload::Intern(val.as_intern())
|
||||||
|
}
|
||||||
_ => ExpandedPayload::Ast(val.as_ast()),
|
_ => ExpandedPayload::Ast(val.as_ast()),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -589,8 +637,10 @@ pub mod syms2 {
|
||||||
kind: SymbolKind,
|
kind: SymbolKind,
|
||||||
ast: AstIndex,
|
ast: AstIndex,
|
||||||
) {
|
) {
|
||||||
self.inner
|
self.inner.insert(
|
||||||
.insert(Key::Symbol { scope, name, kind }, Payload::new_ast(ast));
|
Key::Symbol { scope, name, kind },
|
||||||
|
Payload::new_ast(ast),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
483
src/triples.rs
483
src/triples.rs
|
@ -38,7 +38,9 @@ impl Into<mir::Type> for Type2 {
|
||||||
impl Type2 {
|
impl Type2 {
|
||||||
fn mir_type(self) -> mir::Type {
|
fn mir_type(self) -> mir::Type {
|
||||||
match self {
|
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::Binary32 => mir::Type::SinglePrecision,
|
||||||
Type2::Binary64 => mir::Type::DoublePrecision,
|
Type2::Binary64 => mir::Type::DoublePrecision,
|
||||||
Type2::Bool => mir::Type::from_bitsize_int(1),
|
Type2::Bool => mir::Type::from_bitsize_int(1),
|
||||||
|
@ -94,7 +96,9 @@ impl Type2 {
|
||||||
impl core::fmt::Display for Type2 {
|
impl core::fmt::Display for Type2 {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
match self {
|
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::Binary32 => write!(f, "f32"),
|
||||||
Type2::Binary64 => write!(f, "f64"),
|
Type2::Binary64 => write!(f, "f64"),
|
||||||
Type2::Bool => write!(f, "bool"),
|
Type2::Bool => write!(f, "bool"),
|
||||||
|
@ -121,7 +125,9 @@ impl From<&Type> for Type2 {
|
||||||
Type::Pointer { .. } => Type2::Pointer,
|
Type::Pointer { .. } => Type2::Pointer,
|
||||||
Type::Fn { .. } => 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 {
|
impl Inst {
|
||||||
fn is_constant(self) -> bool {
|
fn is_constant(self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
Inst::ConstantU32 | Inst::ConstantU64 | Inst::ConstantMultiByte => true,
|
Inst::ConstantU32 | Inst::ConstantU64 | Inst::ConstantMultiByte => {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
|
@ -357,23 +365,30 @@ impl<'tree, 'ir> IRBuilder<'tree, 'ir> {
|
||||||
);
|
);
|
||||||
|
|
||||||
self.ir.push(Inst::FunctionStart, {
|
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())
|
Some((*name).into())
|
||||||
});
|
});
|
||||||
|
|
||||||
if let Some(parameters) = parameters {
|
if let Some(parameters) = parameters {
|
||||||
variant!(
|
variant!(
|
||||||
Tag::ParameterList { parameters } = self.tree.nodes.get_node(*parameters)
|
Tag::ParameterList { parameters } =
|
||||||
|
self.tree.nodes.get_node(*parameters)
|
||||||
);
|
);
|
||||||
|
|
||||||
for param in 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 ty = self.tree.type_of_node(*ty);
|
||||||
let size = ty.size_of();
|
let size = ty.size_of();
|
||||||
let align = ty.align_of();
|
let align = ty.align_of();
|
||||||
let ir = self
|
let ir = self.ir.push(
|
||||||
.ir
|
Inst::Parameter(ty.into()),
|
||||||
.push(Inst::Parameter(ty.into()), Some(Data::new(size, align)));
|
Some(Data::new(size, align)),
|
||||||
|
);
|
||||||
|
|
||||||
self.lookup.insert(*param, NodeOrList::Node(ir));
|
self.lookup.insert(*param, NodeOrList::Node(ir));
|
||||||
}
|
}
|
||||||
|
@ -384,16 +399,18 @@ impl<'tree, 'ir> IRBuilder<'tree, 'ir> {
|
||||||
self.tree.st.into_parent();
|
self.tree.st.into_parent();
|
||||||
if value != !0 {
|
if value != !0 {
|
||||||
let ty = self.tree.type_of_node(*body);
|
let ty = self.tree.type_of_node(*body);
|
||||||
self.ir
|
self.ir.push(
|
||||||
.push(Inst::ReturnValue(ty.into()), Some(Data::lhs(value)));
|
Inst::ReturnValue(ty.into()),
|
||||||
|
Some(Data::lhs(value)),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.ir.push(Inst::FunctionEnd, None)
|
self.ir.push(Inst::FunctionEnd, None)
|
||||||
}
|
}
|
||||||
Tag::CallExpr { lhs, rhs } => {
|
Tag::CallExpr { lhs, rhs } => {
|
||||||
let ty = self.tree.type_of_node(*lhs).return_type().unwrap().clone();
|
let ty =
|
||||||
let args =
|
self.tree.type_of_node(*lhs).return_type().unwrap().clone();
|
||||||
if let Some(args) = *rhs {
|
let args = if let Some(args) = *rhs {
|
||||||
variant!(
|
variant!(
|
||||||
self.tree.nodes.get_node(args) => Tag::ArgumentList { arguments }
|
self.tree.nodes.get_node(args) => Tag::ArgumentList { arguments }
|
||||||
);
|
);
|
||||||
|
@ -405,9 +422,10 @@ impl<'tree, 'ir> IRBuilder<'tree, 'ir> {
|
||||||
|
|
||||||
let start = self.ir.nodes.len();
|
let start = self.ir.nodes.len();
|
||||||
for (arg, ty) in args {
|
for (arg, ty) in args {
|
||||||
_ = self
|
_ = self.ir.push(
|
||||||
.ir
|
Inst::Argument(ty.into()),
|
||||||
.push(Inst::Argument(ty.into()), Some(Data::lhs(arg)));
|
Some(Data::lhs(arg)),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
let end = self.ir.nodes.len();
|
let end = self.ir.nodes.len();
|
||||||
|
|
||||||
|
@ -415,8 +433,10 @@ impl<'tree, 'ir> IRBuilder<'tree, 'ir> {
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
let (start, end) =
|
let (start, end) = args.unwrap_or((
|
||||||
args.unwrap_or((self.ir.nodes.len() as u32, self.ir.nodes.len() as u32));
|
self.ir.nodes.len() as u32,
|
||||||
|
self.ir.nodes.len() as u32,
|
||||||
|
));
|
||||||
self.ir.push(Inst::InlineType(ty.into()), None);
|
self.ir.push(Inst::InlineType(ty.into()), None);
|
||||||
|
|
||||||
let func = self.visit(*lhs);
|
let func = self.visit(*lhs);
|
||||||
|
@ -440,16 +460,18 @@ impl<'tree, 'ir> IRBuilder<'tree, 'ir> {
|
||||||
}
|
}
|
||||||
Tag::VarDecl { assignment, .. } => {
|
Tag::VarDecl { assignment, .. } => {
|
||||||
let ty = self.tree.type_of_node(node);
|
let ty = self.tree.type_of_node(node);
|
||||||
let alloca = self
|
let alloca = self.ir.push(
|
||||||
.ir
|
Inst::Alloca,
|
||||||
.push(Inst::Alloca, Some(Data::new(ty.size_of(), ty.align_of())));
|
Some(Data::new(ty.size_of(), ty.align_of())),
|
||||||
|
);
|
||||||
|
|
||||||
if let Some(assignment) = assignment {
|
if let Some(assignment) = assignment {
|
||||||
let value = self.visit(*assignment);
|
let value = self.visit(*assignment);
|
||||||
// discard store
|
// discard store
|
||||||
let _ = self
|
let _ = self.ir.push(
|
||||||
.ir
|
Inst::Store(ty.into()),
|
||||||
.push(Inst::Store(ty.into()), Some(Data::new(value, alloca)));
|
Some(Data::new(value, alloca)),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
self.lookup.insert(node, NodeOrList::Node(alloca));
|
self.lookup.insert(node, NodeOrList::Node(alloca));
|
||||||
alloca
|
alloca
|
||||||
|
@ -474,9 +496,10 @@ impl<'tree, 'ir> IRBuilder<'tree, 'ir> {
|
||||||
}
|
}
|
||||||
Tag::GlobalRef(decl) => {
|
Tag::GlobalRef(decl) => {
|
||||||
let ty = self.tree.type_of_node(*decl);
|
let ty = self.tree.type_of_node(*decl);
|
||||||
let node = self
|
let node = self.ir.push(
|
||||||
.ir
|
Inst::ExternRef(ty.into()),
|
||||||
.push(Inst::ExternRef(ty.into()), Some(Data::lhs(decl.get())));
|
Some(Data::lhs(decl.get())),
|
||||||
|
);
|
||||||
self.fixup.push(node);
|
self.fixup.push(node);
|
||||||
node
|
node
|
||||||
}
|
}
|
||||||
|
@ -500,15 +523,18 @@ impl<'tree, 'ir> IRBuilder<'tree, 'ir> {
|
||||||
if let Some(expr) = expr {
|
if let Some(expr) = expr {
|
||||||
let ty = self.tree.type_of_node(*expr);
|
let ty = self.tree.type_of_node(*expr);
|
||||||
let expr = self.visit(*expr);
|
let expr = self.visit(*expr);
|
||||||
self.ir
|
self.ir.push(
|
||||||
.push(Inst::ReturnValue(ty.into()), Some(Data::lhs(expr)))
|
Inst::ReturnValue(ty.into()),
|
||||||
|
Some(Data::lhs(expr)),
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
self.ir.push(Inst::Return, None)
|
self.ir.push(Inst::Return, None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Tag::ExprStmt { expr } => self.visit(*expr),
|
Tag::ExprStmt { expr } => self.visit(*expr),
|
||||||
Tag::Deref { lhs } => {
|
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);
|
let lhs = self.visit(*lhs);
|
||||||
self.ir.push(Inst::Load(ty.into()), Some(Data::lhs(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 ty = self.tree.type_of_node(node);
|
||||||
let lhs = self.visit(*lhs);
|
let lhs = self.visit(*lhs);
|
||||||
let rhs = self.visit(*rhs);
|
let rhs = self.visit(*rhs);
|
||||||
self.ir
|
self.ir.push(
|
||||||
.push(Inst::ShiftRight(ty.into()), Some(Data::new(lhs, rhs)))
|
Inst::ShiftRight(ty.into()),
|
||||||
|
Some(Data::new(lhs, rhs)),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
Tag::Ref { lhs } => {
|
Tag::Ref { lhs } => {
|
||||||
let ty = self.tree.type_of_node(*lhs);
|
let ty = self.tree.type_of_node(*lhs);
|
||||||
let lhs = self.visit(*lhs);
|
let lhs = self.visit(*lhs);
|
||||||
// self.ir.push(Inst::Load(ty.into()), Some(Data::lhs(lhs)))
|
// self.ir.push(Inst::Load(ty.into()), Some(Data::lhs(lhs)))
|
||||||
// nothing happens here because lhs is of type pointer
|
// nothing happens here because lhs is of type pointer
|
||||||
self.ir
|
self.ir.push(
|
||||||
.push(Inst::GetElementPtr(ty.into()), Some(Data::new(lhs, 0)))
|
Inst::GetElementPtr(ty.into()),
|
||||||
|
Some(Data::new(lhs, 0)),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
Tag::Constant { bytes, .. } => match bytes {
|
Tag::Constant { bytes, .. } => match bytes {
|
||||||
ImmOrIndex::U64(v) => self.ir.push(Inst::ConstantU64, Some((*v).into())),
|
ImmOrIndex::U64(v) => {
|
||||||
ImmOrIndex::U32(v) => self.ir.push(Inst::ConstantU32, Some((*v).into())),
|
self.ir.push(Inst::ConstantU64, Some((*v).into()))
|
||||||
|
}
|
||||||
|
ImmOrIndex::U32(v) => {
|
||||||
|
self.ir.push(Inst::ConstantU32, Some((*v).into()))
|
||||||
|
}
|
||||||
ImmOrIndex::Index(idx) => {
|
ImmOrIndex::Index(idx) => {
|
||||||
self.ir.push(Inst::ConstantMultiByte, Some((*idx).into()))
|
self.ir.push(Inst::ConstantMultiByte, Some((*idx).into()))
|
||||||
}
|
}
|
||||||
|
@ -645,10 +679,14 @@ impl<'tree, 'ir> IRBuilder<'tree, 'ir> {
|
||||||
let condition = self.visit(*condition);
|
let condition = self.visit(*condition);
|
||||||
let br = self.ir.push(Inst::Branch(condition), None);
|
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 _ = self.visit(*body);
|
||||||
let jmp = self.ir.push(Inst::Jump, None);
|
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[br as usize] = Some(Data::new(label_lhs, nojump));
|
||||||
self.ir.data[jmp as usize] = Some(Data::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 condition = self.visit(*condition);
|
||||||
let br = self.ir.push(Inst::Branch(condition), None);
|
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 lhs = self.visit(*body);
|
||||||
let ljmp = self.ir.push(Inst::Jump, None);
|
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 rhs = self.visit(*else_expr);
|
||||||
let rjmp = self.ir.push(Inst::Jump, None);
|
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) {
|
let phi = if let Some(ty) = Type2::try_from_ast_type(&ty) {
|
||||||
self.ir.push(Inst::Phi2(ty), Some(Data::new(lhs, rhs)))
|
self.ir.push(Inst::Phi2(ty), Some(Data::new(lhs, rhs)))
|
||||||
} else {
|
} else {
|
||||||
br
|
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[ljmp as usize] = Some(Data::lhs(nojump));
|
||||||
self.ir.data[rjmp as usize] = Some(Data::lhs(nojump));
|
self.ir.data[rjmp as usize] = Some(Data::lhs(nojump));
|
||||||
phi
|
phi
|
||||||
|
@ -712,7 +757,10 @@ impl IR {
|
||||||
node
|
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 global_decls = tree.global_decls.clone();
|
||||||
let mut builder = IRBuilder::new(self, tree);
|
let mut builder = IRBuilder::new(self, tree);
|
||||||
|
|
||||||
|
@ -723,7 +771,11 @@ impl IR {
|
||||||
for &fix in builder.fixup.iter() {
|
for &fix in builder.fixup.iter() {
|
||||||
let ast_node = builder.ir.data[fix as usize].unwrap().lhs;
|
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, .. } => {
|
Tag::FunctionDecl { proto, .. } => {
|
||||||
variant!(builder.tree.nodes.get_node(*proto) => Tag::FunctionProto { name,..});
|
variant!(builder.tree.nodes.get_node(*proto) => Tag::FunctionProto { name,..});
|
||||||
variant!(builder.tree.nodes.get_node(*name) => Tag::Ident { name });
|
variant!(builder.tree.nodes.get_node(*name) => Tag::Ident { name });
|
||||||
|
@ -758,7 +810,12 @@ impl<'tree, 'ir> IRBuilder<'tree, 'ir> {
|
||||||
match inst {
|
match inst {
|
||||||
Inst::Label => {
|
Inst::Label => {
|
||||||
let label = self.tree.strings.get_str(data.as_index());
|
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 => {
|
Inst::FunctionStart => {
|
||||||
let label = self.tree.strings.get_str(data.as_index());
|
let label = self.tree.strings.get_str(data.as_index());
|
||||||
|
@ -798,59 +855,158 @@ impl<'tree, 'ir> IRBuilder<'tree, 'ir> {
|
||||||
writeln_indented!(indent, w, ")")?;
|
writeln_indented!(indent, w, ")")?;
|
||||||
}
|
}
|
||||||
Inst::ConstantU32 => {
|
Inst::ConstantU32 => {
|
||||||
writeln_indented!(indent, w, "%{} = const i32 {}", node, data.as_u32())?;
|
writeln_indented!(
|
||||||
|
indent,
|
||||||
|
w,
|
||||||
|
"%{} = const i32 {}",
|
||||||
|
node,
|
||||||
|
data.as_u32()
|
||||||
|
)?;
|
||||||
}
|
}
|
||||||
Inst::ConstantU64 => {
|
Inst::ConstantU64 => {
|
||||||
writeln_indented!(indent, w, "%{} = const i64 {}", node, data.as_u64())?;
|
writeln_indented!(
|
||||||
|
indent,
|
||||||
|
w,
|
||||||
|
"%{} = const i64 {}",
|
||||||
|
node,
|
||||||
|
data.as_u64()
|
||||||
|
)?;
|
||||||
}
|
}
|
||||||
Inst::ConstantMultiByte => {
|
Inst::ConstantMultiByte => {
|
||||||
let value = self.tree.strings.get_bytes(data.as_index());
|
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) => {
|
Inst::Add(ty) => {
|
||||||
let (lhs, rhs) = data.as_lhs_rhs();
|
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) => {
|
Inst::Sub(ty) => {
|
||||||
let (lhs, rhs) = data.as_lhs_rhs();
|
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) => {
|
Inst::Eq(ty) => {
|
||||||
let (lhs, rhs) = data.as_lhs_rhs();
|
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) => {
|
Inst::Neq(ty) => {
|
||||||
let (lhs, rhs) = data.as_lhs_rhs();
|
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) => {
|
Inst::Gt(ty) => {
|
||||||
let (lhs, rhs) = data.as_lhs_rhs();
|
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) => {
|
Inst::Lt(ty) => {
|
||||||
let (lhs, rhs) = data.as_lhs_rhs();
|
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) => {
|
Inst::Ge(ty) => {
|
||||||
let (lhs, rhs) = data.as_lhs_rhs();
|
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) => {
|
Inst::Le(ty) => {
|
||||||
let (lhs, rhs) = data.as_lhs_rhs();
|
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) => {
|
Inst::Mul(ty) => {
|
||||||
let (lhs, rhs) = data.as_lhs_rhs();
|
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) => {
|
Inst::Negate(ty) => {
|
||||||
writeln_indented!(indent, w, "%{} = negate_{ty}(%{})", node, data.lhs)?;
|
writeln_indented!(
|
||||||
|
indent,
|
||||||
|
w,
|
||||||
|
"%{} = negate_{ty}(%{})",
|
||||||
|
node,
|
||||||
|
data.lhs
|
||||||
|
)?;
|
||||||
}
|
}
|
||||||
Inst::Not(ty) => {
|
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) => {
|
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) => {
|
Inst::ShiftLeft(ty) => {
|
||||||
writeln_indented!(
|
writeln_indented!(
|
||||||
|
@ -873,14 +1029,25 @@ impl<'tree, 'ir> IRBuilder<'tree, 'ir> {
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
Inst::ReturnValue(ty) => {
|
Inst::ReturnValue(ty) => {
|
||||||
writeln_indented!(indent, w, "%{} = return {ty} %{}", node, data.lhs)?;
|
writeln_indented!(
|
||||||
|
indent,
|
||||||
|
w,
|
||||||
|
"%{} = return {ty} %{}",
|
||||||
|
node,
|
||||||
|
data.lhs
|
||||||
|
)?;
|
||||||
}
|
}
|
||||||
Inst::Return => {
|
Inst::Return => {
|
||||||
writeln_indented!(indent, w, "%{} = return", node)?;
|
writeln_indented!(indent, w, "%{} = return", node)?;
|
||||||
}
|
}
|
||||||
Inst::Alloca => {
|
Inst::Alloca => {
|
||||||
let (size, align) = data.as_lhs_rhs();
|
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) => {
|
Inst::GetElementPtr(ty) => {
|
||||||
let (ptr, idx) = data.as_lhs_rhs();
|
let (ptr, idx) = data.as_lhs_rhs();
|
||||||
|
@ -894,11 +1061,21 @@ impl<'tree, 'ir> IRBuilder<'tree, 'ir> {
|
||||||
}
|
}
|
||||||
Inst::Load(ty) => {
|
Inst::Load(ty) => {
|
||||||
let source = data.lhs;
|
let source = data.lhs;
|
||||||
writeln_indented!(indent, w, "%{} = load {ty}, %{source}", node)?;
|
writeln_indented!(
|
||||||
|
indent,
|
||||||
|
w,
|
||||||
|
"%{} = load {ty}, %{source}",
|
||||||
|
node
|
||||||
|
)?;
|
||||||
}
|
}
|
||||||
Inst::Store(ty) => {
|
Inst::Store(ty) => {
|
||||||
let (src, dst) = data.as_lhs_rhs();
|
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) => {
|
Inst::ExternRef(ty) => {
|
||||||
let idx = data.as_index();
|
let idx = data.as_index();
|
||||||
|
@ -923,12 +1100,20 @@ impl<'tree, 'ir> IRBuilder<'tree, 'ir> {
|
||||||
}
|
}
|
||||||
Inst::Phi2(ty) => {
|
Inst::Phi2(ty) => {
|
||||||
let (lhs, rhs) = data.as_lhs_rhs();
|
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) => {
|
Inst::GlobalConstant(name, ty) => {
|
||||||
let label = self.tree.strings.get_str(name);
|
let label = self.tree.strings.get_str(name);
|
||||||
let value = data.lhs;
|
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")
|
unimplemented!("{inst:?} rendering unimplemented")
|
||||||
|
@ -1000,8 +1185,11 @@ impl<'a> IrToMirMapping<'a> {
|
||||||
|
|
||||||
match self.ir.nodes[ir as usize] {
|
match self.ir.nodes[ir as usize] {
|
||||||
Inst::GlobalConstant(name, ty) => {
|
Inst::GlobalConstant(name, ty) => {
|
||||||
eprintln!("does this even get hit anymore???????????????????//");
|
eprintln!(
|
||||||
let ext = mir::NodeRef(mir.gen_extern(Some(ty.mir_type()), name));
|
"does this even get hit anymore???????????????????//"
|
||||||
|
);
|
||||||
|
let ext =
|
||||||
|
mir::NodeRef(mir.gen_extern(Some(ty.mir_type()), name));
|
||||||
self.insert(ir, ext);
|
self.insert(ir, ext);
|
||||||
Some(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 {
|
loop {
|
||||||
let ir_node = self.ir.node();
|
let ir_node = self.ir.node();
|
||||||
|
@ -1062,14 +1251,18 @@ impl<'a> MirBuilder<'a> {
|
||||||
let range = unresolved_jumps_branches
|
let range = unresolved_jumps_branches
|
||||||
.range(
|
.range(
|
||||||
(ir_node, LeftRight::Left(mir::NodeRef::MIN))
|
(ir_node, LeftRight::Left(mir::NodeRef::MIN))
|
||||||
..=(ir_node, LeftRight::Right(mir::NodeRef::MAX)),
|
..=(
|
||||||
|
ir_node,
|
||||||
|
LeftRight::Right(mir::NodeRef::MAX),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
.map(|(_, n)| n)
|
.map(|(_, n)| n)
|
||||||
.cloned()
|
.cloned()
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
for unresolved in range {
|
for unresolved in range {
|
||||||
unresolved_jumps_branches.remove(&(ir_node, unresolved));
|
unresolved_jumps_branches
|
||||||
|
.remove(&(ir_node, unresolved));
|
||||||
|
|
||||||
let mir_node = unresolved.noderef();
|
let mir_node = unresolved.noderef();
|
||||||
let (inst, data) = mir.get_node_mut(mir_node);
|
let (inst, data) = mir.get_node_mut(mir_node);
|
||||||
|
@ -1082,8 +1275,12 @@ impl<'a> MirBuilder<'a> {
|
||||||
let (lhs, rhs) = data.as_binary_noderefs();
|
let (lhs, rhs) = data.as_binary_noderefs();
|
||||||
|
|
||||||
*data = match unresolved {
|
*data = match unresolved {
|
||||||
LeftRight::Left(_) => mir::Data::binary(label, rhs.0),
|
LeftRight::Left(_) => {
|
||||||
LeftRight::Right(_) => mir::Data::binary(lhs.0, label),
|
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()),
|
mir::Data::imm64(data.unwrap().as_u64()),
|
||||||
),
|
),
|
||||||
Inst::ConstantMultiByte => {
|
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];
|
let mut buf = [0u8; 8];
|
||||||
match bytes.len() {
|
match bytes.len() {
|
||||||
1 => mir.gen_u8(bytes[0]),
|
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 => {
|
3..=4 => {
|
||||||
buf[..bytes.len()].copy_from_slice(bytes);
|
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 => {
|
5..=8 => {
|
||||||
buf[..bytes.len()].copy_from_slice(bytes);
|
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!(
|
unimplemented!(
|
||||||
|
@ -1129,7 +1333,10 @@ impl<'a> MirBuilder<'a> {
|
||||||
}
|
}
|
||||||
Inst::Load(ty) => {
|
Inst::Load(ty) => {
|
||||||
let ty = mir::Type::from_bytesize_int(ty.size());
|
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)
|
mir.gen_load(ty, src)
|
||||||
}
|
}
|
||||||
Inst::Store(ty) => {
|
Inst::Store(ty) => {
|
||||||
|
@ -1170,7 +1377,14 @@ impl<'a> MirBuilder<'a> {
|
||||||
_ => unreachable!(),
|
_ => 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) => {
|
Inst::Add(ty) => {
|
||||||
let (src, dst) = data.unwrap().as_lhs_rhs();
|
let (src, dst) = data.unwrap().as_lhs_rhs();
|
||||||
|
@ -1187,15 +1401,22 @@ impl<'a> MirBuilder<'a> {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
bits => {
|
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);
|
let sum = mir.gen_add(ty, lhs, rhs);
|
||||||
mir.gen_truncate_integer(sum, ty, signed, bits)
|
mir.gen_truncate_integer(sum, ty, signed, bits)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Type2::Binary32 => mir.gen_add(mir::Type::SinglePrecision, lhs, rhs),
|
Type2::Binary32 => {
|
||||||
Type2::Binary64 => mir.gen_add(mir::Type::DoublePrecision, lhs, rhs),
|
mir.gen_add(mir::Type::SinglePrecision, lhs, rhs)
|
||||||
Type2::Pointer => mir.gen_add(mir::Type::QWord, lhs, rhs),
|
}
|
||||||
|
Type2::Binary64 => {
|
||||||
|
mir.gen_add(mir::Type::DoublePrecision, lhs, rhs)
|
||||||
|
}
|
||||||
|
Type2::Pointer => {
|
||||||
|
mir.gen_add(mir::Type::QWord, lhs, rhs)
|
||||||
|
}
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1271,7 +1492,8 @@ impl<'a> MirBuilder<'a> {
|
||||||
let unalignment = ty.mir_unalignment();
|
let unalignment = ty.mir_unalignment();
|
||||||
let ty = ty.mir_type();
|
let ty = ty.mir_type();
|
||||||
|
|
||||||
let (lhs, rhs) = if self.ir.ir.nodes[lhs as usize].is_constant() {
|
let (lhs, rhs) =
|
||||||
|
if self.ir.ir.nodes[lhs as usize].is_constant() {
|
||||||
(rhs, lhs)
|
(rhs, lhs)
|
||||||
} else {
|
} else {
|
||||||
(lhs, rhs)
|
(lhs, rhs)
|
||||||
|
@ -1293,7 +1515,8 @@ impl<'a> MirBuilder<'a> {
|
||||||
let unalignment = ty.mir_unalignment();
|
let unalignment = ty.mir_unalignment();
|
||||||
let ty = ty.mir_type();
|
let ty = ty.mir_type();
|
||||||
|
|
||||||
let (lhs, rhs) = if self.ir.ir.nodes[lhs as usize].is_constant() {
|
let (lhs, rhs) =
|
||||||
|
if self.ir.ir.nodes[lhs as usize].is_constant() {
|
||||||
(rhs, lhs)
|
(rhs, lhs)
|
||||||
} else {
|
} else {
|
||||||
(lhs, rhs)
|
(lhs, rhs)
|
||||||
|
@ -1315,7 +1538,8 @@ impl<'a> MirBuilder<'a> {
|
||||||
let unalignment = ty.mir_unalignment();
|
let unalignment = ty.mir_unalignment();
|
||||||
let ty = ty.mir_type();
|
let ty = ty.mir_type();
|
||||||
|
|
||||||
let (lhs, rhs) = if self.ir.ir.nodes[lhs as usize].is_constant() {
|
let (lhs, rhs) =
|
||||||
|
if self.ir.ir.nodes[lhs as usize].is_constant() {
|
||||||
(rhs, lhs)
|
(rhs, lhs)
|
||||||
} else {
|
} else {
|
||||||
(lhs, rhs)
|
(lhs, rhs)
|
||||||
|
@ -1337,7 +1561,8 @@ impl<'a> MirBuilder<'a> {
|
||||||
let rhs = mapping.get(&mut mir, dst).unwrap().0;
|
let rhs = mapping.get(&mut mir, dst).unwrap().0;
|
||||||
|
|
||||||
// TODO: check rhs type and pass it to gen_sh{l,r}?
|
// 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 {
|
match ty {
|
||||||
Type2::Integral(signed, bits) => match bits {
|
Type2::Integral(signed, bits) => match bits {
|
||||||
8 => mir.gen_shl(mir::Type::Byte, lhs, rhs),
|
8 => mir.gen_shl(mir::Type::Byte, lhs, rhs),
|
||||||
|
@ -1348,7 +1573,8 @@ impl<'a> MirBuilder<'a> {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
bits => {
|
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);
|
let sum = mir.gen_shl(ty, lhs, rhs);
|
||||||
mir.gen_truncate_integer(sum, ty, signed, bits)
|
mir.gen_truncate_integer(sum, ty, signed, bits)
|
||||||
|
@ -1365,7 +1591,8 @@ impl<'a> MirBuilder<'a> {
|
||||||
match ty {
|
match ty {
|
||||||
Type2::Integral(signed, bits) => match bits {
|
Type2::Integral(signed, bits) => match bits {
|
||||||
8 | 16 | 32 | 64 => {
|
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 {
|
if signed {
|
||||||
mir.gen_sar(ty, lhs, rhs)
|
mir.gen_sar(ty, lhs, rhs)
|
||||||
} else {
|
} else {
|
||||||
|
@ -1376,7 +1603,8 @@ impl<'a> MirBuilder<'a> {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
bits => {
|
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 {
|
let sum = if signed {
|
||||||
mir.gen_sar(ty, lhs, rhs)
|
mir.gen_sar(ty, lhs, rhs)
|
||||||
|
@ -1428,9 +1656,14 @@ impl<'a> MirBuilder<'a> {
|
||||||
let lhs = mapping.get(&mut mir, lhs).unwrap().0;
|
let lhs = mapping.get(&mut mir, lhs).unwrap().0;
|
||||||
|
|
||||||
match (from, to) {
|
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 {
|
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 {
|
} else if a < b {
|
||||||
mir.gen_extend_integer(
|
mir.gen_extend_integer(
|
||||||
lhs,
|
lhs,
|
||||||
|
@ -1445,7 +1678,8 @@ impl<'a> MirBuilder<'a> {
|
||||||
let is_zero = mir.gen_is_zero(from_mir, lhs);
|
let is_zero = mir.gen_is_zero(from_mir, lhs);
|
||||||
mir.gen_negate(mir::Type::Byte, is_zero)
|
mir.gen_negate(mir::Type::Byte, is_zero)
|
||||||
}
|
}
|
||||||
(Type2::Bool, Type2::Integral(b_signed, b)) => mir.gen_extend_integer(
|
(Type2::Bool, Type2::Integral(b_signed, b)) => mir
|
||||||
|
.gen_extend_integer(
|
||||||
lhs,
|
lhs,
|
||||||
IntegralType::u1(),
|
IntegralType::u1(),
|
||||||
IntegralType::new(b_signed, b),
|
IntegralType::new(b_signed, b),
|
||||||
|
@ -1468,13 +1702,18 @@ impl<'a> MirBuilder<'a> {
|
||||||
let label = match mapping.get(&mut mir, label) {
|
let label = match mapping.get(&mut mir, label) {
|
||||||
Some(label) => label.0,
|
Some(label) => label.0,
|
||||||
None => {
|
None => {
|
||||||
unresolved_jumps_branches
|
unresolved_jumps_branches.insert((
|
||||||
.insert((label, LeftRight::Left(mir::NodeRef(jmp))));
|
label,
|
||||||
|
LeftRight::Left(mir::NodeRef(jmp)),
|
||||||
|
));
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
mir.set_node_data(mir::NodeRef(jmp), mir::Data::node(label));
|
mir.set_node_data(
|
||||||
|
mir::NodeRef(jmp),
|
||||||
|
mir::Data::node(label),
|
||||||
|
);
|
||||||
|
|
||||||
jmp
|
jmp
|
||||||
}
|
}
|
||||||
|
@ -1487,21 +1726,28 @@ impl<'a> MirBuilder<'a> {
|
||||||
let lhs = match mapping.get(&mut mir, lhs) {
|
let lhs = match mapping.get(&mut mir, lhs) {
|
||||||
Some(n) => n.0,
|
Some(n) => n.0,
|
||||||
None => {
|
None => {
|
||||||
unresolved_jumps_branches
|
unresolved_jumps_branches.insert((
|
||||||
.insert((lhs, LeftRight::Left(mir::NodeRef(br))));
|
lhs,
|
||||||
|
LeftRight::Left(mir::NodeRef(br)),
|
||||||
|
));
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let rhs = match mapping.get(&mut mir, rhs) {
|
let rhs = match mapping.get(&mut mir, rhs) {
|
||||||
Some(n) => n.0,
|
Some(n) => n.0,
|
||||||
None => {
|
None => {
|
||||||
unresolved_jumps_branches
|
unresolved_jumps_branches.insert((
|
||||||
.insert((rhs, LeftRight::Right(mir::NodeRef(br))));
|
rhs,
|
||||||
|
LeftRight::Right(mir::NodeRef(br)),
|
||||||
|
));
|
||||||
0
|
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
|
br
|
||||||
}
|
}
|
||||||
|
@ -1539,12 +1785,13 @@ impl<'a> MirBuilder<'a> {
|
||||||
Inst::Argument(_) | Inst::InlineType(_) => {
|
Inst::Argument(_) | Inst::InlineType(_) => {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
Inst::ExternRef(ty) => {
|
Inst::ExternRef(ty) => mir
|
||||||
mir.gen_extern(Some(ty.mir_type()), data.unwrap().as_index())
|
.gen_extern(Some(ty.mir_type()), data.unwrap().as_index()),
|
||||||
}
|
|
||||||
#[allow(unreachable_patterns)]
|
#[allow(unreachable_patterns)]
|
||||||
_ => {
|
_ => {
|
||||||
eprintln!("ir inst {inst:?} not supported in mir translation");
|
eprintln!(
|
||||||
|
"ir inst {inst:?} not supported in mir translation"
|
||||||
|
);
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -1561,7 +1808,9 @@ impl<'a> MirBuilder<'a> {
|
||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
match inst {
|
match inst {
|
||||||
Inst::FunctionStart => self.build_function(data.unwrap().as_index()),
|
Inst::FunctionStart => {
|
||||||
|
self.build_function(data.unwrap().as_index())
|
||||||
|
}
|
||||||
Inst::GlobalConstant(name, ..) => {
|
Inst::GlobalConstant(name, ..) => {
|
||||||
let mut mir = mir::Mir::new(name);
|
let mut mir = mir::Mir::new(name);
|
||||||
let value = data.unwrap().lhs;
|
let value = data.unwrap().lhs;
|
||||||
|
@ -1577,20 +1826,26 @@ impl<'a> MirBuilder<'a> {
|
||||||
mir::Data::imm64(data.unwrap().as_u64()),
|
mir::Data::imm64(data.unwrap().as_u64()),
|
||||||
),
|
),
|
||||||
Inst::ConstantMultiByte => {
|
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];
|
let mut buf = [0u8; 8];
|
||||||
match bytes.len() {
|
match bytes.len() {
|
||||||
1 => mir.gen_u8(bytes[0]),
|
1 => mir.gen_u8(bytes[0]),
|
||||||
2 => {
|
2 => mir.gen_u16(u16::from_le_bytes(
|
||||||
mir.gen_u16(u16::from_le_bytes(bytes[..2].try_into().unwrap()))
|
bytes[..2].try_into().unwrap(),
|
||||||
}
|
)),
|
||||||
3..=4 => {
|
3..=4 => {
|
||||||
buf[..bytes.len()].copy_from_slice(bytes);
|
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 => {
|
5..=8 => {
|
||||||
buf[..bytes.len()].copy_from_slice(bytes);
|
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!(
|
unimplemented!(
|
||||||
|
|
Loading…
Reference in a new issue