DLL generation of the stdlib for unix
This commit is contained in:
parent
03724c2952
commit
c9e011e36c
9 changed files with 101 additions and 111 deletions
|
|
@ -431,4 +431,6 @@ struct NimException {
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define NIM_POSIX_INIT __attribute__((constructor))
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
5
lib/nimrtl.cfg
Executable file
5
lib/nimrtl.cfg
Executable file
|
|
@ -0,0 +1,5 @@
|
||||||
|
# The RTL.dll needs to be compiled with these options!
|
||||||
|
|
||||||
|
--app:lib
|
||||||
|
--define:createNimRtl
|
||||||
|
|
||||||
104
lib/system.nim
104
lib/system.nim
|
|
@ -666,6 +666,56 @@ proc `&` * (x: char, y: string): string {.
|
||||||
|
|
||||||
proc add*(x: var string, y: char) {.magic: "AppendStrCh", noSideEffect.}
|
proc add*(x: var string, y: char) {.magic: "AppendStrCh", noSideEffect.}
|
||||||
proc add*(x: var string, y: string) {.magic: "AppendStrStr", noSideEffect.}
|
proc add*(x: var string, y: string) {.magic: "AppendStrStr", noSideEffect.}
|
||||||
|
|
||||||
|
type
|
||||||
|
TEndian* = enum ## is a type describing the endianness of a processor.
|
||||||
|
littleEndian, bigEndian
|
||||||
|
|
||||||
|
const
|
||||||
|
isMainModule* {.magic: "IsMainModule".}: bool = false
|
||||||
|
## is true only when accessed in the main module. This works thanks to
|
||||||
|
## compiler magic. It is useful to embed testing code in a module.
|
||||||
|
|
||||||
|
CompileDate* {.magic: "CompileDate"}: string = "0000-00-00"
|
||||||
|
## is the date of compilation as a string of the form
|
||||||
|
## ``YYYY-MM-DD``. This works thanks to compiler magic.
|
||||||
|
|
||||||
|
CompileTime* {.magic: "CompileTime"}: string = "00:00:00"
|
||||||
|
## is the time of compilation as a string of the form
|
||||||
|
## ``HH:MM:SS``. This works thanks to compiler magic.
|
||||||
|
|
||||||
|
NimrodVersion* {.magic: "NimrodVersion"}: string = "0.0.0"
|
||||||
|
## is the version of Nimrod as a string.
|
||||||
|
## This works thanks to compiler magic.
|
||||||
|
|
||||||
|
NimrodMajor* {.magic: "NimrodMajor"}: int = 0
|
||||||
|
## is the major number of Nimrod's version.
|
||||||
|
## This works thanks to compiler magic.
|
||||||
|
|
||||||
|
NimrodMinor* {.magic: "NimrodMinor"}: int = 0
|
||||||
|
## is the minor number of Nimrod's version.
|
||||||
|
## This works thanks to compiler magic.
|
||||||
|
|
||||||
|
NimrodPatch* {.magic: "NimrodPatch"}: int = 0
|
||||||
|
## is the patch number of Nimrod's version.
|
||||||
|
## This works thanks to compiler magic.
|
||||||
|
|
||||||
|
cpuEndian* {.magic: "CpuEndian"}: TEndian = littleEndian
|
||||||
|
## is the endianness of the target CPU. This is a valuable piece of
|
||||||
|
## information for low-level code only. This works thanks to compiler magic.
|
||||||
|
|
||||||
|
hostOS* {.magic: "HostOS"}: string = ""
|
||||||
|
## a string that describes the host operating system. Possible values:
|
||||||
|
## "windows", "macosx", "linux", "netbsd", "freebsd", "openbsd", "solaris",
|
||||||
|
## "aix".
|
||||||
|
|
||||||
|
hostCPU* {.magic: "HostCPU"}: string = ""
|
||||||
|
## a string that describes the host CPU. Possible values:
|
||||||
|
## "i386", "alpha", "powerpc", "sparc", "amd64", "mips", "arm".
|
||||||
|
|
||||||
|
appType* {.magic: "AppType"}: string = ""
|
||||||
|
## a string that describes the application type. Possible values:
|
||||||
|
## "console", "gui", "lib".
|
||||||
|
|
||||||
include "system/inclrtl"
|
include "system/inclrtl"
|
||||||
include "system/cgprocs"
|
include "system/cgprocs"
|
||||||
|
|
@ -771,59 +821,10 @@ type # these work for most platforms:
|
||||||
## high value is large enough to disable bounds checking in practice.
|
## high value is large enough to disable bounds checking in practice.
|
||||||
## Use `cstringArrayToSeq` to convert it into a ``seq[string]``.
|
## Use `cstringArrayToSeq` to convert it into a ``seq[string]``.
|
||||||
|
|
||||||
TEndian* = enum ## is a type describing the endianness of a processor.
|
|
||||||
littleEndian, bigEndian
|
|
||||||
|
|
||||||
PFloat32* = ptr Float32 ## an alias for ``ptr float32``
|
PFloat32* = ptr Float32 ## an alias for ``ptr float32``
|
||||||
PFloat64* = ptr Float64 ## an alias for ``ptr float64``
|
PFloat64* = ptr Float64 ## an alias for ``ptr float64``
|
||||||
PInt64* = ptr Int64 ## an alias for ``ptr int64``
|
PInt64* = ptr Int64 ## an alias for ``ptr int64``
|
||||||
PInt32* = ptr Int32 ## an alias for ``ptr int32``
|
PInt32* = ptr Int32 ## an alias for ``ptr int32``
|
||||||
|
|
||||||
const
|
|
||||||
isMainModule* {.magic: "IsMainModule".}: bool = false
|
|
||||||
## is true only when accessed in the main module. This works thanks to
|
|
||||||
## compiler magic. It is useful to embed testing code in a module.
|
|
||||||
|
|
||||||
CompileDate* {.magic: "CompileDate"}: string = "0000-00-00"
|
|
||||||
## is the date of compilation as a string of the form
|
|
||||||
## ``YYYY-MM-DD``. This works thanks to compiler magic.
|
|
||||||
|
|
||||||
CompileTime* {.magic: "CompileTime"}: string = "00:00:00"
|
|
||||||
## is the time of compilation as a string of the form
|
|
||||||
## ``HH:MM:SS``. This works thanks to compiler magic.
|
|
||||||
|
|
||||||
NimrodVersion* {.magic: "NimrodVersion"}: string = "0.0.0"
|
|
||||||
## is the version of Nimrod as a string.
|
|
||||||
## This works thanks to compiler magic.
|
|
||||||
|
|
||||||
NimrodMajor* {.magic: "NimrodMajor"}: int = 0
|
|
||||||
## is the major number of Nimrod's version.
|
|
||||||
## This works thanks to compiler magic.
|
|
||||||
|
|
||||||
NimrodMinor* {.magic: "NimrodMinor"}: int = 0
|
|
||||||
## is the minor number of Nimrod's version.
|
|
||||||
## This works thanks to compiler magic.
|
|
||||||
|
|
||||||
NimrodPatch* {.magic: "NimrodPatch"}: int = 0
|
|
||||||
## is the patch number of Nimrod's version.
|
|
||||||
## This works thanks to compiler magic.
|
|
||||||
|
|
||||||
cpuEndian* {.magic: "CpuEndian"}: TEndian = littleEndian
|
|
||||||
## is the endianness of the target CPU. This is a valuable piece of
|
|
||||||
## information for low-level code only. This works thanks to compiler magic.
|
|
||||||
|
|
||||||
hostOS* {.magic: "HostOS"}: string = ""
|
|
||||||
## a string that describes the host operating system. Possible values:
|
|
||||||
## "windows", "macosx", "linux", "netbsd", "freebsd", "openbsd", "solaris",
|
|
||||||
## "aix".
|
|
||||||
|
|
||||||
hostCPU* {.magic: "HostCPU"}: string = ""
|
|
||||||
## a string that describes the host CPU. Possible values:
|
|
||||||
## "i386", "alpha", "powerpc", "sparc", "amd64", "mips", "arm".
|
|
||||||
|
|
||||||
appType* {.magic: "AppType"}: string = ""
|
|
||||||
## a string that describes the application type. Possible values:
|
|
||||||
## "console", "gui", "lib".
|
|
||||||
|
|
||||||
proc toFloat*(i: int): float {.
|
proc toFloat*(i: int): float {.
|
||||||
magic: "ToFloat", noSideEffect, importc: "toFloat".}
|
magic: "ToFloat", noSideEffect, importc: "toFloat".}
|
||||||
|
|
@ -1305,7 +1306,10 @@ when not defined(EcmaScript) and not defined(NimrodVM):
|
||||||
proc initGC()
|
proc initGC()
|
||||||
|
|
||||||
proc initStackBottom() {.inline.} =
|
proc initStackBottom() {.inline.} =
|
||||||
var locals: array[0..7, int]
|
# WARNING: This is very fragile! An array size of 8 does not work on my
|
||||||
|
# Linux 64bit system. Very strange, but we are at the will of GCC's
|
||||||
|
# optimizer...
|
||||||
|
var locals {.volatile.}: pointer
|
||||||
setStackBottom(addr(locals))
|
setStackBottom(addr(locals))
|
||||||
|
|
||||||
var
|
var
|
||||||
|
|
|
||||||
2
lib/system/cgprocs.nim
Normal file → Executable file
2
lib/system/cgprocs.nim
Normal file → Executable file
|
|
@ -21,6 +21,6 @@ proc nimGetProcAddr(lib: TLibHandle, name: cstring): TProcAddr {.compilerproc.}
|
||||||
|
|
||||||
proc nimLoadLibraryError(path: string) {.compilerproc, noinline.}
|
proc nimLoadLibraryError(path: string) {.compilerproc, noinline.}
|
||||||
|
|
||||||
proc setStackBottom(theStackBottom: pointer) {.compilerRtl.}
|
proc setStackBottom(theStackBottom: pointer) {.compilerRtl, noinline.}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -491,10 +491,11 @@ else:
|
||||||
const stackIncreases = false
|
const stackIncreases = false
|
||||||
|
|
||||||
proc setStackBottom(theStackBottom: pointer) =
|
proc setStackBottom(theStackBottom: pointer) =
|
||||||
|
#c_fprintf(c_stdout, "stack bottom: %p;\n", theStackBottom)
|
||||||
# the first init must be the one that defines the stack bottom:
|
# the first init must be the one that defines the stack bottom:
|
||||||
if stackBottom == nil: stackBottom = theStackBottom
|
if stackBottom == nil: stackBottom = theStackBottom
|
||||||
else:
|
else:
|
||||||
var a = cast[TAddress](theStackBottom)
|
var a = cast[TAddress](theStackBottom) # and not PageMask - PageSize*2
|
||||||
var b = cast[TAddress](stackBottom)
|
var b = cast[TAddress](stackBottom)
|
||||||
when stackIncreases:
|
when stackIncreases:
|
||||||
stackBottom = cast[pointer](min(a, b))
|
stackBottom = cast[pointer](min(a, b))
|
||||||
|
|
|
||||||
71
rod/cgen.nim
71
rod/cgen.nim
|
|
@ -700,74 +700,51 @@ proc getFileHeader(cfilenoext: string): PRope =
|
||||||
|
|
||||||
proc genMainProc(m: BModule) =
|
proc genMainProc(m: BModule) =
|
||||||
const
|
const
|
||||||
CommonMainBody = " #setStackBottom(dummy);$n" & " nim__datInit();$n" &
|
CommonMainBody =
|
||||||
" systemInit();$n" & "$1" & "$2"
|
" nim__datInit();$n" &
|
||||||
CommonMainBodyLLVM = " %MOC$3 = bitcast [8 x %NI]* %dummy to i8*$n" &
|
" systemInit();$n" &
|
||||||
" call void @#setStackBottom(i8* %MOC$3)$n" &
|
"$1" &
|
||||||
" call void @nim__datInit()$n" & " call void systemInit()$n" & "$1" &
|
|
||||||
"$2"
|
"$2"
|
||||||
PosixNimMain = "int cmdCount;$n" & "char** cmdLine;$n" & "char** gEnv;$n" &
|
PosixNimMain =
|
||||||
"N_CDECL(void, NimMain)(void) {$n" & " int dummy[8];$n" &
|
"int cmdCount;$n" &
|
||||||
|
"char** cmdLine;$n" &
|
||||||
|
"char** gEnv;$n" &
|
||||||
|
"N_CDECL(void, NimMain)(void) {$n" &
|
||||||
CommonMainBody & "}$n"
|
CommonMainBody & "}$n"
|
||||||
PosixCMain = "int main(int argc, char** args, char** env) {$n" &
|
PosixCMain = "int main(int argc, char** args, char** env) {$n" &
|
||||||
" cmdLine = args;$n" & " cmdCount = argc;$n" & " gEnv = env;$n" &
|
" cmdLine = args;$n" & " cmdCount = argc;$n" & " gEnv = env;$n" &
|
||||||
" NimMain();$n" & " return 0;$n" & "}$n"
|
" NimMain();$n" & " return 0;$n" & "}$n"
|
||||||
PosixNimMainLLVM = "@cmdCount = linkonce i32$n" &
|
WinNimMain = "N_CDECL(void, NimMain)(void) {$n" &
|
||||||
"@cmdLine = linkonce i8**$n" & "@gEnv = linkonce i8**$n" &
|
|
||||||
"define void @NimMain(void) {$n" & " %dummy = alloca [8 x %NI]$n" &
|
|
||||||
CommonMainBodyLLVM & "}$n"
|
|
||||||
PosixCMainLLVM = "define i32 @main(i32 %argc, i8** %args, i8** %env) {$n" &
|
|
||||||
" store i8** %args, i8*** @cmdLine$n" &
|
|
||||||
" store i32 %argc, i32* @cmdCount$n" &
|
|
||||||
" store i8** %env, i8*** @gEnv$n" & " call void @NimMain()$n" &
|
|
||||||
" ret i32 0$n" & "}$n"
|
|
||||||
WinNimMain = "N_CDECL(void, NimMain)(void) {$n" & " int dummy[8];$n" &
|
|
||||||
CommonMainBody & "}$n"
|
CommonMainBody & "}$n"
|
||||||
WinCMain = "N_STDCALL(int, WinMain)(HINSTANCE hCurInstance, $n" &
|
WinCMain = "N_STDCALL(int, WinMain)(HINSTANCE hCurInstance, $n" &
|
||||||
" HINSTANCE hPrevInstance, $n" &
|
" HINSTANCE hPrevInstance, $n" &
|
||||||
" LPSTR lpCmdLine, int nCmdShow) {$n" &
|
" LPSTR lpCmdLine, int nCmdShow) {$n" &
|
||||||
" NimMain();$n" & " return 0;$n" & "}$n"
|
" NimMain();$n" & " return 0;$n" & "}$n"
|
||||||
WinNimMainLLVM = "define void @NimMain(void) {$n" &
|
|
||||||
" %dummy = alloca [8 x %NI]$n" & CommonMainBodyLLVM & "}$n"
|
|
||||||
WinCMainLLVM = "define stdcall i32 @WinMain(i32 %hCurInstance, $n" &
|
|
||||||
" i32 %hPrevInstance, $n" &
|
|
||||||
" i8* %lpCmdLine, i32 %nCmdShow) {$n" &
|
|
||||||
" call void @NimMain()$n" & " ret i32 0$n" & "}$n"
|
|
||||||
WinNimDllMain = "N_LIB_EXPORT N_CDECL(void, NimMain)(void) {$n" &
|
WinNimDllMain = "N_LIB_EXPORT N_CDECL(void, NimMain)(void) {$n" &
|
||||||
" int dummy[8];$n" & CommonMainBody & "}$n"
|
CommonMainBody & "}$n"
|
||||||
WinCDllMain = "BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fwdreason, $n" &
|
WinCDllMain = "BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fwdreason, $n" &
|
||||||
" LPVOID lpvReserved) {$n" & " NimMain();$n" &
|
" LPVOID lpvReserved) {$n" & " NimMain();$n" &
|
||||||
" return 1;$n" & "}$n"
|
" return 1;$n" & "}$n"
|
||||||
WinNimDllMainLLVM = WinNimMainLLVM
|
PosixNimDllMain = WinNimDllMain
|
||||||
WinCDllMainLLVM =
|
PosixCDllMain =
|
||||||
"define stdcall i32 @DllMain(i32 %hinstDLL, i32 %fwdreason, $n" &
|
"void NIM_POSIX_INIT NimMainInit(void) {$n" &
|
||||||
" i8* %lpvReserved) {$n" &
|
" NimMain();$n}$n"
|
||||||
" call void @NimMain()$n" & " ret i32 1$n" & "}$n"
|
|
||||||
var nimMain, otherMain: TFormatStr
|
var nimMain, otherMain: TFormatStr
|
||||||
if (platform.targetOS == osWindows) and
|
if (platform.targetOS == osWindows) and
|
||||||
(gGlobalOptions * {optGenGuiApp, optGenDynLib} != {}):
|
(gGlobalOptions * {optGenGuiApp, optGenDynLib} != {}):
|
||||||
if optGenGuiApp in gGlobalOptions:
|
if optGenGuiApp in gGlobalOptions:
|
||||||
if gCmd == cmdCompileToLLVM:
|
nimMain = WinNimMain
|
||||||
nimMain = WinNimMainLLVM
|
otherMain = WinCMain
|
||||||
otherMain = WinCMainLLVM
|
|
||||||
else:
|
|
||||||
nimMain = WinNimMain
|
|
||||||
otherMain = WinCMain
|
|
||||||
else:
|
else:
|
||||||
if gCmd == cmdCompileToLLVM:
|
nimMain = WinNimDllMain
|
||||||
nimMain = WinNimDllMainLLVM
|
otherMain = WinCDllMain
|
||||||
otherMain = WinCDllMainLLVM
|
|
||||||
else:
|
|
||||||
nimMain = WinNimDllMain
|
|
||||||
otherMain = WinCDllMain
|
|
||||||
discard lists.IncludeStr(m.headerFiles, "<windows.h>")
|
discard lists.IncludeStr(m.headerFiles, "<windows.h>")
|
||||||
|
elif optGenDynLib in gGlobalOptions:
|
||||||
|
nimMain = posixNimDllMain
|
||||||
|
otherMain = posixCDllMain
|
||||||
else:
|
else:
|
||||||
if gCmd == cmdCompileToLLVM:
|
nimMain = PosixNimMain
|
||||||
nimMain = PosixNimMainLLVM
|
otherMain = PosixCMain
|
||||||
otherMain = PosixCMainLLVM
|
|
||||||
else:
|
|
||||||
nimMain = PosixNimMain
|
|
||||||
otherMain = PosixCMain
|
|
||||||
if gBreakpoints != nil: discard cgsym(m, "dbgRegisterBreakpoint")
|
if gBreakpoints != nil: discard cgsym(m, "dbgRegisterBreakpoint")
|
||||||
inc(m.labels)
|
inc(m.labels)
|
||||||
appcg(m, m.s[cfsProcs], nimMain, [
|
appcg(m, m.s[cfsProcs], nimMain, [
|
||||||
|
|
|
||||||
|
|
@ -28,15 +28,15 @@ type
|
||||||
of nkList: sons: seq[PCaseNode]
|
of nkList: sons: seq[PCaseNode]
|
||||||
else: unused: seq[string]
|
else: unused: seq[string]
|
||||||
|
|
||||||
TIdObj* = object of TObject
|
TIdObj* = object of TObject
|
||||||
id*: int # unique id; use this for comparisons and not the pointers
|
id*: int # unique id; use this for comparisons and not the pointers
|
||||||
|
|
||||||
PIdObj* = ref TIdObj
|
PIdObj* = ref TIdObj
|
||||||
PIdent* = ref TIdent
|
PIdent* = ref TIdent
|
||||||
TIdent*{.acyclic.} = object of TIdObj
|
TIdent*{.acyclic.} = object of TIdObj
|
||||||
s*: string
|
s*: string
|
||||||
next*: PIdent # for hash-table chaining
|
next*: PIdent # for hash-table chaining
|
||||||
h*: int # hash value of s
|
h*: int # hash value of s
|
||||||
|
|
||||||
var
|
var
|
||||||
flip: int
|
flip: int
|
||||||
|
|
@ -145,8 +145,8 @@ proc buildBTree(father: var TBNode) =
|
||||||
setSons(father)
|
setSons(father)
|
||||||
|
|
||||||
proc getIdent(identifier: cstring, length: int, h: int): PIdent =
|
proc getIdent(identifier: cstring, length: int, h: int): PIdent =
|
||||||
new(result)
|
new(result)
|
||||||
result.h = h
|
result.h = h
|
||||||
result.s = newString(length)
|
result.s = newString(length)
|
||||||
|
|
||||||
proc main() =
|
proc main() =
|
||||||
|
|
|
||||||
1
todo.txt
1
todo.txt
|
|
@ -1,7 +1,6 @@
|
||||||
For version 0.8.10
|
For version 0.8.10
|
||||||
==================
|
==================
|
||||||
|
|
||||||
- support for generation of dynamic libraries
|
|
||||||
- fix exception handling
|
- fix exception handling
|
||||||
- fix implicit generic routines
|
- fix implicit generic routines
|
||||||
- fix the streams implementation so that they use methods
|
- fix the streams implementation so that they use methods
|
||||||
|
|
|
||||||
|
|
@ -58,6 +58,8 @@ Additions
|
||||||
- The ``importc`` and ``exportc`` pragmas support format strings:
|
- The ``importc`` and ``exportc`` pragmas support format strings:
|
||||||
``proc p{.exportc: "nim_$1".}`` exports ``p`` as ``nim_p``. This is useful
|
``proc p{.exportc: "nim_$1".}`` exports ``p`` as ``nim_p``. This is useful
|
||||||
for user defined pragmas.
|
for user defined pragmas.
|
||||||
|
- The standard library can be built as a DLL. Generating DLLs has been
|
||||||
|
improved.
|
||||||
|
|
||||||
|
|
||||||
2010-03-14 Version 0.8.8 released
|
2010-03-14 Version 0.8.8 released
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue