Skip to content

Commit

Permalink
Debug info: Emit objc_direct methods as members of their containing c…
Browse files Browse the repository at this point in the history
…lass

even in DWARF 4 and earlier. This allows the debugger to recognize
them as direct functions as opposed to Objective-C methods.

<rdar://problem/57327663>

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

(cherry picked from commit e0cabe2)
  • Loading branch information
adrian-prantl committed Nov 21, 2019
1 parent 7743452 commit 4fc7e5f
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 24 deletions.
48 changes: 25 additions & 23 deletions clang/lib/CodeGen/CGDebugInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3504,14 +3504,15 @@ llvm::DISubprogram *CGDebugInfo::getObjCMethodDeclaration(
if (!D || DebugKind <= codegenoptions::DebugLineTablesOnly)
return nullptr;

if (CGM.getCodeGenOpts().DwarfVersion < 5)
const auto *OMD = dyn_cast<ObjCMethodDecl>(D);
if (!OMD)
return nullptr;

if (CGM.getCodeGenOpts().DwarfVersion < 5 && !OMD->isDirectMethod())
return nullptr;

// Starting with DWARF V5 method declarations are emitted as children of
// the interface type.
const auto *OMD = dyn_cast<ObjCMethodDecl>(D);
if (!OMD)
return nullptr;
auto *ID = dyn_cast_or_null<ObjCInterfaceDecl>(D->getDeclContext());
if (!ID)
ID = OMD->getClassInterface();
Expand All @@ -3526,7 +3527,7 @@ llvm::DISubprogram *CGDebugInfo::getObjCMethodDeclaration(
InterfaceType, getObjCMethodName(OMD), StringRef(),
InterfaceType->getFile(), LineNo, FnType, LineNo, Flags, SPFlags);
DBuilder.finalizeSubprogram(FD);
ObjCMethodCache[ID].push_back(FD);
ObjCMethodCache[ID].push_back({FD, OMD->isDirectMethod()});
return FD;
}

Expand Down Expand Up @@ -4751,27 +4752,28 @@ void CGDebugInfo::finalize() {
DBuilder.replaceTemporary(llvm::TempDIType(E.Decl), Ty);
}

if (CGM.getCodeGenOpts().DwarfVersion >= 5) {
// Add methods to interface.
for (const auto &P : ObjCMethodCache) {
if (P.second.empty())
continue;
// Add methods to interface.
for (const auto &P : ObjCMethodCache) {
if (P.second.empty())
continue;

QualType QTy(P.first->getTypeForDecl(), 0);
auto It = TypeCache.find(QTy.getAsOpaquePtr());
assert(It != TypeCache.end());
QualType QTy(P.first->getTypeForDecl(), 0);
auto It = TypeCache.find(QTy.getAsOpaquePtr());
assert(It != TypeCache.end());

llvm::DICompositeType *InterfaceDecl =
cast<llvm::DICompositeType>(It->second);
llvm::DICompositeType *InterfaceDecl =
cast<llvm::DICompositeType>(It->second);

SmallVector<llvm::Metadata *, 16> EltTys;
auto CurrenetElts = InterfaceDecl->getElements();
EltTys.append(CurrenetElts.begin(), CurrenetElts.end());
for (auto &MD : P.second)
EltTys.push_back(MD);
llvm::DINodeArray Elements = DBuilder.getOrCreateArray(EltTys);
DBuilder.replaceArrays(InterfaceDecl, Elements);
}
auto CurElts = InterfaceDecl->getElements();
SmallVector<llvm::Metadata *, 16> EltTys(CurElts.begin(), CurElts.end());

// For DWARF v4 or earlier, only add objc_direct methods.
for (auto &SubprogramDirect : P.second)
if (CGM.getCodeGenOpts().DwarfVersion >= 5 || SubprogramDirect.getInt())
EltTys.push_back(SubprogramDirect.getPointer());

llvm::DINodeArray Elements = DBuilder.getOrCreateArray(EltTys);
DBuilder.replaceArrays(InterfaceDecl, Elements);
}

for (const auto &P : ReplaceMap) {
Expand Down
5 changes: 4 additions & 1 deletion clang/lib/CodeGen/CGDebugInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,10 @@ class CGDebugInfo {
llvm::SmallVector<ObjCInterfaceCacheEntry, 32> ObjCInterfaceCache;

/// Cache of forward declarations for methods belonging to the interface.
llvm::DenseMap<const ObjCInterfaceDecl *, std::vector<llvm::DISubprogram *>>
/// The extra bit on the DISubprogram specifies whether a method is
/// "objc_direct".
llvm::DenseMap<const ObjCInterfaceDecl *,
std::vector<llvm::PointerIntPair<llvm::DISubprogram *, 1>>>
ObjCMethodCache;

/// Cache of references to clang modules and precompiled headers.
Expand Down
21 changes: 21 additions & 0 deletions clang/test/CodeGenObjC/debug-info-direct-method.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// 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

__attribute__((objc_root_class))
@interface Root
@end

@implementation Root
- (int)getInt __attribute__((objc_direct)) {
return 42;
}
@end

// Test that objc_direct methods are always (even in DWARF < 5) emitted
// as members of their containing class.

// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "Root",
// CHECK-SAME: elements: ![[MEMBERS:[0-9]+]],
// CHECK-SAME: runtimeLang: DW_LANG_ObjC)
// CHECK: ![[MEMBERS]] = !{![[GETTER:[0-9]+]]}
// CHECK: ![[GETTER]] = !DISubprogram(name: "-[Root getInt]",

0 comments on commit 4fc7e5f

Please sign in to comment.