Add nullptr comparison

This commit is contained in:
Sofia 2025-08-07 21:32:30 +03:00
parent e1ac019ecd
commit 1a8535516c
9 changed files with 50 additions and 29 deletions

View File

@ -0,0 +1,4 @@
fn main() -> bool {
let ptr = i32::null();
return i32::is_null(ptr);
}

View File

@ -1,6 +0,0 @@
import triple_import_vec2::Vec2;
import triple_import_ship::Ship;
fn main() -> i32 {
return 0;
}

View File

@ -1,17 +0,0 @@
//asd
import triple_import_vec2::Vec2;
struct Ship {
position: Vec2,
velocity: Vec2,
}
impl Ship {
pub fn foo(&self, vec: Vec2) {
let b: Ship = Ship {
position: Vec2::zero(),
velocity: Vec2::zero(),
};
}
}

View File

@ -1,6 +0,0 @@
struct Vec2 { x: f32, y: f32 }
impl Vec2 {
pub fn zero() -> Vec2 { Vec2 { x: 0.0, y: 0.0 } }
}

View File

@ -3,6 +3,8 @@
use std::{cell::RefCell, rc::Rc}; use std::{cell::RefCell, rc::Rc};
use llvm_sys::core::LLVMBuildIsNull;
use crate::{ use crate::{
Block, BlockData, CompileResult, ConstValueKind, CustomTypeKind, ErrorKind, FunctionData, Instr, InstructionData, Block, BlockData, CompileResult, ConstValueKind, CustomTypeKind, ErrorKind, FunctionData, Instr, InstructionData,
ModuleData, NamedStruct, TerminatorKind, Type, TypeCategory, TypeData, ModuleData, NamedStruct, TerminatorKind, Type, TypeCategory, TypeData,
@ -614,6 +616,14 @@ impl Builder {
Instr::ShiftRightArithmetic(lhs, rhs) => match_types(&lhs, &rhs, &self).map(|_| ()), Instr::ShiftRightArithmetic(lhs, rhs) => match_types(&lhs, &rhs, &self).map(|_| ()),
Instr::ShiftLeft(lhs, rhs) => match_types(&lhs, &rhs, &self).map(|_| ()), Instr::ShiftLeft(lhs, rhs) => match_types(&lhs, &rhs, &self).map(|_| ()),
Instr::GetGlobal(_) => Ok(()), Instr::GetGlobal(_) => Ok(()),
Instr::IsNull(val) => {
let val_ty = val.get_type(&self)?;
if let Type::Ptr(_) = val_ty {
Ok(())
} else {
Err(ErrorKind::Null)
}
}
} }
} }
} }
@ -770,6 +780,7 @@ impl InstructionValue {
let kind = builder.get_const_kind(constant); let kind = builder.get_const_kind(constant);
Ok(kind.get_type()) Ok(kind.get_type())
} }
IsNull(_) => Ok(Type::Bool),
} }
} }
} }

View File

@ -1051,6 +1051,10 @@ impl InstructionHolder {
LLVMBuildShl(module.builder_ref, lhs_val, rhs_val, name.as_ptr()) LLVMBuildShl(module.builder_ref, lhs_val, rhs_val, name.as_ptr())
} }
GetGlobal(global_value) => module.globals.get(global_value).unwrap().clone(), GetGlobal(global_value) => module.globals.get(global_value).unwrap().clone(),
IsNull(instruction_value) => {
let val = module.values.get(&*instruction_value).unwrap().value_ref;
LLVMBuildIsNull(module.builder_ref, val, name.as_ptr())
}
} }
}; };
if let Some(record) = &self.record { if let Some(record) = &self.record {

View File

@ -393,6 +393,7 @@ impl Debug for Instr {
Instr::ShiftRightArithmetic(lhs, rhs) => fmt_binop(f, lhs, &">>a", rhs), Instr::ShiftRightArithmetic(lhs, rhs) => fmt_binop(f, lhs, &">>a", rhs),
Instr::ShiftLeft(lhs, rhs) => fmt_binop(f, lhs, &"<<", rhs), Instr::ShiftLeft(lhs, rhs) => fmt_binop(f, lhs, &"<<", rhs),
Instr::GetGlobal(global_value) => write!(f, "global {:?}", global_value), Instr::GetGlobal(global_value) => write!(f, "global {:?}", global_value),
Instr::IsNull(_) => write!(f, "is_null"),
} }
} }
} }

View File

@ -298,6 +298,7 @@ impl Instr {
Instr::ShiftRightArithmetic(..) => "ashr", Instr::ShiftRightArithmetic(..) => "ashr",
Instr::ShiftLeft(..) => "shl", Instr::ShiftLeft(..) => "shl",
Instr::GetGlobal(..) => "global", Instr::GetGlobal(..) => "global",
Instr::IsNull(..) => "is_null",
} }
} }
} }
@ -491,6 +492,9 @@ pub enum Instr {
/// no-op cast because no bits change with this conversion. /// no-op cast because no bits change with this conversion.
BitCast(InstructionValue, Type), BitCast(InstructionValue, Type),
/// Check if the given instruction value is a null pointer
IsNull(InstructionValue),
FunctionCall(FunctionValue, Vec<InstructionValue>), FunctionCall(FunctionValue, Vec<InstructionValue>),
} }

View File

@ -388,6 +388,22 @@ pub fn get_intrinsic_assoc_functions(ty: &TypeKind) -> Vec<FunctionDefinition> {
signature_meta: Default::default(), signature_meta: Default::default(),
}); });
intrinsics.push(FunctionDefinition {
name: "is_null".to_owned(),
linkage_name: None,
is_pub: true,
is_imported: false,
return_type: TypeKind::Bool,
parameters: vec![FunctionParam {
name: "value".to_string(),
ty: TypeKind::UserPtr(Box::new(ty.clone())),
meta: Default::default(),
}],
kind: FunctionDefinitionKind::Intrinsic(Box::new(IntrinsicIsNull)),
source: None,
signature_meta: Default::default(),
});
intrinsics intrinsics
} }
@ -755,6 +771,16 @@ impl IntrinsicFunction for IntrinsicNullPtr {
} }
} }
#[derive(Clone, Debug)]
pub struct IntrinsicIsNull;
impl IntrinsicFunction for IntrinsicIsNull {
fn codegen<'ctx, 'a>(&self, scope: &mut Scope<'ctx, 'a>, params: &[StackValue]) -> Result<StackValue, ErrorKind> {
let val = params.get(0).unwrap().instr();
let instr = scope.block.build(Instr::IsNull(val)).unwrap();
Ok(StackValue(StackValueKind::Literal(instr), TypeKind::Bool))
}
}
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct IntrinsicConst(u64); pub struct IntrinsicConst(u64);
impl IntrinsicFunction for IntrinsicConst { impl IntrinsicFunction for IntrinsicConst {