@@ -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 | {
@@ -6627,7 +6628,64 @@ fn resolvePeerTypesInner(analyser: *Analyser, peer_tys: []?Type) !?Type {
6627
6628
6628
6629
.vector = > return null , // TODO
6629
6630
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
+ },
6631
6689
6632
6690
.ptr = > return null , // TODO
6633
6691
@@ -6754,3 +6812,65 @@ fn typeIsArrayLike(analyser: *Analyser, ty: Type) ?ArrayLike {
6754
6812
else = > null ,
6755
6813
};
6756
6814
}
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