handling of compiler procs improved for DLL generation

This commit is contained in:
Andreas Rumpf 2010-07-29 21:30:04 +02:00
commit ff02ce2d50
33 changed files with 694 additions and 664 deletions

39
lib/nimrtl.nim Executable file
View 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'".}

View file

@ -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 ## Searches for `chars` in `s` starting at position `start`. If `s` contains
## none of the characters in `chars`, -1 is returned. ## 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 proc toOctal*(c: char): string
## Converts a character `c` to its octal representation. The resulting ## Converts a character `c` to its octal representation. The resulting
## string may not have a leading zero. Its length is always exactly 3. ## 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' else: break # was '\0'
first = last 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.} = proc splitLines*(s: string): seq[string] {.noSideEffect.} =
## The same as the `splitLines` iterator, but is a proc that returns a ## The same as the `splitLines` iterator, but is a proc that returns a
## sequence of substrings. ## sequence of substrings.
@ -328,12 +297,6 @@ proc ParseHexInt*(s: string): int {.noSideEffect, procvar.}
## following optional prefixes: ``0x``, ``0X``, ``#``. ## following optional prefixes: ``0x``, ``0X``, ``#``.
## Underscores within `s` are ignored. ## 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 proc repeatChar*(count: int, c: Char = ' '): string
## Returns a string of length `count` consisting only of ## Returns a string of length `count` consisting only of
## the character `c`. ## the character `c`.
@ -670,10 +633,6 @@ proc delete*(s: var string, first, last: int) =
inc(j) inc(j)
setlen(s, newLen) 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: # parsing numbers:
proc toHex(x: BiggestInt, len: int): string = proc toHex(x: BiggestInt, len: int): string =

View file

@ -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: char) {.magic: "AppendStrCh", noSideEffect.}
proc add*(x: var string, y: string) {.magic: "AppendStrStr", noSideEffect.} proc add*(x: var string, y: string) {.magic: "AppendStrStr", noSideEffect.}
include "system/cgprocs"
when not defined(ECMAScript): when not defined(ECMAScript):
{.push overflow_checks:off} {.push overflow_checks:off}
proc add* (x: var string, y: cstring) = proc add* (x: var string, y: cstring) =
@ -732,7 +734,6 @@ type
## is the signed integer type that should be used for converting ## is the signed integer type that should be used for converting
## pointers to integer addresses for readability. ## pointers to integer addresses for readability.
type
BiggestInt* = int64 BiggestInt* = int64
## is an alias for the biggest signed integer type the Nimrod compiler ## is an alias for the biggest signed integer type the Nimrod compiler
## supports. Currently this is ``int64``, but it is platform-dependant ## 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] cstringArray* {.importc: "char**", nodecl.} = ptr array [0..50_000, cstring]
## This is binary compatible to the type ``char**`` in *C*. The array's ## This is binary compatible to the type ``char**`` in *C*. The array's
## high value is large enough to disable bounds checking in practice. ## 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. TEndian* = enum ## is a type describing the endianness of a processor.
littleEndian, bigEndian littleEndian, bigEndian
@ -823,6 +824,8 @@ const
## a string that describes the application type. Possible values: ## a string that describes the application type. Possible values:
## "console", "gui", "lib". ## "console", "gui", "lib".
include "system/inclrtl"
proc toFloat*(i: int): float {. proc toFloat*(i: int): float {.
magic: "ToFloat", noSideEffect, importc: "toFloat".} magic: "ToFloat", noSideEffect, importc: "toFloat".}
## converts an integer `i` into a ``float``. If the conversion ## 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 ## otherwise. Like any procedure dealing with raw memory this is
## *unsafe*. ## *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 ## allocates a new memory block with at least ``size`` bytes. The
## block has to be freed with ``realloc(block, 0)`` or ## block has to be freed with ``realloc(block, 0)`` or
## ``dealloc(block)``. The block is not initialized, so reading ## ``dealloc(block)``. The block is not initialized, so reading
## from it before writing to it is undefined behaviour! ## 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 ## allocates a new memory block with at least ``size`` bytes. The
## block has to be freed with ``realloc(block, 0)`` or ## block has to be freed with ``realloc(block, 0)`` or
## ``dealloc(block)``. The block is initialized with all bytes ## ``dealloc(block)``. The block is initialized with all bytes
## containing zero, so it is somewhat safer than ``alloc``. ## 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 ## 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 ## memory block is returned. In either way the block has at least
## ``newsize`` bytes. If ``newsize == 0`` and p is not **nil** ## ``newsize`` bytes. If ``newsize == 0`` and p is not **nil**
## ``realloc`` calls ``dealloc(p)``. In other cases the block has to ## ``realloc`` calls ``dealloc(p)``. In other cases the block has to
## be freed with ``dealloc``. ## be freed with ``dealloc``.
proc dealloc*(p: Pointer) {.noconv.} proc dealloc*(p: Pointer) {.noconv, rtl.}
## frees the memory allocated with ``alloc``, ``alloc0`` or ## frees the memory allocated with ``alloc``, ``alloc0`` or
## ``realloc``. This procedure is dangerous! If one forgets to ## ``realloc``. This procedure is dangerous! If one forgets to
## free the memory a leak occurs; if one tries to access freed ## free the memory a leak occurs; if one tries to access freed
@ -1009,14 +1012,14 @@ var
# GC interface: # GC interface:
proc getOccupiedMem*(): int proc getOccupiedMem*(): int {.rtl.}
## returns the number of bytes that are owned by the process and hold data. ## 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 ## returns the number of bytes that are owned by the process, but do not
## hold any meaningful data. ## hold any meaningful data.
proc getTotalMem*(): int proc getTotalMem*(): int {.rtl.}
## returns the number of bytes that are owned by the process. ## 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 --------------------------------------------- # ----------------- GC interface ---------------------------------------------
proc GC_disable*() proc GC_disable*() {.rtl.}
## disables the GC. If called n-times, n calls to `GC_enable` are needed to ## 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 ## reactivate the GC. Note that in most circumstances one should only disable
## the mark and sweep phase with `GC_disableMarkAndSweep`. ## the mark and sweep phase with `GC_disableMarkAndSweep`.
proc GC_enable*() proc GC_enable*() {.rtl.}
## enables the GC again. ## enables the GC again.
proc GC_fullCollect*() proc GC_fullCollect*() {.rtl.}
## forces a full garbage collection pass. ## forces a full garbage collection pass.
## Ordinary code does not need to call this (and should not). ## Ordinary code does not need to call this (and should not).
@ -1224,18 +1227,18 @@ type
gcOptimizeTime, ## optimize for speed gcOptimizeTime, ## optimize for speed
gcOptimizeSpace ## optimize for memory footprint 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. ## tells the GC the desired strategy for the application.
proc GC_enableMarkAndSweep*() proc GC_enableMarkAndSweep*() {.rtl.}
proc GC_disableMarkAndSweep*() proc GC_disableMarkAndSweep*() {.rtl.}
## the current implementation uses a reference counting garbage collector ## the current implementation uses a reference counting garbage collector
## with a seldomly run mark and sweep phase to free cycles. The mark and ## 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 ## 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 ## does not create cycles. Thus the mark and sweep phase can be deactivated
## and activated separately from the rest of the GC. ## 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 ## returns an informative string about the GC's activity. This may be useful
## for tweaking. ## for tweaking.
@ -1372,23 +1375,14 @@ when not defined(EcmaScript) and not defined(NimrodVM):
## appropriately. It also annoys people if redirection via ``>output.txt`` ## appropriately. It also annoys people if redirection via ``>output.txt``
## does not work because the program writes to ``stderr``. ## 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, proc Open*(f: var TFile, filename: string,
mode: TFileMode = fmRead, bufSize: int = -1): Bool mode: TFileMode = fmRead, bufSize: int = -1): Bool
## Opens a file named `filename` with given `mode`. ## Opens a file named `filename` with given `mode`.
## ##
## Default mode is readonly. Returns true iff the file could be opened. ## 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 ## 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 ## that the programmer needs to provide an appropriate error message
## (yes, even in scripts). ## anyway.
proc Open*(f: var TFile, filehandle: TFileHandle, proc Open*(f: var TFile, filehandle: TFileHandle,
mode: TFileMode = fmRead): Bool 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. ## 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.} proc Close*(f: TFile) {.importc: "fclose", nodecl.}
## Closes the file. ## Closes the file.
@ -1545,7 +1535,7 @@ when not defined(EcmaScript) and not defined(NimrodVM):
const const
GenericSeqSize = (2 * sizeof(int)) 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 = proc getDiscriminant(aa: Pointer, n: ptr TNimNode): int =
assert(n.kind == nkCase) assert(n.kind == nkCase)

14
lib/system/cgprocs.nim Normal file
View 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.}

View file

@ -24,7 +24,12 @@ proc nimUnloadLibrary(lib: TLibHandle) {.compilerproc.}
proc nimGetProcAddr(lib: TLibHandle, name: cstring): TProcAddr {.compilerproc.} proc nimGetProcAddr(lib: TLibHandle, name: cstring): TProcAddr {.compilerproc.}
proc nimLoadLibraryError(path: string) {.compilerproc, noinline.} = 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: # this code was inspired from Lua's source code:
# Lua - An Extensible Extension Language # Lua - An Extensible Extension Language

View file

@ -74,13 +74,13 @@ var
# This is wasteful but safe. This is a lock against recursive garbage # This is wasteful but safe. This is a lock against recursive garbage
# collection, not a lock for threads! # 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 # 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 # 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). # 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 newObj(typ: PNimType, size: int): pointer {.compilerRtl.}
proc newSeq(typ: PNimType, len: int): pointer {.compilerproc.} proc newSeq(typ: PNimType, len: int): pointer {.compilerRtl.}
proc addZCT(s: var TCellSeq, c: PCell) {.noinline.} = proc addZCT(s: var TCellSeq, c: PCell) {.noinline.} =
if (c.refcount and rcZct) == 0: if (c.refcount and rcZct) == 0:
@ -214,8 +214,10 @@ proc prepareDealloc(cell: PCell) =
(cast[TFinalizer](cell.typ.finalizer))(cellToUsr(cell)) (cast[TFinalizer](cell.typ.finalizer))(cellToUsr(cell))
dec(recGcLock) dec(recGcLock)
proc setStackBottom(theStackBottom: pointer) {.compilerproc.} = proc setStackBottom(theStackBottom: pointer) {.compilerRtl.} =
stackBottom = theStackBottom # 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.} = proc PossibleRoot(gch: var TGcHeap, c: PCell) {.inline.} =
if canbeCycleRoot(c): incl(gch.cycleRoots, c) if canbeCycleRoot(c): incl(gch.cycleRoots, c)
@ -236,10 +238,10 @@ proc incRef(c: PCell) {.inline.} =
if canBeCycleRoot(c): if canBeCycleRoot(c):
incl(gch.cycleRoots, c) incl(gch.cycleRoots, c)
proc nimGCref(p: pointer) {.compilerproc, inline.} = incRef(usrToCell(p)) proc nimGCref(p: pointer) {.compilerRtl, inl.} = incRef(usrToCell(p))
proc nimGCunref(p: pointer) {.compilerproc, inline.} = decRef(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! # the code generator calls this proc!
assert(not isOnStack(dest)) assert(not isOnStack(dest))
# BUGFIX: first incRef then decRef! # BUGFIX: first incRef then decRef!
@ -247,7 +249,7 @@ proc asgnRef(dest: ppointer, src: pointer) {.compilerproc, inline.} =
if dest^ != nil: decRef(usrToCell(dest^)) if dest^ != nil: decRef(usrToCell(dest^))
dest^ = src 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 # the code generator calls this proc if it is known at compile time that no
# cycle is possible. # cycle is possible.
if src != nil: if src != nil:

45
lib/system/inclrtl.nim Executable file
View 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.}

View file

@ -187,60 +187,35 @@ elif defined(nogc):
dest^ = src dest^ = src
include "system/cellsets" include "system/cellsets"
elif appType == "lib": elif defined(useNimRtl):
{.warning: "gc in a library context may not work".} proc initGC() = nil
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.}
proc newObj(typ: PNimType, size: int): pointer {. proc newObj(typ: PNimType, size: int): pointer {.compilerRtl.}
compilerproc, cdecl, importc, dynlib: nimrtl.} proc newSeq(typ: PNimType, len: int): pointer {.compilerRtl.}
proc newSeq(typ: PNimType, len: int): pointer {. proc growObj(old: pointer, newsize: int): pointer {.rtl.}
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.}
# The write barrier is performance critical! proc setStackBottom(theStackBottom: pointer) {.compilerProc, inline.} =
# XXX We should ensure that they are inlined here. # This happens before setStackBottom has been loaded by dlsym(), so
# Later implementations will do this. # we simply provide a dummy implemenation here for the code gen. No
# harm is done by this.
nil
proc unsureAsgnRef(dest: ppointer, src: pointer) {. proc nimGCref(p: pointer) {.compilerRtl.}
compilerproc, cdecl, importc, dynlib: nimrtl.} proc nimGCunref(p: pointer) {.compilerRtl.}
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"
# 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" include "system/cellsets"
else: else:
include "system/alloc" include "system/alloc"
include "system/cellsets" include "system/cellsets"

View file

@ -1,7 +1,7 @@
# #
# #
# Nimrod's Runtime Library # Nimrod's Runtime Library
# (c) Copyright 2009 Andreas Rumpf # (c) Copyright 2010 Andreas Rumpf
# #
# See the file "copying.txt", included in this # See the file "copying.txt", included in this
# distribution, for details about the copyright. # distribution, for details about the copyright.
@ -35,15 +35,15 @@ proc reprStrAux(result: var string, s: string) =
else: result.add(c) else: result.add(c)
add result, "\"" add result, "\""
proc reprStr(s: string): string {.compilerproc.} = proc reprStr(s: string): string {.compilerRtl.} =
result = "" result = ""
reprStrAux(result, s) reprStrAux(result, s)
proc reprBool(x: bool): string {.compilerproc.} = proc reprBool(x: bool): string {.compilerRtl.} =
if x: result = "true" if x: result = "true"
else: result = "false" else: result = "false"
proc reprChar(x: char): string {.compilerproc.} = proc reprChar(x: char): string {.compilerRtl.} =
result = "\'" result = "\'"
case x case x
of '"': add result, "\\\"" of '"': add result, "\\\""
@ -52,7 +52,7 @@ proc reprChar(x: char): string {.compilerproc.} =
else: add result, x else: add result, x
add result, "\'" add result, "\'"
proc reprEnum(e: int, typ: PNimType): string {.compilerproc.} = proc reprEnum(e: int, typ: PNimType): string {.compilerRtl.} =
if e <% typ.node.len: # BUGFIX if e <% typ.node.len: # BUGFIX
result = $typ.node.sons[e].name result = $typ.node.sons[e].name
else: else:
@ -97,7 +97,7 @@ proc reprSetAux(result: var string, p: pointer, typ: PNimType) =
inc(elemCounter) inc(elemCounter)
add result, "}" add result, "}"
proc reprSet(p: pointer, typ: PNimType): string {.compilerproc.} = proc reprSet(p: pointer, typ: PNimType): string {.compilerRtl.} =
result = "" result = ""
reprSetAux(result, p, typ) reprSetAux(result, p, typ)
@ -108,122 +108,123 @@ type
recdepth: int # do not recurse endless recdepth: int # do not recurse endless
indent: int # indentation indent: int # indentation
proc initReprClosure(cl: var TReprClosure) = when not defined(useNimRtl):
Init(cl.marked) proc initReprClosure(cl: var TReprClosure) =
cl.recdepth = -1 # default is to display everything! Init(cl.marked)
cl.indent = 0 cl.recdepth = -1 # default is to display everything!
cl.indent = 0
proc deinitReprClosure(cl: var TReprClosure) = proc deinitReprClosure(cl: var TReprClosure) =
Deinit(cl.marked) Deinit(cl.marked)
proc reprBreak(result: var string, cl: TReprClosure) = proc reprBreak(result: var string, cl: TReprClosure) =
add result, "\n" add result, "\n"
for i in 0..cl.indent-1: add result, ' ' for i in 0..cl.indent-1: add result, ' '
proc reprAux(result: var string, p: pointer, typ: PNimType, proc reprAux(result: var string, p: pointer, typ: PNimType,
cl: var TReprClosure) cl: var TReprClosure)
proc reprArray(result: var string, p: pointer, typ: PNimType, proc reprArray(result: var string, p: pointer, typ: PNimType,
cl: var TReprClosure) = cl: var TReprClosure) =
add result, "[" add result, "["
var bs = typ.base.size var bs = typ.base.size
for i in 0..typ.size div bs - 1: for i in 0..typ.size div bs - 1:
if i > 0: add result, ", " if i > 0: add result, ", "
reprAux(result, cast[pointer](cast[TAddress](p) + i*bs), typ.base, cl) reprAux(result, cast[pointer](cast[TAddress](p) + i*bs), typ.base, cl)
add result, "]" 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) = cl: var TReprClosure) =
if p == nil: add result, "["
add result, "nil" reprRecordAux(result, p, typ.node, cl)
return add result, "]"
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, proc reprRef(result: var string, p: pointer, typ: PNimType,
cl: var TReprClosure) = cl: var TReprClosure) =
case n.kind # we know that p is not nil here:
of nkNone: assert(false) when defined(boehmGC) or defined(nogc):
of nkSlot: var cell = cast[PCell](p)
add result, $n.name else:
add result, " = " var cell = usrToCell(p)
reprAux(result, cast[pointer](cast[TAddress](p) + n.offset), n.typ, cl) add result, "ref " & reprPointer(p)
of nkList: if cell notin cl.marked:
for i in 0..n.len-1: # only the address is shown:
if i > 0: add result, ",\n" incl(cl.marked, cell)
reprRecordAux(result, p, n.sons[i], cl) add result, " --> "
of nkCase: reprAux(result, p, typ.base, cl)
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, proc reprAux(result: var string, p: pointer, typ: PNimType,
cl: var TReprClosure) = cl: var TReprClosure) =
add result, "[" if cl.recdepth == 0:
reprRecordAux(result, p, typ.node, cl) add result, "..."
add result, "]" return
dec(cl.recdepth)
proc reprRef(result: var string, p: pointer, typ: PNimType, case typ.kind
cl: var TReprClosure) = of tySet: reprSetAux(result, p, typ)
# we know that p is not nil here: of tyArray: reprArray(result, p, typ, cl)
when defined(boehmGC) or defined(nogc): of tyTuple, tyPureObject: reprRecord(result, p, typ, cl)
var cell = cast[PCell](p) of tyObject:
else: var t = cast[ptr PNimType](p)^
var cell = usrToCell(p) reprRecord(result, p, t, cl)
add result, "ref " & reprPointer(p) of tyRef, tyPtr:
if cell notin cl.marked: assert(p != nil)
# only the address is shown: if cast[ppointer](p)^ == nil: add result, "nil"
incl(cl.marked, cell) else: reprRef(result, cast[ppointer](p)^, typ, cl)
add result, " --> " of tySequence:
reprAux(result, p, typ.base, cl) reprSequence(result, cast[ppointer](p)^, typ, cl)
of tyInt: add result, $(cast[ptr int](p)^)
proc reprAux(result: var string, p: pointer, typ: PNimType, of tyInt8: add result, $int(cast[ptr Int8](p)^)
cl: var TReprClosure) = of tyInt16: add result, $int(cast[ptr Int16](p)^)
if cl.recdepth == 0: of tyInt32: add result, $int(cast[ptr Int32](p)^)
add result, "..." of tyInt64: add result, $(cast[ptr Int64](p)^)
return of tyFloat: add result, $(cast[ptr float](p)^)
dec(cl.recdepth) of tyFloat32: add result, $(cast[ptr float32](p)^)
case typ.kind of tyFloat64: add result, $(cast[ptr float64](p)^)
of tySet: reprSetAux(result, p, typ) of tyEnum: add result, reprEnum(cast[ptr int](p)^, typ)
of tyArray: reprArray(result, p, typ, cl) of tyBool: add result, reprBool(cast[ptr bool](p)^)
of tyTuple, tyPureObject: reprRecord(result, p, typ, cl) of tyChar: add result, reprChar(cast[ptr char](p)^)
of tyObject: of tyString: reprStrAux(result, cast[ptr string](p)^)
var t = cast[ptr PNimType](p)^ of tyCString: reprStrAux(result, $(cast[ptr cstring](p)^))
reprRecord(result, p, t, cl) of tyRange: reprAux(result, p, typ.base, cl)
of tyRef, tyPtr: of tyProc, tyPointer:
assert(p != nil) if cast[ppointer](p)^ == nil: add result, "nil"
if cast[ppointer](p)^ == nil: add result, "nil" else: add result, reprPointer(cast[ppointer](p)^)
else: reprRef(result, cast[ppointer](p)^, typ, cl) else:
of tySequence: add result, "(invalid data!)"
reprSequence(result, cast[ppointer](p)^, typ, cl) inc(cl.recdepth)
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 {. proc reprOpenArray(p: pointer, length: int, elemtyp: PNimType): string {.
compilerproc.} = compilerRtl.} =
var var
cl: TReprClosure cl: TReprClosure
initReprClosure(cl) initReprClosure(cl)
@ -235,15 +236,17 @@ proc reprOpenArray(p: pointer, length: int, elemtyp: PNimType): string {.
add result, "]" add result, "]"
deinitReprClosure(cl) deinitReprClosure(cl)
proc reprAny(p: pointer, typ: PNimType): string = when not defined(useNimRtl):
var proc reprAny(p: pointer, typ: PNimType): string =
cl: TReprClosure var
initReprClosure(cl) cl: TReprClosure
result = "" initReprClosure(cl)
if typ.kind in {tyObject, tyPureObject, tyTuple, tyArray, tySet}: result = ""
reprAux(result, p, typ, cl) if typ.kind in {tyObject, tyPureObject, tyTuple, tyArray, tySet}:
else: reprAux(result, p, typ, cl)
var p = p else:
reprAux(result, addr(p), typ, cl) var p = p
add result, "\n" reprAux(result, addr(p), typ, cl)
deinitReprClosure(cl) add result, "\n"
deinitReprClosure(cl)

View file

@ -135,14 +135,6 @@ proc open(f: var TFile, filehandle: TFileHandle, mode: TFileMode): bool =
f = fdopen(filehandle, FormatOpen[mode]) f = fdopen(filehandle, FormatOpen[mode])
result = f != nil 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: # C routine that is used here:
proc fread(buf: Pointer, size, n: int, f: TFile): int {. proc fread(buf: Pointer, size, n: int, f: TFile): int {.
importc: "fread", noDecl.} importc: "fread", noDecl.}

View file

@ -1,7 +1,7 @@
# #
# #
# Nimrod's Runtime Library # Nimrod's Runtime Library
# (c) Copyright 2009 Andreas Rumpf # (c) Copyright 2010 Andreas Rumpf
# #
# See the file "copying.txt", included in this # See the file "copying.txt", included in this
# distribution, for details about the copyright. # 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.} = proc copyStr(s: NimString, start: int): NimString {.exportc.} =
return copyStrLast(s, start, s.len-1) 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 result = s
if result.len >= result.space: if result.len >= result.space:
result.space = resize(result.space) result.space = resize(result.space)
@ -196,7 +197,7 @@ proc incrSeq(seq: PGenericSeq, elemSize: int): PGenericSeq {.compilerProc.} =
inc(result.len) inc(result.len)
proc setLengthSeq(seq: PGenericSeq, elemSize, newLen: int): PGenericSeq {. proc setLengthSeq(seq: PGenericSeq, elemSize, newLen: int): PGenericSeq {.
compilerProc.} = compilerRtl.} =
when false: when false:
# broken version: # broken version:
result = seq result = seq
@ -223,7 +224,7 @@ proc setLengthSeq(seq: PGenericSeq, elemSize, newLen: int): PGenericSeq {.
result.len = newLen result.len = newLen
# --------------- other string routines ---------------------------------- # --------------- other string routines ----------------------------------
proc nimIntToStr(x: int): string {.compilerproc.} = proc nimIntToStr(x: int): string {.compilerRtl.} =
result = newString(sizeof(x)*4) result = newString(sizeof(x)*4)
var i = 0 var i = 0
var y = x var y = x
@ -246,7 +247,7 @@ proc nimFloatToStr(x: float): string {.compilerproc.} =
c_sprintf(buf, "%#g", x) c_sprintf(buf, "%#g", x)
return $buf 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 # we don't rely on C's runtime here as some C compiler's
# int64 support is weak # int64 support is weak
result = newString(sizeof(x)*4) result = newString(sizeof(x)*4)

View file

@ -530,11 +530,10 @@ proc structPragmas(p: TParser, name: PNode, origName: string): PNode =
result = newNodeP(nkPragmaExpr, p) result = newNodeP(nkPragmaExpr, p)
addson(result, exportSym(p, name)) addson(result, exportSym(p, name))
var pragmas = newNodep(nkPragma, p) var pragmas = newNodep(nkPragma, p)
addSon(pragmas, newIdentNodeP("pure", p)) addSon(pragmas, newIdentNodeP("pure", p), newIdentNodeP("final", p))
addSon(pragmas, newIdentNodeP("final", p))
if p.options.header.len > 0: if p.options.header.len > 0:
addSon(pragmas, newIdentStrLitPair("importc", origName, p)) addSon(pragmas, newIdentStrLitPair("importc", origName, p),
addSon(pragmas, newIdentStrLitPair("header", p.options.header, p)) newIdentStrLitPair("header", p.options.header, p))
addSon(result, pragmas) addSon(result, pragmas)
proc enumPragmas(p: TParser, name: PNode): PNode = proc enumPragmas(p: TParser, name: PNode): PNode =
@ -542,15 +541,13 @@ proc enumPragmas(p: TParser, name: PNode): PNode =
addson(result, name) addson(result, name)
var pragmas = newNodep(nkPragma, p) var pragmas = newNodep(nkPragma, p)
var e = newNodeP(nkExprColonExpr, p) var e = newNodeP(nkExprColonExpr, p)
addSon(e, newIdentNodeP("size", p)) addSon(e, newIdentNodeP("size", p), newIntNodeP(nkIntLit, 4, p))
addSon(e, newIntNodeP(nkIntLit, 4, p))
addSon(pragmas, e) addSon(pragmas, e)
addSon(result, pragmas) addSon(result, pragmas)
proc parseStruct(p: var TParser, isUnion: bool): PNode = proc parseStruct(p: var TParser, isUnion: bool): PNode =
result = newNodeP(nkObjectTy, p) result = newNodeP(nkObjectTy, p)
addSon(result, nil) # no pragmas addSon(result, nil, nil) # no pragmas, no inheritance
addSon(result, nil) # no inheritance
if p.tok.xkind == pxCurlyLe: if p.tok.xkind == pxCurlyLe:
addSon(result, parseStructBody(p, isUnion)) addSon(result, parseStructBody(p, isUnion))
else: else:
@ -569,8 +566,7 @@ proc parseParam(p: var TParser, params: PNode) =
name = newIdentNodeP("a" & $idx, p) name = newIdentNodeP("a" & $idx, p)
typ = parseTypeSuffix(p, typ) typ = parseTypeSuffix(p, typ)
var x = newNodeP(nkIdentDefs, p) var x = newNodeP(nkIdentDefs, p)
addSon(x, name) addSon(x, name, typ)
addSon(x, typ)
if p.tok.xkind == pxAsgn: if p.tok.xkind == pxAsgn:
# we support default parameters for C++: # we support default parameters for C++:
getTok(p, x) getTok(p, x)
@ -621,15 +617,11 @@ proc parseFunctionPointerDecl(p: var TParser, rettyp: PNode): PNode =
if p.inTypeDef == 0: if p.inTypeDef == 0:
result = newNodeP(nkVarSection, p) result = newNodeP(nkVarSection, p)
var def = newNodeP(nkIdentDefs, p) var def = newNodeP(nkIdentDefs, p)
addSon(def, name) addSon(def, name, procType, nil)
addSon(def, procType)
addSon(def, nil)
addSon(result, def) addSon(result, def)
else: else:
result = newNodeP(nkTypeDef, p) result = newNodeP(nkTypeDef, p)
addSon(result, name) addSon(result, name, nil, procType)
addSon(result, nil) # no generics
addSon(result, procType)
proc addTypeDef(section, name, t: PNode) = proc addTypeDef(section, name, t: PNode) =
var def = newNodeI(nkTypeDef, name.info) var def = newNodeI(nkTypeDef, name.info)
@ -674,8 +666,7 @@ proc enumFields(p: var TParser): PNode =
var c = constantExpression(p) var c = constantExpression(p)
var a = e var a = e
e = newNodeP(nkEnumFieldDef, p) e = newNodeP(nkEnumFieldDef, p)
addSon(e, a) addSon(e, a, c)
addSon(e, c)
skipCom(p, e) skipCom(p, e)
addSon(result, e) addSon(result, e)
@ -871,10 +862,8 @@ proc declaration(p: var TParser): PNode =
addSon(pragmas, newIdentNodeP("cdecl", p)) addSon(pragmas, newIdentNodeP("cdecl", p))
elif pfStdcall in p.options.flags: elif pfStdcall in p.options.flags:
addSon(pragmas, newIdentNodeP("stdcall", p)) addSon(pragmas, newIdentNodeP("stdcall", p))
addSon(result, exportSym(p, name)) addSon(result, exportSym(p, name), nil) # no generics
addSon(result, nil) # no generics addSon(result, params, pragmas)
addSon(result, params)
addSon(result, pragmas)
case p.tok.xkind case p.tok.xkind
of pxSemicolon: of pxSemicolon:
getTok(p) getTok(p)
@ -1175,17 +1164,14 @@ proc asgnExpr(p: var TParser, opr: string, a: PNode): PNode =
getTok(p, a) getTok(p, a)
var b = assignmentExpression(p) var b = assignmentExpression(p)
result = newNodeP(nkAsgn, p) result = newNodeP(nkAsgn, p)
addSon(result, a) addSon(result, a, newBinary(opr, copyTree(a), b, p))
addSon(result, newBinary(opr, copyTree(a), b, p))
proc incdec(p: var TParser, opr: string, a: PNode): PNode = proc incdec(p: var TParser, opr: string, a: PNode): PNode =
closeContext(p) closeContext(p)
getTok(p, a) getTok(p, a)
var b = assignmentExpression(p) var b = assignmentExpression(p)
result = newNodeP(nkCall, p) result = newNodeP(nkCall, p)
addSon(result, newIdentNodeP(getIdent(opr), p)) addSon(result, newIdentNodeP(getIdent(opr), p), a, b)
addSon(result, a)
addSon(result, b)
proc assignmentExpression(p: var TParser): PNode = proc assignmentExpression(p: var TParser): PNode =
saveContext(p) saveContext(p)
@ -1196,8 +1182,7 @@ proc assignmentExpression(p: var TParser): PNode =
getTok(p, a) getTok(p, a)
var b = assignmentExpression(p) var b = assignmentExpression(p)
result = newNodeP(nkAsgn, p) result = newNodeP(nkAsgn, p)
addSon(result, a) addSon(result, a, b)
addSon(result, b)
of pxPlusAsgn: result = incDec(p, "inc", a) of pxPlusAsgn: result = incDec(p, "inc", a)
of pxMinusAsgn: result = incDec(p, "dec", a) of pxMinusAsgn: result = incDec(p, "dec", a)
of pxStarAsgn: result = asgnExpr(p, "*", a) of pxStarAsgn: result = asgnExpr(p, "*", a)
@ -1291,8 +1276,7 @@ proc conditionalExpression(p: var TParser): PNode =
var c = conditionalExpression(p) var c = conditionalExpression(p)
result = newNodeP(nkIfExpr, p) result = newNodeP(nkIfExpr, p)
var branch = newNodeP(nkElifExpr, p) var branch = newNodeP(nkElifExpr, p)
addSon(branch, a) addSon(branch, a, b)
addSon(branch, b)
addSon(result, branch) addSon(result, branch)
branch = newNodeP(nkElseExpr, p) branch = newNodeP(nkElseExpr, p)
addSon(branch, c) addSon(branch, c)

0
rod/c2nim/manual.txt Normal file → Executable file
View file

0
rod/c2nim/tests/systest.c Normal file → Executable file
View file

0
rod/c2nim/tests/systest2.c Normal file → Executable file
View file

View file

@ -1,7 +1,7 @@
# #
# #
# The Nimrod Compiler # The Nimrod Compiler
# (c) Copyright 2009 Andreas Rumpf # (c) Copyright 2010 Andreas Rumpf
# #
# See the file "copying.txt", included in this # See the file "copying.txt", included in this
# distribution, for details about the copyright. # distribution, for details about the copyright.
@ -33,7 +33,7 @@ proc genHexLiteral(v: PNode): PRope =
result = intLiteral(v.intVal) result = intLiteral(v.intVal)
proc getStrLit(m: BModule, s: string): PRope = proc getStrLit(m: BModule, s: string): PRope =
useMagic(m, "TGenericSeq") discard cgsym(m, "TGenericSeq")
result = con("TMP", toRope(getID())) result = con("TMP", toRope(getID()))
appf(m.s[cfsData], "STRING_LITERAL($1, $2, $3);$n", appf(m.s[cfsData], "STRING_LITERAL($1, $2, $3);$n",
[result, makeCString(s), ToRope(len(s))]) [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) var id = NodeTableTestOrSet(p.module.dataCache, v, gid)
if id == gid: if id == gid:
# string literal not found in the cache: # string literal not found in the cache:
useMagic(p.module, "NimStringDesc") result = ropecg(p.module, "((#NimStringDesc*) &$1)",
result = ropef("((NimStringDesc*) &$1)", [getStrLit(p.module, v.strVal)]) [getStrLit(p.module, v.strVal)])
else: else:
result = ropef("((NimStringDesc*) &TMP$1)", [toRope(id)]) result = ropecg(p.module, "((#NimStringDesc*) &TMP$1)", [toRope(id)])
else: else:
result = makeCString(v.strVal) result = makeCString(v.strVal)
of nkFloatLit..nkFloat64Lit: of nkFloatLit..nkFloat64Lit:
@ -119,13 +119,11 @@ proc genRawSetData(cs: TBitSet, size: int): PRope =
# result := toRope('0x' + ToHex(bitSetToWord(cs, size), size * 2)) # result := toRope('0x' + ToHex(bitSetToWord(cs, size), size * 2))
proc genSetNode(p: BProc, n: PNode): PRope = proc genSetNode(p: BProc, n: PNode): PRope =
var var cs: TBitSet
cs: TBitSet var size = int(getSize(n.typ))
size, id: int
size = int(getSize(n.typ))
toBitSet(n, cs) toBitSet(n, cs)
if size > 8: if size > 8:
id = NodeTableTestOrSet(p.module.dataCache, n, gid) var id = NodeTableTestOrSet(p.module.dataCache, n, gid)
result = con("TMP", toRope(id)) result = con("TMP", toRope(id))
if id == gid: if id == gid:
# not found in cache: # not found in cache:
@ -201,16 +199,13 @@ proc genRefAssign(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
# end; # end;
# appf(p.s[cpsStmts], '$1 = $2;$n', [rdLoc(dest), rdLoc(src)]); # appf(p.s[cpsStmts], '$1 = $2;$n', [rdLoc(dest), rdLoc(src)]);
if canFormAcycle(dest.t): if canFormAcycle(dest.t):
UseMagic(p.module, "asgnRef") appcg(p.module, p.s[cpsStmts], "#asgnRef((void**) $1, $2);$n",
appf(p.s[cpsStmts], "asgnRef((void**) $1, $2);$n",
[addrLoc(dest), rdLoc(src)]) [addrLoc(dest), rdLoc(src)])
else: else:
UseMagic(p.module, "asgnRefNoCycle") appcg(p.module, p.s[cpsStmts], "#asgnRefNoCycle((void**) $1, $2);$n",
appf(p.s[cpsStmts], "asgnRefNoCycle((void**) $1, $2);$n",
[addrLoc(dest), rdLoc(src)]) [addrLoc(dest), rdLoc(src)])
else: else:
UseMagic(p.module, "unsureAsgnRef") appcg(p.module, p.s[cpsStmts], "#unsureAsgnRef((void**) $1, $2);$n",
appf(p.s[cpsStmts], "unsureAsgnRef((void**) $1, $2);$n",
[addrLoc(dest), rdLoc(src)]) [addrLoc(dest), rdLoc(src)])
proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) = 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): if not (needToCopy in flags):
genRefAssign(p, dest, src, flags) genRefAssign(p, dest, src, flags)
else: else:
useMagic(p.module, "genericSeqAssign") # BUGFIX appcg(p, cpsStmts, "#genericSeqAssign($1, $2, $3);$n",
appf(p.s[cpsStmts], "genericSeqAssign($1, $2, $3);$n",
[addrLoc(dest), rdLoc(src), genTypeInfo(p.module, dest.t)]) [addrLoc(dest), rdLoc(src), genTypeInfo(p.module, dest.t)])
of tyString: of tyString:
if not (needToCopy in flags): if not (needToCopy in flags):
genRefAssign(p, dest, src, flags) genRefAssign(p, dest, src, flags)
else: else:
useMagic(p.module, "copyString")
if (dest.s == OnStack) or not (optRefcGC in gGlobalOptions): 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: elif dest.s == OnHeap:
useMagic(p.module, "asgnRefNoCycle") appcg(p, cpsStmts, "#asgnRefNoCycle((void**) $1, #copyString($2));$n",
useMagic(p.module, "copyString") # BUGFIX
appf(p.s[cpsStmts], "asgnRefNoCycle((void**) $1, copyString($2));$n",
[addrLoc(dest), rdLoc(src)]) [addrLoc(dest), rdLoc(src)])
else: else:
useMagic(p.module, "unsureAsgnRef") appcg(p, cpsStmts, "#unsureAsgnRef((void**) $1, #copyString($2));$n",
useMagic(p.module, "copyString") # BUGFIX
appf(p.s[cpsStmts], "unsureAsgnRef((void**) $1, copyString($2));$n",
[addrLoc(dest), rdLoc(src)]) [addrLoc(dest), rdLoc(src)])
of tyTuple: of tyTuple:
if needsComplexAssignment(dest.t): if needsComplexAssignment(dest.t):
useMagic(p.module, "genericAssign") appcg(p, cpsStmts, "#genericAssign((void*)$1, (void*)$2, $3);$n",
appf(p.s[cpsStmts], "genericAssign((void*)$1, (void*)$2, $3);$n",
[addrLoc(dest), addrLoc(src), genTypeInfo(p.module, dest.t)]) [addrLoc(dest), addrLoc(src), genTypeInfo(p.module, dest.t)])
else: 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: of tyArray, tyArrayConstr:
if needsComplexAssignment(dest.t): if needsComplexAssignment(dest.t):
useMagic(p.module, "genericAssign") appcg(p, cpsStmts, "#genericAssign((void*)$1, (void*)$2, $3);$n",
appf(p.s[cpsStmts], "genericAssign((void*)$1, (void*)$2, $3);$n",
[addrLoc(dest), addrLoc(src), genTypeInfo(p.module, dest.t)]) [addrLoc(dest), addrLoc(src), genTypeInfo(p.module, dest.t)])
else: else:
appf(p.s[cpsStmts], appcg(p, cpsStmts,
"memcpy((void*)$1, (NIM_CONST void*)$2, sizeof($1));$n", "memcpy((void*)$1, (NIM_CONST void*)$2, sizeof($1));$n",
[rdLoc(dest), rdLoc(src)]) [rdLoc(dest), rdLoc(src)])
of tyObject: # XXX: check for subtyping? of tyObject: # XXX: check for subtyping?
if needsComplexAssignment(dest.t): if needsComplexAssignment(dest.t):
useMagic(p.module, "genericAssign") appcg(p, cpsStmts, "#genericAssign((void*)$1, (void*)$2, $3);$n",
appf(p.s[cpsStmts], "genericAssign((void*)$1, (void*)$2, $3);$n",
[addrLoc(dest), addrLoc(src), genTypeInfo(p.module, dest.t)]) [addrLoc(dest), addrLoc(src), genTypeInfo(p.module, dest.t)])
else: else:
appf(p.s[cpsStmts], "$1 = $2;$n", [rdLoc(dest), rdLoc(src)]) appcg(p, cpsStmts, "$1 = $2;$n", [rdLoc(dest), rdLoc(src)])
of tyOpenArray: of tyOpenArray:
# open arrays are always on the stack - really? What if a sequence is # open arrays are always on the stack - really? What if a sequence is
# passed to an open array? # passed to an open array?
if needsComplexAssignment(dest.t): if needsComplexAssignment(dest.t):
useMagic(p.module, "genericAssignOpenArray") appcg(p, cpsStmts, # XXX: is this correct for arrays?
appf(p.s[cpsStmts], # XXX: is this correct for arrays?
"genericAssignOpenArray((void*)$1, (void*)$2, $1Len0, $3);$n", "genericAssignOpenArray((void*)$1, (void*)$2, $1Len0, $3);$n",
[addrLoc(dest), addrLoc(src), genTypeInfo(p.module, dest.t)]) [addrLoc(dest), addrLoc(src), genTypeInfo(p.module, dest.t)])
else: else:
appf(p.s[cpsStmts], appcg(p, cpsStmts,
"memcpy((void*)$1, (NIM_CONST void*)$2, sizeof($1[0])*$1Len0);$n", "memcpy((void*)$1, (NIM_CONST void*)$2, sizeof($1[0])*$1Len0);$n",
[rdLoc(dest), rdLoc(src)]) [rdLoc(dest), rdLoc(src)])
of tySet: of tySet:
if mapType(ty) == ctArray: 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))]) [rdLoc(dest), rdLoc(src), toRope(getSize(dest.t))])
else: 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, of tyPtr, tyPointer, tyChar, tyBool, tyProc, tyEnum, tyCString,
tyInt..tyFloat128, tyRange: 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 & ')') else: InternalError("genAssignment(" & $ty.kind & ')')
proc expr(p: BProc, e: PNode, d: var TLoc) 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, {}) if lfNoDeepCopy in d.flags: genAssignment(p, d, s, {})
else: genAssignment(p, d, s, {needToCopy}) else: genAssignment(p, d, s, {needToCopy})
else: 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) = proc putIntoDest(p: BProc, d: var TLoc, t: PType, r: PRope) =
var a: TLoc var a: TLoc
@ -319,60 +304,53 @@ proc putIntoDest(p: BProc, d: var TLoc, t: PType, r: PRope) =
d.k = locExpr d.k = locExpr
d.t = getUniqueType(t) d.t = getUniqueType(t)
d.r = r 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 var a, b: TLoc
if (d.k != locNone): InternalError(e.info, "binaryStmt") if d.k != locNone: InternalError(e.info, "binaryStmt")
if magic != "": useMagic(p.module, magic)
InitLocExpr(p, e.sons[1], a) InitLocExpr(p, e.sons[1], a)
InitLocExpr(p, e.sons[2], b) 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 var a: TLoc
if (d.k != locNone): InternalError(e.info, "unaryStmt") if (d.k != locNone): InternalError(e.info, "unaryStmt")
if magic != "": useMagic(p.module, magic)
InitLocExpr(p, e.sons[1], a) 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 var a, b: TLoc
if (d.k != locNone): InternalError(e.info, "binaryStmtChar") if (d.k != locNone): InternalError(e.info, "binaryStmtChar")
if magic != "": useMagic(p.module, magic)
InitLocExpr(p, e.sons[1], a) InitLocExpr(p, e.sons[1], a)
InitLocExpr(p, e.sons[2], b) 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 var a, b: TLoc
if magic != "": useMagic(p.module, magic)
assert(e.sons[1].typ != nil) assert(e.sons[1].typ != nil)
assert(e.sons[2].typ != nil) assert(e.sons[2].typ != nil)
InitLocExpr(p, e.sons[1], a) InitLocExpr(p, e.sons[1], a)
InitLocExpr(p, e.sons[2], b) 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 var a, b: TLoc
if magic != "": useMagic(p.module, magic)
assert(e.sons[1].typ != nil) assert(e.sons[1].typ != nil)
assert(e.sons[2].typ != nil) assert(e.sons[2].typ != nil)
InitLocExpr(p, e.sons[1], a) InitLocExpr(p, e.sons[1], a)
InitLocExpr(p, e.sons[2], b) 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 var a: TLoc
if magic != "": useMagic(p.module, magic)
InitLocExpr(p, e.sons[1], a) 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 var a: TLoc
if magic != "": useMagic(p.module, magic)
InitLocExpr(p, e.sons[1], a) 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) = proc binaryArithOverflow(p: BProc, e: PNode, d: var TLoc, m: TMagic) =
const const
@ -389,22 +367,19 @@ proc binaryArithOverflow(p: BProc, e: PNode, d: var TLoc, m: TMagic) =
var t = skipTypes(e.typ, abstractRange) var t = skipTypes(e.typ, abstractRange)
if getSize(t) >= platform.IntSize: if getSize(t) >= platform.IntSize:
if optOverflowCheck in p.options: if optOverflowCheck in p.options:
useMagic(p.module, prc[m]) putIntoDest(p, d, e.typ, ropecg(p.module,
putIntoDest(p, d, e.typ, "#$1($2, $3)", [toRope(prc[m]), rdLoc(a), rdLoc(b)]))
ropef("$1($2, $3)", [toRope(prc[m]), rdLoc(a), rdLoc(b)]))
else: else:
putIntoDest(p, d, e.typ, ropef("(NI$4)($2 $1 $3)", [toRope(opr[m]), putIntoDest(p, d, e.typ, ropef("(NI$4)($2 $1 $3)", [toRope(opr[m]),
rdLoc(a), rdLoc(b), toRope(getSize(t) * 8)])) rdLoc(a), rdLoc(b), toRope(getSize(t) * 8)]))
else: else:
if optOverflowCheck in p.options: if optOverflowCheck in p.options:
useMagic(p.module, "raiseOverflow")
if (m == mModI) or (m == mDivI): if (m == mModI) or (m == mDivI):
useMagic(p.module, "raiseDivByZero") appcg(p, cpsStmts, "if (!$1) #raiseDivByZero();$n", [rdLoc(b)])
appf(p.s[cpsStmts], "if (!$1) raiseDivByZero();$n", [rdLoc(b)])
a.r = ropef("((NI)($2) $1 (NI)($3))", [toRope(opr[m]), rdLoc(a), 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) if d.k == locNone: getTemp(p, getSysType(tyInt), d)
genAssignment(p, d, a, {}) 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))]) [rdLoc(d), intLiteral(firstOrd(t)), intLiteral(lastOrd(t))])
d.t = e.typ d.t = e.typ
d.r = ropef("(NI$1)($2)", [toRope(getSize(t) * 8), rdLoc(d)]) 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) InitLocExpr(p, e.sons[1], a)
t = skipTypes(e.typ, abstractRange) t = skipTypes(e.typ, abstractRange)
if optOverflowCheck in p.options: if optOverflowCheck in p.options:
useMagic(p.module, "raiseOverflow") appcg(p, cpsStmts, "if ($1 == $2) #raiseOverflow();$n",
appf(p.s[cpsStmts], "if ($1 == $2) raiseOverflow();$n",
[rdLoc(a), intLiteral(firstOrd(t))]) [rdLoc(a), intLiteral(firstOrd(t))])
putIntoDest(p, d, e.typ, ropef(opr[m], [rdLoc(a), toRope(getSize(t) * 8)])) 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 id: int
it: PNode it: PNode
if optFieldCheck in p.options: if optFieldCheck in p.options:
useMagic(p.module, "raiseFieldError")
useMagic(p.module, "NimStringDesc")
ty = genRecordFieldAux(p, e.sons[0], d, a) ty = genRecordFieldAux(p, e.sons[0], d, a)
r = rdLoc(a) r = rdLoc(a)
f = e.sons[0].sons[1].sym 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) if id == gid: strLit = getStrLit(p.module, field.name.s)
else: strLit = con("TMP", toRope(id)) else: strLit = con("TMP", toRope(id))
if op.magic == mNot: if op.magic == mNot:
appf(p.s[cpsStmts], appcg(p, cpsStmts,
"if ($1) raiseFieldError(((NimStringDesc*) &$2));$n", "if ($1) #raiseFieldError(((#NimStringDesc*) &$2));$n",
[rdLoc(test), strLit]) [rdLoc(test), strLit])
else: else:
appf(p.s[cpsStmts], appcg(p, cpsStmts,
"if (!($1)) raiseFieldError(((NimStringDesc*) &$2));$n", "if (!($1)) #raiseFieldError(((#NimStringDesc*) &$2));$n",
[rdLoc(test), strLit]) [rdLoc(test), strLit])
appf(r, ".$1", [field.loc.r]) appf(r, ".$1", [field.loc.r])
putIntoDest(p, d, field.typ, 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 (optBoundsCheck in p.options):
if not isConstExpr(e.sons[1]): if not isConstExpr(e.sons[1]):
# semantic pass has already checked for const index expressions # semantic pass has already checked for const index expressions
useMagic(p.module, "raiseIndexError")
if firstOrd(ty) == 0: if firstOrd(ty) == 0:
if (firstOrd(b.t) < firstOrd(ty)) or (lastOrd(b.t) > lastOrd(ty)): 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))]) [rdCharLoc(b), intLiteral(lastOrd(ty))])
else: 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))]) [rdCharLoc(b), first, intLiteral(lastOrd(ty))])
if d.k == locNone: d.s = a.s if d.k == locNone: d.s = a.s
putIntoDest(p, d, elemType(skipTypes(ty, abstractVar)), 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[0], a)
initLocExpr(p, e.sons[1], b) # emit range check: initLocExpr(p, e.sons[1], b) # emit range check:
if (optBoundsCheck in p.options): if (optBoundsCheck in p.options):
useMagic(p.module, "raiseIndexError") appcg(p, cpsStmts, "if ((NU)($1) >= (NU)($2Len0)) #raiseIndexError();$n",
appf(p.s[cpsStmts], "if ((NU)($1) >= (NU)($2Len0)) raiseIndexError();$n",
[rdLoc(b), rdLoc(a)]) # BUGFIX: ``>=`` and not ``>``! [rdLoc(b), rdLoc(a)]) # BUGFIX: ``>=`` and not ``>``!
if d.k == locNone: d.s = a.s if d.k == locNone: d.s = a.s
putIntoDest(p, d, elemType(skipTypes(a.t, abstractVar)), 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}: if ty.kind in {tyRef, tyPtr}:
ty = skipTypes(ty.sons[0], abstractVarRange) # emit range check: ty = skipTypes(ty.sons[0], abstractVarRange) # emit range check:
if (optBoundsCheck in p.options): if (optBoundsCheck in p.options):
useMagic(p.module, "raiseIndexError")
if ty.kind == tyString: if ty.kind == tyString:
appf(p.s[cpsStmts], appcg(p, cpsStmts,
"if ((NU)($1) > (NU)($2->Sup.len)) raiseIndexError();$n", "if ((NU)($1) > (NU)($2->Sup.len)) #raiseIndexError();$n",
[rdLoc(b), rdLoc(a)]) [rdLoc(b), rdLoc(a)])
else: else:
appf(p.s[cpsStmts], appcg(p, cpsStmts,
"if ((NU)($1) >= (NU)($2->Sup.len)) raiseIndexError();$n", "if ((NU)($1) >= (NU)($2->Sup.len)) #raiseIndexError();$n",
[rdLoc(b), rdLoc(a)]) [rdLoc(b), rdLoc(a)])
if d.k == locNone: d.s = OnHeap if d.k == locNone: d.s = OnHeap
if skipTypes(a.t, abstractVar).kind in {tyRef, tyPtr}: 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) = proc genEcho(p: BProc, n: PNode) =
var a: TLoc var a: TLoc
useMagic(p.module, "rawEcho")
useMagic(p.module, "rawEchoNL")
for i in countup(1, sonsLen(n) - 1): for i in countup(1, sonsLen(n) - 1):
initLocExpr(p, n.sons[i], a) initLocExpr(p, n.sons[i], a)
appf(p.s[cpsStmts], "rawEcho($1);$n", [rdLoc(a)]) appcg(p, cpsStmts, "#rawEcho($1);$n", [rdLoc(a)])
app(p.s[cpsStmts], "rawEchoNL();" & tnl) appcg(p, cpsStmts, "#rawEchoNL();$n")
proc genCall(p: BProc, t: PNode, d: var TLoc) = proc genCall(p: BProc, t: PNode, d: var TLoc) =
var var
@ -879,7 +846,6 @@ proc genStrConcat(p: BProc, e: PNode, d: var TLoc) =
# asgn(s, tmp0); # asgn(s, tmp0);
# } # }
var a, tmp: TLoc var a, tmp: TLoc
useMagic(p.module, "rawNewString")
getTemp(p, e.typ, tmp) getTemp(p, e.typ, tmp)
var L = 0 var L = 0
var appends: PRope = nil var appends: PRope = nil
@ -889,16 +855,14 @@ proc genStrConcat(p: BProc, e: PNode, d: var TLoc) =
initLocExpr(p, e.sons[i + 1], a) initLocExpr(p, e.sons[i + 1], a)
if skipTypes(e.sons[i + 1].Typ, abstractVarRange).kind == tyChar: if skipTypes(e.sons[i + 1].Typ, abstractVarRange).kind == tyChar:
Inc(L) Inc(L)
useMagic(p.module, "appendChar") appcg(p.module, appends, "#appendChar($1, $2);$n", [tmp.r, rdLoc(a)])
appf(appends, "appendChar($1, $2);$n", [tmp.r, rdLoc(a)])
else: else:
if e.sons[i + 1].kind in {nkStrLit..nkTripleStrLit}: if e.sons[i + 1].kind in {nkStrLit..nkTripleStrLit}:
Inc(L, len(e.sons[i + 1].strVal)) Inc(L, len(e.sons[i + 1].strVal))
else: else:
appf(lens, "$1->Sup.len + ", [rdLoc(a)]) appf(lens, "$1->Sup.len + ", [rdLoc(a)])
useMagic(p.module, "appendString") appcg(p.module, appends, "#appendString($1, $2);$n", [tmp.r, rdLoc(a)])
appf(appends, "appendString($1, $2);$n", [tmp.r, rdLoc(a)]) appcg(p, cpsStmts, "$1 = #rawNewString($2$3);$n", [tmp.r, lens, toRope(L)])
appf(p.s[cpsStmts], "$1 = rawNewString($2$3);$n", [tmp.r, lens, toRope(L)])
app(p.s[cpsStmts], appends) app(p.s[cpsStmts], appends)
if d.k == locNone: if d.k == locNone:
d = tmp d = tmp
@ -922,7 +886,6 @@ proc genStrAppend(p: BProc, e: PNode, d: var TLoc) =
L: int L: int
appends, lens: PRope appends, lens: PRope
assert(d.k == locNone) assert(d.k == locNone)
useMagic(p.module, "resizeString")
L = 0 L = 0
appends = nil appends = nil
lens = nil lens = nil
@ -932,16 +895,16 @@ proc genStrAppend(p: BProc, e: PNode, d: var TLoc) =
initLocExpr(p, e.sons[i + 2], a) initLocExpr(p, e.sons[i + 2], a)
if skipTypes(e.sons[i + 2].Typ, abstractVarRange).kind == tyChar: if skipTypes(e.sons[i + 2].Typ, abstractVarRange).kind == tyChar:
Inc(L) Inc(L)
useMagic(p.module, "appendChar") appcg(p.module, appends, "#appendChar($1, $2);$n",
appf(appends, "appendChar($1, $2);$n", [rdLoc(dest), rdLoc(a)]) [rdLoc(dest), rdLoc(a)])
else: else:
if e.sons[i + 2].kind in {nkStrLit..nkTripleStrLit}: if e.sons[i + 2].kind in {nkStrLit..nkTripleStrLit}:
Inc(L, len(e.sons[i + 2].strVal)) Inc(L, len(e.sons[i + 2].strVal))
else: else:
appf(lens, "$1->Sup.len + ", [rdLoc(a)]) appf(lens, "$1->Sup.len + ", [rdLoc(a)])
useMagic(p.module, "appendString") appcg(p.module, appends, "#appendString($1, $2);$n",
appf(appends, "appendString($1, $2);$n", [rdLoc(dest), rdLoc(a)]) [rdLoc(dest), rdLoc(a)])
appf(p.s[cpsStmts], "$1 = resizeString($1, $2$3);$n", appcg(p, cpsStmts, "$1 = #resizeString($1, $2$3);$n",
[rdLoc(dest), lens, toRope(L)]) [rdLoc(dest), lens, toRope(L)])
app(p.s[cpsStmts], appends) 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 = (typeof seq) incrSeq(&seq->Sup, sizeof(x));
# seq->data[seq->len-1] = x; # seq->data[seq->len-1] = x;
var a, b, dest: TLoc var a, b, dest: TLoc
useMagic(p.module, "incrSeq")
InitLocExpr(p, e.sons[1], a) InitLocExpr(p, e.sons[1], a)
InitLocExpr(p, e.sons[2], b) 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[1].typ, abstractVar)),
getTypeDesc(p.module, skipTypes(e.sons[2].Typ, abstractVar))]) getTypeDesc(p.module, skipTypes(e.sons[2].Typ, abstractVar))])
initLoc(dest, locExpr, b.t, OnHeap) 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)]) appf(p.s[cpsStmts], "$1.m_type = $2;$n", [r, genTypeInfo(p.module, t)])
of frEmbedded: of frEmbedded:
# worst case for performance: # worst case for performance:
useMagic(p.module, "objectInit")
if takeAddr: r = addrLoc(a) if takeAddr: r = addrLoc(a)
else: r = rdLoc(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) = proc genNew(p: BProc, e: PNode) =
var var
a, b: TLoc a, b: TLoc
reftype, bt: PType reftype, bt: PType
useMagic(p.module, "newObj")
refType = skipTypes(e.sons[1].typ, abstractVarRange) refType = skipTypes(e.sons[1].typ, abstractVarRange)
InitLocExpr(p, e.sons[1], a) InitLocExpr(p, e.sons[1], a)
initLoc(b, locExpr, a.t, OnHeap) 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), genTypeInfo(p.module, refType),
getTypeDesc(p.module, skipTypes(reftype.sons[0], abstractRange))]) getTypeDesc(p.module, skipTypes(reftype.sons[0], abstractRange))])
genAssignment(p, a, b, {}) # set the object type: genAssignment(p, a, b, {}) # set the object type:
@ -1001,13 +963,13 @@ proc genNewSeq(p: BProc, e: PNode) =
var var
a, b, c: TLoc a, b, c: TLoc
seqtype: PType seqtype: PType
useMagic(p.module, "newSeq")
seqType = skipTypes(e.sons[1].typ, abstractVarRange) seqType = skipTypes(e.sons[1].typ, abstractVarRange)
InitLocExpr(p, e.sons[1], a) InitLocExpr(p, e.sons[1], a)
InitLocExpr(p, e.sons[2], b) InitLocExpr(p, e.sons[2], b)
initLoc(c, locExpr, a.t, OnHeap) initLoc(c, locExpr, a.t, OnHeap)
c.r = ropef("($1) newSeq($2, $3)", [getTypeDesc(p.module, seqtype), c.r = ropecg(p.module, "($1) #newSeq($2, $3)", [
genTypeInfo(p.module, seqType), rdLoc(b)]) getTypeDesc(p.module, seqtype),
genTypeInfo(p.module, seqType), rdLoc(b)])
genAssignment(p, a, c, {}) genAssignment(p, a, c, {})
proc genIs(p: BProc, x: PNode, typ: PType, d: var TLoc) = 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 r, nilcheck: PRope
initLocExpr(p, x, a) initLocExpr(p, x, a)
dest = skipTypes(typ, abstractPtrs) dest = skipTypes(typ, abstractPtrs)
useMagic(p.module, "isObj")
r = rdLoc(a) r = rdLoc(a)
nilCheck = nil nilCheck = nil
t = skipTypes(a.t, abstractInst) t = skipTypes(a.t, abstractInst)
@ -1030,10 +991,10 @@ proc genIs(p: BProc, x: PNode, typ: PType, d: var TLoc) =
app(r, ".Sup") app(r, ".Sup")
t = skipTypes(t.sons[0], abstractInst) t = skipTypes(t.sons[0], abstractInst)
if nilCheck != nil: 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)]) [nilCheck, r, genTypeInfo(p.module, dest)])
else: 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) putIntoDest(p, d, getSysType(tyBool), r)
proc genIs(p: BProc, n: PNode, d: var TLoc) = proc genIs(p: BProc, n: PNode, d: var TLoc) =
@ -1045,7 +1006,6 @@ proc genNewFinalize(p: BProc, e: PNode) =
refType, bt: PType refType, bt: PType
ti: PRope ti: PRope
oldModule: BModule oldModule: BModule
useMagic(p.module, "newObj")
refType = skipTypes(e.sons[1].typ, abstractVarRange) refType = skipTypes(e.sons[1].typ, abstractVarRange)
InitLocExpr(p, e.sons[1], a) InitLocExpr(p, e.sons[1], a)
# This is a little hack: # This is a little hack:
@ -1057,7 +1017,8 @@ proc genNewFinalize(p: BProc, e: PNode) =
initLoc(b, locExpr, a.t, OnHeap) initLoc(b, locExpr, a.t, OnHeap)
ti = genTypeInfo(p.module, refType) ti = genTypeInfo(p.module, refType)
appf(gNimDat.s[cfsTypeInit3], "$1->finalizer = (void*)$2;$n", [ti, rdLoc(f)]) 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))]) ti, getTypeDesc(p.module, skipTypes(reftype.sons[0], abstractRange))])
genAssignment(p, a, b, {}) # set the object type: genAssignment(p, a, b, {}) # set the object type:
bt = skipTypes(refType.sons[0], abstractRange) 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) var t = skipTypes(e.sons[1].typ, abstractVarRange)
case t.kind case t.kind
of tyInt..tyInt64: of tyInt..tyInt64:
UseMagic(p.module, "reprInt") putIntoDest(p, d, e.typ, ropecg(p.module, "#reprInt($1)", [rdLoc(a)]))
putIntoDest(p, d, e.typ, ropef("reprInt($1)", [rdLoc(a)]))
of tyFloat..tyFloat128: of tyFloat..tyFloat128:
UseMagic(p.module, "reprFloat") putIntoDest(p, d, e.typ, ropecg(p.module, "#reprFloat($1)", [rdLoc(a)]))
putIntoDest(p, d, e.typ, ropef("reprFloat($1)", [rdLoc(a)]))
of tyBool: of tyBool:
UseMagic(p.module, "reprBool") putIntoDest(p, d, e.typ, ropecg(p.module, "#reprBool($1)", [rdLoc(a)]))
putIntoDest(p, d, e.typ, ropef("reprBool($1)", [rdLoc(a)]))
of tyChar: of tyChar:
UseMagic(p.module, "reprChar") putIntoDest(p, d, e.typ, ropecg(p.module, "#reprChar($1)", [rdLoc(a)]))
putIntoDest(p, d, e.typ, ropef("reprChar($1)", [rdLoc(a)]))
of tyEnum, tyOrdinal: of tyEnum, tyOrdinal:
UseMagic(p.module, "reprEnum")
putIntoDest(p, d, e.typ, 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: of tyString:
UseMagic(p.module, "reprStr") putIntoDest(p, d, e.typ, ropecg(p.module, "#reprStr($1)", [rdLoc(a)]))
putIntoDest(p, d, e.typ, ropef("reprStr($1)", [rdLoc(a)]))
of tySet: of tySet:
useMagic(p.module, "reprSet") putIntoDest(p, d, e.typ, ropecg(p.module, "#reprSet($1, $2)", [
putIntoDest(p, d, e.typ, rdLoc(a), genTypeInfo(p.module, t)]))
ropef("reprSet($1, $2)", [rdLoc(a), genTypeInfo(p.module, t)]))
of tyOpenArray: of tyOpenArray:
useMagic(p.module, "reprOpenArray")
var b: TLoc var b: TLoc
case a.t.kind case a.t.kind
of tyOpenArray: putIntoDest(p, b, e.typ, rdLoc(a)) 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, putIntoDest(p, b, e.typ,
ropef("$1, $2", [rdLoc(a), toRope(lengthOrd(a.t))])) ropef("$1, $2", [rdLoc(a), toRope(lengthOrd(a.t))]))
else: InternalError(e.sons[0].info, "genRepr()") 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))])) genTypeInfo(p.module, elemType(t))]))
of tyCString, tyArray, tyArrayConstr, tyRef, tyPtr, tyPointer, tyNil, of tyCString, tyArray, tyArrayConstr, tyRef, tyPtr, tyPointer, tyNil,
tySequence: tySequence:
useMagic(p.module, "reprAny")
putIntoDest(p, d, e.typ, 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: else:
useMagic(p.module, "reprAny") putIntoDest(p, d, e.typ, ropecg(p.module, "#reprAny($1, $2)",
putIntoDest(p, d, e.typ, ropef("reprAny($1, $2)",
[addrLoc(a), genTypeInfo(p.module, t)])) [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 var a: TLoc
InitLocExpr(p, n.sons[1], a) InitLocExpr(p, n.sons[1], a)
UseMagic(p.module, magic) a.r = ropecg(p.module, frmt, [rdLoc(a)])
a.r = ropef(frmt, [rdLoc(a)])
if d.k == locNone: getTemp(p, n.typ, d) if d.k == locNone: getTemp(p, n.typ, d)
genAssignment(p, d, a, {}) genAssignment(p, d, a, {})
@ -1127,14 +1080,14 @@ proc genArrayLen(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
case typ.kind case typ.kind
of tyOpenArray: of tyOpenArray:
while e.sons[1].kind == nkPassAsOpenArray: e.sons[1] = e.sons[1].sons[0] while e.sons[1].kind == nkPassAsOpenArray: e.sons[1] = e.sons[1].sons[0]
if op == mHigh: unaryExpr(p, e, d, "", "($1Len0-1)") if op == mHigh: unaryExpr(p, e, d, "($1Len0-1)")
else: unaryExpr(p, e, d, "", "$1Len0") else: unaryExpr(p, e, d, "$1Len0")
of tyCstring: of tyCstring:
if op == mHigh: unaryExpr(p, e, d, "", "(strlen($1)-1)") if op == mHigh: unaryExpr(p, e, d, "(strlen($1)-1)")
else: unaryExpr(p, e, d, "", "strlen($1)") else: unaryExpr(p, e, d, "strlen($1)")
of tyString, tySequence: of tyString, tySequence:
if op == mHigh: unaryExpr(p, e, d, "", "($1->Sup.len-1)") if op == mHigh: unaryExpr(p, e, d, "($1->Sup.len-1)")
else: unaryExpr(p, e, d, "", "$1->Sup.len") else: unaryExpr(p, e, d, "$1->Sup.len")
of tyArray, tyArrayConstr: of tyArray, tyArrayConstr:
# YYY: length(sideeffect) is optimized away incorrectly? # YYY: length(sideeffect) is optimized away incorrectly?
if op == mHigh: putIntoDest(p, d, e.typ, toRope(lastOrd(Typ))) 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) = proc genSetLengthSeq(p: BProc, e: PNode, d: var TLoc) =
var a, b: TLoc var a, b: TLoc
assert(d.k == locNone) assert(d.k == locNone)
useMagic(p.module, "setLengthSeq")
InitLocExpr(p, e.sons[1], a) InitLocExpr(p, e.sons[1], a)
InitLocExpr(p, e.sons[2], b) InitLocExpr(p, e.sons[2], b)
var t = skipTypes(e.sons[1].typ, abstractVar) 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), rdLoc(a), rdLoc(b), getTypeDesc(p.module, t),
getTypeDesc(p.module, t.sons[0])]) getTypeDesc(p.module, t.sons[0])])
proc genSetLengthStr(p: BProc, e: PNode, d: var TLoc) = 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) = proc genSwap(p: BProc, e: PNode, d: var TLoc) =
# swap(a, b) --> # 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(" & binaryStmtInExcl(p, e, d, "$1 &= ~(1 << ((" & ts & ")($2) % (sizeof(" &
ts & ")*8)));$n") ts & ")*8)));$n")
of mCard: of mCard:
if size <= 4: unaryExprChar(p, e, d, "countBits32", "countBits32($1)") if size <= 4: unaryExprChar(p, e, d, "#countBits32($1)")
else: unaryExprChar(p, e, d, "countBits64", "countBits64($1)") else: unaryExprChar(p, e, d, "#countBits64($1)")
of mLtSet: binaryExprChar(p, e, d, "", "(($1 & ~ $2 ==0)&&($1 != $2))") of mLtSet: binaryExprChar(p, e, d, "(($1 & ~ $2 ==0)&&($1 != $2))")
of mLeSet: binaryExprChar(p, e, d, "", "(($1 & ~ $2)==0)") of mLeSet: binaryExprChar(p, e, d, "(($1 & ~ $2)==0)")
of mEqSet: binaryExpr(p, e, d, "", "($1 == $2)") of mEqSet: binaryExpr(p, e, d, "($1 == $2)")
of mMulSet: binaryExpr(p, e, d, "", "($1 & $2)") of mMulSet: binaryExpr(p, e, d, "($1 & $2)")
of mPlusSet: binaryExpr(p, e, d, "", "($1 | $2)") of mPlusSet: binaryExpr(p, e, d, "($1 | $2)")
of mMinusSet: binaryExpr(p, e, d, "", "($1 & ~ $2)") of mMinusSet: binaryExpr(p, e, d, "($1 & ~ $2)")
of mSymDiffSet: binaryExpr(p, e, d, "", "($1 ^ $2)") of mSymDiffSet: binaryExpr(p, e, d, "($1 ^ $2)")
of mInSet: of mInSet:
genInOp(p, e, d) genInOp(p, e, d)
else: internalError(e.info, "genSetOp()") else: internalError(e.info, "genSetOp()")
@ -1273,7 +1225,7 @@ proc genSetOp(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
case op case op
of mIncl: binaryStmtInExcl(p, e, d, "$1[$2/8] |=(1<<($2%8));$n") 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 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: of mLtSet, mLeSet:
getTemp(p, getSysType(tyInt), i) # our counter getTemp(p, getSysType(tyInt), i) # our counter
initLocExpr(p, e.sons[1], a) 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], appf(p.s[cpsStmts], lookupOpr[op],
[rdLoc(i), toRope(size), rdLoc(d), rdLoc(a), rdLoc(b)]) [rdLoc(i), toRope(size), rdLoc(d), rdLoc(a), rdLoc(b)])
of mEqSet: 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: of mMulSet, mPlusSet, mMinusSet, mSymDiffSet:
# we inline the simple for loop for better code generation: # we inline the simple for loop for better code generation:
getTemp(p, getSysType(tyInt), i) # our counter 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") else: internalError(e.info, "genSetOp")
proc genOrd(p: BProc, e: PNode, d: var TLoc) = 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) = proc genCast(p: BProc, e: PNode, d: var TLoc) =
const 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) = proc genRangeChck(p: BProc, n: PNode, d: var TLoc, magic: string) =
var a: TLoc var a: TLoc
var dest = skipTypes(n.typ, abstractVar) var dest = skipTypes(n.typ, abstractVar)
if not (optRangeCheck in p.options): if optRangeCheck notin p.options:
InitLocExpr(p, n.sons[0], a) InitLocExpr(p, n.sons[0], a)
putIntoDest(p, d, n.typ, ropef("(($1) ($2))", putIntoDest(p, d, n.typ, ropef("(($1) ($2))",
[getTypeDesc(p.module, dest), rdCharLoc(a)])) [getTypeDesc(p.module, dest), rdCharLoc(a)]))
else: else:
InitLocExpr(p, n.sons[0], a) InitLocExpr(p, n.sons[0], a)
useMagic(p.module, magic) putIntoDest(p, d, dest, ropecg(p.module, "(($1)#$5($2, $3, $4))", [
putIntoDest(p, d, dest, ropef("(($1)$5($2, $3, $4))", [
getTypeDesc(p.module, dest), rdCharLoc(a), getTypeDesc(p.module, dest), rdCharLoc(a),
genLiteral(p, n.sons[1], dest), genLiteral(p, n.sons[2], dest), genLiteral(p, n.sons[1], dest), genLiteral(p, n.sons[2], dest),
toRope(magic)])) toRope(magic)]))
@ -1356,17 +1307,16 @@ proc convStrToCStr(p: BProc, n: PNode, d: var TLoc) =
proc convCStrToStr(p: BProc, n: PNode, d: var TLoc) = proc convCStrToStr(p: BProc, n: PNode, d: var TLoc) =
var a: TLoc var a: TLoc
useMagic(p.module, "cstrToNimstr")
initLocExpr(p, n.sons[0], a) initLocExpr(p, n.sons[0], a)
putIntoDest(p, d, skipTypes(n.typ, abstractVar), 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) = proc genStrEquals(p: BProc, e: PNode, d: var TLoc) =
var x: TLoc var x: TLoc
var a = e.sons[1] var a = e.sons[1]
var b = e.sons[2] var b = e.sons[2]
if (a.kind == nkNilLit) or (b.kind == nkNilLit): 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 == ""): elif (a.kind in {nkStrLit..nkTripleStrLit}) and (a.strVal == ""):
initLocExpr(p, e.sons[2], x) initLocExpr(p, e.sons[2], x)
putIntoDest(p, d, e.typ, ropef("(($1) && ($1)->Sup.len == 0)", [rdLoc(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) initLocExpr(p, e.sons[1], x)
putIntoDest(p, d, e.typ, ropef("(($1) && ($1)->Sup.len == 0)", [rdLoc(x)])) putIntoDest(p, d, e.typ, ropef("(($1) && ($1)->Sup.len == 0)", [rdLoc(x)]))
else: 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) = proc genSeqConstr(p: BProc, t: PNode, d: var TLoc) =
var newSeq, arr: TLoc var newSeq, arr: TLoc
useMagic(p.module, "newSeq")
if d.k == locNone: if d.k == locNone:
getTemp(p, t.typ, d) getTemp(p, t.typ, d)
# generate call to newSeq before adding the elements per hand: # generate call to newSeq before adding the elements per hand:
initLoc(newSeq, locExpr, t.typ, OnHeap) 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))]) genTypeInfo(p.module, t.typ), intLiteral(sonsLen(t))])
genAssignment(p, d, newSeq, {afSrcIsNotNil}) genAssignment(p, d, newSeq, {afSrcIsNotNil})
for i in countup(0, sonsLen(t) - 1): 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 t.sons[1].typ = t.typ
genSeqConstr(p, t.sons[1], d) genSeqConstr(p, t.sons[1], d)
return return
useMagic(p.module, "newSeq")
if d.k == locNone: if d.k == locNone:
getTemp(p, t.typ, d) getTemp(p, t.typ, d)
# generate call to newSeq before adding the elements per hand: # generate call to newSeq before adding the elements per hand:
var L = int(lengthOrd(t.sons[1].typ)) var L = int(lengthOrd(t.sons[1].typ))
initLoc(newSeq, locExpr, t.typ, OnHeap) 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)]) genTypeInfo(p.module, t.typ), intLiteral(L)])
genAssignment(p, d, newSeq, {afSrcIsNotNil}) genAssignment(p, d, newSeq, {afSrcIsNotNil})
initLocExpr(p, t.sons[1], a) 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)", [ putIntoDest(p, d, e.typ, ropef("($2 $1 $3)", [
toRope(opr[m]), rdLoc(a), rdLoc(b)])) toRope(opr[m]), rdLoc(a), rdLoc(b)]))
if optNanCheck in p.options: if optNanCheck in p.options:
useMagic(p.module, "nanCheck") appcg(p, cpsStmts, "#nanCheck($1);$n", [rdLoc(d)])
appf(p.s[cpsStmts], "nanCheck($1);$n", [rdLoc(d)])
if optInfCheck in p.options: if optInfCheck in p.options:
useMagic(p.module, "infCheck") appcg(p, cpsStmts, "#infCheck($1);$n", [rdLoc(d)])
appf(p.s[cpsStmts], "infCheck($1);$n", [rdLoc(d)])
else: else:
binaryArith(p, e, d, m) 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 mSwap: genSwap(p, e, d)
of mPred: of mPred:
# XXX: range checking? # XXX: range checking?
if not (optOverflowCheck in p.Options): binaryExpr(p, e, d, "", "$1 - $2") if not (optOverflowCheck in p.Options): binaryExpr(p, e, d, "$1 - $2")
else: binaryExpr(p, e, d, "subInt", "subInt($1, $2)") else: binaryExpr(p, e, d, "#subInt($1, $2)")
of mSucc: of mSucc:
# XXX: range checking? # XXX: range checking?
if not (optOverflowCheck in p.Options): binaryExpr(p, e, d, "", "$1 + $2") if not (optOverflowCheck in p.Options): binaryExpr(p, e, d, "$1 + $2")
else: binaryExpr(p, e, d, "addInt", "addInt($1, $2)") else: binaryExpr(p, e, d, "#addInt($1, $2)")
of mInc: of mInc:
if not (optOverflowCheck in p.Options): 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: 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: else:
binaryStmt(p, e, d, "addInt", "$1 = addInt($1, $2);$n") binaryStmt(p, e, d, "$1 = #addInt($1, $2);$n")
of ast.mDec: of ast.mDec:
if not (optOverflowCheck in p.Options): 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: 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: 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 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 mAppendStrStr: genStrAppend(p, e, d)
of mAppendSeqElem: genSeqElemAppend(p, e, d) of mAppendSeqElem: genSeqElemAppend(p, e, d)
of mEqStr: genStrEquals(p, e, d) of mEqStr: genStrEquals(p, e, d)
of mLeStr: binaryExpr(p, e, d, "cmpStrings", "(cmpStrings($1, $2) <= 0)") of mLeStr: binaryExpr(p, e, d, "(#cmpStrings($1, $2) <= 0)")
of mLtStr: binaryExpr(p, e, d, "cmpStrings", "(cmpStrings($1, $2) < 0)") of mLtStr: binaryExpr(p, e, d, "(#cmpStrings($1, $2) < 0)")
of mIsNil: unaryExpr(p, e, d, "", "$1 == 0") of mIsNil: unaryExpr(p, e, d, "$1 == 0")
of mIntToStr: genDollar(p, e, d, "nimIntToStr", "nimIntToStr($1)") of mIntToStr: genDollar(p, e, d, "#nimIntToStr($1)")
of mInt64ToStr: genDollar(p, e, d, "nimInt64ToStr", "nimInt64ToStr($1)") of mInt64ToStr: genDollar(p, e, d, "#nimInt64ToStr($1)")
of mBoolToStr: genDollar(p, e, d, "nimBoolToStr", "nimBoolToStr($1)") of mBoolToStr: genDollar(p, e, d, "#nimBoolToStr($1)")
of mCharToStr: genDollar(p, e, d, "nimCharToStr", "nimCharToStr($1)") of mCharToStr: genDollar(p, e, d, "#nimCharToStr($1)")
of mFloatToStr: genDollar(p, e, d, "nimFloatToStr", "nimFloatToStr($1)") of mFloatToStr: genDollar(p, e, d, "#nimFloatToStr($1)")
of mCStrToStr: genDollar(p, e, d, "cstrToNimstr", "cstrToNimstr($1)") of mCStrToStr: genDollar(p, e, d, "#cstrToNimstr($1)")
of mStrToStr: expr(p, e.sons[1], d) of mStrToStr: expr(p, e.sons[1], d)
of mEnumToStr: genRepr(p, e, d) of mEnumToStr: genRepr(p, e, d)
of mAssert: of mAssert:
if (optAssert in p.Options): if (optAssert in p.Options):
useMagic(p.module, "internalAssert")
expr(p, e.sons[1], d) expr(p, e.sons[1], d)
line = toRope(toLinenumber(e.info)) line = toRope(toLinenumber(e.info))
filen = makeCString(ToFilename(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)]) [filen, line, rdLoc(d)])
of mIs: genIs(p, e, d) of mIs: genIs(p, e, d)
of mNew: genNew(p, e) 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 mOrd: genOrd(p, e, d)
of mLengthArray, mHigh, mLengthStr, mLengthSeq, mLengthOpenArray: of mLengthArray, mHigh, mLengthStr, mLengthSeq, mLengthOpenArray:
genArrayLen(p, e, d, op) genArrayLen(p, e, d, op)
of mGCref: unaryStmt(p, e, d, "nimGCref", "nimGCref($1);$n") of mGCref: unaryStmt(p, e, d, "#nimGCref($1);$n")
of mGCunref: unaryStmt(p, e, d, "nimGCunref", "nimGCunref($1);$n") of mGCunref: unaryStmt(p, e, d, "#nimGCunref($1);$n")
of mSetLengthStr: genSetLengthStr(p, e, d) of mSetLengthStr: genSetLengthStr(p, e, d)
of mSetLengthSeq: genSetLengthSeq(p, e, d) of mSetLengthSeq: genSetLengthSeq(p, e, d)
of mIncl, mExcl, mCard, mLtSet, mLeSet, mEqSet, mMulSet, mPlusSet, mMinusSet, 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) initLocExpr(p, n.sons[0], a)
dest = skipTypes(n.typ, abstractPtrs) dest = skipTypes(n.typ, abstractPtrs)
if (optObjCheck in p.options) and not (isPureObject(dest)): if (optObjCheck in p.options) and not (isPureObject(dest)):
useMagic(p.module, "chckObj")
r = rdLoc(a) r = rdLoc(a)
nilCheck = nil nilCheck = nil
t = skipTypes(a.t, abstractInst) t = skipTypes(a.t, abstractInst)
@ -1645,10 +1591,10 @@ proc upConv(p: BProc, n: PNode, d: var TLoc) =
app(r, ".Sup") app(r, ".Sup")
t = skipTypes(t.sons[0], abstractInst) t = skipTypes(t.sons[0], abstractInst)
if nilCheck != nil: 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)]) [nilCheck, r, genTypeInfo(p.module, dest)])
else: 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)]) [r, genTypeInfo(p.module, dest)])
if n.sons[0].typ.kind != tyObject: if n.sons[0].typ.kind != tyObject:
putIntoDest(p, d, n.typ, putIntoDest(p, d, n.typ,

View file

@ -1,7 +1,7 @@
# #
# #
# The Nimrod Compiler # The Nimrod Compiler
# (c) Copyright 2009 Andreas Rumpf # (c) Copyright 2010 Andreas Rumpf
# #
# See the file "copying.txt", included in this # See the file "copying.txt", included in this
# distribution, for details about the copyright. # distribution, for details about the copyright.
@ -20,9 +20,7 @@ proc genLineDir(p: BProc, t: PNode) =
[toRope(toFilename(t.info)), toRope(line)]) [toRope(toFilename(t.info)), toRope(line)])
if ({optStackTrace, optEndb} * p.Options == {optStackTrace, optEndb}) and if ({optStackTrace, optEndb} * p.Options == {optStackTrace, optEndb}) and
((p.prc == nil) or not (sfPure in p.prc.flags)): ((p.prc == nil) or not (sfPure in p.prc.flags)):
useMagic(p.module, "endb") # new: endb support appcg(p, cpsStmts, "#endb($1);$n", [toRope(line)])
appff(p.s[cpsStmts], "endb($1);$n", "call void @endb(%NI $1)$n",
[toRope(line)])
elif ({optLineTrace, optStackTrace} * p.Options == elif ({optLineTrace, optStackTrace} * p.Options ==
{optLineTrace, optStackTrace}) and {optLineTrace, optStackTrace}) and
((p.prc == nil) or not (sfPure in p.prc.flags)): ((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 = proc getRaiseFrmt(p: BProc): string =
if gCmd == cmdCompileToCpp: if gCmd == cmdCompileToCpp:
result = "throw nimException($1, $2);$n" result = "throw #nimException($1, $2);$n"
else: 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) = proc genRaiseStmt(p: BProc, t: PNode) =
genLineDir(p, t) genLineDir(p, t)
if t.sons[0] != nil: if t.sons[0] != nil:
if gCmd != cmdCompileToCpp: useMagic(p.module, "raiseException")
var a: TLoc var a: TLoc
InitLocExpr(p, t.sons[0], a) InitLocExpr(p, t.sons[0], a)
var e = rdLoc(a) var e = rdLoc(a)
var typ = skipTypes(t.sons[0].typ, abstractPtrs) 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: else:
# reraise the last exception: # reraise the last exception:
if gCmd == cmdCompileToCpp: if gCmd == cmdCompileToCpp:
app(p.s[cpsStmts], "throw;" & tnl) appcg(p, cpsStmts, "throw;" & tnl)
else: else:
useMagic(p.module, "reraiseException") appcg(p, cpsStmts, "#reraiseException();" & tnl)
app(p.s[cpsStmts], "reraiseException();" & tnl)
const const
stringCaseThreshold = 100000 stringCaseThreshold = 100000
@ -300,11 +295,11 @@ proc genCaseGenericBranch(p: BProc, b: PNode, e: TLoc,
if b.sons[i].kind == nkRange: if b.sons[i].kind == nkRange:
initLocExpr(p, b.sons[i].sons[0], x) initLocExpr(p, b.sons[i].sons[0], x)
initLocExpr(p, b.sons[i].sons[1], y) initLocExpr(p, b.sons[i].sons[1], y)
appf(p.s[cpsStmts], rangeFormat, appcg(p, cpsStmts, rangeFormat,
[rdCharLoc(e), rdCharLoc(x), rdCharLoc(y), labl]) [rdCharLoc(e), rdCharLoc(x), rdCharLoc(y), labl])
else: else:
initLocExpr(p, b.sons[i], x) 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) = proc genCaseSecondPass(p: BProc, t: PNode, labId: int) =
var Lend = getLabel(p) var Lend = getLabel(p)
@ -373,7 +368,7 @@ proc genCaseStringBranch(p: BProc, b: PNode, e: TLoc, labl: TLabel,
initLocExpr(p, b.sons[i], x) initLocExpr(p, b.sons[i], x)
assert(b.sons[i].kind in {nkStrLit..nkTripleStrLit}) assert(b.sons[i].kind in {nkStrLit..nkTripleStrLit})
j = int(hashString(b.sons[i].strVal) and high(branches)) 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]) [rdLoc(e), rdLoc(x), labl])
proc genStringCase(p: BProc, t: PNode) = proc genStringCase(p: BProc, t: PNode) =
@ -381,13 +376,11 @@ proc genStringCase(p: BProc, t: PNode) =
strings, bitMask, labId: int strings, bitMask, labId: int
a: TLoc a: TLoc
branches: TRopeSeq branches: TRopeSeq
useMagic(p.module, "eqStrings")
# count how many constant strings there are in the case: # count how many constant strings there are in the case:
strings = 0 strings = 0
for i in countup(1, sonsLen(t) - 1): for i in countup(1, sonsLen(t) - 1):
if t.sons[i].kind == nkOfBranch: inc(strings, sonsLen(t.sons[i]) - 1) if t.sons[i].kind == nkOfBranch: inc(strings, sonsLen(t.sons[i]) - 1)
if strings > stringCaseThreshold: if strings > stringCaseThreshold:
useMagic(p.module, "hashString")
bitMask = math.nextPowerOfTwo(strings) - 1 bitMask = math.nextPowerOfTwo(strings) - 1
newSeq(branches, bitMask + 1) newSeq(branches, bitMask + 1)
initLocExpr(p, t.sons[0], a) # fist pass: gnerate ifs+goto: initLocExpr(p, t.sons[0], a) # fist pass: gnerate ifs+goto:
@ -400,7 +393,7 @@ proc genStringCase(p: BProc, t: PNode) =
else: else:
# else statement: nothing to do yet # else statement: nothing to do yet
# but we reserved a label, which we use later # 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)]) [rdLoc(a), toRope(bitMask)])
for j in countup(0, high(branches)): for j in countup(0, high(branches)):
if branches[j] != nil: if branches[j] != nil:
@ -412,7 +405,7 @@ proc genStringCase(p: BProc, t: PNode) =
# third pass: generate statements # third pass: generate statements
genCaseSecondPass(p, t, labId) genCaseSecondPass(p, t, labId)
else: 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 = proc branchHasTooBigRange(b: PNode): bool =
for i in countup(0, sonsLen(b) - 2): for i in countup(0, sonsLen(b) - 2):
@ -588,11 +581,9 @@ proc genTryStmt(p: BProc, t: PNode) =
# longjmp(excHandler->context, sp.status); # longjmp(excHandler->context, sp.status);
genLineDir(p, t) genLineDir(p, t)
var safePoint = getTempName() var safePoint = getTempName()
useMagic(p.module, "TSafePoint") discard cgsym(p.module, "E_Base")
useMagic(p.module, "E_Base") appcg(p, cpsLocals, "#TSafePoint $1;$n", [safePoint])
useMagic(p.module, "excHandler") appcg(p, cpsStmts, "$1.prev = #excHandler;$n" & "excHandler = &$1;$n" &
appf(p.s[cpsLocals], "TSafePoint $1;$n", [safePoint])
appf(p.s[cpsStmts], "$1.prev = excHandler;$n" & "excHandler = &$1;$n" &
"$1.status = setjmp($1.context);$n", [safePoint]) "$1.status = setjmp($1.context);$n", [safePoint])
if optStackTrace in p.Options: if optStackTrace in p.Options:
app(p.s[cpsStmts], "framePtr = (TFrame*)&F;" & tnl) app(p.s[cpsStmts], "framePtr = (TFrame*)&F;" & tnl)
@ -627,9 +618,8 @@ proc genTryStmt(p: BProc, t: PNode) =
dec(p.nestedTryStmts) dec(p.nestedTryStmts)
if (i < length) and (t.sons[i].kind == nkFinally): if (i < length) and (t.sons[i].kind == nkFinally):
genStmts(p, t.sons[i].sons[0]) genStmts(p, t.sons[i].sons[0])
useMagic(p.module, "raiseException") appcg(p, cpsStmts, "if ($1.status != 0) { " &
appf(p.s[cpsStmts], "if ($1.status != 0) { " & "#raiseException($1.exc, $1.exc->name); }$n", [safePoint])
"raiseException($1.exc, $1.exc->name); }$n", [safePoint])
var var
breakPointId: int = 0 breakPointId: int = 0
@ -643,21 +633,17 @@ proc genBreakPoint(p: BProc, t: PNode) =
name = normalize(t.sons[1].strVal) name = normalize(t.sons[1].strVal)
else: else:
inc(breakPointId) inc(breakPointId)
name = "bp" & $(breakPointId) name = "bp" & $breakPointId
genLineDir(p, t) # BUGFIX genLineDir(p, t) # BUGFIX
appf(gBreakpoints, appcg(p.module, gBreakpoints,
"dbgRegisterBreakpoint($1, (NCSTRING)$2, (NCSTRING)$3);$n", [ "#dbgRegisterBreakpoint($1, (NCSTRING)$2, (NCSTRING)$3);$n", [
toRope(toLinenumber(t.info)), makeCString(toFilename(t.info)), toRope(toLinenumber(t.info)), makeCString(toFilename(t.info)),
makeCString(name)]) makeCString(name)])
proc genPragma(p: BProc, n: PNode) = proc genPragma(p: BProc, n: PNode) =
for i in countup(0, sonsLen(n) - 1): for i in countup(0, sonsLen(n) - 1):
var it = n.sons[i] var it = n.sons[i]
var key: PNode var key = if it.kind == nkExprColonExpr: it.sons[0] else: it
if it.kind == nkExprColonExpr:
key = it.sons[0]
else:
key = it
if key.kind == nkIdent: if key.kind == nkIdent:
case whichKeyword(key.ident) case whichKeyword(key.ident)
of wBreakpoint: of wBreakpoint:
@ -667,8 +653,7 @@ proc genPragma(p: BProc, n: PNode) =
# we need to keep track of ``deadCodeElim`` pragma # we need to keep track of ``deadCodeElim`` pragma
if (sfDeadCodeElim in p.module.module.flags): if (sfDeadCodeElim in p.module.module.flags):
addPendingModule(p.module) addPendingModule(p.module)
else: else: nil
nil
proc genAsgn(p: BProc, e: PNode) = proc genAsgn(p: BProc, e: PNode) =
var a: TLoc var a: TLoc

View file

@ -248,7 +248,7 @@ proc getSimpleTypeDesc(m: BModule, typ: PType): PRope =
internalError(typ.sym.info, "getSimpleTypeDesc: " & $(getSize(typ))) internalError(typ.sym.info, "getSimpleTypeDesc: " & $(getSize(typ)))
result = nil result = nil
of tyString: of tyString:
useMagic(m, "NimStringDesc") discard cgsym(m, "NimStringDesc")
result = typeNameOrLiteral(typ, "NimStringDesc*") result = typeNameOrLiteral(typ, "NimStringDesc*")
of tyCstring: result = typeNameOrLiteral(typ, "NCSTRING") of tyCstring: result = typeNameOrLiteral(typ, "NCSTRING")
of tyBool: result = typeNameOrLiteral(typ, "NIM_BOOL") of tyBool: result = typeNameOrLiteral(typ, "NIM_BOOL")
@ -342,20 +342,19 @@ proc getRecordDesc(m: BModule, typ: PType, name: PRope,
# declare the record: # declare the record:
var hasField = false var hasField = false
if typ.kind == tyObject: if typ.kind == tyObject:
useMagic(m, "TNimType")
if typ.sons[0] == nil: if typ.sons[0] == nil:
if typ.sym != nil and sfPure in typ.sym.flags or tfFinal in typ.flags: 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: else:
result = ropef("struct $1 {$nTNimType* m_type;$n", [name]) result = ropecg(m, "struct $1 {$n#TNimType* m_type;$n", [name])
hasField = true hasField = true
elif gCmd == cmdCompileToCpp: elif gCmd == cmdCompileToCpp:
result = ropef("struct $1 : public $2 {$n", result = ropecg(m, "struct $1 : public $2 {$n",
[name, getTypeDescAux(m, typ.sons[0], check)]) [name, getTypeDescAux(m, typ.sons[0], check)])
hasField = true hasField = true
else: else:
result = ropef("struct $1 {$n $2 Sup;$n", result = ropecg(m, "struct $1 {$n $2 Sup;$n",
[name, getTypeDescAux(m, typ.sons[0], check)]) [name, getTypeDescAux(m, typ.sons[0], check)])
hasField = true hasField = true
else: else:
result = ropef("struct $1 {$n", [name]) 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) assert(CacheGetType(m.typeCache, t) == nil)
IdTablePut(m.typeCache, t, con(result, "*")) IdTablePut(m.typeCache, t, con(result, "*"))
if not isImportedType(t): if not isImportedType(t):
useMagic(m, "TGenericSeq")
if skipTypes(t.sons[0], abstractInst).kind != tyEmpty: if skipTypes(t.sons[0], abstractInst).kind != tyEmpty:
appf(m.s[cfsSeqTypes], "struct $2 {$n" & " TGenericSeq Sup;$n" & appcg(m, m.s[cfsSeqTypes],
" $1 data[SEQ_DECL_SIZE];$n" & "};$n", "struct $2 {$n" &
[getTypeDescAux(m, t.sons[0], check), result]) " #TGenericSeq Sup;$n" &
" $1 data[SEQ_DECL_SIZE];$n" &
"};$n", [getTypeDescAux(m, t.sons[0], check), result])
else: else:
result = toRope("TGenericSeq") result = toRope("TGenericSeq")
app(result, "*") app(result, "*")
@ -595,10 +595,9 @@ proc genObjectFields(m: BModule, typ: PType, n: PNode, expr: PRope) =
assert(n.sons[0].kind == nkSym) assert(n.sons[0].kind == nkSym)
field = n.sons[0].sym field = n.sons[0].sym
tmp = getTempName() tmp = getTempName()
useMagic(m, "chckNil")
appf(m.s[cfsTypeInit3], "$1.kind = 3;$n" & appf(m.s[cfsTypeInit3], "$1.kind = 3;$n" &
"$1.offset = offsetof($2, $3);$n" & "$1.typ = $4;$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, "$1.len = $7;$n", [expr, getTypeDesc(m, typ), field.loc.r,
genTypeInfo(m, field.typ), makeCString(field.name.s), genTypeInfo(m, field.typ), makeCString(field.name.s),
tmp, toRope(lengthOrd(field.typ))]) 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)") else: internalError(n.info, "genObjectFields(nkRecCase)")
of nkSym: of nkSym:
field = n.sym field = n.sym
useMagic(m, "chckNil")
appf(m.s[cfsTypeInit3], "$1.kind = 1;$n" & appf(m.s[cfsTypeInit3], "$1.kind = 1;$n" &
"$1.offset = offsetof($2, $3);$n" & "$1.typ = $4;$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)]) field.loc.r, genTypeInfo(m, field.typ), makeCString(field.name.s)])
else: internalError(n.info, "genObjectFields") else: internalError(n.info, "genObjectFields")
@ -658,10 +656,9 @@ proc genTupleInfo(m: BModule, typ: PType, name: PRope) =
a = typ.sons[i] a = typ.sons[i]
tmp2 = getNimNode(m) tmp2 = getNimNode(m)
appf(m.s[cfsTypeInit3], "$1[$2] = &$3;$n", [tmp, toRope(i), tmp2]) appf(m.s[cfsTypeInit3], "$1[$2] = &$3;$n", [tmp, toRope(i), tmp2])
useMagic(m, "chckNil")
appf(m.s[cfsTypeInit3], "$1.kind = 1;$n" & appf(m.s[cfsTypeInit3], "$1.kind = 1;$n" &
"$1.offset = offsetof($2, Field$3);$n" & "$1.typ = $4;$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)]) [tmp2, getTypeDesc(m, typ), toRope(i), genTypeInfo(m, a)])
appf(m.s[cfsTypeInit3], "$1.len = $2; $1.kind = 2; $1.sons = &$3[0];$n", appf(m.s[cfsTypeInit3], "$1.len = $2; $1.kind = 2; $1.sons = &$3[0];$n",
[expr, toRope(length), tmp]) [expr, toRope(length), tmp])
@ -735,8 +732,8 @@ proc genTypeInfo(m: BModule, typ: PType): PRope =
result = ropef("NTI$1", [toRope(id)]) result = ropef("NTI$1", [toRope(id)])
if not IntSetContainsOrIncl(m.typeInfoMarker, id): if not IntSetContainsOrIncl(m.typeInfoMarker, id):
# declare type information structures: # declare type information structures:
useMagic(m, "TNimType") discard cgsym(m, "TNimType")
useMagic(m, "TNimNode") discard cgsym(m, "TNimNode")
appf(m.s[cfsVars], "extern TNimType* $1; /* $2 */$n", appf(m.s[cfsVars], "extern TNimType* $1; /* $2 */$n",
[result, toRope(typeToString(t))]) [result, toRope(typeToString(t))])
if dataGenerated: return if dataGenerated: return

View file

@ -169,7 +169,68 @@ proc useHeader(m: BModule, sym: PSym) =
assert(sym.annex != nil) assert(sym.annex != nil)
discard lists.IncludeStr(m.headerFiles, getStr(sym.annex.path)) 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" include "ccgtypes.nim"
@ -274,26 +335,21 @@ proc assignLocalVar(p: BProc, s: PSym) =
proc assignGlobalVar(p: BProc, s: PSym) = proc assignGlobalVar(p: BProc, s: PSym) =
if s.loc.k == locNone: if s.loc.k == locNone:
fillLoc(s.loc, locGlobalVar, s.typ, mangleName(s), OnHeap) fillLoc(s.loc, locGlobalVar, s.typ, mangleName(s), OnHeap)
if gCmd == cmdCompileToLLVM: useHeader(p.module, s)
appf(p.module.s[cfsVars], "$1 = linkonce global $2 zeroinitializer$n", if lfNoDecl in s.loc.flags: return
[s.loc.r, getTypeDesc(p.module, s.loc.t)]) if sfImportc in s.flags: app(p.module.s[cfsVars], "extern ")
incl(s.loc.flags, lfIndirect) app(p.module.s[cfsVars], getTypeDesc(p.module, s.loc.t))
else: if sfRegister in s.flags: app(p.module.s[cfsVars], " register")
useHeader(p.module, s) if sfVolatile in s.flags: app(p.module.s[cfsVars], " volatile")
if lfNoDecl in s.loc.flags: return if sfThreadVar in s.flags: app(p.module.s[cfsVars], " NIM_THREADVAR")
if sfImportc in s.flags: app(p.module.s[cfsVars], "extern ") appf(p.module.s[cfsVars], " $1;$n", [s.loc.r])
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 == if {optStackTrace, optEndb} * p.module.module.options ==
{optStackTrace, optEndb}: {optStackTrace, optEndb}:
useMagic(p.module, "dbgRegisterGlobal") appcg(p.module, p.module.s[cfsDebugInit],
appff(p.module.s[cfsDebugInit], "dbgRegisterGlobal($1, &$2, $3);$n", "#dbgRegisterGlobal($1, &$2, $3);$n",
"call void @dbgRegisterGlobal(i8* $1, i8* $2, $4* $3)$n", [cstringLit( [cstringLit(p, p.module.s[cfsDebugInit],
p, p.module.s[cfsDebugInit], normalize(s.owner.name.s & '.' & s.name.s)), normalize(s.owner.name.s & '.' & s.name.s)),
s.loc.r, genTypeInfo(p.module, s.typ), getTypeDesc(p.module, "TNimType")]) s.loc.r, genTypeInfo(p.module, s.typ)])
proc iff(cond: bool, the, els: PRope): PRope = proc iff(cond: bool, the, els: PRope): PRope =
if cond: result = the if cond: result = the
@ -352,11 +408,11 @@ proc loadDynamicLib(m: BModule, lib: PLib) =
for i in countup(0, high(s)): for i in countup(0, high(s)):
inc(m.labels) inc(m.labels)
if i > 0: app(loadlib, "||") if i > 0: app(loadlib, "||")
appf(loadlib, "($1 = nimLoadLibrary((NimStringDesc*) &$2))$n", appcg(m, loadlib, "($1 = #nimLoadLibrary((#NimStringDesc*) &$2))$n",
[tmp, getStrLit(m, s[i])]) [tmp, getStrLit(m, s[i])])
appf(m.s[cfsDynLibInit], appcg(m, m.s[cfsDynLibInit],
"if (!($1)) nimLoadLibraryError((NimStringDesc*) &$2);$n", "if (!($1)) #nimLoadLibraryError((#NimStringDesc*) &$2);$n",
[loadlib, getStrLit(m, lib.path.strVal)]) [loadlib, getStrLit(m, lib.path.strVal)])
else: else:
var p = newProc(nil, m) var p = newProc(nil, m)
var dest: TLoc var dest: TLoc
@ -364,37 +420,38 @@ proc loadDynamicLib(m: BModule, lib: PLib) =
app(m.s[cfsVars], p.s[cpsLocals]) app(m.s[cfsVars], p.s[cpsLocals])
app(m.s[cfsDynLibInit], p.s[cpsInit]) app(m.s[cfsDynLibInit], p.s[cpsInit])
app(m.s[cfsDynLibInit], p.s[cpsStmts]) app(m.s[cfsDynLibInit], p.s[cpsStmts])
appf(m.s[cfsDynLibInit], appcg(m, m.s[cfsDynLibInit],
"if (!($1 = nimLoadLibrary($2))) nimLoadLibraryError($2);$n", "if (!($1 = #nimLoadLibrary($2))) #nimLoadLibraryError($2);$n",
[tmp, rdLoc(dest)]) [tmp, rdLoc(dest)])
useMagic(m, "nimLoadLibrary")
useMagic(m, "nimUnloadLibrary")
useMagic(m, "NimStringDesc")
useMagic(m, "nimLoadLibraryError")
if lib.name == nil: InternalError("loadDynamicLib") 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) = proc SymInDynamicLib(m: BModule, sym: PSym) =
var lib = sym.annex var lib = sym.annex
var extname = sym.loc.r var extname = sym.loc.r
loadDynamicLib(m, lib) loadDynamicLib(m, lib)
useMagic(m, "nimGetProcAddr") discard cgsym(m, "nimGetProcAddr")
if gCmd == cmdCompileToLLVM: incl(sym.loc.flags, lfIndirect) 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.loc.r = tmp # from now on we only need the internal name
sym.typ.sym = nil # generate a new name sym.typ.sym = nil # generate a new name
inc(m.labels, 2) inc(m.labels, 2)
appff(m.s[cfsDynLibInit], appf(m.s[cfsDynLibInit],
"$1 = ($2) nimGetProcAddr($3, $4);$n", "%MOC$5 = load i8* $3$n" & "$1 = ($2) nimGetProcAddr($3, $4);$n",
"%MOC$6 = call $2 @nimGetProcAddr(i8* %MOC$5, i8* $4)$n" & [tmp, getTypeDesc(m, sym.typ),
"store $2 %MOC$6, $2* $1$n", [tmp, getTypeDesc(m, sym.typ), lib.name, cstringLit(m, m.s[cfsDynLibInit], ropeToStr(extname))])
lib.name, cstringLit(m, m.s[cfsDynLibInit], ropeToStr(extname)),
toRope(m.labels), toRope(m.labels - 1)])
appff(m.s[cfsVars], "$2 $1;$n", appff(m.s[cfsVars], "$2 $1;$n",
"$1 = linkonce global $2 zeroinitializer$n", "$1 = linkonce global $2 zeroinitializer$n",
[sym.loc.r, getTypeDesc(m, sym.loc.t)]) [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) var sym = magicsys.getCompilerProc(name)
if sym != nil: if sym != nil:
case sym.kind case sym.kind
@ -402,8 +459,16 @@ proc UseMagic(m: BModule, name: string) =
of skVar: genVarPrototype(m, sym) of skVar: genVarPrototype(m, sym)
of skType: discard getTypeDesc(m, sym.typ) of skType: discard getTypeDesc(m, sym.typ)
else: InternalError("useMagic: " & name) else: InternalError("useMagic: " & name)
elif not (sfSystemModule in m.module.flags): else:
rawMessage(errSystemNeeds, name) # don't be too picky here # 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) = proc generateHeaders(m: BModule) =
app(m.s[cfsHeaders], "#include \"nimbase.h\"" & tnl & tnl) app(m.s[cfsHeaders], "#include \"nimbase.h\"" & tnl & tnl)
@ -418,7 +483,7 @@ proc generateHeaders(m: BModule) =
proc getFrameDecl(p: BProc) = proc getFrameDecl(p: BProc) =
var slots: PRope var slots: PRope
if p.frameLen > 0: if p.frameLen > 0:
useMagic(p.module, "TVarSlot") discard cgsym(p.module, "TVarSlot")
slots = ropeff(" TVarSlot s[$1];$n", ", [$1 x %TVarSlot]", slots = ropeff(" TVarSlot s[$1];$n", ", [$1 x %TVarSlot]",
[toRope(p.frameLen)]) [toRope(p.frameLen)])
else: else:
@ -507,7 +572,7 @@ proc genProcAux(m: BModule, prc: PSym) =
if (optProfiler in prc.options) and (gCmd != cmdCompileToLLVM): if (optProfiler in prc.options) and (gCmd != cmdCompileToLLVM):
if gProcProfile >= 64 * 1024: if gProcProfile >= 64 * 1024:
InternalError(prc.info, "too many procedures for profiling") InternalError(prc.info, "too many procedures for profiling")
useMagic(m, "profileData") discard cgsym(m, "profileData")
app(p.s[cpsLocals], "ticks NIM_profilingStart;" & tnl) app(p.s[cpsLocals], "ticks NIM_profilingStart;" & tnl)
if prc.loc.a < 0: if prc.loc.a < 0:
appf(m.s[cfsDebugInit], "profileData[$1].procname = $2;$n", [ 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 lfDynamicLib in sym.loc.Flags:
if (sym.owner.id != m.module.id) and if (sym.owner.id != m.module.id) and
not intSetContainsOrIncl(m.declaredThings, sym.id): not intSetContainsOrIncl(m.declaredThings, sym.id):
appff(m.s[cfsVars], "extern $1 Dl_$2;$n", appff(m.s[cfsVars], "extern $1 $2;$n",
"@Dl_$2 = linkonce global $1 zeroinitializer$n", "@$2 = linkonce global $1 zeroinitializer$n",
[getTypeDesc(m, sym.loc.t), toRope(sym.id)]) [getTypeDesc(m, sym.loc.t), mangleDynLibProc(sym)])
if gCmd == cmdCompileToLLVM: incl(sym.loc.flags, lfIndirect) if gCmd == cmdCompileToLLVM: incl(sym.loc.flags, lfIndirect)
else: else:
if not IntSetContainsOrIncl(m.declaredProtos, sym.id): if not IntSetContainsOrIncl(m.declaredProtos, sym.id):
@ -679,7 +744,7 @@ proc genMainProc(m: BModule) =
" i8* %lpvReserved) {$n" & " i8* %lpvReserved) {$n" &
" call void @NimMain()$n" & " ret i32 1$n" & "}$n" " call void @NimMain()$n" & " ret i32 1$n" & "}$n"
var nimMain, otherMain: TFormatStr var nimMain, otherMain: TFormatStr
useMagic(m, "setStackBottom") discard cgsym(m, "setStackBottom")
if (platform.targetOS == osWindows) and if (platform.targetOS == osWindows) and
(gGlobalOptions * {optGenGuiApp, optGenDynLib} != {}): (gGlobalOptions * {optGenGuiApp, optGenDynLib} != {}):
if optGenGuiApp in gGlobalOptions: if optGenGuiApp in gGlobalOptions:
@ -704,7 +769,7 @@ proc genMainProc(m: BModule) =
else: else:
nimMain = PosixNimMain nimMain = PosixNimMain
otherMain = PosixCMain otherMain = PosixCMain
if gBreakpoints != nil: useMagic(m, "dbgRegisterBreakpoint") if gBreakpoints != nil: discard cgsym(m, "dbgRegisterBreakpoint")
inc(m.labels) inc(m.labels)
appf(m.s[cfsProcs], nimMain, [gBreakpoints, mainModInit, toRope(m.labels)]) appf(m.s[cfsProcs], nimMain, [gBreakpoints, mainModInit, toRope(m.labels)])
if not (optNoMain in gGlobalOptions): appf(m.s[cfsProcs], otherMain, []) 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", prc = ropeff("N_NOINLINE(void, $1)(void) {$n",
"define void $1() noinline {$n", [initname]) "define void $1() noinline {$n", [initname])
if m.typeNodes > 0: if m.typeNodes > 0:
useMagic(m, "TNimNode") appcg(m, m.s[cfsTypeInit1], "static #TNimNode $1[$2];$n",
appff(m.s[cfsTypeInit1], "static TNimNode $1[$2];$n",
"$1 = private alloca [$2 x @TNimNode]$n",
[m.typeNodesName, toRope(m.typeNodes)]) [m.typeNodesName, toRope(m.typeNodes)])
if m.nimTypes > 0: if m.nimTypes > 0:
useMagic(m, "TNimType") appcg(m, m.s[cfsTypeInit1], "static #TNimType $1[$2];$n",
appff(m.s[cfsTypeInit1], "static TNimType $1[$2];$n",
"$1 = private alloca [$2 x @TNimType]$n",
[m.nimTypesName, toRope(m.nimTypes)]) [m.nimTypesName, toRope(m.nimTypes)])
if optStackTrace in m.initProc.options: if optStackTrace in m.initProc.options:
getFrameDecl(m.initProc) getFrameDecl(m.initProc)

View file

@ -1,7 +1,7 @@
# #
# #
# The Nimrod Compiler # The Nimrod Compiler
# (c) Copyright 2009 Andreas Rumpf # (c) Copyright 2010 Andreas Rumpf
# #
# See the file "copying.txt", included in this # See the file "copying.txt", included in this
# distribution, for details about the copyright. # distribution, for details about the copyright.
@ -69,8 +69,7 @@ proc getSysType(kind: TTypeKind): PType =
if result == nil: InternalError("type not found: " & $kind) if result == nil: InternalError("type not found: " & $kind)
proc getCompilerProc(name: string): PSym = proc getCompilerProc(name: string): PSym =
var ident: PIdent var ident = getIdent(name, getNormalizedHash(name))
ident = getIdent(name, getNormalizedHash(name))
result = StrTableGet(compilerprocs, ident) result = StrTableGet(compilerprocs, ident)
if result == nil: if result == nil:
result = StrTableGet(rodCompilerProcs, ident) result = StrTableGet(rodCompilerProcs, ident)

View file

@ -1,8 +1,9 @@
[Project] [Project]
Name: "Nimrod" Name: "Nimrod"
Version: "$version" Version: "$version"
OS: "linux;macosx;freebsd;netbsd;openbsd;solaris" ; Windows and i386 must be first!
CPU: "i386;amd64" # ;sparc;powerpc OS: "windows" ;linux;macosx;freebsd;netbsd;openbsd;solaris"
CPU: "i386" ;amd64" # ;sparc;powerpc
Authors: "Andreas Rumpf" Authors: "Andreas Rumpf"
Description: """This is the Nimrod Compiler. Nimrod is a new statically typed, Description: """This is the Nimrod Compiler. Nimrod is a new statically typed,
imperative programming language, that supports procedural, functional, object imperative programming language, that supports procedural, functional, object

View file

@ -21,13 +21,13 @@ const
procPragmas* = {FirstCallConv..LastCallConv, wImportc, wExportc, wNodecl, procPragmas* = {FirstCallConv..LastCallConv, wImportc, wExportc, wNodecl,
wMagic, wNosideEffect, wSideEffect, wNoreturn, wDynLib, wHeader, wMagic, wNosideEffect, wSideEffect, wNoreturn, wDynLib, wHeader,
wCompilerProc, wPure, wProcVar, wDeprecated, wVarargs, wCompileTime, wMerge, wCompilerProc, wPure, wProcVar, wDeprecated, wVarargs, wCompileTime, wMerge,
wBorrow} wBorrow, wExtern}
converterPragmas* = procPragmas converterPragmas* = procPragmas
methodPragmas* = procPragmas methodPragmas* = procPragmas
macroPragmas* = {FirstCallConv..LastCallConv, wImportc, wExportc, wNodecl, macroPragmas* = {FirstCallConv..LastCallConv, wImportc, wExportc, wNodecl,
wMagic, wNosideEffect, wCompilerProc, wDeprecated, wTypeCheck} wMagic, wNosideEffect, wCompilerProc, wDeprecated, wTypeCheck, wExtern}
iteratorPragmas* = {FirstCallConv..LastCallConv, wNosideEffect, wSideEffect, iteratorPragmas* = {FirstCallConv..LastCallConv, wNosideEffect, wSideEffect,
wImportc, wExportc, wNodecl, wMagic, wDeprecated, wBorrow} wImportc, wExportc, wNodecl, wMagic, wDeprecated, wBorrow, wExtern}
stmtPragmas* = {wChecks, wObjChecks, wFieldChecks, wRangechecks, wBoundchecks, stmtPragmas* = {wChecks, wObjChecks, wFieldChecks, wRangechecks, wBoundchecks,
wOverflowchecks, wNilchecks, wAssertions, wWarnings, wHints, wLinedir, wOverflowchecks, wNilchecks, wAssertions, wWarnings, wHints, wLinedir,
wStacktrace, wLinetrace, wOptimization, wHint, wWarning, wError, wFatal, wStacktrace, wLinetrace, wOptimization, wHint, wWarning, wError, wFatal,
@ -35,13 +35,15 @@ const
wCheckpoint, wPassL, wPassC, wDeadCodeElim, wDeprecated, wFloatChecks, wCheckpoint, wPassL, wPassC, wDeadCodeElim, wDeprecated, wFloatChecks,
wInfChecks, wNanChecks, wPragma} wInfChecks, wNanChecks, wPragma}
lambdaPragmas* = {FirstCallConv..LastCallConv, wImportc, wExportc, wNodecl, 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, typePragmas* = {wImportc, wExportc, wDeprecated, wMagic, wAcyclic, wNodecl,
wPure, wHeader, wCompilerProc, wFinal, wSize} wPure, wHeader, wCompilerProc, wFinal, wSize, wExtern}
fieldPragmas* = {wImportc, wExportc, wDeprecated} fieldPragmas* = {wImportc, wExportc, wDeprecated, wExtern}
varPragmas* = {wImportc, wExportc, wVolatile, wRegister, wThreadVar, wNodecl, varPragmas* = {wImportc, wExportc, wVolatile, wRegister, wThreadVar, wNodecl,
wMagic, wHeader, wDeprecated, wCompilerProc, wDynLib} wMagic, wHeader, wDeprecated, wCompilerProc, wDynLib, wExtern}
constPragmas* = {wImportc, wExportc, wHeader, wDeprecated, wMagic, wNodecl} constPragmas* = {wImportc, wExportc, wHeader, wDeprecated, wMagic, wNodecl,
wExtern}
procTypePragmas* = {FirstCallConv..LastCallConv, wVarargs, wNosideEffect} procTypePragmas* = {FirstCallConv..LastCallConv, wVarargs, wNosideEffect}
proc pragma*(c: PContext, sym: PSym, n: PNode, validPragmas: TSpecialWords) 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)
else: else:
invalidPragma(it) invalidPragma(it)
const proc setExternName(s: PSym, extname: string) =
FirstPragmaWord = wMagic s.loc.r = toRope(extname % s.name.s)
LastPragmaWord = wNoconv
proc MakeExternImport(s: PSym, extname: string) = proc MakeExternImport(s: PSym, extname: string) =
s.loc.r = toRope(extname) setExternName(s, extname)
incl(s.flags, sfImportc) incl(s.flags, sfImportc)
excl(s.flags, sfForward) excl(s.flags, sfForward)
proc MakeExternExport(s: PSym, extname: string) = proc MakeExternExport(s: PSym, extname: string) =
s.loc.r = toRope(extname) setExternName(s, extname)
incl(s.flags, sfExportc) incl(s.flags, sfExportc)
proc getStrLitNode(c: PContext, n: PNode): PNode = 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)) makeExternExport(sym, getOptionalStr(c, it, sym.name.s))
incl(sym.flags, sfUsed) # avoid wrong hints incl(sym.flags, sfUsed) # avoid wrong hints
of wImportc: makeExternImport(sym, getOptionalStr(c, it, sym.name.s)) of wImportc: makeExternImport(sym, getOptionalStr(c, it, sym.name.s))
of wExtern: setExternName(sym, expectStrLit(c, it))
of wAlign: of wAlign:
if sym.typ == nil: invalidPragma(it) if sym.typ == nil: invalidPragma(it)
sym.typ.align = expectIntLit(c, it) sym.typ.align = expectIntLit(c, it)

View file

@ -688,7 +688,7 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
else: else:
if n.sons[pragmasPos] != nil: if n.sons[pragmasPos] != nil:
liMessage(n.sons[pragmasPos].info, errPragmaOnlyInHeaderOfProc) liMessage(n.sons[pragmasPos].info, errPragmaOnlyInHeaderOfProc)
if not (sfForward in proto.flags): if sfForward notin proto.flags:
liMessage(n.info, errAttemptToRedefineX, proto.name.s) liMessage(n.info, errAttemptToRedefineX, proto.name.s)
excl(proto.flags, sfForward) excl(proto.flags, sfForward)
closeScope(c.tab) # close scope with wrong parameter symbols 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) c.p = newProcCon(s)
if (s.typ.sons[0] != nil) and (kind != skIterator): if (s.typ.sons[0] != nil) and (kind != skIterator):
addResult(c, s.typ.sons[0], n.info) 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) if (s.typ.sons[0] != nil) and (kind != skIterator): addResultNode(c, n)
else: else:
if (s.typ.sons[0] != nil) and (kind != skIterator): if (s.typ.sons[0] != nil) and (kind != skIterator):

View file

@ -34,6 +34,7 @@ type
wColon, wEquals, wDot, wDotDot, wHat, wStar, wMinus, wColon, wEquals, wDot, wDotDot, wHat, wStar, wMinus,
wMagic, wTypeCheck, wFinal, wProfiler, wObjChecks, wImportc, wExportc, wMagic, wTypeCheck, wFinal, wProfiler, wObjChecks, wImportc, wExportc,
wExtern,
wAlign, wNodecl, wPure, wVolatile, wRegister, wSideeffect, wHeader, wAlign, wNodecl, wPure, wVolatile, wRegister, wSideeffect, wHeader,
wNosideeffect, wNoreturn, wMerge, wLib, wDynlib, wCompilerproc, wProcVar, wNosideeffect, wNoreturn, wMerge, wLib, wDynlib, wCompilerproc, wProcVar,
wFatal, wError, wWarning, wHint, wLine, wPush, wPop, wDefine, wUndef, wFatal, wError, wWarning, wHint, wLine, wPush, wPop, wDefine, wUndef,
@ -54,7 +55,7 @@ type
wCc, wGenscript, wCheckPoint, wCheckPoints, wNoMain, wSubsChar, wCc, wGenscript, wCheckPoint, wCheckPoints, wNoMain, wSubsChar,
wAcyclic, wIndex, wAcyclic, wIndex,
wCompileToC, wCompileToCpp, wCompileToEcmaScript, wCompileToLLVM, wPretty, wCompileToC, wCompileToCpp, wCompileToEcmaScript, wCompileToLLVM, wPretty,
wDoc, wGenDepend, wListDef, wCheck, wParse, wScan, wBoot, wLazy, wDoc, wGenDepend, wListDef, wCheck, wParse, wScan, wLazy,
wRst2html, wRst2tex, wI, wRst2html, wRst2tex, wI,
wWrite, wPutEnv, wPrependEnv, wAppendEnv, wThreadVar wWrite, wPutEnv, wPrependEnv, wAppendEnv, wThreadVar
@ -78,7 +79,8 @@ const
":", "=", ".", "..", "^", "*", "-", ":", "=", ".", "..", "^", "*", "-",
"magic", "typecheck", "final", "profiler", "objchecks", "importc", "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", "header", "nosideeffect", "noreturn", "merge", "lib", "dynlib",
"compilerproc", "procvar", "fatal", "error", "warning", "hint", "line", "compilerproc", "procvar", "fatal", "error", "warning", "hint", "line",
"push", "pop", "define", "undef", "linedir", "stacktrace", "linetrace", "push", "pop", "define", "undef", "linedir", "stacktrace", "linetrace",
@ -101,7 +103,7 @@ const
"nomain", "subschar", "acyclic", "index", "nomain", "subschar", "acyclic", "index",
"compiletoc", "compiletocpp", "compiletoecmascript", "compiletollvm", "compiletoc", "compiletocpp", "compiletoecmascript", "compiletollvm",
"pretty", "doc", "gendepend", "listdef", "check", "parse", "scan", "pretty", "doc", "gendepend", "listdef", "check", "parse", "scan",
"boot", "lazy", "rst2html", "rst2tex", "i", "lazy", "rst2html", "rst2tex", "i",
"write", "putenv", "prependenv", "appendenv", "threadvar"] "write", "putenv", "prependenv", "appendenv", "threadvar"]
proc whichKeyword*(id: PIdent): TSpecialWord proc whichKeyword*(id: PIdent): TSpecialWord

0
tests/accept/compile/tenum3.nim Normal file → Executable file
View file

0
tests/accept/compile/tuserpragma.nim Normal file → Executable file
View file

0
tests/accept/run/tarray3.nim Normal file → Executable file
View file

0
tests/accept/run/tunhandledexc.nim Normal file → Executable file
View file

0
tests/accept/run/twrongexc.nim Normal file → Executable file
View file

View file

@ -1,10 +1,11 @@
For version 0.8.10 For version 0.8.10
================== ==================
- more robust boot strap process!
- support for generation of dynamic libraries
- fix exception handling - fix exception handling
- fix implicit generic routines - fix implicit generic routines
- fix the streams implementation so that they use methods - fix the streams implementation so that they use methods
- support for generation of dynamic libraries
High priority (version 0.9.0) High priority (version 0.9.0)

View file

@ -1,5 +1,5 @@
#! stdtmpl(subsChar='?') | standard #! stdtmpl(subsChar='?') | standard
#proc GenerateBuildScript(c: TConfigData): string = #proc GenerateBuildShellScript(c: TConfigData): string =
# result = "#! /bin/sh\n# Generated by niminst\n" # result = "#! /bin/sh\n# Generated by niminst\n"
CC="gcc" CC="gcc"
LINKER="gcc" LINKER="gcc"
@ -83,8 +83,16 @@ case $myos in
$LINKER $LINK_FLAGS -o ?{c.binPaths[0]}/?{toLower(c.name)} ?linkCmd || exit 1 $LINKER $LINK_FLAGS -o ?{c.binPaths[0]}/?{toLower(c.name)} ?linkCmd || exit 1
;; ;;
# end for # end for
*)
echo "Error: no C code generated for: [$myos: $mycpu]"
exit 1
;;
esac esac
;; ;;
*)
echo "Error: no C code generated for: [$myos: $mycpu]"
exit 1
;;
# end for # end for
esac esac

View file

@ -1,7 +1,7 @@
# #
# #
# The Nimrod Installation Generator # The Nimrod Installation Generator
# (c) Copyright 2009 Andreas Rumpf # (c) Copyright 2010 Andreas Rumpf
# #
# See the file "copying.txt", included in this # See the file "copying.txt", included in this
# distribution, for details about the copyright. # distribution, for details about the copyright.
@ -20,6 +20,7 @@ const
maxOS = 20 # max number of OSes maxOS = 20 # max number of OSes
maxCPU = 10 # max number of CPUs maxCPU = 10 # max number of CPUs
buildShFile = "build.sh" buildShFile = "build.sh"
buildBatFile = "build.bat"
installShFile = "install.sh" installShFile = "install.sh"
deinstallShFile = "deinstall.sh" deinstallShFile = "deinstall.sh"
@ -89,17 +90,18 @@ proc skipRoot(f: string): string =
if result.len == 0: result = f if result.len == 0: result = f
include "inno.tmpl" include "inno.tmpl"
include "build.tmpl" include "buildsh.tmpl"
include "buildbat.tmpl"
include "install.tmpl" include "install.tmpl"
include "deinstall.tmpl" include "deinstall.tmpl"
# ------------------------- configuration file ------------------------------- # ------------------------- configuration file -------------------------------
const const
Version = "0.7" Version = "0.8"
Usage = "niminst - Nimrod Installation Generator Version " & version & """ Usage = "niminst - Nimrod Installation Generator Version " & version & """
(c) 2009 Andreas Rumpf (c) 2010 Andreas Rumpf
Usage: Usage:
niminst [options] command[;command2...] ini-file[.ini] [compile_options] niminst [options] command[;command2...] ini-file[.ini] [compile_options]
Command: Command:
@ -289,6 +291,22 @@ proc writeFile(filename, content, newline: string) =
else: else:
quit("Cannot open for writing: " & filename) 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) = proc srcdist(c: var TConfigData) =
for x in walkFiles("lib/*.h"): for x in walkFiles("lib/*.h"):
CopyFile(dest="build" / extractFilename(x), source=x) 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]) CopyFile(dest=dest, source=c.cfiles[osA][cpuA][i])
c.cfiles[osA][cpuA][i] = dest c.cfiles[osA][cpuA][i] = dest
# second pass: remove duplicate files # second pass: remove duplicate files
for osA in countdown(c.oses.len, 1): removeDuplicateFiles(c)
for cpuA in countdown(c.cpus.len, 1): writeFile(buildShFile, GenerateBuildShellScript(c), "\10")
for i in 0..c.cfiles[osA][cpuA].len-1: writeFile(buildBatFile, GenerateBuildBatchScript(c), "\13\10")
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")
if c.installScript: if c.installScript:
writeFile(installShFile, GenerateInstallScript(c), "\10") writeFile(installShFile, GenerateInstallScript(c), "\10")
if c.uninstallScript: if c.uninstallScript:

View file

@ -27,6 +27,13 @@ Changes affecting backwards compatibility
unless they are used in the same module. unless they are used in the same module.
- Deprecated ``times.getStartMilsecs``: Use ``epochTime`` or ``cpuTime`` - Deprecated ``times.getStartMilsecs``: Use ``epochTime`` or ``cpuTime``
instead. instead.
- Removed ``system.OpenFile``.
- Removed ``system.CloseFile``.
- Removed ``strutils.replaceStr``.
- Removed ``strutils.deleteStr``.
- Removed ``strutils.splitLinesSeq``.
- Removed ``strutils.splitSeq``.
- Removed ``strutils.toString``.
Additions Additions
@ -43,6 +50,10 @@ Additions
- Implemented ``{.size: sizeof(cint).}`` pragma for enum types. This is useful - Implemented ``{.size: sizeof(cint).}`` pragma for enum types. This is useful
for interfacing with C. for interfacing with C.
- Implemented ``{.pragma.}`` pragma for user defined pragmas. - 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 2010-03-14 Version 0.8.8 released