Rename LoadLibResult constants to start with 'k'.

Enable kLoadLibExists case in TCintWithCling.

Collect statistics about loaded files.
Give access to that through .file; rename SourceManager dump to fileEx.

Documentation.

(Sorry, should have been three patches.)


git-svn-id: http://root.cern.ch/svn/root/trunk@47330 27541ba8-7e3a-0410-8455-c3a389f83636
This commit is contained in:
Axel Naumann 2012-11-15 18:23:11 +00:00
parent 6379c2a21d
commit 226b360b15
3 changed files with 112 additions and 34 deletions

View File

@ -72,10 +72,50 @@ namespace cling {
///\brief Describes the result of loading a library. ///\brief Describes the result of loading a library.
/// ///
enum LoadLibResult { enum LoadLibResult {
LoadLibSuccess, // library loaded successfully kLoadLibSuccess, // library loaded successfully
LoadLibExists, // library was already loaded kLoadLibExists, // library was already loaded
LoadLibError, // library was not found kLoadLibError, // library was not found
LoadLibNumResults 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: private:
@ -176,10 +216,17 @@ namespace cling {
/// ///
std::set<llvm::sys::DynamicLibrary> m_DyLibs; std::set<llvm::sys::DynamicLibrary> m_DyLibs;
///\brief Information about loaded files.
///
llvm::SmallVector<LoadedFileInfo*, 200> m_LoadedFiles;
///\brief Try to load a library file via the llvm::Linker. ///\brief Try to load a library file via the llvm::Linker.
/// ///
LoadLibResult tryLinker(const std::string& filename, bool permanent); 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. ///\brief Processes the invocation options.
/// ///
void handleFrontendOptions(); void handleFrontendOptions();
@ -428,19 +475,24 @@ namespace cling {
///\brief Loads a shared library. ///\brief Loads a shared library.
/// ///
///\param [in] filename - The file to loaded. ///\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 ///\returns kLoadLibSuccess on success, kLoadLibExists if the library was
/// already loaded, LoadLibError if the library cannot be found or any /// already loaded, kLoadLibError if the library cannot be found or any
/// other error was encountered. /// other error was encountered.
/// ///
///
LoadLibResult loadLibrary(const std::string& filename, bool permanent); LoadLibResult loadLibrary(const std::string& filename, bool permanent);
///\brief Get the collection of loaded files.
///
const llvm::SmallVectorImpl<LoadedFileInfo*>& getLoadedFiles() const {
return m_LoadedFiles; }
void enableDynamicLookup(bool value = true); void enableDynamicLookup(bool value = true);
bool isDynamicLookupEnabled() { return m_DynamicLookupEnabled; } bool isDynamicLookupEnabled() { return m_DynamicLookupEnabled; }
bool isPrintingAST() { return m_PrintAST; } 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; clang::CompilerInstance* getCI() const;
const clang::Sema& getSema() const; const clang::Sema& getSema() const;

View File

@ -78,7 +78,6 @@ namespace cling {
} }
#endif #endif
// This function isn't referenced outside its translation unit, but it // This function isn't referenced outside its translation unit, but it
// can't use the "static" keyword because its address is used for // can't use the "static" keyword because its address is used for
// GetMainExecutable (since some platforms don't support taking the // GetMainExecutable (since some platforms don't support taking the
@ -542,15 +541,24 @@ namespace cling {
return Interpreter::kFailure; 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::CompilationResult
Interpreter::loadFile(const std::string& filename, Interpreter::loadFile(const std::string& filename,
bool allowSharedLib /*=true*/) { bool allowSharedLib /*=true*/) {
if (allowSharedLib && loadLibrary(filename, false) == LoadLibSuccess) if (allowSharedLib && loadLibrary(filename, false) == kLoadLibSuccess)
return kSuccess; return kSuccess;
std::string code; std::string code;
code += "#include \"" + filename + "\""; 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 L("cling", module, llvm::Linker::QuietWarnings
| llvm::Linker::QuietErrors); | 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(); const InvocationOptions& Opts = getOptions();
for (std::vector<Path>::const_iterator I for (std::vector<Path>::const_iterator I
= Opts.LibSearchPath.begin(), E = Opts.LibSearchPath.end(); I != E; = Opts.LibSearchPath.begin(), E = Opts.LibSearchPath.end(); I != E;
@ -576,22 +590,21 @@ namespace cling {
std::string Magic; std::string Magic;
if (!FilePath.getMagicNumber(Magic, 64)) { if (!FilePath.getMagicNumber(Magic, 64)) {
// filename doesn't exist... // filename doesn't exist...
L.releaseModule(); return kLoadLibError;
return LoadLibError;
} }
if (IdentifyFileType(Magic.c_str(), 64) == Bitcode_FileType) { 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 {
// Nothing the linker can handle // Nothing the linker can handle
L.releaseModule(); return kLoadLibError;
return LoadLibError;
} }
} 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! // native shared library, load it!
Path SoFile = L.FindLib(filename); Path SoFile = L.FindLib(filename);
assert(!SoFile.isEmpty() && "The shared lib exists but can't find it!"); assert(!SoFile.isEmpty() && "The shared lib exists but can't find it!");
@ -599,30 +612,33 @@ namespace cling {
// TODO: !permanent case // TODO: !permanent case
DynamicLibrary DyLib DynamicLibrary DyLib
= DynamicLibrary::getPermanentLibrary(SoFile.str().c_str(), &errMsg); = DynamicLibrary::getPermanentLibrary(SoFile.str().c_str(), &errMsg);
L.releaseModule();
if (!DyLib.isValid()) if (!DyLib.isValid())
return LoadLibError; return kLoadLibError;
if (!m_DyLibs.insert(DyLib).second) std::pair<std::set<llvm::sys::DynamicLibrary>::iterator, bool> insRes
return LoadLibExists; = m_DyLibs.insert(DyLib);
return LoadLibSuccess; if (!insRes.second)
return kLoadLibExists;
addLoadedFile(filename, LoadedFileInfo::kDynamicLibrary,
&(*insRes.first));
return kLoadLibSuccess;
} }
return LoadLibError; return kLoadLibError;
} }
Interpreter::LoadLibResult Interpreter::LoadLibResult
Interpreter::loadLibrary(const std::string& filename, bool permanent) { Interpreter::loadLibrary(const std::string& filename, bool permanent) {
LoadLibResult res = tryLinker(filename, permanent); LoadLibResult res = tryLinker(filename, permanent);
if (res != LoadLibError) { if (res != kLoadLibError) {
return res; return res;
} }
if (filename.compare(0, 3, "lib") == 0) { if (filename.compare(0, 3, "lib") == 0) {
// starts with "lib", try without (the llvm::Linker forces // starts with "lib", try without (the llvm::Linker forces
// a "lib" in front, which makes it liblib... // a "lib" in front, which makes it liblib...
res = tryLinker(filename.substr(3, std::string::npos), permanent); res = tryLinker(filename.substr(3, std::string::npos), permanent);
if (res != LoadLibError) if (res != kLoadLibError)
return res; return res;
} }
return LoadLibError; return kLoadLibError;
} }
void Interpreter::installLazyFunctionCreator(void* (*fp)(const std::string&)) { void Interpreter::installLazyFunctionCreator(void* (*fp)(const std::string&)) {

View File

@ -421,10 +421,20 @@ namespace cling {
PrintCommandHelp(); PrintCommandHelp();
return true; return true;
} }
else if (Command.equals("file")) { else if (Command.equals("fileEx")) {
PrintFileStats(); PrintFileStats();
return true; return true;
} }
else if (Command.equals("file")) {
typedef llvm::SmallVectorImpl<Interpreter::LoadedFileInfo*> 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; if (compRes) *compRes = Interpreter::kFailure;
return false; return false;