mirror of
https://github.com/github/codeql.git
synced 2026-04-29 02:35:15 +02:00
Swift: add trap linkage awareness infrastructure
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
#include "swift/extractor/infra/TargetDomains.h"
|
||||
#include <iomanip>
|
||||
|
||||
namespace codeql {
|
||||
|
||||
static const char* typeToStr(TrapType type) {
|
||||
switch (type) {
|
||||
case TrapType::source:
|
||||
@@ -9,6 +11,8 @@ static const char* typeToStr(TrapType type) {
|
||||
return "modules";
|
||||
case TrapType::invocation:
|
||||
return "invocations";
|
||||
case TrapType::linkage:
|
||||
return "linkage";
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
@@ -42,4 +46,33 @@ std::optional<TrapDomain> createTargetTrapDomain(SwiftExtractorState& state,
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<LinkDomain> createTargetLinkDomain(const SwiftExtractorState& state,
|
||||
const std::filesystem::path& target) {
|
||||
if (target.empty()) {
|
||||
return std::nullopt;
|
||||
}
|
||||
auto file = getRelativeTrapPath(target, TrapType::linkage, ".link");
|
||||
auto ret =
|
||||
TargetFile::create(file, state.configuration.trapDir, state.configuration.getTempTrapDir());
|
||||
if (ret) {
|
||||
return LinkDomain{*std::move(ret)};
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<ObjectDomain> createTargetObjectDomain(const SwiftExtractorState& state,
|
||||
const std::filesystem::path& target) {
|
||||
if (target.empty()) {
|
||||
return std::nullopt;
|
||||
}
|
||||
auto file = getRelativeTrapPath(target, TrapType::linkage, ".odep");
|
||||
auto ret =
|
||||
TargetFile::create(file, state.configuration.trapDir, state.configuration.getTempTrapDir());
|
||||
if (ret) {
|
||||
return ObjectDomain{*std::move(ret)};
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
} // namespace codeql
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include "swift/extractor/trap/TrapDomain.h"
|
||||
#include "swift/extractor/trap/LinkDomain.h"
|
||||
#include "swift/extractor/trap/ObjectDomain.h"
|
||||
#include "swift/extractor/config/SwiftExtractorState.h"
|
||||
|
||||
namespace codeql {
|
||||
@@ -9,10 +11,17 @@ enum class TrapType {
|
||||
source,
|
||||
module,
|
||||
invocation,
|
||||
linkage,
|
||||
};
|
||||
|
||||
std::optional<TrapDomain> createTargetTrapDomain(SwiftExtractorState& state,
|
||||
const std::filesystem::path& target,
|
||||
TrapType type);
|
||||
|
||||
std::optional<LinkDomain> createTargetLinkDomain(const SwiftExtractorState& state,
|
||||
const std::filesystem::path& target);
|
||||
|
||||
std::optional<ObjectDomain> createTargetObjectDomain(const SwiftExtractorState& state,
|
||||
const std::filesystem::path& target);
|
||||
|
||||
} // namespace codeql
|
||||
|
||||
@@ -30,7 +30,7 @@ filegroup(
|
||||
|
||||
swift_cc_library(
|
||||
name = "trap",
|
||||
srcs = [
|
||||
srcs = glob(["*.cpp"]) + [
|
||||
"generated/%s%s.cpp" % (dir, name)
|
||||
for dir in _dirs
|
||||
for name in ("TrapEntries", "TrapClasses")
|
||||
@@ -43,4 +43,7 @@ swift_cc_library(
|
||||
for name in ("TrapEntries", "TrapClasses")
|
||||
],
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//swift/extractor/infra/file",
|
||||
],
|
||||
)
|
||||
|
||||
37
swift/extractor/trap/LinkDomain.cpp
Normal file
37
swift/extractor/trap/LinkDomain.cpp
Normal file
@@ -0,0 +1,37 @@
|
||||
#include "swift/extractor/trap/LinkDomain.h"
|
||||
|
||||
namespace codeql {
|
||||
LinkDomain::LinkDomain(TargetFile out) : out{std::move(out)} {
|
||||
this->out << "Linker invocation 1.0\n";
|
||||
}
|
||||
|
||||
void LinkDomain::emitTarget(const std::string& target) {
|
||||
ensurePhase(Phase::target);
|
||||
out << target << '\n';
|
||||
}
|
||||
|
||||
void LinkDomain::emitObjectDependency(const std::string& object) {
|
||||
ensurePhase(Phase::objects);
|
||||
out << object << '\n';
|
||||
}
|
||||
|
||||
void LinkDomain::ensurePhase(Phase phase) {
|
||||
assert(phase >= current && "wrong order in .link file attributes");
|
||||
|
||||
if (phase > current) {
|
||||
switch (phase) {
|
||||
case Phase::target:
|
||||
out << "TARGET\n";
|
||||
break;
|
||||
case Phase::objects:
|
||||
out << "OBJECTS\n";
|
||||
break;
|
||||
default:
|
||||
assert(false && "unexpected phase");
|
||||
break;
|
||||
}
|
||||
}
|
||||
current = phase;
|
||||
}
|
||||
|
||||
} // namespace codeql
|
||||
30
swift/extractor/trap/LinkDomain.h
Normal file
30
swift/extractor/trap/LinkDomain.h
Normal file
@@ -0,0 +1,30 @@
|
||||
#pragma once
|
||||
|
||||
#include <cassert>
|
||||
#include "swift/extractor/infra/file/TargetFile.h"
|
||||
|
||||
namespace codeql {
|
||||
|
||||
class LinkDomain {
|
||||
TargetFile out;
|
||||
|
||||
enum class Phase {
|
||||
header,
|
||||
target,
|
||||
objects,
|
||||
end,
|
||||
};
|
||||
|
||||
Phase current{Phase::header};
|
||||
|
||||
public:
|
||||
explicit LinkDomain(TargetFile out);
|
||||
|
||||
void emitTarget(const std::string& target);
|
||||
void emitObjectDependency(const std::string& object);
|
||||
|
||||
private:
|
||||
void ensurePhase(Phase phase);
|
||||
};
|
||||
|
||||
} // namespace codeql
|
||||
45
swift/extractor/trap/ObjectDomain.cpp
Normal file
45
swift/extractor/trap/ObjectDomain.cpp
Normal file
@@ -0,0 +1,45 @@
|
||||
#include "swift/extractor/trap/ObjectDomain.h"
|
||||
|
||||
namespace codeql {
|
||||
ObjectDomain::ObjectDomain(TargetFile out) : out{std::move(out)} {
|
||||
this->out << "TRAP dependencies 1.2\n";
|
||||
}
|
||||
|
||||
void ObjectDomain::emitObject(const std::string& object) {
|
||||
ensurePhase(Phase::objects);
|
||||
out << object << '\n';
|
||||
}
|
||||
|
||||
void ObjectDomain::emitObjectDependency(const std::string& object) {
|
||||
ensurePhase(Phase::input_objects);
|
||||
out << object << '\n';
|
||||
}
|
||||
|
||||
void ObjectDomain::emitTrapDependency(const std::filesystem::path& trap) {
|
||||
ensurePhase(Phase::traps);
|
||||
out << trap.c_str() << '\n';
|
||||
}
|
||||
|
||||
void ObjectDomain::ensurePhase(Phase phase) {
|
||||
assert(phase >= current && "wrong order in .odep file attributes");
|
||||
|
||||
if (phase > current) {
|
||||
switch (phase) {
|
||||
case Phase::objects:
|
||||
out << "OBJECTS\n";
|
||||
break;
|
||||
case Phase::input_objects:
|
||||
out << "INPUT_OBJECTS\n";
|
||||
break;
|
||||
case Phase::traps:
|
||||
out << "TRAPS\n";
|
||||
break;
|
||||
default:
|
||||
assert(false && "unexpected phase");
|
||||
break;
|
||||
}
|
||||
}
|
||||
current = phase;
|
||||
}
|
||||
|
||||
} // namespace codeql
|
||||
33
swift/extractor/trap/ObjectDomain.h
Normal file
33
swift/extractor/trap/ObjectDomain.h
Normal file
@@ -0,0 +1,33 @@
|
||||
#pragma once
|
||||
|
||||
#include <cassert>
|
||||
#include <filesystem>
|
||||
#include "swift/extractor/infra/file/TargetFile.h"
|
||||
|
||||
namespace codeql {
|
||||
|
||||
class ObjectDomain {
|
||||
TargetFile out;
|
||||
|
||||
enum class Phase {
|
||||
header,
|
||||
objects,
|
||||
input_objects,
|
||||
traps,
|
||||
end,
|
||||
};
|
||||
|
||||
Phase current{Phase::header};
|
||||
|
||||
public:
|
||||
explicit ObjectDomain(TargetFile out);
|
||||
|
||||
void emitObject(const std::string& object);
|
||||
void emitObjectDependency(const std::string& object);
|
||||
void emitTrapDependency(const std::filesystem::path& trap);
|
||||
|
||||
private:
|
||||
void ensurePhase(Phase phase);
|
||||
};
|
||||
|
||||
} // namespace codeql
|
||||
@@ -10,27 +10,28 @@ namespace codeql {
|
||||
|
||||
// Abstracts a given trap output file, with its own universe of trap labels
|
||||
class TrapDomain {
|
||||
TargetFile out_;
|
||||
TargetFile out;
|
||||
|
||||
public:
|
||||
explicit TrapDomain(TargetFile&& out) : out_{std::move(out)} {}
|
||||
explicit TrapDomain(TargetFile&& out) : out{std::move(out)} {}
|
||||
|
||||
template <typename Entry>
|
||||
void emit(const Entry& e) {
|
||||
print(e);
|
||||
out << e << '\n';
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
void debug(const Args&... args) {
|
||||
print("/* DEBUG:");
|
||||
print(args...);
|
||||
print("*/");
|
||||
out << "/* DEBUG:\n";
|
||||
(out << ... << args);
|
||||
out << "\n*/\n";
|
||||
}
|
||||
|
||||
template <typename Tag>
|
||||
TrapLabel<Tag> createLabel() {
|
||||
auto ret = allocateLabel<Tag>();
|
||||
assignStar(ret);
|
||||
out << '\n';
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -38,6 +39,16 @@ class TrapDomain {
|
||||
TrapLabel<Tag> createLabel(Args&&... args) {
|
||||
auto ret = allocateLabel<Tag>();
|
||||
assignKey(ret, std::forward<Args>(args)...);
|
||||
out << '\n';
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <typename Tag, typename... Args>
|
||||
TrapLabel<Tag> createLabelWithImplementationId(const std::string_view& implementationId,
|
||||
Args&&... args) {
|
||||
auto ret = allocateLabel<Tag>();
|
||||
assignKey(ret, std::forward<Args>(args)...);
|
||||
out << " .implementation " << trapQuoted(implementationId) << '\n';
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -49,21 +60,16 @@ class TrapDomain {
|
||||
return TrapLabel<Tag>::unsafeCreateFromExplicitId(id_++);
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
void print(const Args&... args) {
|
||||
(out_ << ... << args) << '\n';
|
||||
}
|
||||
|
||||
template <typename Tag>
|
||||
void assignStar(TrapLabel<Tag> label) {
|
||||
print(label, "=*");
|
||||
out << label << "=*";
|
||||
}
|
||||
|
||||
template <typename Tag>
|
||||
void assignKey(TrapLabel<Tag> label, const std::string& key) {
|
||||
// prefix the key with the id to guarantee the same key is not used wrongly with different tags
|
||||
auto prefixed = std::string(Tag::prefix) + '_' + key;
|
||||
print(label, "=@", trapQuoted(prefixed));
|
||||
out << label << "=@" << trapQuoted(prefixed);
|
||||
}
|
||||
|
||||
template <typename Tag, typename... Args>
|
||||
|
||||
@@ -86,7 +86,7 @@ struct TrapLabelVectorWrapper {
|
||||
}
|
||||
};
|
||||
|
||||
inline auto trapQuoted(const std::string& s) {
|
||||
inline auto trapQuoted(const std::string_view& s) {
|
||||
return std::quoted(s, '"', '"');
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user