Manually Linking LLVM Bitcode from Rust with CC, GCC or Clang

I'm working on a compiler project that requires testing some stuff with Rust. I have some LLVM passes that can only be ran out-of-tree. So after the pass, I still have to obtain object files and then binaries. I don't know how to link the object files (I don't suppose there's a way to do it with Rust). I've tried doing it with cc and clang but they scream back about link errors. I was wondering whether anyone has ever done manual linking or has any idea how I can do this any other easier way. I've been able to succeed with small files but for large programs, it's been a disaster.

Any help/suggestions would be most appreciated!

What kind of link errors? Clang doesn't really care about what language emitted the bitcode, I've successfully used it with bitcode files that I wrote manually or generated from a toy language. Maybe you forgot to link against the Rust standard library?

The size of the programs being linked shouldn't matter. Is file size really the only difference between the two cases?

Rust does support linking against code generated from other languages. You may want to look at the cc crate, with which you can invoke a C compiler from a build.rs build script.

1 Like

Thanks you so much for the reply:
Basically, I have a script like this:

#!/bin/bash

set -x

OUTPUT_DIR=`pwd`
LLVM_HOME=/home/martin/rust/build/x86_64-unknown-linux-gnu/llvm/build/
RUSTUP_TOOLCHAIN_LIB=/home/martin/rust/build/lib/rustlib/x86_64-unknown-linux-gnu/lib/
SVF=/home/martin/SVF/cmake-build-default/bin/wpa
MPK_LIB_DIR=/home/martin/mpk-library/build/
CRUST_LIB_DIR=/home/martin/crust/
export RUSTC=/home/martin/rust/build/bin/rustc
env RUSTFLAGS="-L/home/martin/mpk-library/build/ -L/home/martin/crust/ -lmpk -lcrust" ~/rust/build/bin/cargo rustc --verbose -- -v -C save-temps --emit=llvm-ir

cd target/debug/deps

rm *no-opt*

find . -name '*.ll' | xargs -n 1 $LLVM_HOME/bin/llvm-as

#find . -name '*.ll' | rev | cut -c 3- | rev | \
#  xargs -n 1 -I{} $SVF {}bc

#find . -name '*.ll' | rev | cut -c 3- | rev | \
#  xargs -n 1 -I{} $LLVM_HOME/bin/opt -mpk-isolation -mpk-isolation-gates -o {}bc {}bc

find . -name '*.ll' | xargs -n 1 $LLVM_HOME/bin/llc -filetype=obj

cc -m64 -L $RUSTUP_TOOLCHAIN_LIB \
  *.o \
  $(ls | grep '\.rlib$' | sed 's/lib/ \.\/lib/') \
  $(find $RUSTUP_TOOLCHAIN_LIB -name '*rlib') \
  -L $RUSTUP_TOOLCHAIN_LIB \
 # -L $MPK_LIB_DIR \
 # -L $CRUST_LIB_DIR \
  -Wl,-dead_strip -nodefaultlibs -lresolv -lc -lm \
  -o $OUTPUT_DIR/mpktest

I have libmpk.so and libcrust.so from C.
I followed this site.

But I get errors citing undefined references.
I've made sure to link libstd but then I got
undefined reference to symbol '_Unwind_Resume@@GCC_3.0'

Generally speaking, if you get an undefined reference, you need to either include an object module or library on the link command line that defines this symbol, or you need to remove/replace whichever module references the symbol.

_Unwind_Resume@@GCC_3.0 smells like a symbol defined in libgcc.a (it's part of the GCC runtime library's stack unwinding code), so perhaps you'll have to link with -lgcc. However, it's also possible that the module that references it shouldn't have been included in the first place, so it would be helpful if you copied and pasted the exact error, particularly the part that says where the symbol is being referenced.