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