# 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