the Chromium logo

The Chromium Projects

Experimenting with generated bitcode

Sample code (note the noinline attribute - makes it simpler to locate the code, otherwise it will get inlined all the way into _start):

int __attribute__((noinline)) simple_loop(int *a, int n) {
  int sum = 0;
  for (int i = 0; i < n; ++i) {
    sum += a[i];
  return sum;
int main(int argc, char** argv) {
  return simple_loop((int*)argv[0], argc);

Will be using the canary SDK here, so set NACL_SDK_ROOT to point to an install of the NaCl SDK /pepper_canary directory.

Run the compiler to produce optimized bitcode:

$NACL_SDK_ROOT/toolchain/linux_pnacl/bin/pnacl-clang ~/Downloads/loop.c -O2 -o loop.o2.bc

Note: this is LLVM bitcode:

$ $NACL_SDK_ROOT/toolchain/linux_pnacl/bin/pnacl-dis --file-type loop.o2.bc 
loop.o2.bc: LLVM bitcode

We'll keep it in LLVM bitcode format, because the NaCl bitcode writer/reader can't handle some of the types removed by stripping. So fully finalizing (into a stable pexe) a non-stripped file doesn't currently work.

$ $NACL_SDK_ROOT/toolchain/linux_pnacl/bin/pnacl-dis loop.o2.bc |grep -A20 "define internal i32 @simple_loop"
define internal i32 @simple_loop(i32 %a, i32 %n) {
  %cmp4 = icmp sgt i32 %n, 0
  br i1 %cmp4, label %for.body, label %for.end
for.body:                                         ; preds = %for.body, %entry
  %i.06 = phi i32 [ %inc, %for.body ], [ 0, %entry ]
  %sum.05 = phi i32 [ %add, %for.body ], [ 0, %entry ]
  %gep_array = mul i32 %i.06, 4
  %gep = add i32 %a, %gep_array
  %gep.asptr = inttoptr i32 %gep to i32*
  %0 = load i32* %gep.asptr, align 1
  %add = add i32 %0, %sum.05
  %inc = add i32 %i.06, 1
  %cmp = icmp slt i32 %inc, %n
  br i1 %cmp, label %for.body, label %for.end
for.end:                                          ; preds = %for.body, %entry
  %sum.0.lcssa = phi i32 [ 0, %entry ], [ %add, %for.body ]
  ret i32 %sum.0.lcssa

Finally, translate that into a .nexe in -O0 mode, asking pnacl-translate to accept LLVM bitcode explicitly (will be refused otherwise):

$ $NACL_SDK_ROOT/toolchain/linux_pnacl/bin/pnacl-translate loop.o2.bc -o loop.x64.nexe -arch x86-64 -O0 --allow-llvm-bitcode-input

Use objdump to examine the produced nexe.