From: Bruno Cardoso Lopes Date: Mon, 16 Apr 2018 19:42:32 +0000 (+0000) Subject: Use export_as for autolinking frameworks X-Git-Tag: llvmorg-7.0.0-rc1~8087 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=a3b5f71eaa924f71321fb989d727a3a6365ba557;p=platform%2Fupstream%2Fllvm.git Use export_as for autolinking frameworks framework module SomeKitCore { ... export_as SomeKit } Given the module above, while generting autolink information during codegen, clang should to emit '-framework SomeKitCore' only if SomeKit was not imported in the relevant TU, otherwise it should use '-framework SomeKit' instead. rdar://problem/38269782 llvm-svn: 330152 --- diff --git a/clang/include/clang/Basic/Module.h b/clang/include/clang/Basic/Module.h index 3725fcb..d4e2dd4 100644 --- a/clang/include/clang/Basic/Module.h +++ b/clang/include/clang/Basic/Module.h @@ -331,6 +331,10 @@ public: /// an entity from this module is used. llvm::SmallVector LinkLibraries; + /// Autolinking uses the framework name for linking purposes + /// when this is false and the export_as name otherwise. + bool UseExportAsModuleLinkName = false; + /// \brief The set of "configuration macros", which are macros that /// (intentionally) change how this module is built. std::vector ConfigMacros; diff --git a/clang/include/clang/Lex/ModuleMap.h b/clang/include/clang/Lex/ModuleMap.h index 8593fcd..a34f0d8 100644 --- a/clang/include/clang/Lex/ModuleMap.h +++ b/clang/include/clang/Lex/ModuleMap.h @@ -21,6 +21,7 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/PointerIntPair.h" +#include "llvm/ADT/StringSet.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" @@ -104,7 +105,19 @@ class ModuleMap { /// \brief The number of modules we have created in total. unsigned NumCreatedModules = 0; + /// In case a module has a export_as entry, it might have a pending link + /// name to be determined if that module is imported. + llvm::StringMap> PendingLinkAsModule; + public: + /// Use PendingLinkAsModule information to mark top level link names that + /// are going to be replaced by export_as aliases. + void resolveLinkAsDependencies(Module *Mod); + + /// Make module to use export_as as the link dependency name if enough + /// information is available or add it to a pending list otherwise. + void addLinkAsDependency(Module *Mod); + /// \brief Flags describing the role of a module header. enum ModuleHeaderRole { /// \brief This header is normally included in the module. diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 687a6ca..42a8cd8 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -1556,6 +1556,12 @@ static void addLinkOptionsPostorder(CodeGenModule &CGM, Module *Mod, // Add linker options to link against the libraries/frameworks // described by this module. llvm::LLVMContext &Context = CGM.getLLVMContext(); + + // For modules that use export_as for linking, use that module + // name instead. + if (Mod->UseExportAsModuleLinkName) + return; + for (unsigned I = Mod->LinkLibraries.size(); I > 0; --I) { // Link against a framework. Frameworks are currently Darwin only, so we // don't to ask TargetCodeGenInfo for the spelling of the linker option. diff --git a/clang/lib/Frontend/CompilerInstance.cpp b/clang/lib/Frontend/CompilerInstance.cpp index b8f55b6..f57246b 100644 --- a/clang/lib/Frontend/CompilerInstance.cpp +++ b/clang/lib/Frontend/CompilerInstance.cpp @@ -1979,6 +1979,12 @@ CompilerInstance::loadModule(SourceLocation ImportLoc, Module, ImportLoc); } + // Resolve any remaining module using export_as for this one. + getPreprocessor() + .getHeaderSearchInfo() + .getModuleMap() + .resolveLinkAsDependencies(TopModule); + LastModuleImportLoc = ImportLoc; LastModuleImportResult = ModuleLoadResult(Module); return LastModuleImportResult; diff --git a/clang/lib/Lex/ModuleMap.cpp b/clang/lib/Lex/ModuleMap.cpp index a711e1d..e47abd5 100644 --- a/clang/lib/Lex/ModuleMap.cpp +++ b/clang/lib/Lex/ModuleMap.cpp @@ -54,6 +54,24 @@ using namespace clang; +void ModuleMap::resolveLinkAsDependencies(Module *Mod) { + auto PendingLinkAs = PendingLinkAsModule.find(Mod->Name); + if (PendingLinkAs != PendingLinkAsModule.end()) { + for (auto &Name : PendingLinkAs->second) { + auto *M = findModule(Name.getKey()); + if (M) + M->UseExportAsModuleLinkName = true; + } + } +} + +void ModuleMap::addLinkAsDependency(Module *Mod) { + if (findModule(Mod->ExportAsModule)) + Mod->UseExportAsModuleLinkName = true; + else + PendingLinkAsModule[Mod->ExportAsModule].insert(Mod->Name); +} + Module::HeaderKind ModuleMap::headerRoleToKind(ModuleHeaderRole Role) { switch ((int)Role) { default: llvm_unreachable("unknown header role"); @@ -2412,6 +2430,8 @@ void ModuleMapParser::parseExportAsDecl() { } ActiveModule->ExportAsModule = Tok.getString(); + Map.addLinkAsDependency(ActiveModule); + consumeToken(); } diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index 9e83250..179f25e 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -5171,6 +5171,7 @@ ASTReader::ReadSubmoduleBlock(ModuleFile &F, unsigned ClientLoadCapabilities) { break; case SUBMODULE_LINK_LIBRARY: + ModMap.resolveLinkAsDependencies(CurrentModule); CurrentModule->LinkLibraries.push_back( Module::LinkLibrary(Blob, Record[0])); break; @@ -5203,6 +5204,7 @@ ASTReader::ReadSubmoduleBlock(ModuleFile &F, unsigned ClientLoadCapabilities) { case SUBMODULE_EXPORT_AS: CurrentModule->ExportAsModule = Blob.str(); + ModMap.addLinkAsDependency(CurrentModule); break; } } diff --git a/clang/test/Modules/Inputs/exportas-link/OtherKit.framework/Headers/OtherKit.h b/clang/test/Modules/Inputs/exportas-link/OtherKit.framework/Headers/OtherKit.h new file mode 100644 index 0000000..18f0bd5 --- /dev/null +++ b/clang/test/Modules/Inputs/exportas-link/OtherKit.framework/Headers/OtherKit.h @@ -0,0 +1,6 @@ +#import + +#ifdef F +#import +#endif + diff --git a/clang/test/Modules/Inputs/exportas-link/OtherKit.framework/Modules/module.modulemap b/clang/test/Modules/Inputs/exportas-link/OtherKit.framework/Modules/module.modulemap new file mode 100644 index 0000000..1ce7351 --- /dev/null +++ b/clang/test/Modules/Inputs/exportas-link/OtherKit.framework/Modules/module.modulemap @@ -0,0 +1,5 @@ + +framework module OtherKit { + header "OtherKit.h" + export * +} diff --git a/clang/test/Modules/Inputs/exportas-link/SomeKit.framework/Headers/SKWidget.h b/clang/test/Modules/Inputs/exportas-link/SomeKit.framework/Headers/SKWidget.h new file mode 100644 index 0000000..dd99ff7 --- /dev/null +++ b/clang/test/Modules/Inputs/exportas-link/SomeKit.framework/Headers/SKWidget.h @@ -0,0 +1 @@ +#import diff --git a/clang/test/Modules/Inputs/exportas-link/SomeKit.framework/Headers/SomeKit.h b/clang/test/Modules/Inputs/exportas-link/SomeKit.framework/Headers/SomeKit.h new file mode 100644 index 0000000..17a4cc8 --- /dev/null +++ b/clang/test/Modules/Inputs/exportas-link/SomeKit.framework/Headers/SomeKit.h @@ -0,0 +1 @@ +#import diff --git a/clang/test/Modules/Inputs/exportas-link/SomeKit.framework/Modules/module.modulemap b/clang/test/Modules/Inputs/exportas-link/SomeKit.framework/Modules/module.modulemap new file mode 100644 index 0000000..ae4b276 --- /dev/null +++ b/clang/test/Modules/Inputs/exportas-link/SomeKit.framework/Modules/module.modulemap @@ -0,0 +1,6 @@ +framework module SomeKit { + umbrella header "SomeKit.h" + module * { + export * + } +} diff --git a/clang/test/Modules/Inputs/exportas-link/SomeKit.framework/SomeKit.tbd b/clang/test/Modules/Inputs/exportas-link/SomeKit.framework/SomeKit.tbd new file mode 100644 index 0000000..ab95795 --- /dev/null +++ b/clang/test/Modules/Inputs/exportas-link/SomeKit.framework/SomeKit.tbd @@ -0,0 +1 @@ +dummy tbd file diff --git a/clang/test/Modules/Inputs/exportas-link/SomeKitCore.framework/Headers/SKWidget.h b/clang/test/Modules/Inputs/exportas-link/SomeKitCore.framework/Headers/SKWidget.h new file mode 100644 index 0000000..1fb010c --- /dev/null +++ b/clang/test/Modules/Inputs/exportas-link/SomeKitCore.framework/Headers/SKWidget.h @@ -0,0 +1,4 @@ +@interface SKWidget +- (void)someObjCMethod; +@end + diff --git a/clang/test/Modules/Inputs/exportas-link/SomeKitCore.framework/Headers/SomeKitCore.h b/clang/test/Modules/Inputs/exportas-link/SomeKitCore.framework/Headers/SomeKitCore.h new file mode 100644 index 0000000..dd99ff7 --- /dev/null +++ b/clang/test/Modules/Inputs/exportas-link/SomeKitCore.framework/Headers/SomeKitCore.h @@ -0,0 +1 @@ +#import diff --git a/clang/test/Modules/Inputs/exportas-link/SomeKitCore.framework/Modules/module.modulemap b/clang/test/Modules/Inputs/exportas-link/SomeKitCore.framework/Modules/module.modulemap new file mode 100644 index 0000000..30f9770 --- /dev/null +++ b/clang/test/Modules/Inputs/exportas-link/SomeKitCore.framework/Modules/module.modulemap @@ -0,0 +1,7 @@ +framework module SomeKitCore { + umbrella header "SomeKitCore.h" + export_as SomeKit + module * { + export * + } +} diff --git a/clang/test/Modules/Inputs/exportas-link/SomeKitCore.framework/SomeKitCore.tbd b/clang/test/Modules/Inputs/exportas-link/SomeKitCore.framework/SomeKitCore.tbd new file mode 100644 index 0000000..ab95795 --- /dev/null +++ b/clang/test/Modules/Inputs/exportas-link/SomeKitCore.framework/SomeKitCore.tbd @@ -0,0 +1 @@ +dummy tbd file diff --git a/clang/test/Modules/use-exportas-for-link.m b/clang/test/Modules/use-exportas-for-link.m new file mode 100644 index 0000000..69773e6 --- /dev/null +++ b/clang/test/Modules/use-exportas-for-link.m @@ -0,0 +1,44 @@ +// RUN: rm -rf %t +// RUN: %clang_cc1 -emit-llvm -o - -fmodules-cache-path=%t -DA -fmodules -fimplicit-module-maps -F %S/Inputs/exportas-link %s | FileCheck --check-prefix=CHECK_A %s +// CHECK_A: !llvm.linker.options = !{![[MODULE:[0-9]+]]} +// CHECK_A: ![[MODULE]] = !{!"-framework", !"SomeKit"} +#ifdef A +@import SomeKitCore; +@import SomeKit; +#endif + +// RUN: %clang_cc1 -emit-llvm -o - -fmodules-cache-path=%t -DB -fmodules -fimplicit-module-maps -F %S/Inputs/exportas-link %s | FileCheck --check-prefix=CHECK_B %s +// CHECK_B: !llvm.linker.options = !{![[MODULE:[0-9]+]]} +// CHECK_B: ![[MODULE]] = !{!"-framework", !"SomeKit"} +#ifdef B +@import SomeKit; +@import SomeKitCore; +#endif + +// RUN: %clang_cc1 -emit-llvm -o - -fmodules-cache-path=%t -DC -fmodules -fimplicit-module-maps -F %S/Inputs/exportas-link %s | FileCheck --check-prefix=CHECK_C %s +// CHECK_C: !llvm.linker.options = !{![[MODULE:[0-9]+]]} +// CHECK_C: ![[MODULE]] = !{!"-framework", !"SomeKitCore"} +#ifdef C +@import SomeKitCore; +#endif + +// RUN: %clang_cc1 -emit-llvm -o - -fmodules-cache-path=%t -DD -fmodules -fimplicit-module-maps -F %S/Inputs/exportas-link %s | FileCheck --check-prefix=CHECK_D %s +// CHECK_D: !llvm.linker.options = !{![[MODULE:[0-9]+]]} +// CHECK_D: ![[MODULE]] = !{!"-framework", !"SomeKit"} +#ifdef D +@import SomeKit; +#endif + +// RUN: %clang_cc1 -emit-llvm -o - -fmodules-cache-path=%t -DE -fmodules -fimplicit-module-maps -F %S/Inputs/exportas-link %s | FileCheck --check-prefix=CHECK_E %s +// CHECK_E: !llvm.linker.options = !{![[MODULE:[0-9]+]]} +// CHECK_E: ![[MODULE]] = !{!"-framework", !"SomeKitCore"} +#ifdef E +@import OtherKit; +#endif + +// RUN: %clang_cc1 -emit-llvm -o - -fmodules-cache-path=%t -DF -fmodules -fimplicit-module-maps -F %S/Inputs/exportas-link %s | FileCheck --check-prefix=CHECK_F %s +// CHECK_F: !llvm.linker.options = !{![[MODULE:[0-9]+]]} +// CHECK_F: ![[MODULE]] = !{!"-framework", !"SomeKit"} +#ifdef F +@import OtherKit; +#endif