| ... | @@ -1940,7 +1940,7 @@ fn zirRetPtr( | ... | @@ -1940,7 +1940,7 @@ fn zirRetPtr( |
| 1940 | try sema.requireFunctionBlock(block, src); | 1940 | try sema.requireFunctionBlock(block, src); |
| 1941 | | 1941 | |
| 1942 | if (block.is_comptime) { | 1942 | if (block.is_comptime) { |
| 1943 | return sema.analyzeComptimeAlloc(block, sema.fn_ret_ty); | 1943 | return sema.analyzeComptimeAlloc(block, sema.fn_ret_ty, 0); |
| 1944 | } | 1944 | } |
| 1945 | | 1945 | |
| 1946 | const ptr_type = try Type.ptr(sema.arena, .{ | 1946 | const ptr_type = try Type.ptr(sema.arena, .{ |
| ... | @@ -2067,9 +2067,7 @@ fn zirAllocExtended( | ... | @@ -2067,9 +2067,7 @@ fn zirAllocExtended( |
| 2067 | const type_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]); | 2067 | const type_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]); |
| 2068 | extra_index += 1; | 2068 | extra_index += 1; |
| 2069 | break :blk try sema.resolveType(block, ty_src, type_ref); | 2069 | break :blk try sema.resolveType(block, ty_src, type_ref); |
| 2070 | } else { | 2070 | } else undefined; |
| 2071 | return sema.fail(block, src, "TODO implement Sema.zirAllocExtended inferred", .{}); | | |
| 2072 | }; | | |
| 2073 | | 2071 | |
| 2074 | const alignment: u16 = if (small.has_align) blk: { | 2072 | const alignment: u16 = if (small.has_align) blk: { |
| 2075 | const align_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]); | 2073 | const align_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]); |
| ... | @@ -2078,22 +2076,47 @@ fn zirAllocExtended( | ... | @@ -2078,22 +2076,47 @@ fn zirAllocExtended( |
| 2078 | break :blk alignment; | 2076 | break :blk alignment; |
| 2079 | } else 0; | 2077 | } else 0; |
| 2080 | | 2078 | |
| | 2079 | const inferred_alloc_ty = if (small.is_const) |
| | 2080 | Type.initTag(.inferred_alloc_const) |
| | 2081 | else |
| | 2082 | Type.initTag(.inferred_alloc_mut); |
| | 2083 | |
| 2081 | if (small.is_comptime) { | 2084 | if (small.is_comptime) { |
| 2082 | return sema.fail(block, src, "TODO implement Sema.zirAllocExtended comptime", .{}); | 2085 | if (small.has_type) { |
| | 2086 | return sema.analyzeComptimeAlloc(block, var_ty, alignment); |
| | 2087 | } else { |
| | 2088 | return sema.addConstant( |
| | 2089 | inferred_alloc_ty, |
| | 2090 | try Value.Tag.inferred_alloc_comptime.create(sema.arena, undefined), |
| | 2091 | ); |
| | 2092 | } |
| 2083 | } | 2093 | } |
| 2084 | | 2094 | |
| 2085 | if (!small.is_const) { | 2095 | if (small.has_type) { |
| 2086 | return sema.fail(block, src, "TODO implement Sema.zirAllocExtended var", .{}); | 2096 | if (!small.is_const) { |
| | 2097 | try sema.validateVarType(block, ty_src, var_ty, false); |
| | 2098 | } |
| | 2099 | const ptr_type = try Type.ptr(sema.arena, .{ |
| | 2100 | .pointee_type = var_ty, |
| | 2101 | .@"align" = alignment, |
| | 2102 | .@"addrspace" = target_util.defaultAddressSpace(sema.mod.getTarget(), .local), |
| | 2103 | }); |
| | 2104 | try sema.requireRuntimeBlock(block, src); |
| | 2105 | try sema.resolveTypeLayout(block, src, var_ty); |
| | 2106 | return block.addTy(.alloc, ptr_type); |
| 2087 | } | 2107 | } |
| 2088 | | 2108 | |
| 2089 | const ptr_type = try Type.ptr(sema.arena, .{ | 2109 | // `Sema.addConstant` does not add the instruction to the block because it is |
| 2090 | .pointee_type = var_ty, | 2110 | // not needed in the case of constant values. However here, we plan to "downgrade" |
| 2091 | .@"align" = alignment, | 2111 | // to a normal instruction when we hit `resolve_inferred_alloc`. So we append |
| 2092 | .@"addrspace" = target_util.defaultAddressSpace(sema.mod.getTarget(), .local), | 2112 | // to the block even though it is currently a `.constant`. |
| 2093 | }); | 2113 | const result = try sema.addConstant( |
| 2094 | try sema.requireRuntimeBlock(block, src); | 2114 | inferred_alloc_ty, |
| 2095 | try sema.resolveTypeLayout(block, src, var_ty); | 2115 | try Value.Tag.inferred_alloc.create(sema.arena, .{}), |
| 2096 | return block.addTy(.alloc, ptr_type); | 2116 | ); |
| | 2117 | try sema.requireFunctionBlock(block, src); |
| | 2118 | try block.instructions.append(sema.gpa, Air.refToIndex(result).?); |
| | 2119 | return result; |
| 2097 | } | 2120 | } |
| 2098 | | 2121 | |
| 2099 | fn zirAllocComptime(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | 2122 | fn zirAllocComptime(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| ... | @@ -2103,7 +2126,7 @@ fn zirAllocComptime(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr | ... | @@ -2103,7 +2126,7 @@ fn zirAllocComptime(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr |
| 2103 | const inst_data = sema.code.instructions.items(.data)[inst].un_node; | 2126 | const inst_data = sema.code.instructions.items(.data)[inst].un_node; |
| 2104 | const ty_src: LazySrcLoc = .{ .node_offset_var_decl_ty = inst_data.src_node }; | 2127 | const ty_src: LazySrcLoc = .{ .node_offset_var_decl_ty = inst_data.src_node }; |
| 2105 | const var_ty = try sema.resolveType(block, ty_src, inst_data.operand); | 2128 | const var_ty = try sema.resolveType(block, ty_src, inst_data.operand); |
| 2106 | return sema.analyzeComptimeAlloc(block, var_ty); | 2129 | return sema.analyzeComptimeAlloc(block, var_ty, 0); |
| 2107 | } | 2130 | } |
| 2108 | | 2131 | |
| 2109 | fn zirAllocInferredComptime(sema: *Sema, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | 2132 | fn zirAllocInferredComptime(sema: *Sema, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| ... | @@ -2125,7 +2148,7 @@ fn zirAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I | ... | @@ -2125,7 +2148,7 @@ fn zirAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I |
| 2125 | const var_decl_src = inst_data.src(); | 2148 | const var_decl_src = inst_data.src(); |
| 2126 | const var_ty = try sema.resolveType(block, ty_src, inst_data.operand); | 2149 | const var_ty = try sema.resolveType(block, ty_src, inst_data.operand); |
| 2127 | if (block.is_comptime) { | 2150 | if (block.is_comptime) { |
| 2128 | return sema.analyzeComptimeAlloc(block, var_ty); | 2151 | return sema.analyzeComptimeAlloc(block, var_ty, 0); |
| 2129 | } | 2152 | } |
| 2130 | const ptr_type = try Type.ptr(sema.arena, .{ | 2153 | const ptr_type = try Type.ptr(sema.arena, .{ |
| 2131 | .pointee_type = var_ty, | 2154 | .pointee_type = var_ty, |
| ... | @@ -2145,7 +2168,7 @@ fn zirAllocMut(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -2145,7 +2168,7 @@ fn zirAllocMut(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 2145 | const ty_src: LazySrcLoc = .{ .node_offset_var_decl_ty = inst_data.src_node }; | 2168 | const ty_src: LazySrcLoc = .{ .node_offset_var_decl_ty = inst_data.src_node }; |
| 2146 | const var_ty = try sema.resolveType(block, ty_src, inst_data.operand); | 2169 | const var_ty = try sema.resolveType(block, ty_src, inst_data.operand); |
| 2147 | if (block.is_comptime) { | 2170 | if (block.is_comptime) { |
| 2148 | return sema.analyzeComptimeAlloc(block, var_ty); | 2171 | return sema.analyzeComptimeAlloc(block, var_ty, 0); |
| 2149 | } | 2172 | } |
| 2150 | try sema.validateVarType(block, ty_src, var_ty, false); | 2173 | try sema.validateVarType(block, ty_src, var_ty, false); |
| 2151 | const ptr_type = try Type.ptr(sema.arena, .{ | 2174 | const ptr_type = try Type.ptr(sema.arena, .{ |
| ... | @@ -9436,8 +9459,10 @@ fn zirAlignOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air | ... | @@ -9436,8 +9459,10 @@ fn zirAlignOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 9436 | const inst_data = sema.code.instructions.items(.data)[inst].un_node; | 9459 | const inst_data = sema.code.instructions.items(.data)[inst].un_node; |
| 9437 | const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; | 9460 | const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; |
| 9438 | const ty = try sema.resolveType(block, operand_src, inst_data.operand); | 9461 | const ty = try sema.resolveType(block, operand_src, inst_data.operand); |
| | 9462 | const resolved_ty = try sema.resolveTypeFields(block, operand_src, ty); |
| | 9463 | try sema.resolveTypeLayout(block, operand_src, resolved_ty); |
| 9439 | const target = sema.mod.getTarget(); | 9464 | const target = sema.mod.getTarget(); |
| 9440 | const abi_align = ty.abiAlignment(target); | 9465 | const abi_align = resolved_ty.abiAlignment(target); |
| 9441 | return sema.addIntUnsigned(Type.comptime_int, abi_align); | 9466 | return sema.addIntUnsigned(Type.comptime_int, abi_align); |
| 9442 | } | 9467 | } |
| 9443 | | 9468 | |
| ... | @@ -9735,8 +9760,33 @@ fn zirTruncate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -9735,8 +9760,33 @@ fn zirTruncate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 9735 | | 9760 | |
| 9736 | fn zirAlignCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | 9761 | fn zirAlignCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| 9737 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; | 9762 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; |
| 9738 | const src = inst_data.src(); | 9763 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; |
| 9739 | return sema.fail(block, src, "TODO: Sema.zirAlignCast", .{}); | 9764 | const align_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; |
| | 9765 | const ptr_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node }; |
| | 9766 | const dest_align = try sema.resolveAlign(block, align_src, extra.lhs); |
| | 9767 | const ptr = sema.resolveInst(extra.rhs); |
| | 9768 | const ptr_ty = sema.typeOf(ptr); |
| | 9769 | |
| | 9770 | // TODO in addition to pointers, this instruction is supposed to work for |
| | 9771 | // pointer-like optionals and slices. |
| | 9772 | try sema.checkPtrType(block, ptr_src, ptr_ty); |
| | 9773 | |
| | 9774 | // TODO compile error if the result pointer is comptime known and would have an |
| | 9775 | // alignment that disagrees with the Decl's alignment. |
| | 9776 | |
| | 9777 | // TODO insert safety check that the alignment is correct |
| | 9778 | |
| | 9779 | const ptr_info = ptr_ty.ptrInfo().data; |
| | 9780 | const dest_ty = try Type.ptr(sema.arena, .{ |
| | 9781 | .pointee_type = ptr_info.pointee_type, |
| | 9782 | .@"align" = dest_align, |
| | 9783 | .@"addrspace" = ptr_info.@"addrspace", |
| | 9784 | .mutable = ptr_info.mutable, |
| | 9785 | .@"allowzero" = ptr_info.@"allowzero", |
| | 9786 | .@"volatile" = ptr_info.@"volatile", |
| | 9787 | .size = ptr_info.size, |
| | 9788 | }); |
| | 9789 | return sema.coerceCompatiblePtrs(block, dest_ty, ptr, ptr_src); |
| 9740 | } | 9790 | } |
| 9741 | | 9791 | |
| 9742 | fn zirClz(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | 9792 | fn zirClz(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| ... | @@ -9838,6 +9888,18 @@ fn checkIntType(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileEr | ... | @@ -9838,6 +9888,18 @@ fn checkIntType(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileEr |
| 9838 | } | 9888 | } |
| 9839 | } | 9889 | } |
| 9840 | | 9890 | |
| | 9891 | fn checkPtrType( |
| | 9892 | sema: *Sema, |
| | 9893 | block: *Block, |
| | 9894 | ty_src: LazySrcLoc, |
| | 9895 | ty: Type, |
| | 9896 | ) CompileError!void { |
| | 9897 | switch (ty.zigTypeTag()) { |
| | 9898 | .Pointer => {}, |
| | 9899 | else => return sema.fail(block, ty_src, "expected pointer type, found '{}'", .{ty}), |
| | 9900 | } |
| | 9901 | } |
| | 9902 | |
| 9841 | fn checkFloatType( | 9903 | fn checkFloatType( |
| 9842 | sema: *Sema, | 9904 | sema: *Sema, |
| 9843 | block: *Block, | 9905 | block: *Block, |
| ... | @@ -14630,14 +14692,22 @@ fn analyzeComptimeAlloc( | ... | @@ -14630,14 +14692,22 @@ fn analyzeComptimeAlloc( |
| 14630 | sema: *Sema, | 14692 | sema: *Sema, |
| 14631 | block: *Block, | 14693 | block: *Block, |
| 14632 | var_type: Type, | 14694 | var_type: Type, |
| | 14695 | alignment: u32, |
| 14633 | ) CompileError!Air.Inst.Ref { | 14696 | ) CompileError!Air.Inst.Ref { |
| 14634 | const ptr_type = try Type.ptr(sema.arena, .{ | 14697 | const ptr_type = try Type.ptr(sema.arena, .{ |
| 14635 | .pointee_type = var_type, | 14698 | .pointee_type = var_type, |
| 14636 | .@"addrspace" = target_util.defaultAddressSpace(sema.mod.getTarget(), .global_constant), | 14699 | .@"addrspace" = target_util.defaultAddressSpace(sema.mod.getTarget(), .global_constant), |
| | 14700 | .@"align" = alignment, |
| 14637 | }); | 14701 | }); |
| 14638 | | 14702 | |
| 14639 | var anon_decl = try block.startAnonDecl(); | 14703 | var anon_decl = try block.startAnonDecl(); |
| 14640 | defer anon_decl.deinit(); | 14704 | defer anon_decl.deinit(); |
| | 14705 | |
| | 14706 | const align_val = if (alignment == 0) |
| | 14707 | Value.@"null" |
| | 14708 | else |
| | 14709 | try Value.Tag.int_u64.create(anon_decl.arena(), alignment); |
| | 14710 | |
| 14641 | const decl = try anon_decl.finish( | 14711 | const decl = try anon_decl.finish( |
| 14642 | try var_type.copy(anon_decl.arena()), | 14712 | try var_type.copy(anon_decl.arena()), |
| 14643 | // There will be stores before the first load, but they may be to sub-elements or | 14713 | // There will be stores before the first load, but they may be to sub-elements or |
| ... | @@ -14645,6 +14715,8 @@ fn analyzeComptimeAlloc( | ... | @@ -14645,6 +14715,8 @@ fn analyzeComptimeAlloc( |
| 14645 | // into fields/elements and have those overridden with stored values. | 14715 | // into fields/elements and have those overridden with stored values. |
| 14646 | Value.undef, | 14716 | Value.undef, |
| 14647 | ); | 14717 | ); |
| | 14718 | decl.align_val = align_val; |
| | 14719 | |
| 14648 | try sema.mod.declareDeclDependency(sema.owner_decl, decl); | 14720 | try sema.mod.declareDeclDependency(sema.owner_decl, decl); |
| 14649 | return sema.addConstant(ptr_type, try Value.Tag.decl_ref_mut.create(sema.arena, .{ | 14721 | return sema.addConstant(ptr_type, try Value.Tag.decl_ref_mut.create(sema.arena, .{ |
| 14650 | .runtime_index = block.runtime_index, | 14722 | .runtime_index = block.runtime_index, |