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 {...@@ -1088,7 +1088,7 @@ pub const Scope = struct {
1088 /// for the one that will be the same for all Block instances.1088 /// for the one that will be the same for all Block instances.
1089 src_decl: *Decl,1089 src_decl: *Decl,
1090 instructions: ArrayListUnmanaged(*ir.Inst),1090 instructions: ArrayListUnmanaged(*ir.Inst),
1091 label: ?Label = null,1091 label: ?*Label = null,
1092 inlining: ?*Inlining,1092 inlining: ?*Inlining,
1093 is_comptime: bool,1093 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...@@ -1610,8 +1610,7 @@ fn zirLoop(sema: *Sema, parent_block: *Scope.Block, inst: Zir.Inst.Index) InnerE
1610 .body = undefined,1610 .body = undefined,
1611 };1611 };
16121612
1613 var child_block = parent_block.makeSubBlock();1613 var label: Scope.Block.Label = .{
1614 child_block.label = Scope.Block.Label{
1615 .zir_block = inst,1614 .zir_block = inst,
1616 .merges = .{1615 .merges = .{
1617 .results = .{},1616 .results = .{},
...@@ -1619,6 +1618,8 @@ fn zirLoop(sema: *Sema, parent_block: *Scope.Block, inst: Zir.Inst.Index) InnerE...@@ -1619,6 +1618,8 @@ fn zirLoop(sema: *Sema, parent_block: *Scope.Block, inst: Zir.Inst.Index) InnerE
1619 .block_inst = block_inst,1618 .block_inst = block_inst,
1620 },1619 },
1621 };1620 };
1621 var child_block = parent_block.makeSubBlock();
1622 child_block.label = &label;
1622 const merges = &child_block.label.?.merges;1623 const merges = &child_block.label.?.merges;
16231624
1624 defer child_block.instructions.deinit(sema.gpa);1625 defer child_block.instructions.deinit(sema.gpa);
...@@ -1689,20 +1690,21 @@ fn zirBlock(sema: *Sema, parent_block: *Scope.Block, inst: Zir.Inst.Index) Inner...@@ -1689,20 +1690,21 @@ fn zirBlock(sema: *Sema, parent_block: *Scope.Block, inst: Zir.Inst.Index) Inner
1689 .body = undefined,1690 .body = undefined,
1690 };1691 };
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
1692 var child_block: Scope.Block = .{1702 var child_block: Scope.Block = .{
1693 .parent = parent_block,1703 .parent = parent_block,
1694 .sema = sema,1704 .sema = sema,
1695 .src_decl = parent_block.src_decl,1705 .src_decl = parent_block.src_decl,
1696 .instructions = .{},1706 .instructions = .{},
1697 // TODO @as here is working around a stage1 miscompilation bug :(1707 .label = &label,
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 }),
1706 .inlining = parent_block.inlining,1708 .inlining = parent_block.inlining,
1707 .is_comptime = parent_block.is_comptime,1709 .is_comptime = parent_block.is_comptime,
1708 };1710 };
...@@ -1895,7 +1897,7 @@ fn zirBreak(sema: *Sema, start_block: *Scope.Block, inst: Zir.Inst.Index) InnerE...@@ -1895,7 +1897,7 @@ fn zirBreak(sema: *Sema, start_block: *Scope.Block, inst: Zir.Inst.Index) InnerE
18951897
1896 var block = start_block;1898 var block = start_block;
1897 while (true) {1899 while (true) {
1898 if (block.label) |*label| {1900 if (block.label) |label| {
1899 if (label.zir_block == zir_block) {1901 if (label.zir_block == zir_block) {
1900 // Here we add a br instruction, but we over-allocate a little bit1902 // Here we add a br instruction, but we over-allocate a little bit
1901 // (if necessary) to make it possible to convert the instruction into1903 // (if necessary) to make it possible to convert the instruction into
...@@ -2084,26 +2086,38 @@ fn analyzeCall(...@@ -2084,26 +2086,38 @@ fn analyzeCall(
2084 .block_inst = block_inst,2086 .block_inst = block_inst,
2085 },2087 },
2086 };2088 };
2087 const callee_zir = module_fn.owner_decl.namespace.file_scope.zir;2089 // In order to save a bit of stack space, directly modify Sema rather
2088 var inline_sema: Sema = .{2090 // than create a child one.
2089 .mod = sema.mod,2091 const parent_zir = sema.code;
2090 .gpa = sema.mod.gpa,2092 sema.code = module_fn.owner_decl.namespace.file_scope.zir;
2091 .arena = sema.arena,2093 defer sema.code = parent_zir;
2092 .code = callee_zir,2094
2093 .inst_map = try sema.gpa.alloc(*ir.Inst, callee_zir.instructions.len),2095 const parent_inst_map = sema.inst_map;
2094 .owner_decl = sema.owner_decl,2096 sema.inst_map = try sema.gpa.alloc(*ir.Inst, sema.code.instructions.len);
2095 .namespace = sema.owner_decl.namespace,2097 defer {
2096 .owner_func = sema.owner_func,2098 sema.gpa.free(sema.inst_map);
2097 .func = module_fn,2099 sema.inst_map = parent_inst_map;
2098 .param_inst_list = casted_args,2100 }
2099 .branch_quota = sema.branch_quota,2101
2100 .branch_count = sema.branch_count,2102 const parent_namespace = sema.namespace;
2101 };2103 sema.namespace = module_fn.owner_decl.namespace;
2102 defer sema.gpa.free(inline_sema.inst_map);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
2104 var child_block: Scope.Block = .{2118 var child_block: Scope.Block = .{
2105 .parent = null,2119 .parent = null,
2106 .sema = &inline_sema,2120 .sema = sema,
2107 .src_decl = module_fn.owner_decl,2121 .src_decl = module_fn.owner_decl,
2108 .instructions = .{},2122 .instructions = .{},
2109 .label = null,2123 .label = null,
...@@ -2117,16 +2131,13 @@ fn analyzeCall(...@@ -2117,16 +2131,13 @@ fn analyzeCall(
2117 defer merges.results.deinit(sema.gpa);2131 defer merges.results.deinit(sema.gpa);
2118 defer merges.br_list.deinit(sema.gpa);2132 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
2122 // This will have return instructions analyzed as break instructions to2136 // This will have return instructions analyzed as break instructions to
2123 // the block_inst above.2137 // 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);2140 const result = try 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;
21302141
2131 break :res result;2142 break :res result;
2132 } else res: {2143 } else res: {
...@@ -3797,20 +3808,21 @@ fn analyzeSwitch(...@@ -3797,20 +3808,21 @@ fn analyzeSwitch(
3797 .body = undefined,3808 .body = undefined,
3798 };3809 };
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
3800 var child_block: Scope.Block = .{3820 var child_block: Scope.Block = .{
3801 .parent = block,3821 .parent = block,
3802 .sema = sema,3822 .sema = sema,
3803 .src_decl = block.src_decl,3823 .src_decl = block.src_decl,
3804 .instructions = .{},3824 .instructions = .{},
3805 // TODO @as here is working around a stage1 miscompilation bug :(3825 .label = &label,
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 }),
3814 .inlining = block.inlining,3826 .inlining = block.inlining,
3815 .is_comptime = block.is_comptime,3827 .is_comptime = block.is_comptime,
3816 };3828 };
src/main.zig+12
...@@ -180,6 +180,18 @@ pub fn mainArgs(gpa: *Allocator, arena: *Allocator, args: []const []const u8) !v...@@ -180,6 +180,18 @@ pub fn mainArgs(gpa: *Allocator, arena: *Allocator, args: []const []const u8) !v
180180
181 defer log_scopes.deinit(gpa);181 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
183 const cmd = args[1];195 const cmd = args[1];
184 const cmd_args = args[2..];196 const cmd_args = args[2..];
185 if (mem.eql(u8, cmd, "build-exe")) {197 if (mem.eql(u8, cmd, "build-exe")) {