aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/llvm/lib/Support/CodeGenCoverage.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2019-12-20 19:53:05 +0000
committerDimitry Andric <dim@FreeBSD.org>2019-12-20 19:53:05 +0000
commit0b57cec536236d46e3dba9bd041533462f33dbb7 (patch)
tree56229dbdbbf76d18580f72f789003db17246c8d9 /contrib/llvm-project/llvm/lib/Support/CodeGenCoverage.cpp
parent718ef55ec7785aae63f98f8ca05dc07ed399c16d (diff)
Notes
Diffstat (limited to 'contrib/llvm-project/llvm/lib/Support/CodeGenCoverage.cpp')
-rw-r--r--contrib/llvm-project/llvm/lib/Support/CodeGenCoverage.cpp124
1 files changed, 124 insertions, 0 deletions
diff --git a/contrib/llvm-project/llvm/lib/Support/CodeGenCoverage.cpp b/contrib/llvm-project/llvm/lib/Support/CodeGenCoverage.cpp
new file mode 100644
index 000000000000..f39eb7533b43
--- /dev/null
+++ b/contrib/llvm-project/llvm/lib/Support/CodeGenCoverage.cpp
@@ -0,0 +1,124 @@
+//===- lib/Support/CodeGenCoverage.cpp -------------------------------------==//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+/// \file
+/// This file implements the CodeGenCoverage class.
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/CodeGenCoverage.h"
+
+#include "llvm/Config/llvm-config.h"
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/Mutex.h"
+#include "llvm/Support/ScopedPrinter.h"
+#include "llvm/Support/ToolOutputFile.h"
+
+#if LLVM_ON_UNIX
+#include <unistd.h>
+#elif defined(_WIN32)
+#include <windows.h>
+#endif
+
+using namespace llvm;
+
+static sys::SmartMutex<true> OutputMutex;
+
+CodeGenCoverage::CodeGenCoverage() {}
+
+void CodeGenCoverage::setCovered(uint64_t RuleID) {
+ if (RuleCoverage.size() <= RuleID)
+ RuleCoverage.resize(RuleID + 1, 0);
+ RuleCoverage[RuleID] = true;
+}
+
+bool CodeGenCoverage::isCovered(uint64_t RuleID) const {
+ if (RuleCoverage.size() <= RuleID)
+ return false;
+ return RuleCoverage[RuleID];
+}
+
+iterator_range<CodeGenCoverage::const_covered_iterator>
+CodeGenCoverage::covered() const {
+ return RuleCoverage.set_bits();
+}
+
+bool CodeGenCoverage::parse(MemoryBuffer &Buffer, StringRef BackendName) {
+ const char *CurPtr = Buffer.getBufferStart();
+
+ while (CurPtr != Buffer.getBufferEnd()) {
+ // Read the backend name from the input.
+ const char *LexedBackendName = CurPtr;
+ while (*CurPtr++ != 0)
+ ;
+ if (CurPtr == Buffer.getBufferEnd())
+ return false; // Data is invalid, expected rule id's to follow.
+
+ bool IsForThisBackend = BackendName.equals(LexedBackendName);
+ while (CurPtr != Buffer.getBufferEnd()) {
+ if (std::distance(CurPtr, Buffer.getBufferEnd()) < 8)
+ return false; // Data is invalid. Not enough bytes for another rule id.
+
+ uint64_t RuleID = support::endian::read64(CurPtr, support::native);
+ CurPtr += 8;
+
+ // ~0ull terminates the rule id list.
+ if (RuleID == ~0ull)
+ break;
+
+ // Anything else, is recorded or ignored depending on whether it's
+ // intended for the backend we're interested in.
+ if (IsForThisBackend)
+ setCovered(RuleID);
+ }
+ }
+
+ return true;
+}
+
+bool CodeGenCoverage::emit(StringRef CoveragePrefix,
+ StringRef BackendName) const {
+ if (!CoveragePrefix.empty() && !RuleCoverage.empty()) {
+ sys::SmartScopedLock<true> Lock(OutputMutex);
+
+ // We can handle locking within a process easily enough but we don't want to
+ // manage it between multiple processes. Use the process ID to ensure no
+ // more than one process is ever writing to the same file at the same time.
+ std::string Pid =
+#if LLVM_ON_UNIX
+ llvm::to_string(::getpid());
+#elif defined(_WIN32)
+ llvm::to_string(::GetCurrentProcessId());
+#else
+ "";
+#endif
+
+ std::string CoverageFilename = (CoveragePrefix + Pid).str();
+
+ std::error_code EC;
+ sys::fs::OpenFlags OpenFlags = sys::fs::F_Append;
+ std::unique_ptr<ToolOutputFile> CoverageFile =
+ llvm::make_unique<ToolOutputFile>(CoverageFilename, EC, OpenFlags);
+ if (EC)
+ return false;
+
+ uint64_t Zero = 0;
+ uint64_t InvZero = ~0ull;
+ CoverageFile->os() << BackendName;
+ CoverageFile->os().write((const char *)&Zero, sizeof(unsigned char));
+ for (uint64_t I : RuleCoverage.set_bits())
+ CoverageFile->os().write((const char *)&I, sizeof(uint64_t));
+ CoverageFile->os().write((const char *)&InvZero, sizeof(uint64_t));
+
+ CoverageFile->keep();
+ }
+
+ return true;
+}
+
+void CodeGenCoverage::reset() { RuleCoverage.resize(0); }