mirror of
https://github.com/github/codeql.git
synced 2025-12-17 01:03:14 +01:00
Merge pull request #12500 from github/redsun82/swift-dispatcher-rework
Swift: rework fetching and dispatching
This commit is contained in:
@@ -12,7 +12,6 @@ swift_cc_binary(
|
||||
"//swift/extractor/config",
|
||||
"//swift/extractor/infra",
|
||||
"//swift/extractor/invocation",
|
||||
"//swift/extractor/mangler",
|
||||
"//swift/extractor/remapping",
|
||||
"//swift/extractor/translators",
|
||||
"//swift/third_party/swift-llvm-support",
|
||||
|
||||
@@ -44,6 +44,26 @@ static void archiveFile(const SwiftExtractorConfiguration& config, swift::Source
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: This should be factored out/replaced with simplified version of custom mangling
|
||||
static std::string mangledDeclName(const swift::ValueDecl& decl) {
|
||||
std::string_view moduleName = decl.getModuleContext()->getRealName().str();
|
||||
// ASTMangler::mangleAnyDecl crashes when called on `ModuleDecl`
|
||||
if (decl.getKind() == swift::DeclKind::Module) {
|
||||
return std::string{moduleName};
|
||||
}
|
||||
swift::Mangle::ASTMangler mangler;
|
||||
if (decl.getKind() == swift::DeclKind::TypeAlias) {
|
||||
// In cases like this (when coming from PCM)
|
||||
// typealias CFXMLTree = CFTree
|
||||
// typealias CFXMLTreeRef = CFXMLTree
|
||||
// mangleAnyDecl mangles both CFXMLTree and CFXMLTreeRef into 'So12CFXMLTreeRefa'
|
||||
// which is not correct and causes inconsistencies. mangleEntity makes these two distinct
|
||||
// prefix adds a couple of special symbols, we don't necessary need them
|
||||
return mangler.mangleEntity(&decl);
|
||||
}
|
||||
return mangler.mangleAnyDecl(&decl, /* prefix = */ false);
|
||||
}
|
||||
|
||||
static fs::path getFilename(swift::ModuleDecl& module,
|
||||
swift::SourceFile* primaryFile,
|
||||
const swift::Decl* lazyDeclaration) {
|
||||
@@ -52,15 +72,15 @@ static fs::path getFilename(swift::ModuleDecl& module,
|
||||
}
|
||||
if (lazyDeclaration) {
|
||||
// this code will be thrown away in the near future
|
||||
SwiftMangler mangler;
|
||||
auto mangled = mangler.mangledName(*lazyDeclaration);
|
||||
auto decl = llvm::dyn_cast<swift::ValueDecl>(lazyDeclaration);
|
||||
assert(decl);
|
||||
auto mangled = mangledDeclName(*decl);
|
||||
// mangled name can be too long to use as a file name, so we can't use it directly
|
||||
mangled = picosha2::hash256_hex_string(mangled);
|
||||
std::string ret;
|
||||
ret += module.getRealName().str();
|
||||
ret += '_';
|
||||
// lazyDeclaration must be a ValueDecl, as already asserted in SwiftMangler::mangledName
|
||||
ret += llvm::cast<swift::ValueDecl>(lazyDeclaration)->getBaseName().userFacingName();
|
||||
ret += decl->getBaseName().userFacingName();
|
||||
ret += '_';
|
||||
// half a SHA2 is enough
|
||||
ret += std::string_view(mangled).substr(0, mangled.size() / 2);
|
||||
|
||||
@@ -6,12 +6,12 @@
|
||||
#include <swift/Basic/SourceManager.h>
|
||||
#include <swift/Parse/Token.h>
|
||||
|
||||
#include "swift/extractor/trap/TrapLabelStore.h"
|
||||
#include "swift/extractor/trap/TrapDomain.h"
|
||||
#include "swift/extractor/infra/SwiftTagTraits.h"
|
||||
#include "swift/extractor/trap/generated/TrapClasses.h"
|
||||
#include "swift/extractor/infra/SwiftLocationExtractor.h"
|
||||
#include "swift/extractor/infra/SwiftBodyEmissionStrategy.h"
|
||||
#include "swift/extractor/infra/SwiftMangledName.h"
|
||||
#include "swift/extractor/config/SwiftExtractorState.h"
|
||||
#include "swift/extractor/infra/log/SwiftLogging.h"
|
||||
|
||||
@@ -24,24 +24,31 @@ namespace codeql {
|
||||
// node (AST nodes that are not types: declarations, statements, expressions, etc.).
|
||||
class SwiftDispatcher {
|
||||
// types to be supported by assignNewLabel/fetchLabel need to be listed here
|
||||
using Store = TrapLabelStore<const swift::Decl*,
|
||||
const swift::Stmt*,
|
||||
const swift::StmtCondition*,
|
||||
const swift::StmtConditionElement*,
|
||||
const swift::CaseLabelItem*,
|
||||
const swift::Expr*,
|
||||
const swift::Pattern*,
|
||||
const swift::TypeRepr*,
|
||||
const swift::TypeBase*,
|
||||
const swift::CapturedValue*,
|
||||
const swift::PoundAvailableInfo*,
|
||||
const swift::AvailabilitySpec*>;
|
||||
using Handle = std::variant<const swift::Decl*,
|
||||
const swift::Stmt*,
|
||||
const swift::StmtCondition*,
|
||||
const swift::StmtConditionElement*,
|
||||
const swift::CaseLabelItem*,
|
||||
const swift::Expr*,
|
||||
const swift::Pattern*,
|
||||
const swift::TypeRepr*,
|
||||
const swift::TypeBase*,
|
||||
const swift::CapturedValue*,
|
||||
const swift::PoundAvailableInfo*,
|
||||
const swift::AvailabilitySpec*>;
|
||||
|
||||
template <typename E>
|
||||
static constexpr bool IsStorable = std::is_constructible_v<Store::Handle, const E&>;
|
||||
static constexpr bool IsFetchable = std::is_constructible_v<Handle, const E&>;
|
||||
|
||||
template <typename E>
|
||||
static constexpr bool IsLocatable = std::is_base_of_v<LocatableTag, TrapTagOf<E>>;
|
||||
static constexpr bool IsLocatable =
|
||||
std::is_base_of_v<LocatableTag, TrapTagOf<E>> && !std::is_base_of_v<TypeTag, TrapTagOf<E>>;
|
||||
|
||||
template <typename E>
|
||||
static constexpr bool IsDeclPointer = std::is_convertible_v<E, const swift::Decl*>;
|
||||
|
||||
template <typename E>
|
||||
static constexpr bool IsTypePointer = std::is_convertible_v<E, const swift::TypeBase*>;
|
||||
|
||||
public:
|
||||
// all references and pointers passed as parameters to this constructor are supposed to outlive
|
||||
@@ -112,7 +119,7 @@ class SwiftDispatcher {
|
||||
TrapLabel<UnspecifiedElementTag> emitUnspecified(std::optional<TrapLabel<ElementTag>>&& parent,
|
||||
const char* property,
|
||||
int index) {
|
||||
UnspecifiedElement entry{trap.createLabel<UnspecifiedElementTag>()};
|
||||
UnspecifiedElement entry{trap.createTypedLabel<UnspecifiedElementTag>()};
|
||||
entry.error = "element was unspecified by the extractor";
|
||||
entry.parent = std::move(parent);
|
||||
entry.property = property;
|
||||
@@ -135,35 +142,22 @@ class SwiftDispatcher {
|
||||
// This method gives a TRAP label for already emitted AST node.
|
||||
// If the AST node was not emitted yet, then the emission is dispatched to a corresponding
|
||||
// visitor (see `visit(T *)` methods below).
|
||||
template <typename E, typename... Args, std::enable_if_t<IsStorable<E>>* = nullptr>
|
||||
TrapLabelOf<E> fetchLabel(const E& e, Args&&... args) {
|
||||
template <typename E, std::enable_if_t<IsFetchable<E>>* = nullptr>
|
||||
TrapLabelOf<E> fetchLabel(const E& e, swift::Type type = {}) {
|
||||
if constexpr (std::is_constructible_v<bool, const E&>) {
|
||||
if (!e) {
|
||||
// this will be treated on emission
|
||||
return undefined_label;
|
||||
}
|
||||
}
|
||||
// this is required so we avoid any recursive loop: a `fetchLabel` during the visit of `e` might
|
||||
// end up calling `fetchLabel` on `e` itself, so we want the visit of `e` to call `fetchLabel`
|
||||
// only after having called `assignNewLabel` on `e`.
|
||||
assert(std::holds_alternative<std::monostate>(waitingForNewLabel) &&
|
||||
"fetchLabel called before assignNewLabel");
|
||||
if (auto l = store.get(e)) {
|
||||
return *l;
|
||||
auto& stored = store[e];
|
||||
if (!stored.valid()) {
|
||||
auto inserted = fetching.insert(e);
|
||||
assert(inserted.second && "detected infinite fetchLabel recursion");
|
||||
stored = createLabel(e, type);
|
||||
fetching.erase(e);
|
||||
}
|
||||
waitingForNewLabel = e;
|
||||
// TODO: add tracing logs for visited stuff, maybe within the translators?
|
||||
visit(e, std::forward<Args>(args)...);
|
||||
Log::flush();
|
||||
// TODO when everything is moved to structured C++ classes, this should be moved to createEntry
|
||||
if (auto l = store.get(e)) {
|
||||
if constexpr (IsLocatable<E>) {
|
||||
locationExtractor.attachLocation(sourceManager, e, *l);
|
||||
}
|
||||
return *l;
|
||||
}
|
||||
assert(!"assignNewLabel not called during visit");
|
||||
return {};
|
||||
return TrapLabelOf<E>::unsafeCreateFromUntyped(stored);
|
||||
}
|
||||
|
||||
// convenience `fetchLabel` overload for `swift::Type` (which is just a wrapper for
|
||||
@@ -174,39 +168,28 @@ class SwiftDispatcher {
|
||||
return fetchLabelFromUnion<AstNodeTag>(node);
|
||||
}
|
||||
|
||||
template <typename E, std::enable_if_t<IsStorable<E*>>* = nullptr>
|
||||
template <typename E, std::enable_if_t<IsFetchable<E*>>* = nullptr>
|
||||
TrapLabelOf<E> fetchLabel(const E& e) {
|
||||
return fetchLabel(&e);
|
||||
}
|
||||
|
||||
// Due to the lazy emission approach, we must assign a label to a corresponding AST node before
|
||||
// it actually gets emitted to handle recursive cases such as recursive calls, or recursive type
|
||||
// declarations
|
||||
template <typename E, typename... Args, std::enable_if_t<IsStorable<E>>* = nullptr>
|
||||
TrapLabel<ConcreteTrapTagOf<E>> assignNewLabel(const E& e, Args&&... args) {
|
||||
assert(waitingForNewLabel == Store::Handle{e} && "assignNewLabel called on wrong entity");
|
||||
auto label = trap.createLabel<ConcreteTrapTagOf<E>>(std::forward<Args>(args)...);
|
||||
store.insert(e, label);
|
||||
waitingForNewLabel = std::monostate{};
|
||||
return label;
|
||||
}
|
||||
|
||||
template <typename E, typename... Args, std::enable_if_t<IsStorable<E*>>* = nullptr>
|
||||
TrapLabel<ConcreteTrapTagOf<E>> assignNewLabel(const E& e, Args&&... args) {
|
||||
return assignNewLabel(&e, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
// convenience methods for structured C++ creation
|
||||
template <typename E, typename... Args>
|
||||
auto createEntry(const E& e, Args&&... args) {
|
||||
return TrapClassOf<E>{assignNewLabel(e, std::forward<Args>(args)...)};
|
||||
template <typename E>
|
||||
auto createEntry(const E& e) {
|
||||
auto found = store.find(&e);
|
||||
assert(found != store.end() && "createEntry called on non-fetched label");
|
||||
auto label = TrapLabel<ConcreteTrapTagOf<E>>::unsafeCreateFromUntyped(found->second);
|
||||
if constexpr (IsLocatable<E>) {
|
||||
locationExtractor.attachLocation(sourceManager, e, label);
|
||||
}
|
||||
return TrapClassOf<E>{label};
|
||||
}
|
||||
|
||||
// used to create a new entry for entities that should not be cached
|
||||
// an example is swift::Argument, that are created on the fly and thus have no stable pointer
|
||||
template <typename E, typename... Args>
|
||||
auto createUncachedEntry(const E& e, Args&&... args) {
|
||||
auto label = trap.createLabel<TrapTagOf<E>>(std::forward<Args>(args)...);
|
||||
template <typename E>
|
||||
auto createUncachedEntry(const E& e) {
|
||||
auto label = trap.createTypedLabel<TrapTagOf<E>>();
|
||||
locationExtractor.attachLocation(sourceManager, &e, label);
|
||||
return TrapClassOf<E>{label};
|
||||
}
|
||||
@@ -243,31 +226,65 @@ class SwiftDispatcher {
|
||||
trap.debug(args...);
|
||||
}
|
||||
|
||||
bool shouldEmitDeclBody(const swift::Decl& decl) {
|
||||
encounteredModules.insert(decl.getModuleContext());
|
||||
return bodyEmissionStrategy.shouldEmitDeclBody(decl);
|
||||
}
|
||||
|
||||
void emitComment(swift::Token& comment) {
|
||||
CommentsTrap entry{trap.createLabel<CommentTag>(), comment.getRawText().str()};
|
||||
CommentsTrap entry{trap.createTypedLabel<CommentTag>(), comment.getRawText().str()};
|
||||
trap.emit(entry);
|
||||
locationExtractor.attachLocation(sourceManager, comment, entry.id);
|
||||
}
|
||||
|
||||
void extractedDeclaration(const swift::Decl& decl) {
|
||||
if (isLazyDeclaration(decl)) {
|
||||
state.emittedDeclarations.insert(&decl);
|
||||
}
|
||||
}
|
||||
void skippedDeclaration(const swift::Decl& decl) {
|
||||
if (isLazyDeclaration(decl)) {
|
||||
state.pendingDeclarations.insert(&decl);
|
||||
protected:
|
||||
void visitPending() {
|
||||
while (!toBeVisited.empty()) {
|
||||
auto [next, type] = toBeVisited.back();
|
||||
toBeVisited.pop_back();
|
||||
// TODO: add tracing logs for visited stuff, maybe within the translators?
|
||||
std::visit([this, type = type](const auto* e) { visit(e, type); }, next);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
bool isLazyDeclaration(const swift::Decl& decl) {
|
||||
swift::ModuleDecl* module = decl.getModuleContext();
|
||||
template <typename E>
|
||||
UntypedTrapLabel createLabel(const E& e, swift::Type type) {
|
||||
if constexpr (IsDeclPointer<E> || IsTypePointer<E>) {
|
||||
if (auto mangledName = name(e)) {
|
||||
if (shouldVisit(e)) {
|
||||
toBeVisited.emplace_back(e, type);
|
||||
}
|
||||
return trap.createLabel(mangledName);
|
||||
}
|
||||
}
|
||||
// we always need to visit unnamed things
|
||||
toBeVisited.emplace_back(e, type);
|
||||
return trap.createLabel();
|
||||
}
|
||||
|
||||
template <typename E>
|
||||
bool shouldVisit(const E& e) {
|
||||
if constexpr (IsDeclPointer<E>) {
|
||||
encounteredModules.insert(e->getModuleContext());
|
||||
if (bodyEmissionStrategy.shouldEmitDeclBody(*e)) {
|
||||
extractedDeclaration(e);
|
||||
return true;
|
||||
}
|
||||
skippedDeclaration(e);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void extractedDeclaration(const swift::Decl* decl) {
|
||||
if (isLazyDeclaration(decl)) {
|
||||
state.emittedDeclarations.insert(decl);
|
||||
}
|
||||
}
|
||||
void skippedDeclaration(const swift::Decl* decl) {
|
||||
if (isLazyDeclaration(decl)) {
|
||||
state.pendingDeclarations.insert(decl);
|
||||
}
|
||||
}
|
||||
|
||||
static bool isLazyDeclaration(const swift::Decl* decl) {
|
||||
swift::ModuleDecl* module = decl->getModuleContext();
|
||||
return module->isBuiltinModule() || module->getName().str() == "__ObjC" ||
|
||||
module->isNonSwiftModule();
|
||||
}
|
||||
@@ -311,6 +328,8 @@ class SwiftDispatcher {
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual SwiftMangledName name(const swift::Decl* decl) = 0;
|
||||
virtual SwiftMangledName name(const swift::TypeBase* type) = 0;
|
||||
virtual void visit(const swift::Decl* decl) = 0;
|
||||
virtual void visit(const swift::Stmt* stmt) = 0;
|
||||
virtual void visit(const swift::StmtCondition* cond) = 0;
|
||||
@@ -324,13 +343,19 @@ class SwiftDispatcher {
|
||||
virtual void visit(const swift::TypeBase* type) = 0;
|
||||
virtual void visit(const swift::CapturedValue* capture) = 0;
|
||||
|
||||
template <typename T, std::enable_if<!std::is_base_of_v<swift::TypeRepr, T>>* = nullptr>
|
||||
void visit(const T* e, swift::Type) {
|
||||
visit(e);
|
||||
}
|
||||
|
||||
const swift::SourceManager& sourceManager;
|
||||
SwiftExtractorState& state;
|
||||
TrapDomain& trap;
|
||||
Store store;
|
||||
std::unordered_map<Handle, UntypedTrapLabel> store;
|
||||
std::unordered_set<Handle> fetching;
|
||||
std::vector<std::pair<Handle, swift::Type>> toBeVisited;
|
||||
SwiftLocationExtractor& locationExtractor;
|
||||
SwiftBodyEmissionStrategy& bodyEmissionStrategy;
|
||||
Store::Handle waitingForNewLabel{std::monostate{}};
|
||||
std::unordered_set<swift::ModuleDecl*> encounteredModules;
|
||||
Logger logger{"dispatcher"};
|
||||
};
|
||||
|
||||
@@ -8,13 +8,14 @@
|
||||
#include "swift/extractor/trap/generated/TrapClasses.h"
|
||||
#include "swift/extractor/infra/SwiftLocationExtractor.h"
|
||||
#include "swift/extractor/infra/file/Path.h"
|
||||
#include "swift/extractor/infra/SwiftMangledName.h"
|
||||
|
||||
using namespace codeql;
|
||||
|
||||
void SwiftLocationExtractor::attachLocation(const swift::SourceManager& sourceManager,
|
||||
swift::SourceLoc start,
|
||||
swift::SourceLoc end,
|
||||
TrapLabel<LocatableTag> locatableLabel) {
|
||||
void SwiftLocationExtractor::attachLocationImpl(const swift::SourceManager& sourceManager,
|
||||
swift::SourceLoc start,
|
||||
swift::SourceLoc end,
|
||||
TrapLabel<LocatableTag> locatableLabel) {
|
||||
if (!start.isValid() || !end.isValid()) {
|
||||
// invalid locations seem to come from entities synthesized by the compiler
|
||||
return;
|
||||
@@ -24,9 +25,9 @@ void SwiftLocationExtractor::attachLocation(const swift::SourceManager& sourceMa
|
||||
entry.file = fetchFileLabel(file);
|
||||
std::tie(entry.start_line, entry.start_column) = sourceManager.getLineAndColumnInBuffer(start);
|
||||
std::tie(entry.end_line, entry.end_column) = sourceManager.getLineAndColumnInBuffer(end);
|
||||
entry.id = trap.createLabel<DbLocationTag>('{', entry.file, "}:", entry.start_line, ':',
|
||||
entry.start_column, ':', entry.end_line, ':',
|
||||
entry.end_column);
|
||||
SwiftMangledName locName{{"loc", entry.file, ":", entry.start_line, ":", entry.start_column, ":",
|
||||
entry.end_line, ":", entry.end_column}};
|
||||
entry.id = trap.createTypedLabel<DbLocationTag>(locName);
|
||||
trap.emit(entry);
|
||||
trap.emit(LocatableLocationsTrap{locatableLabel, entry.id});
|
||||
}
|
||||
@@ -42,43 +43,54 @@ TrapLabel<FileTag> SwiftLocationExtractor::emitFile(const std::filesystem::path&
|
||||
return fetchFileLabel(resolvePath(file));
|
||||
}
|
||||
|
||||
void SwiftLocationExtractor::attachLocation(const swift::SourceManager& sourceManager,
|
||||
const swift::CapturedValue* capture,
|
||||
TrapLabel<LocatableTag> locatableLabel) {
|
||||
attachLocation(sourceManager, capture->getLoc(), locatableLabel);
|
||||
void SwiftLocationExtractor::attachLocationImpl(const swift::SourceManager& sourceManager,
|
||||
const swift::SourceRange& range,
|
||||
TrapLabel<LocatableTag> locatableLabel) {
|
||||
attachLocationImpl(sourceManager, range.Start, range.End, locatableLabel);
|
||||
}
|
||||
|
||||
void SwiftLocationExtractor::attachLocation(const swift::SourceManager& sourceManager,
|
||||
const swift::IfConfigClause* clause,
|
||||
TrapLabel<LocatableTag> locatableLabel) {
|
||||
attachLocation(sourceManager, clause->Loc, clause->Loc, locatableLabel);
|
||||
void SwiftLocationExtractor::attachLocationImpl(const swift::SourceManager& sourceManager,
|
||||
const swift::CapturedValue* capture,
|
||||
TrapLabel<LocatableTag> locatableLabel) {
|
||||
attachLocationImpl(sourceManager, capture->getLoc(), locatableLabel);
|
||||
}
|
||||
|
||||
void SwiftLocationExtractor::attachLocation(const swift::SourceManager& sourceManager,
|
||||
swift::AvailabilitySpec* spec,
|
||||
TrapLabel<LocatableTag> locatableLabel) {
|
||||
attachLocation(sourceManager, spec->getSourceRange().Start, spec->getSourceRange().End,
|
||||
locatableLabel);
|
||||
void SwiftLocationExtractor::attachLocationImpl(const swift::SourceManager& sourceManager,
|
||||
const swift::IfConfigClause* clause,
|
||||
TrapLabel<LocatableTag> locatableLabel) {
|
||||
attachLocationImpl(sourceManager, clause->Loc, locatableLabel);
|
||||
}
|
||||
|
||||
void SwiftLocationExtractor::attachLocation(const swift::SourceManager& sourceManager,
|
||||
swift::Token& token,
|
||||
TrapLabel<LocatableTag> locatableLabel) {
|
||||
attachLocation(sourceManager, token.getRange().getStart(), token.getRange().getEnd(),
|
||||
locatableLabel);
|
||||
void SwiftLocationExtractor::attachLocationImpl(const swift::SourceManager& sourceManager,
|
||||
const swift::AvailabilitySpec* spec,
|
||||
TrapLabel<LocatableTag> locatableLabel) {
|
||||
attachLocationImpl(sourceManager, spec->getSourceRange(), locatableLabel);
|
||||
}
|
||||
|
||||
void SwiftLocationExtractor::attachLocation(const swift::SourceManager& sourceManager,
|
||||
const swift::KeyPathExpr::Component* component,
|
||||
TrapLabel<LocatableTag> locatableLabel) {
|
||||
attachLocation(sourceManager, component->getSourceRange().Start, component->getSourceRange().End,
|
||||
locatableLabel);
|
||||
void SwiftLocationExtractor::attachLocationImpl(const swift::SourceManager& sourceManager,
|
||||
const swift::KeyPathExpr::Component* component,
|
||||
TrapLabel<LocatableTag> locatableLabel) {
|
||||
attachLocationImpl(sourceManager, component->getSourceRange().Start,
|
||||
component->getSourceRange().End, locatableLabel);
|
||||
}
|
||||
|
||||
void SwiftLocationExtractor::attachLocation(const swift::SourceManager& sourceManager,
|
||||
swift::SourceLoc loc,
|
||||
TrapLabel<LocatableTag> locatableLabel) {
|
||||
attachLocation(sourceManager, loc, loc, locatableLabel);
|
||||
void SwiftLocationExtractor::attachLocationImpl(const swift::SourceManager& sourceManager,
|
||||
const swift::Token* token,
|
||||
TrapLabel<LocatableTag> locatableLabel) {
|
||||
attachLocationImpl(sourceManager, token->getRange().getStart(), token->getRange().getEnd(),
|
||||
locatableLabel);
|
||||
}
|
||||
|
||||
void SwiftLocationExtractor::attachLocationImpl(const swift::SourceManager& sourceManager,
|
||||
swift::SourceLoc loc,
|
||||
TrapLabel<LocatableTag> locatableLabel) {
|
||||
attachLocationImpl(sourceManager, loc, loc, locatableLabel);
|
||||
}
|
||||
|
||||
void SwiftLocationExtractor::attachLocationImpl(const swift::SourceManager& sourceManager,
|
||||
const swift::DiagnosticInfo* diagInfo,
|
||||
TrapLabel<LocatableTag> locatableLabel) {
|
||||
attachLocationImpl(sourceManager, diagInfo->Loc, locatableLabel);
|
||||
}
|
||||
|
||||
TrapLabel<FileTag> SwiftLocationExtractor::fetchFileLabel(const std::filesystem::path& file) {
|
||||
@@ -87,7 +99,7 @@ TrapLabel<FileTag> SwiftLocationExtractor::fetchFileLabel(const std::filesystem:
|
||||
}
|
||||
|
||||
DbFile entry({});
|
||||
entry.id = trap.createLabel<DbFileTag>(file.string());
|
||||
entry.id = trap.createTypedLabel<DbFileTag>({{"file_", file.string()}});
|
||||
entry.name = file.string();
|
||||
trap.emit(entry);
|
||||
store[file] = entry.id;
|
||||
|
||||
@@ -16,6 +16,9 @@ namespace codeql {
|
||||
class TrapDomain;
|
||||
|
||||
class SwiftLocationExtractor {
|
||||
template <typename Locatable, typename = void>
|
||||
struct HasSpecializedImplementation : std::false_type {};
|
||||
|
||||
public:
|
||||
explicit SwiftLocationExtractor(TrapDomain& trap) : trap(trap) {}
|
||||
|
||||
@@ -24,60 +27,79 @@ class SwiftLocationExtractor {
|
||||
|
||||
template <typename Locatable>
|
||||
void attachLocation(const swift::SourceManager& sourceManager,
|
||||
Locatable locatable,
|
||||
const Locatable& locatable,
|
||||
TrapLabel<LocatableTag> locatableLabel) {
|
||||
attachLocation(sourceManager, &locatable, locatableLabel);
|
||||
}
|
||||
|
||||
// Emits a Location TRAP entry and attaches it to a `Locatable` trap label
|
||||
template <typename Locatable>
|
||||
template <typename Locatable,
|
||||
std::enable_if_t<!HasSpecializedImplementation<Locatable>::value>* = nullptr>
|
||||
void attachLocation(const swift::SourceManager& sourceManager,
|
||||
Locatable* locatable,
|
||||
const Locatable* locatable,
|
||||
TrapLabel<LocatableTag> locatableLabel) {
|
||||
attachLocation(sourceManager, locatable->getStartLoc(), locatable->getEndLoc(), locatableLabel);
|
||||
attachLocationImpl(sourceManager, locatable->getStartLoc(), locatable->getEndLoc(),
|
||||
locatableLabel);
|
||||
}
|
||||
|
||||
template <typename Locatable,
|
||||
std::enable_if_t<HasSpecializedImplementation<Locatable>::value>* = nullptr>
|
||||
void attachLocation(const swift::SourceManager& sourceManager,
|
||||
const Locatable* locatable,
|
||||
TrapLabel<LocatableTag> locatableLabel) {
|
||||
attachLocationImpl(sourceManager, locatable, locatableLabel);
|
||||
}
|
||||
|
||||
private:
|
||||
// Emits a Location TRAP entry for a list of swift entities and attaches it to a `Locatable` trap
|
||||
// label
|
||||
template <typename Locatable>
|
||||
void attachLocation(const swift::SourceManager& sourceManager,
|
||||
llvm::MutableArrayRef<Locatable>* locatables,
|
||||
TrapLabel<LocatableTag> locatableLabel) {
|
||||
void attachLocationImpl(const swift::SourceManager& sourceManager,
|
||||
const llvm::MutableArrayRef<Locatable>* locatables,
|
||||
TrapLabel<LocatableTag> locatableLabel) {
|
||||
if (locatables->empty()) {
|
||||
return;
|
||||
}
|
||||
attachLocation(sourceManager, locatables->front().getStartLoc(), locatables->back().getEndLoc(),
|
||||
locatableLabel);
|
||||
attachLocationImpl(sourceManager, locatables->front().getStartLoc(),
|
||||
locatables->back().getEndLoc(), locatableLabel);
|
||||
}
|
||||
|
||||
void attachLocation(const swift::SourceManager& sourceManager,
|
||||
swift::SourceLoc start,
|
||||
swift::SourceLoc end,
|
||||
TrapLabel<LocatableTag> locatableLabel);
|
||||
void attachLocationImpl(const swift::SourceManager& sourceManager,
|
||||
swift::SourceLoc start,
|
||||
swift::SourceLoc end,
|
||||
TrapLabel<LocatableTag> locatableLabel);
|
||||
|
||||
void attachLocation(const swift::SourceManager& sourceManager,
|
||||
swift::SourceLoc loc,
|
||||
TrapLabel<LocatableTag> locatableLabel);
|
||||
void attachLocationImpl(const swift::SourceManager& sourceManager,
|
||||
swift::SourceLoc loc,
|
||||
TrapLabel<LocatableTag> locatableLabel);
|
||||
|
||||
void attachLocation(const swift::SourceManager& sourceManager,
|
||||
const swift::CapturedValue* capture,
|
||||
TrapLabel<LocatableTag> locatableLabel);
|
||||
void attachLocationImpl(const swift::SourceManager& sourceManager,
|
||||
const swift::SourceRange& range,
|
||||
TrapLabel<LocatableTag> locatableLabel);
|
||||
|
||||
void attachLocation(const swift::SourceManager& sourceManager,
|
||||
const swift::IfConfigClause* clause,
|
||||
TrapLabel<LocatableTag> locatableLabel);
|
||||
void attachLocationImpl(const swift::SourceManager& sourceManager,
|
||||
const swift::CapturedValue* capture,
|
||||
TrapLabel<LocatableTag> locatableLabel);
|
||||
|
||||
void attachLocation(const swift::SourceManager& sourceManager,
|
||||
swift::AvailabilitySpec* spec,
|
||||
TrapLabel<LocatableTag> locatableLabel);
|
||||
void attachLocationImpl(const swift::SourceManager& sourceManager,
|
||||
const swift::IfConfigClause* clause,
|
||||
TrapLabel<LocatableTag> locatableLabel);
|
||||
|
||||
void attachLocation(const swift::SourceManager& sourceManager,
|
||||
swift::Token& token,
|
||||
TrapLabel<LocatableTag> locatableLabel);
|
||||
void attachLocationImpl(const swift::SourceManager& sourceManager,
|
||||
const swift::AvailabilitySpec* spec,
|
||||
TrapLabel<LocatableTag> locatableLabel);
|
||||
|
||||
void attachLocation(const swift::SourceManager& sourceManager,
|
||||
const swift::KeyPathExpr::Component* component,
|
||||
TrapLabel<LocatableTag> locatableLabel);
|
||||
void attachLocationImpl(const swift::SourceManager& sourceManager,
|
||||
const swift::Token* token,
|
||||
TrapLabel<LocatableTag> locatableLabel);
|
||||
|
||||
void attachLocationImpl(const swift::SourceManager& sourceManager,
|
||||
const swift::DiagnosticInfo* token,
|
||||
TrapLabel<LocatableTag> locatableLabel);
|
||||
|
||||
void attachLocationImpl(const swift::SourceManager& sourceManager,
|
||||
const swift::KeyPathExpr::Component* component,
|
||||
TrapLabel<LocatableTag> locatableLabel);
|
||||
|
||||
private:
|
||||
TrapLabel<FileTag> fetchFileLabel(const std::filesystem::path& file);
|
||||
@@ -85,4 +107,12 @@ class SwiftLocationExtractor {
|
||||
std::unordered_map<std::filesystem::path, TrapLabel<FileTag>> store;
|
||||
};
|
||||
|
||||
template <typename Locatable>
|
||||
struct SwiftLocationExtractor::HasSpecializedImplementation<
|
||||
Locatable,
|
||||
decltype(std::declval<SwiftLocationExtractor>().attachLocationImpl(
|
||||
std::declval<const swift::SourceManager&>(),
|
||||
std::declval<const Locatable*>(),
|
||||
std::declval<TrapLabel<LocatableTag>>()))> : std::true_type {};
|
||||
|
||||
} // namespace codeql
|
||||
|
||||
30
swift/extractor/infra/SwiftMangledName.cpp
Normal file
30
swift/extractor/infra/SwiftMangledName.cpp
Normal file
@@ -0,0 +1,30 @@
|
||||
#include "swift/extractor/infra/SwiftMangledName.h"
|
||||
|
||||
namespace codeql {
|
||||
|
||||
namespace {
|
||||
void appendPart(std::string& out, const std::string& prefix) {
|
||||
out += prefix;
|
||||
}
|
||||
|
||||
void appendPart(std::string& out, UntypedTrapLabel label) {
|
||||
out += '{';
|
||||
out += label.str();
|
||||
out += '}';
|
||||
}
|
||||
|
||||
void appendPart(std::string& out, unsigned index) {
|
||||
out += std::to_string(index);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
std::string SwiftMangledName::str() const {
|
||||
std::string out;
|
||||
for (const auto& part : parts) {
|
||||
std::visit([&](const auto& contents) { appendPart(out, contents); }, part);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
} // namespace codeql
|
||||
45
swift/extractor/infra/SwiftMangledName.h
Normal file
45
swift/extractor/infra/SwiftMangledName.h
Normal file
@@ -0,0 +1,45 @@
|
||||
#pragma once
|
||||
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <variant>
|
||||
#include <string>
|
||||
|
||||
#include "swift/extractor/trap/TrapLabel.h"
|
||||
|
||||
namespace codeql {
|
||||
|
||||
struct SwiftMangledName {
|
||||
using Part = std::variant<UntypedTrapLabel, std::string, unsigned>;
|
||||
|
||||
std::vector<Part> parts;
|
||||
|
||||
explicit operator bool() const { return !parts.empty(); }
|
||||
|
||||
std::string str() const;
|
||||
|
||||
// streaming labels or ints into a SwiftMangledName just appends them
|
||||
template <typename Tag>
|
||||
SwiftMangledName& operator<<(TrapLabel<Tag> label) {
|
||||
parts.emplace_back(label);
|
||||
return *this;
|
||||
}
|
||||
|
||||
SwiftMangledName& operator<<(unsigned i) {
|
||||
parts.emplace_back(i);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// streaming string-like stuff will add a new part it only if strictly required, otherwise it will
|
||||
// append to the last part if it is a string
|
||||
template <typename T>
|
||||
SwiftMangledName& operator<<(T&& arg) {
|
||||
if (parts.empty() || !std::holds_alternative<std::string>(parts.back())) {
|
||||
parts.emplace_back("");
|
||||
}
|
||||
std::get<std::string>(parts.back()) += std::forward<T>(arg);
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace codeql
|
||||
@@ -8,6 +8,7 @@ swift_cc_library(
|
||||
deps = [
|
||||
"//swift/extractor/config",
|
||||
"//swift/extractor/infra",
|
||||
"//swift/extractor/mangler",
|
||||
"//swift/extractor/remapping",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -15,11 +15,11 @@ void SwiftDiagnosticsConsumer::handleDiagnostic(swift::SourceManager& sourceMana
|
||||
const swift::DiagnosticInfo& diagInfo) {
|
||||
auto message = getDiagMessage(sourceManager, diagInfo);
|
||||
DiagnosticsTrap diag{};
|
||||
diag.id = trap.createLabel<DiagnosticsTag>();
|
||||
diag.id = trap.createTypedLabel<DiagnosticsTag>();
|
||||
diag.kind = translateDiagnosticsKind(diagInfo.Kind);
|
||||
diag.text = message;
|
||||
trap.emit(diag);
|
||||
locationExtractor.attachLocation(sourceManager, diagInfo.Loc, diagInfo.Loc, diag.id);
|
||||
locationExtractor.attachLocation(sourceManager, diagInfo, diag.id);
|
||||
}
|
||||
|
||||
std::string SwiftDiagnosticsConsumer::getDiagMessage(swift::SourceManager& sourceManager,
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#include "swift/extractor/trap/generated/TrapTags.h"
|
||||
#include "swift/extractor/infra/file/TargetFile.h"
|
||||
#include "swift/extractor/infra/file/Path.h"
|
||||
#include "swift/extractor/trap/LinkDomain.h"
|
||||
#include "swift/extractor/mangler/SwiftMangler.h"
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
using namespace std::string_literals;
|
||||
@@ -65,7 +65,8 @@ std::vector<ModuleInfo> emitModuleImplementations(SwiftExtractorState& state,
|
||||
if (auto hash = getModuleHash(modulePath)) {
|
||||
auto target = getModuleTarget(moduleName, *hash);
|
||||
if (auto moduleTrap = createTargetTrapDomain(state, target, TrapType::linkage)) {
|
||||
moduleTrap->createLabelWithImplementationId<ModuleDeclTag>(*hash, moduleName);
|
||||
moduleTrap->createTypedLabelWithImplementationId<ModuleDeclTag>(
|
||||
SwiftMangler::mangleModuleName(moduleName), *hash);
|
||||
ret.push_back({target, getModuleId(moduleName, *hash)});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ swift_cc_library(
|
||||
hdrs = glob(["*.h"]),
|
||||
visibility = ["//swift:__subpackages__"],
|
||||
deps = [
|
||||
"//swift/extractor/infra",
|
||||
"//swift/extractor/trap",
|
||||
"//swift/third_party/swift-llvm-support",
|
||||
],
|
||||
|
||||
@@ -1,21 +1,62 @@
|
||||
#include "swift/extractor/mangler/SwiftMangler.h"
|
||||
#include "swift/extractor/infra/SwiftDispatcher.h"
|
||||
#include "swift/extractor/trap/generated/decl/TrapClasses.h"
|
||||
#include <swift/AST/Module.h>
|
||||
#include <sstream>
|
||||
|
||||
using namespace codeql;
|
||||
|
||||
std::string SwiftMangler::mangledName(const swift::Decl& decl) {
|
||||
assert(llvm::isa<swift::ValueDecl>(decl));
|
||||
auto& valueDecl = llvm::cast<swift::ValueDecl>(decl);
|
||||
std::string_view moduleName = decl.getModuleContext()->getRealName().str();
|
||||
// ASTMangler::mangleAnyDecl crashes when called on `ModuleDecl`
|
||||
if (decl.getKind() == swift::DeclKind::Module) {
|
||||
return std::string{moduleName};
|
||||
namespace {
|
||||
SwiftMangledName initMangled(const swift::TypeBase* type) {
|
||||
switch (type->getKind()) {
|
||||
#define TYPE(ID, PARENT) \
|
||||
case swift::TypeKind::ID: \
|
||||
return {{#ID "Type_"}};
|
||||
#include <swift/AST/TypeNodes.def>
|
||||
default:
|
||||
return {};
|
||||
}
|
||||
std::ostringstream ret;
|
||||
}
|
||||
|
||||
SwiftMangledName initMangled(const swift::Decl* decl) {
|
||||
SwiftMangledName ret;
|
||||
ret << swift::Decl::getKindName(decl->getKind()) << "Decl_";
|
||||
return ret;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
SwiftMangledName SwiftMangler::mangleModuleName(std::string_view name) {
|
||||
SwiftMangledName ret = {{"ModuleDecl_"}};
|
||||
ret << name;
|
||||
return ret;
|
||||
}
|
||||
|
||||
SwiftMangledName SwiftMangler::mangleDecl(const swift::Decl& decl) {
|
||||
if (!llvm::isa<swift::ValueDecl>(decl)) {
|
||||
return {};
|
||||
}
|
||||
// We do not deduplicate local variables, but for the moment also non-local vars from non-swift
|
||||
// (PCM, clang modules) modules as the mangler crashes sometimes
|
||||
if (decl.getKind() == swift::DeclKind::Var &&
|
||||
(decl.getDeclContext()->isLocalContext() || decl.getModuleContext()->isNonSwiftModule())) {
|
||||
return {};
|
||||
}
|
||||
|
||||
// we do not deduplicate GenericTypeParamDecl, as their mangling is ambiguous in the presence of
|
||||
// extensions
|
||||
if (decl.getKind() == swift::DeclKind::GenericTypeParam) {
|
||||
return {};
|
||||
}
|
||||
|
||||
if (decl.getKind() == swift::DeclKind::Module) {
|
||||
return mangleModuleName(llvm::cast<swift::ModuleDecl>(decl).getRealName().str());
|
||||
}
|
||||
|
||||
auto ret = initMangled(&decl);
|
||||
const auto& valueDecl = llvm::cast<swift::ValueDecl>(decl);
|
||||
// stamp all declarations with an id-ref of the containing module
|
||||
ret << '{' << ModuleDeclTag::prefix << '_' << moduleName << '}';
|
||||
auto moduleLabel = dispatcher.fetchLabel(decl.getModuleContext());
|
||||
ret << moduleLabel;
|
||||
if (decl.getKind() == swift::DeclKind::TypeAlias) {
|
||||
// In cases like this (when coming from PCM)
|
||||
// typealias CFXMLTree = CFTree
|
||||
@@ -28,22 +69,21 @@ std::string SwiftMangler::mangledName(const swift::Decl& decl) {
|
||||
// prefix adds a couple of special symbols, we don't necessary need them
|
||||
ret << mangler.mangleAnyDecl(&valueDecl, /* prefix = */ false);
|
||||
}
|
||||
return ret.str();
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::optional<std::string> SwiftMangler::mangleType(const swift::ModuleType& type) {
|
||||
auto key = type.getModule()->getRealName().str().str();
|
||||
if (type.getModule()->isNonSwiftModule()) {
|
||||
key += "|clang";
|
||||
SwiftMangledName SwiftMangler::visitModuleType(const swift::ModuleType* type) {
|
||||
auto ret = initMangled(type);
|
||||
ret << type->getModule()->getRealName().str();
|
||||
if (type->getModule()->isNonSwiftModule()) {
|
||||
ret << "|clang";
|
||||
}
|
||||
return key;
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define TYPE(TYPE_ID, PARENT_TYPE)
|
||||
#define BUILTIN_TYPE(TYPE_ID, PARENT_TYPE) \
|
||||
std::optional<std::string> SwiftMangler::mangleType(const swift::TYPE_ID##Type& type) { \
|
||||
llvm::SmallString<32> buffer; \
|
||||
type.getTypeName(buffer); \
|
||||
return buffer.str().str(); \
|
||||
}
|
||||
#include <swift/AST/TypeNodes.def>
|
||||
SwiftMangledName SwiftMangler::visitBuiltinType(const swift::BuiltinType* type) {
|
||||
auto ret = initMangled(type);
|
||||
llvm::SmallString<32> buffer;
|
||||
ret << type->getTypeName(buffer, /* prependBuiltinNamespace= */ false);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -2,28 +2,48 @@
|
||||
|
||||
#include <swift/AST/ASTMangler.h>
|
||||
#include <swift/AST/Types.h>
|
||||
#include <swift/AST/ASTVisitor.h>
|
||||
#include <swift/AST/TypeVisitor.h>
|
||||
|
||||
#include <variant>
|
||||
|
||||
#include "swift/extractor/trap/TrapLabel.h"
|
||||
#include "swift/extractor/infra/SwiftMangledName.h"
|
||||
|
||||
#include <optional>
|
||||
|
||||
namespace codeql {
|
||||
class SwiftMangler {
|
||||
public:
|
||||
std::string mangledName(const swift::Decl& decl);
|
||||
|
||||
template <typename T>
|
||||
std::optional<std::string> mangleType(const T& type) {
|
||||
return std::nullopt;
|
||||
class SwiftDispatcher;
|
||||
|
||||
class SwiftMangler : private swift::TypeVisitor<SwiftMangler, SwiftMangledName> {
|
||||
public:
|
||||
explicit SwiftMangler(SwiftDispatcher& dispatcher) : dispatcher(dispatcher) {}
|
||||
|
||||
static SwiftMangledName mangleModuleName(std::string_view name);
|
||||
|
||||
// TODO actual visit
|
||||
SwiftMangledName mangleDecl(const swift::Decl& decl);
|
||||
|
||||
SwiftMangledName mangleType(const swift::TypeBase& type) {
|
||||
return visit(const_cast<swift::TypeBase*>(&type));
|
||||
}
|
||||
|
||||
std::optional<std::string> mangleType(const swift::ModuleType& type);
|
||||
private:
|
||||
friend class swift::TypeVisitor<SwiftMangler, SwiftMangledName>;
|
||||
|
||||
#define TYPE(TYPE_ID, PARENT_TYPE)
|
||||
#define BUILTIN_TYPE(TYPE_ID, PARENT_TYPE) \
|
||||
std::optional<std::string> mangleType(const swift::TYPE_ID##Type& type);
|
||||
#include <swift/AST/TypeNodes.def>
|
||||
// default fallback for not yet mangled types. This should never be called in normal situations
|
||||
// will just spawn a random name
|
||||
// TODO: make it assert once we mangle all types
|
||||
static SwiftMangledName visitType(const swift::TypeBase* type) { return {}; }
|
||||
|
||||
SwiftMangledName visitModuleType(const swift::ModuleType* type);
|
||||
|
||||
SwiftMangledName visitBuiltinType(const swift::BuiltinType* type);
|
||||
|
||||
private:
|
||||
swift::Mangle::ASTMangler mangler;
|
||||
SwiftDispatcher& dispatcher;
|
||||
};
|
||||
|
||||
} // namespace codeql
|
||||
|
||||
@@ -24,31 +24,23 @@ std::string constructName(const swift::DeclName& declName) {
|
||||
}
|
||||
} // namespace
|
||||
|
||||
std::optional<codeql::ConcreteFuncDecl> DeclTranslator::translateFuncDecl(
|
||||
const swift::FuncDecl& decl) {
|
||||
if (auto entry = createNamedEntry(decl)) {
|
||||
fillAbstractFunctionDecl(decl, *entry);
|
||||
return entry;
|
||||
}
|
||||
return std::nullopt;
|
||||
codeql::ConcreteFuncDecl DeclTranslator::translateFuncDecl(const swift::FuncDecl& decl) {
|
||||
auto entry = createEntry(decl);
|
||||
fillAbstractFunctionDecl(decl, entry);
|
||||
return entry;
|
||||
}
|
||||
|
||||
std::optional<codeql::ConstructorDecl> DeclTranslator::translateConstructorDecl(
|
||||
codeql::ConstructorDecl DeclTranslator::translateConstructorDecl(
|
||||
const swift::ConstructorDecl& decl) {
|
||||
if (auto entry = createNamedEntry(decl)) {
|
||||
fillAbstractFunctionDecl(decl, *entry);
|
||||
return entry;
|
||||
}
|
||||
return std::nullopt;
|
||||
auto entry = createEntry(decl);
|
||||
fillAbstractFunctionDecl(decl, entry);
|
||||
return entry;
|
||||
}
|
||||
|
||||
std::optional<codeql::DestructorDecl> DeclTranslator::translateDestructorDecl(
|
||||
const swift::DestructorDecl& decl) {
|
||||
if (auto entry = createNamedEntry(decl)) {
|
||||
fillAbstractFunctionDecl(decl, *entry);
|
||||
return entry;
|
||||
}
|
||||
return std::nullopt;
|
||||
codeql::DestructorDecl DeclTranslator::translateDestructorDecl(const swift::DestructorDecl& decl) {
|
||||
auto entry = createEntry(decl);
|
||||
fillAbstractFunctionDecl(decl, entry);
|
||||
return entry;
|
||||
}
|
||||
|
||||
codeql::PrefixOperatorDecl DeclTranslator::translatePrefixOperatorDecl(
|
||||
@@ -79,16 +71,13 @@ codeql::PrecedenceGroupDecl DeclTranslator::translatePrecedenceGroupDecl(
|
||||
return entry;
|
||||
}
|
||||
|
||||
std::optional<codeql::ParamDecl> DeclTranslator::translateParamDecl(const swift::ParamDecl& decl) {
|
||||
auto entry = createNamedEntry(decl);
|
||||
if (!entry) {
|
||||
return std::nullopt;
|
||||
}
|
||||
fillVarDecl(decl, *entry);
|
||||
entry->is_inout = decl.isInOut();
|
||||
codeql::ParamDecl DeclTranslator::translateParamDecl(const swift::ParamDecl& decl) {
|
||||
auto entry = createEntry(decl);
|
||||
fillVarDecl(decl, entry);
|
||||
entry.is_inout = decl.isInOut();
|
||||
if (auto wrapped = decl.getPropertyWrapperWrappedValueVar()) {
|
||||
entry->property_wrapper_local_wrapped_var = dispatcher.fetchLabel(wrapped);
|
||||
entry->property_wrapper_local_wrapped_var_binding =
|
||||
entry.property_wrapper_local_wrapped_var = dispatcher.fetchLabel(wrapped);
|
||||
entry.property_wrapper_local_wrapped_var_binding =
|
||||
dispatcher.fetchLabel(wrapped->getParentPatternBinding());
|
||||
}
|
||||
return entry;
|
||||
@@ -114,56 +103,35 @@ codeql::PatternBindingDecl DeclTranslator::translatePatternBindingDecl(
|
||||
return entry;
|
||||
}
|
||||
|
||||
std::optional<codeql::ConcreteVarDecl> DeclTranslator::translateVarDecl(
|
||||
const swift::VarDecl& decl) {
|
||||
std::optional<codeql::ConcreteVarDecl> entry;
|
||||
// We do not deduplicate variables from non-swift (PCM, clang modules) modules as the mangler
|
||||
// crashes sometimes
|
||||
if (decl.getDeclContext()->isLocalContext() || decl.getModuleContext()->isNonSwiftModule()) {
|
||||
entry = createEntry(decl);
|
||||
} else {
|
||||
entry = createNamedEntry(decl);
|
||||
if (!entry) {
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
entry->introducer_int = static_cast<uint8_t>(decl.getIntroducer());
|
||||
fillVarDecl(decl, *entry);
|
||||
codeql::ConcreteVarDecl DeclTranslator::translateVarDecl(const swift::VarDecl& decl) {
|
||||
auto entry = createEntry(decl);
|
||||
entry.introducer_int = static_cast<uint8_t>(decl.getIntroducer());
|
||||
fillVarDecl(decl, entry);
|
||||
return entry;
|
||||
}
|
||||
|
||||
std::optional<codeql::StructDecl> DeclTranslator::translateStructDecl(
|
||||
const swift::StructDecl& decl) {
|
||||
if (auto entry = createNamedEntry(decl)) {
|
||||
fillNominalTypeDecl(decl, *entry);
|
||||
return entry;
|
||||
}
|
||||
return std::nullopt;
|
||||
codeql::StructDecl DeclTranslator::translateStructDecl(const swift::StructDecl& decl) {
|
||||
auto entry = createEntry(decl);
|
||||
fillNominalTypeDecl(decl, entry);
|
||||
return entry;
|
||||
}
|
||||
|
||||
std::optional<codeql::ClassDecl> DeclTranslator::translateClassDecl(const swift::ClassDecl& decl) {
|
||||
if (auto entry = createNamedEntry(decl)) {
|
||||
fillNominalTypeDecl(decl, *entry);
|
||||
return entry;
|
||||
}
|
||||
return std::nullopt;
|
||||
codeql::ClassDecl DeclTranslator::translateClassDecl(const swift::ClassDecl& decl) {
|
||||
auto entry = createEntry(decl);
|
||||
fillNominalTypeDecl(decl, entry);
|
||||
return entry;
|
||||
}
|
||||
|
||||
std::optional<codeql::EnumDecl> DeclTranslator::translateEnumDecl(const swift::EnumDecl& decl) {
|
||||
if (auto entry = createNamedEntry(decl)) {
|
||||
fillNominalTypeDecl(decl, *entry);
|
||||
return entry;
|
||||
}
|
||||
return std::nullopt;
|
||||
codeql::EnumDecl DeclTranslator::translateEnumDecl(const swift::EnumDecl& decl) {
|
||||
auto entry = createEntry(decl);
|
||||
fillNominalTypeDecl(decl, entry);
|
||||
return entry;
|
||||
}
|
||||
|
||||
std::optional<codeql::ProtocolDecl> DeclTranslator::translateProtocolDecl(
|
||||
const swift::ProtocolDecl& decl) {
|
||||
if (auto entry = createNamedEntry(decl)) {
|
||||
fillNominalTypeDecl(decl, *entry);
|
||||
return entry;
|
||||
}
|
||||
return std::nullopt;
|
||||
codeql::ProtocolDecl DeclTranslator::translateProtocolDecl(const swift::ProtocolDecl& decl) {
|
||||
auto entry = createEntry(decl);
|
||||
fillNominalTypeDecl(decl, entry);
|
||||
return entry;
|
||||
}
|
||||
|
||||
codeql::EnumCaseDecl DeclTranslator::translateEnumCaseDecl(const swift::EnumCaseDecl& decl) {
|
||||
@@ -172,17 +140,14 @@ codeql::EnumCaseDecl DeclTranslator::translateEnumCaseDecl(const swift::EnumCase
|
||||
return entry;
|
||||
}
|
||||
|
||||
std::optional<codeql::EnumElementDecl> DeclTranslator::translateEnumElementDecl(
|
||||
codeql::EnumElementDecl DeclTranslator::translateEnumElementDecl(
|
||||
const swift::EnumElementDecl& decl) {
|
||||
auto entry = createNamedEntry(decl);
|
||||
if (!entry) {
|
||||
return std::nullopt;
|
||||
}
|
||||
entry->name = decl.getNameStr().str();
|
||||
auto entry = createEntry(decl);
|
||||
entry.name = decl.getNameStr().str();
|
||||
if (decl.hasParameterList()) {
|
||||
entry->params = dispatcher.fetchRepeatedLabels(*decl.getParameterList());
|
||||
entry.params = dispatcher.fetchRepeatedLabels(*decl.getParameterList());
|
||||
}
|
||||
fillValueDecl(decl, *entry);
|
||||
fillValueDecl(decl, entry);
|
||||
return entry;
|
||||
}
|
||||
|
||||
@@ -194,72 +159,59 @@ codeql::GenericTypeParamDecl DeclTranslator::translateGenericTypeParamDecl(
|
||||
return entry;
|
||||
}
|
||||
|
||||
std::optional<codeql::AssociatedTypeDecl> DeclTranslator::translateAssociatedTypeDecl(
|
||||
codeql::AssociatedTypeDecl DeclTranslator::translateAssociatedTypeDecl(
|
||||
const swift::AssociatedTypeDecl& decl) {
|
||||
if (auto entry = createNamedEntry(decl)) {
|
||||
fillTypeDecl(decl, *entry);
|
||||
return entry;
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<codeql::TypeAliasDecl> DeclTranslator::translateTypeAliasDecl(
|
||||
const swift::TypeAliasDecl& decl) {
|
||||
if (auto entry = createNamedEntry(decl)) {
|
||||
entry->aliased_type = dispatcher.fetchLabel(decl.getUnderlyingType());
|
||||
fillTypeDecl(decl, *entry);
|
||||
return entry;
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<codeql::AccessorDecl> DeclTranslator::translateAccessorDecl(
|
||||
const swift::AccessorDecl& decl) {
|
||||
auto entry = createNamedEntry(decl);
|
||||
if (!entry) {
|
||||
return std::nullopt;
|
||||
}
|
||||
switch (decl.getAccessorKind()) {
|
||||
case swift::AccessorKind::Get:
|
||||
entry->is_getter = true;
|
||||
break;
|
||||
case swift::AccessorKind::Set:
|
||||
entry->is_setter = true;
|
||||
break;
|
||||
case swift::AccessorKind::WillSet:
|
||||
entry->is_will_set = true;
|
||||
break;
|
||||
case swift::AccessorKind::DidSet:
|
||||
entry->is_did_set = true;
|
||||
break;
|
||||
case swift::AccessorKind::Read:
|
||||
entry->is_read = true;
|
||||
break;
|
||||
case swift::AccessorKind::Modify:
|
||||
entry->is_modify = true;
|
||||
break;
|
||||
case swift::AccessorKind::Address:
|
||||
entry->is_unsafe_address = true;
|
||||
break;
|
||||
case swift::AccessorKind::MutableAddress:
|
||||
entry->is_unsafe_mutable_address = true;
|
||||
break;
|
||||
}
|
||||
fillAbstractFunctionDecl(decl, *entry);
|
||||
auto entry = createEntry(decl);
|
||||
fillTypeDecl(decl, entry);
|
||||
return entry;
|
||||
}
|
||||
|
||||
std::optional<codeql::SubscriptDecl> DeclTranslator::translateSubscriptDecl(
|
||||
const swift::SubscriptDecl& decl) {
|
||||
auto entry = createNamedEntry(decl);
|
||||
if (!entry) {
|
||||
return std::nullopt;
|
||||
codeql::TypeAliasDecl DeclTranslator::translateTypeAliasDecl(const swift::TypeAliasDecl& decl) {
|
||||
auto entry = createEntry(decl);
|
||||
entry.aliased_type = dispatcher.fetchLabel(decl.getUnderlyingType());
|
||||
fillTypeDecl(decl, entry);
|
||||
return entry;
|
||||
}
|
||||
|
||||
codeql::AccessorDecl DeclTranslator::translateAccessorDecl(const swift::AccessorDecl& decl) {
|
||||
auto entry = createEntry(decl);
|
||||
switch (decl.getAccessorKind()) {
|
||||
case swift::AccessorKind::Get:
|
||||
entry.is_getter = true;
|
||||
break;
|
||||
case swift::AccessorKind::Set:
|
||||
entry.is_setter = true;
|
||||
break;
|
||||
case swift::AccessorKind::WillSet:
|
||||
entry.is_will_set = true;
|
||||
break;
|
||||
case swift::AccessorKind::DidSet:
|
||||
entry.is_did_set = true;
|
||||
break;
|
||||
case swift::AccessorKind::Read:
|
||||
entry.is_read = true;
|
||||
break;
|
||||
case swift::AccessorKind::Modify:
|
||||
entry.is_modify = true;
|
||||
break;
|
||||
case swift::AccessorKind::Address:
|
||||
entry.is_unsafe_address = true;
|
||||
break;
|
||||
case swift::AccessorKind::MutableAddress:
|
||||
entry.is_unsafe_mutable_address = true;
|
||||
break;
|
||||
}
|
||||
entry->element_type = dispatcher.fetchLabel(decl.getElementInterfaceType());
|
||||
fillAbstractFunctionDecl(decl, entry);
|
||||
return entry;
|
||||
}
|
||||
|
||||
codeql::SubscriptDecl DeclTranslator::translateSubscriptDecl(const swift::SubscriptDecl& decl) {
|
||||
auto entry = createEntry(decl);
|
||||
entry.element_type = dispatcher.fetchLabel(decl.getElementInterfaceType());
|
||||
if (auto indices = decl.getIndices()) {
|
||||
entry->params = dispatcher.fetchRepeatedLabels(*indices);
|
||||
entry.params = dispatcher.fetchRepeatedLabels(*indices);
|
||||
}
|
||||
fillAbstractStorageDecl(decl, *entry);
|
||||
fillAbstractStorageDecl(decl, entry);
|
||||
return entry;
|
||||
}
|
||||
|
||||
@@ -280,33 +232,25 @@ codeql::ImportDecl DeclTranslator::translateImportDecl(const swift::ImportDecl&
|
||||
return entry;
|
||||
}
|
||||
|
||||
std::optional<codeql::ModuleDecl> DeclTranslator::translateModuleDecl(
|
||||
const swift::ModuleDecl& decl) {
|
||||
auto entry = createNamedEntry(decl);
|
||||
if (!entry) {
|
||||
return std::nullopt;
|
||||
}
|
||||
entry->is_builtin_module = decl.isBuiltinModule();
|
||||
entry->is_system_module = decl.isSystemModule();
|
||||
codeql::ModuleDecl DeclTranslator::translateModuleDecl(const swift::ModuleDecl& decl) {
|
||||
auto entry = createEntry(decl);
|
||||
entry.is_builtin_module = decl.isBuiltinModule();
|
||||
entry.is_system_module = decl.isSystemModule();
|
||||
using K = swift::ModuleDecl::ImportFilterKind;
|
||||
llvm::SmallVector<swift::ImportedModule> imports;
|
||||
decl.getImportedModules(imports, K::Default);
|
||||
for (const auto& import : imports) {
|
||||
entry->imported_modules.push_back(dispatcher.fetchLabel(import.importedModule));
|
||||
entry.imported_modules.push_back(dispatcher.fetchLabel(import.importedModule));
|
||||
}
|
||||
imports.clear();
|
||||
decl.getImportedModules(imports, K::Exported);
|
||||
for (const auto& import : imports) {
|
||||
entry->exported_modules.push_back(dispatcher.fetchLabel(import.importedModule));
|
||||
entry.exported_modules.push_back(dispatcher.fetchLabel(import.importedModule));
|
||||
}
|
||||
fillTypeDecl(decl, *entry);
|
||||
fillTypeDecl(decl, entry);
|
||||
return entry;
|
||||
}
|
||||
|
||||
std::string DeclTranslator::mangledName(const swift::ValueDecl& decl) {
|
||||
return mangler.mangledName(decl);
|
||||
}
|
||||
|
||||
void DeclTranslator::fillAbstractFunctionDecl(const swift::AbstractFunctionDecl& decl,
|
||||
codeql::AbstractFunctionDecl& entry) {
|
||||
assert(decl.hasParameterList() && "Expect functions to have a parameter list");
|
||||
@@ -396,15 +340,12 @@ codeql::IfConfigDecl DeclTranslator::translateIfConfigDecl(const swift::IfConfig
|
||||
return entry;
|
||||
}
|
||||
|
||||
std::optional<codeql::OpaqueTypeDecl> DeclTranslator::translateOpaqueTypeDecl(
|
||||
const swift::OpaqueTypeDecl& decl) {
|
||||
if (auto entry = createNamedEntry(decl)) {
|
||||
fillTypeDecl(decl, *entry);
|
||||
entry->naming_declaration = dispatcher.fetchLabel(decl.getNamingDecl());
|
||||
entry->opaque_generic_params = dispatcher.fetchRepeatedLabels(decl.getOpaqueGenericParams());
|
||||
return entry;
|
||||
}
|
||||
return std::nullopt;
|
||||
codeql::OpaqueTypeDecl DeclTranslator::translateOpaqueTypeDecl(const swift::OpaqueTypeDecl& decl) {
|
||||
auto entry = createEntry(decl);
|
||||
fillTypeDecl(decl, entry);
|
||||
entry.naming_declaration = dispatcher.fetchLabel(decl.getNamingDecl());
|
||||
entry.opaque_generic_params = dispatcher.fetchRepeatedLabels(decl.getOpaqueGenericParams());
|
||||
return entry;
|
||||
}
|
||||
|
||||
codeql::PoundDiagnosticDecl DeclTranslator::translatePoundDiagnosticDecl(
|
||||
@@ -423,7 +364,7 @@ codeql::MissingMemberDecl DeclTranslator::translateMissingMemberDecl(
|
||||
}
|
||||
|
||||
codeql::CapturedDecl DeclTranslator::translateCapturedValue(const swift::CapturedValue& capture) {
|
||||
codeql::CapturedDecl entry{dispatcher.template assignNewLabel(capture)};
|
||||
auto entry = dispatcher.createEntry(capture);
|
||||
auto decl = capture.getDecl();
|
||||
entry.decl = dispatcher.fetchLabel(decl);
|
||||
entry.module = dispatcher.fetchLabel(decl->getModuleContext());
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
|
||||
#include "swift/extractor/translators/TranslatorBase.h"
|
||||
#include "swift/extractor/trap/generated/decl/TrapClasses.h"
|
||||
#include "swift/extractor/mangler/SwiftMangler.h"
|
||||
|
||||
namespace codeql {
|
||||
|
||||
@@ -17,43 +16,39 @@ class DeclTranslator : public AstTranslatorBase<DeclTranslator> {
|
||||
public:
|
||||
using AstTranslatorBase<DeclTranslator>::AstTranslatorBase;
|
||||
|
||||
std::optional<codeql::ConcreteFuncDecl> translateFuncDecl(const swift::FuncDecl& decl);
|
||||
std::optional<codeql::ConstructorDecl> translateConstructorDecl(
|
||||
const swift::ConstructorDecl& decl);
|
||||
std::optional<codeql::DestructorDecl> translateDestructorDecl(const swift::DestructorDecl& decl);
|
||||
codeql::ConcreteFuncDecl translateFuncDecl(const swift::FuncDecl& decl);
|
||||
codeql::ConstructorDecl translateConstructorDecl(const swift::ConstructorDecl& decl);
|
||||
codeql::DestructorDecl translateDestructorDecl(const swift::DestructorDecl& decl);
|
||||
codeql::PrefixOperatorDecl translatePrefixOperatorDecl(const swift::PrefixOperatorDecl& decl);
|
||||
codeql::PostfixOperatorDecl translatePostfixOperatorDecl(const swift::PostfixOperatorDecl& decl);
|
||||
codeql::InfixOperatorDecl translateInfixOperatorDecl(const swift::InfixOperatorDecl& decl);
|
||||
codeql::PrecedenceGroupDecl translatePrecedenceGroupDecl(const swift::PrecedenceGroupDecl& decl);
|
||||
std::optional<codeql::ParamDecl> translateParamDecl(const swift::ParamDecl& decl);
|
||||
codeql::ParamDecl translateParamDecl(const swift::ParamDecl& decl);
|
||||
codeql::TopLevelCodeDecl translateTopLevelCodeDecl(const swift::TopLevelCodeDecl& decl);
|
||||
codeql::PatternBindingDecl translatePatternBindingDecl(const swift::PatternBindingDecl& decl);
|
||||
std::optional<codeql::ConcreteVarDecl> translateVarDecl(const swift::VarDecl& decl);
|
||||
std::optional<codeql::StructDecl> translateStructDecl(const swift::StructDecl& decl);
|
||||
std::optional<codeql::ClassDecl> translateClassDecl(const swift::ClassDecl& decl);
|
||||
std::optional<codeql::EnumDecl> translateEnumDecl(const swift::EnumDecl& decl);
|
||||
std::optional<codeql::ProtocolDecl> translateProtocolDecl(const swift::ProtocolDecl& decl);
|
||||
codeql::ConcreteVarDecl translateVarDecl(const swift::VarDecl& decl);
|
||||
codeql::StructDecl translateStructDecl(const swift::StructDecl& decl);
|
||||
codeql::ClassDecl translateClassDecl(const swift::ClassDecl& decl);
|
||||
codeql::EnumDecl translateEnumDecl(const swift::EnumDecl& decl);
|
||||
codeql::ProtocolDecl translateProtocolDecl(const swift::ProtocolDecl& decl);
|
||||
codeql::EnumCaseDecl translateEnumCaseDecl(const swift::EnumCaseDecl& decl);
|
||||
std::optional<codeql::EnumElementDecl> translateEnumElementDecl(
|
||||
const swift::EnumElementDecl& decl);
|
||||
codeql::EnumElementDecl translateEnumElementDecl(const swift::EnumElementDecl& decl);
|
||||
codeql::GenericTypeParamDecl translateGenericTypeParamDecl(
|
||||
const swift::GenericTypeParamDecl& decl);
|
||||
std::optional<codeql::AssociatedTypeDecl> translateAssociatedTypeDecl(
|
||||
const swift::AssociatedTypeDecl& decl);
|
||||
std::optional<codeql::TypeAliasDecl> translateTypeAliasDecl(const swift::TypeAliasDecl& decl);
|
||||
std::optional<codeql::AccessorDecl> translateAccessorDecl(const swift::AccessorDecl& decl);
|
||||
std::optional<codeql::SubscriptDecl> translateSubscriptDecl(const swift::SubscriptDecl& decl);
|
||||
codeql::AssociatedTypeDecl translateAssociatedTypeDecl(const swift::AssociatedTypeDecl& decl);
|
||||
codeql::TypeAliasDecl translateTypeAliasDecl(const swift::TypeAliasDecl& decl);
|
||||
codeql::AccessorDecl translateAccessorDecl(const swift::AccessorDecl& decl);
|
||||
codeql::SubscriptDecl translateSubscriptDecl(const swift::SubscriptDecl& decl);
|
||||
codeql::ExtensionDecl translateExtensionDecl(const swift::ExtensionDecl& decl);
|
||||
codeql::ImportDecl translateImportDecl(const swift::ImportDecl& decl);
|
||||
std::optional<codeql::ModuleDecl> translateModuleDecl(const swift::ModuleDecl& decl);
|
||||
codeql::ModuleDecl translateModuleDecl(const swift::ModuleDecl& decl);
|
||||
codeql::IfConfigDecl translateIfConfigDecl(const swift::IfConfigDecl& decl);
|
||||
std::optional<codeql::OpaqueTypeDecl> translateOpaqueTypeDecl(const swift::OpaqueTypeDecl& decl);
|
||||
codeql::OpaqueTypeDecl translateOpaqueTypeDecl(const swift::OpaqueTypeDecl& decl);
|
||||
codeql::PoundDiagnosticDecl translatePoundDiagnosticDecl(const swift::PoundDiagnosticDecl& decl);
|
||||
codeql::MissingMemberDecl translateMissingMemberDecl(const swift::MissingMemberDecl& decl);
|
||||
codeql::CapturedDecl translateCapturedValue(const swift::CapturedValue& capture);
|
||||
|
||||
private:
|
||||
std::string mangledName(const swift::ValueDecl& decl);
|
||||
void fillAbstractFunctionDecl(const swift::AbstractFunctionDecl& decl,
|
||||
codeql::AbstractFunctionDecl& entry);
|
||||
void fillOperatorDecl(const swift::OperatorDecl& decl, codeql::OperatorDecl& entry);
|
||||
@@ -66,23 +61,9 @@ class DeclTranslator : public AstTranslatorBase<DeclTranslator> {
|
||||
void fillAbstractStorageDecl(const swift::AbstractStorageDecl& decl,
|
||||
codeql::AbstractStorageDecl& entry);
|
||||
|
||||
template <typename D>
|
||||
auto createNamedEntry(const D& decl) {
|
||||
std::optional<TrapClassOf<D>> entry;
|
||||
auto id = dispatcher.assignNewLabel(decl, mangledName(decl));
|
||||
if (dispatcher.shouldEmitDeclBody(decl)) {
|
||||
dispatcher.extractedDeclaration(decl);
|
||||
entry.emplace(id);
|
||||
fillDecl(decl, *entry);
|
||||
} else {
|
||||
dispatcher.skippedDeclaration(decl);
|
||||
}
|
||||
return entry;
|
||||
}
|
||||
|
||||
template <typename D>
|
||||
auto createEntry(const D& decl) {
|
||||
TrapClassOf<D> entry{dispatcher.template assignNewLabel(decl)};
|
||||
auto entry = dispatcher.createEntry(decl);
|
||||
fillDecl(decl, entry);
|
||||
return entry;
|
||||
}
|
||||
@@ -90,8 +71,6 @@ class DeclTranslator : public AstTranslatorBase<DeclTranslator> {
|
||||
void fillDecl(const swift::Decl& decl, codeql::Decl& entry) {
|
||||
entry.module = dispatcher.fetchLabel(decl.getModuleContext());
|
||||
}
|
||||
|
||||
SwiftMangler mangler;
|
||||
};
|
||||
|
||||
} // namespace codeql
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include "swift/extractor/translators/StmtTranslator.h"
|
||||
#include "swift/extractor/translators/TypeTranslator.h"
|
||||
#include "swift/extractor/translators/PatternTranslator.h"
|
||||
#include "swift/extractor/mangler/SwiftMangler.h"
|
||||
|
||||
namespace codeql {
|
||||
|
||||
@@ -17,10 +18,13 @@ class SwiftVisitor : private SwiftDispatcher {
|
||||
template <typename T>
|
||||
void extract(const T& entity) {
|
||||
fetchLabel(entity);
|
||||
visitPending();
|
||||
}
|
||||
void extract(swift::Token& comment) { emitComment(comment); }
|
||||
|
||||
private:
|
||||
SwiftMangledName name(const swift::Decl* decl) override { return mangler.mangleDecl(*decl); }
|
||||
SwiftMangledName name(const swift::TypeBase* type) override { return mangler.mangleType(*type); }
|
||||
void visit(const swift::Decl* decl) override { declTranslator.translateAndEmit(*decl); }
|
||||
void visit(const swift::Stmt* stmt) override { stmtTranslator.translateAndEmit(*stmt); }
|
||||
void visit(const swift::StmtCondition* cond) override { stmtTranslator.translateAndEmit(*cond); }
|
||||
@@ -54,6 +58,7 @@ class SwiftVisitor : private SwiftDispatcher {
|
||||
StmtTranslator stmtTranslator{*this};
|
||||
TypeTranslator typeTranslator{*this};
|
||||
PatternTranslator patternTranslator{*this};
|
||||
SwiftMangler mangler{*this};
|
||||
};
|
||||
|
||||
} // namespace codeql
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
#include "swift/extractor/translators/TranslatorBase.h"
|
||||
#include "swift/extractor/trap/generated/type/TrapClasses.h"
|
||||
#include "swift/extractor/mangler/SwiftMangler.h"
|
||||
|
||||
namespace codeql {
|
||||
class TypeTranslator : public TypeTranslatorBase<TypeTranslator> {
|
||||
@@ -88,23 +87,12 @@ class TypeTranslator : public TypeTranslatorBase<TypeTranslator> {
|
||||
void fillBoundGenericType(const swift::BoundGenericType& type, codeql::BoundGenericType& entry);
|
||||
void fillAnyGenericType(const swift::AnyGenericType& type, codeql::AnyGenericType& entry);
|
||||
|
||||
template <typename T>
|
||||
auto createMangledTypeEntry(const T& type) {
|
||||
auto mangledName = mangler.mangleType(type);
|
||||
if (mangledName) {
|
||||
return dispatcher.createEntry(type, mangledName.value());
|
||||
}
|
||||
return dispatcher.createEntry(type);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
auto createTypeEntry(const T& type) {
|
||||
auto entry = createMangledTypeEntry(type);
|
||||
auto entry = dispatcher.createEntry(type);
|
||||
fillType(type, entry);
|
||||
return entry;
|
||||
}
|
||||
|
||||
SwiftMangler mangler;
|
||||
};
|
||||
|
||||
} // namespace codeql
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include "swift/extractor/trap/TrapLabel.h"
|
||||
#include "swift/extractor/infra/file/TargetFile.h"
|
||||
#include "swift/extractor/infra/log/SwiftLogging.h"
|
||||
#include "swift/extractor/infra/SwiftMangledName.h"
|
||||
|
||||
namespace codeql {
|
||||
|
||||
@@ -32,59 +33,56 @@ class TrapDomain {
|
||||
out << "\n*/\n";
|
||||
}
|
||||
|
||||
template <typename Tag>
|
||||
TrapLabel<Tag> createLabel() {
|
||||
auto ret = allocateLabel<Tag>();
|
||||
UntypedTrapLabel createLabel() {
|
||||
auto ret = allocateLabel();
|
||||
assignStar(ret);
|
||||
out << '\n';
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <typename Tag, typename... Args>
|
||||
TrapLabel<Tag> createLabel(Args&&... args) {
|
||||
auto ret = allocateLabel<Tag>();
|
||||
assignKey(ret, std::forward<Args>(args)...);
|
||||
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, typename... Args>
|
||||
TrapLabel<Tag> createLabelWithImplementationId(const std::string_view& implementationId,
|
||||
Args&&... args) {
|
||||
auto ret = allocateLabel<Tag>();
|
||||
assignKey(ret, std::forward<Args>(args)...);
|
||||
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 ret;
|
||||
return TrapLabel<Tag>::unsafeCreateFromUntyped(untyped);
|
||||
}
|
||||
|
||||
private:
|
||||
uint64_t id_{0};
|
||||
|
||||
template <typename Tag>
|
||||
TrapLabel<Tag> allocateLabel() {
|
||||
return TrapLabel<Tag>::unsafeCreateFromExplicitId(id_++);
|
||||
}
|
||||
UntypedTrapLabel allocateLabel() { return UntypedTrapLabel{id_++}; }
|
||||
|
||||
template <typename Tag>
|
||||
void assignStar(TrapLabel<Tag> label) {
|
||||
void assignStar(UntypedTrapLabel label) {
|
||||
LOG_TRACE("{}=*", 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;
|
||||
LOG_TRACE("{}=@{}", label, prefixed);
|
||||
out << label << "=@" << trapQuoted(prefixed);
|
||||
}
|
||||
|
||||
template <typename Tag, typename... Args>
|
||||
void assignKey(TrapLabel<Tag> label, const Args&... keyParts) {
|
||||
std::ostringstream oss;
|
||||
(oss << ... << keyParts);
|
||||
assignKey(label, oss.str());
|
||||
void assignKey(UntypedTrapLabel label, const SwiftMangledName& name) {
|
||||
auto key = name.str();
|
||||
LOG_TRACE("{}=@{}", label, key);
|
||||
out << label << "=@" << trapQuoted(key);
|
||||
}
|
||||
|
||||
std::string getLoggerName() {
|
||||
|
||||
@@ -26,11 +26,11 @@ class UntypedTrapLabel {
|
||||
|
||||
static constexpr uint64_t undefined = 0xffffffffffffffff;
|
||||
|
||||
protected:
|
||||
UntypedTrapLabel() : id_{undefined} {}
|
||||
UntypedTrapLabel(uint64_t id) : id_{id} { assert(id != undefined); }
|
||||
|
||||
public:
|
||||
UntypedTrapLabel() : id_{undefined} {}
|
||||
explicit UntypedTrapLabel(uint64_t id) : id_{id} { assert(id != undefined); }
|
||||
UntypedTrapLabel(UndefinedTrapLabel) : UntypedTrapLabel() {}
|
||||
|
||||
bool valid() const { return id_ != undefined; }
|
||||
explicit operator bool() const { return valid(); }
|
||||
|
||||
@@ -58,6 +58,8 @@ class UntypedTrapLabel {
|
||||
// Number of hex digits is ceil(bit_width(id) / 4), but C++ integer division can only do floor.
|
||||
return /* # */ 1 + /* hex digits */ 1 + (absl::bit_width(id_) - 1) / 4;
|
||||
}
|
||||
|
||||
friend bool operator!=(UntypedTrapLabel lhs, UntypedTrapLabel rhs) { return lhs.id_ != rhs.id_; }
|
||||
};
|
||||
|
||||
template <typename TagParam>
|
||||
@@ -79,8 +81,8 @@ class TrapLabel : public UntypedTrapLabel {
|
||||
}
|
||||
|
||||
// The caller is responsible for ensuring ID uniqueness.
|
||||
static TrapLabel unsafeCreateFromExplicitId(uint64_t id) { return {id}; }
|
||||
static TrapLabel unsafeCreateFromUntyped(UntypedTrapLabel label) { return {label.id_}; }
|
||||
static TrapLabel unsafeCreateFromExplicitId(uint64_t id) { return TrapLabel{id}; }
|
||||
static TrapLabel unsafeCreateFromUntyped(UntypedTrapLabel label) { return TrapLabel{label.id_}; }
|
||||
|
||||
template <typename SourceTag>
|
||||
TrapLabel(const TrapLabel<SourceTag>& other) : UntypedTrapLabel(other) {
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <variant>
|
||||
#include <cassert>
|
||||
#include <optional>
|
||||
#include <unordered_map>
|
||||
|
||||
#include <swift/AST/ASTVisitor.h>
|
||||
|
||||
#include "swift/extractor/trap/TrapLabel.h"
|
||||
#include "swift/extractor/trap/TrapTagTraits.h"
|
||||
#include "swift/extractor/trap/generated/TrapTags.h"
|
||||
|
||||
namespace codeql {
|
||||
|
||||
// The extraction is done in a lazy/on-demand fashion:
|
||||
// Each emitted TRAP entry for an AST node gets a TRAP label assigned to it.
|
||||
// To avoid re-emission, we store the "AST node <> label" entry in the TrapLabelStore.
|
||||
// The template parameters `Ts...` indicate to what entity types we restrict the storage
|
||||
template <typename... Ts>
|
||||
class TrapLabelStore {
|
||||
public:
|
||||
using Handle = std::variant<std::monostate, Ts...>;
|
||||
|
||||
template <typename T>
|
||||
std::optional<TrapLabelOf<T>> get(const T& e) {
|
||||
if (auto found = store_.find(e); found != store_.end()) {
|
||||
return TrapLabelOf<T>::unsafeCreateFromUntyped(found->second);
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void insert(const T& e, TrapLabelOf<T> l) {
|
||||
auto [_, inserted] = store_.emplace(e, l);
|
||||
assert(inserted && "already inserted");
|
||||
}
|
||||
|
||||
private:
|
||||
std::unordered_map<Handle, UntypedTrapLabel> store_;
|
||||
};
|
||||
|
||||
} // namespace codeql
|
||||
@@ -1,3 +1,5 @@
|
||||
| (Builtin.IntLiteral, Builtin.IntLiteral) | getName: | (Builtin.IntLiteral, Builtin.IntLiteral) | getCanonicalType: | (Builtin.IntLiteral, Builtin.IntLiteral) | getNumberOfTypes: | 2 |
|
||||
| (Builtin.IntLiteral, Builtin.IntLiteral) | getName: | (Builtin.IntLiteral, Builtin.IntLiteral) | getCanonicalType: | (Builtin.IntLiteral, Builtin.IntLiteral) | getNumberOfTypes: | 2 |
|
||||
| (Int, Int, Int, Int, Int) | getName: | (Int, Int, Int, Int, Int) | getCanonicalType: | (Int, Int, Int, Int, Int) | getNumberOfTypes: | 5 |
|
||||
| (Int, String, Double) | getName: | (Int, String, Double) | getCanonicalType: | (Int, String, Double) | getNumberOfTypes: | 3 |
|
||||
| (Int, s: String, Double) | getName: | (Int, s: String, Double) | getCanonicalType: | (Int, s: String, Double) | getNumberOfTypes: | 3 |
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
| (Builtin.IntLiteral, Builtin.IntLiteral) | 0 | Builtin.IntLiteral |
|
||||
| (Builtin.IntLiteral, Builtin.IntLiteral) | 0 | Builtin.IntLiteral |
|
||||
| (Builtin.IntLiteral, Builtin.IntLiteral) | 1 | Builtin.IntLiteral |
|
||||
| (Builtin.IntLiteral, Builtin.IntLiteral) | 1 | Builtin.IntLiteral |
|
||||
| (Int, Int, Int, Int, Int) | 0 | Int |
|
||||
| (Int, Int, Int, Int, Int) | 1 | Int |
|
||||
| (Int, Int, Int, Int, Int) | 2 | Int |
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
//codeql-extractor-options: -parse-stdlib
|
||||
func f(x : (Builtin.IntLiteral, Builtin.IntLiteral)) {}
|
||||
Reference in New Issue
Block a user