diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2021-06-08 14:16:57 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-06-08 14:16:57 -0400 |
| commit | ccfa16828445ebf3634c2a0f27ec359af1628efc (patch) | |
| tree | 0d73a532885fca9b9e6db9fdceb8f1e014cf495f /src/Sema.zig | |
| parent | c822a0b59fe123ff67bcb188f20290d818467be7 (diff) | |
| parent | d41a5105cd6222564dfe6bad9cff2c445847c6b3 (diff) | |
| download | zig-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.zig | 89 |
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); |
