Skip to content

Commit 9eceba2

Browse files
authored
Merge pull request #11128 from topolarity/comptime-memory-reinterp
stage2: Track parent type for `.elem_ptr`, `.field_ptr`, and `.*_payload_ptr`
2 parents a2a5d3c + 2f92d1a commit 9eceba2

File tree

9 files changed

+670
-326
lines changed

9 files changed

+670
-326
lines changed

src/Module.zig

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -852,7 +852,7 @@ pub const ErrorSet = struct {
852852
}
853853
};
854854

855-
pub const RequiresComptime = enum { no, yes, unknown, wip };
855+
pub const PropertyBoolean = enum { no, yes, unknown, wip };
856856

857857
/// Represents the data that a struct declaration provides.
858858
pub const Struct = struct {
@@ -884,7 +884,7 @@ pub const Struct = struct {
884884
/// If false, resolving the fields is necessary to determine whether the type has only
885885
/// one possible value.
886886
known_non_opv: bool,
887-
requires_comptime: RequiresComptime = .unknown,
887+
requires_comptime: PropertyBoolean = .unknown,
888888

889889
pub const Fields = std.StringArrayHashMapUnmanaged(Field);
890890

@@ -1089,6 +1089,8 @@ pub const EnumFull = struct {
10891089
namespace: Namespace,
10901090
/// Offset from `owner_decl`, points to the enum decl AST node.
10911091
node_offset: i32,
1092+
/// true if zig inferred this tag type, false if user specified it
1093+
tag_ty_inferred: bool,
10921094

10931095
pub const NameMap = std.StringArrayHashMapUnmanaged(void);
10941096
pub const ValueMap = std.ArrayHashMapUnmanaged(Value, void, Value.ArrayHashContext, false);
@@ -1132,7 +1134,7 @@ pub const Union = struct {
11321134
// which `have_layout` does not ensure.
11331135
fully_resolved,
11341136
},
1135-
requires_comptime: RequiresComptime = .unknown,
1137+
requires_comptime: PropertyBoolean = .unknown,
11361138

11371139
pub const Field = struct {
11381140
/// undefined until `status` is `have_field_types` or `have_layout`.

src/Sema.zig

Lines changed: 261 additions & 175 deletions
Large diffs are not rendered by default.

src/codegen/llvm.zig

Lines changed: 64 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -1518,26 +1518,8 @@ pub const DeclGen = struct {
15181518
const llvm_int = llvm_usize.constInt(tv.val.toUnsignedInt(), .False);
15191519
return llvm_int.constIntToPtr(try dg.llvmType(tv.ty));
15201520
},
1521-
.field_ptr, .opt_payload_ptr, .eu_payload_ptr => {
1522-
const parent = try dg.lowerParentPtr(tv.val, tv.ty);
1523-
return parent.llvm_ptr.constBitCast(try dg.llvmType(tv.ty));
1524-
},
1525-
.elem_ptr => {
1526-
const elem_ptr = tv.val.castTag(.elem_ptr).?.data;
1527-
const parent = try dg.lowerParentPtr(elem_ptr.array_ptr, tv.ty);
1528-
const llvm_usize = try dg.llvmType(Type.usize);
1529-
if (parent.llvm_ptr.typeOf().getElementType().getTypeKind() == .Array) {
1530-
const indices: [2]*const llvm.Value = .{
1531-
llvm_usize.constInt(0, .False),
1532-
llvm_usize.constInt(elem_ptr.index, .False),
1533-
};
1534-
return parent.llvm_ptr.constInBoundsGEP(&indices, indices.len);
1535-
} else {
1536-
const indices: [1]*const llvm.Value = .{
1537-
llvm_usize.constInt(elem_ptr.index, .False),
1538-
};
1539-
return parent.llvm_ptr.constInBoundsGEP(&indices, indices.len);
1540-
}
1521+
.field_ptr, .opt_payload_ptr, .eu_payload_ptr, .elem_ptr => {
1522+
return dg.lowerParentPtr(tv.val, tv.ty.childType());
15411523
},
15421524
.null_value, .zero => {
15431525
const llvm_type = try dg.llvmType(tv.ty);
@@ -2786,167 +2768,150 @@ pub const DeclGen = struct {
27862768
llvm_ptr: *const llvm.Value,
27872769
};
27882770

2789-
fn lowerParentPtrDecl(dg: *DeclGen, ptr_val: Value, decl: *Module.Decl) Error!ParentPtr {
2771+
fn lowerParentPtrDecl(dg: *DeclGen, ptr_val: Value, decl: *Module.Decl, ptr_child_ty: Type) Error!*const llvm.Value {
27902772
decl.markAlive();
27912773
var ptr_ty_payload: Type.Payload.ElemType = .{
27922774
.base = .{ .tag = .single_mut_pointer },
27932775
.data = decl.ty,
27942776
};
27952777
const ptr_ty = Type.initPayload(&ptr_ty_payload.base);
27962778
const llvm_ptr = try dg.lowerDeclRefValue(.{ .ty = ptr_ty, .val = ptr_val }, decl);
2797-
return ParentPtr{
2798-
.llvm_ptr = llvm_ptr,
2799-
.ty = decl.ty,
2800-
};
2779+
2780+
if (ptr_child_ty.eql(decl.ty)) {
2781+
return llvm_ptr;
2782+
} else {
2783+
return llvm_ptr.constBitCast((try dg.llvmType(ptr_child_ty)).pointerType(0));
2784+
}
28012785
}
28022786

2803-
fn lowerParentPtr(dg: *DeclGen, ptr_val: Value, base_ty: Type) Error!ParentPtr {
2804-
switch (ptr_val.tag()) {
2787+
fn lowerParentPtr(dg: *DeclGen, ptr_val: Value, ptr_child_ty: Type) Error!*const llvm.Value {
2788+
var bitcast_needed: bool = undefined;
2789+
const llvm_ptr = switch (ptr_val.tag()) {
28052790
.decl_ref_mut => {
28062791
const decl = ptr_val.castTag(.decl_ref_mut).?.data.decl;
2807-
return dg.lowerParentPtrDecl(ptr_val, decl);
2792+
return dg.lowerParentPtrDecl(ptr_val, decl, ptr_child_ty);
28082793
},
28092794
.decl_ref => {
28102795
const decl = ptr_val.castTag(.decl_ref).?.data;
2811-
return dg.lowerParentPtrDecl(ptr_val, decl);
2796+
return dg.lowerParentPtrDecl(ptr_val, decl, ptr_child_ty);
28122797
},
28132798
.variable => {
28142799
const decl = ptr_val.castTag(.variable).?.data.owner_decl;
2815-
return dg.lowerParentPtrDecl(ptr_val, decl);
2800+
return dg.lowerParentPtrDecl(ptr_val, decl, ptr_child_ty);
28162801
},
28172802
.int_i64 => {
28182803
const int = ptr_val.castTag(.int_i64).?.data;
28192804
const llvm_usize = try dg.llvmType(Type.usize);
28202805
const llvm_int = llvm_usize.constInt(@bitCast(u64, int), .False);
2821-
return ParentPtr{
2822-
.llvm_ptr = llvm_int.constIntToPtr(try dg.llvmType(base_ty)),
2823-
.ty = base_ty,
2824-
};
2806+
return llvm_int.constIntToPtr((try dg.llvmType(ptr_child_ty)).pointerType(0));
28252807
},
28262808
.int_u64 => {
28272809
const int = ptr_val.castTag(.int_u64).?.data;
28282810
const llvm_usize = try dg.llvmType(Type.usize);
28292811
const llvm_int = llvm_usize.constInt(int, .False);
2830-
return ParentPtr{
2831-
.llvm_ptr = llvm_int.constIntToPtr(try dg.llvmType(base_ty)),
2832-
.ty = base_ty,
2833-
};
2812+
return llvm_int.constIntToPtr((try dg.llvmType(ptr_child_ty)).pointerType(0));
28342813
},
2835-
.field_ptr => {
2814+
.field_ptr => blk: {
28362815
const field_ptr = ptr_val.castTag(.field_ptr).?.data;
2837-
const parent = try dg.lowerParentPtr(field_ptr.container_ptr, base_ty);
2816+
const parent_llvm_ptr = try dg.lowerParentPtr(field_ptr.container_ptr, field_ptr.container_ty);
2817+
const parent_ty = field_ptr.container_ty;
2818+
28382819
const field_index = @intCast(u32, field_ptr.field_index);
28392820
const llvm_u32 = dg.context.intType(32);
28402821
const target = dg.module.getTarget();
2841-
switch (parent.ty.zigTypeTag()) {
2822+
switch (parent_ty.zigTypeTag()) {
28422823
.Union => {
2843-
const fields = parent.ty.unionFields();
2844-
const layout = parent.ty.unionGetLayout(target);
2845-
const field_ty = fields.values()[field_index].ty;
2824+
bitcast_needed = true;
2825+
2826+
const layout = parent_ty.unionGetLayout(target);
28462827
if (layout.payload_size == 0) {
28472828
// In this case a pointer to the union and a pointer to any
28482829
// (void) payload is the same.
2849-
return ParentPtr{
2850-
.llvm_ptr = parent.llvm_ptr,
2851-
.ty = field_ty,
2852-
};
2853-
}
2854-
if (layout.tag_size == 0) {
2855-
const indices: [2]*const llvm.Value = .{
2856-
llvm_u32.constInt(0, .False),
2857-
llvm_u32.constInt(0, .False),
2858-
};
2859-
return ParentPtr{
2860-
.llvm_ptr = parent.llvm_ptr.constInBoundsGEP(&indices, indices.len),
2861-
.ty = field_ty,
2862-
};
2830+
break :blk parent_llvm_ptr;
28632831
}
2864-
const llvm_pl_index = @boolToInt(layout.tag_align >= layout.payload_align);
2832+
const llvm_pl_index = if (layout.tag_size == 0)
2833+
0
2834+
else
2835+
@boolToInt(layout.tag_align >= layout.payload_align);
28652836
const indices: [2]*const llvm.Value = .{
28662837
llvm_u32.constInt(0, .False),
28672838
llvm_u32.constInt(llvm_pl_index, .False),
28682839
};
2869-
return ParentPtr{
2870-
.llvm_ptr = parent.llvm_ptr.constInBoundsGEP(&indices, indices.len),
2871-
.ty = field_ty,
2872-
};
2840+
break :blk parent_llvm_ptr.constInBoundsGEP(&indices, indices.len);
28732841
},
28742842
.Struct => {
2843+
const field_ty = parent_ty.structFieldType(field_index);
2844+
bitcast_needed = !field_ty.eql(ptr_child_ty);
2845+
28752846
var ty_buf: Type.Payload.Pointer = undefined;
2876-
const llvm_field_index = llvmFieldIndex(parent.ty, field_index, target, &ty_buf).?;
2847+
const llvm_field_index = llvmFieldIndex(parent_ty, field_index, target, &ty_buf).?;
28772848
const indices: [2]*const llvm.Value = .{
28782849
llvm_u32.constInt(0, .False),
28792850
llvm_u32.constInt(llvm_field_index, .False),
28802851
};
2881-
return ParentPtr{
2882-
.llvm_ptr = parent.llvm_ptr.constInBoundsGEP(&indices, indices.len),
2883-
.ty = parent.ty.structFieldType(field_index),
2884-
};
2852+
break :blk parent_llvm_ptr.constInBoundsGEP(&indices, indices.len);
28852853
},
28862854
else => unreachable,
28872855
}
28882856
},
2889-
.elem_ptr => {
2857+
.elem_ptr => blk: {
28902858
const elem_ptr = ptr_val.castTag(.elem_ptr).?.data;
2891-
const parent = try dg.lowerParentPtr(elem_ptr.array_ptr, base_ty);
2859+
const parent_llvm_ptr = try dg.lowerParentPtr(elem_ptr.array_ptr, elem_ptr.elem_ty);
2860+
bitcast_needed = !elem_ptr.elem_ty.eql(ptr_child_ty);
2861+
28922862
const llvm_usize = try dg.llvmType(Type.usize);
2893-
const indices: [2]*const llvm.Value = .{
2894-
llvm_usize.constInt(0, .False),
2863+
const indices: [1]*const llvm.Value = .{
28952864
llvm_usize.constInt(elem_ptr.index, .False),
28962865
};
2897-
return ParentPtr{
2898-
.llvm_ptr = parent.llvm_ptr.constInBoundsGEP(&indices, indices.len),
2899-
.ty = parent.ty.childType(),
2900-
};
2866+
break :blk parent_llvm_ptr.constInBoundsGEP(&indices, indices.len);
29012867
},
2902-
.opt_payload_ptr => {
2868+
.opt_payload_ptr => blk: {
29032869
const opt_payload_ptr = ptr_val.castTag(.opt_payload_ptr).?.data;
2904-
const parent = try dg.lowerParentPtr(opt_payload_ptr, base_ty);
2870+
const parent_llvm_ptr = try dg.lowerParentPtr(opt_payload_ptr.container_ptr, opt_payload_ptr.container_ty);
29052871
var buf: Type.Payload.ElemType = undefined;
2906-
const payload_ty = parent.ty.optionalChild(&buf);
2907-
if (!payload_ty.hasRuntimeBitsIgnoreComptime() or parent.ty.isPtrLikeOptional()) {
2872+
2873+
const payload_ty = opt_payload_ptr.container_ty.optionalChild(&buf);
2874+
bitcast_needed = !payload_ty.eql(ptr_child_ty);
2875+
2876+
if (!payload_ty.hasRuntimeBitsIgnoreComptime() or payload_ty.isPtrLikeOptional()) {
29082877
// In this case, we represent pointer to optional the same as pointer
29092878
// to the payload.
2910-
return ParentPtr{
2911-
.llvm_ptr = parent.llvm_ptr,
2912-
.ty = payload_ty,
2913-
};
2879+
break :blk parent_llvm_ptr;
29142880
}
29152881

29162882
const llvm_u32 = dg.context.intType(32);
29172883
const indices: [2]*const llvm.Value = .{
29182884
llvm_u32.constInt(0, .False),
29192885
llvm_u32.constInt(0, .False),
29202886
};
2921-
return ParentPtr{
2922-
.llvm_ptr = parent.llvm_ptr.constInBoundsGEP(&indices, indices.len),
2923-
.ty = payload_ty,
2924-
};
2887+
break :blk parent_llvm_ptr.constInBoundsGEP(&indices, indices.len);
29252888
},
2926-
.eu_payload_ptr => {
2889+
.eu_payload_ptr => blk: {
29272890
const eu_payload_ptr = ptr_val.castTag(.eu_payload_ptr).?.data;
2928-
const parent = try dg.lowerParentPtr(eu_payload_ptr, base_ty);
2929-
const payload_ty = parent.ty.errorUnionPayload();
2891+
const parent_llvm_ptr = try dg.lowerParentPtr(eu_payload_ptr.container_ptr, eu_payload_ptr.container_ty);
2892+
2893+
const payload_ty = eu_payload_ptr.container_ty.errorUnionPayload();
2894+
bitcast_needed = !payload_ty.eql(ptr_child_ty);
2895+
29302896
if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {
29312897
// In this case, we represent pointer to error union the same as pointer
29322898
// to the payload.
2933-
return ParentPtr{
2934-
.llvm_ptr = parent.llvm_ptr,
2935-
.ty = payload_ty,
2936-
};
2899+
break :blk parent_llvm_ptr;
29372900
}
29382901

29392902
const llvm_u32 = dg.context.intType(32);
29402903
const indices: [2]*const llvm.Value = .{
29412904
llvm_u32.constInt(0, .False),
29422905
llvm_u32.constInt(1, .False),
29432906
};
2944-
return ParentPtr{
2945-
.llvm_ptr = parent.llvm_ptr.constInBoundsGEP(&indices, indices.len),
2946-
.ty = payload_ty,
2947-
};
2907+
break :blk parent_llvm_ptr.constInBoundsGEP(&indices, indices.len);
29482908
},
29492909
else => unreachable,
2910+
};
2911+
if (bitcast_needed) {
2912+
return llvm_ptr.constBitCast((try dg.llvmType(ptr_child_ty)).pointerType(0));
2913+
} else {
2914+
return llvm_ptr;
29502915
}
29512916
}
29522917

0 commit comments

Comments
 (0)