From: Robert Pengelly Date: Sun, 23 Aug 2026 02:20:17 +0000 (+0100) Subject: Added __attribute__((alias)) support X-Git-Url: https://git.candlhat.org/?a=commitdiff_plain;h=479799e1b8aa12b3ecf2387cb1be422bdbaec11f;p=scc.git Added __attribute__((alias)) support --- diff --git a/amd64.c b/amd64.c index fa4abdc..c7a04bf 100644 --- a/amd64.c +++ b/amd64.c @@ -39686,6 +39686,22 @@ static void parse_external_after_type (void) { } + if (declarator_alias_target[0]) { + + if (!name) { + report_line_at (get_filename (), name_line, REPORT_ERROR, name_start, name_caret, "'alias' attribute requires a named declaration"); + } else if (!declarator_has_function || declarator_function_is_pointer) { + report_line_at (get_filename (), name_line, REPORT_ERROR, name_start, name_caret, "'alias' attribute is only supported for functions"); + } else if (tok.kind == TOK_LBRACE || is_type_start (tok.kind)) { + report_line_at (get_filename (), name_line, REPORT_ERROR, name_start, name_caret, "function '%s' cannot be both defined and declared with 'alias'", name); + } else { + record_dllalias (name, declarator_alias_target, declaration_dllexport || parsed_dllexport || declarator_dllexport); + } + + declarator_alias_target[0] = '\0'; + + } + if (name && declarator_has_function && (tok.kind == TOK_LBRACE || is_type_start (tok.kind))) { if (declaration_dllexport || parsed_dllexport || declarator_dllexport) { @@ -39924,6 +39940,26 @@ static void parse_external_after_type (void) { } +static int dll_export_name_is_present (const char *wanted) { + + long i; + + if (!wanted) { + return 0; + } + + for (i = 0; i < vec_dllexports.length; i++) { + + if (vec_dllexports.data[i] && strcmp (vec_dllexports.data[i], wanted) == 0) { + return 1; + } + + } + + return 0; + +} + void compile_translation_unit64 (void) { if (state->ofp) { @@ -39976,7 +40012,7 @@ void compile_translation_unit64 (void) { emit_pending_extern_symbols (); - if (vec_dllexports.length) { + if (vec_dllexports.length || vec_dllaliases.length) { char *p, *tmp; @@ -40009,6 +40045,26 @@ void compile_translation_unit64 (void) { } + for (i = 0; i < vec_dllaliases.length; i++) { + + struct dll_alias_entry *entry = vec_dllaliases.data[i]; + + const char *alias_name; + const char *target_name; + + if (!entry || !entry->dllexport || !dll_export_name_is_present (entry->target)) { + continue; + } + + alias_name = asm_global_symbol_name (entry->name); + target_name = asm_global_symbol_name (entry->target); + + if (alias_name && target_name) { + fprintf (fp, " %s=%s\n", alias_name, target_name); + } + + } + fclose (fp); } diff --git a/i386.c b/i386.c index b7a9a82..15d7553 100644 --- a/i386.c +++ b/i386.c @@ -36929,6 +36929,7 @@ static void parse_external_after_type (void) { int declaration_noreturn = 0; int declaration_dllimport = 0; + int declaration_dllexport = 0; int decl_is_pointer; int decl_pointer_depth; @@ -36953,11 +36954,13 @@ static void parse_external_after_type (void) { declaration_is_inline = parsed_type_is_inline; declaration_storage = parsed_storage_class; declaration_dllimport = parsed_dllimport; + declaration_dllexport = parsed_dllexport; declaration_noreturn = parsed_noreturn; parse_declarator (&name); declaration_dllimport = declaration_dllimport || parsed_dllimport || declarator_dllimport; + declaration_dllexport = declaration_dllexport || parsed_dllexport || declarator_dllexport; declaration_noreturn = declaration_noreturn || parsed_noreturn || declarator_noreturn; apply_typedef_array_to_declarator (); @@ -37016,13 +37019,31 @@ static void parse_external_after_type (void) { } + if (declarator_alias_target[0]) { + + if (!name) { + report_line_at (get_filename (), name_line, REPORT_ERROR, name_start, name_caret, "'alias' attribute requires a named declaration"); + } else if (!declarator_has_function || declarator_function_is_pointer) { + report_line_at (get_filename (), name_line, REPORT_ERROR, name_start, name_caret, "'alias' attribute is only supported for functions"); + } else if (tok.kind == TOK_LBRACE || is_type_start (tok.kind)) { + report_line_at (get_filename (), name_line, REPORT_ERROR, name_start, name_caret, "function '%s' cannot be both defined and declared with 'alias'", name); + } else { + record_dllalias (name, declarator_alias_target, declaration_dllexport || parsed_dllexport || declarator_dllexport); + } + + declarator_alias_target[0] = '\0'; + + } + if (name && declarator_has_function && (tok.kind == TOK_LBRACE || is_type_start (tok.kind))) { - if (parsed_dllexport || declarator_dllexport) { + if (declaration_dllexport || parsed_dllexport || declarator_dllexport) { vec_push (&vec_dllexports, xstrdup (name)); declarator_dllexport = 0; + declaration_dllexport = 0; + parsed_dllexport = 0; } @@ -37252,6 +37273,26 @@ static void parse_external_after_type (void) { } +static int dll_export_name_is_present (const char *wanted) { + + long i; + + if (!wanted) { + return 0; + } + + for (i = 0; i < vec_dllexports.length; i++) { + + if (vec_dllexports.data[i] && strcmp (vec_dllexports.data[i], wanted) == 0) { + return 1; + } + + } + + return 0; + +} + void compile_translation_unit32 (void) { if (state->ofp) { @@ -37307,7 +37348,7 @@ void compile_translation_unit32 (void) { emit_pending_extern_symbols (); - if (vec_dllexports.length) { + if (vec_dllexports.length || vec_dllaliases.length) { char *p, *tmp; @@ -37340,6 +37381,26 @@ void compile_translation_unit32 (void) { } + for (i = 0; i < vec_dllaliases.length; i++) { + + struct dll_alias_entry *entry = vec_dllaliases.data[i]; + + const char *alias_name; + const char *target_name; + + if (!entry || !entry->dllexport || !dll_export_name_is_present (entry->target)) { + continue; + } + + alias_name = asm_global_symbol_name (entry->name); + target_name = asm_global_symbol_name (entry->target); + + if (alias_name && target_name) { + fprintf (fp, " %s=%s\n", alias_name, target_name); + } + + } + fclose (fp); } diff --git a/parse.c b/parse.c index 94a14c1..3f30111 100644 --- a/parse.c +++ b/parse.c @@ -23,6 +23,7 @@ enum token_kind postfix_member_calling_convention = TOK_EOF; enum token_kind parsed_calling_convention = TOK_EOF; struct vector vec_dllexports = { 0 }; +struct vector vec_dllaliases = { 0 }; int parsed_dllexport = 0; int parsed_dllimport = 0; @@ -68,6 +69,8 @@ int declarator_noreturn = 0; int declarator_dllexport = 0; int declarator_dllimport = 0; +char declarator_alias_target[512] = { 0 }; + enum token_kind declarator_calling_convention = TOK_EOF; int global_initializer_accept_symbol_addresses = 0; @@ -122,6 +125,24 @@ int is_string_token (void) { return tok.kind == TOK_PPSTR || tok.kind == TOK_LSTR; } +void record_dllalias (const char *name, const char *target, int dllexport) { + + struct dll_alias_entry *entry; + + if (!name || !*name || !target || !*target) { + return; + } + + entry = xmalloc (sizeof (*entry)); + + entry->name = xstrdup (name); + entry->target = xstrdup (target); + + entry->dllexport = dllexport; + vec_push (&vec_dllaliases, entry); + +} + int expect (enum token_kind k, const char *what) { if (tok.kind == k) { @@ -443,6 +464,62 @@ static void skip_attribute_arguments (void) { } +static int parse_alias_attribute_argument (void) { + + const char *s; + size_t len; + + if (!_accept (TOK_LPAREN)) { + + report_line_at (get_filename (), get_line_number (), REPORT_ERROR, tok.report_start, tok.report_caret, "expected '(' after 'alias'"); + return 0; + + } + + if (!is_string_token () || !tok.ident || tok.kind == TOK_LSTR) { + + report_line_at (get_filename (), get_line_number (), REPORT_ERROR, tok.report_start, tok.report_caret, "expected string literal in 'alias' attribute"); + + skip_attribute_arguments (); + return 0; + + } + + s = tok.ident; + len = strlen (s); + + if (len < 2 || s[0] != '"' || s[len - 1] != '"') { + + report_line_at (get_filename (), get_line_number (), REPORT_ERROR, tok.report_start, tok.report_caret, "invalid string literal in 'alias' attribute"); + + get_token (); + expect (TOK_RPAREN, ")"); + + return 0; + + } + + if (len - 2 >= sizeof (declarator_alias_target)) { + + report_line_at (get_filename (), get_line_number (), REPORT_ERROR, tok.report_start, tok.report_caret, "alias target name is too long"); + + get_token (); + expect (TOK_RPAREN, ")"); + + return 0; + + } + + memcpy (declarator_alias_target, s + 1, len - 2); + declarator_alias_target[len - 2] = '\0'; + + get_token (); + + expect (TOK_RPAREN, ")"); + return 1; + +} + static void apply_decl_attribute (const char *spelling, int is_gnu) { if (attribute_name_is (spelling, "dllexport")) { @@ -555,12 +632,18 @@ static void parse_decl_modifier (void) { } else { name = xstrdup (tok.ident); - - apply_decl_attribute (name, 1); get_token (); - if (tok.kind == TOK_LPAREN) { - skip_attribute_arguments (); + if (attribute_name_is (name, "alias")) { + parse_alias_attribute_argument (); + } else { + + apply_decl_attribute (name, 1); + + if (tok.kind == TOK_LPAREN) { + skip_attribute_arguments (); + } + } free (name); @@ -741,12 +824,14 @@ void parse_declarator (char **out_name) { const char *saved_captured_declarator_name_caret = captured_declarator_name_caret; enum token_kind saved_declarator_calling_convention = declarator_calling_convention; + char saved_declarator_alias_target[sizeof declarator_alias_target]; int saved_declarator_dllexport = declarator_dllexport; int saved_declarator_dllimport = declarator_dllimport; int saved_declarator_noreturn = declarator_noreturn; unsigned long saved_captured_declarator_name_line = captured_declarator_name_line; + memcpy (saved_declarator_alias_target, declarator_alias_target, sizeof (declarator_alias_target)); if (top_level) { @@ -757,6 +842,8 @@ void parse_declarator (char **out_name) { declarator_calling_convention = TOK_EOF; capture_declarator_name_location = 1; + memcpy (declarator_alias_target, saved_declarator_alias_target, sizeof (declarator_alias_target)); + declarator_dllexport = 0; declarator_dllimport = 0; declarator_noreturn = 0; diff --git a/parse.h b/parse.h index edef0cb..75de67d 100644 --- a/parse.h +++ b/parse.h @@ -18,6 +18,14 @@ extern enum token_kind last_found_member_calling_convention; extern enum token_kind postfix_member_calling_convention; extern enum token_kind parsed_calling_convention; +struct dll_alias_entry { + + char *target, *name; + int dllexport; + +}; + +extern struct vector vec_dllaliases; extern struct vector vec_dllexports; extern int parsed_dllexport; @@ -59,6 +67,7 @@ extern int declarator_is_pointer; 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; @@ -102,6 +111,7 @@ int parse_constexpr_address_of_null_member (int64_s *out); int parse_cast_type_name (int *out_size, int *out_is_unsigned, int *out_is_pointer); int resolve_enum_constant (const char *name, int64_s *out); +void record_dllalias (const char *name, const char *target, int dllexport); #define DATA_CHAR (1 | (1 << 5)) #define DATA_SHORT (2 | (1 << 6))