Compare commits
No commits in common. "233ddb60f7f31c67ae1399e8eaf68ac549e8e2c4" and "97fc468d78e7ec80ad08b193a2f1eb630be9508d" have entirely different histories.
233ddb60f7
...
97fc468d78
@ -4,8 +4,8 @@
|
|||||||
use std::{cell::RefCell, rc::Rc};
|
use std::{cell::RefCell, rc::Rc};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
BlockData, CustomTypeKind, FunctionData, Instr, InstructionData, ModuleData, NamedStruct,
|
BlockData, ConstValue, FunctionData, Instr, InstructionData, ModuleData, TerminatorKind, Type,
|
||||||
TerminatorKind, Type, TypeData, util::match_types,
|
TypeData, util::match_types,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Clone, Hash, Copy, PartialEq, Eq)]
|
#[derive(Clone, Hash, Copy, PartialEq, Eq)]
|
||||||
@ -80,16 +80,6 @@ impl Builder {
|
|||||||
value
|
value
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) unsafe fn add_type(&self, mod_val: &ModuleValue, data: TypeData) -> TypeValue {
|
|
||||||
unsafe {
|
|
||||||
let mut modules = self.modules.borrow_mut();
|
|
||||||
let module = modules.get_unchecked_mut(mod_val.0);
|
|
||||||
let value = TypeValue(module.value, module.types.len());
|
|
||||||
module.types.push(TypeHolder { value, data });
|
|
||||||
value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) unsafe fn add_function(
|
pub(crate) unsafe fn add_function(
|
||||||
&self,
|
&self,
|
||||||
mod_val: &ModuleValue,
|
mod_val: &ModuleValue,
|
||||||
@ -223,18 +213,6 @@ impl Builder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) unsafe fn type_data(&self, value: &TypeValue) -> TypeData {
|
|
||||||
unsafe {
|
|
||||||
self.modules
|
|
||||||
.borrow()
|
|
||||||
.get_unchecked(value.0.0)
|
|
||||||
.types
|
|
||||||
.get_unchecked(value.1)
|
|
||||||
.data
|
|
||||||
.clone()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn find_module<'ctx>(&'ctx self, value: ModuleValue) -> ModuleHolder {
|
pub(crate) fn find_module<'ctx>(&'ctx self, value: ModuleValue) -> ModuleHolder {
|
||||||
unsafe { self.modules.borrow().get_unchecked(value.0).clone() }
|
unsafe { self.modules.borrow().get_unchecked(value.0).clone() }
|
||||||
}
|
}
|
||||||
@ -244,15 +222,16 @@ impl Builder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn check_instruction(&self, instruction: &InstructionValue) -> Result<(), ()> {
|
pub fn check_instruction(&self, instruction: &InstructionValue) -> Result<(), ()> {
|
||||||
|
use super::Instr::*;
|
||||||
unsafe {
|
unsafe {
|
||||||
match self.instr_data(&instruction).kind {
|
match self.instr_data(&instruction).kind {
|
||||||
Instr::Param(_) => Ok(()),
|
Param(_) => Ok(()),
|
||||||
Instr::Constant(_) => Ok(()),
|
Constant(_) => Ok(()),
|
||||||
Instr::Add(lhs, rhs) => match_types(&lhs, &rhs, &self).map(|_| ()),
|
Add(lhs, rhs) => match_types(&lhs, &rhs, &self).map(|_| ()),
|
||||||
Instr::Sub(lhs, rhs) => match_types(&lhs, &rhs, &self).map(|_| ()),
|
Sub(lhs, rhs) => match_types(&lhs, &rhs, &self).map(|_| ()),
|
||||||
Instr::Mult(lhs, rhs) => match_types(&lhs, &rhs, &self).map(|_| ()),
|
Mult(lhs, rhs) => match_types(&lhs, &rhs, &self).map(|_| ()),
|
||||||
Instr::And(lhs, rhs) => match_types(&lhs, &rhs, &self).map(|_| ()),
|
And(lhs, rhs) => match_types(&lhs, &rhs, &self).map(|_| ()),
|
||||||
Instr::ICmp(_, lhs, rhs) => {
|
ICmp(_, lhs, rhs) => {
|
||||||
let t = match_types(&lhs, &rhs, self)?;
|
let t = match_types(&lhs, &rhs, self)?;
|
||||||
if t.comparable() {
|
if t.comparable() {
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -260,7 +239,7 @@ impl Builder {
|
|||||||
Err(()) // TODO error: Types not comparable
|
Err(()) // TODO error: Types not comparable
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Instr::FunctionCall(fun, params) => {
|
FunctionCall(fun, params) => {
|
||||||
let param_types = self.function_data(&fun).params;
|
let param_types = self.function_data(&fun).params;
|
||||||
if param_types.len() != params.len() {
|
if param_types.len() != params.len() {
|
||||||
return Err(()); // TODO error: invalid amount of params
|
return Err(()); // TODO error: invalid amount of params
|
||||||
@ -272,7 +251,7 @@ impl Builder {
|
|||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
Instr::Phi(vals) => {
|
Phi(vals) => {
|
||||||
let mut iter = vals.iter();
|
let mut iter = vals.iter();
|
||||||
// TODO error: Phi must contain at least one item
|
// TODO error: Phi must contain at least one item
|
||||||
|
|
||||||
@ -286,53 +265,40 @@ impl Builder {
|
|||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
Instr::Alloca(_, _) => Ok(()),
|
Alloca(_, _) => Ok(()),
|
||||||
Instr::Load(ptr, load_ty) => {
|
Load(ptr, load_ty) => {
|
||||||
let ptr_ty = ptr.get_type(&self)?;
|
if let Ok(ptr_ty) = ptr.get_type(&self) {
|
||||||
if let Type::Ptr(ptr_ty_inner) = ptr_ty {
|
if let Type::Ptr(ptr_ty_inner) = ptr_ty {
|
||||||
if *ptr_ty_inner == load_ty {
|
if *ptr_ty_inner == load_ty {
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
Err(()) // TODO error: inner type mismatch
|
Err(())
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Err(()) // TODO error: not a pointer
|
Err(())
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Err(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Instr::Store(ptr, _) => {
|
Store(ptr, _) => {
|
||||||
let ty = ptr.get_type(&self)?;
|
if let Ok(ty) = ptr.get_type(&self) {
|
||||||
if let Type::Ptr(_) = ty {
|
if let Type::Ptr(_) = ty {
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
Err(()) // TODO error: not a pointer
|
Err(())
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Err(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Instr::ArrayAlloca(_, _) => Ok(()),
|
ArrayAlloca(_, _) => Ok(()),
|
||||||
Instr::GetElemPtr(ptr_val, _) => {
|
GetElemPtr(arr, _) => {
|
||||||
let ptr_ty = ptr_val.get_type(&self)?;
|
let arr_ty = arr.get_type(&self)?;
|
||||||
if let Type::Ptr(_) = ptr_ty {
|
if let Type::Ptr(_) = arr_ty {
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
Err(()) // TODO error: not a pointer
|
Err(())
|
||||||
}
|
|
||||||
}
|
|
||||||
Instr::GetStructElemPtr(ptr_val, idx) => {
|
|
||||||
let ptr_ty = ptr_val.get_type(&self)?;
|
|
||||||
if let Type::Ptr(ty) = ptr_ty {
|
|
||||||
if let Type::CustomType(val) = *ty {
|
|
||||||
match self.type_data(&val).kind {
|
|
||||||
CustomTypeKind::NamedStruct(NamedStruct(_, fields)) => {
|
|
||||||
if fields.len() <= idx as usize {
|
|
||||||
return Err(()); // TODO error: no such field
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
} else {
|
|
||||||
Err(()) // TODO error: not a struct
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Err(()) // TODO error: not a pointer
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -373,3 +339,102 @@ impl Builder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl InstructionValue {
|
||||||
|
pub(crate) fn get_type(&self, builder: &Builder) -> Result<Type, ()> {
|
||||||
|
use Instr::*;
|
||||||
|
unsafe {
|
||||||
|
match &builder.instr_data(self).kind {
|
||||||
|
Param(nth) => builder
|
||||||
|
.function_data(&self.0.0)
|
||||||
|
.params
|
||||||
|
.get(*nth)
|
||||||
|
.cloned()
|
||||||
|
.ok_or(()),
|
||||||
|
Constant(c) => Ok(c.get_type()),
|
||||||
|
Add(lhs, rhs) => match_types(lhs, rhs, &builder),
|
||||||
|
Sub(lhs, rhs) => match_types(lhs, rhs, &builder),
|
||||||
|
Mult(lhs, rhs) => match_types(lhs, rhs, &builder),
|
||||||
|
And(lhs, rhs) => match_types(lhs, rhs, &builder),
|
||||||
|
ICmp(_, _, _) => Ok(Type::Bool),
|
||||||
|
FunctionCall(function_value, _) => Ok(builder.function_data(function_value).ret),
|
||||||
|
Phi(values) => values.first().ok_or(()).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),
|
||||||
|
ArrayAlloca(ty, _) => Ok(Type::Ptr(Box::new(ty.clone()))),
|
||||||
|
GetElemPtr(ptr, _) => ptr.get_type(builder),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ConstValue {
|
||||||
|
pub fn get_type(&self) -> Type {
|
||||||
|
use Type::*;
|
||||||
|
match self {
|
||||||
|
ConstValue::I8(_) => I8,
|
||||||
|
ConstValue::I16(_) => I16,
|
||||||
|
ConstValue::I32(_) => I32,
|
||||||
|
ConstValue::I64(_) => I64,
|
||||||
|
ConstValue::I128(_) => I128,
|
||||||
|
ConstValue::U8(_) => U8,
|
||||||
|
ConstValue::U16(_) => U16,
|
||||||
|
ConstValue::U32(_) => U32,
|
||||||
|
ConstValue::U64(_) => U64,
|
||||||
|
ConstValue::U128(_) => U128,
|
||||||
|
ConstValue::String(_) => Ptr(Box::new(I8)),
|
||||||
|
ConstValue::Bool(_) => Bool,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Type {
|
||||||
|
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,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TerminatorKind {
|
||||||
|
pub(crate) fn get_type(&self, builder: &Builder) -> Result<Type, ()> {
|
||||||
|
use TerminatorKind::*;
|
||||||
|
match self {
|
||||||
|
Ret(instr_val) => instr_val.get_type(builder),
|
||||||
|
RetVoid => Ok(Type::Void),
|
||||||
|
Br(_) => Ok(Type::Void),
|
||||||
|
CondBr(_, _, _) => Ok(Type::Void),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -20,11 +20,7 @@ use llvm_sys::{
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::util::{ErrorMessageHolder, MemoryBufferHolder, from_cstring, into_cstring};
|
||||||
CustomTypeKind, NamedStruct,
|
|
||||||
builder::{TypeHolder, TypeValue},
|
|
||||||
util::{ErrorMessageHolder, MemoryBufferHolder, from_cstring, into_cstring},
|
|
||||||
};
|
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
CmpPredicate, ConstValue, Context, TerminatorKind, Type,
|
CmpPredicate, ConstValue, Context, TerminatorKind, Type,
|
||||||
@ -179,7 +175,6 @@ pub struct LLVMModule<'a> {
|
|||||||
functions: HashMap<FunctionValue, LLVMFunction>,
|
functions: HashMap<FunctionValue, LLVMFunction>,
|
||||||
blocks: HashMap<BlockValue, LLVMBasicBlockRef>,
|
blocks: HashMap<BlockValue, LLVMBasicBlockRef>,
|
||||||
values: HashMap<InstructionValue, LLVMValue>,
|
values: HashMap<InstructionValue, LLVMValue>,
|
||||||
types: HashMap<TypeValue, LLVMTypeRef>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
@ -201,18 +196,18 @@ impl ModuleHolder {
|
|||||||
context.context_ref,
|
context.context_ref,
|
||||||
);
|
);
|
||||||
|
|
||||||
// Compile the contents
|
for _ty in &self.types {
|
||||||
|
todo!("Do something with types!");
|
||||||
let mut types = HashMap::new();
|
|
||||||
for ty in &self.types {
|
|
||||||
types.insert(ty.value, ty.compile_type(context, &types));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Compile the contents
|
||||||
|
|
||||||
let mut functions = HashMap::new();
|
let mut functions = HashMap::new();
|
||||||
|
|
||||||
for function in &self.functions {
|
for function in &self.functions {
|
||||||
functions.insert(
|
functions.insert(
|
||||||
function.value,
|
function.value,
|
||||||
function.compile_signature(context, module_ref, &types),
|
function.compile_signature(context, module_ref),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -222,7 +217,6 @@ impl ModuleHolder {
|
|||||||
builder_ref: context.builder_ref,
|
builder_ref: context.builder_ref,
|
||||||
module_ref,
|
module_ref,
|
||||||
functions,
|
functions,
|
||||||
types,
|
|
||||||
blocks: HashMap::new(),
|
blocks: HashMap::new(),
|
||||||
values: HashMap::new(),
|
values: HashMap::new(),
|
||||||
};
|
};
|
||||||
@ -236,46 +230,19 @@ impl ModuleHolder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TypeHolder {
|
|
||||||
unsafe fn compile_type(
|
|
||||||
&self,
|
|
||||||
context: &LLVMContext,
|
|
||||||
types: &HashMap<TypeValue, LLVMTypeRef>,
|
|
||||||
) -> LLVMTypeRef {
|
|
||||||
unsafe {
|
|
||||||
match &self.data.kind {
|
|
||||||
CustomTypeKind::NamedStruct(named_struct) => {
|
|
||||||
let mut elem_types = Vec::new();
|
|
||||||
for ty in &named_struct.1 {
|
|
||||||
elem_types.push(ty.as_llvm(context.context_ref, types));
|
|
||||||
}
|
|
||||||
let struct_ty = LLVMStructTypeInContext(
|
|
||||||
context.context_ref,
|
|
||||||
elem_types.as_mut_ptr(),
|
|
||||||
elem_types.len() as u32,
|
|
||||||
0,
|
|
||||||
);
|
|
||||||
struct_ty
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FunctionHolder {
|
impl FunctionHolder {
|
||||||
unsafe fn compile_signature(
|
unsafe fn compile_signature(
|
||||||
&self,
|
&self,
|
||||||
context: &LLVMContext,
|
context: &LLVMContext,
|
||||||
module_ref: LLVMModuleRef,
|
module_ref: LLVMModuleRef,
|
||||||
types: &HashMap<TypeValue, LLVMTypeRef>,
|
|
||||||
) -> LLVMFunction {
|
) -> LLVMFunction {
|
||||||
unsafe {
|
unsafe {
|
||||||
let ret_type = self.data.ret.as_llvm(context.context_ref, types);
|
let ret_type = self.data.ret.as_llvm(context.context_ref);
|
||||||
let mut param_types: Vec<LLVMTypeRef> = self
|
let mut param_types: Vec<LLVMTypeRef> = self
|
||||||
.data
|
.data
|
||||||
.params
|
.params
|
||||||
.iter()
|
.iter()
|
||||||
.map(|t| t.as_llvm(context.context_ref, types))
|
.map(|t| t.as_llvm(context.context_ref))
|
||||||
.collect();
|
.collect();
|
||||||
let param_ptr = param_types.as_mut_ptr();
|
let param_ptr = param_types.as_mut_ptr();
|
||||||
let param_len = param_types.len();
|
let param_len = param_types.len();
|
||||||
@ -379,7 +346,7 @@ impl InstructionHolder {
|
|||||||
use super::Instr::*;
|
use super::Instr::*;
|
||||||
match &self.data.kind {
|
match &self.data.kind {
|
||||||
Param(nth) => LLVMGetParam(function.value_ref, *nth as u32),
|
Param(nth) => LLVMGetParam(function.value_ref, *nth as u32),
|
||||||
Constant(val) => val.as_llvm(module),
|
Constant(val) => val.as_llvm(module.context_ref, module.builder_ref),
|
||||||
Add(lhs, rhs) => {
|
Add(lhs, rhs) => {
|
||||||
let lhs_val = module.values.get(&lhs).unwrap().value_ref;
|
let lhs_val = module.values.get(&lhs).unwrap().value_ref;
|
||||||
let rhs_val = module.values.get(&rhs).unwrap().value_ref;
|
let rhs_val = module.values.get(&rhs).unwrap().value_ref;
|
||||||
@ -445,7 +412,7 @@ impl InstructionHolder {
|
|||||||
}
|
}
|
||||||
let phi = LLVMBuildPhi(
|
let phi = LLVMBuildPhi(
|
||||||
module.builder_ref,
|
module.builder_ref,
|
||||||
_ty.as_llvm(module.context_ref, &module.types),
|
_ty.as_llvm(module.context_ref),
|
||||||
c"phi".as_ptr(),
|
c"phi".as_ptr(),
|
||||||
);
|
);
|
||||||
LLVMAddIncoming(
|
LLVMAddIncoming(
|
||||||
@ -458,12 +425,12 @@ impl InstructionHolder {
|
|||||||
}
|
}
|
||||||
Alloca(name, ty) => LLVMBuildAlloca(
|
Alloca(name, ty) => LLVMBuildAlloca(
|
||||||
module.builder_ref,
|
module.builder_ref,
|
||||||
ty.as_llvm(module.context_ref, &module.types),
|
ty.as_llvm(module.context_ref),
|
||||||
into_cstring(name).as_ptr(),
|
into_cstring(name).as_ptr(),
|
||||||
),
|
),
|
||||||
Load(ptr, ty) => LLVMBuildLoad2(
|
Load(ptr, ty) => LLVMBuildLoad2(
|
||||||
module.builder_ref,
|
module.builder_ref,
|
||||||
ty.as_llvm(module.context_ref, &module.types),
|
ty.as_llvm(module.context_ref),
|
||||||
module.values.get(&ptr).unwrap().value_ref,
|
module.values.get(&ptr).unwrap().value_ref,
|
||||||
c"load".as_ptr(),
|
c"load".as_ptr(),
|
||||||
),
|
),
|
||||||
@ -473,10 +440,11 @@ impl InstructionHolder {
|
|||||||
module.values.get(&ptr).unwrap().value_ref,
|
module.values.get(&ptr).unwrap().value_ref,
|
||||||
),
|
),
|
||||||
ArrayAlloca(ty, len) => {
|
ArrayAlloca(ty, len) => {
|
||||||
let array_len = ConstValue::U16(*len as u16).as_llvm(module);
|
let array_len = ConstValue::U16(*len as u16)
|
||||||
|
.as_llvm(module.context_ref, module.builder_ref);
|
||||||
LLVMBuildArrayAlloca(
|
LLVMBuildArrayAlloca(
|
||||||
module.builder_ref,
|
module.builder_ref,
|
||||||
ty.as_llvm(module.context_ref, &module.types),
|
ty.as_llvm(module.context_ref),
|
||||||
array_len,
|
array_len,
|
||||||
c"array_alloca".as_ptr(),
|
c"array_alloca".as_ptr(),
|
||||||
)
|
)
|
||||||
@ -485,46 +453,20 @@ impl InstructionHolder {
|
|||||||
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!() };
|
||||||
|
|
||||||
let mut llvm_indices: Vec<_> = indices
|
let mut indices: Vec<_> = indices
|
||||||
.iter()
|
.iter()
|
||||||
.map(|idx| ConstValue::U32(*idx).as_llvm(module))
|
.map(|idx| {
|
||||||
|
ConstValue::U32(*idx).as_llvm(module.context_ref, module.builder_ref)
|
||||||
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
LLVMBuildGEP2(
|
LLVMBuildGEP2(
|
||||||
module.builder_ref,
|
module.builder_ref,
|
||||||
elem_t.as_llvm(module.context_ref, &module.types),
|
elem_t.as_llvm(module.context_ref),
|
||||||
module.values.get(arr).unwrap().value_ref,
|
module.values.get(arr).unwrap().value_ref,
|
||||||
llvm_indices.as_mut_ptr(),
|
indices.as_mut_ptr(),
|
||||||
llvm_indices.len() as u32,
|
indices.len() as u32,
|
||||||
into_cstring(format!(
|
c"array_gep".as_ptr(),
|
||||||
"array_gep_{:?}",
|
|
||||||
indices
|
|
||||||
.iter()
|
|
||||||
.map(|v| v.to_string())
|
|
||||||
.collect::<Vec<_>>()
|
|
||||||
.join("_")
|
|
||||||
))
|
|
||||||
.as_ptr(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
GetStructElemPtr(struct_val, idx) => {
|
|
||||||
let t = struct_val.get_type(module.builder).unwrap();
|
|
||||||
dbg!(&t);
|
|
||||||
let Type::Ptr(struct_t) = t else { panic!() };
|
|
||||||
|
|
||||||
let type_fmt = if let Type::CustomType(type_val) = *struct_t {
|
|
||||||
format!("M{}T{}", type_val.0.0, type_val.1)
|
|
||||||
} else {
|
|
||||||
format!("{:?}", struct_t)
|
|
||||||
};
|
|
||||||
dbg!(idx);
|
|
||||||
|
|
||||||
LLVMBuildStructGEP2(
|
|
||||||
module.builder_ref,
|
|
||||||
struct_t.as_llvm(module.context_ref, &module.types),
|
|
||||||
module.values.get(struct_val).unwrap().value_ref,
|
|
||||||
*idx,
|
|
||||||
into_cstring(format!("struct.{}.{}.gep", type_fmt, idx)).as_ptr(),
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -590,9 +532,9 @@ impl CmpPredicate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl ConstValue {
|
impl ConstValue {
|
||||||
fn as_llvm(&self, module: &LLVMModule) -> LLVMValueRef {
|
fn as_llvm(&self, context: LLVMContextRef, builder: LLVMBuilderRef) -> LLVMValueRef {
|
||||||
unsafe {
|
unsafe {
|
||||||
let t = self.get_type().as_llvm(module.context_ref, &module.types);
|
let t = self.get_type().as_llvm(context);
|
||||||
match self {
|
match self {
|
||||||
ConstValue::Bool(val) => LLVMConstInt(t, *val as u64, 1),
|
ConstValue::Bool(val) => LLVMConstInt(t, *val as u64, 1),
|
||||||
ConstValue::I8(val) => LLVMConstInt(t, *val as u64, 1),
|
ConstValue::I8(val) => LLVMConstInt(t, *val as u64, 1),
|
||||||
@ -605,8 +547,8 @@ 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::StringPtr(val) => LLVMBuildGlobalStringPtr(
|
ConstValue::String(val) => LLVMBuildGlobalStringPtr(
|
||||||
module.builder_ref,
|
builder,
|
||||||
into_cstring(val).as_ptr(),
|
into_cstring(val).as_ptr(),
|
||||||
c"string".as_ptr(),
|
c"string".as_ptr(),
|
||||||
),
|
),
|
||||||
@ -616,11 +558,7 @@ impl ConstValue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Type {
|
impl Type {
|
||||||
fn as_llvm(
|
fn as_llvm(&self, context: LLVMContextRef) -> LLVMTypeRef {
|
||||||
&self,
|
|
||||||
context: LLVMContextRef,
|
|
||||||
typemap: &HashMap<TypeValue, LLVMTypeRef>,
|
|
||||||
) -> LLVMTypeRef {
|
|
||||||
use Type::*;
|
use Type::*;
|
||||||
unsafe {
|
unsafe {
|
||||||
match self {
|
match self {
|
||||||
@ -631,8 +569,7 @@ impl Type {
|
|||||||
I128 | U128 => LLVMInt128TypeInContext(context),
|
I128 | U128 => LLVMInt128TypeInContext(context),
|
||||||
Bool => LLVMInt1TypeInContext(context),
|
Bool => LLVMInt1TypeInContext(context),
|
||||||
Void => LLVMVoidTypeInContext(context),
|
Void => LLVMVoidTypeInContext(context),
|
||||||
Ptr(ty) => LLVMPointerType(ty.as_llvm(context, typemap), 0),
|
Ptr(ty) => LLVMPointerType(ty.as_llvm(context), 0),
|
||||||
CustomType(struct_ty) => *typemap.get(struct_ty).unwrap(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -99,12 +99,6 @@ impl Debug for InstructionValue {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Debug for TypeValue {
|
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
||||||
write!(f, "Ty[{:0>2}-{:0>2}]", &self.0.0, self.1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Debug for Instr {
|
impl Debug for Instr {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
@ -132,9 +126,6 @@ impl Debug for Instr {
|
|||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
.join(", "),
|
.join(", "),
|
||||||
),
|
),
|
||||||
Instr::GetStructElemPtr(instruction_value, index) => {
|
|
||||||
fmt_index(f, instruction_value, &index.to_string())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,9 +4,8 @@
|
|||||||
|
|
||||||
use std::{fmt::Debug, marker::PhantomData};
|
use std::{fmt::Debug, marker::PhantomData};
|
||||||
|
|
||||||
use builder::{BlockValue, Builder, FunctionValue, InstructionValue, ModuleValue, TypeValue};
|
use builder::{BlockValue, Builder, FunctionValue, InstructionValue, ModuleValue};
|
||||||
use debug::PrintableModule;
|
use debug::PrintableModule;
|
||||||
use util::match_types;
|
|
||||||
|
|
||||||
pub mod builder;
|
pub mod builder;
|
||||||
pub mod compile;
|
pub mod compile;
|
||||||
@ -77,15 +76,6 @@ impl<'ctx> Module<'ctx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn custom_type(&mut self, ty: CustomTypeKind) -> TypeValue {
|
|
||||||
unsafe {
|
|
||||||
let (name, kind) = match &ty {
|
|
||||||
CustomTypeKind::NamedStruct(NamedStruct(name, _)) => (name.clone(), ty),
|
|
||||||
};
|
|
||||||
self.builder.add_type(&self.value, TypeData { name, kind })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn value(&self) -> ModuleValue {
|
pub fn value(&self) -> ModuleValue {
|
||||||
self.value
|
self.value
|
||||||
}
|
}
|
||||||
@ -215,7 +205,6 @@ pub enum CmpPredicate {
|
|||||||
pub enum Instr {
|
pub enum Instr {
|
||||||
Param(usize),
|
Param(usize),
|
||||||
Constant(ConstValue),
|
Constant(ConstValue),
|
||||||
|
|
||||||
Add(InstructionValue, InstructionValue),
|
Add(InstructionValue, InstructionValue),
|
||||||
Sub(InstructionValue, InstructionValue),
|
Sub(InstructionValue, InstructionValue),
|
||||||
Mult(InstructionValue, InstructionValue),
|
Mult(InstructionValue, InstructionValue),
|
||||||
@ -227,7 +216,6 @@ pub enum Instr {
|
|||||||
Store(InstructionValue, InstructionValue),
|
Store(InstructionValue, InstructionValue),
|
||||||
ArrayAlloca(Type, u32),
|
ArrayAlloca(Type, u32),
|
||||||
GetElemPtr(InstructionValue, Vec<u32>),
|
GetElemPtr(InstructionValue, Vec<u32>),
|
||||||
GetStructElemPtr(InstructionValue, u32),
|
|
||||||
|
|
||||||
/// Integer Comparison
|
/// Integer Comparison
|
||||||
ICmp(CmpPredicate, InstructionValue, InstructionValue),
|
ICmp(CmpPredicate, InstructionValue, InstructionValue),
|
||||||
@ -249,7 +237,6 @@ pub enum Type {
|
|||||||
U128,
|
U128,
|
||||||
Bool,
|
Bool,
|
||||||
Void,
|
Void,
|
||||||
CustomType(TypeValue),
|
|
||||||
Ptr(Box<Type>),
|
Ptr(Box<Type>),
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -266,7 +253,7 @@ pub enum ConstValue {
|
|||||||
U64(u64),
|
U64(u64),
|
||||||
U128(u128),
|
U128(u128),
|
||||||
Bool(bool),
|
Bool(bool),
|
||||||
StringPtr(String),
|
String(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Hash)]
|
#[derive(Clone, Hash)]
|
||||||
@ -285,124 +272,5 @@ pub struct TypeData {
|
|||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, Clone, Hash)]
|
#[derive(Debug, PartialEq, Eq, Clone, Hash)]
|
||||||
pub enum CustomTypeKind {
|
pub enum CustomTypeKind {
|
||||||
NamedStruct(NamedStruct),
|
Struct(Vec<Type>),
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, Clone, Hash)]
|
|
||||||
pub struct NamedStruct(pub String, pub Vec<Type>);
|
|
||||||
|
|
||||||
impl InstructionValue {
|
|
||||||
pub(crate) fn get_type(&self, builder: &Builder) -> Result<Type, ()> {
|
|
||||||
use Instr::*;
|
|
||||||
unsafe {
|
|
||||||
match &builder.instr_data(self).kind {
|
|
||||||
Param(nth) => builder
|
|
||||||
.function_data(&self.0.0)
|
|
||||||
.params
|
|
||||||
.get(*nth)
|
|
||||||
.cloned()
|
|
||||||
.ok_or(()),
|
|
||||||
Constant(c) => Ok(c.get_type()),
|
|
||||||
Add(lhs, rhs) => match_types(lhs, rhs, &builder),
|
|
||||||
Sub(lhs, rhs) => match_types(lhs, rhs, &builder),
|
|
||||||
Mult(lhs, rhs) => match_types(lhs, rhs, &builder),
|
|
||||||
And(lhs, rhs) => match_types(lhs, rhs, &builder),
|
|
||||||
ICmp(_, _, _) => Ok(Type::Bool),
|
|
||||||
FunctionCall(function_value, _) => Ok(builder.function_data(function_value).ret),
|
|
||||||
Phi(values) => values.first().ok_or(()).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),
|
|
||||||
ArrayAlloca(ty, _) => Ok(Type::Ptr(Box::new(ty.clone()))),
|
|
||||||
GetElemPtr(ptr, _) => ptr.get_type(builder),
|
|
||||||
GetStructElemPtr(instr, idx) => {
|
|
||||||
let instr_ty = instr.get_type(builder)?;
|
|
||||||
let Type::Ptr(inner_ty) = instr_ty else {
|
|
||||||
panic!("GetStructElemPtr on non-pointer! ({:?})", &instr_ty)
|
|
||||||
};
|
|
||||||
let Type::CustomType(ty_value) = *inner_ty else {
|
|
||||||
panic!("GetStructElemPtr on non-struct! ({:?})", &inner_ty)
|
|
||||||
};
|
|
||||||
let field_ty = match builder.type_data(&ty_value).kind {
|
|
||||||
CustomTypeKind::NamedStruct(NamedStruct(_, fields)) => {
|
|
||||||
fields.get_unchecked(*idx as usize).clone()
|
|
||||||
}
|
|
||||||
};
|
|
||||||
Ok(Type::Ptr(Box::new(field_ty)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ConstValue {
|
|
||||||
pub fn get_type(&self) -> Type {
|
|
||||||
use Type::*;
|
|
||||||
match self {
|
|
||||||
ConstValue::I8(_) => I8,
|
|
||||||
ConstValue::I16(_) => I16,
|
|
||||||
ConstValue::I32(_) => I32,
|
|
||||||
ConstValue::I64(_) => I64,
|
|
||||||
ConstValue::I128(_) => I128,
|
|
||||||
ConstValue::U8(_) => U8,
|
|
||||||
ConstValue::U16(_) => U16,
|
|
||||||
ConstValue::U32(_) => U32,
|
|
||||||
ConstValue::U64(_) => U64,
|
|
||||||
ConstValue::U128(_) => U128,
|
|
||||||
ConstValue::StringPtr(_) => Ptr(Box::new(I8)),
|
|
||||||
ConstValue::Bool(_) => Bool,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Type {
|
|
||||||
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,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TerminatorKind {
|
|
||||||
pub(crate) fn get_type(&self, builder: &Builder) -> Result<Type, ()> {
|
|
||||||
use TerminatorKind::*;
|
|
||||||
match self {
|
|
||||||
Ret(instr_val) => instr_val.get_type(builder),
|
|
||||||
RetVoid => Ok(Type::Void),
|
|
||||||
Br(_) => Ok(Type::Void),
|
|
||||||
CondBr(_, _, _) => Ok(Type::Void),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,11 @@
|
|||||||
use std::{collections::HashMap, mem};
|
use std::{collections::HashMap, mem};
|
||||||
|
|
||||||
use reid_lib::{
|
use reid_lib::{
|
||||||
builder::{InstructionValue, TypeValue},
|
builder::InstructionValue, compile::CompiledModule, Block, CmpPredicate, ConstValue, Context,
|
||||||
compile::CompiledModule,
|
Function, FunctionFlags, Instr, Module, TerminatorKind as Term, Type,
|
||||||
Block, CmpPredicate, ConstValue, Context, CustomTypeKind, Function, FunctionFlags, Instr,
|
|
||||||
Module, NamedStruct, TerminatorKind as Term, Type,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::mir::{
|
use crate::mir::{self, types::ReturnType, IndexedVariableReference, NamedVariableRef, TypeKind};
|
||||||
self, types::ReturnType, IndexedVariableReference, NamedVariableRef, StructType,
|
|
||||||
TypeDefinitionKind, TypeKind,
|
|
||||||
};
|
|
||||||
|
|
||||||
/// Context that contains all of the given modules as complete codegenerated
|
/// Context that contains all of the given modules as complete codegenerated
|
||||||
/// LLIR that can then be finally compiled into LLVM IR.
|
/// LLIR that can then be finally compiled into LLVM IR.
|
||||||
@ -52,42 +47,20 @@ impl mir::Module {
|
|||||||
fn codegen<'ctx>(&self, context: &'ctx Context) -> ModuleCodegen<'ctx> {
|
fn codegen<'ctx>(&self, context: &'ctx Context) -> ModuleCodegen<'ctx> {
|
||||||
let mut module = context.module(&self.name, self.is_main);
|
let mut module = context.module(&self.name, self.is_main);
|
||||||
|
|
||||||
let mut types = HashMap::new();
|
|
||||||
let mut type_values = HashMap::new();
|
|
||||||
|
|
||||||
for typedef in &self.typedefs {
|
|
||||||
let type_value = match &typedef.kind {
|
|
||||||
TypeDefinitionKind::Struct(StructType(fields)) => {
|
|
||||||
module.custom_type(CustomTypeKind::NamedStruct(NamedStruct(
|
|
||||||
typedef.name.clone(),
|
|
||||||
fields
|
|
||||||
.iter()
|
|
||||||
// TODO: Reorder custom-type definitions such that
|
|
||||||
// inner types get evaluated first. Otherwise this
|
|
||||||
// will cause a panic!
|
|
||||||
.map(|(_, t)| t.get_type(&type_values))
|
|
||||||
.collect(),
|
|
||||||
)))
|
|
||||||
}
|
|
||||||
};
|
|
||||||
types.insert(type_value, typedef.kind.clone());
|
|
||||||
type_values.insert(typedef.name.clone(), type_value);
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut functions = HashMap::new();
|
let mut functions = HashMap::new();
|
||||||
|
|
||||||
for function in &self.functions {
|
for function in &self.functions {
|
||||||
let param_types: Vec<Type> = function
|
let param_types: Vec<Type> = function
|
||||||
.parameters
|
.parameters
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(_, p)| p.get_type(&type_values))
|
.map(|(_, p)| p.get_type())
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let is_main = self.is_main && function.name == "main";
|
let is_main = self.is_main && function.name == "main";
|
||||||
let func = match &function.kind {
|
let func = match &function.kind {
|
||||||
mir::FunctionDefinitionKind::Local(_, _) => module.function(
|
mir::FunctionDefinitionKind::Local(_, _) => module.function(
|
||||||
&function.name,
|
&function.name,
|
||||||
function.return_type.get_type(&type_values),
|
function.return_type.get_type(),
|
||||||
param_types,
|
param_types,
|
||||||
FunctionFlags {
|
FunctionFlags {
|
||||||
is_pub: function.is_pub || is_main,
|
is_pub: function.is_pub || is_main,
|
||||||
@ -98,7 +71,7 @@ impl mir::Module {
|
|||||||
),
|
),
|
||||||
mir::FunctionDefinitionKind::Extern(imported) => module.function(
|
mir::FunctionDefinitionKind::Extern(imported) => module.function(
|
||||||
&function.name,
|
&function.name,
|
||||||
function.return_type.get_type(&type_values),
|
function.return_type.get_type(),
|
||||||
param_types,
|
param_types,
|
||||||
FunctionFlags {
|
FunctionFlags {
|
||||||
is_extern: true,
|
is_extern: true,
|
||||||
@ -120,7 +93,7 @@ impl mir::Module {
|
|||||||
p_name.clone(),
|
p_name.clone(),
|
||||||
StackValue(
|
StackValue(
|
||||||
StackValueKind::Immutable(entry.build(Instr::Param(i)).unwrap()),
|
StackValueKind::Immutable(entry.build(Instr::Param(i)).unwrap()),
|
||||||
p_ty.get_type(&type_values),
|
p_ty.get_type(),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -131,8 +104,6 @@ impl mir::Module {
|
|||||||
function,
|
function,
|
||||||
block: entry,
|
block: entry,
|
||||||
functions: &functions,
|
functions: &functions,
|
||||||
types: &types,
|
|
||||||
type_values: &type_values,
|
|
||||||
stack_values,
|
stack_values,
|
||||||
};
|
};
|
||||||
match &mir_function.kind {
|
match &mir_function.kind {
|
||||||
@ -160,8 +131,6 @@ pub struct Scope<'ctx, 'a> {
|
|||||||
module: &'ctx Module<'ctx>,
|
module: &'ctx Module<'ctx>,
|
||||||
function: &'ctx Function<'ctx>,
|
function: &'ctx Function<'ctx>,
|
||||||
block: Block<'ctx>,
|
block: Block<'ctx>,
|
||||||
types: &'a HashMap<TypeValue, TypeDefinitionKind>,
|
|
||||||
type_values: &'a HashMap<String, TypeValue>,
|
|
||||||
functions: &'a HashMap<String, Function<'ctx>>,
|
functions: &'a HashMap<String, Function<'ctx>>,
|
||||||
stack_values: HashMap<String, StackValue>,
|
stack_values: HashMap<String, StackValue>,
|
||||||
}
|
}
|
||||||
@ -183,8 +152,6 @@ impl<'ctx, 'a> Scope<'ctx, 'a> {
|
|||||||
context: self.context,
|
context: self.context,
|
||||||
module: self.module,
|
module: self.module,
|
||||||
functions: self.functions,
|
functions: self.functions,
|
||||||
types: self.types,
|
|
||||||
type_values: self.type_values,
|
|
||||||
stack_values: self.stack_values.clone(),
|
stack_values: self.stack_values.clone(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -196,10 +163,6 @@ impl<'ctx, 'a> Scope<'ctx, 'a> {
|
|||||||
mem::swap(&mut self.block, &mut old_block);
|
mem::swap(&mut self.block, &mut old_block);
|
||||||
old_block
|
old_block
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_typedef(&self, name: &String) -> Option<&TypeDefinitionKind> {
|
|
||||||
self.type_values.get(name).and_then(|v| self.types.get(v))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IndexedVariableReference {
|
impl IndexedVariableReference {
|
||||||
@ -221,24 +184,8 @@ impl IndexedVariableReference {
|
|||||||
_ => panic!("Tried to codegen indexing a non-indexable value!"),
|
_ => panic!("Tried to codegen indexing a non-indexable value!"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mir::IndexedVariableReferenceKind::StructIndex(inner, field) => {
|
mir::IndexedVariableReferenceKind::StructIndex(indexed_variable_reference, _) => {
|
||||||
let (inner_val, mut indices) = inner.get_stack_value(scope)?;
|
todo!("codegen for indexed var refrence")
|
||||||
|
|
||||||
let idx = if let Type::CustomType(ty_val) = inner_val.1 {
|
|
||||||
match scope.types.get(&ty_val).unwrap() {
|
|
||||||
TypeDefinitionKind::Struct(struct_type) => struct_type.find_index(field),
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}?;
|
|
||||||
|
|
||||||
match &inner_val.1 {
|
|
||||||
Type::Ptr(_) => {
|
|
||||||
indices.push(idx as u32);
|
|
||||||
Some((inner_val, indices))
|
|
||||||
}
|
|
||||||
_ => panic!("Tried to codegen indexing a non-indexable value!"),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -259,17 +206,14 @@ impl mir::Statement {
|
|||||||
_ => StackValueKind::Mutable({
|
_ => StackValueKind::Mutable({
|
||||||
let alloca = scope
|
let alloca = scope
|
||||||
.block
|
.block
|
||||||
.build(Instr::Alloca(
|
.build(Instr::Alloca(name.clone(), ty.get_type()))
|
||||||
name.clone(),
|
|
||||||
ty.get_type(scope.type_values),
|
|
||||||
))
|
|
||||||
.unwrap();
|
.unwrap();
|
||||||
scope.block.build(Instr::Store(alloca, value)).unwrap();
|
scope.block.build(Instr::Store(alloca, value)).unwrap();
|
||||||
alloca
|
alloca
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
ty.get_type(scope.type_values),
|
ty.get_type(),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
None
|
None
|
||||||
@ -454,7 +398,7 @@ impl mir::Expression {
|
|||||||
Some(
|
Some(
|
||||||
scope
|
scope
|
||||||
.block
|
.block
|
||||||
.build(Instr::Load(ptr, val_t.get_type(scope.type_values)))
|
.build(Instr::Load(ptr, val_t.get_type()))
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -472,7 +416,7 @@ impl mir::Expression {
|
|||||||
let array = scope
|
let array = scope
|
||||||
.block
|
.block
|
||||||
.build(Instr::ArrayAlloca(
|
.build(Instr::ArrayAlloca(
|
||||||
instr_t.get_type(scope.type_values),
|
instr_t.get_type(),
|
||||||
instr_list.len() as u32,
|
instr_list.len() as u32,
|
||||||
))
|
))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
@ -487,49 +431,10 @@ impl mir::Expression {
|
|||||||
|
|
||||||
Some(array)
|
Some(array)
|
||||||
}
|
}
|
||||||
mir::ExprKind::StructIndex(expression, type_kind, field) => {
|
mir::ExprKind::StructIndex(expression, type_kind, _) => {
|
||||||
let struct_val = expression.codegen(scope)?;
|
todo!("codegen for struct index")
|
||||||
|
|
||||||
let struct_ty = expression.return_type().ok()?.1.known().ok()?;
|
|
||||||
let TypeKind::CustomType(name) = struct_ty else {
|
|
||||||
return None;
|
|
||||||
};
|
|
||||||
let TypeDefinitionKind::Struct(struct_ty) = scope.get_typedef(&name)?;
|
|
||||||
let idx = struct_ty.find_index(field)?;
|
|
||||||
|
|
||||||
let ptr = scope
|
|
||||||
.block
|
|
||||||
.build(Instr::GetStructElemPtr(struct_val, idx as u32))
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
Some(
|
|
||||||
scope
|
|
||||||
.block
|
|
||||||
.build(Instr::Load(ptr, type_kind.get_type(scope.type_values)))
|
|
||||||
.unwrap(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
mir::ExprKind::Struct(name, items) => {
|
|
||||||
let struct_ptr = scope
|
|
||||||
.block
|
|
||||||
.build(Instr::Alloca(
|
|
||||||
name.clone(),
|
|
||||||
Type::CustomType(*scope.type_values.get(name)?),
|
|
||||||
))
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
for (i, (_, exp)) in items.iter().enumerate() {
|
|
||||||
let elem_ptr = scope
|
|
||||||
.block
|
|
||||||
.build(Instr::GetStructElemPtr(struct_ptr, i as u32))
|
|
||||||
.unwrap();
|
|
||||||
if let Some(val) = exp.codegen(scope) {
|
|
||||||
scope.block.build(Instr::Store(elem_ptr, val)).unwrap();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Some(struct_ptr)
|
|
||||||
}
|
}
|
||||||
|
mir::ExprKind::Struct(_, items) => todo!("codegen for struct expression"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -589,14 +494,14 @@ impl mir::Literal {
|
|||||||
mir::Literal::U64(val) => ConstValue::U64(val),
|
mir::Literal::U64(val) => ConstValue::U64(val),
|
||||||
mir::Literal::U128(val) => ConstValue::U128(val),
|
mir::Literal::U128(val) => ConstValue::U128(val),
|
||||||
mir::Literal::Bool(val) => ConstValue::Bool(val),
|
mir::Literal::Bool(val) => ConstValue::Bool(val),
|
||||||
mir::Literal::String(val) => ConstValue::StringPtr(val.clone()),
|
mir::Literal::String(val) => ConstValue::String(val.clone()),
|
||||||
mir::Literal::Vague(_) => panic!("Got vague literal!"),
|
mir::Literal::Vague(_) => panic!("Got vague literal!"),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TypeKind {
|
impl TypeKind {
|
||||||
fn get_type(&self, type_vals: &HashMap<String, TypeValue>) -> Type {
|
fn get_type(&self) -> Type {
|
||||||
match &self {
|
match &self {
|
||||||
TypeKind::I8 => Type::I8,
|
TypeKind::I8 => Type::I8,
|
||||||
TypeKind::I16 => Type::I16,
|
TypeKind::I16 => Type::I16,
|
||||||
@ -610,10 +515,10 @@ impl TypeKind {
|
|||||||
TypeKind::U128 => Type::U128,
|
TypeKind::U128 => Type::U128,
|
||||||
TypeKind::Bool => Type::Bool,
|
TypeKind::Bool => Type::Bool,
|
||||||
TypeKind::StringPtr => Type::Ptr(Box::new(Type::I8)),
|
TypeKind::StringPtr => Type::Ptr(Box::new(Type::I8)),
|
||||||
TypeKind::Array(elem_t, _) => Type::Ptr(Box::new(elem_t.get_type(type_vals))),
|
TypeKind::Array(elem_t, _) => Type::Ptr(Box::new(elem_t.get_type())),
|
||||||
TypeKind::Void => Type::Void,
|
TypeKind::Void => Type::Void,
|
||||||
TypeKind::Vague(_) => panic!("Tried to compile a vague type!"),
|
TypeKind::Vague(_) => panic!("Tried to compile a vague type!"),
|
||||||
TypeKind::CustomType(n) => Type::CustomType(type_vals.get(n).unwrap().clone()),
|
TypeKind::CustomType(_) => todo!("codegen for custom type"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -84,16 +84,6 @@ pub enum VagueType {
|
|||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct StructType(pub Vec<(String, TypeKind)>);
|
pub struct StructType(pub Vec<(String, TypeKind)>);
|
||||||
|
|
||||||
impl StructType {
|
|
||||||
pub fn find_index(&self, name: &String) -> Option<u32> {
|
|
||||||
self.0
|
|
||||||
.iter()
|
|
||||||
.enumerate()
|
|
||||||
.find(|(_, (n, _))| n == name)
|
|
||||||
.map(|(i, _)| i as u32)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub type TypedefMap = HashMap<String, TypeDefinitionKind>;
|
pub type TypedefMap = HashMap<String, TypeDefinitionKind>;
|
||||||
|
|
||||||
impl TypeKind {
|
impl TypeKind {
|
||||||
|
@ -300,7 +300,7 @@ impl Statement {
|
|||||||
StmtKind::Set(_, expression) => {
|
StmtKind::Set(_, expression) => {
|
||||||
expression.pass(pass, state, scope);
|
expression.pass(pass, state, scope);
|
||||||
}
|
}
|
||||||
StmtKind::Import(_) => {} // Never exists at this stage
|
StmtKind::Import(_) => todo!(),
|
||||||
StmtKind::Expression(expression) => {
|
StmtKind::Expression(expression) => {
|
||||||
expression.pass(pass, state, scope);
|
expression.pass(pass, state, scope);
|
||||||
}
|
}
|
||||||
@ -322,7 +322,7 @@ impl Statement {
|
|||||||
.ok();
|
.ok();
|
||||||
}
|
}
|
||||||
StmtKind::Set(_, _) => {}
|
StmtKind::Set(_, _) => {}
|
||||||
StmtKind::Import(_) => {} // Never exists at this stage
|
StmtKind::Import(_) => todo!(),
|
||||||
StmtKind::Expression(_) => {}
|
StmtKind::Expression(_) => {}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -9,13 +9,13 @@ use std::{convert::Infallible, iter};
|
|||||||
use crate::{mir::TypeKind, util::try_all};
|
use crate::{mir::TypeKind, util::try_all};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
pass::{Pass, PassState},
|
pass::{self, Pass, PassState},
|
||||||
typecheck::ErrorKind,
|
typecheck::ErrorKind,
|
||||||
typerefs::{ScopeTypeRefs, TypeRef, TypeRefs},
|
typerefs::{ScopeTypeRefs, TypeRef, TypeRefs},
|
||||||
types::{pick_return, ReturnType},
|
types::{pick_return, ReturnType},
|
||||||
Block, ExprKind, Expression, FunctionDefinition, FunctionDefinitionKind, IfExpression,
|
Block, ExprKind, Expression, FunctionDefinition, FunctionDefinitionKind, IfExpression,
|
||||||
IndexedVariableReference, IndexedVariableReferenceKind, Module, NamedVariableRef, ReturnKind,
|
IndexedVariableReference, IndexedVariableReferenceKind, Module, NamedVariableRef, ReturnKind,
|
||||||
StmtKind, TypeDefinitionKind,
|
StmtKind, StructType, TypeDefinitionKind,
|
||||||
TypeKind::*,
|
TypeKind::*,
|
||||||
VagueType::*,
|
VagueType::*,
|
||||||
};
|
};
|
||||||
|
@ -8,7 +8,7 @@ use crate::mir::VagueType;
|
|||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
typecheck::{Collapsable, ErrorKind},
|
typecheck::{Collapsable, ErrorKind},
|
||||||
BinaryOperator, TypeKind,
|
BinaryOperator, TypeDefinition, TypeKind,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
@ -1,3 +1,7 @@
|
|||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
use crate::util::try_all;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
Loading…
Reference in New Issue
Block a user