How to get llvm bitcode executed

Hi All,

I have a program that uses C++ STL a lot. To have the source code for
STL functions, I undefined "_GLIBCXX_EXTERN_TEMPLATE" in
c++config.h. In spite of this, after compilation (via clang) and
linking (via llvm-ld), the resulting bitcode contains a few declared
functions (with no definitions).

My question is: In the scenario where some function definitions are
missing in a llvm bitcode, can we get a way to run this module via llc
or lli? Or is there any way to make these function definitions
available in the llvm bitcode?

Specifically, these missing functions are as below:

  declare i8* @llvm.eh.exception() nounwind readonly
  declare i32 @__gxx_personality_v0(...)
  declare i32 @llvm.eh.selector(i8*, i8*, ...) nounwind
  declare void @llvm.eh.resume(i8*, i32)
  declare void @_ZSt9terminatev()
  declare i32 @memcmp(i8*, i8*, i64)
  declare i64 @llvm.expect.i64(i64, i64) nounwind readnone
  declare void @_ZSt19__throw_logic_errorPKc(i8*) noreturn
  declare i8* @__cxa_begin_catch(i8*)
  declare void @__cxa_rethrow()
  declare void @__cxa_end_catch()
  declare void @__cxa_call_unexpected(i8*)
  declare void @_ZdlPv(i8*) nounwind
  declare void @_ZSt20__throw_length_errorPKc(i8*) noreturn
  declare void @_ZSt17__throw_bad_allocv() noreturn
  declare noalias i8* @_Znwm(i64)
  declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture, i64, i32, i1) nounwind
  declare void @llvm.memmove.p0i8.p0i8.i64(i8* nocapture, i8* nocapture, i64, i32, i1) nounwind
  declare i32 @llvm.atomic.load.add.i32.p0i32(i32* nocapture, i32) nounwind
  declare void @llvm.memory.barrier(i1, i1, i1, i1, i1) nounwind
  declare void @_ZSt20__throw_out_of_rangePKc(i8*) noreturn
  declare i64 @strlen(i8*)
  declare void @abort()

Xiaolong

Guess I have found some clues. Some necessary libraries have to be
loaded while trying to generate native code or do interpretation. Then
another question emerges: Is there a way to determine the necessary
libraries in need? And where to locate these necessary libraries?

Xiaolong

I've used '-load=<libname>' to load undefined references in the bitcode. Though I'm still stuck with '__dso_handle' now :frowning:

Hi Xialong,

I have a program that uses C++ STL a lot. To have the source code for
STL functions, I undefined "_GLIBCXX_EXTERN_TEMPLATE" in
c++config.h. In spite of this, after compilation (via clang) and
linking (via llvm-ld), the resulting bitcode contains a few declared
functions (with no definitions).

My question is: In the scenario where some function definitions are
missing in a llvm bitcode, can we get a way to run this module via llc
or lli? Or is there any way to make these function definitions
available in the llvm bitcode?

with lli, you should be able to do it by adding
   -load=libstdc++.so
to the lli command line (maybe with a full path). With llc, use g++
to the linking. For example, if llc turned bitcode.bc into bitcode.s,
do
   g++ -o bitcode bitcode.s
since g++ automagically passes libstdc++ to the linker. You can also
use the system linker directly, adding the missing libraries.

Specifically, these missing functions are as below:

   declare i8* @llvm.eh.exception() nounwind readonly

This is an LLVM intrinsic, so isn't really missing.

   declare i32 @__gxx_personality_v0(...)

This should be in libstdc++.

   declare i32 @llvm.eh.selector(i8*, i8*, ...) nounwind
   declare void @llvm.eh.resume(i8*, i32)

LLVM intrinsics.

   declare void @_ZSt9terminatev()

This should be in libstdc++.

   declare i32 @memcmp(i8*, i8*, i64)

In libc (libc.so) which should be pulled in by libstdc++.

   declare i64 @llvm.expect.i64(i64, i64) nounwind readnone

LLVM intrinsic.

   declare void @_ZSt19__throw_logic_errorPKc(i8*) noreturn
   declare i8* @__cxa_begin_catch(i8*)
   declare void @__cxa_rethrow()
   declare void @__cxa_end_catch()
   declare void @__cxa_call_unexpected(i8*)
   declare void @_ZdlPv(i8*) nounwind
   declare void @_ZSt20__throw_length_errorPKc(i8*) noreturn
   declare void @_ZSt17__throw_bad_allocv() noreturn
   declare noalias i8* @_Znwm(i64)

These should all be in libstdc++.

   declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture, i64, i32, i1) nounwind
   declare void @llvm.memmove.p0i8.p0i8.i64(i8* nocapture, i8* nocapture, i64, i32, i1) nounwind
   declare i32 @llvm.atomic.load.add.i32.p0i32(i32* nocapture, i32) nounwind
   declare void @llvm.memory.barrier(i1, i1, i1, i1, i1) nounwind

LLVM intrinsics.

   declare void @_ZSt20__throw_out_of_rangePKc(i8*) noreturn

This should be in libstdc++.

   declare i64 @strlen(i8*)
   declare void @abort()

In libc (libc.so) which should be pulled in by libstdc++.

Ciao, Duncan.

Thanks Duncan and Ashok,

As Duncan described, "lli -load=libstdc++.dylib ..." works. I,
however, encounted an "Illegal instruction" message, while I was
trying to interpret a large program. So, does lli have a debug switch
for dumping out the details for errors?

Using llc is not that simple, and I have not gotten through the
compilation process. For instance, "llc -o test.s test.bc" works and
generates "test.s"; "g++ -o test.o test.s" throws out "Unknown
pseudo-op: .cfi_startproc" messages, however. Not sure about the
reasons yet.

Xiaolong

Duncan Sands wrote:

Hi Xiaolong,

As Duncan described, "lli -load=libstdc++.dylib ..." works. I,
however, encounted an "Illegal instruction" message, while I was
trying to interpret a large program.

are you using the interpreter or the JIT?

  So, does lli have a debug switch

for dumping out the details for errors?

Using llc is not that simple, and I have not gotten through the
compilation process. For instance, "llc -o test.s test.bc" works and
generates "test.s"; "g++ -o test.o test.s" throws out "Unknown
pseudo-op: .cfi_startproc" messages, however. Not sure about the
reasons yet.

This means that your binutils is too old. Try passing -disable-cfi
to llc.

Ciao, Duncan.

Hi Duncan,

Thanks again.

> As Duncan described, "lli -load=libstdc++.dylib ..." works. I,
> however, encounted an "Illegal instruction" message, while I was
> trying to interpret a large program.

are you using the interpreter or the JIT?

I think, I am using the JIT, as passing -force-interpreter=true gives
rise to "Could not resolve external global address: __dso_handle".
The "Illegal instruction" issue might be caused by the program I
attempted to run; I am investigating this issue.

  So, does lli have a debug switch
> for dumping out the details for errors?
>
> Using llc is not that simple, and I have not gotten through the
> compilation process. For instance, "llc -o test.s test.bc" works and
> generates "test.s"; "g++ -o test.o test.s" throws out "Unknown
> pseudo-op: .cfi_startproc" messages, however. Not sure about the
> reasons yet.

This means that your binutils is too old. Try passing -disable-cfi
to llc.

This option works. Actually, the version of my assembler (as) is GNU
assembler version 1.38. I have no idea of the up-to-date version for
working with llc, but the "-disable-cfi" options helps out, even under
my outdated binutils.

Best,
Xiaolong