@@ -2424,6 +2424,24 @@ pub const DeclGen = struct {
2424
2424
}
2425
2425
2426
2426
fn lowerType (dg : * DeclGen , t : Type ) Allocator.Error ! * const llvm.Type {
2427
+ const llvm_ty = try lowerTypeInner (dg , t );
2428
+ if (std .debug .runtime_safety and false ) check : {
2429
+ if (t .zigTypeTag () == .Opaque ) break :check ;
2430
+ if (! t .hasRuntimeBits ()) break :check ;
2431
+ if (! llvm_ty .isSized ().toBool ()) break :check ;
2432
+
2433
+ const zig_size = t .abiSize (dg .module .getTarget ());
2434
+ const llvm_size = dg .object .target_data .abiSizeOfType (llvm_ty );
2435
+ if (llvm_size != zig_size ) {
2436
+ log .err ("when lowering {}, Zig ABI size = {d} but LLVM ABI size = {d}" , .{
2437
+ t .fmt (dg .module ), zig_size , llvm_size ,
2438
+ });
2439
+ }
2440
+ }
2441
+ return llvm_ty ;
2442
+ }
2443
+
2444
+ fn lowerTypeInner (dg : * DeclGen , t : Type ) Allocator.Error ! * const llvm.Type {
2427
2445
const gpa = dg .gpa ;
2428
2446
const target = dg .module .getTarget ();
2429
2447
switch (t .zigTypeTag ()) {
@@ -2519,10 +2537,18 @@ pub const DeclGen = struct {
2519
2537
return payload_llvm_ty ;
2520
2538
}
2521
2539
2522
- const fields : [2 ]* const llvm.Type = .{
2523
- payload_llvm_ty , dg .context .intType (1 ),
2540
+ comptime assert (optional_layout_version == 2 );
2541
+ var fields_buf : [3 ]* const llvm.Type = .{
2542
+ payload_llvm_ty , dg .context .intType (1 ), undefined ,
2524
2543
};
2525
- return dg .context .structType (& fields , fields .len , .False );
2544
+ const offset = child_ty .abiSize (target ) + 1 ;
2545
+ const abi_size = t .abiSize (target );
2546
+ const padding = @intCast (c_uint , abi_size - offset );
2547
+ if (padding == 0 ) {
2548
+ return dg .context .structType (& fields_buf , 2 , .False );
2549
+ }
2550
+ fields_buf [2 ] = dg .context .intType (8 ).arrayType (padding );
2551
+ return dg .context .structType (& fields_buf , 3 , .False );
2526
2552
},
2527
2553
.ErrorUnion = > {
2528
2554
const payload_ty = t .errorUnionPayload ();
@@ -2534,12 +2560,37 @@ pub const DeclGen = struct {
2534
2560
2535
2561
const payload_align = payload_ty .abiAlignment (target );
2536
2562
const error_align = Type .anyerror .abiAlignment (target );
2563
+
2564
+ const payload_size = payload_ty .abiSize (target );
2565
+ const error_size = Type .anyerror .abiSize (target );
2566
+
2567
+ var fields_buf : [3 ]* const llvm.Type = undefined ;
2537
2568
if (error_align > payload_align ) {
2538
- const fields : [2 ]* const llvm.Type = .{ llvm_error_type , llvm_payload_type };
2539
- return dg .context .structType (& fields , fields .len , .False );
2569
+ fields_buf [0 ] = llvm_error_type ;
2570
+ fields_buf [1 ] = llvm_payload_type ;
2571
+ const payload_end =
2572
+ std .mem .alignForwardGeneric (u64 , error_size , payload_align ) +
2573
+ payload_size ;
2574
+ const abi_size = std .mem .alignForwardGeneric (u64 , payload_end , error_align );
2575
+ const padding = @intCast (c_uint , abi_size - payload_end );
2576
+ if (padding == 0 ) {
2577
+ return dg .context .structType (& fields_buf , 2 , .False );
2578
+ }
2579
+ fields_buf [2 ] = dg .context .intType (8 ).arrayType (padding );
2580
+ return dg .context .structType (& fields_buf , 3 , .False );
2540
2581
} else {
2541
- const fields : [2 ]* const llvm.Type = .{ llvm_payload_type , llvm_error_type };
2542
- return dg .context .structType (& fields , fields .len , .False );
2582
+ fields_buf [0 ] = llvm_payload_type ;
2583
+ fields_buf [1 ] = llvm_error_type ;
2584
+ const error_end =
2585
+ std .mem .alignForwardGeneric (u64 , payload_size , error_align ) +
2586
+ error_size ;
2587
+ const abi_size = std .mem .alignForwardGeneric (u64 , error_end , payload_align );
2588
+ const padding = @intCast (c_uint , abi_size - error_end );
2589
+ if (padding == 0 ) {
2590
+ return dg .context .structType (& fields_buf , 2 , .False );
2591
+ }
2592
+ fields_buf [2 ] = dg .context .intType (8 ).arrayType (padding );
2593
+ return dg .context .structType (& fields_buf , 3 , .False );
2543
2594
}
2544
2595
},
2545
2596
.ErrorSet = > return dg .context .intType (16 ),
@@ -2704,7 +2755,7 @@ pub const DeclGen = struct {
2704
2755
llvm_aligned_field_ty ,
2705
2756
dg .context .intType (8 ).arrayType (padding_len ),
2706
2757
};
2707
- break :t dg .context .structType (& fields , fields .len , .False );
2758
+ break :t dg .context .structType (& fields , fields .len , .True );
2708
2759
};
2709
2760
2710
2761
if (layout .tag_size == 0 ) {
@@ -3020,7 +3071,7 @@ pub const DeclGen = struct {
3020
3071
return dg .context .constStruct (
3021
3072
llvm_elems .ptr ,
3022
3073
@intCast (c_uint , llvm_elems .len ),
3023
- .False ,
3074
+ .True ,
3024
3075
);
3025
3076
} else {
3026
3077
const llvm_elem_ty = try dg .lowerType (elem_ty );
@@ -3057,7 +3108,7 @@ pub const DeclGen = struct {
3057
3108
return dg .context .constStruct (
3058
3109
llvm_elems .ptr ,
3059
3110
@intCast (c_uint , llvm_elems .len ),
3060
- .False ,
3111
+ .True ,
3061
3112
);
3062
3113
} else {
3063
3114
const llvm_elem_ty = try dg .lowerType (elem_ty );
@@ -3074,7 +3125,7 @@ pub const DeclGen = struct {
3074
3125
const llvm_elems : [1 ]* const llvm.Value = .{sentinel };
3075
3126
const need_unnamed = dg .isUnnamedType (elem_ty , llvm_elems [0 ]);
3076
3127
if (need_unnamed ) {
3077
- return dg .context .constStruct (& llvm_elems , llvm_elems .len , .False );
3128
+ return dg .context .constStruct (& llvm_elems , llvm_elems .len , .True );
3078
3129
} else {
3079
3130
const llvm_elem_ty = try dg .lowerType (elem_ty );
3080
3131
return llvm_elem_ty .constArray (& llvm_elems , llvm_elems .len );
@@ -3083,6 +3134,7 @@ pub const DeclGen = struct {
3083
3134
else = > unreachable ,
3084
3135
},
3085
3136
.Optional = > {
3137
+ comptime assert (optional_layout_version == 2 );
3086
3138
var buf : Type.Payload.ElemType = undefined ;
3087
3139
const payload_ty = tv .ty .optionalChild (& buf );
3088
3140
const llvm_i1 = dg .context .intType (1 );
@@ -3091,25 +3143,30 @@ pub const DeclGen = struct {
3091
3143
if (! payload_ty .hasRuntimeBitsIgnoreComptime ()) {
3092
3144
return non_null_bit ;
3093
3145
}
3146
+ const llvm_ty = try dg .lowerType (tv .ty );
3094
3147
if (tv .ty .optionalReprIsPayload ()) {
3095
3148
if (tv .val .castTag (.opt_payload )) | payload | {
3096
3149
return dg .lowerValue (.{ .ty = payload_ty , .val = payload .data });
3097
3150
} else if (is_pl ) {
3098
3151
return dg .lowerValue (.{ .ty = payload_ty , .val = tv .val });
3099
3152
} else {
3100
- const llvm_ty = try dg .lowerType (tv .ty );
3101
3153
return llvm_ty .constNull ();
3102
3154
}
3103
3155
}
3104
3156
assert (payload_ty .zigTypeTag () != .Fn );
3105
- const fields : [2 ]* const llvm.Value = .{
3106
- try dg .lowerValue (.{
3107
- .ty = payload_ty ,
3108
- .val = if (tv .val .castTag (.opt_payload )) | pl | pl .data else Value .initTag (.undef ),
3109
- }),
3110
- non_null_bit ,
3111
- };
3112
- return dg .context .constStruct (& fields , fields .len , .False );
3157
+
3158
+ const llvm_field_count = llvm_ty .countStructElementTypes ();
3159
+ var fields_buf : [3 ]* const llvm.Value = undefined ;
3160
+ fields_buf [0 ] = try dg .lowerValue (.{
3161
+ .ty = payload_ty ,
3162
+ .val = if (tv .val .castTag (.opt_payload )) | pl | pl .data else Value .initTag (.undef ),
3163
+ });
3164
+ fields_buf [1 ] = non_null_bit ;
3165
+ if (llvm_field_count > 2 ) {
3166
+ assert (llvm_field_count == 3 );
3167
+ fields_buf [2 ] = llvm_ty .structGetTypeAtIndex (2 ).getUndef ();
3168
+ }
3169
+ return dg .context .constStruct (& fields_buf , llvm_field_count , .False );
3113
3170
},
3114
3171
.Fn = > {
3115
3172
const fn_decl_index = switch (tv .val .tag ()) {
@@ -3155,12 +3212,23 @@ pub const DeclGen = struct {
3155
3212
.ty = payload_type ,
3156
3213
.val = if (tv .val .castTag (.eu_payload )) | pl | pl .data else Value .initTag (.undef ),
3157
3214
});
3215
+ var fields_buf : [3 ]* const llvm.Value = undefined ;
3216
+
3217
+ const llvm_ty = try dg .lowerType (tv .ty );
3218
+ const llvm_field_count = llvm_ty .countStructElementTypes ();
3219
+ if (llvm_field_count > 2 ) {
3220
+ assert (llvm_field_count == 3 );
3221
+ fields_buf [2 ] = llvm_ty .structGetTypeAtIndex (2 ).getUndef ();
3222
+ }
3223
+
3158
3224
if (error_align > payload_align ) {
3159
- const fields : [2 ]* const llvm.Value = .{ llvm_error_value , llvm_payload_value };
3160
- return dg .context .constStruct (& fields , fields .len , .False );
3225
+ fields_buf [0 ] = llvm_error_value ;
3226
+ fields_buf [1 ] = llvm_payload_value ;
3227
+ return dg .context .constStruct (& fields_buf , llvm_field_count , .False );
3161
3228
} else {
3162
- const fields : [2 ]* const llvm.Value = .{ llvm_payload_value , llvm_error_value };
3163
- return dg .context .constStruct (& fields , fields .len , .False );
3229
+ fields_buf [0 ] = llvm_payload_value ;
3230
+ fields_buf [1 ] = llvm_error_value ;
3231
+ return dg .context .constStruct (& fields_buf , llvm_field_count , .False );
3164
3232
}
3165
3233
},
3166
3234
.Struct = > {
@@ -3361,7 +3429,7 @@ pub const DeclGen = struct {
3361
3429
const fields : [2 ]* const llvm.Value = .{
3362
3430
field , dg .context .intType (8 ).arrayType (padding_len ).getUndef (),
3363
3431
};
3364
- break :p dg .context .constStruct (& fields , fields .len , .False );
3432
+ break :p dg .context .constStruct (& fields , fields .len , .True );
3365
3433
};
3366
3434
3367
3435
if (layout .tag_size == 0 ) {
@@ -5847,6 +5915,7 @@ pub const FuncGen = struct {
5847
5915
const ty_op = self .air .instructions .items (.data )[inst ].ty_op ;
5848
5916
const payload_ty = self .air .typeOf (ty_op .operand );
5849
5917
const non_null_bit = self .context .intType (1 ).constAllOnes ();
5918
+ comptime assert (optional_layout_version == 2 );
5850
5919
if (! payload_ty .hasRuntimeBitsIgnoreComptime ()) return non_null_bit ;
5851
5920
const operand = try self .resolveInst (ty_op .operand );
5852
5921
const optional_ty = self .air .typeOfIndex (inst );
@@ -9300,6 +9369,7 @@ fn intrinsicsAllowed(scalar_ty: Type, target: std.Target) bool {
9300
9369
/// We can do this because for all types, Zig ABI alignment >= LLVM ABI
9301
9370
/// alignment.
9302
9371
const struct_layout_version = 2 ;
9372
+ const optional_layout_version = 2 ;
9303
9373
9304
9374
/// We use the least significant bit of the pointer address to tell us
9305
9375
/// whether the type is fully resolved. Types that are only fwd declared
0 commit comments