Compare commits

..

2 Commits

3 changed files with 18 additions and 33 deletions

View File

@ -298,18 +298,19 @@ impl<'ctx, 'a> CodeGenContext<'ctx, 'a> {
(Operator::BitOr, _) => self.builder.build_or(lhs, rhs, "or").into(),
(Operator::BitXor, _) => self.builder.build_xor(lhs, rhs, "xor").into(),
(Operator::BitAnd, _) => self.builder.build_and(lhs, rhs, "and").into(),
(Operator::LShift, _) => {
let rhs = if lhs.get_type().get_bit_width() > rhs.get_type().get_bit_width() {
(Operator::LShift, signed) | (Operator::RShift, signed) => {
let common_type = lhs.get_type();
let rhs = if common_type.get_bit_width() > rhs.get_type().get_bit_width() {
if signed {
self.builder.build_int_s_extend(rhs, lhs.get_type(), "")
self.builder.build_int_s_extend(rhs, common_type, "")
} else {
self.builder.build_int_z_extend(rhs, lhs.get_type(), "")
self.builder.build_int_z_extend(rhs, common_type, "")
}
} else {
self.builder.build_int_truncate_or_bit_cast(rhs, lhs.get_type(), "")
self.builder.build_int_truncate_or_bit_cast(rhs, common_type, "")
};
let rhs_gez = self.builder.build_int_compare(IntPredicate::SGE, rhs, lhs.get_type().const_zero(), "");
let rhs_gez = self.builder.build_int_compare(IntPredicate::SGE, rhs, common_type.const_zero(), "");
self.make_assert(
generator,
rhs_gez,
@ -319,30 +320,11 @@ impl<'ctx, 'a> CodeGenContext<'ctx, 'a> {
self.current_loc
);
self.builder.build_left_shift(lhs, rhs, "lshift").into()
},
(Operator::RShift, _) => {
let rhs = if lhs.get_type().get_bit_width() > rhs.get_type().get_bit_width() {
if signed {
self.builder.build_int_s_extend(rhs, lhs.get_type(), "")
} else {
self.builder.build_int_z_extend(rhs, lhs.get_type(), "")
}
} else {
self.builder.build_int_truncate_or_bit_cast(rhs, lhs.get_type(), "")
};
let rhs_gez = self.builder.build_int_compare(IntPredicate::SGE, rhs, lhs.get_type().const_zero(), "");
self.make_assert(
generator,
rhs_gez,
"ValueError",
"negative shift count",
[None, None, None],
self.current_loc
);
self.builder.build_right_shift(lhs, rhs, true, "rshift").into()
match *op {
Operator::LShift => self.builder.build_left_shift(lhs, rhs, "lshift").into(),
Operator::RShift => self.builder.build_right_shift(lhs, rhs, signed, "rshift").into(),
_ => unreachable!()
}
},
(Operator::FloorDiv, true) => self.builder.build_int_signed_div(lhs, rhs, "floordiv").into(),
(Operator::FloorDiv, false) => self.builder.build_int_unsigned_div(lhs, rhs, "floordiv").into(),

View File

@ -2,9 +2,8 @@ use crate::typecheck::typedef::TypeEnum;
use super::type_inferencer::Inferencer;
use super::typedef::Type;
use nac3parser::ast::{self, Constant, Expr, ExprKind, Stmt, StmtKind, StrRef};
use nac3parser::ast::{self, Constant, Expr, ExprKind, Operator::{LShift, RShift}, Stmt, StmtKind, StrRef};
use std::{collections::HashSet, iter::once};
use nac3parser::ast::Operator::{LShift, RShift};
impl<'a> Inferencer<'a> {
fn should_have_value(&mut self, expr: &Expr<Option<Type>>) -> Result<(), String> {
@ -114,6 +113,7 @@ impl<'a> Inferencer<'a> {
self.should_have_value(left)?;
self.should_have_value(right)?;
// Check whether a bitwise shift has a negative RHS constant value
if *op == LShift || *op == RShift {
if let ExprKind::Constant { value, .. } = &right.node {
let rhs_val = match value {

View File

@ -224,7 +224,10 @@ pub fn impl_bitwise_arithmetic(unifier: &mut Unifier, store: &PrimitiveStore, ty
/// LShift, RShift
pub fn impl_bitwise_shift(unifier: &mut Unifier, store: &PrimitiveStore, ty: Type) {
impl_binop(unifier, store, ty, &[store.int32], ty, &[ast::Operator::LShift, ast::Operator::RShift])
impl_binop(unifier, store, ty, &[store.int32], ty, &[ast::Operator::LShift, ast::Operator::RShift]);
if !unifier.unioned(ty, store.int32) {
impl_binop(unifier, store, ty, &[ty], ty, &[ast::Operator::LShift, ast::Operator::RShift]);
}
}
/// Div