compiler: Check scalar arithmetic lowering
07646b5dd4532736857647272200f5c3370a6a672bec9519573f18416daab706
1 parent
39a13d89
lib/std/lang/lower.rad
+15 -4
| 6305 | 6305 | } |
|
| 6306 | 6306 | return result; |
|
| 6307 | 6307 | } |
|
| 6308 | 6308 | ||
| 6309 | 6309 | /// Emit a scalar binary operation instruction. |
|
| 6310 | - | unsafe fn emitScalarBinOp 'arena 'phase 'function ( |
|
| 6310 | + | fn emitScalarBinOp 'arena 'phase 'function ( |
|
| 6311 | 6311 | self: &mut FnLowerer 'arena 'phase 'function, |
|
| 6312 | 6312 | op: ast::BinaryOp, |
|
| 6313 | 6313 | typ: il::Type, |
|
| 6314 | 6314 | a: il::Val, |
|
| 6315 | 6315 | b: il::Val, |
| 6382 | 6382 | } |
|
| 6383 | 6383 | return il::Val::Reg(dst); |
|
| 6384 | 6384 | } |
|
| 6385 | 6385 | ||
| 6386 | 6386 | /// Normalize sub-word values to well-defined high bits. |
|
| 6387 | - | unsafe fn normalizeSubword 'arena 'phase 'function (self: &mut FnLowerer 'arena 'phase 'function, typ: il::Type, unsigned: bool, val: il::Val) -> il::Val where 'arena: 'phase, 'phase: 'function { |
|
| 6387 | + | fn normalizeSubword 'arena 'phase 'function (self: &mut FnLowerer 'arena 'phase 'function, typ: il::Type, unsigned: bool, val: il::Val) -> il::Val where 'arena: 'phase, 'phase: 'function { |
|
| 6388 | 6388 | if typ == il::Type::W8 or typ == il::Type::W16 { |
|
| 6389 | 6389 | let extDst: il::Reg = nextReg(self); |
|
| 6390 | 6390 | if unsigned { |
|
| 6391 | 6391 | emit(self, il::Instr::Zext { typ, dst: extDst, val }); |
|
| 6392 | 6392 | } else { |
| 6405 | 6405 | } |
|
| 6406 | 6406 | } |
|
| 6407 | 6407 | let val = try lowerExpr(self, unop.value); |
|
| 6408 | 6408 | let t = try typeOf(self, node); |
|
| 6409 | 6409 | let typ = ilType(self.low, t); |
|
| 6410 | + | return emitScalarUnOp(self, unop.op, typ, val, isUnsignedType(t)); |
|
| 6411 | + | } |
|
| 6412 | + | ||
| 6413 | + | /// Emit a unary scalar operation and normalize its subword result. |
|
| 6414 | + | fn emitScalarUnOp 'arena 'phase 'function ( |
|
| 6415 | + | self: &mut FnLowerer 'arena 'phase 'function, |
|
| 6416 | + | op: ast::UnaryOp, |
|
| 6417 | + | typ: il::Type, |
|
| 6418 | + | val: il::Val, |
|
| 6419 | + | unsigned: bool |
|
| 6420 | + | ) -> il::Val where 'arena: 'phase, 'phase: 'function { |
|
| 6410 | 6421 | let dst = nextReg(self); |
|
| 6411 | 6422 | let mut needsExt: bool = false; |
|
| 6412 | 6423 | ||
| 6413 | - | match unop.op { |
|
| 6424 | + | match op { |
|
| 6414 | 6425 | case ast::UnaryOp::Not => { |
|
| 6415 | 6426 | emit(self, il::Instr::BinOp { op: il::BinOp::Eq, typ, dst, a: val, b: il::Val::Imm(0) }); |
|
| 6416 | 6427 | } |
|
| 6417 | 6428 | case ast::UnaryOp::Neg => { |
|
| 6418 | 6429 | emit(self, il::Instr::UnOp { op: il::UnOp::Neg, typ, dst, a: val }); |
| 6422 | 6433 | emit(self, il::Instr::UnOp { op: il::UnOp::Not, typ, dst, a: val }); |
|
| 6423 | 6434 | set needsExt = true; |
|
| 6424 | 6435 | } |
|
| 6425 | 6436 | } |
|
| 6426 | 6437 | if needsExt { |
|
| 6427 | - | return normalizeSubword(self, typ, isUnsignedType(t), il::Val::Reg(dst)); |
|
| 6438 | + | return normalizeSubword(self, typ, unsigned, il::Val::Reg(dst)); |
|
| 6428 | 6439 | } |
|
| 6429 | 6440 | return il::Val::Reg(dst); |
|
| 6430 | 6441 | } |
|
| 6431 | 6442 | ||
| 6432 | 6443 | /// Lower a cast expression (`x as T`). |