| ... | @@ -7983,12 +7983,25 @@ fn analyzePtrArithmetic( | ... | @@ -7983,12 +7983,25 @@ fn analyzePtrArithmetic( |
| 7983 | const runtime_src = rs: { | 7983 | const runtime_src = rs: { |
| 7984 | if (try sema.resolveDefinedValue(block, ptr_src, ptr)) |ptr_val| { | 7984 | if (try sema.resolveDefinedValue(block, ptr_src, ptr)) |ptr_val| { |
| 7985 | if (try sema.resolveDefinedValue(block, offset_src, offset)) |offset_val| { | 7985 | if (try sema.resolveDefinedValue(block, offset_src, offset)) |offset_val| { |
| | 7986 | const ptr_ty = sema.typeOf(ptr); |
| | 7987 | const offset_int = offset_val.toUnsignedInt(); |
| | 7988 | const new_ptr_ty = ptr_ty; // TODO modify alignment |
| | 7989 | if (ptr_val.getUnsignedInt()) |addr| { |
| | 7990 | const target = sema.mod.getTarget(); |
| | 7991 | const elem_ty = ptr_ty.childType(); |
| | 7992 | const elem_size = elem_ty.abiSize(target); |
| | 7993 | const new_addr = switch (air_tag) { |
| | 7994 | .ptr_add => addr + elem_size * offset_int, |
| | 7995 | .ptr_sub => addr - elem_size * offset_int, |
| | 7996 | else => unreachable, |
| | 7997 | }; |
| | 7998 | const new_ptr_val = try Value.Tag.int_u64.create(sema.arena, new_addr); |
| | 7999 | return sema.addConstant(new_ptr_ty, new_ptr_val); |
| | 8000 | } |
| 7986 | if (air_tag == .ptr_sub) { | 8001 | if (air_tag == .ptr_sub) { |
| 7987 | return sema.fail(block, op_src, "TODO implement Sema comptime pointer subtraction", .{}); | 8002 | return sema.fail(block, op_src, "TODO implement Sema comptime pointer subtraction", .{}); |
| 7988 | } | 8003 | } |
| 7989 | const offset_int = offset_val.toUnsignedInt(); | | |
| 7990 | const new_ptr_val = try ptr_val.elemPtr(sema.arena, offset_int); | 8004 | const new_ptr_val = try ptr_val.elemPtr(sema.arena, offset_int); |
| 7991 | const new_ptr_ty = sema.typeOf(ptr); | | |
| 7992 | return sema.addConstant(new_ptr_ty, new_ptr_val); | 8005 | return sema.addConstant(new_ptr_ty, new_ptr_val); |
| 7993 | } else break :rs offset_src; | 8006 | } else break :rs offset_src; |
| 7994 | } else break :rs ptr_src; | 8007 | } else break :rs ptr_src; |
| ... | @@ -11979,6 +11992,8 @@ fn coerce( | ... | @@ -11979,6 +11992,8 @@ fn coerce( |
| 11979 | return sema.wrapOptional(block, dest_ty, intermediate, inst_src); | 11992 | return sema.wrapOptional(block, dest_ty, intermediate, inst_src); |
| 11980 | }, | 11993 | }, |
| 11981 | .Pointer => { | 11994 | .Pointer => { |
| | 11995 | const dest_info = dest_ty.ptrInfo().data; |
| | 11996 | |
| 11982 | // Function body to function pointer. | 11997 | // Function body to function pointer. |
| 11983 | if (inst_ty.zigTypeTag() == .Fn) { | 11998 | if (inst_ty.zigTypeTag() == .Fn) { |
| 11984 | const fn_val = try sema.resolveConstValue(block, inst_src, inst); | 11999 | const fn_val = try sema.resolveConstValue(block, inst_src, inst); |
| ... | @@ -11989,16 +12004,16 @@ fn coerce( | ... | @@ -11989,16 +12004,16 @@ fn coerce( |
| 11989 | | 12004 | |
| 11990 | // *T to *[1]T | 12005 | // *T to *[1]T |
| 11991 | single_item: { | 12006 | single_item: { |
| 11992 | if (!dest_ty.isSinglePointer()) break :single_item; | 12007 | if (dest_info.size != .One) break :single_item; |
| 11993 | if (!inst_ty.isSinglePointer()) break :single_item; | 12008 | if (!inst_ty.isSinglePointer()) break :single_item; |
| 11994 | const ptr_elem_ty = inst_ty.childType(); | 12009 | const ptr_elem_ty = inst_ty.childType(); |
| 11995 | const array_ty = dest_ty.childType(); | 12010 | const array_ty = dest_info.pointee_type; |
| 11996 | if (array_ty.zigTypeTag() != .Array) break :single_item; | 12011 | if (array_ty.zigTypeTag() != .Array) break :single_item; |
| 11997 | const array_elem_ty = array_ty.childType(); | 12012 | const array_elem_ty = array_ty.childType(); |
| 11998 | const dest_is_mut = !dest_ty.isConstPtr(); | 12013 | const dest_is_mut = dest_info.mutable; |
| 11999 | if (inst_ty.isConstPtr() and dest_is_mut) break :single_item; | 12014 | if (inst_ty.isConstPtr() and dest_is_mut) break :single_item; |
| 12000 | if (inst_ty.isVolatilePtr() and !dest_ty.isVolatilePtr()) break :single_item; | 12015 | if (inst_ty.isVolatilePtr() and !dest_info.@"volatile") break :single_item; |
| 12001 | if (inst_ty.ptrAddressSpace() != dest_ty.ptrAddressSpace()) break :single_item; | 12016 | if (inst_ty.ptrAddressSpace() != dest_info.@"addrspace") break :single_item; |
| 12002 | switch (coerceInMemoryAllowed(array_elem_ty, ptr_elem_ty, dest_is_mut, target)) { | 12017 | switch (coerceInMemoryAllowed(array_elem_ty, ptr_elem_ty, dest_is_mut, target)) { |
| 12003 | .ok => {}, | 12018 | .ok => {}, |
| 12004 | .no_match => break :single_item, | 12019 | .no_match => break :single_item, |
| ... | @@ -12012,18 +12027,18 @@ fn coerce( | ... | @@ -12012,18 +12027,18 @@ fn coerce( |
| 12012 | const array_ty = inst_ty.childType(); | 12027 | const array_ty = inst_ty.childType(); |
| 12013 | if (array_ty.zigTypeTag() != .Array) break :src_array_ptr; | 12028 | if (array_ty.zigTypeTag() != .Array) break :src_array_ptr; |
| 12014 | const array_elem_type = array_ty.childType(); | 12029 | const array_elem_type = array_ty.childType(); |
| 12015 | const dest_is_mut = !dest_ty.isConstPtr(); | 12030 | const dest_is_mut = dest_info.mutable; |
| 12016 | if (inst_ty.isConstPtr() and dest_is_mut) break :src_array_ptr; | 12031 | if (inst_ty.isConstPtr() and dest_is_mut) break :src_array_ptr; |
| 12017 | if (inst_ty.isVolatilePtr() and !dest_ty.isVolatilePtr()) break :src_array_ptr; | 12032 | if (inst_ty.isVolatilePtr() and !dest_info.@"volatile") break :src_array_ptr; |
| 12018 | if (inst_ty.ptrAddressSpace() != dest_ty.ptrAddressSpace()) break :src_array_ptr; | 12033 | if (inst_ty.ptrAddressSpace() != dest_info.@"addrspace") break :src_array_ptr; |
| 12019 | | 12034 | |
| 12020 | const dst_elem_type = dest_ty.childType(); | 12035 | const dst_elem_type = dest_info.pointee_type; |
| 12021 | switch (coerceInMemoryAllowed(dst_elem_type, array_elem_type, dest_is_mut, target)) { | 12036 | switch (coerceInMemoryAllowed(dst_elem_type, array_elem_type, dest_is_mut, target)) { |
| 12022 | .ok => {}, | 12037 | .ok => {}, |
| 12023 | .no_match => break :src_array_ptr, | 12038 | .no_match => break :src_array_ptr, |
| 12024 | } | 12039 | } |
| 12025 | | 12040 | |
| 12026 | switch (dest_ty.ptrSize()) { | 12041 | switch (dest_info.size) { |
| 12027 | .Slice => { | 12042 | .Slice => { |
| 12028 | // *[N]T to []T | 12043 | // *[N]T to []T |
| 12029 | return sema.coerceArrayPtrToSlice(block, dest_ty, inst, inst_src); | 12044 | return sema.coerceArrayPtrToSlice(block, dest_ty, inst, inst_src); |
| ... | @@ -12036,7 +12051,7 @@ fn coerce( | ... | @@ -12036,7 +12051,7 @@ fn coerce( |
| 12036 | // *[N]T to [*]T | 12051 | // *[N]T to [*]T |
| 12037 | // *[N:s]T to [*:s]T | 12052 | // *[N:s]T to [*:s]T |
| 12038 | // *[N:s]T to [*]T | 12053 | // *[N:s]T to [*]T |
| 12039 | if (dest_ty.sentinel()) |dst_sentinel| { | 12054 | if (dest_info.sentinel) |dst_sentinel| { |
| 12040 | if (array_ty.sentinel()) |src_sentinel| { | 12055 | if (array_ty.sentinel()) |src_sentinel| { |
| 12041 | if (src_sentinel.eql(dst_sentinel, dst_elem_type)) { | 12056 | if (src_sentinel.eql(dst_sentinel, dst_elem_type)) { |
| 12042 | return sema.coerceCompatiblePtrs(block, dest_ty, inst, inst_src); | 12057 | return sema.coerceCompatiblePtrs(block, dest_ty, inst, inst_src); |
| ... | @@ -12051,9 +12066,24 @@ fn coerce( | ... | @@ -12051,9 +12066,24 @@ fn coerce( |
| 12051 | } | 12066 | } |
| 12052 | | 12067 | |
| 12053 | // coercion to C pointer | 12068 | // coercion to C pointer |
| 12054 | if (dest_ty.ptrSize() == .C) { | 12069 | if (dest_info.size == .C) { |
| 12055 | if (inst_ty.zigTypeTag() == .Null) { | 12070 | switch (inst_ty.zigTypeTag()) { |
| 12056 | return sema.addConstant(dest_ty, Value.@"null"); | 12071 | .Null => { |
| | 12072 | return sema.addConstant(dest_ty, Value.@"null"); |
| | 12073 | }, |
| | 12074 | .ComptimeInt => { |
| | 12075 | const addr = try sema.coerce(block, Type.usize, inst, inst_src); |
| | 12076 | return sema.coerceCompatiblePtrs(block, dest_ty, addr, inst_src); |
| | 12077 | }, |
| | 12078 | .Int => { |
| | 12079 | const ptr_size_ty = switch (inst_ty.intInfo(target).signedness) { |
| | 12080 | .signed => Type.isize, |
| | 12081 | .unsigned => Type.usize, |
| | 12082 | }; |
| | 12083 | const addr = try sema.coerce(block, ptr_size_ty, inst, inst_src); |
| | 12084 | return sema.coerceCompatiblePtrs(block, dest_ty, addr, inst_src); |
| | 12085 | }, |
| | 12086 | else => {}, |
| 12057 | } | 12087 | } |
| 12058 | } | 12088 | } |
| 12059 | }, | 12089 | }, |
| ... | @@ -13632,6 +13662,19 @@ fn resolvePeerTypes( | ... | @@ -13632,6 +13662,19 @@ fn resolvePeerTypes( |
| 13632 | continue; | 13662 | continue; |
| 13633 | } | 13663 | } |
| 13634 | | 13664 | |
| | 13665 | if (chosen_ty_tag == .Pointer and chosen_ty.ptrSize() == .C and |
| | 13666 | (candidate_ty_tag == .Int or candidate_ty_tag == .ComptimeInt)) |
| | 13667 | { |
| | 13668 | continue; |
| | 13669 | } |
| | 13670 | if (candidate_ty_tag == .Pointer and candidate_ty.ptrSize() == .C and |
| | 13671 | (chosen_ty_tag == .Int or chosen_ty_tag == .ComptimeInt)) |
| | 13672 | { |
| | 13673 | chosen = candidate; |
| | 13674 | chosen_i = candidate_i + 1; |
| | 13675 | continue; |
| | 13676 | } |
| | 13677 | |
| 13635 | if (chosen_ty_tag == .ComptimeFloat and candidate_ty_tag == .ComptimeInt) | 13678 | if (chosen_ty_tag == .ComptimeFloat and candidate_ty_tag == .ComptimeInt) |
| 13636 | continue; | 13679 | continue; |
| 13637 | if (chosen_ty_tag == .ComptimeInt and candidate_ty_tag == .ComptimeFloat) { | 13680 | if (chosen_ty_tag == .ComptimeInt and candidate_ty_tag == .ComptimeFloat) { |