Implement builtin associated alloca and nullptr

This commit is contained in:
Sofia 2025-07-27 20:46:17 +03:00
parent acc2964305
commit 7b27f30b9e
5 changed files with 247 additions and 264 deletions

View File

@ -24,5 +24,11 @@ fn main() -> u32 {
print(from_str("i32: ") + i32::test(54) as u64); print(from_str("i32: ") + i32::test(54) as u64);
print(from_str("sizeof i32: ") + i32::sizeof()); print(from_str("sizeof i32: ") + i32::sizeof());
let nullptr = i32::null();
let mut list = u64::alloca(15);
list[4] = 17;
print(from_str("value: ") + list[4]);
return i32::sizeof() as u32; return i32::sizeof() as u32;
} }

View File

@ -4,11 +4,10 @@
use std::{cell::RefCell, rc::Rc}; use std::{cell::RefCell, rc::Rc};
use crate::{ use crate::{
Block, BlockData, CompileResult, CustomTypeKind, ErrorKind, FunctionData, Instr, Block, BlockData, CompileResult, CustomTypeKind, ErrorKind, FunctionData, Instr, InstructionData, ModuleData,
InstructionData, ModuleData, NamedStruct, TerminatorKind, Type, TypeCategory, TypeData, NamedStruct, TerminatorKind, Type, TypeCategory, TypeData,
debug_information::{ debug_information::{
DebugInformation, DebugLocationValue, DebugMetadataValue, DebugProgramValue, DebugInformation, DebugLocationValue, DebugMetadataValue, DebugProgramValue, InstructionDebugRecordData,
InstructionDebugRecordData,
}, },
util::match_types, util::match_types,
}; };
@ -91,11 +90,7 @@ impl Builder {
value value
} }
pub(crate) fn set_debug_information( pub(crate) fn set_debug_information(&self, mod_val: &ModuleValue, debug_info: DebugInformation) {
&self,
mod_val: &ModuleValue,
debug_info: DebugInformation,
) {
unsafe { unsafe {
let mut modules = self.modules.borrow_mut(); let mut modules = self.modules.borrow_mut();
let module = modules.get_unchecked_mut(mod_val.0); let module = modules.get_unchecked_mut(mod_val.0);
@ -113,11 +108,7 @@ impl Builder {
} }
} }
pub(crate) unsafe fn add_function( pub(crate) unsafe fn add_function(&self, mod_val: &ModuleValue, data: FunctionData) -> FunctionValue {
&self,
mod_val: &ModuleValue,
data: FunctionData,
) -> FunctionValue {
unsafe { unsafe {
let mut modules = self.modules.borrow_mut(); let mut modules = self.modules.borrow_mut();
let module = modules.get_unchecked_mut(mod_val.0); let module = modules.get_unchecked_mut(mod_val.0);
@ -174,11 +165,7 @@ impl Builder {
} }
} }
pub(crate) unsafe fn add_instruction_location( pub(crate) unsafe fn add_instruction_location(&self, value: &InstructionValue, location: DebugLocationValue) {
&self,
value: &InstructionValue,
location: DebugLocationValue,
) {
unsafe { unsafe {
let mut modules = self.modules.borrow_mut(); let mut modules = self.modules.borrow_mut();
let module = modules.get_unchecked_mut(value.0.0.0.0); let module = modules.get_unchecked_mut(value.0.0.0.0);
@ -189,11 +176,7 @@ impl Builder {
} }
} }
pub(crate) unsafe fn add_instruction_metadata( pub(crate) unsafe fn add_instruction_metadata(&self, value: &InstructionValue, metadata: DebugMetadataValue) {
&self,
value: &InstructionValue,
metadata: DebugMetadataValue,
) {
unsafe { unsafe {
let mut modules = self.modules.borrow_mut(); let mut modules = self.modules.borrow_mut();
let module = modules.get_unchecked_mut(value.0.0.0.0); let module = modules.get_unchecked_mut(value.0.0.0.0);
@ -204,11 +187,7 @@ impl Builder {
} }
} }
pub(crate) unsafe fn add_instruction_record( pub(crate) unsafe fn add_instruction_record(&self, value: &InstructionValue, record: InstructionDebugRecordData) {
&self,
value: &InstructionValue,
record: InstructionDebugRecordData,
) {
unsafe { unsafe {
let mut modules = self.modules.borrow_mut(); let mut modules = self.modules.borrow_mut();
let module = modules.get_unchecked_mut(value.0.0.0.0); let module = modules.get_unchecked_mut(value.0.0.0.0);
@ -219,11 +198,7 @@ impl Builder {
} }
} }
pub(crate) unsafe fn set_debug_subprogram( pub(crate) unsafe fn set_debug_subprogram(&self, value: &FunctionValue, subprogram: DebugProgramValue) {
&self,
value: &FunctionValue,
subprogram: DebugProgramValue,
) {
unsafe { unsafe {
let mut modules = self.modules.borrow_mut(); let mut modules = self.modules.borrow_mut();
let module = modules.get_unchecked_mut(value.0.0); let module = modules.get_unchecked_mut(value.0.0);
@ -232,11 +207,7 @@ impl Builder {
} }
} }
pub(crate) unsafe fn terminate( pub(crate) unsafe fn terminate(&self, block: &BlockValue, value: TerminatorKind) -> CompileResult<()> {
&self,
block: &BlockValue,
value: TerminatorKind,
) -> CompileResult<()> {
unsafe { unsafe {
let mut modules = self.modules.borrow_mut(); let mut modules = self.modules.borrow_mut();
let module = modules.get_unchecked_mut(block.0.0.0); let module = modules.get_unchecked_mut(block.0.0.0);
@ -354,22 +325,94 @@ impl Builder {
match self.instr_data(&instruction).kind { match self.instr_data(&instruction).kind {
Instr::Param(_) => Ok(()), Instr::Param(_) => Ok(()),
Instr::Constant(_) => Ok(()), Instr::Constant(_) => Ok(()),
Instr::Add(lhs, rhs) => match_types(&lhs, &rhs, &self).map(|_| ()), Instr::Add(lhs, rhs) => {
Instr::FAdd(lhs, rhs) => match_types(&lhs, &rhs, &self).map(|_| ()), if match_types(&lhs, &rhs, &self)?.category().integer() {
Instr::Sub(lhs, rhs) => match_types(&lhs, &rhs, &self).map(|_| ()), Ok(())
Instr::FSub(lhs, rhs) => match_types(&lhs, &rhs, &self).map(|_| ()), } else {
Instr::Mul(lhs, rhs) => match_types(&lhs, &rhs, &self).map(|_| ()), Err(ErrorKind::Null)
Instr::FMul(lhs, rhs) => match_types(&lhs, &rhs, &self).map(|_| ()), }
Instr::UDiv(lhs, rhs) => match_types(&lhs, &rhs, &self).map(|_| ()), }
Instr::SDiv(lhs, rhs) => match_types(&lhs, &rhs, &self).map(|_| ()), Instr::FAdd(lhs, rhs) => {
Instr::FDiv(lhs, rhs) => match_types(&lhs, &rhs, &self).map(|_| ()), if match_types(&lhs, &rhs, &self)?.category() == TypeCategory::Real {
Instr::URem(lhs, rhs) => match_types(&lhs, &rhs, &self).map(|_| ()), Ok(())
Instr::SRem(lhs, rhs) => match_types(&lhs, &rhs, &self).map(|_| ()), } else {
Instr::FRem(lhs, rhs) => match_types(&lhs, &rhs, &self).map(|_| ()), Err(ErrorKind::Null)
}
}
Instr::Sub(lhs, rhs) => {
if match_types(&lhs, &rhs, &self)?.category().integer() {
Ok(())
} else {
Err(ErrorKind::Null)
}
}
Instr::FSub(lhs, rhs) => {
if match_types(&lhs, &rhs, &self)?.category() == TypeCategory::Real {
Ok(())
} else {
Err(ErrorKind::Null)
}
}
Instr::Mul(lhs, rhs) => {
if match_types(&lhs, &rhs, &self)?.category().integer() {
Ok(())
} else {
Err(ErrorKind::Null)
}
}
Instr::FMul(lhs, rhs) => {
if match_types(&lhs, &rhs, &self)?.category() == TypeCategory::Real {
Ok(())
} else {
Err(ErrorKind::Null)
}
}
Instr::UDiv(lhs, rhs) => {
if match_types(&lhs, &rhs, &self)?.category() == TypeCategory::UnsignedInteger {
Ok(())
} else {
Err(ErrorKind::Null)
}
}
Instr::SDiv(lhs, rhs) => {
if match_types(&lhs, &rhs, &self)?.category() == TypeCategory::SignedInteger {
Ok(())
} else {
Err(ErrorKind::Null)
}
}
Instr::FDiv(lhs, rhs) => {
if match_types(&lhs, &rhs, &self)?.category() == TypeCategory::Real {
Ok(())
} else {
Err(ErrorKind::Null)
}
}
Instr::URem(lhs, rhs) => {
if match_types(&lhs, &rhs, &self)?.category() == TypeCategory::UnsignedInteger {
Ok(())
} else {
Err(ErrorKind::Null)
}
}
Instr::SRem(lhs, rhs) => {
if match_types(&lhs, &rhs, &self)?.category() == TypeCategory::SignedInteger {
Ok(())
} else {
Err(ErrorKind::Null)
}
}
Instr::FRem(lhs, rhs) => {
if match_types(&lhs, &rhs, &self)?.category() == TypeCategory::Real {
Ok(())
} else {
Err(ErrorKind::Null)
}
}
Instr::And(lhs, rhs) => match_types(&lhs, &rhs, &self).map(|_| ()), Instr::And(lhs, rhs) => match_types(&lhs, &rhs, &self).map(|_| ()),
Instr::ICmp(_, lhs, rhs) => { Instr::ICmp(_, lhs, rhs) => {
let t = match_types(&lhs, &rhs, self)?; let t = match_types(&lhs, &rhs, self)?;
if t.comparable() || t.category() != TypeCategory::Integer { if t.category().comparable() || !t.category().integer() {
Ok(()) Ok(())
} else { } else {
Err(ErrorKind::Null) // TODO error: Types not comparable Err(ErrorKind::Null) // TODO error: Types not comparable
@ -377,7 +420,7 @@ impl Builder {
} }
Instr::FCmp(_, lhs, rhs) => { Instr::FCmp(_, lhs, rhs) => {
let t = match_types(&lhs, &rhs, self)?; let t = match_types(&lhs, &rhs, self)?;
if t.comparable() || t.category() != TypeCategory::Real { if t.category().comparable() || t.category() != TypeCategory::Real {
Ok(()) Ok(())
} else { } else {
Err(ErrorKind::Null) // TODO error: Types not comparable Err(ErrorKind::Null) // TODO error: Types not comparable
@ -430,7 +473,13 @@ impl Builder {
Err(ErrorKind::Null) // TODO error: not a pointer Err(ErrorKind::Null) // TODO error: not a pointer
} }
} }
Instr::ArrayAlloca(_, _) => Ok(()), Instr::ArrayAlloca(_, val) => {
if val.get_type(self)?.category() == TypeCategory::UnsignedInteger {
Ok(())
} else {
Err(ErrorKind::Null) // TODO error: not a pointer
}
}
Instr::GetElemPtr(ptr_val, _) => { Instr::GetElemPtr(ptr_val, _) => {
let ptr_ty = ptr_val.get_type(&self)?; let ptr_ty = ptr_val.get_type(&self)?;
match ptr_ty { match ptr_ty {
@ -526,11 +575,7 @@ impl InstructionValue {
self self
} }
pub fn maybe_location( pub fn maybe_location(self, block: &mut Block, location: Option<DebugLocationValue>) -> InstructionValue {
self,
block: &mut Block,
location: Option<DebugLocationValue>,
) -> InstructionValue {
unsafe { unsafe {
if let Some(location) = location { if let Some(location) = location {
block.builder.add_instruction_location(&self, location); block.builder.add_instruction_location(&self, location);
@ -572,10 +617,7 @@ impl InstructionValue {
ICmp(_, _, _) => Ok(Type::Bool), ICmp(_, _, _) => Ok(Type::Bool),
FCmp(_, _, _) => Ok(Type::Bool), FCmp(_, _, _) => Ok(Type::Bool),
FunctionCall(function_value, _) => Ok(builder.function_data(function_value).ret), FunctionCall(function_value, _) => Ok(builder.function_data(function_value).ret),
Phi(values) => values Phi(values) => values.first().ok_or(ErrorKind::Null).and_then(|v| v.get_type(&builder)),
.first()
.ok_or(ErrorKind::Null)
.and_then(|v| v.get_type(&builder)),
Alloca(ty) => Ok(Type::Ptr(Box::new(ty.clone()))), Alloca(ty) => Ok(Type::Ptr(Box::new(ty.clone()))),
Load(_, ty) => Ok(ty.clone()), Load(_, ty) => Ok(ty.clone()),
Store(_, value) => value.get_type(builder), Store(_, value) => value.get_type(builder),

View File

@ -19,8 +19,8 @@ use llvm_sys::{
LLVM_InitializeAllTargetMCs, LLVM_InitializeAllTargets, LLVMSetModuleDataLayout, LLVM_InitializeAllTargetMCs, LLVM_InitializeAllTargets, LLVMSetModuleDataLayout,
}, },
target_machine::{ target_machine::{
LLVMCodeGenFileType, LLVMCreateTargetDataLayout, LLVMCreateTargetMachine, LLVMCodeGenFileType, LLVMCreateTargetDataLayout, LLVMCreateTargetMachine, LLVMGetDefaultTargetTriple,
LLVMGetDefaultTargetTriple, LLVMGetTargetFromTriple, LLVMTargetMachineEmitToMemoryBuffer, LLVMGetTargetFromTriple, LLVMTargetMachineEmitToMemoryBuffer,
}, },
}; };
@ -34,8 +34,8 @@ use crate::{
use super::{ use super::{
CmpPredicate, ConstValue, Context, TerminatorKind, Type, CmpPredicate, ConstValue, Context, TerminatorKind, Type,
builder::{ builder::{
BlockHolder, BlockValue, Builder, FunctionHolder, FunctionValue, InstructionHolder, BlockHolder, BlockValue, Builder, FunctionHolder, FunctionValue, InstructionHolder, InstructionValue,
InstructionValue, ModuleHolder, ModuleHolder,
}, },
}; };
@ -119,8 +119,8 @@ impl CompiledModule {
); );
err.into_result().unwrap(); err.into_result().unwrap();
let llvm_ir = from_cstring(LLVMPrintModuleToString(self.module_ref)) let llvm_ir =
.expect("Unable to print LLVM IR to string"); from_cstring(LLVMPrintModuleToString(self.module_ref)).expect("Unable to print LLVM IR to string");
println!("{}", llvm_ir); println!("{}", llvm_ir);
@ -224,17 +224,15 @@ pub struct LLVMFunction {
} }
pub struct LLVMValue { pub struct LLVMValue {
_ty: Type, ty: Type,
value_ref: LLVMValueRef, value_ref: LLVMValueRef,
} }
impl ModuleHolder { impl ModuleHolder {
fn compile(&self, context: &LLVMContext, builder: &Builder) -> LLVMModuleRef { fn compile(&self, context: &LLVMContext, builder: &Builder) -> LLVMModuleRef {
unsafe { unsafe {
let module_ref = LLVMModuleCreateWithNameInContext( let module_ref =
into_cstring(&self.data.name).as_ptr(), LLVMModuleCreateWithNameInContext(into_cstring(&self.data.name).as_ptr(), context.context_ref);
context.context_ref,
);
// Compile the contents // Compile the contents
@ -372,11 +370,7 @@ impl ModuleHolder {
} }
impl DebugLocationHolder { impl DebugLocationHolder {
unsafe fn compile( unsafe fn compile(&self, context: &LLVMContext, debug: &LLVMDebugInformation) -> LLVMMetadataRef {
&self,
context: &LLVMContext,
debug: &LLVMDebugInformation,
) -> LLVMMetadataRef {
unsafe { unsafe {
LLVMDIBuilderCreateDebugLocation( LLVMDIBuilderCreateDebugLocation(
context.context_ref, context.context_ref,
@ -399,13 +393,7 @@ impl DebugScopeHolder {
) { ) {
unsafe { unsafe {
let scope = if let Some(location) = &self.location { let scope = if let Some(location) = &self.location {
LLVMDIBuilderCreateLexicalBlock( LLVMDIBuilderCreateLexicalBlock(di_builder, parent, file, location.pos.line, location.pos.column)
di_builder,
parent,
file,
location.pos.line,
location.pos.column,
)
} else { } else {
LLVMDIBuilderCreateLexicalBlockFile(di_builder, parent, file, 0) LLVMDIBuilderCreateLexicalBlockFile(di_builder, parent, file, 0)
}; };
@ -489,8 +477,7 @@ impl DebugTypeHolder {
ptr.name.len(), ptr.name.len(),
), ),
DebugTypeData::Array(array) => { DebugTypeData::Array(array) => {
let subrange = let subrange = LLVMDIBuilderGetOrCreateSubrange(debug.builder, 0, array.length as i64);
LLVMDIBuilderGetOrCreateSubrange(debug.builder, 0, array.length as i64);
let mut elements = vec![subrange]; let mut elements = vec![subrange];
LLVMDIBuilderCreateArrayType( LLVMDIBuilderCreateArrayType(
debug.builder, debug.builder,
@ -552,11 +539,7 @@ impl DwarfFlags {
} }
impl TypeHolder { impl TypeHolder {
unsafe fn compile_type( unsafe fn compile_type(&self, context: &LLVMContext, types: &HashMap<TypeValue, LLVMTypeRef>) -> LLVMTypeRef {
&self,
context: &LLVMContext,
types: &HashMap<TypeValue, LLVMTypeRef>,
) -> LLVMTypeRef {
unsafe { unsafe {
match &self.data.kind { match &self.data.kind {
CustomTypeKind::NamedStruct(named_struct) => { CustomTypeKind::NamedStruct(named_struct) => {
@ -564,16 +547,9 @@ impl TypeHolder {
for ty in &named_struct.1 { for ty in &named_struct.1 {
elem_types.push(ty.as_llvm(context.context_ref, types)); elem_types.push(ty.as_llvm(context.context_ref, types));
} }
let struct_ty = LLVMStructCreateNamed( let struct_ty =
context.context_ref, LLVMStructCreateNamed(context.context_ref, into_cstring(named_struct.0.clone()).as_ptr());
into_cstring(named_struct.0.clone()).as_ptr(), LLVMStructSetBody(struct_ty, elem_types.as_mut_ptr(), elem_types.len() as u32, 0);
);
LLVMStructSetBody(
struct_ty,
elem_types.as_mut_ptr(),
elem_types.len() as u32,
0,
);
struct_ty struct_ty
} }
} }
@ -602,15 +578,10 @@ impl FunctionHolder {
let fn_type = LLVMFunctionType(ret_type, param_ptr, param_len as u32, 0); let fn_type = LLVMFunctionType(ret_type, param_ptr, param_len as u32, 0);
let function_ref = let function_ref = LLVMAddFunction(module_ref, into_cstring(&self.data.name).as_ptr(), fn_type);
LLVMAddFunction(module_ref, into_cstring(&self.data.name).as_ptr(), fn_type);
if self.data.flags.inline { if self.data.flags.inline {
let attribute = LLVMCreateEnumAttribute( let attribute = LLVMCreateEnumAttribute(context.context_ref, LLVMEnumAttribute::AlwaysInline as u32, 0);
context.context_ref,
LLVMEnumAttribute::AlwaysInline as u32,
0,
);
LLVMAddAttributeAtIndex(function_ref, 0, attribute); LLVMAddAttributeAtIndex(function_ref, 0, attribute);
} }
@ -667,10 +638,7 @@ impl FunctionHolder {
if self.data.flags.is_imported { if self.data.flags.is_imported {
if self.data.flags.is_extern { if self.data.flags.is_extern {
LLVMSetLinkage( LLVMSetLinkage(own_function.value_ref, LLVMLinkage::LLVMAvailableExternallyLinkage);
own_function.value_ref,
LLVMLinkage::LLVMAvailableExternallyLinkage,
);
} else { } else {
LLVMSetLinkage(own_function.value_ref, LLVMLinkage::LLVMExternalLinkage); LLVMSetLinkage(own_function.value_ref, LLVMLinkage::LLVMExternalLinkage);
} }
@ -687,10 +655,8 @@ impl FunctionHolder {
continue; continue;
} }
let block_ref = LLVMCreateBasicBlockInContext( let block_ref =
module.context_ref, LLVMCreateBasicBlockInContext(module.context_ref, into_cstring(&block.data.name).as_ptr());
into_cstring(&block.data.name).as_ptr(),
);
LLVMAppendExistingBasicBlock(own_function.value_ref, block_ref); LLVMAppendExistingBasicBlock(own_function.value_ref, block_ref);
module.blocks.insert(block.value, block_ref); module.blocks.insert(block.value, block_ref);
} }
@ -722,22 +688,13 @@ impl BlockHolder {
.data .data
.terminator .terminator
.clone() .clone()
.expect(&format!( .expect(&format!("Block {} does not have a terminator!", self.data.name))
"Block {} does not have a terminator!",
self.data.name
))
.compile(module, function, block_ref); .compile(module, function, block_ref);
if let Some(location) = &self.data.terminator_location { if let Some(location) = &self.data.terminator_location {
LLVMInstructionSetDebugLoc( LLVMInstructionSetDebugLoc(
term_instr.value_ref, term_instr.value_ref,
*module *module.debug.as_ref().unwrap().locations.get(&location).unwrap(),
.debug
.as_ref()
.unwrap()
.locations
.get(&location)
.unwrap(),
); );
} }
} }
@ -745,12 +702,7 @@ impl BlockHolder {
} }
impl InstructionHolder { impl InstructionHolder {
unsafe fn compile( unsafe fn compile(&self, module: &LLVMModule, function: &LLVMFunction, _block: LLVMBasicBlockRef) -> LLVMValue {
&self,
module: &LLVMModule,
function: &LLVMFunction,
_block: LLVMBasicBlockRef,
) -> LLVMValue {
let _ty = self.value.get_type(module.builder).unwrap(); let _ty = self.value.get_type(module.builder).unwrap();
let name = into_cstring(self.name.clone()); let name = into_cstring(self.name.clone());
let val = unsafe { let val = unsafe {
@ -829,7 +781,7 @@ impl InstructionHolder {
LLVMBuildICmp( LLVMBuildICmp(
module.builder_ref, module.builder_ref,
// Signedness from LHS // Signedness from LHS
pred.as_llvm_int(lhs._ty.signed()), pred.as_llvm_int(lhs.ty.category().signed()),
lhs.value_ref, lhs.value_ref,
rhs_val, rhs_val,
name.as_ptr(), name.as_ptr(),
@ -909,15 +861,12 @@ impl InstructionHolder {
); );
store store
} }
ArrayAlloca(ty, len) => { ArrayAlloca(ty, len) => LLVMBuildArrayAlloca(
let array_len = ConstValue::U16(*len as u16).as_llvm(module);
LLVMBuildArrayAlloca(
module.builder_ref, module.builder_ref,
ty.as_llvm(module.context_ref, &module.types), ty.as_llvm(module.context_ref, &module.types),
array_len, module.values.get(&len).unwrap().value_ref,
name.as_ptr(), name.as_ptr(),
) ),
}
GetElemPtr(arr, indices) => { GetElemPtr(arr, indices) => {
let t = arr.get_type(module.builder).unwrap(); let t = arr.get_type(module.builder).unwrap();
let Type::Ptr(elem_t) = t else { panic!() }; let Type::Ptr(elem_t) = t else { panic!() };
@ -1033,8 +982,7 @@ impl InstructionHolder {
unsafe { unsafe {
let mut addr = Vec::<u64>::new(); let mut addr = Vec::<u64>::new();
let expr = let expr = LLVMDIBuilderCreateExpression(debug.builder, addr.as_mut_ptr(), addr.len());
LLVMDIBuilderCreateExpression(debug.builder, addr.as_mut_ptr(), addr.len());
let location = LLVMDIBuilderCreateDebugLocation( let location = LLVMDIBuilderCreateDebugLocation(
module.context_ref, module.context_ref,
@ -1045,26 +993,22 @@ impl InstructionHolder {
); );
match record.kind { match record.kind {
DebugRecordKind::Declare(instruction_value) => { DebugRecordKind::Declare(instruction_value) => LLVMDIBuilderInsertDeclareRecordBefore(
LLVMDIBuilderInsertDeclareRecordBefore(
debug.builder, debug.builder,
module.values.get(&instruction_value).unwrap().value_ref, module.values.get(&instruction_value).unwrap().value_ref,
*debug.metadata.get(&record.variable).unwrap(), *debug.metadata.get(&record.variable).unwrap(),
expr, expr,
location, location,
val, val,
) ),
} DebugRecordKind::Value(instruction_value) => LLVMDIBuilderInsertDbgValueRecordBefore(
DebugRecordKind::Value(instruction_value) => {
LLVMDIBuilderInsertDbgValueRecordBefore(
debug.builder, debug.builder,
module.values.get(&instruction_value).unwrap().value_ref, module.values.get(&instruction_value).unwrap().value_ref,
*debug.metadata.get(&record.variable).unwrap(), *debug.metadata.get(&record.variable).unwrap(),
expr, expr,
location, location,
val, val,
) ),
}
}; };
} }
} }
@ -1077,13 +1021,7 @@ impl InstructionHolder {
| LLVMValueKind::LLVMMemoryPhiValueKind => { | LLVMValueKind::LLVMMemoryPhiValueKind => {
LLVMInstructionSetDebugLoc( LLVMInstructionSetDebugLoc(
val, val,
*module *module.debug.as_ref().unwrap().locations.get(&location).unwrap(),
.debug
.as_ref()
.unwrap()
.locations
.get(&location)
.unwrap(),
); );
} }
_ => {} _ => {}
@ -1091,19 +1029,14 @@ impl InstructionHolder {
} }
} }
LLVMValue { LLVMValue {
_ty, ty: _ty,
value_ref: val, value_ref: val,
} }
} }
} }
impl TerminatorKind { impl TerminatorKind {
fn compile( fn compile(&self, module: &LLVMModule, _function: &LLVMFunction, _block: LLVMBasicBlockRef) -> LLVMValue {
&self,
module: &LLVMModule,
_function: &LLVMFunction,
_block: LLVMBasicBlockRef,
) -> LLVMValue {
let _ty = self.get_type(module.builder).unwrap(); let _ty = self.get_type(module.builder).unwrap();
let val = unsafe { let val = unsafe {
match self { match self {
@ -1125,7 +1058,7 @@ impl TerminatorKind {
} }
}; };
LLVMValue { LLVMValue {
_ty, ty: _ty,
value_ref: val, value_ref: val,
} }
} }
@ -1179,11 +1112,9 @@ impl ConstValue {
ConstValue::U32(val) => LLVMConstInt(t, *val as u64, 1), ConstValue::U32(val) => LLVMConstInt(t, *val as u64, 1),
ConstValue::U64(val) => LLVMConstInt(t, *val as u64, 1), ConstValue::U64(val) => LLVMConstInt(t, *val as u64, 1),
ConstValue::U128(val) => LLVMConstInt(t, *val as u64, 1), ConstValue::U128(val) => LLVMConstInt(t, *val as u64, 1),
ConstValue::Str(val) => LLVMBuildGlobalString( ConstValue::Str(val) => {
module.builder_ref, LLVMBuildGlobalString(module.builder_ref, into_cstring(val).as_ptr(), c"string".as_ptr())
into_cstring(val).as_ptr(), }
c"string".as_ptr(),
),
ConstValue::F16(val) => LLVMConstReal(t, *val as f64), ConstValue::F16(val) => LLVMConstReal(t, *val as f64),
ConstValue::F32B(val) => LLVMConstReal(t, *val as f64), ConstValue::F32B(val) => LLVMConstReal(t, *val as f64),
ConstValue::F32(val) => LLVMConstReal(t, *val as f64), ConstValue::F32(val) => LLVMConstReal(t, *val as f64),
@ -1197,11 +1128,7 @@ impl ConstValue {
} }
impl Type { impl Type {
fn as_llvm( fn as_llvm(&self, context: LLVMContextRef, typemap: &HashMap<TypeValue, LLVMTypeRef>) -> LLVMTypeRef {
&self,
context: LLVMContextRef,
typemap: &HashMap<TypeValue, LLVMTypeRef>,
) -> LLVMTypeRef {
use Type::*; use Type::*;
unsafe { unsafe {
match self { match self {

View File

@ -375,7 +375,7 @@ pub enum Instr {
Alloca(Type), Alloca(Type),
Load(InstructionValue, Type), Load(InstructionValue, Type),
Store(InstructionValue, InstructionValue), Store(InstructionValue, InstructionValue),
ArrayAlloca(Type, u32), ArrayAlloca(Type, InstructionValue),
GetElemPtr(InstructionValue, Vec<InstructionValue>), GetElemPtr(InstructionValue, Vec<InstructionValue>),
GetStructElemPtr(InstructionValue, u32), GetStructElemPtr(InstructionValue, u32),
ExtractValue(InstructionValue, u32), ExtractValue(InstructionValue, u32),
@ -533,77 +533,56 @@ impl ConstValue {
} }
} }
impl Type { #[derive(PartialEq, Eq, PartialOrd, Ord, Debug)]
enum TypeCategory {
SignedInteger,
UnsignedInteger,
Void,
Real,
Ptr,
CustomType,
Array,
}
impl TypeCategory {
pub fn comparable(&self) -> bool { pub fn comparable(&self) -> bool {
match self { match self {
Type::I8 => true, TypeCategory::SignedInteger => true,
Type::I16 => true, TypeCategory::UnsignedInteger => true,
Type::I32 => true, TypeCategory::Real => true,
Type::I64 => true, _ => false,
Type::I128 => true,
Type::U8 => true,
Type::U16 => true,
Type::U32 => true,
Type::U64 => true,
Type::U128 => true,
Type::Bool => true,
Type::Void => false,
Type::Ptr(_) => false,
Type::CustomType(_) => false,
Type::Array(_, _) => false,
Type::F16 => true,
Type::F32B => true,
Type::F32 => true,
Type::F64 => true,
Type::F80 => true,
Type::F128 => true,
Type::F128PPC => true,
} }
} }
pub fn signed(&self) -> bool { pub fn signed(&self) -> bool {
match self { match self {
Type::I8 => true, TypeCategory::SignedInteger => true,
Type::I16 => true, _ => false,
Type::I32 => true,
Type::I64 => true,
Type::I128 => true,
Type::U8 => false,
Type::U16 => false,
Type::U32 => false,
Type::U64 => false,
Type::U128 => false,
Type::Bool => false,
Type::Void => false,
Type::Ptr(_) => false,
Type::CustomType(_) => false,
Type::Array(_, _) => false,
Type::F16 => true,
Type::F32B => true,
Type::F32 => true,
Type::F64 => true,
Type::F80 => true,
Type::F128 => true,
Type::F128PPC => true,
} }
} }
pub fn integer(&self) -> bool {
match self {
TypeCategory::SignedInteger => true,
TypeCategory::UnsignedInteger => true,
_ => false,
}
}
}
impl Type {
pub fn category(&self) -> TypeCategory { pub fn category(&self) -> TypeCategory {
match self { match self {
Type::I8 Type::I8 | Type::I16 | Type::I32 | Type::I64 | Type::I128 => TypeCategory::SignedInteger,
| Type::I16 Type::U8 | Type::U16 | Type::U32 | Type::U64 | Type::U128 => TypeCategory::UnsignedInteger,
| Type::I32
| Type::I64
| Type::I128
| Type::U8
| Type::U16
| Type::U32
| Type::U64
| Type::U128 => TypeCategory::Integer,
Type::F16 | Type::F32B | Type::F32 | Type::F64 | Type::F80 | Type::F128 | Type::F128PPC => { Type::F16 | Type::F32B | Type::F32 | Type::F64 | Type::F80 | Type::F128 | Type::F128PPC => {
TypeCategory::Real TypeCategory::Real
} }
Type::Bool | Type::Void | Type::CustomType(_) | Type::Array(_, _) | Type::Ptr(_) => TypeCategory::Other, Type::Bool => TypeCategory::UnsignedInteger,
Type::Void => TypeCategory::Void,
Type::CustomType(_) => TypeCategory::CustomType,
Type::Array(_, _) => TypeCategory::Array,
Type::Ptr(_) => TypeCategory::Ptr,
} }
} }
@ -656,13 +635,6 @@ impl Type {
} }
} }
#[derive(PartialEq, Eq, PartialOrd, Ord)]
pub enum TypeCategory {
Integer,
Real,
Other,
}
impl TerminatorKind { impl TerminatorKind {
pub(crate) fn get_type(&self, builder: &Builder) -> CompileResult<Type> { pub(crate) fn get_type(&self, builder: &Builder) -> CompileResult<Type> {
use TerminatorKind::*; use TerminatorKind::*;

View File

@ -1,4 +1,4 @@
use reid_lib::{builder::InstructionValue, CmpPredicate, Instr}; use reid_lib::{builder::InstructionValue, CmpPredicate, ConstValue, Instr};
use crate::{ use crate::{
codegen::{ErrorKind, StackValueKind}, codegen::{ErrorKind, StackValueKind},
@ -46,6 +46,22 @@ pub fn get_intrinsic_assoc_func(ty: &TypeKind, name: &str) -> Option<FunctionDef
parameters: Vec::new(), parameters: Vec::new(),
kind: FunctionDefinitionKind::Intrinsic(Box::new(IntrinsicSizeOf(ty.clone()))), kind: FunctionDefinitionKind::Intrinsic(Box::new(IntrinsicSizeOf(ty.clone()))),
}), }),
"alloca" => Some(FunctionDefinition {
name: "alloca".to_owned(),
is_pub: true,
is_imported: false,
return_type: TypeKind::UserPtr(Box::new(ty.clone())),
parameters: vec![(String::from("size"), TypeKind::U64)],
kind: FunctionDefinitionKind::Intrinsic(Box::new(IntrinsicAlloca(ty.clone()))),
}),
"null" => Some(FunctionDefinition {
name: "null".to_owned(),
is_pub: true,
is_imported: false,
return_type: TypeKind::UserPtr(Box::new(ty.clone())),
parameters: Vec::new(),
kind: FunctionDefinitionKind::Intrinsic(Box::new(IntrinsicNullPtr(ty.clone()))),
}),
_ => None, _ => None,
} }
} }
@ -233,14 +249,8 @@ where
} }
} }
#[derive(Clone)] #[derive(Clone, Debug)]
pub struct IntrinsicSizeOf(TypeKind); pub struct IntrinsicSizeOf(TypeKind);
impl std::fmt::Debug for IntrinsicSizeOf {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_tuple("IntrinsicSizeOf").finish()
}
}
impl IntrinsicFunction for IntrinsicSizeOf { impl IntrinsicFunction for IntrinsicSizeOf {
fn codegen<'ctx, 'a>(&self, scope: &mut Scope<'ctx, 'a>, _: &[StackValue]) -> Result<StackValue, ErrorKind> { fn codegen<'ctx, 'a>(&self, scope: &mut Scope<'ctx, 'a>, _: &[StackValue]) -> Result<StackValue, ErrorKind> {
let instr = scope let instr = scope
@ -251,6 +261,32 @@ impl IntrinsicFunction for IntrinsicSizeOf {
} }
} }
#[derive(Clone, Debug)]
pub struct IntrinsicAlloca(TypeKind);
impl IntrinsicFunction for IntrinsicAlloca {
fn codegen<'ctx, 'a>(&self, scope: &mut Scope<'ctx, 'a>, params: &[StackValue]) -> Result<StackValue, ErrorKind> {
let amount = params.get(0).unwrap();
let instr = scope
.block
.build(Instr::ArrayAlloca(self.0.get_type(scope.type_values), amount.instr()))
.unwrap();
Ok(StackValue(StackValueKind::Literal(instr), self.0.clone()))
}
}
#[derive(Clone, Debug)]
pub struct IntrinsicNullPtr(TypeKind);
impl IntrinsicFunction for IntrinsicNullPtr {
fn codegen<'ctx, 'a>(&self, scope: &mut Scope<'ctx, 'a>, _: &[StackValue]) -> Result<StackValue, ErrorKind> {
let zero = scope.block.build(Instr::Constant(ConstValue::I8(0))).unwrap();
let instr = scope
.block
.build(Instr::IntToPtr(zero, self.0.get_type(scope.type_values)))
.unwrap();
Ok(StackValue(StackValueKind::Literal(instr), self.0.clone()))
}
}
// impl IntrinsicFunction for IntrinsicIAdd { // impl IntrinsicFunction for IntrinsicIAdd {
// fn codegen<'ctx, 'a>( // fn codegen<'ctx, 'a>(
// &self, // &self,