Skip to content

Commit

Permalink
[DebugInfo] Add DILabel metadata and intrinsic llvm.dbg.label.
Browse files Browse the repository at this point in the history
In order to set breakpoints on labels and list source code around
labels, we need collect debug information for labels, i.e., label
name, the function label belong, line number in the file, and the
address label located. In order to keep these information in LLVM
IR and to allow backend to generate debug information correctly.
We create a new kind of metadata for labels, DILabel. The format
of DILabel is

!DILabel(scope: !1, name: "foo", file: !2, line: 3)

We hope to keep debug information as much as possible even the
code is optimized. So, we create a new kind of intrinsic for label
metadata to avoid the metadata is eliminated with basic block.
The intrinsic will keep existing if we keep it from optimized out.
The format of the intrinsic is

llvm.dbg.label(metadata !1)

It has only one argument, that is the DILabel metadata. The
intrinsic will follow the label immediately. Backend could get the
label metadata through the intrinsic's parameter.

We also create DIBuilder API for labels to be used by Frontend.
Frontend could use createLabel() to allocate DILabel objects, and use
insertLabel() to insert llvm.dbg.label intrinsic in LLVM IR.

Differential Revision: https://reviews.llvm.org/D45024

Patch by Hsiangkai Wang.

llvm-svn: 331841
  • Loading branch information
ShivaChen committed May 9, 2018
1 parent 49914cc commit 2c86455
Show file tree
Hide file tree
Showing 753 changed files with 1,698 additions and 1,293 deletions.
7 changes: 6 additions & 1 deletion llvm/.gitattributes
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
# binary files
test/Object/Inputs/*.a-* binary
test/tools/dsymutil/Inputs/* binary
test/tools/dsymutil/Inputs/*.o binary
test/tools/dsymutil/Inputs/*.a binary
test/tools/dsymutil/Inputs/*.i386 binary
test/tools/dsymutil/Inputs/*.x86_64 binary
test/tools/dsymutil/Inputs/*.armv7m binary
test/tools/dsymutil/Inputs/*.dylib binary
test/tools/llvm-ar/Inputs/*.lib binary
test/tools/llvm-objdump/Inputs/*.a binary
test/tools/llvm-rc/Inputs/* binary
Expand Down
1 change: 1 addition & 0 deletions llvm/include/llvm/Analysis/TargetTransformInfoImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ class TargetTransformInfoImplBase {
case Intrinsic::sideeffect:
case Intrinsic::dbg_declare:
case Intrinsic::dbg_value:
case Intrinsic::dbg_label:
case Intrinsic::invariant_start:
case Intrinsic::invariant_end:
case Intrinsic::lifetime_start:
Expand Down
1 change: 1 addition & 0 deletions llvm/include/llvm/Bitcode/LLVMBitCodes.h
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,7 @@ enum MetadataCodes {
METADATA_GLOBAL_VAR_EXPR = 37, // [distinct, var, expr]
METADATA_INDEX_OFFSET = 38, // [offset]
METADATA_INDEX = 39, // [bitpos]
METADATA_LABEL = 40, // [distinct, scope, name, file, line]
};

// The constants block (CONSTANTS_BLOCK_ID) describes emission for each
Expand Down
30 changes: 30 additions & 0 deletions llvm/include/llvm/IR/DIBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ namespace llvm {
DICompileUnit *CUNode; ///< The one compile unit created by this DIBuiler.
Function *DeclareFn; ///< llvm.dbg.declare
Function *ValueFn; ///< llvm.dbg.value
Function *LabelFn; ///< llvm.dbg.label

SmallVector<Metadata *, 4> AllEnumTypes;
/// Track the RetainTypes, since they can be updated later on.
Expand All @@ -69,6 +70,9 @@ namespace llvm {
/// copy.
DenseMap<MDNode *, SmallVector<TrackingMDNodeRef, 1>> PreservedVariables;

/// Each subprogram's preserved labels.
DenseMap<MDNode *, SmallVector<TrackingMDNodeRef, 1>> PreservedLabels;

/// Create a temporary.
///
/// Create an \a temporary node and track it in \a UnresolvedNodes.
Expand All @@ -79,6 +83,10 @@ namespace llvm {
DIExpression *Expr, const DILocation *DL,
BasicBlock *InsertBB, Instruction *InsertBefore);

/// Internal helper for insertLabel.
Instruction *insertLabel(DILabel *LabelInfo, const DILocation *DL,
BasicBlock *InsertBB, Instruction *InsertBefore);

/// Internal helper for insertDbgValueIntrinsic.
Instruction *
insertDbgValueIntrinsic(llvm::Value *Val, DILocalVariable *VarInfo,
Expand Down Expand Up @@ -591,6 +599,14 @@ namespace llvm {
DINode::DIFlags Flags = DINode::FlagZero,
uint32_t AlignInBits = 0);

/// Create a new descriptor for an label.
///
/// \c Scope must be a \a DILocalScope, and thus its scope chain eventually
/// leads to a \a DISubprogram.
DILabel *
createLabel(DIScope *Scope, StringRef Name, DIFile *File, unsigned LineNo,
bool AlwaysPreserve = false);

/// Create a new descriptor for a parameter variable.
///
/// \c Scope must be a \a DILocalScope, and thus its scope chain eventually
Expand Down Expand Up @@ -782,6 +798,20 @@ namespace llvm {
DIExpression *Expr, const DILocation *DL,
Instruction *InsertBefore);

/// Insert a new llvm.dbg.label intrinsic call.
/// \param LabelInfo Label's debug info descriptor.
/// \param DL Debug info location.
/// \param InsertBefore Location for the new intrinsic.
Instruction *insertLabel(DILabel *LabelInfo, const DILocation *DL,
Instruction *InsertBefore);

/// Insert a new llvm.dbg.label intrinsic call.
/// \param LabelInfo Label's debug info descriptor.
/// \param DL Debug info location.
/// \param InsertAtEnd Location for the new intrinsic.
Instruction *insertLabel(DILabel *LabelInfo, const DILocation *DL,
BasicBlock *InsertAtEnd);

/// Insert a new llvm.dbg.value intrinsic call.
/// \param Val llvm::Value of the variable
/// \param VarInfo Variable's debug info descriptor.
Expand Down
93 changes: 82 additions & 11 deletions llvm/include/llvm/IR/DebugInfoMetadata.h
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,7 @@ class DINode : public MDNode {
case DITemplateValueParameterKind:
case DIGlobalVariableKind:
case DILocalVariableKind:
case DILabelKind:
case DIObjCPropertyKind:
case DIImportedEntityKind:
case DIModuleKind:
Expand Down Expand Up @@ -1609,13 +1610,13 @@ class DISubprogram : public DILocalScope {
unsigned VirtualIndex, int ThisAdjustment, DIFlags Flags,
bool IsOptimized, DICompileUnit *Unit,
DITemplateParameterArray TemplateParams, DISubprogram *Declaration,
DILocalVariableArray Variables, DITypeArray ThrownTypes,
DINodeArray RetainedNodes, DITypeArray ThrownTypes,
StorageType Storage, bool ShouldCreate = true) {
return getImpl(Context, Scope, getCanonicalMDString(Context, Name),
getCanonicalMDString(Context, LinkageName), File, Line, Type,
IsLocalToUnit, IsDefinition, ScopeLine, ContainingType,
Virtuality, VirtualIndex, ThisAdjustment, Flags, IsOptimized,
Unit, TemplateParams.get(), Declaration, Variables.get(),
Unit, TemplateParams.get(), Declaration, RetainedNodes.get(),
ThrownTypes.get(), Storage, ShouldCreate);
}
static DISubprogram *
Expand All @@ -1624,7 +1625,7 @@ class DISubprogram : public DILocalScope {
bool IsLocalToUnit, bool IsDefinition, unsigned ScopeLine,
Metadata *ContainingType, unsigned Virtuality, unsigned VirtualIndex,
int ThisAdjustment, DIFlags Flags, bool IsOptimized, Metadata *Unit,
Metadata *TemplateParams, Metadata *Declaration, Metadata *Variables,
Metadata *TemplateParams, Metadata *Declaration, Metadata *RetainedNodes,
Metadata *ThrownTypes, StorageType Storage, bool ShouldCreate = true);

TempDISubprogram cloneImpl() const {
Expand All @@ -1633,7 +1634,7 @@ class DISubprogram : public DILocalScope {
isDefinition(), getScopeLine(), getContainingType(),
getVirtuality(), getVirtualIndex(), getThisAdjustment(),
getFlags(), isOptimized(), getUnit(),
getTemplateParams(), getDeclaration(), getVariables(),
getTemplateParams(), getDeclaration(), getRetainedNodes(),
getThrownTypes());
}

Expand All @@ -1647,24 +1648,24 @@ class DISubprogram : public DILocalScope {
bool IsOptimized, DICompileUnit *Unit,
DITemplateParameterArray TemplateParams = nullptr,
DISubprogram *Declaration = nullptr,
DILocalVariableArray Variables = nullptr,
DINodeArray RetainedNodes = nullptr,
DITypeArray ThrownTypes = nullptr),
(Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit,
IsDefinition, ScopeLine, ContainingType, Virtuality,
VirtualIndex, ThisAdjustment, Flags, IsOptimized, Unit,
TemplateParams, Declaration, Variables, ThrownTypes))
TemplateParams, Declaration, RetainedNodes, ThrownTypes))
DEFINE_MDNODE_GET(
DISubprogram,
(Metadata * Scope, MDString *Name, MDString *LinkageName, Metadata *File,
unsigned Line, Metadata *Type, bool IsLocalToUnit, bool IsDefinition,
unsigned ScopeLine, Metadata *ContainingType, unsigned Virtuality,
unsigned VirtualIndex, int ThisAdjustment, DIFlags Flags,
bool IsOptimized, Metadata *Unit, Metadata *TemplateParams = nullptr,
Metadata *Declaration = nullptr, Metadata *Variables = nullptr,
Metadata *Declaration = nullptr, Metadata *RetainedNodes = nullptr,
Metadata *ThrownTypes = nullptr),
(Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, IsDefinition,
ScopeLine, ContainingType, Virtuality, VirtualIndex, ThisAdjustment,
Flags, IsOptimized, Unit, TemplateParams, Declaration, Variables,
Flags, IsOptimized, Unit, TemplateParams, Declaration, RetainedNodes,
ThrownTypes))

TempDISubprogram clone() const { return cloneImpl(); }
Expand Down Expand Up @@ -1738,8 +1739,8 @@ class DISubprogram : public DILocalScope {
DISubprogram *getDeclaration() const {
return cast_or_null<DISubprogram>(getRawDeclaration());
}
DILocalVariableArray getVariables() const {
return cast_or_null<MDTuple>(getRawVariables());
DINodeArray getRetainedNodes() const {
return cast_or_null<MDTuple>(getRawRetainedNodes());
}
DITypeArray getThrownTypes() const {
return cast_or_null<MDTuple>(getRawThrownTypes());
Expand All @@ -1751,7 +1752,7 @@ class DISubprogram : public DILocalScope {
Metadata *getRawType() const { return getOperand(4); }
Metadata *getRawUnit() const { return getOperand(5); }
Metadata *getRawDeclaration() const { return getOperand(6); }
Metadata *getRawVariables() const { return getOperand(7); }
Metadata *getRawRetainedNodes() const { return getOperand(7); }
Metadata *getRawContainingType() const {
return getNumOperands() > 8 ? getOperandAs<Metadata>(8) : nullptr;
}
Expand Down Expand Up @@ -2607,6 +2608,76 @@ class DILocalVariable : public DIVariable {
}
};

/// Label.
///
class DILabel : public DINode {
friend class LLVMContextImpl;
friend class MDNode;

unsigned Line;

DILabel(LLVMContext &C, StorageType Storage, unsigned Line,
ArrayRef<Metadata *> Ops)
: DINode(C, DILabelKind, Storage, dwarf::DW_TAG_label, Ops), Line(Line) {}
~DILabel() = default;

static DILabel *getImpl(LLVMContext &Context, DIScope *Scope,
StringRef Name, DIFile *File, unsigned Line,
StorageType Storage,
bool ShouldCreate = true) {
return getImpl(Context, Scope, getCanonicalMDString(Context, Name), File,
Line, Storage, ShouldCreate);
}
static DILabel *getImpl(LLVMContext &Context, Metadata *Scope,
MDString *Name, Metadata *File, unsigned Line,
StorageType Storage,
bool ShouldCreate = true);

TempDILabel cloneImpl() const {
return getTemporary(getContext(), getScope(), getName(), getFile(),
getLine());
}

public:
DEFINE_MDNODE_GET(DILabel,
(DILocalScope * Scope, StringRef Name, DIFile *File,
unsigned Line),
(Scope, Name, File, Line))
DEFINE_MDNODE_GET(DILabel,
(Metadata * Scope, MDString *Name, Metadata *File,
unsigned Line),
(Scope, Name, File, Line))

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

/// Get the local scope for this label.
///
/// Labels must be defined in a local scope.
DILocalScope *getScope() const {
return cast_or_null<DILocalScope>(getRawScope());
}
unsigned getLine() const { return Line; }
StringRef getName() const { return getStringOperand(1); }
DIFile *getFile() const { return cast_or_null<DIFile>(getRawFile()); }

Metadata *getRawScope() const { return getOperand(0); }
MDString *getRawName() const { return getOperandAs<MDString>(1); }
Metadata *getRawFile() const { return getOperand(2); }

/// Check that a location is valid for this label.
///
/// Check that \c DL exists, is in the same subprogram, and has the same
/// inlined-at location as \c this. (Otherwise, it's not a valid attachment
/// to a \a DbgInfoIntrinsic.)
bool isValidLocationForIntrinsic(const DILocation *DL) const {
return DL && getScope()->getSubprogram() == DL->getScope()->getSubprogram();
}

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

class DIObjCProperty : public DINode {
friend class LLVMContextImpl;
friend class MDNode;
Expand Down
2 changes: 2 additions & 0 deletions llvm/include/llvm/IR/InstVisitor.h
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,7 @@ class InstVisitor {
// Handle the special instrinsic instruction classes.
RetTy visitDbgDeclareInst(DbgDeclareInst &I) { DELEGATE(DbgInfoIntrinsic);}
RetTy visitDbgValueInst(DbgValueInst &I) { DELEGATE(DbgInfoIntrinsic);}
RetTy visitDbgLabelInst(DbgLabelInst &I) { DELEGATE(DbgInfoIntrinsic);}
RetTy visitDbgInfoIntrinsic(DbgInfoIntrinsic &I) { DELEGATE(IntrinsicInst); }
RetTy visitMemSetInst(MemSetInst &I) { DELEGATE(MemIntrinsic); }
RetTy visitMemCpyInst(MemCpyInst &I) { DELEGATE(MemTransferInst); }
Expand Down Expand Up @@ -272,6 +273,7 @@ class InstVisitor {
default: DELEGATE(IntrinsicInst);
case Intrinsic::dbg_declare: DELEGATE(DbgDeclareInst);
case Intrinsic::dbg_value: DELEGATE(DbgValueInst);
case Intrinsic::dbg_label: DELEGATE(DbgLabelInst);
case Intrinsic::memcpy: DELEGATE(MemCpyInst);
case Intrinsic::memmove: DELEGATE(MemMoveInst);
case Intrinsic::memset: DELEGATE(MemSetInst);
Expand Down
27 changes: 27 additions & 0 deletions llvm/include/llvm/IR/IntrinsicInst.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ namespace llvm {
case Intrinsic::dbg_declare:
case Intrinsic::dbg_value:
case Intrinsic::dbg_addr:
case Intrinsic::dbg_label:
return true;
default: return false;
}
Expand Down Expand Up @@ -159,6 +160,32 @@ namespace llvm {
/// @}
};

/// This represents the llvm.dbg.label instruction.
class DbgLabelInst : public DbgInfoIntrinsic {
public:
DILabel *getLabel() const {
return cast<DILabel>(getRawVariable());
}

Metadata *getRawVariable() const {
return cast<MetadataAsValue>(getArgOperand(0))->getMetadata();
}

Metadata *getRawExpression() const {
return nullptr;
}

/// Methods for support type inquiry through isa, cast, and dyn_cast:
/// @{
static bool classof(const IntrinsicInst *I) {
return I->getIntrinsicID() == Intrinsic::dbg_label;
}
static bool classof(const Value *V) {
return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
}
/// @}
};

/// This is the common base class for constrained floating point intrinsics.
class ConstrainedFPIntrinsic : public IntrinsicInst {
public:
Expand Down
2 changes: 2 additions & 0 deletions llvm/include/llvm/IR/Intrinsics.td
Original file line number Diff line number Diff line change
Expand Up @@ -599,6 +599,8 @@ let IntrProperties = [IntrNoMem, IntrSpeculatable] in {
[llvm_metadata_ty,
llvm_metadata_ty,
llvm_metadata_ty]>;
def int_dbg_label : Intrinsic<[],
[llvm_metadata_ty]>;
}

//===------------------ Exception Handling Intrinsics----------------------===//
Expand Down
1 change: 1 addition & 0 deletions llvm/include/llvm/IR/Metadata.def
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DITemplateValueParameter)
HANDLE_SPECIALIZED_MDNODE_BRANCH(DIVariable)
HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIGlobalVariable)
HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DILocalVariable)
HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DILabel)
HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIObjCProperty)
HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIImportedEntity)
HANDLE_SPECIALIZED_MDNODE_BRANCH(DIMacroNode)
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/Analysis/ObjCARCInstKind.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,7 @@ static bool isInertIntrinsic(unsigned ID) {
// Don't let dbg info affect our results.
case Intrinsic::dbg_declare:
case Intrinsic::dbg_value:
case Intrinsic::dbg_label:
// Short cut: Some intrinsics obviously don't use ObjC pointers.
return true;
default:
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/Analysis/ValueTracking.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -501,6 +501,7 @@ bool llvm::isAssumeLikeIntrinsic(const Instruction *I) {
case Intrinsic::sideeffect:
case Intrinsic::dbg_declare:
case Intrinsic::dbg_value:
case Intrinsic::dbg_label:
case Intrinsic::invariant_start:
case Intrinsic::invariant_end:
case Intrinsic::lifetime_start:
Expand Down
Loading

0 comments on commit 2c86455

Please sign in to comment.