Skip to content
This repository has been archived by the owner on Apr 23, 2020. It is now read-only.

Commit

Permalink
DebugInfo: preparation to implement DW_AT_alignment
Browse files Browse the repository at this point in the history
 - Add alignment attribute to DIVariable family
 - Modify bitcode format to match new DIVariable representation
 - Update tests to match these changes (also add bitcode upgrade test)
 - Expect that frontend passes non-zero align value only when it is not default
   (was forcibly aligned by alignas()/_Alignas()/__atribute__(aligned())

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


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@284678 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
Victor Leschuk committed Oct 20, 2016
1 parent 1c2f240 commit e69c459
Show file tree
Hide file tree
Showing 22 changed files with 329 additions and 188 deletions.
19 changes: 12 additions & 7 deletions include/llvm/IR/DIBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -120,10 +120,9 @@ namespace llvm {
/// type.
/// \param Name Type name.
/// \param SizeInBits Size of the type.
/// \param AlignInBits Type alignment.
/// \param Encoding DWARF encoding code, e.g. dwarf::DW_ATE_float.
DIBasicType *createBasicType(StringRef Name, uint64_t SizeInBits,
uint32_t AlignInBits, unsigned Encoding);
unsigned Encoding);

/// Create debugging information entry for a qualified
/// type, e.g. 'const int'.
Expand Down Expand Up @@ -209,7 +208,7 @@ namespace llvm {
/// \param Ty Parent type.
DIDerivedType *createBitFieldMemberType(
DIScope *Scope, StringRef Name, DIFile *File, unsigned LineNo,
uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits,
uint64_t SizeInBits, uint64_t OffsetInBits,
uint64_t StorageOffsetInBits, DINode::DIFlags Flags, DIType *Ty);

/// Create debugging information entry for a
Expand All @@ -221,10 +220,12 @@ namespace llvm {
/// \param Ty Type of the static member.
/// \param Flags Flags to encode member attribute, e.g. private.
/// \param Val Const initializer of the member.
/// \param AlignInBits Member alignment.
DIDerivedType *createStaticMemberType(DIScope *Scope, StringRef Name,
DIFile *File, unsigned LineNo,
DIType *Ty, DINode::DIFlags Flags,
llvm::Constant *Val);
llvm::Constant *Val,
uint32_t AlignInBits = 0);

/// Create debugging information entry for Objective-C
/// instance variable.
Expand Down Expand Up @@ -458,19 +459,22 @@ namespace llvm {
/// \param Expr The location of the global relative to the attached
/// GlobalVariable.
/// \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);
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);
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 All @@ -483,7 +487,8 @@ namespace llvm {
DILocalVariable *
createAutoVariable(DIScope *Scope, StringRef Name, DIFile *File,
unsigned LineNo, DIType *Ty, bool AlwaysPreserve = false,
DINode::DIFlags Flags = DINode::FlagZero);
DINode::DIFlags Flags = DINode::FlagZero,
uint32_t AlignInBits = 0);

/// Create a new descriptor for a parameter variable.
///
Expand Down
69 changes: 41 additions & 28 deletions include/llvm/IR/DebugInfoMetadata.h
Original file line number Diff line number Diff line change
Expand Up @@ -549,7 +549,8 @@ class DIType : public DIScope {

unsigned getLine() const { return Line; }
uint64_t getSizeInBits() const { return SizeInBits; }
uint64_t getAlignInBits() const { return AlignInBits; }
uint32_t getAlignInBits() const { return AlignInBits; }
uint32_t getAlignInBytes() const { return getAlignInBits() / CHAR_BIT; }
uint64_t getOffsetInBits() const { return OffsetInBits; }
DIFlags getFlags() const { return Flags; }

Expand Down Expand Up @@ -1826,11 +1827,13 @@ class DITemplateValueParameter : public DITemplateParameter {
/// \brief Base class for variables.
class DIVariable : public DINode {
unsigned Line;
uint64_t AlignInBits;

protected:
DIVariable(LLVMContext &C, unsigned ID, StorageType Storage, unsigned Line,
ArrayRef<Metadata *> Ops)
: DINode(C, ID, Storage, dwarf::DW_TAG_variable, Ops), Line(Line) {}
ArrayRef<Metadata *> Ops, uint64_t AlignInBits = 0)
: DINode(C, ID, Storage, dwarf::DW_TAG_variable, Ops), Line(Line),
AlignInBits(AlignInBits) {}
~DIVariable() = default;

public:
Expand All @@ -1839,6 +1842,8 @@ class DIVariable : public DINode {
StringRef getName() const { return getStringOperand(1); }
DIFile *getFile() const { return cast_or_null<DIFile>(getRawFile()); }
DITypeRef getType() const { return DITypeRef(getRawType()); }
uint64_t getAlignInBits() const { return AlignInBits; }
uint64_t getAlignInBytes() const { return getAlignInBits() / CHAR_BIT; }

StringRef getFilename() const {
if (auto *F = getFile())
Expand Down Expand Up @@ -2026,52 +2031,58 @@ class DIGlobalVariable : public DIVariable {
bool IsDefinition;

DIGlobalVariable(LLVMContext &C, StorageType Storage, unsigned Line,
bool IsLocalToUnit, bool IsDefinition,
bool IsLocalToUnit, bool IsDefinition, uint64_t AlignInBits,
ArrayRef<Metadata *> Ops)
: DIVariable(C, DIGlobalVariableKind, Storage, Line, Ops),
: DIVariable(C, DIGlobalVariableKind, Storage, Line, Ops, AlignInBits),
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, StorageType Storage,
bool ShouldCreate = true) {
DIDerivedType *StaticDataMemberDeclaration, uint64_t AlignInBits,
StorageType Storage, bool ShouldCreate = true) {
return getImpl(Context, Scope, getCanonicalMDString(Context, Name),
getCanonicalMDString(Context, LinkageName), File, Line, Type,
IsLocalToUnit, IsDefinition, Expr,
StaticDataMemberDeclaration, Storage, ShouldCreate);
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,
Metadata *StaticDataMemberDeclaration, StorageType Storage,
bool ShouldCreate = true);
Metadata *StaticDataMemberDeclaration, uint64_t AlignInBits,
StorageType Storage, bool ShouldCreate = true);

TempDIGlobalVariable cloneImpl() const {
return getTemporary(getContext(), getScope(), getName(), getLinkageName(),
getFile(), getLine(), getType(), isLocalToUnit(),
isDefinition(), getExpr(),
getStaticDataMemberDeclaration());
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),
bool IsLocalToUnit, bool IsDefinition,
DIExpression *Expr,
DIDerivedType *StaticDataMemberDeclaration,
uint64_t AlignInBits),
(Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit,
IsDefinition, Expr, StaticDataMemberDeclaration))
IsDefinition, Expr, 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),
bool IsLocalToUnit, bool IsDefinition,
Metadata *Expr, Metadata *StaticDataMemberDeclaration,
uint64_t AlignInBits),
(Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit,
IsDefinition, Expr, StaticDataMemberDeclaration))
IsDefinition, Expr, StaticDataMemberDeclaration,
AlignInBits))

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

Expand Down Expand Up @@ -2109,43 +2120,45 @@ class DILocalVariable : public DIVariable {
DIFlags Flags;

DILocalVariable(LLVMContext &C, StorageType Storage, unsigned Line,
unsigned Arg, DIFlags Flags, ArrayRef<Metadata *> Ops)
: DIVariable(C, DILocalVariableKind, Storage, Line, Ops), Arg(Arg),
Flags(Flags) {
unsigned Arg, DIFlags Flags, uint64_t AlignInBits,
ArrayRef<Metadata *> Ops)
: DIVariable(C, DILocalVariableKind, Storage, Line, Ops, AlignInBits),
Arg(Arg), Flags(Flags) {
assert(Arg < (1 << 16) && "DILocalVariable: Arg out of range");
}
~DILocalVariable() = default;

static DILocalVariable *getImpl(LLVMContext &Context, DIScope *Scope,
StringRef Name, DIFile *File, unsigned Line,
DITypeRef Type, unsigned Arg, DIFlags Flags,
StorageType Storage,
uint64_t AlignInBits, StorageType Storage,
bool ShouldCreate = true) {
return getImpl(Context, Scope, getCanonicalMDString(Context, Name), File,
Line, Type, Arg, Flags, Storage, ShouldCreate);
Line, Type, Arg, Flags, AlignInBits, Storage, ShouldCreate);
}
static DILocalVariable *getImpl(LLVMContext &Context, Metadata *Scope,
MDString *Name, Metadata *File, unsigned Line,
Metadata *Type, unsigned Arg, DIFlags Flags,
StorageType Storage,
uint64_t AlignInBits, StorageType Storage,
bool ShouldCreate = true);

TempDILocalVariable cloneImpl() const {
return getTemporary(getContext(), getScope(), getName(), getFile(),
getLine(), getType(), getArg(), getFlags());
getLine(), getType(), getArg(), getFlags(),
getAlignInBits());
}

public:
DEFINE_MDNODE_GET(DILocalVariable,
(DILocalScope * Scope, StringRef Name, DIFile *File,
unsigned Line, DITypeRef Type, unsigned Arg,
DIFlags Flags),
(Scope, Name, File, Line, Type, Arg, Flags))
DIFlags Flags, uint64_t AlignInBits),
(Scope, Name, File, Line, Type, Arg, Flags, AlignInBits))
DEFINE_MDNODE_GET(DILocalVariable,
(Metadata * Scope, MDString *Name, Metadata *File,
unsigned Line, Metadata *Type, unsigned Arg,
DIFlags Flags),
(Scope, Name, File, Line, Type, Arg, Flags))
DIFlags Flags, uint64_t AlignInBits),
(Scope, Name, File, Line, Type, Arg, Flags, AlignInBits))

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

Expand Down
19 changes: 12 additions & 7 deletions lib/AsmParser/LLParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4186,7 +4186,7 @@ bool LLParser::ParseDITemplateValueParameter(MDNode *&Result, bool IsDistinct) {
/// ::= !DIGlobalVariable(scope: !0, name: "foo", linkageName: "foo",
/// file: !1, line: 7, type: !2, isLocal: false,
/// isDefinition: true, variable: i32* @foo,
/// declaration: !3)
/// declaration: !3, align: 8)
bool LLParser::ParseDIGlobalVariable(MDNode *&Result, bool IsDistinct) {
#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \
REQUIRED(name, MDStringField, (/* AllowEmpty */ false)); \
Expand All @@ -4198,22 +4198,26 @@ bool LLParser::ParseDIGlobalVariable(MDNode *&Result, bool IsDistinct) {
OPTIONAL(isLocal, MDBoolField, ); \
OPTIONAL(isDefinition, MDBoolField, (true)); \
OPTIONAL(expr, MDField, ); \
OPTIONAL(declaration, MDField, );
OPTIONAL(declaration, MDField, ); \
OPTIONAL(align, MDUnsignedField, (0, UINT32_MAX));
PARSE_MD_FIELDS();
#undef VISIT_MD_FIELDS

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));
isDefinition.Val, expr.Val, declaration.Val,
align.Val));
return false;
}

/// ParseDILocalVariable:
/// ::= !DILocalVariable(arg: 7, scope: !0, name: "foo",
/// file: !1, line: 7, type: !2, arg: 2, flags: 7)
/// file: !1, line: 7, type: !2, arg: 2, flags: 7,
/// align: 8)
/// ::= !DILocalVariable(scope: !0, name: "foo",
/// file: !1, line: 7, type: !2, arg: 2, flags: 7)
/// file: !1, line: 7, type: !2, arg: 2, flags: 7,
/// align: 8)
bool LLParser::ParseDILocalVariable(MDNode *&Result, bool IsDistinct) {
#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \
REQUIRED(scope, MDField, (/* AllowNull */ false)); \
Expand All @@ -4222,13 +4226,14 @@ bool LLParser::ParseDILocalVariable(MDNode *&Result, bool IsDistinct) {
OPTIONAL(file, MDField, ); \
OPTIONAL(line, LineField, ); \
OPTIONAL(type, MDField, ); \
OPTIONAL(flags, DIFlagField, );
OPTIONAL(flags, DIFlagField, ); \
OPTIONAL(align, MDUnsignedField, (0, UINT32_MAX));
PARSE_MD_FIELDS();
#undef VISIT_MD_FIELDS

Result = GET_OR_DISTINCT(DILocalVariable,
(Context, scope.Val, name.Val, file.Val, line.Val,
type.Val, arg.Val, flags.Val));
type.Val, arg.Val, flags.Val, align.Val));
return false;
}

Expand Down
16 changes: 10 additions & 6 deletions lib/Bitcode/Reader/BitcodeReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2734,14 +2734,15 @@ std::error_code BitcodeReader::parseMetadata(bool ModuleLevel) {
break;
}
case bitc::METADATA_GLOBAL_VAR: {
if (Record.size() != 11)
if (Record.size() < 11 || Record.size() > 12)
return error("Invalid record");

IsDistinct = Record[0];

// Upgrade old metadata, which stored a global variable reference or a
// ConstantInt here.
Metadata *Expr = getMDOrNull(Record[9]);
uint64_t AlignInBits = (Record.size() > 11) ? Record[11] : 0;
GlobalVariable *Attach = nullptr;
if (auto *CMD = dyn_cast_or_null<ConstantAsMetadata>(Expr)) {
if (auto *GV = dyn_cast<GlobalVariable>(CMD->getValue())) {
Expand All @@ -2761,7 +2762,7 @@ std::error_code BitcodeReader::parseMetadata(bool ModuleLevel) {
(Context, getMDOrNull(Record[1]), getMDString(Record[2]),
getMDString(Record[3]), getMDOrNull(Record[4]), Record[5],
getDITypeRefOrNull(Record[6]), Record[7], Record[8], Expr,
getMDOrNull(Record[10])));
getMDOrNull(Record[10]), AlignInBits));
MetadataList.assignValue(DGV, NextMetadataNo++);

if (Attach)
Expand All @@ -2774,18 +2775,21 @@ std::error_code BitcodeReader::parseMetadata(bool ModuleLevel) {
if (Record.size() < 8 || Record.size() > 10)
return error("Invalid record");

IsDistinct = Record[0] & 1;
bool HasAlignment = Record[0] & 2;
// 2nd field used to be an artificial tag, either DW_TAG_auto_variable or
// DW_TAG_arg_variable.
IsDistinct = Record[0];
bool HasTag = Record.size() > 8;
// DW_TAG_arg_variable, if we have alignment flag encoded it means, that
// this is newer version of record which doesn't have artifical tag.
bool HasTag = !HasAlignment && Record.size() > 8;
DINode::DIFlags Flags = static_cast<DINode::DIFlags>(Record[7 + HasTag]);
uint64_t AlignInBits = HasAlignment ? Record[8 + HasTag] : 0;
MetadataList.assignValue(
GET_OR_DISTINCT(DILocalVariable,
(Context, getMDOrNull(Record[1 + HasTag]),
getMDString(Record[2 + HasTag]),
getMDOrNull(Record[3 + HasTag]), Record[4 + HasTag],
getDITypeRefOrNull(Record[5 + HasTag]),
Record[6 + HasTag], Flags)),
Record[6 + HasTag], Flags, AlignInBits)),
NextMetadataNo++);
break;
}
Expand Down
18 changes: 17 additions & 1 deletion lib/Bitcode/Writer/BitcodeWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1712,6 +1712,7 @@ void ModuleBitcodeWriter::writeDIGlobalVariable(
Record.push_back(N->isDefinition());
Record.push_back(VE.getMetadataOrNullID(N->getRawExpr()));
Record.push_back(VE.getMetadataOrNullID(N->getStaticDataMemberDeclaration()));
Record.push_back(N->getAlignInBits());

Stream.EmitRecord(bitc::METADATA_GLOBAL_VAR, Record, Abbrev);
Record.clear();
Expand All @@ -1720,14 +1721,29 @@ void ModuleBitcodeWriter::writeDIGlobalVariable(
void ModuleBitcodeWriter::writeDILocalVariable(
const DILocalVariable *N, SmallVectorImpl<uint64_t> &Record,
unsigned Abbrev) {
Record.push_back(N->isDistinct());
// In order to support all possible bitcode formats in BitcodeReader we need
// to distiguish the following cases:
// 1) Record has no artificial tag (Record[1]),
// has no obsolete inlinedAt field (Record[9]).
// In this case Record size will be 8, HasAlignment flag is false.
// 2) Record has artificial tag (Record[1]),
// has no obsolete inlignedAt field (Record[9]).
// In this case Record size will be 9, HasAlignment flag is false.
// 3) Record has both artificial tag (Record[1]) and
// obsolete inlignedAt field (Record[9]).
// In this case Record size will be 10, HasAlignment flag is false.
// 4) Record has neither artificial tag, nor inlignedAt field, but
// HasAlignment flag is true and Record[8] contains alignment value.
const uint64_t HasAlignmentFlag = 1 << 1;
Record.push_back(N->isDistinct() | HasAlignmentFlag);
Record.push_back(VE.getMetadataOrNullID(N->getScope()));
Record.push_back(VE.getMetadataOrNullID(N->getRawName()));
Record.push_back(VE.getMetadataOrNullID(N->getFile()));
Record.push_back(N->getLine());
Record.push_back(VE.getMetadataOrNullID(N->getType()));
Record.push_back(N->getArg());
Record.push_back(N->getFlags());
Record.push_back(N->getAlignInBits());

Stream.EmitRecord(bitc::METADATA_LOCAL_VAR, Record, Abbrev);
Record.clear();
Expand Down
Loading

0 comments on commit e69c459

Please sign in to comment.