authorgravatar for sahnvour@pm.meSahnvour <sahnvour@pm.me> 2019-09-21 17:38:45+02:00
committergravatar for sahnvour@pm.meSahnvour <sahnvour@pm.me> 2019-11-24 21:33:58+01:00
log104b6f16297812b1578262a5b5b4a091a6fc480d
tree415fbda958356c99758bfdec2c5aa4dafef076c0
parent874b34a30f588294210fe91d08e29fc6baa1a0a4

refactored gen_h_file to improve maintainability and output

- extracted functions - factorised extern "C" into a block containing all function prototypes instead of writing macros all over the place - using intermediate buffers instead of writing directly to the output file

2 files changed, 158 insertions(+), 139 deletions(-)

src/codegen.cpp+142-125
...@@ -9732,113 +9732,7 @@ static Buf *preprocessor_mangle(Buf *src) {...@@ -9732,113 +9732,7 @@ static Buf *preprocessor_mangle(Buf *src) {
9732 return result;9732 return result;
9733}9733}
97349734
9735static void gen_h_file(CodeGen *g) {9735static void gen_h_file_types(CodeGen* g, GenH* gen_h, Buf* out_buf) {
9736 GenH gen_h_data = {0};
9737 GenH *gen_h = &gen_h_data;
9738
9739 assert(!g->is_test_build);
9740 assert(!g->disable_gen_h);
9741
9742 Buf *out_h_path = buf_sprintf("%s" OS_SEP "%s.h", buf_ptr(g->output_dir), buf_ptr(g->root_out_name));
9743
9744 FILE *out_h = fopen(buf_ptr(out_h_path), "wb");
9745 if (!out_h)
9746 zig_panic("unable to open %s: %s\n", buf_ptr(out_h_path), strerror(errno));
9747
9748 Buf *export_macro = nullptr;
9749 if (g->is_dynamic) {
9750 export_macro = preprocessor_mangle(buf_sprintf("%s_EXPORT", buf_ptr(g->root_out_name)));
9751 buf_upcase(export_macro);
9752 }
9753
9754 Buf *extern_c_macro = preprocessor_mangle(buf_sprintf("%s_EXTERN_C", buf_ptr(g->root_out_name)));
9755 buf_upcase(extern_c_macro);
9756
9757 Buf h_buf = BUF_INIT;
9758 buf_resize(&h_buf, 0);
9759 for (size_t fn_def_i = 0; fn_def_i < g->fn_defs.length; fn_def_i += 1) {
9760 ZigFn *fn_table_entry = g->fn_defs.at(fn_def_i);
9761
9762 if (fn_table_entry->export_list.length == 0)
9763 continue;
9764
9765 FnTypeId *fn_type_id = &fn_table_entry->type_entry->data.fn.fn_type_id;
9766
9767 Buf return_type_c = BUF_INIT;
9768 get_c_type(g, gen_h, fn_type_id->return_type, &return_type_c);
9769
9770 Buf *symbol_name;
9771 if (fn_table_entry->export_list.length == 0) {
9772 symbol_name = &fn_table_entry->symbol_name;
9773 } else {
9774 GlobalExport *fn_export = &fn_table_entry->export_list.items[0];
9775 symbol_name = &fn_export->name;
9776 }
9777
9778 buf_appendf(&h_buf, "%s %s %s(",
9779 buf_ptr(g->is_dynamic ? export_macro : extern_c_macro),
9780 buf_ptr(&return_type_c),
9781 buf_ptr(symbol_name));
9782
9783 Buf param_type_c = BUF_INIT;
9784 if (fn_type_id->param_count > 0) {
9785 for (size_t param_i = 0; param_i < fn_type_id->param_count; param_i += 1) {
9786 FnTypeParamInfo *param_info = &fn_type_id->param_info[param_i];
9787 AstNode *param_decl_node = get_param_decl_node(fn_table_entry, param_i);
9788 Buf *param_name = param_decl_node->data.param_decl.name;
9789
9790 const char *comma_str = (param_i == 0) ? "" : ", ";
9791 const char *restrict_str = param_info->is_noalias ? "restrict" : "";
9792 get_c_type(g, gen_h, param_info->type, &param_type_c);
9793
9794 if (param_info->type->id == ZigTypeIdArray) {
9795 // Arrays decay to pointers
9796 buf_appendf(&h_buf, "%s%s%s %s[]", comma_str, buf_ptr(&param_type_c),
9797 restrict_str, buf_ptr(param_name));
9798 } else {
9799 buf_appendf(&h_buf, "%s%s%s %s", comma_str, buf_ptr(&param_type_c),
9800 restrict_str, buf_ptr(param_name));
9801 }
9802 }
9803 buf_appendf(&h_buf, ")");
9804 } else {
9805 buf_appendf(&h_buf, "void)");
9806 }
9807
9808 buf_appendf(&h_buf, ";\n");
9809
9810 }
9811
9812 Buf *ifdef_dance_name = preprocessor_mangle(buf_sprintf("%s_H", buf_ptr(g->root_out_name)));
9813 buf_upcase(ifdef_dance_name);
9814
9815 fprintf(out_h, "#ifndef %s\n", buf_ptr(ifdef_dance_name));
9816 fprintf(out_h, "#define %s\n\n", buf_ptr(ifdef_dance_name));
9817
9818 if (g->c_want_stdbool)
9819 fprintf(out_h, "#include <stdbool.h>\n");
9820 if (g->c_want_stdint)
9821 fprintf(out_h, "#include <stdint.h>\n");
9822
9823 fprintf(out_h, "\n");
9824
9825 fprintf(out_h, "#ifdef __cplusplus\n");
9826 fprintf(out_h, "#define %s extern \"C\"\n", buf_ptr(extern_c_macro));
9827 fprintf(out_h, "#else\n");
9828 fprintf(out_h, "#define %s\n", buf_ptr(extern_c_macro));
9829 fprintf(out_h, "#endif\n");
9830 fprintf(out_h, "\n");
9831
9832 if (g->is_dynamic) {
9833 fprintf(out_h, "#if defined(_WIN32)\n");
9834 fprintf(out_h, "#define %s %s __declspec(dllimport)\n", buf_ptr(export_macro), buf_ptr(extern_c_macro));
9835 fprintf(out_h, "#else\n");
9836 fprintf(out_h, "#define %s %s __attribute__((visibility (\"default\")))\n",
9837 buf_ptr(export_macro), buf_ptr(extern_c_macro));
9838 fprintf(out_h, "#endif\n");
9839 fprintf(out_h, "\n");
9840 }
9841
9842 for (size_t type_i = 0; type_i < gen_h->types_to_declare.length; type_i += 1) {9736 for (size_t type_i = 0; type_i < gen_h->types_to_declare.length; type_i += 1) {
9843 ZigType *type_entry = gen_h->types_to_declare.at(type_i);9737 ZigType *type_entry = gen_h->types_to_declare.at(type_i);
9844 switch (type_entry->id) {9738 switch (type_entry->id) {
...@@ -9869,25 +9763,25 @@ static void gen_h_file(CodeGen *g) {...@@ -9869,25 +9763,25 @@ static void gen_h_file(CodeGen *g) {
98699763
9870 case ZigTypeIdEnum:9764 case ZigTypeIdEnum:
9871 if (type_entry->data.enumeration.layout == ContainerLayoutExtern) {9765 if (type_entry->data.enumeration.layout == ContainerLayoutExtern) {
9872 fprintf(out_h, "enum %s {\n", buf_ptr(type_h_name(type_entry)));9766 buf_appendf(out_buf, "enum %s {\n", buf_ptr(type_h_name(type_entry)));
9873 for (uint32_t field_i = 0; field_i < type_entry->data.enumeration.src_field_count; field_i += 1) {9767 for (uint32_t field_i = 0; field_i < type_entry->data.enumeration.src_field_count; field_i += 1) {
9874 TypeEnumField *enum_field = &type_entry->data.enumeration.fields[field_i];9768 TypeEnumField *enum_field = &type_entry->data.enumeration.fields[field_i];
9875 Buf *value_buf = buf_alloc();9769 Buf *value_buf = buf_alloc();
9876 bigint_append_buf(value_buf, &enum_field->value, 10);9770 bigint_append_buf(value_buf, &enum_field->value, 10);
9877 fprintf(out_h, " %s = %s", buf_ptr(enum_field->name), buf_ptr(value_buf));9771 buf_appendf(out_buf, " %s = %s", buf_ptr(enum_field->name), buf_ptr(value_buf));
9878 if (field_i != type_entry->data.enumeration.src_field_count - 1) {9772 if (field_i != type_entry->data.enumeration.src_field_count - 1) {
9879 fprintf(out_h, ",");9773 buf_appendf(out_buf, ",");
9880 }9774 }
9881 fprintf(out_h, "\n");9775 buf_appendf(out_buf, "\n");
9882 }9776 }
9883 fprintf(out_h, "};\n\n");9777 buf_appendf(out_buf, "};\n\n");
9884 } else {9778 } else {
9885 fprintf(out_h, "enum %s;\n", buf_ptr(type_h_name(type_entry)));9779 buf_appendf(out_buf, "enum %s;\n\n", buf_ptr(type_h_name(type_entry)));
9886 }9780 }
9887 break;9781 break;
9888 case ZigTypeIdStruct:9782 case ZigTypeIdStruct:
9889 if (type_entry->data.structure.layout == ContainerLayoutExtern) {9783 if (type_entry->data.structure.layout == ContainerLayoutExtern) {
9890 fprintf(out_h, "struct %s {\n", buf_ptr(type_h_name(type_entry)));9784 buf_appendf(out_buf, "struct %s {\n", buf_ptr(type_h_name(type_entry)));
9891 for (uint32_t field_i = 0; field_i < type_entry->data.structure.src_field_count; field_i += 1) {9785 for (uint32_t field_i = 0; field_i < type_entry->data.structure.src_field_count; field_i += 1) {
9892 TypeStructField *struct_field = type_entry->data.structure.fields[field_i];9786 TypeStructField *struct_field = type_entry->data.structure.fields[field_i];
98939787
...@@ -9895,43 +9789,166 @@ static void gen_h_file(CodeGen *g) {...@@ -9895,43 +9789,166 @@ static void gen_h_file(CodeGen *g) {
9895 get_c_type(g, gen_h, struct_field->type_entry, type_name_buf);9789 get_c_type(g, gen_h, struct_field->type_entry, type_name_buf);
98969790
9897 if (struct_field->type_entry->id == ZigTypeIdArray) {9791 if (struct_field->type_entry->id == ZigTypeIdArray) {
9898 fprintf(out_h, " %s %s[%" ZIG_PRI_u64 "];\n", buf_ptr(type_name_buf),9792 buf_appendf(out_buf, " %s %s[%" ZIG_PRI_u64 "];\n", buf_ptr(type_name_buf),
9899 buf_ptr(struct_field->name),9793 buf_ptr(struct_field->name),
9900 struct_field->type_entry->data.array.len);9794 struct_field->type_entry->data.array.len);
9901 } else {9795 } else {
9902 fprintf(out_h, " %s %s;\n", buf_ptr(type_name_buf), buf_ptr(struct_field->name));9796 buf_appendf(out_buf, " %s %s;\n", buf_ptr(type_name_buf), buf_ptr(struct_field->name));
9903 }9797 }
99049798
9905 }9799 }
9906 fprintf(out_h, "};\n\n");9800 buf_appendf(out_buf, "};\n\n");
9907 } else {9801 } else {
9908 fprintf(out_h, "struct %s;\n", buf_ptr(type_h_name(type_entry)));9802 buf_appendf(out_buf, "struct %s;\n\n", buf_ptr(type_h_name(type_entry)));
9909 }9803 }
9910 break;9804 break;
9911 case ZigTypeIdUnion:9805 case ZigTypeIdUnion:
9912 if (type_entry->data.unionation.layout == ContainerLayoutExtern) {9806 if (type_entry->data.unionation.layout == ContainerLayoutExtern) {
9913 fprintf(out_h, "union %s {\n", buf_ptr(type_h_name(type_entry)));9807 buf_appendf(out_buf, "union %s {\n", buf_ptr(type_h_name(type_entry)));
9914 for (uint32_t field_i = 0; field_i < type_entry->data.unionation.src_field_count; field_i += 1) {9808 for (uint32_t field_i = 0; field_i < type_entry->data.unionation.src_field_count; field_i += 1) {
9915 TypeUnionField *union_field = &type_entry->data.unionation.fields[field_i];9809 TypeUnionField *union_field = &type_entry->data.unionation.fields[field_i];
99169810
9917 Buf *type_name_buf = buf_alloc();9811 Buf *type_name_buf = buf_alloc();
9918 get_c_type(g, gen_h, union_field->type_entry, type_name_buf);9812 get_c_type(g, gen_h, union_field->type_entry, type_name_buf);
9919 fprintf(out_h, " %s %s;\n", buf_ptr(type_name_buf), buf_ptr(union_field->name));9813 buf_appendf(out_buf, " %s %s;\n", buf_ptr(type_name_buf), buf_ptr(union_field->name));
9920 }9814 }
9921 fprintf(out_h, "};\n\n");9815 buf_appendf(out_buf, "};\n\n");
9922 } else {9816 } else {
9923 fprintf(out_h, "union %s;\n", buf_ptr(type_h_name(type_entry)));9817 buf_appendf(out_buf, "union %s;\n\n", buf_ptr(type_h_name(type_entry)));
9924 }9818 }
9925 break;9819 break;
9926 case ZigTypeIdOpaque:9820 case ZigTypeIdOpaque:
9927 fprintf(out_h, "struct %s;\n\n", buf_ptr(type_h_name(type_entry)));9821 buf_appendf(out_buf, "struct %s;\n\n", buf_ptr(type_h_name(type_entry)));
9928 break;9822 break;
9929 }9823 }
9930 }9824 }
9825}
9826
9827static void gen_h_file_functions(CodeGen* g, GenH* gen_h, Buf* out_buf, Buf* export_macro) {
9828 for (size_t fn_def_i = 0; fn_def_i < g->fn_defs.length; fn_def_i += 1) {
9829 ZigFn *fn_table_entry = g->fn_defs.at(fn_def_i);
9830
9831 if (fn_table_entry->export_list.length == 0)
9832 continue;
9833
9834 FnTypeId *fn_type_id = &fn_table_entry->type_entry->data.fn.fn_type_id;
9835
9836 Buf return_type_c = BUF_INIT;
9837 get_c_type(g, gen_h, fn_type_id->return_type, &return_type_c);
9838
9839 Buf *symbol_name;
9840 if (fn_table_entry->export_list.length == 0) {
9841 symbol_name = &fn_table_entry->symbol_name;
9842 } else {
9843 GlobalExport *fn_export = &fn_table_entry->export_list.items[0];
9844 symbol_name = &fn_export->name;
9845 }
9846
9847 if (export_macro != nullptr) {
9848 buf_appendf(out_buf, "%s %s %s(",
9849 buf_ptr(export_macro),
9850 buf_ptr(&return_type_c),
9851 buf_ptr(symbol_name));
9852 } else {
9853 buf_appendf(out_buf, "%s %s(",
9854 buf_ptr(&return_type_c),
9855 buf_ptr(symbol_name));
9856 }
9857
9858 Buf param_type_c = BUF_INIT;
9859 if (fn_type_id->param_count > 0) {
9860 for (size_t param_i = 0; param_i < fn_type_id->param_count; param_i += 1) {
9861 FnTypeParamInfo *param_info = &fn_type_id->param_info[param_i];
9862 AstNode *param_decl_node = get_param_decl_node(fn_table_entry, param_i);
9863 Buf *param_name = param_decl_node->data.param_decl.name;
9864
9865 const char *comma_str = (param_i == 0) ? "" : ", ";
9866 const char *restrict_str = param_info->is_noalias ? "restrict" : "";
9867 get_c_type(g, gen_h, param_info->type, &param_type_c);
9868
9869 if (param_info->type->id == ZigTypeIdArray) {
9870 // Arrays decay to pointers
9871 buf_appendf(out_buf, "%s%s%s %s[]", comma_str, buf_ptr(&param_type_c),
9872 restrict_str, buf_ptr(param_name));
9873 } else {
9874 buf_appendf(out_buf, "%s%s%s %s", comma_str, buf_ptr(&param_type_c),
9875 restrict_str, buf_ptr(param_name));
9876 }
9877 }
9878 buf_appendf(out_buf, ")");
9879 } else {
9880 buf_appendf(out_buf, "void)");
9881 }
9882
9883 buf_appendf(out_buf, ";\n");
9884 }
9885}
9886
9887static void gen_h_file(CodeGen *g) {
9888 GenH gen_h_data = {0};
9889 GenH *gen_h = &gen_h_data;
9890
9891 assert(!g->is_test_build);
9892 assert(!g->disable_gen_h);
9893
9894 Buf *out_h_path = buf_sprintf("%s" OS_SEP "%s.h", buf_ptr(g->output_dir), buf_ptr(g->root_out_name));
9895
9896 FILE *out_h = fopen(buf_ptr(out_h_path), "wb");
9897 if (!out_h)
9898 zig_panic("unable to open %s: %s\n", buf_ptr(out_h_path), strerror(errno));
9899
9900 Buf *export_macro = nullptr;
9901 if (g->is_dynamic) {
9902 export_macro = preprocessor_mangle(buf_sprintf("%s_EXPORT", buf_ptr(g->root_out_name)));
9903 buf_upcase(export_macro);
9904 }
9905
9906 Buf fns_buf = BUF_INIT;
9907 buf_resize(&fns_buf, 0);
9908 gen_h_file_functions(g, gen_h, &fns_buf, export_macro);
9909
9910 Buf types_buf = BUF_INIT;
9911 buf_resize(&types_buf, 0);
9912 gen_h_file_types(g, gen_h, &types_buf);
9913 Buf *ifdef_dance_name = preprocessor_mangle(buf_sprintf("%s_H", buf_ptr(g->root_out_name)));
9914 buf_upcase(ifdef_dance_name);
9915
9916 fprintf(out_h, "#ifndef %s\n", buf_ptr(ifdef_dance_name));
9917 fprintf(out_h, "#define %s\n\n", buf_ptr(ifdef_dance_name));
9918
9919 if (g->c_want_stdbool)
9920 fprintf(out_h, "#include <stdbool.h>\n");
9921 if (g->c_want_stdint)
9922 fprintf(out_h, "#include <stdint.h>\n");
9923
9924 fprintf(out_h, "\n");
9925
9926 if (g->is_dynamic) {
9927 fprintf(out_h, "#if defined(_WIN32)\n");
9928 fprintf(out_h, "#define %s __declspec(dllimport)\n", buf_ptr(export_macro));
9929 fprintf(out_h, "#else\n");
9930 fprintf(out_h, "#define %s __attribute__((visibility (\"default\")))\n",
9931 buf_ptr(export_macro));
9932 fprintf(out_h, "#endif\n");
9933 fprintf(out_h, "\n");
9934 }
9935
9936 fprintf(out_h, "%s", buf_ptr(&types_buf));
9937
9938 fprintf(out_h, "#ifdef __cplusplus\n");
9939 fprintf(out_h, "extern \"C\" {\n");
9940 fprintf(out_h, "#endif\n");
9941 fprintf(out_h, "\n");
9942
9943 fprintf(out_h, "%s\n", buf_ptr(&fns_buf));
9944
9945 fprintf(out_h, "#ifdef __cplusplus\n");
9946 fprintf(out_h, "} // extern \"C\"\n");
9947 fprintf(out_h, "#endif\n\n");
99319948
9932 fprintf(out_h, "%s", buf_ptr(&h_buf));9949 fprintf(out_h, "%s\n", buf_ptr(&vars_buf));
99339950
9934 fprintf(out_h, "\n#endif\n");9951 fprintf(out_h, "#endif // %s\n", buf_ptr(ifdef_dance_name));
99359952
9936 if (fclose(out_h))9953 if (fclose(out_h))
9937 zig_panic("unable to close h file: %s", strerror(errno));9954 zig_panic("unable to close h file: %s", strerror(errno));
test/gen_h.zig+16-14
...@@ -10,9 +10,8 @@ pub fn addCases(cases: *tests.GenHContext) void {...@@ -10,9 +10,8 @@ pub fn addCases(cases: *tests.GenHContext) void {
10 \\ B = 1,10 \\ B = 1,
11 \\ C = 211 \\ C = 2
12 \\};12 \\};
13 \\13 ,
14 \\TEST_EXTERN_C void entry(enum Foo foo);14 \\void entry(enum Foo foo);
15 \\
16 );15 );
1716
18 cases.add("declare struct",17 cases.add("declare struct",
...@@ -34,8 +33,8 @@ pub fn addCases(cases: *tests.GenHContext) void {...@@ -34,8 +33,8 @@ pub fn addCases(cases: *tests.GenHContext) void {
34 \\ uint64_t E;33 \\ uint64_t E;
35 \\ uint64_t F;34 \\ uint64_t F;
36 \\};35 \\};
37 \\36 ,
38 \\TEST_EXTERN_C void entry(struct Foo foo);37 \\void entry(struct Foo foo);
39 \\38 \\
40 );39 );
4140
...@@ -69,8 +68,8 @@ pub fn addCases(cases: *tests.GenHContext) void {...@@ -69,8 +68,8 @@ pub fn addCases(cases: *tests.GenHContext) void {
69 \\ bool C;68 \\ bool C;
70 \\ struct Big D;69 \\ struct Big D;
71 \\};70 \\};
72 \\71 ,
73 \\TEST_EXTERN_C void entry(union Foo foo);72 \\void entry(union Foo foo);
74 \\73 \\
75 );74 );
7675
...@@ -80,8 +79,8 @@ pub fn addCases(cases: *tests.GenHContext) void {...@@ -80,8 +79,8 @@ pub fn addCases(cases: *tests.GenHContext) void {
80 \\export fn entry(foo: ?*Foo) void { }79 \\export fn entry(foo: ?*Foo) void { }
81 ,80 ,
82 \\struct Foo;81 \\struct Foo;
83 \\82 ,
84 \\TEST_EXTERN_C void entry(struct Foo * foo);83 \\void entry(struct Foo * foo);
85 );84 );
8685
87 cases.add("array field-type",86 cases.add("array field-type",
...@@ -95,8 +94,8 @@ pub fn addCases(cases: *tests.GenHContext) void {...@@ -95,8 +94,8 @@ pub fn addCases(cases: *tests.GenHContext) void {
95 \\ int32_t A[2];94 \\ int32_t A[2];
96 \\ uint32_t * B[4];95 \\ uint32_t * B[4];
97 \\};96 \\};
98 \\97 ,
99 \\TEST_EXTERN_C void entry(struct Foo foo, uint8_t bar[]);98 \\void entry(struct Foo foo, uint8_t bar[]);
100 \\99 \\
101 );100 );
102101
...@@ -110,7 +109,8 @@ pub fn addCases(cases: *tests.GenHContext) void {...@@ -110,7 +109,8 @@ pub fn addCases(cases: *tests.GenHContext) void {
110 \\}109 \\}
111 ,110 ,
112 \\struct S;111 \\struct S;
113 \\TEST_EXTERN_C uint8_t a(struct S * s);112 ,
113 \\uint8_t a(struct S * s);
114 \\114 \\
115 );115 );
116116
...@@ -125,7 +125,8 @@ pub fn addCases(cases: *tests.GenHContext) void {...@@ -125,7 +125,8 @@ pub fn addCases(cases: *tests.GenHContext) void {
125 \\}125 \\}
126 ,126 ,
127 \\union U;127 \\union U;
128 \\TEST_EXTERN_C uint8_t a(union U * s);128 ,
129 \\uint8_t a(union U * s);
129 \\130 \\
130 );131 );
131132
...@@ -140,7 +141,8 @@ pub fn addCases(cases: *tests.GenHContext) void {...@@ -140,7 +141,8 @@ pub fn addCases(cases: *tests.GenHContext) void {
140 \\}141 \\}
141 ,142 ,
142 \\enum E;143 \\enum E;
143 \\TEST_EXTERN_C uint8_t a(enum E * s);144 ,
145 \\uint8_t a(enum E * s);
144 \\146 \\
145 );147 );
146}148}