@@ -3134,6 +3134,7 @@ pub const Type = struct {
3134
3134
const b_type = b .pointer ;
3135
3135
if (a_type .size != b_type .size ) return false ;
3136
3136
if (a_type .sentinel != b_type .sentinel ) return false ;
3137
+ if (a_type .is_const != b_type .is_const ) return false ;
3137
3138
if (! a_type .elem_ty .eql (b_type .elem_ty .* )) return false ;
3138
3139
},
3139
3140
.array = > | a_type | {
@@ -4057,6 +4058,62 @@ pub const Type = struct {
4057
4058
};
4058
4059
}
4059
4060
4061
+ const PointerInfo = struct {
4062
+ elem_ty : Type ,
4063
+ sentinel : InternPool.Index ,
4064
+ flags : InternPool.Key.Pointer.Flags ,
4065
+ };
4066
+
4067
+ fn pointerInfo (ty : Type , analyser : * Analyser ) ? PointerInfo {
4068
+ if (! ty .is_type_val ) return null ;
4069
+ return blk : switch (ty .data ) {
4070
+ .pointer = > | info | .{
4071
+ .elem_ty = info .elem_ty .* ,
4072
+ .sentinel = info .sentinel ,
4073
+ .flags = .{
4074
+ .size = info .size ,
4075
+ .is_const = info .is_const ,
4076
+ },
4077
+ },
4078
+ .ip_index = > | payload | switch (analyser .ip .indexToKey (payload .index orelse return null )) {
4079
+ .pointer_type = > | info | .{
4080
+ .elem_ty = Type .fromIP (analyser , .type_type , info .elem_type ),
4081
+ .sentinel = info .sentinel ,
4082
+ .flags = info .flags ,
4083
+ },
4084
+ else = > null ,
4085
+ },
4086
+ .optional = > | child | switch (child .data ) {
4087
+ .pointer = > continue :blk child .data ,
4088
+ .ip_index = > | payload | switch (analyser .ip .indexToKey (payload .index orelse return null )) {
4089
+ .pointer_type = > continue :blk child .data ,
4090
+ else = > null ,
4091
+ },
4092
+ else = > null ,
4093
+ },
4094
+ else = > null ,
4095
+ };
4096
+ }
4097
+
4098
+ fn isPointerAtRuntime (ty : Type , analyser : * Analyser ) bool {
4099
+ switch (ty .data ) {
4100
+ .optional = > | child | {
4101
+ const p = child .pointerInfo (analyser ) orelse return false ;
4102
+ return switch (p .flags .size ) {
4103
+ .slice , .c = > false ,
4104
+ .many , .one = > ! p .flags .is_allowzero ,
4105
+ };
4106
+ },
4107
+ else = > {
4108
+ const info = ty .pointerInfo (analyser ) orelse return false ;
4109
+ return switch (info .flags .size ) {
4110
+ .slice = > false ,
4111
+ .one , .many , .c = > true ,
4112
+ };
4113
+ },
4114
+ }
4115
+ }
4116
+
4060
4117
pub fn stringifyTypeOf (ty : Type , analyser : * Analyser , options : FormatOptions ) error {OutOfMemory }! []const u8 {
4061
4118
const typeof = try ty .typeOf (analyser );
4062
4119
var aw : std.io.Writer.Allocating = .init (analyser .arena );
@@ -6648,7 +6705,64 @@ fn resolvePeerTypesInner(analyser: *Analyser, peer_tys: []?Type) !?Type {
6648
6705
6649
6706
.vector = > return null , // TODO
6650
6707
6651
- .c_ptr = > return null , // TODO
6708
+ .c_ptr = > {
6709
+ var opt_ptr_info : ? Type.PointerInfo = null ;
6710
+ for (peer_tys ) | opt_ty | {
6711
+ const ty = opt_ty orelse continue ;
6712
+ switch (ty .zigTypeTag (analyser ).? ) {
6713
+ .comptime_int = > continue ,
6714
+ .int = > {
6715
+ const ptr_bits = builtin .target .ptrBitWidth ();
6716
+ const bits = analyser .ip .intInfo (ty .data .ip_index .index .? , builtin .target ).bits ;
6717
+ if (bits >= ptr_bits ) continue ;
6718
+ },
6719
+ .null = > continue ,
6720
+ else = > {},
6721
+ }
6722
+
6723
+ if (! ty .isPointerAtRuntime (analyser )) {
6724
+ return null ;
6725
+ }
6726
+
6727
+ const peer_info = ty .pointerInfo (analyser ).? ;
6728
+
6729
+ var ptr_info = opt_ptr_info orelse {
6730
+ opt_ptr_info = peer_info ;
6731
+ continue ;
6732
+ };
6733
+
6734
+ if (! ptr_info .elem_ty .eql (peer_info .elem_ty )) {
6735
+ // TODO: coerce C pointer element types
6736
+ return null ;
6737
+ }
6738
+
6739
+ if (ptr_info .flags .alignment != ptr_info .flags .alignment ) {
6740
+ // TODO: find minimum C pointer alignment
6741
+ return null ;
6742
+ }
6743
+
6744
+ if (ptr_info .flags .address_space != peer_info .flags .address_space ) {
6745
+ return null ;
6746
+ }
6747
+
6748
+ ptr_info .flags .is_const = ptr_info .flags .is_const or peer_info .flags .is_const ;
6749
+ ptr_info .flags .is_volatile = ptr_info .flags .is_volatile or peer_info .flags .is_volatile ;
6750
+
6751
+ opt_ptr_info = ptr_info ;
6752
+ }
6753
+ const info = opt_ptr_info .? ;
6754
+ return .{
6755
+ .data = .{
6756
+ .pointer = .{
6757
+ .elem_ty = try analyser .allocType (info .elem_ty ),
6758
+ .sentinel = .none ,
6759
+ .size = .c ,
6760
+ .is_const = info .flags .is_const ,
6761
+ },
6762
+ },
6763
+ .is_type_val = true ,
6764
+ };
6765
+ },
6652
6766
6653
6767
.ptr = > return null , // TODO
6654
6768
0 commit comments