@@ -3137,6 +3137,7 @@ pub const Type = struct {
31373137 const b_type = b .pointer ;
31383138 if (a_type .size != b_type .size ) return false ;
31393139 if (a_type .sentinel != b_type .sentinel ) return false ;
3140+ if (a_type .is_const != b_type .is_const ) return false ;
31403141 if (! a_type .elem_ty .eql (b_type .elem_ty .* )) return false ;
31413142 },
31423143 .array = > | a_type | {
@@ -6627,7 +6628,64 @@ fn resolvePeerTypesInner(analyser: *Analyser, peer_tys: []?Type) !?Type {
66276628
66286629 .vector = > return null , // TODO
66296630
6630- .c_ptr = > return null , // TODO
6631+ .c_ptr = > {
6632+ var opt_ptr_info : ? PointerInfo = null ;
6633+ for (peer_tys ) | opt_ty | {
6634+ const ty = opt_ty orelse continue ;
6635+ switch (ty .zigTypeTag (analyser ).? ) {
6636+ .comptime_int = > continue ,
6637+ .int = > {
6638+ const ptr_bits = builtin .target .ptrBitWidth ();
6639+ const bits = analyser .ip .intInfo (ty .data .ip_index .index .? , builtin .target ).bits ;
6640+ if (bits >= ptr_bits ) continue ;
6641+ },
6642+ .null = > continue ,
6643+ else = > {},
6644+ }
6645+
6646+ if (! analyser .typeIsPointerAtRuntime (ty )) {
6647+ return null ;
6648+ }
6649+
6650+ const peer_info = analyser .typePointerInfo (ty ).? ;
6651+
6652+ var ptr_info = opt_ptr_info orelse {
6653+ opt_ptr_info = peer_info ;
6654+ continue ;
6655+ };
6656+
6657+ if (! ptr_info .elem_ty .eql (peer_info .elem_ty )) {
6658+ // TODO: coerce C pointer types
6659+ return null ;
6660+ }
6661+
6662+ if (ptr_info .flags .alignment != ptr_info .flags .alignment ) {
6663+ // TODO: find minimum C pointer alignment
6664+ return null ;
6665+ }
6666+
6667+ if (ptr_info .flags .address_space != peer_info .flags .address_space ) {
6668+ return null ;
6669+ }
6670+
6671+ ptr_info .flags .is_const = ptr_info .flags .is_const or peer_info .flags .is_const ;
6672+ ptr_info .flags .is_volatile = ptr_info .flags .is_volatile or peer_info .flags .is_volatile ;
6673+
6674+ opt_ptr_info = ptr_info ;
6675+ }
6676+ const info = opt_ptr_info .? ;
6677+ return .{
6678+ .data = .{
6679+ .pointer = .{
6680+ .elem_ty = try analyser .allocType (info .elem_ty ),
6681+ .sentinel = .none ,
6682+ .size = .c ,
6683+ .is_const = info .flags .is_const ,
6684+ },
6685+ },
6686+ .is_type_val = true ,
6687+ };
6688+ },
66316689
66326690 .ptr = > return null , // TODO
66336691
@@ -6754,3 +6812,65 @@ fn typeIsArrayLike(analyser: *Analyser, ty: Type) ?ArrayLike {
67546812 else = > null ,
67556813 };
67566814}
6815+
6816+ const PointerInfo = struct {
6817+ is_optional : bool ,
6818+ elem_ty : Type ,
6819+ sentinel : InternPool.Index ,
6820+ flags : InternPool.Key.Pointer.Flags ,
6821+ };
6822+ fn typePointerInfo (analyser : * Analyser , ty : Type ) ? PointerInfo {
6823+ std .debug .assert (ty .is_type_val );
6824+ const ip_index = switch (ty .data ) {
6825+ .ip_index = > | payload | payload .index orelse return null ,
6826+ .pointer = > | p | return .{
6827+ .is_optional = false ,
6828+ .elem_ty = p .elem_ty .* ,
6829+ .sentinel = p .sentinel ,
6830+ .flags = .{
6831+ .size = p .size ,
6832+ .is_const = p .is_const ,
6833+ },
6834+ },
6835+ .optional = > | child | switch (child .data ) {
6836+ .pointer = > | p | return .{
6837+ .is_optional = true ,
6838+ .elem_ty = p .elem_ty .* ,
6839+ .sentinel = p .sentinel ,
6840+ .flags = .{
6841+ .size = p .size ,
6842+ .is_const = p .is_const ,
6843+ },
6844+ },
6845+ else = > return null ,
6846+ },
6847+ else = > return null ,
6848+ };
6849+ return switch (analyser .ip .indexToKey (ip_index )) {
6850+ .pointer_type = > | p | .{
6851+ .is_optional = false ,
6852+ .elem_ty = Type .fromIP (analyser , .type_type , p .elem_type ),
6853+ .sentinel = p .sentinel ,
6854+ .flags = p .flags ,
6855+ },
6856+ .optional_type = > | info | switch (analyser .ip .indexToKey (info .payload_type )) {
6857+ .pointer_type = > | p | .{
6858+ .is_optional = true ,
6859+ .elem_ty = Type .fromIP (analyser , .type_type , p .elem_type ),
6860+ .sentinel = p .sentinel ,
6861+ .flags = p .flags ,
6862+ },
6863+ else = > null ,
6864+ },
6865+ else = > null ,
6866+ };
6867+ }
6868+
6869+ fn typeIsPointerAtRuntime (analyser : * Analyser , ty : Type ) bool {
6870+ const ptr_info = analyser .typePointerInfo (ty ) orelse return false ;
6871+ return switch (ptr_info .flags .size ) {
6872+ .slice = > false ,
6873+ .c = > ! ptr_info .is_optional ,
6874+ .one , .many = > ! ptr_info .is_optional or ! ptr_info .flags .is_allowzero ,
6875+ };
6876+ }
0 commit comments