Subversion Repositories tendra.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 7u83 1
/*
2
    Copyright (c) 1993 Open Software Foundation, Inc.
3
 
4
 
5
    All Rights Reserved
6
 
7
 
8
    Permission to use, copy, modify, and distribute this software
9
    and its documentation for any purpose and without fee is hereby
10
    granted, provided that the above copyright notice appears in all
11
    copies and that both the copyright notice and this permission
12
    notice appear in supporting documentation.
13
 
14
 
15
    OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING
16
    ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
17
    PARTICULAR PURPOSE.
18
 
19
 
20
    IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
21
    CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
22
    LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
23
    NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
24
    WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
25
*/
26
 
27
/*
28
    		 Crown Copyright (c) 1997
29
 
30
    This TenDRA(r) Computer Program is subject to Copyright
31
    owned by the United Kingdom Secretary of State for Defence
32
    acting through the Defence Evaluation and Research Agency
33
    (DERA).  It is made available to Recipients with a
34
    royalty-free licence for its use, reproduction, transfer
35
    to other parties and amendment for any purpose not excluding
36
    product development provided that any such use et cetera
37
    shall be deemed to be acceptance of the following conditions:-
38
 
39
        (1) Its Recipients shall ensure that this Notice is
40
        reproduced upon any copies or amended versions of it;
41
 
42
        (2) Any amended version of it shall be clearly marked to
43
        show both the nature of and the organisation responsible
44
        for the relevant amendment or amendments;
45
 
46
        (3) Its onward transfer from a recipient to another
47
        party shall be deemed to be that party's acceptance of
48
        these conditions;
49
 
50
        (4) DERA gives no warranty or assurance as to its
51
        quality or suitability for any purpose and DERA accepts
52
        no liability whatsoever in relation to any use to which
53
        it may be put.
54
*/
55
 
56
 
57
 
58
/**********************************************************************
59
$Author: release $
60
$Date: 1998/02/04 15:49:12 $
61
$Revision: 1.2 $
62
$Log: translat.c,v $
63
 * Revision 1.2  1998/02/04  15:49:12  release
64
 * Added OSF copyright message.
65
 *
66
 * Revision 1.1.1.1  1998/01/17  15:55:58  release
67
 * First version to be checked into rolling release.
68
 *
69
 * Revision 1.2  1996/10/04  16:04:56  pwe
70
 * add banners and mod for PWE ownership
71
 *
72
**********************************************************************/
73
 
74
 
75
/*
76
 *  Translation is controlled by translate() in this module.
77
 *  Code generation follows the following phases:
78
 *
79
 *  1. The TDF is read in, applying bottom-up optimisations.
80
 *  2. Top-down optimisations are performed.
81
 *  3. Register allocation is performed, and TDF idents introduced
82
 *     so code generation can be performed with no register spills.
83
 *  4. Code is generated for each procedure, and global declarations processed.
84
 *  5. Peephole optimisation and instruction scheduling.
85
 *     (not implemented yet)
86
 *
87
 *  In a little more detail:
88
 *
89
 *  1) During the TDF reading process for tag declarations and tag
90
 *  definitions, applications of tokens are expanded as they are
91
 *  encountered, using the token definitions.  Every token used must have
92
 *  been previously defined in the bitstream.
93
 *
94
 *  The reading of the tag definitions creates a data structure in memory
95
 *  which directly represents the TDF.  At present, all the tag definitions
96
 *  are read into memory in this way before any further translation is
97
 *  performed.  This will shortly be changed, so that translation is
98
 *  performed in smaller units.  The translator is set up already so that
99
 *  the change to translate in units of single global definitions (or
100
 *  groups of these) can easily be made.
101
 *
102
 *  During the creation of the data structure bottom-up optimisations
103
 *  are performed.  These are the optimisations which can be done when a
104
 *  complete sub-tree of TDF is present, and are independent of the context
105
 *  in which the sub-tree is used.  They are defined in check.c and
106
 *  check_id.c.  These optimisation do such things as use the commutative
107
 *  and associative laws for plus to collect together and evaluate
108
 *  constants.  More ambitious examples of these bottom-up optimisations
109
 *  include all constant evaluation, elimination of inaccessible code, and
110
 *  forward propagation of assignments of constants.
111
 *
112
 *  2) After reading in the TDF various optimisations are performed which
113
 *  cannot be done until the whole context is present.  For example,
114
 *  constants cannot be extracted from a loop when we just have the loop
115
 *  itself, because we cannot tell whether the variables used in it are
116
 *  aliased.
117
 *
118
 *  These optimisations are invoked by opt_all_exps which is defined in
119
 *  indep.c.  They include extraction of constants from loops, common
120
 *  expression elimination on them and strength reduction for indexing.
121
 *
122
 *  3) Allocatable registers are partitioned into two sets, the s regs
123
 *  which are preserved over calls, and the t regs which are not.
124
 *
125
 *  The TDF is scanned introducing TDF idents so that expressions can be
126
 *  evaluated within the available t regs with no spills.  These new idents
127
 *  may be later allocated to a s reg later, if the weighting algorithm
128
 *  (below) considers this worth while.  Otherwise they will be on the stack.
129
 *
130
 *  Information is collected to help in global register allocation.  During
131
 *  a forward recursive scan of the TDF the number of accesses to each
132
 *  variable is computed (making assumptions about the frequency of
133
 *  execution of loops).  Then on the return scan of this recursion, for
134
 *  each declaration, the number of registers which must be free for it to
135
 *  be worthwhile to use a register is computed, and put into the TDF as
136
 *  the "break" point.  The procedures to do this are defined in weights.c.
137
 *
138
 *  Suitable idents not alive over a procedure call are allocated to a t reg,
139
 *  and others to s regs.  At the same time stack space requirements are
140
 *  calculated, so this is known before code for a procedure is generated.
141
 *
142
 *  4) Finally the code is generated without register spills.  The code is
143
 *  generated by make_code() in makecode.c, and make_XXX_code() in proc.c.
144
 *
145
 *  Note that loop unrolling optimisations are not currently implemented.
146
 *  Library procedures such as memcpy() are not treated specially.
147
 */
148
 
149
 
150
#include "config.h"
151
#include "memtdf.h"
152
#include "codegen.h"
153
#include "installglob.h"
154
#include "basicread.h"
155
#include "main_reads.h"
156
#include "optimise.h"
157
#include "exp.h"
158
#include "flpt.h"		/* for init_flpt() */
159
#include "externs.h"		/* for "inits.h" init_XXX() procs */
160
#include "myassert.h"
161
#include "tempdecs.h"
162
#include "weights.h"
163
#include "procrecs.h"
164
#include "regalloc.h"
165
#include "makecode.h"
166
#include "eval.h"
167
#include "flags.h"
168
#include "needscan.h"
169
#include "machine.h"
170
#include "diagout.h"
171
#include "xalloc.h"
172
#include "comment.h"
173
 
174
#include "translat.h"
175
#include "readglob.h"
176
#include "stack.h"
177
#include "frames.h"
178
#include "macro.h"
179
#include "dynamic_init.h"
180
#include "target_v.h"
181
 
182
 
183
#define ALIGNNEXT(bitposn, bitalign)	(((bitposn)+(bitalign)-1) & ~((bitalign)-1))
184
 
185
int optim_level;		/* optimisation level from -O# option */
186
int maxfix_tregs;		/* The number of t regs allocatable */
187
FILE *as_file;			/* Assembler output file */
188
dec **main_globals;		/* The globals decs array */
189
procrec *procrecs;		/* The proc records array */
190
dec * diag_def = NULL;
191
bool environ_externed=0;/* environ bug work around */
192
long total_no_of_globals = 0;
193
bool done_scan = 0;
194
 
195
/* 
196
 * Translate the TDF 
197
 */
198
int translate PROTO_N ((infname,outfname)) PROTO_T (char *infname X char *outfname)
199
{
200
  /*
201
   * Open files.
202
   */
203
  if (!initreader(infname))
204
  {
205
    fprintf(stderr, "powertrans: cannot open input file %s\n", infname);
206
    return 3;
207
  }
208
 
209
  if (strcmp(outfname, "-") == 0)
210
  {
211
    /* "-" by convention means stdout */
212
    as_file = stdout;
213
    setbuf(as_file, 0);			/* to help debugging */
214
  }
215
  else
216
  {
217
    as_file = fopen(outfname, "w");
218
    if (as_file == (FILE *) 0)
219
    {
220
      fprintf(stderr, "powertrans: cannot open output file %s\n", outfname);
221
      return 3;
222
    }
223
  }
224
 
225
  /* mark the as output as TDF compiled */
226
#ifdef DO_ASSEMBLER_MACROS
227
  if (do_macros)
228
  {
229
    init_macros();
230
  }
231
#endif
232
  fprintf(as_file, "L.TDF.translated:\n");
233
  fprintf(as_file, "#\tpowertrans version %d.%d\n", target_version, target_revision);
234
 
235
  /* 
236
   * Initialise the automatically generated reader modules with 
237
   * automatically generated inits.h 
238
   */
239
#include "inits.h"
240
 
241
  init_flpt();			/* initialise the floating point array */
242
  top_def = (dec*)0;		/* top_def starts as nil */
243
 
244
 
245
 
246
  /* init nowhere */
247
  setregalt(nowhere.answhere, 0);
248
  nowhere.ashwhere.ashsize = 0;
249
  nowhere.ashwhere.ashsize = 0;
250
 
251
 
252
  /* set assembler id prefixes */
253
  local_prefix = "S.";		/* S for static */
254
  name_prefix = "";
255
 
256
 
257
  /*
258
   * Translate.
259
   */
260
 
261
  /* 
262
   * Start the TDF reader, which calls back to translate_capsule() below 
263
   */
264
 
265
  d_capsule();
266
 
267
  /* check for output errors and close the .s file */
268
  if (ferror(as_file) != 0 || fclose(as_file) != 0)
269
  {
270
    fprintf(stderr, "powertrans: error writing to output file %s\n", outfname);
271
    return 4;
272
  }
273
 
274
  return good_trans;			/* return 1 for error, 0 for good */
275
}
276
 
277
 
278
/*
279
 * Translate a TDF capsule 
280
 */
281
void translate_capsule PROTO_Z ()
282
{
283
  int noprocs, noglobals;
284
  int procno, globalno;
285
  dec *crt_def;
286
  space tempregs;
287
  int r;
288
  bool anydone;
289
 
290
  /*
291
   * Do the high level, portable, TDF optimisations 
292
   */
293
  opt_all_exps();
294
 
295
  /*
296
   * Initialise diagnostic information and produce stab for basic types.
297
   */
298
  if (diagnose)
299
  {
300
    init_diag();
301
  }
302
 
303
 
304
  /*
305
   * Generate .extern, .globl, .lglobl, .comm, .lcomm.
306
   * Also take the opportunity to count proc and global definitions.
307
   *
308
   * Note that .lglobl is only generated if diagnose is set (from -g).
309
   * It requires an updated IBM assembler with fix:
310
   * IX23435 Assembler can't create C_HIDEXT class for static names
311
   */
312
 
313
  noprocs = 0;
314
  noglobals = 0;
315
 
316
  for (crt_def = top_def; crt_def != (dec *) 0; crt_def = crt_def->def_next)
317
  {
318
    exp tg = crt_def->dec_u.dec_val.dec_exp;
319
    shape s = crt_def->dec_u.dec_val.dec_shape;
320
    bool extnamed = crt_def->dec_u.dec_val.extnamed;
321
    char *id;
322
 
323
    noglobals++;
324
    /* diag_def needed for find_dd in diagout.c */
325
    diag_def=crt_def;
326
 
327
    if (diagnose)
328
    {
329
      /*
330
       * It is safe to fixup all names here.  C static within procs
331
       * do not get a diag_descriptor so fixup_name does not change
332
       * their names.
333
       */
334
      fixup_name(son(tg), top_def, crt_def);
335
    }
336
 
337
    id = crt_def->dec_u.dec_val.dec_id;		/* might be changed by fixup_name() */
338
 
339
    FULLCOMMENT4("%s: extnamed=%d no(tg)=%d isvar(tg)=%d", (long)id, extnamed, no(tg), isvar(tg));
340
    FULLCOMMENT4("\tname(tg)=%d dec_outermost=%d have_def=%d son(tg)!=nilexp=%d",
341
		name(tg), crt_def->dec_u.dec_val.dec_outermost, crt_def->dec_u.dec_val.have_def, son(tg) != nilexp);
342
    if (son(tg) != nilexp)
343
      FULLCOMMENT3("\tdec_shape, sh(tg), sh(son(tg))=%d,%d,%d", name(s), name(sh(tg)), name(sh(son(tg))));
344
 
345
    crt_def->dec_u.dec_val.have_def = (son(tg)!=nilexp);
346
 
347
    ASSERT(name(tg) == ident_tag);
348
    ASSERT(son(tg) == nilexp || name(sh(tg)) == name(s));
349
 
350
    if (son(tg) == nilexp)
351
    {
352
#if 0
353
      if (!diagnose && no(tg) == 0)
354
#else
355
      if(no(tg)==0)/* only put out an extern instruction if there is a use */
356
#endif
357
	 {
358
	/* no use of this tag, do nothing */
359
      }
360
      else if (extnamed)
361
      {
362
	if (name(s) == prokhd)
363
	{
364
	  fprintf(as_file, "\t.extern\t%s\n", id);	/* proc descriptor */
365
	  fprintf(as_file, "\t.extern\t.%s\n", id);	/* proc entry point */
366
	}
367
	else
368
	{
369
#if 1
370
	  if (strcmp(id, "environ") == 0)
371
	  {
372
	    /*
373
	     * Kludge for environ, .extern for .csect, AIX 3.1.5 ld/library bug maybe?
374
	     * /lib/syscalls.exp states that environ & errno are specially handled,
375
	     * located on the stack at fixed addresses.
376
	     */
377
	    fprintf(as_file, "\t.extern\t%s[RW]\n", id);
378
	    environ_externed=1;
379
	  }
380
	  else
381
#endif
382
	  {
383
	    fprintf(as_file, "\t.extern\t%s\n", id);
384
	  }
385
	}
386
      }
387
      else
388
      {
389
	long byte_size = ALIGNNEXT(shape_size(sh(son(tg))), 64) >> 3;
390
	/* +++ is .lcomm always kept double aligned?  Otherwise how do we do it? */
391
 
392
	ASSERT(extnamed);
393
	fprintf(as_file, "\t.lcomm\t%s,%ld\n", id, byte_size);
394
      }
395
    }
396
    else if (IS_A_PROC(son(tg)))
397
    {
398
      noprocs++;
399
 
400
      if (extnamed)
401
      {
402
	fprintf(as_file, "\t.globl\t%s\n", id);		/* id proc descriptor */
403
	fprintf(as_file, "\t.globl\t.%s\n", id);	/* .id entry point */
404
      }
405
      else if (diagnose)
406
      {
407
	/* .lglobl is not documented, but avoids dbx and gdb becoming confused */
408
	/* +++ always when .lglobl documented */
409
	fprintf(as_file, "\t.lglobl\t.%s\n", id);	/* .id entry point */
410
      }
411
    }
412
    else if (is_comm(son(tg)) && (diagnose || extnamed || no(tg) > 0))
413
    {
414
      /* zero initialiser needed */
415
      long size = shape_size(sh(son(tg)));
416
      long align = shape_align(sh(son(tg)));
417
      long byte_size = ALIGNNEXT(size, 64) >> 3;	
418
      /* +++ do we need to round up? */
419
      int aligncode = ((align > 32 || size > 32) ? 3 : 2);
420
      /* +++ is .lcomm always kept double aligned?
421
       * Otherwise how do we do it? */
422
 
423
      /* assembler is happy with .comm of size 0, 
424
       * so no need to special case unknown size */
425
 
426
      if (extnamed)
427
      {
428
	fprintf(as_file, "\t.comm\t%s,%ld,%d\n", id, byte_size, aligncode);
429
	if (diagnose)
430
	  stab_global(son(tg), id, extnamed);
431
      }
432
      else
433
      {
434
	if (diagnose)
435
	{
436
	  char *csect_name = "C.";
437
 
438
	  /*
439
	   * assembler is confused if it sees .stabx before any .csect,
440
	   * so keep it happy with a useless .csect:
441
	   */
442
	  fprintf(as_file, "\t.csect\t[PR]\n");
443
	  fprintf(as_file, "\t.lcomm\t%s,%ld,%s\n", id, byte_size, csect_name);
444
	  stab_bs(csect_name);
445
	  stab_global(son(tg), id, extnamed);
446
	  stab_es(csect_name);
447
	}
448
	else if (no(tg) > 0)			/* used */
449
	{
450
	  fprintf(as_file, "\t.lcomm\t%s,%ld\n", id, byte_size);
451
	}
452
      }
453
 
454
      ASSERT((align&63)==0 || align < 64);
455
 
456
      /* mark the defininition as processed */
457
      crt_def->dec_u.dec_val.processed = 1;
458
    }
459
    else
460
    {
461
      if (extnamed)
462
	fprintf(as_file, "\t.globl\t%s\n", id);
463
      else if (diagnose)
464
	fprintf(as_file, "\t.lglobl\t%s\n", id);
465
      /* to avoid 'warning: global ignored' message from dbx */
466
    }
467
  }
468
 
469
#ifdef DO_DYNAMIC_INITIALISATION
470
  (void)do__main_extern();
471
#endif
472
  if (do_profile)
473
#ifdef TDF_MCOUNT
474
    fprintf(as_file, "\t.extern\t.TDF_mcount\n");
475
#else
476
    fprintf(as_file, "\t.extern\t.mcount\n");
477
#endif
478
 
479
 
480
  /*
481
   * Alloc memory for procrecs array, info retained between phases
482
   * about procs and how parameters will be stored.
483
   */
484
  procrecs = (procrec *) xcalloc(noprocs, sizeof (procrec));
485
 
486
  /*
487
   * Alloc memory for main_globals, used to lookup assembler names.
488
   */
489
  main_globals = (dec**)xcalloc(noglobals, sizeof(dec*));
490
 
491
  /*
492
   * Generate .toc entries.
493
   * Also take opportunity to setup main_globals.
494
   */
495
  fprintf(as_file, "\n\t.toc\n");
496
 
497
  for (crt_def = top_def; crt_def != (dec *) 0; crt_def = crt_def->def_next)
498
  {
499
    exp tg = crt_def->dec_u.dec_val.dec_exp;
500
    char *id = crt_def->dec_u.dec_val.dec_id;
501
    /* 
502
     * no(tg) is number of uses 
503
     * If tg is used in this module, 
504
     * generate a .toc entry so it can be addressed 
505
     * +++ differentiate proc descriptor/entry point usage 
506
     */
507
    if (no(tg) > 0 || strcmp(id,"__TDFhandler")==0 
508
	|| strcmp(id,"__TDFstacklim")==0)
509
    {
510
      bool extnamed = crt_def->dec_u.dec_val.extnamed;
511
      char *storage_class;
512
 
513
      if (extnamed && son(tg) == nilexp)
514
      {
515
	/* extern from another module */
516
	if (name(crt_def->dec_u.dec_val.dec_shape) == prokhd)
517
	  storage_class = "";	/* proc descriptor */
518
	else
519
	  storage_class = "";	/* unknown data */
520
      }
521
      else
522
      {
523
	storage_class = "";		/* this module */
524
      }
525
#if 1
526
      if (strcmp(id, "environ") == 0 && environ_externed )
527
      {
528
	/* kludge for environ, .extern for .csect, IBM ld/library bug maybe? */
529
	storage_class = "[RW]";
530
 
531
      }
532
#endif
533
      fprintf(as_file, "T.%s:\t.tc\t%s[TC],%s%s\n", id, id, id, storage_class);
534
    }
535
  }
536
 
537
 
538
 
539
  /* number proc defs and setup main_globals */
540
  procno = 0;
541
  globalno = 0;
542
  for (crt_def = top_def; crt_def != (dec *) 0; crt_def = crt_def->def_next)
543
  {
544
    exp tg = crt_def->dec_u.dec_val.dec_exp;
545
 
546
    main_globals[globalno] = crt_def;
547
    crt_def->dec_u.dec_val.sym_number = globalno;
548
    globalno++;
549
 
550
    if (son(tg) != nilexp && IS_A_PROC(son(tg)))
551
    {
552
      no(son(tg)) = procno;	/* index into procrecs in no(proc) */
553
      procno++;
554
    }
555
  }
556
 
557
  ASSERT(procno==noprocs);
558
  ASSERT(globalno==noglobals);
559
  total_no_of_globals=globalno;
560
 
561
 /*
562
   * Scan to put proc bodies in POWER form,
563
   * and calculate register and stack space needs.
564
   */
565
 
566
  /*
567
   * First work out which t fixed point regs, those not preserved over calls,
568
   * can be used.  This needs to be done before scan() which adds idents
569
   * so temp reg needs are within available temp reg set.
570
   */
571
 
572
  /* initial reg sets */
573
  tempregs.fixed = PROC_TREGS;
574
  tempregs.flt = PROC_FLT_TREGS;
575
 
576
  /* ensure R_TMP0 not allocatable */
577
  tempregs.fixed |= RMASK(R_TMP0);
578
 
579
  /* count t fixed point regs we can use, and set the global maxfix_tregs */
580
  maxfix_tregs = 0;
581
  for ( r = R_FIRST; r <= R_LAST; r++ )
582
  {
583
    /* bit clear means allocatable */
584
    if (IS_TREG(r) && (tempregs.fixed&RMASK(r)) == 0)
585
      maxfix_tregs++;
586
  }
587
  maxfix_tregs -= REGISTER_SAFETY_NUMBER;
588
 
589
  COMMENT4("maxfix_tregs=%d(%#x) maxfloat_tregs=%d(%#x)",
590
	maxfix_tregs, tempregs.fixed, MAXFLT_TREGS, tempregs.flt);
591
 
592
 
593
  /*
594
   * Scan all the procs, to put the TDF in POWER form,
595
   * and do register allocation.
596
   */
597
  for (crt_def = top_def; crt_def != (dec *) 0; crt_def = crt_def->def_next)
598
  {
599
    exp tg = crt_def->dec_u.dec_val.dec_exp;
600
 
601
    if (son(tg) != nilexp && IS_A_PROC(son(tg)))
602
    {
603
      procrec *pr = &procrecs[no(son(tg))];
604
      exp *st = &son(tg);
605
      int freefixed=MAXFIX_SREGS;/* The maximum no of free fixed s regs */
606
      int freefloat=MAXFLT_SREGS;/* The maximum no of free float s regs */
607
      int r;
608
 
609
      /* 
610
       * SCAN the procedure
611
       */
612
 
613
      pr->needsproc = scan(st, &st);
614
      set_up_frame_pointer(pr,son(tg));
615
      /*
616
       * WEIGHTS
617
       * estimate usage of tags in body of proc,
618
       * calculating the break points for register allocation
619
       */
620
      if (!(pr->save_all_sregs))
621
      {
622
	(void) weightsv(UNITWEIGHT, bro(son(son(tg))));      
623
      }
624
      /* Check to see if we need a frame pointer */
625
      if (pr->has_fp)
626
      {
627
	freefixed--;
628
      }
629
      if(pr->has_tp)
630
      {
631
	freefixed--;
632
      }
633
      /* 
634
       * REGALLOC
635
       * reg and stack allocation for tags 
636
       */
637
      pr->spacereqproc = regalloc(bro(son(son(tg))), freefixed, freefloat, 0);
638
      /* 
639
       * Ensure that the registers that were not allocated get stored
640
       */
641
      for ( r=freefixed+R_13 ; r <= R_31 ; r++)
642
      {
643
	pr->spacereqproc.fixdump = pr->spacereqproc.fixdump | RMASK(r);
644
      }
645
      if (pr->save_all_sregs)
646
      {
647
	pr->spacereqproc.fixdump = 0xffffe000;
648
	pr->spacereqproc.fltdump = 0xffffc000;
649
      }
650
      set_up_frame_info(pr,son(tg));
651
    }
652
  }
653
  done_scan = 1;
654
 
655
  /*
656
   * Evaluate outer level data initialisers in [RW] section.
657
   */
658
  anydone = 0;
659
  for (crt_def = top_def; crt_def != (dec *) 0; crt_def = crt_def->def_next)
660
  {
661
    exp tg = crt_def->dec_u.dec_val.dec_exp;
662
    char *id = crt_def->dec_u.dec_val.dec_id;
663
    bool extnamed = crt_def->dec_u.dec_val.extnamed;
664
    diag_def=crt_def;/* just in case find_dd is called */
665
    FULLCOMMENT4("no(tg)=%d isvar(tg)=%d extnamed=%d son(tg)==nilexp=%d",
666
		 no(tg), isvar(tg), extnamed, son(tg)==nilexp);
667
    if (son(tg) != nilexp)
668
    {
669
      /*
670
       * Skip if already processed, eg identified as is_comm() 
671
       */
672
      if (crt_def->dec_u.dec_val.processed)
673
	continue;
674
      /*
675
       * Skip if zero uses and internal to module 
676
       * unless generating diagnostics 
677
       */
678
      if (!(diagnose || extnamed || no(tg) > 0))
679
	continue;
680
      /* +++ could do better than making everything except strings [RW] */
681
      if ( ! IS_A_PROC(son(tg)) ) 
682
	/* put all things in [RW] section */
683
      {
684
	/* 
685
	 * Non proc, which is isvar() [variable] for [RW] section 
686
	 */
687
	long symdef = crt_def->dec_u.dec_val.sym_number;
688
 
689
	/* Check to see if we have made any entries yet */
690
	if (!anydone)
691
	{
692
	  anydone = 1;
693
	  fprintf(as_file, "\n\t.csect\tW.[RW]\n");
694
	  if (diagnose)
695
	  {
696
	    stab_bs("W.[RW]");
697
	  }
698
	}
699
 
700
	evaluated(son(tg), -symdef - 1);
701
 
702
	if (diagnose)
703
	{
704
	  stab_global(son(tg), id, extnamed);
705
	}
706
	fprintf(as_file, "#\t.enddata\t%s\n\n", id);
707
 
708
	/* mark the defininition as processed */
709
	crt_def->dec_u.dec_val.processed = 1;
710
      }
711
    }
712
  }
713
  if (diagnose && anydone)
714
  {
715
    stab_es("W.[RW]"); /* Close the RW section stab */
716
  }
717
 
718
 
719
 
720
  /*
721
   * Evaluate outer level data initialisers in [RO] section.
722
   */
723
  anydone = 0;			/* set to 1 after first tag output */
724
 
725
  for (crt_def = top_def; crt_def != (dec *) 0; crt_def = crt_def->def_next)
726
  {
727
    exp tg = crt_def->dec_u.dec_val.dec_exp;
728
    char *id = crt_def->dec_u.dec_val.dec_id;
729
    bool extnamed = crt_def->dec_u.dec_val.extnamed;
730
    diag_def=crt_def;/* just in case find_dd is called */
731
    if (son(tg) != nilexp)
732
    {
733
      /* skip if already processed, eg identified as is_comm() */
734
      if (crt_def->dec_u.dec_val.processed)
735
	continue;
736
 
737
      /* 
738
       * Skip if zero uses and internal to module unless 
739
       * generating diagnostics 
740
       */
741
      if (!(diagnose || extnamed || no(tg) > 0))
742
	continue;
743
 
744
      if (!IS_A_PROC(son(tg)))
745
      {
746
	/* non proc, which is not isvar() [variable] for [RO] section */
747
	long symdef = crt_def->dec_u.dec_val.sym_number;
748
 
749
	if (!anydone)
750
	{
751
	  anydone = 1;
752
	  fprintf(as_file, "\n\t.csect\tR.[RO]\n");
753
	  if (diagnose)
754
	  {
755
	    stab_bs("R.[RO]");
756
	  }
757
	}
758
 
759
	evaluated(son(tg), symdef + 1);
760
 
761
	if (diagnose)
762
	{
763
	  stab_global(son(tg), id, extnamed);
764
	}
765
	fprintf(as_file, "#\t.enddata\t%s\n\n", id);
766
 
767
	/* mark the defininition as processed */
768
	crt_def->dec_u.dec_val.processed = 1;
769
      }
770
    }
771
  }
772
 
773
  if (diagnose && anydone)
774
  {
775
    stab_es("R.[RO]");
776
  }
777
  anydone=0;
778
 
779
  /*
780
   * Translate procedures.
781
   */
782
  for (crt_def = top_def; crt_def != (dec *) 0; crt_def = crt_def->def_next)
783
  {
784
    exp tg = crt_def->dec_u.dec_val.dec_exp;
785
    char *id = crt_def->dec_u.dec_val.dec_id;
786
    bool extnamed = crt_def->dec_u.dec_val.extnamed;
787
 
788
    if (son(tg) != nilexp)
789
    {
790
      /* skip if already processed */
791
      if (crt_def->dec_u.dec_val.processed)
792
	continue;
793
 
794
      /* skip if zero uses and internal to module unless generating diagnostics */
795
      if (!(diagnose || extnamed || no(tg) > 0))
796
	continue;
797
 
798
      if (IS_A_PROC(son(tg)))
799
      {
800
	/* translate code for proc */
801
	fprintf(as_file, "\n");		/* make proc more visable to reader */
802
	diag_def=crt_def;
803
	/* switch to correct file */
804
	if (diagnose && diag_def->dec_u.dec_val.diag_info!=NULL )
805
	{
806
	  anydone=1;
807
	  stab_proc1(son(tg), id, extnamed);
808
	}
809
 
810
 
811
	fprintf(as_file, "#\t.proc\n");
812
 
813
	/* generate descriptor */
814
	fprintf(as_file, "\t.csect\t[DS]\n");
815
	fprintf(as_file, "%s:\n", id);
816
	fprintf(as_file, "\t.long\t.%s,TOC[tc0],0\n", id);
817
 
818
	/* generate code */
819
	fprintf(as_file, "\t.csect\t[PR]\n");
820
	fprintf(as_file, ".%s:\n", id);
821
 
822
	/* stab proc details */
823
	if (diagnose && diag_def->dec_u.dec_val.diag_info!=NULL)
824
	{
825
	  stab_proc2(son(tg), id, extnamed);
826
	}
827
 
828
	seed_label();		/* reset label sequence */
829
	settempregs(son(tg));	/* reset getreg sequence */
830
 
831
	code_here(son(tg), tempregs, nowhere);
832
 
833
	if (diagnose && diag_def->dec_u.dec_val.diag_info!=NULL)
834
	{
835
	  stab_endproc(son(tg), id, extnamed);
836
	}
837
 
838
	fprintf(as_file, "#\t.end\t%s\n", id);
839
 
840
	/* mark the defininition as processed */
841
	crt_def->dec_u.dec_val.processed = 1;
842
      }
843
    }
844
  }
845
  if ( diagnose && anydone )
846
  {
847
    stab_end_file();/* Ties up any open .bi's with .ei's */
848
  }
849
 
850
}
851
 
852
 
853
/* translate a TDF unit */
854
void translate_unit PROTO_Z ()
855
{
856
  if (separate_units)
857
  {
858
    dec *crt_def;
859
 
860
    translate_capsule();
861
 
862
    for (crt_def = top_def; crt_def != (dec *) 0; crt_def = crt_def->def_next)
863
    {
864
      exp crt_exp = crt_def->dec_u.dec_val.dec_exp;
865
 
866
      no(crt_exp) = 0;
867
      pt(crt_exp) = nilexp;
868
    }
869
 
870
    crt_repeat = nilexp;
871
    repeat_list = nilexp;
872
  }
873
 
874
  return;
875
}
876
 
877
 
878
/* output an identification of two names */
879
void out_rename PROTO_N ((old_nm,nm)) PROTO_T (char *old_nm X char *nm)
880
{
881
  /* all link information is known by code production time, so no need to do anything */
882
}
883
 
884
baseoff find_tg PROTO_N ((n)) PROTO_T (char *n)
885
{
886
  int i;
887
  exp tg;
888
  for (i = 0; i < total_no_of_globals; i++) {
889
    char *id = main_globals[i] -> dec_u.dec_val.dec_id;
890
    tg = main_globals[i] -> dec_u.dec_val.dec_exp;
891
    if (strcmp(id, n) == 0) return boff(tg);
892
  }
893
  printf("%s\n", n);
894
  fail("Extension name not declared ");
895
  tg = main_globals[0] -> dec_u.dec_val.dec_exp;
896
  return boff(tg);
897
}