@@ -4403,60 +4403,73 @@ fn trans_lval(&@block_ctxt cx, &@ast::expr e) -> lval_result {
4403
4403
4404
4404
fn int_cast( & @block_ctxt bcx, TypeRef lldsttype, TypeRef llsrctype,
4405
4405
ValueRef llsrc, bool signed) -> ValueRef {
4406
- if ( llvm:: LLVMGetIntTypeWidth ( lldsttype) >
4407
- llvm:: LLVMGetIntTypeWidth ( llsrctype) ) {
4408
- if ( signed) {
4409
- // Widening signed cast.
4410
-
4411
- ret bcx. build. SExtOrBitCast ( llsrc, lldsttype) ;
4412
- }
4413
- // Widening unsigned cast.
4406
+ auto srcsz = llvm:: LLVMGetIntTypeWidth ( llsrctype) ;
4407
+ auto dstsz = llvm:: LLVMGetIntTypeWidth ( lldsttype) ;
4408
+ ret if dstsz == srcsz { bcx. build. BitCast ( llsrc, lldsttype) }
4409
+ else if srcsz > dstsz { bcx. build. TruncOrBitCast ( llsrc, lldsttype) }
4410
+ else if signed { bcx. build. SExtOrBitCast ( llsrc, lldsttype) }
4411
+ else { bcx. build. ZExtOrBitCast ( llsrc, lldsttype) } ;
4412
+ }
4414
4413
4415
- ret bcx. build. ZExtOrBitCast ( llsrc, lldsttype) ;
4416
- }
4417
- ret bcx. build. TruncOrBitCast ( llsrc, lldsttype) ;
4414
+ fn float_cast( & @block_ctxt bcx, TypeRef lldsttype, TypeRef llsrctype,
4415
+ ValueRef llsrc) -> ValueRef {
4416
+ auto srcsz = lib:: llvm:: float_width( llsrctype) ;
4417
+ auto dstsz = lib:: llvm:: float_width( lldsttype) ;
4418
+ ret if dstsz > srcsz { bcx. build. FPExt ( llsrc, lldsttype) }
4419
+ else if srcsz > dstsz { bcx. build. FPTrunc ( llsrc, lldsttype) }
4420
+ else { llsrc } ;
4418
4421
}
4419
4422
4420
4423
fn trans_cast( & @block_ctxt cx, & @ast:: expr e, ast:: node_id id) -> result {
4424
+ auto ccx = cx. fcx. lcx. ccx;
4421
4425
auto e_res = trans_expr( cx, e) ;
4422
- auto llsrctype = val_ty( e_res. val) ;
4423
- auto t = node_id_type( cx. fcx. lcx. ccx, id) ;
4424
- auto lldsttype = type_of( cx. fcx. lcx. ccx, e. span, t) ;
4425
- if ( !ty:: type_is_fp( cx. fcx. lcx. ccx. tcx, t) ) {
4426
-
4427
- // TODO: native-to-native casts
4428
- if ( ty:: type_is_native( cx. fcx. lcx. ccx. tcx,
4429
- ty:: expr_ty( cx. fcx. lcx. ccx. tcx, e) ) ) {
4430
- e_res =
4431
- rslt( e_res. bcx,
4432
- e_res. bcx. build. PtrToInt ( e_res. val, lldsttype) ) ;
4433
- } else if ( ty:: type_is_native( cx. fcx. lcx. ccx. tcx, t) ) {
4434
- e_res =
4435
- rslt( e_res. bcx,
4436
- e_res. bcx. build. IntToPtr ( e_res. val, lldsttype) ) ;
4437
- } else {
4438
- e_res =
4439
- rslt( e_res. bcx,
4440
- int_cast( e_res. bcx, lldsttype, llsrctype, e_res. val,
4441
- ty:: type_is_signed( cx. fcx. lcx. ccx. tcx, t) ) ) ;
4442
- }
4443
- }
4444
- else {
4445
- if ( ty:: type_is_integral( cx. fcx. lcx. ccx. tcx,
4446
- ty:: expr_ty( cx. fcx. lcx. ccx. tcx, e) ) ) {
4447
- if ( ty:: type_is_signed( cx. fcx. lcx. ccx. tcx,
4448
- ty:: expr_ty( cx. fcx. lcx. ccx. tcx, e) ) ) {
4449
- e_res = rslt( e_res. bcx,
4450
- e_res. bcx. build. SIToFP ( e_res. val, lldsttype) ) ;
4451
- }
4452
- else {
4453
- e_res = rslt( e_res. bcx,
4454
- e_res. bcx. build. UIToFP ( e_res. val, lldsttype) ) ;
4455
- }
4456
- }
4457
- else { cx. fcx. lcx. ccx. sess. unimpl( "fp cast") ; }
4458
- }
4459
- ret e_res;
4426
+ auto ll_t_in = val_ty( e_res. val) ;
4427
+ auto t_in = ty:: expr_ty( ccx. tcx, e) ;
4428
+ auto t_out = node_id_type( ccx, id) ;
4429
+ auto ll_t_out = type_of( ccx, e. span, t_out) ;
4430
+
4431
+ tag kind { native_; integral; float; other; }
4432
+ fn t_kind( & ty:: ctxt tcx, ty:: t t) -> kind {
4433
+ ret if ty:: type_is_fp( tcx, t) { float }
4434
+ else if ty:: type_is_native( tcx, t) { native_ }
4435
+ else if ty:: type_is_integral( tcx, t) { integral }
4436
+ else { other } ;
4437
+ }
4438
+ auto k_in = t_kind( ccx. tcx, t_in) ;
4439
+ auto k_out = t_kind( ccx. tcx, t_out) ;
4440
+ auto s_in = k_in == integral && ty:: type_is_signed( ccx. tcx, t_in) ;
4441
+
4442
+ auto newval = alt rec( in =k_in, out=k_out) {
4443
+ { in : integral, out: integral} {
4444
+ int_cast( e_res. bcx, ll_t_out, ll_t_in, e_res. val, s_in)
4445
+ }
4446
+ { in : float, out: float} {
4447
+ float_cast( e_res. bcx, ll_t_out, ll_t_in, e_res. val)
4448
+ }
4449
+ { in : integral, out: float} {
4450
+ if s_in { e_res. bcx. build. SIToFP ( e_res. val, ll_t_out) }
4451
+ else { e_res. bcx. build. UIToFP ( e_res. val, ll_t_out) }
4452
+ }
4453
+ { in : float, out: integral} {
4454
+ if ty:: type_is_signed( ccx. tcx, t_out) {
4455
+ e_res. bcx. build. FPToSI ( e_res. val, ll_t_out)
4456
+ } else { e_res. bcx. build. FPToUI ( e_res. val, ll_t_out) }
4457
+ }
4458
+ { in : integral, out: native_} {
4459
+ e_res. bcx. build. IntToPtr ( e_res. val, ll_t_out)
4460
+ }
4461
+ { in : native_, out: integral} {
4462
+ e_res. bcx. build. PtrToInt ( e_res. val, ll_t_out)
4463
+ }
4464
+ { in : native_, out: native_} {
4465
+ e_res. bcx. build. PointerCast ( e_res. val, ll_t_out)
4466
+ }
4467
+ _ {
4468
+ ccx. sess. bug( "Translating unsupported cast. ") ;
4469
+ C_nil ( ) // FIXME the typechecker doesn't seem to understand _|_ here
4470
+ }
4471
+ } ;
4472
+ ret rslt( e_res. bcx, newval) ;
4460
4473
}
4461
4474
4462
4475
fn trans_bind_thunk( & @local_ctxt cx, & span sp, & ty:: t incoming_fty,
0 commit comments