diff options
author | dim <dim@FreeBSD.org> | 2014-03-21 17:53:59 +0000 |
---|---|---|
committer | dim <dim@FreeBSD.org> | 2014-03-21 17:53:59 +0000 |
commit | 9cedb8bb69b89b0f0c529937247a6a80cabdbaec (patch) | |
tree | c978f0e9ec1ab92dc8123783f30b08a7fd1e2a39 /contrib/llvm/lib/IR/GCOV.cpp | |
parent | 03fdc2934eb61c44c049a02b02aa974cfdd8a0eb (diff) | |
download | FreeBSD-src-9cedb8bb69b89b0f0c529937247a6a80cabdbaec.zip FreeBSD-src-9cedb8bb69b89b0f0c529937247a6a80cabdbaec.tar.gz |
MFC 261991:
Upgrade our copy of llvm/clang to 3.4 release. This version supports
all of the features in the current working draft of the upcoming C++
standard, provisionally named C++1y.
The code generator's performance is greatly increased, and the loop
auto-vectorizer is now enabled at -Os and -O2 in addition to -O3. The
PowerPC backend has made several major improvements to code generation
quality and compile time, and the X86, SPARC, ARM32, Aarch64 and SystemZ
backends have all seen major feature work.
Release notes for llvm and clang can be found here:
<http://llvm.org/releases/3.4/docs/ReleaseNotes.html>
<http://llvm.org/releases/3.4/tools/clang/docs/ReleaseNotes.html>
MFC 262121 (by emaste):
Update lldb for clang/llvm 3.4 import
This commit largely restores the lldb source to the upstream r196259
snapshot with the addition of threaded inferior support and a few bug
fixes.
Specific upstream lldb revisions restored include:
SVN git
181387 779e6ac
181703 7bef4e2
182099 b31044e
182650 f2dcf35
182683 0d91b80
183862 15c1774
183929 99447a6
184177 0b2934b
184948 4dc3761
184954 007e7bc
186990 eebd175
Sponsored by: DARPA, AFRL
MFC 262186 (by emaste):
Fix mismerge in r262121
A break statement was lost in the merge. The error had no functional
impact, but restore it to reduce the diff against upstream.
MFC 262303:
Pull in r197521 from upstream clang trunk (by rdivacky):
Use the integrated assembler by default on FreeBSD/ppc and ppc64.
Requested by: jhibbits
MFC 262611:
Pull in r196874 from upstream llvm trunk:
Fix a crash that occurs when PWD is invalid.
MCJIT needs to be able to run in hostile environments, even when PWD
is invalid. There's no need to crash MCJIT in this case.
The obvious fix is to simply leave MCContext's CompilationDir empty
when PWD can't be determined. This way, MCJIT clients,
and other clients that link with LLVM don't need a valid working directory.
If we do want to guarantee valid CompilationDir, that should be done
only for clients of getCompilationDir(). This is as simple as checking
for an empty string.
The only current use of getCompilationDir is EmitGenDwarfInfo, which
won't conceivably run with an invalid working dir. However, in the
purely hypothetically and untestable case that this happens, the
AT_comp_dir will be omitted from the compilation_unit DIE.
This should help fix assertions occurring with ports-mgmt/tinderbox,
when it is using jails, and sometimes invalidates clang's current
working directory.
Reported by: decke
MFC 262809:
Pull in r203007 from upstream clang trunk:
Don't produce an alias between destructors with different calling conventions.
Fixes pr19007.
(Please note that is an LLVM PR identifier, not a FreeBSD one.)
This should fix Firefox and/or libxul crashes (due to problems with
regparm/stdcall calling conventions) on i386.
Reported by: multiple users on freebsd-current
PR: bin/187103
MFC 263048:
Repair recognition of "CC" as an alias for the C++ compiler, since it
was silently broken by upstream for a Windows-specific use-case.
Apparently some versions of CMake still rely on this archaic feature...
Reported by: rakuco
MFC 263049:
Garbage collect the old way of adding the libstdc++ include directories
in clang's InitHeaderSearch.cpp. This has been superseded by David
Chisnall's commit in r255321.
Moreover, if libc++ is used, the libstdc++ include directories should
not be in the search path at all. These directories are now only used
if you pass -stdlib=libstdc++.
Diffstat (limited to 'contrib/llvm/lib/IR/GCOV.cpp')
-rw-r--r-- | contrib/llvm/lib/IR/GCOV.cpp | 297 |
1 files changed, 164 insertions, 133 deletions
diff --git a/contrib/llvm/lib/IR/GCOV.cpp b/contrib/llvm/lib/IR/GCOV.cpp index ea2f0a6..f0f8c7d 100644 --- a/contrib/llvm/lib/IR/GCOV.cpp +++ b/contrib/llvm/lib/IR/GCOV.cpp @@ -7,14 +7,16 @@ // //===----------------------------------------------------------------------===// // -// GCOV implements the interface to read and write coverage files that use +// GCOV implements the interface to read and write coverage files that use // 'gcov' format. // //===----------------------------------------------------------------------===// +#include "llvm/Support/Debug.h" #include "llvm/Support/GCOV.h" #include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/Support/Format.h" #include "llvm/Support/MemoryObject.h" #include "llvm/Support/system_error.h" using namespace llvm; @@ -43,27 +45,47 @@ bool GCOVFile::read(GCOVBuffer &Buffer) { if (Format == GCOV::InvalidGCOV) return false; - unsigned i = 0; - while (1) { - GCOVFunction *GFun = NULL; - if (isGCDAFile(Format)) { - // Use existing function while reading .gcda file. - assert(i < Functions.size() && ".gcda data does not match .gcno data"); - GFun = Functions[i]; - } else if (isGCNOFile(Format)){ - GFun = new GCOVFunction(); + if (isGCNOFile(Format)) { + while (true) { + if (!Buffer.readFunctionTag()) break; + GCOVFunction *GFun = new GCOVFunction(); + if (!GFun->read(Buffer, Format)) + return false; Functions.push_back(GFun); } - if (!GFun || !GFun->read(Buffer, Format)) - break; - ++i; } + else if (isGCDAFile(Format)) { + for (size_t i = 0, e = Functions.size(); i < e; ++i) { + if (!Buffer.readFunctionTag()) { + errs() << "Unexpected number of functions.\n"; + return false; + } + if (!Functions[i]->read(Buffer, Format)) + return false; + } + if (Buffer.readObjectTag()) { + uint32_t Length; + uint32_t Dummy; + if (!Buffer.readInt(Length)) return false; + if (!Buffer.readInt(Dummy)) return false; // checksum + if (!Buffer.readInt(Dummy)) return false; // num + if (!Buffer.readInt(RunCount)) return false;; + Buffer.advanceCursor(Length-3); + } + while (Buffer.readProgramTag()) { + uint32_t Length; + if (!Buffer.readInt(Length)) return false; + Buffer.advanceCursor(Length); + ++ProgramCount; + } + } + return true; } -/// dump - Dump GCOVFile content on standard out for debugging purposes. +/// dump - Dump GCOVFile content to dbgs() for debugging purposes. void GCOVFile::dump() { - for (SmallVector<GCOVFunction *, 16>::iterator I = Functions.begin(), + for (SmallVectorImpl<GCOVFunction *>::iterator I = Functions.begin(), E = Functions.end(); I != E; ++I) (*I)->dump(); } @@ -71,10 +93,11 @@ void GCOVFile::dump() { /// collectLineCounts - Collect line counts. This must be used after /// reading .gcno and .gcda files. void GCOVFile::collectLineCounts(FileInfo &FI) { - for (SmallVector<GCOVFunction *, 16>::iterator I = Functions.begin(), - E = Functions.end(); I != E; ++I) + for (SmallVectorImpl<GCOVFunction *>::iterator I = Functions.begin(), + E = Functions.end(); I != E; ++I) (*I)->collectLineCounts(FI); - FI.print(); + FI.setRunCount(RunCount); + FI.setProgramCount(ProgramCount); } //===----------------------------------------------------------------------===// @@ -85,77 +108,122 @@ GCOVFunction::~GCOVFunction() { DeleteContainerPointers(Blocks); } -/// read - Read a aunction from the buffer. Return false if buffer cursor +/// read - Read a function from the buffer. Return false if buffer cursor /// does not point to a function tag. bool GCOVFunction::read(GCOVBuffer &Buff, GCOV::GCOVFormat Format) { - if (!Buff.readFunctionTag()) - return false; + uint32_t Dummy; + if (!Buff.readInt(Dummy)) return false; // Function header length + if (!Buff.readInt(Ident)) return false; + if (!Buff.readInt(Dummy)) return false; // Checksum #1 + if (Format != GCOV::GCNO_402 && Format != GCOV::GCDA_402) + if (!Buff.readInt(Dummy)) return false; // Checksum #2 - Buff.readInt(); // Function header length - Ident = Buff.readInt(); - Buff.readInt(); // Checksum #1 - if (Format != GCOV::GCNO_402) - Buff.readInt(); // Checksum #2 + if (!Buff.readString(Name)) return false; - Name = Buff.readString(); if (Format == GCOV::GCNO_402 || Format == GCOV::GCNO_404) - Filename = Buff.readString(); + if (!Buff.readString(Filename)) return false; if (Format == GCOV::GCDA_402 || Format == GCOV::GCDA_404) { - Buff.readArcTag(); - uint32_t Count = Buff.readInt() / 2; - for (unsigned i = 0, e = Count; i != e; ++i) { - Blocks[i]->addCount(Buff.readInt64()); + if (!Buff.readArcTag()) { + errs() << "Arc tag not found.\n"; + return false; + } + uint32_t Count; + if (!Buff.readInt(Count)) return false; + Count /= 2; + + // This for loop adds the counts for each block. A second nested loop is + // required to combine the edge counts that are contained in the GCDA file. + for (uint32_t Line = 0; Count > 0; ++Line) { + if (Line >= Blocks.size()) { + errs() << "Unexpected number of edges.\n"; + return false; + } + GCOVBlock &Block = *Blocks[Line]; + for (size_t Edge = 0, End = Block.getNumEdges(); Edge < End; ++Edge) { + if (Count == 0) { + errs() << "Unexpected number of edges.\n"; + return false; + } + uint64_t ArcCount; + if (!Buff.readInt64(ArcCount)) return false; + Block.addCount(ArcCount); + --Count; + } } return true; } - LineNumber = Buff.readInt(); + if (!Buff.readInt(LineNumber)) return false; // read blocks. - bool BlockTagFound = Buff.readBlockTag(); - (void)BlockTagFound; - assert(BlockTagFound && "Block Tag not found!"); - uint32_t BlockCount = Buff.readInt(); - for (int i = 0, e = BlockCount; i != e; ++i) { - Buff.readInt(); // Block flags; - Blocks.push_back(new GCOVBlock(i)); + if (!Buff.readBlockTag()) { + errs() << "Block tag not found.\n"; + return false; + } + uint32_t BlockCount; + if (!Buff.readInt(BlockCount)) return false; + for (uint32_t i = 0, e = BlockCount; i != e; ++i) { + if (!Buff.readInt(Dummy)) return false; // Block flags; + Blocks.push_back(new GCOVBlock(*this, i)); } // read edges. while (Buff.readEdgeTag()) { - uint32_t EdgeCount = (Buff.readInt() - 1) / 2; - uint32_t BlockNo = Buff.readInt(); - assert(BlockNo < BlockCount && "Unexpected Block number!"); - for (int i = 0, e = EdgeCount; i != e; ++i) { - Blocks[BlockNo]->addEdge(Buff.readInt()); - Buff.readInt(); // Edge flag + uint32_t EdgeCount; + if (!Buff.readInt(EdgeCount)) return false; + EdgeCount = (EdgeCount - 1) / 2; + uint32_t BlockNo; + if (!Buff.readInt(BlockNo)) return false; + if (BlockNo >= BlockCount) { + errs() << "Unexpected block number.\n"; + return false; + } + for (uint32_t i = 0, e = EdgeCount; i != e; ++i) { + uint32_t Dst; + if (!Buff.readInt(Dst)) return false; + Blocks[BlockNo]->addEdge(Dst); + if (!Buff.readInt(Dummy)) return false; // Edge flag } } // read line table. while (Buff.readLineTag()) { - uint32_t LineTableLength = Buff.readInt(); - uint32_t Size = Buff.getCursor() + LineTableLength*4; - uint32_t BlockNo = Buff.readInt(); - assert(BlockNo < BlockCount && "Unexpected Block number!"); + uint32_t LineTableLength; + if (!Buff.readInt(LineTableLength)) return false; + uint32_t EndPos = Buff.getCursor() + LineTableLength*4; + uint32_t BlockNo; + if (!Buff.readInt(BlockNo)) return false; + if (BlockNo >= BlockCount) { + errs() << "Unexpected block number.\n"; + return false; + } GCOVBlock *Block = Blocks[BlockNo]; - Buff.readInt(); // flag - while (Buff.getCursor() != (Size - 4)) { - StringRef Filename = Buff.readString(); - if (Buff.getCursor() == (Size - 4)) break; - while (uint32_t L = Buff.readInt()) - Block->addLine(Filename, L); + if (!Buff.readInt(Dummy)) return false; // flag + while (Buff.getCursor() != (EndPos - 4)) { + StringRef F; + if (!Buff.readString(F)) return false; + if (F != Filename) { + errs() << "Multiple sources for a single basic block.\n"; + return false; + } + if (Buff.getCursor() == (EndPos - 4)) break; + while (true) { + uint32_t Line; + if (!Buff.readInt(Line)) return false; + if (!Line) break; + Block->addLine(Line); + } } - Buff.readInt(); // flag + if (!Buff.readInt(Dummy)) return false; // flag } return true; } -/// dump - Dump GCOVFunction content on standard out for debugging purposes. +/// dump - Dump GCOVFunction content to dbgs() for debugging purposes. void GCOVFunction::dump() { - outs() << "===== " << Name << " @ " << Filename << ":" << LineNumber << "\n"; - for (SmallVector<GCOVBlock *, 16>::iterator I = Blocks.begin(), + dbgs() << "===== " << Name << " @ " << Filename << ":" << LineNumber << "\n"; + for (SmallVectorImpl<GCOVBlock *>::iterator I = Blocks.begin(), E = Blocks.end(); I != E; ++I) (*I)->dump(); } @@ -163,7 +231,7 @@ void GCOVFunction::dump() { /// collectLineCounts - Collect line counts. This must be used after /// reading .gcno and .gcda files. void GCOVFunction::collectLineCounts(FileInfo &FI) { - for (SmallVector<GCOVBlock *, 16>::iterator I = Blocks.begin(), + for (SmallVectorImpl<GCOVBlock *>::iterator I = Blocks.begin(), E = Blocks.end(); I != E; ++I) (*I)->collectLineCounts(FI); } @@ -174,110 +242,73 @@ void GCOVFunction::collectLineCounts(FileInfo &FI) { /// ~GCOVBlock - Delete GCOVBlock and its content. GCOVBlock::~GCOVBlock() { Edges.clear(); - DeleteContainerSeconds(Lines); -} - -void GCOVBlock::addLine(StringRef Filename, uint32_t LineNo) { - GCOVLines *&LinesForFile = Lines[Filename]; - if (!LinesForFile) - LinesForFile = new GCOVLines(); - LinesForFile->add(LineNo); + Lines.clear(); } /// collectLineCounts - Collect line counts. This must be used after /// reading .gcno and .gcda files. void GCOVBlock::collectLineCounts(FileInfo &FI) { - for (StringMap<GCOVLines *>::iterator I = Lines.begin(), + for (SmallVectorImpl<uint32_t>::iterator I = Lines.begin(), E = Lines.end(); I != E; ++I) - I->second->collectLineCounts(FI, I->first(), Counter); + FI.addLineCount(Parent.getFilename(), *I, Counter); } -/// dump - Dump GCOVBlock content on standard out for debugging purposes. +/// dump - Dump GCOVBlock content to dbgs() for debugging purposes. void GCOVBlock::dump() { - outs() << "Block : " << Number << " Counter : " << Counter << "\n"; + dbgs() << "Block : " << Number << " Counter : " << Counter << "\n"; if (!Edges.empty()) { - outs() << "\tEdges : "; - for (SmallVector<uint32_t, 16>::iterator I = Edges.begin(), E = Edges.end(); + dbgs() << "\tEdges : "; + for (SmallVectorImpl<uint32_t>::iterator I = Edges.begin(), E = Edges.end(); I != E; ++I) - outs() << (*I) << ","; - outs() << "\n"; + dbgs() << (*I) << ","; + dbgs() << "\n"; } if (!Lines.empty()) { - outs() << "\tLines : "; - for (StringMap<GCOVLines *>::iterator LI = Lines.begin(), - LE = Lines.end(); LI != LE; ++LI) { - outs() << LI->first() << " -> "; - LI->second->dump(); - outs() << "\n"; - } + dbgs() << "\tLines : "; + for (SmallVectorImpl<uint32_t>::iterator I = Lines.begin(), + E = Lines.end(); I != E; ++I) + dbgs() << (*I) << ","; + dbgs() << "\n"; } } //===----------------------------------------------------------------------===// -// GCOVLines implementation. - -/// collectLineCounts - Collect line counts. This must be used after -/// reading .gcno and .gcda files. -void GCOVLines::collectLineCounts(FileInfo &FI, StringRef Filename, - uint32_t Count) { - for (SmallVector<uint32_t, 16>::iterator I = Lines.begin(), - E = Lines.end(); I != E; ++I) - FI.addLineCount(Filename, *I, Count); -} - -/// dump - Dump GCOVLines content on standard out for debugging purposes. -void GCOVLines::dump() { - for (SmallVector<uint32_t, 16>::iterator I = Lines.begin(), - E = Lines.end(); I != E; ++I) - outs() << (*I) << ","; -} - -//===----------------------------------------------------------------------===// // FileInfo implementation. -/// addLineCount - Add line count for the given line number in a file. -void FileInfo::addLineCount(StringRef Filename, uint32_t Line, uint32_t Count) { - if (LineInfo.find(Filename) == LineInfo.end()) { - OwningPtr<MemoryBuffer> Buff; - if (error_code ec = MemoryBuffer::getFileOrSTDIN(Filename, Buff)) { - errs() << Filename << ": " << ec.message() << "\n"; - return; - } - StringRef AllLines = Buff.take()->getBuffer(); - LineCounts L(AllLines.count('\n')+2); - L[Line-1] = Count; - LineInfo[Filename] = L; - return; - } - LineCounts &L = LineInfo[Filename]; - L[Line-1] = Count; -} - /// print - Print source files with collected line count information. -void FileInfo::print() { +void FileInfo::print(raw_fd_ostream &OS, StringRef gcnoFile, + StringRef gcdaFile) { for (StringMap<LineCounts>::iterator I = LineInfo.begin(), E = LineInfo.end(); I != E; ++I) { StringRef Filename = I->first(); - outs() << Filename << "\n"; + OS << " -: 0:Source:" << Filename << "\n"; + OS << " -: 0:Graph:" << gcnoFile << "\n"; + OS << " -: 0:Data:" << gcdaFile << "\n"; + OS << " -: 0:Runs:" << RunCount << "\n"; + OS << " -: 0:Programs:" << ProgramCount << "\n"; LineCounts &L = LineInfo[Filename]; OwningPtr<MemoryBuffer> Buff; if (error_code ec = MemoryBuffer::getFileOrSTDIN(Filename, Buff)) { errs() << Filename << ": " << ec.message() << "\n"; return; } - StringRef AllLines = Buff.take()->getBuffer(); - for (unsigned i = 0, e = L.size(); i != e; ++i) { - if (L[i]) - outs() << L[i] << ":\t"; - else - outs() << " :\t"; + StringRef AllLines = Buff->getBuffer(); + uint32_t i = 0; + while (!AllLines.empty()) { + if (L.find(i) != L.end()) { + if (L[i] == 0) + OS << " #####:"; + else + OS << format("%9" PRIu64 ":", L[i]); + } else { + OS << " -:"; + } std::pair<StringRef, StringRef> P = AllLines.split('\n'); if (AllLines != P.first) - outs() << P.first; - outs() << "\n"; + OS << format("%5u:", i+1) << P.first; + OS << "\n"; AllLines = P.second; + ++i; } } } - - |