00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #include "config.h"
00030 #include "system.h"
00031 #include "coretypes.h"
00032 #include "tm.h"
00033 #include "tree.h"
00034 #include "cp-tree.h"
00035 #include "input.h"
00036 #include "obstack.h"
00037 #include "toplev.h"
00038 #include "diagnostic.h"
00039
00040 static char *extract_string (char **);
00041 static const char *get_base_filename (const char *);
00042 static void open_repo_file (const char *);
00043 static char *afgets (FILE *);
00044 static void reopen_repo_file_for_write (void);
00045
00046 static GTY(()) tree pending_repo;
00047 static char *repo_name;
00048 static FILE *repo_file;
00049
00050 static const char *old_args, *old_dir, *old_main;
00051
00052 static struct obstack temporary_obstack;
00053 static bool temporary_obstack_initialized_p;
00054
00055
00056
00057 static char *
00058 extract_string (char **pp)
00059 {
00060 char *p = *pp;
00061 int backquote = 0;
00062 int inside = 0;
00063
00064 for (;;)
00065 {
00066 char c = *p;
00067 if (c == '\0')
00068 break;
00069 ++p;
00070 if (backquote)
00071 {
00072 obstack_1grow (&temporary_obstack, c);
00073 backquote = 0;
00074 }
00075 else if (! inside && c == ' ')
00076 break;
00077 else if (! inside && c == '\\')
00078 backquote = 1;
00079 else if (c == '\'')
00080 inside = !inside;
00081 else
00082 obstack_1grow (&temporary_obstack, c);
00083 }
00084
00085 obstack_1grow (&temporary_obstack, '\0');
00086 *pp = p;
00087 return obstack_finish (&temporary_obstack);
00088 }
00089
00090 static const char *
00091 get_base_filename (const char *filename)
00092 {
00093 char *p = getenv ("COLLECT_GCC_OPTIONS");
00094 char *output = NULL;
00095 int compiling = 0;
00096
00097 while (p && *p)
00098 {
00099 char *q = extract_string (&p);
00100
00101 if (strcmp (q, "-o") == 0)
00102 output = extract_string (&p);
00103 else if (strcmp (q, "-c") == 0)
00104 compiling = 1;
00105 }
00106
00107 if (compiling && output)
00108 return output;
00109
00110 if (p && ! compiling)
00111 {
00112 warning ("-frepo must be used with -c");
00113 flag_use_repository = 0;
00114 return NULL;
00115 }
00116
00117 return lbasename (filename);
00118 }
00119
00120 static void
00121 open_repo_file (const char *filename)
00122 {
00123 const char *p;
00124 const char *s = get_base_filename (filename);
00125
00126 if (s == NULL)
00127 return;
00128
00129 p = lbasename (s);
00130 p = strrchr (p, '.');
00131 if (! p)
00132 p = s + strlen (s);
00133
00134 repo_name = xmalloc (p - s + 5);
00135 memcpy (repo_name, s, p - s);
00136 memcpy (repo_name + (p - s), ".rpo", 5);
00137
00138 repo_file = fopen (repo_name, "r");
00139 }
00140
00141 static char *
00142 afgets (FILE *stream)
00143 {
00144 int c;
00145 while ((c = getc (stream)) != EOF && c != '\n')
00146 obstack_1grow (&temporary_obstack, c);
00147 if (obstack_object_size (&temporary_obstack) == 0)
00148 return NULL;
00149 obstack_1grow (&temporary_obstack, '\0');
00150 return obstack_finish (&temporary_obstack);
00151 }
00152
00153 void
00154 init_repo (void)
00155 {
00156 char *buf;
00157
00158 if (! flag_use_repository)
00159 return;
00160
00161
00162
00163
00164 lang_post_pch_load = init_repo;
00165
00166 if (!temporary_obstack_initialized_p)
00167 gcc_obstack_init (&temporary_obstack);
00168
00169 open_repo_file (main_input_filename);
00170
00171 if (repo_file == 0)
00172 return;
00173
00174 while ((buf = afgets (repo_file)))
00175 {
00176 switch (buf[0])
00177 {
00178 case 'A':
00179 old_args = ggc_strdup (buf + 2);
00180 break;
00181 case 'D':
00182 old_dir = ggc_strdup (buf + 2);
00183 break;
00184 case 'M':
00185 old_main = ggc_strdup (buf + 2);
00186 break;
00187 case 'O':
00188
00189
00190 break;
00191 case 'C':
00192
00193
00194 {
00195 tree id = get_identifier (buf + 2);
00196 IDENTIFIER_REPO_CHOSEN (id) = 1;
00197 }
00198 break;
00199 default:
00200 error ("mysterious repository information in %s", repo_name);
00201 }
00202 obstack_free (&temporary_obstack, buf);
00203 }
00204 fclose (repo_file);
00205 }
00206
00207 static void
00208 reopen_repo_file_for_write (void)
00209 {
00210 repo_file = fopen (repo_name, "w");
00211
00212 if (repo_file == 0)
00213 {
00214 error ("can't create repository information file %qs", repo_name);
00215 flag_use_repository = 0;
00216 }
00217 }
00218
00219
00220
00221 void
00222 finish_repo (void)
00223 {
00224 tree t;
00225 char *dir, *args;
00226
00227 if (!flag_use_repository)
00228 return;
00229
00230 if (errorcount || sorrycount)
00231 goto out;
00232
00233 reopen_repo_file_for_write ();
00234 if (repo_file == 0)
00235 goto out;
00236
00237 fprintf (repo_file, "M %s\n", main_input_filename);
00238 dir = getpwd ();
00239 fprintf (repo_file, "D %s\n", dir);
00240 args = getenv ("COLLECT_GCC_OPTIONS");
00241 if (args)
00242 fprintf (repo_file, "A %s\n", args);
00243
00244 for (t = pending_repo; t; t = TREE_CHAIN (t))
00245 {
00246 tree val = TREE_VALUE (t);
00247 tree name = DECL_ASSEMBLER_NAME (val);
00248 char type = IDENTIFIER_REPO_CHOSEN (name) ? 'C' : 'O';
00249 fprintf (repo_file, "%c %s\n", type, IDENTIFIER_POINTER (name));
00250 }
00251
00252 out:
00253 if (repo_file)
00254 fclose (repo_file);
00255 }
00256
00257
00258
00259
00260
00261
00262
00263
00264 int
00265 repo_emit_p (tree decl)
00266 {
00267 gcc_assert (TREE_PUBLIC (decl));
00268 gcc_assert (TREE_CODE (decl) == FUNCTION_DECL
00269 || TREE_CODE (decl) == VAR_DECL);
00270 gcc_assert (!DECL_REALLY_EXTERN (decl));
00271
00272
00273 if (!flag_use_repository)
00274 return 2;
00275
00276
00277
00278
00279
00280 if (TREE_CODE (decl) == VAR_DECL)
00281 {
00282 tree type = NULL_TREE;
00283 if (DECL_VTABLE_OR_VTT_P (decl))
00284 type = DECL_CONTEXT (decl);
00285 else if (DECL_TINFO_P (decl))
00286 type = TREE_TYPE (DECL_NAME (decl));
00287 if (!DECL_TEMPLATE_INSTANTIATION (decl)
00288 && (!TYPE_LANG_SPECIFIC (type)
00289 || !CLASSTYPE_TEMPLATE_INSTANTIATION (type)))
00290 return 2;
00291 }
00292 else if (!DECL_TEMPLATE_INSTANTIATION (decl))
00293 return 2;
00294
00295
00296
00297
00298 if (DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (decl)
00299 || DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (decl))
00300 {
00301 int emit_p = 0;
00302 tree clone;
00303
00304
00305
00306 FOR_EACH_CLONE (clone, decl)
00307
00308
00309 if (repo_emit_p (clone))
00310 emit_p = 1;
00311 return emit_p;
00312 }
00313
00314
00315 if (!DECL_REPO_AVAILABLE_P (decl))
00316 {
00317 DECL_REPO_AVAILABLE_P (decl) = 1;
00318 pending_repo = tree_cons (NULL_TREE, decl, pending_repo);
00319 }
00320
00321 return IDENTIFIER_REPO_CHOSEN (DECL_ASSEMBLER_NAME (decl));
00322 }
00323
00324
00325
00326
00327 bool
00328 repo_export_class_p (tree class_type)
00329 {
00330 if (!flag_use_repository)
00331 return false;
00332 if (!CLASSTYPE_VTABLES (class_type))
00333 return false;
00334
00335
00336 return (IDENTIFIER_REPO_CHOSEN
00337 (DECL_ASSEMBLER_NAME (CLASSTYPE_VTABLES (class_type))));
00338 }
00339
00340 #include "gt-cp-repo.h"