@@ -25,11 +25,12 @@ use super::{
25
25
Initialized , ResolveTypeCtx ,
26
26
} ;
27
27
use crate :: {
28
- asg:: { self , Asg , Expr , ExprKind , FuncRef , StructRef , TypeKind , TypedExpr } ,
28
+ asg:: { self , Asg , Cast , CastFrom , Expr , ExprKind , FuncRef , StructRef , TypeKind , TypedExpr } ,
29
29
ast:: {
30
30
self , CInteger , CIntegerAssumptions , ConformBehavior , IntegerKnown , Language , Settings ,
31
31
UnaryOperator ,
32
32
} ,
33
+ data_units:: BitUnits ,
33
34
ir:: IntegerSign ,
34
35
resolve:: {
35
36
error:: ResolveErrorKind ,
@@ -447,6 +448,8 @@ pub fn resolve_expr(
447
448
asg:: ExprKind :: Continue . at ( source) ,
448
449
) ) ,
449
450
ast:: ExprKind :: IntegerPromote ( value) => {
451
+ // NOTE: Since this expression comes from C, there
452
+ // should not be any untyped literals.
450
453
let inner = resolve_expr (
451
454
ctx,
452
455
value,
@@ -455,19 +458,59 @@ pub fn resolve_expr(
455
458
ResolveExprMode :: RequireValue ,
456
459
) ?;
457
460
458
- let rank = inner. ty . integer_rank ( ) ;
461
+ // WARNING: For now, we assume that shorts are 16 bits and ints are 32 bits
462
+ // since this is the case for the vast majority of systems.
463
+ // Targets where this does not hold will not be supported for now.
464
+ // If we do wish to support them in the future,
465
+ // We will probably need to add new types such as promoted<T> and arith<A, B>
466
+ // to represent the possible result types on non-conformant architectures.
459
467
460
- // After promotion, types will either be int, unsigned int, or the same
461
- // Maybe we express this type as promoted<T>
462
- // And then for combined
463
- // a + b
464
- // and other arithmetic expressions, the
465
- // result could be a separate type like usual_arithmetic<promoted<ushort>,
466
- // promoted<char>>
467
- // I think we just need to be careful of the sign from promoted unsigned shorts.
468
+ let promoted_type = match & inner. ty . kind {
469
+ TypeKind :: Boolean => {
470
+ Some ( TypeKind :: CInteger ( CInteger :: Int , Some ( IntegerSign :: Signed ) ) )
471
+ }
472
+ TypeKind :: Integer ( bits, sign) => {
473
+ if bits. bits ( ) < BitUnits :: of ( 32 ) {
474
+ Some ( TypeKind :: CInteger ( CInteger :: Int , Some ( IntegerSign :: Signed ) ) )
475
+ } else if bits. bits ( ) == BitUnits :: of ( 32 ) {
476
+ Some ( TypeKind :: CInteger ( CInteger :: Int , Some ( * sign) ) )
477
+ } else {
478
+ None
479
+ }
480
+ }
481
+ TypeKind :: CInteger ( c_integer, _) => match c_integer {
482
+ CInteger :: Char | CInteger :: Short => {
483
+ Some ( TypeKind :: CInteger ( CInteger :: Int , Some ( IntegerSign :: Signed ) ) )
484
+ }
485
+ CInteger :: Int | CInteger :: Long | CInteger :: LongLong => None ,
486
+ } ,
487
+ TypeKind :: SizeInteger ( _) => {
488
+ // We will treat size integers as if they don't get promoted
489
+ None
490
+ }
491
+ TypeKind :: IntegerLiteral ( _) => {
492
+ panic ! ( "Cannot integer promote untyped integer literal. This should never happen since untyped integer literals do not exist in C." )
493
+ }
494
+ _ => None ,
495
+ } ;
496
+
497
+ if let Some ( promoted_type) = promoted_type {
498
+ let promoted_type = promoted_type. at ( ast_expr. source ) ;
499
+
500
+ return Ok ( TypedExpr :: new (
501
+ promoted_type. clone ( ) ,
502
+ ExprKind :: IntegerCast ( Box :: new ( CastFrom {
503
+ cast : Cast {
504
+ target_type : promoted_type,
505
+ value : inner. expr ,
506
+ } ,
507
+ from_type : inner. ty ,
508
+ } ) )
509
+ . at ( ast_expr. source ) ,
510
+ ) ) ;
511
+ }
468
512
469
- Ok ( todo ! ( "integer promote expression - {:?}" , rank) )
470
- // Ok(TypedExpr::new())
513
+ return Ok ( inner) ;
471
514
}
472
515
} ?;
473
516
0 commit comments