From 4cff80ecea3dbe2929137f4dca0e081bb86be226 Mon Sep 17 00:00:00 2001 From: Christoffer Lerno Date: Mon, 24 Jun 2024 15:04:44 +0200 Subject: [PATCH] Header exports implicit. --- src/compiler/headers.c | 73 ++++++++++++++------------------ src/compiler/sema_decls.c | 88 +++++++++++++++++++++++++++++++++------ src/compiler/types.c | 14 ++----- 3 files changed, 109 insertions(+), 66 deletions(-) diff --git a/src/compiler/headers.c b/src/compiler/headers.c index 660e7c783..f27e8f4f0 100644 --- a/src/compiler/headers.c +++ b/src/compiler/headers.c @@ -440,35 +440,34 @@ RETRY: case TYPE_INTERFACE: return; case TYPE_DISTINCT: - if (type->decl->is_export) - { - if (htable_get(table, type)) return; - Type *underlying_type = type->decl->distinct->type; - header_gen_maybe_generate_type(file, table, underlying_type); - PRINTF("typedef "); - header_print_type(file, underlying_type); - PRINTF(" %s;\n", decl_get_extname(type->decl)); - return; - } - type = type_flatten(type); - goto RETRY; + { + assert(type->decl->is_export); + if (htable_get(table, type)) return; + Type *underlying_type = type->decl->distinct->type; + htable_set(table, type, type); + header_gen_maybe_generate_type(file, table, underlying_type); + PRINTF("typedef "); + header_print_type(file, underlying_type); + PRINTF(" %s;\n", decl_get_extname(type->decl)); + return; + } case TYPE_TYPEDEF: - if (type->decl->is_export) - { - if (htable_get(table, type)) return; - Type *underlying_type = type->canonical; - header_gen_maybe_generate_type(file, table, underlying_type); - PRINTF("typedef "); - header_print_type(file, underlying_type); - PRINTF(" %s;\n", decl_get_extname(type->decl)); - return; - } - type = type->canonical; - goto RETRY; + { + assert(type->decl->is_export); + if (htable_get(table, type)) return; + htable_set(table, type, type); + Type *underlying_type = type->canonical; + header_gen_maybe_generate_type(file, table, underlying_type); + PRINTF("typedef "); + header_print_type(file, underlying_type); + PRINTF(" %s;\n", decl_get_extname(type->decl)); + return; + } case TYPE_BITSTRUCT: - if (type->decl->is_export) { + assert(type->decl->is_export); if (htable_get(table, type)) return; + htable_set(table, type, type); Type *underlying_type = type->decl->bitstruct.base_type->type; header_gen_maybe_generate_type(file, table, underlying_type); PRINTF("typedef "); @@ -476,8 +475,6 @@ RETRY: PRINTF(" %s;\n", decl_get_extname(type->decl)); return; } - type = type_flatten(type); - goto RETRY; case TYPE_POINTER: case TYPE_FUNC_PTR: type = type->pointer; @@ -485,6 +482,7 @@ RETRY: case TYPE_ENUM: if (htable_get(table, type)) return; { + assert(type->decl->is_export); Decl *decl = type->decl; htable_set(table, type, type); Type *underlying_type = decl->enums.type_info->type->canonical; @@ -513,6 +511,7 @@ RETRY: case TYPE_UNION: if (htable_get(table, type)) return; { + assert(type->decl->is_export); Decl *decl = type->decl; PRINTF("typedef %s %s__ %s;\n", struct_union_str(decl), decl_get_extname(decl), decl_get_extname(decl)); htable_set(table, type, type); @@ -526,31 +525,21 @@ RETRY: case TYPE_ARRAY: type = type->array.base; goto RETRY; - if (htable_get(table, type)) return; - { - Decl *decl = type->decl; - PRINTF("typedef struct %s__slice__ %s;\n", decl_get_extname(decl), decl_get_extname(decl)); - htable_set(table, type, type); - header_ensure_member_types_exist(file, table, decl->strukt.members); - PRINTF("%s %s__\n", struct_union_str(decl), decl->extname); - PRINTF("{\n"); - header_gen_members(file, 1, decl->strukt.members); - PRINTF("};\n"); - return; - } - break; case TYPE_FLEXIBLE_ARRAY: type = type->array.base; goto RETRY; case TYPE_VECTOR: + { if (htable_get(table, type)) return; PRINTF("typedef "); - header_print_type(file, type->array.base); + Type *flat_type = type_flatten(type->array.base); + header_print_type(file, flat_type); htable_set(table, type, type); PRINTF(" "); header_print_type(file, type); - PRINTF(" __attribute__((vector_size(%d)));\n", (int)type_size(type->array.base) * type->array.len); + PRINTF(" __attribute__((vector_size(%d)));\n", (int)type_size(flat_type) * type->array.len); return; + } } } diff --git a/src/compiler/sema_decls.c b/src/compiler/sema_decls.c index 4906e511b..2ab6b33b2 100644 --- a/src/compiler/sema_decls.c +++ b/src/compiler/sema_decls.c @@ -27,8 +27,8 @@ static inline Decl *operator_in_module(SemaContext *c, Module *module, OperatorO static inline bool sema_analyse_operator_element_at(SemaContext *context, Decl *method); static inline bool sema_analyse_operator_element_set(SemaContext *context, Decl *method); static inline bool sema_analyse_operator_len(Decl *method, SemaContext *context); -static bool sema_require_export_type(SemaContext *context, TypeInfo *type_info); static bool sema_check_operator_method_validity(SemaContext *context, Decl *method); +static void sema_recursively_import(Type *type); static inline const char *method_name_by_decl(Decl *method_like); static bool sema_analyse_struct_union(SemaContext *context, Decl *decl, bool *erase_decl); @@ -242,8 +242,8 @@ static inline bool sema_analyse_struct_member(SemaContext *context, Decl *parent assert(type_infoptrzero(decl->var.type_info)); TypeInfo *type_info = type_infoptr(decl->var.type_info); if (!sema_resolve_type_info(context, type_info, RESOLVE_TYPE_ALLOW_FLEXIBLE)) return decl_poison(decl); - if (is_export && !sema_require_export_type(context, type_info)) return decl_poison(decl); Type *type = type_info->type; + if (is_export) sema_recursively_import(type); switch (type_storage_type(type)) { case STORAGE_NORMAL: @@ -949,14 +949,70 @@ ERROR: return decl_poison(decl); } -static bool sema_require_export_type(SemaContext *context, TypeInfo *type_info) +static void sema_recursively_import(Type *type) { - Decl *decl = type_no_export(type_info->type); - if (!decl) return true; - SEMA_ERROR(type_info, "%s must also be an exported type, to make this work '%s' needs to be marked '@export'", - type_quoted_error_string(type_info->type), decl->name); - SEMA_NOTE(decl, "The definition is here."); - return false; + if (!type) return; + Decl *decl = type_no_export(type); + printf("Recursively import %s %p.\n", type->name, decl); + if (!decl) return; + decl->is_export = true; + printf("Recursively import %s.\n", type->name); + if (decl->resolve_status != RESOLVE_DONE) return; + decl->extname = NULL; + assert(!decl->has_extname); + decl_set_external_name(decl); + switch (decl->decl_kind) + { + case DECL_POISONED: + case DECL_ATTRIBUTE: + case DECL_BODYPARAM: + case DECL_CT_ASSERT: + case DECL_CT_ECHO: + case DECL_CT_EXEC: + case DECL_CT_INCLUDE: + case DECL_DECLARRAY: + case DECL_DEFINE: + case DECL_ENUM_CONSTANT: + case DECL_ERASED: + case DECL_FAULTVALUE: + case DECL_FUNC: + case DECL_GLOBALS: + case DECL_IMPORT: + case DECL_LABEL: + case DECL_MACRO: + case DECL_INTERFACE: + case DECL_VAR: + UNREACHABLE + case DECL_BITSTRUCT: + sema_recursively_import(decl->bitstruct.base_type->type); + return; + case DECL_DISTINCT: + sema_recursively_import(decl->distinct->type); + return; + case DECL_ENUM: + sema_recursively_import(decl->enums.type_info->type); + FOREACH_BEGIN(Decl *param, decl->enums.parameters) + sema_recursively_import(param->type); + FOREACH_END(); + case DECL_TYPEDEF: + sema_recursively_import(type->canonical); + return; + case DECL_FAULT: + return; + case DECL_FNTYPE: + sema_recursively_import(type_infoptr(decl->fntype_decl.rtype)->type); + FOREACH_BEGIN(Decl *param, decl->fntype_decl.params) + sema_recursively_import(param->type); + FOREACH_END(); + return; + case DECL_STRUCT: + case DECL_UNION: + FOREACH_BEGIN(Decl *param, decl->strukt.members) + sema_recursively_import(param->type); + FOREACH_END(); + return; + } + UNREACHABLE } static inline bool sema_analyse_signature(SemaContext *context, Signature *sig, TypeInfoId type_parent, bool is_export) @@ -977,7 +1033,7 @@ static inline bool sema_analyse_signature(SemaContext *context, Signature *sig, is_macro ? RESOLVE_TYPE_ALLOW_INFER : RESOLVE_TYPE_DEFAULT)) return false; rtype = rtype_info->type; - if (is_export && !sema_require_export_type(context, rtype_info)) return false; + if (is_export) sema_recursively_import(rtype); if (sig->attrs.nodiscard) { if (type_is_void(rtype)) @@ -1014,7 +1070,7 @@ static inline bool sema_analyse_signature(SemaContext *context, Signature *sig, if (!sema_resolve_type_info(context, method_parent, is_macro ? RESOLVE_TYPE_MACRO_METHOD : RESOLVE_TYPE_FUNC_METHOD)) return false; } - if (is_export && method_parent && !sema_require_export_type(context, method_parent)) return false; + if (is_export && method_parent) sema_recursively_import(method_parent->type); // Fill in the type if the first parameter is lacking a type. if (method_parent && params && params[0] && !params[0]->var.type_info) @@ -1087,7 +1143,7 @@ static inline bool sema_analyse_signature(SemaContext *context, Signature *sig, if (!sema_resolve_type_info(context, type_info, is_macro ? RESOLVE_TYPE_ALLOW_INFER : RESOLVE_TYPE_DEFAULT)) return decl_poison(param); - if (is_export && !sema_require_export_type(context, type_info)) return false; + if (is_export) sema_recursively_import(type_info->type); param->type = type_info->type; } switch (var_kind) @@ -1245,10 +1301,12 @@ static inline bool sema_analyse_typedef(SemaContext *context, Decl *decl, bool * if (!sema_analyse_attributes(context, decl, decl->attributes, ATTR_DEF, erase_decl)) return decl_poison(decl); if (*erase_decl) return true; - if (decl->is_export) decl_set_external_name(decl); + bool is_export = decl->is_export; + if (is_export) decl_set_external_name(decl); if (decl->typedef_decl.is_func) { Decl *fn_decl = decl->typedef_decl.decl; + fn_decl->is_export = is_export; fn_decl->unit = decl->unit; fn_decl->type = type_new_func(fn_decl, &fn_decl->fntype_decl); decl->type->canonical = type_get_func_ptr(fn_decl->type); @@ -1256,6 +1314,7 @@ static inline bool sema_analyse_typedef(SemaContext *context, Decl *decl, bool * } TypeInfo *info = decl->typedef_decl.type_info; if (!sema_resolve_type_info(context, info, RESOLVE_TYPE_DEFAULT)) return false; + if (is_export) sema_recursively_import(info->type); decl->type->canonical = info->type->canonical; // Do we need anything else? return true; @@ -1279,6 +1338,8 @@ static inline bool sema_analyse_distinct(SemaContext *context, Decl *decl, bool // Optional isn't allowed of course. if (type_is_optional(info->type)) RETURN_SEMA_ERROR(decl, "You cannot create a distinct type from an optional."); + if (decl->is_export) sema_recursively_import(info->type); + // Distinct types drop the canonical part. info->type = info->type->canonical; return true; @@ -1353,6 +1414,7 @@ static inline bool sema_analyse_enum(SemaContext *context, Decl *decl, bool *era break; } if (!sema_analyse_enum_param(context, value)) goto ERR; + value->resolve_status = RESOLVE_DONE; } sema_decl_stack_restore(state); diff --git a/src/compiler/types.c b/src/compiler/types.c index 0a25060ca..ed47c0932 100644 --- a/src/compiler/types.c +++ b/src/compiler/types.c @@ -386,7 +386,6 @@ bool type_flat_is_boolintlike(Type *type) Decl *type_no_export(Type *type) { - type = type->canonical; RETRY: switch (type->type_kind) { @@ -416,10 +415,12 @@ Decl *type_no_export(Type *type) case TYPE_STRUCT: case TYPE_UNION: case TYPE_FAULTTYPE: + case TYPE_DISTINCT: + case TYPE_BITSTRUCT: + case TYPE_TYPEDEF: if (type->decl->is_export) return NULL; return type->decl; case TYPE_SLICE: - case TYPE_TYPEDEF: case TYPE_ARRAY: case TYPE_FLEXIBLE_ARRAY: case TYPE_INFERRED_ARRAY: @@ -428,15 +429,6 @@ Decl *type_no_export(Type *type) case TYPE_VECTOR: case TYPE_INFERRED_VECTOR: return NULL; - case TYPE_BITSTRUCT: - // Can be folded into its primitive version. - return NULL; - case TYPE_DISTINCT: - // Is it exported, then we're fine. - if (type->decl->is_export) return NULL; - // Otherwise the underlying type needs to be exported. - type = type->decl->distinct->type->canonical; - goto RETRY; case TYPE_OPTIONAL: type = type->optional; goto RETRY;