using dynamic libraries from bytecode?

Is it possible to use dynamic library (*.so *.dll) from bytecode?
If "yes" - how?

dlopen? That's be one way. Also, most systems have shared libraries in /usr/lib and these routines are meant to be linked against and used. For example, on darwin, there sinf is resolved from a shared library, you declare it and call it, as normal. You should be able to use llvm-gcc to see the bytecode of such a use of a routine from a dynamic library.

?

Mike Stump wrote:

Is it possible to use dynamic library (*.so *.dll) from bytecode?
If "yes" - how?

dlopen? That's be one way. Also, most systems have shared libraries
in /usr/lib and these routines are meant to be linked against and
used. For example, on darwin, there sinf is resolved from a shared
library, you declare it and call it, as normal. You should be able to
use llvm-gcc to see the bytecode of such a use of a routine from a
dynamic library.

Thanks! But... small example (mingw):

$ cat gcd_ui.c

#include <stdio.h>
#include <gmp.h>

static void check_ui_range (void)
{
  mpz_t x;
  mpz_init_set_ui (x, 111111L);
  mpz_mul_2exp (x, x, 1L);
  mpz_clear (x);
}

int main() {
  check_ui_range();
  printf("All works!\n");
  return 0;
}

$ llvm-gcc.exe -I/mingw/include gcd_ui.c -L/mingw/lib -lgmp -o gcd_ui.exe

$ ./gcd_ui.exe
All works!

$ llvm-gcc.exe -I/mingw/include gcd_ui.c -L/mingw/lib -lgmp -o
gcd_ui.ll -emit-llvm -S
llvm-gcc.exe: -lgmp: linker input file unused because linking not done

How determine library for `-emit-llvm` option?
Next:

$ cat gcd_ui.ll
; ModuleID = 'gcd_ui.c'
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-mingw32"
        %struct.__mpz_struct = type { i32, i32, i32* }
@.str = internal constant [11 x i8] c"All works!\00" ; <[11
x i8]*> [#uses=1]

define internal void @check_ui_range() nounwind {
entry:
        %x = alloca [1 x %struct.__mpz_struct] ; <[1 x
%struct.__mpz_struct]*> [#uses=4]
        %"alloca point" = bitcast i32 0 to i32 ; <i32> [#uses=0]
        %x1 = bitcast [1 x %struct.__mpz_struct]* %x to
%struct.__mpz_struct* ; <%struct.__mpz_struct*> [#uses=1]
        call void @__gmpz_init_set_ui( %struct.__mpz_struct* %x1, i32
111111 ) nounwind
        %x2 = bitcast [1 x %struct.__mpz_struct]* %x to
%struct.__mpz_struct* ; <%struct.__mpz_struct*> [#uses=1]
        %x3 = bitcast [1 x %struct.__mpz_struct]* %x to
%struct.__mpz_struct* ; <%struct.__mpz_struct*> [#uses=1]
        call void @__gmpz_mul_2exp( %struct.__mpz_struct* %x2,
%struct.__mpz_struct* %x3, i32 1 ) nounwind
        %x4 = bitcast [1 x %struct.__mpz_struct]* %x to
%struct.__mpz_struct* ; <%struct.__mpz_struct*> [#uses=1]
        call void @__gmpz_clear( %struct.__mpz_struct* %x4 ) nounwind
        br label %return

return: ; preds = %entry
        ret void
}

declare dllimport void @__gmpz_init_set_ui(%struct.__mpz_struct*, i32)

declare dllimport void @__gmpz_mul_2exp(%struct.__mpz_struct*,
%struct.__mpz_struct*, i32)

declare dllimport void @__gmpz_clear(%struct.__mpz_struct*)

define i32 @main() nounwind {
entry:
        %retval = alloca i32 ; <i32*> [#uses=2]
        %tmp = alloca i32 ; <i32*> [#uses=2]
        %"alloca point" = bitcast i32 0 to i32 ; <i32> [#uses=0]
        call void @check_ui_range( ) nounwind
        %tmp1 = call i32 @puts( i8* getelementptr ([11 x i8]* @.str,
i32 0, i32 0) ) nounwind ; <i32> [#uses=0]
        store i32 0, i32* %tmp, align 4
        %tmp2 = load i32* %tmp, align 4 ; <i32> [#uses=1]
        store i32 %tmp2, i32* %retval, align 4
        br label %return

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

declare i32 @puts(i8*)

$ llvm-as gcd_ui.ll -o gcd_ui.bc

$ lli gcd_ui.bc
ERROR: Program used external function '__gmpz_init_set_ui' which could
not be resolved!

This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.

How and where I must specify library?

$ llvm-gcc.exe -I/mingw/include gcd_ui.c -L/mingw/lib -lgmp -o
gcd_ui.ll -emit-llvm -S

Use

$ llvm-as gcd_ui.ll -o gcd_ui.bc

Use llc gcd_ui.bc and then llvm-gcc.exe gcd_ui.s -L/mingw/lib -lgmp?

I think the question is not how to create a stand-alone exe, but how to tell lli where it should search undefined symbols.

Try: lli -load /path/to/foo.so gcd_ui.bc

Replace ".so" with ".dylib" or ".dll" as appropriate.

-Chris

Chris Lattner wrote:

$ lli gcd_ui.bc
ERROR: Program used external function '__gmpz_init_set_ui' which could
not be resolved!

This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.

Try: lli -load /path/to/foo.so gcd_ui.bc

Replace ".so" with ".dylib" or ".dll" as appropriate.

Many thanks! This is works. Nice!

Next question: there is a standard portable way to do so (load dynamic library) from the body of the program (from bytecode)?

No, you should call dlopen or whatever native routine is appropriate for your system.

-Chris