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("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;
|
||||||
}
|
}
|
||||||
|
@ -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),
|
||||||
|
@ -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);
|
module.builder_ref,
|
||||||
LLVMBuildArrayAlloca(
|
ty.as_llvm(module.context_ref, &module.types),
|
||||||
module.builder_ref,
|
module.values.get(&len).unwrap().value_ref,
|
||||||
ty.as_llvm(module.context_ref, &module.types),
|
name.as_ptr(),
|
||||||
array_len,
|
),
|
||||||
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(
|
||||||
}
|
debug.builder,
|
||||||
DebugRecordKind::Value(instruction_value) => {
|
module.values.get(&instruction_value).unwrap().value_ref,
|
||||||
LLVMDIBuilderInsertDbgValueRecordBefore(
|
*debug.metadata.get(&record.variable).unwrap(),
|
||||||
debug.builder,
|
expr,
|
||||||
module.values.get(&instruction_value).unwrap().value_ref,
|
location,
|
||||||
*debug.metadata.get(&record.variable).unwrap(),
|
val,
|
||||||
expr,
|
),
|
||||||
location,
|
|
||||||
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 {
|
||||||
|
@ -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::*;
|
||||||
|
@ -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,
|
||||||
|
Loading…
Reference in New Issue
Block a user