summaryrefslogtreecommitdiffstats
path: root/tests/codegen/enum
diff options
context:
space:
mode:
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 000000000..aa66c2ed0
--- /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 000000000..b26945bc5
--- /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 000000000..32fdc4a5f
--- /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 000000000..17322d591
--- /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 000000000..1e369a2c4
--- /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 000000000..4b607d505
--- /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 000000000..b718a6854
--- /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 000000000..095c49ac3
--- /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 000000000..cc14c2120
--- /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 000000000..5548cd251
--- /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 000000000..f50d360ac
--- /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;
+}