Skip to content

Commit

Permalink
[FIX] trying fix for #8
Browse files Browse the repository at this point in the history
  • Loading branch information
Cr0a3 committed Aug 27, 2024
1 parent 1cb2720 commit e6caf51
Show file tree
Hide file tree
Showing 8 changed files with 104 additions and 58 deletions.
4 changes: 4 additions & 0 deletions src/Target/target_descr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,11 @@ pub(crate) struct BackendInfos {
pub(crate) openUsableRegisters16: VecDeque<Box<dyn Reg>>,
pub(crate) openUsableRegisters8: VecDeque<Box<dyn Reg>>,
pub(crate) tmpReg: Box<dyn Reg>,

pub(crate) saveRegister: Vec<Box<dyn Reg>>,
pub(crate) savedRegisters: Vec<Box<dyn Reg>>,
pub(crate) mutable: Vec<Box<dyn Reg>>,

pub(crate) stackSafe: bool,

pub(crate) shadow: i64,
Expand All @@ -30,6 +33,7 @@ impl BackendInfos {
openUsableRegisters32: VecDeque::new(),
openUsableRegisters16: VecDeque::new(),
openUsableRegisters8: VecDeque::new(),
mutable: vec![],

tmpReg: x64Reg::Rax.boxed(),

Expand Down
24 changes: 14 additions & 10 deletions src/Target/x64/asm/instr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,10 +133,8 @@ impl Instr {
} else {rex = Some(mem.rex())}
}

op.extend_from_slice(&ModRm::regM(
*op0,
mem.clone()
));
op.push(mem.encode(None).0 | op0.enc() << 3 | 0b100);
op.extend_from_slice(&mem.encode(None).1);

} else { todo!() }

Expand Down Expand Up @@ -322,7 +320,7 @@ impl Instr {
(vec![], None)
}
}
Mnemonic::Debug => (vec![], None),
Mnemonic::Debug | Mnemonic::StartOptimization | Mnemonic::EndOptimization => (vec![], None),
})
}

Expand Down Expand Up @@ -402,7 +400,7 @@ impl Instr {
}
}
}
Mnemonic::Link | Mnemonic::Debug => {},
Mnemonic::Link | Mnemonic::Debug | Mnemonic::StartOptimization | Mnemonic::EndOptimization => {},
Mnemonic::Endbr64 => {
if self.op1.is_some() || self.op2.is_some() {
Err(InstrEncodingError::InvalidVariant(self.clone(), "endbr64 can't have operands".to_string()))?
Expand Down Expand Up @@ -562,6 +560,10 @@ pub enum Mnemonic {
Link,
/// for debugging pourpusis
Debug,
/// start optimization again
StartOptimization,
/// stop optimization
EndOptimization,
}

impl FromStr for Mnemonic {
Expand Down Expand Up @@ -608,6 +610,8 @@ impl Display for Mnemonic {
Mnemonic::Jmp => "jmp",
Mnemonic::Endbr64 => "endbr64",
Mnemonic::Link => "",
Mnemonic::StartOptimization => "",
Mnemonic::EndOptimization => "",
Mnemonic::Debug => "#",
})
}
Expand Down Expand Up @@ -687,11 +691,11 @@ impl MemOp {
modrm |= 0b00 << 6;
} else if self.displ >= -128 && self.displ <= 127 {
modrm |= 0b01 << 6;
scale = 1;
scale = 0b01 << 6;
displ.push(self.displ as u8);
} else {
modrm |= 0b10 << 6;
scale = 4;
scale = 0b10;
displ.extend_from_slice(&(self.displ as i32).to_le_bytes());
}

Expand Down Expand Up @@ -823,7 +827,7 @@ impl Add<u32> for x64Reg {
MemOp {
base: Some(self.boxed()),
index: None,
scale: 2,
scale: 1,
displ: rhs as isize,
rip: false,
}
Expand Down Expand Up @@ -851,7 +855,7 @@ impl Sub<u32> for x64Reg {
MemOp {
base: Some(self.boxed()),
index: None,
scale: 2,
scale: 1,
displ: -(rhs as isize),
rip: false,
}
Expand Down
17 changes: 15 additions & 2 deletions src/Target/x64/asm/optimizer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,23 @@ impl Optimize<Instr> for Vec<Instr> {
fn optimize(&mut self) -> Vec<Instr> {
let mut out: Vec<Instr> = vec![];

let mut optimize = false;

for instr in self.iter() {
let mut optimized = false;


if instr.mnemonic == Mnemonic::StartOptimization {
optimize = true;
}

if instr.mnemonic == Mnemonic::EndOptimization {
optimize = false;
}

if !optimize {
out.push(instr.to_owned());
continue;
}

let last = out.last().cloned();
if let Some(last) = &last {
Expand Down Expand Up @@ -55,7 +68,7 @@ impl Optimize<Instr> for Vec<Instr> {
}
if instr.mnemonic == Mnemonic::Ret && last.mnemonic == Mnemonic::Call {
out.pop();
out.push(Instr::with1(Mnemonic::Jmp, instr.op1.clone().expect("call needs to have only one op")));
out.push(Instr::with1(Mnemonic::Jmp, instr.op1.clone().expect("call needs to have one op")));
optimized = true;
}
if instr.mnemonic == Mnemonic::Ret {
Expand Down
2 changes: 1 addition & 1 deletion src/Target/x64/asm/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ impl x64Parser {
Err(ParsingError::UnexpectedToken(token.clone()))?
} else { todo!() }

if let Some(Token::L_Bracket) = self.tokens.front() {} else {
if let Some(Token::R_Bracket) = self.tokens.front() {} else {
let mut sub = false;
if let Some(Token::Sub) = self.tokens.front() { sub = true; self.tokens.pop_front(); }
if let Some(Token::Add) = self.tokens.front() { sub = false; self.tokens.pop_front(); }
Expand Down
90 changes: 53 additions & 37 deletions src/Target/x64/compilation/call.rs
Original file line number Diff line number Diff line change
@@ -1,44 +1,62 @@
use std::collections::HashMap;

use super::*;

pub(crate) fn CompileCall(call: &Call<Function, Vec<Var>, Var>, registry: &mut TargetBackendDescr) -> Vec<Instr> {
let boxed: Box<dyn Ir> = Box::new(call.clone());
let block = registry.block.unwrap();

let mut asm = vec![];

let mut to_pop = vec![];

for reg in vec![x64Reg::Rcx, x64Reg::Rdx, x64Reg::Rsi, x64Reg::Rdi, x64Reg::Rsi] { // save mutable registers
if !registry.backend.openUsableRegisters64.contains(&reg.boxed()) {
let var = registry.backend.getVarByReg(reg.boxed()).cloned();

if let Some(var) = var {
if block.isVarUsedAfterNode(&boxed, &var) {
asm.push(Instr::with1(Mnemonic::Push, Operand::Reg(reg.boxed())));
to_pop.push(reg);
}
let mut asm = vec![
Instr::with0(Mnemonic::EndOptimization),
];

registry.backend.stackSafe = true;

let mut saved_var_memory_locations = HashMap::new();

let mut offset = registry.backend.currStackOffsetForLocalVars + 8;

for reg in &registry.backend.mutable {
if !registry.backend.openUsableRegisters64.contains(reg) { // is a variable in the reg
let var = registry.backend.getVarByReg(reg.clone());

if let Some(var) = var { // get the var
asm.push( Instr::with2(Mnemonic::Mov, Operand::Mem(x64Reg::Rbp - (offset as u32)), Operand::Reg(reg.clone())) );
saved_var_memory_locations.insert(var.clone(), offset);
offset += 8;
}
}
}

let func = &call.inner1;

let mut reg_args = 0;

for arg in &call.inner2 {
let loc = registry.backend.varsStorage.get_key_value(arg).expect("expected valid variable as arg input");
let loc = if let Some((x, y)) = registry.backend.varsStorage.get_key_value(arg) {
(x, y)
} else {
panic!("unknown variable {}", arg);
};

match loc.1 {
VarStorage::Register(reg) => {
if reg_args < registry.call.regArgs() {
match arg.ty {

let args = match arg.ty {
TypeMetadata::i64 | TypeMetadata::u64 | TypeMetadata::ptr =>
asm.push( Instr::with2(Mnemonic::Mov, Operand::Reg(registry.call.args64()[reg_args].boxed()), Operand::Reg(reg.clone()))),
registry.call.args64(),
TypeMetadata::i32 | TypeMetadata::u32 =>
asm.push( Instr::with2(Mnemonic::Mov, Operand::Reg(registry.call.args32()[reg_args].boxed()), Operand::Reg(reg.clone()))),
registry.call.args32(),
TypeMetadata::i16 | TypeMetadata::u16 =>
asm.push( Instr::with2(Mnemonic::Mov, Operand::Reg(registry.call.args16()[reg_args].boxed()), Operand::Reg(reg.clone()))),
TypeMetadata::Void => {},
registry.call.args16(),
TypeMetadata::Void => vec![],
};

if args.contains(reg.as_any().downcast_ref::<x64Reg>().unwrap()) {
if let Some(offset) = saved_var_memory_locations.get(arg) {
asm.push( Instr::with2(Mnemonic::Mov, Operand::Reg(args[reg_args].boxed()), Operand::Mem(x64Reg::Rbp - (*offset as u32))));
}
} else {
asm.push(Instr::with2(Mnemonic::Mov, Operand::Reg(args[reg_args].boxed()), Operand::Reg(reg.clone())));
}

reg_args += 1;
Expand All @@ -61,22 +79,14 @@ pub(crate) fn CompileCall(call: &Call<Function, Vec<Var>, Var>, registry: &mut T
}
},
}
if !block.isVarUsedAfterNode(&boxed, arg) {
registry.backend.drop(arg);
}
}

if registry.call.reset_eax() {
asm.push(Instr::with2(Mnemonic::Xor, Operand::Reg(x64Reg::Eax.boxed()), Operand::Reg(x64Reg::Eax.boxed())));
}

asm.push( Instr::with1(Mnemonic::Call, Operand::Imm(0)));
asm.push( Instr::with1(Mnemonic::Call, Operand::Imm(0)) );
asm.push( Instr::with1(Mnemonic::Link, Operand::LinkDestination(call.inner1.name.to_string(), -4)) );

asm.push( Instr::with1(Mnemonic::Link, Operand::LinkDestination(call.inner1.name.to_string(), -4)));

if func.ty.ret != TypeMetadata::Void && block.isVarUsedAfterNode(&boxed, &call.inner3){
if call.inner1.ty.ret != TypeMetadata::Void && block.isVarUsedAfterNode(&boxed, &call.inner3){
let store = if let Some(reg) = registry.backend.getOpenRegBasedOnTy(call.inner3.ty) {
match func.ty.ret {
match call.inner1.ty.ret {
TypeMetadata::u16 | TypeMetadata::i16 => asm.push( Instr::with2(Mnemonic::Mov, Operand::Reg(reg.clone()), Operand::Reg(registry.call.ret16().boxed())) ),
TypeMetadata::u32 | TypeMetadata::i32 => asm.push( Instr::with2(Mnemonic::Mov, Operand::Reg(reg.clone()), Operand::Reg(registry.call.ret32().boxed())) ),
TypeMetadata::u64 | TypeMetadata::i64 => asm.push( Instr::with2(Mnemonic::Mov, Operand::Reg(reg.clone()), Operand::Reg(registry.call.ret64().boxed())) ),
Expand All @@ -94,7 +104,7 @@ pub(crate) fn CompileCall(call: &Call<Function, Vec<Var>, Var>, registry: &mut T
registry.backend.currStackOffsetForLocalVars += addend;
let mem = x64Reg::Rbp - (registry.backend.currStackOffsetForLocalVars - addend) as u32;

match func.ty.ret {
match call.inner1.ty.ret {
TypeMetadata::u16 | TypeMetadata::i16 => asm.push( Instr::with2(Mnemonic::Mov, Operand::Mem(mem.clone()), Operand::Reg(registry.call.ret16().boxed())) ),
TypeMetadata::u32 | TypeMetadata::i32 => asm.push( Instr::with2(Mnemonic::Mov, Operand::Mem(mem.clone()), Operand::Reg(registry.call.ret32().boxed())) ),
TypeMetadata::u64 | TypeMetadata::i64 => asm.push( Instr::with2(Mnemonic::Mov, Operand::Mem(mem.clone()), Operand::Reg(registry.call.ret64().boxed())) ),
Expand All @@ -106,10 +116,16 @@ pub(crate) fn CompileCall(call: &Call<Function, Vec<Var>, Var>, registry: &mut T

registry.backend.insertVar(call.inner3.clone(), store);
}

for reg in to_pop {
asm.push(Instr::with1(Mnemonic::Pop, Operand::Reg(reg.boxed())));

for (var, off) in saved_var_memory_locations {
let reg = if let Some(VarStorage::Register(reg)) = registry.backend.varsStorage.get(&var) {
reg.to_owned()
} else { todo!() }; // shouldn't happen

asm.push( Instr::with2(Mnemonic::Mov, Operand::Reg(reg), Operand::Mem(x64Reg::Rbp - (off as u32))) );
}

asm.push(Instr::with0(Mnemonic::StartOptimization));

asm
}
12 changes: 5 additions & 7 deletions src/Target/x64/compilation/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,18 +77,16 @@ pub(crate) fn buildAsmX86<'a>(block: &'a Block, func: &Function, call: &CallConv

registry.block = None;

let mut out = Vec::from(out);

auto_max_optimize(&mut out);

let mut out = VecDeque::from(out);

out.extend(x64BuildEpilog(&block, registry));

for epAsm in x64BuildProlog(&block, registry) {
out.push_front(epAsm);
}

Vec::from(out)
let mut out = Vec::from(out);

auto_max_optimize(&mut out);

out

}
5 changes: 5 additions & 0 deletions src/Target/x64/compilation/prolog.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ pub(crate) fn x64BuildProlog(_: &Block, registry: &mut TargetBackendDescr) -> Ve
res.push( Instr::with1(Mnemonic::Push, Operand::Reg(backuped.boxed())) )
}

res.push( Instr::with0(Mnemonic::StartOptimization) );

res.reverse();

res
Expand All @@ -22,6 +24,9 @@ pub(crate) fn x64BuildProlog(_: &Block, registry: &mut TargetBackendDescr) -> Ve
pub(crate) fn x64BuildEpilog(_: &Block, registry: &mut TargetBackendDescr) -> Vec<Instr> {
let mut res = vec![];


res.push( Instr::with0(Mnemonic::EndOptimization) );

for backuped in &registry.backend.saveRegister {
res.push( Instr::with1(Mnemonic::Pop, Operand::Reg(backuped.boxed())) )
}
Expand Down
8 changes: 7 additions & 1 deletion src/Target/x64/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,13 @@ pub fn initializeX64Target<'a>(call_conv: CallConv) -> TargetBackendDescr<'a> {
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(),
x64Reg::R12.boxed(), x64Reg::R13.boxed(), x64Reg::R14.boxed(), x64Reg::R15.boxed(),
];

target.backend.mutable = vec![
x64Reg::Rax.boxed(), x64Reg::Rbx.boxed(), x64Reg::Rcx.boxed(), x64Reg::Rdx.boxed(),
x64Reg::Rdi.boxed(), x64Reg::Rsi.boxed(), x64Reg::R8.boxed(), x64Reg::R9.boxed(),
x64Reg::R10.boxed(), x64Reg::R11.boxed(),
];

match call_conv {
Expand Down

0 comments on commit e6caf51

Please sign in to comment.