[LLVMdev] lli -force-interpreter complains about external function

347 views
Skip to first unread message

Xu Yang

unread,
Nov 16, 2009, 2:14:27 AM11/16/09
to llv...@cs.uiuc.edu
Hi:

When I try to execute lli -force-interpreter=true hello.bc, it gave the following error:

LLVM ERROR: Tried to execute an unknown external function: i32 (i8*)* puts

I think the error is because C library is not being linked with the byte code, but I was not able to find any helpful instruction in lli's document.

Can you please teach me how to do it?

Thanks
Xu


The hello.bc is generated as the following:

======file: hello.c======
#include <stdio.h>


int main(int argc, char** argv){
  printf("hello world\n");
  return 0;
}

====================


llvm-gcc -o hello.bc -emit-llvm -c hello.c


This is the code in hello.bc (after llvm-dis):
==================================
; ModuleID = 'hello.bc'
target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32"
target triple = "i386-pc-linux-gnu"

@.str = private constant [12 x i8] c"hello world\00", align 1 ; <[12 x i8]*> [#uses=1]

define i32 @main(i32 %argc, i8** %argv) nounwind {
entry:
  %argc_addr = alloca i32                         ; <i32*> [#uses=1]
  %argv_addr = alloca i8**                        ; <i8***> [#uses=1]
  %retval = alloca i32                            ; <i32*> [#uses=2]
  %0 = alloca i32                                 ; <i32*> [#uses=2]
  %"alloca point" = bitcast i32 0 to i32          ; <i32> [#uses=0]
  store i32 %argc, i32* %argc_addr
  store i8** %argv, i8*** %argv_addr
  %1 = call i32 @puts(i8* getelementptr inbounds ([12 x i8]* @.str, i32 0, i32 0)) nounwind ; <i32> [#uses=0]
  store i32 0, i32* %0, align 4
  %2 = load i32* %0, align 4                      ; <i32> [#uses=1]
  store i32 %2, i32* %retval, align 4
  br label %return

return:                                           ; preds = %entry
  %retval1 = load i32* %retval                    ; <i32> [#uses=1]
  ret i32 %retval1
}

Nick Lewycky

unread,
Nov 16, 2009, 2:23:53 AM11/16/09
to Xu Yang, llv...@cs.uiuc.edu
Xu Yang wrote:
> Hi:
>
> When I try to execute lli -force-interpreter=true hello.bc, it gave the
> following error:
>
> LLVM ERROR: Tried to execute an unknown external function: i32 (i8*)* puts
>
> I think the error is because C library is not being linked with the byte
> code, but I was not able to find any helpful instruction in lli's document.
>
> Can you please teach me how to do it?

The interpreter uses libffi to make external function calls. However, it
needs to be detected at LLVM's compile time. If you're using the
released packages, we disabled that because we were worried about users
who don't have libffi installed.

In short, install libffi and rebuild LLVM.

Nick

> _______________________________________________
> LLVM Developers mailing list
> LLV...@cs.uiuc.edu http://llvm.cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev

_______________________________________________
LLVM Developers mailing list
LLV...@cs.uiuc.edu http://llvm.cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev

Timo Juhani Lindfors

unread,
Nov 16, 2009, 7:47:12 AM11/16/09
to Nick Lewycky, llv...@cs.uiuc.edu
Nick Lewycky <nich...@mxc.ca> writes:
> The interpreter uses libffi to make external function calls. However, it
> needs to be detected at LLVM's compile time. If you're using the
> released packages, we disabled that because we were worried about users
> who don't have libffi installed.

This seems to be quite a common problem (I too hit it once, thought it
was a bug and reported it at
http://llvm.org/bugs/show_bug.cgi?id=5466) how about making lli inform
the user that LLVM was built without FFI support?

Nick Lewycky

unread,
Nov 17, 2009, 2:52:14 AM11/17/09
to Timo Juhani Lindfors, llv...@cs.uiuc.edu
Timo Juhani Lindfors wrote:
> Nick Lewycky<nich...@mxc.ca> writes:
>> The interpreter uses libffi to make external function calls. However, it
>> needs to be detected at LLVM's compile time. If you're using the
>> released packages, we disabled that because we were worried about users
>> who don't have libffi installed.
>
> This seems to be quite a common problem (I too hit it once, thought it
> was a bug and reported it at
> http://llvm.org/bugs/show_bug.cgi?id=5466) how about making lli inform
> the user that LLVM was built without FFI support?

Thanks for the reminder. I recall looking at the patch but I didn't
apply it at the time because I couldn't figure out why the code above it
used errs() in one case and llvm_report_error in another.

Nick

Xu Yang

unread,
Nov 18, 2009, 12:02:34 AM11/18/09
to Nick Lewycky, llv...@cs.uiuc.edu
Hi Nick:

Thanks for pointing me to libffi.
Recompile LLVM with libffi does solve the problem of printf.
But it still has other problems:
1) sinf() returns 0 in the interpreter, but returns correct value in JIT (see hellosin.c)
2) calling pthread_create cause lli to crash in the interpreter mode, but no problem in JIT (see phello.c).

My questions are:
i) can I call any arbitrary external function in the interpreter? 
ii) how do I specify the dynamic library (where the external function is implemented), when I call the interpreter?

Thanks
Xu

hellosin.c
=======================
#include <stdio.h>
#include <math.h>


int main(int argc, char** argv){
  float f = sinf(0.5235988f);
  printf("hello sin: %10.2f\n", f);
  return 0;
}
========================
$ llvm-gcc -o hellosin.bc -emit-llvm -c hellosin.c
$ lli -force-interpreter=true hellosin.bc
hello sin:       0.00
$ lli hellosin.bc
hello sin:       0.50

phello.c
========================
#include <pthread.h>
#include <stdio.h>
#define NUM_THREADS     4

void *PrintHello(void *threadid)
{
   long tid;
   tid = (long)threadid;
   printf("Hello from %ld.\n", tid);
   pthread_exit(NULL);
}

int main (int argc, char *argv[])
{
   pthread_t threads[NUM_THREADS];
   int ret;
   long t;
   for(t=0; t<NUM_THREADS; t++){
#ifdef DEBUG
      printf("creating thread %ld\n", t);
#endif
      ret = pthread_create(&threads[t], NULL, PrintHello, (void *)t);
      if (ret){
         printf("pthread_create ERROR: %d\n", ret);
         return(-1);
      }
   }
   pthread_exit(NULL);
}
========================
$ llvm-gcc -o phello.bc -emit-llvm -c phello.c
$ lli -force-interpreter=true phello.bc
0   lli 0x08796bf8
Segmentation fault
$ lli phello.bc
Hello from 0.
Hello from 1.
Hello from 2.
Hello from 3.

Xu Yang

unread,
Nov 18, 2009, 12:29:29 AM11/18/09
to Nick Lewycky, llv...@cs.uiuc.edu
Hi Nick:

The first problem have been solved by calling llvm-ld:

$ llvm-ld -o hellosin.llvm hellosin.bc -lm
$ lli -force-interpreter=true -load=/usr/lib/libm.so hellosin.llvm.bc
hello sin:       0.50

The pthread problem remains after llvm-ld:

$ lli -force-interpreter=true -load=/lib/libpthread.so.0 phello.llvm.bc
0   lli 0x08796bf8
Segmentation fault


For those who are getting "invalid ELF header" error when calling llvm-ld with -lpthread,
please change the load module from /usr/lib/pthread.a to /lib/libpthread.so.0.

Thanks
Xu

Nick Lewycky

unread,
Nov 18, 2009, 12:40:41 AM11/18/09
to Xu Yang, llv...@cs.uiuc.edu
Xu Yang wrote:
> Hi Nick:
>
> The first problem have been solved by calling llvm-ld:
>
> $ llvm-ld -o hellosin.llvm hellosin.bc -lm
> $ lli -force-interpreter=true -load=/usr/lib/libm.so hellosin.llvm.bc
> hello sin: 0.50

Only because the optimizer saw sin(constant) and folded it away. The
entire program became 'print constant string'. There is certainly a bug
calling sinf() from the interpreter but I don't know what it is yet.

> The pthread problem remains after llvm-ld:
>
> $ lli -force-interpreter=true -load=/lib/libpthread.so.0 phello.llvm.bc
> 0 lli 0x08796bf8
> Segmentation fault

I don't expect this to work at all. Unlike the JIT, I don't know of any
work having been done to make the interpreter thread-safe.

By the way, the interpreter can't support many more things, such as
qsort() or any method which expects to call a function pointer. Is there
a reason you need to use the interpreter? It's been largely
undermaintained because it's pretty much useless when you've got a
working JIT.

Nick

> Nick Lewycky<nich...@mxc.ca <mailto:nich...@mxc.ca>> writes:
>
> The interpreter uses libffi to make external function
> calls. However, it
> needs to be detected at LLVM's compile time. If you're
> using the
> released packages, we disabled that because we were
> worried about users
> who don't have libffi installed.
>
>
> This seems to be quite a common problem (I too hit it once,
> thought it
> was a bug and reported it at
> http://llvm.org/bugs/show_bug.cgi?id=5466) how about making
> lli inform
> the user that LLVM was built without FFI support?
>
>
> Thanks for the reminder. I recall looking at the patch but I
> didn't apply it at the time because I couldn't figure out why
> the code above it used errs() in one case and llvm_report_error
> in another.
>
> Nick
>
>
>

_______________________________________________

Nick Lewycky

unread,
Nov 18, 2009, 12:43:40 AM11/18/09
to Xu Yang, llv...@cs.uiuc.edu
Nick Lewycky wrote:
> Xu Yang wrote:
>> Hi Nick:
>>
>> The first problem have been solved by calling llvm-ld:
>>
>> $ llvm-ld -o hellosin.llvm hellosin.bc -lm
>> $ lli -force-interpreter=true -load=/usr/lib/libm.so hellosin.llvm.bc
>> hello sin: 0.50
>
> Only because the optimizer saw sin(constant) and folded it away. The
> entire program became 'print constant string'. There is certainly a bug
> calling sinf() from the interpreter but I don't know what it is yet.

Fixed in r89198.

Xu Yang

unread,
Nov 18, 2009, 1:03:43 AM11/18/09
to Nick Lewycky, llv...@cs.uiuc.edu
Hi Nick:

Thanks for the response.

You are right about sinf. 
I changed the constant to sscanf(argv[1], ...), and it gave me back 0 again.
I also compared the disassembled code, and saw it was indeed the case.

The primary reason I use interpreter is because I wish to do runtime checking on memory access pattern in multithreaded C programs. for example, if thread one is in the critical section, I wish to know if there are any other threads accessing the variables in the critical section without first acquiring a lock. I can do it with native code, but I will have to insert memory check function calls before all memory access instructions (load/store...), which is painful. But if I can run the program in interpreter, I can intercept the load and store instruction in the interpreter, and do the memory check there, which is completely transparent to the user program.

Do you have any suggestions on how LLVM may help in this case?


Thanks
Xu

Jeffrey Yasskin

unread,
Nov 18, 2009, 1:12:35 AM11/18/09
to Xu Yang, llv...@cs.uiuc.edu
Have you looked at
http://code.google.com/p/data-race-test/wiki/ThreadSanitizer or
http://valgrind.org/docs/manual/hg-manual.html? They have the
advantage of having already been debugged.

Timo Juhani Lindfors

unread,
Nov 18, 2009, 7:07:25 AM11/18/09
to Nick Lewycky, llv...@cs.uiuc.edu
Nick Lewycky <nich...@mxc.ca> writes:
> Thanks for the reminder. I recall looking at the patch but I didn't
> apply it at the time because I couldn't figure out why the code above
> it used errs() in one case and llvm_report_error in another.

What was the reason? (I think I too wondered that.)

Nick Lewycky

unread,
Nov 19, 2009, 1:47:30 AM11/19/09
to Timo Juhani Lindfors, llv...@cs.uiuc.edu
Timo Juhani Lindfors wrote:
> Nick Lewycky<nich...@mxc.ca> writes:
>> Thanks for the reminder. I recall looking at the patch but I didn't
>> apply it at the time because I couldn't figure out why the code above
>> it used errs() in one case and llvm_report_error in another.
>
> What was the reason? (I think I too wondered that.)
>
I have no idea. :) I decided that it didn't matter to your patch.

Nick

Reply all
Reply to author
Forward
0 new messages