mirror of
https://github.com/nim-lang/Nim.git
synced 2026-06-07 12:24:19 +00:00
DLL generation of the stdlib for unix
This commit is contained in:
@@ -431,4 +431,6 @@ struct NimException {
|
||||
};
|
||||
#endif
|
||||
|
||||
#define NIM_POSIX_INIT __attribute__((constructor))
|
||||
|
||||
#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: 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/cgprocs"
|
||||
@@ -771,59 +821,10 @@ type # these work for most platforms:
|
||||
## high value is large enough to disable bounds checking in practice.
|
||||
## 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``
|
||||
PFloat64* = ptr Float64 ## an alias for ``ptr float64``
|
||||
PInt64* = ptr Int64 ## an alias for ``ptr int64``
|
||||
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 {.
|
||||
magic: "ToFloat", noSideEffect, importc: "toFloat".}
|
||||
@@ -1305,7 +1306,10 @@ when not defined(EcmaScript) and not defined(NimrodVM):
|
||||
proc initGC()
|
||||
|
||||
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))
|
||||
|
||||
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 setStackBottom(theStackBottom: pointer) {.compilerRtl.}
|
||||
proc setStackBottom(theStackBottom: pointer) {.compilerRtl, noinline.}
|
||||
|
||||
|
||||
|
||||
@@ -491,10 +491,11 @@ else:
|
||||
const stackIncreases = false
|
||||
|
||||
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:
|
||||
if stackBottom == nil: stackBottom = theStackBottom
|
||||
else:
|
||||
var a = cast[TAddress](theStackBottom)
|
||||
var a = cast[TAddress](theStackBottom) # and not PageMask - PageSize*2
|
||||
var b = cast[TAddress](stackBottom)
|
||||
when stackIncreases:
|
||||
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) =
|
||||
const
|
||||
CommonMainBody = " #setStackBottom(dummy);$n" & " nim__datInit();$n" &
|
||||
" systemInit();$n" & "$1" & "$2"
|
||||
CommonMainBodyLLVM = " %MOC$3 = bitcast [8 x %NI]* %dummy to i8*$n" &
|
||||
" call void @#setStackBottom(i8* %MOC$3)$n" &
|
||||
" call void @nim__datInit()$n" & " call void systemInit()$n" & "$1" &
|
||||
CommonMainBody =
|
||||
" nim__datInit();$n" &
|
||||
" systemInit();$n" &
|
||||
"$1" &
|
||||
"$2"
|
||||
PosixNimMain = "int cmdCount;$n" & "char** cmdLine;$n" & "char** gEnv;$n" &
|
||||
"N_CDECL(void, NimMain)(void) {$n" & " int dummy[8];$n" &
|
||||
PosixNimMain =
|
||||
"int cmdCount;$n" &
|
||||
"char** cmdLine;$n" &
|
||||
"char** gEnv;$n" &
|
||||
"N_CDECL(void, NimMain)(void) {$n" &
|
||||
CommonMainBody & "}$n"
|
||||
PosixCMain = "int main(int argc, char** args, char** env) {$n" &
|
||||
" cmdLine = args;$n" & " cmdCount = argc;$n" & " gEnv = env;$n" &
|
||||
" NimMain();$n" & " return 0;$n" & "}$n"
|
||||
PosixNimMainLLVM = "@cmdCount = linkonce i32$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" &
|
||||
WinNimMain = "N_CDECL(void, NimMain)(void) {$n" &
|
||||
CommonMainBody & "}$n"
|
||||
WinCMain = "N_STDCALL(int, WinMain)(HINSTANCE hCurInstance, $n" &
|
||||
" HINSTANCE hPrevInstance, $n" &
|
||||
" LPSTR lpCmdLine, int nCmdShow) {$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" &
|
||||
" int dummy[8];$n" & CommonMainBody & "}$n"
|
||||
CommonMainBody & "}$n"
|
||||
WinCDllMain = "BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fwdreason, $n" &
|
||||
" LPVOID lpvReserved) {$n" & " NimMain();$n" &
|
||||
" return 1;$n" & "}$n"
|
||||
WinNimDllMainLLVM = WinNimMainLLVM
|
||||
WinCDllMainLLVM =
|
||||
"define stdcall i32 @DllMain(i32 %hinstDLL, i32 %fwdreason, $n" &
|
||||
" i8* %lpvReserved) {$n" &
|
||||
" call void @NimMain()$n" & " ret i32 1$n" & "}$n"
|
||||
PosixNimDllMain = WinNimDllMain
|
||||
PosixCDllMain =
|
||||
"void NIM_POSIX_INIT NimMainInit(void) {$n" &
|
||||
" NimMain();$n}$n"
|
||||
var nimMain, otherMain: TFormatStr
|
||||
if (platform.targetOS == osWindows) and
|
||||
(gGlobalOptions * {optGenGuiApp, optGenDynLib} != {}):
|
||||
if optGenGuiApp in gGlobalOptions:
|
||||
if gCmd == cmdCompileToLLVM:
|
||||
nimMain = WinNimMainLLVM
|
||||
otherMain = WinCMainLLVM
|
||||
else:
|
||||
nimMain = WinNimMain
|
||||
otherMain = WinCMain
|
||||
nimMain = WinNimMain
|
||||
otherMain = WinCMain
|
||||
else:
|
||||
if gCmd == cmdCompileToLLVM:
|
||||
nimMain = WinNimDllMainLLVM
|
||||
otherMain = WinCDllMainLLVM
|
||||
else:
|
||||
nimMain = WinNimDllMain
|
||||
otherMain = WinCDllMain
|
||||
nimMain = WinNimDllMain
|
||||
otherMain = WinCDllMain
|
||||
discard lists.IncludeStr(m.headerFiles, "<windows.h>")
|
||||
elif optGenDynLib in gGlobalOptions:
|
||||
nimMain = posixNimDllMain
|
||||
otherMain = posixCDllMain
|
||||
else:
|
||||
if gCmd == cmdCompileToLLVM:
|
||||
nimMain = PosixNimMainLLVM
|
||||
otherMain = PosixCMainLLVM
|
||||
else:
|
||||
nimMain = PosixNimMain
|
||||
otherMain = PosixCMain
|
||||
nimMain = PosixNimMain
|
||||
otherMain = PosixCMain
|
||||
if gBreakpoints != nil: discard cgsym(m, "dbgRegisterBreakpoint")
|
||||
inc(m.labels)
|
||||
appcg(m, m.s[cfsProcs], nimMain, [
|
||||
|
||||
@@ -28,15 +28,15 @@ type
|
||||
of nkList: sons: seq[PCaseNode]
|
||||
else: unused: seq[string]
|
||||
|
||||
TIdObj* = object of TObject
|
||||
id*: int # unique id; use this for comparisons and not the pointers
|
||||
|
||||
PIdObj* = ref TIdObj
|
||||
PIdent* = ref TIdent
|
||||
TIdent*{.acyclic.} = object of TIdObj
|
||||
s*: string
|
||||
next*: PIdent # for hash-table chaining
|
||||
h*: int # hash value of s
|
||||
TIdObj* = object of TObject
|
||||
id*: int # unique id; use this for comparisons and not the pointers
|
||||
|
||||
PIdObj* = ref TIdObj
|
||||
PIdent* = ref TIdent
|
||||
TIdent*{.acyclic.} = object of TIdObj
|
||||
s*: string
|
||||
next*: PIdent # for hash-table chaining
|
||||
h*: int # hash value of s
|
||||
|
||||
var
|
||||
flip: int
|
||||
@@ -145,8 +145,8 @@ proc buildBTree(father: var TBNode) =
|
||||
setSons(father)
|
||||
|
||||
proc getIdent(identifier: cstring, length: int, h: int): PIdent =
|
||||
new(result)
|
||||
result.h = h
|
||||
new(result)
|
||||
result.h = h
|
||||
result.s = newString(length)
|
||||
|
||||
proc main() =
|
||||
|
||||
1
todo.txt
1
todo.txt
@@ -1,7 +1,6 @@
|
||||
For version 0.8.10
|
||||
==================
|
||||
|
||||
- support for generation of dynamic libraries
|
||||
- fix exception handling
|
||||
- fix implicit generic routines
|
||||
- fix the streams implementation so that they use methods
|
||||
|
||||
@@ -58,6 +58,8 @@ Additions
|
||||
- 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.
|
||||
- The standard library can be built as a DLL. Generating DLLs has been
|
||||
improved.
|
||||
|
||||
|
||||
2010-03-14 Version 0.8.8 released
|
||||
|
||||
Reference in New Issue
Block a user