ETISS 0.11.2
ExtendableTranslatingInstructionSetSimulator(version0.11.2)
Loading...
Searching...
No Matches
GCCJIT.cpp
Go to the documentation of this file.
1// SPDX-License-Identifier: BSD-3-Clause
2//
3// This file is part of ETISS. It is licensed under the BSD 3-Clause License; you may not use this file except in
4// compliance with the License. You should have received a copy of the license along with this project. If not, see the
5// LICENSE file.
6
7#include "GCCJIT.h"
8
9#include <cstdlib>
10#include <cstring>
11#include <dlfcn.h>
12#include <fstream>
13#include <iostream>
14#include <sstream>
15#include <stdlib.h> //mkdtemp
16#include <unistd.h>
17
18GCCJIT::GCCJIT(bool cleanup, std::string opt_level, bool quiet)
19 : etiss::JIT("gcc"), cleanup_(cleanup), opt_level_(opt_level), quiet_(quiet)
20{
21
22 id = 0;
23
24 if (system(std::string("mkdir -p \"./tmp\"").c_str()))
25 std::cerr << "ERROR: GCCJIT failed to create ./tmp folder. this may lead to a failure to compile code."
26 << std::endl;
27
28 path_ = "./tmp/XXXXXX";
29 // create unique folder (mkdtemp)
30 {
31 if (mkdtemp(&path_[0]) == 0)
32 {
33 std::cerr << "ERROR: GCCJIT failed to get unique working folder. Resulting compilations my be unrelyable"
34 << std::endl;
35 }
36
37 if (system(std::string("mkdir -p \"" + path_ + "\"").c_str())) // make folder if not present
38 std::cerr << "ERROR: GCCJIT failed to create compilation path. this may lead to a failure to compile code."
39 << std::endl;
40 }
41 path_ = path_ + "/";
42}
43
45{
46 if (cleanup_)
47 if (path_.substr(0, 6) == "./tmp/") // check path before recursive delete operation
48 if (system(std::string("rm -R \"" + path_ + "\"").c_str()))
49 std::cerr << "ERROR: GCCJIT failed to clean up compilation files located in " << path_ << std::endl;
50}
51
52void *GCCJIT::translate(std::string code, std::set<std::string> headerpaths, std::set<std::string> librarypaths,
53 std::set<std::string> libraries, std::string &error, bool debug)
54{
55
56 if (system(NULL) == 0)
57 {
58 error = "system command execution not available";
59 return 0;
60 }
61
62 unsigned lid = id++;
63
64 std::string codefilename;
65 {
66 std::ofstream codeFile;
67 std::stringstream ss;
68 ss << "code_" << lid;
69 codefilename = ss.str();
70 codeFile.open((path_ + codefilename + std::string(".c")).c_str());
71 if (!codeFile.is_open())
72 {
73 error = "failed to create code file";
74 return 0;
75 }
76 codeFile << code;
77 codeFile.flush();
78 codeFile.close();
79 }
80 std::stringstream ss;
81 ss << "gcc -c -std=c99 -fPIC -march=native -mtune=native -pipe ";
82 if (quiet_)
83 ss << "-w ";
84 if (debug)
85 ss << "-g -O0 -Wall -Wno-unused-label ";
86 else
87 ss << "-O" + opt_level_ + " ";
88 for (std::set<std::string>::const_iterator iter = headerpaths.begin(); iter != headerpaths.end(); iter++)
89 {
90 ss << "-I\"" << *iter << "\" ";
91 }
92 ss << path_ << codefilename << ".c"
93 << " -o " << path_ << codefilename << ".o";
94
95 // std::cout << "EXECUTING: " << ss.str() << std::endl;
96
97 int eval = system(ss.str().c_str());
98 // std::cout << eval << std::endl;
99
100 if (eval != 0)
101 {
102 std::cout << "compiler failed with code: " << eval << std::endl;
103 }
104
105 ss.str("");
106
107 ss << "gcc -shared ";
108 /*
109 if (debug)
110 ss <<"-g -dl ";
111 */
112
113 for (std::set<std::string>::const_iterator iter = librarypaths.begin(); iter != librarypaths.end(); iter++)
114 {
115 ss << " -L" << *iter << " ";
116 }
117
118 ss << " -o " << path_ << "lib" << codefilename << ".so " << path_ << codefilename << ".o ";
119
120 for (std::set<std::string>::const_iterator iter = libraries.begin(); iter != libraries.end(); iter++)
121 {
122 ss << " -l\"" << *iter << "\" ";
123 }
124
125 if (!librarypaths.empty())
126 ss << "-Wl";
127
128 for (std::set<std::string>::const_iterator iter = librarypaths.begin(); iter != librarypaths.end(); iter++)
129 {
130 ss << ",-rpath," << *iter;
131 }
132
133 // std::cout << "EXECUTING: " << ss.str() << std::endl;
134 eval = system(ss.str().c_str());
135 // std::cout << eval << std::endl;
136
137 if (eval != 0)
138 {
139 std::cout << "compiler failed with code: " << eval << std::endl;
140 }
141
142 void *lib = dlopen((path_ + "lib" + codefilename + std::string(".so")).c_str(), RTLD_NOW | RTLD_LOCAL);
143
144 if (lib == 0)
145 {
146 error = dlerror();
147 return 0;
148 }
149
150 return lib;
151}
152void *GCCJIT::getFunction(void *handle, std::string name, std::string &error)
153{
154 void *ret = dlsym(handle, name.c_str());
155 if (ret == 0)
156 {
157 error = dlerror();
158 return 0;
159 }
160 return ret;
161}
162void GCCJIT::free(void *handle)
163{
164 dlclose(handle);
165}
std::string opt_level_
Definition GCCJIT.h:28
bool cleanup_
Definition GCCJIT.h:27
virtual void free(void *handle)
clean up handled returned by etiss::JIT::translate
Definition GCCJIT.cpp:162
virtual void * translate(std::string code, std::set< std::string > headerpaths, std::set< std::string > librarypaths, std::set< std::string > libraries, std::string &error, bool debug=false)
translate C code to executable code and return a handle/pointer that identifies the compilation resul...
Definition GCCJIT.cpp:52
std::string path_
Definition GCCJIT.h:26
bool quiet_
Definition GCCJIT.h:29
virtual void * getFunction(void *handle, std::string name, std::string &error)
returns a function pointer to a compiled function from the handle returned by etiss::JIT::translate
Definition GCCJIT.cpp:152
GCCJIT(bool cleanup=true, std::string opt_level="fast", bool quiet=false)
Definition GCCJIT.cpp:18
virtual ~GCCJIT()
Definition GCCJIT.cpp:44
forwards: include/jit/*
Definition Benchmark.h:17
#define NULL