Commit 230529c1 authored by Pierre Aubert's avatar Pierre Aubert
Browse files

Update mangle, architecture read and library load

parent 504af2c4
......@@ -130,11 +130,31 @@ std::string cpp_backendHeader(PSource & source){
return body;
}
///Get the mangled name of the given function name
/** @param libraryName : file name of the library to be used
* @param functionName : name of the function to be searched
* @return mangled name of the corresponding function
*/
std::string getMangleFunctionName(const std::string & libraryName, const std::string & functionName){
if(libraryName == ""){return functionName;}
std::string outputTmpFile(".mangledFunctionName.txt");
std::string command("objdump --syms "+libraryName+" | grep "+functionName+" | sed -e \"s/ /\\n/g\" | grep "+functionName+" | sed -e s/\\.cold//g | head -n 1 > "+outputTmpFile);
if(system(command.c_str()) != 0){
return "";
}
std::string mangleFunction(eraseCharsInStr(getFileContent(outputTmpFile), "\n\t "));
if(remove(outputTmpFile.c_str()) != 0){
std::cerr << "DPS::LibraryHandle::mangleFunctionName : cannot remove file '"<<outputTmpFile<<"'" << std::endl;
}
return mangleFunction;
}
///Save the source of the given PSource
/** @param source : PSource to be used
* @param libName : filename to a binary library
* @return corresponding string
*/
std::string cpp_backendSource(PSource & source){
std::string cpp_backendSource(PSource & source, const std::string & libName){
std::string body(cpp_licenceSaveStr());
body += "#include <stdio.h>\n";
body += "#include <stdlib.h>\n";
......@@ -153,8 +173,8 @@ std::string cpp_backendSource(PSource & source){
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
body += "\t"+getHandleFunction(it->getName())+" = ("+getHandleFunctionType(it->getName())+")(dlsym(handle, \""+it->getName()+"\"));\n";
std::string mangleFunction(getMangleFunctionName(libName, it->getName()));
body += "\t"+getHandleFunction(it->getName())+" = ("+getHandleFunctionType(it->getName())+")(dlsym(handle, \""+mangleFunction+"\"));\n";
}
body += "}\n\n";
return body;
......@@ -162,12 +182,13 @@ std::string cpp_backendSource(PSource & source){
///Save a vector of PSource in the output directory
/** @param source : source to be saved
* @param libName : filename to a binary library
* @param outputDir : output directory where to save PSource
* @return true on success, false otherwise
*/
bool cpp_backend(PSource & source, const std::string & outputDir){
bool cpp_backend(PSource & source, const std::string & libName, const std::string & outputDir){
std::string headerSrc(cpp_backendHeader(source));
std::string sourceSrc(cpp_backendSource(source));
std::string sourceSrc(cpp_backendSource(source, libName));
std::string baseFileName(eraseExtension(source.getName()));
std::string outputHeaderFile(outputDir + "/" + baseFileName + ".h");
std::string outputSourceFile(outputDir + "/" + baseFileName + ".cpp");
......@@ -175,22 +196,25 @@ bool cpp_backend(PSource & source, const std::string & outputDir){
std::cerr << "cpp_backend : cannot save header file '"<<outputHeaderFile<<"'" << std::endl;
return false;
}
std::cout << "cpp_backend : create header file '"<<outputHeaderFile<<"'" <<std::endl;
if(!saveFileContent(outputSourceFile, sourceSrc)){
std::cerr << "cpp_backend : cannot save source file '"<<outputSourceFile<<"'" << std::endl;
return false;
}
std::cout << "cpp_backend : create source file '"<<outputSourceFile<<"'" <<std::endl;
return true;
}
///Save a vector of PSource in the output directory
/** @param vecSource : vector of source
* @param libName : filename to a binary library
* @param outputDir : output directory where to save PSource
* @return true on success, false otherwise
*/
bool cpp_backend(PVecSource & vecSource, const std::string & outputDir){
bool cpp_backend(PVecSource & vecSource, const std::string & libName, const std::string & outputDir){
bool b(true);
for(PVecSource::iterator it(vecSource.begin()); it != vecSource.end(); ++it){
b &= cpp_backend(*it, outputDir);
b &= cpp_backend(*it, libName, outputDir);
}
return b;
}
......
......@@ -11,7 +11,7 @@
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);
bool cpp_backend(PSource & source, const std::string & libName, const std::string & outputDir);
bool cpp_backend(PVecSource & vecSource, const std::string & libName, const std::string & outputDir);
#endif
......@@ -26,6 +26,7 @@ std::string cpp_backendProxyLoaderHeader(const std::string & libraryName, const
body += "\t\tvirtual ~"+className+"();\n";
body += "\t\t\n";
body += "\t\tbool load(const std::string & libName);\n";
body += "\t\tbool parseArchFile(const std::string & archfileName);\n";
body += "\t\tbool isOpen() const;\n";
body += "\t\tvoid close();\n";
body += "\t\t\n";
......@@ -41,24 +42,19 @@ std::string cpp_backendProxyLoaderHeader(const std::string & libraryName, const
}
///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
/** @param className : name of the ProxyLoader class
* @param defaultLib : default library to be use if no extention was found
* @return corresponding code
*/
std::string cpp_backendProxyLoaderConstructorSource(const PVecArchLib & vecArchLib, const std::string & className){
std::string cpp_backendProxyLoaderConstructorSource(const std::string & className, const std::string & defaultLib){
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//First get the /proc/cpuinfo file\n";
body += "\tif(!parseArchFile(\"/proc/cpuinfo\")){\n";
body += "\t\t//No library found, let's load the default library\n";
body += "\t\tload(\""+defaultLib+"\");\n";
body += "\t}\n";
body += "\tupdateFunction();\n";
body += "}\n\n";
......@@ -66,8 +62,7 @@ std::string cpp_backendProxyLoaderConstructorSource(const PVecArchLib & vecArchL
}
///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
/** @param className : name of the ProxyLoader class
* @return corresponding code
*/
std::string cpp_backendProxyLoaderDesonstructorSource(const std::string & className){
......@@ -80,8 +75,7 @@ std::string cpp_backendProxyLoaderDesonstructorSource(const std::string & classN
}
///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
/** @param className : name of the ProxyLoader class
* @return corresponding code
*/
std::string cpp_backendProxyLoaderLoadSource(const std::string & className){
......@@ -91,6 +85,7 @@ std::string cpp_backendProxyLoaderLoadSource(const std::string & className){
body += "* \t@return true on success, false otherwise\n";
body += "*/\n";
body += "bool "+className+"::load(const std::string & libName){\n";
body += "\tif(libName == \"\"){return false;}\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";
......@@ -103,6 +98,52 @@ std::string cpp_backendProxyLoaderLoadSource(const std::string & className){
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_backendProxyLoaderParseArchFileSource(const PVecArchLib & vecArchLib, const std::string & className){
std::string body("");
body += "///Parse the given architecture file\n";
body += "/**\t@param archfileName : name of the architecture file to be loaded\n";
body += "* \t@return true on success, false otherwise\n";
body += "*/\n";
body += "bool "+className+"::parseArchFile(const std::string & archfileName){\n";
body += "\tFILE * fp = fopen(archfileName.c_str(), \"r\");\n";
body += "\tif(fp == NULL){\n";
body += "\t\tstd::cerr << \"Cannot open file '/proc/cpuinfo'\" << std::endl;\n";
body += "\t\treturn false;\n";
body += "\t}\n";
body += "\t//Let's get the file size\n";
body += "\tfseek(fs, 0, SEEK_END);\n";
body += "\tsize_t fileSize(ftell(fs));\n";
body += "\tfseek(fs, 0, SEEK_SET);\n";
body += "\tif(fileSize == 0lu){\n";
body += "\t\treturn false;\n";
body += "\t}\n";
body += "\t//Now we can alloate the table to get the file content\n";
body += "\tchar * procCpuInfo = new char[fileSize];\n";
body += "\t//And load the file\n";
body += "\tif(fread(procCpuInfo, sizeof(char), fileSize, fp) != fileSize){return false;}\n";
body += "\t//Let's check the avalaible architectures\n";
std::string strElse("");
for(PVecArchLib::const_reverse_iterator it(vecArchLib.rbegin()); it != vecArchLib.rend(); ++it){
body += "\t" + strElse + "if(strstr(procCpuInfo, \""+it->getArchitecture()+"\") != NULL){\n";
std::string libName(getFileName(it->getName()));
body += "\t\tload(\""+libName+"\");\n";
body += "\t}";
strElse = "else ";
}
body += "\n";
body += "\tfclose(fp);\n";
body += "\tdelete [] procCpuInfo;\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
......@@ -166,12 +207,11 @@ std::string cpp_backendProxyLoaderInitialisationSource(const std::string & class
///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,
std::string cpp_backendProxyLoaderSource(const PVecSource & vecSource, const PVecArchLib & vecArchLib,
const std::string & className)
{
std::string body(cpp_licenceSaveStr());
......@@ -185,10 +225,11 @@ std::string cpp_backendProxyLoaderSource(const PVecSource & vecSource, const std
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);
std::string defaultLib(getLibraryFile(vecArchLib));
body += cpp_backendProxyLoaderConstructorSource(className, defaultLib);
body += cpp_backendProxyLoaderDesonstructorSource(className);
body += cpp_backendProxyLoaderLoadSource(className);
body += cpp_backendProxyLoaderParseArchFileSource(vecArchLib, className);
body += cpp_backendProxyLoaderIsOpenSource(className);
body += cpp_backendProxyLoaderCloseSource(className);
body += cpp_backendProxyLoaderUpdateSource(className, vecSource);
......@@ -206,7 +247,7 @@ std::string cpp_backendProxyLoaderSource(const PVecSource & vecSource, const std
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 sourceSrc(cpp_backendProxyLoaderSource(vecSource, vecArchLib, className));
std::string outputHeaderFile(outputDir + "/" + className + ".h");
std::string outputSourceFile(outputDir + "/" + className + ".cpp");
if(!saveFileContent(outputHeaderFile, headerSrc)){
......
......@@ -37,3 +37,17 @@ void addArch(PVecArchLib & vecArch, const std::string & arch, const std::string
}
}
///Get the first non empty library file name
/** @param vecArch : vector of architecture
* @return library file name or empty string if none is found
*/
std::string getLibraryFile(const PVecArchLib & vecArch){
std::string libName("");
PVecArchLib::const_iterator it(vecArch.begin());
while(it != vecArch.end() && libName == ""){
libName = it->getName();
++it;
}
return libName;
}
......@@ -21,4 +21,6 @@ bool repr_isFunction(const PFunction & fct);
PArchLib createArchLib(const std::string & arch, const std::string & libName);
void addArch(PVecArchLib & vecArch, const std::string & arch, const std::string & libName);
std::string getLibraryFile(const PVecArchLib & vecArch);
#endif
......@@ -27,16 +27,16 @@ OptionParser createOptionParser(){
std::string libName("lib_shadok");
parser.addOption("library", "l", libName, "name of the library to be created");
parser.addOption("anyarch", "", OptionType::FILENAME, false, "file name of the library to be used for any architectures (kind of security if the other architectures are not found)");
parser.addOption("sse", "", OptionType::FILENAME, false, "file name of the library to be used for sse architecture");
parser.addOption("sse2", "", OptionType::FILENAME, false, "file name of the library to be used for sse2 architecture");
parser.addOption("ssse3", "", OptionType::FILENAME, false, "file name of the library to be used for ssse3 architecture");
parser.addOption("sse4.1", "", OptionType::FILENAME, false, "file name of the library to be used for sse4.1 architecture");
parser.addOption("sse4.2", "", OptionType::FILENAME, false, "file name of the library to be used for sse4.2 architecture");
parser.addOption("avx", "", OptionType::FILENAME, false, "file name of the library to be used for avx architecture");
parser.addOption("avx2", "", OptionType::FILENAME, false, "file name of the library to be used for avx2 architecture");
parser.addOption("avx512f", "", OptionType::FILENAME, false, "file name of the library to be used for avx512f architecture");
parser.addOption("avx512wb", "", OptionType::FILENAME, false, "file name of the library to be used for avx512wb architecture");
parser.addOption("anyarch", "a", OptionType::FILENAME, false, "file name of the library to be used for any architectures (kind of security if the other architectures are not found)");
parser.addOption("sse", "b", OptionType::FILENAME, false, "file name of the library to be used for sse architecture");
parser.addOption("sse2", "c", OptionType::FILENAME, false, "file name of the library to be used for sse2 architecture");
parser.addOption("ssse3", "d", OptionType::FILENAME, false, "file name of the library to be used for ssse3 architecture");
parser.addOption("sse4.1", "e", OptionType::FILENAME, false, "file name of the library to be used for sse4.1 architecture");
parser.addOption("sse4.2", "f", OptionType::FILENAME, false, "file name of the library to be used for sse4.2 architecture");
parser.addOption("avx", "g", OptionType::FILENAME, false, "file name of the library to be used for avx architecture");
parser.addOption("avx2", "j", OptionType::FILENAME, false, "file name of the library to be used for avx2 architecture");
parser.addOption("avx512f", "k", OptionType::FILENAME, false, "file name of the library to be used for avx512f architecture");
parser.addOption("avx512wb", "m", OptionType::FILENAME, false, "file name of the library to be used for avx512wb architecture");
std::string defaultOutputDir(".");
......@@ -87,8 +87,13 @@ bool createSourceFromConfig(const std::string & inputFile, const std::string & l
std::cerr << "createSourceFromConfig : cannot parse the input file '"<<inputFile<<"'" << std::endl;
return false;
}
std::string libName(getLibraryFile(vecArchLib));
PVecSource vecSource = parser.getVecSource();
bool b(cpp_backend(vecSource, outputDir));
if(vecSource.size() == 0lu){
std::cerr << "createSourceFromConfig : no source to be created" << std::endl;
return false;
}
bool b(cpp_backend(vecSource, libName, outputDir));
if(!b){
std::cerr << "createSourceFromConfig : cannot save source/header from input file '"<<inputFile<<"'" << std::endl;
return b;
......@@ -122,14 +127,14 @@ int main(int argc, char** argv){
const OptionMode & defaultMode = parser.getDefaultMode();
std::list<std::string> listInputFile;
defaultMode.getValue(listInputFile, "input");
defaultMode.getValue(listInputFile, "header");
std::string outputDir("."), libName("");
defaultMode.getValue(outputDir, "output");
defaultMode.getValue(libName, "library");
PVecArchLib vecArchLib;
parseVecArchLib(vecArchLib, defaultMode);
// parseVecArchLib(vecArchLib, defaultMode);
return processFiles(listInputFile, libName, vecArchLib, 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