Skip to content

Commit

Permalink
[IR] Remove the DIExpression field from DIGlobalVariable.
Browse files Browse the repository at this point in the history
This patch implements PR31013 by introducing a
DIGlobalVariableExpression that holds a pair of DIGlobalVariable and
DIExpression.

Currently, DIGlobalVariables holds a DIExpression. This is not the
best way to model this:

(1) The DIGlobalVariable should describe the source level variable,
    not how to get to its location.

(2) It makes it unsafe/hard to update the expressions when we call
    replaceExpression on the DIGLobalVariable.

(3) It makes it impossible to represent a global variable that is in
    more than one location (e.g., a variable with multiple
    DW_OP_LLVM_fragment-s).  We also moved away from attaching the
    DIExpression to DILocalVariable for the same reasons.

This reapplies r289902 with additional testcase upgrades and a change
to the Bitcode record for DIGlobalVariable, that makes upgrading the
old format unambiguous also for variables without DIExpressions.

<rdar://problem/29250149>
https://llvm.org/bugs/show_bug.cgi?id=31013
Differential Revision: https://reviews.llvm.org/D26769

llvm-svn: 290153
  • Loading branch information
adrian-prantl committed Dec 20, 2016
1 parent 6db6efd commit bceaaa9
Show file tree
Hide file tree
Showing 191 changed files with 1,060 additions and 681 deletions.
1 change: 1 addition & 0 deletions llvm/include/llvm/Bitcode/LLVMBitCodes.h
Expand Up @@ -252,6 +252,7 @@ enum MetadataCodes {
METADATA_MACRO_FILE = 34, // [distinct, macinfo, line, file, ...]
METADATA_STRINGS = 35, // [count, offset] blob([lengths][chars])
METADATA_GLOBAL_DECL_ATTACHMENT = 36, // [valueid, n x [id, mdnode]]
METADATA_GLOBAL_VAR_EXPR = 37, // [distinct, var, expr]
};

// The constants block (CONSTANTS_BLOCK_ID) describes emission for each
Expand Down
19 changes: 8 additions & 11 deletions llvm/include/llvm/IR/DIBuilder.h
Expand Up @@ -449,8 +449,7 @@ namespace llvm {
/// implicitly uniques the values returned.
DISubrange *getOrCreateSubrange(int64_t Lo, int64_t Count);

/// Create a new descriptor for the specified
/// variable.
/// Create a new descriptor for the specified variable.
/// \param Context Variable scope.
/// \param Name Name of the variable.
/// \param LinkageName Mangled name of the variable.
Expand All @@ -464,20 +463,18 @@ namespace llvm {
/// \param Decl Reference to the corresponding declaration.
/// \param AlignInBits Variable alignment(or 0 if no alignment attr was
/// specified)
DIGlobalVariable *createGlobalVariable(DIScope *Context, StringRef Name,
StringRef LinkageName, DIFile *File,
unsigned LineNo, DIType *Ty,
bool isLocalToUnit,
DIExpression *Expr = nullptr,
MDNode *Decl = nullptr,
uint32_t AlignInBits = 0);
DIGlobalVariableExpression *createGlobalVariableExpression(
DIScope *Context, StringRef Name, StringRef LinkageName, DIFile *File,
unsigned LineNo, DIType *Ty, bool isLocalToUnit,
DIExpression *Expr = nullptr, MDNode *Decl = nullptr,
uint32_t AlignInBits = 0);

/// Identical to createGlobalVariable
/// except that the resulting DbgNode is temporary and meant to be RAUWed.
DIGlobalVariable *createTempGlobalVariableFwdDecl(
DIScope *Context, StringRef Name, StringRef LinkageName, DIFile *File,
unsigned LineNo, DIType *Ty, bool isLocalToUnit, DIExpression *Expr,
MDNode *Decl = nullptr, uint32_t AlignInBits = 0);
unsigned LineNo, DIType *Ty, bool isLocalToUnit, MDNode *Decl = nullptr,
uint32_t AlignInBits = 0);

/// Create a new descriptor for an auto variable. This is a local variable
/// that is not a subprogram parameter.
Expand Down
10 changes: 5 additions & 5 deletions llvm/include/llvm/IR/DebugInfo.h
Expand Up @@ -89,7 +89,7 @@ class DebugInfoFinder {
void processSubprogram(DISubprogram *SP);
void processScope(DIScope *Scope);
bool addCompileUnit(DICompileUnit *CU);
bool addGlobalVariable(DIGlobalVariable *DIG);
bool addGlobalVariable(DIGlobalVariableExpression *DIG);
bool addSubprogram(DISubprogram *SP);
bool addType(DIType *DT);
bool addScope(DIScope *Scope);
Expand All @@ -98,8 +98,8 @@ class DebugInfoFinder {
typedef SmallVectorImpl<DICompileUnit *>::const_iterator
compile_unit_iterator;
typedef SmallVectorImpl<DISubprogram *>::const_iterator subprogram_iterator;
typedef SmallVectorImpl<DIGlobalVariable *>::const_iterator
global_variable_iterator;
typedef SmallVectorImpl<DIGlobalVariableExpression *>::const_iterator
global_variable_expression_iterator;
typedef SmallVectorImpl<DIType *>::const_iterator type_iterator;
typedef SmallVectorImpl<DIScope *>::const_iterator scope_iterator;

Expand All @@ -111,7 +111,7 @@ class DebugInfoFinder {
return make_range(SPs.begin(), SPs.end());
}

iterator_range<global_variable_iterator> global_variables() const {
iterator_range<global_variable_expression_iterator> global_variables() const {
return make_range(GVs.begin(), GVs.end());
}

Expand All @@ -132,7 +132,7 @@ class DebugInfoFinder {
private:
SmallVector<DICompileUnit *, 8> CUs;
SmallVector<DISubprogram *, 8> SPs;
SmallVector<DIGlobalVariable *, 8> GVs;
SmallVector<DIGlobalVariableExpression *, 8> GVs;
SmallVector<DIType *, 8> TYs;
SmallVector<DIScope *, 8> Scopes;
SmallPtrSet<const MDNode *, 32> NodesSeen;
Expand Down
93 changes: 63 additions & 30 deletions llvm/include/llvm/IR/DebugInfoMetadata.h
Expand Up @@ -1038,7 +1038,8 @@ class DICompileUnit : public DIScope {
StringRef Producer, bool IsOptimized, StringRef Flags,
unsigned RuntimeVersion, StringRef SplitDebugFilename,
unsigned EmissionKind, DICompositeTypeArray EnumTypes,
DIScopeArray RetainedTypes, DIGlobalVariableArray GlobalVariables,
DIScopeArray RetainedTypes,
DIGlobalVariableExpressionArray GlobalVariables,
DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros,
uint64_t DWOId, bool SplitDebugInlining, StorageType Storage,
bool ShouldCreate = true) {
Expand Down Expand Up @@ -1078,7 +1079,7 @@ class DICompileUnit : public DIScope {
bool IsOptimized, StringRef Flags, unsigned RuntimeVersion,
StringRef SplitDebugFilename, DebugEmissionKind EmissionKind,
DICompositeTypeArray EnumTypes, DIScopeArray RetainedTypes,
DIGlobalVariableArray GlobalVariables,
DIGlobalVariableExpressionArray GlobalVariables,
DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros,
uint64_t DWOId, bool SplitDebugInlining),
(SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion,
Expand Down Expand Up @@ -1113,7 +1114,7 @@ class DICompileUnit : public DIScope {
DIScopeArray getRetainedTypes() const {
return cast_or_null<MDTuple>(getRawRetainedTypes());
}
DIGlobalVariableArray getGlobalVariables() const {
DIGlobalVariableExpressionArray getGlobalVariables() const {
return cast_or_null<MDTuple>(getRawGlobalVariables());
}
DIImportedEntityArray getImportedEntities() const {
Expand Down Expand Up @@ -1152,7 +1153,7 @@ class DICompileUnit : public DIScope {
void replaceRetainedTypes(DITypeArray N) {
replaceOperandWith(5, N.get());
}
void replaceGlobalVariables(DIGlobalVariableArray N) {
void replaceGlobalVariables(DIGlobalVariableExpressionArray N) {
replaceOperandWith(6, N.get());
}
void replaceImportedEntities(DIImportedEntityArray N) {
Expand Down Expand Up @@ -1981,6 +1982,9 @@ class DIExpression : public MDNode {
/// Return the size of this fragment in bits.
uint64_t getFragmentSizeInBits() const;

/// Determine whether this represents a standalone constant value.
bool isConstant() const;

typedef ArrayRef<uint64_t>::iterator element_iterator;
element_iterator elements_begin() const { return getElements().begin(); }
element_iterator elements_end() const { return getElements().end(); }
Expand Down Expand Up @@ -2100,72 +2104,62 @@ class DIGlobalVariable : public DIVariable {
IsLocalToUnit(IsLocalToUnit), IsDefinition(IsDefinition) {}
~DIGlobalVariable() = default;

static DIGlobalVariable *
getImpl(LLVMContext &Context, DIScope *Scope, StringRef Name,
StringRef LinkageName, DIFile *File, unsigned Line, DITypeRef Type,
bool IsLocalToUnit, bool IsDefinition, DIExpression *Expr,
DIDerivedType *StaticDataMemberDeclaration, uint32_t AlignInBits,
StorageType Storage, bool ShouldCreate = true) {
static DIGlobalVariable *getImpl(LLVMContext &Context, DIScope *Scope,
StringRef Name, StringRef LinkageName,
DIFile *File, unsigned Line, DITypeRef Type,
bool IsLocalToUnit, bool IsDefinition,
DIDerivedType *StaticDataMemberDeclaration,
uint32_t AlignInBits, StorageType Storage,
bool ShouldCreate = true) {
return getImpl(Context, Scope, getCanonicalMDString(Context, Name),
getCanonicalMDString(Context, LinkageName), File, Line, Type,
IsLocalToUnit, IsDefinition, Expr,
StaticDataMemberDeclaration, AlignInBits, Storage,
ShouldCreate);
IsLocalToUnit, IsDefinition, StaticDataMemberDeclaration,
AlignInBits, Storage, ShouldCreate);
}
static DIGlobalVariable *
getImpl(LLVMContext &Context, Metadata *Scope, MDString *Name,
MDString *LinkageName, Metadata *File, unsigned Line, Metadata *Type,
bool IsLocalToUnit, bool IsDefinition, Metadata *Expr,
bool IsLocalToUnit, bool IsDefinition,
Metadata *StaticDataMemberDeclaration, uint32_t AlignInBits,
StorageType Storage, bool ShouldCreate = true);

TempDIGlobalVariable cloneImpl() const {
return getTemporary(getContext(), getScope(), getName(), getLinkageName(),
getFile(), getLine(), getType(), isLocalToUnit(),
isDefinition(), getExpr(),
getStaticDataMemberDeclaration(), getAlignInBits());
isDefinition(), getStaticDataMemberDeclaration(),
getAlignInBits());
}

public:
DEFINE_MDNODE_GET(DIGlobalVariable,
(DIScope * Scope, StringRef Name, StringRef LinkageName,
DIFile *File, unsigned Line, DITypeRef Type,
bool IsLocalToUnit, bool IsDefinition,
DIExpression *Expr,
DIDerivedType *StaticDataMemberDeclaration,
uint32_t AlignInBits),
(Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit,
IsDefinition, Expr, StaticDataMemberDeclaration,
AlignInBits))
IsDefinition, StaticDataMemberDeclaration, AlignInBits))
DEFINE_MDNODE_GET(DIGlobalVariable,
(Metadata * Scope, MDString *Name, MDString *LinkageName,
Metadata *File, unsigned Line, Metadata *Type,
bool IsLocalToUnit, bool IsDefinition,
Metadata *Expr, Metadata *StaticDataMemberDeclaration,
Metadata *StaticDataMemberDeclaration,
uint32_t AlignInBits),
(Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit,
IsDefinition, Expr, StaticDataMemberDeclaration,
AlignInBits))
IsDefinition, StaticDataMemberDeclaration, AlignInBits))

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

bool isLocalToUnit() const { return IsLocalToUnit; }
bool isDefinition() const { return IsDefinition; }
StringRef getDisplayName() const { return getStringOperand(4); }
StringRef getLinkageName() const { return getStringOperand(5); }
DIExpression *getExpr() const {
return cast_or_null<DIExpression>(getRawExpr());
}
void replaceExpr(DIExpression *E) {
replaceOperandWith(6, E);
}
DIDerivedType *getStaticDataMemberDeclaration() const {
return cast_or_null<DIDerivedType>(getRawStaticDataMemberDeclaration());
}

MDString *getRawLinkageName() const { return getOperandAs<MDString>(5); }
Metadata *getRawExpr() const { return getOperand(6); }
Metadata *getRawStaticDataMemberDeclaration() const { return getOperand(7); }
Metadata *getRawStaticDataMemberDeclaration() const { return getOperand(6); }

static bool classof(const Metadata *MD) {
return MD->getMetadataID() == DIGlobalVariableKind;
Expand Down Expand Up @@ -2391,6 +2385,45 @@ class DIImportedEntity : public DINode {
}
};

/// A pair of DIGlobalVariable and DIExpression.
class DIGlobalVariableExpression : public MDNode {
friend class LLVMContextImpl;
friend class MDNode;

DIGlobalVariableExpression(LLVMContext &C, StorageType Storage,
ArrayRef<Metadata *> Ops)
: MDNode(C, DIGlobalVariableExpressionKind, Storage, Ops) {}
~DIGlobalVariableExpression() = default;

static DIGlobalVariableExpression *
getImpl(LLVMContext &Context, Metadata *Variable, Metadata *Expression,
StorageType Storage, bool ShouldCreate = true);

TempDIGlobalVariableExpression cloneImpl() const {
return getTemporary(getContext(), getVariable(), getExpression());
}

public:
DEFINE_MDNODE_GET(DIGlobalVariableExpression,
(Metadata * Variable, Metadata *Expression),
(Variable, Expression))

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

Metadata *getRawVariable() const { return getOperand(0); }
DIGlobalVariable *getVariable() const {
return cast_or_null<DIGlobalVariable>(getRawVariable());
}
Metadata *getRawExpression() const { return getOperand(1); }
DIExpression *getExpression() const {
return cast_or_null<DIExpression>(getRawExpression());
}

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

/// Macro Info DWARF-like metadata node.
///
/// A metadata node with a DWARF macro info (i.e., a constant named
Expand Down
11 changes: 8 additions & 3 deletions llvm/include/llvm/IR/GlobalVariable.h
Expand Up @@ -20,6 +20,7 @@
#ifndef LLVM_IR_GLOBALVARIABLE_H
#define LLVM_IR_GLOBALVARIABLE_H

#include "llvm/ADT/PointerUnion.h"
#include "llvm/ADT/Twine.h"
#include "llvm/ADT/ilist_node.h"
#include "llvm/IR/GlobalObject.h"
Expand All @@ -31,10 +32,11 @@
namespace llvm {

class Constant;
class DIGlobalVariable;
class Module;

template <typename ValueSubClass> class SymbolTableListTraits;
class DIGlobalVariable;
class DIGlobalVariableExpression;

class GlobalVariable : public GlobalObject, public ilist_node<GlobalVariable> {
friend class SymbolTableListTraits<GlobalVariable>;
Expand Down Expand Up @@ -170,8 +172,11 @@ class GlobalVariable : public GlobalObject, public ilist_node<GlobalVariable> {
/// drops not only the reference to the initializer but also to any metadata.
void dropAllReferences();

void addDebugInfo(DIGlobalVariable *GV);
void getDebugInfo(SmallVectorImpl<DIGlobalVariable *> &GVs) const;
/// Attach a DIGlobalVariableExpression.
void addDebugInfo(DIGlobalVariableExpression *GV);

/// Fill the vector with all debug info attachements.
void getDebugInfo(SmallVectorImpl<DIGlobalVariableExpression *> &GVs) const;

// Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const Value *V) {
Expand Down
1 change: 1 addition & 0 deletions llvm/include/llvm/IR/Metadata.def
Expand Up @@ -82,6 +82,7 @@ HANDLE_MDNODE_BRANCH(MDNode)
HANDLE_MDNODE_LEAF_UNIQUABLE(MDTuple)
HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DILocation)
HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIExpression)
HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIGlobalVariableExpression)
HANDLE_SPECIALIZED_MDNODE_BRANCH(DINode)
HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(GenericDINode)
HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DISubrange)
Expand Down
3 changes: 2 additions & 1 deletion llvm/lib/Analysis/ModuleDebugInfoPrinter.cpp
Expand Up @@ -91,7 +91,8 @@ void ModuleDebugInfoPrinter::print(raw_ostream &O, const Module *M) const {
O << '\n';
}

for (const DIGlobalVariable *GV : Finder.global_variables()) {
for (auto GVU : Finder.global_variables()) {
const auto *GV = GVU->getVariable();
O << "Global variable: " << GV->getName();
printFile(O, GV->getFilename(), GV->getDirectory(), GV->getLine());
if (!GV->getLinkageName().empty())
Expand Down
22 changes: 17 additions & 5 deletions llvm/lib/AsmParser/LLParser.cpp
Expand Up @@ -4197,8 +4197,7 @@ bool LLParser::ParseDITemplateValueParameter(MDNode *&Result, bool IsDistinct) {
/// ParseDIGlobalVariable:
/// ::= !DIGlobalVariable(scope: !0, name: "foo", linkageName: "foo",
/// file: !1, line: 7, type: !2, isLocal: false,
/// isDefinition: true, variable: i32* @foo,
/// declaration: !3, align: 8)
/// isDefinition: true, declaration: !3, align: 8)
bool LLParser::ParseDIGlobalVariable(MDNode *&Result, bool IsDistinct) {
#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \
REQUIRED(name, MDStringField, (/* AllowEmpty */ false)); \
Expand All @@ -4209,7 +4208,6 @@ bool LLParser::ParseDIGlobalVariable(MDNode *&Result, bool IsDistinct) {
OPTIONAL(type, MDField, ); \
OPTIONAL(isLocal, MDBoolField, ); \
OPTIONAL(isDefinition, MDBoolField, (true)); \
OPTIONAL(expr, MDField, ); \
OPTIONAL(declaration, MDField, ); \
OPTIONAL(align, MDUnsignedField, (0, UINT32_MAX));
PARSE_MD_FIELDS();
Expand All @@ -4218,8 +4216,7 @@ bool LLParser::ParseDIGlobalVariable(MDNode *&Result, bool IsDistinct) {
Result = GET_OR_DISTINCT(DIGlobalVariable,
(Context, scope.Val, name.Val, linkageName.Val,
file.Val, line.Val, type.Val, isLocal.Val,
isDefinition.Val, expr.Val, declaration.Val,
align.Val));
isDefinition.Val, declaration.Val, align.Val));
return false;
}

Expand Down Expand Up @@ -4287,6 +4284,21 @@ bool LLParser::ParseDIExpression(MDNode *&Result, bool IsDistinct) {
return false;
}

/// ParseDIGlobalVariableExpression:
/// ::= !DIGlobalVariableExpression(var: !0, expr: !1)
bool LLParser::ParseDIGlobalVariableExpression(MDNode *&Result,
bool IsDistinct) {
#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \
REQUIRED(var, MDField, ); \
OPTIONAL(expr, MDField, );
PARSE_MD_FIELDS();
#undef VISIT_MD_FIELDS

Result =
GET_OR_DISTINCT(DIGlobalVariableExpression, (Context, var.Val, expr.Val));
return false;
}

/// ParseDIObjCProperty:
/// ::= !DIObjCProperty(name: "foo", file: !1, line: 7, setter: "setFoo",
/// getter: "getFoo", attributes: 7, type: !2)
Expand Down

0 comments on commit bceaaa9

Please sign in to comment.