mirror of
https://github.com/kmc7468/cs420.git
synced 2025-12-16 23:48:48 +00:00
HW7 (3)
This commit is contained in:
@@ -1,3 +1,4 @@
|
|||||||
|
use core::f32;
|
||||||
use std::collections::{BTreeMap, HashMap, HashSet, VecDeque};
|
use std::collections::{BTreeMap, HashMap, HashSet, VecDeque};
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
|
|
||||||
@@ -7,23 +8,13 @@ use crate::ir::HasDtype;
|
|||||||
use crate::opt::opt_utils;
|
use crate::opt::opt_utils;
|
||||||
use crate::{Translate, asm, ir};
|
use crate::{Translate, asm, ir};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Default)]
|
||||||
pub struct Asmgen {
|
pub struct Asmgen {
|
||||||
functions: Vec<asm::Section<asm::Function>>,
|
functions: Vec<asm::Section<asm::Function>>,
|
||||||
variables: Vec<asm::Section<asm::Variable>>,
|
variables: Vec<asm::Section<asm::Variable>>,
|
||||||
phinode_counter: usize,
|
phinode_counter: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Asmgen {
|
|
||||||
fn default() -> Self {
|
|
||||||
Asmgen {
|
|
||||||
functions: Vec::new(),
|
|
||||||
variables: Vec::new(),
|
|
||||||
phinode_counter: 0,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Translate<ir::TranslationUnit> for Asmgen {
|
impl Translate<ir::TranslationUnit> for Asmgen {
|
||||||
type Target = asm::Asm;
|
type Target = asm::Asm;
|
||||||
type Error = ();
|
type Error = ();
|
||||||
@@ -37,8 +28,8 @@ impl Translate<ir::TranslationUnit> for Asmgen {
|
|||||||
|
|
||||||
Ok(asm::Asm {
|
Ok(asm::Asm {
|
||||||
unit: asm::TranslationUnit {
|
unit: asm::TranslationUnit {
|
||||||
functions: std::mem::replace(&mut self.functions, Vec::new()),
|
functions: std::mem::take(&mut self.functions),
|
||||||
variables: std::mem::replace(&mut self.variables, Vec::new()),
|
variables: std::mem::take(&mut self.variables),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -71,6 +62,15 @@ impl Asmgen {
|
|||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ir::Constant::Float { value, width } => {
|
||||||
|
if width == 32 {
|
||||||
|
asm::Directive::Word((*value as f32).to_bits())
|
||||||
|
} else if width == 64 {
|
||||||
|
asm::Directive::Quad(value.to_bits())
|
||||||
|
} else {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
_ => todo!(),
|
_ => todo!(),
|
||||||
};
|
};
|
||||||
self.variables.push(asm::Section::new(
|
self.variables.push(asm::Section::new(
|
||||||
@@ -111,8 +111,7 @@ impl Asmgen {
|
|||||||
Some(asm::Label::new(name, *bid)),
|
Some(asm::Label::new(name, *bid)),
|
||||||
context.insts,
|
context.insts,
|
||||||
));
|
));
|
||||||
for (label, insts) in std::mem::replace(&mut context.new_blocks, Vec::new())
|
for (label, insts) in std::mem::take(&mut context.new_blocks) {
|
||||||
{
|
|
||||||
blocks.push(asm::Block::new(Some(label), insts));
|
blocks.push(asm::Block::new(Some(label), insts));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -160,46 +159,45 @@ impl Asmgen {
|
|||||||
stack_allocation += 16; // s0, ra
|
stack_allocation += 16; // s0, ra
|
||||||
|
|
||||||
for offset in stack_offsets.values_mut() {
|
for offset in stack_offsets.values_mut() {
|
||||||
*offset = stack_allocation - *offset;
|
*offset = offset.wrapping_sub(stack_allocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut insts = vec![
|
let mut insts = vec![];
|
||||||
asm::Instruction::IType {
|
self.translate_addi(
|
||||||
instr: asm::IType::ADDI,
|
asm::Register::Sp,
|
||||||
rd: asm::Register::Sp,
|
asm::Register::Sp,
|
||||||
rs1: asm::Register::Sp,
|
!stack_allocation + 1,
|
||||||
imm: asm::Immediate::Value(!stack_allocation + 1),
|
&mut insts,
|
||||||
},
|
);
|
||||||
asm::Instruction::SType {
|
self.translate_store(
|
||||||
instr: asm::SType::SD,
|
asm::SType::SD,
|
||||||
rs1: asm::Register::Sp,
|
asm::Register::Sp,
|
||||||
rs2: asm::Register::S0,
|
asm::Register::S0,
|
||||||
imm: asm::Immediate::Value(stack_allocation - 8),
|
stack_allocation - 8,
|
||||||
},
|
&mut insts,
|
||||||
asm::Instruction::IType {
|
);
|
||||||
instr: asm::IType::ADDI,
|
self.translate_addi(
|
||||||
rd: asm::Register::S0,
|
asm::Register::S0,
|
||||||
rs1: asm::Register::Sp,
|
asm::Register::Sp,
|
||||||
imm: asm::Immediate::Value(stack_allocation),
|
stack_allocation,
|
||||||
},
|
&mut insts,
|
||||||
asm::Instruction::SType {
|
);
|
||||||
|
insts.push(asm::Instruction::SType {
|
||||||
instr: asm::SType::SD,
|
instr: asm::SType::SD,
|
||||||
rs1: asm::Register::S0,
|
rs1: asm::Register::S0,
|
||||||
rs2: asm::Register::Ra,
|
rs2: asm::Register::Ra,
|
||||||
imm: asm::Immediate::Value(!16 + 1),
|
imm: asm::Immediate::Value(!16 + 1),
|
||||||
},
|
});
|
||||||
];
|
|
||||||
|
|
||||||
// TODO: Floating point or optimizations
|
// TODO: Floating point or optimizations
|
||||||
for (i, dtype) in signature.params.iter().enumerate() {
|
for (i, dtype) in signature.params.iter().enumerate() {
|
||||||
insts.push(asm::Instruction::SType {
|
self.translate_store(
|
||||||
instr: asm::SType::SD,
|
asm::SType::SD,
|
||||||
rs1: asm::Register::S0,
|
asm::Register::S0,
|
||||||
rs2: asm::Register::arg(asm::RegisterType::Integer, i),
|
asm::Register::arg(asm::RegisterType::Integer, i),
|
||||||
imm: asm::Immediate::Value(
|
|
||||||
stack_offsets[&ir::RegisterId::arg(definition.bid_init, i)],
|
stack_offsets[&ir::RegisterId::arg(definition.bid_init, i)],
|
||||||
),
|
&mut insts,
|
||||||
});
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Context {
|
Context {
|
||||||
@@ -217,18 +215,19 @@ impl Asmgen {
|
|||||||
rs1: asm::Register::S0,
|
rs1: asm::Register::S0,
|
||||||
imm: asm::Immediate::Value(!16 + 1),
|
imm: asm::Immediate::Value(!16 + 1),
|
||||||
});
|
});
|
||||||
context.insts.push(asm::Instruction::IType {
|
self.translate_load(
|
||||||
instr: asm::IType::LD,
|
asm::IType::LD,
|
||||||
rd: asm::Register::S0,
|
asm::Register::S0,
|
||||||
rs1: asm::Register::Sp,
|
asm::Register::Sp,
|
||||||
imm: asm::Immediate::Value(context.stack_allocation - 8),
|
context.stack_allocation - 8,
|
||||||
});
|
&mut context.insts,
|
||||||
context.insts.push(asm::Instruction::IType {
|
);
|
||||||
instr: asm::IType::ADDI,
|
self.translate_addi(
|
||||||
rd: asm::Register::Sp,
|
asm::Register::Sp,
|
||||||
rs1: asm::Register::Sp,
|
asm::Register::Sp,
|
||||||
imm: asm::Immediate::Value(context.stack_allocation),
|
context.stack_allocation,
|
||||||
});
|
&mut context.insts,
|
||||||
|
);
|
||||||
context
|
context
|
||||||
.insts
|
.insts
|
||||||
.push(asm::Instruction::Pseudo(asm::Pseudo::Ret));
|
.push(asm::Instruction::Pseudo(asm::Pseudo::Ret));
|
||||||
@@ -259,24 +258,83 @@ impl Asmgen {
|
|||||||
match op {
|
match op {
|
||||||
ast::BinaryOperator::Multiply => {
|
ast::BinaryOperator::Multiply => {
|
||||||
context.insts.push(asm::Instruction::RType {
|
context.insts.push(asm::Instruction::RType {
|
||||||
instr: asm::RType::mul(operand_dtype),
|
instr: if is_integer(&operand_dtype) {
|
||||||
|
asm::RType::mul(operand_dtype)
|
||||||
|
} else {
|
||||||
|
asm::RType::fmul(operand_dtype)
|
||||||
|
},
|
||||||
|
rd,
|
||||||
|
rs1,
|
||||||
|
rs2: Some(rs2),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
ast::BinaryOperator::Divide => {
|
||||||
|
context.insts.push(asm::Instruction::RType {
|
||||||
|
instr: if is_integer(&operand_dtype) {
|
||||||
|
let is_signed = operand_dtype.is_int_signed();
|
||||||
|
asm::RType::div(operand_dtype, is_signed)
|
||||||
|
} else {
|
||||||
|
asm::RType::fdiv(operand_dtype)
|
||||||
|
},
|
||||||
|
rd,
|
||||||
|
rs1,
|
||||||
|
rs2: Some(rs2),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
ast::BinaryOperator::Modulo => {
|
||||||
|
let is_signed: bool = operand_dtype.is_int_signed();
|
||||||
|
context.insts.push(asm::Instruction::RType {
|
||||||
|
instr: asm::RType::rem(operand_dtype, is_signed),
|
||||||
rd,
|
rd,
|
||||||
rs1,
|
rs1,
|
||||||
rs2: Some(rs2),
|
rs2: Some(rs2),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
ast::BinaryOperator::Plus => context.insts.push(asm::Instruction::RType {
|
ast::BinaryOperator::Plus => context.insts.push(asm::Instruction::RType {
|
||||||
instr: asm::RType::add(operand_dtype),
|
instr: if is_integer(&operand_dtype) {
|
||||||
|
asm::RType::add(operand_dtype)
|
||||||
|
} else {
|
||||||
|
asm::RType::fadd(operand_dtype)
|
||||||
|
},
|
||||||
rd,
|
rd,
|
||||||
rs1,
|
rs1,
|
||||||
rs2: Some(rs2),
|
rs2: Some(rs2),
|
||||||
}),
|
}),
|
||||||
ast::BinaryOperator::Minus => context.insts.push(asm::Instruction::RType {
|
ast::BinaryOperator::Minus => context.insts.push(asm::Instruction::RType {
|
||||||
instr: asm::RType::sub(operand_dtype),
|
instr: if is_integer(&operand_dtype) {
|
||||||
|
asm::RType::sub(operand_dtype)
|
||||||
|
} else {
|
||||||
|
asm::RType::fsub(operand_dtype)
|
||||||
|
},
|
||||||
rd,
|
rd,
|
||||||
rs1,
|
rs1,
|
||||||
rs2: Some(rs2),
|
rs2: Some(rs2),
|
||||||
}),
|
}),
|
||||||
|
ast::BinaryOperator::ShiftLeft => {
|
||||||
|
context.insts.push(asm::Instruction::RType {
|
||||||
|
instr: asm::RType::sll(operand_dtype),
|
||||||
|
rd,
|
||||||
|
rs1,
|
||||||
|
rs2: Some(rs2),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
ast::BinaryOperator::ShiftRight => {
|
||||||
|
if operand_dtype.is_int_signed() {
|
||||||
|
context.insts.push(asm::Instruction::RType {
|
||||||
|
instr: asm::RType::sra(operand_dtype),
|
||||||
|
rd,
|
||||||
|
rs1,
|
||||||
|
rs2: Some(rs2),
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
context.insts.push(asm::Instruction::RType {
|
||||||
|
instr: asm::RType::srl(operand_dtype),
|
||||||
|
rd,
|
||||||
|
rs1,
|
||||||
|
rs2: Some(rs2),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
ast::BinaryOperator::Equals => {
|
ast::BinaryOperator::Equals => {
|
||||||
context.insts.push(asm::Instruction::RType {
|
context.insts.push(asm::Instruction::RType {
|
||||||
instr: asm::RType::Xor,
|
instr: asm::RType::Xor,
|
||||||
@@ -288,6 +346,14 @@ impl Asmgen {
|
|||||||
.insts
|
.insts
|
||||||
.push(asm::Instruction::Pseudo(asm::Pseudo::Seqz { rd, rs: rd }))
|
.push(asm::Instruction::Pseudo(asm::Pseudo::Seqz { rd, rs: rd }))
|
||||||
}
|
}
|
||||||
|
ast::BinaryOperator::NotEquals => {
|
||||||
|
context.insts.push(asm::Instruction::RType {
|
||||||
|
instr: asm::RType::Xor,
|
||||||
|
rd,
|
||||||
|
rs1,
|
||||||
|
rs2: Some(rs2),
|
||||||
|
});
|
||||||
|
}
|
||||||
ast::BinaryOperator::Less => {
|
ast::BinaryOperator::Less => {
|
||||||
// TODO: FLoating point
|
// TODO: FLoating point
|
||||||
context.insts.push(asm::Instruction::RType {
|
context.insts.push(asm::Instruction::RType {
|
||||||
@@ -310,14 +376,120 @@ impl Asmgen {
|
|||||||
rs2: Some(rs1),
|
rs2: Some(rs1),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
ast::BinaryOperator::LessOrEqual => {
|
||||||
|
// TODO: FLoating point
|
||||||
|
context.insts.push(asm::Instruction::RType {
|
||||||
|
instr: asm::RType::Slt {
|
||||||
|
is_signed: operand_dtype.is_int_signed(),
|
||||||
|
},
|
||||||
|
rd,
|
||||||
|
rs1: rs2,
|
||||||
|
rs2: Some(rs1),
|
||||||
|
});
|
||||||
|
context
|
||||||
|
.insts
|
||||||
|
.push(asm::Instruction::Pseudo(asm::Pseudo::Seqz { rd, rs: rd }))
|
||||||
|
}
|
||||||
|
ast::BinaryOperator::GreaterOrEqual => {
|
||||||
|
// TODO: FLoating point
|
||||||
|
context.insts.push(asm::Instruction::RType {
|
||||||
|
instr: asm::RType::Slt {
|
||||||
|
is_signed: operand_dtype.is_int_signed(),
|
||||||
|
},
|
||||||
|
rd,
|
||||||
|
rs1,
|
||||||
|
rs2: Some(rs2),
|
||||||
|
});
|
||||||
|
context
|
||||||
|
.insts
|
||||||
|
.push(asm::Instruction::Pseudo(asm::Pseudo::Seqz { rd, rs: rd }))
|
||||||
|
}
|
||||||
|
ast::BinaryOperator::BitwiseAnd => {
|
||||||
|
context.insts.push(asm::Instruction::RType {
|
||||||
|
instr: asm::RType::And,
|
||||||
|
rd,
|
||||||
|
rs1,
|
||||||
|
rs2: Some(rs2),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
ast::BinaryOperator::BitwiseOr => {
|
||||||
|
context.insts.push(asm::Instruction::RType {
|
||||||
|
instr: asm::RType::Or,
|
||||||
|
rd,
|
||||||
|
rs1,
|
||||||
|
rs2: Some(rs2),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
ast::BinaryOperator::BitwiseXor => {
|
||||||
|
context.insts.push(asm::Instruction::RType {
|
||||||
|
instr: asm::RType::Xor,
|
||||||
|
rd,
|
||||||
|
rs1,
|
||||||
|
rs2: Some(rs2),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
println!("{:?}", op);
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.translate_store_result(&rid, dtype.clone(), rd, context);
|
||||||
|
}
|
||||||
|
ir::Instruction::UnaryOp { op, operand, dtype } => {
|
||||||
|
let rs1 = get_lhs_register(&operand.dtype());
|
||||||
|
let rd = get_res_register(dtype);
|
||||||
|
self.translate_load_operand(operand, rs1, context);
|
||||||
|
match op {
|
||||||
|
ast::UnaryOperator::Minus => {
|
||||||
|
if is_integer(&operand.dtype()) {
|
||||||
|
context
|
||||||
|
.insts
|
||||||
|
.push(asm::Instruction::Pseudo(asm::Pseudo::neg(
|
||||||
|
operand.dtype(),
|
||||||
|
rd,
|
||||||
|
rs1,
|
||||||
|
)));
|
||||||
|
} else {
|
||||||
|
context
|
||||||
|
.insts
|
||||||
|
.push(asm::Instruction::Pseudo(asm::Pseudo::fneg(
|
||||||
|
operand.dtype(),
|
||||||
|
rd,
|
||||||
|
rs1,
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ast::UnaryOperator::Negate => context
|
||||||
|
.insts
|
||||||
|
.push(asm::Instruction::Pseudo(asm::Pseudo::Seqz { rd, rs: rs1 })),
|
||||||
_ => todo!(),
|
_ => todo!(),
|
||||||
}
|
}
|
||||||
self.translate_store_result(&rid, dtype.clone(), rd, context);
|
self.translate_store_result(&rid, dtype.clone(), rd, context);
|
||||||
}
|
}
|
||||||
ir::Instruction::Store { ptr, value } => {
|
ir::Instruction::Store { ptr, value } => {
|
||||||
let (ptr_rid, ptr_dtype) = ptr.get_register().unwrap();
|
|
||||||
let value_dtype = value.dtype().clone();
|
let value_dtype = value.dtype().clone();
|
||||||
match ptr_rid {
|
match ptr {
|
||||||
|
ir::Operand::Constant(ir::Constant::GlobalVariable { name, dtype }) => {
|
||||||
|
let rd = get_lhs_register(dtype);
|
||||||
|
context
|
||||||
|
.insts
|
||||||
|
.push(asm::Instruction::Pseudo(asm::Pseudo::La {
|
||||||
|
rd: asm::Register::T0,
|
||||||
|
symbol: asm::Label(name.clone()),
|
||||||
|
}));
|
||||||
|
let rs2 = get_rhs_register(&value_dtype);
|
||||||
|
self.translate_load_operand(value, rs2, context);
|
||||||
|
context.insts.push(asm::Instruction::SType {
|
||||||
|
instr: asm::SType::store(value_dtype),
|
||||||
|
rs1: rd,
|
||||||
|
rs2,
|
||||||
|
imm: asm::Immediate::Value(0),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
ir::Operand::Register {
|
||||||
|
rid: ptr_rid,
|
||||||
|
dtype: ptr_dtype,
|
||||||
|
} => match ptr_rid {
|
||||||
ir::RegisterId::Temp { .. } => {
|
ir::RegisterId::Temp { .. } => {
|
||||||
let rs1 = get_lhs_register(ptr_dtype);
|
let rs1 = get_lhs_register(ptr_dtype);
|
||||||
let rs2 = get_rhs_register(&value_dtype);
|
let rs2 = get_rhs_register(&value_dtype);
|
||||||
@@ -333,19 +505,22 @@ impl Asmgen {
|
|||||||
ir::RegisterId::Local { aid } => {
|
ir::RegisterId::Local { aid } => {
|
||||||
let rs2 = get_rhs_register(&value_dtype);
|
let rs2 = get_rhs_register(&value_dtype);
|
||||||
self.translate_load_operand(value, rs2, context);
|
self.translate_load_operand(value, rs2, context);
|
||||||
context.insts.push(asm::Instruction::SType {
|
self.translate_store(
|
||||||
instr: asm::SType::store(value_dtype),
|
asm::SType::store(value_dtype),
|
||||||
rs1: asm::Register::S0,
|
asm::Register::S0,
|
||||||
rs2,
|
rs2,
|
||||||
imm: asm::Immediate::Value(context.stack_offsets[ptr_rid]),
|
context.stack_offsets[ptr_rid],
|
||||||
});
|
&mut context.insts,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
_ => todo!(),
|
_ => todo!(),
|
||||||
|
},
|
||||||
|
_ => todo!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ir::Instruction::Load { ptr } => match ptr {
|
ir::Instruction::Load { ptr } => match ptr {
|
||||||
ir::Operand::Constant(ir::Constant::GlobalVariable { name, dtype }) => {
|
ir::Operand::Constant(ir::Constant::GlobalVariable { name, dtype }) => {
|
||||||
let rd = get_lhs_register(&dtype);
|
let rd = get_lhs_register(dtype);
|
||||||
context
|
context
|
||||||
.insts
|
.insts
|
||||||
.push(asm::Instruction::Pseudo(asm::Pseudo::La {
|
.push(asm::Instruction::Pseudo(asm::Pseudo::La {
|
||||||
@@ -380,12 +555,13 @@ impl Asmgen {
|
|||||||
}
|
}
|
||||||
ir::RegisterId::Local { aid } => {
|
ir::RegisterId::Local { aid } => {
|
||||||
let rs1 = get_lhs_register(ptr_dtype);
|
let rs1 = get_lhs_register(ptr_dtype);
|
||||||
context.insts.push(asm::Instruction::IType {
|
self.translate_load(
|
||||||
instr: asm::IType::load(value_dtype.clone()),
|
asm::IType::load(value_dtype.clone()),
|
||||||
rd,
|
rd,
|
||||||
rs1: asm::Register::S0,
|
asm::Register::S0,
|
||||||
imm: asm::Immediate::Value(context.stack_offsets[ptr_rid]),
|
context.stack_offsets[ptr_rid],
|
||||||
});
|
&mut context.insts,
|
||||||
|
);
|
||||||
self.translate_store_result(&rid, value_dtype, rd, context);
|
self.translate_store_result(&rid, value_dtype, rd, context);
|
||||||
}
|
}
|
||||||
_ => todo!(),
|
_ => todo!(),
|
||||||
@@ -406,24 +582,41 @@ impl Asmgen {
|
|||||||
context,
|
context,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
match callee {
|
||||||
|
ir::Operand::Constant(callee) => {
|
||||||
context
|
context
|
||||||
.insts
|
.insts
|
||||||
.push(asm::Instruction::Pseudo(asm::Pseudo::Call {
|
.push(asm::Instruction::Pseudo(asm::Pseudo::Call {
|
||||||
offset: asm::Label(
|
offset: asm::Label(callee.get_global_variable_name().unwrap()),
|
||||||
callee
|
|
||||||
.get_constant()
|
|
||||||
.unwrap()
|
|
||||||
.get_global_variable_name()
|
|
||||||
.unwrap(),
|
|
||||||
),
|
|
||||||
}));
|
}));
|
||||||
|
}
|
||||||
|
ir::Operand::Register { rid, .. } => {
|
||||||
|
self.translate_load_operand(callee, asm::Register::T0, context);
|
||||||
|
context
|
||||||
|
.insts
|
||||||
|
.push(asm::Instruction::Pseudo(asm::Pseudo::Jalr {
|
||||||
|
rs: asm::Register::T0,
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TODO
|
// TODO
|
||||||
|
if is_integer(return_type) {
|
||||||
self.translate_store_result(
|
self.translate_store_result(
|
||||||
&rid,
|
&rid,
|
||||||
return_type.clone(),
|
return_type.clone(),
|
||||||
asm::Register::A0,
|
asm::Register::A0,
|
||||||
context,
|
context,
|
||||||
);
|
);
|
||||||
|
} else if is_float(return_type) {
|
||||||
|
self.translate_store_result(
|
||||||
|
&rid,
|
||||||
|
return_type.clone(),
|
||||||
|
asm::Register::FA0,
|
||||||
|
context,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ir::Instruction::TypeCast {
|
ir::Instruction::TypeCast {
|
||||||
value,
|
value,
|
||||||
@@ -431,9 +624,54 @@ impl Asmgen {
|
|||||||
} => {
|
} => {
|
||||||
let rs1 = get_lhs_register(&value.dtype());
|
let rs1 = get_lhs_register(&value.dtype());
|
||||||
self.translate_load_operand(value, rs1, context);
|
self.translate_load_operand(value, rs1, context);
|
||||||
// TODO: Int <-> Float ...
|
|
||||||
self.translate_store_result(&rid, target_dtype.clone(), rs1, context);
|
match (value.dtype(), target_dtype) {
|
||||||
|
(ir::Dtype::Int { .. }, ir::Dtype::Int { .. }) => {
|
||||||
|
self.translate_store_result(&rid, target_dtype.clone(), rs1, context)
|
||||||
}
|
}
|
||||||
|
(ir::Dtype::Float { .. }, ir::Dtype::Float { .. }) => {
|
||||||
|
let rd = get_rhs_register(target_dtype);
|
||||||
|
context.insts.push(asm::Instruction::RType {
|
||||||
|
instr: asm::RType::FcvtFloatToFloat {
|
||||||
|
from: asm::DataSize::try_from(value.dtype()).unwrap(),
|
||||||
|
to: asm::DataSize::try_from(target_dtype.clone()).unwrap(),
|
||||||
|
},
|
||||||
|
rd,
|
||||||
|
rs1,
|
||||||
|
rs2: None,
|
||||||
|
});
|
||||||
|
self.translate_store_result(&rid, target_dtype.clone(), rd, context);
|
||||||
|
}
|
||||||
|
(ir::Dtype::Int { .. }, ir::Dtype::Float { .. }) => {
|
||||||
|
let rd = get_rhs_register(target_dtype);
|
||||||
|
context.insts.push(asm::Instruction::RType {
|
||||||
|
instr: asm::RType::fcvt_int_to_float(
|
||||||
|
value.dtype(),
|
||||||
|
target_dtype.clone(),
|
||||||
|
),
|
||||||
|
rd,
|
||||||
|
rs1,
|
||||||
|
rs2: None,
|
||||||
|
});
|
||||||
|
self.translate_store_result(&rid, target_dtype.clone(), rd, context);
|
||||||
|
}
|
||||||
|
(ir::Dtype::Float { .. }, ir::Dtype::Int { .. }) => {
|
||||||
|
let rd = get_rhs_register(target_dtype);
|
||||||
|
context.insts.push(asm::Instruction::RType {
|
||||||
|
instr: asm::RType::fcvt_float_to_int(
|
||||||
|
value.dtype(),
|
||||||
|
target_dtype.clone(),
|
||||||
|
),
|
||||||
|
rd,
|
||||||
|
rs1,
|
||||||
|
rs2: None,
|
||||||
|
});
|
||||||
|
self.translate_store_result(&rid, target_dtype.clone(), rd, context);
|
||||||
|
}
|
||||||
|
_ => todo!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ir::Instruction::Nop => (),
|
||||||
_ => todo!(),
|
_ => todo!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -533,7 +771,11 @@ impl Asmgen {
|
|||||||
}
|
}
|
||||||
ir::BlockExit::Return { value } => {
|
ir::BlockExit::Return { value } => {
|
||||||
// TODO
|
// TODO
|
||||||
|
if is_integer(&value.dtype()) {
|
||||||
self.translate_load_operand(value, asm::Register::A0, context);
|
self.translate_load_operand(value, asm::Register::A0, context);
|
||||||
|
} else if is_float(&value.dtype()) {
|
||||||
|
self.translate_load_operand(value, asm::Register::FA0, context);
|
||||||
|
}
|
||||||
self.translate_epilogue(context);
|
self.translate_epilogue(context);
|
||||||
}
|
}
|
||||||
_ => todo!(),
|
_ => todo!(),
|
||||||
@@ -548,9 +790,9 @@ impl Asmgen {
|
|||||||
) {
|
) {
|
||||||
match operand {
|
match operand {
|
||||||
ir::Operand::Constant(c) => match c {
|
ir::Operand::Constant(c) => match c {
|
||||||
ir::Constant::Undef { dtype } => context
|
ir::Constant::Undef { dtype } => {
|
||||||
.insts
|
// Do nothing
|
||||||
.push(asm::Instruction::Pseudo(asm::Pseudo::Li { rd, imm: 0 })),
|
}
|
||||||
ir::Constant::Int {
|
ir::Constant::Int {
|
||||||
value,
|
value,
|
||||||
width,
|
width,
|
||||||
@@ -561,17 +803,68 @@ impl Asmgen {
|
|||||||
rd,
|
rd,
|
||||||
imm: *value as u64,
|
imm: *value as u64,
|
||||||
})),
|
})),
|
||||||
|
ir::Constant::Float { value, width } => {
|
||||||
|
if *width == 32 {
|
||||||
|
context
|
||||||
|
.insts
|
||||||
|
.push(asm::Instruction::Pseudo(asm::Pseudo::Li {
|
||||||
|
rd: asm::Register::T4,
|
||||||
|
imm: (**value as f32).to_bits() as u64,
|
||||||
|
}));
|
||||||
|
context.insts.push(asm::Instruction::RType {
|
||||||
|
instr: asm::RType::fmv_int_to_float(ir::Dtype::float(32)),
|
||||||
|
rd,
|
||||||
|
rs1: asm::Register::T4,
|
||||||
|
rs2: None,
|
||||||
|
});
|
||||||
|
} else if *width == 64 {
|
||||||
|
context
|
||||||
|
.insts
|
||||||
|
.push(asm::Instruction::Pseudo(asm::Pseudo::Li {
|
||||||
|
rd: asm::Register::T4,
|
||||||
|
imm: value.to_bits(),
|
||||||
|
}));
|
||||||
|
context.insts.push(asm::Instruction::RType {
|
||||||
|
instr: asm::RType::fmv_int_to_float(ir::Dtype::float(64)),
|
||||||
|
rd,
|
||||||
|
rs1: asm::Register::T4,
|
||||||
|
rs2: None,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ir::Constant::GlobalVariable { name, dtype } => {
|
||||||
|
context
|
||||||
|
.insts
|
||||||
|
.push(asm::Instruction::Pseudo(asm::Pseudo::La {
|
||||||
|
rd,
|
||||||
|
symbol: asm::Label(name.clone()),
|
||||||
|
}));
|
||||||
|
}
|
||||||
_ => {
|
_ => {
|
||||||
println!("{c}");
|
println!("{c}");
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
ir::Operand::Register { rid, dtype } => context.insts.push(asm::Instruction::IType {
|
ir::Operand::Register { rid, dtype } => {
|
||||||
instr: asm::IType::load(dtype.clone()),
|
if let ir::RegisterId::Local { aid } = rid {
|
||||||
|
self.translate_addi(
|
||||||
rd,
|
rd,
|
||||||
rs1: asm::Register::S0,
|
asm::Register::S0,
|
||||||
imm: asm::Immediate::Value(context.stack_offsets[rid]),
|
context.stack_offsets[rid],
|
||||||
}),
|
&mut context.insts,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
self.translate_load(
|
||||||
|
asm::IType::load(dtype.clone()),
|
||||||
|
rd,
|
||||||
|
asm::Register::S0,
|
||||||
|
context.stack_offsets[rid],
|
||||||
|
&mut context.insts,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -582,17 +875,18 @@ impl Asmgen {
|
|||||||
rs: asm::Register,
|
rs: asm::Register,
|
||||||
context: &mut Context,
|
context: &mut Context,
|
||||||
) {
|
) {
|
||||||
context.insts.push(asm::Instruction::SType {
|
self.translate_store(
|
||||||
instr: asm::SType::store(dtype),
|
asm::SType::store(dtype),
|
||||||
rs1: asm::Register::S0,
|
asm::Register::S0,
|
||||||
rs2: rs,
|
rs,
|
||||||
imm: asm::Immediate::Value(context.stack_offsets[rid]),
|
context.stack_offsets[rid],
|
||||||
})
|
&mut context.insts,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn translate_phinode(
|
fn translate_phinode(
|
||||||
&mut self,
|
&mut self,
|
||||||
name: &String,
|
name: &str,
|
||||||
arg: &ir::JumpArg,
|
arg: &ir::JumpArg,
|
||||||
context: &Context,
|
context: &Context,
|
||||||
) -> Vec<asm::Instruction> {
|
) -> Vec<asm::Instruction> {
|
||||||
@@ -606,29 +900,31 @@ impl Asmgen {
|
|||||||
|
|
||||||
let mut phinode_insts = Vec::new();
|
let mut phinode_insts = Vec::new();
|
||||||
if phinode_stack_allocations > 0 {
|
if phinode_stack_allocations > 0 {
|
||||||
phinode_insts.push(asm::Instruction::IType {
|
self.translate_addi(
|
||||||
instr: asm::IType::ADDI,
|
asm::Register::Sp,
|
||||||
rd: asm::Register::Sp,
|
asm::Register::Sp,
|
||||||
rs1: asm::Register::Sp,
|
!phinode_stack_allocations + 1,
|
||||||
imm: asm::Immediate::Value(!phinode_stack_allocations + 1),
|
&mut phinode_insts,
|
||||||
});
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let bid = arg.bid;
|
let bid = arg.bid;
|
||||||
for (aid, arg) in arg.args.iter().enumerate() {
|
for (aid, arg) in arg.args.iter().enumerate() {
|
||||||
let rs1 = get_lhs_register(&arg.dtype());
|
let rs1 = get_lhs_register(&arg.dtype());
|
||||||
phinode_insts.push(asm::Instruction::IType {
|
self.translate_load(
|
||||||
instr: asm::IType::load(arg.dtype()),
|
asm::IType::load(arg.dtype()),
|
||||||
rd: rs1,
|
rs1,
|
||||||
rs1: asm::Register::S0,
|
asm::Register::S0,
|
||||||
imm: asm::Immediate::Value(context.stack_offsets[&ir::RegisterId::arg(bid, aid)]),
|
context.stack_offsets[&ir::RegisterId::arg(bid, aid)],
|
||||||
});
|
&mut phinode_insts,
|
||||||
phinode_insts.push(asm::Instruction::SType {
|
);
|
||||||
instr: asm::SType::store(arg.dtype()),
|
self.translate_store(
|
||||||
rs1: asm::Register::Sp,
|
asm::SType::store(arg.dtype()),
|
||||||
rs2: rs1,
|
asm::Register::Sp,
|
||||||
imm: asm::Immediate::Value(phinode_stack_offsets[&aid]),
|
rs1,
|
||||||
});
|
phinode_stack_offsets[&aid],
|
||||||
|
&mut phinode_insts,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (aid, arg) in arg.args.iter().enumerate() {
|
for (aid, arg) in arg.args.iter().enumerate() {
|
||||||
@@ -643,6 +939,7 @@ impl Asmgen {
|
|||||||
rd: rs1,
|
rd: rs1,
|
||||||
imm: *value as u64,
|
imm: *value as u64,
|
||||||
})),
|
})),
|
||||||
|
ir::Constant::Undef { .. } => (), // DO nothing
|
||||||
_ => todo!(),
|
_ => todo!(),
|
||||||
},
|
},
|
||||||
ir::Operand::Register { rid, .. } => {
|
ir::Operand::Register { rid, .. } => {
|
||||||
@@ -652,45 +949,49 @@ impl Asmgen {
|
|||||||
} = rid
|
} = rid
|
||||||
{
|
{
|
||||||
if *arg_bid == bid {
|
if *arg_bid == bid {
|
||||||
phinode_insts.push(asm::Instruction::IType {
|
self.translate_load(
|
||||||
instr: asm::IType::load(arg.dtype()),
|
asm::IType::load(arg.dtype()),
|
||||||
rd: rs1,
|
rs1,
|
||||||
rs1: asm::Register::Sp,
|
asm::Register::Sp,
|
||||||
imm: asm::Immediate::Value(phinode_stack_offsets[arg_aid]),
|
phinode_stack_offsets[arg_aid],
|
||||||
});
|
&mut phinode_insts,
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
phinode_insts.push(asm::Instruction::IType {
|
self.translate_load(
|
||||||
instr: asm::IType::load(arg.dtype()),
|
asm::IType::load(arg.dtype()),
|
||||||
rd: rs1,
|
rs1,
|
||||||
rs1: asm::Register::S0,
|
asm::Register::S0,
|
||||||
imm: asm::Immediate::Value(context.stack_offsets[rid]),
|
context.stack_offsets[rid],
|
||||||
});
|
&mut phinode_insts,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
phinode_insts.push(asm::Instruction::IType {
|
self.translate_load(
|
||||||
instr: asm::IType::load(arg.dtype()),
|
asm::IType::load(arg.dtype()),
|
||||||
rd: rs1,
|
rs1,
|
||||||
rs1: asm::Register::S0,
|
asm::Register::S0,
|
||||||
imm: asm::Immediate::Value(context.stack_offsets[rid]),
|
context.stack_offsets[rid],
|
||||||
});
|
&mut phinode_insts,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
phinode_insts.push(asm::Instruction::SType {
|
self.translate_store(
|
||||||
instr: asm::SType::store(arg.dtype()),
|
asm::SType::store(arg.dtype()),
|
||||||
rs1: asm::Register::S0,
|
asm::Register::S0,
|
||||||
rs2: rs1,
|
rs1,
|
||||||
imm: asm::Immediate::Value(context.stack_offsets[&ir::RegisterId::arg(bid, aid)]),
|
context.stack_offsets[&ir::RegisterId::arg(bid, aid)],
|
||||||
});
|
&mut phinode_insts,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if phinode_stack_allocations > 0 {
|
if phinode_stack_allocations > 0 {
|
||||||
phinode_insts.push(asm::Instruction::IType {
|
self.translate_addi(
|
||||||
instr: asm::IType::ADDI,
|
asm::Register::Sp,
|
||||||
rd: asm::Register::Sp,
|
asm::Register::Sp,
|
||||||
rs1: asm::Register::Sp,
|
phinode_stack_allocations,
|
||||||
imm: asm::Immediate::Value(phinode_stack_allocations),
|
&mut phinode_insts,
|
||||||
});
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
phinode_insts.push(asm::Instruction::Pseudo(asm::Pseudo::J {
|
phinode_insts.push(asm::Instruction::Pseudo(asm::Pseudo::J {
|
||||||
@@ -699,6 +1000,107 @@ impl Asmgen {
|
|||||||
|
|
||||||
phinode_insts
|
phinode_insts
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn translate_addi(
|
||||||
|
&mut self,
|
||||||
|
rd: asm::Register,
|
||||||
|
rs1: asm::Register,
|
||||||
|
imm: u64,
|
||||||
|
insts: &mut Vec<asm::Instruction>,
|
||||||
|
) {
|
||||||
|
let imm_signed = imm as i64;
|
||||||
|
if (-2048..=2047).contains(&imm_signed) {
|
||||||
|
insts.push(asm::Instruction::IType {
|
||||||
|
instr: asm::IType::ADDI,
|
||||||
|
rd,
|
||||||
|
rs1,
|
||||||
|
imm: asm::Immediate::Value(imm),
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
insts.push(asm::Instruction::Pseudo(asm::Pseudo::Li {
|
||||||
|
rd: asm::Register::T3,
|
||||||
|
imm,
|
||||||
|
}));
|
||||||
|
insts.push(asm::Instruction::RType {
|
||||||
|
instr: asm::RType::add(ir::Dtype::int(64)),
|
||||||
|
rd,
|
||||||
|
rs1,
|
||||||
|
rs2: Some(asm::Register::T3),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn translate_store(
|
||||||
|
&mut self,
|
||||||
|
instr: asm::SType,
|
||||||
|
rs1: asm::Register,
|
||||||
|
rs2: asm::Register,
|
||||||
|
imm: u64,
|
||||||
|
insts: &mut Vec<asm::Instruction>,
|
||||||
|
) {
|
||||||
|
let imm_signed = imm as i64;
|
||||||
|
if (-2048..=2047).contains(&imm_signed) {
|
||||||
|
insts.push(asm::Instruction::SType {
|
||||||
|
instr,
|
||||||
|
rs1,
|
||||||
|
rs2,
|
||||||
|
imm: asm::Immediate::Value(imm),
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
insts.push(asm::Instruction::Pseudo(asm::Pseudo::Li {
|
||||||
|
rd: asm::Register::T3,
|
||||||
|
imm,
|
||||||
|
}));
|
||||||
|
insts.push(asm::Instruction::RType {
|
||||||
|
instr: asm::RType::add(ir::Dtype::int(64)),
|
||||||
|
rd: asm::Register::T3,
|
||||||
|
rs1,
|
||||||
|
rs2: Some(asm::Register::T3),
|
||||||
|
});
|
||||||
|
insts.push(asm::Instruction::SType {
|
||||||
|
instr,
|
||||||
|
rs1: asm::Register::T3,
|
||||||
|
rs2,
|
||||||
|
imm: asm::Immediate::Value(0),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn translate_load(
|
||||||
|
&mut self,
|
||||||
|
instr: asm::IType,
|
||||||
|
rd: asm::Register,
|
||||||
|
rs1: asm::Register,
|
||||||
|
imm: u64,
|
||||||
|
insts: &mut Vec<asm::Instruction>,
|
||||||
|
) {
|
||||||
|
let imm_signed = imm as i64;
|
||||||
|
if (-2048..=2047).contains(&imm_signed) {
|
||||||
|
insts.push(asm::Instruction::IType {
|
||||||
|
instr,
|
||||||
|
rd,
|
||||||
|
rs1,
|
||||||
|
imm: asm::Immediate::Value(imm),
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
insts.push(asm::Instruction::Pseudo(asm::Pseudo::Li {
|
||||||
|
rd: asm::Register::T3,
|
||||||
|
imm,
|
||||||
|
}));
|
||||||
|
insts.push(asm::Instruction::RType {
|
||||||
|
instr: asm::RType::add(ir::Dtype::int(64)),
|
||||||
|
rd: asm::Register::T3,
|
||||||
|
rs1,
|
||||||
|
rs2: Some(asm::Register::T3),
|
||||||
|
});
|
||||||
|
insts.push(asm::Instruction::IType {
|
||||||
|
instr,
|
||||||
|
rd,
|
||||||
|
rs1: asm::Register::T3,
|
||||||
|
imm: asm::Immediate::Value(0),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_lhs_register(dtype: &ir::Dtype) -> asm::Register {
|
fn get_lhs_register(dtype: &ir::Dtype) -> asm::Register {
|
||||||
@@ -764,8 +1166,43 @@ fn get_constant_from_initializer(initializer: &ast::Initializer) -> ir::Constant
|
|||||||
match initializer {
|
match initializer {
|
||||||
ast::Initializer::Expression(expression) => match &expression.node {
|
ast::Initializer::Expression(expression) => match &expression.node {
|
||||||
ast::Expression::Constant(constant) => ir::Constant::try_from(&constant.node).unwrap(),
|
ast::Expression::Constant(constant) => ir::Constant::try_from(&constant.node).unwrap(),
|
||||||
|
ast::Expression::UnaryOperator(op) => {
|
||||||
|
let operand = match &op.node.operand.node {
|
||||||
|
ast::Expression::Constant(constant) => {
|
||||||
|
ir::Constant::try_from(&constant.node).unwrap()
|
||||||
|
}
|
||||||
|
_ => panic!(),
|
||||||
|
};
|
||||||
|
match op.node.operator.node {
|
||||||
|
ast::UnaryOperator::Minus => match operand {
|
||||||
|
ir::Constant::Int {
|
||||||
|
value,
|
||||||
|
width,
|
||||||
|
is_signed,
|
||||||
|
} => ir::Constant::Int {
|
||||||
|
value: !value + 1,
|
||||||
|
width,
|
||||||
|
is_signed,
|
||||||
|
},
|
||||||
|
ir::Constant::Float { value, width } => ir::Constant::Float {
|
||||||
|
value: -value,
|
||||||
|
width,
|
||||||
|
},
|
||||||
|
_ => panic!(),
|
||||||
|
},
|
||||||
|
_ => panic!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
_ => panic!(),
|
_ => panic!(),
|
||||||
},
|
},
|
||||||
_ => panic!(),
|
_ => panic!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_integer(dtype: &ir::Dtype) -> bool {
|
||||||
|
matches!(dtype, ir::Dtype::Int { .. } | ir::Dtype::Pointer { .. })
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_float(dtype: &ir::Dtype) -> bool {
|
||||||
|
matches!(dtype, ir::Dtype::Float { .. })
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user