@@ -375,8 +375,6 @@ pub const DeclGen = struct {
375
375
val : Value ,
376
376
decl : * Decl ,
377
377
) error { OutOfMemory , AnalysisFail }! void {
378
- decl .markAlive ();
379
-
380
378
const target = dg .module .getTarget ();
381
379
382
380
if (ty .isSlice ()) {
@@ -461,12 +459,14 @@ pub const DeclGen = struct {
461
459
}
462
460
}
463
461
464
- // Renders a "child " pointer (e.g. ElemPtr, FieldPtr) by recursing
465
- // to the root decl/variable that acts as its parent
462
+ // Renders a "parent " pointer by recursing to the root decl/variable
463
+ // that its contents are defined with respect to.
466
464
//
467
- // Used for .elem_ptr, .field_ptr, .opt_payload_ptr, .eu_payload_ptr, since
468
- // the Type of their container cannot be retrieved from their own Type
469
- fn renderChildPtr (dg : * DeclGen , writer : anytype , ptr_val : Value ) error { OutOfMemory , AnalysisFail }! Type {
465
+ // Used for .elem_ptr, .field_ptr, .opt_payload_ptr, .eu_payload_ptr
466
+ fn renderParentPtr (dg : * DeclGen , writer : anytype , ptr_val : Value , ptr_ty : Type ) error { OutOfMemory , AnalysisFail }! void {
467
+ try writer .writeByte ('(' );
468
+ try dg .renderTypecast (writer , ptr_ty );
469
+ try writer .writeByte (')' );
470
470
switch (ptr_val .tag ()) {
471
471
.decl_ref_mut , .decl_ref , .variable = > {
472
472
const decl = switch (ptr_val .tag ()) {
@@ -475,16 +475,12 @@ pub const DeclGen = struct {
475
475
.variable = > ptr_val .castTag (.variable ).? .data .owner_decl ,
476
476
else = > unreachable ,
477
477
};
478
- try dg .renderDeclName (writer , decl );
479
- return decl .ty ;
478
+ try dg .renderDeclValue (writer , ptr_ty , ptr_val , decl );
480
479
},
481
480
.field_ptr = > {
482
481
const field_ptr = ptr_val .castTag (.field_ptr ).? .data ;
482
+ const container_ty = field_ptr .container_ty ;
483
483
const index = field_ptr .field_index ;
484
-
485
- try writer .writeAll ("&(" );
486
- const container_ty = try dg .renderChildPtr (writer , field_ptr .container_ptr );
487
-
488
484
const field_name = switch (container_ty .zigTypeTag ()) {
489
485
.Struct = > container_ty .structFields ().keys ()[index ],
490
486
.Union = > container_ty .unionFields ().keys ()[index ],
@@ -495,19 +491,48 @@ pub const DeclGen = struct {
495
491
.Union = > container_ty .unionFields ().values ()[index ].ty ,
496
492
else = > unreachable ,
497
493
};
498
- try writer .print (").{ }" , .{fmtIdent (field_name )});
494
+ var container_ptr_ty_pl : Type.Payload.ElemType = .{
495
+ .base = .{ .tag = .c_mut_pointer },
496
+ .data = field_ptr .container_ty ,
497
+ };
498
+ const container_ptr_ty = Type .initPayload (& container_ptr_ty_pl .base );
499
499
500
- return field_ty ;
500
+ if (field_ty .hasRuntimeBitsIgnoreComptime ()) {
501
+ try writer .writeAll ("&(" );
502
+ try dg .renderParentPtr (writer , field_ptr .container_ptr , container_ptr_ty );
503
+ if (field_ptr .container_ty .tag () == .union_tagged ) {
504
+ try writer .print (")->payload.{ }" , .{fmtIdent (field_name )});
505
+ } else {
506
+ try writer .print (")->{ }" , .{fmtIdent (field_name )});
507
+ }
508
+ } else {
509
+ try dg .renderParentPtr (writer , field_ptr .container_ptr , field_ty );
510
+ }
501
511
},
502
512
.elem_ptr = > {
503
513
const elem_ptr = ptr_val .castTag (.elem_ptr ).? .data ;
514
+ var elem_ptr_ty_pl : Type.Payload.ElemType = .{
515
+ .base = .{ .tag = .c_mut_pointer },
516
+ .data = elem_ptr .elem_ty ,
517
+ };
518
+ const elem_ptr_ty = Type .initPayload (& elem_ptr_ty_pl .base );
519
+
504
520
try writer .writeAll ("&(" );
505
- const container_ty = try dg .renderChildPtr (writer , elem_ptr .array_ptr );
521
+ try dg .renderParentPtr (writer , elem_ptr .array_ptr , elem_ptr_ty );
506
522
try writer .print (")[{d}]" , .{elem_ptr .index });
507
- return container_ty .childType ();
508
523
},
509
- .opt_payload_ptr = > return dg .fail ("implement renderChildPtr for optional payload" , .{}),
510
- .eu_payload_ptr = > return dg .fail ("implement renderChildPtr for error union payload" , .{}),
524
+ .opt_payload_ptr , .eu_payload_ptr = > {
525
+ const payload_ptr = ptr_val .cast (Value .Payload .PayloadPtr ).? .data ;
526
+ var container_ptr_ty_pl : Type.Payload.ElemType = .{
527
+ .base = .{ .tag = .c_mut_pointer },
528
+ .data = payload_ptr .container_ty ,
529
+ };
530
+ const container_ptr_ty = Type .initPayload (& container_ptr_ty_pl .base );
531
+
532
+ try writer .writeAll ("&(" );
533
+ try dg .renderParentPtr (writer , payload_ptr .container_ptr , container_ptr_ty );
534
+ try writer .writeAll (")->payload" );
535
+ },
511
536
else = > unreachable ,
512
537
}
513
538
}
@@ -559,6 +584,13 @@ pub const DeclGen = struct {
559
584
.Int = > switch (val .tag ()) {
560
585
.int_big_positive = > try dg .renderBigIntConst (writer , val .castTag (.int_big_positive ).? .asBigInt (), ty .isSignedInt ()),
561
586
.int_big_negative = > try dg .renderBigIntConst (writer , val .castTag (.int_big_negative ).? .asBigInt (), true ),
587
+ .field_ptr ,
588
+ .elem_ptr ,
589
+ .opt_payload_ptr ,
590
+ .eu_payload_ptr ,
591
+ .decl_ref_mut ,
592
+ .decl_ref ,
593
+ = > try dg .renderParentPtr (writer , val , ty ),
562
594
else = > {
563
595
if (ty .isSignedInt ())
564
596
return writer .print ("{d}" , .{val .toSignedInt ()});
@@ -586,10 +618,6 @@ pub const DeclGen = struct {
586
618
// to the assigned pointer type. Note this is just a hack to fix warnings from ordered comparisons (<, >, etc)
587
619
// between pointers and 0, which is an extension to begin with.
588
620
.zero = > try writer .writeByte ('0' ),
589
- .decl_ref = > {
590
- const decl = val .castTag (.decl_ref ).? .data ;
591
- return dg .renderDeclValue (writer , ty , val , decl );
592
- },
593
621
.variable = > {
594
622
const decl = val .castTag (.variable ).? .data .owner_decl ;
595
623
return dg .renderDeclValue (writer , ty , val , decl );
@@ -606,9 +634,6 @@ pub const DeclGen = struct {
606
634
try dg .renderValue (writer , Type .usize , slice .len );
607
635
try writer .writeAll ("}" );
608
636
},
609
- .field_ptr , .elem_ptr , .opt_payload_ptr , .eu_payload_ptr = > {
610
- _ = try dg .renderChildPtr (writer , val );
611
- },
612
637
.function = > {
613
638
const func = val .castTag (.function ).? .data ;
614
639
try dg .renderDeclName (writer , func .owner_decl );
@@ -622,6 +647,13 @@ pub const DeclGen = struct {
622
647
try dg .renderTypecast (writer , ty );
623
648
try writer .print (")0x{x}u)" , .{val .toUnsignedInt (target )});
624
649
},
650
+ .field_ptr ,
651
+ .elem_ptr ,
652
+ .opt_payload_ptr ,
653
+ .eu_payload_ptr ,
654
+ .decl_ref_mut ,
655
+ .decl_ref ,
656
+ = > try dg .renderParentPtr (writer , val , ty ),
625
657
else = > unreachable ,
626
658
},
627
659
.Array = > {
@@ -1326,7 +1358,7 @@ pub const DeclGen = struct {
1326
1358
return w .writeAll (name );
1327
1359
},
1328
1360
.Struct = > {
1329
- const name = dg .getTypedefName (t ) orelse if (t .isTuple ())
1361
+ const name = dg .getTypedefName (t ) orelse if (t .isTuple () or t . tag () == .anon_struct )
1330
1362
try dg .renderTupleTypedef (t )
1331
1363
else
1332
1364
try dg .renderStructTypedef (t );
@@ -1346,11 +1378,11 @@ pub const DeclGen = struct {
1346
1378
1347
1379
try dg .renderType (w , int_tag_ty );
1348
1380
},
1381
+ .Opaque = > return w .writeAll ("void" ),
1349
1382
1350
1383
.Frame ,
1351
1384
.AnyFrame ,
1352
1385
.Vector ,
1353
- .Opaque ,
1354
1386
= > | tag | return dg .fail ("TODO: C backend: implement value of type {s}" , .{
1355
1387
@tagName (tag ),
1356
1388
}),
@@ -1497,6 +1529,8 @@ pub const DeclGen = struct {
1497
1529
}
1498
1530
1499
1531
fn renderDeclName (dg : DeclGen , writer : anytype , decl : * Decl ) ! void {
1532
+ decl .markAlive ();
1533
+
1500
1534
if (dg .module .decl_exports .get (decl )) | exports | {
1501
1535
return writer .writeAll (exports [0 ].options .name );
1502
1536
} else if (decl .val .tag () == .extern_fn ) {
@@ -3188,7 +3222,7 @@ fn structFieldPtr(f: *Function, inst: Air.Inst.Index, struct_ptr_ty: Type, struc
3188
3222
field_name = fields .keys ()[index ];
3189
3223
field_val_ty = fields .values ()[index ].ty ;
3190
3224
},
3191
- .tuple = > {
3225
+ .tuple , .anon_struct = > {
3192
3226
const tuple = struct_ty .tupleFields ();
3193
3227
if (tuple .values [index ].tag () != .unreachable_value ) return CValue .none ;
3194
3228
@@ -3203,9 +3237,17 @@ fn structFieldPtr(f: *Function, inst: Air.Inst.Index, struct_ptr_ty: Type, struc
3203
3237
const inst_ty = f .air .typeOfIndex (inst );
3204
3238
const local = try f .allocLocal (inst_ty , .Const );
3205
3239
3206
- try writer .print (" = &" , .{});
3207
- try f .writeCValueDeref (writer , struct_ptr );
3208
- try writer .print (".{s}{ };\n " , .{ payload , fmtIdent (field_name ) });
3240
+ if (field_val_ty .hasRuntimeBitsIgnoreComptime ()) {
3241
+ try writer .writeAll (" = &" );
3242
+ try f .writeCValueDeref (writer , struct_ptr );
3243
+ try writer .print (".{s}{ };\n " , .{ payload , fmtIdent (field_name ) });
3244
+ } else {
3245
+ try writer .writeAll (" = (" );
3246
+ try f .renderTypecast (writer , inst_ty );
3247
+ try writer .writeByte (')' );
3248
+ try f .writeCValue (writer , struct_ptr );
3249
+ try writer .writeAll (";\n " );
3250
+ }
3209
3251
return local ;
3210
3252
}
3211
3253
@@ -3223,7 +3265,7 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {
3223
3265
const field_name = switch (struct_ty .tag ()) {
3224
3266
.@"struct" = > struct_ty .structFields ().keys ()[extra .field_index ],
3225
3267
.@"union" , .union_tagged = > struct_ty .unionFields ().keys ()[extra .field_index ],
3226
- .tuple = > blk : {
3268
+ .tuple , .anon_struct = > blk : {
3227
3269
const tuple = struct_ty .tupleFields ();
3228
3270
if (tuple .values [extra .field_index ].tag () != .unreachable_value ) return CValue .none ;
3229
3271
@@ -3348,8 +3390,36 @@ fn airWrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue {
3348
3390
}
3349
3391
3350
3392
fn airErrUnionPayloadPtrSet (f : * Function , inst : Air.Inst.Index ) ! CValue {
3351
- _ = inst ;
3352
- return f .fail ("TODO: C backend: implement airErrUnionPayloadPtrSet" , .{});
3393
+ const writer = f .object .writer ();
3394
+ const ty_op = f .air .instructions .items (.data )[inst ].ty_op ;
3395
+ const operand = try f .resolveInst (ty_op .operand );
3396
+ const error_union_ty = f .air .typeOf (ty_op .operand ).childType ();
3397
+
3398
+ const error_ty = error_union_ty .errorUnionSet ();
3399
+ const payload_ty = error_union_ty .errorUnionPayload ();
3400
+
3401
+ // First, set the non-error value.
3402
+ if (! payload_ty .hasRuntimeBitsIgnoreComptime ()) {
3403
+ try f .writeCValueDeref (writer , operand );
3404
+ try writer .writeAll (" = " );
3405
+ try f .object .dg .renderValue (writer , error_ty , Value .zero );
3406
+ try writer .writeAll (";\n " );
3407
+
3408
+ return operand ;
3409
+ }
3410
+ try f .writeCValueDeref (writer , operand );
3411
+ try writer .writeAll (".error = " );
3412
+ try f .object .dg .renderValue (writer , error_ty , Value .zero );
3413
+ try writer .writeAll (";\n " );
3414
+
3415
+ // Then return the payload pointer (only if it is used)
3416
+ if (f .liveness .isUnused (inst )) return CValue .none ;
3417
+
3418
+ const local = try f .allocLocal (f .air .typeOfIndex (inst ), .Const );
3419
+ try writer .writeAll (" = &(" );
3420
+ try f .writeCValueDeref (writer , operand );
3421
+ try writer .writeAll (").payload;\n " );
3422
+ return local ;
3353
3423
}
3354
3424
3355
3425
fn airWrapErrUnionPay (f : * Function , inst : Air.Inst.Index ) ! CValue {
0 commit comments