llvm.org GIT mirror llvm / de72ac6
Fix Bug 30978 by emitting cv file checksums. Summary: The checksums had already been placed in the IR, this patch allows MCCodeView to actually write it out to an MCStreamer. Subscribers: llvm-commits, hiraditya Differential Revision: https://reviews.llvm.org/D37157 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@313374 91177308-0d34-0410-b5e6-96231b3b80d8 Eric Beckmann 2 years ago
16 changed file(s) with 314 addition(s) and 85 deletion(s). Raw diff Collapse all Expand all
472472 friend class MDNode;
473473
474474 public:
475 // These values must be explictly set, as they end up in the final object
476 // file.
475477 enum ChecksumKind {
476 CSK_None,
477 CSK_MD5,
478 CSK_SHA1,
478 CSK_None = 0,
479 CSK_MD5 = 1,
480 CSK_SHA1 = 2,
479481 CSK_Last = CSK_SHA1 // Should be last enumeration.
480482 };
481483
509511 ChecksumKind CSK = CSK_None,
510512 StringRef CS = StringRef()),
511513 (Filename, Directory, CSK, CS))
512 DEFINE_MDNODE_GET(DIFile, (MDString *Filename, MDString *Directory,
514 DEFINE_MDNODE_GET(DIFile, (MDString * Filename, MDString *Directory,
513515 ChecksumKind CSK = CSK_None,
514516 MDString *CS = nullptr),
515517 (Filename, Directory, CSK, CS))
160160 ~CodeViewContext();
161161
162162 bool isValidFileNumber(unsigned FileNumber) const;
163 bool addFile(unsigned FileNumber, StringRef Filename);
164 ArrayRef getFilenames() { return Filenames; }
163 bool addFile(MCStreamer &OS, unsigned FileNumber, StringRef Filename,
164 StringRef Checksum, uint8_t ChecksumKind);
165165
166166 /// Records the function id of a normal function. Returns false if the
167167 /// function id has already been used, and true otherwise.
272272 /// Emits the file checksum substream.
273273 void emitFileChecksums(MCObjectStreamer &OS);
274274
275 /// Emits the offset into the checksum table of the given file number.
276 void emitFileChecksumOffset(MCObjectStreamer &OS, unsigned FileNo);
277
275278 private:
276279 /// The current CodeView line information from the last .cv_loc directive.
277280 MCCVLoc CurrentCVLoc = MCCVLoc(0, 0, 0, 0, false, true);
286289
287290 MCDataFragment *getStringTableFragment();
288291
289 /// Add something to the string table.
290 StringRef addToStringTable(StringRef S);
292 /// Add something to the string table. Returns the final string as well as
293 /// offset into the string table.
294 std::pair addToStringTable(StringRef S);
291295
292296 /// Get a string table offset.
293297 unsigned getStringTableOffset(StringRef S);
294298
295 /// An array of absolute paths. Eventually this may include the file checksum.
296 SmallVector Filenames;
299 struct FileInfo {
300 unsigned StringTableOffset;
301
302 // Checksum offset stored as a symbol because it might be requested
303 // before it has been calculated, so a fixup may be needed.
304 MCSymbol *ChecksumTableOffset;
305
306 // Indicates if this FileInfo corresponds to an actual file, or hasn't been
307 // set yet.
308 bool Assigned = false;
309
310 std::string Checksum;
311 uint8_t ChecksumKind;
312 };
313
314 /// Array storing added file information.
315 SmallVector Files;
297316
298317 /// The offset of the first and last .cv_loc directive for a given function
299318 /// id.
304323
305324 /// All known functions and inlined call sites, indexed by function id.
306325 std::vector Functions;
326
327 /// Indicate whether we have already laid out the checksum table addresses or
328 /// not.
329 bool ChecksumOffsetsAssigned = false;
307330 };
308331
309332 } // end namespace llvm
139139 StringRef FixedSizePortion) override;
140140 void EmitCVStringTableDirective() override;
141141 void EmitCVFileChecksumsDirective() override;
142 void EmitCVFileChecksumOffsetDirective(unsigned FileNo) override;
142143 void EmitDTPRel32Value(const MCExpr *Value) override;
143144 void EmitDTPRel64Value(const MCExpr *Value) override;
144145 void EmitTPRel32Value(const MCExpr *Value) override;
728728 unsigned Isa, unsigned Discriminator,
729729 StringRef FileName);
730730
731 /// \brief Associate a filename with a specified logical file number. This
732 /// implements the '.cv_file 4 "foo.c"' assembler directive. Returns true on
733 /// success.
734 virtual bool EmitCVFileDirective(unsigned FileNo, StringRef Filename);
731 /// Associate a filename with a specified logical file number, and also
732 /// specify that file's checksum information. This implements the '.cv_file 4
733 /// "foo.c"' assembler directive. Returns true on success.
734 virtual bool EmitCVFileDirective(unsigned FileNo, StringRef Filename,
735 StringRef Checksum, unsigned ChecksumKind);
735736
736737 /// \brief Introduces a function id for use with .cv_loc.
737738 virtual bool EmitCVFuncIdDirective(unsigned FunctionId);
772773
773774 /// \brief This implements the CodeView '.cv_filechecksums' assembler directive.
774775 virtual void EmitCVFileChecksumsDirective() {}
776
777 /// This implements the CodeView '.cv_filechecksumoffset' assembler
778 /// directive.
779 virtual void EmitCVFileChecksumOffsetDirective(unsigned FileNo) {}
775780
776781 /// Emit the absolute difference between two symbols.
777782 ///
158158 if (Insertion.second) {
159159 // We have to compute the full filepath and emit a .cv_file directive.
160160 StringRef FullPath = getFullFilepath(F);
161 bool Success = OS.EmitCVFileDirective(NextId, FullPath);
161 StringRef Checksum = F->getChecksum();
162 DIFile::ChecksumKind ChecksumKind = F->getChecksumKind();
163 bool Success = OS.EmitCVFileDirective(NextId, FullPath, Checksum,
164 static_cast(ChecksumKind));
162165 (void)Success;
163166 assert(Success && ".cv_file directive failed");
164167 }
680683 OS.AddComment("Inlinee lines subsection");
681684 MCSymbol *InlineEnd = beginCVSubsection(DebugSubsectionKind::InlineeLines);
682685
683 // We don't provide any extra file info.
684 // FIXME: Find out if debuggers use this info.
686 // We emit the checksum info for files. This is used by debuggers to
687 // determine if a pdb matches the source before loading it. Visual Studio,
688 // for instance, will display a warning that the breakpoints are not valid if
689 // the pdb does not match the source.
685690 OS.AddComment("Inlinee lines signature");
686691 OS.EmitIntValue(unsigned(InlineeLinesSignature::Normal), 4);
687692
694699 OS.AddComment("Inlined function " + SP->getName() + " starts at " +
695700 SP->getFilename() + Twine(':') + Twine(SP->getLine()));
696701 OS.AddBlankLine();
697 // The filechecksum table uses 8 byte entries for now, and file ids start at
698 // 1.
699 unsigned FileOffset = (FileId - 1) * 8;
700702 OS.AddComment("Type index of inlined function");
701703 OS.EmitIntValue(InlineeIdx.getIndex(), 4);
702704 OS.AddComment("Offset into filechecksum table");
703 OS.EmitIntValue(FileOffset, 4);
705 OS.EmitCVFileChecksumOffsetDirective(FileId);
704706 OS.AddComment("Starting line number");
705707 OS.EmitIntValue(SP->getLine(), 4);
706708 }
353353 DEFINE_GETIMPL_STORE(DISubroutineType, (Flags, CC), Ops);
354354 }
355355
356 // FIXME: Implement this string-enum correspondence with a .def file and macros,
357 // so that the association is explicit rather than implied.
356358 static const char *ChecksumKindName[DIFile::CSK_Last + 1] = {
357359 "CSK_None",
358360 "CSK_MD5",
224224 StringRef FileName) override;
225225 MCSymbol *getDwarfLineTableSymbol(unsigned CUID) override;
226226
227 bool EmitCVFileDirective(unsigned FileNo, StringRef Filename) override;
227 bool EmitCVFileDirective(unsigned FileNo, StringRef Filename,
228 StringRef Checksum, unsigned ChecksumKind) override;
228229 bool EmitCVFuncIdDirective(unsigned FuncId) override;
229230 bool EmitCVInlineSiteIdDirective(unsigned FunctionId, unsigned IAFunc,
230231 unsigned IAFile, unsigned IALine,
244245 StringRef FixedSizePortion) override;
245246 void EmitCVStringTableDirective() override;
246247 void EmitCVFileChecksumsDirective() override;
248 void EmitCVFileChecksumOffsetDirective(unsigned FileNo) override;
247249
248250 void EmitIdent(StringRef IdentString) override;
249251 void EmitCFISections(bool EH, bool Debug) override;
11191121 return MCStreamer::getDwarfLineTableSymbol(0);
11201122 }
11211123
1122 bool MCAsmStreamer::EmitCVFileDirective(unsigned FileNo, StringRef Filename) {
1123 if (!getContext().getCVContext().addFile(FileNo, Filename))
1124 bool MCAsmStreamer::EmitCVFileDirective(unsigned FileNo, StringRef Filename,
1125 StringRef Checksum,
1126 unsigned ChecksumKind) {
1127 if (!getContext().getCVContext().addFile(*this, FileNo, Filename, Checksum,
1128 ChecksumKind))
11241129 return false;
11251130
11261131 OS << "\t.cv_file\t" << FileNo << ' ';
1127
11281132 PrintQuotedString(Filename, OS);
1133
1134 if (!ChecksumKind) {
1135 EmitEOL();
1136 return true;
1137 }
1138
1139 OS << ' ';
1140 PrintQuotedString(Checksum, OS);
1141 OS << ' ' << ChecksumKind;
1142
11291143 EmitEOL();
11301144 return true;
11311145 }
12241238
12251239 void MCAsmStreamer::EmitCVFileChecksumsDirective() {
12261240 OS << "\t.cv_filechecksums";
1241 EmitEOL();
1242 }
1243
1244 void MCAsmStreamer::EmitCVFileChecksumOffsetDirective(unsigned FileNo) {
1245 OS << "\t.cv_filechecksumoffset\t" << FileNo;
12271246 EmitEOL();
12281247 }
12291248
3838 /// for it.
3939 bool CodeViewContext::isValidFileNumber(unsigned FileNumber) const {
4040 unsigned Idx = FileNumber - 1;
41 if (Idx < Filenames.size())
42 return !Filenames[Idx].empty();
41 if (Idx < Files.size())
42 return Files[Idx].Assigned;
4343 return false;
4444 }
4545
46 bool CodeViewContext::addFile(unsigned FileNumber, StringRef Filename) {
46 bool CodeViewContext::addFile(MCStreamer &OS, unsigned FileNumber,
47 StringRef Filename, StringRef Checksum,
48 uint8_t ChecksumKind) {
4749 assert(FileNumber > 0);
48 Filename = addToStringTable(Filename);
50 auto FilenameOffset = addToStringTable(Filename);
51 Filename = FilenameOffset.first;
4952 unsigned Idx = FileNumber - 1;
50 if (Idx >= Filenames.size())
51 Filenames.resize(Idx + 1);
53 if (Idx >= Files.size())
54 Files.resize(Idx + 1);
5255
5356 if (Filename.empty())
5457 Filename = "";
5558
56 if (!Filenames[Idx].empty())
59 if (Files[Idx].Assigned)
5760 return false;
5861
59 // FIXME: We should store the string table offset of the filename, rather than
60 // the filename itself for efficiency.
61 Filename = addToStringTable(Filename);
62
63 Filenames[Idx] = Filename;
62 FilenameOffset = addToStringTable(Filename);
63 Filename = FilenameOffset.first;
64 unsigned Offset = FilenameOffset.second;
65
66 auto ChecksumOffsetSymbol =
67 OS.getContext().createTempSymbol("checksum_offset", false);
68 Files[Idx].StringTableOffset = Offset;
69 Files[Idx].ChecksumTableOffset = ChecksumOffsetSymbol;
70 Files[Idx].Assigned = true;
71 Files[Idx].Checksum = Checksum.str();
72 Files[Idx].ChecksumKind = ChecksumKind;
73
6474 return true;
6575 }
6676
117127 return StrTabFragment;
118128 }
119129
120 StringRef CodeViewContext::addToStringTable(StringRef S) {
130 std::pair CodeViewContext::addToStringTable(StringRef S) {
121131 SmallVectorImpl &Contents = getStringTableFragment()->getContents();
122132 auto Insertion =
123133 StringTable.insert(std::make_pair(S, unsigned(Contents.size())));
124134 // Return the string from the table, since it is stable.
125 S = Insertion.first->first();
135 std::pair Ret =
136 std::make_pair(Insertion.first->first(), Insertion.first->second);
126137 if (Insertion.second) {
127138 // The string map key is always null terminated.
128 Contents.append(S.begin(), S.end() + 1);
129 }
130 return S;
139 Contents.append(Ret.first.begin(), Ret.first.end() + 1);
140 }
141 return Ret;
131142 }
132143
133144 unsigned CodeViewContext::getStringTableOffset(StringRef S) {
164175 void CodeViewContext::emitFileChecksums(MCObjectStreamer &OS) {
165176 // Do nothing if there are no file checksums. Microsoft's linker rejects empty
166177 // CodeView substreams.
167 if (Filenames.empty())
178 if (Files.empty())
168179 return;
169180
170181 MCContext &Ctx = OS.getContext();
175186 OS.emitAbsoluteSymbolDiff(FileEnd, FileBegin, 4);
176187 OS.EmitLabel(FileBegin);
177188
189 unsigned CurrentOffset = 0;
190
178191 // Emit an array of FileChecksum entries. We index into this table using the
179 // user-provided file number. Each entry is currently 8 bytes, as we don't
180 // emit checksums.
181 for (StringRef Filename : Filenames) {
182 OS.EmitIntValue(getStringTableOffset(Filename), 4);
183 // Zero the next two fields and align back to 4 bytes. This indicates that
184 // no checksum is present.
185 OS.EmitIntValue(0, 4);
192 // user-provided file number. Each entry may be a variable number of bytes
193 // determined by the checksum kind and size.
194 for (auto File : Files) {
195 OS.EmitAssignment(File.ChecksumTableOffset,
196 MCConstantExpr::create(CurrentOffset, Ctx));
197 CurrentOffset += 4; // String table offset.
198 if (!File.ChecksumKind) {
199 CurrentOffset +=
200 4; // One byte each for checksum size and kind, then align to 4 bytes.
201 } else {
202 CurrentOffset += 2; // One byte each for checksum size and kind.
203 CurrentOffset += File.Checksum.size();
204 CurrentOffset = alignTo(CurrentOffset, 4);
205 }
206
207 OS.EmitIntValue(File.StringTableOffset, 4);
208
209 if (!File.ChecksumKind) {
210 // There is no checksum. Therefore zero the next two fields and align
211 // back to 4 bytes.
212 OS.EmitIntValue(0, 4);
213 continue;
214 }
215 OS.EmitIntValue(static_cast(File.Checksum.size()), 1);
216 OS.EmitIntValue(File.ChecksumKind, 1);
217 OS.EmitBytes(File.Checksum);
218 OS.EmitValueToAlignment(4);
186219 }
187220
188221 OS.EmitLabel(FileEnd);
222
223 ChecksumOffsetsAssigned = true;
224 }
225
226 // Output checksum table offset of the given file number. It is possible that
227 // not all files have been registered yet, and so the offset cannot be
228 // calculated. In this case a symbol representing the offset is emitted, and
229 // the value of this symbol will be fixed up at a later time.
230 void CodeViewContext::emitFileChecksumOffset(MCObjectStreamer &OS,
231 unsigned FileNo) {
232 unsigned Idx = FileNo - 1;
233
234 if (Idx >= Files.size())
235 Files.resize(Idx + 1);
236
237 if (ChecksumOffsetsAssigned) {
238 OS.EmitSymbolValue(Files[Idx].ChecksumTableOffset, 4);
239 return;
240 }
241
242 const MCSymbolRefExpr *SRE =
243 MCSymbolRefExpr::create(Files[Idx].ChecksumTableOffset, OS.getContext());
244
245 OS.EmitValueImpl(SRE, 4);
189246 }
190247
191248 void CodeViewContext::emitLineTableForFunction(MCObjectStreamer &OS,
218275 return Loc.getFileNum() != CurFileNum;
219276 });
220277 unsigned EntryCount = FileSegEnd - I;
221 OS.AddComment("Segment for file '" + Twine(Filenames[CurFileNum - 1]) +
222 "' begins");
223 OS.EmitIntValue(8 * (CurFileNum - 1), 4);
278 OS.AddComment(
279 "Segment for file '" +
280 Twine(getStringTableFragment()
281 ->getContents()[Files[CurFileNum - 1].StringTableOffset]) +
282 "' begins");
283 OS.EmitCVFileChecksumOffsetDirective(CurFileNum);
224284 OS.EmitIntValue(EntryCount, 4);
225285 uint32_t SegmentSize = 12;
226286 SegmentSize += 8 * EntryCount;
400460 HaveOpenRange = true;
401461
402462 if (CurSourceLoc.File != LastSourceLoc.File) {
403 // File ids are 1 based, and each file checksum table entry is 8 bytes
404 // long. See emitFileChecksums above.
405 unsigned FileOffset = 8 * (CurSourceLoc.File - 1);
463 unsigned FileOffset = static_cast(
464 Files[CurSourceLoc.File - 1]
465 .ChecksumTableOffset->getVariableValue())
466 ->getValue();
406467 compressAnnotation(BinaryAnnotationsOpCode::ChangeFile, Buffer);
407468 compressAnnotation(FileOffset, Buffer);
408469 }
425425 getContext().getCVContext().emitFileChecksums(*this);
426426 }
427427
428 void MCObjectStreamer::EmitCVFileChecksumOffsetDirective(unsigned FileNo) {
429 getContext().getCVContext().emitFileChecksumOffset(*this, FileNo);
430 }
428431
429432 void MCObjectStreamer::EmitBytes(StringRef Data) {
430433 MCCVLineEntry::Make(this);
500500 DK_CV_DEF_RANGE,
501501 DK_CV_STRINGTABLE,
502502 DK_CV_FILECHECKSUMS,
503 DK_CV_FILECHECKSUM_OFFSET,
503504 DK_CFI_SECTIONS,
504505 DK_CFI_STARTPROC,
505506 DK_CFI_ENDPROC,
575576 bool parseDirectiveCVDefRange();
576577 bool parseDirectiveCVStringTable();
577578 bool parseDirectiveCVFileChecksums();
579 bool parseDirectiveCVFileChecksumOffset();
578580
579581 // .cfi directives
580582 bool parseDirectiveCFIRegister(SMLoc DirectiveLoc);
20292031 return parseDirectiveCVStringTable();
20302032 case DK_CV_FILECHECKSUMS:
20312033 return parseDirectiveCVFileChecksums();
2034 case DK_CV_FILECHECKSUM_OFFSET:
2035 return parseDirectiveCVFileChecksumOffset();
20322036 case DK_CFI_SECTIONS:
20332037 return parseDirectiveCFISections();
20342038 case DK_CFI_STARTPROC:
34563460 }
34573461
34583462 /// parseDirectiveCVFile
3459 /// ::= .cv_file number filename
3463 /// ::= .cv_file number filename [checksum] [checksumkind]
34603464 bool AsmParser::parseDirectiveCVFile() {
34613465 SMLoc FileNumberLoc = getTok().getLoc();
34623466 int64_t FileNumber;
34633467 std::string Filename;
3468 std::string Checksum;
3469 int64_t ChecksumKind = 0;
34643470
34653471 if (parseIntToken(FileNumber,
34663472 "expected file number in '.cv_file' directive") ||
34673473 check(FileNumber < 1, FileNumberLoc, "file number less than one") ||
34683474 check(getTok().isNot(AsmToken::String),
34693475 "unexpected token in '.cv_file' directive") ||
3470 // Usually directory and filename are together, otherwise just
3471 // directory. Allow the strings to have escaped octal character sequence.
3472 parseEscapedString(Filename) ||
3473 parseToken(AsmToken::EndOfStatement,
3474 "unexpected token in '.cv_file' directive"))
3475 return true;
3476
3477 if (!getStreamer().EmitCVFileDirective(FileNumber, Filename))
3476 parseEscapedString(Filename))
3477 return true;
3478 if (!parseOptionalToken(AsmToken::EndOfStatement)) {
3479 if (check(getTok().isNot(AsmToken::String),
3480 "unexpected token in '.cv_file' directive") ||
3481 parseEscapedString(Checksum) ||
3482 parseIntToken(ChecksumKind,
3483 "expected checksum kind in '.cv_file' directive") ||
3484 parseToken(AsmToken::EndOfStatement,
3485 "unexpected token in '.cv_file' directive"))
3486 return true;
3487 }
3488
3489 if (!getStreamer().EmitCVFileDirective(FileNumber, Filename, Checksum,
3490 static_cast(ChecksumKind)))
34783491 return Error(FileNumberLoc, "file number already allocated");
34793492
34803493 return false;
37503763 /// ::= .cv_filechecksums
37513764 bool AsmParser::parseDirectiveCVFileChecksums() {
37523765 getStreamer().EmitCVFileChecksumsDirective();
3766 return false;
3767 }
3768
3769 /// parseDirectiveCVFileChecksumOffset
3770 /// ::= .cv_filechecksumoffset fileno
3771 bool AsmParser::parseDirectiveCVFileChecksumOffset() {
3772 int64_t FileNo;
3773 if (parseIntToken(FileNo, "expected identifier in directive"))
3774 return true;
3775 if (parseToken(AsmToken::EndOfStatement, "Expected End of Statement"))
3776 return true;
3777 getStreamer().EmitCVFileChecksumOffsetDirective(FileNo);
37533778 return false;
37543779 }
37553780
51355160 DirectiveKindMap[".cv_def_range"] = DK_CV_DEF_RANGE;
51365161 DirectiveKindMap[".cv_stringtable"] = DK_CV_STRINGTABLE;
51375162 DirectiveKindMap[".cv_filechecksums"] = DK_CV_FILECHECKSUMS;
5163 DirectiveKindMap[".cv_filechecksumoffset"] = DK_CV_FILECHECKSUM_OFFSET;
51385164 DirectiveKindMap[".sleb128"] = DK_SLEB128;
51395165 DirectiveKindMap[".uleb128"] = DK_ULEB128;
51405166 DirectiveKindMap[".cfi_sections"] = DK_CFI_SECTIONS;
223223 report_fatal_error("No open frame");
224224 }
225225
226 bool MCStreamer::EmitCVFileDirective(unsigned FileNo, StringRef Filename) {
227 return getContext().getCVContext().addFile(FileNo, Filename);
226 bool MCStreamer::EmitCVFileDirective(unsigned FileNo, StringRef Filename,
227 StringRef Checksum,
228 unsigned ChecksumKind) {
229 return getContext().getCVContext().addFile(*this, FileNo, Filename, Checksum,
230 ChecksumKind);
228231 }
229232
230233 bool MCStreamer::EmitCVFuncIdDirective(unsigned FunctionId) {
4848 ; ASM: .long 0
4949 ; ASM: # Inlined function bar starts at t.cpp:8
5050 ; ASM: .long 4098 # Type index of inlined function
51 ; ASM: .long 0 # Offset into filechecksum table
51 ; ASM: .cv_filechecksumoffset 1 # Offset into filechecksum table
5252 ; ASM: .long 8 # Starting line number
5353 ; ASM: # Inlined function foo starts at t.cpp:2
5454 ; ASM: .long 4099
55 ; ASM: .long 0
55 ; ASM: .cv_filechecksumoffset 1 # Offset into filechecksum table
5656 ; ASM: .long 2
5757 ; ASM: [[inline_end]]:
5858
7070 ; ASM: .cv_inline_linetable 2 1 2 Lfunc_begin0 Lfunc_end0
7171 ; ASM: .short 4430
7272 ; ASM: .short 4430
73
74 ; ASM: .cv_filechecksums
7375
7476 ; ASM: .section .debug$T,"dr"
7577 ; ASM: .long 4 # Debug section magic
1717
1818 ; X86-LABEL: _f:
1919 ; X86: # BB
20 ; X86: .cv_file 1 "D:\\one.c"
20 ; X86: .cv_file 1 "D:\\one.c" "70b51f534d80639d033ae92c6a856af6" 1
2121 ; X86: .cv_loc 0 1 1 0 is_stmt 0 # one.c:1:0
2222 ; X86: calll _g
23 ; X86: .cv_file 2 "D:\\two.c"
23 ; X86: .cv_file 2 "D:\\two.c" "70b51f534d80639d033ae92c6a856af6" 1
2424 ; X86: .cv_loc 0 2 2 0 # two.c:2:0
2525 ; X86: calll _g
2626 ; X86: .cv_loc 0 1 7 0 # one.c:7:0
5050 ; OBJ32-NEXT: ProcEnd {
5151 ; OBJ32: }
5252 ; OBJ32-NEXT: ]
53 ; OBJ32: Subsection [
54 ; OBJ32: SubSectionType: FileChecksums (0xF4)
55 ; OBJ32-NEXT: SubSectionSize: 0x50
56 ; OBJ32-NEXT: FileChecksum {
57 ; OBJ32-NEXT: Filename: D:\one.c (0x1)
58 ; OBJ32-NEXT: ChecksumSize: 0x20
59 ; OBJ32-NEXT: ChecksumKind: MD5 (0x1)
60 ; OBJ32-NEXT: ChecksumBytes (
61 ; OBJ32-NEXT: 0000: 37306235 31663533 34643830 36333964 |70b51f534d80639d|
62 ; OBJ32-NEXT: 0010: 30333361 65393263 36613835 36616636 |033ae92c6a856af6|
63 ; OBJ32-NEXT: )
64 ; OBJ32-NEXT: }
65 ; OBJ32-NEXT: FileChecksum {
66 ; OBJ32-NEXT: Filename: D:\two.c (0xA)
67 ; OBJ32-NEXT: ChecksumSize: 0x20
68 ; OBJ32-NEXT: ChecksumKind: MD5 (0x1)
69 ; OBJ32-NEXT: ChecksumBytes (
70 ; OBJ32-NEXT: 0000: 37306235 31663533 34643830 36333964 |70b51f534d80639d|
71 ; OBJ32-NEXT: 0010: 30333361 65393263 36613835 36616636 |033ae92c6a856af6|
72 ; OBJ32-NEXT: )
73 ; OBJ32-NEXT: }
74 ; OBJ32-NEXT: ]
5375 ; OBJ32: FunctionLineTable [
5476 ; OBJ32-NEXT: Name: _f
5577 ; OBJ32-NEXT: Flags: 0x0
87109
88110 ; X64-LABEL: f:
89111 ; X64-NEXT: .L{{.*}}:{{$}}
90 ; X64: .cv_file 1 "D:\\input.c"
112 ; X64: .cv_file 1 "D:\\input.c" "70b51f534d80639d033ae92c6a856af6" 1
91113 ; X64: .cv_loc 0 1 3 0 is_stmt 0 # input.c:3:0
92114 ; X64: # BB
93115 ; X64: subq $40, %rsp
94 ; X64: .cv_file 2 "D:\\one.c"
116 ; X64: .cv_file 2 "D:\\one.c" "70b51f534d80639d033ae92c6a856af6" 1
95117 ; X64: .cv_loc 0 2 1 0 # one.c:1:0
96118 ; X64: callq g
97 ; X64: .cv_file 3 "D:\\two.c"
119 ; X64: .cv_file 3 "D:\\two.c" "70b51f534d80639d033ae92c6a856af6" 1
98120 ; X64: .cv_loc 0 3 2 0 # two.c:2:0
99121 ; X64: callq g
100122 ; X64: .cv_loc 0 2 7 0 # one.c:7:0
122144 ; OBJ64-NEXT: ProcEnd {
123145 ; OBJ64: }
124146 ; OBJ64-NEXT: ]
147 ; OBJ64: Subsection [
148 ; OBJ64: SubSectionType: FileChecksums (0xF4)
149 ; OBJ64-NEXT: SubSectionSize: 0x78
150 ; OBJ64-NEXT: FileChecksum {
151 ; OBJ64-NEXT: Filename: D:\input.c (0x1)
152 ; OBJ64-NEXT: ChecksumSize: 0x20
153 ; OBJ64-NEXT: ChecksumKind: MD5 (0x1)
154 ; OBJ64-NEXT: ChecksumBytes (
155 ; OBJ64-NEXT: 0000: 37306235 31663533 34643830 36333964 |70b51f534d80639d|
156 ; OBJ64-NEXT: 0010: 30333361 65393263 36613835 36616636 |033ae92c6a856af6|
157 ; OBJ64-NEXT: )
158 ; OBJ64-NEXT: }
159 ; OBJ64-NEXT: FileChecksum {
160 ; OBJ64-NEXT: Filename: D:\one.c (0xC)
161 ; OBJ64-NEXT: ChecksumSize: 0x20
162 ; OBJ64-NEXT: ChecksumKind: MD5 (0x1)
163 ; OBJ64-NEXT: ChecksumBytes (
164 ; OBJ64-NEXT: 0000: 37306235 31663533 34643830 36333964 |70b51f534d80639d|
165 ; OBJ64-NEXT: 0010: 30333361 65393263 36613835 36616636 |033ae92c6a856af6|
166 ; OBJ64-NEXT: )
167 ; OBJ64-NEXT: }
168 ; OBJ64-NEXT: FileChecksum {
169 ; OBJ64-NEXT: Filename: D:\two.c (0x15)
170 ; OBJ64-NEXT: ChecksumSize: 0x20
171 ; OBJ64-NEXT: ChecksumKind: MD5 (0x1)
172 ; OBJ64-NEXT: ChecksumBytes (
173 ; OBJ64-NEXT: 0000: 37306235 31663533 34643830 36333964 |70b51f534d80639d|
174 ; OBJ64-NEXT: 0010: 30333361 65393263 36613835 36616636 |033ae92c6a856af6|
175 ; OBJ64-NEXT: )
176 ; OBJ64-NEXT: }
177 ; OBJ64-NEXT: ]
125178 ; OBJ64: FunctionLineTable [
126179 ; OBJ64-NEXT: Name: f
127180 ; OBJ64-NEXT: Flags: 0x0
184237 !llvm.ident = !{!11}
185238
186239 !0 = distinct !DICompileUnit(language: DW_LANG_C99, producer: "clang version 3.5 ", isOptimized: false, emissionKind: FullDebug, file: !1, enums: !2, retainedTypes: !2, globals: !2, imports: !2)
187 !1 = !DIFile(filename: "", directory: "D:\5C")
240 !1 = !DIFile(filename: "", directory: "D:\5C", checksumkind: CSK_MD5, checksum:"70b51f534d80639d033ae92c6a856af6")
188241 !2 = !{}
189242 !4 = distinct !DISubprogram(name: "f", line: 3, isLocal: false, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: false, unit: !0, scopeLine: 3, file: !5, scope: !6, type: !7, variables: !2)
190 !5 = !DIFile(filename: "input.c", directory: "D:\5C")
191 !6 = !DIFile(filename: "input.c", directory: "D:C")
243 !5 = !DIFile(filename: "input.c", directory: "D:\5C", checksumkind: CSK_MD5, checksum:"70b51f534d80639d033ae92c6a856af6")
244 !6 = !DIFile(filename: "input.c", directory: "D:C", checksumkind: CSK_MD5, checksum:"70b51f534d80639d033ae92c6a856af6")
192245 !7 = !DISubroutineType(types: !8)
193246 !8 = !{null}
194247 !9 = !{i32 2, !"CodeView", i32 1}
196249 !11 = !{!"clang version 3.5 "}
197250 !12 = !DILocation(line: 1, scope: !13)
198251 !13 = !DILexicalBlockFile(discriminator: 0, file: !14, scope: !4)
199 !14 = !DIFile(filename: "one.c", directory: "D:\5C")
252 !14 = !DIFile(filename: "one.c", directory: "D:\5C", checksumkind: CSK_MD5, checksum:"70b51f534d80639d033ae92c6a856af6")
200253 !15 = !DILocation(line: 2, scope: !16)
201254 !16 = !DILexicalBlockFile(discriminator: 0, file: !17, scope: !4)
202 !17 = !DIFile(filename: "two.c", directory: "D:\5C")
255 !17 = !DIFile(filename: "two.c", directory: "D:\5C", checksumkind: CSK_MD5, checksum:"70b51f534d80639d033ae92c6a856af6")
203256 !18 = !DILocation(line: 7, scope: !13)
204257 !19 = !DILocation(line: 8, scope: !13)
1616
1717 ; X86-LABEL: _f:
1818 ; X86: # BB
19 ; X86: .cv_file 1 "D:\\test.c"
19 ; X86: .cv_file 1 "D:\\test.c" "f310ab26998ca831cbdf169e4eecacfa" 1
2020 ; X86: .cv_loc 0 1 4 2 is_stmt 0 # test.c:4:2
2121 ; X86: calll _g
2222 ; X86: .cv_loc 0 1 5 0 # test.c:5:0
8484 ; OBJ32-NEXT: ProcEnd {
8585 ; OBJ32: }
8686 ; OBJ32-NEXT: ]
87 ; OBJ32: Subsection [
88 ; OBJ32: SubSectionType: FileChecksums (0xF4)
89 ; OBJ32-NEXT: SubSectionSize: 0x28
90 ; OBJ32-NEXT: FileChecksum {
91 ; OBJ32-NEXT: Filename: D:\test.c (0x1)
92 ; OBJ32-NEXT: ChecksumSize: 0x20
93 ; OBJ32-NEXT: ChecksumKind: MD5 (0x1)
94 ; OBJ32-NEXT: ChecksumBytes (
95 ; OBJ32-NEXT: 0000: 66333130 61623236 39393863 61383331 |f310ab26998ca831|
96 ; OBJ32-NEXT: 0010: 63626466 31363965 34656563 61636661 |cbdf169e4eecacfa|
97 ; OBJ32-NEXT: )
98 ; OBJ32-NEXT: }
99 ; OBJ32-NEXT: ]
87100 ; OBJ32: FunctionLineTable [
88101 ; OBJ32-NEXT: Name: _f
89102 ; OBJ32-NEXT: Flags: 0x1
109122
110123 ; X64-LABEL: f:
111124 ; X64-NEXT: .L{{.*}}:{{$}}
112 ; X64: .cv_file 1 "D:\\test.c"
125 ; X64: .cv_file 1 "D:\\test.c" "f310ab26998ca831cbdf169e4eecacfa" 1
113126 ; X64: .cv_loc 0 1 3 0 is_stmt 0 # test.c:3:0
114127 ; X64: # BB
115128 ; X64: subq $40, %rsp
181194 ; OBJ64-NEXT: ProcEnd {
182195 ; OBJ64: }
183196 ; OBJ64-NEXT: ]
197 ; OBJ64: Subsection [
198 ; OBJ64: SubSectionType: FileChecksums (0xF4)
199 ; OBJ64-NEXT: SubSectionSize: 0x28
200 ; OBJ64-NEXT: FileChecksum {
201 ; OBJ64-NEXT: Filename: D:\test.c (0x1)
202 ; OBJ64-NEXT: ChecksumSize: 0x20
203 ; OBJ64-NEXT: ChecksumKind: MD5 (0x1)
204 ; OBJ64-NEXT: ChecksumBytes (
205 ; OBJ64-NEXT: 0000: 66333130 61623236 39393863 61383331 |f310ab26998ca831|
206 ; OBJ64-NEXT: 0010: 63626466 31363965 34656563 61636661 |cbdf169e4eecacfa|
207 ; OBJ64-NEXT: )
208 ; OBJ64-NEXT: }
209 ; OBJ64-NEXT: ]
184210 ; OBJ64: FunctionLineTable [
185211 ; OBJ64-NEXT: Name: f
186212 ; OBJ64-NEXT: Flags: 0x1
231257 !1 = !DIFile(filename: "", directory: "D:\5C")
232258 !2 = !{}
233259 !4 = distinct !DISubprogram(name: "f", line: 3, isLocal: false, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: false, unit: !0, scopeLine: 3, file: !5, scope: !6, type: !7, variables: !2)
234 !5 = !DIFile(filename: "test.c", directory: "D:\5C")
235 !6 = !DIFile(filename: "test.c", directory: "D:C")
260 !5 = !DIFile(filename: "test.c", directory: "D:\5C", checksumkind: CSK_MD5, checksum: "f310ab26998ca831cbdf169e4eecacfa")
261 !6 = !DIFile(filename: "test.c", directory: "D:C", checksumkind: CSK_MD5, checksum: "f310ab26998ca831cbdf169e4eecacfa")
236262 !7 = !DISubroutineType(types: !8)
237263 !8 = !{null}
238264 !9 = !{i32 2, !"CodeView", i32 1}
102102 ; CHECK: SubSectionType: FileChecksums (0xF4)
103103 ; CHECK: FileChecksum {
104104 ; CHECK: ChecksumSize: 0x0
105 ; CHECK: ChecksumKind: None (0x0)
105 ; CHECK: ChecksumKind: MD5 (0x1)
106106 ; CHECK: ChecksumBytes: ()
107107 ; CHECK: }
108108 ; CHECK: ]
13821382
13831383 EXPECT_NE(N, DIFile::get(Context, "other", Directory, CSKind, Checksum));
13841384 EXPECT_NE(N, DIFile::get(Context, Filename, "other", CSKind, Checksum));
1385 EXPECT_NE(N, DIFile::get(Context, Filename, Directory, DIFile::CSK_SHA1, Checksum));
1385 EXPECT_NE(
1386 N, DIFile::get(Context, Filename, Directory, DIFile::CSK_SHA1, Checksum));
13861387 EXPECT_NE(N, DIFile::get(Context, Filename, Directory));
13871388
13881389 TempDIFile Temp = N->clone();