authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-12-09 20:01:13-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-12-09 20:01:13-05:00
loge9efa74333b4890b2598c96dc7df4761965e6819
tree578fe751aa813d41469440bc0a53063a46d61ec6
parentf466e539ef27d1cf90e2b163d5afbcf0bffc0aa5

partial parameter decl parsing


2 files changed, 433 insertions(+), 33 deletions(-)

src-self-hosted/main.zig+432-32
......@@ -86,6 +86,8 @@ const Token = struct {
8686 LBrace,
8787 RBrace,
8888 Period,
89 Ellipsis2,
90 Ellipsis3,
8991 Minus,
9092 Arrow,
9193 Colon,
......@@ -200,6 +202,8 @@ const Tokenizer = struct {
200202 FloatExponentUnsigned,
201203 FloatExponentNumber,
202204 Ampersand,
205 Period,
206 Period2,
203207 };
204208
205209 pub fn next(self: &Tokenizer) -> Token {
......@@ -278,9 +282,7 @@ const Tokenizer = struct {
278282 break;
279283 },
280284 '.' => {
281 result.id = Token.Id.Period;
282 self.index += 1;
283 break;
285 state = State.Period;
284286 },
285287 '-' => {
286288 state = State.Minus;
......@@ -370,6 +372,29 @@ const Tokenizer = struct {
370372 break;
371373 },
372374 },
375
376 State.Period => switch (c) {
377 '.' => {
378 state = State.Period2;
379 },
380 else => {
381 result.id = Token.Id.Period;
382 break;
383 },
384 },
385
386 State.Period2 => switch (c) {
387 '.' => {
388 result.id = Token.Id.Ellipsis3;
389 self.index += 1;
390 break;
391 },
392 else => {
393 result.id = Token.Id.Ellipsis2;
394 break;
395 },
396 },
397
373398 State.Slash => switch (c) {
374399 '/' => {
375400 result.id = undefined;
......@@ -451,15 +476,30 @@ const Tokenizer = struct {
451476 }
452477};
453478
479const Comptime = enum { No, Yes };
480const NoAlias = enum { No, Yes };
481const Extern = enum { No, Yes };
482const VarArgs = enum { No, Yes };
483const Mutability = enum { Const, Var };
484
485const Inline = enum {
486 Auto,
487 Always,
488 Never,
489};
490
454491const Visibility = enum {
455492 Private,
456493 Pub,
457494 Export,
458495};
459496
460const Mutability = enum {
461 Const,
462 Var,
497const CallingConvention = enum {
498 Auto,
499 C,
500 Cold,
501 Naked,
502 Stdcall,
463503};
464504
465505const AstNode = struct {
......@@ -469,6 +509,8 @@ const AstNode = struct {
469509 Root,
470510 VarDecl,
471511 Identifier,
512 FnProto,
513 ParamDecl,
472514 };
473515
474516 fn iterate(base: &AstNode, index: usize) -> ?&AstNode {
......@@ -476,6 +518,8 @@ const AstNode = struct {
476518 Id.Root => @fieldParentPtr(AstNodeRoot, "base", base).iterate(index),
477519 Id.VarDecl => @fieldParentPtr(AstNodeVarDecl, "base", base).iterate(index),
478520 Id.Identifier => @fieldParentPtr(AstNodeIdentifier, "base", base).iterate(index),
521 Id.FnProto => @fieldParentPtr(AstNodeFnProto, "base", base).iterate(index),
522 Id.ParamDecl => @fieldParentPtr(AstNodeParamDecl, "base", base).iterate(index),
479523 };
480524 }
481525};
......@@ -498,7 +542,9 @@ const AstNodeVarDecl = struct {
498542 name_token: Token,
499543 eq_token: Token,
500544 mut: Mutability,
501 is_comptime: bool,
545 is_comptime: Comptime,
546 is_extern: Extern,
547 lib_name: ?&AstNode,
502548 type_node: ?&AstNode,
503549 align_node: ?&AstNode,
504550 init_node: ?&AstNode,
......@@ -534,12 +580,75 @@ const AstNodeIdentifier = struct {
534580 }
535581};
536582
583const AstNodeFnProto = struct {
584 base: AstNode,
585 visib: Visibility,
586 fn_token: Token,
587 name_token: ?Token,
588 params: ArrayList(&AstNode),
589 return_type: ?&AstNode,
590 var_args: VarArgs,
591 is_extern: Extern,
592 is_inline: Inline,
593 cc: CallingConvention,
594 fn_def_node: ?&AstNode,
595 lib_name: ?&AstNode, // populated if this is an extern declaration
596 align_expr: ?&AstNode, // populated if align(A) is present
597
598 fn iterate(self: &AstNodeFnProto, index: usize) -> ?&AstNode {
599 var i = index;
600
601 if (i < self.params.len) return self.params.items[i];
602 i -= self.params.len;
603
604 if (self.return_type) |return_type| {
605 if (i < 1) return return_type;
606 i -= 1;
607 }
608
609 if (self.fn_def_node) |fn_def_node| {
610 if (i < 1) return fn_def_node;
611 i -= 1;
612 }
613
614 if (self.lib_name) |lib_name| {
615 if (i < 1) return lib_name;
616 i -= 1;
617 }
618
619 if (self.align_expr) |align_expr| {
620 if (i < 1) return align_expr;
621 i -= 1;
622 }
623
624 return null;
625 }
626};
627
628const AstNodeParamDecl = struct {
629 base: AstNode,
630 comptime_token: ?Token,
631 noalias_token: ?Token,
632 name_token: ?Token,
633 type_node: &AstNode,
634 var_args_token: ?Token,
635
636 fn iterate(self: &AstNodeParamDecl, index: usize) -> ?&AstNode {
637 var i = index;
638
639 if (i < 1) return self.type_node;
640 i -= 1;
641
642 return null;
643 }
644};
645
537646error ParseError;
538647
539648const Parser = struct {
540649 tokenizer: &Tokenizer,
541650 allocator: &mem.Allocator,
542 put_back_tokens: [1]Token,
651 put_back_tokens: [2]Token,
543652 put_back_count: usize,
544653 source_file_name: []const u8,
545654
......@@ -556,14 +665,32 @@ const Parser = struct {
556665 const State = union(enum) {
557666 TopLevel,
558667 TopLevelModifier: Visibility,
559 Expression: &?&AstNode,
560 GroupedExpression: &?&AstNode,
561 PrimaryExpression: &?&AstNode,
562 TypeExpr: &?&AstNode,
668 TopLevelExtern: Visibility,
669 Expression: &&AstNode,
670 GroupedExpression: &&AstNode,
671 UnwrapExpression: &&AstNode,
672 BoolOrExpression: &&AstNode,
673 BoolAndExpression: &&AstNode,
674 ComparisonExpression: &&AstNode,
675 BinaryOrExpression: &&AstNode,
676 BinaryXorExpression: &&AstNode,
677 BinaryAndExpression: &&AstNode,
678 BitShiftExpression: &&AstNode,
679 AdditionExpression: &&AstNode,
680 MultiplyExpression: &&AstNode,
681 BraceSuffixExpression: &&AstNode,
682 PrefixOpExpression: &&AstNode,
683 SuffixOpExpression: &&AstNode,
684 PrimaryExpression: &&AstNode,
685 TypeExpr: &&AstNode,
563686 VarDecl: &AstNodeVarDecl,
564687 VarDeclAlign: &AstNodeVarDecl,
565688 VarDeclEq: &AstNodeVarDecl,
566 ExpectSemicolon,
689 ExpectToken: @TagType(Token.Id),
690 FnProto: &AstNodeFnProto,
691 FnProtoAlign: &AstNodeFnProto,
692 ParamDecl: &AstNodeFnProto,
693 ParamDeclComma,
567694 };
568695
569696 pub fn parse(self: &Parser) -> %&AstNode {
......@@ -593,19 +720,31 @@ const Parser = struct {
593720 },
594721 Token.Id.Keyword_const => {
595722 stack.append(State.TopLevel) %% unreachable;
596 const var_decl_node = %return self.createVarDecl(Visibility.Private, Mutability.Const, false);
597 %return root_node.decls.append(&var_decl_node.base);
723 const var_decl_node = {
724 const var_decl_node = %return self.createVarDecl(Visibility.Private, Mutability.Const, Comptime.No, Extern.No);
725 %defer self.allocator.destroy(var_decl_node);
726 %return root_node.decls.append(&var_decl_node.base);
727 var_decl_node
728 };
598729 %return stack.append(State { .VarDecl = var_decl_node });
599730 continue;
600731 },
601732 Token.Id.Keyword_var => {
602733 stack.append(State.TopLevel) %% unreachable;
603 const var_decl_node = %return self.createVarDecl(Visibility.Private, Mutability.Var, false);
604 %return root_node.decls.append(&var_decl_node.base);
734 const var_decl_node = {
735 const var_decl_node = %return self.createVarDecl(Visibility.Private, Mutability.Var, Comptime.No, Extern.No);
736 %defer self.allocator.destroy(var_decl_node);
737 %return root_node.decls.append(&var_decl_node.base);
738 var_decl_node
739 };
605740 %return stack.append(State { .VarDecl = var_decl_node });
606741 continue;
607742 },
608743 Token.Id.Eof => return &root_node.base,
744 Token.Id.Keyword_extern => {
745 stack.append(State { .TopLevelExtern = Visibility.Private }) %% unreachable;
746 continue;
747 },
609748 else => return self.parseError(token, "expected top level declaration, found {}", @tagName(token.id)),
610749 }
611750 },
......@@ -614,28 +753,81 @@ const Parser = struct {
614753 switch (token.id) {
615754 Token.Id.Keyword_const => {
616755 stack.append(State.TopLevel) %% unreachable;
617 const var_decl_node = %return self.createVarDecl(visib, Mutability.Const, false);
618 %return root_node.decls.append(&var_decl_node.base);
756 const var_decl_node = {
757 const var_decl_node = %return self.createVarDecl(visib, Mutability.Const, Comptime.No, Extern.No);
758 %defer self.allocator.destroy(var_decl_node);
759 %return root_node.decls.append(&var_decl_node.base);
760 var_decl_node
761 };
619762 %return stack.append(State { .VarDecl = var_decl_node });
620763 continue;
621764 },
622765 Token.Id.Keyword_var => {
623766 stack.append(State.TopLevel) %% unreachable;
624 const var_decl_node = %return self.createVarDecl(visib, Mutability.Var, false);
625 %return root_node.decls.append(&var_decl_node.base);
767 const var_decl_node = {
768 const var_decl_node = %return self.createVarDecl(visib, Mutability.Var, Comptime.No, Extern.No);
769 %defer self.allocator.destroy(var_decl_node);
770 %return root_node.decls.append(&var_decl_node.base);
771 var_decl_node
772 };
626773 %return stack.append(State { .VarDecl = var_decl_node });
627774 continue;
628775 },
776 Token.Id.Keyword_extern => {
777 stack.append(State { .TopLevelExtern = visib }) %% unreachable;
778 continue;
779 },
629780 else => return self.parseError(token, "expected top level declaration, found {}", @tagName(token.id)),
630781 }
631782 },
783 State.TopLevelExtern => |visib| {
784 const token = self.getNextToken();
785 switch (token.id) {
786 Token.Id.Keyword_var => {
787 stack.append(State.TopLevel) %% unreachable;
788 const var_decl_node = {
789 const var_decl_node = %return self.createVarDecl(visib, Mutability.Var, Comptime.No, Extern.Yes);
790 %defer self.allocator.destroy(var_decl_node);
791 %return root_node.decls.append(&var_decl_node.base);
792 var_decl_node
793 };
794 %return stack.append(State { .VarDecl = var_decl_node });
795 continue;
796 },
797 Token.Id.Keyword_fn => {
798 stack.append(State.TopLevel) %% unreachable;
799 const fn_proto_node = %return self.createAttachFnProto(&root_node.decls, token,
800 Extern.Yes, CallingConvention.Auto, visib, Inline.Auto);
801 %return stack.append(State { .FnProto = fn_proto_node });
802 continue;
803 },
804 Token.Id.StringLiteral => {
805 @panic("TODO extern with string literal");
806 },
807 Token.Id.Keyword_coldcc, Token.Id.Keyword_nakedcc, Token.Id.Keyword_stdcallcc => {
808 stack.append(State.TopLevel) %% unreachable;
809 const cc = switch (token.id) {
810 Token.Id.Keyword_coldcc => CallingConvention.Cold,
811 Token.Id.Keyword_nakedcc => CallingConvention.Naked,
812 Token.Id.Keyword_stdcallcc => CallingConvention.Stdcall,
813 else => unreachable,
814 };
815 const fn_token = %return self.eatToken(Token.Id.Keyword_fn);
816 const fn_proto_node = %return self.createAttachFnProto(&root_node.decls, fn_token,
817 Extern.Yes, cc, visib, Inline.Auto);
818 %return stack.append(State { .FnProto = fn_proto_node });
819 continue;
820 },
821 else => return self.parseError(token, "expected variable declaration or function, found {}", @tagName(token.id)),
822 }
823 },
632824 State.VarDecl => |var_decl| {
633825 var_decl.name_token = %return self.eatToken(Token.Id.Identifier);
634826 stack.append(State { .VarDeclAlign = var_decl }) %% unreachable;
635827
636828 const next_token = self.getNextToken();
637829 if (next_token.id == Token.Id.Colon) {
638 %return stack.append(State { .TypeExpr = &var_decl.type_node });
830 %return stack.append(State { .TypeExpr = removeNullCast(&var_decl.type_node) });
639831 continue;
640832 }
641833
......@@ -647,7 +839,7 @@ const Parser = struct {
647839
648840 const next_token = self.getNextToken();
649841 if (next_token.id == Token.Id.Keyword_align) {
650 %return stack.append(State { .GroupedExpression = &var_decl.align_node });
842 %return stack.append(State { .GroupedExpression = removeNullCast(&var_decl.align_node) });
651843 continue;
652844 }
653845
......@@ -656,21 +848,86 @@ const Parser = struct {
656848 },
657849 State.VarDeclEq => |var_decl| {
658850 var_decl.eq_token = %return self.eatToken(Token.Id.Equal);
659 stack.append(State.ExpectSemicolon) %% unreachable;
851 stack.append(State { .ExpectToken = Token.Id.Semicolon }) %% unreachable;
660852 %return stack.append(State {
661 .Expression = &var_decl.init_node,
853 .Expression = removeNullCast(&var_decl.init_node),
662854 });
663855 continue;
664856 },
665 State.ExpectSemicolon => {
666 _ = %return self.eatToken(Token.Id.Semicolon);
857 State.ExpectToken => |token_id| {
858 _ = %return self.eatToken(token_id);
667859 continue;
668860 },
669861 State.Expression => |result_ptr| {
670 // TODO this should not jump straight to primary expression
671 stack.append(State {.PrimaryExpression = result_ptr}) %% unreachable;
862 stack.append(State {.UnwrapExpression = result_ptr}) %% unreachable;
863 continue;
864 },
865
866 State.UnwrapExpression => |result_ptr| {
867 stack.append(State {.BoolOrExpression = result_ptr}) %% unreachable;
868 continue;
869 },
870
871 State.BoolOrExpression => |result_ptr| {
872 stack.append(State {.BoolAndExpression = result_ptr}) %% unreachable;
873 continue;
874 },
875
876 State.BoolAndExpression => |result_ptr| {
877 stack.append(State {.ComparisonExpression = result_ptr}) %% unreachable;
878 continue;
879 },
880
881 State.ComparisonExpression => |result_ptr| {
882 stack.append(State {.BinaryOrExpression = result_ptr}) %% unreachable;
883 continue;
884 },
885
886 State.BinaryOrExpression => |result_ptr| {
887 stack.append(State {.BinaryXorExpression = result_ptr}) %% unreachable;
888 continue;
889 },
890
891 State.BinaryXorExpression => |result_ptr| {
892 stack.append(State {.BinaryAndExpression = result_ptr}) %% unreachable;
893 continue;
894 },
895
896 State.BinaryAndExpression => |result_ptr| {
897 stack.append(State {.BitShiftExpression = result_ptr}) %% unreachable;
898 continue;
899 },
900
901 State.BitShiftExpression => |result_ptr| {
902 stack.append(State {.AdditionExpression = result_ptr}) %% unreachable;
903 continue;
904 },
905
906 State.AdditionExpression => |result_ptr| {
907 stack.append(State {.AdditionExpression = result_ptr}) %% unreachable;
908 continue;
909 },
910
911 State.MultiplyExpression => |result_ptr| {
912 stack.append(State {.BraceSuffixExpression = result_ptr}) %% unreachable;
913 continue;
914 },
915
916 State.BraceSuffixExpression => |result_ptr| {
917 stack.append(State {.PrefixOpExpression = result_ptr}) %% unreachable;
918 continue;
919 },
920
921 State.PrefixOpExpression => |result_ptr| {
922 stack.append(State { .SuffixOpExpression = result_ptr }) %% unreachable;
923 continue;
924 },
925
926 State.SuffixOpExpression => |result_ptr| {
927 stack.append(State { .PrimaryExpression = result_ptr }) %% unreachable;
672928 continue;
673929 },
930
674931 State.PrimaryExpression => |result_ptr| {
675932 const token = self.getNextToken();
676933 switch (token.id) {
......@@ -682,7 +939,84 @@ const Parser = struct {
682939 else => return self.parseError(token, "expected primary expression, found {}", @tagName(token.id)),
683940 }
684941 },
685 State.TypeExpr => @panic("TODO"),
942
943 State.TypeExpr => |result_ptr| {
944 const token = self.getNextToken();
945 if (token.id == Token.Id.Keyword_var) {
946 @panic("TODO param with type var");
947 }
948 self.putBackToken(token);
949
950 stack.append(State { .PrefixOpExpression = result_ptr }) %% unreachable;
951 continue;
952 },
953
954 State.FnProto => |fn_proto| {
955 stack.append(State { .FnProtoAlign = fn_proto }) %% unreachable;
956 %return stack.append(State { .ParamDecl = fn_proto });
957 %return stack.append(State { .ExpectToken = Token.Id.LParen });
958
959 const next_token = self.getNextToken();
960 if (next_token.id == Token.Id.Identifier) {
961 fn_proto.name_token = next_token;
962 continue;
963 }
964 self.putBackToken(next_token);
965 continue;
966 },
967
968 State.FnProtoAlign => |fn_proto| {
969 @panic("TODO fn proto align");
970 //continue;
971 },
972
973 State.ParamDecl => |fn_proto| {
974 var token = self.getNextToken();
975 if (token.id == Token.Id.RParen) {
976 continue;
977 }
978 const param_decl = %return self.createAttachParamDecl(&fn_proto.params);
979 if (token.id == Token.Id.Keyword_comptime) {
980 param_decl.comptime_token = token;
981 token = self.getNextToken();
982 } else if (token.id == Token.Id.Keyword_noalias) {
983 param_decl.noalias_token = token;
984 token = self.getNextToken();
985 };
986 if (token.id == Token.Id.Identifier) {
987 const next_token = self.getNextToken();
988 if (next_token.id == Token.Id.Colon) {
989 param_decl.name_token = token;
990 token = self.getNextToken();
991 } else {
992 self.putBackToken(next_token);
993 }
994 }
995 if (token.id == Token.Id.Ellipsis3) {
996 param_decl.var_args_token = token;
997 } else {
998 self.putBackToken(token);
999 }
1000
1001 stack.append(State { .ParamDecl = fn_proto }) %% unreachable;
1002 %return stack.append(State.ParamDeclComma);
1003 %return stack.append(State { .TypeExpr = &param_decl.type_node });
1004 continue;
1005 },
1006
1007 State.ParamDeclComma => {
1008 const token = self.getNextToken();
1009 switch (token.id) {
1010 Token.Id.RParen => {
1011 _ = stack.pop(); // pop off the ParamDecl
1012 continue;
1013 },
1014 Token.Id.Comma => continue,
1015 else => return self.parseError(token, "expected ',' or ')', found {}", @tagName(token.id)),
1016 }
1017 },
1018
1019
6861020 State.GroupedExpression => @panic("TODO"),
6871021 }
6881022 unreachable;
......@@ -700,7 +1034,9 @@ const Parser = struct {
7001034 return node;
7011035 }
7021036
703 fn createVarDecl(self: &Parser, visib: Visibility, mut: Mutability, is_comptime: bool) -> %&AstNodeVarDecl {
1037 fn createVarDecl(self: &Parser, visib: Visibility, mut: Mutability, is_comptime: Comptime,
1038 is_extern: Extern) -> %&AstNodeVarDecl
1039 {
7041040 const node = %return self.allocator.create(AstNodeVarDecl);
7051041 %defer self.allocator.destroy(node);
7061042
......@@ -709,9 +1045,11 @@ const Parser = struct {
7091045 .visib = visib,
7101046 .mut = mut,
7111047 .is_comptime = is_comptime,
1048 .is_extern = is_extern,
7121049 .type_node = null,
7131050 .align_node = null,
7141051 .init_node = null,
1052 .lib_name = null,
7151053 // initialized later
7161054 .name_token = undefined,
7171055 .eq_token = undefined,
......@@ -730,6 +1068,61 @@ const Parser = struct {
7301068 return node;
7311069 }
7321070
1071 fn createFnProto(self: &Parser, fn_token: &const Token, is_extern: Extern,
1072 cc: CallingConvention, visib: Visibility, is_inline: Inline) -> %&AstNodeFnProto
1073 {
1074 const node = %return self.allocator.create(AstNodeFnProto);
1075 %defer self.allocator.destroy(node);
1076
1077 *node = AstNodeFnProto {
1078 .base = AstNode {.id = AstNode.Id.FnProto},
1079 .visib = visib,
1080 .name_token = null,
1081 .fn_token = *fn_token,
1082 .params = ArrayList(&AstNode).init(self.allocator),
1083 .return_type = null,
1084 .var_args = VarArgs.No,
1085 .is_extern = is_extern,
1086 .is_inline = is_inline,
1087 .cc = cc,
1088 .fn_def_node = null,
1089 .lib_name = null,
1090 .align_expr = null,
1091 };
1092 return node;
1093 }
1094
1095 fn createParamDecl(self: &Parser) -> %&AstNodeParamDecl {
1096 const node = %return self.allocator.create(AstNodeParamDecl);
1097 %defer self.allocator.destroy(node);
1098
1099 *node = AstNodeParamDecl {
1100 .base = AstNode {.id = AstNode.Id.ParamDecl},
1101 .comptime_token = null,
1102 .noalias_token = null,
1103 .name_token = null,
1104 .type_node = undefined,
1105 .var_args_token = null,
1106 };
1107 return node;
1108 }
1109
1110 fn createAttachParamDecl(self: &Parser, list: &ArrayList(&AstNode)) -> %&AstNodeParamDecl {
1111 const node = %return self.createParamDecl();
1112 %defer self.allocator.destroy(node);
1113 %return list.append(&node.base);
1114 return node;
1115 }
1116
1117 fn createAttachFnProto(self: &Parser, list: &ArrayList(&AstNode), fn_token: &const Token,
1118 is_extern: Extern, cc: CallingConvention, visib: Visibility, is_inline: Inline) -> %&AstNodeFnProto
1119 {
1120 const node = %return self.createFnProto(fn_token, is_extern, cc, visib, is_inline);
1121 %defer self.allocator.destroy(node);
1122 %return list.append(&node.base);
1123 return node;
1124 }
1125
7331126 fn parseError(self: &Parser, token: &const Token, comptime fmt: []const u8, args: ...) -> error {
7341127 const loc = self.tokenizer.getTokenLocation(token);
7351128 warn("{}:{}:{}: error: " ++ fmt ++ "\n", self.source_file_name, loc.line + 1, loc.column + 1, args);
......@@ -778,7 +1171,6 @@ const Parser = struct {
7781171 self.tokenizer.next()
7791172 };
7801173 }
781
7821174};
7831175
7841176
......@@ -841,3 +1233,11 @@ fn render(node: &AstNode, indent: usize) {
8411233 render(child, indent + 2);
8421234 }
8431235}
1236
1237fn removeNullCast(x: var) -> {const InnerPtr = @typeOf(x).Child.Child; &InnerPtr} {
1238 comptime assert(@typeId(@typeOf(x)) == builtin.TypeId.Pointer);
1239 comptime assert(@typeId(@typeOf(x).Child) == builtin.TypeId.Nullable);
1240 comptime assert(@typeId(@typeOf(x).Child.Child) == builtin.TypeId.Pointer);
1241 const InnerPtr = @typeOf(x).Child.Child;
1242 return @ptrCast(&InnerPtr, x);
1243}
src/analyze.cpp+1-1
......@@ -2227,7 +2227,7 @@ static void resolve_union_zero_bits(CodeGen *g, TypeTableEntry *union_type) {
22272227
22282228 tag_type = new_type_table_entry(TypeTableEntryIdEnum);
22292229 buf_resize(&tag_type->name, 0);
2230 buf_appendf(&tag_type->name, "@EnumTagType(%s)", buf_ptr(&union_type->name));
2230 buf_appendf(&tag_type->name, "@TagType(%s)", buf_ptr(&union_type->name));
22312231 tag_type->is_copyable = true;
22322232 tag_type->type_ref = tag_int_type->type_ref;
22332233 tag_type->zero_bits = tag_int_type->zero_bits;