GCC-3.4.6源代码学习笔记(27)

3.3.4. 完成处理

当从handle_options符号时,decode_options相应地更新其他标识。flag_no_inlineflag_really_no_inline初始是2。如果合适,flag_no_inline将被common_handle_option 设为1(见该函数的1060行)。在下面,可以看到,如果内联是可能的,这2个变量均是0。而且如果optimize0flag_no_inline将是1,但flag_really_no_inline可能是0,以表示树内联器(tree inliner)关闭了内联;也可能是1,以表示内联由-fno-inline关闭。

 

decode_options (continue)

 

620      if (flag_pie)

621        flag_pic = flag_pie;

622      if (flag_pic && ! flag_pie)

623        flag_shlib = 1;

624   

625      if (flag_no_inline == 2)

626        flag_no_inline = 0;

627      else

628        flag_really_no_inline = flag_no_inline;

629   

630      /* Set flag_no_inline before the post_options () hook. The C front

631        ends use it to determine tree inlining defaults. FIXME: such

632        code should be lang-independent when all front ends use tree

633        inlining, in which case it, and this condition, should be moved

634        to the top of process_options() instead.  */

635      if (optimize == 0)

636      {

637        /* Inlining does not work if not optimizing,

638          so force it not to be done.  */

639        flag_no_inline = 1;

640        warn_inline = 0;

641   

642        /* The c_decode_option function and decode_option hook set

643          this to `2' if -Wall is used, so we can avoid giving out

644          lots of errors for people who don't realize what -Wall does.  */

645        if (warn_uninitialized == 1)

646          warning ("-Wuninitialized is not supported without -O");

647      }

648   

649      if (flag_really_no_inline == 2)

650        flag_really_no_inline = flag_no_inline;

651    }

4.        预备源码解析

decode_options完成编译选项处理后,回到toplev_main,接下来调用randomize初始化随机种子(random seeds)。进而,如果期望真正的编译,艰苦的工作由do_compile肇始。

 

4638 static void

4639 do_compile (void)                                                                                     in toplev.c

4640 {

4641   /* Initialize timing first. The C front ends read the main file in

4642     the post_options hook, and C++ does file timings.  */

4643   if (time_report || !quiet_flag  || flag_detailed_statistics)

4644     timevar_init ();

4645   timevar_start (TV_TOTAL);

4646

4647   process_options ();

4.1. 选项的后处理

虽然选项已由decode_options中的handle_options解析和记录,这里仍需要确认这些选项对于语言和目标平台是有效的。如果需要,还要进行调整。同时,还要根据这些选项设置编译器。

 

4271 static void

4272 process_options (void)                                                                                     in toplev.c

4273 {

4274   /* Just in case lang_hooks.post_options ends up calling a debug_hook.

4275     This can happen with incorrect pre-processed input. */

4276   debug_hooks = &do_nothing_debug_hooks;

4277

4278   /* Allow the front end to perform consistency checks and do further

4279     initialization based on the command line options. This hook also

4280     sets the original filename if appropriate (e.g. foo.i -> foo.c)

4281     so we can correctly initialize debug output.  */

4282   no_backend = (*lang_hooks.post_options) (&main_input_filename);

 

上面,在4276行,debug_hooksdo_nothing_debug_hooks都是gcc_debug_hooks类型,该类型包含了调试信息输出函数的构子。起初,debug_hooks设为do_nothing_debug_hooks,它是不作任何事的钩子。

4636行,lang_hooks的回调钩子post_options,对于C/C++,是c_common_post_options

 

1060 bool

1061 c_common_post_options (const char **pfilename)                                        in c-opts.c

1062 {

1063   struct cpp_callbacks *cb;

1064

1065   /* Canonicalize the input and output filenames.  */

1066   if (in_fnames == NULL)

1067   {

1068     in_fnames = xmalloc (sizeof (in_fnames[0]));

1069     in_fnames[0] = "";

1070   }

1071   else if (strcmp (in_fnames[0], "-") == 0)

1072     in_fnames[0] = "";

1073

1074   if (out_fname == NULL || !strcmp (out_fname, "-"))

1075     out_fname = "";

1076

1077   if (cpp_opts->deps.style == DEPS_NONE)

1078     check_deps_environment_vars ();

1079

1080   handle_deferred_opts ();

1081

1082   sanitize_cpp_opts ();

1083

1084   register_include_chains (parse_in, sysroot, iprefix,

1085                       std_inc, std_cxx_inc && c_dialect_cxx (), verbose);

 

CC++的编译单元是一个源文件加上相关的头文件,这些文件名及路径由命令行选项传入。在handle_options,在453行,in_frames保存了这些文件名。

而在1074行,out_frame持有由-o选项指定的输出文件名。

如果没有使用-dN-dM-dD-dI,就要检查环境变量DEPENDENCIES_OUTPUTSUNPRO_DEPENDENCIES

DEPENDENCIES_OUTPUT设置为一文件名,会导致预处理器把基于依赖的(dependency-basedmakefile规则至这个文件。但系统头文件名不包括在内。而对于SUNPRO_DEPENDENCIES,系统头文件亦被包括。如果这些环境变量被设为单个名字,它被认为是该输出文件名,而依赖规则的名字从源文件名获取。如果环境变量被设为2个名字,第二个名字即是依赖规则的目标名。设置这些环境变量的结果,等同于同时使用-MM-MF-MT

 

1296 static void

1297 check_deps_environment_vars (void)                                                          in c-opts.c

1298 {

1299   char *spec;

1300

1301   GET_ENVIRONMENT (spec, "DEPENDENCIES_OUTPUT");

1302   if (spec)

1303     cpp_opts->deps.style = DEPS_USER;

1304   else

1305   {

1306     GET_ENVIRONMENT (spec, "SUNPRO_DEPENDENCIES");

1307     if (spec)

1308     {

1309       cpp_opts->deps.style = DEPS_SYSTEM;

1310       cpp_opts->deps.ignore_main_file = true;

1311     }

1312   }

1313

1314   if (spec)

1315   {

1316     /* Find the space before the DEPS_TARGET, if there is one.  */

1317     char *s = strchr (spec, ' ');

1318     if (s)

1319     {

1320       /* Let the caller perform MAKE quoting.  */

1321       defer_opt (OPT_MT, s + 1);

1322       *s = '/0';

1323     }

1324

1325     /* Command line -MF overrides environment variables and default.  */

1326     if (!deps_file)

1327       deps_file = spec;

1328

1329     deps_append = 1;

1330   }

1331 }

 

前面,已经看到选项–MT–MQ需要被延迟处理,而被缓存起来。在上面1080行,这些选项可以被处理了。

 

1334 static void

1335 handle_deferred_opts (void)                                                                       in c-opts.c

1336 {

1337   size_t i;

1338

1339   for (i = 0; i < deferred_count; i++)

1340   {

1341     struct deferred_opt *opt = &deferred_opts[i];

1342

1343     if (opt->code == OPT_MT || opt->code == OPT_MQ)

1344       cpp_add_dependency_target (parse_in, opt->arg, opt->code == OPT_MQ);

1345   }

1346 }

 

因为–MT-MQ改变了由依赖生成(dependency generation)所产生的目标文件名,这个目标名由cpp_add_dependency_target添加。

 

430  void

431  cpp_add_dependency_target (cpp_reader *pfile, const char *target, int quote)   in cppinit.c

432  {

433    if (!pfile->deps)

434      pfile->deps = deps_init ();

435 

436    deps_add_target (pfile->deps, target, quote);

437  }

 

433行的deps被定义如下:

 

27    /* Keep this structure local to this file, so clients don't find it

28      easy to start making assumptions.  */

29    struct deps

30    {

31      const char **targetv;

32      unsigned int ntargets; /* number of slots actually occupied */

33      unsigned int targets_size;   /* amt of allocated space - in words */

34   

35      const char **depv;

36      unsigned int ndeps;

37      unsigned int deps_size;

38    };

 

这个对象由deps_init初始化,而目标名由deps_add_target添加,其中参数quote表示是否需要引用(quote)名字中的特殊字符。

做完延迟选项处理后,sanitize_cpp_opts被调用,以执行一些合理性检查。

 

1350 static void

1351 sanitize_cpp_opts (void)                                                                            in c-opts.c

1352 {

1353   /* If we don't know what style of dependencies to output, complain

1354     if any other dependency switches have been given.  */

1355   if (deps_seen && cpp_opts->deps.style == DEPS_NONE)

1356     error ("to generate dependencies you must specify either -M or -MM");

1357

1358   /* -dM and dependencies suppress normal output; do it here so that

1359      the last -d[MDN] switch overrides earlier ones.  */

1360   if (flag_dump_macros == 'M')

1361     flag_no_output = 1;

1362

1363   /* Disable -dD, -dN and -dI if normal output is suppressed. Allow

1364     -dM since at least glibc relies on -M -dM to work.  */

1365   /* Also, flag_no_output implies flag_no_line_commands, always. */

1366   if (flag_no_output)

1367   {

1368     if (flag_dump_macros != 'M')

1369       flag_dump_macros = 0;

1370     flag_dump_includes = 0;

1371     flag_no_line_commands = 1;

1372   }

1373

1374   cpp_opts->unsigned_char = !flag_signed_char;

1375   cpp_opts->stdc_0_in_system_headers = STDC_0_IN_SYSTEM_HEADERS;

1376

1377   /* We want -Wno-long-long to override -pedantic -std=non-c99

1378     and/or -Wtraditional, whatever the ordering.  */

1379   cpp_opts->warn_long_long

1380     = warn_long_long && ((!flag_isoc99 && pedantic) || warn_traditional);

1381

1382   /* If we're generating preprocessor output, emit current directory

1383     if explicitly requested or if debugging information is enabled.

1384     ??? Maybe we should only do it for debugging formats that

1385     actually output the current directory?  */

1386   if (flag_working_directory == -1)

1387     flag_working_directory = (debug_info_level != DINFO_LEVEL_NONE);

1388 }

 

上面的1360行,flag_dump_macrohandle_OPT_d中设置,在为‘M’的情况下,仅宏被转储。而在1361行,flag_no_output如果非0,导致选项-E的输出不被完成,但诸如#define这样有副作用的指示仍被遵守。

 

你可能感兴趣的:(GCC-3.4.6源代码学习笔记(27))