Skip to content

Commit

Permalink
fixed radix based type error
Browse files Browse the repository at this point in the history
  • Loading branch information
PhilippRados committed Jun 11, 2024
1 parent fa89d93 commit 0218ae3
Show file tree
Hide file tree
Showing 10 changed files with 186 additions and 92 deletions.
13 changes: 13 additions & 0 deletions tests/fixtures/num_literal.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#include <stdio.h>

int main() {
if (0xFFFFFFFF == 037777777777) {
printf("equal");
}
if (0xFFFFFFFA == -6) {
printf("equal");
}
if (-0xFFFFFFFF == 0xFFFFFFFF) {
printf("equal");
}
}
1 change: 1 addition & 0 deletions tests/snapshots/success_num_literal
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
equalequal
3 changes: 1 addition & 2 deletions wrecc_compiler/src/compiler/codegen/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -971,8 +971,7 @@ impl Compiler {
) -> Register {
let value_reg = self.execute_expr(func, expr);
let value_reg = self.convert_to_rval(value_reg);
let by_amount =
Register::Literal(LiteralKind::new(by_amount as u64, &None), value_reg.get_type());
let by_amount = Register::Literal(LiteralKind::Unsigned(by_amount as u64), value_reg.get_type());

match direction {
ScaleDirection::Up => self.cg_mult(by_amount, value_reg),
Expand Down
24 changes: 20 additions & 4 deletions wrecc_compiler/src/compiler/common/token.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,22 @@ pub enum IntSuffix {
ULL,
}

#[derive(Debug, Clone, PartialEq)]
pub enum Radix {
Decimal,
Hex,
Octal,
}
impl Radix {
pub fn to_string(&self) -> &'static str {
match self {
Radix::Hex => "hex",
Radix::Octal => "octal",
Radix::Decimal => "decimal",
}
}
}

#[derive(Debug, Clone, PartialEq)]
pub enum TokenKind {
// Single-character tokens.
Expand Down Expand Up @@ -68,7 +84,7 @@ pub enum TokenKind {
Ident(String),
String(String),
CharLit(char),
Number(u64, Option<IntSuffix>),
Number(u64, Radix, Option<IntSuffix>),

// Keywords.
Void,
Expand Down Expand Up @@ -164,7 +180,7 @@ impl TokenKind {
TokenKind::TypeDef | TokenKind::Default => 7,
TokenKind::Continue | TokenKind::Register => 8,

TokenKind::Number(n, suffix) => {
TokenKind::Number(n, _, suffix) => {
n.to_string().len()
+ match suffix {
Some(IntSuffix::U | IntSuffix::L) => 1,
Expand Down Expand Up @@ -313,9 +329,9 @@ impl Token {
_ => panic!("cant unwrap string on {} token", self.kind),
}
}
pub fn unwrap_num(self) -> (u64, Option<IntSuffix>) {
pub fn unwrap_num(self) -> (u64, Radix, Option<IntSuffix>) {
match self.kind {
TokenKind::Number(n, suffix) => (n, suffix),
TokenKind::Number(n, radix, suffix) => (n, radix, suffix),
_ => panic!("cant unwrap number on {} token", self.kind),
}
}
Expand Down
98 changes: 51 additions & 47 deletions wrecc_compiler/src/compiler/common/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -327,11 +327,8 @@ impl Type {
}
pub fn is_unsigned(&self) -> bool {
match self {
Type::Primitive(Primitive::Char(true))
| Type::Primitive(Primitive::Short(true))
| Type::Primitive(Primitive::Int(true))
| Type::Primitive(Primitive::Long(true))
| Type::Pointer(_) => true,
Type::Primitive(prim) => prim.is_unsigned(),
Type::Pointer(_) => true,
_ => false,
}
}
Expand Down Expand Up @@ -455,6 +452,33 @@ impl TypeInfo for Primitive {
}
}
impl Primitive {
/// 6.4.4.1.5 Determines smallest possible integer-type capable of holding literal number
pub fn new(n: u64, radix: Radix, suffix: Option<IntSuffix>) -> Primitive {
if let Some(IntSuffix::U | IntSuffix::UL | IntSuffix::ULL) = suffix {
return if u32::try_from(n).is_ok() && matches!(suffix, Some(IntSuffix::U)) {
Primitive::Int(true)
} else {
Primitive::Long(true)
};
}
if let Some(IntSuffix::L | IntSuffix::LL) = suffix {
return if i64::try_from(n).is_ok() {
Primitive::Long(false)
} else {
Primitive::Long(true)
};
}

if i32::try_from(n).is_ok() {
Primitive::Int(false)
} else if u32::try_from(n).is_ok() && matches!(radix, Radix::Octal | Radix::Hex) {
Primitive::Int(true)
} else if i64::try_from(n).is_ok() {
Primitive::Long(false)
} else {
Primitive::Long(true)
}
}
fn fmt(&self) -> &str {
match self {
Primitive::Void => "void",
Expand All @@ -469,6 +493,16 @@ impl Primitive {
}
}

pub fn is_unsigned(&self) -> bool {
match self {
Primitive::Char(true)
| Primitive::Short(true)
| Primitive::Int(true)
| Primitive::Long(true) => true,
_ => false,
}
}

fn max(&self) -> u64 {
match self {
Primitive::Void => unreachable!(),
Expand Down Expand Up @@ -521,48 +555,6 @@ pub enum LiteralKind {
Signed(i64),
}
impl LiteralKind {
pub fn new(n: u64, suffix: &Option<IntSuffix>) -> LiteralKind {
if let Some(IntSuffix::U | IntSuffix::UL | IntSuffix::ULL) = suffix {
return LiteralKind::Unsigned(n);
}
if let Ok(n) = i64::try_from(n) {
LiteralKind::Signed(n)
} else {
LiteralKind::Unsigned(n)
}
}
pub fn is_zero(&self) -> bool {
match self {
LiteralKind::Signed(0) | LiteralKind::Unsigned(0) => true,
_ => false,
}
}
pub fn is_negative(&self) -> bool {
match self {
LiteralKind::Signed(n) => *n < 0,
LiteralKind::Unsigned(_) => false,
}
}
/// Determines smallest possible integer-type capable of holding literal number
pub fn integer_type(&self, suffix: Option<IntSuffix>) -> Primitive {
match self {
LiteralKind::Signed(n) => {
// don't have to check for unsigned suffix because then literalkind is already unsigned
if i32::try_from(*n).is_ok() && !matches!(suffix, Some(IntSuffix::L | IntSuffix::LL)) {
Primitive::Int(false)
} else {
Primitive::Long(false)
}
}
LiteralKind::Unsigned(n) => {
if u32::try_from(*n).is_ok() && !matches!(suffix, Some(IntSuffix::UL | IntSuffix::ULL)) {
Primitive::Int(true)
} else {
Primitive::Long(true)
}
}
}
}
pub fn try_i64(&self) -> Option<i64> {
match self {
LiteralKind::Signed(n) => Some(*n),
Expand All @@ -582,6 +574,18 @@ impl LiteralKind {
LiteralKind::Unsigned(n) => *n > ty.max(),
}
}
pub fn is_zero(&self) -> bool {
match self {
LiteralKind::Signed(0) | LiteralKind::Unsigned(0) => true,
_ => false,
}
}
pub fn is_negative(&self) -> bool {
match self {
LiteralKind::Signed(n) => *n < 0,
LiteralKind::Unsigned(_) => false,
}
}
}
impl ToString for LiteralKind {
fn to_string(&self) -> String {
Expand Down
4 changes: 2 additions & 2 deletions wrecc_compiler/src/compiler/parser/hir/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ pub enum ExprKind {
},
String(Token),
Char(char),
Number(u64, Option<IntSuffix>),
Number(u64, Radix, Option<IntSuffix>),
Ident(Token),
Nop,
}
Expand Down Expand Up @@ -104,7 +104,7 @@ impl PrintIndent for ExprKind {
indent_fmt(r_expr.as_ref(), indent_level + 1)
)
}
ExprKind::Number(literal, _) => format!("Literal: {}", literal.to_string()),
ExprKind::Number(literal, ..) => format!("Literal: {}", literal.to_string()),
ExprKind::Char(c) => format!("Character-literal: {}", c),
ExprKind::Ident(name) => format!("Ident: '{}'", name.unwrap_string()),
ExprKind::String(token) => format!("String: {:?}", token.unwrap_string()),
Expand Down
10 changes: 5 additions & 5 deletions wrecc_compiler/src/compiler/parser/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1184,7 +1184,7 @@ impl Parser {
ExprKind::CompoundAssign {
l_expr: Box::new(right),
token,
r_expr: Box::new(ExprKind::Number(1, None)),
r_expr: Box::new(ExprKind::Number(1, Radix::Decimal, None)),
}
}
// typecast
Expand Down Expand Up @@ -1311,8 +1311,8 @@ impl Parser {
}
fn primary(&mut self) -> Result<ExprKind, Error> {
if let Some(n) = match_next!(self, TokenKind::Number(..)) {
let (n, suffix) = n.unwrap_num();
return Ok(ExprKind::Number(n, suffix));
let (n, radix, suffix) = n.unwrap_num();
return Ok(ExprKind::Number(n, radix, suffix));
}
if let Some(c) = match_next!(self, TokenKind::CharLit(_)) {
return Ok(ExprKind::Char(c.unwrap_char()));
Expand Down Expand Up @@ -1730,13 +1730,13 @@ int main() {
#[test]
fn matches_works_on_enums_with_values() {
let tokens = vec![
token_default!(TokenKind::Number(2, None)),
token_default!(TokenKind::Number(2, Radix::Decimal, None)),
token_default!(TokenKind::Plus),
];
let mut p = Parser::new(tokens);

let result = match_next!(p, TokenKind::Number(..) | TokenKind::String(_));
let expected = Some(token_default!(TokenKind::Number(2, None)));
let expected = Some(token_default!(TokenKind::Number(2, Radix::Decimal, None)));

assert_eq!(result, expected);
}
Expand Down
Loading

0 comments on commit 0218ae3

Please sign in to comment.