diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -873,23 +873,7 @@ break; } - switch (BT->getKind()) { - case BuiltinType::Long: - BTName = "long int"; - break; - case BuiltinType::LongLong: - BTName = "long long int"; - break; - case BuiltinType::ULong: - BTName = "long unsigned int"; - break; - case BuiltinType::ULongLong: - BTName = "long long unsigned int"; - break; - default: - BTName = BT->getName(CGM.getLangOpts()); - break; - } + BTName = BT->getName(CGM.getLangOpts()); // Bit size and offset of the type. uint64_t Size = CGM.getContext().getTypeSize(BT); return DBuilder.createBasicType(BTName, Size, Encoding); diff --git a/clang/test/CodeGen/aarch64-debug-sve-vector-types.c b/clang/test/CodeGen/aarch64-debug-sve-vector-types.c --- a/clang/test/CodeGen/aarch64-debug-sve-vector-types.c +++ b/clang/test/CodeGen/aarch64-debug-sve-vector-types.c @@ -46,12 +46,12 @@ // CHECK-DAG: name: "__SVInt64_t",{{.*}}, baseType: ![[CT64:[0-9]+]] // CHECK-DAG: ![[CT64]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY64:[0-9]+]], flags: DIFlagVector, elements: ![[ELTS1_64]]) - // CHECK-DAG: ![[ELTTY64]] = !DIBasicType(name: "long int", size: 64, encoding: DW_ATE_signed) + // CHECK-DAG: ![[ELTTY64]] = !DIBasicType(name: "long", size: 64, encoding: DW_ATE_signed) __SVInt64_t s64; // CHECK-DAG: name: "__SVUint64_t",{{.*}}, baseType: ![[CT64:[0-9]+]] // CHECK-DAG: ![[CT64]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY64:[0-9]+]], flags: DIFlagVector, elements: ![[ELTS1_64]]) - // CHECK-DAG: ![[ELTTY64]] = !DIBasicType(name: "long unsigned int", size: 64, encoding: DW_ATE_unsigned) + // CHECK-DAG: ![[ELTTY64]] = !DIBasicType(name: "unsigned long", size: 64, encoding: DW_ATE_unsigned) __SVUint64_t u64; // CHECK: name: "__SVFloat16_t",{{.*}}, baseType: ![[CT16:[0-9]+]] diff --git a/clang/test/CodeGen/aarch64-debug-sve-vectorx2-types.c b/clang/test/CodeGen/aarch64-debug-sve-vectorx2-types.c --- a/clang/test/CodeGen/aarch64-debug-sve-vectorx2-types.c +++ b/clang/test/CodeGen/aarch64-debug-sve-vectorx2-types.c @@ -40,14 +40,14 @@ // CHECK-DAG: name: "__clang_svint64x2_t",{{.*}}, baseType: ![[CT64:[0-9]+]] // CHECK-DAG: ![[CT64]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY64:[0-9]+]], flags: DIFlagVector, elements: ![[ELTS1x2_64:[0-9]+]]) - // CHECK-DAG: ![[ELTTY64]] = !DIBasicType(name: "long int", size: 64, encoding: DW_ATE_signed) + // CHECK-DAG: ![[ELTTY64]] = !DIBasicType(name: "long", size: 64, encoding: DW_ATE_signed) // CHECK-DAG: ![[ELTS1x2_64]] = !{![[REALELTS1x2_64:[0-9]+]]} // CHECK-DAG: ![[REALELTS1x2_64]] = !DISubrange(lowerBound: 0, upperBound: !DIExpression(DW_OP_constu, 2, DW_OP_bregx, 46, 0, DW_OP_mul, DW_OP_constu, 1, DW_OP_minus)) __clang_svint64x2_t s64; // CHECK-DAG: name: "__clang_svuint64x2_t",{{.*}}, baseType: ![[CT64:[0-9]+]] // CHECK-DAG: ![[CT64]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY64:[0-9]+]], flags: DIFlagVector, elements: ![[ELTS1x2_64]]) - // CHECK-DAG: ![[ELTTY64]] = !DIBasicType(name: "long unsigned int", size: 64, encoding: DW_ATE_unsigned) + // CHECK-DAG: ![[ELTTY64]] = !DIBasicType(name: "unsigned long", size: 64, encoding: DW_ATE_unsigned) __clang_svuint64x2_t u64; // CHECK: name: "__clang_svfloat16x2_t",{{.*}}, baseType: ![[CT16:[0-9]+]] diff --git a/clang/test/CodeGen/aarch64-debug-sve-vectorx3-types.c b/clang/test/CodeGen/aarch64-debug-sve-vectorx3-types.c --- a/clang/test/CodeGen/aarch64-debug-sve-vectorx3-types.c +++ b/clang/test/CodeGen/aarch64-debug-sve-vectorx3-types.c @@ -40,14 +40,14 @@ // CHECK-DAG: name: "__clang_svint64x3_t",{{.*}}, baseType: ![[CT64:[0-9]+]] // CHECK-DAG: ![[CT64]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY64:[0-9]+]], flags: DIFlagVector, elements: ![[ELTS1x3_64:[0-9]+]]) - // CHECK-DAG: ![[ELTTY64]] = !DIBasicType(name: "long int", size: 64, encoding: DW_ATE_signed) + // CHECK-DAG: ![[ELTTY64]] = !DIBasicType(name: "long", size: 64, encoding: DW_ATE_signed) // CHECK-DAG: ![[ELTS1x3_64]] = !{![[REALELTS1x3_64:[0-9]+]]} // CHECK-DAG: ![[REALELTS1x3_64]] = !DISubrange(lowerBound: 0, upperBound: !DIExpression(DW_OP_constu, 3, DW_OP_bregx, 46, 0, DW_OP_mul, DW_OP_constu, 1, DW_OP_minus)) __clang_svint64x3_t s64; // CHECK-DAG: name: "__clang_svuint64x3_t",{{.*}}, baseType: ![[CT64:[0-9]+]] // CHECK-DAG: ![[CT64]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY64:[0-9]+]], flags: DIFlagVector, elements: ![[ELTS1x3_64]]) - // CHECK-DAG: ![[ELTTY64]] = !DIBasicType(name: "long unsigned int", size: 64, encoding: DW_ATE_unsigned) + // CHECK-DAG: ![[ELTTY64]] = !DIBasicType(name: "unsigned long", size: 64, encoding: DW_ATE_unsigned) __clang_svuint64x3_t u64; // CHECK: name: "__clang_svfloat16x3_t",{{.*}}, baseType: ![[CT16:[0-9]+]] diff --git a/clang/test/CodeGen/aarch64-debug-sve-vectorx4-types.c b/clang/test/CodeGen/aarch64-debug-sve-vectorx4-types.c --- a/clang/test/CodeGen/aarch64-debug-sve-vectorx4-types.c +++ b/clang/test/CodeGen/aarch64-debug-sve-vectorx4-types.c @@ -40,14 +40,14 @@ // CHECK-DAG: name: "__clang_svint64x4_t",{{.*}}, baseType: ![[CT64:[0-9]+]] // CHECK-DAG: ![[CT64]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY64:[0-9]+]], flags: DIFlagVector, elements: ![[ELTS1x4_64:[0-9]+]]) - // CHECK-DAG: ![[ELTTY64]] = !DIBasicType(name: "long int", size: 64, encoding: DW_ATE_signed) + // CHECK-DAG: ![[ELTTY64]] = !DIBasicType(name: "long", size: 64, encoding: DW_ATE_signed) // CHECK-DAG: ![[ELTS1x4_64]] = !{![[REALELTS1x4_64:[0-9]+]]} // CHECK-DAG: ![[REALELTS1x4_64]] = !DISubrange(lowerBound: 0, upperBound: !DIExpression(DW_OP_constu, 4, DW_OP_bregx, 46, 0, DW_OP_mul, DW_OP_constu, 1, DW_OP_minus)) __clang_svint64x4_t s64; // CHECK-DAG: name: "__clang_svuint64x4_t",{{.*}}, baseType: ![[CT64:[0-9]+]] // CHECK-DAG: ![[CT64]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY64:[0-9]+]], flags: DIFlagVector, elements: ![[ELTS1x4_64]]) - // CHECK-DAG: ![[ELTTY64]] = !DIBasicType(name: "long unsigned int", size: 64, encoding: DW_ATE_unsigned) + // CHECK-DAG: ![[ELTTY64]] = !DIBasicType(name: "unsigned long", size: 64, encoding: DW_ATE_unsigned) __clang_svuint64x4_t u64; // CHECK: name: "__clang_svfloat16x4_t",{{.*}}, baseType: ![[CT16:[0-9]+]] diff --git a/clang/test/CodeGen/debug-info-enum.cpp b/clang/test/CodeGen/debug-info-enum.cpp --- a/clang/test/CodeGen/debug-info-enum.cpp +++ b/clang/test/CodeGen/debug-info-enum.cpp @@ -77,7 +77,7 @@ // CHECK-SAME: baseType: ![[LONG:[0-9]+]] // CHECK-SAME: DIFlagEnumClass // CHECK-SAME: elements: ![[ELTS6:[0-9]+]] -// CHECK: ![[LONG]] = !DIBasicType(name: "long long int", size: 64, encoding: DW_ATE_signed) +// CHECK: ![[LONG]] = !DIBasicType(name: "long long", size: 64, encoding: DW_ATE_signed) // CHECK: ![[ELTS6]] = !{![[A6:[0-9]+]], ![[B6:[0-9]+]]} // CHECK: ![[A6]] = !DIEnumerator(name: "A6", value: -9223372036854775808) // CHECK: ![[B6]] = !DIEnumerator(name: "B6", value: 9223372036854775807) @@ -87,7 +87,7 @@ // CHECK-SAME: baseType: ![[ULONG:[0-9]+]] // CHECK-SAME: DIFlagEnumClass // CHECK-SAME: elements: ![[ELTS7:[0-9]+]] -// CHECK: ![[ULONG]] = !DIBasicType(name: "long long unsigned int", size: 64, encoding: DW_ATE_unsigned) +// CHECK: ![[ULONG]] = !DIBasicType(name: "unsigned long long", size: 64, encoding: DW_ATE_unsigned) // CHECK: ![[ELTS7]] = !{![[A7:[0-9]+]]} // CHECK: ![[A7]] = !DIEnumerator(name: "A7", value: 18446744073709551615, isUnsigned: true) diff --git a/clang/test/CodeGen/debug-info.c b/clang/test/CodeGen/debug-info.c --- a/clang/test/CodeGen/debug-info.c +++ b/clang/test/CodeGen/debug-info.c @@ -58,3 +58,8 @@ typedef unsigned long long uint64_t; typedef uint64_t uint64x2_t __attribute__((ext_vector_type(2))); uint64x2_t extvectbar[4]; + +// CHECK-DAG: !DIBasicType(name: "long" +// CHECK-DAG: !DIBasicType(name: "unsigned long long" +void integral_types(long x, unsigned long long y) { +} diff --git a/clang/test/CodeGenCXX/debug-info-enum-class.cpp b/clang/test/CodeGenCXX/debug-info-enum-class.cpp --- a/clang/test/CodeGenCXX/debug-info-enum-class.cpp +++ b/clang/test/CodeGenCXX/debug-info-enum-class.cpp @@ -25,7 +25,7 @@ // CHECK-NOT: offset: // CHECK-SAME: flags: DIFlagEnumClass // CHECK-SAME: ){{$}} -// CHECK: ![[ULONG]] = !DIBasicType(name: "long unsigned int" +// CHECK: ![[ULONG]] = !DIBasicType(name: "unsigned long" // CHECK: !DICompositeType(tag: DW_TAG_enumeration_type, name: "C" // CHECK-SAME: line: 5 // CHECK-SAME: baseType: ![[ULONG:[0-9]+]] diff --git a/clang/test/CodeGenObjC/objc-fixed-enum.m b/clang/test/CodeGenObjC/objc-fixed-enum.m --- a/clang/test/CodeGenObjC/objc-fixed-enum.m +++ b/clang/test/CodeGenObjC/objc-fixed-enum.m @@ -54,7 +54,7 @@ // CHECK: ![[ENUMERATOR3]] = !DIDerivedType(tag: DW_TAG_typedef, name: "NSInteger" // CHECK-SAME: line: 6 // CHECK-SAME: baseType: ![[LONGINT:[0-9]+]] -// CHECK: ![[LONGINT]] = !DIBasicType(name: "long int" +// CHECK: ![[LONGINT]] = !DIBasicType(name: "long" // CHECK: ![[ENUMERATOR2:[0-9]+]] = !DICompositeType(tag: DW_TAG_enumeration_type, // CHECK-SAME: line: 22 // CHECK-SAME: baseType: ![[ENUMERATOR3]] diff --git a/lldb/test/Shell/SymbolFile/DWARF/x86/find-basic-variable.cpp b/lldb/test/Shell/SymbolFile/DWARF/x86/find-basic-variable.cpp --- a/lldb/test/Shell/SymbolFile/DWARF/x86/find-basic-variable.cpp +++ b/lldb/test/Shell/SymbolFile/DWARF/x86/find-basic-variable.cpp @@ -45,9 +45,9 @@ namespace bar { int context; long foo; -// NAME-DAG: name = "foo", type = {{.*}} (long int), {{.*}} decl = find-basic-variable.cpp:[[@LINE-1]] -// CONTEXT-DAG: name = "foo", type = {{.*}} (long int), {{.*}} decl = find-basic-variable.cpp:[[@LINE-2]] -// REGEX-DAG: name = "foo", type = {{.*}} (long int), {{.*}} decl = find-basic-variable.cpp:[[@LINE-3]] +// NAME-DAG: name = "foo", type = {{.*}} (long), {{.*}} decl = find-basic-variable.cpp:[[@LINE-1]] +// CONTEXT-DAG: name = "foo", type = {{.*}} (long), {{.*}} decl = find-basic-variable.cpp:[[@LINE-2]] +// REGEX-DAG: name = "foo", type = {{.*}} (long), {{.*}} decl = find-basic-variable.cpp:[[@LINE-3]] namespace baz { static short foo; // NAME-DAG: name = "foo", type = {{.*}} (short), {{.*}} decl = find-basic-variable.cpp:[[@LINE-1]] diff --git a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp --- a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp @@ -1729,9 +1729,14 @@ } // Apply some fixups based on the source-level type name. - if (STK == SimpleTypeKind::Int32 && Ty->getName() == "long int") + // Include some amount of canonicalization from an old naming scheme Clang + // used to use for integer types (in an outdated effort to be compatible with + // GCC's debug info/GDB's behavior, which has since been addressed). + if (STK == SimpleTypeKind::Int32 && + (Ty->getName() == "long int" || Ty->getName() == "long")) STK = SimpleTypeKind::Int32Long; - if (STK == SimpleTypeKind::UInt32 && Ty->getName() == "long unsigned int") + if (STK == SimpleTypeKind::UInt32 && (Ty->getName() == "long unsigned int" || + Ty->getName() == "unsigned long")) STK = SimpleTypeKind::UInt32Long; if (STK == SimpleTypeKind::UInt16Short && (Ty->getName() == "wchar_t" || Ty->getName() == "__wchar_t")) diff --git a/llvm/test/CodeGen/MIR/X86/diexpr-win32.mir b/llvm/test/CodeGen/MIR/X86/diexpr-win32.mir --- a/llvm/test/CodeGen/MIR/X86/diexpr-win32.mir +++ b/llvm/test/CodeGen/MIR/X86/diexpr-win32.mir @@ -128,7 +128,7 @@ !15 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "string", file: !1, line: 1, size: 96, elements: !16, identifier: ".?AUstring@@") !16 = !{!17, !19, !20} !17 = !DIDerivedType(tag: DW_TAG_member, name: "length", scope: !15, file: !1, line: 2, baseType: !18, size: 32) - !18 = !DIBasicType(name: "long int", size: 32, encoding: DW_ATE_signed) + !18 = !DIBasicType(name: "long", size: 32, encoding: DW_ATE_signed) !19 = !DIDerivedType(tag: DW_TAG_member, name: "size", scope: !15, file: !1, line: 3, baseType: !18, size: 32, offset: 32) !20 = !DIDerivedType(tag: DW_TAG_member, name: "data", scope: !15, file: !1, line: 4, baseType: !21, size: 32, offset: 64) !21 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !22, size: 32) diff --git a/llvm/test/DebugInfo/COFF/types-basic.ll b/llvm/test/DebugInfo/COFF/types-basic.ll --- a/llvm/test/DebugInfo/COFF/types-basic.ll +++ b/llvm/test/DebugInfo/COFF/types-basic.ll @@ -675,12 +675,12 @@ !46 = !DIDerivedType(tag: DW_TAG_ptr_to_member_type, baseType: !41, size: 64, extraData: !37) !47 = !DILocation(line: 12, column: 13, scope: !7) !48 = !DILocalVariable(name: "l1", scope: !7, file: !1, line: 13, type: !49) -!49 = !DIBasicType(name: "long int", size: 32, align: 32, encoding: DW_ATE_signed) +!49 = !DIBasicType(name: "long", size: 32, align: 32, encoding: DW_ATE_signed) !50 = !DILocation(line: 13, column: 8, scope: !7) !51 = !DILocalVariable(name: "l2", scope: !7, file: !1, line: 14, type: !49) !52 = !DILocation(line: 14, column: 12, scope: !7) !53 = !DILocalVariable(name: "l3", scope: !7, file: !1, line: 15, type: !54) -!54 = !DIBasicType(name: "long unsigned int", size: 32, align: 32, encoding: DW_ATE_unsigned) +!54 = !DIBasicType(name: "unsigned long", size: 32, align: 32, encoding: DW_ATE_unsigned) !55 = !DILocation(line: 15, column: 17, scope: !7) !56 = !DILocalVariable(name: "l4", scope: !7, file: !1, line: 16, type: !54) !57 = !DILocation(line: 16, column: 21, scope: !7) diff --git a/llvm/test/DebugInfo/COFF/types-integer-old.ll b/llvm/test/DebugInfo/COFF/types-integer-old.ll new file mode 100644 --- /dev/null +++ b/llvm/test/DebugInfo/COFF/types-integer-old.ll @@ -0,0 +1,77 @@ +; RUN: llc < %s -filetype=obj | llvm-readobj - --codeview | FileCheck %s + +; Tests that CodeView integer types are generated even when using Clang's old integer type names. + +; C++ source to regenerate: +; $ cat t.cpp +; void usevars(long, ...); +; void f() { +; long l1 = 0; +; unsigned long l2 = 0; +; usevars(l1, l2); +; } +; $ clang t.cpp -S -emit-llvm -g -gcodeview -o t.ll -target x86_64-pc-windows-msvc19.0.23918 + +; CHECK: LocalSym { +; CHECK: Type: long (0x12) +; CHECK: VarName: l1 +; CHECK: } +; CHECK: LocalSym { +; CHECK: Type: unsigned long (0x22) +; CHECK: VarName: l2 +; CHECK: } + +; ModuleID = '/usr/local/google/home/blaikie/dev/scratch/t.cpp' +source_filename = "/usr/local/google/home/blaikie/dev/scratch/t.cpp" +target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-pc-windows-msvc19.0.23918" + +; Function Attrs: mustprogress noinline optnone uwtable +define dso_local void @"?f@@YAXXZ"() #0 !dbg !8 { +entry: + %l1 = alloca i32, align 4 + %l2 = alloca i32, align 4 + call void @llvm.dbg.declare(metadata i32* %l1, metadata !13, metadata !DIExpression()), !dbg !15 + store i32 0, i32* %l1, align 4, !dbg !15 + call void @llvm.dbg.declare(metadata i32* %l2, metadata !16, metadata !DIExpression()), !dbg !18 + store i32 0, i32* %l2, align 4, !dbg !18 + %0 = load i32, i32* %l2, align 4, !dbg !19 + %1 = load i32, i32* %l1, align 4, !dbg !19 + call void (i32, ...) @"?usevars@@YAXJZZ"(i32 %1, i32 %0), !dbg !19 + ret void, !dbg !20 +} + +; Function Attrs: nofree nosync nounwind readnone speculatable willreturn +declare void @llvm.dbg.declare(metadata, metadata, metadata) #1 + +declare dso_local void @"?usevars@@YAXJZZ"(i32, ...) #2 + +attributes #0 = { mustprogress noinline optnone uwtable "frame-pointer"="none" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } +attributes #1 = { nofree nosync nounwind readnone speculatable willreturn } +attributes #2 = { "frame-pointer"="none" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!2, !3, !4, !5, !6} +!llvm.ident = !{!7} + +!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang version 14.0.0 (git@github.com:llvm/llvm-project.git 3709fb72c86bea1f0e6c51ab334ed6417cbe1c07)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None) +!1 = !DIFile(filename: "/usr/local/google/home/blaikie/dev/scratch/t.cpp", directory: "/usr/local/google/home/blaikie/dev/llvm/src", checksumkind: CSK_MD5, checksum: "a8e7ccc989ea91d67d3cb95afa046aa5") +!2 = !{i32 2, !"CodeView", i32 1} +!3 = !{i32 2, !"Debug Info Version", i32 3} +!4 = !{i32 1, !"wchar_size", i32 2} +!5 = !{i32 7, !"PIC Level", i32 2} +!6 = !{i32 7, !"uwtable", i32 1} +!7 = !{!"clang version 14.0.0 (git@github.com:llvm/llvm-project.git 3709fb72c86bea1f0e6c51ab334ed6417cbe1c07)"} +!8 = distinct !DISubprogram(name: "f", linkageName: "?f@@YAXXZ", scope: !9, file: !9, line: 2, type: !10, scopeLine: 2, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !12) +!9 = !DIFile(filename: "scratch/t.cpp", directory: "/usr/local/google/home/blaikie/dev", checksumkind: CSK_MD5, checksum: "a8e7ccc989ea91d67d3cb95afa046aa5") +!10 = !DISubroutineType(types: !11) +!11 = !{null} +!12 = !{} +!13 = !DILocalVariable(name: "l1", scope: !8, file: !9, line: 3, type: !14) +!14 = !DIBasicType(name: "long int", size: 32, encoding: DW_ATE_signed) +!15 = !DILocation(line: 3, scope: !8) +!16 = !DILocalVariable(name: "l2", scope: !8, file: !9, line: 4, type: !17) +!17 = !DIBasicType(name: "long unsigned int", size: 32, encoding: DW_ATE_unsigned) +!18 = !DILocation(line: 4, scope: !8) +!19 = !DILocation(line: 5, scope: !8) +!20 = !DILocation(line: 6, scope: !8)