12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408 |
- /* 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;
- 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);
- }
- /* 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);
- }
- /* 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);
- }
- }
- 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);
- }
- 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;
- }
|