aboutsummaryrefslogtreecommitdiff
path: root/notes
diff options
context:
space:
mode:
Diffstat (limited to 'notes')
-rw-r--r--notes/arena_io_non_io.txt142
-rw-r--r--notes/backend.txt26
-rw-r--r--notes/easy_linear_types.txt62
-rw-r--r--notes/embedded_binary_interface_data.txt33
-rw-r--r--notes/stdlib_in_slul.txt129
5 files changed, 392 insertions, 0 deletions
diff --git a/notes/arena_io_non_io.txt b/notes/arena_io_non_io.txt
new file mode 100644
index 0000000..6064b98
--- /dev/null
+++ b/notes/arena_io_non_io.txt
@@ -0,0 +1,142 @@
+arena pointers / io vs non-io
+=============================
+
+Could require all "io-capable" objects to have a arena information at
+the beginning of the page (i.e. the address with the low order bits
+set to zero).
+
+This way, constant data can still work as usual without special alignment
+or ordering requirements (e.g. having .rodata before .text in the same page,
+which might not even be possible).
+
+It also allows large data to span across a page boundary, as long as any
+"io-capable" objects are not allocated in a such page (since they need
+the arena-chunk header).
+
+Contents of the arena-chunk
+---------------------------
+
+* Pointer to arena base.
+* Size used in chunk (= offset to next free byte)
+
+If the arena-base is always allocated at a fixed offset (e.g. as the very
+first allocation), then the pointer and the size can be merged into a single
+pointer.
+
+
+Contents of the arena base
+--------------------------
+
+This can be allocated inside the first arena-chunk.
+
+* Capabilities
+* IO-function pointer overrides
+* Chunked-list of pointers to the arena-chunks.
+ (constant-sized block, but can continue in increasing block sizes
+ as normal allocations)
+
+How / where to store information for garbage collection?
+--------------------------------------------------------
+
+Some form of GC would be useful. I don't think it has to be very
+fine-grained, though. It also doesn't have to free everything, but it
+would be good to have some kind of guarantee that it frees e.g. at least
+say 80% of the completely unused "allocation units".
+
+However, "allocation unit" should probably be smaller than the arena-chunk,
+which can be quite large, in particular if the page size is large (like
+64 KiB or even 2 MiB).
+
+It has to be somewhat resistent against attacks. Putting random data that
+happens to resemble pointers MUST NOT affect memory usage, for two reasons:
+1) it could work as a Denial-of-Service attack, and 2) it could cause the
+heap memory base address to be leaked.
+
+The really tricky parts:
+
+* Can it be done without lots of overhead for meta-data / RTTI?
+ - Maybe just a bitmap with 1 bit per pointer-sized word.
+ That's 128 bytes per 4K page on x86, and 64 bytes on x86_64.
+ - It could also be an area that grows down from the top
+ (e.g. run-length encoded). But the overhead might make it
+ less efficient than a bitmap.
+ - Just tracking the pointers is not enough to free parts of a
+ chunk, nor to do copy collection.
+ - That would require knowing the start (or size) of each
+ object.
+ - Could have 2 bits (is-start, contains-pointers)
+ - Or could store only sizes.
+ - Maybe it doesn't need object granularity?
+ - Could have an "end-bit" per e.g. pointer-sized word.
+ It would indicate if at least one object ends inside the word.
+ Granularity -> Size usage -> Percentage of 4K page on 32-bit:
+ 8 bytes 128+128 = 256 6.25%
+ 64 bytes 128+8 = 136 3.32%
+ - With a pointer-bitmap + a 1 byte size (16 byte granularity),
+ assuming 20 byte allocations on average:
+ 16 bytes 128+204 = 332 8.11%
+ assuming 60 byte allocations on average:
+ 16 bytes 128+68 = 196 4.79%
+* With non-io chunks, the meta-data may cover a larger (combined) chunk, and
+ hence the meta-data part will be larger, too.
+* Is limited granularity a problem when detecting live objects.
+ - Yes, it will be less accurate! Objects within the same "object-block"
+ that have a higher address will be incorrectly assumed to be in use.
+* Can GC'ed objects safely be read by C code?
+* Can GC'ed objects safely be modified by C code?
+* Is any temporary space required to perform GC?
+ - Needs to mark used object-blocks.
+ - Needs to queue objects to scan?
+
+Weird ideas:
+
+* Keep an allocation journal (with object sizes and locations of pointers)
+ - Has to be very fast to append to.
+ - Has to be very compact.
+ - Even with only 1 byte used:
+ with avg alloc size of 20 bytes => 5.00% overhead
+ with avg alloc size of 60 bytes => 1.67% overhead
+* Extremely coarse-grained GC:
+ - Just have a bitmap of pointers, don't bother about sizes.
+ Size: pagesize/ptralign/8
+ Overhead: 1.56% (64b) - 3.13% (32b)
+ (pagesize/ptralign/8)/pagesize = 1/(ptralign*8)
+ Possibly no overhead with CHERI
+ (because it already tracks this info)
+ - Track pointers that might point to another arena-chunk
+ (or even another arena).
+ - Garbage collect only entire arena-chunks.
+* Track only allocations in the "topmost" arena-chunk
+ (the one where new allocations go).
+ - Use a bitmaps for:
+ - words that contain a pointer
+ - allocation start status per word:
+ - 00 = inside allocation
+ - 01 = inside allocation, and is the last word of it
+ - 10 = start, hasn't escaped
+ - 11 = start, could have escaped
+ - 3 bits in total per word.
+ - On simple allocations w/o pointers, only a single bit has to be set
+ - Allocations with pointers will be word-aligned, so setting the
+ bitmap bits should be easy for them as well (on 64b platform it's
+ just a byte-aligned OR to the bitmap)
+ - Escaped blocks cannot be moved
+ - Therefore, trigger GC before escaping a block if let's say
+ >= 50% of the arena-chunk has been used and no GC has been
+ performed.
+ - Track free "holes", so escaped blocks can be moved there quickly
+ (by just copying them and updating the refs to them.
+ the refs update is just a linear scan).
+ - Set a "might need GC" flag when a pointer (that at least before pointed
+ to the arena-chunk) is somehow changed.
+ - Just adding new pointers cannot trigger GC
+ - Note that the pointers can come from stack or other chunks.
+ - Scan all words marked as containing a pointer
+ - Can use the next unallocated page as a temporary storage
+ - Will be all 0 at start
+ - Needs to be all 0 at end
+ - Is it possible to use dynamic programming can be used to scan
+ linearly a few times?
+ - If not, simply queue the roots and start scanning from those.
+ - Unmarked words are then free.
+ - Re-pack the movable words to use space more efficiently.
diff --git a/notes/backend.txt b/notes/backend.txt
new file mode 100644
index 0000000..c93c20e
--- /dev/null
+++ b/notes/backend.txt
@@ -0,0 +1,26 @@
+* safe&portable IR vs low-level IR
+ - lots of common stuff across ISAs.
+ - calling conventions (e.g. struct passing) can be complex and
+ it would be good to be able to re-use things that are common.
+ - some optimizations might be easier to do on the low-level IR
+ (and vice versa).
+* register alloc can be tricky:
+ - division on x86 is AFAIK limited to specific regs (eax,edx?)
+ - loop instructions on x86
+ - apparently r0 is unavailable in some insns on sh4?
+ - on x86_64, some regs require prefix bytes
+ - types:
+ - byte/short/int that can use parts of a reg on x86
+ - int/long distinction on aarch64
+ - floating point regs
+ - multi-reg types, typically on 32 bit arches:
+ - 64 bit int on i386
+ - 64 bit double on MIPS?
+ - "special-purpose general-purpose" regs
+ - as above, reg for division, looping, etc.
+ - CHERI and pointers
+* floating point
+ - differences across architectures?
+ - calling conventions
+ - alignment, corner cases, etc.
+ - also, see reg alloc
diff --git a/notes/easy_linear_types.txt b/notes/easy_linear_types.txt
new file mode 100644
index 0000000..8c60122
--- /dev/null
+++ b/notes/easy_linear_types.txt
@@ -0,0 +1,62 @@
+Easy-to-use linear types
+========================
+
+Allow simple usage of linear types when using only local variables
+and/or parameters and/or return values.
+
+Have a "lock system" with automatic garbage collection (collected no later
+than when the arena is destroyed) for more complex cases.
+
+
+Assume that `open` create a linear/owned `File` type.
+
+Trivial case:
+
+ func stuff
+ code
+ own File f = open "file.txt" .write
+ write f "hello" # uses `f` but does not take ownership
+ close f # takes ownership of `f`
+ end
+
+Nested case:
+
+ func get_file
+ returns
+ own File f
+ code
+ # Allow simple usage when returning
+ return open "file.txt" .write
+ end
+
+Complex case:
+
+ func maybe_open_file
+ code
+ if use_file
+ #
+ begin_ownership thefile
+ thefile = open "file.txt" .write
+ suspend_ownership thefile
+ # disallow changing the `file` variable when it is
+ # suspended?
+ end
+ end
+
+ func maybe_write_to_file
+ code
+ if use_file
+ resume_ownership file
+ write thefile "hello"
+ suspend_ownership file
+ end
+ end
+
+ func maybe_close_file
+ code
+ if use_file
+ resume_ownership thefile
+ close thefile
+ end_ownership thefile
+ end
+ end
diff --git a/notes/embedded_binary_interface_data.txt b/notes/embedded_binary_interface_data.txt
new file mode 100644
index 0000000..ad99bbd
--- /dev/null
+++ b/notes/embedded_binary_interface_data.txt
@@ -0,0 +1,33 @@
+Would it be a good idea or not to include the interface of libraries into
+the binary (.so/.dll) files themselves?
+
+This would then have to include:
+* the name and version of the library
+* for each API-version:
+ - function parameters and returns (names and types)
+ - function constraints (if this is added)
+ - struct/types
+* interface dependencies on other libraries and their versions
+* runtime dependencies on other libraries and their versions
+
+Implementation details
+----------------------
+
+Regarding the ELF format, should be be a section or a segment?
+Also, should it have SH_ALLOC or not?
+
+I think that the `strip` program removes everything that doesn't
+have SH_ALLOC?
+
+Maybe it could use ELF .note.* / SHT_NOTE?
+ - .note.slul-module (name and version)
+ - .note.slul-api (API-versions)
+ - .note.slul-bdeps (interface/build dependencies)
+ - .note.slul-xdeps (runtime/execution dependencies)
+
+Problems
+--------
+
+Some distributions (e.g. Fedora) explicitly say that they want to keep the
+distribution small for those who don't need development files. So maybe it's
+a bad idea to make the library files larger for everyone?
diff --git a/notes/stdlib_in_slul.txt b/notes/stdlib_in_slul.txt
index 0479024..99c7953 100644
--- a/notes/stdlib_in_slul.txt
+++ b/notes/stdlib_in_slul.txt
@@ -32,6 +32,27 @@ Write those things in:
e.g. Hare uses QBE, which has somewhat limited target support)
* Formally-verified IR/assembler (see below)
+Discourage people from writing in the unsafe language
+-----------------------------------------------------
+
+It would be sad if the safe SLUL language loses out to an unsafe cousin
+language. So IF an unsafe cousin language is ever created, it should
+1) be very clear that it is NOT slul, and 2) discourage it's use by making
+it an "unappealing" language.
+
+Make it explicitly a different language:
+* Different name (uhoh? oops? noo? slunsafe?)
+* Different file extension (.rtlc? .stdlib? .lul? .uhoh? .rtlu? .noo? .rsy? .slunsafe?)
+* Different syntax
+
+Make it ugly but still readable:
+* Use uppercase keywords?
+* Or use some sigill?
+
+Make unsafe stuff really stand out:
+* Maybe require an UNSAFE_xxx keyword around anything unsafe
+
+
Hard-core solution: formally verified IR/assembler
--------------------------------------------------
@@ -55,3 +76,111 @@ For registers, and for fields in structs in memory:
* not null
* length of field F
* etc.
+
+Hard-code solution 2: write a C compiler in SLUL
+------------------------------------------------
+
+Could write a C compiler in SLUL, using the same backend as the SLUL
+compiler will use.
+
+This could even be a subset of C89 (+ some things like uint64_t etc.).
+Candidates for things to remove/forbid:
+* digraphs/trigraphs
+* float/double
+* varargs (both usage, declarations and va_list etc.)
+* multi-char chars
+* octal literals and escape sequences
+* assuming char is either signed or unsigned, i.e. assigning < 0 or >= 128
+* strange control structures:
+ - case not directly under switch
+ - statements between switch and first case
+ - not using {} when block comes on a separate line
+* some types:
+ - void *
+ - wchat_t
+* several casts:
+ - pointer to/from int
+ - function ptr to/from other data pointer types
+* depending on operator precedence of:
+ - & vs && levels
+* declarations:
+ - * vs [] precedence
+ - prototypes: `f()`
+ - auto/register storage classes
+ - common initialization: `static int i;` or `int i;` at top-level.
+ - volatile
+ - new struct/enum inside function parameter list
+* unwanted macros:
+ - __DATE__, __TIME__
+ - #pragma
+* stdlib except for:
+ - memset, memcmp, memcpy, strlen
+
+
+Syntax test
+-----------
+
+Using UNSAFE_ everywhere to make unsafe stuff stand out and to make the
+language more ugly.
+
+Using __ in identifiers to avoid collisions and also for increased ugliness.
+
+Using % before all keywords for even more ugliness.
+
+
+ %func __init_arena
+ %code
+ [UNSAFEPointer base_ptr, UNSAFESize pgsize] = __sys_mmap 1
+ ArenaBase base_info %UNSAFE_OVERLAY base_ptr
+ .chunk = [
+ # ability to merge base pointers and offsets?
+ #.info = %UNSAFE_ADDROF .base %UNSAFE_PTRADD %UNSAFE_OFFSETOF .freespace
+ .baseptr = %UNSAFE_ADDROF .base
+ .alloced = %UNSAFE_OFFSETOF .freespace
+ .size = pgsize
+ ]
+ .base = [
+ # capability info, list of chunks, ...
+ ]
+ .freespace = []
+ %end
+ %end
+
+ %UNSAFE_GLOBAL __pagesize
+
+ %func __sys_mmap
+ int npages
+ %code
+ %%SYS_if os linux
+ __syscall6 NR_mmap2 ...
+ %%SYS_elif os windows
+ __sys_VirtualAlloc ...
+ %%SYS_endif
+ %end
+
+ %%SYS_switch os
+ %%SYS_case linux
+ %func __syscall6
+ int syscall_number
+ unsigned long arg1
+ ...
+ unsigned long arg6
+ %code
+ %SYS_switch cpu
+ %SYS_case aarch64
+ %UNSAFE_asmdef $sysc($n) $w32_le(...)
+ ...
+ %SYS_case i386
+ %UNSAFE_asmdef $int($n) CD $n
+ # Should probably use the vdso instead...
+ %UNSAFE_machinecode $int(80)
+ %SYS_case x86_64
+ ...
+ %SYS_endswitch
+ %end
+ %%SYS_case windows
+ %func __sys_VirtualAlloc
+ ...
+ %dllimport "kernel32.dll" "VirtualAlloc"
+ %end
+ %%SYS_endswitch