Further header updates.

This commit is contained in:
Christoffer Lerno
2024-06-24 11:34:23 +02:00
parent 0b971c2bd0
commit 616bde2c4d
5 changed files with 213 additions and 80 deletions

View File

@@ -3035,6 +3035,29 @@ static inline Type *type_flatten(Type *type)
}
}
static inline Type *type_flatten_no_export(Type *type)
{
while (1)
{
switch (type->type_kind)
{
case TYPE_TYPEDEF:
if (type->decl->is_export) return type;
type = type->canonical;
break;
case TYPE_DISTINCT:
if (type->decl->is_export) return type;
type = type->decl->distinct->type;
break;
case TYPE_OPTIONAL:
type = type->optional;
break;
default:
return type;
}
}
}
static inline bool type_flat_is_char_array(Type *type)
{
type = type_flatten(type);

View File

@@ -41,7 +41,7 @@ static void header_print_type(FILE *file, Type *type)
return;
}
assert(!type_is_optional(type));
type = type_flatten(type);
type = type_flatten_no_export(type);
switch (type->type_kind)
{
case CT_TYPES:
@@ -117,6 +117,11 @@ static void header_print_type(FILE *file, Type *type)
PRINTF("%s", decl_get_extname(type->decl));
return;
case TYPE_BITSTRUCT:
if (type->decl->is_export)
{
PRINTF("%s", decl_get_extname(type->decl));
return;
}
header_print_type(file, type->decl->bitstruct.base_type->type);
return;
case TYPE_ANYFAULT:
@@ -124,7 +129,21 @@ static void header_print_type(FILE *file, Type *type)
PRINTF("c3fault_t");
return;
case TYPE_DISTINCT:
if (type->decl->is_export)
{
PRINTF("%s", decl_get_extname(type->decl));
return;
}
header_print_type(file, type->decl->distinct->type);
return;
case TYPE_TYPEDEF:
if (type->decl->is_export)
{
PRINTF("%s", decl_get_extname(type->decl));
return;
}
header_print_type(file, type->canonical);
return;
case TYPE_FLEXIBLE_ARRAY:
UNREACHABLE
case TYPE_ARRAY:
@@ -140,7 +159,7 @@ static void header_print_type(FILE *file, Type *type)
PRINTF("c3slice_t");
return;
case TYPE_VECTOR:
switch (type->array.base->type_kind)
switch (type_flatten(type->array.base)->type_kind)
{
case ALL_SIGNED_INTS:
PRINTF("int");
@@ -197,40 +216,61 @@ static void header_gen_function_ptr(FILE *file, HTable *table, Type *type)
PRINTF(");\n");
}
static void header_gen_function(FILE *file, FILE *file_types, HTable *table, Decl *decl)
static void header_gen_function(FILE *file, HTable *table, Decl *decl, bool print_fn, bool* fn_found)
{
if (!decl->is_export) return;
if (decl->name[0] == '_' && decl->name[1] == '_') return;
if (decl->extname[0] == '_' && decl->extname[1] == '_') return;
if (print_fn && !*fn_found)
{
*fn_found = true;
if (decl->func_decl.type_parent)
{
PRINTF("\n/* METHODS */\n");
}
else
{
PRINTF("\n/* FUNCTIONS */\n");
}
}
Signature *sig = &decl->func_decl.signature;
PRINTF("extern ");
Type *rtype = typeget(sig->rtype);
Type *extra_ret = NULL;
if (type_is_optional(rtype))
{
extra_ret = rtype->optional;
header_gen_maybe_generate_type(file_types, table, extra_ret);
if (!print_fn) header_gen_maybe_generate_type(file, table, extra_ret);
rtype = type_anyfault;
}
header_gen_maybe_generate_type(file_types, table, rtype);
header_print_type(file, rtype);
PRINTF(" %s(", decl_get_extname(decl));
if (!vec_size(sig->params) && !extra_ret)
if (!print_fn) header_gen_maybe_generate_type(file, table, rtype);
if (print_fn)
{
PRINTF("void);\n");
return;
}
if (extra_ret)
{
header_print_type(file, type_get_ptr(extra_ret));
PRINTF(" return_ref");
PRINTF("extern ");
header_print_type(file, rtype);
PRINTF(" %s(", decl_get_extname(decl));
if (!vec_size(sig->params) && !extra_ret)
{
PRINTF("void);\n");
return;
}
if (extra_ret)
{
header_print_type(file, type_get_ptr(extra_ret));
PRINTF(" return_ref");
}
}
FOREACH_BEGIN_IDX(i, Decl *param, sig->params)
if (i || extra_ret) PRINTF(", ");
header_print_type(file, param->type);
header_gen_maybe_generate_type(file_types, table, param->type);
if (param->name) PRINTF(" %s", param->name);
if (print_fn)
{
if (i || extra_ret) PRINTF(", ");
header_print_type(file, param->type);
if (param->name) PRINTF(" %s", param->name);
}
else
{
header_gen_maybe_generate_type(file, table, param->type);
}
FOREACH_END();
PRINTF(");\n");
if (print_fn) PRINTF(");\n");
}
static void header_gen_members(FILE *file, int indent, Decl **members)
@@ -238,7 +278,7 @@ static void header_gen_members(FILE *file, int indent, Decl **members)
VECEACH(members, i)
{
Decl *member = members[i];
Type *type = type_flatten(member->type);
Type *type = type_flatten_no_export(member->type);
switch (member->decl_kind)
{
case DECL_VAR:
@@ -377,10 +417,8 @@ static void header_gen_maybe_generate_type(FILE *file, HTable *table, Type *type
}
RETRY:
if (type_is_optional(type)) return;
type = type_flatten(type);
switch (type->type_kind)
{
case FLATTENED_TYPES:
case TYPE_POISONED:
case TYPE_INFERRED_ARRAY:
case TYPE_UNTYPED_LIST:
@@ -388,6 +426,7 @@ RETRY:
case TYPE_MEMBER:
case TYPE_INFERRED_VECTOR:
case TYPE_WILDCARD:
case TYPE_OPTIONAL:
UNREACHABLE
case TYPE_VOID:
case TYPE_BOOL:
@@ -395,12 +434,50 @@ RETRY:
case ALL_INTS:
case TYPE_ANYFAULT:
case TYPE_TYPEID:
case TYPE_BITSTRUCT:
case TYPE_FAULTTYPE:
case TYPE_SLICE:
case TYPE_ANY:
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;
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;
case TYPE_BITSTRUCT:
if (type->decl->is_export)
{
if (htable_get(table, type)) return;
Type *underlying_type = type->decl->bitstruct.base_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;
}
type = type_flatten(type);
goto RETRY;
case TYPE_POINTER:
case TYPE_FUNC_PTR:
type = type->pointer;
@@ -469,6 +546,7 @@ RETRY:
if (htable_get(table, type)) return;
PRINTF("typedef ");
header_print_type(file, type->array.base);
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);
@@ -476,7 +554,7 @@ RETRY:
}
}
static void header_gen_global_var(FILE *file, FILE *file_type, HTable *table, Decl *decl)
static void header_gen_global_var(FILE *file, HTable *table, Decl *decl, bool fn_globals, bool *globals_found)
{
assert(decl->decl_kind == DECL_VAR);
// Only exports.
@@ -484,7 +562,19 @@ static void header_gen_global_var(FILE *file, FILE *file_type, HTable *table, De
Type *type = decl->type->canonical;
// Optionals are ignored.
if (type_is_optional(type)) return;
type = type_flatten(type);
type = type_flatten_no_export(type);
if (fn_globals && !*globals_found)
{
*globals_found = true;
if (decl->var.kind == VARDECL_CONST)
{
PRINTF("\n/* CONSTANTS */\n");
}
else
{
PRINTF("\n/* GLOBALS */\n");
}
}
// Flatten bitstructs.
if (type->type_kind == TYPE_BITSTRUCT) type = type->decl->bitstruct.base_type->type->canonical;
// We will lower some consts to defines, if they are:
@@ -493,8 +583,10 @@ static void header_gen_global_var(FILE *file, FILE *file_type, HTable *table, De
// 3. Has an init method
if (decl->var.kind == VARDECL_CONST && !decl->var.is_addr)
{
if (!fn_globals) return;
Expr *init = decl->var.init_expr;
if (type_is_arraylike(type) || type_is_user_defined(type) || !init) return;
Type *flat = type_flatten(type);
if (type_is_arraylike(flat) || type_is_user_defined(flat) || !init) return;
PRINTF("#define %s ", decl_get_extname(decl));
assert(expr_is_const(init));
switch (init->const_expr.const_kind)
@@ -542,49 +634,21 @@ static void header_gen_global_var(FILE *file, FILE *file_type, HTable *table, De
UNREACHABLE
}
}
if (!fn_globals)
{
header_gen_maybe_generate_type(file, table, decl->type);
return;
}
header_print_type(file, decl->type);
assert(decl->var.kind == VARDECL_GLOBAL || decl->var.kind == VARDECL_CONST);
PRINTF("extern ");
if (decl->var.kind == VARDECL_CONST) PRINTF("const ");
header_gen_maybe_generate_type(file_type, table, decl->type);
header_print_type(file, decl->type);
PRINTF(" %s;\n", decl_get_extname(decl));
}
void header_gen(Module **modules, unsigned module_count)
static void header_gen_global_decls(FILE *file, HTable *table, Module **modules, unsigned module_count, bool fn_globals)
{
HTable table;
htable_init(&table, 1024);
const char *name = build_base_name();
const char *filename = str_printf("%s_fn.h", name);
const char *filename_types = str_printf("%s_types.h", name);
FILE *file = fopen(filename, "w");
FILE *file_types = fopen(filename_types, "w");
OUT(file_types, "#include <stdint.h>\n");
OUT(file_types, "#include <stddef.h>\n");
OUT(file_types, "#include <stdbool.h>\n");
OUT(file_types, "#ifndef __c3__\n");
OUT(file_types, "#define __c3__\n\n");
OUT(file_types, "typedef void* c3typeid_t;\n");
OUT(file_types, "typedef void* c3fault_t;\n");
OUT(file_types, "typedef struct { void* ptr; size_t len; } c3slice_t;\n");
OUT(file_types, "typedef struct { void* ptr; c3typeid_t type; } c3any_t;\n");
OUT(file_types, "\n#endif\n\n");
PRINTF("#include \"%s_types.h\"\n", name);
for (unsigned i = 0; i < module_count; i++)
{
Module *module = modules[i];
// Produce all constants.
FOREACH_BEGIN(CompilationUnit *unit, module->units)
FOREACH_BEGIN(Decl *var, unit->enums)
if (!var->is_export) continue;
header_gen_maybe_generate_type(file_types, &table, var->type);
FOREACH_END();
FOREACH_END();
}
PRINTF("/* Constants */\n");
bool constants_found = false;
for (unsigned i = 0; i < module_count; i++)
{
Module *module = modules[i];
@@ -592,12 +656,12 @@ void header_gen(Module **modules, unsigned module_count)
FOREACH_BEGIN(CompilationUnit *unit, module->units)
FOREACH_BEGIN(Decl *var, unit->vars)
if (var->var.kind != VARDECL_CONST) continue;
header_gen_global_var(file, file_types, &table, var);
header_gen_global_var(file, table, var, fn_globals, &constants_found);
FOREACH_END();
FOREACH_END();
}
PRINTF("\n/* Globals */\n");
bool globals_found = false;
for (unsigned i = 0; i < module_count; i++)
{
Module *module = modules[i];
@@ -606,12 +670,12 @@ void header_gen(Module **modules, unsigned module_count)
FOREACH_BEGIN(CompilationUnit *unit, module->units)
FOREACH_BEGIN(Decl *var, unit->vars)
if (var->var.kind != VARDECL_GLOBAL) continue;
header_gen_global_var(file, file_types, &table, var);
header_gen_global_var(file, table, var, fn_globals, &globals_found);
FOREACH_END();
FOREACH_END();
}
PRINTF("\n/* Functions */\n");
bool functions_found = false;
for (unsigned i = 0; i < module_count; i++)
{
Module *module = modules[i];
@@ -619,12 +683,12 @@ void header_gen(Module **modules, unsigned module_count)
// Generate all functions
FOREACH_BEGIN(CompilationUnit *unit, module->units)
FOREACH_BEGIN(Decl *fn, unit->functions)
header_gen_function(file, file_types, &table, fn);
header_gen_function(file, table, fn, fn_globals, &functions_found);
FOREACH_END();
FOREACH_END();
}
PRINTF("\n/* Methods */\n");
bool methods_found = false;
for (unsigned i = 0; i < module_count; i++)
{
// Ignore stdlib modules
@@ -635,10 +699,45 @@ void header_gen(Module **modules, unsigned module_count)
// Generate all functions
FOREACH_BEGIN(CompilationUnit *unit, module->units)
FOREACH_BEGIN(Decl *method, unit->methods)
header_gen_function(file, file_types, &table, method);
header_gen_function(file, table, method, fn_globals, &methods_found);
FOREACH_END();
FOREACH_END();
}
fclose(file);
fclose(file_types);
}
void header_gen(Module **modules, unsigned module_count)
{
HTable table;
htable_init(&table, 1024);
const char *name = build_base_name();
const char *filename = str_printf("%s.h", name);
FILE *file = fopen(filename, "w");
PRINTF("#include <stdint.h>\n");
PRINTF("#include <stddef.h>\n");
PRINTF("#include <stdbool.h>\n");
PRINTF("#ifndef __c3__\n");
PRINTF("#define __c3__\n\n");
PRINTF("typedef void* c3typeid_t;\n");
PRINTF("typedef void* c3fault_t;\n");
PRINTF("typedef struct { void* ptr; size_t len; } c3slice_t;\n");
PRINTF("typedef struct { void* ptr; c3typeid_t type; } c3any_t;\n");
PRINTF("\n#endif\n\n");
PRINTF("/* TYPES */\n");
for (unsigned i = 0; i < module_count; i++)
{
Module *module = modules[i];
// Produce all constants.
FOREACH_BEGIN(CompilationUnit *unit, module->units)
FOREACH_BEGIN(Decl *type, unit->types)
if (!type->is_export) continue;
header_gen_maybe_generate_type(file, &table, type->type);
FOREACH_END();
FOREACH_END();
}
header_gen_global_decls(file, &table, modules, module_count, false);
header_gen_global_decls(file, &table, modules, module_count, true);
fclose(file);
}

View File

@@ -1766,7 +1766,7 @@ static inline void decl_add_type(Decl *decl, TypeKind kind)
decl->type = type;
}
/**
* typedef_declaration ::= DEF TYPE_IDENT '=' 'distinct'? typedef_type ';'
* typedef_declaration ::= DEF TYPE_IDENT '=' typedef_type ';'
*
* typedef_type ::= func_typedef | type generic_params?
* func_typedef ::= 'fn' optional_type parameter_type_list

View File

@@ -1009,13 +1009,16 @@ static inline bool sema_analyse_signature(SemaContext *context, Signature *sig,
}
TypeInfo *method_parent = type_infoptrzero(type_parent);
if (method_parent)
{
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;
// Fill in the type if the first parameter is lacking a type.
if (method_parent && params && params[0] && !params[0]->var.type_info)
{
if (!sema_resolve_type_info(context, method_parent,
is_macro ? RESOLVE_TYPE_MACRO_METHOD : RESOLVE_TYPE_FUNC_METHOD)) return false;
Decl *param = params[0];
Type *inferred_type = NULL;
switch (param->var.kind)
@@ -1242,6 +1245,7 @@ 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);
if (decl->typedef_decl.is_func)
{
Decl *fn_decl = decl->typedef_decl.decl;
@@ -2269,7 +2273,7 @@ static bool sema_analyse_attribute(SemaContext *context, Decl *decl, Attr *attr,
[ATTRIBUTE_CALLCONV] = ATTR_FUNC | ATTR_INTERFACE_METHOD,
[ATTRIBUTE_DEPRECATED] = USER_DEFINED_TYPES | CALLABLE_TYPE | ATTR_CONST | ATTR_GLOBAL | ATTR_MEMBER | ATTR_BITSTRUCT_MEMBER | ATTR_INTERFACE,
[ATTRIBUTE_DYNAMIC] = ATTR_FUNC,
[ATTRIBUTE_EXPORT] = ATTR_FUNC | ATTR_GLOBAL | ATTR_CONST | EXPORTED_USER_DEFINED_TYPES,
[ATTRIBUTE_EXPORT] = ATTR_FUNC | ATTR_GLOBAL | ATTR_CONST | USER_DEFINED_TYPES | ATTR_DEF,
[ATTRIBUTE_EXTERN] = ATTR_FUNC | ATTR_GLOBAL | ATTR_CONST | USER_DEFINED_TYPES,
[ATTRIBUTE_FINALIZER] = ATTR_FUNC,
[ATTRIBUTE_IF] = (AttributeDomain)~(ATTR_CALL | ATTR_LOCAL | ATTR_PARAM),

View File

@@ -415,9 +415,7 @@ Decl *type_no_export(Type *type)
case TYPE_ENUM:
case TYPE_STRUCT:
case TYPE_UNION:
case TYPE_BITSTRUCT:
case TYPE_FAULTTYPE:
case TYPE_DISTINCT:
if (type->decl->is_export) return NULL;
return type->decl;
case TYPE_SLICE:
@@ -430,6 +428,15 @@ 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;