I've coded a fronted in C++ to exploit LLVM core in order to get a PHP file and generate an IR for a classical architecture. I'm able to run this code with embedded JIT compiler of LLVM.
I would produce an IR to WebAssembly. I'm using LLVM 6.0 with WebAssembly as target built
$ llvm-config --targets-built
AArch64 AMDGPU ARM BPF Hexagon Lanai Mips MSP430 NVPTX PowerPC Sparc SystemZ X86 XCore WebAssembly AVR
I've set this update in my code
...
LLVMSetTarget((LLVMOpaqueModule *)context->module, "wasm32");
...
Now I noticed that dupmed IR code is identical with or without my code edit, and I've followed this pipeline to generate my wasm file
$ llc -asm-verbose=false -march=wasm32 -o my.s my.bc
$ binaryen/bin/s2wasm my.s > my.wast
$ wabt/bin/wat2wasm my.wast -o my.wasm
But when I run
$ node ./runwasm.js my.wasm main
I get the following error
RuntimeError: memory access out of bounds
I can't understand where is the problem because if I follow this tutorial, I will not get any error.
Suggestions?
Related
How can I make use of llvm as clang backend to compile C++ files without using gcc as clang's backend?
I am pretty sure clang is using gcc because
$ clang++ --version
clang version 6.0.1 (tags/RELEASE_601/final)
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: /usr/local/bin
it uses gnu as target instead of llvm. My llvm-config output:
$ llvm-config --version --targets-built
6.0.1
X86
I built both clang and llvm from source using standard options for my build target(X86).
EDIT: I think it is using gcc as backend because this code produces error in online ide but works on my machine with clang++ and g++. Code relies on fact that gcc has implementation of policy based data structures which are not part of standard.
The problem is in the interpretation of the data. The target that clang refers to has to do with the platform for which you are generating code.
x86_64 This is a 64 bit processor compatible with Intel/and
unknown I'm uncertain about this one, though I believe it specifies more detail about the processor, which ain't available
linux You are using a Linux kernel/operation system
gnu The object structure should follow the gnu standards, I believe this directly maps on ELF
This will be different if you use BSD or windows as OS, or when your processor is an ARM, Intel 32 bit, Spark ...
The only moment you should be worrying about the target is when you are cross compiling. In other words, if the computer on which you are running the compiler has other requirements for the executable structure than the machine on which you will be running it.
PS: Clang always uses LLVM for it's IR. ignoring the deprecated Clang+C2, it always uses the LLVM optimizer and code generator.
I am using Archlinux and installed LLVM using the official package (using pacman -S llvm).
I'd like to use it with the wasm-32 backend (available according to the source code).
However, this backend is not enabled on my computer:
$ llc --version
LLVM (http://llvm.org/):
LLVM version 5.0.0
Optimized build.
Default target: x86_64-unknown-linux-gnu
Host CPU: skylake
Registered Targets:
aarch64 - AArch64 (little endian)
aarch64_be - AArch64 (big endian)
amdgcn - AMD GCN GPUs
arm - ARM
arm64 - ARM64 (little endian)
armeb - ARM (big endian)
bpf - BPF (host endian)
bpfeb - BPF (big endian)
bpfel - BPF (little endian)
hexagon - Hexagon
lanai - Lanai
mips - Mips
mips64 - Mips64 [experimental]
mips64el - Mips64el [experimental]
mipsel - Mipsel
msp430 - MSP430 [experimental]
nvptx - NVIDIA PTX 32-bit
nvptx64 - NVIDIA PTX 64-bit
ppc32 - PowerPC 32
ppc64 - PowerPC 64
ppc64le - PowerPC 64 LE
r600 - AMD GPUs HD2XXX-HD6XXX
sparc - Sparc
sparcel - Sparc LE
sparcv9 - Sparc V9
systemz - SystemZ
thumb - Thumb
thumbeb - Thumb (big endian)
x86 - 32-bit X86: Pentium-Pro and above
x86-64 - 64-bit X86: EM64T and AMD64
xcore - XCore
How can I enable LLVM backends?
EDIT (2021-07-23): This answer was updated to use "Motorola 68000" instead of "WebAssembly" as an example experimental target (since Wasm is now stable).
LLVM is not very configurable once it is built.
If you need a configuration beyond the defaults, you have to compile LLVM yourself.
LLVM has a few articles explaining how to compile it, but it does not describe exactly
how to enable additional targets:
Getting Started
Building LLVM with CMake
The enabled targets are controlled by two variables that you need to define when invoking CMake
to prepare the build directory: LLVM_TARGETS_TO_BUILD and LLVM_EXPERIMENTAL_TARGETS_TO_BUILD.
LLVM_TARGETS_TO_BUILD controls only the stable targets.
You can either use the special value all to enable all the stable targets or provide a semicolon-separated list of targets such as ARM;PowerPC;X86. There is an old request
to rename the special value to stable and use all for all the targets.
Its default value is all (see below for the list of targets).
LLVM_EXPERIMENTAL_TARGETS_TO_BUILD is an undocumented (or well hidden) variable that allows you
to enable any target you want. This is also a semicolon-separated list of targets.
The enabled targets will correspond to the union of both lists.
Now, you need to find out the actual name of your target and if it is a stable or experimental target.
The list of stable targets can be found in the Getting Started article.
The default value includes: AArch64, AMDGPU, ARM, AVR, BPF, Hexagon, Lanai, Mips, MSP430, NVPTX, PowerPC, RISCV, Sparc, SystemZ, WebAssembly, X86, XCore.
This list is defined in the main CMakeFile (permalink).
As you can see, WebAssembly is in the list now (in 2021), so it should already be enabled by default. When the question was first asked, it was still an experimental target.
When the question was first asked, WebAssembly was still an experimental target so the rest of the answer will more generally describe how to enable any target. As an example, we'll use "Motorola 68000" instead of wasm.
"Motorola 68000" is not in the list of stable targets. We'll have to find the name used by LLVM and then use LLVM_EXPERIMENTAL_TARGETS_TO_BUILD.
Unfortunately, since this variable is not documented, I wasn't able to find the list of all the targets on their website.
After some trial and error, it seems that the available targets correspond to the names of the directories in /lib/Target. This directory contains a subdirectory named M68k: this is likely the name of the target.
To use LLVM for "Motorola 68000", you'll need to enable the M68k target using the LLVM_EXPERIMENTAL_TARGETS_TO_BUILD
variable when preparing the build directory with CMake.
Here are the steps to compile LLVM with "Motorola 68000" support (adapt it to your own requirements). I used a Linux machine
but you should be able to adapt it to your environment.
Requirements:
CMake
Git
GCC, CLang or Visual Studio depending on your platform
zlib
Clone the LLVM repo. I'll use the /opt/llvm-project directory for the home directory
of my custom version of LLVM (this is the last argument to the command, replace it by the path you want to use).
git clone https://github.com/llvm/llvm-project.git /opt/llvm-project
Navigate to the LLVM sources:
cd /opt/llvm-project/llvm
Create your build directory and navigate to it.
mkdir build && cd build
Use CMake to prepare your build directory. This is the step where you need take care
of setting the variables. In my case I'll use LLVM_EXPERIMENTAL_TARGETS_TO_BUILD="M68k" and
leave LLVM_TARGETS_TO_BUILD to its default value (all stable targets).
Another important variable that I'll set is CMAKE_BUILD_TYPE=Release to get an optimized build and
CMAKE_INSTALL_PREFIX=/opt/llvm-project/llvm/bin to keep this version of LLVM in its directory and do
not interfere with the version I already have on my system (I'll just add this directory to the $PATH
when I'll need it).
cmake -G "Unix Makefiles" -DLLVM_EXPERIMENTAL_TARGETS_TO_BUILD="M68k" -DCMAKE_INSTALL_PREFIX=/opt/llvm-project/llvm/bin -DCMAKE_BUILD_TYPE=Release /opt/llvm-project/llvm
Build LLVM, this may take a while:
cmake --build .
Install LLVM:
cmake --build . --target install
You should compile your backend from source. The only pluggable things in LLVM are passes currently.
Your llc --version command says that you installed LLVM version 5.0.0. WASM wasn't integrated into LLVM until LLVM 8.0.0. It was experimental before that.
Changes to the WebAssembly Target
The WebAssembly target is no longer “experimental”! It’s now built by
default, rather than needing to be enabled with
LLVM_EXPERIMENTAL_TARGETS_TO_BUILD.
The object file format and core C ABI are now considered stable. That
said, the object file format has an ABI versioning capability, and one
anticipated use for it will be to add support for returning small
structs as multiple return values, once the underlying WebAssembly
platform itself supports it. Additionally, multithreading support is
not yet included in the stable ABI.
https://releases.llvm.org/8.0.1/docs/ReleaseNotes.html#changes-to-the-webassembly-target
I am looking into using llvm tools to generate block level profile of small programs. It looks like in older versions this was as simple as running:
perl utils/profile.pl -block program.bc
How is profiling done in newer versions of LLVM?
Use Clang and llvm-profdata
Visit the Clang User's Manual profile with instrumentation
llvm doc llvm-profdata
In summary:
Build an instrumented version of the code
clang -O2 -fprofile-instr-generate code.c
Run the instrumented executable to get the profile data file
./a.out
Combine profiles from multiple runs and format the files by running
llvm-profdata merge *.profraw -output=code.profdata
Build the code again
clang -O2 -fprofile-instr-use=code.profdata code.c
(Optional?) 5. Display the profile counters for this file and for any of the specified function(s)
llvm-profdata show -all-functions code.profdata
So here's the situation: I need to be able to compile binaries from a Linux machine (on Ubuntu, for what it's worth) which are able to run from a SPARC server. The program I'm trying to compile is very simple:
#include <stdio.h>
#include <stdlib.h>
int main() {
printf("Testing the SPARC program...");
return EXIT_SUCCESS;
}
I've tried a number of different compile lines to get it to work, but unfortunately nothing appears to be working.
I tried the traditional:
clang -target sparc blah.c -o blahsparc
But this doesn't work, with a bunch of assembler failures:
/tmp/blah-519e77.s: Assembler messages:
/tmp/blah-519e77.s:7: Error: unknown pseudo-op: '.register'
/tmp/blah-519e77.s:8: Error: unknown pseudo-op: '.register'
/tmp/blah-519e77.s:9: Error: unknown pseudo-op: '.register'
/tmp/blah-519e77.s:10: Error: unknown pseudo-op: '.register'
/tmp/blah-519e77.s:11: Error: no such instruction: 'save %sp,-240,%sp'
/tmp/blah-519e77.s:12: Error: no such instruction: 'st %g0, [%fp+2043]'
...
clang: error: assembler (via gcc) command failed with exit code 1 (use -v to see invocation)
I've tried this also:
clang -cc1 -triple "sparc-unknown-Linux" blah.c -o blahsparc
which complains about the missing headers, so instead of using -cc1, I use -Xclang:
clang -Xclang -triple -Xclang "sparc-unknown-Linux" blah.c -o blahsparc
however, this also fails due to "error: unknown target CPU 'x86-64'".
I'm not sure where to proceed with this. I've tried using crosstool-ng as well with very little success.
As of the 3.4.2 release (June 2014), llvm is missing code necessary to be able to generate object files for sparc targets. Older releases (1.x & 2.x) had support for it, but llvm's framework for emitting object files was less mature back then. When the current framework was rolled out it looks like they didn't migrate all platforms.
The documentation seems to imply that a combination of llvm/gcc is known to work, but I think that table was tabulated based on a much earlier version of llvm when they had a less mature framework for emitting object files.
Support for emitting object files was added to their SVN trunk in revision r198533 (this thread discusses the commit), but as you can see in the 3.4.2 final release, files & changes added in r198533 aren't present.
As an aside, clang currently isn't functional in sparc solaris (not sure about sparc in general). The parser seems to have trouble parsing templates; I get coredumps & the like. I ran across a thread a week or so ago discussing alignment problems in sparc/solaris clang, and this may be one of the reasons clang isn't yet usable on this platform.
If you need a cross compiler for Sparc that runs on an Ubuntu machine, the simplest way I know of is to use Buildroot. Here's a small tutorial on how to obtain a cross compiler and test the generated executables on a Sparc emulator.
LLVM 3.6.2 has some support for sparc now... I was able to build llvm 3.6.2 and clang 3.6.2-r100 on my T2000. I haven't gotten C++ support working but I have built moderately complex C applications like htop.
I did compile LLVM using gcc 5.2 however I lower version should work as well although I'd suggested at least gcc 4.9 and no lower than gcc 4.7.
The LLVM emerge on gentoo crashed during the compile but I was able to resume it by moving to the portage directory with the llvm ebuilds and restarting the build manually:
cd /usr/portage/*/llvm/
ebuild llvm-3.6.2.ebuild merge
I had to override some of the default compiler:
CC="clang -target sparc-unknown-linux-gnu"
CXX="clang++ -target sparc-unknown-linux-gnu"
CFLAGS="-O2 -pipe"
CXXFLAGS="${CFLAGS}"
I don't know if you will be able to use this to build from an x86 machine... though clang is supposed to be able to do that. But worst case you might be able to get this going in qemu-system-sparc64 vm or on some real hardware that you can find cheap on ebay (T5xxx hardware is coming down in price and blades are dirt cheap)
I recently updated to clang 3.8 (which is as yet unreleased) and I was able to compile a c++ application by passing -lstdc++ in addition to the options above. I believe this is the same behavior as gcc when invoked as gcc rather than g++.
I'm under Ubuntu 12.04 x86 64 bit, I have compiled a 32 bit version of llvm/clang from the official svn repository successfully.
I'm now trying to compile c++ code for ARM, at this point i don't care about platform versions like armv5 vs armv7a, I'm focusing on how the platform switch works for clang:
llvm-config --targets-built
ARM CellSPU CppBackend Hexagon Mips MBlaze MSP430 NVPTX PowerPC Sparc X86 XCore
but the following command doesn't work
clang++ -arch arm soft.cpp -o soft_ARM
the output is
clang-3: warning: argument unused during compilation: '-arch arm'
I have also tried gcc-like variants or other combinations like -arch=arm, -arch=armv7a, -march=armv5 but nothing seems to work.
After reading some docs i noticed that clang works for ARM only under MAC OS X / Darwin and it's not supposed to work for ARM under other OS.
How i can compile for ARM with clang and what the output of llvm-config --targets-built is really about ?
-arch is darwin-only feature. You should use -target on non-darwin platforms. Alternatively, compile llvm/target specifying target triplet or create a link from clang to -clang. In your case the target triplet would be arm-none-linux-gnueabi