How to compile and link with other c/c++ programs

It took me a little bit of time to figure this one out, so I’m clarifying my steps here. It might be valuable for me to add this to the docs, however on the latest version of MLIR I encountered an issue compiling (see bottom of reply for details).

However, on LLVM commit 90d1786ba I have it working. As a basic example I have the following C++ and MLIR files, as well as compilation process. The goal is for the MLIR function to change the value of one of our array elements.

I recommend anyone looking at this comment to be aware that you need to create and pass a MemRefDescriptor struct to your external function, and reading the LLVM IR Target - MLIR docs is worthwhile.

#include <iostream>

template <typename T, size_t N> struct MemRefDescriptor {
  T *allocated;
  T *aligned;
  intptr_t offset;
  intptr_t sizes[N];
  intptr_t strides[N];
};

extern "C" {
void *_mlir_ciface_change_value(MemRefDescriptor<int64_t, 1> input);
}

int main(int argc, char *argv[]) {
  int64_t *a = new int64_t[10];
  a[0] = 1;

  MemRefDescriptor<int64_t, 1> memref = {
      a,    // allocated
      a,    // aligned
      0,    // offset
      {10}, // sizes[N]
      {1},  // strides[N]
  };
  std::cout << "a[0] pre-call: " << a[0] << std::endl;
  _mlir_ciface_change_value(memref);
  std::cout << "a[0] post-call: " << a[0] << std::endl;
  return 0;
}

MLIR function

func @change_value(%0: memref<10xi64>) -> (memref<10xi64>) {
     %c1 = arith.constant 2 : i64
     affine.store %c1, %0[0] :  memref<10xi64>
     return %0 : memref<10xi64>
}

Shell commands:

cat vector_print.mlir |
	${LLVM_BUILD}/bin/mlir-opt \
	    --lower-affine \
	    --convert-arith-to-llvm \
	    --convert-scf-to-std \
	    --convert-memref-to-llvm \
    --convert-std-to-llvm='emit-c-wrappers=1' \
	--canonicalize -reconcile-unrealized-casts > value.mlir

$LLVM_BUILD/bin/mlir-translate -mlir-to-llvmir value.mlir > value.ir

llvm-as value.ir -o value.bc

llc -filetype=obj value.bc -o value.o

clang++ value.o main.cc

./a.out

When using a more recent version of MLIR (commit 5182839e), I fail with:

$ llvm-as value.ir -o value.bc
llvm-as: value.ir:4:9: error: expected type
declare ptr @malloc(i64)

My optimization passes are a little different:

cat vector_print.mlir |
	${US_LLVM}/bin/mlir-opt \
	--lower-affine \
    --convert-scf-to-cf \
	--convert-memref-to-llvm \
    --convert-func-to-llvm \
    --convert-cf-to-llvm=emit-c-wrappers=1 \
	--canonicalize \
    --reconcile-unrealized-casts > value.mlir

${US_LLVM}/bin/mlir-translate -mlir-to-llvmir value.mlir > value.ir

llvm-as value.ir -o value.bc
2 Likes