Studying note of GCC-3.4.6 source (69)

来源:互联网 发布:什么是软件什么是硬件 编辑:程序博客网 时间:2024/06/11 08:40

4.3.3. Initialize libray calls table

Machine description file gives out the way to construct instructions of RTL form for certain operation. For instruction emition, compiler tries to open coded RTL code (if something is open-coded, there is no actual function call made, just equivilent code dropped into place; close-coded results in a call to -some- function. In compiler circles, the phrase "open coded" is even more general than that. For instance, some machines have a fancy instruction to do several steps of some computation, such as a POLY instruction to calculate polynomials, or an INDEX instruction to use array subscripts (sometimes with build-in builds-checking). As it turns out, on some particular of the given architecture, it is faster to execute a series of multiple simpler instructions than to use the fancy instruction. This used to occur more often with microcoded systems with optional acceleration hardware – for instance, INDEX might micro-code a multiply, taking dozens of clock cycles, while a simpler MUL and then ADD uses the hardware multiplier and hence finishes in only a few clock cycles. These days it tends to happen instead with parallel-issue microprocessors: for instance, the x86 ENTER instruction is slower, on some x86 CPUs, than the equivalent sequence of instructions. (This is especially true if the compiler can omit several steps due to some specific knowledge, e.g., "we know there is no need for separate stack and frame pointers, nor for any stack adjustment, in this leaf function".) Compiler folks will say things like "we open coded the function entry and exit" when they avoid using the slow ENTER and EXIT instructions). If not possible, the compiler will have to invoke library routines to handle the operation.

 

lang_dependent_init (continue)

 

4540     init_optabs ();

 

5177 void

5178 init_optabs (void)                                                                                      in optabs.c

5179 {

5180   unsigned int i;

5181

5182   /* Start by initializing all tables to contain CODE_FOR_nothing.  */

5183

5184   for (i = 0; i < NUM_RTX_CODE; i++)

5185     setcc_gen_code[i] = CODE_FOR_nothing;

5186

5187 #ifdef HAVE_conditional_move

5188   for (i = 0; i < NUM_MACHINE_MODES; i++)

5189     movcc_gen_code[i] = CODE_FOR_nothing;

5190 #endif

 

setcc_gen_code indexed by the rtx-code for a conditional (eg. EQ, LT,...) gives the insn code to make a store-condition insn to test that condition. While movcc_gen_code indexed by the machine mode, gives the insn code to make a conditional move insn. This is not indexed by the rtx-code like bcc_gen_fctn and setcc_gen_code to cut down on the number of named patterns.

 

init_optabs (continue)

 

5192   add_optab = init_optab (PLUS);

5193   addv_optab = init_optabv (PLUS);

5194   sub_optab = init_optab (MINUS);

5195   subv_optab = init_optabv (MINUS);

5196   smul_optab = init_optab (MULT);

5197   smulv_optab = init_optabv (MULT);

5198   smul_highpart_optab = init_optab (UNKNOWN);

5199   umul_highpart_optab = init_optab (UNKNOWN);

5200   smul_widen_optab = init_optab (UNKNOWN);

5201   umul_widen_optab = init_optab (UNKNOWN);

5202   sdiv_optab = init_optab (DIV);

5203   sdivv_optab = init_optabv (DIV);

5204   sdivmod_optab = init_optab (UNKNOWN);

5205   udiv_optab = init_optab (UDIV);

5206   udivmod_optab = init_optab (UNKNOWN);

5207   smod_optab = init_optab (MOD);

5208   umod_optab = init_optab (UMOD);

5209   ftrunc_optab = init_optab (UNKNOWN);

5210   and_optab = init_optab (AND);

5211   ior_optab = init_optab (IOR);

5212   xor_optab = init_optab (XOR);

5213   ashl_optab = init_optab (ASHIFT);

5214   ashr_optab = init_optab (ASHIFTRT);

5215   lshr_optab = init_optab (LSHIFTRT);

5216   rotl_optab = init_optab (ROTATE);

5217   rotr_optab = init_optab (ROTATERT);

5218   smin_optab = init_optab (SMIN);

5219   smax_optab = init_optab (SMAX);

5220   umin_optab = init_optab (UMIN);

5221   umax_optab = init_optab (UMAX);

5222   pow_optab = init_optab (UNKNOWN);

5223   atan2_optab = init_optab (UNKNOWN);

5224

5225   /* These three have codes assigned exclusively for the sake of

5226     have_insn_for.  */

5227   mov_optab = init_optab (SET);

5228   movstrict_optab = init_optab (STRICT_LOW_PART);

5229   cmp_optab = init_optab (COMPARE);

5230

5231   ucmp_optab = init_optab (UNKNOWN);

5232   tst_optab = init_optab (UNKNOWN);

5233

5234   eq_optab = init_optab (EQ);

5235   ne_optab = init_optab (NE);

5236   gt_optab = init_optab (GT);

5237   ge_optab = init_optab (GE);

5238   lt_optab = init_optab (LT);

5239   le_optab = init_optab (LE);

5240   unord_optab = init_optab (UNORDERED);

5241

5242   neg_optab = init_optab (NEG);

5243   negv_optab = init_optabv (NEG);

5244   abs_optab = init_optab (ABS);

5245   absv_optab = init_optabv (ABS);

5246   addcc_optab = init_optab (UNKNOWN);

5247   one_cmpl_optab = init_optab (NOT);

5248   ffs_optab = init_optab (FFS);

5249   clz_optab = init_optab (CLZ);

5250   ctz_optab = init_optab (CTZ);

5251   popcount_optab = init_optab (POPCOUNT);

5252   parity_optab = init_optab (PARITY);

5253   sqrt_optab = init_optab (SQRT);

5254   floor_optab = init_optab (UNKNOWN);

5255   ceil_optab = init_optab (UNKNOWN);

5256   round_optab = init_optab (UNKNOWN);

5257   btrunc_optab = init_optab (UNKNOWN);

5258   nearbyint_optab = init_optab (UNKNOWN);

5259   sin_optab = init_optab (UNKNOWN);

5260   cos_optab = init_optab (UNKNOWN);

5261   exp_optab = init_optab (UNKNOWN);

5262   log_optab = init_optab (UNKNOWN);

5263   tan_optab = init_optab (UNKNOWN);

5264   atan_optab = init_optab (UNKNOWN);

5265   strlen_optab = init_optab (UNKNOWN);

5266   cbranch_optab = init_optab (UNKNOWN);

5267   cmov_optab = init_optab (UNKNOWN);

5268   cstore_optab = init_optab (UNKNOWN);

5269   push_optab = init_optab (UNKNOWN);

5270

5271   vec_extract_optab = init_optab (UNKNOWN);

5272   vec_set_optab = init_optab (UNKNOWN);

5273   vec_init_optab = init_optab (UNKNOWN);

 

Above, at the left hand side of init_optab, init_optabv, are XXX_optab marco which just selects corresponding element of optab_table, which is a global array of struct optab.

 

41      struct optab_handlers GTY(())                                                                   in optabs.h

42      {

43        enum insn_code insn_code;

44        rtx libfunc;

45      };

 

In the definition, insn_code slot says how to generate an instruction for this operation on a particular machine mode. It is CODE_FOR_nothing if there is no such instruction on the target machine, libfunc slot is the name of the library function that can be used to perform the operation.

 

47      struct optab GTY(())                                                                                in optabs.h

48      {

49        enum rtx_code code;

50        struct optab_handlers handlers[NUM_MACHINE_MODES];

51      };

52      typedef struct optab * optab;

 

In sections of back-end, we know that insn_code describes the instructions the target can support (as result, insn_code must be generated by tool from target machine description file); while rtx_code describes target independent instructions in form of RTL generated by the front-end. Struct optab maps rtx_code to insn_code. Notice that handlers is an array, as on target, operations with different mode may need different instructions.

 

4910 static inline optab

4911 init_optab (enum rtx_code code)                                                          in optabs.c

4912 {

4913   optab op = new_optab ();

4914   op->code = code;

4915   code_to_optab[(int) code] = op;

4916   return op;

4917 }

 

4921 static inline optab

4922 init_optabv (enum rtx_code code)

4923 {

4924   optab op = new_optab ();

4925   op->code = code;

4926   return op;

4927 }

 

Here operation of name followed by ”v” shares the same rtx-code with the operation without “v” in name. The difference is, for “v” versoin, if the result is overflowed, it will trap. They are selected by the value of flag_trapv.

 

init_optabs (continue)

 

5274   /* Conversions.  */

5275   sext_optab = init_convert_optab (SIGN_EXTEND);

5276   zext_optab = init_convert_optab (ZERO_EXTEND);

5277   trunc_optab = init_convert_optab (TRUNCATE);

5278   sfix_optab = init_convert_optab (FIX);

5279   ufix_optab = init_convert_optab (UNSIGNED_FIX);

5280   sfixtrunc_optab = init_convert_optab (UNKNOWN);

5281   ufixtrunc_optab = init_convert_optab (UNKNOWN);

5282   sfloat_optab = init_convert_optab (FLOAT);

5283   ufloat_optab = init_convert_optab (UNSIGNED_FLOAT);

 

In C++, we can use for example (int) f to do the type conversion. It’s clean and convenient, no need consider any detail about the data presentation. However, it’s not for granted and free. Methods must be defined for every permitted type conversion. It’s why comes convert_optab.

Above, at the left hand side of init_convert_optab, XXX_optab macro selects corresponding items in convert_optab_table, which is a global array of convert_optab.

 

57      struct convert_optab GTY(())                                                                    in optabs.h

58      {

59        enum rtx_code code;

60        struct optab_handlers handlers[NUM_MACHINE_MODES][NUM_MACHINE_MODES];

61      };

62      typedef struct convert_optab *convert_optab;

 

In the definition, handlers is two dimensions array, records conversion operation between modes

 

4930 static inline convert_optab

4931 init_convert_optab (enum rtx_code code)                                                     in optabs.c

4932 {

4933   convert_optab op = new_convert_optab ();

4934   op->code = code;

4935   return op;

4936 }

 

Here, movstr_optab records the insn_code of instructions to perform block moves. clrstr_optab records the insn_code of instructions to perform block clears. cmpstr_optab, and cmpmem_optab record the insn_code of two different kinds of instructions to perform block compares. While reload_in_optab and reload_out_optab record the insn_code of insns that may be needed to perform input and output reloads of special objects. They provide a place to pass a scratch register.

 

init_optabs (continue)

 

5285   for (i = 0; i < NUM_MACHINE_MODES; i++)

5286   {

5287     movstr_optab[i] = CODE_FOR_nothing;

5288     clrstr_optab[i] = CODE_FOR_nothing;

5289     cmpstr_optab[i] = CODE_FOR_nothing;

5290     cmpmem_optab[i] = CODE_FOR_nothing;

5291

5292 #ifdef HAVE_SECONDARY_RELOADS

5293     reload_in_optab[i] = reload_out_optab[i] = CODE_FOR_nothing;

5294 #endif

5295   }

5296

5297   /* Fill in the optabs with the insns we support.  */

5298   init_all_optabs ();

 

Now from front-end’s view, all optabs have been filled with related rtx_code, but front-end hasn’t idea about insn_code, it is the business of back-end. To finish optabs, back-end specially generates init_all_optabs with genopinit from target machine description file. It helps fill in insn_code, below is code snippet of the function.

 

  sext_optab->handlers[SImode][HImode].insn_code = CODE_FOR_extendhisi2;

  sext_optab->handlers[HImode][QImode].insn_code = CODE_FOR_extendqihi2;

  sext_optab->handlers[SImode][QImode].insn_code = CODE_FOR_extendqisi2;

  setcc_gen_code[EQ] = CODE_FOR_seq;

  setcc_gen_code[NE] = CODE_FOR_sne;

  setcc_gen_code[GT] = CODE_FOR_sgt;

  setcc_gen_code[GTU] = CODE_FOR_sgtu;

 

  bcc_gen_fctn[EQ] = gen_beq;

  bcc_gen_fctn[NE] = gen_bne;

  bcc_gen_fctn[GT] = gen_bgt;

  bcc_gen_fctn[GTU] = gen_bgtu;

 

Above, sext_optab selects convert_optab for signed extension in convert_optab_table. The first index for handlers is the target mode, the second is the source mode. At right hand side of the assignment is the insn_code.

Following, now setcc_gen_code is initialized with the correct insn_code if the target machine offers such instructions. Notice that not all machine mode of setcc_gen_code will get meaningful insn_code (not CODE_FOR_nothing), which can be not open coded, and library routine will be invoked at place.

Then global array bcc_gen_fctn of type rtx_fun gives the way to test the condition such as EQ (equal), LT (less than). Of course, gen_XXX are also generated following target machine description, and you will find the definition in insn_emit.c.

 

init_optabs (continue)

 

5300   /* Initialize the optabs with the names of the library functions.  */

5301   init_integral_libfuncs (add_optab, "add", '3');

5302   init_floating_libfuncs (add_optab, "add", '3');

5303   init_integral_libfuncs (addv_optab, "addv", '3');

5304   init_floating_libfuncs (addv_optab, "add", '3');

5305   init_integral_libfuncs (sub_optab, "sub", '3');

5306   init_floating_libfuncs (sub_optab, "sub", '3');

5307   init_integral_libfuncs (subv_optab, "subv", '3');

5308   init_floating_libfuncs (subv_optab, "sub", '3');

5309   init_integral_libfuncs (smul_optab, "mul", '3');

5310   init_floating_libfuncs (smul_optab, "mul", '3');

5311   init_integral_libfuncs (smulv_optab, "mulv", '3');

5312   init_floating_libfuncs (smulv_optab, "mul", '3');

5313   init_integral_libfuncs (sdiv_optab, "div", '3');

5314   init_floating_libfuncs (sdiv_optab, "div", '3');

5315   init_integral_libfuncs (sdivv_optab, "divv", '3');

5316   init_integral_libfuncs (udiv_optab, "udiv", '3');

5317   init_integral_libfuncs (sdivmod_optab, "divmod", '4');

5318   init_integral_libfuncs (udivmod_optab, "udivmod", '4');

5319   init_integral_libfuncs (smod_optab, "mod", '3');

5320   init_integral_libfuncs (umod_optab, "umod", '3');

5321   init_floating_libfuncs (ftrunc_optab, "ftrunc", '2');

5322   init_integral_libfuncs (and_optab, "and", '3');

5323   init_integral_libfuncs (ior_optab, "ior", '3');

5324   init_integral_libfuncs (xor_optab, "xor", '3');

5325   init_integral_libfuncs (ashl_optab, "ashl", '3');

5326   init_integral_libfuncs (ashr_optab, "ashr", '3');

5327   init_integral_libfuncs (lshr_optab, "lshr", '3');

5328   init_integral_libfuncs (smin_optab, "min", '3');

5329   init_floating_libfuncs (smin_optab, "min", '3');

5330   init_integral_libfuncs (smax_optab, "max", '3');

5331   init_floating_libfuncs (smax_optab, "max", '3');

5332   init_integral_libfuncs (umin_optab, "umin", '3');

5333   init_integral_libfuncs (umax_optab, "umax", '3');

5334   init_integral_libfuncs (neg_optab, "neg", '2');

5335   init_floating_libfuncs (neg_optab, "neg", '2');

5336   init_integral_libfuncs (negv_optab, "negv", '2');

5337   init_floating_libfuncs (negv_optab, "neg", '2');

5338   init_integral_libfuncs (one_cmpl_optab, "one_cmpl", '2');

5339   init_integral_libfuncs (ffs_optab, "ffs", '2');

5340   init_integral_libfuncs (clz_optab, "clz", '2');

5341   init_integral_libfuncs (ctz_optab, "ctz", '2');

5342   init_integral_libfuncs (popcount_optab, "popcount", '2');

5343   init_integral_libfuncs (parity_optab, "parity", '2');

5344

5345   /* Comparison libcalls for integers MUST come in pairs, signed/unsigned.  */

5346   init_integral_libfuncs (cmp_optab, "cmp", '2');

5347   init_integral_libfuncs (ucmp_optab, "ucmp", '2');

5348   init_floating_libfuncs (cmp_optab, "cmp", '2');

5349

5350  /* EQ etc are floating point only.  */

5351   init_floating_libfuncs (eq_optab, "eq", '2');

5352   init_floating_libfuncs (ne_optab, "ne", '2');

5353   init_floating_libfuncs (gt_optab, "gt", '2');

5354   init_floating_libfuncs (ge_optab, "ge", '2');

5355   init_floating_libfuncs (lt_optab, "lt", '2');

5356   init_floating_libfuncs (le_optab, "le", '2');

5357   init_floating_libfuncs (unord_optab, "unord", '2');

 

Now times for initializing libfunc in handler of optab, this field records the library function that can perform the operation identified by insn_code (however, the library function may not exist).

 

4991 static void

4992 init_integral_libfuncs (optab optable, const char *opname, int suffix)                     in optabs.c

4993 {

4994   int maxsize = 2*BITS_PER_WORD;

4995   if (maxsize < LONG_LONG_TYPE_SIZE)

4996     maxsize = LONG_LONG_TYPE_SIZE;

4997   init_libfuncs (optable, word_mode,

4998               mode_for_size (maxsize, MODE_INT, 0),

4999               opname, suffix);

5000 }

 

At line 4998, mode_for_size finds out the machine mode of specified precision (here indicated by maxsize) in specified class (Here MODE_INT).

 

4955 static void

4956 init_libfuncs (optab optable, int first_mode, int last_mode,                            in optabs.c

4957          const char *opname, int suffix)

4958 {

4959   int mode;

4960   unsigned opname_len = strlen (opname);

4961

4962   for (mode = first_mode; (int) mode <= (int) last_mode;

4963        mode = (enum machine_mode) ((int) mode + 1))

4964   {

4965     const char *mname = GET_MODE_NAME (mode);

4966     unsigned mname_len = strlen (mname);

4967     char *libfunc_name = alloca (2 + opname_len + mname_len + 1 + 1);

4968     char *p;

4969     const char *q;

4970

4971     p = libfunc_name;

4972     *p++ = '_';

4973     *p++ = '_';

4974     for (q = opname; *q; )

4975      *p++ = *q++;

4976     for (q = mname; *q; q++)

4977      *p++ = TOLOWER (*q);

4978     *p++ = suffix;

4979     *p = '/0';

4980

4981     optable->handlers [(int) mode].libfunc

4982       = init_one_libfunc (ggc_alloc_string (libfunc_name, p - libfunc_name));

4983   }

4984 }

 

Before line 4981, it just constructs the library function name. At line 4982 allocates the string on ggc (gcc garbage collection) managing stack. Using code at line 5301 as example, library functions declared are: __addqi3, __addhi3, __addsi3, __adddi3. But these functions aren’t implemented in compiler, as the target machine description file has told the compiler about the detail of the instruction to do the operation.

 

init_optabs (continue)

 

5359   /* Conversions.  */

5360   init_interclass_conv_libfuncs (sfloat_optab, "float", MODE_INT, MODE_FLOAT);

5361   init_interclass_conv_libfuncs (sfix_optab, "fix",   MODE_FLOAT, MODE_INT);

5362   init_interclass_conv_libfuncs (ufix_optab, "fixuns", MODE_FLOAT, MODE_INT);

 

For inter-class conversion, like int to float, it involves the change of data representation. It needs below init_interclass_conv_libfuncs to fill the handlers.

 

5018 static void

5019 init_interclass_conv_libfuncs (convert_optab tab, const char *opname,           in optabs.c

5020                           enum mode_class from_class,

5021                           enum mode_class to_class)

5022 {

5023   enum machine_mode first_from_mode = GET_CLASS_NARROWEST_MODE (from_class);

5024   enum machine_mode first_to_mode = GET_CLASS_NARROWEST_MODE (to_class);

5025   size_t opname_len = strlen (opname);

5026   size_t max_mname_len = 0;

5027

5028   enum machine_mode fmode, tmode;

5029   const char *fname, *tname;

5030   const char *q;

5031   char *libfunc_name, *suffix;

5032   char *p;

5033

5034   for (fmode = first_from_mode;

5035        fmode != VOIDmode;

5036        fmode = GET_MODE_WIDER_MODE (fmode))

5037     max_mname_len = MAX (max_mname_len, strlen (GET_MODE_NAME (fmode)));

5038

5039   for (tmode = first_to_mode;

5040        tmode != VOIDmode;

5041        tmode = GET_MODE_WIDER_MODE (tmode))

5042     max_mname_len = MAX (max_mname_len, strlen (GET_MODE_NAME (tmode)));

5043

5044   libfunc_name = alloca (2 + opname_len + 2*max_mname_len + 1 + 1);

5045   libfunc_name[0] = '_';

5046   libfunc_name[1] = '_';

5047  memcpy (&libfunc_name[2], opname, opname_len);

5048   suffix = libfunc_name + opname_len + 2;

5049

5050   for (fmode = first_from_mode; fmode != VOIDmode;

5051        fmode = GET_MODE_WIDER_MODE (fmode))

5052     for (tmode = first_to_mode; tmode != VOIDmode;

5053          tmode = GET_MODE_WIDER_MODE (tmode))

5054     {

5055       fname = GET_MODE_NAME (fmode);

5056       tname = GET_MODE_NAME (tmode);

5057

5058       p = suffix;

5059       for (q = fname; *q; p++, q++)

5060         *p = TOLOWER (*q);

5061       for (q = tname; *q; p++, q++)

5062         *p = TOLOWER (*q);

5063

5064       *p = '/0';

5065

5066       tab->handlers[tmode][fmode].libfunc

5067         = init_one_libfunc (ggc_alloc_string (libfunc_name,

5068                                        p - libfunc_name));

5069     }

5070 }

 

Similarly, most functions declared here aren’t implemented (refer to libgcc2.c). There are alternative instructions.

 

init_optabs (continue)

 

5364   /* sext_optab is also used for FLOAT_EXTEND.  */

5365   init_intraclass_conv_libfuncs (sext_optab, "extend", MODE_FLOAT, true);

5366   init_intraclass_conv_libfuncs (trunc_optab, "trunc", MODE_FLOAT, false);

 

Before, we have seen that single float and double float have different data representations, so either extending from single to double, or truncating from double to single, both are conversions in essense. Must prepare the conversion functions.

 

5077 static void

5078 init_intraclass_conv_libfuncs (convert_optab tab, const char *opname,           in optabs.c

5079                      enum mode_class class, bool widening)

5080 {

5081   enum machine_mode first_mode = GET_CLASS_NARROWEST_MODE (class);

5082   size_t opname_len = strlen (opname);

5083   size_t max_mname_len = 0;

5084

5085   enum machine_mode nmode, wmode;

5086   const char *nname, *wname;

5087   const char *q;

5088   char *libfunc_name, *suffix;

5089   char *p;

5090

5091   for (nmode = first_mode; nmode != VOIDmode;

5092        nmode = GET_MODE_WIDER_MODE (nmode))

5093     max_mname_len = MAX (max_mname_len, strlen (GET_MODE_NAME (nmode)));

5094

5095   libfunc_name = alloca (2 + opname_len + 2*max_mname_len + 1 + 1);

5096   libfunc_name[0] = '_';

5097   libfunc_name[1] = '_';

5098   memcpy (&libfunc_name[2], opname, opname_len);

5099   suffix = libfunc_name + opname_len + 2;

5100

5101   for (nmode = first_mode; nmode != VOIDmode;

5102        nmode = GET_MODE_WIDER_MODE (nmode))

5103     for (wmode = GET_MODE_WIDER_MODE (nmode); wmode != VOIDmode;

5104         wmode = GET_MODE_WIDER_MODE (wmode))

5105     {

5106       nname = GET_MODE_NAME (nmode);

5107       wname = GET_MODE_NAME (wmode);

5108

5109       p = suffix;

5110       for (q = widening ? nname : wname; *q; p++, q++)

5111         *p = TOLOWER (*q);

5112       for (q = widening ? wname : nname; *q; p++, q++)

5113         *p = TOLOWER (*q);

5114

5115       *p++ = '2';

5116       *p = '/0';

5117

5118       tab->handlers[widening ? wmode : nmode]

5119                  [widening ? nmode : wmode].libfunc

5120           = init_one_libfunc (ggc_alloc_string (libfunc_name,

5121                                          p - libfunc_name));

5122     }

5123 }

 

All these library functions aren’t implemented also, these operations rely on the instructions given by machine description file.

 

init_optabs (continue)

 

5368   /* Use cabs for double complex abs, since systems generally have cabs.

5369     Don't define any libcall for float complex, so that cabs will be used.  */

5370   if (complex_double_type_node)

5371     abs_optab->handlers[TYPE_MODE (complex_double_type_node)].libfunc

5372       = init_one_libfunc ("cabs");

5373

5374   /* The ffs function operates on `int'.  */

5375   ffs_optab->handlers[(int) mode_for_size (INT_TYPE_SIZE, MODE_INT, 0)].libfunc

5376     = init_one_libfunc ("ffs");

5377

5378   abort_libfunc = init_one_libfunc ("abort");

5379   memcpy_libfunc = init_one_libfunc ("memcpy");

5380   memmove_libfunc = init_one_libfunc ("memmove");

5381   bcopy_libfunc = init_one_libfunc ("bcopy");

5382   memcmp_libfunc = init_one_libfunc ("memcmp");

5383   bcmp_libfunc = init_one_libfunc ("__gcc_bcmp");

5384   memset_libfunc = init_one_libfunc ("memset");

5385   bzero_libfunc = init_one_libfunc ("bzero");

5386   setbits_libfunc = init_one_libfunc ("__setbits");

5387

5388   unwind_resume_libfunc = init_one_libfunc (USING_SJLJ_EXCEPTIONS

5389                                 ? "_Unwind_SjLj_Resume"

5390                                 : "_Unwind_Resume");

5391 #ifndef DONT_USE_BUILTIN_SETJMP

5392   setjmp_libfunc = init_one_libfunc ("__builtin_setjmp");

5393   longjmp_libfunc = init_one_libfunc ("__builtin_longjmp");

5394 #else

5395   setjmp_libfunc = init_one_libfunc ("setjmp");

5396   longjmp_libfunc = init_one_libfunc ("longjmp");

5397 #endif

5398   unwind_sjlj_register_libfunc = init_one_libfunc ("_Unwind_SjLj_Register");

5399   unwind_sjlj_unregister_libfunc

5400     = init_one_libfunc ("_Unwind_SjLj_Unregister");

5401

5402   /* For function entry/exit instrumentation.  */

5403   profile_function_entry_libfunc

5404     = init_one_libfunc ("__cyg_profile_func_enter");

5405   profile_function_exit_libfunc

5406     = init_one_libfunc ("__cyg_profile_func_exit");

5407

5408   gcov_flush_libfunc = init_one_libfunc ("__gcov_flush");

5409   gcov_init_libfunc = init_one_libfunc ("__gcov_init");

5410

5411   if (HAVE_conditional_trap)

5412     trap_rtx = gen_rtx_fmt_ee (EQ, VOIDmode, NULL_RTX, NULL_RTX);

5413

5414   /* Allow the target to add more libcalls or rename some, etc.  */

5415   targetm.init_libfuncs ();

5416 }

 

In the install directory, there is sub-diretory “lib”. Within it are libraries compiler would use (of course, they are compiled at installing from the gcc source code). With tool nm, you can find out most functions above. At line 5415, hook init_libfuncs gives the target a chance to add in its library calls or rename some, but for x86, it needesn’t.

 

原创粉丝点击