handling of compiler procs improved for DLL generation

This commit is contained in:
Andreas Rumpf
2010-07-29 21:30:04 +02:00
parent 804e2ac89d
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
## none of the characters in `chars`, -1 is returned.
proc replaceStr*(s, sub, by: string): string {.noSideEffect, deprecated.}
## Replaces `sub` in `s` by the string `by`.
## **Deprecated since version 0.8.0**: Use `replace` instead.
proc replaceStr*(s: string, sub, by: char): string {.noSideEffect, deprecated.}
## optimized version for characters.
## **Deprecated since version 0.8.0**: Use `replace` instead.
proc deleteStr*(s: var string, first, last: int) {.deprecated.}
## Deletes in `s` the characters at position `first` .. `last`. This modifies
## `s` itself, it does not return a copy.
## **Deprecated since version 0.8.0**: Use `delete` instead.
proc toOctal*(c: char): string
## Converts a character `c` to its octal representation. The resulting
## string may not have a leading zero. Its length is always exactly 3.
@@ -241,24 +228,6 @@ iterator splitLines*(s: string): string =
else: break # was '\0'
first = last
proc splitLinesSeq*(s: string): seq[string] {.noSideEffect, deprecated.} =
## The same as `splitLines`, but is a proc that returns a sequence
## of substrings.
## **Deprecated since version 0.8.0**: Use `splitLines` instead.
accumulateResult(splitLines(s))
proc splitSeq*(s: string, seps: set[char] = Whitespace): seq[string] {.
noSideEffect, deprecated.} =
## The same as `split`, but is a proc that returns a sequence of substrings.
## **Deprecated since version 0.8.0**: Use `split` instead.
accumulateResult(split(s, seps))
proc splitSeq*(s: string, sep: char): seq[string] {.noSideEffect,
deprecated.} =
## The same as `split`, but is a proc that returns a sequence of substrings.
## **Deprecated since version 0.8.0**: Use `split` instead.
accumulateResult(split(s, sep))
proc splitLines*(s: string): seq[string] {.noSideEffect.} =
## The same as the `splitLines` iterator, but is a proc that returns a
## sequence of substrings.
@@ -328,12 +297,6 @@ proc ParseHexInt*(s: string): int {.noSideEffect, procvar.}
## following optional prefixes: ``0x``, ``0X``, ``#``.
## Underscores within `s` are ignored.
# the stringify and format operators:
proc toString*[Ty](x: Ty): string {.deprecated.}
## This generic proc is the same as the stringify operator `$`.
##
## **Deprecated since version 0.8.2:** Use `$` instead.
proc repeatChar*(count: int, c: Char = ' '): string
## Returns a string of length `count` consisting only of
## the character `c`.
@@ -670,10 +633,6 @@ proc delete*(s: var string, first, last: int) =
inc(j)
setlen(s, newLen)
proc replaceStr(s, sub, by: string): string = return replace(s, sub, by)
proc replaceStr(s: string, sub, by: char): string = return replace(s, sub, by)
proc deleteStr(s: var string, first, last: int) = delete(s, first, last)
# parsing numbers:
proc toHex(x: BiggestInt, len: int): string =

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

14
lib/system/cgprocs.nim Normal file
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 nimLoadLibraryError(path: string) {.compilerproc, noinline.} =
raise newException(EInvalidLibrary, "could not load: " & path)
when true:
# carefully written to avoid memory allocation:
stdout.write("could not load: ")
quit(path)
else:
raise newException(EInvalidLibrary, "could not load: " & path)
# this code was inspired from Lua's source code:
# Lua - An Extensible Extension Language

View File

@@ -74,13 +74,13 @@ var
# This is wasteful but safe. This is a lock against recursive garbage
# collection, not a lock for threads!
proc unsureAsgnRef(dest: ppointer, src: pointer) {.compilerproc.}
proc unsureAsgnRef(dest: ppointer, src: pointer) {.compilerRtl.}
# unsureAsgnRef updates the reference counters only if dest is not on the
# stack. It is used by the code generator if it cannot decide wether a
# reference is in the stack or not (this can happen for var parameters).
#proc growObj(old: pointer, newsize: int): pointer {.compilerproc.}
proc newObj(typ: PNimType, size: int): pointer {.compilerproc.}
proc newSeq(typ: PNimType, len: int): pointer {.compilerproc.}
proc newObj(typ: PNimType, size: int): pointer {.compilerRtl.}
proc newSeq(typ: PNimType, len: int): pointer {.compilerRtl.}
proc addZCT(s: var TCellSeq, c: PCell) {.noinline.} =
if (c.refcount and rcZct) == 0:
@@ -214,8 +214,10 @@ proc prepareDealloc(cell: PCell) =
(cast[TFinalizer](cell.typ.finalizer))(cellToUsr(cell))
dec(recGcLock)
proc setStackBottom(theStackBottom: pointer) {.compilerproc.} =
stackBottom = theStackBottom
proc setStackBottom(theStackBottom: pointer) {.compilerRtl.} =
# the first init must be the one that defines the stack bottom:
if stackBottom == nil:
stackBottom = theStackBottom
proc PossibleRoot(gch: var TGcHeap, c: PCell) {.inline.} =
if canbeCycleRoot(c): incl(gch.cycleRoots, c)
@@ -236,10 +238,10 @@ proc incRef(c: PCell) {.inline.} =
if canBeCycleRoot(c):
incl(gch.cycleRoots, c)
proc nimGCref(p: pointer) {.compilerproc, inline.} = incRef(usrToCell(p))
proc nimGCunref(p: pointer) {.compilerproc, inline.} = decRef(usrToCell(p))
proc nimGCref(p: pointer) {.compilerRtl, inl.} = incRef(usrToCell(p))
proc nimGCunref(p: pointer) {.compilerRtl, inl.} = decRef(usrToCell(p))
proc asgnRef(dest: ppointer, src: pointer) {.compilerproc, inline.} =
proc asgnRef(dest: ppointer, src: pointer) {.compilerRtl, inl.} =
# the code generator calls this proc!
assert(not isOnStack(dest))
# BUGFIX: first incRef then decRef!
@@ -247,7 +249,7 @@ proc asgnRef(dest: ppointer, src: pointer) {.compilerproc, inline.} =
if dest^ != nil: decRef(usrToCell(dest^))
dest^ = src
proc asgnRefNoCycle(dest: ppointer, src: pointer) {.compilerproc, inline.} =
proc asgnRefNoCycle(dest: ppointer, src: pointer) {.compilerRtl, inl.} =
# the code generator calls this proc if it is known at compile time that no
# cycle is possible.
if src != nil:

45
lib/system/inclrtl.nim Executable file
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
include "system/cellsets"
elif appType == "lib":
{.warning: "gc in a library context may not work".}
when hostOS == "windows":
const nimrtl = "nimrtl.dll"
elif hostOS == "macosx":
const nimrtl = "nimrtl.dynlib"
else:
const nimrtl = "libnimrtl.so"
when not defined(includeGC):
# ordinary client; use the GC from nimrtl.dll:
proc initGC() {.cdecl, importc, dynlib: nimrtl.}
proc GC_disable() {.cdecl, importc, dynlib: nimrtl.}
proc GC_enable() {.cdecl, importc, dynlib: nimrtl.}
proc GC_fullCollect() {.cdecl, importc, dynlib: nimrtl.}
proc GC_setStrategy(strategy: TGC_Strategy) {.
cdecl, importc, dynlib: nimrtl.}
proc GC_enableMarkAndSweep() {.cdecl, importc, dynlib: nimrtl.}
proc GC_disableMarkAndSweep() {.cdecl, importc, dynlib: nimrtl.}
proc GC_getStatistics(): string {.cdecl, importc, dynlib: nimrtl.}
elif defined(useNimRtl):
proc initGC() = nil
proc newObj(typ: PNimType, size: int): pointer {.
compilerproc, cdecl, importc, dynlib: nimrtl.}
proc newSeq(typ: PNimType, len: int): pointer {.
compilerproc, cdecl, importc, dynlib: nimrtl.}
proc growObj(old: pointer, newsize: int): pointer {.
cdecl, importc, dynlib: nimrtl.}
proc setStackBottom(theStackBottom: pointer) {.
compilerproc, cdecl, importc, dynlib: nimrtl.}
proc nimGCref(p: pointer) {.
compilerproc, cdecl, importc, dynlib: nimrtl.}
proc nimGCunref(p: pointer) {.
compilerproc, cdecl, importc, dynlib: nimrtl.}
proc newObj(typ: PNimType, size: int): pointer {.compilerRtl.}
proc newSeq(typ: PNimType, len: int): pointer {.compilerRtl.}
proc growObj(old: pointer, newsize: int): pointer {.rtl.}
# The write barrier is performance critical!
# XXX We should ensure that they are inlined here.
# Later implementations will do this.
proc setStackBottom(theStackBottom: pointer) {.compilerProc, inline.} =
# This happens before setStackBottom has been loaded by dlsym(), so
# we simply provide a dummy implemenation here for the code gen. No
# harm is done by this.
nil
proc unsureAsgnRef(dest: ppointer, src: pointer) {.
compilerproc, cdecl, importc, dynlib: nimrtl.}
proc asgnRef(dest: ppointer, src: pointer) {.
compilerproc, cdecl, importc, dynlib: nimrtl.}
proc asgnRefNoCycle(dest: ppointer, src: pointer) {.
compilerproc, cdecl, importc, dynlib: nimrtl.}
else:
# include the GC and export it!
include "system/alloc"
include "system/cellsets"
assert(sizeof(TCell) == sizeof(TFreeCell))
include "system/gc"
proc nimGCref(p: pointer) {.compilerRtl.}
proc nimGCunref(p: pointer) {.compilerRtl.}
# The write barrier is performance critical!
# XXX We should ensure that they are inlined here.
# Later implementations will do this.
proc unsureAsgnRef(dest: ppointer, src: pointer) {.
compilerRtl.}
proc asgnRef(dest: ppointer, src: pointer) {.
compilerRtl.}
proc asgnRefNoCycle(dest: ppointer, src: pointer) {.
compilerRtl.}
include "system/cellsets"
else:
include "system/alloc"
include "system/cellsets"

View File

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

View File

@@ -135,14 +135,6 @@ proc open(f: var TFile, filehandle: TFileHandle, mode: TFileMode): bool =
f = fdopen(filehandle, FormatOpen[mode])
result = f != nil
proc OpenFile(f: var TFile, filename: string,
mode: TFileMode = fmRead,
bufSize: int = -1): Bool =
result = open(f, filename, mode, bufSize)
proc openFile(f: var TFile, filehandle: TFileHandle, mode: TFileMode): bool =
result = open(f, filehandle, mode)
# C routine that is used here:
proc fread(buf: Pointer, size, n: int, f: TFile): int {.
importc: "fread", noDecl.}

View File

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

View File

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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -688,7 +688,7 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
else:
if n.sons[pragmasPos] != nil:
liMessage(n.sons[pragmasPos].info, errPragmaOnlyInHeaderOfProc)
if not (sfForward in proto.flags):
if sfForward notin proto.flags:
liMessage(n.info, errAttemptToRedefineX, proto.name.s)
excl(proto.flags, sfForward)
closeScope(c.tab) # close scope with wrong parameter symbols
@@ -715,7 +715,9 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
c.p = newProcCon(s)
if (s.typ.sons[0] != nil) and (kind != skIterator):
addResult(c, s.typ.sons[0], n.info)
n.sons[codePos] = semStmtScope(c, n.sons[codePos])
if sfImportc notin s.flags:
# no semantic checking for importc:
n.sons[codePos] = semStmtScope(c, n.sons[codePos])
if (s.typ.sons[0] != nil) and (kind != skIterator): addResultNode(c, n)
else:
if (s.typ.sons[0] != nil) and (kind != skIterator):

View File

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

0
tests/accept/compile/tenum3.nim Normal file → Executable file
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
==================
- more robust boot strap process!
- support for generation of dynamic libraries
- fix exception handling
- fix implicit generic routines
- fix the streams implementation so that they use methods
- support for generation of dynamic libraries
High priority (version 0.9.0)

View File

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

View File

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

View File

@@ -27,6 +27,13 @@ Changes affecting backwards compatibility
unless they are used in the same module.
- Deprecated ``times.getStartMilsecs``: Use ``epochTime`` or ``cpuTime``
instead.
- Removed ``system.OpenFile``.
- Removed ``system.CloseFile``.
- Removed ``strutils.replaceStr``.
- Removed ``strutils.deleteStr``.
- Removed ``strutils.splitLinesSeq``.
- Removed ``strutils.splitSeq``.
- Removed ``strutils.toString``.
Additions
@@ -43,6 +50,10 @@ Additions
- Implemented ``{.size: sizeof(cint).}`` pragma for enum types. This is useful
for interfacing with C.
- Implemented ``{.pragma.}`` pragma for user defined pragmas.
- Implemented ``{.extern.}`` pragma for better control of name mangling.
- The ``importc`` and ``exportc`` pragmas support format strings:
``proc p{.exportc: "nim_$1".}`` exports ``p`` as ``nim_p``. This is useful
for user defined pragmas.
2010-03-14 Version 0.8.8 released