1 //===- DWARFLinkerDeclContext.cpp -----------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "llvm/DWARFLinker/DWARFLinkerDeclContext.h" 10 #include "llvm/DebugInfo/DWARF/DWARFContext.h" 11 #include "llvm/DebugInfo/DWARF/DWARFDie.h" 12 #include "llvm/DebugInfo/DWARF/DWARFUnit.h" 13 14 namespace llvm { 15 16 /// Set the last DIE/CU a context was seen in and, possibly invalidate the 17 /// context if it is ambiguous. 18 /// 19 /// In the current implementation, we don't handle overloaded functions well, 20 /// because the argument types are not taken into account when computing the 21 /// DeclContext tree. 22 /// 23 /// Some of this is mitigated byt using mangled names that do contain the 24 /// arguments types, but sometimes (e.g. with function templates) we don't have 25 /// that. In that case, just do not unique anything that refers to the contexts 26 /// we are not able to distinguish. 27 /// 28 /// If a context that is not a namespace appears twice in the same CU, we know 29 /// it is ambiguous. Make it invalid. 30 bool DeclContext::setLastSeenDIE(CompileUnit &U, const DWARFDie &Die) { 31 if (LastSeenCompileUnitID == U.getUniqueID()) { 32 DWARFUnit &OrigUnit = U.getOrigUnit(); 33 uint32_t FirstIdx = OrigUnit.getDIEIndex(LastSeenDIE); 34 U.getInfo(FirstIdx).Ctxt = nullptr; 35 return false; 36 } 37 38 LastSeenCompileUnitID = U.getUniqueID(); 39 LastSeenDIE = Die; 40 return true; 41 } 42 43 PointerIntPair<DeclContext *, 1> DeclContextTree::getChildDeclContext( 44 DeclContext &Context, const DWARFDie &DIE, CompileUnit &U, 45 UniquingStringPool &StringPool, bool InClangModule) { 46 unsigned Tag = DIE.getTag(); 47 48 // FIXME: dsymutil-classic compat: We should bail out here if we 49 // have a specification or an abstract_origin. We will get the 50 // parent context wrong here. 51 52 switch (Tag) { 53 default: 54 // By default stop gathering child contexts. 55 return PointerIntPair<DeclContext *, 1>(nullptr); 56 case dwarf::DW_TAG_module: 57 break; 58 case dwarf::DW_TAG_compile_unit: 59 return PointerIntPair<DeclContext *, 1>(&Context); 60 case dwarf::DW_TAG_subprogram: 61 // Do not unique anything inside CU local functions. 62 if ((Context.getTag() == dwarf::DW_TAG_namespace || 63 Context.getTag() == dwarf::DW_TAG_compile_unit) && 64 !dwarf::toUnsigned(DIE.find(dwarf::DW_AT_external), 0)) 65 return PointerIntPair<DeclContext *, 1>(nullptr); 66 LLVM_FALLTHROUGH; 67 case dwarf::DW_TAG_member: 68 case dwarf::DW_TAG_namespace: 69 case dwarf::DW_TAG_structure_type: 70 case dwarf::DW_TAG_class_type: 71 case dwarf::DW_TAG_union_type: 72 case dwarf::DW_TAG_enumeration_type: 73 case dwarf::DW_TAG_typedef: 74 // Artificial things might be ambiguous, because they might be created on 75 // demand. For example implicitly defined constructors are ambiguous 76 // because of the way we identify contexts, and they won't be generated 77 // every time everywhere. 78 if (dwarf::toUnsigned(DIE.find(dwarf::DW_AT_artificial), 0)) 79 return PointerIntPair<DeclContext *, 1>(nullptr); 80 break; 81 } 82 83 const char *Name = DIE.getName(DINameKind::LinkageName); 84 const char *ShortName = DIE.getName(DINameKind::ShortName); 85 StringRef NameRef; 86 StringRef ShortNameRef; 87 StringRef FileRef; 88 89 if (Name) 90 NameRef = StringPool.internString(Name); 91 else if (Tag == dwarf::DW_TAG_namespace) 92 // FIXME: For dsymutil-classic compatibility. I think uniquing within 93 // anonymous namespaces is wrong. There is no ODR guarantee there. 94 NameRef = StringPool.internString("(anonymous namespace)"); 95 96 if (ShortName && ShortName != Name) 97 ShortNameRef = StringPool.internString(ShortName); 98 else 99 ShortNameRef = NameRef; 100 101 if (Tag != dwarf::DW_TAG_class_type && Tag != dwarf::DW_TAG_structure_type && 102 Tag != dwarf::DW_TAG_union_type && 103 Tag != dwarf::DW_TAG_enumeration_type && NameRef.empty()) 104 return PointerIntPair<DeclContext *, 1>(nullptr); 105 106 unsigned Line = 0; 107 unsigned ByteSize = std::numeric_limits<uint32_t>::max(); 108 109 if (!InClangModule) { 110 // Gather some discriminating data about the DeclContext we will be 111 // creating: File, line number and byte size. This shouldn't be necessary, 112 // because the ODR is just about names, but given that we do some 113 // approximations with overloaded functions and anonymous namespaces, use 114 // these additional data points to make the process safer. 115 // 116 // This is disabled for clang modules, because forward declarations of 117 // module-defined types do not have a file and line. 118 ByteSize = dwarf::toUnsigned(DIE.find(dwarf::DW_AT_byte_size), 119 std::numeric_limits<uint64_t>::max()); 120 if (Tag != dwarf::DW_TAG_namespace || !Name) { 121 if (unsigned FileNum = 122 dwarf::toUnsigned(DIE.find(dwarf::DW_AT_decl_file), 0)) { 123 if (const auto *LT = U.getOrigUnit().getContext().getLineTableForUnit( 124 &U.getOrigUnit())) { 125 // FIXME: dsymutil-classic compatibility. I'd rather not 126 // unique anything in anonymous namespaces, but if we do, then 127 // verify that the file and line correspond. 128 if (!Name && Tag == dwarf::DW_TAG_namespace) 129 FileNum = 1; 130 131 if (LT->hasFileAtIndex(FileNum)) { 132 Line = dwarf::toUnsigned(DIE.find(dwarf::DW_AT_decl_line), 0); 133 // Cache the resolved paths based on the index in the line table, 134 // because calling realpath is expansive. 135 StringRef ResolvedPath = U.getResolvedPath(FileNum); 136 if (!ResolvedPath.empty()) { 137 FileRef = ResolvedPath; 138 } else { 139 std::string File; 140 bool FoundFileName = LT->getFileNameByIndex( 141 FileNum, U.getOrigUnit().getCompilationDir(), 142 DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, 143 File); 144 (void)FoundFileName; 145 assert(FoundFileName && "Must get file name from line table"); 146 // Second level of caching, this time based on the file's parent 147 // path. 148 FileRef = PathResolver.resolve(File, StringPool); 149 U.setResolvedPath(FileNum, FileRef); 150 } 151 } 152 } 153 } 154 } 155 } 156 157 if (!Line && NameRef.empty()) 158 return PointerIntPair<DeclContext *, 1>(nullptr); 159 160 // We hash NameRef, which is the mangled name, in order to get most 161 // overloaded functions resolve correctly. 162 // 163 // Strictly speaking, hashing the Tag is only necessary for a 164 // DW_TAG_module, to prevent uniquing of a module and a namespace 165 // with the same name. 166 // 167 // FIXME: dsymutil-classic won't unique the same type presented 168 // once as a struct and once as a class. Using the Tag in the fully 169 // qualified name hash to get the same effect. 170 unsigned Hash = hash_combine(Context.getQualifiedNameHash(), Tag, NameRef); 171 172 // FIXME: dsymutil-classic compatibility: when we don't have a name, 173 // use the filename. 174 if (Tag == dwarf::DW_TAG_namespace && NameRef == "(anonymous namespace)") 175 Hash = hash_combine(Hash, FileRef); 176 177 // Now look if this context already exists. 178 DeclContext Key(Hash, Line, ByteSize, Tag, NameRef, FileRef, Context); 179 auto ContextIter = Contexts.find(&Key); 180 181 if (ContextIter == Contexts.end()) { 182 // The context wasn't found. 183 bool Inserted; 184 DeclContext *NewContext = 185 new (Allocator) DeclContext(Hash, Line, ByteSize, Tag, NameRef, FileRef, 186 Context, DIE, U.getUniqueID()); 187 std::tie(ContextIter, Inserted) = Contexts.insert(NewContext); 188 assert(Inserted && "Failed to insert DeclContext"); 189 (void)Inserted; 190 } else if (Tag != dwarf::DW_TAG_namespace && 191 !(*ContextIter)->setLastSeenDIE(U, DIE)) { 192 // The context was found, but it is ambiguous with another context 193 // in the same file. Mark it invalid. 194 return PointerIntPair<DeclContext *, 1>(*ContextIter, /* Invalid= */ 1); 195 } 196 197 assert(ContextIter != Contexts.end()); 198 // FIXME: dsymutil-classic compatibility. Union types aren't 199 // uniques, but their children might be. 200 if ((Tag == dwarf::DW_TAG_subprogram && 201 Context.getTag() != dwarf::DW_TAG_structure_type && 202 Context.getTag() != dwarf::DW_TAG_class_type) || 203 (Tag == dwarf::DW_TAG_union_type)) 204 return PointerIntPair<DeclContext *, 1>(*ContextIter, /* Invalid= */ 1); 205 206 return PointerIntPair<DeclContext *, 1>(*ContextIter); 207 } 208 209 } // namespace llvm 210