about summary refs log tree commit diff
path: root/tests/codegen/enum/enum-two-variants-match.rs
blob: 12d9edc4d6234331e561d2ff71a75624cb32040c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
//@ compile-flags: -Copt-level=3 -C no-prepopulate-passes
//@ only-64bit (because these discriminants are isize)

#![crate_type = "lib"]

// This directly tests what we emit for these matches, rather than what happens
// after optimization, so it doesn't need to worry about extra flags on the
// instructions and is less susceptible to being broken on LLVM updates.

// CHECK-LABEL: @option_match
#[no_mangle]
pub fn option_match(x: Option<i32>) -> u16 {
    // CHECK-NOT: %x = alloca
    // CHECK: %[[OUT:.+]] = alloca [2 x i8]
    // CHECK-NOT: %x = alloca

    // CHECK: %[[DISCR:.+]] = zext i32 %x.0 to i64
    // CHECK: %[[COND:.+]] = trunc nuw i64 %[[DISCR]] to i1
    // CHECK: br i1 %[[COND]], label %[[TRUE:[a-z0-9]+]], label %[[FALSE:[a-z0-9]+]]

    // CHECK: [[TRUE]]:
    // CHECK: store i16 13, ptr %[[OUT]]

    // CHECK: [[FALSE]]:
    // CHECK: store i16 42, ptr %[[OUT]]

    // CHECK: %[[RET:.+]] = load i16, ptr %[[OUT]]
    // CHECK: ret i16 %[[RET]]
    match x {
        Some(_) => 13,
        None => 42,
    }
}

// CHECK-LABEL: @result_match
#[no_mangle]
pub fn result_match(x: Result<u64, i64>) -> u16 {
    // CHECK-NOT: %x = alloca
    // CHECK: %[[OUT:.+]] = alloca [2 x i8]
    // CHECK-NOT: %x = alloca

    // CHECK: %[[COND:.+]] = trunc nuw i64 %x.0 to i1
    // CHECK: br i1 %[[COND]], label %[[TRUE:[a-z0-9]+]], label %[[FALSE:[a-z0-9]+]]

    // CHECK: [[TRUE]]:
    // CHECK: store i16 13, ptr %[[OUT]]

    // CHECK: [[FALSE]]:
    // CHECK: store i16 42, ptr %[[OUT]]

    // CHECK: %[[RET:.+]] = load i16, ptr %[[OUT]]
    // CHECK: ret i16 %[[RET]]
    match x {
        Err(_) => 13,
        Ok(_) => 42,
    }
}

// CHECK-LABEL: @option_bool_match(
#[no_mangle]
pub fn option_bool_match(x: Option<bool>) -> char {
    // CHECK: %[[RAW:.+]] = load i8, ptr %x
    // CHECK: %[[IS_NONE:.+]] = icmp eq i8 %[[RAW]], 2
    // CHECK: %[[OPT_DISCR:.+]] = select i1 %[[IS_NONE]], i64 0, i64 1
    // CHECK: %[[OPT_DISCR_T:.+]] = trunc nuw i64 %[[OPT_DISCR]] to i1
    // CHECK: br i1 %[[OPT_DISCR_T]], label %[[BB_SOME:.+]], label %[[BB_NONE:.+]]

    // CHECK: [[BB_SOME]]:
    // CHECK: %[[FIELD:.+]] = load i8, ptr %x
    // CHECK: %[[FIELD_T:.+]] = trunc nuw i8 %[[FIELD]] to i1
    // CHECK: br i1 %[[FIELD_T]]
    match x {
        None => 'n',
        Some(false) => 'f',
        Some(true) => 't',
    }
}

use std::cmp::Ordering::{self, *};
// CHECK-LABEL: @option_ordering_match(
#[no_mangle]
pub fn option_ordering_match(x: Option<Ordering>) -> char {
    // CHECK: %[[RAW:.+]] = load i8, ptr %x
    // CHECK: %[[IS_NONE:.+]] = icmp eq i8 %[[RAW]], 2
    // CHECK: %[[OPT_DISCR:.+]] = select i1 %[[IS_NONE]], i64 0, i64 1
    // CHECK: %[[OPT_DISCR_T:.+]] = trunc nuw i64 %[[OPT_DISCR]] to i1
    // CHECK: br i1 %[[OPT_DISCR_T]], label %[[BB_SOME:.+]], label %[[BB_NONE:.+]]

    // CHECK: [[BB_SOME]]:
    // CHECK: %[[FIELD:.+]] = load i8, ptr %x
    // CHECK: switch i8 %[[FIELD]], label %[[UNREACHABLE:.+]] [
    // CHECK-NEXT: i8 -1, label
    // CHECK-NEXT: i8 0, label
    // CHECK-NEXT: i8 1, label
    // CHECK-NEXT: ]

    // CHECK: [[UNREACHABLE]]:
    // CHECK-NEXT: unreachable
    match x {
        None => '?',
        Some(Less) => '<',
        Some(Equal) => '=',
        Some(Greater) => '>',
    }
}

// CHECK-LABEL: @option_nonzero_match(
#[no_mangle]
pub fn option_nonzero_match(x: Option<std::num::NonZero<u16>>) -> u16 {
    // CHECK: %[[OUT:.+]] = alloca [2 x i8]

    // CHECK: %[[IS_NONE:.+]] = icmp eq i16 %x, 0
    // CHECK: %[[OPT_DISCR:.+]] = select i1 %[[IS_NONE]], i64 0, i64 1
    // CHECK: %[[OPT_DISCR_T:.+]] = trunc nuw i64 %[[OPT_DISCR]] to i1
    // CHECK: br i1 %[[OPT_DISCR_T]], label %[[BB_SOME:.+]], label %[[BB_NONE:.+]]

    // CHECK: [[BB_SOME]]:
    // CHECK: store i16 987, ptr %[[OUT]]

    // CHECK: [[BB_NONE]]:
    // CHECK: store i16 123, ptr %[[OUT]]

    // CHECK: %[[RET:.+]] = load i16, ptr %[[OUT]]
    // CHECK: ret i16 %[[RET]]

    match x {
        None => 123,
        Some(_) => 987,
    }
}