mirror of
https://github.com/nim-lang/Nim.git
synced 2025-12-29 01:14:41 +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)
|
||||
|
||||
@@ -530,11 +530,10 @@ proc structPragmas(p: TParser, name: PNode, origName: string): PNode =
|
||||
result = newNodeP(nkPragmaExpr, p)
|
||||
addson(result, exportSym(p, name))
|
||||
var pragmas = newNodep(nkPragma, p)
|
||||
addSon(pragmas, newIdentNodeP("pure", p))
|
||||
addSon(pragmas, newIdentNodeP("final", p))
|
||||
addSon(pragmas, newIdentNodeP("pure", p), newIdentNodeP("final", p))
|
||||
if p.options.header.len > 0:
|
||||
addSon(pragmas, newIdentStrLitPair("importc", origName, p))
|
||||
addSon(pragmas, newIdentStrLitPair("header", p.options.header, p))
|
||||
addSon(pragmas, newIdentStrLitPair("importc", origName, p),
|
||||
newIdentStrLitPair("header", p.options.header, p))
|
||||
addSon(result, pragmas)
|
||||
|
||||
proc enumPragmas(p: TParser, name: PNode): PNode =
|
||||
@@ -542,15 +541,13 @@ proc enumPragmas(p: TParser, name: PNode): PNode =
|
||||
addson(result, name)
|
||||
var pragmas = newNodep(nkPragma, p)
|
||||
var e = newNodeP(nkExprColonExpr, p)
|
||||
addSon(e, newIdentNodeP("size", p))
|
||||
addSon(e, newIntNodeP(nkIntLit, 4, p))
|
||||
addSon(e, newIdentNodeP("size", p), newIntNodeP(nkIntLit, 4, p))
|
||||
addSon(pragmas, e)
|
||||
addSon(result, pragmas)
|
||||
|
||||
proc parseStruct(p: var TParser, isUnion: bool): PNode =
|
||||
result = newNodeP(nkObjectTy, p)
|
||||
addSon(result, nil) # no pragmas
|
||||
addSon(result, nil) # no inheritance
|
||||
addSon(result, nil, nil) # no pragmas, no inheritance
|
||||
if p.tok.xkind == pxCurlyLe:
|
||||
addSon(result, parseStructBody(p, isUnion))
|
||||
else:
|
||||
@@ -569,8 +566,7 @@ proc parseParam(p: var TParser, params: PNode) =
|
||||
name = newIdentNodeP("a" & $idx, p)
|
||||
typ = parseTypeSuffix(p, typ)
|
||||
var x = newNodeP(nkIdentDefs, p)
|
||||
addSon(x, name)
|
||||
addSon(x, typ)
|
||||
addSon(x, name, typ)
|
||||
if p.tok.xkind == pxAsgn:
|
||||
# we support default parameters for C++:
|
||||
getTok(p, x)
|
||||
@@ -621,15 +617,11 @@ proc parseFunctionPointerDecl(p: var TParser, rettyp: PNode): PNode =
|
||||
if p.inTypeDef == 0:
|
||||
result = newNodeP(nkVarSection, p)
|
||||
var def = newNodeP(nkIdentDefs, p)
|
||||
addSon(def, name)
|
||||
addSon(def, procType)
|
||||
addSon(def, nil)
|
||||
addSon(def, name, procType, nil)
|
||||
addSon(result, def)
|
||||
else:
|
||||
result = newNodeP(nkTypeDef, p)
|
||||
addSon(result, name)
|
||||
addSon(result, nil) # no generics
|
||||
addSon(result, procType)
|
||||
addSon(result, name, nil, procType)
|
||||
|
||||
proc addTypeDef(section, name, t: PNode) =
|
||||
var def = newNodeI(nkTypeDef, name.info)
|
||||
@@ -674,8 +666,7 @@ proc enumFields(p: var TParser): PNode =
|
||||
var c = constantExpression(p)
|
||||
var a = e
|
||||
e = newNodeP(nkEnumFieldDef, p)
|
||||
addSon(e, a)
|
||||
addSon(e, c)
|
||||
addSon(e, a, c)
|
||||
skipCom(p, e)
|
||||
|
||||
addSon(result, e)
|
||||
@@ -871,10 +862,8 @@ proc declaration(p: var TParser): PNode =
|
||||
addSon(pragmas, newIdentNodeP("cdecl", p))
|
||||
elif pfStdcall in p.options.flags:
|
||||
addSon(pragmas, newIdentNodeP("stdcall", p))
|
||||
addSon(result, exportSym(p, name))
|
||||
addSon(result, nil) # no generics
|
||||
addSon(result, params)
|
||||
addSon(result, pragmas)
|
||||
addSon(result, exportSym(p, name), nil) # no generics
|
||||
addSon(result, params, pragmas)
|
||||
case p.tok.xkind
|
||||
of pxSemicolon:
|
||||
getTok(p)
|
||||
@@ -1175,17 +1164,14 @@ proc asgnExpr(p: var TParser, opr: string, a: PNode): PNode =
|
||||
getTok(p, a)
|
||||
var b = assignmentExpression(p)
|
||||
result = newNodeP(nkAsgn, p)
|
||||
addSon(result, a)
|
||||
addSon(result, newBinary(opr, copyTree(a), b, p))
|
||||
addSon(result, a, newBinary(opr, copyTree(a), b, p))
|
||||
|
||||
proc incdec(p: var TParser, opr: string, a: PNode): PNode =
|
||||
closeContext(p)
|
||||
getTok(p, a)
|
||||
var b = assignmentExpression(p)
|
||||
result = newNodeP(nkCall, p)
|
||||
addSon(result, newIdentNodeP(getIdent(opr), p))
|
||||
addSon(result, a)
|
||||
addSon(result, b)
|
||||
addSon(result, newIdentNodeP(getIdent(opr), p), a, b)
|
||||
|
||||
proc assignmentExpression(p: var TParser): PNode =
|
||||
saveContext(p)
|
||||
@@ -1196,8 +1182,7 @@ proc assignmentExpression(p: var TParser): PNode =
|
||||
getTok(p, a)
|
||||
var b = assignmentExpression(p)
|
||||
result = newNodeP(nkAsgn, p)
|
||||
addSon(result, a)
|
||||
addSon(result, b)
|
||||
addSon(result, a, b)
|
||||
of pxPlusAsgn: result = incDec(p, "inc", a)
|
||||
of pxMinusAsgn: result = incDec(p, "dec", a)
|
||||
of pxStarAsgn: result = asgnExpr(p, "*", a)
|
||||
@@ -1291,8 +1276,7 @@ proc conditionalExpression(p: var TParser): PNode =
|
||||
var c = conditionalExpression(p)
|
||||
result = newNodeP(nkIfExpr, p)
|
||||
var branch = newNodeP(nkElifExpr, p)
|
||||
addSon(branch, a)
|
||||
addSon(branch, b)
|
||||
addSon(branch, a, b)
|
||||
addSon(result, branch)
|
||||
branch = newNodeP(nkElseExpr, p)
|
||||
addSon(branch, c)
|
||||
|
||||
0
rod/c2nim/manual.txt
Normal file → Executable file
0
rod/c2nim/manual.txt
Normal file → Executable file
0
rod/c2nim/tests/systest.c
Normal file → Executable file
0
rod/c2nim/tests/systest.c
Normal file → Executable file
0
rod/c2nim/tests/systest2.c
Normal file → Executable file
0
rod/c2nim/tests/systest2.c
Normal file → Executable file
360
rod/ccgexprs.nim
360
rod/ccgexprs.nim
@@ -1,7 +1,7 @@
|
||||
#
|
||||
#
|
||||
# The Nimrod Compiler
|
||||
# (c) Copyright 2009 Andreas Rumpf
|
||||
# (c) Copyright 2010 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
@@ -33,7 +33,7 @@ proc genHexLiteral(v: PNode): PRope =
|
||||
result = intLiteral(v.intVal)
|
||||
|
||||
proc getStrLit(m: BModule, s: string): PRope =
|
||||
useMagic(m, "TGenericSeq")
|
||||
discard cgsym(m, "TGenericSeq")
|
||||
result = con("TMP", toRope(getID()))
|
||||
appf(m.s[cfsData], "STRING_LITERAL($1, $2, $3);$n",
|
||||
[result, makeCString(s), ToRope(len(s))])
|
||||
@@ -69,10 +69,10 @@ proc genLiteral(p: BProc, v: PNode, ty: PType): PRope =
|
||||
var id = NodeTableTestOrSet(p.module.dataCache, v, gid)
|
||||
if id == gid:
|
||||
# string literal not found in the cache:
|
||||
useMagic(p.module, "NimStringDesc")
|
||||
result = ropef("((NimStringDesc*) &$1)", [getStrLit(p.module, v.strVal)])
|
||||
result = ropecg(p.module, "((#NimStringDesc*) &$1)",
|
||||
[getStrLit(p.module, v.strVal)])
|
||||
else:
|
||||
result = ropef("((NimStringDesc*) &TMP$1)", [toRope(id)])
|
||||
result = ropecg(p.module, "((#NimStringDesc*) &TMP$1)", [toRope(id)])
|
||||
else:
|
||||
result = makeCString(v.strVal)
|
||||
of nkFloatLit..nkFloat64Lit:
|
||||
@@ -119,13 +119,11 @@ proc genRawSetData(cs: TBitSet, size: int): PRope =
|
||||
# result := toRope('0x' + ToHex(bitSetToWord(cs, size), size * 2))
|
||||
|
||||
proc genSetNode(p: BProc, n: PNode): PRope =
|
||||
var
|
||||
cs: TBitSet
|
||||
size, id: int
|
||||
size = int(getSize(n.typ))
|
||||
var cs: TBitSet
|
||||
var size = int(getSize(n.typ))
|
||||
toBitSet(n, cs)
|
||||
if size > 8:
|
||||
id = NodeTableTestOrSet(p.module.dataCache, n, gid)
|
||||
var id = NodeTableTestOrSet(p.module.dataCache, n, gid)
|
||||
result = con("TMP", toRope(id))
|
||||
if id == gid:
|
||||
# not found in cache:
|
||||
@@ -201,16 +199,13 @@ proc genRefAssign(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
|
||||
# end;
|
||||
# appf(p.s[cpsStmts], '$1 = $2;$n', [rdLoc(dest), rdLoc(src)]);
|
||||
if canFormAcycle(dest.t):
|
||||
UseMagic(p.module, "asgnRef")
|
||||
appf(p.s[cpsStmts], "asgnRef((void**) $1, $2);$n",
|
||||
appcg(p.module, p.s[cpsStmts], "#asgnRef((void**) $1, $2);$n",
|
||||
[addrLoc(dest), rdLoc(src)])
|
||||
else:
|
||||
UseMagic(p.module, "asgnRefNoCycle")
|
||||
appf(p.s[cpsStmts], "asgnRefNoCycle((void**) $1, $2);$n",
|
||||
appcg(p.module, p.s[cpsStmts], "#asgnRefNoCycle((void**) $1, $2);$n",
|
||||
[addrLoc(dest), rdLoc(src)])
|
||||
else:
|
||||
UseMagic(p.module, "unsureAsgnRef")
|
||||
appf(p.s[cpsStmts], "unsureAsgnRef((void**) $1, $2);$n",
|
||||
appcg(p.module, p.s[cpsStmts], "#unsureAsgnRef((void**) $1, $2);$n",
|
||||
[addrLoc(dest), rdLoc(src)])
|
||||
|
||||
proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
|
||||
@@ -224,70 +219,60 @@ proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
|
||||
if not (needToCopy in flags):
|
||||
genRefAssign(p, dest, src, flags)
|
||||
else:
|
||||
useMagic(p.module, "genericSeqAssign") # BUGFIX
|
||||
appf(p.s[cpsStmts], "genericSeqAssign($1, $2, $3);$n",
|
||||
appcg(p, cpsStmts, "#genericSeqAssign($1, $2, $3);$n",
|
||||
[addrLoc(dest), rdLoc(src), genTypeInfo(p.module, dest.t)])
|
||||
of tyString:
|
||||
if not (needToCopy in flags):
|
||||
genRefAssign(p, dest, src, flags)
|
||||
else:
|
||||
useMagic(p.module, "copyString")
|
||||
if (dest.s == OnStack) or not (optRefcGC in gGlobalOptions):
|
||||
appf(p.s[cpsStmts], "$1 = copyString($2);$n", [rdLoc(dest), rdLoc(src)])
|
||||
appcg(p, cpsStmts, "$1 = #copyString($2);$n", [rdLoc(dest), rdLoc(src)])
|
||||
elif dest.s == OnHeap:
|
||||
useMagic(p.module, "asgnRefNoCycle")
|
||||
useMagic(p.module, "copyString") # BUGFIX
|
||||
appf(p.s[cpsStmts], "asgnRefNoCycle((void**) $1, copyString($2));$n",
|
||||
appcg(p, cpsStmts, "#asgnRefNoCycle((void**) $1, #copyString($2));$n",
|
||||
[addrLoc(dest), rdLoc(src)])
|
||||
else:
|
||||
useMagic(p.module, "unsureAsgnRef")
|
||||
useMagic(p.module, "copyString") # BUGFIX
|
||||
appf(p.s[cpsStmts], "unsureAsgnRef((void**) $1, copyString($2));$n",
|
||||
appcg(p, cpsStmts, "#unsureAsgnRef((void**) $1, #copyString($2));$n",
|
||||
[addrLoc(dest), rdLoc(src)])
|
||||
of tyTuple:
|
||||
if needsComplexAssignment(dest.t):
|
||||
useMagic(p.module, "genericAssign")
|
||||
appf(p.s[cpsStmts], "genericAssign((void*)$1, (void*)$2, $3);$n",
|
||||
appcg(p, cpsStmts, "#genericAssign((void*)$1, (void*)$2, $3);$n",
|
||||
[addrLoc(dest), addrLoc(src), genTypeInfo(p.module, dest.t)])
|
||||
else:
|
||||
appf(p.s[cpsStmts], "$1 = $2;$n", [rdLoc(dest), rdLoc(src)])
|
||||
appcg(p, cpsStmts, "$1 = $2;$n", [rdLoc(dest), rdLoc(src)])
|
||||
of tyArray, tyArrayConstr:
|
||||
if needsComplexAssignment(dest.t):
|
||||
useMagic(p.module, "genericAssign")
|
||||
appf(p.s[cpsStmts], "genericAssign((void*)$1, (void*)$2, $3);$n",
|
||||
appcg(p, cpsStmts, "#genericAssign((void*)$1, (void*)$2, $3);$n",
|
||||
[addrLoc(dest), addrLoc(src), genTypeInfo(p.module, dest.t)])
|
||||
else:
|
||||
appf(p.s[cpsStmts],
|
||||
appcg(p, cpsStmts,
|
||||
"memcpy((void*)$1, (NIM_CONST void*)$2, sizeof($1));$n",
|
||||
[rdLoc(dest), rdLoc(src)])
|
||||
of tyObject: # XXX: check for subtyping?
|
||||
if needsComplexAssignment(dest.t):
|
||||
useMagic(p.module, "genericAssign")
|
||||
appf(p.s[cpsStmts], "genericAssign((void*)$1, (void*)$2, $3);$n",
|
||||
appcg(p, cpsStmts, "#genericAssign((void*)$1, (void*)$2, $3);$n",
|
||||
[addrLoc(dest), addrLoc(src), genTypeInfo(p.module, dest.t)])
|
||||
else:
|
||||
appf(p.s[cpsStmts], "$1 = $2;$n", [rdLoc(dest), rdLoc(src)])
|
||||
appcg(p, cpsStmts, "$1 = $2;$n", [rdLoc(dest), rdLoc(src)])
|
||||
of tyOpenArray:
|
||||
# open arrays are always on the stack - really? What if a sequence is
|
||||
# passed to an open array?
|
||||
if needsComplexAssignment(dest.t):
|
||||
useMagic(p.module, "genericAssignOpenArray")
|
||||
appf(p.s[cpsStmts], # XXX: is this correct for arrays?
|
||||
appcg(p, cpsStmts, # XXX: is this correct for arrays?
|
||||
"genericAssignOpenArray((void*)$1, (void*)$2, $1Len0, $3);$n",
|
||||
[addrLoc(dest), addrLoc(src), genTypeInfo(p.module, dest.t)])
|
||||
else:
|
||||
appf(p.s[cpsStmts],
|
||||
appcg(p, cpsStmts,
|
||||
"memcpy((void*)$1, (NIM_CONST void*)$2, sizeof($1[0])*$1Len0);$n",
|
||||
[rdLoc(dest), rdLoc(src)])
|
||||
of tySet:
|
||||
if mapType(ty) == ctArray:
|
||||
appf(p.s[cpsStmts], "memcpy((void*)$1, (NIM_CONST void*)$2, $3);$n",
|
||||
appcg(p, cpsStmts, "memcpy((void*)$1, (NIM_CONST void*)$2, $3);$n",
|
||||
[rdLoc(dest), rdLoc(src), toRope(getSize(dest.t))])
|
||||
else:
|
||||
appf(p.s[cpsStmts], "$1 = $2;$n", [rdLoc(dest), rdLoc(src)])
|
||||
appcg(p, cpsStmts, "$1 = $2;$n", [rdLoc(dest), rdLoc(src)])
|
||||
of tyPtr, tyPointer, tyChar, tyBool, tyProc, tyEnum, tyCString,
|
||||
tyInt..tyFloat128, tyRange:
|
||||
appf(p.s[cpsStmts], "$1 = $2;$n", [rdLoc(dest), rdLoc(src)])
|
||||
appcg(p, cpsStmts, "$1 = $2;$n", [rdLoc(dest), rdLoc(src)])
|
||||
else: InternalError("genAssignment(" & $ty.kind & ')')
|
||||
|
||||
proc expr(p: BProc, e: PNode, d: var TLoc)
|
||||
@@ -303,7 +288,7 @@ proc putLocIntoDest(p: BProc, d: var TLoc, s: TLoc) =
|
||||
if lfNoDeepCopy in d.flags: genAssignment(p, d, s, {})
|
||||
else: genAssignment(p, d, s, {needToCopy})
|
||||
else:
|
||||
d = s # ``d`` is free, so fill it with ``s``
|
||||
d = s # ``d`` is free, so fill it with ``s``
|
||||
|
||||
proc putIntoDest(p: BProc, d: var TLoc, t: PType, r: PRope) =
|
||||
var a: TLoc
|
||||
@@ -319,60 +304,53 @@ proc putIntoDest(p: BProc, d: var TLoc, t: PType, r: PRope) =
|
||||
d.k = locExpr
|
||||
d.t = getUniqueType(t)
|
||||
d.r = r
|
||||
d.a = - 1
|
||||
d.a = -1
|
||||
|
||||
proc binaryStmt(p: BProc, e: PNode, d: var TLoc, magic, frmt: string) =
|
||||
proc binaryStmt(p: BProc, e: PNode, d: var TLoc, frmt: string) =
|
||||
var a, b: TLoc
|
||||
if (d.k != locNone): InternalError(e.info, "binaryStmt")
|
||||
if magic != "": useMagic(p.module, magic)
|
||||
if d.k != locNone: InternalError(e.info, "binaryStmt")
|
||||
InitLocExpr(p, e.sons[1], a)
|
||||
InitLocExpr(p, e.sons[2], b)
|
||||
appf(p.s[cpsStmts], frmt, [rdLoc(a), rdLoc(b)])
|
||||
appcg(p, cpsStmts, frmt, [rdLoc(a), rdLoc(b)])
|
||||
|
||||
proc unaryStmt(p: BProc, e: PNode, d: var TLoc, magic, frmt: string) =
|
||||
proc unaryStmt(p: BProc, e: PNode, d: var TLoc, frmt: string) =
|
||||
var a: TLoc
|
||||
if (d.k != locNone): InternalError(e.info, "unaryStmt")
|
||||
if magic != "": useMagic(p.module, magic)
|
||||
InitLocExpr(p, e.sons[1], a)
|
||||
appf(p.s[cpsStmts], frmt, [rdLoc(a)])
|
||||
appcg(p, cpsStmts, frmt, [rdLoc(a)])
|
||||
|
||||
proc binaryStmtChar(p: BProc, e: PNode, d: var TLoc, magic, frmt: string) =
|
||||
proc binaryStmtChar(p: BProc, e: PNode, d: var TLoc, frmt: string) =
|
||||
var a, b: TLoc
|
||||
if (d.k != locNone): InternalError(e.info, "binaryStmtChar")
|
||||
if magic != "": useMagic(p.module, magic)
|
||||
InitLocExpr(p, e.sons[1], a)
|
||||
InitLocExpr(p, e.sons[2], b)
|
||||
appf(p.s[cpsStmts], frmt, [rdCharLoc(a), rdCharLoc(b)])
|
||||
appcg(p, cpsStmts, frmt, [rdCharLoc(a), rdCharLoc(b)])
|
||||
|
||||
proc binaryExpr(p: BProc, e: PNode, d: var TLoc, magic, frmt: string) =
|
||||
proc binaryExpr(p: BProc, e: PNode, d: var TLoc, frmt: string) =
|
||||
var a, b: TLoc
|
||||
if magic != "": useMagic(p.module, magic)
|
||||
assert(e.sons[1].typ != nil)
|
||||
assert(e.sons[2].typ != nil)
|
||||
InitLocExpr(p, e.sons[1], a)
|
||||
InitLocExpr(p, e.sons[2], b)
|
||||
putIntoDest(p, d, e.typ, ropef(frmt, [rdLoc(a), rdLoc(b)]))
|
||||
putIntoDest(p, d, e.typ, ropecg(p.module, frmt, [rdLoc(a), rdLoc(b)]))
|
||||
|
||||
proc binaryExprChar(p: BProc, e: PNode, d: var TLoc, magic, frmt: string) =
|
||||
proc binaryExprChar(p: BProc, e: PNode, d: var TLoc, frmt: string) =
|
||||
var a, b: TLoc
|
||||
if magic != "": useMagic(p.module, magic)
|
||||
assert(e.sons[1].typ != nil)
|
||||
assert(e.sons[2].typ != nil)
|
||||
InitLocExpr(p, e.sons[1], a)
|
||||
InitLocExpr(p, e.sons[2], b)
|
||||
putIntoDest(p, d, e.typ, ropef(frmt, [rdCharLoc(a), rdCharLoc(b)]))
|
||||
putIntoDest(p, d, e.typ, ropecg(p.module, frmt, [rdCharLoc(a), rdCharLoc(b)]))
|
||||
|
||||
proc unaryExpr(p: BProc, e: PNode, d: var TLoc, magic, frmt: string) =
|
||||
proc unaryExpr(p: BProc, e: PNode, d: var TLoc, frmt: string) =
|
||||
var a: TLoc
|
||||
if magic != "": useMagic(p.module, magic)
|
||||
InitLocExpr(p, e.sons[1], a)
|
||||
putIntoDest(p, d, e.typ, ropef(frmt, [rdLoc(a)]))
|
||||
putIntoDest(p, d, e.typ, ropecg(p.module, frmt, [rdLoc(a)]))
|
||||
|
||||
proc unaryExprChar(p: BProc, e: PNode, d: var TLoc, magic, frmt: string) =
|
||||
proc unaryExprChar(p: BProc, e: PNode, d: var TLoc, frmt: string) =
|
||||
var a: TLoc
|
||||
if magic != "": useMagic(p.module, magic)
|
||||
InitLocExpr(p, e.sons[1], a)
|
||||
putIntoDest(p, d, e.typ, ropef(frmt, [rdCharLoc(a)]))
|
||||
putIntoDest(p, d, e.typ, ropecg(p.module, frmt, [rdCharLoc(a)]))
|
||||
|
||||
proc binaryArithOverflow(p: BProc, e: PNode, d: var TLoc, m: TMagic) =
|
||||
const
|
||||
@@ -389,22 +367,19 @@ proc binaryArithOverflow(p: BProc, e: PNode, d: var TLoc, m: TMagic) =
|
||||
var t = skipTypes(e.typ, abstractRange)
|
||||
if getSize(t) >= platform.IntSize:
|
||||
if optOverflowCheck in p.options:
|
||||
useMagic(p.module, prc[m])
|
||||
putIntoDest(p, d, e.typ,
|
||||
ropef("$1($2, $3)", [toRope(prc[m]), rdLoc(a), rdLoc(b)]))
|
||||
putIntoDest(p, d, e.typ, ropecg(p.module,
|
||||
"#$1($2, $3)", [toRope(prc[m]), rdLoc(a), rdLoc(b)]))
|
||||
else:
|
||||
putIntoDest(p, d, e.typ, ropef("(NI$4)($2 $1 $3)", [toRope(opr[m]),
|
||||
rdLoc(a), rdLoc(b), toRope(getSize(t) * 8)]))
|
||||
else:
|
||||
if optOverflowCheck in p.options:
|
||||
useMagic(p.module, "raiseOverflow")
|
||||
if (m == mModI) or (m == mDivI):
|
||||
useMagic(p.module, "raiseDivByZero")
|
||||
appf(p.s[cpsStmts], "if (!$1) raiseDivByZero();$n", [rdLoc(b)])
|
||||
appcg(p, cpsStmts, "if (!$1) #raiseDivByZero();$n", [rdLoc(b)])
|
||||
a.r = ropef("((NI)($2) $1 (NI)($3))", [toRope(opr[m]), rdLoc(a), rdLoc(b)])
|
||||
if d.k == locNone: getTemp(p, getSysType(tyInt), d)
|
||||
genAssignment(p, d, a, {})
|
||||
appf(p.s[cpsStmts], "if ($1 < $2 || $1 > $3) raiseOverflow();$n",
|
||||
appcg(p, cpsStmts, "if ($1 < $2 || $1 > $3) #raiseOverflow();$n",
|
||||
[rdLoc(d), intLiteral(firstOrd(t)), intLiteral(lastOrd(t))])
|
||||
d.t = e.typ
|
||||
d.r = ropef("(NI$1)($2)", [toRope(getSize(t) * 8), rdLoc(d)])
|
||||
@@ -425,8 +400,7 @@ proc unaryArithOverflow(p: BProc, e: PNode, d: var TLoc, m: TMagic) =
|
||||
InitLocExpr(p, e.sons[1], a)
|
||||
t = skipTypes(e.typ, abstractRange)
|
||||
if optOverflowCheck in p.options:
|
||||
useMagic(p.module, "raiseOverflow")
|
||||
appf(p.s[cpsStmts], "if ($1 == $2) raiseOverflow();$n",
|
||||
appcg(p, cpsStmts, "if ($1 == $2) #raiseOverflow();$n",
|
||||
[rdLoc(a), intLiteral(firstOrd(t))])
|
||||
putIntoDest(p, d, e.typ, ropef(opr[m], [rdLoc(a), toRope(getSize(t) * 8)]))
|
||||
|
||||
@@ -623,8 +597,6 @@ proc genCheckedRecordField(p: BProc, e: PNode, d: var TLoc) =
|
||||
id: int
|
||||
it: PNode
|
||||
if optFieldCheck in p.options:
|
||||
useMagic(p.module, "raiseFieldError")
|
||||
useMagic(p.module, "NimStringDesc")
|
||||
ty = genRecordFieldAux(p, e.sons[0], d, a)
|
||||
r = rdLoc(a)
|
||||
f = e.sons[0].sons[1].sym
|
||||
@@ -655,12 +627,12 @@ proc genCheckedRecordField(p: BProc, e: PNode, d: var TLoc) =
|
||||
if id == gid: strLit = getStrLit(p.module, field.name.s)
|
||||
else: strLit = con("TMP", toRope(id))
|
||||
if op.magic == mNot:
|
||||
appf(p.s[cpsStmts],
|
||||
"if ($1) raiseFieldError(((NimStringDesc*) &$2));$n",
|
||||
appcg(p, cpsStmts,
|
||||
"if ($1) #raiseFieldError(((#NimStringDesc*) &$2));$n",
|
||||
[rdLoc(test), strLit])
|
||||
else:
|
||||
appf(p.s[cpsStmts],
|
||||
"if (!($1)) raiseFieldError(((NimStringDesc*) &$2));$n",
|
||||
appcg(p, cpsStmts,
|
||||
"if (!($1)) #raiseFieldError(((#NimStringDesc*) &$2));$n",
|
||||
[rdLoc(test), strLit])
|
||||
appf(r, ".$1", [field.loc.r])
|
||||
putIntoDest(p, d, field.typ, r)
|
||||
@@ -677,13 +649,12 @@ proc genArrayElem(p: BProc, e: PNode, d: var TLoc) =
|
||||
if (optBoundsCheck in p.options):
|
||||
if not isConstExpr(e.sons[1]):
|
||||
# semantic pass has already checked for const index expressions
|
||||
useMagic(p.module, "raiseIndexError")
|
||||
if firstOrd(ty) == 0:
|
||||
if (firstOrd(b.t) < firstOrd(ty)) or (lastOrd(b.t) > lastOrd(ty)):
|
||||
appf(p.s[cpsStmts], "if ((NU)($1) > (NU)($2)) raiseIndexError();$n",
|
||||
appcg(p, cpsStmts, "if ((NU)($1) > (NU)($2)) #raiseIndexError();$n",
|
||||
[rdCharLoc(b), intLiteral(lastOrd(ty))])
|
||||
else:
|
||||
appf(p.s[cpsStmts], "if ($1 < $2 || $1 > $3) raiseIndexError();$n",
|
||||
appcg(p, cpsStmts, "if ($1 < $2 || $1 > $3) #raiseIndexError();$n",
|
||||
[rdCharLoc(b), first, intLiteral(lastOrd(ty))])
|
||||
if d.k == locNone: d.s = a.s
|
||||
putIntoDest(p, d, elemType(skipTypes(ty, abstractVar)),
|
||||
@@ -703,8 +674,7 @@ proc genOpenArrayElem(p: BProc, e: PNode, d: var TLoc) =
|
||||
initLocExpr(p, e.sons[0], a)
|
||||
initLocExpr(p, e.sons[1], b) # emit range check:
|
||||
if (optBoundsCheck in p.options):
|
||||
useMagic(p.module, "raiseIndexError")
|
||||
appf(p.s[cpsStmts], "if ((NU)($1) >= (NU)($2Len0)) raiseIndexError();$n",
|
||||
appcg(p, cpsStmts, "if ((NU)($1) >= (NU)($2Len0)) #raiseIndexError();$n",
|
||||
[rdLoc(b), rdLoc(a)]) # BUGFIX: ``>=`` and not ``>``!
|
||||
if d.k == locNone: d.s = a.s
|
||||
putIntoDest(p, d, elemType(skipTypes(a.t, abstractVar)),
|
||||
@@ -718,14 +688,13 @@ proc genSeqElem(p: BPRoc, e: PNode, d: var TLoc) =
|
||||
if ty.kind in {tyRef, tyPtr}:
|
||||
ty = skipTypes(ty.sons[0], abstractVarRange) # emit range check:
|
||||
if (optBoundsCheck in p.options):
|
||||
useMagic(p.module, "raiseIndexError")
|
||||
if ty.kind == tyString:
|
||||
appf(p.s[cpsStmts],
|
||||
"if ((NU)($1) > (NU)($2->Sup.len)) raiseIndexError();$n",
|
||||
appcg(p, cpsStmts,
|
||||
"if ((NU)($1) > (NU)($2->Sup.len)) #raiseIndexError();$n",
|
||||
[rdLoc(b), rdLoc(a)])
|
||||
else:
|
||||
appf(p.s[cpsStmts],
|
||||
"if ((NU)($1) >= (NU)($2->Sup.len)) raiseIndexError();$n",
|
||||
appcg(p, cpsStmts,
|
||||
"if ((NU)($1) >= (NU)($2->Sup.len)) #raiseIndexError();$n",
|
||||
[rdLoc(b), rdLoc(a)])
|
||||
if d.k == locNone: d.s = OnHeap
|
||||
if skipTypes(a.t, abstractVar).kind in {tyRef, tyPtr}:
|
||||
@@ -811,12 +780,10 @@ proc genIfExpr(p: BProc, n: PNode, d: var TLoc) =
|
||||
|
||||
proc genEcho(p: BProc, n: PNode) =
|
||||
var a: TLoc
|
||||
useMagic(p.module, "rawEcho")
|
||||
useMagic(p.module, "rawEchoNL")
|
||||
for i in countup(1, sonsLen(n) - 1):
|
||||
initLocExpr(p, n.sons[i], a)
|
||||
appf(p.s[cpsStmts], "rawEcho($1);$n", [rdLoc(a)])
|
||||
app(p.s[cpsStmts], "rawEchoNL();" & tnl)
|
||||
appcg(p, cpsStmts, "#rawEcho($1);$n", [rdLoc(a)])
|
||||
appcg(p, cpsStmts, "#rawEchoNL();$n")
|
||||
|
||||
proc genCall(p: BProc, t: PNode, d: var TLoc) =
|
||||
var
|
||||
@@ -879,7 +846,6 @@ proc genStrConcat(p: BProc, e: PNode, d: var TLoc) =
|
||||
# asgn(s, tmp0);
|
||||
# }
|
||||
var a, tmp: TLoc
|
||||
useMagic(p.module, "rawNewString")
|
||||
getTemp(p, e.typ, tmp)
|
||||
var L = 0
|
||||
var appends: PRope = nil
|
||||
@@ -889,16 +855,14 @@ proc genStrConcat(p: BProc, e: PNode, d: var TLoc) =
|
||||
initLocExpr(p, e.sons[i + 1], a)
|
||||
if skipTypes(e.sons[i + 1].Typ, abstractVarRange).kind == tyChar:
|
||||
Inc(L)
|
||||
useMagic(p.module, "appendChar")
|
||||
appf(appends, "appendChar($1, $2);$n", [tmp.r, rdLoc(a)])
|
||||
appcg(p.module, appends, "#appendChar($1, $2);$n", [tmp.r, rdLoc(a)])
|
||||
else:
|
||||
if e.sons[i + 1].kind in {nkStrLit..nkTripleStrLit}:
|
||||
Inc(L, len(e.sons[i + 1].strVal))
|
||||
else:
|
||||
appf(lens, "$1->Sup.len + ", [rdLoc(a)])
|
||||
useMagic(p.module, "appendString")
|
||||
appf(appends, "appendString($1, $2);$n", [tmp.r, rdLoc(a)])
|
||||
appf(p.s[cpsStmts], "$1 = rawNewString($2$3);$n", [tmp.r, lens, toRope(L)])
|
||||
appcg(p.module, appends, "#appendString($1, $2);$n", [tmp.r, rdLoc(a)])
|
||||
appcg(p, cpsStmts, "$1 = #rawNewString($2$3);$n", [tmp.r, lens, toRope(L)])
|
||||
app(p.s[cpsStmts], appends)
|
||||
if d.k == locNone:
|
||||
d = tmp
|
||||
@@ -922,7 +886,6 @@ proc genStrAppend(p: BProc, e: PNode, d: var TLoc) =
|
||||
L: int
|
||||
appends, lens: PRope
|
||||
assert(d.k == locNone)
|
||||
useMagic(p.module, "resizeString")
|
||||
L = 0
|
||||
appends = nil
|
||||
lens = nil
|
||||
@@ -932,16 +895,16 @@ proc genStrAppend(p: BProc, e: PNode, d: var TLoc) =
|
||||
initLocExpr(p, e.sons[i + 2], a)
|
||||
if skipTypes(e.sons[i + 2].Typ, abstractVarRange).kind == tyChar:
|
||||
Inc(L)
|
||||
useMagic(p.module, "appendChar")
|
||||
appf(appends, "appendChar($1, $2);$n", [rdLoc(dest), rdLoc(a)])
|
||||
appcg(p.module, appends, "#appendChar($1, $2);$n",
|
||||
[rdLoc(dest), rdLoc(a)])
|
||||
else:
|
||||
if e.sons[i + 2].kind in {nkStrLit..nkTripleStrLit}:
|
||||
Inc(L, len(e.sons[i + 2].strVal))
|
||||
else:
|
||||
appf(lens, "$1->Sup.len + ", [rdLoc(a)])
|
||||
useMagic(p.module, "appendString")
|
||||
appf(appends, "appendString($1, $2);$n", [rdLoc(dest), rdLoc(a)])
|
||||
appf(p.s[cpsStmts], "$1 = resizeString($1, $2$3);$n",
|
||||
appcg(p.module, appends, "#appendString($1, $2);$n",
|
||||
[rdLoc(dest), rdLoc(a)])
|
||||
appcg(p, cpsStmts, "$1 = #resizeString($1, $2$3);$n",
|
||||
[rdLoc(dest), lens, toRope(L)])
|
||||
app(p.s[cpsStmts], appends)
|
||||
|
||||
@@ -950,10 +913,10 @@ proc genSeqElemAppend(p: BProc, e: PNode, d: var TLoc) =
|
||||
# seq = (typeof seq) incrSeq(&seq->Sup, sizeof(x));
|
||||
# seq->data[seq->len-1] = x;
|
||||
var a, b, dest: TLoc
|
||||
useMagic(p.module, "incrSeq")
|
||||
InitLocExpr(p, e.sons[1], a)
|
||||
InitLocExpr(p, e.sons[2], b)
|
||||
appf(p.s[cpsStmts], "$1 = ($2) incrSeq(&($1)->Sup, sizeof($3));$n", [rdLoc(a),
|
||||
appcg(p, cpsStmts, "$1 = ($2) #incrSeq(&($1)->Sup, sizeof($3));$n", [
|
||||
rdLoc(a),
|
||||
getTypeDesc(p.module, skipTypes(e.sons[1].typ, abstractVar)),
|
||||
getTypeDesc(p.module, skipTypes(e.sons[2].Typ, abstractVar))])
|
||||
initLoc(dest, locExpr, b.t, OnHeap)
|
||||
@@ -977,20 +940,19 @@ proc genObjectInit(p: BProc, t: PType, a: TLoc, takeAddr: bool) =
|
||||
appf(p.s[cpsStmts], "$1.m_type = $2;$n", [r, genTypeInfo(p.module, t)])
|
||||
of frEmbedded:
|
||||
# worst case for performance:
|
||||
useMagic(p.module, "objectInit")
|
||||
if takeAddr: r = addrLoc(a)
|
||||
else: r = rdLoc(a)
|
||||
appf(p.s[cpsStmts], "objectInit($1, $2);$n", [r, genTypeInfo(p.module, t)])
|
||||
appcg(p, cpsStmts, "#objectInit($1, $2);$n", [r, genTypeInfo(p.module, t)])
|
||||
|
||||
proc genNew(p: BProc, e: PNode) =
|
||||
var
|
||||
a, b: TLoc
|
||||
reftype, bt: PType
|
||||
useMagic(p.module, "newObj")
|
||||
refType = skipTypes(e.sons[1].typ, abstractVarRange)
|
||||
InitLocExpr(p, e.sons[1], a)
|
||||
initLoc(b, locExpr, a.t, OnHeap)
|
||||
b.r = ropef("($1) newObj($2, sizeof($3))", [getTypeDesc(p.module, reftype),
|
||||
b.r = ropecg(p.module,
|
||||
"($1) #newObj($2, sizeof($3))", [getTypeDesc(p.module, reftype),
|
||||
genTypeInfo(p.module, refType),
|
||||
getTypeDesc(p.module, skipTypes(reftype.sons[0], abstractRange))])
|
||||
genAssignment(p, a, b, {}) # set the object type:
|
||||
@@ -1001,13 +963,13 @@ proc genNewSeq(p: BProc, e: PNode) =
|
||||
var
|
||||
a, b, c: TLoc
|
||||
seqtype: PType
|
||||
useMagic(p.module, "newSeq")
|
||||
seqType = skipTypes(e.sons[1].typ, abstractVarRange)
|
||||
InitLocExpr(p, e.sons[1], a)
|
||||
InitLocExpr(p, e.sons[2], b)
|
||||
initLoc(c, locExpr, a.t, OnHeap)
|
||||
c.r = ropef("($1) newSeq($2, $3)", [getTypeDesc(p.module, seqtype),
|
||||
genTypeInfo(p.module, seqType), rdLoc(b)])
|
||||
c.r = ropecg(p.module, "($1) #newSeq($2, $3)", [
|
||||
getTypeDesc(p.module, seqtype),
|
||||
genTypeInfo(p.module, seqType), rdLoc(b)])
|
||||
genAssignment(p, a, c, {})
|
||||
|
||||
proc genIs(p: BProc, x: PNode, typ: PType, d: var TLoc) =
|
||||
@@ -1017,7 +979,6 @@ proc genIs(p: BProc, x: PNode, typ: PType, d: var TLoc) =
|
||||
r, nilcheck: PRope
|
||||
initLocExpr(p, x, a)
|
||||
dest = skipTypes(typ, abstractPtrs)
|
||||
useMagic(p.module, "isObj")
|
||||
r = rdLoc(a)
|
||||
nilCheck = nil
|
||||
t = skipTypes(a.t, abstractInst)
|
||||
@@ -1030,10 +991,10 @@ proc genIs(p: BProc, x: PNode, typ: PType, d: var TLoc) =
|
||||
app(r, ".Sup")
|
||||
t = skipTypes(t.sons[0], abstractInst)
|
||||
if nilCheck != nil:
|
||||
r = ropef("(($1) && isObj($2.m_type, $3))",
|
||||
r = ropecg(p.module, "(($1) && #isObj($2.m_type, $3))",
|
||||
[nilCheck, r, genTypeInfo(p.module, dest)])
|
||||
else:
|
||||
r = ropef("isObj($1.m_type, $2)", [r, genTypeInfo(p.module, dest)])
|
||||
r = ropecg(p.module, "#isObj($1.m_type, $2)", [r, genTypeInfo(p.module, dest)])
|
||||
putIntoDest(p, d, getSysType(tyBool), r)
|
||||
|
||||
proc genIs(p: BProc, n: PNode, d: var TLoc) =
|
||||
@@ -1045,7 +1006,6 @@ proc genNewFinalize(p: BProc, e: PNode) =
|
||||
refType, bt: PType
|
||||
ti: PRope
|
||||
oldModule: BModule
|
||||
useMagic(p.module, "newObj")
|
||||
refType = skipTypes(e.sons[1].typ, abstractVarRange)
|
||||
InitLocExpr(p, e.sons[1], a)
|
||||
# This is a little hack:
|
||||
@@ -1057,7 +1017,8 @@ proc genNewFinalize(p: BProc, e: PNode) =
|
||||
initLoc(b, locExpr, a.t, OnHeap)
|
||||
ti = genTypeInfo(p.module, refType)
|
||||
appf(gNimDat.s[cfsTypeInit3], "$1->finalizer = (void*)$2;$n", [ti, rdLoc(f)])
|
||||
b.r = ropef("($1) newObj($2, sizeof($3))", [getTypeDesc(p.module, refType),
|
||||
b.r = ropecg(p.module, "($1) #newObj($2, sizeof($3))", [
|
||||
getTypeDesc(p.module, refType),
|
||||
ti, getTypeDesc(p.module, skipTypes(reftype.sons[0], abstractRange))])
|
||||
genAssignment(p, a, b, {}) # set the object type:
|
||||
bt = skipTypes(refType.sons[0], abstractRange)
|
||||
@@ -1069,30 +1030,23 @@ proc genRepr(p: BProc, e: PNode, d: var TLoc) =
|
||||
var t = skipTypes(e.sons[1].typ, abstractVarRange)
|
||||
case t.kind
|
||||
of tyInt..tyInt64:
|
||||
UseMagic(p.module, "reprInt")
|
||||
putIntoDest(p, d, e.typ, ropef("reprInt($1)", [rdLoc(a)]))
|
||||
putIntoDest(p, d, e.typ, ropecg(p.module, "#reprInt($1)", [rdLoc(a)]))
|
||||
of tyFloat..tyFloat128:
|
||||
UseMagic(p.module, "reprFloat")
|
||||
putIntoDest(p, d, e.typ, ropef("reprFloat($1)", [rdLoc(a)]))
|
||||
putIntoDest(p, d, e.typ, ropecg(p.module, "#reprFloat($1)", [rdLoc(a)]))
|
||||
of tyBool:
|
||||
UseMagic(p.module, "reprBool")
|
||||
putIntoDest(p, d, e.typ, ropef("reprBool($1)", [rdLoc(a)]))
|
||||
putIntoDest(p, d, e.typ, ropecg(p.module, "#reprBool($1)", [rdLoc(a)]))
|
||||
of tyChar:
|
||||
UseMagic(p.module, "reprChar")
|
||||
putIntoDest(p, d, e.typ, ropef("reprChar($1)", [rdLoc(a)]))
|
||||
putIntoDest(p, d, e.typ, ropecg(p.module, "#reprChar($1)", [rdLoc(a)]))
|
||||
of tyEnum, tyOrdinal:
|
||||
UseMagic(p.module, "reprEnum")
|
||||
putIntoDest(p, d, e.typ,
|
||||
ropef("reprEnum($1, $2)", [rdLoc(a), genTypeInfo(p.module, t)]))
|
||||
ropecg(p.module, "#reprEnum($1, $2)", [
|
||||
rdLoc(a), genTypeInfo(p.module, t)]))
|
||||
of tyString:
|
||||
UseMagic(p.module, "reprStr")
|
||||
putIntoDest(p, d, e.typ, ropef("reprStr($1)", [rdLoc(a)]))
|
||||
putIntoDest(p, d, e.typ, ropecg(p.module, "#reprStr($1)", [rdLoc(a)]))
|
||||
of tySet:
|
||||
useMagic(p.module, "reprSet")
|
||||
putIntoDest(p, d, e.typ,
|
||||
ropef("reprSet($1, $2)", [rdLoc(a), genTypeInfo(p.module, t)]))
|
||||
putIntoDest(p, d, e.typ, ropecg(p.module, "#reprSet($1, $2)", [
|
||||
rdLoc(a), genTypeInfo(p.module, t)]))
|
||||
of tyOpenArray:
|
||||
useMagic(p.module, "reprOpenArray")
|
||||
var b: TLoc
|
||||
case a.t.kind
|
||||
of tyOpenArray: putIntoDest(p, b, e.typ, rdLoc(a))
|
||||
@@ -1102,23 +1056,22 @@ proc genRepr(p: BProc, e: PNode, d: var TLoc) =
|
||||
putIntoDest(p, b, e.typ,
|
||||
ropef("$1, $2", [rdLoc(a), toRope(lengthOrd(a.t))]))
|
||||
else: InternalError(e.sons[0].info, "genRepr()")
|
||||
putIntoDest(p, d, e.typ, ropef("reprOpenArray($1, $2)", [rdLoc(b),
|
||||
putIntoDest(p, d, e.typ,
|
||||
ropecg(p.module, "#reprOpenArray($1, $2)", [rdLoc(b),
|
||||
genTypeInfo(p.module, elemType(t))]))
|
||||
of tyCString, tyArray, tyArrayConstr, tyRef, tyPtr, tyPointer, tyNil,
|
||||
tySequence:
|
||||
useMagic(p.module, "reprAny")
|
||||
putIntoDest(p, d, e.typ,
|
||||
ropef("reprAny($1, $2)", [rdLoc(a), genTypeInfo(p.module, t)]))
|
||||
ropecg(p.module, "#reprAny($1, $2)", [
|
||||
rdLoc(a), genTypeInfo(p.module, t)]))
|
||||
else:
|
||||
useMagic(p.module, "reprAny")
|
||||
putIntoDest(p, d, e.typ, ropef("reprAny($1, $2)",
|
||||
putIntoDest(p, d, e.typ, ropecg(p.module, "#reprAny($1, $2)",
|
||||
[addrLoc(a), genTypeInfo(p.module, t)]))
|
||||
|
||||
proc genDollar(p: BProc, n: PNode, d: var TLoc, magic, frmt: string) =
|
||||
proc genDollar(p: BProc, n: PNode, d: var TLoc, frmt: string) =
|
||||
var a: TLoc
|
||||
InitLocExpr(p, n.sons[1], a)
|
||||
UseMagic(p.module, magic)
|
||||
a.r = ropef(frmt, [rdLoc(a)])
|
||||
a.r = ropecg(p.module, frmt, [rdLoc(a)])
|
||||
if d.k == locNone: getTemp(p, n.typ, d)
|
||||
genAssignment(p, d, a, {})
|
||||
|
||||
@@ -1127,14 +1080,14 @@ proc genArrayLen(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
|
||||
case typ.kind
|
||||
of tyOpenArray:
|
||||
while e.sons[1].kind == nkPassAsOpenArray: e.sons[1] = e.sons[1].sons[0]
|
||||
if op == mHigh: unaryExpr(p, e, d, "", "($1Len0-1)")
|
||||
else: unaryExpr(p, e, d, "", "$1Len0")
|
||||
if op == mHigh: unaryExpr(p, e, d, "($1Len0-1)")
|
||||
else: unaryExpr(p, e, d, "$1Len0")
|
||||
of tyCstring:
|
||||
if op == mHigh: unaryExpr(p, e, d, "", "(strlen($1)-1)")
|
||||
else: unaryExpr(p, e, d, "", "strlen($1)")
|
||||
if op == mHigh: unaryExpr(p, e, d, "(strlen($1)-1)")
|
||||
else: unaryExpr(p, e, d, "strlen($1)")
|
||||
of tyString, tySequence:
|
||||
if op == mHigh: unaryExpr(p, e, d, "", "($1->Sup.len-1)")
|
||||
else: unaryExpr(p, e, d, "", "$1->Sup.len")
|
||||
if op == mHigh: unaryExpr(p, e, d, "($1->Sup.len-1)")
|
||||
else: unaryExpr(p, e, d, "$1->Sup.len")
|
||||
of tyArray, tyArrayConstr:
|
||||
# YYY: length(sideeffect) is optimized away incorrectly?
|
||||
if op == mHigh: putIntoDest(p, d, e.typ, toRope(lastOrd(Typ)))
|
||||
@@ -1144,16 +1097,15 @@ proc genArrayLen(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
|
||||
proc genSetLengthSeq(p: BProc, e: PNode, d: var TLoc) =
|
||||
var a, b: TLoc
|
||||
assert(d.k == locNone)
|
||||
useMagic(p.module, "setLengthSeq")
|
||||
InitLocExpr(p, e.sons[1], a)
|
||||
InitLocExpr(p, e.sons[2], b)
|
||||
var t = skipTypes(e.sons[1].typ, abstractVar)
|
||||
appf(p.s[cpsStmts], "$1 = ($3) setLengthSeq(&($1)->Sup, sizeof($4), $2);$n", [
|
||||
appcg(p, cpsStmts, "$1 = ($3) #setLengthSeq(&($1)->Sup, sizeof($4), $2);$n", [
|
||||
rdLoc(a), rdLoc(b), getTypeDesc(p.module, t),
|
||||
getTypeDesc(p.module, t.sons[0])])
|
||||
|
||||
proc genSetLengthStr(p: BProc, e: PNode, d: var TLoc) =
|
||||
binaryStmt(p, e, d, "setLengthStr", "$1 = setLengthStr($1, $2);$n")
|
||||
binaryStmt(p, e, d, "$1 = #setLengthStr($1, $2);$n")
|
||||
|
||||
proc genSwap(p: BProc, e: PNode, d: var TLoc) =
|
||||
# swap(a, b) -->
|
||||
@@ -1257,15 +1209,15 @@ proc genSetOp(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
|
||||
binaryStmtInExcl(p, e, d, "$1 &= ~(1 << ((" & ts & ")($2) % (sizeof(" &
|
||||
ts & ")*8)));$n")
|
||||
of mCard:
|
||||
if size <= 4: unaryExprChar(p, e, d, "countBits32", "countBits32($1)")
|
||||
else: unaryExprChar(p, e, d, "countBits64", "countBits64($1)")
|
||||
of mLtSet: binaryExprChar(p, e, d, "", "(($1 & ~ $2 ==0)&&($1 != $2))")
|
||||
of mLeSet: binaryExprChar(p, e, d, "", "(($1 & ~ $2)==0)")
|
||||
of mEqSet: binaryExpr(p, e, d, "", "($1 == $2)")
|
||||
of mMulSet: binaryExpr(p, e, d, "", "($1 & $2)")
|
||||
of mPlusSet: binaryExpr(p, e, d, "", "($1 | $2)")
|
||||
of mMinusSet: binaryExpr(p, e, d, "", "($1 & ~ $2)")
|
||||
of mSymDiffSet: binaryExpr(p, e, d, "", "($1 ^ $2)")
|
||||
if size <= 4: unaryExprChar(p, e, d, "#countBits32($1)")
|
||||
else: unaryExprChar(p, e, d, "#countBits64($1)")
|
||||
of mLtSet: binaryExprChar(p, e, d, "(($1 & ~ $2 ==0)&&($1 != $2))")
|
||||
of mLeSet: binaryExprChar(p, e, d, "(($1 & ~ $2)==0)")
|
||||
of mEqSet: binaryExpr(p, e, d, "($1 == $2)")
|
||||
of mMulSet: binaryExpr(p, e, d, "($1 & $2)")
|
||||
of mPlusSet: binaryExpr(p, e, d, "($1 | $2)")
|
||||
of mMinusSet: binaryExpr(p, e, d, "($1 & ~ $2)")
|
||||
of mSymDiffSet: binaryExpr(p, e, d, "($1 ^ $2)")
|
||||
of mInSet:
|
||||
genInOp(p, e, d)
|
||||
else: internalError(e.info, "genSetOp()")
|
||||
@@ -1273,7 +1225,7 @@ proc genSetOp(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
|
||||
case op
|
||||
of mIncl: binaryStmtInExcl(p, e, d, "$1[$2/8] |=(1<<($2%8));$n")
|
||||
of mExcl: binaryStmtInExcl(p, e, d, "$1[$2/8] &= ~(1<<($2%8));$n")
|
||||
of mCard: unaryExprChar(p, e, d, "cardSet", "cardSet($1, " & $size & ')')
|
||||
of mCard: unaryExprChar(p, e, d, "#cardSet($1, " & $size & ')')
|
||||
of mLtSet, mLeSet:
|
||||
getTemp(p, getSysType(tyInt), i) # our counter
|
||||
initLocExpr(p, e.sons[1], a)
|
||||
@@ -1282,7 +1234,7 @@ proc genSetOp(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
|
||||
appf(p.s[cpsStmts], lookupOpr[op],
|
||||
[rdLoc(i), toRope(size), rdLoc(d), rdLoc(a), rdLoc(b)])
|
||||
of mEqSet:
|
||||
binaryExprChar(p, e, d, "", "(memcmp($1, $2, " & $(size) & ")==0)")
|
||||
binaryExprChar(p, e, d, "(memcmp($1, $2, " & $(size) & ")==0)")
|
||||
of mMulSet, mPlusSet, mMinusSet, mSymDiffSet:
|
||||
# we inline the simple for loop for better code generation:
|
||||
getTemp(p, getSysType(tyInt), i) # our counter
|
||||
@@ -1297,7 +1249,7 @@ proc genSetOp(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
|
||||
else: internalError(e.info, "genSetOp")
|
||||
|
||||
proc genOrd(p: BProc, e: PNode, d: var TLoc) =
|
||||
unaryExprChar(p, e, d, "", "$1")
|
||||
unaryExprChar(p, e, d, "$1")
|
||||
|
||||
proc genCast(p: BProc, e: PNode, d: var TLoc) =
|
||||
const
|
||||
@@ -1317,14 +1269,13 @@ proc genCast(p: BProc, e: PNode, d: var TLoc) =
|
||||
proc genRangeChck(p: BProc, n: PNode, d: var TLoc, magic: string) =
|
||||
var a: TLoc
|
||||
var dest = skipTypes(n.typ, abstractVar)
|
||||
if not (optRangeCheck in p.options):
|
||||
if optRangeCheck notin p.options:
|
||||
InitLocExpr(p, n.sons[0], a)
|
||||
putIntoDest(p, d, n.typ, ropef("(($1) ($2))",
|
||||
[getTypeDesc(p.module, dest), rdCharLoc(a)]))
|
||||
else:
|
||||
InitLocExpr(p, n.sons[0], a)
|
||||
useMagic(p.module, magic)
|
||||
putIntoDest(p, d, dest, ropef("(($1)$5($2, $3, $4))", [
|
||||
putIntoDest(p, d, dest, ropecg(p.module, "(($1)#$5($2, $3, $4))", [
|
||||
getTypeDesc(p.module, dest), rdCharLoc(a),
|
||||
genLiteral(p, n.sons[1], dest), genLiteral(p, n.sons[2], dest),
|
||||
toRope(magic)]))
|
||||
@@ -1356,17 +1307,16 @@ proc convStrToCStr(p: BProc, n: PNode, d: var TLoc) =
|
||||
|
||||
proc convCStrToStr(p: BProc, n: PNode, d: var TLoc) =
|
||||
var a: TLoc
|
||||
useMagic(p.module, "cstrToNimstr")
|
||||
initLocExpr(p, n.sons[0], a)
|
||||
putIntoDest(p, d, skipTypes(n.typ, abstractVar),
|
||||
ropef("cstrToNimstr($1)", [rdLoc(a)]))
|
||||
ropecg(p.module, "#cstrToNimstr($1)", [rdLoc(a)]))
|
||||
|
||||
proc genStrEquals(p: BProc, e: PNode, d: var TLoc) =
|
||||
var x: TLoc
|
||||
var a = e.sons[1]
|
||||
var b = e.sons[2]
|
||||
if (a.kind == nkNilLit) or (b.kind == nkNilLit):
|
||||
binaryExpr(p, e, d, "", "($1 == $2)")
|
||||
binaryExpr(p, e, d, "($1 == $2)")
|
||||
elif (a.kind in {nkStrLit..nkTripleStrLit}) and (a.strVal == ""):
|
||||
initLocExpr(p, e.sons[2], x)
|
||||
putIntoDest(p, d, e.typ, ropef("(($1) && ($1)->Sup.len == 0)", [rdLoc(x)]))
|
||||
@@ -1374,16 +1324,16 @@ proc genStrEquals(p: BProc, e: PNode, d: var TLoc) =
|
||||
initLocExpr(p, e.sons[1], x)
|
||||
putIntoDest(p, d, e.typ, ropef("(($1) && ($1)->Sup.len == 0)", [rdLoc(x)]))
|
||||
else:
|
||||
binaryExpr(p, e, d, "eqStrings", "eqStrings($1, $2)")
|
||||
binaryExpr(p, e, d, "#eqStrings($1, $2)")
|
||||
|
||||
proc genSeqConstr(p: BProc, t: PNode, d: var TLoc) =
|
||||
var newSeq, arr: TLoc
|
||||
useMagic(p.module, "newSeq")
|
||||
if d.k == locNone:
|
||||
getTemp(p, t.typ, d)
|
||||
# generate call to newSeq before adding the elements per hand:
|
||||
initLoc(newSeq, locExpr, t.typ, OnHeap)
|
||||
newSeq.r = ropef("($1) newSeq($2, $3)", [getTypeDesc(p.module, t.typ),
|
||||
newSeq.r = ropecg(p.module, "($1) #newSeq($2, $3)",
|
||||
[getTypeDesc(p.module, t.typ),
|
||||
genTypeInfo(p.module, t.typ), intLiteral(sonsLen(t))])
|
||||
genAssignment(p, d, newSeq, {afSrcIsNotNil})
|
||||
for i in countup(0, sonsLen(t) - 1):
|
||||
@@ -1398,13 +1348,13 @@ proc genArrToSeq(p: BProc, t: PNode, d: var TLoc) =
|
||||
t.sons[1].typ = t.typ
|
||||
genSeqConstr(p, t.sons[1], d)
|
||||
return
|
||||
useMagic(p.module, "newSeq")
|
||||
if d.k == locNone:
|
||||
getTemp(p, t.typ, d)
|
||||
# generate call to newSeq before adding the elements per hand:
|
||||
var L = int(lengthOrd(t.sons[1].typ))
|
||||
initLoc(newSeq, locExpr, t.typ, OnHeap)
|
||||
newSeq.r = ropef("($1) newSeq($2, $3)", [getTypeDesc(p.module, t.typ),
|
||||
newSeq.r = ropecg(p.module, "($1) #newSeq($2, $3)",
|
||||
[getTypeDesc(p.module, t.typ),
|
||||
genTypeInfo(p.module, t.typ), intLiteral(L)])
|
||||
genAssignment(p, d, newSeq, {afSrcIsNotNil})
|
||||
initLocExpr(p, t.sons[1], a)
|
||||
@@ -1427,11 +1377,9 @@ proc binaryFloatArith(p: BProc, e: PNode, d: var TLoc, m: TMagic) =
|
||||
putIntoDest(p, d, e.typ, ropef("($2 $1 $3)", [
|
||||
toRope(opr[m]), rdLoc(a), rdLoc(b)]))
|
||||
if optNanCheck in p.options:
|
||||
useMagic(p.module, "nanCheck")
|
||||
appf(p.s[cpsStmts], "nanCheck($1);$n", [rdLoc(d)])
|
||||
appcg(p, cpsStmts, "#nanCheck($1);$n", [rdLoc(d)])
|
||||
if optInfCheck in p.options:
|
||||
useMagic(p.module, "infCheck")
|
||||
appf(p.s[cpsStmts], "infCheck($1);$n", [rdLoc(d)])
|
||||
appcg(p, cpsStmts, "#infCheck($1);$n", [rdLoc(d)])
|
||||
else:
|
||||
binaryArith(p, e, d, m)
|
||||
|
||||
@@ -1448,49 +1396,48 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
|
||||
of mSwap: genSwap(p, e, d)
|
||||
of mPred:
|
||||
# XXX: range checking?
|
||||
if not (optOverflowCheck in p.Options): binaryExpr(p, e, d, "", "$1 - $2")
|
||||
else: binaryExpr(p, e, d, "subInt", "subInt($1, $2)")
|
||||
if not (optOverflowCheck in p.Options): binaryExpr(p, e, d, "$1 - $2")
|
||||
else: binaryExpr(p, e, d, "#subInt($1, $2)")
|
||||
of mSucc:
|
||||
# XXX: range checking?
|
||||
if not (optOverflowCheck in p.Options): binaryExpr(p, e, d, "", "$1 + $2")
|
||||
else: binaryExpr(p, e, d, "addInt", "addInt($1, $2)")
|
||||
if not (optOverflowCheck in p.Options): binaryExpr(p, e, d, "$1 + $2")
|
||||
else: binaryExpr(p, e, d, "#addInt($1, $2)")
|
||||
of mInc:
|
||||
if not (optOverflowCheck in p.Options):
|
||||
binaryStmt(p, e, d, "", "$1 += $2;$n")
|
||||
binaryStmt(p, e, d, "$1 += $2;$n")
|
||||
elif skipTypes(e.sons[1].typ, abstractVar).kind == tyInt64:
|
||||
binaryStmt(p, e, d, "addInt64", "$1 = addInt64($1, $2);$n")
|
||||
binaryStmt(p, e, d, "$1 = #addInt64($1, $2);$n")
|
||||
else:
|
||||
binaryStmt(p, e, d, "addInt", "$1 = addInt($1, $2);$n")
|
||||
binaryStmt(p, e, d, "$1 = #addInt($1, $2);$n")
|
||||
of ast.mDec:
|
||||
if not (optOverflowCheck in p.Options):
|
||||
binaryStmt(p, e, d, "", "$1 -= $2;$n")
|
||||
binaryStmt(p, e, d, "$1 -= $2;$n")
|
||||
elif skipTypes(e.sons[1].typ, abstractVar).kind == tyInt64:
|
||||
binaryStmt(p, e, d, "subInt64", "$1 = subInt64($1, $2);$n")
|
||||
binaryStmt(p, e, d, "$1 = #subInt64($1, $2);$n")
|
||||
else:
|
||||
binaryStmt(p, e, d, "subInt", "$1 = subInt($1, $2);$n")
|
||||
binaryStmt(p, e, d, "$1 = #subInt($1, $2);$n")
|
||||
of mConStrStr: genStrConcat(p, e, d)
|
||||
of mAppendStrCh: binaryStmt(p, e, d, "addChar", "$1 = addChar($1, $2);$n")
|
||||
of mAppendStrCh: binaryStmt(p, e, d, "$1 = #addChar($1, $2);$n")
|
||||
of mAppendStrStr: genStrAppend(p, e, d)
|
||||
of mAppendSeqElem: genSeqElemAppend(p, e, d)
|
||||
of mEqStr: genStrEquals(p, e, d)
|
||||
of mLeStr: binaryExpr(p, e, d, "cmpStrings", "(cmpStrings($1, $2) <= 0)")
|
||||
of mLtStr: binaryExpr(p, e, d, "cmpStrings", "(cmpStrings($1, $2) < 0)")
|
||||
of mIsNil: unaryExpr(p, e, d, "", "$1 == 0")
|
||||
of mIntToStr: genDollar(p, e, d, "nimIntToStr", "nimIntToStr($1)")
|
||||
of mInt64ToStr: genDollar(p, e, d, "nimInt64ToStr", "nimInt64ToStr($1)")
|
||||
of mBoolToStr: genDollar(p, e, d, "nimBoolToStr", "nimBoolToStr($1)")
|
||||
of mCharToStr: genDollar(p, e, d, "nimCharToStr", "nimCharToStr($1)")
|
||||
of mFloatToStr: genDollar(p, e, d, "nimFloatToStr", "nimFloatToStr($1)")
|
||||
of mCStrToStr: genDollar(p, e, d, "cstrToNimstr", "cstrToNimstr($1)")
|
||||
of mLeStr: binaryExpr(p, e, d, "(#cmpStrings($1, $2) <= 0)")
|
||||
of mLtStr: binaryExpr(p, e, d, "(#cmpStrings($1, $2) < 0)")
|
||||
of mIsNil: unaryExpr(p, e, d, "$1 == 0")
|
||||
of mIntToStr: genDollar(p, e, d, "#nimIntToStr($1)")
|
||||
of mInt64ToStr: genDollar(p, e, d, "#nimInt64ToStr($1)")
|
||||
of mBoolToStr: genDollar(p, e, d, "#nimBoolToStr($1)")
|
||||
of mCharToStr: genDollar(p, e, d, "#nimCharToStr($1)")
|
||||
of mFloatToStr: genDollar(p, e, d, "#nimFloatToStr($1)")
|
||||
of mCStrToStr: genDollar(p, e, d, "#cstrToNimstr($1)")
|
||||
of mStrToStr: expr(p, e.sons[1], d)
|
||||
of mEnumToStr: genRepr(p, e, d)
|
||||
of mAssert:
|
||||
if (optAssert in p.Options):
|
||||
useMagic(p.module, "internalAssert")
|
||||
expr(p, e.sons[1], d)
|
||||
line = toRope(toLinenumber(e.info))
|
||||
filen = makeCString(ToFilename(e.info))
|
||||
appf(p.s[cpsStmts], "internalAssert($1, $2, $3);$n",
|
||||
appcg(p, cpsStmts, "#internalAssert($1, $2, $3);$n",
|
||||
[filen, line, rdLoc(d)])
|
||||
of mIs: genIs(p, e, d)
|
||||
of mNew: genNew(p, e)
|
||||
@@ -1503,8 +1450,8 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
|
||||
of mOrd: genOrd(p, e, d)
|
||||
of mLengthArray, mHigh, mLengthStr, mLengthSeq, mLengthOpenArray:
|
||||
genArrayLen(p, e, d, op)
|
||||
of mGCref: unaryStmt(p, e, d, "nimGCref", "nimGCref($1);$n")
|
||||
of mGCunref: unaryStmt(p, e, d, "nimGCunref", "nimGCunref($1);$n")
|
||||
of mGCref: unaryStmt(p, e, d, "#nimGCref($1);$n")
|
||||
of mGCunref: unaryStmt(p, e, d, "#nimGCunref($1);$n")
|
||||
of mSetLengthStr: genSetLengthStr(p, e, d)
|
||||
of mSetLengthSeq: genSetLengthSeq(p, e, d)
|
||||
of mIncl, mExcl, mCard, mLtSet, mLeSet, mEqSet, mMulSet, mPlusSet, mMinusSet,
|
||||
@@ -1632,7 +1579,6 @@ proc upConv(p: BProc, n: PNode, d: var TLoc) =
|
||||
initLocExpr(p, n.sons[0], a)
|
||||
dest = skipTypes(n.typ, abstractPtrs)
|
||||
if (optObjCheck in p.options) and not (isPureObject(dest)):
|
||||
useMagic(p.module, "chckObj")
|
||||
r = rdLoc(a)
|
||||
nilCheck = nil
|
||||
t = skipTypes(a.t, abstractInst)
|
||||
@@ -1645,10 +1591,10 @@ proc upConv(p: BProc, n: PNode, d: var TLoc) =
|
||||
app(r, ".Sup")
|
||||
t = skipTypes(t.sons[0], abstractInst)
|
||||
if nilCheck != nil:
|
||||
appf(p.s[cpsStmts], "if ($1) chckObj($2.m_type, $3);$n",
|
||||
appcg(p, cpsStmts, "if ($1) #chckObj($2.m_type, $3);$n",
|
||||
[nilCheck, r, genTypeInfo(p.module, dest)])
|
||||
else:
|
||||
appf(p.s[cpsStmts], "chckObj($1.m_type, $2);$n",
|
||||
appcg(p, cpsStmts, "#chckObj($1.m_type, $2);$n",
|
||||
[r, genTypeInfo(p.module, dest)])
|
||||
if n.sons[0].typ.kind != tyObject:
|
||||
putIntoDest(p, d, n.typ,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#
|
||||
#
|
||||
# The Nimrod Compiler
|
||||
# (c) Copyright 2009 Andreas Rumpf
|
||||
# (c) Copyright 2010 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
@@ -20,9 +20,7 @@ proc genLineDir(p: BProc, t: PNode) =
|
||||
[toRope(toFilename(t.info)), toRope(line)])
|
||||
if ({optStackTrace, optEndb} * p.Options == {optStackTrace, optEndb}) and
|
||||
((p.prc == nil) or not (sfPure in p.prc.flags)):
|
||||
useMagic(p.module, "endb") # new: endb support
|
||||
appff(p.s[cpsStmts], "endb($1);$n", "call void @endb(%NI $1)$n",
|
||||
[toRope(line)])
|
||||
appcg(p, cpsStmts, "#endb($1);$n", [toRope(line)])
|
||||
elif ({optLineTrace, optStackTrace} * p.Options ==
|
||||
{optLineTrace, optStackTrace}) and
|
||||
((p.prc == nil) or not (sfPure in p.prc.flags)):
|
||||
@@ -262,27 +260,24 @@ proc genAsmStmt(p: BProc, t: PNode) =
|
||||
|
||||
proc getRaiseFrmt(p: BProc): string =
|
||||
if gCmd == cmdCompileToCpp:
|
||||
result = "throw nimException($1, $2);$n"
|
||||
result = "throw #nimException($1, $2);$n"
|
||||
else:
|
||||
useMagic(p.module, "E_Base")
|
||||
result = "raiseException((E_Base*)$1, $2);$n"
|
||||
result = "#raiseException((#E_Base*)$1, $2);$n"
|
||||
|
||||
proc genRaiseStmt(p: BProc, t: PNode) =
|
||||
genLineDir(p, t)
|
||||
if t.sons[0] != nil:
|
||||
if gCmd != cmdCompileToCpp: useMagic(p.module, "raiseException")
|
||||
var a: TLoc
|
||||
InitLocExpr(p, t.sons[0], a)
|
||||
var e = rdLoc(a)
|
||||
var typ = skipTypes(t.sons[0].typ, abstractPtrs)
|
||||
appf(p.s[cpsStmts], getRaiseFrmt(p), [e, makeCString(typ.sym.name.s)])
|
||||
appcg(p, cpsStmts, getRaiseFrmt(p), [e, makeCString(typ.sym.name.s)])
|
||||
else:
|
||||
# reraise the last exception:
|
||||
if gCmd == cmdCompileToCpp:
|
||||
app(p.s[cpsStmts], "throw;" & tnl)
|
||||
appcg(p, cpsStmts, "throw;" & tnl)
|
||||
else:
|
||||
useMagic(p.module, "reraiseException")
|
||||
app(p.s[cpsStmts], "reraiseException();" & tnl)
|
||||
appcg(p, cpsStmts, "#reraiseException();" & tnl)
|
||||
|
||||
const
|
||||
stringCaseThreshold = 100000
|
||||
@@ -300,11 +295,11 @@ proc genCaseGenericBranch(p: BProc, b: PNode, e: TLoc,
|
||||
if b.sons[i].kind == nkRange:
|
||||
initLocExpr(p, b.sons[i].sons[0], x)
|
||||
initLocExpr(p, b.sons[i].sons[1], y)
|
||||
appf(p.s[cpsStmts], rangeFormat,
|
||||
appcg(p, cpsStmts, rangeFormat,
|
||||
[rdCharLoc(e), rdCharLoc(x), rdCharLoc(y), labl])
|
||||
else:
|
||||
initLocExpr(p, b.sons[i], x)
|
||||
appf(p.s[cpsStmts], eqFormat, [rdCharLoc(e), rdCharLoc(x), labl])
|
||||
appcg(p, cpsStmts, eqFormat, [rdCharLoc(e), rdCharLoc(x), labl])
|
||||
|
||||
proc genCaseSecondPass(p: BProc, t: PNode, labId: int) =
|
||||
var Lend = getLabel(p)
|
||||
@@ -373,7 +368,7 @@ proc genCaseStringBranch(p: BProc, b: PNode, e: TLoc, labl: TLabel,
|
||||
initLocExpr(p, b.sons[i], x)
|
||||
assert(b.sons[i].kind in {nkStrLit..nkTripleStrLit})
|
||||
j = int(hashString(b.sons[i].strVal) and high(branches))
|
||||
appf(branches[j], "if (eqStrings($1, $2)) goto $3;$n",
|
||||
appcg(p.module, branches[j], "if (#eqStrings($1, $2)) goto $3;$n",
|
||||
[rdLoc(e), rdLoc(x), labl])
|
||||
|
||||
proc genStringCase(p: BProc, t: PNode) =
|
||||
@@ -381,13 +376,11 @@ proc genStringCase(p: BProc, t: PNode) =
|
||||
strings, bitMask, labId: int
|
||||
a: TLoc
|
||||
branches: TRopeSeq
|
||||
useMagic(p.module, "eqStrings")
|
||||
# count how many constant strings there are in the case:
|
||||
strings = 0
|
||||
for i in countup(1, sonsLen(t) - 1):
|
||||
if t.sons[i].kind == nkOfBranch: inc(strings, sonsLen(t.sons[i]) - 1)
|
||||
if strings > stringCaseThreshold:
|
||||
useMagic(p.module, "hashString")
|
||||
bitMask = math.nextPowerOfTwo(strings) - 1
|
||||
newSeq(branches, bitMask + 1)
|
||||
initLocExpr(p, t.sons[0], a) # fist pass: gnerate ifs+goto:
|
||||
@@ -400,7 +393,7 @@ proc genStringCase(p: BProc, t: PNode) =
|
||||
else:
|
||||
# else statement: nothing to do yet
|
||||
# but we reserved a label, which we use later
|
||||
appf(p.s[cpsStmts], "switch (hashString($1) & $2) {$n",
|
||||
appcg(p, cpsStmts, "switch (#hashString($1) & $2) {$n",
|
||||
[rdLoc(a), toRope(bitMask)])
|
||||
for j in countup(0, high(branches)):
|
||||
if branches[j] != nil:
|
||||
@@ -412,7 +405,7 @@ proc genStringCase(p: BProc, t: PNode) =
|
||||
# third pass: generate statements
|
||||
genCaseSecondPass(p, t, labId)
|
||||
else:
|
||||
genCaseGeneric(p, t, "", "if (eqStrings($1, $2)) goto $3;$n")
|
||||
genCaseGeneric(p, t, "", "if (#eqStrings($1, $2)) goto $3;$n")
|
||||
|
||||
proc branchHasTooBigRange(b: PNode): bool =
|
||||
for i in countup(0, sonsLen(b) - 2):
|
||||
@@ -588,11 +581,9 @@ proc genTryStmt(p: BProc, t: PNode) =
|
||||
# longjmp(excHandler->context, sp.status);
|
||||
genLineDir(p, t)
|
||||
var safePoint = getTempName()
|
||||
useMagic(p.module, "TSafePoint")
|
||||
useMagic(p.module, "E_Base")
|
||||
useMagic(p.module, "excHandler")
|
||||
appf(p.s[cpsLocals], "TSafePoint $1;$n", [safePoint])
|
||||
appf(p.s[cpsStmts], "$1.prev = excHandler;$n" & "excHandler = &$1;$n" &
|
||||
discard cgsym(p.module, "E_Base")
|
||||
appcg(p, cpsLocals, "#TSafePoint $1;$n", [safePoint])
|
||||
appcg(p, cpsStmts, "$1.prev = #excHandler;$n" & "excHandler = &$1;$n" &
|
||||
"$1.status = setjmp($1.context);$n", [safePoint])
|
||||
if optStackTrace in p.Options:
|
||||
app(p.s[cpsStmts], "framePtr = (TFrame*)&F;" & tnl)
|
||||
@@ -627,9 +618,8 @@ proc genTryStmt(p: BProc, t: PNode) =
|
||||
dec(p.nestedTryStmts)
|
||||
if (i < length) and (t.sons[i].kind == nkFinally):
|
||||
genStmts(p, t.sons[i].sons[0])
|
||||
useMagic(p.module, "raiseException")
|
||||
appf(p.s[cpsStmts], "if ($1.status != 0) { " &
|
||||
"raiseException($1.exc, $1.exc->name); }$n", [safePoint])
|
||||
appcg(p, cpsStmts, "if ($1.status != 0) { " &
|
||||
"#raiseException($1.exc, $1.exc->name); }$n", [safePoint])
|
||||
|
||||
var
|
||||
breakPointId: int = 0
|
||||
@@ -643,21 +633,17 @@ proc genBreakPoint(p: BProc, t: PNode) =
|
||||
name = normalize(t.sons[1].strVal)
|
||||
else:
|
||||
inc(breakPointId)
|
||||
name = "bp" & $(breakPointId)
|
||||
name = "bp" & $breakPointId
|
||||
genLineDir(p, t) # BUGFIX
|
||||
appf(gBreakpoints,
|
||||
"dbgRegisterBreakpoint($1, (NCSTRING)$2, (NCSTRING)$3);$n", [
|
||||
appcg(p.module, gBreakpoints,
|
||||
"#dbgRegisterBreakpoint($1, (NCSTRING)$2, (NCSTRING)$3);$n", [
|
||||
toRope(toLinenumber(t.info)), makeCString(toFilename(t.info)),
|
||||
makeCString(name)])
|
||||
|
||||
proc genPragma(p: BProc, n: PNode) =
|
||||
for i in countup(0, sonsLen(n) - 1):
|
||||
var it = n.sons[i]
|
||||
var key: PNode
|
||||
if it.kind == nkExprColonExpr:
|
||||
key = it.sons[0]
|
||||
else:
|
||||
key = it
|
||||
var key = if it.kind == nkExprColonExpr: it.sons[0] else: it
|
||||
if key.kind == nkIdent:
|
||||
case whichKeyword(key.ident)
|
||||
of wBreakpoint:
|
||||
@@ -667,8 +653,7 @@ proc genPragma(p: BProc, n: PNode) =
|
||||
# we need to keep track of ``deadCodeElim`` pragma
|
||||
if (sfDeadCodeElim in p.module.module.flags):
|
||||
addPendingModule(p.module)
|
||||
else:
|
||||
nil
|
||||
else: nil
|
||||
|
||||
proc genAsgn(p: BProc, e: PNode) =
|
||||
var a: TLoc
|
||||
|
||||
@@ -248,7 +248,7 @@ proc getSimpleTypeDesc(m: BModule, typ: PType): PRope =
|
||||
internalError(typ.sym.info, "getSimpleTypeDesc: " & $(getSize(typ)))
|
||||
result = nil
|
||||
of tyString:
|
||||
useMagic(m, "NimStringDesc")
|
||||
discard cgsym(m, "NimStringDesc")
|
||||
result = typeNameOrLiteral(typ, "NimStringDesc*")
|
||||
of tyCstring: result = typeNameOrLiteral(typ, "NCSTRING")
|
||||
of tyBool: result = typeNameOrLiteral(typ, "NIM_BOOL")
|
||||
@@ -342,20 +342,19 @@ proc getRecordDesc(m: BModule, typ: PType, name: PRope,
|
||||
# declare the record:
|
||||
var hasField = false
|
||||
if typ.kind == tyObject:
|
||||
useMagic(m, "TNimType")
|
||||
if typ.sons[0] == nil:
|
||||
if typ.sym != nil and sfPure in typ.sym.flags or tfFinal in typ.flags:
|
||||
result = ropef("struct $1 {$n", [name])
|
||||
result = ropecg(m, "struct $1 {$n", [name])
|
||||
else:
|
||||
result = ropef("struct $1 {$nTNimType* m_type;$n", [name])
|
||||
result = ropecg(m, "struct $1 {$n#TNimType* m_type;$n", [name])
|
||||
hasField = true
|
||||
elif gCmd == cmdCompileToCpp:
|
||||
result = ropef("struct $1 : public $2 {$n",
|
||||
[name, getTypeDescAux(m, typ.sons[0], check)])
|
||||
result = ropecg(m, "struct $1 : public $2 {$n",
|
||||
[name, getTypeDescAux(m, typ.sons[0], check)])
|
||||
hasField = true
|
||||
else:
|
||||
result = ropef("struct $1 {$n $2 Sup;$n",
|
||||
[name, getTypeDescAux(m, typ.sons[0], check)])
|
||||
result = ropecg(m, "struct $1 {$n $2 Sup;$n",
|
||||
[name, getTypeDescAux(m, typ.sons[0], check)])
|
||||
hasField = true
|
||||
else:
|
||||
result = ropef("struct $1 {$n", [name])
|
||||
@@ -446,11 +445,12 @@ proc getTypeDescAux(m: BModule, typ: PType, check: var TIntSet): PRope =
|
||||
assert(CacheGetType(m.typeCache, t) == nil)
|
||||
IdTablePut(m.typeCache, t, con(result, "*"))
|
||||
if not isImportedType(t):
|
||||
useMagic(m, "TGenericSeq")
|
||||
if skipTypes(t.sons[0], abstractInst).kind != tyEmpty:
|
||||
appf(m.s[cfsSeqTypes], "struct $2 {$n" & " TGenericSeq Sup;$n" &
|
||||
" $1 data[SEQ_DECL_SIZE];$n" & "};$n",
|
||||
[getTypeDescAux(m, t.sons[0], check), result])
|
||||
appcg(m, m.s[cfsSeqTypes],
|
||||
"struct $2 {$n" &
|
||||
" #TGenericSeq Sup;$n" &
|
||||
" $1 data[SEQ_DECL_SIZE];$n" &
|
||||
"};$n", [getTypeDescAux(m, t.sons[0], check), result])
|
||||
else:
|
||||
result = toRope("TGenericSeq")
|
||||
app(result, "*")
|
||||
@@ -595,10 +595,9 @@ proc genObjectFields(m: BModule, typ: PType, n: PNode, expr: PRope) =
|
||||
assert(n.sons[0].kind == nkSym)
|
||||
field = n.sons[0].sym
|
||||
tmp = getTempName()
|
||||
useMagic(m, "chckNil")
|
||||
appf(m.s[cfsTypeInit3], "$1.kind = 3;$n" &
|
||||
"$1.offset = offsetof($2, $3);$n" & "$1.typ = $4;$n" &
|
||||
"chckNil($1.typ);$n" & "$1.name = $5;$n" & "$1.sons = &$6[0];$n" &
|
||||
"$1.name = $5;$n" & "$1.sons = &$6[0];$n" &
|
||||
"$1.len = $7;$n", [expr, getTypeDesc(m, typ), field.loc.r,
|
||||
genTypeInfo(m, field.typ), makeCString(field.name.s),
|
||||
tmp, toRope(lengthOrd(field.typ))])
|
||||
@@ -628,10 +627,9 @@ proc genObjectFields(m: BModule, typ: PType, n: PNode, expr: PRope) =
|
||||
else: internalError(n.info, "genObjectFields(nkRecCase)")
|
||||
of nkSym:
|
||||
field = n.sym
|
||||
useMagic(m, "chckNil")
|
||||
appf(m.s[cfsTypeInit3], "$1.kind = 1;$n" &
|
||||
"$1.offset = offsetof($2, $3);$n" & "$1.typ = $4;$n" &
|
||||
"chckNil($1.typ);$n" & "$1.name = $5;$n", [expr, getTypeDesc(m, typ),
|
||||
"$1.name = $5;$n", [expr, getTypeDesc(m, typ),
|
||||
field.loc.r, genTypeInfo(m, field.typ), makeCString(field.name.s)])
|
||||
else: internalError(n.info, "genObjectFields")
|
||||
|
||||
@@ -658,10 +656,9 @@ proc genTupleInfo(m: BModule, typ: PType, name: PRope) =
|
||||
a = typ.sons[i]
|
||||
tmp2 = getNimNode(m)
|
||||
appf(m.s[cfsTypeInit3], "$1[$2] = &$3;$n", [tmp, toRope(i), tmp2])
|
||||
useMagic(m, "chckNil")
|
||||
appf(m.s[cfsTypeInit3], "$1.kind = 1;$n" &
|
||||
"$1.offset = offsetof($2, Field$3);$n" & "$1.typ = $4;$n" &
|
||||
"chckNil($1.typ);$n" & "$1.name = \"Field$3\";$n",
|
||||
"$1.name = \"Field$3\";$n",
|
||||
[tmp2, getTypeDesc(m, typ), toRope(i), genTypeInfo(m, a)])
|
||||
appf(m.s[cfsTypeInit3], "$1.len = $2; $1.kind = 2; $1.sons = &$3[0];$n",
|
||||
[expr, toRope(length), tmp])
|
||||
@@ -735,8 +732,8 @@ proc genTypeInfo(m: BModule, typ: PType): PRope =
|
||||
result = ropef("NTI$1", [toRope(id)])
|
||||
if not IntSetContainsOrIncl(m.typeInfoMarker, id):
|
||||
# declare type information structures:
|
||||
useMagic(m, "TNimType")
|
||||
useMagic(m, "TNimNode")
|
||||
discard cgsym(m, "TNimType")
|
||||
discard cgsym(m, "TNimNode")
|
||||
appf(m.s[cfsVars], "extern TNimType* $1; /* $2 */$n",
|
||||
[result, toRope(typeToString(t))])
|
||||
if dataGenerated: return
|
||||
|
||||
169
rod/cgen.nim
169
rod/cgen.nim
@@ -169,7 +169,68 @@ proc useHeader(m: BModule, sym: PSym) =
|
||||
assert(sym.annex != nil)
|
||||
discard lists.IncludeStr(m.headerFiles, getStr(sym.annex.path))
|
||||
|
||||
proc UseMagic(m: BModule, name: string)
|
||||
proc cgsym(m: BModule, name: string): PRope
|
||||
|
||||
proc ropecg(m: BModule, frmt: TFormatStr, args: openarray[PRope]): PRope =
|
||||
var i, j, length, start, num: int
|
||||
i = 0
|
||||
length = len(frmt)
|
||||
result = nil
|
||||
num = 0
|
||||
while i < length:
|
||||
if frmt[i] == '$':
|
||||
inc(i) # skip '$'
|
||||
case frmt[i]
|
||||
of '$':
|
||||
app(result, "$")
|
||||
inc(i)
|
||||
of '#':
|
||||
inc(i)
|
||||
app(result, args[num])
|
||||
inc(num)
|
||||
of '0'..'9':
|
||||
j = 0
|
||||
while true:
|
||||
j = (j * 10) + Ord(frmt[i]) - ord('0')
|
||||
inc(i)
|
||||
if (i > length + 0 - 1) or not (frmt[i] in {'0'..'9'}): break
|
||||
num = j
|
||||
if j > high(args) + 1:
|
||||
internalError("ropes: invalid format string $" & $(j))
|
||||
app(result, args[j - 1])
|
||||
of 'N', 'n':
|
||||
app(result, tnl)
|
||||
inc(i)
|
||||
else: InternalError("ropes: invalid format string $" & frmt[i])
|
||||
elif frmt[i] == '#' and frmt[i+1] in IdentStartChars:
|
||||
inc(i)
|
||||
var j = i
|
||||
while frmt[j] in IdentChars: inc(j)
|
||||
var ident = copy(frmt, i, j-1)
|
||||
i = j
|
||||
app(result, cgsym(m, ident))
|
||||
elif frmt[i] == '#' and frmt[i+1] == '$':
|
||||
inc(i, 2)
|
||||
var j = 0
|
||||
while frmt[i] in Digits:
|
||||
j = (j * 10) + Ord(frmt[i]) - ord('0')
|
||||
inc(i)
|
||||
app(result, cgsym(m, args[j-1].ropeToStr))
|
||||
start = i
|
||||
while i < length:
|
||||
if frmt[i] != '$' and frmt[i] != '#': inc(i)
|
||||
else: break
|
||||
if i - 1 >= start:
|
||||
app(result, copy(frmt, start, i - 1))
|
||||
|
||||
proc appcg(m: BModule, c: var PRope, frmt: TFormatStr, args: openarray[PRope]) =
|
||||
app(c, ropecg(m, frmt, args))
|
||||
|
||||
|
||||
proc appcg(p: BProc, s: TCProcSection, frmt: TFormatStr,
|
||||
args: openarray[PRope]) =
|
||||
app(p.s[s], ropecg(p.module, frmt, args))
|
||||
|
||||
|
||||
include "ccgtypes.nim"
|
||||
|
||||
@@ -274,26 +335,21 @@ proc assignLocalVar(p: BProc, s: PSym) =
|
||||
proc assignGlobalVar(p: BProc, s: PSym) =
|
||||
if s.loc.k == locNone:
|
||||
fillLoc(s.loc, locGlobalVar, s.typ, mangleName(s), OnHeap)
|
||||
if gCmd == cmdCompileToLLVM:
|
||||
appf(p.module.s[cfsVars], "$1 = linkonce global $2 zeroinitializer$n",
|
||||
[s.loc.r, getTypeDesc(p.module, s.loc.t)])
|
||||
incl(s.loc.flags, lfIndirect)
|
||||
else:
|
||||
useHeader(p.module, s)
|
||||
if lfNoDecl in s.loc.flags: return
|
||||
if sfImportc in s.flags: app(p.module.s[cfsVars], "extern ")
|
||||
app(p.module.s[cfsVars], getTypeDesc(p.module, s.loc.t))
|
||||
if sfRegister in s.flags: app(p.module.s[cfsVars], " register")
|
||||
if sfVolatile in s.flags: app(p.module.s[cfsVars], " volatile")
|
||||
if sfThreadVar in s.flags: app(p.module.s[cfsVars], " NIM_THREADVAR")
|
||||
appf(p.module.s[cfsVars], " $1;$n", [s.loc.r])
|
||||
useHeader(p.module, s)
|
||||
if lfNoDecl in s.loc.flags: return
|
||||
if sfImportc in s.flags: app(p.module.s[cfsVars], "extern ")
|
||||
app(p.module.s[cfsVars], getTypeDesc(p.module, s.loc.t))
|
||||
if sfRegister in s.flags: app(p.module.s[cfsVars], " register")
|
||||
if sfVolatile in s.flags: app(p.module.s[cfsVars], " volatile")
|
||||
if sfThreadVar in s.flags: app(p.module.s[cfsVars], " NIM_THREADVAR")
|
||||
appf(p.module.s[cfsVars], " $1;$n", [s.loc.r])
|
||||
if {optStackTrace, optEndb} * p.module.module.options ==
|
||||
{optStackTrace, optEndb}:
|
||||
useMagic(p.module, "dbgRegisterGlobal")
|
||||
appff(p.module.s[cfsDebugInit], "dbgRegisterGlobal($1, &$2, $3);$n",
|
||||
"call void @dbgRegisterGlobal(i8* $1, i8* $2, $4* $3)$n", [cstringLit(
|
||||
p, p.module.s[cfsDebugInit], normalize(s.owner.name.s & '.' & s.name.s)),
|
||||
s.loc.r, genTypeInfo(p.module, s.typ), getTypeDesc(p.module, "TNimType")])
|
||||
appcg(p.module, p.module.s[cfsDebugInit],
|
||||
"#dbgRegisterGlobal($1, &$2, $3);$n",
|
||||
[cstringLit(p, p.module.s[cfsDebugInit],
|
||||
normalize(s.owner.name.s & '.' & s.name.s)),
|
||||
s.loc.r, genTypeInfo(p.module, s.typ)])
|
||||
|
||||
proc iff(cond: bool, the, els: PRope): PRope =
|
||||
if cond: result = the
|
||||
@@ -352,11 +408,11 @@ proc loadDynamicLib(m: BModule, lib: PLib) =
|
||||
for i in countup(0, high(s)):
|
||||
inc(m.labels)
|
||||
if i > 0: app(loadlib, "||")
|
||||
appf(loadlib, "($1 = nimLoadLibrary((NimStringDesc*) &$2))$n",
|
||||
[tmp, getStrLit(m, s[i])])
|
||||
appf(m.s[cfsDynLibInit],
|
||||
"if (!($1)) nimLoadLibraryError((NimStringDesc*) &$2);$n",
|
||||
[loadlib, getStrLit(m, lib.path.strVal)])
|
||||
appcg(m, loadlib, "($1 = #nimLoadLibrary((#NimStringDesc*) &$2))$n",
|
||||
[tmp, getStrLit(m, s[i])])
|
||||
appcg(m, m.s[cfsDynLibInit],
|
||||
"if (!($1)) #nimLoadLibraryError((#NimStringDesc*) &$2);$n",
|
||||
[loadlib, getStrLit(m, lib.path.strVal)])
|
||||
else:
|
||||
var p = newProc(nil, m)
|
||||
var dest: TLoc
|
||||
@@ -364,37 +420,38 @@ proc loadDynamicLib(m: BModule, lib: PLib) =
|
||||
app(m.s[cfsVars], p.s[cpsLocals])
|
||||
app(m.s[cfsDynLibInit], p.s[cpsInit])
|
||||
app(m.s[cfsDynLibInit], p.s[cpsStmts])
|
||||
appf(m.s[cfsDynLibInit],
|
||||
"if (!($1 = nimLoadLibrary($2))) nimLoadLibraryError($2);$n",
|
||||
appcg(m, m.s[cfsDynLibInit],
|
||||
"if (!($1 = #nimLoadLibrary($2))) #nimLoadLibraryError($2);$n",
|
||||
[tmp, rdLoc(dest)])
|
||||
|
||||
useMagic(m, "nimLoadLibrary")
|
||||
useMagic(m, "nimUnloadLibrary")
|
||||
useMagic(m, "NimStringDesc")
|
||||
useMagic(m, "nimLoadLibraryError")
|
||||
if lib.name == nil: InternalError("loadDynamicLib")
|
||||
|
||||
proc mangleDynLibProc(sym: PSym): PRope =
|
||||
if sfCompilerProc in sym.flags:
|
||||
# NOTE: sym.loc.r is the external name!
|
||||
result = toRope(sym.name.s)
|
||||
else:
|
||||
result = ropef("Dl_$1", [toRope(sym.id)])
|
||||
|
||||
proc SymInDynamicLib(m: BModule, sym: PSym) =
|
||||
var lib = sym.annex
|
||||
var extname = sym.loc.r
|
||||
loadDynamicLib(m, lib)
|
||||
useMagic(m, "nimGetProcAddr")
|
||||
discard cgsym(m, "nimGetProcAddr")
|
||||
if gCmd == cmdCompileToLLVM: incl(sym.loc.flags, lfIndirect)
|
||||
var tmp = ropeff("Dl_$1", "@Dl_$1", [toRope(sym.id)])
|
||||
var tmp = mangleDynLibProc(sym)
|
||||
sym.loc.r = tmp # from now on we only need the internal name
|
||||
sym.typ.sym = nil # generate a new name
|
||||
inc(m.labels, 2)
|
||||
appff(m.s[cfsDynLibInit],
|
||||
"$1 = ($2) nimGetProcAddr($3, $4);$n", "%MOC$5 = load i8* $3$n" &
|
||||
"%MOC$6 = call $2 @nimGetProcAddr(i8* %MOC$5, i8* $4)$n" &
|
||||
"store $2 %MOC$6, $2* $1$n", [tmp, getTypeDesc(m, sym.typ),
|
||||
lib.name, cstringLit(m, m.s[cfsDynLibInit], ropeToStr(extname)),
|
||||
toRope(m.labels), toRope(m.labels - 1)])
|
||||
appf(m.s[cfsDynLibInit],
|
||||
"$1 = ($2) nimGetProcAddr($3, $4);$n",
|
||||
[tmp, getTypeDesc(m, sym.typ),
|
||||
lib.name, cstringLit(m, m.s[cfsDynLibInit], ropeToStr(extname))])
|
||||
appff(m.s[cfsVars], "$2 $1;$n",
|
||||
"$1 = linkonce global $2 zeroinitializer$n",
|
||||
[sym.loc.r, getTypeDesc(m, sym.loc.t)])
|
||||
|
||||
proc UseMagic(m: BModule, name: string) =
|
||||
proc cgsym(m: BModule, name: string): PRope =
|
||||
var sym = magicsys.getCompilerProc(name)
|
||||
if sym != nil:
|
||||
case sym.kind
|
||||
@@ -402,8 +459,16 @@ proc UseMagic(m: BModule, name: string) =
|
||||
of skVar: genVarPrototype(m, sym)
|
||||
of skType: discard getTypeDesc(m, sym.typ)
|
||||
else: InternalError("useMagic: " & name)
|
||||
elif not (sfSystemModule in m.module.flags):
|
||||
rawMessage(errSystemNeeds, name) # don't be too picky here
|
||||
else:
|
||||
# we used to exclude the system module from this check, but for DLL
|
||||
# generation support this sloppyness leads to hard to detect bugs, so
|
||||
# we're picky here for the system module too:
|
||||
when false:
|
||||
if not (sfSystemModule in m.module.flags):
|
||||
rawMessage(errSystemNeeds, name)
|
||||
else:
|
||||
rawMessage(errSystemNeeds, name)
|
||||
result = sym.loc.r
|
||||
|
||||
proc generateHeaders(m: BModule) =
|
||||
app(m.s[cfsHeaders], "#include \"nimbase.h\"" & tnl & tnl)
|
||||
@@ -418,7 +483,7 @@ proc generateHeaders(m: BModule) =
|
||||
proc getFrameDecl(p: BProc) =
|
||||
var slots: PRope
|
||||
if p.frameLen > 0:
|
||||
useMagic(p.module, "TVarSlot")
|
||||
discard cgsym(p.module, "TVarSlot")
|
||||
slots = ropeff(" TVarSlot s[$1];$n", ", [$1 x %TVarSlot]",
|
||||
[toRope(p.frameLen)])
|
||||
else:
|
||||
@@ -507,7 +572,7 @@ proc genProcAux(m: BModule, prc: PSym) =
|
||||
if (optProfiler in prc.options) and (gCmd != cmdCompileToLLVM):
|
||||
if gProcProfile >= 64 * 1024:
|
||||
InternalError(prc.info, "too many procedures for profiling")
|
||||
useMagic(m, "profileData")
|
||||
discard cgsym(m, "profileData")
|
||||
app(p.s[cpsLocals], "ticks NIM_profilingStart;" & tnl)
|
||||
if prc.loc.a < 0:
|
||||
appf(m.s[cfsDebugInit], "profileData[$1].procname = $2;$n", [
|
||||
@@ -534,9 +599,9 @@ proc genProcPrototype(m: BModule, sym: PSym) =
|
||||
if lfDynamicLib in sym.loc.Flags:
|
||||
if (sym.owner.id != m.module.id) and
|
||||
not intSetContainsOrIncl(m.declaredThings, sym.id):
|
||||
appff(m.s[cfsVars], "extern $1 Dl_$2;$n",
|
||||
"@Dl_$2 = linkonce global $1 zeroinitializer$n",
|
||||
[getTypeDesc(m, sym.loc.t), toRope(sym.id)])
|
||||
appff(m.s[cfsVars], "extern $1 $2;$n",
|
||||
"@$2 = linkonce global $1 zeroinitializer$n",
|
||||
[getTypeDesc(m, sym.loc.t), mangleDynLibProc(sym)])
|
||||
if gCmd == cmdCompileToLLVM: incl(sym.loc.flags, lfIndirect)
|
||||
else:
|
||||
if not IntSetContainsOrIncl(m.declaredProtos, sym.id):
|
||||
@@ -679,7 +744,7 @@ proc genMainProc(m: BModule) =
|
||||
" i8* %lpvReserved) {$n" &
|
||||
" call void @NimMain()$n" & " ret i32 1$n" & "}$n"
|
||||
var nimMain, otherMain: TFormatStr
|
||||
useMagic(m, "setStackBottom")
|
||||
discard cgsym(m, "setStackBottom")
|
||||
if (platform.targetOS == osWindows) and
|
||||
(gGlobalOptions * {optGenGuiApp, optGenDynLib} != {}):
|
||||
if optGenGuiApp in gGlobalOptions:
|
||||
@@ -704,7 +769,7 @@ proc genMainProc(m: BModule) =
|
||||
else:
|
||||
nimMain = PosixNimMain
|
||||
otherMain = PosixCMain
|
||||
if gBreakpoints != nil: useMagic(m, "dbgRegisterBreakpoint")
|
||||
if gBreakpoints != nil: discard cgsym(m, "dbgRegisterBreakpoint")
|
||||
inc(m.labels)
|
||||
appf(m.s[cfsProcs], nimMain, [gBreakpoints, mainModInit, toRope(m.labels)])
|
||||
if not (optNoMain in gGlobalOptions): appf(m.s[cfsProcs], otherMain, [])
|
||||
@@ -730,14 +795,10 @@ proc genInitCode(m: BModule) =
|
||||
prc = ropeff("N_NOINLINE(void, $1)(void) {$n",
|
||||
"define void $1() noinline {$n", [initname])
|
||||
if m.typeNodes > 0:
|
||||
useMagic(m, "TNimNode")
|
||||
appff(m.s[cfsTypeInit1], "static TNimNode $1[$2];$n",
|
||||
"$1 = private alloca [$2 x @TNimNode]$n",
|
||||
appcg(m, m.s[cfsTypeInit1], "static #TNimNode $1[$2];$n",
|
||||
[m.typeNodesName, toRope(m.typeNodes)])
|
||||
if m.nimTypes > 0:
|
||||
useMagic(m, "TNimType")
|
||||
appff(m.s[cfsTypeInit1], "static TNimType $1[$2];$n",
|
||||
"$1 = private alloca [$2 x @TNimType]$n",
|
||||
appcg(m, m.s[cfsTypeInit1], "static #TNimType $1[$2];$n",
|
||||
[m.nimTypesName, toRope(m.nimTypes)])
|
||||
if optStackTrace in m.initProc.options:
|
||||
getFrameDecl(m.initProc)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#
|
||||
#
|
||||
# The Nimrod Compiler
|
||||
# (c) Copyright 2009 Andreas Rumpf
|
||||
# (c) Copyright 2010 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
@@ -69,8 +69,7 @@ proc getSysType(kind: TTypeKind): PType =
|
||||
if result == nil: InternalError("type not found: " & $kind)
|
||||
|
||||
proc getCompilerProc(name: string): PSym =
|
||||
var ident: PIdent
|
||||
ident = getIdent(name, getNormalizedHash(name))
|
||||
var ident = getIdent(name, getNormalizedHash(name))
|
||||
result = StrTableGet(compilerprocs, ident)
|
||||
if result == nil:
|
||||
result = StrTableGet(rodCompilerProcs, ident)
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
[Project]
|
||||
Name: "Nimrod"
|
||||
Version: "$version"
|
||||
OS: "linux;macosx;freebsd;netbsd;openbsd;solaris"
|
||||
CPU: "i386;amd64" # ;sparc;powerpc
|
||||
; Windows and i386 must be first!
|
||||
OS: "windows" ;linux;macosx;freebsd;netbsd;openbsd;solaris"
|
||||
CPU: "i386" ;amd64" # ;sparc;powerpc
|
||||
Authors: "Andreas Rumpf"
|
||||
Description: """This is the Nimrod Compiler. Nimrod is a new statically typed,
|
||||
imperative programming language, that supports procedural, functional, object
|
||||
|
||||
@@ -21,13 +21,13 @@ const
|
||||
procPragmas* = {FirstCallConv..LastCallConv, wImportc, wExportc, wNodecl,
|
||||
wMagic, wNosideEffect, wSideEffect, wNoreturn, wDynLib, wHeader,
|
||||
wCompilerProc, wPure, wProcVar, wDeprecated, wVarargs, wCompileTime, wMerge,
|
||||
wBorrow}
|
||||
wBorrow, wExtern}
|
||||
converterPragmas* = procPragmas
|
||||
methodPragmas* = procPragmas
|
||||
macroPragmas* = {FirstCallConv..LastCallConv, wImportc, wExportc, wNodecl,
|
||||
wMagic, wNosideEffect, wCompilerProc, wDeprecated, wTypeCheck}
|
||||
wMagic, wNosideEffect, wCompilerProc, wDeprecated, wTypeCheck, wExtern}
|
||||
iteratorPragmas* = {FirstCallConv..LastCallConv, wNosideEffect, wSideEffect,
|
||||
wImportc, wExportc, wNodecl, wMagic, wDeprecated, wBorrow}
|
||||
wImportc, wExportc, wNodecl, wMagic, wDeprecated, wBorrow, wExtern}
|
||||
stmtPragmas* = {wChecks, wObjChecks, wFieldChecks, wRangechecks, wBoundchecks,
|
||||
wOverflowchecks, wNilchecks, wAssertions, wWarnings, wHints, wLinedir,
|
||||
wStacktrace, wLinetrace, wOptimization, wHint, wWarning, wError, wFatal,
|
||||
@@ -35,13 +35,15 @@ const
|
||||
wCheckpoint, wPassL, wPassC, wDeadCodeElim, wDeprecated, wFloatChecks,
|
||||
wInfChecks, wNanChecks, wPragma}
|
||||
lambdaPragmas* = {FirstCallConv..LastCallConv, wImportc, wExportc, wNodecl,
|
||||
wNosideEffect, wSideEffect, wNoreturn, wDynLib, wHeader, wPure, wDeprecated}
|
||||
wNosideEffect, wSideEffect, wNoreturn, wDynLib, wHeader, wPure,
|
||||
wDeprecated, wExtern}
|
||||
typePragmas* = {wImportc, wExportc, wDeprecated, wMagic, wAcyclic, wNodecl,
|
||||
wPure, wHeader, wCompilerProc, wFinal, wSize}
|
||||
fieldPragmas* = {wImportc, wExportc, wDeprecated}
|
||||
wPure, wHeader, wCompilerProc, wFinal, wSize, wExtern}
|
||||
fieldPragmas* = {wImportc, wExportc, wDeprecated, wExtern}
|
||||
varPragmas* = {wImportc, wExportc, wVolatile, wRegister, wThreadVar, wNodecl,
|
||||
wMagic, wHeader, wDeprecated, wCompilerProc, wDynLib}
|
||||
constPragmas* = {wImportc, wExportc, wHeader, wDeprecated, wMagic, wNodecl}
|
||||
wMagic, wHeader, wDeprecated, wCompilerProc, wDynLib, wExtern}
|
||||
constPragmas* = {wImportc, wExportc, wHeader, wDeprecated, wMagic, wNodecl,
|
||||
wExtern}
|
||||
procTypePragmas* = {FirstCallConv..LastCallConv, wVarargs, wNosideEffect}
|
||||
|
||||
proc pragma*(c: PContext, sym: PSym, n: PNode, validPragmas: TSpecialWords)
|
||||
@@ -64,18 +66,17 @@ proc pragmaAsm(c: PContext, n: PNode): char =
|
||||
else: invalidPragma(it)
|
||||
else:
|
||||
invalidPragma(it)
|
||||
|
||||
const
|
||||
FirstPragmaWord = wMagic
|
||||
LastPragmaWord = wNoconv
|
||||
|
||||
proc setExternName(s: PSym, extname: string) =
|
||||
s.loc.r = toRope(extname % s.name.s)
|
||||
|
||||
proc MakeExternImport(s: PSym, extname: string) =
|
||||
s.loc.r = toRope(extname)
|
||||
setExternName(s, extname)
|
||||
incl(s.flags, sfImportc)
|
||||
excl(s.flags, sfForward)
|
||||
|
||||
proc MakeExternExport(s: PSym, extname: string) =
|
||||
s.loc.r = toRope(extname)
|
||||
setExternName(s, extname)
|
||||
incl(s.flags, sfExportc)
|
||||
|
||||
proc getStrLitNode(c: PContext, n: PNode): PNode =
|
||||
@@ -356,6 +357,7 @@ proc pragma(c: PContext, sym: PSym, n: PNode, validPragmas: TSpecialWords) =
|
||||
makeExternExport(sym, getOptionalStr(c, it, sym.name.s))
|
||||
incl(sym.flags, sfUsed) # avoid wrong hints
|
||||
of wImportc: makeExternImport(sym, getOptionalStr(c, it, sym.name.s))
|
||||
of wExtern: setExternName(sym, expectStrLit(c, it))
|
||||
of wAlign:
|
||||
if sym.typ == nil: invalidPragma(it)
|
||||
sym.typ.align = expectIntLit(c, it)
|
||||
|
||||
@@ -688,7 +688,7 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
|
||||
else:
|
||||
if n.sons[pragmasPos] != nil:
|
||||
liMessage(n.sons[pragmasPos].info, errPragmaOnlyInHeaderOfProc)
|
||||
if not (sfForward in proto.flags):
|
||||
if sfForward notin proto.flags:
|
||||
liMessage(n.info, errAttemptToRedefineX, proto.name.s)
|
||||
excl(proto.flags, sfForward)
|
||||
closeScope(c.tab) # close scope with wrong parameter symbols
|
||||
@@ -715,7 +715,9 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
|
||||
c.p = newProcCon(s)
|
||||
if (s.typ.sons[0] != nil) and (kind != skIterator):
|
||||
addResult(c, s.typ.sons[0], n.info)
|
||||
n.sons[codePos] = semStmtScope(c, n.sons[codePos])
|
||||
if sfImportc notin s.flags:
|
||||
# no semantic checking for importc:
|
||||
n.sons[codePos] = semStmtScope(c, n.sons[codePos])
|
||||
if (s.typ.sons[0] != nil) and (kind != skIterator): addResultNode(c, n)
|
||||
else:
|
||||
if (s.typ.sons[0] != nil) and (kind != skIterator):
|
||||
|
||||
@@ -34,6 +34,7 @@ type
|
||||
|
||||
wColon, wEquals, wDot, wDotDot, wHat, wStar, wMinus,
|
||||
wMagic, wTypeCheck, wFinal, wProfiler, wObjChecks, wImportc, wExportc,
|
||||
wExtern,
|
||||
wAlign, wNodecl, wPure, wVolatile, wRegister, wSideeffect, wHeader,
|
||||
wNosideeffect, wNoreturn, wMerge, wLib, wDynlib, wCompilerproc, wProcVar,
|
||||
wFatal, wError, wWarning, wHint, wLine, wPush, wPop, wDefine, wUndef,
|
||||
@@ -54,7 +55,7 @@ type
|
||||
wCc, wGenscript, wCheckPoint, wCheckPoints, wNoMain, wSubsChar,
|
||||
wAcyclic, wIndex,
|
||||
wCompileToC, wCompileToCpp, wCompileToEcmaScript, wCompileToLLVM, wPretty,
|
||||
wDoc, wGenDepend, wListDef, wCheck, wParse, wScan, wBoot, wLazy,
|
||||
wDoc, wGenDepend, wListDef, wCheck, wParse, wScan, wLazy,
|
||||
wRst2html, wRst2tex, wI,
|
||||
wWrite, wPutEnv, wPrependEnv, wAppendEnv, wThreadVar
|
||||
|
||||
@@ -78,7 +79,8 @@ const
|
||||
|
||||
":", "=", ".", "..", "^", "*", "-",
|
||||
"magic", "typecheck", "final", "profiler", "objchecks", "importc",
|
||||
"exportc", "align", "nodecl", "pure", "volatile", "register", "sideeffect",
|
||||
"exportc", "extern",
|
||||
"align", "nodecl", "pure", "volatile", "register", "sideeffect",
|
||||
"header", "nosideeffect", "noreturn", "merge", "lib", "dynlib",
|
||||
"compilerproc", "procvar", "fatal", "error", "warning", "hint", "line",
|
||||
"push", "pop", "define", "undef", "linedir", "stacktrace", "linetrace",
|
||||
@@ -101,7 +103,7 @@ const
|
||||
"nomain", "subschar", "acyclic", "index",
|
||||
"compiletoc", "compiletocpp", "compiletoecmascript", "compiletollvm",
|
||||
"pretty", "doc", "gendepend", "listdef", "check", "parse", "scan",
|
||||
"boot", "lazy", "rst2html", "rst2tex", "i",
|
||||
"lazy", "rst2html", "rst2tex", "i",
|
||||
"write", "putenv", "prependenv", "appendenv", "threadvar"]
|
||||
|
||||
proc whichKeyword*(id: PIdent): TSpecialWord
|
||||
|
||||
0
tests/accept/compile/tenum3.nim
Normal file → Executable file
0
tests/accept/compile/tenum3.nim
Normal file → Executable file
0
tests/accept/compile/tuserpragma.nim
Normal file → Executable file
0
tests/accept/compile/tuserpragma.nim
Normal file → Executable file
0
tests/accept/run/tarray3.nim
Normal file → Executable file
0
tests/accept/run/tarray3.nim
Normal file → Executable file
0
tests/accept/run/tunhandledexc.nim
Normal file → Executable file
0
tests/accept/run/tunhandledexc.nim
Normal file → Executable file
0
tests/accept/run/twrongexc.nim
Normal file → Executable file
0
tests/accept/run/twrongexc.nim
Normal file → Executable file
3
todo.txt
3
todo.txt
@@ -1,10 +1,11 @@
|
||||
For version 0.8.10
|
||||
==================
|
||||
|
||||
- more robust boot strap process!
|
||||
- support for generation of dynamic libraries
|
||||
- fix exception handling
|
||||
- fix implicit generic routines
|
||||
- fix the streams implementation so that they use methods
|
||||
- support for generation of dynamic libraries
|
||||
|
||||
|
||||
High priority (version 0.9.0)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#! stdtmpl(subsChar='?') | standard
|
||||
#proc GenerateBuildScript(c: TConfigData): string =
|
||||
#proc GenerateBuildShellScript(c: TConfigData): string =
|
||||
# result = "#! /bin/sh\n# Generated by niminst\n"
|
||||
CC="gcc"
|
||||
LINKER="gcc"
|
||||
@@ -83,8 +83,16 @@ case $myos in
|
||||
$LINKER $LINK_FLAGS -o ?{c.binPaths[0]}/?{toLower(c.name)} ?linkCmd || exit 1
|
||||
;;
|
||||
# end for
|
||||
*)
|
||||
echo "Error: no C code generated for: [$myos: $mycpu]"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
*)
|
||||
echo "Error: no C code generated for: [$myos: $mycpu]"
|
||||
exit 1
|
||||
;;
|
||||
# end for
|
||||
esac
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#
|
||||
#
|
||||
# The Nimrod Installation Generator
|
||||
# (c) Copyright 2009 Andreas Rumpf
|
||||
# (c) Copyright 2010 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
@@ -20,6 +20,7 @@ const
|
||||
maxOS = 20 # max number of OSes
|
||||
maxCPU = 10 # max number of CPUs
|
||||
buildShFile = "build.sh"
|
||||
buildBatFile = "build.bat"
|
||||
installShFile = "install.sh"
|
||||
deinstallShFile = "deinstall.sh"
|
||||
|
||||
@@ -89,17 +90,18 @@ proc skipRoot(f: string): string =
|
||||
if result.len == 0: result = f
|
||||
|
||||
include "inno.tmpl"
|
||||
include "build.tmpl"
|
||||
include "buildsh.tmpl"
|
||||
include "buildbat.tmpl"
|
||||
include "install.tmpl"
|
||||
include "deinstall.tmpl"
|
||||
|
||||
# ------------------------- configuration file -------------------------------
|
||||
|
||||
const
|
||||
Version = "0.7"
|
||||
Version = "0.8"
|
||||
Usage = "niminst - Nimrod Installation Generator Version " & version & """
|
||||
|
||||
(c) 2009 Andreas Rumpf
|
||||
(c) 2010 Andreas Rumpf
|
||||
Usage:
|
||||
niminst [options] command[;command2...] ini-file[.ini] [compile_options]
|
||||
Command:
|
||||
@@ -289,6 +291,22 @@ proc writeFile(filename, content, newline: string) =
|
||||
else:
|
||||
quit("Cannot open for writing: " & filename)
|
||||
|
||||
proc removeDuplicateFiles(c: var TConfigData) =
|
||||
for osA in countdown(c.oses.len, 1):
|
||||
for cpuA in countdown(c.cpus.len, 1):
|
||||
for i in 0..c.cfiles[osA][cpuA].len-1:
|
||||
var dup = c.cfiles[osA][cpuA][i]
|
||||
var f = extractFilename(dup)
|
||||
for osB in 1..c.oses.len:
|
||||
for cpuB in 1..c.cpus.len:
|
||||
if osB != osA or cpuB != cpuA:
|
||||
var orig = buildDir(osB, cpuB) / f
|
||||
if ExistsFile(orig) and ExistsFile(dup) and
|
||||
sameFileContent(orig, dup):
|
||||
# file is identical, so delete duplicate:
|
||||
RemoveFile(dup)
|
||||
c.cfiles[osA][cpuA][i] = orig
|
||||
|
||||
proc srcdist(c: var TConfigData) =
|
||||
for x in walkFiles("lib/*.h"):
|
||||
CopyFile(dest="build" / extractFilename(x), source=x)
|
||||
@@ -311,21 +329,9 @@ proc srcdist(c: var TConfigData) =
|
||||
CopyFile(dest=dest, source=c.cfiles[osA][cpuA][i])
|
||||
c.cfiles[osA][cpuA][i] = dest
|
||||
# second pass: remove duplicate files
|
||||
for osA in countdown(c.oses.len, 1):
|
||||
for cpuA in countdown(c.cpus.len, 1):
|
||||
for i in 0..c.cfiles[osA][cpuA].len-1:
|
||||
var dup = c.cfiles[osA][cpuA][i]
|
||||
var f = extractFilename(dup)
|
||||
for osB in 1..c.oses.len:
|
||||
for cpuB in 1..c.cpus.len:
|
||||
if osB != osA or cpuB != cpuA:
|
||||
var orig = buildDir(osB, cpuB) / f
|
||||
if ExistsFile(orig) and ExistsFile(dup) and
|
||||
sameFileContent(orig, dup):
|
||||
# file is identical, so delete duplicate:
|
||||
RemoveFile(dup)
|
||||
c.cfiles[osA][cpuA][i] = orig
|
||||
writeFile(buildShFile, GenerateBuildScript(c), "\10")
|
||||
removeDuplicateFiles(c)
|
||||
writeFile(buildShFile, GenerateBuildShellScript(c), "\10")
|
||||
writeFile(buildBatFile, GenerateBuildBatchScript(c), "\13\10")
|
||||
if c.installScript:
|
||||
writeFile(installShFile, GenerateInstallScript(c), "\10")
|
||||
if c.uninstallScript:
|
||||
|
||||
11
web/news.txt
11
web/news.txt
@@ -27,6 +27,13 @@ Changes affecting backwards compatibility
|
||||
unless they are used in the same module.
|
||||
- Deprecated ``times.getStartMilsecs``: Use ``epochTime`` or ``cpuTime``
|
||||
instead.
|
||||
- Removed ``system.OpenFile``.
|
||||
- Removed ``system.CloseFile``.
|
||||
- Removed ``strutils.replaceStr``.
|
||||
- Removed ``strutils.deleteStr``.
|
||||
- Removed ``strutils.splitLinesSeq``.
|
||||
- Removed ``strutils.splitSeq``.
|
||||
- Removed ``strutils.toString``.
|
||||
|
||||
|
||||
Additions
|
||||
@@ -43,6 +50,10 @@ Additions
|
||||
- Implemented ``{.size: sizeof(cint).}`` pragma for enum types. This is useful
|
||||
for interfacing with C.
|
||||
- Implemented ``{.pragma.}`` pragma for user defined pragmas.
|
||||
- Implemented ``{.extern.}`` pragma for better control of name mangling.
|
||||
- The ``importc`` and ``exportc`` pragmas support format strings:
|
||||
``proc p{.exportc: "nim_$1".}`` exports ``p`` as ``nim_p``. This is useful
|
||||
for user defined pragmas.
|
||||
|
||||
|
||||
2010-03-14 Version 0.8.8 released
|
||||
|
||||
Reference in New Issue
Block a user