Skip to content

[NFC] Add module alias map and lookup func to ASTContext #39496

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Sep 30, 2021
Merged
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
13 changes: 13 additions & 0 deletions include/swift/AST/ASTContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,9 @@ class ASTContext final {
/// Cache of module names that fail the 'canImport' test in this context.
mutable llvm::SmallPtrSet<Identifier, 8> FailedModuleImportNames;

/// Mapping between aliases and real (physical) names of imported or referenced modules.
mutable llvm::DenseMap<Identifier, Identifier> ModuleAliasMap;

/// Retrieve the allocator for the given arena.
llvm::BumpPtrAllocator &
getAllocator(AllocationArena arena = AllocationArena::Permanent) const;
Expand Down Expand Up @@ -471,6 +474,16 @@ class ASTContext final {
/// specified string.
Identifier getIdentifier(StringRef Str) const;

/// Convert a given alias map to a map of Identifiers between module aliases and their actual names.
/// For example, if '-module-alias Foo=X -module-alias Bar=Y' input is passed in, the aliases Foo and Bar are
/// the names of the imported or referenced modules in source files in the main module, and X and Y
/// are the real (physical) module names on disk.
void setModuleAliases(const llvm::StringMap<StringRef> &aliasMap);

/// Retrieve the actual module name if a module alias is used via '-module-alias Foo=X', where Foo is
/// a module alias and X is the real (physical) name. Returns \p key if no aliasing is used.
Identifier getRealModuleName(Identifier key) const;

/// Decide how to interpret two precedence groups.
Associativity associateInfixOperators(PrecedenceGroupDecl *left,
PrecedenceGroupDecl *right) const;
Expand Down
10 changes: 10 additions & 0 deletions include/swift/AST/Module.h
Original file line number Diff line number Diff line change
Expand Up @@ -357,6 +357,15 @@ class ModuleDecl
ModuleABIName = name;
}

/// Retrieve the actual module name of an alias used for this module (if any).
///
/// For example, if '-module-alias Foo=Bar' is passed in when building the main module,
/// and this module is (a) not the main module and (b) is named Foo, then it returns
/// the real (physically on-disk) module name Bar.
///
/// If no module aliasing is set, it will return getName(), i.e. Foo.
Identifier getRealName() const;

/// User-defined module version number.
llvm::VersionTuple UserModuleVersion;
void setUserModuleVersion(llvm::VersionTuple UserVer) {
Expand All @@ -365,6 +374,7 @@ class ModuleDecl
llvm::VersionTuple getUserModuleVersion() const {
return UserModuleVersion;
}

private:
/// A cache of this module's underlying module and required bystander if it's
/// an underscored cross-import overlay.
Expand Down
17 changes: 17 additions & 0 deletions lib/AST/ASTContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1642,6 +1642,23 @@ void ASTContext::addModuleInterfaceChecker(
getImpl().InterfaceChecker = std::move(checker);
}

void ASTContext::setModuleAliases(const llvm::StringMap<StringRef> &aliasMap) {
for (auto k: aliasMap.keys()) {
auto val = aliasMap.lookup(k);
if (!val.empty()) {
ModuleAliasMap[getIdentifier(k)] = getIdentifier(val);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this (or something else) copy the strings storage to the AST context?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've had issues in the past with StringRefs parsed from arguments being lost in long running SourceKit process. I'm not sure if we could see the same thing here.

Copy link
Contributor Author

@elsh elsh Sep 29, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

getIdentifier allocates an entry and the ModuleAliasMap is a DenseMap so it'll be stored. Also the StringRefs in the argument map contains allocated data so they won't be lost either by the time this func is called. We could perhaps clear the argument map after the loop for better optimization if needed.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good. Thanks for the details!

}
}
}

Identifier ASTContext::getRealModuleName(Identifier key) const {
auto found = ModuleAliasMap.find(key);
if (found != ModuleAliasMap.end()) {
return found->second;
}
return key;
}

Optional<ModuleDependencies> ASTContext::getModuleDependencies(
StringRef moduleName, bool isUnderlyingClangModule,
ModuleDependenciesCache &cache, InterfaceSubContextDelegate &delegate,
Expand Down
6 changes: 5 additions & 1 deletion lib/AST/Module.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -475,7 +475,6 @@ ModuleDecl::ModuleDecl(Identifier name, ASTContext &ctx,
ctx.addDestructorCleanup(*this);
setImplicit();
setInterfaceType(ModuleType::get(this));

setAccess(AccessLevel::Public);

Bits.ModuleDecl.StaticLibrary = 0;
Expand Down Expand Up @@ -1564,6 +1563,11 @@ ImportedModule::removeDuplicates(SmallVectorImpl<ImportedModule> &imports) {
imports.erase(last, imports.end());
}

Identifier ModuleDecl::getRealName() const {
// This will return the real name for an alias (if used) or getName()
return getASTContext().getRealModuleName(getName());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cute.

}

Identifier ModuleDecl::getABIName() const {
if (!ModuleABIName.empty())
return ModuleABIName;
Expand Down
3 changes: 3 additions & 0 deletions lib/Frontend/Frontend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,9 @@ bool CompilerInstance::setUpASTContextIfNeeded() {
Invocation.getClangImporterOptions(),
Invocation.getSymbolGraphOptions(),
SourceMgr, Diagnostics));
if (!Invocation.getFrontendOptions().ModuleAliasMap.empty())
Context->setModuleAliases(Invocation.getFrontendOptions().ModuleAliasMap);

registerParseRequestFunctions(Context->evaluator);
registerTypeCheckerRequestFunctions(Context->evaluator);
registerSILGenRequestFunctions(Context->evaluator);
Expand Down