Documentation ¶
Overview ¶
Command qbec is a compiler for the QBE intermediate language
Overview ¶
QBE intermediate language introduction:
https://c9x.me/compile/
QBE reference:
https://c9x.me/compile/doc/il.html
QBE vs LLVM:
https://c9x.me/compile/doc/llvm.html
Installation ¶
To install/update qbec invoke:
$ go get [-u] modernc.org/qbe/qbec # Go 1.15
or
$ go install [-u] modernc.org/qbe/qbec # Go 1.16
Online documentation ¶
See https://pkg.go.dev/modernc.org/qbe/qbec
Supported platforms, architectures and compilers ¶
The code is tested/known to work on
os arch compiler ------------------------------------------------- darwin amd64 gcc (Homebrew GCC 11.1.0) 11.1.0 linux 386 gcc (Debian 8.3.0-6) 8.3.0 linux amd64 gcc (Debian 8.3.0-6) 8.3.0 linux arm gcc (Raspbian 8.3.0-6+rpi1) 8.3.0 linux arm64 gcc (Ubuntu 10.2.0-13ubuntu1) 10.2.0 linux s390x gcc (SUSE Linux) 7.5.0 windows amd64 gcc (x86_64-posix-seh-rev0, Built by MinGW-W64 project) 8.1.0
Other C compilers/gcc versions may work too, provided they support these non-standard C extensions:
__attribute__ ((aligned (<expr>))) __attribute__ ((constructor)) __attribute__ ((noinline))
Principle of operation ¶
qbec wraps the system C compiler as defined by the environment variable CC. If CC is not set it defaults to 'gcc'.
qbec detects all arguments with extension .qbe, compiles them to C files in a temporary directory and replaces the arguments with the pathnames of the generated C files. Finally the compiler calls the C compiler with the adjusted arguments to create the executable/object/asembler file according to any other provided command line options that are passed unchanged.
Environmental variables ¶
These can change the behavior of qbec.
QBEC_CC, CC
Selects the back end C compiler. First QBEC_CC is tried. If empty then CC and if empty the default is 'gcc'.;
TARGET_OS
Include files required by the back end compiler may differ per OS. Setting TARGET_OS to the correct value ensures the proper choice. The value to use is searched in this order: TARGET_OS, GOOS, runtime.GOOS.
TARGET_ARCH
Not currently used, but may serve a similar purpose as TARGET_OS. The value to use is searched in this order: TARGET_ARCH, GOARCH, runtime.GOARCH.
Compiling binaries ¶
For example, having
$ cat hello.qbe export function w $main() { @start call $printf(l $fmt, ...) ret 0 } data $fmt = { b "Hello, world!\n", b 0, } $
To produce an executable file:
$ qbec -w hello.qbe && ./a.out Hello, world! $ file a.out a.out: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=f6a2263302a37d182fe9f5264090d62ce89fbe2b, not stripped $
Cross platform issues ¶
The QBE intermediate language is cross-platform, but a particualar QBE program is not. In the above example the first parameter to stdio's printf is of type 'l', ie. hard-coded to be 64 bit wide. That works only for architectures having 64 bit pointers.
Cross compiling ¶
Cross compiling requires the correct cross compiler to be installed and setting CC to point to it. For example having
$ cat hello32.qbe export function w $main() { @start call $printf(w $fmt, ...) # Note the 'w' type specifier. ret 0 } data $fmt = { b "Hello, world!\n", b 0, } $
To produce a 32 bit executable binary on a 64 bit platform:
$ CC=i686-linux-gnu-gcc qbec -w hello32.qbe && ./a.out Hello, world! $ file a.out a.out: ELF 32-bit LSB pie executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=639a23ff35cab438f14b8cc65934ee9734c45a64, not stripped $
Warnings ¶
QBE intermediate language often provides insufficient information to fully infer types of external symbols. That's why the extern symbols in the intermediate C form may not be compatible withe the actual definitions in, say libc. For example
$ qbec hello.qbe && ./a.out /tmp/qbec-810952345/0.c:7:13: warning: conflicting types for built-in function ‘printf’ [-Wbuiltin-declaration-mismatch] extern void printf(); ^~~~~~ Hello, world! $
As seen above, the warning is harmless, the linker produced a working binary anyway.
It's possible to turn off the warnings by adding the -w flag.
$ qbec -w hello.qbe && ./a.out Hello, world! $
Limitations ¶
qbec does not support the environmental function parameter/argument, as defined at
https://c9x.me/compile/doc/il.html#Functions