Rllvm icon indicating copy to clipboard operation
Rllvm copied to clipboard

Segfault for GEP on opaque struct

Open nick-ulle opened this issue 10 years ago • 22 comments

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))

nick-ulle avatar Sep 29 '15 21:09 nick-ulle

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?

duncantl avatar Sep 29 '15 23:09 duncantl

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], ...)
}

nick-ulle avatar Sep 29 '15 23:09 nick-ulle

Try it in C and see what you get.

duncantl avatar Sep 29 '15 23:09 duncantl

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

nick-ulle avatar Sep 29 '15 23:09 nick-ulle

So this is the empty struct, not the opaque struct?

duncantl avatar Sep 29 '15 23:09 duncantl

Empty struct?

nick-ulle avatar Sep 29 '15 23:09 nick-ulle

Show me the C code that you are handing to clang?

duncantl avatar Sep 29 '15 23:09 duncantl

#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);
}

nick-ulle avatar Sep 29 '15 23:09 nick-ulle

I think you will find that pthread is a pointer type.

duncantl avatar Sep 29 '15 23:09 duncantl

I really don't think it is a link time issue.

duncantl avatar Sep 30 '15 02:09 duncantl

No, I don't either. I just meant that there's nothing wrong with allocating a forward-declared struct on the stack.

nick-ulle avatar Sep 30 '15 02:09 nick-ulle

Are you sure? Try it in C where the type is not a pointer.

duncantl avatar Sep 30 '15 02:09 duncantl

For now, I think I can work around this using i64 instead of opaque structs.

nick-ulle avatar Sep 30 '15 02:09 nick-ulle

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);
}

nick-ulle avatar Sep 30 '15 02:09 nick-ulle

Not sure what that illustrates. There is no array or alloc here.

duncantl avatar Sep 30 '15 02:09 duncantl

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.

nick-ulle avatar Sep 30 '15 02:09 nick-ulle

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?

nick-ulle avatar Sep 30 '15 02:09 nick-ulle

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.

duncantl avatar Sep 30 '15 02:09 duncantl

But then why does pthread_t thread; work? Clang never sees the definition for pthread_t, only the declaration in the header file.

nick-ulle avatar Sep 30 '15 03:09 nick-ulle

Er, I think I just realized what you meant--that pthread_t is a typedef for some kind of pointer.

nick-ulle avatar Sep 30 '15 03:09 nick-ulle

Yep, and that really matters.

duncantl avatar Sep 30 '15 03:09 duncantl

Then it seems this is a non-issue.

nick-ulle avatar Oct 02 '15 17:10 nick-ulle