Created
July 19, 2020 13:34
-
-
Save Huud/5a8f5f0a16ed6df25364ecdfc2465674 to your computer and use it in GitHub Desktop.
An esample code that generates C++ code and compiles it to a DLL file then uses it.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#define _CRT_SECURE_NO_WARNINGS | |
#include <iostream> | |
#include <fstream> | |
#include <random> | |
#include <cmath> | |
#include <string> | |
#include <chrono> | |
#include <vector> | |
#include <windows.h> | |
using namespace std; | |
// Instructions implementation | |
void add(int &a, int &b, int &c) { c = a + b; } | |
void sub(int &a, int &b, int &c) { b = c - b; } | |
void mult(int &a, int &b, int &c) { a = c * b; } | |
void divide(int &a, int &b, int &c) { if (a!=0) c = b / a; } | |
void inc(int &a, int &b, int &c) { a++; b++; c++; } | |
void print(int c) { cout << c << endl; } | |
typedef void(*funcPointer)(int&,int&,int&); // function pointer used to get the function from the dll | |
int main() | |
{ | |
int a = 50; // some random initialization | |
int b = 200; | |
int c = 3; | |
std::random_device seedDevice; | |
std::mt19937 rEngine(seedDevice()); | |
std::uniform_int_distribution<int> InstNumDist(100000, 200000); | |
std::uniform_int_distribution<int> InstOpcodeDist(1, 5); | |
int numberOfInst = InstNumDist(rEngine); | |
vector<int> input; | |
for (int i = 0; i != numberOfInst; i++) // emulate user input with random numbers | |
input.push_back(InstOpcodeDist(rEngine)); | |
/// Interpreter | |
auto interpreterStart = chrono::steady_clock::now(); | |
for (int i = 0; i != input.size(); i++) | |
{ | |
switch (input[i]) | |
{ | |
case 1: add(a, b, c); break; | |
case 2: sub(a, b, c); break; | |
case 3: mult(a, b, c); break; | |
case 4: divide(a, b, c); break; | |
case 5: inc(a, b, c); break; | |
case 6: print(c); break; | |
} | |
} | |
cout << "Interpreter: " << endl << "a = " << a << endl; cout << "b = " << b << endl; cout << "c = " << c << endl; | |
auto interpreterEnd = chrono::steady_clock::now(); | |
cout << "Interpreter took " << chrono::duration <double, milli>(interpreterEnd - interpreterStart).count() << " ms" << endl; | |
/// Recompiler: | |
a = 50; // Same initial state | |
b = 200; | |
c = 3; | |
ofstream CompileFile; | |
CompileFile.open("GeneratedCode.cpp"); | |
CompileFile << R"( | |
#include <iostream> | |
extern "C" | |
{ | |
void __declspec(dllexport) GeneratedCode(int &a, int &b, int &c) | |
{ | |
)" << '\n'; | |
// Code Generation | |
for (int i = 0; i != input.size(); i++) | |
{ | |
switch (input[i]) | |
{ | |
case 1: CompileFile << "c = a + b;\n"; break; | |
case 2: CompileFile << "b = c - b;\n"; break; | |
case 3: CompileFile << "a = c * b;\n"; break; | |
case 4: CompileFile << "if (a != 0) c = b / a;\n"; break; | |
case 5: CompileFile << "a++; b++; c++;\n"; break; | |
case 6: print(c); break; | |
} | |
} | |
CompileFile << R"( | |
} | |
} | |
)" << '\n'; | |
CompileFile.close(); // call before compiling | |
auto compilerStart = chrono::steady_clock::now(); | |
// compile the generated code as dll | |
system(R"(call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" && cl /LD GeneratedCode.cpp)"); | |
auto compilerEnd = chrono::steady_clock::now(); | |
cout << "Compilation took " << chrono::duration <double, milli>(compilerEnd - compilerStart).count() << " ms" << endl; | |
HINSTANCE calledCode = LoadLibrary("GeneratedCode.dll"); | |
if (!calledCode) { | |
cout << "Import dll failed" << endl; | |
system("pause"); | |
return EXIT_FAILURE; | |
} | |
else | |
std::cout << "Import dll succeeded" << std::endl; | |
funcPointer fp = (funcPointer)GetProcAddress(calledCode, "GeneratedCode"); // get the function from the dll | |
if (!fp) | |
{ | |
cout << "dll function get failed" << endl; | |
system("pause"); | |
return EXIT_FAILURE; | |
} | |
auto recompilerStart = chrono::steady_clock::now(); | |
fp(a,b,c); // execute the dll function | |
auto recompilerEnd = chrono::steady_clock::now(); | |
cout << "Recompiler took " << chrono::duration <double, milli>(recompilerEnd - recompilerStart).count() << " ms" << endl; | |
cout << "Recompiler: " << endl << "a = " << a << endl; cout << "b = " << b << endl; cout << "c = " << c << endl; | |
system("pause"); | |
return 0; | |
} | |
// output: | |
/* | |
Interpreter: | |
a = 19 | |
b = 4 | |
c = 1 | |
Interpreter took 74.4546 ms | |
*several lines of compiler log* | |
out:GeneratedCode.dll | |
Compilation took 12320.2 ms | |
Import dll succeeded | |
Recompiler took 3.27327 ms | |
Recompiler: | |
a = 19 | |
b = 4 | |
c = 1 | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment