Добавление объектного файла в JIT и вызов его из IR-кодаC++

Программы на C++. Форум разработчиков
Ответить
Anonymous
 Добавление объектного файла в JIT и вызов его из IR-кода

Сообщение Anonymous »

Я создал модифицированную версию HowToUseJIT.cpp (llvm версии 11.x), которая использует класс IRBuilder для создания функции, вызывающей внешний объект, определенный в общем объектном файле.
Этот пример отлично работает (в моей системе), когда внешний аргумент имеет аргумент int и возвращаемое значение, но не работает, когда аргумент и возвращаемое значение имеют двойное значение. >
Исходный код для случая int указан ниже. Кроме того, в исходном коде вверху есть инструкции по преобразованию его в двойной регистр.
Что не так с двойной версией этого примера?
/*
This file is a modified version of the llvm 11.x example HowToUseJIT.cpp:

The file callee.c contains the following text:
int callee(int arg)
{ return arg + 1; }

The shared library callee.so is created from callee.c as follows:
clang -shared callee.c -o callee.so

This example calls the funciton callee from a function that is generated using
the IRBuilder class. It links callee by loading callee.so into its LLJIT.

This works on my sytesm where the progam output is
add1(42) = 43
which is correct.

If I change the type of the function callee from "int (*)(int)" to
"double (*)(double)", the program output is
add1(42) = 4.200000e+01
which is incorrect.

I use following command to change callee.c so that it uses double:
sed -i callee.c \
-e 's|int callee(int arg)|double callee(double arg)|' \
-e 's|return arg + 1;|return arg + 1.0;|'

I use the following command to change this file so that it should porperly
link to the double version of callee:
sed -i add_obj2jit.cpp \
-e '30,$s|"int"|"double"|' \
-e '30,$s|getInt32Ty|getDoubleTy|g' \
-e '/getAddress/s|int|double|g' \
-e 's|int Result = Add1(42);|double Result = Add1(42.0);|

What is wrong with the double version of this example ?
*/
#include "llvm/ExecutionEngine/Orc/LLJIT.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/InitLLVM.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Support/raw_ostream.h"

using namespace llvm;
using namespace llvm::orc;

ExitOnError ExitOnErr;

// --------------------------------------------------------------------------
void add_obj2jit(LLJIT* jit, const std::string filename)
{ // load object file into memory_buffer
ErrorOr< std::unique_ptr > error_or_buffer =
MemoryBuffer::getFile(filename);
std::error_code std_error_code = error_or_buffer.getError();
if( std_error_code )
{ std::string msg = "add_obj2jit: " + filename + "\n";
msg += std_error_code.message();
std::fprintf(stderr, "%s\n", msg.c_str() );
std::exit( std_error_code.value() );
}
std::unique_ptr memory_buffer(
std::move( error_or_buffer.get() )
);
// move object file into jit
Error error = jit->addObjectFile( std::move(memory_buffer) );
if( error )
{ std::fprintf(stderr, "Can't load object file %s", filename.c_str());
std::exit(1);
}
}
// --------------------------------------------------------------------------
ThreadSafeModule createDemoModule() {
auto Context = std::make_unique();
auto M = std::make_unique("test", *Context);

// functiont_t
// function has a return type of "int" and take an argument of "int".
FunctionType* function_t = FunctionType::get(
Type::getInt32Ty(*Context), {Type::getInt32Ty(*Context)}, false
);

// declare the callee function
AttributeList empty_attributes;
FunctionCallee callee = M->getOrInsertFunction(
"callee", function_t, empty_attributes
);

// Create the add1 function entry and insert this entry into module M.
Function *Add1F = Function::Create(
function_t, Function::ExternalLinkage, "add1", M.get()
);

// Add a basic block to the function. As before, it automatically inserts
// because of the last argument.
BasicBlock *BB = BasicBlock::Create(*Context, "EntryBlock", Add1F);

// Create a basic block builder with default parameters. The builder will
// automatically append instructions to the basic block `BB'.
IRBuilder builder(BB);

// Get pointers to the integer argument of the add1 function...
assert(Add1F->arg_begin() +1 == Add1F->arg_end()); // Make sure there's an arg
Argument *ArgX = &*Add1F->arg_begin(); // Get the arg
ArgX->setName("AnArg"); // Give it a nice symbolic name for fun.

// Create the call instruction, inserting it into the end of BB.
Value *Add = builder.CreateCall( callee, {ArgX}, "Add=callee(ArgX)" );

// Create the return instruction and add it to the basic block
builder.CreateRet(Add);

return ThreadSafeModule(std::move(M), std::move(Context));
}
// --------------------------------------------------------------------------
int main(int argc, char *argv[]) {
// Initialize LLVM.
InitLLVM X(argc, argv);

InitializeNativeTarget();
InitializeNativeTargetAsmPrinter();

cl::ParseCommandLineOptions(argc, argv, "add_obj2jit");
ExitOnErr.setBanner(std::string(argv[0]) + ": ");

// Create an LLJIT instance.
auto J = ExitOnErr(LLJITBuilder().create());
auto M = createDemoModule();

ExitOnErr(J->addIRModule(std::move(M)));

add_obj2jit(J.get(), "callee.so");

// Look up the JIT'd function, cast it to a function pointer, then call it.
auto Add1Sym = ExitOnErr(J->lookup("add1"));
int (*Add1)(int) = (int (*)(int))Add1Sym.getAddress();

int Result = Add1(42);
outs()

Подробнее здесь: https://stackoverflow.com/questions/666 ... om-ir-code
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C++»