@@ -109,6 +109,53 @@ aarch64_pe_valid_dllimport_attribute_p (const_tree decl)
109109 return true ;
110110}
111111
112+ /* Mark a function appropriately. This should only be called for
113+ functions for which we are not emitting COFF debugging information.
114+ FILE is the assembler output file, NAME is the name of the
115+ function, and PUB is nonzero if the function is globally
116+ visible. */
117+
118+ void
119+ aarch64_pe_declare_function_type (FILE *file, const char *name, int pub)
120+ {
121+ fprintf (file, " \t .def\t " );
122+ assemble_name (file, name);
123+ fprintf (file, " ;\t .scl\t %d;\t .type\t %d;\t .endef\n " ,
124+ pub ? (int ) C_EXT : (int ) C_STAT,
125+ (int ) DT_FCN << N_BTSHFT);
126+ }
127+
128+
129+
130+ /* Keep a list of external functions. */
131+
132+ struct GTY (()) extern_list
133+ {
134+ struct extern_list *next;
135+ tree decl;
136+ const char *name;
137+ };
138+
139+ static GTY (()) struct extern_list *extern_head;
140+
141+ /* Assemble an external function reference. We need to keep a list of
142+ these, so that we can output the function types at the end of the
143+ assembly. We can't output the types now, because we might see a
144+ definition of the function later on and emit debugging information
145+ for it then. */
146+
147+ void
148+ aarch64_pe_record_external_function (tree decl, const char *name)
149+ {
150+ struct extern_list *p;
151+
152+ p = ggc_alloc<extern_list> ();
153+ p->next = extern_head;
154+ p->decl = decl;
155+ p->name = name;
156+ extern_head = p;
157+ }
158+
112159/* Keep a list of exported symbols. */
113160
114161struct GTY (()) export_list
@@ -118,7 +165,16 @@ struct GTY(()) export_list
118165 int is_data; /* used to type tag exported symbols. */
119166};
120167
168+ /* Keep a list of stub symbols. */
169+
170+ struct GTY (()) stub_list
171+ {
172+ struct stub_list *next;
173+ const char *name;
174+ };
175+
121176static GTY (()) struct export_list *export_head;
177+ static GTY (()) struct stub_list *stub_head;
122178
123179/* Assemble an export symbol entry. We need to keep a list of
124180 these, so that we can output the export list at the end of the
@@ -150,22 +206,6 @@ aarch64_pe_maybe_record_exported_symbol (tree decl, const char *name, int is_dat
150206 export_head = p;
151207}
152208
153- /* Mark a function appropriately. This should only be called for
154- functions for which we are not emitting COFF debugging information.
155- FILE is the assembler output file, NAME is the name of the
156- function, and PUB is nonzero if the function is globally
157- visible. */
158-
159- void
160- aarch64_pe_declare_function_type (FILE *file, const char *name, int pub)
161- {
162- fprintf (file, " \t .def\t " );
163- assemble_name (file, name);
164- fprintf (file, " ;\t .scl\t %d;\t .type\t %d;\t .endef\n " ,
165- pub ? (int ) C_EXT : (int ) C_STAT,
166- (int ) DT_FCN << N_BTSHFT);
167- }
168-
169209/* Handle a "selectany" attribute;
170210 arguments as in struct attribute_spec.handler. */
171211tree
@@ -947,4 +987,150 @@ aarch64_pe_override_options (void)
947987 global_options.x_flag_shrink_wrap = false ;
948988}
949989
990+
991+ void
992+ aarch64_pe_record_stub (const char *name)
993+ {
994+ struct stub_list *p;
995+
996+ if (!name || *name == 0 )
997+ return ;
998+
999+ p = stub_head;
1000+ while (p != NULL )
1001+ {
1002+ if (p->name [0 ] == *name
1003+ && !strcmp (p->name , name))
1004+ return ;
1005+ p = p->next ;
1006+ }
1007+
1008+ p = ggc_alloc<stub_list> ();
1009+ p->next = stub_head;
1010+ p->name = name;
1011+ stub_head = p;
1012+ }
1013+
1014+
1015+ #ifdef CXX_WRAP_SPEC_LIST
1016+
1017+ /* Search for a function named TARGET in the list of library wrappers
1018+ we are using, returning a pointer to it if found or NULL if not.
1019+ This function might be called on quite a few symbols, and we only
1020+ have the list of names of wrapped functions available to us as a
1021+ spec string, so first time round we lazily initialise a hash table
1022+ to make things quicker. */
1023+
1024+ static const char *
1025+ aarch64_find_on_wrapper_list (const char *target)
1026+ {
1027+ static char first_time = 1 ;
1028+ static hash_table<nofree_string_hash> *wrappers;
1029+
1030+ if (first_time)
1031+ {
1032+ /* Beware that this is not a complicated parser, it assumes
1033+ that any sequence of non-whitespace beginning with an
1034+ underscore is one of the wrapped symbols. For now that's
1035+ adequate to distinguish symbols from spec substitutions
1036+ and command-line options. */
1037+ static char wrapper_list_buffer[] = CXX_WRAP_SPEC_LIST;
1038+ char *bufptr;
1039+ /* Breaks up the char array into separated strings
1040+ strings and enter them into the hash table. */
1041+ wrappers = new hash_table<nofree_string_hash> (8 );
1042+ for (bufptr = wrapper_list_buffer; *bufptr; ++bufptr)
1043+ {
1044+ char *found = NULL ;
1045+ if (ISSPACE (*bufptr))
1046+ continue ;
1047+ if (*bufptr == ' _' )
1048+ found = bufptr;
1049+ while (*bufptr && !ISSPACE (*bufptr))
1050+ ++bufptr;
1051+ if (*bufptr)
1052+ *bufptr = 0 ;
1053+ if (found)
1054+ *wrappers->find_slot (found, INSERT) = found;
1055+ }
1056+ first_time = 0 ;
1057+ }
1058+
1059+ return wrappers->find (target);
1060+ }
1061+
1062+ #endif /* CXX_WRAP_SPEC_LIST */
1063+
1064+ /* This is called at the end of assembly. For each external function
1065+ which has not been defined, we output a declaration now. We also
1066+ output the .drectve section. */
1067+
1068+ void
1069+ aarch64_pe_file_end (void )
1070+ {
1071+ struct extern_list *p;
1072+
1073+ for (p = extern_head; p != NULL ; p = p->next )
1074+ {
1075+ tree decl;
1076+
1077+ decl = p->decl ;
1078+
1079+ /* Positively ensure only one declaration for any given symbol. */
1080+ if (! TREE_ASM_WRITTEN (decl)
1081+ && TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)))
1082+ {
1083+ #ifdef CXX_WRAP_SPEC_LIST
1084+ /* To ensure the DLL that provides the corresponding real
1085+ functions is still loaded at runtime, we must reference
1086+ the real function so that an (unused) import is created. */
1087+ const char *realsym = aarch64_find_on_wrapper_list (p->name );
1088+ if (realsym)
1089+ aarch64_pe_declare_function_type (asm_out_file,
1090+ concat (" __real_" , realsym, NULL ), TREE_PUBLIC (decl));
1091+ #endif /* CXX_WRAP_SPEC_LIST */
1092+ TREE_ASM_WRITTEN (decl) = 1 ;
1093+ aarch64_pe_declare_function_type (asm_out_file, p->name ,
1094+ TREE_PUBLIC (decl));
1095+ }
1096+ }
1097+
1098+ if (export_head)
1099+ {
1100+ struct export_list *q;
1101+ drectve_section ();
1102+ for (q = export_head; q != NULL ; q = q->next )
1103+ {
1104+ fprintf (asm_out_file, " \t .ascii \" -export:\\\" %s\\\" %s\"\n " ,
1105+ default_strip_name_encoding (q->name ),
1106+ (q->is_data ? " ,data" : " " ));
1107+ }
1108+ }
1109+
1110+ if (stub_head)
1111+ {
1112+ struct stub_list *q;
1113+
1114+ for (q = stub_head; q != NULL ; q = q->next )
1115+ {
1116+ const char *name = q->name ;
1117+ const char *oname;
1118+
1119+ if (name[0 ] == ' *' )
1120+ ++name;
1121+ oname = name;
1122+ if (name[0 ] == ' .' )
1123+ ++name;
1124+ if (!startswith (name, " refptr." ))
1125+ continue ;
1126+ name += 7 ;
1127+ fprintf (asm_out_file, " \t .section\t .rdata$%s, \" dr\"\n "
1128+ " \t .globl\t %s\n "
1129+ " \t .align 3\n "
1130+ " \t .linkonce\t discard\n " , oname, oname);
1131+ fprintf (asm_out_file, " %s:\n\t .quad\t %s\n " , oname, name);
1132+ }
1133+ }
1134+ }
1135+
9501136#include " gt-winnt.h"
0 commit comments