20
$\begingroup$

The Advanced Compilation Topics talk in the WTC 2018 shows that one can easily link C++ code through the new compiler technology. This feature seems very useful as one can easily load existing C++ code into Mathematica without extensive modifications.

I followed the instruction but unable to make it work:

Needs["Compile`"]

Create the C++ source file

code="extern \"C\"
double square(double a)
{return a * a;}
";
WriteString["/tmp/e.cpp",code]

Compile the C++ code to llvm

Run["clang -S -Wno-everything -O3 -o /tmp/e.ll -emit-llvm -march=skylake /tmp/e.cpp"]

Import the llvm

llvmStr = Import["/tmp/e.ll", "Text"];
prog = Program[{
    LLVMString[llvmStr],
    Function[{Typed[arg1, "Real64"]}, 
     Native`PrimitiveFunction["square"][arg1]]
    }];

Compile to external program

fun = CompileToExternalFunction[prog]

I'm getting an error

Compile: CompilerException. Type kind is not handled

I'm using Mathematica V12 on ubuntu 16.04.

Any ideas about the error and the correct way to compile?

$\endgroup$
6
  • 1
    $\begingroup$ So basically an alternative to LibraryLink? Very interested! $\endgroup$
    – Szabolcs
    Commented Jun 24, 2019 at 8:17
  • $\begingroup$ You ask ask a question, you don't explain a topic. $\endgroup$
    – user64494
    Commented Jun 24, 2019 at 11:24
  • $\begingroup$ Hm, I just get unevaluated Program and LLVMString. Does one need some Needs[]? $\endgroup$
    – Ruslan
    Commented Jun 24, 2019 at 14:01
  • 1
    $\begingroup$ The code is correct and actually works in the current development version. The released version does not have the necessary handling for floating point types, but it would probably work with int square(int a) $\endgroup$
    – ilian
    Commented Jun 28, 2019 at 15:04
  • 2
    $\begingroup$ FunctionCompile with LLVM is finally here in 12.3 and FunctionCompileExportLibrary. But there is not a FunctionCompileImport... yet. I've had a go at hacking the associations returned by FunctionCompile and substituting my own ByteArray of externally compiled llvm bitcode, but it blocks that by overwriting the array on evaluation. Also Program and LLVMString stay unevaluated in 12.3 so something must have changed there too. $\endgroup$
    – flinty
    Commented May 21, 2021 at 17:28

1 Answer 1

7
+50
$\begingroup$

Too long for a comment, but this (undocumented) syntax works in version 12.3 with a minor modification and taking into account a renamed function, for example:

Needs["Compile`"]

llvmStr = "define double @square(double %0) local_unnamed_addr #0 {
  %2 = fmul double %0, %0
  ret double %2
}";

fun = CompileToCodeFunction[
   Program[{LLVMString[llvmStr]}, 
    Function[{Typed[arg1, "Real64"]}, 
     Native`PrimitiveFunction["square"][arg1]]]];

fun[12.]

(* 144. *)

For creating a DLL:

CompileToLibrary[
 Program[{LLVMString[llvmStr]}, 
  Function[{Typed[arg1, "Real64"]}, 
   Native`PrimitiveFunction["square"][arg1]]], 
 "LibraryName" -> "square"]
$\endgroup$
2
  • $\begingroup$ How would you then create a library from it? I tried CompileToLibrary but it always puts the library in some weird path. What if I want to create 'square.dll' at a specific path? $\endgroup$
    – flinty
    Commented May 22, 2021 at 10:36
  • 1
    $\begingroup$ Something like square = First[CompileToLibrary[..., "LibraryName" -> "square"]]; CopyFile[square, "C:\\temp\\square.dll"] $\endgroup$
    – ilian
    Commented May 22, 2021 at 15:20

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.