Skip to content

Commit

Permalink
Add a DIModule metadata node to the IR.
Browse files Browse the repository at this point in the history
It is meant to be used to record modules @imported by the current
compile unit, so a debugger an import the same modules to replicate this
environment before dropping into the expression evaluator.

DIModule is a sibling to DINamespace and behaves quite similarly.
In addition to the name of the module it also records the module
configuration details that are necessary to uniquely identify the module.
This includes the configuration macros (e.g., -DNDEBUG), the include path
where the module.map file is to be found, and the isysroot.

The idea is that the backend will turn this into a DW_TAG_module.

http://reviews.llvm.org/D9614
rdar://problem/20965932

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@241017 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
adrian-prantl committed Jun 29, 2015
1 parent 88f33c9 commit 7177647
Show file tree
Hide file tree
Showing 16 changed files with 261 additions and 0 deletions.
1 change: 1 addition & 0 deletions include/llvm/Bitcode/LLVMBitCodes.h
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@ namespace bitc {
METADATA_EXPRESSION = 29, // [distinct, n x element]
METADATA_OBJC_PROPERTY = 30, // [distinct, name, file, line, ...]
METADATA_IMPORTED_ENTITY=31, // [distinct, tag, scope, entity, line, name]
METADATA_MODULE=32, // [distinct, scope, name, ...]
};

// The constants block (CONSTANTS_BLOCK_ID) describes emission for each
Expand Down
21 changes: 21 additions & 0 deletions include/llvm/IR/DIBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -566,6 +566,20 @@ namespace llvm {
DINamespace *createNameSpace(DIScope *Scope, StringRef Name, DIFile *File,
unsigned LineNo);

/// createModule - This creates new descriptor for a module
/// with the specified parent scope.
/// @param Scope Parent scope
/// @param Name Name of this module
/// @param ConfigurationMacros
/// 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 ISysRoot The clang system root (value of -isysroot).
DIModule *createModule(DIScope *Scope, StringRef Name,
StringRef ConfigurationMacros,
StringRef IncludePath,
StringRef ISysRoot);

/// createLexicalBlockFile - This creates a descriptor for a lexical
/// block with a new file attached. This merely extends the existing
/// lexical block as it crosses a file.
Expand Down Expand Up @@ -598,6 +612,13 @@ namespace llvm {
DIImportedEntity *createImportedModule(DIScope *Context,
DIImportedEntity *NS, unsigned Line);

/// \brief Create a descriptor for an imported module.
/// @param Context The scope this module is imported into
/// @param M The module being imported here
/// @param Line Line number
DIImportedEntity *createImportedModule(DIScope *Context, DIModule *M,
unsigned Line);

/// \brief Create a descriptor for an imported function.
/// @param Context The scope this module is imported into
/// @param Decl The declaration (or definition) of a function, type, or
Expand Down
62 changes: 62 additions & 0 deletions include/llvm/IR/DebugInfoMetadata.h
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,7 @@ class DINode : public MDNode {
case DILocalVariableKind:
case DIObjCPropertyKind:
case DIImportedEntityKind:
case DIModuleKind:
return true;
}
}
Expand Down Expand Up @@ -443,6 +444,7 @@ class DIScope : public DINode {
case DILexicalBlockKind:
case DILexicalBlockFileKind:
case DINamespaceKind:
case DIModuleKind:
return true;
}
}
Expand Down Expand Up @@ -1623,6 +1625,66 @@ class DINamespace : public DIScope {
}
};

/// \brief A (clang) module that has been imported by the compile unit.
///
class DIModule : public DIScope {
friend class LLVMContextImpl;
friend class MDNode;

DIModule(LLVMContext &Context, StorageType Storage, ArrayRef<Metadata *> Ops)
: DIScope(Context, DIModuleKind, Storage, dwarf::DW_TAG_module, Ops) {}
~DIModule() {}

static DIModule *getImpl(LLVMContext &Context, DIScope *Scope,
StringRef Name, StringRef ConfigurationMacros,
StringRef IncludePath, StringRef ISysRoot,
StorageType Storage, bool ShouldCreate = true) {
return getImpl(Context, Scope, getCanonicalMDString(Context, Name),
getCanonicalMDString(Context, ConfigurationMacros),
getCanonicalMDString(Context, IncludePath),
getCanonicalMDString(Context, ISysRoot),
Storage, ShouldCreate);
}
static DIModule *getImpl(LLVMContext &Context, Metadata *Scope,
MDString *Name, MDString *ConfigurationMacros,
MDString *IncludePath, MDString *ISysRoot,
StorageType Storage, bool ShouldCreate = true);

TempDIModule cloneImpl() const {
return getTemporary(getContext(), getScope(), getName(),
getConfigurationMacros(), getIncludePath(),
getISysRoot());
}

public:
DEFINE_MDNODE_GET(DIModule, (DIScope *Scope, StringRef Name,
StringRef ConfigurationMacros, StringRef IncludePath,
StringRef ISysRoot),
(Scope, Name, ConfigurationMacros, IncludePath, ISysRoot))
DEFINE_MDNODE_GET(DIModule,
(Metadata *Scope, MDString *Name, MDString *ConfigurationMacros,
MDString *IncludePath, MDString *ISysRoot),
(Scope, Name, ConfigurationMacros, IncludePath, ISysRoot))

TempDIModule clone() const { return cloneImpl(); }

DIScope *getScope() const { return cast_or_null<DIScope>(getRawScope()); }
StringRef getName() const { return getStringOperand(1); }
StringRef getConfigurationMacros() const { return getStringOperand(2); }
StringRef getIncludePath() const { return getStringOperand(3); }
StringRef getISysRoot() 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 *getRawISysRoot() const { return getOperandAs<MDString>(4); }

static bool classof(const Metadata *MD) {
return MD->getMetadataID() == DIModuleKind;
}
};

/// \brief Base class for template parameters.
class DITemplateParameter : public DINode {
protected:
Expand Down
1 change: 1 addition & 0 deletions include/llvm/IR/Metadata.def
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ HANDLE_SPECIALIZED_MDNODE_BRANCH(DILexicalBlockBase)
HANDLE_SPECIALIZED_MDNODE_LEAF(DILexicalBlock)
HANDLE_SPECIALIZED_MDNODE_LEAF(DILexicalBlockFile)
HANDLE_SPECIALIZED_MDNODE_LEAF(DINamespace)
HANDLE_SPECIALIZED_MDNODE_LEAF(DIModule)
HANDLE_SPECIALIZED_MDNODE_BRANCH(DITemplateParameter)
HANDLE_SPECIALIZED_MDNODE_LEAF(DITemplateTypeParameter)
HANDLE_SPECIALIZED_MDNODE_LEAF(DITemplateValueParameter)
Expand Down
1 change: 1 addition & 0 deletions include/llvm/IR/Metadata.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ class Metadata {
DILexicalBlockKind,
DILexicalBlockFileKind,
DINamespaceKind,
DIModuleKind,
DITemplateTypeParameterKind,
DITemplateValueParameterKind,
DIGlobalVariableKind,
Expand Down
18 changes: 18 additions & 0 deletions lib/AsmParser/LLParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3676,6 +3676,24 @@ bool LLParser::ParseDINamespace(MDNode *&Result, bool IsDistinct) {
return false;
}

/// ParseDIModule:
/// ::= !DIModule(scope: !0, name: "SomeModule", configMacros: "-DNDEBUG",
/// includePath: "/usr/include", isysroot: "/")
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(isysroot, MDStringField, );
PARSE_MD_FIELDS();
#undef VISIT_MD_FIELDS

Result = GET_OR_DISTINCT(DIModule, (Context, scope.Val, name.Val,
configMacros.Val, includePath.Val, isysroot.Val));
return false;
}

/// ParseDITemplateTypeParameter:
/// ::= !DITemplateTypeParameter(name: "Ty", type: !1)
bool LLParser::ParseDITemplateTypeParameter(MDNode *&Result, bool IsDistinct) {
Expand Down
14 changes: 14 additions & 0 deletions lib/Bitcode/Reader/BitcodeReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1827,6 +1827,20 @@ std::error_code BitcodeReader::parseMetadata() {
NextMDValueNo++);
break;
}

case bitc::METADATA_MODULE: {
if (Record.size() != 6)
return error("Invalid record");

MDValueList.assignValue(
GET_OR_DISTINCT(DIModule, Record[0],
(Context, getMDOrNull(Record[1]),
getMDString(Record[2]), getMDString(Record[3]),
getMDString(Record[4]), getMDString(Record[5]))),
NextMDValueNo++);
break;
}

case bitc::METADATA_FILE: {
if (Record.size() != 3)
return error("Invalid record");
Expand Down
11 changes: 11 additions & 0 deletions lib/Bitcode/Writer/BitcodeWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1032,6 +1032,17 @@ static void WriteDINamespace(const DINamespace *N, const ValueEnumerator &VE,
Record.clear();
}

static void WriteDIModule(const DIModule *N, const ValueEnumerator &VE,
BitstreamWriter &Stream,
SmallVectorImpl<uint64_t> &Record, unsigned Abbrev) {
Record.push_back(N->isDistinct());
for (auto &I : N->operands())
Record.push_back(VE.getMetadataOrNullID(I));

Stream.EmitRecord(bitc::METADATA_MODULE, Record, Abbrev);
Record.clear();
}

static void WriteDITemplateTypeParameter(const DITemplateTypeParameter *N,
const ValueEnumerator &VE,
BitstreamWriter &Stream,
Expand Down
14 changes: 14 additions & 0 deletions lib/IR/AsmWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1723,6 +1723,20 @@ static void writeDINamespace(raw_ostream &Out, const DINamespace *N,
Out << ")";
}

static void writeDIModule(raw_ostream &Out, const DIModule *N,
TypePrinting *TypePrinter, SlotTracker *Machine,
const Module *Context) {
Out << "!DIModule(";
MDFieldPrinter Printer(Out, TypePrinter, Machine, Context);
Printer.printMetadata("scope", N->getRawScope(), /* ShouldSkipNull */ false);
Printer.printString("name", N->getName());
Printer.printString("configMacros", N->getConfigurationMacros());
Printer.printString("includePath", N->getIncludePath());
Printer.printString("isysroot", N->getISysRoot());
Out << ")";
}


static void writeDITemplateTypeParameter(raw_ostream &Out,
const DITemplateTypeParameter *N,
TypePrinting *TypePrinter,
Expand Down
14 changes: 14 additions & 0 deletions lib/IR/DIBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,12 @@ DIImportedEntity *DIBuilder::createImportedModule(DIScope *Context,
Context, NS, Line, StringRef(), AllImportedModules);
}

DIImportedEntity *DIBuilder::createImportedModule(DIScope *Context, DIModule *M,
unsigned Line) {
return ::createImportedModule(VMContext, dwarf::DW_TAG_imported_module,
Context, M, Line, StringRef(), AllImportedModules);
}

DIImportedEntity *DIBuilder::createImportedDeclaration(DIScope *Context,
DINode *Decl,
unsigned Line,
Expand Down Expand Up @@ -703,6 +709,14 @@ DINamespace *DIBuilder::createNameSpace(DIScope *Scope, StringRef Name,
LineNo);
}

DIModule *DIBuilder::createModule(DIScope *Scope, StringRef Name,
StringRef ConfigurationMacros,
StringRef IncludePath,
StringRef ISysRoot) {
return DIModule::get(VMContext, getNonCompileUnitScope(Scope), Name,
ConfigurationMacros, IncludePath, ISysRoot);
}

DILexicalBlockFile *DIBuilder::createLexicalBlockFile(DIScope *Scope,
DIFile *File,
unsigned Discriminator) {
Expand Down
4 changes: 4 additions & 0 deletions lib/IR/DebugInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,8 @@ void DebugInfoFinder::processModule(const Module &M) {
processSubprogram(SP);
else if (auto *NS = dyn_cast<DINamespace>(Entity))
processScope(NS->getScope());
else if (auto *M = dyn_cast<DIModule>(Entity))
processScope(M->getScope());
}
}
}
Expand Down Expand Up @@ -201,6 +203,8 @@ void DebugInfoFinder::processScope(DIScope *Scope) {
processScope(LB->getScope());
} else if (auto *NS = dyn_cast<DINamespace>(Scope)) {
processScope(NS->getScope());
} else if (auto *M = dyn_cast<DIModule>(Scope)) {
processScope(M->getScope());
}
}

Expand Down
17 changes: 17 additions & 0 deletions lib/IR/DebugInfoMetadata.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,9 @@ DIScopeRef DIScope::getScope() const {
if (auto *NS = dyn_cast<DINamespace>(this))
return DIScopeRef(NS->getScope());

if (auto *M = dyn_cast<DIModule>(this))
return DIScopeRef(M->getScope());

assert((isa<DIFile>(this) || isa<DICompileUnit>(this)) &&
"Unhandled type of scope.");
return nullptr;
Expand All @@ -150,6 +153,8 @@ StringRef DIScope::getName() const {
return SP->getName();
if (auto *NS = dyn_cast<DINamespace>(this))
return NS->getName();
if (auto *M = dyn_cast<DIModule>(this))
return M->getName();
assert((isa<DILexicalBlockBase>(this) || isa<DIFile>(this) ||
isa<DICompileUnit>(this)) &&
"Unhandled type of scope.");
Expand Down Expand Up @@ -410,6 +415,18 @@ DINamespace *DINamespace::getImpl(LLVMContext &Context, Metadata *Scope,
DEFINE_GETIMPL_STORE(DINamespace, (Line), Ops);
}

DIModule *DIModule::getImpl(LLVMContext &Context, Metadata *Scope,
MDString *Name, MDString *ConfigurationMacros,
MDString *IncludePath, MDString *ISysRoot,
StorageType Storage, bool ShouldCreate) {
assert(isCanonical(Name) && "Expected canonical MDString");
DEFINE_GETIMPL_LOOKUP(DIModule,
(Scope, getString(Name), getString(ConfigurationMacros),
getString(IncludePath), getString(ISysRoot)));
Metadata *Ops[] = {Scope, Name, ConfigurationMacros, IncludePath, ISysRoot};
DEFINE_GETIMPL_STORE_NO_CONSTRUCTOR_ARGS(DIModule, Ops);
}

DITemplateTypeParameter *DITemplateTypeParameter::getImpl(LLVMContext &Context,
MDString *Name,
Metadata *Type,
Expand Down
29 changes: 29 additions & 0 deletions lib/IR/LLVMContextImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -651,6 +651,35 @@ template <> struct MDNodeKeyImpl<DINamespace> {
}
};

template <> struct MDNodeKeyImpl<DIModule> {
Metadata *Scope;
StringRef Name;
StringRef ConfigurationMacros;
StringRef IncludePath;
StringRef ISysRoot;
MDNodeKeyImpl(Metadata *Scope, StringRef Name,
StringRef ConfigurationMacros,
StringRef IncludePath,
StringRef ISysRoot)
: Scope(Scope), Name(Name), ConfigurationMacros(ConfigurationMacros),
IncludePath(IncludePath), ISysRoot(ISysRoot) {}
MDNodeKeyImpl(const DIModule *N)
: Scope(N->getRawScope()), Name(N->getName()),
ConfigurationMacros(N->getConfigurationMacros()),
IncludePath(N->getIncludePath()), ISysRoot(N->getISysRoot()) {}

bool isKeyOf(const DIModule *RHS) const {
return Scope == RHS->getRawScope() && Name == RHS->getName() &&
ConfigurationMacros == RHS->getConfigurationMacros() &&
IncludePath == RHS->getIncludePath() &&
ISysRoot == RHS->getISysRoot();
}
unsigned getHashValue() const {
return hash_combine(Scope, Name,
ConfigurationMacros, IncludePath, ISysRoot);
}
};

template <> struct MDNodeKeyImpl<DITemplateTypeParameter> {
StringRef Name;
Metadata *Type;
Expand Down
5 changes: 5 additions & 0 deletions lib/IR/Verifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1017,6 +1017,11 @@ void Verifier::visitDINamespace(const DINamespace &N) {
Assert(isa<DIScope>(S), "invalid scope ref", &N, S);
}

void Verifier::visitDIModule(const DIModule &N) {
Assert(N.getTag() == dwarf::DW_TAG_module, "invalid tag", &N);
Assert(!N.getName().empty(), "anonymous module", &N);
}

void Verifier::visitDITemplateParameter(const DITemplateParameter &N) {
Assert(isTypeRef(N, N.getType()), "invalid type ref", &N, N.getType());
}
Expand Down
15 changes: 15 additions & 0 deletions test/Assembler/dimodule.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
; 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}

!0 = distinct !{}

; CHECK: !1 = !DIModule(scope: !0, name: "Module")
!1 = !DIModule(scope: !0, name: "Module")

; CHECK: !2 = !DIModule(scope: !0, name: "Module", configMacros: "-DNDEBUG", includePath: "/usr/include", isysroot: "/")
!2 = !DIModule(scope: !0, name: "Module", configMacros: "-DNDEBUG", includePath: "/usr/include", isysroot: "/")

!3 = !DIModule(scope: !0, name: "Module", configMacros: "")
Loading

0 comments on commit 7177647

Please sign in to comment.