-
Notifications
You must be signed in to change notification settings - Fork 1.7k
/
Copy pathTrapDomain.h
116 lines (97 loc) · 3.17 KB
/
TrapDomain.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
#pragma once
#include <memory>
#include <sstream>
#include "absl/strings/str_cat.h"
#include "swift/extractor/trap/TrapLabel.h"
#include "swift/extractor/infra/file/TargetFile.h"
#include "swift/logging/SwiftLogging.h"
#include "swift/extractor/infra/SwiftMangledName.h"
namespace codeql {
// Abstracts a given trap output file, with its own universe of trap labels
class TrapDomain {
TargetFile out;
Logger logger{getLoggerName()};
public:
explicit TrapDomain(TargetFile&& out) : out{std::move(out)} {
LOG_DEBUG("writing trap file with target {}", this->out.target());
}
template <typename Entry>
void emit(const Entry& e, bool check = true) {
LOG_TRACE("{}", e);
if (check) {
e.forEachLabel([&e, this](const char* field, int index, auto& label) {
if (!label.valid()) {
LOG_ERROR("{} has undefined field {}{}", e.NAME, field,
index >= 0 ? absl::StrCat("[", index, "]") : "");
}
});
}
out << e << '\n';
}
template <typename... Args>
void emitComment(const Args&... args) {
out << "/* ";
(out << ... << args);
out << " */\n";
}
template <typename... Args>
void debug(const Args&... args) {
out << "/* DEBUG:\n";
(out << ... << args);
out << "\n*/\n";
}
UntypedTrapLabel createLabel() {
auto ret = allocateLabel();
assignStar(ret);
out << '\n';
return ret;
}
template <typename Tag>
TrapLabel<Tag> createTypedLabel() {
auto untyped = createLabel();
return TrapLabel<Tag>::unsafeCreateFromUntyped(untyped);
}
UntypedTrapLabel createLabel(const SwiftMangledName& name) {
auto ret = allocateLabel();
assignKey(ret, name);
out << '\n';
return ret;
}
template <typename Tag>
TrapLabel<Tag> createTypedLabel(const SwiftMangledName& name) {
auto untyped = createLabel(name);
return TrapLabel<Tag>::unsafeCreateFromUntyped(untyped);
}
template <typename Tag>
TrapLabel<Tag> createTypedLabelWithImplementationId(const SwiftMangledName& name,
const std::string_view& implementationId) {
auto untyped = allocateLabel();
assignKey(untyped, name);
LOG_TRACE("^^^ .implementation {}", implementationId);
out << " .implementation " << trapQuoted(implementationId) << '\n';
return TrapLabel<Tag>::unsafeCreateFromUntyped(untyped);
}
private:
uint64_t id_{0};
UntypedTrapLabel allocateLabel() { return UntypedTrapLabel{id_++}; }
void assignStar(UntypedTrapLabel label) {
LOG_TRACE("{}=*", label);
out << label << "=*";
}
void assignKey(UntypedTrapLabel label, const SwiftMangledName& name) {
auto key = name.str();
LOG_TRACE("{}=@{}", label, key);
out << label << "=@" << trapQuoted(key);
}
std::string getLoggerName() {
// packaged swift modules are typically structured as
// `Module.swiftmodule/<arch_triple>.swiftmodule`, so the parent is more informative
// We use `Module.swiftmodule/.trap` then
if (auto parent = out.target().parent_path(); parent.extension() == ".swiftmodule") {
return parent.filename() / ".trap";
} else {
return out.target().filename();
}
}
};
} // namespace codeql