aboutsummaryrefslogtreecommitdiff
path: root/src/Sema.zig
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2021-06-08 14:16:57 -0400
committerGitHub <noreply@github.com>2021-06-08 14:16:57 -0400
commitccfa16828445ebf3634c2a0f27ec359af1628efc (patch)
tree0d73a532885fca9b9e6db9fdceb8f1e014cf495f /src/Sema.zig
parentc822a0b59fe123ff67bcb188f20290d818467be7 (diff)
parentd41a5105cd6222564dfe6bad9cff2c445847c6b3 (diff)
downloadzig-ccfa16828445ebf3634c2a0f27ec359af1628efc.tar.gz
zig-ccfa16828445ebf3634c2a0f27ec359af1628efc.zip
Merge pull request #9030 from Vexu/stage2
Stage2: implement comptime variables
Diffstat (limited to 'src/Sema.zig')
-rw-r--r--src/Sema.zig89
1 files changed, 83 insertions, 6 deletions
diff --git a/src/Sema.zig b/src/Sema.zig
index 718e145a7d..6145b8c137 100644
--- a/src/Sema.zig
+++ b/src/Sema.zig
@@ -147,7 +147,7 @@ pub fn analyzeBody(
// directly jump to the next one, rather than detouring through the loop
// continue expression. Related: https://github.com/ziglang/zig/issues/8220
var i: usize = 0;
- while (true) : (i += 1) {
+ while (true) {
const inst = body[i];
const air_inst = switch (tags[inst]) {
// zig fmt: off
@@ -394,78 +394,97 @@ pub fn analyzeBody(
// putting them into the map.
.breakpoint => {
try sema.zirBreakpoint(block, inst);
+ i += 1;
continue;
},
.fence => {
try sema.zirFence(block, inst);
+ i += 1;
continue;
},
.dbg_stmt => {
try sema.zirDbgStmt(block, inst);
+ i += 1;
continue;
},
.ensure_err_payload_void => {
try sema.zirEnsureErrPayloadVoid(block, inst);
+ i += 1;
continue;
},
.ensure_result_non_error => {
try sema.zirEnsureResultNonError(block, inst);
+ i += 1;
continue;
},
.ensure_result_used => {
try sema.zirEnsureResultUsed(block, inst);
+ i += 1;
continue;
},
.set_eval_branch_quota => {
try sema.zirSetEvalBranchQuota(block, inst);
+ i += 1;
continue;
},
.store => {
try sema.zirStore(block, inst);
+ i += 1;
continue;
},
.store_node => {
try sema.zirStoreNode(block, inst);
+ i += 1;
continue;
},
.store_to_block_ptr => {
try sema.zirStoreToBlockPtr(block, inst);
+ i += 1;
continue;
},
.store_to_inferred_ptr => {
try sema.zirStoreToInferredPtr(block, inst);
+ i += 1;
continue;
},
.resolve_inferred_alloc => {
try sema.zirResolveInferredAlloc(block, inst);
+ i += 1;
continue;
},
.validate_struct_init_ptr => {
try sema.zirValidateStructInitPtr(block, inst);
+ i += 1;
continue;
},
.validate_array_init_ptr => {
try sema.zirValidateArrayInitPtr(block, inst);
+ i += 1;
continue;
},
.@"export" => {
try sema.zirExport(block, inst);
+ i += 1;
continue;
},
.set_align_stack => {
try sema.zirSetAlignStack(block, inst);
+ i += 1;
continue;
},
.set_cold => {
try sema.zirSetAlignStack(block, inst);
+ i += 1;
continue;
},
.set_float_mode => {
try sema.zirSetFloatMode(block, inst);
+ i += 1;
continue;
},
.set_runtime_safety => {
try sema.zirSetRuntimeSafety(block, inst);
+ i += 1;
continue;
},
@@ -509,7 +528,8 @@ pub fn analyzeBody(
};
if (air_inst.ty.isNoReturn())
return always_noreturn;
- try map.putNoClobber(sema.gpa, inst, air_inst);
+ try map.put(sema.gpa, inst, air_inst);
+ i += 1;
}
}
@@ -1238,9 +1258,26 @@ fn zirAllocExtended(
}
fn zirAllocComptime(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
+ const tracy = trace(@src());
+ defer tracy.end();
+
const inst_data = sema.code.instructions.items(.data)[inst].un_node;
const src = inst_data.src();
- return sema.mod.fail(&block.base, src, "TODO implement Sema.zirAllocComptime", .{});
+ const ty_src: LazySrcLoc = .{ .node_offset_var_decl_ty = inst_data.src_node };
+ const var_type = try sema.resolveType(block, ty_src, inst_data.operand);
+ const ptr_type = try sema.mod.simplePtrType(sema.arena, var_type, true, .One);
+
+ const val_payload = try sema.arena.create(Value.Payload.ComptimeAlloc);
+ val_payload.* = .{
+ .data = .{
+ .runtime_index = block.runtime_index,
+ .val = undefined, // astgen guarantees there will be a store before the first load
+ },
+ };
+ return sema.mod.constInst(sema.arena, src, .{
+ .ty = ptr_type,
+ .val = Value.initPayload(&val_payload.base),
+ });
}
fn zirAllocInferredComptime(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
@@ -1742,6 +1779,9 @@ fn zirLoop(sema: *Sema, parent_block: *Scope.Block, inst: Zir.Inst.Index) InnerE
};
var child_block = parent_block.makeSubBlock();
child_block.label = &label;
+ child_block.runtime_cond = null;
+ child_block.runtime_loop = src;
+ child_block.runtime_index += 1;
const merges = &child_block.label.?.merges;
defer child_block.instructions.deinit(sema.gpa);
@@ -4066,6 +4106,9 @@ fn analyzeSwitch(
const cases = try sema.arena.alloc(Inst.SwitchBr.Case, scalar_cases_len);
var case_block = child_block.makeSubBlock();
+ case_block.runtime_loop = null;
+ case_block.runtime_cond = operand.src;
+ case_block.runtime_index += 1;
defer case_block.instructions.deinit(gpa);
var extra_index: usize = special.end;
@@ -4584,14 +4627,14 @@ fn zirArithmetic(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerEr
const tag_override = block.sema.code.instructions.items(.tag)[inst];
const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
- const src: LazySrcLoc = .{ .node_offset_bin_op = inst_data.src_node };
+ sema.src = .{ .node_offset_bin_op = inst_data.src_node };
const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node };
const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = inst_data.src_node };
const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
const lhs = try sema.resolveInst(extra.lhs);
const rhs = try sema.resolveInst(extra.rhs);
- return sema.analyzeArithmetic(block, tag_override, lhs, rhs, src, lhs_src, rhs_src);
+ return sema.analyzeArithmetic(block, tag_override, lhs, rhs, sema.src, lhs_src, rhs_src);
}
fn zirOverflowArithmetic(
@@ -5150,6 +5193,9 @@ fn zirBoolBr(
};
var child_block = parent_block.makeSubBlock();
+ child_block.runtime_loop = null;
+ child_block.runtime_cond = lhs.src;
+ child_block.runtime_index += 1;
defer child_block.instructions.deinit(sema.gpa);
var then_block = child_block.makeSubBlock();
@@ -5258,6 +5304,9 @@ fn zirCondbr(
}
var sub_block = parent_block.makeSubBlock();
+ sub_block.runtime_loop = null;
+ sub_block.runtime_cond = cond.src;
+ sub_block.runtime_index += 1;
defer sub_block.instructions.deinit(sema.gpa);
_ = try sema.analyzeBody(&sub_block, then_body);
@@ -6753,7 +6802,35 @@ fn storePtr(
if ((try sema.typeHasOnePossibleValue(block, src, elem_ty)) != null)
return;
- // TODO handle comptime pointer writes
+ if (try sema.resolvePossiblyUndefinedValue(block, src, ptr)) |ptr_val| {
+ const const_val = (try sema.resolvePossiblyUndefinedValue(block, src, value)) orelse
+ return sema.mod.fail(&block.base, src, "cannot store runtime value in compile time variable", .{});
+
+ const comptime_alloc = ptr_val.castTag(.comptime_alloc).?;
+ if (comptime_alloc.data.runtime_index < block.runtime_index) {
+ if (block.runtime_cond) |cond_src| {
+ const msg = msg: {
+ const msg = try sema.mod.errMsg(&block.base, src, "store to comptime variable depends on runtime condition", .{});
+ errdefer msg.destroy(sema.gpa);
+ try sema.mod.errNote(&block.base, cond_src, msg, "runtime condition here", .{});
+ break :msg msg;
+ };
+ return sema.mod.failWithOwnedErrorMsg(&block.base, msg);
+ }
+ if (block.runtime_loop) |loop_src| {
+ const msg = msg: {
+ const msg = try sema.mod.errMsg(&block.base, src, "cannot store to comptime variable in non-inline loop", .{});
+ errdefer msg.destroy(sema.gpa);
+ try sema.mod.errNote(&block.base, loop_src, msg, "non-inline loop here", .{});
+ break :msg msg;
+ };
+ return sema.mod.failWithOwnedErrorMsg(&block.base, msg);
+ }
+ unreachable;
+ }
+ comptime_alloc.data.val = const_val;
+ return;
+ }
// TODO handle if the element type requires comptime
try sema.requireRuntimeBlock(block, src);