Skip to content

Commit

Permalink
chore(module): Intern LocationInfo
Browse files Browse the repository at this point in the history
  • Loading branch information
misonijnik committed Nov 16, 2024
1 parent 3d1215a commit 9d57e3f
Show file tree
Hide file tree
Showing 12 changed files with 263 additions and 46 deletions.
2 changes: 1 addition & 1 deletion include/klee/Module/KInstruction.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ struct KInstruction : public KValue {
/// register indices.
int *operands;
KBlock *parent;
mutable std::optional<LocationInfo> locationInfo;
mutable std::optional<ref<LocationInfo>> locationInfo;

private:
// Instruction index in the basic block
Expand Down
75 changes: 71 additions & 4 deletions include/klee/Module/LocationInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,13 @@
#ifndef KLEE_LOCATIONINFO_H
#define KLEE_LOCATIONINFO_H

#include "klee/ADT/Ref.h"

#include <cstdint>
#include <functional>
#include <optional>
#include <string>
#include <unordered_set>

namespace llvm {
class Function;
Expand All @@ -23,12 +27,16 @@ class Module;

namespace klee {
struct PhysicalLocationJson;
}
struct LocationInfo;
} // namespace klee

namespace klee {

/// @brief Immutable struct representing location in source code.
struct LocationInfo {
/// @brief Required by klee::ref-managed objects
class ReferenceCounter _refCount;

/// @brief Path to source file for that location.
const std::string file;

Expand All @@ -44,14 +52,73 @@ struct LocationInfo {
/// @return SARIFs representation of location.
PhysicalLocationJson serialize() const;

static ref<LocationInfo> create(std::string file, uint64_t line,
std::optional<uint64_t> column) {
LocationInfo *locationInfo = new LocationInfo(file, line, column);
return createCachedLocationInfo(locationInfo);
}

bool operator==(const LocationInfo &rhs) const {
return file == rhs.file && line == rhs.line && column == rhs.column;
}

bool equals(const LocationInfo &b) const { return *this == b; }

~LocationInfo() {
if (isCached) {
toBeCleared = true;
cachedLocationInfo.cache.erase(this);
}
}

private:
LocationInfo(std::string file, uint64_t line, std::optional<uint64_t> column)
: file(file), line(line), column(column) {}

struct LocationInfoHash {
std::size_t operator()(LocationInfo *const s) const noexcept {
std::size_t r = 0;
std::size_t h1 = std::hash<std::string>{}(s->file);
std::size_t h2 = std::hash<uint64_t>{}(s->line);
std::size_t h3 = std::hash<std::optional<uint64_t>>{}(s->column);
r ^= h1 + 0x9e3779b9 + (r << 6) + (r >> 2);
r ^= h2 + 0x9e3779b9 + (r << 6) + (r >> 2);
r ^= h3 + 0x9e3779b9 + (r << 6) + (r >> 2);
return r;
}
};

struct LocationInfoCmp {
bool operator()(LocationInfo *const a, LocationInfo *const b) const {
return *a == *b;
}
};

using CacheType =
std::unordered_set<LocationInfo *, LocationInfoHash, LocationInfoCmp>;

struct LocationInfoCacheSet {
CacheType cache;
~LocationInfoCacheSet() {
while (cache.size() != 0) {
ref<LocationInfo> tmp = *cache.begin();
tmp->isCached = false;
cache.erase(cache.begin());
}
}
};

static LocationInfoCacheSet cachedLocationInfo;
bool isCached = false;
bool toBeCleared = false;

static ref<LocationInfo>
createCachedLocationInfo(ref<LocationInfo> locationInfo);
};

LocationInfo getLocationInfo(const llvm::Function *func);
LocationInfo getLocationInfo(const llvm::Instruction *inst);
LocationInfo getLocationInfo(const llvm::GlobalVariable *global);
ref<LocationInfo> getLocationInfo(const llvm::Function *func);
ref<LocationInfo> getLocationInfo(const llvm::Instruction *inst);
ref<LocationInfo> getLocationInfo(const llvm::GlobalVariable *global);

} // namespace klee

Expand Down
6 changes: 3 additions & 3 deletions lib/Core/CodeLocation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ CodeLocation::CodeLocation(const Path::PathIndex &pathIndex,
uint64_t sourceCodeLine,
std::optional<uint64_t> sourceCodeColumn)
: pathIndex(pathIndex), source(source),
location(LocationInfo{sourceFilename, sourceCodeLine, sourceCodeColumn}) {
}
location(LocationInfo::create(sourceFilename, sourceCodeLine,
sourceCodeColumn)) {}

ref<CodeLocation>
CodeLocation::create(const Path::PathIndex &pathIndex, const KValue *source,
Expand All @@ -44,7 +44,7 @@ CodeLocation::create(const KValue *source, const std::string &sourceFilename,
}

PhysicalLocationJson CodeLocation::serialize() const {
return location.serialize();
return location->serialize();
}

bool CodeLocation::equals(const CodeLocation &b) const {
Expand Down
3 changes: 2 additions & 1 deletion lib/Core/CodeLocation.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include <cstdint>
#include <optional>
#include <string>
#include <unordered_set>

namespace klee {

Expand All @@ -35,7 +36,7 @@ struct CodeLocation {
const KValue *source;

/// @brief Location in source code.
const LocationInfo location;
const ref<LocationInfo> location;

private:
CodeLocation(const Path::PathIndex &pathIndex, const KValue *source,
Expand Down
1 change: 1 addition & 0 deletions lib/Core/Executor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@
#include <cassert>
#include <cerrno>
#include <cinttypes>
#include <cstddef>
#include <cstdint>
#include <cstring>
#include <cxxabi.h>
Expand Down
18 changes: 9 additions & 9 deletions lib/Core/StatsTracker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -758,7 +758,7 @@ void StatsTracker::writeIStats() {
// Always try to write the filename before the function name, as otherwise
// KCachegrind can create two entries for the function, one with an
// unnamed file and one without.
auto fnlFile = getLocationInfo(&fn).file;
auto fnlFile = getLocationInfo(&fn)->file;
if (fnlFile != sourceFile) {
of << "fl=" << fnlFile << "\n";
sourceFile = fnlFile;
Expand All @@ -772,9 +772,9 @@ void StatsTracker::writeIStats() {
auto instrLI = getLocationInfo(instrPtr);

unsigned index = executor.kmodule->getGlobalIndex(instrPtr);
if (instrLI.file != sourceFile) {
of << "fl=" << instrLI.file << "\n";
sourceFile = instrLI.file;
if (instrLI->file != sourceFile) {
of << "fl=" << instrLI->file << "\n";
sourceFile = instrLI->file;
}

{
Expand All @@ -783,7 +783,7 @@ void StatsTracker::writeIStats() {
of << asmLine.value() << " ";
}

of << instrLI.line << " ";
of << instrLI->line << " ";
for (unsigned i = 0; i < nStats; i++)
if (istatsMask.test(i))
of << sm.getIndexedValue(sm.getStatistic(i), index) << " ";
Expand All @@ -797,8 +797,8 @@ void StatsTracker::writeIStats() {
const Function *f = fit.first;
CallSiteInfo &csi = fit.second;
auto fli = getLocationInfo(f);
if (fli.file != "" && fli.file != sourceFile)
of << "cfl=" << fli.file << "\n";
if (fli->file != "" && fli->file != sourceFile)
of << "cfl=" << fli->file << "\n";
of << "cfn=" << f->getName().str() << "\n";
of << "calls=" << csi.count << " ";

Expand All @@ -808,15 +808,15 @@ void StatsTracker::writeIStats() {
of << asmLine.value() << " ";
}

of << fli.line << "\n";
of << fli->line << "\n";

{
auto asmLine = executor.kmodule->getAsmLine(instrPtr);
assert(asmLine.has_value());
of << asmLine.value() << " ";
}

of << instrLI.line << " ";
of << instrLI->line << " ";
for (unsigned i = 0; i < nStats; i++) {
if (istatsMask.test(i)) {
Statistic &s = sm.getStatistic(i);
Expand Down
6 changes: 3 additions & 3 deletions lib/Module/KInstruction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,21 +73,21 @@ size_t KInstruction::getLine() const {
if (!this->locationInfo.has_value()) {
this->locationInfo.emplace(getLocationInfo(inst()));
}
return this->locationInfo.value().line;
return this->locationInfo.value()->line;
}

size_t KInstruction::getColumn() const {
if (!this->locationInfo.has_value()) {
this->locationInfo.emplace(getLocationInfo(inst()));
}
return this->locationInfo.value().column.value_or(0);
return this->locationInfo.value()->column.value_or(0);
}

std::string KInstruction::getSourceFilepath() const {
if (!this->locationInfo.has_value()) {
this->locationInfo.emplace(getLocationInfo(inst()));
}
return this->locationInfo.value().file;
return this->locationInfo.value()->file;
}

std::string KInstruction::getSourceLocationString() const {
Expand Down
8 changes: 4 additions & 4 deletions lib/Module/KModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -461,11 +461,11 @@ KGlobalVariable::KGlobalVariable(llvm::GlobalVariable *global, unsigned id)
: KValue(global, KValue::Kind::GLOBAL_VARIABLE), id(id) {}

std::string KGlobalVariable::getSourceFilepath() const {
return getLocationInfo(globalVariable()).file;
return getLocationInfo(globalVariable())->file;
}
// Line number where the global variable is defined
size_t KGlobalVariable::getLine() const {
return getLocationInfo(globalVariable()).line;
return getLocationInfo(globalVariable())->line;
}

bool KGlobalVariable::operator<(const KValue &rhs) const {
Expand Down Expand Up @@ -531,12 +531,12 @@ KFunction::KFunction(llvm::Function *_function, KModule *_km,

size_t KFunction::getLine() const {
auto locationInfo = getLocationInfo(function());
return locationInfo.line;
return locationInfo->line;
}

std::string KFunction::getSourceFilepath() const {
auto locationInfo = getLocationInfo(function());
return locationInfo.file;
return locationInfo->file;
}

KFunction::~KFunction() {
Expand Down
37 changes: 26 additions & 11 deletions lib/Module/LocationInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,18 +44,34 @@ PhysicalLocationJson LocationInfo::serialize() const {

////////////////////////////////////////////////////////////////

LocationInfo getLocationInfo(const llvm::Function *func) {
LocationInfo::LocationInfoCacheSet LocationInfo::cachedLocationInfo;

ref<LocationInfo>
LocationInfo::createCachedLocationInfo(ref<LocationInfo> locationInfo) {
std::pair<CacheType::const_iterator, bool> success =
cachedLocationInfo.cache.insert(locationInfo.get());

if (success.second) {
// Cache miss
locationInfo->isCached = true;
return locationInfo;
}
// Cache hit
return (ref<LocationInfo>)*(success.first);
}

ref<LocationInfo> getLocationInfo(const llvm::Function *func) {
const auto dsub = func->getSubprogram();

if (dsub != nullptr) {
auto path = dsub->getFilename();
return {path.str(), dsub->getLine(), {}};
return LocationInfo::create(path.str(), dsub->getLine(), {});
}

return {"", 0, {}};
return LocationInfo::create("", 0, {});
}

LocationInfo getLocationInfo(const llvm::Instruction *inst) {
ref<LocationInfo> getLocationInfo(const llvm::Instruction *inst) {
// Retrieve debug information associated with instruction
const auto &dl = inst->getDebugLoc();

Expand All @@ -74,13 +90,13 @@ LocationInfo getLocationInfo(const llvm::Instruction *inst) {
column = LexicalBlock->getColumn();
}
}
return {full_path.str(), line, {column}};
return LocationInfo::create(full_path.str(), line, {column});
}

return getLocationInfo(inst->getParent()->getParent());
}

LocationInfo getLocationInfo(const llvm::GlobalVariable *globalVar) {
ref<LocationInfo> getLocationInfo(const llvm::GlobalVariable *globalVar) {
// Retrieve debug information associated with global variable.
// LLVM does not expose API for getting single DINode with location
// information.
Expand All @@ -91,20 +107,19 @@ LocationInfo getLocationInfo(const llvm::GlobalVariable *globalVar) {
// Return location from any debug info for global variable.
if (const llvm::DIGlobalVariable *debugInfoGlobalVar =
debugInfoEntry->getVariable()) {
return {debugInfoGlobalVar->getFilename().str(),
debugInfoGlobalVar->getLine(),
{}};
return LocationInfo::create(debugInfoGlobalVar->getFilename().str(),
debugInfoGlobalVar->getLine(), {});
}
}

// For `extern` variables return `external` file.
if (globalVar->hasExternalLinkage()) {
return {"external", 0, {}};
return LocationInfo::create("external", 0, {});
}

// Fallback to empty location if there is no appropriate debug
// info.
return {"", 0, {}};
return LocationInfo::create("", 0, {});
}

} // namespace klee
14 changes: 7 additions & 7 deletions lib/Module/SarifReport.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -357,19 +357,19 @@ bool Location::isInside(const llvm::Function *f,
auto firstLoc = getLocationInfo(first);
auto lastLoc = getLocationInfo(last);
if (!startColumn.has_value()) {
if (firstLoc.line > endLine) {
if (firstLoc->line > endLine) {
return false;
}
return startLine <= lastLoc.line;
return startLine <= lastLoc->line;
}
for (const auto &block : *f) {
for (const auto &inst : block) {
auto locInfo = getLocationInfo(&inst);
if (!isa<DbgInfoIntrinsic>(&inst) && locInfo.line <= endLine &&
locInfo.line >= startLine && locInfo.column <= *endColumn &&
locInfo.column >= *startColumn &&
origInsts.at(locInfo.line)
.at(locInfo.column.value_or(0))
if (!isa<DbgInfoIntrinsic>(&inst) && locInfo->line <= endLine &&
locInfo->line >= startLine && locInfo->column <= *endColumn &&
locInfo->column >= *startColumn &&
origInsts.at(locInfo->line)
.at(locInfo->column.value_or(0))
.count(inst.getOpcode()) != 0) {
return true;
}
Expand Down
Loading

0 comments on commit 9d57e3f

Please sign in to comment.