Skip to content

Commit a6754f7

Browse files
committed
llvmgen: fix stack location allocation
Emit all `alloca`s at the start of functions, fixing the stack growth issues.
1 parent c170447 commit a6754f7

File tree

2 files changed

+22
-11
lines changed

2 files changed

+22
-11
lines changed

compiler/backend/llvmgen.nim

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@ type
4141
metadata: string
4242
## code defining the named metadata
4343

44+
allocs: string
45+
## all 'alloca' instruction for the current procedure
46+
4447
output: string
4548
currLine: uint16
4649
currFile: StringId
@@ -717,18 +720,20 @@ proc callToC(m; pos; musttail: bool, r: var Writer): Value =
717720

718721
if typ.kind == tkAggregate:
719722
# the value is returned through an out parameter
720-
let ret = r.newTemp()
721723
if args.len > 0:
722724
args.insert ", "
723725

724726
if musttail:
725727
# forward the current out parameter
726728
r.add &"musttail call {cconv} void {callee.val}(ptr sret({typ}) %Result{args})\n"
727-
makeIndirect(typ, ret)
729+
makeVal(VoidType, "")
728730
else:
729-
r.add &"{ret} = alloca {typ}\n"
730-
r.add &"call {cconv} void {callee.val}(ptr sret({typ}) {ret}{args})\n"
731-
makeIndirect(typ, ret)
731+
# manually create a temporary, as we need a name that's not just a number
732+
let name = r.nextTemp
733+
inc r.nextTemp
734+
r.allocs.add &"%temp.{name} = alloca {typ}\n"
735+
r.add &"call {cconv} void {callee.val}(ptr sret({typ}) %temp.{name}{args})\n"
736+
makeIndirect(typ, &"%temp.{name}")
732737
elif typ.kind == tkVoid:
733738
if musttail:
734739
r.add "musttail "
@@ -1048,7 +1053,7 @@ proc stmtToC(m; pos; r: var Writer): bool =
10481053
let typ = typeRefToC(m, typName, r)
10491054
let name = advance(m.ast, pos).val.StringId
10501055

1051-
r.add &"%{m.get(name)} = alloca {typ}, align {align}\n"
1056+
r.allocs.add &"%{m.get(name)} = alloca {typ}, align {align}\n"
10521057
# r.add &" #dbg_declare()\n"
10531058
of cnkUnreachable:
10541059
r.add "unreachable\n"
@@ -2041,6 +2046,7 @@ define private i8 @NIM_UNLIKELY(i8 %0) alwaysinline {
20412046
r.add "inlinehint "
20422047

20432048
r.add "{\n"
2049+
let start = r.output.len
20442050
block:
20452051
# in the CGIR, all parameters are proper locations (i.e., they have
20462052
# an address). Conservatively commit all non-by-address parameters to
@@ -2058,15 +2064,20 @@ define private i8 @NIM_UNLIKELY(i8 %0) alwaysinline {
20582064
# so that their pointer is not unnecessarily commited to a stack
20592065
# location here
20602066
if typ.kind != tkAggregate:
2061-
r.add &"%{m.get(name)} = alloca {typ}\n"
2067+
r.allocs.add &"%{m.get(name)} = alloca {typ}\n"
20622068
r.add &"store {typ} %{i}, ptr %{m.get(name)}\n"
20632069

20642070
r.nextTemp = len(n) + 1 # +1 because of the implicit entry label
20652071

20662072
discard stmtToC(m, pos, r)
20672073
r.add "}\n"
2074+
# insert the 'alloca's at the start, so that all stack locations are
2075+
# allocated before any other instructions
2076+
r.output.insert r.allocs, start
2077+
20682078
# reset the procedure-local state:
20692079
r.labels.clear()
2080+
r.allocs.setLen(0)
20702081
r.nextLabel = 0
20712082
r.nextTemp = 0
20722083

compiler/nim.cfg

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,10 @@ define:nimPreviewFloatRoundtrip
88

99
@if windows:
1010
cincludes: "$lib/wrappers/libffi/common"
11-
# for whatever reason, LLVM emits code that locally leaks stack memory,
12-
# which can quickly exhaust the available space in loops with
13-
# many iterations
14-
passL: "-Wl,--stack,27388608"
11+
@if gcc:
12+
# use an 8MB stack to prevent overflows
13+
passL: "-Wl,--stack,8388608"
14+
@end
1515
@end
1616

1717
define:useStdoutAsStdmsg

0 commit comments

Comments
 (0)