This commit is contained in:
static
2025-06-16 08:24:05 +00:00
parent 96e9ecbd8d
commit c3d6e303a5
2 changed files with 522 additions and 147 deletions

View File

@@ -61,6 +61,25 @@ impl Asmgen {
)); ));
} }
} }
self.variables.push(asm::Section::new(
vec![
asm::Directive::Globl(asm::Label(name.clone())),
asm::Directive::Section(asm::SectionType::Data),
asm::Directive::Type(asm::Label(name.clone()), asm::SymbolType::Object),
],
asm::Variable::new(asm::Label(name.clone()), directives),
));
} else {
let mut directives = Vec::new();
match dtype {
ir::Dtype::Array { inner, size } => directives.push(asm::Directive::Zero(
size * (get_dtype_size(inner, structs) as usize),
)),
_ => directives
.push(asm::Directive::Zero(get_dtype_size(dtype, structs) as usize)),
}
self.variables.push(asm::Section::new( self.variables.push(asm::Section::new(
vec![ vec![
asm::Directive::Globl(asm::Label(name.clone())), asm::Directive::Globl(asm::Label(name.clone())),
@@ -188,15 +207,19 @@ impl Asmgen {
let mut num_int_args = 0; let mut num_int_args = 0;
let mut num_float_args = 0; let mut num_float_args = 0;
if is_struct(&signature.ret, structs).is_some() { if let Some(size) = is_struct(&signature.ret, structs) {
num_int_args += 1; if size > 16 {
num_int_args += 1;
}
} }
let mut large_struct = HashMap::new();
for (i, dtype) in signature.params.iter().enumerate() { for (i, dtype) in signature.params.iter().enumerate() {
let stack_offset = stack_offsets[&ir::RegisterId::arg(definition.bid_init, i)]; let stack_offset = stack_offsets[&ir::RegisterId::arg(definition.bid_init, i)];
if is_integer(dtype) { if is_integer(dtype) {
self.translate_store( self.translate_store(
asm::SType::SD, asm::SType::store(dtype.clone()),
asm::Register::S0, asm::Register::S0,
asm::Register::arg(asm::RegisterType::Integer, num_int_args), asm::Register::arg(asm::RegisterType::Integer, num_int_args),
stack_offset, stack_offset,
@@ -212,6 +235,113 @@ impl Asmgen {
&mut insts, &mut insts,
); );
num_float_args += 1; num_float_args += 1;
} else if let Some(size) = is_struct(dtype, structs) {
if size > 16 {
let _ = large_struct.insert(i, num_int_args);
num_int_args += 1;
} else {
let struct_name = dtype.get_struct_name().unwrap().as_ref().unwrap().clone();
let struct_dtype = structs[&struct_name].clone().unwrap();
let fields = struct_dtype.get_struct_fields().unwrap().as_ref().unwrap();
let mut is_packing = false;
let mut packing_start_offset = 0;
let mut packing_size = 0;
for field_dtype in fields {
let (offset, _) = struct_dtype
.get_offset_struct_field(field_dtype.name().unwrap(), structs)
.unwrap();
let field_size = get_dtype_size(&field_dtype, structs);
if is_integer(&field_dtype) {
if !is_packing {
is_packing = true;
packing_start_offset = offset;
packing_size = field_size;
} else {
if offset == packing_start_offset + (packing_size as usize)
&& packing_size + field_size <= 8
{
packing_size += field_size;
} else {
self.translate_addi(
asm::Register::T5,
asm::Register::S0,
stack_offset,
&mut insts,
);
insts.push(asm::Instruction::SType {
instr: asm::SType::SD,
rs1: asm::Register::T5,
rs2: asm::Register::arg(
asm::RegisterType::Integer,
num_int_args,
),
imm: asm::Immediate::Value(packing_start_offset as u64),
});
num_int_args += 1;
packing_start_offset = offset;
packing_size = field_size;
}
}
} else if is_float(&field_dtype) {
if is_packing {
self.translate_addi(
asm::Register::T5,
asm::Register::S0,
stack_offset,
&mut insts,
);
insts.push(asm::Instruction::SType {
instr: asm::SType::SD,
rs1: asm::Register::T5,
rs2: asm::Register::arg(
asm::RegisterType::Integer,
num_int_args,
),
imm: asm::Immediate::Value(packing_start_offset as u64),
});
num_int_args += 1;
is_packing = false;
}
self.translate_addi(
asm::Register::T5,
asm::Register::S0,
stack_offset,
&mut insts,
);
insts.push(asm::Instruction::SType {
instr: asm::SType::store(field_dtype.deref().clone()),
rs1: asm::Register::T5,
rs2: asm::Register::arg(
asm::RegisterType::FloatingPoint,
num_float_args,
),
imm: asm::Immediate::Value(offset as u64),
});
num_float_args += 1;
} else {
todo!()
}
}
if is_packing {
self.translate_addi(
asm::Register::T5,
asm::Register::S0,
stack_offset,
&mut insts,
);
insts.push(asm::Instruction::SType {
instr: asm::SType::SD,
rs1: asm::Register::T5,
rs2: asm::Register::arg(asm::RegisterType::Integer, num_int_args),
imm: asm::Immediate::Value(packing_start_offset as u64),
});
num_int_args += 1;
}
}
} }
} }
@@ -237,46 +367,49 @@ impl Asmgen {
for (i, dtype) in signature.params.iter().enumerate() { for (i, dtype) in signature.params.iter().enumerate() {
let stack_offset = stack_offsets[&ir::RegisterId::arg(definition.bid_init, i)]; let stack_offset = stack_offsets[&ir::RegisterId::arg(definition.bid_init, i)];
if let Some(size) = is_struct(dtype, structs) { if let Some(size) = is_struct(dtype, structs) {
self.translate_addi( if size > 16 {
asm::Register::A0, let reg_index = large_struct[&i];
asm::Register::S0,
stack_offset,
&mut insts,
);
match i { self.translate_addi(
0 => insts.push(asm::Instruction::IType { asm::Register::A0,
instr: asm::IType::LD, asm::Register::S0,
rd: asm::Register::A1, stack_offset,
rs1: asm::Register::S0, &mut insts,
imm: asm::Immediate::Value(!24 + 1), );
}),
1 => insts.push(asm::Instruction::IType { match reg_index {
instr: asm::IType::LD, 0 => insts.push(asm::Instruction::IType {
rd: asm::Register::A1, instr: asm::IType::LD,
rs1: asm::Register::Sp, rd: asm::Register::A1,
imm: asm::Immediate::Value(0), rs1: asm::Register::S0,
}), imm: asm::Immediate::Value(!24 + 1),
2 => insts.push(asm::Instruction::IType { }),
instr: asm::IType::LD, 1 => insts.push(asm::Instruction::IType {
rd: asm::Register::A1, instr: asm::IType::LD,
rs1: asm::Register::Sp, rd: asm::Register::A1,
imm: asm::Immediate::Value(8), rs1: asm::Register::Sp,
}), imm: asm::Immediate::Value(0),
_ => insts.push(asm::Instruction::Pseudo(asm::Pseudo::Mv { }),
rd: asm::Register::A1, 2 => insts.push(asm::Instruction::IType {
rs: asm::Register::arg(asm::RegisterType::Integer, i), instr: asm::IType::LD,
})), rd: asm::Register::A1,
rs1: asm::Register::Sp,
imm: asm::Immediate::Value(8),
}),
_ => insts.push(asm::Instruction::Pseudo(asm::Pseudo::Mv {
rd: asm::Register::A1,
rs: asm::Register::arg(asm::RegisterType::Integer, reg_index),
})),
}
insts.push(asm::Instruction::Pseudo(asm::Pseudo::Li {
rd: asm::Register::A2,
imm: size,
}));
insts.push(asm::Instruction::Pseudo(asm::Pseudo::Call {
offset: asm::Label(String::from("memcpy")),
}));
} }
insts.push(asm::Instruction::Pseudo(asm::Pseudo::Li {
rd: asm::Register::A2,
imm: size,
}));
insts.push(asm::Instruction::Pseudo(asm::Pseudo::Call {
offset: asm::Label(String::from("memcpy")),
}));
num_int_args += 1;
} }
} }
@@ -441,6 +574,9 @@ impl Asmgen {
rs1, rs1,
rs2: Some(rs2), rs2: Some(rs2),
}); });
context
.insts
.push(asm::Instruction::Pseudo(asm::Pseudo::Snez { rd, rs: rd }));
} }
ast::BinaryOperator::Less => { ast::BinaryOperator::Less => {
if is_integer(&operand_dtype) { if is_integer(&operand_dtype) {
@@ -716,7 +852,7 @@ impl Asmgen {
let value_dtype = ptr_dtype.get_pointer_inner().unwrap().clone(); let value_dtype = ptr_dtype.get_pointer_inner().unwrap().clone();
if let Some(size) = is_struct(&value_dtype, structs) { if let Some(size) = is_struct(&value_dtype, structs) {
match ptr_rid { match ptr_rid {
ir::RegisterId::Temp { .. } => { ir::RegisterId::Temp { .. } | ir::RegisterId::Arg { .. } => {
let rs1 = get_rhs_register(ptr_dtype); let rs1 = get_rhs_register(ptr_dtype);
self.translate_load_operand(ptr, rs1, context); self.translate_load_operand(ptr, rs1, context);
self.translate_addi( self.translate_addi(
@@ -773,7 +909,7 @@ impl Asmgen {
} else { } else {
let rd = get_lhs_register(&value_dtype); let rd = get_lhs_register(&value_dtype);
match ptr_rid { match ptr_rid {
ir::RegisterId::Temp { .. } => { ir::RegisterId::Temp { .. } | ir::RegisterId::Arg { .. } => {
let rs1 = get_rhs_register(ptr_dtype); let rs1 = get_rhs_register(ptr_dtype);
self.translate_load_operand(ptr, rs1, context); self.translate_load_operand(ptr, rs1, context);
context.insts.push(asm::Instruction::IType { context.insts.push(asm::Instruction::IType {
@@ -813,14 +949,18 @@ impl Asmgen {
// 구조체 반환을 위한 공간 예약 // 구조체 반환을 위한 공간 예약
if let Some(size) = is_struct(return_type, structs) { if let Some(size) = is_struct(return_type, structs) {
num_int_args += 1; if size > 16 {
struct_stack_allocations += ceil_to_multiple_of_16(size); num_int_args += 1;
struct_stack_allocations += ceil_to_multiple_of_16(size);
}
} }
for (i, arg) in args.iter().enumerate() { for (i, arg) in args.iter().enumerate() {
if let Some(size) = is_struct(&arg.dtype(), structs) { if let Some(size) = is_struct(&arg.dtype(), structs) {
let _ = struct_stack_offsets.insert(i, struct_stack_allocations); if size > 16 {
struct_stack_allocations += ceil_to_multiple_of_16(size); let _ = struct_stack_offsets.insert(i, struct_stack_allocations);
struct_stack_allocations += ceil_to_multiple_of_16(size);
}
} }
} }
@@ -836,37 +976,39 @@ impl Asmgen {
// 구조체 인수 복사 // 구조체 인수 복사
for (i, arg) in args.iter().enumerate() { for (i, arg) in args.iter().enumerate() {
if let Some(size) = is_struct(&arg.dtype(), structs) { if let Some(size) = is_struct(&arg.dtype(), structs) {
self.translate_addi( if size > 16 {
asm::Register::A0, self.translate_addi(
asm::Register::Sp, asm::Register::A0,
struct_stack_offsets[&i], asm::Register::Sp,
&mut context.insts, struct_stack_offsets[&i],
); &mut context.insts,
match arg { );
ir::Operand::Register { rid, .. } => match rid { match arg {
ir::RegisterId::Temp { bid, iid } => { ir::Operand::Register { rid, .. } => match rid {
self.translate_addi( ir::RegisterId::Temp { bid, iid } => {
asm::Register::A1, self.translate_addi(
asm::Register::S0, asm::Register::A1,
context.stack_offsets[rid], asm::Register::S0,
&mut context.insts, context.stack_offsets[rid],
); &mut context.insts,
} );
}
_ => todo!(),
},
_ => todo!(), _ => todo!(),
}, }
_ => todo!(), context
.insts
.push(asm::Instruction::Pseudo(asm::Pseudo::Li {
rd: asm::Register::A2,
imm: size,
}));
context
.insts
.push(asm::Instruction::Pseudo(asm::Pseudo::Call {
offset: asm::Label(String::from("memcpy")),
}));
} }
context
.insts
.push(asm::Instruction::Pseudo(asm::Pseudo::Li {
rd: asm::Register::A2,
imm: size,
}));
context
.insts
.push(asm::Instruction::Pseudo(asm::Pseudo::Call {
offset: asm::Label(String::from("memcpy")),
}));
} }
} }
@@ -890,25 +1032,136 @@ impl Asmgen {
); );
num_float_args += 1; num_float_args += 1;
} else if let Some(size) = is_struct(&dtype, structs) { } else if let Some(size) = is_struct(&dtype, structs) {
self.translate_addi( if size > 16 {
asm::Register::arg(asm::RegisterType::Integer, num_int_args), self.translate_addi(
asm::Register::Sp, asm::Register::arg(asm::RegisterType::Integer, num_int_args),
struct_stack_offsets[&i], asm::Register::Sp,
&mut context.insts, struct_stack_offsets[&i],
); &mut context.insts,
num_int_args += 1; );
num_int_args += 1;
} else {
match arg {
ir::Operand::Register { rid, .. } => match rid {
ir::RegisterId::Temp { bid, iid } => {
self.translate_addi(
asm::Register::T5,
asm::Register::S0,
context.stack_offsets[rid],
&mut context.insts,
);
}
_ => todo!(),
},
_ => todo!(),
}
let struct_name =
dtype.get_struct_name().unwrap().as_ref().unwrap().clone();
let struct_dtype = structs[&struct_name].clone().unwrap();
let fields =
struct_dtype.get_struct_fields().unwrap().as_ref().unwrap();
let mut is_packing = false;
let mut packing_start_offset = 0;
let mut packing_size = 0;
for field_dtype in fields {
let (offset, _) = struct_dtype
.get_offset_struct_field(
field_dtype.name().unwrap(),
structs,
)
.unwrap();
let field_size = get_dtype_size(&field_dtype, structs);
if is_integer(&field_dtype) {
if !is_packing {
is_packing = true;
packing_start_offset = offset;
packing_size = field_size;
} else {
// TODO: 조건 수정 필요
if offset
== packing_start_offset + (packing_size as usize)
&& packing_size + field_size <= 8
{
packing_size += field_size;
} else {
context.insts.push(asm::Instruction::IType {
instr: asm::IType::LD,
rd: asm::Register::arg(
asm::RegisterType::Integer,
num_int_args,
),
rs1: asm::Register::T5,
imm: asm::Immediate::Value(
packing_start_offset as u64,
),
});
num_int_args += 1;
packing_start_offset = offset;
packing_size = field_size;
}
}
} else if is_float(&field_dtype) {
if is_packing {
context.insts.push(asm::Instruction::IType {
instr: asm::IType::LD,
rd: asm::Register::arg(
asm::RegisterType::Integer,
num_int_args,
),
rs1: asm::Register::T5,
imm: asm::Immediate::Value(
packing_start_offset as u64,
),
});
num_int_args += 1;
is_packing = false;
}
context.insts.push(asm::Instruction::IType {
instr: asm::IType::load(field_dtype.deref().clone()),
rd: asm::Register::arg(
asm::RegisterType::FloatingPoint,
num_float_args,
),
rs1: asm::Register::T5,
imm: asm::Immediate::Value(packing_start_offset as u64),
});
num_float_args += 1;
} else {
todo!()
}
}
if is_packing {
context.insts.push(asm::Instruction::IType {
instr: asm::IType::LD,
rd: asm::Register::arg(
asm::RegisterType::Integer,
num_int_args,
),
rs1: asm::Register::T5,
imm: asm::Immediate::Value(packing_start_offset as u64),
});
num_int_args += 1;
}
}
} else { } else {
todo!(); todo!();
} }
} }
if is_struct(return_type, structs).is_some() { if let Some(size) = is_struct(return_type, structs) {
context if size > 16 {
.insts context
.push(asm::Instruction::Pseudo(asm::Pseudo::Mv { .insts
rd: asm::Register::A0, .push(asm::Instruction::Pseudo(asm::Pseudo::Mv {
rs: asm::Register::Sp, rd: asm::Register::A0,
})); // For returned structure rs: asm::Register::Sp,
})); // For returned structure
}
} }
match callee { match callee {
@@ -945,29 +1198,86 @@ impl Asmgen {
context, context,
); );
} else if let Some(size) = is_struct(return_type, structs) { } else if let Some(size) = is_struct(return_type, structs) {
self.translate_addi( if size > 16 {
asm::Register::A0, self.translate_addi(
asm::Register::S0, asm::Register::A0,
context.stack_offsets[&rid], asm::Register::S0,
&mut context.insts, context.stack_offsets[&rid],
); &mut context.insts,
self.translate_addi( );
asm::Register::A1, self.translate_addi(
asm::Register::Sp, asm::Register::A1,
0, asm::Register::Sp,
&mut context.insts, 0,
); &mut context.insts,
context );
.insts context
.push(asm::Instruction::Pseudo(asm::Pseudo::Li { .insts
rd: asm::Register::A2, .push(asm::Instruction::Pseudo(asm::Pseudo::Li {
imm: size, rd: asm::Register::A2,
})); imm: size,
context }));
.insts context
.push(asm::Instruction::Pseudo(asm::Pseudo::Call { .insts
offset: asm::Label(String::from("memcpy")), .push(asm::Instruction::Pseudo(asm::Pseudo::Call {
})); offset: asm::Label(String::from("memcpy")),
}));
} else {
let struct_name = return_type
.get_struct_name()
.unwrap()
.as_ref()
.unwrap()
.clone();
let struct_dtype = structs[&struct_name].clone().unwrap();
let fields =
struct_dtype.get_struct_fields().unwrap().as_ref().unwrap();
let mut num_int_fields = 0;
let mut num_float_fields = 0;
for field_dtype in fields {
let (offset, _) = struct_dtype
.get_offset_struct_field(field_dtype.name().unwrap(), structs)
.unwrap();
if is_integer(&field_dtype) {
self.translate_addi(
asm::Register::T5,
asm::Register::S0,
context.stack_offsets[&rid],
&mut context.insts,
);
context.insts.push(asm::Instruction::SType {
instr: asm::SType::store(field_dtype.deref().clone()),
rs1: asm::Register::T5,
rs2: asm::Register::arg(
asm::RegisterType::Integer,
num_int_fields,
),
imm: asm::Immediate::Value(0),
});
num_int_fields += 1;
} else if is_float(&field_dtype) {
self.translate_addi(
asm::Register::T5,
asm::Register::S0,
context.stack_offsets[&rid],
&mut context.insts,
);
context.insts.push(asm::Instruction::SType {
instr: asm::SType::store(field_dtype.deref().clone()),
rs1: asm::Register::T5,
rs2: asm::Register::arg(
asm::RegisterType::FloatingPoint,
num_float_fields,
),
imm: asm::Immediate::Value(0),
});
num_float_fields += 1;
} else {
todo!()
}
}
}
} }
if struct_stack_allocations > 0 { if struct_stack_allocations > 0 {
@@ -987,7 +1297,8 @@ impl Asmgen {
self.translate_load_operand(value, rs1, context); self.translate_load_operand(value, rs1, context);
match (value.dtype(), target_dtype) { match (value.dtype(), target_dtype) {
(ir::Dtype::Int { .. }, ir::Dtype::Int { .. }) => { (ir::Dtype::Int { .. }, ir::Dtype::Int { .. })
| (ir::Dtype::Int { .. }, ir::Dtype::Pointer { .. }) => {
self.translate_store_result(&rid, target_dtype.clone(), rs1, context) self.translate_store_result(&rid, target_dtype.clone(), rs1, context)
} }
(ir::Dtype::Float { .. }, ir::Dtype::Float { .. }) => { (ir::Dtype::Float { .. }, ir::Dtype::Float { .. }) => {
@@ -1234,41 +1545,100 @@ impl Asmgen {
} else if is_float(&dtype) { } else if is_float(&dtype) {
self.translate_load_operand(value, asm::Register::FA0, context); self.translate_load_operand(value, asm::Register::FA0, context);
} else if let Some(size) = is_struct(&dtype, structs) { } else if let Some(size) = is_struct(&dtype, structs) {
context.insts.push(asm::Instruction::IType { if size > 16 {
instr: asm::IType::load(ir::Dtype::pointer(ir::Dtype::unit())), // TODO: ok? context.insts.push(asm::Instruction::IType {
rd: asm::Register::A0, instr: asm::IType::load(ir::Dtype::pointer(ir::Dtype::unit())), // TODO: ok?
rs1: asm::Register::S0, rd: asm::Register::A0,
imm: asm::Immediate::Value(!24 + 1), rs1: asm::Register::S0,
}); imm: asm::Immediate::Value(!24 + 1),
match value { });
ir::Operand::Constant(constant) => match constant { match value {
ir::Constant::Undef { .. } => (), // DO nothing ir::Operand::Constant(constant) => match constant {
ir::Constant::Undef { .. } => (), // DO nothing
_ => todo!(),
},
ir::Operand::Register { rid, .. } => match rid {
ir::RegisterId::Temp { bid, iid } => {
self.translate_addi(
asm::Register::A1,
asm::Register::S0,
context.stack_offsets[rid],
&mut context.insts,
);
}
_ => todo!(),
},
_ => todo!(), _ => todo!(),
}, }
ir::Operand::Register { rid, .. } => match rid { context
ir::RegisterId::Temp { bid, iid } => { .insts
self.translate_addi( .push(asm::Instruction::Pseudo(asm::Pseudo::Li {
asm::Register::A1, rd: asm::Register::A2,
asm::Register::S0, imm: size,
context.stack_offsets[rid], }));
&mut context.insts, context
); .insts
.push(asm::Instruction::Pseudo(asm::Pseudo::Call {
offset: asm::Label(String::from("memcpy")),
}));
} else {
match value {
ir::Operand::Constant(constant) => match constant {
ir::Constant::Undef { .. } => (), // DO nothing
_ => todo!(),
},
ir::Operand::Register { rid, .. } => match rid {
ir::RegisterId::Temp { bid, iid } => {
self.translate_addi(
asm::Register::T5,
asm::Register::S0,
context.stack_offsets[rid],
&mut context.insts,
);
}
_ => todo!(),
},
_ => todo!(),
}
let struct_name =
dtype.get_struct_name().unwrap().as_ref().unwrap().clone();
let struct_dtype = structs[&struct_name].clone().unwrap();
let fields = struct_dtype.get_struct_fields().unwrap().as_ref().unwrap();
let mut num_int_fields = 0;
let mut num_float_fields = 0;
for field_dtype in fields {
let (offset, _) = struct_dtype
.get_offset_struct_field(field_dtype.name().unwrap(), structs)
.unwrap();
if is_integer(&field_dtype) {
context.insts.push(asm::Instruction::IType {
instr: asm::IType::load(field_dtype.deref().clone()),
rd: asm::Register::arg(
asm::RegisterType::Integer,
num_int_fields,
),
rs1: asm::Register::T5,
imm: asm::Immediate::Value(offset as u64),
});
num_int_fields += 1;
} else if is_float(&field_dtype) {
context.insts.push(asm::Instruction::IType {
instr: asm::IType::load(field_dtype.deref().clone()),
rd: asm::Register::arg(
asm::RegisterType::FloatingPoint,
num_float_fields,
),
rs1: asm::Register::T5,
imm: asm::Immediate::Value(offset as u64),
});
num_float_fields += 1;
} else {
todo!()
} }
_ => todo!(), }
},
_ => todo!(),
} }
context
.insts
.push(asm::Instruction::Pseudo(asm::Pseudo::Li {
rd: asm::Register::A2,
imm: size,
}));
context
.insts
.push(asm::Instruction::Pseudo(asm::Pseudo::Call {
offset: asm::Label(String::from("memcpy")),
}));
} }
self.translate_epilogue(context); self.translate_epilogue(context);
} }

View File

@@ -2126,7 +2126,12 @@ impl IrgenFunc<'_> {
lhs_dtype lhs_dtype
} }
} }
_ => todo!("merge_dtype"), (&ir::Dtype::Pointer { .. }, &ir::Dtype::Int { .. }) => lhs_dtype,
(&ir::Dtype::Int { .. }, &ir::Dtype::Pointer { .. }) => rhs_dtype,
_ => {
println!("{:?} {:?}", lhs_dtype, rhs_dtype);
todo!("merge_dtype")
}
} }
} }