@@ -3137,6 +3137,7 @@ pub const Type = struct {
3137
3137
const b_type = b .pointer ;
3138
3138
if (a_type .size != b_type .size ) return false ;
3139
3139
if (a_type .sentinel != b_type .sentinel ) return false ;
3140
+ if (a_type .is_const != b_type .is_const ) return false ;
3140
3141
if (! a_type .elem_ty .eql (b_type .elem_ty .* )) return false ;
3141
3142
},
3142
3143
.array = > | a_type | {
@@ -6622,7 +6623,64 @@ fn resolvePeerTypesInner(analyser: *Analyser, peer_tys: []?Type) !?Type {
6622
6623
6623
6624
.vector = > return null , // TODO
6624
6625
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
+ },
6626
6684
6627
6685
.ptr = > return null , // TODO
6628
6686
@@ -6749,3 +6807,65 @@ fn typeIsArrayLike(analyser: *Analyser, ty: Type) ?ArrayLike {
6749
6807
else = > null ,
6750
6808
};
6751
6809
}
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