diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp index 06204a8600914f..675df309e3f0f3 100644 --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -3495,6 +3495,9 @@ llvm::DISubprogram *CGDebugInfo::getObjCMethodDeclaration( if (CGM.getCodeGenOpts().DwarfVersion < 5 && !OMD->isDirectMethod()) return nullptr; + if (OMD->isDirectMethod()) + SPFlags |= llvm::DISubprogram::SPFlagObjCDirect; + // Starting with DWARF V5 method declarations are emitted as children of // the interface type. auto *ID = dyn_cast_or_null(D->getDeclContext()); diff --git a/clang/test/CodeGenObjC/debug-info-direct-method.m b/clang/test/CodeGenObjC/debug-info-direct-method.m index f822088f946ca8..e5e2939a8c8191 100644 --- a/clang/test/CodeGenObjC/debug-info-direct-method.m +++ b/clang/test/CodeGenObjC/debug-info-direct-method.m @@ -1,12 +1,17 @@ // RUN: %clang_cc1 -dwarf-version=5 -emit-llvm -debug-info-kind=limited -w -triple x86_64-apple-darwin10 %s -o - | FileCheck %s // RUN: %clang_cc1 -dwarf-version=4 -emit-llvm -debug-info-kind=limited -w -triple x86_64-apple-darwin10 %s -o - | FileCheck %s +// RUN: %clang_cc1 -dwarf-version=5 -emit-llvm -debug-info-kind=limited -w -triple x86_64-apple-darwin10 %s -o - -DDISABLE_DIRECT | FileCheck --check-prefix=CHECK-DISABLED %s __attribute__((objc_root_class)) @interface Root @end @implementation Root -- (int)getInt __attribute__((objc_direct)) { +- (int)getInt +#ifndef DISABLE_DIRECT + __attribute__((objc_direct)) +#endif +{ return 42; } @end @@ -19,3 +24,6 @@ - (int)getInt __attribute__((objc_direct)) { // CHECK-SAME: runtimeLang: DW_LANG_ObjC) // CHECK: ![[MEMBERS]] = !{![[GETTER:[0-9]+]]} // CHECK: ![[GETTER]] = !DISubprogram(name: "-[Root getInt]", +// CHECK-SAME: spFlags: DISPFlagObjCDirect + +// CHECK-DISABLED-NOT: DISPFlagObjCDirect diff --git a/llvm/include/llvm/BinaryFormat/Dwarf.def b/llvm/include/llvm/BinaryFormat/Dwarf.def index 34a7410f747440..8b1b14de6f0961 100644 --- a/llvm/include/llvm/BinaryFormat/Dwarf.def +++ b/llvm/include/llvm/BinaryFormat/Dwarf.def @@ -421,6 +421,7 @@ HANDLE_DW_AT(0x3fea, APPLE_property_setter, 0, APPLE) HANDLE_DW_AT(0x3feb, APPLE_property_attribute, 0, APPLE) HANDLE_DW_AT(0x3fec, APPLE_objc_complete_type, 0, APPLE) HANDLE_DW_AT(0x3fed, APPLE_property, 0, APPLE) +HANDLE_DW_AT(0x3fee, APPLE_objc_direct, 0, APPLE) // Attribute form encodings. HANDLE_DW_FORM(0x01, addr, 2, DWARF) diff --git a/llvm/include/llvm/IR/DebugInfoFlags.def b/llvm/include/llvm/IR/DebugInfoFlags.def index 587df8bec79cd7..df375b6c68e810 100644 --- a/llvm/include/llvm/IR/DebugInfoFlags.def +++ b/llvm/include/llvm/IR/DebugInfoFlags.def @@ -90,11 +90,12 @@ HANDLE_DISP_FLAG((1u << 8), MainSubprogram) // May also utilize this Flag in future, when adding support // for defaulted functions HANDLE_DISP_FLAG((1u << 9), Deleted) +HANDLE_DISP_FLAG((1u << 11), ObjCDirect) #ifdef DISP_FLAG_LARGEST_NEEDED // Intended to be used with ADT/BitmaskEnum.h. // NOTE: Always must be equal to largest flag, check this when adding new flags. -HANDLE_DISP_FLAG((1 << 9), Largest) +HANDLE_DISP_FLAG((1 << 11), Largest) #undef DISP_FLAG_LARGEST_NEEDED #endif diff --git a/llvm/include/llvm/IR/DebugInfoMetadata.h b/llvm/include/llvm/IR/DebugInfoMetadata.h index d690ccece5fa69..214003ad99343e 100644 --- a/llvm/include/llvm/IR/DebugInfoMetadata.h +++ b/llvm/include/llvm/IR/DebugInfoMetadata.h @@ -1758,6 +1758,7 @@ class DISubprogram : public DILocalScope { bool isPure() const { return getSPFlags() & SPFlagPure; } bool isElemental() const { return getSPFlags() & SPFlagElemental; } bool isRecursive() const { return getSPFlags() & SPFlagRecursive; } + bool isObjCDirect() const { return getSPFlags() & SPFlagObjCDirect; } /// Check if this is deleted member function. /// diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp index 86522a85427a53..e44e432ec6a0c3 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp @@ -1233,6 +1233,9 @@ void DwarfUnit::applySubprogramAttributes(const DISubprogram *SP, DIE &SPDie, Language == dwarf::DW_LANG_ObjC)) addFlag(SPDie, dwarf::DW_AT_prototyped); + if (SP->isObjCDirect()) + addFlag(SPDie, dwarf::DW_AT_APPLE_objc_direct); + unsigned CC = 0; DITypeRefArray Args; if (const DISubroutineType *SPTy = SP->getType()) { diff --git a/llvm/test/DebugInfo/X86/objc_direct.ll b/llvm/test/DebugInfo/X86/objc_direct.ll new file mode 100644 index 00000000000000..c29dec14a4488a --- /dev/null +++ b/llvm/test/DebugInfo/X86/objc_direct.ll @@ -0,0 +1,54 @@ +; RUN: llc < %s -filetype=obj -o %t +; RUN: llvm-dwarfdump -v %t | FileCheck %s + +; Source code to regenerate: +; __attribute__((objc_root_class)) +; @interface Root +; - (int)direct_method __attribute__((objc_direct)); +; @end +; +; @implementation Root +; - (int)direct_method __attribute__((objc_direct)) { +; return 42; +; } +; @end +; +; clang -O0 -g -gdwarf-5 direct.m -c + +; CHECK: DW_TAG_subprogram [3] +; CHECK: DW_AT_APPLE_objc_direct +; CHECK-SAME: DW_FORM_flag_present +; CHECK: DW_TAG_formal_parameter [4] + +; ModuleID = 'direct.bc' +source_filename = "direct.m" + +%0 = type opaque + +define hidden i32 @"\01-[Root direct_method]"(%0* %self, i8* %_cmd) { +entry: + %retval = alloca i32, align 4 + %0 = load i32, i32* %retval, align 4 + ret i32 %0 +} + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!19, !20} +!llvm.ident = !{} + +!0 = distinct !DICompileUnit(language: DW_LANG_ObjC, file: !1, producer: "clang version 10.0.0 (https://github.com/llvm/llvm-project d6b2f33e2b6338d24cf756ba220939aecc81210d)", isOptimized: false, runtimeVersion: 2, emissionKind: FullDebug, enums: !2, retainedTypes: !3, nameTableKind: None) +!1 = !DIFile(filename: "direct.m", directory: "/", checksumkind: CSK_MD5, checksum: "6b49fad130344b0011fc0eef65949390") +!2 = !{} +!3 = !{!4} +!4 = !DICompositeType(tag: DW_TAG_structure_type, name: "Root", scope: !1, file: !1, line: 2, flags: DIFlagObjcClassComplete, elements: !5, runtimeLang: DW_LANG_ObjC) +!5 = !{!6} +!6 = !DISubprogram(name: "-[Root direct_method]", scope: !4, file: !1, line: 7, type: !7, scopeLine: 7, flags: DIFlagPrototyped, spFlags: DISPFlagObjCDirect, retainedNodes: !2) +!7 = !DISubroutineType(types: !8) +!8 = !{!9, !10, !11} +!9 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!10 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !4, size: 64, flags: DIFlagArtificial | DIFlagObjectPointer) +!11 = !DIDerivedType(tag: DW_TAG_typedef, name: "SEL", file: !1, baseType: !12, flags: DIFlagArtificial) +!12 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !13, size: 64) +!13 = !DICompositeType(tag: DW_TAG_structure_type, name: "objc_selector", file: !1, flags: DIFlagFwdDecl) +!19 = !{i32 7, !"Dwarf Version", i32 5} +!20 = !{i32 2, !"Debug Info Version", i32 3}