How is Kotlin code compiled into native code? - kotlin

The official Kotlin/Native documentation states that Kotlin/Native
.. is an LLVM based backend for the Kotlin compiler.
As far as I understand:
The Kotlin compiler (kotlinc) produces .class files (with Java bytecode) from your Kotlin source files.
Generic LLVM backends (that are not related to Kotlin) take LLVM IR and turn it into binary code.
Therefore, is Kotlin/Native converting Java bytecode into LLVM IR?
If so, is it correct to state that Kotlin/Native is a LLVM backend? Does Kotlin code get compiled into LLVM IR?
If not, what is the input and output of each compilation step? (e.g.: Kotlin -(kotlinc)-> Java bytecode -(LLVM backend-> native binary)
This blog post states that the Kotlin frontend compiler (I think it is referring to kotlinc) produces Kotlin IR, which I have never read of.
Kotlin compiler has a single front-end but multiple back-end depending upon the the plugin you are using to build the code. Kotlin/Native plugin converts the Kotlin Intermediate Representation (IR) to native code (i.e code that is machine executable).
Is this quote correct?
It tells you that the compilation process is the same for Java bytecode, native code and JavaScript. You compile your Kotlin code and then you have 3 backend compilers that deliver the expected output format (Java bytecode, JavaScript, binary code).
Does the final platform specific binary include the native Kotlin standard library or is it linked dynamically?

Kotlin compiler has a single front-end but multiple back-end depending upon the the plugin you are using to build the code. Kotlin/Native plugin converts the Kotlin Intermediate Representation (IR) to native code (i.e code that is machine executable).
Is this quote correct?
Yes, it's quite correct. The intermediate representation (IR) is a form that universally represents a Kotlin program, regardless of the platform. Then a platform-specific back-end translates the IR to the final binary form – the JVM class files for Kotlin/JVM, LLVM bitcode and other metadata packed into a *.klib for Kotlin/Native.
So, Kotlin/Native doesn't deal with the JVM bytecode in any way.
The intermediate representation is an implementation detail of the Kotlin compiler, and it's not used by any other consumer than the Kotlin compiler itself, so it's not a thing that a developer should care about. For the JVM, it's even kept in memory and never written to binaries. For Kotlin/Native, it's actually serialized and written into the *.klib to be reused.
It tells you that the compilation process is the same for Java bytecode, native code and JavaScript. You compile your Kotlin code and then you have 3 backend compilers that deliver the expected output format (Java bytecode, JavaScript, binary code).
Actually, a part of the compilation process is the same, namely, the front-end language analysis, which includes parsing, call resolution, type inference, diagnostics and other steps that don't require any code transformations that are platform-specific. Even so, the front-end part is tuned for each of the platforms, as those allow different sets of language features and provide different sets of diagnostics.
And the last question does the final platform specific binary include the native Kotlin standard library? Or is it linked dynamically?
Currently, the standard library is statically linked into the resulting Kotlin/Native binaries.

Related

Kotlin Multiplatform : add a Kotlin/Native as common code

I want to create a Kotlin project compatible with Android and Desktop. This project needs to bind to a C library.
The way I understand it, I should create a Kotlin multiplatform project, and have a common code which wraps the C library using JNI.
However, Kotlin/Native allows a way easier interop with C libraries, so I'd like to use that. But it seems like Kotlin/Native is a platform (equal to eg jvm or android), so it can't be used as a common code.
Is there a way to do what I want? I couldn't find any simple example doing that.
If that's not possible, why? Kotlin/Native is able to target desktop and android platforms. If it's possible to use Kotlin/Native on Android, why is it impossible to use a Kotlin/Native library from a "normal" desktop/android project?
This should be possible with Kotlin Multiplatform, by having a native target.
See https://kotlinlang.org/docs/native-app-with-c-and-libcurl.html#create-a-definition-file
Kotlin/Native helps consume standard C libraries, opening up an entire ecosystem of functionality that exists for pretty much anything you may need. Kotlin/Native is already shipped with a set of prebuilt platform libraries, which provide some additional common functionality to the standard library.
UPDATE:
"common" code in Kotlin Multiplatform under the hood either:
a) has platform-agnostic Kotlin code or
b) uses expect/actual to define platform abstractions
(AFAIK)
Since a C library isn't a), you'll have to define the actual platform definitions, ending up with JNI.
TL;DR KMP isn't suitable for what you're trying to do

Differences in writing Kotlin/JVM and Kotlin/JS?

I read the Big Nerd Ranch guide to Kotlin and it talked in several places about Kotlin/Java interop, but never JS or native. I already had a solid background in Java, so I have gotten used to using Java classes in my Kotlin code. I am trying to write a Kotlin program which will be run on a site where most - if not all - functionality is written in JavaScript, and I am trying to understand how to write my code to make sure that it is interoperable. Will I be able to continue using Java classes in my Kotlin/JS code? What are the differences between writing Kotlin/JVM code and Kotlin/JS code? What should a (ex-) java programmer know when learning to interop with JS using Kotlin? If there are a few chapters on this in any good books written in the recent past, that would be helpful also.
As Steve already mentioned, you can't utilise java classes in Kotlin/JS.
Think of Kotlin/JS as Typescript.
It provides a different syntax to write code that ultimately compiles to JS.
Here are the notable differences of writing Kotlin/JS code vs Kotlin/JVM code
Kotlin/JS internally uses yarn for dependency management. This enables you to depend on any javascript module available on npmjs etc (see note below)
In addition to standard library, you can also leverage other kotlin-first frameworks such as kotlinx-serialization, ktor etc
Testing libraries will be JS specific. So instead of mockito / mockk / junit family, you'll need to get familiar with karma / mocha family.
There will be a difference in Coroutine capabilities - both in terms of the way one writes code and performance expectations.
I found reading about Kotlin Multiplatform helped clarify a lot about the capabilities of kotlin.
I know this was not specifically asked, but giving my 2cents to people considering Kotlin/JS (as of Sep'20)
Great if you're familiar with Kotlin and don't foresee too many third party dependencies apart from http i/o (ktor) , React ( kotlin-react) and basic html / css (covered by kotlin-styled).
Using JS modules as dependencies is not as straight forward as using JVM dependencies since there is no ready-made interop. One has to define javascript functions/classes in kotlin before using them (see here). So if you foresee leveraging a lot of existing javascript modules, it won't be an ideal way forward.
Great if you have a typical backend-frontend model where backend compiles to JVM and Frontend compiles to JS. You can leverage a common data model and http i/o framework across Backend and Frontend code (via Kotlin Multiplatform). I've found this to be a tremendous productivity boost!
Kotlin/JS compiles Kotlin code, including its own standard library, into Javascript code. At the end, that's all you have is Javascript. What you don't have is any connection to the Java Virtual Machine. Kotlin's standard library provides no magic to bridge Javascript code to the JVM so that it can utilize Java classes. So NO, you can't utilize Java classes in standard Kotlin/JS.

What's the difference between Kotlin JVM and Kotlin Native?

So I know Kotlin Native is obviously Native and Kotlin JVM isn't but is the code between Kotlin JVM and Kotlin Native:
1. Different Compiler and Different Code
2. Different Compiler and Similar Code
3. Different Compiler and Same Code
4. None of the above (please explain)
The Kotlin/JVM and Kotlin/Native compilers share the front-end (the part that performs code parsing, name resolution, type inference etc.), but the compiler back-ends that translate the internal program representation to the target code (the JVM bytecode and LLVM bitcode, respectively) are different.
The Kotlin language accepted by the two compilers is the same, but some of the features and checks are platform-specific. Also, the standard libraries for Kotlin/JVM and Kotlin/Native are sufficiently different, see the APIs available on each platform here: Kotlin Standard Library.
Another big difference is the memory model: Kotlin/JVM uses the Java memory model, while Kotlin/Native offers its own concurrency and memory model.
Also, the dependencies that one can use in Kotlin/JVM and Kotlin/Native projects are different. In addition to the projects built using the same Kotlin target:
Kotlin/JVM can also use any libraries built for the JVM (written in Java, Scala etc.)
Kotlin/Native can also interoperate with native libraries written in C (or at least having C headers) using the C interop tools.
Both Kotlin/JVM and Kotlin/Native can use Kotlin Multiplatform libraries. Given that a dependency is a multiplatform library, one can entirely reuse the code working with it between Kotlin/JVM and Kotlin/Native.

Is it possible to compile Java Bytecode to Native Code using pypy?

pypy currently translates Rpython to Native code using Pluggable JIT and GC. Currently it has a Python frontend . I am wondering if it is possible to write a Java Bytecode frontend to pypy making an alternate cool JVM (written in (R)Python)
An RPython interpreter for Java bytecode wouldn't be a compiler for Java bytecode to native code. The RPython code is compiled to native code, not the code the interpreter is interpreting.
At runtime (some-of) the interpreted code would be JIT-compiled to native code, but that's completely different, and the HotSpot VM already does this. Given that HotSpot has been developed over a long period of time with serious resources behind it, and specifically tuned for Java, I doubt you could get anything even approaching as good as it out of PyPy.
PyPy's strength is the idea that you can write things like garbage collectors and JIT compilers as a framework that works independently of the languages you're interpreting. Then lots of people can write lots of interpreters for lots of languages, and write them in a fairly high-level easy-to-code way, but they still all get high quality GCs, JIT compilers, etc without having to specifically implement them for each language. PyPy is unlikely to be a reasonable alternative to an existing project that has already sunk huge amounts of resources into developing highly optimised GCs and JIT compilers that are specifically tuned for their language.

Is it possible to embed LLVM Interpreter in my software and does it make sense?

Suppose I have a software and I want to make cross-plataform plugins. You compile the plugin for a virtual machine, and any platform running my software would be able to run this code.
I am wondering if it is possible to use LLVM interpreter and bytecode for this purpose. Also, I am wondering if does make sense using LLVM for this purpose instead of something else, i.e. is it what LLVM was made for?
I'm not sure that LLVM was designed for it. However, I doubt there is anything that hasn't been done using LLVM1
Other virtual-machines based script engines are specifically created for the job:
LUA is very popular
Wikipedia lists some other Extension/embeddable languages under the Scripting language entry
If you're looking for embeddable virtual machines:
IKVM supports embedding JVM and CLR in a bridged mode (interoperable)
Parrot supports embedding (and includes a Python interpreter; mind you, you can just run python bytecode images)
Perl has similar architecture and supports embedding
Javascript supports embedding (not sure about the architecture of v8, but I guess it would use a virtual machine)
Mono's CLR engine supports embedding: http://www.mono-project.com/Embedding_Mono
1 including compiling c++ information to javascript to run in your browser...
There is VMIR (https://github.com/andoma/vmir) which is a LLVM bitcode interpreter / JIT engine that's intended to be embedded into other apps.
Disclaimer: I'm the author of it and it's still work-in-progress but works reasonable well.
In theory, there exist a limited subset of LLVM IR which can be portable across various platforms. You shall not specify alignments, you shall not bitcast pointers to integral types, you must avoid intrinsics, etc. Which means - you can't immediately use a code generated by a stock C compiler (llvm-gcc, Clang, whatever), unless you specify a limited target for it and implement sanitising LLVM passes. Another issue is that the bitcode format from different LLVM versions is not guaranteed to be compatible.
In practice, I would not go there. Mono is a reasonably small, embeddable, fast VM, and all the .NET stack of tools is available for it. VM itself is pretty low-level (as long as you do not care about the verifyability).
LLVM includes an interpreter, so if you can build this interpreter for your target platforms, you can then evaluate LLVM bitcode on the fly.
It's apparently not so fast though.
In their classic discussion (that you do not want to miss if you're a fan of open source, LLVM, compilers) about LLVM vs libJIT, that has happened long before LLVM became famous and established, the author of libJIT Rhys Weatherley raised this particular issue, he stated that LLVM is not suitable to be embedded, while Chris Lattner, the author of LLVM stated that otherwise, it is modular and you can use it in any possible fashion including embedding only the parts you need.