Skip to content

Commit

Permalink
[TARGET] emiting ir into a object files is now supported
Browse files Browse the repository at this point in the history
  • Loading branch information
Cr0a3 committed Jul 19, 2024
1 parent dba2888 commit 01d8421
Show file tree
Hide file tree
Showing 8 changed files with 138 additions and 53 deletions.
12 changes: 10 additions & 2 deletions examples/simple.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use std::{error::Error, path::Path};
use Ygen::prelude::*;
use std::{error::Error, fs::OpenOptions, path::Path};
use Ygen::{prelude::*, Target::initializeAllTargets};

pub fn main() -> Result<(), Box<dyn Error>> {
let mut module = Module();
Expand All @@ -25,5 +25,13 @@ pub fn main() -> Result<(), Box<dyn Error>> {

module.emitToAsmFile(Path::new("out.asm"))?;

module
.emitMachineCode(
Triple::host(),
&mut initializeAllTargets()
)?.emit(
OpenOptions::new().write(true).create(true).open("out.o")?
)?;

Ok(())
}
25 changes: 23 additions & 2 deletions src/IR/module.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::PassManager;
use crate::{prelude::Triple, Obj::{Decl, Linkage, ObjectBuilder}, PassManager, Target::TargetRegistry};

use super::{func::FunctionType, Function, VerifyError};
use std::collections::HashMap;
use std::{collections::HashMap, error::Error};

/// ## The Module
/// The main class for handeling functions
Expand Down Expand Up @@ -80,6 +80,27 @@ impl Module {
func.runPassMngr(&mngr)
}
}

/// emits the machine code of the module into an object file (in the form of an object builder)
pub fn emitMachineCode(&self, triple: Triple, registry: &mut TargetRegistry) -> Result<ObjectBuilder, Box<dyn Error>> {
let mut obj = ObjectBuilder::new(triple);

for (name, func) in &self.funcs {
obj.decl( (&name, Decl::Function, Linkage::External));

let mut comp = vec![];

for block in &func.blocks {
comp.extend_from_slice(
&registry.buildMachineCodeForTarget(triple, block, &func)?
);
}

obj.define(&name, comp);
}

Ok(obj)
}
}

/// Creates a new module
Expand Down
36 changes: 35 additions & 1 deletion src/Target/registry.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::{collections::HashMap, error::Error, fmt::Display};
use std::{collections::{HashMap, VecDeque}, error::Error, fmt::Display};

use crate::prelude::{Block, Function};

Expand Down Expand Up @@ -58,6 +58,40 @@ impl<'a> TargetRegistry<'a> {
))
}
}

/// Builds the ir of the given triple into machine code
pub fn buildMachineCodeForTarget(&mut self, triple: Triple, block: &Block, funct: &Function) -> Result<Vec<u8>, Box<dyn Error>> {
if let Some(org) = self.targets.get_mut(&triple.arch) {

let call = (org.init.unwrap()(triple.getCallConv()?)).call;

println!("{:?}", call);

let asm: VecDeque<String> = org.buildAsm.unwrap()(
&block, &funct,
&call,
&mut org.init.unwrap()(triple.getCallConv()?)).into();

println!("{:#?}", asm);

let mut res = vec![];

for instr in &asm {
let lexed = org.lexer().lex(instr.clone())?;

let mut comp = org.compiler().new(lexed);
comp.parse()?;

res.extend_from_slice(&comp.out());
}

Ok(res)
} else {
Err(Box::from(
RegistryError::UnsuportedArch(triple.arch)
))
}
}
}

/// Stores errors which can occure in the `getBasedOnTriple` function in the `TargetRegistry`
Expand Down
1 change: 0 additions & 1 deletion src/Target/target_descr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,6 @@ impl BackendInfos {
self.savedRegisters.push(reg.boxed());
}


Some(reg)
}

Expand Down
1 change: 1 addition & 0 deletions src/Target/x64/asm/compile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2517,6 +2517,7 @@ pub(crate) fn compile_lea(tokens: &mut VecDeque<Token>) -> Result<Vec<u8>, Box<d
tokens.pop_front(); // skip ,
}
if let Some(Token::Mem(mut op1)) = tokens.pop_front() {
result.push(103);
result.push(141);
result.extend_from_slice(&op1.enc(op0));
} else {
Expand Down
106 changes: 63 additions & 43 deletions src/Target/x64/asm/lexer.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::{error::Error, fmt::Display, num::ParseIntError};
use std::{collections::VecDeque, error::Error, fmt::Display, num::ParseIntError};

use logos::Logos;

Expand Down Expand Up @@ -39,10 +39,10 @@ impl From<ParseIntError> for LexingError {
#[logos(error = LexingError)]
#[doc(hidden)]
pub enum Token {
#[regex("[a-zA-Z0-9_]+", priority = 3, callback = |lex| lex.slice().to_string())]
#[regex("[a-zA-Z0-9_]+", priority = 5, callback = |lex| lex.slice().to_string())]
Ident(String),

#[regex("[0x0-9_]+", priority = 5, callback = |lex| {
#[regex("[0x0-9_]+", priority = 6, callback = |lex| {
let string = lex.slice();
if string.starts_with("0x") {
u64::from_str_radix(&string.replace("0x", ""), 16)
Expand All @@ -57,9 +57,6 @@ pub enum Token {
#[token(",")]
Comma,

#[token("+")]
Add,

#[token(":")]
DoubleDot,

Expand Down Expand Up @@ -268,45 +265,48 @@ pub enum Token {
js,
#[token("endbr32")]
endbr32,
#[token("bl", |_| x64Reg::Bl)]
#[token("bx", |_| x64Reg::Bx)]
#[token("ebx", |_| x64Reg::Ebx)]
#[token("rbx", |_| x64Reg::Rbx)]
#[token("dil", |_| x64Reg::Dil)]
#[token("di", |_| x64Reg::Di)]
#[token("edi", |_| x64Reg::Dil)]
#[token("rdi", |_| x64Reg::Rdi)]
#[token("dl", |_| x64Reg::Dl)]
#[token("dx", |_| x64Reg::Dx)]
#[token("edx", |_| x64Reg::Edx)]
#[token("rdx", |_| x64Reg::Rdx)]
#[token("sil", |_| x64Reg::Sil)]
#[token("si", |_| x64Reg::Si)]
#[token("esi", |_| x64Reg::Esi)]
#[token("rsi", |_| x64Reg::Rsi)]
#[token("spl", |_| x64Reg::Spl)]
#[token("sp", |_| x64Reg::Sp)]
#[token("esp", |_| x64Reg::Esp)]
#[token("rsp", |_| x64Reg::Rsp)]
#[token("al", |_| x64Reg::Al)]
#[token("ax", |_| x64Reg::Ax)]
#[token("eax", |_| x64Reg::Eax)]
#[token("rax", |_| x64Reg::Rax)]
#[token("bpl", |_| x64Reg::Bpl)]
#[token("bp", |_| x64Reg::Bp)]
#[token("ebp", |_| x64Reg::Ebp)]
#[token("rbp", |_| x64Reg::Rbp)]
#[token("cl", |_| x64Reg::Cl)]
#[token("cx", |_| x64Reg::Cx)]
#[token("ecx", |_| x64Reg::Ecx)]
#[token("rcx", |_| x64Reg::Rcx)]
#[token("bl", |_| x64Reg::Bl, priority=6)]
#[token("bx", |_| x64Reg::Bx, priority=6)]
#[token("ebx", |_| x64Reg::Ebx, priority=6)]
#[token("rbx", |_| x64Reg::Rbx, priority=6)]
#[token("dil", |_| x64Reg::Dil, priority=6)]
#[token("di", |_| x64Reg::Di, priority=6)]
#[token("edi", |_| x64Reg::Edi, priority=6)]
#[token("rdi", |_| x64Reg::Rdi, priority=6)]
#[token("dl", |_| x64Reg::Dl, priority=6)]
#[token("dx", |_| x64Reg::Dx, priority=6)]
#[token("edx", |_| x64Reg::Edx, priority=6)]
#[token("rdx", |_| x64Reg::Rdx, priority=6)]
#[token("sil", |_| x64Reg::Sil, priority=6)]
#[token("si", |_| x64Reg::Si, priority=6)]
#[token("esi", |_| x64Reg::Esi, priority=6)]
#[token("rsi", |_| x64Reg::Rsi, priority=6)]
#[token("spl", |_| x64Reg::Spl, priority=6)]
#[token("sp", |_| x64Reg::Sp, priority=6)]
#[token("esp", |_| x64Reg::Esp, priority=6)]
#[token("rsp", |_| x64Reg::Rsp, priority=6)]
#[token("al", |_| x64Reg::Al, priority=6)]
#[token("ax", |_| x64Reg::Ax, priority=6)]
#[token("eax", |_| x64Reg::Eax, priority=6)]
#[token("rax", |_| x64Reg::Rax, priority=6)]
#[token("bpl", |_| x64Reg::Bpl, priority=6)]
#[token("bp", |_| x64Reg::Bp, priority=6)]
#[token("ebp", |_| x64Reg::Ebp, priority=6)]
#[token("rbp", |_| x64Reg::Rbp, priority=6)]
#[token("cl", |_| x64Reg::Cl, priority=6)]
#[token("cx", |_| x64Reg::Cx, priority=6)]
#[token("ecx", |_| x64Reg::Ecx, priority=6)]
#[token("rcx", |_| x64Reg::Rcx, priority=6)]
Reg(x64Reg),

#[regex(r"[a-zA-Z0-9\[\]]+", priority = 2, callback = |lex| {
#[regex(r#"\[(\s*(\w+)\s*(\+\s*(\w+)\s*)?(\*\s*(1|2|4|8)\s*)?(\+\s*-?\d+|0x[0-9a-fA-F]+)?\s*)?\]"#, priority = 4, callback = |lex| {
let string = lex.slice().to_string();
Mem::from(&string)
})]
Mem(Mem),

#[token("+", priority=5)]
Add,
}

/// An assembly memory displacement
Expand All @@ -320,22 +320,42 @@ impl Mem {
/// Parses the string into an memory displacement
pub fn from(string: &str) -> Result<Self, Box<dyn Error>> {
let string = string.replace("[", "").replace("]", "");
let mut tokens = vec![];

let mut tokens: VecDeque<Token> = VecDeque::new();

for tok in Token::lexer(&string) {
tokens.push( tok?)
tokens.push_back( tok? )
}
if let Some(Token::Num(x)) = tokens.first() {

if let Some(Token::Num(x)) = tokens.front() {
let mut enc = vec![0b100, 0 | 0b100 << 3 | 0b101];
enc.extend_from_slice(&(*x as u32).to_le_bytes().to_vec());
Ok(Self {
enc: enc,
})
} else if let Some(Token::Reg(op0)) = tokens.front() {
if let Some(Token::Add) = tokens.get(1) {
if let Some(Token::Reg(op1)) = tokens.get(2) {
let enc = vec![0b00000100, 0 | op1.enc() << 3 | op0.enc()];
Ok(Self {
enc: enc,
})
} else if let Some(Token::Num(x)) = tokens.get(2) {
todo!()
} else { todo!("print error") }
} else {
let enc = vec![0 | op0.enc()];
Ok(Self {
enc: enc,
})
}

} else { todo!() }
}

/// Returns the encoded
pub fn enc(&mut self, op0: x64Reg) -> Vec<u8> {
self.enc[0] = 0b100 | op0.enc() << 3;
self.enc[0] |= op0.enc() << 3;
self.enc.clone()
}
}
Expand Down
2 changes: 2 additions & 0 deletions src/Target/x64/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ pub fn initializeX64Target<'a>(call_conv: CallConv) -> TargetBackendDescr<'a> {
target.lexer = Some(x64Lexer {}.boxed());
target.compile = Some(x64Compiler::new().boxed());

target.call = call_conv;

target.backend.savedRegisters = vec![
x64Reg::R10.boxed(), x64Reg::R11.boxed(), x64Reg::R12.boxed(), x64Reg::R13.boxed(), x64Reg::R14.boxed(), x64Reg::R15.boxed(),
];
Expand Down
8 changes: 4 additions & 4 deletions src/Target/x64/reg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -179,10 +179,10 @@ impl Reg for x64Reg {
x64Reg::Rcx | x64Reg::Ecx | x64Reg::Cx | x64Reg::Cl => 1,
x64Reg::Rdx | x64Reg::Edx | x64Reg::Dx | x64Reg::Dl => 2,
x64Reg::Rbx | x64Reg::Ebx | x64Reg::Bx | x64Reg::Bl => 3,
x64Reg::Rsi | x64Reg::Esi | x64Reg::Si | x64Reg::Sil => 4,
x64Reg::Rdi | x64Reg::Edi | x64Reg::Di | x64Reg::Dil => 5,
x64Reg::Rsp | x64Reg::Esp | x64Reg::Sp | x64Reg::Spl => 6,
x64Reg::Rbp | x64Reg::Ebp | x64Reg::Bp | x64Reg::Bpl => 0,
x64Reg::Rsi | x64Reg::Esi | x64Reg::Si | x64Reg::Sil => 6,
x64Reg::Rbp | x64Reg::Ebp | x64Reg::Bp | x64Reg::Bpl => 5,
x64Reg::Rsp | x64Reg::Esp | x64Reg::Sp | x64Reg::Spl => 4,
x64Reg::Rdi | x64Reg::Edi | x64Reg::Di | x64Reg::Dil => 7,

// this here use a prefix
x64Reg::R8 | x64Reg::R8d | x64Reg::R8w | x64Reg::R8b => 1,
Expand Down

0 comments on commit 01d8421

Please sign in to comment.