GCC's bacl-end & assemble emission (41)

来源:互联网 发布:c语言bzero 编辑:程序博客网 时间:2024/04/30 15:07

11.4.  Validating modes created

Back to main, after creating data for using modesfrom machmode.def and i386-modes.def,complete_all_modes is invoked to finish thecreation.

 

389  static void

390  complete_all_modes (void)                                                                   ingenmodes.c

391  {

392   struct mode_data*m;

393   enum mode_class c;

394   

395   for_all_modes (c, m)

396     complete_mode (m);

397  }

 

for_all_modes is a macro to iterate all data inmodes.

 

191  #define for_all_modes(C, M)               \                                                ingenmodes.c

192   for (C = 0; C < MAX_MODE_CLASS; C++)         \

193     for (M = modes[C]; M; M = M->next)

 

For every mode, fills the known fields if it is valid.

 

282  static void

283  complete_mode (struct mode_data *m)                                                  ingenmodes.c

284  {

285   unsigned int alignment;

286 

287   if (!m->name)

288   {

289     error ("%s:%d: mode with no name", m->file, m->line);

290     return;

291   }

292   if (m->class == MAX_MODE_CLASS)

293   {

294     error ("%s:%d: %smode has no mode class", m->file,m->line, m->name);

295     return;

296   }

297 

298   switch (m->class)

299   {

300     case MODE_RANDOM:

301       /* Nothing more need be said.  */

302       if (!strcmp (m->name, "VOID"))

303         void_mode= m;

304 

305       validate_mode (m, UNSET, UNSET, UNSET,UNSET, UNSET);

306 

307        m->precision = 0;

308        m->bytesize = 0;

309        m->ncomponents = 0;

310        m->component = 0;

311       break;

312 

313     case MODE_CC:

314       /* Again, nothing more need be said.  For historical reasons,

315          the size of a CC mode is fourunits.  */

316       validate_mode (m, UNSET, UNSET, UNSET,UNSET, UNSET);

317 

318        m->bytesize = 4;

319        m->ncomponents = 1;

320        m->component = 0;

321       break;

322 

323     case MODE_INT:

324     case MODE_FLOAT:

325       /* A scalar mode must have a byte size, mayhave a bit size,

326          and must not have components. A floatmode must have a

327          format. */

328       validate_mode (m, OPTIONAL, SET, UNSET,UNSET,

329                     m->class == MODE_FLOAT ? SET : UNSET);

330 

331        m->ncomponents = 1;

332        m->component = 0;

333       break;

334 

335     case MODE_PARTIAL_INT:

336       /* A partial integer mode uses ->componentto say what the

337          corresponding full-size integer modeis, and may also

338          specify a bit size.  */

339       validate_mode (m, OPTIONAL, UNSET, SET,UNSET, UNSET);

340 

341        m->bytesize = m->component->bytesize;

342 

343        m->ncomponents = 1;

344        m->component = 0;  /* ??? preserve this */

345       break;

346 

347     case MODE_COMPLEX_INT:

348     case MODE_COMPLEX_FLOAT:

349       /* Complex modes should have a component indicated,but no more.  */

350       validate_mode (m, UNSET, UNSET, SET, UNSET,UNSET);

351        m->ncomponents = 2;

352       if (m->component->precision != (unsigned int)-1)

353          m->precision = 2 * m->component->precision;

354        m->bytesize = 2 * m->component->bytesize;

355       break;

356 

357     case MODE_VECTOR_INT:

358     case MODE_VECTOR_FLOAT:

359       /* Vector modes should have a component and anumber of components.  */

360       validate_mode (m, UNSET, UNSET, SET, SET,UNSET);

361       if (m->component->precision != (unsigned int)-1)

362          m->precision = m->ncomponents * m->component->precision;

363        m->bytesize = m->ncomponents * m->component->bytesize;

364       break;

365 

366     default:

367       abort ();

368   }

369 

370   /* If not already specified, the modealignment defaults to the largest

371      power of two that divides the size of theobject. Complex types are

372      not more aligned than their contents.  */

373   if (m->class == MODE_COMPLEX_INT || m->class ==MODE_COMPLEX_FLOAT)

374     alignment = m->component->bytesize;

375   else

376     alignment = m->bytesize;

377 

378    m->alignment = alignment & (~alignment + 1);

379 

380   /* If this mode has components, make thecomponent mode point back

381      to this mode, for the sake ofadjustments.  */

382   if (m->component)

383   {

384      m->next_cont = m->component->contained;

385      m->component->contained = m;

386   }

387  }

 

Modes are validated by validate_mode.

 

263  static void

264  validate_mode (struct mode_data*m,

265                enumrequirement r_precision,

266                enumrequirement r_bytesize,

267                enum requirementr_component,

268                enumrequirement r_ncomponents,

269                enumrequirement r_format)

270  {

271   validate_field (m, precision);

272   validate_field (m, bytesize);

273   validate_field (m, component);

274   validate_field (m, ncomponents);

275   validate_field (m, format);

276  }

277  #undef validate_field

278  #undef validate_field_

 

validate_field above is macro definedbelow. That is why we need so many parameters during invokingvalidate_mode.

 

243  #define validate_field_(mname, fname, req,val, unset, file, line) do {      \     ingenmodes.c

244   switch (req)                                                  \

245   {                                                          \

246     case SET:                                                        \

247       if (val == unset)                                           \

248         error ("%s:%d: (%s) field %s must be set",                \

249               file, line, mname, fname);                        \

250       break;                                                   \

251     case UNSET:                                                   \

252       if (val != unset)                                            \

253         error ("%s:%d: (%s) field %s must not be set",                 \

254               file, line, mname, fname);                        \

255     case OPTIONAL:                                             \

256       break;                                                   \

257   }                                                          \

258  } while(0)

259 

260  #define validate_field(M, F) \

261   validate_field_(M->name, #F, r_##F,M->F,blank_mode.F,M->file, M->line)

 

Notice that the unset value in validate_field_ comes fromblank_modewhich is the templet for creating modes in new_mode. The validation just ensures modes arecorrectly initialized.

11.5.  Outputting Data

11.5.1.1.             Preparation

Before outputting the data, calc_wider_mode sorts mode_data based upon thesame mode with following example, QI < HI < SI < DI < TI and V4QI< V2HI < V8QI < V4HI < V2SI.

 

692  static void

693  calc_wider_mode (void)                                                                       ingenmodes.c

694  {

695   enum mode_class c;

696   struct mode_data*m;

697   struct mode_data**sortbuf;

698   unsigned int max_n_modes = 0;

699   unsigned int i, j;

700 

701   for (c = 0; c < MAX_MODE_CLASS; c++)

702      max_n_modes = MAX (max_n_modes, n_modes[c]);

703 

704   /* Allocate max_n_modes + 1 entries to leaveroom for the extra null

705      pointer assigned after the qsort callbelow.  */

706   sortbuf = alloca ((max_n_modes + 1) * sizeof(struct mode_data *));

707 

708   for (c = 0; c < MAX_MODE_CLASS; c++)

709   {

710     /* "wider" is not meaningful forMODE_RANDOM and MODE_CC.

711        However, we want these in textual order,and we have

712        precisely the reverse.  */

713     if (c == MODE_RANDOM || c == MODE_CC)

714     {

715       struct mode_data*prev, *next;

716 

717       for (prev = 0, m = modes[c]; m; m = next)

718       {

719          m->wider = void_mode;

720 

721         /* this is nreverse */

722         next = m->next;

723          m->next = prev;

724         prev = m;

725       }

726       modes[c]= prev;

727     }

728     else

729     {

730       if (!modes[c])

731         continue;

732 

733       for (i = 0, m = modes[c]; m; i++, m = m->next)

734         sortbuf[i] = m;

735 

736       qsort (sortbuf, i, sizeof (struct mode_data *), cmp_modes);

737 

738        sortbuf[i] = 0;

739        for(j = 0; j < i; j++)

740          sortbuf[j]->next =sortbuf[j]->wider = sortbuf[j + 1];

741 

742 

743        modes[c] = sortbuf[0];

744      }

745   }

746  }

11.5.1.2.             Output insn-modes.h file

Now in main, we can output the header file(insn-modes.h) if –h option used in invoking genmodes.

 

766  static void

767  emit_insn_modes_h (void)                                                                   ingenmodes.c

768  {

769   enum mode_class c;

770   struct mode_data*m, *first, *last;

771 

772   printf ("/* Generated automatically from machmode.def%s%s\n",

773         HAVE_EXTRA_MODES ? " and " : "",

774         EXTRA_MODES_FILE);

775 

776   puts ("\

777    by genmodes.  */\n\

778  \n\

779  #ifndef GCC_INSN_MODES_H\n\

780  #define GCC_INSN_MODES_H\n\

781  \n\

782  enum machine_mode\n{");

783 

784   for (c = 0; c < MAX_MODE_CLASS; c++)

785     for (m = modes[c]; m; m = m->next)

786     {

787       int count_;

788       printf ("  %smode,%n",m->name, &count_);

789       printf ("%*s/* %s:%d */\n", 27 - count_, "",

790              trim_filename (m->file),m->line);

791      }

792 

793    puts ("  MAX_MACHINE_MODE,\n");

794 

795   for (c = 0; c < MAX_MODE_CLASS; c++)

796   {

797     first = modes[c];

798     last = 0;

799     for (m = first; m; last = m, m =m->next)

800       ;

801 

802     /* Don't use BImode for MIN_MODE_INT, sinceotherwise the middle

803        end will try to use it for bitfields instructures and the

804        like, which we do not want. Only thetarget md file should

805        generate BImode widgets.  */

806     if (first && first->precision == 1)

807       first = first->next;

808 

809     if (first && last)

810       printf ("  MIN_%s =%smode,\n  MAX_%s = %smode,\n\n",

811              mode_class_names[c], first->name,

812              mode_class_names[c], last->name);

813     else

814       printf ("  MIN_%s =%smode,\n  MAX_%s = %smode,\n\n",

815              mode_class_names[c], void_mode->name,

816              mode_class_names[c], void_mode->name);

817    }

818 

819    puts ("\

820    NUM_MACHINE_MODES =MAX_MACHINE_MODE\n\

821  };\n");

822 

823   /* I can't think of a better idea, canyou?  */

824   printf ("#define CONST_MODE_SIZE%s\n", adj_bytesize ? "" :" const");

825   printf ("#define CONST_MODE_BASE_ALIGN%s\n", adj_alignment? "" : " const");

826  #if 0 /* disabled for backward compatibility,temporary */

827    printf ("#defineCONST_REAL_FORMAT_FOR_MODE%s\n", adj_format ? "" :"const");

828  #endif

829   puts ("\

830  \n\

831  #endif /* insn-modes.h */");

832  }

 

This header file defines the enumerate machine_mode, and the output fromline 784 to 791 is like following.

 

VOIDmode,                /* machmode.def:146 */

BLKmode,                 /* machmode.def:150 */

CCmode,                  /* machmode.def:178 */

 

And the output from line 795 to 817 is like (we dump all relatedoutput, as it is useful when reading code of other parts).

 

MIN_MODE_RANDOM = VOIDmode,

MAX_MODE_RANDOM = BLKmode,

 

MIN_MODE_CC = CCmode,

MAX_MODE_CC = CCFPUmode,

 

MIN_MODE_INT = QImode,

MAX_MODE_INT = TImode,

 

MIN_MODE_PARTIAL_INT = VOIDmode,

MAX_MODE_PARTIAL_INT = VOIDmode,

 

MIN_MODE_FLOAT = SFmode,

MAX_MODE_FLOAT = TFmode,

 

MIN_MODE_COMPLEX_INT = CQImode,

MAX_MODE_COMPLEX_INT = CTImode,

 

MIN_MODE_COMPLEX_FLOAT = SCmode,

MAX_MODE_COMPLEX_FLOAT = TCmode,

 

MIN_MODE_VECTOR_INT = V2QImode,

MAX_MODE_VECTOR_INT = V8DImode,

 

MIN_MODE_VECTOR_FLOAT = V2SFmode,

MAX_MODE_VECTOR_FLOAT= V8DFmode,

11.5.1.3.             Output insn-modes.c file

For using option –h, we need to output insn-modes.c following abovestep.

 

1153 static void

1154 emit_insn_modes_c (void)                                                                   ingenmodes.c

1155 {

1156   emit_insn_modes_c_header ();

1157  emit_mode_name ();

1158  emit_mode_class ();

1159  emit_mode_precision ();

1160  emit_mode_size ();

1161  emit_mode_nunits ();

1162  emit_mode_wider ();

1163  emit_mode_mask ();

1164  emit_mode_inner ();

1165  emit_mode_base_align ();

1166   emit_class_narrowest_mode ();

1167   emit_real_format_for_mode ();

1168   emit_mode_adjustments ();

1169 }

 

The output functions are simple and straightforward. They willoutput corresponding data from themodes.