Как использовать jit_type_nfloat в библиотеке libjit c? - PullRequest
0 голосов
/ 27 октября 2019

Я столкнулся с действительно странным поведением библиотеки 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. Но это не работает, как вы могли видеть из приведенного выше вывода.

В чем причина этого? Что я делаю не так?

...