| author | |
| committer | |
| log | adb746a7017ba6f91974d5e940bc8a8f64bb45f5 |
| tree | 66cf6d6a07cea65dfb63e4602919b64fb2648695 |
| parent | 5d30e8016d2e29d84efb27ec2a4f7be8a63a4f49 |
* AstGen: remove the setBlockBodyEliding function. This is no longer
needed after 63788b2a511eb87974065a052e2436b0c6202544.
* Sema: store_to_block_ptr instruction is handled as
store_to_inferred_ptr or store, as necessary.6 files changed, 90 insertions(+), 87 deletions(-)
src/AstGen.zig+1-31| ... | @@ -1964,11 +1964,7 @@ fn labeledBlockExpr( | ... | @@ -1964,11 +1964,7 @@ fn labeledBlockExpr( |
| 1964 | }, | 1964 | }, |
| 1965 | .break_operand => { | 1965 | .break_operand => { |
| 1966 | // All break operands are values that did not use the result location pointer. | 1966 | // All break operands are values that did not use the result location pointer. |
| 1967 | if (strat.elide_store_to_block_ptr_instructions) { | 1967 | try block_scope.setBlockBody(block_inst); |
| 1968 | try block_scope.setBlockBodyEliding(block_inst); | ||
| 1969 | } else { | ||
| 1970 | try block_scope.setBlockBody(block_inst); | ||
| 1971 | } | ||
| 1972 | const block_ref = indexToRef(block_inst); | 1968 | const block_ref = indexToRef(block_inst); |
| 1973 | switch (rl) { | 1969 | switch (rl) { |
| 1974 | .ref => return block_ref, | 1970 | .ref => return block_ref, |
| ... | @@ -9734,32 +9730,6 @@ const GenZir = struct { | ... | @@ -9734,32 +9730,6 @@ const GenZir = struct { |
| 9734 | gz.unstack(); | 9730 | gz.unstack(); |
| 9735 | } | 9731 | } |
| 9736 | 9732 | ||
| 9737 | /// Same as `setBlockBody` except we don't copy instructions which are | ||
| 9738 | /// `store_to_block_ptr` instructions with lhs set to .none. | ||
| 9739 | /// Assumes nothing stacked on `gz`. Unstacks `gz`. | ||
| 9740 | fn setBlockBodyEliding(gz: *GenZir, inst: Zir.Inst.Index) !void { | ||
| 9741 | const gpa = gz.astgen.gpa; | ||
| 9742 | const body = gz.instructionsSlice(); | ||
| 9743 | try gz.astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.Block).Struct.fields.len + body.len); | ||
| 9744 | const zir_datas = gz.astgen.instructions.items(.data); | ||
| 9745 | const zir_tags = gz.astgen.instructions.items(.tag); | ||
| 9746 | const block_pl_index = gz.astgen.addExtraAssumeCapacity(Zir.Inst.Block{ | ||
| 9747 | .body_len = @intCast(u32, body.len), | ||
| 9748 | }); | ||
| 9749 | zir_datas[inst].pl_node.payload_index = block_pl_index; | ||
| 9750 | for (body) |sub_inst| { | ||
| 9751 | if (zir_tags[sub_inst] == .store_to_block_ptr and | ||
| 9752 | zir_datas[sub_inst].bin.lhs == .none) | ||
| 9753 | { | ||
| 9754 | // Decrement `body_len`. | ||
| 9755 | gz.astgen.extra.items[block_pl_index] -= 1; | ||
| 9756 | continue; | ||
| 9757 | } | ||
| 9758 | gz.astgen.extra.appendAssumeCapacity(sub_inst); | ||
| 9759 | } | ||
| 9760 | gz.unstack(); | ||
| 9761 | } | ||
| 9762 | |||
| 9763 | /// Supports `body_gz` stacked on `ret_gz` stacked on `gz`. Unstacks `body_gz` and `ret_gz`. | 9733 | /// Supports `body_gz` stacked on `ret_gz` stacked on `gz`. Unstacks `body_gz` and `ret_gz`. |
| 9764 | fn addFunc(gz: *GenZir, args: struct { | 9734 | fn addFunc(gz: *GenZir, args: struct { |
| 9765 | src_node: Ast.Node.Index, | 9735 | src_node: Ast.Node.Index, |
src/Sema.zig+79-45| ... | @@ -3247,22 +3247,31 @@ fn zirStoreToBlockPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE | ... | @@ -3247,22 +3247,31 @@ fn zirStoreToBlockPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE |
| 3247 | defer tracy.end(); | 3247 | defer tracy.end(); |
| 3248 | 3248 | ||
| 3249 | const bin_inst = sema.code.instructions.items(.data)[inst].bin; | 3249 | const bin_inst = sema.code.instructions.items(.data)[inst].bin; |
| 3250 | const ptr = sema.inst_map.get(@enumToInt(bin_inst.lhs) - @as(u32, Zir.Inst.Ref.typed_value_map.len)) orelse { | 3250 | const ptr = sema.inst_map.get(Zir.refToIndex(bin_inst.lhs).?) orelse { |
| 3251 | // This is an elided instruction, but AstGen was unable to omit it. | 3251 | // This is an elided instruction, but AstGen was unable to omit it. |
| 3252 | return; | 3252 | return; |
| 3253 | }; | 3253 | }; |
| 3254 | const value = sema.resolveInst(bin_inst.rhs); | 3254 | const operand = sema.resolveInst(bin_inst.rhs); |
| 3255 | const ptr_ty = try Type.ptr(sema.arena, .{ | 3255 | const src: LazySrcLoc = sema.src; |
| 3256 | .pointee_type = sema.typeOf(value), | 3256 | blk: { |
| 3257 | // TODO figure out which address space is appropriate here | 3257 | const ptr_inst = Air.refToIndex(ptr) orelse break :blk; |
| 3258 | .@"addrspace" = target_util.defaultAddressSpace(sema.mod.getTarget(), .local), | 3258 | if (sema.air_instructions.items(.tag)[ptr_inst] != .constant) break :blk; |
| 3259 | }); | 3259 | const air_datas = sema.air_instructions.items(.data); |
| 3260 | // TODO detect when this store should be done at compile-time. For example, | 3260 | const ptr_val = sema.air_values.items[air_datas[ptr_inst].ty_pl.payload]; |
| 3261 | // if expressions should force it when the condition is compile-time known. | 3261 | switch (ptr_val.tag()) { |
| 3262 | const src: LazySrcLoc = .unneeded; | 3262 | .inferred_alloc_comptime => { |
| 3263 | try sema.requireRuntimeBlock(block, src); | 3263 | const iac = ptr_val.castTag(.inferred_alloc_comptime).?; |
| 3264 | const bitcasted_ptr = try block.addBitCast(ptr_ty, ptr); | 3264 | return sema.storeToInferredAllocComptime(block, src, operand, iac); |
| 3265 | return sema.storePtr(block, src, bitcasted_ptr, value); | 3265 | }, |
| 3266 | .inferred_alloc => { | ||
| 3267 | const inferred_alloc = ptr_val.castTag(.inferred_alloc).?; | ||
| 3268 | return sema.storeToInferredAlloc(block, src, ptr, operand, inferred_alloc); | ||
| 3269 | }, | ||
| 3270 | else => break :blk, | ||
| 3271 | } | ||
| 3272 | } | ||
| 3273 | |||
| 3274 | return sema.storePtr(block, src, ptr, operand); | ||
| 3266 | } | 3275 | } |
| 3267 | 3276 | ||
| 3268 | fn zirStoreToInferredPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void { | 3277 | fn zirStoreToInferredPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void { |
| ... | @@ -3273,46 +3282,71 @@ fn zirStoreToInferredPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Compi | ... | @@ -3273,46 +3282,71 @@ fn zirStoreToInferredPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Compi |
| 3273 | const bin_inst = sema.code.instructions.items(.data)[inst].bin; | 3282 | const bin_inst = sema.code.instructions.items(.data)[inst].bin; |
| 3274 | const ptr = sema.resolveInst(bin_inst.lhs); | 3283 | const ptr = sema.resolveInst(bin_inst.lhs); |
| 3275 | const operand = sema.resolveInst(bin_inst.rhs); | 3284 | const operand = sema.resolveInst(bin_inst.rhs); |
| 3276 | const operand_ty = sema.typeOf(operand); | ||
| 3277 | const ptr_inst = Air.refToIndex(ptr).?; | 3285 | const ptr_inst = Air.refToIndex(ptr).?; |
| 3278 | assert(sema.air_instructions.items(.tag)[ptr_inst] == .constant); | 3286 | assert(sema.air_instructions.items(.tag)[ptr_inst] == .constant); |
| 3279 | const air_datas = sema.air_instructions.items(.data); | 3287 | const air_datas = sema.air_instructions.items(.data); |
| 3280 | const ptr_val = sema.air_values.items[air_datas[ptr_inst].ty_pl.payload]; | 3288 | const ptr_val = sema.air_values.items[air_datas[ptr_inst].ty_pl.payload]; |
| 3281 | 3289 | ||
| 3282 | if (ptr_val.castTag(.inferred_alloc_comptime)) |iac| { | 3290 | switch (ptr_val.tag()) { |
| 3283 | // There will be only one store_to_inferred_ptr because we are running at comptime. | 3291 | .inferred_alloc_comptime => { |
| 3284 | // The alloc will turn into a Decl. | 3292 | const iac = ptr_val.castTag(.inferred_alloc_comptime).?; |
| 3285 | if (try sema.resolveMaybeUndefValAllowVariables(block, src, operand)) |operand_val| { | 3293 | return sema.storeToInferredAllocComptime(block, src, operand, iac); |
| 3286 | if (operand_val.tag() == .variable) { | 3294 | }, |
| 3287 | return sema.failWithNeededComptime(block, src); | 3295 | .inferred_alloc => { |
| 3288 | } | 3296 | const inferred_alloc = ptr_val.castTag(.inferred_alloc).?; |
| 3289 | var anon_decl = try block.startAnonDecl(src); | 3297 | return sema.storeToInferredAlloc(block, src, ptr, operand, inferred_alloc); |
| 3290 | defer anon_decl.deinit(); | 3298 | }, |
| 3291 | iac.data.decl = try anon_decl.finish( | 3299 | else => unreachable, |
| 3292 | try operand_ty.copy(anon_decl.arena()), | ||
| 3293 | try operand_val.copy(anon_decl.arena()), | ||
| 3294 | ); | ||
| 3295 | // TODO set the alignment on the decl | ||
| 3296 | return; | ||
| 3297 | } else { | ||
| 3298 | return sema.failWithNeededComptime(block, src); | ||
| 3299 | } | ||
| 3300 | } | 3300 | } |
| 3301 | } | ||
| 3301 | 3302 | ||
| 3302 | if (ptr_val.castTag(.inferred_alloc)) |inferred_alloc| { | 3303 | fn storeToInferredAlloc( |
| 3303 | // Add the stored instruction to the set we will use to resolve peer types | 3304 | sema: *Sema, |
| 3304 | // for the inferred allocation. | 3305 | block: *Block, |
| 3305 | try inferred_alloc.data.stored_inst_list.append(sema.arena, operand); | 3306 | src: LazySrcLoc, |
| 3306 | // Create a runtime bitcast instruction with exactly the type the pointer wants. | 3307 | ptr: Air.Inst.Ref, |
| 3307 | const ptr_ty = try Type.ptr(sema.arena, .{ | 3308 | operand: Air.Inst.Ref, |
| 3308 | .pointee_type = operand_ty, | 3309 | inferred_alloc: *Value.Payload.InferredAlloc, |
| 3309 | .@"align" = inferred_alloc.data.alignment, | 3310 | ) CompileError!void { |
| 3310 | .@"addrspace" = target_util.defaultAddressSpace(sema.mod.getTarget(), .local), | 3311 | const operand_ty = sema.typeOf(operand); |
| 3311 | }); | 3312 | // Add the stored instruction to the set we will use to resolve peer types |
| 3312 | const bitcasted_ptr = try block.addBitCast(ptr_ty, ptr); | 3313 | // for the inferred allocation. |
| 3313 | return sema.storePtr(block, src, bitcasted_ptr, operand); | 3314 | try inferred_alloc.data.stored_inst_list.append(sema.arena, operand); |
| 3315 | // Create a runtime bitcast instruction with exactly the type the pointer wants. | ||
| 3316 | const ptr_ty = try Type.ptr(sema.arena, .{ | ||
| 3317 | .pointee_type = operand_ty, | ||
| 3318 | .@"align" = inferred_alloc.data.alignment, | ||
| 3319 | .@"addrspace" = target_util.defaultAddressSpace(sema.mod.getTarget(), .local), | ||
| 3320 | }); | ||
| 3321 | const bitcasted_ptr = try block.addBitCast(ptr_ty, ptr); | ||
| 3322 | return sema.storePtr(block, src, bitcasted_ptr, operand); | ||
| 3323 | } | ||
| 3324 | |||
| 3325 | fn storeToInferredAllocComptime( | ||
| 3326 | sema: *Sema, | ||
| 3327 | block: *Block, | ||
| 3328 | src: LazySrcLoc, | ||
| 3329 | operand: Air.Inst.Ref, | ||
| 3330 | iac: *Value.Payload.InferredAllocComptime, | ||
| 3331 | ) CompileError!void { | ||
| 3332 | const operand_ty = sema.typeOf(operand); | ||
| 3333 | // There will be only one store_to_inferred_ptr because we are running at comptime. | ||
| 3334 | // The alloc will turn into a Decl. | ||
| 3335 | if (try sema.resolveMaybeUndefValAllowVariables(block, src, operand)) |operand_val| { | ||
| 3336 | if (operand_val.tag() == .variable) { | ||
| 3337 | return sema.failWithNeededComptime(block, src); | ||
| 3338 | } | ||
| 3339 | var anon_decl = try block.startAnonDecl(src); | ||
| 3340 | defer anon_decl.deinit(); | ||
| 3341 | iac.data.decl = try anon_decl.finish( | ||
| 3342 | try operand_ty.copy(anon_decl.arena()), | ||
| 3343 | try operand_val.copy(anon_decl.arena()), | ||
| 3344 | ); | ||
| 3345 | // TODO set the alignment on the decl | ||
| 3346 | return; | ||
| 3347 | } else { | ||
| 3348 | return sema.failWithNeededComptime(block, src); | ||
| 3314 | } | 3349 | } |
| 3315 | unreachable; | ||
| 3316 | } | 3350 | } |
| 3317 | 3351 | ||
| 3318 | fn zirSetEvalBranchQuota(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void { | 3352 | fn zirSetEvalBranchQuota(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void { |
src/Zir.zig+8-5| ... | @@ -518,11 +518,14 @@ pub const Inst = struct { | ... | @@ -518,11 +518,14 @@ pub const Inst = struct { |
| 518 | /// Same as `store` except provides a source location. | 518 | /// Same as `store` except provides a source location. |
| 519 | /// Uses the `pl_node` union field. Payload is `Bin`. | 519 | /// Uses the `pl_node` union field. Payload is `Bin`. |
| 520 | store_node, | 520 | store_node, |
| 521 | /// Same as `store` but the type of the value being stored will be used to infer | 521 | /// This instruction is not really supposed to be emitted from AstGen; nevetheless it |
| 522 | /// the block type. The LHS is the pointer to store to. | 522 | /// is sometimes emitted due to deficiencies in AstGen. When Sema sees this instruction, |
| 523 | /// Uses the `bin` union field. | 523 | /// it must clean up after AstGen's mess by looking at various context clues and |
| 524 | /// If the pointer is none, it means this instruction has been elided in | 524 | /// then treating it as one of the following: |
| 525 | /// AstGen, but AstGen was unable to actually omit it from the ZIR code. | 525 | /// * no-op |
| 526 | /// * store_to_inferred_ptr | ||
| 527 | /// * store | ||
| 528 | /// Uses the `bin` union field with LHS as the pointer to store to. | ||
| 526 | store_to_block_ptr, | 529 | store_to_block_ptr, |
| 527 | /// Same as `store` but the type of the value being stored will be used to infer | 530 | /// Same as `store` but the type of the value being stored will be used to infer |
| 528 | /// the pointer type. | 531 | /// the pointer type. |
test/behavior.zig+1-1| ... | @@ -124,6 +124,7 @@ test { | ... | @@ -124,6 +124,7 @@ test { |
| 124 | _ = @import("behavior/bugs/421.zig"); | 124 | _ = @import("behavior/bugs/421.zig"); |
| 125 | _ = @import("behavior/bugs/726.zig"); | 125 | _ = @import("behavior/bugs/726.zig"); |
| 126 | _ = @import("behavior/bugs/1421.zig"); | 126 | _ = @import("behavior/bugs/1421.zig"); |
| 127 | _ = @import("behavior/bugs/1442.zig"); | ||
| 127 | _ = @import("behavior/bugs/2114.zig"); | 128 | _ = @import("behavior/bugs/2114.zig"); |
| 128 | _ = @import("behavior/bugs/3742.zig"); | 129 | _ = @import("behavior/bugs/3742.zig"); |
| 129 | _ = @import("behavior/struct_contains_null_ptr_itself.zig"); | 130 | _ = @import("behavior/struct_contains_null_ptr_itself.zig"); |
| ... | @@ -144,7 +145,6 @@ test { | ... | @@ -144,7 +145,6 @@ test { |
| 144 | _ = @import("behavior/bugs/828.zig"); | 145 | _ = @import("behavior/bugs/828.zig"); |
| 145 | _ = @import("behavior/bugs/920.zig"); | 146 | _ = @import("behavior/bugs/920.zig"); |
| 146 | _ = @import("behavior/bugs/1120.zig"); | 147 | _ = @import("behavior/bugs/1120.zig"); |
| 147 | _ = @import("behavior/bugs/1442.zig"); | ||
| 148 | _ = @import("behavior/bugs/1607.zig"); | 148 | _ = @import("behavior/bugs/1607.zig"); |
| 149 | _ = @import("behavior/bugs/1851.zig"); | 149 | _ = @import("behavior/bugs/1851.zig"); |
| 150 | _ = @import("behavior/bugs/3384.zig"); | 150 | _ = @import("behavior/bugs/3384.zig"); |
test/behavior/bugs/1442.zig-2| ... | @@ -7,8 +7,6 @@ const Union = union(enum) { | ... | @@ -7,8 +7,6 @@ const Union = union(enum) { |
| 7 | }; | 7 | }; |
| 8 | 8 | ||
| 9 | test "const error union field alignment" { | 9 | test "const error union field alignment" { |
| 10 | if (builtin.zig_backend != .stage1) return error.SkipZigTest; | ||
| 11 | |||
| 12 | var union_or_err: anyerror!Union = Union{ .Color = 1234 }; | 10 | var union_or_err: anyerror!Union = Union{ .Color = 1234 }; |
| 13 | try std.testing.expect((union_or_err catch unreachable).Color == 1234); | 11 | try std.testing.expect((union_or_err catch unreachable).Color == 1234); |
| 14 | } | 12 | } |
test/behavior/eval.zig+1-3| ... | @@ -495,7 +495,7 @@ test "@tagName of @typeInfo" { | ... | @@ -495,7 +495,7 @@ test "@tagName of @typeInfo" { |
| 495 | } | 495 | } |
| 496 | 496 | ||
| 497 | test "static eval list init" { | 497 | test "static eval list init" { |
| 498 | if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO | 498 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO |
| 499 | 499 | ||
| 500 | try expect(static_vec3.data[2] == 1.0); | 500 | try expect(static_vec3.data[2] == 1.0); |
| 501 | try expect(vec3(0.0, 0.0, 3.0).data[2] == 3.0); | 501 | try expect(vec3(0.0, 0.0, 3.0).data[2] == 3.0); |
| ... | @@ -511,8 +511,6 @@ pub fn vec3(x: f32, y: f32, z: f32) Vec3 { | ... | @@ -511,8 +511,6 @@ pub fn vec3(x: f32, y: f32, z: f32) Vec3 { |
| 511 | } | 511 | } |
| 512 | 512 | ||
| 513 | test "inlined loop has array literal with elided runtime scope on first iteration but not second iteration" { | 513 | test "inlined loop has array literal with elided runtime scope on first iteration but not second iteration" { |
| 514 | if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO | ||
| 515 | |||
| 516 | var runtime = [1]i32{3}; | 514 | var runtime = [1]i32{3}; |
| 517 | comptime var i: usize = 0; | 515 | comptime var i: usize = 0; |
| 518 | inline while (i < 2) : (i += 1) { | 516 | inline while (i < 2) : (i += 1) { |