Reputation: 12175
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
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
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