1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
|
/*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include <fstream>
#include <iostream>
#include <llvm/ExecutionEngine/ExecutionEngine.h>
#include <llvm/ExecutionEngine/ObjectCache.h>
#include <llvm/IR/IRBuilder.h>
#include <llvm/IR/LLVMContext.h>
#include <llvm/IR/Type.h>
#include <llvm/IR/Verifier.h>
#include <llvm/Support/CommandLine.h>
#include <llvm/Support/TargetRegistry.h>
#include <llvm/Object/ObjectFile.h>
#include <llvm/Support/TargetSelect.h>
#include "FN_llvm.hh"
#include "BLI_vector.hh"
namespace blender::fn {
const std::string object_file_path = "C:\\Users\\jacques\\Documents\\my_object.o";
class MyObjectCache : public llvm::ObjectCache {
void notifyObjectCompiled(const llvm::Module *module, llvm::MemoryBufferRef obj) override
{
std::cout << "Compiled Module: " << module->getName().str() << " - "
<< module->getModuleIdentifier() << "\n";
std::cout << "Size: " << obj.getBufferSize() << "\n";
std::ofstream f;
f.open(object_file_path, std::ofstream::out | std::ofstream::binary);
f.write(obj.getBufferStart(), obj.getBufferSize());
f.close();
}
std::unique_ptr<llvm::MemoryBuffer> getObject(const llvm::Module *module) override
{
//return {};
std::cout << "Request Cache: " << module->getName().str() << " - "
<< module->getModuleIdentifier() << "\n";
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> buffer_err = llvm::MemoryBuffer::getFile(object_file_path);
std::unique_ptr<llvm::MemoryBuffer> buffer = std::move(*buffer_err);
return buffer;
}
};
void playground()
{
static bool initialized = []() {
/* Set assembly syntax flavour. */
char const *args[] = {"some-random-name-for-the-parser", "--x86-asm-syntax=intel"};
llvm::cl::ParseCommandLineOptions(std::size(args), args);
llvm::InitializeNativeTarget();
llvm::InitializeNativeTargetAsmPrinter();
llvm::InitializeNativeTargetAsmParser();
return true;
}();
llvm::LLVMContext context;
std::unique_ptr<llvm::Module> module = std::make_unique<llvm::Module>("My Module", context);
llvm::Type *int32_type = llvm::Type::getInt32Ty(context);
llvm::FunctionType *function_type = llvm::FunctionType::get(
int32_type, {int32_type, int32_type}, false);
llvm::Function *function = llvm::Function::Create(
function_type, llvm::GlobalValue::LinkageTypes::ExternalLinkage, "My Func", *module);
llvm::BasicBlock *bb = llvm::BasicBlock::Create(context, "entry", function);
llvm::IRBuilder<> builder{bb};
llvm::Value *sum_value = builder.CreateAdd(function->getArg(0), function->getArg(1));
llvm::Value *product_value = builder.CreateMul(function->getArg(0), sum_value);
builder.CreateRet(product_value);
BLI_assert(!llvm::verifyModule(*module, &llvm::outs()));
MyObjectCache object_cache;
llvm::Expected<llvm::object::OwningBinary<llvm::object::ObjectFile>> object_file_ex = llvm::object::ObjectFile::createObjectFile(object_file_path);
if (!object_file_ex) {
return;
}
llvm::Module *module_ptr = &*module;
std::unique_ptr<llvm::ExecutionEngine> ee{llvm::EngineBuilder(std::move(module)).create()};
ee->addObjectFile(std::move(*object_file_ex));
//ee->setObjectCache(&object_cache);
ee->finalizeObject();
const uint64_t function_ptr = ee->getFunctionAddress(function->getName().str());
using FuncType = int (*)(int, int);
const FuncType generated_function = (FuncType)function_ptr;
const int result = generated_function(3, 5);
std::cout << result << "\n";
/*
LLVMTargetMachineEmitToFile((LLVMTargetMachineRef)ee->getTargetMachine(),
llvm::wrap(module_ptr),
(char *)"C:\\Users\\jacques\\Documents\\machine_code.txt",
LLVMAssemblyFile,
nullptr);
*/
// function->dump();
function->print(llvm::outs());
}
} // namespace blender::fn
|