@@ -11,6 +11,12 @@ static uint64_t cg_now_ns(void) {
1111 return (t * (uint64_t )tb .numer ) / (uint64_t )tb .denom ;
1212}
1313
14+ static const char * g_entry_label_override = NULL ;
15+
16+ void cg_set_entry_label_override (const char * label ) {
17+ g_entry_label_override = label ;
18+ }
19+
1420typedef struct {
1521 const char * key ;
1622 symtab_entry * val ;
@@ -433,6 +439,7 @@ static void emit_adrp_add(cg_blob_t *out, cg_profile_t *prof, uint32_t *w, size_
433439
434440int cg_emit_arm64 (const ir_prog_t * ir , cg_blob_t * out ) {
435441 if (!ir || !out ) return -1 ;
442+ const char * entry_override = (g_entry_label_override && g_entry_label_override [0 ]) ? g_entry_label_override : NULL ;
436443 const int profile_enabled = out -> profile_enabled ;
437444 memset (out ,0 ,sizeof (* out ));
438445 out -> profile_enabled = profile_enabled ;
@@ -512,14 +519,20 @@ int cg_emit_arm64(const ir_prog_t *ir, cg_blob_t *out) {
512519
513520 /* Determine function entry labels: first label, labels named "main", labels prefixed with "fn_", and labels that are CALL targets. */
514521 const uint64_t t_func0 = prof ? cg_now_ns () : 0 ;
522+ int override_found = 0 ;
515523 for (size_t i = 0 ; i < n_labels ; i ++ ) {
516524 int is_func = 0 ;
517- if (!first_label_seen ) { is_func = 1 ; first_label_seen = 1 ; }
525+ if (entry_override && label_list [i ].name && strcmp (label_list [i ].name , entry_override ) == 0 ) { is_func = 1 ; override_found = 1 ; }
526+ if (!entry_override && !first_label_seen ) { is_func = 1 ; first_label_seen = 1 ; }
518527 if (label_list [i ].name && strcmp (label_list [i ].name , "main" ) == 0 ) is_func = 1 ;
519528 if (label_list [i ].name && strncmp (label_list [i ].name , "fn_" , 3 ) == 0 ) is_func = 1 ;
520529 if (label_list [i ].name && seen_has (call_targets , n_calls , label_list [i ].name )) is_func = 1 ;
521530 if (is_func ) func_count ++ ;
522531 }
532+ if (entry_override && !override_found ) {
533+ if (prof ) prof -> func_detect_ns = cg_now_ns () - t_func0 ;
534+ CG_FAIL (NULL , "--entry-label symbol not found in input labels" );
535+ }
523536 if (func_count == 0 && any_instr ) func_count = 1 ;
524537 if (prof ) prof -> func_detect_ns = cg_now_ns () - t_func0 ;
525538
@@ -556,7 +569,8 @@ int cg_emit_arm64(const ir_prog_t *ir, cg_blob_t *out) {
556569 if (e -> kind == IR_ENTRY_LABEL ) {
557570 if (e -> u .label .name ) {
558571 int is_func = 0 ;
559- if (!func_seen ) is_func = 1 ;
572+ if (entry_override && strcmp (e -> u .label .name , entry_override ) == 0 ) is_func = 1 ;
573+ if (!entry_override && !func_seen ) is_func = 1 ;
560574 if (strcmp (e -> u .label .name , "main" ) == 0 ) is_func = 1 ;
561575 if (strncmp (e -> u .label .name , "fn_" , 3 ) == 0 ) is_func = 1 ;
562576 if (seen_has (call_targets , n_calls , e -> u .label .name )) is_func = 1 ;
@@ -566,6 +580,18 @@ int cg_emit_arm64(const ir_prog_t *ir, cg_blob_t *out) {
566580 func_has_prologue = 0 ;
567581 }
568582 symtab_update (& ctx , out -> syms , e -> u .label .name , pcw * 4 );
583+
584+ /* Emit the function prologue at the function entry label.
585+ * This ensures any immediately-following label is placed after the
586+ * prologue (distinct address), avoiding accidental stack growth when
587+ * branching to a basic-block label that would otherwise share the
588+ * function entry address.
589+ */
590+ if (is_func && !func_has_prologue ) {
591+ w [pcw ++ ] = enc_stp_fp_lr ();
592+ w [pcw ++ ] = enc_mov_fp_sp ();
593+ func_has_prologue = 1 ;
594+ }
569595 }
570596 if (prof ) prof -> pass2_labels_ns += cg_now_ns () - t_e0 ;
571597 continue ;
0 commit comments