From: Robert Pengelly Date: Mon, 24 Aug 2026 06:58:44 +0000 (+0100) Subject: Added naked function support X-Git-Url: https://git.candlhat.org/?a=commitdiff_plain;h=6c80fd24dded6f33ed916b13e5eda312dd9e0bcb;p=scc.git Added naked function support --- diff --git a/amd64.c b/amd64.c index 9489702..ae021f9 100644 --- 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 6c7367b..61b4464 100644 --- 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 d7775ad..393b884 100644 --- 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 31c5a29..541a3a0 100644 --- 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;