aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/AstGen.zig119
-rw-r--r--src/Module.zig33
2 files changed, 76 insertions, 76 deletions
diff --git a/src/AstGen.zig b/src/AstGen.zig
index cc80d5d752..b617c534e1 100644
--- a/src/AstGen.zig
+++ b/src/AstGen.zig
@@ -138,7 +138,7 @@ pub const ResultLoc = union(enum) {
/// There is a pointer for the expression to store its result into, however, its type
/// is inferred based on peer type resolution for a `zir.Inst.Block`.
/// The result instruction from the expression must be ignored.
- block_ptr: *Module.Scope.GenZir,
+ block_ptr: *Scope.GenZir,
pub const Strategy = struct {
elide_store_to_block_ptr_instructions: bool,
@@ -154,6 +154,41 @@ pub const ResultLoc = union(enum) {
break_operand,
};
};
+
+ fn strategy(rl: ResultLoc, block_scope: *Scope.GenZir) Strategy {
+ var elide_store_to_block_ptr_instructions = false;
+ switch (rl) {
+ // In this branch there will not be any store_to_block_ptr instructions.
+ .discard, .none, .ty, .ref => return .{
+ .tag = .break_operand,
+ .elide_store_to_block_ptr_instructions = false,
+ },
+ // The pointer got passed through to the sub-expressions, so we will use
+ // break_void here.
+ // In this branch there will not be any store_to_block_ptr instructions.
+ .ptr => return .{
+ .tag = .break_void,
+ .elide_store_to_block_ptr_instructions = false,
+ },
+ .inferred_ptr, .bitcasted_ptr, .block_ptr => {
+ if (block_scope.rvalue_rl_count == block_scope.break_count) {
+ // Neither prong of the if consumed the result location, so we can
+ // use break instructions to create an rvalue.
+ return .{
+ .tag = .break_operand,
+ .elide_store_to_block_ptr_instructions = true,
+ };
+ } else {
+ // Allow the store_to_block_ptr instructions to remain so that
+ // semantic analysis can turn them into bitcasts.
+ return .{
+ .tag = .break_void,
+ .elide_store_to_block_ptr_instructions = false,
+ };
+ }
+ },
+ }
+ }
};
pub fn typeExpr(mod: *Module, scope: *Scope, type_node: ast.Node.Index) InnerError!zir.Inst.Ref {
@@ -989,7 +1024,7 @@ fn labeledBlockExpr(
.block_inst = block_inst,
}),
};
- setBlockResultLoc(&block_scope, rl);
+ block_scope.setBreakResultLoc(rl);
defer block_scope.instructions.deinit(mod.gpa);
defer block_scope.labeled_breaks.deinit(mod.gpa);
defer block_scope.labeled_store_to_block_ptr_list.deinit(mod.gpa);
@@ -1003,7 +1038,7 @@ fn labeledBlockExpr(
const zir_tags = gz.astgen.instructions.items(.tag);
const zir_datas = gz.astgen.instructions.items(.data);
- const strat = rlStrategy(rl, &block_scope);
+ const strat = rl.strategy(&block_scope);
switch (strat.tag) {
.break_void => {
// The code took advantage of the result location as a pointer.
@@ -1740,7 +1775,7 @@ fn orelseCatchExpr(
.force_comptime = parent_gz.force_comptime,
.instructions = .{},
};
- setBlockResultLoc(&block_scope, rl);
+ block_scope.setBreakResultLoc(rl);
defer block_scope.instructions.deinit(mod.gpa);
// This could be a pointer or value depending on the `operand_rl` parameter.
@@ -1856,7 +1891,7 @@ fn finishThenElseBlock(
) InnerError!zir.Inst.Ref {
// We now have enough information to decide whether the result instruction should
// be communicated via result location pointer or break instructions.
- const strat = rlStrategy(rl, block_scope);
+ const strat = rl.strategy(block_scope);
const astgen = block_scope.astgen;
switch (strat.tag) {
.break_void => {
@@ -2035,7 +2070,7 @@ fn ifExpr(
.force_comptime = parent_gz.force_comptime,
.instructions = .{},
};
- setBlockResultLoc(&block_scope, rl);
+ block_scope.setBreakResultLoc(rl);
defer block_scope.instructions.deinit(mod.gpa);
const cond = c: {
@@ -2190,7 +2225,7 @@ fn whileExpr(
.force_comptime = parent_gz.force_comptime,
.instructions = .{},
};
- setBlockResultLoc(&loop_scope, rl);
+ loop_scope.setBreakResultLoc(rl);
defer loop_scope.instructions.deinit(mod.gpa);
var continue_scope: Scope.GenZir = .{
@@ -2338,7 +2373,7 @@ fn forExpr(
.force_comptime = parent_gz.force_comptime,
.instructions = .{},
};
- setBlockResultLoc(&loop_scope, rl);
+ loop_scope.setBreakResultLoc(rl);
defer loop_scope.instructions.deinit(mod.gpa);
var cond_scope: Scope.GenZir = .{
@@ -2520,7 +2555,7 @@ fn switchExpr(
.force_comptime = parent_gz.force_comptime,
.instructions = .{},
};
- setBlockResultLoc(&block_scope, rl);
+ block_scope.setBreakResultLoc(rl);
defer block_scope.instructions.deinit(mod.gpa);
var items = std.ArrayList(zir.Inst.Ref).init(mod.gpa);
@@ -3911,69 +3946,3 @@ fn rvalue(
},
}
}
-
-fn rlStrategy(rl: ResultLoc, block_scope: *Scope.GenZir) ResultLoc.Strategy {
- var elide_store_to_block_ptr_instructions = false;
- switch (rl) {
- // In this branch there will not be any store_to_block_ptr instructions.
- .discard, .none, .ty, .ref => return .{
- .tag = .break_operand,
- .elide_store_to_block_ptr_instructions = false,
- },
- // The pointer got passed through to the sub-expressions, so we will use
- // break_void here.
- // In this branch there will not be any store_to_block_ptr instructions.
- .ptr => return .{
- .tag = .break_void,
- .elide_store_to_block_ptr_instructions = false,
- },
- .inferred_ptr, .bitcasted_ptr, .block_ptr => {
- if (block_scope.rvalue_rl_count == block_scope.break_count) {
- // Neither prong of the if consumed the result location, so we can
- // use break instructions to create an rvalue.
- return .{
- .tag = .break_operand,
- .elide_store_to_block_ptr_instructions = true,
- };
- } else {
- // Allow the store_to_block_ptr instructions to remain so that
- // semantic analysis can turn them into bitcasts.
- return .{
- .tag = .break_void,
- .elide_store_to_block_ptr_instructions = false,
- };
- }
- },
- }
-}
-
-fn setBlockResultLoc(block_scope: *Scope.GenZir, parent_rl: ResultLoc) void {
- // Depending on whether the result location is a pointer or value, different
- // ZIR needs to be generated. In the former case we rely on storing to the
- // pointer to communicate the result, and use breakvoid; in the latter case
- // the block break instructions will have the result values.
- // One more complication: when the result location is a pointer, we detect
- // the scenario where the result location is not consumed. In this case
- // we emit ZIR for the block break instructions to have the result values,
- // and then rvalue() on that to pass the value to the result location.
- switch (parent_rl) {
- .discard, .none, .ty, .ptr, .ref => {
- block_scope.break_result_loc = parent_rl;
- },
-
- .inferred_ptr => |ptr| {
- block_scope.rl_ptr = ptr;
- block_scope.break_result_loc = .{ .block_ptr = block_scope };
- },
-
- .bitcasted_ptr => |ptr| {
- block_scope.rl_ptr = ptr;
- block_scope.break_result_loc = .{ .block_ptr = block_scope };
- },
-
- .block_ptr => |parent_block_scope| {
- block_scope.rl_ptr = parent_block_scope.rl_ptr;
- block_scope.break_result_loc = .{ .block_ptr = block_scope };
- },
- }
-}
diff --git a/src/Module.zig b/src/Module.zig
index de26043050..46b402d7d7 100644
--- a/src/Module.zig
+++ b/src/Module.zig
@@ -920,7 +920,7 @@ pub const Scope = struct {
label: ?Label = null,
break_block: zir.Inst.Index = 0,
continue_block: zir.Inst.Index = 0,
- /// Only valid when setBlockResultLoc is called.
+ /// Only valid when setBreakResultLoc is called.
break_result_loc: AstGen.ResultLoc = undefined,
/// When a block has a pointer result location, here it is.
rl_ptr: zir.Inst.Ref = .none,
@@ -973,6 +973,37 @@ pub const Scope = struct {
return &gz.astgen.decl.container.file_scope.tree;
}
+ pub fn setBreakResultLoc(gz: *GenZir, parent_rl: AstGen.ResultLoc) void {
+ // Depending on whether the result location is a pointer or value, different
+ // ZIR needs to be generated. In the former case we rely on storing to the
+ // pointer to communicate the result, and use breakvoid; in the latter case
+ // the block break instructions will have the result values.
+ // One more complication: when the result location is a pointer, we detect
+ // the scenario where the result location is not consumed. In this case
+ // we emit ZIR for the block break instructions to have the result values,
+ // and then rvalue() on that to pass the value to the result location.
+ switch (parent_rl) {
+ .discard, .none, .ty, .ptr, .ref => {
+ gz.break_result_loc = parent_rl;
+ },
+
+ .inferred_ptr => |ptr| {
+ gz.rl_ptr = ptr;
+ gz.break_result_loc = .{ .block_ptr = gz };
+ },
+
+ .bitcasted_ptr => |ptr| {
+ gz.rl_ptr = ptr;
+ gz.break_result_loc = .{ .block_ptr = gz };
+ },
+
+ .block_ptr => |parent_block_scope| {
+ gz.rl_ptr = parent_block_scope.rl_ptr;
+ gz.break_result_loc = .{ .block_ptr = gz };
+ },
+ }
+ }
+
pub fn setBoolBrBody(gz: GenZir, inst: zir.Inst.Index) !void {
const gpa = gz.astgen.mod.gpa;
try gz.astgen.extra.ensureCapacity(gpa, gz.astgen.extra.items.len +