Files
swift-mirror/lib/SIL/SILCoverageMap.cpp
Vedant Kumar aba9d53736 [Coverage] Refactor SIL generation for profiling
This patch moves the ownership of profiling state from SILGenProfiling
to SILFunction, where it always belonged. Similarly, it moves ownership
of the profile reader from SILGenModule to SILModule.

The refactor sets us up to fix a few outstanding code coverage bugs and
does away with sad hacks like ProfilerRAII. It also allows us to locally
guarantee that a profile counter increment actually corresponds to the
SILFunction at hand.

That local guarantee causes a bugfix to accidentally fall out of this
refactor: we now set up the profiling state for delayed functions
correctly. Previously, we would set up a ProfilerRAII for the delayed
function, but its counter increment would never be emitted :(. This fix
constitutes the only functional change in this patch -- the rest is NFC.

As a follow-up, I plan on removing some dead code in the profiling
logic and fixing a few naming inconsistencies. I've left that for later
to keep this patch simple.
2018-01-03 11:18:40 -08:00

85 lines
2.9 KiB
C++

//===--- SILCoverageMap.cpp - Defines the SILCoverageMap class ------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// This file defines the SILCoverageMap class, which is used to relay coverage
// mapping information from the AST to lower layers of the compiler.
//
//===----------------------------------------------------------------------===//
#include "swift/SIL/SILCoverageMap.h"
#include "swift/SIL/SILModule.h"
using namespace swift;
using llvm::coverage::CounterExpression;
SILCoverageMap *
SILCoverageMap::create(SILModule &M, StringRef Filename, StringRef Name,
bool External, uint64_t Hash,
ArrayRef<MappedRegion> MappedRegions,
ArrayRef<CounterExpression> Expressions) {
auto *Buf = M.allocate<SILCoverageMap>(1);
SILCoverageMap *CM = ::new (Buf) SILCoverageMap(Hash, External);
// Store a copy of the names so that we own the lifetime.
CM->Filename = M.allocateCopy(Filename);
CM->Name = M.allocateCopy(Name);
// Since we have two arrays, we need to manually tail allocate each of them,
// rather than relying on the flexible array trick.
CM->MappedRegions = M.allocateCopy(MappedRegions);
CM->Expressions = M.allocateCopy(Expressions);
M.coverageMaps.push_back(CM);
return CM;
}
SILCoverageMap::SILCoverageMap(uint64_t Hash, bool External)
: External(External), Hash(Hash), HasSymtabEntry(false) {}
SILCoverageMap::~SILCoverageMap() {}
namespace {
struct Printer {
const llvm::coverage::Counter &C;
ArrayRef<llvm::coverage::CounterExpression> Exprs;
Printer(const llvm::coverage::Counter &C,
ArrayRef<llvm::coverage::CounterExpression> Exprs)
: C(C), Exprs(Exprs) {}
void print(raw_ostream &OS) const {
// TODO: This format's nice and human readable, but does it fit well with
// SIL's relatively simple structure?
if (C.isZero())
OS << "zero";
else if (C.isExpression()) {
assert(C.getExpressionID() < Exprs.size() && "expression out of range");
const auto &E = Exprs[C.getExpressionID()];
OS << '(' << Printer(E.LHS, Exprs)
<< (E.Kind == CounterExpression::Add ? " + " : " - ")
<< Printer(E.RHS, Exprs) << ')';
} else
OS << C.getCounterID();
}
friend raw_ostream &operator<<(raw_ostream &OS, const Printer &P) {
P.print(OS);
return OS;
}
};
} // end anonymous namespace
void SILCoverageMap::printCounter(llvm::raw_ostream &OS,
llvm::coverage::Counter C) const {
OS << Printer(C, getExpressions());
}