Skip to content

Commit

Permalink
[CODE GEN] alloca now compiles
Browse files Browse the repository at this point in the history
  • Loading branch information
Cr0a3 committed Sep 20, 2024
1 parent f25060a commit 90556c2
Show file tree
Hide file tree
Showing 7 changed files with 114 additions and 13 deletions.
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
/target
*.asm
*.o
*.c
*.exe
*.out
tmp.yl
Expand Down
2 changes: 1 addition & 1 deletion src/CodeGen/calling_convention.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,6 @@ impl MachineCallingConvention {

/// Returns the alignment
pub fn align(&self, _: Arch) -> i64 {
8 // ygen only supports 64bit architectures
8 // ygen (currently) only supports x64 which has an alignment of 8
}
}
24 changes: 24 additions & 0 deletions src/CodeGen/compilation/alloca.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
use crate::CodeGen::{MachineInstr, MachineMnemonic, MachineOperand};
use crate::IR::{Block, TypeMetadata, Var, ir::Alloca};

use super::CompilationHelper;

impl CompilationHelper {
#[allow(missing_docs)]
pub fn compile_alloca(&mut self, node: &Alloca<Var, TypeMetadata>, mc_sink: &mut Vec<MachineInstr>, _: &Block) {
let (_, offset) = self.alloc_custom_stack(&node.inner2);
let out = self.alloc(&node.inner1);

let out = match out {
super::VarLocation::Reg(reg) => MachineOperand::Reg(reg),
super::VarLocation::Mem(mem) => MachineOperand::Stack(mem),
};

let mut instr = MachineInstr::new(MachineMnemonic::StackAlloc);

instr.set_out(out);
instr.add_operand(MachineOperand::Imm(offset));

mc_sink.push(instr);
}
}
34 changes: 30 additions & 4 deletions src/CodeGen/compilation/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::collections::HashMap;

use crate::{Target::{Arch, CallConv}, IR::{Function, Var}};
use crate::{Target::{Arch, CallConv}, IR::{Function, TypeMetadata, Var}};

use super::{calling_convention::MachineCallingConvention, reg::Reg, reg_vec::RegVec, MCInstr, MachineInstr};

Expand All @@ -12,6 +12,7 @@ mod assign;
mod br;
mod cmp;
mod prolog;
mod alloca;

/// helps with compilation
#[derive(Debug, Clone, PartialEq, Eq)]
Expand Down Expand Up @@ -51,11 +52,36 @@ impl CompilationHelper {

/// allocates resources for a var but on the stack
pub(crate) fn alloc_stack(&mut self, var: &Var) -> VarLocation {
if var.ty.byteSize() as i64 <= self.call.align(self.arch) {
let loc = if var.ty.byteSize() as i64 <= self.call.align(self.arch) {
VarLocation::Mem(self.stack_off)
} else {
todo!()
}
};

self.vars.insert(var.name.to_owned(), loc);

self.stack_off += self.call.align(self.arch);

loc
}

/// allocates a variable on the stack
///
/// The difference to `alloc_stack` is that here you can use a custom stack space size
///
/// **NOTE:** it does not register the var
pub(crate) fn alloc_custom_stack(&mut self, ty: &TypeMetadata) -> (VarLocation, i64) {
let loc = if ty.byteSize() as i64 <= self.call.align(self.arch) {
VarLocation::Mem(self.stack_off)
} else {
todo!()
};

let ret = (loc, self.stack_off);

self.stack_off += self.call.align(self.arch);

ret
}

/// allocates resources for a new variable
Expand All @@ -65,7 +91,7 @@ impl CompilationHelper {
Reg::x64(x64) => Reg::x64(x64.sub_ty(var.ty)),
})
} else {
self.alloc_stack(var)
return self.alloc_stack(var);
};

self.vars.insert(var.name.to_owned(), location);
Expand Down
2 changes: 2 additions & 0 deletions src/CodeGen/instr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ pub enum MachineMnemonic {
Return,

AdressLoad(String),
StackAlloc,

Prolog,
Epilog,
Expand Down Expand Up @@ -134,6 +135,7 @@ impl MachineMnemonic {
MachineMnemonic::Compare(_) => "compare",
MachineMnemonic::Prolog =>"prolog",
MachineMnemonic::Epilog => "epilog",
MachineMnemonic::StackAlloc => "salloc",
}.to_string()
}
}
Expand Down
28 changes: 22 additions & 6 deletions src/Target/target_descr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,23 +87,35 @@ impl TargetBackendDescr {

helper.build_argument_preprocessing(func);

let mut cloned_helper = helper.clone();
let mut cloned_helper = CompilationHelper::new(helper.arch, helper.call);

for node in block.nodes {
node.compile(self);
}

if let Some(helper) = &mut self.helper {
cloned_helper.stack_off = helper.stack_off;
}

let mut vsink = vec![];

cloned_helper.compile_prolog(&mut vsink);

self.sink.extend_from_slice(&vsink);
vsink.extend_from_slice(&self.sink);

let last = vsink.last().cloned();

cloned_helper.compile_epilog(&mut self.sink);
vsink.remove(vsink.len() - 1); // ret

let out = self.sink.clone();
cloned_helper.compile_epilog(&mut vsink);

if let Some(last) = last {
vsink.push(last);
}

out
self.sink = vsink;

self.sink.to_owned()
}

/// Resets all values to "factory standart"
Expand All @@ -115,7 +127,9 @@ impl TargetBackendDescr {
self.compile = reference.compile;
self.helper = reference.helper;
self.block = reference.block;

assert_eq!(self.call, reference.call);

self.call = reference.call;
self.sink = reference.sink;
self.whitelist = reference.whitelist;
Expand Down Expand Up @@ -182,4 +196,6 @@ compile_func!(compile_assign_var_const, compile_assign_var_const, Assign<Var, Co
compile_func!(compile_br, compile_br, Br<Box<Block>>);
compile_func!(compile_br_cond, compile_br_cond, BrCond<Var, Block, Block>);

compile_func!(compile_cmp, compile_cmp, Cmp);
compile_func!(compile_cmp, compile_cmp, Cmp);

compile_func!(compile_alloca, compile_alloca, Alloca<Var, TypeMetadata>);
36 changes: 35 additions & 1 deletion src/Target/x64/lower.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::prelude::CmpMode;
use crate::CodeGen::{MCInstr, MachineInstr, MachineMnemonic};
use crate::CodeGen::{MCInstr, MachineInstr, MachineMnemonic, MachineOperand};
use crate::Optimizations::Optimize;
use crate::Target::CallConv;

Expand Down Expand Up @@ -31,6 +31,7 @@ fn x64_lower_instr(conv: CallConv, sink: &mut Vec<X64MCInstr>, instr: MachineIns
MachineMnemonic::Compare(mode) => x64_lower_cmp(sink, &instr, mode),
MachineMnemonic::Prolog => x64_lower_prolog(sink, &instr),
MachineMnemonic::Epilog => x64_lower_epilog(sink, &instr),
MachineMnemonic::StackAlloc => x64_lower_salloc(sink, &instr),
}
}

Expand Down Expand Up @@ -395,4 +396,37 @@ fn x64_lower_prolog(sink: &mut Vec<X64MCInstr>, instr: &MachineInstr) {

fn x64_lower_epilog(sink: &mut Vec<X64MCInstr>, _: &MachineInstr) {
sink.push( X64MCInstr::with1(Mnemonic::Pop, Operand::Reg(x64Reg::Rbp) ) );
}

fn x64_lower_salloc(sink: &mut Vec<X64MCInstr>, instr: &MachineInstr) {
let out = instr.out.expect("stack allocations need outputs");
let offset = instr.operands.get(0).expect("stack allocations need one operand");

let offset = match offset {
MachineOperand::Imm(imm) => *imm,
_ => panic!("stack allocations require one operand of type imm")
};

let out = match out {
crate::CodeGen::MachineOperand::Imm(i) => Operand::Imm(i),
crate::CodeGen::MachineOperand::Reg(reg) => match reg {
crate::CodeGen::Reg::x64(x64) => Operand::Reg(x64),
},
crate::CodeGen::MachineOperand::Stack(off) => x64_stack!((off as u32)),
};

if let Operand::Mem(_) = out {
let tmp = || Operand::Reg( x64Reg::Rax );

sink.push(
X64MCInstr::with2(Mnemonic::Lea, tmp(), x64_stack!(offset as u32))
);
sink.push(
X64MCInstr::with2(Mnemonic::Mov, out, tmp())
)
} else {
sink.push(
X64MCInstr::with2(Mnemonic::Lea, out, x64_stack!(offset as u32))
)
}
}

0 comments on commit 90556c2

Please sign in to comment.