Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion swift/extractor/SwiftExtractor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ static std::unordered_set<swift::ModuleDecl*> extractDeclarations(
bodyEmissionStrategy);
auto topLevelDecls = getTopLevelDecls(module, primaryFile, lazyDeclaration);
for (auto decl : topLevelDecls) {
if (swift::AvailableAttr::isUnavailable(decl)) {
if (decl->isUnavailable() && !llvm::isa<swift::NominalTypeDecl>(decl)) {
continue;
}
visitor.extract(decl);
Expand Down
3 changes: 1 addition & 2 deletions swift/extractor/infra/SwiftBodyEmissionStrategy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@ using namespace codeql;
// same module one by one. In this mode, we restrict emission only to the same file ignoring
// all the other files.
bool SwiftBodyEmissionStrategy::shouldEmitDeclBody(const swift::Decl& decl) {
auto module = decl.getModuleContext();
if (module != &currentModule) {
if (!currentTopLevelDecls.contains(&decl) && decl.getModuleContext() != &currentModule) {
return false;
}
if (currentLazyDeclaration && currentLazyDeclaration != &decl) {
Expand Down
8 changes: 7 additions & 1 deletion swift/extractor/infra/SwiftBodyEmissionStrategy.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,19 @@ class SwiftBodyEmissionStrategy {
const swift::Decl* currentLazyDeclaration)
: currentModule(currentModule),
currentPrimarySourceFile(currentPrimarySourceFile),
currentLazyDeclaration(currentLazyDeclaration) {}
currentLazyDeclaration(currentLazyDeclaration) {
llvm::SmallVector<swift::Decl*> decls;
currentModule.getTopLevelDecls(decls);
currentTopLevelDecls.insert(decls.begin(), decls.end());
}

bool shouldEmitDeclBody(const swift::Decl& decl);

private:
swift::ModuleDecl& currentModule;
swift::SourceFile* currentPrimarySourceFile;
const swift::Decl* currentLazyDeclaration;
std::unordered_set<const swift::Decl*> currentTopLevelDecls;
};

} // namespace codeql
9 changes: 8 additions & 1 deletion swift/extractor/infra/SwiftLocationExtractor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,14 @@ void SwiftLocationExtractor::attachLocationImpl(const swift::SourceManager& sour
entry.file = fetchFileLabel(file);
std::tie(entry.start_line, entry.start_column) =
sourceManager.getLineAndColumnInBuffer(range.Start);
std::tie(entry.end_line, entry.end_column) = sourceManager.getLineAndColumnInBuffer(range.End);
if (sourceManager.getLineAndColumnInBuffer(range.End) >=
sourceManager.getLineAndColumnInBuffer(range.Start)) {
std::tie(entry.end_line, entry.end_column) = sourceManager.getLineAndColumnInBuffer(range.End);
} else {
// the compiler may generate source ranges that go backwards
entry.end_line = entry.start_line;
entry.end_column = entry.start_column;
}
SwiftMangledName locName{"loc", entry.file, ':', entry.start_line, ':', entry.start_column,
':', entry.end_line, ':', entry.end_column};
entry.id = trap.createTypedLabel<DbLocationTag>(locName);
Expand Down
12 changes: 6 additions & 6 deletions swift/extractor/infra/SwiftTagTraits.h
Original file line number Diff line number Diff line change
Expand Up @@ -102,8 +102,9 @@ MAP(swift::Expr, ExprTag)
MAP(swift::IdentityExpr, IdentityExprTag)
MAP(swift::ParenExpr, ParenExprTag)
MAP(swift::DotSelfExpr, DotSelfExprTag)
MAP(swift::BorrowExpr, BorrowExprTag)
MAP(swift::AwaitExpr, AwaitExprTag)
MAP(swift::UnsafeExpr, void) // TODO: Swift 6.2
MAP(swift::BorrowExpr, BorrowExprTag)
MAP(swift::UnresolvedMemberChainResultExpr, UnresolvedMemberChainResultExprTag)
MAP(swift::AnyTryExpr, AnyTryExprTag)
MAP(swift::TryExpr, TryExprTag)
Expand Down Expand Up @@ -195,7 +196,6 @@ MAP(swift::Expr, ExprTag)
MAP(swift::ObjCSelectorExpr, ObjCSelectorExprTag)
MAP(swift::KeyPathExpr, KeyPathExprTag)
MAP(swift::KeyPathDotExpr, KeyPathDotExprTag)
MAP(swift::OneWayExpr, OneWayExprTag)
MAP(swift::TapExpr, TapExprTag)
MAP(swift::TypeJoinExpr, void) // does not appear in a visible AST, skipping
MAP(swift::MacroExpansionExpr, void) // unexpanded macro in an expr context, skipping
Expand Down Expand Up @@ -237,11 +237,11 @@ MAP(swift::Decl, DeclTag)
MAP(swift::ExtensionDecl, ExtensionDeclTag)
MAP(swift::TopLevelCodeDecl, TopLevelCodeDeclTag)
MAP(swift::ImportDecl, ImportDeclTag)
MAP(swift::PoundDiagnosticDecl, PoundDiagnosticDeclTag)
MAP(swift::PrecedenceGroupDecl, PrecedenceGroupDeclTag)
MAP(swift::MissingMemberDecl, MissingMemberDeclTag)
MAP(swift::PatternBindingDecl, PatternBindingDeclTag)
MAP(swift::EnumCaseDecl, EnumCaseDeclTag)
MAP(swift::UsingDecl, void) // TODO: Swift 6.2
MAP(swift::OperatorDecl, OperatorDeclTag)
MAP(swift::InfixOperatorDecl, InfixOperatorDeclTag)
MAP(swift::PrefixOperatorDecl, PrefixOperatorDeclTag)
Expand Down Expand Up @@ -315,7 +315,7 @@ MAP(swift::TypeBase, TypeTag)
MAP(swift::PrimaryArchetypeType, PrimaryArchetypeTypeTag)
MAP(swift::OpaqueTypeArchetypeType, OpaqueTypeArchetypeTypeTag)
MAP(swift::LocalArchetypeType, LocalArchetypeTypeTag)
MAP(swift::OpenedArchetypeType, OpenedArchetypeTypeTag)
MAP(swift::ExistentialArchetypeType, ExistentialArchetypeTypeTag)
MAP(swift::ElementArchetypeType, ElementArchetypeTypeTag)
MAP(swift::PackArchetypeType, PackArchetypeTypeTag)
MAP(swift::GenericTypeParamType, GenericTypeParamTypeTag)
Expand All @@ -342,16 +342,16 @@ MAP(swift::TypeBase, TypeTag)
MAP(swift::IntegerType, IntegerTypeTag)
MAP(swift::SugarType, SugarTypeTag)
MAP(swift::TypeAliasType, TypeAliasTypeTag)
MAP(swift::LocatableType, void) // TODO: Swift 6.2
MAP(swift::SyntaxSugarType, SyntaxSugarTypeTag)
MAP(swift::UnarySyntaxSugarType, UnarySyntaxSugarTypeTag)
MAP(swift::ArraySliceType, ArraySliceTypeTag)
MAP(swift::OptionalType, OptionalTypeTag)
MAP(swift::VariadicSequenceType, VariadicSequenceTypeTag)
MAP(swift::InlineArrayType, void) // TODO: Swift 6.2
MAP(swift::DictionaryType, DictionaryTypeTag)

MAP(swift::AvailabilitySpec, AvailabilitySpecTag)
MAP(swift::PlatformVersionConstraintAvailabilitySpec, PlatformVersionAvailabilitySpecTag)
MAP(swift::OtherPlatformAvailabilitySpec, OtherAvailabilitySpecTag)

MAP(swift::PoundAvailableInfo, AvailabilityInfoTag)
MAP(swift::MacroRoleAttr, MacroRoleTag)
Expand Down
2 changes: 1 addition & 1 deletion swift/extractor/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ static void processFrontendOptions(codeql::SwiftExtractorState& state,
swift::PrimarySpecificPaths psp{};
if (std::filesystem::path output = input.getPrimarySpecificPaths().OutputFilename;
!output.empty()) {
if (output.extension() == ".swiftmodule") {
if (output.extension() == ".swiftmodule" || output.extension() == ".pcm") {
psp.OutputFilename = codeql::redirect(output);
} else {
psp.OutputFilename = "/dev/null";
Expand Down
85 changes: 75 additions & 10 deletions swift/extractor/mangler/SwiftMangler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
#include <swift/AST/ASTContext.h>
#include <swift/AST/GenericEnvironment.h>
#include <swift/AST/GenericParamList.h>
#include <swift/AST/ClangModuleLoader.h>
#include <clang/Basic/Module.h>

using namespace codeql;

Expand Down Expand Up @@ -38,6 +40,8 @@ std::string_view getTypeKindStr(const swift::TypeBase* type) {

} // namespace

std::unordered_map<const swift::Decl*, unsigned> SwiftMangler::preloadedExtensionIndexes;

SwiftMangledName SwiftMangler::initMangled(const swift::TypeBase* type) {
return {getTypeKindStr(type), '_'};
}
Expand Down Expand Up @@ -109,32 +113,58 @@ unsigned SwiftMangler::getExtensionIndex(const swift::ExtensionDecl* decl,
// indexes once for each encountered parent into the `preloadedExtensionIndexes` mapping.
// Because we mangle declarations only once in a given trap/dispatcher context, we can safely
// discard preloaded indexes on use
if (auto found = preloadedExtensionIndexes.extract(decl)) {
return found.mapped();
if (auto found = SwiftMangler::preloadedExtensionIndexes.find(decl);
found != SwiftMangler::preloadedExtensionIndexes.end()) {
return found->second;
}
if (auto parentModule = llvm::dyn_cast<swift::ModuleDecl>(parent)) {
llvm::SmallVector<swift::Decl*> siblings;
parentModule->getTopLevelDecls(siblings);
indexExtensions(siblings);
if (auto clangModule = parentModule->findUnderlyingClangModule()) {
indexClangExtensions(clangModule, decl->getASTContext().getClangModuleLoader());
}
} else if (auto iterableParent = llvm::dyn_cast<swift::IterableDeclContext>(parent)) {
indexExtensions(iterableParent->getAllMembers());
} else {
// TODO use a generic logging handle for Swift entities here, once it's available
CODEQL_ASSERT(false, "non-local context must be module or iterable decl context");
}
auto found = preloadedExtensionIndexes.extract(decl);
auto found = SwiftMangler::preloadedExtensionIndexes.find(decl);
// TODO use a generic logging handle for Swift entities here, once it's available
CODEQL_ASSERT(found, "extension not found within parent");
return found.mapped();
CODEQL_ASSERT(found != SwiftMangler::preloadedExtensionIndexes.end(),
"extension not found within parent");
return found->second;
}

void SwiftMangler::indexExtensions(llvm::ArrayRef<swift::Decl*> siblings) {
auto index = 0u;
for (auto sibling : siblings) {
if (sibling->getKind() == swift::DeclKind::Extension) {
preloadedExtensionIndexes.emplace(sibling, index);
SwiftMangler::preloadedExtensionIndexes.emplace(sibling, index);
index += 2;
}
}
}

void SwiftMangler::indexClangExtensions(const clang::Module* clangModule,
swift::ClangModuleLoader* moduleLoader) {
if (!moduleLoader) {
return;
}

auto index = 1u;
for (const auto& submodule : clangModule->submodules()) {
if (auto* swiftSubmodule = moduleLoader->getWrapperForModule(submodule)) {
llvm::SmallVector<swift::Decl*> children;
swiftSubmodule->getTopLevelDecls(children);
for (const auto child : children) {
if (child->getKind() == swift::DeclKind::Extension) {
SwiftMangler::preloadedExtensionIndexes.emplace(child, index);
index += 2;
}
}
}
++index;
}
}

Expand Down Expand Up @@ -215,8 +245,8 @@ SwiftMangledName SwiftMangler::visitAnyFunctionType(const swift::AnyFunctionType
if (flags.isSending()) {
ret << "_sending";
}
if (flags.isCompileTimeConst()) {
ret << "_compiletimeconst";
if (flags.isCompileTimeLiteral()) {
ret << "_compiletimeliteral";
}
if (flags.isNoDerivative()) {
ret << "_noderivative";
Expand All @@ -225,6 +255,40 @@ SwiftMangledName SwiftMangler::visitAnyFunctionType(const swift::AnyFunctionType
ret << "...";
}
}

if (type->hasLifetimeDependencies()) {
for (const auto& lifetime : type->getLifetimeDependencies()) {
auto addressable = lifetime.getAddressableIndices();
auto condAddressable = lifetime.getConditionallyAddressableIndices();
ret << "_lifetime";

auto addIndexes = [&](swift::IndexSubset* bitvector) {
for (unsigned i = 0; i < bitvector->getCapacity(); ++i) {
if (bitvector->contains(i)) {
if (addressable && addressable->contains(i)) {
ret << "_address";
} else if (condAddressable && condAddressable->contains(i)) {
ret << "_address_for_deps";
}
ret << "_" << i;
}
}
};

if (lifetime.hasInheritLifetimeParamIndices()) {
ret << "_copy";
addIndexes(lifetime.getInheritIndices());
}
if (lifetime.hasScopeLifetimeParamIndices()) {
ret << "_borrow";
addIndexes(lifetime.getScopeIndices());
}
if (lifetime.isImmortal()) {
ret << "_immortal";
}
}
}

ret << "->" << fetch(type->getResult());
if (type->isAsync()) {
ret << "_async";
Expand Down Expand Up @@ -361,7 +425,8 @@ SwiftMangledName SwiftMangler::visitOpaqueTypeArchetypeType(
return visitArchetypeType(type) << fetch(type->getDecl());
}

SwiftMangledName SwiftMangler::visitOpenedArchetypeType(const swift::OpenedArchetypeType* type) {
SwiftMangledName SwiftMangler::visitExistentialArchetypeType(
const swift::ExistentialArchetypeType* type) {
auto* env = type->getGenericEnvironment();
llvm::SmallVector<char> uuid;
env->getOpenedExistentialUUID().toString(uuid);
Expand Down
6 changes: 4 additions & 2 deletions swift/extractor/mangler/SwiftMangler.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ class SwiftMangler : private swift::TypeVisitor<SwiftMangler, SwiftMangledName>,
SwiftMangledName visitTypeAliasType(const swift::TypeAliasType* type);
SwiftMangledName visitArchetypeType(const swift::ArchetypeType* type);
SwiftMangledName visitOpaqueTypeArchetypeType(const swift::OpaqueTypeArchetypeType* type);
SwiftMangledName visitOpenedArchetypeType(const swift::OpenedArchetypeType* type);
SwiftMangledName visitExistentialArchetypeType(const swift::ExistentialArchetypeType* type);
SwiftMangledName visitProtocolCompositionType(const swift::ProtocolCompositionType* type);
SwiftMangledName visitLValueType(const swift::LValueType* type);
SwiftMangledName visitDynamicSelfType(const swift::DynamicSelfType* type);
Expand All @@ -106,13 +106,15 @@ class SwiftMangler : private swift::TypeVisitor<SwiftMangler, SwiftMangledName>,
SwiftMangledName visitPackExpansionType(const swift::PackExpansionType* type);

private:
std::unordered_map<const swift::Decl*, unsigned> preloadedExtensionIndexes;
static std::unordered_map<const swift::Decl*, unsigned> preloadedExtensionIndexes;

virtual SwiftMangledName fetch(const swift::Decl* decl) = 0;
virtual SwiftMangledName fetch(const swift::TypeBase* type) = 0;
SwiftMangledName fetch(swift::Type type) { return fetch(type.getPointer()); }

void indexExtensions(llvm::ArrayRef<swift::Decl*> siblings);
void indexClangExtensions(const clang::Module* clangModule,
swift::ClangModuleLoader* moduleLoader);
unsigned int getExtensionIndex(const swift::ExtensionDecl* decl, const swift::Decl* parent);
static SwiftMangledName initMangled(const swift::TypeBase* type);
SwiftMangledName initMangled(const swift::Decl* decl);
Expand Down
2 changes: 1 addition & 1 deletion swift/extractor/remapping/SwiftFileInterception.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ auto& fileInterceptorInstance() {

bool mayBeRedirected(const char* path, int flags = O_RDONLY) {
return (!fileInterceptorInstance().expired() && (flags & O_ACCMODE) == O_RDONLY &&
endsWith(path, ".swiftmodule"));
(endsWith(path, ".swiftmodule") || endsWith(path, ".pcm")));
}

std::optional<std::string> hashFile(const fs::path& path) {
Expand Down
22 changes: 13 additions & 9 deletions swift/extractor/translators/DeclTranslator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,18 @@ codeql::Accessor DeclTranslator::translateAccessorDecl(const swift::AccessorDecl
case swift::AccessorKind::MutableAddress:
entry.is_unsafe_mutable_address = true;
break;
case swift::AccessorKind::DistributedGet:
// TODO: Swift 6.2
break;
case swift::AccessorKind::Read2:
// TODO: Swift 6.2
break;
case swift::AccessorKind::Modify2:
// TODO: Swift 6.2
break;
case swift::AccessorKind::Init:
// TODO: Swift 6.2
break;
}
fillFunction(decl, entry);
return entry;
Expand Down Expand Up @@ -280,7 +292,7 @@ void DeclTranslator::fillTypeDecl(const swift::TypeDecl& decl, codeql::TypeDecl&
void DeclTranslator::fillIterableDeclContext(const swift::IterableDeclContext& decl,
codeql::Decl& entry) {
for (auto member : decl.getMembers()) {
if (swift::AvailableAttr::isUnavailable(member)) {
if (member->isUnavailable()) {
continue;
}
entry.members.emplace_back(dispatcher.fetchLabel(member));
Expand Down Expand Up @@ -342,14 +354,6 @@ codeql::OpaqueTypeDecl DeclTranslator::translateOpaqueTypeDecl(const swift::Opaq
return entry;
}

codeql::PoundDiagnosticDecl DeclTranslator::translatePoundDiagnosticDecl(
const swift::PoundDiagnosticDecl& decl) {
auto entry = createEntry(decl);
entry.kind = translateDiagnosticsKind(decl.getKind());
entry.message = dispatcher.fetchLabel(decl.getMessage());
return entry;
}

codeql::MissingMemberDecl DeclTranslator::translateMissingMemberDecl(
const swift::MissingMemberDecl& decl) {
auto entry = createEntry(decl);
Expand Down
1 change: 0 additions & 1 deletion swift/extractor/translators/DeclTranslator.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ class DeclTranslator : public AstTranslatorBase<DeclTranslator> {
codeql::ImportDecl translateImportDecl(const swift::ImportDecl& decl);
codeql::ModuleDecl translateModuleDecl(const swift::ModuleDecl& 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);
codeql::MacroDecl translateMacroDecl(const swift::MacroDecl& decl);
Expand Down
12 changes: 3 additions & 9 deletions swift/extractor/translators/ExprTranslator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -185,12 +185,6 @@ codeql::ObjCSelectorExpr ExprTranslator::translateObjCSelectorExpr(
return entry;
}

codeql::OneWayExpr ExprTranslator::translateOneWayExpr(const swift::OneWayExpr& expr) {
auto entry = createExprEntry(expr);
entry.sub_expr = dispatcher.fetchLabel(expr.getSubExpr());
return entry;
}

codeql::OpenExistentialExpr ExprTranslator::translateOpenExistentialExpr(
const swift::OpenExistentialExpr& expr) {
auto entry = createExprEntry(expr);
Expand Down Expand Up @@ -498,7 +492,7 @@ TrapLabel<KeyPathComponentTag> ExprTranslator::emitKeyPathComponent(
const swift::KeyPathExpr::Component& component) {
auto entry = dispatcher.createUncachedEntry(component);
entry.kind = static_cast<int>(component.getKind());
if (auto subscript_args = component.getSubscriptArgs()) {
if (auto subscript_args = component.getArgs()) {
for (const auto& arg : *subscript_args) {
entry.subscript_arguments.push_back(emitArgument(arg));
}
Expand Down Expand Up @@ -691,8 +685,8 @@ codeql::CurrentContextIsolationExpr ExprTranslator::translateCurrentContextIsola

codeql::TypeValueExpr ExprTranslator::translateTypeValueExpr(const swift::TypeValueExpr& expr) {
auto entry = createExprEntry(expr);
if (expr.getParamTypeRepr() && expr.getParamType()) {
entry.type_repr = dispatcher.fetchLabel(expr.getParamTypeRepr(), expr.getParamType());
if (expr.getRepr() && expr.getParamType()) {
entry.type_repr = dispatcher.fetchLabel(expr.getRepr(), expr.getParamType());
}
return entry;
}
Expand Down
1 change: 0 additions & 1 deletion swift/extractor/translators/ExprTranslator.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ class ExprTranslator : public AstTranslatorBase<ExprTranslator> {
codeql::MakeTemporarilyEscapableExpr translateMakeTemporarilyEscapableExpr(
const swift::MakeTemporarilyEscapableExpr& expr);
codeql::ObjCSelectorExpr translateObjCSelectorExpr(const swift::ObjCSelectorExpr& expr);
codeql::OneWayExpr translateOneWayExpr(const swift::OneWayExpr& expr);
codeql::OpenExistentialExpr translateOpenExistentialExpr(const swift::OpenExistentialExpr& expr);
codeql::OptionalEvaluationExpr translateOptionalEvaluationExpr(
const swift::OptionalEvaluationExpr& expr);
Expand Down
Loading
Loading