Commit 141ed1e4 authored by Pierre Aubert's avatar Pierre Aubert
Browse files

Add base of generator for ProxyLoader

parent 73f89f10
......@@ -40,6 +40,14 @@ std::string getHandleFunctionType(const std::string & functionName){
return "FunctionTypehandle_" + functionName;
}
///Get the update type name of the given file
/** @param fileName : file name
* @return corresponding function name
*/
std::string getUpdateFunction(const std::string & fileName){
return "update_" + eraseExtension(fileName);
}
///Save the function prototype as an inline function
/** @param function : PFunction to be used
* @return corresponding string
......@@ -116,6 +124,8 @@ std::string cpp_backendHeader(PSource & source){
for(PVecFunction::iterator it(vecFunction.begin()); it != vecFunction.end(); ++it){
body += cpp_backendTableHeaderInline(*it);
}
body += "void " + getUpdateFunction(source.getName()) + "(void * handle);\n\n";
body += "#endif\n\n";
return body;
}
......@@ -140,7 +150,7 @@ std::string cpp_backendSource(PSource & source){
body += "///Update the all the function handles of the file\n";
body += "/**\t@param handle : pointer to loaded library\n";
body += "*/\n";
body += "void update_function_handle(void * handle){\n";
body += "void " + getUpdateFunction(source.getName()) + "(void * handle){\n";
for(PVecFunction::iterator it(vecFunction.begin()); it != vecFunction.end(); ++it){
if(!repr_isFunction(*it)){continue;}
//TODO : find a way to demangle the function name
......
......@@ -9,6 +9,8 @@
#include "Representation/representation.h"
std::string cpp_licenceSaveStr();
std::string getUpdateFunction(const std::string & fileName);
bool cpp_backend(PSource & source, const std::string & outputDir);
bool cpp_backend(PVecSource & vecSource, const std::string & outputDir);
......
/***************************************
Auteur : Pierre Aubert
Mail : aubertp7@gmail.com
Licence : CeCILL-C
****************************************/
#include "backend.h"
#include "string_utils.h"
#include "backend_proxy_loader.h"
///Create the Header definition of the ProxyLoader class
/** @param libraryName : name of the library to be created (to avoid multiple definition)
* @param className : name of the ProxyLoader class
* @return corresponding code
*/
std::string cpp_backendProxyLoaderHeader(const std::string & libraryName, const std::string & className){
std::string body(cpp_licenceSaveStr());
std::string baseMacro("__" + strToUpper(className) + "_H__");
body += "#ifndef " + baseMacro + "\n";
body += "#define " + baseMacro + "\n\n";
body += "#include <string>\n\n\n";
body += "///@brief Class which loads automatically the right sub-library of "+libraryName+"\n";
body += "class "+className+"{\n";
body += "\tpublic:\n";
body += "\t\t"+className+"();\n";
body += "\t\tvirtual ~"+className+"();\n";
body += "\t\t\n";
body += "\t\tbool load(const std::string & libName);\n";
body += "\t\tbool isOpen() const;\n";
body += "\t\tvoid close();\n";
body += "\t\t\n";
body += "\t\tvoid updateFunction();\n";
body += "\tprivate:\n";
body += "\t\tvoid initialisation"+className+"();\n";
body += "\t\t\n";
body += "\t\t///Handle of the library we load\n";
body += "\t\tvoid* p_handle;\n";
body += "};\n\n";
body += "#endif\n\n";
return body;
}
///Create the Source of the ProxyLoader class constructor
/** @param vecArchLib : vector of library to be loaded on the fly by respect to the host architecture
* @param className : name of the ProxyLoader class
* @return corresponding code
*/
std::string cpp_backendProxyLoaderConstructorSource(const PVecArchLib & vecArchLib, const std::string & className){
std::string body("");
body += "///Default constructor of "+className+"\n";
body += ""+className+"::"+className+"(){\n";
body += "\tinitialisation"+className+"();\n";
body += "\t//Let's simulate an architecture\n";
body += "\tint arch(2);\n";
body += "\t//Then we select the proper library based on the architecture\n";
//TODO : Here we use vecArchLib
body += "\tif(arch == 1){\n";
body += "\t\tload(CURRENT_LIB_DIR \"/liblibrary_arch1_ld_inline.so\");\n";
body += "\t}else{\n";
body += "\t\tload(CURRENT_LIB_DIR \"/liblibrary_arch2_ld_inline.so\");\n";
body += "\t}\n";
body += "\tupdateFunction();\n";
body += "}\n\n";
return body;
}
///Create the Source of the ProxyLoader class desctructor
/** @param vecArchLib : vector of library to be loaded on the fly by respect to the host architecture
* @param className : name of the ProxyLoader class
* @return corresponding code
*/
std::string cpp_backendProxyLoaderDesonstructorSource(const std::string & className){
std::string body("");
body += "///Destructor of "+className+"\n";
body += ""+className+"::~"+className+"(){\n";
body += "\tclose();\n";
body += "}\n\n";
return body;
}
///Create the Source of the ProxyLoader load
/** @param vecArchLib : vector of library to be loaded on the fly by respect to the host architecture
* @param className : name of the ProxyLoader class
* @return corresponding code
*/
std::string cpp_backendProxyLoaderLoadSource(const std::string & className){
std::string body("");
body += "///Load the given library\n";
body += "/**\t@param libName : name of the library to be loaded\n";
body += "* \t@return true on success, false otherwise\n";
body += "*/\n";
body += "bool "+className+"::load(const std::string & libName){\n";
body += "\tp_handle = dlopen(libName.c_str(), RTLD_LAZY);\n";
body += "\tstd::cout << \""+className+"::load : loading library '\"<<libName<<\"'\" << std::endl;\n";
body += "\tif(p_handle == NULL){\n";
body += "\t\tfprintf(stderr, \""+className+"::load : %s\\n\", dlerror());\n";
body += "\t\treturn false;\n";
body += "\t}\n";
body += "\tdlerror(); //Erase an exsiting error\n";
body += "\treturn true;\n";
body += "}\n\n";
return body;
}
///Create the Source of the ProxyLoader isOpen
/** @param className : name of the ProxyLoader class
* @return corresponding code
*/
std::string cpp_backendProxyLoaderIsOpenSource(const std::string & className){
std::string body("");
body += "///Say if the current library is opened or not\n";
body += "/**\t@return true if the current library is opened, false otherwise\n";
body += "*/\n";
body += "bool "+className+"::isOpen() const{\n";
body += "\treturn p_handle != NULL;\n";
body += "}\n\n";
return body;
}
///Create the Source of the ProxyLoader close
/** @param className : name of the ProxyLoader class
* @return corresponding code
*/
std::string cpp_backendProxyLoaderCloseSource(const std::string & className){
std::string body("");
body += "///Close the current library\n";
body += "void "+className+"::close(){\n";
body += "\tif(isOpen()){\n";
body += "\t\tdlclose(p_handle);\n";
body += "\t}\n";
body += "}\n\n";
return body;
}
///Create the Source of the ProxyLoader update
/** @param className : name of the ProxyLoader class
* @param vecSource : vector of source
* @return corresponding code
*/
std::string cpp_backendProxyLoaderUpdateSource(const std::string & className, const PVecSource & vecSource){
std::string body("");
body += "///Update the functions to be used\n";
body += "void "+className+"::updateFunction(){\n";
body += "\tif(!isOpen()){return;}\n";
body += "\t//Then set all the function pointers\n";
for(PVecSource::const_iterator it(vecSource.begin()); it != vecSource.end(); ++it){
body += "\t"+getUpdateFunction(it->getName())+"(p_handle);\n";
}
body += "}\n\n";
return body;
}
///Create the Source of the ProxyLoader initialisation
/** @param className : name of the ProxyLoader class
* @return corresponding code
*/
std::string cpp_backendProxyLoaderInitialisationSource(const std::string & className){
std::string body("");
body += "///Initialisation function of the class "+className+"\n";
body += "void "+className+"::initialisation"+className+"(){\n";
body += "\tp_handle = NULL;\n";
body += "}\n\n";
return body;
}
///Create the Source of the ProxyLoader class
/** @param vecSource : vector of source
* @param libraryName : name of the library to be created
* @param vecArchLib : vector of library to be loaded on the fly by respect to the host architecture
* @param className : name of the ProxyLoader class
* @return corresponding code
*/
std::string cpp_backendProxyLoaderSource(const PVecSource & vecSource, const std::string & libraryName, const PVecArchLib & vecArchLib,
const std::string & className)
{
std::string body(cpp_licenceSaveStr());
body += "#include <stdio.h>\n";
body += "#include <stdlib.h>\n";
body += "#include <dlfcn.h>\n\n";
for(PVecSource::const_iterator it(vecSource.begin()); it != vecSource.end(); ++it){
body += "#include \""+it->getName()+"\"\n";
}
body += "\n#include \""+className+".h\"\n\n";
body += "///Variable which will load automatically the right library by respect to the given architecture\n";
body += className + " PROXY_LOADER;\n\n";
body += cpp_backendProxyLoaderConstructorSource(vecArchLib, className);
body += cpp_backendProxyLoaderDesonstructorSource(className);
body += cpp_backendProxyLoaderLoadSource(className);
body += cpp_backendProxyLoaderIsOpenSource(className);
body += cpp_backendProxyLoaderCloseSource(className);
body += cpp_backendProxyLoaderUpdateSource(className, vecSource);
body += cpp_backendProxyLoaderInitialisationSource(className);
return body;
}
///Save ProxyLoader with the corresponding a vector of PSource in the output directory
/** @param vecSource : vector of source
* @param libraryName : name of the library to be created
* @param vecArchLib : vector of library to be loaded on the fly by respect to the host architecture
* @param outputDir : output directory where to save ProxyLoader
* @return true on success, false otherwise
*/
bool cpp_backend_proxy(const PVecSource & vecSource, const std::string & libraryName, const PVecArchLib & vecArchLib, const std::string & outputDir){
std::string className(firstToUpper(libraryName + "ProxyLoader"));
std::string headerSrc(cpp_backendProxyLoaderHeader(libraryName, className));
std::string sourceSrc(cpp_backendProxyLoaderSource(vecSource, libraryName, vecArchLib, className));
std::string outputHeaderFile(outputDir + "/" + className + ".h");
std::string outputSourceFile(outputDir + "/" + className + ".cpp");
if(!saveFileContent(outputHeaderFile, headerSrc)){
std::cerr << "cpp_backend : cannot save header file '"<<outputHeaderFile<<"'" << std::endl;
return false;
}
if(!saveFileContent(outputSourceFile, sourceSrc)){
std::cerr << "cpp_backend : cannot save source file '"<<outputSourceFile<<"'" << std::endl;
return false;
}
return true;
}
/***************************************
Auteur : Pierre Aubert
Mail : aubertp7@gmail.com
Licence : CeCILL-C
****************************************/
#ifndef __BACKEND_PROXY_LOADER_H__
#define __BACKEND_PROXY_LOADER_H__
#include "Representation/representation.h"
bool cpp_backend_proxy(const PVecSource & vecSource, const std::string & libraryName, const PVecArchLib & vecArchLib, const std::string & outputDir);
#endif
......@@ -367,3 +367,79 @@ void PSource::copyPSource(const PSource & other){
p_vecFunction = other.p_vecFunction;
}
///Constructor of class PArchLib
PArchLib::PArchLib(){
}
///Copy Constructor of class PArchLib
/** @param other : PArchLib we want ot copy
*/
PArchLib::PArchLib(const PArchLib & other){
copyPArchLib(other);
}
///Destructor of class PArchLib
PArchLib::~PArchLib(){
}
///Operator = of class PArchLib
/** @param other : PArchLib we want ot copy
* @return copied class PArchLib
*/
PArchLib & PArchLib::operator = (const PArchLib & other){
copyPArchLib(other);
return *this;
}
///Sets the name of the PArchLib
/** @param name : name of the PArchLib
*/
void PArchLib::setName(const std::string & name){
p_name = name;
}
///Sets the architecture of the PArchLib
/** @param architecture : architecture of the PArchLib
*/
void PArchLib::setArchitecture(const std::string & architecture){
p_architecture = architecture;
}
///Gets the name of the PArchLib
/** @return name of the PArchLib
*/
const std::string & PArchLib::getName() const{
return p_name;
}
///Gets the name of the PArchLib
/** @return name of the PArchLib
*/
std::string & PArchLib::getName(){
return p_name;
}
///Gets the architecture of the PArchLib
/** @return architecture of the PArchLib
*/
const std::string & PArchLib::getArchitecture() const{
return p_architecture;
}
///Gets the architecture of the PArchLib
/** @return architecture of the PArchLib
*/
std::string & PArchLib::getArchitecture(){
return p_architecture;
}
///Copy Function of class PArchLib
/** @param other : PArchLib we want ot copy
*/
void PArchLib::copyPArchLib(const PArchLib & other){
p_name = other.p_name;
p_architecture = other.p_architecture;
}
......@@ -106,6 +106,28 @@ class PSource{
std::vector<PFunction> p_vecFunction;
};
///@brief Library to be related to an architecture
class PArchLib{
public:
PArchLib();
PArchLib(const PArchLib & other);
virtual ~PArchLib();
PArchLib & operator = (const PArchLib & other);
void setName(const std::string & name);
void setArchitecture(const std::string & architecture);
const std::string & getName() const;
std::string & getName();
const std::string & getArchitecture() const;
std::string & getArchitecture();
protected:
void copyPArchLib(const PArchLib & other);
private:
///Name of the library
std::string p_name;
///Architecture of the library
std::string p_architecture;
};
#endif
......
......@@ -38,6 +38,13 @@ PSource{
std::vector<PFunction> vecFunction;
}
///@brief Library to be related to an architecture
PArchLib{
///Name of the library
std::string name;
///Architecture of the library
std::string architecture;
}
......@@ -14,6 +14,7 @@ typedef std::vector<size_t> PVecSizet;
typedef std::vector<PArgument> PVecArgument;
typedef std::vector<PFunction> PVecFunction;
typedef std::vector<PSource> PVecSource;
typedef std::vector<PArchLib> PVecArchLib;
bool repr_isFunction(const PFunction & fct);
......
......@@ -11,6 +11,7 @@
#include "FrontEnd/HeaderParser.h"
#include "BackEnd/backend.h"
#include "BackEnd/backend_proxy_loader.h"
using namespace std;
......@@ -23,6 +24,8 @@ OptionParser createOptionParser(){
parser.setExampleShortOption("phoenix_hpc_proxy -i file1.ph5 file1.ph5 fileN.ph5 -o output/dir/");
parser.addOption("input", "i", OptionType::FILENAME, true, "list of input files to be treated");
std::string libName("lib_shadok");
parser.addOption("library", "l", libName, "name of the library to be created");
std::string defaultOutputDir(".");
parser.addOption("output", "o", defaultOutputDir, "Output directory");
......@@ -32,10 +35,11 @@ OptionParser createOptionParser(){
///Create the source from configuration file
/** @param inputFile : name of the input file to be used
* @param libraryName : name of the library to be created
* @param outputDir : output directory to be used
* @return true on success, false otherwise
*/
bool createSourceFromConfig(const std::string & inputFile, const std::string & outputDir){
bool createSourceFromConfig(const std::string & inputFile, const std::string & libraryName, const std::string & outputDir){
HeaderParser parser;
if(!parser.load(inputFile)){
std::cerr << "createSourceFromConfig : cannot parse the input file '"<<inputFile<<"'" << std::endl;
......@@ -43,22 +47,29 @@ bool createSourceFromConfig(const std::string & inputFile, const std::string & o
}
PVecSource vecSource = parser.getVecSource();
bool b(cpp_backend(vecSource, outputDir));
PVecArchLib vecArchLib;
if(!b){
std::cerr << "createSourceFromConfig : cannot save source/header from input file '"<<inputFile<<"'" << std::endl;
return b;
}
b &= cpp_backend_proxy(vecSource, libraryName, vecArchLib, outputDir);
if(!b){
std::cerr << "createSourceFromConfig : cannot save source/header ProxyLoader class" << std::endl;
return b;
}
return b;
return true;
}
///Process all the input files
/** @param listInputFile : list of the input files
* @param libraryName : name of the library to be created
* @param outputDir : output directory to be used
* @return 0 on success, -1 otherwise
*/
int processFiles(const std::list<std::string> & listInputFile, const std::string & outputDir){
int processFiles(const std::list<std::string> & listInputFile, const std::string & libName, const std::string & outputDir){
bool b(true);
for(std::list<std::string>::const_iterator it(listInputFile.begin()); it != listInputFile.end(); ++it){
b &= createSourceFromConfig(*it, outputDir);
b &= createSourceFromConfig(*it, libName, outputDir);
}
return b - 1;
}
......@@ -71,10 +82,11 @@ int main(int argc, char** argv){
std::list<std::string> listInputFile;
defaultMode.getValue(listInputFile, "input");
std::string outputDir(".");
std::string outputDir("."), libName("");
defaultMode.getValue(outputDir, "output");
defaultMode.getValue(libName, "library");
return processFiles(listInputFile, outputDir);
return processFiles(listInputFile, libName, outputDir);
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment