mirror of
https://github.com/nim-lang/Nim.git
synced 2026-02-14 15:23:27 +00:00
handling of compiler procs improved for DLL generation
This commit is contained in:
39
lib/nimrtl.nim
Executable file
39
lib/nimrtl.nim
Executable file
@@ -0,0 +1,39 @@
|
||||
#
|
||||
#
|
||||
# Nimrod's Runtime Library
|
||||
# (c) Copyright 2010 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
## Main file to generate a DLL from the standard library.
|
||||
## The default Nimrtl does not only contain the ``system`` module, but these
|
||||
## too:
|
||||
##
|
||||
## * strutils
|
||||
## * parseutils
|
||||
## * parseopt
|
||||
## * parsecfg
|
||||
## * strtabs
|
||||
## * times
|
||||
## * os
|
||||
## * osproc
|
||||
## * pegs
|
||||
## * unicode
|
||||
## * ropes
|
||||
## * re
|
||||
##
|
||||
## So the resulting dynamic library is quite big. However, it is very easy to
|
||||
## strip modules out. Just modify the ``import`` statement in
|
||||
## ``lib/nimrtl.nim`` and recompile. Note that simply *adding* a module
|
||||
## here is not sufficient, though.
|
||||
|
||||
when system.appType != "lib":
|
||||
{.error: "This file has to be compiled as a library!".}
|
||||
|
||||
when not defined(createNimRtl):
|
||||
{.error: "This file has to be compiled with '-d:createNimRtl'".}
|
||||
|
||||
|
||||
|
||||
@@ -125,19 +125,6 @@ proc find*(s: string, chars: set[char], start: int = 0): int {.noSideEffect.}
|
||||
## Searches for `chars` in `s` starting at position `start`. If `s` contains
|
||||
## none of the characters in `chars`, -1 is returned.
|
||||
|
||||
proc replaceStr*(s, sub, by: string): string {.noSideEffect, deprecated.}
|
||||
## Replaces `sub` in `s` by the string `by`.
|
||||
## **Deprecated since version 0.8.0**: Use `replace` instead.
|
||||
|
||||
proc replaceStr*(s: string, sub, by: char): string {.noSideEffect, deprecated.}
|
||||
## optimized version for characters.
|
||||
## **Deprecated since version 0.8.0**: Use `replace` instead.
|
||||
|
||||
proc deleteStr*(s: var string, first, last: int) {.deprecated.}
|
||||
## Deletes in `s` the characters at position `first` .. `last`. This modifies
|
||||
## `s` itself, it does not return a copy.
|
||||
## **Deprecated since version 0.8.0**: Use `delete` instead.
|
||||
|
||||
proc toOctal*(c: char): string
|
||||
## Converts a character `c` to its octal representation. The resulting
|
||||
## string may not have a leading zero. Its length is always exactly 3.
|
||||
@@ -241,24 +228,6 @@ iterator splitLines*(s: string): string =
|
||||
else: break # was '\0'
|
||||
first = last
|
||||
|
||||
proc splitLinesSeq*(s: string): seq[string] {.noSideEffect, deprecated.} =
|
||||
## The same as `splitLines`, but is a proc that returns a sequence
|
||||
## of substrings.
|
||||
## **Deprecated since version 0.8.0**: Use `splitLines` instead.
|
||||
accumulateResult(splitLines(s))
|
||||
|
||||
proc splitSeq*(s: string, seps: set[char] = Whitespace): seq[string] {.
|
||||
noSideEffect, deprecated.} =
|
||||
## The same as `split`, but is a proc that returns a sequence of substrings.
|
||||
## **Deprecated since version 0.8.0**: Use `split` instead.
|
||||
accumulateResult(split(s, seps))
|
||||
|
||||
proc splitSeq*(s: string, sep: char): seq[string] {.noSideEffect,
|
||||
deprecated.} =
|
||||
## The same as `split`, but is a proc that returns a sequence of substrings.
|
||||
## **Deprecated since version 0.8.0**: Use `split` instead.
|
||||
accumulateResult(split(s, sep))
|
||||
|
||||
proc splitLines*(s: string): seq[string] {.noSideEffect.} =
|
||||
## The same as the `splitLines` iterator, but is a proc that returns a
|
||||
## sequence of substrings.
|
||||
@@ -328,12 +297,6 @@ proc ParseHexInt*(s: string): int {.noSideEffect, procvar.}
|
||||
## following optional prefixes: ``0x``, ``0X``, ``#``.
|
||||
## Underscores within `s` are ignored.
|
||||
|
||||
# the stringify and format operators:
|
||||
proc toString*[Ty](x: Ty): string {.deprecated.}
|
||||
## This generic proc is the same as the stringify operator `$`.
|
||||
##
|
||||
## **Deprecated since version 0.8.2:** Use `$` instead.
|
||||
|
||||
proc repeatChar*(count: int, c: Char = ' '): string
|
||||
## Returns a string of length `count` consisting only of
|
||||
## the character `c`.
|
||||
@@ -670,10 +633,6 @@ proc delete*(s: var string, first, last: int) =
|
||||
inc(j)
|
||||
setlen(s, newLen)
|
||||
|
||||
proc replaceStr(s, sub, by: string): string = return replace(s, sub, by)
|
||||
proc replaceStr(s: string, sub, by: char): string = return replace(s, sub, by)
|
||||
proc deleteStr(s: var string, first, last: int) = delete(s, first, last)
|
||||
|
||||
# parsing numbers:
|
||||
|
||||
proc toHex(x: BiggestInt, len: int): string =
|
||||
|
||||
@@ -667,6 +667,8 @@ proc `&` * (x: char, y: string): string {.
|
||||
proc add*(x: var string, y: char) {.magic: "AppendStrCh", noSideEffect.}
|
||||
proc add*(x: var string, y: string) {.magic: "AppendStrStr", noSideEffect.}
|
||||
|
||||
include "system/cgprocs"
|
||||
|
||||
when not defined(ECMAScript):
|
||||
{.push overflow_checks:off}
|
||||
proc add* (x: var string, y: cstring) =
|
||||
@@ -732,7 +734,6 @@ type
|
||||
## is the signed integer type that should be used for converting
|
||||
## pointers to integer addresses for readability.
|
||||
|
||||
type
|
||||
BiggestInt* = int64
|
||||
## is an alias for the biggest signed integer type the Nimrod compiler
|
||||
## supports. Currently this is ``int64``, but it is platform-dependant
|
||||
@@ -767,7 +768,7 @@ type # these work for most platforms:
|
||||
cstringArray* {.importc: "char**", nodecl.} = ptr array [0..50_000, cstring]
|
||||
## This is binary compatible to the type ``char**`` in *C*. The array's
|
||||
## high value is large enough to disable bounds checking in practice.
|
||||
## Use cstringArrayToSeq to convert it into a ``seq[string]``.
|
||||
## Use `cstringArrayToSeq` to convert it into a ``seq[string]``.
|
||||
|
||||
TEndian* = enum ## is a type describing the endianness of a processor.
|
||||
littleEndian, bigEndian
|
||||
@@ -823,6 +824,8 @@ const
|
||||
## a string that describes the application type. Possible values:
|
||||
## "console", "gui", "lib".
|
||||
|
||||
include "system/inclrtl"
|
||||
|
||||
proc toFloat*(i: int): float {.
|
||||
magic: "ToFloat", noSideEffect, importc: "toFloat".}
|
||||
## converts an integer `i` into a ``float``. If the conversion
|
||||
@@ -897,23 +900,23 @@ proc equalMem*(a, b: Pointer, size: int): bool {.
|
||||
## otherwise. Like any procedure dealing with raw memory this is
|
||||
## *unsafe*.
|
||||
|
||||
proc alloc*(size: int): pointer {.noconv.}
|
||||
proc alloc*(size: int): pointer {.noconv, rtl.}
|
||||
## allocates a new memory block with at least ``size`` bytes. The
|
||||
## block has to be freed with ``realloc(block, 0)`` or
|
||||
## ``dealloc(block)``. The block is not initialized, so reading
|
||||
## from it before writing to it is undefined behaviour!
|
||||
proc alloc0*(size: int): pointer {.noconv.}
|
||||
proc alloc0*(size: int): pointer {.noconv, rtl.}
|
||||
## allocates a new memory block with at least ``size`` bytes. The
|
||||
## block has to be freed with ``realloc(block, 0)`` or
|
||||
## ``dealloc(block)``. The block is initialized with all bytes
|
||||
## containing zero, so it is somewhat safer than ``alloc``.
|
||||
proc realloc*(p: Pointer, newsize: int): pointer {.noconv.}
|
||||
proc realloc*(p: Pointer, newsize: int): pointer {.noconv, rtl.}
|
||||
## grows or shrinks a given memory block. If p is **nil** then a new
|
||||
## memory block is returned. In either way the block has at least
|
||||
## ``newsize`` bytes. If ``newsize == 0`` and p is not **nil**
|
||||
## ``realloc`` calls ``dealloc(p)``. In other cases the block has to
|
||||
## be freed with ``dealloc``.
|
||||
proc dealloc*(p: Pointer) {.noconv.}
|
||||
proc dealloc*(p: Pointer) {.noconv, rtl.}
|
||||
## frees the memory allocated with ``alloc``, ``alloc0`` or
|
||||
## ``realloc``. This procedure is dangerous! If one forgets to
|
||||
## free the memory a leak occurs; if one tries to access freed
|
||||
@@ -1009,14 +1012,14 @@ var
|
||||
|
||||
# GC interface:
|
||||
|
||||
proc getOccupiedMem*(): int
|
||||
proc getOccupiedMem*(): int {.rtl.}
|
||||
## returns the number of bytes that are owned by the process and hold data.
|
||||
|
||||
proc getFreeMem*(): int
|
||||
proc getFreeMem*(): int {.rtl.}
|
||||
## returns the number of bytes that are owned by the process, but do not
|
||||
## hold any meaningful data.
|
||||
|
||||
proc getTotalMem*(): int
|
||||
proc getTotalMem*(): int {.rtl.}
|
||||
## returns the number of bytes that are owned by the process.
|
||||
|
||||
|
||||
@@ -1205,15 +1208,15 @@ proc each*[T](data: var openArray[T], op: proc (x: var T)) =
|
||||
|
||||
# ----------------- GC interface ---------------------------------------------
|
||||
|
||||
proc GC_disable*()
|
||||
proc GC_disable*() {.rtl.}
|
||||
## disables the GC. If called n-times, n calls to `GC_enable` are needed to
|
||||
## reactivate the GC. Note that in most circumstances one should only disable
|
||||
## the mark and sweep phase with `GC_disableMarkAndSweep`.
|
||||
|
||||
proc GC_enable*()
|
||||
proc GC_enable*() {.rtl.}
|
||||
## enables the GC again.
|
||||
|
||||
proc GC_fullCollect*()
|
||||
proc GC_fullCollect*() {.rtl.}
|
||||
## forces a full garbage collection pass.
|
||||
## Ordinary code does not need to call this (and should not).
|
||||
|
||||
@@ -1224,18 +1227,18 @@ type
|
||||
gcOptimizeTime, ## optimize for speed
|
||||
gcOptimizeSpace ## optimize for memory footprint
|
||||
|
||||
proc GC_setStrategy*(strategy: TGC_Strategy)
|
||||
proc GC_setStrategy*(strategy: TGC_Strategy) {.rtl.}
|
||||
## tells the GC the desired strategy for the application.
|
||||
|
||||
proc GC_enableMarkAndSweep*()
|
||||
proc GC_disableMarkAndSweep*()
|
||||
proc GC_enableMarkAndSweep*() {.rtl.}
|
||||
proc GC_disableMarkAndSweep*() {.rtl.}
|
||||
## the current implementation uses a reference counting garbage collector
|
||||
## with a seldomly run mark and sweep phase to free cycles. The mark and
|
||||
## sweep phase may take a long time and is not needed if the application
|
||||
## does not create cycles. Thus the mark and sweep phase can be deactivated
|
||||
## and activated separately from the rest of the GC.
|
||||
|
||||
proc GC_getStatistics*(): string
|
||||
proc GC_getStatistics*(): string {.rtl.}
|
||||
## returns an informative string about the GC's activity. This may be useful
|
||||
## for tweaking.
|
||||
|
||||
@@ -1372,23 +1375,14 @@ when not defined(EcmaScript) and not defined(NimrodVM):
|
||||
## appropriately. It also annoys people if redirection via ``>output.txt``
|
||||
## does not work because the program writes to ``stderr``.
|
||||
|
||||
proc OpenFile*(f: var TFile, filename: string,
|
||||
mode: TFileMode = fmRead,
|
||||
bufSize: int = -1): Bool {.deprecated.}
|
||||
## **Deprecated since version 0.8.0**: Use `open` instead.
|
||||
|
||||
proc OpenFile*(f: var TFile, filehandle: TFileHandle,
|
||||
mode: TFileMode = fmRead): Bool {.deprecated.}
|
||||
## **Deprecated since version 0.8.0**: Use `open` instead.
|
||||
|
||||
proc Open*(f: var TFile, filename: string,
|
||||
mode: TFileMode = fmRead, bufSize: int = -1): Bool
|
||||
## Opens a file named `filename` with given `mode`.
|
||||
##
|
||||
## Default mode is readonly. Returns true iff the file could be opened.
|
||||
## This throws no exception if the file could not be opened. The reason is
|
||||
## that the programmer needs to provide an appropriate error message anyway
|
||||
## (yes, even in scripts).
|
||||
## that the programmer needs to provide an appropriate error message
|
||||
## anyway.
|
||||
|
||||
proc Open*(f: var TFile, filehandle: TFileHandle,
|
||||
mode: TFileMode = fmRead): Bool
|
||||
@@ -1403,10 +1397,6 @@ when not defined(EcmaScript) and not defined(NimrodVM):
|
||||
##
|
||||
## Default mode is readonly. Returns true iff the file could be reopened.
|
||||
|
||||
proc CloseFile*(f: TFile) {.importc: "fclose", nodecl, deprecated.}
|
||||
## Closes the file.
|
||||
## **Deprecated since version 0.8.0**: Use `close` instead.
|
||||
|
||||
proc Close*(f: TFile) {.importc: "fclose", nodecl.}
|
||||
## Closes the file.
|
||||
|
||||
@@ -1545,7 +1535,7 @@ when not defined(EcmaScript) and not defined(NimrodVM):
|
||||
const
|
||||
GenericSeqSize = (2 * sizeof(int))
|
||||
|
||||
proc reprAny(p: pointer, typ: PNimType): string {.compilerproc.}
|
||||
proc reprAny(p: pointer, typ: PNimType): string {.compilerRtl.}
|
||||
|
||||
proc getDiscriminant(aa: Pointer, n: ptr TNimNode): int =
|
||||
assert(n.kind == nkCase)
|
||||
|
||||
14
lib/system/cgprocs.nim
Normal file
14
lib/system/cgprocs.nim
Normal file
@@ -0,0 +1,14 @@
|
||||
#
|
||||
#
|
||||
# Nimrod's Runtime Library
|
||||
# (c) Copyright 2010 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
# Headers for procs that the code generator depends on ("compilerprocs")
|
||||
|
||||
proc addChar(s: NimString, c: char): NimString {.compilerProc.}
|
||||
|
||||
|
||||
@@ -24,7 +24,12 @@ proc nimUnloadLibrary(lib: TLibHandle) {.compilerproc.}
|
||||
proc nimGetProcAddr(lib: TLibHandle, name: cstring): TProcAddr {.compilerproc.}
|
||||
|
||||
proc nimLoadLibraryError(path: string) {.compilerproc, noinline.} =
|
||||
raise newException(EInvalidLibrary, "could not load: " & path)
|
||||
when true:
|
||||
# carefully written to avoid memory allocation:
|
||||
stdout.write("could not load: ")
|
||||
quit(path)
|
||||
else:
|
||||
raise newException(EInvalidLibrary, "could not load: " & path)
|
||||
|
||||
# this code was inspired from Lua's source code:
|
||||
# Lua - An Extensible Extension Language
|
||||
|
||||
@@ -74,13 +74,13 @@ var
|
||||
# This is wasteful but safe. This is a lock against recursive garbage
|
||||
# collection, not a lock for threads!
|
||||
|
||||
proc unsureAsgnRef(dest: ppointer, src: pointer) {.compilerproc.}
|
||||
proc unsureAsgnRef(dest: ppointer, src: pointer) {.compilerRtl.}
|
||||
# unsureAsgnRef updates the reference counters only if dest is not on the
|
||||
# stack. It is used by the code generator if it cannot decide wether a
|
||||
# reference is in the stack or not (this can happen for var parameters).
|
||||
#proc growObj(old: pointer, newsize: int): pointer {.compilerproc.}
|
||||
proc newObj(typ: PNimType, size: int): pointer {.compilerproc.}
|
||||
proc newSeq(typ: PNimType, len: int): pointer {.compilerproc.}
|
||||
|
||||
proc newObj(typ: PNimType, size: int): pointer {.compilerRtl.}
|
||||
proc newSeq(typ: PNimType, len: int): pointer {.compilerRtl.}
|
||||
|
||||
proc addZCT(s: var TCellSeq, c: PCell) {.noinline.} =
|
||||
if (c.refcount and rcZct) == 0:
|
||||
@@ -214,8 +214,10 @@ proc prepareDealloc(cell: PCell) =
|
||||
(cast[TFinalizer](cell.typ.finalizer))(cellToUsr(cell))
|
||||
dec(recGcLock)
|
||||
|
||||
proc setStackBottom(theStackBottom: pointer) {.compilerproc.} =
|
||||
stackBottom = theStackBottom
|
||||
proc setStackBottom(theStackBottom: pointer) {.compilerRtl.} =
|
||||
# the first init must be the one that defines the stack bottom:
|
||||
if stackBottom == nil:
|
||||
stackBottom = theStackBottom
|
||||
|
||||
proc PossibleRoot(gch: var TGcHeap, c: PCell) {.inline.} =
|
||||
if canbeCycleRoot(c): incl(gch.cycleRoots, c)
|
||||
@@ -236,10 +238,10 @@ proc incRef(c: PCell) {.inline.} =
|
||||
if canBeCycleRoot(c):
|
||||
incl(gch.cycleRoots, c)
|
||||
|
||||
proc nimGCref(p: pointer) {.compilerproc, inline.} = incRef(usrToCell(p))
|
||||
proc nimGCunref(p: pointer) {.compilerproc, inline.} = decRef(usrToCell(p))
|
||||
proc nimGCref(p: pointer) {.compilerRtl, inl.} = incRef(usrToCell(p))
|
||||
proc nimGCunref(p: pointer) {.compilerRtl, inl.} = decRef(usrToCell(p))
|
||||
|
||||
proc asgnRef(dest: ppointer, src: pointer) {.compilerproc, inline.} =
|
||||
proc asgnRef(dest: ppointer, src: pointer) {.compilerRtl, inl.} =
|
||||
# the code generator calls this proc!
|
||||
assert(not isOnStack(dest))
|
||||
# BUGFIX: first incRef then decRef!
|
||||
@@ -247,7 +249,7 @@ proc asgnRef(dest: ppointer, src: pointer) {.compilerproc, inline.} =
|
||||
if dest^ != nil: decRef(usrToCell(dest^))
|
||||
dest^ = src
|
||||
|
||||
proc asgnRefNoCycle(dest: ppointer, src: pointer) {.compilerproc, inline.} =
|
||||
proc asgnRefNoCycle(dest: ppointer, src: pointer) {.compilerRtl, inl.} =
|
||||
# the code generator calls this proc if it is known at compile time that no
|
||||
# cycle is possible.
|
||||
if src != nil:
|
||||
|
||||
45
lib/system/inclrtl.nim
Executable file
45
lib/system/inclrtl.nim
Executable file
@@ -0,0 +1,45 @@
|
||||
#
|
||||
#
|
||||
# Nimrod's Runtime Library
|
||||
# (c) Copyright 2010 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
## Pragmas for RTL generation. Has to be an include, because user-defined
|
||||
## pragmas cannot be exported.
|
||||
|
||||
# There are 3 different usages:
|
||||
# 1) Ordinary imported code.
|
||||
# 2) Imported from nimrtl.
|
||||
# -> defined(useNimRtl) or appType == "lib" and not defined(createNimRtl)
|
||||
# 3) Exported into nimrtl.
|
||||
# -> appType == "lib" and defined(createNimRtl)
|
||||
|
||||
when defined(createNimRtl):
|
||||
when defined(useNimRtl):
|
||||
{.error: "Cannot create and use nimrtl at the same time!".}
|
||||
elif appType != "lib":
|
||||
{.error: "nimrtl must be build as a library!".}
|
||||
|
||||
when defined(createNimRtl):
|
||||
# NOTE: compilerproc cannot make use of name mangling!
|
||||
{.pragma: rtl, exportc: "nimrtl_$1", dynlib.}
|
||||
{.pragma: inl.}
|
||||
{.pragma: compilerRtl, compilerproc, exportc: "nimrtl_$1", dynlib.}
|
||||
elif defined(useNimRtl):
|
||||
when hostOS == "windows":
|
||||
const nimrtl* = "nimrtl.dll"
|
||||
elif hostOS == "macosx":
|
||||
const nimrtl* = "nimrtl.dynlib"
|
||||
else:
|
||||
const nimrtl* = "libnimrtl.so"
|
||||
{.pragma: rtl, importc: "nimrtl_$1", dynlib: nimrtl.}
|
||||
{.pragma: inl.}
|
||||
{.pragma: compilerRtl, compilerproc, importc: "nimrtl_$1", dynlib: nimrtl.}
|
||||
else:
|
||||
{.pragma: rtl.}
|
||||
{.pragma: inl, inline.}
|
||||
{.pragma: compilerRtl, compilerproc.}
|
||||
|
||||
@@ -187,60 +187,35 @@ elif defined(nogc):
|
||||
dest^ = src
|
||||
|
||||
include "system/cellsets"
|
||||
elif appType == "lib":
|
||||
{.warning: "gc in a library context may not work".}
|
||||
when hostOS == "windows":
|
||||
const nimrtl = "nimrtl.dll"
|
||||
elif hostOS == "macosx":
|
||||
const nimrtl = "nimrtl.dynlib"
|
||||
else:
|
||||
const nimrtl = "libnimrtl.so"
|
||||
|
||||
when not defined(includeGC):
|
||||
# ordinary client; use the GC from nimrtl.dll:
|
||||
proc initGC() {.cdecl, importc, dynlib: nimrtl.}
|
||||
proc GC_disable() {.cdecl, importc, dynlib: nimrtl.}
|
||||
proc GC_enable() {.cdecl, importc, dynlib: nimrtl.}
|
||||
proc GC_fullCollect() {.cdecl, importc, dynlib: nimrtl.}
|
||||
proc GC_setStrategy(strategy: TGC_Strategy) {.
|
||||
cdecl, importc, dynlib: nimrtl.}
|
||||
proc GC_enableMarkAndSweep() {.cdecl, importc, dynlib: nimrtl.}
|
||||
proc GC_disableMarkAndSweep() {.cdecl, importc, dynlib: nimrtl.}
|
||||
proc GC_getStatistics(): string {.cdecl, importc, dynlib: nimrtl.}
|
||||
elif defined(useNimRtl):
|
||||
proc initGC() = nil
|
||||
|
||||
proc newObj(typ: PNimType, size: int): pointer {.
|
||||
compilerproc, cdecl, importc, dynlib: nimrtl.}
|
||||
proc newSeq(typ: PNimType, len: int): pointer {.
|
||||
compilerproc, cdecl, importc, dynlib: nimrtl.}
|
||||
proc growObj(old: pointer, newsize: int): pointer {.
|
||||
cdecl, importc, dynlib: nimrtl.}
|
||||
|
||||
proc setStackBottom(theStackBottom: pointer) {.
|
||||
compilerproc, cdecl, importc, dynlib: nimrtl.}
|
||||
proc nimGCref(p: pointer) {.
|
||||
compilerproc, cdecl, importc, dynlib: nimrtl.}
|
||||
proc nimGCunref(p: pointer) {.
|
||||
compilerproc, cdecl, importc, dynlib: nimrtl.}
|
||||
proc newObj(typ: PNimType, size: int): pointer {.compilerRtl.}
|
||||
proc newSeq(typ: PNimType, len: int): pointer {.compilerRtl.}
|
||||
proc growObj(old: pointer, newsize: int): pointer {.rtl.}
|
||||
|
||||
# The write barrier is performance critical!
|
||||
# XXX We should ensure that they are inlined here.
|
||||
# Later implementations will do this.
|
||||
proc setStackBottom(theStackBottom: pointer) {.compilerProc, inline.} =
|
||||
# This happens before setStackBottom has been loaded by dlsym(), so
|
||||
# we simply provide a dummy implemenation here for the code gen. No
|
||||
# harm is done by this.
|
||||
nil
|
||||
|
||||
proc unsureAsgnRef(dest: ppointer, src: pointer) {.
|
||||
compilerproc, cdecl, importc, dynlib: nimrtl.}
|
||||
proc asgnRef(dest: ppointer, src: pointer) {.
|
||||
compilerproc, cdecl, importc, dynlib: nimrtl.}
|
||||
proc asgnRefNoCycle(dest: ppointer, src: pointer) {.
|
||||
compilerproc, cdecl, importc, dynlib: nimrtl.}
|
||||
|
||||
else:
|
||||
# include the GC and export it!
|
||||
include "system/alloc"
|
||||
include "system/cellsets"
|
||||
assert(sizeof(TCell) == sizeof(TFreeCell))
|
||||
include "system/gc"
|
||||
proc nimGCref(p: pointer) {.compilerRtl.}
|
||||
proc nimGCunref(p: pointer) {.compilerRtl.}
|
||||
|
||||
# The write barrier is performance critical!
|
||||
# XXX We should ensure that they are inlined here.
|
||||
# Later implementations will do this.
|
||||
|
||||
proc unsureAsgnRef(dest: ppointer, src: pointer) {.
|
||||
compilerRtl.}
|
||||
proc asgnRef(dest: ppointer, src: pointer) {.
|
||||
compilerRtl.}
|
||||
proc asgnRefNoCycle(dest: ppointer, src: pointer) {.
|
||||
compilerRtl.}
|
||||
|
||||
include "system/cellsets"
|
||||
|
||||
else:
|
||||
include "system/alloc"
|
||||
include "system/cellsets"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#
|
||||
#
|
||||
# Nimrod's Runtime Library
|
||||
# (c) Copyright 2009 Andreas Rumpf
|
||||
# (c) Copyright 2010 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
@@ -35,15 +35,15 @@ proc reprStrAux(result: var string, s: string) =
|
||||
else: result.add(c)
|
||||
add result, "\""
|
||||
|
||||
proc reprStr(s: string): string {.compilerproc.} =
|
||||
proc reprStr(s: string): string {.compilerRtl.} =
|
||||
result = ""
|
||||
reprStrAux(result, s)
|
||||
|
||||
proc reprBool(x: bool): string {.compilerproc.} =
|
||||
proc reprBool(x: bool): string {.compilerRtl.} =
|
||||
if x: result = "true"
|
||||
else: result = "false"
|
||||
|
||||
proc reprChar(x: char): string {.compilerproc.} =
|
||||
proc reprChar(x: char): string {.compilerRtl.} =
|
||||
result = "\'"
|
||||
case x
|
||||
of '"': add result, "\\\""
|
||||
@@ -52,7 +52,7 @@ proc reprChar(x: char): string {.compilerproc.} =
|
||||
else: add result, x
|
||||
add result, "\'"
|
||||
|
||||
proc reprEnum(e: int, typ: PNimType): string {.compilerproc.} =
|
||||
proc reprEnum(e: int, typ: PNimType): string {.compilerRtl.} =
|
||||
if e <% typ.node.len: # BUGFIX
|
||||
result = $typ.node.sons[e].name
|
||||
else:
|
||||
@@ -97,7 +97,7 @@ proc reprSetAux(result: var string, p: pointer, typ: PNimType) =
|
||||
inc(elemCounter)
|
||||
add result, "}"
|
||||
|
||||
proc reprSet(p: pointer, typ: PNimType): string {.compilerproc.} =
|
||||
proc reprSet(p: pointer, typ: PNimType): string {.compilerRtl.} =
|
||||
result = ""
|
||||
reprSetAux(result, p, typ)
|
||||
|
||||
@@ -108,122 +108,123 @@ type
|
||||
recdepth: int # do not recurse endless
|
||||
indent: int # indentation
|
||||
|
||||
proc initReprClosure(cl: var TReprClosure) =
|
||||
Init(cl.marked)
|
||||
cl.recdepth = -1 # default is to display everything!
|
||||
cl.indent = 0
|
||||
when not defined(useNimRtl):
|
||||
proc initReprClosure(cl: var TReprClosure) =
|
||||
Init(cl.marked)
|
||||
cl.recdepth = -1 # default is to display everything!
|
||||
cl.indent = 0
|
||||
|
||||
proc deinitReprClosure(cl: var TReprClosure) =
|
||||
Deinit(cl.marked)
|
||||
proc deinitReprClosure(cl: var TReprClosure) =
|
||||
Deinit(cl.marked)
|
||||
|
||||
proc reprBreak(result: var string, cl: TReprClosure) =
|
||||
add result, "\n"
|
||||
for i in 0..cl.indent-1: add result, ' '
|
||||
proc reprBreak(result: var string, cl: TReprClosure) =
|
||||
add result, "\n"
|
||||
for i in 0..cl.indent-1: add result, ' '
|
||||
|
||||
proc reprAux(result: var string, p: pointer, typ: PNimType,
|
||||
cl: var TReprClosure)
|
||||
proc reprAux(result: var string, p: pointer, typ: PNimType,
|
||||
cl: var TReprClosure)
|
||||
|
||||
proc reprArray(result: var string, p: pointer, typ: PNimType,
|
||||
cl: var TReprClosure) =
|
||||
add result, "["
|
||||
var bs = typ.base.size
|
||||
for i in 0..typ.size div bs - 1:
|
||||
if i > 0: add result, ", "
|
||||
reprAux(result, cast[pointer](cast[TAddress](p) + i*bs), typ.base, cl)
|
||||
add result, "]"
|
||||
proc reprArray(result: var string, p: pointer, typ: PNimType,
|
||||
cl: var TReprClosure) =
|
||||
add result, "["
|
||||
var bs = typ.base.size
|
||||
for i in 0..typ.size div bs - 1:
|
||||
if i > 0: add result, ", "
|
||||
reprAux(result, cast[pointer](cast[TAddress](p) + i*bs), typ.base, cl)
|
||||
add result, "]"
|
||||
|
||||
proc reprSequence(result: var string, p: pointer, typ: PNimType,
|
||||
proc reprSequence(result: var string, p: pointer, typ: PNimType,
|
||||
cl: var TReprClosure) =
|
||||
if p == nil:
|
||||
add result, "nil"
|
||||
return
|
||||
result.add(reprPointer(p) & "[")
|
||||
var bs = typ.base.size
|
||||
for i in 0..cast[PGenericSeq](p).len-1:
|
||||
if i > 0: add result, ", "
|
||||
reprAux(result, cast[pointer](cast[TAddress](p) + GenericSeqSize + i*bs),
|
||||
typ.Base, cl)
|
||||
add result, "]"
|
||||
|
||||
proc reprRecordAux(result: var string, p: pointer, n: ptr TNimNode,
|
||||
cl: var TReprClosure) =
|
||||
case n.kind
|
||||
of nkNone: assert(false)
|
||||
of nkSlot:
|
||||
add result, $n.name
|
||||
add result, " = "
|
||||
reprAux(result, cast[pointer](cast[TAddress](p) + n.offset), n.typ, cl)
|
||||
of nkList:
|
||||
for i in 0..n.len-1:
|
||||
if i > 0: add result, ",\n"
|
||||
reprRecordAux(result, p, n.sons[i], cl)
|
||||
of nkCase:
|
||||
var m = selectBranch(p, n)
|
||||
reprAux(result, cast[pointer](cast[TAddress](p) + n.offset), n.typ, cl)
|
||||
if m != nil: reprRecordAux(result, p, m, cl)
|
||||
|
||||
proc reprRecord(result: var string, p: pointer, typ: PNimType,
|
||||
cl: var TReprClosure) =
|
||||
if p == nil:
|
||||
add result, "nil"
|
||||
return
|
||||
result.add(reprPointer(p) & "[")
|
||||
var bs = typ.base.size
|
||||
for i in 0..cast[PGenericSeq](p).len-1:
|
||||
if i > 0: add result, ", "
|
||||
reprAux(result, cast[pointer](cast[TAddress](p) + GenericSeqSize + i*bs),
|
||||
typ.Base, cl)
|
||||
add result, "]"
|
||||
add result, "["
|
||||
reprRecordAux(result, p, typ.node, cl)
|
||||
add result, "]"
|
||||
|
||||
proc reprRecordAux(result: var string, p: pointer, n: ptr TNimNode,
|
||||
cl: var TReprClosure) =
|
||||
case n.kind
|
||||
of nkNone: assert(false)
|
||||
of nkSlot:
|
||||
add result, $n.name
|
||||
add result, " = "
|
||||
reprAux(result, cast[pointer](cast[TAddress](p) + n.offset), n.typ, cl)
|
||||
of nkList:
|
||||
for i in 0..n.len-1:
|
||||
if i > 0: add result, ",\n"
|
||||
reprRecordAux(result, p, n.sons[i], cl)
|
||||
of nkCase:
|
||||
var m = selectBranch(p, n)
|
||||
reprAux(result, cast[pointer](cast[TAddress](p) + n.offset), n.typ, cl)
|
||||
if m != nil: reprRecordAux(result, p, m, cl)
|
||||
proc reprRef(result: var string, p: pointer, typ: PNimType,
|
||||
cl: var TReprClosure) =
|
||||
# we know that p is not nil here:
|
||||
when defined(boehmGC) or defined(nogc):
|
||||
var cell = cast[PCell](p)
|
||||
else:
|
||||
var cell = usrToCell(p)
|
||||
add result, "ref " & reprPointer(p)
|
||||
if cell notin cl.marked:
|
||||
# only the address is shown:
|
||||
incl(cl.marked, cell)
|
||||
add result, " --> "
|
||||
reprAux(result, p, typ.base, cl)
|
||||
|
||||
proc reprRecord(result: var string, p: pointer, typ: PNimType,
|
||||
cl: var TReprClosure) =
|
||||
add result, "["
|
||||
reprRecordAux(result, p, typ.node, cl)
|
||||
add result, "]"
|
||||
|
||||
proc reprRef(result: var string, p: pointer, typ: PNimType,
|
||||
cl: var TReprClosure) =
|
||||
# we know that p is not nil here:
|
||||
when defined(boehmGC) or defined(nogc):
|
||||
var cell = cast[PCell](p)
|
||||
else:
|
||||
var cell = usrToCell(p)
|
||||
add result, "ref " & reprPointer(p)
|
||||
if cell notin cl.marked:
|
||||
# only the address is shown:
|
||||
incl(cl.marked, cell)
|
||||
add result, " --> "
|
||||
reprAux(result, p, typ.base, cl)
|
||||
|
||||
proc reprAux(result: var string, p: pointer, typ: PNimType,
|
||||
cl: var TReprClosure) =
|
||||
if cl.recdepth == 0:
|
||||
add result, "..."
|
||||
return
|
||||
dec(cl.recdepth)
|
||||
case typ.kind
|
||||
of tySet: reprSetAux(result, p, typ)
|
||||
of tyArray: reprArray(result, p, typ, cl)
|
||||
of tyTuple, tyPureObject: reprRecord(result, p, typ, cl)
|
||||
of tyObject:
|
||||
var t = cast[ptr PNimType](p)^
|
||||
reprRecord(result, p, t, cl)
|
||||
of tyRef, tyPtr:
|
||||
assert(p != nil)
|
||||
if cast[ppointer](p)^ == nil: add result, "nil"
|
||||
else: reprRef(result, cast[ppointer](p)^, typ, cl)
|
||||
of tySequence:
|
||||
reprSequence(result, cast[ppointer](p)^, typ, cl)
|
||||
of tyInt: add result, $(cast[ptr int](p)^)
|
||||
of tyInt8: add result, $int(cast[ptr Int8](p)^)
|
||||
of tyInt16: add result, $int(cast[ptr Int16](p)^)
|
||||
of tyInt32: add result, $int(cast[ptr Int32](p)^)
|
||||
of tyInt64: add result, $(cast[ptr Int64](p)^)
|
||||
of tyFloat: add result, $(cast[ptr float](p)^)
|
||||
of tyFloat32: add result, $(cast[ptr float32](p)^)
|
||||
of tyFloat64: add result, $(cast[ptr float64](p)^)
|
||||
of tyEnum: add result, reprEnum(cast[ptr int](p)^, typ)
|
||||
of tyBool: add result, reprBool(cast[ptr bool](p)^)
|
||||
of tyChar: add result, reprChar(cast[ptr char](p)^)
|
||||
of tyString: reprStrAux(result, cast[ptr string](p)^)
|
||||
of tyCString: reprStrAux(result, $(cast[ptr cstring](p)^))
|
||||
of tyRange: reprAux(result, p, typ.base, cl)
|
||||
of tyProc, tyPointer:
|
||||
if cast[ppointer](p)^ == nil: add result, "nil"
|
||||
else: add result, reprPointer(cast[ppointer](p)^)
|
||||
else:
|
||||
add result, "(invalid data!)"
|
||||
inc(cl.recdepth)
|
||||
proc reprAux(result: var string, p: pointer, typ: PNimType,
|
||||
cl: var TReprClosure) =
|
||||
if cl.recdepth == 0:
|
||||
add result, "..."
|
||||
return
|
||||
dec(cl.recdepth)
|
||||
case typ.kind
|
||||
of tySet: reprSetAux(result, p, typ)
|
||||
of tyArray: reprArray(result, p, typ, cl)
|
||||
of tyTuple, tyPureObject: reprRecord(result, p, typ, cl)
|
||||
of tyObject:
|
||||
var t = cast[ptr PNimType](p)^
|
||||
reprRecord(result, p, t, cl)
|
||||
of tyRef, tyPtr:
|
||||
assert(p != nil)
|
||||
if cast[ppointer](p)^ == nil: add result, "nil"
|
||||
else: reprRef(result, cast[ppointer](p)^, typ, cl)
|
||||
of tySequence:
|
||||
reprSequence(result, cast[ppointer](p)^, typ, cl)
|
||||
of tyInt: add result, $(cast[ptr int](p)^)
|
||||
of tyInt8: add result, $int(cast[ptr Int8](p)^)
|
||||
of tyInt16: add result, $int(cast[ptr Int16](p)^)
|
||||
of tyInt32: add result, $int(cast[ptr Int32](p)^)
|
||||
of tyInt64: add result, $(cast[ptr Int64](p)^)
|
||||
of tyFloat: add result, $(cast[ptr float](p)^)
|
||||
of tyFloat32: add result, $(cast[ptr float32](p)^)
|
||||
of tyFloat64: add result, $(cast[ptr float64](p)^)
|
||||
of tyEnum: add result, reprEnum(cast[ptr int](p)^, typ)
|
||||
of tyBool: add result, reprBool(cast[ptr bool](p)^)
|
||||
of tyChar: add result, reprChar(cast[ptr char](p)^)
|
||||
of tyString: reprStrAux(result, cast[ptr string](p)^)
|
||||
of tyCString: reprStrAux(result, $(cast[ptr cstring](p)^))
|
||||
of tyRange: reprAux(result, p, typ.base, cl)
|
||||
of tyProc, tyPointer:
|
||||
if cast[ppointer](p)^ == nil: add result, "nil"
|
||||
else: add result, reprPointer(cast[ppointer](p)^)
|
||||
else:
|
||||
add result, "(invalid data!)"
|
||||
inc(cl.recdepth)
|
||||
|
||||
proc reprOpenArray(p: pointer, length: int, elemtyp: PNimType): string {.
|
||||
compilerproc.} =
|
||||
compilerRtl.} =
|
||||
var
|
||||
cl: TReprClosure
|
||||
initReprClosure(cl)
|
||||
@@ -235,15 +236,17 @@ proc reprOpenArray(p: pointer, length: int, elemtyp: PNimType): string {.
|
||||
add result, "]"
|
||||
deinitReprClosure(cl)
|
||||
|
||||
proc reprAny(p: pointer, typ: PNimType): string =
|
||||
var
|
||||
cl: TReprClosure
|
||||
initReprClosure(cl)
|
||||
result = ""
|
||||
if typ.kind in {tyObject, tyPureObject, tyTuple, tyArray, tySet}:
|
||||
reprAux(result, p, typ, cl)
|
||||
else:
|
||||
var p = p
|
||||
reprAux(result, addr(p), typ, cl)
|
||||
add result, "\n"
|
||||
deinitReprClosure(cl)
|
||||
when not defined(useNimRtl):
|
||||
proc reprAny(p: pointer, typ: PNimType): string =
|
||||
var
|
||||
cl: TReprClosure
|
||||
initReprClosure(cl)
|
||||
result = ""
|
||||
if typ.kind in {tyObject, tyPureObject, tyTuple, tyArray, tySet}:
|
||||
reprAux(result, p, typ, cl)
|
||||
else:
|
||||
var p = p
|
||||
reprAux(result, addr(p), typ, cl)
|
||||
add result, "\n"
|
||||
deinitReprClosure(cl)
|
||||
|
||||
|
||||
@@ -135,14 +135,6 @@ proc open(f: var TFile, filehandle: TFileHandle, mode: TFileMode): bool =
|
||||
f = fdopen(filehandle, FormatOpen[mode])
|
||||
result = f != nil
|
||||
|
||||
proc OpenFile(f: var TFile, filename: string,
|
||||
mode: TFileMode = fmRead,
|
||||
bufSize: int = -1): Bool =
|
||||
result = open(f, filename, mode, bufSize)
|
||||
|
||||
proc openFile(f: var TFile, filehandle: TFileHandle, mode: TFileMode): bool =
|
||||
result = open(f, filehandle, mode)
|
||||
|
||||
# C routine that is used here:
|
||||
proc fread(buf: Pointer, size, n: int, f: TFile): int {.
|
||||
importc: "fread", noDecl.}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#
|
||||
#
|
||||
# Nimrod's Runtime Library
|
||||
# (c) Copyright 2009 Andreas Rumpf
|
||||
# (c) Copyright 2010 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
@@ -88,7 +88,8 @@ proc copyStrLast(s: NimString, start, last: int): NimString {.exportc.} =
|
||||
proc copyStr(s: NimString, start: int): NimString {.exportc.} =
|
||||
return copyStrLast(s, start, s.len-1)
|
||||
|
||||
proc addChar(s: NimString, c: char): NimString {.compilerProc.} =
|
||||
proc addChar(s: NimString, c: char): NimString =
|
||||
# is compilerproc!
|
||||
result = s
|
||||
if result.len >= result.space:
|
||||
result.space = resize(result.space)
|
||||
@@ -196,7 +197,7 @@ proc incrSeq(seq: PGenericSeq, elemSize: int): PGenericSeq {.compilerProc.} =
|
||||
inc(result.len)
|
||||
|
||||
proc setLengthSeq(seq: PGenericSeq, elemSize, newLen: int): PGenericSeq {.
|
||||
compilerProc.} =
|
||||
compilerRtl.} =
|
||||
when false:
|
||||
# broken version:
|
||||
result = seq
|
||||
@@ -223,7 +224,7 @@ proc setLengthSeq(seq: PGenericSeq, elemSize, newLen: int): PGenericSeq {.
|
||||
result.len = newLen
|
||||
|
||||
# --------------- other string routines ----------------------------------
|
||||
proc nimIntToStr(x: int): string {.compilerproc.} =
|
||||
proc nimIntToStr(x: int): string {.compilerRtl.} =
|
||||
result = newString(sizeof(x)*4)
|
||||
var i = 0
|
||||
var y = x
|
||||
@@ -246,7 +247,7 @@ proc nimFloatToStr(x: float): string {.compilerproc.} =
|
||||
c_sprintf(buf, "%#g", x)
|
||||
return $buf
|
||||
|
||||
proc nimInt64ToStr(x: int64): string {.compilerproc.} =
|
||||
proc nimInt64ToStr(x: int64): string {.compilerRtl.} =
|
||||
# we don't rely on C's runtime here as some C compiler's
|
||||
# int64 support is weak
|
||||
result = newString(sizeof(x)*4)
|
||||
|
||||
Reference in New Issue
Block a user