# A sketch of Mu-style handles or kinda-safe pointers, that add a modicum of # checking to dynamically allocated memory. # # This approach avoids using 'allocate' directly in favor of two primitives: # - 'new', which allocates some space (the 'payload'), stores the address # along with an opaque 'alloc id' in a 'handle', and prepends the same # alloc id to the payload. # - 'lookup', which checks that the alloc id at the start of a handle matches # the alloc id at the start of the payload before returning the address. # # Layout of a handle: # offset 0: alloc id # offset 4: address # # To run (from the subx directory): # $ ./subx translate *.subx apps/handle.subx -o apps/handle # $ ./subx run apps/handle # Expected result is a hard abort: # ........lookup failed # (This file is a prototype, so the tests in this file aren't real tests. Don't # expect to run anything in the same process after they've completed.) == code # instruction effective address register displacement immediate # . op subop mod rm32 base index scale r32 # . 1-3 bytes 3 bits 2 bits 3 bits 3 bits 3 bits 2 bits 2 bits 0/1/2/4 bytes 0/1/2/4 bytes # no Entry; the standard library runs all tests by default new: # ad : (address allocation-descriptor), n : int, out : (address handle) # . prolog 55/push-EBP 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP # . save registers 50/push-EAX 51/push-ECX 52/push-EDX # ECX = n+4 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 1/r32/ECX 0xc/disp8 . # copy *(EBP+12) to ECX 81 0/subop/add 3/mod/direct 1/rm32/ECX . . . . . 4/imm32 # add to ECX # EAX = allocate(ad, ECX) # . . push args 51/push-ECX ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) # . . call e8/call allocate/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP # EDX = out 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 2/r32/EDX 0x10/disp8 . # copy *(EBP+16) to EDX # out->address = EAX 89/copy 1/mod/*+disp8 2/rm32/EDX . . . 0/r32/EAX 4/disp8 . # copy EAX to *(EDX+4) # if (EAX == 0) out->alloc_id = 0, return 81 7/subop/compare 3/mod/direct 0/rm32/EAX . . . . . 0/imm32 # compare EAX 75/jump-if-not-equal $new:continue/disp8 c7 0/subop/copy 0/mod/indirect 2/rm32/EDX . . . . . 0/imm32 # copy to *EDX eb/jump $new:end/disp8 $new:continue: # otherwise: # ECX = *Next-alloc-id 8b/copy 0/mod/indirect 5/rm32/.disp32 . . 1/r32/ECX Next-alloc-id/disp32 # copy *Next-alloc-id to ECX # *EAX = *Next-alloc-id/ECX 89/copy 0/mod/indirect 0/rm32/EAX . . . 1/r32/ECX . . # copy ECX to *EAX # out->alloc_id = *Next-alloc-id 89/copy 0/mod/indirect 2/rm32/EDX . . . 1/r32/ECX . . # copy ECX to *EDX # increment *Next-alloc-id ff 0/subop/increment 0/mod/indirect 5/rm32/.disp32 . . . Next-alloc-id/disp32 # increment *Next-alloc-id $new:end: # . restore registers 5a/pop-to-EDX 59/pop-to-ECX 58/pop-to-EAX # . epilog 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP 5d/pop-to-EBP c3/return test-new: # . prolog 55/push-EBP 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP # *Next-alloc-id = 0x34 c7 0/subop/copy 0/mod/indirect 5/rm32/.disp32 . . . Next-alloc-id/disp32 0x34/imm32 # copy to *Next-alloc-id # var handle/ECX = {0, 0} 68/push 0/imm32/address 68/push 0/imm32/alloc-id 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX # new(Heap, 2, handle/ECX) #
#
#
# Nim's Runtime Library
# (c) Copyright 2020 Nim Contributors
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
## This module allows querying the compiler about
## diverse configuration settings. See also `compileOption`.
# Note: Only add new enum values at the end to ensure binary compatibility with
# other Nim compiler versions!
type
SingleValueSetting* {.pure.} = enum ## \
## settings resulting in a single string value
arguments, ## experimental: the arguments passed after '-r'
outFile, ## experimental: the output file
outDir, ## the output directory
nimcacheDir, ## the location of the 'nimcache' directory
projectName, ## the project's name that is being compiled
projectPath, ## experimental: some path to the project that is being compiled
projectFull, ## the full path to the project that is being compiled
command, ## experimental: the command (e.g. 'c', 'cpp', 'doc') passed to
## the Nim compiler
commandLine, ## experimental: the command line passed to Nim
linkOptions, ## additional options passed to the linker
compileOptions, ## additional options passed to the C/C++ compiler
ccompilerPath ## the path to the C/C++ compiler
backend ## the backend (eg: c|cpp|objc|js); both `nim doc --backend:js`
## and `nim js` would imply backend=js
libPath ## the absolute path to the stdlib library, i.e. nim's `--lib`, since 1.5.1
gc {.deprecated.} ## gc selected
mm ## memory management selected
MultipleValueSetting* {.pure.} = enum ## \
## settings resulting in a seq of string values
nimblePaths, ## the nimble path(s)
searchPaths, ## the search path for modules
lazyPaths, ## experimental: even more paths
commandArgs, ## the arguments passed to the Nim compiler
cincludes, ## the #include paths passed to the C/C++ compiler
clibs ## libraries passed to the C/C++ compiler
proc querySetting*(setting: SingleValueSetting): string {.
compileTime, noSideEffect.} =
## Can be used to get a string compile-time option.
##
## See also:
## * `compileOption <system.html#compileOption,string>`_ for `on|off` options
## * `compileOption <system.html#compileOption,string,string>`_ for enum options
##
runnableExamples:
const nimcache = querySetting(SingleValueSetting.nimcacheDir)
proc querySettingSeq*(setting: MultipleValueSetting): seq[string] {.
compileTime, noSideEffect.} =
## Can be used to get a multi-string compile-time option.
##
## See also:
## * `compileOption <system.html#compileOption,string>`_ for `on|off` options
## * `compileOption <system.html#compileOption,string,string>`_ for enum options
runnableExamples:
const nimblePaths = querySettingSeq(MultipleValueSetting.nimblePaths