https://github.com/Michael137 created 
https://github.com/llvm/llvm-project/pull/148877

None

>From 7f805d67f73d9683d69410895be1d042f0c6da14 Mon Sep 17 00:00:00 2001
From: Michael Buch <michaelbuc...@gmail.com>
Date: Fri, 15 Nov 2024 01:59:36 +0000
Subject: [PATCH] [lldb][Expression] Encode Module and DIE UIDs into function
 AsmLabels

---
 lldb/include/lldb/Expression/Expression.h     |  12 ++
 lldb/include/lldb/Symbol/SymbolFile.h         |   7 +
 lldb/source/Expression/IRExecutionUnit.cpp    | 127 ++++++++++++++++++
 .../Clang/ClangExpressionDeclMap.cpp          |   2 +-
 .../Language/CPlusPlus/CPlusPlusLanguage.cpp  |   7 +-
 .../SymbolFile/DWARF/DWARFASTParserClang.cpp  |  56 +++++---
 .../SymbolFile/DWARF/SymbolFileDWARF.cpp      |  52 +++++++
 .../SymbolFile/DWARF/SymbolFileDWARF.h        |   5 +
 .../SymbolFile/NativePDB/PdbAstBuilder.cpp    |   6 +-
 .../Plugins/SymbolFile/PDB/PDBASTParser.cpp   |   7 +-
 .../TypeSystem/Clang/TypeSystemClang.cpp      |  50 ++++++-
 .../TypeSystem/Clang/TypeSystemClang.h        |   5 +-
 lldb/unittests/Symbol/TestTypeSystemClang.cpp |  12 +-
 13 files changed, 310 insertions(+), 38 deletions(-)

diff --git a/lldb/include/lldb/Expression/Expression.h 
b/lldb/include/lldb/Expression/Expression.h
index 8de9364436ccf..a3f1fcc0ef442 100644
--- a/lldb/include/lldb/Expression/Expression.h
+++ b/lldb/include/lldb/Expression/Expression.h
@@ -96,6 +96,18 @@ class Expression {
                                  ///invalid.
 };
 
+inline constexpr llvm::StringRef FunctionCallLabelPrefix = "$__lldb_func";
+
+inline bool hasFunctionCallLabelPrefix(llvm::StringRef name) {
+  name.consume_front("_");
+  return name.starts_with(FunctionCallLabelPrefix);
+}
+
+inline bool consumeFunctionCallLabelPrefix(llvm::StringRef &name) {
+  name.consume_front("_");
+  return name.consume_front(FunctionCallLabelPrefix);
+}
+
 } // namespace lldb_private
 
 #endif // LLDB_EXPRESSION_EXPRESSION_H
diff --git a/lldb/include/lldb/Symbol/SymbolFile.h 
b/lldb/include/lldb/Symbol/SymbolFile.h
index e95f95553c17c..bfb89721c98c8 100644
--- a/lldb/include/lldb/Symbol/SymbolFile.h
+++ b/lldb/include/lldb/Symbol/SymbolFile.h
@@ -18,6 +18,7 @@
 #include "lldb/Symbol/CompilerType.h"
 #include "lldb/Symbol/Function.h"
 #include "lldb/Symbol/SourceModule.h"
+#include "lldb/Symbol/SymbolContext.h"
 #include "lldb/Symbol/Type.h"
 #include "lldb/Symbol/TypeList.h"
 #include "lldb/Symbol/TypeSystem.h"
@@ -328,6 +329,12 @@ class SymbolFile : public PluginInterface {
   GetMangledNamesForFunction(const std::string &scope_qualified_name,
                              std::vector<ConstString> &mangled_names);
 
+  virtual ConstString GetMangledNameForUID(lldb::user_id_t uid) { return {}; }
+  virtual llvm::Error ResolveFunctionUID(SymbolContextList &sc_list,
+                                         lldb::user_id_t uid) {
+    return llvm::createStringError("Not implemented");
+  }
+
   virtual void GetTypes(lldb_private::SymbolContextScope *sc_scope,
                         lldb::TypeClass type_mask,
                         lldb_private::TypeList &type_list) = 0;
diff --git a/lldb/source/Expression/IRExecutionUnit.cpp 
b/lldb/source/Expression/IRExecutionUnit.cpp
index e445fa8833022..2edfa661b4e98 100644
--- a/lldb/source/Expression/IRExecutionUnit.cpp
+++ b/lldb/source/Expression/IRExecutionUnit.cpp
@@ -6,6 +6,7 @@
 //
 
//===----------------------------------------------------------------------===//
 
+#include "llvm/ADT/StringRef.h"
 #include "llvm/ExecutionEngine/ExecutionEngine.h"
 #include "llvm/ExecutionEngine/ObjectCache.h"
 #include "llvm/IR/Constants.h"
@@ -19,7 +20,9 @@
 #include "lldb/Core/Debugger.h"
 #include "lldb/Core/Disassembler.h"
 #include "lldb/Core/Module.h"
+#include "lldb/Core/ModuleList.h"
 #include "lldb/Core/Section.h"
+#include "lldb/Expression/Expression.h"
 #include "lldb/Expression/IRExecutionUnit.h"
 #include "lldb/Expression/ObjectFileJIT.h"
 #include "lldb/Host/HostInfo.h"
@@ -36,6 +39,7 @@
 #include "lldb/Utility/LLDBAssert.h"
 #include "lldb/Utility/LLDBLog.h"
 #include "lldb/Utility/Log.h"
+#include "lldb/lldb-defines.h"
 
 #include <optional>
 
@@ -771,6 +775,123 @@ class LoadAddressResolver {
   lldb::addr_t m_best_internal_load_address = LLDB_INVALID_ADDRESS;
 };
 
+static llvm::Expected<Module *> GetModulePtr(llvm::StringRef module, Target 
&target) {
+  uintptr_t module_ptr = 0;
+  if (module.starts_with("0x") && !module.consumeInteger(0, module_ptr)
+      && module_ptr != 0)
+    return reinterpret_cast<Module *>(module_ptr);
+
+  UUID module_uuid;
+  if (!module_uuid.SetFromStringRef(module) || !module_uuid.IsValid())
+    return llvm::createStringError("failed to create Module UUID from '%s'", 
module.data());
+
+  Module *found_module = target.GetImages().FindModule(module_uuid).get();
+  if (!found_module)
+    return llvm::createStringError("failed to find module with UUID '{0}'", 
module.data());
+
+  return found_module;
+}
+
+static lldb::addr_t
+ResolveFunctionCallLabel(llvm::StringRef label,
+                         const lldb_private::SymbolContext &sc,
+                         bool &symbol_was_missing_weak) {
+  symbol_was_missing_weak = false;
+
+  Target *target = sc.target_sp.get();
+  if (!target) {
+    LLDB_LOG(GetLog(LLDBLog::Expressions),
+             "Failed to resolve function label '{0}': target not available.",
+             label);
+    return LLDB_INVALID_ADDRESS;
+  }
+
+  if (!consumeFunctionCallLabelPrefix(label))
+    return LLDB_INVALID_ADDRESS;
+
+  if (!label.consume_front(":")) {
+    LLDB_LOG(GetLog(LLDBLog::Expressions),
+             "Failed to resolve function label '{0}': incorrect format.",
+             label);
+    return LLDB_INVALID_ADDRESS;
+  }
+
+  // Expected format at this point is: <mangled name>:<module
+  // id>:<definition/declaration DIE id>
+  // TODO: YES, GetFunction in ResolveFunction requires a definition
+  // DIE...currently regular functions work because we use definition DIEs?
+  // ...so if we have a declaration DIE, we should do a lookup by linkage_name
+  // (or name for constructors) and make sure specification matches. Then we 
use
+  // that DIE.
+  llvm::SmallVector<llvm::StringRef, 3> components;
+  label.split(components, ":");
+
+  if (components.size() != 3) {
+    LLDB_LOG(GetLog(LLDBLog::Expressions),
+             "Failed to resolve function label '{0}': incorrect format: too "
+             "many label subcomponents.",
+             label);
+    return LLDB_INVALID_ADDRESS;
+  }
+
+  const auto mangled_name = components[0];
+  const auto module = components[1];
+  auto die = components[2];
+
+  // TODO: module UID is only a Darwin concept (?)
+  auto found_module_or_err = GetModulePtr(module, *target);
+  if (!found_module_or_err) {
+    LLDB_LOG_ERROR(GetLog(LLDBLog::Expressions), 
found_module_or_err.takeError(),
+                   "Failed to resolve function label {1}: {0}",
+                   label);
+    return LLDB_INVALID_ADDRESS;
+  }
+
+  Module * found_module = *found_module_or_err;
+
+  lldb::user_id_t die_id;
+  if (die.consumeInteger(/*Radix=*/0, die_id)) {
+    LLDB_LOG(GetLog(LLDBLog::Expressions),
+             "Failed to resolve function label '{0}': failed to parse DIE ID "
+             "for '{1}'.",
+             label, components[2]);
+    return LLDB_INVALID_ADDRESS;
+  }
+ 
+  auto *symbol_file = found_module->GetSymbolFile();
+  if (!symbol_file) {
+    LLDB_LOG(GetLog(LLDBLog::Expressions),
+             "Failed to resolve function label '{0}': no SymbolFile found on "
+             "module.",
+             label);
+    return LLDB_INVALID_ADDRESS;
+  }
+
+  //// TODO: we probably don't need this
+  // auto mangled = symbol_file->GetMangledNameForUID(die_id);
+  // if (!mangled) {
+  //   LLDB_LOG(GetLog(LLDBLog::Expressions),
+  //            "Failed to resolve function label '{0}': failed to get mangled 
"
+  //            "name for DIE '{1}'.",
+  //            die_id);
+  //   return LLDB_INVALID_ADDRESS;
+  // }
+
+  // assert(mangled == mangled_name);
+
+  // TODO: API should return SC list item and we should push it back to sc_list
+  // here. In that case we wouldn't need the sc_list size checks below...
+  SymbolContextList sc_list;
+  if (auto err = symbol_file->ResolveFunctionUID(sc_list, die_id)) {
+    LLDB_LOG_ERROR(GetLog(LLDBLog::Expressions), std::move(err),
+                   "Failed to resolve function by UID: {0}");
+    return LLDB_INVALID_ADDRESS;
+  }
+
+  LoadAddressResolver resolver(target, symbol_was_missing_weak);
+  return resolver.Resolve(sc_list).value_or(LLDB_INVALID_ADDRESS);
+}
+
 lldb::addr_t
 IRExecutionUnit::FindInSymbols(const std::vector<ConstString> &names,
                                const lldb_private::SymbolContext &sc,
@@ -796,6 +917,8 @@ IRExecutionUnit::FindInSymbols(const 
std::vector<ConstString> &names,
   function_options.include_symbols = true;
   function_options.include_inlines = false;
 
+  // TODO: do we need the multiple manglings anymore?
+  // TODO: do we even need this entire loop anymore?
   for (const ConstString &name : names) {
     // The lookup order here is as follows:
     // 1) Functions in `sc.module_sp`
@@ -906,6 +1029,10 @@ lldb::addr_t IRExecutionUnit::FindInUserDefinedSymbols(
 
 lldb::addr_t IRExecutionUnit::FindSymbol(lldb_private::ConstString name,
                                          bool &missing_weak) {
+  // llvm::errs() << __func__ << " " << name.AsCString("<<UNNAMED>>") << '\n';
+  if (hasFunctionCallLabelPrefix(name.GetStringRef()))
+    return ResolveFunctionCallLabel(name, m_sym_ctx, missing_weak);
+
   std::vector<ConstString> candidate_C_names;
   std::vector<ConstString> candidate_CPlusPlus_names;
 
diff --git 
a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp 
b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp
index 9f77fbc1d2434..a6c4334bf2e59 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp
@@ -1991,7 +1991,7 @@ void 
ClangExpressionDeclMap::AddContextClassType(NameSearchContext &context,
     const bool is_artificial = false;
 
     CXXMethodDecl *method_decl = m_clang_ast_context->AddMethodToCXXRecordType(
-        copied_clang_type.GetOpaqueQualType(), "$__lldb_expr", nullptr,
+        copied_clang_type.GetOpaqueQualType(), "$__lldb_expr", std::nullopt,
         method_type, lldb::eAccessPublic, is_virtual, is_static, is_inline,
         is_explicit, is_attr_used, is_artificial);
 
diff --git a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp 
b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
index 17963c0273ba8..bd95590aed607 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
+++ b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
@@ -400,6 +400,11 @@ bool 
CPlusPlusLanguage::CxxMethodName::TrySimplifiedParse() {
   // A::B::C::fun(std::vector<T> &) const
   size_t arg_start, arg_end;
   llvm::StringRef full(m_full.GetCString());
+
+  // TODO: check for "operator" in IsTrivialBasename
+  if (full.starts_with("operator()"))
+    return false;
+
   llvm::StringRef parens("()", 2);
   if (ReverseFindMatchingChars(full, parens, arg_start, arg_end)) {
     m_arguments = full.substr(arg_start, arg_end - arg_start + 1);
@@ -438,7 +443,7 @@ bool CPlusPlusLanguage::CxxMethodName::TrySimplifiedParse() 
{
 
 void CPlusPlusLanguage::CxxMethodName::Parse() {
   if (!m_parsed && m_full) {
-    if (TrySimplifiedParse()) {
+    if (false /*TrySimplifiedParse()*/) {
       m_parse_error = false;
     } else {
       CPlusPlusNameParser parser(m_full.GetStringRef());
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp 
b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
index c76d67b47b336..069e817fba798 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
@@ -24,6 +24,7 @@
 #include "Plugins/Language/ObjC/ObjCLanguage.h"
 #include "lldb/Core/Module.h"
 #include "lldb/Core/Value.h"
+#include "lldb/Expression/Expression.h"
 #include "lldb/Host/Host.h"
 #include "lldb/Symbol/CompileUnit.h"
 #include "lldb/Symbol/Function.h"
@@ -249,6 +250,41 @@ static unsigned GetCXXMethodCVQuals(const DWARFDIE 
&subprogram,
   return cv_quals;
 }
 
+// TODO:
+// 0. Adjust FindInSymbols
+// 1. log failure paths
+// 2. What happens for functions without a linkage name? Previously we didn't
+// attach a label for those but now we would
+// 3. Unit-test
+// 4. API test (whilch checks expr and AST dump)
+static std::optional<std::string> MakeLLDBFuncAsmLabel(const DWARFDIE &die) {
+  std::optional<std::string> label;
+  char const *mangled = die.GetMangledName(/*substitute_name_allowed=*/false);
+  if (mangled)
+    label.emplace(mangled);
+
+  auto module_sp = die.GetModule();
+  if (!module_sp)
+    return label;
+
+  // Module UID is only a Darwin concept (?)
+  // If UUID is not available encode as pointer.
+  // Maybe add character to signal whether this is a pointer
+  // or UUID. Or maybe if it's not hex that implies a UUID?
+  auto module_id = module_sp->GetUUID();
+  Module * module_ptr = nullptr;
+  if (!module_id.IsValid())
+    module_ptr = module_sp.get();
+
+  const auto die_id = die.GetID();
+  if (die_id == LLDB_INVALID_UID)
+    return label;
+
+  return llvm::formatv("{0}:{1}:{2}:{3:x}", FunctionCallLabelPrefix,
+                       mangled ? mangled : "", module_ptr ? 
llvm::formatv("{0:x}", module_ptr).str() : module_id.GetAsString(), die_id)
+      .str();
+}
+
 TypeSP DWARFASTParserClang::ParseTypeFromClangModule(const SymbolContext &sc,
                                                      const DWARFDIE &die,
                                                      Log *log) {
@@ -1231,7 +1267,7 @@ std::pair<bool, TypeSP> 
DWARFASTParserClang::ParseCXXMethod(
 
   clang::CXXMethodDecl *cxx_method_decl = m_ast.AddMethodToCXXRecordType(
       class_opaque_type.GetOpaqueQualType(), attrs.name.GetCString(),
-      attrs.mangled_name, clang_type, accessibility, attrs.is_virtual,
+      MakeLLDBFuncAsmLabel(die), clang_type, accessibility, attrs.is_virtual,
       is_static, attrs.is_inline, attrs.is_explicit, is_attr_used,
       attrs.is_artificial);
 
@@ -1384,7 +1420,7 @@ DWARFASTParserClang::ParseSubroutine(const DWARFDIE &die,
             ignore_containing_context ? m_ast.GetTranslationUnitDecl()
                                       : containing_decl_ctx,
             GetOwningClangModule(die), name, clang_type, attrs.storage,
-            attrs.is_inline);
+            attrs.is_inline, MakeLLDBFuncAsmLabel(die));
         std::free(name_buf);
 
         if (has_template_params) {
@@ -1394,7 +1430,7 @@ DWARFASTParserClang::ParseSubroutine(const DWARFDIE &die,
               ignore_containing_context ? m_ast.GetTranslationUnitDecl()
                                         : containing_decl_ctx,
               GetOwningClangModule(die), attrs.name.GetStringRef(), clang_type,
-              attrs.storage, attrs.is_inline);
+              attrs.storage, attrs.is_inline, /*asm_label=*/std::nullopt);
           clang::FunctionTemplateDecl *func_template_decl =
               m_ast.CreateFunctionTemplateDecl(
                   containing_decl_ctx, GetOwningClangModule(die),
@@ -1406,20 +1442,6 @@ DWARFASTParserClang::ParseSubroutine(const DWARFDIE &die,
         lldbassert(function_decl);
 
         if (function_decl) {
-          // Attach an asm(<mangled_name>) label to the FunctionDecl.
-          // This ensures that clang::CodeGen emits function calls
-          // using symbols that are mangled according to the 
DW_AT_linkage_name.
-          // If we didn't do this, the external symbols wouldn't exactly
-          // match the mangled name LLDB knows about and the IRExecutionUnit
-          // would have to fall back to searching object files for
-          // approximately matching function names. The motivating
-          // example is generating calls to ABI-tagged template functions.
-          // This is done separately for member functions in
-          // AddMethodToCXXRecordType.
-          if (attrs.mangled_name)
-            function_decl->addAttr(clang::AsmLabelAttr::CreateImplicit(
-                m_ast.getASTContext(), attrs.mangled_name, /*literal=*/false));
-
           LinkDeclContextToDIE(function_decl, die);
 
           const clang::FunctionProtoType *function_prototype(
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp 
b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
index 5b16ce5f75138..dea0ec7ad509a 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
@@ -11,6 +11,7 @@
 #include "llvm/DebugInfo/DWARF/DWARFAddressRange.h"
 #include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h"
 #include "llvm/Support/Casting.h"
+#include "llvm/Support/Error.h"
 #include "llvm/Support/FileUtilities.h"
 #include "llvm/Support/FormatAdapters.h"
 #include "llvm/Support/Threading.h"
@@ -22,6 +23,7 @@
 #include "lldb/Core/Progress.h"
 #include "lldb/Core/Section.h"
 #include "lldb/Core/Value.h"
+#include "lldb/Symbol/SymbolContext.h"
 #include "lldb/Utility/ArchSpec.h"
 #include "lldb/Utility/LLDBLog.h"
 #include "lldb/Utility/RegularExpression.h"
@@ -73,6 +75,7 @@
 #include "ManualDWARFIndex.h"
 #include "SymbolFileDWARFDebugMap.h"
 #include "SymbolFileDWARFDwo.h"
+#include "lldb/lldb-enumerations.h"
 
 #include "llvm/DebugInfo/DWARF/DWARFContext.h"
 #include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h"
@@ -2471,6 +2474,51 @@ bool SymbolFileDWARF::ResolveFunction(const DWARFDIE 
&orig_die,
   return false;
 }
 
+llvm::Error SymbolFileDWARF::ResolveFunctionUID(SymbolContextList &sc_list,
+                                                lldb::user_id_t uid) {
+  std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
+  auto die = GetDIE(uid);
+
+  if (!die.IsValid())
+    return llvm::createStringError(
+        llvm::formatv("{0}: invalid input DIE", __func__));
+
+  // TODO: clang indexes by mangled name too...so could technically look up
+  // by mangled name....but GCC doesn't do that
+  char const *name = die.GetMangledName(/*substitute_name_allowed=*/true);
+  if (!name)
+    return llvm::createStringError(
+        llvm::formatv("{0}: input DIE has no name", __func__));
+
+  Module::LookupInfo info(ConstString(name), lldb::eFunctionNameTypeMethod,
+                          lldb::eLanguageTypeUnknown);
+  m_index->GetFunctions(info, *this, {}, [&](DWARFDIE entry) {
+    if (entry.GetAttributeValueAsUnsigned(llvm::dwarf::DW_AT_declaration, 0))
+      return true;
+
+    if (auto spec = entry.GetAttributeValueAsReferenceDIE(
+            llvm::dwarf::DW_AT_specification);
+        spec == die) {
+      die = entry;
+      return false;
+    }
+
+    return true;
+  });
+
+  if (!ResolveFunction(die, false, sc_list))
+    return llvm::createStringError(
+        llvm::formatv("{0}: failed to resolve function DIE", __func__));
+
+  if (sc_list.IsEmpty())
+    return llvm::createStringError(
+        llvm::formatv("{0}: no definition DIE found", __func__));
+
+  assert(sc_list.GetSize() == 1);
+
+  return llvm::Error::success();
+}
+
 bool SymbolFileDWARF::DIEInDeclContext(const CompilerDeclContext &decl_ctx,
                                        const DWARFDIE &die,
                                        bool only_root_namespaces) {
@@ -2958,6 +3006,10 @@ TypeSP 
SymbolFileDWARF::FindCompleteObjCDefinitionTypeForDIE(
   return type_sp;
 }
 
+// llvm::Expected<DWARFDIE>
+// SymbolFileDWARF::FindFunctionDefinitionDIE(const DWARFDIE &die) {
+// }
+
 DWARFDIE
 SymbolFileDWARF::FindDefinitionDIE(const DWARFDIE &die) {
   const char *name = die.GetName();
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h 
b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
index 2dc862cccca14..f3f6d565f3d4a 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
@@ -374,6 +374,8 @@ class SymbolFileDWARF : public SymbolFileCommon {
   SymbolFileDWARF(const SymbolFileDWARF &) = delete;
   const SymbolFileDWARF &operator=(const SymbolFileDWARF &) = delete;
 
+  // llvm::Expected<DWARFDIE> FindFunctionDefinitionDIE(const DWARFDIE &die);
+
   virtual void LoadSectionData(lldb::SectionType sect_type,
                                DWARFDataExtractor &data);
 
@@ -438,6 +440,9 @@ class SymbolFileDWARF : public SymbolFileCommon {
   bool ResolveFunction(const DWARFDIE &die, bool include_inlines,
                        SymbolContextList &sc_list);
 
+  llvm::Error ResolveFunctionUID(SymbolContextList &sc_list,
+                                 lldb::user_id_t uid) override;
+
   /// Resolve functions and (possibly) blocks for the given file address and a
   /// compile unit. The compile unit comes from the sc argument and it must be
   /// set. The results of the lookup (if any) are written back to the symbol
diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp 
b/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp
index 702ec5e5c9ea9..bce721c149fee 100644
--- a/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp
+++ b/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp
@@ -88,7 +88,7 @@ struct CreateMethodDecl : public TypeVisitorCallbacks {
                          MethodOptions::CompilerGenerated;
     function_decl = m_clang.AddMethodToCXXRecordType(
         parent_ty, proc_name,
-        /*mangled_name=*/nullptr, func_ct, /*access=*/access_type,
+        /*mangled_name=*/std::nullopt, func_ct, /*access=*/access_type,
         /*is_virtual=*/is_virtual, /*is_static=*/is_static,
         /*is_inline=*/false, /*is_explicit=*/false,
         /*is_attr_used=*/false, /*is_artificial=*/is_artificial);
@@ -903,7 +903,7 @@ PdbAstBuilder::CreateFunctionDecl(PdbCompilandSymId func_id,
     if (!function_decl) {
       function_decl = m_clang.AddMethodToCXXRecordType(
           parent_opaque_ty, func_name,
-          /*mangled_name=*/nullptr, func_ct,
+          /*mangled_name=*/std::nullopt, func_ct,
           /*access=*/lldb::AccessType::eAccessPublic,
           /*is_virtual=*/false, /*is_static=*/false,
           /*is_inline=*/false, /*is_explicit=*/false,
@@ -913,7 +913,7 @@ PdbAstBuilder::CreateFunctionDecl(PdbCompilandSymId func_id,
   } else {
     function_decl = m_clang.CreateFunctionDeclaration(
         parent, OptionalClangModuleID(), func_name, func_ct, func_storage,
-        is_inline);
+        is_inline, /*asm_label=*/std::nullopt);
     CreateFunctionParameters(func_id, *function_decl, param_count);
   }
   return function_decl;
diff --git a/lldb/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp 
b/lldb/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp
index 0090d8ff03ab6..548a3ed25111f 100644
--- a/lldb/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp
+++ b/lldb/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp
@@ -954,7 +954,8 @@ PDBASTParser::GetDeclForSymbol(const llvm::pdb::PDBSymbol 
&symbol) {
 
     auto decl = m_ast.CreateFunctionDeclaration(
         decl_context, OptionalClangModuleID(), name,
-        type->GetForwardCompilerType(), storage, func->hasInlineAttribute());
+        type->GetForwardCompilerType(), storage, func->hasInlineAttribute(),
+        /*asm_label=*/std::nullopt);
 
     std::vector<clang::ParmVarDecl *> params;
     if (std::unique_ptr<PDBSymbolTypeFunctionSig> sig = func->getSignature()) {
@@ -1446,8 +1447,8 @@ PDBASTParser::AddRecordMethod(lldb_private::SymbolFile 
&symbol_file,
   // TODO: get mangled name for the method.
   return m_ast.AddMethodToCXXRecordType(
       record_type.GetOpaqueQualType(), name.c_str(),
-      /*mangled_name*/ nullptr, method_comp_type, access, method.isVirtual(),
-      method.isStatic(), method.hasInlineAttribute(),
+      /*mangled_name*/ std::nullopt, method_comp_type, access,
+      method.isVirtual(), method.isStatic(), method.hasInlineAttribute(),
       /*is_explicit*/ false, // FIXME: Need this field in CodeView.
       /*is_attr_used*/ false,
       /*is_artificial*/ method.isCompilerGenerated());
diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp 
b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
index 82e07bb8e0ffb..2bcaca6fa6382 100644
--- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
+++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
@@ -2151,7 +2151,8 @@ std::string TypeSystemClang::GetTypeNameForDecl(const 
NamedDecl *named_decl,
 FunctionDecl *TypeSystemClang::CreateFunctionDeclaration(
     clang::DeclContext *decl_ctx, OptionalClangModuleID owning_module,
     llvm::StringRef name, const CompilerType &function_clang_type,
-    clang::StorageClass storage, bool is_inline) {
+    clang::StorageClass storage, bool is_inline,
+    std::optional<std::string> asm_label) {
   FunctionDecl *func_decl = nullptr;
   ASTContext &ast = getASTContext();
   if (!decl_ctx)
@@ -2172,6 +2173,21 @@ FunctionDecl *TypeSystemClang::CreateFunctionDeclaration(
   func_decl->setConstexprKind(isConstexprSpecified
                                   ? ConstexprSpecKind::Constexpr
                                   : ConstexprSpecKind::Unspecified);
+
+  // Attach an asm(<mangled_name>) label to the FunctionDecl.
+  // This ensures that clang::CodeGen emits function calls
+  // using symbols that are mangled according to the DW_AT_linkage_name.
+  // If we didn't do this, the external symbols wouldn't exactly
+  // match the mangled name LLDB knows about and the IRExecutionUnit
+  // would have to fall back to searching object files for
+  // approximately matching function names. The motivating
+  // example is generating calls to ABI-tagged template functions.
+  // This is done separately for member functions in
+  // AddMethodToCXXRecordType.
+  if (asm_label)
+    func_decl->addAttr(clang::AsmLabelAttr::CreateImplicit(ast, *asm_label,
+                                                           /*literal=*/false));
+
   SetOwningModule(func_decl, owning_module);
   decl_ctx->addDecl(func_decl);
 
@@ -7658,7 +7674,7 @@ TypeSystemClang::CreateParameterDeclarations(
 
 clang::CXXMethodDecl *TypeSystemClang::AddMethodToCXXRecordType(
     lldb::opaque_compiler_type_t type, llvm::StringRef name,
-    const char *mangled_name, const CompilerType &method_clang_type,
+    std::optional<std::string> asm_label, const CompilerType 
&method_clang_type,
     lldb::AccessType access, bool is_virtual, bool is_static, bool is_inline,
     bool is_explicit, bool is_attr_used, bool is_artificial) {
   if (!type || !method_clang_type.IsValid() || name.empty())
@@ -7791,10 +7807,9 @@ clang::CXXMethodDecl 
*TypeSystemClang::AddMethodToCXXRecordType(
   if (is_attr_used)
     cxx_method_decl->addAttr(clang::UsedAttr::CreateImplicit(getASTContext()));
 
-  if (mangled_name != nullptr) {
+  if (asm_label)
     cxx_method_decl->addAttr(clang::AsmLabelAttr::CreateImplicit(
-        getASTContext(), mangled_name, /*literal=*/false));
-  }
+        getASTContext(), *asm_label, /*literal=*/false));
 
   // Parameters on member function declarations in DWARF generally don't
   // have names, so we omit them when creating the ParmVarDecls.
@@ -9027,6 +9042,27 @@ bool TypeSystemClang::LayoutRecordType(
 
 // CompilerDecl override functions
 
+// TODO: remove duplication with the ResolveFunctionCallLabel in
+// IRExecutionUnit.cpp
+static std::optional<llvm::StringRef>
+GetMangledNameFromLLDBFuncLabel(llvm::StringRef label) {
+  if (!consumeFunctionCallLabelPrefix(label))
+    return {};
+
+  if (!label.consume_front(":"))
+    return {};
+
+  // Expected format at this point is: <mangled name>:<module
+  // id>:<definition/declaration DIE id>
+  llvm::SmallVector<llvm::StringRef, 3> components;
+  label.split(components, ":");
+
+  if (components.size() != 3)
+    return {};
+
+  return components[0];
+}
+
 ConstString TypeSystemClang::DeclGetName(void *opaque_decl) {
   if (opaque_decl) {
     clang::NamedDecl *nd =
@@ -9048,6 +9084,10 @@ ConstString TypeSystemClang::DeclGetMangledName(void 
*opaque_decl) {
   if (!mc || !mc->shouldMangleCXXName(nd))
     return {};
 
+  if (const auto *label = nd->getAttr<AsmLabelAttr>())
+    if (auto name = GetMangledNameFromLLDBFuncLabel(label->getLabel()))
+      return ConstString(*name);
+
   llvm::SmallVector<char, 1024> buf;
   llvm::raw_svector_ostream llvm_ostrm(buf);
   if (llvm::isa<clang::CXXConstructorDecl>(nd)) {
diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h 
b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h
index 63dee9dceded3..dcf77f9ec1cb8 100644
--- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h
+++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h
@@ -477,7 +477,8 @@ class TypeSystemClang : public TypeSystem {
   clang::FunctionDecl *CreateFunctionDeclaration(
       clang::DeclContext *decl_ctx, OptionalClangModuleID owning_module,
       llvm::StringRef name, const CompilerType &function_Type,
-      clang::StorageClass storage, bool is_inline);
+      clang::StorageClass storage, bool is_inline,
+      std::optional<std::string> asm_label);
 
   CompilerType
   CreateFunctionType(const CompilerType &result_type,
@@ -1001,7 +1002,7 @@ class TypeSystemClang : public TypeSystem {
 
   clang::CXXMethodDecl *AddMethodToCXXRecordType(
       lldb::opaque_compiler_type_t type, llvm::StringRef name,
-      const char *mangled_name, const CompilerType &method_type,
+      std::optional<std::string> mangled_name, const CompilerType &method_type,
       lldb::AccessType access, bool is_virtual, bool is_static, bool is_inline,
       bool is_explicit, bool is_attr_used, bool is_artificial);
 
diff --git a/lldb/unittests/Symbol/TestTypeSystemClang.cpp 
b/lldb/unittests/Symbol/TestTypeSystemClang.cpp
index d555d27bef958..c0428a62f7b3d 100644
--- a/lldb/unittests/Symbol/TestTypeSystemClang.cpp
+++ b/lldb/unittests/Symbol/TestTypeSystemClang.cpp
@@ -869,7 +869,7 @@ TEST_F(TestTypeSystemClang, 
TestFunctionTemplateConstruction) {
   CompilerType clang_type = m_ast->CreateFunctionType(int_type, {}, false, 0U);
   FunctionDecl *func = m_ast->CreateFunctionDeclaration(
       TU, OptionalClangModuleID(), "foo", clang_type, StorageClass::SC_None,
-      false);
+      false, std::nullopt);
   TypeSystemClang::TemplateParameterInfos empty_params;
 
   // Create the actual function template.
@@ -900,7 +900,7 @@ TEST_F(TestTypeSystemClang, 
TestFunctionTemplateInRecordConstruction) {
   // 2. It is mirroring the behavior of DWARFASTParserClang::ParseSubroutine.
   FunctionDecl *func = m_ast->CreateFunctionDeclaration(
       TU, OptionalClangModuleID(), "foo", clang_type, StorageClass::SC_None,
-      false);
+      false, std::nullopt);
   TypeSystemClang::TemplateParameterInfos empty_params;
 
   // Create the actual function template.
@@ -938,7 +938,7 @@ TEST_F(TestTypeSystemClang, 
TestDeletingImplicitCopyCstrDueToMoveCStr) {
   bool is_attr_used = false;
   bool is_artificial = false;
   m_ast->AddMethodToCXXRecordType(
-      t.GetOpaqueQualType(), class_name, nullptr, function_type,
+      t.GetOpaqueQualType(), class_name, std::nullopt, function_type,
       lldb::AccessType::eAccessPublic, is_virtual, is_static, is_inline,
       is_explicit, is_attr_used, is_artificial);
 
@@ -975,7 +975,7 @@ TEST_F(TestTypeSystemClang, 
TestNotDeletingUserCopyCstrDueToMoveCStr) {
     CompilerType function_type = m_ast->CreateFunctionType(
         return_type, args, /*variadic=*/false, /*quals*/ 0U);
     m_ast->AddMethodToCXXRecordType(
-        t.GetOpaqueQualType(), class_name, nullptr, function_type,
+        t.GetOpaqueQualType(), class_name, std::nullopt, function_type,
         lldb::AccessType::eAccessPublic, is_virtual, is_static, is_inline,
         is_explicit, is_attr_used, is_artificial);
   }
@@ -987,7 +987,7 @@ TEST_F(TestTypeSystemClang, 
TestNotDeletingUserCopyCstrDueToMoveCStr) {
         m_ast->CreateFunctionType(return_type, args,
                                   /*variadic=*/false, /*quals*/ 0U);
     m_ast->AddMethodToCXXRecordType(
-        t.GetOpaqueQualType(), class_name, nullptr, function_type,
+        t.GetOpaqueQualType(), class_name, std::nullopt, function_type,
         lldb::AccessType::eAccessPublic, is_virtual, is_static, is_inline,
         is_explicit, is_attr_used, is_artificial);
   }
@@ -1098,7 +1098,7 @@ TEST_F(TestTypeSystemClang, 
AddMethodToCXXRecordType_ParmVarDecls) {
       m_ast->CreateFunctionType(return_type, param_types,
                                 /*variadic=*/false, /*quals*/ 0U);
   m_ast->AddMethodToCXXRecordType(
-      t.GetOpaqueQualType(), "myFunc", nullptr, function_type,
+      t.GetOpaqueQualType(), "myFunc", std::nullopt, function_type,
       lldb::AccessType::eAccessPublic, is_virtual, is_static, is_inline,
       is_explicit, is_attr_used, is_artificial);
 

_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to