Add intrinsic malloc, use that in alloca

This commit is contained in:
Sofia 2025-07-28 20:45:49 +03:00
parent beaba4e7de
commit 5026013df3
5 changed files with 55 additions and 29 deletions

View File

@ -168,6 +168,15 @@ impl Builder {
} }
} }
pub(crate) unsafe fn find_function(&self, module: ModuleValue, name: &String) -> Option<FunctionValue> {
unsafe {
let mut modules = self.modules.borrow_mut();
let module = modules.get_unchecked_mut(module.0);
dbg!(module.functions.iter().map(|f| f.data.name.clone()).collect::<Vec<_>>());
module.functions.iter().find(|f| f.data.name == *name).map(|f| f.value)
}
}
pub(crate) unsafe fn add_instruction_location(&self, value: &InstructionValue, location: DebugLocationValue) { pub(crate) unsafe fn add_instruction_location(&self, value: &InstructionValue, location: DebugLocationValue) {
unsafe { unsafe {
let mut modules = self.modules.borrow_mut(); let mut modules = self.modules.borrow_mut();

View File

@ -290,6 +290,10 @@ impl<'builder> Block<'builder> {
} }
} }
pub fn find_function(&mut self, name: &String) -> Option<FunctionValue> {
unsafe { self.builder.find_function(self.value.0.0, name) }
}
pub fn set_instr_location(&self, instruction: InstructionValue, location: DebugLocationValue) { pub fn set_instr_location(&self, instruction: InstructionValue, location: DebugLocationValue) {
unsafe { unsafe {
self.builder.add_instruction_location(&instruction, location); self.builder.add_instruction_location(&instruction, location);

View File

@ -1,6 +1,5 @@
extern fn puts(message: *char) -> i32; extern fn puts(message: *char) -> i32;
extern fn malloc(size: u64) -> *u8;
extern fn free(ptr: *u8); extern fn free(ptr: *u8);
extern fn div(numerator: i32, denominator: i32) -> div_t; extern fn div(numerator: i32, denominator: i32) -> div_t;
@ -14,7 +13,7 @@ struct String {
impl String { impl String {
pub fn new() -> String { pub fn new() -> String {
String { String {
inner: allocate(0), inner: char::alloca(0),
length: 0, length: 0,
max_length: 0, max_length: 0,
must_be_freed: true, must_be_freed: true,
@ -42,7 +41,7 @@ impl String {
pub fn add_char(&mut self, c: char) { pub fn add_char(&mut self, c: char) {
if ((*self).length + 1) >= (*self).max_length { if ((*self).length + 1) >= (*self).max_length {
let new = allocate((*self).max_length + 4) as *char; let new = char::alloca((*self).max_length + 4);
copy_bits((*self).inner, new, (*self).max_length); copy_bits((*self).inner, new, (*self).max_length);
if (*self).must_be_freed == true { if (*self).must_be_freed == true {
@ -120,13 +119,9 @@ pub fn int_div(numerator: i32, denominator: i32) -> div_t {
return div(numerator, denominator); return div(numerator, denominator);
} }
pub fn allocate(size: u64) -> *u8 {
malloc(size)
}
pub fn new_string() -> String { pub fn new_string() -> String {
String { String {
inner: allocate(0), inner: char::alloca(0),
length: 0, length: 0,
max_length: 0, max_length: 0,
must_be_freed: true, must_be_freed: true,
@ -148,7 +143,7 @@ pub fn from_str(str: *char) -> String {
pub fn add_char(string: &mut String, c: char) { pub fn add_char(string: &mut String, c: char) {
if ((*string).length + 1) >= (*string).max_length { if ((*string).length + 1) >= (*string).max_length {
let new = allocate((*string).max_length + 4) as *char; let new = char::alloca((*string).max_length + 4);
copy_bits((*string).inner, new, (*string).max_length); copy_bits((*string).inner, new, (*string).max_length);
if (*string).must_be_freed == true { if (*string).must_be_freed == true {

View File

@ -33,8 +33,25 @@ const FLOATS: [TypeKind; 7] = [
TypeKind::F128PPC, TypeKind::F128PPC,
]; ];
const MALLOC_IDENT: &str = "reid.malloc";
pub fn form_intrinsics() -> Vec<FunctionDefinition> { pub fn form_intrinsics() -> Vec<FunctionDefinition> {
let intrinsics = Vec::new(); let mut intrinsics = Vec::new();
intrinsics.push(FunctionDefinition {
name: MALLOC_IDENT.to_owned(),
linkage_name: Some("malloc".to_owned()),
is_pub: false,
is_imported: true,
return_type: TypeKind::UserPtr(Box::new(TypeKind::U8)),
parameters: vec![FunctionParam {
name: "size".to_owned(),
ty: TypeKind::U64,
meta: Default::default(),
}],
kind: FunctionDefinitionKind::Extern(false),
source: None,
});
intrinsics intrinsics
} }
@ -62,7 +79,7 @@ pub fn get_intrinsic_assoc_func(ty: &TypeKind, name: &str) -> Option<FunctionDef
ty: TypeKind::U64, ty: TypeKind::U64,
meta: Default::default(), meta: Default::default(),
}], }],
kind: FunctionDefinitionKind::Intrinsic(Box::new(IntrinsicAlloca(ty.clone()))), kind: FunctionDefinitionKind::Intrinsic(Box::new(IntrinsicMalloc(ty.clone()))),
source: None, source: None,
}), }),
"null" => Some(FunctionDefinition { "null" => Some(FunctionDefinition {
@ -353,13 +370,14 @@ impl IntrinsicFunction for IntrinsicSizeOf {
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct IntrinsicAlloca(TypeKind); pub struct IntrinsicMalloc(TypeKind);
impl IntrinsicFunction for IntrinsicAlloca { impl IntrinsicFunction for IntrinsicMalloc {
fn codegen<'ctx, 'a>(&self, scope: &mut Scope<'ctx, 'a>, params: &[StackValue]) -> Result<StackValue, ErrorKind> { fn codegen<'ctx, 'a>(&self, scope: &mut Scope<'ctx, 'a>, params: &[StackValue]) -> Result<StackValue, ErrorKind> {
let amount = params.get(0).unwrap(); let amount = params.get(0).unwrap();
let function = scope.block.find_function(&"malloc".to_owned()).unwrap();
let instr = scope let instr = scope
.block .block
.build(Instr::ArrayAlloca(self.0.get_type(scope.type_values), amount.instr())) .build(Instr::FunctionCall(function, vec![amount.instr()]))
.unwrap(); .unwrap();
Ok(StackValue(StackValueKind::Literal(instr), self.0.clone())) Ok(StackValue(StackValueKind::Literal(instr), self.0.clone()))
} }

View File

@ -125,6 +125,21 @@ pub fn perform_all_passes<'map>(
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
dbg!(&context); dbg!(&context);
#[cfg(debug_assertions)]
println!("{:#}", &context);
let state = context.pass(&mut LinkerPass {
module_map,
is_lib: true,
})?;
#[cfg(debug_assertions)]
println!("{:-^100}", "LINKER OUTPUT");
#[cfg(debug_assertions)]
println!("{:#}", &context);
#[cfg(debug_assertions)]
dbg!(&state);
let mut binops = BinopMap::default(); let mut binops = BinopMap::default();
for module in &mut context.modules { for module in &mut context.modules {
for intrinsic in form_intrinsic_binops() { for intrinsic in form_intrinsic_binops() {
@ -151,21 +166,6 @@ pub fn perform_all_passes<'map>(
} }
} }
#[cfg(debug_assertions)]
println!("{:#}", &context);
let state = context.pass(&mut LinkerPass {
module_map,
is_lib: true,
})?;
#[cfg(debug_assertions)]
println!("{:-^100}", "LINKER OUTPUT");
#[cfg(debug_assertions)]
println!("{:#}", &context);
#[cfg(debug_assertions)]
dbg!(&state);
if !state.errors.is_empty() { if !state.errors.is_empty() {
return Err(ReidError::from_kind( return Err(ReidError::from_kind(
state.errors.iter().map(|e| e.clone().into()).collect(), state.errors.iter().map(|e| e.clone().into()).collect(),