about summary refs log tree commit diff
path: root/tests/codegen/enum
diff options
context:
space:
mode:
authorJubilee Young <workingjubilee@gmail.com>2023-07-29 17:07:57 -0700
committerJubilee Young <workingjubilee@gmail.com>2023-07-29 18:34:41 -0700
commit06711615aa5b3d45e77c1aa20df7de14ed16edf2 (patch)
tree4df501c658dc3b8e93cb434fdfc0f18514312907 /tests/codegen/enum
parent03a57254b56886c43464e23b74af484d11374623 (diff)
downloadrust-06711615aa5b3d45e77c1aa20df7de14ed16edf2.tar.gz
rust-06711615aa5b3d45e77c1aa20df7de14ed16edf2.zip
tests/codegen/enum-* -> enum/enum-*
Diffstat (limited to 'tests/codegen/enum')
-rw-r--r--tests/codegen/enum/enum-bounds-check-derived-idx.rs24
-rw-r--r--tests/codegen/enum/enum-bounds-check-issue-13926.rs18
-rw-r--r--tests/codegen/enum/enum-bounds-check-issue-82871.rs18
-rw-r--r--tests/codegen/enum/enum-bounds-check.rs26
-rw-r--r--tests/codegen/enum/enum-debug-clike.rs23
-rw-r--r--tests/codegen/enum/enum-debug-niche-2.rs50
-rw-r--r--tests/codegen/enum/enum-debug-niche.rs29
-rw-r--r--tests/codegen/enum/enum-debug-tagged.rs27
-rw-r--r--tests/codegen/enum/enum-discriminant-value.rs27
-rw-r--r--tests/codegen/enum/enum-match.rs112
-rw-r--r--tests/codegen/enum/enum-u128.rs27
11 files changed, 381 insertions, 0 deletions
diff --git a/tests/codegen/enum/enum-bounds-check-derived-idx.rs b/tests/codegen/enum/enum-bounds-check-derived-idx.rs
new file mode 100644
index 00000000000..aa66c2ed08e
--- /dev/null
+++ b/tests/codegen/enum/enum-bounds-check-derived-idx.rs
@@ -0,0 +1,24 @@
+// This test checks an optimization that is not guaranteed to work. This test case should not block
+// a future LLVM update.
+// compile-flags: -O
+
+#![crate_type = "lib"]
+
+pub enum Bar {
+    A = 1,
+    B = 3,
+}
+
+// CHECK-LABEL: @lookup_inc
+#[no_mangle]
+pub fn lookup_inc(buf: &[u8; 5], f: Bar) -> u8 {
+    // CHECK-NOT: panic_bounds_check
+    buf[f as usize + 1]
+}
+
+// CHECK-LABEL: @lookup_dec
+#[no_mangle]
+pub fn lookup_dec(buf: &[u8; 5], f: Bar) -> u8 {
+    // CHECK-NOT: panic_bounds_check
+    buf[f as usize - 1]
+}
diff --git a/tests/codegen/enum/enum-bounds-check-issue-13926.rs b/tests/codegen/enum/enum-bounds-check-issue-13926.rs
new file mode 100644
index 00000000000..b26945bc549
--- /dev/null
+++ b/tests/codegen/enum/enum-bounds-check-issue-13926.rs
@@ -0,0 +1,18 @@
+// This test checks an optimization that is not guaranteed to work. This test case should not block
+// a future LLVM update.
+// compile-flags: -O
+
+#![crate_type = "lib"]
+
+#[repr(u8)]
+pub enum Exception {
+    Low = 5,
+    High = 10,
+}
+
+// CHECK-LABEL: @access
+#[no_mangle]
+pub fn access(array: &[usize; 12], exc: Exception) -> usize {
+    // CHECK-NOT: panic_bounds_check
+    array[(exc as u8 - 4) as usize]
+}
diff --git a/tests/codegen/enum/enum-bounds-check-issue-82871.rs b/tests/codegen/enum/enum-bounds-check-issue-82871.rs
new file mode 100644
index 00000000000..32fdc4a5f4f
--- /dev/null
+++ b/tests/codegen/enum/enum-bounds-check-issue-82871.rs
@@ -0,0 +1,18 @@
+// compile-flags: -C opt-level=0
+
+#![crate_type = "lib"]
+
+#[repr(C)]
+pub enum E {
+    A,
+}
+
+// CHECK-LABEL: @index
+#[no_mangle]
+pub fn index(x: &[u32; 3], ind: E) -> u32 {
+    // Canary: we should be able to optimize out the bounds check, but we need
+    // to track the range of the discriminant result in order to be able to do that.
+    // oli-obk tried to add that, but that caused miscompilations all over the place.
+    // CHECK: panic_bounds_check
+    x[ind as usize]
+}
diff --git a/tests/codegen/enum/enum-bounds-check.rs b/tests/codegen/enum/enum-bounds-check.rs
new file mode 100644
index 00000000000..17322d5911b
--- /dev/null
+++ b/tests/codegen/enum/enum-bounds-check.rs
@@ -0,0 +1,26 @@
+// compile-flags: -O
+
+#![crate_type = "lib"]
+
+pub enum Foo {
+    A, B
+}
+
+// CHECK-LABEL: @lookup
+#[no_mangle]
+pub fn lookup(buf: &[u8; 2], f: Foo) -> u8 {
+    // CHECK-NOT: panic_bounds_check
+    buf[f as usize]
+}
+
+pub enum Bar {
+    A = 2,
+    B = 3
+}
+
+// CHECK-LABEL: @lookup_unmodified
+#[no_mangle]
+pub fn lookup_unmodified(buf: &[u8; 5], f: Bar) -> u8 {
+    // CHECK-NOT: panic_bounds_check
+    buf[f as usize]
+}
diff --git a/tests/codegen/enum/enum-debug-clike.rs b/tests/codegen/enum/enum-debug-clike.rs
new file mode 100644
index 00000000000..1e369a2c4e6
--- /dev/null
+++ b/tests/codegen/enum/enum-debug-clike.rs
@@ -0,0 +1,23 @@
+// This tests that debug info for "c-like" enums is properly emitted.
+// This is ignored for the fallback mode on MSVC due to problems with PDB.
+
+//
+// ignore-msvc
+
+// compile-flags: -g -C no-prepopulate-passes
+
+// CHECK-LABEL: @main
+// CHECK: {{.*}}DICompositeType{{.*}}tag: DW_TAG_enumeration_type,{{.*}}name: "E",{{.*}}flags: DIFlagEnumClass,{{.*}}
+// CHECK: {{.*}}DIEnumerator{{.*}}name: "A",{{.*}}value: {{[0-9].*}}
+// CHECK: {{.*}}DIEnumerator{{.*}}name: "B",{{.*}}value: {{[0-9].*}}
+// CHECK: {{.*}}DIEnumerator{{.*}}name: "C",{{.*}}value: {{[0-9].*}}
+
+#![allow(dead_code)]
+#![allow(unused_variables)]
+#![allow(unused_assignments)]
+
+enum E { A, B, C }
+
+pub fn main() {
+    let e = E::C;
+}
diff --git a/tests/codegen/enum/enum-debug-niche-2.rs b/tests/codegen/enum/enum-debug-niche-2.rs
new file mode 100644
index 00000000000..4b607d50574
--- /dev/null
+++ b/tests/codegen/enum/enum-debug-niche-2.rs
@@ -0,0 +1,50 @@
+// This tests that optimized enum debug info accurately reflects the enum layout.
+// This is ignored for the fallback mode on MSVC due to problems with PDB.
+
+//
+// ignore-msvc
+
+// compile-flags: -g -C no-prepopulate-passes
+
+// CHECK: {{.*}}DICompositeType{{.*}}tag: DW_TAG_variant_part,{{.*}}size: 32,{{.*}}
+// CHECK: {{.*}}DIDerivedType{{.*}}tag: DW_TAG_member,{{.*}}name: "Placeholder",{{.*}}extraData: i128 4294967295{{[,)].*}}
+// CHECK: {{.*}}DIDerivedType{{.*}}tag: DW_TAG_member,{{.*}}name: "Error",{{.*}}extraData: i128 0{{[,)].*}}
+
+#![feature(never_type)]
+
+#[derive(Copy, Clone)]
+pub struct Entity {
+    private: std::num::NonZeroU32,
+}
+
+#[derive(Copy, Clone, PartialEq, Eq)]
+pub struct Declaration;
+
+impl TypeFamily for Declaration {
+    type Base = Base;
+    type Placeholder = !;
+
+    fn intern_base_data(_: BaseKind<Self>) {}
+}
+
+#[derive(Copy, Clone)]
+pub struct Base;
+
+pub trait TypeFamily: Copy + 'static {
+    type Base: Copy;
+    type Placeholder: Copy;
+
+    fn intern_base_data(_: BaseKind<Self>);
+}
+
+#[derive(Copy, Clone)]
+pub enum BaseKind<F: TypeFamily> {
+    Named(Entity),
+    Placeholder(F::Placeholder),
+    Error,
+}
+
+pub fn main() {
+    let x = BaseKind::Error::<Declaration>;
+    let y = 7;
+}
diff --git a/tests/codegen/enum/enum-debug-niche.rs b/tests/codegen/enum/enum-debug-niche.rs
new file mode 100644
index 00000000000..b718a6854dd
--- /dev/null
+++ b/tests/codegen/enum/enum-debug-niche.rs
@@ -0,0 +1,29 @@
+// This tests that optimized enum debug info accurately reflects the enum layout.
+// This is ignored for the fallback mode on MSVC due to problems with PDB.
+
+// ignore-msvc
+
+// compile-flags: -g -C no-prepopulate-passes
+
+// CHECK-LABEL: @main
+// CHECK: {{.*}}DICompositeType{{.*}}tag: DW_TAG_variant_part,{{.*}}discriminator:{{.*}}
+// CHECK: {{.*}}DIDerivedType{{.*}}tag: DW_TAG_member,{{.*}}name: "A",{{.*}}extraData:{{.*}}
+// CHECK: {{.*}}DICompositeType{{.*}}tag: DW_TAG_structure_type,{{.*}}name: "A",{{.*}}
+// CHECK: {{.*}}DIDerivedType{{.*}}tag: DW_TAG_member,{{.*}}name: "B",{{.*}}extraData:{{.*}}
+// CHECK: {{.*}}DICompositeType{{.*}}tag: DW_TAG_structure_type,{{.*}}name: "B",{{.*}}
+// CHECK: {{.*}}DIDerivedType{{.*}}tag: DW_TAG_member,{{.*}}name: "C",{{.*}}extraData:{{.*}}
+// CHECK: {{.*}}DICompositeType{{.*}}tag: DW_TAG_structure_type,{{.*}}name: "C",{{.*}}
+// CHECK-NOT: {{.*}}DIDerivedType{{.*}}name: "D",{{.*}}extraData:{{.*}}
+// CHECK: {{.*}}DIDerivedType{{.*}}tag: DW_TAG_member,{{.*}}name: "D",{{.*}}
+// CHECK: {{.*}}DICompositeType{{.*}}tag: DW_TAG_structure_type,{{.*}}name: "D",{{.*}}
+// CHECK: {{.*}}DIDerivedType{{.*}}tag: DW_TAG_member,{{.*}}flags: DIFlagArtificial{{.*}}
+
+#![allow(dead_code)]
+#![allow(unused_variables)]
+#![allow(unused_assignments)]
+
+enum E { A, B, C, D(bool) }
+
+pub fn main() {
+    let e = E::D(true);
+}
diff --git a/tests/codegen/enum/enum-debug-tagged.rs b/tests/codegen/enum/enum-debug-tagged.rs
new file mode 100644
index 00000000000..095c49ac3ac
--- /dev/null
+++ b/tests/codegen/enum/enum-debug-tagged.rs
@@ -0,0 +1,27 @@
+// This tests that debug info for tagged (ordinary) enums is properly emitted.
+// This is ignored for the fallback mode on MSVC due to problems with PDB.
+
+// ignore-msvc
+
+// compile-flags: -g -C no-prepopulate-passes
+
+// CHECK-LABEL: @main
+// CHECK: {{.*}}DICompositeType{{.*}}tag: DW_TAG_structure_type,{{.*}}name: "E",{{.*}}
+// CHECK: {{.*}}DICompositeType{{.*}}tag: DW_TAG_variant_part,{{.*}}discriminator:{{.*}}
+// CHECK: {{.*}}DIDerivedType{{.*}}tag: DW_TAG_member,{{.*}}name: "A",{{.*}}extraData:{{.*}}
+// CHECK: {{.*}}DICompositeType{{.*}}tag: DW_TAG_structure_type,{{.*}}name: "A",{{.*}}
+// CHECK: {{.*}}DIDerivedType{{.*}}tag: DW_TAG_member,{{.*}}name: "__0",{{.*}}
+// CHECK: {{.*}}DIDerivedType{{.*}}tag: DW_TAG_member,{{.*}}name: "B",{{.*}}extraData:{{.*}}
+// CHECK: {{.*}}DICompositeType{{.*}}tag: DW_TAG_structure_type,{{.*}}name: "B",{{.*}}
+// CHECK: {{.*}}DIDerivedType{{.*}}tag: DW_TAG_member,{{.*}}name: "__0",{{.*}}
+// CHECK: {{.*}}DIDerivedType{{.*}}tag: DW_TAG_member,{{.*}}flags: DIFlagArtificial{{.*}}
+
+#![allow(dead_code)]
+#![allow(unused_variables)]
+#![allow(unused_assignments)]
+
+enum E { A(u32), B(u32) }
+
+pub fn main() {
+    let e = E::A(23);
+}
diff --git a/tests/codegen/enum/enum-discriminant-value.rs b/tests/codegen/enum/enum-discriminant-value.rs
new file mode 100644
index 00000000000..cc14c212002
--- /dev/null
+++ b/tests/codegen/enum/enum-discriminant-value.rs
@@ -0,0 +1,27 @@
+// Verify that DIEnumerator uses isUnsigned flag when appropriate.
+//
+// compile-flags: -g -C no-prepopulate-passes
+
+#[repr(i64)]
+pub enum I64 {
+    I64Min = i64::MIN,
+    I64Max = i64::MAX,
+}
+
+#[repr(u64)]
+pub enum U64 {
+    U64Min = u64::MIN,
+    U64Max = u64::MAX,
+}
+
+fn main() {
+    let _a = I64::I64Min;
+    let _b = I64::I64Max;
+    let _c = U64::U64Min;
+    let _d = U64::U64Max;
+}
+
+// CHECK: !DIEnumerator(name: "I64Min", value: -9223372036854775808)
+// CHECK: !DIEnumerator(name: "I64Max", value: 9223372036854775807)
+// CHECK: !DIEnumerator(name: "U64Min", value: 0, isUnsigned: true)
+// CHECK: !DIEnumerator(name: "U64Max", value: 18446744073709551615, isUnsigned: true)
diff --git a/tests/codegen/enum/enum-match.rs b/tests/codegen/enum/enum-match.rs
new file mode 100644
index 00000000000..5548cd25147
--- /dev/null
+++ b/tests/codegen/enum/enum-match.rs
@@ -0,0 +1,112 @@
+// compile-flags: -Copt-level=1
+// only-x86_64
+
+#![crate_type = "lib"]
+
+// Check each of the 3 cases for `codegen_get_discr`.
+
+// Case 0: One tagged variant.
+pub enum Enum0 {
+    A(bool),
+    B,
+}
+
+// CHECK: define noundef i8 @match0{{.*}}
+// CHECK-NEXT: start:
+// CHECK-NEXT: %1 = icmp eq i8 %0, 2
+// CHECK-NEXT: %2 = and i8 %0, 1
+// CHECK-NEXT: %_0.0 = select i1 %1, i8 13, i8 %2
+#[no_mangle]
+pub fn match0(e: Enum0) -> u8 {
+    use Enum0::*;
+    match e {
+        A(b) => b as u8,
+        B => 13,
+    }
+}
+
+// Case 1: Niche values are on a boundary for `range`.
+pub enum Enum1 {
+    A(bool),
+    B,
+    C,
+}
+
+// CHECK: define noundef i8 @match1{{.*}}
+// CHECK-NEXT: start:
+// CHECK-NEXT: %1 = add i8 %0, -2
+// CHECK-NEXT: %2 = zext i8 %1 to i64
+// CHECK-NEXT: %3 = icmp ult i8 %1, 2
+// CHECK-NEXT: %4 = add nuw nsw i64 %2, 1
+// CHECK-NEXT: %_2 = select i1 %3, i64 %4, i64 0
+#[no_mangle]
+pub fn match1(e: Enum1) -> u8 {
+    use Enum1::*;
+    match e {
+        A(b) => b as u8,
+        B => 13,
+        C => 100,
+    }
+}
+
+// Case 2: Special cases don't apply.
+pub enum X {
+    _2=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, _131, _132, _133,
+    _134, _135, _136, _137, _138, _139, _140, _141,
+    _142, _143, _144, _145, _146, _147, _148, _149,
+    _150, _151, _152, _153, _154, _155, _156, _157,
+    _158, _159, _160, _161, _162, _163, _164, _165,
+    _166, _167, _168, _169, _170, _171, _172, _173,
+    _174, _175, _176, _177, _178, _179, _180, _181,
+    _182, _183, _184, _185, _186, _187, _188, _189,
+    _190, _191, _192, _193, _194, _195, _196, _197,
+    _198, _199, _200, _201, _202, _203, _204, _205,
+    _206, _207, _208, _209, _210, _211, _212, _213,
+    _214, _215, _216, _217, _218, _219, _220, _221,
+    _222, _223, _224, _225, _226, _227, _228, _229,
+    _230, _231, _232, _233, _234, _235, _236, _237,
+    _238, _239, _240, _241, _242, _243, _244, _245,
+    _246, _247, _248, _249, _250, _251, _252, _253,
+}
+
+pub enum Enum2 {
+    A(X),
+    B,
+    C,
+    D,
+    E,
+}
+
+// CHECK: define noundef i8 @match2{{.*}}
+// CHECK-NEXT: start:
+// CHECK-NEXT: %1 = add i8 %0, 2
+// CHECK-NEXT: %2 = zext i8 %1 to i64
+// CHECK-NEXT: %3 = icmp ult i8 %1, 4
+// CHECK-NEXT: %4 = add nuw nsw i64 %2, 1
+// CHECK-NEXT: %_2 = select i1 %3, i64 %4, i64 0
+// CHECK-NEXT: switch i64 %_2, label {{.*}} [
+#[no_mangle]
+pub fn match2(e: Enum2) -> u8 {
+    use Enum2::*;
+    match e {
+        A(b) => b as u8,
+        B => 13,
+        C => 100,
+        D => 200,
+        E => 250,
+    }
+}
diff --git a/tests/codegen/enum/enum-u128.rs b/tests/codegen/enum/enum-u128.rs
new file mode 100644
index 00000000000..f50d360ac9f
--- /dev/null
+++ b/tests/codegen/enum/enum-u128.rs
@@ -0,0 +1,27 @@
+// This tests that debug info for "c-like" 128bit enums is properly emitted.
+// This is ignored for the fallback mode on MSVC due to problems with PDB.
+
+//
+// ignore-msvc
+
+// compile-flags: -g -C no-prepopulate-passes
+
+// CHECK-LABEL: @main
+// CHECK: {{.*}}DICompositeType{{.*}}tag: DW_TAG_enumeration_type,{{.*}}name: "Foo",{{.*}}flags: DIFlagEnumClass,{{.*}}
+// CHECK: {{.*}}DIEnumerator{{.*}}name: "Lo",{{.*}}value: 0,{{.*}}
+// CHECK: {{.*}}DIEnumerator{{.*}}name: "Hi",{{.*}}value: 18446744073709551616,{{.*}}
+// CHECK: {{.*}}DIEnumerator{{.*}}name: "Bar",{{.*}}value: 18446745000000000123,{{.*}}
+
+#![allow(incomplete_features)]
+#![feature(repr128)]
+
+#[repr(u128)]
+pub enum Foo {
+    Lo,
+    Hi = 1 << 64,
+    Bar = 18_446_745_000_000_000_123,
+}
+
+pub fn main() {
+    let foo = Foo::Bar;
+}