Я столкнулся с действительно странным поведением библиотеки libjit
.
В моей задаче необходимо использовать массивы long double
. Я играл с массивами libjit и обнаружил, что не могу заставить libjit
работать с длинными двойными массивами. Кажется, он отлично работает с int
, float32
, float64
, но не с sys_long_double
или nfloat
.
У меня есть следующий пример. Это довольно просто. Есть одна функция, которая принимает аргумент x
, помещает его в array[0]
и возвращает array[0]
(который в основном равен x
).
#include <stdio.h>
#include <jit/jit.h>
// Text replacement float64 -> nfloat, and it doesn't work anymore.
int main(int argc, char **argv)
{
jit_context_t context;
jit_type_t params[1];
jit_type_t signature;
jit_function_t function;
jit_value_t x;
/* Create a context to hold the JIT's primary state */
context = jit_context_create();
/* Lock the context while we build and compile the function */
jit_context_build_start(context);
/* Build the function signature */
params[0] = jit_type_float64;
signature = jit_type_create_signature
(jit_abi_cdecl, jit_type_float64, params, 1, 1);
/* Create the function object */
function = jit_function_create(context, signature);
/* Construct the function body */
x = jit_value_get_param(function, 0);
jit_value_t size = jit_value_create_nint_constant(function, jit_type_int, 256);
jit_value_t res = jit_insn_alloca(function, size);
jit_value_t i = jit_value_create_nint_constant(function, jit_type_int, 0);
jit_insn_store_elem(function, res, i, x);
jit_value_t answer = jit_insn_load_elem(function, res, i, jit_type_float64);
jit_insn_return(function, answer);
/* Compile the function */
jit_function_compile(function);
/* Unlock the context */
jit_context_build_end(context);
/* Execute the function and print the result */
jit_float64 arg1;
void *args[1];
jit_float64 result;
arg1 = 3.0;
args[0] = &arg1;
jit_function_apply(function, args, &result);
printf("answer = %Lf\n", (long double)result);
/* Clean up */
jit_context_destroy(context);
/* Finished */
return 0;
}
Мой Makefile:
app: app.c
gcc $< -ljit -lpthread -lm -ldl -o $@
Приведенный выше пример хорошо работает и выдает:
vagrant@jits-host:/vagrant$ make
gcc app.c -ljit -lpthread -lm -ldl -o app
vagrant@jits-host:/vagrant$ ./app
answer = 3.000000
Но как только я заменяю float64
на nfloat
илиsys_long_double
, это больше не работает. Кроме того, он печатает некоторые странные вещи для отладки. После замены:
#include <stdio.h>
#include <jit/jit.h>
int main(int argc, char **argv)
{
jit_context_t context;
jit_type_t params[1];
jit_type_t signature;
jit_function_t function;
jit_value_t x;
/* Create a context to hold the JIT's primary state */
context = jit_context_create();
/* Lock the context while we build and compile the function */
jit_context_build_start(context);
/* Build the function signature */
params[0] = jit_type_nfloat;
signature = jit_type_create_signature
(jit_abi_cdecl, jit_type_nfloat, params, 1, 1);
/* Create the function object */
function = jit_function_create(context, signature);
/* Construct the function body */
x = jit_value_get_param(function, 0);
jit_value_t size = jit_value_create_nint_constant(function, jit_type_int, 256);
jit_value_t res = jit_insn_alloca(function, size);
jit_value_t i = jit_value_create_nint_constant(function, jit_type_int, 0);
jit_insn_store_elem(function, res, i, x);
jit_value_t answer = jit_insn_load_elem(function, res, i, jit_type_nfloat);
jit_insn_return(function, answer);
/* Compile the function */
jit_function_compile(function);
/* Unlock the context */
jit_context_build_end(context);
/* Execute the function and print the result */
jit_nfloat arg1;
void *args[1];
jit_nfloat result;
arg1 = 3.0;
args[0] = &arg1;
jit_function_apply(function, args, &result);
printf("answer = %Lf\n", (long double)result);
/* Clean up */
jit_context_destroy(context);
/* Finished */
return 0;
}
Результат:
vagrant@jits-host:/vagrant$ make
gcc app.c -ljit -lpthread -lm -ldl -o app
vagrant@jits-host:/vagrant$ ./app
TODO(19b) at jit-rules-x86-64.c, 3194
answer = 0.000000
Чего мне не хватает? Должен ли я скомпилировать его по-другому?
Одно важное замечание: похоже, типы arg1
и result
действительно важны. Когда я использую float32
, они должны быть float
или jit_float32
. Когда я использую float64
, они должны быть double
или jit_float64
. Я ожидал абсолютно то же самое при использовании nfloat
или sys_long_double
. Их размеры составляют 16 байтов. Я пытался сделать arg1
и result
оба long double
и jit_nfloat
. Но это не работает, как вы могли видеть из приведенного выше вывода.
В чем причина этого? Что я делаю не так?