Index: include/llvm/IR/DIBuilder.h =================================================================== --- include/llvm/IR/DIBuilder.h +++ include/llvm/IR/DIBuilder.h @@ -457,19 +457,22 @@ /// \param Expr The location of the global relative to the attached /// GlobalVariable. /// \param Decl Reference to the corresponding declaration. + /// \param AlignInBytes 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, + uint64_t AlignInBytes = 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, uint64_t AlignInBytes = 0); /// Create a new descriptor for an auto variable. This is a local variable /// that is not a subprogram parameter. @@ -482,7 +485,8 @@ 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, + uint64_t AlignInBytes = 0); /// Create a new descriptor for a parameter variable. /// Index: include/llvm/IR/DebugInfoMetadata.h =================================================================== --- include/llvm/IR/DebugInfoMetadata.h +++ include/llvm/IR/DebugInfoMetadata.h @@ -513,33 +513,33 @@ unsigned Line; DIFlags Flags; uint64_t SizeInBits; - uint64_t AlignInBits; + uint64_t AlignInBytes; uint64_t OffsetInBits; protected: DIType(LLVMContext &C, unsigned ID, StorageType Storage, unsigned Tag, - unsigned Line, uint64_t SizeInBits, uint64_t AlignInBits, + unsigned Line, uint64_t SizeInBits, uint64_t AlignInBytes, uint64_t OffsetInBits, DIFlags Flags, ArrayRef Ops) : DIScope(C, ID, Storage, Tag, Ops) { - init(Line, SizeInBits, AlignInBits, OffsetInBits, Flags); + init(Line, SizeInBits, AlignInBytes, OffsetInBits, Flags); } ~DIType() = default; - void init(unsigned Line, uint64_t SizeInBits, uint64_t AlignInBits, + void init(unsigned Line, uint64_t SizeInBits, uint64_t AlignInBytes, uint64_t OffsetInBits, DIFlags Flags) { this->Line = Line; this->Flags = Flags; this->SizeInBits = SizeInBits; - this->AlignInBits = AlignInBits; + this->AlignInBytes = AlignInBytes; this->OffsetInBits = OffsetInBits; } /// Change fields in place. void mutate(unsigned Tag, unsigned Line, uint64_t SizeInBits, - uint64_t AlignInBits, uint64_t OffsetInBits, DIFlags Flags) { + uint64_t AlignInBytes, uint64_t OffsetInBits, DIFlags Flags) { assert(isDistinct() && "Only distinct nodes can mutate"); setTag(Tag); - init(Line, SizeInBits, AlignInBits, OffsetInBits, Flags); + init(Line, SizeInBits, AlignInBytes, OffsetInBits, Flags); } public: @@ -549,7 +549,7 @@ unsigned getLine() const { return Line; } uint64_t getSizeInBits() const { return SizeInBits; } - uint64_t getAlignInBits() const { return AlignInBits; } + uint64_t getAlignInBytes() const { return AlignInBytes; } uint64_t getOffsetInBits() const { return OffsetInBits; } DIFlags getFlags() const { return Flags; } @@ -614,28 +614,28 @@ unsigned Encoding; DIBasicType(LLVMContext &C, StorageType Storage, unsigned Tag, - uint64_t SizeInBits, uint64_t AlignInBits, unsigned Encoding, + uint64_t SizeInBits, uint64_t AlignInBytes, unsigned Encoding, ArrayRef Ops) - : DIType(C, DIBasicTypeKind, Storage, Tag, 0, SizeInBits, AlignInBits, 0, + : DIType(C, DIBasicTypeKind, Storage, Tag, 0, SizeInBits, AlignInBytes, 0, FlagZero, Ops), Encoding(Encoding) {} ~DIBasicType() = default; static DIBasicType *getImpl(LLVMContext &Context, unsigned Tag, StringRef Name, uint64_t SizeInBits, - uint64_t AlignInBits, unsigned Encoding, + uint64_t AlignInBytes, unsigned Encoding, StorageType Storage, bool ShouldCreate = true) { return getImpl(Context, Tag, getCanonicalMDString(Context, Name), - SizeInBits, AlignInBits, Encoding, Storage, ShouldCreate); + SizeInBits, AlignInBytes, Encoding, Storage, ShouldCreate); } static DIBasicType *getImpl(LLVMContext &Context, unsigned Tag, MDString *Name, uint64_t SizeInBits, - uint64_t AlignInBits, unsigned Encoding, + uint64_t AlignInBytes, unsigned Encoding, StorageType Storage, bool ShouldCreate = true); TempDIBasicType cloneImpl() const { return getTemporary(getContext(), getTag(), getName(), getSizeInBits(), - getAlignInBits(), getEncoding()); + getAlignInBytes(), getEncoding()); } public: @@ -643,12 +643,12 @@ (Tag, Name, 0, 0, 0)) DEFINE_MDNODE_GET(DIBasicType, (unsigned Tag, StringRef Name, uint64_t SizeInBits, - uint64_t AlignInBits, unsigned Encoding), - (Tag, Name, SizeInBits, AlignInBits, Encoding)) + uint64_t AlignInBytes, unsigned Encoding), + (Tag, Name, SizeInBits, AlignInBytes, Encoding)) DEFINE_MDNODE_GET(DIBasicType, (unsigned Tag, MDString *Name, uint64_t SizeInBits, - uint64_t AlignInBits, unsigned Encoding), - (Tag, Name, SizeInBits, AlignInBits, Encoding)) + uint64_t AlignInBytes, unsigned Encoding), + (Tag, Name, SizeInBits, AlignInBytes, Encoding)) TempDIBasicType clone() const { return cloneImpl(); } @@ -670,27 +670,27 @@ friend class MDNode; DIDerivedType(LLVMContext &C, StorageType Storage, unsigned Tag, - unsigned Line, uint64_t SizeInBits, uint64_t AlignInBits, + unsigned Line, uint64_t SizeInBits, uint64_t AlignInBytes, uint64_t OffsetInBits, DIFlags Flags, ArrayRef Ops) : DIType(C, DIDerivedTypeKind, Storage, Tag, Line, SizeInBits, - AlignInBits, OffsetInBits, Flags, Ops) {} + AlignInBytes, OffsetInBits, Flags, Ops) {} ~DIDerivedType() = default; static DIDerivedType *getImpl(LLVMContext &Context, unsigned Tag, StringRef Name, DIFile *File, unsigned Line, DIScopeRef Scope, DITypeRef BaseType, - uint64_t SizeInBits, uint64_t AlignInBits, + uint64_t SizeInBits, uint64_t AlignInBytes, uint64_t OffsetInBits, DIFlags Flags, Metadata *ExtraData, StorageType Storage, bool ShouldCreate = true) { return getImpl(Context, Tag, getCanonicalMDString(Context, Name), File, - Line, Scope, BaseType, SizeInBits, AlignInBits, OffsetInBits, + Line, Scope, BaseType, SizeInBits, AlignInBytes, OffsetInBits, Flags, ExtraData, Storage, ShouldCreate); } static DIDerivedType *getImpl(LLVMContext &Context, unsigned Tag, MDString *Name, Metadata *File, unsigned Line, Metadata *Scope, Metadata *BaseType, - uint64_t SizeInBits, uint64_t AlignInBits, + uint64_t SizeInBits, uint64_t AlignInBytes, uint64_t OffsetInBits, DIFlags Flags, Metadata *ExtraData, StorageType Storage, bool ShouldCreate = true); @@ -698,7 +698,7 @@ TempDIDerivedType cloneImpl() const { return getTemporary(getContext(), getTag(), getName(), getFile(), getLine(), getScope(), getBaseType(), getSizeInBits(), - getAlignInBits(), getOffsetInBits(), getFlags(), + getAlignInBytes(), getOffsetInBits(), getFlags(), getExtraData()); } @@ -706,18 +706,18 @@ DEFINE_MDNODE_GET(DIDerivedType, (unsigned Tag, MDString *Name, Metadata *File, unsigned Line, Metadata *Scope, Metadata *BaseType, - uint64_t SizeInBits, uint64_t AlignInBits, + uint64_t SizeInBits, uint64_t AlignInBytes, uint64_t OffsetInBits, DIFlags Flags, Metadata *ExtraData = nullptr), (Tag, Name, File, Line, Scope, BaseType, SizeInBits, - AlignInBits, OffsetInBits, Flags, ExtraData)) + AlignInBytes, OffsetInBits, Flags, ExtraData)) DEFINE_MDNODE_GET(DIDerivedType, (unsigned Tag, StringRef Name, DIFile *File, unsigned Line, DIScopeRef Scope, DITypeRef BaseType, uint64_t SizeInBits, - uint64_t AlignInBits, uint64_t OffsetInBits, DIFlags Flags, + uint64_t AlignInBytes, uint64_t OffsetInBits, DIFlags Flags, Metadata *ExtraData = nullptr), (Tag, Name, File, Line, Scope, BaseType, SizeInBits, - AlignInBits, OffsetInBits, Flags, ExtraData)) + AlignInBytes, OffsetInBits, Flags, ExtraData)) TempDIDerivedType clone() const { return cloneImpl(); } @@ -775,40 +775,40 @@ DICompositeType(LLVMContext &C, StorageType Storage, unsigned Tag, unsigned Line, unsigned RuntimeLang, uint64_t SizeInBits, - uint64_t AlignInBits, uint64_t OffsetInBits, DIFlags Flags, + uint64_t AlignInBytes, uint64_t OffsetInBits, DIFlags Flags, ArrayRef Ops) : DIType(C, DICompositeTypeKind, Storage, Tag, Line, SizeInBits, - AlignInBits, OffsetInBits, Flags, Ops), + AlignInBytes, OffsetInBits, Flags, Ops), RuntimeLang(RuntimeLang) {} ~DICompositeType() = default; /// Change fields in place. void mutate(unsigned Tag, unsigned Line, unsigned RuntimeLang, - uint64_t SizeInBits, uint64_t AlignInBits, uint64_t OffsetInBits, + uint64_t SizeInBits, uint64_t AlignInBytes, uint64_t OffsetInBits, DIFlags Flags) { assert(isDistinct() && "Only distinct nodes can mutate"); assert(getRawIdentifier() && "Only ODR-uniqued nodes should mutate"); this->RuntimeLang = RuntimeLang; - DIType::mutate(Tag, Line, SizeInBits, AlignInBits, OffsetInBits, Flags); + DIType::mutate(Tag, Line, SizeInBits, AlignInBytes, OffsetInBits, Flags); } static DICompositeType * getImpl(LLVMContext &Context, unsigned Tag, StringRef Name, Metadata *File, unsigned Line, DIScopeRef Scope, DITypeRef BaseType, - uint64_t SizeInBits, uint64_t AlignInBits, uint64_t OffsetInBits, + uint64_t SizeInBits, uint64_t AlignInBytes, uint64_t OffsetInBits, DIFlags Flags, DINodeArray Elements, unsigned RuntimeLang, DITypeRef VTableHolder, DITemplateParameterArray TemplateParams, StringRef Identifier, StorageType Storage, bool ShouldCreate = true) { return getImpl( Context, Tag, getCanonicalMDString(Context, Name), File, Line, Scope, - BaseType, SizeInBits, AlignInBits, OffsetInBits, Flags, Elements.get(), + BaseType, SizeInBits, AlignInBytes, OffsetInBits, Flags, Elements.get(), RuntimeLang, VTableHolder, TemplateParams.get(), getCanonicalMDString(Context, Identifier), Storage, ShouldCreate); } static DICompositeType * getImpl(LLVMContext &Context, unsigned Tag, MDString *Name, Metadata *File, unsigned Line, Metadata *Scope, Metadata *BaseType, - uint64_t SizeInBits, uint64_t AlignInBits, uint64_t OffsetInBits, + uint64_t SizeInBits, uint64_t AlignInBytes, uint64_t OffsetInBits, DIFlags Flags, Metadata *Elements, unsigned RuntimeLang, Metadata *VTableHolder, Metadata *TemplateParams, MDString *Identifier, StorageType Storage, bool ShouldCreate = true); @@ -816,7 +816,7 @@ TempDICompositeType cloneImpl() const { return getTemporary(getContext(), getTag(), getName(), getFile(), getLine(), getScope(), getBaseType(), getSizeInBits(), - getAlignInBits(), getOffsetInBits(), getFlags(), + getAlignInBytes(), getOffsetInBits(), getFlags(), getElements(), getRuntimeLang(), getVTableHolder(), getTemplateParams(), getIdentifier()); } @@ -825,24 +825,24 @@ DEFINE_MDNODE_GET(DICompositeType, (unsigned Tag, StringRef Name, DIFile *File, unsigned Line, DIScopeRef Scope, DITypeRef BaseType, uint64_t SizeInBits, - uint64_t AlignInBits, uint64_t OffsetInBits, DIFlags Flags, + uint64_t AlignInBytes, uint64_t OffsetInBits, DIFlags Flags, DINodeArray Elements, unsigned RuntimeLang, DITypeRef VTableHolder, DITemplateParameterArray TemplateParams = nullptr, StringRef Identifier = ""), (Tag, Name, File, Line, Scope, BaseType, SizeInBits, - AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang, + AlignInBytes, OffsetInBits, Flags, Elements, RuntimeLang, VTableHolder, TemplateParams, Identifier)) DEFINE_MDNODE_GET(DICompositeType, (unsigned Tag, MDString *Name, Metadata *File, unsigned Line, Metadata *Scope, Metadata *BaseType, - uint64_t SizeInBits, uint64_t AlignInBits, + uint64_t SizeInBits, uint64_t AlignInBytes, uint64_t OffsetInBits, DIFlags Flags, Metadata *Elements, unsigned RuntimeLang, Metadata *VTableHolder, Metadata *TemplateParams = nullptr, MDString *Identifier = nullptr), (Tag, Name, File, Line, Scope, BaseType, SizeInBits, - AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang, + AlignInBytes, OffsetInBits, Flags, Elements, RuntimeLang, VTableHolder, TemplateParams, Identifier)) TempDICompositeType clone() const { return cloneImpl(); } @@ -857,7 +857,7 @@ static DICompositeType * getODRType(LLVMContext &Context, MDString &Identifier, unsigned Tag, MDString *Name, Metadata *File, unsigned Line, Metadata *Scope, - Metadata *BaseType, uint64_t SizeInBits, uint64_t AlignInBits, + Metadata *BaseType, uint64_t SizeInBits, uint64_t AlignInBytes, uint64_t OffsetInBits, DIFlags Flags, Metadata *Elements, unsigned RuntimeLang, Metadata *VTableHolder, Metadata *TemplateParams); @@ -876,7 +876,7 @@ static DICompositeType * buildODRType(LLVMContext &Context, MDString &Identifier, unsigned Tag, MDString *Name, Metadata *File, unsigned Line, Metadata *Scope, - Metadata *BaseType, uint64_t SizeInBits, uint64_t AlignInBits, + Metadata *BaseType, uint64_t SizeInBits, uint64_t AlignInBytes, uint64_t OffsetInBits, DIFlags Flags, Metadata *Elements, unsigned RuntimeLang, Metadata *VTableHolder, Metadata *TemplateParams); @@ -1826,11 +1826,13 @@ /// \brief Base class for variables. class DIVariable : public DINode { unsigned Line; + uint64_t AlignInBytes; protected: DIVariable(LLVMContext &C, unsigned ID, StorageType Storage, unsigned Line, - ArrayRef Ops) - : DINode(C, ID, Storage, dwarf::DW_TAG_variable, Ops), Line(Line) {} + ArrayRef Ops, uint64_t AlignInBytes = 0) + : DINode(C, ID, Storage, dwarf::DW_TAG_variable, Ops), Line(Line), + AlignInBytes(AlignInBytes) {} ~DIVariable() = default; public: @@ -1839,6 +1841,7 @@ StringRef getName() const { return getStringOperand(1); } DIFile *getFile() const { return cast_or_null(getRawFile()); } DITypeRef getType() const { return DITypeRef(getRawType()); } + uint64_t getAlignInBytes() const { return AlignInBytes; } StringRef getFilename() const { if (auto *F = getFile()) @@ -2026,9 +2029,9 @@ bool IsDefinition; DIGlobalVariable(LLVMContext &C, StorageType Storage, unsigned Line, - bool IsLocalToUnit, bool IsDefinition, + bool IsLocalToUnit, bool IsDefinition, uint64_t AlignInBytes, ArrayRef Ops) - : DIVariable(C, DIGlobalVariableKind, Storage, Line, Ops), + : DIVariable(C, DIGlobalVariableKind, Storage, Line, Ops, AlignInBytes), IsLocalToUnit(IsLocalToUnit), IsDefinition(IsDefinition) {} ~DIGlobalVariable() = default; @@ -2036,42 +2039,48 @@ 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 AlignInBytes, + 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, AlignInBytes, 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 AlignInBytes, + StorageType Storage, bool ShouldCreate = true); TempDIGlobalVariable cloneImpl() const { return getTemporary(getContext(), getScope(), getName(), getLinkageName(), getFile(), getLine(), getType(), isLocalToUnit(), isDefinition(), getExpr(), - getStaticDataMemberDeclaration()); + getStaticDataMemberDeclaration(), getAlignInBytes()); } 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 AlignInBytes), (Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, - IsDefinition, Expr, StaticDataMemberDeclaration)) + IsDefinition, Expr, StaticDataMemberDeclaration, + AlignInBytes)) 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 AlignInBytes), (Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, - IsDefinition, Expr, StaticDataMemberDeclaration)) + IsDefinition, Expr, StaticDataMemberDeclaration, + AlignInBytes)) TempDIGlobalVariable clone() const { return cloneImpl(); } @@ -2109,9 +2118,10 @@ DIFlags Flags; DILocalVariable(LLVMContext &C, StorageType Storage, unsigned Line, - unsigned Arg, DIFlags Flags, ArrayRef Ops) - : DIVariable(C, DILocalVariableKind, Storage, Line, Ops), Arg(Arg), - Flags(Flags) { + unsigned Arg, DIFlags Flags, uint64_t AlignInBytes, + ArrayRef Ops) + : DIVariable(C, DILocalVariableKind, Storage, Line, Ops, AlignInBytes), + Arg(Arg), Flags(Flags) { assert(Arg < (1 << 16) && "DILocalVariable: Arg out of range"); } ~DILocalVariable() = default; @@ -2119,33 +2129,34 @@ static DILocalVariable *getImpl(LLVMContext &Context, DIScope *Scope, StringRef Name, DIFile *File, unsigned Line, DITypeRef Type, unsigned Arg, DIFlags Flags, - StorageType Storage, + uint64_t AlignInBytes, StorageType Storage, bool ShouldCreate = true) { return getImpl(Context, Scope, getCanonicalMDString(Context, Name), File, - Line, Type, Arg, Flags, Storage, ShouldCreate); + Line, Type, Arg, Flags, AlignInBytes, 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 AlignInBytes, StorageType Storage, bool ShouldCreate = true); TempDILocalVariable cloneImpl() const { return getTemporary(getContext(), getScope(), getName(), getFile(), - getLine(), getType(), getArg(), getFlags()); + getLine(), getType(), getArg(), getFlags(), + getAlignInBytes()); } 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 AlignInBytes), + (Scope, Name, File, Line, Type, Arg, Flags, AlignInBytes)) 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 AlignInBytes), + (Scope, Name, File, Line, Type, Arg, Flags, AlignInBytes)) TempDILocalVariable clone() const { return cloneImpl(); } Index: lib/AsmParser/LLParser.cpp =================================================================== --- lib/AsmParser/LLParser.cpp +++ lib/AsmParser/LLParser.cpp @@ -4185,7 +4185,7 @@ /// ::= !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)); \ @@ -4197,22 +4197,26 @@ OPTIONAL(isLocal, MDBoolField, ); \ OPTIONAL(isDefinition, MDBoolField, (true)); \ OPTIONAL(expr, MDField, ); \ - OPTIONAL(declaration, MDField, ); + OPTIONAL(declaration, MDField, ); \ + OPTIONAL(align, MDUnsignedField, (0, UINT64_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)); \ @@ -4221,13 +4225,14 @@ OPTIONAL(file, MDField, ); \ OPTIONAL(line, LineField, ); \ OPTIONAL(type, MDField, ); \ - OPTIONAL(flags, DIFlagField, ); + OPTIONAL(flags, DIFlagField, ); \ + OPTIONAL(align, MDUnsignedField, (0, UINT64_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; } Index: lib/Bitcode/Reader/BitcodeReader.cpp =================================================================== --- lib/Bitcode/Reader/BitcodeReader.cpp +++ lib/Bitcode/Reader/BitcodeReader.cpp @@ -2732,7 +2732,7 @@ break; } case bitc::METADATA_GLOBAL_VAR: { - if (Record.size() != 11) + if (Record.size() < 11 || Record.size() > 12) return error("Invalid record"); IsDistinct = Record[0]; @@ -2740,6 +2740,7 @@ // Upgrade old metadata, which stored a global variable reference or a // ConstantInt here. Metadata *Expr = getMDOrNull(Record[9]); + uint64_t AlignInBytes = (Record.size() > 11) ? Record[11] : 0; GlobalVariable *Attach = nullptr; if (auto *CMD = dyn_cast_or_null(Expr)) { if (auto *GV = dyn_cast(CMD->getValue())) { @@ -2759,7 +2760,7 @@ (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]), AlignInBytes)); MetadataList.assignValue(DGV, NextMetadataNo++); if (Attach) @@ -2775,15 +2776,17 @@ // 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; + bool HasTag = Record.size() != 8; DINode::DIFlags Flags = static_cast(Record[7 + HasTag]); + // 11th field if exists contains alignment value + uint64_t AlignInBytes = (Record.size() > 9) ? Record[9] : 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, AlignInBytes)), NextMetadataNo++); break; } Index: lib/Bitcode/Writer/BitcodeWriter.cpp =================================================================== --- lib/Bitcode/Writer/BitcodeWriter.cpp +++ lib/Bitcode/Writer/BitcodeWriter.cpp @@ -1468,7 +1468,7 @@ Record.push_back(N->getTag()); Record.push_back(VE.getMetadataOrNullID(N->getRawName())); Record.push_back(N->getSizeInBits()); - Record.push_back(N->getAlignInBits()); + Record.push_back(N->getAlignInBytes()); Record.push_back(N->getEncoding()); Stream.EmitRecord(bitc::METADATA_BASIC_TYPE, Record, Abbrev); @@ -1486,7 +1486,7 @@ Record.push_back(VE.getMetadataOrNullID(N->getScope())); Record.push_back(VE.getMetadataOrNullID(N->getBaseType())); Record.push_back(N->getSizeInBits()); - Record.push_back(N->getAlignInBits()); + Record.push_back(N->getAlignInBytes()); Record.push_back(N->getOffsetInBits()); Record.push_back(N->getFlags()); Record.push_back(VE.getMetadataOrNullID(N->getExtraData())); @@ -1507,7 +1507,7 @@ Record.push_back(VE.getMetadataOrNullID(N->getScope())); Record.push_back(VE.getMetadataOrNullID(N->getBaseType())); Record.push_back(N->getSizeInBits()); - Record.push_back(N->getAlignInBits()); + Record.push_back(N->getAlignInBytes()); Record.push_back(N->getOffsetInBits()); Record.push_back(N->getFlags()); Record.push_back(VE.getMetadataOrNullID(N->getElements().get())); @@ -1712,6 +1712,7 @@ Record.push_back(N->isDefinition()); Record.push_back(VE.getMetadataOrNullID(N->getRawExpr())); Record.push_back(VE.getMetadataOrNullID(N->getStaticDataMemberDeclaration())); + Record.push_back(N->getAlignInBytes()); Stream.EmitRecord(bitc::METADATA_GLOBAL_VAR, Record, Abbrev); Record.clear(); @@ -1721,6 +1722,8 @@ const DILocalVariable *N, SmallVectorImpl &Record, unsigned Abbrev) { Record.push_back(N->isDistinct()); + // Fake tag value for backwards compatibility + Record.push_back((uint64_t)-1); Record.push_back(VE.getMetadataOrNullID(N->getScope())); Record.push_back(VE.getMetadataOrNullID(N->getRawName())); Record.push_back(VE.getMetadataOrNullID(N->getFile())); @@ -1728,6 +1731,7 @@ Record.push_back(VE.getMetadataOrNullID(N->getType())); Record.push_back(N->getArg()); Record.push_back(N->getFlags()); + Record.push_back(N->getAlignInBytes()); Stream.EmitRecord(bitc::METADATA_LOCAL_VAR, Record, Abbrev); Record.clear(); Index: lib/CodeGen/AsmPrinter/DwarfUnit.cpp =================================================================== --- lib/CodeGen/AsmPrinter/DwarfUnit.cpp +++ lib/CodeGen/AsmPrinter/DwarfUnit.cpp @@ -1404,8 +1404,11 @@ addUInt(MemberDie, dwarf::DW_AT_bit_size, None, Size); uint64_t Offset = DT->getOffsetInBits(); - uint64_t Align = DT->getAlignInBits() ? DT->getAlignInBits() : FieldSize; - uint64_t AlignMask = ~(Align - 1); + // We can't use DT->getAlignInBytes() here: AlignInBytes for member type + // if non-zero if and only if alignment was forced (e.g. _Alignas()), + // which can't be done with bitfields. Thus we use FieldSize here. + uint64_t AlignInBits = FieldSize; + uint64_t AlignMask = ~(AlignInBits - 1); // The bits from the start of the storage unit to the start of the field. uint64_t StartBitOffset = Offset - (Offset & AlignMask); // The byte offset of the field's aligned storage unit inside the struct. Index: lib/IR/AsmWriter.cpp =================================================================== --- lib/IR/AsmWriter.cpp +++ lib/IR/AsmWriter.cpp @@ -1573,7 +1573,7 @@ Printer.printTag(N); Printer.printString("name", N->getName()); Printer.printInt("size", N->getSizeInBits()); - Printer.printInt("align", N->getAlignInBits()); + Printer.printInt("align", N->getAlignInBytes()); Printer.printDwarfEnum("encoding", N->getEncoding(), dwarf::AttributeEncodingString); Out << ")"; @@ -1592,7 +1592,7 @@ Printer.printMetadata("baseType", N->getRawBaseType(), /* ShouldSkipNull */ false); Printer.printInt("size", N->getSizeInBits()); - Printer.printInt("align", N->getAlignInBits()); + Printer.printInt("align", N->getAlignInBytes()); Printer.printInt("offset", N->getOffsetInBits()); Printer.printDIFlags("flags", N->getFlags()); Printer.printMetadata("extraData", N->getRawExtraData()); @@ -1611,7 +1611,7 @@ Printer.printInt("line", N->getLine()); Printer.printMetadata("baseType", N->getRawBaseType()); Printer.printInt("size", N->getSizeInBits()); - Printer.printInt("align", N->getAlignInBits()); + Printer.printInt("align", N->getAlignInBytes()); Printer.printInt("offset", N->getOffsetInBits()); Printer.printDIFlags("flags", N->getFlags()); Printer.printMetadata("elements", N->getRawElements()); @@ -1818,6 +1818,7 @@ Printer.printBool("isDefinition", N->isDefinition()); Printer.printMetadata("expr", N->getExpr()); Printer.printMetadata("declaration", N->getRawStaticDataMemberDeclaration()); + Printer.printInt("align", N->getAlignInBytes()); Out << ")"; } @@ -1833,6 +1834,7 @@ Printer.printInt("line", N->getLine()); Printer.printMetadata("type", N->getRawType()); Printer.printDIFlags("flags", N->getFlags()); + Printer.printInt("align", N->getAlignInBytes()); Out << ")"; } Index: lib/IR/DIBuilder.cpp =================================================================== --- lib/IR/DIBuilder.cpp +++ lib/IR/DIBuilder.cpp @@ -535,28 +535,28 @@ DIGlobalVariable *DIBuilder::createGlobalVariable( DIScope *Context, StringRef Name, StringRef LinkageName, DIFile *F, - unsigned LineNumber, DIType *Ty, bool isLocalToUnit, DIExpression *Expr, - MDNode *Decl) { + unsigned LineNumber, DIType *Ty, bool isLocalToUnit, + DIExpression *Expr, MDNode *Decl, uint64_t AlignInBytes) { checkGlobalVariableScope(Context); auto *N = DIGlobalVariable::getDistinct( VMContext, cast_or_null(Context), Name, LinkageName, F, LineNumber, Ty, isLocalToUnit, true, Expr, - cast_or_null(Decl)); + cast_or_null(Decl), AlignInBytes); AllGVs.push_back(N); return N; } DIGlobalVariable *DIBuilder::createTempGlobalVariableFwdDecl( DIScope *Context, StringRef Name, StringRef LinkageName, DIFile *F, - unsigned LineNumber, DIType *Ty, bool isLocalToUnit, DIExpression *Expr, - MDNode *Decl) { + unsigned LineNumber, DIType *Ty, bool isLocalToUnit, + DIExpression *Expr, MDNode *Decl, uint64_t AlignInBytes) { checkGlobalVariableScope(Context); return DIGlobalVariable::getTemporary( VMContext, cast_or_null(Context), Name, LinkageName, F, LineNumber, Ty, isLocalToUnit, false, Expr, - cast_or_null(Decl)) + cast_or_null(Decl), AlignInBytes) .release(); } @@ -564,7 +564,8 @@ LLVMContext &VMContext, DenseMap> &PreservedVariables, DIScope *Scope, StringRef Name, unsigned ArgNo, DIFile *File, - unsigned LineNo, DIType *Ty, bool AlwaysPreserve, DINode::DIFlags Flags) { + unsigned LineNo, DIType *Ty, bool AlwaysPreserve, DINode::DIFlags Flags, + uint64_t AlignInBytes) { // FIXME: Why getNonCompileUnitScope()? // FIXME: Why is "!Context" okay here? // FIXME: Why doesn't this check for a subprogram or lexical block (AFAICT @@ -573,7 +574,7 @@ auto *Node = DILocalVariable::get(VMContext, cast_or_null(Context), Name, - File, LineNo, Ty, ArgNo, Flags); + File, LineNo, Ty, ArgNo, Flags, AlignInBytes); if (AlwaysPreserve) { // The optimizer may remove local variables. If there is an interest // to preserve variable info in such situation then stash it in a @@ -588,10 +589,11 @@ DILocalVariable *DIBuilder::createAutoVariable(DIScope *Scope, StringRef Name, DIFile *File, unsigned LineNo, DIType *Ty, bool AlwaysPreserve, - DINode::DIFlags Flags) { + DINode::DIFlags Flags, + uint64_t AlignInBytes) { return createLocalVariable(VMContext, PreservedVariables, Scope, Name, /* ArgNo */ 0, File, LineNo, Ty, AlwaysPreserve, - Flags); + Flags, AlignInBytes); } DILocalVariable *DIBuilder::createParameterVariable( @@ -599,7 +601,8 @@ unsigned LineNo, DIType *Ty, bool AlwaysPreserve, DINode::DIFlags Flags) { assert(ArgNo && "Expected non-zero argument number for parameter"); return createLocalVariable(VMContext, PreservedVariables, Scope, Name, ArgNo, - File, LineNo, Ty, AlwaysPreserve, Flags); + File, LineNo, Ty, AlwaysPreserve, Flags, + /* AlignInBytes */0); } DIExpression *DIBuilder::createExpression(ArrayRef Addr) { Index: lib/IR/DebugInfoMetadata.cpp =================================================================== --- lib/IR/DebugInfoMetadata.cpp +++ lib/IR/DebugInfoMetadata.cpp @@ -227,35 +227,35 @@ DIBasicType *DIBasicType::getImpl(LLVMContext &Context, unsigned Tag, MDString *Name, uint64_t SizeInBits, - uint64_t AlignInBits, unsigned Encoding, + uint64_t AlignInBytes, unsigned Encoding, StorageType Storage, bool ShouldCreate) { assert(isCanonical(Name) && "Expected canonical MDString"); DEFINE_GETIMPL_LOOKUP(DIBasicType, - (Tag, Name, SizeInBits, AlignInBits, Encoding)); + (Tag, Name, SizeInBits, AlignInBytes, Encoding)); Metadata *Ops[] = {nullptr, nullptr, Name}; - DEFINE_GETIMPL_STORE(DIBasicType, (Tag, SizeInBits, AlignInBits, Encoding), + DEFINE_GETIMPL_STORE(DIBasicType, (Tag, SizeInBits, AlignInBytes, Encoding), Ops); } DIDerivedType *DIDerivedType::getImpl( LLVMContext &Context, unsigned Tag, MDString *Name, Metadata *File, unsigned Line, Metadata *Scope, Metadata *BaseType, uint64_t SizeInBits, - uint64_t AlignInBits, uint64_t OffsetInBits, DIFlags Flags, + uint64_t AlignInBytes, uint64_t OffsetInBits, DIFlags Flags, Metadata *ExtraData, StorageType Storage, bool ShouldCreate) { assert(isCanonical(Name) && "Expected canonical MDString"); DEFINE_GETIMPL_LOOKUP(DIDerivedType, (Tag, Name, File, Line, Scope, BaseType, SizeInBits, - AlignInBits, OffsetInBits, Flags, ExtraData)); + AlignInBytes, OffsetInBits, Flags, ExtraData)); Metadata *Ops[] = {File, Scope, Name, BaseType, ExtraData}; DEFINE_GETIMPL_STORE( - DIDerivedType, (Tag, Line, SizeInBits, AlignInBits, OffsetInBits, Flags), + DIDerivedType, (Tag, Line, SizeInBits, AlignInBytes, OffsetInBits, Flags), Ops); } DICompositeType *DICompositeType::getImpl( LLVMContext &Context, unsigned Tag, MDString *Name, Metadata *File, unsigned Line, Metadata *Scope, Metadata *BaseType, uint64_t SizeInBits, - uint64_t AlignInBits, uint64_t OffsetInBits, DIFlags Flags, + uint64_t AlignInBytes, uint64_t OffsetInBits, DIFlags Flags, Metadata *Elements, unsigned RuntimeLang, Metadata *VTableHolder, Metadata *TemplateParams, MDString *Identifier, StorageType Storage, bool ShouldCreate) { @@ -264,19 +264,19 @@ // Keep this in sync with buildODRType. DEFINE_GETIMPL_LOOKUP( DICompositeType, (Tag, Name, File, Line, Scope, BaseType, SizeInBits, - AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang, + AlignInBytes, OffsetInBits, Flags, Elements, RuntimeLang, VTableHolder, TemplateParams, Identifier)); Metadata *Ops[] = {File, Scope, Name, BaseType, Elements, VTableHolder, TemplateParams, Identifier}; DEFINE_GETIMPL_STORE(DICompositeType, (Tag, Line, RuntimeLang, SizeInBits, - AlignInBits, OffsetInBits, Flags), + AlignInBytes, OffsetInBits, Flags), Ops); } DICompositeType *DICompositeType::buildODRType( LLVMContext &Context, MDString &Identifier, unsigned Tag, MDString *Name, Metadata *File, unsigned Line, Metadata *Scope, Metadata *BaseType, - uint64_t SizeInBits, uint64_t AlignInBits, uint64_t OffsetInBits, + uint64_t SizeInBits, uint64_t AlignInBytes, uint64_t OffsetInBits, DIFlags Flags, Metadata *Elements, unsigned RuntimeLang, Metadata *VTableHolder, Metadata *TemplateParams) { assert(!Identifier.getString().empty() && "Expected valid identifier"); @@ -286,7 +286,7 @@ if (!CT) return CT = DICompositeType::getDistinct( Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, - AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang, + AlignInBytes, OffsetInBits, Flags, Elements, RuntimeLang, VTableHolder, TemplateParams, &Identifier); // Only mutate CT if it's a forward declaration and the new operands aren't. @@ -295,7 +295,7 @@ return CT; // Mutate CT in place. Keep this in sync with getImpl. - CT->mutate(Tag, Line, RuntimeLang, SizeInBits, AlignInBits, OffsetInBits, + CT->mutate(Tag, Line, RuntimeLang, SizeInBits, AlignInBytes, OffsetInBits, Flags); Metadata *Ops[] = {File, Scope, Name, BaseType, Elements, VTableHolder, TemplateParams, &Identifier}; @@ -310,7 +310,7 @@ DICompositeType *DICompositeType::getODRType( LLVMContext &Context, MDString &Identifier, unsigned Tag, MDString *Name, Metadata *File, unsigned Line, Metadata *Scope, Metadata *BaseType, - uint64_t SizeInBits, uint64_t AlignInBits, uint64_t OffsetInBits, + uint64_t SizeInBits, uint64_t AlignInBytes, uint64_t OffsetInBits, DIFlags Flags, Metadata *Elements, unsigned RuntimeLang, Metadata *VTableHolder, Metadata *TemplateParams) { assert(!Identifier.getString().empty() && "Expected valid identifier"); @@ -320,7 +320,7 @@ if (!CT) CT = DICompositeType::getDistinct( Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, - AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang, VTableHolder, + AlignInBytes, OffsetInBits, Flags, Elements, RuntimeLang, VTableHolder, TemplateParams, &Identifier); return CT; } @@ -510,16 +510,18 @@ Metadata *Type, bool IsLocalToUnit, bool IsDefinition, Metadata *Variable, Metadata *StaticDataMemberDeclaration, + uint64_t AlignInBytes, StorageType Storage, bool ShouldCreate) { assert(isCanonical(Name) && "Expected canonical MDString"); assert(isCanonical(LinkageName) && "Expected canonical MDString"); DEFINE_GETIMPL_LOOKUP(DIGlobalVariable, (Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, IsDefinition, Variable, - StaticDataMemberDeclaration)); + StaticDataMemberDeclaration, AlignInBytes)); Metadata *Ops[] = {Scope, Name, File, Type, Name, LinkageName, Variable, StaticDataMemberDeclaration}; - DEFINE_GETIMPL_STORE(DIGlobalVariable, (Line, IsLocalToUnit, IsDefinition), + DEFINE_GETIMPL_STORE(DIGlobalVariable, + (Line, IsLocalToUnit, IsDefinition, AlignInBytes), Ops); } @@ -527,6 +529,7 @@ MDString *Name, Metadata *File, unsigned Line, Metadata *Type, unsigned Arg, DIFlags Flags, + uint64_t AlignInBytes, StorageType Storage, bool ShouldCreate) { // 64K ought to be enough for any frontend. @@ -535,9 +538,10 @@ assert(Scope && "Expected scope"); assert(isCanonical(Name) && "Expected canonical MDString"); DEFINE_GETIMPL_LOOKUP(DILocalVariable, - (Scope, Name, File, Line, Type, Arg, Flags)); + (Scope, Name, File, Line, Type, Arg, Flags, + AlignInBytes)); Metadata *Ops[] = {Scope, Name, File, Type}; - DEFINE_GETIMPL_STORE(DILocalVariable, (Line, Arg, Flags), Ops); + DEFINE_GETIMPL_STORE(DILocalVariable, (Line, Arg, Flags, AlignInBytes), Ops); } DIExpression *DIExpression::getImpl(LLVMContext &Context, Index: lib/IR/LLVMContextImpl.h =================================================================== --- lib/IR/LLVMContextImpl.h +++ lib/IR/LLVMContextImpl.h @@ -319,25 +319,25 @@ unsigned Tag; MDString *Name; uint64_t SizeInBits; - uint64_t AlignInBits; + uint64_t AlignInBytes; unsigned Encoding; MDNodeKeyImpl(unsigned Tag, MDString *Name, uint64_t SizeInBits, - uint64_t AlignInBits, unsigned Encoding) - : Tag(Tag), Name(Name), SizeInBits(SizeInBits), AlignInBits(AlignInBits), + uint64_t AlignInBytes, unsigned Encoding) + : Tag(Tag), Name(Name), SizeInBits(SizeInBits), AlignInBytes(AlignInBytes), Encoding(Encoding) {} MDNodeKeyImpl(const DIBasicType *N) : Tag(N->getTag()), Name(N->getRawName()), SizeInBits(N->getSizeInBits()), - AlignInBits(N->getAlignInBits()), Encoding(N->getEncoding()) {} + AlignInBytes(N->getAlignInBytes()), Encoding(N->getEncoding()) {} bool isKeyOf(const DIBasicType *RHS) const { return Tag == RHS->getTag() && Name == RHS->getRawName() && SizeInBits == RHS->getSizeInBits() && - AlignInBits == RHS->getAlignInBits() && + AlignInBytes == RHS->getAlignInBytes() && Encoding == RHS->getEncoding(); } unsigned getHashValue() const { - return hash_combine(Tag, Name, SizeInBits, AlignInBits, Encoding); + return hash_combine(Tag, Name, SizeInBits, AlignInBytes, Encoding); } }; @@ -349,23 +349,23 @@ Metadata *Scope; Metadata *BaseType; uint64_t SizeInBits; - uint64_t AlignInBits; + uint64_t AlignInBytes; uint64_t OffsetInBits; unsigned Flags; Metadata *ExtraData; MDNodeKeyImpl(unsigned Tag, MDString *Name, Metadata *File, unsigned Line, Metadata *Scope, Metadata *BaseType, uint64_t SizeInBits, - uint64_t AlignInBits, uint64_t OffsetInBits, unsigned Flags, + uint64_t AlignInBytes, uint64_t OffsetInBits, unsigned Flags, Metadata *ExtraData) : Tag(Tag), Name(Name), File(File), Line(Line), Scope(Scope), - BaseType(BaseType), SizeInBits(SizeInBits), AlignInBits(AlignInBits), + BaseType(BaseType), SizeInBits(SizeInBits), AlignInBytes(AlignInBytes), OffsetInBits(OffsetInBits), Flags(Flags), ExtraData(ExtraData) {} MDNodeKeyImpl(const DIDerivedType *N) : Tag(N->getTag()), Name(N->getRawName()), File(N->getRawFile()), Line(N->getLine()), Scope(N->getRawScope()), BaseType(N->getRawBaseType()), SizeInBits(N->getSizeInBits()), - AlignInBits(N->getAlignInBits()), OffsetInBits(N->getOffsetInBits()), + AlignInBytes(N->getAlignInBytes()), OffsetInBits(N->getOffsetInBits()), Flags(N->getFlags()), ExtraData(N->getRawExtraData()) {} bool isKeyOf(const DIDerivedType *RHS) const { @@ -373,7 +373,7 @@ File == RHS->getRawFile() && Line == RHS->getLine() && Scope == RHS->getRawScope() && BaseType == RHS->getRawBaseType() && SizeInBits == RHS->getSizeInBits() && - AlignInBits == RHS->getAlignInBits() && + AlignInBytes == RHS->getAlignInBytes() && OffsetInBits == RHS->getOffsetInBits() && Flags == RHS->getFlags() && ExtraData == RHS->getRawExtraData(); } @@ -430,7 +430,7 @@ Metadata *Scope; Metadata *BaseType; uint64_t SizeInBits; - uint64_t AlignInBits; + uint64_t AlignInBytes; uint64_t OffsetInBits; unsigned Flags; Metadata *Elements; @@ -441,12 +441,12 @@ MDNodeKeyImpl(unsigned Tag, MDString *Name, Metadata *File, unsigned Line, Metadata *Scope, Metadata *BaseType, uint64_t SizeInBits, - uint64_t AlignInBits, uint64_t OffsetInBits, unsigned Flags, + uint64_t AlignInBytes, uint64_t OffsetInBits, unsigned Flags, Metadata *Elements, unsigned RuntimeLang, Metadata *VTableHolder, Metadata *TemplateParams, MDString *Identifier) : Tag(Tag), Name(Name), File(File), Line(Line), Scope(Scope), - BaseType(BaseType), SizeInBits(SizeInBits), AlignInBits(AlignInBits), + BaseType(BaseType), SizeInBits(SizeInBits), AlignInBytes(AlignInBytes), OffsetInBits(OffsetInBits), Flags(Flags), Elements(Elements), RuntimeLang(RuntimeLang), VTableHolder(VTableHolder), TemplateParams(TemplateParams), Identifier(Identifier) {} @@ -454,7 +454,7 @@ : Tag(N->getTag()), Name(N->getRawName()), File(N->getRawFile()), Line(N->getLine()), Scope(N->getRawScope()), BaseType(N->getRawBaseType()), SizeInBits(N->getSizeInBits()), - AlignInBits(N->getAlignInBits()), OffsetInBits(N->getOffsetInBits()), + AlignInBytes(N->getAlignInBytes()), OffsetInBits(N->getOffsetInBits()), Flags(N->getFlags()), Elements(N->getRawElements()), RuntimeLang(N->getRuntimeLang()), VTableHolder(N->getRawVTableHolder()), TemplateParams(N->getRawTemplateParams()), @@ -465,7 +465,7 @@ File == RHS->getRawFile() && Line == RHS->getLine() && Scope == RHS->getRawScope() && BaseType == RHS->getRawBaseType() && SizeInBits == RHS->getSizeInBits() && - AlignInBits == RHS->getAlignInBits() && + AlignInBytes == RHS->getAlignInBytes() && OffsetInBits == RHS->getOffsetInBits() && Flags == RHS->getFlags() && Elements == RHS->getRawElements() && RuntimeLang == RHS->getRuntimeLang() && @@ -761,22 +761,26 @@ bool IsDefinition; Metadata *Expr; Metadata *StaticDataMemberDeclaration; + uint64_t AlignInBytes; MDNodeKeyImpl(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 AlignInBytes) : Scope(Scope), Name(Name), LinkageName(LinkageName), File(File), Line(Line), Type(Type), IsLocalToUnit(IsLocalToUnit), IsDefinition(IsDefinition), Expr(Expr), - StaticDataMemberDeclaration(StaticDataMemberDeclaration) {} + StaticDataMemberDeclaration(StaticDataMemberDeclaration), + AlignInBytes(AlignInBytes) {} MDNodeKeyImpl(const DIGlobalVariable *N) : Scope(N->getRawScope()), Name(N->getRawName()), LinkageName(N->getRawLinkageName()), File(N->getRawFile()), Line(N->getLine()), Type(N->getRawType()), IsLocalToUnit(N->isLocalToUnit()), IsDefinition(N->isDefinition()), Expr(N->getRawExpr()), - StaticDataMemberDeclaration(N->getRawStaticDataMemberDeclaration()) {} + StaticDataMemberDeclaration(N->getRawStaticDataMemberDeclaration()), + AlignInBytes(N->getAlignInBytes()) {} bool isKeyOf(const DIGlobalVariable *RHS) const { return Scope == RHS->getRawScope() && Name == RHS->getRawName() && @@ -786,11 +790,19 @@ IsDefinition == RHS->isDefinition() && Expr == RHS->getRawExpr() && StaticDataMemberDeclaration == - RHS->getRawStaticDataMemberDeclaration(); + RHS->getRawStaticDataMemberDeclaration() && + AlignInBytes == RHS->getAlignInBytes(); } unsigned getHashValue() const { + // We do not use AlignInBytes in hashing function here on purpose: + // in most cases this param for local variable is zero (for function param + // it is always zero). This leads to lots of hash collisions and errors on + // cases with lots of similar variables. + // clang/test/CodeGen/debug-info-257-args.c is an example of this problem, + // generated IR is random for each run and test fails with Align included. + // TODO: make hashing work fine with such situations return hash_combine(Scope, Name, LinkageName, File, Line, Type, - IsLocalToUnit, IsDefinition, Expr, + IsLocalToUnit, IsDefinition, /* AlignInBytes, */ Expr, StaticDataMemberDeclaration); } }; @@ -803,23 +815,32 @@ Metadata *Type; unsigned Arg; unsigned Flags; + uint64_t AlignInBytes; MDNodeKeyImpl(Metadata *Scope, MDString *Name, Metadata *File, unsigned Line, - Metadata *Type, unsigned Arg, unsigned Flags) + Metadata *Type, unsigned Arg, unsigned Flags, + uint64_t AlignInBytes) : Scope(Scope), Name(Name), File(File), Line(Line), Type(Type), Arg(Arg), - Flags(Flags) {} + Flags(Flags), AlignInBytes(AlignInBytes) {} MDNodeKeyImpl(const DILocalVariable *N) : Scope(N->getRawScope()), Name(N->getRawName()), File(N->getRawFile()), Line(N->getLine()), Type(N->getRawType()), Arg(N->getArg()), - Flags(N->getFlags()) {} + Flags(N->getFlags()), AlignInBytes(N->getAlignInBytes()) {} bool isKeyOf(const DILocalVariable *RHS) const { return Scope == RHS->getRawScope() && Name == RHS->getRawName() && File == RHS->getRawFile() && Line == RHS->getLine() && Type == RHS->getRawType() && Arg == RHS->getArg() && - Flags == RHS->getFlags(); + Flags == RHS->getFlags() && AlignInBytes == RHS->getAlignInBytes(); } unsigned getHashValue() const { + // We do not use AlignInBytes in hashing function here on purpose: + // in most cases this param for local variable is zero (for function param + // it is always zero). This leads to lots of hash collisions and errors on + // cases with lots of similar variables. + // clang/test/CodeGen/debug-info-257-args.c is an example of this problem, + // generated IR is random for each run and test fails with Align included. + // TODO: make hashing work fine with such situations return hash_combine(Scope, Name, File, Line, Type, Arg, Flags); } }; Index: test/Assembler/diglobalvariable.ll =================================================================== --- test/Assembler/diglobalvariable.ll +++ test/Assembler/diglobalvariable.ll @@ -12,10 +12,10 @@ !3 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed) !4 = distinct !{} -; CHECK: !5 = !DIGlobalVariable(name: "foo", linkageName: "foo", scope: !0, file: !2, line: 7, type: !3, isLocal: true, isDefinition: false) +; CHECK: !5 = !DIGlobalVariable(name: "foo", linkageName: "foo", scope: !0, file: !2, line: 7, type: !3, isLocal: true, isDefinition: false, align: 32) !5 = !DIGlobalVariable(name: "foo", linkageName: "foo", scope: !0, file: !2, line: 7, type: !3, isLocal: true, - isDefinition: false) + isDefinition: false, align: 32) ; CHECK: !6 = !DIGlobalVariable(name: "foo", scope: !0, isLocal: false, isDefinition: true, expr: !7) ; CHECK: !7 = !DIExpression(DW_OP_constu, 42, DW_OP_stack_value) Index: test/Assembler/dilocalvariable.ll =================================================================== --- test/Assembler/dilocalvariable.ll +++ test/Assembler/dilocalvariable.ll @@ -18,11 +18,11 @@ !3 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed) !4 = !DILocation(scope: !0) -; CHECK: !5 = !DILocalVariable(name: "foo", arg: 3, scope: !0, file: !2, line: 7, type: !3, flags: DIFlagArtificial) +; CHECK: !5 = !DILocalVariable(name: "foo", arg: 3, scope: !0, file: !2, line: 7, type: !3, flags: DIFlagArtificial, align: 32) ; CHECK: !6 = !DILocalVariable(name: "foo", scope: !0, file: !2, line: 7, type: !3, flags: DIFlagArtificial) !5 = !DILocalVariable(name: "foo", arg: 3, scope: !0, file: !2, line: 7, type: !3, - flags: DIFlagArtificial) + flags: DIFlagArtificial, align: 32) !6 = !DILocalVariable(name: "foo", scope: !0, file: !2, line: 7, type: !3, flags: DIFlagArtificial) Index: unittests/IR/DebugTypeODRUniquingTest.cpp =================================================================== --- unittests/IR/DebugTypeODRUniquingTest.cpp +++ unittests/IR/DebugTypeODRUniquingTest.cpp @@ -123,7 +123,7 @@ DO_FOR_FIELD(Tag) \ DO_FOR_FIELD(Line) \ DO_FOR_FIELD(SizeInBits) \ - DO_FOR_FIELD(AlignInBits) \ + DO_FOR_FIELD(AlignInBytes) \ DO_FOR_FIELD(OffsetInBits) \ DO_FOR_FIELD(RuntimeLang) @@ -140,7 +140,7 @@ EXPECT_EQ(&CT, DICompositeType::buildODRType( Context, UUID, Tag, Name, File, Line, Scope, BaseType, - SizeInBits, AlignInBits, OffsetInBits, DINode::FlagArtificial, + SizeInBits, AlignInBytes, OffsetInBits, DINode::FlagArtificial, Elements, RuntimeLang, VTableHolder, TemplateParams)); // Confirm that all the right fields got updated. Index: unittests/IR/MetadataTest.cpp =================================================================== --- unittests/IR/MetadataTest.cpp +++ unittests/IR/MetadataTest.cpp @@ -974,7 +974,7 @@ EXPECT_EQ(dwarf::DW_TAG_base_type, N->getTag()); EXPECT_EQ("special", N->getName()); EXPECT_EQ(33u, N->getSizeInBits()); - EXPECT_EQ(26u, N->getAlignInBits()); + EXPECT_EQ(26u, N->getAlignInBytes()); EXPECT_EQ(7u, N->getEncoding()); EXPECT_EQ(0u, N->getLine()); EXPECT_EQ(N, DIBasicType::get(Context, dwarf::DW_TAG_base_type, "special", 33, @@ -999,7 +999,7 @@ auto *N = DIBasicType::get(Context, dwarf::DW_TAG_base_type, "special", UINT64_MAX, UINT64_MAX - 1, 7); EXPECT_EQ(UINT64_MAX, N->getSizeInBits()); - EXPECT_EQ(UINT64_MAX - 1, N->getAlignInBits()); + EXPECT_EQ(UINT64_MAX - 1, N->getAlignInBytes()); } TEST_F(DIBasicTypeTest, getUnspecified) { @@ -1008,7 +1008,7 @@ EXPECT_EQ(dwarf::DW_TAG_unspecified_type, N->getTag()); EXPECT_EQ("unspecified", N->getName()); EXPECT_EQ(0u, N->getSizeInBits()); - EXPECT_EQ(0u, N->getAlignInBits()); + EXPECT_EQ(0u, N->getAlignInBytes()); EXPECT_EQ(0u, N->getEncoding()); EXPECT_EQ(0u, N->getLine()); } @@ -1066,7 +1066,7 @@ EXPECT_EQ(Scope, N->getScope()); EXPECT_EQ(BaseType, N->getBaseType()); EXPECT_EQ(2u, N->getSizeInBits()); - EXPECT_EQ(3u, N->getAlignInBits()); + EXPECT_EQ(3u, N->getAlignInBytes()); EXPECT_EQ(4u, N->getOffsetInBits()); EXPECT_EQ(5u, N->getFlags()); EXPECT_EQ(ExtraData, N->getExtraData()); @@ -1123,7 +1123,7 @@ Context, dwarf::DW_TAG_pointer_type, "something", File, 1, Scope, BaseType, UINT64_MAX, UINT64_MAX - 1, UINT64_MAX - 2, Flags, ExtraData); EXPECT_EQ(UINT64_MAX, N->getSizeInBits()); - EXPECT_EQ(UINT64_MAX - 1, N->getAlignInBits()); + EXPECT_EQ(UINT64_MAX - 1, N->getAlignInBytes()); EXPECT_EQ(UINT64_MAX - 2, N->getOffsetInBits()); } @@ -1137,7 +1137,7 @@ DIScope *Scope = getSubprogram(); DIType *BaseType = getCompositeType(); uint64_t SizeInBits = 2; - uint64_t AlignInBits = 3; + uint64_t AlignInBytes = 3; uint64_t OffsetInBits = 4; DINode::DIFlags Flags = static_cast(5); MDTuple *Elements = getTuple(); @@ -1147,7 +1147,7 @@ StringRef Identifier = "some id"; auto *N = DICompositeType::get(Context, Tag, Name, File, Line, Scope, - BaseType, SizeInBits, AlignInBits, + BaseType, SizeInBits, AlignInBytes, OffsetInBits, Flags, Elements, RuntimeLang, VTableHolder, TemplateParams, Identifier); EXPECT_EQ(Tag, N->getTag()); @@ -1157,7 +1157,7 @@ EXPECT_EQ(Scope, N->getScope()); EXPECT_EQ(BaseType, N->getBaseType()); EXPECT_EQ(SizeInBits, N->getSizeInBits()); - EXPECT_EQ(AlignInBits, N->getAlignInBits()); + EXPECT_EQ(AlignInBytes, N->getAlignInBytes()); EXPECT_EQ(OffsetInBits, N->getOffsetInBits()); EXPECT_EQ(Flags, N->getFlags()); EXPECT_EQ(Elements, N->getElements().get()); @@ -1167,80 +1167,80 @@ EXPECT_EQ(Identifier, N->getIdentifier()); EXPECT_EQ(N, DICompositeType::get(Context, Tag, Name, File, Line, Scope, - BaseType, SizeInBits, AlignInBits, + BaseType, SizeInBits, AlignInBytes, OffsetInBits, Flags, Elements, RuntimeLang, VTableHolder, TemplateParams, Identifier)); EXPECT_NE(N, DICompositeType::get(Context, Tag + 1, Name, File, Line, Scope, - BaseType, SizeInBits, AlignInBits, + BaseType, SizeInBits, AlignInBytes, OffsetInBits, Flags, Elements, RuntimeLang, VTableHolder, TemplateParams, Identifier)); EXPECT_NE(N, DICompositeType::get(Context, Tag, "abc", File, Line, Scope, - BaseType, SizeInBits, AlignInBits, + BaseType, SizeInBits, AlignInBytes, OffsetInBits, Flags, Elements, RuntimeLang, VTableHolder, TemplateParams, Identifier)); EXPECT_NE(N, DICompositeType::get(Context, Tag, Name, getFile(), Line, Scope, - BaseType, SizeInBits, AlignInBits, + BaseType, SizeInBits, AlignInBytes, OffsetInBits, Flags, Elements, RuntimeLang, VTableHolder, TemplateParams, Identifier)); EXPECT_NE(N, DICompositeType::get(Context, Tag, Name, File, Line + 1, Scope, - BaseType, SizeInBits, AlignInBits, + BaseType, SizeInBits, AlignInBytes, OffsetInBits, Flags, Elements, RuntimeLang, VTableHolder, TemplateParams, Identifier)); EXPECT_NE(N, DICompositeType::get( Context, Tag, Name, File, Line, getSubprogram(), BaseType, - SizeInBits, AlignInBits, OffsetInBits, Flags, Elements, + SizeInBits, AlignInBytes, OffsetInBits, Flags, Elements, RuntimeLang, VTableHolder, TemplateParams, Identifier)); EXPECT_NE(N, DICompositeType::get( Context, Tag, Name, File, Line, Scope, getBasicType("other"), - SizeInBits, AlignInBits, OffsetInBits, Flags, Elements, + SizeInBits, AlignInBytes, OffsetInBits, Flags, Elements, RuntimeLang, VTableHolder, TemplateParams, Identifier)); EXPECT_NE(N, DICompositeType::get(Context, Tag, Name, File, Line, Scope, - BaseType, SizeInBits + 1, AlignInBits, + BaseType, SizeInBits + 1, AlignInBytes, OffsetInBits, Flags, Elements, RuntimeLang, VTableHolder, TemplateParams, Identifier)); EXPECT_NE(N, DICompositeType::get(Context, Tag, Name, File, Line, Scope, - BaseType, SizeInBits, AlignInBits + 1, + BaseType, SizeInBits, AlignInBytes + 1, OffsetInBits, Flags, Elements, RuntimeLang, VTableHolder, TemplateParams, Identifier)); EXPECT_NE(N, DICompositeType::get( Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, - AlignInBits, OffsetInBits + 1, Flags, Elements, RuntimeLang, + AlignInBytes, OffsetInBits + 1, Flags, Elements, RuntimeLang, VTableHolder, TemplateParams, Identifier)); DINode::DIFlags FlagsPOne = static_cast(Flags + 1); EXPECT_NE(N, DICompositeType::get( Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, - AlignInBits, OffsetInBits, FlagsPOne, Elements, RuntimeLang, + AlignInBytes, OffsetInBits, FlagsPOne, Elements, RuntimeLang, VTableHolder, TemplateParams, Identifier)); EXPECT_NE(N, DICompositeType::get( Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, - AlignInBits, OffsetInBits, Flags, getTuple(), RuntimeLang, + AlignInBytes, OffsetInBits, Flags, getTuple(), RuntimeLang, VTableHolder, TemplateParams, Identifier)); EXPECT_NE(N, DICompositeType::get( Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, - AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang + 1, + AlignInBytes, OffsetInBits, Flags, Elements, RuntimeLang + 1, VTableHolder, TemplateParams, Identifier)); EXPECT_NE(N, DICompositeType::get( Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, - AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang, + AlignInBytes, OffsetInBits, Flags, Elements, RuntimeLang, getCompositeType(), TemplateParams, Identifier)); EXPECT_NE(N, DICompositeType::get(Context, Tag, Name, File, Line, Scope, - BaseType, SizeInBits, AlignInBits, + BaseType, SizeInBits, AlignInBytes, OffsetInBits, Flags, Elements, RuntimeLang, VTableHolder, getTuple(), Identifier)); EXPECT_NE(N, DICompositeType::get(Context, Tag, Name, File, Line, Scope, - BaseType, SizeInBits, AlignInBits, + BaseType, SizeInBits, AlignInBytes, OffsetInBits, Flags, Elements, RuntimeLang, VTableHolder, TemplateParams, "other")); // Be sure that missing identifiers get null pointers. EXPECT_FALSE(DICompositeType::get(Context, Tag, Name, File, Line, Scope, - BaseType, SizeInBits, AlignInBits, + BaseType, SizeInBits, AlignInBytes, OffsetInBits, Flags, Elements, RuntimeLang, VTableHolder, TemplateParams, "") ->getRawIdentifier()); EXPECT_FALSE(DICompositeType::get(Context, Tag, Name, File, Line, Scope, - BaseType, SizeInBits, AlignInBits, + BaseType, SizeInBits, AlignInBytes, OffsetInBits, Flags, Elements, RuntimeLang, VTableHolder, TemplateParams) ->getRawIdentifier()); @@ -1257,7 +1257,7 @@ DIScope *Scope = getSubprogram(); DIType *BaseType = getCompositeType(); uint64_t SizeInBits = UINT64_MAX; - uint64_t AlignInBits = UINT64_MAX - 1; + uint64_t AlignInBytes = UINT64_MAX - 1; uint64_t OffsetInBits = UINT64_MAX - 2; DINode::DIFlags Flags = static_cast(5); MDTuple *Elements = getTuple(); @@ -1267,11 +1267,11 @@ StringRef Identifier = "some id"; auto *N = DICompositeType::get(Context, Tag, Name, File, Line, Scope, - BaseType, SizeInBits, AlignInBits, + BaseType, SizeInBits, AlignInBytes, OffsetInBits, Flags, Elements, RuntimeLang, VTableHolder, TemplateParams, Identifier); EXPECT_EQ(SizeInBits, N->getSizeInBits()); - EXPECT_EQ(AlignInBits, N->getAlignInBits()); + EXPECT_EQ(AlignInBytes, N->getAlignInBytes()); EXPECT_EQ(OffsetInBits, N->getOffsetInBits()); } @@ -1283,14 +1283,14 @@ DIScope *Scope = getSubprogram(); DIType *BaseType = getCompositeType(); uint64_t SizeInBits = 2; - uint64_t AlignInBits = 3; + uint64_t AlignInBytes = 3; uint64_t OffsetInBits = 4; DINode::DIFlags Flags = static_cast(5); unsigned RuntimeLang = 6; StringRef Identifier = "some id"; auto *N = DICompositeType::get( - Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits, + Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBytes, OffsetInBits, Flags, nullptr, RuntimeLang, nullptr, nullptr, Identifier); auto *Elements = MDTuple::getDistinct(Context, None); @@ -1824,10 +1824,12 @@ auto *Expr2 = DIExpression::get(Context, {1, 2, 3}); DIDerivedType *StaticDataMemberDeclaration = cast(getDerivedType()); + uint64_t AlignInBytes = 8; auto *N = DIGlobalVariable::get(Context, Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, IsDefinition, - Expr, StaticDataMemberDeclaration); + Expr, StaticDataMemberDeclaration, + AlignInBytes); EXPECT_EQ(dwarf::DW_TAG_variable, N->getTag()); EXPECT_EQ(Scope, N->getScope()); EXPECT_EQ(Name, N->getName()); @@ -1839,45 +1841,61 @@ EXPECT_EQ(IsDefinition, N->isDefinition()); EXPECT_EQ(Expr, N->getExpr()); EXPECT_EQ(StaticDataMemberDeclaration, N->getStaticDataMemberDeclaration()); + EXPECT_EQ(AlignInBytes, N->getAlignInBytes()); EXPECT_EQ(N, DIGlobalVariable::get(Context, Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, IsDefinition, - Expr, StaticDataMemberDeclaration)); + Expr, StaticDataMemberDeclaration, + AlignInBytes)); EXPECT_NE(N, DIGlobalVariable::get(Context, getSubprogram(), Name, LinkageName, File, Line, Type, IsLocalToUnit, IsDefinition, - Expr, StaticDataMemberDeclaration)); + Expr, StaticDataMemberDeclaration, + AlignInBytes)); EXPECT_NE(N, DIGlobalVariable::get(Context, Scope, "other", LinkageName, File, Line, Type, IsLocalToUnit, IsDefinition, - Expr, StaticDataMemberDeclaration)); + Expr, StaticDataMemberDeclaration, + AlignInBytes)); EXPECT_NE(N, DIGlobalVariable::get(Context, Scope, Name, "other", File, Line, Type, IsLocalToUnit, IsDefinition, Expr, - StaticDataMemberDeclaration)); + StaticDataMemberDeclaration, + AlignInBytes)); EXPECT_NE(N, DIGlobalVariable::get(Context, Scope, Name, LinkageName, getFile(), Line, Type, IsLocalToUnit, IsDefinition, Expr, - StaticDataMemberDeclaration)); + StaticDataMemberDeclaration, + AlignInBytes)); EXPECT_NE(N, DIGlobalVariable::get(Context, Scope, Name, LinkageName, File, Line + 1, Type, IsLocalToUnit, IsDefinition, - Expr, StaticDataMemberDeclaration)); + Expr, StaticDataMemberDeclaration, + AlignInBytes)); EXPECT_NE(N, DIGlobalVariable::get(Context, Scope, Name, LinkageName, File, Line, getDerivedType(), IsLocalToUnit, IsDefinition, - Expr, StaticDataMemberDeclaration)); + Expr, StaticDataMemberDeclaration, + AlignInBytes)); EXPECT_NE(N, DIGlobalVariable::get(Context, Scope, Name, LinkageName, File, Line, Type, !IsLocalToUnit, IsDefinition, - Expr, StaticDataMemberDeclaration)); + Expr, StaticDataMemberDeclaration, + AlignInBytes)); EXPECT_NE(N, DIGlobalVariable::get(Context, Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, !IsDefinition, - Expr, StaticDataMemberDeclaration)); + Expr, StaticDataMemberDeclaration, + AlignInBytes)); EXPECT_NE(N, DIGlobalVariable::get(Context, Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, IsDefinition, - Expr2, StaticDataMemberDeclaration)); + Expr2, StaticDataMemberDeclaration, + AlignInBytes)); EXPECT_NE(N, DIGlobalVariable::get(Context, Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, IsDefinition, Expr, - cast(getDerivedType()))); + cast(getDerivedType()), + AlignInBytes)); + EXPECT_NE(N, DIGlobalVariable::get(Context, Scope, Name, LinkageName, File, + Line, Type, IsLocalToUnit, IsDefinition, + Expr, StaticDataMemberDeclaration, + (AlignInBytes << 1))); TempDIGlobalVariable Temp = N->clone(); EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp))); @@ -1893,9 +1911,11 @@ DIType *Type = getDerivedType(); unsigned Arg = 6; DINode::DIFlags Flags = static_cast(7); + uint64_t AlignInBytes = 8; auto *N = - DILocalVariable::get(Context, Scope, Name, File, Line, Type, Arg, Flags); + DILocalVariable::get(Context, Scope, Name, File, Line, Type, Arg, Flags, + AlignInBytes); EXPECT_TRUE(N->isParameter()); EXPECT_EQ(Scope, N->getScope()); EXPECT_EQ(Name, N->getName()); @@ -1904,24 +1924,27 @@ EXPECT_EQ(Type, N->getType()); EXPECT_EQ(Arg, N->getArg()); EXPECT_EQ(Flags, N->getFlags()); + EXPECT_EQ(AlignInBytes, N->getAlignInBytes()); EXPECT_EQ(N, DILocalVariable::get(Context, Scope, Name, File, Line, Type, Arg, - Flags)); + Flags, AlignInBytes)); EXPECT_FALSE( - DILocalVariable::get(Context, Scope, Name, File, Line, Type, 0, Flags) - ->isParameter()); + DILocalVariable::get(Context, Scope, Name, File, Line, Type, 0, Flags, + AlignInBytes)->isParameter()); EXPECT_NE(N, DILocalVariable::get(Context, getSubprogram(), Name, File, Line, - Type, Arg, Flags)); + Type, Arg, Flags, AlignInBytes)); EXPECT_NE(N, DILocalVariable::get(Context, Scope, "other", File, Line, Type, - Arg, Flags)); + Arg, Flags, AlignInBytes)); EXPECT_NE(N, DILocalVariable::get(Context, Scope, Name, getFile(), Line, Type, - Arg, Flags)); + Arg, Flags, AlignInBytes)); EXPECT_NE(N, DILocalVariable::get(Context, Scope, Name, File, Line + 1, Type, - Arg, Flags)); + Arg, Flags, AlignInBytes)); EXPECT_NE(N, DILocalVariable::get(Context, Scope, Name, File, Line, - getDerivedType(), Arg, Flags)); + getDerivedType(), Arg, Flags, AlignInBytes)); + EXPECT_NE(N, DILocalVariable::get(Context, Scope, Name, File, Line, Type, + Arg + 1, Flags, AlignInBytes)); EXPECT_NE(N, DILocalVariable::get(Context, Scope, Name, File, Line, Type, - Arg + 1, Flags)); + Arg, Flags, (AlignInBytes << 1))); TempDILocalVariable Temp = N->clone(); EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp))); @@ -1929,17 +1952,17 @@ TEST_F(DILocalVariableTest, getArg256) { EXPECT_EQ(255u, DILocalVariable::get(Context, getSubprogram(), "", getFile(), - 0, nullptr, 255, DINode::FlagZero) + 0, nullptr, 255, DINode::FlagZero, 0) ->getArg()); EXPECT_EQ(256u, DILocalVariable::get(Context, getSubprogram(), "", getFile(), - 0, nullptr, 256, DINode::FlagZero) + 0, nullptr, 256, DINode::FlagZero, 0) ->getArg()); EXPECT_EQ(257u, DILocalVariable::get(Context, getSubprogram(), "", getFile(), - 0, nullptr, 257, DINode::FlagZero) + 0, nullptr, 257, DINode::FlagZero, 0) ->getArg()); unsigned Max = UINT16_MAX; EXPECT_EQ(Max, DILocalVariable::get(Context, getSubprogram(), "", getFile(), - 0, nullptr, Max, DINode::FlagZero) + 0, nullptr, Max, DINode::FlagZero, 0) ->getArg()); }