@@ -12,8 +12,9 @@ use rustc_middle::ty::{ParamEnv, Ty, TyCtxt};
12
12
use rustc_target:: abi:: call:: FnAbi ;
13
13
use rustc_target:: spec:: { HasTargetSpec , Target } ;
14
14
15
+ use crate :: c_expr;
15
16
use crate :: context:: { CFunctionBuilder , CodegenCx } ;
16
- use crate :: module:: { CExpr , CStmt } ;
17
+ use crate :: module:: { CDecl , CExpr , CStmt , CType } ;
17
18
use crate :: utils:: slab:: Id ;
18
19
19
20
mod abi;
@@ -127,13 +128,13 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> {
127
128
}
128
129
129
130
fn ret_void ( & mut self ) {
130
- let mut fuctions = self . cx . functions . borrow_mut ( ) ;
131
- fuctions [ self . bb ] . push_stmt ( CStmt :: Return ( None ) ) ;
131
+ let mut functions = self . cx . functions . borrow_mut ( ) ;
132
+ functions [ self . bb ] . push_stmt ( CStmt :: Return ( None ) ) ;
132
133
}
133
134
134
135
fn ret ( & mut self , v : Self :: Value ) {
135
- let mut fuctions = self . cx . functions . borrow_mut ( ) ;
136
- fuctions [ self . bb ] . push_stmt ( CStmt :: Return ( Some ( Box :: new ( CExpr :: Value ( v) ) ) ) ) ;
136
+ let mut functions = self . cx . functions . borrow_mut ( ) ;
137
+ functions [ self . bb ] . push_stmt ( CStmt :: Return ( Some ( Box :: new ( CExpr :: Value ( v) ) ) ) ) ;
137
138
}
138
139
139
140
fn br ( & mut self , dest : Self :: BasicBlock ) {
@@ -495,8 +496,48 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> {
495
496
todo ! ( )
496
497
}
497
498
499
+ /// Performs cast between integers, x as ty in Rust.
500
+ ///
501
+ /// If the bit width is different, a truncation or extension is required.
502
+ /// The type of extension—sign-extension or zero-extension—depends on the
503
+ /// signedness of the source type.
504
+ ///
505
+ /// According to the C17 standard, section "6.3.1.3 Signed and unsigned
506
+ /// integers", casting to an unsigned integer behaves the same as in Rust.
507
+ /// However, casting to a signed integer is implementation-defined.
508
+ ///
509
+ /// Therefore, a two-step cast is necessary. First, cast to an unsigned
510
+ /// integer via explicit conversion. Then, use a helper function to cast the
511
+ /// result to a signed integer.
498
512
fn intcast ( & mut self , val : Self :: Value , dest_ty : Self :: Type , is_signed : bool ) -> Self :: Value {
499
- todo ! ( )
513
+ let mut functions = self . cx . functions . borrow_mut ( ) ;
514
+ let function = & mut functions[ self . bb ] ;
515
+ let ret = function. next_value ( ) ;
516
+
517
+ let dest = if let CType :: Primitive ( ty) = dest_ty { ty } else { unreachable ! ( ) } ;
518
+ let cast = if !dest. is_signed ( ) {
519
+ CExpr :: Cast { ty : CType :: Primitive ( dest) , expr : Box :: new ( CExpr :: Value ( val) ) }
520
+ } else {
521
+ let cast = CExpr :: Cast {
522
+ ty : CType :: Primitive ( dest. to_unsigned ( ) ) ,
523
+ expr : Box :: new ( CExpr :: Value ( val) ) ,
524
+ } ;
525
+ CExpr :: Call {
526
+ callee : c_expr ! ( "__rust_utos" ) ,
527
+ args : vec ! [
528
+ c_expr!( dest. to_unsigned( ) . to_string( ) ) ,
529
+ c_expr!( dest. to_string( ) ) ,
530
+ cast,
531
+ c_expr!( dest. max_value( ) ) ,
532
+ ] ,
533
+ }
534
+ } ;
535
+ function. push_stmt ( CStmt :: Decl ( Box :: new ( CDecl :: Var {
536
+ name : ret,
537
+ ty : dest_ty,
538
+ init : Some ( cast) ,
539
+ } ) ) ) ;
540
+ ret
500
541
}
501
542
502
543
fn pointercast ( & mut self , val : Self :: Value , dest_ty : Self :: Type ) -> Self :: Value {
0 commit comments