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