| author | |
| committer | |
| log | 5d429b03e3d43e937e2b517d594275034a873959 |
| tree | 2071dddfb806b692bf51864dd413c60c90d42bdd |
| parent | 5f3b91437f5cd23bcae66227932555b7abe32669 |
| signature |
17 files changed, 99 insertions(+), 4 deletions(-)
src/Air.zig+5| ... | ... | @@ -729,6 +729,10 @@ pub const Inst = struct { |
| 729 | 729 | /// Sets the operand as the current error return trace, |
| 730 | 730 | set_err_return_trace, |
| 731 | 731 | |
| 732 | /// Convert the address space of a pointer. | |
| 733 | /// Uses the `ty_op` field. | |
| 734 | addrspace_cast, | |
| 735 | ||
| 732 | 736 | pub fn fromCmpOp(op: std.math.CompareOperator, optimized: bool) Tag { |
| 733 | 737 | switch (op) { |
| 734 | 738 | .lt => return if (optimized) .cmp_lt_optimized else .cmp_lt, |
| ... | ... | @@ -1138,6 +1142,7 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type { |
| 1138 | 1142 | .popcount, |
| 1139 | 1143 | .byte_swap, |
| 1140 | 1144 | .bit_reverse, |
| 1145 | .addrspace_cast, | |
| 1141 | 1146 | => return air.getRefType(datas[inst].ty_op.ty), |
| 1142 | 1147 | |
| 1143 | 1148 | .loop, |
src/AstGen.zig+8| ... | ... | @@ -7789,6 +7789,14 @@ fn builtinCall( |
| 7789 | 7789 | }); |
| 7790 | 7790 | return rvalue(gz, rl, result, node); |
| 7791 | 7791 | }, |
| 7792 | .addrspace_cast => { | |
| 7793 | const result = try gz.addExtendedPayload(.addrspace_cast, Zir.Inst.BinNode{ | |
| 7794 | .lhs = try comptimeExpr(gz, scope, .{ .ty = .address_space_type }, params[0]), | |
| 7795 | .rhs = try expr(gz, scope, .none, params[1]), | |
| 7796 | .node = gz.nodeIndexToRelative(node), | |
| 7797 | }); | |
| 7798 | return rvalue(gz, rl, result, node); | |
| 7799 | }, | |
| 7792 | 7800 | |
| 7793 | 7801 | // zig fmt: off |
| 7794 | 7802 | .has_decl => return hasDeclOrField(gz, scope, rl, node, params[0], params[1], .has_decl), |
src/BuiltinFn.zig+8| ... | ... | @@ -2,6 +2,7 @@ const std = @import("std"); |
| 2 | 2 | |
| 3 | 3 | pub const Tag = enum { |
| 4 | 4 | add_with_overflow, |
| 5 | addrspace_cast, | |
| 5 | 6 | align_cast, |
| 6 | 7 | align_of, |
| 7 | 8 | as, |
| ... | ... | @@ -152,6 +153,13 @@ pub const list = list: { |
| 152 | 153 | .param_count = 4, |
| 153 | 154 | }, |
| 154 | 155 | }, |
| 156 | .{ | |
| 157 | "@addrSpaceCast", | |
| 158 | .{ | |
| 159 | .tag = .addrspace_cast, | |
| 160 | .param_count = 2, | |
| 161 | }, | |
| 162 | }, | |
| 155 | 163 | .{ |
| 156 | 164 | "@alignCast", |
| 157 | 165 | .{ |
src/Liveness.zig+2| ... | ... | @@ -268,6 +268,7 @@ pub fn categorizeOperand( |
| 268 | 268 | .bit_reverse, |
| 269 | 269 | .splat, |
| 270 | 270 | .error_set_has_value, |
| 271 | .addrspace_cast, | |
| 271 | 272 | => { |
| 272 | 273 | const o = air_datas[inst].ty_op; |
| 273 | 274 | if (o.operand == operand_ref) return matchOperandSmallIndex(l, inst, 0, .none); |
| ... | ... | @@ -844,6 +845,7 @@ fn analyzeInst( |
| 844 | 845 | .bit_reverse, |
| 845 | 846 | .splat, |
| 846 | 847 | .error_set_has_value, |
| 848 | .addrspace_cast, | |
| 847 | 849 | => { |
| 848 | 850 | const o = inst_datas[inst].ty_op; |
| 849 | 851 | return trackOperands(a, new_set, inst, main_tomb, .{ o.operand, .none, .none }); |
src/Module.zig+1-1| ... | ... | @@ -4617,7 +4617,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool { |
| 4617 | 4617 | .constant => target_util.defaultAddressSpace(target, .global_constant), |
| 4618 | 4618 | else => unreachable, |
| 4619 | 4619 | }, |
| 4620 | else => |addrspace_ref| try sema.analyzeAddrspace(&block_scope, address_space_src, addrspace_ref, addrspace_ctx), | |
| 4620 | else => |addrspace_ref| try sema.analyzeAddressSpace(&block_scope, address_space_src, addrspace_ref, addrspace_ctx), | |
| 4621 | 4621 | }; |
| 4622 | 4622 | }; |
| 4623 | 4623 |
src/Sema.zig+51-3| ... | ... | @@ -975,8 +975,9 @@ fn analyzeBodyInner( |
| 975 | 975 | .reify => try sema.zirReify( block, extended, inst), |
| 976 | 976 | .builtin_async_call => try sema.zirBuiltinAsyncCall( block, extended), |
| 977 | 977 | .cmpxchg => try sema.zirCmpxchg( block, extended), |
| 978 | ||
| 978 | .addrspace_cast => try sema.zirAddrSpaceCast( block, extended), | |
| 979 | 979 | // zig fmt: on |
| 980 | ||
| 980 | 981 | .fence => { |
| 981 | 982 | try sema.zirFence(block, extended); |
| 982 | 983 | i += 1; |
| ... | ... | @@ -16250,7 +16251,7 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 16250 | 16251 | const address_space = if (inst_data.flags.has_addrspace) blk: { |
| 16251 | 16252 | const ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_i]); |
| 16252 | 16253 | extra_i += 1; |
| 16253 | break :blk try sema.analyzeAddrspace(block, addrspace_src, ref, .pointer); | |
| 16254 | break :blk try sema.analyzeAddressSpace(block, addrspace_src, ref, .pointer); | |
| 16254 | 16255 | } else .generic; |
| 16255 | 16256 | |
| 16256 | 16257 | const bit_offset = if (inst_data.flags.has_bit_range) blk: { |
| ... | ... | @@ -18170,6 +18171,53 @@ fn reifyStruct( |
| 18170 | 18171 | return sema.analyzeDeclVal(block, src, new_decl_index); |
| 18171 | 18172 | } |
| 18172 | 18173 | |
| 18174 | fn zirAddrSpaceCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref { | |
| 18175 | const extra = sema.code.extraData(Zir.Inst.BinNode, extended.operand).data; | |
| 18176 | const src = LazySrcLoc.nodeOffset(extra.node); | |
| 18177 | const addrspace_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node }; | |
| 18178 | const ptr_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = extra.node }; | |
| 18179 | ||
| 18180 | const dest_addrspace = try sema.analyzeAddressSpace(block, addrspace_src, extra.lhs, .pointer); | |
| 18181 | const ptr = try sema.resolveInst(extra.rhs); | |
| 18182 | const ptr_ty = sema.typeOf(ptr); | |
| 18183 | ||
| 18184 | // TODO in addition to pointers, this instruction is supposed to work for | |
| 18185 | // pointer-like optionals and slices. | |
| 18186 | try sema.checkPtrOperand(block, ptr_src, ptr_ty); | |
| 18187 | ||
| 18188 | // TODO check address space cast validity. | |
| 18189 | const src_addrspace = ptr_ty.ptrAddressSpace(); | |
| 18190 | _ = src_addrspace; | |
| 18191 | ||
| 18192 | const ptr_info = ptr_ty.ptrInfo().data; | |
| 18193 | const dest_ty = try Type.ptr(sema.arena, sema.mod, .{ | |
| 18194 | .pointee_type = ptr_info.pointee_type, | |
| 18195 | .@"align" = ptr_info.@"align", | |
| 18196 | .@"addrspace" = dest_addrspace, | |
| 18197 | .mutable = ptr_info.mutable, | |
| 18198 | .@"allowzero" = ptr_info.@"allowzero", | |
| 18199 | .@"volatile" = ptr_info.@"volatile", | |
| 18200 | .size = ptr_info.size, | |
| 18201 | }); | |
| 18202 | ||
| 18203 | if (try sema.resolveMaybeUndefVal(block, ptr_src, ptr)) |val| { | |
| 18204 | // Pointer value should compatible with both address spaces. | |
| 18205 | // TODO: Figure out why this generates an invalid bitcast. | |
| 18206 | return sema.addConstant(dest_ty, val); | |
| 18207 | } | |
| 18208 | ||
| 18209 | try sema.requireRuntimeBlock(block, src, ptr_src); | |
| 18210 | // TODO: Address space cast safety? | |
| 18211 | ||
| 18212 | return block.addInst(.{ | |
| 18213 | .tag = .addrspace_cast, | |
| 18214 | .data = .{ .ty_op = .{ | |
| 18215 | .ty = try sema.addType(dest_ty), | |
| 18216 | .operand = ptr, | |
| 18217 | } }, | |
| 18218 | }); | |
| 18219 | } | |
| 18220 | ||
| 18173 | 18221 | fn zirTypeName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| 18174 | 18222 | const inst_data = sema.code.instructions.items(.data)[inst].un_node; |
| 18175 | 18223 | const ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; |
| ... | ... | @@ -30292,7 +30340,7 @@ pub const AddressSpaceContext = enum { |
| 30292 | 30340 | pointer, |
| 30293 | 30341 | }; |
| 30294 | 30342 | |
| 30295 | pub fn analyzeAddrspace( | |
| 30343 | pub fn analyzeAddressSpace( | |
| 30296 | 30344 | sema: *Sema, |
| 30297 | 30345 | block: *Block, |
| 30298 | 30346 | src: LazySrcLoc, |
src/Zir.zig+3| ... | ... | @@ -1969,6 +1969,9 @@ pub const Inst = struct { |
| 1969 | 1969 | /// `small` 0=>weak 1=>strong |
| 1970 | 1970 | /// `operand` is payload index to `Cmpxchg`. |
| 1971 | 1971 | cmpxchg, |
| 1972 | /// Implement the builtin `@addrSpaceCast` | |
| 1973 | /// `Operand` is payload index to `BinNode`. `lhs` is dest type, `rhs` is operand. | |
| 1974 | addrspace_cast, | |
| 1972 | 1975 | |
| 1973 | 1976 | pub const InstData = struct { |
| 1974 | 1977 | opcode: Extended, |
src/arch/aarch64/CodeGen.zig+1| ... | ... | @@ -677,6 +677,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { |
| 677 | 677 | .union_init => try self.airUnionInit(inst), |
| 678 | 678 | .prefetch => try self.airPrefetch(inst), |
| 679 | 679 | .mul_add => try self.airMulAdd(inst), |
| 680 | .addrspace_cast => return self.fail("TODO implement addrspace_cast", .{}), | |
| 680 | 681 | |
| 681 | 682 | .@"try" => try self.airTry(inst), |
| 682 | 683 | .try_ptr => try self.airTryPtr(inst), |
src/arch/arm/CodeGen.zig+1| ... | ... | @@ -690,6 +690,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { |
| 690 | 690 | .union_init => try self.airUnionInit(inst), |
| 691 | 691 | .prefetch => try self.airPrefetch(inst), |
| 692 | 692 | .mul_add => try self.airMulAdd(inst), |
| 693 | .addrspace_cast => return self.fail("TODO implement addrspace_cast", .{}), | |
| 693 | 694 | |
| 694 | 695 | .@"try" => try self.airTry(inst), |
| 695 | 696 | .try_ptr => try self.airTryPtr(inst), |
src/arch/riscv64/CodeGen.zig+1| ... | ... | @@ -604,6 +604,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { |
| 604 | 604 | .union_init => try self.airUnionInit(inst), |
| 605 | 605 | .prefetch => try self.airPrefetch(inst), |
| 606 | 606 | .mul_add => try self.airMulAdd(inst), |
| 607 | .addrspace_cast => @panic("TODO"), | |
| 607 | 608 | |
| 608 | 609 | .@"try" => @panic("TODO"), |
| 609 | 610 | .try_ptr => @panic("TODO"), |
src/arch/sparc64/CodeGen.zig+1| ... | ... | @@ -618,6 +618,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { |
| 618 | 618 | .union_init => @panic("TODO try self.airUnionInit(inst)"), |
| 619 | 619 | .prefetch => try self.airPrefetch(inst), |
| 620 | 620 | .mul_add => @panic("TODO try self.airMulAdd(inst)"), |
| 621 | .addrspace_cast => @panic("TODO try self.airAddrSpaceCast(int)"), | |
| 621 | 622 | |
| 622 | 623 | .@"try" => try self.airTry(inst), |
| 623 | 624 | .try_ptr => @panic("TODO try self.airTryPtr(inst)"), |
src/arch/wasm/CodeGen.zig+1| ... | ... | @@ -1699,6 +1699,7 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue { |
| 1699 | 1699 | .set_err_return_trace, |
| 1700 | 1700 | .is_named_enum_value, |
| 1701 | 1701 | .error_set_has_value, |
| 1702 | .addrspace_cast, | |
| 1702 | 1703 | => |tag| return self.fail("TODO: Implement wasm inst: {s}", .{@tagName(tag)}), |
| 1703 | 1704 | |
| 1704 | 1705 | .add_optimized, |
src/arch/x86_64/CodeGen.zig+1| ... | ... | @@ -695,6 +695,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { |
| 695 | 695 | .union_init => try self.airUnionInit(inst), |
| 696 | 696 | .prefetch => try self.airPrefetch(inst), |
| 697 | 697 | .mul_add => try self.airMulAdd(inst), |
| 698 | .addrspace_cast => return self.fail("TODO implement addrspace_cast", .{}), | |
| 698 | 699 | |
| 699 | 700 | .@"try" => try self.airTry(inst), |
| 700 | 701 | .try_ptr => try self.airTryPtr(inst), |
src/codegen/c.zig+1| ... | ... | @@ -1871,6 +1871,7 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO |
| 1871 | 1871 | .aggregate_init => try airAggregateInit(f, inst), |
| 1872 | 1872 | .union_init => try airUnionInit(f, inst), |
| 1873 | 1873 | .prefetch => try airPrefetch(f, inst), |
| 1874 | .addrspace_cast => return f.fail("TODO: C backend: implement addrspace_cast", .{}), | |
| 1874 | 1875 | |
| 1875 | 1876 | .@"try" => try airTry(f, inst), |
| 1876 | 1877 | .try_ptr => try airTryPtr(f, inst), |
src/codegen/llvm.zig+12| ... | ... | @@ -4512,6 +4512,7 @@ pub const FuncGen = struct { |
| 4512 | 4512 | .aggregate_init => try self.airAggregateInit(inst), |
| 4513 | 4513 | .union_init => try self.airUnionInit(inst), |
| 4514 | 4514 | .prefetch => try self.airPrefetch(inst), |
| 4515 | .addrspace_cast => try self.airAddrSpaceCast(inst), | |
| 4515 | 4516 | |
| 4516 | 4517 | .is_named_enum_value => try self.airIsNamedEnumValue(inst), |
| 4517 | 4518 | .error_set_has_value => try self.airErrorSetHasValue(inst), |
| ... | ... | @@ -9045,6 +9046,17 @@ pub const FuncGen = struct { |
| 9045 | 9046 | return null; |
| 9046 | 9047 | } |
| 9047 | 9048 | |
| 9049 | fn airAddrSpaceCast(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { | |
| 9050 | if (self.liveness.isUnused(inst)) return null; | |
| 9051 | ||
| 9052 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | |
| 9053 | const inst_ty = self.air.typeOfIndex(inst); | |
| 9054 | const operand = try self.resolveInst(ty_op.operand); | |
| 9055 | ||
| 9056 | const llvm_dest_ty = try self.dg.lowerType(inst_ty); | |
| 9057 | return self.builder.buildAddrSpaceCast(operand, llvm_dest_ty, ""); | |
| 9058 | } | |
| 9059 | ||
| 9048 | 9060 | fn softF80TruncOrExt( |
| 9049 | 9061 | self: *FuncGen, |
| 9050 | 9062 | operand: *llvm.Value, |
src/print_air.zig+1| ... | ... | @@ -244,6 +244,7 @@ const Writer = struct { |
| 244 | 244 | .byte_swap, |
| 245 | 245 | .bit_reverse, |
| 246 | 246 | .error_set_has_value, |
| 247 | .addrspace_cast, | |
| 247 | 248 | => try w.writeTyOp(s, inst), |
| 248 | 249 | |
| 249 | 250 | .block, |
src/print_zir.zig+1| ... | ... | @@ -512,6 +512,7 @@ const Writer = struct { |
| 512 | 512 | .err_set_cast, |
| 513 | 513 | .wasm_memory_grow, |
| 514 | 514 | .prefetch, |
| 515 | .addrspace_cast, | |
| 515 | 516 | => { |
| 516 | 517 | const inst_data = self.code.extraData(Zir.Inst.BinNode, extended.operand).data; |
| 517 | 518 | const src = LazySrcLoc.nodeOffset(inst_data.node); |