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;
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");
} 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");
patch_deferred_function_frame ();
+ if (current_function_is_naked) {
+ return;
+ }
+
if (!state->ofp) {
return;
}
}
-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;
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;
}
+ 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;
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;
* 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;
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;
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) {
int declaration_is_inline;
int declaration_storage;
+ int declaration_naked = 0;
int declaration_noreturn = 0;
int declaration_dllimport = 0;
int declaration_dllexport = 0;
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;
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;
}
- 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),
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;
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");
} 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");
patch_deferred_function_frame ();
+ if (current_function_is_naked) {
+ return;
+ }
+
if (!state->ofp) {
return;
}
}
-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;
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;
}
+ 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;
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;
* 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;
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;
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) {
int declaration_is_inline;
int declaration_storage;
+ int declaration_naked = 0;
int declaration_noreturn = 0;
int declaration_dllimport = 0;
int declaration_dllexport = 0;
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;
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 ();
}
- 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),
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;
int declarator_has_array = 0;
int declarator_noreturn = 0;
+int declarator_naked = 0;
int declarator_dllexport = 0;
int declarator_dllimport = 0;
}
+ } 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) {
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));
declarator_dllexport = 0;
declarator_dllimport = 0;
declarator_noreturn = 0;
+ declarator_naked = 0;
captured_declarator_name_location = 0;
captured_declarator_name_start = 0;
declarator_dllexport = saved_declarator_dllexport;
declarator_dllimport = saved_declarator_dllimport;
declarator_noreturn = saved_declarator_noreturn;
+ declarator_naked = saved_declarator_naked;
}
parsed_dllexport = 0;
parsed_dllimport = 0;
parsed_noreturn = 0;
+ parsed_naked = 0;
clear_parsed_fields ();
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;
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;