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("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;
}

View File

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

View File

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

View File

@ -375,7 +375,7 @@ pub enum Instr {
Alloca(Type),
Load(InstructionValue, Type),
Store(InstructionValue, InstructionValue),
ArrayAlloca(Type, u32),
ArrayAlloca(Type, InstructionValue),
GetElemPtr(InstructionValue, Vec<InstructionValue>),
GetStructElemPtr(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 {
match self {
Type::I8 => true,
Type::I16 => true,
Type::I32 => true,
Type::I64 => true,
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,
TypeCategory::SignedInteger => true,
TypeCategory::UnsignedInteger => true,
TypeCategory::Real => true,
_ => false,
}
}
pub fn signed(&self) -> bool {
match self {
Type::I8 => true,
Type::I16 => true,
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,
TypeCategory::SignedInteger => true,
_ => false,
}
}
pub fn integer(&self) -> bool {
match self {
TypeCategory::SignedInteger => true,
TypeCategory::UnsignedInteger => true,
_ => false,
}
}
}
impl Type {
pub fn category(&self) -> TypeCategory {
match self {
Type::I8
| Type::I16
| Type::I32
| Type::I64
| Type::I128
| Type::U8
| Type::U16
| Type::U32
| Type::U64
| Type::U128 => TypeCategory::Integer,
Type::I8 | Type::I16 | Type::I32 | Type::I64 | Type::I128 => TypeCategory::SignedInteger,
Type::U8 | Type::U16 | Type::U32 | Type::U64 | Type::U128 => TypeCategory::UnsignedInteger,
Type::F16 | Type::F32B | Type::F32 | Type::F64 | Type::F80 | Type::F128 | Type::F128PPC => {
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 {
pub(crate) fn get_type(&self, builder: &Builder) -> CompileResult<Type> {
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::{
codegen::{ErrorKind, StackValueKind},
@ -46,6 +46,22 @@ pub fn get_intrinsic_assoc_func(ty: &TypeKind, name: &str) -> Option<FunctionDef
parameters: Vec::new(),
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,
}
}
@ -233,14 +249,8 @@ where
}
}
#[derive(Clone)]
#[derive(Clone, Debug)]
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 {
fn codegen<'ctx, 'a>(&self, scope: &mut Scope<'ctx, 'a>, _: &[StackValue]) -> Result<StackValue, ErrorKind> {
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 {
// fn codegen<'ctx, 'a>(
// &self,