@@ -2410,11 +2410,11 @@ fn make_cmp_glue(&@block_ctxt cx,
2410
2410
2411
2411
// If we hit == all the way through the minimum-shared-length
2412
2412
// section, default to judging the relative sequence lengths.
2413
- r = compare_integral_values ( scx,
2414
- vec_fill ( scx, lhs) ,
2415
- vec_fill ( scx, rhs) ,
2416
- false ,
2417
- llop) ;
2413
+ r = compare_numerical_values ( scx,
2414
+ vec_fill ( scx, lhs) ,
2415
+ vec_fill ( scx, rhs) ,
2416
+ unsigned_int ,
2417
+ llop) ;
2418
2418
r. bcx . build . Store ( r. val , flag) ;
2419
2419
2420
2420
} else {
@@ -2500,88 +2500,111 @@ fn make_cmp_glue(&@block_ctxt cx,
2500
2500
}
2501
2501
}
2502
2502
2503
+ // Used only for creating scalar comparsion glue.
2504
+ tag numerical_type {
2505
+ signed_int;
2506
+ unsigned_int;
2507
+ floating_point;
2508
+ }
2509
+
2503
2510
// A helper function to create scalar comparison glue.
2504
2511
fn make_scalar_cmp_glue ( & @block_ctxt cx , ValueRef lhs, ValueRef rhs,
2505
2512
& ty:: t t, ValueRef llop) {
2506
- if ( ty:: type_is_fp ( cx. fcx . lcx . ccx . tcx , t) ) {
2507
- make_fp_cmp_glue ( cx, lhs, rhs, t, llop) ;
2508
- ret;
2509
- }
2513
+ // assert ty::type_is_scalar(cx.fcx.lcx.ccx.tcx, t);
2510
2514
2511
- if ( ty:: type_is_integral ( cx. fcx . lcx . ccx . tcx , t) ||
2512
- ty:: type_is_bool ( cx. fcx . lcx . ccx . tcx , t) ) {
2513
- make_integral_cmp_glue ( cx, lhs, rhs, t, llop) ;
2514
- ret;
2515
- }
2515
+ // In most cases, we need to know whether to do signed, unsigned, or float
2516
+ // comparison.
2517
+ auto f = bind make_numerical_cmp_glue ( cx, lhs, rhs, _, llop) ;
2516
2518
2517
- if ( ty:: type_is_nil ( cx. fcx . lcx . ccx . tcx , t) ) {
2518
- cx. build . Store ( C_bool ( true ) , cx. fcx . llretptr ) ;
2519
- cx. build . RetVoid ( ) ;
2520
- ret;
2519
+ // FIXME: this could be a lot shorter if we could combine multiple cases
2520
+ // of alt expressions (issue #449).
2521
+ alt ( ty:: struct ( cx. fcx . lcx . ccx . tcx , t) ) {
2522
+ case ( ty:: ty_nil) {
2523
+ cx. build . Store ( C_bool ( true ) , cx. fcx . llretptr ) ;
2524
+ cx. build . RetVoid ( ) ;
2525
+ }
2526
+ case ( ty:: ty_bool) { f ( unsigned_int) ; }
2527
+ case ( ty:: ty_int) { f ( signed_int) ; }
2528
+ case ( ty:: ty_float) { f ( floating_point) ; }
2529
+ case ( ty:: ty_uint) { f ( unsigned_int) ; }
2530
+ case ( ty:: ty_machine ( _) ) {
2531
+ // Floating point machine types
2532
+ if ( ty:: type_is_fp ( cx. fcx . lcx . ccx . tcx , t) ) {
2533
+ f ( floating_point) ;
2534
+ }
2535
+ // Signed, integral machine types
2536
+ else if ( ty:: type_is_signed ( cx. fcx . lcx . ccx . tcx , t) ) {
2537
+ f ( signed_int) ;
2538
+ }
2539
+ // Unsigned, integral machine types
2540
+ else { f ( unsigned_int) ; }
2541
+ }
2542
+ case ( ty:: ty_char) { f ( unsigned_int) ; }
2543
+ case ( ty:: ty_type) {
2544
+ trans_fail ( cx, none[ common:: span] ,
2545
+ "attempt to compare values of type type" ) ;
2546
+ }
2547
+ case ( ty:: ty_native) {
2548
+ trans_fail ( cx, none[ common:: span] ,
2549
+ "attempt to compare values of type native" ) ;
2550
+ }
2551
+ case ( _) {
2552
+ // Should never get here, because t is scalar.
2553
+ fail;
2554
+ }
2521
2555
}
2522
-
2523
- trans_fail ( cx, none[ common:: span] ,
2524
- "attempt to compare values of type " +
2525
- ty:: ty_to_str ( cx. fcx . lcx . ccx . tcx , t) ) ;
2526
2556
}
2527
2557
2528
- // A helper function to create floating point comparison glue.
2529
- fn make_fp_cmp_glue ( & @block_ctxt cx , ValueRef lhs, ValueRef rhs,
2530
- & ty:: t fptype , ValueRef llop) {
2531
- auto last_cx = new_sub_block_ctxt ( cx, "last" ) ;
2532
-
2533
- auto eq_cx = new_sub_block_ctxt ( cx, "eq" ) ;
2534
- auto eq_result = eq_cx. build . FCmp ( lib:: llvm:: LLVMRealUEQ , lhs, rhs) ;
2535
- eq_cx. build . Br ( last_cx. llbb ) ;
2536
-
2537
- auto lt_cx = new_sub_block_ctxt ( cx, "lt" ) ;
2538
- auto lt_result = lt_cx. build . FCmp ( lib:: llvm:: LLVMRealULT , lhs, rhs) ;
2539
- lt_cx. build . Br ( last_cx. llbb ) ;
2540
-
2541
- auto le_cx = new_sub_block_ctxt ( cx, "le" ) ;
2542
- auto le_result = le_cx. build . FCmp ( lib:: llvm:: LLVMRealULE , lhs, rhs) ;
2543
- le_cx. build . Br ( last_cx. llbb ) ;
2544
-
2545
- auto unreach_cx = new_sub_block_ctxt ( cx, "unreach" ) ;
2546
- unreach_cx. build . Unreachable ( ) ;
2547
-
2548
- auto llswitch = cx. build . Switch ( llop, unreach_cx. llbb , 3 u) ;
2549
- llvm:: LLVMAddCase ( llswitch, C_u8 ( abi:: cmp_glue_op_eq) , eq_cx. llbb ) ;
2550
- llvm:: LLVMAddCase ( llswitch, C_u8 ( abi:: cmp_glue_op_lt) , lt_cx. llbb ) ;
2551
- llvm:: LLVMAddCase ( llswitch, C_u8 ( abi:: cmp_glue_op_le) , le_cx. llbb ) ;
2552
-
2553
- auto last_result =
2554
- last_cx. build . Phi ( T_i1 ( ) , [ eq_result, lt_result, le_result] ,
2555
- [ eq_cx. llbb , lt_cx. llbb , le_cx. llbb ] ) ;
2556
- last_cx. build . Store ( last_result, cx. fcx . llretptr ) ;
2557
- last_cx. build . RetVoid ( ) ;
2558
- }
2559
-
2560
- // A helper function to compare integral values. This is used by both
2561
- // `make_integral_cmp_glue` and `make_cmp_glue`.
2562
- fn compare_integral_values ( & @block_ctxt cx , ValueRef lhs, ValueRef rhs,
2563
- bool signed , ValueRef llop) -> result {
2564
- auto lt_cmp; auto le_cmp;
2565
- if ( signed) {
2566
- lt_cmp = lib:: llvm:: LLVMIntSLT ;
2567
- le_cmp = lib:: llvm:: LLVMIntSLE ;
2568
- } else {
2569
- lt_cmp = lib:: llvm:: LLVMIntULT ;
2570
- le_cmp = lib:: llvm:: LLVMIntULE ;
2558
+ // A helper function to compare numerical values.
2559
+ fn compare_numerical_values ( & @block_ctxt cx , ValueRef lhs, ValueRef rhs,
2560
+ numerical_type nt, ValueRef llop) -> result {
2561
+ auto eq_cmp; auto lt_cmp; auto le_cmp;
2562
+ alt ( nt) {
2563
+ case ( floating_point) {
2564
+ eq_cmp = lib:: llvm:: LLVMRealUEQ ;
2565
+ lt_cmp = lib:: llvm:: LLVMRealULT ;
2566
+ le_cmp = lib:: llvm:: LLVMRealULE ;
2567
+ }
2568
+ case ( signed_int) {
2569
+ eq_cmp = lib:: llvm:: LLVMIntEQ ;
2570
+ lt_cmp = lib:: llvm:: LLVMIntSLT ;
2571
+ le_cmp = lib:: llvm:: LLVMIntSLE ;
2572
+ }
2573
+ case ( unsigned_int) {
2574
+ eq_cmp = lib:: llvm:: LLVMIntEQ ;
2575
+ lt_cmp = lib:: llvm:: LLVMIntULT ;
2576
+ le_cmp = lib:: llvm:: LLVMIntULE ;
2577
+ }
2578
+ }
2579
+
2580
+ // FIXME: This wouldn't be necessary if we could bind methods off of
2581
+ // objects and therefore abstract over FCmp and ICmp (issue #435). Then
2582
+ // we could just write, e.g., "cmp_fn = bind cx.build.FCmp(_, _, _);" in
2583
+ // the above, and "auto eq_result = cmp_fn(eq_cmp, lhs, rhs);" in the
2584
+ // below.
2585
+ fn generic_cmp ( & @block_ctxt cx , numerical_type nt,
2586
+ uint op, ValueRef lhs, ValueRef rhs) -> ValueRef {
2587
+ let ValueRef r;
2588
+ if ( nt == floating_point) {
2589
+ r = cx. build . FCmp ( op, lhs, rhs) ;
2590
+ } else {
2591
+ r = cx. build . ICmp ( op, lhs, rhs) ;
2592
+ }
2593
+ ret r;
2571
2594
}
2572
2595
2573
2596
auto last_cx = new_sub_block_ctxt ( cx, "last" ) ;
2574
2597
2575
2598
auto eq_cx = new_sub_block_ctxt ( cx, "eq" ) ;
2576
- auto eq_result = eq_cx . build . ICmp ( lib :: llvm :: LLVMIntEQ , lhs, rhs) ;
2599
+ auto eq_result = generic_cmp ( eq_cx , nt , eq_cmp , lhs, rhs) ;
2577
2600
eq_cx. build . Br ( last_cx. llbb ) ;
2578
2601
2579
2602
auto lt_cx = new_sub_block_ctxt ( cx, "lt" ) ;
2580
- auto lt_result = lt_cx . build . ICmp ( lt_cmp, lhs, rhs) ;
2603
+ auto lt_result = generic_cmp ( lt_cx , nt , lt_cmp, lhs, rhs) ;
2581
2604
lt_cx. build . Br ( last_cx. llbb ) ;
2582
2605
2583
2606
auto le_cx = new_sub_block_ctxt ( cx, "le" ) ;
2584
- auto le_result = le_cx . build . ICmp ( le_cmp, lhs, rhs) ;
2607
+ auto le_result = generic_cmp ( le_cx , nt , le_cmp, lhs, rhs) ;
2585
2608
le_cx. build . Br ( last_cx. llbb ) ;
2586
2609
2587
2610
auto unreach_cx = new_sub_block_ctxt ( cx, "unreach" ) ;
@@ -2598,11 +2621,10 @@ fn compare_integral_values(&@block_ctxt cx, ValueRef lhs, ValueRef rhs,
2598
2621
ret res( last_cx, last_result) ;
2599
2622
}
2600
2623
2601
- // A helper function to create integral comparison glue.
2602
- fn make_integral_cmp_glue ( & @block_ctxt cx , ValueRef lhs, ValueRef rhs,
2603
- & ty:: t intype , ValueRef llop) {
2604
- auto r = compare_integral_values ( cx, lhs, rhs,
2605
- ty:: type_is_signed ( cx. fcx . lcx . ccx . tcx , intype) , llop) ;
2624
+ // A helper function to create numerical comparison glue.
2625
+ fn make_numerical_cmp_glue ( & @block_ctxt cx , ValueRef lhs, ValueRef rhs,
2626
+ numerical_type nt, ValueRef llop) {
2627
+ auto r = compare_numerical_values ( cx, lhs, rhs, nt, llop) ;
2606
2628
r. bcx . build . Store ( r. val , r. bcx . fcx . llretptr ) ;
2607
2629
r. bcx . build . RetVoid ( ) ;
2608
2630
}
0 commit comments