summaryrefslogtreecommitdiff
path: root/docs/appendices/native-libraries.md
blob: 5412ab6a5cbfe971cf6da76f74120cf6677f7573 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# Native library construction

The complete compiler is [Chapter 28b](../../chapter28b/README.md). This appendix
collects the library and native support that accompanied the old combined
Chapter 25. The split preserves that functionality in Chapter 28b.

## Building the library

From `chapter28b`, run:

```sh
make lib release
```

Make builds `build/release/Simple.jar` and, under the selected CPU/ABI directory,
`sys.o`, the child objects under `sys/`, and `simple_crt.o`. The default CPU is x86-64; the default calling
convention is win64 on Windows and SystemV elsewhere. Rebuild serialized
objects after changing the compiler or object format.

`src/main/smp/sys.smp` exposes child units for native libc bindings, I/O,
characters, scanners, arrays, growable buffers, and bitsets. These compile into
one object per compilation unit. Clients read declarations and function
summaries first, then request an object's IR when considering inlining.
Native linking follows recorded object dependencies even when the optimizer
never loads their bodies. Install the complete object tree alongside `sys.o`;
there is no runtime object loading. Function-level IR loading within an object
and a complete incremental build driver remain future work.

The `simple.sh`, `simple.ps1`, and `simple.bat` launchers set `SIMPLE_HOME` so
the compiler can find the release library. The CLI accepts `-L` for additional
Simple objects or search directories. The chapter README gives an explicit
library/client example that needs no library source in the client root.

## Native symbols and pointer sizes

Native function calls and numeric native data symbols have ELF relocations.
The historical `Chapter25Test.testExternDataEncoding` and `testExternDataImports`
exercise native data; `StaticDataTest` covers addresses
and static images. A data symbol names storage, whereas a function symbol names
callable code; loading the former and calling the latter require different IR.

Simple function pointers currently occupy four bytes. On AMD64, a native
function address names a low-address tail-jump thunk, which can reach native
code outside that range. A weak symbol gives static fields and computed
addresses the same entry across objects; direct calls can still use the native
PLT. This preserves constant initialization of function fields without storing
an eight-byte native address in a four-byte slot. The native linker must place
these Simple entries in the representable address range.

Data pointers still occupy eight bytes. Compact code/data arenas and distinct
full-width native pointer types are [future designs](../roadmap.md#compact-code-and-data-arenas).

## Runtime and examples

`src/main/c/simple_crt.c` supplies the errno accessor and converts native process
arguments to Simple byte arrays for an exported `simple_main` function. This
explicit function entry is distinct from the language's class initializer:
the selected initializer still receives the integer `arg`. General class
initializer argument arrays remain a roadmap item.

The executable examples live in
[`src/test/smp/examples`](../../chapter28b/src/test/smp/examples): Hello World,
Bubble Sort, Capitalize, Dijkstra, and FileIO. The existing Chapter25Test tests
compile and link them through the native harness. `make tests` builds the
library/runtime prerequisites and runs those checks; a Java-only build does
not produce the native prerequisites.

The compiler's in-memory evaluator and the native driver have different entry
interfaces. Use the matching harness when comparing their results, especially
for programs taking an argument array or performing I/O.