Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[YCC] starting code gen backend #57

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

63 changes: 63 additions & 0 deletions src/IR/func.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,41 @@ pub struct FunctionType {
pub ret: TypeMetadata,
/// After the given arguments any argument type can be supplied (like the printf function - is in c ...)
pub any_args: bool,

/// Visibility of the target function
pub visibility: Linkage,

/// count of arguments
pub(crate) arg_count: usize,
}

impl FunctionType {
/// Creates a new function type
pub fn new(args: Vec<(String, TypeMetadata)>, ret: TypeMetadata) -> Self {
Self {
arg_count: args.len(),
args: args,
ret: ret,
any_args: false,
visibility: Linkage::Internal,
}
}

/// Overwrites the visibility to extern (imported from another file)
pub fn set_extern(&mut self) {
self.visibility = Linkage::Extern;
}

/// Overwrites the visibility to external (seen outside and inside of the file)
pub fn set_external(&mut self) {
self.visibility = Linkage::External;
}

/// Overwrites the visibility to internal (private)
pub fn set_internal(&mut self) {
self.visibility = Linkage::Internal;
}

/// Activates dynamic arguments
/// Makes that you can supply any argument after the fixed given arguments
pub fn activate_dynamic_arguments(&mut self) {
Expand All @@ -51,6 +74,12 @@ impl FunctionType {

panic!("the func has {} args but args {} is accesed", self.args.len(), num)
}

/// Adds a new argument
pub fn add_arg(&mut self, ty: TypeMetadata) {
self.arg_count = self.args.len();
self.args.push((format!("%{}", self.arg_count), ty));
}
}

/// A ir function with a known variable and arg size and count
Expand All @@ -63,6 +92,8 @@ pub struct Function {

pub(crate) linkage: Linkage,
pub(crate) blocks: VecDeque<Block>,

pub(crate) curr_block: usize,
}

impl Function {
Expand All @@ -76,6 +107,8 @@ impl Function {
name: name,

linkage: Linkage::Internal,

curr_block: 0,
}
}

Expand All @@ -97,9 +130,32 @@ impl Function {
/// Adds a new block to the function
pub fn addBlock(&mut self, name: &str) -> BlockId {
self.blocks.push_back(Block::new(name, &self));
self.curr_block = self.blocks.len() - 1;
BlockId(name.to_owned())
}

/// Returns the current block
pub fn currentBlock(&self) -> BlockId {
let curr_block = self.blocks.back().expect("expected current block");
let name = curr_block.name.to_owned();

BlockId(name)
}

/// Sets the current block (Time: `O(n)`)
pub fn setCurrBlock(&mut self, curr_block: BlockId) {
let mut index = 0;

for block in &self.blocks {
if block.name == curr_block.name {
self.curr_block = index;
break;
}

index += 1;
}
}

/// Emits the Ir of the function into a string
pub fn dump(&self) -> String {
if self.linkage == Linkage::Extern {
Expand Down Expand Up @@ -259,4 +315,11 @@ pub fn Func(name: String, ty: FunctionType) -> Function {
pub struct FuncId {
pub(crate) name: String,
pub(crate) ty: FunctionType,
}

impl FuncId {
/// Creates a new function id with the name `name` and type `ty`
pub fn new(name: &String, ty: FunctionType) -> Self {
Self { name: name.to_owned(), ty }
}
}
2 changes: 1 addition & 1 deletion src/IR/nodes/alloca.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ impl Alloca {
impl Function {
/// Builds an stack allocation (the out var is the pointer to the allocated stack region)
pub fn BuildAlloca(&mut self, ty: TypeMetadata) -> Var {
let block = self.blocks.back_mut().expect("the IRBuilder needs to have an current block\nConsider creating one");
let block = self.blocks.get_mut(self.curr_block).expect("invalid current block");

let out = Var::new(block, TypeMetadata::ptr);

Expand Down
6 changes: 3 additions & 3 deletions src/IR/nodes/assign.rs
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,7 @@ pub trait BuildAssign<T> {
}
impl BuildAssign<Type> for Function {
fn BuildAssign(&mut self, value: Type) -> Var {
let block = self.blocks.back_mut().expect("the IRBuilder needs to have an current block\nConsider creating one");
let block = self.blocks.get_mut(self.curr_block).expect("invalid current block");

let out = Var::new(block, value.into());

Expand All @@ -259,7 +259,7 @@ impl BuildAssign<Type> for Function {

impl BuildAssign<Var> for Function {
fn BuildAssign(&mut self, value: Var) -> Var {
let block = self.blocks.back_mut().expect("the IRBuilder needs to have an current block\nConsider creating one");
let block = self.blocks.get_mut(self.curr_block).expect("invalid current block");

let out = Var::new(block, value.ty);

Expand All @@ -271,7 +271,7 @@ impl BuildAssign<Var> for Function {

impl BuildAssign<&Const> for Function {
fn BuildAssign(&mut self, value: &Const) -> Var {
let block = self.blocks.back_mut().expect("the IRBuilder needs to have an current block\nConsider creating one");
let block = self.blocks.get_mut(self.curr_block).expect("invalid current block");

let out = Var::new(block, TypeMetadata::ptr);

Expand Down
4 changes: 2 additions & 2 deletions src/IR/nodes/br.rs
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ pub trait BuildBr<T> {

impl BuildBr<&BlockId> for Function {
fn BuildBr(&mut self, to: &BlockId) {
let block = self.blocks.back_mut().expect("the IRBuilder needs to have an current block\nConsider creating one");
let block = self.blocks.get_mut(self.curr_block).expect("invalid current block");

block.push_ir(Br::new( to.to_owned() ));
}
Expand All @@ -198,7 +198,7 @@ pub trait BuildBrCond<T, U, Z> {

impl BuildBrCond<Var, &BlockId, &BlockId> for Function {
fn BuildBrCond(&mut self, val: Var, iftrue: &BlockId, iffalse: &BlockId) {
let block = self.blocks.back_mut().expect("the IRBuilder needs to have an current block\nConsider creating one");
let block = self.blocks.get_mut(self.curr_block).expect("invalid current block");

block.push_ir( BrCond::new(val, iftrue.to_owned(), iffalse.to_owned()));
}
Expand Down
2 changes: 1 addition & 1 deletion src/IR/nodes/call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ pub trait BuildCall<T, U> {
}
impl BuildCall<&FuncId, Vec<IROperand>> for Function {
fn BuildCall(&mut self, func: &FuncId, args: Vec<IROperand>) -> Var {
let block = self.blocks.back_mut().expect("the IRBuilder needs to have an current block\nConsider creating one");
let block = self.blocks.get_mut(self.curr_block).expect("invalid current block");

let out = Var::new(block, func.ty.ret);

Expand Down
4 changes: 2 additions & 2 deletions src/IR/nodes/cast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ pub trait BuildCast<T, U> {

impl BuildCast<Var, TypeMetadata> for Function {
fn BuildCast(&mut self, var: Var, ty: TypeMetadata) -> Var {
let block = self.blocks.back_mut().expect("the IRBuilder needs to have an current block\nConsider creating one");
let block = self.blocks.get_mut(self.curr_block).expect("invalid current block");

let out = Var::new(block, ty);

Expand All @@ -156,7 +156,7 @@ impl BuildCast<Var, TypeMetadata> for Function {

impl BuildCast<Type, TypeMetadata> for Function {
fn BuildCast(&mut self, value: Type, ty: TypeMetadata) -> Var {
let block = self.blocks.back_mut().expect("the IRBuilder needs to have an current block\nConsider creating one");
let block = self.blocks.get_mut(self.curr_block).expect("invalid current block");

let out = Var::new(block, ty);

Expand Down
24 changes: 12 additions & 12 deletions src/IR/nodes/cmp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ use super::{Assign, Cmp, EvalOptVisitor, IROperand, Ir, IsNode};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum CmpMode {
/// ls == rs
Eqal,
Equal,
/// ls != rs
NotEqal,
NotEuqal,
/// ls > rs
GreaterThan,
/// ls < rs
Expand All @@ -25,8 +25,8 @@ pub enum CmpMode {
impl Display for CmpMode {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", match self {
CmpMode::Eqal => "eq",
CmpMode::NotEqal => "ne",
CmpMode::Equal => "eq",
CmpMode::NotEuqal => "ne",
CmpMode::GreaterThan => "ge",
CmpMode::LessThan => "le",
CmpMode::GreaterThanOrEqual => "gte",
Expand Down Expand Up @@ -119,8 +119,8 @@ impl Ir for Cmp {

fn calc_based_on_mode(mode: &CmpMode, ls: &Type, rs: &Type, out: Var) -> Option<Box<dyn Ir>> {
let condition_met = match mode {
CmpMode::Eqal => ls.val() == rs.val(),
CmpMode::NotEqal => ls.val() != rs.val(),
CmpMode::Equal => ls.val() == rs.val(),
CmpMode::NotEuqal => ls.val() != rs.val(),
CmpMode::GreaterThan => ls.val() > rs.val(),
CmpMode::LessThan => ls.val() < rs.val(),
CmpMode::GreaterThanOrEqual => ls.val() >= rs.val(),
Expand All @@ -146,8 +146,8 @@ impl EvalOptVisitor for Cmp {
fn eval(&self) -> Option<Box<dyn Ir>> {
if self.ls == self.rs {
let yes = match self.mode {
CmpMode::Eqal => 1,
CmpMode::NotEqal => 0,
CmpMode::Equal => 1,
CmpMode::NotEuqal => 0,
CmpMode::GreaterThan => 0,
CmpMode::LessThan => 0,
CmpMode::GreaterThanOrEqual => 1,
Expand Down Expand Up @@ -218,7 +218,7 @@ pub trait BuildCmp<T, U> {

impl BuildCmp<Var, Var> for Function {
fn BuildCmp(&mut self, mode: CmpMode, ls: Var, rs: Var) -> Var {
let block = self.blocks.back_mut().expect("the IRBuilder needs to have an current block\nConsider creating one");
let block = self.blocks.get_mut(self.curr_block).expect("invalid current block");

let out = Var::new(block, TypeMetadata::u8);

Expand All @@ -230,7 +230,7 @@ impl BuildCmp<Var, Var> for Function {

impl BuildCmp<Var, Type> for Function {
fn BuildCmp(&mut self, mode: CmpMode, ls: Var, rs: Type) -> Var {
let block = self.blocks.back_mut().expect("the IRBuilder needs to have an current block\nConsider creating one");
let block = self.blocks.get_mut(self.curr_block).expect("invalid current block");

let out = Var::new(block, TypeMetadata::u8);

Expand All @@ -242,7 +242,7 @@ impl BuildCmp<Var, Type> for Function {

impl BuildCmp<Type, Var> for Function {
fn BuildCmp(&mut self, mode: CmpMode, ls: Type, rs: Var) -> Var {
let block = self.blocks.back_mut().expect("the IRBuilder needs to have an current block\nConsider creating one");
let block = self.blocks.get_mut(self.curr_block).expect("invalid current block");

let out = Var::new(block, TypeMetadata::u8);

Expand All @@ -254,7 +254,7 @@ impl BuildCmp<Type, Var> for Function {

impl BuildCmp<Type, Type> for Function {
fn BuildCmp(&mut self, mode: CmpMode, ls: Type, rs: Type) -> Var {
let block = self.blocks.back_mut().expect("the IRBuilder needs to have an current block\nConsider creating one");
let block = self.blocks.get_mut(self.curr_block).expect("invalid current block");

let out = Var::new(block, TypeMetadata::u8);

Expand Down
2 changes: 1 addition & 1 deletion src/IR/nodes/debug.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ impl IsNode for DebugNode {
impl Function {
/// Sets the source location for debugging (all of the ir nodes will respond to the location till an new location is set)
pub fn BuildDebug(&mut self, line: i64, coloumn: i64, file: PathBuf) {
let block = self.blocks.back_mut().expect("the IRBuilder needs to have an current block\nConsider creating one");
let block = self.blocks.get_mut(self.curr_block).expect("invalid current block");

block.push_ir( Box::new( DebugNode {
line: line,
Expand Down
2 changes: 1 addition & 1 deletion src/IR/nodes/getelemptr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ impl Function {
/// }
/// ```
pub fn BuildGetelemptr(&mut self, var: Var, index: Var, ty: TypeMetadata) -> Var {
let block = self.blocks.back_mut().expect("expected current block");
let block = self.blocks.get_mut(self.curr_block).expect("invalid current block");

let out = Var::new(block, ty);

Expand Down
2 changes: 1 addition & 1 deletion src/IR/nodes/load.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ impl EvalOptVisitor for Load {
impl Function {
/// the load instruction loads an value from an pointer into a normal variable
pub fn BuildLoad(&mut self, ptr: Var, ty: TypeMetadata) -> Var {
let block = self.blocks.back_mut().expect("the IRBuilder needs to have an current block\nConsider creating one");
let block = self.blocks.get_mut(self.curr_block).expect("invalid current block");

let out = Var::new(block, ty);

Expand Down
8 changes: 4 additions & 4 deletions src/IR/nodes/math.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ macro_rules! MathIrNode {

impl $build_trait<Type, Type> for Function {
fn $build_func(&mut self, op0: Type, op1: Type) -> Var {
let block = self.blocks.back_mut().expect("the IRBuilder needs to have an current block\nConsider creating one");
let block = self.blocks.get_mut(self.curr_block).expect("invalid current block");

let op0Ty: TypeMetadata = op0.into();

Expand All @@ -25,7 +25,7 @@ macro_rules! MathIrNode {

impl $build_trait<Var, Type> for Function {
fn $build_func(&mut self, op0: Var, op1: Type) -> Var {
let block = self.blocks.back_mut().expect("the IRBuilder needs to have an current block\nConsider creating one");
let block = self.blocks.get_mut(self.curr_block).expect("invalid current block");

let op0Ty: TypeMetadata = op0.ty.into();

Expand All @@ -40,7 +40,7 @@ macro_rules! MathIrNode {

impl $build_trait<Type, Var> for Function {
fn $build_func(&mut self, op0: Type, op1: Var) -> Var {
let block = self.blocks.back_mut().expect("the IRBuilder needs to have an current block\nConsider creating one");
let block = self.blocks.get_mut(self.curr_block).expect("invalid current block");

let op0Ty: TypeMetadata = op0.into();

Expand All @@ -55,7 +55,7 @@ macro_rules! MathIrNode {

impl $build_trait<Var, Var> for Function {
fn $build_func(&mut self, op0: Var, op1: Var) -> Var {
let block = self.blocks.back_mut().expect("the IRBuilder needs to have an current block\nConsider creating one");
let block = self.blocks.get_mut(self.curr_block).expect("invalid current block");

let op0Ty: TypeMetadata = op0.ty.into();

Expand Down
2 changes: 1 addition & 1 deletion src/IR/nodes/neg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ impl Function {
panic!("variables need to be signed to get negated");
}

let block = self.blocks.back_mut().expect("expects current block");
let block = self.blocks.get_mut(self.curr_block).expect("invalid current block");

let out = Var::new(block, var.ty);

Expand Down
2 changes: 1 addition & 1 deletion src/IR/nodes/phi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ impl IsNode for Phi {
impl Function {
/// Builds the phi node which recives variables from different blocks
pub fn BuildPhi(&mut self, typ: TypeMetadata, recipients: Vec<(&Block, Var)>) -> Var {
let block = self.blocks.back_mut().expect("expected valid current block.\nConsider creating one");
let block = self.blocks.get_mut(self.curr_block).expect("invalid current block");

let mut owned_recipients = Vec::new();

Expand Down
Loading