authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-05-07 20:03:27-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-05-07 20:03:27-07:00
logd577654e66e3a69592df2a37817260b59a2a190b
tree77573b1d6986362eafadc5b93f009b155c351392
parent81d5104e228dc30184b31158c1b36ec0ec371b0b

stage2: fix stack overflow in `@setEvalBranchQuota` test case

Some of the reworkings in this branch put us over the limit, on Linux, where the kernel disregards the fact that we ask for 16 MiB in the ELF file. So we ask for more stack space in `main`.

3 files changed, 69 insertions(+), 45 deletions(-)

src/Module.zig+1-1
......@@ -1088,7 +1088,7 @@ pub const Scope = struct {
10881088 /// for the one that will be the same for all Block instances.
10891089 src_decl: *Decl,
10901090 instructions: ArrayListUnmanaged(*ir.Inst),
1091 label: ?Label = null,
1091 label: ?*Label = null,
10921092 inlining: ?*Inlining,
10931093 is_comptime: bool,
10941094
src/Sema.zig+56-44
......@@ -1610,8 +1610,7 @@ fn zirLoop(sema: *Sema, parent_block: *Scope.Block, inst: Zir.Inst.Index) InnerE
16101610 .body = undefined,
16111611 };
16121612
1613 var child_block = parent_block.makeSubBlock();
1614 child_block.label = Scope.Block.Label{
1613 var label: Scope.Block.Label = .{
16151614 .zir_block = inst,
16161615 .merges = .{
16171616 .results = .{},
......@@ -1619,6 +1618,8 @@ fn zirLoop(sema: *Sema, parent_block: *Scope.Block, inst: Zir.Inst.Index) InnerE
16191618 .block_inst = block_inst,
16201619 },
16211620 };
1621 var child_block = parent_block.makeSubBlock();
1622 child_block.label = &label;
16221623 const merges = &child_block.label.?.merges;
16231624
16241625 defer child_block.instructions.deinit(sema.gpa);
......@@ -1689,20 +1690,21 @@ fn zirBlock(sema: *Sema, parent_block: *Scope.Block, inst: Zir.Inst.Index) Inner
16891690 .body = undefined,
16901691 };
16911692
1693 var label: Scope.Block.Label = .{
1694 .zir_block = inst,
1695 .merges = .{
1696 .results = .{},
1697 .br_list = .{},
1698 .block_inst = block_inst,
1699 },
1700 };
1701
16921702 var child_block: Scope.Block = .{
16931703 .parent = parent_block,
16941704 .sema = sema,
16951705 .src_decl = parent_block.src_decl,
16961706 .instructions = .{},
1697 // TODO @as here is working around a stage1 miscompilation bug :(
1698 .label = @as(?Scope.Block.Label, Scope.Block.Label{
1699 .zir_block = inst,
1700 .merges = .{
1701 .results = .{},
1702 .br_list = .{},
1703 .block_inst = block_inst,
1704 },
1705 }),
1707 .label = &label,
17061708 .inlining = parent_block.inlining,
17071709 .is_comptime = parent_block.is_comptime,
17081710 };
......@@ -1895,7 +1897,7 @@ fn zirBreak(sema: *Sema, start_block: *Scope.Block, inst: Zir.Inst.Index) InnerE
18951897
18961898 var block = start_block;
18971899 while (true) {
1898 if (block.label) |*label| {
1900 if (block.label) |label| {
18991901 if (label.zir_block == zir_block) {
19001902 // Here we add a br instruction, but we over-allocate a little bit
19011903 // (if necessary) to make it possible to convert the instruction into
......@@ -2084,26 +2086,38 @@ fn analyzeCall(
20842086 .block_inst = block_inst,
20852087 },
20862088 };
2087 const callee_zir = module_fn.owner_decl.namespace.file_scope.zir;
2088 var inline_sema: Sema = .{
2089 .mod = sema.mod,
2090 .gpa = sema.mod.gpa,
2091 .arena = sema.arena,
2092 .code = callee_zir,
2093 .inst_map = try sema.gpa.alloc(*ir.Inst, callee_zir.instructions.len),
2094 .owner_decl = sema.owner_decl,
2095 .namespace = sema.owner_decl.namespace,
2096 .owner_func = sema.owner_func,
2097 .func = module_fn,
2098 .param_inst_list = casted_args,
2099 .branch_quota = sema.branch_quota,
2100 .branch_count = sema.branch_count,
2101 };
2102 defer sema.gpa.free(inline_sema.inst_map);
2089 // In order to save a bit of stack space, directly modify Sema rather
2090 // than create a child one.
2091 const parent_zir = sema.code;
2092 sema.code = module_fn.owner_decl.namespace.file_scope.zir;
2093 defer sema.code = parent_zir;
2094
2095 const parent_inst_map = sema.inst_map;
2096 sema.inst_map = try sema.gpa.alloc(*ir.Inst, sema.code.instructions.len);
2097 defer {
2098 sema.gpa.free(sema.inst_map);
2099 sema.inst_map = parent_inst_map;
2100 }
2101
2102 const parent_namespace = sema.namespace;
2103 sema.namespace = module_fn.owner_decl.namespace;
2104 defer sema.namespace = parent_namespace;
2105
2106 const parent_func = sema.func;
2107 sema.func = module_fn;
2108 defer sema.func = parent_func;
2109
2110 const parent_param_inst_list = sema.param_inst_list;
2111 sema.param_inst_list = casted_args;
2112 defer sema.param_inst_list = parent_param_inst_list;
2113
2114 const parent_next_arg_index = sema.next_arg_index;
2115 sema.next_arg_index = 0;
2116 defer sema.next_arg_index = parent_next_arg_index;
21032117
21042118 var child_block: Scope.Block = .{
21052119 .parent = null,
2106 .sema = &inline_sema,
2120 .sema = sema,
21072121 .src_decl = module_fn.owner_decl,
21082122 .instructions = .{},
21092123 .label = null,
......@@ -2117,16 +2131,13 @@ fn analyzeCall(
21172131 defer merges.results.deinit(sema.gpa);
21182132 defer merges.br_list.deinit(sema.gpa);
21192133
2120 try inline_sema.emitBackwardBranch(&child_block, call_src);
2134 try sema.emitBackwardBranch(&child_block, call_src);
21212135
21222136 // This will have return instructions analyzed as break instructions to
21232137 // the block_inst above.
2124 try inline_sema.analyzeFnBody(&child_block, module_fn.zir_body_inst);
2138 try sema.analyzeFnBody(&child_block, module_fn.zir_body_inst);
21252139
2126 const result = try inline_sema.analyzeBlockBody(block, call_src, &child_block, merges);
2127
2128 sema.branch_quota = inline_sema.branch_quota;
2129 sema.branch_count = inline_sema.branch_count;
2140 const result = try sema.analyzeBlockBody(block, call_src, &child_block, merges);
21302141
21312142 break :res result;
21322143 } else res: {
......@@ -3797,20 +3808,21 @@ fn analyzeSwitch(
37973808 .body = undefined,
37983809 };
37993810
3811 var label: Scope.Block.Label = .{
3812 .zir_block = switch_inst,
3813 .merges = .{
3814 .results = .{},
3815 .br_list = .{},
3816 .block_inst = block_inst,
3817 },
3818 };
3819
38003820 var child_block: Scope.Block = .{
38013821 .parent = block,
38023822 .sema = sema,
38033823 .src_decl = block.src_decl,
38043824 .instructions = .{},
3805 // TODO @as here is working around a stage1 miscompilation bug :(
3806 .label = @as(?Scope.Block.Label, Scope.Block.Label{
3807 .zir_block = switch_inst,
3808 .merges = .{
3809 .results = .{},
3810 .br_list = .{},
3811 .block_inst = block_inst,
3812 },
3813 }),
3825 .label = &label,
38143826 .inlining = block.inlining,
38153827 .is_comptime = block.is_comptime,
38163828 };
src/main.zig+12
......@@ -180,6 +180,18 @@ pub fn mainArgs(gpa: *Allocator, arena: *Allocator, args: []const []const u8) !v
180180
181181 defer log_scopes.deinit(gpa);
182182
183 if (@import("builtin").target.os.tag == .linux) {
184 // Linux does not respect the stack size specified in the ELF, so we
185 // have to do this at runtime. TODO move this code to start.zig using
186 // the GNU_STACK program header.
187 std.os.setrlimit(.STACK, .{
188 .cur = 16 * 1024 * 1024,
189 .max = 16 * 1024 * 1024,
190 }) catch |err| {
191 warn("unable to increase stack size to 16 MiB", .{});
192 };
193 }
194
183195 const cmd = args[1];
184196 const cmd_args = args[2..];
185197 if (mem.eql(u8, cmd, "build-exe")) {