compiler: Check scalar arithmetic lowering

07646b5dd4532736857647272200f5c3370a6a672bec9519573f18416daab706
Alexis Sellier committed ago 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`).