| ... | ... | @@ -9732,113 +9732,7 @@ static Buf *preprocessor_mangle(Buf *src) { |
| 9732 | 9732 | return result; |
| 9733 | 9733 | } |
| 9734 | 9734 | |
| 9735 | | static void gen_h_file(CodeGen *g) { |
| 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 | | |
| 9735 | static void gen_h_file_types(CodeGen* g, GenH* gen_h, Buf* out_buf) { |
| 9842 | 9736 | for (size_t type_i = 0; type_i < gen_h->types_to_declare.length; type_i += 1) { |
| 9843 | 9737 | ZigType *type_entry = gen_h->types_to_declare.at(type_i); |
| 9844 | 9738 | switch (type_entry->id) { |
| ... | ... | @@ -9869,25 +9763,25 @@ static void gen_h_file(CodeGen *g) { |
| 9869 | 9763 | |
| 9870 | 9764 | case ZigTypeIdEnum: |
| 9871 | 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 | 9767 | for (uint32_t field_i = 0; field_i < type_entry->data.enumeration.src_field_count; field_i += 1) { |
| 9874 | 9768 | TypeEnumField *enum_field = &type_entry->data.enumeration.fields[field_i]; |
| 9875 | 9769 | Buf *value_buf = buf_alloc(); |
| 9876 | 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 | 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 | 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 | 9781 | break; |
| 9888 | 9782 | case ZigTypeIdStruct: |
| 9889 | 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 | 9785 | for (uint32_t field_i = 0; field_i < type_entry->data.structure.src_field_count; field_i += 1) { |
| 9892 | 9786 | TypeStructField *struct_field = type_entry->data.structure.fields[field_i]; |
| 9893 | 9787 | |
| ... | ... | @@ -9895,43 +9789,166 @@ static void gen_h_file(CodeGen *g) { |
| 9895 | 9789 | get_c_type(g, gen_h, struct_field->type_entry, type_name_buf); |
| 9896 | 9790 | |
| 9897 | 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 | 9793 | buf_ptr(struct_field->name), |
| 9900 | 9794 | struct_field->type_entry->data.array.len); |
| 9901 | 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 | } |
| 9904 | 9798 | |
| 9905 | 9799 | } |
| 9906 | | fprintf(out_h, "};\n\n"); |
| 9800 | buf_appendf(out_buf, "};\n\n"); |
| 9907 | 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 | 9804 | break; |
| 9911 | 9805 | case ZigTypeIdUnion: |
| 9912 | 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 | 9808 | for (uint32_t field_i = 0; field_i < type_entry->data.unionation.src_field_count; field_i += 1) { |
| 9915 | 9809 | TypeUnionField *union_field = &type_entry->data.unionation.fields[field_i]; |
| 9916 | 9810 | |
| 9917 | 9811 | Buf *type_name_buf = buf_alloc(); |
| 9918 | 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 | 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 | 9819 | break; |
| 9926 | 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 | 9822 | break; |
| 9929 | 9823 | } |
| 9930 | 9824 | } |
| 9825 | } |
| 9826 | |
| 9827 | static 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 | |
| 9887 | static 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"); |
| 9931 | 9948 | |
| 9932 | | fprintf(out_h, "%s", buf_ptr(&h_buf)); |
| 9949 | fprintf(out_h, "%s\n", buf_ptr(&vars_buf)); |
| 9933 | 9950 | |
| 9934 | | fprintf(out_h, "\n#endif\n"); |
| 9951 | fprintf(out_h, "#endif // %s\n", buf_ptr(ifdef_dance_name)); |
| 9935 | 9952 | |
| 9936 | 9953 | if (fclose(out_h)) |
| 9937 | 9954 | zig_panic("unable to close h file: %s", strerror(errno)); |