authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-02-28 10:58:22+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-02-28 11:40:25+01:00
log06f58a0b3b241a38ca4092a9f4ee8012370dcff6
treef69cdaaaea09dd09e9dee4be5e5a5b75b3dfa46f
parent1dc05e9e77e7213e384b9b79b370ae14174fdef1

codegen: impl lowering of union type to memory


1 files changed, 67 insertions(+), 3 deletions(-)

src/codegen.zig+67-3
...@@ -466,10 +466,74 @@ pub fn generateSymbol(...@@ -466,10 +466,74 @@ pub fn generateSymbol(
466 return Result{ .appended = {} };466 return Result{ .appended = {} };
467 },467 },
468 .Union => {468 .Union => {
469 // TODO generateSymbol for unions469 // TODO generate debug info for unions
470 const target = bin_file.options.target;470 const target = bin_file.options.target;
471 const abi_size = try math.cast(usize, typed_value.ty.abiSize(target));471 const union_obj = typed_value.val.castTag(.@"union").?.data;
472 try code.writer().writeByteNTimes(0xaa, abi_size);472 const layout = typed_value.ty.unionGetLayout(target);
473
474 if (layout.payload_size == 0) {
475 switch (try generateSymbol(bin_file, parent_atom_index, src_loc, .{
476 .ty = typed_value.ty.unionTagType().?,
477 .val = union_obj.tag,
478 }, code, debug_output)) {
479 .appended => {},
480 .externally_managed => |external_slice| {
481 code.appendSliceAssumeCapacity(external_slice);
482 },
483 .fail => |em| return Result{ .fail = em },
484 }
485 }
486
487 // Check if we should store the tag first.
488 if (layout.tag_align >= layout.payload_align) {
489 switch (try generateSymbol(bin_file, parent_atom_index, src_loc, .{
490 .ty = typed_value.ty.unionTagType().?,
491 .val = union_obj.tag,
492 }, code, debug_output)) {
493 .appended => {},
494 .externally_managed => |external_slice| {
495 code.appendSliceAssumeCapacity(external_slice);
496 },
497 .fail => |em| return Result{ .fail = em },
498 }
499 }
500
501 const union_ty = typed_value.ty.cast(Type.Payload.Union).?.data;
502 const field_index = union_ty.tag_ty.enumTagFieldIndex(union_obj.tag).?;
503 assert(union_ty.haveFieldTypes());
504 const field_ty = union_ty.fields.values()[field_index].ty;
505 if (!field_ty.hasRuntimeBits()) {
506 try code.writer().writeByteNTimes(0xaa, try math.cast(usize, layout.payload_size));
507 } else {
508 switch (try generateSymbol(bin_file, parent_atom_index, src_loc, .{
509 .ty = field_ty,
510 .val = union_obj.val,
511 }, code, debug_output)) {
512 .appended => {},
513 .externally_managed => |external_slice| {
514 code.appendSliceAssumeCapacity(external_slice);
515 },
516 .fail => |em| return Result{ .fail = em },
517 }
518
519 const padding = try math.cast(usize, layout.payload_size - field_ty.abiSize(target));
520 if (padding > 0) {
521 try code.writer().writeByteNTimes(0, padding);
522 }
523 }
524
525 if (layout.tag_size > 0) {
526 switch (try generateSymbol(bin_file, parent_atom_index, src_loc, .{
527 .ty = union_ty.tag_ty,
528 .val = union_obj.tag,
529 }, code, debug_output)) {
530 .appended => {},
531 .externally_managed => |external_slice| {
532 code.appendSliceAssumeCapacity(external_slice);
533 },
534 .fail => |em| return Result{ .fail = em },
535 }
536 }
473537
474 return Result{ .appended = {} };538 return Result{ .appended = {} };
475 },539 },