diff --git a/include/cling/Interpreter/Interpreter.h b/include/cling/Interpreter/Interpreter.h index 8e0241f1..ca1244ce 100644 --- a/include/cling/Interpreter/Interpreter.h +++ b/include/cling/Interpreter/Interpreter.h @@ -72,10 +72,50 @@ namespace cling { ///\brief Describes the result of loading a library. /// enum LoadLibResult { - LoadLibSuccess, // library loaded successfully - LoadLibExists, // library was already loaded - LoadLibError, // library was not found - LoadLibNumResults + kLoadLibSuccess, // library loaded successfully + kLoadLibExists, // library was already loaded + kLoadLibError, // library was not found + kLoadLibNumResults + }; + + class LoadedFileInfo { + public: + enum FileType { + kSource, + kDynamicLibrary, + kBitcode, + kNumFileTypes + }; + + ///\brief Name as loaded for the first time. + /// + const std::string& getName() const { return m_Name; } + + ///\brief Type of the file. + FileType getType() const { return m_Type; } + + ///\brief Pointer to Interpreter::m_DyLibs entry if dynamic library + /// + const llvm::sys::DynamicLibrary* getDynLib() const { return m_DynLib; } + + private: + ///\brief Constructor used by Interpreter. + LoadedFileInfo(const std::string& name, FileType type, + const llvm::sys::DynamicLibrary* dynLib): + m_Name(name), m_Type(type), m_DynLib(dynLib) {} + + ///\brief Name as loaded for the first time. + /// + std::string m_Name; + + ///\brief Type of the file. + FileType m_Type; + + ///\brief Pointer to Interpreter::m_DyLibs entry if dynamic library + /// + const llvm::sys::DynamicLibrary* m_DynLib; + + friend class Interpreter; }; private: @@ -176,10 +216,17 @@ namespace cling { /// std::set m_DyLibs; + ///\brief Information about loaded files. + /// + llvm::SmallVector m_LoadedFiles; + ///\brief Try to load a library file via the llvm::Linker. /// LoadLibResult tryLinker(const std::string& filename, bool permanent); + void addLoadedFile(const std::string& name, LoadedFileInfo::FileType type, + const llvm::sys::DynamicLibrary* dyLib = 0); + ///\brief Processes the invocation options. /// void handleFrontendOptions(); @@ -428,19 +475,24 @@ namespace cling { ///\brief Loads a shared library. /// ///\param [in] filename - The file to loaded. + ///\param [in] permanent - If false, the file can be unloaded later. /// - ///\returns LoadLibSuccess on success, LoadLibExists if the library was - /// already loaded, LoadLibError if the library cannot be found or any + ///\returns kLoadLibSuccess on success, kLoadLibExists if the library was + /// already loaded, kLoadLibError if the library cannot be found or any /// other error was encountered. /// - /// LoadLibResult loadLibrary(const std::string& filename, bool permanent); + ///\brief Get the collection of loaded files. + /// + const llvm::SmallVectorImpl& getLoadedFiles() const { + return m_LoadedFiles; } + void enableDynamicLookup(bool value = true); bool isDynamicLookupEnabled() { return m_DynamicLookupEnabled; } bool isPrintingAST() { return m_PrintAST; } - void enablePrintAST(bool print = true) { m_PrintAST = print;} + void enablePrintAST(bool print = true) { m_PrintAST = print; } clang::CompilerInstance* getCI() const; const clang::Sema& getSema() const; diff --git a/lib/Interpreter/Interpreter.cpp b/lib/Interpreter/Interpreter.cpp index 80f35f07..f87260ea 100644 --- a/lib/Interpreter/Interpreter.cpp +++ b/lib/Interpreter/Interpreter.cpp @@ -78,7 +78,6 @@ namespace cling { } #endif - // This function isn't referenced outside its translation unit, but it // can't use the "static" keyword because its address is used for // GetMainExecutable (since some platforms don't support taking the @@ -542,15 +541,24 @@ namespace cling { return Interpreter::kFailure; } + void Interpreter::addLoadedFile(const std::string& name, + Interpreter::LoadedFileInfo::FileType type, + const llvm::sys::DynamicLibrary* dyLib) { + m_LoadedFiles.push_back(new LoadedFileInfo(name, type, dyLib)); + } + Interpreter::CompilationResult Interpreter::loadFile(const std::string& filename, bool allowSharedLib /*=true*/) { - if (allowSharedLib && loadLibrary(filename, false) == LoadLibSuccess) + if (allowSharedLib && loadLibrary(filename, false) == kLoadLibSuccess) return kSuccess; std::string code; code += "#include \"" + filename + "\""; - return declare(code); + CompilationResult res = declare(code); + if (res == kSuccess) + addLoadedFile(filename,LoadedFileInfo::kSource); + return res; } @@ -562,6 +570,12 @@ namespace cling { llvm::Linker L("cling", module, llvm::Linker::QuietWarnings | llvm::Linker::QuietErrors); + struct LinkerModuleReleaseRAII { + LinkerModuleReleaseRAII(llvm::Linker& L): m_L(L) {} + ~LinkerModuleReleaseRAII() { m_L.releaseModule(); } + llvm::Linker& m_L; + } LinkerModuleReleaseRAII_(L); + const InvocationOptions& Opts = getOptions(); for (std::vector::const_iterator I = Opts.LibSearchPath.begin(), E = Opts.LibSearchPath.end(); I != E; @@ -576,22 +590,21 @@ namespace cling { std::string Magic; if (!FilePath.getMagicNumber(Magic, 64)) { // filename doesn't exist... - L.releaseModule(); - return LoadLibError; + return kLoadLibError; } - if (IdentifyFileType(Magic.c_str(), 64) == Bitcode_FileType) { - // We are promised a bitcode file, complain if it fails - L.setFlags(0); - if (L.LinkInFile(Path(filename), Native)) { - L.releaseModule(); - return LoadLibError; - } - } else { + if (IdentifyFileType(Magic.c_str(), 64) != Bitcode_FileType) { // Nothing the linker can handle - L.releaseModule(); - return LoadLibError; + return kLoadLibError; } - } else if (Native) { + // We are promised a bitcode file, complain if it fails + L.setFlags(0); + if (L.LinkInFile(Path(filename), Native)) { + return kLoadLibError; + } + addLoadedFile(filename, LoadedFileInfo::kBitcode); + return kLoadLibSuccess; + } + if (Native) { // native shared library, load it! Path SoFile = L.FindLib(filename); assert(!SoFile.isEmpty() && "The shared lib exists but can't find it!"); @@ -599,30 +612,33 @@ namespace cling { // TODO: !permanent case DynamicLibrary DyLib = DynamicLibrary::getPermanentLibrary(SoFile.str().c_str(), &errMsg); - L.releaseModule(); if (!DyLib.isValid()) - return LoadLibError; - if (!m_DyLibs.insert(DyLib).second) - return LoadLibExists; - return LoadLibSuccess; + return kLoadLibError; + std::pair::iterator, bool> insRes + = m_DyLibs.insert(DyLib); + if (!insRes.second) + return kLoadLibExists; + addLoadedFile(filename, LoadedFileInfo::kDynamicLibrary, + &(*insRes.first)); + return kLoadLibSuccess; } - return LoadLibError; + return kLoadLibError; } Interpreter::LoadLibResult Interpreter::loadLibrary(const std::string& filename, bool permanent) { LoadLibResult res = tryLinker(filename, permanent); - if (res != LoadLibError) { + if (res != kLoadLibError) { return res; } if (filename.compare(0, 3, "lib") == 0) { // starts with "lib", try without (the llvm::Linker forces // a "lib" in front, which makes it liblib... res = tryLinker(filename.substr(3, std::string::npos), permanent); - if (res != LoadLibError) + if (res != kLoadLibError) return res; } - return LoadLibError; + return kLoadLibError; } void Interpreter::installLazyFunctionCreator(void* (*fp)(const std::string&)) { diff --git a/lib/MetaProcessor/MetaProcessor.cpp b/lib/MetaProcessor/MetaProcessor.cpp index 8a906ef2..cec7106f 100644 --- a/lib/MetaProcessor/MetaProcessor.cpp +++ b/lib/MetaProcessor/MetaProcessor.cpp @@ -421,10 +421,20 @@ namespace cling { PrintCommandHelp(); return true; } - else if (Command.equals("file")) { + else if (Command.equals("fileEx")) { PrintFileStats(); return true; } + else if (Command.equals("file")) { + typedef llvm::SmallVectorImpl LoadedFiles_t; + const LoadedFiles_t& LoadedFiles = m_Interp.getLoadedFiles(); + for (LoadedFiles_t::const_iterator I = LoadedFiles.begin(), + E = LoadedFiles.end(); I != E; ++I) { + char cType[] = { 'S', 'D', 'B' }; + llvm::outs() << '[' << cType[(*I)->getType()] << "] " << (*I)->getName() << '\n'; + } + return true; + } if (compRes) *compRes = Interpreter::kFailure; return false;