labeledBlockExpr
Function parameters
Parameters
- gz:*GenZir
- parent_scope:*Scope
- block_node:Ast.Node.Index
- statements:[]const Ast.Node.Index
- force_comptime:bool
Functions in this namespace
Functions
Source
Implementation
fn labeledBlockExpr(
gz: *GenZir,
parent_scope: *Scope,
ri: ResultInfo,
block_node: Ast.Node.Index,
statements: []const Ast.Node.Index,
force_comptime: bool,
block_kind: BlockKind,
) InnerError!Zir.Inst.Ref {
const astgen = gz.astgen;
const tree = astgen.tree;
const lbrace = tree.nodeMainToken(block_node);
const label_token = lbrace - 2;
assert(tree.tokenTag(label_token) == .identifier);
try astgen.checkLabelRedefinition(parent_scope, label_token);
const need_rl = astgen.nodes_need_rl.contains(block_node);
const block_ri: ResultInfo = if (need_rl) ri else .{
.rl = switch (ri.rl) {
.ptr => .{ .ty = (try ri.rl.resultType(gz, block_node)).? },
.inferred_ptr => .none,
else => ri.rl,
},
.ctx = ri.ctx,
};
// We need to call `rvalue` to write through to the pointer only if we had a
// result pointer and aren't forwarding it.
const LocTag = @typeInfo(ResultInfo.Loc).@"union".tag_type.?;
const need_result_rvalue = @as(LocTag, block_ri.rl) != @as(LocTag, ri.rl);
// Reserve the Block ZIR instruction index so that we can put it into the GenZir struct
// so that break statements can reference it.
const block_inst = try gz.makeBlockInst(if (force_comptime) .block_comptime else .block, block_node);
try gz.instructions.append(astgen.gpa, block_inst);
var block_scope = gz.makeSubBlock(parent_scope);
block_scope.is_inline = force_comptime;
block_scope.label = GenZir.Label{
.token = label_token,
.block_inst = block_inst,
};
block_scope.setBreakResultInfo(block_ri);
if (force_comptime) block_scope.is_comptime = true;
defer block_scope.unstack();
try blockExprStmts(&block_scope, &block_scope.base, statements, block_kind);
if (!block_scope.endsWithNoReturn()) {
// As our last action before the return, "pop" the error trace if needed
_ = try gz.addRestoreErrRetIndex(.{ .block = block_inst }, .always, block_node);
const result = try rvalue(gz, block_scope.break_result_info, .void_value, block_node);
const break_tag: Zir.Inst.Tag = if (force_comptime) .break_inline else .@"break";
_ = try block_scope.addBreak(break_tag, block_inst, result);
}
if (!block_scope.label.?.used) {
try astgen.appendErrorTok(label_token, "unused block label", .{});
}
if (force_comptime) {
try block_scope.setBlockComptimeBody(block_inst, .comptime_keyword);
} else {
try block_scope.setBlockBody(block_inst);
}
if (need_result_rvalue) {
return rvalue(gz, ri, block_inst.toRef(), block_node);
} else {
return block_inst.toRef();
}
}