harec

[hare] Hare compiler, written in C11 for POSIX OSs
Log | Files | Refs | README | LICENSE

runtime.txt (3245B)


      1 harec expects the runtime to provide some features under the "rt" namespace.
      2 
      3 @noreturn @symbol("rt.abort") fn _abort(msg: str) void;
      4 	Print a diagnostic message and terminate the program.
      5 
      6 @noreturn fn abort_fixed(reason: int) void;
      7 	Print a diagnostic message from a list of pre-determined abort reasons,
      8 	and terminate the program. The list of reasons are:
      9 
     10 	0: Slice or array access out-of-bounds
     11 	1: Type assertion failed
     12 	2: Out of memory
     13 	3: Static append exceeds slice capacity
     14 	4: Unreachable code
     15 
     16 fn memcpy(dest: *void, src: *void, n: size) void;
     17 	Copy "n" bytes from "src" to "dest". The memory areas shall not
     18 	overlap.
     19 
     20 fn memmove(dest: *void, src: *void, n: size) void;
     21 	Copy "n" bytes from "src" to "dest". The memory areas may overlap.
     22 
     23 fn memset(dest: *void, val: u8, n: size) void;
     24 	Set "n" bytes, starting from the address at "dest", to "val".
     25 
     26 fn strcmp(a: str, b: str) bool;
     27 	Compare strings "a" and "b", returning true of they are equal.
     28 
     29 "ensure" and "unensure" are called when slices are expanded or deleted. The
     30 "length" field of the slice will have been updated, and ensure should allocate
     31 or re-allocate the data field to have sufficient space, and update the capacity
     32 field accordingly. "unensure" is called when the space is no longer needed, and
     33 should shrink the allocation as appropriate.
     34 
     35 	type slice = struct {
     36 		data: nullable *void,
     37 		length: size,
     38 		capacity: size,
     39 	};
     40 
     41 	fn ensure(s: *slice, membsz: size) void;
     42 	fn unensure(s: *slice, membsz: size) void;
     43 
     44 "malloc" and "free" are required to support the "alloc" and "free" built-ins.
     45 
     46 	fn malloc(n: size) nullable *void;
     47 
     48 	@symbol("rt.free") fn free_(_p: nullable *void) void;
     49 
     50 The runtime is also expected to provide startup code. A list of function
     51 pointers of type `fn() void` is provided in the __init_array_start and
     52 __fini_array_start globals, which are respectively terminated by
     53 __init_array_end and __fini_array_end. The following Hare code will make these
     54 globals available to the current unit:
     55 
     56 	const @symbol("__init_array_start") init_start: [*]*fn() void;
     57 	const @symbol("__init_array_end") init_end: [*]*fn() void;
     58 	const @symbol("__fini_array_start") fini_start: [*]*fn() void;
     59 	const @symbol("__fini_array_end") fini_end: [*]*fn() void;
     60 
     61 The runtime must call each initialization function, then call the `main`
     62 function (of type `fn() void`), then call all of the finalization functions,
     63 before terminating the program normally.
     64 
     65 When building with +test (harec -T +test), @test functions will be emitted, and
     66 an ELF section, .test_array, will be populated similarly to init_array. The
     67 startup code can enumerate the available tests like so:
     68 
     69 	type test = struct {
     70 		name: str,
     71 		func: *fn() void,
     72 	};
     73 
     74 	const @symbol("__test_array_start") test_start: [*]test;
     75 	const @symbol("__test_array_end") test_end: [*]test;
     76 
     77 In order to use these symbols, a custom linker script must be used. A sample is
     78 provided in rt/hare.sc which is compatible with GNU's ld and LLVM's lld.
     79 
     80 It is expected that, when built in +test mode, the runtime will execute these
     81 test functions instead of calling main. Under these conditions, the runtime is
     82 still expected to call the @init and @fini functions as well, respectively
     83 before and after running the tests.