diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/Basic/Module.cpp | 10 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenModule.cpp | 70 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenModule.h | 12 | ||||
-rw-r--r-- | clang/lib/Lex/ModuleMap.cpp | 44 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTReader.cpp | 17 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTWriter.cpp | 17 |
6 files changed, 164 insertions, 6 deletions
diff --git a/clang/lib/Basic/Module.cpp b/clang/lib/Basic/Module.cpp index 417c7e57453..5e5e431d311 100644 --- a/clang/lib/Basic/Module.cpp +++ b/clang/lib/Basic/Module.cpp @@ -257,6 +257,16 @@ void Module::print(raw_ostream &OS, unsigned Indent) const { OS << "\n"; } + for (unsigned I = 0, N = LinkLibraries.size(); I != N; ++I) { + OS.indent(Indent + 2); + OS << "link "; + if (LinkLibraries[I].IsFramework) + OS << "framework "; + OS << "\""; + OS.write_escaped(LinkLibraries[I].Library); + OS << "\""; + } + if (InferSubmodules) { OS.indent(Indent + 2); if (InferExplicitSubmodules) diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 0257ce23f61..da37e4982d4 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -32,6 +32,7 @@ #include "clang/Basic/Builtins.h" #include "clang/Basic/ConvertUTF.h" #include "clang/Basic/Diagnostic.h" +#include "clang/Basic/Module.h" #include "clang/Basic/SourceManager.h" #include "clang/Basic/TargetInfo.h" #include "clang/Frontend/CodeGenOptions.h" @@ -172,7 +173,8 @@ void CodeGenModule::Release() { EmitCtorList(GlobalDtors, "llvm.global_dtors"); EmitGlobalAnnotations(); EmitLLVMUsed(); - + EmitLinkLibraries(); + SimplifyPersonality(); if (getCodeGenOpts().EmitDeclMetadata) @@ -714,6 +716,24 @@ void CodeGenModule::EmitLLVMUsed() { GV->setSection("llvm.metadata"); } +void CodeGenModule::EmitLinkLibraries() { + // If there are no libraries to link against, do nothing. + if (LinkLibraries.empty()) + return; + + // Create metadata for each library we're linking against. + llvm::NamedMDNode *Metadata + = getModule().getOrInsertNamedMetadata("llvm.link.libraries"); + for (unsigned I = 0, N = LinkLibraries.size(); I != N; ++I) { + llvm::Value *Args[2] = { + llvm::MDString::get(getLLVMContext(), LinkLibraries[I].Library), + llvm::ConstantInt::get(llvm::Type::getInt1Ty(getLLVMContext()), + LinkLibraries[I].IsFramework) + }; + Metadata->addOperand(llvm::MDNode::get(getLLVMContext(), Args)); + } +} + void CodeGenModule::EmitDeferred() { // Emit code for any potentially referenced deferred decls. Since a // previously unused static decl may become used during the generation of code @@ -2681,7 +2701,6 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) { case Decl::TypeAliasTemplate: case Decl::NamespaceAlias: case Decl::Block: - case Decl::Import: break; case Decl::CXXConstructor: // Skip function templates @@ -2762,6 +2781,53 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) { break; } + case Decl::Import: { + ImportDecl *Import = cast<ImportDecl>(D); + + // Ignore import declarations that come from imported modules. + if (clang::Module *Owner = Import->getOwningModule()) { + if (getLangOpts().CurrentModule.empty() || + Owner->getTopLevelModule()->Name == getLangOpts().CurrentModule) + break; + } + + // Walk from this module up to its top-level module; we'll import all of + // these modules and their non-explicit child modules. + llvm::SmallVector<clang::Module *, 2> Stack; + for (clang::Module *Mod = Import->getImportedModule(); Mod; + Mod = Mod->Parent) { + if (!ImportedModules.insert(Mod)) + break; + + Stack.push_back(Mod); + } + + // Find all of the non-explicit submodules of the modules we've imported and + // import them. + while (!Stack.empty()) { + clang::Module *Mod = Stack.back(); + Stack.pop_back(); + + // Add the link libraries for this module. + LinkLibraries.insert(LinkLibraries.end(), + Mod->LinkLibraries.begin(), + Mod->LinkLibraries.end()); + + // We've imported this module; now import any of its children that haven't + // already been imported. + for (clang::Module::submodule_iterator Sub = Mod->submodule_begin(), + SubEnd = Mod->submodule_end(); + Sub != SubEnd; ++Sub) { + if ((*Sub)->IsExplicit) + continue; + + if (ImportedModules.insert(*Sub)) + Stack.push_back(*Sub); + } + } + break; + } + default: // Make sure we handled everything we should, every other kind is a // non-top-level decl. FIXME: Would be nice to have an isTopLevelDeclKind diff --git a/clang/lib/CodeGen/CodeGenModule.h b/clang/lib/CodeGen/CodeGenModule.h index 34fa19c0108..0d644a748e0 100644 --- a/clang/lib/CodeGen/CodeGenModule.h +++ b/clang/lib/CodeGen/CodeGenModule.h @@ -23,7 +23,9 @@ #include "clang/AST/Mangle.h" #include "clang/Basic/ABI.h" #include "clang/Basic/LangOptions.h" +#include "clang/Basic/Module.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SetVector.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/StringMap.h" #include "llvm/IR/Module.h" @@ -66,6 +68,7 @@ namespace clang { class AnnotateAttr; class CXXDestructorDecl; class MangleBuffer; + class Module; namespace CodeGen { @@ -313,6 +316,12 @@ class CodeGenModule : public CodeGenTypeCache { /// run on termination. std::vector<std::pair<llvm::WeakVH,llvm::Constant*> > CXXGlobalDtors; + /// \brief The complete set of modules that has been imported. + llvm::SetVector<clang::Module *> ImportedModules; + + /// \brief The set of libraries to link against. + std::vector<clang::Module::LinkLibrary> LinkLibraries; + /// @name Cache for Objective-C runtime types /// @{ @@ -989,6 +998,9 @@ private: /// references to global which may otherwise be optimized out. void EmitLLVMUsed(); + /// \brief Emit the set of libraries to link against. + void EmitLinkLibraries(); + void EmitDeclMetadata(); /// EmitCoverageFile - Emit the llvm.gcov metadata used to tell LLVM where diff --git a/clang/lib/Lex/ModuleMap.cpp b/clang/lib/Lex/ModuleMap.cpp index d954bc9fc27..6b0eb79a10a 100644 --- a/clang/lib/Lex/ModuleMap.cpp +++ b/clang/lib/Lex/ModuleMap.cpp @@ -645,6 +645,7 @@ namespace clang { ExplicitKeyword, ExportKeyword, FrameworkKeyword, + LinkKeyword, ModuleKeyword, Period, UmbrellaKeyword, @@ -732,6 +733,7 @@ namespace clang { void parseHeaderDecl(SourceLocation UmbrellaLoc, SourceLocation ExcludeLoc); void parseUmbrellaDirDecl(SourceLocation UmbrellaLoc); void parseExportDecl(); + void parseLinkDecl(); void parseInferredModuleDecl(bool Framework, bool Explicit); bool parseOptionalAttributes(Attributes &Attrs); @@ -774,6 +776,7 @@ retry: .Case("explicit", MMToken::ExplicitKeyword) .Case("export", MMToken::ExportKeyword) .Case("framework", MMToken::FrameworkKeyword) + .Case("link", MMToken::LinkKeyword) .Case("module", MMToken::ModuleKeyword) .Case("requires", MMToken::RequiresKeyword) .Case("umbrella", MMToken::UmbrellaKeyword) @@ -944,6 +947,7 @@ namespace { /// header-declaration /// submodule-declaration /// export-declaration +/// link-declaration /// /// submodule-declaration: /// module-declaration @@ -1123,7 +1127,11 @@ void ModuleMapParser::parseModuleDecl() { case MMToken::HeaderKeyword: parseHeaderDecl(SourceLocation(), SourceLocation()); break; - + + case MMToken::LinkKeyword: + parseLinkDecl(); + break; + default: Diags.Report(Tok.getLocation(), diag::err_mmap_expected_member); consumeToken(); @@ -1440,7 +1448,36 @@ void ModuleMapParser::parseExportDecl() { ActiveModule->UnresolvedExports.push_back(Unresolved); } -/// \brief Parse an inferried module declaration (wildcard modules). +/// \brief Parse a link declaration. +/// +/// module-declaration: +/// 'link' 'framework'[opt] string-literal +void ModuleMapParser::parseLinkDecl() { + assert(Tok.is(MMToken::LinkKeyword)); + SourceLocation LinkLoc = consumeToken(); + + // Parse the optional 'framework' keyword. + bool IsFramework = false; + if (Tok.is(MMToken::FrameworkKeyword)) { + consumeToken(); + IsFramework = true; + } + + // Parse the library name + if (!Tok.is(MMToken::StringLiteral)) { + Diags.Report(Tok.getLocation(), diag::err_mmap_expected_library_name) + << IsFramework << SourceRange(LinkLoc); + HadError = true; + return; + } + + std::string LibraryName = Tok.getString(); + consumeToken(); + ActiveModule->LinkLibraries.push_back(Module::LinkLibrary(LibraryName, + IsFramework)); +} + +/// \brief Parse an inferred module declaration (wildcard modules). /// /// module-declaration: /// 'explicit'[opt] 'framework'[opt] 'module' * attributes[opt] @@ -1679,13 +1716,14 @@ bool ModuleMapParser::parseModuleMapFile() { case MMToken::FrameworkKeyword: parseModuleDecl(); break; - + case MMToken::Comma: case MMToken::ExcludeKeyword: case MMToken::ExportKeyword: case MMToken::HeaderKeyword: case MMToken::Identifier: case MMToken::LBrace: + case MMToken::LinkKeyword: case MMToken::LSquare: case MMToken::Period: case MMToken::RBrace: diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index 2ed8853bb2a..81d3cea7ba7 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -3413,6 +3413,9 @@ bool ASTReader::ReadSubmoduleBlock(ModuleFile &F) { DeserializationListener->ModuleRead(GlobalID, CurrentModule); SubmodulesLoaded[GlobalIndex] = CurrentModule; + + // Clear out link libraries; the module file has them. + CurrentModule->LinkLibraries.clear(); break; } @@ -3600,6 +3603,20 @@ bool ASTReader::ReadSubmoduleBlock(ModuleFile &F) { Context.getTargetInfo()); break; } + + case SUBMODULE_LINK_LIBRARY: + if (First) { + Error("missing submodule metadata record at beginning of block"); + return true; + } + + if (!CurrentModule) + break; + + CurrentModule->LinkLibraries.push_back( + Module::LinkLibrary(StringRef(BlobStart, BlobLen), + Record[0])); + break; } } } diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index fe498bee77f..d4b0367cac6 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -2107,6 +2107,12 @@ void ASTWriter::WriteSubmodules(Module *WritingModule) { Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Name unsigned ExcludedHeaderAbbrev = Stream.EmitAbbrev(Abbrev); + Abbrev = new BitCodeAbbrev(); + Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_LINK_LIBRARY)); + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsFramework + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Name + unsigned LinkLibraryAbbrev = Stream.EmitAbbrev(Abbrev); + // Write the submodule metadata block. RecordData Record; Record.push_back(getNumberOfModules(WritingModule)); @@ -2209,7 +2215,16 @@ void ASTWriter::WriteSubmodules(Module *WritingModule) { } Stream.EmitRecord(SUBMODULE_EXPORTS, Record); } - + + // Emit the link libraries. + for (unsigned I = 0, N = Mod->LinkLibraries.size(); I != N; ++I) { + Record.clear(); + Record.push_back(SUBMODULE_LINK_LIBRARY); + Record.push_back(Mod->LinkLibraries[I].IsFramework); + Stream.EmitRecordWithBlob(LinkLibraryAbbrev, Record, + Mod->LinkLibraries[I].Library); + } + // Queue up the submodules of this module. for (Module::submodule_iterator Sub = Mod->submodule_begin(), SubEnd = Mod->submodule_end(); |