Compare commits
3 Commits
515c031f19
...
312a777203
Author | SHA1 | Date | |
---|---|---|---|
312a777203 | |||
d62d6e2845 | |||
a2e52e0bd2 |
@ -3,6 +3,8 @@
|
||||
|
||||
use std::{cell::RefCell, rc::Rc};
|
||||
|
||||
use llvm_sys::core::LLVMBuildArrayAlloca;
|
||||
|
||||
use crate::{
|
||||
BlockData, ConstValue, FunctionData, Instr, InstructionData, ModuleData, TerminatorKind, Type,
|
||||
util::match_types,
|
||||
@ -277,6 +279,28 @@ impl Builder {
|
||||
Err(())
|
||||
}
|
||||
}
|
||||
Extract(arr, idx) => {
|
||||
let arr_ty = arr.get_type(&self)?;
|
||||
if let Type::Array(_, len) = arr_ty {
|
||||
if len > idx { Ok(()) } else { Err(()) }
|
||||
} else {
|
||||
Err(())
|
||||
}
|
||||
}
|
||||
ArrayAlloca(_, _) => Ok(()),
|
||||
Insert(arr, idx, val) => {
|
||||
let arr_ty = arr.get_type(&self)?;
|
||||
let val_ty = val.get_type(&self)?;
|
||||
if let Type::Array(elem_ty, len) = arr_ty {
|
||||
if val_ty == *elem_ty && len > idx {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(())
|
||||
}
|
||||
} else {
|
||||
Err(())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -338,6 +362,15 @@ impl InstructionValue {
|
||||
Alloca(_, ty) => Ok(Type::Ptr(Box::new(ty.clone()))),
|
||||
Load(_, ty) => Ok(ty.clone()),
|
||||
Store(_, value) => value.get_type(builder),
|
||||
Extract(arr, _) => match arr.get_type(builder) {
|
||||
Ok(Type::Array(elem_t, _)) => Ok(*elem_t),
|
||||
Ok(_) => Err(()),
|
||||
Err(_) => Err(()),
|
||||
},
|
||||
ArrayAlloca(ty, len_value) => {
|
||||
Ok(Type::Array(Box::new(ty.clone()), len_value.clone()))
|
||||
}
|
||||
Insert(_, _, val) => val.get_type(builder),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -358,6 +391,15 @@ impl ConstValue {
|
||||
ConstValue::U64(_) => U64,
|
||||
ConstValue::U128(_) => U128,
|
||||
ConstValue::Bool(_) => Bool,
|
||||
// ConstValue::Array(arr) => Array(
|
||||
// Box::new(
|
||||
// arr.iter()
|
||||
// .map(|a| a.get_type(builder).unwrap())
|
||||
// .next()
|
||||
// .unwrap_or(Void),
|
||||
// ),
|
||||
// arr.len() as u32,
|
||||
// ),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -378,6 +420,7 @@ impl Type {
|
||||
Type::Bool => true,
|
||||
Type::Void => false,
|
||||
Type::Ptr(_) => false,
|
||||
Type::Array(_, _) => false,
|
||||
}
|
||||
}
|
||||
|
||||
@ -396,6 +439,7 @@ impl Type {
|
||||
Type::Bool => false,
|
||||
Type::Void => false,
|
||||
Type::Ptr(_) => false,
|
||||
Type::Array(_, _) => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -349,6 +349,66 @@ impl InstructionHolder {
|
||||
module.values.get(&val).unwrap().value_ref,
|
||||
module.values.get(&ptr).unwrap().value_ref,
|
||||
),
|
||||
Extract(arr, idx) => {
|
||||
let t = arr.get_type(module.builder).unwrap();
|
||||
let Type::Array(elem_t, _) = t else { panic!() };
|
||||
|
||||
let indices = &mut [ConstValue::I32(*idx as i32).as_llvm(module.context_ref)];
|
||||
let ptr = LLVMBuildGEP2(
|
||||
module.builder_ref,
|
||||
elem_t.as_llvm(module.context_ref),
|
||||
module.values.get(arr).unwrap().value_ref,
|
||||
indices.as_mut_ptr(),
|
||||
1,
|
||||
c"insert_gep".as_ptr(),
|
||||
);
|
||||
LLVMBuildLoad2(
|
||||
module.builder_ref,
|
||||
elem_t.as_llvm(module.context_ref),
|
||||
ptr,
|
||||
c"load".as_ptr(),
|
||||
)
|
||||
}
|
||||
ArrayAlloca(ty, len) => {
|
||||
let array_len = ConstValue::U16(*len as u16).as_llvm(module.context_ref);
|
||||
let array_ty = Type::Array(Box::new(ty.clone()), *len);
|
||||
dbg!(
|
||||
&ty.as_llvm(module.context_ref),
|
||||
&array_ty.as_llvm(module.context_ref)
|
||||
);
|
||||
LLVMBuildArrayAlloca(
|
||||
module.builder_ref,
|
||||
ty.as_llvm(module.context_ref),
|
||||
array_len,
|
||||
c"array_alloca".as_ptr(),
|
||||
)
|
||||
}
|
||||
Insert(arr, idx, val) => {
|
||||
let indices = &mut [ConstValue::I32(*idx as i32).as_llvm(module.context_ref)];
|
||||
let ptr = LLVMBuildGEP2(
|
||||
module.builder_ref,
|
||||
val.get_type(module.builder)
|
||||
.unwrap()
|
||||
.as_llvm(module.context_ref),
|
||||
module.values.get(arr).unwrap().value_ref,
|
||||
indices.as_mut_ptr(),
|
||||
1,
|
||||
c"insert_gep".as_ptr(),
|
||||
);
|
||||
LLVMBuildStore(
|
||||
module.builder_ref,
|
||||
module.values.get(val).unwrap().value_ref,
|
||||
ptr,
|
||||
)
|
||||
|
||||
// LLVMBuildInsertValue(
|
||||
// module.builder_ref,
|
||||
// ptr,
|
||||
// module.values.get(val).unwrap().value_ref,
|
||||
// *idx,
|
||||
// c"insert".as_ptr(),
|
||||
// )
|
||||
}
|
||||
}
|
||||
};
|
||||
LLVMValue {
|
||||
@ -415,18 +475,18 @@ impl ConstValue {
|
||||
fn as_llvm(&self, context: LLVMContextRef) -> LLVMValueRef {
|
||||
unsafe {
|
||||
let t = self.get_type().as_llvm(context);
|
||||
match *self {
|
||||
ConstValue::Bool(val) => LLVMConstInt(t, val as u64, 1),
|
||||
ConstValue::I8(val) => LLVMConstInt(t, val as u64, 1),
|
||||
ConstValue::I16(val) => LLVMConstInt(t, val as u64, 1),
|
||||
ConstValue::I32(val) => LLVMConstInt(t, val as u64, 1),
|
||||
ConstValue::I64(val) => LLVMConstInt(t, val as u64, 1),
|
||||
ConstValue::I128(val) => LLVMConstInt(t, val as u64, 1),
|
||||
ConstValue::U8(val) => LLVMConstInt(t, val as u64, 1),
|
||||
ConstValue::U16(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::U128(val) => LLVMConstInt(t, val as u64, 1),
|
||||
match self {
|
||||
ConstValue::Bool(val) => LLVMConstInt(t, *val as u64, 1),
|
||||
ConstValue::I8(val) => LLVMConstInt(t, *val as u64, 1),
|
||||
ConstValue::I16(val) => LLVMConstInt(t, *val as u64, 1),
|
||||
ConstValue::I32(val) => LLVMConstInt(t, *val as u64, 1),
|
||||
ConstValue::I64(val) => LLVMConstInt(t, *val as u64, 1),
|
||||
ConstValue::I128(val) => LLVMConstInt(t, *val as u64, 1),
|
||||
ConstValue::U8(val) => LLVMConstInt(t, *val as u64, 1),
|
||||
ConstValue::U16(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::U128(val) => LLVMConstInt(t, *val as u64, 1),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -445,6 +505,7 @@ impl Type {
|
||||
Bool => LLVMInt1TypeInContext(context),
|
||||
Void => LLVMVoidType(),
|
||||
Ptr(ty) => LLVMPointerType(ty.as_llvm(context), 0),
|
||||
Array(elem_t, _) => LLVMPointerType(elem_t.as_llvm(context), 0),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -88,18 +88,23 @@ impl Debug for InstructionValue {
|
||||
impl Debug for Instr {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
Self::Param(nth) => fmt_call(f, &"Param", &nth),
|
||||
Self::Constant(c) => c.fmt(f),
|
||||
Self::Add(lhs, rhs) => fmt_binop(f, lhs, &"+", rhs),
|
||||
Self::Sub(lhs, rhs) => fmt_binop(f, lhs, &"-", rhs),
|
||||
Self::Mult(lhs, rhs) => fmt_binop(f, lhs, &"*", rhs),
|
||||
Self::And(lhs, rhs) => fmt_binop(f, lhs, &"&&", rhs),
|
||||
Self::Phi(val) => fmt_call(f, &"Phi", &val),
|
||||
Self::ICmp(cmp, lhs, rhs) => fmt_binop(f, lhs, cmp, rhs),
|
||||
Self::FunctionCall(fun, params) => fmt_call(f, fun, params),
|
||||
Instr::Param(nth) => fmt_call(f, &"Param", &nth),
|
||||
Instr::Constant(c) => c.fmt(f),
|
||||
Instr::Add(lhs, rhs) => fmt_binop(f, lhs, &"+", rhs),
|
||||
Instr::Sub(lhs, rhs) => fmt_binop(f, lhs, &"-", rhs),
|
||||
Instr::Mult(lhs, rhs) => fmt_binop(f, lhs, &"*", rhs),
|
||||
Instr::And(lhs, rhs) => fmt_binop(f, lhs, &"&&", rhs),
|
||||
Instr::Phi(val) => fmt_call(f, &"Phi", &val),
|
||||
Instr::ICmp(cmp, lhs, rhs) => fmt_binop(f, lhs, cmp, rhs),
|
||||
Instr::FunctionCall(fun, params) => fmt_call(f, fun, params),
|
||||
Instr::Alloca(name, ty) => write!(f, "alloca<{:?}>({})", ty, name),
|
||||
Instr::Load(val, ty) => write!(f, "load<{:?}>({:?})", ty, val),
|
||||
Instr::Store(ptr, val) => write!(f, "store({:?} = {:?})", ptr, val),
|
||||
Instr::Extract(instruction_value, idx) => fmt_index(f, instruction_value, idx),
|
||||
Instr::ArrayAlloca(ty, instruction_value) => {
|
||||
write!(f, "array_alloca<{:?}>({:?})", ty, instruction_value)
|
||||
}
|
||||
Instr::Insert(arr, idx, val) => write!(f, "{:?}[{}] = {:?}", arr, idx, val),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -128,6 +133,17 @@ fn fmt_call(
|
||||
f.write_char(')')
|
||||
}
|
||||
|
||||
fn fmt_index(
|
||||
f: &mut std::fmt::Formatter<'_>,
|
||||
fun: &impl std::fmt::Debug,
|
||||
params: &impl std::fmt::Debug,
|
||||
) -> std::fmt::Result {
|
||||
fun.fmt(f)?;
|
||||
f.write_char('[')?;
|
||||
params.fmt(f)?;
|
||||
f.write_char(']')
|
||||
}
|
||||
|
||||
impl Debug for CmpPredicate {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
|
@ -177,6 +177,9 @@ pub enum Instr {
|
||||
Alloca(String, Type),
|
||||
Load(InstructionValue, Type),
|
||||
Store(InstructionValue, InstructionValue),
|
||||
ArrayAlloca(Type, u32),
|
||||
Insert(InstructionValue, u32, InstructionValue),
|
||||
Extract(InstructionValue, u32),
|
||||
|
||||
/// Integer Comparison
|
||||
ICmp(CmpPredicate, InstructionValue, InstructionValue),
|
||||
@ -199,6 +202,7 @@ pub enum Type {
|
||||
Bool,
|
||||
Void,
|
||||
Ptr(Box<Type>),
|
||||
Array(Box<Type>, u32),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Hash)]
|
||||
|
@ -1,7 +1,7 @@
|
||||
// Arithmetic, function calls and imports!
|
||||
|
||||
fn array() -> [u16; 4] {
|
||||
return [1, 2, 3, 4];
|
||||
return [10, 15, 7, 9];
|
||||
}
|
||||
|
||||
fn main() -> u16 {
|
||||
@ -11,5 +11,5 @@ fn main() -> u16 {
|
||||
|
||||
// list[1] = 5;
|
||||
|
||||
return list[0];
|
||||
return list[3];
|
||||
}
|
||||
|
@ -334,8 +334,44 @@ impl mir::Expression {
|
||||
None
|
||||
}
|
||||
}
|
||||
mir::ExprKind::Index(expression, _) => todo!("codegen for index expression"),
|
||||
mir::ExprKind::Array(expressions) => todo!("codegen for array expression"),
|
||||
mir::ExprKind::Index(expression, idx) => {
|
||||
let expr = expression.codegen(scope)?;
|
||||
Some(
|
||||
scope
|
||||
.block
|
||||
.build(Instr::Extract(expr, *idx as u32))
|
||||
.unwrap(),
|
||||
)
|
||||
}
|
||||
mir::ExprKind::Array(expressions) => {
|
||||
let instr_list = expressions
|
||||
.iter()
|
||||
.map(|e| e.codegen(scope).unwrap())
|
||||
.collect::<Vec<_>>();
|
||||
let instr_t = expressions
|
||||
.iter()
|
||||
.map(|e| e.return_type().unwrap().1)
|
||||
.next()
|
||||
.unwrap_or(TypeKind::Void);
|
||||
|
||||
dbg!(&instr_t);
|
||||
let array = scope
|
||||
.block
|
||||
.build(Instr::ArrayAlloca(
|
||||
instr_t.get_type(),
|
||||
instr_list.len() as u32,
|
||||
))
|
||||
.unwrap();
|
||||
|
||||
for (i, instr) in instr_list.iter().enumerate() {
|
||||
scope
|
||||
.block
|
||||
.build(Instr::Insert(array, i as u32, *instr))
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
Some(array)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -414,9 +450,9 @@ impl TypeKind {
|
||||
TypeKind::U64 => Type::U64,
|
||||
TypeKind::U128 => Type::U128,
|
||||
TypeKind::Bool => Type::Bool,
|
||||
TypeKind::Array(elem_t, len) => Type::Array(Box::new(elem_t.get_type()), *len as u32),
|
||||
TypeKind::Void => panic!("Void not a supported type"),
|
||||
TypeKind::Vague(_) => panic!("Tried to compile a vague type!"),
|
||||
TypeKind::Array(_, _) => todo!("codegen for array type"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user