@@ -114,10 +114,23 @@ lir::BasicBlock *LIRLowering::lower_block_from_operand(hir::Value *value) {
114114 std::unreachable ();
115115}
116116
117- lir::Operand LIRLowering::ensure_reg (lir::Operand op) {
117+ lir::Register::RegClass LIRLowering::class_from_type (hir::type::Type *type) {
118+ if (type->is_array () || type->is_pointer () || type->is_function () ||
119+ type->is_struct ()) {
120+ return lir::Register::GPR64 ;
121+ } else if (type->is_float ()) {
122+ return lir::Register::FPR32 ;
123+ }
124+
125+ return lir::Register::GPR32 ;
126+ }
127+
128+ lir::Operand LIRLowering::ensure_reg (lir::Operand op,
129+ lir::Register::RegClass clazz) {
118130 if (op.is_reg ())
119131 return op;
120132 auto tmp = builder.emit_mov (op);
133+ tmp.set_class (clazz);
121134 return lir::Operand::from_reg (tmp);
122135}
123136
@@ -175,19 +188,16 @@ void LIRLowering::lower_instruction(hir::Instruction *hir_instr) {
175188 return ;
176189 }
177190 case hir::Opcode::SRem: {
191+ auto reg_class = class_from_type (hir_instr->type );
178192 auto lhs = lower_operand (hir_instr->operand (0 ));
179193 auto rhs = lower_operand (hir_instr->operand (1 ));
180- lhs = ensure_reg (lhs);
181- rhs = ensure_reg (rhs);
182- if (hir_instr->type ->is_pointer ()) {
183- lhs.get_reg_mut ().set_class (lir::Register::GPR64 );
184- rhs.get_reg_mut ().set_class (lir::Register::GPR64 );
185- }
186- auto quot = builder.emit_binop (lir::Opcode::SDiv, lhs, rhs);
187- auto prod =
188- builder.emit_binop (lir::Opcode::Mul, lir::Operand::from_reg (quot), rhs);
189- auto rem =
190- builder.emit_binop (lir::Opcode::Sub, lhs, lir::Operand::from_reg (prod));
194+ lhs = ensure_reg (lhs, reg_class);
195+ rhs = ensure_reg (rhs, reg_class);
196+ auto quot = builder.emit_binop (lir::Opcode::SDiv, lhs, rhs, reg_class);
197+ auto prod = builder.emit_binop (
198+ lir::Opcode::Mul, lir::Operand::from_reg (quot), rhs, reg_class);
199+ auto rem = builder.emit_binop (lir::Opcode::Sub, lhs,
200+ lir::Operand::from_reg (prod), reg_class);
191201 vreg_map[hir_instr] = rem;
192202 return ;
193203 }
@@ -233,26 +243,21 @@ void LIRLowering::lower_instruction(hir::Instruction *hir_instr) {
233243 std::vector<lir::Operand> args;
234244 auto *function_type =
235245 dynamic_cast <hir::type::FunctionType *>(hir_instr->type_arg );
236- std::cout << function_type->to_string () << std::endl;
237246 for (size_t i = 1 ; i < hir_instr->operand_count (); i++) {
238247 auto arg_op = lower_operand (hir_instr->operand (i));
239248 if (function_type->param_types .at (i - 1 )->is_pointer ())
240249 arg_op.get_reg_mut ().set_class (lir::Register::GPR64 );
241250 args.push_back (arg_op);
242251 }
243- lir::Register::RegClass clazz;
244- if (hir_instr->type ->is_pointer () || hir_instr->type ->is_array ()) {
245- clazz = lir::Register::GPR64 ;
246- } else {
247- clazz = lir::Register::GPR32 ;
248- }
252+ lir::Register::RegClass clazz = class_from_type (hir_instr->type );
249253 auto *callee = dynamic_cast <hir::Function *>(hir_instr->operand (0 ));
250254 auto dst = builder.emit_call (callee->name , std::move (args), clazz);
251255 dst.set_class (clazz);
252256 vreg_map[hir_instr] = dst;
253257 return ;
254258 }
255259 case hir::Opcode::Load: {
260+ std::cout << " Type arg for load is " << hir_instr->type_arg << std::endl;
256261 auto ptr = lower_operand (hir_instr->operand (0 ));
257262 if (ptr.is_reg ())
258263 ptr.get_reg_mut ().set_class (lir::Register::GPR64 );
@@ -261,10 +266,11 @@ void LIRLowering::lower_instruction(hir::Instruction *hir_instr) {
261266 return ;
262267 }
263268 case hir::Opcode::Store: {
269+ std::cout << " Type arg for store is " << hir_instr->type_arg << std::endl;
264270 auto base = lower_operand (hir_instr->operand (0 ));
265271 auto value = lower_operand (hir_instr->operand (1 ));
266- auto base_reg = ensure_reg (base);
267- auto value_reg = ensure_reg (value);
272+ auto base_reg = ensure_reg (base, class_from_type (hir_instr-> type ) );
273+ auto value_reg = ensure_reg (value, class_from_type (hir_instr-> type_arg ) );
268274
269275 if (base.is_reg ())
270276 base.get_reg_mut ().set_class (lir::Register::GPR64 );
@@ -277,14 +283,15 @@ void LIRLowering::lower_instruction(hir::Instruction *hir_instr) {
277283 auto size = hir_instr->type_arg ->size_of ();
278284 auto size_op = lir::Operand::from_imm (size);
279285
280- auto index_reg = ensure_reg (index);
281- auto size_reg = ensure_reg (size_op);
282- auto offset = builder.emit_binop (lir::Opcode::Mul, index_reg, size_reg);
286+ auto index_reg = ensure_reg (index, class_from_type (hir_instr->type_arg ));
287+ auto size_reg = ensure_reg (size_op, class_from_type (hir_instr->type_arg ));
288+ auto offset = builder.emit_binop (lir::Opcode::Mul, index_reg, size_reg,
289+ class_from_type (hir_instr->type_arg ));
283290 offset.set_class (lir::Register::RegClass::GPR64 );
284291
285292 auto ptr = builder.emit_binop (lir::Opcode::Add, base,
286- lir::Operand::from_reg (offset));
287- ptr. set_class ( lir::Register::RegClass ::GPR64 );
293+ lir::Operand::from_reg (offset),
294+ lir::Register::GPR64 );
288295 vreg_map[hir_instr] = ptr;
289296 return ;
290297 }
@@ -304,18 +311,14 @@ void LIRLowering::lower_binop(hir::Instruction *hir_instr, lir::Opcode op) {
304311 auto rhs = lower_operand (hir_instr->operand (1 ));
305312
306313 // First operand must always be a register
307- lhs = ensure_reg (lhs);
314+ lhs = ensure_reg (lhs, class_from_type (hir_instr-> type ) );
308315
309316 // Second operand: check if target accepts immediate
310317 if (rhs.is_imm () && !target_info.accepts_imm (op))
311- rhs = ensure_reg (rhs);
312-
313- auto dst = builder.emit_binop (op, lhs, rhs);
314- if (hir_instr->type ->is_pointer ()) {
315- lhs.get_reg_mut ().set_class (lir::Register::GPR64 );
316- rhs.get_reg_mut ().set_class (lir::Register::GPR64 );
317- }
318+ rhs = ensure_reg (rhs, class_from_type (hir_instr->type ));
318319
320+ auto dst = builder.emit_binop (op, lhs, rhs, class_from_type (hir_instr->type ));
321+ dst.set_class (class_from_type (hir_instr->type ));
319322 vreg_map[hir_instr] = dst;
320323}
321324
0 commit comments