123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769 |
- /* Top level of GCC compilers (cc1, cc1plus, etc.)
- Copyright (C) 1987-2021 Free Software Foundation, Inc.
- This file is part of GCC.
- GCC is free software; you can redistribute it and/or modify it under
- the terms of the GNU General Public License as published by the Free
- Software Foundation; either version 3, or (at your option) any later
- version.
- GCC is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- for more details.
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING3. If not see
- <http://www.gnu.org/licenses/>. */
- /* This is the top level of cc1/c++.
- It parses command args, opens files, invokes the various passes
- in the proper order, and counts the time used by each.
- Error messages and low-level interface to malloc also handled here. */
- #include "config.h"
- #include "system.h"
- #include "coretypes.h"
- #include "backend.h"
- #include "target.h"
- #include "rtl.h"
- #include "tree.h"
- #include "gimple.h"
- #include "alloc-pool.h"
- #include "timevar.h"
- #include "memmodel.h"
- #include "tm_p.h"
- #include "optabs-libfuncs.h"
- #include "insn-config.h"
- #include "ira.h"
- #include "recog.h"
- #include "cgraph.h"
- #include "coverage.h"
- #include "diagnostic.h"
- #include "varasm.h"
- #include "tree-inline.h"
- #include "realmpfr.h" /* For GMP/MPFR/MPC versions, in print_version. */
- #include "version.h"
- #include "flags.h"
- #include "insn-attr.h"
- #include "output.h"
- #include "toplev.h"
- #include "expr.h"
- #include "intl.h"
- #include "tree-diagnostic.h"
- #include "reload.h"
- #include "lra.h"
- #include "dwarf2asm.h"
- #include "debug.h"
- #include "common/common-target.h"
- #include "langhooks.h"
- #include "cfgloop.h" /* for init_set_costs */
- #include "hosthooks.h"
- #include "opts.h"
- #include "opts-diagnostic.h"
- #include "stringpool.h"
- #include "attribs.h"
- #include "asan.h"
- #include "tsan.h"
- #include "plugin.h"
- #include "context.h"
- #include "pass_manager.h"
- #include "auto-profile.h"
- #include "dwarf2out.h"
- #include "ipa-reference.h"
- #include "symbol-summary.h"
- #include "tree-vrp.h"
- #include "ipa-prop.h"
- #include "gcse.h"
- #include "omp-offload.h"
- #include "edit-context.h"
- #include "tree-pass.h"
- #include "dumpfile.h"
- #include "ipa-fnsummary.h"
- #include "dump-context.h"
- #include "print-tree.h"
- #include "optinfo-emit-json.h"
- #include "ipa-modref-tree.h"
- #include "ipa-modref.h"
- #include "dbgcnt.h"
- #if defined(DBX_DEBUGGING_INFO) || defined(XCOFF_DEBUGGING_INFO)
- #include "dbxout.h"
- #endif
- #ifdef XCOFF_DEBUGGING_INFO
- #include "xcoffout.h" /* Needed for external data declarations. */
- #endif
- #include "selftest.h"
- #ifdef HAVE_isl
- #include <isl/version.h>
- #endif
- static void general_init (const char *, bool);
- static void do_compile ();
- static void process_options (void);
- static void backend_init (void);
- static int lang_dependent_init (const char *);
- static void init_asm_output (const char *);
- static void finalize (bool);
- static void crash_signal (int) ATTRIBUTE_NORETURN;
- static void compile_file (void);
- /* True if we don't need a backend (e.g. preprocessing only). */
- static bool no_backend;
- /* Decoded options, and number of such options. */
- struct cl_decoded_option *save_decoded_options;
- unsigned int save_decoded_options_count;
- /* Used to enable -fvar-tracking, -fweb and -frename-registers according
- to optimize in process_options (). */
- #define AUTODETECT_VALUE 2
- /* Debug hooks - dependent upon command line options. */
- const struct gcc_debug_hooks *debug_hooks;
- /* The FUNCTION_DECL for the function currently being compiled,
- or 0 if between functions. */
- tree current_function_decl;
- /* Set to the FUNC_BEGIN label of the current function, or NULL
- if none. */
- const char * current_function_func_begin_label;
- /* A random sequence of characters, unless overridden by user. */
- static const char *flag_random_seed;
- /* A local time stamp derived from the time of compilation. It will be
- zero if the system cannot provide a time. It will be -1u, if the
- user has specified a particular random seed. */
- unsigned local_tick;
- /* Random number for this compilation */
- HOST_WIDE_INT random_seed;
- /* -f flags. */
- /* When non-NULL, indicates that whenever space is allocated on the
- stack, the resulting stack pointer must not pass this
- address---that is, for stacks that grow downward, the stack pointer
- must always be greater than or equal to this address; for stacks
- that grow upward, the stack pointer must be less than this address.
- At present, the rtx may be either a REG or a SYMBOL_REF, although
- the support provided depends on the backend. */
- rtx stack_limit_rtx;
- class target_flag_state default_target_flag_state;
- #if SWITCHABLE_TARGET
- class target_flag_state *this_target_flag_state = &default_target_flag_state;
- #else
- #define this_target_flag_state (&default_target_flag_state)
- #endif
- /* The user symbol prefix after having resolved same. */
- const char *user_label_prefix;
- /* Output files for assembler code (real compiler output)
- and debugging dumps. */
- FILE *asm_out_file;
- FILE *aux_info_file;
- FILE *callgraph_info_file = NULL;
- /*
- * added
- */
- #include "sfg.c"
- FILE *svg_callgraph_info_file = NULL;
- FILE *gv_callgraph_info_file = NULL;
- #include "splay-tree.h"
- /* edge info */
- struct svg_callgraph_edge
- {
- int fn; /* id of from node */
- int tn; /* id of to node */
- };
- /* node id to node text */
- static splay_tree svg_callgraph_tree_nodes = NULL;
- /* nodes count */
- static int svg_callgraph_tree_nodes_count = 0;
- /* helper to delete the (char *)value string which was strdup()'ed */
- static void svg_callgraph_tree_nodes_delete_value (splay_tree_value val)
- {
- if (val) {
- free ((void *) val);
- }
- return;
- }
- /* node id to node text */
- static splay_tree svg_callgraph_tree_edges = NULL;
- /* edge counter */
- static int svg_callgraph_tree_edges_count = 0;
- /* helper to delete the (char *)value string which was strdup()'ed */
- static void svg_callgraph_tree_edges_delete_value (splay_tree_value val)
- {
- if (val) {
- free ((void *) val);
- }
- return;
- }
- /*
- * end added
- */
- static bitmap callgraph_info_external_printed;
- FILE *stack_usage_file = NULL;
- /* The current working directory of a translation. It's generally the
- directory from which compilation was initiated, but a preprocessed
- file may specify the original directory in which it was
- created. */
- static const char *src_pwd;
- /* Initialize src_pwd with the given string, and return true. If it
- was already initialized, return false. As a special case, it may
- be called with a NULL argument to test whether src_pwd has NOT been
- initialized yet. */
- bool
- set_src_pwd (const char *pwd)
- {
- if (src_pwd)
- {
- if (strcmp (src_pwd, pwd) == 0)
- return true;
- else
- return false;
- }
- src_pwd = xstrdup (pwd);
- return true;
- }
- /* Return the directory from which the translation unit was initiated,
- in case set_src_pwd() was not called before to assign it a
- different value. */
- const char *
- get_src_pwd (void)
- {
- if (! src_pwd)
- {
- src_pwd = getpwd ();
- if (!src_pwd)
- src_pwd = ".";
- }
- return src_pwd;
- }
- /* Called when the start of a function definition is parsed,
- this function prints on stderr the name of the function. */
- void
- announce_function (tree decl)
- {
- if (!quiet_flag)
- {
- if (rtl_dump_and_exit)
- fprintf (stderr, "%s ",
- identifier_to_locale (IDENTIFIER_POINTER (DECL_NAME (decl))));
- else
- fprintf (stderr, " %s",
- identifier_to_locale (lang_hooks.decl_printable_name (decl, 2)));
- fflush (stderr);
- pp_needs_newline (global_dc->printer) = true;
- diagnostic_set_last_function (global_dc, (diagnostic_info *) NULL);
- }
- }
- /* Initialize local_tick with the time of day, or -1 if
- flag_random_seed is set. */
- static void
- init_local_tick (void)
- {
- if (!flag_random_seed)
- {
- #ifdef HAVE_GETTIMEOFDAY
- {
- struct timeval tv;
- gettimeofday (&tv, NULL);
- local_tick = (unsigned) tv.tv_sec * 1000 + tv.tv_usec / 1000;
- }
- #else
- {
- time_t now = time (NULL);
- if (now != (time_t)-1)
- local_tick = (unsigned) now;
- }
- #endif
- }
- else
- local_tick = -1;
- }
- /* Obtain the random_seed. Unless NOINIT, initialize it if
- it's not provided in the command line. */
- HOST_WIDE_INT
- get_random_seed (bool noinit)
- {
- if (!random_seed && !noinit)
- {
- int fd = open ("/dev/urandom", O_RDONLY);
- if (fd >= 0)
- {
- if (read (fd, &random_seed, sizeof (random_seed))
- != sizeof (random_seed))
- random_seed = 0;
- close (fd);
- }
- if (!random_seed)
- random_seed = local_tick ^ getpid ();
- }
- return random_seed;
- }
- /* Set flag_random_seed to VAL, and if non-null, reinitialize random_seed. */
- void
- set_random_seed (const char *val)
- {
- flag_random_seed = val;
- if (flag_random_seed)
- {
- char *endp;
- /* When the driver passed in a hex number don't crc it again */
- random_seed = strtoul (flag_random_seed, &endp, 0);
- if (!(endp > flag_random_seed && *endp == 0))
- random_seed = crc32_string (0, flag_random_seed);
- }
- }
- /* Handler for fatal signals, such as SIGSEGV. These are transformed
- into ICE messages, which is much more user friendly. In case the
- error printer crashes, reset the signal to prevent infinite recursion. */
- static void
- crash_signal (int signo)
- {
- signal (signo, SIG_DFL);
- /* If we crashed while processing an ASM statement, then be a little more
- graceful. It's most likely the user's fault. */
- if (this_is_asm_operands)
- {
- output_operand_lossage ("unrecoverable error");
- exit (FATAL_EXIT_CODE);
- }
- internal_error ("%s", strsignal (signo));
- }
- /* A subroutine of wrapup_global_declarations. We've come to the end of
- the compilation unit. All deferred variables should be undeferred,
- and all incomplete decls should be finalized. */
- void
- wrapup_global_declaration_1 (tree decl)
- {
- /* We're not deferring this any longer. Assignment is conditional to
- avoid needlessly dirtying PCH pages. */
- if (CODE_CONTAINS_STRUCT (TREE_CODE (decl), TS_DECL_WITH_VIS)
- && DECL_DEFER_OUTPUT (decl) != 0)
- DECL_DEFER_OUTPUT (decl) = 0;
- if (VAR_P (decl) && DECL_SIZE (decl) == 0)
- lang_hooks.finish_incomplete_decl (decl);
- }
- /* A subroutine of wrapup_global_declarations. Decide whether or not DECL
- needs to be output. Return true if it is output. */
- bool
- wrapup_global_declaration_2 (tree decl)
- {
- if (TREE_ASM_WRITTEN (decl) || DECL_EXTERNAL (decl)
- || (VAR_P (decl) && DECL_HAS_VALUE_EXPR_P (decl)))
- return false;
- /* Don't write out static consts, unless we still need them.
- We also keep static consts if not optimizing (for debugging),
- unless the user specified -fno-keep-static-consts.
- ??? They might be better written into the debug information.
- This is possible when using DWARF.
- A language processor that wants static constants to be always
- written out (even if it is not used) is responsible for
- calling rest_of_decl_compilation itself. E.g. the C front-end
- calls rest_of_decl_compilation from finish_decl.
- One motivation for this is that is conventional in some
- environments to write things like:
- static const char rcsid[] = "... version string ...";
- intending to force the string to be in the executable.
- A language processor that would prefer to have unneeded
- static constants "optimized away" would just defer writing
- them out until here. E.g. C++ does this, because static
- constants are often defined in header files.
- ??? A tempting alternative (for both C and C++) would be
- to force a constant to be written if and only if it is
- defined in a main file, as opposed to an include file. */
- if (VAR_P (decl) && TREE_STATIC (decl))
- {
- varpool_node *node;
- bool needed = true;
- node = varpool_node::get (decl);
- if (!node && flag_ltrans)
- needed = false;
- else if (node && node->definition)
- needed = false;
- else if (node && node->alias)
- needed = false;
- else if (!symtab->global_info_ready
- && (TREE_USED (decl)
- || TREE_USED (DECL_ASSEMBLER_NAME (decl))))
- /* needed */;
- else if (node && node->analyzed)
- /* needed */;
- else if (DECL_COMDAT (decl))
- needed = false;
- else if (TREE_READONLY (decl) && !TREE_PUBLIC (decl)
- && (optimize || !flag_keep_static_consts
- || DECL_ARTIFICIAL (decl)))
- needed = false;
- if (needed)
- {
- rest_of_decl_compilation (decl, 1, 1);
- return true;
- }
- }
- return false;
- }
- /* Do any final processing required for the declarations in VEC, of
- which there are LEN. We write out inline functions and variables
- that have been deferred until this point, but which are required.
- Returns nonzero if anything was put out. */
- bool
- wrapup_global_declarations (tree *vec, int len)
- {
- bool reconsider, output_something = false;
- int i;
- for (i = 0; i < len; i++)
- wrapup_global_declaration_1 (vec[i]);
- /* Now emit any global variables or functions that we have been
- putting off. We need to loop in case one of the things emitted
- here references another one which comes earlier in the list. */
- do
- {
- reconsider = false;
- for (i = 0; i < len; i++)
- reconsider |= wrapup_global_declaration_2 (vec[i]);
- if (reconsider)
- output_something = true;
- }
- while (reconsider);
- return output_something;
- }
- /* Compile an entire translation unit. Write a file of assembly
- output and various debugging dumps. */
- static void
- compile_file (void)
- {
- timevar_start (TV_PHASE_PARSING);
- timevar_push (TV_PARSE_GLOBAL);
- /* Parse entire file and generate initial debug information. */
- lang_hooks.parse_file ();
- timevar_pop (TV_PARSE_GLOBAL);
- timevar_stop (TV_PHASE_PARSING);
- if (flag_dump_locations)
- dump_location_info (stderr);
- /* Compilation is now finished except for writing
- what's left of the symbol table output. */
- if (flag_syntax_only || flag_wpa)
- return;
-
- /* Reset maximum_field_alignment, it can be adjusted by #pragma pack
- and this shouldn't influence any types built by the middle-end
- from now on (like gcov_info_type). */
- maximum_field_alignment = initial_max_fld_align * BITS_PER_UNIT;
- ggc_protect_identifiers = false;
- /* Run the actual compilation process. */
- if (!in_lto_p)
- {
- timevar_start (TV_PHASE_OPT_GEN);
- symtab->finalize_compilation_unit ();
- timevar_stop (TV_PHASE_OPT_GEN);
- }
- /* Perform any post compilation-proper parser cleanups and
- processing. This is currently only needed for the C++ parser,
- which can be hopefully cleaned up so this hook is no longer
- necessary. */
- if (lang_hooks.decls.post_compilation_parsing_cleanups)
- lang_hooks.decls.post_compilation_parsing_cleanups ();
- dump_context::get ().finish_any_json_writer ();
- if (seen_error ())
- return;
- timevar_start (TV_PHASE_LATE_ASM);
- /* Compilation unit is finalized. When producing non-fat LTO object, we are
- basically finished. */
- if ((in_lto_p && flag_incremental_link != INCREMENTAL_LINK_LTO)
- || !flag_lto || flag_fat_lto_objects)
- {
- /* File-scope initialization for AddressSanitizer. */
- if (flag_sanitize & SANITIZE_ADDRESS)
- asan_finish_file ();
- if (flag_sanitize & SANITIZE_THREAD)
- tsan_finish_file ();
- if (gate_hwasan ())
- hwasan_finish_file ();
- omp_finish_file ();
- output_shared_constant_pool ();
- output_object_blocks ();
- finish_tm_clone_pairs ();
- /* Write out any pending weak symbol declarations. */
- weak_finish ();
- /* This must be at the end before unwind and debug info.
- Some target ports emit PIC setup thunks here. */
- targetm.asm_out.code_end ();
- /* Do dbx symbols. */
- timevar_push (TV_SYMOUT);
- #if defined DWARF2_DEBUGGING_INFO || defined DWARF2_UNWIND_INFO
- dwarf2out_frame_finish ();
- #endif
- debuginfo_start ();
- (*debug_hooks->finish) (main_input_filename);
- debuginfo_stop ();
- timevar_pop (TV_SYMOUT);
- /* Output some stuff at end of file if nec. */
- dw2_output_indirect_constants ();
- /* Flush any pending external directives. */
- process_pending_assemble_externals ();
- }
- /* Let linker plugin know that this is a slim object and must be LTOed
- even when user did not ask for it. */
- if (flag_generate_lto && !flag_fat_lto_objects)
- {
- #if defined ASM_OUTPUT_ALIGNED_DECL_COMMON
- ASM_OUTPUT_ALIGNED_DECL_COMMON (asm_out_file, NULL_TREE, "__gnu_lto_slim",
- HOST_WIDE_INT_1U, 8);
- #elif defined ASM_OUTPUT_ALIGNED_COMMON
- ASM_OUTPUT_ALIGNED_COMMON (asm_out_file, "__gnu_lto_slim",
- HOST_WIDE_INT_1U, 8);
- #else
- ASM_OUTPUT_COMMON (asm_out_file, "__gnu_lto_slim",
- HOST_WIDE_INT_1U,
- HOST_WIDE_INT_1U);
- #endif
- }
- /* Attach a special .ident directive to the end of the file to identify
- the version of GCC which compiled this code. The format of the .ident
- string is patterned after the ones produced by native SVR4 compilers. */
- if (!flag_no_ident)
- {
- const char *pkg_version = "(GNU) ";
- char *ident_str;
- if (strcmp ("(GCC) ", pkgversion_string))
- pkg_version = pkgversion_string;
- ident_str = ACONCAT (("GCC: ", pkg_version, version_string, NULL));
- targetm.asm_out.output_ident (ident_str);
- }
- /* Auto profile finalization. */
- if (flag_auto_profile)
- end_auto_profile ();
- /* Invoke registered plugin callbacks. */
- invoke_plugin_callbacks (PLUGIN_FINISH_UNIT, NULL);
- /* This must be at the end. Some target ports emit end of file directives
- into the assembly file here, and hence we cannot output anything to the
- assembly file after this point. */
- targetm.asm_out.file_end ();
- timevar_stop (TV_PHASE_LATE_ASM);
- }
- /* Print version information to FILE.
- Each line begins with INDENT (for the case where FILE is the
- assembler output file).
- If SHOW_GLOBAL_STATE is true (for cc1 etc), we are within the compiler
- proper and can print pertinent state (e.g. params and plugins).
- If SHOW_GLOBAL_STATE is false (for use by libgccjit), we are outside the
- compiler, and we don't hold the mutex on the compiler's global state:
- we can't print params and plugins, since they might not be initialized,
- or might be being manipulated by a compile running in another
- thread. */
- void
- print_version (FILE *file, const char *indent, bool show_global_state)
- {
- static const char fmt1[] =
- #ifdef __GNUC__
- N_("%s%s%s %sversion %s (%s)\n%s\tcompiled by GNU C version %s, ")
- #else
- N_("%s%s%s %sversion %s (%s) compiled by CC, ")
- #endif
- ;
- static const char fmt2[] =
- N_("GMP version %s, MPFR version %s, MPC version %s, isl version %s\n");
- static const char fmt3[] =
- N_("%s%swarning: %s header version %s differs from library version %s.\n");
- static const char fmt4[] =
- N_("%s%sGGC heuristics: --param ggc-min-expand=%d --param ggc-min-heapsize=%d\n");
- #ifndef __VERSION__
- #define __VERSION__ "[?]"
- #endif
- fprintf (file,
- file == stderr ? _(fmt1) : fmt1,
- indent, *indent != 0 ? " " : "",
- lang_hooks.name, pkgversion_string, version_string, TARGET_NAME,
- indent, __VERSION__);
- /* We need to stringify the GMP macro values. Ugh, gmp_version has
- two string formats, "i.j.k" and "i.j" when k is zero. As of
- gmp-4.3.0, GMP always uses the 3 number format. */
- #define GCC_GMP_STRINGIFY_VERSION3(X) #X
- #define GCC_GMP_STRINGIFY_VERSION2(X) GCC_GMP_STRINGIFY_VERSION3 (X)
- #define GCC_GMP_VERSION_NUM(X,Y,Z) (((X) << 16L) | ((Y) << 8) | (Z))
- #define GCC_GMP_VERSION \
- GCC_GMP_VERSION_NUM(__GNU_MP_VERSION, __GNU_MP_VERSION_MINOR, __GNU_MP_VERSION_PATCHLEVEL)
- #if GCC_GMP_VERSION < GCC_GMP_VERSION_NUM(4,3,0) && __GNU_MP_VERSION_PATCHLEVEL == 0
- #define GCC_GMP_STRINGIFY_VERSION \
- GCC_GMP_STRINGIFY_VERSION2 (__GNU_MP_VERSION) "." \
- GCC_GMP_STRINGIFY_VERSION2 (__GNU_MP_VERSION_MINOR)
- #else
- #define GCC_GMP_STRINGIFY_VERSION \
- GCC_GMP_STRINGIFY_VERSION2 (__GNU_MP_VERSION) "." \
- GCC_GMP_STRINGIFY_VERSION2 (__GNU_MP_VERSION_MINOR) "." \
- GCC_GMP_STRINGIFY_VERSION2 (__GNU_MP_VERSION_PATCHLEVEL)
- #endif
- fprintf (file,
- file == stderr ? _(fmt2) : fmt2,
- GCC_GMP_STRINGIFY_VERSION, MPFR_VERSION_STRING, MPC_VERSION_STRING,
- #ifndef HAVE_isl
- "none"
- #else
- isl_version ()
- #endif
- );
- if (strcmp (GCC_GMP_STRINGIFY_VERSION, gmp_version))
- fprintf (file,
- file == stderr ? _(fmt3) : fmt3,
- indent, *indent != 0 ? " " : "",
- "GMP", GCC_GMP_STRINGIFY_VERSION, gmp_version);
- if (strcmp (MPFR_VERSION_STRING, mpfr_get_version ()))
- fprintf (file,
- file == stderr ? _(fmt3) : fmt3,
- indent, *indent != 0 ? " " : "",
- "MPFR", MPFR_VERSION_STRING, mpfr_get_version ());
- if (strcmp (MPC_VERSION_STRING, mpc_get_version ()))
- fprintf (file,
- file == stderr ? _(fmt3) : fmt3,
- indent, *indent != 0 ? " " : "",
- "MPC", MPC_VERSION_STRING, mpc_get_version ());
- if (show_global_state)
- {
- fprintf (file,
- file == stderr ? _(fmt4) : fmt4,
- indent, *indent != 0 ? " " : "",
- param_ggc_min_expand, param_ggc_min_heapsize);
- print_plugins_versions (file, indent);
- }
- }
- /* Open assembly code output file. Do this even if -fsyntax-only is
- on, because then the driver will have provided the name of a
- temporary file or bit bucket for us. NAME is the file specified on
- the command line, possibly NULL. */
- static void
- init_asm_output (const char *name)
- {
- if (name == NULL && asm_file_name == 0)
- asm_out_file = stdout;
- else
- {
- if (asm_file_name == 0)
- {
- int len = strlen (dump_base_name);
- char *dumpname = XNEWVEC (char, len + 6);
- memcpy (dumpname, dump_base_name, len + 1);
- strip_off_ending (dumpname, len);
- strcat (dumpname, ".s");
- asm_file_name = dumpname;
- }
- if (!strcmp (asm_file_name, "-"))
- asm_out_file = stdout;
- else if (!canonical_filename_eq (asm_file_name, name)
- || !strcmp (asm_file_name, HOST_BIT_BUCKET))
- asm_out_file = fopen (asm_file_name, "w");
- else
- /* Use UNKOWN_LOCATION to prevent gcc from printing the first
- line in the current file. */
- fatal_error (UNKNOWN_LOCATION,
- "input file %qs is the same as output file",
- asm_file_name);
- if (asm_out_file == 0)
- fatal_error (UNKNOWN_LOCATION,
- "cannot open %qs for writing: %m", asm_file_name);
- }
- if (!flag_syntax_only)
- {
- targetm.asm_out.file_start ();
- if (flag_record_gcc_switches)
- {
- if (targetm.asm_out.record_gcc_switches)
- {
- const char *str
- = gen_producer_string (lang_hooks.name,
- save_decoded_options,
- save_decoded_options_count);
- targetm.asm_out.record_gcc_switches (str);
- }
- else
- inform (UNKNOWN_LOCATION,
- "%<-frecord-gcc-switches%> is not supported by "
- "the current target");
- }
- if (flag_verbose_asm)
- {
- print_version (asm_out_file, ASM_COMMENT_START, true);
- fputs (ASM_COMMENT_START, asm_out_file);
- fputs (" options passed: ", asm_out_file);
- char *cmdline = gen_command_line_string (save_decoded_options,
- save_decoded_options_count);
- fputs (cmdline, asm_out_file);
- free (cmdline);
- fputc ('\n', asm_out_file);
- }
- }
- }
- /* A helper function; used as the reallocator function for cpp's line
- table. */
- static void *
- realloc_for_line_map (void *ptr, size_t len)
- {
- return ggc_realloc (ptr, len);
- }
- /* A helper function: used as the allocator function for
- identifier_to_locale. */
- static void *
- alloc_for_identifier_to_locale (size_t len)
- {
- return ggc_alloc_atomic (len);
- }
- /* Output stack usage information. */
- static void
- output_stack_usage_1 (FILE *cf)
- {
- static bool warning_issued = false;
- enum stack_usage_kind_type { STATIC = 0, DYNAMIC, DYNAMIC_BOUNDED };
- const char *stack_usage_kind_str[] = {
- "static",
- "dynamic",
- "dynamic,bounded"
- };
- HOST_WIDE_INT stack_usage = current_function_static_stack_size;
- enum stack_usage_kind_type stack_usage_kind;
- if (stack_usage < 0)
- {
- if (!warning_issued)
- {
- warning (0, "stack usage computation not supported for this target");
- warning_issued = true;
- }
- return;
- }
- stack_usage_kind = STATIC;
- /* Add the maximum amount of space pushed onto the stack. */
- if (maybe_ne (current_function_pushed_stack_size, 0))
- {
- HOST_WIDE_INT extra;
- if (current_function_pushed_stack_size.is_constant (&extra))
- {
- stack_usage += extra;
- stack_usage_kind = DYNAMIC_BOUNDED;
- }
- else
- {
- extra = constant_lower_bound (current_function_pushed_stack_size);
- stack_usage += extra;
- stack_usage_kind = DYNAMIC;
- }
- }
- /* Now on to the tricky part: dynamic stack allocation. */
- if (current_function_allocates_dynamic_stack_space)
- {
- if (stack_usage_kind != DYNAMIC)
- {
- if (current_function_has_unbounded_dynamic_stack_size)
- stack_usage_kind = DYNAMIC;
- else
- stack_usage_kind = DYNAMIC_BOUNDED;
- }
- /* Add the size even in the unbounded case, this can't hurt. */
- stack_usage += current_function_dynamic_stack_size;
- }
- if (cf && flag_callgraph_info & CALLGRAPH_INFO_STACK_USAGE)
- fprintf (cf, "\\n" HOST_WIDE_INT_PRINT_DEC " bytes (%s)",
- stack_usage,
- stack_usage_kind_str[stack_usage_kind]);
- if (stack_usage_file)
- {
- print_decl_identifier (stack_usage_file, current_function_decl,
- PRINT_DECL_ORIGIN | PRINT_DECL_NAME);
- fprintf (stack_usage_file, "\t" HOST_WIDE_INT_PRINT_DEC"\t%s\n",
- stack_usage, stack_usage_kind_str[stack_usage_kind]);
- }
- if (warn_stack_usage >= 0 && warn_stack_usage < HOST_WIDE_INT_MAX)
- {
- const location_t loc = DECL_SOURCE_LOCATION (current_function_decl);
- if (stack_usage_kind == DYNAMIC)
- warning_at (loc, OPT_Wstack_usage_, "stack usage might be unbounded");
- else if (stack_usage > warn_stack_usage)
- {
- if (stack_usage_kind == DYNAMIC_BOUNDED)
- warning_at (loc,
- OPT_Wstack_usage_, "stack usage might be %wu bytes",
- stack_usage);
- else
- warning_at (loc, OPT_Wstack_usage_, "stack usage is %wu bytes",
- stack_usage);
- }
- }
- }
- /* Dump placeholder node for indirect calls in VCG format. */
- #define INDIRECT_CALL_NAME "__indirect_call"
- static void
- dump_final_node_vcg_start (FILE *f, tree decl)
- {
- fputs ("node: { title: \"", f);
- if (decl) {
- print_decl_identifier (f, decl, PRINT_DECL_UNIQUE_NAME);
- } else {
- fputs (INDIRECT_CALL_NAME, f);
- }
- fputs ("\" label: \"", f);
- if (decl)
- {
- print_decl_identifier (f, decl, PRINT_DECL_NAME);
- fputs ("\\n", f);
- print_decl_identifier (f, decl, PRINT_DECL_ORIGIN);
- }
- else {
- fputs ("Indirect Call Placeholder", f);
- }
- /*
- * added
- */
- {
- const char *name = NULL;
- const char *name2 = NULL;
- int nodeid = 0;
- splay_tree_node spn = NULL;
- /* get uniq node name */
- if (decl) {
- name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
- if (!TREE_PUBLIC (decl)
- || (DECL_WEAK (decl) && !DECL_EXTERNAL (decl))) {
- /* The symbol has internal or weak linkage so its assembler name
- is not necessarily unique among the compilation units of the
- program. We therefore have to further mangle it. But we can't
- simply use DECL_SOURCE_FILE because it contains the name of the
- file the symbol originates from so, e.g. for function templates
- in C++ where the templates are defined in a header file, we can
- have symbols with the same assembler name and DECL_SOURCE_FILE.
- That's why we use the name of the top-level source file of the
- compilation unit. ??? Unnecessary for Ada. */
- name = ACONCAT ((main_input_filename, ":", name, NULL));
- }
- nodeid = DECL_UID (decl);
- if (0) printf("--> node \"%s\" has id %d\n",name,nodeid);
- name2 = xstrdup (name);
- spn = splay_tree_insert (svg_callgraph_tree_nodes, (splay_tree_key) nodeid, (splay_tree_value) name2);
- if (spn) {
- svg_callgraph_tree_nodes_count++;
- }
- } else {
- /* node has no decl, it is indirect call name and skipped */
- }
- /*
- * end added
- */
- }
- return;
- }
- /* Dump final cgraph edge in VCG format. */
- static void
- dump_final_callee_vcg (FILE *f, location_t location, tree callee)
- {
- if ((!callee || DECL_EXTERNAL (callee))
- && bitmap_set_bit (callgraph_info_external_printed,
- callee ? DECL_UID (callee) + 1 : 0))
- {
- dump_final_node_vcg_start (f, callee);
- fputs ("\" shape : ellipse }\n", f);
- }
- fputs ("edge: { sourcename: \"", f);
- print_decl_identifier (f, current_function_decl, PRINT_DECL_UNIQUE_NAME);
- fputs ("\" targetname: \"", f);
- if (callee)
- print_decl_identifier (f, callee, PRINT_DECL_UNIQUE_NAME);
- else
- fputs (INDIRECT_CALL_NAME, f);
- if (LOCATION_LOCUS (location) != UNKNOWN_LOCATION)
- {
- expanded_location loc;
- fputs ("\" label: \"", f);
- loc = expand_location (location);
- fprintf (f, "%s:%d:%d", loc.file, loc.line, loc.column);
- }
- fputs ("\" }\n", f);
- /*
- * added
- */
- {
- struct svg_callgraph_edge *newedge = NULL;
- int fid = 0;
- int tid = 0;
- splay_tree_node spn = NULL;
- if (callee) {
- /* add edge to splay tree starting with edge number 1 */
- // newedge = (struct svg_callgraph_edge *) xmalloc (sizeof (struct svg_callgraph_edge));
- newedge = (struct svg_callgraph_edge *) XCNEW (struct svg_callgraph_edge);
- if (newedge) {
- fid = DECL_UID (current_function_decl);
- tid = DECL_UID (callee);
- if (0) printf("--> edge %d to %d\n", fid, tid );
- svg_callgraph_tree_edges_count++;
- newedge->fn = (int) fid;
- newedge->tn = (int) tid;
- spn = splay_tree_insert (svg_callgraph_tree_edges, (splay_tree_key) svg_callgraph_tree_edges_count, (splay_tree_value) newedge);
- if (spn) {
- }
- newedge = NULL;
- }
- } else {
- /* indirect routines are omitted */
- }
- }
- /*
- * end added
- */
- return;
- }
- /* Dump final cgraph node in VCG format. */
- static void
- dump_final_node_vcg (FILE *f)
- {
- dump_final_node_vcg_start (f, current_function_decl);
- if (flag_stack_usage_info
- || (flag_callgraph_info & CALLGRAPH_INFO_STACK_USAGE))
- output_stack_usage_1 (f);
- if (flag_callgraph_info & CALLGRAPH_INFO_DYNAMIC_ALLOC)
- {
- fprintf (f, "\\n%u dynamic objects", vec_safe_length (cfun->su->dallocs));
- unsigned i;
- callinfo_dalloc *cda;
- FOR_EACH_VEC_SAFE_ELT (cfun->su->dallocs, i, cda)
- {
- expanded_location loc = expand_location (cda->location);
- fprintf (f, "\\n %s", cda->name);
- fprintf (f, " %s:%d:%d", loc.file, loc.line, loc.column);
- }
- vec_free (cfun->su->dallocs);
- cfun->su->dallocs = NULL;
- }
- fputs ("\" }\n", f);
- unsigned i;
- callinfo_callee *c;
- FOR_EACH_VEC_SAFE_ELT (cfun->su->callees, i, c)
- dump_final_callee_vcg (f, c->location, c->decl);
- vec_free (cfun->su->callees);
- cfun->su->callees = NULL;
- }
- /* Output stack usage and callgraph info, as requested. */
- void
- output_stack_usage (void)
- {
- if (flag_callgraph_info)
- dump_final_node_vcg (callgraph_info_file);
- else
- output_stack_usage_1 (NULL);
- }
- /* Open an auxiliary output file. */
- static FILE *
- open_auxiliary_file (const char *ext)
- {
- char *filename;
- FILE *file;
- filename = concat (aux_base_name, ".", ext, NULL);
- file = fopen (filename, "w");
- if (!file)
- fatal_error (input_location, "cannot open %s for writing: %m", filename);
- free (filename);
- return file;
- }
- /* Alternative diagnostics callback for reentered ICE reporting. */
- static void
- internal_error_reentered (diagnostic_context *, const char *, va_list *)
- {
- /* Flush the dump file if emergency_dump_function itself caused an ICE. */
- if (dump_file)
- fflush (dump_file);
- }
- /* Auxiliary callback for the diagnostics code. */
- static void
- internal_error_function (diagnostic_context *, const char *, va_list *)
- {
- global_dc->internal_error = internal_error_reentered;
- warn_if_plugins ();
- emergency_dump_function ();
- }
- /* Initialization of the front end environment, before command line
- options are parsed. Signal handlers, internationalization etc.
- ARGV0 is main's argv[0]. */
- static void
- general_init (const char *argv0, bool init_signals)
- {
- const char *p;
- p = argv0 + strlen (argv0);
- while (p != argv0 && !IS_DIR_SEPARATOR (p[-1]))
- --p;
- progname = p;
- xmalloc_set_program_name (progname);
- hex_init ();
- /* Unlock the stdio streams. */
- unlock_std_streams ();
- gcc_init_libintl ();
- identifier_to_locale_alloc = alloc_for_identifier_to_locale;
- identifier_to_locale_free = ggc_free;
- /* Initialize the diagnostics reporting machinery, so option parsing
- can give warnings and errors. */
- diagnostic_initialize (global_dc, N_OPTS);
- global_dc->lang_mask = lang_hooks.option_lang_mask ();
- /* Set a default printer. Language specific initializations will
- override it later. */
- tree_diagnostics_defaults (global_dc);
- global_dc->show_caret
- = global_options_init.x_flag_diagnostics_show_caret;
- global_dc->show_labels_p
- = global_options_init.x_flag_diagnostics_show_labels;
- global_dc->show_line_numbers_p
- = global_options_init.x_flag_diagnostics_show_line_numbers;
- global_dc->show_cwe
- = global_options_init.x_flag_diagnostics_show_cwe;
- global_dc->path_format
- = (enum diagnostic_path_format)global_options_init.x_flag_diagnostics_path_format;
- global_dc->show_path_depths
- = global_options_init.x_flag_diagnostics_show_path_depths;
- global_dc->show_option_requested
- = global_options_init.x_flag_diagnostics_show_option;
- global_dc->min_margin_width
- = global_options_init.x_diagnostics_minimum_margin_width;
- global_dc->show_column
- = global_options_init.x_flag_show_column;
- global_dc->internal_error = internal_error_function;
- global_dc->option_enabled = option_enabled;
- global_dc->option_state = &global_options;
- global_dc->option_name = option_name;
- global_dc->get_option_url = get_option_url;
- if (init_signals)
- {
- /* Trap fatal signals, e.g. SIGSEGV, and convert them to ICE messages. */
- #ifdef SIGSEGV
- signal (SIGSEGV, crash_signal);
- #endif
- #ifdef SIGILL
- signal (SIGILL, crash_signal);
- #endif
- #ifdef SIGBUS
- signal (SIGBUS, crash_signal);
- #endif
- #ifdef SIGABRT
- signal (SIGABRT, crash_signal);
- #endif
- #if defined SIGIOT && (!defined SIGABRT || SIGABRT != SIGIOT)
- signal (SIGIOT, crash_signal);
- #endif
- #ifdef SIGFPE
- signal (SIGFPE, crash_signal);
- #endif
- /* Other host-specific signal setup. */
- (*host_hooks.extra_signals)();
- }
- /* Initialize the garbage-collector, string pools and tree type hash
- table. */
- init_ggc ();
- init_stringpool ();
- input_location = UNKNOWN_LOCATION;
- line_table = ggc_alloc<line_maps> ();
- linemap_init (line_table, BUILTINS_LOCATION);
- line_table->reallocator = realloc_for_line_map;
- line_table->round_alloc_size = ggc_round_alloc_size;
- line_table->default_range_bits = 5;
- init_ttree ();
- /* Initialize register usage now so switches may override. */
- init_reg_sets ();
- /* Create the singleton holder for global state. This creates the
- dump manager. */
- g = new gcc::context ();
- /* Allow languages and middle-end to register their dumps before the
- optimization passes. */
- g->get_dumps ()->register_dumps ();
- /* Create the passes. */
- g->set_passes (new gcc::pass_manager (g));
- symtab = new (ggc_alloc <symbol_table> ()) symbol_table ();
- statistics_early_init ();
- debuginfo_early_init ();
- }
- /* Return true if the current target supports -fsection-anchors. */
- static bool
- target_supports_section_anchors_p (void)
- {
- if (targetm.min_anchor_offset == 0 && targetm.max_anchor_offset == 0)
- return false;
- if (targetm.asm_out.output_anchor == NULL)
- return false;
- return true;
- }
- /* Parse "N[:M][:...]" into struct align_flags A.
- VALUES contains parsed values (in reverse order), all processed
- values are popped. */
- static void
- read_log_maxskip (auto_vec<unsigned> &values, align_flags_tuple *a)
- {
- unsigned n = values.pop ();
- if (n != 0)
- a->log = floor_log2 (n * 2 - 1);
- if (values.is_empty ())
- a->maxskip = n ? n - 1 : 0;
- else
- {
- unsigned m = values.pop ();
- /* -falign-foo=N:M means M-1 max bytes of padding, not M. */
- if (m > 0)
- m--;
- a->maxskip = m;
- }
- /* Normalize the tuple. */
- a->normalize ();
- }
- /* Parse "N[:M[:N2[:M2]]]" string FLAG into a pair of struct align_flags. */
- static void
- parse_N_M (const char *flag, align_flags &a)
- {
- if (flag)
- {
- static hash_map <nofree_string_hash, align_flags> cache;
- align_flags *entry = cache.get (flag);
- if (entry)
- {
- a = *entry;
- return;
- }
- auto_vec<unsigned> result_values;
- bool r = parse_and_check_align_values (flag, NULL, result_values, false,
- UNKNOWN_LOCATION);
- if (!r)
- return;
- /* Reverse values for easier manipulation. */
- result_values.reverse ();
- read_log_maxskip (result_values, &a.levels[0]);
- if (!result_values.is_empty ())
- read_log_maxskip (result_values, &a.levels[1]);
- #ifdef SUBALIGN_LOG
- else
- {
- /* N2[:M2] is not specified. This arch has a default for N2.
- Before -falign-foo=N:M:N2:M2 was introduced, x86 had a tweak.
- -falign-functions=N with N > 8 was adding secondary alignment.
- -falign-functions=10 was emitting this before every function:
- .p2align 4,,9
- .p2align 3
- Now this behavior (and more) can be explicitly requested:
- -falign-functions=16:10:8
- Retain old behavior if N2 is missing: */
- int align = 1 << a.levels[0].log;
- int subalign = 1 << SUBALIGN_LOG;
- if (a.levels[0].log > SUBALIGN_LOG
- && a.levels[0].maxskip >= subalign - 1)
- {
- /* Set N2 unless subalign can never have any effect. */
- if (align > a.levels[0].maxskip + 1)
- {
- a.levels[1].log = SUBALIGN_LOG;
- a.levels[1].normalize ();
- }
- }
- }
- #endif
- /* Cache seen value. */
- cache.put (flag, a);
- }
- }
- /* Process -falign-foo=N[:M[:N2[:M2]]] options. */
- void
- parse_alignment_opts (void)
- {
- parse_N_M (str_align_loops, align_loops);
- parse_N_M (str_align_jumps, align_jumps);
- parse_N_M (str_align_labels, align_labels);
- parse_N_M (str_align_functions, align_functions);
- }
- /* Process the options that have been parsed. */
- static void
- process_options (void)
- {
- /* Just in case lang_hooks.post_options ends up calling a debug_hook.
- This can happen with incorrect pre-processed input. */
- debug_hooks = &do_nothing_debug_hooks;
- maximum_field_alignment = initial_max_fld_align * BITS_PER_UNIT;
- /* Allow the front end to perform consistency checks and do further
- initialization based on the command line options. This hook also
- sets the original filename if appropriate (e.g. foo.i -> foo.c)
- so we can correctly initialize debug output. */
- no_backend = lang_hooks.post_options (&main_input_filename);
- /* Some machines may reject certain combinations of options. */
- location_t saved_location = input_location;
- input_location = UNKNOWN_LOCATION;
- targetm.target_option.override ();
- input_location = saved_location;
- if (flag_diagnostics_generate_patch)
- global_dc->edit_context_ptr = new edit_context ();
- /* Avoid any informative notes in the second run of -fcompare-debug. */
- if (flag_compare_debug)
- diagnostic_inhibit_notes (global_dc);
- if (flag_section_anchors && !target_supports_section_anchors_p ())
- {
- warning_at (UNKNOWN_LOCATION, OPT_fsection_anchors,
- "this target does not support %qs",
- "-fsection-anchors");
- flag_section_anchors = 0;
- }
- if (flag_short_enums == 2)
- flag_short_enums = targetm.default_short_enums ();
- /* Set aux_base_name if not already set. */
- if (aux_base_name)
- ;
- else if (dump_base_name)
- {
- const char *name = dump_base_name;
- int nlen, len;
- if (dump_base_ext && (len = strlen (dump_base_ext))
- && (nlen = strlen (name)) && nlen > len
- && strcmp (name + nlen - len, dump_base_ext) == 0)
- {
- char *p = xstrndup (name, nlen - len);
- name = p;
- }
- aux_base_name = name;
- }
- else
- aux_base_name = "gccaux";
- #ifndef HAVE_isl
- if (flag_graphite
- || flag_loop_nest_optimize
- || flag_graphite_identity
- || flag_loop_parallelize_all)
- sorry ("Graphite loop optimizations cannot be used (isl is not available) "
- "(%<-fgraphite%>, %<-fgraphite-identity%>, "
- "%<-floop-nest-optimize%>, %<-floop-parallelize-all%>)");
- #endif
- if (flag_cf_protection != CF_NONE
- && !(flag_cf_protection & CF_SET))
- {
- if (flag_cf_protection == CF_FULL)
- {
- error_at (UNKNOWN_LOCATION,
- "%<-fcf-protection=full%> is not supported for this "
- "target");
- flag_cf_protection = CF_NONE;
- }
- if (flag_cf_protection == CF_BRANCH)
- {
- error_at (UNKNOWN_LOCATION,
- "%<-fcf-protection=branch%> is not supported for this "
- "target");
- flag_cf_protection = CF_NONE;
- }
- if (flag_cf_protection == CF_RETURN)
- {
- error_at (UNKNOWN_LOCATION,
- "%<-fcf-protection=return%> is not supported for this "
- "target");
- flag_cf_protection = CF_NONE;
- }
- }
- /* One region RA really helps to decrease the code size. */
- if (flag_ira_region == IRA_REGION_AUTODETECT)
- flag_ira_region
- = optimize_size || !optimize ? IRA_REGION_ONE : IRA_REGION_MIXED;
- if (!abi_version_at_least (2))
- {
- /* -fabi-version=1 support was removed after GCC 4.9. */
- error_at (UNKNOWN_LOCATION,
- "%<-fabi-version=1%> is no longer supported");
- flag_abi_version = 2;
- }
- /* web and rename-registers help when run after loop unrolling. */
- if (flag_web == AUTODETECT_VALUE)
- flag_web = flag_unroll_loops;
- if (flag_rename_registers == AUTODETECT_VALUE)
- flag_rename_registers = flag_unroll_loops;
- if (flag_non_call_exceptions)
- flag_asynchronous_unwind_tables = 1;
- if (flag_asynchronous_unwind_tables)
- flag_unwind_tables = 1;
- if (flag_value_profile_transformations)
- flag_profile_values = 1;
- /* Warn about options that are not supported on this machine. */
- #ifndef INSN_SCHEDULING
- if (flag_schedule_insns || flag_schedule_insns_after_reload)
- warning_at (UNKNOWN_LOCATION, 0,
- "instruction scheduling not supported on this target machine");
- #endif
- if (!DELAY_SLOTS && flag_delayed_branch)
- warning_at (UNKNOWN_LOCATION, 0,
- "this target machine does not have delayed branches");
- user_label_prefix = USER_LABEL_PREFIX;
- if (flag_leading_underscore != -1)
- {
- /* If the default prefix is more complicated than "" or "_",
- issue a warning and ignore this option. */
- if (user_label_prefix[0] == 0 ||
- (user_label_prefix[0] == '_' && user_label_prefix[1] == 0))
- {
- user_label_prefix = flag_leading_underscore ? "_" : "";
- }
- else
- warning_at (UNKNOWN_LOCATION, 0,
- "%<-f%sleading-underscore%> not supported on this "
- "target machine", flag_leading_underscore ? "" : "no-");
- }
- /* If we are in verbose mode, write out the version and maybe all the
- option flags in use. */
- if (version_flag)
- {
- print_version (stderr, "", true);
- if (!quiet_flag)
- {
- fputs ("options passed: ", stderr);
- char *cmdline = gen_command_line_string (save_decoded_options,
- save_decoded_options_count);
- fputs (cmdline, stderr);
- free (cmdline);
- fputc ('\n', stderr);
- }
- }
- if (flag_syntax_only)
- {
- write_symbols = NO_DEBUG;
- profile_flag = 0;
- }
- if (flag_gtoggle)
- {
- if (debug_info_level == DINFO_LEVEL_NONE)
- {
- debug_info_level = DINFO_LEVEL_NORMAL;
- if (write_symbols == NO_DEBUG)
- write_symbols = PREFERRED_DEBUGGING_TYPE;
- }
- else
- debug_info_level = DINFO_LEVEL_NONE;
- }
- if (flag_dump_final_insns && !flag_syntax_only && !no_backend)
- {
- FILE *final_output = fopen (flag_dump_final_insns, "w");
- if (!final_output)
- {
- error_at (UNKNOWN_LOCATION,
- "could not open final insn dump file %qs: %m",
- flag_dump_final_insns);
- flag_dump_final_insns = NULL;
- }
- else if (fclose (final_output))
- {
- error_at (UNKNOWN_LOCATION,
- "could not close zeroed insn dump file %qs: %m",
- flag_dump_final_insns);
- flag_dump_final_insns = NULL;
- }
- }
- /* A lot of code assumes write_symbols == NO_DEBUG if the debugging
- level is 0. */
- if (debug_info_level == DINFO_LEVEL_NONE)
- write_symbols = NO_DEBUG;
- if (write_symbols == NO_DEBUG)
- ;
- #if defined(DBX_DEBUGGING_INFO)
- else if (write_symbols == DBX_DEBUG)
- debug_hooks = &dbx_debug_hooks;
- #endif
- #if defined(XCOFF_DEBUGGING_INFO)
- else if (write_symbols == XCOFF_DEBUG)
- debug_hooks = &xcoff_debug_hooks;
- #endif
- #ifdef DWARF2_DEBUGGING_INFO
- else if (write_symbols == DWARF2_DEBUG)
- debug_hooks = &dwarf2_debug_hooks;
- #endif
- #ifdef VMS_DEBUGGING_INFO
- else if (write_symbols == VMS_DEBUG || write_symbols == VMS_AND_DWARF2_DEBUG)
- debug_hooks = &vmsdbg_debug_hooks;
- #endif
- #ifdef DWARF2_LINENO_DEBUGGING_INFO
- else if (write_symbols == DWARF2_DEBUG)
- debug_hooks = &dwarf2_lineno_debug_hooks;
- #endif
- else
- error_at (UNKNOWN_LOCATION,
- "target system does not support the %qs debug format",
- debug_type_names[write_symbols]);
- /* We know which debug output will be used so we can set flag_var_tracking
- and flag_var_tracking_uninit if the user has not specified them. */
- if (debug_info_level < DINFO_LEVEL_NORMAL
- || debug_hooks->var_location == do_nothing_debug_hooks.var_location)
- {
- if (flag_var_tracking == 1
- || flag_var_tracking_uninit == 1)
- {
- if (debug_info_level < DINFO_LEVEL_NORMAL)
- warning_at (UNKNOWN_LOCATION, 0,
- "variable tracking requested, but useless unless "
- "producing debug info");
- else
- warning_at (UNKNOWN_LOCATION, 0,
- "variable tracking requested, but not supported "
- "by this debug format");
- }
- flag_var_tracking = 0;
- flag_var_tracking_uninit = 0;
- }
- /* The debug hooks are used to implement -fdump-go-spec because it
- gives a simple and stable API for all the information we need to
- dump. */
- if (flag_dump_go_spec != NULL)
- debug_hooks = dump_go_spec_init (flag_dump_go_spec, debug_hooks);
- /* If the user specifically requested variable tracking with tagging
- uninitialized variables, we need to turn on variable tracking.
- (We already determined above that variable tracking is feasible.) */
- if (flag_var_tracking_uninit == 1)
- flag_var_tracking = 1;
- if (flag_var_tracking == AUTODETECT_VALUE)
- flag_var_tracking = optimize >= 1;
- if (flag_var_tracking_uninit == AUTODETECT_VALUE)
- flag_var_tracking_uninit = flag_var_tracking;
- if (flag_var_tracking_assignments == AUTODETECT_VALUE)
- flag_var_tracking_assignments
- = (flag_var_tracking
- && !(flag_selective_scheduling || flag_selective_scheduling2));
- if (flag_var_tracking_assignments_toggle)
- flag_var_tracking_assignments = !flag_var_tracking_assignments;
- if (flag_var_tracking_assignments && !flag_var_tracking)
- flag_var_tracking = flag_var_tracking_assignments = -1;
- if (flag_var_tracking_assignments
- && (flag_selective_scheduling || flag_selective_scheduling2))
- warning_at (UNKNOWN_LOCATION, 0,
- "var-tracking-assignments changes selective scheduling");
- if (debug_nonbind_markers_p == AUTODETECT_VALUE)
- debug_nonbind_markers_p
- = (optimize
- && debug_info_level >= DINFO_LEVEL_NORMAL
- && (write_symbols == DWARF2_DEBUG
- || write_symbols == VMS_AND_DWARF2_DEBUG)
- && !(flag_selective_scheduling || flag_selective_scheduling2));
- if (dwarf2out_as_loc_support == AUTODETECT_VALUE)
- dwarf2out_as_loc_support
- = dwarf2out_default_as_loc_support ();
- if (dwarf2out_as_locview_support == AUTODETECT_VALUE)
- dwarf2out_as_locview_support
- = dwarf2out_default_as_locview_support ();
- if (debug_variable_location_views == AUTODETECT_VALUE)
- {
- debug_variable_location_views
- = (flag_var_tracking
- && debug_info_level >= DINFO_LEVEL_NORMAL
- && (write_symbols == DWARF2_DEBUG
- || write_symbols == VMS_AND_DWARF2_DEBUG)
- && !dwarf_strict
- && dwarf2out_as_loc_support
- && dwarf2out_as_locview_support);
- }
- else if (debug_variable_location_views == -1 && dwarf_version != 5)
- {
- warning_at (UNKNOWN_LOCATION, 0,
- "without %<-gdwarf-5%>, "
- "%<-gvariable-location-views=incompat5%> "
- "is equivalent to %<-gvariable-location-views%>");
- debug_variable_location_views = 1;
- }
- if (debug_internal_reset_location_views == 2)
- {
- debug_internal_reset_location_views
- = (debug_variable_location_views
- && targetm.reset_location_view);
- }
- else if (debug_internal_reset_location_views
- && !debug_variable_location_views)
- {
- warning_at (UNKNOWN_LOCATION, 0,
- "%<-ginternal-reset-location-views%> is forced disabled "
- "without %<-gvariable-location-views%>");
- debug_internal_reset_location_views = 0;
- }
- if (debug_inline_points == AUTODETECT_VALUE)
- debug_inline_points = debug_variable_location_views;
- else if (debug_inline_points && !debug_nonbind_markers_p)
- {
- warning_at (UNKNOWN_LOCATION, 0,
- "%<-ginline-points%> is forced disabled without "
- "%<-gstatement-frontiers%>");
- debug_inline_points = 0;
- }
- if (flag_tree_cselim == AUTODETECT_VALUE)
- {
- if (HAVE_conditional_move)
- flag_tree_cselim = 1;
- else
- flag_tree_cselim = 0;
- }
- /* If auxiliary info generation is desired, open the output file.
- This goes in the same directory as the source file--unlike
- all the other output files. */
- if (flag_gen_aux_info)
- {
- aux_info_file = fopen (aux_info_file_name, "w");
- if (aux_info_file == 0)
- fatal_error (UNKNOWN_LOCATION,
- "cannot open %s: %m", aux_info_file_name);
- }
- if (!targetm_common.have_named_sections)
- {
- if (flag_function_sections)
- {
- warning_at (UNKNOWN_LOCATION, 0,
- "%<-ffunction-sections%> not supported for this target");
- flag_function_sections = 0;
- }
- if (flag_data_sections)
- {
- warning_at (UNKNOWN_LOCATION, 0,
- "%<-fdata-sections%> not supported for this target");
- flag_data_sections = 0;
- }
- }
- if (flag_prefetch_loop_arrays > 0 && !targetm.code_for_prefetch)
- {
- warning_at (UNKNOWN_LOCATION, 0,
- "%<-fprefetch-loop-arrays%> not supported for this target");
- flag_prefetch_loop_arrays = 0;
- }
- else if (flag_prefetch_loop_arrays > 0 && !targetm.have_prefetch ())
- {
- warning_at (UNKNOWN_LOCATION, 0,
- "%<-fprefetch-loop-arrays%> not supported for this target "
- "(try %<-march%> switches)");
- flag_prefetch_loop_arrays = 0;
- }
- /* This combination of options isn't handled for i386 targets and doesn't
- make much sense anyway, so don't allow it. */
- if (flag_prefetch_loop_arrays > 0 && optimize_size)
- {
- warning_at (UNKNOWN_LOCATION, 0,
- "%<-fprefetch-loop-arrays%> is not supported with %<-Os%>");
- flag_prefetch_loop_arrays = 0;
- }
- /* The presence of IEEE signaling NaNs, implies all math can trap. */
- if (flag_signaling_nans)
- flag_trapping_math = 1;
- /* We cannot reassociate if we want traps or signed zeros. */
- if (flag_associative_math && (flag_trapping_math || flag_signed_zeros))
- {
- warning_at (UNKNOWN_LOCATION, 0,
- "%<-fassociative-math%> disabled; other options take "
- "precedence");
- flag_associative_math = 0;
- }
- /* -fstack-clash-protection is not currently supported on targets
- where the stack grows up. */
- if (flag_stack_clash_protection && !STACK_GROWS_DOWNWARD)
- {
- warning_at (UNKNOWN_LOCATION, 0,
- "%<-fstack-clash-protection%> is not supported on targets "
- "where the stack grows from lower to higher addresses");
- flag_stack_clash_protection = 0;
- }
- /* We cannot support -fstack-check= and -fstack-clash-protection at
- the same time. */
- if (flag_stack_check != NO_STACK_CHECK && flag_stack_clash_protection)
- {
- warning_at (UNKNOWN_LOCATION, 0,
- "%<-fstack-check=%> and %<-fstack-clash_protection%> are "
- "mutually exclusive; disabling %<-fstack-check=%>");
- flag_stack_check = NO_STACK_CHECK;
- }
- /* With -fcx-limited-range, we do cheap and quick complex arithmetic. */
- if (flag_cx_limited_range)
- flag_complex_method = 0;
- /* With -fcx-fortran-rules, we do something in-between cheap and C99. */
- if (flag_cx_fortran_rules)
- flag_complex_method = 1;
- /* Targets must be able to place spill slots at lower addresses. If the
- target already uses a soft frame pointer, the transition is trivial. */
- if (!FRAME_GROWS_DOWNWARD && flag_stack_protect)
- {
- warning_at (UNKNOWN_LOCATION, 0,
- "%<-fstack-protector%> not supported for this target");
- flag_stack_protect = 0;
- }
- if (!flag_stack_protect)
- warn_stack_protect = 0;
- /* Address Sanitizer needs porting to each target architecture. */
- if ((flag_sanitize & SANITIZE_ADDRESS)
- && !FRAME_GROWS_DOWNWARD)
- {
- warning_at (UNKNOWN_LOCATION, 0,
- "%<-fsanitize=address%> and %<-fsanitize=kernel-address%> "
- "are not supported for this target");
- flag_sanitize &= ~SANITIZE_ADDRESS;
- }
- if ((flag_sanitize & SANITIZE_USER_ADDRESS)
- && ((targetm.asan_shadow_offset == NULL)
- || (targetm.asan_shadow_offset () == 0)))
- {
- warning_at (UNKNOWN_LOCATION, 0,
- "%<-fsanitize=address%> not supported for this target");
- flag_sanitize &= ~SANITIZE_ADDRESS;
- }
- if ((flag_sanitize & SANITIZE_KERNEL_ADDRESS)
- && (targetm.asan_shadow_offset == NULL
- && !asan_shadow_offset_set_p ()))
- {
- warning_at (UNKNOWN_LOCATION, 0,
- "%<-fsanitize=kernel-address%> with stack protection "
- "is not supported without %<-fasan-shadow-offset=%> "
- "for this target");
- flag_sanitize &= ~SANITIZE_ADDRESS;
- }
- /* HWAsan requires top byte ignore feature in the backend. */
- if (flag_sanitize & SANITIZE_HWADDRESS
- && ! targetm.memtag.can_tag_addresses ())
- {
- warning_at (UNKNOWN_LOCATION, 0, "%qs is not supported for this target",
- "-fsanitize=hwaddress");
- flag_sanitize &= ~SANITIZE_HWADDRESS;
- }
- HOST_WIDE_INT patch_area_size, patch_area_start;
- parse_and_check_patch_area (flag_patchable_function_entry, false,
- &patch_area_size, &patch_area_start);
- /* Do not use IPA optimizations for register allocation if profiler is active
- or patchable function entries are inserted for run-time instrumentation
- or port does not emit prologue and epilogue as RTL. */
- if (profile_flag || patch_area_size
- || !targetm.have_prologue () || !targetm.have_epilogue ())
- flag_ipa_ra = 0;
- /* Enable -Werror=coverage-mismatch when -Werror and -Wno-error
- have not been set. */
- if (!global_options_set.x_warnings_are_errors
- && warn_coverage_mismatch
- && (global_dc->classify_diagnostic[OPT_Wcoverage_mismatch] ==
- DK_UNSPECIFIED))
- diagnostic_classify_diagnostic (global_dc, OPT_Wcoverage_mismatch,
- DK_ERROR, UNKNOWN_LOCATION);
- /* Save the current optimization options. */
- optimization_default_node
- = build_optimization_node (&global_options, &global_options_set);
- optimization_current_node = optimization_default_node;
- if (flag_checking >= 2)
- hash_table_sanitize_eq_limit
- = param_hash_table_verification_limit;
- if (flag_large_source_files)
- line_table->default_range_bits = 0;
- /* Please don't change global_options after this point, those changes won't
- be reflected in optimization_{default,current}_node. */
- }
- /* This function can be called multiple times to reinitialize the compiler
- back end when register classes or instruction sets have changed,
- before each function. */
- static void
- backend_init_target (void)
- {
- /* This depends on stack_pointer_rtx. */
- init_fake_stack_mems ();
- /* Sets static_base_value[HARD_FRAME_POINTER_REGNUM], which is
- mode-dependent. */
- init_alias_target ();
- /* Depends on HARD_FRAME_POINTER_REGNUM. */
- if (!ira_use_lra_p)
- init_reload ();
- /* Depends on the enabled attribute. */
- recog_init ();
- /* The following initialization functions need to generate rtl, so
- provide a dummy function context for them. */
- init_dummy_function_start ();
- /* rtx_cost is mode-dependent, so cached values need to be recomputed
- on a mode change. */
- init_expmed ();
- init_lower_subreg ();
- init_set_costs ();
- init_expr_target ();
- ira_init ();
- /* We may need to recompute regno_save_code[] and regno_restore_code[]
- after a mode change as well. */
- caller_save_initialized_p = false;
- expand_dummy_function_end ();
- }
- /* Initialize the compiler back end. This function is called only once,
- when starting the compiler. */
- static void
- backend_init (void)
- {
- init_emit_once ();
- init_rtlanal ();
- init_inline_once ();
- init_varasm_once ();
- save_register_info ();
- /* Middle end needs this initialization for default mem attributes
- used by early calls to make_decl_rtl. */
- init_emit_regs ();
- /* Middle end needs this initialization for mode tables used to assign
- modes to vector variables. */
- init_regs ();
- }
- /* Initialize things that are both lang-dependent and target-dependent.
- This function can be called more than once if target parameters change. */
- static void
- lang_dependent_init_target (void)
- {
- /* This creates various _DECL nodes, so needs to be called after the
- front end is initialized. It also depends on the HAVE_xxx macros
- generated from the target machine description. */
- init_optabs ();
- gcc_assert (!this_target_rtl->target_specific_initialized);
- }
- /* Perform initializations that are lang-dependent or target-dependent.
- but matters only for late optimizations and RTL generation. */
- static int rtl_initialized;
- void
- initialize_rtl (void)
- {
- auto_timevar tv (g_timer, TV_INITIALIZE_RTL);
- /* Initialization done just once per compilation, but delayed
- till code generation. */
- if (!rtl_initialized)
- ira_init_once ();
- rtl_initialized = true;
- /* Target specific RTL backend initialization. */
- if (!this_target_rtl->target_specific_initialized)
- {
- backend_init_target ();
- this_target_rtl->target_specific_initialized = true;
- }
- }
- /* Language-dependent initialization. Returns nonzero on success. */
- static int
- lang_dependent_init (const char *name)
- {
- location_t save_loc = input_location;
- if (!dump_base_name)
- {
- dump_base_name = name && name[0] ? name : "gccdump";
- /* We do not want to derive a non-empty dumpbase-ext from an
- explicit -dumpbase argument, only from a defaulted
- dumpbase. */
- if (!dump_base_ext)
- {
- const char *base = lbasename (dump_base_name);
- const char *ext = strrchr (base, '.');
- if (ext)
- dump_base_ext = ext;
- }
- }
- /* Other front-end initialization. */
- input_location = BUILTINS_LOCATION;
- if (lang_hooks.init () == 0)
- return 0;
- input_location = save_loc;
- if (!flag_wpa)
- {
- init_asm_output (name);
- if (!flag_generate_lto && !flag_compare_debug)
- {
- /* If stack usage information is desired, open the output file. */
- if (flag_stack_usage)
- stack_usage_file = open_auxiliary_file ("su");
- /* If call graph information is desired, open the output file. */
- if (flag_callgraph_info)
- {
- callgraph_info_file = open_auxiliary_file ("ci");
- /* Write the file header. */
- fprintf (callgraph_info_file,
- "graph: { title: \"%s\"\n", main_input_filename);
- bitmap_obstack_initialize (NULL);
- callgraph_info_external_printed = BITMAP_ALLOC (NULL);
- /*
- * added
- */
- {
- svg_callgraph_info_file = open_auxiliary_file ("callgraph-info.svg");
- svg_callgraph_tree_nodes = splay_tree_new (splay_tree_compare_ints, NULL, svg_callgraph_tree_nodes_delete_value);
- svg_callgraph_tree_edges = splay_tree_new (splay_tree_compare_ints, NULL, svg_callgraph_tree_edges_delete_value);
- gv_callgraph_info_file = open_auxiliary_file ("callgraph-info.gv");
- }
- /*
- * end added
- */
- }
- }
- else
- flag_stack_usage = flag_callgraph_info = false;
- }
- /* This creates various _DECL nodes, so needs to be called after the
- front end is initialized. */
- init_eh ();
- /* Do the target-specific parts of the initialization. */
- lang_dependent_init_target ();
- if (!flag_wpa)
- {
- /* If dbx symbol table desired, initialize writing it and output the
- predefined types. */
- timevar_push (TV_SYMOUT);
- /* Now we have the correct original filename, we can initialize
- debug output. */
- (*debug_hooks->init) (name);
- timevar_pop (TV_SYMOUT);
- }
- return 1;
- }
- /* Reinitialize everything when target parameters, such as register usage,
- have changed. */
- void
- target_reinit (void)
- {
- struct rtl_data saved_x_rtl;
- rtx *saved_regno_reg_rtx;
- tree saved_optimization_current_node;
- struct target_optabs *saved_this_fn_optabs;
- /* Temporarily switch to the default optimization node, so that
- *this_target_optabs is set to the default, not reflecting
- whatever a previous function used for the optimize
- attribute. */
- saved_optimization_current_node = optimization_current_node;
- saved_this_fn_optabs = this_fn_optabs;
- if (saved_optimization_current_node != optimization_default_node)
- {
- optimization_current_node = optimization_default_node;
- cl_optimization_restore
- (&global_options, &global_options_set,
- TREE_OPTIMIZATION (optimization_default_node));
- }
- this_fn_optabs = this_target_optabs;
- /* Save *crtl and regno_reg_rtx around the reinitialization
- to allow target_reinit being called even after prepare_function_start. */
- saved_regno_reg_rtx = regno_reg_rtx;
- if (saved_regno_reg_rtx)
- {
- saved_x_rtl = *crtl;
- memset (crtl, '\0', sizeof (*crtl));
- regno_reg_rtx = NULL;
- }
- this_target_rtl->target_specific_initialized = false;
- /* This initializes hard_frame_pointer, and calls init_reg_modes_target()
- to initialize reg_raw_mode[]. */
- init_emit_regs ();
- /* This invokes target hooks to set fixed_reg[] etc, which is
- mode-dependent. */
- init_regs ();
- /* Reinitialize lang-dependent parts. */
- lang_dependent_init_target ();
- /* Restore the original optimization node. */
- if (saved_optimization_current_node != optimization_default_node)
- {
- optimization_current_node = saved_optimization_current_node;
- cl_optimization_restore (&global_options, &global_options_set,
- TREE_OPTIMIZATION (optimization_current_node));
- }
- this_fn_optabs = saved_this_fn_optabs;
- /* Restore regno_reg_rtx at the end, as free_after_compilation from
- expand_dummy_function_end clears it. */
- if (saved_regno_reg_rtx)
- {
- *crtl = saved_x_rtl;
- regno_reg_rtx = saved_regno_reg_rtx;
- saved_regno_reg_rtx = NULL;
- }
- }
- void
- dump_memory_report (const char *header)
- {
- /* Print significant header. */
- fputc ('\n', stderr);
- for (unsigned i = 0; i < 80; i++)
- fputc ('#', stderr);
- fprintf (stderr, "\n# %-77s#\n", header);
- for (unsigned i = 0; i < 80; i++)
- fputc ('#', stderr);
- fputs ("\n\n", stderr);
- dump_line_table_statistics ();
- ggc_print_statistics ();
- stringpool_statistics ();
- dump_tree_statistics ();
- dump_gimple_statistics ();
- dump_rtx_statistics ();
- dump_alloc_pool_statistics ();
- dump_bitmap_statistics ();
- dump_hash_table_loc_statistics ();
- dump_vec_loc_statistics ();
- dump_ggc_loc_statistics ();
- dump_alias_stats (stderr);
- dump_pta_stats (stderr);
- }
- /* Clean up: close opened files, etc. */
- static void
- finalize (bool no_backend)
- {
- /* Close the dump files. */
- if (flag_gen_aux_info)
- {
- fclose (aux_info_file);
- aux_info_file = NULL;
- if (seen_error ())
- unlink (aux_info_file_name);
- }
- /* Close non-debugging input and output files. Take special care to note
- whether fclose returns an error, since the pages might still be on the
- buffer chain while the file is open. */
- if (asm_out_file)
- {
- if (ferror (asm_out_file) != 0)
- fatal_error (input_location, "error writing to %s: %m", asm_file_name);
- if (fclose (asm_out_file) != 0)
- fatal_error (input_location, "error closing %s: %m", asm_file_name);
- asm_out_file = NULL;
- }
- if (stack_usage_file)
- {
- fclose (stack_usage_file);
- stack_usage_file = NULL;
- }
- if (callgraph_info_file)
- {
- fputs ("}\n", callgraph_info_file);
- fclose (callgraph_info_file);
- callgraph_info_file = NULL;
- BITMAP_FREE (callgraph_info_external_printed);
- bitmap_obstack_release (NULL);
- /*
- * added
- */
- {
- int i = 0;
- int len = 0;
- int status = 0;
- int sfgmaxx = 0;
- int sfgmaxy = 0;
- int nmin = 0;
- int nmax = 0;
- int nxpos = 0;
- int nypos = 0;
- int nxsize = 0;
- int nysize = 0;
- char *ntext = NULL;
- int ef = 0;
- int et = 0;
- int eftype = 0;
- int ettype = 0;
- int efposx = 0;
- int etposx = 0;
- int efposy = 0;
- int etposy = 0;
- int svgxoff = 0;
- int svgyoff = 0;
- splay_tree_node spn = (splay_tree_node)0;
- splay_tree_key spnkey = (splay_tree_key)0;
- splay_tree_value spnvalue = (splay_tree_value)0;
- struct svg_callgraph_edge *callgraph_info_sce = (struct svg_callgraph_edge *)0;
- if (svg_callgraph_info_file) {
- if (svg_callgraph_tree_nodes_count) {
- /* init to start */
- status = sfg_init();
- if (status < 0) { /* error */
- }
- spn = splay_tree_min (svg_callgraph_tree_nodes);
- while (spn)
- {
- spnkey = spn->key;
- spnvalue = spn->value;
- len = (int) strlen ((char *) spnvalue);
- status = sfg_addnode((int)spnkey, (len*9), 15);
- spn = splay_tree_successor (svg_callgraph_tree_nodes, (splay_tree_key)spnkey);
- }
- if (svg_callgraph_tree_edges_count) {
- for (i = 0 ; i < (svg_callgraph_tree_edges_count + 1) ; i++)
- {
- spn = splay_tree_lookup (svg_callgraph_tree_edges, (splay_tree_key) i);
- if (spn) {
- callgraph_info_sce = (struct svg_callgraph_edge *) spn->value;
- status = sfg_addedge((int)spn->key, /* from */ callgraph_info_sce->fn, /* to */ callgraph_info_sce->tn, 0, 0);
- }
- }
- }
- /* set min (x,y) spacing of nodes */
- status = sfg_xspacing(5);
- if (status < 0) { /* error */
- }
- status = sfg_yspacing(15);
- if (status < 0) { /* error */
- }
- /* run layout */
- status = sfg_layout();
- if (status < 0) { /* error */
- }
- /* head of svg */
- sfgmaxx = sfg_maxx();
- if (sfgmaxx < 5) {
- sfgmaxx = 5;
- }
- sfgmaxy = sfg_maxy();
- if (sfgmaxy < 5) {
- sfgmaxy = 5;
- }
- svgxoff = 25;
- svgyoff = 25;
- sfgmaxx += (2 * svgxoff);
- sfgmaxy += (2 * svgyoff);
- fprintf(svg_callgraph_info_file, "<svg width=\"%d\" height=\"%d\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:svg=\"http://www.w3.org/2000/svg\">\n", sfgmaxx + 1, sfgmaxy + 5);
- fprintf(svg_callgraph_info_file, "%s\n", " <g>");
- fprintf(svg_callgraph_info_file, "%s\n", " <title>callgraph-info</title>");
- fprintf(svg_callgraph_info_file, "%s\n", " <style>");
- fprintf(svg_callgraph_info_file, "%s\n", " .small { font: italic 15px sans-serif; }");
- fprintf(svg_callgraph_info_file, "%s\n", " </style>");
- nmin = sfg_nodemin ();
- nmax = sfg_nodemax ();
- if (nmin > 0 && nmax > 0) { }
- if (svg_callgraph_tree_nodes_count) {
- /* draw edges */
- if (svg_callgraph_tree_edges_count) {
- for (i = 1 ; i < (svg_callgraph_tree_edges_count + 1) ; i++)
- {
- spn = splay_tree_lookup (svg_callgraph_tree_edges, (splay_tree_key) i);
- if (spn) {
- callgraph_info_sce = (struct svg_callgraph_edge *) spn->value;
- ef = callgraph_info_sce->fn;
- et = callgraph_info_sce->tn;
- eftype = sfg_nodetype (ef);
- ettype = sfg_nodetype (et);
- if(eftype > 0 && ettype > 0) {
- efposx = sfg_nodexpos (ef);
- efposy = sfg_nodeypos (ef);
- etposx = sfg_nodexpos (et);
- etposy = sfg_nodeypos (et);
- if (eftype == 1) {
- efposx += (sfg_nodexsize (ef) / 2);
- efposy += (sfg_nodeysize (ef) / 2);
- }
- if (ettype == 1) {
- etposx += (sfg_nodexsize (et) / 2);
- etposy += (sfg_nodeysize (et) / 2);
- }
- fprintf(svg_callgraph_info_file, " <line id=\"edge_%d\" y2=\"%d\" x2=\"%d\" y1=\"%d\" x1=\"%d\" stroke-linecap=\"null\" stroke-linejoin=\"null\" stroke-dasharray=\"null\" stroke-width=\"2\" stroke=\"#000000\" fill=\"none\"/>\n", i, etposy+svgyoff, etposx+svgxoff, efposy+svgyoff, efposx+svgxoff);
- }
- }
- }
- }
- /* draw nodes */
- i = 0;
- spn = splay_tree_min (svg_callgraph_tree_nodes);
- while (spn)
- {
- i++;
- spnkey = spn->key;
- spnvalue = spn->value;
- nxpos = sfg_nodexpos ((int)spnkey);
- nypos = sfg_nodeypos ((int)spnkey);
- nxsize = sfg_nodexsize ((int)spnkey);
- nysize = sfg_nodeysize ((int)spnkey);
- fprintf(svg_callgraph_info_file, " <rect id=\"node_%d\" x=\"%d\" y=\"%d\" width=\"%d\" height=\"%d\" stroke-linecap=\"null\" stroke-linejoin=\"null\" stroke-dasharray=\"null\" stroke=\"#000000\" fill=\"#7fff00\"/>\n", i, nxpos+svgxoff, nypos+svgyoff, nxsize, nysize);
- ntext = (char *) spn->value;
- if (strlen (ntext) > 0) {
- /* todo unesc special chars but can that happen with this data? */
- fprintf(svg_callgraph_info_file, " <text x=\"%d\" y=\"%d\" class=\"small\">%s</text>\n", nxpos+1+svgxoff, nypos+nysize+svgyoff-1, ntext);
- }
- spn = splay_tree_successor (svg_callgraph_tree_nodes, (splay_tree_key)spnkey);
- }
- }
- /* tail of svg */
- fprintf(svg_callgraph_info_file, "%s\n", " </g>");
- fprintf(svg_callgraph_info_file, "%s\n", "</svg>");
- }
- }
- if (gv_callgraph_info_file) {
- fprintf (gv_callgraph_info_file, "/* callgraph generated by GNU GCC Compiler -fcallgraph-info option version\n");
- print_version (gv_callgraph_info_file, " *", true);
- fprintf (gv_callgraph_info_file, "*/\n");
- fprintf (gv_callgraph_info_file, "digraph \"option-fcallgraph-info\" {\n");
- if (svg_callgraph_tree_nodes_count) {
- i = 0;
- spn = splay_tree_min (svg_callgraph_tree_nodes);
- while (spn)
- {
- i++;
- spnkey = spn->key;
- spnvalue = spn->value;
- fprintf (gv_callgraph_info_file, " \"%d\" [label=\"%s\"]; /* node %d */\n", (int)spnkey, (char *)spnvalue, i);
- spn = splay_tree_successor (svg_callgraph_tree_nodes, (splay_tree_key)spnkey);
- }
- }
- if (svg_callgraph_tree_edges_count) {
- for (i = 0 ; i < (svg_callgraph_tree_edges_count + 1) ; i++)
- {
- spn = splay_tree_lookup (svg_callgraph_tree_edges, (splay_tree_key) i);
- if (spn) {
- callgraph_info_sce = (struct svg_callgraph_edge *) spn->value;
- fprintf (gv_callgraph_info_file, " \"%d\" -> \"%d\"; /* edge %d */\n", callgraph_info_sce->fn, callgraph_info_sce->tn, i);
- }
- }
- }
- fprintf (gv_callgraph_info_file, "}\n");
- }
- if (gv_callgraph_info_file) {
- fclose (gv_callgraph_info_file);
- gv_callgraph_info_file = NULL;
- }
- if (svg_callgraph_info_file) {
- fclose (svg_callgraph_info_file);
- svg_callgraph_info_file = NULL;
- }
- if (svg_callgraph_tree_nodes) {
- splay_tree_delete (svg_callgraph_tree_nodes);
- svg_callgraph_tree_nodes = NULL;
- svg_callgraph_tree_nodes_count = 0;
- }
- if (svg_callgraph_tree_edges) {
- splay_tree_delete (svg_callgraph_tree_edges);
- svg_callgraph_tree_edges = NULL;
- svg_callgraph_tree_edges_count = 0;
- }
- /* ready with layouter */
- status = sfg_deinit ();
- if (status) { }
- }
- /*
- * end added
- */
- }
- if (seen_error ())
- coverage_remove_note_file ();
- if (!no_backend)
- {
- statistics_fini ();
- debuginfo_fini ();
- g->get_passes ()->finish_optimization_passes ();
- lra_finish_once ();
- }
- if (mem_report)
- dump_memory_report ("Final");
- if (profile_report)
- dump_profile_report ();
- if (flag_dbg_cnt_list)
- dbg_cnt_list_all_counters ();
- /* Language-specific end of compilation actions. */
- lang_hooks.finish ();
- }
- static bool
- standard_type_bitsize (int bitsize)
- {
- /* As a special exception, we always want __int128 enabled if possible. */
- if (bitsize == 128)
- return false;
- if (bitsize == CHAR_TYPE_SIZE
- || bitsize == SHORT_TYPE_SIZE
- || bitsize == INT_TYPE_SIZE
- || bitsize == LONG_TYPE_SIZE
- || bitsize == LONG_LONG_TYPE_SIZE)
- return true;
- return false;
- }
- /* Initialize the compiler, and compile the input file. */
- static void
- do_compile ()
- {
- process_options ();
- /* Don't do any more if an error has already occurred. */
- if (!seen_error ())
- {
- int i;
- timevar_start (TV_PHASE_SETUP);
- if (flag_save_optimization_record)
- {
- dump_context::get ().set_json_writer (new optrecord_json_writer ());
- }
- /* This must be run always, because it is needed to compute the FP
- predefined macros, such as __LDBL_MAX__, for targets using non
- default FP formats. */
- init_adjust_machine_modes ();
- init_derived_machine_modes ();
- /* This must happen after the backend has a chance to process
- command line options, but before the parsers are
- initialized. */
- for (i = 0; i < NUM_INT_N_ENTS; i ++)
- if (targetm.scalar_mode_supported_p (int_n_data[i].m)
- && ! standard_type_bitsize (int_n_data[i].bitsize))
- int_n_enabled_p[i] = true;
- else
- int_n_enabled_p[i] = false;
- /* Initialize mpfrs exponent range. This is important to get
- underflow/overflow in a reasonable timeframe. */
- machine_mode mode;
- int min_exp = -1;
- int max_exp = 1;
- FOR_EACH_MODE_IN_CLASS (mode, MODE_FLOAT)
- if (SCALAR_FLOAT_MODE_P (mode))
- {
- const real_format *fmt = REAL_MODE_FORMAT (mode);
- if (fmt)
- {
- /* fmt->emin - fmt->p + 1 should be enough but the
- back-and-forth dance in real_to_decimal_for_mode we
- do for checking fails due to rounding effects then. */
- if ((fmt->emin - fmt->p) < min_exp)
- min_exp = fmt->emin - fmt->p;
- if (fmt->emax > max_exp)
- max_exp = fmt->emax;
- }
- }
- /* E.g. mpc_norm assumes it can square a number without bothering with
- with range scaling, so until that is fixed, double the minimum
- and maximum exponents, plus add some buffer for arithmetics
- on the squared numbers. */
- if (mpfr_set_emin (2 * (min_exp - 1))
- || mpfr_set_emax (2 * (max_exp + 1)))
- sorry ("mpfr not configured to handle all floating modes");
- /* Set up the back-end if requested. */
- if (!no_backend)
- backend_init ();
- /* Language-dependent initialization. Returns true on success. */
- if (lang_dependent_init (main_input_filename))
- {
- /* Initialize yet another pass. */
- ggc_protect_identifiers = true;
- symtab->initialize ();
- init_final (main_input_filename);
- coverage_init (aux_base_name);
- statistics_init ();
- debuginfo_init ();
- invoke_plugin_callbacks (PLUGIN_START_UNIT, NULL);
- timevar_stop (TV_PHASE_SETUP);
- compile_file ();
- }
- else
- {
- timevar_stop (TV_PHASE_SETUP);
- }
- timevar_start (TV_PHASE_FINALIZE);
- finalize (no_backend);
- timevar_stop (TV_PHASE_FINALIZE);
- }
- }
- toplev::toplev (timer *external_timer,
- bool init_signals)
- : m_use_TV_TOTAL (external_timer == NULL),
- m_init_signals (init_signals)
- {
- if (external_timer)
- g_timer = external_timer;
- }
- toplev::~toplev ()
- {
- if (g_timer && m_use_TV_TOTAL)
- {
- g_timer->stop (TV_TOTAL);
- g_timer->print (stderr);
- delete g_timer;
- g_timer = NULL;
- }
- }
- /* Potentially call timevar_init (which will create g_timevars if it
- doesn't already exist). */
- void
- toplev::start_timevars ()
- {
- if (time_report || !quiet_flag || flag_detailed_statistics)
- timevar_init ();
- timevar_start (TV_TOTAL);
- }
- /* Handle -fself-test. */
- void
- toplev::run_self_tests ()
- {
- if (no_backend)
- {
- error_at (UNKNOWN_LOCATION, "self-tests incompatible with %<-E%>");
- return;
- }
- #if CHECKING_P
- /* Reset some state. */
- input_location = UNKNOWN_LOCATION;
- bitmap_obstack_initialize (NULL);
- /* Run the tests; any failures will lead to an abort of the process.
- Use "make selftests-gdb" to run under the debugger. */
- ::selftest::run_tests ();
- /* Cleanup. */
- bitmap_obstack_release (NULL);
- #else
- inform (UNKNOWN_LOCATION, "self-tests are not enabled in this build");
- #endif /* #if CHECKING_P */
- }
- /* Entry point of cc1, cc1plus, jc1, f771, etc.
- Exit code is FATAL_EXIT_CODE if can't open files or if there were
- any errors, or SUCCESS_EXIT_CODE if compilation succeeded.
- It is not safe to call this function more than once. */
- int
- toplev::main (int argc, char **argv)
- {
- /* Parsing and gimplification sometimes need quite large stack.
- Increase stack size limits if possible. */
- stack_limit_increase (64 * 1024 * 1024);
- expandargv (&argc, &argv);
- /* Initialization of GCC's environment, and diagnostics. */
- general_init (argv[0], m_init_signals);
- /* One-off initialization of options that does not need to be
- repeated when options are added for particular functions. */
- init_options_once ();
- init_opts_obstack ();
- /* Initialize global options structures; this must be repeated for
- each structure used for parsing options. */
- init_options_struct (&global_options, &global_options_set);
- lang_hooks.init_options_struct (&global_options);
- /* Init GGC heuristics must be caller after we initialize
- options. */
- init_ggc_heuristics ();
- /* Convert the options to an array. */
- decode_cmdline_options_to_array_default_mask (argc,
- CONST_CAST2 (const char **,
- char **, argv),
- &save_decoded_options,
- &save_decoded_options_count);
- /* Perform language-specific options initialization. */
- lang_hooks.init_options (save_decoded_options_count, save_decoded_options);
- /* Parse the options and do minimal processing; basically just
- enough to default flags appropriately. */
- decode_options (&global_options, &global_options_set,
- save_decoded_options, save_decoded_options_count,
- UNKNOWN_LOCATION, global_dc,
- targetm.target_option.override);
- handle_common_deferred_options ();
- init_local_tick ();
- initialize_plugins ();
- if (version_flag)
- print_version (stderr, "", true);
- if (help_flag)
- print_plugins_help (stderr, "");
- /* Exit early if we can (e.g. -help). */
- if (!exit_after_options)
- {
- if (m_use_TV_TOTAL)
- start_timevars ();
- do_compile ();
- }
- if (warningcount || errorcount || werrorcount)
- print_ignored_options ();
- if (flag_self_test)
- run_self_tests ();
- /* Invoke registered plugin callbacks if any. Some plugins could
- emit some diagnostics here. */
- invoke_plugin_callbacks (PLUGIN_FINISH, NULL);
- if (flag_diagnostics_generate_patch)
- {
- gcc_assert (global_dc->edit_context_ptr);
- pretty_printer pp;
- pp_show_color (&pp) = pp_show_color (global_dc->printer);
- global_dc->edit_context_ptr->print_diff (&pp, true);
- pp_flush (&pp);
- }
- diagnostic_finish (global_dc);
- finalize_plugins ();
- after_memory_report = true;
- if (seen_error () || werrorcount)
- return (FATAL_EXIT_CODE);
- return (SUCCESS_EXIT_CODE);
- }
- /* For those that want to, this function aims to clean up enough state that
- you can call toplev::main again. */
- void
- toplev::finalize (void)
- {
- rtl_initialized = false;
- this_target_rtl->target_specific_initialized = false;
- /* Needs to be called before cgraph_c_finalize since it uses symtab. */
- ipa_reference_c_finalize ();
- ipa_fnsummary_c_finalize ();
- ipa_modref_c_finalize ();
- cgraph_c_finalize ();
- cgraphunit_c_finalize ();
- symtab_thunks_cc_finalize ();
- dwarf2out_c_finalize ();
- gcse_c_finalize ();
- ipa_cp_c_finalize ();
- ira_costs_c_finalize ();
- /* save_decoded_options uses opts_obstack, so these must
- be cleaned up together. */
- obstack_free (&opts_obstack, NULL);
- XDELETEVEC (save_decoded_options);
- save_decoded_options = NULL;
- save_decoded_options_count = 0;
- /* Clean up the context (and pass_manager etc). */
- delete g;
- g = NULL;
- }
|