Segfault for GEP on opaque struct
The following example segfaults with the lastest version of Rllvm and LLVM 3.6.2:
library(Rllvm)
module = Module()
fun = Function("fun", VoidType, list(), module = module)
entry = Block(fun, "entry")
builder = IRBuilder(entry)
data_struct = structType(list(), "data", withNames = FALSE)
x = createAlloc(builder, arrayType(data_struct, 3L), id = "x")
x_id = createGEP(builder, x, createIntegerConstant(0L))
Since data_struct is an opaque data type, can you really be allocating an array of them? Don't you want an array of pointers to these?
Yes, I really do want to allocate the memory for them. Unless I'm misunderstanding, the correct sizes would normally be filled in during linking.
The context for this is allocating opaque pthread_t structs for pthreads. E.g., in C
pthread_t threads[N_THREADS];
for (int i = 0; i < N_THREADS; i++) {
pthread_create(&threads[i], ...)
}
Try it in C and see what you get.
Clang doesn't even declare the structs, it treats them as int64s. But I'm not sure how it arrived at int64 as the first element of the pthreads structs.
%threads = alloca [5 x i64], align 16
So this is the empty struct, not the opaque struct?
Empty struct?
Show me the C code that you are handing to clang?
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#define N_THREADS 5
void *PrintHello(void *thread_id)
{
long tid = (long) thread_id;
printf("Hello World! It's thread %li!\n", tid);
pthread_exit(NULL);
}
int main(int argc, char **argv)
{
pthread_t threads[N_THREADS];
int rc;
for (long thread_id = 0; thread_id < N_THREADS; thread_id++) {
printf("Creating thread %li.\n", thread_id);
rc = pthread_create(&threads[thread_id], NULL,
PrintHello, (void *) thread_id);
if (rc) {
printf("ERROR: pthread_create() returned %i.\n", rc);
exit(-1);
}
}
pthread_exit(NULL);
}
I think you will find that pthread is a pointer type.
I really don't think it is a link time issue.
No, I don't either. I just meant that there's nothing wrong with allocating a forward-declared struct on the stack.
Are you sure? Try it in C where the type is not a pointer.
For now, I think I can work around this using i64 instead of opaque structs.
Clang has no problem with this:
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#define N_THREADS 1
void *PrintHello(void *thread_id)
{
long tid = (long) thread_id;
printf("Hello World! It's thread %li!\n", tid);
pthread_exit(NULL);
}
int main(int argc, char **argv)
{
//pthread_t threads[N_THREADS];
pthread_t thread;
int rc;
for (long thread_id = 0; thread_id < N_THREADS; thread_id++) {
printf("Creating thread %li.\n", thread_id);
rc = pthread_create(&thread, NULL, //s[thread_id], NULL,
PrintHello, (void *) thread_id);
if (rc) {
printf("ERROR: pthread_create() returned %i.\n", rc);
exit(-1);
}
}
pthread_exit(NULL);
}
Not sure what that illustrates. There is no array or alloc here.
The line
pthread_t thread;
corresponds directly to the IR
%thread = alloca i64, align 8
Whether it's an array or not, memory is being alloc'd for the pthread_t data. They are not just pointers.
Unless you mean that pthread_t is itself just holding a pointer (as its element)? But I still don't see how that gets out of the need to alloc an array of pthread_t on the stack?
Allocating an array of pointers is easy as the size of a pointer is known. Allocating an array of structs whose size is not known doesn't work.
But then why does pthread_t thread; work? Clang never sees the definition for pthread_t, only the declaration in the header file.
Er, I think I just realized what you meant--that pthread_t is a typedef for some kind of pointer.
Yep, and that really matters.
Then it seems this is a non-issue.