Skip to content

Commit

Permalink
Continued working on casting operations, including by adding casts to…
Browse files Browse the repository at this point in the history
…/from bool
  • Loading branch information
IsaacShelton committed Oct 21, 2024
1 parent 4737ecc commit c8023c0
Show file tree
Hide file tree
Showing 6 changed files with 120 additions and 16 deletions.
6 changes: 4 additions & 2 deletions src/interpreter/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -221,8 +221,10 @@ impl<'a, S: SyscallHandler> Interpreter<'a, S> {
fields: ty.struct_fields(self.ir_module).unwrap(),
})
}
ir::Instruction::IsZero(_) => todo!("Interpreter / ir::Instruction::IsZero"),
ir::Instruction::IsNonZero(value) => {
ir::Instruction::IsZero(_value, _) => {
todo!("Interpreter / ir::Instruction::IsZero")
}
ir::Instruction::IsNonZero(value, _) => {
let value = self.eval(&registers, value);

match value {
Expand Down
4 changes: 2 additions & 2 deletions src/ir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -134,8 +134,8 @@ pub enum Instruction {
index: Value,
},
StructLiteral(Type, Vec<Value>),
IsZero(Value),
IsNonZero(Value),
IsZero(Value, FloatOrInteger),
IsNonZero(Value, FloatOrInteger),
Negate(Value),
NegateFloat(Value),
BitComplement(Value),
Expand Down
34 changes: 29 additions & 5 deletions src/llvm_backend/functions/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ use llvm_sys::{
core::*,
prelude::{LLVMTypeRef, LLVMValueRef},
LLVMIntPredicate::*,
LLVMRealPredicate::*,
LLVMRealPredicate::{self, *},
};
use std::{borrow::Cow, ptr::null_mut, sync::atomic};

Expand Down Expand Up @@ -568,13 +568,37 @@ pub unsafe fn create_function_block(

Some(literal)
}
Instruction::IsZero(inner) => {
Instruction::IsZero(inner, floating) => {
let value = build_value(ctx, value_catalog, builder, inner)?;
Some(LLVMBuildIsNull(builder.get(), value, cstr!("").as_ptr()))

Some(match floating {
FloatOrInteger::Integer => {
LLVMBuildIsNull(builder.get(), value, cstr!("").as_ptr())
}
FloatOrInteger::Float => LLVMBuildFCmp(
builder.get(),
LLVMRealPredicate::LLVMRealOEQ,
value,
LLVMConstNull(LLVMTypeOf(value)),
cstr!("").as_ptr(),
),
})
}
Instruction::IsNonZero(inner) => {
Instruction::IsNonZero(inner, floating) => {
let value = build_value(ctx, value_catalog, builder, inner)?;
Some(LLVMBuildIsNotNull(builder.get(), value, cstr!("").as_ptr()))

Some(match floating {
FloatOrInteger::Integer => {
LLVMBuildIsNotNull(builder.get(), value, cstr!("").as_ptr())
}
FloatOrInteger::Float => LLVMBuildFCmp(
builder.get(),
LLVMRealPredicate::LLVMRealONE,
value,
LLVMConstNull(LLVMTypeOf(value)),
cstr!("").as_ptr(),
),
})
}
Instruction::Negate(inner) => {
let value = build_value(ctx, value_catalog, builder, inner)?;
Expand Down
13 changes: 11 additions & 2 deletions src/lower/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -816,11 +816,20 @@ fn lower_expr(
let UnaryMathOperation { operator, inner } = &**operation;
let value = lower_expr(builder, ir_module, &inner.expr, function, resolved_ast)?;

let float_or_int = inner
.resolved_type
.kind
.is_float_like()
.then_some(FloatOrInteger::Float)
.unwrap_or(FloatOrInteger::Integer);

let instruction = match operator {
resolved::UnaryMathOperator::Not => ir::Instruction::IsZero(value),
resolved::UnaryMathOperator::Not => ir::Instruction::IsZero(value, float_or_int),
resolved::UnaryMathOperator::BitComplement => ir::Instruction::BitComplement(value),
resolved::UnaryMathOperator::Negate => ir::Instruction::Negate(value),
resolved::UnaryMathOperator::IsNonZero => ir::Instruction::IsNonZero(value),
resolved::UnaryMathOperator::IsNonZero => {
ir::Instruction::IsNonZero(value, float_or_int)
}
};

Ok(builder.push(instruction))
Expand Down
73 changes: 69 additions & 4 deletions src/resolve/expr/call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ pub fn resolve_call_expr(
let name = &call.function_name.basename;

let target_type_kind = match name.as_ref() {
"bool" => Some(resolved::TypeKind::Boolean),
"u8" => Some(resolved::TypeKind::u8()),
"u16" => Some(resolved::TypeKind::u16()),
"u32" => Some(resolved::TypeKind::u32()),
Expand Down Expand Up @@ -87,8 +88,32 @@ pub fn resolve_call_expr(
_ => None,
};

let argument_type_kind = &arguments[0].resolved_type.kind;

if let Some(target_type_kind) = target_type_kind {
if arguments[0].resolved_type.kind.is_floating() {
if target_type_kind.is_boolean()
&& (argument_type_kind.is_integer_like() || argument_type_kind.is_float_like())
{
let target_type = target_type_kind.at(source);
let argument = arguments.into_iter().next().unwrap();
let is_initialized = argument.is_initialized;

let expr = resolved::ExprKind::UnaryMathOperation(Box::new(
resolved::UnaryMathOperation {
operator: resolved::UnaryMathOperator::IsNonZero,
inner: argument,
},
))
.at(source);

return Ok(TypedExpr {
resolved_type: target_type,
expr,
is_initialized,
});
}

if argument_type_kind.is_floating() {
let target_type = target_type_kind.at(source);
let argument = arguments.into_iter().next().unwrap();

Expand All @@ -104,16 +129,56 @@ pub fn resolve_call_expr(
is_initialized: argument.is_initialized,
});
}

if argument_type_kind.is_integer_like() || argument_type_kind.is_boolean() {
let target_type = target_type_kind.at(source);
let argument = arguments.into_iter().next().unwrap();

let expr = resolved::ExprKind::IntegerCast(Box::new(CastFrom {
cast: Cast {
target_type: target_type.clone(),
value: argument.expr,
},
from_type: argument.resolved_type,
}))
.at(source);

return Ok(TypedExpr {
resolved_type: target_type,
expr,
is_initialized: argument.is_initialized,
});
}
}

let target_type_kind = match name.as_ref() {
"f32" => Some(resolved::TypeKind::f32()),
"f64" => Some(resolved::TypeKind::f64()),
"f32" | "float" => Some(resolved::TypeKind::f32()),
"f64" | "double" => Some(resolved::TypeKind::f64()),
_ => None,
};

if let Some(target_type_kind) = target_type_kind {
if arguments[0].resolved_type.kind.is_integer_like() {
if argument_type_kind.is_boolean() {
let target_type = target_type_kind.at(source);
let argument = arguments.into_iter().next().unwrap();
let is_initialized = argument.is_initialized;

let expr = resolved::ExprKind::UnaryMathOperation(Box::new(
resolved::UnaryMathOperation {
operator: resolved::UnaryMathOperator::IsNonZero,
inner: argument,
},
))
.at(source);

return Ok(TypedExpr {
resolved_type: target_type,
expr,
is_initialized,
});
}

if argument_type_kind.is_integer_like() {
let target_type = target_type_kind.at(source);
let argument = arguments.into_iter().next().unwrap();

Expand Down
6 changes: 5 additions & 1 deletion src/resolved/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,10 @@ impl TypeKind {
)
}

pub fn is_float_like(&self) -> bool {
matches!(self, Self::Floating(..) | Self::FloatLiteral(..))
}

pub fn is_ambiguous(&self) -> bool {
self.is_integer_literal()
}
Expand Down Expand Up @@ -354,7 +358,7 @@ impl TypeKind {

pub fn sign(&self, target: Option<&Target>) -> Option<IntegerSign> {
match self {
TypeKind::Boolean => None,
TypeKind::Boolean => Some(IntegerSign::Unsigned),
TypeKind::Integer(_, sign) => Some(*sign),
TypeKind::IntegerLiteral(value) => Some(if value >= &BigInt::zero() {
IntegerSign::Unsigned
Expand Down

0 comments on commit c8023c0

Please sign in to comment.