diff options
author | Reimer Behrends <behrends@gmail.com> | 2014-07-23 03:20:50 +0200 |
---|---|---|
committer | Reimer Behrends <behrends@gmail.com> | 2014-07-23 03:20:50 +0200 |
commit | 15734009ca9077cfc8c4139b8258b2db2d7492dd (patch) | |
tree | bf57ccd859e64dfd2bd86709585f903e33771a09 | |
parent | dcf1425eb996db5d39a23c0360573f1addd4a850 (diff) | |
download | Nim-15734009ca9077cfc8c4139b8258b2db2d7492dd.tar.gz |
More robust implementation for finding the beginning of the stack.
This patch inserts an extra stack frame above the function that calls the actual Nimrod code and ensures that a reference to this frame is stored as the stack bottom.
-rw-r--r-- | compiler/cgen.nim | 25 | ||||
-rw-r--r-- | lib/system.nim | 6 |
2 files changed, 23 insertions, 8 deletions
diff --git a/compiler/cgen.nim b/compiler/cgen.nim index e2f3b5ab0..d7a9d3c9d 100644 --- a/compiler/cgen.nim +++ b/compiler/cgen.nim @@ -954,8 +954,7 @@ proc genMainProc(m: BModule) = "\tsystemInit();$N" & "$1" & "$2" & - "$3" & - "$4" + "$3" MainProcs = "\tNimMain();$N" @@ -963,10 +962,19 @@ proc genMainProc(m: BModule) = MainProcsWithResult = MainProcs & "\treturn nim_program_result;$N" + # The use of a volatile function pointer to call NimMainInner + # prevents inlining of the NimMainInner function and dependent + # functions, which might otherwise merge their stack frames. NimMainBody = - "N_CDECL(void, NimMain)(void) {$N" & + "N_CDECL(void, NimMainInner)(void) {$N" & "\tPreMain();$N" & "$1" & + "}$N$N" & + "N_CDECL(void, NimMain)(void) {$N" & + "\tvoid (*volatile inner)();$N" & + "\tinner = NimMainInner;$N" & + "$2" & + "\t(*inner)();$N" & "}$N$N" PosixNimMain = @@ -1034,14 +1042,15 @@ proc genMainProc(m: BModule) = if optEndb in gOptions: gBreakpoints.app(m.genFilenames) - let initStackBottomCall = if emulatedThreadVars() or - platform.targetOS == osStandalone: "".toRope - else: ropecg(m, "\t#initStackBottom();$N") + let initStackBottomCall = + if emulatedThreadVars() or + platform.targetOS == osStandalone: "".toRope + else: ropecg(m, "\t#initStackBottomWith((void *)&inner);$N") inc(m.labels) appcg(m, m.s[cfsProcs], "void PreMain() {$N" & PreMainBody & "}$N$N", [ - mainDatInit, initStackBottomCall, gBreakpoints, otherModsInit]) + mainDatInit, gBreakpoints, otherModsInit]) - appcg(m, m.s[cfsProcs], nimMain, [mainModInit, toRope(m.labels)]) + appcg(m, m.s[cfsProcs], nimMain, [mainModInit, initStackBottomCall, toRope(m.labels)]) if optNoMain notin gGlobalOptions: appcg(m, m.s[cfsProcs], otherMain, []) diff --git a/lib/system.nim b/lib/system.nim index 753205777..361e94462 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -2115,6 +2115,12 @@ when not defined(JS): #and not defined(NimrodVM): locals = addr(locals) setStackBottom(locals) + proc initStackBottomWith(locals: pointer) {.inline, compilerproc.} = + # We need to keep initStackBottom around for now to avoid + # bootstrapping problems. + when defined(setStackBottom): + setStackBottom(locals) + var strDesc: TNimType |