Compare commits
2 Commits
5d28e4e780
...
09dbae1e63
Author | SHA1 | Date |
---|---|---|
David Mak | 09dbae1e63 | |
David Mak | 625943cf01 |
|
@ -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(),
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue