chasep255
chasep255

Reputation: 12175

GCCJIT, get the size of a type

Given a gcc_jit_type pointer is there any way to get its size? I have been looking over the documentation and I can't really find an example of something like the sizeof operator. I would like to write a kind of generic data structure which is given a gcc_jit_type and compiles itself from that. Kind of hard to do if I don't know the size of the type.

Upvotes: 4

Views: 249

Answers (2)

antoyo
antoyo

Reputation: 11913

Since libgccjit 14, you now have an API function called gcc_jit_context_new_sizeof where you can give it a type and you get a runtime value representing its size:

gcc_jit_rvalue* size = gcc_jit_context_new_sizeof(ctxt, my_type);

Upvotes: 1

chasep255
chasep255

Reputation: 12175

I managed to hack together a solution but I feel like it was way harder than it should have been. There definitely should something like gcc_jit_type_sizeof(...) function added to the api in my opinion.

I realized that in C code sizeof(T) = (size_t)(1 + (T*)0) so I tried to implement this with gccjit. In doing do I realized there is no real way to increment a pointer given the api. I tried to use the addition binary opp but this gave me an error since both operands need to be of the same type. Adding an int to a pointer is invalid in gccjit. I tried assigning one pointer to zero and another to one and adding those but that gave a strange result. I guess this makes sense since (int*)0 + (int*)1 is a compile error in C.

The next thing I tried was the this C equivalent (size_t)&((T*)0)[1] - (size_t)((T*)0) which also failed to compile becase in gccjit you can't cast a pointer type to an int either. I finally got it to work by changing it to (char*)&((T*)0)[1] - (char*)((T*)0) since you can cast a pointer to another pointer type.

gcc_jit_rvalue* jit_sizeof(gcc_jit_context* ctx, gcc_jit_type* t)
{   
    const void* NULL_PTR = 0;

    gcc_jit_type* t_ptr_type = gcc_jit_type_get_pointer(t);
    gcc_jit_type* size_type = gcc_jit_context_get_type(ctx, GCC_JIT_TYPE_SIZE_T);
    gcc_jit_type* byte_type_ptr = gcc_jit_type_get_pointer(gcc_jit_context_get_int_type(ctx, 1, 0));

    gcc_jit_rvalue* one = gcc_jit_context_new_rvalue_from_int(ctx, size_type, 1);

    gcc_jit_rvalue* ptr_0 = gcc_jit_context_new_rvalue_from_ptr(ctx, t_ptr_type, &NULL_PTR);
    gcc_jit_rvalue* ptr_1 = gcc_jit_lvalue_get_address(gcc_jit_context_new_array_access(ctx, NULL, ptr_0, one), NULL);

    ptr_0 = gcc_jit_context_new_cast(ctx, NULL, ptr_0, byte_type_ptr);
    ptr_1 = gcc_jit_context_new_cast(ctx, NULL, ptr_1, byte_type_ptr);

    return gcc_jit_context_new_binary_op(ctx, NULL, GCC_JIT_BINARY_OP_MINUS, size_type, ptr_1, ptr_0);
}

EDIT: I just figured out how to cast a pointer to an integer type as well. You can bitwise and it with itself and set the result type to a size_t.

ptr_0 = gcc_jit_context_new_binary_op(ctx, NULL, GCC_JIT_BINARY_OP_BITWISE_AND, size_type, ptr_0, ptr_0);
ptr_1 = gcc_jit_context_new_binary_op(ctx, NULL, GCC_JIT_BINARY_OP_BITWISE_AND, size_type, ptr_1, ptr_1);

return gcc_jit_context_new_binary_op(ctx, NULL, GCC_JIT_BINARY_OP_MINUS, size_type, ptr_1, ptr_0);

Upvotes: 1

Related Questions