Implement builtin associated alloca and nullptr
This commit is contained in:
parent
acc2964305
commit
7b27f30b9e
@ -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;
|
||||
}
|
||||
|
@ -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),
|
||||
|
@ -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 {
|
||||
|
@ -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::*;
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user