qbec

command
v0.0.9 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 10, 2023 License: BSD-3-Clause, MIT Imports: 3 Imported by: 0

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

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL