[llvm] d5180ea - Add debug info support for Swift/Clang APINotes.
Adrian Prantl via llvm-commits
llvm-commits at lists.llvm.org
Wed Mar 11 18:47:39 PDT 2020
Author: Adrian Prantl
Date: 2020-03-11T18:47:30-07:00
New Revision: d5180ea134796f96b0c6c4ab23c592d58f25733d
URL: https://github.com/llvm/llvm-project/commit/d5180ea134796f96b0c6c4ab23c592d58f25733d
DIFF: https://github.com/llvm/llvm-project/commit/d5180ea134796f96b0c6c4ab23c592d58f25733d.diff
LOG: Add debug info support for Swift/Clang APINotes.
In order for dsymutil to collect .apinotes files (which capture
attributes such as nullability, Swift import names, and availability),
I want to propose adding an apinotes: field to DIModule that gets
translated into a DW_AT_LLVM_apinotes (path) nested inside
DW_TAG_module. This will be primarily used by LLDB to indirectly
extract the Swift names of Clang declarations that were deserialized
from DWARF.
<rdar://problem/59514626>
Differential Revision: https://reviews.llvm.org/D75585
Added:
Modified:
llvm/include/llvm-c/DebugInfo.h
llvm/include/llvm/BinaryFormat/Dwarf.def
llvm/include/llvm/IR/DIBuilder.h
llvm/include/llvm/IR/DebugInfoMetadata.h
llvm/lib/AsmParser/LLParser.cpp
llvm/lib/Bitcode/Reader/MetadataLoader.cpp
llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
llvm/lib/IR/AsmWriter.cpp
llvm/lib/IR/DIBuilder.cpp
llvm/lib/IR/DebugInfo.cpp
llvm/lib/IR/DebugInfoMetadata.cpp
llvm/lib/IR/LLVMContextImpl.h
llvm/test/Assembler/dimodule.ll
llvm/test/DebugInfo/X86/DIModule.ll
llvm/tools/llvm-c-test/debuginfo.c
llvm/unittests/IR/MetadataTest.cpp
Removed:
################################################################################
diff --git a/llvm/include/llvm-c/DebugInfo.h b/llvm/include/llvm-c/DebugInfo.h
index f17517be601e..61702253f69b 100644
--- a/llvm/include/llvm-c/DebugInfo.h
+++ b/llvm/include/llvm-c/DebugInfo.h
@@ -288,12 +288,15 @@ LLVMDIBuilderCreateFile(LLVMDIBuilderRef Builder, const char *Filename,
* \param ConfigMacrosLen The length of the C string passed to \c ConfigMacros.
* \param IncludePath The path to the module map file.
* \param IncludePathLen The length of the C string passed to \c IncludePath.
+ * \param APINotesFile The path to an API notes file for the module.
+ * \param APINotesFileLen The length of the C string passed to \c APINotestFile.
*/
LLVMMetadataRef
LLVMDIBuilderCreateModule(LLVMDIBuilderRef Builder, LLVMMetadataRef ParentScope,
const char *Name, size_t NameLen,
const char *ConfigMacros, size_t ConfigMacrosLen,
- const char *IncludePath, size_t IncludePathLen);
+ const char *IncludePath, size_t IncludePathLen,
+ const char *APINotestFile, size_t APINotestFileLen);
/**
* Creates a new descriptor for a namespace with the specified parent scope.
diff --git a/llvm/include/llvm/BinaryFormat/Dwarf.def b/llvm/include/llvm/BinaryFormat/Dwarf.def
index 287b70af1bef..f5078b3a7291 100644
--- a/llvm/include/llvm/BinaryFormat/Dwarf.def
+++ b/llvm/include/llvm/BinaryFormat/Dwarf.def
@@ -412,7 +412,11 @@ HANDLE_DW_AT(0x3e00, LLVM_include_path, 0, LLVM)
HANDLE_DW_AT(0x3e01, LLVM_config_macros, 0, LLVM)
HANDLE_DW_AT(0x3e02, LLVM_sysroot, 0, LLVM)
HANDLE_DW_AT(0x3e03, LLVM_tag_offset, 0, LLVM)
+// The missing numbers here are reserved for ptrauth support.
+HANDLE_DW_AT(0x3e07, LLVM_apinotes, 0, APPLE)
+
// Apple extensions.
+
HANDLE_DW_AT(0x3fe1, APPLE_optimized, 0, APPLE)
HANDLE_DW_AT(0x3fe2, APPLE_flags, 0, APPLE)
HANDLE_DW_AT(0x3fe3, APPLE_isa, 0, APPLE)
diff --git a/llvm/include/llvm/IR/DIBuilder.h b/llvm/include/llvm/IR/DIBuilder.h
index 82a9c5e67d5c..888512197617 100644
--- a/llvm/include/llvm/IR/DIBuilder.h
+++ b/llvm/include/llvm/IR/DIBuilder.h
@@ -741,9 +741,10 @@ namespace llvm {
/// A space-separated shell-quoted list of -D macro
/// definitions as they would appear on a command line.
/// \param IncludePath The path to the module map file.
+ /// \param APINotesFile The path to an API notes file for this module.
DIModule *createModule(DIScope *Scope, StringRef Name,
StringRef ConfigurationMacros,
- StringRef IncludePath);
+ StringRef IncludePath, StringRef APINotesFile = {});
/// This creates a descriptor for a lexical block with a new file
/// attached. This merely extends the existing
diff --git a/llvm/include/llvm/IR/DebugInfoMetadata.h b/llvm/include/llvm/IR/DebugInfoMetadata.h
index 3bf78ba02592..221ff519e2f5 100644
--- a/llvm/include/llvm/IR/DebugInfoMetadata.h
+++ b/llvm/include/llvm/IR/DebugInfoMetadata.h
@@ -2089,31 +2089,38 @@ class DIModule : public DIScope {
static DIModule *getImpl(LLVMContext &Context, DIScope *Scope, StringRef Name,
StringRef ConfigurationMacros, StringRef IncludePath,
- StorageType Storage, bool ShouldCreate = true) {
+ StringRef APINotesFile, StorageType Storage,
+ bool ShouldCreate = true) {
return getImpl(Context, Scope, getCanonicalMDString(Context, Name),
getCanonicalMDString(Context, ConfigurationMacros),
getCanonicalMDString(Context, IncludePath),
+ getCanonicalMDString(Context, APINotesFile),
Storage, ShouldCreate);
}
static DIModule *getImpl(LLVMContext &Context, Metadata *Scope,
MDString *Name, MDString *ConfigurationMacros,
- MDString *IncludePath, StorageType Storage,
- bool ShouldCreate = true);
+ MDString *IncludePath, MDString *APINotesFile,
+ StorageType Storage, bool ShouldCreate = true);
TempDIModule cloneImpl() const {
return getTemporary(getContext(), getScope(), getName(),
- getConfigurationMacros(), getIncludePath());
+ getConfigurationMacros(), getIncludePath(),
+ getAPINotesFile());
}
public:
DEFINE_MDNODE_GET(DIModule,
(DIScope * Scope, StringRef Name,
- StringRef ConfigurationMacros, StringRef IncludePath),
- (Scope, Name, ConfigurationMacros, IncludePath))
+ StringRef ConfigurationMacros, StringRef IncludePath,
+ StringRef APINotesFile),
+ (Scope, Name, ConfigurationMacros, IncludePath,
+ APINotesFile))
DEFINE_MDNODE_GET(DIModule,
- (Metadata *Scope, MDString *Name, MDString *ConfigurationMacros,
- MDString *IncludePath),
- (Scope, Name, ConfigurationMacros, IncludePath))
+ (Metadata * Scope, MDString *Name,
+ MDString *ConfigurationMacros, MDString *IncludePath,
+ MDString *APINotesFile),
+ (Scope, Name, ConfigurationMacros, IncludePath,
+ APINotesFile))
TempDIModule clone() const { return cloneImpl(); }
@@ -2121,11 +2128,13 @@ class DIModule : public DIScope {
StringRef getName() const { return getStringOperand(1); }
StringRef getConfigurationMacros() const { return getStringOperand(2); }
StringRef getIncludePath() const { return getStringOperand(3); }
+ StringRef getAPINotesFile() const { return getStringOperand(4); }
Metadata *getRawScope() const { return getOperand(0); }
MDString *getRawName() const { return getOperandAs<MDString>(1); }
MDString *getRawConfigurationMacros() const { return getOperandAs<MDString>(2); }
MDString *getRawIncludePath() const { return getOperandAs<MDString>(3); }
+ MDString *getRawAPINotesFile() const { return getOperandAs<MDString>(4); }
static bool classof(const Metadata *MD) {
return MD->getMetadataID() == DIModuleKind;
diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp
index 86313cddfdc4..d219f607410b 100644
--- a/llvm/lib/AsmParser/LLParser.cpp
+++ b/llvm/lib/AsmParser/LLParser.cpp
@@ -4827,18 +4827,20 @@ bool LLParser::ParseDIMacroFile(MDNode *&Result, bool IsDistinct) {
/// ParseDIModule:
/// ::= !DIModule(scope: !0, name: "SomeModule", configMacros: "-DNDEBUG",
-/// includePath: "/usr/include")
+/// includePath: "/usr/include", apinotes: "module.apinotes")
bool LLParser::ParseDIModule(MDNode *&Result, bool IsDistinct) {
#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \
REQUIRED(scope, MDField, ); \
REQUIRED(name, MDStringField, ); \
OPTIONAL(configMacros, MDStringField, ); \
- OPTIONAL(includePath, MDStringField, );
+ OPTIONAL(includePath, MDStringField, ); \
+ OPTIONAL(apinotes, MDStringField, );
PARSE_MD_FIELDS();
#undef VISIT_MD_FIELDS
- Result = GET_OR_DISTINCT(DIModule, (Context, scope.Val, name.Val,
- configMacros.Val, includePath.Val));
+ Result =
+ GET_OR_DISTINCT(DIModule, (Context, scope.Val, name.Val, configMacros.Val,
+ includePath.Val, apinotes.Val));
return false;
}
diff --git a/llvm/lib/Bitcode/Reader/MetadataLoader.cpp b/llvm/lib/Bitcode/Reader/MetadataLoader.cpp
index 17778e73f2f0..c1fa91d0672d 100644
--- a/llvm/lib/Bitcode/Reader/MetadataLoader.cpp
+++ b/llvm/lib/Bitcode/Reader/MetadataLoader.cpp
@@ -1418,14 +1418,15 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata(
}
case bitc::METADATA_MODULE: {
- if (Record.size() < 5 || Record.size() > 6)
+ if (Record.size() < 5 || Record.size() > 7)
return error("Invalid record");
IsDistinct = Record[0];
MetadataList.assignValue(
- GET_OR_DISTINCT(
- DIModule, (Context, getMDOrNull(Record[1]), getMDString(Record[2]),
- getMDString(Record[3]), getMDString(Record[4]))),
+ GET_OR_DISTINCT(DIModule,
+ (Context, getMDOrNull(Record[1]),
+ getMDString(Record[2]), getMDString(Record[3]),
+ getMDString(Record[4]), getMDString(Record[5]))),
NextMetadataNo);
NextMetadataNo++;
break;
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
index 134ef74b2704..91362644da21 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
@@ -1126,6 +1126,8 @@ DIE *DwarfUnit::getOrCreateModule(const DIModule *M) {
M->getConfigurationMacros());
if (!M->getIncludePath().empty())
addString(MDie, dwarf::DW_AT_LLVM_include_path, M->getIncludePath());
+ if (!M->getAPINotesFile().empty())
+ addString(MDie, dwarf::DW_AT_LLVM_apinotes, M->getAPINotesFile());
return &MDie;
}
diff --git a/llvm/lib/IR/AsmWriter.cpp b/llvm/lib/IR/AsmWriter.cpp
index ea603a699822..733fc10c2ee3 100644
--- a/llvm/lib/IR/AsmWriter.cpp
+++ b/llvm/lib/IR/AsmWriter.cpp
@@ -2061,6 +2061,7 @@ static void writeDIModule(raw_ostream &Out, const DIModule *N,
Printer.printString("name", N->getName());
Printer.printString("configMacros", N->getConfigurationMacros());
Printer.printString("includePath", N->getIncludePath());
+ Printer.printString("apinotes", N->getAPINotesFile());
Out << ")";
}
diff --git a/llvm/lib/IR/DIBuilder.cpp b/llvm/lib/IR/DIBuilder.cpp
index 2fcdcd99e3db..b6446f47e03e 100644
--- a/llvm/lib/IR/DIBuilder.cpp
+++ b/llvm/lib/IR/DIBuilder.cpp
@@ -831,9 +831,10 @@ DINamespace *DIBuilder::createNameSpace(DIScope *Scope, StringRef Name,
DIModule *DIBuilder::createModule(DIScope *Scope, StringRef Name,
StringRef ConfigurationMacros,
- StringRef IncludePath) {
+ StringRef IncludePath,
+ StringRef APINotesFile) {
return DIModule::get(VMContext, getNonCompileUnitScope(Scope), Name,
- ConfigurationMacros, IncludePath);
+ ConfigurationMacros, IncludePath, APINotesFile);
}
DILexicalBlockFile *DIBuilder::createLexicalBlockFile(DIScope *Scope,
diff --git a/llvm/lib/IR/DebugInfo.cpp b/llvm/lib/IR/DebugInfo.cpp
index f893ea997a8e..aaa8443769af 100644
--- a/llvm/lib/IR/DebugInfo.cpp
+++ b/llvm/lib/IR/DebugInfo.cpp
@@ -791,11 +791,13 @@ LLVMMetadataRef
LLVMDIBuilderCreateModule(LLVMDIBuilderRef Builder, LLVMMetadataRef ParentScope,
const char *Name, size_t NameLen,
const char *ConfigMacros, size_t ConfigMacrosLen,
- const char *IncludePath, size_t IncludePathLen) {
+ const char *IncludePath, size_t IncludePathLen,
+ const char *APINotesFile, size_t APINotesFileLen) {
return wrap(unwrap(Builder)->createModule(
unwrapDI<DIScope>(ParentScope), StringRef(Name, NameLen),
StringRef(ConfigMacros, ConfigMacrosLen),
- StringRef(IncludePath, IncludePathLen)));
+ StringRef(IncludePath, IncludePathLen),
+ StringRef(APINotesFile, APINotesFileLen)));
}
LLVMMetadataRef LLVMDIBuilderCreateNameSpace(LLVMDIBuilderRef Builder,
diff --git a/llvm/lib/IR/DebugInfoMetadata.cpp b/llvm/lib/IR/DebugInfoMetadata.cpp
index 48e38dbb2b0e..0c0ea50dde70 100644
--- a/llvm/lib/IR/DebugInfoMetadata.cpp
+++ b/llvm/lib/IR/DebugInfoMetadata.cpp
@@ -717,12 +717,13 @@ DICommonBlock *DICommonBlock::getImpl(LLVMContext &Context, Metadata *Scope,
DIModule *DIModule::getImpl(LLVMContext &Context, Metadata *Scope,
MDString *Name, MDString *ConfigurationMacros,
- MDString *IncludePath, StorageType Storage,
- bool ShouldCreate) {
+ MDString *IncludePath, MDString *APINotesFile,
+ StorageType Storage, bool ShouldCreate) {
assert(isCanonical(Name) && "Expected canonical MDString");
- DEFINE_GETIMPL_LOOKUP(DIModule,
- (Scope, Name, ConfigurationMacros, IncludePath));
- Metadata *Ops[] = {Scope, Name, ConfigurationMacros, IncludePath};
+ DEFINE_GETIMPL_LOOKUP(
+ DIModule, (Scope, Name, ConfigurationMacros, IncludePath, APINotesFile));
+ Metadata *Ops[] = {Scope, Name, ConfigurationMacros, IncludePath,
+ APINotesFile};
DEFINE_GETIMPL_STORE_NO_CONSTRUCTOR_ARGS(DIModule, Ops);
}
diff --git a/llvm/lib/IR/LLVMContextImpl.h b/llvm/lib/IR/LLVMContextImpl.h
index 7f324b103997..e136bd54dd90 100644
--- a/llvm/lib/IR/LLVMContextImpl.h
+++ b/llvm/lib/IR/LLVMContextImpl.h
@@ -819,20 +819,23 @@ template <> struct MDNodeKeyImpl<DIModule> {
MDString *Name;
MDString *ConfigurationMacros;
MDString *IncludePath;
+ MDString *APINotesFile;
MDNodeKeyImpl(Metadata *Scope, MDString *Name, MDString *ConfigurationMacros,
- MDString *IncludePath)
+ MDString *IncludePath, MDString *APINotesFile)
: Scope(Scope), Name(Name), ConfigurationMacros(ConfigurationMacros),
- IncludePath(IncludePath) {}
+ IncludePath(IncludePath), APINotesFile(APINotesFile) {}
MDNodeKeyImpl(const DIModule *N)
: Scope(N->getRawScope()), Name(N->getRawName()),
ConfigurationMacros(N->getRawConfigurationMacros()),
- IncludePath(N->getRawIncludePath()) {}
+ IncludePath(N->getRawIncludePath()),
+ APINotesFile(N->getRawAPINotesFile()) {}
bool isKeyOf(const DIModule *RHS) const {
return Scope == RHS->getRawScope() && Name == RHS->getRawName() &&
ConfigurationMacros == RHS->getRawConfigurationMacros() &&
- IncludePath == RHS->getRawIncludePath();
+ IncludePath == RHS->getRawIncludePath() &&
+ APINotesFile == RHS->getRawAPINotesFile();
}
unsigned getHashValue() const {
diff --git a/llvm/test/Assembler/dimodule.ll b/llvm/test/Assembler/dimodule.ll
index cc5f013472c9..c3802ea1265d 100644
--- a/llvm/test/Assembler/dimodule.ll
+++ b/llvm/test/Assembler/dimodule.ll
@@ -1,8 +1,8 @@
; RUN: llvm-as < %s | llvm-dis | llvm-as | llvm-dis | FileCheck %s
; RUN: verify-uselistorder %s
-; CHECK: !named = !{!0, !1, !2, !1}
-!named = !{!0, !1, !2, !3}
+; CHECK: !named = !{!0, !1, !2, !1, !3}
+!named = !{!0, !1, !2, !3, !4}
!0 = distinct !{}
@@ -13,3 +13,6 @@
!2 = !DIModule(scope: !0, name: "Module", configMacros: "-DNDEBUG", includePath: "/usr/include")
!3 = !DIModule(scope: !0, name: "Module", configMacros: "")
+
+; CHECK: !3 = !DIModule(scope: !0, name: "Module", configMacros: "-DNDEBUG", includePath: "/usr/include", apinotes: "/tmp/m.apinotes")
+!4 = !DIModule(scope: !0, name: "Module", configMacros: "-DNDEBUG", includePath: "/usr/include", apinotes: "/tmp/m.apinotes")
diff --git a/llvm/test/DebugInfo/X86/DIModule.ll b/llvm/test/DebugInfo/X86/DIModule.ll
index 4aa785abefbc..fadd38ded160 100644
--- a/llvm/test/DebugInfo/X86/DIModule.ll
+++ b/llvm/test/DebugInfo/X86/DIModule.ll
@@ -9,6 +9,7 @@
; CHECK-NEXT: DW_AT_name {{.*}}"DebugModule"
; CHECK-NEXT: DW_AT_LLVM_config_macros {{.*}}"-DMODULES=0"
; CHECK-NEXT: DW_AT_LLVM_include_path {{.*}}"/llvm/tools/clang/test/Modules/Inputs"
+; CHECK-NEXT: DW_AT_LLVM_apinotes {{.*}}"m.apinotes"
target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-apple-macosx"
@@ -22,7 +23,7 @@ target triple = "x86_64-apple-macosx"
!2 = !{}
!3 = !{!4}
!4 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !0, entity: !5, file: !1, line: 5)
-!5 = !DIModule(scope: null, name: "DebugModule", configMacros: "-DMODULES=0", includePath: "/llvm/tools/clang/test/Modules/Inputs")
+!5 = !DIModule(scope: null, name: "DebugModule", configMacros: "-DMODULES=0", includePath: "/llvm/tools/clang/test/Modules/Inputs", apinotes: "m.apinotes")
!6 = !{i32 2, !"Dwarf Version", i32 4}
!7 = !{i32 2, !"Debug Info Version", i32 3}
!8 = !{!"LLVM version 3.7.0"}
diff --git a/llvm/tools/llvm-c-test/debuginfo.c b/llvm/tools/llvm-c-test/debuginfo.c
index 6ae1f19764cf..994bd5300072 100644
--- a/llvm/tools/llvm-c-test/debuginfo.c
+++ b/llvm/tools/llvm-c-test/debuginfo.c
@@ -44,13 +44,15 @@ int llvm_test_dibuilder(void) {
LLVMDIBuilderCreateModule(DIB, CompileUnit,
"llvm-c-test", 11,
"", 0,
- "/test/include/llvm-c-test.h", 27);
+ "/test/include/llvm-c-test.h", 27,
+ "", 0);
LLVMMetadataRef OtherModule =
LLVMDIBuilderCreateModule(DIB, CompileUnit,
"llvm-c-test-import", 18,
"", 0,
- "/test/include/llvm-c-test-import.h", 34);
+ "/test/include/llvm-c-test-import.h", 34,
+ "", 0);
LLVMMetadataRef ImportedModule =
LLVMDIBuilderCreateImportedModuleFromModule(DIB, Module, OtherModule,
File, 42);
diff --git a/llvm/unittests/IR/MetadataTest.cpp b/llvm/unittests/IR/MetadataTest.cpp
index 0f7109749399..e886c77ebb6f 100644
--- a/llvm/unittests/IR/MetadataTest.cpp
+++ b/llvm/unittests/IR/MetadataTest.cpp
@@ -2057,19 +2057,28 @@ TEST_F(DIModuleTest, get) {
StringRef Name = "module";
StringRef ConfigMacro = "-DNDEBUG";
StringRef Includes = "-I.";
+ StringRef APINotes = "/tmp/m.apinotes";
- auto *N = DIModule::get(Context, Scope, Name, ConfigMacro, Includes);
+ auto *N = DIModule::get(Context, Scope, Name, ConfigMacro, Includes, APINotes);
EXPECT_EQ(dwarf::DW_TAG_module, N->getTag());
EXPECT_EQ(Scope, N->getScope());
EXPECT_EQ(Name, N->getName());
EXPECT_EQ(ConfigMacro, N->getConfigurationMacros());
EXPECT_EQ(Includes, N->getIncludePath());
- EXPECT_EQ(N, DIModule::get(Context, Scope, Name, ConfigMacro, Includes));
- EXPECT_NE(N, DIModule::get(Context, getFile(), Name, ConfigMacro, Includes));
- EXPECT_NE(N, DIModule::get(Context, Scope, "other", ConfigMacro, Includes));
- EXPECT_NE(N, DIModule::get(Context, Scope, Name, "other", Includes));
- EXPECT_NE(N, DIModule::get(Context, Scope, Name, ConfigMacro, "other"));
+ EXPECT_EQ(APINotes, N->getAPINotesFile());
+ EXPECT_EQ(
+ N, DIModule::get(Context, Scope, Name, ConfigMacro, Includes, APINotes));
+ EXPECT_NE(N, DIModule::get(Context, getFile(), Name, ConfigMacro, Includes,
+ APINotes));
+ EXPECT_NE(N, DIModule::get(Context, Scope, "other", ConfigMacro, Includes,
+ APINotes));
+ EXPECT_NE(N,
+ DIModule::get(Context, Scope, Name, "other", Includes, APINotes));
+ EXPECT_NE(
+ N, DIModule::get(Context, Scope, Name, ConfigMacro, "other", APINotes));
+ EXPECT_NE(
+ N, DIModule::get(Context, Scope, Name, ConfigMacro, Includes, "other"));
TempDIModule Temp = N->clone();
EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp)));
More information about the llvm-commits
mailing list