made large parts of the stdlib gcsafe

This commit is contained in:
Araq 2014-04-20 20:01:24 +02:00
commit e6d17e6273
21 changed files with 138 additions and 113 deletions

View file

@ -118,7 +118,7 @@ type
warnNilStatement, warnAnalysisLoophole, warnNilStatement, warnAnalysisLoophole,
warnDifferentHeaps, warnWriteToForeignHeap, warnImplicitClosure, warnDifferentHeaps, warnWriteToForeignHeap, warnImplicitClosure,
warnEachIdentIsTuple, warnShadowIdent, warnEachIdentIsTuple, warnShadowIdent,
warnProveInit, warnProveField, warnProveIndex, warnGcUnsafe, warnProveInit, warnProveField, warnProveIndex, warnGcUnsafe, warnGcUnsafe2,
warnUninit, warnGcMem, warnUser, warnUninit, warnGcMem, warnUser,
hintSuccess, hintSuccessX, hintSuccess, hintSuccessX,
hintLineTooLong, hintXDeclaredButNotUsed, hintConvToBaseNotNeeded, hintLineTooLong, hintXDeclaredButNotUsed, hintConvToBaseNotNeeded,
@ -387,6 +387,7 @@ const
warnProveField: "cannot prove that field '$1' is accessible [ProveField]", warnProveField: "cannot prove that field '$1' is accessible [ProveField]",
warnProveIndex: "cannot prove index '$1' is valid [ProveIndex]", warnProveIndex: "cannot prove index '$1' is valid [ProveIndex]",
warnGcUnsafe: "not GC-safe: '$1' [GcUnsafe]", warnGcUnsafe: "not GC-safe: '$1' [GcUnsafe]",
warnGcUnsafe2: "cannot prove '$1' is GC-safe. This will become a compile time error in the future.",
warnUninit: "'$1' might not have been initialized [Uninit]", warnUninit: "'$1' might not have been initialized [Uninit]",
warnGcMem: "'$1' uses GC'ed memory [GcMem]", warnGcMem: "'$1' uses GC'ed memory [GcMem]",
warnUser: "$1 [User]", warnUser: "$1 [User]",
@ -408,7 +409,7 @@ const
hintUser: "$1 [User]"] hintUser: "$1 [User]"]
const const
WarningsToStr*: array[0..25, string] = ["CannotOpenFile", "OctalEscape", WarningsToStr*: array[0..26, string] = ["CannotOpenFile", "OctalEscape",
"XIsNeverRead", "XmightNotBeenInit", "XIsNeverRead", "XmightNotBeenInit",
"Deprecated", "ConfigDeprecated", "Deprecated", "ConfigDeprecated",
"SmallLshouldNotBeUsed", "UnknownMagic", "SmallLshouldNotBeUsed", "UnknownMagic",
@ -416,7 +417,7 @@ const
"CommentXIgnored", "NilStmt", "CommentXIgnored", "NilStmt",
"AnalysisLoophole", "DifferentHeaps", "WriteToForeignHeap", "AnalysisLoophole", "DifferentHeaps", "WriteToForeignHeap",
"ImplicitClosure", "EachIdentIsTuple", "ShadowIdent", "ImplicitClosure", "EachIdentIsTuple", "ShadowIdent",
"ProveInit", "ProveField", "ProveIndex", "GcUnsafe", "Uninit", "ProveInit", "ProveField", "ProveIndex", "GcUnsafe", "GcUnsafe2", "Uninit",
"GcMem", "User"] "GcMem", "User"]
HintsToStr*: array[0..15, string] = ["Success", "SuccessX", "LineTooLong", HintsToStr*: array[0..15, string] = ["Success", "SuccessX", "LineTooLong",

View file

@ -53,7 +53,7 @@ const
wPure, wHeader, wCompilerproc, wFinal, wSize, wExtern, wShallow, wPure, wHeader, wCompilerproc, wFinal, wSize, wExtern, wShallow,
wImportCpp, wImportObjC, wError, wIncompleteStruct, wByCopy, wByRef, wImportCpp, wImportObjC, wError, wIncompleteStruct, wByCopy, wByRef,
wInheritable, wGensym, wInject, wRequiresInit, wUnchecked, wUnion, wPacked, wInheritable, wGensym, wInject, wRequiresInit, wUnchecked, wUnion, wPacked,
wBorrow} wBorrow, wGcSafe}
fieldPragmas* = {wImportc, wExportc, wDeprecated, wExtern, fieldPragmas* = {wImportc, wExportc, wDeprecated, wExtern,
wImportCpp, wImportObjC, wError} wImportCpp, wImportObjC, wError}
varPragmas* = {wImportc, wExportc, wVolatile, wRegister, wThreadVar, wNodecl, varPragmas* = {wImportc, wExportc, wVolatile, wRegister, wThreadVar, wNodecl,
@ -690,7 +690,7 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int,
if sym.typ != nil: incl(sym.typ.flags, tfThread) if sym.typ != nil: incl(sym.typ.flags, tfThread)
of wGcSafe: of wGcSafe:
noVal(it) noVal(it)
incl(sym.flags, sfThread) if sym.kind != skType: incl(sym.flags, sfThread)
if sym.typ != nil: incl(sym.typ.flags, tfGcSafe) if sym.typ != nil: incl(sym.typ.flags, tfGcSafe)
else: invalidPragma(it) else: invalidPragma(it)
of wPacked: of wPacked:

View file

@ -113,7 +113,8 @@ proc useVar(a: PEffects, n: PNode) =
if {sfGlobal, sfThread} * s.flags == {sfGlobal} and s.kind == skVar: if {sfGlobal, sfThread} * s.flags == {sfGlobal} and s.kind == skVar:
when trackGlobals: when trackGlobals:
a.addUse(copyNode(n)) a.addUse(copyNode(n))
if tfHasGCedMem in s.typ.flags or s.typ.isGCedMem: if (tfHasGCedMem in s.typ.flags or s.typ.isGCedMem) and
tfGcSafe notin s.typ.flags:
message(n.info, warnGcUnsafe, renderTree(n)) message(n.info, warnGcUnsafe, renderTree(n))
a.gcUnsafe = true a.gcUnsafe = true
@ -517,6 +518,7 @@ proc track(tracked: PEffects, n: PNode) =
addEffect(tracked, createRaise(n)) addEffect(tracked, createRaise(n))
addTag(tracked, createTag(n)) addTag(tracked, createTag(n))
when trackGlobals: addUse(tracked, createAnyGlobal(n)) when trackGlobals: addUse(tracked, createAnyGlobal(n))
# XXX handle 'gcsafe' properly for callbacks!
else: else:
mergeEffects(tracked, effectList.sons[exceptionEffects], n) mergeEffects(tracked, effectList.sons[exceptionEffects], n)
mergeTags(tracked, effectList.sons[tagEffects], n) mergeTags(tracked, effectList.sons[tagEffects], n)
@ -704,7 +706,8 @@ proc trackProc*(s: PSym, body: PNode) =
"uses an unlisted global variable: ", hints=on, symbolPredicate) "uses an unlisted global variable: ", hints=on, symbolPredicate)
effects.sons[usesEffects] = usesSpec effects.sons[usesEffects] = usesSpec
if sfThread in s.flags and t.gcUnsafe: if sfThread in s.flags and t.gcUnsafe:
localError(s.info, "'$1' is not GC-safe" % s.name.s) localError(s.info, warnGcUnsafe2, s.name.s)
#localError(s.info, "'$1' is not GC-safe" % s.name.s)
if not t.gcUnsafe: s.typ.flags.incl tfGcSafe if not t.gcUnsafe: s.typ.flags.incl tfGcSafe
proc trackTopLevelStmt*(module: PSym; n: PNode) = proc trackTopLevelStmt*(module: PSym; n: PNode) =

View file

@ -7,6 +7,7 @@
# distribution, for details about the copyright. # distribution, for details about the copyright.
# #
include "system/inclrtl"
## This module contains the interface to the compiler's abstract syntax ## This module contains the interface to the compiler's abstract syntax
## tree (`AST`:idx:). Macros operate on this tree. ## tree (`AST`:idx:). Macros operate on this tree.
@ -109,19 +110,20 @@ const
nnkCallKinds* = {nnkCall, nnkInfix, nnkPrefix, nnkPostfix, nnkCommand, nnkCallKinds* = {nnkCall, nnkInfix, nnkPrefix, nnkPostfix, nnkCommand,
nnkCallStrLit} nnkCallStrLit}
proc `[]`*(n: PNimrodNode, i: int): PNimrodNode {.magic: "NChild".} proc `[]`*(n: PNimrodNode, i: int): PNimrodNode {.magic: "NChild", noSideEffect.}
## get `n`'s `i`'th child. ## get `n`'s `i`'th child.
proc `[]=`*(n: PNimrodNode, i: int, child: PNimrodNode) {.magic: "NSetChild".} proc `[]=`*(n: PNimrodNode, i: int, child: PNimrodNode) {.magic: "NSetChild",
noSideEffect.}
## set `n`'s `i`'th child to `child`. ## set `n`'s `i`'th child to `child`.
proc `!`*(s: string): TNimrodIdent {.magic: "StrToIdent".} proc `!`*(s: string): TNimrodIdent {.magic: "StrToIdent", noSideEffect.}
## constructs an identifier from the string `s` ## constructs an identifier from the string `s`
proc `$`*(i: TNimrodIdent): string {.magic: "IdentToStr".} proc `$`*(i: TNimrodIdent): string {.magic: "IdentToStr", noSideEffect.}
## converts a Nimrod identifier to a string ## converts a Nimrod identifier to a string
proc `$`*(s: PNimrodSymbol): string {.magic: "IdentToStr".} proc `$`*(s: PNimrodSymbol): string {.magic: "IdentToStr", noSideEffect.}
## converts a Nimrod symbol to a string ## converts a Nimrod symbol to a string
proc `==`*(a, b: TNimrodIdent): bool {.magic: "EqIdent", noSideEffect.} proc `==`*(a, b: TNimrodIdent): bool {.magic: "EqIdent", noSideEffect.}
@ -130,35 +132,36 @@ proc `==`*(a, b: TNimrodIdent): bool {.magic: "EqIdent", noSideEffect.}
proc `==`*(a, b: PNimrodNode): bool {.magic: "EqNimrodNode", noSideEffect.} proc `==`*(a, b: PNimrodNode): bool {.magic: "EqNimrodNode", noSideEffect.}
## compares two Nimrod nodes ## compares two Nimrod nodes
proc len*(n: PNimrodNode): int {.magic: "NLen".} proc len*(n: PNimrodNode): int {.magic: "NLen", noSideEffect.}
## returns the number of children of `n`. ## returns the number of children of `n`.
proc add*(father, child: PNimrodNode): PNimrodNode {.magic: "NAdd", discardable.} proc add*(father, child: PNimrodNode): PNimrodNode {.magic: "NAdd", discardable,
noSideEffect.}
## Adds the `child` to the `father` node. Returns the ## Adds the `child` to the `father` node. Returns the
## father node so that calls can be nested. ## father node so that calls can be nested.
proc add*(father: PNimrodNode, children: varargs[PNimrodNode]): PNimrodNode {. proc add*(father: PNimrodNode, children: varargs[PNimrodNode]): PNimrodNode {.
magic: "NAddMultiple", discardable.} magic: "NAddMultiple", discardable, noSideEffect.}
## Adds each child of `children` to the `father` node. ## Adds each child of `children` to the `father` node.
## Returns the `father` node so that calls can be nested. ## Returns the `father` node so that calls can be nested.
proc del*(father: PNimrodNode, idx = 0, n = 1) {.magic: "NDel".} proc del*(father: PNimrodNode, idx = 0, n = 1) {.magic: "NDel", noSideEffect.}
## deletes `n` children of `father` starting at index `idx`. ## deletes `n` children of `father` starting at index `idx`.
proc kind*(n: PNimrodNode): TNimrodNodeKind {.magic: "NKind".} proc kind*(n: PNimrodNode): TNimrodNodeKind {.magic: "NKind", noSideEffect.}
## returns the `kind` of the node `n`. ## returns the `kind` of the node `n`.
proc intVal*(n: PNimrodNode): BiggestInt {.magic: "NIntVal".} proc intVal*(n: PNimrodNode): BiggestInt {.magic: "NIntVal", noSideEffect.}
proc floatVal*(n: PNimrodNode): BiggestFloat {.magic: "NFloatVal".} proc floatVal*(n: PNimrodNode): BiggestFloat {.magic: "NFloatVal", noSideEffect.}
proc symbol*(n: PNimrodNode): PNimrodSymbol {.magic: "NSymbol".} proc symbol*(n: PNimrodNode): PNimrodSymbol {.magic: "NSymbol", noSideEffect.}
proc ident*(n: PNimrodNode): TNimrodIdent {.magic: "NIdent".} proc ident*(n: PNimrodNode): TNimrodIdent {.magic: "NIdent", noSideEffect.}
proc typ*(n: PNimrodNode): typedesc {.magic: "NGetType".} proc typ*(n: PNimrodNode): typedesc {.magic: "NGetType", noSideEffect.}
proc strVal*(n: PNimrodNode): string {.magic: "NStrVal".} proc strVal*(n: PNimrodNode): string {.magic: "NStrVal", noSideEffect.}
proc `intVal=`*(n: PNimrodNode, val: BiggestInt) {.magic: "NSetIntVal".} proc `intVal=`*(n: PNimrodNode, val: BiggestInt) {.magic: "NSetIntVal", noSideEffect.}
proc `floatVal=`*(n: PNimrodNode, val: BiggestFloat) {.magic: "NSetFloatVal".} proc `floatVal=`*(n: PNimrodNode, val: BiggestFloat) {.magic: "NSetFloatVal", noSideEffect.}
proc `symbol=`*(n: PNimrodNode, val: PNimrodSymbol) {.magic: "NSetSymbol".} proc `symbol=`*(n: PNimrodNode, val: PNimrodSymbol) {.magic: "NSetSymbol", noSideEffect.}
proc `ident=`*(n: PNimrodNode, val: TNimrodIdent) {.magic: "NSetIdent".} proc `ident=`*(n: PNimrodNode, val: TNimrodIdent) {.magic: "NSetIdent", noSideEffect.}
#proc `typ=`*(n: PNimrodNode, typ: typedesc) {.magic: "NSetType".} #proc `typ=`*(n: PNimrodNode, typ: typedesc) {.magic: "NSetType".}
# this is not sound! Unfortunately forbidding 'typ=' is not enough, as you # this is not sound! Unfortunately forbidding 'typ=' is not enough, as you
# can easily do: # can easily do:
@ -166,24 +169,24 @@ proc `ident=`*(n: PNimrodNode, val: TNimrodIdent) {.magic: "NSetIdent".}
# let fake = semCheck(2.0) # let fake = semCheck(2.0)
# bracket[0] = fake # constructs a mixed array with ints and floats! # bracket[0] = fake # constructs a mixed array with ints and floats!
proc `strVal=`*(n: PNimrodNode, val: string) {.magic: "NSetStrVal".} proc `strVal=`*(n: PNimrodNode, val: string) {.magic: "NSetStrVal", noSideEffect.}
proc newNimNode*(kind: TNimrodNodeKind, proc newNimNode*(kind: TNimrodNodeKind,
n: PNimrodNode=nil): PNimrodNode {.magic: "NNewNimNode".} n: PNimrodNode=nil): PNimrodNode {.magic: "NNewNimNode", noSideEffect.}
proc copyNimNode*(n: PNimrodNode): PNimrodNode {.magic: "NCopyNimNode".} proc copyNimNode*(n: PNimrodNode): PNimrodNode {.magic: "NCopyNimNode", noSideEffect.}
proc copyNimTree*(n: PNimrodNode): PNimrodNode {.magic: "NCopyNimTree".} proc copyNimTree*(n: PNimrodNode): PNimrodNode {.magic: "NCopyNimTree", noSideEffect.}
proc error*(msg: string) {.magic: "NError".} proc error*(msg: string) {.magic: "NError", gcsafe.}
## writes an error message at compile time ## writes an error message at compile time
proc warning*(msg: string) {.magic: "NWarning".} proc warning*(msg: string) {.magic: "NWarning", gcsafe.}
## writes a warning message at compile time ## writes a warning message at compile time
proc hint*(msg: string) {.magic: "NHint".} proc hint*(msg: string) {.magic: "NHint", gcsafe.}
## writes a hint message at compile time ## writes a hint message at compile time
proc newStrLitNode*(s: string): PNimrodNode {.compileTime.} = proc newStrLitNode*(s: string): PNimrodNode {.compileTime, noSideEffect.} =
## creates a string literal node from `s` ## creates a string literal node from `s`
result = newNimNode(nnkStrLit) result = newNimNode(nnkStrLit)
result.strVal = s result.strVal = s
@ -219,7 +222,7 @@ type
## any other means in the language currently) ## any other means in the language currently)
proc bindSym*(ident: string, rule: TBindSymRule = brClosed): PNimrodNode {. proc bindSym*(ident: string, rule: TBindSymRule = brClosed): PNimrodNode {.
magic: "NBindSym".} magic: "NBindSym", noSideEffect.}
## creates a node that binds `ident` to a symbol node. The bound symbol ## creates a node that binds `ident` to a symbol node. The bound symbol
## may be an overloaded symbol. ## may be an overloaded symbol.
## If ``rule == brClosed`` either an ``nkClosedSymChoice`` tree is ## If ``rule == brClosed`` either an ``nkClosedSymChoice`` tree is
@ -230,11 +233,11 @@ proc bindSym*(ident: string, rule: TBindSymRule = brClosed): PNimrodNode {.
## returned even if the symbol is not ambiguous. ## returned even if the symbol is not ambiguous.
proc genSym*(kind: TNimrodSymKind = nskLet; ident = ""): PNimrodNode {. proc genSym*(kind: TNimrodSymKind = nskLet; ident = ""): PNimrodNode {.
magic: "NGenSym".} magic: "NGenSym", noSideEffect.}
## generates a fresh symbol that is guaranteed to be unique. The symbol ## generates a fresh symbol that is guaranteed to be unique. The symbol
## needs to occur in a declaration context. ## needs to occur in a declaration context.
proc callsite*(): PNimrodNode {.magic: "NCallSite".} proc callsite*(): PNimrodNode {.magic: "NCallSite", gcsafe.}
## returns the AST if the invokation expression that invoked this macro. ## returns the AST if the invokation expression that invoked this macro.
proc toStrLit*(n: PNimrodNode): PNimrodNode {.compileTime.} = proc toStrLit*(n: PNimrodNode): PNimrodNode {.compileTime.} =
@ -242,19 +245,19 @@ proc toStrLit*(n: PNimrodNode): PNimrodNode {.compileTime.} =
## in a string literal node ## in a string literal node
return newStrLitNode(repr(n)) return newStrLitNode(repr(n))
proc lineinfo*(n: PNimrodNode): string {.magic: "NLineInfo".} proc lineinfo*(n: PNimrodNode): string {.magic: "NLineInfo", noSideEffect.}
## returns the position the node appears in the original source file ## returns the position the node appears in the original source file
## in the form filename(line, col) ## in the form filename(line, col)
proc parseExpr*(s: string): PNimrodNode {.magic: "ParseExprToAst".} proc parseExpr*(s: string): PNimrodNode {.magic: "ParseExprToAst", noSideEffect.}
## Compiles the passed string to its AST representation. ## Compiles the passed string to its AST representation.
## Expects a single expression. ## Expects a single expression.
proc parseStmt*(s: string): PNimrodNode {.magic: "ParseStmtToAst".} proc parseStmt*(s: string): PNimrodNode {.magic: "ParseStmtToAst", noSideEffect.}
## Compiles the passed string to its AST representation. ## Compiles the passed string to its AST representation.
## Expects one or more statements. ## Expects one or more statements.
proc getAst*(macroOrTemplate: expr): PNimrodNode {.magic: "ExpandToAst".} proc getAst*(macroOrTemplate: expr): PNimrodNode {.magic: "ExpandToAst", noSideEffect.}
## Obtains the AST nodes returned from a macro or template invocation. ## Obtains the AST nodes returned from a macro or template invocation.
## Example: ## Example:
## ##
@ -263,7 +266,7 @@ proc getAst*(macroOrTemplate: expr): PNimrodNode {.magic: "ExpandToAst".}
## macro FooMacro() = ## macro FooMacro() =
## var ast = getAst(BarTemplate()) ## var ast = getAst(BarTemplate())
proc quote*(bl: stmt, op = "``"): PNimrodNode {.magic: "QuoteAst".} proc quote*(bl: stmt, op = "``"): PNimrodNode {.magic: "QuoteAst", noSideEffect.}
## Quasi-quoting operator. ## Quasi-quoting operator.
## Accepts an expression or a block and returns the AST that represents it. ## Accepts an expression or a block and returns the AST that represents it.
## Within the quoted AST, you are able to interpolate PNimrodNode expressions ## Within the quoted AST, you are able to interpolate PNimrodNode expressions

View file

@ -7,6 +7,8 @@
# distribution, for details about the copyright. # distribution, for details about the copyright.
# #
include "system/inclrtl"
import os, oids, tables, strutils, macros import os, oids, tables, strutils, macros
import rawsockets import rawsockets
@ -31,7 +33,7 @@ export TPort
type type
PFutureBase* = ref object of PObject PFutureBase* = ref object of PObject
cb: proc () {.closure.} cb: proc () {.closure,gcsafe.}
finished: bool finished: bool
PFuture*[T] = ref object of PFutureBase PFuture*[T] = ref object of PFutureBase
@ -68,7 +70,7 @@ proc fail*[T](future: PFuture[T], error: ref EBase) =
if future.cb != nil: if future.cb != nil:
future.cb() future.cb()
proc `callback=`*(future: PFutureBase, cb: proc () {.closure.}) = proc `callback=`*(future: PFutureBase, cb: proc () {.closure,gcsafe.}) =
## Sets the callback proc to be called when the future completes. ## Sets the callback proc to be called when the future completes.
## ##
## If future has already completed then ``cb`` will be called immediately. ## If future has already completed then ``cb`` will be called immediately.
@ -80,7 +82,7 @@ proc `callback=`*(future: PFutureBase, cb: proc () {.closure.}) =
future.cb() future.cb()
proc `callback=`*[T](future: PFuture[T], proc `callback=`*[T](future: PFuture[T],
cb: proc (future: PFuture[T]) {.closure.}) = cb: proc (future: PFuture[T]) {.closure,gcsafe.}) =
## Sets the callback proc to be called when the future completes. ## Sets the callback proc to be called when the future completes.
## ##
## If future has already completed then ``cb`` will be called immediately. ## If future has already completed then ``cb`` will be called immediately.
@ -122,7 +124,7 @@ when defined(windows) or defined(nimdoc):
TCompletionData* = object TCompletionData* = object
sock: TAsyncFD sock: TAsyncFD
cb: proc (sock: TAsyncFD, bytesTransferred: DWORD, cb: proc (sock: TAsyncFD, bytesTransferred: DWORD,
errcode: TOSErrorCode) {.closure.} errcode: TOSErrorCode) {.closure,gcsafe.}
PDispatcher* = ref object PDispatcher* = ref object
ioPort: THandle ioPort: THandle
@ -237,7 +239,7 @@ when defined(windows) or defined(nimdoc):
let func = let func =
cast[proc (s: TSocketHandle, name: ptr TSockAddr, namelen: cint, cast[proc (s: TSocketHandle, name: ptr TSockAddr, namelen: cint,
lpSendBuffer: pointer, dwSendDataLength: dword, lpSendBuffer: pointer, dwSendDataLength: dword,
lpdwBytesSent: PDWORD, lpOverlapped: POverlapped): bool {.stdcall.}](connectExPtr) lpdwBytesSent: PDWORD, lpOverlapped: POverlapped): bool {.stdcall,gcsafe.}](connectExPtr)
result = func(s, name, namelen, lpSendBuffer, dwSendDataLength, lpdwBytesSent, result = func(s, name, namelen, lpSendBuffer, dwSendDataLength, lpdwBytesSent,
lpOverlapped) lpOverlapped)
@ -251,7 +253,7 @@ when defined(windows) or defined(nimdoc):
cast[proc (listenSock, acceptSock: TSocketHandle, lpOutputBuffer: pointer, cast[proc (listenSock, acceptSock: TSocketHandle, lpOutputBuffer: pointer,
dwReceiveDataLength, dwLocalAddressLength, dwReceiveDataLength, dwLocalAddressLength,
dwRemoteAddressLength: DWORD, lpdwBytesReceived: PDWORD, dwRemoteAddressLength: DWORD, lpdwBytesReceived: PDWORD,
lpOverlapped: POverlapped): bool {.stdcall.}](acceptExPtr) lpOverlapped: POverlapped): bool {.stdcall,gcsafe.}](acceptExPtr)
result = func(listenSock, acceptSock, lpOutputBuffer, dwReceiveDataLength, result = func(listenSock, acceptSock, lpOutputBuffer, dwReceiveDataLength,
dwLocalAddressLength, dwRemoteAddressLength, lpdwBytesReceived, dwLocalAddressLength, dwRemoteAddressLength, lpdwBytesReceived,
lpOverlapped) lpOverlapped)
@ -268,7 +270,7 @@ when defined(windows) or defined(nimdoc):
dwReceiveDataLength, dwLocalAddressLength, dwReceiveDataLength, dwLocalAddressLength,
dwRemoteAddressLength: DWORD, LocalSockaddr: ptr ptr TSockAddr, dwRemoteAddressLength: DWORD, LocalSockaddr: ptr ptr TSockAddr,
LocalSockaddrLength: lpint, RemoteSockaddr: ptr ptr TSockAddr, LocalSockaddrLength: lpint, RemoteSockaddr: ptr ptr TSockAddr,
RemoteSockaddrLength: lpint) {.stdcall.}](getAcceptExSockAddrsPtr) RemoteSockaddrLength: lpint) {.stdcall,gcsafe.}](getAcceptExSockAddrsPtr)
func(lpOutputBuffer, dwReceiveDataLength, dwLocalAddressLength, func(lpOutputBuffer, dwReceiveDataLength, dwLocalAddressLength,
dwRemoteAddressLength, LocalSockaddr, LocalSockaddrLength, dwRemoteAddressLength, LocalSockaddr, LocalSockaddrLength,
@ -537,7 +539,7 @@ else:
from posix import EINTR, EAGAIN, EINPROGRESS, EWOULDBLOCK, MSG_PEEK from posix import EINTR, EAGAIN, EINPROGRESS, EWOULDBLOCK, MSG_PEEK
type type
TAsyncFD* = distinct cint TAsyncFD* = distinct cint
TCallback = proc (sock: TAsyncFD): bool {.closure.} TCallback = proc (sock: TAsyncFD): bool {.closure,gcsafe.}
PData* = ref object of PObject PData* = ref object of PObject
sock: TAsyncFD sock: TAsyncFD
@ -757,7 +759,7 @@ proc accept*(socket: TAsyncFD): PFuture[TAsyncFD] =
template createCb*(retFutureSym, iteratorNameSym: expr): stmt {.immediate.} = template createCb*(retFutureSym, iteratorNameSym: expr): stmt {.immediate.} =
var nameIterVar = iteratorNameSym var nameIterVar = iteratorNameSym
proc cb {.closure.} = proc cb {.closure,gcsafe.} =
if not nameIterVar.finished: if not nameIterVar.finished:
var next = nameIterVar() var next = nameIterVar()
if next == nil: if next == nil:

View file

@ -6,6 +6,8 @@
# distribution, for details about the copyright. # distribution, for details about the copyright.
# #
include "system/inclrtl"
import sockets, os import sockets, os
## This module implements an asynchronous event loop together with asynchronous sockets ## This module implements an asynchronous event loop together with asynchronous sockets
@ -98,13 +100,13 @@ type
fd*: TSocketHandle fd*: TSocketHandle
deleVal*: PObject deleVal*: PObject
handleRead*: proc (h: PObject) {.nimcall.} handleRead*: proc (h: PObject) {.nimcall, gcsafe.}
handleWrite*: proc (h: PObject) {.nimcall.} handleWrite*: proc (h: PObject) {.nimcall, gcsafe.}
handleError*: proc (h: PObject) {.nimcall.} handleError*: proc (h: PObject) {.nimcall, gcsafe.}
hasDataBuffered*: proc (h: PObject): bool {.nimcall.} hasDataBuffered*: proc (h: PObject): bool {.nimcall, gcsafe.}
open*: bool open*: bool
task*: proc (h: PObject) {.nimcall.} task*: proc (h: PObject) {.nimcall, gcsafe.}
mode*: TFileMode mode*: TFileMode
PDelegate* = ref TDelegate PDelegate* = ref TDelegate
@ -118,13 +120,13 @@ type
socket: TSocket socket: TSocket
info: TInfo info: TInfo
handleRead*: proc (s: PAsyncSocket) {.closure.} handleRead*: proc (s: PAsyncSocket) {.closure, gcsafe.}
handleWrite: proc (s: PAsyncSocket) {.closure.} handleWrite: proc (s: PAsyncSocket) {.closure, gcsafe.}
handleConnect*: proc (s: PAsyncSocket) {.closure.} handleConnect*: proc (s: PAsyncSocket) {.closure, gcsafe.}
handleAccept*: proc (s: PAsyncSocket) {.closure.} handleAccept*: proc (s: PAsyncSocket) {.closure, gcsafe.}
handleTask*: proc (s: PAsyncSocket) {.closure.} handleTask*: proc (s: PAsyncSocket) {.closure, gcsafe.}
lineBuffer: TaintedString ## Temporary storage for ``readLine`` lineBuffer: TaintedString ## Temporary storage for ``readLine``
sendBuffer: string ## Temporary storage for ``send`` sendBuffer: string ## Temporary storage for ``send``
@ -213,7 +215,7 @@ proc asyncSockHandleRead(h: PObject) =
else: else:
PAsyncSocket(h).handleAccept(PAsyncSocket(h)) PAsyncSocket(h).handleAccept(PAsyncSocket(h))
proc close*(sock: PAsyncSocket) proc close*(sock: PAsyncSocket) {.gcsafe.}
proc asyncSockHandleWrite(h: PObject) = proc asyncSockHandleWrite(h: PObject) =
when defined(ssl): when defined(ssl):
if PAsyncSocket(h).socket.isSSL and not if PAsyncSocket(h).socket.isSSL and not
@ -254,7 +256,7 @@ proc asyncSockHandleWrite(h: PObject) =
PAsyncSocket(h).deleg.mode = fmRead PAsyncSocket(h).deleg.mode = fmRead
when defined(ssl): when defined(ssl):
proc asyncSockDoHandshake(h: PObject) = proc asyncSockDoHandshake(h: PObject) {.gcsafe.} =
if PAsyncSocket(h).socket.isSSL and not if PAsyncSocket(h).socket.isSSL and not
PAsyncSocket(h).socket.gotHandshake: PAsyncSocket(h).socket.gotHandshake:
if PAsyncSocket(h).sslNeedAccept: if PAsyncSocket(h).sslNeedAccept:
@ -437,7 +439,7 @@ proc isSendDataBuffered*(s: PAsyncSocket): bool =
return s.sendBuffer.len != 0 return s.sendBuffer.len != 0
proc setHandleWrite*(s: PAsyncSocket, proc setHandleWrite*(s: PAsyncSocket,
handleWrite: proc (s: PAsyncSocket) {.closure.}) = handleWrite: proc (s: PAsyncSocket) {.closure, gcsafe.}) =
## Setter for the ``handleWrite`` event. ## Setter for the ``handleWrite`` event.
## ##
## To remove this event you should use the ``delHandleWrite`` function. ## To remove this event you should use the ``delHandleWrite`` function.

View file

@ -377,7 +377,7 @@ proc setCookie*(name, value: string) =
write(stdout, "Set-Cookie: ", name, "=", value, "\n") write(stdout, "Set-Cookie: ", name, "=", value, "\n")
var var
gcookies: PStringTable = nil gcookies {.threadvar.}: PStringTable
proc getCookie*(name: string): TaintedString = proc getCookie*(name: string): TaintedString =
## Gets a cookie. If no cookie of `name` exists, "" is returned. ## Gets a cookie. If no cookie of `name` exists, "" is returned.

View file

@ -6,6 +6,8 @@
# distribution, for details about the copyright. # distribution, for details about the copyright.
# #
include "system/inclrtl"
import sockets, strutils, parseutils, times, os, asyncio import sockets, strutils, parseutils, times, os, asyncio
## This module **partially** implements an FTP client as specified ## This module **partially** implements an FTP client as specified
@ -41,7 +43,7 @@ type
dummyA, dummyB: pointer # workaround a Nimrod API issue dummyA, dummyB: pointer # workaround a Nimrod API issue
asyncCSock: PAsyncSocket asyncCSock: PAsyncSocket
asyncDSock: PAsyncSocket asyncDSock: PAsyncSocket
handleEvent*: proc (ftp: PAsyncFTPClient, ev: TFTPEvent) {.closure.} handleEvent*: proc (ftp: PAsyncFTPClient, ev: TFTPEvent){.closure,gcsafe.}
disp: PDispatcher disp: PDispatcher
asyncDSockID: PDelegate asyncDSockID: PDelegate
user, pass: string user, pass: string
@ -59,7 +61,7 @@ type
JRetrText, JRetr, JStore JRetrText, JRetr, JStore
TFTPJob = object TFTPJob = object
prc: proc (ftp: PFTPClient, async: bool): bool {.nimcall.} prc: proc (ftp: PFTPClient, async: bool): bool {.nimcall, gcsafe.}
case typ*: FTPJobType case typ*: FTPJobType
of JRetrText: of JRetrText:
lines: string lines: string
@ -148,7 +150,8 @@ proc assertReply(received: TaintedString, expected: varargs[string]) =
[expected.join("' or '"), received.string]) [expected.join("' or '"), received.string])
proc createJob(ftp: PFTPClient, proc createJob(ftp: PFTPClient,
prc: proc (ftp: PFTPClient, async: bool): bool {.nimcall.}, prc: proc (ftp: PFTPClient, async: bool): bool {.
nimcall,gcsafe.},
cmd: FTPJobType) = cmd: FTPJobType) =
if ftp.jobInProgress: if ftp.jobInProgress:
raise newException(EFTP, "Unable to do two jobs at once.") raise newException(EFTP, "Unable to do two jobs at once.")
@ -558,7 +561,7 @@ proc csockHandleRead(s: PAsyncSocket, ftp: PAsyncFTPClient) =
proc asyncFTPClient*(address: string, port = TPort(21), proc asyncFTPClient*(address: string, port = TPort(21),
user, pass = "", user, pass = "",
handleEvent: proc (ftp: PAsyncFTPClient, ev: TFTPEvent) {.closure.} = handleEvent: proc (ftp: PAsyncFTPClient, ev: TFTPEvent) {.closure,gcsafe.} =
(proc (ftp: PAsyncFTPClient, ev: TFTPEvent) = discard)): PAsyncFTPClient = (proc (ftp: PAsyncFTPClient, ev: TFTPEvent) = discard)): PAsyncFTPClient =
## Create a ``PAsyncFTPClient`` object. ## Create a ``PAsyncFTPClient`` object.
## ##

View file

@ -477,7 +477,7 @@ proc nextAsync(s: PAsyncHTTPServer) =
s.path = data.substr(i, last-1) s.path = data.substr(i, last-1)
proc asyncHTTPServer*(handleRequest: proc (server: PAsyncHTTPServer, client: TSocket, proc asyncHTTPServer*(handleRequest: proc (server: PAsyncHTTPServer, client: TSocket,
path, query: string): bool {.closure.}, path, query: string): bool {.closure, gcsafe.},
port = TPort(80), address = "", port = TPort(80), address = "",
reuseAddr = false): PAsyncHTTPServer = reuseAddr = false): PAsyncHTTPServer =
## Creates an Asynchronous HTTP server at ``port``. ## Creates an Asynchronous HTTP server at ``port``.

View file

@ -32,6 +32,8 @@
## **Warning:** The API of this module is unstable, and therefore is subject ## **Warning:** The API of this module is unstable, and therefore is subject
## to change. ## to change.
include "system/inclrtl"
import sockets, strutils, parseutils, times, asyncio, os import sockets, strutils, parseutils, times, asyncio, os
type type
@ -41,7 +43,7 @@ type
nick, user, realname, serverPass: string nick, user, realname, serverPass: string
case isAsync: bool case isAsync: bool
of true: of true:
handleEvent: proc (irc: PAsyncIRC, ev: TIRCEvent) {.closure.} handleEvent: proc (irc: PAsyncIRC, ev: TIRCEvent) {.closure, gcsafe.}
asyncSock: PAsyncSocket asyncSock: PAsyncSocket
myDispatcher: PDispatcher myDispatcher: PDispatcher
of false: of false:
@ -445,7 +447,7 @@ proc asyncIRC*(address: string, port: TPort = 6667.TPort,
realname = "NimrodBot", serverPass = "", realname = "NimrodBot", serverPass = "",
joinChans: seq[string] = @[], joinChans: seq[string] = @[],
msgLimit: bool = true, msgLimit: bool = true,
ircEvent: proc (irc: PAsyncIRC, ev: TIRCEvent) {.closure.} ircEvent: proc (irc: PAsyncIRC, ev: TIRCEvent) {.closure,gcsafe.}
): PAsyncIRC = ): PAsyncIRC =
## Use this function if you want to use asyncio's dispatcher. ## Use this function if you want to use asyncio's dispatcher.
## ##

View file

@ -12,6 +12,8 @@
## Basic math routines for Nimrod. ## Basic math routines for Nimrod.
## This module is available for the JavaScript target. ## This module is available for the JavaScript target.
include "system/inclrtl"
{.push debugger:off .} # the user does not want to trace a part {.push debugger:off .} # the user does not want to trace a part
# of the standard library! # of the standard library!
@ -127,25 +129,25 @@ proc variance*(x: openArray[float]): float {.noSideEffect.} =
result = result + diff*diff result = result + diff*diff
result = result / toFloat(len(x)) result = result / toFloat(len(x))
proc random*(max: int): int proc random*(max: int): int {.gcsafe.}
## returns a random number in the range 0..max-1. The sequence of ## returns a random number in the range 0..max-1. The sequence of
## random number is always the same, unless `randomize` is called ## random number is always the same, unless `randomize` is called
## which initializes the random number generator with a "random" ## which initializes the random number generator with a "random"
## number, i.e. a tickcount. ## number, i.e. a tickcount.
when not defined(windows): when not defined(windows):
proc random*(max: float): float proc random*(max: float): float {.gcsafe.}
## returns a random number in the range 0..<max. The sequence of ## returns a random number in the range 0..<max. The sequence of
## random number is always the same, unless `randomize` is called ## random number is always the same, unless `randomize` is called
## which initializes the random number generator with a "random" ## which initializes the random number generator with a "random"
## number, i.e. a tickcount. This is currently not supported for windows. ## number, i.e. a tickcount. This is currently not supported for windows.
proc randomize*() proc randomize*() {.gcsafe.}
## initializes the random number generator with a "random" ## initializes the random number generator with a "random"
## number, i.e. a tickcount. Note: Does nothing for the JavaScript target, ## number, i.e. a tickcount. Note: Does nothing for the JavaScript target,
## as JavaScript does not support this. ## as JavaScript does not support this.
proc randomize*(seed: int) proc randomize*(seed: int) {.gcsafe.}
## initializes the random number generator with a specific seed. ## initializes the random number generator with a specific seed.
## Note: Does nothing for the JavaScript target, ## Note: Does nothing for the JavaScript target,
## as JavaScript does not support this. ## as JavaScript does not support this.
@ -227,8 +229,8 @@ else:
result = int(floor(mathrandom() * float(max))) result = int(floor(mathrandom() * float(max)))
proc random(max: float): float = proc random(max: float): float =
result = float(mathrandom() * float(max)) result = float(mathrandom() * float(max))
proc randomize() = nil proc randomize() = discard
proc randomize(seed: int) = nil proc randomize(seed: int) = discard
proc sqrt*(x: float): float {.importc: "Math.sqrt", nodecl.} proc sqrt*(x: float): float {.importc: "Math.sqrt", nodecl.}
proc ln*(x: float): float {.importc: "Math.log", nodecl.} proc ln*(x: float): float {.importc: "Math.log", nodecl.}

View file

@ -1564,7 +1564,7 @@ when defined(windows):
# ourselves. This has the additional benefit that the program's behaviour # ourselves. This has the additional benefit that the program's behaviour
# is always the same -- independent of the used C compiler. # is always the same -- independent of the used C compiler.
var var
ownArgv: seq[string] ownArgv {.threadvar.}: seq[string]
proc paramCount*(): int {.rtl, extern: "nos$1", tags: [FReadIO].} = proc paramCount*(): int {.rtl, extern: "nos$1", tags: [FReadIO].} =
## Returns the number of `command line arguments`:idx: given to the ## Returns the number of `command line arguments`:idx: given to the

View file

@ -70,7 +70,7 @@ const
SymChars: TCharSet = {'a'..'z', 'A'..'Z', '0'..'9', '_', '\x80'..'\xFF', '.', SymChars: TCharSet = {'a'..'z', 'A'..'Z', '0'..'9', '_', '\x80'..'\xFF', '.',
'/', '\\'} '/', '\\'}
proc rawGetTok(c: var TCfgParser, tok: var TToken) proc rawGetTok(c: var TCfgParser, tok: var TToken) {.gcsafe.}
proc open*(c: var TCfgParser, input: PStream, filename: string, proc open*(c: var TCfgParser, input: PStream, filename: string,
lineOffset = 0) {. lineOffset = 0) {.

View file

@ -26,6 +26,8 @@
## **Warning:** The API of this module is unstable, and therefore is subject ## **Warning:** The API of this module is unstable, and therefore is subject
## to change. ## to change.
include "system/inclrtl"
import sockets, strutils, os, strtabs, asyncio import sockets, strutils, os, strtabs, asyncio
type type
@ -82,7 +84,7 @@ type
TAsyncScgiState = object TAsyncScgiState = object
handleRequest: proc (client: PAsyncSocket, handleRequest: proc (client: PAsyncSocket,
input: string, headers: PStringTable) {.closure.} input: string, headers: PStringTable) {.closure,gcsafe.}
asyncServer: PAsyncSocket asyncServer: PAsyncSocket
disp: PDispatcher disp: PDispatcher
PAsyncScgiState* = ref TAsyncScgiState PAsyncScgiState* = ref TAsyncScgiState
@ -150,7 +152,7 @@ proc writeStatusOkTextContent*(c: TSocket, contentType = "text/html") =
"Content-Type: $1\r\L\r\L" % contentType) "Content-Type: $1\r\L\r\L" % contentType)
proc run*(handleRequest: proc (client: TSocket, input: string, proc run*(handleRequest: proc (client: TSocket, input: string,
headers: PStringTable): bool {.nimcall.}, headers: PStringTable): bool {.nimcall,gcsafe.},
port = TPort(4000)) = port = TPort(4000)) =
## encapsulates the SCGI object and main loop. ## encapsulates the SCGI object and main loop.
var s: TScgiState var s: TScgiState
@ -246,7 +248,8 @@ proc handleAccept(sock: PAsyncSocket, s: PAsyncScgiState) =
s.disp.register(client) s.disp.register(client)
proc open*(handleRequest: proc (client: PAsyncSocket, proc open*(handleRequest: proc (client: PAsyncSocket,
input: string, headers: PStringTable) {.closure.}, input: string, headers: PStringTable) {.
closure, gcsafe.},
port = TPort(4000), address = "127.0.0.1", port = TPort(4000), address = "127.0.0.1",
reuseAddr = false): PAsyncScgiState = reuseAddr = false): PAsyncScgiState =
## Creates an ``PAsyncScgiState`` object which serves as a SCGI server. ## Creates an ``PAsyncScgiState`` object which serves as a SCGI server.

View file

@ -24,6 +24,8 @@
## Asynchronous sockets are supported, however a better alternative is to use ## Asynchronous sockets are supported, however a better alternative is to use
## the `asyncio <asyncio.html>`_ module. ## the `asyncio <asyncio.html>`_ module.
include "system/inclrtl"
{.deadCodeElim: on.} {.deadCodeElim: on.}
when hostOS == "solaris": when hostOS == "solaris":
@ -544,7 +546,7 @@ proc acceptAddr*(server: TSocket, client: var TSocket, address: var string) {.
else: else:
SSLError("Unknown error") SSLError("Unknown error")
proc setBlocking*(s: TSocket, blocking: bool) {.tags: [].} proc setBlocking*(s: TSocket, blocking: bool) {.tags: [], gcsafe.}
## Sets blocking mode on socket ## Sets blocking mode on socket
when defined(ssl): when defined(ssl):

View file

@ -12,6 +12,8 @@
## interface for Nimrod file objects (`TFile`) and strings. Other modules ## interface for Nimrod file objects (`TFile`) and strings. Other modules
## may provide other implementations for this standard stream interface. ## may provide other implementations for this standard stream interface.
include "system/inclrtl"
proc newEIO(msg: string): ref EIO = proc newEIO(msg: string): ref EIO =
new(result) new(result)
result.msg = msg result.msg = msg
@ -23,15 +25,15 @@ type
## here shouldn't be used directly. They are ## here shouldn't be used directly. They are
## accessible so that a stream implementation ## accessible so that a stream implementation
## can override them. ## can override them.
closeImpl*: proc (s: PStream) {.nimcall, tags: [].} closeImpl*: proc (s: PStream) {.nimcall, tags: [], gcsafe.}
atEndImpl*: proc (s: PStream): bool {.nimcall, tags: [].} atEndImpl*: proc (s: PStream): bool {.nimcall, tags: [], gcsafe.}
setPositionImpl*: proc (s: PStream, pos: int) {.nimcall, tags: [].} setPositionImpl*: proc (s: PStream, pos: int) {.nimcall, tags: [], gcsafe.}
getPositionImpl*: proc (s: PStream): int {.nimcall, tags: [].} getPositionImpl*: proc (s: PStream): int {.nimcall, tags: [], gcsafe.}
readDataImpl*: proc (s: PStream, buffer: pointer, readDataImpl*: proc (s: PStream, buffer: pointer,
bufLen: int): int {.nimcall, tags: [FReadIO].} bufLen: int): int {.nimcall, tags: [FReadIO], gcsafe.}
writeDataImpl*: proc (s: PStream, buffer: pointer, bufLen: int) {.nimcall, writeDataImpl*: proc (s: PStream, buffer: pointer, bufLen: int) {.nimcall,
tags: [FWriteIO].} tags: [FWriteIO], gcsafe.}
flushImpl*: proc (s: PStream) {.nimcall, tags: [FWriteIO].} flushImpl*: proc (s: PStream) {.nimcall, tags: [FWriteIO], gcsafe.}
proc flush*(s: PStream) = proc flush*(s: PStream) =
## flushes the buffers that the stream `s` might use. ## flushes the buffers that the stream `s` might use.

View file

@ -135,38 +135,38 @@ type
months*: int ## The number of months months*: int ## The number of months
years*: int ## The number of years years*: int ## The number of years
proc getTime*(): TTime {.tags: [FTime].} proc getTime*(): TTime {.tags: [FTime], gcsafe.}
## gets the current calendar time as a UNIX epoch value (number of seconds ## gets the current calendar time as a UNIX epoch value (number of seconds
## elapsed since 1970) with integer precission. Use epochTime for higher ## elapsed since 1970) with integer precission. Use epochTime for higher
## resolution. ## resolution.
proc getLocalTime*(t: TTime): TTimeInfo {.tags: [FTime], raises: [].} proc getLocalTime*(t: TTime): TTimeInfo {.tags: [FTime], raises: [], gcsafe.}
## converts the calendar time `t` to broken-time representation, ## converts the calendar time `t` to broken-time representation,
## expressed relative to the user's specified time zone. ## expressed relative to the user's specified time zone.
proc getGMTime*(t: TTime): TTimeInfo {.tags: [FTime], raises: [].} proc getGMTime*(t: TTime): TTimeInfo {.tags: [FTime], raises: [], gcsafe.}
## converts the calendar time `t` to broken-down time representation, ## converts the calendar time `t` to broken-down time representation,
## expressed in Coordinated Universal Time (UTC). ## expressed in Coordinated Universal Time (UTC).
proc timeInfoToTime*(timeInfo: TTimeInfo): TTime {.tags: [].} proc timeInfoToTime*(timeInfo: TTimeInfo): TTime {.tags: [], gcsafe.}
## converts a broken-down time structure to ## converts a broken-down time structure to
## calendar time representation. The function ignores the specified ## calendar time representation. The function ignores the specified
## contents of the structure members `weekday` and `yearday` and recomputes ## contents of the structure members `weekday` and `yearday` and recomputes
## them from the other information in the broken-down time structure. ## them from the other information in the broken-down time structure.
proc fromSeconds*(since1970: float): TTime {.tags: [], raises: [].} proc fromSeconds*(since1970: float): TTime {.tags: [], raises: [], gcsafe.}
## Takes a float which contains the number of seconds since the unix epoch and ## Takes a float which contains the number of seconds since the unix epoch and
## returns a time object. ## returns a time object.
proc fromSeconds*(since1970: int64): TTime {.tags: [], raises: [].} = proc fromSeconds*(since1970: int64): TTime {.tags: [], raises: [], gcsafe.} =
## Takes an int which contains the number of seconds since the unix epoch and ## Takes an int which contains the number of seconds since the unix epoch and
## returns a time object. ## returns a time object.
fromSeconds(float(since1970)) fromSeconds(float(since1970))
proc toSeconds*(time: TTime): float {.tags: [], raises: [].} proc toSeconds*(time: TTime): float {.tags: [], raises: [], gcsafe.}
## Returns the time in seconds since the unix epoch. ## Returns the time in seconds since the unix epoch.
proc `$` *(timeInfo: TTimeInfo): string {.tags: [], raises: [].} proc `$` *(timeInfo: TTimeInfo): string {.tags: [], raises: [], gcsafe.}
## converts a `TTimeInfo` object to a string representation. ## converts a `TTimeInfo` object to a string representation.
proc `$` *(time: TTime): string {.tags: [], raises: [].} proc `$` *(time: TTime): string {.tags: [], raises: [], gcsafe.}
## converts a calendar time to a string representation. ## converts a calendar time to a string representation.
proc `-`*(a, b: TTime): int64 {. proc `-`*(a, b: TTime): int64 {.
@ -189,14 +189,15 @@ proc `==`*(a, b: TTime): bool {.
result = a - b == 0 result = a - b == 0
when not defined(JS): when not defined(JS):
proc getTzname*(): tuple[nonDST, DST: string] {.tags: [FTime], raises: [].} proc getTzname*(): tuple[nonDST, DST: string] {.tags: [FTime], raises: [],
gcsafe.}
## returns the local timezone; ``nonDST`` is the name of the local non-DST ## returns the local timezone; ``nonDST`` is the name of the local non-DST
## timezone, ``DST`` is the name of the local DST timezone. ## timezone, ``DST`` is the name of the local DST timezone.
proc getTimezone*(): int {.tags: [FTime], raises: [].} proc getTimezone*(): int {.tags: [FTime], raises: [], gcsafe.}
## returns the offset of the local (non-DST) timezone in seconds west of UTC. ## returns the offset of the local (non-DST) timezone in seconds west of UTC.
proc getStartMilsecs*(): int {.deprecated, tags: [FTime].} proc getStartMilsecs*(): int {.deprecated, tags: [FTime], gcsafe.}
## get the miliseconds from the start of the program. **Deprecated since ## get the miliseconds from the start of the program. **Deprecated since
## version 0.8.10.** Use ``epochTime`` or ``cpuTime`` instead. ## version 0.8.10.** Use ``epochTime`` or ``cpuTime`` instead.

View file

@ -192,9 +192,6 @@ when defined(nimNewShared):
type type
`shared`* {.magic: "Shared".} `shared`* {.magic: "Shared".}
guarded* {.magic: "Guarded".} guarded* {.magic: "Guarded".}
else:
{.pragma: gcsafe.}
#{.pragma: gcsafe.}
const NoFakeVars* = defined(NimrodVM) ## true if the backend doesn't support \ const NoFakeVars* = defined(NimrodVM) ## true if the backend doesn't support \
## "fake variables" like 'var EBADF {.importc.}: cint'. ## "fake variables" like 'var EBADF {.importc.}: cint'.

View file

@ -29,7 +29,7 @@ type
region: TMemRegion region: TMemRegion
PRawChannel = ptr TRawChannel PRawChannel = ptr TRawChannel
TLoadStoreMode = enum mStore, mLoad TLoadStoreMode = enum mStore, mLoad
TChannel*[TMsg] = TRawChannel ## a channel for thread communication TChannel* {.gcsafe.}[TMsg] = TRawChannel ## a channel for thread communication
const ChannelDeadMask = -2 const ChannelDeadMask = -2

View file

@ -16,6 +16,8 @@
# -> defined(useNimRtl) or appType == "lib" and not defined(createNimRtl) # -> defined(useNimRtl) or appType == "lib" and not defined(createNimRtl)
# 3) Exported into nimrtl. # 3) Exported into nimrtl.
# -> appType == "lib" and defined(createNimRtl) # -> appType == "lib" and defined(createNimRtl)
when not defined(nimNewShared):
{.pragma: gcsafe.}
when defined(createNimRtl): when defined(createNimRtl):
when defined(useNimRtl): when defined(useNimRtl):
@ -24,7 +26,7 @@ when defined(createNimRtl):
{.error: "nimrtl must be built as a library!".} {.error: "nimrtl must be built as a library!".}
when defined(createNimRtl): when defined(createNimRtl):
{.pragma: rtl, exportc: "nimrtl_$1", dynlib.} {.pragma: rtl, exportc: "nimrtl_$1", dynlib, gcsafe.}
{.pragma: inl.} {.pragma: inl.}
{.pragma: compilerRtl, compilerproc, exportc: "nimrtl_$1", dynlib.} {.pragma: compilerRtl, compilerproc, exportc: "nimrtl_$1", dynlib.}
elif defined(useNimRtl): elif defined(useNimRtl):
@ -34,11 +36,11 @@ elif defined(useNimRtl):
const nimrtl* = "nimrtl.dylib" const nimrtl* = "nimrtl.dylib"
else: else:
const nimrtl* = "libnimrtl.so" const nimrtl* = "libnimrtl.so"
{.pragma: rtl, importc: "nimrtl_$1", dynlib: nimrtl.} {.pragma: rtl, importc: "nimrtl_$1", dynlib: nimrtl, gcsafe.}
{.pragma: inl.} {.pragma: inl.}
{.pragma: compilerRtl, compilerproc, importc: "nimrtl_$1", dynlib: nimrtl.} {.pragma: compilerRtl, compilerproc, importc: "nimrtl_$1", dynlib: nimrtl.}
else: else:
{.pragma: rtl.} {.pragma: rtl, gcsafe.}
{.pragma: inl, inline.} {.pragma: inl, inline.}
{.pragma: compilerRtl, compilerproc.} {.pragma: compilerRtl, compilerproc.}

View file

@ -256,9 +256,9 @@ type
## that **must not** be part of a message! Use ## that **must not** be part of a message! Use
## a ``TThreadId`` for that. ## a ``TThreadId`` for that.
when TArg is void: when TArg is void:
dataFn: proc () {.nimcall.} dataFn: proc () {.nimcall, gcsafe.}
else: else:
dataFn: proc (m: TArg) {.nimcall.} dataFn: proc (m: TArg) {.nimcall, gcsafe.}
data: TArg data: TArg
TThreadId*[TArg] = ptr TThread[TArg] ## the current implementation uses TThreadId*[TArg] = ptr TThread[TArg] ## the current implementation uses
## a pointer as a thread ID. ## a pointer as a thread ID.