[llvm] 059d1f8 - [DebugInfo] Correctly recognize bitfields when emitting dwarf

Jeremy Morse via llvm-commits llvm-commits at lists.llvm.org
Mon Apr 4 03:14:38 PDT 2022


Author: Jeremy Morse
Date: 2022-04-04T11:14:13+01:00
New Revision: 059d1f84d2d59093300a81c246de81b1c1da767b

URL: https://github.com/llvm/llvm-project/commit/059d1f84d2d59093300a81c246de81b1c1da767b
DIFF: https://github.com/llvm/llvm-project/commit/059d1f84d2d59093300a81c246de81b1c1da767b.diff

LOG: [DebugInfo] Correctly recognize bitfields when emitting dwarf

Use the "isBitfield" flag for debug types to determine whether something is
a bitfield, rather than trying to guess from it's layout. Fixes
https://bugs.llvm.org/show_bug.cgi?id=44601

Patch by: mahkoh

Differential Revision: https://reviews.llvm.org/D96334

Added: 
    llvm/test/DebugInfo/X86/packed_bitfields2.ll

Modified: 
    llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
    llvm/test/DebugInfo/AArch64/bitfields.ll
    llvm/test/DebugInfo/ARM/big-endian-bitfield.ll
    llvm/test/DebugInfo/ARM/bitfield.ll
    llvm/test/DebugInfo/X86/bitfields-dwarf4.ll
    llvm/test/DebugInfo/X86/bitfields.ll
    llvm/test/DebugInfo/X86/debug-info-packed-struct.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
index 1657c73f873bc..3026dac37181e 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
@@ -1621,7 +1621,7 @@ DIE &DwarfUnit::constructMemberDIE(DIE &Buffer, const DIDerivedType *DT) {
     uint32_t AlignInBytes = DT->getAlignInBytes();
     uint64_t OffsetInBytes;
 
-    bool IsBitfield = FieldSize && Size != FieldSize;
+    bool IsBitfield = DT->isBitField();
     if (IsBitfield) {
       // Handle bitfield, assume bytes are 8 bits.
       if (DD->useDWARF2Bitfields())

diff  --git a/llvm/test/DebugInfo/AArch64/bitfields.ll b/llvm/test/DebugInfo/AArch64/bitfields.ll
index a7363a5b28236..868ac330d4fca 100644
--- a/llvm/test/DebugInfo/AArch64/bitfields.ll
+++ b/llvm/test/DebugInfo/AArch64/bitfields.ll
@@ -24,6 +24,9 @@
 ; CHECK: DW_TAG_member
 ; CHECK-NEXT: DW_AT_name{{.*}}"b"
 ; CHECK-NOT: DW_TAG_member
+; CHECK:      DW_AT_byte_size  {{.*}} (0x04)
+; CHECK-NEXT: DW_AT_bit_size   {{.*}} (0x20)
+; CHECK-NEXT: DW_AT_bit_offset {{.*}} (0x00)
 ; CHECK:      DW_AT_data_member_location {{.*}} (DW_OP_plus_uconst 0x4)
 
 ; CHECK: DW_TAG_member
@@ -63,11 +66,11 @@ target triple = "aarch64_be--linux-gnu"
 !5 = !{!0}
 !6 = !DICompositeType(tag: DW_TAG_structure_type, name: "bitfield", file: !3, line: 1, size: 96, elements: !7)
 !7 = !{!8, !10, !11, !12}
-!8 = !DIDerivedType(tag: DW_TAG_member, name: "a", scope: !6, file: !3, line: 2, baseType: !9, size: 2)
+!8 = !DIDerivedType(tag: DW_TAG_member, name: "a", scope: !6, file: !3, line: 2, baseType: !9, size: 2, flags: DIFlagBitField)
 !9 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
-!10 = !DIDerivedType(tag: DW_TAG_member, name: "b", scope: !6, file: !3, line: 3, baseType: !9, size: 32, offset: 32)
-!11 = !DIDerivedType(tag: DW_TAG_member, name: "c", scope: !6, file: !3, line: 4, baseType: !9, size: 1, offset: 64)
-!12 = !DIDerivedType(tag: DW_TAG_member, name: "d", scope: !6, file: !3, line: 5, baseType: !9, size: 28, offset: 65)
+!10 = !DIDerivedType(tag: DW_TAG_member, name: "b", scope: !6, file: !3, line: 3, baseType: !9, size: 32, offset: 32, flags: DIFlagBitField)
+!11 = !DIDerivedType(tag: DW_TAG_member, name: "c", scope: !6, file: !3, line: 4, baseType: !9, size: 1, offset: 64, flags: DIFlagBitField)
+!12 = !DIDerivedType(tag: DW_TAG_member, name: "d", scope: !6, file: !3, line: 5, baseType: !9, size: 28, offset: 65, flags: DIFlagBitField)
 !13 = !{i32 2, !"Dwarf Version", i32 2}
 !14 = !{i32 2, !"Debug Info Version", i32 3}
 !15 = !{i32 1, !"PIC Level", i32 2}

diff  --git a/llvm/test/DebugInfo/ARM/big-endian-bitfield.ll b/llvm/test/DebugInfo/ARM/big-endian-bitfield.ll
index e175238d3bea9..168c88a5e480a 100644
--- a/llvm/test/DebugInfo/ARM/big-endian-bitfield.ll
+++ b/llvm/test/DebugInfo/ARM/big-endian-bitfield.ll
@@ -27,15 +27,15 @@ target datalayout = "E-m:e-p:32:32-i64:64-v128:64:128-n32-S64"
 !5 = !{!0}
 !6 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "S", file: !3, line: 1, size: 32, elements: !7)
 !7 = !{!8, !10, !11, !12}
-!8 = !DIDerivedType(tag: DW_TAG_member, name: "j", scope: !6, file: !3, line: 2, baseType: !9, size: 5)
+!8 = !DIDerivedType(tag: DW_TAG_member, name: "j", scope: !6, file: !3, line: 2, baseType: !9, size: 5, flags: DIFlagBitField)
 ; CHECK: DW_TAG_member
 ; CHECK-NEXT: DW_AT_name{{.*}}"j"
 ; CHECK-NOT:  DW_TAG
 ; CHECK:      DW_AT_data_bit_offset      [DW_FORM_data1]	(0x00)
 !9 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
-!10 = !DIDerivedType(tag: DW_TAG_member, name: "k", scope: !6, file: !3, line: 3, baseType: !9, size: 6, offset: 5)
-!11 = !DIDerivedType(tag: DW_TAG_member, name: "m", scope: !6, file: !3, line: 4, baseType: !9, size: 5, offset: 11)
-!12 = !DIDerivedType(tag: DW_TAG_member, name: "n", scope: !6, file: !3, line: 5, baseType: !9, size: 8, offset: 16)
+!10 = !DIDerivedType(tag: DW_TAG_member, name: "k", scope: !6, file: !3, line: 3, baseType: !9, size: 6, offset: 5, flags: DIFlagBitField)
+!11 = !DIDerivedType(tag: DW_TAG_member, name: "m", scope: !6, file: !3, line: 4, baseType: !9, size: 5, offset: 11, flags: DIFlagBitField)
+!12 = !DIDerivedType(tag: DW_TAG_member, name: "n", scope: !6, file: !3, line: 5, baseType: !9, size: 8, offset: 16, flags: DIFlagBitField)
 !13 = !{i32 2, !"Dwarf Version", i32 4}
 ; CHECK: DW_TAG_member
 ; CHECK-NEXT: DW_AT_name{{.*}}"k"

diff  --git a/llvm/test/DebugInfo/ARM/bitfield.ll b/llvm/test/DebugInfo/ARM/bitfield.ll
index c33fc36e40591..c85680ef96055 100644
--- a/llvm/test/DebugInfo/ARM/bitfield.ll
+++ b/llvm/test/DebugInfo/ARM/bitfield.ll
@@ -36,7 +36,7 @@ target triple = "thumbv7-apple-ios"
 !7 = !{!8, !10}
 !8 = !DIDerivedType(tag: DW_TAG_member, name: "c", scope: !6, file: !3, line: 2, baseType: !9, size: 8, align: 8)
 !9 = !DIBasicType(name: "char", size: 8, align: 8, encoding: DW_ATE_signed_char)
-!10 = !DIDerivedType(tag: DW_TAG_member, name: "reserved", scope: !6, file: !3, line: 4, baseType: !11, size: 28, align: 32, offset: 12)
+!10 = !DIDerivedType(tag: DW_TAG_member, name: "reserved", scope: !6, file: !3, line: 4, baseType: !11, size: 28, align: 32, offset: 12, flags: DIFlagBitField)
 !11 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed)
 !12 = !{i32 2, !"Dwarf Version", i32 2}
 !13 = !{i32 2, !"Debug Info Version", i32 3}

diff  --git a/llvm/test/DebugInfo/X86/bitfields-dwarf4.ll b/llvm/test/DebugInfo/X86/bitfields-dwarf4.ll
index 018653751961a..52382be51fec7 100644
--- a/llvm/test/DebugInfo/X86/bitfields-dwarf4.ll
+++ b/llvm/test/DebugInfo/X86/bitfields-dwarf4.ll
@@ -43,7 +43,7 @@ target triple = "x86_64-apple-macosx"
 ; CHECK-NOT:  DW_AT_data_bit_offset
 ; CHECK:      DW_AT_data_member_location [DW_FORM_data1]	(0x00)
 !9 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_signed_char)
-!10 = !DIDerivedType(tag: DW_TAG_member, name: "b", scope: !6, file: !3, line: 6, baseType: !11, size: 5, offset: 8)
+!10 = !DIDerivedType(tag: DW_TAG_member, name: "b", scope: !6, file: !3, line: 6, baseType: !11, size: 5, offset: 8, flags: DIFlagBitField)
 !11 = !DIDerivedType(tag: DW_TAG_typedef, name: "uint32_t", file: !12, line: 183, baseType: !13)
 !12 = !DIFile(filename: "/Volumes/Data/llvm/_build.ninja.release/bin/../lib/clang/3.9.0/include/stdint.h", directory: "/Volumes/Data/llvm")
 !13 = !DIBasicType(name: "unsigned int", size: 32, encoding: DW_ATE_unsigned)
@@ -56,7 +56,7 @@ target triple = "x86_64-apple-macosx"
 ; CHECK-NOT:  DW_AT_byte_size
 ; CHECK-NEXT: DW_AT_data_bit_offset      [DW_FORM_data1]	(0x08)
 ; CHECK-NOT:  DW_AT_data_member_location
-!14 = !DIDerivedType(tag: DW_TAG_member, name: "c", scope: !6, file: !3, line: 7, baseType: !11, size: 27, offset: 13)
+!14 = !DIDerivedType(tag: DW_TAG_member, name: "c", scope: !6, file: !3, line: 7, baseType: !11, size: 27, offset: 13, flags: DIFlagBitField)
 !15 = !{i32 2, !"Dwarf Version", i32 4}
 !16 = !{i32 2, !"Debug Info Version", i32 3}
 !17 = !{i32 1, !"PIC Level", i32 2}

diff  --git a/llvm/test/DebugInfo/X86/bitfields.ll b/llvm/test/DebugInfo/X86/bitfields.ll
index 500898dd2816e..dae92f9785e05 100644
--- a/llvm/test/DebugInfo/X86/bitfields.ll
+++ b/llvm/test/DebugInfo/X86/bitfields.ll
@@ -63,11 +63,11 @@ target triple = "x86_64-apple-macosx"
 !5 = !{!0}
 !6 = !DICompositeType(tag: DW_TAG_structure_type, name: "bitfield", file: !3, line: 1, size: 96, elements: !7)
 !7 = !{!8, !10, !11, !12}
-!8 = !DIDerivedType(tag: DW_TAG_member, name: "a", scope: !6, file: !3, line: 2, baseType: !9, size: 2)
+!8 = !DIDerivedType(tag: DW_TAG_member, name: "a", scope: !6, file: !3, line: 2, baseType: !9, size: 2, flags: DIFlagBitField)
 !9 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
-!10 = !DIDerivedType(tag: DW_TAG_member, name: "b", scope: !6, file: !3, line: 3, baseType: !9, size: 32, offset: 32)
-!11 = !DIDerivedType(tag: DW_TAG_member, name: "c", scope: !6, file: !3, line: 4, baseType: !9, size: 1, offset: 64)
-!12 = !DIDerivedType(tag: DW_TAG_member, name: "d", scope: !6, file: !3, line: 5, baseType: !9, size: 28, offset: 65)
+!10 = !DIDerivedType(tag: DW_TAG_member, name: "b", scope: !6, file: !3, line: 3, baseType: !9, size: 32, offset: 32, flags: DIFlagBitField)
+!11 = !DIDerivedType(tag: DW_TAG_member, name: "c", scope: !6, file: !3, line: 4, baseType: !9, size: 1, offset: 64, flags: DIFlagBitField)
+!12 = !DIDerivedType(tag: DW_TAG_member, name: "d", scope: !6, file: !3, line: 5, baseType: !9, size: 28, offset: 65, flags: DIFlagBitField)
 !13 = !{i32 2, !"Dwarf Version", i32 2}
 !14 = !{i32 2, !"Debug Info Version", i32 3}
 !15 = !{i32 1, !"PIC Level", i32 2}

diff  --git a/llvm/test/DebugInfo/X86/debug-info-packed-struct.ll b/llvm/test/DebugInfo/X86/debug-info-packed-struct.ll
index d9eeab4ccd37f..d252318cb79d4 100644
--- a/llvm/test/DebugInfo/X86/debug-info-packed-struct.ll
+++ b/llvm/test/DebugInfo/X86/debug-info-packed-struct.ll
@@ -157,7 +157,7 @@ target triple = "x86_64-apple-darwin"
 !12 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_signed_char)
 !13 = !DIDerivedType(tag: DW_TAG_member, name: "l1_ofs1", scope: !9, file: !8, line: 36, baseType: !14, size: 64, offset: 8)
 !14 = !DICompositeType(tag: DW_TAG_structure_type, name: "size8_anon", file: !8, line: 30, size: 64, elements: !4)
-!15 = !DIDerivedType(tag: DW_TAG_member, name: "l1_ofs9", scope: !9, file: !8, line: 37, baseType: !16, size: 1, offset: 72)
+!15 = !DIDerivedType(tag: DW_TAG_member, name: "l1_ofs9", scope: !9, file: !8, line: 37, baseType: !16, size: 1, offset: 72, flags: DIFlagBitField)
 !16 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
 !17 = !DIGlobalVariableExpression(var: !18, expr: !DIExpression())
 !18 = !DIGlobalVariable(name: "l2", scope: !2, file: !8, line: 90, type: !19, isLocal: false, isDefinition: true)
@@ -167,10 +167,10 @@ target triple = "x86_64-apple-darwin"
 !22 = !DIDerivedType(tag: DW_TAG_member, name: "l2_ofs1", scope: !19, file: !8, line: 56, baseType: !23, size: 64, offset: 8)
 !23 = !DICompositeType(tag: DW_TAG_structure_type, name: "size8_pack1", file: !8, line: 50, size: 64, elements: !24)
 !24 = !{!25, !26}
-!25 = !DIDerivedType(tag: DW_TAG_member, name: "i", scope: !23, file: !8, line: 51, baseType: !16, size: 4)
-!26 = !DIDerivedType(tag: DW_TAG_member, name: "l", scope: !23, file: !8, line: 52, baseType: !27, size: 60, offset: 4)
+!25 = !DIDerivedType(tag: DW_TAG_member, name: "i", scope: !23, file: !8, line: 51, baseType: !16, size: 4, flags: DIFlagBitField)
+!26 = !DIDerivedType(tag: DW_TAG_member, name: "l", scope: !23, file: !8, line: 52, baseType: !27, size: 60, offset: 4, flags: DIFlagBitField)
 !27 = !DIBasicType(name: "long long int", size: 64, encoding: DW_ATE_signed)
-!28 = !DIDerivedType(tag: DW_TAG_member, name: "l2_ofs9", scope: !19, file: !8, line: 57, baseType: !16, size: 1, offset: 72)
+!28 = !DIDerivedType(tag: DW_TAG_member, name: "l2_ofs9", scope: !19, file: !8, line: 57, baseType: !16, size: 1, offset: 72, flags: DIFlagBitField)
 !29 = !DIGlobalVariableExpression(var: !30, expr: !DIExpression())
 !30 = !DIGlobalVariable(name: "l3", scope: !2, file: !8, line: 91, type: !31, isLocal: false, isDefinition: true)
 !31 = !DICompositeType(tag: DW_TAG_structure_type, name: "layout3", file: !8, line: 76, size: 128, elements: !32)
@@ -179,18 +179,18 @@ target triple = "x86_64-apple-darwin"
 !34 = !DIDerivedType(tag: DW_TAG_member, name: "l3_ofs4", scope: !31, file: !8, line: 78, baseType: !35, size: 64, offset: 32)
 !35 = !DICompositeType(tag: DW_TAG_structure_type, name: "size8_pack4", file: !8, line: 72, size: 64, elements: !36)
 !36 = !{!37, !38}
-!37 = !DIDerivedType(tag: DW_TAG_member, name: "i", scope: !35, file: !8, line: 73, baseType: !16, size: 4)
-!38 = !DIDerivedType(tag: DW_TAG_member, name: "l", scope: !35, file: !8, line: 74, baseType: !27, size: 60, offset: 4)
-!39 = !DIDerivedType(tag: DW_TAG_member, name: "l3_ofs12", scope: !31, file: !8, line: 79, baseType: !16, size: 1, offset: 96)
+!37 = !DIDerivedType(tag: DW_TAG_member, name: "i", scope: !35, file: !8, line: 73, baseType: !16, size: 4, flags: DIFlagBitField)
+!38 = !DIDerivedType(tag: DW_TAG_member, name: "l", scope: !35, file: !8, line: 74, baseType: !27, size: 60, offset: 4, flags: DIFlagBitField)
+!39 = !DIDerivedType(tag: DW_TAG_member, name: "l3_ofs12", scope: !31, file: !8, line: 79, baseType: !16, size: 1, offset: 96, flags: DIFlagBitField)
 !40 = !DICompositeType(tag: DW_TAG_structure_type, name: "layout0", file: !8, line: 15, size: 192, elements: !41)
 !41 = !{!42, !43, !48}
 !42 = !DIDerivedType(tag: DW_TAG_member, name: "l0_ofs0", scope: !40, file: !8, line: 16, baseType: !12, size: 8)
 !43 = !DIDerivedType(tag: DW_TAG_member, name: "l0_ofs8", scope: !40, file: !8, line: 17, baseType: !44, size: 64, offset: 64)
 !44 = !DICompositeType(tag: DW_TAG_structure_type, name: "size8", file: !8, line: 11, size: 64, elements: !45)
 !45 = !{!46, !47}
-!46 = !DIDerivedType(tag: DW_TAG_member, name: "i", scope: !44, file: !8, line: 12, baseType: !16, size: 4)
-!47 = !DIDerivedType(tag: DW_TAG_member, name: "l", scope: !44, file: !8, line: 13, baseType: !27, size: 60, offset: 4)
-!48 = !DIDerivedType(tag: DW_TAG_member, name: "l0_ofs16", scope: !40, file: !8, line: 18, baseType: !16, size: 1, offset: 128)
+!46 = !DIDerivedType(tag: DW_TAG_member, name: "i", scope: !44, file: !8, line: 12, baseType: !16, size: 4, flags: DIFlagBitField)
+!47 = !DIDerivedType(tag: DW_TAG_member, name: "l", scope: !44, file: !8, line: 13, baseType: !27, size: 60, offset: 4, flags: DIFlagBitField)
+!48 = !DIDerivedType(tag: DW_TAG_member, name: "l0_ofs16", scope: !40, file: !8, line: 18, baseType: !16, size: 1, offset: 128, flags: DIFlagBitField)
 !49 = !{i32 2, !"Dwarf Version", i32 2}
 !50 = !{i32 2, !"Debug Info Version", i32 3}
 !51 = !{!"clang version 3.7.0 (trunk 240791) (llvm/trunk 240790)"}

diff  --git a/llvm/test/DebugInfo/X86/packed_bitfields2.ll b/llvm/test/DebugInfo/X86/packed_bitfields2.ll
new file mode 100644
index 0000000000000..904187aa89a52
--- /dev/null
+++ b/llvm/test/DebugInfo/X86/packed_bitfields2.ll
@@ -0,0 +1,51 @@
+; RUN: llc -dwarf-version=5 -debugger-tune=lldb -mtriple x86_64-unknown-linux-gnu -O0 -filetype=obj -o %t_2_le.o %s
+; RUN: llvm-dwarfdump -v -debug-info %t_2_le.o | FileCheck %s
+
+; Produced at -O0 from:
+; struct __attribute__((packed)) bitfield {
+; 	int i:1;
+; 	int j:32;
+; } bitfield;
+
+; CHECK: DW_TAG_member
+; CHECK-NEXT: DW_AT_name{{.*}}"i"
+; CHECK-NOT: DW_TAG_member
+; CHECK: DW_AT_bit_size   {{.*}} (0x01)
+; CHECK-NEXT: DW_AT_data_bit_offset {{.*}} (0x00)
+
+; CHECK: DW_TAG_member
+; CHECK-NEXT: DW_AT_name{{.*}}"j"
+; CHECK-NOT: DW_TAG_member
+; CHECK: DW_AT_bit_size   {{.*}} (0x20)
+; CHECK-NEXT: DW_AT_data_bit_offset {{.*}} (0x01)
+
+; ModuleID = 'packed_bitfields2.c'
+source_filename = "packed_bitfields2.c"
+target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-pc-linux-gnu"
+
+%struct.bitfield = type { [5 x i8] }
+
+ at bitfield = dso_local global %struct.bitfield zeroinitializer, align 1, !dbg !0
+
+!llvm.dbg.cu = !{!2}
+!llvm.module.flags = !{!11, !12, !13, !14, !15}
+!llvm.ident = !{!16}
+
+!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
+!1 = distinct !DIGlobalVariable(name: "bitfield", scope: !2, file: !3, line: 4, type: !6, isLocal: false, isDefinition: true)
+!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 11.0.1", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5, splitDebugInlining: false, nameTableKind: None, sysroot: "/")
+!3 = !DIFile(filename: "packed_bitfields2.c", directory: "/")
+!4 = !{}
+!5 = !{!0}
+!6 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "bitfield", file: !3, line: 1, size: 40, elements: !7)
+!7 = !{!8, !10}
+!8 = !DIDerivedType(tag: DW_TAG_member, name: "i", scope: !6, file: !3, line: 2, baseType: !9, size: 1, flags: DIFlagBitField, extraData: i64 0)
+!9 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!10 = !DIDerivedType(tag: DW_TAG_member, name: "j", scope: !6, file: !3, line: 3, baseType: !9, size: 32, offset: 1, flags: DIFlagBitField, extraData: i64 0)
+!11 = !{i32 7, !"Dwarf Version", i32 5}
+!12 = !{i32 2, !"Debug Info Version", i32 3}
+!13 = !{i32 1, !"wchar_size", i32 4}
+!14 = !{i32 7, !"PIC Level", i32 2}
+!15 = !{i32 7, !"PIE Level", i32 2}
+!16 = !{!"clang version 11.0.1"}


        


More information about the llvm-commits mailing list