this is my first Stackoverflow question :-)
My background:
Facts: - crystal-lang is compiling and running without any problem - running on x86_64
Please be nice, as i don't have much low-level language knowledge yet.
From my understanding, when we compile and run a basic hello.c file using LLVM, it goes as follow:
hello.c :
#include
int main() {
printf("hello world\n");
return 0;
}
shell :
$ clang -O3 -emit-llvm hello.c -c -o hello.bc
$ llc hello.bc -o hello.s
$ gcc hello.s -o hello.native
$ ./hello.native
this comes from the LLVM examples )
My point is that we can produce a pretty short hello.bc file (128 lines) that can be run in a slower way using:
$ lli hello.bc
but when I tried to generate a similar hello.bc from a hello.cr file and run it like i did with the hello.c file:
hello.cr :
puts "hello world"
shell :
$ crystal build hello.cr --emit llvm-bc --release
$ llc hello.bc -o hello.s
what i noticed:
This hello.bc can't be run using "lli" as it generates an:
"LLVM ERROR: Program used external function 'pcre_malloc' which could not be resolved!
I can't even compile from hello.s to hello.native
As i understood, LLVM is portable , and that all front-end languages would produce an intermediate *.bc that can then be compiled to any architecture.
My questions are:
Thank you!
NOTE: The Clang/LLVM Compiler naming convention has changed so that the version number reflects the community version. The previous had the installation command of llvm-toolset-7 which was based on Clang/LLVM 6.0. If you encounter difficulties at any point, see Troubleshooting and FAQ.
If the -o option is omitted, the clang++ compiler creates a file named a.out by default. When you are working on a project that consists of several source files, it is common to compile an object file for each of the source files first and then link these object files together.
$ scl enable llvm-toolset-7.0 'clang++ -o output_file object_file...' Note that you can execute any command using the scl utility, causing it to be run with the LLVM Toolset binaries available. This allows you to run a shell session with LLVM Toolset clang directly available:
When clang++ compiles a program, it creates an executable binary file. To run this program on the command line, change to the directory with the executable file and type: $ ./hello Hello, World! To run a C program, see the documentation instructions.
Everything is just as it is supposed to be. Crystal has a runtime library that is always present even if you didn't include anything. This is required to run the Crystal program.
The C example pretty much doesn't contain anything else than a syscall to printf
. That's why the compiled ASM is also really tiny.
Crystal's simple puts
call has a much more behind it. It is based on libraries for handling asynchronous IO, concurrency, signal handling, garbage collection and more. Some of these libraries are completely implemented in the Crystal standard library, some use other libraries that are either directly embedded into the binary (libgc
) or still require dynamic libraries from the system (libpcre
, libpthread
).
Any Crystal program comes with this runtime library by default. Even an empty program. This usually goes completely unnoticed because larger programs will eventually need those things anyway and the compiled binary size of the runtime library is less than 500 KB (in release mode). Such a small program like yours doesn't really need all of this just to print a string. But these libraries are required for the Crystal runtime.
NOTE: You can compile a Crystal program without these default libraries. But this means you can't use anything from the Crystal stdlib and you have to essentially write C code with Crystal syntax (or implement your own stdlib):
require "lib_c"
require "c/stdio"
LibC.printf pointerof("hello world".@c)
This can be compiled with --prelude=empty
option and it will generate a substantially smaller ASM, roughly similar to the C example.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With