diff options
Diffstat (limited to 'llvm/lib')
-rw-r--r-- | llvm/lib/AsmParser/LLParser.cpp | 19 | ||||
-rw-r--r-- | llvm/lib/Bitcode/Reader/BitcodeReader.cpp | 16 | ||||
-rw-r--r-- | llvm/lib/Bitcode/Writer/BitcodeWriter.cpp | 18 | ||||
-rw-r--r-- | llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp | 8 | ||||
-rw-r--r-- | llvm/lib/IR/AsmWriter.cpp | 2 | ||||
-rw-r--r-- | llvm/lib/IR/DIBuilder.cpp | 46 | ||||
-rw-r--r-- | llvm/lib/IR/DebugInfoMetadata.cpp | 12 | ||||
-rw-r--r-- | llvm/lib/IR/LLVMContextImpl.h | 41 |
8 files changed, 110 insertions, 52 deletions
diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp index 959501fc04f..961ae65425b 100644 --- a/llvm/lib/AsmParser/LLParser.cpp +++ b/llvm/lib/AsmParser/LLParser.cpp @@ -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)); \ @@ -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)); \ @@ -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; } diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp index 825df2b535d..9b1adc7f668 100644 --- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp @@ -2734,7 +2734,7 @@ 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]; @@ -2742,6 +2742,7 @@ std::error_code BitcodeReader::parseMetadata(bool ModuleLevel) { // 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())) { @@ -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) @@ -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; } diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp index af722723845..99aa60f45e9 100644 --- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -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(); @@ -1720,7 +1721,21 @@ 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())); @@ -1728,6 +1743,7 @@ void ModuleBitcodeWriter::writeDILocalVariable( 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(); diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp index 6e3c43b2b9e..bec554dcdf0 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp @@ -1404,9 +1404,11 @@ void DwarfUnit::constructMemberDIE(DIE &Buffer, const DIDerivedType *DT) { addUInt(MemberDie, dwarf::DW_AT_bit_size, None, Size); uint64_t Offset = DT->getOffsetInBits(); - uint32_t Align = DT->getAlignInBits() ? DT->getAlignInBits() - : FieldSize; - uint32_t AlignMask = ~(Align - 1); + // We can't use DT->getAlignInBits() here: AlignInBits for member type + // is non-zero if and only if alignment was forced (e.g. _Alignas()), + // which can't be done with bitfields. Thus we use FieldSize here. + uint32_t AlignInBits = FieldSize; + uint32_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. diff --git a/llvm/lib/IR/AsmWriter.cpp b/llvm/lib/IR/AsmWriter.cpp index 5500e9638b2..ea00baf3d97 100644 --- a/llvm/lib/IR/AsmWriter.cpp +++ b/llvm/lib/IR/AsmWriter.cpp @@ -1822,6 +1822,7 @@ static void writeDIGlobalVariable(raw_ostream &Out, const DIGlobalVariable *N, Printer.printBool("isDefinition", N->isDefinition()); Printer.printMetadata("expr", N->getExpr()); Printer.printMetadata("declaration", N->getRawStaticDataMemberDeclaration()); + Printer.printInt("align", N->getAlignInBits()); Out << ")"; } @@ -1837,6 +1838,7 @@ static void writeDILocalVariable(raw_ostream &Out, const DILocalVariable *N, Printer.printInt("line", N->getLine()); Printer.printMetadata("type", N->getRawType()); Printer.printDIFlags("flags", N->getFlags()); + Printer.printInt("align", N->getAlignInBits()); Out << ")"; } diff --git a/llvm/lib/IR/DIBuilder.cpp b/llvm/lib/IR/DIBuilder.cpp index a459a524777..741a3a27f13 100644 --- a/llvm/lib/IR/DIBuilder.cpp +++ b/llvm/lib/IR/DIBuilder.cpp @@ -195,11 +195,10 @@ DIBasicType *DIBuilder::createNullPtrType() { } DIBasicType *DIBuilder::createBasicType(StringRef Name, uint64_t SizeInBits, - uint32_t AlignInBits, unsigned Encoding) { assert(!Name.empty() && "Unable to create type without name"); return DIBasicType::get(VMContext, dwarf::DW_TAG_base_type, Name, SizeInBits, - AlignInBits, Encoding); + 0, Encoding); } DIDerivedType *DIBuilder::createQualifiedType(unsigned Tag, DIType *FromTy) { @@ -277,24 +276,26 @@ static ConstantAsMetadata *getConstantOrNull(Constant *C) { DIDerivedType *DIBuilder::createBitFieldMemberType( DIScope *Scope, StringRef Name, DIFile *File, unsigned LineNumber, - uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits, - uint64_t StorageOffsetInBits, DINode::DIFlags Flags, DIType *Ty) { + uint64_t SizeInBits, uint64_t OffsetInBits, uint64_t StorageOffsetInBits, + DINode::DIFlags Flags, DIType *Ty) { Flags |= DINode::FlagBitField; return DIDerivedType::get( VMContext, dwarf::DW_TAG_member, Name, File, LineNumber, - getNonCompileUnitScope(Scope), Ty, SizeInBits, AlignInBits, OffsetInBits, - Flags, ConstantAsMetadata::get(ConstantInt::get( - IntegerType::get(VMContext, 64), StorageOffsetInBits))); + getNonCompileUnitScope(Scope), Ty, SizeInBits, /* AlignInBits */ 0, + OffsetInBits, Flags, + ConstantAsMetadata::get(ConstantInt::get(IntegerType::get(VMContext, 64), + StorageOffsetInBits))); } DIDerivedType * DIBuilder::createStaticMemberType(DIScope *Scope, StringRef Name, DIFile *File, unsigned LineNumber, DIType *Ty, - DINode::DIFlags Flags, llvm::Constant *Val) { + DINode::DIFlags Flags, llvm::Constant *Val, + uint32_t AlignInBits) { Flags |= DINode::FlagStaticMember; return DIDerivedType::get(VMContext, dwarf::DW_TAG_member, Name, File, - LineNumber, getNonCompileUnitScope(Scope), Ty, 0, 0, - 0, Flags, getConstantOrNull(Val)); + LineNumber, getNonCompileUnitScope(Scope), Ty, 0, + AlignInBits, 0, Flags, getConstantOrNull(Val)); } DIDerivedType * @@ -535,28 +536,28 @@ static void checkGlobalVariableScope(DIScope *Context) { 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, uint32_t AlignInBits) { checkGlobalVariableScope(Context); auto *N = DIGlobalVariable::getDistinct( VMContext, cast_or_null<DIScope>(Context), Name, LinkageName, F, LineNumber, Ty, isLocalToUnit, true, Expr, - cast_or_null<DIDerivedType>(Decl)); + cast_or_null<DIDerivedType>(Decl), AlignInBits); 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, uint32_t AlignInBits) { checkGlobalVariableScope(Context); return DIGlobalVariable::getTemporary( VMContext, cast_or_null<DIScope>(Context), Name, LinkageName, F, LineNumber, Ty, isLocalToUnit, false, Expr, - cast_or_null<DIDerivedType>(Decl)) + cast_or_null<DIDerivedType>(Decl), AlignInBits) .release(); } @@ -564,7 +565,8 @@ static DILocalVariable *createLocalVariable( LLVMContext &VMContext, DenseMap<MDNode *, SmallVector<TrackingMDNodeRef, 1>> &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, + uint32_t AlignInBits) { // FIXME: Why getNonCompileUnitScope()? // FIXME: Why is "!Context" okay here? // FIXME: Why doesn't this check for a subprogram or lexical block (AFAICT @@ -573,7 +575,7 @@ static DILocalVariable *createLocalVariable( auto *Node = DILocalVariable::get(VMContext, cast_or_null<DILocalScope>(Context), Name, - File, LineNo, Ty, ArgNo, Flags); + File, LineNo, Ty, ArgNo, Flags, AlignInBits); 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 +590,11 @@ static DILocalVariable *createLocalVariable( DILocalVariable *DIBuilder::createAutoVariable(DIScope *Scope, StringRef Name, DIFile *File, unsigned LineNo, DIType *Ty, bool AlwaysPreserve, - DINode::DIFlags Flags) { + DINode::DIFlags Flags, + uint32_t AlignInBits) { return createLocalVariable(VMContext, PreservedVariables, Scope, Name, /* ArgNo */ 0, File, LineNo, Ty, AlwaysPreserve, - Flags); + Flags, AlignInBits); } DILocalVariable *DIBuilder::createParameterVariable( @@ -599,7 +602,8 @@ DILocalVariable *DIBuilder::createParameterVariable( 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, + /* AlignInBits */0); } DIExpression *DIBuilder::createExpression(ArrayRef<uint64_t> Addr) { diff --git a/llvm/lib/IR/DebugInfoMetadata.cpp b/llvm/lib/IR/DebugInfoMetadata.cpp index 3a7b0d943ab..19f02cd38d6 100644 --- a/llvm/lib/IR/DebugInfoMetadata.cpp +++ b/llvm/lib/IR/DebugInfoMetadata.cpp @@ -510,16 +510,18 @@ DIGlobalVariable::getImpl(LLVMContext &Context, Metadata *Scope, MDString *Name, Metadata *Type, bool IsLocalToUnit, bool IsDefinition, Metadata *Variable, Metadata *StaticDataMemberDeclaration, + uint64_t AlignInBits, 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, AlignInBits)); Metadata *Ops[] = {Scope, Name, File, Type, Name, LinkageName, Variable, StaticDataMemberDeclaration}; - DEFINE_GETIMPL_STORE(DIGlobalVariable, (Line, IsLocalToUnit, IsDefinition), + DEFINE_GETIMPL_STORE(DIGlobalVariable, + (Line, IsLocalToUnit, IsDefinition, AlignInBits), Ops); } @@ -527,6 +529,7 @@ DILocalVariable *DILocalVariable::getImpl(LLVMContext &Context, Metadata *Scope, MDString *Name, Metadata *File, unsigned Line, Metadata *Type, unsigned Arg, DIFlags Flags, + uint64_t AlignInBits, StorageType Storage, bool ShouldCreate) { // 64K ought to be enough for any frontend. @@ -535,9 +538,10 @@ DILocalVariable *DILocalVariable::getImpl(LLVMContext &Context, Metadata *Scope, 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, + AlignInBits)); Metadata *Ops[] = {Scope, Name, File, Type}; - DEFINE_GETIMPL_STORE(DILocalVariable, (Line, Arg, Flags), Ops); + DEFINE_GETIMPL_STORE(DILocalVariable, (Line, Arg, Flags, AlignInBits), Ops); } DIExpression *DIExpression::getImpl(LLVMContext &Context, diff --git a/llvm/lib/IR/LLVMContextImpl.h b/llvm/lib/IR/LLVMContextImpl.h index acae104a900..dd5e1584f1e 100644 --- a/llvm/lib/IR/LLVMContextImpl.h +++ b/llvm/lib/IR/LLVMContextImpl.h @@ -761,22 +761,26 @@ template <> struct MDNodeKeyImpl<DIGlobalVariable> { bool IsDefinition; Metadata *Expr; Metadata *StaticDataMemberDeclaration; + uint64_t AlignInBits; 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 AlignInBits) : Scope(Scope), Name(Name), LinkageName(LinkageName), File(File), Line(Line), Type(Type), IsLocalToUnit(IsLocalToUnit), IsDefinition(IsDefinition), Expr(Expr), - StaticDataMemberDeclaration(StaticDataMemberDeclaration) {} + StaticDataMemberDeclaration(StaticDataMemberDeclaration), + AlignInBits(AlignInBits) {} 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()), + AlignInBits(N->getAlignInBits()) {} bool isKeyOf(const DIGlobalVariable *RHS) const { return Scope == RHS->getRawScope() && Name == RHS->getRawName() && @@ -786,11 +790,19 @@ template <> struct MDNodeKeyImpl<DIGlobalVariable> { IsDefinition == RHS->isDefinition() && Expr == RHS->getRawExpr() && StaticDataMemberDeclaration == - RHS->getRawStaticDataMemberDeclaration(); + RHS->getRawStaticDataMemberDeclaration() && + AlignInBits == RHS->getAlignInBits(); } unsigned getHashValue() const { + // We do not use AlignInBits 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, /* AlignInBits, */ Expr, StaticDataMemberDeclaration); } }; @@ -803,23 +815,32 @@ template <> struct MDNodeKeyImpl<DILocalVariable> { Metadata *Type; unsigned Arg; unsigned Flags; + uint64_t AlignInBits; MDNodeKeyImpl(Metadata *Scope, MDString *Name, Metadata *File, unsigned Line, - Metadata *Type, unsigned Arg, unsigned Flags) + Metadata *Type, unsigned Arg, unsigned Flags, + uint64_t AlignInBits) : Scope(Scope), Name(Name), File(File), Line(Line), Type(Type), Arg(Arg), - Flags(Flags) {} + Flags(Flags), AlignInBits(AlignInBits) {} 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()), AlignInBits(N->getAlignInBits()) {} 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() && AlignInBits == RHS->getAlignInBits(); } unsigned getHashValue() const { + // We do not use AlignInBits 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); } }; |