Added naked function support
authorRobert Pengelly <robertapengelly@hotmail.com>
Mon, 24 Aug 2026 06:58:44 +0000 (07:58 +0100)
committerRobert Pengelly <robertapengelly@hotmail.com>
Mon, 24 Aug 2026 06:58:44 +0000 (07:58 +0100)
amd64.c
i386.c
parse.c
parse.h

diff --git a/amd64.c b/amd64.c
index 94897021ee2fe11094ffa6a0a6b253e31d8221f1..ae021f9674d122d1b117a969009f0d6e4308463d 100644 (file)
--- a/amd64.c
+++ b/amd64.c
@@ -107,6 +107,7 @@ static int fallthrough_case_ends_control_flow[MAX_FALLTHROUGH_SWITCH_DEPTH];
 static int current_function_has_return_statement = 0;
 static int statement_ends_control_flow = 0;
 
+static int current_function_is_naked = 0;
 static int current_parse_block_depth = 0;
 static int current_function_is_void = 0;
 static int current_function_is_noreturn = 0;
@@ -6809,6 +6810,11 @@ static void emit_function_start (const char *name, int is_static) {
     if (state->syntax & ASM_SYNTAX_INTEL) {
     
         fprintf (state->ofp, "%s:\n", asm_name);
+        
+        if (current_function_is_naked) {
+            return;
+        }
+        
         fprintf (state->ofp, "    push rbp\n");
         fprintf (state->ofp, "    mov rbp, rsp\n");
         
@@ -6820,6 +6826,11 @@ static void emit_function_start (const char *name, int is_static) {
     } else {
     
         fprintf (state->ofp, "%s:\n", asm_name);
+        
+        if (current_function_is_naked) {
+            return;
+        }
+        
         fprintf (state->ofp, "    pushq %%rbp\n");
         fprintf (state->ofp, "    movq %%rsp, %%rbp\n");
         
@@ -7263,6 +7274,10 @@ static void emit_function_end (void) {
 
     patch_deferred_function_frame ();
     
+    if (current_function_is_naked) {
+        return;
+    }
+    
     if (!state->ofp) {
         return;
     }
@@ -38167,7 +38182,7 @@ static void parse_statement (void) {
 
 }
 
-static void parse_function_body (const char *name, int storage_class, int is_inline, int is_noreturn, int return_is_void, int return_is_floating, int return_is_unsigned, int return_size, int return_pointer_depth, unsigned long function_line, const char *function_start, const char *function_caret) {
+static void parse_function_body (const char *name, int storage_class, int is_inline, int is_noreturn, int is_naked, int return_is_void, int return_is_floating, int return_is_unsigned, int return_size, int return_pointer_depth, unsigned long function_line, const char *function_start, const char *function_caret) {
 
     int old_return_label = current_return_label;
     int should_emit = 1;
@@ -38191,6 +38206,7 @@ static void parse_function_body (const char *name, int storage_class, int is_inl
     int saved_declarator_function_is_variadic;
     int saved_current_section = current_section;
     
+    int old_function_is_naked;
     int old_function_is_void;
     int old_function_is_noreturn;
     int old_function_is_floating;
@@ -38287,6 +38303,7 @@ static void parse_function_body (const char *name, int storage_class, int is_inl
     
     }
     
+    old_function_is_naked = current_function_is_naked;
     old_function_has_return_statement = current_function_has_return_statement;
     old_function_is_void = current_function_is_void;
     old_function_is_noreturn = current_function_is_noreturn;
@@ -38296,6 +38313,7 @@ static void parse_function_body (const char *name, int storage_class, int is_inl
     old_function_return_pointer_depth = current_function_return_pointer_depth;
     old_function_returns_aggregate = current_function_returns_aggregate;
     
+    current_function_is_naked = is_naked ? 1 : 0;
     current_function_is_void = return_is_void;
     current_function_is_noreturn = effective_noreturn;
     current_function_is_floating = return_is_floating;
@@ -38349,7 +38367,7 @@ static void parse_function_body (const char *name, int storage_class, int is_inl
      * Moving all automatic storage to a synthetic prologue changes that
      * analysis and can corrupt the self-built compiler.
      */
-    current_function_frame_enabled = (!is_inline && capture_function_body);
+    current_function_frame_enabled = (!current_function_is_naked && !is_inline && capture_function_body);
     emit_function_start (name, !emit_public);
     
     statement_ends_control_flow = 0;
@@ -38432,6 +38450,7 @@ static void parse_function_body (const char *name, int storage_class, int is_inl
     reset_local_symbols ();
     reset_goto_labels ();
     
+    current_function_is_naked = old_function_is_naked;
     current_function_has_return_statement = old_function_has_return_statement;
     current_function_is_void = old_function_is_void;
     current_function_is_noreturn = old_function_is_noreturn;
@@ -38604,7 +38623,7 @@ static int parse_possible_knr_function (void) {
     
     if (is_type_start (tok.kind) || tok.kind == TOK_LBRACE) {
     
-        parse_function_body (name, STORAGE_NONE, 0, 0, 0, 0, 0, DATA_INT & 0x1f, 0, name_line, name_start, name_caret);
+        parse_function_body (name, STORAGE_NONE, 0, 0, 0, 0, 0, 0, DATA_INT & 0x1f, 0, name_line, name_start, name_caret);
         
         if (parsed_dllexport || declarator_dllexport) {
         
@@ -39912,6 +39931,7 @@ static void parse_external_after_type (void) {
         int declaration_is_inline;
         int declaration_storage;
         
+        int declaration_naked = 0;
         int declaration_noreturn = 0;
         int declaration_dllimport = 0;
         int declaration_dllexport = 0;
@@ -39936,6 +39956,7 @@ static void parse_external_after_type (void) {
         
         object_field_count = saved_field_count;
         
+        declaration_naked = parsed_naked;
         declaration_is_inline = parsed_type_is_inline;
         declaration_storage = parsed_storage_class;
         declaration_noreturn = parsed_noreturn;
@@ -39944,6 +39965,7 @@ static void parse_external_after_type (void) {
         
         parse_declarator (&name);
         
+        declaration_naked = declaration_naked || parsed_naked || declarator_naked;
         declaration_noreturn = declaration_noreturn || parsed_noreturn || declarator_noreturn;
         declaration_dllimport = declaration_dllimport || parsed_dllimport || declarator_dllimport;
         declaration_dllexport = declaration_dllexport || parsed_dllexport || declarator_dllexport;
@@ -40032,7 +40054,7 @@ static void parse_external_after_type (void) {
             
             }
             
-            parse_function_body (name, declaration_storage, declaration_is_inline, declaration_noreturn,
+            parse_function_body (name, declaration_storage, declaration_is_inline, declaration_noreturn, declaration_naked,
                 (parsed_type_is_void && !declarator_is_pointer),
                     (declarator_is_pointer ? 0 : parsed_type_is_floating),
                         (declarator_is_pointer ? 0 : parsed_type_is_unsigned),
diff --git a/i386.c b/i386.c
index 6c7367bfd82e30ee35ee044f90f7cb919108e51f..61b446425b8060677d4db152649f7465beffa207 100644 (file)
--- a/i386.c
+++ b/i386.c
@@ -82,6 +82,7 @@ static int statement_ends_control_flow = 0;
 static int current_parse_block_depth = 0;
 static int current_function_is_void = 0;
 static int current_function_is_noreturn = 0;
+static int current_function_is_naked = 0;
 static int current_function_is_floating = 0;
 static int current_function_return_size = DATA_NONE;
 static int current_function_return_is_unsigned = 0;
@@ -6347,6 +6348,11 @@ static void emit_function_start (const char *name, int is_static) {
     if (state->syntax & ASM_SYNTAX_INTEL) {
     
         fprintf (state->ofp, "%s:\n", asm_name);
+        
+        if (current_function_is_naked) {
+            return;
+        }
+        
         fprintf (state->ofp, "    push ebp\n");
         fprintf (state->ofp, "    mov ebp, esp\n");
         
@@ -6355,6 +6361,11 @@ static void emit_function_start (const char *name, int is_static) {
     } else {
     
         fprintf (state->ofp, "%s:\n", asm_name);
+        
+        if (current_function_is_naked) {
+            return;
+        }
+        
         fprintf (state->ofp, "    pushl %%ebp\n");
         fprintf (state->ofp, "    movl %%esp, %%ebp\n");
         
@@ -6751,6 +6762,10 @@ static void emit_function_end (void) {
 
     patch_deferred_function_frame ();
     
+    if (current_function_is_naked) {
+        return;
+    }
+    
     if (!state->ofp) {
         return;
     }
@@ -35614,7 +35629,7 @@ static void parse_statement (void) {
 
 }
 
-static void parse_function_body (const char *name, int storage_class, int is_inline, int is_noreturn, int return_is_void, int return_is_floating, int return_is_unsigned, int return_size, unsigned long function_line, const char *function_start, const char *function_caret) {
+static void parse_function_body (const char *name, int storage_class, int is_inline, int is_noreturn, int is_naked, int return_is_void, int return_is_floating, int return_is_unsigned, int return_size, unsigned long function_line, const char *function_start, const char *function_caret) {
 
     int old_return_label = current_return_label;
     int should_emit = 1;
@@ -35638,6 +35653,7 @@ static void parse_function_body (const char *name, int storage_class, int is_inl
     int saved_declarator_function_is_variadic;
     int saved_current_section = current_section;
     
+    int old_function_is_naked;
     int old_function_is_void;
     int old_function_is_noreturn;
     int old_function_is_floating;
@@ -35733,6 +35749,7 @@ static void parse_function_body (const char *name, int storage_class, int is_inl
     
     }
     
+    old_function_is_naked = current_function_is_naked;
     old_function_has_return_statement = current_function_has_return_statement;
     old_function_is_void = current_function_is_void;
     old_function_is_noreturn = current_function_is_noreturn;
@@ -35741,6 +35758,7 @@ static void parse_function_body (const char *name, int storage_class, int is_inl
     old_function_return_is_unsigned = current_function_return_is_unsigned;
     old_function_returns_aggregate = current_function_returns_aggregate;
     
+    current_function_is_naked = is_naked ? 1 : 0;
     current_function_is_void = return_is_void;
     current_function_is_noreturn = effective_noreturn;
     current_function_is_floating = return_is_floating;
@@ -35791,7 +35809,7 @@ static void parse_function_body (const char *name, int storage_class, int is_inl
      * Moving all automatic storage to a synthetic prologue changes that
      * analysis and can corrupt the self-built compiler.
      */
-    current_function_frame_enabled = (!is_inline && capture_function_body);
+    current_function_frame_enabled = (!current_function_is_naked && !is_inline && capture_function_body);
     emit_function_start (name, !emit_public);
     
     statement_ends_control_flow = 0;
@@ -35873,6 +35891,7 @@ static void parse_function_body (const char *name, int storage_class, int is_inl
     reset_local_symbols ();
     reset_goto_labels ();
     
+    current_function_is_naked = old_function_is_naked;
     current_function_has_return_statement = old_function_has_return_statement;
     current_function_is_void = old_function_is_void;
     current_function_is_noreturn = old_function_is_noreturn;
@@ -36044,7 +36063,7 @@ static int parse_possible_knr_function (void) {
     
     if (is_type_start (tok.kind) || tok.kind == TOK_LBRACE) {
     
-        parse_function_body (name, STORAGE_NONE, 0, 0, 0, 0, 0, DATA_INT & 0x1f, name_line, name_start, name_caret);
+        parse_function_body (name, STORAGE_NONE, 0, 0, 0, 0, 0, 0, DATA_INT & 0x1f, name_line, name_start, name_caret);
         
         if (parsed_dllexport || declarator_dllexport) {
         
@@ -37245,6 +37264,7 @@ static void parse_external_after_type (void) {
         int declaration_is_inline;
         int declaration_storage;
         
+        int declaration_naked = 0;
         int declaration_noreturn = 0;
         int declaration_dllimport = 0;
         int declaration_dllexport = 0;
@@ -37269,6 +37289,7 @@ static void parse_external_after_type (void) {
         
         object_field_count = saved_field_count;
         
+        declaration_naked = parsed_naked;
         declaration_is_inline = parsed_type_is_inline;
         declaration_storage = parsed_storage_class;
         declaration_dllimport = parsed_dllimport;
@@ -37280,6 +37301,7 @@ static void parse_external_after_type (void) {
         declaration_dllimport = declaration_dllimport || parsed_dllimport || declarator_dllimport;
         declaration_dllexport = declaration_dllexport || parsed_dllexport || declarator_dllexport;
         declaration_noreturn = declaration_noreturn || parsed_noreturn || declarator_noreturn;
+        declaration_naked = declaration_naked || parsed_naked || declarator_naked;
         
         apply_typedef_array_to_declarator ();
         
@@ -37366,7 +37388,7 @@ static void parse_external_after_type (void) {
             
             }
             
-            parse_function_body (name, declaration_storage, declaration_is_inline, declaration_noreturn,
+            parse_function_body (name, declaration_storage, declaration_is_inline, declaration_noreturn, declaration_naked,
                 (parsed_type_is_void && !declarator_is_pointer),
                     (declarator_is_pointer ? 0 : parsed_type_is_floating),
                         (declarator_is_pointer ? 0 : parsed_type_is_unsigned),
diff --git a/parse.c b/parse.c
index d7775ad0c85dc18144ba942aca197abd2d47719c..393b884101036d384baa40bdd51ab99fad2ce567 100644 (file)
--- a/parse.c
+++ b/parse.c
@@ -28,6 +28,7 @@ struct vector vec_dllaliases = { 0 };
 int parsed_dllexport = 0;
 int parsed_dllimport = 0;
 int parsed_noreturn = 0;
+int parsed_naked = 0;
 
 int parsed_type_size = DATA_NONE;
 int parsed_type_is_inline = 0;
@@ -65,6 +66,7 @@ int declarator_is_pointer = 0;
 
 int declarator_has_array = 0;
 int declarator_noreturn = 0;
+int declarator_naked = 0;
 
 int declarator_dllexport = 0;
 int declarator_dllimport = 0;
@@ -567,6 +569,17 @@ static void apply_decl_attribute (const char *spelling, int is_gnu) {
         
         }
     
+    } else if (attribute_name_is (spelling, "naked")) {
+    
+        if (parsed_naked || declarator_naked) {
+            report_line_at (get_filename (), get_line_number (), REPORT_ERROR, tok.report_start, tok.report_caret, "duplicate '%s(naked)'", is_gnu ? "__attribute__" : "__declspec");
+        } else {
+        
+            declarator_naked = 1;
+            parsed_naked = 1;
+        
+        }
+    
     } else if (is_gnu && attribute_name_is (spelling, "stdcall")) {
     
         if (parsed_calling_convention == TOK_EOF && declarator_calling_convention == TOK_EOF) {
@@ -845,6 +858,7 @@ void parse_declarator (char **out_name) {
     int saved_declarator_dllexport = declarator_dllexport;
     int saved_declarator_dllimport = declarator_dllimport;
     int saved_declarator_noreturn = declarator_noreturn;
+    int saved_declarator_naked = declarator_naked;
     
     unsigned long saved_captured_declarator_name_line = captured_declarator_name_line;
     memcpy (saved_declarator_alias_target, declarator_alias_target, sizeof (declarator_alias_target));
@@ -863,6 +877,7 @@ void parse_declarator (char **out_name) {
         declarator_dllexport = 0;
         declarator_dllimport = 0;
         declarator_noreturn = 0;
+        declarator_naked = 0;
         
         captured_declarator_name_location = 0;
         captured_declarator_name_start = 0;
@@ -928,6 +943,7 @@ void parse_declarator (char **out_name) {
         declarator_dllexport = saved_declarator_dllexport;
         declarator_dllimport = saved_declarator_dllimport;
         declarator_noreturn = saved_declarator_noreturn;
+        declarator_naked = saved_declarator_naked;
     
     }
 
@@ -2890,6 +2906,7 @@ void parse_type_spec (void) {
     parsed_dllexport = 0;
     parsed_dllimport = 0;
     parsed_noreturn = 0;
+    parsed_naked = 0;
     
     clear_parsed_fields ();
     
diff --git a/parse.h b/parse.h
index 31c5a295e6c948957bb4953af3a75eca049a3e6d..541a3a00d6de785d4335d7b84dc33e0112eb6811 100644 (file)
--- a/parse.h
+++ b/parse.h
@@ -31,6 +31,7 @@ extern struct vector vec_dllexports;
 extern int parsed_dllexport;
 extern int parsed_dllimport;
 extern int parsed_noreturn;
+extern int parsed_naked;
 
 extern int parsed_type_size;
 extern int parsed_type_is_inline;
@@ -68,9 +69,11 @@ extern int declarator_pointer_depth;
 extern int declarator_has_array;
 
 extern char declarator_alias_target[512];
+
 extern int declarator_dllexport;
 extern int declarator_dllimport;
 extern int declarator_noreturn;
+extern int declarator_naked;
 
 extern enum token_kind declarator_calling_convention;
 extern int global_initializer_accept_symbol_addresses;