summaryrefslogtreecommitdiff
path: root/src/codegen
diff options
context:
space:
mode:
Diffstat (limited to 'src/codegen')
-rw-r--r--src/codegen/codegen.h22
-rw-r--r--src/codegen/codegen_decl.c88
-rw-r--r--src/codegen/codegen_stmt.c35
-rw-r--r--src/codegen/codegen_utils.c9
-rw-r--r--src/codegen/compat.h8
5 files changed, 101 insertions, 61 deletions
diff --git a/src/codegen/codegen.h b/src/codegen/codegen.h
index 9d32110..b3e971d 100644
--- a/src/codegen/codegen.h
+++ b/src/codegen/codegen.h
@@ -11,7 +11,7 @@
/**
* @brief Generates code for a given AST node.
- *
+ *
* @param ctx Parser context.
* @param node The AST node to generate code for.
* @param out Output file stream.
@@ -76,19 +76,19 @@ int emit_tests_and_runner(ParserContext *ctx, ASTNode *node, FILE *out);
void print_type_defs(ParserContext *ctx, FILE *out, ASTNode *nodes);
// Global state (shared across modules).
-extern ASTNode *global_user_structs; ///< List of user defined structs.
-extern char *g_current_impl_type; ///< Type currently being implemented (in impl block).
-extern int tmp_counter; ///< Counter for temporary variables.
-extern int defer_count; ///< Counter for defer statements in current scope.
-extern ASTNode *defer_stack[]; ///< Stack of deferred nodes.
-extern ASTNode *g_current_lambda; ///< Current lambda being generated.
-extern char *g_current_func_ret_type; ///< Return type of current function.
+extern ASTNode *global_user_structs; ///< List of user defined structs.
+extern char *g_current_impl_type; ///< Type currently being implemented (in impl block).
+extern int tmp_counter; ///< Counter for temporary variables.
+extern int defer_count; ///< Counter for defer statements in current scope.
+extern ASTNode *defer_stack[]; ///< Stack of deferred nodes.
+extern ASTNode *g_current_lambda; ///< Current lambda being generated.
+extern char *g_current_func_ret_type; ///< Return type of current function.
// Defer boundary tracking for proper defer execution on break/continue/return
#define MAX_DEFER 1024
#define MAX_LOOP_DEPTH 64
-extern int loop_defer_boundary[]; ///< Defer stack index at start of each loop.
-extern int loop_depth; ///< Current loop nesting depth.
-extern int func_defer_boundary; ///< Defer stack index at function entry.
+extern int loop_defer_boundary[]; ///< Defer stack index at start of each loop.
+extern int loop_depth; ///< Current loop nesting depth.
+extern int func_defer_boundary; ///< Defer stack index at function entry.
#endif
diff --git a/src/codegen/codegen_decl.c b/src/codegen/codegen_decl.c
index d59511d..10294e4 100644
--- a/src/codegen/codegen_decl.c
+++ b/src/codegen/codegen_decl.c
@@ -34,13 +34,9 @@ static void emit_freestanding_preamble(FILE *out)
fputs("#define _z_arg(x) _Generic((x), _Bool: _z_bool_str(x), default: (x))\n", out);
fputs("typedef struct { void *func; void *ctx; } z_closure_T;\n", out);
- fputs("__attribute__((weak)) void* z_malloc(usize sz) { return NULL; }\n", out);
- fputs("__attribute__((weak)) void* z_realloc(void* ptr, usize sz) { return "
- "NULL; }\n",
- out);
- fputs("__attribute__((weak)) void z_free(void* ptr) { }\n", out);
- fputs("__attribute__((weak)) void z_print(const char* fmt, ...) { }\n", out);
- fputs("__attribute__((weak)) void z_panic(const char* msg) { while(1); }\n", out);
+ // In true freestanding, explicit definitions of z_malloc/etc are removed.
+ // The user must implement them if they use features requiring them.
+ // Most primitives (integers, pointers) work without them.
}
void emit_preamble(ParserContext *ctx, FILE *out)
@@ -48,6 +44,7 @@ void emit_preamble(ParserContext *ctx, FILE *out)
if (g_config.is_freestanding)
{
emit_freestanding_preamble(out);
+ return;
}
else
{
@@ -1034,53 +1031,52 @@ void print_type_defs(ParserContext *ctx, FILE *out, ASTNode *nodes)
if (!g_config.is_freestanding)
{
fprintf(out, "typedef char* string;\n");
- }
+
- fprintf(out, "typedef struct { void **data; int len; int cap; } Vec;\n");
- fprintf(out, "#define Vec_new() (Vec){.data=0, .len=0, .cap=0}\n");
+ fprintf(out, "typedef struct { void **data; int len; int cap; } Vec;\n");
+ fprintf(out, "#define Vec_new() (Vec){.data=0, .len=0, .cap=0}\n");
- if (g_config.use_cpp)
- {
- fprintf(out, "void _z_vec_push(Vec *v, void *item) { if(v->len >= v->cap) { "
- "v->cap = v->cap?v->cap*2:8; "
- "v->data = static_cast<void**>(realloc(v->data, v->cap * sizeof(void*))); } "
- "v->data[v->len++] = item; }\n");
- fprintf(out, "static inline Vec _z_make_vec(int count, ...) { Vec v = {0}; v.cap = "
- "count > 8 ? "
- "count : 8; v.data = static_cast<void**>(malloc(v.cap * sizeof(void*))); "
- "v.len = 0; va_list "
- "args; "
- "va_start(args, count); for(int i=0; i<count; i++) { v.data[v.len++] = "
- "va_arg(args, void*); } va_end(args); return v; }\n");
- }
- else
- {
- fprintf(out, "void _z_vec_push(Vec *v, void *item) { if(v->len >= v->cap) { "
- "v->cap = v->cap?v->cap*2:8; "
- "v->data = z_realloc(v->data, v->cap * sizeof(void*)); } "
- "v->data[v->len++] = item; }\n");
- fprintf(out, "static inline Vec _z_make_vec(int count, ...) { Vec v = {0}; v.cap = "
- "count > 8 ? "
- "count : 8; v.data = z_malloc(v.cap * sizeof(void*)); v.len = 0; va_list "
- "args; "
- "va_start(args, count); for(int i=0; i<count; i++) { v.data[v.len++] = "
- "va_arg(args, void*); } va_end(args); return v; }\n");
- }
- fprintf(out, "#define Vec_push(v, i) _z_vec_push(&(v), (void*)(long)(i))\n");
+ if (g_config.use_cpp)
+ {
+ fprintf(out, "void _z_vec_push(Vec *v, void *item) { if(v->len >= v->cap) { "
+ "v->cap = v->cap?v->cap*2:8; "
+ "v->data = static_cast<void**>(realloc(v->data, v->cap * sizeof(void*))); } "
+ "v->data[v->len++] = item; }\n");
+ fprintf(out, "static inline Vec _z_make_vec(int count, ...) { Vec v = {0}; v.cap = "
+ "count > 8 ? "
+ "count : 8; v.data = static_cast<void**>(malloc(v.cap * sizeof(void*))); "
+ "v.len = 0; va_list "
+ "args; "
+ "va_start(args, count); for(int i=0; i<count; i++) { v.data[v.len++] = "
+ "va_arg(args, void*); } va_end(args); return v; }\n");
+ }
+ else
+ {
+ fprintf(out, "void _z_vec_push(Vec *v, void *item) { if(v->len >= v->cap) { "
+ "v->cap = v->cap?v->cap*2:8; "
+ "v->data = z_realloc(v->data, v->cap * sizeof(void*)); } "
+ "v->data[v->len++] = item; }\n");
+ fprintf(out, "static inline Vec _z_make_vec(int count, ...) { Vec v = {0}; v.cap = "
+ "count > 8 ? "
+ "count : 8; v.data = z_malloc(v.cap * sizeof(void*)); v.len = 0; va_list "
+ "args; "
+ "va_start(args, count); for(int i=0; i<count; i++) { v.data[v.len++] = "
+ "va_arg(args, void*); } va_end(args); return v; }\n");
+ }
+ fprintf(out, "#define Vec_push(v, i) _z_vec_push(&(v), (void*)(long)(i))\n");
- if (g_config.is_freestanding)
- {
fprintf(out, "#define _z_check_bounds(index, limit) ({ ZC_AUTO _i = "
- "(index); if(_i < 0 "
- "|| _i >= (limit)) { z_panic(\"index out of bounds\"); } _i; })\n");
+ "(index); if(_i < 0 "
+ "|| _i >= (limit)) { fprintf(stderr, \"Index out of bounds: "
+ "%%ld (limit "
+ "%%d)\\n\", (long)_i, (int)(limit)); exit(1); } _i; })\n");
}
else
{
- fprintf(out, "#define _z_check_bounds(index, limit) ({ ZC_AUTO _i = "
+ // We might need to change this later. So TODO.
+ fprintf(out, "#define _z_check_bounds(index, limit) ({ ZC_AUTO _i = "
"(index); if(_i < 0 "
- "|| _i >= (limit)) { fprintf(stderr, \"Index out of bounds: "
- "%%ld (limit "
- "%%d)\\n\", (long)_i, (int)(limit)); exit(1); } _i; })\n");
+ "|| _i >= (limit)) { z_panic(\"index out of bounds\"); } _i; })\n");
}
SliceType *c = ctx->used_slices;
diff --git a/src/codegen/codegen_stmt.c b/src/codegen/codegen_stmt.c
index 43e5bb5..6e41109 100644
--- a/src/codegen/codegen_stmt.c
+++ b/src/codegen/codegen_stmt.c
@@ -697,6 +697,41 @@ void codegen_node_single(ParserContext *ctx, ASTNode *node, FILE *out)
fprintf(out, "{\n");
char *prev_ret = g_current_func_ret_type;
g_current_func_ret_type = node->func.ret_type;
+
+ // Initialize drop flags for arguments that implement Drop
+ for (int i = 0; i < node->func.arg_count; i++)
+ {
+ Type *arg_type = node->func.arg_types[i];
+ char *arg_name = node->func.param_names[i];
+ if (arg_type && arg_name)
+ {
+ // Check if type implements Drop
+ int has_drop = 0;
+ if (arg_type->kind == TYPE_STRUCT && arg_type->name)
+ {
+ ASTNode *def = find_struct_def(ctx, arg_type->name);
+ if (def && def->type == NODE_STRUCT && def->type_info &&
+ def->type_info->traits.has_drop)
+ {
+ has_drop = 1;
+ }
+ else if (def)
+ {
+ // No drop needed
+ }
+ else
+ {
+ // No struct def found
+ }
+ }
+
+ if (has_drop)
+ {
+ fprintf(out, " int __z_drop_flag_%s = 1;\n", arg_name);
+ }
+ }
+ }
+
codegen_walker(ctx, node->func.body, out);
for (int i = defer_count - 1; i >= 0; i--)
{
diff --git a/src/codegen/codegen_utils.c b/src/codegen/codegen_utils.c
index c48f4eb..8de3cf6 100644
--- a/src/codegen/codegen_utils.c
+++ b/src/codegen/codegen_utils.c
@@ -474,6 +474,15 @@ char *infer_type(ParserContext *ctx, ASTNode *node)
return node->struct_init.struct_name;
}
+ if (node->type == NODE_EXPR_ARRAY_LITERAL)
+ {
+ if (node->type_info)
+ {
+ return type_to_string(node->type_info);
+ }
+ return NULL;
+ }
+
if (node->type == NODE_EXPR_LITERAL)
{
if (node->literal.type_kind == LITERAL_STRING)
diff --git a/src/codegen/compat.h b/src/codegen/compat.h
index f34d612..f2d221a 100644
--- a/src/codegen/compat.h
+++ b/src/codegen/compat.h
@@ -14,10 +14,10 @@
#define ZC_EXTERN_C_END }
#else
/* C mode */
-#define ZC_AUTO __auto_type ///< Auto type inference.
-#define ZC_CAST(T, x) ((T)(x)) ///< Explicit cast.
-#define ZC_REINTERPRET(T, x) ((T)(x)) ///< Reinterpret cast.
-#define ZC_EXTERN_C ///< Extern "C" (no-op in C).
+#define ZC_AUTO __auto_type ///< Auto type inference.
+#define ZC_CAST(T, x) ((T)(x)) ///< Explicit cast.
+#define ZC_REINTERPRET(T, x) ((T)(x)) ///< Reinterpret cast.
+#define ZC_EXTERN_C ///< Extern "C" (no-op in C).
#define ZC_EXTERN_C_BEGIN
#define ZC_EXTERN_C_END
#endif